1 /* 2 * Copyright (c) 2001-2007, Tom St Denis 3 * All rights reserved. 4 * 5 * Redistribution and use in source and binary forms, with or without 6 * modification, are permitted provided that the following conditions are met: 7 * 8 * 1. Redistributions of source code must retain the above copyright notice, 9 * this list of conditions and the following disclaimer. 10 * 11 * 2. Redistributions in binary form must reproduce the above copyright notice, 12 * this list of conditions and the following disclaimer in the documentation 13 * and/or other materials provided with the distribution. 14 * 15 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 16 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 17 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 18 * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE 19 * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 20 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 21 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 22 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 23 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 24 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 25 * POSSIBILITY OF SUCH DAMAGE. 26 */ 27 28 /* LibTomCrypt, modular cryptographic library -- Tom St Denis 29 * 30 * LibTomCrypt is a library that provides various cryptographic 31 * algorithms in a highly modular and flexible manner. 32 * 33 * The library is free for all purposes without any express 34 * guarantee it works. 35 * 36 * Tom St Denis, tomstdenis@gmail.com, http://libtom.org 37 */ 38 #include "tomcrypt.h" 39 40 /** 41 @file yarrow.c 42 Yarrow PRNG, Tom St Denis 43 */ 44 45 #ifdef LTC_YARROW 46 47 const struct ltc_prng_descriptor yarrow_desc = 48 { 49 "yarrow", 64, 50 &yarrow_start, 51 &yarrow_add_entropy, 52 &yarrow_ready, 53 &yarrow_read, 54 &yarrow_done, 55 &yarrow_export, 56 &yarrow_import, 57 &yarrow_test 58 }; 59 60 /** 61 Start the PRNG 62 @param prng [out] The PRNG state to initialize 63 @return CRYPT_OK if successful 64 */ 65 int yarrow_start(prng_state *prng) 66 { 67 int err; 68 69 LTC_ARGCHK(prng != NULL); 70 71 /* these are the default hash/cipher combo used */ 72 #ifdef LTC_RIJNDAEL 73 #if LTC_YARROW_AES==0 74 prng->yarrow.cipher = register_cipher(&rijndael_enc_desc); 75 #elif LTC_YARROW_AES==1 76 prng->yarrow.cipher = register_cipher(&aes_enc_desc); 77 #elif LTC_YARROW_AES==2 78 prng->yarrow.cipher = register_cipher(&rijndael_desc); 79 #elif LTC_YARROW_AES==3 80 prng->yarrow.cipher = register_cipher(&aes_desc); 81 #endif 82 #elif defined(LTC_BLOWFISH) 83 prng->yarrow.cipher = register_cipher(&blowfish_desc); 84 #elif defined(LTC_TWOFISH) 85 prng->yarrow.cipher = register_cipher(&twofish_desc); 86 #elif defined(LTC_RC6) 87 prng->yarrow.cipher = register_cipher(&rc6_desc); 88 #elif defined(LTC_RC5) 89 prng->yarrow.cipher = register_cipher(&rc5_desc); 90 #elif defined(LTC_SAFERP) 91 prng->yarrow.cipher = register_cipher(&saferp_desc); 92 #elif defined(LTC_RC2) 93 prng->yarrow.cipher = register_cipher(&rc2_desc); 94 #elif defined(LTC_NOEKEON) 95 prng->yarrow.cipher = register_cipher(&noekeon_desc); 96 #elif defined(LTC_ANUBIS) 97 prng->yarrow.cipher = register_cipher(&anubis_desc); 98 #elif defined(LTC_KSEED) 99 prng->yarrow.cipher = register_cipher(&kseed_desc); 100 #elif defined(LTC_KHAZAD) 101 prng->yarrow.cipher = register_cipher(&khazad_desc); 102 #elif defined(LTC_CAST5) 103 prng->yarrow.cipher = register_cipher(&cast5_desc); 104 #elif defined(LTC_XTEA) 105 prng->yarrow.cipher = register_cipher(&xtea_desc); 106 #elif defined(LTC_SAFER) 107 prng->yarrow.cipher = register_cipher(&safer_sk128_desc); 108 #elif defined(LTC_DES) 109 prng->yarrow.cipher = register_cipher(&des3_desc); 110 #else 111 #error LTC_YARROW needs at least one CIPHER 112 #endif 113 if ((err = cipher_is_valid(prng->yarrow.cipher)) != CRYPT_OK) { 114 return err; 115 } 116 117 #ifdef LTC_SHA256 118 prng->yarrow.hash = register_hash(&sha256_desc); 119 #elif defined(LTC_SHA512) 120 prng->yarrow.hash = register_hash(&sha512_desc); 121 #elif defined(LTC_TIGER) 122 prng->yarrow.hash = register_hash(&tiger_desc); 123 #elif defined(LTC_SHA1) 124 prng->yarrow.hash = register_hash(&sha1_desc); 125 #elif defined(LTC_RIPEMD320) 126 prng->yarrow.hash = register_hash(&rmd320_desc); 127 #elif defined(LTC_RIPEMD256) 128 prng->yarrow.hash = register_hash(&rmd256_desc); 129 #elif defined(LTC_RIPEMD160) 130 prng->yarrow.hash = register_hash(&rmd160_desc); 131 #elif defined(LTC_RIPEMD128) 132 prng->yarrow.hash = register_hash(&rmd128_desc); 133 #elif defined(LTC_MD5) 134 prng->yarrow.hash = register_hash(&md5_desc); 135 #elif defined(LTC_MD4) 136 prng->yarrow.hash = register_hash(&md4_desc); 137 #elif defined(LTC_MD2) 138 prng->yarrow.hash = register_hash(&md2_desc); 139 #elif defined(LTC_WHIRLPOOL) 140 prng->yarrow.hash = register_hash(&whirlpool_desc); 141 #else 142 #error LTC_YARROW needs at least one HASH 143 #endif 144 if ((err = hash_is_valid(prng->yarrow.hash)) != CRYPT_OK) { 145 return err; 146 } 147 148 /* zero the memory used */ 149 zeromem(prng->yarrow.pool, sizeof(prng->yarrow.pool)); 150 LTC_MUTEX_INIT(&prng->yarrow.prng_lock) 151 152 return CRYPT_OK; 153 } 154 155 /** 156 Add entropy to the PRNG state 157 @param in The data to add 158 @param inlen Length of the data to add 159 @param prng PRNG state to update 160 @return CRYPT_OK if successful 161 */ 162 int yarrow_add_entropy(const unsigned char *in, unsigned long inlen, prng_state *prng) 163 { 164 hash_state md; 165 int err; 166 167 LTC_ARGCHK(in != NULL); 168 LTC_ARGCHK(prng != NULL); 169 170 LTC_MUTEX_LOCK(&prng->yarrow.prng_lock); 171 172 if ((err = hash_is_valid(prng->yarrow.hash)) != CRYPT_OK) { 173 LTC_MUTEX_UNLOCK(&prng->yarrow.prng_lock); 174 return err; 175 } 176 177 /* start the hash */ 178 if ((err = hash_descriptor[prng->yarrow.hash].init(&md)) != CRYPT_OK) { 179 LTC_MUTEX_UNLOCK(&prng->yarrow.prng_lock); 180 return err; 181 } 182 183 /* hash the current pool */ 184 if ((err = hash_descriptor[prng->yarrow.hash].process(&md, prng->yarrow.pool, 185 hash_descriptor[prng->yarrow.hash].hashsize)) != CRYPT_OK) { 186 LTC_MUTEX_UNLOCK(&prng->yarrow.prng_lock); 187 return err; 188 } 189 190 /* add the new entropy */ 191 if ((err = hash_descriptor[prng->yarrow.hash].process(&md, in, inlen)) != CRYPT_OK) { 192 LTC_MUTEX_UNLOCK(&prng->yarrow.prng_lock); 193 return err; 194 } 195 196 /* store result */ 197 if ((err = hash_descriptor[prng->yarrow.hash].done(&md, prng->yarrow.pool)) != CRYPT_OK) { 198 LTC_MUTEX_UNLOCK(&prng->yarrow.prng_lock); 199 return err; 200 } 201 202 LTC_MUTEX_UNLOCK(&prng->yarrow.prng_lock); 203 return CRYPT_OK; 204 } 205 206 /** 207 Make the PRNG ready to read from 208 @param prng The PRNG to make active 209 @return CRYPT_OK if successful 210 */ 211 int yarrow_ready(prng_state *prng) 212 { 213 int ks, err; 214 215 LTC_ARGCHK(prng != NULL); 216 LTC_MUTEX_LOCK(&prng->yarrow.prng_lock); 217 218 if ((err = hash_is_valid(prng->yarrow.hash)) != CRYPT_OK) { 219 LTC_MUTEX_UNLOCK(&prng->yarrow.prng_lock); 220 return err; 221 } 222 223 if ((err = cipher_is_valid(prng->yarrow.cipher)) != CRYPT_OK) { 224 LTC_MUTEX_UNLOCK(&prng->yarrow.prng_lock); 225 return err; 226 } 227 228 /* setup CTR mode using the "pool" as the key */ 229 ks = (int)hash_descriptor[prng->yarrow.hash].hashsize; 230 if ((err = cipher_descriptor[prng->yarrow.cipher].keysize(&ks)) != CRYPT_OK) { 231 LTC_MUTEX_UNLOCK(&prng->yarrow.prng_lock); 232 return err; 233 } 234 235 if ((err = ctr_start(prng->yarrow.cipher, /* what cipher to use */ 236 prng->yarrow.pool, /* IV */ 237 prng->yarrow.pool, ks, /* KEY and key size */ 238 0, /* number of rounds */ 239 CTR_COUNTER_LITTLE_ENDIAN, /* little endian counter */ 240 &prng->yarrow.ctr)) != CRYPT_OK) { 241 LTC_MUTEX_UNLOCK(&prng->yarrow.prng_lock); 242 return err; 243 } 244 LTC_MUTEX_UNLOCK(&prng->yarrow.prng_lock); 245 return CRYPT_OK; 246 } 247 248 /** 249 Read from the PRNG 250 @param out Destination 251 @param outlen Length of output 252 @param prng The active PRNG to read from 253 @return Number of octets read 254 */ 255 unsigned long yarrow_read(unsigned char *out, unsigned long outlen, prng_state *prng) 256 { 257 LTC_ARGCHK(out != NULL); 258 LTC_ARGCHK(prng != NULL); 259 260 LTC_MUTEX_LOCK(&prng->yarrow.prng_lock); 261 262 /* put out in predictable state first */ 263 zeromem(out, outlen); 264 265 /* now randomize it */ 266 if (ctr_encrypt(out, out, outlen, &prng->yarrow.ctr) != CRYPT_OK) { 267 LTC_MUTEX_UNLOCK(&prng->yarrow.prng_lock); 268 return 0; 269 } 270 LTC_MUTEX_UNLOCK(&prng->yarrow.prng_lock); 271 return outlen; 272 } 273 274 /** 275 Terminate the PRNG 276 @param prng The PRNG to terminate 277 @return CRYPT_OK if successful 278 */ 279 int yarrow_done(prng_state *prng) 280 { 281 int err; 282 LTC_ARGCHK(prng != NULL); 283 284 LTC_MUTEX_LOCK(&prng->yarrow.prng_lock); 285 286 /* call cipher done when we invent one ;-) */ 287 288 /* we invented one */ 289 err = ctr_done(&prng->yarrow.ctr); 290 291 LTC_MUTEX_UNLOCK(&prng->yarrow.prng_lock); 292 return err; 293 } 294 295 /** 296 Export the PRNG state 297 @param out [out] Destination 298 @param outlen [in/out] Max size and resulting size of the state 299 @param prng The PRNG to export 300 @return CRYPT_OK if successful 301 */ 302 int yarrow_export(unsigned char *out, unsigned long *outlen, prng_state *prng) 303 { 304 LTC_ARGCHK(out != NULL); 305 LTC_ARGCHK(outlen != NULL); 306 LTC_ARGCHK(prng != NULL); 307 308 LTC_MUTEX_LOCK(&prng->yarrow.prng_lock); 309 310 /* we'll write 64 bytes for s&g's */ 311 if (*outlen < 64) { 312 LTC_MUTEX_UNLOCK(&prng->yarrow.prng_lock); 313 *outlen = 64; 314 return CRYPT_BUFFER_OVERFLOW; 315 } 316 317 if (yarrow_read(out, 64, prng) != 64) { 318 LTC_MUTEX_UNLOCK(&prng->yarrow.prng_lock); 319 return CRYPT_ERROR_READPRNG; 320 } 321 *outlen = 64; 322 323 return CRYPT_OK; 324 } 325 326 /** 327 Import a PRNG state 328 @param in The PRNG state 329 @param inlen Size of the state 330 @param prng The PRNG to import 331 @return CRYPT_OK if successful 332 */ 333 int yarrow_import(const unsigned char *in, unsigned long inlen, prng_state *prng) 334 { 335 int err; 336 337 LTC_ARGCHK(in != NULL); 338 LTC_ARGCHK(prng != NULL); 339 340 LTC_MUTEX_LOCK(&prng->yarrow.prng_lock); 341 342 if (inlen != 64) { 343 LTC_MUTEX_UNLOCK(&prng->yarrow.prng_lock); 344 return CRYPT_INVALID_ARG; 345 } 346 347 if ((err = yarrow_start(prng)) != CRYPT_OK) { 348 LTC_MUTEX_UNLOCK(&prng->yarrow.prng_lock); 349 return err; 350 } 351 err = yarrow_add_entropy(in, 64, prng); 352 LTC_MUTEX_UNLOCK(&prng->yarrow.prng_lock); 353 return err; 354 } 355 356 /** 357 PRNG self-test 358 @return CRYPT_OK if successful, CRYPT_NOP if self-testing has been disabled 359 */ 360 int yarrow_test(void) 361 { 362 #ifndef LTC_TEST 363 return CRYPT_NOP; 364 #else 365 int err; 366 prng_state prng; 367 368 if ((err = yarrow_start(&prng)) != CRYPT_OK) { 369 return err; 370 } 371 372 /* now let's test the hash/cipher that was chosen */ 373 if ((err = cipher_descriptor[prng.yarrow.cipher].test()) != CRYPT_OK) { 374 return err; 375 } 376 if ((err = hash_descriptor[prng.yarrow.hash].test()) != CRYPT_OK) { 377 return err; 378 } 379 380 return CRYPT_OK; 381 #endif 382 } 383 384 #endif 385 386 387 /* $Source: /cvs/libtom/libtomcrypt/src/prngs/yarrow.c,v $ */ 388 /* $Revision: 1.16 $ */ 389 /* $Date: 2007/05/12 14:32:35 $ */ 390