X-Git-Url: https://git.carlh.net/gitweb/?a=blobdiff_plain;f=src%2FKM_prng.cpp;h=031cb3546eb099a604edc2ad98c3460c354c4964;hb=08da7aadab3eb7fd03eae5a9a8038ecf8d05808a;hp=5e3dd48a2107219dca6fb3d2281c0510874e2880;hpb=bfedf725dac9d13f3a02fe69f45c302ab29d2b1e;p=asdcplib.git diff --git a/src/KM_prng.cpp b/src/KM_prng.cpp index 5e3dd48..031cb35 100755 --- a/src/KM_prng.cpp +++ b/src/KM_prng.cpp @@ -1,5 +1,5 @@ /* -Copyright (c) 2006, John Hurst +Copyright (c) 2006-2009, John Hurst All rights reserved. Redistribution and use in source and binary forms, with or without @@ -36,32 +36,16 @@ THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. #include #include #include +#include using namespace Kumu; #ifdef KM_WIN32 - -// make up a byte by sampling the perf counter LSB -static byte_t get_perf_byte() -{ - LARGE_INTEGER ticks; - byte_t retval; - - for ( int i = 0; i < 8; i++ ) - { - QueryPerformanceCounter(&ticks); - retval |= (ticks.LowPart & 0x00000001) << i; - } - - return retval; -} - +# include #else // KM_WIN32 - -#include +# include const char* DEV_URANDOM = "/dev/urandom"; - #endif // KM_WIN32 @@ -91,9 +75,9 @@ public: AutoMutex Lock(m_Lock); #ifdef KM_WIN32 - for ( ui32_t i = 0; i < RNG_KEY_SIZE; i++ ) - rng_key[i] = get_perf_byte(); - + HCRYPTPROV hProvider = 0; + CryptAcquireContext(&hProvider, 0, 0, PROV_RSA_FULL, CRYPT_VERIFYCONTEXT); + CryptGenRandom(hProvider, RNG_KEY_SIZE, rng_key); #else // KM_WIN32 // on POSIX systems we simply read some seed from /dev/urandom FileReader URandom; @@ -152,8 +136,7 @@ public: { byte_t tmp[RNG_BLOCK_SIZE]; AES_encrypt(m_ctr_buf, tmp, &m_Context); - *(ui32_t*)(m_ctr_buf + 12) += 1; - memcpy(buf, tmp, len - gen_count); + memcpy(buf + gen_count, tmp, len - gen_count); } } }; @@ -164,7 +147,7 @@ static h__RNG* s_RNG = 0; //------------------------------------------------------------------------------------------ // -// public interface +// Fortuna public interface Kumu::FortunaRNG::FortunaRNG() { @@ -208,6 +191,76 @@ Kumu::FortunaRNG::FillRandom(Kumu::ByteString& Buffer) return Buffer.Data(); } +//------------------------------------------------------------------------------------------ + +// +// FIPS 186-2 Sec. 3.1 as modified by Change 1, section entitled "General Purpose Random Number Generation" +void +Kumu::Gen_FIPS_186_Value(const byte_t* key, ui32_t key_size, byte_t* out_buf, ui32_t out_buf_len) +{ + byte_t sha_buf[SHA_DIGEST_LENGTH]; + ui32_t const xkey_len = 64; // 512/8 + byte_t xkey[xkey_len]; + BN_CTX* ctx1 = BN_CTX_new(); // used by BN_* functions + assert(ctx1); + + if ( key_size > xkey_len ) + DefaultLogSink().Warn("Key too large for FIPS 186 seed, truncating to 64 bytes.\n"); + + // init key + memset(xkey, 0, xkey_len); + memcpy(xkey, key, xmin(key_size, xkey_len)); + + if ( key_size < SHA_DIGEST_LENGTH ) + key_size = SHA_DIGEST_LENGTH; // pad short key ( b < 160 ) + + // create the 2^b constant + BIGNUM c_2powb, c_2, c_b; + BN_init(&c_2powb); BN_init(&c_2); BN_init(&c_b); + BN_set_word(&c_2, 2); + BN_set_word(&c_b, key_size * 8); + BN_exp(&c_2powb, &c_2, &c_b, ctx1); + + for (;;) + { + SHA_CTX SHA; + + // step c -- x = G(t,xkey) + SHA1_Init(&SHA); // set t + SHA1_Update(&SHA, xkey, xkey_len); + + ui32_t* buf_p = (ui32_t*)sha_buf; + *buf_p++ = KM_i32_BE(SHA.h0); + *buf_p++ = KM_i32_BE(SHA.h1); + *buf_p++ = KM_i32_BE(SHA.h2); + *buf_p++ = KM_i32_BE(SHA.h3); + *buf_p++ = KM_i32_BE(SHA.h4); + memcpy(out_buf, sha_buf, xmin(out_buf_len, SHA_DIGEST_LENGTH)); + + if ( out_buf_len <= SHA_DIGEST_LENGTH ) + break; + + out_buf_len -= SHA_DIGEST_LENGTH; + out_buf += SHA_DIGEST_LENGTH; + + // step d -- XKEY = (1 + XKEY + x) mod 2^b + BIGNUM bn_tmp, bn_xkey, bn_x_n; + BN_init(&bn_tmp); BN_init(&bn_xkey); BN_init(&bn_x_n); + + BN_bin2bn(xkey, key_size, &bn_xkey); + BN_bin2bn(sha_buf, SHA_DIGEST_LENGTH, &bn_x_n); + BN_add_word(&bn_xkey, 1); // xkey += 1 + BN_add(&bn_tmp, &bn_xkey, &bn_x_n); // xkey += x + BN_mod(&bn_xkey, &bn_tmp, &c_2powb, ctx1); // xkey = xkey mod (2^b) + + memset(xkey, 0, xkey_len); + ui32_t bn_buf_len = BN_num_bytes(&bn_xkey); + ui32_t idx = ( bn_buf_len < key_size ) ? key_size - bn_buf_len : 0; + BN_bn2bin(&bn_xkey, &xkey[idx]); + } + + BN_CTX_free(ctx1); +} // // end KM_prng.cpp