diff options
Diffstat (limited to 'networking/tls.c')
-rw-r--r-- | networking/tls.c | 225 |
1 files changed, 188 insertions, 37 deletions
diff --git a/networking/tls.c b/networking/tls.c index 69c81b558..b0a4f7e75 100644 --- a/networking/tls.c +++ b/networking/tls.c | |||
@@ -1,7 +1,7 @@ | |||
1 | /* | 1 | /* |
2 | * Licensed under GPLv2, see file LICENSE in this source tree. | ||
3 | * | ||
4 | * Copyright (C) 2017 Denys Vlasenko | 2 | * Copyright (C) 2017 Denys Vlasenko |
3 | * | ||
4 | * Licensed under GPLv2, see file LICENSE in this source tree. | ||
5 | */ | 5 | */ |
6 | //config:config TLS | 6 | //config:config TLS |
7 | //config: bool "tls (debugging)" | 7 | //config: bool "tls (debugging)" |
@@ -10,6 +10,11 @@ | |||
10 | //applet:IF_TLS(APPLET(tls, BB_DIR_USR_BIN, BB_SUID_DROP)) | 10 | //applet:IF_TLS(APPLET(tls, BB_DIR_USR_BIN, BB_SUID_DROP)) |
11 | 11 | ||
12 | //kbuild:lib-$(CONFIG_TLS) += tls.o | 12 | //kbuild:lib-$(CONFIG_TLS) += tls.o |
13 | //kbuild:lib-$(CONFIG_TLS) += tls_pstm.o | ||
14 | //kbuild:lib-$(CONFIG_TLS) += tls_pstm_montgomery_reduce.o | ||
15 | //kbuild:lib-$(CONFIG_TLS) += tls_pstm_mul_comba.o | ||
16 | //kbuild:lib-$(CONFIG_TLS) += tls_pstm_sqr_comba.o | ||
17 | //kbuild:lib-$(CONFIG_TLS) += tls_rsa.o | ||
13 | ////kbuild:lib-$(CONFIG_TLS) += tls_ciphers.o | 18 | ////kbuild:lib-$(CONFIG_TLS) += tls_ciphers.o |
14 | ////kbuild:lib-$(CONFIG_TLS) += tls_aes.o | 19 | ////kbuild:lib-$(CONFIG_TLS) += tls_aes.o |
15 | ////kbuild:lib-$(CONFIG_TLS) += tls_aes_gcm.o | 20 | ////kbuild:lib-$(CONFIG_TLS) += tls_aes_gcm.o |
@@ -18,9 +23,7 @@ | |||
18 | //usage: "HOST[:PORT]" | 23 | //usage: "HOST[:PORT]" |
19 | //usage:#define tls_full_usage "\n\n" | 24 | //usage:#define tls_full_usage "\n\n" |
20 | 25 | ||
21 | #include "libbb.h" | 26 | #include "tls.h" |
22 | //#include "tls_cryptoapi.h" | ||
23 | //#include "tls_ciphers.h" | ||
24 | 27 | ||
25 | #if 1 | 28 | #if 1 |
26 | # define dbg(...) fprintf(stderr, __VA_ARGS__) | 29 | # define dbg(...) fprintf(stderr, __VA_ARGS__) |
@@ -28,23 +31,26 @@ | |||
28 | # define dbg(...) ((void)0) | 31 | # define dbg(...) ((void)0) |
29 | #endif | 32 | #endif |
30 | 33 | ||
31 | #define RECORD_TYPE_CHANGE_CIPHER_SPEC 20 | 34 | #define RECORD_TYPE_CHANGE_CIPHER_SPEC 20 |
32 | #define RECORD_TYPE_ALERT 21 | 35 | #define RECORD_TYPE_ALERT 21 |
33 | #define RECORD_TYPE_HANDSHAKE 22 | 36 | #define RECORD_TYPE_HANDSHAKE 22 |
34 | #define RECORD_TYPE_APPLICATION_DATA 23 | 37 | #define RECORD_TYPE_APPLICATION_DATA 23 |
35 | 38 | ||
36 | #define HANDSHAKE_HELLO_REQUEST 0 | 39 | #define HANDSHAKE_HELLO_REQUEST 0 |
37 | #define HANDSHAKE_CLIENT_HELLO 1 | 40 | #define HANDSHAKE_CLIENT_HELLO 1 |
38 | #define HANDSHAKE_SERVER_HELLO 2 | 41 | #define HANDSHAKE_SERVER_HELLO 2 |
39 | #define HANDSHAKE_HELLO_VERIFY_REQUEST 3 | 42 | #define HANDSHAKE_HELLO_VERIFY_REQUEST 3 |
40 | #define HANDSHAKE_NEW_SESSION_TICKET 4 | 43 | #define HANDSHAKE_NEW_SESSION_TICKET 4 |
41 | #define HANDSHAKE_CERTIFICATE 11 | 44 | #define HANDSHAKE_CERTIFICATE 11 |
42 | #define HANDSHAKE_SERVER_KEY_EXCHANGE 12 | 45 | #define HANDSHAKE_SERVER_KEY_EXCHANGE 12 |
43 | #define HANDSHAKE_CERTIFICATE_REQUEST 13 | 46 | #define HANDSHAKE_CERTIFICATE_REQUEST 13 |
44 | #define HANDSHAKE_SERVER_HELLO_DONE 14 | 47 | #define HANDSHAKE_SERVER_HELLO_DONE 14 |
45 | #define HANDSHAKE_CERTIFICATE_VERIFY 15 | 48 | #define HANDSHAKE_CERTIFICATE_VERIFY 15 |
46 | #define HANDSHAKE_CLIENT_KEY_EXCHANGE 16 | 49 | #define HANDSHAKE_CLIENT_KEY_EXCHANGE 16 |
47 | #define HANDSHAKE_FINISHED 20 | 50 | #define HANDSHAKE_FINISHED 20 |
51 | |||
52 | #define SSL_HS_RANDOM_SIZE 32 | ||
53 | #define SSL_HS_RSA_PREMASTER_SIZE 48 | ||
48 | 54 | ||
49 | #define SSL_NULL_WITH_NULL_NULL 0x0000 | 55 | #define SSL_NULL_WITH_NULL_NULL 0x0000 |
50 | #define SSL_RSA_WITH_NULL_MD5 0x0001 | 56 | #define SSL_RSA_WITH_NULL_MD5 0x0001 |
@@ -112,6 +118,7 @@ | |||
112 | //TLS 1.2 | 118 | //TLS 1.2 |
113 | #define TLS_MAJ 3 | 119 | #define TLS_MAJ 3 |
114 | #define TLS_MIN 3 | 120 | #define TLS_MIN 3 |
121 | //#define CIPHER_ID TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA // ok, recvs SERVER_KEY_EXCHANGE *** matrixssl uses this on my box | ||
115 | //#define CIPHER_ID TLS_RSA_WITH_AES_256_CBC_SHA256 // ok, no SERVER_KEY_EXCHANGE | 122 | //#define CIPHER_ID TLS_RSA_WITH_AES_256_CBC_SHA256 // ok, no SERVER_KEY_EXCHANGE |
116 | // All GCMs: | 123 | // All GCMs: |
117 | //#define CIPHER_ID TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384 // SSL_ALERT_HANDSHAKE_FAILURE | 124 | //#define CIPHER_ID TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384 // SSL_ALERT_HANDSHAKE_FAILURE |
@@ -123,9 +130,9 @@ | |||
123 | //#define CIPHER_ID TLS_ECDH_RSA_WITH_AES_256_GCM_SHA384 | 130 | //#define CIPHER_ID TLS_ECDH_RSA_WITH_AES_256_GCM_SHA384 |
124 | //#define CIPHER_ID TLS_ECDH_RSA_WITH_AES_128_GCM_SHA256 // SSL_ALERT_HANDSHAKE_FAILURE | 131 | //#define CIPHER_ID TLS_ECDH_RSA_WITH_AES_128_GCM_SHA256 // SSL_ALERT_HANDSHAKE_FAILURE |
125 | //#define CIPHER_ID TLS_RSA_WITH_AES_256_GCM_SHA384 // ok, no SERVER_KEY_EXCHANGE | 132 | //#define CIPHER_ID TLS_RSA_WITH_AES_256_GCM_SHA384 // ok, no SERVER_KEY_EXCHANGE |
126 | #define CIPHER_ID TLS_RSA_WITH_AES_128_GCM_SHA256 // ok, no SERVER_KEY_EXCHANGE | 133 | #define CIPHER_ID TLS_RSA_WITH_AES_128_GCM_SHA256 // ok, no SERVER_KEY_EXCHANGE *** select this? |
127 | //#define CIPHER_ID TLS_DH_anon_WITH_AES_256_CBC_SHA // SSL_ALERT_HANDSHAKE_FAILURE | 134 | //#define CIPHER_ID TLS_DH_anon_WITH_AES_256_CBC_SHA // SSL_ALERT_HANDSHAKE_FAILURE |
128 | // (tested b/c this one doesn't req server certs... no luck) | 135 | //^^^^^^^^^^^^^^^^^^^^^^^ (tested b/c this one doesn't req server certs... no luck) |
129 | //test TLS_RSA_WITH_AES_128_CBC_SHA, in tls 1.2 it's mandated to be always supported | 136 | //test TLS_RSA_WITH_AES_128_CBC_SHA, in tls 1.2 it's mandated to be always supported |
130 | 137 | ||
131 | struct record_hdr { | 138 | struct record_hdr { |
@@ -137,8 +144,7 @@ struct record_hdr { | |||
137 | typedef struct tls_state { | 144 | typedef struct tls_state { |
138 | int fd; | 145 | int fd; |
139 | 146 | ||
140 | uint8_t *pubkey; | 147 | psRsaKey_t server_rsa_pub_key; |
141 | int pubkey_len; | ||
142 | 148 | ||
143 | // RFC 5246 | 149 | // RFC 5246 |
144 | // |6.2.1. Fragmentation | 150 | // |6.2.1. Fragmentation |
@@ -170,6 +176,12 @@ typedef struct tls_state { | |||
170 | uint8_t inbuf[18*1024]; | 176 | uint8_t inbuf[18*1024]; |
171 | } tls_state_t; | 177 | } tls_state_t; |
172 | 178 | ||
179 | void tls_get_random(void *buf, unsigned len) | ||
180 | { | ||
181 | if (len != open_read_close("/dev/urandom", buf, len)) | ||
182 | xfunc_die(); | ||
183 | } | ||
184 | |||
173 | static | 185 | static |
174 | tls_state_t *new_tls_state(void) | 186 | tls_state_t *new_tls_state(void) |
175 | { | 187 | { |
@@ -286,7 +298,7 @@ static void send_client_hello(tls_state_t *tls) | |||
286 | hello.len24_lo = (sizeof(hello) - sizeof(hello.xhdr) - 4); | 298 | hello.len24_lo = (sizeof(hello) - sizeof(hello.xhdr) - 4); |
287 | hello.proto_maj = TLS_MAJ; | 299 | hello.proto_maj = TLS_MAJ; |
288 | hello.proto_min = TLS_MIN; | 300 | hello.proto_min = TLS_MIN; |
289 | open_read_close("/dev/urandom", hello.rand32, sizeof(hello.rand32)); | 301 | tls_get_random(hello.rand32, sizeof(hello.rand32)); |
290 | //hello.session_id_len = 0; | 302 | //hello.session_id_len = 0; |
291 | //hello.cipherid_len16_hi = 0; | 303 | //hello.cipherid_len16_hi = 0; |
292 | hello.cipherid_len16_lo = 2 * 1; | 304 | hello.cipherid_len16_lo = 2 * 1; |
@@ -407,7 +419,18 @@ static uint8_t *skip_der_item(uint8_t *der, uint8_t *end) | |||
407 | return new_der; | 419 | return new_der; |
408 | } | 420 | } |
409 | 421 | ||
410 | static void *find_key_in_der_cert(int *key_len, uint8_t *der, int len) | 422 | static void der_binary_to_pstm(pstm_int *pstm_n, uint8_t *der, uint8_t *end) |
423 | { | ||
424 | uint8_t *bin_ptr; | ||
425 | unsigned len = get_der_len(&bin_ptr, der, end); | ||
426 | |||
427 | dbg("binary bytes:%u, first:0x%02x\n", len, bin_ptr[0]); | ||
428 | pstm_init_for_read_unsigned_bin(/*pool:*/ NULL, pstm_n, len); | ||
429 | pstm_read_unsigned_bin(pstm_n, bin_ptr, len); | ||
430 | //return bin + len; | ||
431 | } | ||
432 | |||
433 | static void find_key_in_der_cert(tls_state_t *tls, uint8_t *der, int len) | ||
411 | { | 434 | { |
412 | /* Certificate is a DER-encoded data structure. Each DER element has a length, | 435 | /* Certificate is a DER-encoded data structure. Each DER element has a length, |
413 | * which makes it easy to skip over large compound elements of any complexity | 436 | * which makes it easy to skip over large compound elements of any complexity |
@@ -504,19 +527,43 @@ static void *find_key_in_der_cert(int *key_len, uint8_t *der, int len) | |||
504 | der = skip_der_item(der, end); /* validity */ | 527 | der = skip_der_item(der, end); /* validity */ |
505 | der = skip_der_item(der, end); /* subject */ | 528 | der = skip_der_item(der, end); /* subject */ |
506 | 529 | ||
507 | /* enter "subjectPublicKeyInfo" */ | 530 | /* enter subjectPublicKeyInfo */ |
508 | der = enter_der_item(der, &end); | 531 | der = enter_der_item(der, &end); |
509 | 532 | { /* check subjectPublicKeyInfo.algorithm */ | |
510 | /* skip "subjectPublicKeyInfo.algorithm" */ | 533 | static const uint8_t expected[] = { |
534 | 0x30,0x0d, // SEQ 13 bytes | ||
535 | 0x06,0x09, 0x2a,0x86,0x48,0x86,0xf7,0x0d,0x01,0x01,0x01, // OID RSA_KEY_ALG 42.134.72.134.247.13.1.1.1 | ||
536 | //0x05,0x00, // NULL | ||
537 | }; | ||
538 | if (memcmp(der, expected, sizeof(expected)) != 0) | ||
539 | bb_error_msg_and_die("not RSA key"); | ||
540 | } | ||
541 | /* skip subjectPublicKeyInfo.algorithm */ | ||
511 | der = skip_der_item(der, end); | 542 | der = skip_der_item(der, end); |
512 | /* enter "subjectPublicKeyInfo.publicKey" */ | 543 | /* enter subjectPublicKeyInfo.publicKey */ |
513 | // die_if_not_this_der_type(der, end, 0x03); /* must be BITSTRING */ | 544 | // die_if_not_this_der_type(der, end, 0x03); /* must be BITSTRING */ |
514 | der = enter_der_item(der, &end); | 545 | der = enter_der_item(der, &end); |
515 | 546 | ||
516 | /* return a copy */ | 547 | /* parse RSA key: */ |
517 | *key_len = end - der; | 548 | //based on getAsnRsaPubKey(), pkcs1ParsePrivBin() is also of note |
518 | dbg("copying key bytes:%u, first:0x%02x\n", *key_len, der[0]); | 549 | dbg("key bytes:%u, first:0x%02x\n", (int)(end - der), der[0]); |
519 | return xmemdup(der, *key_len); | 550 | if (end - der < 14) xfunc_die(); |
551 | /* example format: | ||
552 | * ignore bits: 00 | ||
553 | * SEQ 0x018a/394 bytes: 3082018a | ||
554 | * INTEGER 0x0181/385 bytes (modulus): 02820181 XX...XXX | ||
555 | * INTEGER 3 bytes (exponent): 0203 010001 | ||
556 | */ | ||
557 | if (*der != 0) /* "ignore bits", should be 0 */ | ||
558 | xfunc_die(); | ||
559 | der++; | ||
560 | der = enter_der_item(der, &end); /* enter SEQ */ | ||
561 | //memset(tls->server_rsa_pub_key, 0, sizeof(tls->server_rsa_pub_key)); | ||
562 | der_binary_to_pstm(&tls->server_rsa_pub_key.N, der, end); /* modulus */ | ||
563 | der = skip_der_item(der, end); | ||
564 | der_binary_to_pstm(&tls->server_rsa_pub_key.e, der, end); /* exponent */ | ||
565 | tls->server_rsa_pub_key.size = pstm_unsigned_bin_size(&tls->server_rsa_pub_key.N); | ||
566 | dbg("server_rsa_pub_key.size:%d\n", tls->server_rsa_pub_key.size); | ||
520 | } | 567 | } |
521 | 568 | ||
522 | static void get_server_cert_or_die(tls_state_t *tls) | 569 | static void get_server_cert_or_die(tls_state_t *tls) |
@@ -553,7 +600,107 @@ static void get_server_cert_or_die(tls_state_t *tls) | |||
553 | len = len1; | 600 | len = len1; |
554 | 601 | ||
555 | if (len) | 602 | if (len) |
556 | tls->pubkey = find_key_in_der_cert(&tls->pubkey_len, certbuf + 10, len); | 603 | find_key_in_der_cert(tls, certbuf + 10, len); |
604 | } | ||
605 | |||
606 | static void send_client_key_exchange(tls_state_t *tls) | ||
607 | { | ||
608 | #if 0 //matrixssl code snippets: | ||
609 | int32 csRsaEncryptPub(psPool_t *pool, psPubKey_t *key, | ||
610 | unsigned char *in, uint32 inlen, unsigned char *out, uint32 outlen, | ||
611 | void *data) | ||
612 | { | ||
613 | psAssert(key->type == PS_RSA); | ||
614 | return psRsaEncryptPub(pool, (psRsaKey_t*)key->key, in, inlen, out, outlen, | ||
615 | data); | ||
616 | } | ||
617 | ... | ||
618 | /* pkaAfter.user is buffer len */ | ||
619 | if ((rc = csRsaEncryptPub(pka->pool, &ssl->sec.cert->publicKey, | ||
620 | ssl->sec.premaster, ssl->sec.premasterSize, pka->outbuf, | ||
621 | pka->user, pka->data)) < 0) { | ||
622 | if (rc == PS_PENDING) { | ||
623 | /* For these ClientKeyExchange paths, we do want to come | ||
624 | back through nowDoCkePka for a double pass so each | ||
625 | case can manage its own pkaAfter and to make sure | ||
626 | psX509FreeCert and sslCreateKeys() are hit below. */ | ||
627 | return rc; | ||
628 | } | ||
629 | psTraceIntInfo("csRsaEncryptPub in CKE failed %d\n", rc); | ||
630 | return MATRIXSSL_ERROR; | ||
631 | } | ||
632 | /* RSA closed the pool on second pass */ | ||
633 | pka->pool = NULL; | ||
634 | clearPkaAfter(ssl); | ||
635 | ... | ||
636 | #ifdef USE_RSA_CIPHER_SUITE | ||
637 | /* | ||
638 | Standard RSA suite | ||
639 | */ | ||
640 | ssl->sec.premasterSize = SSL_HS_RSA_PREMASTER_SIZE; | ||
641 | ssl->sec.premaster = psMalloc(ssl->hsPool, | ||
642 | SSL_HS_RSA_PREMASTER_SIZE); | ||
643 | if (ssl->sec.premaster == NULL) { | ||
644 | return SSL_MEM_ERROR; | ||
645 | } | ||
646 | |||
647 | ssl->sec.premaster[0] = ssl->reqMajVer; | ||
648 | ssl->sec.premaster[1] = ssl->reqMinVer; | ||
649 | if (matrixCryptoGetPrngData(ssl->sec.premaster + 2, | ||
650 | SSL_HS_RSA_PREMASTER_SIZE - 2, ssl->userPtr) < 0) { | ||
651 | return MATRIXSSL_ERROR; | ||
652 | } | ||
653 | |||
654 | /* Shedule RSA encryption. Put tmp pool under control of After */ | ||
655 | pkaAfter->type = PKA_AFTER_RSA_ENCRYPT; | ||
656 | pkaAfter->outbuf = c; | ||
657 | pkaAfter->data = pkiData; | ||
658 | pkaAfter->pool = pkiPool; | ||
659 | pkaAfter->user = (uint32)(end - c); /* Available space */ | ||
660 | |||
661 | c += keyLen; | ||
662 | #endif | ||
663 | #endif // 0 | ||
664 | |||
665 | struct client_key_exchange { | ||
666 | struct record_hdr xhdr; | ||
667 | uint8_t type; | ||
668 | uint8_t len24_hi, len24_mid, len24_lo; | ||
669 | uint8_t keylen16_hi, keylen16_lo; /* exist for RSA, but not for some other key types */ | ||
670 | //had a bug when had no keylen: we: | ||
671 | //write(3, "\x16\x03\x03\x01\x84\x10\x00\x01\x80\xXX\xXX\xXX\xXX\xXX\xXX...", 393) = 393 | ||
672 | //openssl: | ||
673 | //write to 0xe9a090 [0xf9ac20] (395 bytes => 395 (0x18B)) | ||
674 | //0000 - 16 03 03 01 86 10 00 01 -82 01 80 xx xx xx xx xx | ||
675 | uint8_t key[384]; // size?? | ||
676 | }; | ||
677 | struct client_key_exchange record; | ||
678 | uint8_t premaster[SSL_HS_RSA_PREMASTER_SIZE]; | ||
679 | |||
680 | memset(&record, 0, sizeof(record)); | ||
681 | record.xhdr.type = RECORD_TYPE_HANDSHAKE; | ||
682 | record.xhdr.proto_maj = TLS_MAJ; | ||
683 | record.xhdr.proto_min = TLS_MIN; | ||
684 | record.xhdr.len16_hi = (sizeof(record) - sizeof(record.xhdr)) >> 8; | ||
685 | record.xhdr.len16_lo = (sizeof(record) - sizeof(record.xhdr)) & 0xff; | ||
686 | record.type = HANDSHAKE_CLIENT_KEY_EXCHANGE; | ||
687 | //record.len24_hi = 0; | ||
688 | record.len24_mid = (sizeof(record) - sizeof(record.xhdr) - 4) >> 8; | ||
689 | record.len24_lo = (sizeof(record) - sizeof(record.xhdr) - 4) & 0xff; | ||
690 | record.keylen16_hi = (sizeof(record) - sizeof(record.xhdr) - 6) >> 8; | ||
691 | record.keylen16_lo = (sizeof(record) - sizeof(record.xhdr) - 6) & 0xff; | ||
692 | |||
693 | tls_get_random(premaster, sizeof(premaster)); | ||
694 | premaster[0] = TLS_MAJ; | ||
695 | premaster[1] = TLS_MIN; | ||
696 | psRsaEncryptPub(/*pool:*/ NULL, | ||
697 | /* psRsaKey_t* */ &tls->server_rsa_pub_key, | ||
698 | premaster, /*inlen:*/ sizeof(premaster), | ||
699 | record.key, sizeof(record.key), | ||
700 | data_param_ignored | ||
701 | ); | ||
702 | |||
703 | xwrite(tls->fd, &record, sizeof(record)); | ||
557 | } | 704 | } |
558 | 705 | ||
559 | static void tls_handshake(tls_state_t *tls) | 706 | static void tls_handshake(tls_state_t *tls) |
@@ -614,6 +761,8 @@ static void tls_handshake(tls_state_t *tls) | |||
614 | // 459 bytes: | 761 | // 459 bytes: |
615 | // 0c 00|01|c7 03|00|17|41|04|87|94|2e|2f|68|d0|c9|f4|97|a8|2d|ef|ed|67|ea|c6|f3|b3|56|47|5d|27|b6|bd|ee|70|25|30|5e|b0|8e|f6|21|5a... | 762 | // 0c 00|01|c7 03|00|17|41|04|87|94|2e|2f|68|d0|c9|f4|97|a8|2d|ef|ed|67|ea|c6|f3|b3|56|47|5d|27|b6|bd|ee|70|25|30|5e|b0|8e|f6|21|5a... |
616 | //SvKey len=455^ | 763 | //SvKey len=455^ |
764 | // with TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA: 461 bytes: | ||
765 | // 0c 00|01|c9 03|00|17|41|04|cd|9b|b4|29|1f|f6|b0|c2|84|82|7f|29|6a|47|4e|ec|87|0b|c1|9c|69|e1|f8|c6|d0|53|e9|27|90|a5|c8|02|15|75... | ||
617 | dbg("got SERVER_KEY_EXCHANGE\n"); | 766 | dbg("got SERVER_KEY_EXCHANGE\n"); |
618 | len = xread_tls_block(tls); | 767 | len = xread_tls_block(tls); |
619 | break; | 768 | break; |
@@ -624,6 +773,8 @@ static void tls_handshake(tls_state_t *tls) | |||
624 | case HANDSHAKE_SERVER_HELLO_DONE: | 773 | case HANDSHAKE_SERVER_HELLO_DONE: |
625 | // 0e 000000 (len:0) | 774 | // 0e 000000 (len:0) |
626 | dbg("got SERVER_HELLO_DONE\n"); | 775 | dbg("got SERVER_HELLO_DONE\n"); |
776 | send_client_key_exchange(tls); | ||
777 | len = xread_tls_block(tls); | ||
627 | break; | 778 | break; |
628 | default: | 779 | default: |
629 | tls_error_die(tls); | 780 | tls_error_die(tls); |