mirror of
https://github.com/guanzhi/GmSSL.git
synced 2026-08-07 12:33:39 +08:00
Add more options to TLS
add `-get` and `-quiet` option to `tlcp_client`
This commit is contained in:
@@ -684,6 +684,8 @@ typedef struct {
|
|||||||
SM2_KEY signkey;
|
SM2_KEY signkey;
|
||||||
SM2_KEY kenckey;
|
SM2_KEY kenckey;
|
||||||
int verify_depth;
|
int verify_depth;
|
||||||
|
|
||||||
|
int quiet;
|
||||||
} TLS_CTX;
|
} TLS_CTX;
|
||||||
|
|
||||||
int tls_ctx_init(TLS_CTX *ctx, int protocol, int is_client);
|
int tls_ctx_init(TLS_CTX *ctx, int protocol, int is_client);
|
||||||
@@ -751,6 +753,7 @@ typedef struct {
|
|||||||
BLOCK_CIPHER_KEY client_write_key;
|
BLOCK_CIPHER_KEY client_write_key;
|
||||||
BLOCK_CIPHER_KEY server_write_key;
|
BLOCK_CIPHER_KEY server_write_key;
|
||||||
|
|
||||||
|
int quiet;
|
||||||
} TLS_CONNECT;
|
} TLS_CONNECT;
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
34
src/tlcp.c
34
src/tlcp.c
@@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright 2014-2023 The GmSSL Project. All Rights Reserved.
|
* Copyright 2014-2024 The GmSSL Project. All Rights Reserved.
|
||||||
*
|
*
|
||||||
* Licensed under the Apache License, Version 2.0 (the License); you may
|
* Licensed under the Apache License, Version 2.0 (the License); you may
|
||||||
* not use this file except in compliance with the License.
|
* not use this file except in compliance with the License.
|
||||||
@@ -28,15 +28,6 @@
|
|||||||
static const int tlcp_ciphers[] = { TLS_cipher_ecc_sm4_cbc_sm3 };
|
static const int tlcp_ciphers[] = { TLS_cipher_ecc_sm4_cbc_sm3 };
|
||||||
static const size_t tlcp_ciphers_count = sizeof(tlcp_ciphers)/sizeof(tlcp_ciphers[0]);
|
static const size_t tlcp_ciphers_count = sizeof(tlcp_ciphers)/sizeof(tlcp_ciphers[0]);
|
||||||
|
|
||||||
void printbyte(uint8_t *ptr, int len, char *name) {
|
|
||||||
fprintf(stderr, "%s", name);
|
|
||||||
for (int i = 0; i < len; i++) {
|
|
||||||
if (i % 16 == 0)
|
|
||||||
fprintf(stderr, "\n");
|
|
||||||
fprintf(stderr, "0x%02X ", ptr[i]);
|
|
||||||
}
|
|
||||||
fprintf(stderr, "\n");
|
|
||||||
}
|
|
||||||
|
|
||||||
int tlcp_record_print(FILE *fp, const uint8_t *record, size_t recordlen, int format, int indent)
|
int tlcp_record_print(FILE *fp, const uint8_t *record, size_t recordlen, int format, int indent)
|
||||||
{
|
{
|
||||||
@@ -46,6 +37,19 @@ int tlcp_record_print(FILE *fp, const uint8_t *record, size_t recordlen, int fo
|
|||||||
return tls_record_print(fp, record, recordlen, format, indent);
|
return tls_record_print(fp, record, recordlen, format, indent);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
select (KeyExchangeAlgorithm) {
|
||||||
|
case ECC:
|
||||||
|
digitall-signed struct {
|
||||||
|
opaque client_random[32];
|
||||||
|
opaque server_random[32];
|
||||||
|
opaque ASN1.Cert<1..2^24-1>;
|
||||||
|
} signed_params;
|
||||||
|
}
|
||||||
|
} ServerKeyExchange;
|
||||||
|
|
||||||
|
-- in TLCP 1.1, the `signed_params` is DER signature encoded in uint16array
|
||||||
|
*/
|
||||||
int tlcp_record_set_handshake_server_key_exchange_pke(uint8_t *record, size_t *recordlen,
|
int tlcp_record_set_handshake_server_key_exchange_pke(uint8_t *record, size_t *recordlen,
|
||||||
const uint8_t *sig, size_t siglen)
|
const uint8_t *sig, size_t siglen)
|
||||||
{
|
{
|
||||||
@@ -66,8 +70,6 @@ int tlcp_record_set_handshake_server_key_exchange_pke(uint8_t *record, size_t *r
|
|||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
p = tls_handshake_data(tls_record_data(record));
|
p = tls_handshake_data(tls_record_data(record));
|
||||||
// 注意TLCP的ServerKeyExchange中的签名值需要封装在uint16array中
|
|
||||||
// 但是CertificateVerify中直接装载签名值DER
|
|
||||||
tls_uint16array_to_bytes(sig, siglen, &p, &len);
|
tls_uint16array_to_bytes(sig, siglen, &p, &len);
|
||||||
tls_record_set_handshake(record, recordlen, type, NULL, len);
|
tls_record_set_handshake(record, recordlen, type, NULL, len);
|
||||||
return 1;
|
return 1;
|
||||||
@@ -556,7 +558,9 @@ int tlcp_do_connect(TLS_CONNECT *conn)
|
|||||||
tls_send_alert(conn, TLS_alert_decrypt_error);
|
tls_send_alert(conn, TLS_alert_decrypt_error);
|
||||||
goto end;
|
goto end;
|
||||||
}
|
}
|
||||||
fprintf(stderr, "Connection established!\n");
|
|
||||||
|
if (!conn->quiet)
|
||||||
|
fprintf(stderr, "Connection established!\n");
|
||||||
|
|
||||||
|
|
||||||
conn->protocol = TLS_protocol_tlcp;
|
conn->protocol = TLS_protocol_tlcp;
|
||||||
@@ -996,7 +1000,9 @@ int tlcp_do_accept(TLS_CONNECT *conn)
|
|||||||
|
|
||||||
conn->protocol = TLS_protocol_tlcp;
|
conn->protocol = TLS_protocol_tlcp;
|
||||||
|
|
||||||
fprintf(stderr, "Connection Established!\n\n");
|
if (!conn->quiet)
|
||||||
|
fprintf(stderr, "Connection Established!\n\n");
|
||||||
|
|
||||||
ret = 1;
|
ret = 1;
|
||||||
|
|
||||||
end:
|
end:
|
||||||
|
|||||||
@@ -2298,6 +2298,8 @@ int tls_init(TLS_CONNECT *conn, const TLS_CTX *ctx)
|
|||||||
conn->sign_key = ctx->signkey;
|
conn->sign_key = ctx->signkey;
|
||||||
conn->kenc_key = ctx->kenckey;
|
conn->kenc_key = ctx->kenckey;
|
||||||
|
|
||||||
|
conn->quiet = ctx->quiet;
|
||||||
|
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -630,8 +630,9 @@ int tls12_do_connect(TLS_CONNECT *conn)
|
|||||||
tls_send_alert(conn, TLS_alert_decrypt_error);
|
tls_send_alert(conn, TLS_alert_decrypt_error);
|
||||||
goto end;
|
goto end;
|
||||||
}
|
}
|
||||||
fprintf(stderr, "Connection established!\n");
|
|
||||||
|
|
||||||
|
if (!conn->quiet)
|
||||||
|
fprintf(stderr, "Connection established!\n");
|
||||||
|
|
||||||
conn->protocol = conn->protocol;
|
conn->protocol = conn->protocol;
|
||||||
conn->cipher_suite = cipher_suite;
|
conn->cipher_suite = cipher_suite;
|
||||||
@@ -1061,7 +1062,9 @@ int tls12_do_accept(TLS_CONNECT *conn)
|
|||||||
|
|
||||||
conn->protocol = conn->protocol;
|
conn->protocol = conn->protocol;
|
||||||
|
|
||||||
fprintf(stderr, "Connection Established!\n\n");
|
if (!conn->quiet)
|
||||||
|
fprintf(stderr, "Connection Established!\n\n");
|
||||||
|
|
||||||
ret = 1;
|
ret = 1;
|
||||||
|
|
||||||
end:
|
end:
|
||||||
|
|||||||
11
src/tls13.c
11
src/tls13.c
@@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright 2014-2023 The GmSSL Project. All Rights Reserved.
|
* Copyright 2014-2024 The GmSSL Project. All Rights Reserved.
|
||||||
*
|
*
|
||||||
* Licensed under the Apache License, Version 2.0 (the License); you may
|
* Licensed under the Apache License, Version 2.0 (the License); you may
|
||||||
* not use this file except in compliance with the License.
|
* not use this file except in compliance with the License.
|
||||||
@@ -1887,7 +1887,10 @@ int tls13_do_connect(TLS_CONNECT *conn)
|
|||||||
format_bytes(stderr, 0, 4, "client_write_iv", conn->client_write_iv, 12);
|
format_bytes(stderr, 0, 4, "client_write_iv", conn->client_write_iv, 12);
|
||||||
format_print(stderr, 0, 0, "\n");
|
format_print(stderr, 0, 0, "\n");
|
||||||
*/
|
*/
|
||||||
fprintf(stderr, "Connection established\n");
|
|
||||||
|
if (!conn->quiet)
|
||||||
|
fprintf(stderr, "Connection established\n");
|
||||||
|
|
||||||
ret = 1;
|
ret = 1;
|
||||||
|
|
||||||
end:
|
end:
|
||||||
@@ -2354,7 +2357,9 @@ int tls13_do_accept(TLS_CONNECT *conn)
|
|||||||
format_print(stderr, 0, 0, "\n");
|
format_print(stderr, 0, 0, "\n");
|
||||||
*/
|
*/
|
||||||
|
|
||||||
fprintf(stderr, "Connection Established!\n\n");
|
if (!conn->quiet)
|
||||||
|
fprintf(stderr, "Connection Established!\n\n");
|
||||||
|
|
||||||
ret = 1;
|
ret = 1;
|
||||||
end:
|
end:
|
||||||
gmssl_secure_clear(&server_ecdhe, sizeof(server_ecdhe));
|
gmssl_secure_clear(&server_ecdhe, sizeof(server_ecdhe));
|
||||||
|
|||||||
@@ -344,7 +344,23 @@ int tls_pre_master_secret_print(FILE *fp, const uint8_t pre_master_secret[48], i
|
|||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
// supported_versions 的格式还受到 handshake_type 影响
|
/*
|
||||||
|
* SupportedVersions Extension (only defined in TLS 1.3)
|
||||||
|
*
|
||||||
|
* In ClientHello:
|
||||||
|
* struct {
|
||||||
|
* ProtocolVersion versions<2..254>;
|
||||||
|
* } SupportedVersions;
|
||||||
|
*
|
||||||
|
* In ServerHello:
|
||||||
|
* struct {
|
||||||
|
* ProtocolVersion selected_version;
|
||||||
|
* } SupportedVersions;
|
||||||
|
*
|
||||||
|
|
||||||
|
这个函数需要一个参数表示扩展是在ClientHello还是在ServerHello中
|
||||||
|
|
||||||
|
*/
|
||||||
int tls_extension_print(FILE *fp, int type, const uint8_t *data, size_t datalen, int format, int indent)
|
int tls_extension_print(FILE *fp, int type, const uint8_t *data, size_t datalen, int format, int indent)
|
||||||
{
|
{
|
||||||
const uint8_t *p;
|
const uint8_t *p;
|
||||||
@@ -354,6 +370,7 @@ int tls_extension_print(FILE *fp, int type, const uint8_t *data, size_t datalen,
|
|||||||
indent += 4;
|
indent += 4;
|
||||||
|
|
||||||
switch (type) {
|
switch (type) {
|
||||||
|
// FIXME: 不支持ServerHello
|
||||||
case TLS_extension_supported_versions:
|
case TLS_extension_supported_versions:
|
||||||
if (tls_uint16array_from_bytes(&p, &len, &data, &datalen) != 1
|
if (tls_uint16array_from_bytes(&p, &len, &data, &datalen) != 1
|
||||||
|| tls_length_is_zero(datalen) != 1
|
|| tls_length_is_zero(datalen) != 1
|
||||||
@@ -846,6 +863,7 @@ int tls_finished_print(FILE *fp, const uint8_t *data, size_t datalen, int format
|
|||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// FIXME: 应该将这个函数融合到 tls_handshake_print 中
|
||||||
int tls13_handshake_print(FILE *fp, int fmt, int ind, const uint8_t *handshake, size_t handshake_len)
|
int tls13_handshake_print(FILE *fp, int fmt, int ind, const uint8_t *handshake, size_t handshake_len)
|
||||||
{
|
{
|
||||||
const uint8_t *p = handshake;
|
const uint8_t *p = handshake;
|
||||||
@@ -1052,6 +1070,7 @@ int tls13_record_print(FILE *fp, int format, int indent, const uint8_t *record,
|
|||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// FIXME: 需要根据RFC来考虑这个函数的参数,从底向上逐步修改每个函数的接口参数
|
||||||
|
|
||||||
// 仅从record数据是不能判断这个record是TLS 1.2还是TLS 1.3
|
// 仅从record数据是不能判断这个record是TLS 1.2还是TLS 1.3
|
||||||
// 不同协议上,同名的握手消息,其格式也是不一样的。这真是太恶心了!!!!
|
// 不同协议上,同名的握手消息,其格式也是不一样的。这真是太恶心了!!!!
|
||||||
@@ -1130,34 +1149,6 @@ int tls_record_print(FILE *fp, const uint8_t *record, size_t recordlen, int for
|
|||||||
|
|
||||||
fprintf(fp, "\n");
|
fprintf(fp, "\n");
|
||||||
return 1;
|
return 1;
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
int tls_secrets_print(FILE *fp,
|
int tls_secrets_print(FILE *fp,
|
||||||
@@ -1168,6 +1159,9 @@ int tls_secrets_print(FILE *fp,
|
|||||||
int format, int indent)
|
int format, int indent)
|
||||||
{
|
{
|
||||||
// 应该检查一下key_block_len的值,判断是否支持,或者算法选择, 或者要求输入一个cipher_suite参数
|
// 应该检查一下key_block_len的值,判断是否支持,或者算法选择, 或者要求输入一个cipher_suite参数
|
||||||
|
// 这个函数不支持GCM模式套件,使用GCM模式时key_block_len更短
|
||||||
|
// 可以考虑通过key_block_len判断CBC还是GCM,或者在参数上增加cipher_suite
|
||||||
|
// FIXME: 如果增加了GCM套件,需要更新这个函数
|
||||||
format_bytes(stderr, format, indent, "pre_master_secret", pre_master_secret, pre_master_secret_len);
|
format_bytes(stderr, format, indent, "pre_master_secret", pre_master_secret, pre_master_secret_len);
|
||||||
format_bytes(stderr, format, indent, "client_random", client_random, 32);
|
format_bytes(stderr, format, indent, "client_random", client_random, 32);
|
||||||
format_bytes(stderr, format, indent, "server_random", server_random, 32);
|
format_bytes(stderr, format, indent, "server_random", server_random, 32);
|
||||||
|
|||||||
@@ -13,17 +13,19 @@
|
|||||||
#include <string.h>
|
#include <string.h>
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
#include <gmssl/tls.h>
|
#include <gmssl/tls.h>
|
||||||
|
#include <gmssl/x509.h>
|
||||||
#include <gmssl/error.h>
|
#include <gmssl/error.h>
|
||||||
|
|
||||||
|
|
||||||
|
#define TIMEOUT_SECONDS 1
|
||||||
|
|
||||||
static int client_ciphers[] = { TLS_cipher_ecc_sm4_cbc_sm3, };
|
static int client_ciphers[] = { TLS_cipher_ecc_sm4_cbc_sm3, };
|
||||||
|
|
||||||
static const char *http_get =
|
|
||||||
"GET / HTTP/1.1\r\n"
|
|
||||||
"Hostname: aaa\r\n"
|
|
||||||
"\r\n\r\n";
|
|
||||||
|
|
||||||
static const char *options = "-host str [-port num] [-cacert file] [-cert file -key file -pass str]";
|
static const char *options = "-host str [-port num] [-cacert file] [-cert file -key file -pass str]"
|
||||||
|
" -quiet"
|
||||||
|
" -get [path]"
|
||||||
|
" [-outcerts file]";
|
||||||
|
|
||||||
int tlcp_client_main(int argc, char *argv[])
|
int tlcp_client_main(int argc, char *argv[])
|
||||||
{
|
{
|
||||||
@@ -35,6 +37,9 @@ int tlcp_client_main(int argc, char *argv[])
|
|||||||
char *certfile = NULL;
|
char *certfile = NULL;
|
||||||
char *keyfile = NULL;
|
char *keyfile = NULL;
|
||||||
char *pass = NULL;
|
char *pass = NULL;
|
||||||
|
char *get = NULL;
|
||||||
|
char *outcertsfile = NULL;
|
||||||
|
int quiet = 0;
|
||||||
struct hostent *hp;
|
struct hostent *hp;
|
||||||
struct sockaddr_in server;
|
struct sockaddr_in server;
|
||||||
tls_socket_t sock;
|
tls_socket_t sock;
|
||||||
@@ -44,6 +49,7 @@ int tlcp_client_main(int argc, char *argv[])
|
|||||||
char buf[1024] = {0};
|
char buf[1024] = {0};
|
||||||
size_t len = sizeof(buf);
|
size_t len = sizeof(buf);
|
||||||
char send_buf[1024] = {0};
|
char send_buf[1024] = {0};
|
||||||
|
size_t sentlen;
|
||||||
|
|
||||||
argc--;
|
argc--;
|
||||||
argv++;
|
argv++;
|
||||||
@@ -73,6 +79,14 @@ int tlcp_client_main(int argc, char *argv[])
|
|||||||
} else if (!strcmp(*argv, "-pass")) {
|
} else if (!strcmp(*argv, "-pass")) {
|
||||||
if (--argc < 1) goto bad;
|
if (--argc < 1) goto bad;
|
||||||
pass = *(++argv);
|
pass = *(++argv);
|
||||||
|
} else if (!strcmp(*argv, "-get")) {
|
||||||
|
if (--argc < 1) goto bad;
|
||||||
|
get = *(++argv);
|
||||||
|
} else if (!strcmp(*argv, "-outcerts")) {
|
||||||
|
if (--argc < 1) goto bad;
|
||||||
|
outcertsfile = *(++argv);
|
||||||
|
} else if (!strcmp(*argv, "-quiet")) {
|
||||||
|
quiet = 1;
|
||||||
} else {
|
} else {
|
||||||
fprintf(stderr, "%s: invalid option '%s'\n", prog, *argv);
|
fprintf(stderr, "%s: invalid option '%s'\n", prog, *argv);
|
||||||
return 1;
|
return 1;
|
||||||
@@ -135,6 +149,9 @@ bad:
|
|||||||
goto end;
|
goto end;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
if (quiet || get) {
|
||||||
|
ctx.quiet = 1;
|
||||||
|
}
|
||||||
|
|
||||||
if (tls_init(&conn, &ctx) != 1
|
if (tls_init(&conn, &ctx) != 1
|
||||||
|| tls_set_socket(&conn, sock) != 1
|
|| tls_set_socket(&conn, sock) != 1
|
||||||
@@ -143,9 +160,60 @@ bad:
|
|||||||
goto end;
|
goto end;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (outcertsfile) {
|
||||||
|
FILE *outcertsfp;
|
||||||
|
if (!(outcertsfp = fopen(outcertsfile, "wb"))) {
|
||||||
|
fprintf(stderr, "%s: open '%s' failure\n", prog, outcertsfile);
|
||||||
|
perror("fopen");
|
||||||
|
goto end;
|
||||||
|
}
|
||||||
|
if (x509_certs_to_pem(conn.server_certs, conn.server_certs_len, outcertsfp) != 1) {
|
||||||
|
fprintf(stderr, "%s: x509_certs_to_pem error\n", prog);
|
||||||
|
fclose(outcertsfp);
|
||||||
|
goto end;
|
||||||
|
}
|
||||||
|
fclose(outcertsfp);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (get) {
|
||||||
|
struct timeval timeout;
|
||||||
|
timeout.tv_sec = TIMEOUT_SECONDS;
|
||||||
|
timeout.tv_usec = 0;
|
||||||
|
|
||||||
|
snprintf(buf, sizeof(buf), "GET %s HTTP/1.1\r\nHost: %s\r\n\r\n", get, host);
|
||||||
|
|
||||||
|
if (tls_send(&conn, (uint8_t *)buf, strlen(buf), &len) != 1) {
|
||||||
|
fprintf(stderr, "%s: send error\n", prog);
|
||||||
|
goto end;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (setsockopt(conn.sock, SOL_SOCKET, SO_RCVTIMEO, (const char*)&timeout, sizeof(timeout)) != 0) {
|
||||||
|
perror("setsockopt");
|
||||||
|
fprintf(stderr, "%s: set socket timeout error\n", prog);
|
||||||
|
goto end;
|
||||||
|
}
|
||||||
|
|
||||||
|
for (;;) {
|
||||||
|
int ret;
|
||||||
|
if ((ret = tls_recv(&conn, (uint8_t *)buf, sizeof(buf), &len)) != 1) {
|
||||||
|
if (ret == 0) {
|
||||||
|
fprintf(stderr, "%s: TLCP connection is closed by remote host\n", prog);
|
||||||
|
} else if (ret != -EAGAIN) {
|
||||||
|
fprintf(stderr, "%s: recv error\n", prog);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
fwrite(buf, 1, len, stdout);
|
||||||
|
fflush(stdout);
|
||||||
|
}
|
||||||
|
|
||||||
|
tls_shutdown(&conn);
|
||||||
|
goto end;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
for (;;) {
|
for (;;) {
|
||||||
fd_set fds;
|
fd_set fds;
|
||||||
size_t sentlen;
|
|
||||||
|
|
||||||
if (!fgets(send_buf, sizeof(send_buf), stdin)) {
|
if (!fgets(send_buf, sizeof(send_buf), stdin)) {
|
||||||
if (feof(stdin)) {
|
if (feof(stdin)) {
|
||||||
|
|||||||
Reference in New Issue
Block a user