aboutsummaryrefslogtreecommitdiff
path: root/networking/tls.c
diff options
context:
space:
mode:
Diffstat (limited to 'networking/tls.c')
-rw-r--r--networking/tls.c281
1 files changed, 42 insertions, 239 deletions
diff --git a/networking/tls.c b/networking/tls.c
index 89726fee0..9c05364ea 100644
--- a/networking/tls.c
+++ b/networking/tls.c
@@ -22,19 +22,7 @@
22 22
23#include "tls.h" 23#include "tls.h"
24 24
25#if ENABLE_FEATURE_TLS_SCHANNEL || ENABLE_FEATURE_USE_CNG_API
26#include <windows.h>
27#endif
28
29#if !ENABLE_FEATURE_TLS_SCHANNEL 25#if !ENABLE_FEATURE_TLS_SCHANNEL
30#if ENABLE_FEATURE_USE_CNG_API
31# include <bcrypt.h>
32
33// these work on Windows >= 10
34# define BCRYPT_HMAC_SHA1_ALG_HANDLE ((BCRYPT_ALG_HANDLE) 0x000000a1)
35# define BCRYPT_HMAC_SHA256_ALG_HANDLE ((BCRYPT_ALG_HANDLE) 0x000000b1)
36#endif
37
38// Usually enabled. You can disable some of them to force only 26// Usually enabled. You can disable some of them to force only
39// specific ciphers to be advertized to server. 27// specific ciphers to be advertized to server.
40// (this would not exclude code to handle disabled ciphers, no code size win) 28// (this would not exclude code to handle disabled ciphers, no code size win)
@@ -201,8 +189,6 @@
201#define TLS_MAX_OUTBUF (1 << 14) 189#define TLS_MAX_OUTBUF (1 << 14)
202 190
203enum { 191enum {
204 SHA_INSIZE = 64,
205
206 AES128_KEYSIZE = 16, 192 AES128_KEYSIZE = 16,
207 AES256_KEYSIZE = 32, 193 AES256_KEYSIZE = 32,
208 194
@@ -348,34 +334,6 @@ void FAST_FUNC tls_get_random(void *buf, unsigned len)
348 xfunc_die(); 334 xfunc_die();
349} 335}
350 336
351static void xorbuf3(void *dst, const void *src1, const void *src2, unsigned count)
352{
353 uint8_t *d = dst;
354 const uint8_t *s1 = src1;
355 const uint8_t* s2 = src2;
356 while (count--)
357 *d++ = *s1++ ^ *s2++;
358}
359
360void FAST_FUNC xorbuf(void *dst, const void *src, unsigned count)
361{
362 xorbuf3(dst, dst, src, count);
363}
364
365void FAST_FUNC xorbuf_aligned_AES_BLOCK_SIZE(void *dst, const void *src)
366{
367 unsigned long *d = dst;
368 const unsigned long *s = src;
369 d[0] ^= s[0];
370#if ULONG_MAX <= 0xffffffffffffffff
371 d[1] ^= s[1];
372 #if ULONG_MAX == 0xffffffff
373 d[2] ^= s[2];
374 d[3] ^= s[3];
375 #endif
376#endif
377}
378
379#if !TLS_DEBUG_HASH 337#if !TLS_DEBUG_HASH
380# define hash_handshake(tls, fmt, buffer, len) \ 338# define hash_handshake(tls, fmt, buffer, len) \
381 hash_handshake(tls, buffer, len) 339 hash_handshake(tls, buffer, len)
@@ -406,191 +364,6 @@ static void hash_handshake(tls_state_t *tls, const char *fmt, const void *buffer
406# define TLS_MAC_SIZE(tls) (tls)->MAC_size 364# define TLS_MAC_SIZE(tls) (tls)->MAC_size
407#endif 365#endif
408 366
409// RFC 2104:
410// HMAC(key, text) based on a hash H (say, sha256) is:
411// ipad = [0x36 x INSIZE]
412// opad = [0x5c x INSIZE]
413// HMAC(key, text) = H((key XOR opad) + H((key XOR ipad) + text))
414//
415// H(key XOR opad) and H(key XOR ipad) can be precomputed
416// if we often need HMAC hmac with the same key.
417//
418// text is often given in disjoint pieces.
419#if !ENABLE_FEATURE_USE_CNG_API
420typedef struct hmac_precomputed {
421 md5sha_ctx_t hashed_key_xor_ipad;
422 md5sha_ctx_t hashed_key_xor_opad;
423} hmac_precomputed_t;
424
425typedef void md5sha_begin_func(md5sha_ctx_t *ctx) FAST_FUNC;
426
427#define sha1_begin_hmac sha1_begin
428#define sha256_begin_hmac sha256_begin
429#define hmac_uninit(...) ((void)0)
430
431#if !ENABLE_FEATURE_TLS_SHA1
432#define hmac_begin(pre,key,key_size,begin) \
433 hmac_begin(pre,key,key_size)
434#define begin sha256_begin
435#endif
436
437static void hmac_begin(hmac_precomputed_t *pre, uint8_t *key, unsigned key_size, md5sha_begin_func *begin)
438{
439 uint8_t key_xor_ipad[SHA_INSIZE];
440 uint8_t key_xor_opad[SHA_INSIZE];
441// uint8_t tempkey[SHA1_OUTSIZE < SHA256_OUTSIZE ? SHA256_OUTSIZE : SHA1_OUTSIZE];
442 unsigned i;
443
444 // "The authentication key can be of any length up to INSIZE, the
445 // block length of the hash function. Applications that use keys longer
446 // than INSIZE bytes will first hash the key using H and then use the
447 // resultant OUTSIZE byte string as the actual key to HMAC."
448 if (key_size > SHA_INSIZE) {
449 bb_simple_error_msg_and_die("HMAC key>64"); //does not happen (yet?)
450// md5sha_ctx_t ctx;
451// begin(&ctx);
452// md5sha_hash(&ctx, key, key_size);
453// key_size = sha_end(&ctx, tempkey);
454// //key = tempkey; - right? RIGHT? why does it work without this?
455// // because SHA_INSIZE is 64, but hmac() is always called with
456// // key_size = tls->MAC_size = SHA1/256_OUTSIZE (20 or 32),
457// // and prf_hmac_sha256() -> hmac_sha256() key sizes are:
458// // - RSA_PREMASTER_SIZE is 48
459// // - CURVE25519_KEYSIZE is 32
460// // - master_secret[] is 48
461 }
462
463 for (i = 0; i < key_size; i++) {
464 key_xor_ipad[i] = key[i] ^ 0x36;
465 key_xor_opad[i] = key[i] ^ 0x5c;
466 }
467 for (; i < SHA_INSIZE; i++) {
468 key_xor_ipad[i] = 0x36;
469 key_xor_opad[i] = 0x5c;
470 }
471
472 begin(&pre->hashed_key_xor_ipad);
473 begin(&pre->hashed_key_xor_opad);
474 md5sha_hash(&pre->hashed_key_xor_ipad, key_xor_ipad, SHA_INSIZE);
475 md5sha_hash(&pre->hashed_key_xor_opad, key_xor_opad, SHA_INSIZE);
476}
477#undef begin
478
479static unsigned hmac_sha_precomputed_v(
480 hmac_precomputed_t *pre,
481 uint8_t *out,
482 va_list va)
483{
484 uint8_t *text;
485 unsigned len;
486
487 /* pre->hashed_key_xor_ipad contains unclosed "H((key XOR ipad) +" state */
488 /* pre->hashed_key_xor_opad contains unclosed "H((key XOR opad) +" state */
489
490 /* calculate out = H((key XOR ipad) + text) */
491 while ((text = va_arg(va, uint8_t*)) != NULL) {
492 unsigned text_size = va_arg(va, unsigned);
493 md5sha_hash(&pre->hashed_key_xor_ipad, text, text_size);
494 }
495 len = sha_end(&pre->hashed_key_xor_ipad, out);
496
497 /* out = H((key XOR opad) + out) */
498 md5sha_hash(&pre->hashed_key_xor_opad, out, len);
499 return sha_end(&pre->hashed_key_xor_opad, out);
500}
501#else
502#define sha1_begin_hmac BCRYPT_HMAC_SHA1_ALG_HANDLE
503#define sha256_begin_hmac BCRYPT_HMAC_SHA256_ALG_HANDLE
504
505#if !ENABLE_FEATURE_TLS_SHA1
506#define hmac_begin(pre,key,key_size,begin) _hmac_begin(pre, key, key_size, sha256_begin_hmac)
507#else
508#define hmac_begin _hmac_begin
509#endif
510
511typedef struct bcrypt_hash_ctx_t hmac_precomputed_t;
512
513static void _hmac_begin(hmac_precomputed_t *pre, uint8_t *key, unsigned key_size, BCRYPT_ALG_HANDLE alg_handle) {
514 DWORD hash_object_length = 0;
515 ULONG _unused;
516 NTSTATUS status;
517
518 status = BCryptGetProperty(alg_handle, BCRYPT_OBJECT_LENGTH, (PUCHAR)&hash_object_length, sizeof(DWORD), &_unused, 0);
519 mingw_die_if_error(status, "BCryptGetProperty");
520 status = BCryptGetProperty(alg_handle, BCRYPT_HASH_LENGTH, (PUCHAR)&pre->output_size, sizeof(DWORD), &_unused, 0);
521 mingw_die_if_error(status, "BCryptGetProperty");
522
523
524 pre->hash_obj = xmalloc(hash_object_length);
525
526 status = BCryptCreateHash(alg_handle, &pre->handle, pre->hash_obj, hash_object_length, key, key_size, BCRYPT_HASH_REUSABLE_FLAG);
527 mingw_die_if_error(status, "BCryptCreateHash");
528}
529
530static unsigned hmac_sha_precomputed_v(
531 hmac_precomputed_t *pre,
532 uint8_t *out,
533 va_list va)
534{
535 uint8_t *text;
536 NTSTATUS status;
537
538 while ((text = va_arg(va, uint8_t*)) != NULL) {
539 unsigned text_size = va_arg(va, unsigned);
540 /*status = */ BCryptHashData(pre->handle, text, text_size, 0);
541 //mingw_die_if_error(status, "BCryptHashData");
542 }
543
544 status = BCryptFinishHash(pre->handle, out, pre->output_size, 0);
545 mingw_die_if_error(status, "BCryptFinishHash");
546
547 return pre->output_size;
548}
549
550static void hmac_uninit(hmac_precomputed_t *pre) {
551 BCryptDestroyHash(pre->handle);
552 free(pre->hash_obj);
553}
554
555#endif
556
557static unsigned hmac_sha_precomputed(hmac_precomputed_t *pre_init, uint8_t *out, ...)
558{
559 hmac_precomputed_t pre;
560 va_list va;
561 unsigned len;
562
563 va_start(va, out);
564 pre = *pre_init; /* struct copy */
565 len = hmac_sha_precomputed_v(&pre, out, va);
566 va_end(va);
567 return len;
568}
569
570#if !ENABLE_FEATURE_TLS_SHA1
571#define hmac(tls,out,key,key_size,...) \
572 hmac(out,key,key_size, __VA_ARGS__)
573#endif
574static unsigned hmac(tls_state_t *tls, uint8_t *out, uint8_t *key, unsigned key_size, ...)
575{
576 hmac_precomputed_t pre;
577 va_list va;
578 unsigned len;
579
580 va_start(va, key_size);
581
582 hmac_begin(&pre, key, key_size,
583 (ENABLE_FEATURE_TLS_SHA1 && tls->MAC_size == SHA1_OUTSIZE)
584 ? sha1_begin_hmac
585 : sha256_begin_hmac
586 );
587 len = hmac_sha_precomputed_v(&pre, out, va);
588
589 va_end(va);
590 hmac_uninit(&pre);
591 return len;
592}
593
594// RFC 5246: 367// RFC 5246:
595// 5. HMAC and the Pseudorandom Function 368// 5. HMAC and the Pseudorandom Function
596//... 369//...
@@ -635,7 +408,7 @@ static void prf_hmac_sha256(/*tls_state_t *tls,*/
635 const char *label, 408 const char *label,
636 uint8_t *seed, unsigned seed_size) 409 uint8_t *seed, unsigned seed_size)
637{ 410{
638 hmac_precomputed_t pre; 411 hmac_ctx_t ctx;
639 uint8_t a[TLS_MAX_MAC_SIZE]; 412 uint8_t a[TLS_MAX_MAC_SIZE];
640 uint8_t *out_p = outbuf; 413 uint8_t *out_p = outbuf;
641 unsigned label_size = strlen(label); 414 unsigned label_size = strlen(label);
@@ -645,29 +418,28 @@ static void prf_hmac_sha256(/*tls_state_t *tls,*/
645#define SEED label, label_size, seed, seed_size 418#define SEED label, label_size, seed, seed_size
646#define A a, MAC_size 419#define A a, MAC_size
647 420
648 hmac_begin(&pre, secret, secret_size, sha256_begin_hmac); 421 hmac_begin(&ctx, secret, secret_size, sha256_begin_hmac);
649 422
650 /* A(1) = HMAC_hash(secret, seed) */ 423 /* A(1) = HMAC_hash(secret, seed) */
651 hmac_sha_precomputed(&pre, a, SEED, NULL); 424 hmac_peek_hash(&ctx, a, SEED, NULL);
652 425
653 for (;;) { 426 for (;;) {
654 /* HMAC_hash(secret, A(1) + seed) */ 427 /* HMAC_hash(secret, A(1) + seed) */
655 if (outbuf_size <= MAC_size) { 428 if (outbuf_size <= MAC_size) {
656 /* Last, possibly incomplete, block */ 429 /* Last, possibly incomplete, block */
657 /* (use a[] as temp buffer) */ 430 /* (use a[] as temp buffer) */
658 hmac_sha_precomputed(&pre, a, A, SEED, NULL); 431 hmac_peek_hash(&ctx, a, A, SEED, NULL);
659 memcpy(out_p, a, outbuf_size); 432 memcpy(out_p, a, outbuf_size);
433 hmac_uninit(&ctx);
660 return; 434 return;
661 } 435 }
662 /* Not last block. Store directly to result buffer */ 436 /* Not last block. Store directly to result buffer */
663 hmac_sha_precomputed(&pre, out_p, A, SEED, NULL); 437 hmac_peek_hash(&ctx, out_p, A, SEED, NULL);
664 out_p += MAC_size; 438 out_p += MAC_size;
665 outbuf_size -= MAC_size; 439 outbuf_size -= MAC_size;
666 /* A(2) = HMAC_hash(secret, A(1)) */ 440 /* A(2) = HMAC_hash(secret, A(1)) */
667 hmac_sha_precomputed(&pre, a, A, NULL); 441 hmac_peek_hash(&ctx, a, A, NULL);
668 } 442 }
669
670 hmac_uninit(&pre);
671#undef A 443#undef A
672#undef SECRET 444#undef SECRET
673#undef SEED 445#undef SEED
@@ -733,6 +505,32 @@ static void *tls_get_zeroed_outbuf(tls_state_t *tls, int len)
733 return record; 505 return record;
734} 506}
735 507
508/* Calculate the HMAC over the list of blocks */
509#if !ENABLE_FEATURE_TLS_SHA1
510#define hmac_blocks(tls,out,key,key_size,...) \
511 hmac_blocks(out,key,key_size, __VA_ARGS__)
512#endif
513static unsigned hmac_blocks(tls_state_t *tls, uint8_t *out, uint8_t *key, unsigned key_size, ...)
514{
515 hmac_ctx_t ctx;
516 va_list va;
517 unsigned len;
518
519 hmac_begin(&ctx, key, key_size,
520 (ENABLE_FEATURE_TLS_SHA1 && tls->MAC_size == SHA1_OUTSIZE)
521 ? sha1_begin_hmac
522 : sha256_begin_hmac
523 );
524
525 va_start(va, key_size);
526 hmac_hash_v(&ctx, va);
527 va_end(va);
528
529 len = hmac_end(&ctx, out);
530 hmac_uninit(&ctx);
531 return len;
532}
533
736static void xwrite_encrypted_and_hmac_signed(tls_state_t *tls, unsigned size, unsigned type) 534static void xwrite_encrypted_and_hmac_signed(tls_state_t *tls, unsigned size, unsigned type)
737{ 535{
738 uint8_t *buf = tls->outbuf + OUTBUF_PFX; 536 uint8_t *buf = tls->outbuf + OUTBUF_PFX;
@@ -754,7 +552,7 @@ static void xwrite_encrypted_and_hmac_signed(tls_state_t *tls, unsigned size, un
754 xhdr->len16_lo = size & 0xff; 552 xhdr->len16_lo = size & 0xff;
755 553
756 /* Calculate MAC signature */ 554 /* Calculate MAC signature */
757 hmac(tls, buf + size, /* result */ 555 hmac_blocks(tls, buf + size, /* result */
758 tls->client_write_MAC_key, TLS_MAC_SIZE(tls), 556 tls->client_write_MAC_key, TLS_MAC_SIZE(tls),
759 &tls->write_seq64_be, sizeof(tls->write_seq64_be), 557 &tls->write_seq64_be, sizeof(tls->write_seq64_be),
760 xhdr, RECHDR_LEN, 558 xhdr, RECHDR_LEN,
@@ -943,8 +741,13 @@ static void xwrite_encrypted_aesgcm(tls_state_t *tls, unsigned size, unsigned ty
943 cnt++; 741 cnt++;
944 COUNTER(nonce) = htonl(cnt); /* yes, first cnt here is 2 (!) */ 742 COUNTER(nonce) = htonl(cnt); /* yes, first cnt here is 2 (!) */
945 aes_encrypt_one_block(&tls->aes_encrypt, nonce, scratch); 743 aes_encrypt_one_block(&tls->aes_encrypt, nonce, scratch);
946 n = remaining > AES_BLOCK_SIZE ? AES_BLOCK_SIZE : remaining; 744 if (remaining >= AES_BLOCK_SIZE) {
947 xorbuf(buf, scratch, n); 745 n = AES_BLOCK_SIZE;
746 xorbuf_AES_BLOCK_SIZE(buf, scratch);
747 } else {
748 n = remaining;
749 xorbuf(buf, scratch, n);
750 }
948 buf += n; 751 buf += n;
949 remaining -= n; 752 remaining -= n;
950 } 753 }
@@ -1102,7 +905,7 @@ static void tls_aesgcm_decrypt(tls_state_t *tls, uint8_t *buf, int size)
1102 COUNTER(nonce) = htonl(cnt); /* yes, first cnt here is 2 (!) */ 905 COUNTER(nonce) = htonl(cnt); /* yes, first cnt here is 2 (!) */
1103 aes_encrypt_one_block(&tls->aes_decrypt, nonce, scratch); 906 aes_encrypt_one_block(&tls->aes_decrypt, nonce, scratch);
1104 n = remaining > AES_BLOCK_SIZE ? AES_BLOCK_SIZE : remaining; 907 n = remaining > AES_BLOCK_SIZE ? AES_BLOCK_SIZE : remaining;
1105 xorbuf3(buf, scratch, buf + 8, n); 908 xorbuf_3(buf, scratch, buf + 8, n);
1106 buf += n; 909 buf += n;
1107 remaining -= n; 910 remaining -= n;
1108 } 911 }