From 34d7229d4ea09f43dd83dfca64cae26dd4b0e45a Mon Sep 17 00:00:00 2001 From: John Bland Date: Sat, 23 Sep 2023 18:16:06 -0400 Subject: [PATCH] add functions for using an hpke context multiple times --- wolfcrypt/src/hpke.c | 89 ++++++++++++++++++---------- wolfcrypt/test/test.c | 125 +++++++++++++++++++++++++++++++++++---- wolfssl/wolfcrypt/hpke.h | 9 +++ 3 files changed, 179 insertions(+), 44 deletions(-) diff --git a/wolfcrypt/src/hpke.c b/wolfcrypt/src/hpke.c index 15e8d8569..6502d3bd8 100644 --- a/wolfcrypt/src/hpke.c +++ b/wolfcrypt/src/hpke.c @@ -875,49 +875,63 @@ static int wc_HpkeSetupBaseSender(Hpke* hpke, HpkeBaseContext* context, return ret; } +/* give SetupBaseSender a more intuitive and wolfCrypt friendly name */ +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)) { + return BAD_FUNC_ARG; + } + + /* zero out all fields */ + XMEMSET(context, 0, sizeof(HpkeBaseContext)); + + return wc_HpkeSetupBaseSender(hpke, context, ephemeralKey, receiverKey, + info, infoSz); +} + /* encrypt a message using an hpke base context, return 0 or error */ -static int wc_HpkeContextSealBase(Hpke* hpke, HpkeBaseContext* context, +int wc_HpkeContextSealBase(Hpke* hpke, HpkeBaseContext* context, byte* aad, word32 aadSz, byte* plaintext, word32 ptSz, byte* out) { int ret; byte nonce[HPKE_Nn_MAX]; #ifndef WOLFSSL_SMALL_STACK - Aes aes_key[1]; + Aes aes[1]; #else - Aes* aes_key; + Aes* aes; #endif - - if (hpke == NULL) { + if (hpke == NULL || context == NULL || (aad == NULL && aadSz > 0) || + plaintext == NULL || out == NULL) { return BAD_FUNC_ARG; } - #ifdef WOLFSSL_SMALL_STACK - aes_key = (Aes*)XMALLOC(sizeof(Aes), hpke->heap, DYNAMIC_TYPE_AES); - if (aes_key == NULL) { + aes = (Aes*)XMALLOC(sizeof(Aes), hpke->heap, DYNAMIC_TYPE_AES); + if (aes == NULL) { return MEMORY_E; } #endif - - ret = wc_AesInit(aes_key, hpke->heap, INVALID_DEVID); + ret = wc_AesInit(aes, hpke->heap, INVALID_DEVID); if (ret == 0) { + /* compute nonce */ ret = wc_HpkeContextComputeNonce(hpke, context, nonce); if (ret == 0) { - ret = wc_AesGcmSetKey(aes_key, context->key, hpke->Nk); + ret = wc_AesGcmSetKey(aes, context->key, hpke->Nk); } if (ret == 0) { - ret = wc_AesGcmEncrypt(aes_key, out, plaintext, ptSz, nonce, + ret = wc_AesGcmEncrypt(aes, out, plaintext, ptSz, nonce, hpke->Nn, out + ptSz, hpke->Nt, aad, aadSz); } + /* increment sequence for non one shot */ if (ret == 0) { context->seq++; } - wc_AesFree(aes_key); + wc_AesFree(aes); } - #ifdef WOLFSSL_SMALL_STACK - XFREE(aes_key, hpke->heap, DYNAMIC_TYPE_AES); + XFREE(aes, hpke->heap, DYNAMIC_TYPE_AES); #endif - return ret; } @@ -1111,49 +1125,60 @@ static int wc_HpkeSetupBaseReceiver(Hpke* hpke, HpkeBaseContext* context, return ret; } +/* give SetupBaseReceiver a more intuitive and wolfCrypt friendly name */ +int wc_HpkeInitOpenContext(Hpke* hpke, HpkeBaseContext* context, + void* receiverKey, const byte* pubKey, word16 pubKeySz, byte* info, + word32 infoSz) +{ + if (hpke == NULL || context == NULL || receiverKey == NULL || pubKey == NULL + || (info == NULL && infoSz > 0)) { + return BAD_FUNC_ARG; + } + + return wc_HpkeSetupBaseReceiver(hpke, context, receiverKey, pubKey, + pubKeySz, info, infoSz); +} + /* decrypt a message using a setup hpke context, return 0 or error */ -static int wc_HpkeContextOpenBase(Hpke* hpke, HpkeBaseContext* context, - byte* aad, word32 aadSz, byte* ciphertext, word32 ctSz, byte* out) +int wc_HpkeContextOpenBase(Hpke* hpke, HpkeBaseContext* context, byte* aad, + word32 aadSz, byte* ciphertext, word32 ctSz, byte* out) { int ret; byte nonce[HPKE_Nn_MAX]; #ifndef WOLFSSL_SMALL_STACK - Aes aes_key[1]; + Aes aes[1]; #else - Aes* aes_key; + Aes* aes; #endif - if (hpke == NULL) { return BAD_FUNC_ARG; } - XMEMSET(nonce, 0, sizeof(nonce)); #ifdef WOLFSSL_SMALL_STACK - aes_key = (Aes*)XMALLOC(sizeof(Aes), hpke->heap, DYNAMIC_TYPE_AES); - if (aes_key == NULL) { + aes = (Aes*)XMALLOC(sizeof(Aes), hpke->heap, DYNAMIC_TYPE_AES); + if (aes == NULL) { return MEMORY_E; } #endif - + /* compute nonce */ ret = wc_HpkeContextComputeNonce(hpke, context, nonce); if (ret == 0) - ret = wc_AesInit(aes_key, hpke->heap, INVALID_DEVID); + ret = wc_AesInit(aes, hpke->heap, INVALID_DEVID); if (ret == 0) { - ret = wc_AesGcmSetKey(aes_key, context->key, hpke->Nk); + ret = wc_AesGcmSetKey(aes, context->key, hpke->Nk); if (ret == 0) { - ret = wc_AesGcmDecrypt(aes_key, out, ciphertext, ctSz, nonce, + ret = wc_AesGcmDecrypt(aes, out, ciphertext, ctSz, nonce, hpke->Nn, ciphertext + ctSz, hpke->Nt, aad, aadSz); } + /* increment sequence for non one shot */ if (ret == 0) { context->seq++; } - wc_AesFree(aes_key); + wc_AesFree(aes); } - #ifdef WOLFSSL_SMALL_STACK - XFREE(aes_key, hpke->heap, DYNAMIC_TYPE_AES); + XFREE(aes, hpke->heap, DYNAMIC_TYPE_AES); #endif - return ret; } diff --git a/wolfcrypt/test/test.c b/wolfcrypt/test/test.c index f8bab002b..a43abeaa4 100644 --- a/wolfcrypt/test/test.c +++ b/wolfcrypt/test/test.c @@ -25309,6 +25309,106 @@ static wc_test_ret_t hpke_test_single(Hpke* hpke) return ret; } +static wc_test_ret_t hpke_test_multi(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 ciphertexts[2][MAX_HPKE_LABEL_SZ]; + byte plaintext[MAX_HPKE_LABEL_SZ]; + void* receiverKey = NULL; + void* ephemeralKey = NULL; +#ifdef WOLFSSL_SMALL_STACK + HpkeBaseContext* context = NULL; + byte *pubKey = NULL; /* public key */ + word16 pubKeySz = (word16)HPKE_Npk_MAX; +#else + HpkeBaseContext context[1]; + byte pubKey[HPKE_Npk_MAX]; /* public key */ + word16 pubKeySz = (word16)sizeof(pubKey); +#endif + rngRet = ret = wc_InitRng(rng); + if (ret != 0) + return ret; +#ifdef WOLFSSL_SMALL_STACK + pubKey = (byte *)XMALLOC(pubKeySz, HEAP_HINT, DYNAMIC_TYPE_TMP_BUFFER); + if (pubKey == NULL) + ret = MEMORY_E; + if (ret == 0) { + context = (HpkeBaseContext*)XMALLOC(sizeof(HpkeBaseContext), HEAP_HINT, + DYNAMIC_TYPE_TMP_BUFFER); + } + if (context == NULL) + ret = MEMORY_E; +#endif + /* generate the keys */ + if (ret == 0) + ret = wc_HpkeGenerateKeyPair(hpke, &ephemeralKey, rng); + if (ret == 0) + ret = wc_HpkeGenerateKeyPair(hpke, &receiverKey, rng); + /* setup seal context */ + if (ret == 0) { + ret = wc_HpkeInitSealContext(hpke, context, ephemeralKey, receiverKey, + (byte*)info_text, (word32)XSTRLEN(info_text)); + } + /* seal message 0 */ + if (ret == 0) { + ret = wc_HpkeContextSealBase(hpke, context, + (byte*)aad_text, (word32)XSTRLEN(aad_text), + (byte*)start_text, (word32)XSTRLEN(start_text), + ciphertexts[context->seq]); + } + /* seal message 1 */ + if (ret == 0) { + ret = wc_HpkeContextSealBase(hpke, context, + (byte*)aad_text, (word32)XSTRLEN(aad_text), + (byte*)start_text, (word32)XSTRLEN(start_text), + ciphertexts[context->seq]); + } + /* export ephemeral key */ + if (ret == 0) + ret = wc_HpkeSerializePublicKey(hpke, ephemeralKey, pubKey, &pubKeySz); + /* setup open context */ + if (ret == 0) { + ret = wc_HpkeInitOpenContext(hpke, context, receiverKey, pubKey, + pubKeySz, (byte*)info_text, (word32)XSTRLEN(info_text)); + } + /* open message 0 */ + if (ret == 0) { + ret = wc_HpkeContextOpenBase(hpke, context, (byte*)aad_text, + (word32)XSTRLEN(aad_text), ciphertexts[context->seq], + (word32)XSTRLEN(start_text), plaintext); + } + /* check message 0 */ + if (ret == 0) + ret = XMEMCMP(plaintext, start_text, XSTRLEN(start_text)); + /* open message 1 */ + if (ret == 0) { + ret = wc_HpkeContextOpenBase(hpke, context, (byte*)aad_text, + (word32)XSTRLEN(aad_text), ciphertexts[context->seq], + (word32)XSTRLEN(start_text), plaintext); + } + /* check message 1 */ + if (ret == 0) + ret = XMEMCMP(plaintext, start_text, XSTRLEN(start_text)); + if (ephemeralKey != NULL) + wc_HpkeFreeKey(hpke, hpke->kem, ephemeralKey, hpke->heap); + if (receiverKey != NULL) + wc_HpkeFreeKey(hpke, hpke->kem, receiverKey, hpke->heap); +#ifdef WOLFSSL_SMALL_STACK + if (pubKey != NULL) + XFREE(pubKey, HEAP_HINT, DYNAMIC_TYPE_TMP_BUFFER); + if (context != NULL) + XFREE(context, HEAP_HINT, DYNAMIC_TYPE_TMP_BUFFER); +#endif + if (rngRet == 0) + wc_FreeRng(rng); + return ret; +} + WOLFSSL_TEST_SUBROUTINE wc_test_ret_t hpke_test(void) { wc_test_ret_t ret = 0; @@ -25319,14 +25419,15 @@ WOLFSSL_TEST_SUBROUTINE wc_test_ret_t hpke_test(void) /* p256 */ 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_single(hpke); - if (ret != 0) return ret; + ret = hpke_test_multi(hpke); + if (ret != 0) + return ret; + #endif #if defined(WOLFSSL_SHA384) && \ @@ -25334,12 +25435,12 @@ WOLFSSL_TEST_SUBROUTINE wc_test_ret_t hpke_test(void) /* p384 */ ret = wc_HpkeInit(hpke, DHKEM_P384_HKDF_SHA384, HKDF_SHA384, HPKE_AES_128_GCM, NULL); - if (ret != 0) return WC_TEST_RET_ENC_EC(ret); - ret = hpke_test_single(hpke); - + if (ret != 0) + return ret; + ret = hpke_test_multi(hpke); if (ret != 0) return ret; #endif @@ -25349,12 +25450,12 @@ WOLFSSL_TEST_SUBROUTINE wc_test_ret_t hpke_test(void) /* p521 */ ret = wc_HpkeInit(hpke, DHKEM_P521_HKDF_SHA512, HKDF_SHA512, HPKE_AES_128_GCM, NULL); - if (ret != 0) return WC_TEST_RET_ENC_EC(ret); - ret = hpke_test_single(hpke); - + if (ret != 0) + return ret; + ret = hpke_test_multi(hpke); if (ret != 0) return ret; #endif @@ -25364,12 +25465,12 @@ WOLFSSL_TEST_SUBROUTINE wc_test_ret_t hpke_test(void) /* test with curve25519 and aes256 */ ret = wc_HpkeInit(hpke, DHKEM_X25519_HKDF_SHA256, HKDF_SHA256, HPKE_AES_256_GCM, NULL); - if (ret != 0) return WC_TEST_RET_ENC_EC(ret); - ret = hpke_test_single(hpke); - + if (ret != 0) + return ret; + ret = hpke_test_multi(hpke); if (ret != 0) return ret; #endif diff --git a/wolfssl/wolfcrypt/hpke.h b/wolfssl/wolfcrypt/hpke.h index 432f574da..3e6b43c37 100644 --- a/wolfssl/wolfcrypt/hpke.h +++ b/wolfssl/wolfcrypt/hpke.h @@ -120,9 +120,18 @@ WOLFSSL_API int wc_HpkeDeserializePublicKey(Hpke* hpke, void** key, const byte* in, word16 inSz); WOLFSSL_API void wc_HpkeFreeKey(Hpke* hpke, word16 kem, void* keypair, void* heap); +WOLFSSL_API int wc_HpkeInitSealContext(Hpke* hpke, HpkeBaseContext* context, + void* ephemeralKey, void* receiverKey, byte* info, word32 infoSz); +WOLFSSL_API int wc_HpkeContextSealBase(Hpke* hpke, HpkeBaseContext* context, + byte* aad, word32 aadSz, byte* plaintext, word32 ptSz, byte* out); WOLFSSL_API int wc_HpkeSealBase(Hpke* hpke, void* ephemeralKey, void* receiverKey, byte* info, word32 infoSz, byte* aad, word32 aadSz, byte* plaintext, word32 ptSz, byte* ciphertext); +WOLFSSL_API int wc_HpkeInitOpenContext(Hpke* hpke, HpkeBaseContext* context, + void* receiverKey, const byte* pubKey, word16 pubKeySz, byte* info, + word32 infoSz); +WOLFSSL_API int wc_HpkeContextOpenBase(Hpke* hpke, HpkeBaseContext* context, + byte* aad, word32 aadSz, byte* ciphertext, word32 ctSz, byte* out); 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);