]> git.sur5r.net Git - freertos/blob - FreeRTOS-Plus/CyaSSL/ctaocrypt/src/pwdbased.c
d36f7e9aa2ec40af26882e55f03d792497306ec4
[freertos] / FreeRTOS-Plus / CyaSSL / ctaocrypt / src / pwdbased.c
1 /* pwdbased.c
2  *
3  * Copyright (C) 2006-2012 Sawtooth Consulting Ltd.
4  *
5  * This file is part of CyaSSL.
6  *
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.
11  *
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.
16  *
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
20  */
21
22 #ifdef HAVE_CONFIG_H
23     #include <config.h>
24 #endif
25
26 #ifndef NO_PWDBASED
27
28 #include <cyassl/ctaocrypt/pwdbased.h>
29 #include <cyassl/ctaocrypt/hmac.h>
30 #include <cyassl/ctaocrypt/integer.h>
31 #include <cyassl/ctaocrypt/error.h>
32 #ifdef CYASSL_SHA512
33     #include <cyassl/ctaocrypt/sha512.h>
34 #endif
35 #ifdef NO_INLINE
36     #include <cyassl/ctaocrypt/misc.h>
37 #else
38     #include <ctaocrypt/src/misc.c>
39 #endif
40
41
42 #ifndef min
43
44     static INLINE word32 min(word32 a, word32 b)
45     {
46         return a > b ? b : a;
47     }
48
49 #endif /* min */
50
51
52 int PBKDF1(byte* output, const byte* passwd, int pLen, const byte* salt,
53            int sLen, int iterations, int kLen, int hashType)
54 {
55     Md5  md5;
56     Sha  sha;
57     int  hLen = (hashType == MD5) ? MD5_DIGEST_SIZE : SHA_DIGEST_SIZE;
58     int  i;
59     byte buffer[SHA_DIGEST_SIZE];  /* max size */
60
61     if (hashType != MD5 && hashType != SHA)
62         return BAD_FUNC_ARG;
63
64     if (kLen > hLen)
65         return BAD_FUNC_ARG;
66
67     if (iterations < 1)
68         return BAD_FUNC_ARG;
69
70     if (hashType == MD5) {
71         InitMd5(&md5);
72         Md5Update(&md5, passwd, pLen);
73         Md5Update(&md5, salt,   sLen);
74         Md5Final(&md5,  buffer);
75     }
76     else {
77         InitSha(&sha);
78         ShaUpdate(&sha, passwd, pLen);
79         ShaUpdate(&sha, salt,   sLen);
80         ShaFinal(&sha,  buffer);
81     }
82
83     for (i = 1; i < iterations; i++) {
84         if (hashType == MD5) {
85             Md5Update(&md5, buffer, hLen);
86             Md5Final(&md5,  buffer);
87         }
88         else {
89             ShaUpdate(&sha, buffer, hLen);
90             ShaFinal(&sha,  buffer);
91         }
92     }
93     XMEMCPY(output, buffer, kLen);
94
95     return 0;
96 }
97
98
99 int PBKDF2(byte* output, const byte* passwd, int pLen, const byte* salt,
100            int sLen, int iterations, int kLen, int hashType)
101 {
102     word32 i = 1;
103     int    hLen;
104     int    j;
105     Hmac   hmac;
106     byte   buffer[INNER_HASH_SIZE];  /* max size */
107
108     if (hashType == MD5) {
109         hLen = MD5_DIGEST_SIZE;
110     }
111     else if (hashType == SHA) {
112         hLen = SHA_DIGEST_SIZE;
113     }
114 #ifndef NO_SHA256
115     else if (hashType == SHA256) {
116         hLen = SHA256_DIGEST_SIZE;
117     }
118 #endif
119 #ifdef CYASSL_SHA512
120     else if (hashType == SHA512) {
121         hLen = SHA512_DIGEST_SIZE;
122     }
123 #endif
124     else
125         return BAD_FUNC_ARG;
126
127     HmacSetKey(&hmac, hashType, passwd, pLen);
128
129     while (kLen) {
130         int currentLen;
131         HmacUpdate(&hmac, salt, sLen);
132
133         /* encode i */
134         for (j = 0; j < 4; j++) {
135             byte b = (byte)(i >> ((3-j) * 8));
136             HmacUpdate(&hmac, &b, 1);
137         }
138         HmacFinal(&hmac, buffer);
139
140         currentLen = min(kLen, hLen);
141         XMEMCPY(output, buffer, currentLen);
142
143         for (j = 1; j < iterations; j++) {
144             HmacUpdate(&hmac, buffer, hLen);
145             HmacFinal(&hmac, buffer);
146             xorbuf(output, buffer, currentLen);
147         }
148
149         output += currentLen;
150         kLen   -= currentLen;
151         i++;
152     }
153
154     return 0;
155 }
156
157
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)
160 {
161     /* all in bytes instead of bits */
162     word32 u, v, dLen, pLen, iLen, sLen, totalLen;
163     int    dynamic = 0;
164     int    ret = 0;
165     int    i;
166     byte   *D, *S, *P, *I;
167     byte   staticBuffer[1024];
168     byte*  buffer = staticBuffer;
169 #ifdef CYASSL_SHA512
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];
175 #else
176     byte   Ai[SHA_DIGEST_SIZE];
177     byte   B[SHA_BLOCK_SIZE];
178 #endif
179
180     if (!iterations)
181         iterations = 1;
182
183     if (hashType == MD5) {
184         v = MD5_BLOCK_SIZE;
185         u = MD5_DIGEST_SIZE;
186     }
187     else if (hashType == SHA) {
188         v = SHA_BLOCK_SIZE;
189         u = SHA_DIGEST_SIZE;
190     }
191 #ifndef NO_SHA256
192     else if (hashType == SHA256) {
193         v = SHA256_BLOCK_SIZE;
194         u = SHA256_DIGEST_SIZE;
195     }
196 #endif
197 #ifdef CYASSL_SHA512
198     else if (hashType == SHA512) {
199         v = SHA512_BLOCK_SIZE;
200         u = SHA512_DIGEST_SIZE;
201     }
202 #endif
203     else
204         return BAD_FUNC_ARG; 
205
206     dLen = v;
207     sLen =  v * ((saltLen + v - 1) / v);
208     if (passLen)
209         pLen = v * ((passLen + v - 1) / v);
210     else
211         pLen = 0;
212     iLen = sLen + pLen;
213
214     totalLen = dLen + sLen + pLen;
215
216     if (totalLen > sizeof(staticBuffer)) {
217         buffer = (byte*)XMALLOC(totalLen, 0, DYNAMIC_TYPE_KEY);
218         if (buffer == NULL) return MEMORY_E;
219         dynamic = 1;
220     } 
221
222     D = buffer;
223     S = D + dLen;
224     P = S + sLen;
225     I = S;
226
227     XMEMSET(D, id, dLen);
228
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];
233
234     while (kLen > 0) {
235         word32 currentLen;
236         mp_int B1;
237
238         if (hashType == MD5) {
239         }
240         else if (hashType == SHA) {
241             Sha sha;
242
243             InitSha(&sha);
244             ShaUpdate(&sha, buffer, totalLen);
245             ShaFinal(&sha, Ai);
246
247             for (i = 1; i < iterations; i++) {
248                 ShaUpdate(&sha, Ai, u);
249                 ShaFinal(&sha, Ai);
250             }
251         }
252 #ifndef NO_SHA256
253         else if (hashType == SHA256) {
254         }
255 #endif
256 #ifdef CYASSL_SHA512
257         else if (hashType == SHA512) {
258         }
259 #endif
260
261         for (i = 0; i < (int)v; i++)
262             B[i] = Ai[i % u];
263
264         mp_init(&B1);
265         if (mp_read_unsigned_bin(&B1, B, v) != MP_OKAY)
266             ret = MP_READ_E;
267         else if (mp_add_d(&B1, (mp_digit)1, &B1) != MP_OKAY) {
268             ret = MP_ADD_E;
269             mp_clear(&B1);
270             break;
271         }
272
273         for (i = 0; i < (int)iLen; i += v) {
274             int    outSz;
275             mp_int i1;
276             mp_int res;
277
278             mp_init(&i1);
279             mp_init(&res);
280
281             if (mp_read_unsigned_bin(&i1, I + i, v) != MP_OKAY)
282                 ret = MP_READ_E;
283             else if (mp_add(&i1, &B1, &res) != MP_OKAY)
284                 ret = MP_ADD_E;
285             else if ( (outSz = mp_unsigned_bin_size(&res)) < 0)
286                 ret = MP_TO_E;
287             else {
288                 if (outSz > (int)v) {
289                     /* take off MSB */
290                     byte  tmp[129];
291                     mp_to_unsigned_bin(&res, tmp);
292                     XMEMCPY(I + i, tmp + 1, v);
293                 }
294                 else if (outSz < (int)v) {
295                     XMEMSET(I + i, 0, v - outSz);
296                     mp_to_unsigned_bin(&res, I + i + v - outSz);
297                 }
298                 else
299                     mp_to_unsigned_bin(&res, I + i);
300             }
301
302             mp_clear(&i1);
303             mp_clear(&res);
304             if (ret < 0) break;
305         }
306
307         currentLen = min(kLen, (int)u);
308         XMEMCPY(output, Ai, currentLen);
309         output += currentLen;
310         kLen   -= currentLen;
311         mp_clear(&B1);
312     }
313
314     if (dynamic) XFREE(buffer, 0, DYNAMIC_TYPE_KEY);
315     return ret;
316 }
317
318 #endif /* NO_PWDBASED */
319