ec_kem.c 26 KB

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