3 * Copyright (C) 2006-2012 Sawtooth Consulting Ltd.
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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
28 #include <cyassl/ctaocrypt/pwdbased.h>
29 #include <cyassl/ctaocrypt/hmac.h>
30 #include <cyassl/ctaocrypt/integer.h>
31 #include <cyassl/ctaocrypt/error.h>
33 #include <cyassl/ctaocrypt/sha512.h>
36 #include <cyassl/ctaocrypt/misc.h>
38 #include <ctaocrypt/src/misc.c>
44 static INLINE word32 min(word32 a, word32 b)
52 int PBKDF1(byte* output, const byte* passwd, int pLen, const byte* salt,
53 int sLen, int iterations, int kLen, int hashType)
57 int hLen = (hashType == MD5) ? MD5_DIGEST_SIZE : SHA_DIGEST_SIZE;
59 byte buffer[SHA_DIGEST_SIZE]; /* max size */
61 if (hashType != MD5 && hashType != SHA)
70 if (hashType == MD5) {
72 Md5Update(&md5, passwd, pLen);
73 Md5Update(&md5, salt, sLen);
74 Md5Final(&md5, buffer);
78 ShaUpdate(&sha, passwd, pLen);
79 ShaUpdate(&sha, salt, sLen);
80 ShaFinal(&sha, buffer);
83 for (i = 1; i < iterations; i++) {
84 if (hashType == MD5) {
85 Md5Update(&md5, buffer, hLen);
86 Md5Final(&md5, buffer);
89 ShaUpdate(&sha, buffer, hLen);
90 ShaFinal(&sha, buffer);
93 XMEMCPY(output, buffer, kLen);
99 int PBKDF2(byte* output, const byte* passwd, int pLen, const byte* salt,
100 int sLen, int iterations, int kLen, int hashType)
106 byte buffer[INNER_HASH_SIZE]; /* max size */
108 if (hashType == MD5) {
109 hLen = MD5_DIGEST_SIZE;
111 else if (hashType == SHA) {
112 hLen = SHA_DIGEST_SIZE;
115 else if (hashType == SHA256) {
116 hLen = SHA256_DIGEST_SIZE;
120 else if (hashType == SHA512) {
121 hLen = SHA512_DIGEST_SIZE;
127 HmacSetKey(&hmac, hashType, passwd, pLen);
131 HmacUpdate(&hmac, salt, sLen);
134 for (j = 0; j < 4; j++) {
135 byte b = (byte)(i >> ((3-j) * 8));
136 HmacUpdate(&hmac, &b, 1);
138 HmacFinal(&hmac, buffer);
140 currentLen = min(kLen, hLen);
141 XMEMCPY(output, buffer, currentLen);
143 for (j = 1; j < iterations; j++) {
144 HmacUpdate(&hmac, buffer, hLen);
145 HmacFinal(&hmac, buffer);
146 xorbuf(output, buffer, currentLen);
149 output += currentLen;
158 int PKCS12_PBKDF(byte* output, const byte* passwd, int passLen,const byte* salt,
159 int saltLen, int iterations, int kLen, int hashType, int id)
161 /* all in bytes instead of bits */
162 word32 u, v, dLen, pLen, iLen, sLen, totalLen;
167 byte staticBuffer[1024];
168 byte* buffer = staticBuffer;
170 byte Ai[SHA512_DIGEST_SIZE];
171 byte B[SHA512_BLOCK_SIZE];
172 #elif !defined(NO_SHA256)
173 byte Ai[SHA256_DIGEST_SIZE];
174 byte B[SHA256_BLOCK_SIZE];
176 byte Ai[SHA_DIGEST_SIZE];
177 byte B[SHA_BLOCK_SIZE];
183 if (hashType == MD5) {
187 else if (hashType == SHA) {
192 else if (hashType == SHA256) {
193 v = SHA256_BLOCK_SIZE;
194 u = SHA256_DIGEST_SIZE;
198 else if (hashType == SHA512) {
199 v = SHA512_BLOCK_SIZE;
200 u = SHA512_DIGEST_SIZE;
207 sLen = v * ((saltLen + v - 1) / v);
209 pLen = v * ((passLen + v - 1) / v);
214 totalLen = dLen + sLen + pLen;
216 if (totalLen > sizeof(staticBuffer)) {
217 buffer = (byte*)XMALLOC(totalLen, 0, DYNAMIC_TYPE_KEY);
218 if (buffer == NULL) return MEMORY_E;
227 XMEMSET(D, id, dLen);
229 for (i = 0; i < (int)sLen; i++)
230 S[i] = salt[i % saltLen];
231 for (i = 0; i < (int)pLen; i++)
232 P[i] = passwd[i % passLen];
238 if (hashType == MD5) {
240 else if (hashType == SHA) {
244 ShaUpdate(&sha, buffer, totalLen);
247 for (i = 1; i < iterations; i++) {
248 ShaUpdate(&sha, Ai, u);
253 else if (hashType == SHA256) {
257 else if (hashType == SHA512) {
261 for (i = 0; i < (int)v; i++)
265 if (mp_read_unsigned_bin(&B1, B, v) != MP_OKAY)
267 else if (mp_add_d(&B1, (mp_digit)1, &B1) != MP_OKAY) {
273 for (i = 0; i < (int)iLen; i += v) {
281 if (mp_read_unsigned_bin(&i1, I + i, v) != MP_OKAY)
283 else if (mp_add(&i1, &B1, &res) != MP_OKAY)
285 else if ( (outSz = mp_unsigned_bin_size(&res)) < 0)
288 if (outSz > (int)v) {
291 mp_to_unsigned_bin(&res, tmp);
292 XMEMCPY(I + i, tmp + 1, v);
294 else if (outSz < (int)v) {
295 XMEMSET(I + i, 0, v - outSz);
296 mp_to_unsigned_bin(&res, I + i + v - outSz);
299 mp_to_unsigned_bin(&res, I + i);
307 currentLen = min(kLen, (int)u);
308 XMEMCPY(output, Ai, currentLen);
309 output += currentLen;
314 if (dynamic) XFREE(buffer, 0, DYNAMIC_TYPE_KEY);
318 #endif /* NO_PWDBASED */