/**
  Gets length of DER encoding of num 
  @param num    The int to get the size of 
  @param outlen [out] The length of the DER encoding for the given integer
  @return CRYPT_OK if successful
*/
int der_length_integer(void *num, unsigned long *outlen)
{
   unsigned long z, len;
   int           leading_zero;

   LTC_ARGCHK(num     != NULL);
   LTC_ARGCHK(outlen  != NULL);

   if (mp_cmp_d(num, 0) != LTC_MP_LT) {
      /* positive */

      /* we only need a leading zero if the msb of the first byte is one */
      if ((mp_count_bits(num) & 7) == 0 || mp_iszero(num) == LTC_MP_YES) {
         leading_zero = 1;
      } else {
         leading_zero = 0;
      }

      /* size for bignum */
      z = len = leading_zero + mp_unsigned_bin_size(num);
   } else {
      /* it's negative */
      /* find power of 2 that is a multiple of eight and greater than count bits */
      leading_zero = 0;
      z = mp_count_bits(num);
      z = z + (8 - (z & 7));
      if (((mp_cnt_lsb(num)+1)==mp_count_bits(num)) && ((mp_count_bits(num)&7)==0)) --z;
      len = z = z >> 3;
   }

   /* now we need a length */
   if (z < 128) {
      /* short form */
      ++len;
   } else {
      /* long form (relies on z != 0), assumes length bytes < 128 */
      ++len;

      while (z) {
         ++len;
         z >>= 8;
      }
   }

   /* we need a 0x02 to indicate it's INTEGER */
   ++len;

   /* return length */
   *outlen = len; 
   return CRYPT_OK;
}
Exemplo n.º 2
0
/**
  Store a mp_int integer
  @param num      The first mp_int to encode
  @param out      [out] The destination for the DER encoded integers
  @param outlen   [in/out] The max size and resulting size of the DER encoded integers
  @return CRYPT_OK if successful
*/
int der_encode_integer(void *num, unsigned char *out, unsigned long *outlen)
{  
   unsigned long tmplen, y;
   int           err, leading_zero;

   LTC_ARGCHK(num    != NULL);
   LTC_ARGCHK(out    != NULL);
   LTC_ARGCHK(outlen != NULL);

   /* find out how big this will be */
   if ((err = der_length_integer(num, &tmplen)) != CRYPT_OK) {
      return err;
   }

   if (*outlen < tmplen) {
      *outlen = tmplen;
      return CRYPT_BUFFER_OVERFLOW;
   }

   if (mp_cmp_d(num, 0) != LTC_MP_LT) {
      /* we only need a leading zero if the msb of the first byte is one */
      if ((mp_count_bits(num) & 7) == 0 || mp_iszero(num) == LTC_MP_YES) {
         leading_zero = 1;
      } else {
         leading_zero = 0;
      }

      /* get length of num in bytes (plus 1 since we force the msbyte to zero) */
      y = mp_unsigned_bin_size(num) + leading_zero;
   } else {
      leading_zero = 0;
      y            = mp_count_bits(num);
      y            = y + (8 - (y & 7));
      y            = y >> 3;
      if (((mp_cnt_lsb(num)+1)==mp_count_bits(num)) && ((mp_count_bits(num)&7)==0)) --y;
   }

   /* now store initial data */
   *out++ = 0x02;
   if (y < 128) {
      /* short form */
      *out++ = (unsigned char)y;
   } else if (y < 256) {
      *out++ = 0x81;
      *out++ = (unsigned char)y;
   } else if (y < 65536UL) {
      *out++ = 0x82;
      *out++ = (unsigned char)((y>>8)&255);
      *out++ = (unsigned char)y;
   } else if (y < 16777216UL) {
Exemplo n.º 3
0
/* computes the jacobi c = (a | n) (or Legendre if n is prime)
 * HAC pp. 73 Algorithm 2.149
 */
int mp_jacobi (mp_int * a, mp_int * p, int *c)
{
  mp_int  a1, p1;
  int     k, s, r, res;
  mp_digit residue;

  /* if p <= 0 return MP_VAL */
  if (mp_cmp_d(p, 0) != MP_GT) {
     return MP_VAL;
  }

  /* step 1.  if a == 0, return 0 */
  if (mp_iszero (a) == 1) {
    *c = 0;
    return MP_OKAY;
  }

  /* step 2.  if a == 1, return 1 */
  if (mp_cmp_d (a, 1) == MP_EQ) {
    *c = 1;
    return MP_OKAY;
  }

  /* default */
  s = 0;

  /* step 3.  write a = a1 * 2**k  */
  if ((res = mp_init_copy (&a1, a)) != MP_OKAY) {
    return res;
  }

  if ((res = mp_init (&p1)) != MP_OKAY) {
    goto LBL_A1;
  }

  /* divide out larger power of two */
  k = mp_cnt_lsb(&a1);
  if ((res = mp_div_2d(&a1, k, &a1, NULL)) != MP_OKAY) {
     goto LBL_P1;
  }

  /* step 4.  if e is even set s=1 */
  if ((k & 1) == 0) {
    s = 1;
  } else {
    /* else set s=1 if p = 1/7 (mod 8) or s=-1 if p = 3/5 (mod 8) */
    residue = p->dp[0] & 7;

    if (residue == 1 || residue == 7) {
      s = 1;
    } else if (residue == 3 || residue == 5) {
      s = -1;
    }
  }

  /* step 5.  if p == 3 (mod 4) *and* a1 == 3 (mod 4) then s = -s */
  if ( ((p->dp[0] & 3) == 3) && ((a1.dp[0] & 3) == 3)) {
    s = -s;
  }

  /* if a1 == 1 we're done */
  if (mp_cmp_d (&a1, 1) == MP_EQ) {
    *c = s;
  } else {
    /* n1 = n mod a1 */
    if ((res = mp_mod (p, &a1, &p1)) != MP_OKAY) {
      goto LBL_P1;
    }
    if ((res = mp_jacobi (&p1, &a1, &r)) != MP_OKAY) {
      goto LBL_P1;
    }
    *c = s * r;
  }

  /* done */
  res = MP_OKAY;
LBL_P1:mp_clear (&p1);
LBL_A1:mp_clear (&a1);
  return res;
}
/* Miller-Rabin test of "a" to the base of "b" as described in 
 * HAC pp. 139 Algorithm 4.24
 *
 * Sets result to 0 if definitely composite or 1 if probably prime.
 * Randomly the chance of error is no more than 1/4 and often 
 * very much lower.
 */
int mp_prime_miller_rabin (mp_int * a, mp_int * b, int *result)
{
  mp_int  n1, y, r;
  int     s, j, err;

  /* default */
  *result = MP_NO;

  /* ensure b > 1 */
  if (mp_cmp_d(b, 1) != MP_GT) {
     return MP_VAL;
  }     

  /* get n1 = a - 1 */
  if ((err = mp_init_copy (&n1, a)) != MP_OKAY) {
    return err;
  }
  if ((err = mp_sub_d (&n1, 1, &n1)) != MP_OKAY) {
    goto LBL_N1;
  }

  /* set 2**s * r = n1 */
  if ((err = mp_init_copy (&r, &n1)) != MP_OKAY) {
    goto LBL_N1;
  }

  /* count the number of least significant bits
   * which are zero
   */
  s = mp_cnt_lsb(&r);

  /* now divide n - 1 by 2**s */
  if ((err = mp_div_2d (&r, s, &r, NULL)) != MP_OKAY) {
    goto LBL_R;
  }

  /* compute y = b**r mod a */
  if ((err = mp_init (&y)) != MP_OKAY) {
    goto LBL_R;
  }
  if ((err = mp_exptmod (b, &r, a, &y)) != MP_OKAY) {
    goto LBL_Y;
  }

  /* if y != 1 and y != n1 do */
  if (mp_cmp_d (&y, 1) != MP_EQ && mp_cmp (&y, &n1) != MP_EQ) {
    j = 1;
    /* while j <= s-1 and y != n1 */
    while ((j <= (s - 1)) && mp_cmp (&y, &n1) != MP_EQ) {
      if ((err = mp_sqrmod (&y, a, &y)) != MP_OKAY) {
         goto LBL_Y;
      }

      /* if y == 1 then composite */
      if (mp_cmp_d (&y, 1) == MP_EQ) {
         goto LBL_Y;
      }

      ++j;
    }

    /* if y != n1 then composite */
    if (mp_cmp (&y, &n1) != MP_EQ) {
      goto LBL_Y;
    }
  }

  /* probably prime now */
  *result = MP_YES;
LBL_Y:mp_clear (&y);
LBL_R:mp_clear (&r);
LBL_N1:mp_clear (&n1);
  return err;
}
Exemplo n.º 5
0
static int count_lsb_bits(void *a)
{
   LTC_ARGCHK(a != NULL);
   return mp_cnt_lsb(a);
}
Exemplo n.º 6
0
/* Greatest Common Divisor using the binary method */
int mp_gcd (mp_int * a, mp_int * b, mp_int * c)
{
  mp_int  u, v;
  int     k, u_lsb, v_lsb, res;

  /* either zero than gcd is the largest */
  if (mp_iszero (a) == MP_YES) {
    return mp_abs (b, c);
  }
  if (mp_iszero (b) == MP_YES) {
    return mp_abs (a, c);
  }

  /* get copies of a and b we can modify */
  if ((res = mp_init_copy (&u, a)) != MP_OKAY) {
    return res;
  }

  if ((res = mp_init_copy (&v, b)) != MP_OKAY) {
    goto LBL_U;
  }

  /* must be positive for the remainder of the algorithm */
  u.sign = v.sign = MP_ZPOS;

  /* B1.  Find the common power of two for u and v */
  u_lsb = mp_cnt_lsb(&u);
  v_lsb = mp_cnt_lsb(&v);
  k     = MIN(u_lsb, v_lsb);

  if (k > 0) {
     /* divide the power of two out */
     if ((res = mp_div_2d(&u, k, &u, NULL)) != MP_OKAY) {
        goto LBL_V;
     }

     if ((res = mp_div_2d(&v, k, &v, NULL)) != MP_OKAY) {
        goto LBL_V;
     }
  }

  /* divide any remaining factors of two out */
  if (u_lsb != k) {
     if ((res = mp_div_2d(&u, u_lsb - k, &u, NULL)) != MP_OKAY) {
        goto LBL_V;
     }
  }

  if (v_lsb != k) {
     if ((res = mp_div_2d(&v, v_lsb - k, &v, NULL)) != MP_OKAY) {
        goto LBL_V;
     }
  }

  while (mp_iszero(&v) == MP_NO) {
     /* make sure v is the largest */
     if (mp_cmp_mag(&u, &v) == MP_GT) {
        /* swap u and v to make sure v is >= u */
        mp_exch(&u, &v);
     }
     
     /* subtract smallest from largest */
     if ((res = s_mp_sub(&v, &u, &v)) != MP_OKAY) {
        goto LBL_V;
     }
     
     /* Divide out all factors of two */
     if ((res = mp_div_2d(&v, mp_cnt_lsb(&v), &v, NULL)) != MP_OKAY) {
        goto LBL_V;
     } 
  } 

  /* multiply by 2**k which we divided out at the beginning */
  if ((res = mp_mul_2d (&u, k, c)) != MP_OKAY) {
     goto LBL_V;
  }
  c->sign = MP_ZPOS;
  res = MP_OKAY;
LBL_V:mp_clear (&u);
LBL_U:mp_clear (&v);
  return res;
}
Exemplo n.º 7
0
int main(void)
{
   mp_int a, b, c, d, e, f;
   unsigned long expt_n, add_n, sub_n, mul_n, div_n, sqr_n, mul2d_n, div2d_n,
      gcd_n, lcm_n, inv_n, div2_n, mul2_n, add_d_n, sub_d_n, t;
   unsigned rr;
   int i, n, err, cnt, ix, old_kara_m, old_kara_s;
   mp_digit mp;


   mp_init(&a);
   mp_init(&b);
   mp_init(&c);
   mp_init(&d);
   mp_init(&e);
   mp_init(&f);

   srand(time(NULL));

#if 0
   // test montgomery
   printf("Testing montgomery...\n");
   for (i = 1; i < 10; i++) {
      printf("Testing digit size: %d\n", i);
      for (n = 0; n < 1000; n++) {
         mp_rand(&a, i);
         a.dp[0] |= 1;

         // let's see if R is right
         mp_montgomery_calc_normalization(&b, &a);
         mp_montgomery_setup(&a, &mp);

         // now test a random reduction
         for (ix = 0; ix < 100; ix++) {
             mp_rand(&c, 1 + abs(rand()) % (2*i));
             mp_copy(&c, &d);
             mp_copy(&c, &e);

             mp_mod(&d, &a, &d);
             mp_montgomery_reduce(&c, &a, mp);
             mp_mulmod(&c, &b, &a, &c);

             if (mp_cmp(&c, &d) != MP_EQ) {
printf("d = e mod a, c = e MOD a\n");
mp_todecimal(&a, buf); printf("a = %s\n", buf);
mp_todecimal(&e, buf); printf("e = %s\n", buf);
mp_todecimal(&d, buf); printf("d = %s\n", buf);
mp_todecimal(&c, buf); printf("c = %s\n", buf);
printf("compare no compare!\n"); exit(EXIT_FAILURE); }
         }
      }
   }
   printf("done\n");

   // test mp_get_int
   printf("Testing: mp_get_int\n");
   for (i = 0; i < 1000; ++i) {
      t = ((unsigned long) rand() * rand() + 1) & 0xFFFFFFFF;
      mp_set_int(&a, t);
      if (t != mp_get_int(&a)) {
	 printf("mp_get_int() bad result!\n");
	 return 1;
      }
   }
   mp_set_int(&a, 0);
   if (mp_get_int(&a) != 0) {
      printf("mp_get_int() bad result!\n");
      return 1;
   }
   mp_set_int(&a, 0xffffffff);
   if (mp_get_int(&a) != 0xffffffff) {
      printf("mp_get_int() bad result!\n");
      return 1;
   }
   // test mp_sqrt
   printf("Testing: mp_sqrt\n");
   for (i = 0; i < 1000; ++i) {
      printf("%6d\r", i);
      fflush(stdout);
      n = (rand() & 15) + 1;
      mp_rand(&a, n);
      if (mp_sqrt(&a, &b) != MP_OKAY) {
	 printf("mp_sqrt() error!\n");
	 return 1;
      }
      mp_n_root(&a, 2, &a);
      if (mp_cmp_mag(&b, &a) != MP_EQ) {
	 printf("mp_sqrt() bad result!\n");
	 return 1;
      }
   }

   printf("\nTesting: mp_is_square\n");
   for (i = 0; i < 1000; ++i) {
      printf("%6d\r", i);
      fflush(stdout);

      /* test mp_is_square false negatives */
      n = (rand() & 7) + 1;
      mp_rand(&a, n);
      mp_sqr(&a, &a);
      if (mp_is_square(&a, &n) != MP_OKAY) {
	 printf("fn:mp_is_square() error!\n");
	 return 1;
      }
      if (n == 0) {
	 printf("fn:mp_is_square() bad result!\n");
	 return 1;
      }

      /* test for false positives */
      mp_add_d(&a, 1, &a);
      if (mp_is_square(&a, &n) != MP_OKAY) {
	 printf("fp:mp_is_square() error!\n");
	 return 1;
      }
      if (n == 1) {
	 printf("fp:mp_is_square() bad result!\n");
	 return 1;
      }

   }
   printf("\n\n");

   /* test for size */
   for (ix = 10; ix < 128; ix++) {
      printf("Testing (not safe-prime): %9d bits    \r", ix);
      fflush(stdout);
      err =
	 mp_prime_random_ex(&a, 8, ix,
			    (rand() & 1) ? LTM_PRIME_2MSB_OFF :
			    LTM_PRIME_2MSB_ON, myrng, NULL);
      if (err != MP_OKAY) {
	 printf("failed with err code %d\n", err);
	 return EXIT_FAILURE;
      }
      if (mp_count_bits(&a) != ix) {
	 printf("Prime is %d not %d bits!!!\n", mp_count_bits(&a), ix);
	 return EXIT_FAILURE;
      }
   }

   for (ix = 16; ix < 128; ix++) {
      printf("Testing (   safe-prime): %9d bits    \r", ix);
      fflush(stdout);
      err =
	 mp_prime_random_ex(&a, 8, ix,
			    ((rand() & 1) ? LTM_PRIME_2MSB_OFF :
			     LTM_PRIME_2MSB_ON) | LTM_PRIME_SAFE, myrng,
			    NULL);
      if (err != MP_OKAY) {
	 printf("failed with err code %d\n", err);
	 return EXIT_FAILURE;
      }
      if (mp_count_bits(&a) != ix) {
	 printf("Prime is %d not %d bits!!!\n", mp_count_bits(&a), ix);
	 return EXIT_FAILURE;
      }
      /* let's see if it's really a safe prime */
      mp_sub_d(&a, 1, &a);
      mp_div_2(&a, &a);
      mp_prime_is_prime(&a, 8, &cnt);
      if (cnt != MP_YES) {
	 printf("sub is not prime!\n");
	 return EXIT_FAILURE;
      }
   }

   printf("\n\n");

   mp_read_radix(&a, "123456", 10);
   mp_toradix_n(&a, buf, 10, 3);
   printf("a == %s\n", buf);
   mp_toradix_n(&a, buf, 10, 4);
   printf("a == %s\n", buf);
   mp_toradix_n(&a, buf, 10, 30);
   printf("a == %s\n", buf);


#if 0
   for (;;) {
      fgets(buf, sizeof(buf), stdin);
      mp_read_radix(&a, buf, 10);
      mp_prime_next_prime(&a, 5, 1);
      mp_toradix(&a, buf, 10);
      printf("%s, %lu\n", buf, a.dp[0] & 3);
   }
#endif

   /* test mp_cnt_lsb */
   printf("testing mp_cnt_lsb...\n");
   mp_set(&a, 1);
   for (ix = 0; ix < 1024; ix++) {
      if (mp_cnt_lsb(&a) != ix) {
	 printf("Failed at %d, %d\n", ix, mp_cnt_lsb(&a));
	 return 0;
      }
      mp_mul_2(&a, &a);
   }

/* test mp_reduce_2k */
   printf("Testing mp_reduce_2k...\n");
   for (cnt = 3; cnt <= 128; ++cnt) {
      mp_digit tmp;

      mp_2expt(&a, cnt);
      mp_sub_d(&a, 2, &a);	/* a = 2**cnt - 2 */


      printf("\nTesting %4d bits", cnt);
      printf("(%d)", mp_reduce_is_2k(&a));
      mp_reduce_2k_setup(&a, &tmp);
      printf("(%d)", tmp);
      for (ix = 0; ix < 1000; ix++) {
	 if (!(ix & 127)) {
	    printf(".");
	    fflush(stdout);
	 }
	 mp_rand(&b, (cnt / DIGIT_BIT + 1) * 2);
	 mp_copy(&c, &b);
	 mp_mod(&c, &a, &c);
	 mp_reduce_2k(&b, &a, 2);
	 if (mp_cmp(&c, &b)) {
	    printf("FAILED\n");
	    exit(0);
	 }
      }
   }

/* test mp_div_3  */
   printf("Testing mp_div_3...\n");
   mp_set(&d, 3);
   for (cnt = 0; cnt < 10000;) {
      mp_digit r1, r2;

      if (!(++cnt & 127))
	 printf("%9d\r", cnt);
      mp_rand(&a, abs(rand()) % 128 + 1);
      mp_div(&a, &d, &b, &e);
      mp_div_3(&a, &c, &r2);

      if (mp_cmp(&b, &c) || mp_cmp_d(&e, r2)) {
	 printf("\n\nmp_div_3 => Failure\n");
      }
   }
   printf("\n\nPassed div_3 testing\n");

/* test the DR reduction */
   printf("testing mp_dr_reduce...\n");
   for (cnt = 2; cnt < 32; cnt++) {
      printf("%d digit modulus\n", cnt);
      mp_grow(&a, cnt);
      mp_zero(&a);
      for (ix = 1; ix < cnt; ix++) {
	 a.dp[ix] = MP_MASK;
      }
      a.used = cnt;
      a.dp[0] = 3;

      mp_rand(&b, cnt - 1);
      mp_copy(&b, &c);

      rr = 0;
      do {
	 if (!(rr & 127)) {
	    printf("%9lu\r", rr);
	    fflush(stdout);
	 }
	 mp_sqr(&b, &b);
	 mp_add_d(&b, 1, &b);
	 mp_copy(&b, &c);

	 mp_mod(&b, &a, &b);
	 mp_dr_reduce(&c, &a, (((mp_digit) 1) << DIGIT_BIT) - a.dp[0]);

	 if (mp_cmp(&b, &c) != MP_EQ) {
	    printf("Failed on trial %lu\n", rr);
	    exit(-1);

	 }
      } while (++rr < 500);
      printf("Passed DR test for %d digits\n", cnt);
   }

#endif

/* test the mp_reduce_2k_l code */
#if 0
#if 0
/* first load P with 2^1024 - 0x2A434 B9FDEC95 D8F9D550 FFFFFFFF FFFFFFFF */
   mp_2expt(&a, 1024);
   mp_read_radix(&b, "2A434B9FDEC95D8F9D550FFFFFFFFFFFFFFFF", 16);
   mp_sub(&a, &b, &a);
#elif 1
/*  p = 2^2048 - 0x1 00000000 00000000 00000000 00000000 4945DDBF 8EA2A91D 5776399B B83E188F  */
   mp_2expt(&a, 2048);
   mp_read_radix(&b,
		 "1000000000000000000000000000000004945DDBF8EA2A91D5776399BB83E188F",
		 16);
   mp_sub(&a, &b, &a);
#endif

   mp_todecimal(&a, buf);
   printf("p==%s\n", buf);
/* now mp_reduce_is_2k_l() should return */
   if (mp_reduce_is_2k_l(&a) != 1) {
      printf("mp_reduce_is_2k_l() return 0, should be 1\n");
      return EXIT_FAILURE;
   }
   mp_reduce_2k_setup_l(&a, &d);
   /* now do a million square+1 to see if it varies */
   mp_rand(&b, 64);
   mp_mod(&b, &a, &b);
   mp_copy(&b, &c);
   printf("testing mp_reduce_2k_l...");
   fflush(stdout);
   for (cnt = 0; cnt < (1UL << 20); cnt++) {
      mp_sqr(&b, &b);
      mp_add_d(&b, 1, &b);
      mp_reduce_2k_l(&b, &a, &d);
      mp_sqr(&c, &c);
      mp_add_d(&c, 1, &c);
      mp_mod(&c, &a, &c);
      if (mp_cmp(&b, &c) != MP_EQ) {
	 printf("mp_reduce_2k_l() failed at step %lu\n", cnt);
	 mp_tohex(&b, buf);
	 printf("b == %s\n", buf);
	 mp_tohex(&c, buf);
	 printf("c == %s\n", buf);
	 return EXIT_FAILURE;
      }
   }
   printf("...Passed\n");
#endif

   div2_n = mul2_n = inv_n = expt_n = lcm_n = gcd_n = add_n =
      sub_n = mul_n = div_n = sqr_n = mul2d_n = div2d_n = cnt = add_d_n =
      sub_d_n = 0;

   /* force KARA and TOOM to enable despite cutoffs */
   KARATSUBA_SQR_CUTOFF = KARATSUBA_MUL_CUTOFF = 8;
   TOOM_SQR_CUTOFF = TOOM_MUL_CUTOFF = 16;

   for (;;) {
      /* randomly clear and re-init one variable, this has the affect of triming the alloc space */
      switch (abs(rand()) % 7) {
      case 0:
	 mp_clear(&a);
	 mp_init(&a);
	 break;
      case 1:
	 mp_clear(&b);
	 mp_init(&b);
	 break;
      case 2:
	 mp_clear(&c);
	 mp_init(&c);
	 break;
      case 3:
	 mp_clear(&d);
	 mp_init(&d);
	 break;
      case 4:
	 mp_clear(&e);
	 mp_init(&e);
	 break;
      case 5:
	 mp_clear(&f);
	 mp_init(&f);
	 break;
      case 6:
	 break;			/* don't clear any */
      }


      printf
	 ("%4lu/%4lu/%4lu/%4lu/%4lu/%4lu/%4lu/%4lu/%4lu/%4lu/%4lu/%4lu/%4lu/%4lu/%4lu ",
	  add_n, sub_n, mul_n, div_n, sqr_n, mul2d_n, div2d_n, gcd_n, lcm_n,
	  expt_n, inv_n, div2_n, mul2_n, add_d_n, sub_d_n);
      fgets(cmd, 4095, stdin);
      cmd[strlen(cmd) - 1] = 0;
      printf("%s  ]\r", cmd);
      fflush(stdout);
      if (!strcmp(cmd, "mul2d")) {
	 ++mul2d_n;
	 fgets(buf, 4095, stdin);
	 mp_read_radix(&a, buf, 64);
	 fgets(buf, 4095, stdin);
	 sscanf(buf, "%d", &rr);
	 fgets(buf, 4095, stdin);
	 mp_read_radix(&b, buf, 64);

	 mp_mul_2d(&a, rr, &a);
	 a.sign = b.sign;
	 if (mp_cmp(&a, &b) != MP_EQ) {
	    printf("mul2d failed, rr == %d\n", rr);
	    draw(&a);
	    draw(&b);
	    return 0;
	 }
      } else if (!strcmp(cmd, "div2d")) {
	 ++div2d_n;
	 fgets(buf, 4095, stdin);
	 mp_read_radix(&a, buf, 64);
	 fgets(buf, 4095, stdin);
	 sscanf(buf, "%d", &rr);
	 fgets(buf, 4095, stdin);
	 mp_read_radix(&b, buf, 64);

	 mp_div_2d(&a, rr, &a, &e);
	 a.sign = b.sign;
	 if (a.used == b.used && a.used == 0) {
	    a.sign = b.sign = MP_ZPOS;
	 }
	 if (mp_cmp(&a, &b) != MP_EQ) {
	    printf("div2d failed, rr == %d\n", rr);
	    draw(&a);
	    draw(&b);
	    return 0;
	 }
      } else if (!strcmp(cmd, "add")) {
	 ++add_n;
	 fgets(buf, 4095, stdin);
	 mp_read_radix(&a, buf, 64);
	 fgets(buf, 4095, stdin);
	 mp_read_radix(&b, buf, 64);
	 fgets(buf, 4095, stdin);
	 mp_read_radix(&c, buf, 64);
	 mp_copy(&a, &d);
	 mp_add(&d, &b, &d);
	 if (mp_cmp(&c, &d) != MP_EQ) {
	    printf("add %lu failure!\n", add_n);
	    draw(&a);
	    draw(&b);
	    draw(&c);
	    draw(&d);
	    return 0;
	 }

	 /* test the sign/unsigned storage functions */

	 rr = mp_signed_bin_size(&c);
	 mp_to_signed_bin(&c, (unsigned char *) cmd);
	 memset(cmd + rr, rand() & 255, sizeof(cmd) - rr);
	 mp_read_signed_bin(&d, (unsigned char *) cmd, rr);
	 if (mp_cmp(&c, &d) != MP_EQ) {
	    printf("mp_signed_bin failure!\n");
	    draw(&c);
	    draw(&d);
	    return 0;
	 }


	 rr = mp_unsigned_bin_size(&c);
	 mp_to_unsigned_bin(&c, (unsigned char *) cmd);
	 memset(cmd + rr, rand() & 255, sizeof(cmd) - rr);
	 mp_read_unsigned_bin(&d, (unsigned char *) cmd, rr);
	 if (mp_cmp_mag(&c, &d) != MP_EQ) {
	    printf("mp_unsigned_bin failure!\n");
	    draw(&c);
	    draw(&d);
	    return 0;
	 }

      } else if (!strcmp(cmd, "sub")) {
	 ++sub_n;
	 fgets(buf, 4095, stdin);
	 mp_read_radix(&a, buf, 64);
	 fgets(buf, 4095, stdin);
	 mp_read_radix(&b, buf, 64);
	 fgets(buf, 4095, stdin);
	 mp_read_radix(&c, buf, 64);
	 mp_copy(&a, &d);
	 mp_sub(&d, &b, &d);
	 if (mp_cmp(&c, &d) != MP_EQ) {
	    printf("sub %lu failure!\n", sub_n);
	    draw(&a);
	    draw(&b);
	    draw(&c);
	    draw(&d);
	    return 0;
	 }
      } else if (!strcmp(cmd, "mul")) {
	 ++mul_n;
	 fgets(buf, 4095, stdin);
	 mp_read_radix(&a, buf, 64);
	 fgets(buf, 4095, stdin);
	 mp_read_radix(&b, buf, 64);
	 fgets(buf, 4095, stdin);
	 mp_read_radix(&c, buf, 64);
	 mp_copy(&a, &d);
	 mp_mul(&d, &b, &d);
	 if (mp_cmp(&c, &d) != MP_EQ) {
	    printf("mul %lu failure!\n", mul_n);
	    draw(&a);
	    draw(&b);
	    draw(&c);
	    draw(&d);
	    return 0;
	 }
      } else if (!strcmp(cmd, "div")) {
	 ++div_n;
	 fgets(buf, 4095, stdin);
	 mp_read_radix(&a, buf, 64);
	 fgets(buf, 4095, stdin);
	 mp_read_radix(&b, buf, 64);
	 fgets(buf, 4095, stdin);
	 mp_read_radix(&c, buf, 64);
	 fgets(buf, 4095, stdin);
	 mp_read_radix(&d, buf, 64);

	 mp_div(&a, &b, &e, &f);
	 if (mp_cmp(&c, &e) != MP_EQ || mp_cmp(&d, &f) != MP_EQ) {
	    printf("div %lu %d, %d, failure!\n", div_n, mp_cmp(&c, &e),
		   mp_cmp(&d, &f));
	    draw(&a);
	    draw(&b);
	    draw(&c);
	    draw(&d);
	    draw(&e);
	    draw(&f);
	    return 0;
	 }

      } else if (!strcmp(cmd, "sqr")) {
	 ++sqr_n;
	 fgets(buf, 4095, stdin);
	 mp_read_radix(&a, buf, 64);
	 fgets(buf, 4095, stdin);
	 mp_read_radix(&b, buf, 64);
	 mp_copy(&a, &c);
	 mp_sqr(&c, &c);
	 if (mp_cmp(&b, &c) != MP_EQ) {
	    printf("sqr %lu failure!\n", sqr_n);
	    draw(&a);
	    draw(&b);
	    draw(&c);
	    return 0;
	 }
      } else if (!strcmp(cmd, "gcd")) {
	 ++gcd_n;
	 fgets(buf, 4095, stdin);
	 mp_read_radix(&a, buf, 64);
	 fgets(buf, 4095, stdin);
	 mp_read_radix(&b, buf, 64);
	 fgets(buf, 4095, stdin);
	 mp_read_radix(&c, buf, 64);
	 mp_copy(&a, &d);
	 mp_gcd(&d, &b, &d);
	 d.sign = c.sign;
	 if (mp_cmp(&c, &d) != MP_EQ) {
	    printf("gcd %lu failure!\n", gcd_n);
	    draw(&a);
	    draw(&b);
	    draw(&c);
	    draw(&d);
	    return 0;
	 }
      } else if (!strcmp(cmd, "lcm")) {
	 ++lcm_n;
	 fgets(buf, 4095, stdin);
	 mp_read_radix(&a, buf, 64);
	 fgets(buf, 4095, stdin);
	 mp_read_radix(&b, buf, 64);
	 fgets(buf, 4095, stdin);
	 mp_read_radix(&c, buf, 64);
	 mp_copy(&a, &d);
	 mp_lcm(&d, &b, &d);
	 d.sign = c.sign;
	 if (mp_cmp(&c, &d) != MP_EQ) {
	    printf("lcm %lu failure!\n", lcm_n);
	    draw(&a);
	    draw(&b);
	    draw(&c);
	    draw(&d);
	    return 0;
	 }
      } else if (!strcmp(cmd, "expt")) {
	 ++expt_n;
	 fgets(buf, 4095, stdin);
	 mp_read_radix(&a, buf, 64);
	 fgets(buf, 4095, stdin);
	 mp_read_radix(&b, buf, 64);
	 fgets(buf, 4095, stdin);
	 mp_read_radix(&c, buf, 64);
	 fgets(buf, 4095, stdin);
	 mp_read_radix(&d, buf, 64);
	 mp_copy(&a, &e);
	 mp_exptmod(&e, &b, &c, &e);
	 if (mp_cmp(&d, &e) != MP_EQ) {
	    printf("expt %lu failure!\n", expt_n);
	    draw(&a);
	    draw(&b);
	    draw(&c);
	    draw(&d);
	    draw(&e);
	    return 0;
	 }
      } else if (!strcmp(cmd, "invmod")) {
	 ++inv_n;
	 fgets(buf, 4095, stdin);
	 mp_read_radix(&a, buf, 64);
	 fgets(buf, 4095, stdin);
	 mp_read_radix(&b, buf, 64);
	 fgets(buf, 4095, stdin);
	 mp_read_radix(&c, buf, 64);
	 mp_invmod(&a, &b, &d);
	 mp_mulmod(&d, &a, &b, &e);
	 if (mp_cmp_d(&e, 1) != MP_EQ) {
	    printf("inv [wrong value from MPI?!] failure\n");
	    draw(&a);
	    draw(&b);
	    draw(&c);
	    draw(&d);
	    mp_gcd(&a, &b, &e);
	    draw(&e);
	    return 0;
	 }

      } else if (!strcmp(cmd, "div2")) {
	 ++div2_n;
	 fgets(buf, 4095, stdin);
	 mp_read_radix(&a, buf, 64);
	 fgets(buf, 4095, stdin);
	 mp_read_radix(&b, buf, 64);
	 mp_div_2(&a, &c);
	 if (mp_cmp(&c, &b) != MP_EQ) {
	    printf("div_2 %lu failure\n", div2_n);
	    draw(&a);
	    draw(&b);
	    draw(&c);
	    return 0;
	 }
      } else if (!strcmp(cmd, "mul2")) {
	 ++mul2_n;
	 fgets(buf, 4095, stdin);
	 mp_read_radix(&a, buf, 64);
	 fgets(buf, 4095, stdin);
	 mp_read_radix(&b, buf, 64);
	 mp_mul_2(&a, &c);
	 if (mp_cmp(&c, &b) != MP_EQ) {
	    printf("mul_2 %lu failure\n", mul2_n);
	    draw(&a);
	    draw(&b);
	    draw(&c);
	    return 0;
	 }
      } else if (!strcmp(cmd, "add_d")) {
	 ++add_d_n;
	 fgets(buf, 4095, stdin);
	 mp_read_radix(&a, buf, 64);
	 fgets(buf, 4095, stdin);
	 sscanf(buf, "%d", &ix);
	 fgets(buf, 4095, stdin);
	 mp_read_radix(&b, buf, 64);
	 mp_add_d(&a, ix, &c);
	 if (mp_cmp(&b, &c) != MP_EQ) {
	    printf("add_d %lu failure\n", add_d_n);
	    draw(&a);
	    draw(&b);
	    draw(&c);
	    printf("d == %d\n", ix);
	    return 0;
	 }
      } else if (!strcmp(cmd, "sub_d")) {
	 ++sub_d_n;
	 fgets(buf, 4095, stdin);
	 mp_read_radix(&a, buf, 64);
	 fgets(buf, 4095, stdin);
	 sscanf(buf, "%d", &ix);
	 fgets(buf, 4095, stdin);
	 mp_read_radix(&b, buf, 64);
	 mp_sub_d(&a, ix, &c);
	 if (mp_cmp(&b, &c) != MP_EQ) {
	    printf("sub_d %lu failure\n", sub_d_n);
	    draw(&a);
	    draw(&b);
	    draw(&c);
	    printf("d == %d\n", ix);
	    return 0;
	 }
      }
   }
   return 0;
}
Exemplo n.º 8
0
/* computes the jacobi c = (a | n) (or Legendre if n is prime)
 * HAC pp. 73 Algorithm 2.149
 * HAC is wrong here, as the special case of (0 | 1) is not
 * handled correctly.
 */
int mp_jacobi(const mp_int *a, const mp_int *n, int *c)
{
   mp_int  a1, p1;
   int     k, s, r, res;
   mp_digit residue;

   /* if a < 0 return MP_VAL */
   if (mp_isneg(a) == MP_YES) {
      return MP_VAL;
   }

   /* if n <= 0 return MP_VAL */
   if (mp_cmp_d(n, 0uL) != MP_GT) {
      return MP_VAL;
   }

   /* step 1. handle case of a == 0 */
   if (mp_iszero(a) == MP_YES) {
      /* special case of a == 0 and n == 1 */
      if (mp_cmp_d(n, 1uL) == MP_EQ) {
         *c = 1;
      } else {
         *c = 0;
      }
      return MP_OKAY;
   }

   /* step 2.  if a == 1, return 1 */
   if (mp_cmp_d(a, 1uL) == MP_EQ) {
      *c = 1;
      return MP_OKAY;
   }

   /* default */
   s = 0;

   /* step 3.  write a = a1 * 2**k  */
   if ((res = mp_init_copy(&a1, a)) != MP_OKAY) {
      return res;
   }

   if ((res = mp_init(&p1)) != MP_OKAY) {
      goto LBL_A1;
   }

   /* divide out larger power of two */
   k = mp_cnt_lsb(&a1);
   if ((res = mp_div_2d(&a1, k, &a1, NULL)) != MP_OKAY) {
      goto LBL_P1;
   }

   /* step 4.  if e is even set s=1 */
   if (((unsigned)k & 1u) == 0u) {
      s = 1;
   } else {
      /* else set s=1 if p = 1/7 (mod 8) or s=-1 if p = 3/5 (mod 8) */
      residue = n->dp[0] & 7u;

      if ((residue == 1u) || (residue == 7u)) {
         s = 1;
      } else if ((residue == 3u) || (residue == 5u)) {
         s = -1;
      }
   }

   /* step 5.  if p == 3 (mod 4) *and* a1 == 3 (mod 4) then s = -s */
   if (((n->dp[0] & 3u) == 3u) && ((a1.dp[0] & 3u) == 3u)) {
      s = -s;
   }

   /* if a1 == 1 we're done */
   if (mp_cmp_d(&a1, 1uL) == MP_EQ) {
      *c = s;
   } else {
      /* n1 = n mod a1 */
      if ((res = mp_mod(n, &a1, &p1)) != MP_OKAY) {
         goto LBL_P1;
      }
      if ((res = mp_jacobi(&p1, &a1, &r)) != MP_OKAY) {
         goto LBL_P1;
      }
      *c = s * r;
   }

   /* done */
   res = MP_OKAY;
LBL_P1:
   mp_clear(&p1);
LBL_A1:
   mp_clear(&a1);
   return res;
}
/*
    Strong Lucas-Selfridge test.
    returns MP_YES if it is a strong L-S prime, MP_NO if it is composite

    Code ported from  Thomas Ray Nicely's implementation of the BPSW test
    at http://www.trnicely.net/misc/bpsw.html

    Freeware copyright (C) 2016 Thomas R. Nicely <http://www.trnicely.net>.
    Released into the public domain by the author, who disclaims any legal
    liability arising from its use

    The multi-line comments are made by Thomas R. Nicely and are copied verbatim.
    Additional comments marked "CZ" (without the quotes) are by the code-portist.

    (If that name sounds familiar, he is the guy who found the fdiv bug in the
     Pentium (P5x, I think) Intel processor)
*/
int mp_prime_strong_lucas_selfridge(const mp_int *a, int *result)
{
   /* CZ TODO: choose better variable names! */
   mp_int Dz, gcd, Np1, Uz, Vz, U2mz, V2mz, Qmz, Q2mz, Qkdz, T1z, T2z, T3z, T4z, Q2kdz;
   /* CZ TODO: Some of them need the full 32 bit, hence the (temporary) exclusion of MP_8BIT */
   int32_t D, Ds, J, sign, P, Q, r, s, u, Nbits;
   int e;
   int isset;

   *result = MP_NO;

   /*
   Find the first element D in the sequence {5, -7, 9, -11, 13, ...}
   such that Jacobi(D,N) = -1 (Selfridge's algorithm). Theory
   indicates that, if N is not a perfect square, D will "nearly
   always" be "small." Just in case, an overflow trap for D is
   included.
   */

   if ((e = mp_init_multi(&Dz, &gcd, &Np1, &Uz, &Vz, &U2mz, &V2mz, &Qmz, &Q2mz, &Qkdz, &T1z, &T2z, &T3z, &T4z, &Q2kdz,
                          NULL)) != MP_OKAY) {
      return e;
   }

   D = 5;
   sign = 1;

   for (;;) {
      Ds   = sign * D;
      sign = -sign;
      if ((e = mp_set_long(&Dz, (unsigned long)D)) != MP_OKAY) {
         goto LBL_LS_ERR;
      }
      if ((e = mp_gcd(a, &Dz, &gcd)) != MP_OKAY) {
         goto LBL_LS_ERR;
      }
      /* if 1 < GCD < N then N is composite with factor "D", and
         Jacobi(D,N) is technically undefined (but often returned
         as zero). */
      if ((mp_cmp_d(&gcd, 1uL) == MP_GT) && (mp_cmp(&gcd, a) == MP_LT)) {
         goto LBL_LS_ERR;
      }
      if (Ds < 0) {
         Dz.sign = MP_NEG;
      }
      if ((e = mp_kronecker(&Dz, a, &J)) != MP_OKAY) {
         goto LBL_LS_ERR;
      }

      if (J == -1) {
         break;
      }
      D += 2;

      if (D > (INT_MAX - 2)) {
         e = MP_VAL;
         goto LBL_LS_ERR;
      }
   }

   P = 1;              /* Selfridge's choice */
   Q = (1 - Ds) / 4;   /* Required so D = P*P - 4*Q */

   /* NOTE: The conditions (a) N does not divide Q, and
      (b) D is square-free or not a perfect square, are included by
      some authors; e.g., "Prime numbers and computer methods for
      factorization," Hans Riesel (2nd ed., 1994, Birkhauser, Boston),
      p. 130. For this particular application of Lucas sequences,
      these conditions were found to be immaterial. */

   /* Now calculate N - Jacobi(D,N) = N + 1 (even), and calculate the
      odd positive integer d and positive integer s for which
      N + 1 = 2^s*d (similar to the step for N - 1 in Miller's test).
      The strong Lucas-Selfridge test then returns N as a strong
      Lucas probable prime (slprp) if any of the following
      conditions is met: U_d=0, V_d=0, V_2d=0, V_4d=0, V_8d=0,
      V_16d=0, ..., etc., ending with V_{2^(s-1)*d}=V_{(N+1)/2}=0
      (all equalities mod N). Thus d is the highest index of U that
      must be computed (since V_2m is independent of U), compared
      to U_{N+1} for the standard Lucas-Selfridge test; and no
      index of V beyond (N+1)/2 is required, just as in the
      standard Lucas-Selfridge test. However, the quantity Q^d must
      be computed for use (if necessary) in the latter stages of
      the test. The result is that the strong Lucas-Selfridge test
      has a running time only slightly greater (order of 10 %) than
      that of the standard Lucas-Selfridge test, while producing
      only (roughly) 30 % as many pseudoprimes (and every strong
      Lucas pseudoprime is also a standard Lucas pseudoprime). Thus
      the evidence indicates that the strong Lucas-Selfridge test is
      more effective than the standard Lucas-Selfridge test, and a
      Baillie-PSW test based on the strong Lucas-Selfridge test
      should be more reliable. */

   if ((e = mp_add_d(a, 1uL, &Np1)) != MP_OKAY) {
      goto LBL_LS_ERR;
   }
   s = mp_cnt_lsb(&Np1);

   /* CZ
    * This should round towards zero because
    * Thomas R. Nicely used GMP's mpz_tdiv_q_2exp()
    * and mp_div_2d() is equivalent. Additionally:
    * dividing an even number by two does not produce
    * any leftovers.
    */
   if ((e = mp_div_2d(&Np1, s, &Dz, NULL)) != MP_OKAY) {
      goto LBL_LS_ERR;
   }
   /* We must now compute U_d and V_d. Since d is odd, the accumulated
      values U and V are initialized to U_1 and V_1 (if the target
      index were even, U and V would be initialized instead to U_0=0
      and V_0=2). The values of U_2m and V_2m are also initialized to
      U_1 and V_1; the FOR loop calculates in succession U_2 and V_2,
      U_4 and V_4, U_8 and V_8, etc. If the corresponding bits
      (1, 2, 3, ...) of t are on (the zero bit having been accounted
      for in the initialization of U and V), these values are then
      combined with the previous totals for U and V, using the
      composition formulas for addition of indices. */

   mp_set(&Uz, 1uL);    /* U=U_1 */
   mp_set(&Vz, (mp_digit)P);    /* V=V_1 */
   mp_set(&U2mz, 1uL);  /* U_1 */
   mp_set(&V2mz, (mp_digit)P);  /* V_1 */

   if (Q < 0) {
      Q = -Q;
      if ((e = mp_set_long(&Qmz, (unsigned long)Q)) != MP_OKAY) {
         goto LBL_LS_ERR;
      }
      if ((e = mp_mul_2(&Qmz, &Q2mz)) != MP_OKAY) {
         goto LBL_LS_ERR;
      }
      /* Initializes calculation of Q^d */
      if ((e = mp_set_long(&Qkdz, (unsigned long)Q)) != MP_OKAY) {
         goto LBL_LS_ERR;
      }
      Qmz.sign = MP_NEG;
      Q2mz.sign = MP_NEG;
      Qkdz.sign = MP_NEG;
      Q = -Q;
   } else {
      if ((e = mp_set_long(&Qmz, (unsigned long)Q)) != MP_OKAY) {
         goto LBL_LS_ERR;
      }
      if ((e = mp_mul_2(&Qmz, &Q2mz)) != MP_OKAY) {
         goto LBL_LS_ERR;
      }
      /* Initializes calculation of Q^d */
      if ((e = mp_set_long(&Qkdz, (unsigned long)Q)) != MP_OKAY) {
         goto LBL_LS_ERR;
      }
   }

   Nbits = mp_count_bits(&Dz);
   for (u = 1; u < Nbits; u++) { /* zero bit off, already accounted for */
      /* Formulas for doubling of indices (carried out mod N). Note that
       * the indices denoted as "2m" are actually powers of 2, specifically
       * 2^(ul-1) beginning each loop and 2^ul ending each loop.
       *
       * U_2m = U_m*V_m
       * V_2m = V_m*V_m - 2*Q^m
       */

      if ((e = mp_mul(&U2mz, &V2mz, &U2mz)) != MP_OKAY) {
         goto LBL_LS_ERR;
      }
      if ((e = mp_mod(&U2mz, a, &U2mz)) != MP_OKAY) {
         goto LBL_LS_ERR;
      }
      if ((e = mp_sqr(&V2mz, &V2mz)) != MP_OKAY) {
         goto LBL_LS_ERR;
      }
      if ((e = mp_sub(&V2mz, &Q2mz, &V2mz)) != MP_OKAY) {
         goto LBL_LS_ERR;
      }
      if ((e = mp_mod(&V2mz, a, &V2mz)) != MP_OKAY) {
         goto LBL_LS_ERR;
      }
      /* Must calculate powers of Q for use in V_2m, also for Q^d later */
      if ((e = mp_sqr(&Qmz, &Qmz)) != MP_OKAY) {
         goto LBL_LS_ERR;
      }
      /* prevents overflow */ /* CZ  still necessary without a fixed prealloc'd mem.? */
      if ((e = mp_mod(&Qmz, a, &Qmz)) != MP_OKAY) {
         goto LBL_LS_ERR;
      }
      if ((e = mp_mul_2(&Qmz, &Q2mz)) != MP_OKAY) {
         goto LBL_LS_ERR;
      }

      if ((isset = mp_get_bit(&Dz, u)) == MP_VAL) {
         e = isset;
         goto LBL_LS_ERR;
      }
      if (isset == MP_YES) {
         /* Formulas for addition of indices (carried out mod N);
          *
          * U_(m+n) = (U_m*V_n + U_n*V_m)/2
          * V_(m+n) = (V_m*V_n + D*U_m*U_n)/2
          *
          * Be careful with division by 2 (mod N)!
          */

         if ((e = mp_mul(&U2mz, &Vz, &T1z)) != MP_OKAY) {
            goto LBL_LS_ERR;
         }
         if ((e = mp_mul(&Uz, &V2mz, &T2z)) != MP_OKAY) {
            goto LBL_LS_ERR;
         }
         if ((e = mp_mul(&V2mz, &Vz, &T3z)) != MP_OKAY) {
            goto LBL_LS_ERR;
         }
         if ((e = mp_mul(&U2mz, &Uz, &T4z)) != MP_OKAY) {
            goto LBL_LS_ERR;
         }
         if ((e = s_mp_mul_si(&T4z, (long)Ds, &T4z)) != MP_OKAY) {
            goto LBL_LS_ERR;
         }
         if ((e = mp_add(&T1z, &T2z, &Uz)) != MP_OKAY) {
            goto LBL_LS_ERR;
         }
         if (mp_isodd(&Uz) != MP_NO) {
            if ((e = mp_add(&Uz, a, &Uz)) != MP_OKAY) {
               goto LBL_LS_ERR;
            }
         }
         /* CZ
          * This should round towards negative infinity because
          * Thomas R. Nicely used GMP's mpz_fdiv_q_2exp().
          * But mp_div_2() does not do so, it is truncating instead.
          */
         if ((e = mp_div_2(&Uz, &Uz)) != MP_OKAY) {
            goto LBL_LS_ERR;
         }
         if ((Uz.sign == MP_NEG) && (mp_isodd(&Uz) != MP_NO)) {
            if ((e = mp_sub_d(&Uz, 1uL, &Uz)) != MP_OKAY) {
               goto LBL_LS_ERR;
            }
         }
         if ((e = mp_add(&T3z, &T4z, &Vz)) != MP_OKAY) {
            goto LBL_LS_ERR;
         }
         if (mp_isodd(&Vz) != MP_NO) {
            if ((e = mp_add(&Vz, a, &Vz)) != MP_OKAY) {
               goto LBL_LS_ERR;
            }
         }
         if ((e = mp_div_2(&Vz, &Vz)) != MP_OKAY) {
            goto LBL_LS_ERR;
         }
         if ((Vz.sign == MP_NEG) && (mp_isodd(&Vz) != MP_NO)) {
            if ((e = mp_sub_d(&Vz, 1uL, &Vz)) != MP_OKAY) {
               goto LBL_LS_ERR;
            }
         }
         if ((e = mp_mod(&Uz, a, &Uz)) != MP_OKAY) {
            goto LBL_LS_ERR;
         }
         if ((e = mp_mod(&Vz, a, &Vz)) != MP_OKAY) {
            goto LBL_LS_ERR;
         }
         /* Calculating Q^d for later use */
         if ((e = mp_mul(&Qkdz, &Qmz, &Qkdz)) != MP_OKAY) {
            goto LBL_LS_ERR;
         }
         if ((e = mp_mod(&Qkdz, a, &Qkdz)) != MP_OKAY) {
            goto LBL_LS_ERR;
         }
      }
   }

   /* If U_d or V_d is congruent to 0 mod N, then N is a prime or a
      strong Lucas pseudoprime. */
   if ((mp_iszero(&Uz) != MP_NO) || (mp_iszero(&Vz) != MP_NO)) {
      *result = MP_YES;
      goto LBL_LS_ERR;
   }

   /* NOTE: Ribenboim ("The new book of prime number records," 3rd ed.,
      1995/6) omits the condition V0 on p.142, but includes it on
      p. 130. The condition is NECESSARY; otherwise the test will
      return false negatives---e.g., the primes 29 and 2000029 will be
      returned as composite. */

   /* Otherwise, we must compute V_2d, V_4d, V_8d, ..., V_{2^(s-1)*d}
      by repeated use of the formula V_2m = V_m*V_m - 2*Q^m. If any of
      these are congruent to 0 mod N, then N is a prime or a strong
      Lucas pseudoprime. */

   /* Initialize 2*Q^(d*2^r) for V_2m */
   if ((e = mp_mul_2(&Qkdz, &Q2kdz)) != MP_OKAY) {
      goto LBL_LS_ERR;
   }

   for (r = 1; r < s; r++) {
      if ((e = mp_sqr(&Vz, &Vz)) != MP_OKAY) {
         goto LBL_LS_ERR;
      }
      if ((e = mp_sub(&Vz, &Q2kdz, &Vz)) != MP_OKAY) {
         goto LBL_LS_ERR;
      }
      if ((e = mp_mod(&Vz, a, &Vz)) != MP_OKAY) {
         goto LBL_LS_ERR;
      }
      if (mp_iszero(&Vz) != MP_NO) {
         *result = MP_YES;
         goto LBL_LS_ERR;
      }
      /* Calculate Q^{d*2^r} for next r (final iteration irrelevant). */
      if (r < (s - 1)) {
         if ((e = mp_sqr(&Qkdz, &Qkdz)) != MP_OKAY) {
            goto LBL_LS_ERR;
         }
         if ((e = mp_mod(&Qkdz, a, &Qkdz)) != MP_OKAY) {
            goto LBL_LS_ERR;
         }
         if ((e = mp_mul_2(&Qkdz, &Q2kdz)) != MP_OKAY) {
            goto LBL_LS_ERR;
         }
      }
   }
LBL_LS_ERR:
   mp_clear_multi(&Q2kdz, &T4z, &T3z, &T2z, &T1z, &Qkdz, &Q2mz, &Qmz, &V2mz, &U2mz, &Vz, &Uz, &Np1, &gcd, &Dz, NULL);
   return e;
}
Exemplo n.º 10
0
Arquivo: demo.c Projeto: mkj/dropbear
int main(void)
{
   unsigned rr;
   int cnt, ix;
#if LTM_DEMO_TEST_VS_MTEST
   unsigned long expt_n, add_n, sub_n, mul_n, div_n, sqr_n, mul2d_n, div2d_n,
      gcd_n, lcm_n, inv_n, div2_n, mul2_n, add_d_n, sub_d_n;
   char* ret;
#else
   unsigned long s, t;
   unsigned long long q, r;
   mp_digit mp;
   int i, n, err, should;
#endif

   if (mp_init_multi(&a, &b, &c, &d, &e, &f, NULL)!= MP_OKAY)
     return EXIT_FAILURE;

   atexit(_cleanup);

#if defined(LTM_DEMO_REAL_RAND)
   if (!fd_urandom) {
      fd_urandom = fopen("/dev/urandom", "r");
      if (!fd_urandom) {
#if !defined(_WIN32)
         fprintf(stderr, "\ncould not open /dev/urandom\n");
#endif
      }
   }
#endif
   srand(LTM_DEMO_RAND_SEED);

#ifdef MP_8BIT
   printf("Digit size 8 Bit \n");
#endif
#ifdef MP_16BIT
   printf("Digit size 16 Bit \n");
#endif
#ifdef MP_32BIT
   printf("Digit size 32 Bit \n");
#endif
#ifdef MP_64BIT
   printf("Digit size 64 Bit \n");
#endif
   printf("Size of mp_digit: %u\n", (unsigned int)sizeof(mp_digit));
   printf("Size of mp_word: %u\n", (unsigned int)sizeof(mp_word));
   printf("DIGIT_BIT: %d\n", DIGIT_BIT);
   printf("MP_PREC: %d\n", MP_PREC);

#if LTM_DEMO_TEST_VS_MTEST == 0
   // trivial stuff
   // a: 0->5
   mp_set_int(&a, 5);
   // a: 5-> b: -5
   mp_neg(&a, &b);
   if (mp_cmp(&a, &b) != MP_GT) {
      return EXIT_FAILURE;
   }
   if (mp_cmp(&b, &a) != MP_LT) {
      return EXIT_FAILURE;
   }
   // a: 5-> a: -5
   mp_neg(&a, &a);
   if (mp_cmp(&b, &a) != MP_EQ) {
      return EXIT_FAILURE;
   }
   // a: -5-> b: 5
   mp_abs(&a, &b);
   if (mp_isneg(&b) != MP_NO) {
      return EXIT_FAILURE;
   }
   // a: -5-> b: -4
   mp_add_d(&a, 1, &b);
   if (mp_isneg(&b) != MP_YES) {
      return EXIT_FAILURE;
   }
   if (mp_get_int(&b) != 4) {
      return EXIT_FAILURE;
   }
   // a: -5-> b: 1
   mp_add_d(&a, 6, &b);
   if (mp_get_int(&b) != 1) {
      return EXIT_FAILURE;
   }
   // a: -5-> a: 1
   mp_add_d(&a, 6, &a);
   if (mp_get_int(&a) != 1) {
      return EXIT_FAILURE;
   }
   mp_zero(&a);
   // a: 0-> a: 6
   mp_add_d(&a, 6, &a);
   if (mp_get_int(&a) != 6) {
      return EXIT_FAILURE;
   }


   mp_set_int(&a, 0);
   mp_set_int(&b, 1);
   if ((err = mp_jacobi(&a, &b, &i)) != MP_OKAY) {
      printf("Failed executing mp_jacobi(0 | 1) %s.\n", mp_error_to_string(err));
      return EXIT_FAILURE;
   }
   if (i != 1) {
      printf("Failed trivial mp_jacobi(0 | 1) %d != 1\n", i);
      return EXIT_FAILURE;
   }
   for (cnt = 0; cnt < (int)(sizeof(jacobi)/sizeof(jacobi[0])); ++cnt) {
      mp_set_int(&b, jacobi[cnt].n);
      /* only test positive values of a */
      for (n = -5; n <= 10; ++n) {
         mp_set_int(&a, abs(n));
         should = MP_OKAY;
         if (n < 0) {
            mp_neg(&a, &a);
            /* Until #44 is fixed the negative a's must fail */
            should = MP_VAL;
         }
         if ((err = mp_jacobi(&a, &b, &i)) != should) {
            printf("Failed executing mp_jacobi(%d | %lu) %s.\n", n, jacobi[cnt].n, mp_error_to_string(err));
            return EXIT_FAILURE;
         }
         if (err == MP_OKAY && i != jacobi[cnt].c[n + 5]) {
            printf("Failed trivial mp_jacobi(%d | %lu) %d != %d\n", n, jacobi[cnt].n, i, jacobi[cnt].c[n + 5]);
            return EXIT_FAILURE;
         }
      }
   }

   // test mp_get_int
   printf("\n\nTesting: mp_get_int");
   for (i = 0; i < 1000; ++i) {
      t = ((unsigned long) rand () * rand () + 1) & 0xFFFFFFFF;
      mp_set_int (&a, t);
      if (t != mp_get_int (&a)) {
         printf ("\nmp_get_int() bad result!");
         return EXIT_FAILURE;
      }
   }
   mp_set_int(&a, 0);
   if (mp_get_int(&a) != 0) {
      printf("\nmp_get_int() bad result!");
      return EXIT_FAILURE;
   }
   mp_set_int(&a, 0xffffffff);
   if (mp_get_int(&a) != 0xffffffff) {
      printf("\nmp_get_int() bad result!");
      return EXIT_FAILURE;
   }

   printf("\n\nTesting: mp_get_long\n");
   for (i = 0; i < (int)(sizeof(unsigned long)*CHAR_BIT) - 1; ++i) {
      t = (1ULL << (i+1)) - 1;
      if (!t)
         t = -1;
      printf(" t = 0x%lx i = %d\r", t, i);
      do {
         if (mp_set_long(&a, t) != MP_OKAY) {
            printf("\nmp_set_long() error!");
            return EXIT_FAILURE;
         }
         s = mp_get_long(&a);
         if (s != t) {
            printf("\nmp_get_long() bad result! 0x%lx != 0x%lx", s, t);
            return EXIT_FAILURE;
         }
         t <<= 1;
      } while(t);
   }

   printf("\n\nTesting: mp_get_long_long\n");
   for (i = 0; i < (int)(sizeof(unsigned long long)*CHAR_BIT) - 1; ++i) {
      r = (1ULL << (i+1)) - 1;
      if (!r)
         r = -1;
      printf(" r = 0x%llx i = %d\r", r, i);
      do {
         if (mp_set_long_long(&a, r) != MP_OKAY) {
            printf("\nmp_set_long_long() error!");
            return EXIT_FAILURE;
         }
         q = mp_get_long_long(&a);
         if (q != r) {
            printf("\nmp_get_long_long() bad result! 0x%llx != 0x%llx", q, r);
            return EXIT_FAILURE;
         }
         r <<= 1;
      } while(r);
   }

   // test mp_sqrt
   printf("\n\nTesting: mp_sqrt\n");
   for (i = 0; i < 1000; ++i) {
      printf ("%6d\r", i);
      fflush (stdout);
      n = (rand () & 15) + 1;
      mp_rand (&a, n);
      if (mp_sqrt (&a, &b) != MP_OKAY) {
         printf ("\nmp_sqrt() error!");
         return EXIT_FAILURE;
      }
      mp_n_root_ex (&a, 2, &c, 0);
      mp_n_root_ex (&a, 2, &d, 1);
      if (mp_cmp_mag (&c, &d) != MP_EQ) {
         printf ("\nmp_n_root_ex() bad result!");
         return EXIT_FAILURE;
      }
      if (mp_cmp_mag (&b, &c) != MP_EQ) {
         printf ("mp_sqrt() bad result!\n");
         return EXIT_FAILURE;
      }
   }

   printf("\n\nTesting: mp_is_square\n");
   for (i = 0; i < 1000; ++i) {
      printf ("%6d\r", i);
      fflush (stdout);

      /* test mp_is_square false negatives */
      n = (rand () & 7) + 1;
      mp_rand (&a, n);
      mp_sqr (&a, &a);
      if (mp_is_square (&a, &n) != MP_OKAY) {
         printf ("\nfn:mp_is_square() error!");
         return EXIT_FAILURE;
      }
      if (n == 0) {
         printf ("\nfn:mp_is_square() bad result!");
         return EXIT_FAILURE;
      }

      /* test for false positives */
      mp_add_d (&a, 1, &a);
      if (mp_is_square (&a, &n) != MP_OKAY) {
         printf ("\nfp:mp_is_square() error!");
         return EXIT_FAILURE;
      }
      if (n == 1) {
         printf ("\nfp:mp_is_square() bad result!");
         return EXIT_FAILURE;
      }

   }
   printf("\n\n");

   // r^2 = n (mod p)
   for (i = 0; i < (int)(sizeof(sqrtmod_prime)/sizeof(sqrtmod_prime[0])); ++i) {
      mp_set_int(&a, sqrtmod_prime[i].p);
      mp_set_int(&b, sqrtmod_prime[i].n);
      if (mp_sqrtmod_prime(&b, &a, &c) != MP_OKAY) {
         printf("Failed executing %d. mp_sqrtmod_prime\n", (i+1));
         return EXIT_FAILURE;
      }
      if (mp_cmp_d(&c, sqrtmod_prime[i].r) != MP_EQ) {
         printf("Failed %d. trivial mp_sqrtmod_prime\n", (i+1));
         ndraw(&c, "r");
         return EXIT_FAILURE;
      }
   }

   /* test for size */
   for (ix = 10; ix < 128; ix++) {
      printf ("Testing (not safe-prime): %9d bits    \r", ix);
      fflush (stdout);
      err = mp_prime_random_ex (&a, 8, ix,
                                (rand () & 1) ? 0 : LTM_PRIME_2MSB_ON, myrng,
                                NULL);
      if (err != MP_OKAY) {
         printf ("failed with err code %d\n", err);
         return EXIT_FAILURE;
      }
      if (mp_count_bits (&a) != ix) {
         printf ("Prime is %d not %d bits!!!\n", mp_count_bits (&a), ix);
         return EXIT_FAILURE;
      }
   }
   printf("\n");

   for (ix = 16; ix < 128; ix++) {
      printf ("Testing (    safe-prime): %9d bits    \r", ix);
      fflush (stdout);
      err = mp_prime_random_ex (
            &a, 8, ix, ((rand () & 1) ? 0 : LTM_PRIME_2MSB_ON) | LTM_PRIME_SAFE,
            myrng, NULL);
      if (err != MP_OKAY) {
         printf ("failed with err code %d\n", err);
         return EXIT_FAILURE;
      }
      if (mp_count_bits (&a) != ix) {
         printf ("Prime is %d not %d bits!!!\n", mp_count_bits (&a), ix);
         return EXIT_FAILURE;
      }
      /* let's see if it's really a safe prime */
      mp_sub_d (&a, 1, &a);
      mp_div_2 (&a, &a);
      mp_prime_is_prime (&a, 8, &cnt);
      if (cnt != MP_YES) {
         printf ("sub is not prime!\n");
         return EXIT_FAILURE;
      }
   }

   printf("\n\n");

   // test montgomery
   printf("Testing: montgomery...\n");
   for (i = 1; i <= 10; i++) {
      if (i == 10)
         i = 1000;
      printf(" digit size: %2d\r", i);
      fflush(stdout);
      for (n = 0; n < 1000; n++) {
         mp_rand(&a, i);
         a.dp[0] |= 1;

         // let's see if R is right
         mp_montgomery_calc_normalization(&b, &a);
         mp_montgomery_setup(&a, &mp);

         // now test a random reduction
         for (ix = 0; ix < 100; ix++) {
             mp_rand(&c, 1 + abs(rand()) % (2*i));
             mp_copy(&c, &d);
             mp_copy(&c, &e);

             mp_mod(&d, &a, &d);
             mp_montgomery_reduce(&c, &a, mp);
             mp_mulmod(&c, &b, &a, &c);

             if (mp_cmp(&c, &d) != MP_EQ) {
printf("d = e mod a, c = e MOD a\n");
mp_todecimal(&a, buf); printf("a = %s\n", buf);
mp_todecimal(&e, buf); printf("e = %s\n", buf);
mp_todecimal(&d, buf); printf("d = %s\n", buf);
mp_todecimal(&c, buf); printf("c = %s\n", buf);
printf("compare no compare!\n"); return EXIT_FAILURE; }
             /* only one big montgomery reduction */
             if (i > 10)
             {
                n = 1000;
                ix = 100;
             }
         }
      }
   }

   printf("\n\n");

   mp_read_radix(&a, "123456", 10);
   mp_toradix_n(&a, buf, 10, 3);
   printf("a == %s\n", buf);
   mp_toradix_n(&a, buf, 10, 4);
   printf("a == %s\n", buf);
   mp_toradix_n(&a, buf, 10, 30);
   printf("a == %s\n", buf);


#if 0
   for (;;) {
      fgets(buf, sizeof(buf), stdin);
      mp_read_radix(&a, buf, 10);
      mp_prime_next_prime(&a, 5, 1);
      mp_toradix(&a, buf, 10);
      printf("%s, %lu\n", buf, a.dp[0] & 3);
   }
#endif

   /* test mp_cnt_lsb */
   printf("\n\nTesting: mp_cnt_lsb");
   mp_set(&a, 1);
   for (ix = 0; ix < 1024; ix++) {
      if (mp_cnt_lsb (&a) != ix) {
         printf ("Failed at %d, %d\n", ix, mp_cnt_lsb (&a));
         return EXIT_FAILURE;
      }
      mp_mul_2 (&a, &a);
   }

/* test mp_reduce_2k */
   printf("\n\nTesting: mp_reduce_2k\n");
   for (cnt = 3; cnt <= 128; ++cnt) {
      mp_digit tmp;

      mp_2expt (&a, cnt);
      mp_sub_d (&a, 2, &a); /* a = 2**cnt - 2 */

      printf ("\r %4d bits", cnt);
      printf ("(%d)", mp_reduce_is_2k (&a));
      mp_reduce_2k_setup (&a, &tmp);
      printf ("(%lu)", (unsigned long) tmp);
      for (ix = 0; ix < 1000; ix++) {
         if (!(ix & 127)) {
            printf (".");
            fflush (stdout);
         }
         mp_rand (&b, (cnt / DIGIT_BIT + 1) * 2);
         mp_copy (&c, &b);
         mp_mod (&c, &a, &c);
         mp_reduce_2k (&b, &a, 2);
         if (mp_cmp (&c, &b)) {
            printf ("FAILED\n");
            return EXIT_FAILURE;
         }
      }
   }

/* test mp_div_3  */
   printf("\n\nTesting: mp_div_3...\n");
   mp_set(&d, 3);
   for (cnt = 0; cnt < 10000;) {
      mp_digit r2;

      if (!(++cnt & 127))
      {
        printf("%9d\r", cnt);
        fflush(stdout);
      }
      mp_rand(&a, abs(rand()) % 128 + 1);
      mp_div(&a, &d, &b, &e);
      mp_div_3(&a, &c, &r2);

      if (mp_cmp(&b, &c) || mp_cmp_d(&e, r2)) {
	 printf("\nmp_div_3 => Failure\n");
      }
   }
   printf("\nPassed div_3 testing");

/* test the DR reduction */
   printf("\n\nTesting: mp_dr_reduce...\n");
   for (cnt = 2; cnt < 32; cnt++) {
      printf ("\r%d digit modulus", cnt);
      mp_grow (&a, cnt);
      mp_zero (&a);
      for (ix = 1; ix < cnt; ix++) {
         a.dp[ix] = MP_MASK;
      }
      a.used = cnt;
      a.dp[0] = 3;

      mp_rand (&b, cnt - 1);
      mp_copy (&b, &c);

      rr = 0;
      do {
         if (!(rr & 127)) {
            printf (".");
            fflush (stdout);
         }
         mp_sqr (&b, &b);
         mp_add_d (&b, 1, &b);
         mp_copy (&b, &c);

         mp_mod (&b, &a, &b);
         mp_dr_setup(&a, &mp),
         mp_dr_reduce (&c, &a, mp);

         if (mp_cmp (&b, &c) != MP_EQ) {
            printf ("Failed on trial %u\n", rr);
            return EXIT_FAILURE;
         }
      } while (++rr < 500);
      printf (" passed");
      fflush (stdout);
   }

#if LTM_DEMO_TEST_REDUCE_2K_L
/* test the mp_reduce_2k_l code */
#if LTM_DEMO_TEST_REDUCE_2K_L == 1
/* first load P with 2^1024 - 0x2A434 B9FDEC95 D8F9D550 FFFFFFFF FFFFFFFF */
   mp_2expt(&a, 1024);
   mp_read_radix(&b, "2A434B9FDEC95D8F9D550FFFFFFFFFFFFFFFF", 16);
   mp_sub(&a, &b, &a);
#elif LTM_DEMO_TEST_REDUCE_2K_L == 2
/*  p = 2^2048 - 0x1 00000000 00000000 00000000 00000000 4945DDBF 8EA2A91D 5776399B B83E188F  */
   mp_2expt(&a, 2048);
   mp_read_radix(&b,
		 "1000000000000000000000000000000004945DDBF8EA2A91D5776399BB83E188F",
		 16);
   mp_sub(&a, &b, &a);
#else
#error oops
#endif

   mp_todecimal(&a, buf);
   printf("\n\np==%s\n", buf);
/* now mp_reduce_is_2k_l() should return */
   if (mp_reduce_is_2k_l(&a) != 1) {
      printf("mp_reduce_is_2k_l() return 0, should be 1\n");
      return EXIT_FAILURE;
   }
   mp_reduce_2k_setup_l(&a, &d);
   /* now do a million square+1 to see if it varies */
   mp_rand(&b, 64);
   mp_mod(&b, &a, &b);
   mp_copy(&b, &c);
   printf("Testing: mp_reduce_2k_l...");
   fflush(stdout);
   for (cnt = 0; cnt < (int)(1UL << 20); cnt++) {
      mp_sqr(&b, &b);
      mp_add_d(&b, 1, &b);
      mp_reduce_2k_l(&b, &a, &d);
      mp_sqr(&c, &c);
      mp_add_d(&c, 1, &c);
      mp_mod(&c, &a, &c);
      if (mp_cmp(&b, &c) != MP_EQ) {
	 printf("mp_reduce_2k_l() failed at step %d\n", cnt);
	 mp_tohex(&b, buf);
	 printf("b == %s\n", buf);
	 mp_tohex(&c, buf);
	 printf("c == %s\n", buf);
	 return EXIT_FAILURE;
      }
   }
   printf("...Passed\n");
#endif /* LTM_DEMO_TEST_REDUCE_2K_L */

#else

   div2_n = mul2_n = inv_n = expt_n = lcm_n = gcd_n = add_n =
      sub_n = mul_n = div_n = sqr_n = mul2d_n = div2d_n = cnt = add_d_n =
      sub_d_n = 0;

   /* force KARA and TOOM to enable despite cutoffs */
   KARATSUBA_SQR_CUTOFF = KARATSUBA_MUL_CUTOFF = 8;
   TOOM_SQR_CUTOFF = TOOM_MUL_CUTOFF = 16;

   for (;;) {
      /* randomly clear and re-init one variable, this has the affect of triming the alloc space */
      switch (abs(rand()) % 7) {
      case 0:
	 mp_clear(&a);
	 mp_init(&a);
	 break;
      case 1:
	 mp_clear(&b);
	 mp_init(&b);
	 break;
      case 2:
	 mp_clear(&c);
	 mp_init(&c);
	 break;
      case 3:
	 mp_clear(&d);
	 mp_init(&d);
	 break;
      case 4:
	 mp_clear(&e);
	 mp_init(&e);
	 break;
      case 5:
	 mp_clear(&f);
	 mp_init(&f);
	 break;
      case 6:
	 break;			/* don't clear any */
      }


      printf
	 ("%4lu/%4lu/%4lu/%4lu/%4lu/%4lu/%4lu/%4lu/%4lu/%4lu/%4lu/%4lu/%4lu/%4lu/%4lu ",
	  add_n, sub_n, mul_n, div_n, sqr_n, mul2d_n, div2d_n, gcd_n, lcm_n,
	  expt_n, inv_n, div2_n, mul2_n, add_d_n, sub_d_n);
      ret=fgets(cmd, 4095, stdin); if(!ret){_panic(__LINE__);}
      cmd[strlen(cmd) - 1] = 0;
      printf("%-6s ]\r", cmd);
      fflush(stdout);
      if (!strcmp(cmd, "mul2d")) {
	 ++mul2d_n;
	 ret=fgets(buf, 4095, stdin); if(!ret){_panic(__LINE__);}
	 mp_read_radix(&a, buf, 64);
	 ret=fgets(buf, 4095, stdin); if(!ret){_panic(__LINE__);}
	 sscanf(buf, "%d", &rr);
	 ret=fgets(buf, 4095, stdin); if(!ret){_panic(__LINE__);}
	 mp_read_radix(&b, buf, 64);

	 mp_mul_2d(&a, rr, &a);
	 a.sign = b.sign;
	 if (mp_cmp(&a, &b) != MP_EQ) {
	    printf("mul2d failed, rr == %d\n", rr);
	    draw(&a);
	    draw(&b);
	    return EXIT_FAILURE;
	 }
      } else if (!strcmp(cmd, "div2d")) {
	 ++div2d_n;
	 ret=fgets(buf, 4095, stdin); if(!ret){_panic(__LINE__);}
	 mp_read_radix(&a, buf, 64);
	 ret=fgets(buf, 4095, stdin); if(!ret){_panic(__LINE__);}
	 sscanf(buf, "%d", &rr);
	 ret=fgets(buf, 4095, stdin); if(!ret){_panic(__LINE__);}
	 mp_read_radix(&b, buf, 64);

	 mp_div_2d(&a, rr, &a, &e);
	 a.sign = b.sign;
	 if (a.used == b.used && a.used == 0) {
	    a.sign = b.sign = MP_ZPOS;
	 }
	 if (mp_cmp(&a, &b) != MP_EQ) {
	    printf("div2d failed, rr == %d\n", rr);
	    draw(&a);
	    draw(&b);
	    return EXIT_FAILURE;
	 }
      } else if (!strcmp(cmd, "add")) {
	 ++add_n;
	 ret=fgets(buf, 4095, stdin); if(!ret){_panic(__LINE__);}
	 mp_read_radix(&a, buf, 64);
	 ret=fgets(buf, 4095, stdin); if(!ret){_panic(__LINE__);}
	 mp_read_radix(&b, buf, 64);
	 ret=fgets(buf, 4095, stdin); if(!ret){_panic(__LINE__);}
	 mp_read_radix(&c, buf, 64);
	 mp_copy(&a, &d);
	 mp_add(&d, &b, &d);
	 if (mp_cmp(&c, &d) != MP_EQ) {
	    printf("add %lu failure!\n", add_n);
	    draw(&a);
	    draw(&b);
	    draw(&c);
	    draw(&d);
	    return EXIT_FAILURE;
	 }

	 /* test the sign/unsigned storage functions */

	 rr = mp_signed_bin_size(&c);
	 mp_to_signed_bin(&c, (unsigned char *) cmd);
	 memset(cmd + rr, rand() & 255, sizeof(cmd) - rr);
	 mp_read_signed_bin(&d, (unsigned char *) cmd, rr);
	 if (mp_cmp(&c, &d) != MP_EQ) {
	    printf("mp_signed_bin failure!\n");
	    draw(&c);
	    draw(&d);
	    return EXIT_FAILURE;
	 }


	 rr = mp_unsigned_bin_size(&c);
	 mp_to_unsigned_bin(&c, (unsigned char *) cmd);
	 memset(cmd + rr, rand() & 255, sizeof(cmd) - rr);
	 mp_read_unsigned_bin(&d, (unsigned char *) cmd, rr);
	 if (mp_cmp_mag(&c, &d) != MP_EQ) {
	    printf("mp_unsigned_bin failure!\n");
	    draw(&c);
	    draw(&d);
	    return EXIT_FAILURE;
	 }

      } else if (!strcmp(cmd, "sub")) {
	 ++sub_n;
	 ret=fgets(buf, 4095, stdin); if(!ret){_panic(__LINE__);}
	 mp_read_radix(&a, buf, 64);
	 ret=fgets(buf, 4095, stdin); if(!ret){_panic(__LINE__);}
	 mp_read_radix(&b, buf, 64);
	 ret=fgets(buf, 4095, stdin); if(!ret){_panic(__LINE__);}
	 mp_read_radix(&c, buf, 64);
	 mp_copy(&a, &d);
	 mp_sub(&d, &b, &d);
	 if (mp_cmp(&c, &d) != MP_EQ) {
	    printf("sub %lu failure!\n", sub_n);
	    draw(&a);
	    draw(&b);
	    draw(&c);
	    draw(&d);
	    return EXIT_FAILURE;
	 }
      } else if (!strcmp(cmd, "mul")) {
	 ++mul_n;
	 ret=fgets(buf, 4095, stdin); if(!ret){_panic(__LINE__);}
	 mp_read_radix(&a, buf, 64);
	 ret=fgets(buf, 4095, stdin); if(!ret){_panic(__LINE__);}
	 mp_read_radix(&b, buf, 64);
	 ret=fgets(buf, 4095, stdin); if(!ret){_panic(__LINE__);}
	 mp_read_radix(&c, buf, 64);
	 mp_copy(&a, &d);
	 mp_mul(&d, &b, &d);
	 if (mp_cmp(&c, &d) != MP_EQ) {
	    printf("mul %lu failure!\n", mul_n);
	    draw(&a);
	    draw(&b);
	    draw(&c);
	    draw(&d);
	    return EXIT_FAILURE;
	 }
      } else if (!strcmp(cmd, "div")) {
	 ++div_n;
	 ret=fgets(buf, 4095, stdin); if(!ret){_panic(__LINE__);}
	 mp_read_radix(&a, buf, 64);
	 ret=fgets(buf, 4095, stdin); if(!ret){_panic(__LINE__);}
	 mp_read_radix(&b, buf, 64);
	 ret=fgets(buf, 4095, stdin); if(!ret){_panic(__LINE__);}
	 mp_read_radix(&c, buf, 64);
	 ret=fgets(buf, 4095, stdin); if(!ret){_panic(__LINE__);}
	 mp_read_radix(&d, buf, 64);

	 mp_div(&a, &b, &e, &f);
	 if (mp_cmp(&c, &e) != MP_EQ || mp_cmp(&d, &f) != MP_EQ) {
	    printf("div %lu %d, %d, failure!\n", div_n, mp_cmp(&c, &e),
		   mp_cmp(&d, &f));
	    draw(&a);
	    draw(&b);
	    draw(&c);
	    draw(&d);
	    draw(&e);
	    draw(&f);
	    return EXIT_FAILURE;
	 }

      } else if (!strcmp(cmd, "sqr")) {
	 ++sqr_n;
	 ret=fgets(buf, 4095, stdin); if(!ret){_panic(__LINE__);}
	 mp_read_radix(&a, buf, 64);
	 ret=fgets(buf, 4095, stdin); if(!ret){_panic(__LINE__);}
	 mp_read_radix(&b, buf, 64);
	 mp_copy(&a, &c);
	 mp_sqr(&c, &c);
	 if (mp_cmp(&b, &c) != MP_EQ) {
	    printf("sqr %lu failure!\n", sqr_n);
	    draw(&a);
	    draw(&b);
	    draw(&c);
	    return EXIT_FAILURE;
	 }
      } else if (!strcmp(cmd, "gcd")) {
	 ++gcd_n;
	 ret=fgets(buf, 4095, stdin); if(!ret){_panic(__LINE__);}
	 mp_read_radix(&a, buf, 64);
	 ret=fgets(buf, 4095, stdin); if(!ret){_panic(__LINE__);}
	 mp_read_radix(&b, buf, 64);
	 ret=fgets(buf, 4095, stdin); if(!ret){_panic(__LINE__);}
	 mp_read_radix(&c, buf, 64);
	 mp_copy(&a, &d);
	 mp_gcd(&d, &b, &d);
	 d.sign = c.sign;
	 if (mp_cmp(&c, &d) != MP_EQ) {
	    printf("gcd %lu failure!\n", gcd_n);
	    draw(&a);
	    draw(&b);
	    draw(&c);
	    draw(&d);
	    return EXIT_FAILURE;
	 }
      } else if (!strcmp(cmd, "lcm")) {
	 ++lcm_n;
	 ret=fgets(buf, 4095, stdin); if(!ret){_panic(__LINE__);}
	 mp_read_radix(&a, buf, 64);
	 ret=fgets(buf, 4095, stdin); if(!ret){_panic(__LINE__);}
	 mp_read_radix(&b, buf, 64);
	 ret=fgets(buf, 4095, stdin); if(!ret){_panic(__LINE__);}
	 mp_read_radix(&c, buf, 64);
	 mp_copy(&a, &d);
	 mp_lcm(&d, &b, &d);
	 d.sign = c.sign;
	 if (mp_cmp(&c, &d) != MP_EQ) {
	    printf("lcm %lu failure!\n", lcm_n);
	    draw(&a);
	    draw(&b);
	    draw(&c);
	    draw(&d);
	    return EXIT_FAILURE;
	 }
      } else if (!strcmp(cmd, "expt")) {
	 ++expt_n;
	 ret=fgets(buf, 4095, stdin); if(!ret){_panic(__LINE__);}
	 mp_read_radix(&a, buf, 64);
	 ret=fgets(buf, 4095, stdin); if(!ret){_panic(__LINE__);}
	 mp_read_radix(&b, buf, 64);
	 ret=fgets(buf, 4095, stdin); if(!ret){_panic(__LINE__);}
	 mp_read_radix(&c, buf, 64);
	 ret=fgets(buf, 4095, stdin); if(!ret){_panic(__LINE__);}
	 mp_read_radix(&d, buf, 64);
	 mp_copy(&a, &e);
	 mp_exptmod(&e, &b, &c, &e);
	 if (mp_cmp(&d, &e) != MP_EQ) {
	    printf("expt %lu failure!\n", expt_n);
	    draw(&a);
	    draw(&b);
	    draw(&c);
	    draw(&d);
	    draw(&e);
	    return EXIT_FAILURE;
	 }
      } else if (!strcmp(cmd, "invmod")) {
	 ++inv_n;
	 ret=fgets(buf, 4095, stdin); if(!ret){_panic(__LINE__);}
	 mp_read_radix(&a, buf, 64);
	 ret=fgets(buf, 4095, stdin); if(!ret){_panic(__LINE__);}
	 mp_read_radix(&b, buf, 64);
	 ret=fgets(buf, 4095, stdin); if(!ret){_panic(__LINE__);}
	 mp_read_radix(&c, buf, 64);
	 mp_invmod(&a, &b, &d);
	 mp_mulmod(&d, &a, &b, &e);
	 if (mp_cmp_d(&e, 1) != MP_EQ) {
	    printf("inv [wrong value from MPI?!] failure\n");
	    draw(&a);
	    draw(&b);
	    draw(&c);
	    draw(&d);
	    draw(&e);
	    mp_gcd(&a, &b, &e);
	    draw(&e);
	    return EXIT_FAILURE;
	 }

      } else if (!strcmp(cmd, "div2")) {
	 ++div2_n;
	 ret=fgets(buf, 4095, stdin); if(!ret){_panic(__LINE__);}
	 mp_read_radix(&a, buf, 64);
	 ret=fgets(buf, 4095, stdin); if(!ret){_panic(__LINE__);}
	 mp_read_radix(&b, buf, 64);
	 mp_div_2(&a, &c);
	 if (mp_cmp(&c, &b) != MP_EQ) {
	    printf("div_2 %lu failure\n", div2_n);
	    draw(&a);
	    draw(&b);
	    draw(&c);
	    return EXIT_FAILURE;
	 }
      } else if (!strcmp(cmd, "mul2")) {
	 ++mul2_n;
	 ret=fgets(buf, 4095, stdin); if(!ret){_panic(__LINE__);}
	 mp_read_radix(&a, buf, 64);
	 ret=fgets(buf, 4095, stdin); if(!ret){_panic(__LINE__);}
	 mp_read_radix(&b, buf, 64);
	 mp_mul_2(&a, &c);
	 if (mp_cmp(&c, &b) != MP_EQ) {
	    printf("mul_2 %lu failure\n", mul2_n);
	    draw(&a);
	    draw(&b);
	    draw(&c);
	    return EXIT_FAILURE;
	 }
      } else if (!strcmp(cmd, "add_d")) {
	 ++add_d_n;
	 ret=fgets(buf, 4095, stdin); if(!ret){_panic(__LINE__);}
	 mp_read_radix(&a, buf, 64);
	 ret=fgets(buf, 4095, stdin); if(!ret){_panic(__LINE__);}
	 sscanf(buf, "%d", &ix);
	 ret=fgets(buf, 4095, stdin); if(!ret){_panic(__LINE__);}
	 mp_read_radix(&b, buf, 64);
	 mp_add_d(&a, ix, &c);
	 if (mp_cmp(&b, &c) != MP_EQ) {
	    printf("add_d %lu failure\n", add_d_n);
	    draw(&a);
	    draw(&b);
	    draw(&c);
	    printf("d == %d\n", ix);
	    return EXIT_FAILURE;
	 }
      } else if (!strcmp(cmd, "sub_d")) {
	 ++sub_d_n;
	 ret=fgets(buf, 4095, stdin); if(!ret){_panic(__LINE__);}
	 mp_read_radix(&a, buf, 64);
	 ret=fgets(buf, 4095, stdin); if(!ret){_panic(__LINE__);}
	 sscanf(buf, "%d", &ix);
	 ret=fgets(buf, 4095, stdin); if(!ret){_panic(__LINE__);}
	 mp_read_radix(&b, buf, 64);
	 mp_sub_d(&a, ix, &c);
	 if (mp_cmp(&b, &c) != MP_EQ) {
	    printf("sub_d %lu failure\n", sub_d_n);
	    draw(&a);
	    draw(&b);
	    draw(&c);
	    printf("d == %d\n", ix);
	    return EXIT_FAILURE;
	 }
      } else if (!strcmp(cmd, "exit")) {
         printf("\nokay, exiting now\n");
         break;
      }
   }
#endif
   return 0;
}
Exemplo n.º 11
0
/**
  Store a mp_int integer
  @param num      The first mp_int to encode
  @param out      [out] The destination for the DER encoded integers
  @param outlen   [in/out] The max size and resulting size of the DER encoded integers
  @return CRYPT_OK if successful
*/
int der_encode_integer(void *num, unsigned char *out, unsigned long *outlen)
{
   unsigned long tmplen, y, len;
   int           err, leading_zero;

   LTC_ARGCHK(num    != NULL);
   LTC_ARGCHK(out    != NULL);
   LTC_ARGCHK(outlen != NULL);

   /* find out how big this will be */
   if ((err = der_length_integer(num, &tmplen)) != CRYPT_OK) {
      return err;
   }

   if (*outlen < tmplen) {
      *outlen = tmplen;
      return CRYPT_BUFFER_OVERFLOW;
   }

   if (mp_cmp_d(num, 0) != LTC_MP_LT) {
      /* we only need a leading zero if the msb of the first byte is one */
      if ((mp_count_bits(num) & 7) == 0 || mp_iszero(num) == LTC_MP_YES) {
         leading_zero = 1;
      } else {
         leading_zero = 0;
      }

      /* get length of num in bytes (plus 1 since we force the msbyte to zero) */
      y = mp_unsigned_bin_size(num) + leading_zero;
   } else {
      leading_zero = 0;
      y            = mp_count_bits(num);
      y            = y + (8 - (y & 7));
      y            = y >> 3;
      if (((mp_cnt_lsb(num)+1)==mp_count_bits(num)) && ((mp_count_bits(num)&7)==0)) --y;
   }

   /* now store initial data */
   *out++ = 0x02;
   len = *outlen - 1;
   if ((err = der_encode_asn1_length(y, out, &len)) != CRYPT_OK) {
      return err;
   }
   out += len;

   /* now store msbyte of zero if num is non-zero */
   if (leading_zero) {
      *out++ = 0x00;
   }

   /* if it's not zero store it as big endian */
   if (mp_cmp_d(num, 0) == LTC_MP_GT) {
      /* now store the mpint */
      if ((err = mp_to_unsigned_bin(num, out)) != CRYPT_OK) {
          return err;
      }
   } else if (mp_iszero(num) != LTC_MP_YES) {
      void *tmp;

      /* negative */
      if (mp_init(&tmp) != CRYPT_OK) {
         return CRYPT_MEM;
      }

      /* 2^roundup and subtract */
      y = mp_count_bits(num);
      y = y + (8 - (y & 7));
      if (((mp_cnt_lsb(num)+1)==mp_count_bits(num)) && ((mp_count_bits(num)&7)==0)) y -= 8;
      if (mp_2expt(tmp, y) != CRYPT_OK || mp_add(tmp, num, tmp) != CRYPT_OK) {
         mp_clear(tmp);
         return CRYPT_MEM;
      }
      if ((err = mp_to_unsigned_bin(tmp, out)) != CRYPT_OK) {
         mp_clear(tmp);
         return err;
      }
      mp_clear(tmp);
   }

   /* we good */
   *outlen = tmplen;
   return CRYPT_OK;
}