diff options
Diffstat (limited to 'networking/tls.c')
-rw-r--r-- | networking/tls.c | 843 |
1 files changed, 598 insertions, 245 deletions
diff --git a/networking/tls.c b/networking/tls.c index 736bce323..9c05364ea 100644 --- a/networking/tls.c +++ b/networking/tls.c | |||
@@ -10,27 +10,19 @@ | |||
10 | //Config.src also defines FEATURE_TLS_SHA1 option | 10 | //Config.src also defines FEATURE_TLS_SHA1 option |
11 | 11 | ||
12 | //kbuild:lib-$(CONFIG_TLS) += tls.o | 12 | //kbuild:lib-$(CONFIG_TLS) += tls.o |
13 | //kbuild:lib-$(CONFIG_TLS) += tls_pstm.o | 13 | //kbuild:lib-$(CONFIG_FEATURE_TLS_INTERNAL) += tls_pstm.o |
14 | //kbuild:lib-$(CONFIG_TLS) += tls_pstm_montgomery_reduce.o | 14 | //kbuild:lib-$(CONFIG_FEATURE_TLS_INTERNAL) += tls_pstm_montgomery_reduce.o |
15 | //kbuild:lib-$(CONFIG_TLS) += tls_pstm_mul_comba.o | 15 | //kbuild:lib-$(CONFIG_FEATURE_TLS_INTERNAL) += tls_pstm_mul_comba.o |
16 | //kbuild:lib-$(CONFIG_TLS) += tls_pstm_sqr_comba.o | 16 | //kbuild:lib-$(CONFIG_FEATURE_TLS_INTERNAL) += tls_pstm_sqr_comba.o |
17 | //kbuild:lib-$(CONFIG_TLS) += tls_aes.o | 17 | //kbuild:lib-$(CONFIG_FEATURE_TLS_INTERNAL) += tls_aes.o |
18 | //kbuild:lib-$(CONFIG_TLS) += tls_aesgcm.o | 18 | //kbuild:lib-$(CONFIG_FEATURE_TLS_INTERNAL) += tls_aesgcm.o |
19 | //kbuild:lib-$(CONFIG_TLS) += tls_rsa.o | 19 | //kbuild:lib-$(CONFIG_FEATURE_TLS_INTERNAL) += tls_rsa.o |
20 | //kbuild:lib-$(CONFIG_TLS) += tls_fe.o | 20 | //kbuild:lib-$(CONFIG_FEATURE_TLS_INTERNAL) += tls_fe.o |
21 | //kbuild:lib-$(CONFIG_TLS) += tls_sp_c32.o | 21 | //kbuild:lib-$(CONFIG_FEATURE_TLS_INTERNAL) += tls_sp_c32.o |
22 | 22 | ||
23 | #include "tls.h" | 23 | #include "tls.h" |
24 | 24 | ||
25 | #if ENABLE_FEATURE_USE_CNG_API | 25 | #if !ENABLE_FEATURE_TLS_SCHANNEL |
26 | # include <windows.h> | ||
27 | # include <bcrypt.h> | ||
28 | |||
29 | // these work on Windows >= 10 | ||
30 | # define BCRYPT_HMAC_SHA1_ALG_HANDLE ((BCRYPT_ALG_HANDLE) 0x000000a1) | ||
31 | # define BCRYPT_HMAC_SHA256_ALG_HANDLE ((BCRYPT_ALG_HANDLE) 0x000000b1) | ||
32 | #endif | ||
33 | |||
34 | // Usually enabled. You can disable some of them to force only | 26 | // Usually enabled. You can disable some of them to force only |
35 | // specific ciphers to be advertized to server. | 27 | // specific ciphers to be advertized to server. |
36 | // (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) |
@@ -197,8 +189,6 @@ | |||
197 | #define TLS_MAX_OUTBUF (1 << 14) | 189 | #define TLS_MAX_OUTBUF (1 << 14) |
198 | 190 | ||
199 | enum { | 191 | enum { |
200 | SHA_INSIZE = 64, | ||
201 | |||
202 | AES128_KEYSIZE = 16, | 192 | AES128_KEYSIZE = 16, |
203 | AES256_KEYSIZE = 32, | 193 | AES256_KEYSIZE = 32, |
204 | 194 | ||
@@ -344,34 +334,6 @@ void FAST_FUNC tls_get_random(void *buf, unsigned len) | |||
344 | xfunc_die(); | 334 | xfunc_die(); |
345 | } | 335 | } |
346 | 336 | ||
347 | static void xorbuf3(void *dst, const void *src1, const void *src2, unsigned count) | ||
348 | { | ||
349 | uint8_t *d = dst; | ||
350 | const uint8_t *s1 = src1; | ||
351 | const uint8_t* s2 = src2; | ||
352 | while (count--) | ||
353 | *d++ = *s1++ ^ *s2++; | ||
354 | } | ||
355 | |||
356 | void FAST_FUNC xorbuf(void *dst, const void *src, unsigned count) | ||
357 | { | ||
358 | xorbuf3(dst, dst, src, count); | ||
359 | } | ||
360 | |||
361 | void FAST_FUNC xorbuf_aligned_AES_BLOCK_SIZE(void *dst, const void *src) | ||
362 | { | ||
363 | unsigned long *d = dst; | ||
364 | const unsigned long *s = src; | ||
365 | d[0] ^= s[0]; | ||
366 | #if ULONG_MAX <= 0xffffffffffffffff | ||
367 | d[1] ^= s[1]; | ||
368 | #if ULONG_MAX == 0xffffffff | ||
369 | d[2] ^= s[2]; | ||
370 | d[3] ^= s[3]; | ||
371 | #endif | ||
372 | #endif | ||
373 | } | ||
374 | |||
375 | #if !TLS_DEBUG_HASH | 337 | #if !TLS_DEBUG_HASH |
376 | # define hash_handshake(tls, fmt, buffer, len) \ | 338 | # define hash_handshake(tls, fmt, buffer, len) \ |
377 | hash_handshake(tls, buffer, len) | 339 | hash_handshake(tls, buffer, len) |
@@ -402,191 +364,6 @@ static void hash_handshake(tls_state_t *tls, const char *fmt, const void *buffer | |||
402 | # define TLS_MAC_SIZE(tls) (tls)->MAC_size | 364 | # define TLS_MAC_SIZE(tls) (tls)->MAC_size |
403 | #endif | 365 | #endif |
404 | 366 | ||
405 | // RFC 2104: | ||
406 | // HMAC(key, text) based on a hash H (say, sha256) is: | ||
407 | // ipad = [0x36 x INSIZE] | ||
408 | // opad = [0x5c x INSIZE] | ||
409 | // HMAC(key, text) = H((key XOR opad) + H((key XOR ipad) + text)) | ||
410 | // | ||
411 | // H(key XOR opad) and H(key XOR ipad) can be precomputed | ||
412 | // if we often need HMAC hmac with the same key. | ||
413 | // | ||
414 | // text is often given in disjoint pieces. | ||
415 | #if !ENABLE_FEATURE_USE_CNG_API | ||
416 | typedef struct hmac_precomputed { | ||
417 | md5sha_ctx_t hashed_key_xor_ipad; | ||
418 | md5sha_ctx_t hashed_key_xor_opad; | ||
419 | } hmac_precomputed_t; | ||
420 | |||
421 | typedef void md5sha_begin_func(md5sha_ctx_t *ctx) FAST_FUNC; | ||
422 | |||
423 | #define sha1_begin_hmac sha1_begin | ||
424 | #define sha256_begin_hmac sha256_begin | ||
425 | #define hmac_uninit(...) ((void)0) | ||
426 | |||
427 | #if !ENABLE_FEATURE_TLS_SHA1 | ||
428 | #define hmac_begin(pre,key,key_size,begin) \ | ||
429 | hmac_begin(pre,key,key_size) | ||
430 | #define begin sha256_begin | ||
431 | #endif | ||
432 | |||
433 | static void hmac_begin(hmac_precomputed_t *pre, uint8_t *key, unsigned key_size, md5sha_begin_func *begin) | ||
434 | { | ||
435 | uint8_t key_xor_ipad[SHA_INSIZE]; | ||
436 | uint8_t key_xor_opad[SHA_INSIZE]; | ||
437 | // uint8_t tempkey[SHA1_OUTSIZE < SHA256_OUTSIZE ? SHA256_OUTSIZE : SHA1_OUTSIZE]; | ||
438 | unsigned i; | ||
439 | |||
440 | // "The authentication key can be of any length up to INSIZE, the | ||
441 | // block length of the hash function. Applications that use keys longer | ||
442 | // than INSIZE bytes will first hash the key using H and then use the | ||
443 | // resultant OUTSIZE byte string as the actual key to HMAC." | ||
444 | if (key_size > SHA_INSIZE) { | ||
445 | bb_simple_error_msg_and_die("HMAC key>64"); //does not happen (yet?) | ||
446 | // md5sha_ctx_t ctx; | ||
447 | // begin(&ctx); | ||
448 | // md5sha_hash(&ctx, key, key_size); | ||
449 | // key_size = sha_end(&ctx, tempkey); | ||
450 | // //key = tempkey; - right? RIGHT? why does it work without this? | ||
451 | // // because SHA_INSIZE is 64, but hmac() is always called with | ||
452 | // // key_size = tls->MAC_size = SHA1/256_OUTSIZE (20 or 32), | ||
453 | // // and prf_hmac_sha256() -> hmac_sha256() key sizes are: | ||
454 | // // - RSA_PREMASTER_SIZE is 48 | ||
455 | // // - CURVE25519_KEYSIZE is 32 | ||
456 | // // - master_secret[] is 48 | ||
457 | } | ||
458 | |||
459 | for (i = 0; i < key_size; i++) { | ||
460 | key_xor_ipad[i] = key[i] ^ 0x36; | ||
461 | key_xor_opad[i] = key[i] ^ 0x5c; | ||
462 | } | ||
463 | for (; i < SHA_INSIZE; i++) { | ||
464 | key_xor_ipad[i] = 0x36; | ||
465 | key_xor_opad[i] = 0x5c; | ||
466 | } | ||
467 | |||
468 | begin(&pre->hashed_key_xor_ipad); | ||
469 | begin(&pre->hashed_key_xor_opad); | ||
470 | md5sha_hash(&pre->hashed_key_xor_ipad, key_xor_ipad, SHA_INSIZE); | ||
471 | md5sha_hash(&pre->hashed_key_xor_opad, key_xor_opad, SHA_INSIZE); | ||
472 | } | ||
473 | #undef begin | ||
474 | |||
475 | static unsigned hmac_sha_precomputed_v( | ||
476 | hmac_precomputed_t *pre, | ||
477 | uint8_t *out, | ||
478 | va_list va) | ||
479 | { | ||
480 | uint8_t *text; | ||
481 | unsigned len; | ||
482 | |||
483 | /* pre->hashed_key_xor_ipad contains unclosed "H((key XOR ipad) +" state */ | ||
484 | /* pre->hashed_key_xor_opad contains unclosed "H((key XOR opad) +" state */ | ||
485 | |||
486 | /* calculate out = H((key XOR ipad) + text) */ | ||
487 | while ((text = va_arg(va, uint8_t*)) != NULL) { | ||
488 | unsigned text_size = va_arg(va, unsigned); | ||
489 | md5sha_hash(&pre->hashed_key_xor_ipad, text, text_size); | ||
490 | } | ||
491 | len = sha_end(&pre->hashed_key_xor_ipad, out); | ||
492 | |||
493 | /* out = H((key XOR opad) + out) */ | ||
494 | md5sha_hash(&pre->hashed_key_xor_opad, out, len); | ||
495 | return sha_end(&pre->hashed_key_xor_opad, out); | ||
496 | } | ||
497 | #else | ||
498 | #define sha1_begin_hmac BCRYPT_HMAC_SHA1_ALG_HANDLE | ||
499 | #define sha256_begin_hmac BCRYPT_HMAC_SHA256_ALG_HANDLE | ||
500 | |||
501 | #if !ENABLE_FEATURE_TLS_SHA1 | ||
502 | #define hmac_begin(pre,key,key_size,begin) _hmac_begin(pre, key, key_size, sha256_begin_hmac) | ||
503 | #else | ||
504 | #define hmac_begin _hmac_begin | ||
505 | #endif | ||
506 | |||
507 | typedef struct bcrypt_hash_ctx_t hmac_precomputed_t; | ||
508 | |||
509 | static void _hmac_begin(hmac_precomputed_t *pre, uint8_t *key, unsigned key_size, BCRYPT_ALG_HANDLE alg_handle) { | ||
510 | DWORD hash_object_length = 0; | ||
511 | ULONG _unused; | ||
512 | NTSTATUS status; | ||
513 | |||
514 | status = BCryptGetProperty(alg_handle, BCRYPT_OBJECT_LENGTH, (PUCHAR)&hash_object_length, sizeof(DWORD), &_unused, 0); | ||
515 | mingw_die_if_error(status, "BCryptGetProperty"); | ||
516 | status = BCryptGetProperty(alg_handle, BCRYPT_HASH_LENGTH, (PUCHAR)&pre->output_size, sizeof(DWORD), &_unused, 0); | ||
517 | mingw_die_if_error(status, "BCryptGetProperty"); | ||
518 | |||
519 | |||
520 | pre->hash_obj = xmalloc(hash_object_length); | ||
521 | |||
522 | status = BCryptCreateHash(alg_handle, &pre->handle, pre->hash_obj, hash_object_length, key, key_size, BCRYPT_HASH_REUSABLE_FLAG); | ||
523 | mingw_die_if_error(status, "BCryptCreateHash"); | ||
524 | } | ||
525 | |||
526 | static unsigned hmac_sha_precomputed_v( | ||
527 | hmac_precomputed_t *pre, | ||
528 | uint8_t *out, | ||
529 | va_list va) | ||
530 | { | ||
531 | uint8_t *text; | ||
532 | NTSTATUS status; | ||
533 | |||
534 | while ((text = va_arg(va, uint8_t*)) != NULL) { | ||
535 | unsigned text_size = va_arg(va, unsigned); | ||
536 | /*status = */ BCryptHashData(pre->handle, text, text_size, 0); | ||
537 | //mingw_die_if_error(status, "BCryptHashData"); | ||
538 | } | ||
539 | |||
540 | status = BCryptFinishHash(pre->handle, out, pre->output_size, 0); | ||
541 | mingw_die_if_error(status, "BCryptFinishHash"); | ||
542 | |||
543 | return pre->output_size; | ||
544 | } | ||
545 | |||
546 | static void hmac_uninit(hmac_precomputed_t *pre) { | ||
547 | BCryptDestroyHash(pre->handle); | ||
548 | free(pre->hash_obj); | ||
549 | } | ||
550 | |||
551 | #endif | ||
552 | |||
553 | static unsigned hmac_sha_precomputed(hmac_precomputed_t *pre_init, uint8_t *out, ...) | ||
554 | { | ||
555 | hmac_precomputed_t pre; | ||
556 | va_list va; | ||
557 | unsigned len; | ||
558 | |||
559 | va_start(va, out); | ||
560 | pre = *pre_init; /* struct copy */ | ||
561 | len = hmac_sha_precomputed_v(&pre, out, va); | ||
562 | va_end(va); | ||
563 | return len; | ||
564 | } | ||
565 | |||
566 | #if !ENABLE_FEATURE_TLS_SHA1 | ||
567 | #define hmac(tls,out,key,key_size,...) \ | ||
568 | hmac(out,key,key_size, __VA_ARGS__) | ||
569 | #endif | ||
570 | static unsigned hmac(tls_state_t *tls, uint8_t *out, uint8_t *key, unsigned key_size, ...) | ||
571 | { | ||
572 | hmac_precomputed_t pre; | ||
573 | va_list va; | ||
574 | unsigned len; | ||
575 | |||
576 | va_start(va, key_size); | ||
577 | |||
578 | hmac_begin(&pre, key, key_size, | ||
579 | (ENABLE_FEATURE_TLS_SHA1 && tls->MAC_size == SHA1_OUTSIZE) | ||
580 | ? sha1_begin_hmac | ||
581 | : sha256_begin_hmac | ||
582 | ); | ||
583 | len = hmac_sha_precomputed_v(&pre, out, va); | ||
584 | |||
585 | va_end(va); | ||
586 | hmac_uninit(&pre); | ||
587 | return len; | ||
588 | } | ||
589 | |||
590 | // RFC 5246: | 367 | // RFC 5246: |
591 | // 5. HMAC and the Pseudorandom Function | 368 | // 5. HMAC and the Pseudorandom Function |
592 | //... | 369 | //... |
@@ -631,7 +408,7 @@ static void prf_hmac_sha256(/*tls_state_t *tls,*/ | |||
631 | const char *label, | 408 | const char *label, |
632 | uint8_t *seed, unsigned seed_size) | 409 | uint8_t *seed, unsigned seed_size) |
633 | { | 410 | { |
634 | hmac_precomputed_t pre; | 411 | hmac_ctx_t ctx; |
635 | uint8_t a[TLS_MAX_MAC_SIZE]; | 412 | uint8_t a[TLS_MAX_MAC_SIZE]; |
636 | uint8_t *out_p = outbuf; | 413 | uint8_t *out_p = outbuf; |
637 | unsigned label_size = strlen(label); | 414 | unsigned label_size = strlen(label); |
@@ -641,29 +418,28 @@ static void prf_hmac_sha256(/*tls_state_t *tls,*/ | |||
641 | #define SEED label, label_size, seed, seed_size | 418 | #define SEED label, label_size, seed, seed_size |
642 | #define A a, MAC_size | 419 | #define A a, MAC_size |
643 | 420 | ||
644 | hmac_begin(&pre, secret, secret_size, sha256_begin_hmac); | 421 | hmac_begin(&ctx, secret, secret_size, sha256_begin_hmac); |
645 | 422 | ||
646 | /* A(1) = HMAC_hash(secret, seed) */ | 423 | /* A(1) = HMAC_hash(secret, seed) */ |
647 | hmac_sha_precomputed(&pre, a, SEED, NULL); | 424 | hmac_peek_hash(&ctx, a, SEED, NULL); |
648 | 425 | ||
649 | for (;;) { | 426 | for (;;) { |
650 | /* HMAC_hash(secret, A(1) + seed) */ | 427 | /* HMAC_hash(secret, A(1) + seed) */ |
651 | if (outbuf_size <= MAC_size) { | 428 | if (outbuf_size <= MAC_size) { |
652 | /* Last, possibly incomplete, block */ | 429 | /* Last, possibly incomplete, block */ |
653 | /* (use a[] as temp buffer) */ | 430 | /* (use a[] as temp buffer) */ |
654 | hmac_sha_precomputed(&pre, a, A, SEED, NULL); | 431 | hmac_peek_hash(&ctx, a, A, SEED, NULL); |
655 | memcpy(out_p, a, outbuf_size); | 432 | memcpy(out_p, a, outbuf_size); |
433 | hmac_uninit(&ctx); | ||
656 | return; | 434 | return; |
657 | } | 435 | } |
658 | /* Not last block. Store directly to result buffer */ | 436 | /* Not last block. Store directly to result buffer */ |
659 | hmac_sha_precomputed(&pre, out_p, A, SEED, NULL); | 437 | hmac_peek_hash(&ctx, out_p, A, SEED, NULL); |
660 | out_p += MAC_size; | 438 | out_p += MAC_size; |
661 | outbuf_size -= MAC_size; | 439 | outbuf_size -= MAC_size; |
662 | /* A(2) = HMAC_hash(secret, A(1)) */ | 440 | /* A(2) = HMAC_hash(secret, A(1)) */ |
663 | hmac_sha_precomputed(&pre, a, A, NULL); | 441 | hmac_peek_hash(&ctx, a, A, NULL); |
664 | } | 442 | } |
665 | |||
666 | hmac_uninit(&pre); | ||
667 | #undef A | 443 | #undef A |
668 | #undef SECRET | 444 | #undef SECRET |
669 | #undef SEED | 445 | #undef SEED |
@@ -729,6 +505,32 @@ static void *tls_get_zeroed_outbuf(tls_state_t *tls, int len) | |||
729 | return record; | 505 | return record; |
730 | } | 506 | } |
731 | 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 | |||
732 | 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) |
733 | { | 535 | { |
734 | uint8_t *buf = tls->outbuf + OUTBUF_PFX; | 536 | uint8_t *buf = tls->outbuf + OUTBUF_PFX; |
@@ -750,7 +552,7 @@ static void xwrite_encrypted_and_hmac_signed(tls_state_t *tls, unsigned size, un | |||
750 | xhdr->len16_lo = size & 0xff; | 552 | xhdr->len16_lo = size & 0xff; |
751 | 553 | ||
752 | /* Calculate MAC signature */ | 554 | /* Calculate MAC signature */ |
753 | hmac(tls, buf + size, /* result */ | 555 | hmac_blocks(tls, buf + size, /* result */ |
754 | tls->client_write_MAC_key, TLS_MAC_SIZE(tls), | 556 | tls->client_write_MAC_key, TLS_MAC_SIZE(tls), |
755 | &tls->write_seq64_be, sizeof(tls->write_seq64_be), | 557 | &tls->write_seq64_be, sizeof(tls->write_seq64_be), |
756 | xhdr, RECHDR_LEN, | 558 | xhdr, RECHDR_LEN, |
@@ -939,8 +741,13 @@ static void xwrite_encrypted_aesgcm(tls_state_t *tls, unsigned size, unsigned ty | |||
939 | cnt++; | 741 | cnt++; |
940 | COUNTER(nonce) = htonl(cnt); /* yes, first cnt here is 2 (!) */ | 742 | COUNTER(nonce) = htonl(cnt); /* yes, first cnt here is 2 (!) */ |
941 | aes_encrypt_one_block(&tls->aes_encrypt, nonce, scratch); | 743 | aes_encrypt_one_block(&tls->aes_encrypt, nonce, scratch); |
942 | n = remaining > AES_BLOCK_SIZE ? AES_BLOCK_SIZE : remaining; | 744 | if (remaining >= AES_BLOCK_SIZE) { |
943 | 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 | } | ||
944 | buf += n; | 751 | buf += n; |
945 | remaining -= n; | 752 | remaining -= n; |
946 | } | 753 | } |
@@ -1098,7 +905,7 @@ static void tls_aesgcm_decrypt(tls_state_t *tls, uint8_t *buf, int size) | |||
1098 | COUNTER(nonce) = htonl(cnt); /* yes, first cnt here is 2 (!) */ | 905 | COUNTER(nonce) = htonl(cnt); /* yes, first cnt here is 2 (!) */ |
1099 | aes_encrypt_one_block(&tls->aes_decrypt, nonce, scratch); | 906 | aes_encrypt_one_block(&tls->aes_decrypt, nonce, scratch); |
1100 | n = remaining > AES_BLOCK_SIZE ? AES_BLOCK_SIZE : remaining; | 907 | n = remaining > AES_BLOCK_SIZE ? AES_BLOCK_SIZE : remaining; |
1101 | xorbuf3(buf, scratch, buf + 8, n); | 908 | xorbuf_3(buf, scratch, buf + 8, n); |
1102 | buf += n; | 909 | buf += n; |
1103 | remaining -= n; | 910 | remaining -= n; |
1104 | } | 911 | } |
@@ -2555,3 +2362,549 @@ void FAST_FUNC tls_run_copy_loop(tls_state_t *tls, unsigned flags) | |||
2555 | } | 2362 | } |
2556 | } | 2363 | } |
2557 | } | 2364 | } |
2365 | #else | ||
2366 | |||
2367 | #if ENABLE_FEATURE_TLS_SCHANNEL_1_3 | ||
2368 | #include <subauth.h> | ||
2369 | #endif | ||
2370 | |||
2371 | #define SCHANNEL_USE_BLACKLISTS | ||
2372 | |||
2373 | #include <security.h> | ||
2374 | #include <schannel.h> | ||
2375 | |||
2376 | |||
2377 | #define BB_SCHANNEL_ISC_FLAGS \ | ||
2378 | (ISC_REQ_ALLOCATE_MEMORY | ISC_REQ_CONFIDENTIALITY | ISC_REQ_INTEGRITY | ISC_REQ_REPLAY_DETECT | \ | ||
2379 | ISC_REQ_SEQUENCE_DETECT | ISC_REQ_STREAM | ISC_REQ_USE_SUPPLIED_CREDS) | ||
2380 | |||
2381 | static char *hresult_to_error_string(HRESULT result) { | ||
2382 | char *output = NULL; | ||
2383 | |||
2384 | FormatMessageA(FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM | ||
2385 | | FORMAT_MESSAGE_IGNORE_INSERTS | | ||
2386 | FORMAT_MESSAGE_MAX_WIDTH_MASK, NULL, result, | ||
2387 | MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), | ||
2388 | (char *) &output, 0, NULL); | ||
2389 | return output; | ||
2390 | } | ||
2391 | |||
2392 | static ssize_t tls_read(struct tls_state *state, char *buf, ssize_t len) { | ||
2393 | ssize_t amount_read = 0; | ||
2394 | |||
2395 | if (state->closed) { | ||
2396 | return 0; | ||
2397 | } | ||
2398 | |||
2399 | while (len > 0) { | ||
2400 | if (state->out_buffer && (state->out_buffer_size > 0)) { | ||
2401 | unsigned long copy_amount = | ||
2402 | min(len, (ssize_t) state->out_buffer_size); | ||
2403 | memcpy(buf, state->out_buffer, copy_amount); | ||
2404 | |||
2405 | amount_read += copy_amount; | ||
2406 | buf += copy_amount; | ||
2407 | len -= copy_amount; | ||
2408 | |||
2409 | if (copy_amount == state->out_buffer_size) { | ||
2410 | // We've used all the decrypted data | ||
2411 | // Move extra data to the front | ||
2412 | memmove(state->in_buffer, | ||
2413 | state->in_buffer + state->out_buffer_used, | ||
2414 | state->in_buffer_size - state->out_buffer_used); | ||
2415 | state->in_buffer_size -= state->out_buffer_used; | ||
2416 | |||
2417 | state->out_buffer = NULL; | ||
2418 | state->out_buffer_used = 0; | ||
2419 | state->out_buffer_size = 0; | ||
2420 | } else { | ||
2421 | state->out_buffer_size -= copy_amount; | ||
2422 | state->out_buffer += copy_amount; | ||
2423 | } | ||
2424 | } else { | ||
2425 | SECURITY_STATUS status; | ||
2426 | |||
2427 | int received; | ||
2428 | |||
2429 | SecBuffer buffers[4]; | ||
2430 | |||
2431 | SecBufferDesc desc; | ||
2432 | |||
2433 | buffers[0].BufferType = SECBUFFER_DATA; | ||
2434 | buffers[0].pvBuffer = state->in_buffer; | ||
2435 | buffers[0].cbBuffer = state->in_buffer_size; | ||
2436 | |||
2437 | buffers[1].BufferType = SECBUFFER_EMPTY; | ||
2438 | buffers[1].pvBuffer = NULL; | ||
2439 | buffers[1].cbBuffer = 0; | ||
2440 | |||
2441 | buffers[2].BufferType = SECBUFFER_EMPTY; | ||
2442 | buffers[2].pvBuffer = NULL; | ||
2443 | buffers[2].cbBuffer = 0; | ||
2444 | |||
2445 | buffers[3].BufferType = SECBUFFER_EMPTY; | ||
2446 | buffers[3].pvBuffer = NULL; | ||
2447 | buffers[3].cbBuffer = 0; | ||
2448 | |||
2449 | desc.ulVersion = SECBUFFER_VERSION; | ||
2450 | desc.pBuffers = buffers; | ||
2451 | desc.cBuffers = _countof(buffers); | ||
2452 | |||
2453 | status = DecryptMessage(&state->ctx_handle, &desc, 0, NULL); | ||
2454 | |||
2455 | switch (status) { | ||
2456 | case SEC_E_OK:{ | ||
2457 | state->out_buffer = buffers[1].pvBuffer; | ||
2458 | state->out_buffer_size = buffers[1].cbBuffer; | ||
2459 | |||
2460 | state->out_buffer_used = state->in_buffer_size; | ||
2461 | if (buffers[3].BufferType == SECBUFFER_EXTRA) { | ||
2462 | state->out_buffer_used -= buffers[3].cbBuffer; | ||
2463 | } | ||
2464 | |||
2465 | continue; | ||
2466 | } | ||
2467 | case SEC_I_CONTEXT_EXPIRED:{ | ||
2468 | state->closed = 1; | ||
2469 | goto Success; | ||
2470 | } | ||
2471 | case SEC_I_RENEGOTIATE:{ | ||
2472 | // Renegotiate the TLS connection. | ||
2473 | // Microsoft repurposed this flag | ||
2474 | // for TLS 1.3 support. | ||
2475 | int i; | ||
2476 | |||
2477 | DWORD flags; | ||
2478 | |||
2479 | SecBuffer in_buffers[2]; | ||
2480 | |||
2481 | SecBuffer out_buffers[2]; | ||
2482 | |||
2483 | SecBufferDesc in_desc; | ||
2484 | |||
2485 | SecBufferDesc out_desc; | ||
2486 | |||
2487 | |||
2488 | for (i = 0; i < 4; i++) { | ||
2489 | if (buffers[i].BufferType == SECBUFFER_EXTRA) | ||
2490 | break; | ||
2491 | } | ||
2492 | |||
2493 | flags = BB_SCHANNEL_ISC_FLAGS; | ||
2494 | |||
2495 | in_buffers[0].BufferType = SECBUFFER_TOKEN; | ||
2496 | in_buffers[0].pvBuffer = buffers[i].pvBuffer; | ||
2497 | in_buffers[0].cbBuffer = buffers[i].cbBuffer; | ||
2498 | |||
2499 | in_buffers[1].BufferType = SECBUFFER_EMPTY; | ||
2500 | in_buffers[1].pvBuffer = NULL; | ||
2501 | in_buffers[1].cbBuffer = 0; | ||
2502 | |||
2503 | out_buffers[0].BufferType = SECBUFFER_TOKEN; | ||
2504 | out_buffers[0].pvBuffer = NULL; | ||
2505 | out_buffers[0].cbBuffer = 0; | ||
2506 | |||
2507 | out_buffers[1].BufferType = SECBUFFER_ALERT; | ||
2508 | out_buffers[1].pvBuffer = NULL; | ||
2509 | out_buffers[1].cbBuffer = 0; | ||
2510 | |||
2511 | in_desc.ulVersion = SECBUFFER_VERSION; | ||
2512 | in_desc.pBuffers = in_buffers; | ||
2513 | in_desc.cBuffers = _countof(in_buffers); | ||
2514 | |||
2515 | out_desc.ulVersion = SECBUFFER_VERSION; | ||
2516 | out_desc.pBuffers = out_buffers; | ||
2517 | out_desc.cBuffers = _countof(out_buffers); | ||
2518 | |||
2519 | status = InitializeSecurityContext(&state->cred_handle, | ||
2520 | state->initialized ? | ||
2521 | &state->ctx_handle : NULL, | ||
2522 | state->initialized ? NULL : | ||
2523 | state->hostname, flags, 0, | ||
2524 | 0, | ||
2525 | state->initialized ? | ||
2526 | &in_desc : NULL, 0, | ||
2527 | state->initialized ? NULL : | ||
2528 | &state->ctx_handle, | ||
2529 | &out_desc, &flags, 0); | ||
2530 | |||
2531 | if (status != SEC_E_OK) { | ||
2532 | bb_error_msg_and_die("schannel: renegotiate failed: (0x%08lx): %s", | ||
2533 | status, hresult_to_error_string(status)); | ||
2534 | } | ||
2535 | |||
2536 | if (in_buffers[1].BufferType == SECBUFFER_EXTRA) { | ||
2537 | memmove(state->in_buffer, | ||
2538 | state->in_buffer + (state->in_buffer_size - | ||
2539 | in_buffers[1].cbBuffer), | ||
2540 | in_buffers[1].cbBuffer); | ||
2541 | } | ||
2542 | |||
2543 | state->out_buffer_used = | ||
2544 | state->in_buffer_size - in_buffers[1].cbBuffer; | ||
2545 | state->in_buffer_size = in_buffers[1].cbBuffer; | ||
2546 | |||
2547 | continue; | ||
2548 | } | ||
2549 | case SEC_E_INCOMPLETE_MESSAGE:{ | ||
2550 | break; | ||
2551 | } | ||
2552 | default:{ | ||
2553 | bb_error_msg_and_die("schannel: DecryptMessage failed: (0x%08lx): %s", status, | ||
2554 | hresult_to_error_string(status)); | ||
2555 | } | ||
2556 | } | ||
2557 | |||
2558 | received = | ||
2559 | safe_read(state->ifd, | ||
2560 | state->in_buffer + state->in_buffer_size, | ||
2561 | sizeof(state->in_buffer) - state->in_buffer_size); | ||
2562 | if (received == 0) { | ||
2563 | state->closed = 1; | ||
2564 | goto Success; | ||
2565 | } else if (received < 0) { | ||
2566 | bb_error_msg_and_die("schannel: read() failed"); | ||
2567 | } | ||
2568 | |||
2569 | state->in_buffer_size += received; | ||
2570 | } | ||
2571 | } | ||
2572 | |||
2573 | Success: | ||
2574 | return amount_read; | ||
2575 | } | ||
2576 | |||
2577 | static void tls_write(struct tls_state *state, char *buf, size_t len) { | ||
2578 | if (state->closed) { | ||
2579 | bb_error_msg_and_die("schannel: attempted to write to a closed connection"); | ||
2580 | } | ||
2581 | |||
2582 | while (len > 0) { | ||
2583 | unsigned long copy_amount = | ||
2584 | min(len, (size_t) state->stream_sizes.cbMaximumMessage); | ||
2585 | char *write_buffer = _alloca(sizeof(state->in_buffer)); | ||
2586 | |||
2587 | SECURITY_STATUS status; | ||
2588 | |||
2589 | SecBuffer buffers[4]; | ||
2590 | |||
2591 | SecBufferDesc desc; | ||
2592 | |||
2593 | buffers[0].BufferType = SECBUFFER_STREAM_HEADER; | ||
2594 | buffers[0].pvBuffer = write_buffer; | ||
2595 | buffers[0].cbBuffer = state->stream_sizes.cbHeader; | ||
2596 | |||
2597 | buffers[1].BufferType = SECBUFFER_DATA; | ||
2598 | buffers[1].pvBuffer = write_buffer + state->stream_sizes.cbHeader; | ||
2599 | buffers[1].cbBuffer = copy_amount; | ||
2600 | |||
2601 | buffers[2].BufferType = SECBUFFER_STREAM_TRAILER; | ||
2602 | buffers[2].pvBuffer = | ||
2603 | write_buffer + state->stream_sizes.cbHeader + copy_amount; | ||
2604 | buffers[2].cbBuffer = state->stream_sizes.cbTrailer; | ||
2605 | |||
2606 | buffers[3].BufferType = SECBUFFER_EMPTY; | ||
2607 | buffers[3].pvBuffer = NULL; | ||
2608 | buffers[3].cbBuffer = 0; | ||
2609 | |||
2610 | memcpy(buffers[1].pvBuffer, buf, copy_amount); | ||
2611 | |||
2612 | desc.ulVersion = SECBUFFER_VERSION; | ||
2613 | desc.pBuffers = buffers; | ||
2614 | desc.cBuffers = _countof(buffers); | ||
2615 | |||
2616 | status = EncryptMessage(&state->ctx_handle, 0, &desc, 0); | ||
2617 | if (status != SEC_E_OK) { | ||
2618 | bb_error_msg_and_die("schannel: EncryptMessage failed: (0x%08lx): %s", status, | ||
2619 | hresult_to_error_string(status)); | ||
2620 | } | ||
2621 | |||
2622 | xwrite(state->ofd, write_buffer, | ||
2623 | buffers[0].cbBuffer + buffers[1].cbBuffer + | ||
2624 | buffers[2].cbBuffer); | ||
2625 | |||
2626 | len -= copy_amount; | ||
2627 | } | ||
2628 | } | ||
2629 | |||
2630 | static void tls_disconnect(tls_state_t * state) { | ||
2631 | SECURITY_STATUS status; | ||
2632 | DWORD token = SCHANNEL_SHUTDOWN; | ||
2633 | DWORD flags = BB_SCHANNEL_ISC_FLAGS; | ||
2634 | |||
2635 | SecBuffer buf_token; | ||
2636 | |||
2637 | SecBufferDesc buf_token_desc; | ||
2638 | |||
2639 | SecBuffer in_buffers[2]; | ||
2640 | SecBuffer out_buffers[2]; | ||
2641 | |||
2642 | SecBufferDesc in_desc; | ||
2643 | SecBufferDesc out_desc; | ||
2644 | |||
2645 | buf_token.BufferType = SECBUFFER_TOKEN; | ||
2646 | buf_token.pvBuffer = &token; | ||
2647 | buf_token.cbBuffer = sizeof(token); | ||
2648 | |||
2649 | buf_token_desc.ulVersion = SECBUFFER_VERSION; | ||
2650 | buf_token_desc.pBuffers = &buf_token; | ||
2651 | buf_token_desc.cBuffers = 1; | ||
2652 | |||
2653 | ApplyControlToken(&state->ctx_handle, &buf_token_desc); | ||
2654 | |||
2655 | // attempt to send any final data | ||
2656 | |||
2657 | in_buffers[0].BufferType = SECBUFFER_TOKEN; | ||
2658 | in_buffers[0].pvBuffer = state->in_buffer; | ||
2659 | in_buffers[0].cbBuffer = state->in_buffer_size; | ||
2660 | |||
2661 | in_buffers[1].BufferType = SECBUFFER_EMPTY; | ||
2662 | in_buffers[1].pvBuffer = NULL; | ||
2663 | in_buffers[1].cbBuffer = 0; | ||
2664 | |||
2665 | out_buffers[0].BufferType = SECBUFFER_TOKEN; | ||
2666 | out_buffers[0].pvBuffer = NULL; | ||
2667 | out_buffers[0].cbBuffer = 0; | ||
2668 | |||
2669 | out_buffers[1].BufferType = SECBUFFER_ALERT; | ||
2670 | out_buffers[1].pvBuffer = NULL; | ||
2671 | out_buffers[1].cbBuffer = 0; | ||
2672 | |||
2673 | in_desc.ulVersion = SECBUFFER_VERSION; | ||
2674 | in_desc.pBuffers = in_buffers; | ||
2675 | in_desc.cBuffers = _countof(in_buffers); | ||
2676 | |||
2677 | out_desc.ulVersion = SECBUFFER_VERSION; | ||
2678 | out_desc.pBuffers = out_buffers; | ||
2679 | out_desc.cBuffers = _countof(out_buffers); | ||
2680 | |||
2681 | status = InitializeSecurityContext(&state->cred_handle, | ||
2682 | state-> | ||
2683 | initialized ? &state->ctx_handle : | ||
2684 | NULL, | ||
2685 | state-> | ||
2686 | initialized ? NULL : state->hostname, | ||
2687 | flags, 0, 0, | ||
2688 | state->initialized ? &in_desc : NULL, | ||
2689 | 0, | ||
2690 | state-> | ||
2691 | initialized ? NULL : | ||
2692 | &state->ctx_handle, &out_desc, &flags, | ||
2693 | 0); | ||
2694 | |||
2695 | if (status == SEC_E_OK) { | ||
2696 | // attempt to write any extra data | ||
2697 | write(state->ofd, out_buffers[0].pvBuffer, out_buffers[0].cbBuffer); | ||
2698 | } | ||
2699 | |||
2700 | DeleteSecurityContext(&state->ctx_handle); | ||
2701 | FreeCredentialsHandle(&state->cred_handle); | ||
2702 | free(state->hostname); | ||
2703 | } | ||
2704 | |||
2705 | |||
2706 | void FAST_FUNC tls_handshake(tls_state_t * state, const char *hostname) { | ||
2707 | SECURITY_STATUS status; | ||
2708 | int received; | ||
2709 | |||
2710 | #if ENABLE_FEATURE_TLS_SCHANNEL_1_3 | ||
2711 | SCH_CREDENTIALS credential = {.dwVersion = SCH_CREDENTIALS_VERSION, | ||
2712 | .dwCredFormat = 0, | ||
2713 | .cCreds = 0, | ||
2714 | .paCred = NULL, | ||
2715 | .hRootStore = NULL, | ||
2716 | .cMappers = 0, | ||
2717 | .aphMappers = NULL, | ||
2718 | .dwSessionLifespan = 0, | ||
2719 | .dwFlags = | ||
2720 | SCH_CRED_AUTO_CRED_VALIDATION | SCH_CRED_NO_DEFAULT_CREDS | | ||
2721 | SCH_USE_STRONG_CRYPTO, | ||
2722 | .cTlsParameters = 0, | ||
2723 | .pTlsParameters = NULL | ||
2724 | }; | ||
2725 | #else | ||
2726 | SCHANNEL_CRED credential = {.dwVersion = SCHANNEL_CRED_VERSION, | ||
2727 | .cCreds = 0, | ||
2728 | .paCred = NULL, | ||
2729 | .hRootStore = NULL, | ||
2730 | .cMappers = 0, | ||
2731 | .aphMappers = NULL, | ||
2732 | .cSupportedAlgs = 0, | ||
2733 | .palgSupportedAlgs = NULL, | ||
2734 | .grbitEnabledProtocols = | ||
2735 | SP_PROT_TLS1_0_CLIENT | SP_PROT_TLS1_1_CLIENT | | ||
2736 | SP_PROT_TLS1_2_CLIENT, | ||
2737 | .dwMinimumCipherStrength = 0, | ||
2738 | .dwMaximumCipherStrength = 0, | ||
2739 | .dwSessionLifespan = 0, | ||
2740 | .dwFlags = | ||
2741 | SCH_CRED_AUTO_CRED_VALIDATION | SCH_CRED_NO_DEFAULT_CREDS | | ||
2742 | SCH_USE_STRONG_CRYPTO, | ||
2743 | .dwCredFormat = 0 | ||
2744 | }; | ||
2745 | #endif | ||
2746 | |||
2747 | if ((status = AcquireCredentialsHandleA(NULL, (SEC_CHAR *) UNISP_NAME_A, | ||
2748 | SECPKG_CRED_OUTBOUND, NULL, | ||
2749 | &credential, | ||
2750 | NULL, NULL, &state->cred_handle, | ||
2751 | NULL)) != SEC_E_OK) { | ||
2752 | bb_error_msg_and_die("schannel: AcquireCredentialsHandleA failed: (0x%08lx): %s", | ||
2753 | status, hresult_to_error_string(status)); | ||
2754 | } | ||
2755 | |||
2756 | state->in_buffer_size = 0; | ||
2757 | state->out_buffer_size = 0; | ||
2758 | state->out_buffer_used = 0; | ||
2759 | |||
2760 | state->out_buffer = NULL; | ||
2761 | |||
2762 | state->hostname = strdup(hostname); | ||
2763 | |||
2764 | state->initialized = 0; | ||
2765 | state->closed = 0; | ||
2766 | |||
2767 | while (1) { | ||
2768 | DWORD flags = BB_SCHANNEL_ISC_FLAGS; | ||
2769 | |||
2770 | SecBuffer in_buffers[2]; | ||
2771 | SecBuffer out_buffers[2]; | ||
2772 | |||
2773 | SecBufferDesc in_desc; | ||
2774 | SecBufferDesc out_desc; | ||
2775 | |||
2776 | in_buffers[0].BufferType = SECBUFFER_TOKEN; | ||
2777 | in_buffers[0].pvBuffer = state->in_buffer; | ||
2778 | in_buffers[0].cbBuffer = state->in_buffer_size; | ||
2779 | |||
2780 | in_buffers[1].BufferType = SECBUFFER_EMPTY; | ||
2781 | in_buffers[1].pvBuffer = NULL; | ||
2782 | in_buffers[1].cbBuffer = 0; | ||
2783 | |||
2784 | out_buffers[0].BufferType = SECBUFFER_TOKEN; | ||
2785 | out_buffers[0].pvBuffer = NULL; | ||
2786 | out_buffers[0].cbBuffer = 0; | ||
2787 | |||
2788 | out_buffers[1].BufferType = SECBUFFER_ALERT; | ||
2789 | out_buffers[1].pvBuffer = NULL; | ||
2790 | out_buffers[1].cbBuffer = 0; | ||
2791 | |||
2792 | in_desc.ulVersion = SECBUFFER_VERSION; | ||
2793 | in_desc.pBuffers = in_buffers; | ||
2794 | in_desc.cBuffers = _countof(in_buffers); | ||
2795 | |||
2796 | out_desc.ulVersion = SECBUFFER_VERSION; | ||
2797 | out_desc.pBuffers = out_buffers; | ||
2798 | out_desc.cBuffers = _countof(out_buffers); | ||
2799 | |||
2800 | status = InitializeSecurityContext(&state->cred_handle, | ||
2801 | state-> | ||
2802 | initialized ? &state->ctx_handle : | ||
2803 | NULL, | ||
2804 | state-> | ||
2805 | initialized ? NULL : | ||
2806 | state->hostname, flags, 0, 0, | ||
2807 | state->initialized ? &in_desc : | ||
2808 | NULL, 0, | ||
2809 | state->initialized ? NULL : | ||
2810 | &state->ctx_handle, &out_desc, | ||
2811 | &flags, 0); | ||
2812 | |||
2813 | state->initialized = 1; | ||
2814 | |||
2815 | if (in_buffers[1].BufferType == SECBUFFER_EXTRA) { | ||
2816 | memmove(state->in_buffer, | ||
2817 | state->in_buffer + (state->in_buffer_size - | ||
2818 | in_buffers[1].cbBuffer), | ||
2819 | in_buffers[1].cbBuffer); | ||
2820 | state->in_buffer_size = in_buffers[1].cbBuffer; | ||
2821 | } else if (status != SEC_E_INCOMPLETE_MESSAGE) { | ||
2822 | state->in_buffer_size = 0; | ||
2823 | } | ||
2824 | |||
2825 | switch (status) { | ||
2826 | case SEC_E_OK:{ | ||
2827 | if (out_buffers[0].cbBuffer > 0) { | ||
2828 | xwrite(state->ofd, out_buffers[0].pvBuffer, | ||
2829 | out_buffers[0].cbBuffer); | ||
2830 | FreeContextBuffer(out_buffers[0].pvBuffer); | ||
2831 | } | ||
2832 | goto Success; | ||
2833 | } | ||
2834 | case SEC_I_CONTINUE_NEEDED:{ | ||
2835 | xwrite(state->ofd, out_buffers[0].pvBuffer, | ||
2836 | out_buffers[0].cbBuffer); | ||
2837 | FreeContextBuffer(out_buffers[0].pvBuffer); | ||
2838 | break; | ||
2839 | } | ||
2840 | case SEC_I_INCOMPLETE_CREDENTIALS:{ | ||
2841 | // we don't support this | ||
2842 | bb_error_msg_and_die("schannel: client certificates not supported"); | ||
2843 | } | ||
2844 | case SEC_E_INCOMPLETE_MESSAGE:{ | ||
2845 | break; | ||
2846 | } | ||
2847 | default:{ | ||
2848 | bb_error_msg_and_die("schannel: handshake failed: (0x%08lx): %s", | ||
2849 | status, hresult_to_error_string(status)); | ||
2850 | } | ||
2851 | } | ||
2852 | |||
2853 | received = | ||
2854 | safe_read(state->ifd, state->in_buffer + state->in_buffer_size, | ||
2855 | sizeof(state->in_buffer) - state->in_buffer_size); | ||
2856 | if (received <= 0) { | ||
2857 | bb_error_msg_and_die("schannel: handshake read() failed"); | ||
2858 | } | ||
2859 | state->in_buffer_size += received; | ||
2860 | } | ||
2861 | |||
2862 | Success: | ||
2863 | QueryContextAttributes(&state->ctx_handle, SECPKG_ATTR_STREAM_SIZES, | ||
2864 | &state->stream_sizes); | ||
2865 | |||
2866 | //SecPkgContext_ConnectionInfo info; | ||
2867 | //QueryContextAttributes(&state->ctx_handle, SECPKG_ATTR_CONNECTION_INFO, | ||
2868 | // &info); | ||
2869 | // | ||
2870 | //fprintf(stderr, "TLS 1.%d\n", (((uint32_t)(8 * sizeof(unsigned long long) - __builtin_clzll((info.dwProtocol)) - 1)) - 7)/2); | ||
2871 | } | ||
2872 | |||
2873 | void FAST_FUNC tls_run_copy_loop(tls_state_t * tls, unsigned flags) { | ||
2874 | char buffer[65536]; | ||
2875 | |||
2876 | struct pollfd pfds[2]; | ||
2877 | |||
2878 | pfds[0].fd = STDIN_FILENO; | ||
2879 | pfds[0].events = POLLIN; | ||
2880 | pfds[1].fd = tls->ifd; | ||
2881 | pfds[1].events = POLLIN; | ||
2882 | |||
2883 | for (;;) { | ||
2884 | int nread; | ||
2885 | |||
2886 | if (safe_poll(pfds, 2, -1) < 0) | ||
2887 | bb_simple_perror_msg_and_die("poll"); | ||
2888 | |||
2889 | if (pfds[0].revents) { | ||
2890 | nread = safe_read(STDIN_FILENO, buffer, sizeof(buffer)); | ||
2891 | if (nread < 1) { | ||
2892 | pfds[0].fd = -1; | ||
2893 | tls_disconnect(tls); | ||
2894 | if (flags & TLSLOOP_EXIT_ON_LOCAL_EOF) | ||
2895 | break; | ||
2896 | } else { | ||
2897 | tls_write(tls, buffer, nread); | ||
2898 | } | ||
2899 | } | ||
2900 | if (pfds[1].revents) { | ||
2901 | nread = tls_read(tls, buffer, sizeof(buffer)); | ||
2902 | if (nread < 1) { | ||
2903 | tls_disconnect(tls); | ||
2904 | break; | ||
2905 | } | ||
2906 | xwrite(STDOUT_FILENO, buffer, nread); | ||
2907 | } | ||
2908 | } | ||
2909 | } | ||
2910 | #endif | ||