• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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