ec_kem.c 27 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841
  1. /*
  2. * Copyright 2022 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. /*
  10. * The following implementation is part of RFC 9180 related to DHKEM using
  11. * EC keys (i.e. P-256, P-384 and P-521)
  12. * References to Sections in the comments below refer to RFC 9180.
  13. */
  14. #include "internal/deprecated.h"
  15. #include <openssl/crypto.h>
  16. #include <openssl/evp.h>
  17. #include <openssl/core_dispatch.h>
  18. #include <openssl/core_names.h>
  19. #include <openssl/ec.h>
  20. #include <openssl/params.h>
  21. #include <openssl/err.h>
  22. #include <openssl/proverr.h>
  23. #include <openssl/kdf.h>
  24. #include <openssl/rand.h>
  25. #include "prov/provider_ctx.h"
  26. #include "prov/implementations.h"
  27. #include "prov/securitycheck.h"
  28. #include "prov/providercommon.h"
  29. #include "crypto/hpke.h"
  30. #include "crypto/ec.h"
  31. #include "prov/ecx.h"
  32. #include "eckem.h"
  33. /*
  34. * Used to store constants from Section 7.1 "Table 2 KEM IDs"
  35. * and the bitmask for curves described in Section 7.1.3 DeriveKeyPair
  36. */
  37. typedef struct {
  38. const char *curve;
  39. const char *kdfdigestname;
  40. uint16_t kemid;
  41. size_t secretlen; /* Nsecret = Nh */
  42. size_t encodedpublen;
  43. size_t encodedprivlen;
  44. uint8_t bitmask;
  45. } DHKEM_ALG;
  46. typedef struct {
  47. EC_KEY *recipient_key;
  48. EC_KEY *sender_authkey;
  49. OSSL_LIB_CTX *libctx;
  50. char *propq;
  51. unsigned int mode;
  52. unsigned int op;
  53. unsigned char *ikm;
  54. size_t ikmlen;
  55. const char *kdfname;
  56. const DHKEM_ALG *alg;
  57. } PROV_EC_CTX;
  58. static OSSL_FUNC_kem_newctx_fn eckem_newctx;
  59. static OSSL_FUNC_kem_encapsulate_init_fn eckem_encapsulate_init;
  60. static OSSL_FUNC_kem_auth_encapsulate_init_fn eckem_auth_encapsulate_init;
  61. static OSSL_FUNC_kem_encapsulate_fn eckem_encapsulate;
  62. static OSSL_FUNC_kem_decapsulate_init_fn eckem_decapsulate_init;
  63. static OSSL_FUNC_kem_auth_decapsulate_init_fn eckem_auth_decapsulate_init;
  64. static OSSL_FUNC_kem_decapsulate_fn eckem_decapsulate;
  65. static OSSL_FUNC_kem_freectx_fn eckem_freectx;
  66. static OSSL_FUNC_kem_set_ctx_params_fn eckem_set_ctx_params;
  67. static OSSL_FUNC_kem_settable_ctx_params_fn eckem_settable_ctx_params;
  68. /* See Section 7.1 "Table 2 KEM IDs" */
  69. static const DHKEM_ALG dhkem_alg[] = {
  70. { "P-256", "SHA256", 0x0010, 32, 65, 32, 0xFF },
  71. { "P-384", "SHA384", 0x0011, 48, 97, 48, 0xFF },
  72. { "P-521", "SHA512", 0x0012, 64, 133, 66, 0x01 },
  73. { NULL }
  74. };
  75. /* Return an object containing KEM constants associated with a EC curve name */
  76. static const DHKEM_ALG *dhkem_ec_find_alg(const char *curve)
  77. {
  78. int i;
  79. for (i = 0; dhkem_alg[i].curve != NULL; ++i) {
  80. if (OPENSSL_strcasecmp(curve, dhkem_alg[i].curve) == 0)
  81. return &dhkem_alg[i];
  82. }
  83. ERR_raise(ERR_LIB_PROV, PROV_R_INVALID_CURVE);
  84. return NULL;
  85. }
  86. static int eckey_check(const EC_KEY *ec, int requires_privatekey)
  87. {
  88. int rv = 0;
  89. BN_CTX *bnctx = NULL;
  90. BIGNUM *rem = NULL;
  91. const BIGNUM *priv = EC_KEY_get0_private_key(ec);
  92. const EC_POINT *pub = EC_KEY_get0_public_key(ec);
  93. /* Keys always require a public component */
  94. if (pub == NULL) {
  95. ERR_raise(ERR_LIB_PROV, PROV_R_NOT_A_PUBLIC_KEY);
  96. return 0;
  97. }
  98. if (priv == NULL) {
  99. return (requires_privatekey == 0);
  100. } else {
  101. /* If there is a private key, check that is non zero (mod order) */
  102. const EC_GROUP *group = EC_KEY_get0_group(ec);
  103. const BIGNUM *order = EC_GROUP_get0_order(group);
  104. bnctx = BN_CTX_new_ex(ossl_ec_key_get_libctx(ec));
  105. rem = BN_new();
  106. if (order != NULL && rem != NULL && bnctx != NULL) {
  107. rv = BN_mod(rem, priv, order, bnctx)
  108. && !BN_is_zero(rem);
  109. }
  110. }
  111. BN_free(rem);
  112. BN_CTX_free(bnctx);
  113. return rv;
  114. }
  115. /* Returns NULL if the curve is not supported */
  116. static const char *ec_curvename_get0(const EC_KEY *ec)
  117. {
  118. const EC_GROUP *group = EC_KEY_get0_group(ec);
  119. return EC_curve_nid2nist(EC_GROUP_get_curve_name(group));
  120. }
  121. /*
  122. * Set the recipient key, and free any existing key.
  123. * ec can be NULL.
  124. * The ec key may have only a private or public component
  125. * (but it must have a group).
  126. */
  127. static int recipient_key_set(PROV_EC_CTX *ctx, EC_KEY *ec)
  128. {
  129. EC_KEY_free(ctx->recipient_key);
  130. ctx->recipient_key = NULL;
  131. if (ec != NULL) {
  132. const char *curve = ec_curvename_get0(ec);
  133. if (curve == NULL)
  134. return -2;
  135. ctx->alg = dhkem_ec_find_alg(curve);
  136. if (ctx->alg == NULL)
  137. return -2;
  138. if (!EC_KEY_up_ref(ec))
  139. return 0;
  140. ctx->recipient_key = ec;
  141. ctx->kdfname = "HKDF";
  142. }
  143. return 1;
  144. }
  145. /*
  146. * Set the senders auth key, and free any existing auth key.
  147. * ec can be NULL.
  148. */
  149. static int sender_authkey_set(PROV_EC_CTX *ctx, EC_KEY *ec)
  150. {
  151. EC_KEY_free(ctx->sender_authkey);
  152. ctx->sender_authkey = NULL;
  153. if (ec != NULL) {
  154. if (!EC_KEY_up_ref(ec))
  155. return 0;
  156. ctx->sender_authkey = ec;
  157. }
  158. return 1;
  159. }
  160. /*
  161. * Serializes a encoded public key buffer into a EC public key.
  162. * Params:
  163. * in Contains the group.
  164. * pubbuf The encoded public key buffer
  165. * Returns: The created public EC key, or NULL if there is an error.
  166. */
  167. static EC_KEY *eckey_frompub(EC_KEY *in,
  168. const unsigned char *pubbuf, size_t pubbuflen)
  169. {
  170. EC_KEY *key;
  171. key = EC_KEY_new_ex(ossl_ec_key_get_libctx(in), ossl_ec_key_get0_propq(in));
  172. if (key == NULL)
  173. goto err;
  174. if (!EC_KEY_set_group(key, EC_KEY_get0_group(in)))
  175. goto err;
  176. if (!EC_KEY_oct2key(key, pubbuf, pubbuflen, NULL))
  177. goto err;
  178. return key;
  179. err:
  180. EC_KEY_free(key);
  181. return NULL;
  182. }
  183. /*
  184. * Deserialises a EC public key into a encoded byte array.
  185. * Returns: 1 if successful or 0 otherwise.
  186. */
  187. static int ecpubkey_todata(const EC_KEY *ec, unsigned char *out, size_t *outlen,
  188. size_t maxoutlen)
  189. {
  190. const EC_POINT *pub;
  191. const EC_GROUP *group;
  192. group = EC_KEY_get0_group(ec);
  193. pub = EC_KEY_get0_public_key(ec);
  194. *outlen = EC_POINT_point2oct(group, pub, POINT_CONVERSION_UNCOMPRESSED,
  195. out, maxoutlen, NULL);
  196. return *outlen != 0;
  197. }
  198. static void *eckem_newctx(void *provctx)
  199. {
  200. PROV_EC_CTX *ctx = OPENSSL_zalloc(sizeof(PROV_EC_CTX));
  201. if (ctx == NULL)
  202. return NULL;
  203. ctx->libctx = PROV_LIBCTX_OF(provctx);
  204. return ctx;
  205. }
  206. static void eckem_freectx(void *vectx)
  207. {
  208. PROV_EC_CTX *ctx = (PROV_EC_CTX *)vectx;
  209. OPENSSL_clear_free(ctx->ikm, ctx->ikmlen);
  210. recipient_key_set(ctx, NULL);
  211. sender_authkey_set(ctx, NULL);
  212. OPENSSL_free(ctx);
  213. }
  214. static int ossl_ec_match_params(const EC_KEY *key1, const EC_KEY *key2)
  215. {
  216. int ret;
  217. BN_CTX *ctx = NULL;
  218. const EC_GROUP *group1 = EC_KEY_get0_group(key1);
  219. const EC_GROUP *group2 = EC_KEY_get0_group(key2);
  220. ctx = BN_CTX_new_ex(ossl_ec_key_get_libctx(key1));
  221. if (ctx == NULL)
  222. return 0;
  223. ret = group1 != NULL
  224. && group2 != NULL
  225. && EC_GROUP_cmp(group1, group2, ctx) == 0;
  226. if (!ret)
  227. ERR_raise(ERR_LIB_PROV, PROV_R_MISMATCHING_DOMAIN_PARAMETERS);
  228. BN_CTX_free(ctx);
  229. return ret;
  230. }
  231. static int eckem_init(void *vctx, int operation, void *vec, void *vauth,
  232. const OSSL_PARAM params[])
  233. {
  234. int rv;
  235. PROV_EC_CTX *ctx = (PROV_EC_CTX *)vctx;
  236. EC_KEY *ec = vec;
  237. EC_KEY *auth = vauth;
  238. if (!ossl_prov_is_running())
  239. return 0;
  240. if (!eckey_check(ec, operation == EVP_PKEY_OP_DECAPSULATE))
  241. return 0;
  242. rv = recipient_key_set(ctx, ec);
  243. if (rv <= 0)
  244. return rv;
  245. if (auth != NULL) {
  246. if (!ossl_ec_match_params(ec, auth)
  247. || !eckey_check(auth, operation == EVP_PKEY_OP_ENCAPSULATE)
  248. || !sender_authkey_set(ctx, auth))
  249. return 0;
  250. }
  251. ctx->op = operation;
  252. return eckem_set_ctx_params(vctx, params);
  253. }
  254. static int eckem_encapsulate_init(void *vctx, void *vec,
  255. const OSSL_PARAM params[])
  256. {
  257. return eckem_init(vctx, EVP_PKEY_OP_ENCAPSULATE, vec, NULL, params);
  258. }
  259. static int eckem_decapsulate_init(void *vctx, void *vec,
  260. const OSSL_PARAM params[])
  261. {
  262. return eckem_init(vctx, EVP_PKEY_OP_DECAPSULATE, vec, NULL, params);
  263. }
  264. static int eckem_auth_encapsulate_init(void *vctx, void *vecx, void *vauthpriv,
  265. const OSSL_PARAM params[])
  266. {
  267. return eckem_init(vctx, EVP_PKEY_OP_ENCAPSULATE, vecx, vauthpriv, params);
  268. }
  269. static int eckem_auth_decapsulate_init(void *vctx, void *vecx, void *vauthpub,
  270. const OSSL_PARAM params[])
  271. {
  272. return eckem_init(vctx, EVP_PKEY_OP_DECAPSULATE, vecx, vauthpub, params);
  273. }
  274. static int eckem_set_ctx_params(void *vctx, const OSSL_PARAM params[])
  275. {
  276. PROV_EC_CTX *ctx = (PROV_EC_CTX *)vctx;
  277. const OSSL_PARAM *p;
  278. int mode;
  279. if (params == NULL)
  280. return 1;
  281. p = OSSL_PARAM_locate_const(params, OSSL_KEM_PARAM_IKME);
  282. if (p != NULL) {
  283. void *tmp = NULL;
  284. size_t tmplen = 0;
  285. if (p->data != NULL && p->data_size != 0) {
  286. if (!OSSL_PARAM_get_octet_string(p, &tmp, 0, &tmplen))
  287. return 0;
  288. }
  289. OPENSSL_clear_free(ctx->ikm, ctx->ikmlen);
  290. /* Set the ephemeral seed */
  291. ctx->ikm = tmp;
  292. ctx->ikmlen = tmplen;
  293. }
  294. p = OSSL_PARAM_locate_const(params, OSSL_KEM_PARAM_OPERATION);
  295. if (p != NULL) {
  296. if (p->data_type != OSSL_PARAM_UTF8_STRING)
  297. return 0;
  298. mode = ossl_eckem_modename2id(p->data);
  299. if (mode == KEM_MODE_UNDEFINED)
  300. return 0;
  301. ctx->mode = mode;
  302. }
  303. return 1;
  304. }
  305. static const OSSL_PARAM known_settable_eckem_ctx_params[] = {
  306. OSSL_PARAM_utf8_string(OSSL_KEM_PARAM_OPERATION, NULL, 0),
  307. OSSL_PARAM_octet_string(OSSL_KEM_PARAM_IKME, NULL, 0),
  308. OSSL_PARAM_END
  309. };
  310. static const OSSL_PARAM *eckem_settable_ctx_params(ossl_unused void *vctx,
  311. ossl_unused void *provctx)
  312. {
  313. return known_settable_eckem_ctx_params;
  314. }
  315. /*
  316. * See Section 4.1 DH-Based KEM (DHKEM) ExtractAndExpand
  317. */
  318. static int dhkem_extract_and_expand(EVP_KDF_CTX *kctx,
  319. unsigned char *okm, size_t okmlen,
  320. uint16_t kemid,
  321. const unsigned char *dhkm, size_t dhkmlen,
  322. const unsigned char *kemctx,
  323. size_t kemctxlen)
  324. {
  325. uint8_t suiteid[5];
  326. uint8_t prk[EVP_MAX_MD_SIZE];
  327. size_t prklen = okmlen;
  328. int ret;
  329. if (prklen > sizeof(prk))
  330. return 0;
  331. ossl_dhkem_getsuiteid(suiteid, kemid);
  332. ret = ossl_hpke_labeled_extract(kctx, prk, prklen,
  333. NULL, 0, suiteid, sizeof(suiteid),
  334. OSSL_DHKEM_LABEL_EAE_PRK, dhkm, dhkmlen)
  335. && ossl_hpke_labeled_expand(kctx, okm, okmlen, prk, prklen,
  336. suiteid, sizeof(suiteid),
  337. OSSL_DHKEM_LABEL_SHARED_SECRET,
  338. kemctx, kemctxlen);
  339. OPENSSL_cleanse(prk, prklen);
  340. return ret;
  341. }
  342. /*
  343. * See Section 7.1.3 DeriveKeyPair.
  344. *
  345. * This function is used by ec keygen.
  346. * (For this reason it does not use any of the state stored in PROV_EC_CTX).
  347. *
  348. * Params:
  349. * ec An initialized ec key.
  350. * priv The buffer to store the generated private key into (it is assumed
  351. * this is of length alg->encodedprivlen).
  352. * ikm buffer containing the input key material (seed). This must be set.
  353. * ikmlen size of the ikm buffer in bytes
  354. * Returns:
  355. * 1 if successful or 0 otherwise.
  356. */
  357. int ossl_ec_dhkem_derive_private(EC_KEY *ec, BIGNUM *priv,
  358. const unsigned char *ikm, size_t ikmlen)
  359. {
  360. int ret = 0;
  361. EVP_KDF_CTX *kdfctx = NULL;
  362. uint8_t suiteid[5];
  363. unsigned char prk[OSSL_HPKE_MAX_SECRET];
  364. unsigned char privbuf[OSSL_HPKE_MAX_PRIVATE];
  365. const BIGNUM *order;
  366. unsigned char counter = 0;
  367. const DHKEM_ALG *alg;
  368. const char *curve = ec_curvename_get0(ec);
  369. if (curve == NULL)
  370. return -2;
  371. alg = dhkem_ec_find_alg(curve);
  372. if (alg == NULL)
  373. return -2;
  374. kdfctx = ossl_kdf_ctx_create("HKDF", alg->kdfdigestname,
  375. ossl_ec_key_get_libctx(ec),
  376. ossl_ec_key_get0_propq(ec));
  377. if (kdfctx == NULL)
  378. return 0;
  379. /* ikmlen should have a length of at least Nsk */
  380. if (ikmlen < alg->encodedprivlen) {
  381. ERR_raise_data(ERR_LIB_PROV, PROV_R_INVALID_INPUT_LENGTH,
  382. "ikm length is :%zu, should be at least %zu",
  383. ikmlen, alg->encodedprivlen);
  384. goto err;
  385. }
  386. ossl_dhkem_getsuiteid(suiteid, alg->kemid);
  387. if (!ossl_hpke_labeled_extract(kdfctx, prk, alg->secretlen,
  388. NULL, 0, suiteid, sizeof(suiteid),
  389. OSSL_DHKEM_LABEL_DKP_PRK, ikm, ikmlen))
  390. goto err;
  391. order = EC_GROUP_get0_order(EC_KEY_get0_group(ec));
  392. do {
  393. if (!ossl_hpke_labeled_expand(kdfctx, privbuf, alg->encodedprivlen,
  394. prk, alg->secretlen,
  395. suiteid, sizeof(suiteid),
  396. OSSL_DHKEM_LABEL_CANDIDATE,
  397. &counter, 1))
  398. goto err;
  399. privbuf[0] &= alg->bitmask;
  400. if (BN_bin2bn(privbuf, alg->encodedprivlen, priv) == NULL)
  401. goto err;
  402. if (counter == 0xFF) {
  403. ERR_raise(ERR_LIB_PROV, PROV_R_FAILED_TO_GENERATE_KEY);
  404. goto err;
  405. }
  406. counter++;
  407. } while (BN_is_zero(priv) || BN_cmp(priv, order) >= 0);
  408. ret = 1;
  409. err:
  410. OPENSSL_cleanse(prk, sizeof(prk));
  411. OPENSSL_cleanse(privbuf, sizeof(privbuf));
  412. EVP_KDF_CTX_free(kdfctx);
  413. return ret;
  414. }
  415. /*
  416. * Do a keygen operation without having to use EVP_PKEY.
  417. * Params:
  418. * ctx Context object
  419. * ikm The seed material - if this is NULL, then a random seed is used.
  420. * Returns:
  421. * The generated EC key, or NULL on failure.
  422. */
  423. static EC_KEY *derivekey(PROV_EC_CTX *ctx,
  424. const unsigned char *ikm, size_t ikmlen)
  425. {
  426. int ret = 0;
  427. EC_KEY *key;
  428. unsigned char *seed = (unsigned char *)ikm;
  429. size_t seedlen = ikmlen;
  430. unsigned char tmpbuf[OSSL_HPKE_MAX_PRIVATE];
  431. key = EC_KEY_new_ex(ctx->libctx, ctx->propq);
  432. if (key == NULL)
  433. goto err;
  434. if (!EC_KEY_set_group(key, EC_KEY_get0_group(ctx->recipient_key)))
  435. goto err;
  436. /* Generate a random seed if there is no input ikm */
  437. if (seed == NULL || seedlen == 0) {
  438. seedlen = ctx->alg->encodedprivlen;
  439. if (seedlen > sizeof(tmpbuf))
  440. goto err;
  441. if (RAND_priv_bytes_ex(ctx->libctx, tmpbuf, seedlen, 0) <= 0)
  442. goto err;
  443. seed = tmpbuf;
  444. }
  445. ret = ossl_ec_generate_key_dhkem(key, seed, seedlen);
  446. err:
  447. if (seed != ikm)
  448. OPENSSL_cleanse(seed, seedlen);
  449. if (ret <= 0) {
  450. EC_KEY_free(key);
  451. key = NULL;
  452. }
  453. return key;
  454. }
  455. /*
  456. * Before doing a key exchange the public key of the peer needs to be checked
  457. * Note that the group check is not done here as we have already checked
  458. * that it only uses one of the approved curve names when the key was set.
  459. *
  460. * Returns 1 if the public key is valid, or 0 if it fails.
  461. */
  462. static int check_publickey(const EC_KEY *pub)
  463. {
  464. int ret = 0;
  465. BN_CTX *bnctx = BN_CTX_new_ex(ossl_ec_key_get_libctx(pub));
  466. if (bnctx == NULL)
  467. return 0;
  468. ret = ossl_ec_key_public_check(pub, bnctx);
  469. BN_CTX_free(bnctx);
  470. return ret;
  471. }
  472. /*
  473. * Do an ecdh key exchange.
  474. * dhkm = DH(sender, peer)
  475. *
  476. * NOTE: Instead of using EVP_PKEY_derive() API's, we use EC_KEY operations
  477. * to avoid messy conversions back to EVP_PKEY.
  478. *
  479. * Returns the size of the secret if successful, or 0 otherwise,
  480. */
  481. static int generate_ecdhkm(const EC_KEY *sender, const EC_KEY *peer,
  482. unsigned char *out, size_t maxout,
  483. unsigned int secretsz)
  484. {
  485. const EC_GROUP *group = EC_KEY_get0_group(sender);
  486. size_t secretlen = (EC_GROUP_get_degree(group) + 7) / 8;
  487. if (secretlen != secretsz || secretlen > maxout) {
  488. ERR_raise_data(ERR_LIB_PROV, PROV_R_BAD_LENGTH, "secretsz invalid");
  489. return 0;
  490. }
  491. if (!check_publickey(peer))
  492. return 0;
  493. return ECDH_compute_key(out, secretlen, EC_KEY_get0_public_key(peer),
  494. sender, NULL) > 0;
  495. }
  496. /*
  497. * Derive a secret using ECDH (code is shared by the encap and decap)
  498. *
  499. * dhkm = Concat(ecdh(privkey1, peerkey1), ecdh(privkey2, peerkey2)
  500. * kemctx = Concat(sender_pub, recipient_pub, ctx->sender_authkey)
  501. * secret = dhkem_extract_and_expand(kemid, dhkm, kemctx);
  502. *
  503. * Params:
  504. * ctx Object that contains algorithm state and constants.
  505. * secret The returned secret (with a length ctx->alg->secretlen bytes).
  506. * privkey1 A private key used for ECDH key derivation.
  507. * peerkey1 A public key used for ECDH key derivation with privkey1
  508. * privkey2 A optional private key used for a second ECDH key derivation.
  509. * It can be NULL.
  510. * peerkey2 A optional public key used for a second ECDH key derivation
  511. * with privkey2,. It can be NULL.
  512. * sender_pub The senders public key in encoded form.
  513. * recipient_pub The recipients public key in encoded form.
  514. * Notes:
  515. * The second ecdh() is only used for the HPKE auth modes when both privkey2
  516. * and peerkey2 are non NULL (i.e. ctx->sender_authkey is not NULL).
  517. */
  518. static int derive_secret(PROV_EC_CTX *ctx, unsigned char *secret,
  519. const EC_KEY *privkey1, const EC_KEY *peerkey1,
  520. const EC_KEY *privkey2, const EC_KEY *peerkey2,
  521. const unsigned char *sender_pub,
  522. const unsigned char *recipient_pub)
  523. {
  524. int ret = 0;
  525. EVP_KDF_CTX *kdfctx = NULL;
  526. unsigned char sender_authpub[OSSL_HPKE_MAX_PUBLIC];
  527. unsigned char dhkm[OSSL_HPKE_MAX_PRIVATE * 2];
  528. unsigned char kemctx[OSSL_HPKE_MAX_PUBLIC * 3];
  529. size_t sender_authpublen;
  530. size_t kemctxlen = 0, dhkmlen = 0;
  531. size_t encodedpublen = ctx->alg->encodedpublen;
  532. size_t encodedprivlen = ctx->alg->encodedprivlen;
  533. int auth = ctx->sender_authkey != NULL;
  534. if (!generate_ecdhkm(privkey1, peerkey1, dhkm, sizeof(dhkm), encodedprivlen))
  535. goto err;
  536. dhkmlen = encodedprivlen;
  537. kemctxlen = 2 * encodedpublen;
  538. /* Concat the optional second ECDH (used for Auth) */
  539. if (auth) {
  540. /* Get the public key of the auth sender in encoded form */
  541. if (!ecpubkey_todata(ctx->sender_authkey, sender_authpub,
  542. &sender_authpublen, sizeof(sender_authpub)))
  543. goto err;
  544. if (sender_authpublen != encodedpublen) {
  545. ERR_raise_data(ERR_LIB_PROV, PROV_R_INVALID_KEY,
  546. "Invalid sender auth public key");
  547. goto err;
  548. }
  549. if (!generate_ecdhkm(privkey2, peerkey2,
  550. dhkm + dhkmlen, sizeof(dhkm) - dhkmlen,
  551. encodedprivlen))
  552. goto err;
  553. dhkmlen += encodedprivlen;
  554. kemctxlen += encodedpublen;
  555. }
  556. if (kemctxlen > sizeof(kemctx))
  557. goto err;
  558. /* kemctx is the concat of both sides encoded public key */
  559. memcpy(kemctx, sender_pub, ctx->alg->encodedpublen);
  560. memcpy(kemctx + ctx->alg->encodedpublen, recipient_pub,
  561. ctx->alg->encodedpublen);
  562. if (auth)
  563. memcpy(kemctx + 2 * encodedpublen, sender_authpub, encodedpublen);
  564. kdfctx = ossl_kdf_ctx_create(ctx->kdfname, ctx->alg->kdfdigestname,
  565. ctx->libctx, ctx->propq);
  566. if (kdfctx == NULL)
  567. goto err;
  568. if (!dhkem_extract_and_expand(kdfctx, secret, ctx->alg->secretlen,
  569. ctx->alg->kemid, dhkm, dhkmlen,
  570. kemctx, kemctxlen))
  571. goto err;
  572. ret = 1;
  573. err:
  574. OPENSSL_cleanse(dhkm, dhkmlen);
  575. EVP_KDF_CTX_free(kdfctx);
  576. return ret;
  577. }
  578. /*
  579. * Do a DHKEM encapsulate operation.
  580. *
  581. * See Section 4.1 Encap() and AuthEncap()
  582. *
  583. * Params:
  584. * ctx A context object holding the recipients public key and the
  585. * optional senders auth private key.
  586. * enc A buffer to return the senders ephemeral public key.
  587. * Setting this to NULL allows the enclen and secretlen to return
  588. * values, without calculating the secret.
  589. * enclen Passes in the max size of the enc buffer and returns the
  590. * encoded public key length.
  591. * secret A buffer to return the calculated shared secret.
  592. * secretlen Passes in the max size of the secret buffer and returns the
  593. * secret length.
  594. * Returns: 1 on success or 0 otherwise.
  595. */
  596. static int dhkem_encap(PROV_EC_CTX *ctx,
  597. unsigned char *enc, size_t *enclen,
  598. unsigned char *secret, size_t *secretlen)
  599. {
  600. int ret = 0;
  601. EC_KEY *sender_ephemkey = NULL;
  602. unsigned char sender_pub[OSSL_HPKE_MAX_PUBLIC];
  603. unsigned char recipient_pub[OSSL_HPKE_MAX_PUBLIC];
  604. size_t sender_publen, recipient_publen;
  605. if (enc == NULL) {
  606. if (enclen == NULL && secretlen == NULL)
  607. return 0;
  608. if (enclen != NULL)
  609. *enclen = ctx->alg->encodedpublen;
  610. if (secretlen != NULL)
  611. *secretlen = ctx->alg->secretlen;
  612. return 1;
  613. }
  614. if (*secretlen < ctx->alg->secretlen) {
  615. ERR_raise_data(ERR_LIB_PROV, PROV_R_BAD_LENGTH, "*secretlen too small");
  616. return 0;
  617. }
  618. if (*enclen < ctx->alg->encodedpublen) {
  619. ERR_raise_data(ERR_LIB_PROV, PROV_R_BAD_LENGTH, "*enclen too small");
  620. return 0;
  621. }
  622. /* Create an ephemeral key */
  623. sender_ephemkey = derivekey(ctx, ctx->ikm, ctx->ikmlen);
  624. if (sender_ephemkey == NULL)
  625. goto err;
  626. if (!ecpubkey_todata(sender_ephemkey, sender_pub, &sender_publen,
  627. sizeof(sender_pub))
  628. || !ecpubkey_todata(ctx->recipient_key, recipient_pub,
  629. &recipient_publen, sizeof(recipient_pub)))
  630. goto err;
  631. if (sender_publen != ctx->alg->encodedpublen
  632. || recipient_publen != sender_publen) {
  633. ERR_raise_data(ERR_LIB_PROV, PROV_R_INVALID_KEY, "Invalid public key");
  634. goto err;
  635. }
  636. if (!derive_secret(ctx, secret,
  637. sender_ephemkey, ctx->recipient_key,
  638. ctx->sender_authkey, ctx->recipient_key,
  639. sender_pub, recipient_pub))
  640. goto err;
  641. /* Return the senders ephemeral public key in encoded form */
  642. memcpy(enc, sender_pub, sender_publen);
  643. *enclen = sender_publen;
  644. *secretlen = ctx->alg->secretlen;
  645. ret = 1;
  646. err:
  647. EC_KEY_free(sender_ephemkey);
  648. return ret;
  649. }
  650. /*
  651. * Do a DHKEM decapsulate operation.
  652. * See Section 4.1 Decap() and Auth Decap()
  653. *
  654. * Params:
  655. * ctx A context object holding the recipients private key and the
  656. * optional senders auth public key.
  657. * secret A buffer to return the calculated shared secret. Setting this to
  658. * NULL can be used to return the secretlen.
  659. * secretlen Passes in the max size of the secret buffer and returns the
  660. * secret length.
  661. * enc A buffer containing the senders ephemeral public key that was returned
  662. * from dhkem_encap().
  663. * enclen The length in bytes of enc.
  664. * Returns: 1 If the shared secret is returned or 0 on error.
  665. */
  666. static int dhkem_decap(PROV_EC_CTX *ctx,
  667. unsigned char *secret, size_t *secretlen,
  668. const unsigned char *enc, size_t enclen)
  669. {
  670. int ret = 0;
  671. EC_KEY *sender_ephempubkey = NULL;
  672. unsigned char recipient_pub[OSSL_HPKE_MAX_PUBLIC];
  673. size_t recipient_publen;
  674. size_t encodedpublen = ctx->alg->encodedpublen;
  675. if (secret == NULL) {
  676. *secretlen = ctx->alg->secretlen;
  677. return 1;
  678. }
  679. if (*secretlen < ctx->alg->secretlen) {
  680. ERR_raise_data(ERR_LIB_PROV, PROV_R_BAD_LENGTH, "*secretlen too small");
  681. return 0;
  682. }
  683. if (enclen != encodedpublen) {
  684. ERR_raise_data(ERR_LIB_PROV, PROV_R_INVALID_KEY, "Invalid enc public key");
  685. return 0;
  686. }
  687. sender_ephempubkey = eckey_frompub(ctx->recipient_key, enc, enclen);
  688. if (sender_ephempubkey == NULL)
  689. goto err;
  690. if (!ecpubkey_todata(ctx->recipient_key, recipient_pub, &recipient_publen,
  691. sizeof(recipient_pub)))
  692. goto err;
  693. if (recipient_publen != encodedpublen) {
  694. ERR_raise_data(ERR_LIB_PROV, PROV_R_INVALID_KEY, "Invalid recipient public key");
  695. goto err;
  696. }
  697. if (!derive_secret(ctx, secret,
  698. ctx->recipient_key, sender_ephempubkey,
  699. ctx->recipient_key, ctx->sender_authkey,
  700. enc, recipient_pub))
  701. goto err;
  702. *secretlen = ctx->alg->secretlen;
  703. ret = 1;
  704. err:
  705. EC_KEY_free(sender_ephempubkey);
  706. return ret;
  707. }
  708. static int eckem_encapsulate(void *vctx, unsigned char *out, size_t *outlen,
  709. unsigned char *secret, size_t *secretlen)
  710. {
  711. PROV_EC_CTX *ctx = (PROV_EC_CTX *)vctx;
  712. switch (ctx->mode) {
  713. case KEM_MODE_DHKEM:
  714. return dhkem_encap(ctx, out, outlen, secret, secretlen);
  715. default:
  716. ERR_raise(ERR_LIB_PROV, PROV_R_INVALID_MODE);
  717. return -2;
  718. }
  719. }
  720. static int eckem_decapsulate(void *vctx, unsigned char *out, size_t *outlen,
  721. const unsigned char *in, size_t inlen)
  722. {
  723. PROV_EC_CTX *ctx = (PROV_EC_CTX *)vctx;
  724. switch (ctx->mode) {
  725. case KEM_MODE_DHKEM:
  726. return dhkem_decap(ctx, out, outlen, in, inlen);
  727. default:
  728. ERR_raise(ERR_LIB_PROV, PROV_R_INVALID_MODE);
  729. return -2;
  730. }
  731. }
  732. const OSSL_DISPATCH ossl_ec_asym_kem_functions[] = {
  733. { OSSL_FUNC_KEM_NEWCTX, (void (*)(void))eckem_newctx },
  734. { OSSL_FUNC_KEM_ENCAPSULATE_INIT,
  735. (void (*)(void))eckem_encapsulate_init },
  736. { OSSL_FUNC_KEM_ENCAPSULATE, (void (*)(void))eckem_encapsulate },
  737. { OSSL_FUNC_KEM_DECAPSULATE_INIT,
  738. (void (*)(void))eckem_decapsulate_init },
  739. { OSSL_FUNC_KEM_DECAPSULATE, (void (*)(void))eckem_decapsulate },
  740. { OSSL_FUNC_KEM_FREECTX, (void (*)(void))eckem_freectx },
  741. { OSSL_FUNC_KEM_SET_CTX_PARAMS,
  742. (void (*)(void))eckem_set_ctx_params },
  743. { OSSL_FUNC_KEM_SETTABLE_CTX_PARAMS,
  744. (void (*)(void))eckem_settable_ctx_params },
  745. { OSSL_FUNC_KEM_AUTH_ENCAPSULATE_INIT,
  746. (void (*)(void))eckem_auth_encapsulate_init },
  747. { OSSL_FUNC_KEM_AUTH_DECAPSULATE_INIT,
  748. (void (*)(void))eckem_auth_decapsulate_init },
  749. { 0, NULL }
  750. };