1 // SPDX-License-Identifier: BSD-2-Clause 2 /* LibTomCrypt, modular cryptographic library -- Tom St Denis 3 * 4 * LibTomCrypt is a library that provides various cryptographic 5 * algorithms in a highly modular and flexible manner. 6 * 7 * The library is free for all purposes without any express 8 * guarantee it works. 9 */ 10 #include "tomcrypt_private.h" 11 12 /** 13 @file yarrow.c 14 Yarrow PRNG, Tom St Denis 15 */ 16 17 #ifdef LTC_YARROW 18 19 const struct ltc_prng_descriptor yarrow_desc = 20 { 21 "yarrow", 64, 22 &yarrow_start, 23 &yarrow_add_entropy, 24 &yarrow_ready, 25 &yarrow_read, 26 &yarrow_done, 27 &yarrow_export, 28 &yarrow_import, 29 &yarrow_test 30 }; 31 32 /** 33 Start the PRNG 34 @param prng [out] The PRNG state to initialize 35 @return CRYPT_OK if successful 36 */ 37 int yarrow_start(prng_state *prng) 38 { 39 int err; 40 41 LTC_ARGCHK(prng != NULL); 42 prng->ready = 0; 43 44 /* these are the default hash/cipher combo used */ 45 #ifdef LTC_RIJNDAEL 46 #if LTC_YARROW_AES==0 47 prng->u.yarrow.cipher = register_cipher(&rijndael_enc_desc); 48 #elif LTC_YARROW_AES==1 49 prng->u.yarrow.cipher = register_cipher(&aes_enc_desc); 50 #elif LTC_YARROW_AES==2 51 prng->u.yarrow.cipher = register_cipher(&rijndael_desc); 52 #elif LTC_YARROW_AES==3 53 prng->u.yarrow.cipher = register_cipher(&aes_desc); 54 #endif 55 #elif defined(LTC_BLOWFISH) 56 prng->u.yarrow.cipher = register_cipher(&blowfish_desc); 57 #elif defined(LTC_TWOFISH) 58 prng->u.yarrow.cipher = register_cipher(&twofish_desc); 59 #elif defined(LTC_RC6) 60 prng->u.yarrow.cipher = register_cipher(&rc6_desc); 61 #elif defined(LTC_RC5) 62 prng->u.yarrow.cipher = register_cipher(&rc5_desc); 63 #elif defined(LTC_SAFERP) 64 prng->u.yarrow.cipher = register_cipher(&saferp_desc); 65 #elif defined(LTC_RC2) 66 prng->u.yarrow.cipher = register_cipher(&rc2_desc); 67 #elif defined(LTC_NOEKEON) 68 prng->u.yarrow.cipher = register_cipher(&noekeon_desc); 69 #elif defined(LTC_ANUBIS) 70 prng->u.yarrow.cipher = register_cipher(&anubis_desc); 71 #elif defined(LTC_KSEED) 72 prng->u.yarrow.cipher = register_cipher(&kseed_desc); 73 #elif defined(LTC_KHAZAD) 74 prng->u.yarrow.cipher = register_cipher(&khazad_desc); 75 #elif defined(LTC_CAST5) 76 prng->u.yarrow.cipher = register_cipher(&cast5_desc); 77 #elif defined(LTC_XTEA) 78 prng->u.yarrow.cipher = register_cipher(&xtea_desc); 79 #elif defined(LTC_SAFER) 80 prng->u.yarrow.cipher = register_cipher(&safer_sk128_desc); 81 #elif defined(LTC_DES) 82 prng->u.yarrow.cipher = register_cipher(&des3_desc); 83 #else 84 #error LTC_YARROW needs at least one CIPHER 85 #endif 86 if ((err = cipher_is_valid(prng->u.yarrow.cipher)) != CRYPT_OK) { 87 return err; 88 } 89 90 #ifdef LTC_SHA256 91 prng->u.yarrow.hash = register_hash(&sha256_desc); 92 #elif defined(LTC_SHA512) 93 prng->u.yarrow.hash = register_hash(&sha512_desc); 94 #elif defined(LTC_TIGER) 95 prng->u.yarrow.hash = register_hash(&tiger_desc); 96 #elif defined(LTC_SHA1) 97 prng->u.yarrow.hash = register_hash(&sha1_desc); 98 #elif defined(LTC_RIPEMD320) 99 prng->u.yarrow.hash = register_hash(&rmd320_desc); 100 #elif defined(LTC_RIPEMD256) 101 prng->u.yarrow.hash = register_hash(&rmd256_desc); 102 #elif defined(LTC_RIPEMD160) 103 prng->u.yarrow.hash = register_hash(&rmd160_desc); 104 #elif defined(LTC_RIPEMD128) 105 prng->u.yarrow.hash = register_hash(&rmd128_desc); 106 #elif defined(LTC_MD5) 107 prng->u.yarrow.hash = register_hash(&md5_desc); 108 #elif defined(LTC_MD4) 109 prng->u.yarrow.hash = register_hash(&md4_desc); 110 #elif defined(LTC_MD2) 111 prng->u.yarrow.hash = register_hash(&md2_desc); 112 #elif defined(LTC_WHIRLPOOL) 113 prng->u.yarrow.hash = register_hash(&whirlpool_desc); 114 #else 115 #error LTC_YARROW needs at least one HASH 116 #endif 117 if ((err = hash_is_valid(prng->u.yarrow.hash)) != CRYPT_OK) { 118 return err; 119 } 120 121 /* zero the memory used */ 122 zeromem(prng->u.yarrow.pool, sizeof(prng->u.yarrow.pool)); 123 LTC_MUTEX_INIT(&prng->lock) 124 125 return CRYPT_OK; 126 } 127 128 /** 129 Add entropy to the PRNG state 130 @param in The data to add 131 @param inlen Length of the data to add 132 @param prng PRNG state to update 133 @return CRYPT_OK if successful 134 */ 135 int yarrow_add_entropy(const unsigned char *in, unsigned long inlen, prng_state *prng) 136 { 137 hash_state md; 138 int err; 139 140 LTC_ARGCHK(prng != NULL); 141 LTC_ARGCHK(in != NULL); 142 LTC_ARGCHK(inlen > 0); 143 144 LTC_MUTEX_LOCK(&prng->lock); 145 146 if ((err = hash_is_valid(prng->u.yarrow.hash)) != CRYPT_OK) { 147 goto LBL_UNLOCK; 148 } 149 150 /* start the hash */ 151 if ((err = hash_descriptor[prng->u.yarrow.hash]->init(&md)) != CRYPT_OK) { 152 goto LBL_UNLOCK; 153 } 154 155 /* hash the current pool */ 156 if ((err = hash_descriptor[prng->u.yarrow.hash]->process(&md, prng->u.yarrow.pool, 157 hash_descriptor[prng->u.yarrow.hash]->hashsize)) != CRYPT_OK) { 158 goto LBL_UNLOCK; 159 } 160 161 /* add the new entropy */ 162 if ((err = hash_descriptor[prng->u.yarrow.hash]->process(&md, in, inlen)) != CRYPT_OK) { 163 goto LBL_UNLOCK; 164 } 165 166 /* store result */ 167 err = hash_descriptor[prng->u.yarrow.hash]->done(&md, prng->u.yarrow.pool); 168 169 LBL_UNLOCK: 170 LTC_MUTEX_UNLOCK(&prng->lock); 171 return err; 172 } 173 174 /** 175 Make the PRNG ready to read from 176 @param prng The PRNG to make active 177 @return CRYPT_OK if successful 178 */ 179 int yarrow_ready(prng_state *prng) 180 { 181 int ks, err; 182 183 LTC_ARGCHK(prng != NULL); 184 185 LTC_MUTEX_LOCK(&prng->lock); 186 187 if ((err = hash_is_valid(prng->u.yarrow.hash)) != CRYPT_OK) { 188 goto LBL_UNLOCK; 189 } 190 191 if ((err = cipher_is_valid(prng->u.yarrow.cipher)) != CRYPT_OK) { 192 goto LBL_UNLOCK; 193 } 194 195 /* setup CTR mode using the "pool" as the key */ 196 ks = (int)hash_descriptor[prng->u.yarrow.hash]->hashsize; 197 if ((err = cipher_descriptor[prng->u.yarrow.cipher]->keysize(&ks)) != CRYPT_OK) { 198 goto LBL_UNLOCK; 199 } 200 201 if ((err = ctr_start(prng->u.yarrow.cipher, /* what cipher to use */ 202 prng->u.yarrow.pool, /* IV */ 203 prng->u.yarrow.pool, ks, /* KEY and key size */ 204 0, /* number of rounds */ 205 CTR_COUNTER_LITTLE_ENDIAN, /* little endian counter */ 206 &prng->u.yarrow.ctr)) != CRYPT_OK) { 207 goto LBL_UNLOCK; 208 } 209 prng->ready = 1; 210 211 LBL_UNLOCK: 212 LTC_MUTEX_UNLOCK(&prng->lock); 213 return err; 214 } 215 216 /** 217 Read from the PRNG 218 @param out Destination 219 @param outlen Length of output 220 @param prng The active PRNG to read from 221 @return Number of octets read 222 */ 223 unsigned long yarrow_read(unsigned char *out, unsigned long outlen, prng_state *prng) 224 { 225 if (outlen == 0 || prng == NULL || out == NULL) return 0; 226 227 LTC_MUTEX_LOCK(&prng->lock); 228 229 if (!prng->ready) { 230 outlen = 0; 231 goto LBL_UNLOCK; 232 } 233 234 /* put out in predictable state first */ 235 zeromem(out, outlen); 236 237 /* now randomize it */ 238 if (ctr_encrypt(out, out, outlen, &prng->u.yarrow.ctr) != CRYPT_OK) { 239 outlen = 0; 240 } 241 242 LBL_UNLOCK: 243 LTC_MUTEX_UNLOCK(&prng->lock); 244 return outlen; 245 } 246 247 /** 248 Terminate the PRNG 249 @param prng The PRNG to terminate 250 @return CRYPT_OK if successful 251 */ 252 int yarrow_done(prng_state *prng) 253 { 254 int err; 255 LTC_ARGCHK(prng != NULL); 256 257 LTC_MUTEX_LOCK(&prng->lock); 258 prng->ready = 0; 259 260 /* call cipher done when we invent one ;-) */ 261 262 /* we invented one */ 263 err = ctr_done(&prng->u.yarrow.ctr); 264 265 LTC_MUTEX_UNLOCK(&prng->lock); 266 LTC_MUTEX_DESTROY(&prng->lock); 267 return err; 268 } 269 270 /** 271 Export the PRNG state 272 @param out [out] Destination 273 @param outlen [in/out] Max size and resulting size of the state 274 @param prng The PRNG to export 275 @return CRYPT_OK if successful 276 */ 277 _LTC_PRNG_EXPORT(yarrow) 278 279 /** 280 Import a PRNG state 281 @param in The PRNG state 282 @param inlen Size of the state 283 @param prng The PRNG to import 284 @return CRYPT_OK if successful 285 */ 286 int yarrow_import(const unsigned char *in, unsigned long inlen, prng_state *prng) 287 { 288 int err; 289 290 LTC_ARGCHK(in != NULL); 291 LTC_ARGCHK(prng != NULL); 292 if (inlen < (unsigned long)yarrow_desc.export_size) return CRYPT_INVALID_ARG; 293 294 if ((err = yarrow_start(prng)) != CRYPT_OK) return err; 295 if ((err = yarrow_add_entropy(in, inlen, prng)) != CRYPT_OK) return err; 296 return CRYPT_OK; 297 } 298 299 /** 300 PRNG self-test 301 @return CRYPT_OK if successful, CRYPT_NOP if self-testing has been disabled 302 */ 303 int yarrow_test(void) 304 { 305 #ifndef LTC_TEST 306 return CRYPT_NOP; 307 #else 308 int err; 309 prng_state prng; 310 311 if ((err = yarrow_start(&prng)) != CRYPT_OK) { 312 return err; 313 } 314 315 /* now let's test the hash/cipher that was chosen */ 316 if (cipher_descriptor[prng.u.yarrow.cipher]->test && 317 ((err = cipher_descriptor[prng.u.yarrow.cipher]->test()) != CRYPT_OK)) { 318 return err; 319 } 320 if (hash_descriptor[prng.u.yarrow.hash]->test && 321 ((err = hash_descriptor[prng.u.yarrow.hash]->test()) != CRYPT_OK)) { 322 return err; 323 } 324 325 return CRYPT_OK; 326 #endif 327 } 328 329 #endif 330 331 332 /* ref: $Format:%D$ */ 333 /* git commit: $Format:%H$ */ 334 /* commit time: $Format:%ai$ */ 335