diff --git a/CMakeLists.txt b/CMakeLists.txt index 9f87028c..ba8a56b8 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -433,6 +433,7 @@ if (ENABLE_SECP256R1) message(STATUS "ENABLE_SECP256R1 is ON") add_definitions(-DENABLE_SECP256R1) list(APPEND src src/secp256r1.c src/secp256r1_key.c src/ecdsa.c src/ecdh.c) + list(APPEND tools tools/p256keygen.c) list(APPEND tests secp256r1 secp256r1_key ecdsa) endif() diff --git a/include/gmssl/x509_key.h b/include/gmssl/x509_key.h index 9933abe0..7c33e6bc 100644 --- a/include/gmssl/x509_key.h +++ b/include/gmssl/x509_key.h @@ -107,6 +107,8 @@ int x509_private_key_print_ex(FILE *fp, int fmt, int ind, const char *label, con #define X509_PUBLIC_KEY_INFO_MAX_SIZE 1280 // for kyber and 91 for others int x509_public_key_info_to_der(const X509_KEY *key, uint8_t **out, size_t *outlen); int x509_public_key_info_from_der(X509_KEY *key, const uint8_t **in, size_t *inlen); +int x509_public_key_info_to_pem(const X509_KEY *a, FILE *fp); +int x509_public_key_info_from_pem(X509_KEY *a, FILE *fp); int x509_public_key_info_print(FILE *fp, int fmt, int ind, const char *label, const uint8_t *d, size_t dlen); diff --git a/src/secp256r1_key.c b/src/secp256r1_key.c index 8747161e..10e9d09b 100644 --- a/src/secp256r1_key.c +++ b/src/secp256r1_key.c @@ -199,8 +199,8 @@ int secp256r1_public_key_from_der(SECP256R1_KEY *key, const uint8_t **in, size_t } - - +// 这里应该提供public_key_info_to_pem 和SM2完全一样的功能 +// 这样才可以生成证书 diff --git a/src/tls.c b/src/tls.c index 8dce7912..c445054d 100644 --- a/src/tls.c +++ b/src/tls.c @@ -2780,6 +2780,8 @@ int tls_init(TLS_CONNECT *conn, TLS_CTX *ctx) return -1; } + fprintf(stderr, "%s %d: conn->key_exchange_modes = %d\n", __FILE__, __LINE__, conn->key_exchange_modes); + if (conn->key_exchange_modes & (TLS_KE_CERT_DHE|TLS_KE_PSK_DHE)) { conn->key_share = 1; diff --git a/src/tls13.c b/src/tls13.c index 3d98325c..b44a97bd 100644 --- a/src/tls13.c +++ b/src/tls13.c @@ -316,7 +316,7 @@ int tls13_send(TLS_CONNECT *conn, const uint8_t *data, size_t datalen, size_t *s *sentlen = 0; - + // 这个可能是有问题的 if (!conn->recordlen) { const BLOCK_CIPHER_KEY *key; const uint8_t *iv; @@ -336,13 +336,23 @@ int tls13_send(TLS_CONNECT *conn, const uint8_t *data, size_t datalen, size_t *s key = &conn->client_write_key; iv = conn->client_write_iv; seq_num = conn->client_seq_num; + format_bytes(stderr, 0, 4, "client_write_iv", iv, 12); + format_bytes(stderr, 0, 4, "client_seq_num", seq_num, 8); + format_print(stderr, 0, 0, "\n"); + } else { key = &conn->server_write_key; iv = conn->server_write_iv; seq_num = conn->server_seq_num; + format_bytes(stderr, 0, 4, "server_write_iv", iv, 12); + format_bytes(stderr, 0, 4, "server_seq_num", seq_num, 8); + format_print(stderr, 0, 0, "\n"); } tls13_padding_len_rand(&padding_len); + + + // 这个其实不太好,最好是直接加密一个record,这样我们可以打印出record if (tls13_gcm_encrypt(key, iv, seq_num, TLS_record_application_data, data, datalen, padding_len, conn->record + 5, &record_datalen) != 1) { @@ -350,7 +360,6 @@ int tls13_send(TLS_CONNECT *conn, const uint8_t *data, size_t datalen, size_t *s return -1; } tls_seq_num_incr(seq_num); - tls_record_set_type(conn->record, TLS_record_application_data); tls_record_set_protocol(conn->record, TLS_protocol_tls12); tls_record_set_data_length(conn->record, record_datalen); @@ -359,6 +368,11 @@ int tls13_send(TLS_CONNECT *conn, const uint8_t *data, size_t datalen, size_t *s conn->record_offset = 0; conn->plain_recordlen = datalen + 5; + + tls13_record_print(stderr, 0, 0, conn->record, conn->recordlen); + + + /* KeyUpdate有两个原因 * 我们自己检查,应该KeyUpdate了,那么发送KeyUpdate并且要求对方也Update @@ -367,9 +381,12 @@ int tls13_send(TLS_CONNECT *conn, const uint8_t *data, size_t datalen, size_t *s */ // check if KeyUpdate + /* + // key_update_seq_num_limit 似乎还没有设置 if (GETU64(seq_num) >= conn->ctx->key_update_seq_num_limit) { key_update = 1; } + */ } while (conn->recordlen) { @@ -390,7 +407,7 @@ int tls13_send(TLS_CONNECT *conn, const uint8_t *data, size_t datalen, size_t *s conn->record_offset += n; } - + /* if (key_update) { int ret; @@ -416,10 +433,11 @@ int tls13_send(TLS_CONNECT *conn, const uint8_t *data, size_t datalen, size_t *s } - } + */ *sentlen = conn->plain_recordlen - 5; + return 1; } @@ -434,11 +452,15 @@ int tls13_do_recv(TLS_CONNECT *conn) switch (conn->state) { case 0: + error_print(); + fprintf(stderr, "----------------------------------------------------------------\n"); conn->record_offset = 0; conn->recordlen = TLS_RECORD_HEADER_SIZE; conn->state = TLS_state_recv_record_header; + error_print(); case TLS_state_recv_record_header: + error_print(); while (conn->recordlen) { if ((n = tls_socket_recv(conn->sock, conn->record + conn->record_offset, conn->recordlen, 0)) <= 0) { if (errno == EAGAIN || errno == EWOULDBLOCK) { @@ -449,6 +471,7 @@ int tls13_do_recv(TLS_CONNECT *conn) } } conn->recordlen -= n; + conn->record_offset += n; } if (tls_record_type(conn->record) != TLS_record_application_data) { error_print(); @@ -458,10 +481,17 @@ int tls13_do_recv(TLS_CONNECT *conn) error_print(); return -1; } - conn->recordlen = tls_record_length(conn->record); + conn->recordlen = tls_record_data_length(conn->record); + + fprintf(stderr, "%d: recordlen = %zu\n", __LINE__, conn->recordlen); + + fprintf(stderr, "record_offset = %zu\n", conn->record_offset); + conn->state = TLS_state_recv_record_data; case TLS_state_recv_record_data: + error_print(); + while (conn->recordlen) { if ((n = tls_socket_recv(conn->sock, conn->record + conn->record_offset, conn->recordlen, 0)) <= 0) { if (errno == EAGAIN || errno == EWOULDBLOCK) { @@ -472,6 +502,7 @@ int tls13_do_recv(TLS_CONNECT *conn) } } conn->recordlen -= n; + conn->record_offset += n; } conn->state = 0; break; @@ -480,18 +511,35 @@ int tls13_do_recv(TLS_CONNECT *conn) error_print(); return -1; } - conn->recordlen = tls_record_length(conn->record) + TLS_RECORD_HEADER_SIZE; - // tls13_record_print(stderr, 0, 0, conn->record, conn->recordlen); + + conn->recordlen = tls_record_length(conn->record); + + fprintf(stderr, "%d: recordlen = %zu\n", __LINE__, conn->recordlen); + + + tls13_record_print(stderr, 0, 0, conn->record, conn->recordlen); + if (conn->is_client) { key = &conn->server_write_key; iv = conn->server_write_iv; seq_num = conn->server_seq_num; + + format_bytes(stderr, 0, 4, "server_write_iv", iv, 12); + format_bytes(stderr, 0, 4, "server_seq_num", seq_num, 8); + format_print(stderr, 0, 0, "\n"); + + } else { key = &conn->client_write_key; iv = conn->client_write_iv; seq_num = conn->client_seq_num; + format_bytes(stderr, 0, 4, "client_write_iv", iv, 12); + format_bytes(stderr, 0, 4, "client_seq_num", seq_num, 8); + format_print(stderr, 0, 0, "\n"); } + + if (tls13_record_decrypt(key, iv, seq_num, conn->record, conn->recordlen, conn->plain_record, &conn->plain_recordlen) != 1) { error_print(); @@ -499,6 +547,8 @@ int tls13_do_recv(TLS_CONNECT *conn) } tls_seq_num_incr(seq_num); + tls13_record_print(stderr, 0, 0, conn->plain_record, conn->plain_recordlen); + switch (tls_record_type(conn->plain_record)) { case TLS_record_application_data: conn->data = conn->plain_record + 5; @@ -520,6 +570,10 @@ int tls13_do_recv(TLS_CONNECT *conn) // NewSessionTicket 也不应该是被单独接收的,只能在解密并解析了handshake之后才可以 case TLS_handshake_new_session_ticket: + + error_print(); + fprintf(stderr, "tls13_process_new_session_ticket\n"); + if (tls13_process_new_session_ticket(conn) != 1) { error_print(); return -1; @@ -609,6 +663,9 @@ int tls13_recv(TLS_CONNECT *conn, uint8_t *out, size_t outlen, size_t *recvlen) error_print(); return -1; } + fprintf(stderr, "%d: conn->state %d\n", __LINE__, conn->state); + + if (conn->datalen == 0) { int ret; if ((ret = tls13_do_recv(conn)) != 1) { @@ -620,6 +677,12 @@ int tls13_recv(TLS_CONNECT *conn, uint8_t *out, size_t outlen, size_t *recvlen) memcpy(out, conn->data, *recvlen); conn->data += *recvlen; conn->datalen -= *recvlen; + + // 这里接受完成之后,应该recordlen = 0 + + conn->recordlen = 0; + + return 1; } @@ -695,8 +758,12 @@ int tls13_derive_secret(const uint8_t secret[32], const char *label, const DIGES uint8_t dgst[64]; size_t dgstlen; - if (digest_finish(&ctx, dgst, &dgstlen) != 1 - || tls13_hkdf_expand_label(dgst_ctx->digest, secret, label, dgst, 32, dgstlen, out) != 1) { + if (digest_finish(&ctx, dgst, &dgstlen) != 1) { + error_print(); + return -1; + } + + if (tls13_hkdf_expand_label(dgst_ctx->digest, secret, label, dgst, 32, dgstlen, out) != 1) { error_print(); return -1; } @@ -3286,16 +3353,24 @@ Auth | {CertificateVerify*} int tls_key_exchange_modes_print(FILE *fp, int fmt, int ind, const char *label, int modes) { + int first = 1; + format_print(fp, fmt, ind, "%s:", label); if (modes & TLS_KE_CERT_DHE) { fprintf(fp, " CERT_DHE"); + first = 0; } if (modes & TLS_KE_PSK_DHE) { - fprintf(fp, " PSK_DHE"); + if (first) + fprintf(fp, " PSK_DHE"); + else fprintf(fp, "|PSK_DHE"); + first = 0; } if (modes & TLS_KE_PSK) { - fprintf(fp, " PSK"); + if (first) + fprintf(fp, " PSK"); + else fprintf(fp, "|PSK"); } fprintf(fp, "\n"); return 1; @@ -3500,11 +3575,16 @@ int tls13_init(TLS_CONNECT *conn, TLS_CTX *ctx) // key_exchange_modes conn->key_exchange_modes = ctx->psk_key_exchange_modes; if (ctx->supported_groups_cnt && ctx->signature_algorithms_cnt) { - conn->key_exchange_modes = TLS_KE_CERT_DHE; + conn->key_exchange_modes |= TLS_KE_CERT_DHE; } if (!ctx->supported_groups_cnt) { conn->key_exchange_modes &= ~(TLS_KE_CERT_DHE|TLS_KE_PSK_DHE); } + + + tls_key_exchange_modes_print(stderr, 0, 0, "server key_exchange_modes", conn->key_exchange_modes); + + if (!conn->key_exchange_modes) { error_print(); return -1; @@ -3529,6 +3609,11 @@ int tls13_init(TLS_CONNECT *conn, TLS_CTX *ctx) } +/* +ClientHello中的很多扩展是和证书有关的 +如果客户端在ClientHello中已经明确不支持证书认证(没有提供group + sig_alg的组合) +那么就不应该在ClientHello中包含这些扩展 +*/ int tls13_send_client_hello(TLS_CONNECT *conn) { @@ -3703,6 +3788,9 @@ int tls13_send_client_hello(TLS_CONNECT *conn) } } + fprintf(stderr, ">>>>> conn->pre_shared_key = %d\n", conn->pre_shared_key); + + // pre_shared_key (must be the last extension) if (conn->pre_shared_key) { uint8_t *ptruncated_exts = pexts; @@ -3711,6 +3799,9 @@ int tls13_send_client_hello(TLS_CONNECT *conn) uint8_t *pbinders = binders; size_t binderslen = 0; + + fprintf(stderr, "add pre_shared_key\n"); + if (!conn->psk_identities_len || !conn->psk_keys_len || !conn->psk_cipher_suites_cnt ) { @@ -5682,6 +5773,9 @@ int tls13_recv_server_certificate_verify(TLS_CONNECT *conn) return -1; } + conn->recordlen = 0; + conn->plain_recordlen = 0; + return 1; } @@ -5759,18 +5853,7 @@ int tls13_recv_client_certificate_verify(TLS_CONNECT *conn) } - - - - - - - - - - - - +// ServerFinished消息之前有可能是什么消息? int tls13_recv_server_finished(TLS_CONNECT *conn) { @@ -5790,22 +5873,27 @@ int tls13_recv_server_finished(TLS_CONNECT *conn) } tls_trace("recv server {Finished}\n"); - if ((ret = tls_recv_record(conn)) != 1) { - if (ret != TLS_ERROR_RECV_AGAIN) { - error_print(); - } - return ret; - } - if (tls13_record_decrypt(&conn->server_write_key, conn->server_write_iv, - conn->server_seq_num, conn->record, conn->recordlen, - conn->plain_record, &conn->plain_recordlen) != 1) { - error_print(); - tls13_send_alert(conn, TLS_alert_bad_record_mac); - return -1; + if (!conn->plain_recordlen) { + + if ((ret = tls_recv_record(conn)) != 1) { + if (ret != TLS_ERROR_RECV_AGAIN) { + error_print(); + } + return ret; + } + + if (tls13_record_decrypt(&conn->server_write_key, conn->server_write_iv, + conn->server_seq_num, conn->record, conn->recordlen, + conn->plain_record, &conn->plain_recordlen) != 1) { + error_print(); + tls13_send_alert(conn, TLS_alert_bad_record_mac); + return -1; + } + tls_seq_num_incr(conn->server_seq_num); } - tls_seq_num_incr(conn->server_seq_num); tls13_record_print(stderr, 0, 0, conn->plain_record, conn->plain_recordlen); + if (digest_update(&conn->dgst_ctx, conn->plain_record + 5, conn->plain_recordlen - 5) != 1) { error_print(); return -1; @@ -5846,9 +5934,10 @@ int tls13_recv_server_finished(TLS_CONNECT *conn) format_bytes(stderr, 0, 4, "server_application_traffic_secret", conn->server_application_traffic_secret, 48); format_bytes(stderr, 0, 4, "server_write_key", server_write_key, 16); format_bytes(stderr, 0, 4, "server_write_iv", conn->server_write_iv, 12); + format_bytes(stderr, 0, 4, "server_seq_num", conn->server_seq_num, 8); + format_print(stderr, 0, 0, "\n"); - tls_seq_num_reset(conn->server_seq_num); return 1; } @@ -6699,7 +6788,7 @@ int tls13_recv_client_hello(TLS_CONNECT *conn) return -1; } - //tls_key_exchange_modes_print(stderr, 0, 0, ">>>> key_exchange_modes", conn->key_exchange_modes); + tls_key_exchange_modes_print(stderr, 0, 0, "server key_exchange_mode", conn->key_exchange_modes); // hello_retry_request if (conn->hello_retry_request) { @@ -7709,6 +7798,7 @@ int tls13_send_server_finished(TLS_CONNECT *conn) format_bytes(stderr, 0, 4, "server_application_traffic_secret", conn->server_application_traffic_secret, 48); format_bytes(stderr, 0, 4, "server_write_key", server_write_key, 16); format_bytes(stderr, 0, 4, "server_write_iv", conn->server_write_iv, 12); + format_bytes(stderr, 0, 4, "server_seq_num", conn->server_seq_num, 8); format_print(stderr, 0, 0, "\n"); } @@ -8384,8 +8474,13 @@ int tls13_client_handshake(TLS_CONNECT *conn) } return ret; } + + } + + conn->state = 0; + // TODO: cleanup conn? return 1; @@ -8407,6 +8502,8 @@ int tls13_server_handshake(TLS_CONNECT *conn) } } + conn->state = 0; + // TODO: cleanup conn? return 1; diff --git a/src/tls_psk.c b/src/tls_psk.c index c2ba6d08..d46cbd20 100644 --- a/src/tls_psk.c +++ b/src/tls_psk.c @@ -581,6 +581,8 @@ int tls13_session_print(FILE *fp, int fmt, int ind, const char *label, const uin return 1; } +// 需要检查一下加入的SESSION的cipher_suite是否和conn的匹配 + // client only int tls13_add_pre_shared_key_from_session_file(TLS_CONNECT *conn, FILE *fp) { @@ -664,20 +666,24 @@ int tls13_send_new_session_ticket(TLS_CONNECT *conn) uint32_t max_early_data_size = 256 * 1024; // 256 KB uint32_t ticket_issue_time = time(NULL); + uint8_t resumption_master_secret[48]; + size_t dgstlen = 32; + uint8_t pre_shared_key[32]; + if (rand_bytes((uint8_t *)&ticket_age_add, sizeof(ticket_age_add)) != 1) { error_print(); return -1; } + if (rand_bytes(ticket_nonce, sizeof(ticket_nonce)) != 1) { error_print(); return -1; } - uint8_t resumption_master_secret[48]; - size_t dgstlen = 32; - uint8_t pre_shared_key[32]; - // generate resumption_master_secret + + digest_init(&conn->dgst_ctx, conn->digest); + /* [14] */ tls13_derive_secret(conn->master_secret, "res master", &conn->dgst_ctx, resumption_master_secret); // pre_shared_key = HKDF-Expand-Label(resumption_master_secret, "resumption", ticket_nonce, Hash.length) @@ -713,6 +719,12 @@ int tls13_send_new_session_ticket(TLS_CONNECT *conn) } tls13_record_print(stderr, 0, 0, conn->plain_record, conn->plain_recordlen); + format_print(stderr, 0, 0, "update server secrets\n"); + format_bytes(stderr, 0, 4, "server_application_traffic_secret", conn->server_application_traffic_secret, 48); + format_bytes(stderr, 0, 4, "server_write_iv", conn->server_write_iv, 12); + format_bytes(stderr, 0, 4, "server_seq_num", conn->server_seq_num, 8); + format_print(stderr, 0, 0, "\n"); + tls13_padding_len_rand(&padding_len); if (tls13_record_encrypt(&conn->server_write_key, conn->server_write_iv, conn->server_seq_num, conn->plain_record, conn->plain_recordlen, padding_len, @@ -799,6 +811,8 @@ int tls13_process_new_session_ticket(TLS_CONNECT *conn) size_t dgstlen = 32; uint8_t pre_shared_key[32]; + digest_init(&conn->dgst_ctx, conn->digest); + // generate resumption_master_secret /* [14] */ tls13_derive_secret(conn->master_secret, "res master", &conn->dgst_ctx, resumption_master_secret); @@ -1943,3 +1957,4 @@ int tls13_recv_end_of_early_data(TLS_CONNECT *conn) return 1; } + diff --git a/src/x509_key.c b/src/x509_key.c index 1fbff140..25115add 100644 --- a/src/x509_key.c +++ b/src/x509_key.c @@ -787,6 +787,41 @@ int x509_public_key_info_from_der(X509_KEY *x509_key, const uint8_t **in, size_t return 1; } +int x509_public_key_info_to_pem(const X509_KEY *a, FILE *fp) +{ + uint8_t buf[512]; + uint8_t *p = buf; + size_t len = 0; + + if (x509_public_key_info_to_der(a, &p, &len) != 1) { + error_print(); + return -1; + } + if (pem_write(fp, "PUBLIC KEY", buf, len) <= 0) { + error_print(); + return -1; + } + return 1; +} + +int x509_public_key_info_from_pem(X509_KEY *a, FILE *fp) +{ + uint8_t buf[512]; + const uint8_t *cp = buf; + size_t len; + + if (pem_read(fp, "PUBLIC KEY", buf, &len, sizeof(buf)) != 1) { + error_print(); + return -1; + } + if (x509_public_key_info_from_der(a, &cp, &len) != 1 + || asn1_length_is_zero(len) != 1) { + error_print(); + return -1; + } + return 1; +} + int x509_public_key_info_print(FILE *fp, int fmt, int ind, const char *label, const uint8_t *d, size_t dlen) { const uint8_t *p = d; diff --git a/tools/gmssl.c b/tools/gmssl.c index d2fe4576..7475f376 100644 --- a/tools/gmssl.c +++ b/tools/gmssl.c @@ -64,6 +64,9 @@ extern int tls12_client_main(int argc, char **argv); extern int tls12_server_main(int argc, char **argv); extern int tls13_client_main(int argc, char **argv); extern int tls13_server_main(int argc, char **argv); +#ifdef ENABLE_SECP256R1 +extern int p256keygen_main(int argc, char **argv); +#endif #ifdef ENABLE_LMS extern int lmskeygen_main(int argc, char **argv); extern int lmssign_main(int argc, char **argv); @@ -154,6 +157,9 @@ static const char *options = " cmsdecrypt Decrypt CMS EnvelopedData\n" " cmssign Generate CMS SignedData\n" " cmsverify Verify CMS SignedData\n" +#ifdef ENABLE_SECP256R1 + " p256keygen Generate P-256 (secp256r1, prime256v1) keypair\n" +#endif #ifdef ENABLE_LMS " lmskeygen Generate LMS-SM3 (Leighton-Micali Signature) keypair\n" " lmssign Generate LMS-SM3 signature\n" @@ -334,6 +340,10 @@ int main(int argc, char **argv) return tls13_client_main(argc, argv); } else if (!strcmp(*argv, "tls13_server")) { return tls13_server_main(argc, argv); +#ifdef ENABLE_SECP256R1 + } else if (!strcmp(*argv, "p256keygen")) { + return p256keygen_main(argc, argv); +#endif #ifdef ENABLE_LMS } else if (!strcmp(*argv, "lmskeygen")) { return lmskeygen_main(argc, argv); diff --git a/tools/p256keygen.c b/tools/p256keygen.c new file mode 100644 index 00000000..c2fbb515 --- /dev/null +++ b/tools/p256keygen.c @@ -0,0 +1,114 @@ +/* + * 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 +#include +#include +#include +#include +#include + + +static const char *usage = "-pass str [-out pem] [-pubout pem]\n"; + +static const char *options = +"Options\n" +"\n" +" -pass pass Password to encrypt the private key\n" +" -out pem Output password-encrypted PKCS #8 private key in PEM format\n" +" -pubout pem Output public key in PEM format\n" +"\n" +"Examples\n" +"\n" +" $ gmssl p256keygen -pass P@ssw0rd -out p256.pem\n" +" $ gmssl p256keygen -pass P@ssw0rd -out p256.pem -pubout p256pub.pem\n" +"\n"; + +int p256keygen_main(int argc, char **argv) +{ + int ret = 1; + char *prog = argv[0]; + char *pass = NULL; + char *outfile = NULL; + char *puboutfile = NULL; + FILE *outfp = stdout; + FILE *puboutfp = stdout; + int curve_oid = OID_secp256r1; + X509_KEY key; + + argc--; + argv++; + + if (argc < 1) { + fprintf(stderr, "usage: gmssl %s %s\n", prog, usage); + return 1; + } + + while (argc > 0) { + if (!strcmp(*argv, "-help")) { + printf("usage: gmssl %s %s\n", prog, usage); + printf("%s\n", options); + ret = 0; + goto end; + } else if (!strcmp(*argv, "-pass")) { + if (--argc < 1) goto bad; + pass = *(++argv); + } else if (!strcmp(*argv, "-out")) { + if (--argc < 1) goto bad; + outfile = *(++argv); + if (!(outfp = fopen(outfile, "wb"))) { + fprintf(stderr, "gmssl %s: open '%s' failure : %s\n", prog, outfile, strerror(errno)); + goto end; + } + } else if (!strcmp(*argv, "-pubout")) { + if (--argc < 1) goto bad; + puboutfile = *(++argv); + if (!(puboutfp = fopen(puboutfile, "wb"))) { + fprintf(stderr, "gmssl %s: open '%s' failure : %s\n", prog, outfile, strerror(errno)); + goto end; + } + } else { + fprintf(stderr, "gmssl %s: illegal option '%s'\n", prog, *argv); + goto end; +bad: + fprintf(stderr, "gmssl %s: `%s` option value missing\n", prog, *argv); + goto end; + } + + argc--; + argv++; + } + + if (!pass) { + fprintf(stderr, "gmssl %s: `-pass` option required\n", prog); + goto end; + } + + + if (x509_key_generate(&key, OID_ec_public_key, &curve_oid, sizeof(curve_oid)) != 1) { + fprintf(stderr, "gmssl %s: inner failure\n", prog); + return -1; + } + if (x509_private_key_info_encrypt_to_pem(&key, pass, outfp) != 1) { + fprintf(stderr, "gmssl %s: inner failure\n", prog); + return -1; + } + if (x509_public_key_info_to_pem(&key, puboutfp) != 1) { + fprintf(stderr, "gmssl %s: inner failure\n", prog); + goto end; + } + ret = 0; + +end: + gmssl_secure_clear(&key, sizeof(key)); + if (outfile && outfp) fclose(outfp); + if (puboutfile && puboutfp) fclose(puboutfp); + return ret; +} diff --git a/tools/reqgen.c b/tools/reqgen.c index 0ac0e4e0..18a5717e 100644 --- a/tools/reqgen.c +++ b/tools/reqgen.c @@ -58,8 +58,11 @@ static char *usage = "\n" "Examples\n" "\n" -" gmssl sm2keygen -pass P@ssw0rd -out key.pem\n" -" gmssl reqgen -CN www.gmssl.org -key key.pem -pass P@ssw0rd -out req.pem\n" +" gmssl sm2keygen -pass P@ssw0rd -out sm2key.pem\n" +" gmssl reqgen -CN www.gmssl.org -key sm2key.pem -pass P@ssw0rd -out sm2req.pem\n" +"\n" +" gmssl p256keygen -pass P@ssw0rd -out p256key.pem\n" +" gmssl reqgen -CN www.gmssl.org -key p256key.pem -pass P@ssw0rd -out p256req.pem\n" "\n"; diff --git a/tools/tls13_client.c b/tools/tls13_client.c index 32f8945c..b68c9e73 100644 --- a/tools/tls13_client.c +++ b/tools/tls13_client.c @@ -365,9 +365,8 @@ bad: error_print(); return -1; } + error_print(); tls13_ctx_set_psk_key_exchange_modes(&ctx, psk_ke, psk_dhe_ke); - - } @@ -411,7 +410,6 @@ bad: if (sess_in) { FILE *sess_infp; - int enable_psk = 0; int psk_ret = 1; if (!(sess_infp = fopen(sess_in, "rb"))) { @@ -431,7 +429,7 @@ bad: // 客户端是否发送pre_shared_key是由什么决定的?需要显式的支持吗 // 我觉得应该是不需要的,因为如果设置了psk_key_exchange_mode,那么自然要发送pre_shared_key - tls13_enable_pre_shared_key(&conn, enable_psk); + tls13_enable_pre_shared_key(&conn, 1); } if (sess_out) { diff --git a/tools/tls13_server.c b/tools/tls13_server.c index 953609af..ddf070e4 100644 --- a/tools/tls13_server.c +++ b/tools/tls13_server.c @@ -19,6 +19,19 @@ #include +/* +如果采用PSK模式并且是外部密钥,那么意味着每个预置密钥关联一个cipher_suite +那么ClientHello中的cipher_suites应该是这些套件的集合 +但是ClientHello也可能支持PSK之外的套件,因此最终是常规cipher_suite + psk_cipher_suite的合集 + + +我们需要多组证书,也就是 -cert -key -pass 构成一组,我们可以用一个数组把这些放到一起 + + + +*/ + + static const char *options = "[-port num] -cert file -key file -pass str [-cacert file]"; static const char *help = @@ -59,32 +72,34 @@ static const char *help = "\n" "Examples\n" "\n" -" gmssl sm2keygen -pass 1234 -out rootcakey.pem\n" +" gmssl sm2keygen -pass 1234 -out sm2rootcakey.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 sm2rootcakey.pem -pass 1234 -out sm2rootcacert.pem \\\n" " -key_usage keyCertSign -key_usage cRLSign -ca\n" "\n" -" gmssl sm2keygen -pass 1234 -out cakey.pem\n" +" gmssl sm2keygen -pass 1234 -out sm2cakey.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" +" -key sm2cakey.pem -pass 1234 -out sm2careq.pem\n" +" gmssl reqsign -in sm2careq.pem -days 365 -key_usage keyCertSign -cacert rootcacert.pem -key rootcakey.pem -pass 1234 \\\n" +" -out sm2cacert.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" +" gmssl sm2keygen -pass 1234 -out sm2signkey.pem\n" +" gmssl reqgen -C CN -ST Beijing -L Haidian -O PKU -OU CS -CN localhost -key sm2signkey.pem -pass 1234 -out sm2signreq.pem\n" +" gmssl reqsign -in sm2signreq.pem -days 365 -key_usage digitalSignature -cacert sm2cacert.pem -key sm2cakey.pem -pass 1234 -out sm2signcert.pem\n" "\n" -" cat signcert.pem > certs.pem\n" -" cat cacert.pem >> certs.pem\n" +" cat sm2signcert.pem > sm2certs.pem\n" +" cat sm2cacert.pem >> sm2certs.pem\n" "\n" -" sudo gmssl tls13_server -port 4430 -cert certs.pem -key signkey.pem -pass 1234 -cipher_suite TLS_SM4_GCM_SM3 -supported_group sm2p256v1 -sig_alg sm2sig_sm3\n" -" gmssl tls13_client -host 127.0.0.1 -port 4430 -cacert rootcacert.pem -cipher_suite TLS_SM4_GCM_SM3 -supported_group sm2p256v1 -sig_alg sm2sig_sm3\n" +" sudo gmssl tls13_server -port 4430 -cert sm2certs.pem -key sm2signkey.pem -pass 1234 -cipher_suite TLS_SM4_GCM_SM3 -supported_group sm2p256v1 -sig_alg sm2sig_sm3\n" +" gmssl tls13_client -host 127.0.0.1 -port 4430 -cacert sm2rootcacert.pem -cipher_suite TLS_SM4_GCM_SM3 -supported_group sm2p256v1 -sig_alg sm2sig_sm3\n" "\n" -" sudo gmssl tls13_server -port 4430 -cert certs.pem -key signkey.pem -pass 1234 \\\n" +"\n" +" sudo gmssl tls13_server -port 4430 -cert sm2certs.pem -key sm2signkey.pem -pass 1234 \\\n" " -cipher_suite TLS_SM4_GCM_SM3 -cipher_suite TLS_AES_128_GCM_SHA256 \\\n" " -supported_group sm2p256v1 -supported_group prime256v1 \\\n" " -sig_alg sm2sig_sm3 -sig_alg ecdsa_secp256r1_sha256\n" -" gmssl tls13_client -host 127.0.0.1 -port 4430 -cacert rootcacert.pem \\\n" +"\n" +" gmssl tls13_client -host 127.0.0.1 -port 4430 -cacert sm2rootcacert.pem \\\n" " -cipher_suite TLS_SM4_GCM_SM3 -cipher_suite TLS_AES_128_GCM_SHA256 \\\n" " -supported_group sm2p256v1 -supported_group prime256v1 \\\n" " -sig_alg sm2sig_sm3 -sig_alg ecdsa_secp256r1_sha256 \\\n" @@ -95,23 +110,31 @@ static const char *help = " -post_handshake_auth \\\n" " -ct\n" "\n" +"\n" +" TICKET_KEY=11223344556677881122334455667788\n" +" sudo gmssl tls13_server -port 4430 -cert sm2certs.pem -key sm2signkey.pem -pass 1234 \\\n" +" -cipher_suite TLS_SM4_GCM_SM3 -supported_group sm2p256v1 -sig_alg sm2sig_sm3 \\\n" +" -new_session_ticket 2 -ticket_key $TICKET_KEY\n" +"\n" +" gmssl tls13_client -host 127.0.0.1 -port 4430 -cacert sm2rootcacert.pem \\\n" +" -cipher_suite TLS_SM4_GCM_SM3 -supported_group sm2p256v1 -sig_alg sm2sig_sm3 \\\n" +" -sess_out session.bin\n" +"\n" +" sudo gmssl tls13_server -port 4430 -cert sm2certs.pem -key sm2signkey.pem -pass 1234 \\\n" +" -cipher_suite TLS_SM4_GCM_SM3 -supported_group sm2p256v1 \\\n" +" -psk_dhe_ke -ticket_key $TICKET_KEY\n" +"\n" +" gmssl tls13_client -host 127.0.0.1 -port 4430 \\\n" +" -cipher_suite TLS_SM4_GCM_SM3 -supported_group sm2p256v1 \\\n" +" -psk_dhe_ke -sess_in session.bin\n" +"\n" +"\n" " PSK=1122334455667788112233445566778811223344556677881122334455667788\n" -" sudo gmssl tls13_server -port 4430 -cipher_suite TLS_SM4_GCM_SM3 -psk_ke -psk_identity 001 -psk_cipher_suite TLS_SM4_GCM_SM3 -psk_key $PSK\n" -" gmssl tls13_client -host 127.0.0.1 -port 4430 -cipher_suite TLS_SM4_GCM_SM3 -psk_ke -psk_identity 001 -psk_cipher_suite TLS_SM4_GCM_SM3 -psk_key $PSK\n" +" sudo gmssl tls13_server -port 4430 -cipher_suite TLS_SM4_GCM_SM3 \\\n" +" -psk_ke -psk_identity 001 -psk_cipher_suite TLS_SM4_GCM_SM3 -psk_key $PSK\n" +" gmssl tls13_client -host 127.0.0.1 -port 4430 -cipher_suite TLS_SM4_GCM_SM3 \\\n" +" -psk_ke -psk_identity 001 -psk_cipher_suite TLS_SM4_GCM_SM3 -psk_key $PSK\n" "\n" -" sudo gmssl tls13_server -port 4430 -cipher_suite TLS_SM4_GCM_SM3 -psk_ke -psk_identity 001 -psk_cipher_suite TLS_SM4_GCM_SM3 -psk_key $PSK -early_data\n" -" gmssl tls13_client -host 127.0.0.1 -port 4430 -cipher_suite TLS_SM4_GCM_SM3 -psk_ke -psk_identity 001 -psk_cipher_suite TLS_SM4_GCM_SM3 -psk_key $PSK -early_data early_data.txt\n" -"\n" -" sudo gmssl tls13_server -port 4430 -cipher_suite TLS_SM4_GCM_SM3 -psk_ke -psk_identity 001 -psk_cipher_suite TLS_SM4_GCM_SM3 -psk_key $PSK -new_session_ticket 2\n" -"\n" -" sudo gmssl tls13_server -port 4430 -cipher_suite TLS_SM4_GCM_SM3 -psk_dhe_ke -supported_group sm2p256v1 -psk_identity 001 -psk_cipher_suite TLS_SM4_GCM_SM3 -psk_key $PSK -early_data\n" -" gmssl tls13_client -host 127.0.0.1 -port 4430 -cipher_suite TLS_SM4_GCM_SM3 -psk_dhe_ke -supported_group sm2p256v1 -psk_identity 001 -psk_cipher_suite TLS_SM4_GCM_SM3 -psk_key $PSK -early_data early_data.txt\n" -"\n" -" sudo gmssl tls13_server -port 4430 -cipher_suite TLS_SM4_GCM_SM3 -psk_ke -supported_group sm2p256v1 -psk_identity 001 -psk_cipher_suite TLS_SM4_GCM_SM3 -psk_key $PSK -new_session_ticket 2 -ticket_key $TICKET_KEY\n" -" gmssl tls13_client -host 127.0.0.1 -port 4430 -cipher_suite TLS_SM4_GCM_SM3 -psk_dhe_ke -supported_group sm2p256v1 -psk_identity 001 -psk_cipher_suite TLS_SM4_GCM_SM3 -psk_key $PSK -sess_out session.bin\n" -" sudo gmssl tls13_server -port 4430 -cipher_suite TLS_SM4_GCM_SM3 -psk_ke -ticket_key $TICKET_KEY\n" -" gmssl tls13_client -host 127.0.0.1 -port 4430 -cipher_suite TLS_SM4_GCM_SM3 -psk_ke -sess_in session.bin\n" - "\n"; int tls13_server_main(int argc , char **argv) @@ -122,6 +145,17 @@ int tls13_server_main(int argc , char **argv) char *certfile = NULL; char *keyfile = NULL; char *pass = NULL; + + + char *certfiles[4]; + char *keyfiles[sizeof(certfiles)/sizeof(certfiles[0])]; + char *passes[sizeof(certfiles)/sizeof(certfiles[0])]; + size_t certfiles_cnt = 0; + size_t keyfiles_cnt = 0; + size_t passes_cnt = 0; + + + char *cacertfile = NULL; int server_ciphers[] = { TLS_cipher_sm4_gcm_sm3, }; TLS_CTX ctx; @@ -168,6 +202,9 @@ int tls13_server_main(int argc , char **argv) int sig_algs[4]; size_t sig_algs_cnt = 0; + size_t i; + + argc--; argv++; @@ -184,15 +221,37 @@ int tls13_server_main(int argc , char **argv) } else if (!strcmp(*argv, "-port")) { if (--argc < 1) goto bad; port = atoi(*(++argv)); + } else if (!strcmp(*argv, "-cert")) { if (--argc < 1) goto bad; certfile = *(++argv); + + if (certfiles_cnt >= sizeof(certfiles)/sizeof(certfiles[0])) { + error_print(); + return -1; + } + certfiles[certfiles_cnt++] = certfile; + } else if (!strcmp(*argv, "-key")) { if (--argc < 1) goto bad; keyfile = *(++argv); + + if (keyfiles_cnt >= sizeof(keyfiles)/sizeof(keyfiles[0])) { + error_print(); + return -1; + } + keyfiles[keyfiles_cnt++] = keyfile; + } else if (!strcmp(*argv, "-pass")) { if (--argc < 1) goto bad; pass = *(++argv); + + if (passes_cnt >= sizeof(passes)/sizeof(passes[0])) { + error_print(); + return -1; + } + passes[passes_cnt++] = pass; + } else if (!strcmp(*argv, "-cacert")) { if (--argc < 1) goto bad; cacertfile = *(++argv); @@ -286,6 +345,11 @@ bad: argv++; } + if (certfiles_cnt != keyfiles_cnt || keyfiles_cnt != passes_cnt) { + error_print(); + return -1; + } + /* if (!cipher_suites_cnt) { error_print(); @@ -311,6 +375,16 @@ bad: goto end; } + for (i = 0; i < certfiles_cnt; i++) { + + fprintf(stderr, "add_certificate_chain_and_key\n"); + if (tls_ctx_add_certificate_chain_and_key(&ctx, certfiles[i], keyfiles[i], passes[i]) != 1) { + error_print(); + return -1; + } + } + + /* if (certfile) { if (!keyfile) { fprintf(stderr, "%s: '-key' option required\n", prog); @@ -325,6 +399,7 @@ bad: return -1; } } + */ if (supported_groups_cnt > 0) { if (tls_ctx_set_supported_groups(&ctx, supported_groups, supported_groups_cnt) != 1) { @@ -355,12 +430,13 @@ bad: } if (new_session_ticket < 0) { - error_print(); + fprintf(stderr, "%s: '-ticket_key' is required by '-new_session_ticket'\n", prog); return -1; } if (new_session_ticket > 0) { if (!ticket_key) { error_print(); + return -1; } if (tls13_ctx_enable_new_session_ticket(&ctx, new_session_ticket) != 1) { @@ -482,6 +558,51 @@ restart: return -1; } + + for (;;) { + + fd_set fds; + size_t sentlen; + + FD_ZERO(&fds); + + // listen socket + FD_SET(conn.sock, &fds); + + // 等待阻塞 + if (select((int)(conn.sock + 1), // In WinSock2, select() ignore the this arg + &fds, NULL, NULL, NULL) < 0) { + fprintf(stderr, "%s: select failed\n", prog); + goto end; + } + + if (FD_ISSET(conn.sock, &fds)) { + for (;;) { + memset(buf, 0, sizeof(buf)); + if (tls13_recv(&conn, (uint8_t *)buf, sizeof(buf), &len) != 1) { + goto end; + } + fwrite(buf, 1, len, stdout); + fflush(stdout); + + // FIXME: change tls13_recv API + if (conn.datalen == 0) { + break; + } + } + + fprintf(stderr, ">>>>>>>> send back\n"); + + if (tls13_send(&conn, (uint8_t *)buf, len, &sentlen) != 1) { + fprintf(stderr, "%s: send error\n", prog); + goto end; + } + } + } + + + + for (;;) { int rv;