- added random source ./configure options
[strongswan.git] / src / libstrongswan / 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
32 typedef struct private_randomizer_t private_randomizer_t;
33
34 /**
35 * Private data of an randomizer_t object.
36 */
37 struct private_randomizer_t {
38
39 /**
40 * Public randomizer_t 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 from 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 */
54 status_t (*get_bytes_from_device) (private_randomizer_t *this,bool pseudo_random, size_t bytes, u_int8_t *buffer);
55 };
56
57
58 /**
59 * Implementation of private_randomizer_t.get_bytes_from_device.
60 */
61 static status_t get_bytes_from_device(private_randomizer_t *this,bool pseudo_random, size_t bytes, u_int8_t *buffer)
62 {
63 size_t ndone;
64 int device;
65 size_t got;
66 char * device_name;
67
68 device_name = pseudo_random ? DEV_URANDOM : DEV_RANDOM;
69
70 device = open(device_name, 0);
71 if (device < 0) {
72 return FAILED;
73 }
74 ndone = 0;
75
76 /* read until nbytes are read */
77 while (ndone < bytes)
78 {
79 got = read(device, buffer + ndone, bytes - ndone);
80 if (got <= 0) {
81 close(device);
82 return FAILED;
83 }
84 ndone += got;
85 }
86 close(device);
87 return SUCCESS;
88 }
89
90 /**
91 * Implementation of randomizer_t.get_random_bytes.
92 */
93 static status_t get_random_bytes(private_randomizer_t *this,size_t bytes, u_int8_t *buffer)
94 {
95 return this->get_bytes_from_device(this, FALSE, bytes, buffer);
96 }
97
98 /**
99 * Implementation of randomizer_t.allocate_random_bytes.
100 */
101 static status_t allocate_random_bytes(private_randomizer_t *this, size_t bytes, chunk_t *chunk)
102 {
103 status_t status;
104 chunk->len = bytes;
105 chunk->ptr = malloc(bytes);
106 status = this->get_bytes_from_device(this, FALSE, bytes, chunk->ptr);
107 if (status != SUCCESS)
108 {
109 free(chunk->ptr);
110 }
111 return status;
112 }
113
114 /**
115 * Implementation of randomizer_t.get_pseudo_random_bytes.
116 */
117 static status_t get_pseudo_random_bytes(private_randomizer_t *this,size_t bytes, u_int8_t *buffer)
118 {
119 return (this->get_bytes_from_device(this, TRUE, bytes, buffer));
120 }
121
122 /**
123 * Implementation of randomizer_t.allocate_pseudo_random_bytes.
124 */
125 static status_t allocate_pseudo_random_bytes(private_randomizer_t *this, size_t bytes, chunk_t *chunk)
126 {
127 status_t status;
128 chunk->len = bytes;
129 chunk->ptr = malloc(bytes);
130 status = this->get_bytes_from_device(this, TRUE, bytes, chunk->ptr);
131 if (status != SUCCESS)
132 {
133 free(chunk->ptr);
134 }
135 return status;
136 }
137
138 /**
139 * Implementation of randomizer_t.destroy.
140 */
141 static void destroy(private_randomizer_t *this)
142 {
143 free(this);
144 }
145
146 /*
147 * Described in header.
148 */
149 randomizer_t *randomizer_create(void)
150 {
151 private_randomizer_t *this = malloc_thing(private_randomizer_t);
152
153 /* public functions */
154 this->public.get_random_bytes = (status_t (*) (randomizer_t *,size_t, u_int8_t *)) get_random_bytes;
155 this->public.allocate_random_bytes = (status_t (*) (randomizer_t *,size_t, chunk_t *)) allocate_random_bytes;
156 this->public.get_pseudo_random_bytes = (status_t (*) (randomizer_t *,size_t, u_int8_t *)) get_pseudo_random_bytes;
157 this->public.allocate_pseudo_random_bytes = (status_t (*) (randomizer_t *,size_t, chunk_t *)) allocate_pseudo_random_bytes;
158 this->public.destroy = (void (*) (randomizer_t *))destroy;
159
160 /* private functions */
161 this->get_bytes_from_device = get_bytes_from_device;
162
163 return &(this->public);
164 }