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;
mp_int prime;
mp_int order;
#ifdef CYASSL_SMALL_STACK
byte* buf;
#else
byte buf[ECC_MAXSIZE];
#endif
int keysize;
if (key == NULL || rng == NULL || dp == NULL)
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->dp = dp;
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 */
err = RNG_GenerateBlock(rng, buf, keysize);
if (err != 0)
return err;
buf[0] |= 0x0c;
if (err == 0)
buf[0] |= 0x0c;
/* setup the key variables */
if ((err = mp_init_multi(&key->pubkey.x, &key->pubkey.y, &key->pubkey.z,
&key->k, &prime, &order)) != MP_OKAY)
return MEMORY_E;
if (err == 0) {
err = mp_init_multi(&key->pubkey.x, &key->pubkey.y, &key->pubkey.z,
&key->k, &prime, &order);
if (err != MP_OKAY)
err = MEMORY_E;
}
base = ecc_new_point();
if (base == NULL)
err = MEMORY_E;
if (err == MP_OKAY) {
base = ecc_new_point();
if (base == NULL)
err = MEMORY_E;
}
/* read in the specs for this key */
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);
mp_clear(&prime);
mp_clear(&order);
#ifdef ECC_CLEAN_STACK
XMEMSET(buff, 0, ECC_MAXSIZE);
XMEMSET(buf, 0, ECC_MAXSIZE);
#endif
#ifdef CYASSL_SMALL_STACK
XFREE(buf, NULL, DYNAMIC_TYPE_TMP_BUFFER);
#endif
return err;
}
@ -1750,8 +1769,8 @@ static int ecc_mul2add(ecc_point* A, mp_int* kA,
}
}
#ifdef ECC_CLEAN_STACK
XMEMSET(tA, 0, ECC_BUF_SIZE);
XMEMSET(tB, 0, ECC_BUF_SIZE);
XMEMSET(tA, 0, ECC_BUFSIZE);
XMEMSET(tB, 0, ECC_BUFSIZE);
#endif
XFREE(tA, 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 */
int ecc_export_x963(ecc_key* key, byte* out, word32* outLen)
{
#ifdef CYASSL_SMALL_STACK
byte* buf;
#else
byte buf[ECC_BUFSIZE];
#endif
word32 numlen;
int ret = MP_OKAY;
@ -1975,25 +1998,37 @@ int ecc_export_x963(ecc_key* key, byte* out, word32* outLen)
/* store byte 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 */
XMEMSET(buf, 0, sizeof(buf));
XMEMSET(buf, 0, ECC_BUFSIZE);
ret = mp_to_unsigned_bin(&key->pubkey.x,
buf + (numlen - mp_unsigned_bin_size(&key->pubkey.x)));
if (ret != MP_OKAY)
return ret;
break;
XMEMCPY(out+1, buf, numlen);
/* pad and store y */
XMEMSET(buf, 0, sizeof(buf));
XMEMSET(buf, 0, ECC_BUFSIZE);
ret = mp_to_unsigned_bin(&key->pubkey.y,
buf + (numlen - mp_unsigned_bin_size(&key->pubkey.y)));
if (ret != MP_OKAY)
return ret;
break;
XMEMCPY(out+1+numlen, buf, 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,
mp_digit* mp, int map)
{
#define KB_SIZE 128
#ifdef CYASSL_SMALL_STACK
unsigned char* kb;
#else
unsigned char kb[128];
#endif
int x;
unsigned y, z, err, bitlen, bitpos, lut_gap, first;
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;
/* 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);
return BUFFER_E;
}
/* 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) {
mp_clear(&tk);
return err;
}
else {
/* let's reverse kb so it's little endian */
x = 0;
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 */
if (!first) {
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 ((err = ecc_projective_add_point(R, fp_cache[idx].LUT[z], R,
modulus, mp)) != MP_OKAY) {
return err;
break;
}
} else if (z) {
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].mu, &R->z) != MP_OKAY)) {
return GEN_MEM_ERR;
err = GEN_MEM_ERR;
break;
}
first = 0;
}
}
}
}
if (err == MP_OKAY) {
z = 0;
XMEMSET(kb, 0, sizeof(kb));
XMEMSET(kb, 0, KB_SIZE);
/* map R back from projective space */
if (map) {
err = ecc_map(R, modulus, mp);
} else {
err = MP_OKAY;
}
}
#ifdef CYASSL_SMALL_STACK
XFREE(kb, NULL, DYNAMIC_TYPE_TMP_BUFFER);
#endif
#undef KB_SIZE
return err;
}
@ -3057,7 +3114,13 @@ static int accel_fp_mul2add(int idx1, int idx2,
mp_int* kA, mp_int* kB,
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];
#endif
int x;
unsigned y, z, err, bitlen, bitpos, lut_gap, first, zA, zB;
mp_int tka;
@ -3154,18 +3217,25 @@ static int accel_fp_mul2add(int idx1, int idx2,
lut_gap = bitlen / FP_LUT;
/* get the k value */
if ((mp_unsigned_bin_size(&tka) > (int)(sizeof(kb[0]) - 2)) ||
(mp_unsigned_bin_size(&tkb) > (int)(sizeof(kb[0]) - 2)) ) {
if ((mp_unsigned_bin_size(&tka) > (int)(KB_SIZE - 2)) ||
(mp_unsigned_bin_size(&tkb) > (int)(KB_SIZE - 2)) ) {
mp_clear(&tka);
mp_clear(&tkb);
return BUFFER_E;
}
/* 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) {
mp_clear(&tka);
mp_clear(&tkb);
XFREE(kb[0], NULL, DYNAMIC_TYPE_TMP_BUFFER);
return err;
}
@ -3179,11 +3249,19 @@ static int accel_fp_mul2add(int idx1, int idx2,
}
/* 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) {
mp_clear(&tkb);
return err;
}
else {
x = 0;
y = mp_unsigned_bin_size(&tkb) - 1;
mp_clear(&tkb);
@ -3208,7 +3286,7 @@ static int accel_fp_mul2add(int idx1, int idx2,
/* double if not first */
if (!first) {
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 ((err = ecc_projective_add_point(R, fp_cache[idx1].LUT[zA],
R, modulus, mp)) != MP_OKAY) {
return err;
break;
}
}
if (zB) {
if ((err = ecc_projective_add_point(R, fp_cache[idx2].LUT[zB],
R, modulus, mp)) != MP_OKAY) {
return err;
break;
}
}
} 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) ||
(mp_copy(&fp_cache[idx1].LUT[zA]->y, &R->y) != MP_OKAY) ||
(mp_copy(&fp_cache[idx1].mu, &R->z) != MP_OKAY)) {
return GEN_MEM_ERR;
err = GEN_MEM_ERR;
break;
}
first = 0;
}
@ -3239,20 +3318,31 @@ static int accel_fp_mul2add(int idx1, int idx2,
if (zB) {
if ((err = ecc_projective_add_point(R, fp_cache[idx2].LUT[zB],
R, modulus, mp)) != MP_OKAY){
return err;
break;
}
}
} else if (zB && first == 1) {
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].mu, &R->z) != MP_OKAY)) {
return GEN_MEM_ERR;
err = GEN_MEM_ERR;
break;
}
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);
}
@ -3741,9 +3831,14 @@ int ecc_encrypt(ecc_key* privKey, ecc_key* pubKey, const byte* msg,
word32 blockSz;
word32 digestSz;
ecEncCtx localCtx;
#ifdef CYASSL_SMALL_STACK
byte* sharedSecret;
byte* keys;
#else
byte sharedSecret[ECC_MAXSIZE]; /* 521 max size */
byte keys[ECC_BUFSIZE]; /* max size */
word32 sharedSz = sizeof(sharedSecret);
#endif
word32 sharedSz = ECC_MAXSIZE;
int keysLen;
int encKeySz;
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 */
}
if (keysLen > (int)sizeof(keys))
if (keysLen > ECC_BUFSIZE) /* keys size */
return BUFFER_E;
if ( (msgSz%blockSz) != 0)
@ -3791,23 +3886,34 @@ int ecc_encrypt(ecc_key* privKey, ecc_key* pubKey, const byte* msg,
if (*outSz < (msgSz + digestSz))
return BUFFER_E;
ret = ecc_shared_secret(privKey, pubKey, sharedSecret, &sharedSz);
if (ret != 0)
return ret;
#ifdef CYASSL_SMALL_STACK
sharedSecret = (byte*)XMALLOC(ECC_MAXSIZE, NULL, DYNAMIC_TYPE_TMP_BUFFER);
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) {
case ecHKDF_SHA256 :
ret = HKDF(SHA256, sharedSecret, sharedSz, ctx->kdfSalt,
ctx->kdfSaltSz, ctx->kdfInfo,
ctx->kdfInfoSz, keys, keysLen);
if (ret != 0)
return ret;
ret = HKDF(SHA256, sharedSecret, sharedSz, ctx->kdfSalt,
ctx->kdfSaltSz, ctx->kdfInfo, ctx->kdfInfoSz, keys, keysLen);
break;
default:
return BAD_FUNC_ARG;
ret = BAD_FUNC_ARG;
break;
}
}
if (ret == 0) {
encKey = keys + offset;
encIv = encKey + encKeySz;
macKey = encKey + encKeySz + ivSz;
@ -3818,43 +3924,50 @@ int ecc_encrypt(ecc_key* privKey, ecc_key* pubKey, const byte* msg,
Aes aes;
ret = AesSetKey(&aes, encKey,KEY_SIZE_128,encIv,AES_ENCRYPTION);
if (ret != 0)
return ret;
break;
ret = AesCbcEncrypt(&aes, out, msg, msgSz);
if (ret != 0)
return ret;
}
break;
default:
return BAD_FUNC_ARG;
ret = BAD_FUNC_ARG;
break;
}
}
if (ret == 0) {
switch (ctx->macAlgo) {
case ecHMAC_SHA256:
{
Hmac hmac;
ret = HmacSetKey(&hmac, SHA256, macKey, SHA256_DIGEST_SIZE);
if (ret != 0)
return ret;
break;
ret = HmacUpdate(&hmac, out, msgSz);
if (ret != 0)
return ret;
break;
ret = HmacUpdate(&hmac, ctx->macSalt, ctx->macSaltSz);
if (ret != 0)
return ret;
break;
ret = HmacFinal(&hmac, out+msgSz);
if (ret != 0)
return ret;
}
break;
default:
return BAD_FUNC_ARG;
ret = BAD_FUNC_ARG;
break;
}
}
if (ret == 0)
*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 digestSz;
ecEncCtx localCtx;
#ifdef CYASSL_SMALL_STACK
byte* sharedSecret;
byte* keys;
#else
byte sharedSecret[ECC_MAXSIZE]; /* 521 max size */
byte keys[ECC_BUFSIZE]; /* max size */
word32 sharedSz = sizeof(sharedSecret);
#endif
word32 sharedSz = ECC_MAXSIZE;
int keysLen;
int encKeySz;
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 */
}
if (keysLen > (int)sizeof(keys))
if (keysLen > ECC_BUFSIZE) /* keys size */
return BUFFER_E;
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))
return BUFFER_E;
ret = ecc_shared_secret(privKey, pubKey, sharedSecret, &sharedSz);
if (ret != 0)
return ret;
#ifdef CYASSL_SMALL_STACK
sharedSecret = (byte*)XMALLOC(ECC_MAXSIZE, NULL, DYNAMIC_TYPE_TMP_BUFFER);
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) {
case ecHKDF_SHA256 :
ret = HKDF(SHA256, sharedSecret, sharedSz, ctx->kdfSalt,
ctx->kdfSaltSz, ctx->kdfInfo,
ctx->kdfInfoSz, keys, keysLen);
if (ret != 0)
return ret;
ret = HKDF(SHA256, sharedSecret, sharedSz, ctx->kdfSalt,
ctx->kdfSaltSz, ctx->kdfInfo, ctx->kdfInfoSz, keys, keysLen);
break;
default:
return BAD_FUNC_ARG;
ret = BAD_FUNC_ARG;
break;
}
}
if (ret == 0) {
encKey = keys + offset;
encIv = encKey + encKeySz;
macKey = encKey + encKeySz + ivSz;
@ -3946,47 +4075,54 @@ int ecc_decrypt(ecc_key* privKey, ecc_key* pubKey, const byte* msg,
Hmac hmac;
ret = HmacSetKey(&hmac, SHA256, macKey, SHA256_DIGEST_SIZE);
if (ret != 0)
return ret;
break;
ret = HmacUpdate(&hmac, msg, msgSz-digestSz);
if (ret != 0)
return ret;
break;
ret = HmacUpdate(&hmac, ctx->macSalt, ctx->macSaltSz);
if (ret != 0)
return ret;
break;
ret = HmacFinal(&hmac, verify);
if (ret != 0)
return ret;
if (memcmp(verify, msg + msgSz - digestSz, digestSz) != 0) {
return -1;
}
break;
if (memcmp(verify, msg + msgSz - digestSz, digestSz) != 0)
ret = -1;
}
break;
default:
return BAD_FUNC_ARG;
ret = BAD_FUNC_ARG;
break;
}
}
if (ret == 0) {
switch (ctx->encAlgo) {
case ecAES_128_CBC:
{
Aes aes;
ret = AesSetKey(&aes, encKey,KEY_SIZE_128,encIv,AES_DECRYPTION);
if (ret != 0)
return ret;
break;
ret = AesCbcDecrypt(&aes, out, msg, msgSz-digestSz);
if (ret != 0)
return ret;
}
break;
default:
return BAD_FUNC_ARG;
ret = BAD_FUNC_ARG;
break;
}
}
if (ret == 0)
*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;
}