Various randomness handling bugfixes and improvements --

some utilities that should have used RANDFILE did not,
and -rand handling was broken except in genrsa.
This commit is contained in:
Bodo Möller 1999-10-26 01:56:29 +00:00
parent 38899535f8
commit a31011e8e0
15 changed files with 134 additions and 172 deletions

27
CHANGES
View file

@ -4,6 +4,33 @@
Changes between 0.9.4 and 0.9.5 [xx XXX 1999]
*) New file apps/app_rand.c with commonly needed functionality
for handling the random seed file.
Use the random seed file in some applications that previously did not:
ca,
dsaparam -genkey (which also ignored its `-rand' option),
s_client,
s_server,
x509 (when signing).
Except on systems with /dev/urandom, it is crucial to have a random
seed file at least for key creation, DSA signing, and for DH exchanges;
for RSA signatures it might not hurt _that_ much not to have one.
gendh and gendsa (unlike genrsa) used to read only the first byte
of each file listed in the `-rand' option. The function as previously
found in genrsa is now in app_rand.c and is used by all programs
that support `-rand'.
[Bodo Moeller]
*) In RAND_write_file, use mode 0600 for creating files;
don't just chmod when it may be too late.
[Bodo Moeller]
*) Report an error from X509_STORE_load_locations
when X509_LOOKUP_load_file or X509_LOOKUP_add_dir failed.
[Bill Perry]
*) New function ASN1_mbstring_copy() this copies a string in either
ASCII, Unicode, Universal (4 bytes per character) or UTF8 format
into an ASN1_STRING type. A mask of permissible types is passed

View file

@ -13,6 +13,7 @@ OPENSSLDIR= /usr/local/ssl
MAKE= make -f Makefile.ssl
MAKEDEPEND= $(TOP)/util/domd $(TOP)
MAKEFILE= Makefile.ssl
PERL=/usr/local/bin/perl
RM= rm -f
PEX_LIBS=
@ -45,12 +46,14 @@ A_OBJ=apps.o
A_SRC=apps.c
S_OBJ= s_cb.o s_socket.o
S_SRC= s_cb.c s_socket.c
RAND_OBJ=app_rand.o
RAND_SRC=app_rand.c
E_OBJ= verify.o asn1pars.o req.o dgst.o dh.o enc.o gendh.o errstr.o ca.o \
pkcs7.o crl2p7.o crl.o \
rsa.o dsa.o dsaparam.o \
x509.o genrsa.o gendsa.o s_server.o s_client.o speed.o \
s_time.o $(A_OBJ) $(S_OBJ) version.o sess_id.o \
s_time.o $(A_OBJ) $(S_OBJ) $(RAND_OBJ) version.o sess_id.o \
ciphers.o nseq.o pkcs12.o pkcs8.o spkac.o
# pem_mail.o
@ -59,7 +62,7 @@ E_SRC= verify.c asn1pars.c req.c dgst.c dh.c enc.c gendh.c errstr.c ca.c \
pkcs7.c crl2p7.c crl.c \
rsa.c dsa.c dsaparam.c \
x509.c genrsa.c gendsa.c s_server.c s_client.c speed.c \
s_time.c $(A_SRC) $(S_SRC) version.c sess_id.c \
s_time.c $(A_SRC) $(S_SRC) $(RAND_SRC) version.c sess_id.c \
ciphers.c nseq.c pkcs12.c pkcs8.c spkac.c
# pem_mail.c
@ -81,7 +84,7 @@ all: exe
exe: $(EXE)
req: sreq.o $(A_OBJ) $(DLIBCRYPTO)
$(CC) -o req $(CFLAG) sreq.o $(A_OBJ) $(PEX_LIBS) $(LIBCRYPTO) $(EX_LIBS)
$(CC) -o req $(CFLAG) sreq.o $(A_OBJ) $(RAND_OBJ) $(PEX_LIBS) $(LIBCRYPTO) $(EX_LIBS)
sreq.o: req.c
$(CC) -c $(INCLUDES) $(CFLAG) -o sreq.o req.c
@ -138,8 +141,8 @@ $(PROGRAM): progs.h $(E_OBJ) $(PROGRAM).o $(DLIBCRYPTO) $(DLIBSSL)
$(CC) -o $(PROGRAM) $(CFLAGS) $(PROGRAM).o $(E_OBJ) $(PEX_LIBS) $(LIBSSL) $(LIBCRYPTO) $(EX_LIBS)
@(cd ..; OPENSSL="`pwd`/apps/openssl"; export OPENSSL; sh tools/c_rehash certs)
progs.h:
$(PERL) ./progs.pl $(E_EXE) >progs.h
progs.h: progs.pl
$(PERL) progs.pl $(E_EXE) >progs.h
$(RM) $(PROGRAM).o
# DO NOT DELETE THIS LINE -- make depend depends on it.

View file

@ -66,6 +66,16 @@
#include <openssl/crypto.h>
#include "progs.h"
int app_RAND_load_file(const char *file, BIO *bio_e, int dont_warn);
int app_RAND_write_file(const char *file, BIO *bio_e);
/* When `file' is NULL, use defaults.
* `bio_e' is for error messages. */
void app_RAND_allow_write_file(void);
long app_RAND_load_files(char *file); /* `file' is a list of files to read,
* separated by LIST_SEPARATOR_CHAR
* (see e_os.h). The string is
* destroyed! */
#ifdef NO_STDIO
BIO_METHOD *BIO_s_file();
#endif

View file

@ -266,6 +266,7 @@ int MAIN(int argc, char **argv)
#undef BSIZE
#define BSIZE 256
MS_STATIC char buf[3][BSIZE];
char *randfile;
#ifdef EFENCE
EF_PROTECT_FREE=1;
@ -495,12 +496,16 @@ bad:
BIO_free(oid_bio);
}
}
}
if(!add_oid_section(conf)) {
if(!add_oid_section(conf))
{
ERR_print_errors(bio_err);
goto err;
}
}
randfile = CONF_get_string(conf, BASE_SECTION, "RANDFILE");
app_RAND_load_file(randfile, bio_err, 0);
in=BIO_new(BIO_s_file());
out=BIO_new(BIO_s_file());
Sout=BIO_new(BIO_s_file());
@ -1236,6 +1241,7 @@ err:
sk_pop_free(cert_sk,X509_free);
if (ret) ERR_print_errors(bio_err);
app_RAND_write_file(randfile, bio_err);
BN_free(serial);
TXT_DB_free(db);
EVP_PKEY_free(pkey);

