void eb_curve_get_vm(bn_t vm) { if (core_get()->eb_is_kbltz) { bn_copy(vm, &(core_get()->eb_vm)); } else { bn_zero(vm); } }
void bn_sqr_basic(bn_t c, const bn_t a) { int i, digits; bn_t t; bn_null(t); digits = 2 * a->used; TRY { bn_new_size(t, digits); bn_zero(t); t->used = digits; for (i = 0; i < a->used; i++) { bn_sqra_low(t->dp + (2 * i), a->dp + i, a->used - i); } t->sign = BN_POS; bn_trim(t); bn_copy(c, t); } CATCH_ANY { THROW(ERR_CAUGHT); } FINALLY { bn_free(t); } }
void eb_curve_get_vm(bn_t vm) { if (curve_is_kbltz) { bn_copy(vm, &curve_vm); } else { bn_zero(vm); } }
void eb_curve_get_s0(bn_t s0) { if (core_get()->eb_is_kbltz) { bn_copy(s0, &(core_get()->eb_s0)); } else { bn_zero(s0); } }
void eb_curve_get_s0(bn_t s0) { if (curve_is_kbltz) { bn_copy(s0, &curve_s0); } else { bn_zero(s0); } }
void eb_curve_get_s1(bn_t s1) { if (curve_is_kbltz) { bn_copy(s1, &curve_s1); } else { bn_zero(s1); } }
void bn_read_bin(bn_t a, const uint8_t *bin, int len) { int i, j; dig_t d = (BN_DIGIT / 8); int digs = (len % d == 0 ? len / d : len / d + 1); bn_grow(a, digs); bn_zero(a); a->used = digs; for (i = 0; i < digs - 1; i++) { d = 0; for (j = (BN_DIGIT / 8) - 1; j >= 0; j--) { d = d << 8; d |= bin[len - 1 - (i * (BN_DIGIT / 8) + j)]; } a->dp[i] = d; } d = 0; for (j = (BN_DIGIT / 8) - 1; j >= 0; j--) { if ((int)(i * (BN_DIGIT / 8) + j) < len) { d = d << 8; d |= bin[len - 1 - (i * (BN_DIGIT / 8) + j)]; } } a->dp[i] = d; a->sign = BN_POS; bn_trim(a); }
void eb_curve_get_s1(bn_t s1) { if (core_get()->eb_is_kbltz) { bn_copy(s1, &(core_get()->eb_s1)); } else { bn_zero(s1); } }
void bn_from_mon(uint8_t *d, uint8_t *N, uint32_t n) { uint8_t t[512]; bn_zero(t, n); t[n-1] = 1; bn_mon_mul(d, d, t, N, n); }
int bn_zero_array(bn_t * array, int size) { for (int i = 0; i < size; ++i) { bn_zero(array[i]); } return 0; }
void bn_from_mon(u8 *d, u8 *N, u32 n) { u8 t[512]; bn_zero(t, n); t[n-1] = 1; bn_mon_mul(d, d, t, N, n); }
void bn_mon_inv(u8 *d, u8 *a, u8 *N, u32 n) { u8 t[512], s[512]; bn_zero(s, n); s[n-1] = 2; bn_sub_1(t, N, s, n); bn_mon_exp(d, a, N, n, t, n); }
void bn_mon_inv(uint8_t *d, uint8_t *a, uint8_t *N, uint32_t n) { uint8_t t[512], s[512]; bn_zero(s, n); s[n-1] = 2; bn_sub_1(t, N, s, n); bn_mon_exp(d, a, N, n, t, n); }
// only for prime N -- stupid but lazy, see if I care void bn_inv(u8 *d, u8 *a, u8 *N, u32 n) { u8 t[512], s[512]; bn_copy(t, N, n); bn_zero(s, n); s[n-1] = 2; bn_sub_modulus(t, s, n); bn_exp(d, a, N, n, t, n); }
uint32_t eccutils_affine_to_projective(bn_uint_t *ax, bn_uint_t *ay, bn_uint_t *px, bn_uint_t *py, bn_uint_t *pz, ecc_curve_t *curve) { (void)(curve); //trying to create (X,Y,Z) => (X,Y,1) from (x,y) bn_copy(ax, px, ax->length); bn_copy(ay, py, ay->length); bn_zero(pz); pz->number[0] = 1; return 0; }
void bn_mon_mul(u8 *d, u8 *a, u8 *b, u8 *N, u32 n) { u8 t[512]; u32 i; bn_zero(t, n); for (i = n - 1; i < n; i--) bn_mon_muladd_dig(t, a, b[i], N, n); bn_copy(d, t, n); }
void bn_mon_mul(uint8_t *d, uint8_t *a, uint8_t *b, uint8_t *N, uint32_t n) { uint8_t t[512]; uint32_t i; bn_zero(t, n); for (i = n - 1; i < n; i--) bn_mon_muladd_dig(t, a, b[i], N, n); bn_copy(d, t, n); }
int mpz2bn(bn_t out, mpz_t in) { int size = mpz_sizeinbase(in, 10) + 2; // + 2 bytes for minus sign and NULL char * temp = malloc(sizeof(char)*size); mpz_get_str(temp, 10, in); bn_zero(out); bn_read_str(out, temp, size, 10); free(temp); return 0; }
/** * 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 bn_mul(u8 *d, u8 *a, u8 *b, u8 *N, u32 n) { u32 i; u8 mask; bn_zero(d, n); for (i = 0; i < n; i++) for (mask = 0x80; mask != 0; mask >>= 1) { bn_add(d, d, d, N, n); if ((a[i] & mask) != 0) bn_add(d, d, b, N, n); } }
status_t element_init_Zr(element_t e, int init_value) { // if(e->bn != NULL) bn_free(e->bn); bn_inits(e->bn); bn_inits(e->order); if(init_value == 0) /* default value */ bn_zero(e->bn); else bn_set_dig(e->bn, (dig_t) init_value); g1_get_ord(e->order); e->isInitialized = TRUE; e->type = ZR; return ELEMENT_OK; }
void bn_exp(u8 *d, u8 *a, u8 *N, u32 n, u8 *e, u32 en) { u8 t[512]; u32 i; u8 mask; bn_zero(d, n); d[n-1] = 1; for (i = 0; i < en; i++) for (mask = 0x80; mask != 0; mask >>= 1) { bn_mul(t, d, d, N, n); if ((e[i] & mask) != 0) bn_mul(d, t, a, N, n); else bn_copy(d, t, n); } }
static void bn_mon_exp(uint8_t *d, uint8_t *a, uint8_t *N, uint32_t n, uint8_t *e, uint32_t en) { uint8_t t[512]; uint32_t i; uint8_t mask; bn_zero(d, n); d[n-1] = 1; bn_to_mon(d, N, n); for (i = 0; i < en; i++) for (mask = 0x80; mask != 0; mask >>= 1) { bn_mon_mul(t, d, d, N, n); if ((e[i] & mask) != 0) bn_mon_mul(d, t, a, N, n); else bn_copy(d, t, n); } }
uint32_t eccutils_projective_to_affine(bn_uint_t *px, bn_uint_t *py, bn_uint_t *pz, bn_uint_t *ax, bn_uint_t *ay, ecc_curve_t *curve) { BN_CREATE_VARIABLE(invz, pz->length); BN_CREATE_VARIABLE(invztmp, pz->length); BN_CREATE_VARIABLE(invztmp2, pz->length); bn_zero(&invz); invz.number[0] = 1; if (bn_compare(&invz, pz) == 0) { bn_copy(px, ax, px->length); bn_copy(py, ay, py->length); return 0; } bn_field_inverse(pz, curve->p, &invz); bn_field_mul_barret(&invz, &invz, curve->barret_mi, curve->p, &invztmp); //now we've got z^2 bn_field_mul_barret(&invztmp, px, curve->barret_mi, curve->p, ax); //now we've got affine x bn_field_mul_barret(&invztmp, &invz, curve->barret_mi, curve->p, &invztmp2); //now we've got z^3 bn_field_mul_barret(&invztmp2, py, curve->barret_mi, curve->p, ay); //now we've got affine y return 0; }
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; }
/** * 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; }
/** * Divides two multiple precision integers, computing the quotient and the * remainder. * * @param[out] c - the quotient. * @param[out] d - the remainder. * @param[in] a - the dividend. * @param[in] b - the the divisor. */ static void bn_div_imp(bn_t c, bn_t d, const bn_t a, const bn_t b) { bn_t q, x, y, r; int sign; bn_null(q); bn_null(x); bn_null(y); bn_null(r); /* If a < b, we're done. */ if (bn_cmp_abs(a, b) == CMP_LT) { if (bn_sign(a) == BN_POS) { if (c != NULL) { bn_zero(c); } if (d != NULL) { bn_copy(d, a); } } else { if (c != NULL) { bn_set_dig(c, 1); if (bn_sign(b) == BN_POS) { bn_neg(c, c); } } if (d != NULL) { if (bn_sign(b) == BN_POS) { bn_add(d, a, b); } else { bn_sub(d, a, b); } } } return; } TRY { bn_new(x); bn_new(y); bn_new_size(q, a->used + 1); bn_new(r); bn_zero(q); bn_zero(r); bn_abs(x, a); bn_abs(y, b); /* Find the sign. */ sign = (a->sign == b->sign ? BN_POS : BN_NEG); bn_divn_low(q->dp, r->dp, x->dp, a->used, y->dp, b->used); /* We have the quotient in q and the remainder in r. */ if (c != NULL) { q->used = a->used - b->used + 1; q->sign = sign; bn_trim(q); if (bn_sign(a) == BN_NEG) { bn_sub_dig(c, q, 1); } else { bn_copy(c, q); } } if (d != NULL) { r->used = b->used; r->sign = a->sign; bn_trim(r); if (bn_sign(a) == BN_NEG) { bn_add(d, r, b); } else { bn_copy(d, r); } } } CATCH_ANY { THROW(ERR_CAUGHT); } FINALLY { bn_free(r); bn_free(q); bn_free(x); bn_free(y); } }
int cp_rsa_enc(uint8_t *out, int *out_len, uint8_t *in, int in_len, rsa_t pub) { bn_t m, eb; int size, pad_len, result = STS_OK; bn_null(m); bn_null(eb); size = bn_size_bin(pub->n); if (pub == NULL || in_len <= 0 || in_len > (size - RSA_PAD_LEN)) { return STS_ERR; } TRY { bn_new(m); bn_new(eb); bn_zero(m); bn_zero(eb); #if CP_RSAPD == BASIC if (pad_basic(eb, &pad_len, in_len, size, RSA_ENC) == STS_OK) { #elif CP_RSAPD == PKCS1 if (pad_pkcs1(eb, &pad_len, in_len, size, RSA_ENC) == STS_OK) { #elif CP_RSAPD == PKCS2 if (pad_pkcs2(eb, &pad_len, in_len, size, RSA_ENC) == STS_OK) { #endif bn_read_bin(m, in, in_len); bn_add(eb, eb, m); #if CP_RSAPD == PKCS2 pad_pkcs2(eb, &pad_len, in_len, size, RSA_ENC_FIN); #endif bn_mxp(eb, eb, pub->e, pub->n); if (size <= *out_len) { *out_len = size; memset(out, 0, *out_len); bn_write_bin(out, size, eb); } else { result = STS_ERR; } } else { result = STS_ERR; } } CATCH_ANY { result = STS_ERR; } FINALLY { bn_free(m); bn_free(eb); } return result; } #if CP_RSA == BASIC || !defined(STRIP) int cp_rsa_dec_basic(uint8_t *out, int *out_len, uint8_t *in, int in_len, rsa_t prv) { bn_t m, eb; int size, pad_len, result = STS_OK; size = bn_size_bin(prv->n); if (prv == NULL || in_len != size || in_len < RSA_PAD_LEN) { return STS_ERR; } bn_null(m); bn_null(eb); TRY { bn_new(m); bn_new(eb); bn_read_bin(eb, in, in_len); bn_mxp(eb, eb, prv->d, prv->n); if (bn_cmp(eb, prv->n) != CMP_LT) { result = STS_ERR; } #if CP_RSAPD == BASIC if (pad_basic(eb, &pad_len, in_len, size, RSA_DEC) == STS_OK) { #elif CP_RSAPD == PKCS1 if (pad_pkcs1(eb, &pad_len, in_len, size, RSA_DEC) == STS_OK) { #elif CP_RSAPD == PKCS2 if (pad_pkcs2(eb, &pad_len, in_len, size, RSA_DEC) == STS_OK) { #endif size = size - pad_len; if (size <= *out_len) { memset(out, 0, size); bn_write_bin(out, size, eb); *out_len = size; } else { result = STS_ERR; } } else { result = STS_ERR; } } CATCH_ANY { result = STS_ERR; } FINALLY { bn_free(m); bn_free(eb); } return result; } #endif #if CP_RSA == QUICK || !defined(STRIP) int cp_rsa_dec_quick(uint8_t *out, int *out_len, uint8_t *in, int in_len, rsa_t prv) { bn_t m, eb; int size, pad_len, result = STS_OK; bn_null(m); bn_null(eb); size = bn_size_bin(prv->n); if (prv == NULL || in_len != size || in_len < RSA_PAD_LEN) { return STS_ERR; } TRY { bn_new(m); bn_new(eb); bn_read_bin(eb, in, in_len); bn_copy(m, eb); /* m1 = c^dP mod p. */ bn_mxp(eb, eb, prv->dp, prv->p); /* m2 = c^dQ mod q. */ bn_mxp(m, m, prv->dq, prv->q); /* m1 = m1 - m2 mod p. */ bn_sub(eb, eb, m); while (bn_sign(eb) == BN_NEG) { bn_add(eb, eb, prv->p); } bn_mod(eb, eb, prv->p); /* m1 = qInv(m1 - m2) mod p. */ bn_mul(eb, eb, prv->qi); bn_mod(eb, eb, prv->p); /* m = m2 + m1 * q. */ bn_mul(eb, eb, prv->q); bn_add(eb, eb, m); if (bn_cmp(eb, prv->n) != CMP_LT) { result = STS_ERR; } #if CP_RSAPD == BASIC if (pad_basic(eb, &pad_len, in_len, size, RSA_DEC) == STS_OK) { #elif CP_RSAPD == PKCS1 if (pad_pkcs1(eb, &pad_len, in_len, size, RSA_DEC) == STS_OK) { #elif CP_RSAPD == PKCS2 if (pad_pkcs2(eb, &pad_len, in_len, size, RSA_DEC) == STS_OK) { #endif size = size - pad_len; if (size <= *out_len) { memset(out, 0, size); bn_write_bin(out, size, eb); *out_len = size; } else { result = STS_ERR; } } else { result = STS_ERR; } } CATCH_ANY { result = STS_ERR; } FINALLY { bn_free(m); bn_free(eb); } return result; } #endif #if CP_RSA == BASIC || !defined(STRIP) int cp_rsa_sig_basic(uint8_t *sig, int *sig_len, uint8_t *msg, int msg_len, int hash, rsa_t prv) { bn_t m, eb; int size, pad_len, result = STS_OK; uint8_t h[MD_LEN]; if (prv == NULL || msg_len < 0) { return STS_ERR; } pad_len = (!hash ? MD_LEN : msg_len); #if CP_RSAPD == PKCS2 size = bn_bits(prv->n) - 1; size = (size / 8) + (size % 8 > 0); if (pad_len > (size - 2)) { return STS_ERR; } #else size = bn_size_bin(prv->n); if (pad_len > (size - RSA_PAD_LEN)) { return STS_ERR; } #endif bn_null(m); bn_null(eb); TRY { bn_new(m); bn_new(eb); bn_zero(m); bn_zero(eb); int operation = (!hash ? RSA_SIG : RSA_SIG_HASH); #if CP_RSAPD == BASIC if (pad_basic(eb, &pad_len, pad_len, size, operation) == STS_OK) { #elif CP_RSAPD == PKCS1 if (pad_pkcs1(eb, &pad_len, pad_len, size, operation) == STS_OK) { #elif CP_RSAPD == PKCS2 if (pad_pkcs2(eb, &pad_len, pad_len, size, operation) == STS_OK) { #endif if (!hash) { md_map(h, msg, msg_len); bn_read_bin(m, h, MD_LEN); bn_add(eb, eb, m); } else { bn_read_bin(m, msg, msg_len); bn_add(eb, eb, m); } #if CP_RSAPD == PKCS2 pad_pkcs2(eb, &pad_len, bn_bits(prv->n), size, RSA_SIG_FIN); #endif bn_mxp(eb, eb, prv->d, prv->n); size = bn_size_bin(prv->n); if (size <= *sig_len) { memset(sig, 0, size); bn_write_bin(sig, size, eb); *sig_len = size; } else { result = STS_ERR; } } else { result = STS_ERR; } } CATCH_ANY { THROW(ERR_CAUGHT); } FINALLY { bn_free(m); bn_free(eb); } return result; } #endif #if CP_RSA == QUICK || !defined(STRIP) int cp_rsa_sig_quick(uint8_t *sig, int *sig_len, uint8_t *msg, int msg_len, int hash, rsa_t prv) { bn_t m, eb; int pad_len, size, result = STS_OK; uint8_t h[MD_LEN]; if (prv == NULL || msg_len < 0) { return STS_ERR; } pad_len = (!hash ? MD_LEN : msg_len); #if CP_RSAPD == PKCS2 size = bn_bits(prv->n) - 1; size = (size / 8) + (size % 8 > 0); if (pad_len > (size - 2)) { return STS_ERR; } #else size = bn_size_bin(prv->n); if (pad_len > (size - RSA_PAD_LEN)) { return STS_ERR; } #endif bn_null(m); bn_null(eb); TRY { bn_new(m); bn_new(eb); bn_zero(m); bn_zero(eb); int operation = (!hash ? RSA_SIG : RSA_SIG_HASH); #if CP_RSAPD == BASIC if (pad_basic(eb, &pad_len, pad_len, size, operation) == STS_OK) { #elif CP_RSAPD == PKCS1 if (pad_pkcs1(eb, &pad_len, pad_len, size, operation) == STS_OK) { #elif CP_RSAPD == PKCS2 if (pad_pkcs2(eb, &pad_len, pad_len, size, operation) == STS_OK) { #endif if (!hash) { md_map(h, msg, msg_len); bn_read_bin(m, h, MD_LEN); bn_add(eb, eb, m); } else { bn_read_bin(m, msg, msg_len); bn_add(eb, eb, m); } #if CP_RSAPD == PKCS2 pad_pkcs2(eb, &pad_len, bn_bits(prv->n), size, RSA_SIG_FIN); #endif bn_copy(m, eb); /* m1 = c^dP mod p. */ bn_mxp(eb, eb, prv->dp, prv->p); /* m2 = c^dQ mod q. */ bn_mxp(m, m, prv->dq, prv->q); /* m1 = m1 - m2 mod p. */ bn_sub(eb, eb, m); while (bn_sign(eb) == BN_NEG) { bn_add(eb, eb, prv->p); } bn_mod(eb, eb, prv->p); /* m1 = qInv(m1 - m2) mod p. */ bn_mul(eb, eb, prv->qi); bn_mod(eb, eb, prv->p); /* m = m2 + m1 * q. */ bn_mul(eb, eb, prv->q); bn_add(eb, eb, m); bn_mod(eb, eb, prv->n); size = bn_size_bin(prv->n); if (size <= *sig_len) { memset(sig, 0, size); bn_write_bin(sig, size, eb); *sig_len = size; } else { result = STS_ERR; } } else { result = STS_ERR; } } CATCH_ANY { THROW(ERR_CAUGHT); } FINALLY { bn_free(m); bn_free(eb); } return result; } #endif int cp_rsa_ver(uint8_t *sig, int sig_len, uint8_t *msg, int msg_len, int hash, rsa_t pub) { bn_t m, eb; int size, pad_len, result; uint8_t h1[MAX(msg_len, MD_LEN) + 8], h2[MAX(msg_len, MD_LEN)]; /* We suppose that the signature is invalid. */ result = 0; if (pub == NULL || msg_len < 0) { return 0; } pad_len = (!hash ? MD_LEN : msg_len); #if CP_RSAPD == PKCS2 size = bn_bits(pub->n) - 1; if (size % 8 == 0) { size = size / 8 - 1; } else { size = bn_size_bin(pub->n); } if (pad_len > (size - 2)) { return 0; } #else size = bn_size_bin(pub->n); if (pad_len > (size - RSA_PAD_LEN)) { return 0; } #endif bn_null(m); bn_null(eb); TRY { bn_new(m); bn_new(eb); bn_read_bin(eb, sig, sig_len); bn_mxp(eb, eb, pub->e, pub->n); int operation = (!hash ? RSA_VER : RSA_VER_HASH); #if CP_RSAPD == BASIC if (pad_basic(eb, &pad_len, MD_LEN, size, operation) == STS_OK) { #elif CP_RSAPD == PKCS1 if (pad_pkcs1(eb, &pad_len, MD_LEN, size, operation) == STS_OK) { #elif CP_RSAPD == PKCS2 if (pad_pkcs2(eb, &pad_len, bn_bits(pub->n), size, operation) == STS_OK) { #endif #if CP_RSAPD == PKCS2 memset(h1, 0, 8); if (!hash) { md_map(h1 + 8, msg, msg_len); md_map(h2, h1, MD_LEN + 8); memset(h1, 0, MD_LEN); bn_write_bin(h1, size - pad_len, eb); /* Everything went ok, so signature status is changed. */ result = util_cmp_const(h1, h2, MD_LEN); } else { memcpy(h1 + 8, msg, msg_len); md_map(h2, h1, MD_LEN + 8); memset(h1, 0, msg_len); bn_write_bin(h1, size - pad_len, eb); /* Everything went ok, so signature status is changed. */ result = util_cmp_const(h1, h2, msg_len); } #else memset(h1, 0, MAX(msg_len, MD_LEN)); bn_write_bin(h1, size - pad_len, eb); if (!hash) { md_map(h2, msg, msg_len); /* Everything went ok, so signature status is changed. */ result = util_cmp_const(h1, h2, MD_LEN); } else { /* Everything went ok, so signature status is changed. */ result = util_cmp_const(h1, msg, msg_len); } #endif result = (result == CMP_EQ ? 1 : 0); } else { result = 0; } } CATCH_ANY { result = 0; } FINALLY { bn_free(m); bn_free(eb); } return result; }
/** * 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); } }