]> git.saurik.com Git - apple/xnu.git/blobdiff - bsd/dev/random/randomdev.c
xnu-1228.5.18.tar.gz
[apple/xnu.git] / bsd / dev / random / randomdev.c
index 4a7741e2a78c551c47ebda5d9517d05b8feeed08..9208ff6b69e6cb449fc8c34be2b29e310b2e6c1d 100644 (file)
@@ -99,7 +99,7 @@ typedef BlockWord Block[kBSize];
 
 void add_blocks(Block a, Block b, BlockWord carry);
 void fips_initialize(void);
-void random_block(Block b);
+void random_block(Block b, int addOptional);
 u_int32_t CalculateCRC(u_int8_t* buffer, size_t length);
 
 /*
@@ -194,18 +194,22 @@ u_int32_t CalculateCRC(u_int8_t* buffer, size_t length)
  * get a random block of data per fips 186-2
  */
 void
-random_block(Block b)
+random_block(Block b, int addOptional)
 {
        int repeatCount = 0;
        do
        {
                // do one iteration
-               Block xSeed;
-               prngOutput (gPrngRef, (BYTE*) &xSeed, sizeof (xSeed));
                
-               // add the seed to the previous value of g_xkey
-               add_blocks (g_xkey, xSeed, 0);
-
+               if (addOptional)
+               {
+                       Block xSeed;
+                       prngOutput (gPrngRef, (BYTE*) &xSeed, sizeof (xSeed));
+                       
+                       // add the seed to the previous value of g_xkey
+                       add_blocks (g_xkey, xSeed, 0);
+               }
+               
                // compute "G"
                SHA1Update (&g_sha1_ctx, (const u_int8_t *) &g_xkey, sizeof (g_xkey));
                
@@ -309,11 +313,13 @@ PreliminarySetup(void)
        fips_initialize ();
 }
 
+const Block kKnownAnswer = {0x92b404e5, 0x56588ced, 0x6c1acd4e, 0xbf053f68, 0x9f73a93};
+
 void
 fips_initialize(void)
 {
-       /* Read the initial value of g_xkey from yarrow */
-       prngOutput (gPrngRef, (BYTE*) &g_xkey, sizeof (g_xkey));
+       /* So that we can do the self test, set the seed to zero */
+       memset(&g_xkey, 0, sizeof(g_xkey));
        
        /* initialize our SHA1 generator */
        SHA1Init (&g_sha1_ctx);
@@ -321,7 +327,20 @@ fips_initialize(void)
        /* other initializations */
        memset (zeros, 0, sizeof (zeros));
        g_bytes_used = 0;
-       random_block(g_random_data);
+       random_block(g_random_data, FALSE);
+       
+       // check here to see if we got the initial data we were expecting
+       int i;
+       for (i = 0; i < kBSize; ++i)
+       {
+               if (kKnownAnswer[i] != g_random_data[i])
+               {
+                       panic("FIPS random self test failed");
+               }
+       }
+       
+       // now do the random block again to make sure that userland doesn't get predicatable data
+       random_block(g_random_data, TRUE);
 }
 
 /*
@@ -490,7 +509,7 @@ random_read(__unused dev_t dev, struct uio *uio, __unused int ioflag)
                int bytes_available = kBSizeInBytes - g_bytes_used;
         if (bytes_available == 0)
                {
-                       random_block(g_random_data);
+                       random_block(g_random_data, TRUE);
                        g_bytes_used = 0;
                        bytes_available = kBSizeInBytes;
                }
@@ -533,7 +552,7 @@ read_random(void* buffer, u_int numbytes)
         int bytes_to_read = min(bytes_remaining, kBSizeInBytes - g_bytes_used);
         if (bytes_to_read == 0)
                {
-                       random_block(g_random_data);
+                       random_block(g_random_data, TRUE);
                        g_bytes_used = 0;
                        bytes_to_read = min(bytes_remaining, kBSizeInBytes);
                }