static E_GMP_RSA_CTX *e_gmp_get_rsa(RSA *rsa) { E_GMP_RSA_CTX *hptr = RSA_get_ex_data(rsa, hndidx_rsa); if (hptr) return hptr; hptr = OPENSSL_malloc(sizeof(*hptr)); if (!hptr) return NULL; /* * These inits could probably be replaced by more intelligent mpz_init2() * versions, to reduce malloc-thrashing. */ mpz_init(hptr->n); mpz_init(hptr->d); mpz_init(hptr->e); mpz_init(hptr->p); mpz_init(hptr->q); mpz_init(hptr->dmp1); mpz_init(hptr->dmq1); mpz_init(hptr->iqmp); mpz_init(hptr->r0); mpz_init(hptr->r1); mpz_init(hptr->I0); mpz_init(hptr->m1); if (!bn2gmp(rsa->n, hptr->n) || !bn2gmp(rsa->e, hptr->e)) goto err; if (!rsa->p || !rsa->q || !rsa->d || !rsa->dmp1 || !rsa->dmq1 || !rsa->iqmp) { hptr->public_only = 1; return hptr; } if (!bn2gmp(rsa->d, hptr->d) || !bn2gmp(rsa->p, hptr->p) || !bn2gmp(rsa->q, hptr->q) || !bn2gmp(rsa->dmp1, hptr->dmp1) || !bn2gmp(rsa->dmq1, hptr->dmq1) || !bn2gmp(rsa->iqmp, hptr->iqmp)) goto err; hptr->public_only = 0; RSA_set_ex_data(rsa, hndidx_rsa, hptr); return hptr; err: mpz_clear(hptr->n); mpz_clear(hptr->d); mpz_clear(hptr->e); mpz_clear(hptr->p); mpz_clear(hptr->q); mpz_clear(hptr->dmp1); mpz_clear(hptr->dmq1); mpz_clear(hptr->iqmp); mpz_clear(hptr->r0); mpz_clear(hptr->r1); mpz_clear(hptr->I0); mpz_clear(hptr->m1); OPENSSL_free(hptr); return NULL; }
static int e_gmp_rsa_mod_exp(BIGNUM *r, const BIGNUM *I, RSA *rsa, BN_CTX *ctx) { E_GMP_RSA_CTX *hptr; int to_return = 0; hptr = e_gmp_get_rsa(rsa); if(!hptr) { GMPerr(GMP_F_E_GMP_RSA_MOD_EXP, GMP_R_KEY_CONTEXT_ERROR); return 0; } if(hptr->public_only) { GMPerr(GMP_F_E_GMP_RSA_MOD_EXP, GMP_R_MISSING_KEY_COMPONENTS); return 0; } /* ugh!!! */ if(!bn2gmp(I, hptr->I0)) return 0; /* This is basically the CRT logic in crypto/rsa/rsa_eay.c reworded into * GMP-speak. It may be that GMP's API facilitates cleaner formulations * of this stuff, eg. better handling of negatives, or functions that * combine operations. */ mpz_mod(hptr->r1, hptr->I0, hptr->q); mpz_powm(hptr->m1, hptr->r1, hptr->dmq1, hptr->q); mpz_mod(hptr->r1, hptr->I0, hptr->p); mpz_powm(hptr->r0, hptr->r1, hptr->dmp1, hptr->p); mpz_sub(hptr->r0, hptr->r0, hptr->m1); if(mpz_sgn(hptr->r0) < 0) mpz_add(hptr->r0, hptr->r0, hptr->p); mpz_mul(hptr->r1, hptr->r0, hptr->iqmp); mpz_mod(hptr->r0, hptr->r1, hptr->p); if(mpz_sgn(hptr->r0) < 0) mpz_add(hptr->r0, hptr->r0, hptr->p); mpz_mul(hptr->r1, hptr->r0, hptr->q); mpz_add(hptr->r0, hptr->r1, hptr->m1); /* ugh!!! */ if(gmp2bn(hptr->r0, r)) to_return = 1; return 1; }