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);
}
dhtstloop.sh