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