redo 1.1 -> 1.2. on RAND_file_name(), return /dev/urandom by default.
RAND_{load,write}_file() takes care of device file case. from openbsd.
This commit is contained in:
parent
07c471d18e
commit
0265b9e0c2
164
crypto/dist/openssl/crypto/rand/randfile.c
vendored
164
crypto/dist/openssl/crypto/rand/randfile.c
vendored
@ -60,22 +60,35 @@
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <sys/types.h>
|
||||
#include <sys/stat.h>
|
||||
#include <sys/types.h>
|
||||
|
||||
#include "openssl/e_os.h"
|
||||
|
||||
#ifdef VMS
|
||||
#include <unixio.h>
|
||||
#endif
|
||||
#ifndef NO_SYS_TYPES_H
|
||||
# include <sys/types.h>
|
||||
#endif
|
||||
#ifdef MAC_OS_pre_X
|
||||
# include <stat.h>
|
||||
#else
|
||||
# include <sys/stat.h>
|
||||
#endif
|
||||
|
||||
#include <openssl/crypto.h>
|
||||
#include <openssl/rand.h>
|
||||
|
||||
#undef BUFSIZE
|
||||
#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)
|
||||
{
|
||||
/* If bytes >= 0, read up to 'bytes' bytes.
|
||||
* if bytes == -1, read complete file. */
|
||||
|
||||
MS_STATIC unsigned char buf[BUFSIZE];
|
||||
struct stat sb;
|
||||
int i,ret=0,n;
|
||||
@ -85,23 +98,37 @@ int RAND_load_file(const char *file, long bytes)
|
||||
|
||||
i=stat(file,&sb);
|
||||
/* If the state fails, put some crap in anyway */
|
||||
RAND_seed(&sb,sizeof(sb));
|
||||
ret+=sizeof(sb);
|
||||
RAND_add(&sb,sizeof(sb),0);
|
||||
if (i < 0) return(0);
|
||||
if (bytes <= 0) return(ret);
|
||||
if (bytes == 0) return(ret);
|
||||
|
||||
in=fopen(file,"rb");
|
||||
if (in == NULL) goto err;
|
||||
if (sb.st_mode & (S_IFBLK | S_IFCHR)) {
|
||||
/*
|
||||
* this file is a device. we don't want read an infinite number
|
||||
* of bytes from a random device, nor do we want to use buffered
|
||||
* I/O because we will waste system entropy.
|
||||
*/
|
||||
bytes = (bytes == -1) ? 2048 : bytes; /* ok, is 2048 enough? */
|
||||
setvbuf(in, NULL, _IONBF, 0); /* don't do buffered reads */
|
||||
}
|
||||
for (;;)
|
||||
{
|
||||
n=(bytes < BUFSIZE)?(int)bytes:BUFSIZE;
|
||||
if (bytes > 0)
|
||||
n = (bytes < BUFSIZE)?(int)bytes:BUFSIZE;
|
||||
else
|
||||
n = BUFSIZE;
|
||||
i=fread(buf,1,n,in);
|
||||
if (i <= 0) break;
|
||||
/* even if n != i, use the full array */
|
||||
RAND_seed(buf,n);
|
||||
RAND_add(buf,n,i);
|
||||
ret+=i;
|
||||
bytes-=n;
|
||||
if (bytes <= 0) break;
|
||||
if (bytes > 0)
|
||||
{
|
||||
bytes-=n;
|
||||
if (bytes == 0) break;
|
||||
}
|
||||
}
|
||||
fclose(in);
|
||||
memset(buf,0,BUFSIZE);
|
||||
@ -112,29 +139,47 @@ err:
|
||||
int RAND_write_file(const char *file)
|
||||
{
|
||||
unsigned char buf[BUFSIZE];
|
||||
int i,ret=0;
|
||||
FILE *out;
|
||||
int i,ret=0,err=0;
|
||||
FILE *out = NULL;
|
||||
int n;
|
||||
struct stat sb;
|
||||
|
||||
/* Under VMS, fopen(file, "wb") will craete a new version of the
|
||||
same file. This is not good, so let's try updating an existing
|
||||
one, and create file only if it doesn't already exist. This
|
||||
should be completely harmless on system that have no file
|
||||
versions. -- Richard Levitte */
|
||||
out=fopen(file,"rb+");
|
||||
if (out == NULL && errno == ENOENT)
|
||||
{
|
||||
errno = 0;
|
||||
out=fopen(file,"wb");
|
||||
i=stat(file,&sb);
|
||||
if (i != -1) {
|
||||
if (sb.st_mode & (S_IFBLK | S_IFCHR)) {
|
||||
/*
|
||||
* this file is a device. we don't write back to it.
|
||||
* we "succeed" on the assumption this is some sort
|
||||
* of random device. Otherwise attempting to write to
|
||||
* and chmod the device causes problems.
|
||||
*/
|
||||
return(1);
|
||||
}
|
||||
if (out == NULL) goto err;
|
||||
}
|
||||
|
||||
#if defined(O_CREAT) && defined(O_EXCL) && !defined(WIN32)
|
||||
/* For some reason Win32 can't write to files created this way */
|
||||
|
||||
/* 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");
|
||||
#endif
|
||||
if (out == NULL)
|
||||
out = fopen(file,"wb");
|
||||
if (out == NULL) goto err;
|
||||
|
||||
#ifndef NO_CHMOD
|
||||
chmod(file,0600);
|
||||
#endif
|
||||
n=RAND_DATA;
|
||||
for (;;)
|
||||
{
|
||||
i=(n > BUFSIZE)?BUFSIZE:n;
|
||||
n-=BUFSIZE;
|
||||
RAND_bytes(buf,i);
|
||||
if (RAND_bytes(buf,i) <= 0)
|
||||
err=1;
|
||||
i=fwrite(buf,1,i,out);
|
||||
if (i <= 0)
|
||||
{
|
||||
@ -143,37 +188,78 @@ int RAND_write_file(const char *file)
|
||||
}
|
||||
ret+=i;
|
||||
if (n <= 0) break;
|
||||
}
|
||||
#ifdef VMS
|
||||
/* Try to delete older versions of the file, until there aren't
|
||||
any */
|
||||
{
|
||||
char *tmpf;
|
||||
|
||||
tmpf = Malloc(strlen(file) + 4); /* to add ";-1" and a nul */
|
||||
if (tmpf)
|
||||
{
|
||||
strcpy(tmpf, file);
|
||||
strcat(tmpf, ";-1");
|
||||
while(delete(tmpf) == 0)
|
||||
;
|
||||
rename(file,";1"); /* Make sure it's version 1, or we
|
||||
will reach the limit (32767) at
|
||||
some point... */
|
||||
}
|
||||
}
|
||||
#endif /* VMS */
|
||||
|
||||
fclose(out);
|
||||
memset(buf,0,BUFSIZE);
|
||||
err:
|
||||
return(ret);
|
||||
return(err ? -1 : ret);
|
||||
}
|
||||
|
||||
const char *RAND_file_name(char *buf, int size)
|
||||
{
|
||||
char *s;
|
||||
char *s = NULL;
|
||||
char *ret=NULL;
|
||||
struct stat sb;
|
||||
|
||||
s=getenv("RANDFILE");
|
||||
if (s != NULL)
|
||||
if (issetugid() == 0)
|
||||
s = getenv("RANDFILE");
|
||||
if (s != NULL && *s && strlen(s) + 1 < size)
|
||||
{
|
||||
strncpy(buf,s,size-1);
|
||||
buf[size-1]='\0';
|
||||
strlcpy(buf,s,size);
|
||||
ret=buf;
|
||||
}
|
||||
else
|
||||
{
|
||||
s=getenv("HOME");
|
||||
if (s == NULL) return(RFILE);
|
||||
if (((int)(strlen(s)+strlen(RFILE)+2)) > size)
|
||||
return(RFILE);
|
||||
strcpy(buf,s);
|
||||
if (issetugid() == 0)
|
||||
s=getenv("HOME");
|
||||
if (s && *s && strlen(s)+strlen(RFILE)+2 < size)
|
||||
{
|
||||
strlcpy(buf,s,size);
|
||||
#ifndef VMS
|
||||
strcat(buf,"/");
|
||||
strlcat(buf,"/",size);
|
||||
#endif
|
||||
strcat(buf,RFILE);
|
||||
ret=buf;
|
||||
strlcat(buf,RFILE,size);
|
||||
ret=buf;
|
||||
}
|
||||
}
|
||||
|
||||
#ifdef DEVRANDOM
|
||||
/* given that all random loads just fail if the file can't be
|
||||
* seen on a stat, we stat the file we're returning, if it
|
||||
* fails, use DEVRANDOM instead. the allows the user to
|
||||
* use their own source for good random data, but defaults
|
||||
* to something hopefully decent if that isn't available.
|
||||
*/
|
||||
|
||||
if (ret == NULL)
|
||||
ret = DEVRANDOM;
|
||||
|
||||
if (stat(ret,&sb) == -1)
|
||||
ret = DEVRANDOM;
|
||||
#else
|
||||
/* old behavior */
|
||||
if (ret == NULL)
|
||||
ret = RFILE;
|
||||
#endif
|
||||
return(ret);
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user