Files
m241Neelima/vxworks-6.9/target/src/drv/wlan/dot11RandLib.c
T
2026-07-30 11:19:44 +05:30

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();
}