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, tomstdenis@gmail.com, 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 */
yarrow_start(prng_state * prng)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 */
yarrow_add_entropy(const unsigned char * in,unsigned long inlen,prng_state * prng)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 */
yarrow_ready(prng_state * prng)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 */
yarrow_read(unsigned char * out,unsigned long outlen,prng_state * prng)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 */
yarrow_done(prng_state * prng)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 */
yarrow_export(unsigned char * out,unsigned long * outlen,prng_state * prng)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 */
yarrow_import(const unsigned char * in,unsigned long inlen,prng_state * prng)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 */
yarrow_test(void)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 $ */
363