Created SILC Crypto Toolkit git repository.
[crypto.git] / lib / silccrypt / silcrng.c
1 /*
2
3   silcrng.c
4
5   Author: Pekka Riikonen <priikone@silcnet.org>
6
7   Copyright (C) 1997 - 2008 Pekka Riikonen
8
9   This program is free software; you can redistribute it and/or modify
10   it under the terms of the GNU General Public License as published by
11   the Free Software Foundation; version 2 of the License.
12
13   This program is distributed in the hope that it will be useful,
14   but WITHOUT ANY WARRANTY; without even the implied warranty of
15   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
16   GNU General Public License for more details.
17
18 */
19 /*
20  * Created: Sun Mar  9 00:09:18 1997
21  *
22  * The original RNG was based on Secure Shell's random number generator
23  * by Tatu Ylönen and was used as reference when programming this RNG.
24  * This RNG has been rewritten twice since the creation.
25  */
26
27 #include "silccrypto.h"
28
29 #ifndef WIN32
30 #ifdef HAVE_GETSID
31 extern pid_t getsid (pid_t __pid);
32 #endif
33
34 #ifdef HAVE_GETPGID
35 extern pid_t getpgid (pid_t __pid);
36 #endif
37 #endif
38
39 #undef SILC_RNG_DEBUG
40 /*#define SILC_RNG_DEBUG*/
41
42 /* Number of states to fetch data from pool. */
43 #define SILC_RNG_STATE_NUM 4
44
45 /* Byte size of the random data pool. */
46 #define SILC_RNG_POOLSIZE (20 * 48)
47
48 static SilcUInt32 silc_rng_get_position(SilcRng rng);
49 static void silc_rng_stir_pool(SilcRng rng);
50 static void silc_rng_xor(SilcRng rng, SilcUInt32 val, unsigned int pos);
51 static void silc_rng_exec_command(SilcRng rng, char *command);
52 static void silc_rng_get_hard_noise(SilcRng rng);
53 static void silc_rng_get_medium_noise(SilcRng rng);
54 static void silc_rng_get_soft_noise(SilcRng rng);
55
56 /*
57    SILC SilcRng State context.
58
59    This object is used by the random number generator to provide
60    variable points where the actual random number is fetched from
61    the random pool. This provides that the data is not fetched always
62    from the same point of the pool. Short description of the fields
63    following.
64
65    SilcUInt32 low
66    SilcUInt32 pos
67
68        The index for the random pool buffer. Lowest and current
69        positions.
70
71    SilcRngStateContext *next
72
73        Pointer to the next state. If this is the last state this
74        will point to the first state thus providing circular list.
75
76 */
77 typedef struct SilcRngStateContext {
78   SilcUInt32 low;
79   SilcUInt32 pos;
80   struct SilcRngStateContext *next;
81 } *SilcRngState;
82
83 /*
84    SILC Random Number Generator object.
85
86    This object holds random pool which is used to generate the random
87    numbers used by various routines needing cryptographically strong
88    random numbers. Following short descriptions of the fields.
89
90    unsigned char pool[]
91
92        The random pool. This buffer holds the random data. This is
93        frequently stirred thus providing ever changing randomnes.
94
95    unsigned char key[64]
96
97        Key used in stirring the random pool. The pool is encrypted
98        with SHA1 hash function in CFB (Cipher Feedback) mode.
99
100    SilcSilcRngState state
101
102        State object that is used to get the next position for the
103        random pool. This position is used to fetch data from pool
104        or to save the data to the pool. The state changes everytime
105        SilcRng is used.
106
107    SilcHash sha1
108
109        Hash object (SHA1) used to make the CFB encryption to the
110        random pool. This is allocated when RNG object is allocated and
111        free'd when RNG object is free'd.
112
113    SilcUInt8 threshold
114
115        Threshold to indicate when it is required to acquire more
116        noise from the environment.  More soft noise is acquired after
117        64 bits of output and hard noise every 160 bits of output.
118
119 */
120 struct SilcRngStruct {
121   unsigned char pool[SILC_RNG_POOLSIZE];
122   unsigned char key[64];
123   SilcRngState state;
124   SilcHash sha1;
125   SilcUInt8 threshold;
126   char *devrandom;
127   int fd_devurandom;
128 };
129
130 /* Allocates new RNG object. */
131
132 SilcRng silc_rng_alloc(void)
133 {
134   SilcRng new;
135
136   SILC_LOG_DEBUG(("Allocating new RNG object"));
137
138   new = silc_calloc(1, sizeof(*new));
139   new->fd_devurandom = -1;
140
141   memset(new->pool, 0, sizeof(new->pool));
142   memset(new->key, 0, sizeof(new->key));
143   new->state = NULL;
144   if (!silc_hash_alloc("sha1", &new->sha1)) {
145     silc_free(new);
146     SILC_LOG_ERROR(("Could not allocate sha1 hash, probably not registered"));
147     return NULL;
148   }
149
150   new->devrandom = strdup("/dev/random");
151
152   return new;
153 }
154
155 /* Free's RNG object. */
156
157 void silc_rng_free(SilcRng rng)
158 {
159   if (rng) {
160     SilcRngState t, n;
161
162     memset(rng->pool, 0, sizeof(rng->pool));
163     memset(rng->key, 0, sizeof(rng->key));
164     silc_hash_free(rng->sha1);
165     silc_free(rng->devrandom);
166
167     if (rng->fd_devurandom != -1)
168       close(rng->fd_devurandom);
169
170     for (t = rng->state->next; t != rng->state; ) {
171       n = t->next;
172       silc_free(t);
173       t = n;
174     }
175     silc_free(rng->state);
176
177     silc_free(rng);
178   }
179 }
180
181 /* Initializes random number generator by getting noise from environment.
182    The environmental noise is our so called seed. One should not call
183    this function more than once. */
184
185 void silc_rng_init(SilcRng rng)
186 {
187   int i;
188   SilcRngState first, next;
189
190   assert(rng != NULL);
191
192   SILC_LOG_DEBUG(("Initializing RNG object"));
193
194   /* Initialize the states for the RNG. */
195   rng->state = silc_calloc(1, sizeof(*rng->state));
196   rng->state->low = 0;
197   rng->state->pos = 8;
198   rng->state->next = NULL;
199   first = rng->state;
200   for (i = SILC_RNG_STATE_NUM - 1; i >= 1; i--) {
201     next = silc_calloc(1, sizeof(*rng->state));
202     next->low =
203       (i * (sizeof(rng->pool) / SILC_RNG_STATE_NUM));
204     next->pos =
205       (i * (sizeof(rng->pool) / SILC_RNG_STATE_NUM)) + 8;
206     next->next = rng->state;
207     rng->state = next;
208   }
209   first->next = next;
210   rng->state = first;
211
212   memset(rng->pool, 0, sizeof(rng->pool));
213
214   /* Get noise from various environmental sources */
215   silc_rng_get_soft_noise(rng);
216   silc_rng_get_medium_noise(rng);
217   silc_rng_get_hard_noise(rng);
218   silc_rng_get_soft_noise(rng);
219   silc_free(rng->devrandom);
220   rng->devrandom = strdup("/dev/urandom");
221 }
222
223 /* This function gets 'soft' noise from environment. */
224
225 static void silc_rng_get_soft_noise(SilcRng rng)
226 {
227 #ifndef SILC_WIN32
228   struct tms ptime;
229 #endif
230   SilcUInt32 pos;
231 #ifdef HAVE_GETRUSAGE
232   struct rusage r;
233 #endif
234
235   pos = silc_rng_get_position(rng);
236
237   silc_rng_xor(rng, clock(), 0);
238 #ifndef SILC_WIN32
239 #ifdef HAVE_GETPID
240   silc_rng_xor(rng, getpid(), 1);
241 #ifdef HAVE_GETPGID
242   silc_rng_xor(rng, getpgid(getpid()) << 8, 2);
243   silc_rng_xor(rng, getpgid(getpid()) << 8, 3);
244 #endif
245 #ifdef HAVE_GETGID
246   silc_rng_xor(rng, getgid(), 4);
247 #endif
248 #endif
249 #ifdef HAVE_GETPGRP
250   silc_rng_xor(rng, getpgrp(), 5);
251 #endif
252 #ifdef HAVE_GETSID
253   silc_rng_xor(rng, getsid(getpid()) << 16, 6);
254 #endif
255 #ifndef SILC_SYMBIAN
256   silc_rng_xor(rng, times(&ptime), 7);
257   silc_rng_xor(rng, ptime.tms_utime, 8);
258   silc_rng_xor(rng, (ptime.tms_utime + ptime.tms_stime), pos++);
259   silc_rng_xor(rng, (ptime.tms_stime + ptime.tms_cutime), pos++);
260   silc_rng_xor(rng, (ptime.tms_utime + ptime.tms_stime), pos++);
261   silc_rng_xor(rng, (ptime.tms_cutime ^ ptime.tms_stime), pos++);
262   silc_rng_xor(rng, (ptime.tms_cutime ^ ptime.tms_cstime), pos++);
263   silc_rng_xor(rng, (ptime.tms_utime ^ ptime.tms_stime), pos++);
264   silc_rng_xor(rng, (ptime.tms_stime ^ ptime.tms_cutime), pos++);
265   silc_rng_xor(rng, (ptime.tms_cutime + ptime.tms_stime), pos++);
266   silc_rng_xor(rng, (ptime.tms_stime << 8), pos++);
267 #endif /* SILC_SYMBIAN */
268 #endif
269   silc_rng_xor(rng, clock() << 4, pos++);
270 #ifndef SILC_WIN32
271 #ifdef HAVE_GETPGID
272   silc_rng_xor(rng, getpgid(getpid()) << 8, pos++);
273 #endif
274 #ifdef HAVE_GETPGRP
275   silc_rng_xor(rng, getpgrp(), pos++);
276 #endif
277 #ifdef HAVE_SETSID
278   silc_rng_xor(rng, getsid(getpid()) << 16, pos++);
279 #endif
280 #ifndef SILC_SYMBIAN
281   silc_rng_xor(rng, times(&ptime), pos++);
282   silc_rng_xor(rng, ptime.tms_utime, pos++);
283 #endif /* SILC_SYMBIAN */
284 #ifdef HAVE_GETPGRP
285   silc_rng_xor(rng, getpgrp(), pos++);
286 #endif
287 #endif
288 #ifdef HAVE_GETRUSAGE
289   getrusage(RUSAGE_SELF, &r);
290   silc_rng_xor(rng, (r.ru_utime.tv_sec + r.ru_utime.tv_usec), pos++);
291   silc_rng_xor(rng, (r.ru_utime.tv_sec ^ r.ru_utime.tv_usec), pos++);
292   silc_rng_xor(rng, (r.ru_stime.tv_sec + r.ru_stime.tv_usec), pos++);
293   silc_rng_xor(rng, (r.ru_stime.tv_sec ^ r.ru_stime.tv_usec), pos++);
294 #ifndef SILC_SYMBIAN
295   silc_rng_xor(rng, (r.ru_maxrss + r.ru_ixrss), pos++);
296   silc_rng_xor(rng, (r.ru_maxrss ^ r.ru_ixrss), pos++);
297   silc_rng_xor(rng, (r.ru_idrss + r.ru_idrss), pos++);
298   silc_rng_xor(rng, (r.ru_idrss ^ r.ru_idrss), pos++);
299   silc_rng_xor(rng, (r.ru_idrss << 16), pos++);
300   silc_rng_xor(rng, (r.ru_minflt + r.ru_majflt), pos++);
301   silc_rng_xor(rng, (r.ru_minflt ^ r.ru_majflt), pos++);
302   silc_rng_xor(rng, (r.ru_nswap + r.ru_oublock + r.ru_inblock), pos++);
303   silc_rng_xor(rng, (r.ru_nswap << 8), pos++);
304   silc_rng_xor(rng, (r.ru_inblock + r.ru_oublock), pos++);
305   silc_rng_xor(rng, (r.ru_inblock ^ r.ru_oublock), pos++);
306   silc_rng_xor(rng, (r.ru_msgsnd ^ r.ru_msgrcv), pos++);
307   silc_rng_xor(rng, (r.ru_nsignals + r.ru_msgsnd + r.ru_msgrcv), pos++);
308   silc_rng_xor(rng, (r.ru_nsignals << 16), pos++);
309   silc_rng_xor(rng, (r.ru_nvcsw + r.ru_nivcsw), pos++);
310   silc_rng_xor(rng, (r.ru_nvcsw ^ r.ru_nivcsw), pos++);
311 #endif /* SILC_SYMBIAN */
312 #endif /* HAVE_GETRUSAGE */
313
314 #ifdef SILC_RNG_DEBUG
315   SILC_LOG_HEXDUMP(("pool"), rng->pool, sizeof(rng->pool));
316 #endif
317
318   /* Stir random pool */
319   silc_rng_stir_pool(rng);
320 }
321
322 /* This function gets noise from different commands */
323
324 static void silc_rng_get_medium_noise(SilcRng rng)
325 {
326   /* If getrusage is available, there is no need for shell commands */
327 #ifdef HAVE_GETRUSAGE
328   return;
329 #endif
330   silc_rng_exec_command(rng, "ps -leaww 2> /dev/null");
331   silc_rng_exec_command(rng, "ls -afiln ~ 2> /dev/null");
332   silc_rng_exec_command(rng, "ls -afiln /proc 2> /dev/null");
333   silc_rng_exec_command(rng, "ps -axww 2> /dev/null");
334
335 #ifdef SILC_RNG_DEBUG
336   SILC_LOG_HEXDUMP(("pool"), rng->pool, sizeof(rng->pool));
337 #endif
338 }
339
340 /* This function gets 'hard' noise from environment. This tries to
341    get the noise from /dev/random if available. */
342
343 static void silc_rng_get_hard_noise(SilcRng rng)
344 {
345 #if defined(SILC_UNIX)
346   unsigned char buf[32];
347   int fd, len, i;
348
349   /* Get noise from /dev/[u]random if available */
350   fd = silc_file_open(rng->devrandom, O_RDONLY);
351   if (fd < 0)
352     return;
353
354   fcntl(fd, F_SETFL, O_NONBLOCK);
355
356   for (i = 0; i < 2; i++) {
357     len = read(fd, buf, sizeof(buf));
358     if (len <= 0)
359       goto out;
360     silc_rng_add_noise(rng, buf, len);
361   }
362
363 #ifdef SILC_RNG_DEBUG
364   SILC_LOG_HEXDUMP(("pool"), rng->pool, sizeof(rng->pool));
365 #endif
366
367  out:
368   silc_file_close(fd);
369   memset(buf, 0, sizeof(buf));
370 #endif
371 }
372
373 /* Execs command and gets noise from its output */
374
375 static void silc_rng_exec_command(SilcRng rng, char *command)
376 {
377 #if defined(SILC_UNIX)
378   unsigned char buf[1024];
379   FILE *fd;
380   int i;
381   int c;
382
383   /* Open process */
384   fd = popen(command, "r");
385   if (!fd)
386     return;
387
388   /* Get data as much as we can get into the buffer */
389   for (i = 0; i < sizeof(buf); i++) {
390     c = fgetc(fd);
391     if (c == EOF)
392       break;
393     buf[i] = c;
394   }
395
396   pclose(fd);
397
398   if (i != 0) {
399     /* Add the buffer into random pool */
400     silc_rng_add_noise(rng, buf, i);
401     memset(buf, 0, sizeof(buf));
402   }
403 #endif
404 }
405
406 /* This function adds the contents of the buffer as noise into random
407    pool. After adding the noise the pool is stirred. */
408
409 void silc_rng_add_noise(SilcRng rng, unsigned char *buffer, SilcUInt32 len)
410 {
411   SilcUInt32 i, pos;
412
413   pos = silc_rng_get_position(rng);
414
415   /* Add the buffer one by one into the pool */
416   for(i = 0; i < len; i++, buffer++) {
417     if(pos >= SILC_RNG_POOLSIZE)
418       break;
419     rng->pool[pos++] ^= *buffer;
420   }
421
422   /* Stir random pool */
423   silc_rng_stir_pool(rng);
424 }
425
426 /* XOR's data into the pool */
427
428 static void silc_rng_xor(SilcRng rng, SilcUInt32 val, unsigned int pos)
429 {
430   SilcUInt32 tmp;
431
432   SILC_GET32_MSB(tmp, &rng->pool[pos]);
433   val ^= tmp + val;
434   SILC_PUT32_MSB(val, &rng->pool[pos]);
435 }
436
437 /* This function stirs the random pool by encrypting buffer in CFB
438    (cipher feedback) mode with SHA1 algorithm. */
439
440 static void silc_rng_stir_pool(SilcRng rng)
441 {
442   int i;
443   SilcUInt32 iv[5], tmp;
444
445   /* Get the IV */
446   SILC_GET32_MSB(iv[0], &rng->pool[16     ]);
447   SILC_GET32_MSB(iv[1], &rng->pool[16 +  4]);
448   SILC_GET32_MSB(iv[2], &rng->pool[16 +  8]);
449   SILC_GET32_MSB(iv[3], &rng->pool[16 + 12]);
450   SILC_GET32_MSB(iv[4], &rng->pool[16 + 16]);
451
452   /* First CFB pass */
453   for (i = 0; i < SILC_RNG_POOLSIZE; i += 20) {
454     silc_hash_transform(rng->sha1, iv, rng->key);
455
456     SILC_GET32_MSB(tmp, &rng->pool[i]);
457     iv[0] ^= tmp;
458     SILC_PUT32_MSB(iv[0], &rng->pool[i]);
459
460     SILC_GET32_MSB(tmp, &rng->pool[i + 4]);
461     iv[1] ^= tmp;
462     SILC_PUT32_MSB(iv[1], &rng->pool[i + 4]);
463
464     SILC_GET32_MSB(tmp, &rng->pool[i + 8]);
465     iv[2] ^= tmp;
466     SILC_PUT32_MSB(iv[2], &rng->pool[i + 8]);
467
468     SILC_GET32_MSB(tmp, &rng->pool[i + 12]);
469     iv[3] ^= tmp;
470     SILC_PUT32_MSB(iv[3], &rng->pool[i + 12]);
471
472     SILC_GET32_MSB(tmp, &rng->pool[i + 16]);
473     iv[4] ^= tmp;
474     SILC_PUT32_MSB(iv[4], &rng->pool[i + 16]);
475   }
476
477   /* Get new key */
478   memcpy(rng->key, &rng->pool[silc_rng_get_position(rng)], sizeof(rng->key));
479
480   /* Second CFB pass */
481   for (i = 0; i < SILC_RNG_POOLSIZE; i += 20) {
482     silc_hash_transform(rng->sha1, iv, rng->key);
483
484     SILC_GET32_MSB(tmp, &rng->pool[i]);
485     iv[0] ^= tmp;
486     SILC_PUT32_MSB(iv[0], &rng->pool[i]);
487
488     SILC_GET32_MSB(tmp, &rng->pool[i + 4]);
489     iv[1] ^= tmp;
490     SILC_PUT32_MSB(iv[1], &rng->pool[i + 4]);
491
492     SILC_GET32_MSB(tmp, &rng->pool[i + 8]);
493     iv[2] ^= tmp;
494     SILC_PUT32_MSB(iv[2], &rng->pool[i + 8]);
495
496     SILC_GET32_MSB(tmp, &rng->pool[i + 12]);
497     iv[3] ^= tmp;
498     SILC_PUT32_MSB(iv[3], &rng->pool[i + 12]);
499
500     SILC_GET32_MSB(tmp, &rng->pool[i + 16]);
501     iv[4] ^= tmp;
502     SILC_PUT32_MSB(iv[4], &rng->pool[i + 16]);
503   }
504
505   memset(iv, 0, sizeof(iv));
506 }
507
508 /* Returns next position where data is fetched from the pool or
509    put to the pool. */
510
511 static SilcUInt32 silc_rng_get_position(SilcRng rng)
512 {
513   SilcRngState next;
514   SilcUInt32 pos;
515
516   next = rng->state->next;
517
518   pos = rng->state->pos++;
519   if ((next->low != 0 && pos >= next->low) || (pos >= SILC_RNG_POOLSIZE))
520     rng->state->pos = rng->state->low;
521
522 #ifdef SILC_RNG_DEBUG
523     fprintf(stderr, "state: %p: low: %lu, pos: %lu\n",
524             rng->state, rng->state->low, rng->state->pos);
525 #endif
526
527   rng->state = next;
528
529   return pos;
530 }
531
532 /* Returns random byte. */
533
534 SilcUInt8 silc_rng_get_byte(SilcRng rng)
535 {
536   SilcUInt8 byte;
537
538   rng->threshold++;
539
540   /* Get more soft noise after 64 bits threshold */
541   if (rng->threshold >= 8)
542     silc_rng_get_soft_noise(rng);
543
544   /* Get hard noise after 160 bits threshold, zero the threshold. */
545   if (rng->threshold >= 20) {
546     rng->threshold = 0;
547     silc_rng_get_hard_noise(rng);
548   }
549
550   do byte = rng->pool[silc_rng_get_position(rng)]; while (byte == 0x00);
551   return byte;
552 }
553
554 /* Return random byte as fast as possible. Reads from /dev/urandom if
555    available. If not then return from normal RNG (not so fast). */
556
557 SilcUInt8 silc_rng_get_byte_fast(SilcRng rng)
558 {
559 #if defined(SILC_UNIX)
560   unsigned char buf[1];
561
562   if (rng->fd_devurandom == -1) {
563     rng->fd_devurandom = open("/dev/urandom", O_RDONLY);
564     if (rng->fd_devurandom < 0)
565       return silc_rng_get_byte(rng);
566     fcntl(rng->fd_devurandom, F_SETFL, O_NONBLOCK);
567   }
568
569   if (read(rng->fd_devurandom, buf, sizeof(buf)) < 0)
570     return silc_rng_get_byte(rng);
571
572   return buf[0] != 0x00 ? buf[0] : silc_rng_get_byte(rng);
573 #else
574   return silc_rng_get_byte(rng);
575 #endif
576 }
577
578 /* Returns 16 bit random number */
579
580 SilcUInt16 silc_rng_get_rn16(SilcRng rng)
581 {
582   unsigned char rn[2];
583   SilcUInt16 num;
584
585   rn[0] = silc_rng_get_byte(rng);
586   rn[1] = silc_rng_get_byte(rng);
587   SILC_GET16_MSB(num, rn);
588
589   return num;
590 }
591
592 /* Returns 32 bit random number */
593
594 SilcUInt32 silc_rng_get_rn32(SilcRng rng)
595 {
596   unsigned char rn[4];
597   SilcUInt32 num;
598
599   rn[0] = silc_rng_get_byte(rng);
600   rn[1] = silc_rng_get_byte(rng);
601   rn[2] = silc_rng_get_byte(rng);
602   rn[3] = silc_rng_get_byte(rng);
603   SILC_GET32_MSB(num, rn);
604
605   return num;
606 }
607
608 /* Returns non-zero random number string. Returned string is in HEX format. */
609
610 unsigned char *silc_rng_get_rn_string(SilcRng rng, SilcUInt32 len)
611 {
612   int i;
613   unsigned char *string;
614
615   string = silc_calloc((len * 2 + 1), sizeof(unsigned char));
616
617   for (i = 0; i < len; i++)
618     sprintf(string + 2 * i, "%02x", silc_rng_get_byte(rng));
619
620   return string;
621 }
622
623 /* Returns non-zero random number binary data. */
624
625 SilcBool silc_rng_get_rn_data(SilcRng rng, SilcUInt32 len, unsigned char *buf,
626                               SilcUInt32 buf_size)
627 {
628   int i;
629
630   if (len > buf_size)
631     return FALSE;
632
633   for (i = 0; i < len; i++)
634     buf[i] = silc_rng_get_byte(rng);
635
636   return TRUE;
637 }
638
639 /* Global RNG. This is global RNG that application can initialize so
640    that any part of code anywhere can use RNG without having to allocate
641    new RNG object everytime.  If this is not initialized then these routines
642    will fail.  Note: currently in SILC applications always initialize this. */
643
644 SilcRng global_rng = NULL;
645
646 /* Initialize global RNG. If `rng' is provided it is set as the global
647    RNG object (it can be allocated by the application for example). */
648
649 SilcBool silc_rng_global_init(SilcRng rng)
650 {
651   if (rng) {
652     global_rng = rng;
653     return TRUE;
654   }
655
656   global_rng = silc_rng_alloc();
657   silc_rng_init(global_rng);
658
659   return TRUE;
660 }
661
662 /* Uninitialize global RNG */
663
664 SilcBool silc_rng_global_uninit(void)
665 {
666   if (global_rng) {
667     silc_rng_free(global_rng);
668     global_rng = NULL;
669   }
670
671   return TRUE;
672 }
673
674 /* These are analogous to the functions above. */
675
676 SilcUInt8 silc_rng_global_get_byte(void)
677 {
678   return global_rng ? silc_rng_get_byte(global_rng) : 0;
679 }
680
681 /* Return random byte as fast as possible. Reads from /dev/urandom if
682    available. If not then return from normal RNG (not so fast). */
683
684 SilcUInt8 silc_rng_global_get_byte_fast(void)
685 {
686   return global_rng ? silc_rng_get_byte_fast(global_rng) : 0;
687 }
688
689 SilcUInt16 silc_rng_global_get_rn16(void)
690 {
691   return global_rng ? silc_rng_get_rn16(global_rng) : 0;
692 }
693
694 SilcUInt32 silc_rng_global_get_rn32(void)
695 {
696   return global_rng ? silc_rng_get_rn32(global_rng) : 0;
697 }
698
699 unsigned char *silc_rng_global_get_rn_string(SilcUInt32 len)
700 {
701   return global_rng ? silc_rng_get_rn_string(global_rng, len) : NULL;
702 }
703
704 SilcBool silc_rng_global_get_rn_data(SilcRng rng, SilcUInt32 len,
705                                      unsigned char *buf, SilcUInt32 buf_size)
706 {
707   return global_rng ? silc_rng_get_rn_data(global_rng, len, buf,
708                                            buf_size) : FALSE;
709 }
710
711 void silc_rng_global_add_noise(unsigned char *buffer, SilcUInt32 len)
712 {
713   if (global_rng)
714     silc_rng_add_noise(global_rng, buffer, len);
715 }