Mercurial > dropbear
comparison libtomcrypt/src/prngs/yarrow.c @ 391:00fcf5045160
propagate from branch 'au.asn.ucc.matt.ltc.dropbear' (head c1db4398d56c56c6d06ae1e20c1e0d04dbb598ed)
to branch 'au.asn.ucc.matt.dropbear' (head d26d5eb2837f46b56a33fb0e7573aa0201abd4d5)
author | Matt Johnston <matt@ucc.asn.au> |
---|---|
date | Thu, 11 Jan 2007 04:29:08 +0000 |
parents | 0cbe8f6dbf9e |
children | f849a5ca2efc |
comparison
equal
deleted
inserted
replaced
390:d8e44bef7917 | 391:00fcf5045160 |
---|---|
1 /* LibTomCrypt, modular cryptographic library -- Tom St Denis | |
2 * | |
3 * LibTomCrypt is a library that provides various cryptographic | |
4 * algorithms in a highly modular and flexible manner. | |
5 * | |
6 * The library is free for all purposes without any express | |
7 * guarantee it works. | |
8 * | |
9 * Tom St Denis, [email protected], http://libtomcrypt.com | |
10 */ | |
11 #include "tomcrypt.h" | |
12 | |
13 /** | |
14 @file yarrow.c | |
15 Yarrow PRNG, Tom St Denis | |
16 */ | |
17 | |
18 #ifdef YARROW | |
19 | |
20 const struct ltc_prng_descriptor yarrow_desc = | |
21 { | |
22 "yarrow", 64, | |
23 &yarrow_start, | |
24 &yarrow_add_entropy, | |
25 &yarrow_ready, | |
26 &yarrow_read, | |
27 &yarrow_done, | |
28 &yarrow_export, | |
29 &yarrow_import, | |
30 &yarrow_test | |
31 }; | |
32 | |
33 /** | |
34 Start the PRNG | |
35 @param prng [out] The PRNG state to initialize | |
36 @return CRYPT_OK if successful | |
37 */ | |
38 int yarrow_start(prng_state *prng) | |
39 { | |
40 int err; | |
41 | |
42 LTC_ARGCHK(prng != NULL); | |
43 | |
44 /* these are the default hash/cipher combo used */ | |
45 #ifdef RIJNDAEL | |
46 #if YARROW_AES==0 | |
47 prng->yarrow.cipher = register_cipher(&rijndael_enc_desc); | |
48 #elif YARROW_AES==1 | |
49 prng->yarrow.cipher = register_cipher(&aes_enc_desc); | |
50 #elif YARROW_AES==2 | |
51 prng->yarrow.cipher = register_cipher(&rijndael_desc); | |
52 #elif YARROW_AES==3 | |
53 prng->yarrow.cipher = register_cipher(&aes_desc); | |
54 #endif | |
55 #elif defined(BLOWFISH) | |
56 prng->yarrow.cipher = register_cipher(&blowfish_desc); | |
57 #elif defined(TWOFISH) | |
58 prng->yarrow.cipher = register_cipher(&twofish_desc); | |
59 #elif defined(RC6) | |
60 prng->yarrow.cipher = register_cipher(&rc6_desc); | |
61 #elif defined(RC5) | |
62 prng->yarrow.cipher = register_cipher(&rc5_desc); | |
63 #elif defined(SAFERP) | |
64 prng->yarrow.cipher = register_cipher(&saferp_desc); | |
65 #elif defined(RC2) | |
66 prng->yarrow.cipher = register_cipher(&rc2_desc); | |
67 #elif defined(NOEKEON) | |
68 prng->yarrow.cipher = register_cipher(&noekeon_desc); | |
69 #elif defined(ANUBIS) | |
70 prng->yarrow.cipher = register_cipher(&anubis_desc); | |
71 #elif defined(KSEED) | |
72 prng->yarrow.cipher = register_cipher(&kseed_desc); | |
73 #elif defined(KHAZAD) | |
74 prng->yarrow.cipher = register_cipher(&khazad_desc); | |
75 #elif defined(CAST5) | |
76 prng->yarrow.cipher = register_cipher(&cast5_desc); | |
77 #elif defined(XTEA) | |
78 prng->yarrow.cipher = register_cipher(&xtea_desc); | |
79 #elif defined(SAFER) | |
80 prng->yarrow.cipher = register_cipher(&safer_sk128_desc); | |
81 #elif defined(DES) | |
82 prng->yarrow.cipher = register_cipher(&des3_desc); | |
83 #else | |
84 #error YARROW needs at least one CIPHER | |
85 #endif | |
86 if ((err = cipher_is_valid(prng->yarrow.cipher)) != CRYPT_OK) { | |
87 return err; | |
88 } | |
89 | |
90 #ifdef SHA256 | |
91 prng->yarrow.hash = register_hash(&sha256_desc); | |
92 #elif defined(SHA512) | |
93 prng->yarrow.hash = register_hash(&sha512_desc); | |
94 #elif defined(TIGER) | |
95 prng->yarrow.hash = register_hash(&tiger_desc); | |
96 #elif defined(SHA1) | |
97 prng->yarrow.hash = register_hash(&sha1_desc); | |
98 #elif defined(RIPEMD320) | |
99 prng->yarrow.hash = register_hash(&rmd320_desc); | |
100 #elif defined(RIPEMD256) | |
101 prng->yarrow.hash = register_hash(&rmd256_desc); | |
102 #elif defined(RIPEMD160) | |
103 prng->yarrow.hash = register_hash(&rmd160_desc); | |
104 #elif defined(RIPEMD128) | |
105 prng->yarrow.hash = register_hash(&rmd128_desc); | |
106 #elif defined(MD5) | |
107 prng->yarrow.hash = register_hash(&md5_desc); | |
108 #elif defined(MD4) | |
109 prng->yarrow.hash = register_hash(&md4_desc); | |
110 #elif defined(MD2) | |
111 prng->yarrow.hash = register_hash(&md2_desc); | |
112 #elif defined(WHIRLPOOL) | |
113 prng->yarrow.hash = register_hash(&whirlpool_desc); | |
114 #else | |
115 #error YARROW needs at least one HASH | |
116 #endif | |
117 if ((err = hash_is_valid(prng->yarrow.hash)) != CRYPT_OK) { | |
118 return err; | |
119 } | |
120 | |
121 /* zero the memory used */ | |
122 zeromem(prng->yarrow.pool, sizeof(prng->yarrow.pool)); | |
123 LTC_MUTEX_INIT(&prng->yarrow.prng_lock) | |
124 | |
125 return CRYPT_OK; | |
126 } | |
127 | |
128 /** | |
129 Add entropy to the PRNG state | |
130 @param in The data to add | |
131 @param inlen Length of the data to add | |
132 @param prng PRNG state to update | |
133 @return CRYPT_OK if successful | |
134 */ | |
135 int yarrow_add_entropy(const unsigned char *in, unsigned long inlen, prng_state *prng) | |
136 { | |
137 hash_state md; | |
138 int err; | |
139 | |
140 LTC_ARGCHK(in != NULL); | |
141 LTC_ARGCHK(prng != NULL); | |
142 | |
143 LTC_MUTEX_LOCK(&prng->yarrow.prng_lock); | |
144 | |
145 if ((err = hash_is_valid(prng->yarrow.hash)) != CRYPT_OK) { | |
146 LTC_MUTEX_UNLOCK(&prng->yarrow.prng_lock); | |
147 return err; | |
148 } | |
149 | |
150 /* start the hash */ | |
151 if ((err = hash_descriptor[prng->yarrow.hash].init(&md)) != CRYPT_OK) { | |
152 LTC_MUTEX_UNLOCK(&prng->yarrow.prng_lock); | |
153 return err; | |
154 } | |
155 | |
156 /* hash the current pool */ | |
157 if ((err = hash_descriptor[prng->yarrow.hash].process(&md, prng->yarrow.pool, | |
158 hash_descriptor[prng->yarrow.hash].hashsize)) != CRYPT_OK) { | |
159 LTC_MUTEX_UNLOCK(&prng->yarrow.prng_lock); | |
160 return err; | |
161 } | |
162 | |
163 /* add the new entropy */ | |
164 if ((err = hash_descriptor[prng->yarrow.hash].process(&md, in, inlen)) != CRYPT_OK) { | |
165 LTC_MUTEX_UNLOCK(&prng->yarrow.prng_lock); | |
166 return err; | |
167 } | |
168 | |
169 /* store result */ | |
170 if ((err = hash_descriptor[prng->yarrow.hash].done(&md, prng->yarrow.pool)) != CRYPT_OK) { | |
171 LTC_MUTEX_UNLOCK(&prng->yarrow.prng_lock); | |
172 return err; | |
173 } | |
174 | |
175 LTC_MUTEX_UNLOCK(&prng->yarrow.prng_lock); | |
176 return CRYPT_OK; | |
177 } | |
178 | |
179 /** | |
180 Make the PRNG ready to read from | |
181 @param prng The PRNG to make active | |
182 @return CRYPT_OK if successful | |
183 */ | |
184 int yarrow_ready(prng_state *prng) | |
185 { | |
186 int ks, err; | |
187 | |
188 LTC_ARGCHK(prng != NULL); | |
189 LTC_MUTEX_LOCK(&prng->yarrow.prng_lock); | |
190 | |
191 if ((err = hash_is_valid(prng->yarrow.hash)) != CRYPT_OK) { | |
192 LTC_MUTEX_UNLOCK(&prng->yarrow.prng_lock); | |
193 return err; | |
194 } | |
195 | |
196 if ((err = cipher_is_valid(prng->yarrow.cipher)) != CRYPT_OK) { | |
197 LTC_MUTEX_UNLOCK(&prng->yarrow.prng_lock); | |
198 return err; | |
199 } | |
200 | |
201 /* setup CTR mode using the "pool" as the key */ | |
202 ks = (int)hash_descriptor[prng->yarrow.hash].hashsize; | |
203 if ((err = cipher_descriptor[prng->yarrow.cipher].keysize(&ks)) != CRYPT_OK) { | |
204 LTC_MUTEX_UNLOCK(&prng->yarrow.prng_lock); | |
205 return err; | |
206 } | |
207 | |
208 if ((err = ctr_start(prng->yarrow.cipher, /* what cipher to use */ | |
209 prng->yarrow.pool, /* IV */ | |
210 prng->yarrow.pool, ks, /* KEY and key size */ | |
211 0, /* number of rounds */ | |
212 CTR_COUNTER_LITTLE_ENDIAN, /* little endian counter */ | |
213 &prng->yarrow.ctr)) != CRYPT_OK) { | |
214 LTC_MUTEX_UNLOCK(&prng->yarrow.prng_lock); | |
215 return err; | |
216 } | |
217 LTC_MUTEX_UNLOCK(&prng->yarrow.prng_lock); | |
218 return CRYPT_OK; | |
219 } | |
220 | |
221 /** | |
222 Read from the PRNG | |
223 @param out Destination | |
224 @param outlen Length of output | |
225 @param prng The active PRNG to read from | |
226 @return Number of octets read | |
227 */ | |
228 unsigned long yarrow_read(unsigned char *out, unsigned long outlen, prng_state *prng) | |
229 { | |
230 LTC_ARGCHK(out != NULL); | |
231 LTC_ARGCHK(prng != NULL); | |
232 | |
233 LTC_MUTEX_LOCK(&prng->yarrow.prng_lock); | |
234 | |
235 /* put out in predictable state first */ | |
236 zeromem(out, outlen); | |
237 | |
238 /* now randomize it */ | |
239 if (ctr_encrypt(out, out, outlen, &prng->yarrow.ctr) != CRYPT_OK) { | |
240 LTC_MUTEX_UNLOCK(&prng->yarrow.prng_lock); | |
241 return 0; | |
242 } | |
243 LTC_MUTEX_UNLOCK(&prng->yarrow.prng_lock); | |
244 return outlen; | |
245 } | |
246 | |
247 /** | |
248 Terminate the PRNG | |
249 @param prng The PRNG to terminate | |
250 @return CRYPT_OK if successful | |
251 */ | |
252 int yarrow_done(prng_state *prng) | |
253 { | |
254 int err; | |
255 LTC_ARGCHK(prng != NULL); | |
256 | |
257 LTC_MUTEX_LOCK(&prng->yarrow.prng_lock); | |
258 | |
259 /* call cipher done when we invent one ;-) */ | |
260 | |
261 /* we invented one */ | |
262 err = ctr_done(&prng->yarrow.ctr); | |
263 | |
264 LTC_MUTEX_UNLOCK(&prng->yarrow.prng_lock); | |
265 return err; | |
266 } | |
267 | |
268 /** | |
269 Export the PRNG state | |
270 @param out [out] Destination | |
271 @param outlen [in/out] Max size and resulting size of the state | |
272 @param prng The PRNG to export | |
273 @return CRYPT_OK if successful | |
274 */ | |
275 int yarrow_export(unsigned char *out, unsigned long *outlen, prng_state *prng) | |
276 { | |
277 LTC_ARGCHK(out != NULL); | |
278 LTC_ARGCHK(outlen != NULL); | |
279 LTC_ARGCHK(prng != NULL); | |
280 | |
281 LTC_MUTEX_LOCK(&prng->yarrow.prng_lock); | |
282 | |
283 /* we'll write 64 bytes for s&g's */ | |
284 if (*outlen < 64) { | |
285 LTC_MUTEX_UNLOCK(&prng->yarrow.prng_lock); | |
286 *outlen = 64; | |
287 return CRYPT_BUFFER_OVERFLOW; | |
288 } | |
289 | |
290 if (yarrow_read(out, 64, prng) != 64) { | |
291 LTC_MUTEX_UNLOCK(&prng->yarrow.prng_lock); | |
292 return CRYPT_ERROR_READPRNG; | |
293 } | |
294 *outlen = 64; | |
295 | |
296 return CRYPT_OK; | |
297 } | |
298 | |
299 /** | |
300 Import a PRNG state | |
301 @param in The PRNG state | |
302 @param inlen Size of the state | |
303 @param prng The PRNG to import | |
304 @return CRYPT_OK if successful | |
305 */ | |
306 int yarrow_import(const unsigned char *in, unsigned long inlen, prng_state *prng) | |
307 { | |
308 int err; | |
309 | |
310 LTC_ARGCHK(in != NULL); | |
311 LTC_ARGCHK(prng != NULL); | |
312 | |
313 LTC_MUTEX_LOCK(&prng->yarrow.prng_lock); | |
314 | |
315 if (inlen != 64) { | |
316 LTC_MUTEX_UNLOCK(&prng->yarrow.prng_lock); | |
317 return CRYPT_INVALID_ARG; | |
318 } | |
319 | |
320 if ((err = yarrow_start(prng)) != CRYPT_OK) { | |
321 LTC_MUTEX_UNLOCK(&prng->yarrow.prng_lock); | |
322 return err; | |
323 } | |
324 err = yarrow_add_entropy(in, 64, prng); | |
325 LTC_MUTEX_UNLOCK(&prng->yarrow.prng_lock); | |
326 return err; | |
327 } | |
328 | |
329 /** | |
330 PRNG self-test | |
331 @return CRYPT_OK if successful, CRYPT_NOP if self-testing has been disabled | |
332 */ | |
333 int yarrow_test(void) | |
334 { | |
335 #ifndef LTC_TEST | |
336 return CRYPT_NOP; | |
337 #else | |
338 int err; | |
339 prng_state prng; | |
340 | |
341 if ((err = yarrow_start(&prng)) != CRYPT_OK) { | |
342 return err; | |
343 } | |
344 | |
345 /* now let's test the hash/cipher that was chosen */ | |
346 if ((err = cipher_descriptor[prng.yarrow.cipher].test()) != CRYPT_OK) { | |
347 return err; | |
348 } | |
349 if ((err = hash_descriptor[prng.yarrow.hash].test()) != CRYPT_OK) { | |
350 return err; | |
351 } | |
352 | |
353 return CRYPT_OK; | |
354 #endif | |
355 } | |
356 | |
357 #endif | |
358 | |
359 | |
360 /* $Source: /cvs/libtom/libtomcrypt/src/prngs/yarrow.c,v $ */ | |
361 /* $Revision: 1.10 $ */ | |
362 /* $Date: 2006/11/14 04:21:17 $ */ |