Пример #1
0
/* Construct a generic GFMethod for arithmetic over prime fields with
 * irreducible irr. */
GFMethod *
GFMethod_consGFp(const mp_int *irr)
{
    mp_err res = MP_OKAY;
    GFMethod *meth = NULL;

    meth = GFMethod_new();
    if (meth == NULL)
        return NULL;

    MP_CHECKOK(mp_copy(irr, &meth->irr));
    meth->irr_arr[0] = mpl_significant_bits(irr);
    meth->irr_arr[1] = meth->irr_arr[2] = meth->irr_arr[3] =
        meth->irr_arr[4] = 0;
    switch (MP_USED(&meth->irr)) {
        /* maybe we need 1 and 2 words here as well?*/
        case 3:
            meth->field_add = &ec_GFp_add_3;
            meth->field_sub = &ec_GFp_sub_3;
            break;
        case 4:
            meth->field_add = &ec_GFp_add_4;
            meth->field_sub = &ec_GFp_sub_4;
            break;
        case 5:
            meth->field_add = &ec_GFp_add_5;
            meth->field_sub = &ec_GFp_sub_5;
            break;
        case 6:
            meth->field_add = &ec_GFp_add_6;
            meth->field_sub = &ec_GFp_sub_6;
            break;
        default:
            meth->field_add = &ec_GFp_add;
            meth->field_sub = &ec_GFp_sub;
    }
    meth->field_neg = &ec_GFp_neg;
    meth->field_mod = &ec_GFp_mod;
    meth->field_mul = &ec_GFp_mul;
    meth->field_sqr = &ec_GFp_sqr;
    meth->field_div = &ec_GFp_div;
    meth->field_enc = NULL;
    meth->field_dec = NULL;
    meth->extra1 = NULL;
    meth->extra2 = NULL;
    meth->extra_free = NULL;

CLEANUP:
    if (res != MP_OKAY) {
        GFMethod_free(meth);
        return NULL;
    }
    return meth;
}
Пример #2
0
/* Tests the time required for a point multiplication */
mp_err
testPointMulTime(ECGroup *ecgroup)
{
	mp_err res = MP_OKAY;
	mp_int rx, ry, n;
	int size;

	MP_DIGITS(&rx) = 0;
	MP_DIGITS(&ry) = 0;
	MP_DIGITS(&n) = 0;

	MP_CHECKOK(mp_init(&rx));
	MP_CHECKOK(mp_init(&ry));
	MP_CHECKOK(mp_init(&n));

	/* compute random scalar */
	size = mpl_significant_bits(&ecgroup->meth->irr);
	if (size < MP_OKAY) {
		res = MP_NO;
		goto CLEANUP;
	}

	MP_CHECKOK(mpp_random_size(&n, (size + ECL_BITS - 1) / ECL_BITS));
	MP_CHECKOK(ecgroup->meth->field_mod(&n, &n, ecgroup->meth));

	M_TimeOperation(ec_GFp_pt_mul_jac_fp
					(&n, &ecgroup->genx, &ecgroup->geny, &rx, &ry,
					 ecgroup), 1000);

	M_TimeOperation(ec_GFp_point_mul_jac_4w_fp
					(&n, &ecgroup->genx, &ecgroup->geny, &rx, &ry,
					 ecgroup), 1000);

	M_TimeOperation(ec_GFp_point_mul_wNAF_fp
					(&n, &ecgroup->genx, &ecgroup->geny, &rx, &ry,
					 ecgroup), 1000);

	M_TimeOperation(ec_GFp_pt_mul_jac
					(&n, &ecgroup->genx, &ecgroup->geny, &rx, &ry,
					 ecgroup), 100);

  CLEANUP:
	if (res == MP_OKAY)
		printf("  Test Passed - Point Multiplication Timing\n");
	else
		printf("TEST FAILED - Point Multiplication Timing\n");
	mp_clear(&rx);
	mp_clear(&ry);
	mp_clear(&n);

	return res;
}
Пример #3
0
/* Construct a generic GFMethod for arithmetic over prime fields with
 * irreducible irr. */
GFMethod *
GFMethod_consGFp_mont(const mp_int *irr)
{
	mp_err res = MP_OKAY;
	int i;
	GFMethod *meth = NULL;
	mp_mont_modulus *mmm;

	meth = GFMethod_consGFp(irr);
	if (meth == NULL)
		return NULL;

	mmm = (mp_mont_modulus *) malloc(sizeof(mp_mont_modulus));
	if (mmm == NULL) {
		res = MP_MEM;
		goto CLEANUP;
	}

	meth->field_mul = &ec_GFp_mul_mont;
	meth->field_sqr = &ec_GFp_sqr_mont;
	meth->field_div = &ec_GFp_div_mont;
	meth->field_enc = &ec_GFp_enc_mont;
	meth->field_dec = &ec_GFp_dec_mont;
	meth->extra1 = mmm;
	meth->extra2 = NULL;
	meth->extra_free = &ec_GFp_extra_free_mont;

	mmm->N = meth->irr;
	i = mpl_significant_bits(&meth->irr);
	i += MP_DIGIT_BIT - 1;
	mmm->b = i - i % MP_DIGIT_BIT;
	mmm->n0prime = 0 - s_mp_invmod_radix(MP_DIGIT(&meth->irr, 0));

  CLEANUP:
	if (res != MP_OKAY) {
		GFMethod_free(meth);
		return NULL;
	}
	return meth;
}
Пример #4
0
/* Tests point multiplication with a random scalar repeatedly, comparing
 * for consistency within different algorithms. */
mp_err
testPointMulRandom(ECGroup *ecgroup)
{
	mp_err res;
	mp_int rx, ry, rx2, ry2, n;
	int i, size;
	EC_group_fp *group = (EC_group_fp *) ecgroup->extra1;

	MP_DIGITS(&rx) = 0;
	MP_DIGITS(&ry) = 0;
	MP_DIGITS(&rx2) = 0;
	MP_DIGITS(&ry2) = 0;
	MP_DIGITS(&n) = 0;

	MP_CHECKOK(mp_init(&rx));
	MP_CHECKOK(mp_init(&ry));
	MP_CHECKOK(mp_init(&rx2));
	MP_CHECKOK(mp_init(&ry2));
	MP_CHECKOK(mp_init(&n));

	for (i = 0; i < 100; i++) {
		/* compute random scalar */
		size = mpl_significant_bits(&ecgroup->meth->irr);
		if (size < MP_OKAY) {
			res = MP_NO;
			goto CLEANUP;
		}
		MP_CHECKOK(mpp_random_size(&n, group->orderBitSize));
		MP_CHECKOK(mp_mod(&n, &ecgroup->order, &n));

		ec_GFp_pt_mul_jac(&n, &ecgroup->genx, &ecgroup->geny, &rx, &ry,
						  ecgroup);
		ec_GFp_pt_mul_jac_fp(&n, &ecgroup->genx, &ecgroup->geny, &rx2,
							 &ry2, ecgroup);

		if ((mp_cmp(&rx, &rx2) != 0) || (mp_cmp(&ry, &ry2) != 0)) {
			printf
				("  Error: different results for Point Multiplication - Double & Add.\n");
			res = MP_NO;
			goto CLEANUP;
		}

		ec_GFp_point_mul_wNAF_fp(&n, &ecgroup->genx, &ecgroup->geny, &rx,
								 &ry, ecgroup);
		if ((mp_cmp(&rx, &rx2) != 0) || (mp_cmp(&ry, &ry2) != 0)) {
			printf
				("  Error: different results for Point Multiplication - wNAF.\n");
			res = MP_NO;
			goto CLEANUP;
		}

		ec_GFp_point_mul_jac_4w_fp(&n, &ecgroup->genx, &ecgroup->geny, &rx,
								   &ry, ecgroup);
		if ((mp_cmp(&rx, &rx2) != 0) || (mp_cmp(&ry, &ry2) != 0)) {
			printf
				("  Error: different results for Point Multiplication - 4 bit window.\n");
			res = MP_NO;
			goto CLEANUP;
		}

	}

  CLEANUP:
	if (res == MP_OKAY)
		printf("  Test Passed - Point Random Multiplication\n");
	else
		printf("TEST FAILED - Point Random Multiplication\n");
	mp_clear(&rx);
	mp_clear(&ry);
	mp_clear(&rx2);
	mp_clear(&ry2);
	mp_clear(&n);

	return res;
}
Пример #5
0
/* Elliptic curve scalar-point multiplication. Computes R(x, y) = k1 * G + 
 * k2 * P(x, y), where G is the generator (base point) of the group of
 * points on the elliptic curve. Allows k1 = NULL or { k2, P } = NULL.
 * Uses mixed Jacobian-affine coordinates. Input and output values are
 * assumed to be NOT field-encoded. Uses algorithm 15 (simultaneous
 * multiple point multiplication) from Brown, Hankerson, Lopez, Menezes.
 * Software Implementation of the NIST Elliptic Curves over Prime Fields. */
