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