/* * shifts with subtractions when the result is greater than b. * * The method is slightly modified to shift B unconditionally upto just under * the leading bit of b. This saves alot of multiple precision shifting. */ int mp_montgomery_calc_normalization (mp_int * a, mp_int * b) { int x, bits, res; /* how many bits of last digit does b use */ bits = mp_count_bits (b) % DIGIT_BIT; if (b->used > 1) { if ((res = mp_2expt (a, (b->used - 1) * DIGIT_BIT + bits - 1)) != MP_OKAY) { return res; } } else { mp_set(a, 1); bits = 1; } /* now compute C = A * B mod b */ for (x = bits - 1; x < (int)DIGIT_BIT; x++) { if ((res = mp_mul_2 (a, a)) != MP_OKAY) { return res; } if (mp_cmp_mag (a, b) != MP_LT) { if ((res = s_mp_sub (a, b, a)) != MP_OKAY) { return res; } } } return MP_OKAY; }
/* determines the setup value */ int mp_reduce_2k_setup(mp_int *a, mp_digit *d) { int res, p; mp_int tmp; if ((res = mp_init(&tmp)) != MP_OKAY) { return res; } p = mp_count_bits(a); if ((res = mp_2expt(&tmp, p)) != MP_OKAY) { mp_clear(&tmp); return res; } if ((res = s_mp_sub(&tmp, a, &tmp)) != MP_OKAY) { mp_clear(&tmp); return res; } *d = tmp.dp[0]; mp_clear(&tmp); return MP_OKAY; }
/* pre-calculate the value required for Barrett reduction * For a given modulus "b" it calulates the value required in "a" */ int mp_reduce_setup (mp_int * a, mp_int * b) { int res; if ((res = mp_2expt (a, b->used * 2 * DIGIT_BIT)) != MP_OKAY) { return res; } return mp_div (a, b, a, NULL); }
/* determines the setup value */ int mp_reduce_2k_setup_l(mp_int *a, mp_int *d) { int res; mp_int tmp; if ((res = mp_init(&tmp)) != MP_OKAY) { return res; } if ((res = mp_2expt(&tmp, mp_count_bits(a))) != MP_OKAY) { goto ERR; } if ((res = s_mp_sub(&tmp, a, d)) != MP_OKAY) { goto ERR; } ERR: mp_clear(&tmp); return res; }
int main(void) { char buf[2000]; int x, y; mp_int q, p; FILE *out; clock_t t1; mp_digit z; mp_init_multi(&q, &p, NULL); out = fopen("2kprime.1", "w"); for (x = 0; x < (int)(sizeof(sizes) / sizeof(sizes[0])); x++) { top: mp_2expt(&q, sizes[x]); mp_add_d(&q, 3, &q); z = -3; t1 = clock(); for(;;) { mp_sub_d(&q, 4, &q); z += 4; if (z > MP_MASK) { printf("No primes of size %d found\n", sizes[x]); break; } if (clock() - t1 > CLOCKS_PER_SEC) { printf("."); fflush(stdout); // sleep((clock() - t1 + CLOCKS_PER_SEC/2)/CLOCKS_PER_SEC); t1 = clock(); } /* quick test on q */ mp_prime_is_prime(&q, 1, &y); if (y == 0) { continue; } /* find (q-1)/2 */ mp_sub_d(&q, 1, &p); mp_div_2(&p, &p); mp_prime_is_prime(&p, 3, &y); if (y == 0) { continue; } /* test on q */ mp_prime_is_prime(&q, 3, &y); if (y == 0) { continue; } break; } if (y == 0) { ++sizes[x]; goto top; } mp_toradix(&q, buf, 10); printf("\n\n%d-bits (k = %lu) = %s\n", sizes[x], z, buf); fprintf(out, "%d-bits (k = %lu) = %s\n", sizes[x], z, buf); fflush(out); } return 0; }
static int twoexpt(void *a, int n) { LTC_ARGCHK(a != NULL); return mpi_to_ltc_error(mp_2expt(a, n)); }
/** Read a mp_int integer @param in The DER encoded data @param inlen Size of DER encoded data @param num The first mp_int to decode @return CRYPT_OK if successful */ int der_decode_integer(const unsigned char *in, unsigned long inlen, void *num) { unsigned long x, y, z; int err; LTC_ARGCHK(num != NULL); LTC_ARGCHK(in != NULL); /* min DER INTEGER is 0x02 01 00 == 0 */ if (inlen < (1 + 1 + 1)) { return CRYPT_INVALID_PACKET; } /* ok expect 0x02 when we AND with 0001 1111 [1F] */ x = 0; if ((in[x++] & 0x1F) != 0x02) { return CRYPT_INVALID_PACKET; } /* now decode the len stuff */ z = in[x++]; if ((z & 0x80) == 0x00) { /* short form */ /* will it overflow? */ if (x + z > inlen) { return CRYPT_INVALID_PACKET; } /* no so read it */ if ((err = mp_read_unsigned_bin(num, (unsigned char *)in + x, z)) != CRYPT_OK) { return err; } } else { /* long form */ z &= 0x7F; /* will number of length bytes overflow? (or > 4) */ if (((x + z) > inlen) || (z > 4) || (z == 0)) { return CRYPT_INVALID_PACKET; } /* now read it in */ y = 0; while (z--) { y = ((unsigned long)(in[x++])) | (y << 8); } /* now will reading y bytes overrun? */ if ((x + y) > inlen) { return CRYPT_INVALID_PACKET; } /* no so read it */ if ((err = mp_read_unsigned_bin(num, (unsigned char *)in + x, y)) != CRYPT_OK) { return err; } } /* see if it's negative */ if (in[x] & 0x80) { void *tmp; if (mp_init(&tmp) != CRYPT_OK) { return CRYPT_MEM; } if (mp_2expt(tmp, mp_count_bits(num)) != CRYPT_OK || mp_sub(num, tmp, num) != CRYPT_OK) { mp_clear(tmp); return CRYPT_MEM; } mp_clear(tmp); } return CRYPT_OK; }
/* * Try to find the two primes based on 2 exponents plus either a prime * or a modulus. * * In: e, d and either p or n (depending on the setting of hasModulus). * Out: p,q. * * Step 1, Since d = e**-1 mod phi, we know that d*e == 1 mod phi, or * d*e = 1+k*phi, or d*e-1 = k*phi. since d is less than phi and e is * usually less than d, then k must be an integer between e-1 and 1 * (probably on the order of e). * Step 1a, If we were passed just a prime, we can divide k*phi by that * prime-1 and get k*(q-1). This will reduce the size of our division * through the rest of the loop. * Step 2, Loop through the values k=e-1 to 1 looking for k. k should be on * the order or e, and e is typically small. This may take a while for * a large random e. We are looking for a k that divides kphi * evenly. Once we find a k that divides kphi evenly, we assume it * is the true k. It's possible this k is not the 'true' k but has * swapped factors of p-1 and/or q-1. Because of this, we * tentatively continue Steps 3-6 inside this loop, and may return looking * for another k on failure. * Step 3, Calculate are tentative phi=kphi/k. Note: real phi is (p-1)*(q-1). * Step 4a, if we have a prime, kphi is already k*(q-1), so phi is or tenative * q-1. q = phi+1. If k is correct, q should be the right length and * prime. * Step 4b, It's possible q-1 and k could have swapped factors. We now have a * possible solution that meets our criteria. It may not be the only * solution, however, so we keep looking. If we find more than one, * we will fail since we cannot determine which is the correct * solution, and returning the wrong modulus will compromise both * moduli. If no other solution is found, we return the unique solution. * Step 5a, If we have the modulus (n=pq), then use the following formula to * calculate s=(p+q): , phi = (p-1)(q-1) = pq -p-q +1 = n-s+1. so * s=n-phi+1. * Step 5b, Use n=pq and s=p+q to solve for p and q as follows: * since q=s-p, then n=p*(s-p)= sp - p^2, rearranging p^2-s*p+n = 0. * from the quadratic equation we have p=1/2*(s+sqrt(s*s-4*n)) and * q=1/2*(s-sqrt(s*s-4*n)) if s*s-4*n is a perfect square, we are DONE. * If it is not, continue in our look looking for another k. NOTE: the * code actually distributes the 1/2 and results in the equations: * sqrt = sqrt(s/2*s/2-n), p=s/2+sqrt, q=s/2-sqrt. The algebra saves us * and extra divide by 2 and a multiply by 4. * * This will return p & q. q may be larger than p in the case that p was given * and it was the smaller prime. */ static mp_err rsa_get_primes_from_exponents(mp_int *e, mp_int *d, mp_int *p, mp_int *q, mp_int *n, PRBool hasModulus, unsigned int keySizeInBits) { mp_int kphi; /* k*phi */ mp_int k; /* current guess at 'k' */ mp_int phi; /* (p-1)(q-1) */ mp_int s; /* p+q/2 (s/2 in the algebra) */ mp_int r; /* remainder */ mp_int tmp; /* p-1 if p is given, n+1 is modulus is given */ mp_int sqrt; /* sqrt(s/2*s/2-n) */ mp_err err = MP_OKAY; unsigned int order_k; MP_DIGITS(&kphi) = 0; MP_DIGITS(&phi) = 0; MP_DIGITS(&s) = 0; MP_DIGITS(&k) = 0; MP_DIGITS(&r) = 0; MP_DIGITS(&tmp) = 0; MP_DIGITS(&sqrt) = 0; CHECK_MPI_OK( mp_init(&kphi) ); CHECK_MPI_OK( mp_init(&phi) ); CHECK_MPI_OK( mp_init(&s) ); CHECK_MPI_OK( mp_init(&k) ); CHECK_MPI_OK( mp_init(&r) ); CHECK_MPI_OK( mp_init(&tmp) ); CHECK_MPI_OK( mp_init(&sqrt) ); /* our algorithm looks for a factor k whose maximum size is dependent * on the size of our smallest exponent, which had better be the public * exponent (if it's the private, the key is vulnerable to a brute force * attack). * * since our factor search is linear, we need to limit the maximum * size of the public key. this should not be a problem normally, since * public keys are usually small. * * if we want to handle larger public key sizes, we should have * a version which tries to 'completely' factor k*phi (where completely * means 'factor into primes, or composites with which are products of * large primes). Once we have all the factors, we can sort them out and * try different combinations to form our phi. The risk is if (p-1)/2, * (q-1)/2, and k are all large primes. In any case if the public key * is small (order of 20 some bits), then a linear search for k is * manageable. */ if (mpl_significant_bits(e) > 23) { err=MP_RANGE; goto cleanup; } /* calculate k*phi = e*d - 1 */ CHECK_MPI_OK( mp_mul(e, d, &kphi) ); CHECK_MPI_OK( mp_sub_d(&kphi, 1, &kphi) ); /* kphi is (e*d)-1, which is the same as k*(p-1)(q-1) * d < (p-1)(q-1), therefor k must be less than e-1 * We can narrow down k even more, though. Since p and q are odd and both * have their high bit set, then we know that phi must be on order of * keySizeBits. */ order_k = (unsigned)mpl_significant_bits(&kphi) - keySizeInBits; /* for (k=kinit; order(k) >= order_k; k--) { */ /* k=kinit: k can't be bigger than kphi/2^(keySizeInBits -1) */ CHECK_MPI_OK( mp_2expt(&k,keySizeInBits-1) ); CHECK_MPI_OK( mp_div(&kphi, &k, &k, NULL)); if (mp_cmp(&k,e) >= 0) { /* also can't be bigger then e-1 */ CHECK_MPI_OK( mp_sub_d(e, 1, &k) ); } /* calculate our temp value */ /* This saves recalculating this value when the k guess is wrong, which * is reasonably frequent. */ /* for the modulus case, tmp = n+1 (used to calculate p+q = tmp - phi) */ /* for the prime case, tmp = p-1 (used to calculate q-1= phi/tmp) */ if (hasModulus) { CHECK_MPI_OK( mp_add_d(n, 1, &tmp) ); } else { CHECK_MPI_OK( mp_sub_d(p, 1, &tmp) ); CHECK_MPI_OK(mp_div(&kphi,&tmp,&kphi,&r)); if (mp_cmp_z(&r) != 0) { /* p-1 doesn't divide kphi, some parameter wasn't correct */ err=MP_RANGE; goto cleanup; } mp_zero(q); /* kphi is now k*(q-1) */ } /* rest of the for loop */ for (; (err == MP_OKAY) && (mpl_significant_bits(&k) >= order_k); err = mp_sub_d(&k, 1, &k)) { /* looking for k as a factor of kphi */ CHECK_MPI_OK(mp_div(&kphi,&k,&phi,&r)); if (mp_cmp_z(&r) != 0) { /* not a factor, try the next one */ continue; } /* we have a possible phi, see if it works */ if (!hasModulus) { if ((unsigned)mpl_significant_bits(&phi) != keySizeInBits/2) { /* phi is not the right size */ continue; } /* phi should be divisible by 2, since * q is odd and phi=(q-1). */ if (mpp_divis_d(&phi,2) == MP_NO) { /* phi is not divisible by 4 */ continue; } /* we now have a candidate for the second prime */ CHECK_MPI_OK(mp_add_d(&phi, 1, &tmp)); /* check to make sure it is prime */ err = rsa_is_prime(&tmp); if (err != MP_OKAY) { if (err == MP_NO) { /* No, then we still have the wrong phi */ err = MP_OKAY; continue; } goto cleanup; } /* * It is possible that we have the wrong phi if * k_guess*(q_guess-1) = k*(q-1) (k and q-1 have swapped factors). * since our q_quess is prime, however. We have found a valid * rsa key because: * q is the correct order of magnitude. * phi = (p-1)(q-1) where p and q are both primes. * e*d mod phi = 1. * There is no way to know from the info given if this is the * original key. We never want to return the wrong key because if * two moduli with the same factor is known, then euclid's gcd * algorithm can be used to find that factor. Even though the * caller didn't pass the original modulus, it doesn't mean the * modulus wasn't known or isn't available somewhere. So to be safe * if we can't be sure we have the right q, we don't return any. * * So to make sure we continue looking for other valid q's. If none * are found, then we can safely return this one, otherwise we just * fail */ if (mp_cmp_z(q) != 0) { /* this is the second valid q, don't return either, * just fail */ err = MP_RANGE; break; } /* we only have one q so far, save it and if no others are found, * it's safe to return it */ CHECK_MPI_OK(mp_copy(&tmp, q)); continue; } /* test our tentative phi */ /* phi should be the correct order */ if ((unsigned)mpl_significant_bits(&phi) != keySizeInBits) { /* phi is not the right size */ continue; } /* phi should be divisible by 4, since * p and q are odd and phi=(p-1)(q-1). */ if (mpp_divis_d(&phi,4) == MP_NO) { /* phi is not divisible by 4 */ continue; } /* n was given, calculate s/2=(p+q)/2 */ CHECK_MPI_OK( mp_sub(&tmp, &phi, &s) ); CHECK_MPI_OK( mp_div_2(&s, &s) ); /* calculate sqrt(s/2*s/2-n) */ CHECK_MPI_OK(mp_sqr(&s,&sqrt)); CHECK_MPI_OK(mp_sub(&sqrt,n,&r)); /* r as a tmp */ CHECK_MPI_OK(mp_sqrt(&r,&sqrt)); /* make sure it's a perfect square */ /* r is our original value we took the square root of */ /* q is the square of our tentative square root. They should be equal*/ CHECK_MPI_OK(mp_sqr(&sqrt,q)); /* q as a tmp */ if (mp_cmp(&r,q) != 0) { /* sigh according to the doc, mp_sqrt could return sqrt-1 */ CHECK_MPI_OK(mp_add_d(&sqrt,1,&sqrt)); CHECK_MPI_OK(mp_sqr(&sqrt,q)); if (mp_cmp(&r,q) != 0) { /* s*s-n not a perfect square, this phi isn't valid, find * another.*/ continue; } } /* NOTE: In this case we know we have the one and only answer. * "Why?", you ask. Because: * 1) n is a composite of two large primes (or it wasn't a * valid RSA modulus). * 2) If we know any number such that x^2-n is a perfect square * and x is not (n+1)/2, then we can calculate 2 non-trivial * factors of n. * 3) Since we know that n has only 2 non-trivial prime factors, * we know the two factors we have are the only possible factors. */ /* Now we are home free to calculate p and q */ /* p = s/2 + sqrt, q= s/2 - sqrt */ CHECK_MPI_OK(mp_add(&s,&sqrt,p)); CHECK_MPI_OK(mp_sub(&s,&sqrt,q)); break; } if ((unsigned)mpl_significant_bits(&k) < order_k) { if (hasModulus || (mp_cmp_z(q) == 0)) { /* If we get here, something was wrong with the parameters we * were given */ err = MP_RANGE; } } cleanup: mp_clear(&kphi); mp_clear(&phi); mp_clear(&s); mp_clear(&k); mp_clear(&r); mp_clear(&tmp); mp_clear(&sqrt); return err; }
int is_mersenne (long s, int *pp) { mp_int n, u; int res, k; *pp = 0; if ((res = mp_init (&n)) != MP_OKAY) { return res; } if ((res = mp_init (&u)) != MP_OKAY) { goto LBL_N; } /* n = 2^s - 1 */ if ((res = mp_2expt(&n, s)) != MP_OKAY) { goto LBL_MU; } if ((res = mp_sub_d (&n, 1, &n)) != MP_OKAY) { goto LBL_MU; } /* set u=4 */ mp_set (&u, 4); /* for k=1 to s-2 do */ for (k = 1; k <= s - 2; k++) { /* u = u^2 - 2 mod n */ if ((res = mp_sqr (&u, &u)) != MP_OKAY) { goto LBL_MU; } if ((res = mp_sub_d (&u, 2, &u)) != MP_OKAY) { goto LBL_MU; } /* make sure u is positive */ while (u.sign == MP_NEG) { if ((res = mp_add (&u, &n, &u)) != MP_OKAY) { goto LBL_MU; } } /* reduce */ if ((res = mp_reduce_2k (&u, &n, 1)) != MP_OKAY) { goto LBL_MU; } } /* if u == 0 then its prime */ if (mp_iszero (&u) == 1) { mp_prime_is_prime(&n, 8, pp); if (*pp != 1) printf("FAILURE\n"); } res = MP_OKAY; LBL_MU:mp_clear (&u); LBL_N:mp_clear (&n); return res; }
/** Create DSA parameters (INTERNAL ONLY, not part of public API) @param prng An active PRNG state @param wprng The index of the PRNG desired @param group_size Size of the multiplicative group (octets) @param modulus_size Size of the modulus (octets) @param p [out] bignum where generated 'p' is stored (must be initialized by caller) @param q [out] bignum where generated 'q' is stored (must be initialized by caller) @param g [out] bignum where generated 'g' is stored (must be initialized by caller) @return CRYPT_OK if successful, upon error this function will free all allocated memory */ static int _dsa_make_params(prng_state *prng, int wprng, int group_size, int modulus_size, void *p, void *q, void *g) { unsigned long L, N, n, outbytes, seedbytes, counter, j, i; int err, res, mr_tests_q, mr_tests_p, found_p, found_q, hash; unsigned char *wbuf, *sbuf, digest[MAXBLOCKSIZE]; void *t2L1, *t2N1, *t2q, *t2seedlen, *U, *W, *X, *c, *h, *e, *seedinc; /* check size */ if (group_size >= LTC_MDSA_MAX_GROUP || group_size < 1 || group_size >= modulus_size) { return CRYPT_INVALID_ARG; } /* FIPS-186-4 A.1.1.2 Generation of the Probable Primes p and q Using an Approved Hash Function * * L = The desired length of the prime p (in bits e.g. L = 1024) * N = The desired length of the prime q (in bits e.g. N = 160) * seedlen = The desired bit length of the domain parameter seed; seedlen shallbe equal to or greater than N * outlen = The bit length of Hash function * * 1. Check that the (L, N) * 2. If (seedlen <N), then return INVALID. * 3. n = ceil(L / outlen) - 1 * 4. b = L- 1 - (n * outlen) * 5. domain_parameter_seed = an arbitrary sequence of seedlen bits * 6. U = Hash (domain_parameter_seed) mod 2^(N-1) * 7. q = 2^(N-1) + U + 1 - (U mod 2) * 8. Test whether or not q is prime as specified in Appendix C.3 * 9. If qis not a prime, then go to step 5. * 10. offset = 1 * 11. For counter = 0 to (4L- 1) do { * For j=0 to n do { * Vj = Hash ((domain_parameter_seed+ offset + j) mod 2^seedlen * } * W = V0 + (V1 *2^outlen) + ... + (Vn-1 * 2^((n-1) * outlen)) + ((Vn mod 2^b) * 2^(n * outlen)) * X = W + 2^(L-1) Comment: 0 <= W < 2^(L-1); hence 2^(L-1) <= X < 2^L * c = X mod 2*q * p = X - (c - 1) Comment: p ~ 1 (mod 2*q) * If (p >= 2^(L-1)) { * Test whether or not p is prime as specified in Appendix C.3. * If p is determined to be prime, then return VALID and the values of p, qand (optionally) the values of domain_parameter_seed and counter * } * offset = offset + n + 1 Comment: Increment offset * } */ seedbytes = group_size; L = (unsigned long)modulus_size * 8; N = (unsigned long)group_size * 8; /* XXX-TODO no Lucas test */ #ifdef LTC_MPI_HAS_LUCAS_TEST /* M-R tests (when followed by one Lucas test) according FIPS-186-4 - Appendix C.3 - table C.1 */ mr_tests_p = (L <= 2048) ? 3 : 2; if (N <= 160) { mr_tests_q = 19; } else if (N <= 224) { mr_tests_q = 24; } else { mr_tests_q = 27; } #else /* M-R tests (without Lucas test) according FIPS-186-4 - Appendix C.3 - table C.1 */ if (L <= 1024) { mr_tests_p = 40; } else if (L <= 2048) { mr_tests_p = 56; } else { mr_tests_p = 64; } if (N <= 160) { mr_tests_q = 40; } else if (N <= 224) { mr_tests_q = 56; } else { mr_tests_q = 64; } #endif if (N <= 256) { hash = register_hash(&sha256_desc); } else if (N <= 384) { hash = register_hash(&sha384_desc); } else if (N <= 512) { hash = register_hash(&sha512_desc); } else { return CRYPT_INVALID_ARG; /* group_size too big */ } if ((err = hash_is_valid(hash)) != CRYPT_OK) { return err; } outbytes = hash_descriptor[hash].hashsize; n = ((L + outbytes*8 - 1) / (outbytes*8)) - 1; if ((wbuf = XMALLOC((n+1)*outbytes)) == NULL) { err = CRYPT_MEM; goto cleanup3; } if ((sbuf = XMALLOC(seedbytes)) == NULL) { err = CRYPT_MEM; goto cleanup2; } err = mp_init_multi(&t2L1, &t2N1, &t2q, &t2seedlen, &U, &W, &X, &c, &h, &e, &seedinc, NULL); if (err != CRYPT_OK) { goto cleanup1; } if ((err = mp_2expt(t2L1, L-1)) != CRYPT_OK) { goto cleanup; } /* t2L1 = 2^(L-1) */ if ((err = mp_2expt(t2N1, N-1)) != CRYPT_OK) { goto cleanup; } /* t2N1 = 2^(N-1) */ if ((err = mp_2expt(t2seedlen, seedbytes*8)) != CRYPT_OK) { goto cleanup; } /* t2seedlen = 2^seedlen */ for(found_p=0; !found_p;) { /* q */ for(found_q=0; !found_q;) { if (prng_descriptor[wprng].read(sbuf, seedbytes, prng) != seedbytes) { err = CRYPT_ERROR_READPRNG; goto cleanup; } i = outbytes; if ((err = hash_memory(hash, sbuf, seedbytes, digest, &i)) != CRYPT_OK) { goto cleanup; } if ((err = mp_read_unsigned_bin(U, digest, outbytes)) != CRYPT_OK) { goto cleanup; } if ((err = mp_mod(U, t2N1, U)) != CRYPT_OK) { goto cleanup; } if ((err = mp_add(t2N1, U, q)) != CRYPT_OK) { goto cleanup; } if (!mp_isodd(q)) mp_add_d(q, 1, q); if ((err = mp_prime_is_prime(q, mr_tests_q, &res)) != CRYPT_OK) { goto cleanup; } if (res == LTC_MP_YES) found_q = 1; } /* p */ if ((err = mp_read_unsigned_bin(seedinc, sbuf, seedbytes)) != CRYPT_OK) { goto cleanup; } if ((err = mp_add(q, q, t2q)) != CRYPT_OK) { goto cleanup; } for(counter=0; counter < 4*L && !found_p; counter++) { for(j=0; j<=n; j++) { if ((err = mp_add_d(seedinc, 1, seedinc)) != CRYPT_OK) { goto cleanup; } if ((err = mp_mod(seedinc, t2seedlen, seedinc)) != CRYPT_OK) { goto cleanup; } /* seedinc = (seedinc+1) % 2^seed_bitlen */ if ((i = mp_unsigned_bin_size(seedinc)) > seedbytes) { err = CRYPT_INVALID_ARG; goto cleanup; } zeromem(sbuf, seedbytes); if ((err = mp_to_unsigned_bin(seedinc, sbuf + seedbytes-i)) != CRYPT_OK) { goto cleanup; } i = outbytes; err = hash_memory(hash, sbuf, seedbytes, wbuf+(n-j)*outbytes, &i); if (err != CRYPT_OK) { goto cleanup; } } if ((err = mp_read_unsigned_bin(W, wbuf, (n+1)*outbytes)) != CRYPT_OK) { goto cleanup; } if ((err = mp_mod(W, t2L1, W)) != CRYPT_OK) { goto cleanup; } if ((err = mp_add(W, t2L1, X)) != CRYPT_OK) { goto cleanup; } if ((err = mp_mod(X, t2q, c)) != CRYPT_OK) { goto cleanup; } if ((err = mp_sub_d(c, 1, p)) != CRYPT_OK) { goto cleanup; } if ((err = mp_sub(X, p, p)) != CRYPT_OK) { goto cleanup; } if (mp_cmp(p, t2L1) != LTC_MP_LT) { /* p >= 2^(L-1) */ if ((err = mp_prime_is_prime(p, mr_tests_p, &res)) != CRYPT_OK) { goto cleanup; } if (res == LTC_MP_YES) { found_p = 1; } } } } /* FIPS-186-4 A.2.1 Unverifiable Generation of the Generator g * 1. e = (p - 1)/q * 2. h = any integer satisfying: 1 < h < (p - 1) * h could be obtained from a random number generator or from a counter that changes after each use * 3. g = h^e mod p * 4. if (g == 1), then go to step 2. * */ if ((err = mp_sub_d(p, 1, e)) != CRYPT_OK) { goto cleanup; } if ((err = mp_div(e, q, e, c)) != CRYPT_OK) { goto cleanup; } /* e = (p - 1)/q */ i = mp_count_bits(p); do { do { if ((err = rand_bn_bits(h, i, prng, wprng)) != CRYPT_OK) { goto cleanup; } } while (mp_cmp(h, p) != LTC_MP_LT || mp_cmp_d(h, 2) != LTC_MP_GT); if ((err = mp_sub_d(h, 1, h)) != CRYPT_OK) { goto cleanup; } /* h is randon and 1 < h < (p-1) */ if ((err = mp_exptmod(h, e, p, g)) != CRYPT_OK) { goto cleanup; } } while (mp_cmp_d(g, 1) == LTC_MP_EQ); err = CRYPT_OK; cleanup: mp_clear_multi(t2L1, t2N1, t2q, t2seedlen, U, W, X, c, h, e, seedinc, NULL); cleanup1: XFREE(sbuf); cleanup2: XFREE(wbuf); cleanup3: return err; }
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; }
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; }
/** 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; }
int main(int argc, char *argv[]) { int ix; mp_int a, b, c, d; mp_digit r; mp_err res; if(argc < 3) { fprintf(stderr, "Usage: %s <a> <b>\n", argv[0]); return 1; } printf("Test 3: Multiplication and division\n\n"); srand(time(NULL)); mp_init(&a); mp_init(&b); mp_read_radix(&a, argv[1], 10); mp_read_radix(&b, argv[2], 10); printf("a = "); mp_print(&a, stdout); fputc('\n', stdout); printf("b = "); mp_print(&b, stdout); fputc('\n', stdout); mp_init(&c); printf("\nc = a * b\n"); mp_mul(&a, &b, &c); printf("c = "); mp_print(&c, stdout); fputc('\n', stdout); printf("\nc = b * 32523\n"); mp_mul_d(&b, 32523, &c); printf("c = "); mp_print(&c, stdout); fputc('\n', stdout); mp_init(&d); printf("\nc = a / b, d = a mod b\n"); mp_div(&a, &b, &c, &d); printf("c = "); mp_print(&c, stdout); fputc('\n', stdout); printf("d = "); mp_print(&d, stdout); fputc('\n', stdout); ix = rand() % 256; printf("\nc = a / %d, r = a mod %d\n", ix, ix); mp_div_d(&a, (mp_digit)ix, &c, &r); printf("c = "); mp_print(&c, stdout); fputc('\n', stdout); printf("r = %04X\n", r); #if EXPT printf("\nc = a ** b\n"); mp_expt(&a, &b, &c); printf("c = "); mp_print(&c, stdout); fputc('\n', stdout); #endif ix = rand() % 256; printf("\nc = 2^%d\n", ix); mp_2expt(&c, ix); printf("c = "); mp_print(&c, stdout); fputc('\n', stdout); #if SQRT printf("\nc = sqrt(a)\n"); if((res = mp_sqrt(&a, &c)) != MP_OKAY) { printf("mp_sqrt: %s\n", mp_strerror(res)); } else { printf("c = "); mp_print(&c, stdout); fputc('\n', stdout); mp_sqr(&c, &c); printf("c^2 = "); mp_print(&c, stdout); fputc('\n', stdout); } #endif mp_clear(&d); mp_clear(&c); mp_clear(&b); mp_clear(&a); return 0; }