X-Git-Url: https://git.saurik.com/apple/xnu.git/blobdiff_plain/21362eb3e66fd2c787aee132bce100a44d71a99c..cf7d32b81c573a0536dc4da4157f9c26f8d0bed3:/bsd/dev/random/randomdev.c diff --git a/bsd/dev/random/randomdev.c b/bsd/dev/random/randomdev.c index 6f99d775d..9208ff6b6 100644 --- a/bsd/dev/random/randomdev.c +++ b/bsd/dev/random/randomdev.c @@ -1,5 +1,5 @@ /* - * Copyright (c)1999-2004 Apple Computer, Inc. All rights reserved. + * Copyright (c) 1999-2006 Apple Computer, Inc. All rights reserved. * * @APPLE_OSREFERENCE_LICENSE_HEADER_START@ * @@ -36,13 +36,17 @@ #include #include #include +#include #include #include #include #include #include -#include +#include + +#include +#include #define RANDOM_MAJOR -1 /* let the kernel pick the device number */ @@ -74,7 +78,12 @@ static struct cdevsw random_cdevsw = static int gRandomInstalled = 0; static PrngRef gPrngRef; static int gRandomError = 1; -static mutex_t *gYarrowMutex = 0; +static lck_grp_t *gYarrowGrp; +static lck_attr_t *gYarrowAttr; +static lck_grp_attr_t *gYarrowGrpAttr; +static lck_mtx_t *gYarrowMutex = 0; + +void CheckReseed(void); #define RESEED_TICKS 50 /* how long a reseed operation can take */ @@ -90,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); /* @@ -185,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)); @@ -252,8 +265,6 @@ void PreliminarySetup(void) { prng_error_status perr; - struct timeval tt; - char buffer [16]; /* create a Yarrow object */ perr = prngInitialize(&gPrngRef); @@ -265,6 +276,10 @@ PreliminarySetup(void) /* clear the error flag, reads and write should then work */ gRandomError = 0; + { + struct timeval tt; + char buffer [16]; + /* get a little non-deterministic data as an initial seed. */ microtime(&tt); @@ -283,22 +298,28 @@ PreliminarySetup(void) } /* turn the data around */ - perr = prngOutput(gPrngRef, (BYTE*)buffer, sizeof (buffer)); + perr = prngOutput(gPrngRef, (BYTE*) buffer, sizeof (buffer)); /* and scramble it some more */ perr = prngForceReseed(gPrngRef, RESEED_TICKS); + } /* make a mutex to control access */ - gYarrowMutex = mutex_alloc(0); + gYarrowGrpAttr = lck_grp_attr_alloc_init(); + gYarrowGrp = lck_grp_alloc_init("random", gYarrowGrpAttr); + gYarrowAttr = lck_attr_alloc_init(); + gYarrowMutex = lck_mtx_alloc_init(gYarrowGrp, gYarrowAttr); 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); @@ -306,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); } /* @@ -324,8 +358,10 @@ random_init(void) /* install us in the file system */ gRandomInstalled = 1; +#ifndef ARM_BOARD_CONFIG_S5L8900XFPGA_1136JFS /* setup yarrow and the mutex */ PreliminarySetup(); +#endif ret = cdevsw_add(RANDOM_MAJOR, &random_cdevsw); if (ret < 0) { @@ -416,7 +452,7 @@ random_write (__unused dev_t dev, struct uio *uio, __unused int ioflag) } /* get control of the Yarrow instance, Yarrow is NOT thread safe */ - mutex_lock(gYarrowMutex); + lck_mtx_lock(gYarrowMutex); /* Security server is sending us entropy */ @@ -429,7 +465,7 @@ random_write (__unused dev_t dev, struct uio *uio, __unused int ioflag) goto /*ugh*/ error_exit; /* put it in Yarrow */ - if (prngInput(gPrngRef, (BYTE*)rdBuffer, + if (prngInput(gPrngRef, (BYTE*) rdBuffer, bytesToInput, SYSTEM_SOURCE, bytesToInput * 8) != 0) { retCode = EIO; @@ -446,14 +482,15 @@ random_write (__unused dev_t dev, struct uio *uio, __unused int ioflag) /* retCode should be 0 at this point */ error_exit: /* do this to make sure the mutex unlocks. */ - mutex_unlock(gYarrowMutex); + lck_mtx_unlock(gYarrowMutex); return (retCode); } /* * return data to the caller. Results unpredictable. */ -int random_read(__unused dev_t dev, struct uio *uio, __unused int ioflag) +int +random_read(__unused dev_t dev, struct uio *uio, __unused int ioflag) { int retCode = 0; @@ -461,8 +498,9 @@ int random_read(__unused dev_t dev, struct uio *uio, __unused int ioflag) return (ENOTSUP); /* lock down the mutex */ - mutex_lock(gYarrowMutex); + lck_mtx_lock(gYarrowMutex); + CheckReseed(); int bytes_remaining = uio_resid(uio); while (bytes_remaining > 0 && retCode == 0) { /* get the user's data */ @@ -471,14 +509,14 @@ int 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; } bytes_to_read = min (bytes_remaining, bytes_available); - retCode = uiomove(((u_int8_t*)g_random_data)+ g_bytes_used, bytes_to_read, uio); + retCode = uiomove(((caddr_t)g_random_data)+ g_bytes_used, bytes_to_read, uio); g_bytes_used += bytes_to_read; if (retCode != 0) @@ -490,7 +528,7 @@ int random_read(__unused dev_t dev, struct uio *uio, __unused int ioflag) retCode = 0; error_exit: - mutex_unlock(gYarrowMutex); + lck_mtx_unlock(gYarrowMutex); return retCode; } @@ -499,11 +537,14 @@ void read_random(void* buffer, u_int numbytes) { if (gYarrowMutex == 0) { /* are we initialized? */ +#ifndef ARM_BOARD_CONFIG_S5L8900XFPGA_1136JFS PreliminarySetup (); +#endif } - mutex_lock(gYarrowMutex); - + lck_mtx_lock(gYarrowMutex); + CheckReseed(); + int bytes_read = 0; int bytes_remaining = numbytes; @@ -511,18 +552,18 @@ 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); } - memmove (buffer, ((u_int8_t*)g_random_data)+ bytes_read, bytes_to_read); + memmove ((u_int8_t*) buffer + bytes_read, ((u_int8_t*)g_random_data)+ g_bytes_used, bytes_to_read); g_bytes_used += bytes_to_read; bytes_read += bytes_to_read; bytes_remaining -= bytes_to_read; } - mutex_unlock(gYarrowMutex); + lck_mtx_unlock(gYarrowMutex); } /* @@ -536,3 +577,7 @@ RandomULong(void) return (buf); } +void +CheckReseed(void) +{ +}