mp_err
ec_GFp_pts_mul_jac(const mp_int *k1, const mp_int *k2, const mp_int *px,
				   const mp_int *py, mp_int *rx, mp_int *ry,
				   const ECGroup *group)
{
	mp_err res = MP_OKAY;
	mp_int precomp[4][4][2];
	mp_int rz;
	const mp_int *a, *b;
	unsigned int i, j;
	int ai, bi, d;

	for (i = 0; i < 4; i++) {
		for (j = 0; j < 4; j++) {
			MP_DIGITS(&precomp[i][j][0]) = 0;
			MP_DIGITS(&precomp[i][j][1]) = 0;
		}
	}
	MP_DIGITS(&rz) = 0;

	ARGCHK(group != NULL, MP_BADARG);
	ARGCHK(!((k1 == NULL)
			 && ((k2 == NULL) || (px == NULL)
				 || (py == NULL))), MP_BADARG);

	/* if some arguments are not defined used ECPoint_mul */
	if (k1 == NULL) {
		return ECPoint_mul(group, k2, px, py, rx, ry);
	} else if ((k2 == NULL) || (px == NULL) || (py == NULL)) {
		return ECPoint_mul(group, k1, NULL, NULL, rx, ry);
	}

	/* initialize precomputation table */
	for (i = 0; i < 4; i++) {
		for (j = 0; j < 4; j++) {
			MP_CHECKOK(mp_init(&precomp[i][j][0]));
			MP_CHECKOK(mp_init(&precomp[i][j][1]));
		}
	}

	/* fill precomputation table */
	/* assign {k1, k2} = {a, b} such that len(a) >= len(b) */
	if (mpl_significant_bits(k1) < mpl_significant_bits(k2)) {
		a = k2;
		b = k1;
		if (group->meth->field_enc) {
			MP_CHECKOK(group->meth->
					   field_enc(px, &precomp[1][0][0], group->meth));
			MP_CHECKOK(group->meth->
					   field_enc(py, &precomp[1][0][1], group->meth));
		} else {
			MP_CHECKOK(mp_copy(px, &precomp[1][0][0]));
			MP_CHECKOK(mp_copy(py, &precomp[1][0][1]));
		}
		MP_CHECKOK(mp_copy(&group->genx, &precomp[0][1][0]));
		MP_CHECKOK(mp_copy(&group->geny, &precomp[0][1][1]));
	} else {
		a = k1;
		b = k2;
		MP_CHECKOK(mp_copy(&group->genx, &precomp[1][0][0]));
		MP_CHECKOK(mp_copy(&group->geny, &precomp[1][0][1]));
		if (group->meth->field_enc) {
			MP_CHECKOK(group->meth->
					   field_enc(px, &precomp[0][1][0], group->meth));
			MP_CHECKOK(group->meth->
					   field_enc(py, &precomp[0][1][1], group->meth));
		} else {
			MP_CHECKOK(mp_copy(px, &precomp[0][1][0]));
			MP_CHECKOK(mp_copy(py, &precomp[0][1][1]));
		}
	}
	/* precompute [*][0][*] */
	mp_zero(&precomp[0][0][0]);
	mp_zero(&precomp[0][0][1]);
	MP_CHECKOK(group->
			   point_dbl(&precomp[1][0][0], &precomp[1][0][1],
						 &precomp[2][0][0], &precomp[2][0][1], group));
	MP_CHECKOK(group->
			   point_add(&precomp[1][0][0], &precomp[1][0][1],
						 &precomp[2][0][0], &precomp[2][0][1],
						 &precomp[3][0][0], &precomp[3][0][1], group));
	/* precompute [*][1][*] */
	for (i = 1; i < 4; i++) {
		MP_CHECKOK(group->
				   point_add(&precomp[0][1][0], &precomp[0][1][1],
							 &precomp[i][0][0], &precomp[i][0][1],
							 &precomp[i][1][0], &precomp[i][1][1], group));
	}
	/* precompute [*][2][*] */
	MP_CHECKOK(group->
			   point_dbl(&precomp[0][1][0], &precomp[0][1][1],
						 &precomp[0][2][0], &precomp[0][2][1], group));
	for (i = 1; i < 4; i++) {
		MP_CHECKOK(group->
				   point_add(&precomp[0][2][0], &precomp[0][2][1],
							 &precomp[i][0][0], &precomp[i][0][1],
							 &precomp[i][2][0], &precomp[i][2][1], group));
	}
	/* precompute [*][3][*] */
	MP_CHECKOK(group->
			   point_add(&precomp[0][1][0], &precomp[0][1][1],
						 &precomp[0][2][0], &precomp[0][2][1],
						 &precomp[0][3][0], &precomp[0][3][1], group));
	for (i = 1; i < 4; i++) {
		MP_CHECKOK(group->
				   point_add(&precomp[0][3][0], &precomp[0][3][1],
							 &precomp[i][0][0], &precomp[i][0][1],
							 &precomp[i][3][0], &precomp[i][3][1], group));
	}

	d = (mpl_significant_bits(a) + 1) / 2;

	/* R = inf */
	MP_CHECKOK(mp_init(&rz));
	MP_CHECKOK(ec_GFp_pt_set_inf_jac(rx, ry, &rz));

        for (i = d; i-- > 0;) {
		ai = MP_GET_BIT(a, 2 * i + 1);
		ai <<= 1;
		ai |= MP_GET_BIT(a, 2 * i);
		bi = MP_GET_BIT(b, 2 * i + 1);
		bi <<= 1;
		bi |= MP_GET_BIT(b, 2 * i);
		/* R = 2^2 * R */
		MP_CHECKOK(ec_GFp_pt_dbl_jac(rx, ry, &rz, rx, ry, &rz, group));
		MP_CHECKOK(ec_GFp_pt_dbl_jac(rx, ry, &rz, rx, ry, &rz, group));
		/* R = R + (ai * A + bi * B) */
		MP_CHECKOK(ec_GFp_pt_add_jac_aff
				   (rx, ry, &rz, &precomp[ai][bi][0], &precomp[ai][bi][1],
					rx, ry, &rz, group));
	}

	MP_CHECKOK(ec_GFp_pt_jac2aff(rx, ry, &rz, rx, ry, group));

	if (group->meth->field_dec) {
		MP_CHECKOK(group->meth->field_dec(rx, rx, group->meth));
		MP_CHECKOK(group->meth->field_dec(ry, ry, group->meth));
	}

  CLEANUP:
	mp_clear(&rz);
	for (i = 0; i < 4; i++) {
		for (j = 0; j < 4; j++) {
			mp_clear(&precomp[i][j][0]);
			mp_clear(&precomp[i][j][1]);
		}
	}
	return res;
}
Пример #6
0
/* Computes R = nP where R is (rx, ry) and P is (px, py). The parameters
 * a, b and p are the elliptic curve coefficients and the prime that
 * determines the field GFp.  Elliptic curve points P and R can be
 * identical.  Uses mixed Jacobian-affine coordinates. Assumes input is
 * already field-encoded using field_enc, and returns output that is still 
 * field-encoded. Uses 4-bit window method. */
mp_err
ec_GFp_pt_mul_jac(const mp_int *n, const mp_int *px, const mp_int *py,
				  mp_int *rx, mp_int *ry, const ECGroup *group)
{
	mp_err res = MP_OKAY;
	mp_int precomp[16][2], rz;
	int i, ni, d;

	MP_DIGITS(&rz) = 0;
	for (i = 0; i < 16; i++) {
		MP_DIGITS(&precomp[i][0]) = 0;
		MP_DIGITS(&precomp[i][1]) = 0;
	}

	ARGCHK(group != NULL, MP_BADARG);
	ARGCHK((n != NULL) && (px != NULL) && (py != NULL), MP_BADARG);

	/* initialize precomputation table */
	for (i = 0; i < 16; i++) {
		MP_CHECKOK(mp_init(&precomp[i][0]));
		MP_CHECKOK(mp_init(&precomp[i][1]));
	}

	/* fill precomputation table */
	mp_zero(&precomp[0][0]);
	mp_zero(&precomp[0][1]);
	MP_CHECKOK(mp_copy(px, &precomp[1][0]));
	MP_CHECKOK(mp_copy(py, &precomp[1][1]));
	for (i = 2; i < 16; i++) {
		MP_CHECKOK(group->
				   point_add(&precomp[1][0], &precomp[1][1],
							 &precomp[i - 1][0], &precomp[i - 1][1],
							 &precomp[i][0], &precomp[i][1], group));
	}

	d = (mpl_significant_bits(n) + 3) / 4;

	/* R = inf */
	MP_CHECKOK(mp_init(&rz));
	MP_CHECKOK(ec_GFp_pt_set_inf_jac(rx, ry, &rz));

	for (i = d - 1; i >= 0; i--) {
		/* compute window ni */
		ni = MP_GET_BIT(n, 4 * i + 3);
		ni <<= 1;
		ni |= MP_GET_BIT(n, 4 * i + 2);
		ni <<= 1;
		ni |= MP_GET_BIT(n, 4 * i + 1);
		ni <<= 1;
		ni |= MP_GET_BIT(n, 4 * i);
		/* R = 2^4 * R */
		MP_CHECKOK(ec_GFp_pt_dbl_jac(rx, ry, &rz, rx, ry, &rz, group));
		MP_CHECKOK(ec_GFp_pt_dbl_jac(rx, ry, &rz, rx, ry, &rz, group));
		MP_CHECKOK(ec_GFp_pt_dbl_jac(rx, ry, &rz, rx, ry, &rz, group));
		MP_CHECKOK(ec_GFp_pt_dbl_jac(rx, ry, &rz, rx, ry, &rz, group));
		/* R = R + (ni * P) */
		MP_CHECKOK(ec_GFp_pt_add_jac_aff
				   (rx, ry, &rz, &precomp[ni][0], &precomp[ni][1], rx, ry,
					&rz, group));
	}

	/* convert result S to affine coordinates */
	MP_CHECKOK(ec_GFp_pt_jac2aff(rx, ry, &rz, rx, ry, group));

  CLEANUP:
	mp_clear(&rz);
	for (i = 0; i < 16; i++) {
		mp_clear(&precomp[i][0]);
		mp_clear(&precomp[i][1]);
	}
	return res;
}
Пример #7
0
/* Construct ECGroup from hex parameters and name, if any. Called by
 * ECGroup_fromHex and ECGroup_fromName. */
