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