- code documentation cleaned
[strongswan.git] / Source / charon / utils / gmp_helper.c
1 /**
2 * @file gmp_helper.c
3 *
4 * @brief Implementation of gmp_helper_t.
5 *
6 */
7
8 /*
9 * Copyright (C) 1999, 2000, 2001 Henry Spencer.
10 * Copyright (C) 2005 Jan Hutter, Martin Willi
11 * Hochschule fuer Technik Rapperswil
12 *
13 * This program is free software; you can redistribute it and/or modify it
14 * under the terms of the GNU General Public License as published by the
15 * Free Software Foundation; either version 2 of the License, or (at your
16 * option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>.
17 *
18 * This program is distributed in the hope that it will be useful, but
19 * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
20 * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
21 * for more details.
22 */
23
24 #include <stdio.h>
25
26 #include "gmp_helper.h"
27
28 #include <utils/allocator.h>
29 #include <utils/randomizer.h>
30
31 /**
32 * Number of times the probabilistic primality test is applied.
33 */
34 #define PRIMECHECK_ROUNDS 30
35
36
37 typedef struct private_gmp_helper_t private_gmp_helper_t;
38
39 /**
40 * Private data of an gmp_helper_t object.
41 */
42 struct private_gmp_helper_t {
43 /**
44 * Public gmp_helper_t interface.
45 */
46 gmp_helper_t public;
47
48 };
49
50
51 /**
52 * Implementation of gmp_helper_t.chunk_to_mpz.
53 */
54 static void chunk_to_mpz(private_gmp_helper_t *this, mpz_t *mpz_value, chunk_t data)
55 {
56 size_t i;
57
58 mpz_init_set_ui(*(mpz_value), 0);
59
60 for (i = 0; i < data.len; i++)
61 {
62 mpz_mul_ui(*(mpz_value),*(mpz_value), 1 << 8);
63 mpz_add_ui(*(mpz_value),*(mpz_value), data.ptr[i]);
64 }
65 }
66
67 /**
68 * Implementation of gmp_helper_t.mpz_to_chunk.
69 */
70 static status_t mpz_to_chunk (private_gmp_helper_t *this,mpz_t *mpz_value, chunk_t *data,size_t bytes)
71 {
72 mpz_t temp1, temp2;
73 status_t status = SUCCESS;
74 int i;
75 chunk_t tmp_chunk;
76
77 tmp_chunk.len = bytes;
78 tmp_chunk.ptr = allocator_alloc(tmp_chunk.len);
79
80 if (tmp_chunk.ptr == NULL)
81 {
82 allocator_free_chunk(&tmp_chunk);
83 return OUT_OF_RES;
84 }
85
86 /* free memory */
87 memset(tmp_chunk.ptr,0,tmp_chunk.len);
88
89 mpz_init(temp1);
90 mpz_init(temp2);
91
92 mpz_set(temp1, *mpz_value);
93
94 for (i = tmp_chunk.len-1; i >= 0; i--)
95 {
96 tmp_chunk.ptr[i] = mpz_mdivmod_ui(temp2, NULL, temp1, 1 << 8);
97 mpz_set(temp1, temp2);
98
99 }
100
101 if (mpz_sgn(temp1) != 0)
102 {
103 fprintf (stderr,"value %d\n",mpz_sgn(temp1));
104 status = FAILED;
105 }
106 mpz_clear(temp1);
107 mpz_clear(temp2);
108 *data = tmp_chunk;
109 if (status != SUCCESS)
110 {
111 allocator_free_chunk(&tmp_chunk);
112 }
113 return status;
114 }
115
116 /**
117 * Implementation of gmp_helper_t.init_prime.
118 */
119 static status_t init_prime (private_gmp_helper_t *this, mpz_t *prime, int bytes)
120 {
121 randomizer_t *randomizer;
122 chunk_t random_bytes;
123 status_t status;
124 randomizer = randomizer_create();
125
126 if (randomizer == NULL)
127 {
128 return OUT_OF_RES;
129 }
130
131 /* TODO change to true random device ? */
132 // status = randomizer->allocate_random_bytes(randomizer,bytes, &random_bytes);
133 status = randomizer->allocate_pseudo_random_bytes(randomizer,bytes, &random_bytes);
134
135 /* make sure most significant bit is set */
136 random_bytes.ptr[0] = random_bytes.ptr[0] | 0x80;
137
138
139 /* not needed anymore */
140 randomizer->destroy(randomizer);
141
142 /* convert chunk to mpz value */
143 this->public.chunk_to_mpz(&(this->public),prime, random_bytes);
144
145 /* chunk is not used anymore */
146 allocator_free(random_bytes.ptr);
147 random_bytes.ptr = NULL;
148
149 /* composites are possible but should never occur */
150 mpz_nextprime (*(prime),*(prime));
151
152 return SUCCESS;
153 }
154
155 /**
156 * Implementation of gmp_helper_t.init_prime_fast.
157 */
158 static status_t init_prime_fast (private_gmp_helper_t *this, mpz_t *prime, int bytes){
159 randomizer_t *randomizer;
160 chunk_t random_bytes;
161 status_t status;
162 unsigned long tries;
163 size_t length;
164
165
166 randomizer = randomizer_create();
167
168 if (randomizer == NULL)
169 {
170 return OUT_OF_RES;
171 }
172
173 /* TODO change to true random device ? */
174 // status = randomizer->allocate_random_bytes(randomizer,bytes, &random_bytes);
175 status = randomizer->allocate_pseudo_random_bytes(randomizer,bytes, &random_bytes);
176
177 /* make sure most significant bit is set */
178 random_bytes.ptr[0] = random_bytes.ptr[0] | 0x80;
179 /* not needed anymore */
180 randomizer->destroy(randomizer);
181
182 /* convert chunk to mpz value */
183 this->public.chunk_to_mpz(&(this->public),prime, random_bytes);
184
185 /* chunk is not used anymore */
186 allocator_free(random_bytes.ptr);
187 random_bytes.ptr = NULL;
188
189 /* make value odd */
190 if (mpz_fdiv_ui(*prime, 2) != 1)
191 {
192 /* make value odd */
193 mpz_add_ui(*prime,*prime,1);
194 }
195
196 tries = 1;
197
198 /* starting find a prime */
199 while (!mpz_probab_prime_p(*prime, PRIMECHECK_ROUNDS))
200 {
201 /* not a prime, increase by 2 */
202 mpz_add_ui(*prime, *prime, 2);
203 tries++;
204 }
205
206 length = mpz_sizeinbase(*prime, 2);
207
208
209 /* check bit length of prime */
210 if ((length < (bytes * 8)) || (length > ((bytes * 8) + 1)))
211 {
212 return FAILED;
213 }
214
215
216 if (length == ((bytes * 8) + 1))
217 {
218 /* carry out occured! retry */
219 mpz_clear(*prime);
220
221 /* recursive call */
222 return this->public.init_prime_fast(&(this->public),prime, bytes);
223 }
224
225 return SUCCESS;
226 }
227
228
229 /**
230 * Implementation of gmp_helper_t.destroy.
231 */
232 static status_t destroy(private_gmp_helper_t *this)
233 {
234 allocator_free(this);
235 return SUCCESS;
236 }
237
238 /*
239 * Described in header
240 */
241 gmp_helper_t *gmp_helper_create()
242 {
243 private_gmp_helper_t *this = allocator_alloc_thing(private_gmp_helper_t);
244 if ((this == NULL))
245 {
246 return NULL;
247 }
248
249 /* public functions */
250 this->public.destroy = (status_t (*)(gmp_helper_t *)) destroy;
251 this->public.init_prime = (status_t (*) (gmp_helper_t *, mpz_t *, int)) init_prime;
252 this->public.init_prime_fast = (status_t (*) (gmp_helper_t *, mpz_t *, int)) init_prime_fast;
253
254 /* private functions */
255 this->public.chunk_to_mpz = (void (*) (gmp_helper_t *,mpz_t *, chunk_t )) chunk_to_mpz;
256 this->public.mpz_to_chunk = (status_t (*) (gmp_helper_t *,mpz_t *, chunk_t *,size_t )) mpz_to_chunk;
257
258 return &(this->public);
259 }