hpke.c 48 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392139313941395139613971398139914001401140214031404140514061407140814091410141114121413141414151416141714181419142014211422142314241425142614271428142914301431143214331434143514361437
  1. /*
  2. * Copyright 2022-2023 The OpenSSL Project Authors. All Rights Reserved.
  3. *
  4. * Licensed under the OpenSSL license (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. /* An OpenSSL-based HPKE implementation of RFC9180 */
  10. #include <string.h>
  11. #include <openssl/rand.h>
  12. #include <openssl/kdf.h>
  13. #include <openssl/core_names.h>
  14. #include <openssl/hpke.h>
  15. #include <openssl/sha.h>
  16. #include <openssl/evp.h>
  17. #include <openssl/err.h>
  18. #include "internal/hpke_util.h"
  19. #include "internal/nelem.h"
  20. /** default buffer size for keys and internal buffers we use */
  21. #define OSSL_HPKE_MAXSIZE 512
  22. /* Define HPKE labels from RFC9180 in hex for EBCDIC compatibility */
  23. /* "HPKE" - "suite_id" label for section 5.1 */
  24. static const char OSSL_HPKE_SEC51LABEL[] = "\x48\x50\x4b\x45";
  25. /* "psk_id_hash" - in key_schedule_context */
  26. static const char OSSL_HPKE_PSKIDHASH_LABEL[] = "\x70\x73\x6b\x5f\x69\x64\x5f\x68\x61\x73\x68";
  27. /* "info_hash" - in key_schedule_context */
  28. static const char OSSL_HPKE_INFOHASH_LABEL[] = "\x69\x6e\x66\x6f\x5f\x68\x61\x73\x68";
  29. /* "base_nonce" - base nonce calc label */
  30. static const char OSSL_HPKE_NONCE_LABEL[] = "\x62\x61\x73\x65\x5f\x6e\x6f\x6e\x63\x65";
  31. /* "exp" - internal exporter secret generation label */
  32. static const char OSSL_HPKE_EXP_LABEL[] = "\x65\x78\x70";
  33. /* "sec" - external label for exporting secret */
  34. static const char OSSL_HPKE_EXP_SEC_LABEL[] = "\x73\x65\x63";
  35. /* "key" - label for use when generating key from shared secret */
  36. static const char OSSL_HPKE_KEY_LABEL[] = "\x6b\x65\x79";
  37. /* "psk_hash" - for hashing PSK */
  38. static const char OSSL_HPKE_PSK_HASH_LABEL[] = "\x70\x73\x6b\x5f\x68\x61\x73\x68";
  39. /* "secret" - for generating shared secret */
  40. static const char OSSL_HPKE_SECRET_LABEL[] = "\x73\x65\x63\x72\x65\x74";
  41. /**
  42. * @brief sender or receiver context
  43. */
  44. struct ossl_hpke_ctx_st
  45. {
  46. OSSL_LIB_CTX *libctx; /* library context */
  47. char *propq; /* properties */
  48. int mode; /* HPKE mode */
  49. OSSL_HPKE_SUITE suite; /* suite */
  50. const OSSL_HPKE_KEM_INFO *kem_info;
  51. const OSSL_HPKE_KDF_INFO *kdf_info;
  52. const OSSL_HPKE_AEAD_INFO *aead_info;
  53. EVP_CIPHER *aead_ciph;
  54. int role; /* sender(0) or receiver(1) */
  55. uint64_t seq; /* aead sequence number */
  56. unsigned char *shared_secret; /* KEM output, zz */
  57. size_t shared_secretlen;
  58. unsigned char *key; /* final aead key */
  59. size_t keylen;
  60. unsigned char *nonce; /* aead base nonce */
  61. size_t noncelen;
  62. unsigned char *exportersec; /* exporter secret */
  63. size_t exporterseclen;
  64. char *pskid; /* PSK stuff */
  65. unsigned char *psk;
  66. size_t psklen;
  67. EVP_PKEY *authpriv; /* sender's authentication private key */
  68. unsigned char *authpub; /* auth public key */
  69. size_t authpublen;
  70. unsigned char *ikme; /* IKM for sender deterministic key gen */
  71. size_t ikmelen;
  72. };
  73. /**
  74. * @brief check if KEM uses NIST curve or not
  75. * @param kem_id is the externally supplied kem_id
  76. * @return 1 for NIST curves, 0 for other
  77. */
  78. static int hpke_kem_id_nist_curve(uint16_t kem_id)
  79. {
  80. const OSSL_HPKE_KEM_INFO *kem_info;
  81. kem_info = ossl_HPKE_KEM_INFO_find_id(kem_id);
  82. return kem_info != NULL && kem_info->groupname != NULL;
  83. }
  84. /**
  85. * @brief wrapper to import NIST curve public key as easily as x25519/x448
  86. * @param libctx is the context to use
  87. * @param propq is a properties string
  88. * @param gname is the curve groupname
  89. * @param buf is the binary buffer with the (uncompressed) public value
  90. * @param buflen is the length of the private key buffer
  91. * @return a working EVP_PKEY * or NULL
  92. *
  93. * Note that this could be a useful function to make public in
  94. * future, but would likely require a name change.
  95. */
  96. static EVP_PKEY *evp_pkey_new_raw_nist_public_key(OSSL_LIB_CTX *libctx,
  97. const char *propq,
  98. const char *gname,
  99. const unsigned char *buf,
  100. size_t buflen)
  101. {
  102. OSSL_PARAM params[2];
  103. EVP_PKEY *ret = NULL;
  104. EVP_PKEY_CTX *cctx = EVP_PKEY_CTX_new_from_name(libctx, "EC", propq);
  105. params[0] = OSSL_PARAM_construct_utf8_string(OSSL_PKEY_PARAM_GROUP_NAME,
  106. (char *)gname, 0);
  107. params[1] = OSSL_PARAM_construct_end();
  108. if (cctx == NULL
  109. || EVP_PKEY_paramgen_init(cctx) <= 0
  110. || EVP_PKEY_CTX_set_params(cctx, params) <= 0
  111. || EVP_PKEY_paramgen(cctx, &ret) <= 0
  112. || EVP_PKEY_set1_encoded_public_key(ret, buf, buflen) != 1) {
  113. EVP_PKEY_CTX_free(cctx);
  114. EVP_PKEY_free(ret);
  115. ERR_raise(ERR_LIB_CRYPTO, ERR_R_INTERNAL_ERROR);
  116. return NULL;
  117. }
  118. EVP_PKEY_CTX_free(cctx);
  119. return ret;
  120. }
  121. /**
  122. * @brief do the AEAD decryption
  123. * @param hctx is the context to use
  124. * @param iv is the initialisation vector
  125. * @param aad is the additional authenticated data
  126. * @param aadlen is the length of the aad
  127. * @param ct is the ciphertext buffer
  128. * @param ctlen is the ciphertext length (including tag).
  129. * @param pt is the output buffer
  130. * @param ptlen input/output, better be big enough on input, exact on output
  131. * @return 1 on success, 0 otherwise
  132. */
  133. static int hpke_aead_dec(OSSL_HPKE_CTX *hctx, const unsigned char *iv,
  134. const unsigned char *aad, size_t aadlen,
  135. const unsigned char *ct, size_t ctlen,
  136. unsigned char *pt, size_t *ptlen)
  137. {
  138. int erv = 0;
  139. EVP_CIPHER_CTX *ctx = NULL;
  140. int len = 0;
  141. size_t taglen;
  142. taglen = hctx->aead_info->taglen;
  143. if (ctlen <= taglen || *ptlen < ctlen - taglen) {
  144. ERR_raise(ERR_LIB_CRYPTO, ERR_R_PASSED_INVALID_ARGUMENT);
  145. return 0;
  146. }
  147. /* Create and initialise the context */
  148. if ((ctx = EVP_CIPHER_CTX_new()) == NULL)
  149. return 0;
  150. /* Initialise the decryption operation. */
  151. if (EVP_DecryptInit_ex(ctx, hctx->aead_ciph, NULL, NULL, NULL) != 1) {
  152. ERR_raise(ERR_LIB_CRYPTO, ERR_R_INTERNAL_ERROR);
  153. goto err;
  154. }
  155. if (EVP_CIPHER_CTX_ctrl(ctx, EVP_CTRL_AEAD_SET_IVLEN,
  156. hctx->noncelen, NULL) != 1) {
  157. ERR_raise(ERR_LIB_CRYPTO, ERR_R_INTERNAL_ERROR);
  158. goto err;
  159. }
  160. /* Initialise key and IV */
  161. if (EVP_DecryptInit_ex(ctx, NULL, NULL, hctx->key, iv) != 1) {
  162. ERR_raise(ERR_LIB_CRYPTO, ERR_R_INTERNAL_ERROR);
  163. goto err;
  164. }
  165. /* Provide AAD. */
  166. if (aadlen != 0 && aad != NULL) {
  167. if (EVP_DecryptUpdate(ctx, NULL, &len, aad, aadlen) != 1) {
  168. ERR_raise(ERR_LIB_CRYPTO, ERR_R_INTERNAL_ERROR);
  169. goto err;
  170. }
  171. }
  172. if (EVP_DecryptUpdate(ctx, pt, &len, ct, ctlen - taglen) != 1) {
  173. ERR_raise(ERR_LIB_CRYPTO, ERR_R_INTERNAL_ERROR);
  174. goto err;
  175. }
  176. *ptlen = len;
  177. if (!EVP_CIPHER_CTX_ctrl(ctx, EVP_CTRL_AEAD_SET_TAG,
  178. taglen, (void *)(ct + ctlen - taglen))) {
  179. ERR_raise(ERR_LIB_CRYPTO, ERR_R_INTERNAL_ERROR);
  180. goto err;
  181. }
  182. /* Finalise decryption. */
  183. if (EVP_DecryptFinal_ex(ctx, pt + len, &len) <= 0) {
  184. ERR_raise(ERR_LIB_CRYPTO, ERR_R_INTERNAL_ERROR);
  185. goto err;
  186. }
  187. erv = 1;
  188. err:
  189. if (erv != 1)
  190. OPENSSL_cleanse(pt, *ptlen);
  191. EVP_CIPHER_CTX_free(ctx);
  192. return erv;
  193. }
  194. /**
  195. * @brief do AEAD encryption as per the RFC
  196. * @param hctx is the context to use
  197. * @param iv is the initialisation vector
  198. * @param aad is the additional authenticated data
  199. * @param aadlen is the length of the aad
  200. * @param pt is the plaintext buffer
  201. * @param ptlen is the length of pt
  202. * @param ct is the output buffer
  203. * @param ctlen input/output, needs space for tag on input, exact on output
  204. * @return 1 for success, 0 otherwise
  205. */
  206. static int hpke_aead_enc(OSSL_HPKE_CTX *hctx, const unsigned char *iv,
  207. const unsigned char *aad, size_t aadlen,
  208. const unsigned char *pt, size_t ptlen,
  209. unsigned char *ct, size_t *ctlen)
  210. {
  211. int erv = 0;
  212. EVP_CIPHER_CTX *ctx = NULL;
  213. int len;
  214. size_t taglen = 0;
  215. unsigned char tag[16];
  216. taglen = hctx->aead_info->taglen;
  217. if (*ctlen <= taglen || ptlen > *ctlen - taglen) {
  218. ERR_raise(ERR_LIB_CRYPTO, ERR_R_PASSED_INVALID_ARGUMENT);
  219. return 0;
  220. }
  221. /* Create and initialise the context */
  222. if ((ctx = EVP_CIPHER_CTX_new()) == NULL)
  223. return 0;
  224. /* Initialise the encryption operation. */
  225. if (EVP_EncryptInit_ex(ctx, hctx->aead_ciph, NULL, NULL, NULL) != 1) {
  226. ERR_raise(ERR_LIB_CRYPTO, ERR_R_INTERNAL_ERROR);
  227. goto err;
  228. }
  229. if (EVP_CIPHER_CTX_ctrl(ctx, EVP_CTRL_AEAD_SET_IVLEN,
  230. hctx->noncelen, NULL) != 1) {
  231. ERR_raise(ERR_LIB_CRYPTO, ERR_R_INTERNAL_ERROR);
  232. goto err;
  233. }
  234. /* Initialise key and IV */
  235. if (EVP_EncryptInit_ex(ctx, NULL, NULL, hctx->key, iv) != 1) {
  236. ERR_raise(ERR_LIB_CRYPTO, ERR_R_INTERNAL_ERROR);
  237. goto err;
  238. }
  239. /* Provide any AAD data. */
  240. if (aadlen != 0 && aad != NULL) {
  241. if (EVP_EncryptUpdate(ctx, NULL, &len, aad, aadlen) != 1) {
  242. ERR_raise(ERR_LIB_CRYPTO, ERR_R_INTERNAL_ERROR);
  243. goto err;
  244. }
  245. }
  246. if (EVP_EncryptUpdate(ctx, ct, &len, pt, ptlen) != 1) {
  247. ERR_raise(ERR_LIB_CRYPTO, ERR_R_INTERNAL_ERROR);
  248. goto err;
  249. }
  250. *ctlen = len;
  251. /* Finalise the encryption. */
  252. if (EVP_EncryptFinal_ex(ctx, ct + len, &len) != 1) {
  253. ERR_raise(ERR_LIB_CRYPTO, ERR_R_INTERNAL_ERROR);
  254. goto err;
  255. }
  256. *ctlen += len;
  257. /* Get tag. Not a duplicate so needs to be added to the ciphertext */
  258. if (EVP_CIPHER_CTX_ctrl(ctx, EVP_CTRL_AEAD_GET_TAG, taglen, tag) != 1) {
  259. ERR_raise(ERR_LIB_CRYPTO, ERR_R_INTERNAL_ERROR);
  260. goto err;
  261. }
  262. memcpy(ct + *ctlen, tag, taglen);
  263. *ctlen += taglen;
  264. erv = 1;
  265. err:
  266. if (erv != 1)
  267. OPENSSL_cleanse(ct, *ctlen);
  268. EVP_CIPHER_CTX_free(ctx);
  269. return erv;
  270. }
  271. /**
  272. * @brief check mode is in-range and supported
  273. * @param mode is the caller's chosen mode
  274. * @return 1 for good mode, 0 otherwise
  275. */
  276. static int hpke_mode_check(unsigned int mode)
  277. {
  278. switch (mode) {
  279. case OSSL_HPKE_MODE_BASE:
  280. case OSSL_HPKE_MODE_PSK:
  281. case OSSL_HPKE_MODE_AUTH:
  282. case OSSL_HPKE_MODE_PSKAUTH:
  283. break;
  284. default:
  285. return 0;
  286. }
  287. return 1;
  288. }
  289. /**
  290. * @brief check if a suite is supported locally
  291. * @param suite is the suite to check
  292. * @return 1 for good, 0 otherwise
  293. */
  294. static int hpke_suite_check(OSSL_HPKE_SUITE suite,
  295. const OSSL_HPKE_KEM_INFO **kem_info,
  296. const OSSL_HPKE_KDF_INFO **kdf_info,
  297. const OSSL_HPKE_AEAD_INFO **aead_info)
  298. {
  299. const OSSL_HPKE_KEM_INFO *kem_info_;
  300. const OSSL_HPKE_KDF_INFO *kdf_info_;
  301. const OSSL_HPKE_AEAD_INFO *aead_info_;
  302. /* check KEM, KDF and AEAD are supported here */
  303. if ((kem_info_ = ossl_HPKE_KEM_INFO_find_id(suite.kem_id)) == NULL)
  304. return 0;
  305. if ((kdf_info_ = ossl_HPKE_KDF_INFO_find_id(suite.kdf_id)) == NULL)
  306. return 0;
  307. if ((aead_info_ = ossl_HPKE_AEAD_INFO_find_id(suite.aead_id)) == NULL)
  308. return 0;
  309. if (kem_info != NULL)
  310. *kem_info = kem_info_;
  311. if (kdf_info != NULL)
  312. *kdf_info = kdf_info_;
  313. if (aead_info != NULL)
  314. *aead_info = aead_info_;
  315. return 1;
  316. }
  317. /*
  318. * @brief randomly pick a suite
  319. * @param libctx is the context to use
  320. * @param propq is a properties string
  321. * @param suite is the result
  322. * @return 1 for success, 0 otherwise
  323. */
  324. static int hpke_random_suite(OSSL_LIB_CTX *libctx,
  325. const char *propq,
  326. OSSL_HPKE_SUITE *suite)
  327. {
  328. const OSSL_HPKE_KEM_INFO *kem_info = NULL;
  329. const OSSL_HPKE_KDF_INFO *kdf_info = NULL;
  330. const OSSL_HPKE_AEAD_INFO *aead_info = NULL;
  331. /* random kem, kdf and aead */
  332. kem_info = ossl_HPKE_KEM_INFO_find_random(libctx);
  333. if (kem_info == NULL)
  334. return 0;
  335. suite->kem_id = kem_info->kem_id;
  336. kdf_info = ossl_HPKE_KDF_INFO_find_random(libctx);
  337. if (kdf_info == NULL)
  338. return 0;
  339. suite->kdf_id = kdf_info->kdf_id;
  340. aead_info = ossl_HPKE_AEAD_INFO_find_random(libctx);
  341. if (aead_info == NULL)
  342. return 0;
  343. suite->aead_id = aead_info->aead_id;
  344. return 1;
  345. }
  346. /*
  347. * @brief tell the caller how big the ciphertext will be
  348. *
  349. * AEAD algorithms add a tag for data authentication.
  350. * Those are almost always, but not always, 16 octets
  351. * long, and who knows what will be true in the future.
  352. * So this function allows a caller to find out how
  353. * much data expansion they will see with a given suite.
  354. *
  355. * "enc" is the name used in RFC9180 for the encapsulated
  356. * public value of the sender, who calls OSSL_HPKE_seal(),
  357. * that is sent to the recipient, who calls OSSL_HPKE_open().
  358. *
  359. * @param suite is the suite to be used
  360. * @param enclen points to what will be enc length
  361. * @param clearlen is the length of plaintext
  362. * @param cipherlen points to what will be ciphertext length (including tag)
  363. * @return 1 for success, 0 otherwise
  364. */
  365. static int hpke_expansion(OSSL_HPKE_SUITE suite,
  366. size_t *enclen,
  367. size_t clearlen,
  368. size_t *cipherlen)
  369. {
  370. const OSSL_HPKE_AEAD_INFO *aead_info = NULL;
  371. const OSSL_HPKE_KEM_INFO *kem_info = NULL;
  372. if (cipherlen == NULL || enclen == NULL) {
  373. ERR_raise(ERR_LIB_CRYPTO, ERR_R_INTERNAL_ERROR);
  374. return 0;
  375. }
  376. if (hpke_suite_check(suite, &kem_info, NULL, &aead_info) != 1) {
  377. ERR_raise(ERR_LIB_CRYPTO, ERR_R_PASSED_INVALID_ARGUMENT);
  378. return 0;
  379. }
  380. *cipherlen = clearlen + aead_info->taglen;
  381. *enclen = kem_info->Nenc;
  382. return 1;
  383. }
  384. /*
  385. * @brief expand and XOR the 64-bit unsigned seq with (nonce) buffer
  386. * @param ctx is the HPKE context
  387. * @param buf is the buffer for the XOR'd seq and nonce
  388. * @param blen is the size of buf
  389. * @return 0 for error, otherwise blen
  390. */
  391. static size_t hpke_seqnonce2buf(OSSL_HPKE_CTX *ctx,
  392. unsigned char *buf, size_t blen)
  393. {
  394. size_t i;
  395. uint64_t seq_copy;
  396. if (ctx == NULL || blen < sizeof(seq_copy) || blen != ctx->noncelen)
  397. return 0;
  398. seq_copy = ctx->seq;
  399. memset(buf, 0, blen);
  400. for (i = 0; i < sizeof(seq_copy); i++) {
  401. buf[blen - i - 1] = seq_copy & 0xff;
  402. seq_copy >>= 8;
  403. }
  404. for (i = 0; i < blen; i++)
  405. buf[i] ^= ctx->nonce[i];
  406. return blen;
  407. }
  408. /*
  409. * @brief call the underlying KEM to encap
  410. * @param ctx is the OSSL_HPKE_CTX
  411. * @param enc is a buffer for the sender's ephemeral public value
  412. * @param enclen is the size of enc on input, number of octets used on output
  413. * @param pub is the recipient's public value
  414. * @param publen is the length of pub
  415. * @return 1 for success, 0 for error
  416. */
  417. static int hpke_encap(OSSL_HPKE_CTX *ctx, unsigned char *enc, size_t *enclen,
  418. const unsigned char *pub, size_t publen)
  419. {
  420. int erv = 0;
  421. OSSL_PARAM params[3], *p = params;
  422. size_t lsslen = 0;
  423. EVP_PKEY_CTX *pctx = NULL;
  424. EVP_PKEY *pkR = NULL;
  425. const OSSL_HPKE_KEM_INFO *kem_info = NULL;
  426. if (ctx == NULL || enc == NULL || enclen == NULL || *enclen == 0
  427. || pub == NULL || publen == 0) {
  428. ERR_raise(ERR_LIB_CRYPTO, ERR_R_INTERNAL_ERROR);
  429. return 0;
  430. }
  431. if (ctx->shared_secret != NULL) {
  432. /* only run the KEM once per OSSL_HPKE_CTX */
  433. ERR_raise(ERR_LIB_CRYPTO, ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED);
  434. return 0;
  435. }
  436. kem_info = ossl_HPKE_KEM_INFO_find_id(ctx->suite.kem_id);
  437. if (kem_info == NULL) {
  438. ERR_raise(ERR_LIB_CRYPTO, ERR_R_INTERNAL_ERROR);
  439. return 0;
  440. }
  441. if (hpke_kem_id_nist_curve(ctx->suite.kem_id) == 1) {
  442. pkR = evp_pkey_new_raw_nist_public_key(ctx->libctx, ctx->propq,
  443. kem_info->groupname,
  444. pub, publen);
  445. } else {
  446. pkR = EVP_PKEY_new_raw_public_key_ex(ctx->libctx,
  447. kem_info->keytype,
  448. ctx->propq, pub, publen);
  449. }
  450. if (pkR == NULL) {
  451. ERR_raise(ERR_LIB_CRYPTO, ERR_R_INTERNAL_ERROR);
  452. goto err;
  453. }
  454. pctx = EVP_PKEY_CTX_new_from_pkey(ctx->libctx, pkR, ctx->propq);
  455. if (pctx == NULL) {
  456. ERR_raise(ERR_LIB_CRYPTO, ERR_R_INTERNAL_ERROR);
  457. goto err;
  458. }
  459. *p++ = OSSL_PARAM_construct_utf8_string(OSSL_KEM_PARAM_OPERATION,
  460. OSSL_KEM_PARAM_OPERATION_DHKEM,
  461. 0);
  462. if (ctx->ikme != NULL) {
  463. *p++ = OSSL_PARAM_construct_octet_string(OSSL_KEM_PARAM_IKME,
  464. ctx->ikme, ctx->ikmelen);
  465. }
  466. *p = OSSL_PARAM_construct_end();
  467. if (ctx->mode == OSSL_HPKE_MODE_AUTH
  468. || ctx->mode == OSSL_HPKE_MODE_PSKAUTH) {
  469. if (EVP_PKEY_auth_encapsulate_init(pctx, ctx->authpriv,
  470. params) != 1) {
  471. ERR_raise(ERR_LIB_CRYPTO, ERR_R_INTERNAL_ERROR);
  472. goto err;
  473. }
  474. } else {
  475. if (EVP_PKEY_encapsulate_init(pctx, params) != 1) {
  476. ERR_raise(ERR_LIB_CRYPTO, ERR_R_INTERNAL_ERROR);
  477. goto err;
  478. }
  479. }
  480. if (EVP_PKEY_encapsulate(pctx, NULL, enclen, NULL, &lsslen) != 1) {
  481. ERR_raise(ERR_LIB_CRYPTO, ERR_R_INTERNAL_ERROR);
  482. goto err;
  483. }
  484. ctx->shared_secret = OPENSSL_malloc(lsslen);
  485. if (ctx->shared_secret == NULL)
  486. goto err;
  487. ctx->shared_secretlen = lsslen;
  488. if (EVP_PKEY_encapsulate(pctx, enc, enclen, ctx->shared_secret,
  489. &ctx->shared_secretlen) != 1) {
  490. ctx->shared_secretlen = 0;
  491. OPENSSL_free(ctx->shared_secret);
  492. ctx->shared_secret = NULL;
  493. ERR_raise(ERR_LIB_CRYPTO, ERR_R_INTERNAL_ERROR);
  494. goto err;
  495. }
  496. erv = 1;
  497. err:
  498. EVP_PKEY_CTX_free(pctx);
  499. EVP_PKEY_free(pkR);
  500. return erv;
  501. }
  502. /*
  503. * @brief call the underlying KEM to decap
  504. * @param ctx is the OSSL_HPKE_CTX
  505. * @param enc is a buffer for the sender's ephemeral public value
  506. * @param enclen is the length of enc
  507. * @param priv is the recipient's private value
  508. * @return 1 for success, 0 for error
  509. */
  510. static int hpke_decap(OSSL_HPKE_CTX *ctx,
  511. const unsigned char *enc, size_t enclen,
  512. EVP_PKEY *priv)
  513. {
  514. int erv = 0;
  515. EVP_PKEY_CTX *pctx = NULL;
  516. EVP_PKEY *spub = NULL;
  517. OSSL_PARAM params[2], *p = params;
  518. size_t lsslen = 0;
  519. if (ctx == NULL || enc == NULL || enclen == 0 || priv == NULL) {
  520. ERR_raise(ERR_LIB_CRYPTO, ERR_R_INTERNAL_ERROR);
  521. return 0;
  522. }
  523. if (ctx->shared_secret != NULL) {
  524. /* only run the KEM once per OSSL_HPKE_CTX */
  525. ERR_raise(ERR_LIB_CRYPTO, ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED);
  526. return 0;
  527. }
  528. pctx = EVP_PKEY_CTX_new_from_pkey(ctx->libctx, priv, ctx->propq);
  529. if (pctx == NULL) {
  530. ERR_raise(ERR_LIB_CRYPTO, ERR_R_INTERNAL_ERROR);
  531. goto err;
  532. }
  533. *p++ = OSSL_PARAM_construct_utf8_string(OSSL_KEM_PARAM_OPERATION,
  534. OSSL_KEM_PARAM_OPERATION_DHKEM,
  535. 0);
  536. *p = OSSL_PARAM_construct_end();
  537. if (ctx->mode == OSSL_HPKE_MODE_AUTH
  538. || ctx->mode == OSSL_HPKE_MODE_PSKAUTH) {
  539. const OSSL_HPKE_KEM_INFO *kem_info = NULL;
  540. kem_info = ossl_HPKE_KEM_INFO_find_id(ctx->suite.kem_id);
  541. if (kem_info == NULL) {
  542. ERR_raise(ERR_LIB_CRYPTO, ERR_R_INTERNAL_ERROR);
  543. goto err;
  544. }
  545. if (hpke_kem_id_nist_curve(ctx->suite.kem_id) == 1) {
  546. spub = evp_pkey_new_raw_nist_public_key(ctx->libctx, ctx->propq,
  547. kem_info->groupname,
  548. ctx->authpub,
  549. ctx->authpublen);
  550. } else {
  551. spub = EVP_PKEY_new_raw_public_key_ex(ctx->libctx,
  552. kem_info->keytype,
  553. ctx->propq,
  554. ctx->authpub,
  555. ctx->authpublen);
  556. }
  557. if (spub == NULL) {
  558. ERR_raise(ERR_LIB_CRYPTO, ERR_R_INTERNAL_ERROR);
  559. goto err;
  560. }
  561. if (EVP_PKEY_auth_decapsulate_init(pctx, spub, params) != 1) {
  562. ERR_raise(ERR_LIB_CRYPTO, ERR_R_INTERNAL_ERROR);
  563. goto err;
  564. }
  565. } else {
  566. if (EVP_PKEY_decapsulate_init(pctx, params) != 1) {
  567. ERR_raise(ERR_LIB_CRYPTO, ERR_R_INTERNAL_ERROR);
  568. goto err;
  569. }
  570. }
  571. if (EVP_PKEY_decapsulate(pctx, NULL, &lsslen, enc, enclen) != 1) {
  572. ERR_raise(ERR_LIB_CRYPTO, ERR_R_INTERNAL_ERROR);
  573. goto err;
  574. }
  575. ctx->shared_secret = OPENSSL_malloc(lsslen);
  576. if (ctx->shared_secret == NULL)
  577. goto err;
  578. if (EVP_PKEY_decapsulate(pctx, ctx->shared_secret, &lsslen,
  579. enc, enclen) != 1) {
  580. ERR_raise(ERR_LIB_CRYPTO, ERR_R_INTERNAL_ERROR);
  581. goto err;
  582. }
  583. ctx->shared_secretlen = lsslen;
  584. erv = 1;
  585. err:
  586. EVP_PKEY_CTX_free(pctx);
  587. EVP_PKEY_free(spub);
  588. if (erv == 0) {
  589. OPENSSL_free(ctx->shared_secret);
  590. ctx->shared_secret = NULL;
  591. ctx->shared_secretlen = 0;
  592. }
  593. return erv;
  594. }
  595. /*
  596. * @brief do "middle" of HPKE, between KEM and AEAD
  597. * @param ctx is the OSSL_HPKE_CTX
  598. * @param info is a buffer for the added binding information
  599. * @param infolen is the length of info
  600. * @return 0 for error, 1 for success
  601. *
  602. * This does all the HPKE extracts and expands as defined in RFC9180
  603. * section 5.1, (badly termed there as a "key schedule") and sets the
  604. * ctx fields for the shared_secret, nonce, key and exporter_secret
  605. */
  606. static int hpke_do_middle(OSSL_HPKE_CTX *ctx,
  607. const unsigned char *info, size_t infolen)
  608. {
  609. int erv = 0;
  610. size_t ks_contextlen = OSSL_HPKE_MAXSIZE;
  611. unsigned char ks_context[OSSL_HPKE_MAXSIZE];
  612. size_t halflen = 0;
  613. size_t pskidlen = 0;
  614. size_t psk_hashlen = OSSL_HPKE_MAXSIZE;
  615. unsigned char psk_hash[OSSL_HPKE_MAXSIZE];
  616. const OSSL_HPKE_AEAD_INFO *aead_info = NULL;
  617. const OSSL_HPKE_KDF_INFO *kdf_info = NULL;
  618. size_t secretlen = OSSL_HPKE_MAXSIZE;
  619. unsigned char secret[OSSL_HPKE_MAXSIZE];
  620. EVP_KDF_CTX *kctx = NULL;
  621. unsigned char suitebuf[6];
  622. const char *mdname = NULL;
  623. /* only let this be done once */
  624. if (ctx->exportersec != NULL) {
  625. ERR_raise(ERR_LIB_CRYPTO, ERR_R_INTERNAL_ERROR);
  626. return 0;
  627. }
  628. if (ossl_HPKE_KEM_INFO_find_id(ctx->suite.kem_id) == NULL) {
  629. ERR_raise(ERR_LIB_CRYPTO, ERR_R_INTERNAL_ERROR);
  630. return 0;
  631. }
  632. aead_info = ossl_HPKE_AEAD_INFO_find_id(ctx->suite.aead_id);
  633. if (aead_info == NULL) {
  634. ERR_raise(ERR_LIB_CRYPTO, ERR_R_INTERNAL_ERROR);
  635. return 0;
  636. }
  637. kdf_info = ossl_HPKE_KDF_INFO_find_id(ctx->suite.kdf_id);
  638. if (kdf_info == NULL) {
  639. ERR_raise(ERR_LIB_CRYPTO, ERR_R_INTERNAL_ERROR);
  640. return 0;
  641. }
  642. mdname = kdf_info->mdname;
  643. /* create key schedule context */
  644. memset(ks_context, 0, sizeof(ks_context));
  645. ks_context[0] = (unsigned char)(ctx->mode % 256);
  646. ks_contextlen--; /* remaining space */
  647. halflen = kdf_info->Nh;
  648. if ((2 * halflen) > ks_contextlen) {
  649. ERR_raise(ERR_LIB_CRYPTO, ERR_R_INTERNAL_ERROR);
  650. return 0;
  651. }
  652. /* check a psk was set if in that mode */
  653. if (ctx->mode == OSSL_HPKE_MODE_PSK
  654. || ctx->mode == OSSL_HPKE_MODE_PSKAUTH) {
  655. if (ctx->psk == NULL || ctx->psklen == 0 || ctx->pskid == NULL) {
  656. ERR_raise(ERR_LIB_CRYPTO, ERR_R_INTERNAL_ERROR);
  657. return 0;
  658. }
  659. }
  660. kctx = ossl_kdf_ctx_create("HKDF", mdname, ctx->libctx, ctx->propq);
  661. if (kctx == NULL) {
  662. ERR_raise(ERR_LIB_CRYPTO, ERR_R_INTERNAL_ERROR);
  663. return 0;
  664. }
  665. pskidlen = (ctx->psk == NULL ? 0 : strlen(ctx->pskid));
  666. /* full suite details as per RFC9180 sec 5.1 */
  667. suitebuf[0] = ctx->suite.kem_id / 256;
  668. suitebuf[1] = ctx->suite.kem_id % 256;
  669. suitebuf[2] = ctx->suite.kdf_id / 256;
  670. suitebuf[3] = ctx->suite.kdf_id % 256;
  671. suitebuf[4] = ctx->suite.aead_id / 256;
  672. suitebuf[5] = ctx->suite.aead_id % 256;
  673. if (ossl_hpke_labeled_extract(kctx, ks_context + 1, halflen,
  674. NULL, 0, OSSL_HPKE_SEC51LABEL,
  675. suitebuf, sizeof(suitebuf),
  676. OSSL_HPKE_PSKIDHASH_LABEL,
  677. (unsigned char *)ctx->pskid, pskidlen) != 1) {
  678. ERR_raise(ERR_LIB_CRYPTO, ERR_R_INTERNAL_ERROR);
  679. goto err;
  680. }
  681. if (ossl_hpke_labeled_extract(kctx, ks_context + 1 + halflen, halflen,
  682. NULL, 0, OSSL_HPKE_SEC51LABEL,
  683. suitebuf, sizeof(suitebuf),
  684. OSSL_HPKE_INFOHASH_LABEL,
  685. (unsigned char *)info, infolen) != 1) {
  686. ERR_raise(ERR_LIB_CRYPTO, ERR_R_INTERNAL_ERROR);
  687. goto err;
  688. }
  689. ks_contextlen = 1 + 2 * halflen;
  690. /* Extract and Expand variously... */
  691. psk_hashlen = halflen;
  692. if (ossl_hpke_labeled_extract(kctx, psk_hash, psk_hashlen,
  693. NULL, 0, OSSL_HPKE_SEC51LABEL,
  694. suitebuf, sizeof(suitebuf),
  695. OSSL_HPKE_PSK_HASH_LABEL,
  696. ctx->psk, ctx->psklen) != 1) {
  697. ERR_raise(ERR_LIB_CRYPTO, ERR_R_INTERNAL_ERROR);
  698. goto err;
  699. }
  700. secretlen = kdf_info->Nh;
  701. if (secretlen > OSSL_HPKE_MAXSIZE) {
  702. ERR_raise(ERR_LIB_CRYPTO, ERR_R_INTERNAL_ERROR);
  703. goto err;
  704. }
  705. if (ossl_hpke_labeled_extract(kctx, secret, secretlen,
  706. ctx->shared_secret, ctx->shared_secretlen,
  707. OSSL_HPKE_SEC51LABEL,
  708. suitebuf, sizeof(suitebuf),
  709. OSSL_HPKE_SECRET_LABEL,
  710. ctx->psk, ctx->psklen) != 1) {
  711. ERR_raise(ERR_LIB_CRYPTO, ERR_R_INTERNAL_ERROR);
  712. goto err;
  713. }
  714. if (ctx->suite.aead_id != OSSL_HPKE_AEAD_ID_EXPORTONLY) {
  715. /* we only need nonce/key for non export AEADs */
  716. ctx->noncelen = aead_info->Nn;
  717. ctx->nonce = OPENSSL_malloc(ctx->noncelen);
  718. if (ctx->nonce == NULL)
  719. goto err;
  720. if (ossl_hpke_labeled_expand(kctx, ctx->nonce, ctx->noncelen,
  721. secret, secretlen, OSSL_HPKE_SEC51LABEL,
  722. suitebuf, sizeof(suitebuf),
  723. OSSL_HPKE_NONCE_LABEL,
  724. ks_context, ks_contextlen) != 1) {
  725. ERR_raise(ERR_LIB_CRYPTO, ERR_R_INTERNAL_ERROR);
  726. goto err;
  727. }
  728. ctx->keylen = aead_info->Nk;
  729. ctx->key = OPENSSL_malloc(ctx->keylen);
  730. if (ctx->key == NULL)
  731. goto err;
  732. if (ossl_hpke_labeled_expand(kctx, ctx->key, ctx->keylen,
  733. secret, secretlen, OSSL_HPKE_SEC51LABEL,
  734. suitebuf, sizeof(suitebuf),
  735. OSSL_HPKE_KEY_LABEL,
  736. ks_context, ks_contextlen) != 1) {
  737. ERR_raise(ERR_LIB_CRYPTO, ERR_R_INTERNAL_ERROR);
  738. goto err;
  739. }
  740. }
  741. ctx->exporterseclen = kdf_info->Nh;
  742. ctx->exportersec = OPENSSL_malloc(ctx->exporterseclen);
  743. if (ctx->exportersec == NULL)
  744. goto err;
  745. if (ossl_hpke_labeled_expand(kctx, ctx->exportersec, ctx->exporterseclen,
  746. secret, secretlen, OSSL_HPKE_SEC51LABEL,
  747. suitebuf, sizeof(suitebuf),
  748. OSSL_HPKE_EXP_LABEL,
  749. ks_context, ks_contextlen) != 1) {
  750. ERR_raise(ERR_LIB_CRYPTO, ERR_R_INTERNAL_ERROR);
  751. goto err;
  752. }
  753. erv = 1;
  754. err:
  755. OPENSSL_cleanse(ks_context, OSSL_HPKE_MAXSIZE);
  756. OPENSSL_cleanse(psk_hash, OSSL_HPKE_MAXSIZE);
  757. OPENSSL_cleanse(secret, OSSL_HPKE_MAXSIZE);
  758. EVP_KDF_CTX_free(kctx);
  759. return erv;
  760. }
  761. /*
  762. * externally visible functions from below here, API documentation is
  763. * in doc/man3/OSSL_HPKE_CTX_new.pod to avoid duplication
  764. */
  765. OSSL_HPKE_CTX *OSSL_HPKE_CTX_new(int mode, OSSL_HPKE_SUITE suite, int role,
  766. OSSL_LIB_CTX *libctx, const char *propq)
  767. {
  768. OSSL_HPKE_CTX *ctx = NULL;
  769. const OSSL_HPKE_KEM_INFO *kem_info;
  770. const OSSL_HPKE_KDF_INFO *kdf_info;
  771. const OSSL_HPKE_AEAD_INFO *aead_info;
  772. if (hpke_mode_check(mode) != 1) {
  773. ERR_raise(ERR_LIB_CRYPTO, ERR_R_PASSED_INVALID_ARGUMENT);
  774. return NULL;
  775. }
  776. if (hpke_suite_check(suite, &kem_info, &kdf_info, &aead_info) != 1) {
  777. ERR_raise(ERR_LIB_CRYPTO, ERR_R_PASSED_INVALID_ARGUMENT);
  778. return NULL;
  779. }
  780. if (role != OSSL_HPKE_ROLE_SENDER && role != OSSL_HPKE_ROLE_RECEIVER) {
  781. ERR_raise(ERR_LIB_CRYPTO, ERR_R_PASSED_INVALID_ARGUMENT);
  782. return 0;
  783. }
  784. ctx = OPENSSL_zalloc(sizeof(*ctx));
  785. if (ctx == NULL)
  786. return NULL;
  787. ctx->libctx = libctx;
  788. if (propq != NULL) {
  789. ctx->propq = OPENSSL_strdup(propq);
  790. if (ctx->propq == NULL)
  791. goto err;
  792. }
  793. if (suite.aead_id != OSSL_HPKE_AEAD_ID_EXPORTONLY) {
  794. ctx->aead_ciph = EVP_CIPHER_fetch(libctx, aead_info->name, propq);
  795. if (ctx->aead_ciph == NULL) {
  796. ERR_raise(ERR_LIB_CRYPTO, ERR_R_FETCH_FAILED);
  797. goto err;
  798. }
  799. }
  800. ctx->role = role;
  801. ctx->mode = mode;
  802. ctx->suite = suite;
  803. ctx->kem_info = kem_info;
  804. ctx->kdf_info = kdf_info;
  805. ctx->aead_info = aead_info;
  806. return ctx;
  807. err:
  808. EVP_CIPHER_free(ctx->aead_ciph);
  809. OPENSSL_free(ctx);
  810. return NULL;
  811. }
  812. void OSSL_HPKE_CTX_free(OSSL_HPKE_CTX *ctx)
  813. {
  814. if (ctx == NULL)
  815. return;
  816. EVP_CIPHER_free(ctx->aead_ciph);
  817. OPENSSL_free(ctx->propq);
  818. OPENSSL_clear_free(ctx->exportersec, ctx->exporterseclen);
  819. OPENSSL_free(ctx->pskid);
  820. OPENSSL_clear_free(ctx->psk, ctx->psklen);
  821. OPENSSL_clear_free(ctx->key, ctx->keylen);
  822. OPENSSL_clear_free(ctx->nonce, ctx->noncelen);
  823. OPENSSL_clear_free(ctx->shared_secret, ctx->shared_secretlen);
  824. OPENSSL_clear_free(ctx->ikme, ctx->ikmelen);
  825. EVP_PKEY_free(ctx->authpriv);
  826. OPENSSL_free(ctx->authpub);
  827. OPENSSL_free(ctx);
  828. return;
  829. }
  830. int OSSL_HPKE_CTX_set1_psk(OSSL_HPKE_CTX *ctx,
  831. const char *pskid,
  832. const unsigned char *psk, size_t psklen)
  833. {
  834. if (ctx == NULL || pskid == NULL || psk == NULL || psklen == 0) {
  835. ERR_raise(ERR_LIB_CRYPTO, ERR_R_PASSED_NULL_PARAMETER);
  836. return 0;
  837. }
  838. if (psklen > OSSL_HPKE_MAX_PARMLEN) {
  839. ERR_raise(ERR_LIB_CRYPTO, ERR_R_PASSED_INVALID_ARGUMENT);
  840. return 0;
  841. }
  842. if (strlen(pskid) > OSSL_HPKE_MAX_PARMLEN) {
  843. ERR_raise(ERR_LIB_CRYPTO, ERR_R_PASSED_INVALID_ARGUMENT);
  844. return 0;
  845. }
  846. if (ctx->mode != OSSL_HPKE_MODE_PSK
  847. && ctx->mode != OSSL_HPKE_MODE_PSKAUTH) {
  848. ERR_raise(ERR_LIB_CRYPTO, ERR_R_PASSED_INVALID_ARGUMENT);
  849. return 0;
  850. }
  851. /* free previous values if any */
  852. OPENSSL_clear_free(ctx->psk, ctx->psklen);
  853. ctx->psk = OPENSSL_memdup(psk, psklen);
  854. if (ctx->psk == NULL)
  855. return 0;
  856. ctx->psklen = psklen;
  857. OPENSSL_free(ctx->pskid);
  858. ctx->pskid = OPENSSL_strdup(pskid);
  859. if (ctx->pskid == NULL) {
  860. OPENSSL_clear_free(ctx->psk, ctx->psklen);
  861. ctx->psk = NULL;
  862. ctx->psklen = 0;
  863. return 0;
  864. }
  865. return 1;
  866. }
  867. int OSSL_HPKE_CTX_set1_ikme(OSSL_HPKE_CTX *ctx,
  868. const unsigned char *ikme, size_t ikmelen)
  869. {
  870. if (ctx == NULL || ikme == NULL) {
  871. ERR_raise(ERR_LIB_CRYPTO, ERR_R_PASSED_NULL_PARAMETER);
  872. return 0;
  873. }
  874. if (ikmelen == 0 || ikmelen > OSSL_HPKE_MAX_PARMLEN) {
  875. ERR_raise(ERR_LIB_CRYPTO, ERR_R_PASSED_INVALID_ARGUMENT);
  876. return 0;
  877. }
  878. if (ctx->role != OSSL_HPKE_ROLE_SENDER) {
  879. ERR_raise(ERR_LIB_CRYPTO, ERR_R_PASSED_INVALID_ARGUMENT);
  880. return 0;
  881. }
  882. OPENSSL_clear_free(ctx->ikme, ctx->ikmelen);
  883. ctx->ikme = OPENSSL_memdup(ikme, ikmelen);
  884. if (ctx->ikme == NULL)
  885. return 0;
  886. ctx->ikmelen = ikmelen;
  887. return 1;
  888. }
  889. int OSSL_HPKE_CTX_set1_authpriv(OSSL_HPKE_CTX *ctx, EVP_PKEY *priv)
  890. {
  891. if (ctx == NULL || priv == NULL) {
  892. ERR_raise(ERR_LIB_CRYPTO, ERR_R_PASSED_NULL_PARAMETER);
  893. return 0;
  894. }
  895. if (ctx->mode != OSSL_HPKE_MODE_AUTH
  896. && ctx->mode != OSSL_HPKE_MODE_PSKAUTH) {
  897. ERR_raise(ERR_LIB_CRYPTO, ERR_R_PASSED_INVALID_ARGUMENT);
  898. return 0;
  899. }
  900. if (ctx->role != OSSL_HPKE_ROLE_SENDER) {
  901. ERR_raise(ERR_LIB_CRYPTO, ERR_R_PASSED_INVALID_ARGUMENT);
  902. return 0;
  903. }
  904. EVP_PKEY_free(ctx->authpriv);
  905. ctx->authpriv = EVP_PKEY_dup(priv);
  906. if (ctx->authpriv == NULL)
  907. return 0;
  908. return 1;
  909. }
  910. int OSSL_HPKE_CTX_set1_authpub(OSSL_HPKE_CTX *ctx,
  911. const unsigned char *pub, size_t publen)
  912. {
  913. int erv = 0;
  914. EVP_PKEY *pubp = NULL;
  915. unsigned char *lpub = NULL;
  916. size_t lpublen = 0;
  917. const OSSL_HPKE_KEM_INFO *kem_info = NULL;
  918. if (ctx == NULL || pub == NULL || publen == 0) {
  919. ERR_raise(ERR_LIB_CRYPTO, ERR_R_PASSED_NULL_PARAMETER);
  920. return 0;
  921. }
  922. if (ctx->mode != OSSL_HPKE_MODE_AUTH
  923. && ctx->mode != OSSL_HPKE_MODE_PSKAUTH) {
  924. ERR_raise(ERR_LIB_CRYPTO, ERR_R_PASSED_INVALID_ARGUMENT);
  925. return 0;
  926. }
  927. if (ctx->role != OSSL_HPKE_ROLE_RECEIVER) {
  928. ERR_raise(ERR_LIB_CRYPTO, ERR_R_PASSED_INVALID_ARGUMENT);
  929. return 0;
  930. }
  931. /* check the value seems like a good public key for this kem */
  932. kem_info = ossl_HPKE_KEM_INFO_find_id(ctx->suite.kem_id);
  933. if (kem_info == NULL)
  934. return 0;
  935. if (hpke_kem_id_nist_curve(ctx->suite.kem_id) == 1) {
  936. pubp = evp_pkey_new_raw_nist_public_key(ctx->libctx, ctx->propq,
  937. kem_info->groupname,
  938. pub, publen);
  939. } else {
  940. pubp = EVP_PKEY_new_raw_public_key_ex(ctx->libctx,
  941. kem_info->keytype,
  942. ctx->propq,
  943. pub, publen);
  944. }
  945. if (pubp == NULL) {
  946. /* can happen based on external input - buffer value may be garbage */
  947. ERR_raise(ERR_LIB_CRYPTO, ERR_R_PASSED_INVALID_ARGUMENT);
  948. goto err;
  949. }
  950. /*
  951. * extract out the public key in encoded form so we
  952. * should be fine even if given compressed form
  953. */
  954. lpub = OPENSSL_malloc(OSSL_HPKE_MAXSIZE);
  955. if (lpub == NULL)
  956. goto err;
  957. if (EVP_PKEY_get_octet_string_param(pubp,
  958. OSSL_PKEY_PARAM_ENCODED_PUBLIC_KEY,
  959. lpub, OSSL_HPKE_MAXSIZE, &lpublen)
  960. != 1) {
  961. OPENSSL_free(lpub);
  962. ERR_raise(ERR_LIB_CRYPTO, ERR_R_INTERNAL_ERROR);
  963. goto err;
  964. }
  965. /* free up old value */
  966. OPENSSL_free(ctx->authpub);
  967. ctx->authpub = lpub;
  968. ctx->authpublen = lpublen;
  969. erv = 1;
  970. err:
  971. EVP_PKEY_free(pubp);
  972. return erv;
  973. }
  974. int OSSL_HPKE_CTX_get_seq(OSSL_HPKE_CTX *ctx, uint64_t *seq)
  975. {
  976. if (ctx == NULL || seq == NULL) {
  977. ERR_raise(ERR_LIB_CRYPTO, ERR_R_PASSED_NULL_PARAMETER);
  978. return 0;
  979. }
  980. *seq = ctx->seq;
  981. return 1;
  982. }
  983. int OSSL_HPKE_CTX_set_seq(OSSL_HPKE_CTX *ctx, uint64_t seq)
  984. {
  985. if (ctx == NULL) {
  986. ERR_raise(ERR_LIB_CRYPTO, ERR_R_PASSED_NULL_PARAMETER);
  987. return 0;
  988. }
  989. /*
  990. * We disallow senders from doing this as it's dangerous
  991. * Receivers are ok to use this, as no harm should ensue
  992. * if they go wrong.
  993. */
  994. if (ctx->role == OSSL_HPKE_ROLE_SENDER) {
  995. ERR_raise(ERR_LIB_CRYPTO, ERR_R_PASSED_INVALID_ARGUMENT);
  996. return 0;
  997. }
  998. ctx->seq = seq;
  999. return 1;
  1000. }
  1001. int OSSL_HPKE_encap(OSSL_HPKE_CTX *ctx,
  1002. unsigned char *enc, size_t *enclen,
  1003. const unsigned char *pub, size_t publen,
  1004. const unsigned char *info, size_t infolen)
  1005. {
  1006. int erv = 1;
  1007. if (ctx == NULL || enc == NULL || enclen == NULL || *enclen == 0
  1008. || pub == NULL || publen == 0) {
  1009. ERR_raise(ERR_LIB_CRYPTO, ERR_R_PASSED_NULL_PARAMETER);
  1010. return 0;
  1011. }
  1012. if (ctx->role != OSSL_HPKE_ROLE_SENDER) {
  1013. ERR_raise(ERR_LIB_CRYPTO, ERR_R_PASSED_INVALID_ARGUMENT);
  1014. return 0;
  1015. }
  1016. if (infolen > OSSL_HPKE_MAX_INFOLEN) {
  1017. ERR_raise(ERR_LIB_CRYPTO, ERR_R_PASSED_INVALID_ARGUMENT);
  1018. return 0;
  1019. }
  1020. if (ctx->shared_secret != NULL) {
  1021. /* only allow one encap per OSSL_HPKE_CTX */
  1022. ERR_raise(ERR_LIB_CRYPTO, ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED);
  1023. return 0;
  1024. }
  1025. if (hpke_encap(ctx, enc, enclen, pub, publen) != 1) {
  1026. ERR_raise(ERR_LIB_CRYPTO, ERR_R_INTERNAL_ERROR);
  1027. return 0;
  1028. }
  1029. /*
  1030. * note that the info is not part of the context as it
  1031. * only needs to be used once here so doesn't need to
  1032. * be stored
  1033. */
  1034. erv = hpke_do_middle(ctx, info, infolen);
  1035. return erv;
  1036. }
  1037. int OSSL_HPKE_decap(OSSL_HPKE_CTX *ctx,
  1038. const unsigned char *enc, size_t enclen,
  1039. EVP_PKEY *recippriv,
  1040. const unsigned char *info, size_t infolen)
  1041. {
  1042. int erv = 1;
  1043. if (ctx == NULL || enc == NULL || enclen == 0 || recippriv == NULL) {
  1044. ERR_raise(ERR_LIB_CRYPTO, ERR_R_PASSED_NULL_PARAMETER);
  1045. return 0;
  1046. }
  1047. if (ctx->role != OSSL_HPKE_ROLE_RECEIVER) {
  1048. ERR_raise(ERR_LIB_CRYPTO, ERR_R_PASSED_INVALID_ARGUMENT);
  1049. return 0;
  1050. }
  1051. if (infolen > OSSL_HPKE_MAX_INFOLEN) {
  1052. ERR_raise(ERR_LIB_CRYPTO, ERR_R_PASSED_INVALID_ARGUMENT);
  1053. return 0;
  1054. }
  1055. if (ctx->shared_secret != NULL) {
  1056. /* only allow one encap per OSSL_HPKE_CTX */
  1057. ERR_raise(ERR_LIB_CRYPTO, ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED);
  1058. return 0;
  1059. }
  1060. erv = hpke_decap(ctx, enc, enclen, recippriv);
  1061. if (erv != 1) {
  1062. ERR_raise(ERR_LIB_CRYPTO, ERR_R_INTERNAL_ERROR);
  1063. return 0;
  1064. }
  1065. /*
  1066. * note that the info is not part of the context as it
  1067. * only needs to be used once here so doesn't need to
  1068. * be stored
  1069. */
  1070. erv = hpke_do_middle(ctx, info, infolen);
  1071. return erv;
  1072. }
  1073. int OSSL_HPKE_seal(OSSL_HPKE_CTX *ctx,
  1074. unsigned char *ct, size_t *ctlen,
  1075. const unsigned char *aad, size_t aadlen,
  1076. const unsigned char *pt, size_t ptlen)
  1077. {
  1078. unsigned char seqbuf[OSSL_HPKE_MAX_NONCELEN];
  1079. size_t seqlen = 0;
  1080. if (ctx == NULL || ct == NULL || ctlen == NULL || *ctlen == 0
  1081. || pt == NULL || ptlen == 0) {
  1082. ERR_raise(ERR_LIB_CRYPTO, ERR_R_PASSED_NULL_PARAMETER);
  1083. return 0;
  1084. }
  1085. if (ctx->role != OSSL_HPKE_ROLE_SENDER) {
  1086. ERR_raise(ERR_LIB_CRYPTO, ERR_R_PASSED_INVALID_ARGUMENT);
  1087. return 0;
  1088. }
  1089. if ((ctx->seq + 1) == 0) { /* wrap around imminent !!! */
  1090. ERR_raise(ERR_LIB_CRYPTO, ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED);
  1091. return 0;
  1092. }
  1093. if (ctx->key == NULL || ctx->nonce == NULL) {
  1094. /* need to have done an encap first, info can be NULL */
  1095. ERR_raise(ERR_LIB_CRYPTO, ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED);
  1096. return 0;
  1097. }
  1098. seqlen = hpke_seqnonce2buf(ctx, seqbuf, sizeof(seqbuf));
  1099. if (seqlen == 0) {
  1100. ERR_raise(ERR_LIB_CRYPTO, ERR_R_INTERNAL_ERROR);
  1101. return 0;
  1102. }
  1103. if (hpke_aead_enc(ctx, seqbuf, aad, aadlen, pt, ptlen, ct, ctlen) != 1) {
  1104. ERR_raise(ERR_LIB_CRYPTO, ERR_R_INTERNAL_ERROR);
  1105. OPENSSL_cleanse(seqbuf, sizeof(seqbuf));
  1106. return 0;
  1107. } else {
  1108. ctx->seq++;
  1109. }
  1110. OPENSSL_cleanse(seqbuf, sizeof(seqbuf));
  1111. return 1;
  1112. }
  1113. int OSSL_HPKE_open(OSSL_HPKE_CTX *ctx,
  1114. unsigned char *pt, size_t *ptlen,
  1115. const unsigned char *aad, size_t aadlen,
  1116. const unsigned char *ct, size_t ctlen)
  1117. {
  1118. unsigned char seqbuf[OSSL_HPKE_MAX_NONCELEN];
  1119. size_t seqlen = 0;
  1120. if (ctx == NULL || pt == NULL || ptlen == NULL || *ptlen == 0
  1121. || ct == NULL || ctlen == 0) {
  1122. ERR_raise(ERR_LIB_CRYPTO, ERR_R_PASSED_NULL_PARAMETER);
  1123. return 0;
  1124. }
  1125. if (ctx->role != OSSL_HPKE_ROLE_RECEIVER) {
  1126. ERR_raise(ERR_LIB_CRYPTO, ERR_R_PASSED_INVALID_ARGUMENT);
  1127. return 0;
  1128. }
  1129. if ((ctx->seq + 1) == 0) { /* wrap around imminent !!! */
  1130. ERR_raise(ERR_LIB_CRYPTO, ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED);
  1131. return 0;
  1132. }
  1133. if (ctx->key == NULL || ctx->nonce == NULL) {
  1134. /* need to have done an encap first, info can be NULL */
  1135. ERR_raise(ERR_LIB_CRYPTO, ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED);
  1136. return 0;
  1137. }
  1138. seqlen = hpke_seqnonce2buf(ctx, seqbuf, sizeof(seqbuf));
  1139. if (seqlen == 0) {
  1140. ERR_raise(ERR_LIB_CRYPTO, ERR_R_INTERNAL_ERROR);
  1141. return 0;
  1142. }
  1143. if (hpke_aead_dec(ctx, seqbuf, aad, aadlen, ct, ctlen, pt, ptlen) != 1) {
  1144. ERR_raise(ERR_LIB_CRYPTO, ERR_R_INTERNAL_ERROR);
  1145. OPENSSL_cleanse(seqbuf, sizeof(seqbuf));
  1146. return 0;
  1147. }
  1148. ctx->seq++;
  1149. OPENSSL_cleanse(seqbuf, sizeof(seqbuf));
  1150. return 1;
  1151. }
  1152. int OSSL_HPKE_export(OSSL_HPKE_CTX *ctx,
  1153. unsigned char *secret, size_t secretlen,
  1154. const unsigned char *label, size_t labellen)
  1155. {
  1156. int erv = 0;
  1157. EVP_KDF_CTX *kctx = NULL;
  1158. unsigned char suitebuf[6];
  1159. const char *mdname = NULL;
  1160. const OSSL_HPKE_KDF_INFO *kdf_info = NULL;
  1161. if (ctx == NULL) {
  1162. ERR_raise(ERR_LIB_CRYPTO, ERR_R_PASSED_NULL_PARAMETER);
  1163. return 0;
  1164. }
  1165. if (labellen > OSSL_HPKE_MAX_PARMLEN) {
  1166. ERR_raise(ERR_LIB_CRYPTO, ERR_R_PASSED_INVALID_ARGUMENT);
  1167. return 0;
  1168. }
  1169. if (ctx->exportersec == NULL) {
  1170. ERR_raise(ERR_LIB_CRYPTO, ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED);
  1171. return 0;
  1172. }
  1173. kdf_info = ossl_HPKE_KDF_INFO_find_id(ctx->suite.kdf_id);
  1174. if (kdf_info == NULL) {
  1175. ERR_raise(ERR_LIB_CRYPTO, ERR_R_INTERNAL_ERROR);
  1176. return 0;
  1177. }
  1178. mdname = kdf_info->mdname;
  1179. kctx = ossl_kdf_ctx_create("HKDF", mdname, ctx->libctx, ctx->propq);
  1180. if (kctx == NULL) {
  1181. ERR_raise(ERR_LIB_CRYPTO, ERR_R_INTERNAL_ERROR);
  1182. return 0;
  1183. }
  1184. /* full suiteid as per RFC9180 sec 5.3 */
  1185. suitebuf[0] = ctx->suite.kem_id / 256;
  1186. suitebuf[1] = ctx->suite.kem_id % 256;
  1187. suitebuf[2] = ctx->suite.kdf_id / 256;
  1188. suitebuf[3] = ctx->suite.kdf_id % 256;
  1189. suitebuf[4] = ctx->suite.aead_id / 256;
  1190. suitebuf[5] = ctx->suite.aead_id % 256;
  1191. erv = ossl_hpke_labeled_expand(kctx, secret, secretlen,
  1192. ctx->exportersec, ctx->exporterseclen,
  1193. OSSL_HPKE_SEC51LABEL,
  1194. suitebuf, sizeof(suitebuf),
  1195. OSSL_HPKE_EXP_SEC_LABEL,
  1196. label, labellen);
  1197. EVP_KDF_CTX_free(kctx);
  1198. if (erv != 1)
  1199. ERR_raise(ERR_LIB_CRYPTO, ERR_R_INTERNAL_ERROR);
  1200. return erv;
  1201. }
  1202. int OSSL_HPKE_keygen(OSSL_HPKE_SUITE suite,
  1203. unsigned char *pub, size_t *publen, EVP_PKEY **priv,
  1204. const unsigned char *ikm, size_t ikmlen,
  1205. OSSL_LIB_CTX *libctx, const char *propq)
  1206. {
  1207. int erv = 0; /* Our error return value - 1 is success */
  1208. EVP_PKEY_CTX *pctx = NULL;
  1209. EVP_PKEY *skR = NULL;
  1210. const OSSL_HPKE_KEM_INFO *kem_info = NULL;
  1211. OSSL_PARAM params[3], *p = params;
  1212. if (pub == NULL || publen == NULL || *publen == 0 || priv == NULL) {
  1213. ERR_raise(ERR_LIB_CRYPTO, ERR_R_PASSED_NULL_PARAMETER);
  1214. return 0;
  1215. }
  1216. if (hpke_suite_check(suite, &kem_info, NULL, NULL) != 1) {
  1217. ERR_raise(ERR_LIB_CRYPTO, ERR_R_PASSED_INVALID_ARGUMENT);
  1218. return 0;
  1219. }
  1220. if ((ikmlen > 0 && ikm == NULL)
  1221. || (ikmlen == 0 && ikm != NULL)
  1222. || ikmlen > OSSL_HPKE_MAX_PARMLEN) {
  1223. ERR_raise(ERR_LIB_CRYPTO, ERR_R_PASSED_INVALID_ARGUMENT);
  1224. return 0;
  1225. }
  1226. if (hpke_kem_id_nist_curve(suite.kem_id) == 1) {
  1227. *p++ = OSSL_PARAM_construct_utf8_string(OSSL_PKEY_PARAM_GROUP_NAME,
  1228. (char *)kem_info->groupname, 0);
  1229. pctx = EVP_PKEY_CTX_new_from_name(libctx, "EC", propq);
  1230. } else {
  1231. pctx = EVP_PKEY_CTX_new_from_name(libctx, kem_info->keytype, propq);
  1232. }
  1233. if (pctx == NULL
  1234. || EVP_PKEY_keygen_init(pctx) <= 0) {
  1235. ERR_raise(ERR_LIB_CRYPTO, ERR_R_INTERNAL_ERROR);
  1236. goto err;
  1237. }
  1238. if (ikm != NULL)
  1239. *p++ = OSSL_PARAM_construct_octet_string(OSSL_PKEY_PARAM_DHKEM_IKM,
  1240. (char *)ikm, ikmlen);
  1241. *p = OSSL_PARAM_construct_end();
  1242. if (EVP_PKEY_CTX_set_params(pctx, params) <= 0) {
  1243. ERR_raise(ERR_LIB_CRYPTO, ERR_R_INTERNAL_ERROR);
  1244. goto err;
  1245. }
  1246. if (EVP_PKEY_generate(pctx, &skR) <= 0) {
  1247. ERR_raise(ERR_LIB_CRYPTO, ERR_R_INTERNAL_ERROR);
  1248. goto err;
  1249. }
  1250. EVP_PKEY_CTX_free(pctx);
  1251. pctx = NULL;
  1252. if (EVP_PKEY_get_octet_string_param(skR, OSSL_PKEY_PARAM_ENCODED_PUBLIC_KEY,
  1253. pub, *publen, publen) != 1) {
  1254. ERR_raise(ERR_LIB_CRYPTO, ERR_R_INTERNAL_ERROR);
  1255. goto err;
  1256. }
  1257. *priv = skR;
  1258. erv = 1;
  1259. err:
  1260. if (erv != 1)
  1261. EVP_PKEY_free(skR);
  1262. EVP_PKEY_CTX_free(pctx);
  1263. return erv;
  1264. }
  1265. int OSSL_HPKE_suite_check(OSSL_HPKE_SUITE suite)
  1266. {
  1267. return hpke_suite_check(suite, NULL, NULL, NULL);
  1268. }
  1269. int OSSL_HPKE_get_grease_value(const OSSL_HPKE_SUITE *suite_in,
  1270. OSSL_HPKE_SUITE *suite,
  1271. unsigned char *enc, size_t *enclen,
  1272. unsigned char *ct, size_t ctlen,
  1273. OSSL_LIB_CTX *libctx, const char *propq)
  1274. {
  1275. OSSL_HPKE_SUITE chosen;
  1276. size_t plen = 0;
  1277. const OSSL_HPKE_KEM_INFO *kem_info = NULL;
  1278. const OSSL_HPKE_AEAD_INFO *aead_info = NULL;
  1279. EVP_PKEY *fakepriv = NULL;
  1280. if (enc == NULL || enclen == 0
  1281. || ct == NULL || ctlen == 0 || suite == NULL) {
  1282. ERR_raise(ERR_LIB_CRYPTO, ERR_R_PASSED_NULL_PARAMETER);
  1283. return 0;
  1284. }
  1285. if (suite_in == NULL) {
  1286. /* choose a random suite */
  1287. if (hpke_random_suite(libctx, propq, &chosen) != 1) {
  1288. ERR_raise(ERR_LIB_CRYPTO, ERR_R_INTERNAL_ERROR);
  1289. goto err;
  1290. }
  1291. } else {
  1292. chosen = *suite_in;
  1293. }
  1294. if (hpke_suite_check(chosen, &kem_info, NULL, &aead_info) != 1) {
  1295. ERR_raise(ERR_LIB_CRYPTO, ERR_R_INTERNAL_ERROR);
  1296. goto err;
  1297. }
  1298. *suite = chosen;
  1299. /* make sure room for tag and one plaintext octet */
  1300. if (aead_info->taglen >= ctlen) {
  1301. ERR_raise(ERR_LIB_CRYPTO, ERR_R_INTERNAL_ERROR);
  1302. goto err;
  1303. }
  1304. /* publen */
  1305. plen = kem_info->Npk;
  1306. if (plen > *enclen) {
  1307. ERR_raise(ERR_LIB_CRYPTO, ERR_R_INTERNAL_ERROR);
  1308. goto err;
  1309. }
  1310. /*
  1311. * In order for our enc to look good for sure, we generate and then
  1312. * delete a real key for that curve - bit OTT but it ensures we do
  1313. * get the encoding right (e.g. 0x04 as 1st octet for NIST curves in
  1314. * uncompressed form) and that the value really does map to a point on
  1315. * the relevant curve.
  1316. */
  1317. if (OSSL_HPKE_keygen(chosen, enc, enclen, &fakepriv, NULL, 0,
  1318. libctx, propq) != 1) {
  1319. ERR_raise(ERR_LIB_CRYPTO, ERR_R_INTERNAL_ERROR);
  1320. goto err;
  1321. }
  1322. EVP_PKEY_free(fakepriv);
  1323. if (RAND_bytes_ex(libctx, ct, ctlen, 0) <= 0) {
  1324. ERR_raise(ERR_LIB_CRYPTO, ERR_R_INTERNAL_ERROR);
  1325. goto err;
  1326. }
  1327. return 1;
  1328. err:
  1329. return 0;
  1330. }
  1331. int OSSL_HPKE_str2suite(const char *str, OSSL_HPKE_SUITE *suite)
  1332. {
  1333. return ossl_hpke_str2suite(str, suite);
  1334. }
  1335. size_t OSSL_HPKE_get_ciphertext_size(OSSL_HPKE_SUITE suite, size_t clearlen)
  1336. {
  1337. size_t enclen = 0;
  1338. size_t cipherlen = 0;
  1339. if (hpke_expansion(suite, &enclen, clearlen, &cipherlen) != 1)
  1340. return 0;
  1341. return cipherlen;
  1342. }
  1343. size_t OSSL_HPKE_get_public_encap_size(OSSL_HPKE_SUITE suite)
  1344. {
  1345. size_t enclen = 0;
  1346. size_t cipherlen = 0;
  1347. size_t clearlen = 16;
  1348. if (hpke_expansion(suite, &enclen, clearlen, &cipherlen) != 1)
  1349. return 0;
  1350. return enclen;
  1351. }
  1352. size_t OSSL_HPKE_get_recommended_ikmelen(OSSL_HPKE_SUITE suite)
  1353. {
  1354. const OSSL_HPKE_KEM_INFO *kem_info = NULL;
  1355. if (hpke_suite_check(suite, &kem_info, NULL, NULL) != 1)
  1356. return 0;
  1357. if (kem_info == NULL)
  1358. return 0;
  1359. return kem_info->Nsk;
  1360. }