Example #1
0
/* 
 * Computes scalar point multiplication pointQ = k1 * G + k2 * pointP for
 * the curve whose parameters are encoded in params with base point G.
 */
SECStatus 
ec_points_mul(const ECParams *params, const mp_int *k1, const mp_int *k2,
             const SECItem *pointP, SECItem *pointQ)
{
    mp_int Px, Py, Qx, Qy;
    mp_int Gx, Gy, order, irreducible, a, b;
#if 0 /* currently don't support non-named curves */
    unsigned int irr_arr[5];
#endif
    ECGroup *group = NULL;
    SECStatus rv = SECFailure;
    mp_err err = MP_OKAY;
    int len;

#if EC_DEBUG
    int i;
    char mpstr[256];

    printf("ec_points_mul: params [len=%d]:", params->DEREncoding.len);
    for (i = 0; i < params->DEREncoding.len; i++) 
	    printf("%02x:", params->DEREncoding.data[i]);
    printf("\n");

	if (k1 != NULL) {
		mp_tohex(k1, mpstr);
		printf("ec_points_mul: scalar k1: %s\n", mpstr);
		mp_todecimal(k1, mpstr);
		printf("ec_points_mul: scalar k1: %s (dec)\n", mpstr);
	}

	if (k2 != NULL) {
		mp_tohex(k2, mpstr);
		printf("ec_points_mul: scalar k2: %s\n", mpstr);
		mp_todecimal(k2, mpstr);
		printf("ec_points_mul: scalar k2: %s (dec)\n", mpstr);
	}

	if (pointP != NULL) {
		printf("ec_points_mul: pointP [len=%d]:", pointP->len);
		for (i = 0; i < pointP->len; i++) 
			printf("%02x:", pointP->data[i]);
		printf("\n");
	}
#endif

	/* NOTE: We only support uncompressed points for now */
	len = (params->fieldID.size + 7) >> 3;
	if (pointP != NULL) {
		if ((pointP->data[0] != EC_POINT_FORM_UNCOMPRESSED) ||
			(pointP->len != (2 * len + 1))) {
			PORT_SetError(SEC_ERROR_UNSUPPORTED_EC_POINT_FORM);
			return SECFailure;
		};
	}

	MP_DIGITS(&Px) = 0;
	MP_DIGITS(&Py) = 0;
	MP_DIGITS(&Qx) = 0;
	MP_DIGITS(&Qy) = 0;
	MP_DIGITS(&Gx) = 0;
	MP_DIGITS(&Gy) = 0;
	MP_DIGITS(&order) = 0;
	MP_DIGITS(&irreducible) = 0;
	MP_DIGITS(&a) = 0;
	MP_DIGITS(&b) = 0;
	CHECK_MPI_OK( mp_init(&Px) );
	CHECK_MPI_OK( mp_init(&Py) );
	CHECK_MPI_OK( mp_init(&Qx) );
	CHECK_MPI_OK( mp_init(&Qy) );
	CHECK_MPI_OK( mp_init(&Gx) );
	CHECK_MPI_OK( mp_init(&Gy) );
	CHECK_MPI_OK( mp_init(&order) );
	CHECK_MPI_OK( mp_init(&irreducible) );
	CHECK_MPI_OK( mp_init(&a) );
	CHECK_MPI_OK( mp_init(&b) );

	if ((k2 != NULL) && (pointP != NULL)) {
		/* Initialize Px and Py */
		CHECK_MPI_OK( mp_read_unsigned_octets(&Px, pointP->data + 1, (mp_size) len) );
		CHECK_MPI_OK( mp_read_unsigned_octets(&Py, pointP->data + 1 + len, (mp_size) len) );
	}

	/* construct from named params, if possible */
	if (params->name != ECCurve_noName) {
		group = ECGroup_fromName(params->name);
	}

#if 0 /* currently don't support non-named curves */
	if (group == NULL) {
		/* Set up mp_ints containing the curve coefficients */
		CHECK_MPI_OK( mp_read_unsigned_octets(&Gx, params->base.data + 1, 
										  (mp_size) len) );
		CHECK_MPI_OK( mp_read_unsigned_octets(&Gy, params->base.data + 1 + len, 
										  (mp_size) len) );
		SECITEM_TO_MPINT( params->order, &order );
		SECITEM_TO_MPINT( params->curve.a, &a );
		SECITEM_TO_MPINT( params->curve.b, &b );
		if (params->fieldID.type == ec_field_GFp) {
			SECITEM_TO_MPINT( params->fieldID.u.prime, &irreducible );
			group = ECGroup_consGFp(&irreducible, &a, &b, &Gx, &Gy, &order, params->cofactor);
		} else {
			SECITEM_TO_MPINT( params->fieldID.u.poly, &irreducible );
			irr_arr[0] = params->fieldID.size;
			irr_arr[1] = params->fieldID.k1;
			irr_arr[2] = params->fieldID.k2;
			irr_arr[3] = params->fieldID.k3;
			irr_arr[4] = 0;
			group = ECGroup_consGF2m(&irreducible, irr_arr, &a, &b, &Gx, &Gy, &order, params->cofactor);
		}
	}
#endif
	if (group == NULL)
		goto cleanup;

	if ((k2 != NULL) && (pointP != NULL)) {
		CHECK_MPI_OK( ECPoints_mul(group, k1, k2, &Px, &Py, &Qx, &Qy) );
	} else {
		CHECK_MPI_OK( ECPoints_mul(group, k1, NULL, NULL, NULL, &Qx, &Qy) );
    }

    /* Construct the SECItem representation of point Q */
    pointQ->data[0] = EC_POINT_FORM_UNCOMPRESSED;
    CHECK_MPI_OK( mp_to_fixlen_octets(&Qx, pointQ->data + 1,
	                              (mp_size) len) );
    CHECK_MPI_OK( mp_to_fixlen_octets(&Qy, pointQ->data + 1 + len,
	                              (mp_size) len) );

    rv = SECSuccess;

#if EC_DEBUG
    printf("ec_points_mul: pointQ [len=%d]:", pointQ->len);
    for (i = 0; i < pointQ->len; i++) 
	    printf("%02x:", pointQ->data[i]);
    printf("\n");
#endif

cleanup:
    ECGroup_free(group);
    mp_clear(&Px);
    mp_clear(&Py);
    mp_clear(&Qx);
    mp_clear(&Qy);
    mp_clear(&Gx);
    mp_clear(&Gy);
    mp_clear(&order);
    mp_clear(&irreducible);
    mp_clear(&a);
    mp_clear(&b);
    if (err) {
	MP_TO_SEC_ERROR(err);
	rv = SECFailure;
    }

    return rv;
}
Example #2
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;
}