Example #1
0
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;
	}