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