source: UsbWattMeter/trunk/wolfssl-3.7.0/wolfcrypt/src/hmac.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: 21.1 KB
Line 
1/* hmac.h
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_HMAC
29
30#include <wolfssl/wolfcrypt/hmac.h>
31
32#ifdef HAVE_FIPS
33/* does init */
34int wc_HmacSetKey(Hmac* hmac, int type, const byte* key, word32 keySz)
35{
36 return HmacSetKey_fips(hmac, type, key, keySz);
37}
38
39
40int wc_HmacUpdate(Hmac* hmac, const byte* in, word32 sz)
41{
42 return HmacUpdate_fips(hmac, in, sz);
43}
44
45
46int wc_HmacFinal(Hmac* hmac, byte* out)
47{
48 return HmacFinal_fips(hmac, out);
49}
50
51
52#ifdef HAVE_CAVIUM
53 int wc_HmacInitCavium(Hmac* hmac, int i)
54 {
55 return HmacInitCavium(hmac, i);
56 }
57
58
59 void wc_HmacFreeCavium(Hmac* hmac)
60 {
61 HmacFreeCavium(hmac);
62 }
63#endif
64
65int wolfSSL_GetHmacMaxSize(void)
66{
67 return CyaSSL_GetHmacMaxSize();
68}
69
70#ifdef HAVE_HKDF
71
72int wc_HKDF(int type, const byte* inKey, word32 inKeySz,
73 const byte* salt, word32 saltSz,
74 const byte* info, word32 infoSz,
75 byte* out, word32 outSz)
76{
77 return HKDF(type, inKey, inKeySz, salt, saltSz, info, infoSz, out, outSz);
78}
79
80
81#endif /* HAVE_HKDF */
82#else /* else build without fips */
83#ifdef WOLFSSL_PIC32MZ_HASH
84
85#define wc_InitMd5 wc_InitMd5_sw
86#define wc_Md5Update wc_Md5Update_sw
87#define wc_Md5Final wc_Md5Final_sw
88
89#define wc_InitSha wc_InitSha_sw
90#define wc_ShaUpdate wc_ShaUpdate_sw
91#define wc_ShaFinal wc_ShaFinal_sw
92
93#define wc_InitSha256 wc_InitSha256_sw
94#define wc_Sha256Update wc_Sha256Update_sw
95#define wc_Sha256Final wc_Sha256Final_sw
96
97#endif
98
99#ifdef HAVE_FIPS
100 /* set NO_WRAPPERS before headers, use direct internal f()s not wrappers */
101 #define FIPS_NO_WRAPPERS
102#endif
103
104#include <wolfssl/wolfcrypt/error-crypt.h>
105
106
107#ifdef HAVE_CAVIUM
108 static void HmacCaviumFinal(Hmac* hmac, byte* hash);
109 static void HmacCaviumUpdate(Hmac* hmac, const byte* msg, word32 length);
110 static void HmacCaviumSetKey(Hmac* hmac, int type, const byte* key,
111 word32 length);
112#endif
113
114static int InitHmac(Hmac* hmac, int type)
115{
116 int ret = 0;
117
118 hmac->innerHashKeyed = 0;
119 hmac->macType = (byte)type;
120
121 if (!(type == MD5 || type == SHA || type == SHA256 || type == SHA384
122 || type == SHA512 || type == BLAKE2B_ID))
123 return BAD_FUNC_ARG;
124
125 switch (type) {
126 #ifndef NO_MD5
127 case MD5:
128 wc_InitMd5(&hmac->hash.md5);
129 break;
130 #endif
131
132 #ifndef NO_SHA
133 case SHA:
134 ret = wc_InitSha(&hmac->hash.sha);
135 break;
136 #endif
137
138 #ifndef NO_SHA256
139 case SHA256:
140 ret = wc_InitSha256(&hmac->hash.sha256);
141 break;
142 #endif
143
144 #ifdef WOLFSSL_SHA384
145 case SHA384:
146 ret = wc_InitSha384(&hmac->hash.sha384);
147 break;
148 #endif
149
150 #ifdef WOLFSSL_SHA512
151 case SHA512:
152 ret = wc_InitSha512(&hmac->hash.sha512);
153 break;
154 #endif
155
156 #ifdef HAVE_BLAKE2
157 case BLAKE2B_ID:
158 ret = wc_InitBlake2b(&hmac->hash.blake2b, BLAKE2B_256);
159 break;
160 #endif
161
162 default:
163 return BAD_FUNC_ARG;
164 }
165
166 return ret;
167}
168
169
170int wc_HmacSetKey(Hmac* hmac, int type, const byte* key, word32 length)
171{
172 byte* ip = (byte*) hmac->ipad;
173 byte* op = (byte*) hmac->opad;
174 word32 i, hmac_block_size = 0;
175 int ret;
176
177#ifdef HAVE_CAVIUM
178 if (hmac->magic == WOLFSSL_HMAC_CAVIUM_MAGIC)
179 return HmacCaviumSetKey(hmac, type, key, length);
180#endif
181
182 ret = InitHmac(hmac, type);
183 if (ret != 0)
184 return ret;
185
186#ifdef HAVE_FIPS
187 if (length < HMAC_FIPS_MIN_KEY)
188 return HMAC_MIN_KEYLEN_E;
189#endif
190
191 switch (hmac->macType) {
192 #ifndef NO_MD5
193 case MD5:
194 {
195 hmac_block_size = MD5_BLOCK_SIZE;
196 if (length <= MD5_BLOCK_SIZE) {
197 XMEMCPY(ip, key, length);
198 }
199 else {
200 wc_Md5Update(&hmac->hash.md5, key, length);
201 wc_Md5Final(&hmac->hash.md5, ip);
202 length = MD5_DIGEST_SIZE;
203 }
204 }
205 break;
206 #endif
207
208 #ifndef NO_SHA
209 case SHA:
210 {
211 hmac_block_size = SHA_BLOCK_SIZE;
212 if (length <= SHA_BLOCK_SIZE) {
213 XMEMCPY(ip, key, length);
214 }
215 else {
216 wc_ShaUpdate(&hmac->hash.sha, key, length);
217 wc_ShaFinal(&hmac->hash.sha, ip);
218 length = SHA_DIGEST_SIZE;
219 }
220 }
221 break;
222 #endif
223
224 #ifndef NO_SHA256
225 case SHA256:
226 {
227 hmac_block_size = SHA256_BLOCK_SIZE;
228 if (length <= SHA256_BLOCK_SIZE) {
229 XMEMCPY(ip, key, length);
230 }
231 else {
232 ret = wc_Sha256Update(&hmac->hash.sha256, key, length);
233 if (ret != 0)
234 return ret;
235
236 ret = wc_Sha256Final(&hmac->hash.sha256, ip);
237 if (ret != 0)
238 return ret;
239
240 length = SHA256_DIGEST_SIZE;
241 }
242 }
243 break;
244 #endif
245
246 #ifdef WOLFSSL_SHA384
247 case SHA384:
248 {
249 hmac_block_size = SHA384_BLOCK_SIZE;
250 if (length <= SHA384_BLOCK_SIZE) {
251 XMEMCPY(ip, key, length);
252 }
253 else {
254 ret = wc_Sha384Update(&hmac->hash.sha384, key, length);
255 if (ret != 0)
256 return ret;
257
258 ret = wc_Sha384Final(&hmac->hash.sha384, ip);
259 if (ret != 0)
260 return ret;
261
262 length = SHA384_DIGEST_SIZE;
263 }
264 }
265 break;
266 #endif
267
268 #ifdef WOLFSSL_SHA512
269 case SHA512:
270 {
271 hmac_block_size = SHA512_BLOCK_SIZE;
272 if (length <= SHA512_BLOCK_SIZE) {
273 XMEMCPY(ip, key, length);
274 }
275 else {
276 ret = wc_Sha512Update(&hmac->hash.sha512, key, length);
277 if (ret != 0)
278 return ret;
279
280 ret = wc_Sha512Final(&hmac->hash.sha512, ip);
281 if (ret != 0)
282 return ret;
283
284 length = SHA512_DIGEST_SIZE;
285 }
286 }
287 break;
288 #endif
289
290 #ifdef HAVE_BLAKE2
291 case BLAKE2B_ID:
292 {
293 hmac_block_size = BLAKE2B_BLOCKBYTES;
294 if (length <= BLAKE2B_BLOCKBYTES) {
295 XMEMCPY(ip, key, length);
296 }
297 else {
298 ret = wc_Blake2bUpdate(&hmac->hash.blake2b, key, length);
299 if (ret != 0)
300 return ret;
301
302 ret = wc_Blake2bFinal(&hmac->hash.blake2b, ip, BLAKE2B_256);
303 if (ret != 0)
304 return ret;
305
306 length = BLAKE2B_256;
307 }
308 }
309 break;
310 #endif
311
312 default:
313 return BAD_FUNC_ARG;
314 }
315 if (length < hmac_block_size)
316 XMEMSET(ip + length, 0, hmac_block_size - length);
317
318 for(i = 0; i < hmac_block_size; i++) {
319 op[i] = ip[i] ^ OPAD;
320 ip[i] ^= IPAD;
321 }
322 return 0;
323}
324
325
326static int HmacKeyInnerHash(Hmac* hmac)
327{
328 int ret = 0;
329
330 switch (hmac->macType) {
331 #ifndef NO_MD5
332 case MD5:
333 wc_Md5Update(&hmac->hash.md5, (byte*) hmac->ipad, MD5_BLOCK_SIZE);
334 break;
335 #endif
336
337 #ifndef NO_SHA
338 case SHA:
339 wc_ShaUpdate(&hmac->hash.sha, (byte*) hmac->ipad, SHA_BLOCK_SIZE);
340 break;
341 #endif
342
343 #ifndef NO_SHA256
344 case SHA256:
345 ret = wc_Sha256Update(&hmac->hash.sha256,
346 (byte*) hmac->ipad, SHA256_BLOCK_SIZE);
347 if (ret != 0)
348 return ret;
349 break;
350 #endif
351
352 #ifdef WOLFSSL_SHA384
353 case SHA384:
354 ret = wc_Sha384Update(&hmac->hash.sha384,
355 (byte*) hmac->ipad, SHA384_BLOCK_SIZE);
356 if (ret != 0)
357 return ret;
358 break;
359 #endif
360
361 #ifdef WOLFSSL_SHA512
362 case SHA512:
363 ret = wc_Sha512Update(&hmac->hash.sha512,
364 (byte*) hmac->ipad, SHA512_BLOCK_SIZE);
365 if (ret != 0)
366 return ret;
367 break;
368 #endif
369
370 #ifdef HAVE_BLAKE2
371 case BLAKE2B_ID:
372 ret = wc_Blake2bUpdate(&hmac->hash.blake2b,
373 (byte*) hmac->ipad,BLAKE2B_BLOCKBYTES);
374 if (ret != 0)
375 return ret;
376 break;
377 #endif
378
379 default:
380 break;
381 }
382
383 hmac->innerHashKeyed = 1;
384
385 return ret;
386}
387
388
389int wc_HmacUpdate(Hmac* hmac, const byte* msg, word32 length)
390{
391 int ret;
392
393#ifdef HAVE_CAVIUM
394 if (hmac->magic == WOLFSSL_HMAC_CAVIUM_MAGIC)
395 return HmacCaviumUpdate(hmac, msg, length);
396#endif
397
398 if (!hmac->innerHashKeyed) {
399 ret = HmacKeyInnerHash(hmac);
400 if (ret != 0)
401 return ret;
402 }
403
404 switch (hmac->macType) {
405 #ifndef NO_MD5
406 case MD5:
407 wc_Md5Update(&hmac->hash.md5, msg, length);
408 break;
409 #endif
410
411 #ifndef NO_SHA
412 case SHA:
413 wc_ShaUpdate(&hmac->hash.sha, msg, length);
414 break;
415 #endif
416
417 #ifndef NO_SHA256
418 case SHA256:
419 ret = wc_Sha256Update(&hmac->hash.sha256, msg, length);
420 if (ret != 0)
421 return ret;
422 break;
423 #endif
424
425 #ifdef WOLFSSL_SHA384
426 case SHA384:
427 ret = wc_Sha384Update(&hmac->hash.sha384, msg, length);
428 if (ret != 0)
429 return ret;
430 break;
431 #endif
432
433 #ifdef WOLFSSL_SHA512
434 case SHA512:
435 ret = wc_Sha512Update(&hmac->hash.sha512, msg, length);
436 if (ret != 0)
437 return ret;
438 break;
439 #endif
440
441 #ifdef HAVE_BLAKE2
442 case BLAKE2B_ID:
443 ret = wc_Blake2bUpdate(&hmac->hash.blake2b, msg, length);
444 if (ret != 0)
445 return ret;
446 break;
447 #endif
448
449 default:
450 break;
451 }
452
453 return 0;
454}
455
456
457int wc_HmacFinal(Hmac* hmac, byte* hash)
458{
459 int ret;
460
461#ifdef HAVE_CAVIUM
462 if (hmac->magic == WOLFSSL_HMAC_CAVIUM_MAGIC)
463 return HmacCaviumFinal(hmac, hash);
464#endif
465
466 if (!hmac->innerHashKeyed) {
467 ret = HmacKeyInnerHash(hmac);
468 if (ret != 0)
469 return ret;
470 }
471
472 switch (hmac->macType) {
473 #ifndef NO_MD5
474 case MD5:
475 {
476 wc_Md5Final(&hmac->hash.md5, (byte*) hmac->innerHash);
477
478 wc_Md5Update(&hmac->hash.md5, (byte*) hmac->opad, MD5_BLOCK_SIZE);
479 wc_Md5Update(&hmac->hash.md5,
480 (byte*) hmac->innerHash, MD5_DIGEST_SIZE);
481
482 wc_Md5Final(&hmac->hash.md5, hash);
483 }
484 break;
485 #endif
486
487 #ifndef NO_SHA
488 case SHA:
489 {
490 wc_ShaFinal(&hmac->hash.sha, (byte*) hmac->innerHash);
491
492 wc_ShaUpdate(&hmac->hash.sha, (byte*) hmac->opad, SHA_BLOCK_SIZE);
493 wc_ShaUpdate(&hmac->hash.sha,
494 (byte*) hmac->innerHash, SHA_DIGEST_SIZE);
495
496 wc_ShaFinal(&hmac->hash.sha, hash);
497 }
498 break;
499 #endif
500
501 #ifndef NO_SHA256
502 case SHA256:
503 {
504 ret = wc_Sha256Final(&hmac->hash.sha256, (byte*) hmac->innerHash);
505 if (ret != 0)
506 return ret;
507
508 ret = wc_Sha256Update(&hmac->hash.sha256,
509 (byte*) hmac->opad, SHA256_BLOCK_SIZE);
510 if (ret != 0)
511 return ret;
512
513 ret = wc_Sha256Update(&hmac->hash.sha256,
514 (byte*) hmac->innerHash, SHA256_DIGEST_SIZE);
515 if (ret != 0)
516 return ret;
517
518 ret = wc_Sha256Final(&hmac->hash.sha256, hash);
519 if (ret != 0)
520 return ret;
521 }
522 break;
523 #endif
524
525 #ifdef WOLFSSL_SHA384
526 case SHA384:
527 {
528 ret = wc_Sha384Final(&hmac->hash.sha384, (byte*) hmac->innerHash);
529 if (ret != 0)
530 return ret;
531
532 ret = wc_Sha384Update(&hmac->hash.sha384,
533 (byte*) hmac->opad, SHA384_BLOCK_SIZE);
534 if (ret != 0)
535 return ret;
536
537 ret = wc_Sha384Update(&hmac->hash.sha384,
538 (byte*) hmac->innerHash, SHA384_DIGEST_SIZE);
539 if (ret != 0)
540 return ret;
541
542 ret = wc_Sha384Final(&hmac->hash.sha384, hash);
543 if (ret != 0)
544 return ret;
545 }
546 break;
547 #endif
548
549 #ifdef WOLFSSL_SHA512
550 case SHA512:
551 {
552 ret = wc_Sha512Final(&hmac->hash.sha512, (byte*) hmac->innerHash);
553 if (ret != 0)
554 return ret;
555
556 ret = wc_Sha512Update(&hmac->hash.sha512,
557 (byte*) hmac->opad, SHA512_BLOCK_SIZE);
558 if (ret != 0)
559 return ret;
560
561 ret = wc_Sha512Update(&hmac->hash.sha512,
562 (byte*) hmac->innerHash, SHA512_DIGEST_SIZE);
563 if (ret != 0)
564 return ret;
565
566 ret = wc_Sha512Final(&hmac->hash.sha512, hash);
567 if (ret != 0)
568 return ret;
569 }
570 break;
571 #endif
572
573 #ifdef HAVE_BLAKE2
574 case BLAKE2B_ID:
575 {
576 ret = wc_Blake2bFinal(&hmac->hash.blake2b, (byte*) hmac->innerHash,
577 BLAKE2B_256);
578 if (ret != 0)
579 return ret;
580
581 ret = wc_Blake2bUpdate(&hmac->hash.blake2b,
582 (byte*) hmac->opad, BLAKE2B_BLOCKBYTES);
583 if (ret != 0)
584 return ret;
585
586 ret = wc_Blake2bUpdate(&hmac->hash.blake2b,
587 (byte*) hmac->innerHash, BLAKE2B_256);
588 if (ret != 0)
589 return ret;
590
591 ret = wc_Blake2bFinal(&hmac->hash.blake2b, hash, BLAKE2B_256);
592 if (ret != 0)
593 return ret;
594 }
595 break;
596 #endif
597
598 default:
599 break;
600 }
601
602 hmac->innerHashKeyed = 0;
603
604 return 0;
605}
606
607
608#ifdef HAVE_CAVIUM
609
610/* Initiliaze Hmac for use with Nitrox device */
611int wc_HmacInitCavium(Hmac* hmac, int devId)
612{
613 if (hmac == NULL)
614 return -1;
615
616 if (CspAllocContext(CONTEXT_SSL, &hmac->contextHandle, devId) != 0)
617 return -1;
618
619 hmac->keyLen = 0;
620 hmac->dataLen = 0;
621 hmac->type = 0;
622 hmac->devId = devId;
623 hmac->magic = WOLFSSL_HMAC_CAVIUM_MAGIC;
624 hmac->data = NULL; /* buffered input data */
625
626 hmac->innerHashKeyed = 0;
627
628 return 0;
629}
630
631
632/* Free Hmac from use with Nitrox device */
633void wc_HmacFreeCavium(Hmac* hmac)
634{
635 if (hmac == NULL)
636 return;
637
638 CspFreeContext(CONTEXT_SSL, hmac->contextHandle, hmac->devId);
639 hmac->magic = 0;
640 XFREE(hmac->data, NULL, DYNAMIC_TYPE_CAVIUM_TMP);
641 hmac->data = NULL;
642}
643
644
645static void HmacCaviumFinal(Hmac* hmac, byte* hash)
646{
647 word32 requestId;
648
649 if (CspHmac(CAVIUM_BLOCKING, hmac->type, NULL, hmac->keyLen,
650 (byte*)hmac->ipad, hmac->dataLen, hmac->data, hash, &requestId,
651 hmac->devId) != 0) {
652 WOLFSSL_MSG("Cavium Hmac failed");
653 }
654 hmac->innerHashKeyed = 0; /* tell update to start over if used again */
655}
656
657
658static void HmacCaviumUpdate(Hmac* hmac, const byte* msg, word32 length)
659{
660 word16 add = (word16)length;
661 word32 total;
662 byte* tmp;
663
664 if (length > WOLFSSL_MAX_16BIT) {
665 WOLFSSL_MSG("Too big msg for cavium hmac");
666 return;
667 }
668
669 if (hmac->innerHashKeyed == 0) { /* starting new */
670 hmac->dataLen = 0;
671 hmac->innerHashKeyed = 1;
672 }
673
674 total = add + hmac->dataLen;
675 if (total > WOLFSSL_MAX_16BIT) {
676 WOLFSSL_MSG("Too big msg for cavium hmac");
677 return;
678 }
679
680 tmp = XMALLOC(hmac->dataLen + add, NULL,DYNAMIC_TYPE_CAVIUM_TMP);
681 if (tmp == NULL) {
682 WOLFSSL_MSG("Out of memory for cavium update");
683 return;
684 }
685 if (hmac->dataLen)
686 XMEMCPY(tmp, hmac->data, hmac->dataLen);
687 XMEMCPY(tmp + hmac->dataLen, msg, add);
688
689 hmac->dataLen += add;
690 XFREE(hmac->data, NULL, DYNAMIC_TYPE_CAVIUM_TMP);
691 hmac->data = tmp;
692}
693
694
695static void HmacCaviumSetKey(Hmac* hmac, int type, const byte* key,
696 word32 length)
697{
698 hmac->macType = (byte)type;
699 if (type == MD5)
700 hmac->type = MD5_TYPE;
701 else if (type == SHA)
702 hmac->type = SHA1_TYPE;
703 else if (type == SHA256)
704 hmac->type = SHA256_TYPE;
705 else {
706 WOLFSSL_MSG("unsupported cavium hmac type");
707 }
708
709 hmac->innerHashKeyed = 0; /* should we key Startup flag */
710
711 hmac->keyLen = (word16)length;
712 /* store key in ipad */
713 XMEMCPY(hmac->ipad, key, length);
714}
715
716#endif /* HAVE_CAVIUM */
717
718int wolfSSL_GetHmacMaxSize(void)
719{
720 return MAX_DIGEST_SIZE;
721}
722
723#ifdef HAVE_HKDF
724
725#ifdef min
726#define WOLFSSL_HAVE_MIN
727#endif
728#ifndef WOLFSSL_HAVE_MIN
729#define WOLFSSL_HAVE_MIN
730
731 static INLINE word32 min(word32 a, word32 b)
732 {
733 return a > b ? b : a;
734 }
735
736#endif /* WOLFSSL_HAVE_MIN */
737
738
739static INLINE int GetHashSizeByType(int type)
740{
741 if (!(type == MD5 || type == SHA || type == SHA256 || type == SHA384
742 || type == SHA512 || type == BLAKE2B_ID))
743 return BAD_FUNC_ARG;
744
745 switch (type) {
746 #ifndef NO_MD5
747 case MD5:
748 return MD5_DIGEST_SIZE;
749 #endif
750
751 #ifndef NO_SHA
752 case SHA:
753 return SHA_DIGEST_SIZE;
754 #endif
755
756 #ifndef NO_SHA256
757 case SHA256:
758 return SHA256_DIGEST_SIZE;
759 #endif
760
761 #ifdef WOLFSSL_SHA384
762 case SHA384:
763 return SHA384_DIGEST_SIZE;
764 #endif
765
766 #ifdef WOLFSSL_SHA512
767 case SHA512:
768 return SHA512_DIGEST_SIZE;
769 #endif
770
771 #ifdef HAVE_BLAKE2
772 case BLAKE2B_ID:
773 return BLAKE2B_OUTBYTES;
774 #endif
775
776 default:
777 return BAD_FUNC_ARG;
778 }
779}
780
781
782/* HMAC-KDF with hash type, optional salt and info, return 0 on success */
783int wc_HKDF(int type, const byte* inKey, word32 inKeySz,
784 const byte* salt, word32 saltSz,
785 const byte* info, word32 infoSz,
786 byte* out, word32 outSz)
787{
788 Hmac myHmac;
789#ifdef WOLFSSL_SMALL_STACK
790 byte* tmp;
791 byte* prk;
792#else
793 byte tmp[MAX_DIGEST_SIZE]; /* localSalt helper and T */
794 byte prk[MAX_DIGEST_SIZE];
795#endif
796 const byte* localSalt; /* either points to user input or tmp */
797 int hashSz = GetHashSizeByType(type);
798 word32 outIdx = 0;
799 byte n = 0x1;
800 int ret;
801
802 if (hashSz < 0)
803 return BAD_FUNC_ARG;
804
805#ifdef WOLFSSL_SMALL_STACK
806 tmp = (byte*)XMALLOC(MAX_DIGEST_SIZE, NULL, DYNAMIC_TYPE_TMP_BUFFER);
807 if (tmp == NULL)
808 return MEMORY_E;
809
810 prk = (byte*)XMALLOC(MAX_DIGEST_SIZE, NULL, DYNAMIC_TYPE_TMP_BUFFER);
811 if (prk == NULL) {
812 XFREE(tmp, NULL, DYNAMIC_TYPE_TMP_BUFFER);
813 return MEMORY_E;
814 }
815#endif
816
817 localSalt = salt;
818 if (localSalt == NULL) {
819 XMEMSET(tmp, 0, hashSz);
820 localSalt = tmp;
821 saltSz = hashSz;
822 }
823
824 do {
825 ret = wc_HmacSetKey(&myHmac, type, localSalt, saltSz);
826 if (ret != 0)
827 break;
828 ret = wc_HmacUpdate(&myHmac, inKey, inKeySz);
829 if (ret != 0)
830 break;
831 ret = wc_HmacFinal(&myHmac, prk);
832 } while (0);
833
834 if (ret == 0) {
835 while (outIdx < outSz) {
836 int tmpSz = (n == 1) ? 0 : hashSz;
837 word32 left = outSz - outIdx;
838
839 ret = wc_HmacSetKey(&myHmac, type, prk, hashSz);
840 if (ret != 0)
841 break;
842 ret = wc_HmacUpdate(&myHmac, tmp, tmpSz);
843 if (ret != 0)
844 break;
845 ret = wc_HmacUpdate(&myHmac, info, infoSz);
846 if (ret != 0)
847 break;
848 ret = wc_HmacUpdate(&myHmac, &n, 1);
849 if (ret != 0)
850 break;
851 ret = wc_HmacFinal(&myHmac, tmp);
852 if (ret != 0)
853 break;
854
855 left = min(left, (word32)hashSz);
856 XMEMCPY(out+outIdx, tmp, left);
857
858 outIdx += hashSz;
859 n++;
860 }
861 }
862
863#ifdef WOLFSSL_SMALL_STACK
864 XFREE(tmp, NULL, DYNAMIC_TYPE_TMP_BUFFER);
865 XFREE(prk, NULL, DYNAMIC_TYPE_TMP_BUFFER);
866#endif
867
868 return ret;
869}
870
871#endif /* HAVE_HKDF */
872
873#endif /* HAVE_FIPS */
874#endif /* NO_HMAC */
Note: See TracBrowser for help on using the repository browser.