Home | History | Annotate | Download | only in pkcs5
      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 pkcs_5_2.c
     15    PKCS #5, Algorithm #2, Tom St Denis
     16 */
     17 #ifdef PKCS_5
     18 
     19 /**
     20    Execute PKCS #5 v2
     21    @param password          The input password (or key)
     22    @param password_len      The length of the password (octets)
     23    @param salt              The salt (or nonce)
     24    @param salt_len          The length of the salt (octets)
     25    @param iteration_count   # of iterations desired for PKCS #5 v2 [read specs for more]
     26    @param hash_idx          The index of the hash desired
     27    @param out               [out] The destination for this algorithm
     28    @param outlen            [in/out] The max size and resulting size of the algorithm output
     29    @return CRYPT_OK if successful
     30 */
     31 int pkcs_5_alg2(const unsigned char *password, unsigned long password_len,
     32                 const unsigned char *salt,     unsigned long salt_len,
     33                 int iteration_count,           int hash_idx,
     34                 unsigned char *out,            unsigned long *outlen)
     35 {
     36    int err, itts;
     37    ulong32  blkno;
     38    unsigned long stored, left, x, y;
     39    unsigned char *buf[2];
     40    hmac_state    *hmac;
     41 
     42    LTC_ARGCHK(password != NULL);
     43    LTC_ARGCHK(salt     != NULL);
     44    LTC_ARGCHK(out      != NULL);
     45    LTC_ARGCHK(outlen   != NULL);
     46 
     47    /* test hash IDX */
     48    if ((err = hash_is_valid(hash_idx)) != CRYPT_OK) {
     49       return err;
     50    }
     51 
     52    buf[0] = XMALLOC(MAXBLOCKSIZE * 2);
     53    hmac   = XMALLOC(sizeof(hmac_state));
     54    if (hmac == NULL || buf[0] == NULL) {
     55       if (hmac != NULL) {
     56          XFREE(hmac);
     57       }
     58       if (buf[0] != NULL) {
     59          XFREE(buf[0]);
     60       }
     61       return CRYPT_MEM;
     62    }
     63    /* buf[1] points to the second block of MAXBLOCKSIZE bytes */
     64    buf[1] = buf[0] + MAXBLOCKSIZE;
     65 
     66    left   = *outlen;
     67    blkno  = 1;
     68    stored = 0;
     69    while (left != 0) {
     70        /* process block number blkno */
     71        zeromem(buf[0], MAXBLOCKSIZE*2);
     72 
     73        /* store current block number and increment for next pass */
     74        STORE32H(blkno, buf[1]);
     75        ++blkno;
     76 
     77        /* get PRF(P, S||int(blkno)) */
     78        if ((err = hmac_init(hmac, hash_idx, password, password_len)) != CRYPT_OK) {
     79           goto LBL_ERR;
     80        }
     81        if ((err = hmac_process(hmac, salt, salt_len)) != CRYPT_OK) {
     82           goto LBL_ERR;
     83        }
     84        if ((err = hmac_process(hmac, buf[1], 4)) != CRYPT_OK) {
     85           goto LBL_ERR;
     86        }
     87        x = MAXBLOCKSIZE;
     88        if ((err = hmac_done(hmac, buf[0], &x)) != CRYPT_OK) {
     89           goto LBL_ERR;
     90        }
     91 
     92        /* now compute repeated and XOR it in buf[1] */
     93        XMEMCPY(buf[1], buf[0], x);
     94        for (itts = 1; itts < iteration_count; ++itts) {
     95            if ((err = hmac_memory(hash_idx, password, password_len, buf[0], x, buf[0], &x)) != CRYPT_OK) {
     96               goto LBL_ERR;
     97            }
     98            for (y = 0; y < x; y++) {
     99                buf[1][y] ^= buf[0][y];
    100            }
    101        }
    102 
    103        /* now emit upto x bytes of buf[1] to output */
    104        for (y = 0; y < x && left != 0; ++y) {
    105            out[stored++] = buf[1][y];
    106            --left;
    107        }
    108    }
    109    *outlen = stored;
    110 
    111    err = CRYPT_OK;
    112 LBL_ERR:
    113 #ifdef LTC_CLEAN_STACK
    114    zeromem(buf[0], MAXBLOCKSIZE*2);
    115    zeromem(hmac, sizeof(hmac_state));
    116 #endif
    117 
    118    XFREE(hmac);
    119    XFREE(buf[0]);
    120 
    121    return err;
    122 }
    123 
    124 #endif
    125 
    126 
    127 /* $Source: /cvs/libtom/libtomcrypt/src/misc/pkcs5/pkcs_5_2.c,v $ */
    128 /* $Revision: 1.5 $ */
    129 /* $Date: 2006/03/31 14:15:35 $ */
    130