3 * Copyright (C) 2006-2014 wolfSSL Inc.
5 * This file is part of CyaSSL.
7 * CyaSSL is free software; you can redistribute it and/or modify
8 * it under the terms of the GNU General Public License as published by
9 * the Free Software Foundation; either version 2 of the License, or
10 * (at your option) any later version.
12 * CyaSSL is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 * GNU General Public License for more details.
17 * You should have received a copy of the GNU General Public License
18 * along with this program; if not, write to the Free Software
19 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
26 #include <cyassl/ctaocrypt/settings.h>
30 #ifdef CYASSL_PIC32MZ_HASH
32 #define InitMd5 InitMd5_sw
33 #define Md5Update Md5Update_sw
34 #define Md5Final Md5Final_sw
36 #define InitSha InitSha_sw
37 #define ShaUpdate ShaUpdate_sw
38 #define ShaFinal ShaFinal_sw
40 #define InitSha256 InitSha256_sw
41 #define Sha256Update Sha256Update_sw
42 #define Sha256Final Sha256Final_sw
46 #include <cyassl/ctaocrypt/pwdbased.h>
47 #include <cyassl/ctaocrypt/hmac.h>
48 #include <cyassl/ctaocrypt/integer.h>
49 #include <cyassl/ctaocrypt/error-crypt.h>
50 #if defined(CYASSL_SHA512) || defined(CYASSL_SHA384)
51 #include <cyassl/ctaocrypt/sha512.h>
55 #include <cyassl/ctaocrypt/misc.h>
57 #include <ctaocrypt/src/misc.c>
63 static INLINE word32 min(word32 a, word32 b)
71 int PBKDF1(byte* output, const byte* passwd, int pLen, const byte* salt,
72 int sLen, int iterations, int kLen, int hashType)
76 int hLen = (hashType == MD5) ? (int)MD5_DIGEST_SIZE : (int)SHA_DIGEST_SIZE;
78 byte buffer[SHA_DIGEST_SIZE]; /* max size */
80 if (hashType != MD5 && hashType != SHA)
89 if (hashType == MD5) {
91 Md5Update(&md5, passwd, pLen);
92 Md5Update(&md5, salt, sLen);
93 Md5Final(&md5, buffer);
99 ShaUpdate(&sha, passwd, pLen);
100 ShaUpdate(&sha, salt, sLen);
101 ShaFinal(&sha, buffer);
104 for (i = 1; i < iterations; i++) {
105 if (hashType == MD5) {
106 Md5Update(&md5, buffer, hLen);
107 Md5Final(&md5, buffer);
110 ShaUpdate(&sha, buffer, hLen);
111 ShaFinal(&sha, buffer);
114 XMEMCPY(output, buffer, kLen);
120 int PBKDF2(byte* output, const byte* passwd, int pLen, const byte* salt,
121 int sLen, int iterations, int kLen, int hashType)
127 #ifdef CYASSL_SMALL_STACK
130 byte buffer[MAX_DIGEST_SIZE];
133 if (hashType == MD5) {
134 hLen = MD5_DIGEST_SIZE;
136 else if (hashType == SHA) {
137 hLen = SHA_DIGEST_SIZE;
140 else if (hashType == SHA256) {
141 hLen = SHA256_DIGEST_SIZE;
145 else if (hashType == SHA512) {
146 hLen = SHA512_DIGEST_SIZE;
152 #ifdef CYASSL_SMALL_STACK
153 buffer = (byte*)XMALLOC(MAX_DIGEST_SIZE, NULL, DYNAMIC_TYPE_TMP_BUFFER);
158 ret = HmacSetKey(&hmac, hashType, passwd, pLen);
164 ret = HmacUpdate(&hmac, salt, sLen);
169 for (j = 0; j < 4; j++) {
170 byte b = (byte)(i >> ((3-j) * 8));
172 ret = HmacUpdate(&hmac, &b, 1);
177 /* check ret from inside for loop */
181 ret = HmacFinal(&hmac, buffer);
185 currentLen = min(kLen, hLen);
186 XMEMCPY(output, buffer, currentLen);
188 for (j = 1; j < iterations; j++) {
189 ret = HmacUpdate(&hmac, buffer, hLen);
192 ret = HmacFinal(&hmac, buffer);
195 xorbuf(output, buffer, currentLen);
198 /* check ret from inside for loop */
202 output += currentLen;
208 #ifdef CYASSL_SMALL_STACK
209 XFREE(buffer, NULL, DYNAMIC_TYPE_TMP_BUFFER);
216 #define PBKDF_DIGEST_SIZE SHA512_BLOCK_SIZE
217 #elif !defined(NO_SHA256)
218 #define PBKDF_DIGEST_SIZE SHA256_BLOCK_SIZE
220 #define PBKDF_DIGEST_SIZE SHA_DIGEST_SIZE
223 int PKCS12_PBKDF(byte* output, const byte* passwd, int passLen,const byte* salt,
224 int saltLen, int iterations, int kLen, int hashType, int id)
226 /* all in bytes instead of bits */
227 word32 u, v, dLen, pLen, iLen, sLen, totalLen;
232 #ifdef CYASSL_SMALL_STACK
233 byte staticBuffer[1]; /* force dynamic usage */
235 byte staticBuffer[1024];
237 byte* buffer = staticBuffer;
239 #ifdef CYASSL_SMALL_STACK
243 byte Ai[PBKDF_DIGEST_SIZE];
244 byte B[PBKDF_DIGEST_SIZE];
250 if (hashType == MD5) {
254 else if (hashType == SHA) {
259 else if (hashType == SHA256) {
260 v = SHA256_BLOCK_SIZE;
261 u = SHA256_DIGEST_SIZE;
265 else if (hashType == SHA512) {
266 v = SHA512_BLOCK_SIZE;
267 u = SHA512_DIGEST_SIZE;
273 #ifdef CYASSL_SMALL_STACK
274 Ai = (byte*)XMALLOC(PBKDF_DIGEST_SIZE, NULL, DYNAMIC_TYPE_TMP_BUFFER);
278 B = (byte*)XMALLOC(PBKDF_DIGEST_SIZE, NULL, DYNAMIC_TYPE_TMP_BUFFER);
280 XFREE(Ai, NULL, DYNAMIC_TYPE_TMP_BUFFER);
286 sLen = v * ((saltLen + v - 1) / v);
288 pLen = v * ((passLen + v - 1) / v);
293 totalLen = dLen + sLen + pLen;
295 if (totalLen > sizeof(staticBuffer)) {
296 buffer = (byte*)XMALLOC(totalLen, 0, DYNAMIC_TYPE_KEY);
297 if (buffer == NULL) {
298 #ifdef CYASSL_SMALL_STACK
299 XFREE(Ai, NULL, DYNAMIC_TYPE_TMP_BUFFER);
300 XFREE(B, NULL, DYNAMIC_TYPE_TMP_BUFFER);
312 XMEMSET(D, id, dLen);
314 for (i = 0; i < (int)sLen; i++)
315 S[i] = salt[i % saltLen];
316 for (i = 0; i < (int)pLen; i++)
317 P[i] = passwd[i % passLen];
323 if (hashType == MD5) {
327 Md5Update(&md5, buffer, totalLen);
330 for (i = 1; i < iterations; i++) {
331 Md5Update(&md5, Ai, u);
335 else if (hashType == SHA) {
341 ShaUpdate(&sha, buffer, totalLen);
344 for (i = 1; i < iterations; i++) {
345 ShaUpdate(&sha, Ai, u);
350 else if (hashType == SHA256) {
353 ret = InitSha256(&sha256);
357 ret = Sha256Update(&sha256, buffer, totalLen);
361 ret = Sha256Final(&sha256, Ai);
365 for (i = 1; i < iterations; i++) {
366 ret = Sha256Update(&sha256, Ai, u);
370 ret = Sha256Final(&sha256, Ai);
377 else if (hashType == SHA512) {
380 ret = InitSha512(&sha512);
384 ret = Sha512Update(&sha512, buffer, totalLen);
388 ret = Sha512Final(&sha512, Ai);
392 for (i = 1; i < iterations; i++) {
393 ret = Sha512Update(&sha512, Ai, u);
397 ret = Sha512Final(&sha512, Ai);
404 for (i = 0; i < (int)v; i++)
407 if (mp_init(&B1) != MP_OKAY)
409 else if (mp_read_unsigned_bin(&B1, B, v) != MP_OKAY)
411 else if (mp_add_d(&B1, (mp_digit)1, &B1) != MP_OKAY)
419 for (i = 0; i < (int)iLen; i += v) {
424 if (mp_init_multi(&i1, &res, NULL, NULL, NULL, NULL) != MP_OKAY) {
428 if (mp_read_unsigned_bin(&i1, I + i, v) != MP_OKAY)
430 else if (mp_add(&i1, &B1, &res) != MP_OKAY)
432 else if ( (outSz = mp_unsigned_bin_size(&res)) < 0)
435 if (outSz > (int)v) {
438 ret = mp_to_unsigned_bin(&res, tmp);
439 XMEMCPY(I + i, tmp + 1, v);
441 else if (outSz < (int)v) {
442 XMEMSET(I + i, 0, v - outSz);
443 ret = mp_to_unsigned_bin(&res, I + i + v - outSz);
446 ret = mp_to_unsigned_bin(&res, I + i);
454 currentLen = min(kLen, (int)u);
455 XMEMCPY(output, Ai, currentLen);
456 output += currentLen;
461 if (dynamic) XFREE(buffer, 0, DYNAMIC_TYPE_KEY);
463 #ifdef CYASSL_SMALL_STACK
464 XFREE(Ai, NULL, DYNAMIC_TYPE_TMP_BUFFER);
465 XFREE(B, NULL, DYNAMIC_TYPE_TMP_BUFFER);
471 #undef PBKDF_DIGEST_SIZE
473 #endif /* NO_PWDBASED */