ECGroup *
ecgroup_fromNameAndHex(const ECCurveName name,
                       const ECCurveParams * params)
{
    mp_int irr, curvea, curveb, genx, geny, order;
    int bits;
    ECGroup *group = NULL;
    mp_err res = MP_OKAY;

    /* initialize values */
    MP_DIGITS(&irr) = 0;
    MP_DIGITS(&curvea) = 0;
    MP_DIGITS(&curveb) = 0;
    MP_DIGITS(&genx) = 0;
    MP_DIGITS(&geny) = 0;
    MP_DIGITS(&order) = 0;
    MP_CHECKOK(mp_init(&irr));
    MP_CHECKOK(mp_init(&curvea));
    MP_CHECKOK(mp_init(&curveb));
    MP_CHECKOK(mp_init(&genx));
    MP_CHECKOK(mp_init(&geny));
    MP_CHECKOK(mp_init(&order));
    MP_CHECKOK(mp_read_radix(&irr, params->irr, 16));
    MP_CHECKOK(mp_read_radix(&curvea, params->curvea, 16));
    MP_CHECKOK(mp_read_radix(&curveb, params->curveb, 16));
    MP_CHECKOK(mp_read_radix(&genx, params->genx, 16));
    MP_CHECKOK(mp_read_radix(&geny, params->geny, 16));
    MP_CHECKOK(mp_read_radix(&order, params->order, 16));

    /* determine number of bits */
    bits = mpl_significant_bits(&irr) - 1;
    if (bits < MP_OKAY) {
        res = bits;
        goto CLEANUP;
    }

    /* determine which optimizations (if any) to use */
    if (params->field == ECField_GFp) {
        switch (name) {
#ifdef NSS_ECC_MORE_THAN_SUITE_B
#ifdef ECL_USE_FP
        case ECCurve_SECG_PRIME_160R1:
            group =
                ECGroup_consGFp(&irr, &curvea, &curveb, &genx, &geny,
                                &order, params->cofactor);
            if (group == NULL) {
                res = MP_UNDEF;
                goto CLEANUP;
            }
            MP_CHECKOK(ec_group_set_secp160r1_fp(group));
            break;
#endif
        case ECCurve_SECG_PRIME_192R1:
#ifdef ECL_USE_FP
            group =
                ECGroup_consGFp(&irr, &curvea, &curveb, &genx, &geny,
                                &order, params->cofactor);
            if (group == NULL) {
                res = MP_UNDEF;
                goto CLEANUP;
            }
            MP_CHECKOK(ec_group_set_nistp192_fp(group));
#else
            group =
                ECGroup_consGFp(&irr, &curvea, &curveb, &genx, &geny,
                                &order, params->cofactor);
            if (group == NULL) {
                res = MP_UNDEF;
                goto CLEANUP;
            }
            MP_CHECKOK(ec_group_set_gfp192(group, name));
#endif
            break;
        case ECCurve_SECG_PRIME_224R1:
#ifdef ECL_USE_FP
            group =
                ECGroup_consGFp(&irr, &curvea, &curveb, &genx, &geny,
                                &order, params->cofactor);
            if (group == NULL) {
                res = MP_UNDEF;
                goto CLEANUP;
            }
            MP_CHECKOK(ec_group_set_nistp224_fp(group));
#else
            group =
                ECGroup_consGFp(&irr, &curvea, &curveb, &genx, &geny,
                                &order, params->cofactor);
            if (group == NULL) {
                res = MP_UNDEF;
                goto CLEANUP;
            }
            MP_CHECKOK(ec_group_set_gfp224(group, name));
#endif
            break;
#endif /* NSS_ECC_MORE_THAN_SUITE_B */
        case ECCurve_SECG_PRIME_256R1:
            group =
                ECGroup_consGFp(&irr, &curvea, &curveb, &genx, &geny,
                                &order, params->cofactor);
            if (group == NULL) {
                res = MP_UNDEF;
                goto CLEANUP;
            }
            MP_CHECKOK(ec_group_set_gfp256(group, name));
            MP_CHECKOK(ec_group_set_gfp256_32(group, name));
            break;
        case ECCurve_SECG_PRIME_521R1:
            group =
                ECGroup_consGFp(&irr, &curvea, &curveb, &genx, &geny,
                                &order, params->cofactor);
            if (group == NULL) {
                res = MP_UNDEF;
                goto CLEANUP;
            }
            MP_CHECKOK(ec_group_set_gfp521(group, name));
            break;
        default:
            /* use generic arithmetic */
            group =
                ECGroup_consGFp_mont(&irr, &curvea, &curveb, &genx, &geny,
                                     &order, params->cofactor);
            if (group == NULL) {
                res = MP_UNDEF;
                goto CLEANUP;
            }
        }
#ifdef NSS_ECC_MORE_THAN_SUITE_B
    } else if (params->field == ECField_GF2m) {
        group = ECGroup_consGF2m(&irr, NULL, &curvea, &curveb, &genx, &geny, &order, params->cofactor);
        if (group == NULL) {
            res = MP_UNDEF;
            goto CLEANUP;
        }
        if ((name == ECCurve_NIST_K163) ||
                (name == ECCurve_NIST_B163) ||
                (name == ECCurve_SECG_CHAR2_163R1)) {
            MP_CHECKOK(ec_group_set_gf2m163(group, name));
        } else if ((name == ECCurve_SECG_CHAR2_193R1) ||
                   (name == ECCurve_SECG_CHAR2_193R2)) {
            MP_CHECKOK(ec_group_set_gf2m193(group, name));
        } else if ((name == ECCurve_NIST_K233) ||
                   (name == ECCurve_NIST_B233)) {
            MP_CHECKOK(ec_group_set_gf2m233(group, name));
        }
#endif
    } else {
        res = MP_UNDEF;
        goto CLEANUP;
    }

    /* set name, if any */
    if ((group != NULL) && (params->text != NULL)) {
        group->text = strdup(params->text);
        if (group->text == NULL) {
            res = MP_MEM;
        }
    }

CLEANUP:
    mp_clear(&irr);
    mp_clear(&curvea);
    mp_clear(&curveb);
    mp_clear(&genx);
    mp_clear(&geny);
    mp_clear(&order);
    if (res != MP_OKAY) {
        ECGroup_free(group);
        return NULL;
    }
    return group;
}
Пример #8
0
static SECStatus
rsa_build_from_primes(mp_int *p, mp_int *q, 
		mp_int *e, PRBool needPublicExponent, 
		mp_int *d, PRBool needPrivateExponent,
		RSAPrivateKey *key, unsigned int keySizeInBits)
{
    mp_int n, phi;
    mp_int psub1, qsub1, tmp;
    mp_err   err = MP_OKAY;
    SECStatus rv = SECSuccess;
    MP_DIGITS(&n)     = 0;
    MP_DIGITS(&phi)   = 0;
    MP_DIGITS(&psub1) = 0;
    MP_DIGITS(&qsub1) = 0;
    MP_DIGITS(&tmp)   = 0;
    CHECK_MPI_OK( mp_init(&n)     );
    CHECK_MPI_OK( mp_init(&phi)   );
    CHECK_MPI_OK( mp_init(&psub1) );
    CHECK_MPI_OK( mp_init(&qsub1) );
    CHECK_MPI_OK( mp_init(&tmp)   );
    /* 1.  Compute n = p*q */
    CHECK_MPI_OK( mp_mul(p, q, &n) );
    /*     verify that the modulus has the desired number of bits */
    if ((unsigned)mpl_significant_bits(&n) != keySizeInBits) {
	PORT_SetError(SEC_ERROR_NEED_RANDOM);
	rv = SECFailure;
	goto cleanup;
    }

    /* at least one exponent must be given */
    PORT_Assert(!(needPublicExponent && needPrivateExponent));

    /* 2.  Compute phi = (p-1)*(q-1) */
    CHECK_MPI_OK( mp_sub_d(p, 1, &psub1) );
    CHECK_MPI_OK( mp_sub_d(q, 1, &qsub1) );
    if (needPublicExponent || needPrivateExponent) {
	CHECK_MPI_OK( mp_mul(&psub1, &qsub1, &phi) );
	/* 3.  Compute d = e**-1 mod(phi) */
	/*     or      e = d**-1 mod(phi) as necessary */
	if (needPublicExponent) {
	    err = mp_invmod(d, &phi, e);
	} else {
	    err = mp_invmod(e, &phi, d);
	}
    } else {
	err = MP_OKAY;
    }
    /*     Verify that phi(n) and e have no common divisors */
    if (err != MP_OKAY) {
	if (err == MP_UNDEF) {
	    PORT_SetError(SEC_ERROR_NEED_RANDOM);
	    err = MP_OKAY; /* to keep PORT_SetError from being called again */
	    rv = SECFailure;
	}
	goto cleanup;
    }

    /* 4.  Compute exponent1 = d mod (p-1) */
    CHECK_MPI_OK( mp_mod(d, &psub1, &tmp) );
    MPINT_TO_SECITEM(&tmp, &key->exponent1, key->arena);
    /* 5.  Compute exponent2 = d mod (q-1) */
    CHECK_MPI_OK( mp_mod(d, &qsub1, &tmp) );
    MPINT_TO_SECITEM(&tmp, &key->exponent2, key->arena);
    /* 6.  Compute coefficient = q**-1 mod p */
    CHECK_MPI_OK( mp_invmod(q, p, &tmp) );
    MPINT_TO_SECITEM(&tmp, &key->coefficient, key->arena);

    /* copy our calculated results, overwrite what is there */
    key->modulus.data = NULL;
    MPINT_TO_SECITEM(&n, &key->modulus, key->arena);
    key->privateExponent.data = NULL;
    MPINT_TO_SECITEM(d, &key->privateExponent, key->arena);
    key->publicExponent.data = NULL;
    MPINT_TO_SECITEM(e, &key->publicExponent, key->arena);
    key->prime1.data = NULL;
    MPINT_TO_SECITEM(p, &key->prime1, key->arena);
    key->prime2.data = NULL;
    MPINT_TO_SECITEM(q, &key->prime2, key->arena);
cleanup:
    mp_clear(&n);
    mp_clear(&phi);
    mp_clear(&psub1);
    mp_clear(&qsub1);
    mp_clear(&tmp);
    if (err) {
	MP_TO_SEC_ERROR(err);
	rv = SECFailure;
    }
    return rv;
}
Пример #9
0
static SECStatus
rsa_keygen_from_primes(mp_int *p, mp_int *q, mp_int *e, RSAPrivateKey *key,
                       unsigned int keySizeInBits)
{
    mp_int n, d, phi;
    mp_int psub1, qsub1, tmp;
    mp_err   err = MP_OKAY;
    SECStatus rv = SECSuccess;
    MP_DIGITS(&n)     = 0;
    MP_DIGITS(&d)     = 0;
    MP_DIGITS(&phi)   = 0;
    MP_DIGITS(&psub1) = 0;
    MP_DIGITS(&qsub1) = 0;
    MP_DIGITS(&tmp)   = 0;
    CHECK_MPI_OK( mp_init(&n)     );
    CHECK_MPI_OK( mp_init(&d)     );
    CHECK_MPI_OK( mp_init(&phi)   );
    CHECK_MPI_OK( mp_init(&psub1) );
    CHECK_MPI_OK( mp_init(&qsub1) );
    CHECK_MPI_OK( mp_init(&tmp)   );
    /* 1.  Compute n = p*q */
    CHECK_MPI_OK( mp_mul(p, q, &n) );
    /*     verify that the modulus has the desired number of bits */
    if ((unsigned)mpl_significant_bits(&n) != keySizeInBits) {
	PORT_SetError(SEC_ERROR_NEED_RANDOM);
	rv = SECFailure;
	goto cleanup;
    }
    /* 2.  Compute phi = (p-1)*(q-1) */
    CHECK_MPI_OK( mp_sub_d(p, 1, &psub1) );
    CHECK_MPI_OK( mp_sub_d(q, 1, &qsub1) );
    CHECK_MPI_OK( mp_mul(&psub1, &qsub1, &phi) );
    /* 3.  Compute d = e**-1 mod(phi) */
    err = mp_invmod(e, &phi, &d);
    /*     Verify that phi(n) and e have no common divisors */
    if (err != MP_OKAY) {
	if (err == MP_UNDEF) {
	    PORT_SetError(SEC_ERROR_NEED_RANDOM);
	    err = MP_OKAY; /* to keep PORT_SetError from being called again */
	    rv = SECFailure;
	}
	goto cleanup;
    }
    MPINT_TO_SECITEM(&n, &key->modulus, key->arena);
    MPINT_TO_SECITEM(&d, &key->privateExponent, key->arena);
    /* 4.  Compute exponent1 = d mod (p-1) */
    CHECK_MPI_OK( mp_mod(&d, &psub1, &tmp) );
    MPINT_TO_SECITEM(&tmp, &key->exponent1, key->arena);
    /* 5.  Compute exponent2 = d mod (q-1) */
    CHECK_MPI_OK( mp_mod(&d, &qsub1, &tmp) );
    MPINT_TO_SECITEM(&tmp, &key->exponent2, key->arena);
    /* 6.  Compute coefficient = q**-1 mod p */
    CHECK_MPI_OK( mp_invmod(q, p, &tmp) );
    MPINT_TO_SECITEM(&tmp, &key->coefficient, key->arena);
cleanup:
    mp_clear(&n);
    mp_clear(&d);
    mp_clear(&phi);
    mp_clear(&psub1);
    mp_clear(&qsub1);
    mp_clear(&tmp);
    if (err) {
	MP_TO_SEC_ERROR(err);
	rv = SECFailure;
    }
    return rv;
}
Пример #10
0
/*
** Checks the signature on the given digest using the key provided.
*/
SECStatus 
ECDSA_VerifyDigest(ECPublicKey *key, const SECItem *signature, 
                 const SECItem *digest)
{
    SECStatus rv = SECFailure;
#ifndef NSS_DISABLE_ECC
    mp_int r_, s_;           /* tuple (r', s') is received signature) */
    mp_int c, u1, u2, v;     /* intermediate values used in verification */
    mp_int x1;
    mp_int n;
    mp_err err = MP_OKAY;
    ECParams *ecParams = NULL;
    SECItem pointC = { siBuffer, NULL, 0 };
    int slen;       /* length in bytes of a half signature (r or s) */
    int flen;       /* length in bytes of the field size */
    unsigned olen;  /* length in bytes of the base point order */
    unsigned obits; /* length in bits  of the base point order */

#if EC_DEBUG
    char mpstr[256];
    printf("ECDSA verification called\n");
#endif

    /* Initialize MPI integers. */
    /* must happen before the first potential call to cleanup */
    MP_DIGITS(&r_) = 0;
    MP_DIGITS(&s_) = 0;
    MP_DIGITS(&c) = 0;
    MP_DIGITS(&u1) = 0;
    MP_DIGITS(&u2) = 0;
    MP_DIGITS(&x1) = 0;
    MP_DIGITS(&v)  = 0;
    MP_DIGITS(&n)  = 0;

    /* Check args */
    if (!key || !signature || !digest) {
	PORT_SetError(SEC_ERROR_INVALID_ARGS);
	goto cleanup;
    }

    ecParams = &(key->ecParams);
    flen = (ecParams->fieldID.size + 7) >> 3;  
    olen = ecParams->order.len;  
    if (signature->len == 0 || signature->len%2 != 0 ||
	signature->len > 2*olen) {
	PORT_SetError(SEC_ERROR_INPUT_LEN);
	goto cleanup;
    }
    slen = signature->len/2;

    SECITEM_AllocItem(NULL, &pointC, 2*flen + 1);
    if (pointC.data == NULL)
	goto cleanup;

    CHECK_MPI_OK( mp_init(&r_) );
    CHECK_MPI_OK( mp_init(&s_) );
    CHECK_MPI_OK( mp_init(&c)  );
    CHECK_MPI_OK( mp_init(&u1) );
    CHECK_MPI_OK( mp_init(&u2) );
    CHECK_MPI_OK( mp_init(&x1)  );
    CHECK_MPI_OK( mp_init(&v)  );
    CHECK_MPI_OK( mp_init(&n)  );

    /*
    ** Convert received signature (r', s') into MPI integers.
    */
    CHECK_MPI_OK( mp_read_unsigned_octets(&r_, signature->data, slen) );
    CHECK_MPI_OK( mp_read_unsigned_octets(&s_, signature->data + slen, slen) );
                                          
    /* 
    ** ANSI X9.62, Section 5.4.2, Steps 1 and 2
    **
    ** Verify that 0 < r' < n and 0 < s' < n
    */
    SECITEM_TO_MPINT(ecParams->order, &n);
    if (mp_cmp_z(&r_) <= 0 || mp_cmp_z(&s_) <= 0 ||
        mp_cmp(&r_, &n) >= 0 || mp_cmp(&s_, &n) >= 0) {
	PORT_SetError(SEC_ERROR_BAD_SIGNATURE);
	goto cleanup; /* will return rv == SECFailure */
    }

    /*
    ** ANSI X9.62, Section 5.4.2, Step 3
    **
    ** c = (s')**-1 mod n
    */
    CHECK_MPI_OK( mp_invmod(&s_, &n, &c) );      /* c = (s')**-1 mod n */

    /*
    ** ANSI X9.62, Section 5.4.2, Step 4
    **
    ** u1 = ((HASH(M')) * c) mod n
    */
    SECITEM_TO_MPINT(*digest, &u1);                  /* u1 = HASH(M)     */

    /* In the definition of EC signing, digests are truncated
     * to the length of n in bits. 
     * (see SEC 1 "Elliptic Curve Digit Signature Algorithm" section 4.1.*/
    CHECK_MPI_OK( (obits = mpl_significant_bits(&n)) );
    if (digest->len*8 > obits) {  /* u1 = HASH(M')     */
	mpl_rsh(&u1,&u1,digest->len*8 - obits);
    }

#if EC_DEBUG
    mp_todecimal(&r_, mpstr);
    printf("r_: %s (dec)\n", mpstr);
    mp_todecimal(&s_, mpstr);
    printf("s_: %s (dec)\n", mpstr);
    mp_todecimal(&c, mpstr);
    printf("c : %s (dec)\n", mpstr);
    mp_todecimal(&u1, mpstr);
    printf("digest: %s (dec)\n", mpstr);
#endif

    CHECK_MPI_OK( mp_mulmod(&u1, &c, &n, &u1) );  /* u1 = u1 * c mod n */

    /*
    ** ANSI X9.62, Section 5.4.2, Step 4
    **
    ** u2 = ((r') * c) mod n
    */
    CHECK_MPI_OK( mp_mulmod(&r_, &c, &n, &u2) );

    /*
    ** ANSI X9.62, Section 5.4.3, Step 1
    **
    ** Compute u1*G + u2*Q
    ** Here, A = u1.G     B = u2.Q    and   C = A + B
    ** If the result, C, is the point at infinity, reject the signature
    */
    if (ec_points_mul(ecParams, &u1, &u2, &key->publicValue, &pointC)
	!= SECSuccess) {
	rv = SECFailure;
	goto cleanup;
    }
    if (ec_point_at_infinity(&pointC)) {
	PORT_SetError(SEC_ERROR_BAD_SIGNATURE);
	rv = SECFailure;
	goto cleanup;
    }

    CHECK_MPI_OK( mp_read_unsigned_octets(&x1, pointC.data + 1, flen) );

    /*
    ** ANSI X9.62, Section 5.4.4, Step 2
    **
    ** v = x1 mod n
    */
    CHECK_MPI_OK( mp_mod(&x1, &n, &v) );

#if EC_DEBUG
    mp_todecimal(&r_, mpstr);
    printf("r_: %s (dec)\n", mpstr);
    mp_todecimal(&v, mpstr);
    printf("v : %s (dec)\n", mpstr);
#endif

    /*
    ** ANSI X9.62, Section 5.4.4, Step 3
    **
    ** Verification:  v == r'
    */
    if (mp_cmp(&v, &r_)) {
	PORT_SetError(SEC_ERROR_BAD_SIGNATURE);
	rv = SECFailure; /* Signature failed to verify. */
    } else {
	rv = SECSuccess; /* Signature verified. */
    }

#if EC_DEBUG
    mp_todecimal(&u1, mpstr);
    printf("u1: %s (dec)\n", mpstr);
    mp_todecimal(&u2, mpstr);
    printf("u2: %s (dec)\n", mpstr);
    mp_tohex(&x1, mpstr);
    printf("x1: %s\n", mpstr);
    mp_todecimal(&v, mpstr);
    printf("v : %s (dec)\n", mpstr);
#endif

cleanup:
    mp_clear(&r_);
    mp_clear(&s_);
    mp_clear(&c);
    mp_clear(&u1);
    mp_clear(&u2);
    mp_clear(&x1);
    mp_clear(&v);
    mp_clear(&n);

    if (pointC.data) SECITEM_FreeItem(&pointC, PR_FALSE);
    if (err) {
	MP_TO_SEC_ERROR(err);
	rv = SECFailure;
    }

#if EC_DEBUG
    printf("ECDSA verification %s\n",
	(rv == SECSuccess) ? "succeeded" : "failed");
#endif
#else
    PORT_SetError(SEC_ERROR_UNSUPPORTED_KEYALG);
#endif /* NSS_DISABLE_ECC */

    return rv;
}
Пример #11
0
/* Performs basic tests of elliptic curve cryptography over prime fields.
 * If tests fail, then it prints an error message, aborts, and returns an
 * error code. Otherwise, returns 0. */
int
ectest_curve_GFp(ECGroup *group, int ectestPrint, int ectestTime,
                 int generic)
{

    mp_int one, order_1, gx, gy, rx, ry, n;
    int size;
    mp_err res;
    char s[1000];

    /* initialize values */
    MP_CHECKOK(mp_init(&one));
    MP_CHECKOK(mp_init(&order_1));
    MP_CHECKOK(mp_init(&gx));
    MP_CHECKOK(mp_init(&gy));
    MP_CHECKOK(mp_init(&rx));
    MP_CHECKOK(mp_init(&ry));
    MP_CHECKOK(mp_init(&n));

    MP_CHECKOK(mp_set_int(&one, 1));
    MP_CHECKOK(mp_sub(&group->order, &one, &order_1));

    /* encode base point */
    if (group->meth->field_dec) {
        MP_CHECKOK(group->meth->field_dec(&group->genx, &gx, group->meth));
        MP_CHECKOK(group->meth->field_dec(&group->geny, &gy, group->meth));
    } else {
        MP_CHECKOK(mp_copy(&group->genx, &gx));
        MP_CHECKOK(mp_copy(&group->geny, &gy));
    }
    if (ectestPrint) {
        /* output base point */
        printf("  base point P:\n");
        MP_CHECKOK(mp_toradix(&gx, s, 16));
        printf("    %s\n", s);
        MP_CHECKOK(mp_toradix(&gy, s, 16));
        printf("    %s\n", s);
        if (group->meth->field_enc) {
            printf("  base point P (encoded):\n");
            MP_CHECKOK(mp_toradix(&group->genx, s, 16));
            printf("    %s\n", s);
            MP_CHECKOK(mp_toradix(&group->geny, s, 16));
            printf("    %s\n", s);
        }
    }

#ifdef ECL_ENABLE_GFP_PT_MUL_AFF
    /* multiply base point by order - 1 and check for negative of base
     * point */
    MP_CHECKOK(ec_GFp_pt_mul_aff(&order_1, &group->genx, &group->geny, &rx, &ry, group));
    if (ectestPrint) {
        printf("  (order-1)*P (affine):\n");
        MP_CHECKOK(mp_toradix(&rx, s, 16));
        printf("    %s\n", s);
        MP_CHECKOK(mp_toradix(&ry, s, 16));
        printf("    %s\n", s);
    }
    MP_CHECKOK(group->meth->field_neg(&ry, &ry, group->meth));
    if ((mp_cmp(&rx, &group->genx) != 0) || (mp_cmp(&ry, &group->geny) != 0)) {
        printf("  Error: invalid result (expected (- base point)).\n");
        res = MP_NO;
        goto CLEANUP;
    }
#endif

#ifdef ECL_ENABLE_GFP_PT_MUL_AFF
    /* multiply base point by order - 1 and check for negative of base
     * point */
    MP_CHECKOK(ec_GFp_pt_mul_jac(&order_1, &group->genx, &group->geny, &rx, &ry, group));
    if (ectestPrint) {
        printf("  (order-1)*P (jacobian):\n");
        MP_CHECKOK(mp_toradix(&rx, s, 16));
        printf("    %s\n", s);
        MP_CHECKOK(mp_toradix(&ry, s, 16));
        printf("    %s\n", s);
    }
    MP_CHECKOK(group->meth->field_neg(&ry, &ry, group->meth));
    if ((mp_cmp(&rx, &group->genx) != 0) || (mp_cmp(&ry, &group->geny) != 0)) {
        printf("  Error: invalid result (expected (- base point)).\n");
        res = MP_NO;
        goto CLEANUP;
    }
#endif

    /* multiply base point by order - 1 and check for negative of base
     * point */
    MP_CHECKOK(ECPoint_mul(group, &order_1, NULL, NULL, &rx, &ry));
    if (ectestPrint) {
        printf("  (order-1)*P (ECPoint_mul):\n");
        MP_CHECKOK(mp_toradix(&rx, s, 16));
        printf("    %s\n", s);
        MP_CHECKOK(mp_toradix(&ry, s, 16));
        printf("    %s\n", s);
    }
    MP_CHECKOK(mp_submod(&group->meth->irr, &ry, &group->meth->irr, &ry));
    if ((mp_cmp(&rx, &gx) != 0) || (mp_cmp(&ry, &gy) != 0)) {
        printf("  Error: invalid result (expected (- base point)).\n");
        res = MP_NO;
        goto CLEANUP;
    }

    /* multiply base point by order - 1 and check for negative of base
     * point */
    MP_CHECKOK(ECPoint_mul(group, &order_1, &gx, &gy, &rx, &ry));
    if (ectestPrint) {
        printf("  (order-1)*P (ECPoint_mul):\n");
        MP_CHECKOK(mp_toradix(&rx, s, 16));
        printf("    %s\n", s);
        MP_CHECKOK(mp_toradix(&ry, s, 16));
        printf("    %s\n", s);
    }
    MP_CHECKOK(mp_submod(&group->meth->irr, &ry, &group->meth->irr, &ry));
    if ((mp_cmp(&rx, &gx) != 0) || (mp_cmp(&ry, &gy) != 0)) {
        printf("  Error: invalid result (expected (- base point)).\n");
        res = MP_NO;
        goto CLEANUP;
    }

#ifdef ECL_ENABLE_GFP_PT_MUL_AFF
    /* multiply base point by order and check for point at infinity */
    MP_CHECKOK(ec_GFp_pt_mul_aff(&group->order, &group->genx, &group->geny, &rx, &ry,
                                 group));
    if (ectestPrint) {
        printf("  (order)*P (affine):\n");
        MP_CHECKOK(mp_toradix(&rx, s, 16));
        printf("    %s\n", s);
        MP_CHECKOK(mp_toradix(&ry, s, 16));
        printf("    %s\n", s);
    }
    if (ec_GFp_pt_is_inf_aff(&rx, &ry) != MP_YES) {
        printf("  Error: invalid result (expected point at infinity).\n");
        res = MP_NO;
        goto CLEANUP;
    }
#endif

#ifdef ECL_ENABLE_GFP_PT_MUL_JAC
    /* multiply base point by order and check for point at infinity */
    MP_CHECKOK(ec_GFp_pt_mul_jac(&group->order, &group->genx, &group->geny, &rx, &ry,
                                 group));
    if (ectestPrint) {
        printf("  (order)*P (jacobian):\n");
        MP_CHECKOK(mp_toradix(&rx, s, 16));
        printf("    %s\n", s);
        MP_CHECKOK(mp_toradix(&ry, s, 16));
        printf("    %s\n", s);
    }
    if (ec_GFp_pt_is_inf_aff(&rx, &ry) != MP_YES) {
        printf("  Error: invalid result (expected point at infinity).\n");
        res = MP_NO;
        goto CLEANUP;
    }
#endif

    /* multiply base point by order and check for point at infinity */
    MP_CHECKOK(ECPoint_mul(group, &group->order, NULL, NULL, &rx, &ry));
    if (ectestPrint) {
        printf("  (order)*P (ECPoint_mul):\n");
        MP_CHECKOK(mp_toradix(&rx, s, 16));
        printf("    %s\n", s);
        MP_CHECKOK(mp_toradix(&ry, s, 16));
        printf("    %s\n", s);
    }
    if (ec_GFp_pt_is_inf_aff(&rx, &ry) != MP_YES) {
        printf("  Error: invalid result (expected point at infinity).\n");
        res = MP_NO;
        goto CLEANUP;
    }

    /* multiply base point by order and check for point at infinity */
    MP_CHECKOK(ECPoint_mul(group, &group->order, &gx, &gy, &rx, &ry));
    if (ectestPrint) {
        printf("  (order)*P (ECPoint_mul):\n");
        MP_CHECKOK(mp_toradix(&rx, s, 16));
        printf("    %s\n", s);
        MP_CHECKOK(mp_toradix(&ry, s, 16));
        printf("    %s\n", s);
    }
    if (ec_GFp_pt_is_inf_aff(&rx, &ry) != MP_YES) {
        printf("  Error: invalid result (expected point at infinity).\n");
        res = MP_NO;
        goto CLEANUP;
    }

    /* check that (order-1)P + (order-1)P + P == (order-1)P */
    MP_CHECKOK(ECPoints_mul(group, &order_1, &order_1, &gx, &gy, &rx, &ry));
    MP_CHECKOK(ECPoints_mul(group, &one, &one, &rx, &ry, &rx, &ry));
    if (ectestPrint) {
        printf("  (order-1)*P + (order-1)*P + P == (order-1)*P (ECPoints_mul):\n");
        MP_CHECKOK(mp_toradix(&rx, s, 16));
        printf("    %s\n", s);
        MP_CHECKOK(mp_toradix(&ry, s, 16));
        printf("    %s\n", s);
    }
    MP_CHECKOK(mp_submod(&group->meth->irr, &ry, &group->meth->irr, &ry));
    if ((mp_cmp(&rx, &gx) != 0) || (mp_cmp(&ry, &gy) != 0)) {
        printf("  Error: invalid result (expected (- base point)).\n");
        res = MP_NO;
        goto CLEANUP;
    }

    /* test validate_point function */
    if (ECPoint_validate(group, &gx, &gy) != MP_YES) {
        printf("  Error: validate point on base point failed.\n");
        res = MP_NO;
        goto CLEANUP;
    }
    MP_CHECKOK(mp_add_d(&gy, 1, &ry));
    if (ECPoint_validate(group, &gx, &ry) != MP_NO) {
        printf("  Error: validate point on invalid point passed.\n");
        res = MP_NO;
        goto CLEANUP;
    }

    if (ectestTime) {
        /* compute random scalar */
        size = mpl_significant_bits(&group->meth->irr);
        if (size < MP_OKAY) {
            goto CLEANUP;
        }
        MP_CHECKOK(mpp_random_size(&n, (size + ECL_BITS - 1) / ECL_BITS));
        MP_CHECKOK(group->meth->field_mod(&n, &n, group->meth));
        /* timed test */
        if (generic) {
#ifdef ECL_ENABLE_GFP_PT_MUL_AFF
            M_TimeOperation(MP_CHECKOK(ec_GFp_pt_mul_aff(&n, &group->genx, &group->geny, &rx, &ry,
                                       group)),
                            100);
#endif
            M_TimeOperation(MP_CHECKOK(ECPoint_mul(group, &n, NULL, NULL, &rx, &ry)),
                            100);
            M_TimeOperation(MP_CHECKOK(ECPoints_mul(group, &n, &n, &gx, &gy, &rx, &ry)), 100);
        } else {
            M_TimeOperation(MP_CHECKOK(ECPoint_mul(group, &n, NULL, NULL, &rx, &ry)),
                            100);
            M_TimeOperation(MP_CHECKOK(ECPoint_mul(group, &n, &gx, &gy, &rx, &ry)),
                            100);
            M_TimeOperation(MP_CHECKOK(ECPoints_mul(group, &n, &n, &gx, &gy, &rx, &ry)), 100);
        }
    }

CLEANUP:
    mp_clear(&one);
    mp_clear(&order_1);
    mp_clear(&gx);
    mp_clear(&gy);
    mp_clear(&rx);
    mp_clear(&ry);
    mp_clear(&n);
    if (res != MP_OKAY) {
        printf("  Error: exiting with error value %i\n", res);
    }
    return res;
}
Пример #12
0
/* Computes R = nP based on IEEE P1363 A.10.3. Elliptic curve points P and
 * R can be identical. Uses affine coordinates. Assumes input is already
 * field-encoded using field_enc, and returns output that is still
 * field-encoded. */
