mirror of
https://github.com/guanzhi/GmSSL.git
synced 2026-06-20 03:44:15 +08:00
Add renegotiation_info and SCSV support
This commit is contained in:
@@ -901,6 +901,10 @@ typedef struct {
|
|||||||
// 66. client_id (TLCP only)
|
// 66. client_id (TLCP only)
|
||||||
int client_id;
|
int client_id;
|
||||||
|
|
||||||
|
// 65281. renegotiation_info (TLS 1.2 only)
|
||||||
|
int renegotiation_info;
|
||||||
|
int empty_renegotiation_info_scsv;
|
||||||
|
|
||||||
} TLS_CTX;
|
} TLS_CTX;
|
||||||
|
|
||||||
|
|
||||||
@@ -1264,6 +1268,9 @@ typedef struct {
|
|||||||
// 66. client_id (TLCP only)
|
// 66. client_id (TLCP only)
|
||||||
int client_id;
|
int client_id;
|
||||||
|
|
||||||
|
// 65281. renegotiation_info (TLS 1.2 only)
|
||||||
|
int secure_renegotiation;
|
||||||
|
|
||||||
} TLS_CONNECT;
|
} TLS_CONNECT;
|
||||||
|
|
||||||
|
|
||||||
@@ -1782,6 +1789,10 @@ int tls_server_name_from_bytes(const uint8_t **host_name, size_t *host_name_len,
|
|||||||
const uint8_t *ext_data, size_t ext_datalen);
|
const uint8_t *ext_data, size_t ext_datalen);
|
||||||
int tls_server_name_print(FILE *fp, int fmt, int ind, const uint8_t *ext_data, size_t ext_datalen);
|
int tls_server_name_print(FILE *fp, int fmt, int ind, const uint8_t *ext_data, size_t ext_datalen);
|
||||||
|
|
||||||
|
// 65281. renegotiation_info (TLS 1.2 only)
|
||||||
|
int tls12_ctx_set_renegotiation_info(TLS_CTX *ctx, int enable);
|
||||||
|
int tls12_ctx_set_empty_renegotiation_info_scsv(TLS_CTX *ctx, int enable);
|
||||||
|
|
||||||
// 16. application_layer_protocol_negotiation
|
// 16. application_layer_protocol_negotiation
|
||||||
int tls_ctx_set_application_layer_protocol_negotiation(TLS_CTX *ctx,
|
int tls_ctx_set_application_layer_protocol_negotiation(TLS_CTX *ctx,
|
||||||
char *protocols[], size_t protocols_cnt);
|
char *protocols[], size_t protocols_cnt);
|
||||||
|
|||||||
161
src/tls12.c
161
src/tls12.c
@@ -888,6 +888,57 @@ int tls_handshake_init(TLS_CONNECT *conn)
|
|||||||
const int ec_point_formats[] = { TLS_point_uncompressed };
|
const int ec_point_formats[] = { TLS_point_uncompressed };
|
||||||
size_t ec_point_formats_cnt = sizeof(ec_point_formats)/sizeof(ec_point_formats[0]);
|
size_t ec_point_formats_cnt = sizeof(ec_point_formats)/sizeof(ec_point_formats[0]);
|
||||||
|
|
||||||
|
int tls12_ctx_set_renegotiation_info(TLS_CTX *ctx, int enable)
|
||||||
|
{
|
||||||
|
if (!ctx || ctx->protocol != TLS_protocol_tls12) {
|
||||||
|
error_print();
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
ctx->renegotiation_info = enable ? 1 : 0;
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
int tls12_ctx_set_empty_renegotiation_info_scsv(TLS_CTX *ctx, int enable)
|
||||||
|
{
|
||||||
|
if (!ctx || ctx->protocol != TLS_protocol_tls12) {
|
||||||
|
error_print();
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
ctx->empty_renegotiation_info_scsv = enable ? 1 : 0;
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int tls12_renegotiation_info_ext_is_empty(const uint8_t *ext_data, size_t ext_datalen)
|
||||||
|
{
|
||||||
|
const uint8_t *renegotiated_connection;
|
||||||
|
size_t renegotiated_connection_len;
|
||||||
|
|
||||||
|
if (tls_uint8array_from_bytes(&renegotiated_connection, &renegotiated_connection_len,
|
||||||
|
&ext_data, &ext_datalen) != 1
|
||||||
|
|| tls_length_is_zero(ext_datalen) != 1) {
|
||||||
|
error_print();
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
return renegotiated_connection_len == 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int tls12_cipher_suites_include_empty_renegotiation_info_scsv(
|
||||||
|
const uint8_t *cipher_suites, size_t cipher_suites_len)
|
||||||
|
{
|
||||||
|
while (cipher_suites_len) {
|
||||||
|
uint16_t cipher_suite;
|
||||||
|
|
||||||
|
if (tls_uint16_from_bytes(&cipher_suite, &cipher_suites, &cipher_suites_len) != 1) {
|
||||||
|
error_print();
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
if (cipher_suite == TLS_cipher_empty_renegotiation_info_scsv) {
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
// 有可能需要支持SNI
|
// 有可能需要支持SNI
|
||||||
@@ -900,6 +951,9 @@ int tls_send_client_hello(TLS_CONNECT *conn)
|
|||||||
uint8_t exts[TLS_MAX_EXTENSIONS_SIZE];
|
uint8_t exts[TLS_MAX_EXTENSIONS_SIZE];
|
||||||
uint8_t *pexts = exts;
|
uint8_t *pexts = exts;
|
||||||
size_t extslen = 0;
|
size_t extslen = 0;
|
||||||
|
int cipher_suites[TLS_MAX_CIPHER_SUITES_COUNT + 1];
|
||||||
|
const int *client_cipher_suites = conn->ctx->cipher_suites;
|
||||||
|
size_t client_cipher_suites_cnt = conn->ctx->cipher_suites_cnt;
|
||||||
|
|
||||||
tls_trace("send ClientHello\n");
|
tls_trace("send ClientHello\n");
|
||||||
|
|
||||||
@@ -943,9 +997,33 @@ int tls_send_client_hello(TLS_CONNECT *conn)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// renegotiation_info
|
||||||
|
if (conn->ctx->renegotiation_info) {
|
||||||
|
uint8_t ext_data[1] = { 0 };
|
||||||
|
|
||||||
|
if (conn->ctx->empty_renegotiation_info_scsv) {
|
||||||
|
error_print();
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
if (tls_ext_to_bytes(TLS_extension_renegotiation_info,
|
||||||
|
ext_data, sizeof(ext_data), &pexts, &extslen) != 1) {
|
||||||
|
error_print();
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// TLS_EMPTY_RENEGOTIATION_INFO_SCSV
|
||||||
|
if (conn->ctx->empty_renegotiation_info_scsv) {
|
||||||
|
memcpy(cipher_suites, conn->ctx->cipher_suites,
|
||||||
|
conn->ctx->cipher_suites_cnt * sizeof(conn->ctx->cipher_suites[0]));
|
||||||
|
cipher_suites[conn->ctx->cipher_suites_cnt] = TLS_cipher_empty_renegotiation_info_scsv;
|
||||||
|
client_cipher_suites = cipher_suites;
|
||||||
|
client_cipher_suites_cnt = conn->ctx->cipher_suites_cnt + 1;
|
||||||
|
}
|
||||||
|
|
||||||
if (tls_record_set_handshake_client_hello(conn->record, &conn->recordlen,
|
if (tls_record_set_handshake_client_hello(conn->record, &conn->recordlen,
|
||||||
conn->protocol, conn->client_random, NULL, 0,
|
conn->protocol, conn->client_random, NULL, 0,
|
||||||
conn->ctx->cipher_suites, conn->ctx->cipher_suites_cnt,
|
client_cipher_suites, client_cipher_suites_cnt,
|
||||||
exts, extslen) != 1) {
|
exts, extslen) != 1) {
|
||||||
error_print();
|
error_print();
|
||||||
return -1;
|
return -1;
|
||||||
@@ -1315,6 +1393,9 @@ int tls_recv_client_hello(TLS_CONNECT *conn)
|
|||||||
size_t signature_algorithms_cert_len = 0;
|
size_t signature_algorithms_cert_len = 0;
|
||||||
const uint8_t *server_name = NULL;
|
const uint8_t *server_name = NULL;
|
||||||
size_t server_name_len = 0;
|
size_t server_name_len = 0;
|
||||||
|
const uint8_t *renegotiation_info = NULL;
|
||||||
|
size_t renegotiation_info_len = 0;
|
||||||
|
int empty_renegotiation_info_scsv = 0;
|
||||||
int common_cipher_suites[TLS_MAX_CIPHER_SUITES_COUNT];
|
int common_cipher_suites[TLS_MAX_CIPHER_SUITES_COUNT];
|
||||||
size_t common_cipher_suites_cnt = 0;
|
size_t common_cipher_suites_cnt = 0;
|
||||||
int common_supported_groups[32];
|
int common_supported_groups[32];
|
||||||
@@ -1388,6 +1469,7 @@ int tls_recv_client_hello(TLS_CONNECT *conn)
|
|||||||
case TLS_extension_signature_algorithms:
|
case TLS_extension_signature_algorithms:
|
||||||
case TLS_extension_signature_algorithms_cert:
|
case TLS_extension_signature_algorithms_cert:
|
||||||
case TLS_extension_server_name:
|
case TLS_extension_server_name:
|
||||||
|
case TLS_extension_renegotiation_info:
|
||||||
if (!ext_data) {
|
if (!ext_data) {
|
||||||
error_print();
|
error_print();
|
||||||
tls_send_alert(conn, TLS_alert_decode_error);
|
tls_send_alert(conn, TLS_alert_decode_error);
|
||||||
@@ -1442,11 +1524,50 @@ int tls_recv_client_hello(TLS_CONNECT *conn)
|
|||||||
server_name = ext_data;
|
server_name = ext_data;
|
||||||
server_name_len = ext_datalen;
|
server_name_len = ext_datalen;
|
||||||
break;
|
break;
|
||||||
|
case TLS_extension_renegotiation_info:
|
||||||
|
if (renegotiation_info) {
|
||||||
|
error_print();
|
||||||
|
tls_send_alert(conn, TLS_alert_illegal_parameter);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
renegotiation_info = ext_data;
|
||||||
|
renegotiation_info_len = ext_datalen;
|
||||||
|
break;
|
||||||
default:
|
default:
|
||||||
warning_print();
|
warning_print();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if ((ret = tls12_cipher_suites_include_empty_renegotiation_info_scsv(
|
||||||
|
cipher_suites, cipher_suites_len)) < 0) {
|
||||||
|
error_print();
|
||||||
|
tls_send_alert(conn, TLS_alert_decode_error);
|
||||||
|
return -1;
|
||||||
|
} else if (ret == 1) {
|
||||||
|
empty_renegotiation_info_scsv = 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (renegotiation_info && empty_renegotiation_info_scsv) {
|
||||||
|
error_print();
|
||||||
|
tls_send_alert(conn, TLS_alert_handshake_failure);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
if (renegotiation_info) {
|
||||||
|
if ((ret = tls12_renegotiation_info_ext_is_empty(
|
||||||
|
renegotiation_info, renegotiation_info_len)) < 0) {
|
||||||
|
error_print();
|
||||||
|
tls_send_alert(conn, TLS_alert_decode_error);
|
||||||
|
return -1;
|
||||||
|
} else if (ret == 0) {
|
||||||
|
error_print();
|
||||||
|
tls_send_alert(conn, TLS_alert_illegal_parameter);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (conn->ctx->renegotiation_info && (renegotiation_info || empty_renegotiation_info_scsv)) {
|
||||||
|
conn->secure_renegotiation = 1;
|
||||||
|
}
|
||||||
|
|
||||||
if (ec_point_formats) {
|
if (ec_point_formats) {
|
||||||
if ((ret = tls_ec_point_formats_support_uncompressed(ec_point_formats, ec_point_formats_len)) < 0) {
|
if ((ret = tls_ec_point_formats_support_uncompressed(ec_point_formats, ec_point_formats_len)) < 0) {
|
||||||
error_print();
|
error_print();
|
||||||
@@ -1631,6 +1752,17 @@ int tls_send_server_hello(TLS_CONNECT *conn)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// renegotiation_info
|
||||||
|
if (conn->secure_renegotiation) {
|
||||||
|
uint8_t ext_data[1] = { 0 };
|
||||||
|
|
||||||
|
if (tls_ext_to_bytes(TLS_extension_renegotiation_info,
|
||||||
|
ext_data, sizeof(ext_data), &pexts, &extslen) != 1) {
|
||||||
|
error_print();
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if (tls_record_set_handshake_server_hello(conn->record, &conn->recordlen,
|
if (tls_record_set_handshake_server_hello(conn->record, &conn->recordlen,
|
||||||
conn->protocol, conn->server_random, NULL, 0,
|
conn->protocol, conn->server_random, NULL, 0,
|
||||||
conn->cipher_suite,
|
conn->cipher_suite,
|
||||||
@@ -1679,6 +1811,7 @@ int tls_recv_server_hello(TLS_CONNECT *conn)
|
|||||||
const uint8_t *ec_point_formats = NULL;
|
const uint8_t *ec_point_formats = NULL;
|
||||||
size_t ec_point_formats_len = 0;
|
size_t ec_point_formats_len = 0;
|
||||||
int server_name = 0;
|
int server_name = 0;
|
||||||
|
int renegotiation_info = 0;
|
||||||
|
|
||||||
tls_trace("recv ServerHello\n");
|
tls_trace("recv ServerHello\n");
|
||||||
|
|
||||||
@@ -1770,6 +1903,25 @@ int tls_recv_server_hello(TLS_CONNECT *conn)
|
|||||||
}
|
}
|
||||||
server_name = 1;
|
server_name = 1;
|
||||||
break;
|
break;
|
||||||
|
case TLS_extension_renegotiation_info:
|
||||||
|
if ((!conn->ctx->renegotiation_info && !conn->ctx->empty_renegotiation_info_scsv)
|
||||||
|
|| renegotiation_info) {
|
||||||
|
error_print();
|
||||||
|
tls_send_alert(conn, TLS_alert_illegal_parameter);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
if ((ret = tls12_renegotiation_info_ext_is_empty(ext_data, ext_datalen)) < 0) {
|
||||||
|
error_print();
|
||||||
|
tls_send_alert(conn, TLS_alert_decode_error);
|
||||||
|
return -1;
|
||||||
|
} else if (ret == 0) {
|
||||||
|
error_print();
|
||||||
|
tls_send_alert(conn, TLS_alert_illegal_parameter);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
renegotiation_info = 1;
|
||||||
|
conn->secure_renegotiation = 1;
|
||||||
|
break;
|
||||||
default:
|
default:
|
||||||
error_print();
|
error_print();
|
||||||
tls_send_alert(conn, TLS_alert_illegal_parameter);
|
tls_send_alert(conn, TLS_alert_illegal_parameter);
|
||||||
@@ -1777,6 +1929,13 @@ int tls_recv_server_hello(TLS_CONNECT *conn)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if ((conn->ctx->renegotiation_info || conn->ctx->empty_renegotiation_info_scsv)
|
||||||
|
&& !renegotiation_info) {
|
||||||
|
error_print();
|
||||||
|
tls_send_alert(conn, TLS_alert_handshake_failure);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
if (ec_point_formats) {
|
if (ec_point_formats) {
|
||||||
if ((ret = tls_ec_point_formats_support_uncompressed(ec_point_formats, ec_point_formats_len)) < 0) {
|
if ((ret = tls_ec_point_formats_support_uncompressed(ec_point_formats, ec_point_formats_len)) < 0) {
|
||||||
error_print();
|
error_print();
|
||||||
|
|||||||
@@ -40,6 +40,9 @@ static const char *help =
|
|||||||
" -pass str Password to decrypt private key\n"
|
" -pass str Password to decrypt private key\n"
|
||||||
" -client_cert_optional Allow client send empty Certificate\n"
|
" -client_cert_optional Allow client send empty Certificate\n"
|
||||||
" -server_name str Send server_name (SNI) request\n"
|
" -server_name str Send server_name (SNI) request\n"
|
||||||
|
" -renegotiation_info Send renegotiation_info extension\n"
|
||||||
|
" -renegotiation_info_scsv\n"
|
||||||
|
" Send TLS_EMPTY_RENEGOTIATION_INFO_SCSV\n"
|
||||||
" -status_request Send status_request (OCSP Stapling) request\n"
|
" -status_request Send status_request (OCSP Stapling) request\n"
|
||||||
"\n"
|
"\n"
|
||||||
#include "tls12_help.h"
|
#include "tls12_help.h"
|
||||||
@@ -64,6 +67,8 @@ int tls12_client_main(int argc, char *argv[])
|
|||||||
char *pass = NULL;
|
char *pass = NULL;
|
||||||
int client_cert_optional = 0;
|
int client_cert_optional = 0;
|
||||||
char *server_name = NULL;
|
char *server_name = NULL;
|
||||||
|
int renegotiation_info = 0;
|
||||||
|
int empty_renegotiation_info_scsv = 0;
|
||||||
TLS_CTX ctx;
|
TLS_CTX ctx;
|
||||||
TLS_CONNECT conn;
|
TLS_CONNECT conn;
|
||||||
struct hostent *hp;
|
struct hostent *hp;
|
||||||
@@ -155,6 +160,10 @@ int tls12_client_main(int argc, char *argv[])
|
|||||||
} else if (!strcmp(*argv, "-server_name")) {
|
} else if (!strcmp(*argv, "-server_name")) {
|
||||||
if (--argc < 1) goto bad;
|
if (--argc < 1) goto bad;
|
||||||
server_name = *(++argv);
|
server_name = *(++argv);
|
||||||
|
} else if (!strcmp(*argv, "-renegotiation_info")) {
|
||||||
|
renegotiation_info = 1;
|
||||||
|
} else if (!strcmp(*argv, "-renegotiation_info_scsv")) {
|
||||||
|
empty_renegotiation_info_scsv = 1;
|
||||||
} else if (!strcmp(*argv, "-client_cert_optional")) {
|
} else if (!strcmp(*argv, "-client_cert_optional")) {
|
||||||
client_cert_optional = 1;
|
client_cert_optional = 1;
|
||||||
} else {
|
} else {
|
||||||
@@ -214,6 +223,19 @@ bad:
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (renegotiation_info) {
|
||||||
|
if (tls12_ctx_set_renegotiation_info(&ctx, 1) != 1) {
|
||||||
|
error_print();
|
||||||
|
goto end;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (empty_renegotiation_info_scsv) {
|
||||||
|
if (tls12_ctx_set_empty_renegotiation_info_scsv(&ctx, 1) != 1) {
|
||||||
|
error_print();
|
||||||
|
goto end;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if (certfile) {
|
if (certfile) {
|
||||||
if (!keyfile) {
|
if (!keyfile) {
|
||||||
fprintf(stderr, "%s: option '-key' missing\n", prog);
|
fprintf(stderr, "%s: option '-key' missing\n", prog);
|
||||||
|
|||||||
@@ -34,6 +34,7 @@ static const char *help =
|
|||||||
" -cacert file CA certificate for client certificate verification\n"
|
" -cacert file CA certificate for client certificate verification\n"
|
||||||
" -verify_depth num Certificate verification depth\n"
|
" -verify_depth num Certificate verification depth\n"
|
||||||
" -client_cert_optional Allow client send empty Certificate\n"
|
" -client_cert_optional Allow client send empty Certificate\n"
|
||||||
|
" -renegotiation_info Send renegotiation_info response when client supports RFC 5746\n"
|
||||||
"\n"
|
"\n"
|
||||||
#include "tls12_help.h"
|
#include "tls12_help.h"
|
||||||
"\n";
|
"\n";
|
||||||
@@ -60,6 +61,7 @@ int tls12_server_main(int argc , char **argv)
|
|||||||
char *cacertfile = NULL;
|
char *cacertfile = NULL;
|
||||||
int verify_depth = TLS_DEFAULT_VERIFY_DEPTH;
|
int verify_depth = TLS_DEFAULT_VERIFY_DEPTH;
|
||||||
int client_cert_optional = 0;
|
int client_cert_optional = 0;
|
||||||
|
int renegotiation_info = 0;
|
||||||
TLS_CTX ctx;
|
TLS_CTX ctx;
|
||||||
TLS_CONNECT conn;
|
TLS_CONNECT conn;
|
||||||
char buf[1600] = {0};
|
char buf[1600] = {0};
|
||||||
@@ -165,6 +167,8 @@ int tls12_server_main(int argc , char **argv)
|
|||||||
}
|
}
|
||||||
} else if (!strcmp(*argv, "-client_cert_optional")) {
|
} else if (!strcmp(*argv, "-client_cert_optional")) {
|
||||||
client_cert_optional = 1;
|
client_cert_optional = 1;
|
||||||
|
} else if (!strcmp(*argv, "-renegotiation_info")) {
|
||||||
|
renegotiation_info = 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;
|
||||||
@@ -224,6 +228,13 @@ bad:
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (renegotiation_info) {
|
||||||
|
if (tls12_ctx_set_renegotiation_info(&ctx, 1) != 1) {
|
||||||
|
error_print();
|
||||||
|
goto end;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// Certificate
|
// Certificate
|
||||||
for (i = 0; i < certfiles_cnt; i++) {
|
for (i = 0; i < certfiles_cnt; i++) {
|
||||||
if (tls_ctx_add_certificate_chain_and_key(&ctx, certfiles[i], keyfiles[i], passes[i]) != 1) {
|
if (tls_ctx_add_certificate_chain_and_key(&ctx, certfiles[i], keyfiles[i], passes[i]) != 1) {
|
||||||
|
|||||||
Reference in New Issue
Block a user