From 9f2ff95210997d160e73ec5eebaa6c4583a178eb Mon Sep 17 00:00:00 2001 From: sebastian-carpenter Date: Fri, 27 Mar 2026 10:56:50 -0600 Subject: [PATCH 1/7] increase TLS ECH inner hello lengths to word32 --- src/tls.c | 8 +++++--- src/tls13.c | 4 ++-- wolfssl/internal.h | 4 ++-- 3 files changed, 9 insertions(+), 7 deletions(-) diff --git a/src/tls.c b/src/tls.c index 535b43826b..a75c0daea7 100644 --- a/src/tls.c +++ b/src/tls.c @@ -13673,7 +13673,7 @@ static int TLSX_ECH_Write(WOLFSSL_ECH* ech, byte msgType, byte* writeBuf, writeBuf_p += ech->encLen; } /* innerClientHelloLen */ - c16toa(ech->innerClientHelloLen, writeBuf_p); + c16toa((word16)ech->innerClientHelloLen, writeBuf_p); writeBuf_p += 2; /* set payload offset for when we finalize */ ech->outerClientPayload = writeBuf_p; @@ -14132,7 +14132,7 @@ static int TLSX_ECH_ExpandOuterExtensions(WOLFSSL* ssl, WOLFSSL_ECH* ech, if (ret == 0) { XFREE(ech->innerClientHello, heap, DYNAMIC_TYPE_TMP_BUFFER); ech->innerClientHello = newInnerCh; - ech->innerClientHelloLen = (word16)newInnerChLen; + ech->innerClientHelloLen = newInnerChLen; newInnerCh = NULL; } @@ -14246,6 +14246,7 @@ static int TLSX_ECH_Parse(WOLFSSL* ssl, const byte* readBuf, word16 size, word32 offset = 0; word16 len; word16 tmpVal16; + word16 lenCh; WOLFSSL_MSG("TLSX_ECH_Parse"); if (ssl->options.disableECH) { @@ -14362,7 +14363,8 @@ static int TLSX_ECH_Parse(WOLFSSL* ssl, const byte* readBuf, word16 size, readBuf_p += len; offset += len; /* read payload (encrypted CH) len */ - ato16(readBuf_p, &ech->innerClientHelloLen); + ato16(readBuf_p, &lenCh); + ech->innerClientHelloLen = lenCh; readBuf_p += 2; offset += 2; /* Check payload is no bigger than remaining bytes. */ diff --git a/src/tls13.c b/src/tls13.c index e63e824d79..afaf125a71 100644 --- a/src/tls13.c +++ b/src/tls13.c @@ -4724,8 +4724,8 @@ int SendTls13ClientHello(WOLFSSL* ssl) args->ech->type = 0; /* set innerClientHelloLen to ClientHelloInner + padding + tag */ args->ech->paddingLen = 31 - ((args->length - 1) % 32); - args->ech->innerClientHelloLen = (word16)(args->length + - args->ech->paddingLen + args->ech->hpke->Nt); + args->ech->innerClientHelloLen = args->length + + args->ech->paddingLen + args->ech->hpke->Nt; /* set the length back to before we computed ClientHelloInner size */ args->length = (word32)args->preXLength; } diff --git a/wolfssl/internal.h b/wolfssl/internal.h index e12bdc1239..0955781b8a 100644 --- a/wolfssl/internal.h +++ b/wolfssl/internal.h @@ -3135,9 +3135,9 @@ typedef struct WOLFSSL_ECH { byte* outerClientPayload; byte* confBuf; EchCipherSuite cipherSuite; - word16 aadLen; + word32 aadLen; + word32 innerClientHelloLen; word16 paddingLen; - word16 innerClientHelloLen; word16 kemId; word16 encLen; EchState state; From d754c573aa5c5bb7659f97ed79ab8ef6a1cc6b1c Mon Sep 17 00:00:00 2001 From: sebastian-carpenter Date: Fri, 27 Mar 2026 11:37:28 -0600 Subject: [PATCH 2/7] improve GetMsgHash error checks --- src/tls13.c | 13 +++++++++++-- 1 file changed, 11 insertions(+), 2 deletions(-) diff --git a/src/tls13.c b/src/tls13.c index afaf125a71..77bdcb8b59 100644 --- a/src/tls13.c +++ b/src/tls13.c @@ -3907,10 +3907,14 @@ static int EchCalcAcceptance(WOLFSSL* ssl, byte* label, word16 labelSz, if (isHrr) { /* the transcript hash of ClientHelloInner1 */ - hashSz = GetMsgHash(ssl, clientHelloInnerHash); - if (hashSz > 0) { + ret = GetMsgHash(ssl, clientHelloInnerHash); + if (ret > 0) { + hashSz = ret; ret = 0; } + else if (ret == 0) { + ret = HASH_TYPE_E; + } /* restart ECH transcript hash, similar to RestartHandshakeHash but * don't add a cookie */ @@ -3950,6 +3954,9 @@ static int EchCalcAcceptance(WOLFSSL* ssl, byte* label, word16 labelSz, if (ret > 0) { ret = 0; } + else if (ret == 0) { + ret = HASH_TYPE_E; + } } /* pick the right type and size based on mac_algorithm */ @@ -8563,6 +8570,8 @@ int CreateSigData(WOLFSSL* ssl, byte* sigData, word16* sigDataSz, ret = GetMsgHash(ssl, &sigData[idx]); if (ret < 0) return ret; + if (ret == 0) + return HASH_TYPE_E; *sigDataSz = (word16)(idx + ret); ret = 0; From 85485528b352488a76ca48ea38c32842ce21cf27 Mon Sep 17 00:00:00 2001 From: sebastian-carpenter Date: Fri, 27 Mar 2026 13:21:56 -0600 Subject: [PATCH 3/7] add null check --- src/tls13.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/src/tls13.c b/src/tls13.c index 77bdcb8b59..7801a0381e 100644 --- a/src/tls13.c +++ b/src/tls13.c @@ -5657,6 +5657,9 @@ int DoTls13ServerHello(WOLFSSL* ssl, const byte* input, word32* inOutIdx, /* check for acceptConfirmation */ if (ssl->echConfigs != NULL && !ssl->options.disableECH) { args->echX = TLSX_Find(ssl->extensions, TLSX_ECH); + if (args->echX == NULL || args->echX->data == NULL) + return WOLFSSL_FATAL_ERROR; + /* account for hrr extension instead of server random */ if (args->extMsgType == hello_retry_request) { args->acceptOffset = From 98a0f9268e03e5d84504ab62f3838a227b30c82e Mon Sep 17 00:00:00 2001 From: sebastian-carpenter Date: Fri, 27 Mar 2026 13:22:28 -0600 Subject: [PATCH 4/7] mirror arg requirements from wc_HpkeContextSealBase --- wolfcrypt/src/hpke.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/wolfcrypt/src/hpke.c b/wolfcrypt/src/hpke.c index c83158d4f6..52f2ad8fd7 100644 --- a/wolfcrypt/src/hpke.c +++ b/wolfcrypt/src/hpke.c @@ -1175,7 +1175,8 @@ int wc_HpkeContextOpenBase(Hpke* hpke, HpkeBaseContext* context, byte* aad, int ret; byte nonce[HPKE_Nn_MAX]; WC_DECLARE_VAR(aes, Aes, 1, 0); - if (hpke == NULL) { + if (hpke == NULL || context == NULL || (aad == NULL && aadSz > 0) || + ciphertext == NULL || out == NULL) { return BAD_FUNC_ARG; } From 166ed817541eaf25355c396ca5830d688bff1140 Mon Sep 17 00:00:00 2001 From: sebastian-carpenter Date: Fri, 27 Mar 2026 13:50:30 -0600 Subject: [PATCH 5/7] fixing bad state for ech->type --- src/tls13.c | 12 ++++++++---- 1 file changed, 8 insertions(+), 4 deletions(-) diff --git a/src/tls13.c b/src/tls13.c index 7801a0381e..482b3636b2 100644 --- a/src/tls13.c +++ b/src/tls13.c @@ -4874,8 +4874,10 @@ int SendTls13ClientHello(WOLFSSL* ssl) args->ech->innerClientHello = (byte*)XMALLOC(args->ech->innerClientHelloLen - args->ech->hpke->Nt, ssl->heap, DYNAMIC_TYPE_TMP_BUFFER); - if (args->ech->innerClientHello == NULL) + if (args->ech->innerClientHello == NULL) { + args->ech->type = ECH_TYPE_OUTER; return MEMORY_E; + } /* set the padding bytes to 0 */ XMEMSET(args->ech->innerClientHello + args->ech->innerClientHelloLen - args->ech->hpke->Nt - args->ech->paddingLen, 0, @@ -4898,8 +4900,10 @@ int SendTls13ClientHello(WOLFSSL* ssl) /* change the outer client random */ ret = wc_RNG_GenerateBlock(ssl->rng, args->output + args->clientRandomOffset, RAN_LEN); - if (ret != 0) + if (ret != 0) { + args->ech->type = ECH_TYPE_OUTER; return ret; + } /* copy the new client random */ XMEMCPY(ssl->arrays->clientRandom, args->output + args->clientRandomOffset, RAN_LEN); @@ -4908,10 +4912,10 @@ int SendTls13ClientHello(WOLFSSL* ssl) ret = TLSX_WriteRequest(ssl, args->ech->innerClientHello + args->idx - (RECORD_HEADER_SZ + HANDSHAKE_HEADER_SZ), client_hello, &args->length); + /* set the type to outer */ + args->ech->type = ECH_TYPE_OUTER; if (ret != 0) return ret; - /* set the type to outer */ - args->ech->type = 0; } #endif From 1f5fca53fa2e58611758aa680a1b9cad1a4ae660 Mon Sep 17 00:00:00 2001 From: sebastian-carpenter Date: Fri, 27 Mar 2026 14:19:58 -0600 Subject: [PATCH 6/7] faster key length validation when setting configs --- src/ssl_ech.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/ssl_ech.c b/src/ssl_ech.c index eb9b9a6a5a..bb456cc456 100644 --- a/src/ssl_ech.c +++ b/src/ssl_ech.c @@ -548,7 +548,8 @@ int SetEchConfigsEx(WOLFSSL_EchConfig** outputConfigs, void* heap, echConfig += 2; /* hpke public_key */ - if (hpkePubkeyLen > HPKE_Npk_MAX || hpkePubkeyLen == 0) { + if (hpkePubkeyLen > HPKE_Npk_MAX || + hpkePubkeyLen != wc_HpkeKemGetEncLen(workingConfig->kemId)) { ret = BUFFER_E; break; } From 384c378572015e0dfcf509caebd4f0e849af7b99 Mon Sep 17 00:00:00 2001 From: sebastian-carpenter Date: Mon, 30 Mar 2026 13:36:50 -0600 Subject: [PATCH 7/7] hpke testing - broke api testing into a different function --- wolfcrypt/src/hpke.c | 8 +- wolfcrypt/test/test.c | 323 ++++++++++++++++++++++++++++++++++++++++-- 2 files changed, 313 insertions(+), 18 deletions(-) diff --git a/wolfcrypt/src/hpke.c b/wolfcrypt/src/hpke.c index 52f2ad8fd7..0c1037325d 100644 --- a/wolfcrypt/src/hpke.c +++ b/wolfcrypt/src/hpke.c @@ -917,7 +917,7 @@ int wc_HpkeInitSealContext(Hpke* hpke, HpkeBaseContext* context, void* ephemeralKey, void* receiverKey, byte* info, word32 infoSz) { if (hpke == NULL || context == NULL || ephemeralKey == NULL || - receiverKey == NULL || (info == NULL && infoSz > 0)) { + receiverKey == NULL || (info == NULL && infoSz != 0)) { return BAD_FUNC_ARG; } @@ -935,7 +935,7 @@ int wc_HpkeContextSealBase(Hpke* hpke, HpkeBaseContext* context, int ret; byte nonce[HPKE_Nn_MAX]; WC_DECLARE_VAR(aes, Aes, 1, 0); - if (hpke == NULL || context == NULL || (aad == NULL && aadSz > 0) || + if (hpke == NULL || context == NULL || (aad == NULL && aadSz != 0) || plaintext == NULL || out == NULL) { return BAD_FUNC_ARG; } @@ -1160,7 +1160,7 @@ int wc_HpkeInitOpenContext(Hpke* hpke, HpkeBaseContext* context, word32 infoSz) { if (hpke == NULL || context == NULL || receiverKey == NULL || pubKey == NULL - || (info == NULL && infoSz > 0)) { + || (info == NULL && infoSz != 0)) { return BAD_FUNC_ARG; } @@ -1175,7 +1175,7 @@ int wc_HpkeContextOpenBase(Hpke* hpke, HpkeBaseContext* context, byte* aad, int ret; byte nonce[HPKE_Nn_MAX]; WC_DECLARE_VAR(aes, Aes, 1, 0); - if (hpke == NULL || context == NULL || (aad == NULL && aadSz > 0) || + if (hpke == NULL || context == NULL || (aad == NULL && aadSz != 0) || ciphertext == NULL || out == NULL) { return BAD_FUNC_ARG; } diff --git a/wolfcrypt/test/test.c b/wolfcrypt/test/test.c index 8d0780c0a2..57b613be49 100644 --- a/wolfcrypt/test/test.c +++ b/wolfcrypt/test/test.c @@ -32000,7 +32000,9 @@ WOLFSSL_TEST_SUBROUTINE wc_test_ret_t x963kdf_test(void) defined(HAVE_CURVE448)) && \ defined(HAVE_AESGCM) -static wc_test_ret_t hpke_test_single(Hpke* hpke) +#if defined(HAVE_ECC) && defined(WOLFSSL_AES_128) && \ + (!defined(NO_ECC256) || defined(HAVE_ALL_CURVES)) && !defined(NO_SHA256) +static wc_test_ret_t hpke_test_api(Hpke* hpke) { wc_test_ret_t ret = 0; int rngRet = 0; @@ -32034,6 +32036,29 @@ static wc_test_ret_t hpke_test_single(Hpke* hpke) } #endif + /* Negative test case with NULL argument */ + if (ret == 0) { + ret = wc_HpkeGenerateKeyPair(NULL, &receiverKey, rng); + if (ret != WC_NO_ERR_TRACE(BAD_FUNC_ARG)) + ret = WC_TEST_RET_ENC_EC(ret); + else + ret = 0; + } + if (ret == 0) { + ret = wc_HpkeGenerateKeyPair(hpke, NULL, rng); + if (ret != WC_NO_ERR_TRACE(BAD_FUNC_ARG)) + ret = WC_TEST_RET_ENC_EC(ret); + else + ret = 0; + } + if (ret == 0) { + ret = wc_HpkeGenerateKeyPair(hpke, &receiverKey, NULL); + if (ret != WC_NO_ERR_TRACE(BAD_FUNC_ARG)) + ret = WC_TEST_RET_ENC_EC(ret); + else + ret = 0; + } + /* generate the keys */ if (ret == 0) { ret = wc_HpkeGenerateKeyPair(hpke, &ephemeralKey, rng); @@ -32047,6 +32072,85 @@ static wc_test_ret_t hpke_test_single(Hpke* hpke) ret = WC_TEST_RET_ENC_EC(ret); } + /* Negative test case with NULL argument */ + if (ret == 0) { + ret = wc_HpkeSealBase(NULL, ephemeralKey, receiverKey, + (byte*)info_text, (word32)XSTRLEN(info_text), + (byte*)aad_text, (word32)XSTRLEN(aad_text), + (byte*)start_text, (word32)XSTRLEN(start_text), + ciphertext); + if (ret != WC_NO_ERR_TRACE(BAD_FUNC_ARG)) + ret = WC_TEST_RET_ENC_EC(ret); + else + ret = 0; + } + if (ret == 0) { + ret = wc_HpkeSealBase(hpke, NULL, receiverKey, + (byte*)info_text, (word32)XSTRLEN(info_text), + (byte*)aad_text, (word32)XSTRLEN(aad_text), + (byte*)start_text, (word32)XSTRLEN(start_text), + ciphertext); + if (ret != WC_NO_ERR_TRACE(BAD_FUNC_ARG)) + ret = WC_TEST_RET_ENC_EC(ret); + else + ret = 0; + } + if (ret == 0) { + ret = wc_HpkeSealBase(hpke, ephemeralKey, NULL, + (byte*)info_text, (word32)XSTRLEN(info_text), + (byte*)aad_text, (word32)XSTRLEN(aad_text), + (byte*)start_text, (word32)XSTRLEN(start_text), + ciphertext); + if (ret != WC_NO_ERR_TRACE(BAD_FUNC_ARG)) + ret = WC_TEST_RET_ENC_EC(ret); + else + ret = 0; + } + if (ret == 0) { + ret = wc_HpkeSealBase(hpke, ephemeralKey, receiverKey, + (byte*)NULL, (word32)XSTRLEN(info_text), + (byte*)aad_text, (word32)XSTRLEN(aad_text), + (byte*)start_text, (word32)XSTRLEN(start_text), + ciphertext); + if (ret != WC_NO_ERR_TRACE(BAD_FUNC_ARG)) + ret = WC_TEST_RET_ENC_EC(ret); + else + ret = 0; + } + if (ret == 0) { + ret = wc_HpkeSealBase(hpke, ephemeralKey, receiverKey, + (byte*)info_text, (word32)XSTRLEN(info_text), + (byte*)NULL, (word32)XSTRLEN(aad_text), + (byte*)start_text, (word32)XSTRLEN(start_text), + ciphertext); + if (ret != WC_NO_ERR_TRACE(BAD_FUNC_ARG)) + ret = WC_TEST_RET_ENC_EC(ret); + else + ret = 0; + } + if (ret == 0) { + ret = wc_HpkeSealBase(hpke, ephemeralKey, receiverKey, + (byte*)info_text, (word32)XSTRLEN(info_text), + (byte*)aad_text, (word32)XSTRLEN(aad_text), + (byte*)NULL, (word32)XSTRLEN(start_text), + ciphertext); + if (ret != WC_NO_ERR_TRACE(BAD_FUNC_ARG)) + ret = WC_TEST_RET_ENC_EC(ret); + else + ret = 0; + } + if (ret == 0) { + ret = wc_HpkeSealBase(hpke, ephemeralKey, receiverKey, + (byte*)info_text, (word32)XSTRLEN(info_text), + (byte*)aad_text, (word32)XSTRLEN(aad_text), + (byte*)start_text, (word32)XSTRLEN(start_text), + NULL); + if (ret != WC_NO_ERR_TRACE(BAD_FUNC_ARG)) + ret = WC_TEST_RET_ENC_EC(ret); + else + ret = 0; + } + /* seal */ if (ret == 0) { ret = wc_HpkeSealBase(hpke, ephemeralKey, receiverKey, @@ -32058,6 +32162,36 @@ static wc_test_ret_t hpke_test_single(Hpke* hpke) ret = WC_TEST_RET_ENC_EC(ret); } + /* Negative test case with NULL argument */ + if (ret == 0) { + ret = wc_HpkeSerializePublicKey(NULL, ephemeralKey, pubKey, &pubKeySz); + if (ret != WC_NO_ERR_TRACE(BAD_FUNC_ARG)) + ret = WC_TEST_RET_ENC_EC(ret); + else + ret = 0; + } + if (ret == 0) { + ret = wc_HpkeSerializePublicKey(hpke, NULL, pubKey, &pubKeySz); + if (ret != WC_NO_ERR_TRACE(BAD_FUNC_ARG)) + ret = WC_TEST_RET_ENC_EC(ret); + else + ret = 0; + } + if (ret == 0) { + ret = wc_HpkeSerializePublicKey(hpke, ephemeralKey, NULL, &pubKeySz); + if (ret != WC_NO_ERR_TRACE(BAD_FUNC_ARG)) + ret = WC_TEST_RET_ENC_EC(ret); + else + ret = 0; + } + if (ret == 0) { + ret = wc_HpkeSerializePublicKey(hpke, ephemeralKey, pubKey, NULL); + if (ret != WC_NO_ERR_TRACE(BAD_FUNC_ARG)) + ret = WC_TEST_RET_ENC_EC(ret); + else + ret = 0; + } + /* export ephemeral key */ if (ret == 0) { ret = wc_HpkeSerializePublicKey(hpke, ephemeralKey, pubKey, &pubKeySz); @@ -32065,6 +32199,85 @@ static wc_test_ret_t hpke_test_single(Hpke* hpke) ret = WC_TEST_RET_ENC_EC(ret); } + /* Negative test case with NULL argument */ + if (ret == 0) { + ret = wc_HpkeOpenBase(NULL, receiverKey, pubKey, pubKeySz, + (byte*)info_text, (word32)XSTRLEN(info_text), + (byte*)aad_text, (word32)XSTRLEN(aad_text), + ciphertext, (word32)XSTRLEN(start_text), + plaintext); + if (ret != WC_NO_ERR_TRACE(BAD_FUNC_ARG)) + ret = WC_TEST_RET_ENC_EC(ret); + else + ret = 0; + } + if (ret == 0) { + ret = wc_HpkeOpenBase(hpke, NULL, pubKey, pubKeySz, + (byte*)info_text, (word32)XSTRLEN(info_text), + (byte*)aad_text, (word32)XSTRLEN(aad_text), + ciphertext, (word32)XSTRLEN(start_text), + plaintext); + if (ret != WC_NO_ERR_TRACE(BAD_FUNC_ARG)) + ret = WC_TEST_RET_ENC_EC(ret); + else + ret = 0; + } + if (ret == 0) { + ret = wc_HpkeOpenBase(hpke, receiverKey, NULL, pubKeySz, + (byte*)info_text, (word32)XSTRLEN(info_text), + (byte*)aad_text, (word32)XSTRLEN(aad_text), + ciphertext, (word32)XSTRLEN(start_text), + plaintext); + if (ret != WC_NO_ERR_TRACE(BAD_FUNC_ARG)) + ret = WC_TEST_RET_ENC_EC(ret); + else + ret = 0; + } + if (ret == 0) { + ret = wc_HpkeOpenBase(hpke, receiverKey, pubKey, pubKeySz, + (byte*)NULL, (word32)XSTRLEN(info_text), + (byte*)aad_text, (word32)XSTRLEN(aad_text), + ciphertext, (word32)XSTRLEN(start_text), + plaintext); + if (ret != WC_NO_ERR_TRACE(BAD_FUNC_ARG)) + ret = WC_TEST_RET_ENC_EC(ret); + else + ret = 0; + } + if (ret == 0) { + ret = wc_HpkeOpenBase(hpke, receiverKey, pubKey, pubKeySz, + (byte*)info_text, (word32)XSTRLEN(info_text), + (byte*)NULL, (word32)XSTRLEN(aad_text), + ciphertext, (word32)XSTRLEN(start_text), + plaintext); + if (ret != WC_NO_ERR_TRACE(BAD_FUNC_ARG)) + ret = WC_TEST_RET_ENC_EC(ret); + else + ret = 0; + } + if (ret == 0) { + ret = wc_HpkeOpenBase(hpke, receiverKey, pubKey, pubKeySz, + (byte*)info_text, (word32)XSTRLEN(info_text), + (byte*)aad_text, (word32)XSTRLEN(aad_text), + NULL, (word32)XSTRLEN(start_text), + plaintext); + if (ret != WC_NO_ERR_TRACE(BAD_FUNC_ARG)) + ret = WC_TEST_RET_ENC_EC(ret); + else + ret = 0; + } + if (ret == 0) { + ret = wc_HpkeOpenBase(hpke, receiverKey, pubKey, pubKeySz, + (byte*)info_text, (word32)XSTRLEN(info_text), + (byte*)aad_text, (word32)XSTRLEN(aad_text), + ciphertext, (word32)XSTRLEN(start_text), + NULL); + if (ret != WC_NO_ERR_TRACE(BAD_FUNC_ARG)) + ret = WC_TEST_RET_ENC_EC(ret); + else + ret = 0; + } + /* open with exported ephemeral key */ if (ret == 0) { ret = wc_HpkeOpenBase(hpke, receiverKey, pubKey, pubKeySz, @@ -32082,29 +32295,102 @@ static wc_test_ret_t hpke_test_single(Hpke* hpke) ret = WC_TEST_RET_ENC_NC; } - /* Negative test case with NULL argument */ + if (ephemeralKey != NULL) + wc_HpkeFreeKey(hpke, hpke->kem, ephemeralKey, hpke->heap); + + if (receiverKey != NULL) + wc_HpkeFreeKey(hpke, hpke->kem, receiverKey, hpke->heap); + + WC_FREE_VAR_EX(pubKey, HEAP_HINT, DYNAMIC_TYPE_TMP_BUFFER); + + if (rngRet == 0) + wc_FreeRng(rng); + + return ret; +} +#endif /* HAVE_ECC && WOLFSSL_AES_128 && (!NO_ECC256 || HAVE_ALL_CURVES) && + !NO_SHA256 */ + +static wc_test_ret_t hpke_test_single(Hpke* hpke) +{ + wc_test_ret_t ret = 0; + int rngRet = 0; + WC_RNG rng[1]; + const char* start_text = "this is a test"; + const char* info_text = "info"; + const char* aad_text = "aad"; + byte ciphertext[MAX_HPKE_LABEL_SZ]; + byte plaintext[MAX_HPKE_LABEL_SZ]; + void* receiverKey = NULL; + void* ephemeralKey = NULL; +#ifdef WOLFSSL_SMALL_STACK + byte *pubKey = NULL; /* public key */ + word16 pubKeySz = (word16)HPKE_Npk_MAX; +#else + byte pubKey[HPKE_Npk_MAX]; /* public key */ + word16 pubKeySz = (word16)sizeof(pubKey); +#endif + + rngRet = ret = wc_InitRng(rng); + + if (ret != 0) + return WC_TEST_RET_ENC_EC(ret); + +#ifdef WOLFSSL_SMALL_STACK if (ret == 0) { - ret = wc_HpkeGenerateKeyPair(NULL, &receiverKey, rng); - if (ret != WC_NO_ERR_TRACE(BAD_FUNC_ARG)) + pubKey = (byte *)XMALLOC(pubKeySz, HEAP_HINT, + DYNAMIC_TYPE_TMP_BUFFER); + if (pubKey == NULL) + ret = WC_TEST_RET_ENC_EC(MEMORY_E); + } +#endif + + /* generate the keys */ + if (ret == 0) { + ret = wc_HpkeGenerateKeyPair(hpke, &ephemeralKey, rng); + if (ret != 0) ret = WC_TEST_RET_ENC_EC(ret); - else - ret = 0; } if (ret == 0) { - ret = wc_HpkeGenerateKeyPair(hpke, NULL, rng); - if (ret != WC_NO_ERR_TRACE(BAD_FUNC_ARG)) + ret = wc_HpkeGenerateKeyPair(hpke, &receiverKey, rng); + if (ret != 0) ret = WC_TEST_RET_ENC_EC(ret); - else - ret = 0; } + /* seal */ if (ret == 0) { - ret = wc_HpkeGenerateKeyPair(hpke, &receiverKey, NULL); - if (ret != WC_NO_ERR_TRACE(BAD_FUNC_ARG)) + ret = wc_HpkeSealBase(hpke, ephemeralKey, receiverKey, + (byte*)info_text, (word32)XSTRLEN(info_text), + (byte*)aad_text, (word32)XSTRLEN(aad_text), + (byte*)start_text, (word32)XSTRLEN(start_text), + ciphertext); + if (ret != 0) ret = WC_TEST_RET_ENC_EC(ret); - else - ret = 0; + } + + /* export ephemeral key */ + if (ret == 0) { + ret = wc_HpkeSerializePublicKey(hpke, ephemeralKey, pubKey, &pubKeySz); + if (ret != 0) + ret = WC_TEST_RET_ENC_EC(ret); + } + + /* open with exported ephemeral key */ + if (ret == 0) { + ret = wc_HpkeOpenBase(hpke, receiverKey, pubKey, pubKeySz, + (byte*)info_text, (word32)XSTRLEN(info_text), + (byte*)aad_text, (word32)XSTRLEN(aad_text), + ciphertext, (word32)XSTRLEN(start_text), + plaintext); + if (ret != 0) + ret = WC_TEST_RET_ENC_EC(ret); + } + + if (ret == 0) { + ret = XMEMCMP(plaintext, start_text, XSTRLEN(start_text)); + if (ret != 0) + ret = WC_TEST_RET_ENC_NC; } if (ephemeralKey != NULL) @@ -32229,6 +32515,15 @@ WOLFSSL_TEST_SUBROUTINE wc_test_ret_t hpke_test(void) #if defined(HAVE_ECC) && defined(WOLFSSL_AES_128) #if (!defined(NO_ECC256) || defined(HAVE_ALL_CURVES)) && !defined(NO_SHA256) + /* p256 but this will only test the api */ + ret = wc_HpkeInit(hpke, DHKEM_P256_HKDF_SHA256, HKDF_SHA256, + HPKE_AES_128_GCM, NULL); + if (ret != 0) + return WC_TEST_RET_ENC_EC(ret); + ret = hpke_test_api(hpke); + if (ret != 0) + return ret; + /* p256 */ ret = wc_HpkeInit(hpke, DHKEM_P256_HKDF_SHA256, HKDF_SHA256, HPKE_AES_128_GCM, NULL);