Blob Blame History Raw
# HG changeset patch
# User Wan-Teh Chang <wtc@google.com>
# Date 1430759760 25200
# Node ID 2c05e861ce070a1c29083b00f987cc930974909d
# Parent  ca159a08d006b28aff5b66545f9782a4a0e53349
Bug 1125025: Check for P == Q or P == -Q before adding P and Q.
Check for P == -P before doubling P. r=rrelyea.

diff --git a/lib/freebl/ecl/ecp_jac.c b/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));