1 
2 /***************************************************************************
3                                                                            *
4 Copyright 2012 CertiVox IOM Ltd.                                           *
5                                                                            *
6 This file is part of CertiVox MIRACL Crypto SDK.                           *
7                                                                            *
8 The CertiVox MIRACL Crypto SDK provides developers with an                 *
9 extensive and efficient set of cryptographic functions.                    *
10 For further information about its features and functionalities please      *
11 refer to http://www.certivox.com                                           *
12                                                                            *
13 * The CertiVox MIRACL Crypto SDK is free software: you can                 *
14   redistribute it and/or modify it under the terms of the                  *
15   GNU Affero General Public License as published by the                    *
16   Free Software Foundation, either version 3 of the License,               *
17   or (at your option) any later version.                                   *
18                                                                            *
19 * The CertiVox MIRACL Crypto SDK is distributed in the hope                *
20   that it will be useful, but WITHOUT ANY WARRANTY; without even the       *
21   implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. *
22   See the GNU Affero General Public License for more details.              *
23                                                                            *
24 * You should have received a copy of the GNU Affero General Public         *
25   License along with CertiVox MIRACL Crypto SDK.                           *
26   If not, see <http://www.gnu.org/licenses/>.                              *
27                                                                            *
28 You can be released from the requirements of the license by purchasing     *
29 a commercial license. Buying such a license is mandatory as soon as you    *
30 develop commercial activities involving the CertiVox MIRACL Crypto SDK     *
31 without disclosing the source code of your own applications, or shipping   *
32 the CertiVox MIRACL Crypto SDK with a closed source product.               *
33                                                                            *
34 ***************************************************************************/
35 /*
36  *   MIRACL cryptographic strong random number generator
37  *   mrstrong.c
38  *
39  *   Unguessable seed -> SHA -> PRNG internal state -> SHA -> random numbers
40  *   Slow - but secure
41  *
42  *   See ftp://ftp.rsasecurity.com/pub/pdfs/bull-1.pdf for a justification
43  */
44 
45 #include "miracl.h"
46 
47 #ifndef MR_NO_RAND
48 
sbrand(csprng * rng)49 static mr_unsign32 sbrand(csprng *rng)
50 { /* Marsaglia & Zaman random number generator */
51     int i,k;
52     mr_unsign32 pdiff,t;
53     rng->rndptr++;
54     if (rng->rndptr<NK) return rng->ira[rng->rndptr];
55     rng->rndptr=0;
56     for (i=0,k=NK-NJ;i<NK;i++,k++)
57     { /* calculate next NK values */
58         if (k==NK) k=0;
59         t=rng->ira[k];
60         pdiff=t - rng->ira[i] - rng->borrow;
61         if (pdiff<t) rng->borrow=0;
62         if (pdiff>t) rng->borrow=1;
63         rng->ira[i]=pdiff;
64     }
65     return rng->ira[0];
66 }
67 
sirand(csprng * rng,mr_unsign32 seed)68 static void sirand(csprng* rng,mr_unsign32 seed)
69 { /* initialise random number system */
70   /* modified so that a subsequent call "stirs" in another seed value */
71   /* in this way as many seed bits as desired may be used */
72     int i,in;
73     mr_unsign32 t,m=1L;
74     rng->borrow=0L;
75     rng->rndptr=0;
76     rng->ira[0]^=seed;
77     for (i=1;i<NK;i++)
78     { /* fill initialisation vector */
79         in=(NV*i)%NK;
80         rng->ira[in]^=m;      /* note XOR */
81         t=m;
82         m=seed-m;
83         seed=t;
84     }
85     for (i=0;i<10000;i++) sbrand(rng ); /* "warm-up" & stir the generator */
86 }
87 
fill_pool(csprng * rng)88 static void fill_pool(csprng *rng)
89 { /* hash down output of RNG to re-fill the pool */
90     int i;
91     sha256 sh;
92     shs256_init(&sh);
93     for (i=0;i<128;i++) shs256_process(&sh,sbrand(rng));
94     shs256_hash(&sh,rng->pool);
95     rng->pool_ptr=0;
96 }
97 
strong_init(csprng * rng,int rawlen,char * raw,mr_unsign32 tod)98 void strong_init(csprng *rng,int rawlen,char *raw,mr_unsign32 tod)
99 { /* initialise from at least 128 byte string of raw  *
100    * random (keyboard?) input, and 32-bit time-of-day */
101     int i;
102     mr_unsign32 hash[MR_HASH_BYTES/4];
103     sha256 sh;
104     rng->pool_ptr=0;
105     for (i=0;i<NK;i++) rng->ira[i]=0;
106     if (rawlen>0)
107     {
108         shs256_init(&sh);
109         for (i=0;i<rawlen;i++)
110             shs256_process(&sh,raw[i]);
111         shs256_hash(&sh,(char *)hash);
112 
113 /* initialise PRNG from distilled randomness */
114 
115         for (i=0;i<MR_HASH_BYTES/4;i++) sirand(rng,hash[i]);
116     }
117     sirand(rng,tod);
118 
119     fill_pool(rng);
120 }
121 
strong_kill(csprng * rng)122 void strong_kill(csprng *rng)
123 { /* kill internal state */
124     int i;
125     rng->pool_ptr=rng->rndptr=0;
126     for (i=0;i<MR_HASH_BYTES;i++) rng->pool[i]=0;
127     for (i=0;i<NK;i++) rng->ira[i]=0;
128     rng->borrow=0;
129 }
130 
131 /* get random byte */
132 
strong_rng(csprng * rng)133 int strong_rng(csprng *rng)
134 {
135     int r;
136     r=rng->pool[rng->pool_ptr++];
137     if (rng->pool_ptr>=MR_HASH_BYTES) fill_pool(rng);
138     return r;
139 }
140 
strong_bigrand(_MIPD_ csprng * rng,big w,big x)141 void strong_bigrand(_MIPD_ csprng *rng,big w,big x)
142 {
143 	int i, m;
144 	mr_small r;
145     unsigned int ran;
146     unsigned int ch;
147 
148 #ifdef MR_OS_THREADS
149     miracl *mr_mip=get_mip();
150 #endif
151     if (mr_mip->ERNUM) return;
152     MR_IN(20)
153 
154 	m = 0;
155     zero(mr_mip->w1);
156 
157     do
158     {
159 		m++;
160 		mr_mip->w1->len=m;
161 		for (r = 0, i = 0; i < sizeof(mr_small); i++) {
162 			ch=(unsigned char)strong_rng(rng);
163 			ran=ch;
164 			r = (r << 8) ^ ran;
165 		}
166         if (mr_mip->base==0) mr_mip->w1->w[m-1]=r;
167         else                 mr_mip->w1->w[m-1]=MR_REMAIN(r,mr_mip->base);
168     } while (mr_compare(mr_mip->w1,w)<0);
169 	mr_lzero(mr_mip->w1);
170     divide(_MIPP_ mr_mip->w1,w,w);
171 
172     copy(mr_mip->w1,x);
173     MR_OUT
174 }
175 
strong_bigdig(_MIPD_ csprng * rng,int n,int b,big x)176 void strong_bigdig(_MIPD_ csprng *rng,int n,int b,big x)
177 { /* generate random number n digits long *
178    * to "printable" base b                */
179 #ifdef MR_OS_THREADS
180     miracl *mr_mip=get_mip();
181 #endif
182     if (mr_mip->ERNUM) return;
183 
184     MR_IN(19)
185 
186     if (b<2 || b>256)
187     {
188         mr_berror(_MIPP_ MR_ERR_BASE_TOO_BIG);
189         MR_OUT
190         return;
191     }
192 
193     do
194     { /* repeat if x too small */
195         expint(_MIPP_ b,n,mr_mip->w2);
196         strong_bigrand(_MIPP_ rng,mr_mip->w2,x);
197         subdiv(_MIPP_ mr_mip->w2,b,mr_mip->w2);
198     } while (!mr_mip->ERNUM && mr_compare(x,mr_mip->w2)<0);
199 
200     MR_OUT
201 }
202 
203 #endif
204 
205 /* test main program
206 
207 #include <stdio.h>
208 #include "miracl.h"
209 #include <time.h>
210 
211 void main()
212 {
213     int i;
214     char raw[256];
215     big x,w;
216     time_t seed;
217     csprng rng;
218     miracl *mip=mirsys(200,256);
219     x=mirvar(0);
220     w=mirvar(0);
221     printf("Enter Raw random string= ");
222     scanf("%s",raw);
223     getchar();
224     time(&seed);
225     strong_init(&rng,strlen(raw),raw,(long)seed);
226     mip->IOBASE=16;
227     expint(2,256,w);
228     cotnum(w,stdout);
229     for (i=0;i<20;i++)
230     {
231         strong_bigrand(&rng,w,x);
232         cotnum(x,stdout);
233     }
234     printf("\n");
235     for (i=0;i<20;i++)
236     {
237         strong_bigdig(&rng,128,2,x);
238         cotnum(x,stdout);
239     }
240 }
241 
242 */
243 
244