/*------------------------------------------------------------ * * is_small_prime * * Returns 1 if n is prime, Returns 0 if n is composite * Returns -1 if we cannot decide * */ static int is_small_prime(mpanum n) { mpa_word_t v; /* If n is larger than a mpa_word_t, we can only decide if */ /* n is even. If it's odd we cannot tell. */ if (__mpanum_size(n) > 1) return ((mpa_parity(n) == MPA_EVEN_PARITY) ? 0 : -1); v = mpa_get_word(n); /* will convert negative n:s to positive v:s. */ if ((v | 1) == 1) /* 0 and 1 are not prime */ return DEF_COMPOSITE; if (v == 2) /* 2 is prime */ return DEF_PRIME; if ((v & 1) == 0) return DEF_COMPOSITE; /* but no other even number */ #if defined(USE_PRIME_TABLE) if (mpa_cmp_short(n, MAX_TABULATED_PRIME) > 0) return -1; v = (v - 3) >> 1; return check_table(v); #else return -1; #endif }
/* * TEE_BigIntMulMod */ void TEE_BigIntMulMod(TEE_BigInt *dest, const TEE_BigInt *op1, const TEE_BigInt *op2, const TEE_BigInt *n) { mpanum mpa_dest = (mpa_num_base *)dest; mpanum mpa_op1 = (mpa_num_base *)op1; mpanum mpa_op2 = (mpa_num_base *)op2; mpanum mpa_n = (mpa_num_base *)n; mpanum tmp_dest; if (TEE_BigIntCmpS32(n, 2) < 0) TEE_BigInt_Panic("Modulus is too short"); /* * From the spec, mpa_dest must be of magnitude "mpa_n" * But internal computations in mpa do not have such assumptions * (as __mpa_div_q_r, where "r" must be of magnitude "op1", * whereas GP provides a magnitude of "op2") * This is a tempory variable is used, before storing the * final result. */ mpa_alloc_static_temp_var(&tmp_dest, mempool); mpa_mul_mod(tmp_dest, mpa_op1, mpa_op2, mpa_n, mempool); if (mpa_cmp_short(tmp_dest, 0) < 0) mpa_add(tmp_dest, tmp_dest, mpa_n, mempool); mpa_copy(mpa_dest, tmp_dest); mpa_free_static_temp_var(&tmp_dest, mempool); }
/* get size as unsigned char string */ static unsigned long unsigned_size(void *a) { unsigned long t; LTC_ARGCHK(a != NULL); t = count_bits(a); if (mpa_cmp_short((const mpanum)a, 0) == 0) return 0; return (t>>3) + ((t&7)?1:0); }
static int mod(void *a, void *b, void *c) { LTC_ARGCHK(a != NULL); LTC_ARGCHK(b != NULL); LTC_ARGCHK(c != NULL); mpa_mod((mpanum) c, (const mpanum) a, (const mpanum) b, external_mem_pool); if (mpa_cmp_short(c, 0) < 0) { mpa_add(c, c, b, external_mem_pool); } return CRYPT_OK; }
/*------------------------------------------------------------ * * has_small_factors * * returns 1 if n has small factors * returns 0 if not. */ static int has_small_factors(mpanum n, mpa_scratch_mem pool) { const mpa_num_base *factors = &const_small_prime_factors; int result; mpanum res; mpa_alloc_static_temp_var(&res, pool); mpa_gcd(res, n, (const mpanum)factors, pool); result = (mpa_cmp_short(res, 1) == 0) ? 0 : 1; mpa_free_static_temp_var(&res, pool); return result; }
/*------------------------------------------------------------ * * mpa_inv_mod * */ int mpa_inv_mod(mpanum dest, const mpanum op, const mpanum n, mpa_scratch_mem pool) { mpanum gcd; mpanum tmp_dest; int mem_marker; int res; if (mpa_cmp_short(op, 1) == 0) { mpa_set_S32(dest, 1); return 0; } mem_marker = (dest == op); if (mem_marker) mpa_alloc_static_temp_var(&tmp_dest, pool); else tmp_dest = dest; mpa_alloc_static_temp_var(&gcd, pool); /* The function mpa_extended_gcd behaves badly if tmp_dest = op */ mpa_extended_gcd(gcd, tmp_dest, NULL, op, n, pool); res = mpa_cmp_short(gcd, 1); if (mem_marker) { mpa_copy(dest, tmp_dest); mpa_free_static_temp_var(&tmp_dest, pool); } mpa_free_static_temp_var(&gcd, pool); if (res == 0) { while (mpa_cmp_short(dest, 0) < 0) mpa_add(dest, dest, n, pool); return 0; } else { return -1; } }
/* * TEE_BigIntSubMod */ void TEE_BigIntSubMod(TEE_BigInt *dest, const TEE_BigInt *op1, const TEE_BigInt *op2, const TEE_BigInt *n) { mpanum mpa_dest = (mpa_num_base *)dest; mpanum mpa_op1 = (mpa_num_base *)op1; mpanum mpa_op2 = (mpa_num_base *)op2; mpanum mpa_n = (mpa_num_base *)n; if (TEE_BigIntCmpS32(n, 2) < 0) TEE_BigInt_Panic("Modulus is too short"); mpa_sub_mod(mpa_dest, mpa_op1, mpa_op2, mpa_n, mempool); if (mpa_cmp_short(mpa_dest, 0) < 0) mpa_add(mpa_dest, mpa_dest, mpa_n, mempool); }
/* * TEE_BigIntRelativePrime */ bool TEE_BigIntRelativePrime(const TEE_BigInt *op1, const TEE_BigInt *op2) { mpanum mpa_op1 = (mpa_num_base *)op1; mpanum mpa_op2 = (mpa_num_base *)op2; mpanum gcd; uint32_t cmp; mpa_alloc_static_temp_var(&gcd, mempool); mpa_gcd(gcd, mpa_op1, mpa_op2, mempool); cmp = mpa_cmp_short(gcd, 1); mpa_free_static_temp_var(&gcd, mempool); return cmp == 0 ? true : false; }
static int compare_d(void *a, unsigned long b) { int ret; LTC_ARGCHK(a != NULL); // this particular case must be handled separately... if (b > (unsigned long) MPA_INT_MAX) { mpanum tmp = (mpanum) a; ret = (tmp->size <= 0 ? LTC_MP_LT : tmp->size > 1 ? LTC_MP_GT : tmp->d[0] < b ? LTC_MP_LT : tmp->d[0] == b ? LTC_MP_EQ : LTC_MP_GT); } else { ret = mpa_cmp_short(((const mpanum)a), b); } if (ret < 0) { return LTC_MP_LT; } else if (ret > 0) { return LTC_MP_GT; } else { return LTC_MP_EQ; } }
/* * TEE_BigIntCmpS32 */ int32_t TEE_BigIntCmpS32(const TEE_BigInt *op, int32_t shortVal) { mpanum mpa_op = (mpa_num_base *)op; return mpa_cmp_short(mpa_op, shortVal); }
/*------------------------------------------------------------ * * primality_test_miller_rabin * */ static int primality_test_miller_rabin(mpanum n, int conf_level, mpa_scratch_mem pool) { int result; bool proof_version; static const int32_t proof_a[7] = { 2, 3, 5, 7, 11, 13, 17 }; int cnt; int idx; int t; int e = 0; int cmp_one; mpanum a; mpanum q; mpanum n_minus_1; mpanum b; mpanum r_modn; mpanum r2_modn; mpa_word_t n_inv; mpa_alloc_static_temp_var(&r_modn, pool); mpa_alloc_static_temp_var(&r2_modn, pool); if (mpa_compute_fmm_context(n, r_modn, r2_modn, &n_inv, pool) == -1) { result = DEF_COMPOSITE; goto cleanup_short; } mpa_alloc_static_temp_var(&a, pool); mpa_alloc_static_temp_var(&q, pool); mpa_alloc_static_temp_var(&n_minus_1, pool); mpa_alloc_static_temp_var(&b, pool); proof_version = (mpa_cmp(n, (mpanum) &const_miller_rabin_proof_limit) < 0); if (proof_version) cnt = 7; else /* MR has 1/4 chance in failing a composite */ cnt = (conf_level + 1) / 2; mpa_sub_word(n_minus_1, n, 1, pool); mpa_set(q, n_minus_1); t = 0; /* calculate q such that n - 1 = 2^t * q where q is odd */ while (mpa_is_even(q)) { mpa_shift_right(q, q, 1); t++; } result = PROB_PRIME; for (idx = 0; idx < cnt && result == PROB_PRIME; idx++) { if (proof_version) { mpa_set_S32(a, proof_a[idx]); if (mpa_cmp(n, a) == 0) { result = DEF_PRIME; continue; } } else { /* * Get random a, 1 < a < N by * asking for a random in range 0 <= x < N - 2 * and then add 2 to it. */ mpa_sub_word(n_minus_1, n_minus_1, 1, pool); /* n_minus_1 is now N - 2 ! */ mpa_get_random(a, n_minus_1); mpa_add_word(n_minus_1, n_minus_1, 1, pool); /* and a is now 2 <= a < N */ mpa_add_word(a, a, 2, pool); } mpa_exp_mod(b, a, q, n, r_modn, r2_modn, n_inv, pool); e = 0; inner_loop: cmp_one = mpa_cmp_short(b, 1); if ((cmp_one == 0) && (e > 0)) { result = DEF_COMPOSITE; continue; } if ((mpa_cmp(b, n_minus_1) == 0) || ((cmp_one == 0) && (e == 0))) { /* probably prime, try another a */ continue; } e++; if (e < t) { mpa_exp_mod(b, b, (mpanum) &const_two, n, r_modn, r2_modn, n_inv, pool); goto inner_loop; } result = DEF_COMPOSITE; } if (result == PROB_PRIME && proof_version) result = DEF_PRIME; mpa_free_static_temp_var(&a, pool); mpa_free_static_temp_var(&q, pool); mpa_free_static_temp_var(&n_minus_1, pool); mpa_free_static_temp_var(&b, pool); cleanup_short: mpa_free_static_temp_var(&r_modn, pool); mpa_free_static_temp_var(&r2_modn, pool); return result; }