diff options
-rw-r--r-- | doc/credits.txt | 9 | ||||
-rw-r--r-- | doc/license.txt | 2 | ||||
-rw-r--r-- | include/sha1prng.h | 2 | ||||
-rw-r--r-- | src/sha1prng.cpp | 167 |
4 files changed, 177 insertions, 3 deletions
diff --git a/doc/credits.txt b/doc/credits.txt index 67a64539c..cdf6a2bba 100644 --- a/doc/credits.txt +++ b/doc/credits.txt @@ -17,6 +17,11 @@ D: Binary file I/O support, allocator fixes N: Hany Greiss D: Windows porting +N: Manuel Hartl +W: http://www.flexsecure.de/ +D: SHA1PRNG + N: Yves Jerschow D: Optimizations for memory load/store and HMAC @@ -32,13 +37,13 @@ D: Bzip2 compression module S: Colorado, USA N: Justin Karneges -D: The Qt-related modules, X.509 API design +D: Qt support modules (mutexes and types), X.509 API design N: Jack Lloyd W: http://www.randombit.net/ P: 3F69 2E64 6D92 3BBE E7AE 9258 5C0F 96E8 4EC1 6D6B -D: Original author +D: Original designer/author, maintainer 2001-current S: New York NY, USA N: Joel Low diff --git a/doc/license.txt b/doc/license.txt index 827bc839b..43cc7decb 100644 --- a/doc/license.txt +++ b/doc/license.txt @@ -5,6 +5,8 @@ Copyright (C) 1999-2008 Jack Lloyd 2005-2006 Matt Johnston 2006 Luca Piccarreta 2007 Yves Jerschow + 2007 FlexSecure GmbH + 2007 Manuel Hartl Redistribution and use in source and binary forms, for any use, with or without modification, is permitted provided that the following conditions are met: diff --git a/include/sha1prng.h b/include/sha1prng.h index e762cf069..0ba2a96a9 100644 --- a/include/sha1prng.h +++ b/include/sha1prng.h @@ -12,7 +12,7 @@ namespace Botan { /************************************************* -* SHA1PRNG (propriery * +* SHA1PRNG * *************************************************/ class SHA1PRNG : public RandomNumberGenerator { diff --git a/src/sha1prng.cpp b/src/sha1prng.cpp new file mode 100644 index 000000000..562b001bd --- /dev/null +++ b/src/sha1prng.cpp @@ -0,0 +1,167 @@ +/************************************************* +* SHA1PRNG Source File * +* (C) 2007 FlexSecure GmbH / Manuel Hartl * +* (C) 2008 Jack Lloyd * +*************************************************/ + +#include <botan/sha1prng.h> +#include <botan/lookup.h> +#include <botan/bit_ops.h> +#include <algorithm> + +namespace Botan { + +/************************************************* +* Generate a buffer of random bytes * +*************************************************/ +void SHA1PRNG::randomize(byte result[], u32bit length) throw(PRNG_Unseeded) + { + if(!is_seeded()) + throw PRNG_Unseeded(name()); + + const u32bit SHA1_BYTES = hash->OUTPUT_LENGTH; + + u32bit resultIndex=0; + /** + * use ramining bytes from buffer for result + */ + if(buf_pos>0) + { + u32bit remainderCountIndex=buf_pos; + unsigned int j = length >= (unsigned)(SHA1_BYTES - buf_pos) ? SHA1_BYTES - buf_pos : length; + + for(;resultIndex < j;resultIndex++) + { + result[resultIndex] = buffer[remainderCountIndex]; + buffer[remainderCountIndex++] = 0; + } + + buf_pos += j; + } + + /** + * fill result with fresh random bytes + */ + while(resultIndex < length) + { + hash->update(state.begin(),SHA1_BYTES); + hash->final(buffer.begin()); + update_state(buffer.begin()); + int k=length-1 <= SHA1_BYTES ? length : SHA1_BYTES; + for(int j = 0;j < k; j++) + { + result[resultIndex++] = buffer[j]; + buffer[j] = 0; + } + buf_pos+=k; + } + buf_pos %=SHA1_BYTES; + } + +/************************************************* +* Refill the internal state * +*************************************************/ +void SHA1PRNG::update_state(byte update[]) + { + signed int i = 1; + bool flag2 = false; + + for(u32bit k = 0; k < state.size(); k++) + { + int b1 = state[k]%256; + if(b1>128) + { + b1-=256; + } + + int b2 = update[k]%256; + if(b2>128) + { + b2-=256; + } + int j = b1+b2+i; + if(j>256) + { + j-=256; + } + flag2 |= state.begin()[k] != (byte)j; + state.begin()[k] = (byte)j; + i = j >> 8; + } + + if(!flag2) + { + state[0]++; + } + } + +/************************************************* +* Add entropy to internal state * +*************************************************/ +void SHA1PRNG::add_randomness(const byte data[], u32bit length) + { + prng->add_entropy(data, length); + MemoryVector<byte> for_rand; + for_rand.set(data, length); + + if(prng->is_seeded()) + { + prng->randomize(for_rand, length); + hash->clear(); + hash->update(for_rand,length); + hash->final(state.begin()); + } + } + +/************************************************* +* Check if the RNG is seeded * +*************************************************/ +bool SHA1PRNG::is_seeded() const + { + return prng->is_seeded(); + } + +/************************************************* +* Clear memory of sensitive data * +*************************************************/ +void SHA1PRNG::clear() throw() + { + hash->clear(); + prng->clear(); + } + +/************************************************* +* Return the name of this type * +*************************************************/ +std::string SHA1PRNG::name() const + { + return "SHA1PRNG"; + } + +/************************************************* +* SHA1PRNG Constructor * +*************************************************/ +SHA1PRNG::SHA1PRNG(RandomNumberGenerator* prng_ptr) + { + if(!prng_ptr) + throw Invalid_Argument("SHA1PRNG constructor: NULL prng"); + + hash = get_hash("SHA-1"); + prng = prng_ptr; + + buf_pos = 0; + + state.grow_to(hash->OUTPUT_LENGTH); + buffer.grow_to(hash->OUTPUT_LENGTH); + } + +/************************************************* +* SHA1PRNG Destructor * +*************************************************/ +SHA1PRNG::~SHA1PRNG() + { + delete hash; + delete prng; + } + +} |