diff --git a/configure.ac b/configure.ac index 12388db48..adbbeb410 100644 --- a/configure.ac +++ b/configure.ac @@ -3026,7 +3026,7 @@ fi # ECC encrypt AC_ARG_ENABLE([eccencrypt], - [AS_HELP_STRING([--enable-eccencrypt],[Enable ECC encrypt (default: disabled). yes = SEC1 standard, iso18033 = ISO 18033 standard, old = original wolfSSL algorithm])], + [AS_HELP_STRING([--enable-eccencrypt],[Enable ECC encrypt (default: disabled). yes = SEC1 standard, geniv = Generate IV, iso18033 = ISO 18033 standard, old = original wolfSSL algorithm])], [ ENABLED_ECC_ENCRYPT=$enableval ], [ ENABLED_ECC_ENCRYPT=no ] ) @@ -3050,6 +3050,10 @@ then then AM_CFLAGS="$AM_CFLAGS -DWOLFSSL_ECIES_ISO18033" fi + if test "$ENABLED_ECC_ENCRYPT" = "geniv" + then + AM_CFLAGS="$AM_CFLAGS -DWOLFSSL_ECIES_GEN_IV" + fi fi # Elliptic Curve-Based Certificateless Signatures for Identity-Based Encryption (ECCSI) diff --git a/doc/dox_comments/header_files/ecc.h b/doc/dox_comments/header_files/ecc.h index 953652971..f504f4118 100644 --- a/doc/dox_comments/header_files/ecc.h +++ b/doc/dox_comments/header_files/ecc.h @@ -1664,6 +1664,7 @@ int wc_ecc_ctx_set_algo(ecEncCtx* ctx, byte encAlgo, byte kdfAlgo, \sa wc_ecc_ctx_new \sa wc_ecc_ctx_set_peer_salt + \sa wc_ecc_ctx_set_kdf_salt */ const byte* wc_ecc_ctx_get_own_salt(ecEncCtx*); @@ -1702,10 +1703,46 @@ const byte* wc_ecc_ctx_get_own_salt(ecEncCtx*); \endcode \sa wc_ecc_ctx_get_own_salt + \sa wc_ecc_ctx_set_kdf_salt */ int wc_ecc_ctx_set_peer_salt(ecEncCtx* ctx, const byte* salt); +/*! + \ingroup ECC + + \brief This function sets the salt pointer and length to use with KDF + into the ecEncCtx object. + + \return 0 Returned upon successfully setting the salt for the + ecEncCtx object. + \return BAD_FUNC_ARG Returned if the given ecEncCtx object is NULL + or if the given salt is NULL and length is not NULL. + + \param ctx pointer to the ecEncCtx for which to set the salt + \param salt pointer to salt buffer + \param len length salt in bytes + + _Example_ + \code + ecEncCtx* srvCtx; + WC_WC_RNG rng; + byte cliSalt[] = { fixed salt data }; + word32 cliSaltLen = (word32)sizeof(cliSalt); + int ret; + + wc_InitRng(&rng); + cliCtx = wc_ecc_ctx_new(REQ_RESP_SERVER, &rng); + + ret = wc_ecc_ctx_set_kdf_salt(&cliCtx, cliSalt, cliSaltLen); + \endcode + + \sa wc_ecc_ctx_get_own_salt + \sa wc_ecc_ctx_get_peer_salt +*/ + +int wc_ecc_ctx_set_kdf_salt(ecEncCtx* ctx, const byte* salt, word32 len); + /*! \ingroup ECC diff --git a/tests/api.c b/tests/api.c index a19bcf2b1..dd14c617b 100644 --- a/tests/api.c +++ b/tests/api.c @@ -25514,6 +25514,9 @@ static int test_wc_ecc_encryptDecrypt (void) word32 msgSz = (word32)XSTRLEN("EccBlock Size 16"); #ifdef WOLFSSL_ECIES_OLD byte out[(sizeof("EccBlock Size 16") - 1) + WC_SHA256_DIGEST_SIZE]; +#elif defined(WOLFSSL_ECIES_GEN_IV) + byte out[KEY20 * 2 + 1 + AES_BLOCK_SIZE + + (sizeof("EccBlock Size 16") - 1) + WC_SHA256_DIGEST_SIZE]; #else byte out[KEY20 * 2 + 1 + (sizeof("EccBlock Size 16") - 1) + WC_SHA256_DIGEST_SIZE]; #endif diff --git a/wolfcrypt/src/ecc.c b/wolfcrypt/src/ecc.c index 9397c43bd..085515838 100644 --- a/wolfcrypt/src/ecc.c +++ b/wolfcrypt/src/ecc.c @@ -12436,6 +12436,31 @@ int wc_ecc_ctx_set_peer_salt(ecEncCtx* ctx, const byte* salt) return 0; } +/* Set the salt pointer into context. + * + * @param [in, out] ctx ECIES context object. + * @param [in] salt Salt to use with KDF. + * @param [in] len Length of salt in bytes. + * @return 0 on success. + * @return BAD_FUNC_ARG when ctx is NULL or salt is NULL and len is not 0. + */ +int wc_ecc_ctx_set_kdf_salt(ecEncCtx* ctx, const byte* salt, word32 len) +{ + if (ctx == NULL || (salt == NULL && len != 0)) + return BAD_FUNC_ARG; + + ctx->kdfSalt = salt; + ctx->kdfSaltSz = len; + + if (ctx->protocol == REQ_RESP_CLIENT) { + ctx->srvSt = ecSRV_SALT_SET; + } + else if (ctx->protocol == REQ_RESP_SERVER) { + ctx->srvSt = ecSRV_SALT_SET; + } + + return 0; +} static int ecc_ctx_set_salt(ecEncCtx* ctx, int flags) { @@ -12553,12 +12578,12 @@ static int ecc_get_key_sizes(ecEncCtx* ctx, int* encKeySz, int* ivSz, #if !defined(NO_AES) && defined(WOLFSSL_AES_COUNTER) case ecAES_128_CTR: *encKeySz = KEY_SIZE_128; - *ivSz = IV_SIZE_128; + *ivSz = 12; *blockSz = 1; break; case ecAES_256_CTR: *encKeySz = KEY_SIZE_256; - *ivSz = IV_SIZE_128; + *ivSz = 12; *blockSz = 1; break; #endif @@ -12596,7 +12621,9 @@ int wc_ecc_encrypt_ex(ecc_key* privKey, ecc_key* pubKey, const byte* msg, int ret = 0; word32 blockSz = 0; #ifndef WOLFSSL_ECIES_OLD +#ifndef WOLFSSL_ECIES_GEN_IV byte iv[ECC_MAX_IV_SIZE]; +#endif word32 pubKeySz = 0; #endif word32 digestSz = 0; @@ -12676,6 +12703,9 @@ int wc_ecc_encrypt_ex(ecc_key* privKey, ecc_key* pubKey, const byte* msg, #ifdef WOLFSSL_ECIES_OLD if (*outSz < (msgSz + digestSz)) return BUFFER_E; +#elif defined(WOLFSSL_ECIES_GEN_IV) + if (*outSz < (pubKeySz + ivSz + msgSz + digestSz)) + return BUFFER_E; #else if (*outSz < (pubKeySz + msgSz + digestSz)) return BUFFER_E; @@ -12757,13 +12787,21 @@ int wc_ecc_encrypt_ex(ecc_key* privKey, ecc_key* pubKey, const byte* msg, encKey = keys + offset; encIv = encKey + encKeySz; macKey = encKey + encKeySz + ivSz; + #elif defined(WOLFSSL_ECIES_GEN_IV) + encKey = keys + offset; + encIv = out; + out += ivSz; + macKey = encKey + encKeySz; + ret = wc_RNG_GenerateBlock(privKey->rng, encIv, ivSz); #else XMEMSET(iv, 0, ivSz); encKey = keys + offset; encIv = iv; macKey = encKey + encKeySz; #endif + } + if (ret == 0) { switch (ctx->encAlgo) { case ecAES_128_CBC: case ecAES_256_CBC: @@ -12805,19 +12843,26 @@ int wc_ecc_encrypt_ex(ecc_key* privKey, ecc_key* pubKey, const byte* msg, case ecAES_256_CTR: { #if !defined(NO_AES) && defined(WOLFSSL_AES_COUNTER) - #ifdef WOLFSSL_SMALL_STACK + byte ctr_iv[AES_BLOCK_SIZE]; + #ifndef WOLFSSL_SMALL_STACK + Aes aes[1]; + #else Aes *aes = (Aes *)XMALLOC(sizeof *aes, ctx->heap, DYNAMIC_TYPE_AES); if (aes == NULL) { ret = MEMORY_E; break; } - #else - Aes aes[1]; #endif + + /* Include 4 byte counter starting at all zeros. */ + XMEMCPY(ctr_iv, encIv, WOLFSSL_ECIES_GEN_IV_SIZE); + XMEMSET(ctr_iv + WOLFSSL_ECIES_GEN_IV_SIZE, 0, + AES_BLOCK_SIZE - WOLFSSL_ECIES_GEN_IV_SIZE); + ret = wc_AesInit(aes, NULL, INVALID_DEVID); if (ret == 0) { - ret = wc_AesSetKey(aes, encKey, encKeySz, encIv, + ret = wc_AesSetKey(aes, encKey, encKeySz, ctr_iv, AES_ENCRYPTION); if (ret == 0) { ret = wc_AesCtrEncrypt(aes, out, msg, msgSz); @@ -12861,8 +12906,14 @@ int wc_ecc_encrypt_ex(ecc_key* privKey, ecc_key* pubKey, const byte* msg, if (ret == 0) { ret = wc_HmacSetKey(hmac, WC_SHA256, macKey, WC_SHA256_DIGEST_SIZE); - if (ret == 0) + if (ret == 0) { + #if !defined(WOLFSSL_ECIES_GEN_IV) ret = wc_HmacUpdate(hmac, out, msgSz); + #else + /* IV is before encrypted message. */ + ret = wc_HmacUpdate(hmac, encIv, ivSz + msgSz); + #endif + } if (ret == 0) ret = wc_HmacUpdate(hmac, ctx->macSalt, ctx->macSaltSz); if (ret == 0) @@ -12884,6 +12935,8 @@ int wc_ecc_encrypt_ex(ecc_key* privKey, ecc_key* pubKey, const byte* msg, if (ret == 0) { #ifdef WOLFSSL_ECIES_OLD *outSz = msgSz + digestSz; +#elif defined(WOLFSSL_ECIES_GEN_IV) + *outSz = pubKeySz + ivSz + msgSz + digestSz; #else *outSz = pubKeySz + msgSz + digestSz; #endif @@ -12918,7 +12971,9 @@ int wc_ecc_decrypt(ecc_key* privKey, ecc_key* pubKey, const byte* msg, int ret = 0; word32 blockSz = 0; #ifndef WOLFSSL_ECIES_OLD +#ifndef WOLFSSL_ECIES_GEN_IV byte iv[ECC_MAX_IV_SIZE]; +#endif word32 pubKeySz = 0; #ifdef WOLFSSL_SMALL_STACK ecc_key* peerKey = NULL; @@ -12949,7 +13004,7 @@ int wc_ecc_decrypt(ecc_key* privKey, ecc_key* pubKey, const byte* msg, int ivSz = 0; int offset = 0; /* in case using msg exchange */ byte* encKey = NULL; - byte* encIv = NULL; + const byte* encIv = NULL; byte* macKey = NULL; @@ -13006,6 +13061,14 @@ int wc_ecc_decrypt(ecc_key* privKey, ecc_key* pubKey, const byte* msg, if (*outSz < (msgSz - digestSz)) return BUFFER_E; +#elif defined(WOLFSSL_ECIES_GEN_IV) + if (((msgSz - ivSz - digestSz - pubKeySz) % blockSz) != 0) + return BAD_PADDING_E; + + if (msgSz < pubKeySz + ivSz + blockSz + digestSz) + return BAD_FUNC_ARG; + if (*outSz < (msgSz - ivSz - digestSz - pubKeySz)) + return BUFFER_E; #else if (((msgSz - digestSz - pubKeySz) % blockSz) != 0) return BAD_PADDING_E; @@ -13117,6 +13180,12 @@ int wc_ecc_decrypt(ecc_key* privKey, ecc_key* pubKey, const byte* msg, encKey = keys + offset; encIv = encKey + encKeySz; macKey = encKey + encKeySz + ivSz; + #elif defined(WOLFSSL_ECIES_GEN_IV) + encKey = keys + offset; + encIv = msg; + msg += ivSz; + msgSz -= ivSz; + macKey = encKey + encKeySz; #else XMEMSET(iv, 0, ivSz); encKey = keys + offset; @@ -13143,7 +13212,12 @@ int wc_ecc_decrypt(ecc_key* privKey, ecc_key* pubKey, const byte* msg, ret = wc_HmacSetKey(hmac, WC_SHA256, macKey, WC_SHA256_DIGEST_SIZE); if (ret == 0) + #if !defined(WOLFSSL_ECIES_GEN_IV) ret = wc_HmacUpdate(hmac, msg, msgSz-digestSz); + #else + /* IV is before encrypted message. */ + ret = wc_HmacUpdate(hmac, encIv, ivSz+msgSz-digestSz); + #endif if (ret == 0) ret = wc_HmacUpdate(hmac, ctx->macSalt, ctx->macSaltSz); @@ -13220,7 +13294,12 @@ int wc_ecc_decrypt(ecc_key* privKey, ecc_key* pubKey, const byte* msg, #endif ret = wc_AesInit(aes, NULL, INVALID_DEVID); if (ret == 0) { - ret = wc_AesSetKey(aes, encKey, encKeySz, encIv, + byte ctr_iv[AES_BLOCK_SIZE]; + /* Make a 16 byte IV from the bytes passed in. */ + XMEMCPY(ctr_iv, encIv, WOLFSSL_ECIES_GEN_IV_SIZE); + XMEMSET(ctr_iv + WOLFSSL_ECIES_GEN_IV_SIZE, 0, + AES_BLOCK_SIZE - WOLFSSL_ECIES_GEN_IV_SIZE); + ret = wc_AesSetKey(aes, encKey, encKeySz, ctr_iv, AES_ENCRYPTION); if (ret == 0) { ret = wc_AesCtrEncrypt(aes, out, msg, msgSz-digestSz); diff --git a/wolfcrypt/test/test.c b/wolfcrypt/test/test.c index ec7d34603..d117813b6 100644 --- a/wolfcrypt/test/test.c +++ b/wolfcrypt/test/test.c @@ -25183,6 +25183,34 @@ static int ecc_encrypt_kat(WC_RNG *rng) 0xf4, 0x95, 0xd4, 0xcf, 0x30, 0xd6, 0xa2, 0xc5, 0x35, 0x96, 0x6a, 0xd4, 0x36, 0x15, 0xa9, 0xbd, 0x7f +#elif defined(WOLFSSL_ECIES_GEN_IV) + /* EC P-256 point */ + 0x04, + /* X */ + 0x50, 0xf2, 0x93, 0xa2, 0x48, 0xa9, 0xc0, 0x5a, + 0x9a, 0xa7, 0x70, 0x34, 0xb7, 0x7f, 0x4c, 0x3a, + 0xad, 0xfc, 0xd8, 0xb6, 0x76, 0x0a, 0xe3, 0xc1, + 0x87, 0x17, 0x07, 0x2d, 0x8d, 0xa3, 0x63, 0xa0, + /* Y */ + 0xc1, 0x27, 0xb2, 0x97, 0x9b, 0x84, 0xe7, 0xcd, + 0x20, 0x65, 0x8d, 0x2b, 0x6a, 0x93, 0x75, 0xaa, + 0x8b, 0xe1, 0x3a, 0x7b, 0x24, 0x1a, 0xbe, 0xe8, + 0x36, 0xd2, 0xe6, 0x34, 0x8a, 0x7a, 0xb3, 0x28, + /* IV */ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + /* Encrypted Msg */ + 0xe5, 0x17, 0xaf, 0x0d, 0x65, 0x4d, 0x3d, 0x50, + 0x96, 0x05, 0xc9, 0x63, 0x2c, 0xef, 0x1c, 0x1f, + 0x78, 0xc9, 0x90, 0x7a, 0x14, 0x00, 0xfc, 0x44, + 0x71, 0x6d, 0x57, 0x8c, 0xdf, 0x23, 0xca, 0x65, + 0xcf, 0x93, 0x06, 0xb6, 0x9a, 0xf4, 0x61, 0xbd, + 0x44, 0x1a, 0xeb, 0x52, 0x68, 0x0f, 0xd1, 0xde, + /* HMAC */ + 0x5a, 0x22, 0xc1, 0x5d, 0x99, 0x66, 0x3f, 0x24, + 0x35, 0x96, 0xac, 0xf7, 0xf6, 0x28, 0x45, 0x16, + 0x52, 0x19, 0x0d, 0xe4, 0xb2, 0xca, 0x5b, 0x28, + 0x4e, 0xbb, 0xf3, 0x98, 0x57, 0xd7, 0x3b, 0xe2 #else 0x04, 0x50, 0xf2, 0x93, 0xa2, 0x48, 0xa9, 0xc0, 0x5a, 0x9a, 0xa7, 0x70, 0x34, 0xb7, 0x7f, 0x4c, @@ -25327,6 +25355,8 @@ static int ecc_encrypt_e2e_test(WC_RNG* rng, ecc_key* userA, ecc_key* userB, byte plain[48]; #ifdef WOLFSSL_ECIES_OLD byte out[80]; +#elif defined(WOLFSSL_ECIES_GEN_IV) + byte out[1 + ECC_KEYGEN_SIZE * 2 + 16 + 80]; #else byte out[1 + ECC_KEYGEN_SIZE * 2 + 80]; #endif @@ -25342,6 +25372,8 @@ static int ecc_encrypt_e2e_test(WC_RNG* rng, ecc_key* userA, ecc_key* userB, byte plain2[48]; #ifdef WOLFSSL_ECIES_OLD byte out2[80]; +#elif defined(WOLFSSL_ECIES_GEN_IV) + byte out2[1 + ECC_KEYGEN_SIZE * 2 + 16 + 80]; #else byte out2[1 + ECC_KEYGEN_SIZE * 2 + 80]; #endif diff --git a/wolfssl/wolfcrypt/ecc.h b/wolfssl/wolfcrypt/ecc.h index e4676f593..1b2e6a12e 100644 --- a/wolfssl/wolfcrypt/ecc.h +++ b/wolfssl/wolfcrypt/ecc.h @@ -850,6 +850,10 @@ enum ecFlags { REQ_RESP_SERVER = 2 }; +#ifndef WOLFSSL_ECIES_GEN_IV_SIZE +#define WOLFSSL_ECIES_GEN_IV_SIZE 12 +#endif + typedef struct ecEncCtx ecEncCtx; @@ -870,6 +874,8 @@ const byte* wc_ecc_ctx_get_own_salt(ecEncCtx* ctx); WOLFSSL_API int wc_ecc_ctx_set_peer_salt(ecEncCtx* ctx, const byte* salt); WOLFSSL_API +int wc_ecc_ctx_set_kdf_salt(ecEncCtx* ctx, const byte* salt, word32 sz); +WOLFSSL_API int wc_ecc_ctx_set_info(ecEncCtx* ctx, const byte* info, int sz); WOLFSSL_API