1*8411e6adSJerome Forissier /* LibTomCrypt, modular cryptographic library -- Tom St Denis */
2*8411e6adSJerome Forissier /* SPDX-License-Identifier: Unlicense */
35a913ee7SJerome Forissier #include "tomcrypt_private.h"
4b0104773SPascal Brand
5b0104773SPascal Brand /**
6b0104773SPascal Brand @file yarrow.c
7b0104773SPascal Brand Yarrow PRNG, Tom St Denis
8b0104773SPascal Brand */
9b0104773SPascal Brand
10b0104773SPascal Brand #ifdef LTC_YARROW
11b0104773SPascal Brand
12b0104773SPascal Brand const struct ltc_prng_descriptor yarrow_desc =
13b0104773SPascal Brand {
14b0104773SPascal Brand "yarrow", 64,
15b0104773SPascal Brand &yarrow_start,
16b0104773SPascal Brand &yarrow_add_entropy,
17b0104773SPascal Brand &yarrow_ready,
18b0104773SPascal Brand &yarrow_read,
19b0104773SPascal Brand &yarrow_done,
20b0104773SPascal Brand &yarrow_export,
21b0104773SPascal Brand &yarrow_import,
22b0104773SPascal Brand &yarrow_test
23b0104773SPascal Brand };
24b0104773SPascal Brand
25b0104773SPascal Brand /**
26b0104773SPascal Brand Start the PRNG
27b0104773SPascal Brand @param prng [out] The PRNG state to initialize
28b0104773SPascal Brand @return CRYPT_OK if successful
29b0104773SPascal Brand */
yarrow_start(prng_state * prng)30b0104773SPascal Brand int yarrow_start(prng_state *prng)
31b0104773SPascal Brand {
32b0104773SPascal Brand int err;
33b0104773SPascal Brand
34b0104773SPascal Brand LTC_ARGCHK(prng != NULL);
355a913ee7SJerome Forissier prng->ready = 0;
36b0104773SPascal Brand
37b0104773SPascal Brand /* these are the default hash/cipher combo used */
38b0104773SPascal Brand #ifdef LTC_RIJNDAEL
39b0104773SPascal Brand #if LTC_YARROW_AES==0
405a913ee7SJerome Forissier prng->u.yarrow.cipher = register_cipher(&rijndael_enc_desc);
41b0104773SPascal Brand #elif LTC_YARROW_AES==1
425a913ee7SJerome Forissier prng->u.yarrow.cipher = register_cipher(&aes_enc_desc);
43b0104773SPascal Brand #elif LTC_YARROW_AES==2
445a913ee7SJerome Forissier prng->u.yarrow.cipher = register_cipher(&rijndael_desc);
45b0104773SPascal Brand #elif LTC_YARROW_AES==3
465a913ee7SJerome Forissier prng->u.yarrow.cipher = register_cipher(&aes_desc);
47b0104773SPascal Brand #endif
48b0104773SPascal Brand #elif defined(LTC_BLOWFISH)
495a913ee7SJerome Forissier prng->u.yarrow.cipher = register_cipher(&blowfish_desc);
50b0104773SPascal Brand #elif defined(LTC_TWOFISH)
515a913ee7SJerome Forissier prng->u.yarrow.cipher = register_cipher(&twofish_desc);
52b0104773SPascal Brand #elif defined(LTC_RC6)
535a913ee7SJerome Forissier prng->u.yarrow.cipher = register_cipher(&rc6_desc);
54b0104773SPascal Brand #elif defined(LTC_RC5)
555a913ee7SJerome Forissier prng->u.yarrow.cipher = register_cipher(&rc5_desc);
56b0104773SPascal Brand #elif defined(LTC_SAFERP)
575a913ee7SJerome Forissier prng->u.yarrow.cipher = register_cipher(&saferp_desc);
58b0104773SPascal Brand #elif defined(LTC_RC2)
595a913ee7SJerome Forissier prng->u.yarrow.cipher = register_cipher(&rc2_desc);
60b0104773SPascal Brand #elif defined(LTC_NOEKEON)
615a913ee7SJerome Forissier prng->u.yarrow.cipher = register_cipher(&noekeon_desc);
62b0104773SPascal Brand #elif defined(LTC_ANUBIS)
635a913ee7SJerome Forissier prng->u.yarrow.cipher = register_cipher(&anubis_desc);
64b0104773SPascal Brand #elif defined(LTC_KSEED)
655a913ee7SJerome Forissier prng->u.yarrow.cipher = register_cipher(&kseed_desc);
66b0104773SPascal Brand #elif defined(LTC_KHAZAD)
675a913ee7SJerome Forissier prng->u.yarrow.cipher = register_cipher(&khazad_desc);
68b0104773SPascal Brand #elif defined(LTC_CAST5)
695a913ee7SJerome Forissier prng->u.yarrow.cipher = register_cipher(&cast5_desc);
70b0104773SPascal Brand #elif defined(LTC_XTEA)
715a913ee7SJerome Forissier prng->u.yarrow.cipher = register_cipher(&xtea_desc);
72b0104773SPascal Brand #elif defined(LTC_SAFER)
735a913ee7SJerome Forissier prng->u.yarrow.cipher = register_cipher(&safer_sk128_desc);
74b0104773SPascal Brand #elif defined(LTC_DES)
755a913ee7SJerome Forissier prng->u.yarrow.cipher = register_cipher(&des3_desc);
76b0104773SPascal Brand #else
77b0104773SPascal Brand #error LTC_YARROW needs at least one CIPHER
78b0104773SPascal Brand #endif
795a913ee7SJerome Forissier if ((err = cipher_is_valid(prng->u.yarrow.cipher)) != CRYPT_OK) {
80b0104773SPascal Brand return err;
81b0104773SPascal Brand }
82b0104773SPascal Brand
83b0104773SPascal Brand #ifdef LTC_SHA256
845a913ee7SJerome Forissier prng->u.yarrow.hash = register_hash(&sha256_desc);
85b0104773SPascal Brand #elif defined(LTC_SHA512)
865a913ee7SJerome Forissier prng->u.yarrow.hash = register_hash(&sha512_desc);
87b0104773SPascal Brand #elif defined(LTC_TIGER)
885a913ee7SJerome Forissier prng->u.yarrow.hash = register_hash(&tiger_desc);
89b0104773SPascal Brand #elif defined(LTC_SHA1)
905a913ee7SJerome Forissier prng->u.yarrow.hash = register_hash(&sha1_desc);
91b0104773SPascal Brand #elif defined(LTC_RIPEMD320)
925a913ee7SJerome Forissier prng->u.yarrow.hash = register_hash(&rmd320_desc);
93b0104773SPascal Brand #elif defined(LTC_RIPEMD256)
945a913ee7SJerome Forissier prng->u.yarrow.hash = register_hash(&rmd256_desc);
95b0104773SPascal Brand #elif defined(LTC_RIPEMD160)
965a913ee7SJerome Forissier prng->u.yarrow.hash = register_hash(&rmd160_desc);
97b0104773SPascal Brand #elif defined(LTC_RIPEMD128)
985a913ee7SJerome Forissier prng->u.yarrow.hash = register_hash(&rmd128_desc);
99b0104773SPascal Brand #elif defined(LTC_MD5)
1005a913ee7SJerome Forissier prng->u.yarrow.hash = register_hash(&md5_desc);
101b0104773SPascal Brand #elif defined(LTC_MD4)
1025a913ee7SJerome Forissier prng->u.yarrow.hash = register_hash(&md4_desc);
103b0104773SPascal Brand #elif defined(LTC_MD2)
1045a913ee7SJerome Forissier prng->u.yarrow.hash = register_hash(&md2_desc);
105b0104773SPascal Brand #elif defined(LTC_WHIRLPOOL)
1065a913ee7SJerome Forissier prng->u.yarrow.hash = register_hash(&whirlpool_desc);
107b0104773SPascal Brand #else
108b0104773SPascal Brand #error LTC_YARROW needs at least one HASH
109b0104773SPascal Brand #endif
1105a913ee7SJerome Forissier if ((err = hash_is_valid(prng->u.yarrow.hash)) != CRYPT_OK) {
111b0104773SPascal Brand return err;
112b0104773SPascal Brand }
113b0104773SPascal Brand
114b0104773SPascal Brand /* zero the memory used */
1155a913ee7SJerome Forissier zeromem(prng->u.yarrow.pool, sizeof(prng->u.yarrow.pool));
1165a913ee7SJerome Forissier LTC_MUTEX_INIT(&prng->lock)
117b0104773SPascal Brand
118b0104773SPascal Brand return CRYPT_OK;
119b0104773SPascal Brand }
120b0104773SPascal Brand
121b0104773SPascal Brand /**
122b0104773SPascal Brand Add entropy to the PRNG state
123b0104773SPascal Brand @param in The data to add
124b0104773SPascal Brand @param inlen Length of the data to add
125b0104773SPascal Brand @param prng PRNG state to update
126b0104773SPascal Brand @return CRYPT_OK if successful
127b0104773SPascal Brand */
yarrow_add_entropy(const unsigned char * in,unsigned long inlen,prng_state * prng)128b0104773SPascal Brand int yarrow_add_entropy(const unsigned char *in, unsigned long inlen, prng_state *prng)
129b0104773SPascal Brand {
130b0104773SPascal Brand hash_state md;
131b0104773SPascal Brand int err;
132b0104773SPascal Brand
133b0104773SPascal Brand LTC_ARGCHK(prng != NULL);
1345a913ee7SJerome Forissier LTC_ARGCHK(in != NULL);
1355a913ee7SJerome Forissier LTC_ARGCHK(inlen > 0);
136b0104773SPascal Brand
1375a913ee7SJerome Forissier LTC_MUTEX_LOCK(&prng->lock);
138b0104773SPascal Brand
1395a913ee7SJerome Forissier if ((err = hash_is_valid(prng->u.yarrow.hash)) != CRYPT_OK) {
1405a913ee7SJerome Forissier goto LBL_UNLOCK;
141b0104773SPascal Brand }
142b0104773SPascal Brand
143b0104773SPascal Brand /* start the hash */
1445a913ee7SJerome Forissier if ((err = hash_descriptor[prng->u.yarrow.hash]->init(&md)) != CRYPT_OK) {
1455a913ee7SJerome Forissier goto LBL_UNLOCK;
146b0104773SPascal Brand }
147b0104773SPascal Brand
148b0104773SPascal Brand /* hash the current pool */
1495a913ee7SJerome Forissier if ((err = hash_descriptor[prng->u.yarrow.hash]->process(&md, prng->u.yarrow.pool,
1505a913ee7SJerome Forissier hash_descriptor[prng->u.yarrow.hash]->hashsize)) != CRYPT_OK) {
1515a913ee7SJerome Forissier goto LBL_UNLOCK;
152b0104773SPascal Brand }
153b0104773SPascal Brand
154b0104773SPascal Brand /* add the new entropy */
1555a913ee7SJerome Forissier if ((err = hash_descriptor[prng->u.yarrow.hash]->process(&md, in, inlen)) != CRYPT_OK) {
1565a913ee7SJerome Forissier goto LBL_UNLOCK;
157b0104773SPascal Brand }
158b0104773SPascal Brand
159b0104773SPascal Brand /* store result */
1605a913ee7SJerome Forissier err = hash_descriptor[prng->u.yarrow.hash]->done(&md, prng->u.yarrow.pool);
161b0104773SPascal Brand
1625a913ee7SJerome Forissier LBL_UNLOCK:
1635a913ee7SJerome Forissier LTC_MUTEX_UNLOCK(&prng->lock);
1645a913ee7SJerome Forissier return err;
165b0104773SPascal Brand }
166b0104773SPascal Brand
167b0104773SPascal Brand /**
168b0104773SPascal Brand Make the PRNG ready to read from
169b0104773SPascal Brand @param prng The PRNG to make active
170b0104773SPascal Brand @return CRYPT_OK if successful
171b0104773SPascal Brand */
yarrow_ready(prng_state * prng)172b0104773SPascal Brand int yarrow_ready(prng_state *prng)
173b0104773SPascal Brand {
174b0104773SPascal Brand int ks, err;
175b0104773SPascal Brand
176b0104773SPascal Brand LTC_ARGCHK(prng != NULL);
177b0104773SPascal Brand
1785a913ee7SJerome Forissier LTC_MUTEX_LOCK(&prng->lock);
1795a913ee7SJerome Forissier
1805a913ee7SJerome Forissier if ((err = hash_is_valid(prng->u.yarrow.hash)) != CRYPT_OK) {
1815a913ee7SJerome Forissier goto LBL_UNLOCK;
182b0104773SPascal Brand }
183b0104773SPascal Brand
1845a913ee7SJerome Forissier if ((err = cipher_is_valid(prng->u.yarrow.cipher)) != CRYPT_OK) {
1855a913ee7SJerome Forissier goto LBL_UNLOCK;
186b0104773SPascal Brand }
187b0104773SPascal Brand
188b0104773SPascal Brand /* setup CTR mode using the "pool" as the key */
1895a913ee7SJerome Forissier ks = (int)hash_descriptor[prng->u.yarrow.hash]->hashsize;
1905a913ee7SJerome Forissier if ((err = cipher_descriptor[prng->u.yarrow.cipher]->keysize(&ks)) != CRYPT_OK) {
1915a913ee7SJerome Forissier goto LBL_UNLOCK;
192b0104773SPascal Brand }
193b0104773SPascal Brand
1945a913ee7SJerome Forissier if ((err = ctr_start(prng->u.yarrow.cipher, /* what cipher to use */
1955a913ee7SJerome Forissier prng->u.yarrow.pool, /* IV */
1965a913ee7SJerome Forissier prng->u.yarrow.pool, ks, /* KEY and key size */
197b0104773SPascal Brand 0, /* number of rounds */
198b0104773SPascal Brand CTR_COUNTER_LITTLE_ENDIAN, /* little endian counter */
1995a913ee7SJerome Forissier &prng->u.yarrow.ctr)) != CRYPT_OK) {
2005a913ee7SJerome Forissier goto LBL_UNLOCK;
201b0104773SPascal Brand }
2025a913ee7SJerome Forissier prng->ready = 1;
2035a913ee7SJerome Forissier
2045a913ee7SJerome Forissier LBL_UNLOCK:
2055a913ee7SJerome Forissier LTC_MUTEX_UNLOCK(&prng->lock);
2065a913ee7SJerome Forissier return err;
207b0104773SPascal Brand }
208b0104773SPascal Brand
209b0104773SPascal Brand /**
210b0104773SPascal Brand Read from the PRNG
211b0104773SPascal Brand @param out Destination
212b0104773SPascal Brand @param outlen Length of output
213b0104773SPascal Brand @param prng The active PRNG to read from
214b0104773SPascal Brand @return Number of octets read
215b0104773SPascal Brand */
yarrow_read(unsigned char * out,unsigned long outlen,prng_state * prng)216b0104773SPascal Brand unsigned long yarrow_read(unsigned char *out, unsigned long outlen, prng_state *prng)
217b0104773SPascal Brand {
2185a913ee7SJerome Forissier if (outlen == 0 || prng == NULL || out == NULL) return 0;
219b0104773SPascal Brand
2205a913ee7SJerome Forissier LTC_MUTEX_LOCK(&prng->lock);
2215a913ee7SJerome Forissier
2225a913ee7SJerome Forissier if (!prng->ready) {
2235a913ee7SJerome Forissier outlen = 0;
2245a913ee7SJerome Forissier goto LBL_UNLOCK;
2255a913ee7SJerome Forissier }
226b0104773SPascal Brand
227b0104773SPascal Brand /* put out in predictable state first */
228b0104773SPascal Brand zeromem(out, outlen);
229b0104773SPascal Brand
230b0104773SPascal Brand /* now randomize it */
2315a913ee7SJerome Forissier if (ctr_encrypt(out, out, outlen, &prng->u.yarrow.ctr) != CRYPT_OK) {
2325a913ee7SJerome Forissier outlen = 0;
233b0104773SPascal Brand }
2345a913ee7SJerome Forissier
2355a913ee7SJerome Forissier LBL_UNLOCK:
2365a913ee7SJerome Forissier LTC_MUTEX_UNLOCK(&prng->lock);
237b0104773SPascal Brand return outlen;
238b0104773SPascal Brand }
239b0104773SPascal Brand
240b0104773SPascal Brand /**
241b0104773SPascal Brand Terminate the PRNG
242b0104773SPascal Brand @param prng The PRNG to terminate
243b0104773SPascal Brand @return CRYPT_OK if successful
244b0104773SPascal Brand */
yarrow_done(prng_state * prng)245b0104773SPascal Brand int yarrow_done(prng_state *prng)
246b0104773SPascal Brand {
247b0104773SPascal Brand int err;
248b0104773SPascal Brand LTC_ARGCHK(prng != NULL);
249b0104773SPascal Brand
2505a913ee7SJerome Forissier LTC_MUTEX_LOCK(&prng->lock);
2515a913ee7SJerome Forissier prng->ready = 0;
252b0104773SPascal Brand
253b0104773SPascal Brand /* call cipher done when we invent one ;-) */
254b0104773SPascal Brand
255b0104773SPascal Brand /* we invented one */
2565a913ee7SJerome Forissier err = ctr_done(&prng->u.yarrow.ctr);
257b0104773SPascal Brand
2585a913ee7SJerome Forissier LTC_MUTEX_UNLOCK(&prng->lock);
2595a913ee7SJerome Forissier LTC_MUTEX_DESTROY(&prng->lock);
260b0104773SPascal Brand return err;
261b0104773SPascal Brand }
262b0104773SPascal Brand
263b0104773SPascal Brand /**
264b0104773SPascal Brand Export the PRNG state
265b0104773SPascal Brand @param out [out] Destination
266b0104773SPascal Brand @param outlen [in/out] Max size and resulting size of the state
267b0104773SPascal Brand @param prng The PRNG to export
268b0104773SPascal Brand @return CRYPT_OK if successful
269b0104773SPascal Brand */
LTC_PRNG_EXPORT(yarrow)270*8411e6adSJerome Forissier LTC_PRNG_EXPORT(yarrow)
271b0104773SPascal Brand
272b0104773SPascal Brand /**
273b0104773SPascal Brand Import a PRNG state
274b0104773SPascal Brand @param in The PRNG state
275b0104773SPascal Brand @param inlen Size of the state
276b0104773SPascal Brand @param prng The PRNG to import
277b0104773SPascal Brand @return CRYPT_OK if successful
278b0104773SPascal Brand */
279b0104773SPascal Brand int yarrow_import(const unsigned char *in, unsigned long inlen, prng_state *prng)
280b0104773SPascal Brand {
281b0104773SPascal Brand int err;
282b0104773SPascal Brand
283b0104773SPascal Brand LTC_ARGCHK(in != NULL);
284b0104773SPascal Brand LTC_ARGCHK(prng != NULL);
2855a913ee7SJerome Forissier if (inlen < (unsigned long)yarrow_desc.export_size) return CRYPT_INVALID_ARG;
286b0104773SPascal Brand
2875a913ee7SJerome Forissier if ((err = yarrow_start(prng)) != CRYPT_OK) return err;
2885a913ee7SJerome Forissier if ((err = yarrow_add_entropy(in, inlen, prng)) != CRYPT_OK) return err;
2895a913ee7SJerome Forissier return CRYPT_OK;
290b0104773SPascal Brand }
291b0104773SPascal Brand
292b0104773SPascal Brand /**
293b0104773SPascal Brand PRNG self-test
294b0104773SPascal Brand @return CRYPT_OK if successful, CRYPT_NOP if self-testing has been disabled
295b0104773SPascal Brand */
yarrow_test(void)296b0104773SPascal Brand int yarrow_test(void)
297b0104773SPascal Brand {
298b0104773SPascal Brand #ifndef LTC_TEST
299b0104773SPascal Brand return CRYPT_NOP;
300b0104773SPascal Brand #else
301b0104773SPascal Brand int err;
302b0104773SPascal Brand prng_state prng;
303b0104773SPascal Brand
304b0104773SPascal Brand if ((err = yarrow_start(&prng)) != CRYPT_OK) {
305b0104773SPascal Brand return err;
306b0104773SPascal Brand }
307b0104773SPascal Brand
308b0104773SPascal Brand /* now let's test the hash/cipher that was chosen */
3095a913ee7SJerome Forissier if (cipher_descriptor[prng.u.yarrow.cipher]->test &&
3105a913ee7SJerome Forissier ((err = cipher_descriptor[prng.u.yarrow.cipher]->test()) != CRYPT_OK)) {
311b0104773SPascal Brand return err;
312b0104773SPascal Brand }
3135a913ee7SJerome Forissier if (hash_descriptor[prng.u.yarrow.hash]->test &&
3145a913ee7SJerome Forissier ((err = hash_descriptor[prng.u.yarrow.hash]->test()) != CRYPT_OK)) {
315b0104773SPascal Brand return err;
316b0104773SPascal Brand }
317b0104773SPascal Brand
318b0104773SPascal Brand return CRYPT_OK;
319b0104773SPascal Brand #endif
320b0104773SPascal Brand }
321b0104773SPascal Brand
322b0104773SPascal Brand #endif
323b0104773SPascal Brand
324