mp_err
ec_GFp_pt_mul_aff(const mp_int *n, const mp_int *px, const mp_int *py,
                  mp_int *rx, mp_int *ry, const ECGroup *group)
{
    mp_err res = MP_OKAY;
    mp_int k, k3, qx, qy, sx, sy;
    int b1, b3, i, l;

    MP_DIGITS(&k) = 0;
    MP_DIGITS(&k3) = 0;
    MP_DIGITS(&qx) = 0;
    MP_DIGITS(&qy) = 0;
    MP_DIGITS(&sx) = 0;
    MP_DIGITS(&sy) = 0;
    MP_CHECKOK(mp_init(&k));
    MP_CHECKOK(mp_init(&k3));
    MP_CHECKOK(mp_init(&qx));
    MP_CHECKOK(mp_init(&qy));
    MP_CHECKOK(mp_init(&sx));
    MP_CHECKOK(mp_init(&sy));

    /* if n = 0 then r = inf */
    if (mp_cmp_z(n) == 0) {
        mp_zero(rx);
        mp_zero(ry);
        res = MP_OKAY;
        goto CLEANUP;
    }
    /* Q = P, k = n */
    MP_CHECKOK(mp_copy(px, &qx));
    MP_CHECKOK(mp_copy(py, &qy));
    MP_CHECKOK(mp_copy(n, &k));
    /* if n < 0 then Q = -Q, k = -k */
    if (mp_cmp_z(n) < 0) {
        MP_CHECKOK(group->meth->field_neg(&qy, &qy, group->meth));
        MP_CHECKOK(mp_neg(&k, &k));
    }
#ifdef ECL_DEBUG /* basic double and add method */
    l = mpl_significant_bits(&k) - 1;
    MP_CHECKOK(mp_copy(&qx, &sx));
    MP_CHECKOK(mp_copy(&qy, &sy));
    for (i = l - 1; i >= 0; i--) {
        /* S = 2S */
        MP_CHECKOK(group->point_dbl(&sx, &sy, &sx, &sy, group));
        /* if k_i = 1, then S = S + Q */
        if (mpl_get_bit(&k, i) != 0) {
            MP_CHECKOK(group->point_add(&sx, &sy, &qx, &qy, &sx, &sy, group));
        }
    }
#else /* double and add/subtract method from \
               * standard */
    /* k3 = 3 * k */
    MP_CHECKOK(mp_set_int(&k3, 3));
    MP_CHECKOK(mp_mul(&k, &k3, &k3));
    /* S = Q */
    MP_CHECKOK(mp_copy(&qx, &sx));
    MP_CHECKOK(mp_copy(&qy, &sy));
    /* l = index of high order bit in binary representation of 3*k */
    l = mpl_significant_bits(&k3) - 1;
    /* for i = l-1 downto 1 */
    for (i = l - 1; i >= 1; i--) {
        /* S = 2S */
        MP_CHECKOK(group->point_dbl(&sx, &sy, &sx, &sy, group));
        b3 = MP_GET_BIT(&k3, i);
        b1 = MP_GET_BIT(&k, i);
        /* if k3_i = 1 and k_i = 0, then S = S + Q */
        if ((b3 == 1) && (b1 == 0)) {
            MP_CHECKOK(group->point_add(&sx, &sy, &qx, &qy, &sx, &sy, group));
            /* if k3_i = 0 and k_i = 1, then S = S - Q */
        } else if ((b3 == 0) && (b1 == 1)) {
            MP_CHECKOK(group->point_sub(&sx, &sy, &qx, &qy, &sx, &sy, group));
        }
    }
#endif
    /* output S */
    MP_CHECKOK(mp_copy(&sx, rx));
    MP_CHECKOK(mp_copy(&sy, ry));

CLEANUP:
    mp_clear(&k);
    mp_clear(&k3);
    mp_clear(&qx);
    mp_clear(&qy);
    mp_clear(&sx);
    mp_clear(&sy);
    return res;
}
Пример #13
0
/* Uses mixed Jacobian-affine coordinates to perform a point
 * multiplication: R = n * P, n scalar. Uses mixed Jacobian-affine
 * coordinates (Jacobian coordinates for doubles and affine coordinates
 * for additions; based on recommendation from Brown et al.). Not very
 * time efficient but quite space efficient, no precomputation needed.
 * group contains the elliptic curve coefficients and the prime that
 * determines the field GFp.  Elliptic curve points P and R can be
 * identical. Performs calculations in floating point number format, since 
 * this is faster than the integer operations on the ULTRASPARC III.
 * Uses left-to-right binary method (double & add) (algorithm 9) for
 * scalar-point multiplication from Brown, Hankerson, Lopez, Menezes.
 * Software Implementation of the NIST Elliptic Curves Over Prime Fields. */
mp_err
ec_GFp_pt_mul_jac_fp(const mp_int *n, const mp_int *px, const mp_int *py,
					 mp_int *rx, mp_int *ry, const ECGroup *ecgroup)
{
	mp_err res;
	mp_int sx, sy, sz;

	ecfp_aff_pt p;
	ecfp_jac_pt r;
	EC_group_fp *group = (EC_group_fp *) ecgroup->extra1;

	int i, l;

	MP_DIGITS(&sx) = 0;
	MP_DIGITS(&sy) = 0;
	MP_DIGITS(&sz) = 0;
	MP_CHECKOK(mp_init(&sx));
	MP_CHECKOK(mp_init(&sy));
	MP_CHECKOK(mp_init(&sz));

	/* if n = 0 then r = inf */
	if (mp_cmp_z(n) == 0) {
		mp_zero(rx);
		mp_zero(ry);
		res = MP_OKAY;
		goto CLEANUP;
		/* if n < 0 then out of range error */
	} else if (mp_cmp_z(n) < 0) {
		res = MP_RANGE;
		goto CLEANUP;
	}

	/* Convert from integer to floating point */
	ecfp_i2fp(p.x, px, ecgroup);
	ecfp_i2fp(p.y, py, ecgroup);
	ecfp_i2fp(group->curvea, &(ecgroup->curvea), ecgroup);

	/* Init r to point at infinity */
	for (i = 0; i < group->numDoubles; i++) {
		r.z[i] = 0;
	}

	/* double and add method */
	l = mpl_significant_bits(n) - 1;

	for (i = l; i >= 0; i--) {
		/* R = 2R */
		group->pt_dbl_jac(&r, &r, group);

		/* if n_i = 1, then R = R + Q */
		if (MP_GET_BIT(n, i) != 0) {
			group->pt_add_jac_aff(&r, &p, &r, group);
		}
	}

	/* Convert from floating point to integer */
	ecfp_fp2i(&sx, r.x, ecgroup);
	ecfp_fp2i(&sy, r.y, ecgroup);
	ecfp_fp2i(&sz, r.z, ecgroup);

	/* convert result R to affine coordinates */
	MP_CHECKOK(ec_GFp_pt_jac2aff(&sx, &sy, &sz, rx, ry, ecgroup));

  CLEANUP:
	mp_clear(&sx);
	mp_clear(&sy);
	mp_clear(&sz);
	return res;
}
Пример #14
0
/* Computes R = nP where R is (rx, ry) and P is (px, py). The parameters
 * a, b and p are the elliptic curve coefficients and the prime that
 * determines the field GFp.  Elliptic curve points P and R can be
 * identical.  Uses Jacobian coordinates. Uses 4-bit window method. */