View file

@ -57,6 +57,7 @@
*/
#ifndef NO_DSA
#include <assert.h>
#include <stdio.h>
#include <stdlib.h>
#include <time.h>
@ -65,7 +66,6 @@
#include <openssl/bio.h>
#include <openssl/err.h>
#include <openssl/bn.h>
#include <openssl/rand.h>
#include <openssl/dsa.h>
#include <openssl/x509.h>
#include <openssl/pem.h>
@ -93,7 +93,7 @@ int MAIN(int argc, char **argv)
int informat,outformat,noout=0,C=0,ret=1;
char *infile,*outfile,*prog,*inrand=NULL;
int numbits= -1,num,genkey=0;
char buffer[200],*randfile=NULL;
int need_rand=0;
apps_startup();
@ -136,11 +136,15 @@ int MAIN(int argc, char **argv)
else if (strcmp(*argv,"-C") == 0)
C=1;
else if (strcmp(*argv,"-genkey") == 0)
{
genkey=1;
need_rand=1;
}
else if (strcmp(*argv,"-rand") == 0)
{
if (--argc < 1) goto bad;
inrand= *(++argv);
need_rand=1;
}
else if (strcmp(*argv,"-noout") == 0)
noout=1;
@ -148,6 +152,7 @@ int MAIN(int argc, char **argv)
{
/* generate a key */
numbits=num;
need_rand=1;
}
else
{
@ -207,11 +212,17 @@ bad:
}
}
if (need_rand)
{
app_RAND_load_file(NULL, bio_err, (inrand != NULL));
if (inrand != NULL)
BIO_printf(bio_err,"%ld semi-random bytes loaded\n",
app_RAND_load_files(inrand));
}
if (numbits > 0)
{
randfile=RAND_file_name(buffer,200);
RAND_load_file(randfile,1024L*1024L);
assert(need_rand);
BIO_printf(bio_err,"Generating DSA parameters, %d bit long prime\n",num);
BIO_printf(bio_err,"This could take some time\n");
dsa=DSA_generate_parameters(num,NULL,0,NULL,NULL,
@ -316,6 +327,7 @@ bad:
{
DSA *dsakey;
assert(need_rand);
if ((dsakey=DSAparams_dup(dsa)) == NULL) goto end;
if (!DSA_generate_key(dsakey)) goto end;
if (outformat == FORMAT_ASN1)
@ -328,6 +340,8 @@ bad:
}
DSA_free(dsakey);
}
if (need_rand)
app_RAND_write_file(NULL, bio_err);
ret=0;
end:
if (in != NULL) BIO_free(in);

View file

@ -75,7 +75,6 @@
#define PROG gendh_main
static void MS_CALLBACK dh_cb(int p, int n, void *arg);
static long dh_load_rand(char *names);
int MAIN(int argc, char **argv)
{
char buffer[200];
@ -83,7 +82,7 @@ int MAIN(int argc, char **argv)
int ret=1,num=DEFBITS;
int g=2;
char *outfile=NULL;
char *inrand=NULL,*randfile;
char *inrand=NULL;
BIO *out=NULL;
apps_startup();
@ -150,17 +149,13 @@ bad:
}
}
randfile=RAND_file_name(buffer,200);
if ((randfile == NULL)|| !RAND_load_file(randfile,1024L*1024L))
BIO_printf(bio_err,"unable to load 'random state'\n");
if (inrand == NULL)
BIO_printf(bio_err,"warning, not much extra random data, consider using the -rand option\n");
else
if (!app_RAND_load_file(NULL, bio_err, 1) && inrand == NULL)
{
BIO_printf(bio_err,"%ld semi-random bytes loaded\n",
dh_load_rand(inrand));
BIO_printf(bio_err,"warning, not much extra random data, consider using the -rand option\n");
}
if (inrand != NULL)
BIO_printf(bio_err,"%ld semi-random bytes loaded\n",
app_RAND_load_files(inrand));
BIO_printf(bio_err,"Generating DH parameters, %d bit long strong prime, generator of %d\n",num,g);
BIO_printf(bio_err,"This is going to take a long time\n");
@ -168,10 +163,7 @@ bad:
if (dh == NULL) goto end;
if (randfile == NULL)
BIO_printf(bio_err,"unable to write 'random state'\n");
else
RAND_write_file(randfile);
app_RAND_write_file(NULL, bio_err);
if (!PEM_write_bio_DHparams(out,dh))
goto end;
@ -198,26 +190,4 @@ static void MS_CALLBACK dh_cb(int p, int n, void *arg)
p=n;
#endif
}
static long dh_load_rand(char *name)
{
char *p,*n;
int last;
long tot=0;
for (;;)
{
last=0;
for (p=name; ((*p != '\0') && (*p != LIST_SEPARATOR_CHAR)); p++);
if (*p == '\0') last=1;
*p='\0';
n=name;
name=p+1;
if (*n == '\0') break;
tot+=RAND_load_file(n,1);
if (last) break;
}
return(tot);
}
#endif

