ECIES: Support SEC 1 and ISO 18033

Default is SEC 1.
To use old ECIES implementation: --enable-eccencrypt=old or define
WOLFSSL_ECIES_OLD
To use ISO-18033 implememtation: --enable-eccencrypt=iso18033 or
define WOLFSSL_ECIES_ISO18033
Support passing NULL for public key into wc_ecc_decrypt().
Support not having public key in privKey passed into wc_ecc_encrypt() -
public key is calculated and stored in priKey.
Add decrypt KAT test for ECIES.
This commit is contained in:
Sean Parkinson
2021-07-14 15:23:26 +10:00
parent 8e6c31b15d
commit 31dde4706e
5 changed files with 538 additions and 50 deletions

View File

@ -2257,12 +2257,12 @@ fi
# ECC encrypt
AC_ARG_ENABLE([eccencrypt],
[AS_HELP_STRING([--enable-eccencrypt],[Enable ECC encrypt (default: disabled)])],
[AS_HELP_STRING([--enable-eccencrypt],[Enable ECC encrypt (default: disabled). yes = SEC1 standard, iso18033 = ISO 18033 standard, old = original wolfSSL algorithm])],
[ ENABLED_ECC_ENCRYPT=$enableval ],
[ ENABLED_ECC_ENCRYPT=no ]
)
if test "$ENABLED_ECC_ENCRYPT" = "yes"
if test "$ENABLED_ECC_ENCRYPT" != "no"
then
if test "$ENABLED_ECC" = "no"
then
@ -2273,6 +2273,14 @@ then
AC_MSG_ERROR([cannot enable eccencrypt without enabling hkdf.])
fi
AM_CFLAGS="$AM_CFLAGS -DHAVE_ECC_ENCRYPT"
if test "$ENABLED_ECC_ENCRYPT" = "old"
then
AM_CFLAGS="$AM_CFLAGS -DWOLFSSL_ECIES_OLD"
fi
if test "$ENABLED_ECC_ENCRYPT" = "iso18033"
then
AM_CFLAGS="$AM_CFLAGS -DWOLFSSL_ECIES_ISO18033"
fi
fi
# Elliptic Curve-Based Certificateless Signatures for Identity-Based Encryption (ECCSI)

View File

