Bug 1125025: Check for P == Q or P == -Q before adding P and Q.
authorWan-Teh Chang <wtc@google.com>
Mon, 04 May 2015 10:16:00 -0700
changeset 11453 2c05e861ce070a1c29083b00f987cc930974909d
parent 11452 ca159a08d006b28aff5b66545f9782a4a0e53349
child 11454 fc6870938172e7d8ebc502badca7634dc737a8cc
push id633
push userwtc@google.com
push dateMon, 04 May 2015 17:16:16 +0000
bugs1125025
Bug 1125025: Check for P == Q or P == -Q before adding P and Q. Check for P == -P before doubling P. r=rrelyea.
lib/freebl/ecl/ecp_jac.c
--- a/lib/freebl/ecl/ecp_jac.c
+++ b/lib/freebl/ecl/ecp_jac.c
@@ -139,16 +139,30 @@ ec_GFp_pt_add_jac_aff(const mp_int *px, 
 	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 */
@@ -200,17 +214,18 @@ ec_GFp_pt_dbl_jac(const mp_int *px, cons
 	MP_DIGITS(&t1) = 0;
 	MP_DIGITS(&M) = 0;
 	MP_DIGITS(&S) = 0;
 	MP_CHECKOK(mp_init(&t0));
 	MP_CHECKOK(mp_init(&t1));
 	MP_CHECKOK(mp_init(&M));
 	MP_CHECKOK(mp_init(&S));
 
-	if (ec_GFp_pt_is_inf_jac(px, py, pz) == MP_YES) {
+	/* P == inf or P == -P */
+	if (ec_GFp_pt_is_inf_jac(px, py, pz) == MP_YES || mp_cmp_z(py) == 0) {
 		MP_CHECKOK(ec_GFp_pt_set_inf_jac(rx, ry, rz));
 		goto CLEANUP;
 	}
 
 	if (mp_cmp_d(pz, 1) == 0) {
 		/* M = 3 * px^2 + a */
 		MP_CHECKOK(group->meth->field_sqr(px, &t0, group->meth));
 		MP_CHECKOK(group->meth->field_add(&t0, &t0, &M, group->meth));