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