Replace FIPS PRNG with AES version.
authorDr. Stephen Henson <steve@openssl.org>
Wed, 21 Feb 2007 16:57:35 +0000 (16:57 +0000)
committerDr. Stephen Henson <steve@openssl.org>
Wed, 21 Feb 2007 16:57:35 +0000 (16:57 +0000)
14 files changed:
CHANGES
crypto/evp/names.c
crypto/fips_err.h
crypto/rand/rand.h
crypto/rand/rand_err.c
fips-1.0/dsa/fips_dsatest.c
fips-1.0/fips.c
fips-1.0/fips.h
fips-1.0/rand/fips_rand.c
fips-1.0/rand/fips_rand.h
fips-1.0/rand/fips_rand_selftest.c
fips-1.0/rand/fips_randtest.c
fips-1.0/rand/fips_rngvs.c
fips-1.0/sha/Makefile

diff --git a/CHANGES b/CHANGES
index 5df10ebc7bdbc9031198675a0f396ddf00e87e09..73aacc380edb717fe4a8eb680a43f2f6653658e3 100644 (file)
--- a/CHANGES
+++ b/CHANGES
@@ -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>]
 
index 771245304615c01e61655e82f48e6c3b22a4fa5a..eb9f4329cd4dda102e7ccb469a49c0530ec35ad9 100644 (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)
        {
index 448f157153cbf38d1c73d44e393f2d34c34ba605..092ec22cdbaddf921d9fec984996694b9c70af22 100644 (file)
@@ -1,4 +1,4 @@
-/* crypto/fips_err.c */
+/* crypto/fips_err.h */
 /* ====================================================================
  * Copyright (c) 1999-2006 The OpenSSL Project.  All rights reserved.
  *
index 604df9be6c3882e66ed169d747ede934991a69bd..d5fd3b15e93031bf0ae89a5f9574a6ef5476e056 100644 (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
index f3e11f83963bf7fffeb7b6cf06321083e42a3c76..8c6bcce833f9f221031f91d17bd50efd98419f70 100644 (file)
 
 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"},
index f4cc37b19aaa6944ad378e0333545b1016e41d37..b20e8f48a34973664eb27fc0152f5e45d9faade3 100644 (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");
index d2d35be52821effa2e706b0007d83208ced66c1e..5c7c3a04548f52c4310a5434647ce3f341750792 100644 (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 */
index 9c5a4ca968d88cc639365581621ef67fe87703bc..f9736a4656469fd9e02437ff4a45b5e868f145da 100644 (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
index 7df2dc804e4424114beeccbea0225744556409bb..7e7a0362316daca3df28e1021a9c5bcaae993b72 100644 (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
 
 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;
+}
index 093727240e74405189ab0db1c165e38953a7c5d7..a175aaf6c5774c89c813e51d252a67b8e83c2a61 100644 (file)
 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);
 
index 691b929d71c2c444737e8218e5a4d0726819d4ad..2194a76cd1bd71701dc856a924671c0e09949007 100644 (file)
 #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
index f7e4d836346a6e4086a76d0a841ecaffb22373e5..0393518370b06f691b0e52281bf59912eea96cef 100644 (file)
 
 #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;
-
-/* 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)
     {
@@ -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)
-    {
-    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
index 0a56b828f20e2307e3299777ff11591b202686e9..f1740cf97d595798b0aa9b5bca8088bbdca353f0 100644 (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"))
index 31556697ceb7b0613f8e6d7bc5ec58bfbafd950c..0769fc496336273941fc7387b7d5bf75fe614927 100644 (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