Home | History | Annotate | Download | only in prngs
      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, tomstdenis (at) gmail.com, http://libtomcrypt.com
     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(ANUBIS)
     70    prng->yarrow.cipher = register_cipher(&anubis_desc);
     71 #elif defined(KSEED)
     72    prng->yarrow.cipher = register_cipher(&kseed_desc);
     73 #elif defined(KHAZAD)
     74    prng->yarrow.cipher = register_cipher(&khazad_desc);
     75 #elif defined(CAST5)
     76    prng->yarrow.cipher = register_cipher(&cast5_desc);
     77 #elif defined(XTEA)
     78    prng->yarrow.cipher = register_cipher(&xtea_desc);
     79 #elif defined(SAFER)
     80    prng->yarrow.cipher = register_cipher(&safer_sk128_desc);
     81 #elif defined(DES)
     82    prng->yarrow.cipher = register_cipher(&des3_desc);
     83 #else
     84    #error YARROW needs at least one CIPHER
     85 #endif
     86    if ((err = cipher_is_valid(prng->yarrow.cipher)) != CRYPT_OK) {
     87       return err;
     88    }
     89 
     90 #ifdef SHA256
     91    prng->yarrow.hash   = register_hash(&sha256_desc);
     92 #elif defined(SHA512)
     93    prng->yarrow.hash   = register_hash(&sha512_desc);
     94 #elif defined(TIGER)
     95    prng->yarrow.hash   = register_hash(&tiger_desc);
     96 #elif defined(SHA1)
     97    prng->yarrow.hash   = register_hash(&sha1_desc);
     98 #elif defined(RIPEMD320)
     99    prng->yarrow.hash   = register_hash(&rmd320_desc);
    100 #elif defined(RIPEMD256)
    101    prng->yarrow.hash   = register_hash(&rmd256_desc);
    102 #elif defined(RIPEMD160)
    103    prng->yarrow.hash   = register_hash(&rmd160_desc);
    104 #elif defined(RIPEMD128)
    105    prng->yarrow.hash   = register_hash(&rmd128_desc);
    106 #elif defined(MD5)
    107    prng->yarrow.hash   = register_hash(&md5_desc);
    108 #elif defined(MD4)
    109    prng->yarrow.hash   = register_hash(&md4_desc);
    110 #elif defined(MD2)
    111    prng->yarrow.hash   = register_hash(&md2_desc);
    112 #elif defined(WHIRLPOOL)
    113    prng->yarrow.hash   = register_hash(&whirlpool_desc);
    114 #else
    115    #error YARROW needs at least one HASH
    116 #endif
    117    if ((err = hash_is_valid(prng->yarrow.hash)) != CRYPT_OK) {
    118       return err;
    119    }
    120 
    121    /* zero the memory used */
    122    zeromem(prng->yarrow.pool, sizeof(prng->yarrow.pool));
    123    LTC_MUTEX_INIT(&prng->yarrow.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(in  != NULL);
    141    LTC_ARGCHK(prng != NULL);
    142 
    143    LTC_MUTEX_LOCK(&prng->yarrow.prng_lock);
    144 
    145    if ((err = hash_is_valid(prng->yarrow.hash)) != CRYPT_OK) {
    146       LTC_MUTEX_UNLOCK(&prng->yarrow.prng_lock);
    147       return err;
    148    }
    149 
    150    /* start the hash */
    151    if ((err = hash_descriptor[prng->yarrow.hash].init(&md)) != CRYPT_OK) {
    152       LTC_MUTEX_UNLOCK(&prng->yarrow.prng_lock);
    153       return err;
    154    }
    155 
    156    /* hash the current pool */
    157    if ((err = hash_descriptor[prng->yarrow.hash].process(&md, prng->yarrow.pool,
    158                                                         hash_descriptor[prng->yarrow.hash].hashsize)) != CRYPT_OK) {
    159       LTC_MUTEX_UNLOCK(&prng->yarrow.prng_lock);
    160       return err;
    161    }
    162 
    163    /* add the new entropy */
    164    if ((err = hash_descriptor[prng->yarrow.hash].process(&md, in, inlen)) != CRYPT_OK) {
    165       LTC_MUTEX_UNLOCK(&prng->yarrow.prng_lock);
    166       return err;
    167    }
    168 
    169    /* store result */
    170    if ((err = hash_descriptor[prng->yarrow.hash].done(&md, prng->yarrow.pool)) != CRYPT_OK) {
    171       LTC_MUTEX_UNLOCK(&prng->yarrow.prng_lock);
    172       return err;
    173    }
    174 
    175    LTC_MUTEX_UNLOCK(&prng->yarrow.prng_lock);
    176    return CRYPT_OK;
    177 }
    178 
    179 /**
    180   Make the PRNG ready to read from
    181   @param prng   The PRNG to make active
    182   @return CRYPT_OK if successful
    183 */
    184 int yarrow_ready(prng_state *prng)
    185 {
    186    int ks, err;
    187 
    188    LTC_ARGCHK(prng != NULL);
    189    LTC_MUTEX_LOCK(&prng->yarrow.prng_lock);
    190 
    191    if ((err = hash_is_valid(prng->yarrow.hash)) != CRYPT_OK) {
    192       LTC_MUTEX_UNLOCK(&prng->yarrow.prng_lock);
    193       return err;
    194    }
    195 
    196    if ((err = cipher_is_valid(prng->yarrow.cipher)) != CRYPT_OK) {
    197       LTC_MUTEX_UNLOCK(&prng->yarrow.prng_lock);
    198       return err;
    199    }
    200 
    201    /* setup CTR mode using the "pool" as the key */
    202    ks = (int)hash_descriptor[prng->yarrow.hash].hashsize;
    203    if ((err = cipher_descriptor[prng->yarrow.cipher].keysize(&ks)) != CRYPT_OK) {
    204       LTC_MUTEX_UNLOCK(&prng->yarrow.prng_lock);
    205       return err;
    206    }
    207 
    208    if ((err = ctr_start(prng->yarrow.cipher,     /* what cipher to use */
    209                         prng->yarrow.pool,       /* IV */
    210                         prng->yarrow.pool, ks,   /* KEY and key size */
    211                         0,                       /* number of rounds */
    212                         CTR_COUNTER_LITTLE_ENDIAN, /* little endian counter */
    213                         &prng->yarrow.ctr)) != CRYPT_OK) {
    214       LTC_MUTEX_UNLOCK(&prng->yarrow.prng_lock);
    215       return err;
    216    }
    217    LTC_MUTEX_UNLOCK(&prng->yarrow.prng_lock);
    218    return CRYPT_OK;
    219 }
    220 
    221 /**
    222   Read from the PRNG
    223   @param out      Destination
    224   @param outlen   Length of output
    225   @param prng     The active PRNG to read from
    226   @return Number of octets read
    227 */
    228 unsigned long yarrow_read(unsigned char *out, unsigned long outlen, prng_state *prng)
    229 {
    230    LTC_ARGCHK(out  != NULL);
    231    LTC_ARGCHK(prng != NULL);
    232 
    233    LTC_MUTEX_LOCK(&prng->yarrow.prng_lock);
    234 
    235    /* put out in predictable state first */
    236    zeromem(out, outlen);
    237 
    238    /* now randomize it */
    239    if (ctr_encrypt(out, out, outlen, &prng->yarrow.ctr) != CRYPT_OK) {
    240       LTC_MUTEX_UNLOCK(&prng->yarrow.prng_lock);
    241       return 0;
    242    }
    243    LTC_MUTEX_UNLOCK(&prng->yarrow.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->yarrow.prng_lock);
    258 
    259    /* call cipher done when we invent one ;-) */
    260 
    261    /* we invented one */
    262    err = ctr_done(&prng->yarrow.ctr);
    263 
    264    LTC_MUTEX_UNLOCK(&prng->yarrow.prng_lock);
    265    return err;
    266 }
    267 
    268 /**
    269   Export the PRNG state
    270   @param out       [out] Destination
    271   @param outlen    [in/out] Max size and resulting size of the state
    272   @param prng      The PRNG to export
    273   @return CRYPT_OK if successful
    274 */
    275 int yarrow_export(unsigned char *out, unsigned long *outlen, prng_state *prng)
    276 {
    277    LTC_ARGCHK(out    != NULL);
    278    LTC_ARGCHK(outlen != NULL);
    279    LTC_ARGCHK(prng   != NULL);
    280 
    281    LTC_MUTEX_LOCK(&prng->yarrow.prng_lock);
    282 
    283    /* we'll write 64 bytes for s&g's */
    284    if (*outlen < 64) {
    285       LTC_MUTEX_UNLOCK(&prng->yarrow.prng_lock);
    286       *outlen = 64;
    287       return CRYPT_BUFFER_OVERFLOW;
    288    }
    289 
    290    if (yarrow_read(out, 64, prng) != 64) {
    291       LTC_MUTEX_UNLOCK(&prng->yarrow.prng_lock);
    292       return CRYPT_ERROR_READPRNG;
    293    }
    294    *outlen = 64;
    295 
    296    return CRYPT_OK;
    297 }
    298 
    299 /**
    300   Import a PRNG state
    301   @param in       The PRNG state
    302   @param inlen    Size of the state
    303   @param prng     The PRNG to import
    304   @return CRYPT_OK if successful
    305 */
    306 int yarrow_import(const unsigned char *in, unsigned long inlen, prng_state *prng)
    307 {
    308    int err;
    309 
    310    LTC_ARGCHK(in   != NULL);
    311    LTC_ARGCHK(prng != NULL);
    312 
    313    LTC_MUTEX_LOCK(&prng->yarrow.prng_lock);
    314 
    315    if (inlen != 64) {
    316       LTC_MUTEX_UNLOCK(&prng->yarrow.prng_lock);
    317       return CRYPT_INVALID_ARG;
    318    }
    319 
    320    if ((err = yarrow_start(prng)) != CRYPT_OK) {
    321       LTC_MUTEX_UNLOCK(&prng->yarrow.prng_lock);
    322       return err;
    323    }
    324    err = yarrow_add_entropy(in, 64, prng);
    325    LTC_MUTEX_UNLOCK(&prng->yarrow.prng_lock);
    326    return err;
    327 }
    328 
    329 /**
    330   PRNG self-test
    331   @return CRYPT_OK if successful, CRYPT_NOP if self-testing has been disabled
    332 */
    333 int yarrow_test(void)
    334 {
    335 #ifndef LTC_TEST
    336    return CRYPT_NOP;
    337 #else
    338    int err;
    339    prng_state prng;
    340 
    341    if ((err = yarrow_start(&prng)) != CRYPT_OK) {
    342       return err;
    343    }
    344 
    345    /* now let's test the hash/cipher that was chosen */
    346    if ((err = cipher_descriptor[prng.yarrow.cipher].test()) != CRYPT_OK) {
    347       return err;
    348    }
    349    if ((err = hash_descriptor[prng.yarrow.hash].test()) != CRYPT_OK) {
    350       return err;
    351    }
    352 
    353    return CRYPT_OK;
    354 #endif
    355 }
    356 
    357 #endif
    358 
    359 
    360 /* $Source: /cvs/libtom/libtomcrypt/src/prngs/yarrow.c,v $ */
    361 /* $Revision: 1.10 $ */
    362 /* $Date: 2006/11/14 04:21:17 $ */
    363