mirror of
https://github.com/guanzhi/GmSSL.git
synced 2026-06-27 07:33:41 +08:00
Add ECDHE cipher suites to TLCP
This commit is contained in:
@@ -244,6 +244,7 @@ set(tests
|
||||
sm2_key
|
||||
sm2_sign
|
||||
sm2_enc
|
||||
sm2_exch
|
||||
block_cipher
|
||||
digest
|
||||
hkdf
|
||||
@@ -873,6 +874,8 @@ if(ENABLE_TLS AND NOT WIN32)
|
||||
add_test(NAME tool_tlcp_sm4_gcm_sni COMMAND ${CMAKE_COMMAND} -DTEST_CASE=tlcp_sm4_gcm_sni -P "${CMAKE_SOURCE_DIR}/cmake/tlcp_commands.cmake")
|
||||
add_test(NAME tool_tlcp_sm4_cbc_sni COMMAND ${CMAKE_COMMAND} -DTEST_CASE=tlcp_sm4_cbc_sni -P "${CMAKE_SOURCE_DIR}/cmake/tlcp_commands.cmake")
|
||||
add_test(NAME tool_tlcp_sm4_gcm_client_cert COMMAND ${CMAKE_COMMAND} -DTEST_CASE=tlcp_sm4_gcm_client_cert -P "${CMAKE_SOURCE_DIR}/cmake/tlcp_commands.cmake")
|
||||
add_test(NAME tool_tlcp_ecdhe_sm4_cbc_client_cert COMMAND ${CMAKE_COMMAND} -DTEST_CASE=tlcp_ecdhe_sm4_cbc_client_cert -P "${CMAKE_SOURCE_DIR}/cmake/tlcp_commands.cmake")
|
||||
add_test(NAME tool_tlcp_ecdhe_sm4_gcm_client_cert COMMAND ${CMAKE_COMMAND} -DTEST_CASE=tlcp_ecdhe_sm4_gcm_client_cert -P "${CMAKE_SOURCE_DIR}/cmake/tlcp_commands.cmake")
|
||||
add_test(NAME tool_tls12_sm4_gcm_sni COMMAND ${CMAKE_COMMAND} -DTEST_CASE=tls12_sm4_gcm_sni -P "${CMAKE_SOURCE_DIR}/cmake/tls12_commands.cmake")
|
||||
add_test(NAME tool_tls12_sm4_cbc_sni COMMAND ${CMAKE_COMMAND} -DTEST_CASE=tls12_sm4_cbc_sni -P "${CMAKE_SOURCE_DIR}/cmake/tls12_commands.cmake")
|
||||
add_test(NAME tool_tls12_sm4_gcm_client_cert COMMAND ${CMAKE_COMMAND} -DTEST_CASE=tls12_sm4_gcm_client_cert -P "${CMAKE_SOURCE_DIR}/cmake/tls12_commands.cmake")
|
||||
@@ -890,6 +893,8 @@ if(ENABLE_TLS AND NOT WIN32)
|
||||
tool_tlcp_sm4_gcm_sni
|
||||
tool_tlcp_sm4_cbc_sni
|
||||
tool_tlcp_sm4_gcm_client_cert
|
||||
tool_tlcp_ecdhe_sm4_cbc_client_cert
|
||||
tool_tlcp_ecdhe_sm4_gcm_client_cert
|
||||
tool_tls12_sm4_gcm_sni
|
||||
tool_tls12_sm4_cbc_sni
|
||||
tool_tls12_sm4_gcm_client_cert
|
||||
@@ -942,7 +947,7 @@ endif()
|
||||
#
|
||||
set(CPACK_PACKAGE_NAME "GmSSL")
|
||||
set(CPACK_PACKAGE_VENDOR "GmSSL develop team")
|
||||
set(CPACK_PACKAGE_VERSION "3.3.0-dev.1162")
|
||||
set(CPACK_PACKAGE_VERSION "3.3.0-dev.1163")
|
||||
set(CPACK_PACKAGE_DESCRIPTION_FILE ${PROJECT_SOURCE_DIR}/README.md)
|
||||
set(CPACK_NSIS_MODIFY_PATH ON)
|
||||
include(CPack)
|
||||
|
||||
@@ -5,6 +5,8 @@ gmssl_require_file(sm2_tlcp_server_certs.pem)
|
||||
gmssl_require_file(sm2_tlcp_server_keys.pem)
|
||||
gmssl_require_file(sm2_tls_client_certs.pem)
|
||||
gmssl_require_file(sm2_tls_client_key.pem)
|
||||
gmssl_require_file(sm2_tlcp_client_certs.pem)
|
||||
gmssl_require_file(sm2_tlcp_client_keys.pem)
|
||||
|
||||
if(NOT DEFINED TEST_CASE)
|
||||
set(TEST_CASE tlcp_sm4_gcm_sni)
|
||||
@@ -25,6 +27,18 @@ elseif(TEST_CASE STREQUAL tlcp_sm4_gcm_client_cert)
|
||||
set(TEST_PORT 4436)
|
||||
set(TEST_CIPHER_SUITE TLS_ECC_SM4_GCM_SM3)
|
||||
set(TEST_CLIENT_CERT ON)
|
||||
elseif(TEST_CASE STREQUAL tlcp_ecdhe_sm4_cbc_client_cert)
|
||||
set(TEST_NAME tlcp_ecdhe_sm4_cbc_client_cert)
|
||||
set(TEST_PORT 4437)
|
||||
set(TEST_CIPHER_SUITE TLS_ECDHE_SM4_CBC_SM3)
|
||||
set(TEST_CLIENT_CERT ON)
|
||||
set(TEST_CLIENT_DOUBLE_CERT ON)
|
||||
elseif(TEST_CASE STREQUAL tlcp_ecdhe_sm4_gcm_client_cert)
|
||||
set(TEST_NAME tlcp_ecdhe_sm4_gcm_client_cert)
|
||||
set(TEST_PORT 4438)
|
||||
set(TEST_CIPHER_SUITE TLS_ECDHE_SM4_GCM_SM3)
|
||||
set(TEST_CLIENT_CERT ON)
|
||||
set(TEST_CLIENT_DOUBLE_CERT ON)
|
||||
else()
|
||||
message(FATAL_ERROR "unknown TLCP test case: ${TEST_CASE}")
|
||||
endif()
|
||||
@@ -50,10 +64,17 @@ if(TEST_CLIENT_CERT)
|
||||
list(APPEND TEST_SERVER_ARGS
|
||||
-cacert sm2_root_ca_cert.pem
|
||||
-cert_request)
|
||||
list(APPEND TEST_CLIENT_ARGS
|
||||
-cert sm2_tls_client_certs.pem
|
||||
-key sm2_tls_client_key.pem
|
||||
-pass P@ssw0rd)
|
||||
if(TEST_CLIENT_DOUBLE_CERT)
|
||||
list(APPEND TEST_CLIENT_ARGS
|
||||
-cert sm2_tlcp_client_certs.pem
|
||||
-key sm2_tlcp_client_keys.pem
|
||||
-pass P@ssw0rd)
|
||||
else()
|
||||
list(APPEND TEST_CLIENT_ARGS
|
||||
-cert sm2_tls_client_certs.pem
|
||||
-key sm2_tls_client_key.pem
|
||||
-pass P@ssw0rd)
|
||||
endif()
|
||||
endif()
|
||||
|
||||
gmssl_run_tls_command_test(
|
||||
|
||||
@@ -187,6 +187,20 @@ gmssl_generate_end_entity(SM2 sm2_tls_client "GmSSL SM2 TLS Client"
|
||||
gmssl_write_bundle(sm2_tls_client_certs.pem
|
||||
sm2_tls_client_cert.pem sm2_tls_client_ca_cert.pem)
|
||||
|
||||
# SM2 TLCP client chain reuses the SM2 TLS client CA and adds an encryption certificate.
|
||||
gmssl_generate_end_entity(SM2 sm2_tlcp_client_sign "GmSSL SM2 TLCP Client"
|
||||
sm2_tls_client_ca_cert.pem sm2_tls_client_ca_key.pem
|
||||
digitalSignature clientAuth "" OFF)
|
||||
gmssl_generate_end_entity(SM2 sm2_tlcp_client_enc "GmSSL SM2 TLCP Client"
|
||||
sm2_tls_client_ca_cert.pem sm2_tls_client_ca_key.pem
|
||||
keyEncipherment clientAuth "" OFF)
|
||||
gmssl_write_bundle(sm2_tlcp_client_certs.pem
|
||||
sm2_tlcp_client_sign_cert.pem
|
||||
sm2_tlcp_client_enc_cert.pem
|
||||
sm2_tls_client_ca_cert.pem)
|
||||
gmssl_write_bundle(sm2_tlcp_client_keys.pem
|
||||
sm2_tlcp_client_sign_key.pem sm2_tlcp_client_enc_key.pem)
|
||||
|
||||
# P256 TLS client chain: root -> client CA -> client certificate
|
||||
gmssl_generate_ca(P256 p256_tls_client_ca "GmSSL P256 TLS Client CA"
|
||||
p256_root_ca_cert.pem p256_root_ca_key.pem 0)
|
||||
|
||||
@@ -254,6 +254,22 @@ int sm2_encrypt_fixlen(const SM2_KEY *key, const uint8_t *in, size_t inlen, int
|
||||
int sm2_do_ecdh(const SM2_KEY *key, const SM2_KEY *peer_key, uint8_t out[32]);
|
||||
int sm2_ecdh(const SM2_KEY *key, const uint8_t uncompressed_point[65], uint8_t out[32]);
|
||||
|
||||
int sm2_key_exchange(int is_initiator,
|
||||
const SM2_KEY *key, const char *id, size_t idlen,
|
||||
const SM2_KEY *peer_public_key, const char *peer_id, size_t peer_idlen,
|
||||
const SM2_KEY *key_exchange, const uint8_t peer_key_exchange[65],
|
||||
uint8_t optional_shared_point[65], size_t shared_key_len, uint8_t *shared_key);
|
||||
int sm2_key_exchange_compute_confirm(int is_initiator,
|
||||
const SM2_KEY *key, const char *id, size_t idlen,
|
||||
const SM2_KEY *peer_public_key, const char *peer_id, size_t peer_idlen,
|
||||
const SM2_KEY *key_exchange, const uint8_t peer_key_exchange[65],
|
||||
const uint8_t shared_point[65], uint8_t confirm[32]);
|
||||
int sm2_key_exchange_verify_confirm(int is_initiator,
|
||||
const SM2_KEY *key, const char *id, size_t idlen,
|
||||
const SM2_KEY *peer_public_key, const char *peer_id, size_t peer_idlen,
|
||||
const SM2_KEY *key_exchange, const uint8_t peer_key_exchange[65],
|
||||
const uint8_t shared_point[65], const uint8_t confirm[32]);
|
||||
|
||||
|
||||
typedef struct {
|
||||
sm2_z256_t k;
|
||||
|
||||
@@ -1008,8 +1008,12 @@ int tls_ctx_set_certificate_and_key(TLS_CTX *ctx, const char *chainfile,
|
||||
const char *keyfile, const char *keypass);
|
||||
int tlcp_ctx_add_server_certificate_and_keys(TLS_CTX *ctx, const char *chainfile,
|
||||
const char *keyfile, const char *keypass);
|
||||
int tlcp_ctx_add_client_certificate_and_keys(TLS_CTX *ctx, const char *chainfile,
|
||||
const char *keyfile, const char *keypass);
|
||||
int tls_ctx_set_tlcp_server_certificate_and_keys(TLS_CTX *ctx, const char *chainfile,
|
||||
const char *keyfile, const char *keypass);
|
||||
int tls_ctx_set_tlcp_client_certificate_and_keys(TLS_CTX *ctx, const char *chainfile,
|
||||
const char *keyfile, const char *keypass);
|
||||
void tls_ctx_cleanup(TLS_CTX *ctx);
|
||||
|
||||
int tls_ctx_add_certificate_chain_and_key(TLS_CTX *ctx, const char *chainfile,
|
||||
|
||||
@@ -18,7 +18,7 @@ extern "C" {
|
||||
|
||||
|
||||
#define GMSSL_VERSION_NUM 30300
|
||||
#define GMSSL_VERSION_STR "GmSSL 3.3.0-dev.1162"
|
||||
#define GMSSL_VERSION_STR "GmSSL 3.3.0-dev.1163"
|
||||
|
||||
int gmssl_version_num(void);
|
||||
const char *gmssl_version_str(void);
|
||||
|
||||
242
src/sm2_exch.c
242
src/sm2_exch.c
@@ -55,3 +55,245 @@ int sm2_ecdh(const SM2_KEY *key, const uint8_t uncompressed_point[65], uint8_t o
|
||||
gmssl_secure_clear(x, sizeof(sm2_z256_t));
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int sm2_z256_point_get_x_hat(const SM2_Z256_POINT *P, sm2_z256_t x_hat)
|
||||
{
|
||||
sm2_z256_t x;
|
||||
|
||||
if (sm2_z256_point_get_xy(P, x, NULL) != 1) {
|
||||
error_print();
|
||||
return -1;
|
||||
}
|
||||
|
||||
// x' = 2^127 + (x mod 2^127)
|
||||
x_hat[0] = x[0];
|
||||
x_hat[1] = (x[1] & 0x7fffffffffffffff) | 0x8000000000000000;
|
||||
x_hat[2] = 0;
|
||||
x_hat[3] = 0;
|
||||
|
||||
gmssl_secure_clear(x, sizeof(x));
|
||||
return 1;
|
||||
}
|
||||
|
||||
int sm2_key_exchange(int is_initiator,
|
||||
const SM2_KEY *key, const char *id, size_t idlen,
|
||||
const SM2_KEY *peer_public_key, const char *peer_id, size_t peer_idlen,
|
||||
const SM2_KEY *key_exchange, const uint8_t peer_key_exchange[65],
|
||||
uint8_t optional_shared_point[65], size_t shared_key_len, uint8_t *shared_key)
|
||||
{
|
||||
SM2_Z256_POINT peer_point;
|
||||
SM2_Z256_POINT point;
|
||||
sm2_z256_t local_x_hat;
|
||||
sm2_z256_t peer_x_hat;
|
||||
sm2_z256_t t;
|
||||
uint8_t za[32];
|
||||
uint8_t zb[32];
|
||||
uint8_t kdf_input[128];
|
||||
int ret = -1;
|
||||
|
||||
if (!key || !id || !peer_public_key || !peer_id || !key_exchange
|
||||
|| !peer_key_exchange || !shared_key_len || !shared_key) {
|
||||
error_print();
|
||||
return -1;
|
||||
}
|
||||
if (idlen > SM2_MAX_ID_LENGTH || peer_idlen > SM2_MAX_ID_LENGTH) {
|
||||
error_print();
|
||||
return -1;
|
||||
}
|
||||
if (sm2_z256_point_from_octets(&peer_point, peer_key_exchange, 65) != 1) {
|
||||
error_print();
|
||||
goto end;
|
||||
}
|
||||
if (is_initiator) {
|
||||
if (sm2_compute_z(za, &key->public_key, id, idlen) != 1
|
||||
|| sm2_compute_z(zb, &peer_public_key->public_key, peer_id, peer_idlen) != 1) {
|
||||
error_print();
|
||||
goto end;
|
||||
}
|
||||
} else {
|
||||
if (sm2_compute_z(za, &peer_public_key->public_key, peer_id, peer_idlen) != 1
|
||||
|| sm2_compute_z(zb, &key->public_key, id, idlen) != 1) {
|
||||
error_print();
|
||||
goto end;
|
||||
}
|
||||
}
|
||||
|
||||
if (sm2_z256_point_get_x_hat(&key_exchange->public_key, local_x_hat) != 1
|
||||
|| sm2_z256_point_get_x_hat(&peer_point, peer_x_hat) != 1) {
|
||||
error_print();
|
||||
goto end;
|
||||
}
|
||||
|
||||
sm2_z256_modn_mul(t, local_x_hat, key_exchange->private_key);
|
||||
sm2_z256_modn_add(t, t, key->private_key);
|
||||
|
||||
sm2_z256_point_mul(&point, peer_x_hat, &peer_point);
|
||||
sm2_z256_point_add(&point, &peer_public_key->public_key, &point);
|
||||
if (sm2_z256_point_is_at_infinity(&point)) {
|
||||
error_print();
|
||||
goto end;
|
||||
}
|
||||
|
||||
sm2_z256_point_mul(&point, t, &point);
|
||||
if (sm2_z256_point_is_at_infinity(&point)) {
|
||||
error_print();
|
||||
goto end;
|
||||
}
|
||||
if (optional_shared_point
|
||||
&& sm2_z256_point_to_uncompressed_octets(&point, optional_shared_point) != 1) {
|
||||
error_print();
|
||||
goto end;
|
||||
}
|
||||
|
||||
sm2_z256_point_to_bytes(&point, kdf_input);
|
||||
memcpy(kdf_input + 64, za, 32);
|
||||
memcpy(kdf_input + 96, zb, 32);
|
||||
if (sm2_kdf(kdf_input, sizeof(kdf_input), shared_key_len, shared_key) != 1) {
|
||||
error_print();
|
||||
goto end;
|
||||
}
|
||||
if (mem_is_zero(shared_key, shared_key_len)) {
|
||||
error_print();
|
||||
goto end;
|
||||
}
|
||||
|
||||
ret = 1;
|
||||
|
||||
end:
|
||||
gmssl_secure_clear(&peer_point, sizeof(peer_point));
|
||||
gmssl_secure_clear(&point, sizeof(point));
|
||||
gmssl_secure_clear(local_x_hat, sizeof(local_x_hat));
|
||||
gmssl_secure_clear(peer_x_hat, sizeof(peer_x_hat));
|
||||
gmssl_secure_clear(t, sizeof(t));
|
||||
gmssl_secure_clear(za, sizeof(za));
|
||||
gmssl_secure_clear(zb, sizeof(zb));
|
||||
gmssl_secure_clear(kdf_input, sizeof(kdf_input));
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int sm2_key_exchange_compute_confirm_ex(int is_initiator,
|
||||
const SM2_KEY *key, const char *id, size_t idlen,
|
||||
const SM2_KEY *peer_public_key, const char *peer_id, size_t peer_idlen,
|
||||
const SM2_KEY *key_exchange, const uint8_t peer_key_exchange[65],
|
||||
const uint8_t shared_point[65], int is_initiator_confirm, uint8_t confirm[32])
|
||||
{
|
||||
SM2_Z256_POINT uv;
|
||||
SM2_Z256_POINT peer_point;
|
||||
SM2_Z256_POINT ra;
|
||||
SM2_Z256_POINT rb;
|
||||
uint8_t za[32];
|
||||
uint8_t zb[32];
|
||||
uint8_t xy[64];
|
||||
uint8_t ra_bytes[64];
|
||||
uint8_t rb_bytes[64];
|
||||
uint8_t hash[32];
|
||||
uint8_t prefix = is_initiator_confirm ? 0x03 : 0x02;
|
||||
SM3_CTX ctx;
|
||||
int ret = -1;
|
||||
|
||||
if (!key || !id || !peer_public_key || !peer_id || !key_exchange
|
||||
|| !peer_key_exchange || !shared_point || !confirm) {
|
||||
error_print();
|
||||
return -1;
|
||||
}
|
||||
if (idlen > SM2_MAX_ID_LENGTH || peer_idlen > SM2_MAX_ID_LENGTH) {
|
||||
error_print();
|
||||
return -1;
|
||||
}
|
||||
if (sm2_z256_point_from_octets(&uv, shared_point, 65) != 1
|
||||
|| sm2_z256_point_from_octets(&peer_point, peer_key_exchange, 65) != 1) {
|
||||
error_print();
|
||||
goto end;
|
||||
}
|
||||
if (is_initiator) {
|
||||
ra = key_exchange->public_key;
|
||||
rb = peer_point;
|
||||
if (sm2_compute_z(za, &key->public_key, id, idlen) != 1
|
||||
|| sm2_compute_z(zb, &peer_public_key->public_key, peer_id, peer_idlen) != 1) {
|
||||
error_print();
|
||||
goto end;
|
||||
}
|
||||
} else {
|
||||
ra = peer_point;
|
||||
rb = key_exchange->public_key;
|
||||
if (sm2_compute_z(za, &peer_public_key->public_key, peer_id, peer_idlen) != 1
|
||||
|| sm2_compute_z(zb, &key->public_key, id, idlen) != 1) {
|
||||
error_print();
|
||||
goto end;
|
||||
}
|
||||
}
|
||||
|
||||
sm2_z256_point_to_bytes(&uv, xy);
|
||||
sm2_z256_point_to_bytes(&ra, ra_bytes);
|
||||
sm2_z256_point_to_bytes(&rb, rb_bytes);
|
||||
|
||||
sm3_init(&ctx);
|
||||
sm3_update(&ctx, xy, 32);
|
||||
sm3_update(&ctx, za, sizeof(za));
|
||||
sm3_update(&ctx, zb, sizeof(zb));
|
||||
sm3_update(&ctx, ra_bytes, sizeof(ra_bytes));
|
||||
sm3_update(&ctx, rb_bytes, sizeof(rb_bytes));
|
||||
sm3_finish(&ctx, hash);
|
||||
|
||||
sm3_init(&ctx);
|
||||
sm3_update(&ctx, &prefix, sizeof(prefix));
|
||||
sm3_update(&ctx, xy + 32, 32);
|
||||
sm3_update(&ctx, hash, sizeof(hash));
|
||||
sm3_finish(&ctx, confirm);
|
||||
|
||||
ret = 1;
|
||||
|
||||
end:
|
||||
gmssl_secure_clear(&uv, sizeof(uv));
|
||||
gmssl_secure_clear(&peer_point, sizeof(peer_point));
|
||||
gmssl_secure_clear(&ra, sizeof(ra));
|
||||
gmssl_secure_clear(&rb, sizeof(rb));
|
||||
gmssl_secure_clear(za, sizeof(za));
|
||||
gmssl_secure_clear(zb, sizeof(zb));
|
||||
gmssl_secure_clear(xy, sizeof(xy));
|
||||
gmssl_secure_clear(ra_bytes, sizeof(ra_bytes));
|
||||
gmssl_secure_clear(rb_bytes, sizeof(rb_bytes));
|
||||
gmssl_secure_clear(hash, sizeof(hash));
|
||||
gmssl_secure_clear(&ctx, sizeof(ctx));
|
||||
return ret;
|
||||
}
|
||||
|
||||
int sm2_key_exchange_compute_confirm(int is_initiator,
|
||||
const SM2_KEY *key, const char *id, size_t idlen,
|
||||
const SM2_KEY *peer_public_key, const char *peer_id, size_t peer_idlen,
|
||||
const SM2_KEY *key_exchange, const uint8_t peer_key_exchange[65],
|
||||
const uint8_t shared_point[65], uint8_t confirm[32])
|
||||
{
|
||||
if (sm2_key_exchange_compute_confirm_ex(is_initiator,
|
||||
key, id, idlen, peer_public_key, peer_id, peer_idlen,
|
||||
key_exchange, peer_key_exchange, shared_point, is_initiator, confirm) != 1) {
|
||||
error_print();
|
||||
return -1;
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
int sm2_key_exchange_verify_confirm(int is_initiator,
|
||||
const SM2_KEY *key, const char *id, size_t idlen,
|
||||
const SM2_KEY *peer_public_key, const char *peer_id, size_t peer_idlen,
|
||||
const SM2_KEY *key_exchange, const uint8_t peer_key_exchange[65],
|
||||
const uint8_t shared_point[65], const uint8_t confirm[32])
|
||||
{
|
||||
uint8_t expected[32];
|
||||
int ret;
|
||||
|
||||
if (!confirm) {
|
||||
error_print();
|
||||
return -1;
|
||||
}
|
||||
if (sm2_key_exchange_compute_confirm_ex(is_initiator,
|
||||
key, id, idlen, peer_public_key, peer_id, peer_idlen,
|
||||
key_exchange, peer_key_exchange, shared_point, !is_initiator, expected) != 1) {
|
||||
error_print();
|
||||
return -1;
|
||||
}
|
||||
|
||||
ret = gmssl_secure_memcmp(expected, confirm, sizeof(expected)) == 0 ? 1 : 0;
|
||||
gmssl_secure_clear(expected, sizeof(expected));
|
||||
return ret;
|
||||
}
|
||||
|
||||
501
src/tlcp.c
501
src/tlcp.c
@@ -39,13 +39,77 @@ const size_t tlcp_signature_algorithms_cnt =
|
||||
const int tlcp_cipher_suites[] = {
|
||||
TLS_cipher_ecc_sm4_cbc_sm3,
|
||||
TLS_cipher_ecc_sm4_gcm_sm3,
|
||||
TLS_cipher_ecdhe_sm4_cbc_sm3,
|
||||
TLS_cipher_ecdhe_sm4_gcm_sm3,
|
||||
};
|
||||
const size_t tlcp_cipher_suites_cnt =
|
||||
sizeof(tlcp_cipher_suites)/sizeof(tlcp_cipher_suites[0]);
|
||||
|
||||
static int tlcp_cipher_suite_is_ecc(int cipher_suite)
|
||||
{
|
||||
switch (cipher_suite) {
|
||||
case TLS_cipher_ecc_sm4_cbc_sm3:
|
||||
case TLS_cipher_ecc_sm4_gcm_sm3:
|
||||
return 1;
|
||||
default:
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
static int tlcp_cipher_suite_is_ecdhe(int cipher_suite)
|
||||
{
|
||||
switch (cipher_suite) {
|
||||
case TLS_cipher_ecdhe_sm4_cbc_sm3:
|
||||
case TLS_cipher_ecdhe_sm4_gcm_sm3:
|
||||
return 1;
|
||||
default:
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
/*--
|
||||
|
||||
当采用ECDHE_SM4_CBC/GCM_SM3时
|
||||
|
||||
双方采用SM2密钥交换算法,也就是 sm2_key_exchange 函数完成密钥交换
|
||||
其中服务器作为发起方,客户端做为接收方
|
||||
|
||||
当采用这个套件时,要求服务器方必须发起cert_reqeust,发送CertificateRequest
|
||||
客户端必须响应不为空的client Certificate
|
||||
|
||||
客户端响应的证书链必须是SM2的双证书证书链
|
||||
|
||||
服务器加密证书中的公钥作为发起方的持久公钥,即sm2_key_exchange的参数key
|
||||
服务器ServerKeyExchagne中的public公钥作为临时公钥,即_key_exchange的参数key_exchange
|
||||
|
||||
客户端加密证书中的公钥作为响应方的持久公钥
|
||||
客户端ClientKeyExchagne中的公钥作为响应方的临时公钥
|
||||
|
||||
双方的id,peed_id参数使用默认的SM2_DEFAULT_ID
|
||||
|
||||
在密钥交换时,使用sm2_key_exchange进行密钥交换
|
||||
|
||||
|
||||
|
||||
ServerKeyExchange
|
||||
|
||||
select (KeyExchangeAlgorithm) {
|
||||
case ECC:
|
||||
digitall-signed struct {
|
||||
opaque client_random[32];
|
||||
opaque server_random[32];
|
||||
opaque ASN1.Cert<1..2^24-1>;
|
||||
} signed_params;
|
||||
|
||||
case ECDHE:
|
||||
ServerECDHEParams params;
|
||||
digitally-signed struct {
|
||||
opaque client_random[32];
|
||||
opaque server_random[32];
|
||||
ServerECDHEParams params;
|
||||
|
||||
|
||||
|
||||
/*
|
||||
ServerKeyExchange
|
||||
|
||||
select (KeyExchangeAlgorithm) {
|
||||
@@ -82,8 +146,52 @@ select (KeyExchangeAlgorithm) {
|
||||
} ServerKeyExchange;
|
||||
|
||||
`signed_params` is DER signature encoded in uint16array
|
||||
|
||||
struct {
|
||||
ECParameters curve_params;
|
||||
ECPoint public;
|
||||
} ServerECDHEParams;
|
||||
|
||||
struct {
|
||||
ClientCertificateType certificate_type<1..2^8-1>;
|
||||
DistinguishedName certificate_authorities<0..2^16-1>;
|
||||
} CertificateRequest;
|
||||
|
||||
enum {
|
||||
ecdsa_sign(64), ibc_params(80),
|
||||
} ClientCertificateType;
|
||||
|
||||
struct {
|
||||
select (KeyExchangeAlgorithm) {
|
||||
case ECC:
|
||||
opaque ECCEncryptedPreMasterSecret<0..2^16-1>;
|
||||
case ECDHE:
|
||||
Opaque ClientECDHEParams<1..2^16-1>;
|
||||
case IBSDH:
|
||||
Opaque ClientIBSDHParams<1..2^16-1>;
|
||||
case IBC:
|
||||
opaque IBCEncryptedPreMasterSecret<0..2^16-1>;
|
||||
} exchange_keys;
|
||||
} ClientKeyExchange;
|
||||
|
||||
|
||||
struct {
|
||||
ECParameters curve_params; 值为SM2命名曲线
|
||||
ECPoint pubulic;
|
||||
} ClientECDHEParams;
|
||||
|
||||
ClientIBSDHParams SM9的密钥交换数据
|
||||
|
||||
IBCEncryptedPreMasterSecret SM9密文加密的pre_master_secret
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
*/
|
||||
|
||||
|
||||
|
||||
int tlcp_server_key_exchange_ecc_print(FILE *fp, const uint8_t *data, size_t datalen, int fmt, int ind)
|
||||
{
|
||||
const uint8_t *sig;
|
||||
@@ -214,22 +322,7 @@ int tlcp_record_get_handshake_server_key_exchange(const uint8_t *record,
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
struct {
|
||||
select (KeyExchangeAlgorithm) {
|
||||
case ECC:
|
||||
opaque ECCEncryptedPreMasterSecret<0..2^16-1>;
|
||||
case ECDHE:
|
||||
Opaque ClientECDHEParams<1..2^16-1>;
|
||||
case IBSDH:
|
||||
Opaque ClientIBSDHParams<1..2^16-1>;
|
||||
case IBC:
|
||||
opaque IBCEncryptedPreMasterSecret<0..2^16-1>;
|
||||
case RSA:
|
||||
opaque RSAEncryptedPreMasterSecret<0..2^16-1>;
|
||||
} exchange_keys;
|
||||
} ClientKeyExchange;
|
||||
*/
|
||||
|
||||
|
||||
int tlcp_record_set_handshake_client_key_exchange(uint8_t *record, size_t *recordlen,
|
||||
const uint8_t *enced_pms, size_t enced_pms_len)
|
||||
@@ -817,6 +910,8 @@ int tlcp_recv_server_certificate(TLS_CONNECT *conn)
|
||||
int tlcp_recv_server_key_exchange(TLS_CONNECT *conn)
|
||||
{
|
||||
int ret;
|
||||
const uint8_t *server_ecdh_params;
|
||||
size_t server_ecdh_params_len;
|
||||
const uint8_t *sig;
|
||||
size_t siglen;
|
||||
const uint8_t *sign_cert;
|
||||
@@ -857,36 +952,95 @@ int tlcp_recv_server_key_exchange(TLS_CONNECT *conn)
|
||||
tls_send_alert(conn, TLS_alert_protocol_version);
|
||||
return -1;
|
||||
}
|
||||
if (tlcp_record_get_handshake_server_key_exchange(conn->record,
|
||||
TLS_server_key_exchange_ecc, NULL, 0, &sig, &siglen) != 1) {
|
||||
error_print();
|
||||
tls_send_alert(conn, TLS_alert_unexpected_message);
|
||||
return -1;
|
||||
}
|
||||
|
||||
// verify ServerKeyExchange
|
||||
if (x509_certs_get_cert_by_index(conn->peer_cert_chain, conn->peer_cert_chain_len, 0, &sign_cert, &sign_cert_len) != 1
|
||||
|| x509_cert_get_subject_public_key(sign_cert, sign_cert_len, &sign_key) != 1
|
||||
|| x509_certs_get_cert_by_index(conn->peer_cert_chain, conn->peer_cert_chain_len, 1, &enc_cert, &enc_cert_len) != 1) {
|
||||
|| x509_cert_get_subject_public_key(sign_cert, sign_cert_len, &sign_key) != 1) {
|
||||
error_print();
|
||||
return -1;
|
||||
}
|
||||
tls_uint24_to_bytes(enc_cert_len, &enc_cert_header_ptr, &enc_cert_header_len);
|
||||
if (sign_key.algor != OID_ec_public_key || sign_key.algor_param != OID_sm2) {
|
||||
error_print();
|
||||
tls_send_alert(conn, TLS_alert_bad_certificate);
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (sm2_verify_init(&verify_ctx, &sign_key.u.sm2_key, SM2_DEFAULT_ID, SM2_DEFAULT_ID_LENGTH) != 1
|
||||
|| sm2_verify_update(&verify_ctx, conn->client_random, 32) != 1
|
||||
|| sm2_verify_update(&verify_ctx, conn->server_random, 32) != 1
|
||||
|| sm2_verify_update(&verify_ctx, enc_cert_header, enc_cert_header_len) != 1
|
||||
|| sm2_verify_update(&verify_ctx, enc_cert, enc_cert_len) != 1) {
|
||||
if (tlcp_cipher_suite_is_ecdhe(conn->cipher_suite)) {
|
||||
const uint8_t *server_key_exchange;
|
||||
size_t server_key_exchange_len;
|
||||
const uint8_t *params;
|
||||
size_t params_len;
|
||||
|
||||
if (tlcp_record_get_handshake_server_key_exchange(conn->record,
|
||||
TLS_server_key_exchange_ecdhe, &server_ecdh_params, &server_ecdh_params_len,
|
||||
&sig, &siglen) != 1) {
|
||||
error_print();
|
||||
tls_send_alert(conn, TLS_alert_unexpected_message);
|
||||
return -1;
|
||||
}
|
||||
if (sm2_verify_init(&verify_ctx, &sign_key.u.sm2_key, SM2_DEFAULT_ID, SM2_DEFAULT_ID_LENGTH) != 1
|
||||
|| sm2_verify_update(&verify_ctx, conn->client_random, 32) != 1
|
||||
|| sm2_verify_update(&verify_ctx, conn->server_random, 32) != 1
|
||||
|| sm2_verify_update(&verify_ctx, server_ecdh_params, server_ecdh_params_len) != 1) {
|
||||
error_print();
|
||||
tls_send_alert(conn, TLS_alert_internal_error);
|
||||
return -1;
|
||||
}
|
||||
if (sm2_verify_finish(&verify_ctx, sig, siglen) != 1) {
|
||||
error_print();
|
||||
tls_send_alert(conn, TLS_alert_decrypt_error);
|
||||
return -1;
|
||||
}
|
||||
params = server_ecdh_params;
|
||||
params_len = server_ecdh_params_len;
|
||||
if (tls_server_ecdh_params_from_bytes(&conn->key_exchange_group,
|
||||
&server_key_exchange, &server_key_exchange_len, ¶ms, ¶ms_len) != 1
|
||||
|| tls_length_is_zero(params_len) != 1) {
|
||||
error_print();
|
||||
tls_send_alert(conn, TLS_alert_decode_error);
|
||||
return -1;
|
||||
}
|
||||
if (conn->key_exchange_group != TLS_curve_sm2p256v1
|
||||
|| server_key_exchange_len != sizeof(conn->peer_key_exchange)) {
|
||||
error_print();
|
||||
tls_send_alert(conn, TLS_alert_illegal_parameter);
|
||||
return -1;
|
||||
}
|
||||
memcpy(conn->peer_key_exchange, server_key_exchange, server_key_exchange_len);
|
||||
conn->peer_key_exchange_len = server_key_exchange_len;
|
||||
} else if (tlcp_cipher_suite_is_ecc(conn->cipher_suite)) {
|
||||
if (tlcp_record_get_handshake_server_key_exchange(conn->record,
|
||||
TLS_server_key_exchange_ecc, NULL, 0, &sig, &siglen) != 1) {
|
||||
error_print();
|
||||
tls_send_alert(conn, TLS_alert_unexpected_message);
|
||||
return -1;
|
||||
}
|
||||
if (x509_certs_get_cert_by_index(conn->peer_cert_chain, conn->peer_cert_chain_len, 1,
|
||||
&enc_cert, &enc_cert_len) != 1) {
|
||||
error_print();
|
||||
return -1;
|
||||
}
|
||||
tls_uint24_to_bytes(enc_cert_len, &enc_cert_header_ptr, &enc_cert_header_len);
|
||||
|
||||
if (sm2_verify_init(&verify_ctx, &sign_key.u.sm2_key, SM2_DEFAULT_ID, SM2_DEFAULT_ID_LENGTH) != 1
|
||||
|| sm2_verify_update(&verify_ctx, conn->client_random, 32) != 1
|
||||
|| sm2_verify_update(&verify_ctx, conn->server_random, 32) != 1
|
||||
|| sm2_verify_update(&verify_ctx, enc_cert_header, enc_cert_header_len) != 1
|
||||
|| sm2_verify_update(&verify_ctx, enc_cert, enc_cert_len) != 1) {
|
||||
error_print();
|
||||
tls_send_alert(conn, TLS_alert_internal_error);
|
||||
return -1;
|
||||
}
|
||||
if (sm2_verify_finish(&verify_ctx, sig, siglen) != 1) {
|
||||
error_print();
|
||||
tls_send_alert(conn, TLS_alert_decrypt_error);
|
||||
return -1;
|
||||
}
|
||||
} else {
|
||||
error_print();
|
||||
tls_send_alert(conn, TLS_alert_internal_error);
|
||||
return -1;
|
||||
}
|
||||
if (sm2_verify_finish(&verify_ctx, sig, siglen) != 1) {
|
||||
error_print();
|
||||
tls_send_alert(conn, TLS_alert_decrypt_error);
|
||||
return -1;
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
@@ -981,33 +1135,90 @@ int tlcp_send_client_key_exchange(TLS_CONNECT *conn)
|
||||
X509_KEY public_key;
|
||||
uint8_t enced_pre_master_secret[SM2_MAX_CIPHERTEXT_SIZE];
|
||||
size_t enced_pre_master_secret_len;
|
||||
uint8_t client_ecdh_params[69];
|
||||
uint8_t *client_ecdh_params_ptr = client_ecdh_params;
|
||||
size_t client_ecdh_params_len = 0;
|
||||
int curve_oid = tls_named_curve_oid(TLS_curve_sm2p256v1);
|
||||
|
||||
if (conn->verbose)
|
||||
tls_trace("send ClientKeyExchange\n");
|
||||
|
||||
if (x509_certs_get_cert_by_index(conn->peer_cert_chain, conn->peer_cert_chain_len, 1,
|
||||
&enc_cert, &enc_cert_len) != 1
|
||||
|| x509_cert_get_subject_public_key(enc_cert, enc_cert_len, &public_key) != 1) {
|
||||
error_print();
|
||||
return -1;
|
||||
}
|
||||
if (tlcp_cipher_suite_is_ecdhe(conn->cipher_suite)) {
|
||||
X509_KEY *enc_key;
|
||||
|
||||
if (tlcp_generate_pre_master_secret(conn) != 1
|
||||
|| tls_derive_master_secret(conn) != 1
|
||||
|| tls_derive_key_block(conn) != 1
|
||||
|| tls_init_application_keys(conn) != 1) {
|
||||
error_print();
|
||||
return -1;
|
||||
}
|
||||
if (!conn->client_certificate_verify || !conn->cert_chain_idx || !conn->peer_key_exchange_len) {
|
||||
error_print();
|
||||
tls_send_alert(conn, TLS_alert_internal_error);
|
||||
return -1;
|
||||
}
|
||||
if (x509_certs_get_cert_by_index(conn->peer_cert_chain, conn->peer_cert_chain_len, 1,
|
||||
&enc_cert, &enc_cert_len) != 1
|
||||
|| x509_cert_get_subject_public_key(enc_cert, enc_cert_len, &public_key) != 1) {
|
||||
error_print();
|
||||
return -1;
|
||||
}
|
||||
enc_key = &conn->ctx->enc_keys[conn->cert_chain_idx - 1];
|
||||
if (public_key.algor != OID_ec_public_key || public_key.algor_param != OID_sm2
|
||||
|| enc_key->algor != OID_ec_public_key || enc_key->algor_param != OID_sm2) {
|
||||
error_print();
|
||||
tls_send_alert(conn, TLS_alert_internal_error);
|
||||
return -1;
|
||||
}
|
||||
if (x509_key_generate(&conn->key_exchanges[0], OID_ec_public_key,
|
||||
&curve_oid, sizeof(curve_oid)) != 1
|
||||
|| tls_server_ecdh_params_to_bytes(&conn->key_exchanges[0],
|
||||
&client_ecdh_params_ptr, &client_ecdh_params_len) != 1) {
|
||||
error_print();
|
||||
tls_send_alert(conn, TLS_alert_internal_error);
|
||||
return -1;
|
||||
}
|
||||
if (client_ecdh_params_len != sizeof(client_ecdh_params)) {
|
||||
error_print();
|
||||
tls_send_alert(conn, TLS_alert_internal_error);
|
||||
return -1;
|
||||
}
|
||||
if (sm2_key_exchange(0, &enc_key->u.sm2_key,
|
||||
SM2_DEFAULT_ID, SM2_DEFAULT_ID_LENGTH,
|
||||
&public_key.u.sm2_key,
|
||||
SM2_DEFAULT_ID, SM2_DEFAULT_ID_LENGTH,
|
||||
&conn->key_exchanges[0].u.sm2_key,
|
||||
conn->peer_key_exchange, NULL, 48, conn->pre_master_secret) != 1) {
|
||||
error_print();
|
||||
tls_send_alert(conn, TLS_alert_internal_error);
|
||||
return -1;
|
||||
}
|
||||
conn->pre_master_secret_len = 48;
|
||||
if (tlcp_record_set_handshake_client_key_exchange(conn->record, &conn->recordlen,
|
||||
client_ecdh_params, client_ecdh_params_len) != 1) {
|
||||
error_print();
|
||||
tls_send_alert(conn, TLS_alert_internal_error);
|
||||
return -1;
|
||||
}
|
||||
} else if (tlcp_cipher_suite_is_ecc(conn->cipher_suite)) {
|
||||
if (x509_certs_get_cert_by_index(conn->peer_cert_chain, conn->peer_cert_chain_len, 1,
|
||||
&enc_cert, &enc_cert_len) != 1
|
||||
|| x509_cert_get_subject_public_key(enc_cert, enc_cert_len, &public_key) != 1) {
|
||||
error_print();
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (sm2_encrypt(&public_key.u.sm2_key, conn->pre_master_secret, 48,
|
||||
enced_pre_master_secret, &enced_pre_master_secret_len) != 1) {
|
||||
error_print();
|
||||
tls_send_alert(conn, TLS_alert_internal_error);
|
||||
return -1;
|
||||
}
|
||||
if (tlcp_record_set_handshake_client_key_exchange(conn->record, &conn->recordlen,
|
||||
enced_pre_master_secret, enced_pre_master_secret_len) != 1) {
|
||||
if (tlcp_generate_pre_master_secret(conn) != 1) {
|
||||
error_print();
|
||||
return -1;
|
||||
}
|
||||
if (sm2_encrypt(&public_key.u.sm2_key, conn->pre_master_secret, 48,
|
||||
enced_pre_master_secret, &enced_pre_master_secret_len) != 1) {
|
||||
error_print();
|
||||
tls_send_alert(conn, TLS_alert_internal_error);
|
||||
return -1;
|
||||
}
|
||||
if (tlcp_record_set_handshake_client_key_exchange(conn->record, &conn->recordlen,
|
||||
enced_pre_master_secret, enced_pre_master_secret_len) != 1) {
|
||||
error_print();
|
||||
tls_send_alert(conn, TLS_alert_internal_error);
|
||||
return -1;
|
||||
}
|
||||
} else {
|
||||
error_print();
|
||||
tls_send_alert(conn, TLS_alert_internal_error);
|
||||
return -1;
|
||||
@@ -1026,6 +1237,13 @@ int tlcp_send_client_key_exchange(TLS_CONNECT *conn)
|
||||
error_print();
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (tls_derive_master_secret(conn) != 1
|
||||
|| tls_derive_key_block(conn) != 1
|
||||
|| tls_init_application_keys(conn) != 1) {
|
||||
error_print();
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
if ((ret = tls_send_record(conn)) != 1) {
|
||||
@@ -1201,6 +1419,11 @@ int tlcp_recv_client_hello(TLS_CONNECT *conn)
|
||||
break;
|
||||
case TLS_cipher_ecdhe_sm4_cbc_sm3:
|
||||
case TLS_cipher_ecdhe_sm4_gcm_sm3:
|
||||
conn->sig_alg = TLS_sig_sm2sig_sm3;
|
||||
conn->signature_algorithms[0] = TLS_sig_sm2sig_sm3;
|
||||
conn->key_exchange_group = TLS_curve_sm2p256v1;
|
||||
conn->client_certificate_verify = 1;
|
||||
break;
|
||||
default:
|
||||
error_print();
|
||||
return -1;
|
||||
@@ -1546,6 +1769,10 @@ int tlcp_send_server_key_exchange(TLS_CONNECT *conn)
|
||||
uint8_t enc_cert_header[3];
|
||||
uint8_t *enc_cert_header_ptr = enc_cert_header;
|
||||
size_t enc_cert_header_len = 0;
|
||||
uint8_t server_ecdh_params[69];
|
||||
uint8_t *server_ecdh_params_ptr = server_ecdh_params;
|
||||
size_t server_ecdh_params_len = 0;
|
||||
int curve_oid = tls_named_curve_oid(TLS_curve_sm2p256v1);
|
||||
X509_KEY *sign_key;
|
||||
SM2_SIGN_CTX sign_ctx;
|
||||
uint8_t sigbuf[SM2_MAX_SIGNATURE_SIZE];
|
||||
@@ -1574,19 +1801,54 @@ int tlcp_send_server_key_exchange(TLS_CONNECT *conn)
|
||||
tls_send_alert(conn, TLS_alert_internal_error);
|
||||
return -1;
|
||||
}
|
||||
if (sm2_sign_init(&sign_ctx, &sign_key->u.sm2_key, SM2_DEFAULT_ID, SM2_DEFAULT_ID_LENGTH) != 1
|
||||
|| sm2_sign_update(&sign_ctx, conn->client_random, 32) != 1
|
||||
|| sm2_sign_update(&sign_ctx, conn->server_random, 32) != 1
|
||||
|| sm2_sign_update(&sign_ctx, enc_cert_header, enc_cert_header_len) != 1
|
||||
|| sm2_sign_update(&sign_ctx, enc_cert, enc_cert_len) != 1
|
||||
|| sm2_sign_finish(&sign_ctx, sigbuf, &siglen) != 1) {
|
||||
error_print();
|
||||
tls_send_alert(conn, TLS_alert_internal_error);
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (tlcp_record_set_handshake_server_key_exchange(conn->record, &conn->recordlen,
|
||||
TLS_server_key_exchange_ecc, NULL, 0, sigbuf, siglen) != 1) {
|
||||
if (tlcp_cipher_suite_is_ecdhe(conn->cipher_suite)) {
|
||||
if (x509_key_generate(&conn->key_exchanges[0], OID_ec_public_key,
|
||||
&curve_oid, sizeof(curve_oid)) != 1
|
||||
|| tls_server_ecdh_params_to_bytes(&conn->key_exchanges[0],
|
||||
&server_ecdh_params_ptr, &server_ecdh_params_len) != 1) {
|
||||
error_print();
|
||||
tls_send_alert(conn, TLS_alert_internal_error);
|
||||
return -1;
|
||||
}
|
||||
if (server_ecdh_params_len != sizeof(server_ecdh_params)) {
|
||||
error_print();
|
||||
tls_send_alert(conn, TLS_alert_internal_error);
|
||||
return -1;
|
||||
}
|
||||
if (sm2_sign_init(&sign_ctx, &sign_key->u.sm2_key, SM2_DEFAULT_ID, SM2_DEFAULT_ID_LENGTH) != 1
|
||||
|| sm2_sign_update(&sign_ctx, conn->client_random, 32) != 1
|
||||
|| sm2_sign_update(&sign_ctx, conn->server_random, 32) != 1
|
||||
|| sm2_sign_update(&sign_ctx, server_ecdh_params, server_ecdh_params_len) != 1
|
||||
|| sm2_sign_finish(&sign_ctx, sigbuf, &siglen) != 1) {
|
||||
error_print();
|
||||
tls_send_alert(conn, TLS_alert_internal_error);
|
||||
return -1;
|
||||
}
|
||||
if (tlcp_record_set_handshake_server_key_exchange(conn->record, &conn->recordlen,
|
||||
TLS_server_key_exchange_ecdhe, server_ecdh_params, server_ecdh_params_len,
|
||||
sigbuf, siglen) != 1) {
|
||||
error_print();
|
||||
tls_send_alert(conn, TLS_alert_internal_error);
|
||||
return -1;
|
||||
}
|
||||
} else if (tlcp_cipher_suite_is_ecc(conn->cipher_suite)) {
|
||||
if (sm2_sign_init(&sign_ctx, &sign_key->u.sm2_key, SM2_DEFAULT_ID, SM2_DEFAULT_ID_LENGTH) != 1
|
||||
|| sm2_sign_update(&sign_ctx, conn->client_random, 32) != 1
|
||||
|| sm2_sign_update(&sign_ctx, conn->server_random, 32) != 1
|
||||
|| sm2_sign_update(&sign_ctx, enc_cert_header, enc_cert_header_len) != 1
|
||||
|| sm2_sign_update(&sign_ctx, enc_cert, enc_cert_len) != 1
|
||||
|| sm2_sign_finish(&sign_ctx, sigbuf, &siglen) != 1) {
|
||||
error_print();
|
||||
tls_send_alert(conn, TLS_alert_internal_error);
|
||||
return -1;
|
||||
}
|
||||
if (tlcp_record_set_handshake_server_key_exchange(conn->record, &conn->recordlen,
|
||||
TLS_server_key_exchange_ecc, NULL, 0, sigbuf, siglen) != 1) {
|
||||
error_print();
|
||||
tls_send_alert(conn, TLS_alert_internal_error);
|
||||
return -1;
|
||||
}
|
||||
} else {
|
||||
error_print();
|
||||
tls_send_alert(conn, TLS_alert_internal_error);
|
||||
return -1;
|
||||
@@ -1773,7 +2035,6 @@ int tlcp_recv_client_key_exchange(TLS_CONNECT *conn)
|
||||
return -1;
|
||||
}
|
||||
|
||||
// decrypt enced_pre_master_secret
|
||||
if (!conn->cert_chain_idx) {
|
||||
error_print();
|
||||
tls_send_alert(conn, TLS_alert_internal_error);
|
||||
@@ -1785,25 +2046,82 @@ int tlcp_recv_client_key_exchange(TLS_CONNECT *conn)
|
||||
tls_send_alert(conn, TLS_alert_internal_error);
|
||||
return -1;
|
||||
}
|
||||
if (sm2_decrypt(&enc_key->u.sm2_key, enced_pms, enced_pms_len,
|
||||
pre_master_secret, &pre_master_secret_len) != 1) {
|
||||
error_print();
|
||||
tls_send_alert(conn, TLS_alert_decrypt_error);
|
||||
return -1;
|
||||
}
|
||||
if (pre_master_secret_len != 48) {
|
||||
gmssl_secure_clear(pre_master_secret, pre_master_secret_len);
|
||||
error_print();
|
||||
tls_send_alert(conn, TLS_alert_illegal_parameter);
|
||||
return -1;
|
||||
}
|
||||
memcpy(conn->pre_master_secret, pre_master_secret, pre_master_secret_len);
|
||||
conn->pre_master_secret_len = pre_master_secret_len;
|
||||
gmssl_secure_clear(pre_master_secret, pre_master_secret_len);
|
||||
|
||||
if (tlcp_check_pre_master_secret(conn) != 1) {
|
||||
if (tlcp_cipher_suite_is_ecdhe(conn->cipher_suite)) {
|
||||
int key_exchange_group;
|
||||
const uint8_t *client_key_exchange;
|
||||
size_t client_key_exchange_len;
|
||||
const uint8_t *params = enced_pms;
|
||||
size_t params_len = enced_pms_len;
|
||||
const uint8_t *enc_cert;
|
||||
size_t enc_cert_len;
|
||||
X509_KEY peer_public_key;
|
||||
|
||||
if (tls_server_ecdh_params_from_bytes(&key_exchange_group,
|
||||
&client_key_exchange, &client_key_exchange_len, ¶ms, ¶ms_len) != 1
|
||||
|| tls_length_is_zero(params_len) != 1) {
|
||||
error_print();
|
||||
tls_send_alert(conn, TLS_alert_decode_error);
|
||||
return -1;
|
||||
}
|
||||
if (key_exchange_group != TLS_curve_sm2p256v1
|
||||
|| client_key_exchange_len != sizeof(conn->peer_key_exchange)) {
|
||||
error_print();
|
||||
tls_send_alert(conn, TLS_alert_illegal_parameter);
|
||||
return -1;
|
||||
}
|
||||
if (x509_certs_get_cert_by_index(conn->client_certs, conn->client_certs_len, 1,
|
||||
&enc_cert, &enc_cert_len) != 1
|
||||
|| x509_cert_get_subject_public_key(enc_cert, enc_cert_len, &peer_public_key) != 1) {
|
||||
error_print();
|
||||
tls_send_alert(conn, TLS_alert_bad_certificate);
|
||||
return -1;
|
||||
}
|
||||
if (peer_public_key.algor != OID_ec_public_key || peer_public_key.algor_param != OID_sm2
|
||||
|| conn->key_exchanges[0].algor != OID_ec_public_key
|
||||
|| conn->key_exchanges[0].algor_param != OID_sm2) {
|
||||
error_print();
|
||||
tls_send_alert(conn, TLS_alert_internal_error);
|
||||
return -1;
|
||||
}
|
||||
if (sm2_key_exchange(1, &enc_key->u.sm2_key,
|
||||
SM2_DEFAULT_ID, SM2_DEFAULT_ID_LENGTH,
|
||||
&peer_public_key.u.sm2_key,
|
||||
SM2_DEFAULT_ID, SM2_DEFAULT_ID_LENGTH,
|
||||
&conn->key_exchanges[0].u.sm2_key,
|
||||
client_key_exchange, NULL, 48, conn->pre_master_secret) != 1) {
|
||||
error_print();
|
||||
tls_send_alert(conn, TLS_alert_decrypt_error);
|
||||
return -1;
|
||||
}
|
||||
memcpy(conn->peer_key_exchange, client_key_exchange, client_key_exchange_len);
|
||||
conn->peer_key_exchange_len = client_key_exchange_len;
|
||||
conn->pre_master_secret_len = 48;
|
||||
} else if (tlcp_cipher_suite_is_ecc(conn->cipher_suite)) {
|
||||
if (sm2_decrypt(&enc_key->u.sm2_key, enced_pms, enced_pms_len,
|
||||
pre_master_secret, &pre_master_secret_len) != 1) {
|
||||
error_print();
|
||||
tls_send_alert(conn, TLS_alert_decrypt_error);
|
||||
return -1;
|
||||
}
|
||||
if (pre_master_secret_len != 48) {
|
||||
gmssl_secure_clear(pre_master_secret, pre_master_secret_len);
|
||||
error_print();
|
||||
tls_send_alert(conn, TLS_alert_illegal_parameter);
|
||||
return -1;
|
||||
}
|
||||
memcpy(conn->pre_master_secret, pre_master_secret, pre_master_secret_len);
|
||||
conn->pre_master_secret_len = pre_master_secret_len;
|
||||
gmssl_secure_clear(pre_master_secret, pre_master_secret_len);
|
||||
|
||||
if (tlcp_check_pre_master_secret(conn) != 1) {
|
||||
error_print();
|
||||
tls_send_alert(conn, TLS_alert_illegal_parameter);
|
||||
return -1;
|
||||
}
|
||||
} else {
|
||||
error_print();
|
||||
tls_send_alert(conn, TLS_alert_illegal_parameter);
|
||||
tls_send_alert(conn, TLS_alert_internal_error);
|
||||
return -1;
|
||||
}
|
||||
if (tls_derive_master_secret(conn) != 1
|
||||
@@ -1877,6 +2195,7 @@ int tlcp_send(TLS_CONNECT *conn, const uint8_t *in, size_t inlen, size_t *sentle
|
||||
|
||||
switch (conn->cipher_suite) {
|
||||
case TLS_cipher_ecc_sm4_cbc_sm3:
|
||||
case TLS_cipher_ecdhe_sm4_cbc_sm3:
|
||||
if (tls_cbc_encrypt(hmac_ctx, enc_key, seq_num, conn->databuf,
|
||||
conn->databuf + 5, tls_record_data_length(conn->databuf),
|
||||
conn->record + 5, &recordlen) != 1) {
|
||||
@@ -1886,6 +2205,7 @@ int tlcp_send(TLS_CONNECT *conn, const uint8_t *in, size_t inlen, size_t *sentle
|
||||
break;
|
||||
|
||||
case TLS_cipher_ecc_sm4_gcm_sm3:
|
||||
case TLS_cipher_ecdhe_sm4_gcm_sm3:
|
||||
if (tls_gcm_encrypt(enc_key, iv, seq_num, conn->databuf,
|
||||
conn->databuf + 5, tls_record_data_length(conn->databuf),
|
||||
conn->record + 5, &recordlen) != 1) {
|
||||
@@ -1977,6 +2297,11 @@ int tlcp_do_client_handshake(TLS_CONNECT *conn)
|
||||
|
||||
case TLS_state_certificate_request:
|
||||
ret = tlcp_recv_certificate_request(conn);
|
||||
if (ret == 0 && tlcp_cipher_suite_is_ecdhe(conn->cipher_suite)) {
|
||||
error_print();
|
||||
tls_send_alert(conn, TLS_alert_handshake_failure);
|
||||
return -1;
|
||||
}
|
||||
if (ret == 1) conn->client_certificate_verify = 1;
|
||||
next_state = TLS_state_server_hello_done;
|
||||
break;
|
||||
|
||||
41
src/tls.c
41
src/tls.c
@@ -3077,6 +3077,29 @@ static int tls_ctx_get_certificate_chain(const TLS_CTX *ctx, size_t idx,
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int tls_cipher_suite_is_tlcp_ecdhe(int cipher_suite)
|
||||
{
|
||||
switch (cipher_suite) {
|
||||
case TLS_cipher_ecdhe_sm4_cbc_sm3:
|
||||
case TLS_cipher_ecdhe_sm4_gcm_sm3:
|
||||
return 1;
|
||||
default:
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
static int tls_ctx_has_tlcp_ecdhe_cipher_suite(const TLS_CTX *ctx)
|
||||
{
|
||||
size_t i;
|
||||
|
||||
for (i = 0; i < ctx->cipher_suites_cnt; i++) {
|
||||
if (tls_cipher_suite_is_tlcp_ecdhe(ctx->cipher_suites[i])) {
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int tls_ctx_check(const TLS_CTX *ctx)
|
||||
{
|
||||
const int *supported_cipher_suites = NULL;
|
||||
@@ -3088,6 +3111,7 @@ static int tls_ctx_check(const TLS_CTX *ctx)
|
||||
const uint8_t *cert_chains;
|
||||
size_t cert_chains_len;
|
||||
size_t cert_chains_cnt = 0;
|
||||
int tlcp_client_needs_double_certs = 0;
|
||||
size_t i;
|
||||
|
||||
if (!ctx) {
|
||||
@@ -3137,6 +3161,9 @@ static int tls_ctx_check(const TLS_CTX *ctx)
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
if (ctx->protocol == TLS_protocol_tlcp && ctx->is_client) {
|
||||
tlcp_client_needs_double_certs = tls_ctx_has_tlcp_ecdhe_cipher_suite(ctx);
|
||||
}
|
||||
|
||||
if (ctx->supported_groups_cnt > sizeof(ctx->supported_groups)/sizeof(ctx->supported_groups[0])) {
|
||||
error_print();
|
||||
@@ -3249,6 +3276,7 @@ static int tls_ctx_check(const TLS_CTX *ctx)
|
||||
const uint8_t *cert_chain;
|
||||
size_t cert_chain_len;
|
||||
size_t certs_cnt;
|
||||
size_t key_idx = cert_chains_cnt;
|
||||
|
||||
if (tls_uint24array_from_bytes(&cert_chain, &cert_chain_len,
|
||||
&cert_chains, &cert_chains_len) != 1
|
||||
@@ -3264,6 +3292,14 @@ static int tls_ctx_check(const TLS_CTX *ctx)
|
||||
error_print();
|
||||
return -1;
|
||||
}
|
||||
if (tlcp_client_needs_double_certs) {
|
||||
if (certs_cnt < 2
|
||||
|| ctx->enc_keys[key_idx].algor != OID_ec_public_key
|
||||
|| ctx->enc_keys[key_idx].algor_param != OID_sm2) {
|
||||
error_print();
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
cert_chains_cnt++;
|
||||
}
|
||||
|
||||
@@ -3272,6 +3308,11 @@ static int tls_ctx_check(const TLS_CTX *ctx)
|
||||
error_print();
|
||||
return -1;
|
||||
}
|
||||
} else if (tlcp_client_needs_double_certs) {
|
||||
if (!ctx->cert_chains_len || !ctx->x509_keys_cnt || cert_chains_cnt != ctx->x509_keys_cnt) {
|
||||
error_print();
|
||||
return -1;
|
||||
}
|
||||
} else if (ctx->cert_chains_len) {
|
||||
if (!ctx->x509_keys_cnt || cert_chains_cnt != ctx->x509_keys_cnt) {
|
||||
error_print();
|
||||
|
||||
124
src/tls12.c
124
src/tls12.c
@@ -14,6 +14,7 @@
|
||||
#include <string.h>
|
||||
#include <assert.h>
|
||||
#include <gmssl/x509.h>
|
||||
#include <gmssl/x509_ext.h>
|
||||
#include <gmssl/error.h>
|
||||
#include <gmssl/sm2.h>
|
||||
#include <gmssl/sm3.h>
|
||||
@@ -1676,9 +1677,91 @@ int tls_recv_server_hello_done(TLS_CONNECT *conn)
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int tlcp_cert_is_encryption_cert(const uint8_t *cert, size_t certlen)
|
||||
{
|
||||
int ret;
|
||||
int critical;
|
||||
const uint8_t *exts;
|
||||
size_t extslen;
|
||||
const uint8_t *val;
|
||||
size_t vlen;
|
||||
int bits;
|
||||
|
||||
if (!cert || !certlen) {
|
||||
error_print();
|
||||
return -1;
|
||||
}
|
||||
if ((ret = x509_cert_get_exts(cert, certlen, &exts, &extslen)) != 1) {
|
||||
if (ret) error_print();
|
||||
return ret;
|
||||
}
|
||||
if ((ret = x509_exts_get_ext_by_oid(exts, extslen, OID_ce_key_usage,
|
||||
&critical, &val, &vlen)) != 1) {
|
||||
if (ret) error_print();
|
||||
return ret;
|
||||
}
|
||||
if (x509_key_usage_from_der(&bits, &val, &vlen) != 1
|
||||
|| asn1_length_is_zero(vlen) != 1) {
|
||||
error_print();
|
||||
return -1;
|
||||
}
|
||||
return (bits & X509_KU_KEY_ENCIPHERMENT) ? 1 : 0;
|
||||
}
|
||||
|
||||
static int tlcp_client_certs_without_encryption_cert(const uint8_t *certs, size_t certslen,
|
||||
uint8_t *out, size_t *outlen, size_t maxlen)
|
||||
{
|
||||
const uint8_t *p = certs;
|
||||
size_t len = certslen;
|
||||
size_t cert_idx = 0;
|
||||
|
||||
if (!certs || !certslen || !out || !outlen) {
|
||||
error_print();
|
||||
return -1;
|
||||
}
|
||||
|
||||
*outlen = 0;
|
||||
while (len) {
|
||||
const uint8_t *cert_der = p;
|
||||
const uint8_t *cert;
|
||||
size_t certlen;
|
||||
size_t derlen;
|
||||
int skip = 0;
|
||||
|
||||
if (x509_cert_from_der(&cert, &certlen, &p, &len) != 1) {
|
||||
error_print();
|
||||
return -1;
|
||||
}
|
||||
derlen = (size_t)(p - cert_der);
|
||||
if (cert_idx == 1) {
|
||||
int ret = tlcp_cert_is_encryption_cert(cert, certlen);
|
||||
if (ret < 0) {
|
||||
error_print();
|
||||
return -1;
|
||||
}
|
||||
skip = ret;
|
||||
}
|
||||
if (!skip) {
|
||||
if (*outlen > maxlen || derlen > maxlen - *outlen) {
|
||||
error_print();
|
||||
return -1;
|
||||
}
|
||||
memcpy(out + *outlen, cert_der, derlen);
|
||||
*outlen += derlen;
|
||||
}
|
||||
cert_idx++;
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
int tls_send_client_certificate(TLS_CONNECT *conn)
|
||||
{
|
||||
int ret;
|
||||
const uint8_t *client_certs;
|
||||
size_t client_certs_len;
|
||||
uint8_t client_certs_without_enc[TLS_MAX_CERTIFICATES_SIZE];
|
||||
size_t client_certs_without_enc_len;
|
||||
|
||||
if(conn->verbose) tls_trace("send client Certificate\n");
|
||||
|
||||
if (conn->client_certs_len == 0) {
|
||||
@@ -1687,8 +1770,23 @@ int tls_send_client_certificate(TLS_CONNECT *conn)
|
||||
}
|
||||
|
||||
if (conn->recordlen == 0) {
|
||||
client_certs = conn->client_certs;
|
||||
client_certs_len = conn->client_certs_len;
|
||||
if (conn->protocol == TLS_protocol_tlcp
|
||||
&& (conn->cipher_suite == TLS_cipher_ecc_sm4_cbc_sm3
|
||||
|| conn->cipher_suite == TLS_cipher_ecc_sm4_gcm_sm3)) {
|
||||
if (tlcp_client_certs_without_encryption_cert(conn->client_certs, conn->client_certs_len,
|
||||
client_certs_without_enc, &client_certs_without_enc_len,
|
||||
sizeof(client_certs_without_enc)) != 1) {
|
||||
error_print();
|
||||
tls_send_alert(conn, TLS_alert_internal_error);
|
||||
return -1;
|
||||
}
|
||||
client_certs = client_certs_without_enc;
|
||||
client_certs_len = client_certs_without_enc_len;
|
||||
}
|
||||
if (tls_record_set_handshake_certificate(conn->record, &conn->recordlen,
|
||||
conn->client_certs, conn->client_certs_len) != 1) {
|
||||
client_certs, client_certs_len) != 1) {
|
||||
error_print();
|
||||
tls_send_alert(conn, TLS_alert_internal_error);
|
||||
return -1;
|
||||
@@ -2747,6 +2845,30 @@ int tls_recv_client_certificate(TLS_CONNECT *conn)
|
||||
}
|
||||
conn->verify_result = verify_result;
|
||||
|
||||
if (conn->protocol == TLS_protocol_tlcp
|
||||
&& (conn->cipher_suite == TLS_cipher_ecdhe_sm4_cbc_sm3
|
||||
|| conn->cipher_suite == TLS_cipher_ecdhe_sm4_gcm_sm3)) {
|
||||
const uint8_t *enc_cert;
|
||||
size_t enc_cert_len;
|
||||
|
||||
if (x509_certs_get_cert_by_index(conn->client_certs, conn->client_certs_len,
|
||||
1, &enc_cert, &enc_cert_len) != 1) {
|
||||
error_print();
|
||||
tls_send_alert(conn, TLS_alert_bad_certificate);
|
||||
return -1;
|
||||
}
|
||||
ret = tlcp_cert_is_encryption_cert(enc_cert, enc_cert_len);
|
||||
if (ret < 0) {
|
||||
error_print();
|
||||
tls_send_alert(conn, TLS_alert_bad_certificate);
|
||||
return -1;
|
||||
} else if (ret == 0) {
|
||||
error_print();
|
||||
tls_send_alert(conn, TLS_alert_unsupported_certificate);
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
if (digest_update(&conn->dgst_ctx, conn->record + 5, conn->recordlen - 5) != 1) {
|
||||
error_print();
|
||||
|
||||
@@ -287,7 +287,7 @@ int tls_ctx_set_certificate_and_key(TLS_CTX *ctx, const char *chainfile,
|
||||
return 1;
|
||||
}
|
||||
|
||||
int tlcp_ctx_add_server_certificate_and_keys(TLS_CTX *ctx, const char *chainfile,
|
||||
static int tlcp_ctx_add_certificate_and_keys(TLS_CTX *ctx, const char *chainfile,
|
||||
const char *keyfile, const char *keypass)
|
||||
{
|
||||
int ret = -1;
|
||||
@@ -314,7 +314,7 @@ int tlcp_ctx_add_server_certificate_and_keys(TLS_CTX *ctx, const char *chainfile
|
||||
error_print();
|
||||
return -1;
|
||||
}
|
||||
if (ctx->protocol != TLS_protocol_tlcp || ctx->is_client) {
|
||||
if (ctx->protocol != TLS_protocol_tlcp) {
|
||||
error_print();
|
||||
return -1;
|
||||
}
|
||||
@@ -397,6 +397,34 @@ end:
|
||||
return ret;
|
||||
}
|
||||
|
||||
int tlcp_ctx_add_server_certificate_and_keys(TLS_CTX *ctx, const char *chainfile,
|
||||
const char *keyfile, const char *keypass)
|
||||
{
|
||||
if (!ctx || ctx->is_client) {
|
||||
error_print();
|
||||
return -1;
|
||||
}
|
||||
if (tlcp_ctx_add_certificate_and_keys(ctx, chainfile, keyfile, keypass) != 1) {
|
||||
error_print();
|
||||
return -1;
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
int tlcp_ctx_add_client_certificate_and_keys(TLS_CTX *ctx, const char *chainfile,
|
||||
const char *keyfile, const char *keypass)
|
||||
{
|
||||
if (!ctx || !ctx->is_client) {
|
||||
error_print();
|
||||
return -1;
|
||||
}
|
||||
if (tlcp_ctx_add_certificate_and_keys(ctx, chainfile, keyfile, keypass) != 1) {
|
||||
error_print();
|
||||
return -1;
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
int tls_ctx_set_tlcp_server_certificate_and_keys(TLS_CTX *ctx, const char *chainfile,
|
||||
const char *keyfile, const char *keypass)
|
||||
{
|
||||
@@ -412,6 +440,21 @@ int tls_ctx_set_tlcp_server_certificate_and_keys(TLS_CTX *ctx, const char *chain
|
||||
return 1;
|
||||
}
|
||||
|
||||
int tls_ctx_set_tlcp_client_certificate_and_keys(TLS_CTX *ctx, const char *chainfile,
|
||||
const char *keyfile, const char *keypass)
|
||||
{
|
||||
if (!ctx || ctx->cert_chains_len || ctx->x509_keys_cnt) {
|
||||
error_print();
|
||||
return -1;
|
||||
}
|
||||
if (tlcp_ctx_add_client_certificate_and_keys(ctx, chainfile,
|
||||
keyfile, keypass) != 1) {
|
||||
error_print();
|
||||
return -1;
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
int tls_authorities_issued_certificate(const uint8_t *ca_names, size_t ca_names_len, const uint8_t *certs, size_t certslen)
|
||||
{
|
||||
const uint8_t *cert;
|
||||
@@ -584,4 +627,3 @@ int tls12_cert_chains_select(const uint8_t *cert_chains, size_t cert_chains_len,
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -101,6 +101,17 @@ static int tls12_signature_scheme_from_cipher_suite(int cipher_suite)
|
||||
}
|
||||
}
|
||||
|
||||
static int tls_cipher_suite_is_tlcp_ecdhe(int cipher_suite)
|
||||
{
|
||||
switch (cipher_suite) {
|
||||
case TLS_cipher_ecdhe_sm4_cbc_sm3:
|
||||
case TLS_cipher_ecdhe_sm4_gcm_sm3:
|
||||
return 1;
|
||||
default:
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
static int tls_cert_chain_check_name(const uint8_t *cert_chain, size_t cert_chain_len,
|
||||
const uint8_t *host_name, size_t host_name_len, int *verify_result)
|
||||
{
|
||||
@@ -398,7 +409,10 @@ int tls_cert_chain_verify(
|
||||
}
|
||||
|
||||
if (verify_chain) {
|
||||
if (protocol == TLS_protocol_tlcp && cert_chain_type == X509_cert_chain_server) {
|
||||
if (protocol == TLS_protocol_tlcp
|
||||
&& (cert_chain_type == X509_cert_chain_server
|
||||
|| (cert_chain_type == X509_cert_chain_client
|
||||
&& tls_cipher_suite_is_tlcp_ecdhe(cipher_suite)))) {
|
||||
ret = x509_certs_verify_tlcp(cert_chain, cert_chain_len, cert_chain_type,
|
||||
cacerts, cacerts_len, crl, crl_len, ocsp, ocsp_len,
|
||||
verify_depth, verify_result);
|
||||
|
||||
@@ -2116,7 +2116,7 @@ int x509_certs_verify(const uint8_t *certs, size_t certslen, int certs_type,
|
||||
return 1;
|
||||
}
|
||||
|
||||
// 只有 TLCP 的服务器证书链才是双证书,客户端证书和TLS12是一样的
|
||||
// TLCP ECC server and TLCP ECDHE client certificate chains use dual entity certificates.
|
||||
int x509_certs_verify_tlcp(const uint8_t *certs, size_t certslen, int certs_type,
|
||||
const uint8_t *rootcerts, size_t rootcertslen,
|
||||
const uint8_t *crl, size_t crl_len,
|
||||
@@ -2144,6 +2144,10 @@ int x509_certs_verify_tlcp(const uint8_t *certs, size_t certslen, int certs_type
|
||||
sign_cert_type = X509_cert_server_auth;
|
||||
kenc_cert_type = X509_cert_server_key_encipher;
|
||||
break;
|
||||
case X509_cert_chain_client:
|
||||
sign_cert_type = X509_cert_client_auth;
|
||||
kenc_cert_type = X509_cert_client_key_encipher;
|
||||
break;
|
||||
default:
|
||||
error_print();
|
||||
x509_verify_set_result(verify_result, X509_verify_err_certificate);
|
||||
|
||||
90
tests/sm2_exchtest.c
Normal file
90
tests/sm2_exchtest.c
Normal file
@@ -0,0 +1,90 @@
|
||||
/*
|
||||
* Copyright 2014-2026 The GmSSL Project. All Rights Reserved.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the License); you may
|
||||
* not use this file except in compliance with the License.
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*/
|
||||
|
||||
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include <gmssl/error.h>
|
||||
#include <gmssl/sm2.h>
|
||||
|
||||
|
||||
static int test_sm2_key_exchange(void)
|
||||
{
|
||||
SM2_KEY a;
|
||||
SM2_KEY b;
|
||||
SM2_KEY ra;
|
||||
SM2_KEY rb;
|
||||
uint8_t ra_octets[65];
|
||||
uint8_t rb_octets[65];
|
||||
uint8_t ua[65];
|
||||
uint8_t vb[65];
|
||||
uint8_t ska[48];
|
||||
uint8_t skb[48];
|
||||
uint8_t sa[32];
|
||||
uint8_t sb[32];
|
||||
const char ida[] = "Alice";
|
||||
const char idb[] = "Bob";
|
||||
|
||||
if (sm2_key_generate(&a) != 1
|
||||
|| sm2_key_generate(&b) != 1
|
||||
|| sm2_key_generate(&ra) != 1
|
||||
|| sm2_key_generate(&rb) != 1
|
||||
|| sm2_z256_point_to_uncompressed_octets(&ra.public_key, ra_octets) != 1
|
||||
|| sm2_z256_point_to_uncompressed_octets(&rb.public_key, rb_octets) != 1) {
|
||||
error_print();
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (sm2_key_exchange(1, &a, ida, sizeof(ida) - 1, &b, idb, sizeof(idb) - 1,
|
||||
&ra, rb_octets, ua, sizeof(ska), ska) != 1
|
||||
|| sm2_key_exchange(0, &b, idb, sizeof(idb) - 1, &a, ida, sizeof(ida) - 1,
|
||||
&rb, ra_octets, vb, sizeof(skb), skb) != 1) {
|
||||
error_print();
|
||||
return -1;
|
||||
}
|
||||
if (memcmp(ska, skb, sizeof(ska)) != 0 || memcmp(ua, vb, sizeof(ua)) != 0) {
|
||||
error_print();
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (sm2_key_exchange_compute_confirm(1, &a, ida, sizeof(ida) - 1, &b, idb, sizeof(idb) - 1,
|
||||
&ra, rb_octets, ua, sa) != 1
|
||||
|| sm2_key_exchange_compute_confirm(0, &b, idb, sizeof(idb) - 1, &a, ida, sizeof(ida) - 1,
|
||||
&rb, ra_octets, vb, sb) != 1) {
|
||||
error_print();
|
||||
return -1;
|
||||
}
|
||||
if (sm2_key_exchange_verify_confirm(1, &a, ida, sizeof(ida) - 1, &b, idb, sizeof(idb) - 1,
|
||||
&ra, rb_octets, ua, sb) != 1
|
||||
|| sm2_key_exchange_verify_confirm(0, &b, idb, sizeof(idb) - 1, &a, ida, sizeof(ida) - 1,
|
||||
&rb, ra_octets, vb, sa) != 1) {
|
||||
error_print();
|
||||
return -1;
|
||||
}
|
||||
|
||||
sb[0] ^= 0x01;
|
||||
if (sm2_key_exchange_verify_confirm(1, &a, ida, sizeof(ida) - 1, &b, idb, sizeof(idb) - 1,
|
||||
&ra, rb_octets, ua, sb) != 0) {
|
||||
error_print();
|
||||
return -1;
|
||||
}
|
||||
|
||||
printf("%s() ok\n", __FUNCTION__);
|
||||
return 1;
|
||||
}
|
||||
|
||||
int main(void)
|
||||
{
|
||||
if (test_sm2_key_exchange() != 1) goto err;
|
||||
printf("%s all tests passed\n", __FILE__);
|
||||
return 0;
|
||||
err:
|
||||
error_print();
|
||||
return -1;
|
||||
}
|
||||
@@ -37,8 +37,8 @@ static const char *help =
|
||||
" -sig_alg str Supported signature algorithms\n"
|
||||
" -cacert pem Trusted CA certificate(s) in PEM format\n"
|
||||
" -verify_depth num Certificate verification depth\n"
|
||||
" -cert pem Client certificate(s) in PEM format\n"
|
||||
" -key pem Private key of client certificate in PEM format\n"
|
||||
" -cert pem Client certificate(s) in PEM format, TLCP ECDHE requires a double certificate chain\n"
|
||||
" -key pem Private key of client certificate in PEM format, TLCP ECDHE requires signing and encryption keys\n"
|
||||
" -pass password Password of encrypted private key\n"
|
||||
" -client_cert_optional Allow client send empty Certificate\n"
|
||||
" -get path Send a GET request with given path of URI\n"
|
||||
@@ -53,6 +53,29 @@ static const char *help =
|
||||
#include "tlcp_help.h"
|
||||
"\n";
|
||||
|
||||
static int tlcp_cipher_suite_is_ecdhe(int cipher_suite)
|
||||
{
|
||||
switch (cipher_suite) {
|
||||
case TLS_cipher_ecdhe_sm4_cbc_sm3:
|
||||
case TLS_cipher_ecdhe_sm4_gcm_sm3:
|
||||
return 1;
|
||||
default:
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
static int tlcp_cipher_suites_have_ecdhe(const int *cipher_suites, size_t cipher_suites_cnt)
|
||||
{
|
||||
size_t i;
|
||||
|
||||
for (i = 0; i < cipher_suites_cnt; i++) {
|
||||
if (tlcp_cipher_suite_is_ecdhe(cipher_suites[i])) {
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
static int do_handshake_select(TLS_CONNECT *conn)
|
||||
{
|
||||
@@ -228,6 +251,7 @@ int tlcp_client_main(int argc, char *argv[])
|
||||
char *infile = NULL;
|
||||
char *certoutfile = NULL;
|
||||
int verbose = 0;
|
||||
int has_ecdhe_cipher_suite = 0;
|
||||
struct sockaddr_in server;
|
||||
tls_socket_t sock = tls_socket_invalid();
|
||||
TLS_CTX ctx;
|
||||
@@ -379,6 +403,11 @@ bad:
|
||||
fprintf(stderr, "%s: '-get' and '-in' should not be used together\n", prog);
|
||||
return -1;
|
||||
}
|
||||
has_ecdhe_cipher_suite = tlcp_cipher_suites_have_ecdhe(cipher_suites, cipher_suites_cnt);
|
||||
if (has_ecdhe_cipher_suite && (!certfile || !keyfile || !pass)) {
|
||||
fprintf(stderr, "%s: TLCP ECDHE cipher suites require '-cert', '-key' and '-pass' with a double certificate chain\n", prog);
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (tls_socket_lib_init() != 1) {
|
||||
error_print();
|
||||
@@ -447,9 +476,16 @@ bad:
|
||||
fprintf(stderr, "%s: option '-pass' missing\n", prog);
|
||||
goto end;
|
||||
}
|
||||
if (tls_ctx_set_certificate_and_key(&ctx, certfile, keyfile, pass) != 1) {
|
||||
fprintf(stderr, "%s: failed to load client certificate\n", prog);
|
||||
goto end;
|
||||
if (has_ecdhe_cipher_suite) {
|
||||
if (tls_ctx_set_tlcp_client_certificate_and_keys(&ctx, certfile, keyfile, pass) != 1) {
|
||||
fprintf(stderr, "%s: failed to load TLCP client double certificate chain and keys\n", prog);
|
||||
goto end;
|
||||
}
|
||||
} else {
|
||||
if (tls_ctx_set_certificate_and_key(&ctx, certfile, keyfile, pass) != 1) {
|
||||
fprintf(stderr, "%s: failed to load client certificate\n", prog);
|
||||
goto end;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -11,6 +11,8 @@
|
||||
"Supported cipher suites:\n"
|
||||
" TLS_ECC_SM4_CBC_SM3\n"
|
||||
" TLS_ECC_SM4_GCM_SM3\n"
|
||||
" TLS_ECDHE_SM4_CBC_SM3\n"
|
||||
" TLS_ECDHE_SM4_GCM_SM3\n"
|
||||
"\n"
|
||||
"\n"
|
||||
"Examples\n"
|
||||
|
||||
Reference in New Issue
Block a user