mp_err
ec_GFp_point_mul_jac_4w_fp(const mp_int *n, const mp_int *px,
						   const mp_int *py, mp_int *rx, mp_int *ry,
						   const ECGroup *ecgroup)
{
	mp_err res = MP_OKAY;
	ecfp_jac_pt precomp[16], r;
	ecfp_aff_pt p;
	EC_group_fp *group;

	mp_int rz;
	int i, ni, d;

	ARGCHK(ecgroup != NULL, MP_BADARG);
	ARGCHK((n != NULL) && (px != NULL) && (py != NULL), MP_BADARG);

	group = (EC_group_fp *) ecgroup->extra1;
	MP_DIGITS(&rz) = 0;
	MP_CHECKOK(mp_init(&rz));

	/* init p, da */
	ecfp_i2fp(p.x, px, ecgroup);
	ecfp_i2fp(p.y, py, ecgroup);
	ecfp_i2fp(group->curvea, &ecgroup->curvea, ecgroup);

	/* Do precomputation */
	group->precompute_jac(precomp, &p, group);

	/* Do main body of calculations */
	d = (mpl_significant_bits(n) + 3) / 4;

	/* R = inf */
	for (i = 0; i < group->numDoubles; i++) {
		r.z[i] = 0;
	}

	for (i = d - 1; i >= 0; i--) {
		/* compute window ni */
		ni = MP_GET_BIT(n, 4 * i + 3);
		ni <<= 1;
		ni |= MP_GET_BIT(n, 4 * i + 2);
		ni <<= 1;
		ni |= MP_GET_BIT(n, 4 * i + 1);
		ni <<= 1;
		ni |= MP_GET_BIT(n, 4 * i);

		/* R = 2^4 * R */
		group->pt_dbl_jac(&r, &r, group);
		group->pt_dbl_jac(&r, &r, group);
		group->pt_dbl_jac(&r, &r, group);
		group->pt_dbl_jac(&r, &r, group);

		/* R = R + (ni * P) */
		group->pt_add_jac(&r, &precomp[ni], &r, group);
	}

	/* Convert back to integer */
	ecfp_fp2i(rx, r.x, ecgroup);
	ecfp_fp2i(ry, r.y, ecgroup);
	ecfp_fp2i(&rz, r.z, ecgroup);

	/* convert result S to affine coordinates */
	MP_CHECKOK(ec_GFp_pt_jac2aff(rx, ry, &rz, rx, ry, ecgroup));

  CLEANUP:
	mp_clear(&rz);
	return res;
}
Пример #15
0
mp_err mp_exptmod(const mp_int *inBase, const mp_int *exponent, 
		  const mp_int *modulus, mp_int *result)
{
  const mp_int *base;
  mp_size bits_in_exponent, i, window_bits, odd_ints;
  mp_err  res;
  int     nLen;
  mp_int  montBase, goodBase;
  mp_mont_modulus mmm;
#ifdef MP_USING_CACHE_SAFE_MOD_EXP
  static unsigned int max_window_bits;
#endif

  /* function for computing n0prime only works if n0 is odd */
  if (!mp_isodd(modulus))
    return s_mp_exptmod(inBase, exponent, modulus, result);

  MP_DIGITS(&montBase) = 0;
  MP_DIGITS(&goodBase) = 0;

  if (mp_cmp(inBase, modulus) < 0) {
    base = inBase;
  } else {
    MP_CHECKOK( mp_init(&goodBase) );
    base = &goodBase;
    MP_CHECKOK( mp_mod(inBase, modulus, &goodBase) );
  }

  nLen  = MP_USED(modulus);
  MP_CHECKOK( mp_init_size(&montBase, 2 * nLen + 2) );

  mmm.N = *modulus;			/* a copy of the mp_int struct */

  /* compute n0', given n0, n0' = -(n0 ** -1) mod MP_RADIX
  **		where n0 = least significant mp_digit of N, the modulus.
  */
  mmm.n0prime = 0 - s_mp_invmod_radix( MP_DIGIT(modulus, 0) );

  MP_CHECKOK( s_mp_to_mont(base, &mmm, &montBase) );

  bits_in_exponent = mpl_significant_bits(exponent);
#ifdef MP_USING_CACHE_SAFE_MOD_EXP
  if (mp_using_cache_safe_exp) {
    if (bits_in_exponent > 780)
	window_bits = 6;
    else if (bits_in_exponent > 256)
	window_bits = 5;
    else if (bits_in_exponent > 20)
	window_bits = 4;
       /* RSA public key exponents are typically under 20 bits (common values 
        * are: 3, 17, 65537) and a 4-bit window is inefficient
        */
    else 
	window_bits = 1;
  } else
#endif
  if (bits_in_exponent > 480)
    window_bits = 6;
  else if (bits_in_exponent > 160)
    window_bits = 5;
  else if (bits_in_exponent > 20)
    window_bits = 4;
  /* RSA public key exponents are typically under 20 bits (common values 
   * are: 3, 17, 65537) and a 4-bit window is inefficient
   */
  else 
    window_bits = 1;

#ifdef MP_USING_CACHE_SAFE_MOD_EXP
  /*
   * clamp the window size based on
   * the cache line size.
   */
  if (!max_window_bits) {
    unsigned long cache_size = s_mpi_getProcessorLineSize();
    /* processor has no cache, use 'fast' code always */
    if (cache_size == 0) {
      mp_using_cache_safe_exp = 0;
    } 
    if ((cache_size == 0) || (cache_size >= 64)) {
      max_window_bits = 6;
    } else if (cache_size >= 32) {
      max_window_bits = 5;
    } else if (cache_size >= 16) {
      max_window_bits = 4;
    } else max_window_bits = 1; /* should this be an assert? */
  }

  /* clamp the window size down before we caclulate bits_in_exponent */
  if (mp_using_cache_safe_exp) {
    if (window_bits > max_window_bits) {
      window_bits = max_window_bits;
    }
  }
#endif

  odd_ints = 1 << (window_bits - 1);
  i = bits_in_exponent % window_bits;
  if (i != 0) {
    bits_in_exponent += window_bits - i;
  } 

#ifdef MP_USING_MONT_MULF
  if (mp_using_mont_mulf) {
    MP_CHECKOK( s_mp_pad(&montBase, nLen) );
    res = mp_exptmod_f(&montBase, exponent, modulus, result, &mmm, nLen, 
		     bits_in_exponent, window_bits, odd_ints);
  } else
#endif
#ifdef MP_USING_CACHE_SAFE_MOD_EXP
  if (mp_using_cache_safe_exp) {
    res = mp_exptmod_safe_i(&montBase, exponent, modulus, result, &mmm, nLen, 
		     bits_in_exponent, window_bits, 1 << window_bits);
  } else
#endif
  res = mp_exptmod_i(&montBase, exponent, modulus, result, &mmm, nLen, 
		     bits_in_exponent, window_bits, odd_ints);

CLEANUP:
  mp_clear(&montBase);
  mp_clear(&goodBase);
  /* Don't mp_clear mmm.N because it is merely a copy of modulus.
  ** Just zap it.
  */
  memset(&mmm, 0, sizeof mmm);
  return res;
}
Пример #16
0
/* Computes the ECDSA signature (a concatenation of two values r and s)
 * on the digest using the given key and the random value kb (used in
 * computing s).
 */
