1 //
2 //! \file  libecc/rng.h
3 //! \brief Random number generator.
4 //!
5 //! This header file declares <code>class libecc::rng</code>, a pseudo random number generator.
6 //
7 // This file is part of the libecc package.
8 // Copyright (C) 2002, by
9 //
10 // Carlo Wood, Run on IRC <carlo@alinoe.com>
11 // RSA-1024 0x624ACAD5 1997-01-26                    Sign & Encrypt
12 // Fingerprint16 = 32 EC A7 B6 AC DB 65 A6  F6 F6 55 DD 1C DC FF 61
13 //
14 // This program is free software; you can redistribute it and/or
15 // modify it under the terms of the GNU General Public License
16 // as published by the Free Software Foundation; either version 2
17 // of the License, or (at your option) any later version.
18 //
19 // This program is distributed in the hope that it will be useful,
20 // but WITHOUT ANY WARRANTY; without even the implied warranty of
21 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
22 // GNU General Public License for more details.
23 //
24 // You should have received a copy of the GNU General Public License
25 // along with this program; if not, write to the Free Software
26 // Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
27 //
28 
29 #ifndef LIBECC_RNG_H
30 #define LIBECC_RNG_H
31 
32 #include <libecc/bitset.h>
33 
34 namespace libecc {
35 
36 class rng {
37   public:
38     static unsigned int const S_pool_size = 521;		//!< Pool size in bits.  This RNG uses a pool of 521 bits.
39 
40   private:
41     uint32_t M_pool[S_pool_size / 32 + 1];
42     bitset<512> M_out;
43     unsigned int M_out_cnt;
44 
45     class bit_iterator {
46       private:
47 	uint32_t* M_ptr;
48 	uint32_t M_head_mask;
49       public:
bit_iterator(uint32_t * pool,int bit)50 	bit_iterator(uint32_t* pool, int bit) : M_ptr(pool + bit / 32), M_head_mask(1 << bit % 32) { }
toggle(void)51 	void toggle(void) const { *M_ptr ^= M_head_mask; }
set(void)52 	void set(void) { *M_ptr |= M_head_mask; }
clear(void)53 	void clear(void) { *M_ptr &= ~M_head_mask; }
increment_and_test(uint32_t * pool)54 	uint32_t increment_and_test(uint32_t* pool)
55 	{
56 	  M_head_mask <<= 1;
57 	  if (M_head_mask == 0)
58 	  {
59 	    M_head_mask = 1;
60 	    ++M_ptr;
61 	  }
62 	  else if (M_head_mask == (1 << (S_pool_size % 32)) && M_ptr - pool == S_pool_size / 32)
63 	  {
64 	    M_ptr = pool;
65 	    M_head_mask = 1;
66 	  }
67 	  return (*M_ptr & M_head_mask);
68 	}
69     };
70 
71     uint32_t* M_entropy_ptr;
72     uint32_t const* M_entropy_ptr_end;
73 
74     bit_iterator M_head;
75     bit_iterator M_fbp1;
76     bit_iterator M_fbp2;
77     bit_iterator M_fbp3;
78     bit_iterator M_fbp4;
79     bit_iterator M_fbp5;
80     bit_iterator M_fbp6;
81     bit_iterator M_fbp7;
82     bit_iterator M_fbp8;
83     bit_iterator M_fbp9;
84 
85   public:
86     /**
87      * \brief The type of the constructor argument.
88      */
89     typedef bitset<S_pool_size> pool_type;
90     rng(pool_type const& seed);
91 
92     void generate_512_bits(void);
93     /** \brief Retrieve a reference to the 512 bits that were generated with a call to rng::generate_512_bits(). */
get_512_bits(void)94     bitset<512> const& get_512_bits(void) const { return M_out; }
95 
96     void add_entropy(uint32_t const* noise, unsigned int number_of_ints);
97 
98     /**
99      * \brief Add entropy from a bitset.
100      *
101      * Calls <code>add_entropy(uint32_t const*, unsigned int)</code>.
102      */
103     template<unsigned int n>
add_entropy(bitset<n> const noise)104       void add_entropy(bitset<n> const noise)
105       {
106 	add_entropy(reinterpret_cast<uint32_t const*>(noise.digits_ptr()), bitset<n>::digits * sizeof(bitset_digit_t) / 4);
107       }
108 };
109 
110 } // namespace libecc
111 
112 #endif // LIBECC_RNG_H
113