summaryrefslogtreecommitdiff
path: root/providers
diff options
context:
space:
mode:
authorStephen Farrell <stephen.farrell@cs.tcd.ie>2022-11-22 02:42:04 +0000
committerMatt Caswell <matt@openssl.org>2022-11-25 16:26:55 +0000
commitad062480f7490197b174edad8625ce40d74f6e68 (patch)
treef4ac43084558412509820b4d167b4c2906f5cfb2 /providers
parent0dbd3a81e46dd7ea9f7832307fdd0b2ac207a5bf (diff)
downloadopenssl-new-ad062480f7490197b174edad8625ce40d74f6e68.tar.gz
Implements Hybrid Public Key Encryption (HPKE) as per RFC9180.
This supports all the modes, suites and export mechanisms defined in RFC9180 and should be relatively easily extensible if/as new suites are added. The APIs are based on the pseudo-code from the RFC, e.g. OSS_HPKE_encap() roughly maps to SetupBaseS(). External APIs are defined in include/openssl/hpke.h and documented in doc/man3/OSSL_HPKE_CTX_new.pod. Tests (test/hpke_test.c) include verifying a number of the test vectors from the RFC as well as round-tripping for all the modes and suites. We have demonstrated interoperability with other HPKE implementations via a fork [1] that implements TLS Encrypted ClientHello (ECH) which uses HPKE. @slontis provided huge help in getting this done and this makes extensive use of the KEM handling code from his PR#19068. [1] https://github.com/sftcd/openssl/tree/ECH-draft-13c Reviewed-by: Tomas Mraz <tomas@openssl.org> Reviewed-by: Shane Lontis <shane.lontis@oracle.com> Reviewed-by: Matt Caswell <matt@openssl.org> (Merged from https://github.com/openssl/openssl/pull/17172)
Diffstat (limited to 'providers')
-rw-r--r--providers/common/include/prov/proverr.h2
-rw-r--r--providers/common/provider_err.c4
-rw-r--r--providers/implementations/kem/ec_kem.c125
-rw-r--r--providers/implementations/kem/eckem.h1
-rw-r--r--providers/implementations/kem/ecx_kem.c114
-rw-r--r--providers/implementations/kem/kem_util.c8
6 files changed, 109 insertions, 145 deletions
diff --git a/providers/common/include/prov/proverr.h b/providers/common/include/prov/proverr.h
index 5084af201e..8ad6cc048d 100644
--- a/providers/common/include/prov/proverr.h
+++ b/providers/common/include/prov/proverr.h
@@ -1,6 +1,6 @@
/*
* Generated by util/mkerr.pl DO NOT EDIT
- * Copyright 2020-2021 The OpenSSL Project Authors. All Rights Reserved.
+ * Copyright 2020-2022 The OpenSSL Project Authors. All Rights Reserved.
*
* Licensed under the Apache License 2.0 (the "License"). You may not use
* this file except in compliance with the License. You can obtain a copy
diff --git a/providers/common/provider_err.c b/providers/common/provider_err.c
index 344c122112..f6144072aa 100644
--- a/providers/common/provider_err.c
+++ b/providers/common/provider_err.c
@@ -1,6 +1,6 @@
/*
* Generated by util/mkerr.pl DO NOT EDIT
- * Copyright 1995-2021 The OpenSSL Project Authors. All Rights Reserved.
+ * Copyright 1995-2022 The OpenSSL Project Authors. All Rights Reserved.
*
* Licensed under the Apache License 2.0 (the "License"). You may not use
* this file except in compliance with the License. You can obtain a copy
@@ -67,6 +67,7 @@ static const ERR_STRING_DATA PROV_str_reasons[] = {
{ERR_PACK(ERR_LIB_PROV, 0, PROV_R_INSUFFICIENT_DRBG_STRENGTH),
"insufficient drbg strength"},
{ERR_PACK(ERR_LIB_PROV, 0, PROV_R_INVALID_AAD), "invalid aad"},
+ {ERR_PACK(ERR_LIB_PROV, 0, PROV_R_INVALID_AEAD), "invalid aead"},
{ERR_PACK(ERR_LIB_PROV, 0, PROV_R_INVALID_CONFIG_DATA),
"invalid config data"},
{ERR_PACK(ERR_LIB_PROV, 0, PROV_R_INVALID_CONSTANT_LENGTH),
@@ -85,6 +86,7 @@ static const ERR_STRING_DATA PROV_str_reasons[] = {
{ERR_PACK(ERR_LIB_PROV, 0, PROV_R_INVALID_ITERATION_COUNT),
"invalid iteration count"},
{ERR_PACK(ERR_LIB_PROV, 0, PROV_R_INVALID_IV_LENGTH), "invalid iv length"},
+ {ERR_PACK(ERR_LIB_PROV, 0, PROV_R_INVALID_KDF), "invalid kdf"},
{ERR_PACK(ERR_LIB_PROV, 0, PROV_R_INVALID_KEY), "invalid key"},
{ERR_PACK(ERR_LIB_PROV, 0, PROV_R_INVALID_KEY_LENGTH),
"invalid key length"},
diff --git a/providers/implementations/kem/ec_kem.c b/providers/implementations/kem/ec_kem.c
index 57dcea4196..cdec509f06 100644
--- a/providers/implementations/kem/ec_kem.c
+++ b/providers/implementations/kem/ec_kem.c
@@ -30,25 +30,12 @@
#include "prov/securitycheck.h"
#include "prov/providercommon.h"
-#include "crypto/hpke.h"
+#include <openssl/hpke.h>
+#include "internal/hpke_util.h"
#include "crypto/ec.h"
#include "prov/ecx.h"
#include "eckem.h"
-/*
- * Used to store constants from Section 7.1 "Table 2 KEM IDs"
- * and the bitmask for curves described in Section 7.1.3 DeriveKeyPair
- */
-typedef struct {
- const char *curve;
- const char *kdfdigestname;
- uint16_t kemid;
- size_t secretlen; /* Nsecret = Nh */
- size_t encodedpublen;
- size_t encodedprivlen;
- uint8_t bitmask;
-} DHKEM_ALG;
-
typedef struct {
EC_KEY *recipient_key;
EC_KEY *sender_authkey;
@@ -59,7 +46,7 @@ typedef struct {
unsigned char *ikm;
size_t ikmlen;
const char *kdfname;
- const DHKEM_ALG *alg;
+ const OSSL_HPKE_KEM_INFO *info;
} PROV_EC_CTX;
static OSSL_FUNC_kem_newctx_fn eckem_newctx;
@@ -73,26 +60,8 @@ static OSSL_FUNC_kem_freectx_fn eckem_freectx;
static OSSL_FUNC_kem_set_ctx_params_fn eckem_set_ctx_params;
static OSSL_FUNC_kem_settable_ctx_params_fn eckem_settable_ctx_params;
-/* See Section 7.1 "Table 2 KEM IDs" */
-static const DHKEM_ALG dhkem_alg[] = {
- { "P-256", "SHA256", 0x0010, 32, 65, 32, 0xFF },
- { "P-384", "SHA384", 0x0011, 48, 97, 48, 0xFF },
- { "P-521", "SHA512", 0x0012, 64, 133, 66, 0x01 },
- { NULL }
-};
-
-/* Return an object containing KEM constants associated with a EC curve name */
-static const DHKEM_ALG *dhkem_ec_find_alg(const char *curve)
-{
- int i;
-
- for (i = 0; dhkem_alg[i].curve != NULL; ++i) {
- if (OPENSSL_strcasecmp(curve, dhkem_alg[i].curve) == 0)
- return &dhkem_alg[i];
- }
- ERR_raise(ERR_LIB_PROV, PROV_R_INVALID_CURVE);
- return NULL;
-}
+/* ASCII: "KEM", in hex for EBCDIC compatibility */
+static const char LABEL_KEM[] = "\x4b\x45\x4d";
static int eckey_check(const EC_KEY *ec, int requires_privatekey)
{
@@ -151,8 +120,8 @@ static int recipient_key_set(PROV_EC_CTX *ctx, EC_KEY *ec)
if (curve == NULL)
return -2;
- ctx->alg = dhkem_ec_find_alg(curve);
- if (ctx->alg == NULL)
+ ctx->info = ossl_HPKE_KEM_INFO_find_curve(curve);
+ if (ctx->info == NULL)
return -2;
if (!EC_KEY_up_ref(ec))
return 0;
@@ -372,7 +341,7 @@ static int dhkem_extract_and_expand(EVP_KDF_CTX *kctx,
const unsigned char *kemctx,
size_t kemctxlen)
{
- uint8_t suiteid[5];
+ uint8_t suiteid[2];
uint8_t prk[EVP_MAX_MD_SIZE];
size_t prklen = okmlen;
int ret;
@@ -380,13 +349,14 @@ static int dhkem_extract_and_expand(EVP_KDF_CTX *kctx,
if (prklen > sizeof(prk))
return 0;
- ossl_dhkem_getsuiteid(suiteid, kemid);
+ suiteid[0] = (kemid >> 8) & 0xff;
+ suiteid[1] = kemid & 0xff;
ret = ossl_hpke_labeled_extract(kctx, prk, prklen,
- NULL, 0, suiteid, sizeof(suiteid),
+ NULL, 0, LABEL_KEM, suiteid, sizeof(suiteid),
OSSL_DHKEM_LABEL_EAE_PRK, dhkm, dhkmlen)
&& ossl_hpke_labeled_expand(kctx, okm, okmlen, prk, prklen,
- suiteid, sizeof(suiteid),
+ LABEL_KEM, suiteid, sizeof(suiteid),
OSSL_DHKEM_LABEL_SHARED_SECRET,
kemctx, kemctxlen);
OPENSSL_cleanse(prk, prklen);
@@ -413,52 +383,53 @@ int ossl_ec_dhkem_derive_private(EC_KEY *ec, BIGNUM *priv,
{
int ret = 0;
EVP_KDF_CTX *kdfctx = NULL;
- uint8_t suiteid[5];
+ uint8_t suiteid[2];
unsigned char prk[OSSL_HPKE_MAX_SECRET];
unsigned char privbuf[OSSL_HPKE_MAX_PRIVATE];
const BIGNUM *order;
unsigned char counter = 0;
- const DHKEM_ALG *alg;
const char *curve = ec_curvename_get0(ec);
+ const OSSL_HPKE_KEM_INFO *info;
if (curve == NULL)
return -2;
- alg = dhkem_ec_find_alg(curve);
- if (alg == NULL)
+ info = ossl_HPKE_KEM_INFO_find_curve(curve);
+ if (info == NULL)
return -2;
- kdfctx = ossl_kdf_ctx_create("HKDF", alg->kdfdigestname,
+ kdfctx = ossl_kdf_ctx_create("HKDF", info->mdname,
ossl_ec_key_get_libctx(ec),
ossl_ec_key_get0_propq(ec));
if (kdfctx == NULL)
return 0;
/* ikmlen should have a length of at least Nsk */
- if (ikmlen < alg->encodedprivlen) {
+ if (ikmlen < info->Nsecret) {
ERR_raise_data(ERR_LIB_PROV, PROV_R_INVALID_INPUT_LENGTH,
"ikm length is :%zu, should be at least %zu",
- ikmlen, alg->encodedprivlen);
+ ikmlen, info->Nsecret);
goto err;
}
- ossl_dhkem_getsuiteid(suiteid, alg->kemid);
+ suiteid[0] = info->kem_id / 256;
+ suiteid[1] = info->kem_id % 256;
- if (!ossl_hpke_labeled_extract(kdfctx, prk, alg->secretlen,
- NULL, 0, suiteid, sizeof(suiteid),
+ if (!ossl_hpke_labeled_extract(kdfctx, prk, info->Nsecret,
+ NULL, 0, LABEL_KEM, suiteid, sizeof(suiteid),
OSSL_DHKEM_LABEL_DKP_PRK, ikm, ikmlen))
goto err;
order = EC_GROUP_get0_order(EC_KEY_get0_group(ec));
do {
- if (!ossl_hpke_labeled_expand(kdfctx, privbuf, alg->encodedprivlen,
- prk, alg->secretlen,
- suiteid, sizeof(suiteid),
+ if (!ossl_hpke_labeled_expand(kdfctx, privbuf, info->Nsk,
+ prk, info->Nsecret,
+ LABEL_KEM, suiteid, sizeof(suiteid),
OSSL_DHKEM_LABEL_CANDIDATE,
&counter, 1))
goto err;
- privbuf[0] &= alg->bitmask;
- if (BN_bin2bn(privbuf, alg->encodedprivlen, priv) == NULL)
+ privbuf[0] &= info->bitmask;
+ if (BN_bin2bn(privbuf, info->Nsk, priv) == NULL)
goto err;
if (counter == 0xFF) {
ERR_raise(ERR_LIB_PROV, PROV_R_FAILED_TO_GENERATE_KEY);
@@ -499,7 +470,7 @@ static EC_KEY *derivekey(PROV_EC_CTX *ctx,
/* Generate a random seed if there is no input ikm */
if (seed == NULL || seedlen == 0) {
- seedlen = ctx->alg->encodedprivlen;
+ seedlen = ctx->info->Nsk;
if (seedlen > sizeof(tmpbuf))
goto err;
if (RAND_priv_bytes_ex(ctx->libctx, tmpbuf, seedlen, 0) <= 0)
@@ -599,8 +570,9 @@ static int derive_secret(PROV_EC_CTX *ctx, unsigned char *secret,
unsigned char kemctx[OSSL_HPKE_MAX_PUBLIC * 3];
size_t sender_authpublen;
size_t kemctxlen = 0, dhkmlen = 0;
- size_t encodedpublen = ctx->alg->encodedpublen;
- size_t encodedprivlen = ctx->alg->encodedprivlen;
+ const OSSL_HPKE_KEM_INFO *info = ctx->info;
+ size_t encodedpublen = info->Npk;
+ size_t encodedprivlen = info->Nsk;
int auth = ctx->sender_authkey != NULL;
if (!generate_ecdhkm(privkey1, peerkey1, dhkm, sizeof(dhkm), encodedprivlen))
@@ -630,17 +602,16 @@ static int derive_secret(PROV_EC_CTX *ctx, unsigned char *secret,
goto err;
/* kemctx is the concat of both sides encoded public key */
- memcpy(kemctx, sender_pub, ctx->alg->encodedpublen);
- memcpy(kemctx + ctx->alg->encodedpublen, recipient_pub,
- ctx->alg->encodedpublen);
+ memcpy(kemctx, sender_pub, info->Npk);
+ memcpy(kemctx + info->Npk, recipient_pub, info->Npk);
if (auth)
memcpy(kemctx + 2 * encodedpublen, sender_authpub, encodedpublen);
- kdfctx = ossl_kdf_ctx_create(ctx->kdfname, ctx->alg->kdfdigestname,
+ kdfctx = ossl_kdf_ctx_create(ctx->kdfname, info->mdname,
ctx->libctx, ctx->propq);
if (kdfctx == NULL)
goto err;
- if (!dhkem_extract_and_expand(kdfctx, secret, ctx->alg->secretlen,
- ctx->alg->kemid, dhkm, dhkmlen,
+ if (!dhkem_extract_and_expand(kdfctx, secret, info->Nsecret,
+ info->kem_id, dhkm, dhkmlen,
kemctx, kemctxlen))
goto err;
ret = 1;
@@ -677,22 +648,23 @@ static int dhkem_encap(PROV_EC_CTX *ctx,
unsigned char sender_pub[OSSL_HPKE_MAX_PUBLIC];
unsigned char recipient_pub[OSSL_HPKE_MAX_PUBLIC];
size_t sender_publen, recipient_publen;
+ const OSSL_HPKE_KEM_INFO *info = ctx->info;
if (enc == NULL) {
if (enclen == NULL && secretlen == NULL)
return 0;
if (enclen != NULL)
- *enclen = ctx->alg->encodedpublen;
+ *enclen = info->Nenc;
if (secretlen != NULL)
- *secretlen = ctx->alg->secretlen;
+ *secretlen = info->Nsecret;
return 1;
}
- if (*secretlen < ctx->alg->secretlen) {
+ if (*secretlen < info->Nsecret) {
ERR_raise_data(ERR_LIB_PROV, PROV_R_BAD_LENGTH, "*secretlen too small");
return 0;
}
- if (*enclen < ctx->alg->encodedpublen) {
+ if (*enclen < info->Nenc) {
ERR_raise_data(ERR_LIB_PROV, PROV_R_BAD_LENGTH, "*enclen too small");
return 0;
}
@@ -707,7 +679,7 @@ static int dhkem_encap(PROV_EC_CTX *ctx,
&recipient_publen, sizeof(recipient_pub)))
goto err;
- if (sender_publen != ctx->alg->encodedpublen
+ if (sender_publen != info->Npk
|| recipient_publen != sender_publen) {
ERR_raise_data(ERR_LIB_PROV, PROV_R_INVALID_KEY, "Invalid public key");
goto err;
@@ -722,7 +694,7 @@ static int dhkem_encap(PROV_EC_CTX *ctx,
/* Return the senders ephemeral public key in encoded form */
memcpy(enc, sender_pub, sender_publen);
*enclen = sender_publen;
- *secretlen = ctx->alg->secretlen;
+ *secretlen = info->Nsecret;
ret = 1;
err:
EC_KEY_free(sender_ephemkey);
@@ -751,16 +723,17 @@ static int dhkem_decap(PROV_EC_CTX *ctx,
{
int ret = 0;
EC_KEY *sender_ephempubkey = NULL;
+ const OSSL_HPKE_KEM_INFO *info = ctx->info;
unsigned char recipient_pub[OSSL_HPKE_MAX_PUBLIC];
size_t recipient_publen;
- size_t encodedpublen = ctx->alg->encodedpublen;
+ size_t encodedpublen = info->Npk;
if (secret == NULL) {
- *secretlen = ctx->alg->secretlen;
+ *secretlen = info->Nsecret;
return 1;
}
- if (*secretlen < ctx->alg->secretlen) {
+ if (*secretlen < info->Nsecret) {
ERR_raise_data(ERR_LIB_PROV, PROV_R_BAD_LENGTH, "*secretlen too small");
return 0;
}
@@ -785,7 +758,7 @@ static int dhkem_decap(PROV_EC_CTX *ctx,
ctx->recipient_key, ctx->sender_authkey,
enc, recipient_pub))
goto err;
- *secretlen = ctx->alg->secretlen;
+ *secretlen = info->Nsecret;
ret = 1;
err:
EC_KEY_free(sender_ephempubkey);
diff --git a/providers/implementations/kem/eckem.h b/providers/implementations/kem/eckem.h
index 44fdde852b..2e46a0f2ff 100644
--- a/providers/implementations/kem/eckem.h
+++ b/providers/implementations/kem/eckem.h
@@ -11,4 +11,3 @@
#define KEM_MODE_DHKEM 1
int ossl_eckem_modename2id(const char *name);
-void ossl_dhkem_getsuiteid(unsigned char suiteid[5], uint16_t kemid);
diff --git a/providers/implementations/kem/ecx_kem.c b/providers/implementations/kem/ecx_kem.c
index 979035fa1c..b868afdfbc 100644
--- a/providers/implementations/kem/ecx_kem.c
+++ b/providers/implementations/kem/ecx_kem.c
@@ -32,7 +32,8 @@
#include "prov/providercommon.h"
#include "prov/ecx.h"
#include "crypto/ecx.h"
-#include "crypto/hpke.h"
+#include <openssl/hpke.h>
+#include "internal/hpke_util.h"
#include "eckem.h"
#define MAX_ECX_KEYLEN X448_KEYLEN
@@ -41,6 +42,9 @@
#define KEMID_X25519_HKDF_SHA256 0x20
#define KEMID_X448_HKDF_SHA512 0x21
+/* ASCII: "KEM", in hex for EBCDIC compatibility */
+static const char LABEL_KEM[] = "\x4b\x45\x4d";
+
typedef struct {
ECX_KEY *recipient_key;
ECX_KEY *sender_authkey;
@@ -48,13 +52,10 @@ typedef struct {
char *propq;
unsigned int mode;
unsigned int op;
- uint16_t kemid;
unsigned char *ikm;
size_t ikmlen;
const char *kdfname;
- const char *kdfdigestname;
- size_t sharedsecretlen;
- size_t keylen;
+ const OSSL_HPKE_KEM_INFO *info;
} PROV_ECX_CTX;
static OSSL_FUNC_kem_newctx_fn ecxkem_newctx;
@@ -72,21 +73,15 @@ static OSSL_FUNC_kem_auth_decapsulate_init_fn ecxkem_auth_decapsulate_init;
* There is only one set of values for X25519 and X448.
* Additional values could be set via set_params if required.
*/
-static void get_kem_values(ECX_KEY *ecx, uint16_t *kemid,
- const char **kdfdigestname, size_t *secretlen,
- size_t *keylen)
+static const OSSL_HPKE_KEM_INFO *get_kem_info(ECX_KEY *ecx)
{
- if (ecx->type == ECX_KEY_TYPE_X25519) {
- *kemid = KEMID_X25519_HKDF_SHA256;
- *kdfdigestname = "SHA256";
- *secretlen = SHA256_DIGEST_LENGTH;
- } else {
- *kemid = KEMID_X448_HKDF_SHA512;
- *kdfdigestname = "SHA512";
- *secretlen = SHA512_DIGEST_LENGTH;
- }
- /* ECX keys have the same length for public and private keys */
- *keylen = ecx->keylen;
+ const char *name = NULL;
+
+ if (ecx->type == ECX_KEY_TYPE_X25519)
+ name = SN_X25519;
+ else
+ name = SN_X448;
+ return ossl_HPKE_KEM_INFO_find_curve(name);
}
/*
@@ -98,8 +93,9 @@ static int recipient_key_set(PROV_ECX_CTX *ctx, ECX_KEY *ecx)
ossl_ecx_key_free(ctx->recipient_key);
ctx->recipient_key = NULL;
if (ecx != NULL) {
- get_kem_values(ecx, &ctx->kemid, &ctx->kdfdigestname,
- &ctx->sharedsecretlen, &ctx->keylen);
+ ctx->info = get_kem_info(ecx);
+ if (ctx->info == NULL)
+ return -2;
ctx->kdfname = "HKDF";
if (!ossl_ecx_key_up_ref(ecx))
return 0;
@@ -302,7 +298,7 @@ static int dhkem_extract_and_expand(EVP_KDF_CTX *kctx,
const unsigned char *kemctx,
size_t kemctxlen)
{
- uint8_t suiteid[5];
+ uint8_t suiteid[2];
uint8_t prk[EVP_MAX_MD_SIZE];
size_t prklen = okmlen; /* Nh */
int ret;
@@ -310,13 +306,14 @@ static int dhkem_extract_and_expand(EVP_KDF_CTX *kctx,
if (prklen > sizeof(prk))
return 0;
- ossl_dhkem_getsuiteid(suiteid, kemid);
+ suiteid[0] = (kemid >> 8) &0xff;
+ suiteid[1] = kemid & 0xff;
ret = ossl_hpke_labeled_extract(kctx, prk, prklen,
- NULL, 0, suiteid, sizeof(suiteid),
+ NULL, 0, LABEL_KEM, suiteid, sizeof(suiteid),
OSSL_DHKEM_LABEL_EAE_PRK, dhkm, dhkmlen)
&& ossl_hpke_labeled_expand(kctx, okm, okmlen, prk, prklen,
- suiteid, sizeof(suiteid),
+ LABEL_KEM, suiteid, sizeof(suiteid),
OSSL_DHKEM_LABEL_SHARED_SECRET,
kemctx, kemctxlen);
OPENSSL_cleanse(prk, prklen);
@@ -344,35 +341,32 @@ int ossl_ecx_dhkem_derive_private(ECX_KEY *ecx, unsigned char *privout,
int ret = 0;
EVP_KDF_CTX *kdfctx = NULL;
unsigned char prk[EVP_MAX_MD_SIZE];
- uint16_t kemid;
- const char *kdfdigestname;
- uint8_t suiteid[5];
- size_t prklen, keylen;
-
- get_kem_values(ecx, &kemid, &kdfdigestname, &prklen, &keylen);
+ uint8_t suiteid[2];
+ const OSSL_HPKE_KEM_INFO *info = get_kem_info(ecx);
/* ikmlen should have a length of at least Nsk */
- if (ikmlen < keylen) {
+ if (ikmlen < info->Nsk) {
ERR_raise_data(ERR_LIB_PROV, PROV_R_INVALID_INPUT_LENGTH,
"ikm length is :%zu, should be at least %zu",
- ikmlen, keylen);
+ ikmlen, info->Nsk);
goto err;
}
- kdfctx = ossl_kdf_ctx_create("HKDF", kdfdigestname, ecx->libctx, ecx->propq);
+ kdfctx = ossl_kdf_ctx_create("HKDF", info->mdname, ecx->libctx, ecx->propq);
if (kdfctx == NULL)
return 0;
- ossl_dhkem_getsuiteid(suiteid, kemid);
+ suiteid[0] = info->kem_id / 256;
+ suiteid[1] = info->kem_id % 256;
- if (!ossl_hpke_labeled_extract(kdfctx, prk, prklen,
- NULL, 0, suiteid, sizeof(suiteid),
+ if (!ossl_hpke_labeled_extract(kdfctx, prk, info->Nsecret,
+ NULL, 0, LABEL_KEM, suiteid, sizeof(suiteid),
OSSL_DHKEM_LABEL_DKP_PRK, ikm, ikmlen))
goto err;
- if (!ossl_hpke_labeled_expand(kdfctx, privout, keylen, prk, prklen,
- suiteid, sizeof(suiteid), OSSL_DHKEM_LABEL_SK,
- NULL, 0))
+ if (!ossl_hpke_labeled_expand(kdfctx, privout, info->Nsk, prk, info->Nsecret,
+ LABEL_KEM, suiteid, sizeof(suiteid),
+ OSSL_DHKEM_LABEL_SK, NULL, 0))
goto err;
ret = 1;
err:
@@ -398,6 +392,7 @@ static ECX_KEY *derivekey(PROV_ECX_CTX *ctx,
unsigned char *seed = (unsigned char *)ikm;
size_t seedlen = ikmlen;
unsigned char tmpbuf[OSSL_HPKE_MAX_PRIVATE];
+ const OSSL_HPKE_KEM_INFO *info = ctx->info;
key = ossl_ecx_key_new(ctx->libctx, ctx->recipient_key->type, 0, ctx->propq);
if (key == NULL)
@@ -408,12 +403,12 @@ static ECX_KEY *derivekey(PROV_ECX_CTX *ctx,
/* Generate a random seed if there is no input ikm */
if (seed == NULL || seedlen == 0) {
- if (ctx->keylen > sizeof(tmpbuf))
+ if (info->Nsk > sizeof(tmpbuf))
goto err;
- if (RAND_priv_bytes_ex(ctx->libctx, tmpbuf, ctx->keylen, 0) <= 0)
+ if (RAND_priv_bytes_ex(ctx->libctx, tmpbuf, info->Nsk, 0) <= 0)
goto err;
seed = tmpbuf;
- seedlen = ctx->keylen;
+ seedlen = info->Nsk;
}
if (!ossl_ecx_dhkem_derive_private(key, privkey, seed, seedlen))
goto err;
@@ -485,8 +480,9 @@ static int derive_secret(PROV_ECX_CTX *ctx, unsigned char *secret,
unsigned char dhkm[MAX_ECX_KEYLEN * 2];
unsigned char kemctx[MAX_ECX_KEYLEN * 3];
size_t kemctxlen = 0, dhkmlen = 0;
- size_t encodedkeylen = ctx->keylen;
+ const OSSL_HPKE_KEM_INFO *info = ctx->info;
int auth = ctx->sender_authkey != NULL;
+ size_t encodedkeylen = info->Npk;
if (!generate_ecxdhkm(privkey1, peerkey1, dhkm, sizeof(dhkm), encodedkeylen))
goto err;
@@ -513,12 +509,12 @@ static int derive_secret(PROV_ECX_CTX *ctx, unsigned char *secret,
memcpy(kemctx + encodedkeylen, recipient_pub, encodedkeylen);
if (auth)
memcpy(kemctx + 2 * encodedkeylen, sender_authpub, encodedkeylen);
- kdfctx = ossl_kdf_ctx_create(ctx->kdfname, ctx->kdfdigestname,
+ kdfctx = ossl_kdf_ctx_create(ctx->kdfname, info->mdname,
ctx->libctx, ctx->propq);
if (kdfctx == NULL)
goto err;
- if (!dhkem_extract_and_expand(kdfctx, secret, ctx->sharedsecretlen,
- ctx->kemid, dhkm, dhkmlen,
+ if (!dhkem_extract_and_expand(kdfctx, secret, info->Nsecret,
+ info->kem_id, dhkm, dhkmlen,
kemctx, kemctxlen))
goto err;
ret = 1;
@@ -553,22 +549,23 @@ static int dhkem_encap(PROV_ECX_CTX *ctx,
int ret = 0;
ECX_KEY *sender_ephemkey = NULL;
unsigned char *sender_ephempub, *recipient_pub;
+ const OSSL_HPKE_KEM_INFO *info = ctx->info;
if (enc == NULL) {
if (enclen == NULL && secretlen == NULL)
return 0;
if (enclen != NULL)
- *enclen = ctx->keylen;
+ *enclen = info->Nenc;
if (secretlen != NULL)
- *secretlen = ctx->sharedsecretlen;
+ *secretlen = info->Nsecret;
return 1;
}
- if (*secretlen < ctx->sharedsecretlen) {
+ if (*secretlen < info->Nsecret) {
ERR_raise_data(ERR_LIB_PROV, PROV_R_BAD_LENGTH, "*secretlen too small");
return 0;
}
- if (*enclen < ctx->keylen) {
+ if (*enclen < info->Nenc) {
ERR_raise_data(ERR_LIB_PROV, PROV_R_BAD_LENGTH, "*enclen too small");
return 0;
}
@@ -588,9 +585,9 @@ static int dhkem_encap(PROV_ECX_CTX *ctx,
goto err;
/* Return the public part of the ephemeral key */
- memcpy(enc, sender_ephempub, ctx->keylen);
- *enclen = ctx->keylen;
- *secretlen = ctx->sharedsecretlen;
+ memcpy(enc, sender_ephempub, info->Nenc);
+ *enclen = info->Nenc;
+ *secretlen = info->Nsecret;
ret = 1;
err:
ossl_ecx_key_free(sender_ephemkey);
@@ -620,17 +617,18 @@ static int dhkem_decap(PROV_ECX_CTX *ctx,
int ret = 0;
ECX_KEY *recipient_privkey = ctx->recipient_key;
ECX_KEY *sender_ephempubkey = NULL;
+ const OSSL_HPKE_KEM_INFO *info = ctx->info;
unsigned char *recipient_pub;
if (secret == NULL) {
- *secretlen = ctx->sharedsecretlen;
+ *secretlen = info->Nsecret;
return 1;
}
- if (*secretlen < ctx->sharedsecretlen) {
+ if (*secretlen < info->Nsecret) {
ERR_raise_data(ERR_LIB_PROV, PROV_R_BAD_LENGTH, "*secretlen too small");
return 0;
}
- if (enclen != ctx->keylen) {
+ if (enclen != info->Nenc) {
ERR_raise_data(ERR_LIB_PROV, PROV_R_INVALID_KEY, "Invalid enc public key");
return 0;
}
@@ -650,7 +648,7 @@ static int dhkem_decap(PROV_ECX_CTX *ctx,
enc, recipient_pub))
goto err;
- *secretlen = ctx->sharedsecretlen;
+ *secretlen = info->Nsecret;
ret = 1;
err:
ossl_ecx_key_free(sender_ephempubkey);
diff --git a/providers/implementations/kem/kem_util.c b/providers/implementations/kem/kem_util.c
index 8ce2854ee4..1fd52e1c2d 100644
--- a/providers/implementations/kem/kem_util.c
+++ b/providers/implementations/kem/kem_util.c
@@ -35,11 +35,3 @@ int ossl_eckem_modename2id(const char *name)
}
return KEM_MODE_UNDEFINED;
}
-
-/* suiteid = concat("KEM", I2OSP(kem_id, 2)) */
-void ossl_dhkem_getsuiteid(unsigned char suiteid[5], uint16_t kemid)
-{
- memcpy(suiteid, "KEM", 3);
- suiteid[3] = kemid >> 8;
- suiteid[4] = kemid & 0xFF;
-}