Exemple #1
0
/* Converts a point P(px, py) from affine coordinates to Jacobian
 * projective coordinates R(rx, ry, rz). Assumes input is already
 * field-encoded using field_enc, and returns output that is still
 * field-encoded. */
mp_err
ec_GFp_pt_aff2jac(const mp_int *px, const mp_int *py, mp_int *rx,
				  mp_int *ry, mp_int *rz, const ECGroup *group)
{
	mp_err res = MP_OKAY;

	if (ec_GFp_pt_is_inf_aff(px, py) == MP_YES) {
		MP_CHECKOK(ec_GFp_pt_set_inf_jac(rx, ry, rz));
	} else {
		MP_CHECKOK(mp_copy(px, rx));
		MP_CHECKOK(mp_copy(py, ry));
		MP_CHECKOK(mp_set_int(rz, 1));
		if (group->meth->field_enc) {
			MP_CHECKOK(group->meth->field_enc(rz, rz, group->meth));
		}
	}
  CLEANUP:
	return res;
}
Exemple #2
0
/* Computes R = P + Q where R is (rx, ry, rz), P is (px, py, pz) and Q is
 * (qx, qy, 1).  Elliptic curve points P, Q, and R can all be identical.
 * Uses mixed Modified_Jacobian-affine coordinates. Assumes input is
 * already field-encoded using field_enc, and returns output that is still
 * field-encoded. */
