Commit 4486d0cd authored by Ulf Möller's avatar Ulf Möller
Browse files

Document the DH library, and make some minor changes along the way.

parent 09483c58
Loading
Loading
Loading
Loading
+13 −2
Original line number Diff line number Diff line
@@ -4,6 +4,17 @@

 Changes between 0.9.4 and 0.9.5  [xx XXX 1999]

  *) Make BN_generate_prime() return NULL on error if ret!=NULL.
     [Ulf Möller]

  *) Retain source code compatibility for BN_prime_checks macro.
     [Ulf Möller]

  *) Diffie-Hellman uses "safe" primes: DH_check() return code renamed to
     DH_CHECK_P_NOT_SAFE_PRIME.
     (Check if this is true? OpenPGP calls them "strong".)
     [Ulf Möller]

  *) Merge the functionality of "dh" and "gendh" programs into a new program
     "dhparam". The old programs are retained for now but will handle DH keys
     (instead of parameters) in future.
@@ -57,8 +68,8 @@

  *) Do more iterations of Rabin-Miller probable prime test (specifically,
     3 for 1024-bit primes, 6 for 512-bit primes, 12 for 256-bit primes
     instead of only 2 for all lengths; see BN_prime_checks definition
     in crypto/bn/bn.h for the complete table).  This guarantees a
     instead of only 2 for all lengths; see BN_prime_checks_size definition
     in crypto/bn/bn_prime.c for the complete table).  This guarantees a
     false-positive rate of at most 2^-80 (actually less because we are
     additionally doing trial division) for random input.
     [Bodo Moeller]
+2 −17
Original line number Diff line number Diff line
@@ -283,23 +283,8 @@ typedef struct bn_recp_ctx_st
#define BN_to_montgomery(r,a,mont,ctx)	BN_mod_mul_montgomery(\
	r,a,&((mont)->RR),(mont),ctx)

/* number of Miller-Rabin iterations for an error rate  of less than 2^-80
 * for random 'b'-bit input, b >= 100 (taken from table 4.4 in the Handbook
 * of Applied Cryptography [Menezes, van Oorschot, Vanstone; CRC Press 1996];
 * original paper: Damgaard, Landrock, Pomerance: Average case error estimates
 * for the strong probable prime test. -- Math. Comp. 61 (1993) 177-194) */
#define BN_prime_checks(b) ((b) >= 1300 ?  2 : \
                            (b) >=  850 ?  3 : \
                            (b) >=  650 ?  4 : \
                            (b) >=  550 ?  5 : \
                            (b) >=  450 ?  6 : \
                            (b) >=  400 ?  7 : \
                            (b) >=  350 ?  8 : \
                            (b) >=  300 ?  9 : \
                            (b) >=  250 ? 12 : \
                            (b) >=  200 ? 15 : \
                            (b) >=  150 ? 18 : \
                            /* b >= 100 */ 27)
#define BN_prime_checks 0 /* default: select number of iterations
			     based on the size of the number */

#define BN_num_bytes(a)	((BN_num_bits(a)+7)/8)
#define BN_is_word(a,w)	(((a)->top == 1) && ((a)->d[0] == (BN_ULONG)(w)))
+30 −5
Original line number Diff line number Diff line
@@ -62,12 +62,30 @@
#include "bn_lcl.h"
#include <openssl/rand.h>

/* The quick seive algorithm approach to weeding out primes is
/* The quick sieve algorithm approach to weeding out primes is
 * Philip Zimmermann's, as implemented in PGP.  I have had a read of
 * his comments and implemented my own version.
 */
#include "bn_prime.h"

/* number of Miller-Rabin iterations for an error rate  of less than 2^-80
 * for random 'b'-bit input, b >= 100 (taken from table 4.4 in the Handbook
 * of Applied Cryptography [Menezes, van Oorschot, Vanstone; CRC Press 1996];
 * original paper: Damgaard, Landrock, Pomerance: Average case error estimates
 * for the strong probable prime test. -- Math. Comp. 61 (1993) 177-194) */
#define BN_prime_checks_size(b) ((b) >= 1300 ?  2 : \
                                (b) >=  850 ?  3 : \
                                (b) >=  650 ?  4 : \
                                (b) >=  550 ?  5 : \
                                (b) >=  450 ?  6 : \
                                (b) >=  400 ?  7 : \
                                (b) >=  350 ?  8 : \
                                (b) >=  300 ?  9 : \
                                (b) >=  250 ? 12 : \
                                (b) >=  200 ? 15 : \
                                (b) >=  150 ? 18 : \
                                /* b >= 100 */ 27)

static int witness(BIGNUM *a, BIGNUM *n, BN_CTX *ctx,BN_CTX *ctx2,
	BN_MONT_CTX *mont);
