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