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