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