void fp_prime_set_pmers(const int *f, int len) { bn_t p, t; bn_null(p); bn_null(t); TRY { bn_new(p); bn_new(t); if (len >= MAX_TERMS) { THROW(ERR_NO_VALID); } bn_set_2b(p, f[len - 1]); for (int i = len - 2; i > 0; i--) { if (f[i] > 0) { bn_set_2b(t, f[i]); bn_add(p, p, t); } else { bn_set_2b(t, -f[i]); bn_sub(p, p, t); } } if (f[0] > 0) { bn_add_dig(p, p, f[0]); } else { bn_sub_dig(p, p, -f[0]); } #if FP_RDC == QUICK || !defined(STRIP) ctx_t *ctx = core_get(); for (int i = 0; i < len; i++) { ctx->sps[i] = f[i]; } ctx->sps[len] = 0; ctx->sps_len = len; #endif /* FP_RDC == QUICK */ fp_prime_set(p); } CATCH_ANY { THROW(ERR_CAUGHT); } FINALLY { bn_free(p); bn_free(t); } }
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_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; }
void fp_param_get_var(bn_t x) { bn_t a; bn_null(a); TRY { bn_new(a); switch (fp_param_get()) { case BN_158: /* x = 4000000031. */ bn_set_2b(x, 38); bn_add_dig(x, x, 0x31); break; case BN_254: /* x = -4080000000000001. */ bn_set_2b(x, 62); bn_set_2b(a, 55); bn_add(x, x, a); bn_add_dig(x, x, 1); bn_neg(x, x); break; case BN_256: /* x = -600000000000219B. */ bn_set_2b(x, 62); bn_set_2b(a, 61); bn_add(x, x, a); bn_set_dig(a, 0x21); bn_lsh(a, a, 8); bn_add(x, x, a); bn_add_dig(x, x, 0x9B); bn_neg(x, x); break; case B24_477: /* x = -2^48 + 2^45 + 2^31 - 2^7. */ bn_set_2b(x, 48); bn_set_2b(a, 45); bn_sub(x, x, a); bn_set_2b(a, 31); bn_sub(x, x, a); bn_set_2b(a, 7); bn_add(x, x, a); bn_neg(x, x); break; case KSS_508: /* x = -(2^64 + 2^51 - 2^46 - 2^12). */ bn_set_2b(x, 64); bn_set_2b(a, 51); bn_add(x, x, a); bn_set_2b(a, 46); bn_sub(x, x, a); bn_set_2b(a, 12); bn_sub(x, x, a); bn_neg(x, x); break; case BN_638: /* x = 2^158 - 2^128 - 2^68 + 1. */ bn_set_2b(x, 158); bn_set_2b(a, 128); bn_sub(x, x, a); bn_set_2b(a, 68); bn_sub(x, x, a); bn_add_dig(x, x, 1); break; case B12_638: /* x = -2^107 + 2^105 + 2^93 + 2^5. */ bn_set_2b(x, 107); bn_set_2b(a, 105); bn_sub(x, x, a); bn_set_2b(a, 93); bn_sub(x, x, a); bn_set_2b(a, 5); bn_sub(x, x, a); bn_neg(x, x); break; case SS_1536: /* x = 2^255 + 2^41 + 1. */ bn_set_2b(x, 255); bn_set_2b(a, 41); bn_add(x, x, a); bn_add_dig(x, x, 1); break; default: THROW(ERR_NO_VALID); break; } } CATCH_ANY { THROW(ERR_CAUGHT); } FINALLY { bn_free(a); } }