]> pd.if.org Git - zpackage/blob - libtomcrypt/src/prngs/yarrow.c
remove sha224 and sha512-224
[zpackage] / libtomcrypt / src / prngs / yarrow.c
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 #include "tomcrypt.h"
10
11 /**
12   @file yarrow.c
13   Yarrow PRNG, Tom St Denis
14 */
15
16 #ifdef LTC_YARROW
17
18 const struct ltc_prng_descriptor yarrow_desc =
19 {
20     "yarrow", 64,
21     &yarrow_start,
22     &yarrow_add_entropy,
23     &yarrow_ready,
24     &yarrow_read,
25     &yarrow_done,
26     &yarrow_export,
27     &yarrow_import,
28     &yarrow_test
29 };
30
31 /**
32   Start the PRNG
33   @param prng     [out] The PRNG state to initialize
34   @return CRYPT_OK if successful
35 */
36 int yarrow_start(prng_state *prng)
37 {
38    int err;
39
40    LTC_ARGCHK(prng != NULL);
41    prng->ready = 0;
42
43    /* these are the default hash/cipher combo used */
44 #ifdef LTC_RIJNDAEL
45 #if    LTC_YARROW_AES==0
46    prng->yarrow.cipher = register_cipher(&rijndael_enc_desc);
47 #elif  LTC_YARROW_AES==1
48    prng->yarrow.cipher = register_cipher(&aes_enc_desc);
49 #elif  LTC_YARROW_AES==2
50    prng->yarrow.cipher = register_cipher(&rijndael_desc);
51 #elif  LTC_YARROW_AES==3
52    prng->yarrow.cipher = register_cipher(&aes_desc);
53 #endif
54 #elif defined(LTC_BLOWFISH)
55    prng->yarrow.cipher = register_cipher(&blowfish_desc);
56 #elif defined(LTC_TWOFISH)
57    prng->yarrow.cipher = register_cipher(&twofish_desc);
58 #elif defined(LTC_RC6)
59    prng->yarrow.cipher = register_cipher(&rc6_desc);
60 #elif defined(LTC_RC5)
61    prng->yarrow.cipher = register_cipher(&rc5_desc);
62 #elif defined(LTC_SAFERP)
63    prng->yarrow.cipher = register_cipher(&saferp_desc);
64 #elif defined(LTC_RC2)
65    prng->yarrow.cipher = register_cipher(&rc2_desc);
66 #elif defined(LTC_NOEKEON)
67    prng->yarrow.cipher = register_cipher(&noekeon_desc);
68 #elif defined(LTC_ANUBIS)
69    prng->yarrow.cipher = register_cipher(&anubis_desc);
70 #elif defined(LTC_KSEED)
71    prng->yarrow.cipher = register_cipher(&kseed_desc);
72 #elif defined(LTC_KHAZAD)
73    prng->yarrow.cipher = register_cipher(&khazad_desc);
74 #elif defined(LTC_CAST5)
75    prng->yarrow.cipher = register_cipher(&cast5_desc);
76 #elif defined(LTC_XTEA)
77    prng->yarrow.cipher = register_cipher(&xtea_desc);
78 #elif defined(LTC_SAFER)
79    prng->yarrow.cipher = register_cipher(&safer_sk128_desc);
80 #elif defined(LTC_DES)
81    prng->yarrow.cipher = register_cipher(&des3_desc);
82 #else
83    #error LTC_YARROW needs at least one CIPHER
84 #endif
85    if ((err = cipher_is_valid(prng->yarrow.cipher)) != CRYPT_OK) {
86       return err;
87    }
88
89 #ifdef LTC_SHA256
90    prng->yarrow.hash   = register_hash(&sha256_desc);
91 #elif defined(LTC_SHA512)
92    prng->yarrow.hash   = register_hash(&sha512_desc);
93 #elif defined(LTC_TIGER)
94    prng->yarrow.hash   = register_hash(&tiger_desc);
95 #elif defined(LTC_SHA1)
96    prng->yarrow.hash   = register_hash(&sha1_desc);
97 #elif defined(LTC_RIPEMD320)
98    prng->yarrow.hash   = register_hash(&rmd320_desc);
99 #elif defined(LTC_RIPEMD256)
100    prng->yarrow.hash   = register_hash(&rmd256_desc);
101 #elif defined(LTC_RIPEMD160)
102    prng->yarrow.hash   = register_hash(&rmd160_desc);
103 #elif defined(LTC_RIPEMD128)
104    prng->yarrow.hash   = register_hash(&rmd128_desc);
105 #elif defined(LTC_MD5)
106    prng->yarrow.hash   = register_hash(&md5_desc);
107 #elif defined(LTC_MD4)
108    prng->yarrow.hash   = register_hash(&md4_desc);
109 #elif defined(LTC_MD2)
110    prng->yarrow.hash   = register_hash(&md2_desc);
111 #elif defined(LTC_WHIRLPOOL)
112    prng->yarrow.hash   = register_hash(&whirlpool_desc);
113 #else
114    #error LTC_YARROW needs at least one HASH
115 #endif
116    if ((err = hash_is_valid(prng->yarrow.hash)) != CRYPT_OK) {
117       return err;
118    }
119
120    /* zero the memory used */
121    zeromem(prng->yarrow.pool, sizeof(prng->yarrow.pool));
122    LTC_MUTEX_INIT(&prng->lock)
123
124    return CRYPT_OK;
125 }
126
127 /**
128   Add entropy to the PRNG state
129   @param in       The data to add
130   @param inlen    Length of the data to add
131   @param prng     PRNG state to update
132   @return CRYPT_OK if successful
133 */
134 int yarrow_add_entropy(const unsigned char *in, unsigned long inlen, prng_state *prng)
135 {
136    hash_state md;
137    int err;
138
139    LTC_ARGCHK(prng != NULL);
140    LTC_ARGCHK(in != NULL);
141    LTC_ARGCHK(inlen > 0);
142
143    LTC_MUTEX_LOCK(&prng->lock);
144
145    if ((err = hash_is_valid(prng->yarrow.hash)) != CRYPT_OK) {
146       goto LBL_UNLOCK;
147    }
148
149    /* start the hash */
150    if ((err = hash_descriptor[prng->yarrow.hash].init(&md)) != CRYPT_OK) {
151       goto LBL_UNLOCK;
152    }
153
154    /* hash the current pool */
155    if ((err = hash_descriptor[prng->yarrow.hash].process(&md, prng->yarrow.pool,
156                                                         hash_descriptor[prng->yarrow.hash].hashsize)) != CRYPT_OK) {
157       goto LBL_UNLOCK;
158    }
159
160    /* add the new entropy */
161    if ((err = hash_descriptor[prng->yarrow.hash].process(&md, in, inlen)) != CRYPT_OK) {
162       goto LBL_UNLOCK;
163    }
164
165    /* store result */
166    err = hash_descriptor[prng->yarrow.hash].done(&md, prng->yarrow.pool);
167
168 LBL_UNLOCK:
169    LTC_MUTEX_UNLOCK(&prng->lock);
170    return err;
171 }
172
173 /**
174   Make the PRNG ready to read from
175   @param prng   The PRNG to make active
176   @return CRYPT_OK if successful
177 */
178 int yarrow_ready(prng_state *prng)
179 {
180    int ks, err;
181
182    LTC_ARGCHK(prng != NULL);
183
184    LTC_MUTEX_LOCK(&prng->lock);
185
186    if ((err = hash_is_valid(prng->yarrow.hash)) != CRYPT_OK) {
187       goto LBL_UNLOCK;
188    }
189
190    if ((err = cipher_is_valid(prng->yarrow.cipher)) != CRYPT_OK) {
191       goto LBL_UNLOCK;
192    }
193
194    /* setup CTR mode using the "pool" as the key */
195    ks = (int)hash_descriptor[prng->yarrow.hash].hashsize;
196    if ((err = cipher_descriptor[prng->yarrow.cipher].keysize(&ks)) != CRYPT_OK) {
197       goto LBL_UNLOCK;
198    }
199
200    if ((err = ctr_start(prng->yarrow.cipher,     /* what cipher to use */
201                         prng->yarrow.pool,       /* IV */
202                         prng->yarrow.pool, ks,   /* KEY and key size */
203                         0,                       /* number of rounds */
204                         CTR_COUNTER_LITTLE_ENDIAN, /* little endian counter */
205                         &prng->yarrow.ctr)) != CRYPT_OK) {
206       goto LBL_UNLOCK;
207    }
208    prng->ready = 1;
209
210 LBL_UNLOCK:
211    LTC_MUTEX_UNLOCK(&prng->lock);
212    return err;
213 }
214
215 /**
216   Read from the PRNG
217   @param out      Destination
218   @param outlen   Length of output
219   @param prng     The active PRNG to read from
220   @return Number of octets read
221 */
222 unsigned long yarrow_read(unsigned char *out, unsigned long outlen, prng_state *prng)
223 {
224    if (outlen == 0 || prng == NULL || out == NULL) return 0;
225
226    LTC_MUTEX_LOCK(&prng->lock);
227
228    if (!prng->ready) {
229       outlen = 0;
230       goto LBL_UNLOCK;
231    }
232
233    /* put out in predictable state first */
234    zeromem(out, outlen);
235
236    /* now randomize it */
237    if (ctr_encrypt(out, out, outlen, &prng->yarrow.ctr) != CRYPT_OK) {
238       outlen = 0;
239    }
240
241 LBL_UNLOCK:
242    LTC_MUTEX_UNLOCK(&prng->lock);
243    return outlen;
244 }
245
246 /**
247   Terminate the PRNG
248   @param prng   The PRNG to terminate
249   @return CRYPT_OK if successful
250 */
251 int yarrow_done(prng_state *prng)
252 {
253    int err;
254    LTC_ARGCHK(prng != NULL);
255
256    LTC_MUTEX_LOCK(&prng->lock);
257    prng->ready = 0;
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->lock);
265    LTC_MUTEX_DESTROY(&prng->lock);
266    return err;
267 }
268
269 /**
270   Export the PRNG state
271   @param out       [out] Destination
272   @param outlen    [in/out] Max size and resulting size of the state
273   @param prng      The PRNG to export
274   @return CRYPT_OK if successful
275 */
276 int yarrow_export(unsigned char *out, unsigned long *outlen, prng_state *prng)
277 {
278    unsigned long len = yarrow_desc.export_size;
279
280    LTC_ARGCHK(out    != NULL);
281    LTC_ARGCHK(outlen != NULL);
282    LTC_ARGCHK(prng   != NULL);
283
284    if (*outlen < len) {
285       *outlen = len;
286       return CRYPT_BUFFER_OVERFLOW;
287    }
288
289    if (yarrow_read(out, len, prng) != len) {
290       return CRYPT_ERROR_READPRNG;
291    }
292
293    *outlen = len;
294    return CRYPT_OK;
295 }
296
297 /**
298   Import a PRNG state
299   @param in       The PRNG state
300   @param inlen    Size of the state
301   @param prng     The PRNG to import
302   @return CRYPT_OK if successful
303 */
304 int yarrow_import(const unsigned char *in, unsigned long inlen, prng_state *prng)
305 {
306    int err;
307
308    LTC_ARGCHK(in   != NULL);
309    LTC_ARGCHK(prng != NULL);
310    if (inlen < (unsigned long)yarrow_desc.export_size) return CRYPT_INVALID_ARG;
311
312    if ((err = yarrow_start(prng)) != CRYPT_OK)                  return err;
313    if ((err = yarrow_add_entropy(in, inlen, prng)) != CRYPT_OK) return err;
314    return CRYPT_OK;
315 }
316
317 /**
318   PRNG self-test
319   @return CRYPT_OK if successful, CRYPT_NOP if self-testing has been disabled
320 */
321 int yarrow_test(void)
322 {
323 #ifndef LTC_TEST
324    return CRYPT_NOP;
325 #else
326    int err;
327    prng_state prng;
328
329    if ((err = yarrow_start(&prng)) != CRYPT_OK) {
330       return err;
331    }
332
333    /* now let's test the hash/cipher that was chosen */
334    if (cipher_descriptor[prng.yarrow.cipher].test &&
335        ((err = cipher_descriptor[prng.yarrow.cipher].test()) != CRYPT_OK)) {
336       return err;
337    }
338    if (hash_descriptor[prng.yarrow.hash].test &&
339        ((err = hash_descriptor[prng.yarrow.hash].test()) != CRYPT_OK)) {
340       return err;
341    }
342
343    return CRYPT_OK;
344 #endif
345 }
346
347 #endif
348
349
350 /* ref:         $Format:%D$ */
351 /* git commit:  $Format:%H$ */
352 /* commit time: $Format:%ai$ */