SECStatus 
ECDSA_SignDigestWithSeed(ECPrivateKey *key, SECItem *signature, 
    const SECItem *digest, const unsigned char *kb, const int kblen)
{
    SECStatus rv = SECFailure;
#ifndef NSS_DISABLE_ECC
    mp_int x1;
    mp_int d, k;     /* private key, random integer */
    mp_int r, s;     /* tuple (r, s) is the signature */
    mp_int n;
    mp_err err = MP_OKAY;
    ECParams *ecParams = NULL;
    SECItem kGpoint = { siBuffer, NULL, 0};
    int flen = 0;    /* length in bytes of the field size */
    unsigned olen;   /* length in bytes of the base point order */
    unsigned obits;  /* length in bits  of the base point order */

#if EC_DEBUG
    char mpstr[256];
#endif

    /* Initialize MPI integers. */
    /* must happen before the first potential call to cleanup */
    MP_DIGITS(&x1) = 0;
    MP_DIGITS(&d) = 0;
    MP_DIGITS(&k) = 0;
    MP_DIGITS(&r) = 0;
    MP_DIGITS(&s) = 0;
    MP_DIGITS(&n) = 0;

    /* Check args */
    if (!key || !signature || !digest || !kb || (kblen < 0)) {
	PORT_SetError(SEC_ERROR_INVALID_ARGS);
	goto cleanup;
    }

    ecParams = &(key->ecParams);
    flen = (ecParams->fieldID.size + 7) >> 3;
    olen = ecParams->order.len;  
    if (signature->data == NULL) {
	/* a call to get the signature length only */
	goto finish;
    }
    if (signature->len < 2*olen) {
	PORT_SetError(SEC_ERROR_OUTPUT_LEN);
	goto cleanup;
    }


    CHECK_MPI_OK( mp_init(&x1) );
    CHECK_MPI_OK( mp_init(&d) );
    CHECK_MPI_OK( mp_init(&k) );
    CHECK_MPI_OK( mp_init(&r) );
    CHECK_MPI_OK( mp_init(&s) );
    CHECK_MPI_OK( mp_init(&n) );

    SECITEM_TO_MPINT( ecParams->order, &n );
    SECITEM_TO_MPINT( key->privateValue, &d );

    CHECK_MPI_OK( mp_read_unsigned_octets(&k, kb, kblen) );
    /* Make sure k is in the interval [1, n-1] */
    if ((mp_cmp_z(&k) <= 0) || (mp_cmp(&k, &n) >= 0)) {
#if EC_DEBUG
        printf("k is outside [1, n-1]\n");
        mp_tohex(&k, mpstr);
	printf("k : %s \n", mpstr);
        mp_tohex(&n, mpstr);
	printf("n : %s \n", mpstr);
#endif
	PORT_SetError(SEC_ERROR_NEED_RANDOM);
	goto cleanup;
    }

    /*
    ** We do not want timing information to leak the length of k,
    ** so we compute k*G using an equivalent scalar of fixed
    ** bit-length.
    ** Fix based on patch for ECDSA timing attack in the paper
    ** by Billy Bob Brumley and Nicola Tuveri at
    **   http://eprint.iacr.org/2011/232
    **
    ** How do we convert k to a value of a fixed bit-length?
    ** k starts off as an integer satisfying 0 <= k < n.  Hence,
    ** n <= k+n < 2n, which means k+n has either the same number
    ** of bits as n or one more bit than n.  If k+n has the same
    ** number of bits as n, the second addition ensures that the
    ** final value has exactly one more bit than n.  Thus, we
    ** always end up with a value that exactly one more bit than n.
    */
    CHECK_MPI_OK( mp_add(&k, &n, &k) );
    if (mpl_significant_bits(&k) <= mpl_significant_bits(&n)) {
	CHECK_MPI_OK( mp_add(&k, &n, &k) );
    }

    /* 
    ** ANSI X9.62, Section 5.3.2, Step 2
    **
    ** Compute kG
    */
    kGpoint.len = 2*flen + 1;
    kGpoint.data = PORT_Alloc(2*flen + 1);
    if ((kGpoint.data == NULL) ||
	(ec_points_mul(ecParams, &k, NULL, NULL, &kGpoint)
	    != SECSuccess))
	goto cleanup;

    /* 
    ** ANSI X9.62, Section 5.3.3, Step 1
    **
    ** Extract the x co-ordinate of kG into x1
    */
    CHECK_MPI_OK( mp_read_unsigned_octets(&x1, kGpoint.data + 1, 
	                                  (mp_size) flen) );

    /* 
    ** ANSI X9.62, Section 5.3.3, Step 2
    **
    ** r = x1 mod n  NOTE: n is the order of the curve
    */
    CHECK_MPI_OK( mp_mod(&x1, &n, &r) );

    /*
    ** ANSI X9.62, Section 5.3.3, Step 3
    **
    ** verify r != 0 
    */
    if (mp_cmp_z(&r) == 0) {
	PORT_SetError(SEC_ERROR_NEED_RANDOM);
	goto cleanup;
    }

    /*                                  
    ** ANSI X9.62, Section 5.3.3, Step 4
    **
    ** s = (k**-1 * (HASH(M) + d*r)) mod n 
    */
    SECITEM_TO_MPINT(*digest, &s);        /* s = HASH(M)     */

    /* In the definition of EC signing, digests are truncated
     * to the length of n in bits. 
     * (see SEC 1 "Elliptic Curve Digit Signature Algorithm" section 4.1.*/
    CHECK_MPI_OK( (obits = mpl_significant_bits(&n)) );
    if (digest->len*8 > obits) {
	mpl_rsh(&s,&s,digest->len*8 - obits);
    }

#if EC_DEBUG
    mp_todecimal(&n, mpstr);
    printf("n : %s (dec)\n", mpstr);
    mp_todecimal(&d, mpstr);
    printf("d : %s (dec)\n", mpstr);
    mp_tohex(&x1, mpstr);
    printf("x1: %s\n", mpstr);
    mp_todecimal(&s, mpstr);
    printf("digest: %s (decimal)\n", mpstr);
    mp_todecimal(&r, mpstr);
    printf("r : %s (dec)\n", mpstr);
    mp_tohex(&r, mpstr);
    printf("r : %s\n", mpstr);
#endif

    CHECK_MPI_OK( mp_invmod(&k, &n, &k) );      /* k = k**-1 mod n */
    CHECK_MPI_OK( mp_mulmod(&d, &r, &n, &d) );  /* d = d * r mod n */
    CHECK_MPI_OK( mp_addmod(&s, &d, &n, &s) );  /* s = s + d mod n */
    CHECK_MPI_OK( mp_mulmod(&s, &k, &n, &s) );  /* s = s * k mod n */

#if EC_DEBUG
    mp_todecimal(&s, mpstr);
    printf("s : %s (dec)\n", mpstr);
    mp_tohex(&s, mpstr);
    printf("s : %s\n", mpstr);
#endif

    /*
    ** ANSI X9.62, Section 5.3.3, Step 5
    **
    ** verify s != 0
    */
    if (mp_cmp_z(&s) == 0) {
	PORT_SetError(SEC_ERROR_NEED_RANDOM);
	goto cleanup;
    }

   /*
    **
    ** Signature is tuple (r, s)
    */
    CHECK_MPI_OK( mp_to_fixlen_octets(&r, signature->data, olen) );
    CHECK_MPI_OK( mp_to_fixlen_octets(&s, signature->data + olen, olen) );
finish:
    signature->len = 2*olen;

    rv = SECSuccess;
    err = MP_OKAY;
cleanup:
    mp_clear(&x1);
    mp_clear(&d);
    mp_clear(&k);
    mp_clear(&r);
    mp_clear(&s);
    mp_clear(&n);

    if (kGpoint.data) {
	PORT_ZFree(kGpoint.data, 2*flen + 1);
    }

    if (err) {
	MP_TO_SEC_ERROR(err);
	rv = SECFailure;
    }

#if EC_DEBUG
    printf("ECDSA signing with seed %s\n",
	(rv == SECSuccess) ? "succeeded" : "failed");
#endif
#else
    PORT_SetError(SEC_ERROR_UNSUPPORTED_KEYALG);
#endif /* NSS_DISABLE_ECC */

   return rv;
}
Пример #17
0
mp_err mpp_make_prime(mp_int *start, mp_size nBits, mp_size strong,
		      unsigned long * nTries)
{
  mp_digit      np;
  mp_err        res;
  int           i	= 0;
  mp_int        trial;
  mp_int        q;
  mp_size       num_tests;
  unsigned char *sieve;
  
  ARGCHK(start != 0, MP_BADARG);
  ARGCHK(nBits > 16, MP_RANGE);

  sieve = malloc(SIEVE_SIZE);
  ARGCHK(sieve != NULL, MP_MEM);

  MP_DIGITS(&trial) = 0;
  MP_DIGITS(&q) = 0;
  MP_CHECKOK( mp_init(&trial) );
  MP_CHECKOK( mp_init(&q)     );
  /* values taken from table 4.4, HandBook of Applied Cryptography */
  if (nBits >= 1300) {
    num_tests = 2;
  } else if (nBits >= 850) {
    num_tests = 3;
  } else if (nBits >= 650) {
    num_tests = 4;
  } else if (nBits >= 550) {
    num_tests = 5;
  } else if (nBits >= 450) {
    num_tests = 6;
  } else if (nBits >= 400) {
    num_tests = 7;
  } else if (nBits >= 350) {
    num_tests = 8;
  } else if (nBits >= 300) {
    num_tests = 9;
  } else if (nBits >= 250) {
    num_tests = 12;
  } else if (nBits >= 200) {
    num_tests = 15;
  } else if (nBits >= 150) {
    num_tests = 18;
  } else if (nBits >= 100) {
    num_tests = 27;
  } else
    num_tests = 50;

  if (strong) 
    --nBits;
  MP_CHECKOK( mpl_set_bit(start, nBits - 1, 1) );
  MP_CHECKOK( mpl_set_bit(start,         0, 1) );
  for (i = mpl_significant_bits(start) - 1; i >= nBits; --i) {
    MP_CHECKOK( mpl_set_bit(start, i, 0) );
  }
  /* start sieveing with prime value of 3. */
  MP_CHECKOK(mpp_sieve(start, prime_tab + 1, prime_tab_size - 1, 
		       sieve, SIEVE_SIZE) );

#ifdef DEBUG_SIEVE
  res = 0;
  for (i = 0; i < SIEVE_SIZE; ++i) {
    if (!sieve[i])
      ++res;
  }
  fprintf(stderr,"sieve found %d potential primes.\n", res);
#define FPUTC(x,y) fputc(x,y)
#else
#define FPUTC(x,y) 
#endif

  res = MP_NO;
  for(i = 0; i < SIEVE_SIZE; ++i) {
    if (sieve[i])	/* this number is composite */
      continue;
    MP_CHECKOK( mp_add_d(start, 2 * i, &trial) );
    FPUTC('.', stderr);
    /* run a Fermat test */
    res = mpp_fermat(&trial, 2);
    if (res != MP_OKAY) {
      if (res == MP_NO)
	continue;	/* was composite */
      goto CLEANUP;
    }
      
    FPUTC('+', stderr);
    /* If that passed, run some Miller-Rabin tests	*/
    res = mpp_pprime(&trial, num_tests);
    if (res != MP_OKAY) {
      if (res == MP_NO)
	continue;	/* was composite */
      goto CLEANUP;
    }
    FPUTC('!', stderr);

    if (!strong) 
      break;	/* success !! */

    /* At this point, we have strong evidence that our candidate
       is itself prime.  If we want a strong prime, we need now
       to test q = 2p + 1 for primality...
     */
    MP_CHECKOK( mp_mul_2(&trial, &q) );
    MP_CHECKOK( mp_add_d(&q, 1, &q)  );

    /* Test q for small prime divisors ... */
    np = prime_tab_size;
    res = mpp_divis_primes(&q, &np);
    if (res == MP_YES) { /* is composite */
      mp_clear(&q);
      continue;
    }
    if (res != MP_NO) 
      goto CLEANUP;

    /* And test with Fermat, as with its parent ... */
    res = mpp_fermat(&q, 2);
    if (res != MP_YES) {
      mp_clear(&q);
      if (res == MP_NO)
	continue;	/* was composite */
      goto CLEANUP;
    }

    /* And test with Miller-Rabin, as with its parent ... */
    res = mpp_pprime(&q, num_tests);
    if (res != MP_YES) {
      mp_clear(&q);
      if (res == MP_NO)
	continue;	/* was composite */
      goto CLEANUP;
    }

    /* If it passed, we've got a winner */
    mp_exch(&q, &trial);
    mp_clear(&q);
    break;

  } /* end of loop through sieved values */
  if (res == MP_YES) 
    mp_exch(&trial, start);
CLEANUP:
  mp_clear(&trial);
  mp_clear(&q);
  if (nTries)
    *nTries += i;
  if (sieve != NULL) {
  	memset(sieve, 0, SIEVE_SIZE);
  	free (sieve);
  }
  return res;
}
Пример #18
0
/* Computes R = nP where R is (rx, ry) and P is the base point. Elliptic
 * curve points P and R can be identical. Uses mixed Modified-Jacobian
 * co-ordinates for doubling and Chudnovsky Jacobian coordinates for
 * additions. Assumes input is already field-encoded using field_enc, and
 * returns output that is still field-encoded. Uses 5-bit window NAF
 * method (algorithm 11) for scalar-point multiplication from Brown,
 * Hankerson, Lopez, Menezes. Software Implementation of the NIST Elliptic
 * Curves Over Prime Fields. */
mp_err
ec_GFp_pt_mul_jm_wNAF(const mp_int *n, const mp_int *px, const mp_int *py,
                                          mp_int *rx, mp_int *ry, const ECGroup *group)
{
        mp_err res = MP_OKAY;
        mp_int precomp[16][2], rz, tpx, tpy;
        mp_int raz4;
        mp_int scratch[MAX_SCRATCH];
        signed char *naf = NULL;
        int i, orderBitSize;

        MP_DIGITS(&rz) = 0;
        MP_DIGITS(&raz4) = 0;
        MP_DIGITS(&tpx) = 0;
        MP_DIGITS(&tpy) = 0;
        for (i = 0; i < 16; i++) {
                MP_DIGITS(&precomp[i][0]) = 0;
                MP_DIGITS(&precomp[i][1]) = 0;
        }
        for (i = 0; i < MAX_SCRATCH; i++) {
                MP_DIGITS(&scratch[i]) = 0;
        }

        ARGCHK(group != NULL, MP_BADARG);
        ARGCHK((n != NULL) && (px != NULL) && (py != NULL), MP_BADARG);

        /* initialize precomputation table */
        MP_CHECKOK(mp_init(&tpx, FLAG(n)));
        MP_CHECKOK(mp_init(&tpy, FLAG(n)));;
        MP_CHECKOK(mp_init(&rz, FLAG(n)));
        MP_CHECKOK(mp_init(&raz4, FLAG(n)));

        for (i = 0; i < 16; i++) {
                MP_CHECKOK(mp_init(&precomp[i][0], FLAG(n)));
                MP_CHECKOK(mp_init(&precomp[i][1], FLAG(n)));
        }
        for (i = 0; i < MAX_SCRATCH; i++) {
                MP_CHECKOK(mp_init(&scratch[i], FLAG(n)));
        }

        /* Set out[8] = P */
        MP_CHECKOK(mp_copy(px, &precomp[8][0]));
        MP_CHECKOK(mp_copy(py, &precomp[8][1]));

        /* Set (tpx, tpy) = 2P */
        MP_CHECKOK(group->
                           point_dbl(&precomp[8][0], &precomp[8][1], &tpx, &tpy,
                                                 group));

        /* Set 3P, 5P, ..., 15P */
        for (i = 8; i < 15; i++) {
                MP_CHECKOK(group->
                                   point_add(&precomp[i][0], &precomp[i][1], &tpx, &tpy,
                                                         &precomp[i + 1][0], &precomp[i + 1][1],
                                                         group));
        }

        /* Set -15P, -13P, ..., -P */
        for (i = 0; i < 8; i++) {
                MP_CHECKOK(mp_copy(&precomp[15 - i][0], &precomp[i][0]));
                MP_CHECKOK(group->meth->
                                   field_neg(&precomp[15 - i][1], &precomp[i][1],
                                                         group->meth));
        }

        /* R = inf */
        MP_CHECKOK(ec_GFp_pt_set_inf_jac(rx, ry, &rz));

        orderBitSize = mpl_significant_bits(&group->order);

        /* Allocate memory for NAF */
#ifdef _KERNEL
        naf = (signed char *) kmem_alloc((orderBitSize + 1), FLAG(n));
#else
        naf = (signed char *) malloc(sizeof(signed char) * (orderBitSize + 1));
        if (naf == NULL) {
                res = MP_MEM;
                goto CLEANUP;
        }
#endif

        /* Compute 5NAF */
        ec_compute_wNAF(naf, orderBitSize, n, 5);

        /* wNAF method */
        for (i = orderBitSize; i >= 0; i--) {
                /* R = 2R */
                ec_GFp_pt_dbl_jm(rx, ry, &rz, &raz4, rx, ry, &rz,
                                             &raz4, scratch, group);
                if (naf[i] != 0) {
                        ec_GFp_pt_add_jm_aff(rx, ry, &rz, &raz4,
                                                                 &precomp[(naf[i] + 15) / 2][0],
                                                                 &precomp[(naf[i] + 15) / 2][1], rx, ry,
                                                                 &rz, &raz4, scratch, group);
                }
        }

        /* convert result S to affine coordinates */
        MP_CHECKOK(ec_GFp_pt_jac2aff(rx, ry, &rz, rx, ry, group));

  CLEANUP:
        for (i = 0; i < MAX_SCRATCH; i++) {
                mp_clear(&scratch[i]);
        }
        for (i = 0; i < 16; i++) {
                mp_clear(&precomp[i][0]);
                mp_clear(&precomp[i][1]);
        }
        mp_clear(&tpx);
        mp_clear(&tpy);
        mp_clear(&rz);
        mp_clear(&raz4);
#ifdef _KERNEL
        kmem_free(naf, (orderBitSize + 1));
#else
        free(naf);
#endif
        return res;
}
Пример #19
0
/*
 * Try to find the two primes based on 2 exponents plus either a prime
 *   or a modulus.
 *
 * In: e, d and either p or n (depending on the setting of hasModulus).
 * Out: p,q.
 * 
 * Step 1, Since d = e**-1 mod phi, we know that d*e == 1 mod phi, or
 *	d*e = 1+k*phi, or d*e-1 = k*phi. since d is less than phi and e is
 *	usually less than d, then k must be an integer between e-1 and 1 
 *	(probably on the order of e).
 * Step 1a, If we were passed just a prime, we can divide k*phi by that
 *      prime-1 and get k*(q-1). This will reduce the size of our division
 *      through the rest of the loop.
 * Step 2, Loop through the values k=e-1 to 1 looking for k. k should be on
 *	the order or e, and e is typically small. This may take a while for
 *	a large random e. We are looking for a k that divides kphi
 *	evenly. Once we find a k that divides kphi evenly, we assume it 
 *	is the true k. It's possible this k is not the 'true' k but has 
 *	swapped factors of p-1 and/or q-1. Because of this, we 
 *	tentatively continue Steps 3-6 inside this loop, and may return looking
 *	for another k on failure.
 * Step 3, Calculate are tentative phi=kphi/k. Note: real phi is (p-1)*(q-1).
 * Step 4a, if we have a prime, kphi is already k*(q-1), so phi is or tenative
 *      q-1. q = phi+1. If k is correct, q should be the right length and 
 *      prime.
 * Step 4b, It's possible q-1 and k could have swapped factors. We now have a
 * 	possible solution that meets our criteria. It may not be the only 
 *      solution, however, so we keep looking. If we find more than one, 
 *      we will fail since we cannot determine which is the correct
 *      solution, and returning the wrong modulus will compromise both
 *      moduli. If no other solution is found, we return the unique solution.
 * Step 5a, If we have the modulus (n=pq), then use the following formula to 
 * 	calculate  s=(p+q): , phi = (p-1)(q-1) = pq  -p-q +1 = n-s+1. so
 *	s=n-phi+1.
 * Step 5b, Use n=pq and s=p+q to solve for p and q as follows:
 *	since q=s-p, then n=p*(s-p)= sp - p^2, rearranging p^2-s*p+n = 0.
 *	from the quadratic equation we have p=1/2*(s+sqrt(s*s-4*n)) and
 *	q=1/2*(s-sqrt(s*s-4*n)) if s*s-4*n is a perfect square, we are DONE.
 *	If it is not, continue in our look looking for another k. NOTE: the
 *	code actually distributes the 1/2 and results in the equations:
 *	sqrt = sqrt(s/2*s/2-n), p=s/2+sqrt, q=s/2-sqrt. The algebra saves us
 *	and extra divide by 2 and a multiply by 4.
 * 
 * This will return p & q. q may be larger than p in the case that p was given
 * and it was the smaller prime.
 */
