/* LibTomCrypt, modular cryptographic library -- Tom St Denis */
/* SPDX-License-Identifier: Unlicense */

#include "tomcrypt_private.h"

#ifdef LTC_MECC

/* http://crypto.stackexchange.com/questions/41468/point-at-infinity-for-jacobian-coordinates
 * a point at infinity is any point (x,y,0) such that y^2 == x^3, except (0,0,0)
 */

int ltc_ecc_is_point_at_infinity(const ecc_point *P, const void *modulus, int *retval)
{
   int err;
   void  *x3, *y2;

   /* trivial case */
   if (!ltc_mp_iszero(P->z)) {
      *retval = 0;
      return CRYPT_OK;
   }

   /* point (0,0,0) is not at infinity */
   if (ltc_mp_iszero(P->x) && ltc_mp_iszero(P->y)) {
      *retval = 0;
      return CRYPT_OK;
   }

   /* initialize */
   if ((err = ltc_mp_init_multi(&x3, &y2, LTC_NULL))      != CRYPT_OK)   goto done;

   /* compute y^2 */
   if ((err = ltc_mp_mulmod(P->y, P->y, modulus, y2)) != CRYPT_OK)   goto cleanup;

   /* compute x^3 */
   if ((err = ltc_mp_mulmod(P->x, P->x, modulus, x3)) != CRYPT_OK)   goto cleanup;
   if ((err = ltc_mp_mulmod(P->x, x3, modulus, x3))   != CRYPT_OK)   goto cleanup;

   /* test y^2 == x^3 */
   err = CRYPT_OK;
   if ((ltc_mp_cmp(x3, y2) == LTC_MP_EQ) && !ltc_mp_iszero(y2)) {
      *retval = 1;
   } else {
      *retval = 0;
   }

cleanup:
   ltc_mp_deinit_multi(x3, y2, LTC_NULL);
done:
   return err;
}

#endif
