I do not think this is a bug. On average with truly random exponents, you
would expect that about 1/2 of the time the result of DH_generate_key() is
less than 1/2 of the modulus, 1/4 of the time it is less than 1/4 of the
modulus, ..., 2^-n of the time it is less than 2^-n * modulus. So if your
modulus is very close to 2^(8n), you would expect to see about 1/256 of the
time a result that is one byte smaller than the modulus, and 1/65536 of the
time a result that is two bytes smaller than the modulus. This is in fact
what you are seeing. There is nothing wrong with this, you simply have to
deal with it. For example, the IKE protocol says you must always send n
bytes and must pad with high-order zeros if necessary.
Greg Stark, [EMAIL PROTECTED]
Chief Security Architect
Ethentica, Inc.
www.ethentica.com
----- Original Message -----
From: "Lawrence MacIntyre" <[EMAIL PROTECTED]>
To: <[EMAIL PROTECTED]>
Sent: Wednesday, November 01, 2000 9:40 AM
Subject: possible bug in DH_generate_key()
> Hi:
>
> I have been having spurious problems with one of my client server
> programs. It uses a DH Key exchange to generate a blowfish key and
> encrypts the data using that key. I believe I have isolated the problem
> to the minimum of code. I'm attaching the test program, Makefile, and a
> bash script that runs the program 1000 times. It uses BN_new() and
> BN_hex2bn() to convert two strings to BIGNUMs, stuffs them into a DH,
> and then calls DH_generate_key() to generate the private/public key
> pair. When you run the program 1000 times, somewhere between 3 and 9
> times the length of the public key will be 55 bytes instead of 56, as it
> should be. This breaks my client:-( Once, the key was actually 54
> bytes. My workaround is to test for the length and if it's wrong,
> delete the DH struct, and regenerate (ugly but effective). Simply
> regenerating the key doesn't work. Am I doing something dopey or is
> this a bug?
>
> --
> Lawrence
> ~
> ------------------------------------------------------------------------
> Lawrence MacIntyre Center for Information Infrastructure Technology
> [EMAIL PROTECTED] http://www.ciit.y12.doe.gov/~lpz 865.574.8696
>
>
----------------------------------------------------------------------------
----
> # $Id: Makefile,v 1.2 2000/10/04 19:25:19 lpz Exp $
> #
> # Changes:
> #CC = kgcc #for RH 7.0
> CC = gcc
> CFLAGS = -g -Wall
> COMMONOBJS =
> INCLUDES =
> INCLUDEDIRS = -I/usr/local/ssl/include
> OBJS = dhtst.o
> LIBDIRS = -L/usr/local/ssl/lib
> LIBS = -lcrypto
> RM = rm -f
> EXES = dhtst
> TAR = tar
> ZIP = zip
> SRCS = Makefile.dhtst dhtst.c dh_crypto.h dhtstloop.sh
>
> all: dhtst
>
> dhtst: dhtst.o
> $(CC) $(CFLAGS) -o dhtst dhtst.o $(COMMONOBJS) $(LIBDIRS) $(LIBS)
>
> .PHONY: clean tar zip
>
> clean:
> $(RM) $(OBJS) $(COMMONOBJS) $(EXES) *.tar *.zip
>
> tar:
> $(TAR) czvf dhtst.tgz $(SRCS)
>
> zip:
> $(ZIP) dhtst.zip $(SRCS)
>
> dhtst.o: dhtst.c Makefile
> $(CC) $(CFLAGS) -c $(INCLUDEDIRS) dhtst.c
>
----------------------------------------------------------------------------
----
> /*
> * $Id: dh_crypto.h,v 1.2 2000/10/04 19:25:19 lpz Exp $
> *
> * Changes:
> *
> * 10/06/2000 - LPM - Remove DH pointer from dh_crypto struct
> * 10/13/2000 - LPM - Add P and G
> * remove dh_crypto struct (we only need the sock)
> */
> #ifndef DH_CRYPTO_H
> #define DH_CRYPTO_H
>
> #define DH_GMAX 1
> #define KEY_SIZE 448
> #define DH_PMAX KEY_SIZE/8
>
> struct pgpub {
> short int psize;
> short int gsize;
> short int pubsize;
> unsigned char buffer[2*DH_PMAX + DH_GMAX];
> };
>
> struct pubreply {
> short int pubsize;
> unsigned char pubk[DH_PMAX];
> };
>
> const char P[DH_PMAX] = {0xCA, 0x9C, 0x3C, 0xB3, 0xE2, 0x39, 0x84, 0x50,
0x76, 0xAC, 0xC3, 0x96, 0x36, 0x34, 0xA0, 0x2F, \
> 0x1A, 0x50, 0x03, 0x20, 0x9B, 0x29, 0xB1, 0xBF, 0x31, 0x7E, 0x18, 0xA0,
0xD2, 0x44, 0x0A, 0x63, \
> 0x08, 0x25, 0xC0, 0xC3, 0xE3, 0xF7, 0x22, 0x58, 0x59, 0x62, 0x91, 0x17,
0xC7, 0xDF, 0x28, 0x99, \
> 0x49, 0x3C, 0x7C, 0x49, 0xB1, 0x0F, 0x89, 0x37};
>
> const char G = 0x05;
> #endif
>
----------------------------------------------------------------------------
----
> #include <stdio.h>
> #include <string.h>
>
> #include <openssl/bn.h>
> #include <openssl/dh.h>
> #include <openssl/err.h>
>
> #include "dh_crypto.h"
>
> int main(int argc, char **argv)
> {
> int status;
> int retries = 0;
> DH *a = NULL;
>
> do {
> a = DH_new();
> if(a == NULL) {
> perror("DH_new(a): ");
> status = ERR_get_error();
> goto err;
> }
>
> a->p = BN_new();
> if(a->p == NULL) {
> status = ERR_get_error();
> goto err;
> }
>
> BN_bin2bn(P, sizeof(P), a->p);
>
> a->g = BN_new();
> if(a->g == NULL)
> status = ERR_get_error();
> goto err;
> }
>
> BN_bin2bn(&G, sizeof(G), a->g);
>
> if(!DH_generate_key(a)) {
> perror("DH_generate key: ");
> status = ERR_get_error();
> goto err;
> }
>
> status = BN_num_bytes(a->pub_key);
> if(status != 56) {
> printf("pub key size: %d\n", status);
> printf("Retries: %d\n", ++retries);
> }
> BN_free(a->g);
> a->g = NULL;
> BN_free(a->p);
> a->p = NULL;
> DH_free(a);
>
> } while(status != 56);
>
> status = 0;
> err:
> if(status != 0) {
> printf("Status: %d\n", status);
> }
> return(status);
> }
>
______________________________________________________________________
OpenSSL Project http://www.openssl.org
User Support Mailing List [EMAIL PROTECTED]
Automated List Manager [EMAIL PROTECTED]