comparison src/prngs/yarrow.c @ 191:1c15b283127b libtomcrypt-orig

Import of libtomcrypt 1.02 with manual path rename rearrangement etc
author Matt Johnston <matt@ucc.asn.au>
date Fri, 06 May 2005 13:23:02 +0000
parents
children 39d5d58461d6
comparison
equal deleted inserted replaced
143:5d99163f7e32 191:1c15b283127b
1 /* LibTomCrypt, modular cryptographic library -- Tom St Denis
2 *
3 * LibTomCrypt is a library that provides various cryptographic
4 * algorithms in a highly modular and flexible manner.
5 *
6 * The library is free for all purposes without any express
7 * guarantee it works.
8 *
9 * Tom St Denis, [email protected], http://libtomcrypt.org
10 */
11 #include "tomcrypt.h"
12
13 /**
14 @file yarrow.c
15 Yarrow PRNG, Tom St Denis
16 */
17
18 #ifdef YARROW
19
20 const struct ltc_prng_descriptor yarrow_desc =
21 {
22 "yarrow", 64,
23 &yarrow_start,
24 &yarrow_add_entropy,
25 &yarrow_ready,
26 &yarrow_read,
27 &yarrow_done,
28 &yarrow_export,
29 &yarrow_import,
30 &yarrow_test
31 };
32
33 /**
34 Start the PRNG
35 @param prng [out] The PRNG state to initialize
36 @return CRYPT_OK if successful
37 */
38 int yarrow_start(prng_state *prng)
39 {
40 int err;
41
42 LTC_ARGCHK(prng != NULL);
43
44 /* these are the default hash/cipher combo used */
45 #ifdef RIJNDAEL
46 #if YARROW_AES==0
47 prng->yarrow.cipher = register_cipher(&rijndael_enc_desc);
48 #elif YARROW_AES==1
49 prng->yarrow.cipher = register_cipher(&aes_enc_desc);
50 #elif YARROW_AES==2
51 prng->yarrow.cipher = register_cipher(&rijndael_desc);
52 #elif YARROW_AES==3
53 prng->yarrow.cipher = register_cipher(&aes_desc);
54 #endif
55 #elif defined(BLOWFISH)
56 prng->yarrow.cipher = register_cipher(&blowfish_desc);
57 #elif defined(TWOFISH)
58 prng->yarrow.cipher = register_cipher(&twofish_desc);
59 #elif defined(RC6)
60 prng->yarrow.cipher = register_cipher(&rc6_desc);
61 #elif defined(RC5)
62 prng->yarrow.cipher = register_cipher(&rc5_desc);
63 #elif defined(SAFERP)
64 prng->yarrow.cipher = register_cipher(&saferp_desc);
65 #elif defined(RC2)
66 prng->yarrow.cipher = register_cipher(&rc2_desc);
67 #elif defined(NOEKEON)
68 prng->yarrow.cipher = register_cipher(&noekeon_desc);
69 #elif defined(CAST5)
70 prng->yarrow.cipher = register_cipher(&cast5_desc);
71 #elif defined(XTEA)
72 prng->yarrow.cipher = register_cipher(&xtea_desc);
73 #elif defined(SAFER)
74 prng->yarrow.cipher = register_cipher(&safer_sk128_desc);
75 #elif defined(DES)
76 prng->yarrow.cipher = register_cipher(&des3_desc);
77 #else
78 #error YARROW needs at least one CIPHER
79 #endif
80 if ((err = cipher_is_valid(prng->yarrow.cipher)) != CRYPT_OK) {
81 return err;
82 }
83
84 #ifdef SHA256
85 prng->yarrow.hash = register_hash(&sha256_desc);
86 #elif defined(SHA512)
87 prng->yarrow.hash = register_hash(&sha512_desc);
88 #elif defined(TIGER)
89 prng->yarrow.hash = register_hash(&tiger_desc);
90 #elif defined(SHA1)
91 prng->yarrow.hash = register_hash(&sha1_desc);
92 #elif defined(RIPEMD160)
93 prng->yarrow.hash = register_hash(&rmd160_desc);
94 #elif defined(RIPEMD128)
95 prng->yarrow.hash = register_hash(&rmd128_desc);
96 #elif defined(MD5)
97 prng->yarrow.hash = register_hash(&md5_desc);
98 #elif defined(MD4)
99 prng->yarrow.hash = register_hash(&md4_desc);
100 #elif defined(MD2)
101 prng->yarrow.hash = register_hash(&md2_desc);
102 #elif defined(WHIRLPOOL)
103 prng->yarrow.hash = register_hash(&whirlpool_desc);
104 #else
105 #error YARROW needs at least one HASH
106 #endif
107 if ((err = hash_is_valid(prng->yarrow.hash)) != CRYPT_OK) {
108 return err;
109 }
110
111 /* zero the memory used */
112 zeromem(prng->yarrow.pool, sizeof(prng->yarrow.pool));
113
114 return CRYPT_OK;
115 }
116
117 /**
118 Add entropy to the PRNG state
119 @param in The data to add
120 @param inlen Length of the data to add
121 @param prng PRNG state to update
122 @return CRYPT_OK if successful
123 */
124 int yarrow_add_entropy(const unsigned char *in, unsigned long inlen, prng_state *prng)
125 {
126 hash_state md;
127 int err;
128
129 LTC_ARGCHK(in != NULL);
130 LTC_ARGCHK(prng != NULL);
131
132 if ((err = hash_is_valid(prng->yarrow.hash)) != CRYPT_OK) {
133 return err;
134 }
135
136 /* start the hash */
137 if ((err = hash_descriptor[prng->yarrow.hash].init(&md)) != CRYPT_OK) {
138 return err;
139 }
140
141 /* hash the current pool */
142 if ((err = hash_descriptor[prng->yarrow.hash].process(&md, prng->yarrow.pool,
143 hash_descriptor[prng->yarrow.hash].hashsize)) != CRYPT_OK) {
144 return err;
145 }
146
147 /* add the new entropy */
148 if ((err = hash_descriptor[prng->yarrow.hash].process(&md, in, inlen)) != CRYPT_OK) {
149 return err;
150 }
151
152 /* store result */
153 if ((err = hash_descriptor[prng->yarrow.hash].done(&md, prng->yarrow.pool)) != CRYPT_OK) {
154 return err;
155 }
156
157 return CRYPT_OK;
158 }
159
160 /**
161 Make the PRNG ready to read from
162 @param prng The PRNG to make active
163 @return CRYPT_OK if successful
164 */
165 int yarrow_ready(prng_state *prng)
166 {
167 int ks, err;
168
169 LTC_ARGCHK(prng != NULL);
170
171 if ((err = hash_is_valid(prng->yarrow.hash)) != CRYPT_OK) {
172 return err;
173 }
174
175 if ((err = cipher_is_valid(prng->yarrow.cipher)) != CRYPT_OK) {
176 return err;
177 }
178
179 /* setup CTR mode using the "pool" as the key */
180 ks = (int)hash_descriptor[prng->yarrow.hash].hashsize;
181 if ((err = cipher_descriptor[prng->yarrow.cipher].keysize(&ks)) != CRYPT_OK) {
182 return err;
183 }
184
185 if ((err = ctr_start(prng->yarrow.cipher, /* what cipher to use */
186 prng->yarrow.pool, /* IV */
187 prng->yarrow.pool, ks, /* KEY and key size */
188 0, /* number of rounds */
189 &prng->yarrow.ctr)) != CRYPT_OK) {
190 return err;
191 }
192 return CRYPT_OK;
193 }
194
195 /**
196 Read from the PRNG
197 @param out Destination
198 @param outlen Length of output
199 @param prng The active PRNG to read from
200 @return Number of octets read
201 */
202 unsigned long yarrow_read(unsigned char *out, unsigned long outlen, prng_state *prng)
203 {
204 LTC_ARGCHK(out != NULL);
205 LTC_ARGCHK(prng != NULL);
206
207 /* put out in predictable state first */
208 zeromem(out, outlen);
209
210 /* now randomize it */
211 if (ctr_encrypt(out, out, outlen, &prng->yarrow.ctr) != CRYPT_OK) {
212 return 0;
213 }
214 return outlen;
215 }
216
217 /**
218 Terminate the PRNG
219 @param prng The PRNG to terminate
220 @return CRYPT_OK if successful
221 */
222 int yarrow_done(prng_state *prng)
223 {
224 LTC_ARGCHK(prng != NULL);
225
226 /* call cipher done when we invent one ;-) */
227
228 /* we invented one */
229 return ctr_done(&prng->yarrow.ctr);
230 }
231
232 /**
233 Export the PRNG state
234 @param out [out] Destination
235 @param outlen [in/out] Max size and resulting size of the state
236 @param prng The PRNG to export
237 @return CRYPT_OK if successful
238 */
239 int yarrow_export(unsigned char *out, unsigned long *outlen, prng_state *prng)
240 {
241 LTC_ARGCHK(out != NULL);
242 LTC_ARGCHK(outlen != NULL);
243 LTC_ARGCHK(prng != NULL);
244
245 /* we'll write 64 bytes for s&g's */
246 if (*outlen < 64) {
247 return CRYPT_BUFFER_OVERFLOW;
248 }
249
250 if (yarrow_read(out, 64, prng) != 64) {
251 return CRYPT_ERROR_READPRNG;
252 }
253 *outlen = 64;
254
255 return CRYPT_OK;
256 }
257
258 /**
259 Import a PRNG state
260 @param in The PRNG state
261 @param inlen Size of the state
262 @param prng The PRNG to import
263 @return CRYPT_OK if successful
264 */
265 int yarrow_import(const unsigned char *in, unsigned long inlen, prng_state *prng)
266 {
267 int err;
268
269 LTC_ARGCHK(in != NULL);
270 LTC_ARGCHK(prng != NULL);
271
272 if (inlen != 64) {
273 return CRYPT_INVALID_ARG;
274 }
275
276 if ((err = yarrow_start(prng)) != CRYPT_OK) {
277 return err;
278 }
279 return yarrow_add_entropy(in, 64, prng);
280 }
281
282 /**
283 PRNG self-test
284 @return CRYPT_OK if successful, CRYPT_NOP if self-testing has been disabled
285 */
286 int yarrow_test(void)
287 {
288 #ifndef LTC_TEST
289 return CRYPT_NOP;
290 #else
291 int err;
292 prng_state prng;
293
294 if ((err = yarrow_start(&prng)) != CRYPT_OK) {
295 return err;
296 }
297
298 /* now let's test the hash/cipher that was chosen */
299 if ((err = cipher_descriptor[prng.yarrow.cipher].test()) != CRYPT_OK) {
300 return err;
301 }
302 if ((err = hash_descriptor[prng.yarrow.hash].test()) != CRYPT_OK) {
303 return err;
304 }
305
306 yarrow_done(&prng);
307 return CRYPT_OK;
308 #endif
309 }
310
311 #endif
312