int cp_ecss_sig(bn_t e, bn_t s, uint8_t *msg, int len, bn_t d) { bn_t n, k, x, r; ec_t p; uint8_t hash[MD_LEN]; uint8_t m[len + FC_BYTES]; int result = STS_OK; bn_null(n); bn_null(k); bn_null(x); bn_null(r); ec_null(p); TRY { bn_new(n); bn_new(k); bn_new(x); bn_new(r); ec_new(p); ec_curve_get_ord(n); do { bn_rand_mod(k, n); ec_mul_gen(p, k); ec_get_x(x, p); bn_mod(r, x, n); } while (bn_is_zero(r)); memcpy(m, msg, len); bn_write_bin(m + len, FC_BYTES, r); md_map(hash, m, len + FC_BYTES); if (8 * MD_LEN > bn_bits(n)) { len = CEIL(bn_bits(n), 8); bn_read_bin(e, hash, len); bn_rsh(e, e, 8 * MD_LEN - bn_bits(n)); } else { bn_read_bin(e, hash, MD_LEN); } bn_mod(e, e, n); bn_mul(s, d, e); bn_mod(s, s, n); bn_sub(s, n, s); bn_add(s, s, k); bn_mod(s, s, n); } CATCH_ANY { result = STS_ERR; } FINALLY { bn_free(n); bn_free(k); bn_free(x); bn_free(r); ec_free(p); } return result; }
int cp_bbs_ver(g1_t s, uint8_t *msg, int len, int hash, g2_t q, gt_t z) { bn_t m, n; g2_t g; gt_t e; uint8_t h[MD_LEN]; int result = 0; bn_null(m); bn_null(n); g2_null(g); gt_null(e); TRY { bn_new(m); bn_new(n); g2_new(g); gt_new(e); g2_get_ord(n); /* m = H(msg). */ if (hash) { bn_read_bin(m, msg, len); } else { md_map(h, msg, len); bn_read_bin(m, h, MD_LEN); } bn_mod(m, m, n); g2_mul_gen(g, m); g2_add(g, g, q); g2_norm(g, g); pc_map(e, s, g); if (gt_cmp(e, z) == CMP_EQ) { result = 1; } } CATCH_ANY { THROW(ERR_CAUGHT); } FINALLY { bn_free(m); bn_free(n); g2_free(g); gt_free(e); } return result; }
int cp_pss_sig(g1_t a, g1_t b, uint8_t *msg, int len, bn_t r, bn_t s) { bn_t m, n; int result = RLC_OK; bn_null(m); bn_null(n); TRY { bn_new(m); bn_new(n); g1_get_ord(n); bn_read_bin(m, msg, len); bn_mul(m, m, s); bn_mod(m, m, n); bn_add(m, m, r); bn_mod(m, m, n); g1_rand(a); g1_mul(b, a, m); } CATCH_ANY { result = RLC_ERR; } FINALLY { bn_free(m); bn_free(n); } return result; }
void ep2_map(ep2_t p, uint8_t *msg, int len) { bn_t x; fp2_t t0; uint8_t digest[MD_LEN]; bn_null(x); fp2_null(t0); TRY { bn_new(x); fp2_new(t0); md_map(digest, msg, len); bn_read_bin(x, digest, MIN(FP_BYTES, MD_LEN)); fp_prime_conv(p->x[0], x); fp_zero(p->x[1]); fp_set_dig(p->z[0], 1); fp_zero(p->z[1]); while (1) { ep2_rhs(t0, p); if (fp2_srt(p->y, t0)) { p->norm = 1; break; } fp_add_dig(p->x[0], p->x[0], 1); } switch (ep_param_get()) { case BN_P158: case BN_P254: case BN_P256: case BN_P638: ep2_mul_cof_bn(p, p); break; case B12_P638: ep2_mul_cof_b12(p, p); break; default: /* Now, multiply by cofactor to get the correct group. */ ep2_curve_get_cof(x); if (bn_bits(x) < BN_DIGIT) { ep2_mul_dig(p, p, x->dp[0]); } else { ep2_mul(p, p, x); } break; } } CATCH_ANY { THROW(ERR_CAUGHT); } FINALLY { bn_free(x); fp2_free(t0); } }
int Element_FromBytes(Element & e, int type, unsigned char *data) { string d = ""; if(is_base64((unsigned char) data[0])) { string b64_encoded((char *) data); d = _base64_decode(b64_encoded); } else { return ELEMENT_INVALID_ARG; } if(type == ZR_t) { bn_read_bin(e.zr.z, (unsigned char *) d.c_str(), d.size()); } else if(type == G1_t) { return g1_read_bin(e.g1.g, (unsigned char *) d.c_str(), d.size()); // x & y } else if(type == G2_t) { return g2_read_bin(e.g2.g, (unsigned char *) d.c_str(), d.size()); // x1, y1 & x2, y2 } else if(type == GT_t) { return gt_read_bin(e.gt.g, (unsigned char *) d.c_str(), d.size()); // x1-6 && y1-6 } return ELEMENT_INVALID_ARG; }
status_t element_from_hash(element_t e, unsigned char *data, int len) { LEAVE_IF(e->isInitialized == FALSE, "uninitialized argument."); GroupType type = e->type; status_t result = ELEMENT_OK; int digest_len = SHA_LEN; unsigned char digest[digest_len + 1]; memset(digest, 0, digest_len); SHA_FUNC(digest, data, len); #ifdef DEBUG printf("%s: digest: ", __FUNCTION__); print_as_hex(digest, digest_len); #endif switch(type) { case ZR: bn_read_bin(e->bn, digest, digest_len); if(bn_cmp(e->bn, e->order) == CMP_GT) bn_mod(e->bn, e->bn, e->order); // bn_print(e->bn); break; case G1: g1_map(e->g1, digest, digest_len); break; case G2: g2_map(e->g2, digest, digest_len); break; default: result = ELEMENT_INVALID_TYPES; break; } return result; }
void fp_read_bin(fp_t a, const unsigned char *str, int len) { bn_t t; bn_null(t); TRY { bn_new(t); bn_read_bin(t, (unsigned char *) str, len); if (bn_is_zero(t)) { fp_zero(a); } else { if (t->used == 1) { fp_prime_conv_dig(a, t->dp[0]); } else { fp_prime_conv(a, t); } } } CATCH_ANY { THROW(ERR_CAUGHT); } FINALLY { bn_free(t); } }
void fp_read_bin(fp_t a, const uint8_t *bin, int len) { bn_t t; bn_null(t); if (len != RLC_FP_BYTES) { THROW(ERR_NO_BUFFER); } TRY { bn_new(t); bn_read_bin(t, bin, len); if (bn_is_zero(t)) { fp_zero(a); } else { if (t->used == 1) { fp_prime_conv_dig(a, t->dp[0]); } else { fp_prime_conv(a, t); } } } CATCH_ANY { THROW(ERR_CAUGHT); } FINALLY { bn_free(t); } }
int cp_pss_ver(g1_t a, g1_t b, uint8_t *msg, int len, g2_t g, g2_t x, g2_t y) { g1_t p[2]; g2_t r[2]; gt_t e; bn_t m, n; int result = 1; g1_null(p[0]); g1_null(p[1]); g2_null(r[0]); g2_null(r[1]); gt_null(e); bn_null(m); bn_null(n); TRY { g1_new(p[0]); g1_new(p[1]); g2_new(r[0]); g2_new(r[1]); gt_new(e); bn_new(m); bn_new(n); if (g1_is_infty(a)) { result = 0; } g1_copy(p[0], a); g1_copy(p[1], b); g2_copy(r[1], g); g2_neg(r[1], r[1]); g1_get_ord(n); bn_read_bin(m, msg, len); bn_mod(m, m, n); g2_mul(r[0], y, m); g2_add(r[0], r[0], x); g2_norm(r[0], r[0]); pc_map_sim(e, p, r, 2); if (!gt_is_unity(e)) { result = 0; } } CATCH_ANY { THROW(ERR_CAUGHT); } FINALLY { g1_free(p[0]); g1_free(p[1]); g2_free(r[0]); g2_free(r[1]); gt_free(e); bn_free(m); bn_free(n); } return result; }
int cp_bbs_sig(g1_t s, uint8_t *msg, int len, int hash, bn_t d) { bn_t m, n, r; uint8_t h[MD_LEN]; int result = STS_OK; bn_null(m); bn_null(n); bn_null(r); TRY { bn_new(m); bn_new(n); bn_new(r); g1_get_ord(n); /* m = H(msg). */ if (hash) { bn_read_bin(m, msg, len); } else { md_map(h, msg, len); bn_read_bin(m, h, MD_LEN); } bn_mod(m, m, n); /* m = 1/(m + d) mod n. */ bn_add(m, m, d); bn_gcd_ext(r, m, NULL, m, n); if (bn_sign(m) == BN_NEG) { bn_add(m, m, n); } /* s = 1/(m+d) * g1. */ g1_mul_gen(s, m); } CATCH_ANY { result = STS_ERR; } FINALLY { bn_free(m); bn_free(n); bn_free(r); } return result; }
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; }
int cp_phpe_dec(uint8_t *out, int out_len, uint8_t *in, int in_len, bn_t n, bn_t l) { bn_t c, u, s; int size, result = STS_OK; size = bn_size_bin(n); if (in_len < 0 || in_len != 2 * size) { return STS_ERR; } bn_null(c); bn_null(u); bn_null(s); TRY { bn_new(c); bn_new(u); bn_new(s); /* Compute (c^l mod n^2) * u mod n. */ bn_sqr(s, n); bn_read_bin(c, in, in_len); bn_mxp(c, c, l, s); bn_sub_dig(c, c, 1); bn_div(c, c, n); bn_gcd_ext(s, u, NULL, l, n); if (bn_sign(u) == BN_NEG) { bn_add(u, u, n); } bn_mul(c, c, u); bn_mod(c, c, n); size = bn_size_bin(c); if (size <= out_len) { memset(out, 0, out_len); bn_write_bin(out + (out_len - size), size, c); } else { result = STS_ERR; } } CATCH_ANY { result = STS_ERR; } FINALLY { bn_free(c); bn_free(u); bn_free(s); } return result; }
status_t element_from_bytes(element_t e, unsigned char *data, int data_len) { LEAVE_IF(e->isInitialized != TRUE, "uninitialized argument."); GroupType type = e->type; if(type == ZR) { bn_read_bin(e->bn, data, data_len); } else if(type == G1) { return g1_read_bin(e->g1, data, data_len); // x & y } else if(type == G2) { return g2_read_bin(e->g2, data, data_len); // x1, y1 & x2, y2 } else if(type == GT) { return gt_read_bin(e->gt, data, data_len); // x1-6 && y1-6 } else { return ELEMENT_INVALID_TYPES; } return ELEMENT_OK; }
int cp_psb_sig(g1_t a, g1_t b, uint8_t *msgs[], int lens[], bn_t r, bn_t s[], int l) { bn_t m, n, t; int i, result = RLC_OK; bn_null(m); bn_null(n); bn_null(t); TRY { bn_new(m); bn_new(n); bn_new(t); /* Choose random a in G1. */ g1_rand(a); /* Compute b = a^x+\sum y_im_i. */ g1_get_ord(n); bn_copy(t, r); for (i = 0; i < l; i++) { bn_read_bin(m, msgs[i], lens[i]); bn_mod(m, m, n); bn_mul(m, m, s[i]); bn_mod(m, m, n); bn_add(t, t, m); bn_mod(t, t, n); } g1_mul(b, a, t); } CATCH_ANY { result = RLC_ERR; } FINALLY { bn_free(m); bn_free(n); bn_free(t); } return result; }
status_t element_from_hash(element_t e, unsigned char *data, int len) { LEAVE_IF(e->isInitialized == FALSE, "uninitialized argument."); GroupType type = e->type; status_t result = ELEMENT_OK; int digest_len = SHA_LEN; unsigned char digest[digest_len + 1]; memset(digest, 0, digest_len); SHA_FUNC(digest, data, len); switch(type) { case ZR: bn_read_bin(e->bn, digest, digest_len); break; case G1: g1_map(e->g1, digest, digest_len); break; case G2: g2_map(e->g2, digest, digest_len); break; default: result = ELEMENT_INVALID_TYPES; break; } 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 cp_ecss_sig(bn_t e, bn_t s, unsigned char *msg, int len, bn_t d) { bn_t n, k, x, r; ec_t p; unsigned char hash[MD_LEN]; unsigned char m[len + EC_BYTES]; bn_null(n); bn_null(k); bn_null(x); bn_null(r); ec_null(p); TRY { bn_new(n); bn_new(k); bn_new(x); bn_new(r); ec_new(p); ec_curve_get_ord(n); do { do { bn_rand(k, BN_POS, bn_bits(n)); bn_mod(k, k, n); } while (bn_is_zero(k)); ec_mul_gen(p, k); ec_get_x(x, p); bn_mod(r, x, n); } while (bn_is_zero(r)); memcpy(m, msg, len); bn_write_bin(m + len, EC_BYTES, r); md_map(hash, m, len + EC_BYTES); if (8 * MD_LEN > bn_bits(n)) { len = CEIL(bn_bits(n), 8); bn_read_bin(e, hash, len); bn_rsh(e, e, 8 * MD_LEN - bn_bits(n)); } else { bn_read_bin(e, hash, MD_LEN); } bn_mod(e, e, n); bn_mul(s, d, e); bn_mod(s, s, n); bn_sub(s, n, s); bn_add(s, s, k); bn_mod(s, s, n); } CATCH_ANY { THROW(ERR_CAUGHT); } FINALLY { bn_free(n); bn_free(k); bn_free(x); bn_free(r); ec_free(p); } }
int cp_ecss_ver(bn_t e, bn_t s, uint8_t *msg, int len, ec_t q) { bn_t n, ev, rv; ec_t p; uint8_t hash[MD_LEN]; uint8_t m[len + FC_BYTES]; int result = 0; bn_null(n); bn_null(ev); bn_null(rv); ec_null(p); TRY { bn_new(n); bn_new(ev); bn_new(rv); ec_new(p); ec_curve_get_ord(n); if (bn_sign(e) == BN_POS && bn_sign(s) == BN_POS && !bn_is_zero(s)) { if (bn_cmp(e, n) == CMP_LT && bn_cmp(s, n) == CMP_LT) { ec_mul_sim_gen(p, s, q, e); ec_get_x(rv, p); bn_mod(rv, rv, n); memcpy(m, msg, len); bn_write_bin(m + len, FC_BYTES, rv); md_map(hash, m, len + FC_BYTES); if (8 * MD_LEN > bn_bits(n)) { len = CEIL(bn_bits(n), 8); bn_read_bin(ev, hash, len); bn_rsh(ev, ev, 8 * MD_LEN - bn_bits(n)); } else { bn_read_bin(ev, hash, MD_LEN); } bn_mod(ev, ev, n); result = dv_cmp_const(ev->dp, e->dp, MIN(ev->used, e->used)); result = (result == CMP_NE ? 0 : 1); if (ev->used != e->used) { result = 0; } } } } CATCH_ANY { THROW(ERR_CAUGHT); } FINALLY { bn_free(n); bn_free(ev); bn_free(rv); ec_free(p); } 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; }
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; }
int cp_psb_ver(g1_t a, g1_t b, uint8_t *msgs[], int lens[], g2_t g, g2_t x, g2_t y[], int l) { g1_t p[2]; g2_t q[2]; gt_t e; bn_t m, n; int i, result = 1; g1_null(p[0]); g1_null(p[1]); g2_null(q[0]); g2_null(q[1]); gt_null(e); bn_null(m); bn_null(n); TRY { g1_new(p[0]); g1_new(p[1]); g2_new(q[0]); g2_new(q[1]); gt_new(e); bn_new(m); bn_new(n); if (g1_is_infty(a)) { result = 0; } /* Check that e(a, x \prod y_i^m_i) = e(b, g). */ g1_copy(p[0], a); g1_copy(p[1], b); g2_copy(q[0], x); g1_get_ord(n); for (i = 0; i < l; i++) { bn_read_bin(m, msgs[i], lens[i]); bn_mod(m, m, n); g2_mul(q[1], y[i], m); g2_add(q[0], q[0], q[1]); } g2_norm(q[0], q[0]); g2_copy(q[1], g); g2_neg(q[1], q[1]); pc_map_sim(e, p, q, 2); if (!gt_is_unity(e)) { result = 0; } } CATCH_ANY { THROW(ERR_CAUGHT); } FINALLY { g1_free(p[0]); g1_free(p[1]); g2_free(q[0]); g2_free(q[1]); gt_free(e); bn_free(m); bn_free(n); } return result; }