View file

@ -63,7 +63,6 @@
#include <sys/stat.h>
#include "apps.h"
#include <openssl/bio.h>
#include <openssl/rand.h>
#include <openssl/err.h>
#include <openssl/bn.h>
#include <openssl/dsa.h>
@ -74,14 +73,12 @@
#undef PROG
#define PROG gendsa_main
static long dsa_load_rand(char *names);
int MAIN(int argc, char **argv)
{
char buffer[200];
DSA *dsa=NULL;
int ret=1;
char *outfile=NULL;
char *inrand=NULL,*randfile,*dsaparams=NULL;
char *inrand=NULL,*dsaparams=NULL;
BIO *out=NULL,*in=NULL;
EVP_CIPHER *enc=NULL;
@ -176,26 +173,19 @@ bad:
}
}
randfile=RAND_file_name(buffer,200);
if ((randfile == NULL)|| !RAND_load_file(randfile,1024L*1024L))
BIO_printf(bio_err,"unable to load 'random state'\n");
if (inrand == NULL)
BIO_printf(bio_err,"warning, not much extra random data, consider using the -rand option\n");
else
if (!app_RAND_load_file(NULL, bio_err, 1) && inrand == NULL)
{
BIO_printf(bio_err,"%ld semi-random bytes loaded\n",
dsa_load_rand(inrand));
BIO_printf(bio_err,"warning, not much extra random data, consider using the -rand option\n");
}
if (inrand != NULL)
BIO_printf(bio_err,"%ld semi-random bytes loaded\n",
app_RAND_load_files(inrand));
BIO_printf(bio_err,"Generating DSA key, %d bits\n",
BN_num_bits(dsa->p));
if (!DSA_generate_key(dsa)) goto end;
if (randfile == NULL)
BIO_printf(bio_err,"unable to write 'random state'\n");
else
RAND_write_file(randfile);
app_RAND_write_file(NULL, bio_err);
if (!PEM_write_bio_DSAPrivateKey(out,dsa,enc,NULL,0,NULL,NULL))
goto end;
@ -207,26 +197,4 @@ end:
if (dsa != NULL) DSA_free(dsa);
EXIT(ret);
}
static long dsa_load_rand(char *name)
{
char *p,*n;
int last;
long tot=0;
for (;;)
{
last=0;
for (p=name; ((*p != '\0') && (*p != LIST_SEPARATOR_CHAR)); p++);
if (*p == '\0') last=1;
*p='\0';
n=name;
name=p+1;
if (*n == '\0') break;
tot+=RAND_load_file(n,1);
if (last) break;
}
return(tot);
}
#endif