mp_err
ec_GFp_pt_add_jm_aff(const mp_int *px, const mp_int *py, const mp_int *pz,
                                         const mp_int *paz4, const mp_int *qx,
                                         const mp_int *qy, mp_int *rx, mp_int *ry, mp_int *rz,
                                         mp_int *raz4, mp_int scratch[], const ECGroup *group)
{
        mp_err res = MP_OKAY;
        mp_int *A, *B, *C, *D, *C2, *C3;

        A = &scratch[0];
        B = &scratch[1];
        C = &scratch[2];
        D = &scratch[3];
        C2 = &scratch[4];
        C3 = &scratch[5];

#if MAX_SCRATCH < 6
#error "Scratch array defined too small "
#endif

        /* If either P or Q is the point at infinity, then return the other
         * point */
        if (ec_GFp_pt_is_inf_jac(px, py, pz) == MP_YES) {
                MP_CHECKOK(ec_GFp_pt_aff2jac(qx, qy, rx, ry, rz, group));
                MP_CHECKOK(group->meth->field_sqr(rz, raz4, group->meth));
                MP_CHECKOK(group->meth->field_sqr(raz4, raz4, group->meth));
                MP_CHECKOK(group->meth->
                                   field_mul(raz4, &group->curvea, raz4, group->meth));
                goto CLEANUP;
        }
        if (ec_GFp_pt_is_inf_aff(qx, qy) == MP_YES) {
                MP_CHECKOK(mp_copy(px, rx));
                MP_CHECKOK(mp_copy(py, ry));
                MP_CHECKOK(mp_copy(pz, rz));
                MP_CHECKOK(mp_copy(paz4, raz4));
                goto CLEANUP;
        }

        /* A = qx * pz^2, B = qy * pz^3 */
        MP_CHECKOK(group->meth->field_sqr(pz, A, group->meth));
        MP_CHECKOK(group->meth->field_mul(A, pz, B, group->meth));
        MP_CHECKOK(group->meth->field_mul(A, qx, A, group->meth));
        MP_CHECKOK(group->meth->field_mul(B, qy, B, group->meth));

        /* C = A - px, D = B - py */
        MP_CHECKOK(group->meth->field_sub(A, px, C, group->meth));
        MP_CHECKOK(group->meth->field_sub(B, py, D, group->meth));

        /* C2 = C^2, C3 = C^3 */
        MP_CHECKOK(group->meth->field_sqr(C, C2, group->meth));
        MP_CHECKOK(group->meth->field_mul(C, C2, C3, group->meth));

        /* rz = pz * C */
        MP_CHECKOK(group->meth->field_mul(pz, C, rz, group->meth));

        /* C = px * C^2 */
        MP_CHECKOK(group->meth->field_mul(px, C2, C, group->meth));
        /* A = D^2 */
        MP_CHECKOK(group->meth->field_sqr(D, A, group->meth));

        /* rx = D^2 - (C^3 + 2 * (px * C^2)) */
        MP_CHECKOK(group->meth->field_add(C, C, rx, group->meth));
        MP_CHECKOK(group->meth->field_add(C3, rx, rx, group->meth));
        MP_CHECKOK(group->meth->field_sub(A, rx, rx, group->meth));

        /* C3 = py * C^3 */
        MP_CHECKOK(group->meth->field_mul(py, C3, C3, group->meth));

        /* ry = D * (px * C^2 - rx) - py * C^3 */
        MP_CHECKOK(group->meth->field_sub(C, rx, ry, group->meth));
        MP_CHECKOK(group->meth->field_mul(D, ry, ry, group->meth));
        MP_CHECKOK(group->meth->field_sub(ry, C3, ry, group->meth));

        /* raz4 = a * rz^4 */
        MP_CHECKOK(group->meth->field_sqr(rz, raz4, group->meth));
        MP_CHECKOK(group->meth->field_sqr(raz4, raz4, group->meth));
        MP_CHECKOK(group->meth->
                           field_mul(raz4, &group->curvea, raz4, group->meth));
CLEANUP:
        return res;
}
Exemple #3
0
/* Tests a point multiplication (various algorithms) */
mp_err
testPointMul(ECGroup *ecgroup)
{
	mp_err res;
	char s[1000];
	mp_int rx, ry, order_1;

	/* Init */
	MP_DIGITS(&rx) = 0;
	MP_DIGITS(&ry) = 0;
	MP_DIGITS(&order_1) = 0;

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

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

	/* Test Algorithm 1: Jacobian-Affine Double & Add */
	ec_GFp_pt_mul_jac_fp(&order_1, &ecgroup->genx, &ecgroup->geny, &rx,
						 &ry, ecgroup);
	MP_CHECKOK(ecgroup->meth->field_neg(&ry, &ry, ecgroup->meth));
	if ((mp_cmp(&rx, &ecgroup->genx) != 0)
		|| (mp_cmp(&ry, &ecgroup->geny) != 0)) {
		printf
			("  Error: ec_GFp_pt_mul_jac_fp invalid result (expected (- base point)).\n");
		MP_CHECKOK(mp_toradix(&rx, s, 16));
		printf("rx   %s\n", s);
		MP_CHECKOK(mp_toradix(&ry, s, 16));
		printf("ry   %s\n", s);
		res = MP_NO;
		goto CLEANUP;
	}

	ec_GFp_pt_mul_jac_fp(&ecgroup->order, &ecgroup->genx, &ecgroup->geny,
						 &rx, &ry, ecgroup);
	if (ec_GFp_pt_is_inf_aff(&rx, &ry) != MP_YES) {
		printf
			("  Error: ec_GFp_pt_mul_jac_fp invalid result (expected point at infinity.\n");
		MP_CHECKOK(mp_toradix(&rx, s, 16));
		printf("rx   %s\n", s);
		MP_CHECKOK(mp_toradix(&ry, s, 16));
		printf("ry   %s\n", s);
		res = MP_NO;
		goto CLEANUP;
	}

	/* Test Algorithm 2: 4-bit Window in Jacobian */
	ec_GFp_point_mul_jac_4w_fp(&order_1, &ecgroup->genx, &ecgroup->geny,
							   &rx, &ry, ecgroup);
	MP_CHECKOK(ecgroup->meth->field_neg(&ry, &ry, ecgroup->meth));
	if ((mp_cmp(&rx, &ecgroup->genx) != 0)
		|| (mp_cmp(&ry, &ecgroup->geny) != 0)) {
		printf
			("  Error: ec_GFp_point_mul_jac_4w_fp invalid result (expected (- base point)).\n");
		MP_CHECKOK(mp_toradix(&rx, s, 16));
		printf("rx   %s\n", s);
		MP_CHECKOK(mp_toradix(&ry, s, 16));
		printf("ry   %s\n", s);
		res = MP_NO;
		goto CLEANUP;
	}

	ec_GFp_point_mul_jac_4w_fp(&ecgroup->order, &ecgroup->genx,
							   &ecgroup->geny, &rx, &ry, ecgroup);
	if (ec_GFp_pt_is_inf_aff(&rx, &ry) != MP_YES) {
		printf
			("  Error: ec_GFp_point_mul_jac_4w_fp invalid result (expected point at infinity.\n");
		MP_CHECKOK(mp_toradix(&rx, s, 16));
		printf("rx   %s\n", s);
		MP_CHECKOK(mp_toradix(&ry, s, 16));
		printf("ry   %s\n", s);
		res = MP_NO;
		goto CLEANUP;
	}

	/* Test Algorithm 3: wNAF with modified Jacobian coordinates */
	ec_GFp_point_mul_wNAF_fp(&order_1, &ecgroup->genx, &ecgroup->geny, &rx,
							 &ry, ecgroup);
	MP_CHECKOK(ecgroup->meth->field_neg(&ry, &ry, ecgroup->meth));
	if ((mp_cmp(&rx, &ecgroup->genx) != 0)
		|| (mp_cmp(&ry, &ecgroup->geny) != 0)) {
		printf
			("  Error: ec_GFp_pt_mul_wNAF_fp invalid result (expected (- base point)).\n");
		MP_CHECKOK(mp_toradix(&rx, s, 16));
		printf("rx   %s\n", s);
		MP_CHECKOK(mp_toradix(&ry, s, 16));
		printf("ry   %s\n", s);
		res = MP_NO;
		goto CLEANUP;
	}

	ec_GFp_point_mul_wNAF_fp(&ecgroup->order, &ecgroup->genx,
							 &ecgroup->geny, &rx, &ry, ecgroup);
	if (ec_GFp_pt_is_inf_aff(&rx, &ry) != MP_YES) {
		printf
			("  Error: ec_GFp_pt_mul_wNAF_fp invalid result (expected point at infinity.\n");
		MP_CHECKOK(mp_toradix(&rx, s, 16));
		printf("rx   %s\n", s);
		MP_CHECKOK(mp_toradix(&ry, s, 16));
		printf("ry   %s\n", s);
		res = MP_NO;
		goto CLEANUP;
	}

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

	return res;
}
Exemple #4
0
/* Computes R = P + Q where R is (rx, ry, rz), P is (px, py, pz) and Q is
 * (qx, qy, 1).  Elliptic curve points P, Q, and R can all 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 equation (2) from Brown, Hankerson, Lopez, and
 * Menezes. Software Implementation of the NIST Elliptic Curves Over Prime
 * Fields. */
