mirror of
https://github.com/guanzhi/GmSSL.git
synced 2026-05-06 16:36:16 +08:00
Update TLCP to state machine
This commit is contained in:
@@ -652,6 +652,7 @@ int tls_record_get_handshake_finished(const uint8_t *record,
|
|||||||
int tls_finished_print(FILE *fp, const uint8_t *a, size_t len, int format, int indent);
|
int tls_finished_print(FILE *fp, const uint8_t *a, size_t len, int format, int indent);
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
// Alert
|
// Alert
|
||||||
typedef struct {
|
typedef struct {
|
||||||
uint8_t level;
|
uint8_t level;
|
||||||
@@ -739,14 +740,52 @@ void tls_ctx_cleanup(TLS_CTX *ctx);
|
|||||||
#define TLS_ERROR_SYSCALL -1003 // SSL_ERROR_SYSCALL
|
#define TLS_ERROR_SYSCALL -1003 // SSL_ERROR_SYSCALL
|
||||||
|
|
||||||
|
|
||||||
|
enum {
|
||||||
|
TLS_state_handshake_init = 0,
|
||||||
|
TLS_state_client_hello,
|
||||||
|
TLS_state_server_hello,
|
||||||
|
TLS_state_server_certificate,
|
||||||
|
TLS_state_server_key_exchange,
|
||||||
|
TLS_state_certificate_request,
|
||||||
|
TLS_state_server_hello_done,
|
||||||
|
TLS_state_client_certificate,
|
||||||
|
TLS_state_client_key_exchange,
|
||||||
|
TLS_state_certificate_verify,
|
||||||
|
TLS_state_generate_keys,
|
||||||
|
TLS_state_client_change_cipher_spec,
|
||||||
|
TLS_state_client_finished,
|
||||||
|
TLS_state_server_change_cipher_spec,
|
||||||
|
TLS_state_server_finished,
|
||||||
|
TLS_state_handshake_over,
|
||||||
|
};
|
||||||
|
|
||||||
typedef struct {
|
typedef struct {
|
||||||
int protocol;
|
|
||||||
int is_client;
|
int is_client;
|
||||||
|
|
||||||
|
|
||||||
|
int protocol;
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
服务器端在初始化之后,会创建一个server_ciphers列表
|
||||||
|
在接收到client_ciphers之后,和自己的server_ciphers对比,选择出conn->cipher
|
||||||
|
也可能没有找到一致的cipher,那么就失败了
|
||||||
|
实际上服务器端的ciphers可以完全来自CTX,并不需要缓存
|
||||||
|
|
||||||
|
客户端在初始化之后,创建client_ciphers,发送给服务器
|
||||||
|
在接收到服务器的cipher后,要判断这个cipher是否在自己的client_ciphers之中
|
||||||
|
但是客户端是需要缓存ciphers的,这样才能够判断返回的cipher是否在自己的ciphers之中
|
||||||
|
|
||||||
|
下面的问题是在CONN中要维护哪些信息?
|
||||||
|
*/
|
||||||
|
|
||||||
|
|
||||||
int cipher_suites[TLS_MAX_CIPHER_SUITES_COUNT];
|
int cipher_suites[TLS_MAX_CIPHER_SUITES_COUNT];
|
||||||
size_t cipher_suites_cnt;
|
size_t cipher_suites_cnt;
|
||||||
|
int cipher_suite;
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
tls_socket_t sock;
|
tls_socket_t sock;
|
||||||
|
|
||||||
uint8_t enced_record[TLS_MAX_RECORD_SIZE];
|
uint8_t enced_record[TLS_MAX_RECORD_SIZE];
|
||||||
@@ -764,7 +803,6 @@ typedef struct {
|
|||||||
uint8_t *data;
|
uint8_t *data;
|
||||||
size_t datalen;
|
size_t datalen;
|
||||||
|
|
||||||
int cipher_suite;
|
|
||||||
uint8_t session_id[32];
|
uint8_t session_id[32];
|
||||||
size_t session_id_len;
|
size_t session_id_len;
|
||||||
uint8_t server_certs[TLS_MAX_CERTIFICATES_SIZE]; // TODO: use ptr and malloc
|
uint8_t server_certs[TLS_MAX_CERTIFICATES_SIZE]; // TODO: use ptr and malloc
|
||||||
@@ -775,9 +813,11 @@ typedef struct {
|
|||||||
size_t ca_certs_len;
|
size_t ca_certs_len;
|
||||||
|
|
||||||
X509_KEY sign_key;
|
X509_KEY sign_key;
|
||||||
X509_KEY kenc_key;
|
X509_KEY kenc_key; // 应该作为服务器的SM2加密
|
||||||
|
X509_KEY server_enc_key;
|
||||||
|
|
||||||
int verify_result;
|
int verify_result;
|
||||||
|
uint8_t pre_master_secret[48]; // 是否可以重用master_secret作为pre_master_secret呢?
|
||||||
uint8_t master_secret[48];
|
uint8_t master_secret[48];
|
||||||
uint8_t key_block[96];
|
uint8_t key_block[96];
|
||||||
|
|
||||||
@@ -833,6 +873,45 @@ typedef struct {
|
|||||||
#define TLS_MAX_EXTENSIONS_SIZE 512 // FIXME: no reason to give fixed max length
|
#define TLS_MAX_EXTENSIONS_SIZE 512 // FIXME: no reason to give fixed max length
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
int tls_send_client_hello(TLS_CONNECT *conn);
|
||||||
|
int tls_recv_client_hello(TLS_CONNECT *conn);
|
||||||
|
int tls_send_server_hello(TLS_CONNECT *conn);
|
||||||
|
int tls_recv_server_hello(TLS_CONNECT *conn);
|
||||||
|
int tls_send_server_certificate(TLS_CONNECT *conn);
|
||||||
|
int tls_recv_server_certificate(TLS_CONNECT *conn);
|
||||||
|
int tls_send_server_key_exchange(TLS_CONNECT *conn);
|
||||||
|
int tls_recv_server_key_exchange(TLS_CONNECT *conn);
|
||||||
|
int tls_send_certificate_request(TLS_CONNECT *conn);
|
||||||
|
int tls_recv_certificate_request(TLS_CONNECT *conn);
|
||||||
|
int tls_send_server_hello_done(TLS_CONNECT *conn);
|
||||||
|
int tls_recv_server_hello_done(TLS_CONNECT *conn);
|
||||||
|
int tls_send_client_certificate(TLS_CONNECT *conn);
|
||||||
|
int tls_recv_client_certificate(TLS_CONNECT *conn);
|
||||||
|
int tls_generate_keys(TLS_CONNECT *conn);
|
||||||
|
int tls_send_client_key_exchange(TLS_CONNECT *conn);
|
||||||
|
int tls_recv_client_key_exchange(TLS_CONNECT *conn);
|
||||||
|
int tls_send_certificate_verify(TLS_CONNECT *conn);
|
||||||
|
int tls_recv_certificate_verify(TLS_CONNECT *conn);
|
||||||
|
int tls_send_change_cipher_spec(TLS_CONNECT *conn);
|
||||||
|
int tls_recv_change_cipher_spec(TLS_CONNECT *conn);
|
||||||
|
int tls_send_client_finished(TLS_CONNECT *conn);
|
||||||
|
int tls_recv_client_finished(TLS_CONNECT *conn);
|
||||||
|
int tls_send_server_finished(TLS_CONNECT *conn);
|
||||||
|
int tls_recv_server_finished(TLS_CONNECT *conn);
|
||||||
|
|
||||||
|
int tlcp_send_client_hello(TLS_CONNECT *conn);
|
||||||
|
int tlcp_recv_client_hello(TLS_CONNECT *conn);
|
||||||
|
int tlcp_send_server_key_exchange(TLS_CONNECT *conn);
|
||||||
|
int tlcp_recv_server_key_exchange(TLS_CONNECT *conn);
|
||||||
|
int tlcp_generate_keys(TLS_CONNECT *conn);
|
||||||
|
int tlcp_send_client_key_exchange(TLS_CONNECT *conn);
|
||||||
|
int tlcp_recv_client_key_exchange(TLS_CONNECT *conn);
|
||||||
|
|
||||||
|
void tls_clean_record(TLS_CONNECT *conn);
|
||||||
|
|
||||||
|
|
||||||
int tls_init(TLS_CONNECT *conn, const TLS_CTX *ctx);
|
int tls_init(TLS_CONNECT *conn, const TLS_CTX *ctx);
|
||||||
int tls_set_socket(TLS_CONNECT *conn, tls_socket_t sock);
|
int tls_set_socket(TLS_CONNECT *conn, tls_socket_t sock);
|
||||||
int tls_do_handshake(TLS_CONNECT *conn);
|
int tls_do_handshake(TLS_CONNECT *conn);
|
||||||
@@ -916,6 +995,17 @@ int tls13_gcm_decrypt(const BLOCK_CIPHER_KEY *key, const uint8_t iv[12],
|
|||||||
|
|
||||||
int tls_encrypted_record_print(FILE *fp, const uint8_t *record, size_t recordlen, int format, int indent);
|
int tls_encrypted_record_print(FILE *fp, const uint8_t *record, size_t recordlen, int format, int indent);
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
#ifdef __cplusplus
|
#ifdef __cplusplus
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|||||||
@@ -600,9 +600,6 @@ int sm2_sign_finish_fixlen(SM2_SIGN_CTX *ctx, size_t siglen, uint8_t *sig)
|
|||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
sm3_finish(&ctx->sm3_ctx, dgst);
|
sm3_finish(&ctx->sm3_ctx, dgst);
|
||||||
format_bytes(stderr, 0, 4, "signed dgst", dgst, 32);
|
|
||||||
|
|
||||||
|
|
||||||
if (sm2_sign_fixlen(&ctx->key, dgst, siglen, sig) != 1) {
|
if (sm2_sign_fixlen(&ctx->key, dgst, siglen, sig) != 1) {
|
||||||
error_print();
|
error_print();
|
||||||
return -1;
|
return -1;
|
||||||
|
|||||||
417
src/tlcp.c
417
src/tlcp.c
@@ -25,6 +25,21 @@
|
|||||||
#include <gmssl/tls.h>
|
#include <gmssl/tls.h>
|
||||||
|
|
||||||
|
|
||||||
|
// sign_master_public_key, enc_master_public_key, sign_key, enc_key
|
||||||
|
int tls_ctx_set_sm9_keys(TLS_CTX *ctx, const char *masterfile,
|
||||||
|
const char *keyfile, const char *keypass)
|
||||||
|
{
|
||||||
|
// 从masterfile中读取两个
|
||||||
|
|
||||||
|
|
||||||
|
// 从keyfile中读取两个密钥
|
||||||
|
|
||||||
|
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// TLCP的套件和TLS12不一样,我们现在只支持一种
|
||||||
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]);
|
||||||
|
|
||||||
@@ -37,6 +52,8 @@ 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) {
|
select (KeyExchangeAlgorithm) {
|
||||||
case ECC:
|
case ECC:
|
||||||
@@ -49,6 +66,11 @@ select (KeyExchangeAlgorithm) {
|
|||||||
} ServerKeyExchange;
|
} ServerKeyExchange;
|
||||||
|
|
||||||
-- in TLCP 1.1, the `signed_params` is DER signature encoded in uint16array
|
-- in TLCP 1.1, the `signed_params` is DER signature encoded in uint16array
|
||||||
|
|
||||||
|
|
||||||
|
在TLS12中,ServerKeyExchange中是有ECDH公钥的,但是在TLCP中
|
||||||
|
|
||||||
|
|
||||||
*/
|
*/
|
||||||
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)
|
||||||
@@ -128,7 +150,7 @@ int tlcp_server_key_exchange_pke_print(FILE *fp, const uint8_t *data, size_t dat
|
|||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
int tlcp_do_connect(TLS_CONNECT *conn)
|
int _tlcp_do_connect(TLS_CONNECT *conn)
|
||||||
{
|
{
|
||||||
int ret = -1;
|
int ret = -1;
|
||||||
uint8_t *record = conn->record;
|
uint8_t *record = conn->record;
|
||||||
@@ -174,7 +196,7 @@ int tlcp_do_connect(TLS_CONNECT *conn)
|
|||||||
int verify_result;
|
int verify_result;
|
||||||
|
|
||||||
|
|
||||||
// 初始化记录缓冲
|
// 初始化记录缓冲,这里的主要区别在于,版本号是确定的!
|
||||||
tls_record_set_protocol(record, TLS_protocol_tlcp);
|
tls_record_set_protocol(record, TLS_protocol_tlcp);
|
||||||
tls_record_set_protocol(finished_record, TLS_protocol_tlcp);
|
tls_record_set_protocol(finished_record, TLS_protocol_tlcp);
|
||||||
|
|
||||||
@@ -256,9 +278,11 @@ int tlcp_do_connect(TLS_CONNECT *conn)
|
|||||||
sm3_update(&sm3_ctx, record + 5, recordlen - 5);
|
sm3_update(&sm3_ctx, record + 5, recordlen - 5);
|
||||||
|
|
||||||
// verify ServerCertificate
|
// verify ServerCertificate
|
||||||
if (conn->ca_certs_len) {
|
if (conn->ca_certs_len) { // 这里不对啊,如果没准备CA证书,难道就不验证服务器证书了吗
|
||||||
// 只有提供了CA证书才验证服务器证书链
|
// 只有提供了CA证书才验证服务器证书链
|
||||||
// FIXME: 逻辑需要再检查
|
// FIXME: 逻辑需要再检查
|
||||||
|
// 这里验证证书链的逻辑和TLS12不同
|
||||||
|
// 但是证书链的验证逻辑可以根据协议的差异来选择
|
||||||
if (x509_certs_verify_tlcp(conn->server_certs, conn->server_certs_len, X509_cert_chain_server,
|
if (x509_certs_verify_tlcp(conn->server_certs, conn->server_certs_len, X509_cert_chain_server,
|
||||||
conn->ca_certs, conn->ca_certs_len, depth, &verify_result) != 1) {
|
conn->ca_certs, conn->ca_certs_len, depth, &verify_result) != 1) {
|
||||||
error_print();
|
error_print();
|
||||||
@@ -276,6 +300,7 @@ int tlcp_do_connect(TLS_CONNECT *conn)
|
|||||||
goto end;
|
goto end;
|
||||||
}
|
}
|
||||||
tlcp_record_trace(stderr, record, recordlen, 0, 0);
|
tlcp_record_trace(stderr, record, recordlen, 0, 0);
|
||||||
|
// 显然这是一个TLCP独特的版本
|
||||||
if (tlcp_record_get_handshake_server_key_exchange_pke(record, &sig, &siglen) != 1) {
|
if (tlcp_record_get_handshake_server_key_exchange_pke(record, &sig, &siglen) != 1) {
|
||||||
error_print();
|
error_print();
|
||||||
tls_send_alert(conn, TLS_alert_unexpected_message);
|
tls_send_alert(conn, TLS_alert_unexpected_message);
|
||||||
@@ -284,6 +309,7 @@ int tlcp_do_connect(TLS_CONNECT *conn)
|
|||||||
sm3_update(&sm3_ctx, record + 5, recordlen - 5);
|
sm3_update(&sm3_ctx, record + 5, recordlen - 5);
|
||||||
|
|
||||||
// verify ServerKeyExchange
|
// verify ServerKeyExchange
|
||||||
|
// 这个策略应该没有什么不同,因为都是用第一个证书来验证签名
|
||||||
if (x509_certs_get_cert_by_index(conn->server_certs, conn->server_certs_len, 0, &cp, &len) != 1
|
if (x509_certs_get_cert_by_index(conn->server_certs, conn->server_certs_len, 0, &cp, &len) != 1
|
||||||
|| x509_cert_get_subject_public_key(cp, len, &server_sign_key) != 1
|
|| x509_cert_get_subject_public_key(cp, len, &server_sign_key) != 1
|
||||||
|| x509_certs_get_cert_by_index(conn->server_certs, conn->server_certs_len, 1, &server_enc_cert, &server_enc_cert_len) != 1
|
|| x509_certs_get_cert_by_index(conn->server_certs, conn->server_certs_len, 1, &server_enc_cert, &server_enc_cert_len) != 1
|
||||||
@@ -419,8 +445,10 @@ int tlcp_do_connect(TLS_CONNECT *conn)
|
|||||||
|
|
||||||
// send ClientKeyExchange
|
// send ClientKeyExchange
|
||||||
tls_trace("send ClientKeyExchange\n");
|
tls_trace("send ClientKeyExchange\n");
|
||||||
|
// 这里是比较特殊的,这里应该改为用X509_KEY的API,这样可以支持SM9等
|
||||||
if (sm2_encrypt(&server_enc_key.u.sm2_key, pre_master_secret, 48,
|
if (sm2_encrypt(&server_enc_key.u.sm2_key, pre_master_secret, 48,
|
||||||
enced_pre_master_secret, &enced_pre_master_secret_len) != 1
|
enced_pre_master_secret, &enced_pre_master_secret_len) != 1
|
||||||
|
// 这个函数是TLCP专属的
|
||||||
|| tls_record_set_handshake_client_key_exchange_pke(record, &recordlen,
|
|| tls_record_set_handshake_client_key_exchange_pke(record, &recordlen,
|
||||||
enced_pre_master_secret, enced_pre_master_secret_len) != 1) {
|
enced_pre_master_secret, enced_pre_master_secret_len) != 1) {
|
||||||
error_print();
|
error_print();
|
||||||
@@ -580,7 +608,7 @@ end:
|
|||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
int tlcp_do_accept(TLS_CONNECT *conn)
|
int _tlcp_do_accept(TLS_CONNECT *conn)
|
||||||
{
|
{
|
||||||
int ret = -1;
|
int ret = -1;
|
||||||
|
|
||||||
@@ -680,7 +708,7 @@ int tlcp_do_accept(TLS_CONNECT *conn)
|
|||||||
goto end;
|
goto end;
|
||||||
}
|
}
|
||||||
if (exts) {
|
if (exts) {
|
||||||
// 忽略客户端扩展错误可以兼容错误的TLCP客户端实现
|
// 忽略客户端扩展错误可以兼容错误的TLCP客户端实现
|
||||||
error_print();
|
error_print();
|
||||||
tls_send_alert(conn, TLS_alert_unexpected_message);
|
tls_send_alert(conn, TLS_alert_unexpected_message);
|
||||||
goto end;
|
goto end;
|
||||||
@@ -738,6 +766,7 @@ int tlcp_do_accept(TLS_CONNECT *conn)
|
|||||||
tls_send_alert(conn, TLS_alert_internal_error);
|
tls_send_alert(conn, TLS_alert_internal_error);
|
||||||
goto end;
|
goto end;
|
||||||
}
|
}
|
||||||
|
// 需要检查一下TLCP和TLS12在这个消息上的差异是什么
|
||||||
if (tlcp_record_set_handshake_server_key_exchange_pke(record, &recordlen, sigbuf, siglen) != 1) {
|
if (tlcp_record_set_handshake_server_key_exchange_pke(record, &recordlen, sigbuf, siglen) != 1) {
|
||||||
error_print();
|
error_print();
|
||||||
tls_send_alert(conn, TLS_alert_internal_error);
|
tls_send_alert(conn, TLS_alert_internal_error);
|
||||||
@@ -819,11 +848,13 @@ int tlcp_do_accept(TLS_CONNECT *conn)
|
|||||||
goto end;
|
goto end;
|
||||||
}
|
}
|
||||||
tlcp_record_trace(stderr, record, recordlen, 0, 0);
|
tlcp_record_trace(stderr, record, recordlen, 0, 0);
|
||||||
|
// tls_record_get_handshake_client_key_exchange_pke 这个函数有问题,只用于TLCP的,应该放在TLCP文件中
|
||||||
if (tls_record_get_handshake_client_key_exchange_pke(record, &enced_pms, &enced_pms_len) != 1) {
|
if (tls_record_get_handshake_client_key_exchange_pke(record, &enced_pms, &enced_pms_len) != 1) {
|
||||||
error_print();
|
error_print();
|
||||||
tls_send_alert(conn, TLS_alert_unexpected_message);
|
tls_send_alert(conn, TLS_alert_unexpected_message);
|
||||||
goto end;
|
goto end;
|
||||||
}
|
}
|
||||||
|
// 这个处理是TLCP专属的
|
||||||
if (sm2_decrypt(&conn->kenc_key.u.sm2_key, enced_pms, enced_pms_len,
|
if (sm2_decrypt(&conn->kenc_key.u.sm2_key, enced_pms, enced_pms_len,
|
||||||
pre_master_secret, &pre_master_secret_len) != 1) {
|
pre_master_secret, &pre_master_secret_len) != 1) {
|
||||||
error_print();
|
error_print();
|
||||||
@@ -1021,3 +1052,379 @@ end:
|
|||||||
gmssl_secure_clear(pre_master_secret, sizeof(pre_master_secret));
|
gmssl_secure_clear(pre_master_secret, sizeof(pre_master_secret));
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
SM9_SM4_CBC_SM3
|
||||||
|
|
||||||
|
opaque SM9SignMasterPublicKey<0..2^24-1>;
|
||||||
|
struct {
|
||||||
|
opaque id<1..2^16-1>; // server's domain name, equivalent to entity cert
|
||||||
|
SM9SignMasterPublicKey sign_params; // equavalent to ca root cert, optional
|
||||||
|
} Certificate;
|
||||||
|
|
||||||
|
opaque SM9EncMasterPublicKey<0..2^24-1>;
|
||||||
|
struct {
|
||||||
|
SM9EncMasterPublicKey enc_params;
|
||||||
|
digitally-signed struct {
|
||||||
|
opaque client_random[32];
|
||||||
|
opaque server_random[32];
|
||||||
|
SM9EncMasterPublicKey enc_params;
|
||||||
|
opaque id<1..2^16-1>;
|
||||||
|
} signed_params;
|
||||||
|
} ServerKeyExchange;
|
||||||
|
|
||||||
|
struct {
|
||||||
|
opaque encrypted_pre_master_secret<0..2^16-1>;
|
||||||
|
} ClientKeyExchange
|
||||||
|
|
||||||
|
*/
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
Client Server
|
||||||
|
|
||||||
|
ClientHello -------->
|
||||||
|
ServerHello
|
||||||
|
Certificate
|
||||||
|
ServerKeyExchange
|
||||||
|
CertificateRequest*
|
||||||
|
<-------- ServerHelloDone
|
||||||
|
Certificate*
|
||||||
|
ClientKeyExchange
|
||||||
|
CertificateVerify*
|
||||||
|
[ChangeCipherSpec]
|
||||||
|
Finished -------->
|
||||||
|
[ChangeCipherSpec]
|
||||||
|
<-------- Finished
|
||||||
|
Application Data <-------> Application Data
|
||||||
|
|
||||||
|
|
||||||
|
*/
|
||||||
|
|
||||||
|
int tlcp_do_client_handshake(TLS_CONNECT *conn)
|
||||||
|
{
|
||||||
|
int ret;
|
||||||
|
int next_state;
|
||||||
|
|
||||||
|
switch (conn->state) {
|
||||||
|
case TLS_state_client_hello:
|
||||||
|
ret = tlcp_send_client_hello(conn);
|
||||||
|
next_state = TLS_state_server_hello;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case TLS_state_server_hello:
|
||||||
|
ret = tls_recv_server_hello(conn);
|
||||||
|
next_state = TLS_state_server_certificate;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case TLS_state_server_certificate:
|
||||||
|
ret = tls_recv_server_certificate(conn);
|
||||||
|
next_state = TLS_state_server_key_exchange;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case TLS_state_server_key_exchange:
|
||||||
|
ret = tlcp_recv_server_key_exchange(conn);
|
||||||
|
next_state = TLS_state_certificate_request;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case TLS_state_certificate_request:
|
||||||
|
ret = tls_recv_certificate_request(conn);
|
||||||
|
if (ret == 1) conn->client_certificate_verify = 1;
|
||||||
|
next_state = TLS_state_server_hello_done;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case TLS_state_server_hello_done:
|
||||||
|
ret = tls_recv_server_hello_done(conn);
|
||||||
|
if (conn->client_certificate_verify)
|
||||||
|
next_state = TLS_state_client_certificate;
|
||||||
|
else next_state = TLS_state_client_key_exchange;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case TLS_state_client_certificate:
|
||||||
|
ret = tls_send_client_certificate(conn);
|
||||||
|
next_state = TLS_state_client_key_exchange;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case TLS_state_client_key_exchange:
|
||||||
|
ret = tlcp_send_client_key_exchange(conn);
|
||||||
|
next_state = TLS_state_generate_keys;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case TLS_state_generate_keys:
|
||||||
|
ret = tlcp_generate_keys(conn);
|
||||||
|
if (conn->client_certificate_verify)
|
||||||
|
next_state = TLS_state_certificate_verify;
|
||||||
|
else next_state = TLS_state_client_change_cipher_spec;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case TLS_state_certificate_verify:
|
||||||
|
ret = tls_send_certificate_verify(conn);
|
||||||
|
next_state = TLS_state_client_change_cipher_spec;
|
||||||
|
|
||||||
|
case TLS_state_client_change_cipher_spec:
|
||||||
|
ret = tls_send_change_cipher_spec(conn);
|
||||||
|
next_state = TLS_state_client_finished;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case TLS_state_client_finished:
|
||||||
|
ret = tls_send_client_finished(conn);
|
||||||
|
next_state = TLS_state_server_change_cipher_spec;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case TLS_state_server_change_cipher_spec:
|
||||||
|
ret = tls_recv_change_cipher_spec(conn);
|
||||||
|
next_state = TLS_state_server_finished;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case TLS_state_server_finished:
|
||||||
|
ret = tls_recv_server_finished(conn);
|
||||||
|
next_state = TLS_state_handshake_over;
|
||||||
|
break;
|
||||||
|
|
||||||
|
default:
|
||||||
|
error_print();
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (ret < 0) {
|
||||||
|
if (ret == TLS_ERROR_RECV_AGAIN || ret == TLS_ERROR_SEND_AGAIN) {
|
||||||
|
return ret;
|
||||||
|
} else {
|
||||||
|
error_print();
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
conn->state = next_state;
|
||||||
|
|
||||||
|
// ret == 0 means this step is bypassed
|
||||||
|
if (ret == 1) {
|
||||||
|
tls_clean_record(conn);
|
||||||
|
}
|
||||||
|
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
int tlcp_do_server_handshake(TLS_CONNECT *conn)
|
||||||
|
{
|
||||||
|
int ret;
|
||||||
|
int next_state;
|
||||||
|
|
||||||
|
switch (conn->state) {
|
||||||
|
case TLS_state_client_hello:
|
||||||
|
ret = tlcp_recv_client_hello(conn);
|
||||||
|
next_state = TLS_state_server_hello;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case TLS_state_server_hello:
|
||||||
|
ret = tls_send_server_hello(conn);
|
||||||
|
next_state = TLS_state_server_certificate;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case TLS_state_server_certificate:
|
||||||
|
ret = tls_send_server_certificate(conn);
|
||||||
|
next_state = TLS_state_server_key_exchange;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case TLS_state_server_key_exchange:
|
||||||
|
ret = tlcp_send_server_key_exchange(conn);
|
||||||
|
if (conn->client_certificate_verify)
|
||||||
|
next_state = TLS_state_certificate_request;
|
||||||
|
else next_state = TLS_state_server_hello_done;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case TLS_state_certificate_request:
|
||||||
|
ret = tls_send_certificate_request(conn);
|
||||||
|
next_state = TLS_state_server_hello_done;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case TLS_state_server_hello_done:
|
||||||
|
ret = tls_send_server_hello_done(conn);
|
||||||
|
if (conn->client_certificate_verify)
|
||||||
|
next_state = TLS_state_client_certificate;
|
||||||
|
else next_state = TLS_state_client_key_exchange;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case TLS_state_client_certificate:
|
||||||
|
ret = tls_recv_client_certificate(conn);
|
||||||
|
next_state = TLS_state_client_key_exchange;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case TLS_state_client_key_exchange:
|
||||||
|
ret = tlcp_recv_client_key_exchange(conn);
|
||||||
|
if (conn->client_certificate_verify)
|
||||||
|
next_state = TLS_state_certificate_verify;
|
||||||
|
else next_state = TLS_state_generate_keys;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case TLS_state_certificate_verify:
|
||||||
|
ret = tls_recv_certificate_verify(conn);
|
||||||
|
next_state = TLS_state_generate_keys;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case TLS_state_generate_keys:
|
||||||
|
ret = tlcp_generate_keys(conn);
|
||||||
|
next_state = TLS_state_client_change_cipher_spec;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case TLS_state_client_change_cipher_spec:
|
||||||
|
ret = tls_recv_change_cipher_spec(conn);
|
||||||
|
next_state = TLS_state_client_finished;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case TLS_state_client_finished:
|
||||||
|
ret = tls_recv_client_finished(conn);
|
||||||
|
next_state = TLS_state_server_change_cipher_spec;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case TLS_state_server_change_cipher_spec:
|
||||||
|
ret = tls_send_change_cipher_spec(conn);
|
||||||
|
next_state = TLS_state_server_finished;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case TLS_state_server_finished:
|
||||||
|
ret = tls_send_server_finished(conn);
|
||||||
|
next_state = TLS_state_handshake_over;
|
||||||
|
break;
|
||||||
|
|
||||||
|
default:
|
||||||
|
error_print();
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (ret != 1) {
|
||||||
|
if (ret == TLS_ERROR_RECV_AGAIN || ret == TLS_ERROR_SEND_AGAIN) {
|
||||||
|
return ret;
|
||||||
|
} else {
|
||||||
|
error_print();
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
conn->state = next_state;
|
||||||
|
|
||||||
|
tls_clean_record(conn);
|
||||||
|
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
int tlcp_client_handshake(TLS_CONNECT *conn)
|
||||||
|
{
|
||||||
|
int ret;
|
||||||
|
|
||||||
|
while (conn->state != TLS_state_handshake_over) {
|
||||||
|
|
||||||
|
ret = tlcp_do_client_handshake(conn);
|
||||||
|
|
||||||
|
if (ret != 1) {
|
||||||
|
if (ret != TLS_ERROR_RECV_AGAIN && ret != TLS_ERROR_SEND_AGAIN) {
|
||||||
|
error_print();
|
||||||
|
}
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// TODO: cleanup conn?
|
||||||
|
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
int tlcp_server_handshake(TLS_CONNECT *conn)
|
||||||
|
{
|
||||||
|
int ret;
|
||||||
|
|
||||||
|
|
||||||
|
while (conn->state != TLS_state_handshake_over) {
|
||||||
|
|
||||||
|
ret = tlcp_do_server_handshake(conn);
|
||||||
|
|
||||||
|
if (ret != 1) {
|
||||||
|
if (ret != TLS_ERROR_RECV_AGAIN && ret != TLS_ERROR_SEND_AGAIN) {
|
||||||
|
error_print();
|
||||||
|
}
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// TODO: cleanup conn?
|
||||||
|
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
int tlcp_do_connect(TLS_CONNECT *conn)
|
||||||
|
{
|
||||||
|
int ret;
|
||||||
|
fd_set rfds;
|
||||||
|
fd_set wfds;
|
||||||
|
|
||||||
|
// 应该把protocol_version的初始化放在这里
|
||||||
|
|
||||||
|
conn->state = TLS_state_client_hello;
|
||||||
|
sm3_init(&conn->sm3_ctx);
|
||||||
|
|
||||||
|
while (1) {
|
||||||
|
|
||||||
|
ret = tlcp_client_handshake(conn);
|
||||||
|
if (ret == 1) {
|
||||||
|
break;
|
||||||
|
|
||||||
|
} else if (ret == TLS_ERROR_SEND_AGAIN) {
|
||||||
|
FD_ZERO(&rfds);
|
||||||
|
FD_ZERO(&wfds);
|
||||||
|
FD_SET(conn->sock, &rfds);
|
||||||
|
select(conn->sock + 1, &rfds, &wfds, NULL, NULL);
|
||||||
|
|
||||||
|
} else if (ret == TLS_ERROR_RECV_AGAIN) {
|
||||||
|
FD_ZERO(&rfds);
|
||||||
|
FD_ZERO(&wfds);
|
||||||
|
FD_SET(conn->sock, &wfds);
|
||||||
|
select(conn->sock + 1, &rfds, &wfds, NULL, NULL);
|
||||||
|
|
||||||
|
} else {
|
||||||
|
error_print();
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
int tlcp_do_accept(TLS_CONNECT *conn)
|
||||||
|
{
|
||||||
|
int ret;
|
||||||
|
fd_set rfds;
|
||||||
|
fd_set wfds;
|
||||||
|
|
||||||
|
conn->state = TLS_state_client_hello;
|
||||||
|
|
||||||
|
sm3_init(&conn->sm3_ctx);
|
||||||
|
|
||||||
|
while (1) {
|
||||||
|
|
||||||
|
ret = tlcp_server_handshake(conn);
|
||||||
|
|
||||||
|
if (ret == 1) {
|
||||||
|
break;
|
||||||
|
|
||||||
|
} else if (ret == TLS_ERROR_SEND_AGAIN) {
|
||||||
|
FD_ZERO(&rfds);
|
||||||
|
FD_ZERO(&wfds);
|
||||||
|
FD_SET(conn->sock, &rfds);
|
||||||
|
select(conn->sock + 1, &rfds, &wfds, NULL, NULL);
|
||||||
|
|
||||||
|
} else if (ret == TLS_ERROR_RECV_AGAIN) {
|
||||||
|
FD_ZERO(&rfds);
|
||||||
|
FD_ZERO(&wfds);
|
||||||
|
FD_SET(conn->sock, &wfds);
|
||||||
|
select(conn->sock + 1, &rfds, &wfds, NULL, NULL);
|
||||||
|
|
||||||
|
} else {
|
||||||
|
error_print();
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -2096,6 +2096,8 @@ int tls_ctx_init(TLS_CTX *ctx, int protocol, int is_client)
|
|||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// FIXME: 根据protocol,核对输入的ciphers是否满足protocol的条件
|
||||||
int tls_ctx_set_cipher_suites(TLS_CTX *ctx, const int *cipher_suites, size_t cipher_suites_cnt)
|
int tls_ctx_set_cipher_suites(TLS_CTX *ctx, const int *cipher_suites, size_t cipher_suites_cnt)
|
||||||
{
|
{
|
||||||
size_t i;
|
size_t i;
|
||||||
@@ -2314,8 +2316,11 @@ int tls_init(TLS_CONNECT *conn, const TLS_CTX *ctx)
|
|||||||
size_t i;
|
size_t i;
|
||||||
memset(conn, 0, sizeof(*conn));
|
memset(conn, 0, sizeof(*conn));
|
||||||
|
|
||||||
conn->protocol = ctx->protocol;
|
|
||||||
conn->is_client = ctx->is_client;
|
conn->is_client = ctx->is_client;
|
||||||
|
|
||||||
|
conn->protocol = ctx->protocol;
|
||||||
|
|
||||||
for (i = 0; i < ctx->cipher_suites_cnt; i++) {
|
for (i = 0; i < ctx->cipher_suites_cnt; i++) {
|
||||||
conn->cipher_suites[i] = ctx->cipher_suites[i];
|
conn->cipher_suites[i] = ctx->cipher_suites[i];
|
||||||
}
|
}
|
||||||
@@ -2348,6 +2353,7 @@ int tls_init(TLS_CONNECT *conn, const TLS_CTX *ctx)
|
|||||||
|
|
||||||
|
|
||||||
conn->verify_depth = ctx->verify_depth;
|
conn->verify_depth = ctx->verify_depth;
|
||||||
|
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
569
src/tls12.c
569
src/tls12.c
@@ -27,14 +27,13 @@
|
|||||||
#include <errno.h>
|
#include <errno.h>
|
||||||
#include <sys/select.h>
|
#include <sys/select.h>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
static const int tls12_ciphers[] = {
|
static const int tls12_ciphers[] = {
|
||||||
TLS_cipher_ecdhe_sm4_cbc_sm3,
|
TLS_cipher_ecdhe_sm4_cbc_sm3,
|
||||||
TLS_cipher_ecdhe_sm4_gcm_sm3,
|
TLS_cipher_ecdhe_sm4_gcm_sm3,
|
||||||
TLS_cipher_ecdhe_ecdsa_with_aes_128_cbc_sha256,
|
TLS_cipher_ecdhe_ecdsa_with_aes_128_cbc_sha256,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
// 现在client_certificate_verify做的是不好的
|
// 现在client_certificate_verify做的是不好的
|
||||||
/*
|
/*
|
||||||
是否要求客户端提供证书是服务器决定的,服务器方需要提供相应的CA证书
|
是否要求客户端提供证书是服务器决定的,服务器方需要提供相应的CA证书
|
||||||
@@ -194,24 +193,11 @@ int tls_named_curve_from_oid(int oid)
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
enum {
|
|
||||||
TLS_state_handshake_init = 0,
|
|
||||||
TLS_state_client_hello,
|
|
||||||
TLS_state_server_hello,
|
|
||||||
TLS_state_server_certificate,
|
|
||||||
TLS_state_server_key_exchange,
|
|
||||||
TLS_state_certificate_request,
|
|
||||||
TLS_state_server_hello_done,
|
|
||||||
TLS_state_client_certificate,
|
|
||||||
TLS_state_client_key_exchange,
|
|
||||||
TLS_state_certificate_verify,
|
|
||||||
TLS_state_generate_keys,
|
|
||||||
TLS_state_client_change_cipher_spec,
|
|
||||||
TLS_state_client_finished,
|
|
||||||
TLS_state_server_change_cipher_spec,
|
|
||||||
TLS_state_server_finished,
|
|
||||||
TLS_state_handshake_over,
|
|
||||||
};
|
|
||||||
|
|
||||||
// 这个是必选的
|
// 这个是必选的
|
||||||
const int ec_point_formats[] = { TLS_point_uncompressed };
|
const int ec_point_formats[] = { TLS_point_uncompressed };
|
||||||
@@ -256,6 +242,7 @@ int tls_record_set_handshake_server_key_exchange(uint8_t *record, size_t *record
|
|||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// 这个函数是有问题的,因为tlcp的格式和TLS不一样
|
||||||
int tls_record_get_handshake_server_key_exchange(const uint8_t *record,
|
int tls_record_get_handshake_server_key_exchange(const uint8_t *record,
|
||||||
uint8_t *curve_type, uint16_t *named_curve,
|
uint8_t *curve_type, uint16_t *named_curve,
|
||||||
const uint8_t **point_octets, size_t *point_octets_len,
|
const uint8_t **point_octets, size_t *point_octets_len,
|
||||||
@@ -373,6 +360,13 @@ int tls_handshake_init(TLS_CONNECT *conn)
|
|||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
TLCP协议中ClientHello中不包含扩展,并且cipher_suites使用的是TLCP的cipher_suites
|
||||||
|
ciphers我觉得应该在设置ctx的时候设置好
|
||||||
|
exts
|
||||||
|
|
||||||
|
*/
|
||||||
int tls_send_client_hello(TLS_CONNECT *conn)
|
int tls_send_client_hello(TLS_CONNECT *conn)
|
||||||
{
|
{
|
||||||
int ret;
|
int ret;
|
||||||
@@ -383,12 +377,23 @@ int tls_send_client_hello(TLS_CONNECT *conn)
|
|||||||
uint8_t *p = client_exts;
|
uint8_t *p = client_exts;
|
||||||
size_t client_exts_len = 0;
|
size_t client_exts_len = 0;
|
||||||
|
|
||||||
tls_record_set_protocol(record, TLS_protocol_tls1);
|
switch (conn->protocol) {
|
||||||
|
case TLS_protocol_tls12:
|
||||||
|
tls_record_set_protocol(record, TLS_protocol_tls1);
|
||||||
|
break;
|
||||||
|
case TLS_protocol_tlcp:
|
||||||
|
tls_record_set_protocol(record, TLS_protocol_tlcp);
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
error_print();
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
if (tls_random_generate(conn->client_random) != 1) {
|
if (tls_random_generate(conn->client_random) != 1) {
|
||||||
error_print();
|
error_print();
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (tls_ec_point_formats_ext_to_bytes(ec_point_formats, ec_point_formats_cnt, &p, &client_exts_len) != 1
|
if (tls_ec_point_formats_ext_to_bytes(ec_point_formats, ec_point_formats_cnt, &p, &client_exts_len) != 1
|
||||||
|| tls_supported_groups_ext_to_bytes(supported_groups, supported_groups_cnt, &p, &client_exts_len) != 1
|
|| tls_supported_groups_ext_to_bytes(supported_groups, supported_groups_cnt, &p, &client_exts_len) != 1
|
||||||
|| tls_signature_algorithms_ext_to_bytes(signature_algors, signature_algors_cnt, &p, &client_exts_len) != 1) {
|
|| tls_signature_algorithms_ext_to_bytes(signature_algors, signature_algors_cnt, &p, &client_exts_len) != 1) {
|
||||||
@@ -397,7 +402,7 @@ int tls_send_client_hello(TLS_CONNECT *conn)
|
|||||||
}
|
}
|
||||||
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,
|
||||||
tls12_ciphers, sizeof(tls12_ciphers)/sizeof(tls12_ciphers[0]),
|
conn->cipher_suites, conn->cipher_suites_cnt,
|
||||||
client_exts, client_exts_len) != 1) {
|
client_exts, client_exts_len) != 1) {
|
||||||
error_print();
|
error_print();
|
||||||
return -1;
|
return -1;
|
||||||
@@ -427,8 +432,160 @@ int tls_send_client_hello(TLS_CONNECT *conn)
|
|||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//static const int tlcp_ciphers[] = { TLS_cipher_ecc_sm4_cbc_sm3 };
|
||||||
|
|
||||||
|
int tlcp_send_client_hello(TLS_CONNECT *conn)
|
||||||
|
{
|
||||||
|
int ret;
|
||||||
|
uint8_t *record = conn->record;
|
||||||
|
|
||||||
|
if (!conn->recordlen) {
|
||||||
|
tls_record_set_protocol(record, TLS_protocol_tlcp);
|
||||||
|
|
||||||
|
if (tls_random_generate(conn->client_random) != 1) {
|
||||||
|
error_print();
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (tls_record_set_handshake_client_hello(conn->record, &conn->recordlen,
|
||||||
|
conn->protocol, conn->client_random, NULL, 0,
|
||||||
|
conn->cipher_suites, conn->cipher_suites_cnt,
|
||||||
|
NULL, 0) != 1) {
|
||||||
|
error_print();
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
// offset = 0, recordlen > 0
|
||||||
|
|
||||||
|
tls_trace("send ClientHello\n");
|
||||||
|
tlcp_record_trace(stderr, conn->record, conn->recordlen, 0, 0);
|
||||||
|
sm3_update(&conn->sm3_ctx, conn->record + 5, conn->recordlen - 5);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (conn->client_certificate_verify) {
|
||||||
|
sm2_sign_update(&conn->sign_ctx, conn->record + 5, conn->recordlen - 5);
|
||||||
|
}
|
||||||
|
|
||||||
|
if ((ret = tls_send_record(conn)) != 1) {
|
||||||
|
if (ret != TLS_ERROR_SEND_AGAIN) {
|
||||||
|
error_print();
|
||||||
|
}
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
tls_clean_record(conn);
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
int tlcp_recv_client_hello(TLS_CONNECT *conn)
|
||||||
|
{
|
||||||
|
int ret;
|
||||||
|
uint8_t *record = conn->record;
|
||||||
|
size_t recordlen;
|
||||||
|
|
||||||
|
int client_verify = 0;
|
||||||
|
|
||||||
|
int protocol;
|
||||||
|
const uint8_t *client_random;
|
||||||
|
const uint8_t *session_id;
|
||||||
|
size_t session_id_len;
|
||||||
|
const uint8_t *client_ciphers;
|
||||||
|
size_t client_ciphers_len;
|
||||||
|
const uint8_t *client_exts;
|
||||||
|
size_t client_exts_len;
|
||||||
|
|
||||||
|
sm3_init(&conn->sm3_ctx);
|
||||||
|
|
||||||
|
|
||||||
|
// 服务器端如果设置了CA
|
||||||
|
if (conn->ca_certs_len)
|
||||||
|
client_verify = 1;
|
||||||
|
|
||||||
|
// 这个判断应该改为一个函数
|
||||||
|
if (client_verify)
|
||||||
|
tls_client_verify_init(&conn->client_verify_ctx);
|
||||||
|
|
||||||
|
|
||||||
|
tls_trace("recv ClientHello\n");
|
||||||
|
|
||||||
|
if ((ret = tls_recv_record(conn)) != 1) {
|
||||||
|
if (ret != TLS_ERROR_RECV_AGAIN) {
|
||||||
|
error_print();
|
||||||
|
}
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
tlcp_record_trace(stderr, conn->record, conn->recordlen, 0, 0);
|
||||||
|
|
||||||
|
|
||||||
|
// 这里TLCP和TLS12是不一样的
|
||||||
|
if (tls_record_protocol(record) != conn->protocol) {
|
||||||
|
error_print();
|
||||||
|
tls_send_alert(conn, TLS_alert_protocol_version);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (tls_record_get_handshake_client_hello(record,
|
||||||
|
&protocol, &client_random, &session_id, &session_id_len,
|
||||||
|
&client_ciphers, &client_ciphers_len,
|
||||||
|
&client_exts, &client_exts_len) != 1) {
|
||||||
|
error_print();
|
||||||
|
tls_send_alert(conn, TLS_alert_unexpected_message);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (protocol != conn->protocol) {
|
||||||
|
error_print();
|
||||||
|
tls_send_alert(conn, TLS_alert_protocol_version);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
memcpy(conn->client_random, client_random, 32);
|
||||||
|
|
||||||
|
if (tls_cipher_suites_select(client_ciphers, client_ciphers_len,
|
||||||
|
conn->cipher_suites, conn->cipher_suites_cnt,
|
||||||
|
&conn->cipher_suite) != 1) {
|
||||||
|
error_print();
|
||||||
|
tls_send_alert(conn, TLS_alert_insufficient_security);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
switch (conn->cipher_suite) {
|
||||||
|
case TLS_cipher_ecc_sm4_cbc_sm3:
|
||||||
|
conn->sig_alg = TLS_sig_sm2sig_sm3;
|
||||||
|
conn->ecdh_named_curve = 0;
|
||||||
|
break;
|
||||||
|
case TLS_cipher_ecdhe_sm4_cbc_sm3:
|
||||||
|
case TLS_cipher_ecdhe_sm4_gcm_sm3:
|
||||||
|
default:
|
||||||
|
error_print();
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (client_exts) {
|
||||||
|
error_print();
|
||||||
|
tls_send_alert(conn, TLS_alert_unexpected_message);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
sm3_update(&conn->sm3_ctx, conn->record + 5, conn->recordlen - 5);
|
||||||
|
if (client_verify)
|
||||||
|
tls_client_verify_update(&conn->client_verify_ctx, conn->record + 5, conn->recordlen - 5);
|
||||||
|
|
||||||
|
|
||||||
|
fprintf(stderr, "end of recv_client_hello\n");
|
||||||
|
tls_clean_record(conn);
|
||||||
|
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
const int server_ciphers[] = { TLS_cipher_ecdhe_sm4_cbc_sm3 };
|
const int server_ciphers[] = { TLS_cipher_ecdhe_sm4_cbc_sm3 };
|
||||||
const size_t server_ciphers_cnt = 1;
|
const size_t server_ciphers_cnt = 1;
|
||||||
|
*/
|
||||||
const int curve = TLS_curve_sm2p256v1;
|
const int curve = TLS_curve_sm2p256v1;
|
||||||
|
|
||||||
|
|
||||||
@@ -473,6 +630,8 @@ int tls_recv_client_hello(TLS_CONNECT *conn)
|
|||||||
tls12_record_trace(stderr, conn->record, conn->recordlen, 0, 0);
|
tls12_record_trace(stderr, conn->record, conn->recordlen, 0, 0);
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
if (tls_record_protocol(record) != conn->protocol
|
if (tls_record_protocol(record) != conn->protocol
|
||||||
&& tls_record_protocol(record) != TLS_protocol_tls1) {
|
&& tls_record_protocol(record) != TLS_protocol_tls1) {
|
||||||
error_print();
|
error_print();
|
||||||
@@ -498,7 +657,7 @@ int tls_recv_client_hello(TLS_CONNECT *conn)
|
|||||||
|
|
||||||
// 服务器选择的cipher_suites需要和服务器准备的证书和公钥匹配
|
// 服务器选择的cipher_suites需要和服务器准备的证书和公钥匹配
|
||||||
if (tls_cipher_suites_select(client_ciphers, client_ciphers_len,
|
if (tls_cipher_suites_select(client_ciphers, client_ciphers_len,
|
||||||
server_ciphers, server_ciphers_cnt,
|
conn->cipher_suites, conn->cipher_suites_cnt,
|
||||||
&conn->cipher_suite) != 1) {
|
&conn->cipher_suite) != 1) {
|
||||||
error_print();
|
error_print();
|
||||||
tls_send_alert(conn, TLS_alert_insufficient_security);
|
tls_send_alert(conn, TLS_alert_insufficient_security);
|
||||||
@@ -539,17 +698,26 @@ int tls_recv_client_hello(TLS_CONNECT *conn)
|
|||||||
int tls_send_server_hello(TLS_CONNECT *conn)
|
int tls_send_server_hello(TLS_CONNECT *conn)
|
||||||
{
|
{
|
||||||
int ret;
|
int ret;
|
||||||
|
|
||||||
tls_trace("send ServerHello\n");
|
tls_trace("send ServerHello\n");
|
||||||
|
|
||||||
if (conn->recordlen == 0) {
|
if (conn->recordlen == 0) {
|
||||||
|
const uint8_t *server_exts = NULL;
|
||||||
|
size_t server_exts_len = 0;
|
||||||
|
|
||||||
tls_record_set_protocol(conn->record, conn->protocol);
|
tls_record_set_protocol(conn->record, conn->protocol);
|
||||||
if (tls_random_generate(conn->server_random) != 1) {
|
if (tls_random_generate(conn->server_random) != 1) {
|
||||||
error_print();
|
error_print();
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
if (conn->server_exts_len) {
|
||||||
|
server_exts = conn->server_exts;
|
||||||
|
server_exts_len = conn->server_exts_len;
|
||||||
|
}
|
||||||
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->server_exts, conn->server_exts_len) != 1) {
|
conn->cipher_suite,
|
||||||
|
server_exts, server_exts_len) != 1) {
|
||||||
error_print();
|
error_print();
|
||||||
tls_send_alert(conn, TLS_alert_internal_error);
|
tls_send_alert(conn, TLS_alert_internal_error);
|
||||||
return -1;
|
return -1;
|
||||||
@@ -617,24 +785,33 @@ int tls_recv_server_hello(TLS_CONNECT *conn)
|
|||||||
tls_send_alert(conn, TLS_alert_protocol_version);
|
tls_send_alert(conn, TLS_alert_protocol_version);
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
// tls12_ciphers 应该改为conn的内部变量
|
if (tls_cipher_suite_in_list(cipher_suite, conn->cipher_suites, conn->cipher_suites_cnt) != 1) {
|
||||||
if (tls_cipher_suite_in_list(cipher_suite, tls12_ciphers, sizeof(tls12_ciphers)/sizeof(tls12_ciphers[0])) != 1) {
|
|
||||||
error_print();
|
error_print();
|
||||||
tls_send_alert(conn, TLS_alert_handshake_failure);
|
tls_send_alert(conn, TLS_alert_handshake_failure);
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
if (!server_exts) {
|
|
||||||
error_print();
|
/*
|
||||||
tls_send_alert(conn, TLS_alert_unexpected_message);
|
对于扩展的处理
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
if (tls_process_server_hello_exts(server_exts, server_exts_len, &ec_point_format, &supported_group, &signature_algor) != 1
|
首先扩展是由客户端ClientHello进行设定,服务器选择,最后由Client验证的一个过程。
|
||||||
|| ec_point_format < 0
|
因此客户端和服务器端都需要存储扩展相应的数据。
|
||||||
|| supported_group < 0
|
|
||||||
|| signature_algor < 0) {
|
扩展的初始化是如何实现的?我觉得也应该在CTX中完成。
|
||||||
error_print();
|
|
||||||
tls_send_alert(conn, TLS_alert_unexpected_message);
|
现在对扩展的处理逻辑是有问题的,服务器ServerHello是否包含扩展是取决于ClientHello的
|
||||||
return -1;
|
|
||||||
|
*/
|
||||||
|
if (server_exts) {
|
||||||
|
if (tls_process_server_hello_exts(server_exts, server_exts_len, &ec_point_format, &supported_group, &signature_algor) != 1
|
||||||
|
|| ec_point_format < 0
|
||||||
|
|| supported_group < 0
|
||||||
|
|| signature_algor < 0) {
|
||||||
|
error_print();
|
||||||
|
tls_send_alert(conn, TLS_alert_unexpected_message);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
memcpy(conn->server_random, server_random, 32);
|
memcpy(conn->server_random, server_random, 32);
|
||||||
@@ -648,6 +825,10 @@ int tls_recv_server_hello(TLS_CONNECT *conn)
|
|||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// TLS12 发送的是常规的证书链
|
||||||
|
// TLCP SM2 发送的是SM2的双证书链,但是在数据格式上没有区别
|
||||||
|
// TLCP SM9 发送的是服务器的ID和SM9公开参数(这个格式是不同的),但是存储上可能也是一样的
|
||||||
|
// 我不确定SM2和SM9的格式是否是相容的
|
||||||
int tls_send_server_certificate(TLS_CONNECT *conn)
|
int tls_send_server_certificate(TLS_CONNECT *conn)
|
||||||
{
|
{
|
||||||
int ret;
|
int ret;
|
||||||
@@ -708,6 +889,8 @@ int tls_recv_server_certificate(TLS_CONNECT *conn)
|
|||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// 这下面是对获取的证书链的处理
|
||||||
|
|
||||||
if (x509_certs_get_cert_by_index(conn->server_certs, conn->server_certs_len, 0,
|
if (x509_certs_get_cert_by_index(conn->server_certs, conn->server_certs_len, 0,
|
||||||
&server_cert, &server_cert_len) != 1) {
|
&server_cert, &server_cert_len) != 1) {
|
||||||
error_print();
|
error_print();
|
||||||
@@ -720,6 +903,9 @@ int tls_recv_server_certificate(TLS_CONNECT *conn)
|
|||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// 这里的逻辑需要统筹考虑
|
||||||
|
// cipher_suite,扩展,证书之间的关系
|
||||||
|
|
||||||
// set conn->server_sig_alg (decided by cipher_suite and server_cert.sign_key.algor, algor_param)
|
// set conn->server_sig_alg (decided by cipher_suite and server_cert.sign_key.algor, algor_param)
|
||||||
if (server_sign_key.algor != OID_ec_public_key) {
|
if (server_sign_key.algor != OID_ec_public_key) {
|
||||||
error_print();
|
error_print();
|
||||||
@@ -757,16 +943,96 @@ int tls_recv_server_certificate(TLS_CONNECT *conn)
|
|||||||
assert(conn->verify_depth > 0 && conn->verify_depth < 10);
|
assert(conn->verify_depth > 0 && conn->verify_depth < 10);
|
||||||
|
|
||||||
// verify ServerCertificate
|
// verify ServerCertificate
|
||||||
if (x509_certs_verify(conn->server_certs, conn->server_certs_len, X509_cert_chain_server,
|
|
||||||
conn->ca_certs, conn->ca_certs_len, conn->verify_depth, &verify_result) != 1) {
|
switch (conn->protocol) {
|
||||||
|
case TLS_protocol_tls12:
|
||||||
|
if (x509_certs_verify(conn->server_certs, conn->server_certs_len, X509_cert_chain_server,
|
||||||
|
conn->ca_certs, conn->ca_certs_len, conn->verify_depth, &verify_result) != 1) {
|
||||||
|
error_print();
|
||||||
|
tls_send_alert(conn, TLS_alert_bad_certificate);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case TLS_protocol_tlcp:
|
||||||
|
if (!conn->ca_certs_len) {
|
||||||
|
error_print();
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
if (x509_certs_verify_tlcp(conn->server_certs, conn->server_certs_len, X509_cert_chain_server,
|
||||||
|
conn->ca_certs, conn->ca_certs_len, conn->verify_depth, &verify_result) != 1) {
|
||||||
|
error_print();
|
||||||
|
tls_send_alert(conn, TLS_alert_bad_certificate);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
default:
|
||||||
error_print();
|
error_print();
|
||||||
tls_send_alert(conn, TLS_alert_bad_certificate);
|
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int tlcp_send_server_key_exchange(TLS_CONNECT *conn)
|
||||||
|
{
|
||||||
|
SM2_SIGN_CTX sign_ctx;
|
||||||
|
uint8_t sigbuf[SM2_MAX_SIGNATURE_SIZE];
|
||||||
|
size_t siglen;
|
||||||
|
const uint8_t *server_enc_cert;
|
||||||
|
size_t server_enc_cert_len;
|
||||||
|
uint8_t server_enc_cert_lenbuf[3];
|
||||||
|
uint8_t *p;
|
||||||
|
size_t len;
|
||||||
|
int ret;
|
||||||
|
|
||||||
|
tls_trace("send ServerKeyExchange\n");
|
||||||
|
|
||||||
|
if (conn->recordlen == 0) {
|
||||||
|
|
||||||
|
if (x509_certs_get_cert_by_index(conn->server_certs, conn->server_certs_len, 1,
|
||||||
|
&server_enc_cert, &server_enc_cert_len) != 1) {
|
||||||
|
error_print();
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
p = server_enc_cert_lenbuf;
|
||||||
|
len = 0;
|
||||||
|
tls_uint24_to_bytes((uint24_t)server_enc_cert_len, &p, &len);
|
||||||
|
|
||||||
|
if (sm2_sign_init(&sign_ctx, &conn->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_enc_cert_lenbuf, 3) != 1
|
||||||
|
|| sm2_sign_update(&sign_ctx, server_enc_cert, server_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_pke(conn->record, &conn->recordlen, sigbuf, siglen) != 1) {
|
||||||
|
error_print();
|
||||||
|
tls_send_alert(conn, TLS_alert_internal_error);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
tlcp_record_trace(stderr, conn->record, conn->recordlen, 0, 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
if ((ret = tls_send_record(conn)) != 1) {
|
||||||
|
if (ret != TLS_ERROR_SEND_AGAIN) {
|
||||||
|
error_print();
|
||||||
|
}
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
sm3_update(&conn->sm3_ctx, conn->record + 5, conn->recordlen - 5);
|
||||||
|
if (conn->client_certificate_verify) {
|
||||||
|
tls_client_verify_update(&conn->client_verify_ctx, conn->record + 5, conn->recordlen - 5);
|
||||||
|
}
|
||||||
|
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
int tls_send_server_key_exchange(TLS_CONNECT *conn)
|
int tls_send_server_key_exchange(TLS_CONNECT *conn)
|
||||||
{
|
{
|
||||||
int ret;
|
int ret;
|
||||||
@@ -903,6 +1169,8 @@ int tls_signature_scheme_match_cipher_suite(int sig_alg, int cipher_suite)
|
|||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// 这里应该给一个新的key_exchange
|
||||||
|
|
||||||
int tls_recv_server_key_exchange(TLS_CONNECT *conn)
|
int tls_recv_server_key_exchange(TLS_CONNECT *conn)
|
||||||
{
|
{
|
||||||
int ret;
|
int ret;
|
||||||
@@ -942,7 +1210,8 @@ int tls_recv_server_key_exchange(TLS_CONNECT *conn)
|
|||||||
}
|
}
|
||||||
tls12_record_trace(stderr, conn->record, conn->recordlen, 0, 0);
|
tls12_record_trace(stderr, conn->record, conn->recordlen, 0, 0);
|
||||||
|
|
||||||
|
// 这里应该改为,首先获取一个基础的ServerKeyExchange的数据(已经经过了验证签名)
|
||||||
|
// 然后再用不同的函数(不同协议)去分解
|
||||||
if (tls_record_get_handshake_server_key_exchange(conn->record,
|
if (tls_record_get_handshake_server_key_exchange(conn->record,
|
||||||
&curve_type, &named_curve, &point_octets, &point_octets_len,
|
&curve_type, &named_curve, &point_octets, &point_octets_len,
|
||||||
&server_ecdh_params, &server_ecdh_params_len,
|
&server_ecdh_params, &server_ecdh_params_len,
|
||||||
@@ -1051,6 +1320,79 @@ int tls_recv_server_key_exchange(TLS_CONNECT *conn)
|
|||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int tlcp_recv_server_key_exchange(TLS_CONNECT *conn)
|
||||||
|
{
|
||||||
|
const uint8_t *sig;
|
||||||
|
size_t siglen;
|
||||||
|
const uint8_t *cp;
|
||||||
|
size_t len;
|
||||||
|
X509_KEY server_sign_key;
|
||||||
|
|
||||||
|
const uint8_t *server_enc_cert;
|
||||||
|
size_t server_enc_cert_len;
|
||||||
|
|
||||||
|
uint8_t server_enc_cert_lenbuf[3];
|
||||||
|
uint8_t *p;
|
||||||
|
|
||||||
|
SM2_VERIFY_CTX verify_ctx;
|
||||||
|
|
||||||
|
|
||||||
|
tls_trace("recv ServerKeyExchange\n");
|
||||||
|
|
||||||
|
if (tls_record_recv(conn->record, &conn->recordlen, conn->sock) != 1
|
||||||
|
|| tls_record_protocol(conn->record) != TLS_protocol_tlcp) {
|
||||||
|
error_print();
|
||||||
|
tls_send_alert(conn, TLS_alert_unexpected_message);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
tlcp_record_trace(stderr, conn->record, conn->recordlen, 0, 0);
|
||||||
|
|
||||||
|
if (tlcp_record_get_handshake_server_key_exchange_pke(conn->record, &sig, &siglen) != 1) {
|
||||||
|
error_print();
|
||||||
|
tls_send_alert(conn, TLS_alert_unexpected_message);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
sm3_update(&conn->sm3_ctx, conn->record + 5, conn->recordlen - 5);
|
||||||
|
|
||||||
|
|
||||||
|
// verify ServerKeyExchange
|
||||||
|
if (x509_certs_get_cert_by_index(conn->server_certs, conn->server_certs_len, 0, &cp, &len) != 1
|
||||||
|
|| x509_cert_get_subject_public_key(cp, len, &server_sign_key) != 1
|
||||||
|
|| x509_certs_get_cert_by_index(conn->server_certs, conn->server_certs_len, 1, &server_enc_cert, &server_enc_cert_len) != 1
|
||||||
|
|| x509_cert_get_subject_public_key(server_enc_cert, server_enc_cert_len, &conn->server_enc_key) != 1) {
|
||||||
|
error_print();
|
||||||
|
tls_send_alert(conn, TLS_alert_bad_certificate);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
if (server_sign_key.algor != OID_ec_public_key
|
||||||
|
|| server_sign_key.algor_param != OID_sm2
|
||||||
|
|| conn->server_enc_key.algor != OID_ec_public_key
|
||||||
|
|| conn->server_enc_key.algor_param != OID_sm2) {
|
||||||
|
error_print();
|
||||||
|
tls_send_alert(conn, TLS_alert_bad_certificate);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
p = server_enc_cert_lenbuf;
|
||||||
|
len = 0;
|
||||||
|
tls_uint24_to_bytes((uint24_t)server_enc_cert_len, &p, &len);
|
||||||
|
if (sm2_verify_init(&verify_ctx, &server_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_enc_cert_lenbuf, 3) != 1
|
||||||
|
|| sm2_verify_update(&verify_ctx, server_enc_cert, server_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;
|
||||||
|
}
|
||||||
|
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
int tls_send_certificate_request(TLS_CONNECT *conn)
|
int tls_send_certificate_request(TLS_CONNECT *conn)
|
||||||
{
|
{
|
||||||
int ret;
|
int ret;
|
||||||
@@ -1303,12 +1645,36 @@ int tls_recv_client_certificate(TLS_CONNECT *conn)
|
|||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
不同密码套件中使用的密钥生成方法不一样,需要的输入也不一样。
|
||||||
|
应该考虑在CONN中维护union版本的ServerKeyExchange和ClientKeyExchange
|
||||||
|
|
||||||
|
ServerKeyExchange ClientKeyExchange
|
||||||
|
ECDHE Server X509_KEY X509_KEY public
|
||||||
|
ECDHE Client X509_KEY X509_KEY public
|
||||||
|
ECC Server N/A SM2Cipher
|
||||||
|
ECC Client N/A N/A 客户端可能需要服务器公钥的类型
|
||||||
|
|
||||||
|
|
||||||
|
我们现在还不支持SM2的ECDH呢!
|
||||||
|
SM9相关的密码套件呢?
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
*/
|
||||||
|
|
||||||
int tls_generate_keys(TLS_CONNECT *conn)
|
int tls_generate_keys(TLS_CONNECT *conn)
|
||||||
{
|
{
|
||||||
uint8_t pre_master_secret[32];
|
uint8_t pre_master_secret[32];
|
||||||
size_t pre_master_secret_len;
|
size_t pre_master_secret_len;
|
||||||
uint8_t key_block[96];
|
uint8_t key_block[96];
|
||||||
|
|
||||||
|
// 此时已经获得了ServerKeyExchange和ClientKeyExchange
|
||||||
|
// 但是不同密码套件中,这些KeyExchange的数据其实是不一样的
|
||||||
|
// 我们需要根据不同的套件去解析数据,并且根据不同的数据类型去生成密钥
|
||||||
|
// 还需要检查 TLS 1.3 的协议
|
||||||
|
|
||||||
if (x509_key_exchange(&conn->ecdh_key,
|
if (x509_key_exchange(&conn->ecdh_key,
|
||||||
conn->peer_ecdh_point, conn->peer_ecdh_point_len,
|
conn->peer_ecdh_point, conn->peer_ecdh_point_len,
|
||||||
@@ -1359,6 +1725,51 @@ int tls_generate_keys(TLS_CONNECT *conn)
|
|||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// 对于客户端,是先发送client_key_exchange在generate_keys
|
||||||
|
int tlcp_generate_keys(TLS_CONNECT *conn)
|
||||||
|
{
|
||||||
|
uint8_t enced_pre_master_secret[SM2_MAX_CIPHERTEXT_SIZE];
|
||||||
|
size_t enced_pre_master_secret_len;
|
||||||
|
|
||||||
|
tls_trace("generate secrets\n");
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
if (tls_prf(conn->pre_master_secret, 48, "master secret",
|
||||||
|
conn->client_random, 32,
|
||||||
|
conn->server_random, 32,
|
||||||
|
48, conn->master_secret) != 1
|
||||||
|
|| tls_prf(conn->master_secret, 48, "key expansion",
|
||||||
|
conn->server_random, 32, // 这里顺序为什么是反的
|
||||||
|
conn->client_random, 32,
|
||||||
|
96, conn->key_block) != 1) {
|
||||||
|
error_print();
|
||||||
|
tls_send_alert(conn, TLS_alert_internal_error);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
// 主力这里是不对的,需要为client, server设定不同的加密密钥
|
||||||
|
sm3_hmac_init(&conn->client_write_mac_ctx, conn->key_block, 32);
|
||||||
|
sm3_hmac_init(&conn->server_write_mac_ctx, conn->key_block + 32, 32);
|
||||||
|
|
||||||
|
if (conn->is_client) {
|
||||||
|
sm4_set_encrypt_key(&conn->client_write_enc_key, conn->key_block + 64);
|
||||||
|
sm4_set_decrypt_key(&conn->server_write_enc_key, conn->key_block + 80);
|
||||||
|
} else {
|
||||||
|
sm4_set_decrypt_key(&conn->client_write_enc_key, conn->key_block + 64);
|
||||||
|
sm4_set_encrypt_key(&conn->server_write_enc_key, conn->key_block + 80);
|
||||||
|
}
|
||||||
|
|
||||||
|
tls_secrets_print(stderr,
|
||||||
|
conn->pre_master_secret, 48,
|
||||||
|
conn->client_random, conn->server_random,
|
||||||
|
conn->master_secret,
|
||||||
|
conn->key_block, 96,
|
||||||
|
0, 4);
|
||||||
|
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
int tls_send_client_key_exchange(TLS_CONNECT *conn)
|
int tls_send_client_key_exchange(TLS_CONNECT *conn)
|
||||||
{
|
{
|
||||||
int ret;
|
int ret;
|
||||||
@@ -1449,6 +1860,80 @@ int tls_recv_client_key_exchange(TLS_CONNECT *conn)
|
|||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// 对于TLCP是否应该先执行send_client_key_exchange再生成密钥呢?
|
||||||
|
int tlcp_send_client_key_exchange(TLS_CONNECT *conn)
|
||||||
|
{
|
||||||
|
uint8_t enced_pre_master_secret[SM2_MAX_CIPHERTEXT_SIZE];
|
||||||
|
size_t enced_pre_master_secret_len;
|
||||||
|
|
||||||
|
tls_trace("send ClientKeyExchange\n");
|
||||||
|
|
||||||
|
if (tls_pre_master_secret_generate(conn->pre_master_secret, TLS_protocol_tlcp) != 1) {
|
||||||
|
error_print();
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (sm2_encrypt(&conn->server_enc_key.u.sm2_key, conn->pre_master_secret, 48,
|
||||||
|
enced_pre_master_secret, &enced_pre_master_secret_len) != 1
|
||||||
|
|| tls_record_set_handshake_client_key_exchange_pke(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;
|
||||||
|
}
|
||||||
|
tlcp_record_trace(stderr, conn->record, conn->recordlen, 0, 0);
|
||||||
|
if (tls_record_send(conn->record, conn->recordlen, conn->sock) != 1) {
|
||||||
|
error_print();
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
sm3_update(&conn->sm3_ctx, conn->record + 5, conn->recordlen - 5);
|
||||||
|
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
int tlcp_recv_client_key_exchange(TLS_CONNECT *conn)
|
||||||
|
{
|
||||||
|
const uint8_t *enced_pms;
|
||||||
|
size_t enced_pms_len;
|
||||||
|
size_t pre_master_secret_len;
|
||||||
|
|
||||||
|
tls_trace("recv ClientKeyExchange\n");
|
||||||
|
|
||||||
|
if (tls_record_recv(conn->record, &conn->recordlen, conn->sock) != 1
|
||||||
|
|| tls_record_protocol(conn->record) != TLS_protocol_tlcp) {
|
||||||
|
error_print();
|
||||||
|
tls_send_alert(conn, TLS_alert_unexpected_message);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
tlcp_record_trace(stderr, conn->record, conn->recordlen, 0, 0);
|
||||||
|
|
||||||
|
if (tls_record_get_handshake_client_key_exchange_pke(conn->record, &enced_pms, &enced_pms_len) != 1) {
|
||||||
|
error_print();
|
||||||
|
tls_send_alert(conn, TLS_alert_unexpected_message);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
// FIXME:
|
||||||
|
// 这里需要检查一下密钥的长度,因为输入的长度是确定的,因此输出的密文长度应该也是确定的
|
||||||
|
|
||||||
|
if (sm2_decrypt(&conn->kenc_key.u.sm2_key, enced_pms, enced_pms_len,
|
||||||
|
conn->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) {
|
||||||
|
error_print();
|
||||||
|
tls_send_alert(conn, TLS_alert_decrypt_error);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
sm3_update(&conn->sm3_ctx, conn->record + 5, conn->recordlen - 5);
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
int tls_send_certificate_verify(TLS_CONNECT *conn)
|
int tls_send_certificate_verify(TLS_CONNECT *conn)
|
||||||
{
|
{
|
||||||
int ret;
|
int ret;
|
||||||
|
|||||||
@@ -46,8 +46,32 @@ static const char *help =
|
|||||||
" gmssl tlcp_client -host www.pbc.gov.cn -get / -outcerts certs.pem\n"
|
" gmssl tlcp_client -host www.pbc.gov.cn -get / -outcerts certs.pem\n"
|
||||||
"\n"
|
"\n"
|
||||||
" gmssl tlcp_client -host www.pbc.gov.cn -port 443\n"
|
" gmssl tlcp_client -host www.pbc.gov.cn -port 443\n"
|
||||||
|
"\n"
|
||||||
|
"Examples\n"
|
||||||
|
"\n"
|
||||||
|
" gmssl sm2keygen -pass 1234 -out rootcakey.pem\n"
|
||||||
|
" gmssl certgen -C CN -ST Beijing -L Haidian -O PKU -OU CS -CN ROOTCA -days 3650 -key rootcakey.pem -pass 1234 -out rootcacert.pem -key_usage keyCertSign -key_usage cRLSign -ca\n"
|
||||||
|
" gmssl sm2keygen -pass 1234 -out cakey.pem\n"
|
||||||
|
" gmssl reqgen -C CN -ST Beijing -L Haidian -O PKU -OU CS -CN \"Sub CA\" -key cakey.pem -pass 1234 -out careq.pem\n"
|
||||||
|
" gmssl reqsign -in careq.pem -days 365 -key_usage keyCertSign -ca -path_len_constraint 0 -cacert rootcacert.pem -key rootcakey.pem -pass 1234 -out cacert.pem\n"
|
||||||
|
"\n"
|
||||||
|
" gmssl sm2keygen -pass 1234 -out signkey.pem\n"
|
||||||
|
" gmssl reqgen -C CN -ST Beijing -L Haidian -O PKU -OU CS -CN localhost -key signkey.pem -pass 1234 -out signreq.pem\n"
|
||||||
|
" gmssl reqsign -in signreq.pem -days 365 -key_usage digitalSignature -cacert cacert.pem -key cakey.pem -pass 1234 -out signcert.pem\n"
|
||||||
|
"\n"
|
||||||
|
" gmssl sm2keygen -pass 1234 -out enckey.pem\n"
|
||||||
|
" gmssl reqgen -C CN -ST Beijing -L Haidian -O PKU -OU CS -CN localhost -key enckey.pem -pass 1234 -out encreq.pem\n"
|
||||||
|
" gmssl reqsign -in encreq.pem -days 365 -key_usage keyEncipherment -cacert cacert.pem -key cakey.pem -pass 1234 -out enccert.pem\n"
|
||||||
|
"\n"
|
||||||
|
" cat signcert.pem > double_certs.pem\n"
|
||||||
|
" cat enccert.pem >> double_certs.pem\n"
|
||||||
|
" cat cacert.pem >> double_certs.pem\n"
|
||||||
|
"\n"
|
||||||
|
" sudo gmssl tlcp_server -port 443 -cert double_certs.pem -key signkey.pem -pass 1234 -ex_key enckey.pem -ex_pass 1234\n"
|
||||||
|
" gmssl tlcp_client -host 127.0.0.1 -cacert rootcacert.pem\n"
|
||||||
"\n";
|
"\n";
|
||||||
|
|
||||||
|
|
||||||
int tlcp_client_main(int argc, char *argv[])
|
int tlcp_client_main(int argc, char *argv[])
|
||||||
{
|
{
|
||||||
int ret = -1;
|
int ret = -1;
|
||||||
|
|||||||
@@ -20,6 +20,40 @@
|
|||||||
|
|
||||||
static const char *options = "[-port num] -cert file -key file [-pass str] -ex_key file [-ex_pass str] [-cacert file]";
|
static const char *options = "[-port num] -cert file -key file [-pass str] -ex_key file [-ex_pass str] [-cacert file]";
|
||||||
|
|
||||||
|
|
||||||
|
static const char *help =
|
||||||
|
"Options\n"
|
||||||
|
"\n"
|
||||||
|
" -port num Listening port number, default 443\n"
|
||||||
|
" -cert file Server's certificate chain in PEM format\n"
|
||||||
|
" -key file Server's encrypted private key in PEM format\n"
|
||||||
|
" -pass str Password to decrypt private key\n"
|
||||||
|
" -cacert file CA certificate for client certificate verification\n"
|
||||||
|
"\n"
|
||||||
|
"Examples\n"
|
||||||
|
"\n"
|
||||||
|
" gmssl sm2keygen -pass 1234 -out rootcakey.pem\n"
|
||||||
|
" gmssl certgen -C CN -ST Beijing -L Haidian -O PKU -OU CS -CN ROOTCA -days 3650 -key rootcakey.pem -pass 1234 -out rootcacert.pem -key_usage keyCertSign -key_usage cRLSign -ca\n"
|
||||||
|
" gmssl sm2keygen -pass 1234 -out cakey.pem\n"
|
||||||
|
" gmssl reqgen -C CN -ST Beijing -L Haidian -O PKU -OU CS -CN \"Sub CA\" -key cakey.pem -pass 1234 -out careq.pem\n"
|
||||||
|
" gmssl reqsign -in careq.pem -days 365 -key_usage keyCertSign -ca -path_len_constraint 0 -cacert rootcacert.pem -key rootcakey.pem -pass 1234 -out cacert.pem\n"
|
||||||
|
"\n"
|
||||||
|
" gmssl sm2keygen -pass 1234 -out signkey.pem\n"
|
||||||
|
" gmssl reqgen -C CN -ST Beijing -L Haidian -O PKU -OU CS -CN localhost -key signkey.pem -pass 1234 -out signreq.pem\n"
|
||||||
|
" gmssl reqsign -in signreq.pem -days 365 -key_usage digitalSignature -cacert cacert.pem -key cakey.pem -pass 1234 -out signcert.pem\n"
|
||||||
|
"\n"
|
||||||
|
" gmssl sm2keygen -pass 1234 -out enckey.pem\n"
|
||||||
|
" gmssl reqgen -C CN -ST Beijing -L Haidian -O PKU -OU CS -CN localhost -key enckey.pem -pass 1234 -out encreq.pem\n"
|
||||||
|
" gmssl reqsign -in encreq.pem -days 365 -key_usage keyEncipherment -cacert cacert.pem -key cakey.pem -pass 1234 -out enccert.pem\n"
|
||||||
|
"\n"
|
||||||
|
" cat signcert.pem > double_certs.pem\n"
|
||||||
|
" cat enccert.pem >> double_certs.pem\n"
|
||||||
|
" cat cacert.pem >> double_certs.pem\n"
|
||||||
|
"\n"
|
||||||
|
" sudo gmssl tlcp_server -port 443 -cert double_certs.pem -key signkey.pem -pass 1234 -ex_key enckey.pem -ex_pass 1234\n"
|
||||||
|
" gmssl tlcp_client -host 127.0.0.1 -cacert rootcacert.pem\n"
|
||||||
|
"\n";
|
||||||
|
|
||||||
int tlcp_server_main(int argc , char **argv)
|
int tlcp_server_main(int argc , char **argv)
|
||||||
{
|
{
|
||||||
int ret = 1;
|
int ret = 1;
|
||||||
@@ -55,6 +89,7 @@ int tlcp_server_main(int argc , char **argv)
|
|||||||
while (argc > 0) {
|
while (argc > 0) {
|
||||||
if (!strcmp(*argv, "-help")) {
|
if (!strcmp(*argv, "-help")) {
|
||||||
printf("usage: %s %s\n", prog, options);
|
printf("usage: %s %s\n", prog, options);
|
||||||
|
printf("%s\n", help);
|
||||||
return 0;
|
return 0;
|
||||||
} else if (!strcmp(*argv, "-port")) {
|
} else if (!strcmp(*argv, "-port")) {
|
||||||
if (--argc < 1) goto bad;
|
if (--argc < 1) goto bad;
|
||||||
|
|||||||
@@ -25,6 +25,40 @@ static const char *http_get =
|
|||||||
|
|
||||||
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]";
|
||||||
|
|
||||||
|
static const char *help =
|
||||||
|
"Options\n"
|
||||||
|
"\n"
|
||||||
|
" -host str Server's hostname\n"
|
||||||
|
" -port num Server's port number, default 443\n"
|
||||||
|
" -cacert file Root CA certificate\n"
|
||||||
|
" -cert file Client's certificate chain in PEM format\n"
|
||||||
|
" -key file Client's encrypted private key in PEM format\n"
|
||||||
|
" -pass str Password to decrypt private key\n"
|
||||||
|
"\n"
|
||||||
|
"Examples\n"
|
||||||
|
"\n"
|
||||||
|
" gmssl sm2keygen -pass 1234 -out rootcakey.pem\n"
|
||||||
|
" gmssl certgen -C CN -ST Beijing -L Haidian -O PKU -OU CS -CN ROOTCA -days 3650 \\\n"
|
||||||
|
" -key rootcakey.pem -pass 1234 -out rootcacert.pem \\\n"
|
||||||
|
" -key_usage keyCertSign -key_usage cRLSign -ca\n"
|
||||||
|
"\n"
|
||||||
|
" gmssl sm2keygen -pass 1234 -out cakey.pem\n"
|
||||||
|
" gmssl reqgen -C CN -ST Beijing -L Haidian -O PKU -OU CS -CN \"Sub CA\" \\\n"
|
||||||
|
" -key cakey.pem -pass 1234 -out careq.pem\n"
|
||||||
|
" gmssl reqsign -in careq.pem -days 365 -key_usage keyCertSign -cacert rootcacert.pem -key rootcakey.pem -pass 1234 \\\n"
|
||||||
|
" -out cacert.pem -ca -path_len_constraint 0\n"
|
||||||
|
"\n"
|
||||||
|
" gmssl sm2keygen -pass 1234 -out signkey.pem\n"
|
||||||
|
" gmssl reqgen -C CN -ST Beijing -L Haidian -O PKU -OU CS -CN localhost -key signkey.pem -pass 1234 -out signreq.pem\n"
|
||||||
|
" gmssl reqsign -in signreq.pem -days 365 -key_usage digitalSignature -cacert cacert.pem -key cakey.pem -pass 1234 -out signcert.pem\n"
|
||||||
|
"\n"
|
||||||
|
" cat signcert.pem > certs.pem\n"
|
||||||
|
" cat cacert.pem >> certs.pem\n"
|
||||||
|
"\n"
|
||||||
|
" sudo gmssl tls12_server -port 4430 -cert certs.pem -key signkey.pem -pass 1234\n"
|
||||||
|
" gmssl tls12_client -host 127.0.0.1 -port 4430 -cacert rootcacert.pem\n"
|
||||||
|
"\n";
|
||||||
|
|
||||||
int tls12_client_main(int argc, char *argv[])
|
int tls12_client_main(int argc, char *argv[])
|
||||||
{
|
{
|
||||||
int ret = -1;
|
int ret = -1;
|
||||||
@@ -53,6 +87,7 @@ int tls12_client_main(int argc, char *argv[])
|
|||||||
while (argc >= 1) {
|
while (argc >= 1) {
|
||||||
if (!strcmp(*argv, "-help")) {
|
if (!strcmp(*argv, "-help")) {
|
||||||
printf("usage: %s %s\n", prog, options);
|
printf("usage: %s %s\n", prog, options);
|
||||||
|
printf("%s\n", help);
|
||||||
return 0;
|
return 0;
|
||||||
} else if (!strcmp(*argv, "-host")) {
|
} else if (!strcmp(*argv, "-host")) {
|
||||||
if (--argc < 1) goto bad;
|
if (--argc < 1) goto bad;
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright 2014-2022 The GmSSL Project. All Rights Reserved.
|
* Copyright 2014-2026 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.
|
||||||
@@ -20,6 +20,40 @@
|
|||||||
|
|
||||||
static const char *options = "[-port num] -cert file -key file -pass str [-cacert file]";
|
static const char *options = "[-port num] -cert file -key file -pass str [-cacert file]";
|
||||||
|
|
||||||
|
static const char *help =
|
||||||
|
"Options\n"
|
||||||
|
"\n"
|
||||||
|
" -port num Listening port number, default 443\n"
|
||||||
|
" -cert file Server's certificate chain in PEM format\n"
|
||||||
|
" -key file Server's encrypted private key in PEM format\n"
|
||||||
|
" -pass str Password to decrypt private key\n"
|
||||||
|
" -cacert file CA certificate for client certificate verification\n"
|
||||||
|
"\n"
|
||||||
|
"Examples\n"
|
||||||
|
"\n"
|
||||||
|
" gmssl sm2keygen -pass 1234 -out rootcakey.pem\n"
|
||||||
|
" gmssl certgen -C CN -ST Beijing -L Haidian -O PKU -OU CS -CN ROOTCA -days 3650 \\\n"
|
||||||
|
" -key rootcakey.pem -pass 1234 -out rootcacert.pem \\\n"
|
||||||
|
" -key_usage keyCertSign -key_usage cRLSign -ca\n"
|
||||||
|
"\n"
|
||||||
|
" gmssl sm2keygen -pass 1234 -out cakey.pem\n"
|
||||||
|
" gmssl reqgen -C CN -ST Beijing -L Haidian -O PKU -OU CS -CN \"Sub CA\" \\\n"
|
||||||
|
" -key cakey.pem -pass 1234 -out careq.pem\n"
|
||||||
|
" gmssl reqsign -in careq.pem -days 365 -key_usage keyCertSign -cacert rootcacert.pem -key rootcakey.pem -pass 1234 \\\n"
|
||||||
|
" -out cacert.pem -ca -path_len_constraint 0\n"
|
||||||
|
"\n"
|
||||||
|
" gmssl sm2keygen -pass 1234 -out signkey.pem\n"
|
||||||
|
" gmssl reqgen -C CN -ST Beijing -L Haidian -O PKU -OU CS -CN localhost -key signkey.pem -pass 1234 -out signreq.pem\n"
|
||||||
|
" gmssl reqsign -in signreq.pem -days 365 -key_usage digitalSignature -cacert cacert.pem -key cakey.pem -pass 1234 -out signcert.pem\n"
|
||||||
|
"\n"
|
||||||
|
" cat signcert.pem > certs.pem\n"
|
||||||
|
" cat cacert.pem >> certs.pem\n"
|
||||||
|
"\n"
|
||||||
|
" sudo gmssl tls12_server -port 4430 -cert certs.pem -key signkey.pem -pass 1234\n"
|
||||||
|
" gmssl tls12_client -host 127.0.0.1 -port 4430 -cacert rootcacert.pem\n"
|
||||||
|
"\n";
|
||||||
|
|
||||||
|
|
||||||
int tls12_server_main(int argc , char **argv)
|
int tls12_server_main(int argc , char **argv)
|
||||||
{
|
{
|
||||||
int ret = 1;
|
int ret = 1;
|
||||||
@@ -52,6 +86,7 @@ int tls12_server_main(int argc , char **argv)
|
|||||||
while (argc > 0) {
|
while (argc > 0) {
|
||||||
if (!strcmp(*argv, "-help")) {
|
if (!strcmp(*argv, "-help")) {
|
||||||
printf("usage: %s %s\n", prog, options);
|
printf("usage: %s %s\n", prog, options);
|
||||||
|
printf("%s\n", help);
|
||||||
return 0;
|
return 0;
|
||||||
} else if (!strcmp(*argv, "-port")) {
|
} else if (!strcmp(*argv, "-port")) {
|
||||||
if (--argc < 1) goto bad;
|
if (--argc < 1) goto bad;
|
||||||
|
|||||||
Reference in New Issue
Block a user