BIGNUM *BN_generate_prime(BIGNUM *ret, int bits, int safe, BIGNUM *add,
	     BIGNUM *rem, void (*callback)(int,int,void *), void *cb_arg)
	{
	BIGNUM *rnd=NULL;
	BIGNUM t;
	int found=0;
	int i,j,c1=0;
	BN_CTX *ctx;
	int checks = BN_prime_checks_for_size(bits);

	ctx=BN_CTX_new();
	if (ctx == NULL) goto err;
	if (ret == NULL)
		{
		if ((rnd=BN_new()) == NULL) goto err;
		}
	else
		rnd=ret;
	BN_init(&t);
loop: 
	/* make a random number and set the top and bottom bits */
	if (add == NULL)
		{
		if (!probable_prime(rnd,bits)) goto err;
		}
	else
		{
		if (safe)
			{
			if (!probable_prime_dh_safe(rnd,bits,add,rem,ctx))
				 goto err;
			}
		else
			{
			if (!probable_prime_dh(rnd,bits,add,rem,ctx))
				goto err;
			}
		}
	/* if (BN_mod_word(rnd,(BN_ULONG)3) == 1) goto loop; */
	if (callback != NULL) callback(0,c1++,cb_arg);

	if (!safe)
		{
		i=BN_is_prime_fasttest(rnd,checks,callback,ctx,cb_arg,0);
		if (i == -1) goto err;
		if (i == 0) goto loop;
		}
	else
		{
		/* for "safe prime" generation,
		 * check that (p-1)/2 is prime.
		 * Since a prime is odd, We just
		 * need to divide by 2 */
		if (!BN_rshift1(&t,rnd)) goto err;

		for (i=0; i<checks; i++)
			{
			j=BN_is_prime_fasttest(rnd,1,callback,ctx,cb_arg,0);
			if (j == -1) goto err;
			if (j == 0) goto loop;

			j=BN_is_prime_fasttest(&t,1,callback,ctx,cb_arg,0);
			if (j == -1) goto err;
			if (j == 0) goto loop;

			if (callback != NULL) callback(2,c1-1,cb_arg);
			/* We have a safe prime test pass */
			}
		}
	/* we have a prime :-) */
	found = 1;
err:
	if (!found && (ret == NULL) && (rnd != NULL)) BN_free(rnd);
	BN_free(&t);
	if (ctx != NULL) BN_CTX_free(ctx);
	return(found ? rnd : NULL);
	}