encoder_lib.c 13 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431
  1. /*
  2. * Copyright 2019 The OpenSSL Project Authors. All Rights Reserved.
  3. *
  4. * Licensed under the Apache License 2.0 (the "License"). You may not use
  5. * this file except in compliance with the License. You can obtain a copy
  6. * in the file LICENSE in the source distribution or at
  7. * https://www.openssl.org/source/license.html
  8. */
  9. #include "e_os.h" /* strcasecmp on Windows */
  10. #include <openssl/core_names.h>
  11. #include <openssl/bio.h>
  12. #include <openssl/encoder.h>
  13. #include <openssl/buffer.h>
  14. #include <openssl/params.h>
  15. #include <openssl/provider.h>
  16. #include "encoder_local.h"
  17. static int encoder_process(OSSL_ENCODER_CTX *ctx, BIO *out);
  18. int OSSL_ENCODER_to_bio(OSSL_ENCODER_CTX *ctx, BIO *out)
  19. {
  20. return encoder_process(ctx, out);
  21. }
  22. #ifndef OPENSSL_NO_STDIO
  23. static BIO *bio_from_file(FILE *fp)
  24. {
  25. BIO *b;
  26. if ((b = BIO_new(BIO_s_file())) == NULL) {
  27. ERR_raise(ERR_LIB_OSSL_ENCODER, ERR_R_BUF_LIB);
  28. return NULL;
  29. }
  30. BIO_set_fp(b, fp, BIO_NOCLOSE);
  31. return b;
  32. }
  33. int OSSL_ENCODER_to_fp(OSSL_ENCODER_CTX *ctx, FILE *fp)
  34. {
  35. BIO *b = bio_from_file(fp);
  36. int ret = 0;
  37. if (b != NULL)
  38. ret = OSSL_ENCODER_to_bio(ctx, b);
  39. BIO_free(b);
  40. return ret;
  41. }
  42. #endif
  43. int OSSL_ENCODER_to_data(OSSL_ENCODER_CTX *ctx, unsigned char **pdata,
  44. size_t *pdata_len)
  45. {
  46. BIO *out = BIO_new(BIO_s_mem());
  47. BUF_MEM *buf = NULL;
  48. int ret = 0;
  49. if (pdata_len == NULL) {
  50. ERR_raise(ERR_LIB_OSSL_DECODER, ERR_R_PASSED_NULL_PARAMETER);
  51. return 0;
  52. }
  53. if (OSSL_ENCODER_to_bio(ctx, out)
  54. && BIO_get_mem_ptr(out, &buf) > 0) {
  55. ret = 1; /* Hope for the best. A too small buffer will clear this */
  56. if (pdata != NULL && *pdata != NULL) {
  57. if (*pdata_len < buf->length)
  58. /*
  59. * It's tempting to do |*pdata_len = (size_t)buf->length|
  60. * However, it's believed to be confusing more than helpful,
  61. * so we don't.
  62. */
  63. ret = 0;
  64. else
  65. *pdata_len -= buf->length;
  66. } else {
  67. /* The buffer with the right size is already allocated for us */
  68. *pdata_len = (size_t)buf->length;
  69. }
  70. if (ret) {
  71. if (pdata != NULL) {
  72. if (*pdata != NULL) {
  73. memcpy(*pdata, buf->data, buf->length);
  74. *pdata += buf->length;
  75. } else {
  76. /* In this case, we steal the data from BIO_s_mem() */
  77. *pdata = (unsigned char *)buf->data;
  78. buf->data = NULL;
  79. }
  80. }
  81. }
  82. }
  83. BIO_free(out);
  84. return ret;
  85. }
  86. int OSSL_ENCODER_CTX_set_output_type(OSSL_ENCODER_CTX *ctx,
  87. const char *output_type)
  88. {
  89. if (!ossl_assert(ctx != NULL) || !ossl_assert(output_type != NULL)) {
  90. ERR_raise(ERR_LIB_OSSL_ENCODER, ERR_R_PASSED_NULL_PARAMETER);
  91. return 0;
  92. }
  93. ctx->output_type = output_type;
  94. return 1;
  95. }
  96. int OSSL_ENCODER_CTX_set_selection(OSSL_ENCODER_CTX *ctx, int selection)
  97. {
  98. if (!ossl_assert(ctx != NULL)) {
  99. ERR_raise(ERR_LIB_OSSL_ENCODER, ERR_R_PASSED_NULL_PARAMETER);
  100. return 0;
  101. }
  102. if (!ossl_assert(selection != 0)) {
  103. ERR_raise(ERR_LIB_OSSL_ENCODER, ERR_R_PASSED_INVALID_ARGUMENT);
  104. return 0;
  105. }
  106. ctx->selection = selection;
  107. return 1;
  108. }
  109. static OSSL_ENCODER_INSTANCE *ossl_encoder_instance_new(OSSL_ENCODER *encoder,
  110. void *encoderctx)
  111. {
  112. OSSL_ENCODER_INSTANCE *encoder_inst = NULL;
  113. OSSL_PARAM params[3];
  114. if (!ossl_assert(encoder != NULL)) {
  115. ERR_raise(ERR_LIB_OSSL_ENCODER, ERR_R_PASSED_NULL_PARAMETER);
  116. return 0;
  117. }
  118. if (encoder->get_params == NULL) {
  119. ERR_raise(ERR_LIB_OSSL_ENCODER,
  120. OSSL_ENCODER_R_MISSING_GET_PARAMS);
  121. return 0;
  122. }
  123. if ((encoder_inst = OPENSSL_zalloc(sizeof(*encoder_inst))) == NULL) {
  124. ERR_raise(ERR_LIB_OSSL_ENCODER, ERR_R_MALLOC_FAILURE);
  125. return 0;
  126. }
  127. /*
  128. * Cache the input and output types for this encoder. The output type
  129. * is mandatory.
  130. */
  131. params[0] =
  132. OSSL_PARAM_construct_utf8_ptr(OSSL_ENCODER_PARAM_OUTPUT_TYPE,
  133. (char **)&encoder_inst->output_type, 0);
  134. params[1] =
  135. OSSL_PARAM_construct_utf8_ptr(OSSL_ENCODER_PARAM_INPUT_TYPE,
  136. (char **)&encoder_inst->input_type, 0);
  137. params[2] = OSSL_PARAM_construct_end();
  138. if (!encoder->get_params(params)
  139. || !OSSL_PARAM_modified(&params[1]))
  140. goto err;
  141. if (!OSSL_ENCODER_up_ref(encoder)) {
  142. ERR_raise(ERR_LIB_OSSL_ENCODER, ERR_R_INTERNAL_ERROR);
  143. goto err;
  144. }
  145. encoder_inst->encoder = encoder;
  146. encoder_inst->encoderctx = encoderctx;
  147. return encoder_inst;
  148. err:
  149. ossl_encoder_instance_free(encoder_inst);
  150. return NULL;
  151. }
  152. void ossl_encoder_instance_free(OSSL_ENCODER_INSTANCE *encoder_inst)
  153. {
  154. if (encoder_inst != NULL) {
  155. if (encoder_inst->encoder != NULL)
  156. encoder_inst->encoder->freectx(encoder_inst->encoderctx);
  157. encoder_inst->encoderctx = NULL;
  158. OSSL_ENCODER_free(encoder_inst->encoder);
  159. encoder_inst->encoder = NULL;
  160. OPENSSL_free(encoder_inst);
  161. }
  162. }
  163. static int ossl_encoder_ctx_add_encoder_inst(OSSL_ENCODER_CTX *ctx,
  164. OSSL_ENCODER_INSTANCE *ei)
  165. {
  166. if (ctx->encoder_insts == NULL
  167. && (ctx->encoder_insts =
  168. sk_OSSL_ENCODER_INSTANCE_new_null()) == NULL) {
  169. ERR_raise(ERR_LIB_OSSL_ENCODER, ERR_R_MALLOC_FAILURE);
  170. return 0;
  171. }
  172. return (sk_OSSL_ENCODER_INSTANCE_push(ctx->encoder_insts, ei) > 0);
  173. }
  174. int OSSL_ENCODER_CTX_add_encoder(OSSL_ENCODER_CTX *ctx, OSSL_ENCODER *encoder)
  175. {
  176. OSSL_ENCODER_INSTANCE *encoder_inst = NULL;
  177. const OSSL_PROVIDER *prov = NULL;
  178. void *encoderctx = NULL;
  179. void *provctx = NULL;
  180. if (!ossl_assert(ctx != NULL) || !ossl_assert(encoder != NULL)) {
  181. ERR_raise(ERR_LIB_OSSL_ENCODER, ERR_R_PASSED_NULL_PARAMETER);
  182. return 0;
  183. }
  184. prov = OSSL_ENCODER_provider(encoder);
  185. provctx = OSSL_PROVIDER_get0_provider_ctx(prov);
  186. if ((encoderctx = encoder->newctx(provctx)) == NULL
  187. || (encoder_inst =
  188. ossl_encoder_instance_new(encoder, encoderctx)) == NULL)
  189. goto err;
  190. /* Avoid double free of encoderctx on further errors */
  191. encoderctx = NULL;
  192. if (!ossl_encoder_ctx_add_encoder_inst(ctx, encoder_inst))
  193. goto err;
  194. return 1;
  195. err:
  196. ossl_encoder_instance_free(encoder_inst);
  197. if (encoderctx != NULL)
  198. encoder->freectx(encoderctx);
  199. return 0;
  200. }
  201. int OSSL_ENCODER_CTX_add_extra(OSSL_ENCODER_CTX *ctx,
  202. OSSL_LIB_CTX *libctx, const char *propq)
  203. {
  204. return 1;
  205. }
  206. int OSSL_ENCODER_CTX_get_num_encoders(OSSL_ENCODER_CTX *ctx)
  207. {
  208. if (ctx == NULL || ctx->encoder_insts == NULL)
  209. return 0;
  210. return sk_OSSL_ENCODER_INSTANCE_num(ctx->encoder_insts);
  211. }
  212. int OSSL_ENCODER_CTX_set_construct(OSSL_ENCODER_CTX *ctx,
  213. OSSL_ENCODER_CONSTRUCT *construct)
  214. {
  215. if (!ossl_assert(ctx != NULL)) {
  216. ERR_raise(ERR_LIB_OSSL_ENCODER, ERR_R_PASSED_NULL_PARAMETER);
  217. return 0;
  218. }
  219. ctx->construct = construct;
  220. return 1;
  221. }
  222. int OSSL_ENCODER_CTX_set_construct_data(OSSL_ENCODER_CTX *ctx,
  223. void *construct_data)
  224. {
  225. if (!ossl_assert(ctx != NULL)) {
  226. ERR_raise(ERR_LIB_OSSL_ENCODER, ERR_R_PASSED_NULL_PARAMETER);
  227. return 0;
  228. }
  229. ctx->construct_data = construct_data;
  230. return 1;
  231. }
  232. int OSSL_ENCODER_CTX_set_cleanup(OSSL_ENCODER_CTX *ctx,
  233. OSSL_ENCODER_CLEANUP *cleanup)
  234. {
  235. if (!ossl_assert(ctx != NULL)) {
  236. ERR_raise(ERR_LIB_OSSL_ENCODER, ERR_R_PASSED_NULL_PARAMETER);
  237. return 0;
  238. }
  239. ctx->cleanup = cleanup;
  240. return 1;
  241. }
  242. OSSL_ENCODER *
  243. OSSL_ENCODER_INSTANCE_get_encoder(OSSL_ENCODER_INSTANCE *encoder_inst)
  244. {
  245. if (encoder_inst == NULL)
  246. return NULL;
  247. return encoder_inst->encoder;
  248. }
  249. void *
  250. OSSL_ENCODER_INSTANCE_get_encoder_ctx(OSSL_ENCODER_INSTANCE *encoder_inst)
  251. {
  252. if (encoder_inst == NULL)
  253. return NULL;
  254. return encoder_inst->encoderctx;
  255. }
  256. const char *
  257. OSSL_ENCODER_INSTANCE_get_input_type(OSSL_ENCODER_INSTANCE *encoder_inst)
  258. {
  259. if (encoder_inst == NULL)
  260. return NULL;
  261. return encoder_inst->input_type;
  262. }
  263. const char *
  264. OSSL_ENCODER_INSTANCE_get_output_type(OSSL_ENCODER_INSTANCE *encoder_inst)
  265. {
  266. if (encoder_inst == NULL)
  267. return NULL;
  268. return encoder_inst->output_type;
  269. }
  270. static int encoder_process(OSSL_ENCODER_CTX *ctx, BIO *out)
  271. {
  272. size_t i, end;
  273. void *latest_output = NULL;
  274. size_t latest_output_length = 0;
  275. const char *latest_output_type = NULL;
  276. const char *last_input_type = NULL;
  277. int ok = 0;
  278. end = OSSL_ENCODER_CTX_get_num_encoders(ctx);
  279. for (i = 0; i < end; i++) {
  280. OSSL_ENCODER_INSTANCE *encoder_inst =
  281. sk_OSSL_ENCODER_INSTANCE_value(ctx->encoder_insts, i);
  282. OSSL_ENCODER *encoder = OSSL_ENCODER_INSTANCE_get_encoder(encoder_inst);
  283. void *encoderctx = OSSL_ENCODER_INSTANCE_get_encoder_ctx(encoder_inst);
  284. const char *current_input_type =
  285. OSSL_ENCODER_INSTANCE_get_input_type(encoder_inst);
  286. const char *current_output_type =
  287. OSSL_ENCODER_INSTANCE_get_output_type(encoder_inst);
  288. BIO *current_out;
  289. BIO *allocated_out = NULL;
  290. const void *current_data = NULL;
  291. OSSL_PARAM abstract[3];
  292. OSSL_PARAM *abstract_p;
  293. const OSSL_PARAM *current_abstract = NULL;
  294. if (latest_output_type == NULL) {
  295. /*
  296. * This is the first iteration, so we prepare the object to be
  297. * encoded
  298. */
  299. current_data = ctx->construct(encoder_inst, ctx->construct_data);
  300. /* Assume that the constructor recorded an error */
  301. if (current_data == NULL)
  302. goto loop_end;
  303. } else {
  304. /*
  305. * Check that the latest output type matches the currently
  306. * considered encoder
  307. */
  308. if (!OSSL_ENCODER_is_a(encoder, latest_output_type))
  309. continue;
  310. /*
  311. * If there is a latest output type, there should be a latest output
  312. */
  313. if (!ossl_assert(latest_output != NULL)) {
  314. ERR_raise(ERR_LIB_OSSL_ENCODER, ERR_R_INTERNAL_ERROR);
  315. goto loop_end;
  316. }
  317. /*
  318. * Create an object abstraction from the latest output, which was
  319. * stolen from the previous round.
  320. */
  321. abstract_p = abstract;
  322. if (last_input_type != NULL)
  323. *abstract_p++ =
  324. OSSL_PARAM_construct_utf8_string(OSSL_OBJECT_PARAM_DATA_TYPE,
  325. (char *)last_input_type, 0);
  326. *abstract_p++ =
  327. OSSL_PARAM_construct_octet_string(OSSL_OBJECT_PARAM_DATA,
  328. latest_output,
  329. latest_output_length);
  330. *abstract_p = OSSL_PARAM_construct_end();
  331. current_abstract = abstract;
  332. }
  333. /*
  334. * If the desired output type matches the output type of the currently
  335. * considered encoder, we're setting up final output. Otherwise, set
  336. * up an intermediary memory output.
  337. */
  338. if (strcasecmp(ctx->output_type, current_output_type) == 0)
  339. current_out = out;
  340. else if ((current_out = allocated_out = BIO_new(BIO_s_mem())) == NULL)
  341. goto loop_end; /* Assume BIO_new() recorded an error */
  342. ok = encoder->encode(encoderctx, (OSSL_CORE_BIO *)current_out,
  343. current_data, current_abstract, ctx->selection,
  344. ossl_pw_passphrase_callback_enc, &ctx->pwdata);
  345. if (current_input_type != NULL)
  346. last_input_type = current_input_type;
  347. if (!ok)
  348. goto loop_end;
  349. OPENSSL_free(latest_output);
  350. /*
  351. * Steal the output from the BIO_s_mem, if we did allocate one.
  352. * That'll be the data for an object abstraction in the next round.
  353. */
  354. if (allocated_out != NULL) {
  355. BUF_MEM *buf;
  356. BIO_get_mem_ptr(allocated_out, &buf);
  357. latest_output = buf->data;
  358. latest_output_length = buf->length;
  359. memset(buf, 0, sizeof(*buf));
  360. BIO_free(allocated_out);
  361. }
  362. loop_end:
  363. if (current_data != NULL)
  364. ctx->cleanup(ctx->construct_data);
  365. if (ok)
  366. break;
  367. }
  368. OPENSSL_free(latest_output);
  369. return ok;
  370. }