source: UsbWattMeter/trunk/wolfssl-3.7.0/wolfcrypt/src/pwdbased.c@ 164

Last change on this file since 164 was 164, checked in by coas-nagasima, 6 years ago

TOPPERS/ECNLサンプルアプリ「USB充電器電力計」を追加

  • Property svn:eol-style set to native
  • Property svn:keywords set to Id
  • Property svn:mime-type set to text/x-csrc
File size: 13.7 KB
Line 
1/* pwdbased.c
2 *
3 * Copyright (C) 2006-2015 wolfSSL Inc.
4 *
5 * This file is part of wolfSSL. (formerly known as CyaSSL)
6 *
7 * wolfSSL 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 * wolfSSL 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 <wolfssl/wolfcrypt/settings.h>
27
28#ifndef NO_PWDBASED
29
30#ifdef WOLFSSL_PIC32MZ_HASH
31 #ifndef NO_MD5
32 #define wc_InitMd5 wc_InitMd5_sw
33 #define wc_Md5Update wc_Md5Update_sw
34 #define wc_Md5Final wc_Md5Final_sw
35 #endif /* NO_MD5 */
36
37 #define wc_InitSha wc_InitSha_sw
38 #define wc_ShaUpdate wc_ShaUpdate_sw
39 #define wc_ShaFinal wc_ShaFinal_sw
40
41 #define wc_InitSha256 wc_InitSha256_sw
42 #define wc_Sha256Update wc_Sha256Update_sw
43 #define wc_Sha256Final wc_Sha256Final_sw
44#endif
45
46#include <wolfssl/wolfcrypt/pwdbased.h>
47#include <wolfssl/wolfcrypt/hmac.h>
48#include <wolfssl/wolfcrypt/integer.h>
49#include <wolfssl/wolfcrypt/error-crypt.h>
50#if defined(WOLFSSL_SHA512) || defined(WOLFSSL_SHA384)
51 #include <wolfssl/wolfcrypt/sha512.h>
52#endif
53
54#ifdef NO_INLINE
55 #include <wolfssl/wolfcrypt/misc.h>
56#else
57 #include <wolfcrypt/src/misc.c>
58#endif
59
60#ifdef min
61#define WOLFSSL_HAVE_MIN
62#endif
63#ifndef WOLFSSL_HAVE_MIN
64#define WOLFSSL_HAVE_MIN
65
66 static INLINE word32 min(word32 a, word32 b)
67 {
68 return a > b ? b : a;
69 }
70
71#endif /* WOLFSSL_HAVE_MIN */
72
73
74#ifndef NO_SHA
75/* PBKDF1 needs at least SHA available */
76int wc_PBKDF1(byte* output, const byte* passwd, int pLen, const byte* salt,
77 int sLen, int iterations, int kLen, int hashType)
78{
79 Sha sha;
80#ifndef NO_MD5
81 Md5 md5;
82#endif
83 int hLen = (int)SHA_DIGEST_SIZE;
84 int i, ret = 0;
85 byte buffer[SHA_DIGEST_SIZE]; /* max size */
86
87 if (hashType != MD5 && hashType != SHA)
88 return BAD_FUNC_ARG;
89
90#ifndef NO_MD5
91 if (hashType == MD5)
92 hLen = (int)MD5_DIGEST_SIZE;
93#endif
94
95 if (kLen > hLen)
96 return BAD_FUNC_ARG;
97
98 if (iterations < 1)
99 return BAD_FUNC_ARG;
100
101 switch (hashType) {
102#ifndef NO_MD5
103 case MD5:
104 wc_InitMd5(&md5);
105 wc_Md5Update(&md5, passwd, pLen);
106 wc_Md5Update(&md5, salt, sLen);
107 wc_Md5Final(&md5, buffer);
108 break;
109#endif /* NO_MD5 */
110 case SHA:
111 default:
112 ret = wc_InitSha(&sha);
113 if (ret != 0)
114 return ret;
115 wc_ShaUpdate(&sha, passwd, pLen);
116 wc_ShaUpdate(&sha, salt, sLen);
117 wc_ShaFinal(&sha, buffer);
118 break;
119 }
120
121 for (i = 1; i < iterations; i++) {
122 if (hashType == SHA) {
123 wc_ShaUpdate(&sha, buffer, hLen);
124 wc_ShaFinal(&sha, buffer);
125 }
126#ifndef NO_MD5
127 else {
128 wc_Md5Update(&md5, buffer, hLen);
129 wc_Md5Final(&md5, buffer);
130 }
131#endif
132 }
133 XMEMCPY(output, buffer, kLen);
134
135 return 0;
136}
137#endif /* NO_SHA */
138
139
140int GetDigestSize(int hashType)
141{
142 int hLen;
143
144 switch (hashType) {
145#ifndef NO_MD5
146 case MD5:
147 hLen = MD5_DIGEST_SIZE;
148 break;
149#endif
150#ifndef NO_SHA
151 case SHA:
152 hLen = SHA_DIGEST_SIZE;
153 break;
154#endif
155#ifndef NO_SHA256
156 case SHA256:
157 hLen = SHA256_DIGEST_SIZE;
158 break;
159#endif
160#ifdef WOLFSSL_SHA512
161 case SHA512:
162 hLen = SHA512_DIGEST_SIZE;
163 break;
164#endif
165 default:
166 return BAD_FUNC_ARG;
167 }
168
169 return hLen;
170}
171
172
173int wc_PBKDF2(byte* output, const byte* passwd, int pLen, const byte* salt,
174 int sLen, int iterations, int kLen, int hashType)
175{
176 word32 i = 1;
177 int hLen;
178 int j, ret;
179 Hmac hmac;
180#ifdef WOLFSSL_SMALL_STACK
181 byte* buffer;
182#else
183 byte buffer[MAX_DIGEST_SIZE];
184#endif
185
186 hLen = GetDigestSize(hashType);
187 if (hLen < 0)
188 return BAD_FUNC_ARG;
189
190#ifdef WOLFSSL_SMALL_STACK
191 buffer = (byte*)XMALLOC(MAX_DIGEST_SIZE, NULL, DYNAMIC_TYPE_TMP_BUFFER);
192 if (buffer == NULL)
193 return MEMORY_E;
194#endif
195
196 ret = wc_HmacSetKey(&hmac, hashType, passwd, pLen);
197
198 if (ret == 0) {
199 while (kLen) {
200 int currentLen;
201
202 ret = wc_HmacUpdate(&hmac, salt, sLen);
203 if (ret != 0)
204 break;
205
206 /* encode i */
207 for (j = 0; j < 4; j++) {
208 byte b = (byte)(i >> ((3-j) * 8));
209
210 ret = wc_HmacUpdate(&hmac, &b, 1);
211 if (ret != 0)
212 break;
213 }
214
215 /* check ret from inside for loop */
216 if (ret != 0)
217 break;
218
219 ret = wc_HmacFinal(&hmac, buffer);
220 if (ret != 0)
221 break;
222
223 currentLen = min(kLen, hLen);
224 XMEMCPY(output, buffer, currentLen);
225
226 for (j = 1; j < iterations; j++) {
227 ret = wc_HmacUpdate(&hmac, buffer, hLen);
228 if (ret != 0)
229 break;
230 ret = wc_HmacFinal(&hmac, buffer);
231 if (ret != 0)
232 break;
233 xorbuf(output, buffer, currentLen);
234 }
235
236 /* check ret from inside for loop */
237 if (ret != 0)
238 break;
239
240 output += currentLen;
241 kLen -= currentLen;
242 i++;
243 }
244 }
245
246#ifdef WOLFSSL_SMALL_STACK
247 XFREE(buffer, NULL, DYNAMIC_TYPE_TMP_BUFFER);
248#endif
249
250 return ret;
251}
252
253#ifdef WOLFSSL_SHA512
254 #define PBKDF_DIGEST_SIZE SHA512_BLOCK_SIZE
255#elif !defined(NO_SHA256)
256 #define PBKDF_DIGEST_SIZE SHA256_BLOCK_SIZE
257#else
258 #define PBKDF_DIGEST_SIZE SHA_DIGEST_SIZE
259#endif
260
261/* helper for wc_PKCS12_PBKDF(), sets block and digest sizes */
262int GetPKCS12HashSizes(int hashType, word32* v, word32* u)
263{
264 if (!v || !u)
265 return BAD_FUNC_ARG;
266
267 switch (hashType) {
268#ifndef NO_MD5
269 case MD5:
270 *v = MD5_BLOCK_SIZE;
271 *u = MD5_DIGEST_SIZE;
272 break;
273#endif
274#ifndef NO_SHA
275 case SHA:
276 *v = SHA_BLOCK_SIZE;
277 *u = SHA_DIGEST_SIZE;
278 break;
279#endif
280#ifndef NO_SHA256
281 case SHA256:
282 *v = SHA256_BLOCK_SIZE;
283 *u = SHA256_DIGEST_SIZE;
284 break;
285#endif
286#ifdef WOLFSSL_SHA512
287 case SHA512:
288 *v = SHA512_BLOCK_SIZE;
289 *u = SHA512_DIGEST_SIZE;
290 break;
291#endif
292 default:
293 return BAD_FUNC_ARG;
294 }
295
296 return 0;
297}
298
299/* helper for PKCS12_PBKDF(), does hash operation */
300int DoPKCS12Hash(int hashType, byte* buffer, word32 totalLen,
301 byte* Ai, word32 u, int iterations)
302{
303 int i;
304 int ret = 0;
305
306 if (buffer == NULL || Ai == NULL)
307 return BAD_FUNC_ARG;
308
309 switch (hashType) {
310#ifndef NO_MD5
311 case MD5:
312 {
313 Md5 md5;
314 wc_InitMd5(&md5);
315 wc_Md5Update(&md5, buffer, totalLen);
316 wc_Md5Final(&md5, Ai);
317
318 for (i = 1; i < iterations; i++) {
319 wc_Md5Update(&md5, Ai, u);
320 wc_Md5Final(&md5, Ai);
321 }
322 }
323 break;
324#endif /* NO_MD5 */
325#ifndef NO_SHA
326 case SHA:
327 {
328 Sha sha;
329 ret = wc_InitSha(&sha);
330 if (ret != 0)
331 break;
332 wc_ShaUpdate(&sha, buffer, totalLen);
333 wc_ShaFinal(&sha, Ai);
334
335 for (i = 1; i < iterations; i++) {
336 wc_ShaUpdate(&sha, Ai, u);
337 wc_ShaFinal(&sha, Ai);
338 }
339 }
340 break;
341#endif /* NO_SHA */
342#ifndef NO_SHA256
343 case SHA256:
344 {
345 Sha256 sha256;
346 ret = wc_InitSha256(&sha256);
347 if (ret != 0)
348 break;
349
350 ret = wc_Sha256Update(&sha256, buffer, totalLen);
351 if (ret != 0)
352 break;
353
354 ret = wc_Sha256Final(&sha256, Ai);
355 if (ret != 0)
356 break;
357
358 for (i = 1; i < iterations; i++) {
359 ret = wc_Sha256Update(&sha256, Ai, u);
360 if (ret != 0)
361 break;
362
363 ret = wc_Sha256Final(&sha256, Ai);
364 if (ret != 0)
365 break;
366 }
367 }
368 break;
369#endif /* NO_SHA256 */
370#ifdef WOLFSSL_SHA512
371 case SHA512:
372 {
373 Sha512 sha512;
374 ret = wc_InitSha512(&sha512);
375 if (ret != 0)
376 break;
377
378 ret = wc_Sha512Update(&sha512, buffer, totalLen);
379 if (ret != 0)
380 break;
381
382 ret = wc_Sha512Final(&sha512, Ai);
383 if (ret != 0)
384 break;
385
386 for (i = 1; i < iterations; i++) {
387 ret = wc_Sha512Update(&sha512, Ai, u);
388 if (ret != 0)
389 break;
390
391 ret = wc_Sha512Final(&sha512, Ai);
392 if (ret != 0)
393 break;
394 }
395 }
396 break;
397#endif /* WOLFSSL_SHA512 */
398
399 default:
400 ret = BAD_FUNC_ARG;
401 break;
402 }
403
404 return ret;
405}
406
407int wc_PKCS12_PBKDF(byte* output, const byte* passwd, int passLen,const byte* salt,
408 int saltLen, int iterations, int kLen, int hashType, int id)
409{
410 /* all in bytes instead of bits */
411 word32 u, v, dLen, pLen, iLen, sLen, totalLen;
412 int dynamic = 0;
413 int ret = 0;
414 int i;
415 byte *D, *S, *P, *I;
416#ifdef WOLFSSL_SMALL_STACK
417 byte staticBuffer[1]; /* force dynamic usage */
418#else
419 byte staticBuffer[1024];
420#endif
421 byte* buffer = staticBuffer;
422
423#ifdef WOLFSSL_SMALL_STACK
424 byte* Ai;
425 byte* B;
426#else
427 byte Ai[PBKDF_DIGEST_SIZE];
428 byte B[PBKDF_DIGEST_SIZE];
429#endif
430
431 if (!iterations)
432 iterations = 1;
433
434 ret = GetPKCS12HashSizes(hashType, &v, &u);
435 if (ret < 0)
436 return BAD_FUNC_ARG;
437
438#ifdef WOLFSSL_SMALL_STACK
439 Ai = (byte*)XMALLOC(PBKDF_DIGEST_SIZE, NULL, DYNAMIC_TYPE_TMP_BUFFER);
440 if (Ai == NULL)
441 return MEMORY_E;
442
443 B = (byte*)XMALLOC(PBKDF_DIGEST_SIZE, NULL, DYNAMIC_TYPE_TMP_BUFFER);
444 if (B == NULL) {
445 XFREE(Ai, NULL, DYNAMIC_TYPE_TMP_BUFFER);
446 return MEMORY_E;
447 }
448#endif
449
450 XMEMSET(Ai, 0, PBKDF_DIGEST_SIZE);
451 XMEMSET(B, 0, PBKDF_DIGEST_SIZE);
452
453 dLen = v;
454 sLen = v * ((saltLen + v - 1) / v);
455 if (passLen)
456 pLen = v * ((passLen + v - 1) / v);
457 else
458 pLen = 0;
459 iLen = sLen + pLen;
460
461 totalLen = dLen + sLen + pLen;
462
463 if (totalLen > sizeof(staticBuffer)) {
464 buffer = (byte*)XMALLOC(totalLen, 0, DYNAMIC_TYPE_KEY);
465 if (buffer == NULL) {
466#ifdef WOLFSSL_SMALL_STACK
467 XFREE(Ai, NULL, DYNAMIC_TYPE_TMP_BUFFER);
468 XFREE(B, NULL, DYNAMIC_TYPE_TMP_BUFFER);
469#endif
470 return MEMORY_E;
471 }
472 dynamic = 1;
473 }
474
475 D = buffer;
476 S = D + dLen;
477 P = S + sLen;
478 I = S;
479
480 XMEMSET(D, id, dLen);
481
482 for (i = 0; i < (int)sLen; i++)
483 S[i] = salt[i % saltLen];
484 for (i = 0; i < (int)pLen; i++)
485 P[i] = passwd[i % passLen];
486
487 while (kLen > 0) {
488 word32 currentLen;
489 mp_int B1;
490
491 ret = DoPKCS12Hash(hashType, buffer, totalLen, Ai, u, iterations);
492 if (ret < 0)
493 break;
494
495 for (i = 0; i < (int)v; i++)
496 B[i] = Ai[i % u];
497
498 if (mp_init(&B1) != MP_OKAY)
499 ret = MP_INIT_E;
500 else if (mp_read_unsigned_bin(&B1, B, v) != MP_OKAY)
501 ret = MP_READ_E;
502 else if (mp_add_d(&B1, (mp_digit)1, &B1) != MP_OKAY)
503 ret = MP_ADD_E;
504
505 if (ret != 0) {
506 mp_clear(&B1);
507 break;
508 }
509
510 for (i = 0; i < (int)iLen; i += v) {
511 int outSz;
512 mp_int i1;
513 mp_int res;
514
515 if (mp_init_multi(&i1, &res, NULL, NULL, NULL, NULL) != MP_OKAY) {
516 ret = MP_INIT_E;
517 break;
518 }
519 if (mp_read_unsigned_bin(&i1, I + i, v) != MP_OKAY)
520 ret = MP_READ_E;
521 else if (mp_add(&i1, &B1, &res) != MP_OKAY)
522 ret = MP_ADD_E;
523 else if ( (outSz = mp_unsigned_bin_size(&res)) < 0)
524 ret = MP_TO_E;
525 else {
526 if (outSz > (int)v) {
527 /* take off MSB */
528 byte tmp[129];
529 ret = mp_to_unsigned_bin(&res, tmp);
530 XMEMCPY(I + i, tmp + 1, v);
531 }
532 else if (outSz < (int)v) {
533 XMEMSET(I + i, 0, v - outSz);
534 ret = mp_to_unsigned_bin(&res, I + i + v - outSz);
535 }
536 else
537 ret = mp_to_unsigned_bin(&res, I + i);
538 }
539
540 mp_clear(&i1);
541 mp_clear(&res);
542 if (ret < 0) break;
543 }
544
545 currentLen = min(kLen, (int)u);
546 XMEMCPY(output, Ai, currentLen);
547 output += currentLen;
548 kLen -= currentLen;
549 mp_clear(&B1);
550 }
551
552 if (dynamic) XFREE(buffer, 0, DYNAMIC_TYPE_KEY);
553
554#ifdef WOLFSSL_SMALL_STACK
555 XFREE(Ai, NULL, DYNAMIC_TYPE_TMP_BUFFER);
556 XFREE(B, NULL, DYNAMIC_TYPE_TMP_BUFFER);
557#endif
558
559 return ret;
560}
561
562#undef PBKDF_DIGEST_SIZE
563
564#endif /* NO_PWDBASED */
565
Note: See TracBrowser for help on using the repository browser.