diff options
Diffstat (limited to 'networking/tls.c')
-rw-r--r-- | networking/tls.c | 281 |
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 | ||
203 | enum { | 191 | enum { |
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 | ||
351 | static 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 | |||
360 | void FAST_FUNC xorbuf(void *dst, const void *src, unsigned count) | ||
361 | { | ||
362 | xorbuf3(dst, dst, src, count); | ||
363 | } | ||
364 | |||
365 | void 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 | ||
420 | typedef struct hmac_precomputed { | ||
421 | md5sha_ctx_t hashed_key_xor_ipad; | ||
422 | md5sha_ctx_t hashed_key_xor_opad; | ||
423 | } hmac_precomputed_t; | ||
424 | |||
425 | typedef 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 | |||
437 | static 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 | |||
479 | static 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 | |||
511 | typedef struct bcrypt_hash_ctx_t hmac_precomputed_t; | ||
512 | |||
513 | static 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 | |||
530 | static 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 | |||
550 | static void hmac_uninit(hmac_precomputed_t *pre) { | ||
551 | BCryptDestroyHash(pre->handle); | ||
552 | free(pre->hash_obj); | ||
553 | } | ||
554 | |||
555 | #endif | ||
556 | |||
557 | static 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 | ||
574 | static 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 | ||
513 | static 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 | |||
736 | static void xwrite_encrypted_and_hmac_signed(tls_state_t *tls, unsigned size, unsigned type) | 534 | static 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 | } |