--- /dev/null
+/* TomsFastMath, a fast ISO C bignum library.
+ *
+ * This project is meant to fill in where LibTomMath
+ * falls short. That is speed ;-)
+ *
+ * This project is public domain and free for all purposes.
+ *
+ * Tom St Denis, tomstdenis@gmail.com
+ */
+#include <tfm_private.h>
+
+/* This is possibly the mother of all prime generation functions, muahahahahaha! */
+int fp_prime_random_ex(fp_int *a, int t, int size, int flags, tfm_prime_callback cb, void *dat)
+{
+ unsigned char *tmp, maskAND, maskOR_msb, maskOR_lsb;
+ int res, err, bsize, maskOR_msb_offset;
+
+ /* sanity check the input */
+ if (size <= 1 || cb == NULL || t <= 0 || t > FP_PRIME_SIZE) {
+ return FP_VAL;
+ }
+
+ /* TFM_PRIME_SAFE implies TFM_PRIME_BBS */
+ if (flags & TFM_PRIME_SAFE) {
+ flags |= TFM_PRIME_BBS;
+ }
+
+ /* calc the byte size */
+ bsize = (size>>3)+(size&7?1:0);
+
+ /* we need a buffer of bsize bytes */
+ tmp = malloc(bsize);
+ if (tmp == NULL) {
+ return FP_MEM;
+ }
+
+ /* calc the maskAND value for the MSbyte*/
+ maskAND = 0xFF >> ((8 - (size & 7)) & 7);
+
+ /* calc the maskOR_msb */
+ maskOR_msb = 0;
+ maskOR_msb_offset = (size - 2) >> 3;
+ if (flags & TFM_PRIME_2MSB_ON) {
+ maskOR_msb |= 1 << ((size - 2) & 7);
+ } else if (flags & TFM_PRIME_2MSB_OFF) {
+ maskAND &= ~(1 << ((size - 2) & 7));
+ }
+
+ /* get the maskOR_lsb */
+ maskOR_lsb = 1;
+ if (flags & TFM_PRIME_BBS) {
+ maskOR_lsb |= 3;
+ }
+
+ do {
+ /* read the bytes */
+ if (cb(tmp, bsize, dat) != bsize) {
+ err = FP_VAL;
+ goto error;
+ }
+
+ /* work over the MSbyte */
+ tmp[0] &= maskAND;
+ tmp[0] |= 1 << ((size - 1) & 7);
+
+ /* mix in the maskORs */
+ tmp[maskOR_msb_offset] |= maskOR_msb;
+ tmp[bsize-1] |= maskOR_lsb;
+
+ /* read it in */
+ fp_read_unsigned_bin(a, tmp, bsize);
+
+ /* is it prime? */
+ res = fp_isprime_ex(a, t);
+ if (res == FP_NO) continue;
+
+ if (flags & TFM_PRIME_SAFE) {
+ /* see if (a-1)/2 is prime */
+ fp_sub_d(a, 1, a);
+ fp_div_2(a, a);
+
+ /* is it prime? */
+ res = fp_isprime_ex(a, t);
+ }
+ } while (res == FP_NO);
+
+ if (flags & TFM_PRIME_SAFE) {
+ /* restore a to the original value */
+ fp_mul_2(a, a);
+ fp_add_d(a, 1, a);
+ }
+
+ err = FP_OKAY;
+error:
+ free(tmp);
+ return err;
+}
+
+/* $Source$ */
+/* $Revision$ */
+/* $Date$ */