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