1 /* kdf.c
2  *
3  * Copyright (C) 2006-2021 wolfSSL Inc.
4  *
5  * This file is part of wolfSSL.
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-1335, USA
20  */
21 
22 
23 #ifdef HAVE_CONFIG_H
24     #include <config.h>
25 #endif
26 
27 #include <wolfssl/wolfcrypt/wc_port.h>
28 #include <wolfssl/wolfcrypt/error-crypt.h>
29 #include <wolfssl/wolfcrypt/logging.h>
30 
31 #ifndef NO_KDF
32 
33 #if defined(HAVE_FIPS) && \
34     defined(HAVE_FIPS_VERSION) && (HAVE_FIPS_VERSION >= 5)
35 
36     /* set NO_WRAPPERS before headers, use direct internal f()s not wrappers */
37     #define FIPS_NO_WRAPPERS
38 
39     #ifdef USE_WINDOWS_API
40         #pragma code_seg(".fipsA$m")
41         #pragma const_seg(".fipsB$m")
42     #endif
43 #endif
44 
45 
46 #ifdef NO_INLINE
47     #include <wolfssl/wolfcrypt/misc.h>
48 #else
49     #define WOLFSSL_MISC_INCLUDED
50     #include <wolfcrypt/src/misc.c>
51 #endif
52 
53 #include <wolfssl/wolfcrypt/hmac.h>
54 #include <wolfssl/wolfcrypt/kdf.h>
55 
56 
57 #ifdef WOLFSSL_HAVE_PRF
58 
59 #ifdef WOLFSSL_SHA512
60     #define P_HASH_MAX_SIZE WC_SHA512_DIGEST_SIZE
61 #elif defined(WOLFSSL_SHA384)
62     #define P_HASH_MAX_SIZE WC_SHA384_DIGEST_SIZE
63 #else
64     #define P_HASH_MAX_SIZE WC_SHA256_DIGEST_SIZE
65 #endif
66 
67 /* Pseudo Random Function for MD5, SHA-1, SHA-256, SHA-384, or SHA-512 */
68 int wc_PRF(byte* result, word32 resLen, const byte* secret,
69                   word32 secLen, const byte* seed, word32 seedLen, int hash,
70                   void* heap, int devId)
71 {
72     word32 len = P_HASH_MAX_SIZE;
73     word32 times;
74     word32 lastLen;
75     word32 lastTime;
76     word32 i;
77     word32 idx = 0;
78     int    ret = 0;
79 #ifdef WOLFSSL_SMALL_STACK
80     byte*  previous;
81     byte*  current;
82     Hmac*  hmac;
83 #else
84     byte   previous[P_HASH_MAX_SIZE];  /* max size */
85     byte   current[P_HASH_MAX_SIZE];   /* max size */
86     Hmac   hmac[1];
87 #endif
88 
89 #ifdef WOLFSSL_SMALL_STACK
90     previous = (byte*)XMALLOC(P_HASH_MAX_SIZE, heap, DYNAMIC_TYPE_DIGEST);
91     current  = (byte*)XMALLOC(P_HASH_MAX_SIZE, heap, DYNAMIC_TYPE_DIGEST);
92     hmac     = (Hmac*)XMALLOC(sizeof(Hmac),    heap, DYNAMIC_TYPE_HMAC);
93 
94     if (previous == NULL || current == NULL || hmac == NULL) {
95         if (previous) XFREE(previous, heap, DYNAMIC_TYPE_DIGEST);
96         if (current)  XFREE(current,  heap, DYNAMIC_TYPE_DIGEST);
97         if (hmac)     XFREE(hmac,     heap, DYNAMIC_TYPE_HMAC);
98 
99         return MEMORY_E;
100     }
101 #endif
102 
103     switch (hash) {
104     #ifndef NO_MD5
105         case md5_mac:
106             hash = WC_MD5;
107             len  = WC_MD5_DIGEST_SIZE;
108         break;
109     #endif
110 
111     #ifndef NO_SHA256
112         case sha256_mac:
113             hash = WC_SHA256;
114             len  = WC_SHA256_DIGEST_SIZE;
115         break;
116     #endif
117 
118     #ifdef WOLFSSL_SHA384
119         case sha384_mac:
120             hash = WC_SHA384;
121             len  = WC_SHA384_DIGEST_SIZE;
122         break;
123     #endif
124 
125     #ifdef WOLFSSL_SHA512
126         case sha512_mac:
127             hash = WC_SHA512;
128             len  = WC_SHA512_DIGEST_SIZE;
129         break;
130     #endif
131 
132     #ifndef NO_SHA
133         case sha_mac:
134             hash = WC_SHA;
135             len  = WC_SHA_DIGEST_SIZE;
136         break;
137     #endif
138         default:
139         #ifdef WOLFSSL_SMALL_STACK
140             if (previous) XFREE(previous, heap, DYNAMIC_TYPE_DIGEST);
141             if (current)  XFREE(current,  heap, DYNAMIC_TYPE_DIGEST);
142             if (hmac)     XFREE(hmac,     heap, DYNAMIC_TYPE_HMAC);
143         #endif
144             return HASH_TYPE_E;
145     }
146 
147     times   = resLen / len;
148     lastLen = resLen % len;
149 
150     if (lastLen)
151         times += 1;
152 
153     lastTime = times - 1;
154 
155     ret = wc_HmacInit(hmac, heap, devId);
156     if (ret == 0) {
157         ret = wc_HmacSetKey(hmac, hash, secret, secLen);
158         if (ret == 0)
159             ret = wc_HmacUpdate(hmac, seed, seedLen); /* A0 = seed */
160         if (ret == 0)
161             ret = wc_HmacFinal(hmac, previous);       /* A1 */
162         if (ret == 0) {
163             for (i = 0; i < times; i++) {
164                 ret = wc_HmacUpdate(hmac, previous, len);
165                 if (ret != 0)
166                     break;
167                 ret = wc_HmacUpdate(hmac, seed, seedLen);
168                 if (ret != 0)
169                     break;
170                 ret = wc_HmacFinal(hmac, current);
171                 if (ret != 0)
172                     break;
173 
174                 if ((i == lastTime) && lastLen)
175                     XMEMCPY(&result[idx], current,
176                                              min(lastLen, P_HASH_MAX_SIZE));
177                 else {
178                     XMEMCPY(&result[idx], current, len);
179                     idx += len;
180                     ret = wc_HmacUpdate(hmac, previous, len);
181                     if (ret != 0)
182                         break;
183                     ret = wc_HmacFinal(hmac, previous);
184                     if (ret != 0)
185                         break;
186                 }
187             }
188         }
cstring_to_text(const char * s)189         wc_HmacFree(hmac);
190     }
191 
192     ForceZero(previous,  P_HASH_MAX_SIZE);
193     ForceZero(current,   P_HASH_MAX_SIZE);
194     ForceZero(hmac,      sizeof(Hmac));
195 
196 #ifdef WOLFSSL_SMALL_STACK
197     XFREE(previous, heap, DYNAMIC_TYPE_DIGEST);
198     XFREE(current,  heap, DYNAMIC_TYPE_DIGEST);
199     XFREE(hmac,     heap, DYNAMIC_TYPE_HMAC);
200 #endif
cstring_to_text_with_len(const char * s,int len)201 
202     return ret;
203 }
204 #undef P_HASH_MAX_SIZE
205 
206 /* compute PRF (pseudo random function) using SHA1 and MD5 for TLSv1 */
207 int wc_PRF_TLSv1(byte* digest, word32 digLen, const byte* secret,
208            word32 secLen, const byte* label, word32 labLen,
209            const byte* seed, word32 seedLen, void* heap, int devId)
210 {
211     int    ret  = 0;
212     word32 half = (secLen + 1) / 2;
213 
214 #ifdef WOLFSSL_SMALL_STACK
215     byte* md5_half;
216     byte* sha_half;
217     byte* md5_result;
218     byte* sha_result;
219 #else
220     byte  md5_half[MAX_PRF_HALF];     /* half is real size */
221     byte  sha_half[MAX_PRF_HALF];     /* half is real size */
text_to_cstring(const text * t)222     byte  md5_result[MAX_PRF_DIG];    /* digLen is real size */
223     byte  sha_result[MAX_PRF_DIG];    /* digLen is real size */
224 #endif
225 #if defined(WOLFSSL_ASYNC_CRYPT) && !defined(WC_ASYNC_NO_HASH)
226     WC_DECLARE_VAR(labelSeed, byte, MAX_PRF_LABSEED, heap);
227     if (labelSeed == NULL)
228         return MEMORY_E;
229 #else
230     byte labelSeed[MAX_PRF_LABSEED];
231 #endif
232 
233     if (half > MAX_PRF_HALF ||
234         labLen + seedLen > MAX_PRF_LABSEED ||
235         digLen > MAX_PRF_DIG)
236     {
237     #if defined(WOLFSSL_ASYNC_CRYPT) && !defined(WC_ASYNC_NO_HASH)
238         WC_FREE_VAR(labelSeed, heap);
239     #endif
240         return BUFFER_E;
241     }
242 
243 #ifdef WOLFSSL_SMALL_STACK
244     md5_half   = (byte*)XMALLOC(MAX_PRF_HALF,    heap, DYNAMIC_TYPE_DIGEST);
245     sha_half   = (byte*)XMALLOC(MAX_PRF_HALF,    heap, DYNAMIC_TYPE_DIGEST);
246     md5_result = (byte*)XMALLOC(MAX_PRF_DIG,     heap, DYNAMIC_TYPE_DIGEST);
247     sha_result = (byte*)XMALLOC(MAX_PRF_DIG,     heap, DYNAMIC_TYPE_DIGEST);
248 
249     if (md5_half == NULL || sha_half == NULL || md5_result == NULL ||
250                                                            sha_result == NULL) {
251         if (md5_half)   XFREE(md5_half,   heap, DYNAMIC_TYPE_DIGEST);
252         if (sha_half)   XFREE(sha_half,   heap, DYNAMIC_TYPE_DIGEST);
text_to_cstring_buffer(const text * src,char * dst,size_t dst_len)253         if (md5_result) XFREE(md5_result, heap, DYNAMIC_TYPE_DIGEST);
254         if (sha_result) XFREE(sha_result, heap, DYNAMIC_TYPE_DIGEST);
255     #if defined(WOLFSSL_ASYNC_CRYPT) && !defined(WC_ASYNC_NO_HASH)
256         WC_FREE_VAR(labelSeed, heap);
257     #endif
258 
259         return MEMORY_E;
260     }
261 #endif
262 
263     XMEMSET(md5_result, 0, digLen);
264     XMEMSET(sha_result, 0, digLen);
265 
266     XMEMCPY(md5_half, secret, half);
267     XMEMCPY(sha_half, secret + half - secLen % 2, half);
268 
269     XMEMCPY(labelSeed, label, labLen);
270     XMEMCPY(labelSeed + labLen, seed, seedLen);
271 
272     if ((ret = wc_PRF(md5_result, digLen, md5_half, half, labelSeed,
273                                 labLen + seedLen, md5_mac, heap, devId)) == 0) {
274         if ((ret = wc_PRF(sha_result, digLen, sha_half, half, labelSeed,
275                                 labLen + seedLen, sha_mac, heap, devId)) == 0) {
276             /* calculate XOR for TLSv1 PRF */
277             XMEMCPY(digest, md5_result, digLen);
278             xorbuf(digest, sha_result, digLen);
279         }
280     }
281 
282 #ifdef WOLFSSL_SMALL_STACK
283     XFREE(md5_half,   heap, DYNAMIC_TYPE_DIGEST);
284     XFREE(sha_half,   heap, DYNAMIC_TYPE_DIGEST);
285     XFREE(md5_result, heap, DYNAMIC_TYPE_DIGEST);
286     XFREE(sha_result, heap, DYNAMIC_TYPE_DIGEST);
287 #endif
288 
289 #if defined(WOLFSSL_ASYNC_CRYPT) && !defined(WC_ASYNC_NO_HASH)
290     WC_FREE_VAR(labelSeed, heap);
291 #endif
292 
293     return ret;
294 }
byteain(PG_FUNCTION_ARGS)295 
296 /* Wrapper for TLS 1.2 and TLSv1 cases to calculate PRF */
297 /* In TLS 1.2 case call straight thru to wc_PRF */
298 int wc_PRF_TLS(byte* digest, word32 digLen, const byte* secret, word32 secLen,
299             const byte* label, word32 labLen, const byte* seed, word32 seedLen,
300             int useAtLeastSha256, int hash_type, void* heap, int devId)
301 {
302     int ret = 0;
303 
304     if (useAtLeastSha256) {
305     #if defined(WOLFSSL_ASYNC_CRYPT) && !defined(WC_ASYNC_NO_HASH)
306         WC_DECLARE_VAR(labelSeed, byte, MAX_PRF_LABSEED, heap);
307         if (labelSeed == NULL)
308             return MEMORY_E;
309     #else
310         byte labelSeed[MAX_PRF_LABSEED];
311     #endif
312 
313         if (labLen + seedLen > MAX_PRF_LABSEED)
314             return BUFFER_E;
315 
316         XMEMCPY(labelSeed, label, labLen);
317         XMEMCPY(labelSeed + labLen, seed, seedLen);
318 
319         /* If a cipher suite wants an algorithm better than sha256, it
320          * should use better. */
321         if (hash_type < sha256_mac || hash_type == blake2b_mac)
322             hash_type = sha256_mac;
323         /* compute PRF for MD5, SHA-1, SHA-256, or SHA-384 for TLSv1.2 PRF */
324         ret = wc_PRF(digest, digLen, secret, secLen, labelSeed,
325                      labLen + seedLen, hash_type, heap, devId);
326 
327     #if defined(WOLFSSL_ASYNC_CRYPT) && !defined(WC_ASYNC_NO_HASH)
328         WC_FREE_VAR(labelSeed, heap);
329     #endif
330     }
331     else {
332 #ifndef NO_OLD_TLS
333         /* compute TLSv1 PRF (pseudo random function using HMAC) */
334         ret = wc_PRF_TLSv1(digest, digLen, secret, secLen, label, labLen, seed,
335                           seedLen, heap, devId);
336 #else
337         ret = BAD_FUNC_ARG;
338 #endif
339     }
340 
341 
342     return ret;
343 }
344 #endif /* WOLFSSL_HAVE_PRF */
345 
346 
347 #if defined(HAVE_HKDF)
348 
349     /* Extract data using HMAC, salt and input.
350      * RFC 5869 - HMAC-based Extract-and-Expand Key Derivation Function (HKDF)
351      *
352      * prk      The generated pseudorandom key.
353      * salt     The salt.
354      * saltLen  The length of the salt.
355      * ikm      The input keying material.
356      * ikmLen   The length of the input keying material.
357      * digest   The type of digest to use.
358      * returns 0 on success, otherwise failure.
359      */
360     int wc_Tls13_HKDF_Extract(byte* prk, const byte* salt, int saltLen,
361                                  byte* ikm, int ikmLen, int digest)
362     {
363         int ret;
364         int len = 0;
365 
366         switch (digest) {
367             #ifndef NO_SHA256
368             case WC_SHA256:
369                 len = WC_SHA256_DIGEST_SIZE;
370                 break;
371             #endif
372 
373             #ifdef WOLFSSL_SHA384
374             case WC_SHA384:
375                 len = WC_SHA384_DIGEST_SIZE;
376                 break;
377             #endif
378 
379             #ifdef WOLFSSL_TLS13_SHA512
380             case WC_SHA512:
381                 len = WC_SHA512_DIGEST_SIZE;
382                 break;
383             #endif
384             default:
385                 return BAD_FUNC_ARG;
386         }
387 
388         /* When length is 0 then use zeroed data of digest length. */
389         if (ikmLen == 0) {
390             ikmLen = len;
byteaout(PG_FUNCTION_ARGS)391             XMEMSET(ikm, 0, len);
392         }
393 
394 #ifdef WOLFSSL_DEBUG_TLS
395         WOLFSSL_MSG("  Salt");
396         WOLFSSL_BUFFER(salt, saltLen);
397         WOLFSSL_MSG("  IKM");
398         WOLFSSL_BUFFER(ikm, ikmLen);
399 #endif
400 
401         ret = wc_HKDF_Extract(digest, salt, saltLen, ikm, ikmLen, prk);
402 
403 #ifdef WOLFSSL_DEBUG_TLS
404         WOLFSSL_MSG("  PRK");
405         WOLFSSL_BUFFER(prk, len);
406 #endif
407 
408         return ret;
409     }
410 
411     /* Expand data using HMAC, salt and label and info.
412      * TLS v1.3 defines this function.
413      *
414      * okm          The generated pseudorandom key - output key material.
415      * okmLen       The length of generated pseudorandom key -
416      *              output key material.
417      * prk          The salt - pseudo-random key.
418      * prkLen       The length of the salt - pseudo-random key.
419      * protocol     The TLS protocol label.
420      * protocolLen  The length of the TLS protocol label.
421      * info         The information to expand.
422      * infoLen      The length of the information.
423      * digest       The type of digest to use.
424      * returns 0 on success, otherwise failure.
425      */
426     int wc_Tls13_HKDF_Expand_Label(byte* okm, word32 okmLen,
427                                  const byte* prk, word32 prkLen,
428                                  const byte* protocol, word32 protocolLen,
429                                  const byte* label, word32 labelLen,
430                                  const byte* info, word32 infoLen,
431                                  int digest)
432     {
433         int    ret = 0;
434         int    idx = 0;
435         byte   data[MAX_TLS13_HKDF_LABEL_SZ];
436 
437         /* Output length. */
438         data[idx++] = (byte)(okmLen >> 8);
439         data[idx++] = (byte)okmLen;
440         /* Length of protocol | label. */
441         data[idx++] = (byte)(protocolLen + labelLen);
442         /* Protocol */
443         XMEMCPY(&data[idx], protocol, protocolLen);
444         idx += protocolLen;
445         /* Label */
446         XMEMCPY(&data[idx], label, labelLen);
447         idx += labelLen;
448         /* Length of hash of messages */
449         data[idx++] = (byte)infoLen;
450         /* Hash of messages */
451         XMEMCPY(&data[idx], info, infoLen);
452         idx += infoLen;
453 
454 #ifdef WOLFSSL_DEBUG_TLS
455         WOLFSSL_MSG("  PRK");
456         WOLFSSL_BUFFER(prk, prkLen);
457         WOLFSSL_MSG("  Info");
458         WOLFSSL_BUFFER(data, idx);
459 #endif
460 
461         ret = wc_HKDF_Expand(digest, prk, prkLen, data, idx, okm, okmLen);
462 
463 #ifdef WOLFSSL_DEBUG_TLS
464         WOLFSSL_MSG("  OKM");
465         WOLFSSL_BUFFER(okm, okmLen);
466 #endif
467 
468         ForceZero(data, idx);
469 
470         return ret;
471     }
472 
473 #endif /* HAVE_HKDF */
bytearecv(PG_FUNCTION_ARGS)474 
475 
476 #ifdef WOLFSSL_WOLFSSH
477 
478 /* hash union */
479 typedef union {
480 #ifndef NO_MD5
481     wc_Md5 md5;
482 #endif
483 #ifndef NO_SHA
484     wc_Sha sha;
485 #endif
486 #ifdef WOLFSSL_SHA224
487     wc_Sha224 sha224;
488 #endif
489 #ifndef NO_SHA256
490     wc_Sha256 sha256;
491 #endif
492 #ifdef WOLFSSL_SHA384
493     wc_Sha384 sha384;
494 #endif
495 #ifdef WOLFSSL_SHA512
496     wc_Sha512 sha512;
497 #endif
498 #ifdef WOLFSSL_SHA3
499     wc_Sha3 sha3;
500 #endif
501 } _hash;
502 
503 static
504 int _HashInit(byte hashId, _hash* hash)
505 {
506     int ret = BAD_FUNC_ARG;
507 
508     switch (hashId) {
509     #ifndef NO_SHA
510         case WC_SHA:
511             ret = wc_InitSha(&hash->sha);
512             break;
513     #endif /* !NO_SHA */
514 
515     #ifndef NO_SHA256
516         case WC_SHA256:
517             ret = wc_InitSha256(&hash->sha256);
518             break;
519     #endif /* !NO_SHA256 */
520 
521     #ifdef WOLFSSL_SHA384
522         case WC_SHA384:
523             ret = wc_InitSha384(&hash->sha384);
524             break;
525     #endif /* WOLFSSL_SHA384 */
526     #ifdef WOLFSSL_SHA512
527         case WC_SHA512:
528             ret = wc_InitSha512(&hash->sha512);
529             break;
530     #endif /* WOLFSSL_SHA512 */
531     }
532 
bytea_string_agg_finalfn(PG_FUNCTION_ARGS)533     return ret;
534 }
535 
536 static
537 int _HashUpdate(byte hashId, _hash* hash,
538         const byte* data, word32 dataSz)
539 {
540     int ret = BAD_FUNC_ARG;
541 
542     switch (hashId) {
543     #ifndef NO_SHA
544         case WC_SHA:
545             ret = wc_ShaUpdate(&hash->sha, data, dataSz);
546             break;
547     #endif /* !NO_SHA */
548 
549     #ifndef NO_SHA256
550         case WC_SHA256:
551             ret = wc_Sha256Update(&hash->sha256, data, dataSz);
552             break;
553     #endif /* !NO_SHA256 */
554 
555     #ifdef WOLFSSL_SHA384
556         case WC_SHA384:
557             ret = wc_Sha384Update(&hash->sha384, data, dataSz);
558             break;
textin(PG_FUNCTION_ARGS)559     #endif /* WOLFSSL_SHA384 */
560     #ifdef WOLFSSL_SHA512
561         case WC_SHA512:
562             ret = wc_Sha512Update(&hash->sha512, data, dataSz);
563             break;
564     #endif /* WOLFSSL_SHA512 */
565     }
566 
567     return ret;
568 }
569 
textout(PG_FUNCTION_ARGS)570 static
571 int _HashFinal(byte hashId, _hash* hash, byte* digest)
572 {
573     int ret = BAD_FUNC_ARG;
574 
575     switch (hashId) {
576     #ifndef NO_SHA
577         case WC_SHA:
578             ret = wc_ShaFinal(&hash->sha, digest);
579             break;
580     #endif /* !NO_SHA */
581 
582     #ifndef NO_SHA256
583         case WC_SHA256:
584             ret = wc_Sha256Final(&hash->sha256, digest);
585             break;
586     #endif /* !NO_SHA256 */
587 
588     #ifdef WOLFSSL_SHA384
589         case WC_SHA384:
590             ret = wc_Sha384Final(&hash->sha384, digest);
591             break;
592     #endif /* WOLFSSL_SHA384 */
593     #ifdef WOLFSSL_SHA512
594         case WC_SHA512:
595             ret = wc_Sha512Final(&hash->sha512, digest);
596             break;
597     #endif /* WOLFSSL_SHA512 */
598     }
599 
600     return ret;
601 }
602 
603 static
604 void _HashFree(byte hashId, _hash* hash)
605 {
606     switch (hashId) {
607     #ifndef NO_SHA
608         case WC_SHA:
609             wc_ShaFree(&hash->sha);
610             break;
611     #endif /* !NO_SHA */
612 
613     #ifndef NO_SHA256
unknownin(PG_FUNCTION_ARGS)614         case WC_SHA256:
615             wc_Sha256Free(&hash->sha256);
616             break;
617     #endif /* !NO_SHA256 */
618 
619     #ifdef WOLFSSL_SHA384
620         case WC_SHA384:
621             wc_Sha384Free(&hash->sha384);
622             break;
623     #endif /* WOLFSSL_SHA384 */
624     #ifdef WOLFSSL_SHA512
625         case WC_SHA512:
unknownout(PG_FUNCTION_ARGS)626             wc_Sha512Free(&hash->sha512);
627             break;
628     #endif /* WOLFSSL_SHA512 */
629     }
630 }
631 
632 
633 #define LENGTH_SZ 4
634 
635 int wc_SSH_KDF(byte hashId, byte keyId, byte* key, word32 keySz,
636         const byte* k, word32 kSz, const byte* h, word32 hSz,
637         const byte* sessionId, word32 sessionIdSz)
unknownrecv(PG_FUNCTION_ARGS)638 {
639     word32 blocks, remainder;
640     _hash hash;
641     enum wc_HashType enmhashId = (enum wc_HashType)hashId;
642     byte kPad = 0;
643     byte pad = 0;
644     byte kSzFlat[LENGTH_SZ];
645     int digestSz;
646     int ret;
647 
648     if (key == NULL || keySz == 0 ||
649         k == NULL || kSz == 0 ||
650         h == NULL || hSz == 0 ||
651         sessionId == NULL || sessionIdSz == 0) {
652 
653         return BAD_FUNC_ARG;
654     }
655 
656     digestSz = wc_HmacSizeByType(enmhashId);
657     if (digestSz < 0) {
658         return BAD_FUNC_ARG;
659     }
660 
661     if (k[0] & 0x80) kPad = 1;
662     c32toa(kSz + kPad, kSzFlat);
663 
664     blocks = keySz / digestSz;
665     remainder = keySz % digestSz;
666 
667     ret = _HashInit(enmhashId, &hash);
668     if (ret == 0)
669         ret = _HashUpdate(enmhashId, &hash, kSzFlat, LENGTH_SZ);
670     if (ret == 0 && kPad)
671         ret = _HashUpdate(enmhashId, &hash, &pad, 1);
672     if (ret == 0)
673         ret = _HashUpdate(enmhashId, &hash, k, kSz);
674     if (ret == 0)
675         ret = _HashUpdate(enmhashId, &hash, h, hSz);
676     if (ret == 0)
677         ret = _HashUpdate(enmhashId, &hash, &keyId, sizeof(keyId));
678     if (ret == 0)
679         ret = _HashUpdate(enmhashId, &hash, sessionId, sessionIdSz);
680 
681     if (ret == 0) {
682         if (blocks == 0) {
683             if (remainder > 0) {
684                 byte lastBlock[WC_MAX_DIGEST_SIZE];
685                 ret = _HashFinal(enmhashId, &hash, lastBlock);
686                 if (ret == 0)
687                     XMEMCPY(key, lastBlock, remainder);
688             }
689         }
690         else {
691             word32 runningKeySz, curBlock;
692 
693             runningKeySz = digestSz;
694             ret = _HashFinal(enmhashId, &hash, key);
695 
696             for (curBlock = 1; curBlock < blocks; curBlock++) {
697                 ret = _HashInit(enmhashId, &hash);
698                 if (ret != 0) break;
699                 ret = _HashUpdate(enmhashId, &hash, kSzFlat, LENGTH_SZ);
700                 if (ret != 0) break;
701                 if (kPad)
702                     ret = _HashUpdate(enmhashId, &hash, &pad, 1);
703                 if (ret != 0) break;
704                 ret = _HashUpdate(enmhashId, &hash, k, kSz);
705                 if (ret != 0) break;
706                 ret = _HashUpdate(enmhashId, &hash, h, hSz);
707                 if (ret != 0) break;
708                 ret = _HashUpdate(enmhashId, &hash, key, runningKeySz);
709                 if (ret != 0) break;
710                 ret = _HashFinal(enmhashId, &hash, key + runningKeySz);
711                 if (ret != 0) break;
712                 runningKeySz += digestSz;
713             }
714 
715             if (remainder > 0) {
716                 byte lastBlock[WC_MAX_DIGEST_SIZE];
717                 if (ret == 0)
718                     ret = _HashInit(enmhashId, &hash);
719                 if (ret == 0)
720                     ret = _HashUpdate(enmhashId, &hash, kSzFlat, LENGTH_SZ);
721                 if (ret == 0 && kPad)
722                     ret = _HashUpdate(enmhashId, &hash, &pad, 1);
723                 if (ret == 0)
724                     ret = _HashUpdate(enmhashId, &hash, k, kSz);
725                 if (ret == 0)
726                     ret = _HashUpdate(enmhashId, &hash, h, hSz);
727                 if (ret == 0)
728                     ret = _HashUpdate(enmhashId, &hash, key, runningKeySz);
729                 if (ret == 0)
730                     ret = _HashFinal(enmhashId, &hash, lastBlock);
731                 if (ret == 0)
732                     XMEMCPY(key + runningKeySz, lastBlock, remainder);
733             }
734         }
735     }
736 
737     _HashFree(enmhashId, &hash);
738 
739     return ret;
740 }
741 
742 #endif /* WOLFSSL_WOLFSSH */
743 
744 #endif /* NO_KDF */
text_catenate(text * t1,text * t2)745