xref: /optee_os/core/lib/libtomcrypt/src/prngs/yarrow.c (revision bc420748bfc44a9e09000a3966fc59e9e0219df4)
1 /*
2  * Copyright (c) 2001-2007, Tom St Denis
3  * All rights reserved.
4  *
5  * Redistribution and use in source and binary forms, with or without
6  * modification, are permitted provided that the following conditions are met:
7  *
8  * 1. Redistributions of source code must retain the above copyright notice,
9  * this list of conditions and the following disclaimer.
10  *
11  * 2. Redistributions in binary form must reproduce the above copyright notice,
12  * this list of conditions and the following disclaimer in the documentation
13  * and/or other materials provided with the distribution.
14  *
15  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
16  * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
17  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
18  * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
19  * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
20  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
21  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
22  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
23  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
24  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
25  * POSSIBILITY OF SUCH DAMAGE.
26  */
27 
28 /* LibTomCrypt, modular cryptographic library -- Tom St Denis
29  *
30  * LibTomCrypt is a library that provides various cryptographic
31  * algorithms in a highly modular and flexible manner.
32  *
33  * The library is free for all purposes without any express
34  * guarantee it works.
35  *
36  * Tom St Denis, tomstdenis@gmail.com, http://libtom.org
37  */
38 #include "tomcrypt.h"
39 
40 /**
41   @file yarrow.c
42   Yarrow PRNG, Tom St Denis
43 */
44 
45 #ifdef LTC_YARROW
46 
47 const struct ltc_prng_descriptor yarrow_desc =
48 {
49     "yarrow", 64,
50     &yarrow_start,
51     &yarrow_add_entropy,
52     &yarrow_ready,
53     &yarrow_read,
54     &yarrow_done,
55     &yarrow_export,
56     &yarrow_import,
57     &yarrow_test
58 };
59 
60 /**
61   Start the PRNG
62   @param prng     [out] The PRNG state to initialize
63   @return CRYPT_OK if successful
64 */
65 int yarrow_start(prng_state *prng)
66 {
67    int err;
68 
69    LTC_ARGCHK(prng != NULL);
70 
71    /* these are the default hash/cipher combo used */
72 #ifdef LTC_RIJNDAEL
73 #if    LTC_YARROW_AES==0
74    prng->yarrow.cipher = register_cipher(&rijndael_enc_desc);
75 #elif  LTC_YARROW_AES==1
76    prng->yarrow.cipher = register_cipher(&aes_enc_desc);
77 #elif  LTC_YARROW_AES==2
78    prng->yarrow.cipher = register_cipher(&rijndael_desc);
79 #elif  LTC_YARROW_AES==3
80    prng->yarrow.cipher = register_cipher(&aes_desc);
81 #endif
82 #elif defined(LTC_BLOWFISH)
83    prng->yarrow.cipher = register_cipher(&blowfish_desc);
84 #elif defined(LTC_TWOFISH)
85    prng->yarrow.cipher = register_cipher(&twofish_desc);
86 #elif defined(LTC_RC6)
87    prng->yarrow.cipher = register_cipher(&rc6_desc);
88 #elif defined(LTC_RC5)
89    prng->yarrow.cipher = register_cipher(&rc5_desc);
90 #elif defined(LTC_SAFERP)
91    prng->yarrow.cipher = register_cipher(&saferp_desc);
92 #elif defined(LTC_RC2)
93    prng->yarrow.cipher = register_cipher(&rc2_desc);
94 #elif defined(LTC_NOEKEON)
95    prng->yarrow.cipher = register_cipher(&noekeon_desc);
96 #elif defined(LTC_ANUBIS)
97    prng->yarrow.cipher = register_cipher(&anubis_desc);
98 #elif defined(LTC_KSEED)
99    prng->yarrow.cipher = register_cipher(&kseed_desc);
100 #elif defined(LTC_KHAZAD)
101    prng->yarrow.cipher = register_cipher(&khazad_desc);
102 #elif defined(LTC_CAST5)
103    prng->yarrow.cipher = register_cipher(&cast5_desc);
104 #elif defined(LTC_XTEA)
105    prng->yarrow.cipher = register_cipher(&xtea_desc);
106 #elif defined(LTC_SAFER)
107    prng->yarrow.cipher = register_cipher(&safer_sk128_desc);
108 #elif defined(LTC_DES)
109    prng->yarrow.cipher = register_cipher(&des3_desc);
110 #else
111    #error LTC_YARROW needs at least one CIPHER
112 #endif
113    if ((err = cipher_is_valid(prng->yarrow.cipher)) != CRYPT_OK) {
114       return err;
115    }
116 
117 #ifdef LTC_SHA256
118    prng->yarrow.hash   = register_hash(&sha256_desc);
119 #elif defined(LTC_SHA512)
120    prng->yarrow.hash   = register_hash(&sha512_desc);
121 #elif defined(LTC_TIGER)
122    prng->yarrow.hash   = register_hash(&tiger_desc);
123 #elif defined(LTC_SHA1)
124    prng->yarrow.hash   = register_hash(&sha1_desc);
125 #elif defined(LTC_RIPEMD320)
126    prng->yarrow.hash   = register_hash(&rmd320_desc);
127 #elif defined(LTC_RIPEMD256)
128    prng->yarrow.hash   = register_hash(&rmd256_desc);
129 #elif defined(LTC_RIPEMD160)
130    prng->yarrow.hash   = register_hash(&rmd160_desc);
131 #elif defined(LTC_RIPEMD128)
132    prng->yarrow.hash   = register_hash(&rmd128_desc);
133 #elif defined(LTC_MD5)
134    prng->yarrow.hash   = register_hash(&md5_desc);
135 #elif defined(LTC_MD4)
136    prng->yarrow.hash   = register_hash(&md4_desc);
137 #elif defined(LTC_MD2)
138    prng->yarrow.hash   = register_hash(&md2_desc);
139 #elif defined(LTC_WHIRLPOOL)
140    prng->yarrow.hash   = register_hash(&whirlpool_desc);
141 #else
142    #error LTC_YARROW needs at least one HASH
143 #endif
144    if ((err = hash_is_valid(prng->yarrow.hash)) != CRYPT_OK) {
145       return err;
146    }
147 
148    /* zero the memory used */
149    zeromem(prng->yarrow.pool, sizeof(prng->yarrow.pool));
150    LTC_MUTEX_INIT(&prng->yarrow.prng_lock)
151 
152    return CRYPT_OK;
153 }
154 
155 /**
156   Add entropy to the PRNG state
157   @param in       The data to add
158   @param inlen    Length of the data to add
159   @param prng     PRNG state to update
160   @return CRYPT_OK if successful
161 */
162 int yarrow_add_entropy(const unsigned char *in, unsigned long inlen, prng_state *prng)
163 {
164    hash_state md;
165    int err;
166 
167    LTC_ARGCHK(in  != NULL);
168    LTC_ARGCHK(prng != NULL);
169 
170    LTC_MUTEX_LOCK(&prng->yarrow.prng_lock);
171 
172    if ((err = hash_is_valid(prng->yarrow.hash)) != CRYPT_OK) {
173       LTC_MUTEX_UNLOCK(&prng->yarrow.prng_lock);
174       return err;
175    }
176 
177    /* start the hash */
178    if ((err = hash_descriptor[prng->yarrow.hash].init(&md)) != CRYPT_OK) {
179       LTC_MUTEX_UNLOCK(&prng->yarrow.prng_lock);
180       return err;
181    }
182 
183    /* hash the current pool */
184    if ((err = hash_descriptor[prng->yarrow.hash].process(&md, prng->yarrow.pool,
185                                                         hash_descriptor[prng->yarrow.hash].hashsize)) != CRYPT_OK) {
186       LTC_MUTEX_UNLOCK(&prng->yarrow.prng_lock);
187       return err;
188    }
189 
190    /* add the new entropy */
191    if ((err = hash_descriptor[prng->yarrow.hash].process(&md, in, inlen)) != CRYPT_OK) {
192       LTC_MUTEX_UNLOCK(&prng->yarrow.prng_lock);
193       return err;
194    }
195 
196    /* store result */
197    if ((err = hash_descriptor[prng->yarrow.hash].done(&md, prng->yarrow.pool)) != CRYPT_OK) {
198       LTC_MUTEX_UNLOCK(&prng->yarrow.prng_lock);
199       return err;
200    }
201 
202    LTC_MUTEX_UNLOCK(&prng->yarrow.prng_lock);
203    return CRYPT_OK;
204 }
205 
206 /**
207   Make the PRNG ready to read from
208   @param prng   The PRNG to make active
209   @return CRYPT_OK if successful
210 */
211 int yarrow_ready(prng_state *prng)
212 {
213    int ks, err;
214 
215    LTC_ARGCHK(prng != NULL);
216    LTC_MUTEX_LOCK(&prng->yarrow.prng_lock);
217 
218    if ((err = hash_is_valid(prng->yarrow.hash)) != CRYPT_OK) {
219       LTC_MUTEX_UNLOCK(&prng->yarrow.prng_lock);
220       return err;
221    }
222 
223    if ((err = cipher_is_valid(prng->yarrow.cipher)) != CRYPT_OK) {
224       LTC_MUTEX_UNLOCK(&prng->yarrow.prng_lock);
225       return err;
226    }
227 
228    /* setup CTR mode using the "pool" as the key */
229    ks = (int)hash_descriptor[prng->yarrow.hash].hashsize;
230    if ((err = cipher_descriptor[prng->yarrow.cipher].keysize(&ks)) != CRYPT_OK) {
231       LTC_MUTEX_UNLOCK(&prng->yarrow.prng_lock);
232       return err;
233    }
234 
235    if ((err = ctr_start(prng->yarrow.cipher,     /* what cipher to use */
236                         prng->yarrow.pool,       /* IV */
237                         prng->yarrow.pool, ks,   /* KEY and key size */
238                         0,                       /* number of rounds */
239                         CTR_COUNTER_LITTLE_ENDIAN, /* little endian counter */
240                         &prng->yarrow.ctr)) != CRYPT_OK) {
241       LTC_MUTEX_UNLOCK(&prng->yarrow.prng_lock);
242       return err;
243    }
244    LTC_MUTEX_UNLOCK(&prng->yarrow.prng_lock);
245    return CRYPT_OK;
246 }
247 
248 /**
249   Read from the PRNG
250   @param out      Destination
251   @param outlen   Length of output
252   @param prng     The active PRNG to read from
253   @return Number of octets read
254 */
255 unsigned long yarrow_read(unsigned char *out, unsigned long outlen, prng_state *prng)
256 {
257    LTC_ARGCHK(out  != NULL);
258    LTC_ARGCHK(prng != NULL);
259 
260    LTC_MUTEX_LOCK(&prng->yarrow.prng_lock);
261 
262    /* put out in predictable state first */
263    zeromem(out, outlen);
264 
265    /* now randomize it */
266    if (ctr_encrypt(out, out, outlen, &prng->yarrow.ctr) != CRYPT_OK) {
267       LTC_MUTEX_UNLOCK(&prng->yarrow.prng_lock);
268       return 0;
269    }
270    LTC_MUTEX_UNLOCK(&prng->yarrow.prng_lock);
271    return outlen;
272 }
273 
274 /**
275   Terminate the PRNG
276   @param prng   The PRNG to terminate
277   @return CRYPT_OK if successful
278 */
279 int yarrow_done(prng_state *prng)
280 {
281    int err;
282    LTC_ARGCHK(prng != NULL);
283 
284    LTC_MUTEX_LOCK(&prng->yarrow.prng_lock);
285 
286    /* call cipher done when we invent one ;-) */
287 
288    /* we invented one */
289    err = ctr_done(&prng->yarrow.ctr);
290 
291    LTC_MUTEX_UNLOCK(&prng->yarrow.prng_lock);
292    return err;
293 }
294 
295 /**
296   Export the PRNG state
297   @param out       [out] Destination
298   @param outlen    [in/out] Max size and resulting size of the state
299   @param prng      The PRNG to export
300   @return CRYPT_OK if successful
301 */
302 int yarrow_export(unsigned char *out, unsigned long *outlen, prng_state *prng)
303 {
304    LTC_ARGCHK(out    != NULL);
305    LTC_ARGCHK(outlen != NULL);
306    LTC_ARGCHK(prng   != NULL);
307 
308    LTC_MUTEX_LOCK(&prng->yarrow.prng_lock);
309 
310    /* we'll write 64 bytes for s&g's */
311    if (*outlen < 64) {
312       LTC_MUTEX_UNLOCK(&prng->yarrow.prng_lock);
313       *outlen = 64;
314       return CRYPT_BUFFER_OVERFLOW;
315    }
316 
317    if (yarrow_read(out, 64, prng) != 64) {
318       LTC_MUTEX_UNLOCK(&prng->yarrow.prng_lock);
319       return CRYPT_ERROR_READPRNG;
320    }
321    *outlen = 64;
322 
323    return CRYPT_OK;
324 }
325 
326 /**
327   Import a PRNG state
328   @param in       The PRNG state
329   @param inlen    Size of the state
330   @param prng     The PRNG to import
331   @return CRYPT_OK if successful
332 */
333 int yarrow_import(const unsigned char *in, unsigned long inlen, prng_state *prng)
334 {
335    int err;
336 
337    LTC_ARGCHK(in   != NULL);
338    LTC_ARGCHK(prng != NULL);
339 
340    LTC_MUTEX_LOCK(&prng->yarrow.prng_lock);
341 
342    if (inlen != 64) {
343       LTC_MUTEX_UNLOCK(&prng->yarrow.prng_lock);
344       return CRYPT_INVALID_ARG;
345    }
346 
347    if ((err = yarrow_start(prng)) != CRYPT_OK) {
348       LTC_MUTEX_UNLOCK(&prng->yarrow.prng_lock);
349       return err;
350    }
351    err = yarrow_add_entropy(in, 64, prng);
352    LTC_MUTEX_UNLOCK(&prng->yarrow.prng_lock);
353    return err;
354 }
355 
356 /**
357   PRNG self-test
358   @return CRYPT_OK if successful, CRYPT_NOP if self-testing has been disabled
359 */
360 int yarrow_test(void)
361 {
362 #ifndef LTC_TEST
363    return CRYPT_NOP;
364 #else
365    int err;
366    prng_state prng;
367 
368    if ((err = yarrow_start(&prng)) != CRYPT_OK) {
369       return err;
370    }
371 
372    /* now let's test the hash/cipher that was chosen */
373    if ((err = cipher_descriptor[prng.yarrow.cipher].test()) != CRYPT_OK) {
374       return err;
375    }
376    if ((err = hash_descriptor[prng.yarrow.hash].test()) != CRYPT_OK) {
377       return err;
378    }
379 
380    return CRYPT_OK;
381 #endif
382 }
383 
384 #endif
385 
386 
387 /* $Source: /cvs/libtom/libtomcrypt/src/prngs/yarrow.c,v $ */
388 /* $Revision: 1.16 $ */
389 /* $Date: 2007/05/12 14:32:35 $ */
390