Replace FIPS PRNG with AES version.

This commit is contained in:
Dr. Stephen Henson 2007-02-21 16:57:35 +00:00
parent 28def5dc99
commit 7e92432b39
14 changed files with 843 additions and 569 deletions

View file

@ -4,6 +4,11 @@
Changes between 0.9.7l and 0.9.7m-fips2 [xx XXX xxxx]
*) Replace FIPS PRNG with AES based version based on ANSI X9.31 A.2.4 .
This supports larger keys (up to 256 bits) and large seeding and DT
vectors (128 bits each). Update tests for modified PRNG.
[Steve Henson]
*) FIPS portability patches.
[Brad House <brad@mainstreetsoftworks.com>]

View file

@ -61,9 +61,6 @@
#include <openssl/evp.h>
#include <openssl/objects.h>
#include <openssl/x509.h>
#ifdef OPENSSL_FIPS
#include <openssl/fips.h>
#endif
int EVP_add_cipher(const EVP_CIPHER *c)
{

View file

@ -1,4 +1,4 @@
/* crypto/fips_err.c */
/* crypto/fips_err.h */
/* ====================================================================
* Copyright (c) 1999-2006 The OpenSSL Project. All rights reserved.
*

View file

@ -125,13 +125,20 @@ void ERR_load_RAND_strings(void);
/* Error codes for the RAND functions. */
/* Function codes. */
#define RAND_F_FIPS_RAND 103
#define RAND_F_FIPS_RAND_BYTES 102
#define RAND_F_FIPS_SET_DT 104
#define RAND_F_FIPS_SET_TEST_MODE 105
#define RAND_F_RAND_GET_RAND_METHOD 101
#define RAND_F_SSLEAY_RAND_BYTES 100
/* Reason codes. */
#define RAND_R_NON_FIPS_METHOD 101
#define RAND_R_NOT_IN_TEST_MODE 106
#define RAND_R_NO_KEY_SET 107
#define RAND_R_PRNG_ASKING_FOR_TOO_MUCH 105
#define RAND_R_PRNG_ERROR 108
#define RAND_R_PRNG_KEYED 109
#define RAND_R_PRNG_NOT_REKEYED 103
#define RAND_R_PRNG_NOT_RESEEDED 104
#define RAND_R_PRNG_NOT_SEEDED 100

View file

@ -70,7 +70,10 @@
static ERR_STRING_DATA RAND_str_functs[]=
{
{ERR_FUNC(RAND_F_FIPS_RAND), "FIPS_RAND"},
{ERR_FUNC(RAND_F_FIPS_RAND_BYTES), "FIPS_RAND_BYTES"},
{ERR_FUNC(RAND_F_FIPS_SET_DT), "FIPS_SET_DT"},
{ERR_FUNC(RAND_F_FIPS_SET_TEST_MODE), "FIPS_SET_TEST_MODE"},
{ERR_FUNC(RAND_F_RAND_GET_RAND_METHOD), "RAND_get_rand_method"},
{ERR_FUNC(RAND_F_SSLEAY_RAND_BYTES), "SSLEAY_RAND_BYTES"},
{0,NULL}
@ -79,7 +82,11 @@ static ERR_STRING_DATA RAND_str_functs[]=
static ERR_STRING_DATA RAND_str_reasons[]=
{
{ERR_REASON(RAND_R_NON_FIPS_METHOD) ,"non fips method"},
{ERR_REASON(RAND_R_NOT_IN_TEST_MODE) ,"not in test mode"},
{ERR_REASON(RAND_R_NO_KEY_SET) ,"no key set"},
{ERR_REASON(RAND_R_PRNG_ASKING_FOR_TOO_MUCH),"prng asking for too much"},
{ERR_REASON(RAND_R_PRNG_ERROR) ,"prng error"},
{ERR_REASON(RAND_R_PRNG_KEYED) ,"prng keyed"},
{ERR_REASON(RAND_R_PRNG_NOT_REKEYED) ,"prng not rekeyed"},
{ERR_REASON(RAND_R_PRNG_NOT_RESEEDED) ,"prng not reseeded"},
{ERR_REASON(RAND_R_PRNG_NOT_SEEDED) ,"PRNG not seeded"},

View file

@ -129,8 +129,7 @@ static unsigned char out_g[]={
static const unsigned char str1[]="12345678901234567890";
static const char rnd_seed[] = "string to make the random number generator think it has entropy";
static const unsigned char rnd_key1[]="12345678";
static const unsigned char rnd_key2[]="abcdefgh";
static const unsigned char rnd_key[]="ABCDEFGHIJKLMNOPQRSTUVWXYZ123456";
static BIO *bio_err=NULL;
@ -156,7 +155,7 @@ int main(int argc, char **argv)
CRYPTO_dbg_set_options(V_CRYPTO_MDEBUG_ALL);
CRYPTO_mem_ctrl(CRYPTO_MEM_CHECK_ON);
FIPS_set_prng_key(rnd_key1,rnd_key2);
FIPS_rand_set_key(rnd_key, 32);
RAND_seed(rnd_seed, sizeof rnd_seed);
BIO_printf(bio_err,"test generation of DSA parameters\n");

View file

@ -265,7 +265,7 @@ int FIPS_mode_set(int onoff)
}
/* automagically seed PRNG if not already seeded */
if(!FIPS_rand_seeded())
if(!FIPS_rand_status())
{
if(RAND_bytes(buf,sizeof buf) <= 0)
{
@ -273,8 +273,8 @@ int FIPS_mode_set(int onoff)
ret = 0;
goto end;
}
FIPS_set_prng_key(buf,buf+8);
FIPS_rand_seed(buf+16,8);
FIPS_rand_set_key(buf,32);
FIPS_rand_seed(buf+32,16);
}
/* now switch into FIPS mode */

View file

@ -92,7 +92,7 @@ void ERR_load_FIPS_strings(void);
#define FIPS_F_FIPS_CHECK_DSA 116
#define FIPS_F_FIPS_CHECK_DSO 120
#define FIPS_F_FIPS_CHECK_EXE 106
#define FIPS_F_FIPS_CHECK_FINGERPRINT 120
#define FIPS_F_FIPS_CHECK_FINGERPRINT 121
#define FIPS_F_FIPS_CHECK_RSA 115
#define FIPS_F_FIPS_DSA_CHECK 102
#define FIPS_F_FIPS_MODE_SET 105

View file

@ -1,5 +1,5 @@
/* ====================================================================
* Copyright (c) 2003 The OpenSSL Project. All rights reserved.
* Copyright (c) 2007 The OpenSSL Project. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
@ -48,7 +48,7 @@
*/
/*
* This is a FIPS approved PRNG, ANSI X9.31 A.2.4.
* This is a FIPS approved AES PRNG based on ANSI X9.31 A.2.4.
*/
#include "e_os.h"
@ -60,8 +60,8 @@
#define _XOPEN_SOURCE_EXTENDED 1
#endif
#include <openssl/des.h>
#include <openssl/rand.h>
#include <openssl/aes.h>
#include <openssl/err.h>
#include <openssl/fips_rand.h>
#ifndef OPENSSL_SYS_WIN32
@ -79,281 +79,288 @@
void *OPENSSL_stderr(void);
#ifdef OPENSSL_FIPS
#define AES_BLOCK_LENGTH 16
#define SEED_SIZE 8
static unsigned char seed[SEED_SIZE];
static FIPS_RAND_SIZE_T n_seed;
static FIPS_RAND_SIZE_T o_seed;
static DES_cblock key1;
static DES_cblock key2;
static DES_key_schedule ks1,ks2;
static int key_set;
static int key_init;
static int test_mode;
static unsigned char test_faketime[8];
/* AES FIPS PRNG implementation */
typedef struct
{
int seeded;
int keyed;
int test_mode;
int second;
int error;
unsigned long counter;
AES_KEY ks;
int vpos;
unsigned char V[AES_BLOCK_LENGTH];
unsigned char DT[AES_BLOCK_LENGTH];
unsigned char last[AES_BLOCK_LENGTH];
} FIPS_PRNG_CTX;
static FIPS_PRNG_CTX sctx;
void fips_rand_prng_reset(FIPS_PRNG_CTX *ctx)
{
ctx->seeded = 0;
ctx->keyed = 0;
ctx->test_mode = 0;
ctx->counter = 0;
ctx->second = 0;
ctx->error = 0;
ctx->vpos = 0;
OPENSSL_cleanse(ctx->V, AES_BLOCK_LENGTH);
OPENSSL_cleanse(&ctx->ks, sizeof(AES_KEY));
}
static int fips_set_prng_key(FIPS_PRNG_CTX *ctx,
const unsigned char *key, FIPS_RAND_SIZE_T keylen)
{
if (keylen != 16 && keylen != 24 && keylen != 32)
{
/* error: invalid key size */
return 0;
}
AES_set_encrypt_key(key, keylen << 3, &ctx->ks);
ctx->keyed = 1;
ctx->seeded = 0;
ctx->second = 0;
return 1;
}
static int fips_set_prng_seed(FIPS_PRNG_CTX *ctx,
const unsigned char *seed, FIPS_RAND_SIZE_T seedlen)
{
int i;
if (!ctx->keyed)
return 0;
/* In test mode seed is just supplied data */
if (ctx->test_mode)
{
if (seedlen != AES_BLOCK_LENGTH)
return 0;
memcpy(ctx->V, seed, AES_BLOCK_LENGTH);
ctx->seeded = 1;
return 1;
}
/* Outside test mode XOR supplied data with existing seed */
for (i = 0; i < seedlen; i++)
{
ctx->V[ctx->vpos++] ^= seed[i];
if (ctx->vpos == AES_BLOCK_LENGTH)
{
ctx->vpos = 0;
ctx->seeded = 1;
}
}
return 1;
}
int fips_set_test_mode(FIPS_PRNG_CTX *ctx)
{
if (ctx->keyed)
{
RANDerr(RAND_F_FIPS_SET_TEST_MODE,RAND_R_PRNG_KEYED);
return 0;
}
ctx->test_mode = 1;
return 1;
}
int FIPS_rand_test_mode(void)
{
return fips_set_test_mode(&sctx);
}
int FIPS_rand_set_dt(unsigned char *dt)
{
if (!sctx.test_mode)
{
RANDerr(RAND_F_FIPS_SET_DT,RAND_R_NOT_IN_TEST_MODE);
return 0;
}
memcpy(sctx.DT, dt, AES_BLOCK_LENGTH);
return 1;
}
static void fips_get_dt(FIPS_PRNG_CTX *ctx)
{
#ifdef OPENSSL_SYS_WIN32
FILETIME ft;
#else
struct timeval tv;
#endif
unsigned char *buf = ctx->DT;
unsigned long pid;
#ifdef OPENSSL_SYS_WIN32
GetSystemTimeAsFileTime(&ft);
buf[0] = (unsigned char) (ft.dwHighDateTime & 0xff);
buf[1] = (unsigned char) ((ft.dwHighDateTime >> 8) & 0xff);
buf[2] = (unsigned char) ((ft.dwHighDateTime >> 16) & 0xff);
buf[3] = (unsigned char) ((ft.dwHighDateTime >> 24) & 0xff);
buf[4] = (unsigned char) (ft.dwLowDateTime & 0xff);
buf[5] = (unsigned char) ((ft.dwLowDateTime >> 8) & 0xff);
buf[6] = (unsigned char) ((ft.dwLowDateTime >> 16) & 0xff);
buf[7] = (unsigned char) ((ft.dwLowDateTime >> 24) & 0xff);
#else
gettimeofday(&tv,NULL);
buf[0] = (unsigned char) (tv.tv_sec & 0xff);
buf[1] = (unsigned char) ((tv.tv_sec >> 8) & 0xff);
buf[2] = (unsigned char) ((tv.tv_sec >> 16) & 0xff);
buf[3] = (unsigned char) ((tv.tv_sec >> 24) & 0xff);
buf[4] = (unsigned char) (tv.tv_usec & 0xff);
buf[5] = (unsigned char) ((tv.tv_usec >> 8) & 0xff);
buf[6] = (unsigned char) ((tv.tv_usec >> 16) & 0xff);
buf[7] = (unsigned char) ((tv.tv_usec >> 24) & 0xff);
#endif
buf[8] = (unsigned char) (ctx->counter & 0xff);
buf[9] = (unsigned char) ((ctx->counter >> 8) & 0xff);
buf[10] = (unsigned char) ((ctx->counter >> 16) & 0xff);
buf[11] = (unsigned char) ((ctx->counter >> 24) & 0xff);
pid=(unsigned long)getpid();
#ifndef GETPID_IS_MEANINGLESS
static int seed_pid;
static int key_pid;
buf[12] = (unsigned char) (pid & 0xff);
buf[13] = (unsigned char) ((pid >> 8) & 0xff);
buf[14] = (unsigned char) ((pid >> 16) & 0xff);
buf[15] = (unsigned char) ((pid >> 24) & 0xff);
#endif
}
static void fips_rand_cleanup(void);
static void fips_rand_add(const void *buf, FIPS_RAND_SIZE_T num, double add_entropy);
static int fips_rand_bytes(unsigned char *buf, FIPS_RAND_SIZE_T num);
static int fips_rand_status(void);
static int fips_rand(FIPS_PRNG_CTX *ctx,
unsigned char *out, FIPS_RAND_SIZE_T outlen)
{
unsigned char R[AES_BLOCK_LENGTH], I[AES_BLOCK_LENGTH];
unsigned char tmp[AES_BLOCK_LENGTH];
int i;
if (ctx->error)
{
RANDerr(RAND_F_FIPS_RAND,RAND_R_PRNG_ERROR);
return 0;
}
if (!ctx->keyed)
{
RANDerr(RAND_F_FIPS_RAND,RAND_R_NO_KEY_SET);
return 0;
}
if (!ctx->seeded)
{
RANDerr(RAND_F_FIPS_RAND,RAND_R_PRNG_NOT_SEEDED);
return 0;
}
for (;;)
{
if (!ctx->test_mode)
fips_get_dt(ctx);
AES_encrypt(ctx->DT, I, &ctx->ks);
for (i = 0; i < AES_BLOCK_LENGTH; i++)
tmp[i] = I[i] ^ ctx->V[i];
AES_encrypt(tmp, R, &ctx->ks);
for (i = 0; i < AES_BLOCK_LENGTH; i++)
tmp[i] = R[i] ^ I[i];
AES_encrypt(tmp, ctx->V, &ctx->ks);
if (ctx->second)
{
if (!memcmp(R, ctx->last, AES_BLOCK_LENGTH))
{
RANDerr(RAND_F_FIPS_RAND,RAND_R_PRNG_STUCK);
ctx->error = 1;
return 0;
}
}
memcpy(ctx->last, R, AES_BLOCK_LENGTH);
if (!ctx->second)
{
ctx->second = 1;
if (!ctx->test_mode)
continue;
}
if (outlen <= AES_BLOCK_LENGTH)
{
memcpy(out, R, outlen);
break;
}
memcpy(out, R, AES_BLOCK_LENGTH);
out += AES_BLOCK_LENGTH;
outlen -= AES_BLOCK_LENGTH;
}
return 1;
}
int FIPS_rand_set_key(const unsigned char *key, FIPS_RAND_SIZE_T keylen)
{
int ret;
CRYPTO_w_lock(CRYPTO_LOCK_RAND);
ret = fips_set_prng_key(&sctx, key, keylen);
CRYPTO_w_unlock(CRYPTO_LOCK_RAND);
return ret;
}
int FIPS_rand_seed(const void *seed, FIPS_RAND_SIZE_T seedlen)
{
int ret;
CRYPTO_w_lock(CRYPTO_LOCK_RAND);
ret = fips_set_prng_seed(&sctx, seed, seedlen);
CRYPTO_w_unlock(CRYPTO_LOCK_RAND);
return ret;
}
int FIPS_rand_bytes(unsigned char *out, FIPS_RAND_SIZE_T count)
{
int ret;
CRYPTO_w_lock(CRYPTO_LOCK_RAND);
ret = fips_rand(&sctx, out, count);
CRYPTO_w_unlock(CRYPTO_LOCK_RAND);
return ret;
}
int FIPS_rand_status(void)
{
int ret;
CRYPTO_r_lock(CRYPTO_LOCK_RAND);
ret = sctx.seeded;
CRYPTO_r_unlock(CRYPTO_LOCK_RAND);
return ret;
}
void FIPS_rand_reset(void)
{
CRYPTO_w_lock(CRYPTO_LOCK_RAND);
fips_rand_prng_reset(&sctx);
CRYPTO_w_unlock(CRYPTO_LOCK_RAND);
}
static void fips_do_rand_seed(const void *seed, FIPS_RAND_SIZE_T seedlen)
{
FIPS_rand_seed(seed, seedlen);
}
static void fips_do_rand_add(const void *seed, FIPS_RAND_SIZE_T seedlen,
double add_entropy)
{
FIPS_rand_seed(seed, seedlen);
}
static const RAND_METHOD rand_fips_meth=
{
FIPS_rand_seed,
fips_rand_bytes,
fips_rand_cleanup,
fips_rand_add,
fips_rand_bytes,
fips_rand_status
fips_do_rand_seed,
FIPS_rand_bytes,
FIPS_rand_reset,
fips_do_rand_add,
FIPS_rand_bytes,
FIPS_rand_status
};
static int second;
const RAND_METHOD *FIPS_rand_method(void)
{
return &rand_fips_meth;
}
void FIPS_set_prng_key(const unsigned char k1[8],const unsigned char k2[8])
{
memcpy(&key1,k1,sizeof key1);
memcpy(&key2,k2,sizeof key2);
key_set=1;
#ifndef GETPID_IS_MEANINGLESS
key_pid=getpid();
#endif
second=0;
}
void FIPS_test_mode(int test,const unsigned char faketime[8])
{
test_mode=test;
if(!test_mode)
return;
memcpy(test_faketime,faketime,sizeof test_faketime);
}
/* NB: this returns true if _partially_ seeded */
int FIPS_rand_seeded()
{ return key_set || n_seed; }
static void fips_gettime(unsigned char buf[8])
{
#ifdef OPENSSL_SYS_WIN32
FILETIME ft;
#else
struct timeval tv;
#endif
if(test_mode)
{
/* fprintf(OPENSSL_stderr(),"WARNING!!! PRNG IN TEST MODE!!!\n"); */
memcpy(buf,test_faketime,sizeof test_faketime);
return;
}
#ifdef OPENSSL_SYS_WIN32
GetSystemTimeAsFileTime(&ft);
buf[0] = (unsigned char) (ft.dwHighDateTime & 0xff);
buf[1] = (unsigned char) ((ft.dwHighDateTime >> 8) & 0xff);
buf[2] = (unsigned char) ((ft.dwHighDateTime >> 16) & 0xff);
buf[3] = (unsigned char) ((ft.dwHighDateTime >> 24) & 0xff);
buf[4] = (unsigned char) (ft.dwLowDateTime & 0xff);
buf[5] = (unsigned char) ((ft.dwLowDateTime >> 8) & 0xff);
buf[6] = (unsigned char) ((ft.dwLowDateTime >> 16) & 0xff);
buf[7] = (unsigned char) ((ft.dwLowDateTime >> 24) & 0xff);
#else
gettimeofday(&tv,NULL);
buf[0] = (unsigned char) (tv.tv_sec & 0xff);
buf[1] = (unsigned char) ((tv.tv_sec >> 8) & 0xff);
buf[2] = (unsigned char) ((tv.tv_sec >> 16) & 0xff);
buf[3] = (unsigned char) ((tv.tv_sec >> 24) & 0xff);
buf[4] = (unsigned char) (tv.tv_usec & 0xff);
buf[5] = (unsigned char) ((tv.tv_usec >> 8) & 0xff);
buf[6] = (unsigned char) ((tv.tv_usec >> 16) & 0xff);
buf[7] = (unsigned char) ((tv.tv_usec >> 24) & 0xff);
#endif
#if 0 /* This eminently sensible strategy is not acceptable to NIST. Sigh. */
#ifndef GETPID_IS_MEANINGLESS
/* we mix in the PID to ensure that after a fork the children don't give
* the same results as each other
*/
pid=getpid();
/* make sure we shift the pid to the MSB */
if((pid&0xffff0000) == 0)
pid<<=16;
*(long *)&buf[0]^=pid;
#endif
#endif
}
static void fips_rand_encrypt(unsigned char *out,const unsigned char *in)
{
DES_ecb2_encrypt(in,out,&ks1,&ks2,1);
}
static void fips_rand_cleanup(void)
{
OPENSSL_cleanse(seed,sizeof seed);
n_seed=0;
o_seed=0;
key_init=0;
}
void FIPS_rand_seed(const void *buf_, FIPS_RAND_SIZE_T num)
{
const char *buf=buf_;
FIPS_RAND_SIZE_T n;
/* If the key hasn't been set, we can't seed! */
if(!key_set)
return;
CRYPTO_w_lock(CRYPTO_LOCK_RAND);
if(!key_init)
{
key_init=1;
DES_set_key(&key1,&ks1);
DES_set_key(&key2,&ks2);
}
/*
* This algorithm only uses 64 bits of seed, so ensure that we use
* the most recent 64 bits.
*/
for(n=0 ; n < num ; )
{
FIPS_RAND_SIZE_T t=num-n;
if(o_seed+t > sizeof seed)
t=sizeof seed-o_seed;
memcpy(seed+o_seed,buf+n,t);
n+=t;
o_seed+=t;
if(o_seed == sizeof seed)
o_seed=0;
if(n_seed < sizeof seed)
n_seed+=t;
}
#ifndef GETPID_IS_MEANINGLESS
seed_pid=getpid();
#endif
CRYPTO_w_unlock(CRYPTO_LOCK_RAND);
}
static void fips_rand_add(const void *buf, FIPS_RAND_SIZE_T num, double add_entropy)
{
FIPS_rand_seed(buf,num);
}
static int fips_rand_bytes(unsigned char *buf,FIPS_RAND_SIZE_T num)
{
FIPS_RAND_SIZE_T n;
unsigned char timeseed[8];
unsigned char intermediate[SEED_SIZE];
unsigned char output[SEED_SIZE];
static unsigned char previous[SEED_SIZE];
#ifndef GETPID_IS_MEANINGLESS
int pid;
#endif
if(n_seed < sizeof seed)
{
RANDerr(RAND_F_FIPS_RAND_BYTES,RAND_R_PRNG_NOT_SEEDED);
return 0;
}
#ifdef FIPS_RAND_MAX_SIZE_T
if (num > FIPS_RAND_MAX_SIZE_T)
{
#ifdef RAND_R_PRNG_ASKING_FOR_TOO_MUCH
RANDerr(RAND_F_FIPS_RAND_BYTES,RAND_R_PRNG_ASKING_FOR_TOO_MUCH);
return 0;
#else
return -1; /* signal "not supported" condition */
#endif
}
#endif
#ifndef GETPID_IS_MEANINGLESS
pid=getpid();
if(pid != seed_pid)
{
RANDerr(RAND_F_FIPS_RAND_BYTES,RAND_R_PRNG_NOT_RESEEDED);
return 0;
}
if(pid != key_pid)
{
RANDerr(RAND_F_FIPS_RAND_BYTES,RAND_R_PRNG_NOT_REKEYED);
return 0;
}
#endif
CRYPTO_w_lock(CRYPTO_LOCK_RAND);
for(n=0 ; n < num ; )
{
unsigned char t[SEED_SIZE];
FIPS_RAND_SIZE_T l;
/* ANS X9.31 A.2.4: I = ede*K(DT)
timeseed == DT
intermediate == I
*/
fips_gettime(timeseed);
fips_rand_encrypt(intermediate,timeseed);
/* ANS X9.31 A.2.4: R = ede*K(I^V)
intermediate == I
seed == V
output == R
*/
for(l=0 ; l < sizeof t ; ++l)
t[l]=intermediate[l]^seed[l];
fips_rand_encrypt(output,t);
/* ANS X9.31 A.2.4: V = ede*K(R^I)
output == R
intermediate == I
seed == V
*/
for(l=0 ; l < sizeof t ; ++l)
t[l]=output[l]^intermediate[l];
fips_rand_encrypt(seed,t);
if(second && !memcmp(output,previous,sizeof previous))
{
RANDerr(RAND_F_FIPS_RAND_BYTES,RAND_R_PRNG_STUCK);
CRYPTO_w_unlock(CRYPTO_LOCK_RAND);
return 0;
}
memcpy(previous,output,sizeof previous);
second=1;
/* Successive values of R may be concatenated to produce a
pseudo random number of the desired length */
l=SEED_SIZE < num-n ? SEED_SIZE : num-n;
memcpy(buf+n,output,l);
n+=l;
}
CRYPTO_w_unlock(CRYPTO_LOCK_RAND);
return 1;
}
static int fips_rand_status(void)
{
return n_seed == sizeof seed;
}
#endif /* OPENSSL_FIPS */

View file

@ -58,11 +58,15 @@
extern "C" {
#endif
void FIPS_set_prng_key(const unsigned char k1[8],const unsigned char k2[8]);
void FIPS_test_mode(int test,const unsigned char faketime[8]);
void FIPS_rand_seed(const void *buf, FIPS_RAND_SIZE_T num);
/* NB: this returns true if _partially_ seeded */
int FIPS_rand_seeded(void);
int FIPS_rand_set_key(const unsigned char *key, FIPS_RAND_SIZE_T keylen);
int FIPS_rand_seed(const void *buf, FIPS_RAND_SIZE_T num);
int FIPS_rand_bytes(unsigned char *out, FIPS_RAND_SIZE_T outlen);
int FIPS_rand_test_mode(void);
void FIPS_rand_reset(void);
int FIPS_rand_set_dt(unsigned char *dt);
int FIPS_rand_status(void);
const RAND_METHOD *FIPS_rand_method(void);

View file

@ -54,67 +54,318 @@
#include <openssl/fips_rand.h>
#ifdef OPENSSL_FIPS
static struct
{
unsigned char key1[8];
unsigned char key2[8];
unsigned char seed[8];
unsigned char dt[8];
} init_iv[] =
{
{
{ 0x75, 0xc7, 0x1a, 0xe5, 0xa1, 0x1a, 0x23, 0x2c },
{ 0x40, 0x25, 0x6d, 0xcd, 0x94, 0xf7, 0x67, 0xb0 },
{ 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 },
{ 0xc8, 0x9a, 0x1d, 0x88, 0x8e, 0xd1, 0x2f, 0x3c },
},
{
{ 0x75, 0xc7, 0x1a, 0xe5, 0xa1, 0x1a, 0x23, 0x2c },
{ 0x40, 0x25, 0x6d, 0xcd, 0x94, 0xf7, 0x67, 0xb0 },
{ 0xf8, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 },
{ 0xc8, 0x9a, 0x1d, 0x88, 0x8e, 0xd1, 0x2f, 0x40 },
},
{
{ 0x75, 0xc7, 0x1a, 0xe5, 0xa1, 0x1a, 0x23, 0x2c },
{ 0x40, 0x25, 0x6d, 0xcd, 0x94, 0xf7, 0x67, 0xb0 },
{ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff },
{ 0xc8, 0x9a, 0x1d, 0x88, 0x8e, 0xd1, 0x2f, 0x7b },
},
};
static const unsigned char expected_ret[][8]=
{
{ 0x94, 0x4d, 0xc7, 0x21, 0x0d, 0x6d, 0x7f, 0xd7 },
{ 0x02, 0x43, 0x3c, 0x94, 0x17, 0xa3, 0x32, 0x6f },
{ 0xe7, 0xe2, 0xb2, 0x96, 0x4f, 0x36, 0xed, 0x41 },
};
typedef struct
{
unsigned char DT[16];
unsigned char V[16];
unsigned char R[16];
} AES_PRNG_TV;
/* The following test vectors are taken directly from the RGNVS spec */
static unsigned char aes_128_key[16] =
{0xf3,0xb1,0x66,0x6d,0x13,0x60,0x72,0x42,
0xed,0x06,0x1c,0xab,0xb8,0xd4,0x62,0x02};
static AES_PRNG_TV aes_128_tv[] = {
{
/* DT */
{0xe6,0xb3,0xbe,0x78,0x2a,0x23,0xfa,0x62,
0xd7,0x1d,0x4a,0xfb,0xb0,0xe9,0x22,0xf9},
/* V */
{0x80,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00},
/* R */
{0x59,0x53,0x1e,0xd1,0x3b,0xb0,0xc0,0x55,
0x84,0x79,0x66,0x85,0xc1,0x2f,0x76,0x41}
},
{
/* DT */
{0xe6,0xb3,0xbe,0x78,0x2a,0x23,0xfa,0x62,
0xd7,0x1d,0x4a,0xfb,0xb0,0xe9,0x22,0xfa},
/* V */
{0xc0,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00},
/* R */
{0x7c,0x22,0x2c,0xf4,0xca,0x8f,0xa2,0x4c,
0x1c,0x9c,0xb6,0x41,0xa9,0xf3,0x22,0x0d}
},
{
/* DT */
{0xe6,0xb3,0xbe,0x78,0x2a,0x23,0xfa,0x62,
0xd7,0x1d,0x4a,0xfb,0xb0,0xe9,0x22,0xfb},
/* V */
{0xe0,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00},
/* R */
{0x8a,0xaa,0x00,0x39,0x66,0x67,0x5b,0xe5,
0x29,0x14,0x28,0x81,0xa9,0x4d,0x4e,0xc7}
},
{
/* DT */
{0xe6,0xb3,0xbe,0x78,0x2a,0x23,0xfa,0x62,
0xd7,0x1d,0x4a,0xfb,0xb0,0xe9,0x22,0xfc},
/* V */
{0xf0,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00},
/* R */
{0x88,0xdd,0xa4,0x56,0x30,0x24,0x23,0xe5,
0xf6,0x9d,0xa5,0x7e,0x7b,0x95,0xc7,0x3a}
},
{
/* DT */
{0xe6,0xb3,0xbe,0x78,0x2a,0x23,0xfa,0x62,
0xd7,0x1d,0x4a,0xfb,0xb0,0xe9,0x22,0xfd},
/* V */
{0xf8,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00},
/* R */
{0x05,0x25,0x92,0x46,0x61,0x79,0xd2,0xcb,
0x78,0xc4,0x0b,0x14,0x0a,0x5a,0x9a,0xc8}
},
{
/* DT */
{0xe6,0xb3,0xbe,0x78,0x2a,0x23,0xfa,0x62,
0xd7,0x1d,0x4a,0xfb,0xb0,0xe9,0x23,0x77},
/* V */
{0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xfe},
/* R */
{0x0d,0xd5,0xa0,0x36,0x7a,0x59,0x26,0xbc,
0x48,0xd9,0x38,0xbf,0xf0,0x85,0x8f,0xea}
},
{
/* DT */
{0xe6,0xb3,0xbe,0x78,0x2a,0x23,0xfa,0x62,
0xd7,0x1d,0x4a,0xfb,0xb0,0xe9,0x23,0x78},
/* V */
{0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff},
/* R */
{0xae,0x53,0x87,0xee,0x8c,0xd9,0x12,0xf5,
0x73,0x53,0xae,0x03,0xf9,0xd5,0x13,0x33}
},
};
static unsigned char aes_192_key[24] =
{0x15,0xd8,0x78,0x0d,0x62,0xd3,0x25,0x6e,
0x44,0x64,0x10,0x13,0x60,0x2b,0xa9,0xbc,
0x4a,0xfb,0xca,0xeb,0x4c,0x8b,0x99,0x3b};
static AES_PRNG_TV aes_192_tv[] = {
{
/* DT */
{0x3f,0xd8,0xff,0xe8,0x80,0x69,0x8b,0xc1,
0xbf,0x99,0x7d,0xa4,0x24,0x78,0xf3,0x4b},
/* V */
{0x80,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00},
/* R */
{0x17,0x07,0xd5,0x28,0x19,0x79,0x1e,0xef,
0xa5,0x0c,0xbf,0x25,0xe5,0x56,0xb4,0x93}
},
{
/* DT */
{0x3f,0xd8,0xff,0xe8,0x80,0x69,0x8b,0xc1,
0xbf,0x99,0x7d,0xa4,0x24,0x78,0xf3,0x4c},
/* V */
{0xc0,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00},
/* R */
{0x92,0x8d,0xbe,0x07,0xdd,0xc7,0x58,0xc0,
0x6f,0x35,0x41,0x9b,0x17,0xc9,0xbd,0x9b}
},
{
/* DT */
{0x3f,0xd8,0xff,0xe8,0x80,0x69,0x8b,0xc1,
0xbf,0x99,0x7d,0xa4,0x24,0x78,0xf3,0x4d},
/* V */
{0xe0,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00},
/* R */
{0xd5,0xde,0xf4,0x50,0xf3,0xb7,0x10,0x4e,
0xb8,0xc6,0xf8,0xcf,0xe2,0xb1,0xca,0xa2}
},
{
/* DT */
{0x3f,0xd8,0xff,0xe8,0x80,0x69,0x8b,0xc1,
0xbf,0x99,0x7d,0xa4,0x24,0x78,0xf3,0x4e},
/* V */
{0xf0,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00},
/* R */
{0xce,0x29,0x08,0x43,0xfc,0x34,0x41,0xe7,
0x47,0x8f,0xb3,0x66,0x2b,0x46,0xb1,0xbb}
},
{
/* DT */
{0x3f,0xd8,0xff,0xe8,0x80,0x69,0x8b,0xc1,
0xbf,0x99,0x7d,0xa4,0x24,0x78,0xf3,0x4f},
/* V */
{0xf8,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00},
/* R */
{0xb3,0x26,0x0f,0xf5,0xd6,0xca,0xa8,0xbf,
0x89,0xb8,0x5e,0x2f,0x22,0x56,0x92,0x2f}
},
{
/* DT */
{0x3f,0xd8,0xff,0xe8,0x80,0x69,0x8b,0xc1,
0xbf,0x99,0x7d,0xa4,0x24,0x78,0xf3,0xc9},
/* V */
{0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xfe},
/* R */
{0x05,0xeb,0x18,0x52,0x34,0x43,0x00,0x43,
0x6e,0x5a,0xa5,0xfe,0x7b,0x32,0xc4,0x2d}
},
{
/* DT */
{0x3f,0xd8,0xff,0xe8,0x80,0x69,0x8b,0xc1,
0xbf,0x99,0x7d,0xa4,0x24,0x78,0xf3,0xca},
/* V */
{0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff},
/* R */
{0x15,0x3c,0xe8,0xd1,0x04,0xc7,0xad,0x50,
0x0b,0xf0,0x07,0x16,0xe7,0x56,0x7a,0xea}
},
};
static unsigned char aes_256_key[32] =
{0x6d,0x14,0x06,0x6c,0xb6,0xd8,0x21,0x2d,
0x82,0x8d,0xfa,0xf2,0x7a,0x03,0xb7,0x9f,
0x0c,0xc7,0x3e,0xcd,0x76,0xeb,0xee,0xb5,
0x21,0x05,0x8c,0x4f,0x31,0x7a,0x80,0xbb};
static AES_PRNG_TV aes_256_tv[] = {
{
/* DT */
{0xda,0x3a,0x41,0xec,0x1d,0xa3,0xb0,0xd5,
0xf2,0xa9,0x4e,0x34,0x74,0x8e,0x9e,0x88},
/* V */
{0x80,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00},
/* R */
{0x35,0xc7,0xef,0xa7,0x78,0x4d,0x29,0xbc,
0x82,0x79,0x99,0xfb,0xd0,0xb3,0x3b,0x72}
},
{
/* DT */
{0xda,0x3a,0x41,0xec,0x1d,0xa3,0xb0,0xd5,
0xf2,0xa9,0x4e,0x34,0x74,0x8e,0x9e,0x89},
/* V */
{0xc0,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00},
/* R */
{0x6c,0xf4,0x42,0x5d,0xc7,0x04,0x1a,0x41,
0x28,0x2a,0x78,0xa9,0xb0,0x12,0xc4,0x95}
},
{
/* DT */
{0xda,0x3a,0x41,0xec,0x1d,0xa3,0xb0,0xd5,
0xf2,0xa9,0x4e,0x34,0x74,0x8e,0x9e,0x8a},
/* V */
{0xe0,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00},
/* R */
{0x16,0x90,0xa4,0xff,0x7b,0x7e,0xb9,0x30,
0xdb,0x67,0x4b,0xac,0x2d,0xe1,0xd1,0x75}
},
{
/* DT */
{0xda,0x3a,0x41,0xec,0x1d,0xa3,0xb0,0xd5,
0xf2,0xa9,0x4e,0x34,0x74,0x8e,0x9e,0x8b},
/* V */
{0xf0,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00},
/* R */
{0x14,0x6f,0xf5,0x95,0xa1,0x46,0x65,0x30,
0xbc,0x57,0xe2,0x4a,0xf7,0x45,0x62,0x05}
},
{
/* DT */
{0xda,0x3a,0x41,0xec,0x1d,0xa3,0xb0,0xd5,
0xf2,0xa9,0x4e,0x34,0x74,0x8e,0x9e,0x8c},
/* V */
{0xf8,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00},
/* R */
{0x96,0xe2,0xb4,0x1e,0x66,0x5e,0x0f,0xa4,
0xc5,0xcd,0xa2,0x07,0xcc,0xb7,0x94,0x40}
},
{
/* DT */
{0xda,0x3a,0x41,0xec,0x1d,0xa3,0xb0,0xd5,
0xf2,0xa9,0x4e,0x34,0x74,0x8e,0x9f,0x06},
/* V */
{0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xfe},
/* R */
{0x61,0xce,0x1d,0x6a,0x48,0x75,0x97,0x28,
0x4b,0x41,0xde,0x18,0x44,0x4f,0x56,0xec}
},
{
/* DT */
{0xda,0x3a,0x41,0xec,0x1d,0xa3,0xb0,0xd5,
0xf2,0xa9,0x4e,0x34,0x74,0x8e,0x9f,0x07},
/* V */
{0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff},
/* R */
{0x52,0x89,0x59,0x79,0x2d,0xaa,0x28,0xb3,
0xb0,0x8a,0x3e,0x70,0xfa,0x71,0x59,0x84}
},
};
void FIPS_corrupt_rng()
{
init_iv[0].dt[0]++;
aes_192_tv[0].V[0]++;
}
#define fips_rand_test(key, tv) \
do_rand_test(key, sizeof key, tv, sizeof(tv)/sizeof(AES_PRNG_TV))
static int do_rand_test(unsigned char *key, int keylen,
AES_PRNG_TV *tv, int ntv)
{
unsigned char R[16];
int i;
if (!FIPS_rand_set_key(key, keylen))
return 0;
for (i = 0; i < ntv; i++)
{
FIPS_rand_seed(tv[i].V, 16);
FIPS_rand_set_dt(tv[i].DT);
FIPS_rand_bytes(R, 16);
if (memcmp(R, tv[i].R, 16))
return 0;
}
return 1;
}
int FIPS_selftest_rng()
{
int n;
for(n=0 ; n < 3 ; ++n)
{
unsigned char actual_ret[8];
FIPS_rand_method()->cleanup();
FIPS_set_prng_key(init_iv[n].key1,init_iv[n].key2);
FIPS_rand_seed(init_iv[n].seed,8);
FIPS_test_mode(1,init_iv[n].dt);
if ((FIPS_rand_method()->bytes(actual_ret, 8) <=0) || (memcmp(actual_ret,expected_ret[n],sizeof actual_ret)))
{
FIPS_test_mode(0,NULL);
FIPSerr(FIPS_F_FIPS_SELFTEST_RNG,FIPS_R_SELFTEST_FAILED);
return 0;
}
FIPS_rand_reset();
if (!FIPS_rand_test_mode())
{
FIPSerr(FIPS_F_FIPS_SELFTEST_RNG,FIPS_R_SELFTEST_FAILED);
return 0;
}
if (!fips_rand_test(aes_128_key,aes_128_tv)
|| !fips_rand_test(aes_192_key, aes_192_tv)
|| !fips_rand_test(aes_256_key, aes_256_tv))
{
FIPSerr(FIPS_F_FIPS_SELFTEST_RNG,FIPS_R_SELFTEST_FAILED);
return 0;
}
FIPS_rand_reset();
return 1;
}
FIPS_test_mode(0,NULL);
return 1;
}
#endif

View file

@ -105,6 +105,7 @@
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <openssl/rand.h>
#include <openssl/fips_rand.h>
#include <openssl/err.h>
@ -120,42 +121,63 @@ int main(int argc, char *argv[])
#else
/* some FIPS 140-1 random number test */
/* some simple tests */
static DES_cblock prng_key1={0x21,0x58,0x47,0xb7,0xc2,0x97,0x5a,0x8e};
static DES_cblock prng_key2={0x61,0x23,0x05,0x96,0x18,0x91,0x86,0xac};
static unsigned char prng_seed[8]={0x6b,0xa3,0x4f,0x07,0xe4,0x2a,0xb0,0xc};
typedef struct
{
DES_cblock keys[2];
const unsigned char time[8];
const unsigned char seed[8];
const unsigned char block1[8];
const unsigned char block100[8];
} PRNGtest;
{
unsigned char DT[16];
unsigned char V[16];
unsigned char R[16];
} AES_PRNG_MCT;
/* FIXME: these test vectors are made up! */
static PRNGtest t1=
{
{ { 0x00,0x01,0x02,0x03,0x04,0x05,0x06,0x07 },
{ 0x08,0x09,0x0a,0x0b,0x0c,0x0d,0x0e,0x0f },
},
{ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 },
{ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 },
{ 0x33,0xc3,0xdf,0xfe,0x60,0x60,0x49,0x9e },
{ 0xcd,0x2b,0x41,0xaf,0x80,0x51,0x37,0xd8 }
};
static PRNGtest t2=
{
{ { 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff },
{ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff } },
{ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff },
{ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff },
{ 0x65,0xf1,0xa4,0x07,0x42,0x38,0xd5,0x25 },
{ 0xbb,0x75,0x84,0x20,0x7a,0x44,0xf0,0xa0 }
};
static unsigned char aes_128_mct_key[16] =
{0x9f,0x5b,0x51,0x20,0x0b,0xf3,0x34,0xb5,
0xd8,0x2b,0xe8,0xc3,0x72,0x55,0xc8,0x48};
static AES_PRNG_MCT aes_128_mct_tv = {
/* DT */
{0x63,0x76,0xbb,0xe5,0x29,0x02,0xba,0x3b,
0x67,0xc9,0x25,0xfa,0x70,0x1f,0x11,0xac},
/* V */
{0x57,0x2c,0x8e,0x76,0x87,0x26,0x47,0x97,
0x7e,0x74,0xfb,0xdd,0xc4,0x95,0x01,0xd1},
/* R */
{0x48,0xe9,0xbd,0x0d,0x06,0xee,0x18,0xfb,
0xe4,0x57,0x90,0xd5,0xc3,0xfc,0x9b,0x73}
};
static unsigned char aes_192_mct_key[24] =
{0xb7,0x6c,0x34,0xd1,0x09,0x67,0xab,0x73,
0x4d,0x5a,0xd5,0x34,0x98,0x16,0x0b,0x91,
0xbc,0x35,0x51,0x16,0x6b,0xae,0x93,0x8a};
static AES_PRNG_MCT aes_192_mct_tv = {
/* DT */
{0x84,0xce,0x22,0x7d,0x91,0x5a,0xa3,0xc9,
0x84,0x3c,0x0a,0xb3,0xa9,0x63,0x15,0x52},
/* V */
{0xb6,0xaf,0xe6,0x8f,0x99,0x9e,0x90,0x64,
0xdd,0xc7,0x7a,0xc1,0xbb,0x90,0x3a,0x6d},
/* R */
{0xfc,0x85,0x60,0x9a,0x29,0x6f,0xef,0x21,
0xdd,0x86,0x20,0x32,0x8a,0x29,0x6f,0x47}
};
static unsigned char aes_256_mct_key[32] =
{0x9b,0x05,0xc8,0x68,0xff,0x47,0xf8,0x3a,
0xa6,0x3a,0xa8,0xcb,0x4e,0x71,0xb2,0xe0,
0xb8,0x7e,0xf1,0x37,0xb6,0xb4,0xf6,0x6d,
0x86,0x32,0xfc,0x1f,0x5e,0x1d,0x1e,0x50};
static AES_PRNG_MCT aes_256_mct_tv = {
/* DT */
{0x31,0x6e,0x35,0x9a,0xb1,0x44,0xf0,0xee,
0x62,0x6d,0x04,0x46,0xe0,0xa3,0x92,0x4c},
/* V */
{0x4f,0xcd,0xc1,0x87,0x82,0x1f,0x4d,0xa1,
0x3e,0x0e,0x56,0x44,0x59,0xe8,0x83,0xca},
/* R */
{0xc8,0x87,0xc2,0x61,0x5b,0xd0,0xb9,0xe1,
0xe7,0xf3,0x8b,0xd7,0x5b,0xd5,0xf1,0x8d}
};
static void dump(const unsigned char *b,int n)
{
@ -174,195 +196,49 @@ static void compare(const unsigned char *result,const unsigned char *expected,
if(result[i] != expected[i])
{
puts("Random test failed, got:");
dump(result,8);
dump(result,n);
puts("\n expected:");
dump(expected,8);
dump(expected,n);
putchar('\n');
EXIT(1);
}
}
static void run_test(const PRNGtest *t)
static void run_test(unsigned char *key, int keylen, AES_PRNG_MCT *tv)
{
unsigned char buf[8];
int n;
FIPS_set_prng_key(t->keys[0],t->keys[1]);
FIPS_test_mode(1,t->time);
RAND_seed(t->seed,sizeof t->seed);
if(RAND_bytes(buf,8) <= 0)
unsigned char buf[16], dt[16];
int i, j;
FIPS_rand_reset();
FIPS_rand_test_mode();
FIPS_rand_set_key(key, keylen);
FIPS_rand_seed(tv->V, 16);
memcpy(dt, tv->DT, 16);
for (i = 0; i < 10000; i++)
{
ERR_print_errors_fp(stderr);
EXIT(2);
FIPS_rand_set_dt(dt);
FIPS_rand_bytes(buf, 16);
/* Increment DT */
for (j = 15; j >= 0; j--)
{
dt[j]++;
if (dt[j])
break;
}
}
compare(buf,t->block1,8);
for(n=0 ; n < 99 ; ++n)
if(RAND_bytes(buf,8) <= 0)
{
ERR_print_errors_fp(stderr);
EXIT(2);
}
compare(buf,t->block100,8);
FIPS_test_mode(0,NULL);
compare(buf,tv->R, 16);
}
int main()
{
unsigned char buf[2500];
int i,j,k,s,sign,nsign,err=0;
unsigned long n1;
unsigned long n2[16];
unsigned long runs[2][34];
/*double d; */
long d;
RAND_set_rand_method(FIPS_rand_method());
run_test(&t1);
run_test(&t2);
FIPS_set_prng_key(prng_key1,prng_key2);
RAND_seed(prng_seed,sizeof prng_seed);
i = RAND_pseudo_bytes(buf,2500);
if (i <= 0)
{
printf ("init failed, the rand method is not properly installed\n");
err++;
goto err;
}
n1=0;
for (i=0; i<16; i++) n2[i]=0;
for (i=0; i<34; i++) runs[0][i]=runs[1][i]=0;
/* test 1 and 2 */
sign=0;
nsign=0;
for (i=0; i<2500; i++)
{
j=buf[i];
n2[j&0x0f]++;
n2[(j>>4)&0x0f]++;
for (k=0; k<8; k++)
{
s=(j&0x01);
if (s == sign)
nsign++;
else
{
if (nsign > 34) nsign=34;
if (nsign != 0)
{
runs[sign][nsign-1]++;
if (nsign > 6)
runs[sign][5]++;
}
sign=s;
nsign=1;
}
if (s) n1++;
j>>=1;
}
}
if (nsign > 34) nsign=34;
if (nsign != 0) runs[sign][nsign-1]++;
/* test 1 */
if (!((9654 < n1) && (n1 < 10346)))
{
printf("test 1 failed, X=%lu\n",n1);
err++;
}
printf("test 1 done\n");
/* test 2 */
#ifdef undef
d=0;
for (i=0; i<16; i++)
d+=n2[i]*n2[i];
d=d*16.0/5000.0-5000.0;
if (!((1.03 < d) && (d < 57.4)))
{
printf("test 2 failed, X=%.2f\n",d);
err++;
}
#endif
d=0;
for (i=0; i<16; i++)
d+=n2[i]*n2[i];
d=(d*8)/25-500000;
if (!((103 < d) && (d < 5740)))
{
printf("test 2 failed, X=%ld.%02ld\n",d/100L,d%100L);
err++;
}
printf("test 2 done\n");
/* test 3 */
for (i=0; i<2; i++)
{
if (!((2267 < runs[i][0]) && (runs[i][0] < 2733)))
{
printf("test 3 failed, bit=%d run=%d num=%lu\n",
i,1,runs[i][0]);
err++;
}
if (!((1079 < runs[i][1]) && (runs[i][1] < 1421)))
{
printf("test 3 failed, bit=%d run=%d num=%lu\n",
i,2,runs[i][1]);
err++;
}
if (!(( 502 < runs[i][2]) && (runs[i][2] < 748)))
{
printf("test 3 failed, bit=%d run=%d num=%lu\n",
i,3,runs[i][2]);
err++;
}
if (!(( 223 < runs[i][3]) && (runs[i][3] < 402)))
{
printf("test 3 failed, bit=%d run=%d num=%lu\n",
i,4,runs[i][3]);
err++;
}
if (!(( 90 < runs[i][4]) && (runs[i][4] < 223)))
{
printf("test 3 failed, bit=%d run=%d num=%lu\n",
i,5,runs[i][4]);
err++;
}
if (!(( 90 < runs[i][5]) && (runs[i][5] < 223)))
{
printf("test 3 failed, bit=%d run=%d num=%lu\n",
i,6,runs[i][5]);
err++;
}
}
printf("test 3 done\n");
/* test 4 */
if (runs[0][33] != 0)
{
printf("test 4 failed, bit=%d run=%d num=%lu\n",
0,34,runs[0][33]);
err++;
}
if (runs[1][33] != 0)
{
printf("test 4 failed, bit=%d run=%d num=%lu\n",
1,34,runs[1][33]);
err++;
}
printf("test 4 done\n");
err:
err=((err)?1:0);
EXIT(err);
return(err);
run_test(aes_128_mct_key, 16, &aes_128_mct_tv);
printf("FIPS PRNG test 1 done\n");
run_test(aes_192_mct_key, 24, &aes_192_mct_tv);
printf("FIPS PRNG test 2 done\n");
run_test(aes_256_mct_key, 32, &aes_256_mct_tv);
printf("FIPS PRNG test 3 done\n");
return 0;
}
#endif

View file

@ -24,6 +24,7 @@ int main()
#include <openssl/err.h>
#include <openssl/rand.h>
#include <openssl/fips_rand.h>
#include <openssl/x509v3.h>
#include <string.h>
#include <ctype.h>
@ -134,55 +135,161 @@ void pv(const char *tag,const unsigned char *val,int len)
void vst()
{
unsigned char key1[8];
unsigned char key2[8];
unsigned char v[8];
unsigned char dt[8];
unsigned char ret[8];
unsigned char *key;
unsigned char *v;
unsigned char *dt;
unsigned char ret[16];
char buf[1024];
char lbuf[1024];
char *keyword, *value;
int n;
long i, keylen;
keylen = 0;
while(fgets(buf,sizeof buf,stdin) != NULL)
{
fputs(buf,stdout);
if(!strncmp(buf,"[AES 128-Key]", 13))
keylen = 16;
else if(!strncmp(buf,"[AES 192-Key]", 13))
keylen = 24;
else if(!strncmp(buf,"[AES 256-Key]", 13))
keylen = 32;
if (!parse_line(&keyword, &value, lbuf, buf))
continue;
if(!strcmp(keyword,"Key1"))
if(!strcmp(keyword,"Key"))
{
n=hex2bin(value,key1);
}
else if(!strcmp(keyword,"Key2"))
{
n=hex2bin(value,key2);
key=string_to_hex(value,&i);
if (i != keylen)
{
fprintf(stderr, "Invalid key length, expecting %ld\n", keylen);
return;
}
}
else if(!strcmp(keyword,"DT"))
{
n=hex2bin(value,dt);
dt=string_to_hex(value,&i);
if (i != 16)
{
fprintf(stderr, "Invalid DT length\n");
return;
}
}
else if(!strcmp(keyword,"V"))
{
n=hex2bin(value,v);
v=string_to_hex(value,&i);
if (i != 16)
{
fprintf(stderr, "Invalid V length\n");
return;
}
FIPS_rand_method()->cleanup();
FIPS_set_prng_key(key1,key2);
FIPS_rand_seed(v,8);
FIPS_test_mode(1,dt);
if (FIPS_rand_method()->bytes(ret,8) <= 0)
{
FIPS_test_mode(0,NULL);
FIPSerr(FIPS_F_FIPS_SELFTEST_RNG,FIPS_R_SELFTEST_FAILED);
if (!key || !dt)
{
fprintf(stderr, "Missing key or DT\n");
return;
}
FIPS_rand_set_key(key, keylen);
FIPS_rand_seed(v,16);
FIPS_rand_set_dt(dt);
if (FIPS_rand_bytes(ret,16) <= 0)
{
fprintf(stderr, "Error getting PRNG value\n");
return;
}
pv("R",ret,8);
pv("R",ret,16);
putc('\n',stdout);
}
}
}
void mct()
{
unsigned char *key;
unsigned char *v;
unsigned char *dt;
unsigned char ret[16];
char buf[1024];
char lbuf[1024];
char *keyword, *value;
long i, keylen;
int j;
keylen = 0;
while(fgets(buf,sizeof buf,stdin) != NULL)
{
fputs(buf,stdout);
if(!strncmp(buf,"[AES 128-Key]", 13))
keylen = 16;
else if(!strncmp(buf,"[AES 192-Key]", 13))
keylen = 24;
else if(!strncmp(buf,"[AES 256-Key]", 13))
keylen = 32;
if (!parse_line(&keyword, &value, lbuf, buf))
continue;
if(!strcmp(keyword,"Key"))
{
key=string_to_hex(value,&i);
if (i != keylen)
{
fprintf(stderr, "Invalid key length, expecting %ld\n", keylen);
return;
}
}
else if(!strcmp(keyword,"DT"))
{
dt=string_to_hex(value,&i);
if (i != 16)
{
fprintf(stderr, "Invalid DT length\n");
return;
}
}
else if(!strcmp(keyword,"V"))
{
v=string_to_hex(value,&i);
if (i != 16)
{
fprintf(stderr, "Invalid V length\n");
return;
}
if (!key || !dt)
{
fprintf(stderr, "Missing key or DT\n");
return;
}
FIPS_rand_set_key(key, keylen);
FIPS_rand_seed(v,16);
for (i = 0; i < 10000; i++)
{
FIPS_rand_set_dt(dt);
if (FIPS_rand_bytes(ret,16) <= 0)
{
fprintf(stderr, "Error getting PRNG value\n");
return;
}
/* Increment DT */
for (j = 15; j >= 0; j--)
{
dt[j]++;
if (dt[j])
break;
}
}
pv("R",ret,16);
putc('\n',stdout);
}
}
}
#if 0
void mct()
{
unsigned char key1[8];
@ -199,6 +306,12 @@ void mct()
BIGNUM *pbn;
bn = BN_new();
if (FIPS_rand_reset() && !FIPS_rand_test_mode())
{
fprintf(stderr, Error setting PRNG test mode\n");
return;
}
while(fgets(buf,sizeof buf,stdin) != NULL)
{
fputs(buf,stdout);
@ -244,6 +357,7 @@ void mct()
}
BN_free(bn);
}
#endif
int main(int argc,char **argv)
{
@ -257,6 +371,13 @@ int main(int argc,char **argv)
ERR_print_errors(BIO_new_fp(stderr,BIO_NOCLOSE));
exit(1);
}
FIPS_rand_reset();
if (!FIPS_rand_test_mode())
{
fprintf(stderr, "Error setting PRNG test mode\n");
ERR_print_errors_fp(stderr);
exit(1);
}
if(!strcmp(argv[1],"mct"))
mct();
else if(!strcmp(argv[1],"vst"))

View file

@ -38,7 +38,7 @@ HEADER= $(EXHEADER) fips_sha_locl.h fips_md32_common.h
ALL= $(GENERAL) $(SRC) $(HEADER)
top:
(cd $(TOP); $(MAKE) DIRS=fips SDIRS=$(DIR) sub_all)
(cd $(TOP); $(MAKE) DIRS=fips-1.0 SDIRS=$(DIR) sub_all)
all: fips_standalone_sha1$(EXE_EXT) lib