From 98c76a7ef2e0973ff103d634d8d3f51afba6260b Mon Sep 17 00:00:00 2001 From: Karel Miko Date: Thu, 21 Jun 2018 21:33:23 +0200 Subject: [PATCH] fix LTC_MECC_FP --- src/headers/tomcrypt_private.h | 4 +- src/math/fp/ltc_ecc_fp_mulmod.c | 421 +++++++++++++--------- src/pk/ecc/ltc_ecc_is_point_at_infinity.c | 6 + 3 files changed, 250 insertions(+), 181 deletions(-) diff --git a/src/headers/tomcrypt_private.h b/src/headers/tomcrypt_private.h index 39c56454d..28bf7a28d 100644 --- a/src/headers/tomcrypt_private.h +++ b/src/headers/tomcrypt_private.h @@ -623,13 +623,13 @@ int ltc_ecc_projective_add_point(const ecc_point *P, const ecc_point *Q, ecc_poi #if defined(LTC_MECC_FP) /* optimized point multiplication using fixed point cache (HAC algorithm 14.117) */ -int ltc_ecc_fp_mulmod(void *k, ecc_point *G, ecc_point *R, void *a, void *modulus, int map); +int ltc_ecc_fp_mulmod(const void *k, const ecc_point *G, ecc_point *R, const void *ma, const void *modulus, int map); /* functions for saving/loading/freeing/adding to fixed point cache */ int ltc_ecc_fp_save_state(unsigned char **out, unsigned long *outlen); int ltc_ecc_fp_restore_state(unsigned char *in, unsigned long inlen); void ltc_ecc_fp_free(void); -int ltc_ecc_fp_add_point(ecc_point *g, void *modulus, int lock); +int ltc_ecc_fp_add_point(const ecc_point *g, const void *ma, const void *modulus, int lock); /* lock/unlock all points currently in fixed point cache */ void ltc_ecc_fp_tablelock(int lock); diff --git a/src/math/fp/ltc_ecc_fp_mulmod.c b/src/math/fp/ltc_ecc_fp_mulmod.c index fa9562524..1fff6303a 100644 --- a/src/math/fp/ltc_ecc_fp_mulmod.c +++ b/src/math/fp/ltc_ecc_fp_mulmod.c @@ -565,6 +565,30 @@ static const struct { #endif }; +static int s_find_order_for_modulus(const void *modulus, void **order) +{ + void *bn; + int err; + const ltc_ecc_curve *curve; + + if ((err = ltc_mp_init(&bn)) != CRYPT_OK) return err; + for (curve = ltc_ecc_curves; curve->prime != NULL; curve++) { + if (ltc_mp_read_radix(bn, curve->prime, 16) != CRYPT_OK) continue; + if (ltc_mp_cmp(bn, modulus) != LTC_MP_EQ) continue; + break; /* found */ + } + ltc_mp_clear(bn); + if (curve->order == NULL) return CRYPT_ERROR; + if ((err = ltc_mp_init(order)) != CRYPT_OK) { + return err; + } + if ((err = ltc_mp_read_radix(*order, curve->order, 16)) != CRYPT_OK) { + ltc_mp_clear(*order); + return err; + } + return CRYPT_OK; +} + /* find a hole and free as required, return -1 if no hole found */ static int s_find_hole(void) { @@ -602,7 +626,7 @@ static int s_find_hole(void) } /* determine if a base is already in the cache and if so, where */ -static int s_find_base(ecc_point *g) +static int s_find_base(const ecc_point *g) { int x; for (x = 0; x < FP_ENTRIES; x++) { @@ -620,7 +644,7 @@ static int s_find_base(ecc_point *g) } /* add a new base to the cache */ -static int s_add_entry(int idx, ecc_point *g) +static int s_add_entry(int idx, const ecc_point *g) { unsigned x, y; @@ -662,7 +686,7 @@ static int s_add_entry(int idx, ecc_point *g) * The algorithm builds patterns in increasing bit order by first making all * single bit input patterns, then all two bit input patterns and so on */ -static int s_build_lut(int idx, void *a, void *modulus, void *mp, void *mu) +static int s_build_lut(int idx, const void *ma, const void *modulus, void *mp, const void *mu) { unsigned x, y, err, bitlen, lut_gap; void *tmp; @@ -685,24 +709,24 @@ static int s_build_lut(int idx, void *a, void *modulus, void *mp, void *mu) /* init the mu */ if ((err = ltc_mp_init_copy(&fp_cache[idx].mu, mu)) != CRYPT_OK) { - goto ERR; + goto DONE; } /* copy base */ if ((ltc_mp_mulmod(fp_cache[idx].g->x, mu, modulus, fp_cache[idx].LUT[1]->x) != CRYPT_OK) || (ltc_mp_mulmod(fp_cache[idx].g->y, mu, modulus, fp_cache[idx].LUT[1]->y) != CRYPT_OK) || - (ltc_mp_mulmod(fp_cache[idx].g->z, mu, modulus, fp_cache[idx].LUT[1]->z) != CRYPT_OK)) { goto ERR; } + (ltc_mp_mulmod(fp_cache[idx].g->z, mu, modulus, fp_cache[idx].LUT[1]->z) != CRYPT_OK)) { err = CRYPT_ERROR; goto DONE; } /* make all single bit entries */ for (x = 1; x < FP_LUT; x++) { if ((ltc_mp_copy(fp_cache[idx].LUT[1<<(x-1)]->x, fp_cache[idx].LUT[1<x) != CRYPT_OK) || (ltc_mp_copy(fp_cache[idx].LUT[1<<(x-1)]->y, fp_cache[idx].LUT[1<y) != CRYPT_OK) || - (ltc_mp_copy(fp_cache[idx].LUT[1<<(x-1)]->z, fp_cache[idx].LUT[1<z) != CRYPT_OK)) { goto ERR; } + (ltc_mp_copy(fp_cache[idx].LUT[1<<(x-1)]->z, fp_cache[idx].LUT[1<z) != CRYPT_OK)) { err = CRYPT_MEM; goto DONE; } /* now double it bitlen/FP_LUT times */ for (y = 0; y < lut_gap; y++) { - if ((err = ltc_mp.ecc_ptdbl(fp_cache[idx].LUT[1<z, modulus, mp)) != CRYPT_OK) { goto ERR; } + if ((err = ltc_mp_montgomery_reduce(fp_cache[idx].LUT[x]->z, modulus, mp)) != CRYPT_OK) { goto DONE; } /* invert it */ - if ((err = ltc_mp_invmod(fp_cache[idx].LUT[x]->z, modulus, fp_cache[idx].LUT[x]->z)) != CRYPT_OK) { goto ERR; } + if ((err = ltc_mp_invmod(fp_cache[idx].LUT[x]->z, modulus, fp_cache[idx].LUT[x]->z)) != CRYPT_OK) { goto DONE; } /* now square it */ - if ((err = ltc_mp_sqrmod(fp_cache[idx].LUT[x]->z, modulus, tmp)) != CRYPT_OK) { goto ERR; } + if ((err = ltc_mp_sqrmod(fp_cache[idx].LUT[x]->z, modulus, tmp)) != CRYPT_OK) { goto DONE; } /* fix x */ - if ((err = ltc_mp_mulmod(fp_cache[idx].LUT[x]->x, tmp, modulus, fp_cache[idx].LUT[x]->x)) != CRYPT_OK) { goto ERR; } + if ((err = ltc_mp_mulmod(fp_cache[idx].LUT[x]->x, tmp, modulus, fp_cache[idx].LUT[x]->x)) != CRYPT_OK) { goto DONE; } /* get 1/z^3 */ - if ((err = ltc_mp_mulmod(tmp, fp_cache[idx].LUT[x]->z, modulus, tmp)) != CRYPT_OK) { goto ERR; } + if ((err = ltc_mp_mulmod(tmp, fp_cache[idx].LUT[x]->z, modulus, tmp)) != CRYPT_OK) { goto DONE; } /* fix y */ - if ((err = ltc_mp_mulmod(fp_cache[idx].LUT[x]->y, tmp, modulus, fp_cache[idx].LUT[x]->y)) != CRYPT_OK) { goto ERR; } + if ((err = ltc_mp_mulmod(fp_cache[idx].LUT[x]->y, tmp, modulus, fp_cache[idx].LUT[x]->y)) != CRYPT_OK) { goto DONE; } - /* free z */ + /* affine LUT points are stored without z so point-add can use the fast affine path */ ltc_mp_clear(fp_cache[idx].LUT[x]->z); fp_cache[idx].LUT[x]->z = NULL; } ltc_mp_clear(tmp); return CRYPT_OK; -ERR: - err = CRYPT_MEM; DONE: for (y = 0; y < (1U< ltc_mp_unsigned_bin_size(modulus)) { /* find order */ - y = ltc_mp_unsigned_bin_size(modulus); - for (x = 0; ltc_ecc_sets[x].size; x++) { - if (y <= (unsigned)ltc_ecc_sets[x].size) break; - } - - /* back off if we are on the 521 bit curve */ - if (y == 66) --x; - - if ((err = ltc_mp_init(&order)) != CRYPT_OK) { - return err; - } - if ((err = ltc_mp_read_radix(order, ltc_ecc_sets[x].order, 16)) != CRYPT_OK) { - ltc_mp_clear(&order); + if ((err = s_find_order_for_modulus(modulus, &order)) != CRYPT_OK) { return err; } /* k must be less than modulus */ if (ltc_mp_cmp(k, order) != LTC_MP_LT) { - if ((err = ltc_mp_init(&tk)) != CRYPT_OK) { + if ((err = ltc_mp_init(&tmpk)) != CRYPT_OK) { ltc_mp_clear(order); return err; } - if ((err = ltc_mp_mod(k, order, tk)) != CRYPT_OK) { - ltc_mp_clear(tk); + if ((err = ltc_mp_mod(k, order, tmpk)) != CRYPT_OK) { + ltc_mp_clear(tmpk); ltc_mp_clear(order); return err; } + tk = tmpk; } else { tk = k; } @@ -824,8 +836,8 @@ static int s_accel_fp_mul(int idx, void *k, ecc_point *R, void *a, void *modulus /* get the k value */ if (ltc_mp_unsigned_bin_size(tk) > (sizeof(kb) - 2)) { - if (tk != k) { - ltc_mp_clear(tk); + if (tmpk != NULL) { + ltc_mp_clear(tmpk); } return CRYPT_BUFFER_OVERFLOW; } @@ -833,8 +845,8 @@ static int s_accel_fp_mul(int idx, void *k, ecc_point *R, void *a, void *modulus /* store k */ zeromem(kb, sizeof(kb)); if ((err = ltc_mp_to_unsigned_bin(tk, kb)) != CRYPT_OK) { - if (tk != k) { - ltc_mp_clear(tk); + if (tmpk != NULL) { + ltc_mp_clear(tmpk); } return err; } @@ -842,8 +854,8 @@ static int s_accel_fp_mul(int idx, void *k, ecc_point *R, void *a, void *modulus /* let's reverse kb so it's little endian */ x = 0; y = ltc_mp_unsigned_bin_size(tk) - 1; - if (tk != k) { - ltc_mp_clear(tk); + if (tmpk != NULL) { + ltc_mp_clear(tmpk); } while ((unsigned)x < y) { z = kb[x]; kb[x] = kb[y]; kb[y] = z; @@ -862,14 +874,14 @@ static int s_accel_fp_mul(int idx, void *k, ecc_point *R, void *a, void *modulus /* double if not first */ if (!first) { - if ((err = ltc_mp.ecc_ptdbl(R, R, a, modulus, mp)) != CRYPT_OK) { + if ((err = ltc_mp.ecc_ptdbl(R, R, ma, modulus, mp)) != CRYPT_OK) { return err; } } /* add if not first, otherwise copy */ if (!first && z) { - if ((err = ltc_mp.ecc_ptadd(R, fp_cache[idx].LUT[z], R, a, modulus, mp)) != CRYPT_OK) { + if ((err = ltc_mp.ecc_ptadd(R, fp_cache[idx].LUT[z], R, ma, modulus, mp)) != CRYPT_OK) { return err; } } else if (z) { @@ -894,7 +906,7 @@ static int s_accel_fp_mul(int idx, void *k, ecc_point *R, void *a, void *modulus /* perform a fixed point ECC mulmod */ static int ss_accel_fp_mul2add(int idx1, int idx2, void *kA, void *kB, - ecc_point *R, void *a, void *modulus, void *mp) + ecc_point *R, const void *a, const void *modulus, void *mp) { unsigned char kb[2][128]; int x; @@ -904,19 +916,7 @@ static int ss_accel_fp_mul2add(int idx1, int idx2, /* if it's smaller than modulus we fine */ if (ltc_mp_unsigned_bin_size(kA) > ltc_mp_unsigned_bin_size(modulus)) { /* find order */ - y = ltc_mp_unsigned_bin_size(modulus); - for (x = 0; ltc_ecc_sets[x].size; x++) { - if (y <= (unsigned)ltc_ecc_sets[x].size) break; - } - - /* back off if we are on the 521 bit curve */ - if (y == 66) --x; - - if ((err = ltc_mp_init(&order)) != CRYPT_OK) { - return err; - } - if ((err = ltc_mp_read_radix(order, ltc_ecc_sets[x].order, 16)) != CRYPT_OK) { - ltc_mp_clear(&order); + if ((err = s_find_order_for_modulus(modulus, &order)) != CRYPT_OK) { return err; } @@ -942,19 +942,7 @@ static int ss_accel_fp_mul2add(int idx1, int idx2, /* if it's smaller than modulus we fine */ if (ltc_mp_unsigned_bin_size(kB) > ltc_mp_unsigned_bin_size(modulus)) { /* find order */ - y = ltc_mp_unsigned_bin_size(modulus); - for (x = 0; ltc_ecc_sets[x].size; x++) { - if (y <= (unsigned)ltc_ecc_sets[x].size) break; - } - - /* back off if we are on the 521 bit curve */ - if (y == 66) --x; - - if ((err = ltc_mp_init(&order)) != CRYPT_OK) { - return err; - } - if ((err = ltc_mp_read_radix(order, ltc_ecc_sets[x].order, 16)) != CRYPT_OK) { - ltc_mp_clear(&order); + if ((err = s_find_order_for_modulus(modulus, &order)) != CRYPT_OK) { return err; } @@ -1056,37 +1044,41 @@ static int ss_accel_fp_mul2add(int idx1, int idx2, } /* add if not first, otherwise copy */ - if (!first) { - if (zA) { - if ((err = ltc_mp.ecc_ptadd(R, fp_cache[idx1].LUT[zA], R, a, modulus, mp)) != CRYPT_OK) { - return err; - } - } - if (zB) { - if ((err = ltc_mp.ecc_ptadd(R, fp_cache[idx2].LUT[zB], R, a, modulus, mp)) != CRYPT_OK) { - return err; - } - } - } else { - if (zA) { - if ((ltc_mp_copy(fp_cache[idx1].LUT[zA]->x, R->x) != CRYPT_OK) || - (ltc_mp_copy(fp_cache[idx1].LUT[zA]->y, R->y) != CRYPT_OK) || - (ltc_mp_copy(fp_cache[idx1].mu, R->z) != CRYPT_OK)) { return CRYPT_MEM; } - first = 0; - } - if (zB && first == 0) { - if (zB) { - if ((err = ltc_mp.ecc_ptadd(R, fp_cache[idx2].LUT[zB], R, a, modulus, mp)) != CRYPT_OK) { - return err; - } - } - } else if (zB && first == 1) { - if ((ltc_mp_copy(fp_cache[idx2].LUT[zB]->x, R->x) != CRYPT_OK) || - (ltc_mp_copy(fp_cache[idx2].LUT[zB]->y, R->y) != CRYPT_OK) || - (ltc_mp_copy(fp_cache[idx2].mu, R->z) != CRYPT_OK)) { return CRYPT_MEM; } - first = 0; - } - } + if (!first) { + if (zA) { + if ((err = ltc_mp.ecc_ptadd(R, fp_cache[idx1].LUT[zA], R, a, modulus, mp)) != CRYPT_OK) { + return err; + } + } + if (zB) { + if ((err = ltc_mp.ecc_ptadd(R, fp_cache[idx2].LUT[zB], R, a, modulus, mp)) != CRYPT_OK) { + return err; + } + } + } else { + if (zA) { + if ((ltc_mp_copy(fp_cache[idx1].LUT[zA]->x, R->x) != CRYPT_OK) || + (ltc_mp_copy(fp_cache[idx1].LUT[zA]->y, R->y) != CRYPT_OK) || + (ltc_mp_copy(fp_cache[idx1].mu, R->z) != CRYPT_OK)) { + return CRYPT_MEM; + } + first = 0; + } + if (zB) { + if (!first) { + if ((err = ltc_mp.ecc_ptadd(R, fp_cache[idx2].LUT[zB], R, a, modulus, mp)) != CRYPT_OK) { + return err; + } + } else { + if ((ltc_mp_copy(fp_cache[idx2].LUT[zB]->x, R->x) != CRYPT_OK) || + (ltc_mp_copy(fp_cache[idx2].LUT[zB]->y, R->y) != CRYPT_OK) || + (ltc_mp_copy(fp_cache[idx2].mu, R->z) != CRYPT_OK)) { + return CRYPT_MEM; + } + first = 0; + } + } + } } zeromem(kb, sizeof(kb)); return ltc_ecc_map(R, modulus, mp); @@ -1099,14 +1091,15 @@ static int ss_accel_fp_mul2add(int idx1, int idx2, @param B Second point to multiply @param kB What to multiple B by @param C [out] Destination point (can overlap with A or B) + @param ma ECC curve parameter a in montgomery form @param modulus Modulus for curve @return CRYPT_OK on success */ -int ltc_ecc_fp_mul2add(ecc_point *A, void *kA, - ecc_point *B, void *kB, - ecc_point *C, - void *a, - void *modulus) +int ltc_ecc_fp_mul2add(const ecc_point *A, void *kA, + const ecc_point *B, void *kB, + ecc_point *C, + const void *ma, + const void *modulus) { int idx1, idx2, err; void *mp, *mu; @@ -1126,7 +1119,7 @@ int ltc_ecc_fp_mul2add(ecc_point *A, void *kA, } } } - if (idx1 != -1) { + if (idx1 >= 0) { /* increment LRU */ ++(fp_cache[idx1].lru_count); } @@ -1143,7 +1136,7 @@ int ltc_ecc_fp_mul2add(ecc_point *A, void *kA, } } } - if (idx2 != -1) { + if (idx2 >= 0) { /* increment LRU */ ++(fp_cache[idx2].lru_count); } @@ -1162,7 +1155,7 @@ int ltc_ecc_fp_mul2add(ecc_point *A, void *kA, } /* build the LUT */ - if ((err = s_build_lut(idx1, a, modulus, mp, mu)) != CRYPT_OK) { + if ((err = s_build_lut(idx1,ma, modulus, mp, mu)) != CRYPT_OK) { goto LBL_ERR;; } } @@ -1183,7 +1176,7 @@ int ltc_ecc_fp_mul2add(ecc_point *A, void *kA, } /* build the LUT */ - if ((err = s_build_lut(idx2, a, modulus, mp, mu)) != CRYPT_OK) { + if ((err = s_build_lut(idx2, ma, modulus, mp, mu)) != CRYPT_OK) { goto LBL_ERR;; } } @@ -1194,9 +1187,9 @@ int ltc_ecc_fp_mul2add(ecc_point *A, void *kA, /* compute mp */ if ((err = ltc_mp_montgomery_setup(modulus, &mp)) != CRYPT_OK) { goto LBL_ERR; } } - err = ss_accel_fp_mul2add(idx1, idx2, kA, kB, C, a, modulus, mp); + err = ss_accel_fp_mul2add(idx1, idx2, kA, kB, C, ma, modulus, mp); } else { - err = ltc_ecc_mul2add(A, kA, B, kB, C, a, modulus); + err = ltc_ecc_mul2add(A, kA, B, kB, C, ma, modulus); } LBL_ERR: LTC_MUTEX_UNLOCK(<c_ecc_fp_lock); @@ -1219,13 +1212,15 @@ int ltc_ecc_fp_mul2add(ecc_point *A, void *kA, @param map [boolean] If non-zero maps the point back to affine co-ordinates, otherwise it's left in jacobian-montgomery form @return CRYPT_OK if successful */ -int ltc_ecc_fp_mulmod(void *k, ecc_point *G, ecc_point *R, void *a, void *modulus, int map) +int ltc_ecc_fp_mulmod(const void *k, const ecc_point *G, ecc_point *R, const void *a, const void *modulus, int map) { int idx, err; - void *mp, *mu; + void *mp, *mu, *ma, *a_plus3; mp = NULL; mu = NULL; + ma = NULL; + a_plus3 = NULL; LTC_MUTEX_LOCK(<c_ecc_fp_lock); /* find point */ idx = s_find_base(G); @@ -1241,37 +1236,54 @@ int ltc_ecc_fp_mulmod(void *k, ecc_point *G, ecc_point *R, void *a, void *modulu } } } - if (idx != -1) { + if (idx >= 0) { /* increment LRU */ ++(fp_cache[idx].lru_count); } - - /* if it's 2 build the LUT, if it's higher just use the LUT */ - if (idx >= 0 && fp_cache[idx].lru_count == 2) { + if (idx >= 0 && fp_cache[idx].lru_count >= 2) { /* compute mp */ if ((err = ltc_mp_montgomery_setup(modulus, &mp)) != CRYPT_OK) { goto LBL_ERR; } - /* compute mu */ - if ((err = ltc_mp_init(&mu)) != CRYPT_OK) { - goto LBL_ERR; + /* match ltc_ecc_mulmod(): keep ma == NULL for curves with a == -3 */ + if ((err = ltc_mp_init(&a_plus3)) != CRYPT_OK) { + goto LBL_ERR; } - if ((err = ltc_mp_montgomery_normalization(mu, modulus)) != CRYPT_OK) { + if ((err = ltc_mp_add_d(a, 3, a_plus3)) != CRYPT_OK) { goto LBL_ERR; } + if (ltc_mp_cmp(a_plus3, modulus) != LTC_MP_EQ) { + if ((err = ltc_mp_init(&ma)) != CRYPT_OK) { + goto LBL_ERR; + } + if ((err = ltc_mp_init(&mu)) != CRYPT_OK) { + goto LBL_ERR; + } + if ((err = ltc_mp_montgomery_normalization(mu, modulus)) != CRYPT_OK) { + goto LBL_ERR; + } + if ((err = ltc_mp_mulmod(a, mu, modulus, ma)) != CRYPT_OK) { + goto LBL_ERR; + } + } else if (fp_cache[idx].lru_count == 2) { + if ((err = ltc_mp_init(&mu)) != CRYPT_OK) { + goto LBL_ERR; + } + if ((err = ltc_mp_montgomery_normalization(mu, modulus)) != CRYPT_OK) { + goto LBL_ERR; + } + } - /* build the LUT */ - if ((err = s_build_lut(idx, a, modulus, mp, mu)) != CRYPT_OK) { - goto LBL_ERR;; + /* if it's 2 build the LUT, if it's higher just use the LUT */ + if (fp_cache[idx].lru_count == 2) { + if ((err = s_build_lut(idx, ma, modulus, mp, mu)) != CRYPT_OK) { + goto LBL_ERR; + } } } if (idx >= 0 && fp_cache[idx].lru_count >= 2) { - if (mp == NULL) { - /* compute mp */ - if ((err = ltc_mp_montgomery_setup(modulus, &mp)) != CRYPT_OK) { goto LBL_ERR; } - } - err = s_accel_fp_mul(idx, k, R, a, modulus, mp, map); + err = s_accel_fp_mul(idx, k, R, ma, modulus, mp, map); } else { err = ltc_ecc_mulmod(k, G, R, a, modulus, map); } @@ -1283,6 +1295,12 @@ int ltc_ecc_fp_mulmod(void *k, ecc_point *G, ecc_point *R, void *a, void *modulu if (mu != NULL) { ltc_mp_clear(mu); } + if (ma != NULL) { + ltc_mp_clear(ma); + } + if (a_plus3 != NULL) { + ltc_mp_clear(a_plus3); + } return err; } @@ -1323,7 +1341,7 @@ void ltc_ecc_fp_free(void) @return CRYPT_OK on success */ int -ltc_ecc_fp_add_point(ecc_point *g, void *modulus, int lock) +ltc_ecc_fp_add_point(const ecc_point *g, const void *ma, const void *modulus, int lock) { int idx; int err; @@ -1339,13 +1357,17 @@ ltc_ecc_fp_add_point(ecc_point *g, void *modulus, int lock) } } - if(idx == -1 && (idx = s_find_hole()) == -1) { + if (idx == -1 && (idx = s_find_hole()) == -1) { err = CRYPT_BUFFER_OVERFLOW; goto LBL_ERR; } - if ((err = s_add_entry(idx, g)) != CRYPT_OK) { - goto LBL_ERR; + + if (idx >= 0 && fp_cache[idx].g == NULL) { + if ((err = s_add_entry(idx, g)) != CRYPT_OK) { + goto LBL_ERR; + } } + /* compute mp */ if ((err = ltc_mp_montgomery_setup(modulus, &mp)) != CRYPT_OK) { goto LBL_ERR; @@ -1353,15 +1375,14 @@ ltc_ecc_fp_add_point(ecc_point *g, void *modulus, int lock) /* compute mu */ if ((err = ltc_mp_init(&mu)) != CRYPT_OK) { - goto LBL_ERR; + goto LBL_ERR; } if ((err = ltc_mp_montgomery_normalization(mu, modulus)) != CRYPT_OK) { goto LBL_ERR; } - /* build the LUT */ - if ((err = s_build_lut(idx, a, modulus, mp, mu)) != CRYPT_OK) { - goto LBL_ERR; + if ((err = s_build_lut(idx, ma, modulus, mp, mu)) != CRYPT_OK) { + goto LBL_ERR; } fp_cache[idx].lru_count = 2; fp_cache[idx].lock = lock; @@ -1481,9 +1502,9 @@ int ltc_ecc_fp_save_state(unsigned char **out, unsigned long *outlen) int ltc_ecc_fp_restore_state(unsigned char *in, unsigned long inlen) { int err; - ltc_asn1_list *asn1_list; + ltc_asn1_list *decoded_list, *cur; unsigned long num_entries, fp_entries, fp_lut; - unsigned long i, j; + unsigned long i, decoded_len; unsigned int x; LTC_ARGCHK(in != NULL); @@ -1491,10 +1512,9 @@ int ltc_ecc_fp_restore_state(unsigned char *in, unsigned long inlen) return CRYPT_INVALID_ARG; } - /* zero indecies */ - i = 0; - j = 0; - asn1_list = NULL; + decoded_list = NULL; + cur = NULL; + decoded_len = inlen; LTC_MUTEX_LOCK(<c_ecc_fp_lock); /* @@ -1502,40 +1522,69 @@ int ltc_ecc_fp_restore_state(unsigned char *in, unsigned long inlen) */ s_ltc_ecc_fp_free_cache(); - /* - * decode the input packet: It consists of a sequence with a few - * integers (including the FP_ENTRIES and FP_LUT sizes), followed by a - * SEQUENCE which is the cache itself. - * - * use standard decoding for the first part, then flexible for the second - */ - if((err = der_decode_sequence_multi(in, inlen, - LTC_ASN1_SHORT_INTEGER, 1, &num_entries, - LTC_ASN1_SHORT_INTEGER, 1, &fp_entries, - LTC_ASN1_SHORT_INTEGER, 1, &fp_lut, - LTC_ASN1_EOL, 0, 0)) != CRYPT_OK) { + if ((err = der_decode_sequence_flexi(in, &decoded_len, &decoded_list)) != CRYPT_OK) { goto ERR_OUT; } - if (fp_entries != FP_ENTRIES || fp_lut != FP_LUT || num_entries > fp_entries) { + if (decoded_len != inlen) { err = CRYPT_INVALID_PACKET; goto ERR_OUT; } - if ((asn1_list = XCALLOC(3+num_entries*(4+2*(1<type != LTC_ASN1_SEQUENCE || cur->child == NULL || cur->next != NULL) { + err = CRYPT_INVALID_PACKET; + goto ERR_OUT; + } + + cur = cur->child; + if (cur->type != LTC_ASN1_INTEGER) { + err = CRYPT_INVALID_PACKET; + goto ERR_OUT; + } + num_entries = ltc_mp_get_int(cur->data); + cur = cur->next; + + if (cur == NULL || cur->type != LTC_ASN1_INTEGER) { + err = CRYPT_INVALID_PACKET; + goto ERR_OUT; + } + fp_entries = ltc_mp_get_int(cur->data); + cur = cur->next; + + if (cur == NULL || cur->type != LTC_ASN1_INTEGER) { + err = CRYPT_INVALID_PACKET; + goto ERR_OUT; + } + fp_lut = ltc_mp_get_int(cur->data); + cur = cur->next; + + if (fp_entries != FP_ENTRIES || fp_lut != FP_LUT || num_entries > fp_entries) { + err = CRYPT_INVALID_PACKET; goto ERR_OUT; } - j = 0; - LTC_SET_ASN1(asn1_list, j++, LTC_ASN1_SHORT_INTEGER, &num_entries, 1); - LTC_SET_ASN1(asn1_list, j++, LTC_ASN1_SHORT_INTEGER, &fp_entries, 1); - LTC_SET_ASN1(asn1_list, j++, LTC_ASN1_SHORT_INTEGER, &fp_lut, 1); + for (i = 0; i < num_entries; i++) { if((fp_cache[i].g = ltc_ecc_new_point()) == NULL) { err = CRYPT_MEM; goto ERR_OUT; } - LTC_SET_ASN1(asn1_list, j++, LTC_ASN1_INTEGER, fp_cache[i].g->x, 1); - LTC_SET_ASN1(asn1_list, j++, LTC_ASN1_INTEGER, fp_cache[i].g->y, 1); - LTC_SET_ASN1(asn1_list, j++, LTC_ASN1_INTEGER, fp_cache[i].g->z, 1); + + if (cur == NULL || cur->type != LTC_ASN1_INTEGER || (err = ltc_mp_copy(cur->data, fp_cache[i].g->x)) != CRYPT_OK) { + if (err == CRYPT_OK) err = CRYPT_INVALID_PACKET; + goto ERR_OUT; + } + cur = cur->next; + if (cur == NULL || cur->type != LTC_ASN1_INTEGER || (err = ltc_mp_copy(cur->data, fp_cache[i].g->y)) != CRYPT_OK) { + if (err == CRYPT_OK) err = CRYPT_INVALID_PACKET; + goto ERR_OUT; + } + cur = cur->next; + if (cur == NULL || cur->type != LTC_ASN1_INTEGER || (err = ltc_mp_copy(cur->data, fp_cache[i].g->z)) != CRYPT_OK) { + if (err == CRYPT_OK) err = CRYPT_INVALID_PACKET; + goto ERR_OUT; + } + cur = cur->next; + for (x = 0; x < (1U<z = NULL; - LTC_SET_ASN1(asn1_list, j++, LTC_ASN1_INTEGER, p->x, 1); - LTC_SET_ASN1(asn1_list, j++, LTC_ASN1_INTEGER, p->y, 1); + + if (cur == NULL || cur->type != LTC_ASN1_INTEGER || (err = ltc_mp_copy(cur->data, p->x)) != CRYPT_OK) { + if (err == CRYPT_OK) err = CRYPT_INVALID_PACKET; + goto ERR_OUT; + } + cur = cur->next; + if (cur == NULL || cur->type != LTC_ASN1_INTEGER || (err = ltc_mp_copy(cur->data, p->y)) != CRYPT_OK) { + if (err == CRYPT_OK) err = CRYPT_INVALID_PACKET; + goto ERR_OUT; + } + cur = cur->next; } - if((err = ltc_mp_init(&fp_cache[i].mu)) != CRYPT_OK) { + + if (cur == NULL || cur->type != LTC_ASN1_INTEGER) { + err = CRYPT_INVALID_PACKET; + goto ERR_OUT; + } + if((err = ltc_mp_init_copy(&fp_cache[i].mu, cur->data)) != CRYPT_OK) { goto ERR_OUT; } - LTC_SET_ASN1(asn1_list, j++, LTC_ASN1_INTEGER, fp_cache[i].mu, 1); + cur = cur->next; fp_cache[i].lru_count = 3; fp_cache[i].lock = 1; } - if ((err = der_decode_sequence(in, inlen, asn1_list, j)) != CRYPT_OK) { + if (cur != NULL) { + err = CRYPT_INVALID_PACKET; goto ERR_OUT; } - XFREE(asn1_list); + der_sequence_free(decoded_list); LTC_MUTEX_UNLOCK(<c_ecc_fp_lock); return CRYPT_OK; ERR_OUT: - if(asn1_list) - XFREE(asn1_list); + if (decoded_list != NULL) { + der_sequence_free(decoded_list); + } s_ltc_ecc_fp_free_cache(); LTC_MUTEX_UNLOCK(<c_ecc_fp_lock); return err; } #endif - - diff --git a/src/pk/ecc/ltc_ecc_is_point_at_infinity.c b/src/pk/ecc/ltc_ecc_is_point_at_infinity.c index 1a4f79613..ca22d50d7 100644 --- a/src/pk/ecc/ltc_ecc_is_point_at_infinity.c +++ b/src/pk/ecc/ltc_ecc_is_point_at_infinity.c @@ -14,6 +14,12 @@ int ltc_ecc_is_point_at_infinity(const ecc_point *P, const void *modulus, int *r int err; void *x3, *y2; + /* affine points in the fixed-point cache omit z entirely */ + if (P->z == NULL) { + *retval = 0; + return CRYPT_OK; + } + /* trivial case */ if (!ltc_mp_iszero(P->z)) { *retval = 0;