From 6bbcc7a8d95cd55525ffa0af503a2a635463d877 Mon Sep 17 00:00:00 2001 From: John Bland Date: Wed, 21 Sep 2022 19:01:29 -0400 Subject: [PATCH] update hpke to compile and handle single shot... encryption and decryption with, currently hpke is missing x25519, x448, chacha20 and has a problem running in external applications with the public api functions being undefined when the application compiles, though it works fine with tests --- wolfcrypt/src/hpke.c | 894 +++++++++++++++++++++++++-------------- wolfcrypt/test/test.c | 35 +- wolfssl/wolfcrypt/hpke.h | 46 +- 3 files changed, 637 insertions(+), 338 deletions(-) diff --git a/wolfcrypt/src/hpke.c b/wolfcrypt/src/hpke.c index 5d857807f86..50214ce6d0e 100644 --- a/wolfcrypt/src/hpke.c +++ b/wolfcrypt/src/hpke.c @@ -24,158 +24,233 @@ #endif #include +#include #include +#include #include #include #include #include +#include -static void I2OSP(int n, int w, uint8_t* out) +static const char* KEM_STR = "KEM"; +static const int KEM_STR_LEN = 3; + +static const char* HPKE_STR = "HPKE"; +static const int HPKE_STR_LEN = 4; + +static const char* HPKE_VERSION_STR = "HPKE-v1"; +static const int HPKE_VERSION_STR_LEN = 7; + +static const char* EAE_PRK_LABEL_STR = "eae_prk"; +static const int EAE_PRK_LABEL_STR_LEN = 7; + +static const char* SHARED_SECRET_LABEL_STR = "shared_secret"; +static const int SHARED_SECRET_LABEL_STR_LEN = 13; + +static const char* PSK_ID_HASH_LABEL_STR = "psk_id_hash"; +static const int PSK_ID_HASH_LABEL_STR_LEN = 11; + +static const char* INFO_HASH_LABEL_STR = "info_hash"; +static const int INFO_HASH_LABEL_STR_LEN = 9; + +static const char* SECRET_LABEL_STR = "secret"; +static const int SECRET_LABEL_STR_LEN = 6; + +static const char* KEY_LABEL_STR = "key"; +static const int KEY_LABEL_STR_LEN = 3; + +static const char* BASE_NONCE_LABEL_STR = "base_nonce"; +static const int BASE_NONCE_LABEL_STR_LEN = 10; + +static const char* EXP_LABEL_STR = "exp"; +static const int EXP_LABEL_STR_LEN = 3; + +static int I2OSP(int n, int w, byte* out) { int i; - const int exp = 256; - if (w <= 0) { - return -1; + if (w <= 0 || w > 32) + { + return MP_VAL; } - for (i = 0; i < w; i++) { - exp *= 256; - } + // make sure the byte string is cleared + XMEMSET( out, 0, w ); - if (n >= exp) { - return -1; + // we're only concerned with up to integer max + if ((n > 256 && w < 2) || + (n > 65536 && w < 3) || + (n > 16777216 && w < 4)) + { + return MP_VAL; } - for (i = 0; i < w && n > 0; i++) { + for (i = 0; i < w && n > 0; i++) + { out[w - ( i + 1 )] = n % 256; n = n >> 8; } + + return 0; } int wc_HpkeInit(Hpke* hpke, int kem, int kdf, int aead, void* heap) { - /* TODO: Add argument NULL checking for public API's */ + int ret; + + if (hpke == NULL || kem == 0 || kdf == 0 || aead == 0) + { + return BAD_FUNC_ARG; + } hpke->kem = kem; hpke->kdf = kdf; hpke->aead = aead; + hpke->heap = heap; + + XMEMCPY(hpke->kem_suite_id, KEM_STR, KEM_STR_LEN); - XMEMCPY( hpke->kem_suite_id, "KEM", strlen( "KEM" ) ); - I2OSP( kem, 2, hpke->kem_suite_id + strlen( "KEM" ) ); - XMEMCPY( hpke->hpke_suite_id, "HPKE", strlen( "HPKE" ) ); - I2OSP( kem, 2, hpke->hpke_suite_id + strlen( "HPKE" ) ); - I2OSP( kdf, 2, hpke->hpke_suite_id + strlen( "HPKE" ) + 2 ); - I2OSP( aead, 2, hpke->hpke_suite_id + strlen( "HPKE" ) + 2 + 2 ); - - switch (kem) { - case DHKEM_P256_HKDF_SHA256: - hpke->Nsecret = 32; - hpke->Nh = 32; - hpke->Ndh = 32; - hpke->Npk = 65; - hpke->curve_id = ECC_SECP256R1; - break; - - case DHKEM_P384_HKDF_SHA384: - hpke->Nsecret = 48; - hpke->Nh = 48; - hpke->Ndh = 48; - hpke->Npk = 97; - hpke->curve_id = ECC_SECP384R1; - break; - - case DHKEM_P521_HKDF_SHA512: - hpke->Nsecret = 64; - hpke->Nh = 64; - hpke->Ndh = 66; - hpke->Npk = 133; - hpke->curve_id = ECC_SECP521R1; - break; - - case DHKEM_X25519_HKDF_SHA256: - hpke->Nsecret = 32; - hpke->Nh = 32; - hpke->Ndh = 32; - hpke->Npk = 32; - hpke->curve_id = ECC_X25519; - break; - - case DHKEM_X448_HKDF_SHA512: - hpke->Nsecret = 64; - hpke->Nh = 64; - hpke->Ndh = 64; - hpke->Npk = 56; - hpke->curve_id = ECC_X448; - break; - - default: - break; + ret = I2OSP(kem, 2, hpke->kem_suite_id + KEM_STR_LEN); + + XMEMCPY(hpke->hpke_suite_id, HPKE_STR, HPKE_STR_LEN); + + if (ret == 0) + ret = I2OSP(kem, 2, hpke->hpke_suite_id + HPKE_STR_LEN); + + if (ret == 0) + ret = I2OSP(kdf, 2, hpke->hpke_suite_id + HPKE_STR_LEN + 2); + + if (ret == 0) + ret = I2OSP(aead, 2, hpke->hpke_suite_id + HPKE_STR_LEN + 2 + 2); + + if (ret != 0) + return ret; + + switch (kem) + { + case DHKEM_P256_HKDF_SHA256: + hpke->Nsecret = 32; + hpke->Nh = 32; + hpke->Ndh = 32; + hpke->Npk = 65; + hpke->curve_id = ECC_SECP256R1; + break; + + case DHKEM_P384_HKDF_SHA384: + hpke->Nsecret = 48; + hpke->Nh = 48; + hpke->Ndh = 48; + hpke->Npk = 97; + hpke->curve_id = ECC_SECP384R1; + break; + + case DHKEM_P521_HKDF_SHA512: + hpke->Nsecret = 64; + hpke->Nh = 64; + hpke->Ndh = 66; + hpke->Npk = 133; + hpke->curve_id = ECC_SECP521R1; + break; + + case DHKEM_X25519_HKDF_SHA256: + hpke->Nsecret = 32; + hpke->Nh = 32; + hpke->Ndh = 32; + hpke->Npk = 32; + //hpke->curve_id = ECC_X25519; + break; + + case DHKEM_X448_HKDF_SHA512: + hpke->Nsecret = 64; + hpke->Nh = 64; + hpke->Ndh = 64; + hpke->Npk = 56; + //hpke->curve_id = ECC_X448; + break; + + default: + ret = BAD_FUNC_ARG; + break; } - switch (kdf) { - case HKDF_SHA256: - hpke->kdf_digest = WC_SHA256; - break; + switch (kdf) + { + case HKDF_SHA256: + hpke->kdf_digest = WC_SHA256; + break; - case HKDF_SHA384: - hpke->kdf_digest = WC_SHA384; - break; + case HKDF_SHA384: + hpke->kdf_digest = WC_SHA384; + break; - case HKDF_SHA512: - hpke->kdf_digest = WC_SHA512; - break; + case HKDF_SHA512: + hpke->kdf_digest = WC_SHA512; + break; - default: - break; + default: + ret = BAD_FUNC_ARG; + break; } - switch (aead) { - case HPKE_AES_128_GCM: - hpke->Nk = 16; - hpke->Nn = 12; - hpke->Nt = 16; - break; - - case HPKE_AES_256_GCM: - hpke->Nk = 32; - hpke->Nn = 12; - hpke->Nt = 16; - break; - - default: - break; + switch (aead) + { + case HPKE_AES_128_GCM: + hpke->Nk = 16; + hpke->Nn = 12; + hpke->Nt = 16; + break; + + case HPKE_AES_256_GCM: + hpke->Nk = 32; + hpke->Nn = 12; + hpke->Nt = 16; + break; + + default: + ret = BAD_FUNC_ARG; + break; } return 0; } -int wc_HpkeSerializePublicKey(ecc_key* key, uint8_t* out) +int wc_HpkeSerializePublicKey(ecc_key* key, byte* out) { int ret; - uint32_t qxLen; - uint32_t qyLen; + word32 qxLen; + word32 qyLen; + + if (key == NULL || out == NULL) + return BAD_FUNC_ARG; /* first byte indicates uncompressed public key */ out[0] = 0x04; qxLen = qyLen = key->dp->size; - ret = wc_ecc_export_public_raw( key, out + 1, &qxLen, out + 1 + qxLen, &qyLen ); + ret = wc_ecc_export_public_raw(key, out + 1, &qxLen, out + 1 + qxLen, + &qyLen); return ret; } -int wc_HpkeDeserializePublicKey(Hpke* hpke, ecc_key* key, uint8_t* in) +int wc_HpkeDeserializePublicKey(Hpke* hpke, ecc_key* key, byte* in) { int ret; - ret = wc_ecc_init( key ); + if (hpke == NULL || key == NULL || in == NULL) + return BAD_FUNC_ARG; + + ret = wc_ecc_init(key); /* import +1 to skip the leading x.963 byte */ - if (ret == 0) { - ret = wc_ecc_import_unsigned( key, in + 1, in + 1 + hpke->Npk / 2, NULL, hpke->curve_id ); - //ret = wc_ecc_import_raw_ex( key, in + 1, in + 1 + hpke->Npk / 2, NULL, hpke->curve_id ); - } + if (ret == 0) + ret = wc_ecc_import_unsigned(key, in + 1, in + 1 + hpke->Npk / 2, NULL, + hpke->curve_id); + /* + ret = wc_ecc_import_raw_ex(key, (char*)in + 1, (char*)in + 1 + hpke->Npk / 2, NULL, + hpke->curve_id); + */ return ret; } @@ -183,371 +258,578 @@ int wc_HpkeDeserializePublicKey(Hpke* hpke, ecc_key* key, uint8_t* in) int wc_HpkeGenerateKeyPair( Hpke* hpke, ecc_key* keypair ) { int ret; - int ecc_curve_id; +#ifdef WOLFSSL_SMALL_STACK + WC_RNG* rng; +#else WC_RNG rng[1]; +#endif + + if (hpke == NULL || keypair == NULL) + return BAD_FUNC_ARG; + +#ifdef WOLFSSL_SMALL_STACK + // allocate after we know hpke is good + rng = (WC_RNG*)XMALLOC(sizeof(WC_RNG), hpke->heap, DYNAMIC_TYPE_RNG); +#endif ret = wc_InitRng(rng); - if (ret != 0) - return ret; - ret = wc_ecc_init(keypair); - if (ret == 0) { - switch (hpke->kem) { - case DHKEM_P256_HKDF_SHA256: - ret = wc_ecc_make_key_ex( rng, 32, keypair, ECC_SECP256R1 ); - break; - case DHKEM_P384_HKDF_SHA384: - ret = wc_ecc_make_key_ex( rng, 48, keypair, ECC_SECP384R1 ); - break; - case DHKEM_P521_HKDF_SHA512: - ret = wc_ecc_make_key_ex( rng, 66, keypair, ECC_SECP521R1 ); - break; - case DHKEM_X25519_HKDF_SHA256: - /* TODO: Add X25519 */ - break; - case DHKEM_X448_HKDF_SHA512: - /* TODO: Add X448 */ - break; - default: - ret = -1; - break; - } + if (ret == 0) + ret = wc_ecc_init(keypair); + + if (ret == 0) + switch (hpke->kem) + { + case DHKEM_P256_HKDF_SHA256: + ret = wc_ecc_make_key_ex(rng, 32, keypair, ECC_SECP256R1); + break; + case DHKEM_P384_HKDF_SHA384: + ret = wc_ecc_make_key_ex(rng, 48, keypair, ECC_SECP384R1); + break; + case DHKEM_P521_HKDF_SHA512: + ret = wc_ecc_make_key_ex(rng, 66, keypair, ECC_SECP521R1); + break; + case DHKEM_X25519_HKDF_SHA256: + /* TODO: Add X25519 */ + break; + case DHKEM_X448_HKDF_SHA512: + /* TODO: Add X448 */ + break; + default: + ret = BAD_FUNC_ARG; + break; + } wc_FreeRng(rng); +#ifdef WOLFSSL_SMALL_STACK + XFREE(rng, hpke->heap, DYNAMIC_TYPE_RNG); +#endif + return ret; } -int wc_HpkeLabeledExtract(Hpke* hpke, uint8_t* suite_id, uint32_t suite_id_len, - uint8_t* salt, uint32_t salt_len, uint8_t* label, uint32_t label_len, - uint8_t* ikm, uint32_t ikm_len, uint8_t* out ) +static int wc_HpkeLabeledExtract(Hpke* hpke, byte* suite_id, word32 suite_id_len, + byte* salt, word32 salt_len, byte* label, word32 label_len, + byte* ikm, word32 ikm_len, byte* out) { int ret; - /* TODO: Add support for WOLFSSL_SMALL_STACK */ - uint8_t labeled_ikm[512]; - uint8_t* labeled_ikm_p; + byte* labeled_ikm_p; +#ifdef WOLFSSL_SMALL_STACK + byte* labeled_ikm = XMALLOC(sizeof(byte) * 512, hpke->heap, + DYNAMIC_TYPE_NONE); +#else + byte labeled_ikm[512]; +#endif /* concat the labeled_ikm */ /* version */ - /* TODO: Make all of the duplicated strings either static const char* or defines */ - XMEMCPY( labeled_ikm, "HPKE-v1", strlen( "HPKE-v1" ) ); - labeled_ikm_p = labeled_ikm + strlen( "HPKE-v1" ); + XMEMCPY(labeled_ikm, HPKE_VERSION_STR, HPKE_VERSION_STR_LEN); + labeled_ikm_p = labeled_ikm + HPKE_VERSION_STR_LEN; - // suite_id - /* TODO: Convert all // to /* */ - XMEMCPY( labeled_ikm_p, suite_id, suite_id_len ); + /* suite_id */ + XMEMCPY(labeled_ikm_p, suite_id, suite_id_len); labeled_ikm_p += suite_id_len; - // label - /* TODO: Eliminate extra spaces around () */ - XMEMCPY( labeled_ikm_p, label, label_len ); + /* label */ + XMEMCPY(labeled_ikm_p, label, label_len); labeled_ikm_p += label_len; - // ikm - XMEMCPY( labeled_ikm_p, ikm, ikm_len ); + /* ikm */ + XMEMCPY(labeled_ikm_p, ikm, ikm_len); labeled_ikm_p += ikm_len; - // call extract - ret = wc_HKDF_Extract( hpke->kdf_digest, salt, salt_len, labeled_ikm, labeled_ikm_p - labeled_ikm, out ); + /* call extract */ + ret = wc_HKDF_Extract(hpke->kdf_digest, salt, salt_len, labeled_ikm, + labeled_ikm_p - labeled_ikm, out); + +#ifdef WOLFSSL_SMALL_STACK + XFREE(labeled_ikm, hpke->heap, DYNAMIC_TYPE_NONE); +#endif return ret; } -int wc_HpkeLabeledExpand( Hpke* hpke, uint8_t* suite_id, uint32_t suite_id_len, uint8_t* prk, uint32_t prk_len, uint8_t* label, uint32_t label_len, uint8_t* info, uint32_t info_len, uint32_t L, uint8_t* out ) +static int wc_HpkeLabeledExpand(Hpke* hpke, byte* suite_id, word32 suite_id_len, + byte* prk, word32 prk_len, byte* label, word32 label_len, byte* info, + word32 info_len, word32 L, byte* out) { int ret; - // TODO I don't think it's possible to know in advance how long this should be since any label can be used - uint8_t labeled_info[512] = { 0 }; - uint8_t* labeled_info_p; + byte* labeled_info_p; +#ifdef WOLFSSL_SMALL_STACK + byte* labeled_info = XMALLOC(sizeof(byte) * 512, hpke->heap, + DYNAMIC_TYPE_NONE); +#else + byte labeled_info[512]; +#endif - // copy length - I2OSP( L, 2, labeled_info ); + /* copy length */ + ret = I2OSP(L, 2, labeled_info); labeled_info_p = labeled_info + 2; - // version - XMEMCPY( labeled_info_p, "HPKE-v1", strlen( "HPKE-v1" ) ); - labeled_info_p += strlen( "HPKE-v1" ); + if (ret == 0) + { + /* version */ + XMEMCPY(labeled_info_p, HPKE_VERSION_STR, HPKE_VERSION_STR_LEN); + labeled_info_p += HPKE_VERSION_STR_LEN; + + /* suite_id */ + XMEMCPY(labeled_info_p, suite_id, suite_id_len); + labeled_info_p += suite_id_len; - // suite_id - XMEMCPY( labeled_info_p, suite_id, suite_id_len ); - labeled_info_p += suite_id_len; + /* label */ + XMEMCPY(labeled_info_p, label, label_len); + labeled_info_p += label_len; - // label - XMEMCPY( labeled_info_p, label, label_len ); - labeled_info_p += label_len; + /* info */ + XMEMCPY(labeled_info_p, info, info_len); + labeled_info_p += info_len; - // info - XMEMCPY( labeled_info_p, info, info_len ); - labeled_info_p += info_len; + /* call expand */ + ret = wc_HKDF_Expand(hpke->kdf_digest, prk, prk_len, labeled_info, + labeled_info_p - labeled_info, out, L); + } - // call expand - ret = wc_HKDF_Expand( hpke->kdf_digest, prk, prk_len, labeled_info, labeled_info_p - labeled_info, out, L ); +#ifdef WOLFSSL_SMALL_STACK + XFREE(labeled_info, hpke->heap, DYNAMIC_TYPE_NONE); +#endif return ret; } -void wc_HpkeContextComputeNonce( Hpke* hpke, HpkeBaseContext* context, uint8_t* out ) +static int wc_HpkeContextComputeNonce(Hpke* hpke, HpkeBaseContext* context, byte* out) { - int i; - uint8_t seq_bytes[12]; + int i; + int ret; + /* TODO is this small enough for small stack? */ + byte seq_bytes[HPKE_Nn_MAX]; - // convert the sequence into a byte string with the same length as the nonce - I2OSP( context->seq, hpke->Nn, seq_bytes ); + /* convert the sequence into a byte string with the same length as the + nonce */ + ret = I2OSP(context->seq, hpke->Nn, seq_bytes); - for ( i = 0; i < hpke->Nn; i++ ) - { - out[i] = context->base_nonce[i] ^ seq_bytes[i]; - } + if (ret != 0) + return ret; + + for (i = 0; i < hpke->Nn; i++) + { + out[i] = context->base_nonce[i] ^ seq_bytes[i]; + } + + return ret; } -int wc_HpkeExtractAndExpand( Hpke* hpke, uint8_t* dh, uint32_t dh_len, uint8_t* kem_context, uint32_t kem_context_length, uint8_t* shared_secret ) +static int wc_HpkeExtractAndExpand( Hpke* hpke, byte* dh, word32 dh_len, + byte* kem_context, word32 kem_context_length, byte* shared_secret) { int ret; - // max length is the largest hmac digest possible - uint8_t eae_prk[WC_MAX_DIGEST_SIZE]; + /* max length is the largest hmac digest possible */ +#ifdef WOLFSSL_SMALL_STACK + byte* eae_prk = XMALLOC(sizeof(byte) * WC_MAX_DIGEST_SIZE, hpke->heap, + DYNAMIC_TYPE_NONE); +#else + byte eae_prk[WC_MAX_DIGEST_SIZE]; +#endif - // extract - ret = wc_HpkeLabeledExtract( hpke, hpke->kem_suite_id, sizeof( hpke->kem_suite_id ), NULL, 0, (uint8_t*)"eae_prk", strlen( "eae_prk" ), dh, dh_len, eae_prk ); + /* extract */ + ret = wc_HpkeLabeledExtract(hpke, hpke->kem_suite_id, + sizeof( hpke->kem_suite_id ), NULL, 0, (byte*)EAE_PRK_LABEL_STR, + EAE_PRK_LABEL_STR_LEN, dh, dh_len, eae_prk); - // expand - /* TODO: Max line length is 80 */ - if ( ret == 0 ) { - ret = wc_HpkeLabeledExpand( hpke, hpke->kem_suite_id, sizeof( hpke->kem_suite_id ), eae_prk, hpke->Nh, "shared_secret", strlen( "shared_secret" ), kem_context, kem_context_length, hpke->Nsecret, shared_secret ); - } + /* expand */ + if ( ret == 0 ) + ret = wc_HpkeLabeledExpand(hpke, hpke->kem_suite_id, + sizeof( hpke->kem_suite_id ), eae_prk, hpke->Nh, + (byte*)SHARED_SECRET_LABEL_STR, SHARED_SECRET_LABEL_STR_LEN, + kem_context, kem_context_length, hpke->Nsecret, shared_secret); + +#ifdef WOLFSSL_SMALL_STACK + XFREE(eae_prk, hpke->heap, DYNAMIC_TYPE_NONE); +#endif return ret; } -int wc_HpkeKeyScheduleBase( Hpke* hpke, HpkeBaseContext* context, uint8_t* shared_secret, uint8_t* info, uint32_t info_len ) +static int wc_HpkeKeyScheduleBase(Hpke* hpke, HpkeBaseContext* context, + byte* shared_secret, byte* info, word32 info_len) { int ret; - // 1 for mode and WC_MAX_DIGEST_SIZE times 2 for psk_id_hash and info_hash - uint8_t key_schedule_context[1 + 2 * WC_MAX_DIGEST_SIZE]; - // maximum size of secret is largest hash of extract - uint8_t secret[WC_MAX_DIGEST_SIZE]; +#ifdef WOLFSSL_SMALL_STACK + byte* key_schedule_context = + XMALLOC(sizeof(byte) * (1 + 2 * WC_MAX_DIGEST_SIZE), hpke->heap, + DYNAMIC_TYPE_NONE); + byte* secret = XMALLOC(sizeof(byte) * WC_MAX_DIGEST_SIZE, hpke->heap, + DYNAMIC_TYPE_NONE); +#else + /* 1 for mode and WC_MAX_DIGEST_SIZE times 2 for psk_id_hash and info_hash */ + byte key_schedule_context[1 + 2 * WC_MAX_DIGEST_SIZE]; + /* maximum size of secret is largest hash of extract */ + byte secret[WC_MAX_DIGEST_SIZE]; +#endif - // set the sequence to 0 + /* set the sequence to 0 */ context->seq = 0; - // 0 for mode + /* 0 for mode */ key_schedule_context[0] = 0; - // extract psk_id, which for base is null - ret = wc_HpkeLabeledExtract( hpke, hpke->hpke_suite_id, sizeof( hpke->hpke_suite_id ), NULL, 0, "psk_id_hash", strlen( "psk_id_hash" ), NULL, 0, key_schedule_context + 1 ); - - // extract info - if ( ret == 0 ) - ret = wc_HpkeLabeledExtract( hpke, hpke->hpke_suite_id, sizeof( hpke->hpke_suite_id ), NULL, 0, "info_hash", strlen( "info_hash" ), info, info_len, key_schedule_context + 1 + hpke->Nh ); - - // extract secret - if ( ret == 0 ) - ret = wc_HpkeLabeledExtract( hpke, hpke->hpke_suite_id, sizeof( hpke->hpke_suite_id ), shared_secret, hpke->Nsecret, "secret", strlen( "secret" ), NULL, 0, secret ); - - // expand key - if ( ret == 0 ) - ret = wc_HpkeLabeledExpand( hpke, hpke->hpke_suite_id, sizeof( hpke->hpke_suite_id ), secret, hpke->Nh, "key", strlen( "key" ), key_schedule_context, 1 + 2 * hpke->Nh, hpke->Nk, context->key ); - - // expand nonce - if ( ret == 0 ) - ret = wc_HpkeLabeledExpand( hpke, hpke->hpke_suite_id, sizeof( hpke->hpke_suite_id ), secret, hpke->Nh, "base_nonce", strlen( "base_nonce" ), key_schedule_context, 1 + 2 * hpke->Nh, hpke->Nn, context->base_nonce ); - - // expand exporter_secret - if ( ret == 0 ) - ret = wc_HpkeLabeledExpand( hpke, hpke->hpke_suite_id, sizeof( hpke->hpke_suite_id ), secret, hpke->Nh, "exp", strlen( "exp" ), key_schedule_context, 1 + 2 * hpke->Nh, hpke->Nh, context->exporter_secret ); + /* extract psk_id, which for base is null */ + ret = wc_HpkeLabeledExtract(hpke, hpke->hpke_suite_id, + sizeof( hpke->hpke_suite_id ), NULL, 0, (byte*)PSK_ID_HASH_LABEL_STR, + PSK_ID_HASH_LABEL_STR_LEN, NULL, 0, key_schedule_context + 1); + + /* extract info */ + if (ret == 0) + ret = wc_HpkeLabeledExtract(hpke, hpke->hpke_suite_id, + sizeof( hpke->hpke_suite_id ), NULL, 0, (byte*)INFO_HASH_LABEL_STR, + INFO_HASH_LABEL_STR_LEN, info, info_len, + key_schedule_context + 1 + hpke->Nh); + + /* extract secret */ + if (ret == 0) + ret = wc_HpkeLabeledExtract(hpke, hpke->hpke_suite_id, + sizeof( hpke->hpke_suite_id ), shared_secret, hpke->Nsecret, + (byte*)SECRET_LABEL_STR, SECRET_LABEL_STR_LEN, NULL, 0, secret); + + /* expand key */ + if (ret == 0) + ret = wc_HpkeLabeledExpand(hpke, hpke->hpke_suite_id, + sizeof( hpke->hpke_suite_id ), secret, hpke->Nh, + (byte*)KEY_LABEL_STR, KEY_LABEL_STR_LEN, key_schedule_context, + 1 + 2 * hpke->Nh, hpke->Nk, context->key); + + /* expand nonce */ + if (ret == 0) + ret = wc_HpkeLabeledExpand(hpke, hpke->hpke_suite_id, + sizeof( hpke->hpke_suite_id ), secret, hpke->Nh, + (byte*)BASE_NONCE_LABEL_STR, BASE_NONCE_LABEL_STR_LEN, + key_schedule_context, 1 + 2 * hpke->Nh, hpke->Nn, + context->base_nonce); + + /* expand exporter_secret */ + if (ret == 0) + ret = wc_HpkeLabeledExpand(hpke, hpke->hpke_suite_id, + sizeof( hpke->hpke_suite_id ), secret, hpke->Nh, + (byte*)EXP_LABEL_STR, EXP_LABEL_STR_LEN, key_schedule_context, + 1 + 2 * hpke->Nh, hpke->Nh, context->exporter_secret); + +#ifdef WOLFSSL_SMALL_STACK + XFREE(key_schedule_context, hpke->heap, DYNAMIC_TYPE_NONE); + XFREE(secret, hpke->heap, DYNAMIC_TYPE_NONE); +#endif return ret; } -int wc_HpkeEncap( Hpke* hpke, uint8_t* shared_secret, uint8_t* enc ) +static int wc_HpkeEncap(Hpke* hpke, byte* shared_secret, byte* enc) { int ret; + word32 dh_len = hpke->Ndh; +#ifdef WOLFSSL_SMALL_STACK + ecc_key* ephemiral_key = (ecc_key*)XMALLOC(sizeof(ecc_key), hpke->heap, + DYNAMIC_TYPE_ECC); + byte* dh = XMALLOC(sizeof(byte) * hpke->Ndh, hpke->heap, DYNAMIC_TYPE_NONE); + byte* kem_context = XMALLOC(sizeof(byte) * hpke->Npk * 2, hpke->heap, + DYNAMIC_TYPE_NONE); +#else ecc_key ephemiral_key[1]; - // maximum value of Ndh is 66 - uint8_t dh[66]; - uint32_t dh_len = hpke->Ndh; - // kem_context max is 133 for pubkey max size * 2 for ephemiral_key and receiver_key - uint8_t kem_context[266]; - - // generate keypair - ret = wc_HpkeGenerateKeyPair( hpke, ephemiral_key ); + byte dh[HPKE_Ndh_MAX]; + byte kem_context[HPKE_Npk_MAX * 2]; +#endif - if ( ret != 0 ) - return ret; + /* generate keypair */ + ret = wc_HpkeGenerateKeyPair(hpke, ephemiral_key); - // generate dh - if ( ret == 0 ) + if (ret == 0) { - ephemiral_key->rng = wc_rng_new( NULL, 0, NULL ); + /* generate dh */ + ephemiral_key->rng = wc_rng_new(NULL, 0, hpke->heap); - ret = wc_ecc_shared_secret( ephemiral_key, hpke->receiver_key, dh, &dh_len ); + ret = wc_ecc_shared_secret(ephemiral_key, hpke->receiver_key, dh, &dh_len); - wc_rng_free( ephemiral_key->rng ); - } + wc_rng_free(ephemiral_key->rng); - // serialize ephemiral_key - if ( ret == 0 ) - ret = wc_HpkeSerializePublicKey( ephemiral_key, enc ); + /* serialize ephemiral_key */ + if (ret == 0) + ret = wc_HpkeSerializePublicKey(ephemiral_key, enc); - // free ephemiral_key - wc_ecc_free( ephemiral_key ); + /* free ephemiral_key */ + wc_ecc_free(ephemiral_key); + } - if ( ret == 0 ) + if (ret == 0) { - // copy enc into kem_context - XMEMCPY( kem_context, enc, hpke->Npk ); + /* copy enc into kem_context */ + XMEMCPY(kem_context, enc, hpke->Npk); - // serialize pkR into kem_context - ret = wc_HpkeSerializePublicKey( hpke->receiver_key, kem_context + hpke->Npk ); + /* serialize pkR into kem_context */ + ret = wc_HpkeSerializePublicKey(hpke->receiver_key, + kem_context + hpke->Npk); } - // compute the shared secret - if ( ret == 0 ) - ret = wc_HpkeExtractAndExpand( hpke, dh, dh_len, kem_context, hpke->Npk * 2, shared_secret ); + /* compute the shared secret */ + if (ret == 0) + ret = wc_HpkeExtractAndExpand(hpke, dh, dh_len, kem_context, + hpke->Npk * 2, shared_secret); + +#ifdef WOLFSSL_SMALL_STACK + XFREE(ephemiral_key, hpke->heap, DYNAMIC_TYPE_ECC); + XFREE(dh, hpke->heap, DYNAMIC_TYPE_NONE); + XFREE(kem_context, hpke->heap, DYNAMIC_TYPE_NONE); +#endif return ret; } -int wc_HpkeSetupBaseSender( Hpke* hpke, HpkeBaseContext* context, uint8_t* info, uint32_t info_len, uint8_t* enc ) +static int wc_HpkeSetupBaseSender(Hpke* hpke, HpkeBaseContext* context, byte* info, + word32 info_len, byte* enc) { int ret; - // 64 is the maximum size of Nsecret - uint8_t shared_secret[64]; +#ifdef WOLFSSL_SMALL_STACK + byte* shared_secret = XMALLOC(sizeof(byte) * hpke->Nsecret, hpke->heap, + DYNAMIC_TYPE_NONE); +#else + byte shared_secret[HPKE_Nsecret_MAX]; +#endif - // encap - ret = wc_HpkeEncap( hpke, shared_secret, enc ); + /* encap */ + ret = wc_HpkeEncap(hpke, shared_secret, enc); - // schedule - if ( ret == 0 ) - ret = wc_HpkeKeyScheduleBase( hpke, context, shared_secret, info, info_len ); + /* schedule */ + if (ret == 0) + ret = wc_HpkeKeyScheduleBase(hpke, context, shared_secret, info, + info_len); + +#ifdef WOLFSSL_SMALL_STACK + XFREE(shared_secret, hpke->heap, DYNAMIC_TYPE_NONE); +#endif return ret; } -int wc_HpkeContextSealBase( Hpke* hpke, HpkeBaseContext* context, uint8_t* aad, uint32_t aad_len, uint8_t* plaintext, uint32_t pt_len, uint8_t* out ) +static int wc_HpkeContextSealBase(Hpke* hpke, HpkeBaseContext* context, byte* aad, + word32 aad_len, byte* plaintext, word32 pt_len, byte* out) { int ret; - uint8_t nonce[12]; + /* TODO is this small enough for small stack? */ + byte nonce[HPKE_Nn_MAX]; +#ifdef WOLFSSL_SMALL_STACK + Aes* aes_key = XMALLOC(sizeof(Aes), hpke->heap, DYNAMIC_TYPE_AES); +#else Aes aes_key[1]; +#endif - wc_HpkeContextComputeNonce( hpke, context, nonce ); + ret = wc_HpkeContextComputeNonce(hpke, context, nonce); - // TODO implement chacha and change this based on the alg - ret = wc_AesGcmSetKey( aes_key, context->key, hpke->Nk ); + /* TODO implement chacha and change this based on the alg */ + if (ret == 0) + ret = wc_AesGcmSetKey( aes_key, context->key, hpke->Nk ); - if ( ret == 0 ) - ret = wc_AesGcmEncrypt( aes_key, out, plaintext, pt_len, nonce, hpke->Nn, out + pt_len, hpke->Nt, aad, aad_len ); + if (ret == 0) + ret = wc_AesGcmEncrypt(aes_key, out, plaintext, pt_len, nonce, hpke->Nn, + out + pt_len, hpke->Nt, aad, aad_len); - if ( ret == 0 ) + if (ret == 0) context->seq++; +#ifdef WOLFSSL_SMALL_STACK + XFREE(aes_key, hpke->heap, DYNAMIC_TYPE_AES); +#endif + return ret; } -int wc_HpkeSealBase( Hpke* hpke, uint8_t* info, uint32_t info_len, uint8_t* aad, uint32_t aad_len, uint8_t* plaintext, uint32_t pt_len, uint8_t* ciphertext, uint8_t* enc ) +int wc_HpkeSealBase(Hpke* hpke, byte* info, word32 info_len, byte* aad, + word32 aad_len, byte* plaintext, word32 pt_len, byte* ciphertext, byte* enc) { int ret; +#ifdef WOLFSSL_SMALL_STACK + HpkeBaseContext* context; +#else HpkeBaseContext context[1]; +#endif - if ( hpke->receiver_key_set == false ) - { - return -1; - } + /* check that all the buffers are non NULL or optional with 0 length */ + if (hpke == NULL || hpke->receiver_pubkey_set == 0 || + (info == NULL && info_len != 0) || (aad == NULL && aad_len != 0) || + plaintext == NULL || ciphertext == NULL || enc == NULL) + return BAD_FUNC_ARG; - // setup the context and enc - ret = wc_HpkeSetupBaseSender( hpke, context, info, info_len, enc ); +#ifdef WOLFSSL_SMALL_STACK + // allocate after we know hpke is good + context = XMALLOC(sizeof(HpkeBaseContext), hpke->heap, DYNAMIC_TYPE_NONE); +#endif - // run seal using the context - if ( ret == 0 ) - ret = wc_HpkeContextSealBase( hpke, context, aad, aad_len, plaintext, pt_len, ciphertext ); + /* setup the context and enc */ + ret = wc_HpkeSetupBaseSender(hpke, context, info, info_len, enc); + + /* run seal using the context */ + if (ret == 0) + ret = wc_HpkeContextSealBase(hpke, context, aad, aad_len, plaintext, + pt_len, ciphertext); + +#ifdef WOLFSSL_SMALL_STACK + XFREE(context, hpke->heap, DYNAMIC_TYPE_NONE); +#endif return ret; } -int wc_HpkeDecap( Hpke* hpke, uint8_t* enc, uint8_t* shared_secret ) +static int wc_HpkeDecap(Hpke* hpke, byte* enc, byte* shared_secret) { int ret; - // maximum value of Ndh is 66 - uint8_t dh[66]; - uint32_t dh_len = hpke->Ndh; - uint8_t kem_context[266]; + word32 dh_len = hpke->Ndh; +#ifdef WOLFSSL_SMALL_STACK + ecc_key* ephemiral_key = (ecc_key*)XMALLOC(sizeof(ecc_key), hpke->heap, + DYNAMIC_TYPE_ECC); + byte* dh = XMALLOC(sizeof(byte) * hpke->Ndh, hpke->heap, DYNAMIC_TYPE_NONE); + byte* kem_context = XMALLOC(sizeof(byte) * hpke->Npk * 2, hpke->heap, + DYNAMIC_TYPE_NONE); +#else ecc_key ephemiral_key[1]; + byte dh[HPKE_Ndh_MAX]; + byte kem_context[HPKE_Npk_MAX * 2]; +#endif - // deserialize ephemiral_key from enc - ret = wc_HpkeDeserializePublicKey( hpke, ephemiral_key, enc ); + /* deserialize ephemiral_key from enc */ + ret = wc_HpkeDeserializePublicKey(hpke, ephemiral_key, enc); - // generate dh - if ( ret == 0 ) + if (ret == 0) { - hpke->receiver_key->rng = wc_rng_new( NULL, 0, NULL ); + /* generate dh */ + hpke->receiver_key->rng = wc_rng_new(NULL, 0, hpke->heap); + + ret = wc_ecc_shared_secret(hpke->receiver_key, ephemiral_key, dh, + &dh_len); - ret = wc_ecc_shared_secret( hpke->receiver_key, ephemiral_key, dh, &dh_len ); + wc_rng_free(hpke->receiver_key->rng); - wc_rng_free( hpke->receiver_key->rng ); + /* free ephemiral_key */ + wc_ecc_free(ephemiral_key); } - if ( ret == 0 ) + if (ret == 0) { - // copy enc into kem_context - XMEMCPY( kem_context, enc, hpke->Npk ); + /* copy enc into kem_context */ + XMEMCPY(kem_context, enc, hpke->Npk); - // serialize pkR into kem_context - ret = wc_HpkeSerializePublicKey( hpke->receiver_key, kem_context + hpke->Npk ); + /* serialize pkR into kem_context */ + ret = wc_HpkeSerializePublicKey(hpke->receiver_key, + kem_context + hpke->Npk); } - // compute the shared secret - if ( ret == 0 ) - ret = wc_HpkeExtractAndExpand( hpke, dh, dh_len, kem_context, hpke->Npk * 2, shared_secret ); + /* compute the shared secret */ + if (ret == 0) + ret = wc_HpkeExtractAndExpand(hpke, dh, dh_len, kem_context, + hpke->Npk * 2, shared_secret); + +#ifdef WOLFSSL_SMALL_STACK + XFREE(ephemiral_key, hpke->heap, DYNAMIC_TYPE_ECC); + XFREE(dh, hpke->heap, DYNAMIC_TYPE_NONE); + XFREE(kem_context, hpke->heap, DYNAMIC_TYPE_NONE); +#endif return ret; } -int wc_HpkeSetupBaseReceiver( Hpke* hpke, HpkeBaseContext* context, uint8_t* enc, uint8_t* info, uint32_t info_len ) +static int wc_HpkeSetupBaseReceiver(Hpke* hpke, HpkeBaseContext* context, + byte* enc, byte* info, word32 info_len) { int ret; - // 64 is the maximum size of Nsecret - uint8_t shared_secret[64]; +#ifdef WOLFSSL_SMALL_STACK + byte* shared_secret = XMALLOC(sizeof(byte) * hpke->Nsecret, hpke->heap, + DYNAMIC_TYPE_NONE); +#else + byte shared_secret[HPKE_Nsecret_MAX]; +#endif - // decap - ret = wc_HpkeDecap( hpke, enc, shared_secret ); + /* decap */ + ret = wc_HpkeDecap(hpke, enc, shared_secret); - // schedule + /* schedule */ if ( ret == 0 ) - ret = wc_HpkeKeyScheduleBase( hpke, context, shared_secret, info, info_len ); + ret = wc_HpkeKeyScheduleBase(hpke, context, shared_secret, info, + info_len); + +#ifdef WOLFSSL_SMALL_STACK + XFREE(shared_secret, hpke->heap, DYNAMIC_TYPE_NONE); +#endif return ret; } -int wc_HpkeContextOpenBase( Hpke* hpke, HpkeBaseContext* context, uint8_t* aad, uint32_t aad_len, uint8_t* ciphertext, uint32_t ct_len, uint8_t* out ) +static int wc_HpkeContextOpenBase(Hpke* hpke, HpkeBaseContext* context, byte* aad, + word32 aad_len, byte* ciphertext, word32 ct_len, byte* out) { int ret; - uint8_t nonce[12]; + byte nonce[HPKE_Nn_MAX]; +#ifdef WOLFSSL_SMALL_STACK + Aes* aes_key = XMALLOC(sizeof(Aes), hpke->heap, DYNAMIC_TYPE_AES); +#else Aes aes_key[1]; +#endif - wc_HpkeContextComputeNonce( hpke, context, nonce ); + ret = wc_HpkeContextComputeNonce(hpke, context, nonce); - // TODO implement chacha and change this based on the alg - ret = wc_AesGcmSetKey( aes_key, context->key, hpke->Nk ); + /* TODO implement chacha and change this based on the alg */ + if (ret == 0) + ret = wc_AesGcmSetKey(aes_key, context->key, hpke->Nk); - if ( ret == 0 ) - ret = wc_AesGcmDecrypt( aes_key, out, ciphertext, ct_len, nonce, hpke->Nn, ciphertext + ct_len, hpke->Nt, aad, aad_len ); + if (ret == 0) + ret = wc_AesGcmDecrypt(aes_key, out, ciphertext, ct_len, nonce, + hpke->Nn, ciphertext + ct_len, hpke->Nt, aad, aad_len); - if ( ret == 0 ) + if (ret == 0) context->seq++; +#ifdef WOLFSSL_SMALL_STACK + XFREE(aes_key, hpke->heap, DYNAMIC_TYPE_AES); +#endif + return ret; } -int wc_HpkeOpenBase( Hpke* hpke, uint8_t* enc, uint8_t* info, uint32_t info_len, uint8_t* aad, uint32_t aad_len, uint8_t* ciphertext, uint32_t ct_len, uint8_t* plaintext ) +int wc_HpkeOpenBase(Hpke* hpke, byte* enc, byte* info, word32 info_len, + byte* aad, word32 aad_len, byte* ciphertext, word32 ct_len, + byte* plaintext) { int ret; +#ifdef WOLFSSL_SMALL_STACK + HpkeBaseContext* context; +#else HpkeBaseContext context[1]; +#endif - // setup receiver - ret = wc_HpkeSetupBaseReceiver( hpke, context, enc, info, info_len ); + /* check that all the buffer are non NULL or optional with 0 length */ + if (hpke == NULL || hpke->receiver_privkey_set == 0 || + (info == NULL && info_len != 0) || (aad == NULL && aad_len != 0) || + plaintext == NULL || ciphertext == NULL || enc == NULL) + return BAD_FUNC_ARG; - // open the ciphertext +#ifdef WOLFSSL_SMALL_STACK + // allocate after we know hpke is good + context = XMALLOC(sizeof(HpkeBaseContext), hpke->heap, DYNAMIC_TYPE_NONE); +#endif + + /* setup receiver */ + ret = wc_HpkeSetupBaseReceiver(hpke, context, enc, info, info_len); + + /* open the ciphertext */ if ( ret == 0 ) - ret = wc_HpkeContextOpenBase( hpke, context, aad, aad_len, ciphertext, ct_len, plaintext ); + ret = wc_HpkeContextOpenBase(hpke, context, aad, aad_len, ciphertext, + ct_len, plaintext); + +#ifdef WOLFSSL_SMALL_STACK + XFREE(context, hpke->heap, DYNAMIC_TYPE_NONE); +#endif return ret; } + +void wc_HpkeFree(Hpke* hpke) +{ + if (hpke->receiver_privkey_set == 1 || hpke->receiver_pubkey_set == 1) + { + wc_ecc_free(hpke->receiver_key); + } +} diff --git a/wolfcrypt/test/test.c b/wolfcrypt/test/test.c index a7cfa7f33ca..9b3feba37be 100644 --- a/wolfcrypt/test/test.c +++ b/wolfcrypt/test/test.c @@ -437,6 +437,7 @@ WOLFSSL_TEST_SUBROUTINE int sshkdf_test(void); WOLFSSL_TEST_SUBROUTINE int tls13_kdf_test(void); #endif WOLFSSL_TEST_SUBROUTINE int x963kdf_test(void); +WOLFSSL_TEST_SUBROUTINE int hpke_test(void); WOLFSSL_TEST_SUBROUTINE int arc4_test(void); #ifdef WC_RC2 WOLFSSL_TEST_SUBROUTINE int rc2_test(void); @@ -22259,19 +22260,19 @@ WOLFSSL_TEST_SUBROUTINE int x963kdf_test(void) WOLFSSL_TEST_SUBROUTINE int hpke_test(void) { - int i; int ret; Hpke hpke[1]; const char* start_text = "this is a test"; - uint8_t ciphertext[512] = { 0 }; - uint8_t plaintext[512] = { 0 }; + byte ciphertext[512] = { 0 }; + byte plaintext[512] = { 0 }; // 133 bytes is the max for each of the 2 points that make up the public key uint8_t enc[133]; //const uint8_t serialized_pubkey[] = {0x04, 0x53, 0x21, 0x3f, 0x7d, 0xb7, 0xb5, 0xa4, 0x59, 0x90, 0xf8, 0xd5, 0x97, 0x18, 0x63, 0x2d, 0x64, 0x2b, 0x75, 0x1c, 0x20, 0x78, 0xd1, 0xf3, 0xd9, 0xa7, 0x4e, 0x6b, 0xd1, 0x25, 0xb3, 0x3a, 0x7b, 0xab, 0x62, 0xc1, 0x36, 0xee, 0x9f, 0x8f, 0xba, 0xa5, 0x56, 0x3d, 0x2d, 0x0a, 0xe1, 0x1c, 0x85, 0xe7, 0xe6, 0x72, 0x2a, 0xeb, 0x97, 0x5f, 0x33, 0xd2, 0xc5, 0xa7, 0x68, 0x58, 0xeb, 0xd2, 0x76}; //ret = wc_HpkeInit( hpke, DHKEM_P256_HKDF_SHA256, WC_SHA256, HPKE_AES_256_GCM, NULL ); - ret = wc_HpkeInit( hpke, DHKEM_P256_HKDF_SHA256, HKDF_SHA256, HPKE_AES_128_GCM, NULL ); - if ( ret == 0 ) + ret = wc_HpkeInit(hpke, DHKEM_P256_HKDF_SHA256, HKDF_SHA256, HPKE_AES_128_GCM, NULL); + + if (ret == 0) ret = wc_HpkeGenerateKeyPair( hpke, hpke->receiver_key ); /* @@ -22279,11 +22280,12 @@ WOLFSSL_TEST_SUBROUTINE int hpke_test(void) ret = wc_HpkeDeserializePublicKey( hpke, hpke->receiver_key, serialized_pubkey ); */ - if ( ret == 0 ) + if (ret == 0) { - hpke->receiver_key_set = true; + hpke->receiver_pubkey_set = 1; + hpke->receiver_privkey_set = 1; - ret = wc_HpkeSealBase( hpke, "info", strlen( "info" ), "aad", strlen( "aad" ), start_text, strlen( start_text ), ciphertext, enc ); + ret = wc_HpkeSealBase(hpke, (byte*)"info", strlen( "info" ), (byte*)"aad", strlen( "aad" ), (byte*)start_text, strlen( start_text ), ciphertext, enc); } /* @@ -22304,20 +22306,15 @@ WOLFSSL_TEST_SUBROUTINE int hpke_test(void) printf( "\n" ); */ - if ( ret == 0 ) - ret = wc_HpkeOpenBase( hpke, enc, "info", strlen( "info" ), "aad", strlen( "aad" ), ciphertext, strlen( start_text ), plaintext ); + if (ret == 0) + ret = wc_HpkeOpenBase(hpke, enc, (byte*)"info", strlen( "info" ), (byte*)"aad", strlen( "aad" ), ciphertext, strlen( start_text ), plaintext); - if ( ret == 0 ) - { - //printf( "plaintext\n" ); + if (ret == 0) + ret = XMEMCMP(plaintext, start_text, strlen( start_text )); - for ( i = 0; i < strlen( start_text ); i++ ) - { - printf( "%c", plaintext[i] ); - } + wc_HpkeFree( hpke ); - printf( "\n" ); - } + return ret; } #endif /* HAVE_HPKE */ diff --git a/wolfssl/wolfcrypt/hpke.h b/wolfssl/wolfcrypt/hpke.h index a84a6056937..455aad6b371 100644 --- a/wolfssl/wolfcrypt/hpke.h +++ b/wolfssl/wolfcrypt/hpke.h @@ -23,6 +23,10 @@ \file wolfssl/wolfcrypt/hpke.h */ +#include + +#include + #ifdef __cplusplus extern "C" { #endif @@ -49,6 +53,16 @@ enum { HPKE_AES_256_GCM = 0x0002, }; +#define HPKE_Nh_MAX 64 +#define HPKE_Nk_MAX 32 +#define HPKE_Nn_MAX 12 +#define HPKE_Nt_MAX 16 +#define HPKE_Ndh_MAX 66 +#define HPKE_Npk_MAX 133 +#define HPKE_Nsecret_MAX 64 +#define KEM_SUITE_ID_LEN 5 +#define HPKE_SUITE_ID_LEN 10 + typedef struct { int kem; int kdf; @@ -60,30 +74,36 @@ typedef struct { int Ndh; int Npk; int Nsecret; - uint8_t kem_suite_id[5]; - uint8_t hpke_suite_id[10]; + byte kem_suite_id[5]; + byte hpke_suite_id[10]; ecc_key receiver_key[1]; - bool receiver_key_set; + byte receiver_pubkey_set:1; + byte receiver_privkey_set:1; int kdf_digest; int curve_id; + void* heap; } Hpke; typedef struct { int seq; - uint8_t key[32]; /* TODO: Use const/enum/define for these */ - uint8_t base_nonce[12]; - uint8_t exporter_secret[64]; + byte key[HPKE_Nk_MAX]; + byte base_nonce[HPKE_Nn_MAX]; + byte exporter_secret[HPKE_Nsecret_MAX]; } HpkeBaseContext; WOLFSSL_API int wc_HpkeInit(Hpke* hpke, int kem, int kdf, int aead, void* heap); WOLFSSL_API int wc_HpkeGenerateKeyPair(Hpke* hpke, ecc_key* keypair); -WOLFSSL_API int wc_HpkeSerializePublicKey(ecc_key* key, uint8_t* out); -WOLFSSL_API int wc_HpkeDeserializePublicKey(Hpke* hpke, ecc_key* key, uint8_t* in); -WOLFSSL_API int wc_HpkeSealBase(Hpke* hpke, uint8_t* info, uint32_t info_len, - uint8_t* aad, uint32_t aad_len, uint8_t* plaintext, uint32_t pt_len, uint8_t* out); -WOLFSSL_API int wc_HpkeOpenBase(Hpke* hpke, uint8_t* enc, - uint8_t* info, uint32_t info_len, uint8_t* aad, uint32_t aad_len, - uint8_t* ciphertext, uint32_t ct_len, uint8_t* plaintext); +WOLFSSL_API int wc_HpkeSerializePublicKey(ecc_key* key, byte* out); +WOLFSSL_API int wc_HpkeDeserializePublicKey(Hpke* hpke, ecc_key* key, byte* in); +WOLFSSL_API +int wc_HpkeSealBase(Hpke* hpke, byte* info, word32 info_len, byte* aad, + word32 aad_len, byte* plaintext, word32 pt_len, byte* ciphertext, + byte* enc); +WOLFSSL_API +int wc_HpkeOpenBase(Hpke* hpke, byte* enc, byte* info, word32 info_len, + byte* aad, word32 aad_len, byte* ciphertext, word32 ct_len, + byte* plaintext); +WOLFSSL_API void wc_HpkeFree(Hpke* hpke); #ifdef __cplusplus } /* extern "C" */