Browse Source

Fix cases where the points are equal.

In the case where `(P.x,P.y) == (Q.x,Q.y)` in affine coordinates, which
shows itself as either of the two being 0 after the add, we have
to double instead of add.

Signed-off-by: Steffen Jaeckel <[email protected]>
Steffen Jaeckel 3 weeks ago
parent
commit
7ef06b04ec
2 changed files with 16 additions and 2 deletions
  1. 8 1
      src/math/tfm_desc.c
  2. 8 1
      src/pk/ecc/ltc_ecc_projective_add_point.c

+ 8 - 1
src/math/tfm_desc.c

@@ -597,7 +597,7 @@ static int tfm_ecc_projective_add_point(const ecc_point *P, const ecc_point *Q,
 {
 {
    fp_int  t1, t2, x, y, z;
    fp_int  t1, t2, x, y, z;
    fp_digit mp;
    fp_digit mp;
-   int err, inf;
+   int err, inf, x_or_y_is_zero;
 
 
    LTC_ARGCHK(P       != NULL);
    LTC_ARGCHK(P       != NULL);
    LTC_ARGCHK(Q       != NULL);
    LTC_ARGCHK(Q       != NULL);
@@ -636,6 +636,7 @@ static int tfm_ecc_projective_add_point(const ecc_point *P, const ecc_point *Q,
    if ( (fp_cmp(P->x, Q->x) == FP_EQ) &&
    if ( (fp_cmp(P->x, Q->x) == FP_EQ) &&
         (Q->z != NULL && fp_cmp(P->z, Q->z) == FP_EQ) &&
         (Q->z != NULL && fp_cmp(P->z, Q->z) == FP_EQ) &&
         (fp_cmp(P->y, Q->y) == FP_EQ || fp_cmp(P->y, &t1) == FP_EQ)) {
         (fp_cmp(P->y, Q->y) == FP_EQ || fp_cmp(P->y, &t1) == FP_EQ)) {
+dbl_point:
         return tfm_ecc_projective_dbl_point(P, R, ma, modulus, Mp);
         return tfm_ecc_projective_dbl_point(P, R, ma, modulus, Mp);
    }
    }
 
 
@@ -735,6 +736,7 @@ static int tfm_ecc_projective_add_point(const ecc_point *P, const ecc_point *Q,
    if (fp_cmp_d(&x, 0) == FP_LT) {
    if (fp_cmp_d(&x, 0) == FP_LT) {
       fp_add(&x, TFM_UNCONST(void *)modulus, &x);
       fp_add(&x, TFM_UNCONST(void *)modulus, &x);
    }
    }
+   x_or_y_is_zero = fp_cmp_d(&x, 0) == FP_EQ;
 
 
    /* T2 = T2 - X */
    /* T2 = T2 - X */
    fp_sub(&t2, &x, &t2);
    fp_sub(&t2, &x, &t2);
@@ -759,6 +761,11 @@ static int tfm_ecc_projective_add_point(const ecc_point *P, const ecc_point *Q,
       fp_add(&y, TFM_UNCONST(void *)modulus, &y);
       fp_add(&y, TFM_UNCONST(void *)modulus, &y);
    }
    }
    fp_div_2(&y, &y);
    fp_div_2(&y, &y);
+   x_or_y_is_zero |= fp_cmp_d(&y, 0) == LTC_MP_EQ;
+
+   if (x_or_y_is_zero) {
+      goto dbl_point;
+   }
 
 
    fp_copy(&x, R->x);
    fp_copy(&x, R->x);
    fp_copy(&y, R->y);
    fp_copy(&y, R->y);

+ 8 - 1
src/pk/ecc/ltc_ecc_projective_add_point.c

@@ -24,7 +24,7 @@ int ltc_ecc_projective_add_point(const ecc_point *P, const ecc_point *Q, ecc_poi
                                  const void *ma, const void *modulus, void *mp)
                                  const void *ma, const void *modulus, void *mp)
 {
 {
    void  *t1, *t2, *x, *y, *z;
    void  *t1, *t2, *x, *y, *z;
-   int    err, inf;
+   int    err, inf, x_or_y_is_zero;
 
 
    LTC_ARGCHK(P       != NULL);
    LTC_ARGCHK(P       != NULL);
    LTC_ARGCHK(Q       != NULL);
    LTC_ARGCHK(Q       != NULL);
@@ -52,6 +52,7 @@ int ltc_ecc_projective_add_point(const ecc_point *P, const ecc_point *Q, ecc_poi
 
 
    if ((ltc_mp_cmp(P->x, Q->x) == LTC_MP_EQ) && (ltc_mp_cmp(P->z, Q->z) == LTC_MP_EQ)) {
    if ((ltc_mp_cmp(P->x, Q->x) == LTC_MP_EQ) && (ltc_mp_cmp(P->z, Q->z) == LTC_MP_EQ)) {
       if (ltc_mp_cmp(P->y, Q->y) == LTC_MP_EQ) {
       if (ltc_mp_cmp(P->y, Q->y) == LTC_MP_EQ) {
+dbl_point:
          /* here P = Q >> Result = 2 * P (use doubling) */
          /* here P = Q >> Result = 2 * P (use doubling) */
          ltc_mp_deinit_multi(t1, t2, x, y, z, LTC_NULL);
          ltc_mp_deinit_multi(t1, t2, x, y, z, LTC_NULL);
          return ltc_ecc_projective_dbl_point(P, R, ma, modulus, mp);
          return ltc_ecc_projective_dbl_point(P, R, ma, modulus, mp);
@@ -160,6 +161,7 @@ int ltc_ecc_projective_add_point(const ecc_point *P, const ecc_point *Q, ecc_poi
    if (ltc_mp_cmp_d(x, 0) == LTC_MP_LT) {
    if (ltc_mp_cmp_d(x, 0) == LTC_MP_LT) {
       if ((err = ltc_mp_add(x, modulus, x)) != CRYPT_OK)                           { goto done; }
       if ((err = ltc_mp_add(x, modulus, x)) != CRYPT_OK)                           { goto done; }
    }
    }
+   x_or_y_is_zero = ltc_mp_cmp_d(x, 0) == LTC_MP_EQ;
 
 
    /* T2 = T2 - X */
    /* T2 = T2 - X */
    if ((err = ltc_mp_sub(t2, x, t2)) != CRYPT_OK)                                  { goto done; }
    if ((err = ltc_mp_sub(t2, x, t2)) != CRYPT_OK)                                  { goto done; }
@@ -184,6 +186,11 @@ int ltc_ecc_projective_add_point(const ecc_point *P, const ecc_point *Q, ecc_poi
       if ((err = ltc_mp_add(y, modulus, y)) != CRYPT_OK)                           { goto done; }
       if ((err = ltc_mp_add(y, modulus, y)) != CRYPT_OK)                           { goto done; }
    }
    }
    if ((err = ltc_mp_div_2(y, y)) != CRYPT_OK)                                     { goto done; }
    if ((err = ltc_mp_div_2(y, y)) != CRYPT_OK)                                     { goto done; }
+   x_or_y_is_zero |= ltc_mp_cmp_d(y, 0) == LTC_MP_EQ;
+
+   if (x_or_y_is_zero) {
+      goto dbl_point;
+   }
 
 
    if ((err = ltc_mp_copy(x, R->x)) != CRYPT_OK)                                   { goto done; }
    if ((err = ltc_mp_copy(x, R->x)) != CRYPT_OK)                                   { goto done; }
    if ((err = ltc_mp_copy(y, R->y)) != CRYPT_OK)                                   { goto done; }
    if ((err = ltc_mp_copy(y, R->y)) != CRYPT_OK)                                   { goto done; }