@ -23021,11 +23021,15 @@ static int test_wc_ecc_encryptDecrypt (void)
#if defined(HAVE_ECC) && defined(HAVE_ECC_ENCRYPT) && defined(WOLFSSL_AES_128) \
&& !defined(WC_NO_RNG)
ecc_key srvKey, cliKey;
ecc_key srvKey, cliKey, tmpKey;
WC_RNG rng;
const char* msg = "EccBlock Size 16";
word32 msgSz = (word32)XSTRLEN(msg);
#ifdef WOLFSSL_ECIES_OLD
byte out[XSTRLEN(msg) + WC_SHA256_DIGEST_SIZE];
#else
byte out[KEY20 * 2 + 1 + XSTRLEN(msg) + WC_SHA256_DIGEST_SIZE];
#endif
word32 outSz = (word32)sizeof(out);
byte plain[XSTRLEN(msg) + 1];
word32 plainSz = (word32)sizeof(plain);
@ -23050,6 +23054,9 @@ static int test_wc_ecc_encryptDecrypt (void)
if (ret == 0) {
ret = wc_ecc_make_key(&rng, keySz, &srvKey);
}
if (ret == 0) {
ret = wc_ecc_init(&tmpKey);
}
}
#if defined(ECC_TIMING_RESISTANT) && (!defined(HAVE_FIPS) || \
@ -23098,27 +23105,38 @@ static int test_wc_ecc_encryptDecrypt (void)
printf(resultFmt, ret == 0 ? passed : failed);
printf(testingFmt, "wc_ecc_decrypt()");
#ifdef WOLFSSL_ECIES_OLD
if (ret == 0) {
ret = wc_ecc_decrypt(&srvKey, &cliKey, out, outSz, plain,
tmpKey.dp = cliKey.dp;
ret = wc_ecc_copy_point(&cliKey.pubkey, &tmpKey.pubkey);
}
#endif
if (ret == 0) {
ret = wc_ecc_decrypt(&srvKey, &tmpKey, out, outSz, plain,
&plainSz, NULL);
}
if (ret == 0) {
ret = wc_ecc_decrypt(NULL, &cliKey, out, outSz, plain,
ret = wc_ecc_decrypt(NULL, &tmpKey, out, outSz, plain,
&plainSz, NULL);
#ifdef WOLFSSL_ECIES_OLD
/* NULL parameter allowed in new implementations - public key comes from
* the message. */
if (ret == BAD_FUNC_ARG) {
ret = wc_ecc_decrypt(&srvKey, NULL, out, outSz, plain,
&plainSz, NULL);
}
#endif
if (ret == BAD_FUNC_ARG) {
ret = wc_ecc_decrypt(&srvKey, &cliKey, NULL, outSz, plain,
ret = wc_ecc_decrypt(&srvKey, &tmpKey, NULL, outSz, plain,
&plainSz, NULL);
}
if (ret == BAD_FUNC_ARG) {
ret = wc_ecc_decrypt(&srvKey, &cliKey, out, outSz, NULL,
ret = wc_ecc_decrypt(&srvKey, &tmpKey, out, outSz, NULL,
&plainSz, NULL);
}
if (ret == BAD_FUNC_ARG) {
ret = wc_ecc_decrypt(&srvKey, &cliKey, out, outSz,
ret = wc_ecc_decrypt(&srvKey, &tmpKey, out, outSz,
plain, NULL, NULL);
}
if (ret == BAD_FUNC_ARG) {
@ -23137,6 +23155,7 @@ static int test_wc_ecc_encryptDecrypt (void)
if (wc_FreeRng(&rng) && ret == 0) {
ret = WOLFSSL_FATAL_ERROR;
}
wc_ecc_free(&tmpKey);
wc_ecc_free(&cliKey);
wc_ecc_free(&srvKey);

View File

@ -9148,8 +9148,8 @@ int wc_ecc_import_raw_ex(ecc_key* key, const char* qx, const char* qy,
}
/* Import x, y and optional private (d) as unsigned binary */
int wc_ecc_import_unsigned(ecc_key* key, byte* qx, byte* qy,
byte* d, int curve_id)
int wc_ecc_import_unsigned(ecc_key* key, const byte* qx, const byte* qy,
const byte* d, int curve_id)
{
return wc_ecc_import_raw_private(key, (const char*)qx, (const char*)qy,
(const char*)d, curve_id, WC_TYPE_UNSIGNED_BIN);
@ -9195,6 +9195,20 @@ int wc_ecc_import_raw(ecc_key* key, const char* qx, const char* qy,
}
#endif /* HAVE_ECC_KEY_IMPORT */
#if defined(HAVE_ECC_ENCRYPT) && !defined(WOLFSSL_ECIES_OLD)
/* public key size in octets */
static int ecc_public_key_size(ecc_key* key, word32* sz)
{
if (key == NULL || key->dp == NULL)
return BAD_FUNC_ARG;
/* 'Uncompressed' | x | y */
*sz = 1 + 2 * key->dp->size;
return 0;
}
#endif
/* key size in octets */
int wc_ecc_size(ecc_key* key)
{
@ -11170,7 +11184,6 @@ void wc_ecc_ctx_free(ecEncCtx* ctx)
}
}
static int ecc_get_key_sizes(ecEncCtx* ctx, int* encKeySz, int* ivSz,
int* keysLen, word32* digestSz, word32* blockSz)
{
@ -11195,7 +11208,11 @@ static int ecc_get_key_sizes(ecEncCtx* ctx, int* encKeySz, int* ivSz,
} else
return BAD_FUNC_ARG;
#ifdef WOLFSSL_ECIES_OLD
*keysLen = *encKeySz + *ivSz + *digestSz;
#else
*keysLen = *encKeySz + *digestSz;
#endif
return 0;
}
@ -11210,16 +11227,29 @@ int wc_ecc_encrypt(ecc_key* privKey, ecc_key* pubKey, const byte* msg,
{
int ret = 0;
word32 blockSz;
#ifndef WOLFSSL_ECIES_OLD
byte iv[ECC_MAX_IV_SIZE];
word32 pubKeySz;
#endif
word32 digestSz;
ecEncCtx localCtx;
#ifdef WOLFSSL_SMALL_STACK
byte* sharedSecret;
byte* keys;
#else
#if defined(WOLFSSL_ECIES_OLD) || !defined(WOLFSSL_ECIES_ISO18033)
byte sharedSecret[ECC_MAXSIZE]; /* 521 max size */
#else
byte sharedSecret[ECC_MAXSIZE * 3 + 1]; /* Public key too */
#endif
byte keys[ECC_BUFSIZE]; /* max size */
#endif
#if defined(WOLFSSL_ECIES_OLD) || !defined(WOLFSSL_ECIES_ISO18033)
word32 sharedSz = ECC_MAXSIZE;
#else
/* 'Uncompressed' byte | public key x | public key y | secret */
word32 sharedSz = 1 + ECC_MAXSIZE * 3;
#endif
int keysLen;
int encKeySz;
int ivSz;
@ -11242,6 +11272,10 @@ int wc_ecc_encrypt(ecc_key* privKey, ecc_key* pubKey, const byte* msg,
if (ret != 0)
return ret;
#ifndef WOLFSSL_ECIES_OLD
pubKeySz = 1 + wc_ecc_size(privKey) * 2;
#endif
if (ctx->protocol == REQ_RESP_SERVER) {
offset = keysLen;
keysLen *= 2;
@ -11264,35 +11298,66 @@ int wc_ecc_encrypt(ecc_key* privKey, ecc_key* pubKey, const byte* msg,
if ( (msgSz%blockSz) != 0)
return BAD_PADDING_E;
#ifdef WOLFSSL_ECIES_OLD
if (*outSz < (msgSz + digestSz))
return BUFFER_E;
#else
if (*outSz < (pubKeySz + msgSz + digestSz))
return BUFFER_E;
#endif
#ifdef ECC_TIMING_RESISTANT
if (ctx->rng != NULL && privKey->rng == NULL)
privKey->rng = ctx->rng;
#endif
#ifndef WOLFSSL_ECIES_OLD
if (privKey->type == ECC_PRIVATEKEY_ONLY) {
ret = wc_ecc_make_pub_ex(privKey, NULL, privKey->rng);
if (ret != 0)
return ret;
}
ret = wc_ecc_export_x963(privKey, out, &pubKeySz);
if (ret != 0)
return ret;
out += pubKeySz;
#endif
#ifdef WOLFSSL_SMALL_STACK
sharedSecret = (byte*)XMALLOC(ECC_MAXSIZE, NULL, DYNAMIC_TYPE_ECC_BUFFER);
sharedSecret = (byte*)XMALLOC(sharedSz, ctx->heap, DYNAMIC_TYPE_ECC_BUFFER);
if (sharedSecret == NULL)
return MEMORY_E;
keys = (byte*)XMALLOC(ECC_BUFSIZE, NULL, DYNAMIC_TYPE_ECC_BUFFER);
keys = (byte*)XMALLOC(ECC_BUFSIZE, ctx->heap, DYNAMIC_TYPE_ECC_BUFFER);
if (keys == NULL) {
XFREE(sharedSecret, NULL, DYNAMIC_TYPE_ECC_BUFFER);
XFREE(sharedSecret, ctx->heap, DYNAMIC_TYPE_ECC_BUFFER);
return MEMORY_E;
}
#endif
#ifdef WOLFSSL_ECIES_ISO18033
XMEMCPY(sharedSecret, out - pubKeySz, pubKeySz);
sharedSz -= pubKeySz;
#endif
do {
#if defined(WOLFSSL_ASYNC_CRYPT) && defined(WC_ASYNC_ENABLE_ECC)
ret = wc_AsyncWait(ret, &privKey->asyncDev, WC_ASYNC_FLAG_CALL_AGAIN);
if (ret != 0)
break;
#endif
#ifndef WOLFSSL_ECIES_ISO18033
ret = wc_ecc_shared_secret(privKey, pubKey, sharedSecret, &sharedSz);
#else
ret = wc_ecc_shared_secret(privKey, pubKey, sharedSecret + pubKeySz,
&sharedSz);
#endif
} while (ret == WC_PENDING_E);
if (ret == 0) {
#ifdef WOLFSSL_ECIES_ISO18033
/* KDF data is encoded public key and secret. */
sharedSz += pubKeySz;
#endif
switch (ctx->kdfAlgo) {
case ecHKDF_SHA256 :
ret = wc_HKDF(WC_SHA256, sharedSecret, sharedSz, ctx->kdfSalt,
@ -11307,15 +11372,22 @@ int wc_ecc_encrypt(ecc_key* privKey, ecc_key* pubKey, const byte* msg,
}
if (ret == 0) {
#ifdef WOLFSSL_ECIES_OLD
encKey = keys + offset;
encIv = encKey + encKeySz;
macKey = encKey + encKeySz + ivSz;
#else
XMEMSET(iv, 0, ivSz);
encKey = keys + offset;
encIv = iv;
macKey = encKey + encKeySz;
#endif
switch (ctx->encAlgo) {
case ecAES_128_CBC:
{
#ifdef WOLFSSL_SMALL_STACK
Aes *aes = (Aes *)XMALLOC(sizeof *aes, NULL,
Aes *aes = (Aes *)XMALLOC(sizeof *aes, ctx->heap,
DYNAMIC_TYPE_AES);
if (aes == NULL) {
ret = MEMORY_E;
@ -11338,7 +11410,7 @@ int wc_ecc_encrypt(ecc_key* privKey, ecc_key* pubKey, const byte* msg,
wc_AesFree(aes);
}
#ifdef WOLFSSL_SMALL_STACK
XFREE(aes, NULL, DYNAMIC_TYPE_AES);
XFREE(aes, ctx->heap, DYNAMIC_TYPE_AES);
#endif
if (ret != 0)
break;
@ -11356,7 +11428,7 @@ int wc_ecc_encrypt(ecc_key* privKey, ecc_key* pubKey, const byte* msg,
case ecHMAC_SHA256:
{
#ifdef WOLFSSL_SMALL_STACK
Hmac *hmac = (Hmac *)XMALLOC(sizeof *hmac, NULL,
Hmac *hmac = (Hmac *)XMALLOC(sizeof *hmac, ctx->heap,
DYNAMIC_TYPE_HMAC);
if (hmac == NULL) {
ret = MEMORY_E;
@ -11377,7 +11449,7 @@ int wc_ecc_encrypt(ecc_key* privKey, ecc_key* pubKey, const byte* msg,
wc_HmacFree(hmac);
}
#ifdef WOLFSSL_SMALL_STACK
XFREE(hmac, NULL, DYNAMIC_TYPE_HMAC);
XFREE(hmac, ctx->heap, DYNAMIC_TYPE_HMAC);
#endif
}
break;
@ -11388,12 +11460,17 @@ int wc_ecc_encrypt(ecc_key* privKey, ecc_key* pubKey, const byte* msg,
}
}
if (ret == 0)
if (ret == 0) {
#ifdef WOLFSSL_ECIES_OLD
*outSz = msgSz + digestSz;
#else
*outSz = pubKeySz + msgSz + digestSz;
#endif
}
#ifdef WOLFSSL_SMALL_STACK
XFREE(sharedSecret, NULL, DYNAMIC_TYPE_ECC_BUFFER);
XFREE(keys, NULL, DYNAMIC_TYPE_ECC_BUFFER);
XFREE(sharedSecret, ctx->heap, DYNAMIC_TYPE_ECC_BUFFER);
XFREE(keys, ctx->heap, DYNAMIC_TYPE_ECC_BUFFER);
#endif
return ret;
@ -11408,16 +11485,33 @@ int wc_ecc_decrypt(ecc_key* privKey, ecc_key* pubKey, const byte* msg,
{
int ret = 0;
word32 blockSz;
#ifndef WOLFSSL_ECIES_OLD
byte iv[ECC_MAX_IV_SIZE];
word32 pubKeySz;
#ifdef WOLFSSL_SMALL_STACK
ecc_key* peerKey = NULL;
#else
ecc_key peerKey[1];
#endif
#endif
word32 digestSz;
ecEncCtx localCtx;
#ifdef WOLFSSL_SMALL_STACK
byte* sharedSecret;
byte* keys;
#else
#if defined(WOLFSSL_ECIES_OLD) || !defined(WOLFSSL_ECIES_ISO18033)
byte sharedSecret[ECC_MAXSIZE]; /* 521 max size */
#else
byte sharedSecret[ECC_MAXSIZE * 3 + 1]; /* Public key too */
#endif
byte keys[ECC_BUFSIZE]; /* max size */
#endif
#if defined(WOLFSSL_ECIES_OLD) || !defined(WOLFSSL_ECIES_ISO18033)
word32 sharedSz = ECC_MAXSIZE;
#else
word32 sharedSz = ECC_MAXSIZE * 3 + 1;
#endif
int keysLen;
int encKeySz;
int ivSz;
@ -11426,9 +11520,13 @@ int wc_ecc_decrypt(ecc_key* privKey, ecc_key* pubKey, const byte* msg,
byte* encIv;
byte* macKey;
if (privKey == NULL || pubKey == NULL || msg == NULL || out == NULL ||
outSz == NULL)
if (privKey == NULL || msg == NULL || out == NULL || outSz == NULL)
return BAD_FUNC_ARG;
#ifdef WOLFSSL_ECIES_OLD
if (pubKey == NULL)
return BAD_FUNC_ARG;
#endif
if (ctx == NULL) { /* use defaults */
ecc_ctx_init(&localCtx, 0, NULL);
@ -11440,6 +11538,12 @@ int wc_ecc_decrypt(ecc_key* privKey, ecc_key* pubKey, const byte* msg,
if (ret != 0)
return ret;
#ifndef WOLFSSL_ECIES_OLD
ret = ecc_public_key_size(privKey, &pubKeySz);
if (ret != 0)
return ret;
#endif
if (ctx->protocol == REQ_RESP_CLIENT) {
offset = keysLen;
keysLen *= 2;
@ -11459,11 +11563,21 @@ int wc_ecc_decrypt(ecc_key* privKey, ecc_key* pubKey, const byte* msg,
if (keysLen > ECC_BUFSIZE) /* keys size */
return BUFFER_E;
#ifdef WOLFSSL_ECIES_OLD
if ( ((msgSz-digestSz) % blockSz) != 0)
return BAD_PADDING_E;
if (*outSz < (msgSz - digestSz))
return BUFFER_E;
#else
if ( ((msgSz-digestSz-pubKeySz) % blockSz) != 0)
return BAD_PADDING_E;
if (msgSz < pubKeySz + blockSz + digestSz)
return BAD_FUNC_ARG;
if (*outSz < (msgSz - digestSz - pubKeySz))
return BUFFER_E;
#endif
#ifdef ECC_TIMING_RESISTANT
if (ctx->rng != NULL && privKey->rng == NULL)
@ -11471,26 +11585,76 @@ int wc_ecc_decrypt(ecc_key* privKey, ecc_key* pubKey, const byte* msg,
#endif
#ifdef WOLFSSL_SMALL_STACK
sharedSecret = (byte*)XMALLOC(ECC_MAXSIZE, NULL, DYNAMIC_TYPE_ECC_BUFFER);
if (sharedSecret == NULL)
sharedSecret = (byte*)XMALLOC(sharedSz, ctx->heap, DYNAMIC_TYPE_ECC_BUFFER);
if (sharedSecret == NULL) {
#ifndef WOLFSSL_ECIES_OLD
if (pubKey == peerKey)
wc_ecc_free(peerKey);
#endif
return MEMORY_E;
}
keys = (byte*)XMALLOC(ECC_BUFSIZE, NULL, DYNAMIC_TYPE_ECC_BUFFER);
keys = (byte*)XMALLOC(ECC_BUFSIZE, ctx->heap, DYNAMIC_TYPE_ECC_BUFFER);
if (keys == NULL) {
XFREE(sharedSecret, NULL, DYNAMIC_TYPE_ECC_BUFFER);
XFREE(sharedSecret, ctx->heap, DYNAMIC_TYPE_ECC_BUFFER);
#ifndef WOLFSSL_ECIES_OLD
if (pubKey == peerKey)
wc_ecc_free(peerKey);
#endif
return MEMORY_E;
}
#endif
do {
#if defined(WOLFSSL_ASYNC_CRYPT) && defined(WC_ASYNC_ENABLE_ECC)
ret = wc_AsyncWait(ret, &privKey->asyncDev, WC_ASYNC_FLAG_CALL_AGAIN);
if (ret != 0)
break;
#endif
ret = wc_ecc_shared_secret(privKey, pubKey, sharedSecret, &sharedSz);
} while (ret == WC_PENDING_E);
#ifndef WOLFSSL_ECIES_OLD
if (pubKey == NULL) {
#ifdef WOLFSSL_SMALL_STACK
peerKey = (ecc_key*)XMALLOC(sizeof(*peerKey), ctx->heap,
DYNAMIC_TYPE_ECC_BUFFER);
if (peerKey == NULL)
ret = MEMORY_E;
#endif
pubKey = peerKey;
}
if (ret == 0) {
ret = wc_ecc_init_ex(pubKey, privKey->heap, INVALID_DEVID);
}
if (ret == 0) {
ret = wc_ecc_import_x963_ex(msg, pubKeySz, pubKey, privKey->dp->id);
}
if (ret == 0) {
/* Point is not MACed. */
msg += pubKeySz;
msgSz -= pubKeySz;
}
#endif
if (ret == 0) {
#ifdef WOLFSSL_ECIES_ISO18033
XMEMCPY(sharedSecret, msg - pubKeySz, pubKeySz);
sharedSz -= pubKeySz;
#endif
do {
#if defined(WOLFSSL_ASYNC_CRYPT) && defined(WC_ASYNC_ENABLE_ECC)
ret = wc_AsyncWait(ret, &privKey->asyncDev,
WC_ASYNC_FLAG_CALL_AGAIN);
if (ret != 0)
break;
#endif
#ifndef WOLFSSL_ECIES_ISO18033
ret = wc_ecc_shared_secret(privKey, pubKey, sharedSecret,
&sharedSz);
#else
ret = wc_ecc_shared_secret(privKey, pubKey, sharedSecret +
pubKeySz, &sharedSz);
#endif
} while (ret == WC_PENDING_E);
}
if (ret == 0) {
#ifdef WOLFSSL_ECIES_ISO18033
/* KDF data is encoded public key and secret. */
sharedSz += pubKeySz;
#endif
switch (ctx->kdfAlgo) {
case ecHKDF_SHA256 :
ret = wc_HKDF(WC_SHA256, sharedSecret, sharedSz, ctx->kdfSalt,
@ -11505,16 +11669,24 @@ int wc_ecc_decrypt(ecc_key* privKey, ecc_key* pubKey, const byte* msg,
}
if (ret == 0) {
#ifdef WOLFSSL_ECIES_OLD
encKey = keys + offset;
encIv = encKey + encKeySz;
macKey = encKey + encKeySz + ivSz;
#else
XMEMSET(iv, 0, ivSz);
encKey = keys + offset;
encIv = iv;
macKey = encKey + encKeySz;
#endif
switch (ctx->macAlgo) {
case ecHMAC_SHA256:
{
byte verify[WC_SHA256_DIGEST_SIZE];
#ifdef WOLFSSL_SMALL_STACK
Hmac *hmac = (Hmac *)XMALLOC(sizeof *hmac, NULL, DYNAMIC_TYPE_HMAC);
Hmac *hmac = (Hmac *)XMALLOC(sizeof *hmac, ctx->heap,
DYNAMIC_TYPE_HMAC);
if (hmac == NULL) {
ret = MEMORY_E;
break;
@ -11539,7 +11711,7 @@ int wc_ecc_decrypt(ecc_key* privKey, ecc_key* pubKey, const byte* msg,
wc_HmacFree(hmac);
}
#ifdef WOLFSSL_SMALL_STACK
XFREE(hmac, NULL, DYNAMIC_TYPE_HMAC);
XFREE(hmac, ctx->heap, DYNAMIC_TYPE_HMAC);
#endif
break;
}
@ -11556,7 +11728,7 @@ int wc_ecc_decrypt(ecc_key* privKey, ecc_key* pubKey, const byte* msg,
case ecAES_128_CBC:
{
#ifdef WOLFSSL_SMALL_STACK
Aes *aes = (Aes *)XMALLOC(sizeof *aes, NULL,
Aes *aes = (Aes *)XMALLOC(sizeof *aes, ctx->heap,
DYNAMIC_TYPE_AES);
if (aes == NULL) {
ret = MEMORY_E;
@ -11580,7 +11752,7 @@ int wc_ecc_decrypt(ecc_key* privKey, ecc_key* pubKey, const byte* msg,
wc_AesFree(aes);
}
#ifdef WOLFSSL_SMALL_STACK
XFREE(aes, NULL, DYNAMIC_TYPE_AES);
XFREE(aes, ctx->heap, DYNAMIC_TYPE_AES);
#endif
if (ret != 0)
break;
@ -11596,9 +11768,18 @@ int wc_ecc_decrypt(ecc_key* privKey, ecc_key* pubKey, const byte* msg,
if (ret == 0)
*outSz = msgSz - digestSz;
#ifndef WOLFSSL_ECIES_OLD
if (pubKey == peerKey)
wc_ecc_free(peerKey);
#endif
#ifdef WOLFSSL_SMALL_STACK
XFREE(sharedSecret, NULL, DYNAMIC_TYPE_ECC_BUFFER);
XFREE(keys, NULL, DYNAMIC_TYPE_ECC_BUFFER);
#ifndef WOLFSSL_ECIES_OLD
if (peerKey != NULL) {
XFREE(peerKey, ctx->heap, DYNAMIC_TYPE_ECC_BUFFER);
}
#endif
XFREE(sharedSecret, ctx->heap, DYNAMIC_TYPE_ECC_BUFFER);
XFREE(keys, ctx->heap, DYNAMIC_TYPE_ECC_BUFFER);
#endif
return ret;

View File

@ -23891,19 +23891,228 @@ done:
#if defined(HAVE_ECC_ENCRYPT) && defined(WOLFSSL_AES_128)
#if (!defined(NO_ECC256) || defined(HAVE_ALL_CURVES)) && ECC_MIN_KEY_SZ <= 256
static int ecc_encrypt_kat(WC_RNG *rng)
{
int ret = 0;
#ifdef WOLFSSL_ECIES_OLD
#ifdef WOLFSSL_SMALL_STACK
ecc_key* userA = NULL;
#else
ecc_key userA[1];
#endif
int userAInit = 0;
#endif
#ifdef WOLFSSL_SMALL_STACK
ecc_key* userB = NULL;
#else
ecc_key userB[1];
#endif
int userBInit = 0;
ecc_key* tmpKey;
byte plain[48];
word32 plainSz = sizeof(plain);
WOLFSSL_SMALL_STACK_STATIC const byte privKey[] = {
0x04, 0x80, 0xef, 0x1d, 0xbe, 0x02, 0x0c, 0x20,
0x5b, 0xab, 0x80, 0x35, 0x5b, 0x2a, 0x0f, 0x6d,
0xd3, 0xb0, 0x7f, 0x7e, 0x7f, 0x86, 0x8a, 0x49,
0xee, 0xb4, 0xaa, 0x09, 0x2d, 0x1e, 0x1d, 0x02
};
#ifdef WOLFSSL_ECIES_OLD
WOLFSSL_SMALL_STACK_STATIC const byte pubKey[] = {
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,
/* X */
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
};
#endif
WOLFSSL_SMALL_STACK_STATIC const byte enc_msg[] = {
#ifdef WOLFSSL_ECIES_OLD
0x42, 0x70, 0xbf, 0xf9, 0xf4, 0x7e, 0x4b, 0x9b,
0xb5, 0x4c, 0xcc, 0xc5, 0x94, 0xa7, 0xef, 0xaa,
0xc3, 0x7c, 0x85, 0xa6, 0x51, 0x6e, 0xd3, 0xfa,
0x56, 0xc9, 0x10, 0x4d, 0x14, 0x32, 0x61, 0xb8,
0xbb, 0x66, 0x7a, 0xb5, 0xbc, 0x95, 0xf8, 0xca,
0xd1, 0x2a, 0x19, 0x51, 0x44, 0xd8, 0x0e, 0x57,
0x34, 0xed, 0x45, 0x89, 0x2e, 0x57, 0xbe, 0xd5,
0x06, 0x22, 0xd7, 0x13, 0x0a, 0x0e, 0x40, 0x36,
0x0d, 0x05, 0x0d, 0xb6, 0xae, 0x61, 0x37, 0x18,
0x83, 0x90, 0x0a, 0x27, 0x95, 0x41, 0x8c, 0x45
#elif defined(WOLFSSL_ECIES_ISO18033)
0x04, 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, 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, 0xbb, 0x9f, 0xa8, 0x2d, 0xe1, 0xf1, 0x67,
0x45, 0x02, 0x19, 0xdc, 0xc8, 0x24, 0x8b, 0x20,
0x02, 0xa0, 0x8f, 0x95, 0x12, 0x55, 0x51, 0xf8,
0x03, 0xc4, 0x54, 0x13, 0x98, 0x2d, 0xf0, 0x31,
0x51, 0x80, 0x45, 0x24, 0xcb, 0x8b, 0x48, 0xa6,
0x8b, 0x8e, 0x97, 0x9c, 0x56, 0x4d, 0x70, 0x00,
0x53, 0xd3, 0x47, 0x00, 0x5a, 0x23, 0x8c, 0xf9,
0xfd, 0xd2, 0x33, 0x2c, 0x43, 0x6e, 0x9e, 0xb2,
0xf4, 0x95, 0xd4, 0xcf, 0x30, 0xd6, 0xa2, 0xc5,
0x35, 0x96, 0x6a, 0xd4, 0x36, 0x15, 0xa9, 0xbd,
0x7f
#else
0x04, 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, 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, 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, 0xc7, 0x3f, 0x6f, 0xce, 0xbe, 0x49, 0x61,
0x48, 0x01, 0x77, 0x41, 0xd0, 0xd8, 0x5b, 0x48,
0xca, 0x4e, 0x47, 0x3e, 0x47, 0xbf, 0x1d, 0x28,
0x4c, 0x18, 0x1a, 0xfb, 0x96, 0x95, 0xda, 0xde,
0x55
#endif
};
WOLFSSL_SMALL_STACK_STATIC const byte msg[] = {
0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f,
0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17,
0x18, 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f,
0x20, 0x21, 0x22, 0x23, 0x24, 0x25, 0x26, 0x27,
0x28, 0x29, 0x2a, 0x2b, 0x2c, 0x2d, 0x2e, 0x2f
};
#ifdef WOLFSSL_SMALL_STACK
userB = (ecc_key *)XMALLOC(sizeof(*userB), HEAP_HINT,
DYNAMIC_TYPE_TMP_BUFFER);
if (userB == NULL) {
ret = -10451;
}
#ifdef WOLFSSL_ECIES_OLD
if (ret == 0) {
userA = (ecc_key *)XMALLOC(sizeof(*userA), HEAP_HINT,
DYNAMIC_TYPE_TMP_BUFFER);
if (userA == NULL) {
ret = -10450;
}
}
#endif
#endif
if (ret == 0) {
ret = wc_ecc_init_ex(userB, HEAP_HINT, devId);
if (ret != 0)
ret = -10453;
}
if (ret == 0) {
userBInit = 1;
#ifdef WOLFSSL_ECIES_OLD
ret = wc_ecc_init_ex(userA, HEAP_HINT, devId);
if (ret != 0)
ret = -10452;
}
if (ret == 0) {
userAInit = 1;
tmpKey = userA;
#else
tmpKey = NULL;
#endif
}
if (ret == 0) {
ret = wc_ecc_import_private_key_ex(privKey, sizeof(privKey), NULL, 0,
userB, ECC_SECP256R1);
if (ret != 0)
ret = -10454;
}
#ifdef WOLFSSL_ECIES_OLD
if (ret == 0) {
ret = wc_ecc_import_x963_ex(pubKey, sizeof(pubKey), userA,
ECC_SECP256R1);
if (ret != 0)
ret = -10455;
}
#endif
#if defined(ECC_TIMING_RESISTANT) && (!defined(HAVE_FIPS) || \
(!defined(HAVE_FIPS_VERSION) || (HAVE_FIPS_VERSION != 2))) && \
!defined(HAVE_SELFTEST)
if (ret == 0) {
ret = wc_ecc_set_rng(userB, rng);
if (ret != 0) {
ret = -10456;
}
}
#endif
if (ret == 0) {
ret = wc_ecc_decrypt(userB, tmpKey, enc_msg, sizeof(enc_msg), plain,
&plainSz, NULL);
if (ret != 0)
ret = -10457;
}
if (ret == 0) {
if (XMEMCMP(plain, msg, sizeof(msg)) != 0) {
ret = -10458;
}
}
if (userBInit)
wc_ecc_free(userB);
#ifdef WOLFSSL_ECIES_OLD
if (userAInit)
wc_ecc_free(userA);
#endif
#ifdef WOLFSSL_SMALL_STACK
if (userB != NULL) {
XFREE(userB, HEAP_HINT, DYNAMIC_TYPE_TMP_BUFFER);
}
#ifdef WOLFSSL_ECIES_OLD
if (userA != NULL) {
XFREE(userA, HEAP_HINT, DYNAMIC_TYPE_TMP_BUFFER);
}
#endif
#endif
return ret;
}
#endif
WOLFSSL_TEST_SUBROUTINE int ecc_encrypt_test(void)
{
WC_RNG rng;
int ret = 0;
#ifdef WOLFSSL_SMALL_STACK
ecc_key *userA = (ecc_key *)XMALLOC(sizeof *userA, HEAP_HINT, DYNAMIC_TYPE_TMP_BUFFER),
*userB = (ecc_key *)XMALLOC(sizeof *userB, HEAP_HINT, DYNAMIC_TYPE_TMP_BUFFER);
*userB = (ecc_key *)XMALLOC(sizeof *userB, HEAP_HINT, DYNAMIC_TYPE_TMP_BUFFER),
*tmpKey = (ecc_key *)XMALLOC(sizeof *userB, HEAP_HINT, DYNAMIC_TYPE_TMP_BUFFER);
#else
ecc_key userA[1], userB[1];
ecc_key userA[1], userB[1], tmpKey[1];
#endif
byte msg[48];
byte plain[48];
#ifdef WOLFSSL_ECIES_OLD
byte out[80];
#else
byte out[1 + ECC_KEYGEN_SIZE * 2 + 80];
#endif
word32 outSz = sizeof(out);
word32 plainSz = sizeof(plain);
int i;
@ -23914,7 +24123,11 @@ WOLFSSL_TEST_SUBROUTINE int ecc_encrypt_test(void)
const byte* tmpSalt;
byte msg2[48];
byte plain2[48];
#ifdef WOLFSSL_ECIES_OLD
byte out2[80];
#else
byte out2[1 + ECC_KEYGEN_SIZE * 2 + 80];
#endif
word32 outSz2 = sizeof(out2);
word32 plainSz2 = sizeof(plain2);
@ -23939,6 +24152,9 @@ WOLFSSL_TEST_SUBROUTINE int ecc_encrypt_test(void)
if (ret != 0)
goto done;
ret = wc_ecc_init_ex(userB, HEAP_HINT, devId);
if (ret != 0)
goto done;
ret = wc_ecc_init_ex(tmpKey, HEAP_HINT, devId);
if (ret != 0)
goto done;
@ -23981,8 +24197,16 @@ WOLFSSL_TEST_SUBROUTINE int ecc_encrypt_test(void)
ret = -10405; goto done;
}
#ifdef WOLFSSL_ECIES_OLD
tmpKey->dp = userA->dp;
ret = wc_ecc_copy_point(&userA->pubkey, &tmpKey->pubkey);
if (ret != 0) {
ret = -10413; goto done;
}
#endif
/* decrypt msg from A */
ret = wc_ecc_decrypt(userB, userA, out, outSz, plain, &plainSz, NULL);
ret = wc_ecc_decrypt(userB, tmpKey, out, outSz, plain, &plainSz, NULL);
if (ret != 0) {
ret = -10406; goto done;
}
@ -23991,6 +24215,17 @@ WOLFSSL_TEST_SUBROUTINE int ecc_encrypt_test(void)
ret = -10407; goto done;
}
#ifndef WOLFSSL_ECIES_OLD
/* A decrypts msg (response) from B */
ret = wc_ecc_decrypt(userB, NULL, out, outSz, plain2, &plainSz2, NULL);
if (ret != 0)
goto done;
if (XMEMCMP(plain, msg, sizeof(msg)) != 0) {
ret = -10415; goto done;
}
#endif
/* let's verify message exchange works, A is client, B is server */
cliCtx = wc_ecc_ctx_new(REQ_RESP_CLIENT, &rng);
srvCtx = wc_ecc_ctx_new(REQ_RESP_SERVER, &rng);
@ -24032,9 +24267,12 @@ WOLFSSL_TEST_SUBROUTINE int ecc_encrypt_test(void)
if (ret != 0)
goto done;
#ifndef WOLFSSL_ECIES_OLD
wc_ecc_free(tmpKey);
#endif
/* B decrypts msg (request) from A */
plainSz = sizeof(plain);
ret = wc_ecc_decrypt(userB, userA, out, outSz, plain, &plainSz, srvCtx);
ret = wc_ecc_decrypt(userB, tmpKey, out, outSz, plain, &plainSz, srvCtx);
if (ret != 0)
goto done;
@ -24052,8 +24290,18 @@ WOLFSSL_TEST_SUBROUTINE int ecc_encrypt_test(void)
if (ret != 0)
goto done;
#ifdef WOLFSSL_ECIES_OLD
tmpKey->dp = userB->dp;
ret = wc_ecc_copy_point(&userB->pubkey, &tmpKey->pubkey);
if (ret != 0) {
ret = -10414; goto done;
}
#else
wc_ecc_free(tmpKey);
#endif
/* A decrypts msg (response) from B */
ret = wc_ecc_decrypt(userA, userB, out2, outSz2, plain2, &plainSz2,
ret = wc_ecc_decrypt(userA, tmpKey, out2, outSz2, plain2, &plainSz2,
cliCtx);
if (ret != 0)
goto done;
@ -24062,6 +24310,10 @@ WOLFSSL_TEST_SUBROUTINE int ecc_encrypt_test(void)
ret = -10412; goto done;
}
#if (!defined(NO_ECC256) || defined(HAVE_ALL_CURVES)) && ECC_MIN_KEY_SZ <= 256
ret = ecc_encrypt_kat(&rng);
#endif
done:
/* cleanup */
@ -24077,7 +24329,12 @@ done:
wc_ecc_free(userB);
XFREE(userB, HEAP_HINT, DYNAMIC_TYPE_TMP_BUFFER);
}
if (tmpKey != NULL) {
wc_ecc_free(tmpKey);
XFREE(tmpKey, HEAP_HINT, DYNAMIC_TYPE_TMP_BUFFER);
}
#else
wc_ecc_free(tmpKey);
wc_ecc_free(userB);
wc_ecc_free(userA);
#endif
@ -24098,9 +24355,11 @@ WOLFSSL_TEST_SUBROUTINE int ecc_test_buffers(void)
#ifdef WOLFSSL_SMALL_STACK
ecc_key *cliKey = (ecc_key *)XMALLOC(sizeof *cliKey, HEAP_HINT, DYNAMIC_TYPE_TMP_BUFFER);
ecc_key *servKey = (ecc_key *)XMALLOC(sizeof *servKey, HEAP_HINT, DYNAMIC_TYPE_TMP_BUFFER);
ecc_key *tmpKey = (ecc_key *)XMALLOC(sizeof *tmpKey, HEAP_HINT, DYNAMIC_TYPE_TMP_BUFFER);
#else
ecc_key cliKey[1];
ecc_key servKey[1];
ecc_key tmpKey[1];
#endif
WC_RNG rng;
word32 idx = 0;
@ -24114,7 +24373,7 @@ WOLFSSL_TEST_SUBROUTINE int ecc_test_buffers(void)
word32 x;
#ifdef WOLFSSL_SMALL_STACK
if ((cliKey == NULL) || (servKey == NULL))
if ((cliKey == NULL) || (servKey == NULL) || (tmpKey == NULL))
ERROR_OUT(MEMORY_E, done);
#endif
@ -24122,6 +24381,9 @@ WOLFSSL_TEST_SUBROUTINE int ecc_test_buffers(void)
if (ret != 0)
ERROR_OUT(-10420, done);
ret = wc_ecc_init_ex(servKey, HEAP_HINT, devId);
if (ret != 0)
ERROR_OUT(-10421, done);
ret = wc_ecc_init_ex(tmpKey, HEAP_HINT, devId);
if (ret != 0)
ERROR_OUT(-10421, done);
@ -24157,6 +24419,10 @@ WOLFSSL_TEST_SUBROUTINE int ecc_test_buffers(void)
if (ret != 0) {
ERROR_OUT(-10425, done);
}
ret = wc_ecc_set_rng(servKey, &rng);
if (ret != 0) {
ERROR_OUT(-10425, done);
}
#endif
#endif /* !WC_NO_RNG */
@ -24169,8 +24435,16 @@ WOLFSSL_TEST_SUBROUTINE int ecc_test_buffers(void)
if (ret < 0)
ERROR_OUT(-10426, done);
#ifdef WOLFSSL_ECIES_OLD
tmpKey->dp = cliKey->dp;
ret = wc_ecc_copy_point(&cliKey->pubkey, &tmpKey->pubkey);
if (ret != 0) {
ret = -10414; goto done;
}
#endif
y = sizeof(plain);
ret = wc_ecc_decrypt(cliKey, servKey, out, x, plain, &y, NULL);
ret = wc_ecc_decrypt(servKey, tmpKey, out, x, plain, &y, NULL);
if (ret < 0)
ERROR_OUT(-10427, done);
@ -24232,9 +24506,14 @@ WOLFSSL_TEST_SUBROUTINE int ecc_test_buffers(void)
wc_ecc_free(servKey);
XFREE(servKey, HEAP_HINT, DYNAMIC_TYPE_TMP_BUFFER);
}
if (tmpKey != NULL) {
wc_ecc_free(tmpKey);
XFREE(tmpKey, HEAP_HINT, DYNAMIC_TYPE_TMP_BUFFER);
}
#else
wc_ecc_free(cliKey);
wc_ecc_free(servKey);
wc_ecc_free(tmpKey);
#endif
wc_FreeRng(&rng);

View File

@ -722,8 +722,8 @@ WOLFSSL_API
int wc_ecc_import_raw_ex(ecc_key* key, const char* qx, const char* qy,
const char* d, int curve_id);
WOLFSSL_API
int wc_ecc_import_unsigned(ecc_key* key, byte* qx, byte* qy,
byte* d, int curve_id);
int wc_ecc_import_unsigned(ecc_key* key, const byte* qx, const byte* qy,
const byte* d, int curve_id);
#endif /* HAVE_ECC_KEY_IMPORT */
#ifdef HAVE_ECC_KEY_EXPORT
@ -803,6 +803,7 @@ enum {
KEY_SIZE_256 = 32,
IV_SIZE_64 = 8,
IV_SIZE_128 = 16,
ECC_MAX_IV_SIZE = 16,
EXCHANGE_SALT_SZ = 16,
EXCHANGE_INFO_SZ = 23
};