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