|
@@ -0,0 +1,81 @@
|
|
|
|
+/* LibTomCrypt, modular cryptographic library -- Tom St Denis
|
|
|
|
+ *
|
|
|
|
+ * LibTomCrypt is a library that provides various cryptographic
|
|
|
|
+ * algorithms in a highly modular and flexible manner.
|
|
|
|
+ *
|
|
|
|
+ * The library is free for all purposes without any express
|
|
|
|
+ * guarantee it works.
|
|
|
|
+ */
|
|
|
|
+
|
|
|
|
+#include "tomcrypt_private.h"
|
|
|
|
+
|
|
|
|
+#ifdef LTC_PKCS_12
|
|
|
|
+
|
|
|
|
+int 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)
|
|
|
|
+{
|
|
|
|
+ unsigned long u = hash_descriptor[hash_id].hashsize;
|
|
|
|
+ unsigned long v = hash_descriptor[hash_id].blocksize;
|
|
|
|
+ unsigned long c = (outlen + u - 1) / u;
|
|
|
|
+ unsigned long Slen = ((saltlen + v - 1) / v) * v;
|
|
|
|
+ unsigned long Plen = ((pwlen + v - 1) / v) * v;
|
|
|
|
+ unsigned long k = (Plen + Slen) / v;
|
|
|
|
+ unsigned long Alen, keylen = 0;
|
|
|
|
+ unsigned int tmp, i, j, n;
|
|
|
|
+ unsigned char ch;
|
|
|
|
+ unsigned char D[MAXBLOCKSIZE], A[MAXBLOCKSIZE], B[MAXBLOCKSIZE];
|
|
|
|
+ unsigned char *I = NULL, *key = NULL;
|
|
|
|
+ int err = CRYPT_ERROR;
|
|
|
|
+
|
|
|
|
+ key = XMALLOC(u * c);
|
|
|
|
+ I = XMALLOC(Plen + Slen);
|
|
|
|
+ if (key == NULL || I == NULL) goto DONE;
|
|
|
|
+ zeromem(key, u * c);
|
|
|
|
+
|
|
|
|
+ for (i = 0; i < v; i++) D[i] = purpose; /* D - diversifier */
|
|
|
|
+ for (i = 0; i < Slen; i++) I[i] = salt[i % saltlen];
|
|
|
|
+ for (i = 0; i < Plen; i++) I[Slen + i] = pw[i % pwlen]; /* I = Salt || Pass */
|
|
|
|
+
|
|
|
|
+ for (i = 0; i < c; i++) {
|
|
|
|
+ Alen = u; /* hash size */
|
|
|
|
+ err = hash_memory_multi(hash_id, A, &Alen, D, v, I, Slen + Plen, NULL); /* A = HASH(D || I) */
|
|
|
|
+ if (err != CRYPT_OK) goto DONE;
|
|
|
|
+ for (j = 1; j < iterations; j++) {
|
|
|
|
+ err = hash_memory(hash_id, A, Alen, A, &Alen); /* A = HASH(A) */
|
|
|
|
+ if (err != CRYPT_OK) goto DONE;
|
|
|
|
+ }
|
|
|
|
+ /* fill buffer B with A */
|
|
|
|
+ for (j = 0; j < v; j++) B[j] = A[j % Alen];
|
|
|
|
+ /* B += 1 */
|
|
|
|
+ for (j = v; j > 0; j--) {
|
|
|
|
+ if (++B[j - 1] != 0) break;
|
|
|
|
+ }
|
|
|
|
+ /* I_n += B */
|
|
|
|
+ for (n = 0; n < k; n++) {
|
|
|
|
+ ch = 0;
|
|
|
|
+ for (j = v; j > 0; j--) {
|
|
|
|
+ tmp = I[n * v + j - 1] + B[j - 1] + ch;
|
|
|
|
+ ch = (unsigned char)((tmp >> 8) & 0xFF);
|
|
|
|
+ I[n * v + j - 1] = (unsigned char)(tmp & 0xFF);
|
|
|
|
+ }
|
|
|
|
+ }
|
|
|
|
+ /* store derived key block */
|
|
|
|
+ for (j = 0; j < Alen; j++) key[keylen++] = A[j];
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ for (i = 0; i < outlen; i++) out[i] = key[i];
|
|
|
|
+ err = CRYPT_OK;
|
|
|
|
+DONE:
|
|
|
|
+ if (I) XFREE(I);
|
|
|
|
+ if (key) XFREE(key);
|
|
|
|
+ return err;
|
|
|
|
+}
|
|
|
|
+
|
|
|
|
+#endif
|
|
|
|
+
|
|
|
|
+/* ref: $Format:%D$ */
|
|
|
|
+/* git commit: $Format:%H$ */
|
|
|
|
+/* commit time: $Format:%ai$ */
|