void pp_exp_k2(fp2_t c, fp2_t a) { bn_t e, n; bn_null(n); bn_null(e); TRY { bn_new(n); bn_new(e); ep_curve_get_ord(n); fp2_conv_uni(c, a); dv_copy(e->dp, fp_prime_get(), FP_DIGS); e->used = FP_DIGS; e->sign = BN_POS; bn_add_dig(e, e, 1); bn_div(e, e, n); fp2_exp_uni(c, c, e); } CATCH_ANY { THROW(ERR_CAUGHT); } FINALLY { bn_free(n); bn_free(e); } }
int cp_phpe_enc(uint8_t *out, int *out_len, uint8_t *in, int in_len, bn_t n) { bn_t g, m, r, s; int size, result = STS_OK; bn_null(g); bn_null(m); bn_null(r); bn_null(s); size = bn_size_bin(n); if (n == NULL || in_len <= 0 || in_len > size) { return STS_ERR; } TRY { bn_new(g); bn_new(m); bn_new(r); bn_new(s); /* Represent m as a padded element of Z_n. */ bn_read_bin(m, in, in_len); /* Generate r in Z_n^*. */ bn_rand_mod(r, n); /* Compute c = (g^m)(r^n) mod n^2. */ bn_add_dig(g, n, 1); bn_sqr(s, n); bn_mxp(m, g, m, s); bn_mxp(r, r, n, s); bn_mul(m, m, r); bn_mod(m, m, s); if (2 * size <= *out_len) { *out_len = 2 * size; memset(out, 0, *out_len); bn_write_bin(out, *out_len, m); } else { result = STS_ERR; } } CATCH_ANY { result = STS_ERR; } FINALLY { bn_free(g); bn_free(m); bn_free(r); bn_free(s); } return result; }
int cp_bdpe_dec(dig_t *out, uint8_t *in, int in_len, bdpe_t prv) { bn_t m, t, z; unsigned i; int size, result = STS_OK; size = bn_size_bin(prv->n); if (in_len < 0 || in_len != size) { return STS_ERR; } bn_null(m); bn_null(t); bn_null(z); TRY { bn_new(m); bn_new(t); bn_new(z); /* Compute t = (p-1)(q-1)/block. */ bn_mul(t, prv->p, prv->q); bn_sub(t, t, prv->p); bn_sub(t, t, prv->q); bn_add_dig(t, t, 1); bn_div_dig(t, t, prv->t); bn_read_bin(m, in, in_len); bn_mxp(m, m, t, prv->n); bn_mxp(t, prv->y, t, prv->n); for (i = 0; i < prv->t; i++) { bn_mxp_dig(z, t, i, prv->n); if (bn_cmp(z, m) == CMP_EQ) { *out = i; break; } } if (i == prv->t) { result = STS_ERR; } } CATCH_ANY { result = STS_ERR; } FINALLY { bn_free(m); bn_free(t); bn_free(z); } return result; }
/** * 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 fp_prime_set_pmers(const int *f, int len) { bn_t p, t; bn_null(p); bn_null(t); TRY { bn_new(p); bn_new(t); if (len >= MAX_TERMS) { THROW(ERR_NO_VALID); } bn_set_2b(p, f[len - 1]); for (int i = len - 2; i > 0; i--) { if (f[i] > 0) { bn_set_2b(t, f[i]); bn_add(p, p, t); } else { bn_set_2b(t, -f[i]); bn_sub(p, p, t); } } if (f[0] > 0) { bn_add_dig(p, p, f[0]); } else { bn_sub_dig(p, p, -f[0]); } #if FP_RDC == QUICK || !defined(STRIP) ctx_t *ctx = core_get(); for (int i = 0; i < len; i++) { ctx->sps[i] = f[i]; } ctx->sps[len] = 0; ctx->sps_len = len; #endif /* FP_RDC == QUICK */ fp_prime_set(p); } CATCH_ANY { THROW(ERR_CAUGHT); } FINALLY { bn_free(p); 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 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_read_str(bn_t a, const char *str, int len, int radix) { int sign, i, j; char c; bn_zero(a); if (radix < 2 || radix > 64) { THROW(ERR_NO_VALID) } j = 0; if (str[0] == '-') { j++; sign = BN_NEG; } else { sign = BN_POS; } while (str[j] && j < len) { c = (char)((radix < 36) ? TOUPPER(str[j]) : str[j]); for (i = 0; i < 64; i++) { if (c == util_conv_char(i)) { break; } } if (i < radix) { bn_mul_dig(a, a, (dig_t)radix); bn_add_dig(a, a, (dig_t)i); } else { break; } j++; } a->sign = sign; }
int cp_rsa_gen_quick(rsa_t pub, rsa_t prv, int bits) { bn_t t, r; int result = STS_OK; if (pub == NULL || prv == NULL || bits == 0) { return STS_ERR; } bn_null(t); bn_null(r); TRY { bn_new(t); bn_new(r); /* Generate different primes p and q. */ do { bn_gen_prime(prv->p, bits / 2); bn_gen_prime(prv->q, bits / 2); } while (bn_cmp(prv->p, prv->q) == CMP_EQ); /* Swap p and q so that p is smaller. */ if (bn_cmp(prv->p, prv->q) == CMP_LT) { bn_copy(t, prv->p); bn_copy(prv->p, prv->q); bn_copy(prv->q, t); } /* n = pq. */ bn_mul(pub->n, prv->p, prv->q); bn_copy(prv->n, pub->n); bn_sub_dig(prv->p, prv->p, 1); bn_sub_dig(prv->q, prv->q, 1); /* phi(n) = (p - 1)(q - 1). */ bn_mul(t, prv->p, prv->q); bn_set_2b(pub->e, 16); bn_add_dig(pub->e, pub->e, 1); /* d = e^(-1) mod phi(n). */ bn_gcd_ext(r, prv->d, NULL, pub->e, t); if (bn_sign(prv->d) == BN_NEG) { bn_add(prv->d, prv->d, t); } if (bn_cmp_dig(r, 1) == CMP_EQ) { /* dP = d mod (p - 1). */ bn_mod(prv->dp, prv->d, prv->p); /* dQ = d mod (q - 1). */ bn_mod(prv->dq, prv->d, prv->q); bn_add_dig(prv->p, prv->p, 1); bn_add_dig(prv->q, prv->q, 1); /* qInv = q^(-1) mod p. */ bn_gcd_ext(r, prv->qi, NULL, prv->q, prv->p); if (bn_sign(prv->qi) == BN_NEG) { bn_add(prv->qi, prv->qi, prv->p); } result = STS_OK; } } CATCH_ANY { result = STS_ERR; } FINALLY { bn_free(t); bn_free(r); } return result; }
/** * 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; }
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); } }
int cp_bdpe_gen(bdpe_t pub, bdpe_t prv, dig_t block, int bits) { bn_t t, r; int result = STS_OK; bn_null(t); bn_null(r); TRY { bn_new(t); bn_new(r); prv->t = pub->t = block; /* Make sure that block size is prime. */ bn_set_dig(t, block); if (bn_is_prime_basic(t) == 0) { THROW(ERR_NO_VALID); } /* Generate prime q such that gcd(block, (q - 1)) = 1. */ do { bn_gen_prime(prv->q, bits / 2); bn_sub_dig(prv->q, prv->q, 1); bn_gcd_dig(t, prv->q, block); bn_add_dig(prv->q, prv->q, 1); } while (bn_cmp_dig(t, 1) != CMP_EQ); /* Generate different primes p and q. */ do { /* Compute p = block * (x * block + b) + 1, 0 < b < block random. */ bn_rand(prv->p, BN_POS, bits / 2 - 2 * util_bits_dig(block)); bn_mul_dig(prv->p, prv->p, block); bn_rand(t, BN_POS, util_bits_dig(block)); bn_add_dig(prv->p, prv->p, t->dp[0]); /* We know that block divides (p-1). */ bn_gcd_dig(t, prv->p, block); bn_mul_dig(prv->p, prv->p, block); bn_add_dig(prv->p, prv->p, 1); } while (bn_cmp_dig(t, 1) != CMP_EQ || bn_is_prime(prv->p) == 0); /* Compute t = (p-1)*(q-1). */ bn_sub_dig(prv->q, prv->q, 1); bn_sub_dig(prv->p, prv->p, 1); bn_mul(t, prv->p, prv->q); bn_div_dig(t, t, block); /* Restore factors p and q and compute n = p * q. */ bn_add_dig(prv->p, prv->p, 1); bn_add_dig(prv->q, prv->q, 1); bn_mul(pub->n, prv->p, prv->q); bn_copy(prv->n, pub->n); /* Select random y such that y^{(p-1)(q-1)}/block \neq 1 mod N. */ do { bn_rand(pub->y, BN_POS, bits); bn_mxp(r, pub->y, t, pub->n); } while (bn_cmp_dig(r, 1) == CMP_EQ); bn_copy(prv->y, pub->y); } CATCH_ANY { result = STS_ERR; } FINALLY { bn_free(t); bn_free(r); } return result; }
void pp_map_oatep_k12(fp12_t r, ep_t p, ep2_t q) { ep_t _p[1]; ep2_t t[1], _q[1]; bn_t a; int len = FP_BITS, s[FP_BITS]; ep_null(_p[0]); ep2_null(_q[0]); ep2_null(t[0]); bn_null(a); TRY { ep_new(_p[0]); ep2_new(_q[0]); ep2_new(t[0]); bn_new(a); fp_param_get_var(a); bn_mul_dig(a, a, 6); bn_add_dig(a, a, 2); fp_param_get_map(s, &len); fp12_set_dig(r, 1); ep_norm(_p[0], p); ep2_norm(_q[0], q); if (!ep_is_infty(_p[0]) && !ep2_is_infty(_q[0])) { switch (ep_param_get()) { case BN_P158: case BN_P254: case BN_P256: case BN_P638: /* r = f_{|a|,Q}(P). */ pp_mil_sps_k12(r, t, _q, _p, 1, s, len); if (bn_sign(a) == BN_NEG) { /* f_{-a,Q}(P) = 1/f_{a,Q}(P). */ fp12_inv_uni(r, r); ep2_neg(t[0], t[0]); } pp_fin_k12_oatep(r, t[0], _q[0], _p[0]); pp_exp_k12(r, r); break; case B12_P638: /* r = f_{|a|,Q}(P). */ pp_mil_sps_k12(r, t, _q, _p, 1, s, len); if (bn_sign(a) == BN_NEG) { fp12_inv_uni(r, r); ep2_neg(t[0], t[0]); } pp_exp_k12(r, r); break; } } } CATCH_ANY { THROW(ERR_CAUGHT); } FINALLY { ep_free(_p[0]); ep2_free(_q[0]); ep2_free(t[0]); bn_free(a); } }
void pp_map_sim_oatep_k12(fp12_t r, ep_t *p, ep2_t *q, int m) { ep_t _p[m]; ep2_t t[m], _q[m]; bn_t a; int i, j, len = FP_BITS, s[FP_BITS]; TRY { bn_null(a); bn_new(a); for (i = 0; i < m; i++) { ep_null(_p[i]); ep2_null(_q[i]); ep2_null(t[i]); ep_new(_p[i]); ep2_new(_q[i]); ep2_new(t[i]); } j = 0; for (i = 0; i < m; i++) { if (!ep_is_infty(p[i]) && !ep2_is_infty(q[i])) { ep_norm(_p[j], p[i]); ep2_norm(_q[j++], q[i]); } } fp12_set_dig(r, 1); fp_param_get_var(a); bn_mul_dig(a, a, 6); bn_add_dig(a, a, 2); fp_param_get_map(s, &len); if (j > 0) { switch (ep_param_get()) { case BN_P158: case BN_P254: case BN_P256: case BN_P638: /* r = f_{|a|,Q}(P). */ pp_mil_sps_k12(r, t, _q, _p, j, s, len); if (bn_sign(a) == BN_NEG) { /* f_{-a,Q}(P) = 1/f_{a,Q}(P). */ fp12_inv_uni(r, r); } for (i = 0; i < j; i++) { if (bn_sign(a) == BN_NEG) { ep2_neg(t[i], t[i]); } pp_fin_k12_oatep(r, t[i], _q[i], _p[i]); } pp_exp_k12(r, r); break; case B12_P638: /* r = f_{|a|,Q}(P). */ pp_mil_sps_k12(r, t, _q, _p, j, s, len); if (bn_sign(a) == BN_NEG) { fp12_inv_uni(r, r); } pp_exp_k12(r, r); break; } } } CATCH_ANY { THROW(ERR_CAUGHT); } FINALLY { bn_free(a); for (i = 0; i < m; i++) { ep_free(_p[i]); ep2_free(_q[i]); ep2_free(t[i]); } } }
/** * Precomputes additional parameters for Koblitz curves used by the w-TNAF * multiplication algorithm. */ static void compute_kbltz(void) { int u, i; bn_t a, b, c; bn_null(a); bn_null(b); bn_null(c); TRY { bn_new(a); bn_new(b); bn_new(c); if (curve_opt_a == OPT_ZERO) { u = -1; } else { u = 1; } bn_set_dig(a, 2); bn_set_dig(b, 1); if (u == -1) { bn_neg(b, b); } for (i = 2; i <= FB_BITS; i++) { bn_copy(c, b); if (u == -1) { bn_neg(b, b); } bn_dbl(a, a); bn_sub(b, b, a); bn_copy(a, c); } bn_copy(&curve_vm, b); bn_zero(a); bn_set_dig(b, 1); for (i = 2; i <= FB_BITS; i++) { bn_copy(c, b); if (u == -1) { bn_neg(b, b); } bn_dbl(a, a); bn_sub(b, b, a); bn_add_dig(b, b, 1); bn_copy(a, c); } bn_copy(&curve_s0, b); bn_zero(a); bn_zero(b); for (i = 2; i <= FB_BITS; i++) { bn_copy(c, b); if (u == -1) { bn_neg(b, b); } bn_dbl(a, a); bn_sub(b, b, a); bn_sub_dig(b, b, 1); bn_copy(a, c); } bn_copy(&curve_s1, b); } CATCH_ANY { THROW(ERR_CAUGHT); } FINALLY { bn_free(a); bn_free(b); bn_free(c); } }
void bn_gen_prime_stron(bn_t a, int bits) { dig_t i, j; int found, k; bn_t r, s, t; bn_null(r); bn_null(s); bn_null(t); TRY { bn_new(r); bn_new(s); bn_new(t); do { do { /* Generate two large primes r and s. */ bn_rand(s, BN_POS, bits / 2 - BN_DIGIT / 2); bn_rand(t, BN_POS, bits / 2 - BN_DIGIT / 2); } while (!bn_is_prime(s) || !bn_is_prime(t)); found = 1; bn_rand(a, BN_POS, bits / 2 - bn_bits(t) - 1); i = a->dp[0]; bn_dbl(t, t); do { /* Find first prime r = 2 * i * t + 1. */ bn_mul_dig(r, t, i); bn_add_dig(r, r, 1); i++; if (bn_bits(r) > bits / 2 - 1) { found = 0; break; } } while (!bn_is_prime(r)); if (found == 0) { continue; } /* Compute t = 2 * (s^(r-2) mod r) * s - 1. */ bn_sub_dig(t, r, 2); #if BN_MOD != PMERS bn_mxp(t, s, t, r); #else bn_exp(t, s, t, r); #endif bn_mul(t, t, s); bn_dbl(t, t); bn_sub_dig(t, t, 1); k = bits - bn_bits(r); k -= bn_bits(s); bn_rand(a, BN_POS, k); j = a->dp[0]; do { /* Find first prime a = t + 2 * j * r * s. */ bn_mul(a, r, s); bn_mul_dig(a, a, j); bn_dbl(a, a); bn_add(a, a, t); j++; if (bn_bits(a) > bits) { found = 0; break; } } while (!bn_is_prime(a)); } while (found == 0 && bn_bits(a) != bits); } CATCH_ANY { THROW(ERR_CAUGHT); } FINALLY { bn_free(r); bn_free(s); bn_free(t); } }
void fp_param_set(int param) { bn_t t0, t1, t2, p; int f[10] = { 0 }; bn_null(t0); bn_null(t1); bn_null(t2); bn_null(p); /* Suppress possible unused parameter warning. */ (void) f; TRY { bn_new(t0); bn_new(t1); bn_new(t2); bn_new(p); core_get()->fp_id = param; switch (param) { #if FP_PRIME == 158 case BN_158: /* x = 4000000031. */ fp_param_get_var(t0); /* p = 36 * x^4 + 36 * x^3 + 24 * x^2 + 6 * x + 1. */ bn_set_dig(p, 1); bn_mul_dig(t1, t0, 6); bn_add(p, p, t1); bn_mul(t1, t0, t0); bn_mul_dig(t1, t1, 24); bn_add(p, p, t1); bn_mul(t1, t0, t0); bn_mul(t1, t1, t0); bn_mul_dig(t1, t1, 36); bn_add(p, p, t1); bn_mul(t0, t0, t0); bn_mul(t1, t0, t0); bn_mul_dig(t1, t1, 36); bn_add(p, p, t1); fp_prime_set_dense(p); break; #elif FP_PRIME == 160 case SECG_160: /* p = 2^160 - 2^31 + 1. */ f[0] = -1; f[1] = -31; f[2] = 160; fp_prime_set_pmers(f, 3); break; case SECG_160D: /* p = 2^160 - 2^32 - 2^14 - 2^12 - 2^9 - 2^8 - 2^7 - 2^3 - 2^2 - 1.*/ f[0] = -1; f[1] = -2; f[2] = -3; f[3] = -7; f[4] = -8; f[5] = -9; f[6] = -12; f[7] = -14; f[8] = -32; f[9] = 160; fp_prime_set_pmers(f, 10); break; #elif FP_PRIME == 192 case NIST_192: /* p = 2^192 - 2^64 - 1. */ f[0] = -1; f[1] = -64; f[2] = 192; fp_prime_set_pmers(f, 3); break; case SECG_192: /* p = 2^192 - 2^32 - 2^12 - 2^8 - 2^7 - 2^6 - 2^3 - 1.*/ f[0] = -1; f[1] = -3; f[2] = -6; f[3] = -7; f[4] = -8; f[5] = -12; f[6] = -32; f[7] = 192; fp_prime_set_pmers(f, 8); break; #elif FP_PRIME == 224 case NIST_224: /* p = 2^224 - 2^96 + 1. */ f[0] = 1; f[1] = -96; f[2] = 224; fp_prime_set_pmers(f, 3); break; case SECG_224: /* p = 2^224 - 2^32 - 2^12 - 2^11 - 2^9 - 2^7 - 2^4 - 2 - 1.*/ f[0] = -1; f[1] = -1; f[2] = -4; f[3] = -7; f[4] = -9; f[5] = -11; f[6] = -12; f[7] = -32; f[8] = 224; fp_prime_set_pmers(f, 9); break; #elif FP_PRIME == 254 case BN_254: /* x = -4080000000000001. */ fp_param_get_var(t0); /* p = 36 * x^4 + 36 * x^3 + 24 * x^2 + 6 * x + 1. */ bn_set_dig(p, 1); bn_mul_dig(t1, t0, 6); bn_add(p, p, t1); bn_mul(t1, t0, t0); bn_mul_dig(t1, t1, 24); bn_add(p, p, t1); bn_mul(t1, t0, t0); bn_mul(t1, t1, t0); bn_mul_dig(t1, t1, 36); bn_add(p, p, t1); bn_mul(t0, t0, t0); bn_mul(t1, t0, t0); bn_mul_dig(t1, t1, 36); bn_add(p, p, t1); fp_prime_set_dense(p); break; #elif FP_PRIME == 256 case NIST_256: /* p = 2^256 - 2^224 + 2^192 + 2^96 - 1. */ f[0] = -1; f[1] = 96; f[2] = 192; f[3] = -224; f[4] = 256; fp_prime_set_pmers(f, 5); break; case SECG_256: /* p = 2^256 - 2^32 - 2^9 - 2^8 - 2^7 - 2^6 - 2^4 - 1. */ f[0] = -1; f[1] = -4; f[2] = -6; f[3] = -7; f[4] = -8; f[5] = -9; f[6] = -32; f[7] = 256; fp_prime_set_pmers(f, 8); break; case BN_256: /* x = 6000000000001F2D. */ fp_param_get_var(t0); /* p = 36 * x^4 + 36 * x^3 + 24 * x^2 + 6 * x + 1. */ bn_set_dig(p, 1); bn_mul_dig(t1, t0, 6); bn_add(p, p, t1); bn_mul(t1, t0, t0); bn_mul_dig(t1, t1, 24); bn_add(p, p, t1); bn_mul(t1, t0, t0); bn_mul(t1, t1, t0); bn_mul_dig(t1, t1, 36); bn_add(p, p, t1); bn_mul(t0, t0, t0); bn_mul(t1, t0, t0); bn_mul_dig(t1, t1, 36); bn_add(p, p, t1); fp_prime_set_dense(p); break; #elif FP_PRIME == 384 case NIST_384: /* p = 2^384 - 2^128 - 2^96 + 2^32 - 1. */ f[0] = -1; f[1] = 32; f[2] = -96; f[3] = -128; f[4] = 384; fp_prime_set_pmers(f, 5); break; #elif FP_PRIME == 477 case B24_477: fp_param_get_var(t0); /* p = (u - 1)^2 * (u^8 - u^4 + 1) div 3 + u. */ bn_sub_dig(p, t0, 1); bn_sqr(p, p); bn_sqr(t1, t0); bn_sqr(t1, t1); bn_sqr(t2, t1); bn_sub(t2, t2, t1); bn_add_dig(t2, t2, 1); bn_mul(p, p, t2); bn_div_dig(p, p, 3); bn_add(p, p, t0); fp_prime_set_dense(p); break; #elif FP_PRIME == 508 case KSS_508: fp_param_get_var(t0); /* h = (49*u^2 + 245 * u + 343)/3 */ bn_mul_dig(p, t0, 245); bn_add_dig(p, p, 200); bn_add_dig(p, p, 143); bn_sqr(t1, t0); bn_mul_dig(t2, t1, 49); bn_add(p, p, t2); bn_div_dig(p, p, 3); /* n = (u^6 + 37 * u^3 + 343)/343. */ bn_mul(t1, t1, t0); bn_mul_dig(t2, t1, 37); bn_sqr(t1, t1); bn_add(t2, t2, t1); bn_add_dig(t2, t2, 200); bn_add_dig(t2, t2, 143); bn_div_dig(t2, t2, 49); bn_div_dig(t2, t2, 7); bn_mul(p, p, t2); /* t = (u^4 + 16 * u + 7)/7. */ bn_mul_dig(t1, t0, 16); bn_add_dig(t1, t1, 7); bn_sqr(t2, t0); bn_sqr(t2, t2); bn_add(t2, t2, t1); bn_div_dig(t2, t2, 7); bn_add(p, p, t2); bn_sub_dig(p, p, 1); fp_prime_set_dense(p); break; #elif FP_PRIME == 521 case NIST_521: /* p = 2^521 - 1. */ f[0] = -1; f[1] = 521; fp_prime_set_pmers(f, 2); break; #elif FP_PRIME == 638 case BN_638: fp_param_get_var(t0); /* p = 36 * x^4 + 36 * x^3 + 24 * x^2 + 6 * x + 1. */ bn_set_dig(p, 1); bn_mul_dig(t1, t0, 6); bn_add(p, p, t1); bn_mul(t1, t0, t0); bn_mul_dig(t1, t1, 24); bn_add(p, p, t1); bn_mul(t1, t0, t0); bn_mul(t1, t1, t0); bn_mul_dig(t1, t1, 36); bn_add(p, p, t1); bn_mul(t0, t0, t0); bn_mul(t1, t0, t0); bn_mul_dig(t1, t1, 36); bn_add(p, p, t1); fp_prime_set_dense(p); break; case B12_638: fp_param_get_var(t0); /* p = (x^2 - 2x + 1) * (x^4 - x^2 + 1)/3 + x. */ bn_sqr(t1, t0); bn_sqr(p, t1); bn_sub(p, p, t1); bn_add_dig(p, p, 1); bn_sub(t1, t1, t0); bn_sub(t1, t1, t0); bn_add_dig(t1, t1, 1); bn_mul(p, p, t1); bn_div_dig(p, p, 3); bn_add(p, p, t0); fp_prime_set_dense(p); break; #elif FP_PRIME == 1536 case SS_1536: fp_param_get_var(t0); bn_read_str(p, SS_P1536, strlen(SS_P1536), 16); bn_mul(p, p, t0); bn_dbl(p, p); bn_sub_dig(p, p, 1); fp_prime_set_dense(p); break; #else default: bn_gen_prime(p, FP_BITS); fp_prime_set_dense(p); core_get()->fp_id = 0; break; #endif } } CATCH_ANY { THROW(ERR_CAUGHT); } FINALLY { bn_free(t0); bn_free(t1); bn_free(t2); bn_free(p); } }
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; }