static int probable_prime(BIGNUM *rnd, int bits);
@@ -81,9 +99,10 @@ BIGNUM *BN_generate_prime(BIGNUM *ret, int bits, int safe, BIGNUM *add,
	{
	BIGNUM *rnd=NULL;
	BIGNUM t;
	int found=0;
	int i,j,c1=0;
	BN_CTX *ctx;
	int checks = BN_prime_checks(bits);
	int checks = BN_prime_checks_size(bits);

	ctx=BN_CTX_new();
	if (ctx == NULL) goto err;
@@ -145,12 +164,12 @@ loop:
			}
		}
	/* we have a prime :-) */
	ret=rnd;
	found = 1;
err:
	if ((ret == NULL) && (rnd != NULL)) BN_free(rnd);
	if (!found && (ret == NULL) && (rnd != NULL)) BN_free(rnd);
	BN_free(&t);
	if (ctx != NULL) BN_CTX_free(ctx);
	return(ret);
	return(found ? rnd : NULL);
	}

int BN_is_prime(BIGNUM *a, int checks, void (*callback)(int,int,void *),
@@ -161,6 +180,12 @@ int BN_is_prime(BIGNUM *a, int checks, void (*callback)(int,int,void *),
	BN_CTX *ctx=NULL,*ctx2=NULL;
	BN_MONT_CTX *mont=NULL;

	if (checks == BN_prime_checks)
		{
		int bits = BN_num_bits(a);
		checks = BN_prime_checks_size(bits);
		}

	if (!BN_is_odd(a))
		return(0);
	if (ctx_passed != NULL)
+6 −2
Original line number Diff line number Diff line
@@ -98,7 +98,7 @@ struct dh_st
	BIGNUM *p;
	BIGNUM *g;
	int length; /* optional */
	BIGNUM *pub_key;	/* y */
	BIGNUM *pub_key;	/* g^x */
	BIGNUM *priv_key;	/* x */

	int flags;
@@ -121,10 +121,14 @@ struct dh_st

/* DH_check error codes */
#define DH_CHECK_P_NOT_PRIME		0x01
#define DH_CHECK_P_NOT_STRONG_PRIME	0x02
#define DH_CHECK_P_NOT_SAFE_PRIME	0x02
#define DH_UNABLE_TO_CHECK_GENERATOR	0x04
#define DH_NOT_SUITABLE_GENERATOR	0x08

/* primes p where (p-1)/2 is prime too are called "safe"; we define
   this for backward compatibility: */
#define DH_CHECK_P_NOT_STRONG_PRIME	DH_CHECK_P_NOT_SAFE_PRIME

#define DHparams_dup(x) (DH *)ASN1_dup((int (*)())i2d_DHparams, \
		(char *(*)())d2i_DHparams,(char *)(x))
#define d2i_DHparams_fp(fp,x) (DH *)ASN1_d2i_fp((char *(*)())DH_new, \
+8 −6
Original line number Diff line number Diff line
@@ -61,7 +61,7 @@
#include <openssl/bn.h>
#include <openssl/dh.h>

/* Check that p is a strong prime and
/* Check that p is a safe prime and
 * if g is 2, 3 or 5, check that is is a suitable generator
 * where
 * for 2, p mod 24 == 11
@@ -88,11 +88,13 @@ int DH_check(DH *dh, int *ret)
		l=BN_mod_word(dh->p,24);
		if (l != 11) *ret|=DH_NOT_SUITABLE_GENERATOR;
		}
/*	else if (BN_is_word(dh->g,DH_GENERATOR_3))
#if 0
	else if (BN_is_word(dh->g,DH_GENERATOR_3))
		{
		l=BN_mod_word(dh->p,12);
		if (l != 5) *ret|=DH_NOT_SUITABLE_GENERATOR;
		}*/
		}
#endif
	else if (BN_is_word(dh->g,DH_GENERATOR_5))
		{
		l=BN_mod_word(dh->p,10);
@@ -102,13 +104,13 @@ int DH_check(DH *dh, int *ret)
	else
		*ret|=DH_UNABLE_TO_CHECK_GENERATOR;

	if (!BN_is_prime(dh->p,BN_prime_checks(BN_num_bits(dh->p)),NULL,ctx,NULL))
	if (!BN_is_prime(dh->p,BN_prime_checks,NULL,ctx,NULL))
		*ret|=DH_CHECK_P_NOT_PRIME;
	else
		{
		if (!BN_rshift1(q,dh->p)) goto err;
		if (!BN_is_prime(q,BN_prime_checks(BN_num_bits(q)),NULL,ctx,NULL))
			*ret|=DH_CHECK_P_NOT_STRONG_PRIME;
		if (!BN_is_prime(q,BN_prime_checks,NULL,ctx,NULL))
			*ret|=DH_CHECK_P_NOT_SAFE_PRIME;
		}
	ok=1;
err:
Loading