From 290d6993363c39f9ff3accd68a5285ae92c95229 Mon Sep 17 00:00:00 2001 From: Zhi Guan Date: Sun, 17 May 2026 11:44:43 +0800 Subject: [PATCH] Update TLS 1.3 KeyUpdate passed. --- include/gmssl/tls.h | 2 + src/debug.c | 2 +- src/gf128_arm64.c | 1 + src/tls.c | 11 ++ src/tls12.c | 5 + src/tls13.c | 317 +++++++++++++++++++++++++++++++------------ tools/tls13_client.c | 137 +++++++++++++------ tools/tls13_server.c | 127 +++++++++++------ 8 files changed, 437 insertions(+), 165 deletions(-) diff --git a/include/gmssl/tls.h b/include/gmssl/tls.h index 35790e33..703e0fe9 100644 --- a/include/gmssl/tls.h +++ b/include/gmssl/tls.h @@ -875,6 +875,7 @@ int tls_ctx_add_certificate_list_and_key(TLS_CTX *ctx, const char *chainfile, const uint8_t *entity_signed_certificate_timestamp_list, size_t entity_signed_certificate_timestamp_list_len, // optional const char *keyfile, const char *keypass); +int tls_ctx_set_key_update_seq_num_limit(TLS_CTX *ctx, size_t max_seq_num); @@ -1072,6 +1073,7 @@ typedef struct { const char *session_out; // KeyUpdate + int key_update; // 标志位,send之前看这个值,如果为1的话就先做keyUpdate size_t client_data_size; size_t server_data_size; diff --git a/src/debug.c b/src/debug.c index 48343032..b2dfde05 100644 --- a/src/debug.c +++ b/src/debug.c @@ -75,7 +75,7 @@ int format_bytes(FILE *fp, int format, int indent, const char *str, const uint8_ return 1; } for (i = 0; i < datalen; i++) { - fprintf(fp, "%02X", data[i]); + fprintf(fp, "%02x", data[i]); } fprintf(fp, "\n"); return 1; diff --git a/src/gf128_arm64.c b/src/gf128_arm64.c index 42b0ad67..28df802f 100644 --- a/src/gf128_arm64.c +++ b/src/gf128_arm64.c @@ -11,6 +11,7 @@ #include #include + = a0 * b0 + ((a0 + a1)*(b0 + b1) - a0*b0 - a1*b1) * x^64 + a1 * b1 * x^128 // this version is converted from the gf128_arm64.S by ChatGPT 4 // a little slower than the asm version diff --git a/src/tls.c b/src/tls.c index 1b8466e2..f62af17e 100644 --- a/src/tls.c +++ b/src/tls.c @@ -2736,6 +2736,17 @@ int tls_ctx_set_signature_algorithms(TLS_CTX *ctx, const int *sig_algs, size_t s return 1; } +int tls_ctx_set_key_update_seq_num_limit(TLS_CTX *ctx, size_t max_seq_num) +{ + if (!ctx) { + error_print(); + return -1; + } + ctx->key_update_seq_num_limit = max_seq_num; + return 1; +} + + int tls13_ctx_set_client_hello_key_exchanges_cnt(TLS_CTX *ctx, size_t cnt) { if (!ctx) { diff --git a/src/tls12.c b/src/tls12.c index 2f230fde..958dbfac 100644 --- a/src/tls12.c +++ b/src/tls12.c @@ -82,11 +82,16 @@ int tls_send_record(TLS_CONNECT *conn) while (left) { n = tls_socket_send(conn->sock, conn->record + conn->record_offset, left, 0); if (n < 0) { + + fprintf(stderr, "send() return %d\n", n); + fprintf(stderr, "send() errno %d\n", errno); + if (errno == EAGAIN && errno == EWOULDBLOCK) { return TLS_ERROR_SEND_AGAIN; } else if (errno == EINTR) { continue; } else { + fprintf(stderr, "%s %d: send() error: %s\n", __FILE__, __LINE__, strerror(errno)); error_print(); return -1; } diff --git a/src/tls13.c b/src/tls13.c index 955fd0c3..e5262db3 100644 --- a/src/tls13.c +++ b/src/tls13.c @@ -70,6 +70,9 @@ int tls13_padding_len_rand(size_t *padding_len) uint8_t val; rand_bytes(&val, 1); *padding_len = val % 128; + + + *padding_len = 0; return 1; } @@ -280,7 +283,6 @@ int tls13_record_decrypt(const BLOCK_CIPHER_KEY *key, const uint8_t iv[12], /* KeyUpate的流程 - 客户端发现需要KeyUpdate (可能是C->S 或者C <- S某个方向需要) 如果是自己方向的需要更新,或者对方需要更新,那么就一定要发送KeyUpdate 如果对方不需要更新,那么不要求对方更新 @@ -298,18 +300,28 @@ KeyUpate的流程 这里一个主要的状态判断是, 某一方在接收到对方的KeyUpdate请求后,是否响。 + +发送过程本身也是个状态机 + + + 判断发送方向的seq_num是否已经到达了上限,如果到达上限 + 构造KeyUpdate记录 + 加密KeyUpdate记录,并写入缓冲区 + 更新发送方向的key和seq_num + 发送缓冲区记录,或返回SEND_AGAIN + 构造AppData消息 + 加密AppData消息并写入缓冲区 + 发送缓冲区记录,或返回SEND_AGAIN */ int tls13_send(TLS_CONNECT *conn, const uint8_t *data, size_t datalen, size_t *sentlen) { + int ret = 1; int key_update = 0; - tls_trace("send {ApplicationData}\n"); - *sentlen = 0; - // 当前的发送缓冲区是空的,没有之前剩余的数据 if (!conn->recordlen) { const BLOCK_CIPHER_KEY *key; const uint8_t *iv; @@ -318,9 +330,11 @@ int tls13_send(TLS_CONNECT *conn, const uint8_t *data, size_t datalen, size_t *s size_t record_datalen; if (!data || !datalen) { + error_print(); return 0; } + // 这个应该放在后面 if (datalen > TLS_MAX_PLAINTEXT_SIZE) { datalen = TLS_MAX_PLAINTEXT_SIZE; } @@ -342,17 +356,105 @@ int tls13_send(TLS_CONNECT *conn, const uint8_t *data, size_t datalen, size_t *s //format_print(stderr, 0, 0, "\n"); } + + fprintf(stderr, "conn->key_update = %d\n", conn->key_update); + + format_bytes(stderr, 0, 0, "seq_num", seq_num, 8); + + + // check if KeyUpdate + if (GETU64(seq_num) >= conn->ctx->key_update_seq_num_limit) { + conn->key_update = 1; + } + fprintf(stderr, "conn->key_update = %d\n", conn->key_update); + + if (conn->key_update) { + + int ret; + + + tls_trace("send {KeyUpdate}\n"); + + + int request_update = 1; + + + // 这个显然是不对的,这里要根据请求方设置 + if (conn->is_client) { + ret = tls13_send_client_key_update(conn, request_update); + fprintf(stderr, "tls13_send_client_key_update ret = %d\n", ret); + } else { + ret = tls13_send_server_key_update(conn, request_update); + } + + + if (ret != 1) { + error_print(); + } + + conn->key_update = 0; + + return ret; + + + // 直接在这里面发送KeyUpdate + if (tls13_record_set_handshake_key_update(conn->plain_record, &conn->plain_recordlen, + request_update) != 1) { + error_print(); + return -1; + } + tls13_record_print(stderr, 0, 0, conn->plain_record, conn->plain_recordlen); + + + + + key_update = 1; + + + } else { + tls_trace("send {ApplicationData}\n"); + } + tls13_padding_len_rand(&padding_len); - // 这个其实不太好,最好是直接加密一个record,这样我们可以打印出record - if (tls13_gcm_encrypt(key, iv, - seq_num, TLS_record_application_data, data, datalen, padding_len, - conn->record + 5, &record_datalen) != 1) { - error_print(); - return -1; + if (key_update) { + if (tls13_gcm_encrypt(key, iv, + seq_num, TLS_record_handshake, + conn->plain_record + 5, conn->plain_recordlen - 5, padding_len, + conn->record + 5, &record_datalen) != 1) { + error_print(); + return -1; + } + + if (conn->is_client) { + tls13_update_client_application_keys(conn); + } else { + tls13_update_server_application_keys(conn); + } + + ret = TLS_ERROR_SEND_AGAIN; + + } else { + + if (datalen > 8) { + datalen = 8; + } + + format_bytes(stderr, 0, 0, "send hex", data, datalen); + + if (tls13_gcm_encrypt(key, iv, + seq_num, TLS_record_application_data, data, datalen, padding_len, + conn->record + 5, &record_datalen) != 1) { + error_print(); + return -1; + } + + tls_seq_num_incr(seq_num); + + ret = 1; + } - tls_seq_num_incr(seq_num); tls_record_set_type(conn->record, TLS_record_application_data); tls_record_set_protocol(conn->record, TLS_protocol_tls12); tls_record_set_data_length(conn->record, record_datalen); @@ -360,29 +462,13 @@ int tls13_send(TLS_CONNECT *conn, const uint8_t *data, size_t datalen, size_t *s conn->recordlen = 5 + record_datalen; conn->record_offset = 0; + // 需要记录密文对应的明文是什么,当完整的报文发送之后,这些信息要返回给调用方 //conn->plain_recordlen = datalen + 5; conn->sentlen = datalen; - tls13_record_print(stderr, 0, 0, conn->record, conn->recordlen); - - - /* - KeyUpdate有两个原因 - * 我们自己检查,应该KeyUpdate了,那么发送KeyUpdate并且要求对方也Update - * 对方要求KeyUpdate,那么我们只是通知对方,我方KeyUPdate,不要求对方再次Update - - */ - - // check if KeyUpdate - /* - // key_update_seq_num_limit 似乎还没有设置 - if (GETU64(seq_num) >= conn->ctx->key_update_seq_num_limit) { - key_update = 1; - } - */ } while (conn->recordlen) { @@ -390,7 +476,7 @@ int tls13_send(TLS_CONNECT *conn, const uint8_t *data, size_t datalen, size_t *s if ((n = tls_socket_send(conn->sock, conn->record + conn->record_offset, conn->recordlen, 0)) <= 0) { if (errno == EAGAIN || errno == EWOULDBLOCK) { - return EAGAIN; + return TLS_ERROR_SEND_AGAIN; } else { if (n == 0) { error_puts("TCP connection closed"); @@ -403,39 +489,16 @@ int tls13_send(TLS_CONNECT *conn, const uint8_t *data, size_t datalen, size_t *s conn->record_offset += n; } - /* - if (key_update) { - int ret; - if (conn->is_client) { - if ((ret = tls13_send_client_key_update(conn, 1)) <= 0) { - if (ret == TLS_ERROR_SEND_AGAIN) { - return ret; - } - } else { - error_print(); - return -1; - } + // 这里有一种可能是,用户输入的消息长度比较长,超出了我们的长度限制 - } else { - if ((ret = tls13_send_server_key_update(conn, 1)) <= 0) { - if (ret == TLS_ERROR_SEND_AGAIN) { - return ret; - } - } else { - error_print(); - return -1; - } - - - } - } - */ //*sentlen = conn->plain_recordlen - 5; *sentlen = conn->sentlen; - return 1; + + fprintf(stderr, "tls13_send last ret = %d\n", ret); + return ret; } int tls13_do_recv(TLS_CONNECT *conn) @@ -459,6 +522,10 @@ int tls13_do_recv(TLS_CONNECT *conn) case TLS_state_recv_record_header: while (conn->recordlen) { + + fprintf(stderr, "conn->record_offet = %zu\n", conn->record_offset); + fprintf(stderr, "len = %zu \n", conn->recordlen); + if ((n = tls_socket_recv(conn->sock, conn->record + conn->record_offset, conn->recordlen, 0)) <= 0) { if (errno == EAGAIN || errno == EWOULDBLOCK) { return TLS_ERROR_RECV_AGAIN; @@ -467,8 +534,13 @@ int tls13_do_recv(TLS_CONNECT *conn) return -1; } } + fprintf(stderr, "len = %zu %zu\n", conn->recordlen, n); + conn->recordlen -= n; conn->record_offset += n; + + format_bytes(stderr, 0, 0, "recv record", conn->record, conn->record_offset); + } if (tls_record_type(conn->record) != TLS_record_application_data) { error_print(); @@ -506,7 +578,9 @@ int tls13_do_recv(TLS_CONNECT *conn) conn->recordlen = tls_record_length(conn->record); - tls13_record_print(stderr, 0, 0, conn->record, conn->recordlen); + fprintf(stderr, "tls13_do_recv\n"); + + tls13_record_print(stderr, 0, 4, conn->record, conn->recordlen); if (conn->is_client) { @@ -536,12 +610,18 @@ int tls13_do_recv(TLS_CONNECT *conn) } tls_seq_num_incr(seq_num); - tls13_record_print(stderr, 0, 0, conn->plain_record, conn->plain_recordlen); + fprintf(stderr, " plain\n"); + tls13_record_print(stderr, 0, 4, conn->plain_record, conn->plain_recordlen); + switch (tls_record_type(conn->plain_record)) { case TLS_record_application_data: conn->data = conn->plain_record + 5; conn->datalen = conn->plain_recordlen - 5; + + + format_bytes(stderr, 0, 0, "recv record", conn->data, conn->datalen); + break; case TLS_record_handshake: @@ -572,8 +652,11 @@ int tls13_do_recv(TLS_CONNECT *conn) return -1; } - // 对方的密钥已经更新了,我方必须更新 - // 但是我方密钥是否更新(以及发送KeyUpdate通知呢?),要看当前密钥使用了多久 + // 如果对方要求KeyUpdate,并且也满足我方KeyUpdate的最低条件 + // 那么我们就设置key_update标志位 + // 下次发送的时候就启动KeyUpdate + + if (conn->is_client) { uint64_t seq_num; int ret; @@ -582,13 +665,9 @@ int tls13_do_recv(TLS_CONNECT *conn) seq_num = GETU64(conn->client_seq_num); - if (seq_num > 1 && update_requested) { - if ((ret = tls13_send_client_key_update(conn, 0)) <= 0) { - if (ret == TLS_ERROR_SEND_AGAIN) { - return ret; - } - } + if (seq_num > 2 && update_requested) { + conn->key_update = 1; } @@ -596,20 +675,14 @@ int tls13_do_recv(TLS_CONNECT *conn) uint64_t seq_num; int ret; + fprintf(stderr, "%%%%%%%%%%555 tls13_update_client_application_keys\n"); + tls13_update_client_application_keys(conn); seq_num = GETU64(conn->server_seq_num); - - if (seq_num > 1 && update_requested) { - if ((ret = tls13_send_server_key_update(conn, 0)) <= 0) { - if (ret == TLS_ERROR_SEND_AGAIN) { - return ret; - } else { - error_print(); - return -1; - } - } + if (seq_num > 2 && update_requested) { + conn->key_update = 1; } } @@ -654,7 +727,9 @@ int tls13_recv(TLS_CONNECT *conn, uint8_t *out, size_t outlen, size_t *recvlen) if (conn->datalen == 0) { int ret; if ((ret = tls13_do_recv(conn)) != 1) { - if (ret) error_print(); + if (ret != TLS_ERROR_RECV_AGAIN && ret != TLS_ERROR_SEND_AGAIN) { + error_print(); + } return ret; } } @@ -8313,6 +8388,17 @@ int tls13_update_server_application_keys(TLS_CONNECT *conn) } // 参数request_update应该根据当前状态设置 + + +/* +如果我方是首先发送KeyUpdate一方,那么默认设置要求对方也更新密钥 + + +如果我们接收到对方的要求,并且满足我方的一个最低限度,那么就设置key_update的标志位,下次send的时候就会启动更新 + + +*/ + int tls13_send_client_key_update(TLS_CONNECT *conn, int request_update) { int ret; @@ -8320,7 +8406,7 @@ int tls13_send_client_key_update(TLS_CONNECT *conn, int request_update) if (conn->recordlen == 0) { size_t padding_len = 0; - tls_trace("send {KeyUpdate}\n"); + tls_trace("send client {KeyUpdate}\n"); if (tls13_record_set_handshake_key_update(conn->plain_record, &conn->plain_recordlen, request_update) != 1) { @@ -8330,6 +8416,7 @@ int tls13_send_client_key_update(TLS_CONNECT *conn, int request_update) tls13_record_print(stderr, 0, 0, conn->plain_record, conn->plain_recordlen); tls13_padding_len_rand(&padding_len); + if (tls13_record_encrypt(&conn->client_write_key, conn->client_write_iv, conn->client_seq_num, conn->plain_record, conn->plain_recordlen, padding_len, conn->record, &conn->recordlen) != 1) { @@ -8337,15 +8424,57 @@ int tls13_send_client_key_update(TLS_CONNECT *conn, int request_update) return -1; } + // 这个很重要啊,但是record_encrypt没有设置这个值,这是很奇怪的 + // xxxxxxxx + conn->record_offset = 0; + + format_bytes(stderr, 0, 0, "KeyUpdate record", conn->record, conn->recordlen); + tls13_record_print(stderr, 0, 0, conn->record, conn->recordlen); + tls13_update_client_application_keys(conn); + } if ((ret = tls_send_record(conn)) != 1) { - if (ret != TLS_ERROR_SEND_AGAIN) { + if (ret != TLS_ERROR_SEND_AGAIN && ret != TLS_ERROR_RECV_AGAIN) { error_print(); } - return ret; } + + if (ret == 1) { + + // 首先我们在发送数据的时候,应该根据offset是否已经达到末尾来判断数据是否完全发送 + // 其次在记录已经完全发送之后,应该自动的清空recordlen, offset这个数据 + + conn->record_offset = 0; + conn->recordlen = 0; + } + + return ret; + + + + + while (conn->recordlen) { + tls_ret_t n; + + if ((n = tls_socket_send(conn->sock, conn->record + conn->record_offset, conn->recordlen, 0)) <= 0) { + if (errno == EAGAIN || errno == EWOULDBLOCK) { + return TLS_ERROR_SEND_AGAIN; + } else { + if (n == 0) { + error_puts("TCP connection closed"); + } + error_print(); + return -1; + } + } + conn->recordlen -= n; + conn->record_offset += n; + } + + + return 1; } @@ -8356,7 +8485,7 @@ int tls13_send_server_key_update(TLS_CONNECT *conn, int request_update) if (conn->recordlen == 0) { size_t padding_len = 0; - tls_trace("send {KeyUpdate}\n"); + tls_trace("send server {KeyUpdate}\n"); if (tls13_record_set_handshake_key_update(conn->plain_record, &conn->plain_recordlen, request_update) != 1) { @@ -8373,16 +8502,36 @@ int tls13_send_server_key_update(TLS_CONNECT *conn, int request_update) return -1; } + conn->record_offset = 0; + tls13_update_server_application_keys(conn); } + if ((ret = tls_send_record(conn)) != 1) { - if (ret != TLS_ERROR_SEND_AGAIN) { + if (ret != TLS_ERROR_SEND_AGAIN && ret != TLS_ERROR_RECV_AGAIN) { error_print(); } - return ret; } - return 1; + + if (ret == 1) { + + // 首先我们在发送数据的时候,应该根据offset是否已经达到末尾来判断数据是否完全发送 + // 其次在记录已经完全发送之后,应该自动的清空recordlen, offset这个数据 + + conn->record_offset = 0; + conn->recordlen = 0; + } + + return ret; + + + + + + + + } diff --git a/tools/tls13_client.c b/tools/tls13_client.c index 867aed8f..9e5d65ec 100644 --- a/tools/tls13_client.c +++ b/tools/tls13_client.c @@ -53,6 +53,7 @@ static const char *help = " -sess_in Load server's session ticket file\n" " -sess_out Save server's session ticket file\n" " -early_data file Send early data, -psk_ke and/or -psk_dhe_ke should be set\n" +" -key_update_seq_num num Send KeyUpdate handshake after sending/receiving records\n" " -post_handshake_auth Support post_handshake_auth\n" "\n" "CipherSuites\n" @@ -108,6 +109,9 @@ int tls13_client_main(int argc, char *argv[]) char buf[1024] = {0}; size_t len = sizeof(buf); char send_buf[1024] = {0}; + size_t sent_len = 0; + size_t sent_offset = 0; + char *sess_in = NULL; char *sess_out = NULL; @@ -153,8 +157,14 @@ int tls13_client_main(int argc, char *argv[]) int signature_algorithms_cert = 0; int status_request = 0; int signed_certificate_timestamp = 0; + + int key_update_seq_num = 0; + int post_handshake_auth = 0; + int send_again = 0; + + argc--; argv++; if (argc < 1) { @@ -285,6 +295,14 @@ int tls13_client_main(int argc, char *argv[]) error_print(); return -1; } + } else if (!strcmp(*argv, "-key_update_seq_num")) { + if (--argc < 1) goto bad; + key_update_seq_num = atoi(*(++argv)); + if (key_update_seq_num < 0) { + error_print(); + fprintf(stderr, "%s: invalid '-key_update_seq_num' value\n", prog); + return -1; + } } else { fprintf(stderr, "%s: invalid option '%s'\n", prog, *argv); return 1; @@ -381,8 +399,12 @@ bad: - - + if (key_update_seq_num > 0) { + if (tls_ctx_set_key_update_seq_num_limit(&ctx, key_update_seq_num) != 1) { + error_print(); + return -1; + } + } if (tls13_init(&conn, &ctx) != 1) { @@ -558,75 +580,112 @@ bad: for (;;) { - fd_set fds; + + fd_set fds_send; + fd_set fds_recv; + size_t sentlen; - - FD_ZERO(&fds); + FD_ZERO(&fds_send); + FD_ZERO(&fds_recv); // listen socket - FD_SET(conn.sock, &fds); + FD_SET(conn.sock, &fds_recv); // listen stdin - FD_SET(fileno(stdin), &fds); + FD_SET(fileno(stdin), &fds_recv); + if (sent_len > 0) { + FD_SET(conn.sock, &fds_send); + } + // 等待阻塞 if (select((int)(conn.sock + 1), // In WinSock2, select() ignore the this arg - &fds, NULL, NULL, NULL) < 0) { + &fds_recv, &fds_send, NULL, NULL) < 0) { fprintf(stderr, "%s: select failed\n", prog); goto end; } - /* - if (!fgets(send_buf, sizeof(send_buf), stdin)) { - if (feof(stdin)) { - tls_shutdown(&conn); - goto end; - } else { - continue; - } - } - if (tls13_send(&conn, (uint8_t *)send_buf, strlen(send_buf), &sentlen) != 1) { - fprintf(stderr, "%s: send error\n", prog); - goto end; - } - */ + // 读socket + if (FD_ISSET(conn.sock, &fds_recv)) { - - if (FD_ISSET(conn.sock, &fds)) { - for (;;) { - memset(buf, 0, sizeof(buf)); - if (tls13_recv(&conn, (uint8_t *)buf, sizeof(buf), &len) != 1) { + memset(buf, 0, sizeof(buf)); + if ((ret = tls13_recv(&conn, (uint8_t *)buf, sizeof(buf), &len)) != 1) { + if (ret == TLS_ERROR_SEND_AGAIN || ret == TLS_ERROR_RECV_AGAIN) { + continue; + } else { + error_print(); goto end; } - fwrite(buf, 1, len, stdout); - fflush(stdout); - - // FIXME: change tls13_recv API - if (conn.datalen == 0) { - break; - } } + fwrite(buf, 1, len, stdout); + fflush(stdout); + + + format_bytes(stderr, 0, 0, "tls13_recv return", buf, len); + + + // FIXME: change tls13_recv API + /* + if (conn.datalen == 0) { + error_print(); + break; + } + */ } - if (FD_ISSET(fileno(stdin), &fds)) { + // 读用户输入 + if (FD_ISSET(fileno(stdin), &fds_recv)) { + memset(send_buf, 0, sizeof(send_buf)); if (!fgets(send_buf, sizeof(send_buf), stdin)) { if (feof(stdin)) { + error_print(); + fprintf(stderr, "client shutdown\n"); tls_shutdown(&conn); goto end; } else { continue; } } - if (tls13_send(&conn, (uint8_t *)send_buf, strlen(send_buf), &sentlen) != 1) { - fprintf(stderr, "%s: send error\n", prog); - goto end; - } + sent_len = strlen(send_buf) + 1; + sent_offset = 0; + + fprintf(stderr, "###############################\n"); + fprintf(stderr, "sentlen = %zu\n", sentlen); + format_bytes(stderr, 0, 0, "send hex", send_buf, sent_len); + fprintf(stderr, "sent_len = %zu\n", sent_len); + fprintf(stderr, "sent_offset = %zu\n", sent_offset); } + + if (sent_len > 0 && FD_ISSET(conn.sock, &fds_send)) { + + + // tls13_send 会返回一个 -1 , 但是没有打印错误信息!!!! + if ((ret = tls13_send(&conn, (uint8_t *)send_buf + sent_offset, sent_len, &sentlen)) != 1) { + if (ret == TLS_ERROR_SEND_AGAIN || ret == TLS_ERROR_RECV_AGAIN) { + continue; + } else { + fprintf(stderr, "ret = %d\n", ret); + fprintf(stderr, "%s: send error\n", prog); + goto end; + } + } + + sent_offset += sentlen; + sent_len -= sentlen; + fprintf(stderr, "###############################\n"); + fprintf(stderr, "sentlen = %zu\n", sentlen); + fprintf(stderr, "sent_len = %zu\n", sent_len); + fprintf(stderr, "sent_offset = %zu\n", sent_offset); + } + + fprintf(stderr, "\n\n\n\n"); + + } end: diff --git a/tools/tls13_server.c b/tools/tls13_server.c index a7341516..01e86121 100644 --- a/tools/tls13_server.c +++ b/tools/tls13_server.c @@ -24,8 +24,10 @@ // psk_cipher_suite 和 cipher_suite 是冗余的 -// 现在我要尝试CertificateRequest -// + +// 重新思考一下,各个层次如何将各自的输入输出打印出来,特别是在record层 +// 每个报文包括密文和明文,应该将两者紧密连在一起,没有空格 +// 在报文层,只显示明文的16进制,但是在上层,应该显示明文的ASCII和HEX,能够看清楚消息 static const char *options = "[-port num] -cert file -key file -pass str [-cacert file]"; @@ -51,6 +53,7 @@ static const char *help = " -max_early_data_size num Set extension max_early_data_size\n" " -cert_request Client certificate request\n" " -cacert file CA certificate for client certificate verification\n" +" -key_update_seq_num num Send KeyUpdate handshake after sending/receiving records\n" "\n" " -cipher_suite options\n" " TLS_SM4_GCM_SM3 TLS 1.3\n" @@ -315,10 +318,14 @@ int tls13_server_main(int argc , char **argv) int sig_algs[4]; size_t sig_algs_cnt = 0; + int key_update_seq_num = 0; + + size_t i; + int cert_request = 0; char *cacertfile = NULL; @@ -453,6 +460,14 @@ int tls13_server_main(int argc , char **argv) return -1; } sig_algs[sig_algs_cnt++] = sig_alg; + } else if (!strcmp(*argv, "-key_update_seq_num")) { + if (--argc < 1) goto bad; + key_update_seq_num = atoi(*(++argv)); + if (key_update_seq_num < 0) { + error_print(); + fprintf(stderr, "%s: invalid '-key_update_seq_num' value\n", prog); + return -1; + } } else { fprintf(stderr, "%s: invalid option '%s'\n", prog, *argv); return 1; @@ -589,6 +604,12 @@ bad: } } + if (key_update_seq_num > 0) { + if (tls_ctx_set_key_update_seq_num_limit(&ctx, key_update_seq_num) != 1) { + error_print(); + return -1; + } + } if (tls_socket_create(&sock, AF_INET, SOCK_STREAM, 0) != 1) { fprintf(stderr, "%s: socket create error\n", prog); @@ -677,74 +698,98 @@ restart: format_string(stderr, 0, 0, "EarlyData", conn.early_data_buf, conn.early_data_len); } + size_t send_len = 0; + size_t send_offset = 0; + + + + // 如果客户端发送的数据比较长,会被切分为多个record + // 服务器在接收到record之后,必须做同步,就是每收到一个record必须返回一个record + // 也就是server必须有一个同步机制 for (;;) { + fd_set fds_recv; + + fd_set fds_send; // 只有在接收数据之后才需要设置 - fd_set fds; size_t sentlen; - FD_ZERO(&fds); + FD_ZERO(&fds_recv); + FD_ZERO(&fds_send); // listen socket - FD_SET(conn.sock, &fds); + FD_SET(conn.sock, &fds_recv); + + if (send_len > 0) { + FD_SET(conn.sock, &fds_send); + } - // 等待阻塞 if (select((int)(conn.sock + 1), // In WinSock2, select() ignore the this arg - &fds, NULL, NULL, NULL) < 0) { + &fds_recv, &fds_send, NULL, NULL) < 0) { fprintf(stderr, "%s: select failed\n", prog); goto end; } - if (FD_ISSET(conn.sock, &fds)) { - for (;;) { - memset(buf, 0, sizeof(buf)); - if (tls13_recv(&conn, (uint8_t *)buf, sizeof(buf), &len) != 1) { - goto end; - } - fwrite(buf, 1, len, stdout); - fflush(stdout); - - // FIXME: change tls13_recv API - if (conn.datalen == 0) { - break; - } - } - + if (send_len > 0 && FD_ISSET(conn.sock, &fds_send)) { fprintf(stderr, ">>>>>>>> send back\n"); - if (tls13_send(&conn, (uint8_t *)buf, len, &sentlen) != 1) { + + format_bytes(stderr, 0, 0, "tls13_send", buf + send_offset, send_len); + + + if ((ret = tls13_send(&conn, (uint8_t *)buf + send_offset, send_len, &sentlen)) != 1) { + if (ret == TLS_ERROR_SEND_AGAIN || ret == TLS_ERROR_RECV_AGAIN) { + continue; + } fprintf(stderr, "%s: send error\n", prog); goto end; } + + send_offset += sentlen; + send_len -= sentlen; + + fprintf(stderr, "---------------\n"); + + //memset(conn.record, 0, sizeof(conn.record)); + //memset(conn.plain_record, 0, sizeof(conn.plain_record)); } - } - for (;;) { + if (FD_ISSET(conn.sock, &fds_recv)) { - int rv; - size_t sentlen; + memset(buf, 0, sizeof(buf)); - do { - len = sizeof(buf); - if ((rv = tls13_recv(&conn, (uint8_t *)buf, sizeof(buf), &len)) != 1) { - if (rv < 0) fprintf(stderr, "%s: recv failure\n", prog); - else fprintf(stderr, "%s: Disconnected by remote\n", prog); - - //close(conn.sock); - tls_cleanup(&conn); - goto restart; + if ((ret = tls13_recv(&conn, (uint8_t *)buf, sizeof(buf), &len)) != 1) { + if (ret == TLS_ERROR_SEND_AGAIN || ret == TLS_ERROR_RECV_AGAIN) { + continue; + } + error_print(); + goto end; } - } while (!len); + fwrite(buf, 1, len, stdout); + fflush(stdout); - if (tls13_send(&conn, (uint8_t *)buf, len, &sentlen) != 1) { - fprintf(stderr, "%s: send failure, close connection\n", prog); - tls_socket_close(conn.sock); - goto end; + send_len = len; + send_offset = 0; + /* + // FIXME: change tls13_recv API + if (conn.datalen == 0) { + break; + } + */ } + + + + + + + + fprintf(stderr, "\n\n\n\n"); } + end: return ret; }