View file

@ -63,7 +63,6 @@
#include <sys/stat.h>
#include "apps.h"
#include <openssl/bio.h>
#include <openssl/rand.h>
#include <openssl/err.h>
#include <openssl/bn.h>
#include <openssl/rsa.h>
@ -76,18 +75,16 @@
#define PROG genrsa_main
static void MS_CALLBACK genrsa_cb(int p, int n, void *arg);
static long gr_load_rand(char *names);
int MAIN(int argc, char **argv)
{
int ret=1;
char buffer[200];
RSA *rsa=NULL;
int i,num=DEFBITS;
long rnum=0,l;
long l;
EVP_CIPHER *enc=NULL;
unsigned long f4=RSA_F4;
char *outfile=NULL;
char *inrand=NULL,*randfile;
char *inrand=NULL;
BIO *out=NULL;
apps_startup();
@ -165,41 +162,19 @@ bad:
}
}
#ifdef WINDOWS
BIO_printf(bio_err,"Loading 'screen' into random state -");
BIO_flush(bio_err);
RAND_screen();
BIO_printf(bio_err," done\n");
#endif
randfile=RAND_file_name(buffer,200);
if ((randfile == NULL) ||
!(rnum=(long)RAND_load_file(randfile,1024L*1024L)))
if (!app_RAND_load_file(NULL, bio_err, 1) && inrand == NULL)
{
BIO_printf(bio_err,"unable to load 'random state'\n");
BIO_printf(bio_err,"warning, not much extra random data, consider using the -rand option\n");
}
if (inrand == NULL)
{
if (rnum == 0)
{
BIO_printf(bio_err,"warning, not much extra random data, consider using the -rand option\n");
}
}
else
{
rnum+=gr_load_rand(inrand);
}
if (rnum != 0)
BIO_printf(bio_err,"%ld semi-random bytes loaded\n",rnum);
if (inrand != NULL)
BIO_printf(bio_err,"%ld semi-random bytes loaded\n",
app_RAND_load_files(inrand));
BIO_printf(bio_err,"Generating RSA private key, %d bit long modulus\n",
num);
rsa=RSA_generate_key(num,f4,genrsa_cb,bio_err);
if (randfile == NULL)
BIO_printf(bio_err,"unable to write 'random state'\n");
else
RAND_write_file(randfile);
app_RAND_write_file(NULL, bio_err);
if (rsa == NULL) goto err;
@ -241,26 +216,4 @@ static void MS_CALLBACK genrsa_cb(int p, int n, void *arg)
p=n;
#endif
}
static long gr_load_rand(char *name)
{
char *p,*n;
int last;
long tot=0;
for (;;)
{
last=0;
for (p=name; ((*p != '\0') && (*p != LIST_SEPARATOR_CHAR)); p++);
if (*p == '\0') last=1;
*p='\0';
n=name;
name=p+1;
if (*n == '\0') break;
tot+=RAND_load_file(n,1024L*1024L);
if (last) break;
}
return(tot);
}
#endif

