add functions for using an hpke context multiple times

This commit is contained in:
John Bland
2023-09-23 18:16:06 -04:00
parent faeae02030
commit 34d7229d4e
3 changed files with 179 additions and 44 deletions

View File

@ -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;
}

View File

@ -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

View File

@ -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);