static mp_err
rsa_get_primes_from_exponents(mp_int *e, mp_int *d, mp_int *p, mp_int *q,
			      mp_int *n, PRBool hasModulus, 
			      unsigned int keySizeInBits)
{
    mp_int kphi; /* k*phi */
    mp_int k;    /* current guess at 'k' */
    mp_int phi;  /* (p-1)(q-1) */
    mp_int s;    /* p+q/2 (s/2 in the algebra) */
    mp_int r;    /* remainder */
    mp_int tmp; /* p-1 if p is given, n+1 is modulus is given */
    mp_int sqrt; /* sqrt(s/2*s/2-n) */
    mp_err err = MP_OKAY;
    unsigned int order_k;

    MP_DIGITS(&kphi) = 0;
    MP_DIGITS(&phi) = 0;
    MP_DIGITS(&s) = 0;
    MP_DIGITS(&k) = 0;
    MP_DIGITS(&r) = 0;
    MP_DIGITS(&tmp) = 0;
    MP_DIGITS(&sqrt) = 0;
    CHECK_MPI_OK( mp_init(&kphi) );
    CHECK_MPI_OK( mp_init(&phi) );
    CHECK_MPI_OK( mp_init(&s) );
    CHECK_MPI_OK( mp_init(&k) );
    CHECK_MPI_OK( mp_init(&r) );
    CHECK_MPI_OK( mp_init(&tmp) );
    CHECK_MPI_OK( mp_init(&sqrt) );

    /* our algorithm looks for a factor k whose maximum size is dependent
     * on the size of our smallest exponent, which had better be the public
     * exponent (if it's the private, the key is vulnerable to a brute force
     * attack).
     * 
     * since our factor search is linear, we need to limit the maximum
     * size of the public key. this should not be a problem normally, since 
     * public keys are usually small. 
     *
     * if we want to handle larger public key sizes, we should have
     * a version which tries to 'completely' factor k*phi (where completely
     * means 'factor into primes, or composites with which are products of
     * large primes). Once we have all the factors, we can sort them out and
     * try different combinations to form our phi. The risk is if (p-1)/2,
     * (q-1)/2, and k are all large primes. In any case if the public key
     * is small (order of 20 some bits), then a linear search for k is 
     * manageable.
     */
    if (mpl_significant_bits(e) > 23) {
	err=MP_RANGE;
	goto cleanup;
    }

    /* calculate k*phi = e*d - 1 */
    CHECK_MPI_OK( mp_mul(e, d, &kphi) );
    CHECK_MPI_OK( mp_sub_d(&kphi, 1, &kphi) );


    /* kphi is (e*d)-1, which is the same as k*(p-1)(q-1)
     * d < (p-1)(q-1), therefor k must be less than e-1
     * We can narrow down k even more, though. Since p and q are odd and both 
     * have their high bit set, then we know that phi must be on order of 
     * keySizeBits.
     */
    order_k = (unsigned)mpl_significant_bits(&kphi) - keySizeInBits;

    /* for (k=kinit; order(k) >= order_k; k--) { */
    /* k=kinit: k can't be bigger than  kphi/2^(keySizeInBits -1) */
    CHECK_MPI_OK( mp_2expt(&k,keySizeInBits-1) );
    CHECK_MPI_OK( mp_div(&kphi, &k, &k, NULL));
    if (mp_cmp(&k,e) >= 0) {
	/* also can't be bigger then e-1 */
        CHECK_MPI_OK( mp_sub_d(e, 1, &k) );
    }

    /* calculate our temp value */
    /* This saves recalculating this value when the k guess is wrong, which
     * is reasonably frequent. */
    /* for the modulus case, tmp = n+1 (used to calculate p+q = tmp - phi) */
    /* for the prime case, tmp = p-1 (used to calculate q-1= phi/tmp) */
    if (hasModulus) {
	CHECK_MPI_OK( mp_add_d(n, 1, &tmp) );
    } else {
	CHECK_MPI_OK( mp_sub_d(p, 1, &tmp) );
	CHECK_MPI_OK(mp_div(&kphi,&tmp,&kphi,&r));
	if (mp_cmp_z(&r) != 0) {
	    /* p-1 doesn't divide kphi, some parameter wasn't correct */
	    err=MP_RANGE;
	    goto cleanup;
	}
	mp_zero(q);
	/* kphi is now k*(q-1) */
    }

    /* rest of the for loop */
    for (; (err == MP_OKAY) && (mpl_significant_bits(&k) >= order_k); 
						err = mp_sub_d(&k, 1, &k)) {
	/* looking for k as a factor of kphi */
	CHECK_MPI_OK(mp_div(&kphi,&k,&phi,&r));
	if (mp_cmp_z(&r) != 0) {
	    /* not a factor, try the next one */
	    continue;
	}
	/* we have a possible phi, see if it works */
	if (!hasModulus) {
	    if ((unsigned)mpl_significant_bits(&phi) != keySizeInBits/2) {
		/* phi is not the right size */
		continue;
	    }
	    /* phi should be divisible by 2, since
	     * q is odd and phi=(q-1). */
	    if (mpp_divis_d(&phi,2) == MP_NO) {
		/* phi is not divisible by 4 */
		continue;
	    }
	    /* we now have a candidate for the second prime */
	    CHECK_MPI_OK(mp_add_d(&phi, 1, &tmp));
	    
	    /* check to make sure it is prime */
	    err = rsa_is_prime(&tmp);
	    if (err != MP_OKAY) {
		if (err == MP_NO) {
		    /* No, then we still have the wrong phi */
		    err = MP_OKAY;
        	    continue;
		}
		goto cleanup;
	    }
	    /*
	     * It is possible that we have the wrong phi if 
	     * k_guess*(q_guess-1) = k*(q-1) (k and q-1 have swapped factors).
	     * since our q_quess is prime, however. We have found a valid
	     * rsa key because:
	     *   q is the correct order of magnitude.
	     *   phi = (p-1)(q-1) where p and q are both primes.
	     *   e*d mod phi = 1.
	     * There is no way to know from the info given if this is the 
	     * original key. We never want to return the wrong key because if
	     * two moduli with the same factor is known, then euclid's gcd
	     * algorithm can be used to find that factor. Even though the 
	     * caller didn't pass the original modulus, it doesn't mean the
	     * modulus wasn't known or isn't available somewhere. So to be safe
	     * if we can't be sure we have the right q, we don't return any.
	     * 
	     * So to make sure we continue looking for other valid q's. If none
	     * are found, then we can safely return this one, otherwise we just
	     * fail */
	    if (mp_cmp_z(q) != 0) {
		/* this is the second valid q, don't return either, 
		 * just fail */
		err = MP_RANGE;
		break;
	    }
	    /* we only have one q so far, save it and if no others are found,
	     * it's safe to return it */
	    CHECK_MPI_OK(mp_copy(&tmp, q));
	    continue;
	}
	/* test our tentative phi */
	/* phi should be the correct order */
	if ((unsigned)mpl_significant_bits(&phi) != keySizeInBits) {
	    /* phi is not the right size */
	    continue;
	}
	/* phi should be divisible by 4, since
	 * p and q are odd and phi=(p-1)(q-1). */
	if (mpp_divis_d(&phi,4) == MP_NO) {
	    /* phi is not divisible by 4 */
	    continue;
	}
	/* n was given, calculate s/2=(p+q)/2 */
	CHECK_MPI_OK( mp_sub(&tmp, &phi, &s) );
	CHECK_MPI_OK( mp_div_2(&s, &s) );

	/* calculate sqrt(s/2*s/2-n) */
	CHECK_MPI_OK(mp_sqr(&s,&sqrt));
	CHECK_MPI_OK(mp_sub(&sqrt,n,&r));  /* r as a tmp */
	CHECK_MPI_OK(mp_sqrt(&r,&sqrt));
	/* make sure it's a perfect square */
	/* r is our original value we took the square root of */
	/* q is the square of our tentative square root. They should be equal*/
	CHECK_MPI_OK(mp_sqr(&sqrt,q)); /* q as a tmp */
	if (mp_cmp(&r,q) != 0) {
	    /* sigh according to the doc, mp_sqrt could return sqrt-1 */
	   CHECK_MPI_OK(mp_add_d(&sqrt,1,&sqrt));
	   CHECK_MPI_OK(mp_sqr(&sqrt,q));
	   if (mp_cmp(&r,q) != 0) {
		/* s*s-n not a perfect square, this phi isn't valid, find 			 * another.*/
		continue;
	    }
	}

	/* NOTE: In this case we know we have the one and only answer.
	 * "Why?", you ask. Because:
	 *    1) n is a composite of two large primes (or it wasn't a
	 *       valid RSA modulus).
	 *    2) If we know any number such that x^2-n is a perfect square 
	 *       and x is not (n+1)/2, then we can calculate 2 non-trivial
	 *       factors of n.
	 *    3) Since we know that n has only 2 non-trivial prime factors, 
	 *       we know the two factors we have are the only possible factors.
	 */

	/* Now we are home free to calculate p and q */
	/* p = s/2 + sqrt, q= s/2 - sqrt */
	CHECK_MPI_OK(mp_add(&s,&sqrt,p));
	CHECK_MPI_OK(mp_sub(&s,&sqrt,q));
	break;
    }
    if ((unsigned)mpl_significant_bits(&k) < order_k) {
	if (hasModulus || (mp_cmp_z(q) == 0)) {
	    /* If we get here, something was wrong with the parameters we 
	     * were given */
	    err = MP_RANGE; 
	}
    }
cleanup:
    mp_clear(&kphi);
    mp_clear(&phi);
    mp_clear(&s);
    mp_clear(&k);
    mp_clear(&r);
    mp_clear(&tmp);
    mp_clear(&sqrt);
    return err;
}