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; }
cbor_item_t* relic_bn2cbor(const bn_t n) { int size = bn_size_bin(n); uint8_t* data = (uint8_t*)malloc(size); cbor_item_t* ret = NULL; bn_write_bin(data, size, n); ret = cbor_build_bytestring(data, size); free(data); return ret; }
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_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; }
int cp_bdpe_enc(uint8_t *out, int *out_len, dig_t in, bdpe_t pub) { bn_t m, u; int size, result = STS_OK; bn_null(m); bn_null(u); size = bn_size_bin(pub->n); if (in > pub->t) { return STS_ERR; } TRY { bn_new(m); bn_new(u); bn_set_dig(m, in); do { bn_rand(u, BN_POS, bn_bits(pub->n)); bn_mod(u, u, pub->n); } while (bn_is_zero(u)); bn_mxp(m, pub->y, m, pub->n); bn_mxp_dig(u, u, pub->t, pub->n); bn_mul(m, m, u); bn_mod(m, m, pub->n); if (size <= *out_len) { *out_len = size; memset(out, 0, *out_len); bn_write_bin(out, size, m); } else { result = STS_ERR; } } CATCH_ANY { result = STS_ERR; } FINALLY { bn_free(m); bn_free(u); } return result; }
string Element_ToBytes(Element &e) { int data_len; string encoded= ""; if(e.type == Str_t) { return string(e.strPtr); } else if(e.type == ZR_t) { data_len = compute_length(e.type); uint8_t data[data_len+1]; memset(data, 0, data_len); bn_write_bin(data, data_len, e.zr.z); string t((char *) data, data_len); encoded = _base64_encode(reinterpret_cast<const unsigned char*>(t.c_str()), t.size()); memset(data, 0, data_len); } else if(e.type == G1_t) { data_len = compute_length(e.type); uint8_t data[data_len+1]; memset(data, 0, data_len); g1_write_bin(e.g1.g, data, data_len); string t((char *) data, data_len); encoded = _base64_encode(reinterpret_cast<const unsigned char*>(t.c_str()), t.size()); memset(data, 0, data_len); } else if(e.type == G2_t) { data_len = compute_length(e.type); uint8_t data[data_len+1]; memset(data, 0, data_len); g2_write_bin(e.g2.g, data, data_len); string t((char *) data, data_len); encoded = _base64_encode(reinterpret_cast<const unsigned char*>(t.c_str()), t.size()); memset(data, 0, data_len); } else if(e.type == GT_t) { data_len = compute_length(e.type); uint8_t data[data_len+1]; memset(data, 0, data_len); gt_write_bin(e.gt.g, data, data_len); // x1-6 && y1-6 string t((char *) data, data_len); encoded = _base64_encode(reinterpret_cast<const unsigned char*>(t.c_str()), t.size()); memset(data, 0, data_len); } return encoded; }
void fp_write_bin(unsigned char *str, int len, fp_t a) { bn_t t; bn_null(t); TRY { bn_new(t); fp_prime_back(t, a); bn_write_bin(str, len, t); } CATCH_ANY { THROW(ERR_CAUGHT); } FINALLY { bn_free(t); } }
int cp_ecdh_key(uint8_t *key, int key_len, bn_t d, ec_t q) { ec_t p; bn_t x, h; int l, result = STS_OK; uint8_t _x[FC_BYTES]; ec_null(p); bn_null(x); bn_null(h); TRY { ec_new(p); bn_new(x); bn_new(h); ec_curve_get_cof(h); if (bn_bits(h) < BN_DIGIT) { ec_mul_dig(p, q, h->dp[0]); } else { ec_mul(p, q, h); } ec_mul(p, p, d); if (ec_is_infty(p)) { result = STS_ERR; } ec_get_x(x, p); l = bn_size_bin(x); bn_write_bin(_x, l, x); md_kdf2(key, key_len, _x, l); } CATCH_ANY { THROW(ERR_CAUGHT); } FINALLY { ec_free(p); bn_free(x); bn_free(h); } return result; }
status_t element_to_bytes(unsigned char *data, int data_len, element_t e) { LEAVE_IF(e->isInitialized != TRUE, "uninitialized argument."); GroupType type = e->type; if(type == ZR) { bn_write_bin(data, data_len, e->bn); } else if(type == G1) { return g1_write_bin(e->g1, data, data_len); // x & y } else if(type == G2) { return g2_write_bin(e->g2, data, data_len); // x1, y1 & x2, y2 } else if(type == GT) { return gt_write_bin(e->gt, data, data_len); // x1-6 && y1-6 } else { return ELEMENT_INVALID_TYPES; } return ELEMENT_OK; }
void fp_write_bin(uint8_t *bin, int len, const fp_t a) { bn_t t; bn_null(t); if (len != RLC_FP_BYTES) { THROW(ERR_NO_BUFFER); } TRY { bn_new(t); fp_prime_back(t, a); bn_write_bin(bin, len, t); } CATCH_ANY { THROW(ERR_CAUGHT); } FINALLY { bn_free(t); } }
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; }
/** * 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_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; }
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); } }