287 lines
8.8 KiB
C
287 lines
8.8 KiB
C
/* dot11RandLib.c - random number generator for wireless framework */
|
|
|
|
/*
|
|
Modification History
|
|
--------------------
|
|
02a,02mar10,kr Initial version
|
|
*/
|
|
|
|
/*
|
|
DESCRIPTION
|
|
|
|
This module contains functions for generating random numbers:
|
|
- depends on openssl for the SHA256 and MD5 hashes;
|
|
- code adapted from the CCI library (cci_DefaultRand.c).
|
|
|
|
\NOMANUAL
|
|
|
|
*/
|
|
|
|
#include <vxWorks.h>
|
|
#include <semLib.h>
|
|
#include <sys/types.h>
|
|
#include <stdio.h>
|
|
#include "drv/wlan/dot11Lib.h"
|
|
#include "drv/wlan/dot11RsnLib.h"
|
|
|
|
/****************************************************************************
|
|
*
|
|
* *** Restricted Rights Legend ***
|
|
*
|
|
* The programs and information contained herein are licensed only
|
|
* pursuant to a license agreement that contains use, reverse
|
|
* engineering, disclosure, and other restrictions; accordingly, it
|
|
* is "Unpublished--all rights reserved under the applicable
|
|
* copyright laws".
|
|
*
|
|
* Use duplication, or disclosure by the Government is subject to
|
|
* restrictions as set forth in subparagraph (c)(1)(ii) of the Rights
|
|
* in Technical Data and Computer Licensed Programs clause of DFARS
|
|
* 52.227 7013.
|
|
*
|
|
* Copyright 2000-2010 Wind River Systems, Inc.
|
|
* Copyright 1997 Epilogue Technology Corporation.
|
|
* Copyright 1998-1999 Integrated Systems, Inc.
|
|
* All rights reserved.
|
|
*
|
|
* *** Government Use ***
|
|
*
|
|
* The Licensed Programs and their documentation were developed at
|
|
* private expense and no part of them is in the public domain.
|
|
*
|
|
* The Licensed Programs are "Restricted Computer Software" as that
|
|
* term is defined in Clause 52.227-19 of the Federal Acquisition
|
|
* Regulations (FAR) and are "Commercial Computer Software" as that
|
|
* term is defined in Subpart 227.401 of the Department of Defense
|
|
* Federal Acquisition Regulation Supplement (DFARS).
|
|
*
|
|
* (i) If the licensed Programs are supplied to the Department of
|
|
* Defense (DoD), the Licensed Programs are classified as
|
|
* "Commercial Computer Software" and the Government is acquiring
|
|
* only "restricted rights" in the Licensed Programs and their
|
|
* documentation as that term is defined in Clause 52.227
|
|
* 7013(c)(1) of the DFARS, and
|
|
*
|
|
* (ii) If the Licensed Programs are supplied to any unit or agency
|
|
* of the United States Government other than DoD, the
|
|
* Government's rights in the Licensed Programs and their
|
|
* documentation will be as defined in Clause 52.227-19(c)(2) of
|
|
* the FAR.
|
|
****************************************************************************/
|
|
|
|
/*
|
|
* This file implements a cryptographically strong random number generator.
|
|
* The algorithm is based on the ANSI X9.17 generator. Keyed MD5 is used
|
|
* as the basic transform rather than TDES. The DT value is augmented with
|
|
* a monotonically increasing counter. See [Stallings - Network and
|
|
* Internetwork Security pp 102-103] or ANSI X9.17 Appendix C.
|
|
*/
|
|
|
|
/*
|
|
* these next 2 bits of magic are used to seed the generator with
|
|
* less than 32 bytes of randomness. If the user hands in N < 32 bytes (call
|
|
* them "B") we generate MD5 (MAGIC1 "+" B "+" MAGIC1), and
|
|
* MD5 (MAGIC2 "+" B "+" MAGIC2), and combine them to get our needed 32 bytes.
|
|
* The actual values here are *not* of any importance, although having a
|
|
* reasonably "random" bit distribution is useful. These were generated by
|
|
* running some real-time system statistics through MD5.
|
|
*/
|
|
|
|
static UINT8 PRNG_MAGIC1 [] =
|
|
{ 0xb4, 0x33, 0x4b, 0xf5, 0x9b, 0x7a, 0x24, 0x19,
|
|
0x8c, 0x04, 0xa5, 0xd1, 0x1e, 0xab, 0xa2, 0xe9
|
|
};
|
|
|
|
static UINT8 PRNG_MAGIC2 [] =
|
|
{ 0xaa, 0x9b, 0x49, 0xd4, 0x0f, 0x4c, 0xa7, 0x1b,
|
|
0x1d, 0x0e, 0x83, 0xd6, 0xe7, 0x9c, 0xab, 0xf8
|
|
};
|
|
|
|
#define PRNG_SEEDBYTES_NEEDED 32
|
|
|
|
static MD5_CTX PRNG_CCI_MD5_CONTEXT;
|
|
|
|
static UINT8 PRNG_MD5_K[16]; /* MD5 keyed hash key */
|
|
static UINT8 PRNG_SV[16]; /* current seed value */
|
|
static UINT8 PRNG_R[16]; /* current random pool */
|
|
static UINT32 PRNG_DT; /* "date+time" value */
|
|
static UINT32 PRNG_CNT; /* counter; increments with each call */
|
|
static UINT8 PRNG_N; /* number of "random" bytes currently available */
|
|
static UINT8 PRNG_INJIDX; /* index of PRNG_SV where prng_inject_random8 will xor next random input into */
|
|
|
|
static SEM_ID defaultMtx;
|
|
|
|
/*
|
|
** --- randomly get current time
|
|
*/
|
|
static UINT32 randomTime( void )
|
|
{
|
|
struct timespec tspec;
|
|
clock_gettime( CLOCK_REALTIME, &tspec );
|
|
return( (UINT32) tspec.tv_nsec );
|
|
}
|
|
|
|
/*
|
|
** --- Get a random number from the SHA256 algorithm that produces
|
|
** a 32-byte digest --- which is equal to PRNG_SEEDBYTES_NEEDED(the value of the variable 'length').
|
|
*/
|
|
static unsigned glue_seed_prng( UINT8 *buffer, unsigned length )
|
|
{
|
|
SHA256_CTX context;
|
|
UINT32 t = randomTime();
|
|
|
|
SHA256_Init( &context );
|
|
SHA256_Update( &context, (void *) &t, sizeof(UINT32) );
|
|
SHA256_Final( buffer, &context );
|
|
return( length );
|
|
}
|
|
|
|
/*
|
|
* compute next seed value and state
|
|
*/
|
|
static void prng_iterate( void )
|
|
{
|
|
int i;
|
|
UINT8 *p, *q;
|
|
UINT8 digest[16];
|
|
|
|
/* step 1. R = MD5_K (MD5_K ((DT concat (++CNT)) XOR SV)) */
|
|
|
|
/* digest <-- MD5 ((DT concat (++CNT)) XOR SV */
|
|
++PRNG_CNT;
|
|
PRNG_DT = randomTime();
|
|
MD5_Init( &PRNG_CCI_MD5_CONTEXT );
|
|
MD5_Update( &PRNG_CCI_MD5_CONTEXT, PRNG_MD5_K, 16 );
|
|
MD5_Update( &PRNG_CCI_MD5_CONTEXT, (UINT8 *) &PRNG_DT, 4 );
|
|
MD5_Update( &PRNG_CCI_MD5_CONTEXT, (UINT8 *) &PRNG_CNT, 4 );
|
|
MD5_Update( &PRNG_CCI_MD5_CONTEXT, PRNG_MD5_K, 16 );
|
|
MD5_Final( digest, &PRNG_CCI_MD5_CONTEXT );
|
|
|
|
/* PRNG_SV <-- (PRNG_SV XOR digest) */
|
|
|
|
/* leave digest alone as we'll need it again when we compute new SV */
|
|
for( i = 0, p = PRNG_SV, q = digest; i < 16; i++ ) *p++ ^= *q++;
|
|
|
|
/* PRNG_R <-- MD5 (PRNG_SV) */
|
|
MD5_Init( &PRNG_CCI_MD5_CONTEXT );
|
|
MD5_Update( &PRNG_CCI_MD5_CONTEXT, PRNG_MD5_K, 16 );
|
|
MD5_Update( &PRNG_CCI_MD5_CONTEXT, PRNG_SV, 16 );
|
|
MD5_Update( &PRNG_CCI_MD5_CONTEXT, PRNG_MD5_K, 16 );
|
|
MD5_Final( PRNG_R, &PRNG_CCI_MD5_CONTEXT );
|
|
|
|
/*
|
|
* step 2. SV = MD5_K (MD5_K ((DT concat (++CNT)) XOR R))
|
|
*
|
|
* digest is still MD5_K ((DT concat (++CNT)), so we dont need another
|
|
* MD5 operation
|
|
*/
|
|
|
|
/* PRNG_SV <-- (PRNG_SV XOR digest) */
|
|
for( i = 0, p = PRNG_R, q = digest; i < 16; i++ ) *q++ ^= *p++;
|
|
|
|
MD5_Init( &PRNG_CCI_MD5_CONTEXT );
|
|
MD5_Update( &PRNG_CCI_MD5_CONTEXT, PRNG_MD5_K, 16 );
|
|
MD5_Update( &PRNG_CCI_MD5_CONTEXT, (UINT8 *)digest, 16 );
|
|
MD5_Update( &PRNG_CCI_MD5_CONTEXT, PRNG_MD5_K, 16 );
|
|
MD5_Final( PRNG_SV, &PRNG_CCI_MD5_CONTEXT );
|
|
|
|
/* now we have another 16 bytes of usable R */
|
|
PRNG_N = 16;
|
|
}
|
|
|
|
/*
|
|
* seed the prng
|
|
*/
|
|
static void prng_seed( UINT32 seedSize, UINT8 *seedvalues )
|
|
{
|
|
if( seedSize <= PRNG_SEEDBYTES_NEEDED )
|
|
{
|
|
MD5_Init( &PRNG_CCI_MD5_CONTEXT );
|
|
MD5_Update( &PRNG_CCI_MD5_CONTEXT, PRNG_MAGIC1, 16 );
|
|
if( seedSize > 0 ) MD5_Update( &PRNG_CCI_MD5_CONTEXT, seedvalues, seedSize );
|
|
MD5_Update( &PRNG_CCI_MD5_CONTEXT, PRNG_MAGIC1, 16 );
|
|
MD5_Final( PRNG_MD5_K, &PRNG_CCI_MD5_CONTEXT );
|
|
|
|
MD5_Init( &PRNG_CCI_MD5_CONTEXT );
|
|
MD5_Update( &PRNG_CCI_MD5_CONTEXT, PRNG_MAGIC2, 16 );
|
|
MD5_Update( &PRNG_CCI_MD5_CONTEXT, seedvalues, seedSize );
|
|
MD5_Update( &PRNG_CCI_MD5_CONTEXT, PRNG_MAGIC2, 16 );
|
|
MD5_Final( PRNG_SV, &PRNG_CCI_MD5_CONTEXT );
|
|
|
|
memcpy( &PRNG_CNT, seedvalues, 4 );
|
|
}
|
|
else
|
|
{
|
|
memcpy( PRNG_SV, seedvalues, 16 );
|
|
memcpy( PRNG_MD5_K, seedvalues + 16, 16 );
|
|
memcpy( &PRNG_CNT, seedvalues, 4 );
|
|
}
|
|
|
|
PRNG_DT = randomTime();
|
|
PRNG_N = PRNG_INJIDX = 0;
|
|
prng_iterate(); /* kick start the PRNG */
|
|
}
|
|
|
|
/*
|
|
* Initialize the prng system. This involves calling out for seed bytes. 32
|
|
* of them, in fact.
|
|
*/
|
|
static void prng_init( void )
|
|
{
|
|
UINT8 seedvalues[PRNG_SEEDBYTES_NEEDED];
|
|
unsigned int seedSize;
|
|
|
|
memset( seedvalues, 0, PRNG_SEEDBYTES_NEEDED );
|
|
seedSize = glue_seed_prng( seedvalues, PRNG_SEEDBYTES_NEEDED );
|
|
prng_seed( seedSize, seedvalues );
|
|
}
|
|
|
|
/*
|
|
* hand back a "random" byte
|
|
*/
|
|
static UINT8 prng_random8( void )
|
|
{
|
|
if( !PRNG_N ) prng_iterate();
|
|
|
|
return PRNG_R[--PRNG_N];
|
|
}
|
|
|
|
/*
|
|
* fill up a buffer with "random" bytes
|
|
*/
|
|
static void prng_random( UINT8 *buf, UINT32 N )
|
|
{
|
|
while( N-- ) *buf++ = prng_random8();
|
|
}
|
|
|
|
/*************************************************************************************************
|
|
* Method Name: dot11RandNum
|
|
* Description: Fill buffer with random numbers.
|
|
*
|
|
* Parameters:
|
|
*
|
|
* < *buffer > -
|
|
* < byteCount > -
|
|
*
|
|
* Returns: void - No value returned.
|
|
*
|
|
**************************************************************************************************/
|
|
void dot11RandNum(UINT8 *buffer, UINT32 byteCount)
|
|
{
|
|
semTake(defaultMtx, WAIT_FOREVER);
|
|
prng_random( buffer, byteCount );
|
|
semGive(defaultMtx);
|
|
}
|
|
|
|
/*************************************************************************************************
|
|
* Method Name: dot11RandNumInit
|
|
* Description: Initialize the dot11RandLib
|
|
*
|
|
**************************************************************************************************/
|
|
void dot11RandNumInit(void)
|
|
{
|
|
defaultMtx = semBCreate(SEM_Q_FIFO, SEM_FULL);
|
|
|
|
prng_init();
|
|
}
|