mp_err
ec_GFp_pt_add_jac_aff(const mp_int *px, const mp_int *py, const mp_int *pz,
					  const mp_int *qx, const mp_int *qy, mp_int *rx,
					  mp_int *ry, mp_int *rz, const ECGroup *group)
{
	mp_err res = MP_OKAY;
	mp_int A, B, C, D, C2, C3;

	MP_DIGITS(&A) = 0;
	MP_DIGITS(&B) = 0;
	MP_DIGITS(&C) = 0;
	MP_DIGITS(&D) = 0;
	MP_DIGITS(&C2) = 0;
	MP_DIGITS(&C3) = 0;
	MP_CHECKOK(mp_init(&A));
	MP_CHECKOK(mp_init(&B));
	MP_CHECKOK(mp_init(&C));
	MP_CHECKOK(mp_init(&D));
	MP_CHECKOK(mp_init(&C2));
	MP_CHECKOK(mp_init(&C3));

	/* If either P or Q is the point at infinity, then return the other
	 * point */
	if (ec_GFp_pt_is_inf_jac(px, py, pz) == MP_YES) {
		MP_CHECKOK(ec_GFp_pt_aff2jac(qx, qy, rx, ry, rz, group));
		goto CLEANUP;
	}
	if (ec_GFp_pt_is_inf_aff(qx, qy) == MP_YES) {
		MP_CHECKOK(mp_copy(px, rx));
		MP_CHECKOK(mp_copy(py, ry));
		MP_CHECKOK(mp_copy(pz, rz));
		goto CLEANUP;
	}

	/* A = qx * pz^2, B = qy * pz^3 */
	MP_CHECKOK(group->meth->field_sqr(pz, &A, group->meth));
	MP_CHECKOK(group->meth->field_mul(&A, pz, &B, group->meth));
	MP_CHECKOK(group->meth->field_mul(&A, qx, &A, group->meth));
	MP_CHECKOK(group->meth->field_mul(&B, qy, &B, group->meth));

	/* C = A - px, D = B - py */
	MP_CHECKOK(group->meth->field_sub(&A, px, &C, group->meth));
	MP_CHECKOK(group->meth->field_sub(&B, py, &D, group->meth));

	if (mp_cmp_z(&C) == 0) {
		/* P == Q or P == -Q */
		if (mp_cmp_z(&D) == 0) {
			/* P == Q */
			/* It is cheaper to double (qx, qy, 1) than (px, py, pz). */
			MP_DIGIT(&D, 0) = 1; /* Set D to 1. */
			MP_CHECKOK(ec_GFp_pt_dbl_jac(qx, qy, &D, rx, ry, rz, group));
		} else {
			/* P == -Q */
			MP_CHECKOK(ec_GFp_pt_set_inf_jac(rx, ry, rz));
		}
		goto CLEANUP;
	}

	/* C2 = C^2, C3 = C^3 */
	MP_CHECKOK(group->meth->field_sqr(&C, &C2, group->meth));
	MP_CHECKOK(group->meth->field_mul(&C, &C2, &C3, group->meth));

	/* rz = pz * C */
	MP_CHECKOK(group->meth->field_mul(pz, &C, rz, group->meth));

	/* C = px * C^2 */
	MP_CHECKOK(group->meth->field_mul(px, &C2, &C, group->meth));
	/* A = D^2 */
	MP_CHECKOK(group->meth->field_sqr(&D, &A, group->meth));

	/* rx = D^2 - (C^3 + 2 * (px * C^2)) */
	MP_CHECKOK(group->meth->field_add(&C, &C, rx, group->meth));
	MP_CHECKOK(group->meth->field_add(&C3, rx, rx, group->meth));
	MP_CHECKOK(group->meth->field_sub(&A, rx, rx, group->meth));

	/* C3 = py * C^3 */
	MP_CHECKOK(group->meth->field_mul(py, &C3, &C3, group->meth));

	/* ry = D * (px * C^2 - rx) - py * C^3 */
	MP_CHECKOK(group->meth->field_sub(&C, rx, ry, group->meth));
	MP_CHECKOK(group->meth->field_mul(&D, ry, ry, group->meth));
	MP_CHECKOK(group->meth->field_sub(ry, &C3, ry, group->meth));

  CLEANUP:
	mp_clear(&A);
	mp_clear(&B);
	mp_clear(&C);
	mp_clear(&D);
	mp_clear(&C2);
	mp_clear(&C3);
	return res;
}
Exemple #5
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;
}
Exemple #6
0
/* Computes R = P + Q based on IEEE P1363 A.10.1. Elliptic curve points P,
 * Q, and R can all 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_add_aff(const mp_int *px, const mp_int *py, const mp_int *qx,
                  const mp_int *qy, mp_int *rx, mp_int *ry,
                  const ECGroup *group)
{
    mp_err res = MP_OKAY;
    mp_int lambda, temp, tempx, tempy;

    MP_DIGITS(&lambda) = 0;
    MP_DIGITS(&temp) = 0;
    MP_DIGITS(&tempx) = 0;
    MP_DIGITS(&tempy) = 0;
    MP_CHECKOK(mp_init(&lambda));
    MP_CHECKOK(mp_init(&temp));
    MP_CHECKOK(mp_init(&tempx));
    MP_CHECKOK(mp_init(&tempy));
    /* if P = inf, then R = Q */
    if (ec_GFp_pt_is_inf_aff(px, py) == 0) {
        MP_CHECKOK(mp_copy(qx, rx));
        MP_CHECKOK(mp_copy(qy, ry));
        res = MP_OKAY;
        goto CLEANUP;
    }
    /* if Q = inf, then R = P */
    if (ec_GFp_pt_is_inf_aff(qx, qy) == 0) {
        MP_CHECKOK(mp_copy(px, rx));
        MP_CHECKOK(mp_copy(py, ry));
        res = MP_OKAY;
        goto CLEANUP;
    }
    /* if px != qx, then lambda = (py-qy) / (px-qx) */
    if (mp_cmp(px, qx) != 0) {
        MP_CHECKOK(group->meth->field_sub(py, qy, &tempy, group->meth));
        MP_CHECKOK(group->meth->field_sub(px, qx, &tempx, group->meth));
        MP_CHECKOK(group->meth->field_div(&tempy, &tempx, &lambda, group->meth));
    } else {
        /* if py != qy or qy = 0, then R = inf */
        if (((mp_cmp(py, qy) != 0)) || (mp_cmp_z(qy) == 0)) {
            mp_zero(rx);
            mp_zero(ry);
            res = MP_OKAY;
            goto CLEANUP;
        }
        /* lambda = (3qx^2+a) / (2qy) */
        MP_CHECKOK(group->meth->field_sqr(qx, &tempx, group->meth));
        MP_CHECKOK(mp_set_int(&temp, 3));
        if (group->meth->field_enc) {
            MP_CHECKOK(group->meth->field_enc(&temp, &temp, group->meth));
        }
        MP_CHECKOK(group->meth->field_mul(&tempx, &temp, &tempx, group->meth));
        MP_CHECKOK(group->meth->field_add(&tempx, &group->curvea, &tempx, group->meth));
        MP_CHECKOK(mp_set_int(&temp, 2));
        if (group->meth->field_enc) {
            MP_CHECKOK(group->meth->field_enc(&temp, &temp, group->meth));
        }
        MP_CHECKOK(group->meth->field_mul(qy, &temp, &tempy, group->meth));
        MP_CHECKOK(group->meth->field_div(&tempx, &tempy, &lambda, group->meth));
    }
    /* rx = lambda^2 - px - qx */
    MP_CHECKOK(group->meth->field_sqr(&lambda, &tempx, group->meth));
    MP_CHECKOK(group->meth->field_sub(&tempx, px, &tempx, group->meth));
    MP_CHECKOK(group->meth->field_sub(&tempx, qx, &tempx, group->meth));
    /* ry = (x1-x2) * lambda - y1 */
    MP_CHECKOK(group->meth->field_sub(qx, &tempx, &tempy, group->meth));
    MP_CHECKOK(group->meth->field_mul(&tempy, &lambda, &tempy, group->meth));
    MP_CHECKOK(group->meth->field_sub(&tempy, qy, &tempy, group->meth));
    MP_CHECKOK(mp_copy(&tempx, rx));
    MP_CHECKOK(mp_copy(&tempy, ry));