View file

@ -73,14 +73,14 @@ FUNCTION functions[] = {
#ifndef NO_DSA
{FUNC_TYPE_GENERAL,"gendsa",gendsa_main},
#endif
#if !defined(NO_SOCK) && !(defined(NO_SSL2) && defined(O_SSL3))
#if !defined(NO_SOCK) && !(defined(NO_SSL2) && defined(NO_SSL3))
{FUNC_TYPE_GENERAL,"s_server",s_server_main},
#endif
#if !defined(NO_SOCK) && !(defined(NO_SSL2) && defined(O_SSL3))
#if !defined(NO_SOCK) && !(defined(NO_SSL2) && defined(NO_SSL3))
{FUNC_TYPE_GENERAL,"s_client",s_client_main},
#endif
{FUNC_TYPE_GENERAL,"speed",speed_main},
#if !defined(NO_SOCK) && !(defined(NO_SSL2) && defined(O_SSL3))
#if !defined(NO_SOCK) && !(defined(NO_SSL2) && defined(NO_SSL3))
{FUNC_TYPE_GENERAL,"s_time",s_time_main},
#endif
{FUNC_TYPE_GENERAL,"version",version_main},

View file

@ -29,13 +29,15 @@ foreach (@ARGV)
push(@files,$_);
$str="\t{FUNC_TYPE_GENERAL,\"$_\",${_}_main},\n";
if (($_ =~ /^s_/) || ($_ =~ /^ciphers$/))
{ print "#if !defined(NO_SOCK) && !(defined(NO_SSL2) && defined(O_SSL3))\n${str}#endif\n"; }
{ print "#if !defined(NO_SOCK) && !(defined(NO_SSL2) && defined(NO_SSL3))\n${str}#endif\n"; }
elsif ( ($_ =~ /^rsa$/) || ($_ =~ /^genrsa$/) )
{ print "#ifndef NO_RSA\n${str}#endif\n"; }
elsif ( ($_ =~ /^dsa$/) || ($_ =~ /^gendsa$/) || ($_ =~ /^dsaparam$/))
{ print "#ifndef NO_DSA\n${str}#endif\n"; }
elsif ( ($_ =~ /^dh$/) || ($_ =~ /^gendh$/))
{ print "#ifndef NO_DH\n${str}#endif\n"; }
elsif ( ($_ =~ /^pkcs12$/))
{ print "#if !defined(NO_DES) && !defined(NO_SHA1)\n${str}#endif\n"; }
else
{ print $str; }
}

View file

