int cp_rsa_gen_basic(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); } 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); bn_mul(t, prv->p, prv->q); bn_set_2b(pub->e, 16); bn_add_dig(pub->e, pub->e, 1); 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) { bn_add_dig(prv->p, prv->p, 1); bn_add_dig(prv->q, prv->q, 1); } } CATCH_ANY { result = STS_ERR; } FINALLY { bn_free(t); bn_free(r); } return result; }
int inverse(bn_st * inv_in, bn_st * in, bn_st * modulus, int sizeof_mod) { // Compute the inverse of in using an extended Euclidian Algorithm // This cooresponds to the formula out = inv_in*in + useless*modulus // Where, since mod is prime, out should be equal to 1 and 1 = in*inv_in // Otherwise throws an error bn_mod_basic(in,in,modulus); bn_st out, useless; bn_new_size(&out, 2*sizeof_mod+1); bn_new_size(&useless, sizeof_mod); bn_gcd_ext(&out, inv_in, &useless, in, modulus); // Check if out is actually one bn_st is_one; bn_new_size(&is_one, sizeof_mod); bn_set_2b(&is_one, 0); // Set an integer to one if (bn_cmp(&out, &is_one) != CMP_EQ) { error_hdl(-1,"The modulus is not prime, can't calculate the inverse"); return 1; } bn_clean(&is_one); bn_clean(&out); bn_clean(&useless); return 0; }
int cp_phpe_gen(bn_t n, bn_t l, int bits) { bn_t p, q; int result = STS_OK; bn_null(p); bn_null(q); TRY { bn_new(p); bn_new(q); /* Generate primes p and q of equivalent length. */ do { bn_gen_prime(p, bits / 2); bn_gen_prime(q, bits / 2); } while (bn_cmp(p, q) == CMP_EQ); /* Compute n = pq and l = \phi(n). */ bn_mul(n, p, q); bn_sub_dig(p, p, 1); bn_sub_dig(q, q, 1); bn_mul(l, p, q); } CATCH_ANY { result = STS_ERR; } FINALLY { bn_free(p); bn_free(q); } 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); #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; }
int kx_self_test() { const static unsigned char test_a[] = {0x2e, 0x4e, 0x3a, 0x05, 0xd8, 0xff, 0x06, 0x2b, 0x4e, 0x46, 0xda, 0x6e, 0x12, 0x9c, 0xf3, 0x40, 0xb3, 0x07, 0x66, 0x99, 0x8a, 0x0e, 0x09, 0xe3, 0x93, 0x65, 0xa5, 0x52, 0x2d, 0x84, 0x83, 0x04}, test_b[] = {0x6d, 0xd0, 0xae, 0x87, 0x4e, 0x86, 0xa8, 0x11, 0xf8, 0x1b, 0x2e, 0xf5, 0x25, 0x61, 0x50, 0x8d, 0x91, 0x4a, 0x43, 0x53, 0xb1, 0x24, 0x73, 0xe1, 0x18, 0xff, 0x35, 0xdb, 0x2c, 0x77, 0xbd, 0x4e, 0x24, 0x3f, 0xd8, 0x81, 0x82, 0xcd, 0x9e, 0x30, 0xf4, 0xd1, 0x62, 0xb1, 0xe5, 0x57, 0xd5, 0x09, 0x66, 0xfa, 0x9c, 0xdf, 0x97, 0xd4, 0xf6, 0x94, 0xc2, 0x68, 0xb8, 0x91, 0x7d, 0x40, 0xa5, 0x43, 0x96, 0xbe, 0xc4, 0xa9, 0x50, 0x93, 0xbf, 0x13, 0x44, 0x06, 0xaf, 0x3a, 0xb2, 0xf6, 0xf6, 0x22, 0x1f, 0x11, 0x38, 0xae, 0x7e, 0x6c, 0xa1, 0xb4, 0xb9, 0xd1, 0x07, 0x4f, 0x06, 0xf7, 0x09, 0x8d, 0x85, 0x11, 0x38, 0xd4, 0xd4, 0xb8, 0x8f, 0x4d, 0xe1, 0xce, 0x9f, 0x11, 0xb0, 0x49, 0xac, 0x5b, 0x74, 0xef, 0x8b, 0x8e, 0xa4, 0x80, 0xb3, 0xdf, 0xea, 0x85, 0x18, 0x58, 0xc0, 0x3f, 0x79, 0x31, 0x99, 0x96, 0x9f, 0x8e, 0x12, 0x08, 0xb2, 0x32, 0x3f, 0x73, 0xdb, 0x31, 0x4b, 0x19, 0x41, 0x06, 0xb9, 0x98, 0x4b, 0xe5, 0x13, 0xd8, 0xb8, 0xab, 0x4e, 0x1d, 0x0e, 0xff, 0x5a, 0x1a, 0x13, 0xa0, 0x9c, 0xa1, 0x74, 0x59, 0xce, 0x9a, 0x6e, 0x5e, 0xf5, 0xec, 0x2e, 0x3a, 0xcb, 0x76, 0x61, 0x33, 0x36, 0x59, 0x70, 0xa8, 0xcb, 0x86, 0x88, 0x24, 0xff, 0x14, 0x61, 0x8e, 0x0d, 0x2d, 0x58, 0xe2, 0x45, 0xb9, 0x8b, 0x1c, 0xb6, 0x66, 0xa7, 0xa0, 0x7d, 0xb1, 0x45, 0x93, 0x1b, 0xe6, 0xb0, 0x4c, 0xb2, 0xd4, 0xe2, 0x62, 0x0b, 0x26, 0x30, 0x91, 0x40, 0xe9, 0x1e, 0x60, 0x8e, 0xcd, 0xba, 0x19, 0x92, 0x1b, 0xdd, 0xf3, 0xd7, 0xff, 0x7b, 0x12, 0x97, 0x5c, 0x9c, 0xe9, 0x5e, 0x28, 0x82, 0x6d, 0xbc, 0xc9, 0xd8, 0x77, 0x47, 0x94, 0x04, 0xd6, 0xa7, 0x74, 0xcb, 0xc8, 0xfa, 0x78, 0x08, 0xa0}, exp_A[] = {0x69, 0x72, 0x9a, 0x40, 0x98, 0xdc, 0x2c, 0x5c, 0xaa, 0xc5, 0xd8, 0x27, 0x9a, 0xc4, 0xa1, 0x2f, 0x24, 0x66, 0x8f, 0xd0, 0xe4, 0xf1, 0x17, 0xd3, 0x51, 0xa7, 0xb3, 0xcf, 0x00, 0x5c, 0x5e, 0x31, 0x74, 0x19, 0xca, 0xeb, 0xb1, 0x13, 0x1f, 0xd7, 0x58, 0x45, 0x29, 0x79, 0x21, 0x03, 0x88, 0x89, 0xcd, 0x31, 0x4d, 0xff, 0x9f, 0x56, 0xaf, 0xf2, 0x18, 0xcd, 0x81, 0x04, 0x0b, 0x17, 0x75, 0x63, 0x60, 0x1d, 0xfe, 0x58, 0xa0, 0xe0, 0x2b, 0x2f, 0xf3, 0x57, 0x46, 0xcb, 0xee, 0x51, 0x76, 0xcb, 0x4e, 0x69, 0x34, 0xcf, 0xa2, 0x7d, 0x59, 0xcc, 0x12, 0x08, 0x89, 0x76, 0x6b, 0x72, 0xcc, 0xe4, 0x6c, 0x09, 0x79, 0x57, 0xd0, 0x06, 0xe0, 0xf2, 0x21, 0xc3, 0xe2, 0x30, 0x3b, 0x63, 0x41, 0x6f, 0xe5, 0x84, 0xa3, 0x8a, 0x8b, 0x79, 0xb7, 0x92, 0xbc, 0xd5, 0xb6, 0xe7, 0xfe, 0xa2, 0x9a, 0x1d, 0x26, 0x00, 0x52, 0x92, 0x02, 0xb3, 0xdf, 0xf2, 0xf3, 0x41, 0x42, 0xa6, 0x82, 0xd9, 0xad, 0x0a, 0xf8, 0x32, 0x1c, 0x11, 0x14, 0x2c, 0x9d, 0xc3, 0x08, 0x6a, 0x92, 0x59, 0x3a, 0x61, 0x8a, 0xda, 0xc9, 0xbb, 0x46, 0x4f, 0xc8, 0x68, 0x3d, 0xee, 0x6a, 0xac, 0x15, 0xb0, 0x94, 0x64, 0x27, 0x74, 0xc9, 0xe4, 0xa8, 0xf6, 0xb6, 0x0e, 0x6c, 0x26, 0x0b, 0x31, 0x38, 0x9d, 0x40, 0xd7, 0x34, 0x3c, 0xd4, 0xe5, 0xf6, 0xea, 0xa0, 0xcb, 0xec, 0xfa, 0x92, 0x0a, 0x6a, 0x9d, 0x95, 0x52, 0x39, 0x22, 0x29, 0x54, 0x2d, 0x52, 0x43, 0x50, 0xab, 0x94, 0xf9, 0xda, 0x45, 0x6f, 0xa7, 0xd1, 0x64, 0x18, 0x25, 0x3e, 0xb4, 0x0a, 0xda, 0xf6, 0xb7, 0x49, 0x7d, 0xe2, 0x0c, 0x9c, 0x26, 0xed, 0xbb, 0xdc, 0x56, 0xc2, 0x7f, 0x43, 0x2e, 0xad, 0xac, 0x5e, 0x1f, 0xbc, 0x9f, 0xdf, 0x2c, 0xe8, 0x4b, 0xe6}, exp_k[] = {0x25, 0xe1, 0xd6, 0xba, 0x1f, 0x49, 0x90, 0x47, 0x87, 0x87, 0xc8, 0x54, 0xfb, 0xed, 0xe8, 0xff, 0xe9, 0x5e, 0x2d, 0xc5, 0xed, 0xf7, 0x88, 0x36, 0x5f, 0x27, 0x98, 0x32, 0x7e, 0x10, 0x77}; int result = FAILURE; kx_t kx; bn_t A, b, exp; unsigned char k[31]; bn_init(&A); bn_init(&b); bn_init(&exp); if (kx_init_std(&kx, KX_GROUP_2048_256) != SUCCESS) goto fail2; if (bn_from_bytes(&kx.a, test_a, sizeof(test_a)) != SUCCESS) goto fail; if (kx_get_A(&kx, &A) != SUCCESS) goto fail; if (bn_from_bytes(&exp, exp_A, sizeof(exp_A)) != SUCCESS) goto fail; if (bn_cmp(&A, &exp) != 0) goto fail; if (bn_from_bytes(&b, test_b, sizeof(test_b)) != SUCCESS) goto fail; if (kx_set_b(&kx, &b) != SUCCESS) goto fail; if (kx_get_sk(&kx, k, sizeof(k) * 8) != SUCCESS) goto fail; if (memcmp(k, exp_k, sizeof(k)) != 0) goto fail; result = SUCCESS; fail: kx_destroy(&kx); fail2: if (result == FAILURE) fdprintf(STDERR, "KX self-test FAILED!\n"); bn_destroy(&A); bn_destroy(&b); bn_destroy(&exp); 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 igraph_biguint_compare(igraph_biguint_t *left, igraph_biguint_t *right) { /* bn_cmp requires the two numbers to have the same number of limbs, so we do this partially by hand here */ long int size_left=igraph_biguint_size(left); long int size_right=igraph_biguint_size(right); while (size_left > size_right) { if (VECTOR(left->v)[--size_left] > 0) { return +1; } } while (size_right > size_left) { if (VECTOR(right->v)[--size_right] > 0) { return -1; } } return bn_cmp( VECTOR(left->v), VECTOR(right->v), size_right ); }
int element_is_member(element_t e) { LEAVE_IF(e->isInitialized != TRUE, "uninitialized argument."); int result; if(e->type == ZR) { if(bn_cmp(e->bn, e->order) <= CMP_EQ) result = TRUE; else result = FALSE; } else if(e->type == G1) { g1_t r; g1_inits(r); g1_mul(r, e->g1, e->order); if(g1_is_infty(r) == 1) result = TRUE; else result = FALSE; g1_free(r); } else if(e->type == G2) { g2_t r; g2_inits(r); g2_mul(r, e->g2, e->order); if(g2_is_infty(r) == 1) result = TRUE; else result = FALSE; g2_free(r); } else if(e->type == GT) { gt_t r; gt_inits(r); gt_exp(r, e->gt, e->order); if(gt_is_unity(r) == 1) result = TRUE; else result = FALSE; gt_free(r); } else { result = ELEMENT_INVALID_ARG; } return result; }
int bn_sub_mod(bn_st * out, bn_st * in1, bn_st * in2, bn_st * modulus) { if (bn_cmp(in1,in2) == CMP_GT) { // If in1 > in2 we just subtract bn_sub(out,in1,in2); } else { // Otherwise compute mod + in1 - in2 bn_add(out, modulus, in1); bn_sub(out,out,in2); } return 0; }
int element_cmp(element_t a, element_t b) { GroupType type = a->type; LEAVE_IF(a->isInitialized != TRUE || b->isInitialized != TRUE, "uninitialized argument."); EXIT_IF_NOT_SAME(a, b); switch(type) { case ZR: return bn_cmp(a->bn, b->bn); case G1: return g1_cmp(a->g1, b->g1); case G2: return g2_cmp(a->g2, b->g2); case GT: return gt_cmp(a->gt, b->gt); default: break; } return ELEMENT_INVALID_TYPES; }
int bn_factor(bn_t c, const bn_t a) { bn_t t0, t1; int result; unsigned int i, tests; bn_null(t0); bn_null(t1); result = 1; if (bn_is_even(a)) { bn_set_dig(c, 2); return 1; } TRY { bn_new(t0); bn_new(t1); bn_set_dig(t0, 2); #if WORD == 8 tests = 255; #else tests = 65535; #endif for (i = 2; i < tests; i++) { bn_set_dig(t1, i); bn_mxp(t0, t0, t1, a); } bn_sub_dig(t0, t0, 1); bn_gcd(t1, t0, a); if (bn_cmp_dig(t1, 1) == CMP_GT && bn_cmp(t1, a) == CMP_LT) { bn_copy(c, t1); } else { result = 0; } } CATCH_ANY { THROW(ERR_CAUGHT); } FINALLY { bn_free(t0); bn_free(t1); } return result; }
dh_ctxt_t *dh_init(bn_t *p, bn_t *g) { dh_ctxt_t *res; bn_t *t; if (p == NULL || g == NULL) return NULL; assert(p->n == g->n); if ((res = (dh_ctxt_t *)mem_alloc(sizeof(dh_ctxt_t))) == NULL) return NULL; res->g = g; res->p = p; t = bn_copy(bn_alloc(p->n), p); bn_sub_ui(t, t, 2, p); // Check g \in [2, p - 2]. if (bn_cmp_ui(g, 2) < 0 || bn_cmp(g, t) > 0) goto outerr; // Generate c \in [1, p - 2]. res->c = bn_alloc(p->n); bn_rand_range(res->c, 1, p, 2); // C = g^c mod p res->C = bn_alloc(p->n); bn_pow_mod(res->C, res->g, res->c, p); goto outok; outerr:; mem_free(res); res = NULL; outok:; bn_free(t); return res; }
bool ceckey::tweakpublic(const unsigned char vchtweak[32]) { bool ret = true; bn_ctx *ctx = bn_ctx_new(); bn_ctx_start(ctx); bignum *bntweak = bn_ctx_get(ctx); bignum *bnorder = bn_ctx_get(ctx); bignum *bnone = bn_ctx_get(ctx); const ec_group *group = ec_key_get0_group(pkey); ec_group_get_order(group, bnorder, ctx); // what a grossly inefficient way to get the (constant) group order... bn_bin2bn(vchtweak, 32, bntweak); if (bn_cmp(bntweak, bnorder) >= 0) ret = false; // extremely unlikely ec_point *point = ec_point_dup(ec_key_get0_public_key(pkey), group); bn_one(bnone); ec_point_mul(group, point, bntweak, point, bnone, ctx); if (ec_point_is_at_infinity(group, point)) ret = false; // ridiculously unlikely ec_key_set_public_key(pkey, point); ec_point_free(point); bn_ctx_end(ctx); bn_ctx_free(ctx); return ret; }
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_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; }
int bn_is_prime_rabin(const bn_t a) { bn_t t, n1, y, r; int i, s, j, result, b, tests = 0; tests = 0; result = 1; bn_null(t); bn_null(n1); bn_null(y); bn_null(r); if (bn_cmp_dig(a, 1) == CMP_EQ) { return 0; } TRY { /* * These values are taken from Table 4.4 inside Handbook of Applied * Cryptography. */ b = bn_bits(a); if (b >= 1300) { tests = 2; } else if (b >= 850) { tests = 3; } else if (b >= 650) { tests = 4; } else if (b >= 550) { tests = 5; } else if (b >= 450) { tests = 6; } else if (b >= 400) { tests = 7; } else if (b >= 350) { tests = 8; } else if (b >= 300) { tests = 9; } else if (b >= 250) { tests = 12; } else if (b >= 200) { tests = 15; } else if (b >= 150) { tests = 18; } else { tests = 27; } bn_new(t); bn_new(n1); bn_new(y); bn_new(r); /* r = (n - 1)/2^s. */ bn_sub_dig(n1, a, 1); s = 0; while (bn_is_even(n1)) { s++; bn_rsh(n1, n1, 1); } bn_lsh(r, n1, s); for (i = 0; i < tests; i++) { /* Fix the basis as the first few primes. */ bn_set_dig(t, primes[i]); /* y = b^r mod a. */ #if BN_MOD != PMERS bn_mxp(y, t, r, a); #else bn_exp(y, t, r, a); #endif if (bn_cmp_dig(y, 1) != CMP_EQ && bn_cmp(y, n1) != CMP_EQ) { j = 1; while ((j <= (s - 1)) && bn_cmp(y, n1) != CMP_EQ) { bn_sqr(y, y); bn_mod(y, y, a); /* If y == 1 then composite. */ if (bn_cmp_dig(y, 1) == CMP_EQ) { result = 0; break; } ++j; } /* If y != n1 then composite. */ if (bn_cmp(y, n1) != CMP_EQ) { result = 0; break; } } } } CATCH_ANY { result = 0; THROW(ERR_CAUGHT); } FINALLY { bn_free(r); bn_free(y); bn_free(n1); bn_free(t); } return result; }
int bn_is_prime_solov(const bn_t a) { bn_t t0, t1, t2; int i, result; bn_null(t0); bn_null(t1); bn_null(t2); result = 1; TRY { bn_new(t0); bn_new(t1); bn_new(t2); for (i = 0; i < 100; i++) { /* Generate t0, 2 <= t0, <= a - 2. */ do { bn_rand(t0, BN_POS, bn_bits(a)); bn_mod(t0, t0, a); } while (bn_cmp_dig(t0, 2) == CMP_LT); /* t2 = a - 1. */ bn_copy(t2, a); bn_sub_dig(t2, t2, 1); /* t1 = (a - 1)/2. */ bn_rsh(t1, t2, 1); /* t1 = t0^(a - 1)/2 mod a. */ #if BN_MOD != PMERS bn_mxp(t1, t0, t1, a); #else bn_exp(t1, t0, t1, a); #endif /* If t1 != 1 and t1 != n - 1 return 0 */ if (bn_cmp_dig(t1, 1) != CMP_EQ && bn_cmp(t1, t2) != CMP_EQ) { result = 0; break; } /* t2 = (t0|a). */ bn_smb_jac(t2, t0, a); if (bn_sign(t2) == BN_NEG) { bn_add(t2, t2, a); } /* If t1 != t2 (mod a) return 0. */ bn_mod(t1, t1, a); bn_mod(t2, t2, a); if (bn_cmp(t1, t2) != CMP_EQ) { result = 0; break; } } } CATCH_ANY { result = 0; THROW(ERR_CAUGHT); } FINALLY { bn_free(t0); bn_free(t1); bn_free(t2); } return result; }