1 /* LibTomCrypt, modular cryptographic library -- Tom St Denis */
2 /* SPDX-License-Identifier: Unlicense */
3
4 #include "tomcrypt_private.h"
5
6 #ifdef LTC_PKCS_12
7
pkcs12_kdf(int hash_id,const unsigned char * pw,unsigned long pwlen,const unsigned char * salt,unsigned long saltlen,unsigned int iterations,unsigned char purpose,unsigned char * out,unsigned long outlen)8 int pkcs12_kdf( int hash_id,
9 const unsigned char *pw, unsigned long pwlen,
10 const unsigned char *salt, unsigned long saltlen,
11 unsigned int iterations, unsigned char purpose,
12 unsigned char *out, unsigned long outlen)
13 {
14 unsigned long u = hash_descriptor[hash_id]->hashsize;
15 unsigned long v = hash_descriptor[hash_id]->blocksize;
16 unsigned long c = (outlen + u - 1) / u;
17 unsigned long Slen = ((saltlen + v - 1) / v) * v;
18 unsigned long Plen = ((pwlen + v - 1) / v) * v;
19 unsigned long k = (Plen + Slen) / v;
20 unsigned long Alen, keylen = 0;
21 unsigned int tmp, i, j, n;
22 unsigned char ch;
23 unsigned char D[MAXBLOCKSIZE], A[MAXBLOCKSIZE], B[MAXBLOCKSIZE];
24 unsigned char *I, *key;
25 int err = CRYPT_ERROR;
26
27 LTC_ARGCHK(pw != NULL);
28 LTC_ARGCHK(salt != NULL);
29 LTC_ARGCHK(out != NULL);
30
31 key = XMALLOC(u * c);
32 I = XMALLOC(Plen + Slen);
33 if (key == NULL || I == NULL) goto DONE;
34 zeromem(key, u * c);
35
36 for (i = 0; i < v; i++) D[i] = purpose; /* D - diversifier */
37 for (i = 0; i < Slen; i++) I[i] = salt[i % saltlen];
38 for (i = 0; i < Plen; i++) I[Slen + i] = pw[i % pwlen]; /* I = Salt || Pass */
39
40 for (i = 0; i < c; i++) {
41 Alen = sizeof(A);
42 err = hash_memory_multi(hash_id, A, &Alen, D, v, I, Slen + Plen, LTC_NULL); /* A = HASH(D || I) */
43 if (err != CRYPT_OK) goto DONE;
44 for (j = 1; j < iterations; j++) {
45 err = hash_memory(hash_id, A, Alen, A, &Alen); /* A = HASH(A) */
46 if (err != CRYPT_OK) goto DONE;
47 }
48 /* fill buffer B with A */
49 for (j = 0; j < v; j++) B[j] = A[j % Alen];
50 /* B += 1 */
51 for (j = v; j > 0; j--) {
52 if (++B[j - 1] != 0) break;
53 }
54 /* I_n += B */
55 for (n = 0; n < k; n++) {
56 ch = 0;
57 for (j = v; j > 0; j--) {
58 tmp = I[n * v + j - 1] + B[j - 1] + ch;
59 ch = (unsigned char)((tmp >> 8) & 0xFF);
60 I[n * v + j - 1] = (unsigned char)(tmp & 0xFF);
61 }
62 }
63 /* store derived key block */
64 XMEMCPY(&key[keylen], A, Alen);
65 keylen += Alen;
66 }
67
68 XMEMCPY(out, key, outlen);
69 err = CRYPT_OK;
70 DONE:
71 if (I) {
72 zeromem(I, Plen + Slen);
73 XFREE(I);
74 }
75 if (key) {
76 zeromem(key, u * c);
77 XFREE(key);
78 }
79 return err;
80 }
81
82 #endif
83