kem.c 17 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531
  1. /*
  2. * Copyright 2020-2021 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. kem->lock = CRYPTO_THREAD_lock_new();
  252. if (kem->lock == NULL) {
  253. ERR_raise(ERR_LIB_EVP, ERR_R_CRYPTO_LIB);
  254. OPENSSL_free(kem);
  255. return NULL;
  256. }
  257. kem->prov = prov;
  258. ossl_provider_up_ref(prov);
  259. kem->refcnt = 1;
  260. return kem;
  261. }
  262. static void *evp_kem_from_algorithm(int name_id, const OSSL_ALGORITHM *algodef,
  263. OSSL_PROVIDER *prov)
  264. {
  265. const OSSL_DISPATCH *fns = algodef->implementation;
  266. EVP_KEM *kem = NULL;
  267. int ctxfncnt = 0, encfncnt = 0, decfncnt = 0;
  268. int gparamfncnt = 0, sparamfncnt = 0;
  269. if ((kem = evp_kem_new(prov)) == NULL) {
  270. ERR_raise(ERR_LIB_EVP, ERR_R_EVP_LIB);
  271. goto err;
  272. }
  273. kem->name_id = name_id;
  274. if ((kem->type_name = ossl_algorithm_get1_first_name(algodef)) == NULL)
  275. goto err;
  276. kem->description = algodef->algorithm_description;
  277. for (; fns->function_id != 0; fns++) {
  278. switch (fns->function_id) {
  279. case OSSL_FUNC_KEM_NEWCTX:
  280. if (kem->newctx != NULL)
  281. break;
  282. kem->newctx = OSSL_FUNC_kem_newctx(fns);
  283. ctxfncnt++;
  284. break;
  285. case OSSL_FUNC_KEM_ENCAPSULATE_INIT:
  286. if (kem->encapsulate_init != NULL)
  287. break;
  288. kem->encapsulate_init = OSSL_FUNC_kem_encapsulate_init(fns);
  289. encfncnt++;
  290. break;
  291. case OSSL_FUNC_KEM_AUTH_ENCAPSULATE_INIT:
  292. if (kem->auth_encapsulate_init != NULL)
  293. break;
  294. kem->auth_encapsulate_init = OSSL_FUNC_kem_auth_encapsulate_init(fns);
  295. encfncnt++;
  296. break;
  297. case OSSL_FUNC_KEM_ENCAPSULATE:
  298. if (kem->encapsulate != NULL)
  299. break;
  300. kem->encapsulate = OSSL_FUNC_kem_encapsulate(fns);
  301. encfncnt++;
  302. break;
  303. case OSSL_FUNC_KEM_DECAPSULATE_INIT:
  304. if (kem->decapsulate_init != NULL)
  305. break;
  306. kem->decapsulate_init = OSSL_FUNC_kem_decapsulate_init(fns);
  307. decfncnt++;
  308. break;
  309. case OSSL_FUNC_KEM_AUTH_DECAPSULATE_INIT:
  310. if (kem->auth_decapsulate_init != NULL)
  311. break;
  312. kem->auth_decapsulate_init = OSSL_FUNC_kem_auth_decapsulate_init(fns);
  313. decfncnt++;
  314. break;
  315. case OSSL_FUNC_KEM_DECAPSULATE:
  316. if (kem->decapsulate != NULL)
  317. break;
  318. kem->decapsulate = OSSL_FUNC_kem_decapsulate(fns);
  319. decfncnt++;
  320. break;
  321. case OSSL_FUNC_KEM_FREECTX:
  322. if (kem->freectx != NULL)
  323. break;
  324. kem->freectx = OSSL_FUNC_kem_freectx(fns);
  325. ctxfncnt++;
  326. break;
  327. case OSSL_FUNC_KEM_DUPCTX:
  328. if (kem->dupctx != NULL)
  329. break;
  330. kem->dupctx = OSSL_FUNC_kem_dupctx(fns);
  331. break;
  332. case OSSL_FUNC_KEM_GET_CTX_PARAMS:
  333. if (kem->get_ctx_params != NULL)
  334. break;
  335. kem->get_ctx_params
  336. = OSSL_FUNC_kem_get_ctx_params(fns);
  337. gparamfncnt++;
  338. break;
  339. case OSSL_FUNC_KEM_GETTABLE_CTX_PARAMS:
  340. if (kem->gettable_ctx_params != NULL)
  341. break;
  342. kem->gettable_ctx_params
  343. = OSSL_FUNC_kem_gettable_ctx_params(fns);
  344. gparamfncnt++;
  345. break;
  346. case OSSL_FUNC_KEM_SET_CTX_PARAMS:
  347. if (kem->set_ctx_params != NULL)
  348. break;
  349. kem->set_ctx_params
  350. = OSSL_FUNC_kem_set_ctx_params(fns);
  351. sparamfncnt++;
  352. break;
  353. case OSSL_FUNC_KEM_SETTABLE_CTX_PARAMS:
  354. if (kem->settable_ctx_params != NULL)
  355. break;
  356. kem->settable_ctx_params
  357. = OSSL_FUNC_kem_settable_ctx_params(fns);
  358. sparamfncnt++;
  359. break;
  360. }
  361. }
  362. if (ctxfncnt != 2
  363. || (encfncnt != 0 && encfncnt != 2 && encfncnt != 3)
  364. || (decfncnt != 0 && decfncnt != 2 && decfncnt != 3)
  365. || (encfncnt != decfncnt)
  366. || (gparamfncnt != 0 && gparamfncnt != 2)
  367. || (sparamfncnt != 0 && sparamfncnt != 2)) {
  368. /*
  369. * In order to be a consistent set of functions we must have at least
  370. * a set of context functions (newctx and freectx) as well as a pair
  371. * (or triplet) of "kem" functions:
  372. * (encapsulate_init, (and/or auth_encapsulate_init), encapsulate) or
  373. * (decapsulate_init, (and/or auth_decapsulate_init), decapsulate).
  374. * set_ctx_params and settable_ctx_params are optional, but if one of
  375. * them is present then the other one must also be present. The same
  376. * applies to get_ctx_params and gettable_ctx_params.
  377. * The dupctx function is optional.
  378. */
  379. ERR_raise(ERR_LIB_EVP, EVP_R_INVALID_PROVIDER_FUNCTIONS);
  380. goto err;
  381. }
  382. return kem;
  383. err:
  384. EVP_KEM_free(kem);
  385. return NULL;
  386. }
  387. void EVP_KEM_free(EVP_KEM *kem)
  388. {
  389. int i;
  390. if (kem == NULL)
  391. return;
  392. CRYPTO_DOWN_REF(&kem->refcnt, &i, kem->lock);
  393. if (i > 0)
  394. return;
  395. OPENSSL_free(kem->type_name);
  396. ossl_provider_free(kem->prov);
  397. CRYPTO_THREAD_lock_free(kem->lock);
  398. OPENSSL_free(kem);
  399. }
  400. int EVP_KEM_up_ref(EVP_KEM *kem)
  401. {
  402. int ref = 0;
  403. CRYPTO_UP_REF(&kem->refcnt, &ref, kem->lock);
  404. return 1;
  405. }
  406. OSSL_PROVIDER *EVP_KEM_get0_provider(const EVP_KEM *kem)
  407. {
  408. return kem->prov;
  409. }
  410. EVP_KEM *EVP_KEM_fetch(OSSL_LIB_CTX *ctx, const char *algorithm,
  411. const char *properties)
  412. {
  413. return evp_generic_fetch(ctx, OSSL_OP_KEM, algorithm, properties,
  414. evp_kem_from_algorithm,
  415. (int (*)(void *))EVP_KEM_up_ref,
  416. (void (*)(void *))EVP_KEM_free);
  417. }
  418. EVP_KEM *evp_kem_fetch_from_prov(OSSL_PROVIDER *prov, const char *algorithm,
  419. const char *properties)
  420. {
  421. return evp_generic_fetch_from_prov(prov, OSSL_OP_KEM, algorithm, properties,
  422. evp_kem_from_algorithm,
  423. (int (*)(void *))EVP_KEM_up_ref,
  424. (void (*)(void *))EVP_KEM_free);
  425. }
  426. int EVP_KEM_is_a(const EVP_KEM *kem, const char *name)
  427. {
  428. return kem != NULL && evp_is_a(kem->prov, kem->name_id, NULL, name);
  429. }
  430. int evp_kem_get_number(const EVP_KEM *kem)
  431. {
  432. return kem->name_id;
  433. }
  434. const char *EVP_KEM_get0_name(const EVP_KEM *kem)
  435. {
  436. return kem->type_name;
  437. }
  438. const char *EVP_KEM_get0_description(const EVP_KEM *kem)
  439. {
  440. return kem->description;
  441. }
  442. void EVP_KEM_do_all_provided(OSSL_LIB_CTX *libctx,
  443. void (*fn)(EVP_KEM *kem, void *arg),
  444. void *arg)
  445. {
  446. evp_generic_do_all(libctx, OSSL_OP_KEM, (void (*)(void *, void *))fn, arg,
  447. evp_kem_from_algorithm,
  448. (int (*)(void *))EVP_KEM_up_ref,
  449. (void (*)(void *))EVP_KEM_free);
  450. }
  451. int EVP_KEM_names_do_all(const EVP_KEM *kem,
  452. void (*fn)(const char *name, void *data),
  453. void *data)
  454. {
  455. if (kem->prov != NULL)
  456. return evp_names_do_all(kem->prov, kem->name_id, fn, data);
  457. return 1;
  458. }
  459. const OSSL_PARAM *EVP_KEM_gettable_ctx_params(const EVP_KEM *kem)
  460. {
  461. void *provctx;
  462. if (kem == NULL || kem->gettable_ctx_params == NULL)
  463. return NULL;
  464. provctx = ossl_provider_ctx(EVP_KEM_get0_provider(kem));
  465. return kem->gettable_ctx_params(NULL, provctx);
  466. }
  467. const OSSL_PARAM *EVP_KEM_settable_ctx_params(const EVP_KEM *kem)
  468. {
  469. void *provctx;
  470. if (kem == NULL || kem->settable_ctx_params == NULL)
  471. return NULL;
  472. provctx = ossl_provider_ctx(EVP_KEM_get0_provider(kem));
  473. return kem->settable_ctx_params(NULL, provctx);
  474. }