void ep_curve_set_endom(const fp_t b, const ep_t g, const bn_t r, const bn_t h, const fp_t beta, const bn_t l) { int bits = bn_bits(r); ctx_t *ctx = core_get(); ctx->ep_is_endom = 1; ctx->ep_is_super = 0; fp_zero(ctx->ep_a); fp_copy(ctx->ep_b, b); detect_opt(&(ctx->ep_opt_a), ctx->ep_a); detect_opt(&(ctx->ep_opt_b), ctx->ep_b); #if EP_MUL == LWNAF || EP_FIX == COMBS || EP_FIX == LWNAF || EP_SIM == INTER || !defined(STRIP) fp_copy(ctx->beta, beta); bn_gcd_ext_mid(&(ctx->ep_v1[1]), &(ctx->ep_v1[2]), &(ctx->ep_v2[1]), &(ctx->ep_v2[2]), l, r); /* l = v1[1] * v2[2] - v1[2] * v2[1], r = l / 2. */ bn_mul(&(ctx->ep_v1[0]), &(ctx->ep_v1[1]), &(ctx->ep_v2[2])); bn_mul(&(ctx->ep_v2[0]), &(ctx->ep_v1[2]), &(ctx->ep_v2[1])); bn_sub(&(ctx->ep_r), &(ctx->ep_v1[0]), &(ctx->ep_v2[0])); bn_hlv(&(ctx->ep_r), &(ctx->ep_r)); /* v1[0] = round(v2[2] * 2^|n| / l). */ bn_lsh(&(ctx->ep_v1[0]), &(ctx->ep_v2[2]), bits + 1); if (bn_sign(&(ctx->ep_v1[0])) == BN_POS) { bn_add(&(ctx->ep_v1[0]), &(ctx->ep_v1[0]), &(ctx->ep_r)); } else { bn_sub(&(ctx->ep_v1[0]), &(ctx->ep_v1[0]), &(ctx->ep_r)); } bn_dbl(&(ctx->ep_r), &(ctx->ep_r)); bn_div(&(ctx->ep_v1[0]), &(ctx->ep_v1[0]), &(ctx->ep_r)); if (bn_sign(&ctx->ep_v1[0]) == BN_NEG) { bn_add_dig(&(ctx->ep_v1[0]), &(ctx->ep_v1[0]), 1); } /* v2[0] = round(v1[2] * 2^|n| / l). */ bn_lsh(&(ctx->ep_v2[0]), &(ctx->ep_v1[2]), bits + 1); if (bn_sign(&(ctx->ep_v2[0])) == BN_POS) { bn_add(&(ctx->ep_v2[0]), &(ctx->ep_v2[0]), &(ctx->ep_r)); } else { bn_sub(&(ctx->ep_v2[0]), &(ctx->ep_v2[0]), &(ctx->ep_r)); } bn_div(&(ctx->ep_v2[0]), &(ctx->ep_v2[0]), &(ctx->ep_r)); if (bn_sign(&ctx->ep_v2[0]) == BN_NEG) { bn_add_dig(&(ctx->ep_v2[0]), &(ctx->ep_v2[0]), 1); } bn_neg(&(ctx->ep_v2[0]), &(ctx->ep_v2[0])); #endif ep_norm(&(ctx->ep_g), g); bn_copy(&(ctx->ep_r), r); bn_copy(&(ctx->ep_h), h); #if defined(EP_PRECO) ep_mul_pre((ep_t *)ep_curve_get_tab(), &(ctx->ep_g)); #endif }
/** * Applies or removes simple encryption padding. * * @param[out] m - the buffer to pad. * @param[out] p_len - the number of added pad bytes. * @param[in] m_len - the message length in bytes. * @param[in] k_len - the key length in bytes. * @param[in] operation - flag to indicate the operation type. * @return STS_ERR if errors occurred, STS_OK otherwise. */ static int pad_basic(bn_t m, int *p_len, int m_len, int k_len, int operation) { uint8_t pad = 0; int result = STS_OK; bn_t t; TRY { bn_null(t); bn_new(t); switch (operation) { case RSA_ENC: case RSA_SIG: case RSA_SIG_HASH: /* EB = 00 | FF | D. */ bn_zero(m); bn_lsh(m, m, 8); bn_add_dig(m, m, RSA_PAD); /* Make room for the real message. */ bn_lsh(m, m, m_len * 8); break; case RSA_DEC: case RSA_VER: case RSA_VER_HASH: /* EB = 00 | FF | D. */ m_len = k_len - 1; bn_rsh(t, m, 8 * m_len); if (!bn_is_zero(t)) { result = STS_ERR; } *p_len = 1; do { (*p_len)++; m_len--; bn_rsh(t, m, 8 * m_len); pad = (uint8_t)t->dp[0]; } while (pad == 0); if (pad != RSA_PAD) { result = STS_ERR; } bn_mod_2b(m, m, (k_len - *p_len) * 8); break; } } CATCH_ANY { result = STS_ERR; } FINALLY { bn_free(t); } return result; }
void ep2_curve_get_vs(bn_t *v) { bn_t x, t; bn_null(x); bn_null(t); TRY { bn_new(x); bn_new(t); fp_param_get_var(x); bn_mul_dig(v[0], x, 3); bn_add_dig(v[0], v[0], 1); bn_copy(v[1], x); bn_copy(v[2], x); bn_copy(v[3], x); bn_sqr(x, x); bn_lsh(t, x, 1); bn_add(v[0], v[0], t); bn_add(v[3], v[3], t); bn_lsh(t, t, 1); bn_add(v[2], v[2], t); bn_lsh(t, t, 1); bn_add(v[1], v[1], t); fp_param_get_var(t); bn_mul(x, x, t); bn_mul_dig(t, x, 6); bn_add(v[2], v[2], t); bn_lsh(t, t, 1); bn_add(v[1], v[1], t); bn_neg(v[3], v[3]); } CATCH_ANY { THROW(ERR_CAUGHT); } FINALLY { bn_free(x); bn_free(t); } }
void bn_gen_prime_safep(bn_t a, int bits) { while (1) { do { bn_rand(a, BN_POS, bits); } while (bn_bits(a) != bits); /* Check if (a - 1)/2 is prime. */ bn_sub_dig(a, a, 1); bn_rsh(a, a, 1); if (bn_is_prime(a)) { /* Restore a. */ bn_lsh(a, a, 1); bn_add_dig(a, a, 1); if (bn_is_prime(a)) { /* Should be prime now. */ return; } } } }
void fp_prime_conv(fp_t c, const bn_t a) { bn_t t; bn_null(t); TRY { bn_new(t); #if FP_RDC == MONTY bn_mod(t, a, &(core_get()->prime)); bn_lsh(t, t, FP_DIGS * FP_DIGIT); bn_mod(t, t, &(core_get()->prime)); dv_copy(c, t->dp, FP_DIGS); #else if (a->used > FP_DIGS) { THROW(ERR_NO_PRECI); } bn_mod(t, a, &(core_get()->prime)); if (bn_is_zero(t)) { fp_zero(c); } else { int i; for (i = 0; i < t->used; i++) { c[i] = t->dp[i]; } for (; i < FP_DIGS; i++) { c[i] = 0; } } (void)t; #endif } CATCH_ANY { THROW(ERR_CAUGHT); } FINALLY { bn_free(t); } }
/** * Applies or removes a PKCS#1 v2.1 encryption padding. * * @param[out] m - the buffer to pad. * @param[out] p_len - the number of added pad bytes. * @param[in] m_len - the message length in bytes. * @param[in] k_len - the key length in bytes. * @param[in] operation - flag to indicate the operation type. * @return STS_ERR if errors occurred, STS_OK otherwise. */ static int pad_pkcs2(bn_t m, int *p_len, int m_len, int k_len, int operation) { uint8_t pad, h1[MD_LEN], h2[MD_LEN], mask[k_len]; int result = STS_OK; bn_t t; bn_null(t); TRY { bn_new(t); switch (operation) { case RSA_ENC: /* DB = lHash | PS | 01 | D. */ md_map(h1, NULL, 0); bn_read_bin(m, h1, MD_LEN); *p_len = k_len - 2 * MD_LEN - 2 - m_len; bn_lsh(m, m, *p_len * 8); bn_lsh(m, m, 8); bn_add_dig(m, m, 0x01); /* Make room for the real message. */ bn_lsh(m, m, m_len * 8); break; case RSA_ENC_FIN: /* EB = 00 | maskedSeed | maskedDB. */ rand_bytes(h1, MD_LEN); md_mgf1(mask, k_len - MD_LEN - 1, h1, MD_LEN); bn_read_bin(t, mask, k_len - MD_LEN - 1); for (int i = 0; i < t->used; i++) { m->dp[i] ^= t->dp[i]; } bn_write_bin(mask, k_len - MD_LEN - 1, m); md_mgf1(h2, MD_LEN, mask, k_len - MD_LEN - 1); for (int i = 0; i < MD_LEN; i++) { h1[i] ^= h2[i]; } bn_read_bin(t, h1, MD_LEN); bn_lsh(t, t, 8 * (k_len - MD_LEN - 1)); bn_add(t, t, m); bn_copy(m, t); break; case RSA_DEC: m_len = k_len - 1; bn_rsh(t, m, 8 * m_len); if (!bn_is_zero(t)) { result = STS_ERR; } m_len -= MD_LEN; bn_rsh(t, m, 8 * m_len); bn_write_bin(h1, MD_LEN, t); bn_mod_2b(m, m, 8 * m_len); bn_write_bin(mask, m_len, m); md_mgf1(h2, MD_LEN, mask, m_len); for (int i = 0; i < MD_LEN; i++) { h1[i] ^= h2[i]; } md_mgf1(mask, k_len - MD_LEN - 1, h1, MD_LEN); bn_read_bin(t, mask, k_len - MD_LEN - 1); for (int i = 0; i < t->used; i++) { m->dp[i] ^= t->dp[i]; } m_len -= MD_LEN; bn_rsh(t, m, 8 * m_len); bn_write_bin(h2, MD_LEN, t); md_map(h1, NULL, 0); pad = 0; for (int i = 0; i < MD_LEN; i++) { pad |= h1[i] - h2[i]; } if (result == STS_OK) { result = (pad ? STS_ERR : STS_OK); } bn_mod_2b(m, m, 8 * m_len); *p_len = bn_size_bin(m); (*p_len)--; bn_rsh(t, m, *p_len * 8); if (bn_cmp_dig(t, 1) != CMP_EQ) { result = STS_ERR; } bn_mod_2b(m, m, *p_len * 8); *p_len = k_len - *p_len; break; case RSA_SIG: case RSA_SIG_HASH: /* M' = 00 00 00 00 00 00 00 00 | H(M). */ bn_zero(m); bn_lsh(m, m, 64); /* Make room for the real message. */ bn_lsh(m, m, MD_LEN * 8); break; case RSA_SIG_FIN: memset(mask, 0, 8); bn_write_bin(mask + 8, MD_LEN, m); md_map(h1, mask, MD_LEN + 8); bn_read_bin(m, h1, MD_LEN); md_mgf1(mask, k_len - MD_LEN - 1, h1, MD_LEN); bn_read_bin(t, mask, k_len - MD_LEN - 1); t->dp[0] ^= 0x01; /* m_len is now the size in bits of the modulus. */ bn_lsh(t, t, 8 * MD_LEN); bn_add(m, t, m); bn_lsh(m, m, 8); bn_add_dig(m, m, RSA_PSS); for (int i = m_len - 1; i < 8 * k_len; i++) { bn_set_bit(m, i, 0); } break; case RSA_VER: case RSA_VER_HASH: bn_mod_2b(t, m, 8); if (bn_cmp_dig(t, RSA_PSS) != CMP_EQ) { result = STS_ERR; } else { for (int i = m_len; i < 8 * k_len; i++) { if (bn_get_bit(m, i) != 0) { result = STS_ERR; } } bn_rsh(m, m, 8); bn_mod_2b(t, m, 8 * MD_LEN); bn_write_bin(h2, MD_LEN, t); bn_rsh(m, m, 8 * MD_LEN); bn_write_bin(h1, MD_LEN, t); md_mgf1(mask, k_len - MD_LEN - 1, h1, MD_LEN); bn_read_bin(t, mask, k_len - MD_LEN - 1); for (int i = 0; i < t->used; i++) { m->dp[i] ^= t->dp[i]; } m->dp[0] ^= 0x01; for (int i = m_len - 1; i < 8 * k_len; i++) { bn_set_bit(m, i - ((MD_LEN + 1) * 8), 0); } if (!bn_is_zero(m)) { result = STS_ERR; } bn_read_bin(m, h2, MD_LEN); *p_len = k_len - MD_LEN; } break; } } CATCH_ANY { result = STS_ERR; } FINALLY { bn_free(t); } return result; }
/** * Applies or removes a PKCS#1 v1.5 encryption padding. * * @param[out] m - the buffer to pad. * @param[out] p_len - the number of added pad bytes. * @param[in] m_len - the message length in bytes. * @param[in] k_len - the key length in bytes. * @param[in] operation - flag to indicate the operation type. * @return STS_ERR if errors occurred, STS_OK otherwise. */ static int pad_pkcs1(bn_t m, int *p_len, int m_len, int k_len, int operation) { uint8_t *id, pad = 0; int len, result = STS_OK; bn_t t; bn_null(t); TRY { bn_new(t); switch (operation) { case RSA_ENC: /* EB = 00 | 02 | PS | 00 | D. */ bn_zero(m); bn_lsh(m, m, 8); bn_add_dig(m, m, RSA_PUB); *p_len = k_len - 3 - m_len; for (int i = 0; i < *p_len; i++) { bn_lsh(m, m, 8); do { rand_bytes(&pad, 1); } while (pad == 0); bn_add_dig(m, m, pad); } bn_lsh(m, m, 8); bn_add_dig(m, m, 0); /* Make room for the real message. */ bn_lsh(m, m, m_len * 8); break; case RSA_DEC: m_len = k_len - 1; bn_rsh(t, m, 8 * m_len); if (!bn_is_zero(t)) { result = STS_ERR; } *p_len = m_len; m_len--; bn_rsh(t, m, 8 * m_len); pad = (uint8_t)t->dp[0]; if (pad != RSA_PUB) { result = STS_ERR; } do { m_len--; bn_rsh(t, m, 8 * m_len); pad = (uint8_t)t->dp[0]; } while (pad != 0); /* Remove padding and trailing zero. */ *p_len -= (m_len - 1); bn_mod_2b(m, m, (k_len - *p_len) * 8); break; case RSA_SIG: /* EB = 00 | 01 | PS | 00 | D. */ id = hash_id(MD_MAP, &len); bn_zero(m); bn_lsh(m, m, 8); bn_add_dig(m, m, RSA_PRV); *p_len = k_len - 3 - m_len - len; for (int i = 0; i < *p_len; i++) { bn_lsh(m, m, 8); bn_add_dig(m, m, RSA_PAD); } bn_lsh(m, m, 8); bn_add_dig(m, m, 0); bn_lsh(m, m, 8 * len); bn_read_bin(t, id, len); bn_add(m, m, t); /* Make room for the real message. */ bn_lsh(m, m, m_len * 8); break; case RSA_SIG_HASH: /* EB = 00 | 01 | PS | 00 | D. */ bn_zero(m); bn_lsh(m, m, 8); bn_add_dig(m, m, RSA_PRV); *p_len = k_len - 3 - m_len; for (int i = 0; i < *p_len; i++) { bn_lsh(m, m, 8); bn_add_dig(m, m, RSA_PAD); } bn_lsh(m, m, 8); bn_add_dig(m, m, 0); /* Make room for the real message. */ bn_lsh(m, m, m_len * 8); break; case RSA_VER: m_len = k_len - 1; bn_rsh(t, m, 8 * m_len); if (!bn_is_zero(t)) { result = STS_ERR; } m_len--; bn_rsh(t, m, 8 * m_len); pad = (uint8_t)t->dp[0]; if (pad != RSA_PRV) { result = STS_ERR; } do { m_len--; bn_rsh(t, m, 8 * m_len); pad = (uint8_t)t->dp[0]; } while (pad != 0 && m_len > 0); if (m_len == 0) { result = STS_ERR; } /* Remove padding and trailing zero. */ id = hash_id(MD_MAP, &len); m_len -= len; bn_rsh(t, m, m_len * 8); int r = 0; for (int i = 0; i < len; i++) { pad = (uint8_t)t->dp[0]; r |= pad - id[len - i - 1]; bn_rsh(t, t, 8); } *p_len = k_len - m_len; bn_mod_2b(m, m, m_len * 8); result = (r == 0 ? STS_OK : STS_ERR); break; case RSA_VER_HASH: m_len = k_len - 1; bn_rsh(t, m, 8 * m_len); if (!bn_is_zero(t)) { result = STS_ERR; } m_len--; bn_rsh(t, m, 8 * m_len); pad = (uint8_t)t->dp[0]; if (pad != RSA_PRV) { result = STS_ERR; } do { m_len--; bn_rsh(t, m, 8 * m_len); pad = (uint8_t)t->dp[0]; } while (pad != 0 && m_len > 0); if (m_len == 0) { result = STS_ERR; } /* Remove padding and trailing zero. */ *p_len = k_len - m_len; bn_mod_2b(m, m, m_len * 8); break; } } CATCH_ANY { result = STS_ERR; } FINALLY { bn_free(t); } return result; }
int bn_is_prime_rabin(const bn_t a) { bn_t t, n1, y, r; int i, s, j, result, b, tests = 0; tests = 0; result = 1; bn_null(t); bn_null(n1); bn_null(y); bn_null(r); if (bn_cmp_dig(a, 1) == CMP_EQ) { return 0; } TRY { /* * These values are taken from Table 4.4 inside Handbook of Applied * Cryptography. */ b = bn_bits(a); if (b >= 1300) { tests = 2; } else if (b >= 850) { tests = 3; } else if (b >= 650) { tests = 4; } else if (b >= 550) { tests = 5; } else if (b >= 450) { tests = 6; } else if (b >= 400) { tests = 7; } else if (b >= 350) { tests = 8; } else if (b >= 300) { tests = 9; } else if (b >= 250) { tests = 12; } else if (b >= 200) { tests = 15; } else if (b >= 150) { tests = 18; } else { tests = 27; } bn_new(t); bn_new(n1); bn_new(y); bn_new(r); /* r = (n - 1)/2^s. */ bn_sub_dig(n1, a, 1); s = 0; while (bn_is_even(n1)) { s++; bn_rsh(n1, n1, 1); } bn_lsh(r, n1, s); for (i = 0; i < tests; i++) { /* Fix the basis as the first few primes. */ bn_set_dig(t, primes[i]); /* y = b^r mod a. */ #if BN_MOD != PMERS bn_mxp(y, t, r, a); #else bn_exp(y, t, r, a); #endif if (bn_cmp_dig(y, 1) != CMP_EQ && bn_cmp(y, n1) != CMP_EQ) { j = 1; while ((j <= (s - 1)) && bn_cmp(y, n1) != CMP_EQ) { bn_sqr(y, y); bn_mod(y, y, a); /* If y == 1 then composite. */ if (bn_cmp_dig(y, 1) == CMP_EQ) { result = 0; break; } ++j; } /* If y != n1 then composite. */ if (bn_cmp(y, n1) != CMP_EQ) { result = 0; break; } } } } CATCH_ANY { result = 0; THROW(ERR_CAUGHT); } FINALLY { bn_free(r); bn_free(y); bn_free(n1); bn_free(t); } return result; }
/** * Assigns the prime field modulus. * * @param[in] p - the new prime field modulus. */ static void fp_prime_set(const bn_t p) { dv_t s, q; bn_t t; ctx_t *ctx = core_get(); if (p->used != FP_DIGS) { THROW(ERR_NO_VALID); } dv_null(s); bn_null(t); dv_null(q); TRY { dv_new(s); bn_new(t); dv_new(q); bn_copy(&(ctx->prime), p); bn_mod_dig(&(ctx->mod8), &(ctx->prime), 8); switch (ctx->mod8) { case 3: case 7: ctx->qnr = -1; /* The current code for extensions of Fp^3 relies on qnr being * also a cubic non-residue. */ ctx->cnr = 0; break; case 1: case 5: ctx->qnr = ctx->cnr = -2; break; default: ctx->qnr = ctx->cnr = 0; THROW(ERR_NO_VALID); break; } #ifdef FP_QNRES if (ctx->mod8 != 3) { THROW(ERR_NO_VALID); } #endif #if FP_RDC == MONTY || !defined(STRIP) bn_mod_pre_monty(t, &(ctx->prime)); ctx->u = t->dp[0]; dv_zero(s, 2 * FP_DIGS); s[2 * FP_DIGS] = 1; dv_zero(q, 2 * FP_DIGS + 1); dv_copy(q, ctx->prime.dp, FP_DIGS); bn_divn_low(t->dp, ctx->conv.dp, s, 2 * FP_DIGS + 1, q, FP_DIGS); ctx->conv.used = FP_DIGS; bn_trim(&(ctx->conv)); bn_set_dig(&(ctx->one), 1); bn_lsh(&(ctx->one), &(ctx->one), ctx->prime.used * BN_DIGIT); bn_mod(&(ctx->one), &(ctx->one), &(ctx->prime)); #endif fp_prime_calc(); } CATCH_ANY { THROW(ERR_CAUGHT); } FINALLY { bn_free(t); dv_free(s); dv_free(q); } }
/** * Computes the square of a multiple precision integer using recursive Karatsuba * squaring. * * @param[out] c - the result. * @param[in] a - the multiple precision integer to square. * @param[in] level - the number of Karatsuba steps to apply. */ static void bn_sqr_karat_imp(bn_t c, const bn_t a, int level) { int h; bn_t a0, a1, a0a0, a1a1, t; const dig_t *tmpa; dig_t *t0; bn_null(a0); bn_null(a1); bn_null(a0a0); bn_null(a1a1); bn_null(t); /* Compute half the digits of a or b. */ h = a->used >> 1; TRY { /* Allocate the temp variables. */ bn_new(a0); bn_new(a1); bn_new(a0a0); bn_new(a1a1); bn_new(t); a0->used = h; a1->used = a->used - h; tmpa = a->dp; /* a = a1 || a0 */ t0 = a0->dp; for (int i = 0; i < h; i++, t0++, tmpa++) *t0 = *tmpa; t0 = a1->dp; for (int i = 0; i < a1->used; i++, t0++, tmpa++) *t0 = *tmpa; bn_trim(a0); if (level <= 1) { /* a0a0 = a0 * a0 and a1a1 = a1 * a1 */ #if BN_SQR == BASIC bn_sqr_basic(a0a0, a0); bn_sqr_basic(a1a1, a1); #elif BN_SQR == COMBA bn_sqr_comba(a0a0, a0); bn_sqr_comba(a1a1, a1); #elif BN_SQR == MULTP bn_mul_comba(a0a0, a0, a0); bn_mul_comba(a1a1, a1, a1); #endif } else { bn_sqr_karat_imp(a0a0, a0, level - 1); bn_sqr_karat_imp(a1a1, a1, level - 1); } /* t = (a1 + a0) */ bn_add(t, a1, a0); if (level <= 1) { /* t = (a1 + a0)*(a1 + a0) */ #if BN_SQR == BASIC bn_sqr_basic(t, t); #elif BN_SQR == COMBA bn_sqr_comba(t, t); #elif BN_SQR == MULTP bn_mul_comba(t, t, t); #endif } else { bn_sqr_karat_imp(t, t, level - 1); } /* t2 = (a0*a0 + a1*a1) */ bn_add(a0, a0a0, a1a1); /* t = (a1 + a0)*(b1 + b0) - (a0*a0 + a1*a1) */ bn_sub(t, t, a0); /* t = (a1 + a0)*(a1 + a0) - (a0*a0 + a1*a1) << h digits */ bn_lsh(t, t, h * BN_DIGIT); /* t2 = a1 * b1 << 2*h digits */ bn_lsh(a1a1, a1a1, 2 * h * BN_DIGIT); /* t = t + a0*a0 */ bn_add(t, t, a0a0); /* c = t + a1*a1 */ bn_add(t, t, a1a1); t->sign = BN_POS; bn_copy(c, t); } CATCH_ANY { THROW(ERR_CAUGHT); } FINALLY { bn_free(a0); bn_free(a1); bn_free(a0a0); bn_free(a1a1); bn_free(t); } }
int fp_srt(fp_t c, const fp_t a) { bn_t e; fp_t t0; fp_t t1; int r = 0; bn_null(e); fp_null(t0); fp_null(t1); TRY { bn_new(e); fp_new(t0); fp_new(t1); /* Make e = p. */ e->used = FP_DIGS; dv_copy(e->dp, fp_prime_get(), FP_DIGS); if (fp_prime_get_mod8() == 3 || fp_prime_get_mod8() == 7) { /* Easy case, compute a^((p + 1)/4). */ bn_add_dig(e, e, 1); bn_rsh(e, e, 2); fp_exp(t0, a, e); fp_sqr(t1, t0); r = (fp_cmp(t1, a) == CMP_EQ); fp_copy(c, t0); } else { int f = 0, m = 0; /* First, check if there is a root. Compute t1 = a^((p - 1)/2). */ bn_rsh(e, e, 1); fp_exp(t0, a, e); if (fp_cmp_dig(t0, 1) != CMP_EQ) { /* Nope, there is no square root. */ r = 0; } else { r = 1; /* Find a quadratic non-residue modulo p, that is a number t2 * such that (t2 | p) = t2^((p - 1)/2)!= 1. */ do { fp_rand(t1); fp_exp(t0, t1, e); } while (fp_cmp_dig(t0, 1) == CMP_EQ); /* Write p - 1 as (e * 2^f), odd e. */ bn_lsh(e, e, 1); while (bn_is_even(e)) { bn_rsh(e, e, 1); f++; } /* Compute t2 = t2^e. */ fp_exp(t1, t1, e); /* Compute t1 = a^e, c = a^((e + 1)/2) = a^(e/2 + 1), odd e. */ bn_rsh(e, e, 1); fp_exp(t0, a, e); fp_mul(e->dp, t0, a); fp_sqr(t0, t0); fp_mul(t0, t0, a); fp_copy(c, e->dp); while (1) { if (fp_cmp_dig(t0, 1) == CMP_EQ) { break; } fp_copy(e->dp, t0); for (m = 0; (m < f) && (fp_cmp_dig(t0, 1) != CMP_EQ); m++) { fp_sqr(t0, t0); } fp_copy(t0, e->dp); for (int i = 0; i < f - m - 1; i++) { fp_sqr(t1, t1); } fp_mul(c, c, t1); fp_sqr(t1, t1); fp_mul(t0, t0, t1); f = m; } } } } CATCH_ANY { THROW(ERR_CAUGHT); } FINALLY { bn_free(e); fp_free(t0); fp_free(t1); } return r; }
void fp_param_get_var(bn_t x) { bn_t a; bn_null(a); TRY { bn_new(a); switch (fp_param_get()) { case BN_158: /* x = 4000000031. */ bn_set_2b(x, 38); bn_add_dig(x, x, 0x31); break; case BN_254: /* x = -4080000000000001. */ bn_set_2b(x, 62); bn_set_2b(a, 55); bn_add(x, x, a); bn_add_dig(x, x, 1); bn_neg(x, x); break; case BN_256: /* x = -600000000000219B. */ bn_set_2b(x, 62); bn_set_2b(a, 61); bn_add(x, x, a); bn_set_dig(a, 0x21); bn_lsh(a, a, 8); bn_add(x, x, a); bn_add_dig(x, x, 0x9B); bn_neg(x, x); break; case B24_477: /* x = -2^48 + 2^45 + 2^31 - 2^7. */ bn_set_2b(x, 48); bn_set_2b(a, 45); bn_sub(x, x, a); bn_set_2b(a, 31); bn_sub(x, x, a); bn_set_2b(a, 7); bn_add(x, x, a); bn_neg(x, x); break; case KSS_508: /* x = -(2^64 + 2^51 - 2^46 - 2^12). */ bn_set_2b(x, 64); bn_set_2b(a, 51); bn_add(x, x, a); bn_set_2b(a, 46); bn_sub(x, x, a); bn_set_2b(a, 12); bn_sub(x, x, a); bn_neg(x, x); break; case BN_638: /* x = 2^158 - 2^128 - 2^68 + 1. */ bn_set_2b(x, 158); bn_set_2b(a, 128); bn_sub(x, x, a); bn_set_2b(a, 68); bn_sub(x, x, a); bn_add_dig(x, x, 1); break; case B12_638: /* x = -2^107 + 2^105 + 2^93 + 2^5. */ bn_set_2b(x, 107); bn_set_2b(a, 105); bn_sub(x, x, a); bn_set_2b(a, 93); bn_sub(x, x, a); bn_set_2b(a, 5); bn_sub(x, x, a); bn_neg(x, x); break; case SS_1536: /* x = 2^255 + 2^41 + 1. */ bn_set_2b(x, 255); bn_set_2b(a, 41); bn_add(x, x, a); bn_add_dig(x, x, 1); break; default: THROW(ERR_NO_VALID); break; } } CATCH_ANY { THROW(ERR_CAUGHT); } FINALLY { bn_free(a); } }