1 /* LibTomCrypt, modular cryptographic library -- Tom St Denis
3 * LibTomCrypt is a library that provides various cryptographic
4 * algorithms in a highly modular and flexible manner.
6 * The library is free for all purposes without any express
13 Yarrow PRNG, Tom St Denis
18 const struct ltc_prng_descriptor yarrow_desc =
33 @param prng [out] The PRNG state to initialize
34 @return CRYPT_OK if successful
36 int yarrow_start(prng_state *prng)
40 LTC_ARGCHK(prng != NULL);
43 /* these are the default hash/cipher combo used */
46 prng->yarrow.cipher = register_cipher(&rijndael_enc_desc);
47 #elif LTC_YARROW_AES==1
48 prng->yarrow.cipher = register_cipher(&aes_enc_desc);
49 #elif LTC_YARROW_AES==2
50 prng->yarrow.cipher = register_cipher(&rijndael_desc);
51 #elif LTC_YARROW_AES==3
52 prng->yarrow.cipher = register_cipher(&aes_desc);
54 #elif defined(LTC_BLOWFISH)
55 prng->yarrow.cipher = register_cipher(&blowfish_desc);
56 #elif defined(LTC_TWOFISH)
57 prng->yarrow.cipher = register_cipher(&twofish_desc);
58 #elif defined(LTC_RC6)
59 prng->yarrow.cipher = register_cipher(&rc6_desc);
60 #elif defined(LTC_RC5)
61 prng->yarrow.cipher = register_cipher(&rc5_desc);
62 #elif defined(LTC_SAFERP)
63 prng->yarrow.cipher = register_cipher(&saferp_desc);
64 #elif defined(LTC_RC2)
65 prng->yarrow.cipher = register_cipher(&rc2_desc);
66 #elif defined(LTC_NOEKEON)
67 prng->yarrow.cipher = register_cipher(&noekeon_desc);
68 #elif defined(LTC_ANUBIS)
69 prng->yarrow.cipher = register_cipher(&anubis_desc);
70 #elif defined(LTC_KSEED)
71 prng->yarrow.cipher = register_cipher(&kseed_desc);
72 #elif defined(LTC_KHAZAD)
73 prng->yarrow.cipher = register_cipher(&khazad_desc);
74 #elif defined(LTC_CAST5)
75 prng->yarrow.cipher = register_cipher(&cast5_desc);
76 #elif defined(LTC_XTEA)
77 prng->yarrow.cipher = register_cipher(&xtea_desc);
78 #elif defined(LTC_SAFER)
79 prng->yarrow.cipher = register_cipher(&safer_sk128_desc);
80 #elif defined(LTC_DES)
81 prng->yarrow.cipher = register_cipher(&des3_desc);
83 #error LTC_YARROW needs at least one CIPHER
85 if ((err = cipher_is_valid(prng->yarrow.cipher)) != CRYPT_OK) {
90 prng->yarrow.hash = register_hash(&sha256_desc);
91 #elif defined(LTC_SHA512)
92 prng->yarrow.hash = register_hash(&sha512_desc);
93 #elif defined(LTC_TIGER)
94 prng->yarrow.hash = register_hash(&tiger_desc);
95 #elif defined(LTC_SHA1)
96 prng->yarrow.hash = register_hash(&sha1_desc);
97 #elif defined(LTC_RIPEMD320)
98 prng->yarrow.hash = register_hash(&rmd320_desc);
99 #elif defined(LTC_RIPEMD256)
100 prng->yarrow.hash = register_hash(&rmd256_desc);
101 #elif defined(LTC_RIPEMD160)
102 prng->yarrow.hash = register_hash(&rmd160_desc);
103 #elif defined(LTC_RIPEMD128)
104 prng->yarrow.hash = register_hash(&rmd128_desc);
105 #elif defined(LTC_MD5)
106 prng->yarrow.hash = register_hash(&md5_desc);
107 #elif defined(LTC_MD4)
108 prng->yarrow.hash = register_hash(&md4_desc);
109 #elif defined(LTC_MD2)
110 prng->yarrow.hash = register_hash(&md2_desc);
111 #elif defined(LTC_WHIRLPOOL)
112 prng->yarrow.hash = register_hash(&whirlpool_desc);
114 #error LTC_YARROW needs at least one HASH
116 if ((err = hash_is_valid(prng->yarrow.hash)) != CRYPT_OK) {
120 /* zero the memory used */
121 zeromem(prng->yarrow.pool, sizeof(prng->yarrow.pool));
122 LTC_MUTEX_INIT(&prng->lock)
128 Add entropy to the PRNG state
129 @param in The data to add
130 @param inlen Length of the data to add
131 @param prng PRNG state to update
132 @return CRYPT_OK if successful
134 int yarrow_add_entropy(const unsigned char *in, unsigned long inlen, prng_state *prng)
139 LTC_ARGCHK(prng != NULL);
140 LTC_ARGCHK(in != NULL);
141 LTC_ARGCHK(inlen > 0);
143 LTC_MUTEX_LOCK(&prng->lock);
145 if ((err = hash_is_valid(prng->yarrow.hash)) != CRYPT_OK) {
150 if ((err = hash_descriptor[prng->yarrow.hash].init(&md)) != CRYPT_OK) {
154 /* hash the current pool */
155 if ((err = hash_descriptor[prng->yarrow.hash].process(&md, prng->yarrow.pool,
156 hash_descriptor[prng->yarrow.hash].hashsize)) != CRYPT_OK) {
160 /* add the new entropy */
161 if ((err = hash_descriptor[prng->yarrow.hash].process(&md, in, inlen)) != CRYPT_OK) {
166 err = hash_descriptor[prng->yarrow.hash].done(&md, prng->yarrow.pool);
169 LTC_MUTEX_UNLOCK(&prng->lock);
174 Make the PRNG ready to read from
175 @param prng The PRNG to make active
176 @return CRYPT_OK if successful
178 int yarrow_ready(prng_state *prng)
182 LTC_ARGCHK(prng != NULL);
184 LTC_MUTEX_LOCK(&prng->lock);
186 if ((err = hash_is_valid(prng->yarrow.hash)) != CRYPT_OK) {
190 if ((err = cipher_is_valid(prng->yarrow.cipher)) != CRYPT_OK) {
194 /* setup CTR mode using the "pool" as the key */
195 ks = (int)hash_descriptor[prng->yarrow.hash].hashsize;
196 if ((err = cipher_descriptor[prng->yarrow.cipher].keysize(&ks)) != CRYPT_OK) {
200 if ((err = ctr_start(prng->yarrow.cipher, /* what cipher to use */
201 prng->yarrow.pool, /* IV */
202 prng->yarrow.pool, ks, /* KEY and key size */
203 0, /* number of rounds */
204 CTR_COUNTER_LITTLE_ENDIAN, /* little endian counter */
205 &prng->yarrow.ctr)) != CRYPT_OK) {
211 LTC_MUTEX_UNLOCK(&prng->lock);
217 @param out Destination
218 @param outlen Length of output
219 @param prng The active PRNG to read from
220 @return Number of octets read
222 unsigned long yarrow_read(unsigned char *out, unsigned long outlen, prng_state *prng)
224 if (outlen == 0 || prng == NULL || out == NULL) return 0;
226 LTC_MUTEX_LOCK(&prng->lock);
233 /* put out in predictable state first */
234 zeromem(out, outlen);
236 /* now randomize it */
237 if (ctr_encrypt(out, out, outlen, &prng->yarrow.ctr) != CRYPT_OK) {
242 LTC_MUTEX_UNLOCK(&prng->lock);
248 @param prng The PRNG to terminate
249 @return CRYPT_OK if successful
251 int yarrow_done(prng_state *prng)
254 LTC_ARGCHK(prng != NULL);
256 LTC_MUTEX_LOCK(&prng->lock);
259 /* call cipher done when we invent one ;-) */
261 /* we invented one */
262 err = ctr_done(&prng->yarrow.ctr);
264 LTC_MUTEX_UNLOCK(&prng->lock);
265 LTC_MUTEX_DESTROY(&prng->lock);
270 Export the PRNG state
271 @param out [out] Destination
272 @param outlen [in/out] Max size and resulting size of the state
273 @param prng The PRNG to export
274 @return CRYPT_OK if successful
276 int yarrow_export(unsigned char *out, unsigned long *outlen, prng_state *prng)
278 unsigned long len = yarrow_desc.export_size;
280 LTC_ARGCHK(out != NULL);
281 LTC_ARGCHK(outlen != NULL);
282 LTC_ARGCHK(prng != NULL);
286 return CRYPT_BUFFER_OVERFLOW;
289 if (yarrow_read(out, len, prng) != len) {
290 return CRYPT_ERROR_READPRNG;
299 @param in The PRNG state
300 @param inlen Size of the state
301 @param prng The PRNG to import
302 @return CRYPT_OK if successful
304 int yarrow_import(const unsigned char *in, unsigned long inlen, prng_state *prng)
308 LTC_ARGCHK(in != NULL);
309 LTC_ARGCHK(prng != NULL);
310 if (inlen < (unsigned long)yarrow_desc.export_size) return CRYPT_INVALID_ARG;
312 if ((err = yarrow_start(prng)) != CRYPT_OK) return err;
313 if ((err = yarrow_add_entropy(in, inlen, prng)) != CRYPT_OK) return err;
319 @return CRYPT_OK if successful, CRYPT_NOP if self-testing has been disabled
321 int yarrow_test(void)
329 if ((err = yarrow_start(&prng)) != CRYPT_OK) {
333 /* now let's test the hash/cipher that was chosen */
334 if (cipher_descriptor[prng.yarrow.cipher].test &&
335 ((err = cipher_descriptor[prng.yarrow.cipher].test()) != CRYPT_OK)) {
338 if (hash_descriptor[prng.yarrow.hash].test &&
339 ((err = hash_descriptor[prng.yarrow.hash].test()) != CRYPT_OK)) {
350 /* ref: $Format:%D$ */
351 /* git commit: $Format:%H$ */
352 /* commit time: $Format:%ai$ */