Skip to content

mp_sqrtmod_prime can get caught in an infinite loop if "prime" isn't prime #486

@friedrichsenm

Description

@friedrichsenm

If *prime isn't prime but is composite that is 1 mod 4, you can hit infinite loops in two places. (My use case only involves numbers 1 mod 4, so this may happen other times too)

The first is in lines 62-69

mp_set(&Z, 2uL);
   /* Z = 2 */
   for (;;) {
      if ((err = mp_kronecker(&Z, prime, &legendre)) != MP_OKAY)     goto LBL_END;
      if (legendre == -1) break;
      if ((err = mp_add_d(&Z, 1uL, &Z)) != MP_OKAY)               goto LBL_END;
      /* Z = Z + 1 */
   }

I was able to fix this in a local copy adding the following check after line 66

if (legendre == 0) {err = MP_VAL; goto LBL_END;}

The second infinite loop was in lines 84-111

for (;;) {
      if ((err = mp_copy(&T, &t1)) != MP_OKAY)                    goto LBL_END;
      i = 0;
      for (;;) {
         if (mp_cmp_d(&t1, 1uL) == MP_EQ) break;
         if ((err = mp_exptmod(&t1, &two, prime, &t1)) != MP_OKAY) goto LBL_END;
         i++;
      }
      if (i == 0u) {
         if ((err = mp_copy(&R, ret)) != MP_OKAY)                  goto LBL_END;
         err = MP_OKAY;
         goto LBL_END;
      }
      if ((err = mp_sub_d(&M, i, &t1)) != MP_OKAY)                goto LBL_END;
      if ((err = mp_sub_d(&t1, 1uL, &t1)) != MP_OKAY)             goto LBL_END;
      if ((err = mp_exptmod(&two, &t1, prime, &t1)) != MP_OKAY)   goto LBL_END;
      /* t1 = 2 ^ (M - i - 1) */
      if ((err = mp_exptmod(&C, &t1, prime, &t1)) != MP_OKAY)     goto LBL_END;
      /* t1 = C ^ (2 ^ (M - i - 1)) mod prime */
      if ((err = mp_sqrmod(&t1, prime, &C)) != MP_OKAY)           goto LBL_END;
      /* C = (t1 * t1) mod prime */
      if ((err = mp_mulmod(&R, &t1, prime, &R)) != MP_OKAY)       goto LBL_END;
      /* R = (R * t1) mod prime */
      if ((err = mp_mulmod(&T, &C, prime, &T)) != MP_OKAY)        goto LBL_END;
      /* T = (T * C) mod prime */
      mp_set(&M, i);
      /* M = i */
   }

I was able to fix this by adding the following after line 88

if (mp_cmp_d(&M, i) == MP_EQ) {err = MP_VAL; goto LBL_END;}

Metadata

Metadata

Assignees

No one assigned

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions