Merge pull request #5308 from SparkiDev/ecies_gen_iv

ECIES: Google Pay generates IV and places it before msg
This commit is contained in:
David Garske
2022-07-20 06:46:14 -07:00
committed by GitHub
6 changed files with 171 additions and 10 deletions

View File

@ -3041,7 +3041,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 ]
)
@ -3065,6 +3065,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)

View File

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

View File

@ -25573,6 +25573,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

View File

@ -12452,6 +12452,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)
{
@ -12569,12 +12594,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
@ -12612,7 +12637,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;
@ -12692,6 +12719,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;
@ -12773,13 +12803,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:
@ -12821,19 +12859,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);
@ -12877,8 +12922,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)
@ -12900,6 +12951,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
@ -12934,7 +12987,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;
@ -12965,7 +13020,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;
@ -13022,6 +13077,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;
@ -13133,6 +13196,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;
@ -13159,7 +13228,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);
@ -13236,7 +13310,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);

View File

@ -25213,6 +25213,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,
@ -25357,6 +25385,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
@ -25372,6 +25402,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

View File

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