mirror of
https://github.com/wolfSSL/wolfssl.git
synced 2026-07-05 15:50:51 +02:00
move hpke-esque code out of tls
This commit is contained in:
+2
-25
@@ -338,23 +338,7 @@ int GetEchConfig(WOLFSSL_EchConfig* config, byte* output, word32* outputLen)
|
||||
totalLen += 2;
|
||||
|
||||
/* hpke_pub_key */
|
||||
switch (config->kemId) {
|
||||
case DHKEM_P256_HKDF_SHA256:
|
||||
totalLen += DHKEM_P256_ENC_LEN;
|
||||
break;
|
||||
case DHKEM_P384_HKDF_SHA384:
|
||||
totalLen += DHKEM_P384_ENC_LEN;
|
||||
break;
|
||||
case DHKEM_P521_HKDF_SHA512:
|
||||
totalLen += DHKEM_P521_ENC_LEN;
|
||||
break;
|
||||
case DHKEM_X25519_HKDF_SHA256:
|
||||
totalLen += DHKEM_X25519_ENC_LEN;
|
||||
break;
|
||||
case DHKEM_X448_HKDF_SHA512:
|
||||
totalLen += DHKEM_X448_ENC_LEN;
|
||||
break;
|
||||
}
|
||||
totalLen += wc_HpkeKemGetEncLen(config->kemId);
|
||||
|
||||
/* cipherSuitesLen */
|
||||
totalLen += 2;
|
||||
@@ -693,16 +677,9 @@ int SetEchConfigsEx(WOLFSSL_EchConfig** outputConfigs, void* heap,
|
||||
break;
|
||||
}
|
||||
|
||||
/* check that we support this config */
|
||||
for (j = 0; j < HPKE_SUPPORTED_KEM_LEN; j++) {
|
||||
if (hpkeSupportedKem[j] == workingConfig->kemId)
|
||||
break;
|
||||
}
|
||||
|
||||
/* KEM or ciphersuite not supported, free this config and then try to
|
||||
* parse another */
|
||||
if (j >= HPKE_SUPPORTED_KEM_LEN ||
|
||||
EchConfigGetSupportedCipherSuite(workingConfig) < 0) {
|
||||
if (EchConfigGetSupportedCipherSuite(workingConfig) < 0) {
|
||||
XFREE(workingConfig->cipherSuites, heap, DYNAMIC_TYPE_TMP_BUFFER);
|
||||
XFREE(workingConfig->publicName, heap, DYNAMIC_TYPE_TMP_BUFFER);
|
||||
XFREE(workingConfig->raw, heap, DYNAMIC_TYPE_TMP_BUFFER);
|
||||
|
||||
@@ -13259,24 +13259,7 @@ static int TLSX_ECH_Use(WOLFSSL_EchConfig* echConfig, TLSX** extensions,
|
||||
/* configId */
|
||||
ech->configId = echConfig->configId;
|
||||
/* encLen */
|
||||
switch (echConfig->kemId)
|
||||
{
|
||||
case DHKEM_P256_HKDF_SHA256:
|
||||
ech->encLen = DHKEM_P256_ENC_LEN;
|
||||
break;
|
||||
case DHKEM_P384_HKDF_SHA384:
|
||||
ech->encLen = DHKEM_P384_ENC_LEN;
|
||||
break;
|
||||
case DHKEM_P521_HKDF_SHA512:
|
||||
ech->encLen = DHKEM_P521_ENC_LEN;
|
||||
break;
|
||||
case DHKEM_X25519_HKDF_SHA256:
|
||||
ech->encLen = DHKEM_X25519_ENC_LEN;
|
||||
break;
|
||||
case DHKEM_X448_HKDF_SHA512:
|
||||
ech->encLen = DHKEM_X448_ENC_LEN;
|
||||
break;
|
||||
}
|
||||
ech->encLen = wc_HpkeKemGetEncLen(echConfig->kemId);
|
||||
/* setup hpke */
|
||||
ech->hpke = (Hpke*)XMALLOC(sizeof(Hpke), heap, DYNAMIC_TYPE_TMP_BUFFER);
|
||||
if (ech->hpke == NULL) {
|
||||
@@ -13288,8 +13271,13 @@ static int TLSX_ECH_Use(WOLFSSL_EchConfig* echConfig, TLSX** extensions,
|
||||
/* setup the ephemeralKey */
|
||||
if (ret == 0)
|
||||
ret = wc_HpkeGenerateKeyPair(ech->hpke, &ech->ephemeralKey, rng);
|
||||
if (ret == 0)
|
||||
if (ret == 0) {
|
||||
ret = TLSX_Push(extensions, TLSX_ECH, ech, heap);
|
||||
if (ret != 0) {
|
||||
wc_HpkeFreeKey(ech->hpke, ech->hpke->kem, ech->ephemeralKey,
|
||||
ech->hpke->heap);
|
||||
}
|
||||
}
|
||||
if (ret != 0) {
|
||||
XFREE(ech->hpke, heap, DYNAMIC_TYPE_TMP_BUFFER);
|
||||
XFREE(ech, heap, DYNAMIC_TYPE_TMP_BUFFER);
|
||||
@@ -13916,7 +13904,6 @@ static int TLSX_ExtractEch(WOLFSSL_ECH* ech, WOLFSSL_EchConfig* echConfig,
|
||||
byte* aad, word32 aadLen, void* heap)
|
||||
{
|
||||
int ret = 0;
|
||||
int expectedEncLen;
|
||||
int i;
|
||||
word32 rawConfigLen = 0;
|
||||
byte* info = NULL;
|
||||
@@ -13924,28 +13911,7 @@ static int TLSX_ExtractEch(WOLFSSL_ECH* ech, WOLFSSL_EchConfig* echConfig,
|
||||
if (ech == NULL || echConfig == NULL || aad == NULL)
|
||||
return BAD_FUNC_ARG;
|
||||
/* verify the kem and key len */
|
||||
switch (echConfig->kemId)
|
||||
{
|
||||
case DHKEM_P256_HKDF_SHA256:
|
||||
expectedEncLen = DHKEM_P256_ENC_LEN;
|
||||
break;
|
||||
case DHKEM_P384_HKDF_SHA384:
|
||||
expectedEncLen = DHKEM_P384_ENC_LEN;
|
||||
break;
|
||||
case DHKEM_P521_HKDF_SHA512:
|
||||
expectedEncLen = DHKEM_P521_ENC_LEN;
|
||||
break;
|
||||
case DHKEM_X25519_HKDF_SHA256:
|
||||
expectedEncLen = DHKEM_X25519_ENC_LEN;
|
||||
break;
|
||||
case DHKEM_X448_HKDF_SHA512:
|
||||
expectedEncLen = DHKEM_X448_ENC_LEN;
|
||||
break;
|
||||
default:
|
||||
expectedEncLen = 0;
|
||||
break;
|
||||
}
|
||||
if (expectedEncLen != ech->encLen)
|
||||
if (wc_HpkeKemGetEncLen(echConfig->kemId) != ech->encLen)
|
||||
return BAD_FUNC_ARG;
|
||||
/* verify the cipher suite */
|
||||
for (i = 0; i < echConfig->numCipherSuites; i++) {
|
||||
@@ -14229,11 +14195,12 @@ static int TLSX_ECH_Parse(WOLFSSL* ssl, const byte* readBuf, word16 size,
|
||||
static void TLSX_ECH_Free(WOLFSSL_ECH* ech, void* heap)
|
||||
{
|
||||
XFREE(ech->innerClientHello, heap, DYNAMIC_TYPE_TMP_BUFFER);
|
||||
if (ech->ephemeralKey != NULL)
|
||||
wc_HpkeFreeKey(ech->hpke, ech->hpke->kem, ech->ephemeralKey,
|
||||
ech->hpke->heap);
|
||||
if (ech->hpke != NULL)
|
||||
if (ech->hpke != NULL) {
|
||||
if (ech->ephemeralKey != NULL)
|
||||
wc_HpkeFreeKey(ech->hpke, ech->hpke->kem, ech->ephemeralKey,
|
||||
ech->hpke->heap);
|
||||
XFREE(ech->hpke, heap, DYNAMIC_TYPE_TMP_BUFFER);
|
||||
}
|
||||
if (ech->hpkeContext != NULL)
|
||||
XFREE(ech->hpkeContext, heap, DYNAMIC_TYPE_TMP_BUFFER);
|
||||
if (ech->privateName != NULL)
|
||||
|
||||
+8
-17
@@ -3782,26 +3782,17 @@ static byte helloRetryRequestRandom[] = {
|
||||
/* returns the index of the first supported cipher suite, -1 if none */
|
||||
int EchConfigGetSupportedCipherSuite(WOLFSSL_EchConfig* config)
|
||||
{
|
||||
int i, j, supported = 0;
|
||||
int i = 0;
|
||||
|
||||
if (!wc_HpkeKemIsSupported(config->kemId)) {
|
||||
return WOLFSSL_FATAL_ERROR;
|
||||
}
|
||||
|
||||
for (i = 0; i < config->numCipherSuites; i++) {
|
||||
supported = 0;
|
||||
|
||||
for (j = 0; j < HPKE_SUPPORTED_KDF_LEN; j++) {
|
||||
if (config->cipherSuites[i].kdfId == hpkeSupportedKdf[j])
|
||||
break;
|
||||
}
|
||||
|
||||
if (j < HPKE_SUPPORTED_KDF_LEN)
|
||||
for (j = 0; j < HPKE_SUPPORTED_AEAD_LEN; j++) {
|
||||
if (config->cipherSuites[i].aeadId == hpkeSupportedAead[j]) {
|
||||
supported = 1;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (supported)
|
||||
if (wc_HpkeKdfIsSupported(config->cipherSuites[i].kdfId) &&
|
||||
wc_HpkeAeadIsSupported(config->cipherSuites[i].aeadId)) {
|
||||
return i;
|
||||
}
|
||||
}
|
||||
|
||||
return WOLFSSL_FATAL_ERROR;
|
||||
|
||||
+29
-3
@@ -14547,15 +14547,41 @@ static int test_wolfSSL_Tls13_ECH_all_algos(void)
|
||||
int j;
|
||||
int k;
|
||||
static const word16 kems[] = {
|
||||
#if defined(HAVE_ECC)
|
||||
#if (defined(WOLFSSL_SHA224) || !defined(NO_SHA256))
|
||||
DHKEM_P256_HKDF_SHA256,
|
||||
#endif
|
||||
#if defined(WOLFSSL_SHA384)
|
||||
DHKEM_P384_HKDF_SHA384,
|
||||
#endif
|
||||
#if (defined(WOLFSSL_SHA384) || defined(WOLFSSL_SHA512))
|
||||
DHKEM_P521_HKDF_SHA512,
|
||||
#endif
|
||||
#endif /* HAVE_ECC */
|
||||
#if defined(HAVE_CURVE25519) && (defined(WOLFSSL_SHA224) || !defined(NO_SHA256))
|
||||
DHKEM_X25519_HKDF_SHA256,
|
||||
#endif
|
||||
};
|
||||
static const word16 kdfs[] = {
|
||||
#if defined(WOLFSSL_SHA224) || !defined(NO_SHA256)
|
||||
HKDF_SHA256,
|
||||
#endif
|
||||
#ifdef WOLFSSL_SHA384
|
||||
HKDF_SHA384,
|
||||
#endif
|
||||
#ifdef WOLFSSL_SHA512
|
||||
HKDF_SHA512,
|
||||
#endif
|
||||
};
|
||||
static const word16 aeads[] = {
|
||||
#ifdef WOLFSSL_AES_128
|
||||
HPKE_AES_128_GCM,
|
||||
#endif
|
||||
#ifdef WOLFSSL_AES_256
|
||||
HPKE_AES_256_GCM,
|
||||
#endif
|
||||
};
|
||||
static const word16 kdfs[] = { HKDF_SHA256, HKDF_SHA384, HKDF_SHA512 };
|
||||
static const word16 aeads[] = { HPKE_AES_128_GCM, HPKE_AES_256_GCM };
|
||||
|
||||
/* test each KEM with default KDF and AEAD */
|
||||
for (i = 0; i < (int)(sizeof(kems) / sizeof(*kems)); i++) {
|
||||
echCbTestKemID = kems[i];
|
||||
for (j = 0; j < (int)(sizeof(kdfs) / sizeof(*kdfs)); j++) {
|
||||
|
||||
+110
-24
@@ -45,24 +45,6 @@
|
||||
#include <wolfcrypt/src/misc.c>
|
||||
#endif
|
||||
|
||||
const int hpkeSupportedKem[HPKE_SUPPORTED_KEM_LEN] = {
|
||||
DHKEM_P256_HKDF_SHA256,
|
||||
DHKEM_P384_HKDF_SHA384,
|
||||
DHKEM_P521_HKDF_SHA512,
|
||||
DHKEM_X25519_HKDF_SHA256,
|
||||
};
|
||||
|
||||
const int hpkeSupportedKdf[HPKE_SUPPORTED_KDF_LEN] = {
|
||||
HKDF_SHA256,
|
||||
HKDF_SHA384,
|
||||
HKDF_SHA512,
|
||||
};
|
||||
|
||||
const int hpkeSupportedAead[HPKE_SUPPORTED_AEAD_LEN] = {
|
||||
HPKE_AES_128_GCM,
|
||||
HPKE_AES_256_GCM,
|
||||
};
|
||||
|
||||
static const char* KEM_STR = "KEM";
|
||||
static const int KEM_STR_LEN = 3;
|
||||
|
||||
@@ -132,9 +114,9 @@ int wc_HpkeInit(Hpke* hpke, int kem, int kdf, int aead, void* heap)
|
||||
}
|
||||
|
||||
XMEMSET(hpke, 0, sizeof(*hpke));
|
||||
hpke->kem = (word32)kem;
|
||||
hpke->kdf = (word32)kdf;
|
||||
hpke->aead = (word32)aead;
|
||||
hpke->kem = (word16)kem;
|
||||
hpke->kdf = (word16)kdf;
|
||||
hpke->aead = (word16)aead;
|
||||
hpke->heap = heap;
|
||||
|
||||
/* set kem_suite_id */
|
||||
@@ -227,20 +209,26 @@ int wc_HpkeInit(Hpke* hpke, int kem, int kdf, int aead, void* heap)
|
||||
|
||||
if (ret == 0) {
|
||||
switch (kdf) {
|
||||
#if defined(WOLFSSL_SHA224) || !defined(NO_SHA256)
|
||||
case HKDF_SHA256:
|
||||
hpke->Nh = WC_SHA256_DIGEST_SIZE;
|
||||
hpke->kdf_digest = WC_SHA256;
|
||||
break;
|
||||
#endif
|
||||
|
||||
#ifdef WOLFSSL_SHA384
|
||||
case HKDF_SHA384:
|
||||
hpke->Nh = WC_SHA384_DIGEST_SIZE;
|
||||
hpke->kdf_digest = WC_SHA384;
|
||||
break;
|
||||
#endif
|
||||
|
||||
#ifdef WOLFSSL_SHA512
|
||||
case HKDF_SHA512:
|
||||
hpke->Nh = WC_SHA512_DIGEST_SIZE;
|
||||
hpke->kdf_digest = WC_SHA512;
|
||||
break;
|
||||
#endif
|
||||
|
||||
default:
|
||||
ret = BAD_FUNC_ARG;
|
||||
@@ -250,17 +238,21 @@ int wc_HpkeInit(Hpke* hpke, int kem, int kdf, int aead, void* heap)
|
||||
|
||||
if (ret == 0) {
|
||||
switch (aead) {
|
||||
#ifdef WOLFSSL_AES_128
|
||||
case HPKE_AES_128_GCM:
|
||||
hpke->Nk = AES_128_KEY_SIZE;
|
||||
hpke->Nn = GCM_NONCE_MID_SZ;
|
||||
hpke->Nt = WC_AES_BLOCK_SIZE;
|
||||
break;
|
||||
#endif
|
||||
|
||||
#ifdef WOLFSSL_AES_256
|
||||
case HPKE_AES_256_GCM:
|
||||
hpke->Nk = AES_256_KEY_SIZE;
|
||||
hpke->Nn = GCM_NONCE_MID_SZ;
|
||||
hpke->Nt = WC_AES_BLOCK_SIZE;
|
||||
break;
|
||||
#endif
|
||||
|
||||
default:
|
||||
ret = BAD_FUNC_ARG;
|
||||
@@ -329,7 +321,7 @@ int wc_HpkeGenerateKeyPair(Hpke* hpke, void** keypair, WC_RNG* rng)
|
||||
ret = MEMORY_E;
|
||||
|
||||
if (ret != 0 && *keypair != NULL) {
|
||||
wc_HpkeFreeKey(hpke, (word16)hpke->kem, *keypair, hpke->heap);
|
||||
wc_HpkeFreeKey(hpke, hpke->kem, *keypair, hpke->heap);
|
||||
*keypair = NULL;
|
||||
}
|
||||
|
||||
@@ -427,7 +419,7 @@ int wc_HpkeDeserializePublicKey(Hpke* hpke, void** key, const byte* in,
|
||||
ret = MEMORY_E;
|
||||
|
||||
if (ret != 0 && *key != NULL) {
|
||||
wc_HpkeFreeKey(hpke, (word16)hpke->kem, *key, hpke->heap);
|
||||
wc_HpkeFreeKey(hpke, hpke->kem, *key, hpke->heap);
|
||||
*key = NULL;
|
||||
}
|
||||
|
||||
@@ -1083,7 +1075,7 @@ static int wc_HpkeDecap(Hpke* hpke, void* receiverKey, const byte* pubKey,
|
||||
}
|
||||
|
||||
if (ephemeralKey != NULL)
|
||||
wc_HpkeFreeKey(hpke, (word16)hpke->kem, ephemeralKey, hpke->heap);
|
||||
wc_HpkeFreeKey(hpke, hpke->kem, ephemeralKey, hpke->heap);
|
||||
|
||||
if (ret == 0) {
|
||||
/* copy pubKey into kemContext */
|
||||
@@ -1226,4 +1218,98 @@ int wc_HpkeOpenBase(Hpke* hpke, void* receiverKey, const byte* pubKey,
|
||||
return ret;
|
||||
}
|
||||
|
||||
WOLFSSL_LOCAL word16 wc_HpkeKemGetEncLen(word16 kemId)
|
||||
{
|
||||
switch (kemId)
|
||||
{
|
||||
#if defined(HAVE_ECC)
|
||||
#if defined(WOLFSSL_SHA224) || !defined(NO_SHA256)
|
||||
case DHKEM_P256_HKDF_SHA256:
|
||||
return DHKEM_P256_ENC_LEN;
|
||||
#endif
|
||||
#ifdef WOLFSSL_SHA384
|
||||
case DHKEM_P384_HKDF_SHA384:
|
||||
return DHKEM_P384_ENC_LEN;
|
||||
#endif
|
||||
#if defined(WOLFSSL_SHA384) || defined(WOLFSSL_SHA512)
|
||||
case DHKEM_P521_HKDF_SHA512:
|
||||
return DHKEM_P521_ENC_LEN;
|
||||
#endif
|
||||
#endif /* HAVE_ECC */
|
||||
#if defined(HAVE_CURVE25519) && \
|
||||
(defined(WOLFSSL_SHA224) || !defined(NO_SHA256))
|
||||
case DHKEM_X25519_HKDF_SHA256:
|
||||
return DHKEM_X25519_ENC_LEN;
|
||||
#endif
|
||||
#if defined(HAVE_CURVE448) &&\
|
||||
(defined(WOLFSSL_SHA384) || defined(WOLFSSL_SHA512))
|
||||
case DHKEM_X448_HKDF_SHA512:
|
||||
return DHKEM_X448_ENC_LEN;
|
||||
#endif
|
||||
default:
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
WOLFSSL_LOCAL int wc_HpkeKemIsSupported(word16 kemId)
|
||||
{
|
||||
switch (kemId) {
|
||||
#if defined(HAVE_ECC)
|
||||
#if defined(WOLFSSL_SHA224) || !defined(NO_SHA256)
|
||||
case DHKEM_P256_HKDF_SHA256:
|
||||
#endif
|
||||
#ifdef WOLFSSL_SHA384
|
||||
case DHKEM_P384_HKDF_SHA384:
|
||||
#endif
|
||||
#if defined(WOLFSSL_SHA384) || defined(WOLFSSL_SHA512)
|
||||
case DHKEM_P521_HKDF_SHA512:
|
||||
#endif
|
||||
#endif /* HAVE_ECC */
|
||||
#if defined(HAVE_CURVE25519) && \
|
||||
(defined(WOLFSSL_SHA224) || !defined(NO_SHA256))
|
||||
case DHKEM_X25519_HKDF_SHA256:
|
||||
#endif
|
||||
return 1;
|
||||
|
||||
case DHKEM_X448_HKDF_SHA512:
|
||||
default:
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
WOLFSSL_LOCAL int wc_HpkeKdfIsSupported(word16 kdfId)
|
||||
{
|
||||
switch (kdfId) {
|
||||
#if defined(WOLFSSL_SHA224) || !defined(NO_SHA256)
|
||||
case HKDF_SHA256:
|
||||
#endif
|
||||
#ifdef WOLFSSL_SHA384
|
||||
case HKDF_SHA384:
|
||||
#endif
|
||||
#ifdef WOLFSSL_SHA512
|
||||
case HKDF_SHA512:
|
||||
#endif
|
||||
return 1;
|
||||
|
||||
default:
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
WOLFSSL_LOCAL int wc_HpkeAeadIsSupported(word16 aeadId)
|
||||
{
|
||||
switch (aeadId) {
|
||||
#ifdef WOLFSSL_AES_128
|
||||
case HPKE_AES_128_GCM:
|
||||
#endif
|
||||
#ifdef WOLFSSL_AES_256
|
||||
case HPKE_AES_256_GCM:
|
||||
#endif
|
||||
return 1;
|
||||
|
||||
default:
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
#endif /* HAVE_HPKE && (HAVE_ECC || HAVE_CURVE25519) && HAVE_AESGCM */
|
||||
|
||||
@@ -64,14 +64,6 @@ enum {
|
||||
HPKE_AES_256_GCM = 0x0002
|
||||
};
|
||||
|
||||
/* TODO better way of doing this */
|
||||
#define HPKE_SUPPORTED_KEM_LEN 4
|
||||
#define HPKE_SUPPORTED_KDF_LEN 3
|
||||
#define HPKE_SUPPORTED_AEAD_LEN 2
|
||||
extern const int hpkeSupportedKem[HPKE_SUPPORTED_KEM_LEN];
|
||||
extern const int hpkeSupportedKdf[HPKE_SUPPORTED_KDF_LEN];
|
||||
extern const int hpkeSupportedAead[HPKE_SUPPORTED_AEAD_LEN];
|
||||
|
||||
#define HPKE_Nh_MAX 64
|
||||
#define HPKE_Nk_MAX 32
|
||||
#define HPKE_Nn_MAX 12
|
||||
@@ -88,9 +80,6 @@ extern const int hpkeSupportedAead[HPKE_SUPPORTED_AEAD_LEN];
|
||||
|
||||
typedef struct {
|
||||
void* heap;
|
||||
word32 kem;
|
||||
word32 kdf;
|
||||
word32 aead;
|
||||
word32 Nh;
|
||||
word32 Nk;
|
||||
word32 Nn;
|
||||
@@ -101,6 +90,9 @@ typedef struct {
|
||||
int kdf_digest;
|
||||
int kem_digest;
|
||||
int curve_id;
|
||||
word16 kem;
|
||||
word16 kdf;
|
||||
word16 aead;
|
||||
byte kem_suite_id[KEM_SUITE_ID_LEN];
|
||||
byte hpke_suite_id[HPKE_SUITE_ID_LEN];
|
||||
} Hpke;
|
||||
@@ -137,6 +129,11 @@ WOLFSSL_API int wc_HpkeOpenBase(Hpke* hpke, void* receiverKey,
|
||||
const byte* pubKey, word16 pubKeySz, byte* info, word32 infoSz, byte* aad,
|
||||
word32 aadSz, byte* ciphertext, word32 ctSz, byte* plaintext);
|
||||
|
||||
WOLFSSL_LOCAL word16 wc_HpkeKemGetEncLen(word16 kemId);
|
||||
WOLFSSL_LOCAL int wc_HpkeKemIsSupported(word16 kemId);
|
||||
WOLFSSL_LOCAL int wc_HpkeKdfIsSupported(word16 kdfId);
|
||||
WOLFSSL_LOCAL int wc_HpkeAeadIsSupported(word16 aeadId);
|
||||
|
||||
#endif
|
||||
|
||||
#endif /* HAVE_HPKE && HAVE_ECC */
|
||||
|
||||
Reference in New Issue
Block a user