815dbbc38d12466cc6a1379b06a7cdab0755de9e
[gnuk/gnuk.git] / src / random.c
1 /*
2  * random.c -- get random bytes
3  *
4  * Copyright (C) 2010, 2011, 2012, 2013 Free Software Initiative of Japan
5  * Author: NIIBE Yutaka <gniibe@fsij.org>
6  *
7  * This file is a part of Gnuk, a GnuPG USB Token implementation.
8  *
9  * Gnuk is free software: you can redistribute it and/or modify it
10  * under the terms of the GNU General Public License as published by
11  * the Free Software Foundation, either version 3 of the License, or
12  * (at your option) any later version.
13  *
14  * Gnuk is distributed in the hope that it will be useful, but WITHOUT
15  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
16  * or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public
17  * License for more details.
18  *
19  * You should have received a copy of the GNU General Public License
20  * along with this program.  If not, see <http://www.gnu.org/licenses/>.
21  *
22  */
23
24 #include <stdint.h>
25 #include <string.h>
26
27 #include "config.h"
28
29 #include "gnuk.h"
30 #include "neug.h"
31
32 #define RANDOM_BYTES_LENGTH 32
33 static uint32_t random_word[RANDOM_BYTES_LENGTH/sizeof (uint32_t)];
34
35 void
36 random_init (void)
37 {
38   int i;
39
40   neug_init (random_word, RANDOM_BYTES_LENGTH/sizeof (uint32_t));
41
42   for (i = 0; i < NEUG_PRE_LOOP; i++)
43     (void)neug_get (NEUG_KICK_FILLING);
44 }
45
46 void
47 random_fini (void)
48 {
49   neug_fini ();
50 }
51
52 /*
53  * Return pointer to random 32-byte
54  */
55 const uint8_t *
56 random_bytes_get (void)
57 {
58   neug_wait_full ();
59   return (const uint8_t *)random_word;
60 }
61
62 /*
63  * Free pointer to random 32-byte
64  */
65 void
66 random_bytes_free (const uint8_t *p)
67 {
68   (void)p;
69   memset (random_word, 0, RANDOM_BYTES_LENGTH);
70   neug_flush ();
71 }
72
73 /*
74  * Return 4-byte salt
75  */
76 void
77 random_get_salt (uint8_t *p)
78 {
79   uint32_t rnd;
80
81   rnd = neug_get (NEUG_KICK_FILLING);
82   memcpy (p, &rnd, sizeof (uint32_t));
83   rnd = neug_get (NEUG_KICK_FILLING);
84   memcpy (p + sizeof (uint32_t), &rnd, sizeof (uint32_t));
85 }
86
87
88 #ifdef KEYGEN_SUPPORT
89 /*
90  * Random byte iterator
91  */
92 int
93 random_gen (void *arg, unsigned char *out, size_t out_len)
94 {
95   uint8_t *index_p = (uint8_t *)arg;
96   uint8_t index = *index_p;
97   size_t n;
98
99   while (out_len)
100     {
101       neug_wait_full ();
102
103       n = RANDOM_BYTES_LENGTH - index;
104       if (n > out_len)
105         n = out_len;
106
107       memcpy (out, ((unsigned char *)random_word) + index, n);
108       out += n;
109       out_len -= n;
110       index += n;
111
112       if (index >= RANDOM_BYTES_LENGTH)
113         {
114           index = 0;
115           neug_flush ();
116         }
117     }
118
119   *index_p = index;
120
121   return 0;
122 }
123 #endif