/* Produce table of composites from list of primes and trial value. ** trial must be odd. List of primes must not include 2. ** sieve should have dimension >= MAXPRIME/2, where MAXPRIME is largest ** prime in list of primes. After this function is finished, ** if sieve[i] is non-zero, then (trial + 2*i) is composite. ** Each prime used in the sieve costs one division of trial, and eliminates ** one or more values from the search space. (3 eliminates 1/3 of the values ** alone!) Each value left in the search space costs 1 or more modular ** exponentations. So, these divisions are a bargain! */ mp_err mpp_sieve(mp_int *trial, const mp_digit *primes, mp_size nPrimes, unsigned char *sieve, mp_size nSieve) { mp_err res; mp_digit rem; mp_size ix; unsigned long offset; memset(sieve, 0, nSieve); for(ix = 0; ix < nPrimes; ix++) { mp_digit prime = primes[ix]; mp_size i; if((res = mp_mod_d(trial, prime, &rem)) != MP_OKAY) return res; if (rem == 0) { offset = 0; } else { offset = prime - (rem / 2); } for (i = offset; i < nSieve ; i += prime) { sieve[i] = 1; } } return MP_OKAY; }
int mp_isprime(mp_int *a) { mp_int b; mp_digit d; int r, res; /* do trial division */ for (r = 0; r < 256; r++) { mp_mod_d(a, primes[r], &d); if (d == 0) { return MP_NO; } } /* now do 8 miller rabins */ mp_init(&b); for (r = 0; r < 128; r++) { mp_set(&b, primes[r]); mp_prime_miller_rabin(a, &b, &res); if (res == MP_NO) { return MP_NO; } } return MP_YES; }
int mp_isdivisible_d(mp_int *a, mp_digit d) { int err; mp_digit res; if ((err = mp_mod_d(a, d, &res)) != MP_OKAY) { return err; } if (res == 0) { return MP_YES; } return MP_NO; }
/* modi */ static int modi(void *a, unsigned long b, unsigned long *c) { mp_digit tmp; int err; LTC_ARGCHK(a != NULL); LTC_ARGCHK(c != NULL); if ((err = mpi_to_ltc_error(mp_mod_d(a, b, &tmp))) != CRYPT_OK) { return err; } *c = tmp; return CRYPT_OK; }
mp_err mpp_divis_d(mp_int *a, mp_digit d) { mp_err res; mp_digit rem; ARGCHK(a != NULL, MP_BADARG); if(d == 0) return MP_NO; if((res = mp_mod_d(a, d, &rem)) != MP_OKAY) return res; if(rem == 0) return MP_YES; else return MP_NO; } /* end mpp_divis_d() */
mp_err s_mpp_divp(mp_int *a, const mp_digit *vec, int size, int *which) { mp_err res; mp_digit rem; int ix; for(ix = 0; ix < size; ix++) { if((res = mp_mod_d(a, vec[ix], &rem)) != MP_OKAY) return res; if(rem == 0) { if(which) *which = ix; return MP_YES; } } return MP_NO; } /* end s_mpp_divp() */
/* determines if an integers is divisible by one * of the first PRIME_SIZE primes or not * * sets result to 0 if not, 1 if yes */ int mp_prime_is_divisible (mp_int * a, int *result) { int err, ix; mp_digit res; /* default to not */ *result = MP_NO; for (ix = 0; ix < PRIME_SIZE; ix++) { /* what is a mod LBL_prime_tab[ix] */ if ((err = mp_mod_d (a, ltm_prime_tab[ix], &res)) != MP_OKAY) { return err; } /* is the residue zero? */ if (res == 0) { *result = MP_YES; return MP_OKAY; } } return MP_OKAY; }
/* Store non-zero to ret if arg is square, and zero if not */ int mp_is_square(mp_int *arg,int *ret) { int res; mp_digit c; mp_int t; unsigned long r; /* Default to Non-square :) */ *ret = MP_NO; if (arg->sign == MP_NEG) { return MP_VAL; } /* digits used? (TSD) */ if (arg->used == 0) { return MP_OKAY; } /* First check mod 128 (suppose that DIGIT_BIT is at least 7) */ if (rem_128[127 & DIGIT(arg,0)] == 1) { return MP_OKAY; } /* Next check mod 105 (3*5*7) */ if ((res = mp_mod_d(arg,105,&c)) != MP_OKAY) { return res; } if (rem_105[c] == 1) { return MP_OKAY; } /* product of primes less than 2^31 */ if ((res = mp_init_set_int(&t,11L*13L*17L*19L*23L*29L*31L)) != MP_OKAY) { return res; } if ((res = mp_mod(arg,&t,&t)) != MP_OKAY) { goto ERR; } r = mp_get_int(&t); /* Check for other prime modules, note it's not an ERROR but we must * free "t" so the easiest way is to goto ERR. We know that res * is already equal to MP_OKAY from the mp_mod call */ if ( (1L<<(r%11)) & 0x5C4L ) goto ERR; if ( (1L<<(r%13)) & 0x9E4L ) goto ERR; if ( (1L<<(r%17)) & 0x5CE8L ) goto ERR; if ( (1L<<(r%19)) & 0x4F50CL ) goto ERR; if ( (1L<<(r%23)) & 0x7ACCA0L ) goto ERR; if ( (1L<<(r%29)) & 0xC2EDD0CL ) goto ERR; if ( (1L<<(r%31)) & 0x6DE2B848L ) goto ERR; /* Final check - is sqr(sqrt(arg)) == arg ? */ if ((res = mp_sqrt(arg,&t)) != MP_OKAY) { goto ERR; } if ((res = mp_sqr(&t,&t)) != MP_OKAY) { goto ERR; } *ret = (mp_cmp_mag(&t,arg) == MP_EQ) ? MP_YES : MP_NO; ERR:mp_clear(&t); return res; }
/* finds the next prime after the number "a" using "t" trials * of Miller-Rabin. * * bbs_style = 1 means the prime must be congruent to 3 mod 4 */ int mp_prime_next_prime(mp_int *a, int t, int bbs_style) { int err, res, x, y; mp_digit res_tab[PRIME_SIZE], step, kstep; mp_int b; /* ensure t is valid */ if (t <= 0 || t > PRIME_SIZE) { return MP_VAL; } /* force positive */ a->sign = MP_ZPOS; /* simple algo if a is less than the largest prime in the table */ if (mp_cmp_d(a, ltm_prime_tab[PRIME_SIZE-1]) == MP_LT) { /* find which prime it is bigger than */ for (x = PRIME_SIZE - 2; x >= 0; x--) { if (mp_cmp_d(a, ltm_prime_tab[x]) != MP_LT) { if (bbs_style == 1) { /* ok we found a prime smaller or * equal [so the next is larger] * * however, the prime must be * congruent to 3 mod 4 */ if ((ltm_prime_tab[x + 1] & 3) != 3) { /* scan upwards for a prime congruent to 3 mod 4 */ for (y = x + 1; y < PRIME_SIZE; y++) { if ((ltm_prime_tab[y] & 3) == 3) { mp_set(a, ltm_prime_tab[y]); return MP_OKAY; } } } } else { mp_set(a, ltm_prime_tab[x + 1]); return MP_OKAY; } } } /* at this point a maybe 1 */ if (mp_cmp_d(a, 1) == MP_EQ) { mp_set(a, 2); return MP_OKAY; } /* fall through to the sieve */ } /* generate a prime congruent to 3 mod 4 or 1/3 mod 4? */ if (bbs_style == 1) { kstep = 4; } else { kstep = 2; } /* at this point we will use a combination of a sieve and Miller-Rabin */ if (bbs_style == 1) { /* if a mod 4 != 3 subtract the correct value to make it so */ if ((a->dp[0] & 3) != 3) { if ((err = mp_sub_d(a, (a->dp[0] & 3) + 1, a)) != MP_OKAY) { return err; }; } } else { if (mp_iseven(a) == 1) { /* force odd */ if ((err = mp_sub_d(a, 1, a)) != MP_OKAY) { return err; } } } /* generate the restable */ for (x = 1; x < PRIME_SIZE; x++) { if ((err = mp_mod_d(a, ltm_prime_tab[x], res_tab + x)) != MP_OKAY) { return err; } } /* init temp used for Miller-Rabin Testing */ if ((err = mp_init(&b)) != MP_OKAY) { return err; } for (;;) { /* skip to the next non-trivially divisible candidate */ step = 0; do { /* y == 1 if any residue was zero [e.g. cannot be prime] */ y = 0; /* increase step to next candidate */ step += kstep; /* compute the new residue without using division */ for (x = 1; x < PRIME_SIZE; x++) { /* add the step to each residue */ res_tab[x] += kstep; /* subtract the modulus [instead of using division] */ if (res_tab[x] >= ltm_prime_tab[x]) { res_tab[x] -= ltm_prime_tab[x]; } /* set flag if zero */ if (res_tab[x] == 0) { y = 1; } } } while (y == 1 && step < ((((mp_digit)1)<<DIGIT_BIT) - kstep)); /* add the step */ if ((err = mp_add_d(a, step, a)) != MP_OKAY) { goto LBL_ERR; } /* if didn't pass sieve and step == MAX then skip test */ if (y == 1 && step >= ((((mp_digit)1)<<DIGIT_BIT) - kstep)) { continue; } /* is this prime? */ for (x = 0; x < t; x++) { mp_set(&b, ltm_prime_tab[t]); if ((err = mp_prime_miller_rabin(a, &b, &res)) != MP_OKAY) { goto LBL_ERR; } if (res == MP_NO) { break; } } if (res == MP_YES) { break; } } err = MP_OKAY; LBL_ERR: mp_clear(&b); return err; }
int main(int argc, char *argv[]) { int ix; mp_int a, b, c, m; mp_digit r; if(argc < 4) { fprintf(stderr, "Usage: %s <a> <b> <m>\n", argv[0]); return 1; } printf("Test 4: Modular arithmetic\n\n"); mp_init(&a); mp_init(&b); mp_init(&m); mp_read_radix(&a, argv[1], 10); mp_read_radix(&b, argv[2], 10); mp_read_radix(&m, argv[3], 10); printf("a = "); mp_print(&a, stdout); fputc('\n', stdout); printf("b = "); mp_print(&b, stdout); fputc('\n', stdout); printf("m = "); mp_print(&m, stdout); fputc('\n', stdout); mp_init(&c); printf("\nc = a (mod m)\n"); mp_mod(&a, &m, &c); printf("c = "); mp_print(&c, stdout); fputc('\n', stdout); printf("\nc = b (mod m)\n"); mp_mod(&b, &m, &c); printf("c = "); mp_print(&c, stdout); fputc('\n', stdout); printf("\nc = b (mod 1853)\n"); mp_mod_d(&b, 1853, &r); printf("c = %04X\n", r); printf("\nc = (a + b) mod m\n"); mp_addmod(&a, &b, &m, &c); printf("c = "); mp_print(&c, stdout); fputc('\n', stdout); printf("\nc = (a - b) mod m\n"); mp_submod(&a, &b, &m, &c); printf("c = "); mp_print(&c, stdout); fputc('\n', stdout); printf("\nc = (a * b) mod m\n"); mp_mulmod(&a, &b, &m, &c); printf("c = "); mp_print(&c, stdout); fputc('\n', stdout); printf("\nc = (a ** b) mod m\n"); mp_exptmod(&a, &b, &m, &c); printf("c = "); mp_print(&c, stdout); fputc('\n', stdout); printf("\nIn-place modular squaring test:\n"); for(ix = 0; ix < 5; ix++) { printf("a = (a * a) mod m a = "); mp_sqrmod(&a, &m, &a); mp_print(&a, stdout); fputc('\n', stdout); } mp_clear(&c); mp_clear(&m); mp_clear(&b); mp_clear(&a); return 0; }
/* Sets ret to nonzero value if arg is square, 0 if not Sets t to the square root of arg if one is available, 0 if not */ static int mp_issquare(mp_int *arg, int *ret, mp_int *t) { int res; mp_digit c; mp_int tmp; unsigned long r; /* Default to Non-square :) */ *ret = MP_NO; if (arg->sign == MP_NEG) { return MP_VAL; } /* digits used? (TSD) */ if (arg->used == 0) { return MP_OKAY; } /* First check mod 128 (suppose that DIGIT_BIT is at least 7) */ if (rem_128[127 & DIGIT(arg, 0)] == 1) { mp_set_int(t, (mp_digit)(0)); return MP_OKAY; } /* Next check mod 105 (3*5*7) */ if ((res = mp_mod_d(arg, 105, &c)) != MP_OKAY) { mp_set_int(t, (mp_digit)(0)); return res; } if (rem_105[c] == 1) { mp_set_int(t, (mp_digit)(0)); return MP_OKAY; } if ((res = mp_init_set_int(t, 11L * 13L * 17L * 19L * 23L * 29L * 31L)) != MP_OKAY) { mp_set_int(t, (mp_digit)(0)); return res; } if ((res = mp_mod(arg, t, t)) != MP_OKAY) { goto ERR; } r = mp_get_int(t); /* Check for other prime modules. We know that res * is already equal to MP_OKAY from the mp_mod call */ if ((1L << (r % 11)) & 0x5C4L) goto ERR; if ((1L << (r % 13)) & 0x9E4L) goto ERR; if ((1L << (r % 17)) & 0x5CE8L) goto ERR; if ((1L << (r % 19)) & 0x4F50CL) goto ERR; if ((1L << (r % 23)) & 0x7ACCA0L) goto ERR; if ((1L << (r % 29)) & 0xC2EDD0CL) goto ERR; if ((1L << (r % 31)) & 0x6DE2B848L) goto ERR; /* Final check - is sqr(sqrt(arg)) == arg ? */ if ((res = mp_sqrt(arg, t)) != MP_OKAY) { goto ERR; } mp_init(&tmp); if ((res = mp_sqr(t, &tmp)) != MP_OKAY) { goto ERR; } *ret = (mp_cmp_mag(&tmp, arg) == MP_EQ) ? MP_YES : MP_NO; mp_clear(&tmp); return res; ERR: mp_set_int(t, (mp_digit)(0)); mp_clear(&tmp); return res; }
static int next_prime(mp_int *N, mp_digit step) { long x, s, j, total_dist; int res; mp_int n1, a, y, r; mp_digit dist, residues[UPPER_LIMIT]; _ARGCHK(N != NULL); /* first find the residues */ for (x = 0; x < (long)UPPER_LIMIT; x++) { if (mp_mod_d(N, __prime_tab[x], &residues[x]) != MP_OKAY) { return CRYPT_MEM; } } /* init variables */ if (mp_init_multi(&r, &n1, &a, &y, NULL) != MP_OKAY) { return CRYPT_MEM; } total_dist = 0; loop: /* while one of the residues is zero keep looping */ dist = step; for (x = 0; (dist < (MP_DIGIT_MAX-step-1)) && (x < (long)UPPER_LIMIT); x++) { j = (long)residues[x] + (long)dist + total_dist; if (j % (long)__prime_tab[x] == 0) { dist += step; x = -1; } } /* recalc the total distance from where we started */ total_dist += dist; /* add to N */ if (mp_add_d(N, dist, N) != MP_OKAY) { goto error; } /* n1 = N - 1 */ if (mp_sub_d(N, 1, &n1) != MP_OKAY) { goto error; } /* r = N - 1 */ if (mp_copy(&n1, &r) != MP_OKAY) { goto error; } /* find s such that N-1 = (2^s)r */ s = 0; while (mp_iseven(&r)) { ++s; if (mp_div_2(&r, &r) != MP_OKAY) { goto error; } } for (x = 0; x < 8; x++) { /* choose a */ mp_set(&a, __prime_tab[x]); /* compute y = a^r mod n */ if (mp_exptmod(&a, &r, N, &y) != MP_OKAY) { goto error; } /* (y != 1) AND (y != N-1) */ if ((mp_cmp_d(&y, 1) != 0) && (mp_cmp(&y, &n1) != 0)) { /* while j <= s-1 and y != n-1 */ for (j = 1; (j <= (s-1)) && (mp_cmp(&y, &n1) != 0); j++) { /* y = y^2 mod N */ if (mp_sqrmod(&y, N, &y) != MP_OKAY) { goto error; } /* if y == 1 return false */ if (mp_cmp_d(&y, 1) == 0) { goto loop; } } /* if y != n-1 return false */ if (mp_cmp(&y, &n1) != 0) { goto loop; } } } res = CRYPT_OK; goto done; error: res = CRYPT_MEM; done: mp_clear_multi(&a, &y, &n1, &r, NULL); #ifdef CLEAN_STACK zeromem(residues, sizeof(residues)); #endif return res; }