From ce655f61c56b70f4cf3aa3f0f0d7b2e5d311d018 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mois=C3=A9s=20Guimar=C3=A3es?= Date: Wed, 23 Apr 2014 11:44:54 -0300 Subject: [PATCH] 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) --- ctaocrypt/src/ecc.c | 310 +++++++++++++++++++++++++++++++------------- 1 file changed, 223 insertions(+), 87 deletions(-) diff --git a/ctaocrypt/src/ecc.c b/ctaocrypt/src/ecc.c index 32c827d0f..8059b2216 100644 --- a/ctaocrypt/src/ecc.c +++ b/ctaocrypt/src/ecc.c @@ -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; }