kem.c 17 KB

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