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>]
#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)
{
-/* crypto/fips_err.c */
+/* crypto/fips_err.h */
/* ====================================================================
* Copyright (c) 1999-2006 The OpenSSL Project. All rights reserved.
*
/* 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
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}
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"},
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;
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");
}
/* automagically seed PRNG if not already seeded */
- if(!FIPS_rand_seeded())
+ if(!FIPS_rand_status())
{
if(RAND_bytes(buf,sizeof buf) <= 0)
{
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 */
#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
/* ====================================================================
- * 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
*/
/*
- * 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"
#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
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 */
-#ifndef GETPID_IS_MEANINGLESS
-static int seed_pid;
-static int key_pid;
-#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 const RAND_METHOD rand_fips_meth=
- {
- FIPS_rand_seed,
- fips_rand_bytes,
- fips_rand_cleanup,
- fips_rand_add,
- fips_rand_bytes,
- fips_rand_status
- };
+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 second;
+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;
+ }
-const RAND_METHOD *FIPS_rand_method(void)
-{
- return &rand_fips_meth;
-}
+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;
+ }
-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;
- }
+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;
+ }
-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);
- }
+int FIPS_rand_test_mode(void)
+ {
+ return fips_set_test_mode(&sctx);
+ }
-/* NB: this returns true if _partially_ seeded */
-int FIPS_rand_seeded()
- { return key_set || n_seed; }
+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_gettime(unsigned char buf[8])
+static void fips_get_dt(FIPS_PRNG_CTX *ctx)
{
#ifdef OPENSSL_SYS_WIN32
- FILETIME ft;
+ FILETIME ft;
#else
- struct timeval tv;
+ struct timeval tv;
#endif
+ unsigned char *buf = ctx->DT;
+
+ unsigned long pid;
- 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);
+ 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);
+ 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();
-#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;
+ 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
-#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;
+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;
+ }
- /* If the key hasn't been set, we can't seed! */
- if(!key_set)
- return;
- CRYPTO_w_lock(CRYPTO_LOCK_RAND);
- if(!key_init)
+int FIPS_rand_set_key(const unsigned char *key, FIPS_RAND_SIZE_T keylen)
{
- key_init=1;
- DES_set_key(&key1,&ks1);
- DES_set_key(&key2,&ks2);
+ int ret;
+ CRYPTO_w_lock(CRYPTO_LOCK_RAND);
+ ret = fips_set_prng_key(&sctx, key, keylen);
+ CRYPTO_w_unlock(CRYPTO_LOCK_RAND);
+ return ret;
}
- /*
- * This algorithm only uses 64 bits of seed, so ensure that we use
- * the most recent 64 bits.
- */
- for(n=0 ; n < num ; )
+int FIPS_rand_seed(const void *seed, FIPS_RAND_SIZE_T seedlen)
{
- 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;
+ int ret;
+ CRYPTO_w_lock(CRYPTO_LOCK_RAND);
+ ret = fips_set_prng_seed(&sctx, seed, seedlen);
+ CRYPTO_w_unlock(CRYPTO_LOCK_RAND);
+ return ret;
}
-#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)
+int FIPS_rand_bytes(unsigned char *out, FIPS_RAND_SIZE_T count)
{
- RANDerr(RAND_F_FIPS_RAND_BYTES,RAND_R_PRNG_NOT_SEEDED);
- return 0;
+ int ret;
+ CRYPTO_w_lock(CRYPTO_LOCK_RAND);
+ ret = fips_rand(&sctx, out, count);
+ CRYPTO_w_unlock(CRYPTO_LOCK_RAND);
+ return ret;
}
-#ifdef FIPS_RAND_MAX_SIZE_T
- if (num > FIPS_RAND_MAX_SIZE_T)
+int FIPS_rand_status(void)
{
-#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
+ int ret;
+ CRYPTO_r_lock(CRYPTO_LOCK_RAND);
+ ret = sctx.seeded;
+ CRYPTO_r_unlock(CRYPTO_LOCK_RAND);
+ return ret;
}
-#endif
-#ifndef GETPID_IS_MEANINGLESS
- pid=getpid();
- if(pid != seed_pid)
+void FIPS_rand_reset(void)
{
- RANDerr(RAND_F_FIPS_RAND_BYTES,RAND_R_PRNG_NOT_RESEEDED);
- return 0;
+ CRYPTO_w_lock(CRYPTO_LOCK_RAND);
+ fips_rand_prng_reset(&sctx);
+ CRYPTO_w_unlock(CRYPTO_LOCK_RAND);
}
- if(pid != key_pid)
+
+static void fips_do_rand_seed(const void *seed, FIPS_RAND_SIZE_T seedlen)
{
- RANDerr(RAND_F_FIPS_RAND_BYTES,RAND_R_PRNG_NOT_REKEYED);
- return 0;
+ FIPS_rand_seed(seed, seedlen);
}
-#endif
-
- CRYPTO_w_lock(CRYPTO_LOCK_RAND);
- for(n=0 ; n < num ; )
+static void fips_do_rand_add(const void *seed, FIPS_RAND_SIZE_T seedlen,
+ double add_entropy)
{
- 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;
+ FIPS_rand_seed(seed, seedlen);
}
- CRYPTO_w_unlock(CRYPTO_LOCK_RAND);
-
- return 1;
- }
-
-static int fips_rand_status(void)
+static const RAND_METHOD rand_fips_meth=
{
- return n_seed == sizeof seed;
- }
+ fips_do_rand_seed,
+ FIPS_rand_bytes,
+ FIPS_rand_reset,
+ fips_do_rand_add,
+ FIPS_rand_bytes,
+ FIPS_rand_status
+ };
-#endif /* OPENSSL_FIPS */
+const RAND_METHOD *FIPS_rand_method(void)
+{
+ return &rand_fips_meth;
+}
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);
#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
#include <stdio.h>
#include <stdlib.h>
+#include <string.h>
#include <openssl/rand.h>
#include <openssl/fips_rand.h>
#include <openssl/err.h>
#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;
-
-/* 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 }
- };
+ {
+ unsigned char DT[16];
+ unsigned char V[16];
+ unsigned char R[16];
+ } AES_PRNG_MCT;
+
+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)
{
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)
- {
- 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)
+static void run_test(unsigned char *key, int keylen, AES_PRNG_MCT *tv)
+ {
+ 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
#include <openssl/err.h>
#include <openssl/rand.h>
#include <openssl/fips_rand.h>
+#include <openssl/x509v3.h>
#include <string.h>
#include <ctype.h>
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];
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);
}
BN_free(bn);
}
+#endif
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"))
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