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