CLEANUP:
    mp_clear(&lambda);
    mp_clear(&temp);
    mp_clear(&tempx);
    mp_clear(&tempy);
    return res;
}
Exemple #7
0
/* Validates a point on a GFp curve. */
mp_err
ec_GFp_validate_point(const mp_int *px, const mp_int *py, const ECGroup *group)
{
    mp_err res = MP_NO;
    mp_int accl, accr, tmp, pxt, pyt;

    MP_DIGITS(&accl) = 0;
    MP_DIGITS(&accr) = 0;
    MP_DIGITS(&tmp) = 0;
    MP_DIGITS(&pxt) = 0;
    MP_DIGITS(&pyt) = 0;
    MP_CHECKOK(mp_init(&accl));
    MP_CHECKOK(mp_init(&accr));
    MP_CHECKOK(mp_init(&tmp));
    MP_CHECKOK(mp_init(&pxt));
    MP_CHECKOK(mp_init(&pyt));

    /* 1: Verify that publicValue is not the point at infinity */
    if (ec_GFp_pt_is_inf_aff(px, py) == MP_YES) {
        res = MP_NO;
        goto CLEANUP;
    }
    /* 2: Verify that the coordinates of publicValue are elements
     *    of the field.
     */
    if ((MP_SIGN(px) == MP_NEG) || (mp_cmp(px, &group->meth->irr) >= 0) ||
        (MP_SIGN(py) == MP_NEG) || (mp_cmp(py, &group->meth->irr) >= 0)) {
        res = MP_NO;
        goto CLEANUP;
    }
    /* 3: Verify that publicValue is on the curve. */
    if (group->meth->field_enc) {
        group->meth->field_enc(px, &pxt, group->meth);
        group->meth->field_enc(py, &pyt, group->meth);
    } else {
        MP_CHECKOK(mp_copy(px, &pxt));
        MP_CHECKOK(mp_copy(py, &pyt));
    }
    /* left-hand side: y^2  */
    MP_CHECKOK(group->meth->field_sqr(&pyt, &accl, group->meth));
    /* right-hand side: x^3 + a*x + b = (x^2 + a)*x + b by Horner's rule */
    MP_CHECKOK(group->meth->field_sqr(&pxt, &tmp, group->meth));
    MP_CHECKOK(group->meth->field_add(&tmp, &group->curvea, &tmp, group->meth));
    MP_CHECKOK(group->meth->field_mul(&tmp, &pxt, &accr, group->meth));
    MP_CHECKOK(group->meth->field_add(&accr, &group->curveb, &accr, group->meth));
    /* check LHS - RHS == 0 */
    MP_CHECKOK(group->meth->field_sub(&accl, &accr, &accr, group->meth));
    if (mp_cmp_z(&accr) != 0) {
        res = MP_NO;
        goto CLEANUP;
    }
    /* 4: Verify that the order of the curve times the publicValue
     *    is the point at infinity.
     */
    MP_CHECKOK(ECPoint_mul(group, &group->order, px, py, &pxt, &pyt));
    if (ec_GFp_pt_is_inf_aff(&pxt, &pyt) != MP_YES) {
        res = MP_NO;
        goto CLEANUP;
    }

    res = MP_YES;

CLEANUP:
    mp_clear(&accl);
    mp_clear(&accr);
    mp_clear(&tmp);
    mp_clear(&pxt);
    mp_clear(&pyt);
    return res;
}
Exemple #8
0
/* Computes R = P + Q where R is (rx, ry, rz), P is (px, py, pz) and Q is
 * (qx, qy, 1).  Elliptic curve points P, Q, and R can all be identical.
 * Uses mixed Modified_Jacobian-affine coordinates. Assumes input is
 * already field-encoded using field_enc, and returns output that is still
 * field-encoded. */