@ -66,7 +66,6 @@
#include "apps.h"
#include <openssl/bio.h>
#include <openssl/evp.h>
#include <openssl/rand.h>
#include <openssl/conf.h>
#include <openssl/err.h>
#include <openssl/asn1.h>
@ -501,25 +500,9 @@ bad:
if (newreq && (pkey == NULL))
{
char *randfile;
char buffer[200];
if ((randfile=CONF_get_string(req_conf,SECTION,"RANDFILE")) == NULL)
randfile=RAND_file_name(buffer,200);
#ifdef WINDOWS
BIO_printf(bio_err,"Loading 'screen' into random state -");
BIO_flush(bio_err);
RAND_screen();
BIO_printf(bio_err," done\n");
#endif
if ((randfile == NULL) || !RAND_load_file(randfile,1024L*1024L))
{
BIO_printf(bio_err,"unable to load 'random state'\n");
BIO_printf(bio_err,"What this means is that the random number generator has not been seeded\n");
BIO_printf(bio_err,"with much random data.\n");
BIO_printf(bio_err,"Consider setting the RANDFILE environment variable to point at a file that\n");
BIO_printf(bio_err,"'random' data can be kept in.\n");
}
char *randfile = CONF_get_string(req_conf,SECTION,"RANDFILE");
app_RAND_load_file(randfile, bio_err, 0);
if (newkey <= 0)
{
newkey=(int)CONF_get_number(req_conf,SECTION,BITS);
@ -557,8 +540,7 @@ bad:
}
#endif
if ((randfile == NULL) || (RAND_write_file(randfile) == 0))
BIO_printf(bio_err,"unable to write 'random state'\n");
app_RAND_write_file(randfile, bio_err);
if (pkey == NULL) goto end;

View file

@ -323,6 +323,8 @@ bad:
goto end;
}
app_RAND_load_file(NULL, bio_err, 0);
if (bio_c_out == NULL)
{
if (c_quiet)

View file

@ -583,6 +583,8 @@ bad:
goto end;
}
app_RAND_load_file(NULL, bio_err, 0);
if (bio_s_out == NULL)
{
if (s_quiet && !s_debug)

View file

@ -56,6 +56,7 @@
* [including the GNU Public Licence.]
*/
#include <assert.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
@ -161,6 +162,7 @@ int MAIN(int argc, char **argv)
const EVP_MD *md_alg,*digest=EVP_md5();
LHASH *extconf = NULL;
char *extsect = NULL, *extfile = NULL;
int need_rand = 0;
reqfile=0;
@ -201,7 +203,10 @@ int MAIN(int argc, char **argv)
keyformat=str2fmt(*(++argv));
}
else if (strcmp(*argv,"-req") == 0)
{
reqfile=1;
need_rand = 1;
}
else if (strcmp(*argv,"-CAform") == 0)
{
if (--argc < 1) goto bad;
@ -247,6 +252,7 @@ int MAIN(int argc, char **argv)
if (--argc < 1) goto bad;
keyfile= *(++argv);
sign_flag= ++num;
need_rand = 1;
}
else if (strcmp(*argv,"-CA") == 0)
{
@ -320,6 +326,9 @@ bad:
goto end;
}
if (need_rand)
app_RAND_load_file(NULL, bio_err, 0);
ERR_load_crypto_strings();
X509V3_add_standard_extensions();
X509_PURPOSE_add_standard();
@ -651,6 +660,7 @@ bad:
digest=EVP_dss1();
#endif
assert(need_rand);
if (!sign(x,Upkey,days,digest,
extconf, extsect)) goto end;
}
@ -667,6 +677,7 @@ bad:
digest=EVP_dss1();
#endif
assert(need_rand);
if (!x509_certify(ctx,CAfile,digest,x,xca,
CApkey, CAserial,CA_createserial,days,
extconf, extsect))
@ -742,6 +753,8 @@ bad:
}
ret=0;
end:
if (need_rand)
app_RAND_write_file(NULL, bio_err);
OBJ_cleanup();
CONF_free(extconf);
BIO_free(out);

View file

@ -78,7 +78,7 @@
#define BUFSIZE 1024
#define RAND_DATA 1024
/* #define RFILE ".rand" - defined in ../../e_os.h */
/* #define RFILE ".rnd" - defined in ../../e_os.h */
int RAND_load_file(const char *file, long bytes)
{
@ -119,7 +119,7 @@ int RAND_write_file(const char *file)
{
unsigned char buf[BUFSIZE];
int i,ret=0;
FILE *out;
FILE *out = NULL;
int n;
/* Under VMS, fopen(file, "wb") will create a new version of the
@ -130,12 +130,22 @@ int RAND_write_file(const char *file)
out=fopen(file,"rb+");
if (out == NULL
#ifdef ENOENT
&& errno == ENOENT
&& errno == ENOENT
#endif
)
{
errno = 0;
#if defined O_CREAT && defined O_EXCL
/* chmod(..., 0600) is too late to protect the file,
* permissions should be restrictive from the start */
{
int fd = open(file, O_CREAT | O_EXCL, 0600);
if (fd != -1)
out = fdopen(fd, "wb");
}
#else
out=fopen(file,"wb");
#endif
}
if (out == NULL) goto err;
#ifndef NO_CHMOD