ecc: ecc_make_key_ex, ecc_export_x963, accel_fp_mul, accel_fp_mul2add, ecc_encrypt and ecc_decrypt refactory to reduce stack usage: (1350 bytes - pointer sizes) moved to the heap.

--- ecc_make_key_ex: buf variable moved to the heap; (66 bytes)
--- ecc_export_x963: buf variable moved to the heap; (256 bytes)
--- accel_fp_mul: kb variable moved to the heap; (128 bytes)
--- accel_fp_mul2add: kb variable moved to the heap; (256 bytes)
--- ecc_encrypt: sharedSecret and keys variables moved to the heap; (66 + 256 bytes)
--- ecc_decrypt: sharedSecret and keys variables moved to the heap; (66 + 256 bytes)
This commit is contained in:
Moisés Guimarães
2014-04-23 11:44:54 -03:00
parent fc24dca12d
commit ce655f61c5

View File

@@ -1319,12 +1319,22 @@ int ecc_make_key_ex(RNG* rng, ecc_key* key, const ecc_set_type* dp)
ecc_point* base; ecc_point* base;
mp_int prime; mp_int prime;
mp_int order; mp_int order;
#ifdef CYASSL_SMALL_STACK
byte* buf;
#else
byte buf[ECC_MAXSIZE]; byte buf[ECC_MAXSIZE];
#endif
int keysize; int keysize;
if (key == NULL || rng == NULL || dp == NULL) if (key == NULL || rng == NULL || dp == NULL)
return ECC_BAD_ARG_E; return ECC_BAD_ARG_E;
#ifdef CYASSL_SMALL_STACK
buf = (byte*)XMALLOC(ECC_MAXSIZE, NULL, DYNAMIC_TYPE_TMP_BUFFER);
if (buf == NULL)
return MEMORY_E;
#endif
key->idx = -1; key->idx = -1;
key->dp = dp; key->dp = dp;
keysize = dp->size; keysize = dp->size;
@@ -1334,19 +1344,22 @@ int ecc_make_key_ex(RNG* rng, ecc_key* key, const ecc_set_type* dp)
/* make up random string */ /* make up random string */
err = RNG_GenerateBlock(rng, buf, keysize); err = RNG_GenerateBlock(rng, buf, keysize);
if (err != 0) if (err == 0)
return err;
buf[0] |= 0x0c; buf[0] |= 0x0c;
/* setup the key variables */ /* setup the key variables */
if ((err = mp_init_multi(&key->pubkey.x, &key->pubkey.y, &key->pubkey.z, if (err == 0) {
&key->k, &prime, &order)) != MP_OKAY) err = mp_init_multi(&key->pubkey.x, &key->pubkey.y, &key->pubkey.z,
return MEMORY_E; &key->k, &prime, &order);
if (err != MP_OKAY)
err = MEMORY_E;
}
if (err == MP_OKAY) {
base = ecc_new_point(); base = ecc_new_point();
if (base == NULL) if (base == NULL)
err = MEMORY_E; err = MEMORY_E;
}
/* read in the specs for this key */ /* read in the specs for this key */
if (err == MP_OKAY) if (err == MP_OKAY)
@@ -1384,9 +1397,15 @@ int ecc_make_key_ex(RNG* rng, ecc_key* key, const ecc_set_type* dp)
ecc_del_point(base); ecc_del_point(base);
mp_clear(&prime); mp_clear(&prime);
mp_clear(&order); mp_clear(&order);
#ifdef ECC_CLEAN_STACK #ifdef ECC_CLEAN_STACK
XMEMSET(buff, 0, ECC_MAXSIZE); XMEMSET(buf, 0, ECC_MAXSIZE);
#endif #endif
#ifdef CYASSL_SMALL_STACK
XFREE(buf, NULL, DYNAMIC_TYPE_TMP_BUFFER);
#endif
return err; return err;
} }
@@ -1750,8 +1769,8 @@ static int ecc_mul2add(ecc_point* A, mp_int* kA,
} }
} }
#ifdef ECC_CLEAN_STACK #ifdef ECC_CLEAN_STACK
XMEMSET(tA, 0, ECC_BUF_SIZE); XMEMSET(tA, 0, ECC_BUFSIZE);
XMEMSET(tB, 0, ECC_BUF_SIZE); XMEMSET(tB, 0, ECC_BUFSIZE);
#endif #endif
XFREE(tA, NULL, DYNAMIC_TYPE_TMP_BUFFER); XFREE(tA, NULL, DYNAMIC_TYPE_TMP_BUFFER);
XFREE(tB, NULL, DYNAMIC_TYPE_TMP_BUFFER); XFREE(tB, NULL, DYNAMIC_TYPE_TMP_BUFFER);
@@ -1955,7 +1974,11 @@ int ecc_verify_hash(const byte* sig, word32 siglen, const byte* hash,
/* export public ECC key in ANSI X9.63 format */ /* export public ECC key in ANSI X9.63 format */
int ecc_export_x963(ecc_key* key, byte* out, word32* outLen) int ecc_export_x963(ecc_key* key, byte* out, word32* outLen)
{ {
#ifdef CYASSL_SMALL_STACK
byte* buf;
#else
byte buf[ECC_BUFSIZE]; byte buf[ECC_BUFSIZE];
#endif
word32 numlen; word32 numlen;
int ret = MP_OKAY; int ret = MP_OKAY;
@@ -1975,25 +1998,37 @@ int ecc_export_x963(ecc_key* key, byte* out, word32* outLen)
/* store byte 0x04 */ /* store byte 0x04 */
out[0] = 0x04; out[0] = 0x04;
#ifdef CYASSL_SMALL_STACK
buf = (byte*)XMALLOC(ECC_BUFSIZE, NULL, DYNAMIC_TYPE_TMP_BUFFER);
if (buf == NULL)
return MEMORY_E;
#endif
do {
/* pad and store x */ /* pad and store x */
XMEMSET(buf, 0, sizeof(buf)); XMEMSET(buf, 0, ECC_BUFSIZE);
ret = mp_to_unsigned_bin(&key->pubkey.x, ret = mp_to_unsigned_bin(&key->pubkey.x,
buf + (numlen - mp_unsigned_bin_size(&key->pubkey.x))); buf + (numlen - mp_unsigned_bin_size(&key->pubkey.x)));
if (ret != MP_OKAY) if (ret != MP_OKAY)
return ret; break;
XMEMCPY(out+1, buf, numlen); XMEMCPY(out+1, buf, numlen);
/* pad and store y */ /* pad and store y */
XMEMSET(buf, 0, sizeof(buf)); XMEMSET(buf, 0, ECC_BUFSIZE);
ret = mp_to_unsigned_bin(&key->pubkey.y, ret = mp_to_unsigned_bin(&key->pubkey.y,
buf + (numlen - mp_unsigned_bin_size(&key->pubkey.y))); buf + (numlen - mp_unsigned_bin_size(&key->pubkey.y)));
if (ret != MP_OKAY) if (ret != MP_OKAY)
return ret; break;
XMEMCPY(out+1+numlen, buf, numlen); XMEMCPY(out+1+numlen, buf, numlen);
*outLen = 1 + 2*numlen; *outLen = 1 + 2*numlen;
} while (0);
return 0; #ifdef CYASSL_SMALL_STACK
XFREE(buf, NULL, DYNAMIC_TYPE_TMP_BUFFER);
#endif
return ret;
} }
@@ -2928,7 +2963,13 @@ static int build_lut(int idx, mp_int* modulus, mp_digit* mp, mp_int* mu)
static int accel_fp_mul(int idx, mp_int* k, ecc_point *R, mp_int* modulus, static int accel_fp_mul(int idx, mp_int* k, ecc_point *R, mp_int* modulus,
mp_digit* mp, int map) mp_digit* mp, int map)
{ {
#define KB_SIZE 128
#ifdef CYASSL_SMALL_STACK
unsigned char* kb;
#else
unsigned char kb[128]; unsigned char kb[128];
#endif
int x; int x;
unsigned y, z, err, bitlen, bitpos, lut_gap, first; unsigned y, z, err, bitlen, bitpos, lut_gap, first;
mp_int tk; mp_int tk;
@@ -2983,18 +3024,23 @@ static int accel_fp_mul(int idx, mp_int* k, ecc_point *R, mp_int* modulus,
lut_gap = bitlen / FP_LUT; lut_gap = bitlen / FP_LUT;
/* get the k value */ /* get the k value */
if (mp_unsigned_bin_size(&tk) > (int)(sizeof(kb) - 2)) { if (mp_unsigned_bin_size(&tk) > (int)(KB_SIZE - 2)) {
mp_clear(&tk); mp_clear(&tk);
return BUFFER_E; return BUFFER_E;
} }
/* store k */ /* store k */
XMEMSET(kb, 0, sizeof(kb)); #ifdef CYASSL_SMALL_STACK
kb = (unsigned char*)XMALLOC(KB_SIZE, NULL, DYNAMIC_TYPE_TMP_BUFFER);
if (kb == NULL)
return MEMORY_E;
#endif
XMEMSET(kb, 0, KB_SIZE);
if ((err = mp_to_unsigned_bin(&tk, kb)) != MP_OKAY) { if ((err = mp_to_unsigned_bin(&tk, kb)) != MP_OKAY) {
mp_clear(&tk); mp_clear(&tk);
return err;
} }
else {
/* let's reverse kb so it's little endian */ /* let's reverse kb so it's little endian */
x = 0; x = 0;
y = mp_unsigned_bin_size(&tk) - 1; y = mp_unsigned_bin_size(&tk) - 1;
@@ -3020,7 +3066,7 @@ static int accel_fp_mul(int idx, mp_int* k, ecc_point *R, mp_int* modulus,
/* double if not first */ /* double if not first */
if (!first) { if (!first) {
if ((err = ecc_projective_dbl_point(R, R, modulus, mp)) != MP_OKAY) { if ((err = ecc_projective_dbl_point(R, R, modulus, mp)) != MP_OKAY) {
return err; break;
} }
} }
@@ -3028,25 +3074,36 @@ static int accel_fp_mul(int idx, mp_int* k, ecc_point *R, mp_int* modulus,
if (!first && z) { if (!first && z) {
if ((err = ecc_projective_add_point(R, fp_cache[idx].LUT[z], R, if ((err = ecc_projective_add_point(R, fp_cache[idx].LUT[z], R,
modulus, mp)) != MP_OKAY) { modulus, mp)) != MP_OKAY) {
return err; break;
} }
} else if (z) { } else if (z) {
if ((mp_copy(&fp_cache[idx].LUT[z]->x, &R->x) != MP_OKAY) || if ((mp_copy(&fp_cache[idx].LUT[z]->x, &R->x) != MP_OKAY) ||
(mp_copy(&fp_cache[idx].LUT[z]->y, &R->y) != MP_OKAY) || (mp_copy(&fp_cache[idx].LUT[z]->y, &R->y) != MP_OKAY) ||
(mp_copy(&fp_cache[idx].mu, &R->z) != MP_OKAY)) { (mp_copy(&fp_cache[idx].mu, &R->z) != MP_OKAY)) {
return GEN_MEM_ERR; err = GEN_MEM_ERR;
break;
} }
first = 0; first = 0;
} }
} }
}
if (err == MP_OKAY) {
z = 0; z = 0;
XMEMSET(kb, 0, sizeof(kb)); XMEMSET(kb, 0, KB_SIZE);
/* map R back from projective space */ /* map R back from projective space */
if (map) { if (map) {
err = ecc_map(R, modulus, mp); err = ecc_map(R, modulus, mp);
} else { } else {
err = MP_OKAY; err = MP_OKAY;
} }
}
#ifdef CYASSL_SMALL_STACK
XFREE(kb, NULL, DYNAMIC_TYPE_TMP_BUFFER);
#endif
#undef KB_SIZE
return err; return err;
} }
@@ -3057,7 +3114,13 @@ static int accel_fp_mul2add(int idx1, int idx2,
mp_int* kA, mp_int* kB, mp_int* kA, mp_int* kB,
ecc_point *R, mp_int* modulus, mp_digit* mp) ecc_point *R, mp_int* modulus, mp_digit* mp)
{ {
#define KB_SIZE 128
#ifdef CYASSL_SMALL_STACK
unsigned char* kb[2];
#else
unsigned char kb[2][128]; unsigned char kb[2][128];
#endif
int x; int x;
unsigned y, z, err, bitlen, bitpos, lut_gap, first, zA, zB; unsigned y, z, err, bitlen, bitpos, lut_gap, first, zA, zB;
mp_int tka; mp_int tka;
@@ -3154,18 +3217,25 @@ static int accel_fp_mul2add(int idx1, int idx2,
lut_gap = bitlen / FP_LUT; lut_gap = bitlen / FP_LUT;
/* get the k value */ /* get the k value */
if ((mp_unsigned_bin_size(&tka) > (int)(sizeof(kb[0]) - 2)) || if ((mp_unsigned_bin_size(&tka) > (int)(KB_SIZE - 2)) ||
(mp_unsigned_bin_size(&tkb) > (int)(sizeof(kb[0]) - 2)) ) { (mp_unsigned_bin_size(&tkb) > (int)(KB_SIZE - 2)) ) {
mp_clear(&tka); mp_clear(&tka);
mp_clear(&tkb); mp_clear(&tkb);
return BUFFER_E; return BUFFER_E;
} }
/* store k */ /* store k */
XMEMSET(kb, 0, sizeof(kb)); #ifdef CYASSL_SMALL_STACK
kb[0] = (unsigned char*)XMALLOC(KB_SIZE, NULL, DYNAMIC_TYPE_TMP_BUFFER);
if (kb[0] == NULL)
return MEMORY_E;
#endif
XMEMSET(kb[0], 0, KB_SIZE);
if ((err = mp_to_unsigned_bin(&tka, kb[0])) != MP_OKAY) { if ((err = mp_to_unsigned_bin(&tka, kb[0])) != MP_OKAY) {
mp_clear(&tka); mp_clear(&tka);
mp_clear(&tkb); mp_clear(&tkb);
XFREE(kb[0], NULL, DYNAMIC_TYPE_TMP_BUFFER);
return err; return err;
} }
@@ -3179,11 +3249,19 @@ static int accel_fp_mul2add(int idx1, int idx2,
} }
/* store b */ /* store b */
#ifdef CYASSL_SMALL_STACK
kb[1] = (unsigned char*)XMALLOC(KB_SIZE, NULL, DYNAMIC_TYPE_TMP_BUFFER);
if (kb[1] == NULL) {
XFREE(kb[0], NULL, DYNAMIC_TYPE_TMP_BUFFER);
return MEMORY_E;
}
#endif
XMEMSET(kb[1], 0, KB_SIZE);
if ((err = mp_to_unsigned_bin(&tkb, kb[1])) != MP_OKAY) { if ((err = mp_to_unsigned_bin(&tkb, kb[1])) != MP_OKAY) {
mp_clear(&tkb); mp_clear(&tkb);
return err;
} }
else {
x = 0; x = 0;
y = mp_unsigned_bin_size(&tkb) - 1; y = mp_unsigned_bin_size(&tkb) - 1;
mp_clear(&tkb); mp_clear(&tkb);
@@ -3208,7 +3286,7 @@ static int accel_fp_mul2add(int idx1, int idx2,
/* double if not first */ /* double if not first */
if (!first) { if (!first) {
if ((err = ecc_projective_dbl_point(R, R, modulus, mp)) != MP_OKAY) { if ((err = ecc_projective_dbl_point(R, R, modulus, mp)) != MP_OKAY) {
return err; break;
} }
} }
@@ -3217,13 +3295,13 @@ static int accel_fp_mul2add(int idx1, int idx2,
if (zA) { if (zA) {
if ((err = ecc_projective_add_point(R, fp_cache[idx1].LUT[zA], if ((err = ecc_projective_add_point(R, fp_cache[idx1].LUT[zA],
R, modulus, mp)) != MP_OKAY) { R, modulus, mp)) != MP_OKAY) {
return err; break;
} }
} }
if (zB) { if (zB) {
if ((err = ecc_projective_add_point(R, fp_cache[idx2].LUT[zB], if ((err = ecc_projective_add_point(R, fp_cache[idx2].LUT[zB],
R, modulus, mp)) != MP_OKAY) { R, modulus, mp)) != MP_OKAY) {
return err; break;
} }
} }
} else { } else {
@@ -3231,7 +3309,8 @@ static int accel_fp_mul2add(int idx1, int idx2,
if ((mp_copy(&fp_cache[idx1].LUT[zA]->x, &R->x) != MP_OKAY) || if ((mp_copy(&fp_cache[idx1].LUT[zA]->x, &R->x) != MP_OKAY) ||
(mp_copy(&fp_cache[idx1].LUT[zA]->y, &R->y) != MP_OKAY) || (mp_copy(&fp_cache[idx1].LUT[zA]->y, &R->y) != MP_OKAY) ||
(mp_copy(&fp_cache[idx1].mu, &R->z) != MP_OKAY)) { (mp_copy(&fp_cache[idx1].mu, &R->z) != MP_OKAY)) {
return GEN_MEM_ERR; err = GEN_MEM_ERR;
break;
} }
first = 0; first = 0;
} }
@@ -3239,20 +3318,31 @@ static int accel_fp_mul2add(int idx1, int idx2,
if (zB) { if (zB) {
if ((err = ecc_projective_add_point(R, fp_cache[idx2].LUT[zB], if ((err = ecc_projective_add_point(R, fp_cache[idx2].LUT[zB],
R, modulus, mp)) != MP_OKAY){ R, modulus, mp)) != MP_OKAY){
return err; break;
} }
} }
} else if (zB && first == 1) { } else if (zB && first == 1) {
if ((mp_copy(&fp_cache[idx2].LUT[zB]->x, &R->x) != MP_OKAY) || if ((mp_copy(&fp_cache[idx2].LUT[zB]->x, &R->x) != MP_OKAY) ||
(mp_copy(&fp_cache[idx2].LUT[zB]->y, &R->y) != MP_OKAY) || (mp_copy(&fp_cache[idx2].LUT[zB]->y, &R->y) != MP_OKAY) ||
(mp_copy(&fp_cache[idx2].mu, &R->z) != MP_OKAY)) { (mp_copy(&fp_cache[idx2].mu, &R->z) != MP_OKAY)) {
return GEN_MEM_ERR; err = GEN_MEM_ERR;
break;
} }
first = 0; first = 0;
} }
} }
} }
XMEMSET(kb, 0, sizeof(kb)); }
XMEMSET(kb[0], 0, KB_SIZE);
XMEMSET(kb[1], 0, KB_SIZE);
#ifdef CYASSL_SMALL_STACK
XFREE(kb[0], NULL, DYNAMIC_TYPE_TMP_BUFFER);
XFREE(kb[1], NULL, DYNAMIC_TYPE_TMP_BUFFER);
#endif
#undef KB_SIZE
return ecc_map(R, modulus, mp); return ecc_map(R, modulus, mp);
} }
@@ -3741,9 +3831,14 @@ int ecc_encrypt(ecc_key* privKey, ecc_key* pubKey, const byte* msg,
word32 blockSz; word32 blockSz;
word32 digestSz; word32 digestSz;
ecEncCtx localCtx; ecEncCtx localCtx;
#ifdef CYASSL_SMALL_STACK
byte* sharedSecret;
byte* keys;
#else
byte sharedSecret[ECC_MAXSIZE]; /* 521 max size */ byte sharedSecret[ECC_MAXSIZE]; /* 521 max size */
byte keys[ECC_BUFSIZE]; /* max size */ byte keys[ECC_BUFSIZE]; /* max size */
word32 sharedSz = sizeof(sharedSecret); #endif
word32 sharedSz = ECC_MAXSIZE;
int keysLen; int keysLen;
int encKeySz; int encKeySz;
int ivSz; int ivSz;
@@ -3782,7 +3877,7 @@ int ecc_encrypt(ecc_key* privKey, ecc_key* pubKey, const byte* msg,
ctx->cliSt = ecCLI_SENT_REQ; /* only do this once */ ctx->cliSt = ecCLI_SENT_REQ; /* only do this once */
} }
if (keysLen > (int)sizeof(keys)) if (keysLen > ECC_BUFSIZE) /* keys size */
return BUFFER_E; return BUFFER_E;
if ( (msgSz%blockSz) != 0) if ( (msgSz%blockSz) != 0)
@@ -3791,23 +3886,34 @@ int ecc_encrypt(ecc_key* privKey, ecc_key* pubKey, const byte* msg,
if (*outSz < (msgSz + digestSz)) if (*outSz < (msgSz + digestSz))
return BUFFER_E; return BUFFER_E;
ret = ecc_shared_secret(privKey, pubKey, sharedSecret, &sharedSz); #ifdef CYASSL_SMALL_STACK
if (ret != 0) sharedSecret = (byte*)XMALLOC(ECC_MAXSIZE, NULL, DYNAMIC_TYPE_TMP_BUFFER);
return ret; if (sharedSecret == NULL)
return MEMORY_E;
keys = (byte*)XMALLOC(ECC_BUFSIZE, NULL, DYNAMIC_TYPE_TMP_BUFFER);
if (keys == NULL) {
XFREE(sharedSecret, NULL, DYNAMIC_TYPE_TMP_BUFFER);
return MEMORY_E;
}
#endif
ret = ecc_shared_secret(privKey, pubKey, sharedSecret, &sharedSz);
if (ret == 0) {
switch (ctx->kdfAlgo) { switch (ctx->kdfAlgo) {
case ecHKDF_SHA256 : case ecHKDF_SHA256 :
ret = HKDF(SHA256, sharedSecret, sharedSz, ctx->kdfSalt, ret = HKDF(SHA256, sharedSecret, sharedSz, ctx->kdfSalt,
ctx->kdfSaltSz, ctx->kdfInfo, ctx->kdfSaltSz, ctx->kdfInfo, ctx->kdfInfoSz, keys, keysLen);
ctx->kdfInfoSz, keys, keysLen);
if (ret != 0)
return ret;
break; break;
default: default:
return BAD_FUNC_ARG; ret = BAD_FUNC_ARG;
break;
}
} }
if (ret == 0) {
encKey = keys + offset; encKey = keys + offset;
encIv = encKey + encKeySz; encIv = encKey + encKeySz;
macKey = encKey + encKeySz + ivSz; macKey = encKey + encKeySz + ivSz;
@@ -3818,43 +3924,50 @@ int ecc_encrypt(ecc_key* privKey, ecc_key* pubKey, const byte* msg,
Aes aes; Aes aes;
ret = AesSetKey(&aes, encKey,KEY_SIZE_128,encIv,AES_ENCRYPTION); ret = AesSetKey(&aes, encKey,KEY_SIZE_128,encIv,AES_ENCRYPTION);
if (ret != 0) if (ret != 0)
return ret; break;
ret = AesCbcEncrypt(&aes, out, msg, msgSz); ret = AesCbcEncrypt(&aes, out, msg, msgSz);
if (ret != 0)
return ret;
} }
break; break;
default: default:
return BAD_FUNC_ARG; ret = BAD_FUNC_ARG;
break;
}
} }
if (ret == 0) {
switch (ctx->macAlgo) { switch (ctx->macAlgo) {
case ecHMAC_SHA256: case ecHMAC_SHA256:
{ {
Hmac hmac; Hmac hmac;
ret = HmacSetKey(&hmac, SHA256, macKey, SHA256_DIGEST_SIZE); ret = HmacSetKey(&hmac, SHA256, macKey, SHA256_DIGEST_SIZE);
if (ret != 0) if (ret != 0)
return ret; break;
ret = HmacUpdate(&hmac, out, msgSz); ret = HmacUpdate(&hmac, out, msgSz);
if (ret != 0) if (ret != 0)
return ret; break;
ret = HmacUpdate(&hmac, ctx->macSalt, ctx->macSaltSz); ret = HmacUpdate(&hmac, ctx->macSalt, ctx->macSaltSz);
if (ret != 0) if (ret != 0)
return ret; break;
ret = HmacFinal(&hmac, out+msgSz); ret = HmacFinal(&hmac, out+msgSz);
if (ret != 0)
return ret;
} }
break; break;
default: default:
return BAD_FUNC_ARG; ret = BAD_FUNC_ARG;
break;
}
} }
if (ret == 0)
*outSz = msgSz + digestSz; *outSz = msgSz + digestSz;
return 0; #ifdef CYASSL_SMALL_STACK
XFREE(sharedSecret, NULL, DYNAMIC_TYPE_TMP_BUFFER);
XFREE(keys, NULL, DYNAMIC_TYPE_TMP_BUFFER);
#endif
return ret;
} }
@@ -3868,9 +3981,14 @@ int ecc_decrypt(ecc_key* privKey, ecc_key* pubKey, const byte* msg,
word32 blockSz; word32 blockSz;
word32 digestSz; word32 digestSz;
ecEncCtx localCtx; ecEncCtx localCtx;
#ifdef CYASSL_SMALL_STACK
byte* sharedSecret;
byte* keys;
#else
byte sharedSecret[ECC_MAXSIZE]; /* 521 max size */ byte sharedSecret[ECC_MAXSIZE]; /* 521 max size */
byte keys[ECC_BUFSIZE]; /* max size */ byte keys[ECC_BUFSIZE]; /* max size */
word32 sharedSz = sizeof(sharedSecret); #endif
word32 sharedSz = ECC_MAXSIZE;
int keysLen; int keysLen;
int encKeySz; int encKeySz;
int ivSz; int ivSz;
@@ -3909,7 +4027,7 @@ int ecc_decrypt(ecc_key* privKey, ecc_key* pubKey, const byte* msg,
ctx->srvSt = ecSRV_RECV_REQ; /* only do this once */ ctx->srvSt = ecSRV_RECV_REQ; /* only do this once */
} }
if (keysLen > (int)sizeof(keys)) if (keysLen > ECC_BUFSIZE) /* keys size */
return BUFFER_E; return BUFFER_E;
if ( ((msgSz-digestSz) % blockSz) != 0) if ( ((msgSz-digestSz) % blockSz) != 0)
@@ -3918,23 +4036,34 @@ int ecc_decrypt(ecc_key* privKey, ecc_key* pubKey, const byte* msg,
if (*outSz < (msgSz - digestSz)) if (*outSz < (msgSz - digestSz))
return BUFFER_E; return BUFFER_E;
ret = ecc_shared_secret(privKey, pubKey, sharedSecret, &sharedSz); #ifdef CYASSL_SMALL_STACK
if (ret != 0) sharedSecret = (byte*)XMALLOC(ECC_MAXSIZE, NULL, DYNAMIC_TYPE_TMP_BUFFER);
return ret; if (sharedSecret == NULL)
return MEMORY_E;
keys = (byte*)XMALLOC(ECC_BUFSIZE, NULL, DYNAMIC_TYPE_TMP_BUFFER);
if (keys == NULL) {
XFREE(sharedSecret, NULL, DYNAMIC_TYPE_TMP_BUFFER);
return MEMORY_E;
}
#endif
ret = ecc_shared_secret(privKey, pubKey, sharedSecret, &sharedSz);
if (ret == 0) {
switch (ctx->kdfAlgo) { switch (ctx->kdfAlgo) {
case ecHKDF_SHA256 : case ecHKDF_SHA256 :
ret = HKDF(SHA256, sharedSecret, sharedSz, ctx->kdfSalt, ret = HKDF(SHA256, sharedSecret, sharedSz, ctx->kdfSalt,
ctx->kdfSaltSz, ctx->kdfInfo, ctx->kdfSaltSz, ctx->kdfInfo, ctx->kdfInfoSz, keys, keysLen);
ctx->kdfInfoSz, keys, keysLen);
if (ret != 0)
return ret;
break; break;
default: default:
return BAD_FUNC_ARG; ret = BAD_FUNC_ARG;
break;
}
} }
if (ret == 0) {
encKey = keys + offset; encKey = keys + offset;
encIv = encKey + encKeySz; encIv = encKey + encKeySz;
macKey = encKey + encKeySz + ivSz; macKey = encKey + encKeySz + ivSz;
@@ -3946,47 +4075,54 @@ int ecc_decrypt(ecc_key* privKey, ecc_key* pubKey, const byte* msg,
Hmac hmac; Hmac hmac;
ret = HmacSetKey(&hmac, SHA256, macKey, SHA256_DIGEST_SIZE); ret = HmacSetKey(&hmac, SHA256, macKey, SHA256_DIGEST_SIZE);
if (ret != 0) if (ret != 0)
return ret; break;
ret = HmacUpdate(&hmac, msg, msgSz-digestSz); ret = HmacUpdate(&hmac, msg, msgSz-digestSz);
if (ret != 0) if (ret != 0)
return ret; break;
ret = HmacUpdate(&hmac, ctx->macSalt, ctx->macSaltSz); ret = HmacUpdate(&hmac, ctx->macSalt, ctx->macSaltSz);
if (ret != 0) if (ret != 0)
return ret; break;
ret = HmacFinal(&hmac, verify); ret = HmacFinal(&hmac, verify);
if (ret != 0) if (ret != 0)
return ret; break;
if (memcmp(verify, msg + msgSz - digestSz, digestSz) != 0)
if (memcmp(verify, msg + msgSz - digestSz, digestSz) != 0) { ret = -1;
return -1;
}
} }
break; break;
default: default:
return BAD_FUNC_ARG; ret = BAD_FUNC_ARG;
break;
}
} }
if (ret == 0) {
switch (ctx->encAlgo) { switch (ctx->encAlgo) {
case ecAES_128_CBC: case ecAES_128_CBC:
{ {
Aes aes; Aes aes;
ret = AesSetKey(&aes, encKey,KEY_SIZE_128,encIv,AES_DECRYPTION); ret = AesSetKey(&aes, encKey,KEY_SIZE_128,encIv,AES_DECRYPTION);
if (ret != 0) if (ret != 0)
return ret; break;
ret = AesCbcDecrypt(&aes, out, msg, msgSz-digestSz); ret = AesCbcDecrypt(&aes, out, msg, msgSz-digestSz);
if (ret != 0)
return ret;
} }
break; break;
default: default:
return BAD_FUNC_ARG; ret = BAD_FUNC_ARG;
break;
}
} }
if (ret == 0)
*outSz = msgSz - digestSz; *outSz = msgSz - digestSz;
return 0; #ifdef CYASSL_SMALL_STACK
XFREE(sharedSecret, NULL, DYNAMIC_TYPE_TMP_BUFFER);
XFREE(keys, NULL, DYNAMIC_TYPE_TMP_BUFFER);
#endif
return ret;
} }