2
0

kem.c 17 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528
  1. /*
  2. * Copyright 2020-2023 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 <stdio.h>
  10. #include <stdlib.h>
  11. #include <openssl/objects.h>
  12. #include <openssl/evp.h>
  13. #include "internal/cryptlib.h"
  14. #include "internal/provider.h"
  15. #include "internal/core.h"
  16. #include "crypto/evp.h"
  17. #include "evp_local.h"
  18. static int evp_kem_init(EVP_PKEY_CTX *ctx, int operation,
  19. const OSSL_PARAM params[], EVP_PKEY *authkey)
  20. {
  21. int ret = 0;
  22. EVP_KEM *kem = NULL;
  23. EVP_KEYMGMT *tmp_keymgmt = NULL;
  24. const OSSL_PROVIDER *tmp_prov = NULL;
  25. void *provkey = NULL, *provauthkey = NULL;
  26. const char *supported_kem = NULL;
  27. int iter;
  28. if (ctx == NULL || ctx->keytype == NULL) {
  29. ERR_raise(ERR_LIB_EVP, EVP_R_INITIALIZATION_ERROR);
  30. return 0;
  31. }
  32. evp_pkey_ctx_free_old_ops(ctx);
  33. ctx->operation = operation;
  34. if (ctx->pkey == NULL) {
  35. ERR_raise(ERR_LIB_EVP, EVP_R_NO_KEY_SET);
  36. goto err;
  37. }
  38. if (authkey != NULL && authkey->type != ctx->pkey->type) {
  39. ERR_raise(ERR_LIB_EVP, EVP_R_DIFFERENT_KEY_TYPES);
  40. return 0;
  41. }
  42. /*
  43. * Try to derive the supported kem from |ctx->keymgmt|.
  44. */
  45. if (!ossl_assert(ctx->pkey->keymgmt == NULL
  46. || ctx->pkey->keymgmt == ctx->keymgmt)) {
  47. ERR_raise(ERR_LIB_EVP, ERR_R_INTERNAL_ERROR);
  48. goto err;
  49. }
  50. supported_kem = evp_keymgmt_util_query_operation_name(ctx->keymgmt,
  51. OSSL_OP_KEM);
  52. if (supported_kem == NULL) {
  53. ERR_raise(ERR_LIB_EVP, EVP_R_INITIALIZATION_ERROR);
  54. goto err;
  55. }
  56. /*
  57. * Because we cleared out old ops, we shouldn't need to worry about
  58. * checking if kem is already there.
  59. * We perform two iterations:
  60. *
  61. * 1. Do the normal kem fetch, using the fetching data given by
  62. * the EVP_PKEY_CTX.
  63. * 2. Do the provider specific kem fetch, from the same provider
  64. * as |ctx->keymgmt|
  65. *
  66. * We then try to fetch the keymgmt from the same provider as the
  67. * kem, and try to export |ctx->pkey| to that keymgmt (when this
  68. * keymgmt happens to be the same as |ctx->keymgmt|, the export is
  69. * a no-op, but we call it anyway to not complicate the code even
  70. * more).
  71. * If the export call succeeds (returns a non-NULL provider key pointer),
  72. * we're done and can perform the operation itself. If not, we perform
  73. * the second iteration, or jump to legacy.
  74. */
  75. for (iter = 1, provkey = NULL; iter < 3 && provkey == NULL; iter++) {
  76. EVP_KEYMGMT *tmp_keymgmt_tofree = NULL;
  77. /*
  78. * If we're on the second iteration, free the results from the first.
  79. * They are NULL on the first iteration, so no need to check what
  80. * iteration we're on.
  81. */
  82. EVP_KEM_free(kem);
  83. EVP_KEYMGMT_free(tmp_keymgmt);
  84. switch (iter) {
  85. case 1:
  86. kem = EVP_KEM_fetch(ctx->libctx, supported_kem, ctx->propquery);
  87. if (kem != NULL)
  88. tmp_prov = EVP_KEM_get0_provider(kem);
  89. break;
  90. case 2:
  91. tmp_prov = EVP_KEYMGMT_get0_provider(ctx->keymgmt);
  92. kem = evp_kem_fetch_from_prov((OSSL_PROVIDER *)tmp_prov,
  93. supported_kem, ctx->propquery);
  94. if (kem == NULL) {
  95. ERR_raise(ERR_LIB_EVP,
  96. EVP_R_OPERATION_NOT_SUPPORTED_FOR_THIS_KEYTYPE);
  97. ret = -2;
  98. goto err;
  99. }
  100. }
  101. if (kem == NULL)
  102. continue;
  103. /*
  104. * Ensure that the key is provided, either natively, or as a cached
  105. * export. We start by fetching the keymgmt with the same name as
  106. * |ctx->pkey|, but from the provider of the kem method, using the
  107. * same property query as when fetching the kem method.
  108. * With the keymgmt we found (if we did), we try to export |ctx->pkey|
  109. * to it (evp_pkey_export_to_provider() is smart enough to only actually
  110. * export it if |tmp_keymgmt| is different from |ctx->pkey|'s keymgmt)
  111. */
  112. tmp_keymgmt_tofree = tmp_keymgmt =
  113. evp_keymgmt_fetch_from_prov((OSSL_PROVIDER *)tmp_prov,
  114. EVP_KEYMGMT_get0_name(ctx->keymgmt),
  115. ctx->propquery);
  116. if (tmp_keymgmt != NULL) {
  117. provkey = evp_pkey_export_to_provider(ctx->pkey, ctx->libctx,
  118. &tmp_keymgmt, ctx->propquery);
  119. if (provkey != NULL && authkey != NULL) {
  120. provauthkey = evp_pkey_export_to_provider(authkey, ctx->libctx,
  121. &tmp_keymgmt,
  122. ctx->propquery);
  123. if (provauthkey == NULL) {
  124. EVP_KEM_free(kem);
  125. ERR_raise(ERR_LIB_EVP, EVP_R_INITIALIZATION_ERROR);
  126. goto err;
  127. }
  128. }
  129. }
  130. if (tmp_keymgmt == NULL)
  131. EVP_KEYMGMT_free(tmp_keymgmt_tofree);
  132. }
  133. if (provkey == NULL) {
  134. EVP_KEM_free(kem);
  135. ERR_raise(ERR_LIB_EVP, EVP_R_INITIALIZATION_ERROR);
  136. goto err;
  137. }
  138. ctx->op.encap.kem = kem;
  139. ctx->op.encap.algctx = kem->newctx(ossl_provider_ctx(kem->prov));
  140. if (ctx->op.encap.algctx == NULL) {
  141. /* The provider key can stay in the cache */
  142. ERR_raise(ERR_LIB_EVP, EVP_R_INITIALIZATION_ERROR);
  143. goto err;
  144. }
  145. switch (operation) {
  146. case EVP_PKEY_OP_ENCAPSULATE:
  147. if (provauthkey != NULL && kem->auth_encapsulate_init != NULL) {
  148. ret = kem->auth_encapsulate_init(ctx->op.encap.algctx, provkey,
  149. provauthkey, params);
  150. } else if (provauthkey == NULL && kem->encapsulate_init != NULL) {
  151. ret = kem->encapsulate_init(ctx->op.encap.algctx, provkey, params);
  152. } else {
  153. ERR_raise(ERR_LIB_EVP, EVP_R_OPERATION_NOT_SUPPORTED_FOR_THIS_KEYTYPE);
  154. ret = -2;
  155. goto err;
  156. }
  157. break;
  158. case EVP_PKEY_OP_DECAPSULATE:
  159. if (provauthkey != NULL && kem->auth_decapsulate_init != NULL) {
  160. ret = kem->auth_decapsulate_init(ctx->op.encap.algctx, provkey,
  161. provauthkey, params);
  162. } else if (provauthkey == NULL && kem->encapsulate_init != NULL) {
  163. ret = kem->decapsulate_init(ctx->op.encap.algctx, provkey, params);
  164. } else {
  165. ERR_raise(ERR_LIB_EVP, EVP_R_OPERATION_NOT_SUPPORTED_FOR_THIS_KEYTYPE);
  166. ret = -2;
  167. goto err;
  168. }
  169. break;
  170. default:
  171. ERR_raise(ERR_LIB_EVP, EVP_R_INITIALIZATION_ERROR);
  172. goto err;
  173. }
  174. EVP_KEYMGMT_free(tmp_keymgmt);
  175. tmp_keymgmt = NULL;
  176. if (ret > 0)
  177. return 1;
  178. err:
  179. if (ret <= 0) {
  180. evp_pkey_ctx_free_old_ops(ctx);
  181. ctx->operation = EVP_PKEY_OP_UNDEFINED;
  182. }
  183. EVP_KEYMGMT_free(tmp_keymgmt);
  184. return ret;
  185. }
  186. int EVP_PKEY_auth_encapsulate_init(EVP_PKEY_CTX *ctx, EVP_PKEY *authpriv,
  187. const OSSL_PARAM params[])
  188. {
  189. if (authpriv == NULL)
  190. return 0;
  191. return evp_kem_init(ctx, EVP_PKEY_OP_ENCAPSULATE, params, authpriv);
  192. }
  193. int EVP_PKEY_encapsulate_init(EVP_PKEY_CTX *ctx, const OSSL_PARAM params[])
  194. {
  195. return evp_kem_init(ctx, EVP_PKEY_OP_ENCAPSULATE, params, NULL);
  196. }
  197. int EVP_PKEY_encapsulate(EVP_PKEY_CTX *ctx,
  198. unsigned char *out, size_t *outlen,
  199. unsigned char *secret, size_t *secretlen)
  200. {
  201. if (ctx == NULL)
  202. return 0;
  203. if (ctx->operation != EVP_PKEY_OP_ENCAPSULATE) {
  204. ERR_raise(ERR_LIB_EVP, EVP_R_OPERATION_NOT_INITIALIZED);
  205. return -1;
  206. }
  207. if (ctx->op.encap.algctx == NULL) {
  208. ERR_raise(ERR_LIB_EVP, EVP_R_OPERATION_NOT_SUPPORTED_FOR_THIS_KEYTYPE);
  209. return -2;
  210. }
  211. if (out != NULL && secret == NULL)
  212. return 0;
  213. return ctx->op.encap.kem->encapsulate(ctx->op.encap.algctx,
  214. out, outlen, secret, secretlen);
  215. }
  216. int EVP_PKEY_decapsulate_init(EVP_PKEY_CTX *ctx, const OSSL_PARAM params[])
  217. {
  218. return evp_kem_init(ctx, EVP_PKEY_OP_DECAPSULATE, params, NULL);
  219. }
  220. int EVP_PKEY_auth_decapsulate_init(EVP_PKEY_CTX *ctx, EVP_PKEY *authpub,
  221. const OSSL_PARAM params[])
  222. {
  223. if (authpub == NULL)
  224. return 0;
  225. return evp_kem_init(ctx, EVP_PKEY_OP_DECAPSULATE, params, authpub);
  226. }
  227. int EVP_PKEY_decapsulate(EVP_PKEY_CTX *ctx,
  228. unsigned char *secret, size_t *secretlen,
  229. const unsigned char *in, size_t inlen)
  230. {
  231. if (ctx == NULL
  232. || (in == NULL || inlen == 0)
  233. || (secret == NULL && secretlen == NULL))
  234. return 0;
  235. if (ctx->operation != EVP_PKEY_OP_DECAPSULATE) {
  236. ERR_raise(ERR_LIB_EVP, EVP_R_OPERATION_NOT_INITIALIZED);
  237. return -1;
  238. }
  239. if (ctx->op.encap.algctx == NULL) {
  240. ERR_raise(ERR_LIB_EVP, EVP_R_OPERATION_NOT_SUPPORTED_FOR_THIS_KEYTYPE);
  241. return -2;
  242. }
  243. return ctx->op.encap.kem->decapsulate(ctx->op.encap.algctx,
  244. secret, secretlen, in, inlen);
  245. }
  246. static EVP_KEM *evp_kem_new(OSSL_PROVIDER *prov)
  247. {
  248. EVP_KEM *kem = OPENSSL_zalloc(sizeof(EVP_KEM));
  249. if (kem == NULL)
  250. return NULL;
  251. if (!CRYPTO_NEW_REF(&kem->refcnt, 1)) {
  252. OPENSSL_free(kem);
  253. return NULL;
  254. }
  255. kem->prov = prov;
  256. ossl_provider_up_ref(prov);
  257. return kem;
  258. }
  259. static void *evp_kem_from_algorithm(int name_id, const OSSL_ALGORITHM *algodef,
  260. OSSL_PROVIDER *prov)
  261. {
  262. const OSSL_DISPATCH *fns = algodef->implementation;
  263. EVP_KEM *kem = NULL;
  264. int ctxfncnt = 0, encfncnt = 0, decfncnt = 0;
  265. int gparamfncnt = 0, sparamfncnt = 0;
  266. if ((kem = evp_kem_new(prov)) == NULL) {
  267. ERR_raise(ERR_LIB_EVP, ERR_R_EVP_LIB);
  268. goto err;
  269. }
  270. kem->name_id = name_id;
  271. if ((kem->type_name = ossl_algorithm_get1_first_name(algodef)) == NULL)
  272. goto err;
  273. kem->description = algodef->algorithm_description;
  274. for (; fns->function_id != 0; fns++) {
  275. switch (fns->function_id) {
  276. case OSSL_FUNC_KEM_NEWCTX:
  277. if (kem->newctx != NULL)
  278. break;
  279. kem->newctx = OSSL_FUNC_kem_newctx(fns);
  280. ctxfncnt++;
  281. break;
  282. case OSSL_FUNC_KEM_ENCAPSULATE_INIT:
  283. if (kem->encapsulate_init != NULL)
  284. break;
  285. kem->encapsulate_init = OSSL_FUNC_kem_encapsulate_init(fns);
  286. encfncnt++;
  287. break;
  288. case OSSL_FUNC_KEM_AUTH_ENCAPSULATE_INIT:
  289. if (kem->auth_encapsulate_init != NULL)
  290. break;
  291. kem->auth_encapsulate_init = OSSL_FUNC_kem_auth_encapsulate_init(fns);
  292. encfncnt++;
  293. break;
  294. case OSSL_FUNC_KEM_ENCAPSULATE:
  295. if (kem->encapsulate != NULL)
  296. break;
  297. kem->encapsulate = OSSL_FUNC_kem_encapsulate(fns);
  298. encfncnt++;
  299. break;
  300. case OSSL_FUNC_KEM_DECAPSULATE_INIT:
  301. if (kem->decapsulate_init != NULL)
  302. break;
  303. kem->decapsulate_init = OSSL_FUNC_kem_decapsulate_init(fns);
  304. decfncnt++;
  305. break;
  306. case OSSL_FUNC_KEM_AUTH_DECAPSULATE_INIT:
  307. if (kem->auth_decapsulate_init != NULL)
  308. break;
  309. kem->auth_decapsulate_init = OSSL_FUNC_kem_auth_decapsulate_init(fns);
  310. decfncnt++;
  311. break;
  312. case OSSL_FUNC_KEM_DECAPSULATE:
  313. if (kem->decapsulate != NULL)
  314. break;
  315. kem->decapsulate = OSSL_FUNC_kem_decapsulate(fns);
  316. decfncnt++;
  317. break;
  318. case OSSL_FUNC_KEM_FREECTX:
  319. if (kem->freectx != NULL)
  320. break;
  321. kem->freectx = OSSL_FUNC_kem_freectx(fns);
  322. ctxfncnt++;
  323. break;
  324. case OSSL_FUNC_KEM_DUPCTX:
  325. if (kem->dupctx != NULL)
  326. break;
  327. kem->dupctx = OSSL_FUNC_kem_dupctx(fns);
  328. break;
  329. case OSSL_FUNC_KEM_GET_CTX_PARAMS:
  330. if (kem->get_ctx_params != NULL)
  331. break;
  332. kem->get_ctx_params
  333. = OSSL_FUNC_kem_get_ctx_params(fns);
  334. gparamfncnt++;
  335. break;
  336. case OSSL_FUNC_KEM_GETTABLE_CTX_PARAMS:
  337. if (kem->gettable_ctx_params != NULL)
  338. break;
  339. kem->gettable_ctx_params
  340. = OSSL_FUNC_kem_gettable_ctx_params(fns);
  341. gparamfncnt++;
  342. break;
  343. case OSSL_FUNC_KEM_SET_CTX_PARAMS:
  344. if (kem->set_ctx_params != NULL)
  345. break;
  346. kem->set_ctx_params
  347. = OSSL_FUNC_kem_set_ctx_params(fns);
  348. sparamfncnt++;
  349. break;
  350. case OSSL_FUNC_KEM_SETTABLE_CTX_PARAMS:
  351. if (kem->settable_ctx_params != NULL)
  352. break;
  353. kem->settable_ctx_params
  354. = OSSL_FUNC_kem_settable_ctx_params(fns);
  355. sparamfncnt++;
  356. break;
  357. }
  358. }
  359. if (ctxfncnt != 2
  360. || (encfncnt != 0 && encfncnt != 2 && encfncnt != 3)
  361. || (decfncnt != 0 && decfncnt != 2 && decfncnt != 3)
  362. || (encfncnt != decfncnt)
  363. || (gparamfncnt != 0 && gparamfncnt != 2)
  364. || (sparamfncnt != 0 && sparamfncnt != 2)) {
  365. /*
  366. * In order to be a consistent set of functions we must have at least
  367. * a set of context functions (newctx and freectx) as well as a pair
  368. * (or triplet) of "kem" functions:
  369. * (encapsulate_init, (and/or auth_encapsulate_init), encapsulate) or
  370. * (decapsulate_init, (and/or auth_decapsulate_init), decapsulate).
  371. * set_ctx_params and settable_ctx_params are optional, but if one of
  372. * them is present then the other one must also be present. The same
  373. * applies to get_ctx_params and gettable_ctx_params.
  374. * The dupctx function is optional.
  375. */
  376. ERR_raise(ERR_LIB_EVP, EVP_R_INVALID_PROVIDER_FUNCTIONS);
  377. goto err;
  378. }
  379. return kem;
  380. err:
  381. EVP_KEM_free(kem);
  382. return NULL;
  383. }
  384. void EVP_KEM_free(EVP_KEM *kem)
  385. {
  386. int i;
  387. if (kem == NULL)
  388. return;
  389. CRYPTO_DOWN_REF(&kem->refcnt, &i);
  390. if (i > 0)
  391. return;
  392. OPENSSL_free(kem->type_name);
  393. ossl_provider_free(kem->prov);
  394. CRYPTO_FREE_REF(&kem->refcnt);
  395. OPENSSL_free(kem);
  396. }
  397. int EVP_KEM_up_ref(EVP_KEM *kem)
  398. {
  399. int ref = 0;
  400. CRYPTO_UP_REF(&kem->refcnt, &ref);
  401. return 1;
  402. }
  403. OSSL_PROVIDER *EVP_KEM_get0_provider(const EVP_KEM *kem)
  404. {
  405. return kem->prov;
  406. }
  407. EVP_KEM *EVP_KEM_fetch(OSSL_LIB_CTX *ctx, const char *algorithm,
  408. const char *properties)
  409. {
  410. return evp_generic_fetch(ctx, OSSL_OP_KEM, algorithm, properties,
  411. evp_kem_from_algorithm,
  412. (int (*)(void *))EVP_KEM_up_ref,
  413. (void (*)(void *))EVP_KEM_free);
  414. }
  415. EVP_KEM *evp_kem_fetch_from_prov(OSSL_PROVIDER *prov, const char *algorithm,
  416. const char *properties)
  417. {
  418. return evp_generic_fetch_from_prov(prov, OSSL_OP_KEM, algorithm, properties,
  419. evp_kem_from_algorithm,
  420. (int (*)(void *))EVP_KEM_up_ref,
  421. (void (*)(void *))EVP_KEM_free);
  422. }
  423. int EVP_KEM_is_a(const EVP_KEM *kem, const char *name)
  424. {
  425. return kem != NULL && evp_is_a(kem->prov, kem->name_id, NULL, name);
  426. }
  427. int evp_kem_get_number(const EVP_KEM *kem)
  428. {
  429. return kem->name_id;
  430. }
  431. const char *EVP_KEM_get0_name(const EVP_KEM *kem)
  432. {
  433. return kem->type_name;
  434. }
  435. const char *EVP_KEM_get0_description(const EVP_KEM *kem)
  436. {
  437. return kem->description;
  438. }
  439. void EVP_KEM_do_all_provided(OSSL_LIB_CTX *libctx,
  440. void (*fn)(EVP_KEM *kem, void *arg),
  441. void *arg)
  442. {
  443. evp_generic_do_all(libctx, OSSL_OP_KEM, (void (*)(void *, void *))fn, arg,
  444. evp_kem_from_algorithm,
  445. (int (*)(void *))EVP_KEM_up_ref,
  446. (void (*)(void *))EVP_KEM_free);
  447. }
  448. int EVP_KEM_names_do_all(const EVP_KEM *kem,
  449. void (*fn)(const char *name, void *data),
  450. void *data)
  451. {
  452. if (kem->prov != NULL)
  453. return evp_names_do_all(kem->prov, kem->name_id, fn, data);
  454. return 1;
  455. }
  456. const OSSL_PARAM *EVP_KEM_gettable_ctx_params(const EVP_KEM *kem)
  457. {
  458. void *provctx;
  459. if (kem == NULL || kem->gettable_ctx_params == NULL)
  460. return NULL;
  461. provctx = ossl_provider_ctx(EVP_KEM_get0_provider(kem));
  462. return kem->gettable_ctx_params(NULL, provctx);
  463. }
  464. const OSSL_PARAM *EVP_KEM_settable_ctx_params(const EVP_KEM *kem)
  465. {
  466. void *provctx;
  467. if (kem == NULL || kem->settable_ctx_params == NULL)
  468. return NULL;
  469. provctx = ossl_provider_ctx(EVP_KEM_get0_provider(kem));
  470. return kem->settable_ctx_params(NULL, provctx);
  471. }