mp_err
ec_GFp_pt_add_jm_aff(const mp_int *px, const mp_int *py, const mp_int *pz,
					 const mp_int *paz4, const mp_int *qx,
					 const mp_int *qy, mp_int *rx, mp_int *ry, mp_int *rz,
					 mp_int *raz4, const ECGroup *group)
{
	mp_err res = MP_OKAY;
	mp_int A, B, C, D, C2, C3;

	MP_DIGITS(&A) = 0;
	MP_DIGITS(&B) = 0;
	MP_DIGITS(&C) = 0;
	MP_DIGITS(&D) = 0;
	MP_DIGITS(&C2) = 0;
	MP_DIGITS(&C3) = 0;
	MP_CHECKOK(mp_init(&A));
	MP_CHECKOK(mp_init(&B));
	MP_CHECKOK(mp_init(&C));
	MP_CHECKOK(mp_init(&D));
	MP_CHECKOK(mp_init(&C2));
	MP_CHECKOK(mp_init(&C3));

	/* If either P or Q is the point at infinity, then return the other
	 * point */
	if (ec_GFp_pt_is_inf_jac(px, py, pz) == MP_YES) {
		MP_CHECKOK(ec_GFp_pt_aff2jac(qx, qy, rx, ry, rz, group));
		MP_CHECKOK(group->meth->field_sqr(rz, raz4, group->meth));
		MP_CHECKOK(group->meth->field_sqr(raz4, raz4, group->meth));
		MP_CHECKOK(group->meth->
				   field_mul(raz4, &group->curvea, raz4, group->meth));
		goto CLEANUP;
	}
	if (ec_GFp_pt_is_inf_aff(qx, qy) == MP_YES) {
		MP_CHECKOK(mp_copy(px, rx));
		MP_CHECKOK(mp_copy(py, ry));
		MP_CHECKOK(mp_copy(pz, rz));
		MP_CHECKOK(mp_copy(paz4, raz4));
		goto CLEANUP;
	}

	/* A = qx * pz^2, B = qy * pz^3 */
	MP_CHECKOK(group->meth->field_sqr(pz, &A, group->meth));
	MP_CHECKOK(group->meth->field_mul(&A, pz, &B, group->meth));
	MP_CHECKOK(group->meth->field_mul(&A, qx, &A, group->meth));
	MP_CHECKOK(group->meth->field_mul(&B, qy, &B, group->meth));

	/* C = A - px, D = B - py */
	MP_CHECKOK(group->meth->field_sub(&A, px, &C, group->meth));
	MP_CHECKOK(group->meth->field_sub(&B, py, &D, group->meth));

	/* C2 = C^2, C3 = C^3 */
	MP_CHECKOK(group->meth->field_sqr(&C, &C2, group->meth));
	MP_CHECKOK(group->meth->field_mul(&C, &C2, &C3, group->meth));

	/* rz = pz * C */
	MP_CHECKOK(group->meth->field_mul(pz, &C, rz, group->meth));

	/* C = px * C^2 */
	MP_CHECKOK(group->meth->field_mul(px, &C2, &C, group->meth));
	/* A = D^2 */
	MP_CHECKOK(group->meth->field_sqr(&D, &A, group->meth));

	/* rx = D^2 - (C^3 + 2 * (px * C^2)) */
	MP_CHECKOK(group->meth->field_add(&C, &C, rx, group->meth));
	MP_CHECKOK(group->meth->field_add(&C3, rx, rx, group->meth));
	MP_CHECKOK(group->meth->field_sub(&A, rx, rx, group->meth));

	/* C3 = py * C^3 */
	MP_CHECKOK(group->meth->field_mul(py, &C3, &C3, group->meth));

	/* ry = D * (px * C^2 - rx) - py * C^3 */
	MP_CHECKOK(group->meth->field_sub(&C, rx, ry, group->meth));
	MP_CHECKOK(group->meth->field_mul(&D, ry, ry, group->meth));
	MP_CHECKOK(group->meth->field_sub(ry, &C3, ry, group->meth));

	/* raz4 = a * rz^4 */
	MP_CHECKOK(group->meth->field_sqr(rz, raz4, group->meth));
	MP_CHECKOK(group->meth->field_sqr(raz4, raz4, group->meth));
	MP_CHECKOK(group->meth->
			   field_mul(raz4, &group->curvea, raz4, group->meth));

  CLEANUP:
	mp_clear(&A);
	mp_clear(&B);
	mp_clear(&C);
	mp_clear(&D);
	mp_clear(&C2);
	mp_clear(&C3);
	return res;
}