- code documentation cleaned
[strongswan.git] / Source / charon / utils / randomizer.c
1 /**
2 * @file randomizer.c
3 *
4 * @brief Implementation of randomizer_t.
5 *
6 */
7
8 /*
9 * Copyright (C) 2005 Jan Hutter, Martin Willi
10 * Hochschule fuer Technik Rapperswil
11 *
12 * This program is free software; you can redistribute it and/or modify it
13 * under the terms of the GNU General Public License as published by the
14 * Free Software Foundation; either version 2 of the License, or (at your
15 * option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>.
16 *
17 * This program is distributed in the hope that it will be useful, but
18 * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
19 * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
20 * for more details.
21 */
22
23 #include <string.h>
24 #include <sys/types.h>
25 #include <sys/stat.h>
26 #include <fcntl.h>
27 #include <unistd.h>
28
29 #include "randomizer.h"
30
31 #include <utils/allocator.h>
32
33 typedef struct private_randomizer_t private_randomizer_t;
34
35 /**
36 * Private data of an randomizer_t object
37 */
38 struct private_randomizer_t {
39 /**
40 * Public interface.
41 */
42 randomizer_t public;
43
44 /**
45 * @brief Reads a specific number of bytes from random or pseudo random device.
46 *
47 * @param this calling object
48 * @param pseudo_random TRUE, if pseudo random bytes should be read,
49 * FALSE for true random bytes
50 * @param bytes number of bytes to read
51 * @param[out] buffer pointer to buffer where to write the data in.
52 * Size of buffer has to be at least bytes.
53 * @return
54 * - SUCCESS
55 * - FAILED if random device could not be opened
56 */
57 status_t (*get_bytes_from_device) (private_randomizer_t *this,bool pseudo_random, size_t bytes, u_int8_t *buffer);
58
59 /**
60 * Random device name.
61 */
62 char *random_dev_name;
63
64 /**
65 * Pseudo random device name.
66 */
67 char *pseudo_random_dev_name;
68 };
69
70
71 /**
72 * Implementation of private_randomizer_t.get_bytes_from_device.
73 */
74 static status_t get_bytes_from_device(private_randomizer_t *this,bool pseudo_random, size_t bytes, u_int8_t *buffer)
75 {
76 /* number of bytes already done */
77 size_t ndone;
78 /* device file descriptor */
79 int device;
80 size_t got;
81 char * device_name;
82
83 device_name = (pseudo_random) ? this->pseudo_random_dev_name : this->random_dev_name;
84
85 // open device
86 device = open(device_name, 0);
87 if (device < 0) {
88 return FAILED;
89 }
90 ndone = 0;
91
92 // read until nbytes are read
93 while (ndone < bytes)
94 {
95 got = read(device, buffer + ndone, bytes - ndone);
96 if (got < 0) {
97 return FAILED;
98 }
99 if (got == 0) {
100 return FAILED;
101 }
102 ndone += got;
103 }
104 // close device
105 close(device);
106 return SUCCESS;
107 }
108
109 /**
110 * Implementation of randomizer_t.get_random_bytes.
111 */
112 static status_t get_random_bytes(private_randomizer_t *this,size_t bytes, u_int8_t *buffer)
113 {
114 return (this->get_bytes_from_device(this, FALSE, bytes, buffer));
115 }
116
117 /**
118 * Implementation of randomizer_t.allocate_random_bytes.
119 */
120 static status_t allocate_random_bytes(private_randomizer_t *this, size_t bytes, chunk_t *chunk)
121 {
122 chunk->len = bytes;
123 chunk->ptr = allocator_alloc(bytes);
124 if (chunk->ptr == NULL)
125 {
126 return OUT_OF_RES;
127 }
128 return (this->get_bytes_from_device(this, FALSE, bytes, chunk->ptr));
129 }
130
131 /**
132 * Implementation of randomizer_t.get_pseudo_random_bytes.
133 */
134 static status_t get_pseudo_random_bytes(private_randomizer_t *this,size_t bytes, u_int8_t *buffer)
135 {
136 return (this->get_bytes_from_device(this, TRUE, bytes, buffer));
137 }
138
139
140 /**
141 * Implementation of randomizer_t.allocate_pseudo_random_bytes.
142 */
143 static status_t allocate_pseudo_random_bytes(private_randomizer_t *this, size_t bytes, chunk_t *chunk)
144 {
145 chunk->len = bytes;
146 chunk->ptr = allocator_alloc(bytes);
147 if (chunk->ptr == NULL)
148 {
149 return OUT_OF_RES;
150 }
151 return (this->get_bytes_from_device(this, TRUE, bytes, chunk->ptr));
152 }
153
154
155 /**
156 * Implementation of randomizer_t.destroy.
157 */
158 static status_t destroy(private_randomizer_t *this)
159 {
160 allocator_free(this->random_dev_name);
161 allocator_free(this->pseudo_random_dev_name);
162 allocator_free(this);
163
164 return SUCCESS;
165 }
166
167 /*
168 * Described in header.
169 */
170 randomizer_t *randomizer_create(void)
171 {
172 return randomizer_create_on_devices(DEFAULT_RANDOM_DEVICE,DEFAULT_PSEUDO_RANDOM_DEVICE);
173 }
174
175 /*
176 * Described in header.
177 */
178 randomizer_t *randomizer_create_on_devices(char * random_dev_name,char * prandom_dev_name)
179 {
180 private_randomizer_t *this = allocator_alloc_thing(private_randomizer_t);
181 if (this == NULL)
182 {
183 return NULL;
184 }
185 if ((random_dev_name == NULL) || (prandom_dev_name == NULL))
186 {
187 return NULL;
188 }
189
190 /* public functions */
191 this->public.get_random_bytes = (status_t (*) (randomizer_t *,size_t, u_int8_t *)) get_random_bytes;
192 this->public.allocate_random_bytes = (status_t (*) (randomizer_t *,size_t, chunk_t *)) allocate_random_bytes;
193 this->public.get_pseudo_random_bytes = (status_t (*) (randomizer_t *,size_t, u_int8_t *)) get_pseudo_random_bytes;
194 this->public.allocate_pseudo_random_bytes = (status_t (*) (randomizer_t *,size_t, chunk_t *)) allocate_pseudo_random_bytes;
195 this->public.destroy = (status_t (*) (randomizer_t *))destroy;
196
197 /* private functions */
198 this->get_bytes_from_device = get_bytes_from_device;
199
200 /* private fields */
201 this->random_dev_name = allocator_alloc(strlen(random_dev_name) + 1);
202 if (this->random_dev_name == NULL)
203 {
204 allocator_free(this);
205 return NULL;
206 }
207 strcpy(this->random_dev_name,random_dev_name);
208
209 this->pseudo_random_dev_name = allocator_alloc(strlen(prandom_dev_name) + 1);
210 if (this->pseudo_random_dev_name == NULL)
211 {
212 allocator_free(this->random_dev_name);
213 allocator_free(this);
214 return NULL;
215 }
216 strcpy(this->pseudo_random_dev_name,prandom_dev_name);
217
218 return &(this->public);
219 }