43 #if defined( INC_ALL )
45 #ifdef CONFIG_RANDSEED
51 #ifdef CONFIG_RANDSEED
59 #if !( defined( __BEOS__ ) || defined( __ECOS__ ) || \
60 defined( __IBM4758__ ) || defined( __MAC__ ) || \
61 defined( __MSDOS__ ) || defined( __MVS__ ) || \
62 defined( __OS2__ ) || defined( __PALMOS__ ) || \
63 defined( __TANDEM_NSK__ ) || defined( __TANDEM_OSS__ ) || \
64 defined( __UNIX__ ) || defined( __VMCMS__ ) || \
65 defined( __WIN16__ ) || defined( __WIN32__ ) || \
66 defined( __WINCE__ ) || defined( __XMK__ ) )
67 #error You need to create OS-specific randomness-gathering functions in random/<os-name>.c
73 #ifdef CONFIG_RANDSEED
74 #ifndef CONFIG_RANDSEED_QUALITY
76 #define CONFIG_RANDSEED_QUALITY 80
78 #if ( CONFIG_RANDSEED_QUALITY < 10 ) || ( CONFIG_RANDSEED_QUALITY > 100 )
79 #error CONFIG_RANDSEED_QUALITY must be between 10 and 100
90 #define REQUIRES_MUTEX( x ) \
91 if( !( x ) ) { krnlExitMutex( MUTEX_RANDOM ); retIntError(); }
92 #define ENSURES_MUTEX REQUIRES_MUTEX
108 #define RANDOMPOOL_MIXES 10
182 REQUIRES( sanityCheck( randomInfo ) );
193 int dataBufIndex, poolIndex;
196 REQUIRES( hashIndex % hashSize == 0 );
201 poolIndex = ( hashIndex >=
hashSize ) ? \
202 hashIndex - hashSize : RANDOMPOOL_SIZE - hashSize;
203 ENSURES( poolIndex >= 0 && poolIndex <= RANDOMPOOL_SIZE - hashSize );
227 for( dataBufIndex = 0; dataBufIndex < hashSize + 64; dataBufIndex++ )
229 dataBuffer[ dataBufIndex ] = randomInfo->randomPool[ poolIndex ];
230 poolIndex = ( poolIndex + 1 ) % RANDOMPOOL_SIZE;
235 ENSURES( dataBufIndex == hashSize + 64 );
241 dataBuffer, dataBufIndex );
247 ENSURES( hashIndex >= RANDOMPOOL_SIZE );
249 dataBuffer[ i ] == 0 );
254 randomInfo->randomPoolMixes++;
255 randomInfo->randomPoolPos = 0;
260 randomInfo->randomPoolMixes == \
262 ENSURES( randomInfo->randomPoolPos == 0 );
264 ENSURES( sanityCheck( randomInfo ) );
305 #define RANDOM_OUTPUTSIZE ( RANDOMPOOL_SIZE / 2 )
311 const BYTE *samplePtr = randomInfo->randomPool;
312 const BYTE *x917SamplePtr = exportedRandomInfo->randomPool;
313 unsigned long sample;
325 REQUIRES( sanityCheck( randomInfo ) );
326 REQUIRES( randomInfo->randomQuality >= 100 && \
328 randomInfo->x917Inited ==
TRUE );
329 REQUIRES( exportedRandomInfo->randomQuality == 0 && \
330 exportedRandomInfo->randomPoolMixes == 0 && \
331 exportedRandomInfo->x917Inited ==
FALSE );
336 exportedRandomInfo->randomPool[ i ] = randomInfo->randomPool[ i ] ^ 0xFF;
340 ENSURES( memcmp( randomInfo->randomPool, exportedRandomInfo->randomPool,
341 RANDOMPOOL_ALLOCSIZE ) );
342 FORALL( i, 0, RANDOMPOOL_ALLOCSIZE, \
343 randomInfo->randomPool[ i ] == \
344 ( exportedRandomInfo->randomPool[ i ] ^ 0xFF ) );
348 status = mixRandomPool( randomInfo );
350 status = mixRandomPool( exportedRandomInfo );
357 ENSURES( memcmp( randomInfo->randomPool, exportedRandomInfo->randomPool,
358 RANDOMPOOL_ALLOCSIZE ) );
359 ENSURES( randomInfo->randomPool[ 0 ] != \
360 ( exportedRandomInfo->randomPool[ 0 ] ^ 0xFF ) ||
361 randomInfo->randomPool[ 8 ] != \
362 ( exportedRandomInfo->randomPool[ 8 ] ^ 0xFF ) ||
363 randomInfo->randomPool[ 16 ] != \
364 ( exportedRandomInfo->randomPool[ 16 ] ^ 0xFF ) ||
365 randomInfo->randomPool[ 24 ] != \
366 ( exportedRandomInfo->randomPool[ 24 ] ^ 0xFF ) ||
367 randomInfo->randomPool[ 32 ] != \
368 ( exportedRandomInfo->randomPool[ 32 ] ^ 0xFF ) ||
369 randomInfo->randomPool[ 40 ] != \
370 ( exportedRandomInfo->randomPool[ 40 ] ^ 0xFF ) );
374 ENSURES( samplePtr == randomInfo->randomPool && \
375 x917SamplePtr == exportedRandomInfo->randomPool );
382 if( randomInfo->prevOutput[ i ] == sample )
392 FORALL( i, 0, RANDOMPOOL_SAMPLES, \
393 randomInfo->prevOutput[ i ] != sample );
396 status = generateX917( randomInfo, exportedRandomInfo->randomPool,
397 RANDOMPOOL_ALLOCSIZE );
421 if( randomInfo->x917PrevOutput[ i ] == sample )
426 !memcmp( randomInfo->x917OuputSample,
427 exportedRandomInfo->randomPool,
441 FORALL( i, 0, RANDOMPOOL_SAMPLES, \
442 randomInfo->x917PrevOutput[ i ] != sample );
444 ENSURES( sanityCheck( randomInfo ) );
456 int noRandomRetries, i,
status;
463 "Random pool size" );
467 REQUIRES( sanityCheck( randomInfo ) );
469 length <= RANDOMPOOL_SIZE / 2 );
476 if( !randomInfo->x917Inited || \
479 status = mixRandomPool( randomInfo );
481 status = setKeyX917( randomInfo, randomInfo->randomPool,
485 status = mixRandomPool( randomInfo );
487 status = generateX917( randomInfo, randomInfo->randomPool,
490 status = mixRandomPool( randomInfo );
492 status = generateX917( randomInfo, randomInfo->randomPool,
496 memcpy( randomInfo->x917OuputSample, randomInfo->randomPool,
504 randomInfo->randomQuality >= 100 && randomInfo->x917Inited );
507 initRandomPool( &exportedRandomInfo );
511 status = tryGetRandomOutput( randomInfo, &exportedRandomInfo );
512 for( noRandomRetries = 1;
516 status = tryGetRandomOutput( randomInfo, &exportedRandomInfo );
522 endRandomPool( &exportedRandomInfo );
526 exportedRandomInfo.randomPool[ i ] == 0 );
531 randomInfo->randomQuality = randomInfo->randomPoolMixes = 0;
532 randomInfo->x917Inited =
FALSE;
537 REQUIRES( randomInfo->prevOutputIndex >= 0 && \
539 samplePtr = randomInfo->randomPool;
540 randomInfo->prevOutput[ randomInfo->prevOutputIndex ] =
mgetLong( samplePtr );
541 samplePtr = exportedRandomInfo.randomPool;
542 randomInfo->x917PrevOutput[ randomInfo->prevOutputIndex ] =
mgetLong( samplePtr );
543 randomInfo->prevOutputIndex = ( randomInfo->prevOutputIndex + 1 ) % \
545 memcpy( randomInfo->x917OuputSample, exportedRandomInfo.randomPool,
548 ENSURES( randomInfo->prevOutputIndex == 0 || \
549 randomInfo->prevOutputIndex ==
ORIGINAL_VALUE( prevOutputIndex ) + 1 );
550 ENSURES( randomInfo->prevOutputIndex >= 0 && \
555 for( i = 0; i <
length; i++ )
557 buffer[ i ] = exportedRandomInfo.randomPool[ i ] ^ \
564 ENSURES( i <= RANDOMPOOL_SIZE / 2 );
565 EXISTS( i, 0, RANDOMPOOL_SIZE / 2, \
566 buffer[ i ] != ( randomInfo->randomPool[ i ] ^ \
570 endRandomPool( &exportedRandomInfo );
574 exportedRandomInfo.randomPool[ i ] == 0 );
576 ENSURES( sanityCheck( randomInfo ) );
588 int randomQuality, count, iterationCount,
status;
612 #ifdef CONFIG_RANDSEED
613 if( !randomInfo->seedProcessed )
614 addStoredSeedData( randomInfo );
629 if( randomQuality < 100 )
701 status = mixRandomPool( randomInfo );
731 status = getRandomOutput( randomInfo, bufPtr, outputBytes );
737 bufPtr += outputBytes;
742 ( bufPtr <= (
BYTE * ) buffer + length ) );
778 BYTE buffer[ 16 + 8 ];
781 assert(
isWritePtr( randomInfoPtrPtr,
sizeof(
void * ) ) );
784 *randomInfoPtrPtr = NULL;
792 initRandomPool( &testRandomInfo );
793 status = mixRandomPool( &testRandomInfo );
795 memcmp( testRandomInfo.randomPool,
796 "\xF6\x8F\x30\xEE\x52\x13\x3E\x40\x06\x06\xA6\xBE\x91\xD2\xD9\x82", 16 ) )
799 status = mixRandomPool( &testRandomInfo );
801 memcmp( testRandomInfo.randomPool,
802 "\xAE\x94\x3B\xF2\x86\x5F\xCF\x76\x36\x2B\x80\xD5\x73\x86\x9B\x69", 16 ) )
805 status = mixRandomPool( &testRandomInfo );
807 memcmp( testRandomInfo.randomPool,
808 "\xBC\x2D\xC1\x03\x8C\x78\x6D\x04\xA8\xBD\xD5\x51\x80\xCA\x42\xF4", 16 ) )
812 endRandomPool( &testRandomInfo );
817 status =
selfTestX917( &testRandomInfo, testRandomInfo.randomPool );
820 endRandomPool( &testRandomInfo );
829 status = getRandomOutput( &testRandomInfo, buffer, 16 );
831 memcmp( buffer,
"\x6B\x59\x1D\xCD\xE1\xB3\xA8\x50\x32\x84\x8C\x8D\x93\xB0\x74\xD7", 16 ) )
835 endRandomPool( &testRandomInfo );
838 endRandomPool( &testRandomInfo );
844 endRandomPool( &testRandomInfo );
849 if( ( status = krnlMemalloc( (
void ** ) &randomInfoPtr, \
852 initRandomPool( randomInfoPtr );
857 *randomInfoPtrPtr = randomInfoPtr;
878 assert(
isWritePtr( randomInfoPtrPtr,
sizeof(
void * ) ) );
894 endRandomPool( randomInfoPtr );
896 status = krnlMemfree( randomInfoPtrPtr );
914 const BYTE *bufPtr = (
BYTE * ) buffer;
940 for( count = 0; count <
length; count++ )
951 status = mixRandomPool( randomInfo );
968 randomInfo->randomPool[ randomInfo->
randomPoolPos++ ] ^= bufPtr[ count ];
990 randomInfo->entropyByteCount +=
length;
996 ENSURES( randomInfo->entropyByteCount == \
1009 IN_RANGE( 1, 100 )
const int quality )
1016 REQUIRES( quality > 0 && quality <= 100 );
1053 if( randomInfo->entropyByteCount <= 0 || \
1054 quality / 2 > randomInfo->entropyByteCount )
1064 randomInfo->entropyByteCount = 0;
1086 #ifdef CONFIG_RANDSEED
1095 char seedFilePath[ MAX_PATH_LENGTH + 8 ];
1101 status = fileBuildCryptlibPath( seedFilePath, MAX_PATH_LENGTH,
1102 &seedFilePathLen, NULL, 0,
1110 seedFilePath[ seedFilePathLen ] =
'\0';
1116 randomInfo->seedProcessed =
TRUE;
1117 DEBUG_DIAG((
"Error opening random seed file" ));
1126 status = length = sread( &stream, seedBuffer, 1024 );
1127 sFileClose( &stream );
1133 randomInfo->seedProcessed =
TRUE;
1134 DEBUG_DIAG((
"Error reading random seed file" ));
1138 ENSURES_V( length >= 16 && length <= 1024 );
1139 randomInfo->seedSize =
length;
1143 seedBuffer[ i ] != 0 );
1151 for( poolCount = RANDOMPOOL_SIZE; poolCount > 0; poolCount -=
length )
1153 status = addEntropyData( randomInfo, seedBuffer, length );
1159 status = addEntropyQuality( randomInfo, CONFIG_RANDSEED_QUALITY );
1166 seedBuffer[ i ] == 0 );
1202 "Random pool state size" );
1208 state->bufSize = maxSize;
1221 int bytesToCopy =
min( valueLength, state->bufSize - state->bufPos );
1225 assert(
isReadPtr( value, valueLength ) );
1228 REQUIRES( state->bufPos >= 0 && state->bufPos <= state->bufSize );
1233 return( state->updateStatus );
1236 if( bytesToCopy > 0 )
1240 ANALYSER_HINT( bytesToCopy > 0 && bytesToCopy <= valueLength );
1242 memcpy( (
BYTE * ) state->buffer + state->bufPos, valuePtr, bytesToCopy );
1243 state->bufPos += bytesToCopy;
1244 valuePtr += bytesToCopy;
1245 totalLength -= bytesToCopy;
1250 if( state->bufPos < state->bufSize )
1253 ENSURES( state->bufPos == state->bufSize );
1258 &msgData, CRYPT_IATTRIBUTE_ENTROPY );
1267 state->updateStatus =
status;
1274 if( totalLength <= 0 )
1283 assert( totalLength < state->
bufSize );
1284 bytesToCopy =
min( totalLength, state->bufSize );
1285 memcpy( state->buffer, valuePtr, bytesToCopy );
1286 state->bufPos += bytesToCopy;
1292 int addRandomLong(
INOUT void *statePtr,
const long value )
1294 return( addRandomData( statePtr, &value,
sizeof(
long ) ) );
1298 int endRandomData(
INOUT void *statePtr, \
1299 IN_RANGE( 0, 100 )
const int quality )
1302 int status = state->updateStatus;
1307 REQUIRES( state->bufPos >= 0 && state->bufPos <= state->bufSize );
1308 REQUIRES( quality >= 0 && quality <= 100 );
1312 return( state->updateStatus );
1320 if( state->bufPos > 0 )
1327 CRYPT_IATTRIBUTE_ENTROPY );
1337 CRYPT_IATTRIBUTE_ENTROPY_QUALITY );
1342 zeroise( state->buffer, state->bufSize );