@@ -469,6 +469,14 @@ static int tfm_ecc_projective_dbl_point(const ecc_point *P, ecc_point *R, const
469469 return CRYPT_OK ;
470470 }
471471
472+ /* Y == 0 or Z == 0 doubles to infinity. */
473+ if (fp_cmp_d (R -> y , 0 ) == FP_EQ || fp_cmp_d (R -> z , 0 ) == FP_EQ ) {
474+ ltc_mp .set_int (R -> x , 1 );
475+ ltc_mp .set_int (R -> y , 1 );
476+ ltc_mp .set_int (R -> z , 0 );
477+ return CRYPT_OK ;
478+ }
479+
472480 /* t1 = Z * Z */
473481 fp_sqr (R -> z , & t1 );
474482 fp_montgomery_reduce (& t1 , TFM_UNCONST (void * )modulus , mp );
@@ -597,7 +605,7 @@ static int tfm_ecc_projective_add_point(const ecc_point *P, const ecc_point *Q,
597605{
598606 fp_int t1 , t2 , x , y , z ;
599607 fp_digit mp ;
600- int err , inf ;
608+ int err , inf , x_or_y_is_zero ;
601609
602610 LTC_ARGCHK (P != NULL );
603611 LTC_ARGCHK (Q != NULL );
@@ -613,6 +621,29 @@ static int tfm_ecc_projective_add_point(const ecc_point *P, const ecc_point *Q,
613621 fp_init (& y );
614622 fp_init (& z );
615623
624+ /* treat internal Z == 0 states as infinity */
625+ if (P -> z != NULL && fp_cmp_d (P -> z , 0 ) == FP_EQ ) {
626+ if (Q -> z != NULL && fp_cmp_d (Q -> z , 0 ) == FP_EQ ) {
627+ /* inf + inf = inf */
628+ ltc_mp .set_int (R -> x , 1 );
629+ ltc_mp .set_int (R -> y , 1 );
630+ ltc_mp .set_int (R -> z , 0 );
631+ } else {
632+ /* inf + Q = Q */
633+ ltc_mp .copy (Q -> x , R -> x );
634+ ltc_mp .copy (Q -> y , R -> y );
635+ ltc_mp .copy (Q -> z , R -> z );
636+ }
637+ return CRYPT_OK ;
638+ }
639+ if (Q -> z != NULL && fp_cmp_d (Q -> z , 0 ) == FP_EQ ) {
640+ /* P + inf = P */
641+ ltc_mp .copy (P -> x , R -> x );
642+ ltc_mp .copy (P -> y , R -> y );
643+ ltc_mp .copy (P -> z , R -> z );
644+ return CRYPT_OK ;
645+ }
646+
616647 if ((err = ltc_ecc_is_point_at_infinity (P , modulus , & inf )) != CRYPT_OK ) return err ;
617648 if (inf ) {
618649 /* P is point at infinity >> Result = Q */
@@ -636,6 +667,7 @@ static int tfm_ecc_projective_add_point(const ecc_point *P, const ecc_point *Q,
636667 if ( (fp_cmp (P -> x , Q -> x ) == FP_EQ ) &&
637668 (Q -> z != NULL && fp_cmp (P -> z , Q -> z ) == FP_EQ ) &&
638669 (fp_cmp (P -> y , Q -> y ) == FP_EQ || fp_cmp (P -> y , & t1 ) == FP_EQ )) {
670+ dbl_point :
639671 return tfm_ecc_projective_dbl_point (P , R , ma , modulus , Mp );
640672 }
641673
@@ -735,6 +767,7 @@ static int tfm_ecc_projective_add_point(const ecc_point *P, const ecc_point *Q,
735767 if (fp_cmp_d (& x , 0 ) == FP_LT ) {
736768 fp_add (& x , TFM_UNCONST (void * )modulus , & x );
737769 }
770+ x_or_y_is_zero = fp_cmp_d (& x , 0 ) == FP_EQ ;
738771
739772 /* T2 = T2 - X */
740773 fp_sub (& t2 , & x , & t2 );
@@ -759,6 +792,11 @@ static int tfm_ecc_projective_add_point(const ecc_point *P, const ecc_point *Q,
759792 fp_add (& y , TFM_UNCONST (void * )modulus , & y );
760793 }
761794 fp_div_2 (& y , & y );
795+ x_or_y_is_zero |= fp_cmp_d (& y , 0 ) == LTC_MP_EQ ;
796+
797+ if (x_or_y_is_zero ) {
798+ goto dbl_point ;
799+ }
762800
763801 fp_copy (& x , R -> x );
764802 fp_copy (& y , R -> y );
0 commit comments