Static analyzer bug fixes
[silc.git] / lib / silccrypt / silcrng.c
1 /*
2
3   silcrng.c
4
5   Author: Pekka Riikonen <priikone@silcnet.org>
6
7   Copyright (C) 1997 - 2014 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   if (!new->devrandom) {
153     silc_rng_free(new);
154     return NULL;
155   }
156
157   return new;
158 }
159
160 /* Free's RNG object. */
161
162 void silc_rng_free(SilcRng rng)
163 {
164   if (rng) {
165     SilcRngState t, n;
166
167     memset(rng->pool, 0, sizeof(rng->pool));
168     memset(rng->key, 0, sizeof(rng->key));
169     silc_hash_free(rng->sha1);
170     silc_free(rng->devrandom);
171
172     if (rng->fd_devurandom != -1)
173       close(rng->fd_devurandom);
174
175     for (t = rng->state->next; t != rng->state; ) {
176       n = t->next;
177       silc_free(t);
178       t = n;
179     }
180     silc_free(rng->state);
181
182     silc_free(rng);
183   }
184 }
185
186 /* Initializes random number generator by getting noise from environment.
187    The environmental noise is our so called seed. One should not call
188    this function more than once. */
189
190 void silc_rng_init(SilcRng rng)
191 {
192   int i;
193   SilcRngState first, next;
194
195   assert(rng != NULL);
196
197   SILC_LOG_DEBUG(("Initializing RNG object"));
198
199   /* Initialize the states for the RNG. */
200   rng->state = silc_calloc(1, sizeof(*rng->state));
201   if (!rng->state) {
202     SILC_LOG_ERROR(("Error allocating memory for RNG"));
203     return;
204   }
205   rng->state->low = 0;
206   rng->state->pos = 8;
207   rng->state->next = NULL;
208   first = rng->state;
209   for (i = SILC_RNG_STATE_NUM - 1; i >= 1; i--) {
210     next = silc_calloc(1, sizeof(*rng->state));
211     if (!next) {
212       SILC_LOG_ERROR(("Error allocating memory for RNG"));
213       return;
214     }
215     next->low =
216       (i * (sizeof(rng->pool) / SILC_RNG_STATE_NUM));
217     next->pos =
218       (i * (sizeof(rng->pool) / SILC_RNG_STATE_NUM)) + 8;
219     next->next = rng->state;
220     rng->state = next;
221   }
222   first->next = next;
223   rng->state = first;
224
225   memset(rng->pool, 0, sizeof(rng->pool));
226
227   /* Get noise from various environmental sources */
228   silc_rng_get_soft_noise(rng);
229   silc_rng_get_medium_noise(rng);
230   silc_rng_get_hard_noise(rng);
231   silc_rng_get_soft_noise(rng);
232   silc_free(rng->devrandom);
233   rng->devrandom = strdup("/dev/urandom");
234 }
235
236 /* This function gets 'soft' noise from environment. */
237
238 static void silc_rng_get_soft_noise(SilcRng rng)
239 {
240 #ifndef SILC_WIN32
241   struct tms ptime;
242 #endif
243   SilcUInt32 pos;
244 #ifdef HAVE_GETRUSAGE
245   struct rusage r;
246 #endif
247
248   pos = silc_rng_get_position(rng);
249
250   silc_rng_xor(rng, clock(), 0);
251 #ifndef SILC_WIN32
252 #ifdef HAVE_GETPID
253   silc_rng_xor(rng, getpid(), 1);
254 #ifdef HAVE_GETPGID
255   silc_rng_xor(rng, getpgid(getpid()) << 8, 2);
256   silc_rng_xor(rng, getpgid(getpid()) << 8, 3);
257 #endif
258 #ifdef HAVE_GETGID
259   silc_rng_xor(rng, getgid(), 4);
260 #endif
261 #endif
262 #ifdef HAVE_GETPGRP
263   silc_rng_xor(rng, getpgrp(), 5);
264 #endif
265 #ifdef HAVE_GETSID
266   silc_rng_xor(rng, getsid(getpid()) << 16, 6);
267 #endif
268 #ifndef SILC_SYMBIAN
269   silc_rng_xor(rng, times(&ptime), 7);
270   silc_rng_xor(rng, ptime.tms_utime, 8);
271   silc_rng_xor(rng, (ptime.tms_utime + ptime.tms_stime), pos++);
272   silc_rng_xor(rng, (ptime.tms_stime + ptime.tms_cutime), pos++);
273   silc_rng_xor(rng, (ptime.tms_utime + ptime.tms_stime), pos++);
274   silc_rng_xor(rng, (ptime.tms_cutime ^ ptime.tms_stime), pos++);
275   silc_rng_xor(rng, (ptime.tms_cutime ^ ptime.tms_cstime), pos++);
276   silc_rng_xor(rng, (ptime.tms_utime ^ ptime.tms_stime), pos++);
277   silc_rng_xor(rng, (ptime.tms_stime ^ ptime.tms_cutime), pos++);
278   silc_rng_xor(rng, (ptime.tms_cutime + ptime.tms_stime), pos++);
279   silc_rng_xor(rng, (ptime.tms_stime << 8), pos++);
280 #endif /* SILC_SYMBIAN */
281 #endif
282   silc_rng_xor(rng, clock() << 4, pos++);
283 #ifndef SILC_WIN32
284 #ifdef HAVE_GETPGID
285   silc_rng_xor(rng, getpgid(getpid()) << 8, pos++);
286 #endif
287 #ifdef HAVE_GETPGRP
288   silc_rng_xor(rng, getpgrp(), pos++);
289 #endif
290 #ifdef HAVE_SETSID
291   silc_rng_xor(rng, getsid(getpid()) << 16, pos++);
292 #endif
293 #ifndef SILC_SYMBIAN
294   silc_rng_xor(rng, times(&ptime), pos++);
295   silc_rng_xor(rng, ptime.tms_utime, pos++);
296 #endif /* SILC_SYMBIAN */
297 #ifdef HAVE_GETPGRP
298   silc_rng_xor(rng, getpgrp(), pos++);
299 #endif
300 #endif
301 #ifdef HAVE_GETRUSAGE
302   getrusage(RUSAGE_SELF, &r);
303   silc_rng_xor(rng, (r.ru_utime.tv_sec + r.ru_utime.tv_usec), pos++);
304   silc_rng_xor(rng, (r.ru_utime.tv_sec ^ r.ru_utime.tv_usec), pos++);
305   silc_rng_xor(rng, (r.ru_stime.tv_sec + r.ru_stime.tv_usec), pos++);
306   silc_rng_xor(rng, (r.ru_stime.tv_sec ^ r.ru_stime.tv_usec), pos++);
307 #ifndef SILC_SYMBIAN
308   silc_rng_xor(rng, (r.ru_maxrss + r.ru_ixrss), pos++);
309   silc_rng_xor(rng, (r.ru_maxrss ^ r.ru_ixrss), pos++);
310   silc_rng_xor(rng, (r.ru_idrss + r.ru_idrss), pos++);
311   silc_rng_xor(rng, (r.ru_idrss ^ r.ru_idrss), pos++);
312   silc_rng_xor(rng, (r.ru_idrss << 16), pos++);
313   silc_rng_xor(rng, (r.ru_minflt + r.ru_majflt), pos++);
314   silc_rng_xor(rng, (r.ru_minflt ^ r.ru_majflt), pos++);
315   silc_rng_xor(rng, (r.ru_nswap + r.ru_oublock + r.ru_inblock), pos++);
316   silc_rng_xor(rng, (r.ru_nswap << 8), pos++);
317   silc_rng_xor(rng, (r.ru_inblock + r.ru_oublock), pos++);
318   silc_rng_xor(rng, (r.ru_inblock ^ r.ru_oublock), pos++);
319   silc_rng_xor(rng, (r.ru_msgsnd ^ r.ru_msgrcv), pos++);
320   silc_rng_xor(rng, (r.ru_nsignals + r.ru_msgsnd + r.ru_msgrcv), pos++);
321   silc_rng_xor(rng, (r.ru_nsignals << 16), pos++);
322   silc_rng_xor(rng, (r.ru_nvcsw + r.ru_nivcsw), pos++);
323   silc_rng_xor(rng, (r.ru_nvcsw ^ r.ru_nivcsw), pos++);
324 #endif /* SILC_SYMBIAN */
325 #endif /* HAVE_GETRUSAGE */
326   
327 #ifdef SILC_RNG_DEBUG
328   SILC_LOG_HEXDUMP(("pool"), rng->pool, sizeof(rng->pool));
329 #endif
330
331   /* Stir random pool */
332   silc_rng_stir_pool(rng);
333 }
334
335 /* This function gets noise from different commands */
336
337 static void silc_rng_get_medium_noise(SilcRng rng)
338 {
339   /* If getrusage is available, there is no need for shell commands */
340 #ifdef HAVE_GETRUSAGE
341   return;
342 #endif
343   silc_rng_exec_command(rng, "ps -leaww 2> /dev/null");
344   silc_rng_exec_command(rng, "ls -afiln ~ 2> /dev/null");
345   silc_rng_exec_command(rng, "ls -afiln /proc 2> /dev/null");
346   silc_rng_exec_command(rng, "ps -axww 2> /dev/null");
347
348 #ifdef SILC_RNG_DEBUG
349   SILC_LOG_HEXDUMP(("pool"), rng->pool, sizeof(rng->pool));
350 #endif
351 }
352
353 /* This function gets 'hard' noise from environment. This tries to
354    get the noise from /dev/random if available. */
355
356 static void silc_rng_get_hard_noise(SilcRng rng)
357 {
358 #if defined(SILC_UNIX)
359   unsigned char buf[32];
360   int fd, len, i;
361
362   /* Get noise from /dev/[u]random if available */
363   fd = open(rng->devrandom, O_RDONLY);
364   if (fd < 0)
365     return;
366
367   fcntl(fd, F_SETFL, O_NONBLOCK);
368
369   for (i = 0; i < 2; i++) {
370     len = read(fd, buf, sizeof(buf));
371     if (len <= 0)
372       goto out;
373     silc_rng_add_noise(rng, buf, len);
374   }
375
376 #ifdef SILC_RNG_DEBUG
377   SILC_LOG_HEXDUMP(("pool"), rng->pool, sizeof(rng->pool));
378 #endif
379
380  out:
381   close(fd);
382   memset(buf, 0, sizeof(buf));
383 #endif
384 }
385
386 /* Execs command and gets noise from its output */
387
388 static void silc_rng_exec_command(SilcRng rng, char *command)
389 {
390 #if defined(SILC_UNIX)
391   unsigned char buf[1024];
392   FILE *fd;
393   int i;
394   int c;
395
396   /* Open process */
397   fd = popen(command, "r");
398   if (!fd)
399     return;
400
401   /* Get data as much as we can get into the buffer */
402   for (i = 0; i < sizeof(buf); i++) {
403     c = fgetc(fd);
404     if (c == EOF)
405       break;
406     buf[i] = c;
407   }
408
409   pclose(fd);
410
411   if (i != 0) {
412     /* Add the buffer into random pool */
413     silc_rng_add_noise(rng, buf, i);
414     memset(buf, 0, sizeof(buf));
415   }
416 #endif
417 }
418
419 /* This function adds the contents of the buffer as noise into random
420    pool. After adding the noise the pool is stirred. */
421
422 void silc_rng_add_noise(SilcRng rng, unsigned char *buffer, SilcUInt32 len)
423 {
424   SilcUInt32 i, pos;
425
426   pos = silc_rng_get_position(rng);
427
428   /* Add the buffer one by one into the pool */
429   for(i = 0; i < len; i++, buffer++) {
430     if(pos >= SILC_RNG_POOLSIZE)
431       break;
432     rng->pool[pos++] ^= *buffer;
433   }
434
435   /* Stir random pool */
436   silc_rng_stir_pool(rng);
437 }
438
439 /* XOR's data into the pool */
440
441 static void silc_rng_xor(SilcRng rng, SilcUInt32 val, unsigned int pos)
442 {
443   SilcUInt32 tmp;
444
445   SILC_GET32_MSB(tmp, &rng->pool[pos]);
446   val ^= tmp + val;
447   SILC_PUT32_MSB(val, &rng->pool[pos]);
448 }
449
450 /* This function stirs the random pool by encrypting buffer in CFB
451    (cipher feedback) mode with SHA1 algorithm. */
452
453 static void silc_rng_stir_pool(SilcRng rng)
454 {
455   int i;
456   SilcUInt32 iv[5], tmp;
457
458   /* Get the IV */
459   SILC_GET32_MSB(iv[0], &rng->pool[16     ]);
460   SILC_GET32_MSB(iv[1], &rng->pool[16 +  4]);
461   SILC_GET32_MSB(iv[2], &rng->pool[16 +  8]);
462   SILC_GET32_MSB(iv[3], &rng->pool[16 + 12]);
463   SILC_GET32_MSB(iv[4], &rng->pool[16 + 16]);
464
465   /* First CFB pass */
466   for (i = 0; i < SILC_RNG_POOLSIZE; i += 20) {
467     silc_hash_transform(rng->sha1, iv, rng->key);
468
469     SILC_GET32_MSB(tmp, &rng->pool[i]);
470     iv[0] ^= tmp;
471     SILC_PUT32_MSB(iv[0], &rng->pool[i]);
472
473     SILC_GET32_MSB(tmp, &rng->pool[i + 4]);
474     iv[1] ^= tmp;
475     SILC_PUT32_MSB(iv[1], &rng->pool[i + 4]);
476
477     SILC_GET32_MSB(tmp, &rng->pool[i + 8]);
478     iv[2] ^= tmp;
479     SILC_PUT32_MSB(iv[2], &rng->pool[i + 8]);
480
481     SILC_GET32_MSB(tmp, &rng->pool[i + 12]);
482     iv[3] ^= tmp;
483     SILC_PUT32_MSB(iv[3], &rng->pool[i + 12]);
484
485     SILC_GET32_MSB(tmp, &rng->pool[i + 16]);
486     iv[4] ^= tmp;
487     SILC_PUT32_MSB(iv[4], &rng->pool[i + 16]);
488   }
489
490   /* Get new key */
491   memcpy(rng->key, &rng->pool[silc_rng_get_position(rng)], sizeof(rng->key));
492
493   /* Second CFB pass */
494   for (i = 0; i < SILC_RNG_POOLSIZE; i += 20) {
495     silc_hash_transform(rng->sha1, iv, rng->key);
496
497     SILC_GET32_MSB(tmp, &rng->pool[i]);
498     iv[0] ^= tmp;
499     SILC_PUT32_MSB(iv[0], &rng->pool[i]);
500
501     SILC_GET32_MSB(tmp, &rng->pool[i + 4]);
502     iv[1] ^= tmp;
503     SILC_PUT32_MSB(iv[1], &rng->pool[i + 4]);
504
505     SILC_GET32_MSB(tmp, &rng->pool[i + 8]);
506     iv[2] ^= tmp;
507     SILC_PUT32_MSB(iv[2], &rng->pool[i + 8]);
508
509     SILC_GET32_MSB(tmp, &rng->pool[i + 12]);
510     iv[3] ^= tmp;
511     SILC_PUT32_MSB(iv[3], &rng->pool[i + 12]);
512
513     SILC_GET32_MSB(tmp, &rng->pool[i + 16]);
514     iv[4] ^= tmp;
515     SILC_PUT32_MSB(iv[4], &rng->pool[i + 16]);
516   }
517
518   memset(iv, 0, sizeof(iv));
519 }
520
521 /* Returns next position where data is fetched from the pool or
522    put to the pool. */
523
524 static SilcUInt32 silc_rng_get_position(SilcRng rng)
525 {
526   SilcRngState next;
527   SilcUInt32 pos;
528
529   next = rng->state->next;
530
531   pos = rng->state->pos++;
532   if ((next->low != 0 && pos >= next->low) || (pos >= SILC_RNG_POOLSIZE))
533     rng->state->pos = rng->state->low;
534
535 #ifdef SILC_RNG_DEBUG
536     fprintf(stderr, "state: %p: low: %lu, pos: %lu\n",
537             rng->state, rng->state->low, rng->state->pos);
538 #endif
539
540   rng->state = next;
541
542   return pos;
543 }
544
545 /* Returns random byte. */
546
547 SilcUInt8 silc_rng_get_byte(SilcRng rng)
548 {
549   SilcUInt8 byte;
550
551   rng->threshold++;
552
553   /* Get more soft noise after 64 bits threshold */
554   if (rng->threshold >= 8)
555     silc_rng_get_soft_noise(rng);
556
557   /* Get hard noise after 160 bits threshold, zero the threshold. */
558   if (rng->threshold >= 20) {
559     rng->threshold = 0;
560     silc_rng_get_hard_noise(rng);
561   }
562
563   do byte = rng->pool[silc_rng_get_position(rng)]; while (byte == 0x00);
564   return byte;
565 }
566
567 /* Return random byte as fast as possible. Reads from /dev/urandom if
568    available. If not then return from normal RNG (not so fast). */
569
570 SilcUInt8 silc_rng_get_byte_fast(SilcRng rng)
571 {
572 #if defined(SILC_UNIX)
573   unsigned char buf[1];
574
575   if (rng->fd_devurandom == -1) {
576     rng->fd_devurandom = open("/dev/urandom", O_RDONLY);
577     if (rng->fd_devurandom < 0)
578       return silc_rng_get_byte(rng);
579     fcntl(rng->fd_devurandom, F_SETFL, O_NONBLOCK);
580   }
581
582   if (read(rng->fd_devurandom, buf, sizeof(buf)) < 0)
583     return silc_rng_get_byte(rng);
584
585   return buf[0] != 0x00 ? buf[0] : silc_rng_get_byte(rng);
586 #else
587   return silc_rng_get_byte(rng);
588 #endif
589 }
590
591 /* Returns 16 bit random number */
592
593 SilcUInt16 silc_rng_get_rn16(SilcRng rng)
594 {
595   unsigned char rn[2];
596   SilcUInt16 num;
597
598   rn[0] = silc_rng_get_byte(rng);
599   rn[1] = silc_rng_get_byte(rng);
600   SILC_GET16_MSB(num, rn);
601
602   return num;
603 }
604
605 /* Returns 32 bit random number */
606
607 SilcUInt32 silc_rng_get_rn32(SilcRng rng)
608 {
609   unsigned char rn[4];
610   SilcUInt32 num;
611
612   rn[0] = silc_rng_get_byte(rng);
613   rn[1] = silc_rng_get_byte(rng);
614   rn[2] = silc_rng_get_byte(rng);
615   rn[3] = silc_rng_get_byte(rng);
616   SILC_GET32_MSB(num, rn);
617
618   return num;
619 }
620
621 /* Returns non-zero random number string. Returned string is in HEX format. */
622
623 unsigned char *silc_rng_get_rn_string(SilcRng rng, SilcUInt32 len)
624 {
625   int i;
626   unsigned char *string;
627
628   string = silc_calloc((len * 2 + 1), sizeof(unsigned char));
629   if (!string)
630     return NULL;
631
632   for (i = 0; i < len; i++)
633     sprintf(string + 2 * i, "%02x", silc_rng_get_byte(rng));
634
635   return string;
636 }
637
638 /* Returns non-zero random number binary data. */
639
640 unsigned char *silc_rng_get_rn_data(SilcRng rng, SilcUInt32 len)
641 {
642   int i;
643   unsigned char *data;
644
645   data = silc_calloc(len + 1, sizeof(*data));
646   if (!data)
647     return NULL;
648
649   for (i = 0; i < len; i++)
650     data[i] = silc_rng_get_byte(rng);
651
652   return data;
653 }
654
655 /* Global RNG. This is global RNG that application can initialize so
656    that any part of code anywhere can use RNG without having to allocate
657    new RNG object everytime.  If this is not initialized then these routines
658    will fail.  Note: currently in SILC applications always initialize this. */
659
660 SilcRng global_rng = NULL;
661
662 /* Initialize global RNG. If `rng' is provided it is set as the global
663    RNG object (it can be allocated by the application for example). */
664
665 SilcBool silc_rng_global_init(SilcRng rng)
666 {
667   if (rng) {
668     global_rng = rng;
669     return TRUE;
670   }
671
672   global_rng = silc_rng_alloc();
673   silc_rng_init(global_rng);
674
675   return TRUE;
676 }
677
678 /* Uninitialize global RNG */
679
680 SilcBool silc_rng_global_uninit(void)
681 {
682   if (global_rng) {
683     silc_rng_free(global_rng);
684     global_rng = NULL;
685   }
686
687   return TRUE;
688 }
689
690 /* These are analogous to the functions above. */
691
692 SilcUInt8 silc_rng_global_get_byte(void)
693 {
694   return global_rng ? silc_rng_get_byte(global_rng) : 0;
695 }
696
697 /* Return random byte as fast as possible. Reads from /dev/urandom if
698    available. If not then return from normal RNG (not so fast). */
699
700 SilcUInt8 silc_rng_global_get_byte_fast(void)
701 {
702   return global_rng ? silc_rng_get_byte_fast(global_rng) : 0;
703 }
704
705 SilcUInt16 silc_rng_global_get_rn16(void)
706 {
707   return global_rng ? silc_rng_get_rn16(global_rng) : 0;
708 }
709
710 SilcUInt32 silc_rng_global_get_rn32(void)
711 {
712   return global_rng ? silc_rng_get_rn32(global_rng) : 0;
713 }
714
715 unsigned char *silc_rng_global_get_rn_string(SilcUInt32 len)
716 {
717   return global_rng ? silc_rng_get_rn_string(global_rng, len) : NULL;
718 }
719
720 unsigned char *silc_rng_global_get_rn_data(SilcUInt32 len)
721 {
722   return global_rng ? silc_rng_get_rn_data(global_rng, len) : NULL;
723 }
724
725 void silc_rng_global_add_noise(unsigned char *buffer, SilcUInt32 len)
726 {
727   if (global_rng)
728     silc_rng_add_noise(global_rng, buffer, len);
729 }