]> git.sur5r.net Git - freertos/blob - FreeRTOS-Plus/Source/CyaSSL/ctaocrypt/src/pwdbased.c
582c80fb9886bd21694c58925e0bec1987e06f46
[freertos] / FreeRTOS-Plus / Source / CyaSSL / ctaocrypt / src / pwdbased.c
1 /* pwdbased.c
2  *
3  * Copyright (C) 2006-2014 wolfSSL Inc.
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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
20  */
21
22 #ifdef HAVE_CONFIG_H
23     #include <config.h>
24 #endif
25
26 #include <cyassl/ctaocrypt/settings.h>
27
28 #ifndef NO_PWDBASED
29
30 #ifdef CYASSL_PIC32MZ_HASH
31
32 #define InitMd5   InitMd5_sw
33 #define Md5Update Md5Update_sw
34 #define Md5Final  Md5Final_sw
35
36 #define InitSha   InitSha_sw
37 #define ShaUpdate ShaUpdate_sw
38 #define ShaFinal  ShaFinal_sw
39
40 #define InitSha256   InitSha256_sw
41 #define Sha256Update Sha256Update_sw
42 #define Sha256Final  Sha256Final_sw
43
44 #endif
45
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>
52 #endif
53
54 #ifdef NO_INLINE
55     #include <cyassl/ctaocrypt/misc.h>
56 #else
57     #include <ctaocrypt/src/misc.c>
58 #endif
59
60
61 #ifndef min
62
63     static INLINE word32 min(word32 a, word32 b)
64     {
65         return a > b ? b : a;
66     }
67
68 #endif /* min */
69
70
71 int PBKDF1(byte* output, const byte* passwd, int pLen, const byte* salt,
72            int sLen, int iterations, int kLen, int hashType)
73 {
74     Md5  md5;
75     Sha  sha;
76     int  hLen = (hashType == MD5) ? (int)MD5_DIGEST_SIZE : (int)SHA_DIGEST_SIZE;
77     int  i, ret = 0;
78     byte buffer[SHA_DIGEST_SIZE];  /* max size */
79
80     if (hashType != MD5 && hashType != SHA)
81         return BAD_FUNC_ARG;
82
83     if (kLen > hLen)
84         return BAD_FUNC_ARG;
85
86     if (iterations < 1)
87         return BAD_FUNC_ARG;
88
89     if (hashType == MD5) {
90         InitMd5(&md5);
91         Md5Update(&md5, passwd, pLen);
92         Md5Update(&md5, salt,   sLen);
93         Md5Final(&md5,  buffer);
94     }
95     else {
96         ret = InitSha(&sha);
97         if (ret != 0)
98             return ret;
99         ShaUpdate(&sha, passwd, pLen);
100         ShaUpdate(&sha, salt,   sLen);
101         ShaFinal(&sha,  buffer);
102     }
103
104     for (i = 1; i < iterations; i++) {
105         if (hashType == MD5) {
106             Md5Update(&md5, buffer, hLen);
107             Md5Final(&md5,  buffer);
108         }
109         else {
110             ShaUpdate(&sha, buffer, hLen);
111             ShaFinal(&sha,  buffer);
112         }
113     }
114     XMEMCPY(output, buffer, kLen);
115
116     return 0;
117 }
118
119
120 int PBKDF2(byte* output, const byte* passwd, int pLen, const byte* salt,
121            int sLen, int iterations, int kLen, int hashType)
122 {
123     word32 i = 1;
124     int    hLen;
125     int    j, ret;
126     Hmac   hmac;
127 #ifdef CYASSL_SMALL_STACK
128     byte*  buffer;
129 #else
130     byte   buffer[MAX_DIGEST_SIZE];
131 #endif
132
133     if (hashType == MD5) {
134         hLen = MD5_DIGEST_SIZE;
135     }
136     else if (hashType == SHA) {
137         hLen = SHA_DIGEST_SIZE;
138     }
139 #ifndef NO_SHA256
140     else if (hashType == SHA256) {
141         hLen = SHA256_DIGEST_SIZE;
142     }
143 #endif
144 #ifdef CYASSL_SHA512
145     else if (hashType == SHA512) {
146         hLen = SHA512_DIGEST_SIZE;
147     }
148 #endif
149     else
150         return BAD_FUNC_ARG;
151
152 #ifdef CYASSL_SMALL_STACK
153     buffer = (byte*)XMALLOC(MAX_DIGEST_SIZE, NULL, DYNAMIC_TYPE_TMP_BUFFER);
154     if (buffer == NULL)
155         return MEMORY_E;
156 #endif
157
158     ret = HmacSetKey(&hmac, hashType, passwd, pLen);
159
160     if (ret == 0) {
161         while (kLen) {
162             int currentLen;
163
164             ret = HmacUpdate(&hmac, salt, sLen);
165             if (ret != 0)
166                 break;
167
168             /* encode i */
169             for (j = 0; j < 4; j++) {
170                 byte b = (byte)(i >> ((3-j) * 8));
171
172                 ret = HmacUpdate(&hmac, &b, 1);
173                 if (ret != 0)
174                     break;
175             }
176
177             /* check ret from inside for loop */
178             if (ret != 0)
179                 break;
180
181             ret = HmacFinal(&hmac, buffer);
182             if (ret != 0)
183                 break;
184
185             currentLen = min(kLen, hLen);
186             XMEMCPY(output, buffer, currentLen);
187
188             for (j = 1; j < iterations; j++) {
189                 ret = HmacUpdate(&hmac, buffer, hLen);
190                 if (ret != 0)
191                     break;
192                 ret = HmacFinal(&hmac, buffer);
193                 if (ret != 0)
194                     break;
195                 xorbuf(output, buffer, currentLen);
196             }
197
198             /* check ret from inside for loop */
199             if (ret != 0)
200                 break;
201
202             output += currentLen;
203             kLen   -= currentLen;
204             i++;
205         }
206     }
207
208 #ifdef CYASSL_SMALL_STACK
209     XFREE(buffer, NULL, DYNAMIC_TYPE_TMP_BUFFER);
210 #endif
211
212     return ret;
213 }
214
215 #ifdef CYASSL_SHA512
216 #define PBKDF_DIGEST_SIZE SHA512_BLOCK_SIZE
217 #elif !defined(NO_SHA256)
218 #define PBKDF_DIGEST_SIZE SHA256_BLOCK_SIZE
219 #else
220 #define PBKDF_DIGEST_SIZE SHA_DIGEST_SIZE
221 #endif
222
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)
225 {
226     /* all in bytes instead of bits */
227     word32 u, v, dLen, pLen, iLen, sLen, totalLen;
228     int    dynamic = 0;
229     int    ret = 0;
230     int    i;
231     byte   *D, *S, *P, *I;
232 #ifdef CYASSL_SMALL_STACK
233     byte   staticBuffer[1]; /* force dynamic usage */
234 #else
235     byte   staticBuffer[1024];
236 #endif
237     byte*  buffer = staticBuffer;
238
239 #ifdef CYASSL_SMALL_STACK
240     byte*  Ai;
241     byte*  B;
242 #else
243     byte   Ai[PBKDF_DIGEST_SIZE];
244     byte   B[PBKDF_DIGEST_SIZE];
245 #endif
246
247     if (!iterations)
248         iterations = 1;
249
250     if (hashType == MD5) {
251         v = MD5_BLOCK_SIZE;
252         u = MD5_DIGEST_SIZE;
253     }
254     else if (hashType == SHA) {
255         v = SHA_BLOCK_SIZE;
256         u = SHA_DIGEST_SIZE;
257     }
258 #ifndef NO_SHA256
259     else if (hashType == SHA256) {
260         v = SHA256_BLOCK_SIZE;
261         u = SHA256_DIGEST_SIZE;
262     }
263 #endif
264 #ifdef CYASSL_SHA512
265     else if (hashType == SHA512) {
266         v = SHA512_BLOCK_SIZE;
267         u = SHA512_DIGEST_SIZE;
268     }
269 #endif
270     else
271         return BAD_FUNC_ARG;
272
273 #ifdef CYASSL_SMALL_STACK
274     Ai = (byte*)XMALLOC(PBKDF_DIGEST_SIZE, NULL, DYNAMIC_TYPE_TMP_BUFFER);
275     if (Ai == NULL)
276         return MEMORY_E;
277
278     B = (byte*)XMALLOC(PBKDF_DIGEST_SIZE, NULL, DYNAMIC_TYPE_TMP_BUFFER);
279     if (B == NULL) {
280         XFREE(Ai, NULL, DYNAMIC_TYPE_TMP_BUFFER);
281         return MEMORY_E;
282     }
283 #endif
284
285     dLen = v;
286     sLen =  v * ((saltLen + v - 1) / v);
287     if (passLen)
288         pLen = v * ((passLen + v - 1) / v);
289     else
290         pLen = 0;
291     iLen = sLen + pLen;
292
293     totalLen = dLen + sLen + pLen;
294
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);
301 #endif
302             return MEMORY_E;
303         }
304         dynamic = 1;
305     } 
306
307     D = buffer;
308     S = D + dLen;
309     P = S + sLen;
310     I = S;
311
312     XMEMSET(D, id, dLen);
313
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];
318
319     while (kLen > 0) {
320         word32 currentLen;
321         mp_int B1;
322
323         if (hashType == MD5) {
324             Md5 md5;
325
326             InitMd5(&md5);
327             Md5Update(&md5, buffer, totalLen);
328             Md5Final(&md5, Ai);
329
330             for (i = 1; i < iterations; i++) {
331                 Md5Update(&md5, Ai, u);
332                 Md5Final(&md5, Ai);
333             }
334         }
335         else if (hashType == SHA) {
336             Sha sha;
337
338             ret = InitSha(&sha);
339             if (ret != 0)
340                 break;
341             ShaUpdate(&sha, buffer, totalLen);
342             ShaFinal(&sha, Ai);
343
344             for (i = 1; i < iterations; i++) {
345                 ShaUpdate(&sha, Ai, u);
346                 ShaFinal(&sha, Ai);
347             }
348         }
349 #ifndef NO_SHA256
350         else if (hashType == SHA256) {
351             Sha256 sha256;
352
353             ret = InitSha256(&sha256);
354             if (ret != 0)
355                 break;
356
357             ret = Sha256Update(&sha256, buffer, totalLen);
358             if (ret != 0)
359                 break;
360
361             ret = Sha256Final(&sha256, Ai);
362             if (ret != 0)
363                 break;
364
365             for (i = 1; i < iterations; i++) {
366                 ret = Sha256Update(&sha256, Ai, u);
367                 if (ret != 0)
368                     break;
369
370                 ret = Sha256Final(&sha256, Ai);
371                 if (ret != 0)
372                     break;
373             }
374         }
375 #endif
376 #ifdef CYASSL_SHA512
377         else if (hashType == SHA512) {
378             Sha512 sha512;
379
380             ret = InitSha512(&sha512);
381             if (ret != 0)
382                 break;
383
384             ret = Sha512Update(&sha512, buffer, totalLen);
385             if (ret != 0)
386                 break;
387
388             ret = Sha512Final(&sha512, Ai);
389             if (ret != 0)
390                 break;
391
392             for (i = 1; i < iterations; i++) {
393                 ret = Sha512Update(&sha512, Ai, u);
394                 if (ret != 0)
395                     break;
396
397                 ret = Sha512Final(&sha512, Ai);
398                 if (ret != 0)
399                     break;
400             }
401         }
402 #endif
403
404         for (i = 0; i < (int)v; i++)
405             B[i] = Ai[i % u];
406
407         if (mp_init(&B1) != MP_OKAY)
408             ret = MP_INIT_E;
409         else if (mp_read_unsigned_bin(&B1, B, v) != MP_OKAY)
410             ret = MP_READ_E;
411         else if (mp_add_d(&B1, (mp_digit)1, &B1) != MP_OKAY)
412             ret = MP_ADD_E;
413
414         if (ret != 0) {
415             mp_clear(&B1);
416             break;
417         }
418
419         for (i = 0; i < (int)iLen; i += v) {
420             int    outSz;
421             mp_int i1;
422             mp_int res;
423
424             if (mp_init_multi(&i1, &res, NULL, NULL, NULL, NULL) != MP_OKAY) {
425                 ret = MP_INIT_E;
426                 break;
427             }
428             if (mp_read_unsigned_bin(&i1, I + i, v) != MP_OKAY)
429                 ret = MP_READ_E;
430             else if (mp_add(&i1, &B1, &res) != MP_OKAY)
431                 ret = MP_ADD_E;
432             else if ( (outSz = mp_unsigned_bin_size(&res)) < 0)
433                 ret = MP_TO_E;
434             else {
435                 if (outSz > (int)v) {
436                     /* take off MSB */
437                     byte  tmp[129];
438                     ret = mp_to_unsigned_bin(&res, tmp);
439                     XMEMCPY(I + i, tmp + 1, v);
440                 }
441                 else if (outSz < (int)v) {
442                     XMEMSET(I + i, 0, v - outSz);
443                     ret = mp_to_unsigned_bin(&res, I + i + v - outSz);
444                 }
445                 else
446                     ret = mp_to_unsigned_bin(&res, I + i);
447             }
448
449             mp_clear(&i1);
450             mp_clear(&res);
451             if (ret < 0) break;
452         }
453
454         currentLen = min(kLen, (int)u);
455         XMEMCPY(output, Ai, currentLen);
456         output += currentLen;
457         kLen   -= currentLen;
458         mp_clear(&B1);
459     }
460
461     if (dynamic) XFREE(buffer, 0, DYNAMIC_TYPE_KEY);
462
463 #ifdef CYASSL_SMALL_STACK
464     XFREE(Ai, NULL, DYNAMIC_TYPE_TMP_BUFFER);
465     XFREE(B,  NULL, DYNAMIC_TYPE_TMP_BUFFER);
466 #endif
467
468     return ret;
469 }
470
471 #undef PBKDF_DIGEST_SIZE
472
473 #endif /* NO_PWDBASED */
474