From 6289c9ee003f9ba6121e068c520287735db31aae Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=96=BD=E6=A5=9A=E6=BD=AE?= <463779137@qq.com> Date: Wed, 8 Jun 2022 19:47:25 +0800 Subject: [PATCH] add TLCP feature --- ...certificate-signing-and-verification.patch | 2370 +++++++ Feature-Support-TLCP-protocol.patch | 6090 +++++++++++++++++ openssl.spec | 9 +- 3 files changed, 8467 insertions(+), 2 deletions(-) create mode 100644 Backport-Support-SM2-certificate-signing-and-verification.patch create mode 100644 Feature-Support-TLCP-protocol.patch diff --git a/Backport-Support-SM2-certificate-signing-and-verification.patch b/Backport-Support-SM2-certificate-signing-and-verification.patch new file mode 100644 index 0000000..2803aa1 --- /dev/null +++ b/Backport-Support-SM2-certificate-signing-and-verification.patch @@ -0,0 +1,2370 @@ +From 86fdbec352b75b6af4dcf68f76fe739baa5313bb Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?=E6=96=BD=E6=A5=9A=E6=BD=AE?= <463779137@qq.com> +Date: Wed, 8 Jun 2022 19:06:01 +0800 +Subject: [PATCH] Support SM2 certificate signing and verification + +--- + CHANGES | 3 + + apps/ca.c | 68 ++++++++++- + apps/pkeyutl.c | 171 +++++++++++++++++++++++++--- + apps/req.c | 167 +++++++++++++++++++++++++-- + apps/verify.c | 81 ++++++++++--- + crypto/asn1/a_sign.c | 13 ++- + crypto/asn1/a_verify.c | 3 +- + crypto/ec/ec_pmeth.c | 3 +- + crypto/err/openssl.txt | 5 + + crypto/objects/obj_dat.h | 17 ++- + crypto/objects/obj_mac.num | 1 + + crypto/objects/obj_xref.h | 4 +- + crypto/objects/obj_xref.txt | 2 + + crypto/objects/objects.txt | 2 + + crypto/sm2/sm2_pmeth.c | 22 ++++ + crypto/x509/x509_err.c | 6 + + crypto/x509/x_all.c | 158 +++++++++++++++++++++++++ + crypto/x509/x_req.c | 38 ++++++- + crypto/x509/x_x509.c | 22 ++++ + doc/man1/ca.pod | 16 +++ + doc/man1/pkeyutl.pod | 52 +++++++++ + doc/man1/req.pod | 21 ++++ + doc/man1/verify.pod | 14 +++ + doc/man3/X509_get0_sm2_id.pod | 55 +++++++++ + fuzz/oids.txt | 1 + + include/crypto/x509.h | 8 +- + include/openssl/ec.h | 1 - + include/openssl/obj_mac.h | 7 +- + include/openssl/x509.h | 7 ++ + include/openssl/x509err.h | 5 + + test/certs/sm2-ca-cert.pem | 14 +++ + test/certs/sm2-csr.pem | 9 ++ + test/certs/sm2-root.crt | 14 +++ + test/certs/sm2-root.key | 5 + + test/certs/sm2.key | 5 + + test/certs/sm2.pem | 13 +++ + test/recipes/20-test_pkeyutl.t | 41 +++++++ + test/recipes/25-test_req.t | 32 +++++- + test/recipes/25-test_verify.t | 14 ++- + test/recipes/70-test_verify_extra.t | 3 +- + test/recipes/80-test_ca.t | 20 +++- + test/verify_extra_test.c | 91 ++++++++++++++- + util/libcrypto.num | 4 + + 43 files changed, 1168 insertions(+), 70 deletions(-) + create mode 100644 doc/man3/X509_get0_sm2_id.pod + create mode 100644 test/certs/sm2-ca-cert.pem + create mode 100644 test/certs/sm2-csr.pem + create mode 100644 test/certs/sm2-root.crt + create mode 100644 test/certs/sm2-root.key + create mode 100644 test/certs/sm2.key + create mode 100644 test/certs/sm2.pem + create mode 100644 test/recipes/20-test_pkeyutl.t + +diff --git a/CHANGES b/CHANGES +index 9d58cb0..6ab70fe 100644 +--- a/CHANGES ++++ b/CHANGES +@@ -9,6 +9,9 @@ + + Changes between 1.1.1l and 1.1.1m [14 Dec 2021] + ++ *) Support SM2 signing and verification schemes with X509 certificate. ++ [Paul Yang] ++ + *) Avoid loading of a dynamic engine twice. + + [Bernd Edlinger] +diff --git a/apps/ca.c b/apps/ca.c +index 390ac37..795ee2c 100755 +--- a/apps/ca.c ++++ b/apps/ca.c +@@ -96,7 +96,8 @@ static int certify(X509 **xret, const char *infile, EVP_PKEY *pkey, X509 *x509, + const char *enddate, + long days, int batch, const char *ext_sect, CONF *conf, + int verbose, unsigned long certopt, unsigned long nameopt, +- int default_op, int ext_copy, int selfsign); ++ int default_op, int ext_copy, int selfsign, ++ unsigned char *sm2_id, size_t sm2idlen); + static int certify_cert(X509 **xret, const char *infile, EVP_PKEY *pkey, X509 *x509, + const EVP_MD *dgst, STACK_OF(OPENSSL_STRING) *sigopts, + STACK_OF(CONF_VALUE) *policy, CA_DB *db, +@@ -147,7 +148,7 @@ typedef enum OPTION_choice { + OPT_INFILES, OPT_SS_CERT, OPT_SPKAC, OPT_REVOKE, OPT_VALID, + OPT_EXTENSIONS, OPT_EXTFILE, OPT_STATUS, OPT_UPDATEDB, OPT_CRLEXTS, + OPT_RAND_SERIAL, +- OPT_R_ENUM, ++ OPT_R_ENUM, OPT_SM2ID, OPT_SM2HEXID, + /* Do not change the order here; see related case statements below */ + OPT_CRL_REASON, OPT_CRL_HOLD, OPT_CRL_COMPROMISE, OPT_CRL_CA_COMPROMISE + } OPTION_CHOICE; +@@ -217,6 +218,12 @@ const OPTIONS ca_options[] = { + OPT_R_OPTIONS, + #ifndef OPENSSL_NO_ENGINE + {"engine", OPT_ENGINE, 's', "Use engine, possibly a hardware device"}, ++#endif ++#ifndef OPENSSL_NO_SM2 ++ {"sm2-id", OPT_SM2ID, 's', ++ "Specify an ID string to verify an SM2 certificate request"}, ++ {"sm2-hex-id", OPT_SM2HEXID, 's', ++ "Specify a hex ID string to verify an SM2 certificate request"}, + #endif + {NULL} + }; +@@ -262,6 +269,9 @@ int ca_main(int argc, char **argv) + REVINFO_TYPE rev_type = REV_NONE; + X509_REVOKED *r = NULL; + OPTION_CHOICE o; ++ unsigned char *sm2_id = NULL; ++ size_t sm2_idlen = 0; ++ int sm2_free = 0; + + prog = opt_init(argc, argv, ca_options); + while ((o = opt_next()) != OPT_EOF) { +@@ -425,6 +435,30 @@ opthelp: + case OPT_ENGINE: + e = setup_engine(opt_arg(), 0); + break; ++ case OPT_SM2ID: ++ /* we assume the input is not a hex string */ ++ if (sm2_id != NULL) { ++ BIO_printf(bio_err, ++ "Use one of the options 'sm2-hex-id' or 'sm2-id'\n"); ++ goto end; ++ } ++ sm2_id = (unsigned char *)opt_arg(); ++ sm2_idlen = strlen((const char *)sm2_id); ++ break; ++ case OPT_SM2HEXID: ++ /* try to parse the input as hex string first */ ++ if (sm2_id != NULL) { ++ BIO_printf(bio_err, ++ "Use one of the options 'sm2-hex-id' or 'sm2-id'\n"); ++ goto end; ++ } ++ sm2_free = 1; ++ sm2_id = OPENSSL_hexstr2buf(opt_arg(), (long *)&sm2_idlen); ++ if (sm2_id == NULL) { ++ BIO_printf(bio_err, "Invalid hex string input\n"); ++ goto end; ++ } ++ break; + } + } + end_of_options: +@@ -913,7 +947,8 @@ end_of_options: + j = certify(&x, infile, pkey, x509p, dgst, sigopts, attribs, db, + serial, subj, chtype, multirdn, email_dn, startdate, + enddate, days, batch, extensions, conf, verbose, +- certopt, get_nameopt(), default_op, ext_copy, selfsign); ++ certopt, get_nameopt(), default_op, ext_copy, selfsign, ++ sm2_id, sm2_idlen); + if (j < 0) + goto end; + if (j > 0) { +@@ -932,7 +967,8 @@ end_of_options: + j = certify(&x, argv[i], pkey, x509p, dgst, sigopts, attribs, db, + serial, subj, chtype, multirdn, email_dn, startdate, + enddate, days, batch, extensions, conf, verbose, +- certopt, get_nameopt(), default_op, ext_copy, selfsign); ++ certopt, get_nameopt(), default_op, ext_copy, selfsign, ++ sm2_id, sm2_idlen); + if (j < 0) + goto end; + if (j > 0) { +@@ -1230,6 +1266,8 @@ end_of_options: + ret = 0; + + end: ++ if (sm2_free) ++ OPENSSL_free(sm2_id); + if (ret) + ERR_print_errors(bio_err); + BIO_free_all(Sout); +@@ -1268,7 +1306,8 @@ static int certify(X509 **xret, const char *infile, EVP_PKEY *pkey, X509 *x509, + const char *enddate, + long days, int batch, const char *ext_sect, CONF *lconf, + int verbose, unsigned long certopt, unsigned long nameopt, +- int default_op, int ext_copy, int selfsign) ++ int default_op, int ext_copy, int selfsign, ++ unsigned char *sm2id, size_t sm2idlen) + { + X509_REQ *req = NULL; + BIO *in = NULL; +@@ -1300,6 +1339,25 @@ static int certify(X509 **xret, const char *infile, EVP_PKEY *pkey, X509 *x509, + BIO_printf(bio_err, "error unpacking public key\n"); + goto end; + } ++ if (sm2id != NULL) { ++#ifndef OPENSSL_NO_SM2 ++ ASN1_OCTET_STRING *v; ++ ++ v = ASN1_OCTET_STRING_new(); ++ if (v == NULL) { ++ BIO_printf(bio_err, "error: SM2 ID allocation failed\n"); ++ goto end; ++ } ++ ++ if (!ASN1_OCTET_STRING_set(v, sm2id, sm2idlen)) { ++ BIO_printf(bio_err, "error: setting SM2 ID failed\n"); ++ ASN1_OCTET_STRING_free(v); ++ goto end; ++ } ++ ++ X509_REQ_set0_sm2_id(req, v); ++#endif ++ } + i = X509_REQ_verify(req, pktmp); + pktmp = NULL; + if (i < 0) { +diff --git a/apps/pkeyutl.c b/apps/pkeyutl.c +index 831e14d..1d3d57b 100644 +--- a/apps/pkeyutl.c ++++ b/apps/pkeyutl.c +@@ -22,7 +22,7 @@ + static EVP_PKEY_CTX *init_ctx(const char *kdfalg, int *pkeysize, + const char *keyfile, int keyform, int key_type, + char *passinarg, int pkey_op, ENGINE *e, +- const int impl); ++ const int impl, EVP_PKEY **ppkey); + + static int setup_peer(EVP_PKEY_CTX *ctx, int peerform, const char *file, + ENGINE *e); +@@ -31,6 +31,11 @@ static int do_keyop(EVP_PKEY_CTX *ctx, int pkey_op, + unsigned char *out, size_t *poutlen, + const unsigned char *in, size_t inlen); + ++static int do_raw_keyop(int pkey_op, EVP_PKEY_CTX *ctx, ++ const EVP_MD *md, EVP_PKEY *pkey, BIO *in, ++ unsigned char *sig, int siglen, ++ unsigned char **out, size_t *poutlen); ++ + typedef enum OPTION_choice { + OPT_ERR = -1, OPT_EOF = 0, OPT_HELP, + OPT_ENGINE, OPT_ENGINE_IMPL, OPT_IN, OPT_OUT, +@@ -38,12 +43,15 @@ typedef enum OPTION_choice { + OPT_VERIFY, OPT_VERIFYRECOVER, OPT_REV, OPT_ENCRYPT, OPT_DECRYPT, + OPT_DERIVE, OPT_SIGFILE, OPT_INKEY, OPT_PEERKEY, OPT_PASSIN, + OPT_PEERFORM, OPT_KEYFORM, OPT_PKEYOPT, OPT_KDF, OPT_KDFLEN, +- OPT_R_ENUM ++ OPT_R_ENUM, OPT_RAWIN, OPT_DIGEST + } OPTION_CHOICE; + + const OPTIONS pkeyutl_options[] = { + {"help", OPT_HELP, '-', "Display this summary"}, + {"in", OPT_IN, '<', "Input file - default stdin"}, ++ {"rawin", OPT_RAWIN, '-', "Indicate the input data is in raw form"}, ++ {"digest", OPT_DIGEST, 's', ++ "Specify the digest algorithm when signing the raw input data"}, + {"out", OPT_OUT, '>', "Output file - default stdout"}, + {"pubin", OPT_PUBIN, '-', "Input is a public key"}, + {"certin", OPT_CERTIN, '-', "Input is a cert with a public key"}, +@@ -80,6 +88,7 @@ int pkeyutl_main(int argc, char **argv) + BIO *in = NULL, *out = NULL; + ENGINE *e = NULL; + EVP_PKEY_CTX *ctx = NULL; ++ EVP_PKEY *pkey = NULL; + char *infile = NULL, *outfile = NULL, *sigfile = NULL, *passinarg = NULL; + char hexdump = 0, asn1parse = 0, rev = 0, *prog; + unsigned char *buf_in = NULL, *buf_out = NULL, *sig = NULL; +@@ -94,6 +103,8 @@ int pkeyutl_main(int argc, char **argv) + const char *kdfalg = NULL; + int kdflen = 0; + STACK_OF(OPENSSL_STRING) *pkeyopts = NULL; ++ int rawin = 0; ++ const EVP_MD *md = NULL; + + prog = opt_init(argc, argv, pkeyutl_options); + while ((o = opt_next()) != OPT_EOF) { +@@ -192,12 +203,39 @@ int pkeyutl_main(int argc, char **argv) + goto end; + } + break; ++ case OPT_RAWIN: ++ rawin = 1; ++ break; ++ case OPT_DIGEST: ++ if (!opt_md(opt_arg(), &md)) ++ goto end; ++ break; + } + } + argc = opt_num_rest(); + if (argc != 0) + goto opthelp; + ++ if (rawin && pkey_op != EVP_PKEY_OP_SIGN && pkey_op != EVP_PKEY_OP_VERIFY) { ++ BIO_printf(bio_err, ++ "%s: -rawin can only be used with -sign or -verify\n", ++ prog); ++ goto opthelp; ++ } ++ ++ if (md != NULL && !rawin) { ++ BIO_printf(bio_err, ++ "%s: -digest can only be used with -rawin\n", ++ prog); ++ goto opthelp; ++ } ++ ++ if (rawin && rev) { ++ BIO_printf(bio_err, "%s: -rev cannot be used with raw input\n", ++ prog); ++ goto opthelp; ++ } ++ + if (kdfalg != NULL) { + if (kdflen == 0) { + BIO_printf(bio_err, +@@ -214,7 +252,7 @@ int pkeyutl_main(int argc, char **argv) + goto opthelp; + } + ctx = init_ctx(kdfalg, &keysize, inkey, keyform, key_type, +- passinarg, pkey_op, e, engine_impl); ++ passinarg, pkey_op, e, engine_impl, &pkey); + if (ctx == NULL) { + BIO_printf(bio_err, "%s: Error initializing context\n", prog); + ERR_print_errors(bio_err); +@@ -277,7 +315,8 @@ int pkeyutl_main(int argc, char **argv) + } + } + +- if (in != NULL) { ++ /* Raw input data is handled elsewhere */ ++ if (in != NULL && !rawin) { + /* Read the input data */ + buf_inlen = bio_to_mem(&buf_in, keysize * 10, in); + if (buf_inlen < 0) { +@@ -296,8 +335,9 @@ int pkeyutl_main(int argc, char **argv) + } + } + +- /* Sanity check the input */ +- if (buf_inlen > EVP_MAX_MD_SIZE ++ /* Sanity check the input if the input is not raw */ ++ if (!rawin ++ && buf_inlen > EVP_MAX_MD_SIZE + && (pkey_op == EVP_PKEY_OP_SIGN + || pkey_op == EVP_PKEY_OP_VERIFY)) { + BIO_printf(bio_err, +@@ -306,8 +346,13 @@ int pkeyutl_main(int argc, char **argv) + } + + if (pkey_op == EVP_PKEY_OP_VERIFY) { +- rv = EVP_PKEY_verify(ctx, sig, (size_t)siglen, +- buf_in, (size_t)buf_inlen); ++ if (rawin) { ++ rv = do_raw_keyop(pkey_op, ctx, md, pkey, in, sig, siglen, ++ NULL, 0); ++ } else { ++ rv = EVP_PKEY_verify(ctx, sig, (size_t)siglen, ++ buf_in, (size_t)buf_inlen); ++ } + if (rv == 1) { + BIO_puts(out, "Signature Verified Successfully\n"); + ret = 0; +@@ -320,14 +365,20 @@ int pkeyutl_main(int argc, char **argv) + buf_outlen = kdflen; + rv = 1; + } else { +- rv = do_keyop(ctx, pkey_op, NULL, (size_t *)&buf_outlen, +- buf_in, (size_t)buf_inlen); +- } +- if (rv > 0 && buf_outlen != 0) { +- buf_out = app_malloc(buf_outlen, "buffer output"); +- rv = do_keyop(ctx, pkey_op, +- buf_out, (size_t *)&buf_outlen, +- buf_in, (size_t)buf_inlen); ++ if (rawin) { ++ /* rawin allocates the buffer in do_raw_keyop() */ ++ rv = do_raw_keyop(pkey_op, ctx, md, pkey, in, NULL, 0, ++ &buf_out, (size_t *)&buf_outlen); ++ } else { ++ rv = do_keyop(ctx, pkey_op, NULL, (size_t *)&buf_outlen, ++ buf_in, (size_t)buf_inlen); ++ if (rv > 0 && buf_outlen != 0) { ++ buf_out = app_malloc(buf_outlen, "buffer output"); ++ rv = do_keyop(ctx, pkey_op, ++ buf_out, (size_t *)&buf_outlen, ++ buf_in, (size_t)buf_inlen); ++ } ++ } + } + if (rv <= 0) { + if (pkey_op != EVP_PKEY_OP_DERIVE) { +@@ -364,7 +415,7 @@ int pkeyutl_main(int argc, char **argv) + static EVP_PKEY_CTX *init_ctx(const char *kdfalg, int *pkeysize, + const char *keyfile, int keyform, int key_type, + char *passinarg, int pkey_op, ENGINE *e, +- const int engine_impl) ++ const int engine_impl, EVP_PKEY **ppkey) + { + EVP_PKEY *pkey = NULL; + EVP_PKEY_CTX *ctx = NULL; +@@ -424,8 +475,26 @@ static EVP_PKEY_CTX *init_ctx(const char *kdfalg, int *pkeysize, + } else { + if (pkey == NULL) + goto end; ++ ++#ifndef OPENSSL_NO_EC ++ /* SM2 needs a special treatment */ ++ if (EVP_PKEY_id(pkey) == EVP_PKEY_EC) { ++ EC_KEY *eckey = NULL; ++ const EC_GROUP *group = NULL; ++ int nid; ++ ++ if ((eckey = EVP_PKEY_get0_EC_KEY(pkey)) == NULL ++ || (group = EC_KEY_get0_group(eckey)) == NULL ++ || (nid = EC_GROUP_get_curve_name(group)) == 0) ++ goto end; ++ if (nid == NID_sm2) ++ EVP_PKEY_set_alias_type(pkey, EVP_PKEY_SM2); ++ } ++#endif + *pkeysize = EVP_PKEY_size(pkey); + ctx = EVP_PKEY_CTX_new(pkey, impl); ++ if (ppkey != NULL) ++ *ppkey = pkey; + EVP_PKEY_free(pkey); + } + +@@ -522,3 +591,71 @@ static int do_keyop(EVP_PKEY_CTX *ctx, int pkey_op, + } + return rv; + } ++ ++#define TBUF_MAXSIZE 2048 ++ ++static int do_raw_keyop(int pkey_op, EVP_PKEY_CTX *ctx, ++ const EVP_MD *md, EVP_PKEY *pkey, BIO *in, ++ unsigned char *sig, int siglen, ++ unsigned char **out, size_t *poutlen) ++{ ++ int rv = 0; ++ EVP_MD_CTX *mctx = NULL; ++ unsigned char tbuf[TBUF_MAXSIZE]; ++ int tbuf_len = 0; ++ ++ if ((mctx = EVP_MD_CTX_new()) == NULL) { ++ BIO_printf(bio_err, "Error: out of memory\n"); ++ return rv; ++ } ++ EVP_MD_CTX_set_pkey_ctx(mctx, ctx); ++ ++ switch(pkey_op) { ++ case EVP_PKEY_OP_VERIFY: ++ if (EVP_DigestVerifyInit(mctx, NULL, md, NULL, pkey) != 1) ++ goto end; ++ for (;;) { ++ tbuf_len = BIO_read(in, tbuf, TBUF_MAXSIZE); ++ if (tbuf_len == 0) ++ break; ++ if (tbuf_len < 0) { ++ BIO_printf(bio_err, "Error reading raw input data\n"); ++ goto end; ++ } ++ rv = EVP_DigestVerifyUpdate(mctx, tbuf, (size_t)tbuf_len); ++ if (rv != 1) { ++ BIO_printf(bio_err, "Error verifying raw input data\n"); ++ goto end; ++ } ++ } ++ rv = EVP_DigestVerifyFinal(mctx, sig, (size_t)siglen); ++ break; ++ case EVP_PKEY_OP_SIGN: ++ if (EVP_DigestSignInit(mctx, NULL, md, NULL, pkey) != 1) ++ goto end; ++ for (;;) { ++ tbuf_len = BIO_read(in, tbuf, TBUF_MAXSIZE); ++ if (tbuf_len == 0) ++ break; ++ if (tbuf_len < 0) { ++ BIO_printf(bio_err, "Error reading raw input data\n"); ++ goto end; ++ } ++ rv = EVP_DigestSignUpdate(mctx, tbuf, (size_t)tbuf_len); ++ if (rv != 1) { ++ BIO_printf(bio_err, "Error signing raw input data\n"); ++ goto end; ++ } ++ } ++ rv = EVP_DigestSignFinal(mctx, NULL, poutlen); ++ if (rv == 1 && out != NULL) { ++ *out = app_malloc(*poutlen, "buffer output"); ++ rv = EVP_DigestSignFinal(mctx, *out, poutlen); ++ } ++ break; ++ } ++ ++ end: ++ EVP_MD_CTX_free(mctx); ++ return rv; ++} +diff --git a/apps/req.c b/apps/req.c +index a603907..95dd0e4 100644 +--- a/apps/req.c ++++ b/apps/req.c +@@ -90,7 +90,7 @@ typedef enum OPTION_choice { + OPT_VERIFY, OPT_NODES, OPT_NOOUT, OPT_VERBOSE, OPT_UTF8, + OPT_NAMEOPT, OPT_REQOPT, OPT_SUBJ, OPT_SUBJECT, OPT_TEXT, OPT_X509, + OPT_MULTIVALUE_RDN, OPT_DAYS, OPT_SET_SERIAL, OPT_ADDEXT, OPT_EXTENSIONS, +- OPT_REQEXTS, OPT_PRECERT, OPT_MD, ++ OPT_REQEXTS, OPT_PRECERT, OPT_MD, OPT_SM2ID, OPT_SM2HEXID, + OPT_R_ENUM + } OPTION_CHOICE; + +@@ -145,6 +145,12 @@ const OPTIONS req_options[] = { + {"engine", OPT_ENGINE, 's', "Use engine, possibly a hardware device"}, + {"keygen_engine", OPT_KEYGEN_ENGINE, 's', + "Specify engine to be used for key generation operations"}, ++#endif ++#ifndef OPENSSL_NO_SM2 ++ {"sm2-id", OPT_SM2ID, 's', ++ "Specify an ID string to verify an SM2 certificate request"}, ++ {"sm2-hex-id", OPT_SM2HEXID, 's', ++ "Specify a hex ID string to verify an SM2 certificate request"}, + #endif + {NULL} + }; +@@ -242,6 +248,9 @@ int req_main(int argc, char **argv) + int nodes = 0, newhdr = 0, subject = 0, pubkey = 0, precert = 0; + long newkey = -1; + unsigned long chtype = MBSTRING_ASC, reqflag = 0; ++ unsigned char *sm2_id = NULL; ++ size_t sm2_idlen = 0; ++ int sm2_free = 0; + + #ifndef OPENSSL_NO_DES + cipher = EVP_des_ede3_cbc(); +@@ -417,6 +426,29 @@ int req_main(int argc, char **argv) + goto opthelp; + digest = md_alg; + break; ++ case OPT_SM2ID: ++ if (sm2_id != NULL) { ++ BIO_printf(bio_err, ++ "Use one of the options 'sm2-hex-id' or 'sm2-id'\n"); ++ goto end; ++ } ++ sm2_id = (unsigned char *)opt_arg(); ++ sm2_idlen = strlen((const char *)sm2_id); ++ break; ++ case OPT_SM2HEXID: ++ if (sm2_id != NULL) { ++ BIO_printf(bio_err, ++ "Use one of the options 'sm2-hex-id' or 'sm2-id'\n"); ++ goto end; ++ } ++ /* try to parse the input as hex string first */ ++ sm2_free = 1; ++ sm2_id = OPENSSL_hexstr2buf(opt_arg(), (long *)&sm2_idlen); ++ if (sm2_id == NULL) { ++ BIO_printf(bio_err, "Invalid hex string input\n"); ++ goto end; ++ } ++ break; + } + } + argc = opt_num_rest(); +@@ -849,6 +881,26 @@ int req_main(int argc, char **argv) + goto end; + } + ++ if (sm2_id != NULL) { ++#ifndef OPENSSL_NO_SM2 ++ ASN1_OCTET_STRING *v; ++ ++ v = ASN1_OCTET_STRING_new(); ++ if (v == NULL) { ++ BIO_printf(bio_err, "error: SM2 ID allocation failed\n"); ++ goto end; ++ } ++ ++ if (!ASN1_OCTET_STRING_set(v, sm2_id, sm2_idlen)) { ++ BIO_printf(bio_err, "error: setting SM2 ID failed\n"); ++ ASN1_OCTET_STRING_free(v); ++ goto end; ++ } ++ ++ X509_REQ_set0_sm2_id(req, v); ++#endif ++ } ++ + i = X509_REQ_verify(req, tpubkey); + + if (i < 0) { +@@ -957,6 +1009,8 @@ int req_main(int argc, char **argv) + } + ret = 0; + end: ++ if (sm2_free) ++ OPENSSL_free(sm2_id); + if (ret) { + ERR_print_errors(bio_err); + } +@@ -1611,14 +1665,58 @@ static int genpkey_cb(EVP_PKEY_CTX *ctx) + return 1; + } + ++#ifndef OPENSSL_NO_SM2 ++static int ec_pkey_is_sm2(EVP_PKEY *pkey) ++{ ++ EC_KEY *eckey = NULL; ++ const EC_GROUP *group = NULL; ++ ++ if (EVP_PKEY_id(pkey) == EVP_PKEY_SM2) ++ return 1; ++ if (EVP_PKEY_id(pkey) == EVP_PKEY_EC ++ && (eckey = EVP_PKEY_get0_EC_KEY(pkey)) != NULL ++ && (group = EC_KEY_get0_group(eckey)) != NULL ++ && EC_GROUP_get_curve_name(group) == NID_sm2) ++ return 1; ++ return 0; ++} ++#endif ++ + static int do_sign_init(EVP_MD_CTX *ctx, EVP_PKEY *pkey, + const EVP_MD *md, STACK_OF(OPENSSL_STRING) *sigopts) + { + EVP_PKEY_CTX *pkctx = NULL; +- int i, def_nid; ++#ifndef OPENSSL_NO_SM2 ++ EVP_PKEY_CTX *pctx = NULL; ++#endif ++ int i, def_nid, ret = 0; + + if (ctx == NULL) +- return 0; ++ goto err; ++#ifndef OPENSSL_NO_SM2 ++ if (ec_pkey_is_sm2(pkey)) { ++ /* initialize some SM2-specific code */ ++ if (!EVP_PKEY_set_alias_type(pkey, EVP_PKEY_SM2)) { ++ BIO_printf(bio_err, "Internal error.\n"); ++ goto err; ++ } ++ pctx = EVP_PKEY_CTX_new(pkey, NULL); ++ if (pctx == NULL) { ++ BIO_printf(bio_err, "memory allocation failure.\n"); ++ goto err; ++ } ++ /* set SM2 ID from sig options before calling the real init routine */ ++ for (i = 0; i < sk_OPENSSL_STRING_num(sigopts); i++) { ++ char *sigopt = sk_OPENSSL_STRING_value(sigopts, i); ++ if (pkey_ctrl_string(pctx, sigopt) <= 0) { ++ BIO_printf(bio_err, "parameter error \"%s\"\n", sigopt); ++ ERR_print_errors(bio_err); ++ goto err; ++ } ++ } ++ EVP_MD_CTX_set_pkey_ctx(ctx, pctx); ++ } ++#endif + /* + * EVP_PKEY_get_default_digest_nid() returns 2 if the digest is mandatory + * for this algorithm. +@@ -1629,16 +1727,23 @@ static int do_sign_init(EVP_MD_CTX *ctx, EVP_PKEY *pkey, + md = NULL; + } + if (!EVP_DigestSignInit(ctx, &pkctx, md, NULL, pkey)) +- return 0; ++ goto err; + for (i = 0; i < sk_OPENSSL_STRING_num(sigopts); i++) { + char *sigopt = sk_OPENSSL_STRING_value(sigopts, i); + if (pkey_ctrl_string(pkctx, sigopt) <= 0) { + BIO_printf(bio_err, "parameter error \"%s\"\n", sigopt); + ERR_print_errors(bio_err); +- return 0; ++ goto err; + } + } +- return 1; ++ ++ ret = 1; ++ err: ++#ifndef OPENSSL_NO_SM2 ++ if (!ret) ++ EVP_PKEY_CTX_free(pctx); ++#endif ++ return ret; + } + + int do_X509_sign(X509 *x, EVP_PKEY *pkey, const EVP_MD *md, +@@ -1646,10 +1751,24 @@ int do_X509_sign(X509 *x, EVP_PKEY *pkey, const EVP_MD *md, + { + int rv; + EVP_MD_CTX *mctx = EVP_MD_CTX_new(); ++#ifndef OPENSSL_NO_SM2 ++ EVP_PKEY_CTX *pctx = NULL; ++#endif + + rv = do_sign_init(mctx, pkey, md, sigopts); +- if (rv > 0) ++ if (rv > 0) { + rv = X509_sign_ctx(x, mctx); ++#ifndef OPENSSL_NO_SM2 ++ /* ++ * only in SM2 case we need to free the pctx explicitly ++ * if do_sign_init() fails, pctx is already freed in it ++ */ ++ if (ec_pkey_is_sm2(pkey)) { ++ pctx = EVP_MD_CTX_pkey_ctx(mctx); ++ EVP_PKEY_CTX_free(pctx); ++ } ++#endif ++ } + EVP_MD_CTX_free(mctx); + return rv > 0 ? 1 : 0; + } +@@ -1659,9 +1778,24 @@ int do_X509_REQ_sign(X509_REQ *x, EVP_PKEY *pkey, const EVP_MD *md, + { + int rv; + EVP_MD_CTX *mctx = EVP_MD_CTX_new(); ++#ifndef OPENSSL_NO_SM2 ++ EVP_PKEY_CTX *pctx = NULL; ++#endif ++ + rv = do_sign_init(mctx, pkey, md, sigopts); +- if (rv > 0) ++ if (rv > 0) { + rv = X509_REQ_sign_ctx(x, mctx); ++#ifndef OPENSSL_NO_SM2 ++ /* ++ * only in SM2 case we need to free the pctx explicitly ++ * if do_sign_init() fails, pctx is already freed in it ++ */ ++ if (ec_pkey_is_sm2(pkey)) { ++ pctx = EVP_MD_CTX_pkey_ctx(mctx); ++ EVP_PKEY_CTX_free(pctx); ++ } ++#endif ++ } + EVP_MD_CTX_free(mctx); + return rv > 0 ? 1 : 0; + } +@@ -1671,9 +1805,24 @@ int do_X509_CRL_sign(X509_CRL *x, EVP_PKEY *pkey, const EVP_MD *md, + { + int rv; + EVP_MD_CTX *mctx = EVP_MD_CTX_new(); ++#ifndef OPENSSL_NO_SM2 ++ EVP_PKEY_CTX *pctx = NULL; ++#endif ++ + rv = do_sign_init(mctx, pkey, md, sigopts); +- if (rv > 0) ++ if (rv > 0) { + rv = X509_CRL_sign_ctx(x, mctx); ++#ifndef OPENSSL_NO_SM2 ++ /* ++ * only in SM2 case we need to free the pctx explicitly ++ * if do_sign_init() fails, no need to double free pctx ++ */ ++ if (ec_pkey_is_sm2(pkey)) { ++ pctx = EVP_MD_CTX_pkey_ctx(mctx); ++ EVP_PKEY_CTX_free(pctx); ++ } ++#endif ++ } + EVP_MD_CTX_free(mctx); + return rv > 0 ? 1 : 0; + } +diff --git a/apps/verify.c b/apps/verify.c +index 1f93856..9000567 100644 +--- a/apps/verify.c ++++ b/apps/verify.c +@@ -21,7 +21,8 @@ + static int cb(int ok, X509_STORE_CTX *ctx); + static int check(X509_STORE *ctx, const char *file, + STACK_OF(X509) *uchain, STACK_OF(X509) *tchain, +- STACK_OF(X509_CRL) *crls, int show_chain); ++ STACK_OF(X509_CRL) *crls, int show_chain, ++ unsigned char *sm2id, size_t sm2idlen); + static int v_verbose = 0, vflags = 0; + + typedef enum OPTION_choice { +@@ -29,7 +30,7 @@ typedef enum OPTION_choice { + OPT_ENGINE, OPT_CAPATH, OPT_CAFILE, OPT_NOCAPATH, OPT_NOCAFILE, + OPT_UNTRUSTED, OPT_TRUSTED, OPT_CRLFILE, OPT_CRL_DOWNLOAD, OPT_SHOW_CHAIN, + OPT_V_ENUM, OPT_NAMEOPT, +- OPT_VERBOSE ++ OPT_VERBOSE, OPT_SM2ID, OPT_SM2HEXID + } OPTION_CHOICE; + + const OPTIONS verify_options[] = { +@@ -56,6 +57,12 @@ const OPTIONS verify_options[] = { + OPT_V_OPTIONS, + #ifndef OPENSSL_NO_ENGINE + {"engine", OPT_ENGINE, 's', "Use engine, possibly a hardware device"}, ++#endif ++#ifndef OPENSSL_NO_SM2 ++ {"sm2-id", OPT_SM2ID, 's', ++ "Specify an ID string to verify an SM2 certificate"}, ++ {"sm2-hex-id", OPT_SM2HEXID, 's', ++ "Specify a hex ID string to verify an SM2 certificate"}, + #endif + {NULL} + }; +@@ -71,6 +78,9 @@ int verify_main(int argc, char **argv) + int noCApath = 0, noCAfile = 0; + int vpmtouched = 0, crl_download = 0, show_chain = 0, i = 0, ret = 1; + OPTION_CHOICE o; ++ unsigned char *sm2_id = NULL; ++ size_t sm2_idlen = 0; ++ int sm2_free = 0; + + if ((vpm = X509_VERIFY_PARAM_new()) == NULL) + goto end; +@@ -158,6 +168,20 @@ int verify_main(int argc, char **argv) + case OPT_VERBOSE: + v_verbose = 1; + break; ++ case OPT_SM2ID: ++ /* we assume the input is not a hex string */ ++ sm2_id = (unsigned char *)opt_arg(); ++ sm2_idlen = strlen((const char *)sm2_id); ++ break; ++ case OPT_SM2HEXID: ++ /* try to parse the input as hex string first */ ++ sm2_free = 1; ++ sm2_id = OPENSSL_hexstr2buf(opt_arg(), (long *)&sm2_idlen); ++ if (sm2_id == NULL) { ++ BIO_printf(bio_err, "Invalid hex string input\n"); ++ goto end; ++ } ++ break; + } + } + argc = opt_num_rest(); +@@ -183,16 +207,19 @@ int verify_main(int argc, char **argv) + + ret = 0; + if (argc < 1) { +- if (check(store, NULL, untrusted, trusted, crls, show_chain) != 1) ++ if (check(store, NULL, untrusted, trusted, crls, show_chain, ++ sm2_id, sm2_idlen) != 1) + ret = -1; + } else { + for (i = 0; i < argc; i++) + if (check(store, argv[i], untrusted, trusted, crls, +- show_chain) != 1) ++ show_chain, sm2_id, sm2_idlen) != 1) + ret = -1; + } + + end: ++ if (sm2_free) ++ OPENSSL_free(sm2_id); + X509_VERIFY_PARAM_free(vpm); + X509_STORE_free(store); + sk_X509_pop_free(untrusted, X509_free); +@@ -204,7 +231,8 @@ int verify_main(int argc, char **argv) + + static int check(X509_STORE *ctx, const char *file, + STACK_OF(X509) *uchain, STACK_OF(X509) *tchain, +- STACK_OF(X509_CRL) *crls, int show_chain) ++ STACK_OF(X509_CRL) *crls, int show_chain, ++ unsigned char *sm2id, size_t sm2idlen) + { + X509 *x = NULL; + int i = 0, ret = 0; +@@ -216,18 +244,39 @@ static int check(X509_STORE *ctx, const char *file, + if (x == NULL) + goto end; + ++ if (sm2id != NULL) { ++#ifndef OPENSSL_NO_SM2 ++ ASN1_OCTET_STRING *v; ++ ++ v = ASN1_OCTET_STRING_new(); ++ if (v == NULL) { ++ BIO_printf(bio_err, "error: SM2 ID allocation failed\n"); ++ goto end; ++ } ++ ++ if (!ASN1_OCTET_STRING_set(v, sm2id, sm2idlen)) { ++ BIO_printf(bio_err, "error: setting SM2 ID failed\n"); ++ ASN1_OCTET_STRING_free(v); ++ goto end; ++ } ++ ++ X509_set0_sm2_id(x, v); ++#endif ++ } ++ + csc = X509_STORE_CTX_new(); + if (csc == NULL) { +- printf("error %s: X.509 store context allocation failed\n", +- (file == NULL) ? "stdin" : file); ++ BIO_printf(bio_err, "error %s: X.509 store context allocation failed\n", ++ (file == NULL) ? "stdin" : file); + goto end; + } + + X509_STORE_set_flags(ctx, vflags); + if (!X509_STORE_CTX_init(csc, ctx, x, uchain)) { + X509_STORE_CTX_free(csc); +- printf("error %s: X.509 store context initialization failed\n", +- (file == NULL) ? "stdin" : file); ++ BIO_printf(bio_err, ++ "error %s: X.509 store context initialization failed\n", ++ (file == NULL) ? "stdin" : file); + goto end; + } + if (tchain != NULL) +@@ -236,28 +285,30 @@ static int check(X509_STORE *ctx, const char *file, + X509_STORE_CTX_set0_crls(csc, crls); + i = X509_verify_cert(csc); + if (i > 0 && X509_STORE_CTX_get_error(csc) == X509_V_OK) { +- printf("%s: OK\n", (file == NULL) ? "stdin" : file); ++ BIO_printf(bio_out, "%s: OK\n", (file == NULL) ? "stdin" : file); + ret = 1; + if (show_chain) { + int j; + + chain = X509_STORE_CTX_get1_chain(csc); + num_untrusted = X509_STORE_CTX_get_num_untrusted(csc); +- printf("Chain:\n"); ++ BIO_printf(bio_out, "Chain:\n"); + for (j = 0; j < sk_X509_num(chain); j++) { + X509 *cert = sk_X509_value(chain, j); +- printf("depth=%d: ", j); ++ BIO_printf(bio_out, "depth=%d: ", j); + X509_NAME_print_ex_fp(stdout, + X509_get_subject_name(cert), + 0, get_nameopt()); + if (j < num_untrusted) +- printf(" (untrusted)"); +- printf("\n"); ++ BIO_printf(bio_out, " (untrusted)"); ++ BIO_printf(bio_out, "\n"); + } + sk_X509_pop_free(chain, X509_free); + } + } else { +- printf("error %s: verification failed\n", (file == NULL) ? "stdin" : file); ++ BIO_printf(bio_err, ++ "error %s: verification failed\n", ++ (file == NULL) ? "stdin" : file); + } + X509_STORE_CTX_free(csc); + +diff --git a/crypto/asn1/a_sign.c b/crypto/asn1/a_sign.c +index 72381b6..c29080b 100644 +--- a/crypto/asn1/a_sign.c ++++ b/crypto/asn1/a_sign.c +@@ -145,7 +145,7 @@ int ASN1_item_sign_ctx(const ASN1_ITEM *it, + unsigned char *buf_in = NULL, *buf_out = NULL; + size_t inl = 0, outl = 0, outll = 0; + int signid, paramtype, buf_len = 0; +- int rv; ++ int rv, pkey_id; + + type = EVP_MD_CTX_md(ctx); + pkey = EVP_PKEY_CTX_get0_pkey(EVP_MD_CTX_pkey_ctx(ctx)); +@@ -184,9 +184,14 @@ int ASN1_item_sign_ctx(const ASN1_ITEM *it, + ASN1err(ASN1_F_ASN1_ITEM_SIGN_CTX, ASN1_R_CONTEXT_NOT_INITIALISED); + goto err; + } +- if (!OBJ_find_sigid_by_algs(&signid, +- EVP_MD_nid(type), +- pkey->ameth->pkey_id)) { ++ ++ pkey_id = ++#ifndef OPENSSL_NO_SM2 ++ EVP_PKEY_id(pkey) == NID_sm2 ? NID_sm2 : ++#endif ++ pkey->ameth->pkey_id; ++ ++ if (!OBJ_find_sigid_by_algs(&signid, EVP_MD_nid(type), pkey_id)) { + ASN1err(ASN1_F_ASN1_ITEM_SIGN_CTX, + ASN1_R_DIGEST_AND_KEY_TYPE_NOT_SUPPORTED); + goto err; +diff --git a/crypto/asn1/a_verify.c b/crypto/asn1/a_verify.c +index 4b5f542..f543aa1 100644 +--- a/crypto/asn1/a_verify.c ++++ b/crypto/asn1/a_verify.c +@@ -94,7 +94,7 @@ int ASN1_item_verify(const ASN1_ITEM *it, X509_ALGOR *a, + int mdnid, pknid; + size_t inll = 0; + +- if (!pkey) { ++ if (pkey == NULL) { + ASN1err(ASN1_F_ASN1_ITEM_VERIFY, ERR_R_PASSED_NULL_PARAMETER); + return -1; + } +@@ -150,7 +150,6 @@ int ASN1_item_verify(const ASN1_ITEM *it, X509_ALGOR *a, + ret = 0; + goto err; + } +- + } + + inl = ASN1_item_i2d(asn, &buf_in, it); +diff --git a/crypto/ec/ec_pmeth.c b/crypto/ec/ec_pmeth.c +index 77876a0..591f27a 100644 +--- a/crypto/ec/ec_pmeth.c ++++ b/crypto/ec/ec_pmeth.c +@@ -327,7 +327,8 @@ static int pkey_ec_ctrl(EVP_PKEY_CTX *ctx, int type, int p1, void *p2) + EVP_MD_type((const EVP_MD *)p2) != NID_sha3_224 && + EVP_MD_type((const EVP_MD *)p2) != NID_sha3_256 && + EVP_MD_type((const EVP_MD *)p2) != NID_sha3_384 && +- EVP_MD_type((const EVP_MD *)p2) != NID_sha3_512) { ++ EVP_MD_type((const EVP_MD *)p2) != NID_sha3_512 && ++ EVP_MD_type((const EVP_MD *)p2) != NID_sm3) { + ECerr(EC_F_PKEY_EC_CTRL, EC_R_INVALID_DIGEST_TYPE); + return 0; + } +diff --git a/crypto/err/openssl.txt b/crypto/err/openssl.txt +index 902e97b..b93cace 100644 +--- a/crypto/err/openssl.txt ++++ b/crypto/err/openssl.txt +@@ -1711,6 +1711,7 @@ X509_F_BUILD_CHAIN:106:build_chain + X509_F_BY_FILE_CTRL:101:by_file_ctrl + X509_F_CHECK_NAME_CONSTRAINTS:149:check_name_constraints + X509_F_CHECK_POLICY:145:check_policy ++X509_F_COMMON_VERIFY_SM2:165:common_verify_sm2 + X509_F_DANE_I2D:107:dane_i2d + X509_F_DIR_CTRL:102:dir_ctrl + X509_F_GET_CERT_BY_SUBJECT:103:get_cert_by_subject +@@ -1755,6 +1756,8 @@ X509_F_X509_REQ_CHECK_PRIVATE_KEY:144:X509_REQ_check_private_key + X509_F_X509_REQ_PRINT_EX:121:X509_REQ_print_ex + X509_F_X509_REQ_PRINT_FP:122:X509_REQ_print_fp + X509_F_X509_REQ_TO_X509:123:X509_REQ_to_X509 ++X509_F_X509_REQ_VERIFY:163:X509_REQ_verify ++X509_F_X509_REQ_VERIFY_SM2:164:x509_req_verify_sm2 + X509_F_X509_STORE_ADD_CERT:124:X509_STORE_add_cert + X509_F_X509_STORE_ADD_CRL:125:X509_STORE_add_crl + X509_F_X509_STORE_ADD_LOOKUP:157:X509_STORE_add_lookup +@@ -1766,8 +1769,10 @@ X509_F_X509_STORE_NEW:158:X509_STORE_new + X509_F_X509_TO_X509_REQ:126:X509_to_X509_REQ + X509_F_X509_TRUST_ADD:133:X509_TRUST_add + X509_F_X509_TRUST_SET:141:X509_TRUST_set ++X509_F_X509_VERIFY:161:X509_verify + X509_F_X509_VERIFY_CERT:127:X509_verify_cert + X509_F_X509_VERIFY_PARAM_NEW:159:X509_VERIFY_PARAM_new ++X509_F_X509_VERIFY_SM2:162:x509_verify_sm2 + + #Reason codes + ASN1_R_ADDING_OBJECT:171:adding object +diff --git a/crypto/objects/obj_dat.h b/crypto/objects/obj_dat.h +index 24b49a2..eb4cce4 100644 +--- a/crypto/objects/obj_dat.h ++++ b/crypto/objects/obj_dat.h +@@ -2,7 +2,7 @@ + * WARNING: do not edit! + * Generated by crypto/objects/obj_dat.pl + * +- * Copyright 1995-2021 The OpenSSL Project Authors. All Rights Reserved. ++ * Copyright 1995-2022 The OpenSSL Project Authors. All Rights Reserved. + * Licensed under the OpenSSL license (the "License"). You may not use + * this file except in compliance with the License. You can obtain a copy + * in the file LICENSE in the source distribution or at +@@ -10,7 +10,7 @@ + */ + + /* Serialized OID's */ +-static const unsigned char so[7762] = { ++static const unsigned char so[7770] = { + 0x2A,0x86,0x48,0x86,0xF7,0x0D, /* [ 0] OBJ_rsadsi */ + 0x2A,0x86,0x48,0x86,0xF7,0x0D,0x01, /* [ 6] OBJ_pkcs */ + 0x2A,0x86,0x48,0x86,0xF7,0x0D,0x02,0x02, /* [ 13] OBJ_md2 */ +@@ -1076,9 +1076,10 @@ static const unsigned char so[7762] = { + 0x2A,0x85,0x03,0x07,0x01,0x02,0x01,0x01,0x04, /* [ 7736] OBJ_id_tc26_gost_3410_2012_256_paramSetD */ + 0x2A,0x86,0x48,0x86,0xF7,0x0D,0x02,0x0C, /* [ 7745] OBJ_hmacWithSHA512_224 */ + 0x2A,0x86,0x48,0x86,0xF7,0x0D,0x02,0x0D, /* [ 7753] OBJ_hmacWithSHA512_256 */ ++ 0x2A,0x81,0x1C,0xCF,0x55,0x01,0x83,0x75, /* [ 7761] OBJ_SM2_with_SM3 */ + }; + +-#define NUM_NID 1195 ++#define NUM_NID 1196 + static const ASN1_OBJECT nid_objs[NUM_NID] = { + {"UNDEF", "undefined", NID_undef}, + {"rsadsi", "RSA Data Security, Inc.", NID_rsadsi, 6, &so[0]}, +@@ -2275,9 +2276,10 @@ static const ASN1_OBJECT nid_objs[NUM_NID] = { + {"magma-mac", "magma-mac", NID_magma_mac}, + {"hmacWithSHA512-224", "hmacWithSHA512-224", NID_hmacWithSHA512_224, 8, &so[7745]}, + {"hmacWithSHA512-256", "hmacWithSHA512-256", NID_hmacWithSHA512_256, 8, &so[7753]}, ++ {"SM2-SM3", "SM2-with-SM3", NID_SM2_with_SM3, 8, &so[7761]}, + }; + +-#define NUM_SN 1186 ++#define NUM_SN 1187 + static const unsigned int sn_objs[NUM_SN] = { + 364, /* "AD_DVCS" */ + 419, /* "AES-128-CBC" */ +@@ -2543,6 +2545,7 @@ static const unsigned int sn_objs[NUM_SN] = { + 1100, /* "SHAKE128" */ + 1101, /* "SHAKE256" */ + 1172, /* "SM2" */ ++ 1195, /* "SM2-SM3" */ + 1143, /* "SM3" */ + 1134, /* "SM4-CBC" */ + 1137, /* "SM4-CFB" */ +@@ -3467,7 +3470,7 @@ static const unsigned int sn_objs[NUM_SN] = { + 1093, /* "x509ExtAdmission" */ + }; + +-#define NUM_LN 1186 ++#define NUM_LN 1187 + static const unsigned int ln_objs[NUM_LN] = { + 363, /* "AD Time Stamping" */ + 405, /* "ANSI X9.62" */ +@@ -3623,6 +3626,7 @@ static const unsigned int ln_objs[NUM_LN] = { + 1119, /* "RSA-SHA3-512" */ + 188, /* "S/MIME" */ + 167, /* "S/MIME Capabilities" */ ++ 1195, /* "SM2-with-SM3" */ + 1006, /* "SNILS" */ + 387, /* "SNMPv2" */ + 1025, /* "SSH Client" */ +@@ -4657,7 +4661,7 @@ static const unsigned int ln_objs[NUM_LN] = { + 125, /* "zlib compression" */ + }; + +-#define NUM_OBJ 1071 ++#define NUM_OBJ 1072 + static const unsigned int obj_objs[NUM_OBJ] = { + 0, /* OBJ_undef 0 */ + 181, /* OBJ_iso 1 */ +@@ -5126,6 +5130,7 @@ static const unsigned int obj_objs[NUM_OBJ] = { + 1139, /* OBJ_sm4_ctr 1 2 156 10197 1 104 7 */ + 1172, /* OBJ_sm2 1 2 156 10197 1 301 */ + 1143, /* OBJ_sm3 1 2 156 10197 1 401 */ ++ 1195, /* OBJ_SM2_with_SM3 1 2 156 10197 1 501 */ + 1144, /* OBJ_sm3WithRSAEncryption 1 2 156 10197 1 504 */ + 776, /* OBJ_seed_ecb 1 2 410 200004 1 3 */ + 777, /* OBJ_seed_cbc 1 2 410 200004 1 4 */ +diff --git a/crypto/objects/obj_mac.num b/crypto/objects/obj_mac.num +index 1b6a9c6..8b797b0 100644 +--- a/crypto/objects/obj_mac.num ++++ b/crypto/objects/obj_mac.num +@@ -1192,3 +1192,4 @@ magma_cfb 1191 + magma_mac 1192 + hmacWithSHA512_224 1193 + hmacWithSHA512_256 1194 ++SM2_with_SM3 1195 +diff --git a/crypto/objects/obj_xref.h b/crypto/objects/obj_xref.h +index 5c3561a..1acfcde 100644 +--- a/crypto/objects/obj_xref.h ++++ b/crypto/objects/obj_xref.h +@@ -2,7 +2,7 @@ + * WARNING: do not edit! + * Generated by objxref.pl + * +- * Copyright 1998-2021 The OpenSSL Project Authors. All Rights Reserved. ++ * Copyright 1998-2022 The OpenSSL Project Authors. All Rights Reserved. + * + * Licensed under the OpenSSL license (the "License"). You may not use + * this file except in compliance with the License. You can obtain a copy +@@ -79,6 +79,7 @@ static const nid_triple sigoid_srt[] = { + {NID_RSA_SHA3_256, NID_sha3_256, NID_rsaEncryption}, + {NID_RSA_SHA3_384, NID_sha3_384, NID_rsaEncryption}, + {NID_RSA_SHA3_512, NID_sha3_512, NID_rsaEncryption}, ++ {NID_SM2_with_SM3, NID_sm3, NID_sm2}, + }; + + static const nid_triple *const sigoid_srt_xref[] = { +@@ -125,4 +126,5 @@ static const nid_triple *const sigoid_srt_xref[] = { + &sigoid_srt[45], + &sigoid_srt[46], + &sigoid_srt[47], ++ &sigoid_srt[48], + }; +diff --git a/crypto/objects/obj_xref.txt b/crypto/objects/obj_xref.txt +index ca3e744..f3dd8ed 100644 +--- a/crypto/objects/obj_xref.txt ++++ b/crypto/objects/obj_xref.txt +@@ -64,3 +64,5 @@ dhSinglePass_cofactorDH_sha224kdf_scheme sha224 dh_cofactor_kdf + dhSinglePass_cofactorDH_sha256kdf_scheme sha256 dh_cofactor_kdf + dhSinglePass_cofactorDH_sha384kdf_scheme sha384 dh_cofactor_kdf + dhSinglePass_cofactorDH_sha512kdf_scheme sha512 dh_cofactor_kdf ++ ++SM2_with_SM3 sm3 sm2 +diff --git a/crypto/objects/objects.txt b/crypto/objects/objects.txt +index c49d4c5..be9da47 100644 +--- a/crypto/objects/objects.txt ++++ b/crypto/objects/objects.txt +@@ -385,6 +385,8 @@ sm-scheme 301 : SM2 : sm2 + sm-scheme 401 : SM3 : sm3 + sm-scheme 504 : RSA-SM3 : sm3WithRSAEncryption + ++sm-scheme 501 : SM2-SM3 : SM2-with-SM3 ++ + # From RFC4231 + rsadsi 2 8 : : hmacWithSHA224 + rsadsi 2 9 : : hmacWithSHA256 +diff --git a/crypto/sm2/sm2_pmeth.c b/crypto/sm2/sm2_pmeth.c +index 0e722b9..9551d70 100644 +--- a/crypto/sm2/sm2_pmeth.c ++++ b/crypto/sm2/sm2_pmeth.c +@@ -232,6 +232,10 @@ static int pkey_sm2_ctrl(EVP_PKEY_CTX *ctx, int type, int p1, void *p2) + static int pkey_sm2_ctrl_str(EVP_PKEY_CTX *ctx, + const char *type, const char *value) + { ++ uint8_t *hex_id; ++ long hex_len = 0; ++ int ret = 0; ++ + if (strcmp(type, "ec_paramgen_curve") == 0) { + int nid = NID_undef; + +@@ -252,6 +256,24 @@ static int pkey_sm2_ctrl_str(EVP_PKEY_CTX *ctx, + else + return -2; + return EVP_PKEY_CTX_set_ec_param_enc(ctx, param_enc); ++ } else if (strcmp(type, "sm2_id") == 0) { ++ return pkey_sm2_ctrl(ctx, EVP_PKEY_CTRL_SET1_ID, ++ (int)strlen(value), (void *)value); ++ } else if (strcmp(type, "sm2_hex_id") == 0) { ++ /* ++ * TODO(3.0): reconsider the name "sm2_hex_id", OR change ++ * OSSL_PARAM_construct_from_text() / OSSL_PARAM_allocate_from_text() ++ * to handle infix "_hex_" ++ */ ++ hex_id = OPENSSL_hexstr2buf((const char *)value, &hex_len); ++ if (hex_id == NULL) { ++ SM2err(SM2_F_PKEY_SM2_CTRL_STR, ERR_R_PASSED_INVALID_ARGUMENT); ++ return 0; ++ } ++ ret = pkey_sm2_ctrl(ctx, EVP_PKEY_CTRL_SET1_ID, (int)hex_len, ++ (void *)hex_id); ++ OPENSSL_free(hex_id); ++ return ret; + } + + return -2; +diff --git a/crypto/x509/x509_err.c b/crypto/x509/x509_err.c +index bdd1e67..f02793b 100644 +--- a/crypto/x509/x509_err.c ++++ b/crypto/x509/x509_err.c +@@ -20,6 +20,7 @@ static const ERR_STRING_DATA X509_str_functs[] = { + {ERR_PACK(ERR_LIB_X509, X509_F_CHECK_NAME_CONSTRAINTS, 0), + "check_name_constraints"}, + {ERR_PACK(ERR_LIB_X509, X509_F_CHECK_POLICY, 0), "check_policy"}, ++ {ERR_PACK(ERR_LIB_X509, X509_F_COMMON_VERIFY_SM2, 0), "common_verify_sm2"}, + {ERR_PACK(ERR_LIB_X509, X509_F_DANE_I2D, 0), "dane_i2d"}, + {ERR_PACK(ERR_LIB_X509, X509_F_DIR_CTRL, 0), "dir_ctrl"}, + {ERR_PACK(ERR_LIB_X509, X509_F_GET_CERT_BY_SUBJECT, 0), +@@ -87,6 +88,9 @@ static const ERR_STRING_DATA X509_str_functs[] = { + {ERR_PACK(ERR_LIB_X509, X509_F_X509_REQ_PRINT_EX, 0), "X509_REQ_print_ex"}, + {ERR_PACK(ERR_LIB_X509, X509_F_X509_REQ_PRINT_FP, 0), "X509_REQ_print_fp"}, + {ERR_PACK(ERR_LIB_X509, X509_F_X509_REQ_TO_X509, 0), "X509_REQ_to_X509"}, ++ {ERR_PACK(ERR_LIB_X509, X509_F_X509_REQ_VERIFY, 0), "X509_REQ_verify"}, ++ {ERR_PACK(ERR_LIB_X509, X509_F_X509_REQ_VERIFY_SM2, 0), ++ "x509_req_verify_sm2"}, + {ERR_PACK(ERR_LIB_X509, X509_F_X509_STORE_ADD_CERT, 0), + "X509_STORE_add_cert"}, + {ERR_PACK(ERR_LIB_X509, X509_F_X509_STORE_ADD_CRL, 0), +@@ -105,9 +109,11 @@ static const ERR_STRING_DATA X509_str_functs[] = { + {ERR_PACK(ERR_LIB_X509, X509_F_X509_TO_X509_REQ, 0), "X509_to_X509_REQ"}, + {ERR_PACK(ERR_LIB_X509, X509_F_X509_TRUST_ADD, 0), "X509_TRUST_add"}, + {ERR_PACK(ERR_LIB_X509, X509_F_X509_TRUST_SET, 0), "X509_TRUST_set"}, ++ {ERR_PACK(ERR_LIB_X509, X509_F_X509_VERIFY, 0), "X509_verify"}, + {ERR_PACK(ERR_LIB_X509, X509_F_X509_VERIFY_CERT, 0), "X509_verify_cert"}, + {ERR_PACK(ERR_LIB_X509, X509_F_X509_VERIFY_PARAM_NEW, 0), + "X509_VERIFY_PARAM_new"}, ++ {ERR_PACK(ERR_LIB_X509, X509_F_X509_VERIFY_SM2, 0), "x509_verify_sm2"}, + {0, NULL} + }; + +diff --git a/crypto/x509/x_all.c b/crypto/x509/x_all.c +index a4e9cda..5c371f5 100644 +--- a/crypto/x509/x_all.c ++++ b/crypto/x509/x_all.c +@@ -19,16 +19,174 @@ + #include + #include + ++#ifndef OPENSSL_NO_SM2 ++ ++# include "crypto/asn1.h" ++# include "crypto/evp.h" ++ ++static int common_verify_sm2(void *data, EVP_PKEY *pkey, ++ int mdnid, int pknid, int req) ++{ ++ X509 *x = NULL; ++ X509_REQ *r = NULL; ++ EVP_MD_CTX *ctx = NULL; ++ unsigned char *buf_in = NULL; ++ int ret = -1, inl = 0; ++ size_t inll = 0; ++ EVP_PKEY_CTX *pctx = NULL; ++ const EVP_MD *type = EVP_get_digestbynid(mdnid); ++ ASN1_BIT_STRING *signature = NULL; ++ ASN1_OCTET_STRING *sm2_id = NULL; ++ ASN1_VALUE *tbv = NULL; ++ ++ if (type == NULL) { ++ X509err(X509_F_COMMON_VERIFY_SM2, ++ ASN1_R_UNKNOWN_MESSAGE_DIGEST_ALGORITHM); ++ goto err; ++ } ++ ++ if (pkey == NULL) { ++ X509err(X509_F_COMMON_VERIFY_SM2, ERR_R_PASSED_NULL_PARAMETER); ++ return -1; ++ } ++ ++ if (req == 1) { ++ r = (X509_REQ *)data; ++ signature = r->signature; ++ sm2_id = r->sm2_id; ++ tbv = (ASN1_VALUE *)&r->req_info; ++ } else { ++ x = (X509 *)data; ++ signature = &x->signature; ++ sm2_id = x->sm2_id; ++ tbv = (ASN1_VALUE *)&x->cert_info; ++ } ++ ++ if (signature->type == V_ASN1_BIT_STRING && signature->flags & 0x7) { ++ X509err(X509_F_COMMON_VERIFY_SM2, ASN1_R_INVALID_BIT_STRING_BITS_LEFT); ++ return -1; ++ } ++ ++ ctx = EVP_MD_CTX_new(); ++ if (ctx == NULL) { ++ X509err(X509_F_COMMON_VERIFY_SM2, ERR_R_MALLOC_FAILURE); ++ goto err; ++ } ++ ++ /* Check public key OID matches public key type */ ++ if (EVP_PKEY_type(pknid) != pkey->ameth->pkey_id) { ++ X509err(X509_F_COMMON_VERIFY_SM2, ASN1_R_WRONG_PUBLIC_KEY_TYPE); ++ goto err; ++ } ++ ++ if (!EVP_PKEY_set_alias_type(pkey, EVP_PKEY_SM2)) { ++ X509err(X509_F_COMMON_VERIFY_SM2, ERR_R_EVP_LIB); ++ ret = 0; ++ goto err; ++ } ++ pctx = EVP_PKEY_CTX_new(pkey, NULL); ++ if (pctx == NULL) { ++ X509err(X509_F_COMMON_VERIFY_SM2, ERR_R_EVP_LIB); ++ ret = 0; ++ goto err; ++ } ++ /* NOTE: we tolerate no actual ID, to provide maximum flexibility */ ++ if (sm2_id != NULL ++ && EVP_PKEY_CTX_set1_id(pctx, sm2_id->data, sm2_id->length) != 1) { ++ X509err(X509_F_COMMON_VERIFY_SM2, ERR_R_EVP_LIB); ++ ret = 0; ++ goto err; ++ } ++ EVP_MD_CTX_set_pkey_ctx(ctx, pctx); ++ ++ if (!EVP_DigestVerifyInit(ctx, NULL, type, NULL, pkey)) { ++ X509err(X509_F_COMMON_VERIFY_SM2, ERR_R_EVP_LIB); ++ ret = 0; ++ goto err; ++ } ++ ++ inl = ASN1_item_i2d(tbv, &buf_in, ++ req == 1 ? ++ ASN1_ITEM_rptr(X509_REQ_INFO) : ++ ASN1_ITEM_rptr(X509_CINF)); ++ if (inl <= 0) { ++ X509err(X509_F_COMMON_VERIFY_SM2, ERR_R_INTERNAL_ERROR); ++ goto err; ++ } ++ if (buf_in == NULL) { ++ X509err(X509_F_COMMON_VERIFY_SM2, ERR_R_MALLOC_FAILURE); ++ goto err; ++ } ++ inll = inl; ++ ++ ret = EVP_DigestVerify(ctx, signature->data, ++ (size_t)signature->length, buf_in, inl); ++ if (ret <= 0) { ++ X509err(X509_F_COMMON_VERIFY_SM2, ERR_R_EVP_LIB); ++ goto err; ++ } ++ ret = 1; ++ err: ++ OPENSSL_clear_free(buf_in, inll); ++ EVP_MD_CTX_free(ctx); ++ EVP_PKEY_CTX_free(pctx); ++ return ret; ++} ++ ++static int x509_verify_sm2(X509 *x, EVP_PKEY *pkey, int mdnid, int pknid) ++{ ++ return common_verify_sm2(x, pkey, mdnid, pknid, 0); ++} ++ ++static int x509_req_verify_sm2(X509_REQ *x, EVP_PKEY *pkey, ++ int mdnid, int pknid) ++{ ++ return common_verify_sm2(x, pkey, mdnid, pknid, 1); ++} ++ ++#endif ++ + int X509_verify(X509 *a, EVP_PKEY *r) + { ++#ifndef OPENSSL_NO_SM2 ++ int mdnid, pknid; ++#endif ++ + if (X509_ALGOR_cmp(&a->sig_alg, &a->cert_info.signature)) + return 0; ++ ++#ifndef OPENSSL_NO_SM2 ++ /* Convert signature OID into digest and public key OIDs */ ++ if (!OBJ_find_sigid_algs(OBJ_obj2nid(a->sig_alg.algorithm), ++ &mdnid, &pknid)) { ++ X509err(X509_F_X509_VERIFY, ASN1_R_UNKNOWN_SIGNATURE_ALGORITHM); ++ return 0; ++ } ++ ++ if (pknid == NID_sm2) ++ return x509_verify_sm2(a, r, mdnid, pknid); ++#endif ++ + return (ASN1_item_verify(ASN1_ITEM_rptr(X509_CINF), &a->sig_alg, + &a->signature, &a->cert_info, r)); + } + + int X509_REQ_verify(X509_REQ *a, EVP_PKEY *r) + { ++#ifndef OPENSSL_NO_SM2 ++ int mdnid, pknid; ++ ++ /* Convert signature OID into digest and public key OIDs */ ++ if (!OBJ_find_sigid_algs(OBJ_obj2nid(a->sig_alg.algorithm), ++ &mdnid, &pknid)) { ++ X509err(X509_F_X509_REQ_VERIFY, ASN1_R_UNKNOWN_SIGNATURE_ALGORITHM); ++ return 0; ++ } ++ ++ if (pknid == NID_sm2) ++ return x509_req_verify_sm2(a, r, mdnid, pknid); ++#endif ++ + return (ASN1_item_verify(ASN1_ITEM_rptr(X509_REQ_INFO), + &a->sig_alg, a->signature, &a->req_info, r)); + } +diff --git a/crypto/x509/x_req.c b/crypto/x509/x_req.c +index d2b02f6..de4ff2c 100644 +--- a/crypto/x509/x_req.c ++++ b/crypto/x509/x_req.c +@@ -45,6 +45,29 @@ static int rinf_cb(int operation, ASN1_VALUE **pval, const ASN1_ITEM *it, + return 1; + } + ++static int req_cb(int operation, ASN1_VALUE **pval, const ASN1_ITEM *it, ++ void *exarg) ++{ ++#ifndef OPENSSL_NO_SM2 ++ X509_REQ *ret = (X509_REQ *)*pval; ++ ++ switch (operation) { ++ case ASN1_OP_D2I_PRE: ++ ASN1_OCTET_STRING_free(ret->sm2_id); ++ /* fall thru */ ++ case ASN1_OP_NEW_POST: ++ ret->sm2_id = NULL; ++ break; ++ ++ case ASN1_OP_FREE_POST: ++ ASN1_OCTET_STRING_free(ret->sm2_id); ++ break; ++ } ++#endif ++ ++ return 1; ++} ++ + ASN1_SEQUENCE_enc(X509_REQ_INFO, enc, rinf_cb) = { + ASN1_SIMPLE(X509_REQ_INFO, version, ASN1_INTEGER), + ASN1_SIMPLE(X509_REQ_INFO, subject, X509_NAME), +@@ -57,7 +80,7 @@ ASN1_SEQUENCE_enc(X509_REQ_INFO, enc, rinf_cb) = { + + IMPLEMENT_ASN1_FUNCTIONS(X509_REQ_INFO) + +-ASN1_SEQUENCE_ref(X509_REQ, 0) = { ++ASN1_SEQUENCE_ref(X509_REQ, req_cb) = { + ASN1_EMBED(X509_REQ, req_info, X509_REQ_INFO), + ASN1_EMBED(X509_REQ, sig_alg, X509_ALGOR), + ASN1_SIMPLE(X509_REQ, signature, ASN1_BIT_STRING) +@@ -66,3 +89,16 @@ ASN1_SEQUENCE_ref(X509_REQ, 0) = { + IMPLEMENT_ASN1_FUNCTIONS(X509_REQ) + + IMPLEMENT_ASN1_DUP_FUNCTION(X509_REQ) ++ ++#ifndef OPENSSL_NO_SM2 ++void X509_REQ_set0_sm2_id(X509_REQ *x, ASN1_OCTET_STRING *sm2_id) ++{ ++ ASN1_OCTET_STRING_free(x->sm2_id); ++ x->sm2_id = sm2_id; ++} ++ ++ASN1_OCTET_STRING *X509_REQ_get0_sm2_id(X509_REQ *x) ++{ ++ return x->sm2_id; ++} ++#endif +diff --git a/crypto/x509/x_x509.c b/crypto/x509/x_x509.c +index 7aa8b77..8c27265 100644 +--- a/crypto/x509/x_x509.c ++++ b/crypto/x509/x_x509.c +@@ -53,6 +53,9 @@ static int x509_cb(int operation, ASN1_VALUE **pval, const ASN1_ITEM *it, + sk_IPAddressFamily_pop_free(ret->rfc3779_addr, IPAddressFamily_free); + ASIdentifiers_free(ret->rfc3779_asid); + #endif ++#ifndef OPENSSL_NO_SM2 ++ ASN1_OCTET_STRING_free(ret->sm2_id); ++#endif + + /* fall thru */ + +@@ -72,6 +75,9 @@ static int x509_cb(int operation, ASN1_VALUE **pval, const ASN1_ITEM *it, + #ifndef OPENSSL_NO_RFC3779 + ret->rfc3779_addr = NULL; + ret->rfc3779_asid = NULL; ++#endif ++#ifndef OPENSSL_NO_SM2 ++ ret->sm2_id = NULL; + #endif + ret->aux = NULL; + ret->crldp = NULL; +@@ -91,6 +97,9 @@ static int x509_cb(int operation, ASN1_VALUE **pval, const ASN1_ITEM *it, + #ifndef OPENSSL_NO_RFC3779 + sk_IPAddressFamily_pop_free(ret->rfc3779_addr, IPAddressFamily_free); + ASIdentifiers_free(ret->rfc3779_asid); ++#endif ++#ifndef OPENSSL_NO_SM2 ++ ASN1_OCTET_STRING_free(ret->sm2_id); + #endif + break; + +@@ -245,3 +254,16 @@ int X509_get_signature_nid(const X509 *x) + { + return OBJ_obj2nid(x->sig_alg.algorithm); + } ++ ++#ifndef OPENSSL_NO_SM2 ++void X509_set0_sm2_id(X509 *x, ASN1_OCTET_STRING *sm2_id) ++{ ++ ASN1_OCTET_STRING_free(x->sm2_id); ++ x->sm2_id = sm2_id; ++} ++ ++ASN1_OCTET_STRING *X509_get0_sm2_id(X509 *x) ++{ ++ return x->sm2_id; ++} ++#endif +diff --git a/doc/man1/ca.pod b/doc/man1/ca.pod +index 4380d86..1a6c53e 100644 +--- a/doc/man1/ca.pod ++++ b/doc/man1/ca.pod +@@ -57,6 +57,8 @@ B B + [B<-multivalue-rdn>] + [B<-rand file...>] + [B<-writerand file>] ++[B<-sm2-id string>] ++[B<-sm2-hex-id hex-string>] + + =head1 DESCRIPTION + +@@ -303,6 +305,16 @@ all others. + Writes random data to the specified I upon exit. + This can be used with a subsequent B<-rand> flag. + ++=item B<-sm2-id> ++ ++Specify the ID string to use when verifying an SM2 certificate. The ID string is ++required by the SM2 signature algorithm for signing and verification. ++ ++=item B<-sm2-hex-id> ++ ++Specify a binary ID string to use when signing or verifying using an SM2 ++certificate. The argument for this option is string of hexadecimal digits. ++ + =back + + =head1 CRL OPTIONS +@@ -600,6 +612,10 @@ Sign a certificate request: + + openssl ca -in req.pem -out newcert.pem + ++Sign an SM2 certificate request: ++ ++ openssl ca -in sm2.csr -out sm2.crt -md sm3 -sigopt "sm2_id:1234567812345678" -sm2-id "1234567812345678" ++ + Sign a certificate request, using CA extensions: + + openssl ca -in req.pem -extensions v3_ca -out newcert.pem +diff --git a/doc/man1/pkeyutl.pod b/doc/man1/pkeyutl.pod +index f6fd48d..1a742ab 100644 +--- a/doc/man1/pkeyutl.pod ++++ b/doc/man1/pkeyutl.pod +@@ -10,6 +10,8 @@ pkeyutl - public key algorithm utility + B B + [B<-help>] + [B<-in file>] ++[B<-rawin>] ++[B<-digest algorithm>] + [B<-out file>] + [B<-sigfile file>] + [B<-inkey file>] +@@ -54,6 +56,23 @@ Print out a usage message. + This specifies the input filename to read data from or standard input + if this option is not specified. + ++=item B<-rawin> ++ ++This indicates that the input data is raw data, which is not hashed by any ++message digest algorithm. The user can specify a digest algorithm by using ++the B<-digest> option. This option can only be used with B<-sign> and ++B<-verify>. ++ ++=item B<-digest algorithm> ++ ++This specifies the digest algorithm which is used to hash the input data before ++signing or verifying it with the input key. This option could be omitted if the ++signature algorithm does not require one (for instance, EdDSA). If this option ++is omitted but the signature algorithm requires one, a default value will be ++used. For signature algorithms like RSA, DSA and ECDSA, SHA-256 will be the ++default digest algorithm. For SM2, it will be SM3. If this option is present, ++then the B<-rawin> option must be also specified to B. ++ + =item B<-out filename> + + Specifies the output filename to write to or standard output by +@@ -296,6 +315,29 @@ the B<-pkeyopt> B option. + The X25519 and X448 algorithms support key derivation only. Currently there are + no additional options. + ++=head1 SM2 ++ ++The SM2 algorithm supports sign, verify, encrypt and decrypt operations. For ++the sign and verify operations, SM2 requires an ID string to be passed in. The ++following B value is supported: ++ ++=over 4 ++ ++=item B ++ ++This sets the ID string used in SM2 sign or verify operations. While verifying ++an SM2 signature, the ID string must be the same one used when signing the data. ++Otherwise the verification will fail. ++ ++=item B ++ ++This sets the ID string used in SM2 sign or verify operations. While verifying ++an SM2 signature, the ID string must be the same one used when signing the data. ++Otherwise the verification will fail. The ID string provided with this option ++should be a valid hexadecimal value. ++ ++=back ++ + =head1 EXAMPLES + + Sign some data using a private key: +@@ -329,6 +371,16 @@ Decrypt some data using a private key with OAEP padding using SHA256: + openssl pkeyutl -decrypt -in file -inkey key.pem -out secret \ + -pkeyopt rsa_padding_mode:oaep -pkeyopt rsa_oaep_md:sha256 + ++Sign some data using an L private key and a specific ID: ++ ++ openssl pkeyutl -sign -in file -inkey sm2.key -out sig -rawin -digest sm3 \ ++ -pkeyopt sm2_id:someid ++ ++Verify some data using an L certificate and a specific ID: ++ ++ openssl pkeyutl -verify -certin -in file -inkey sm2.cert -sigfile sig \ ++ -rawin -digest sm3 -pkeyopt sm2_id:someid ++ + =head1 SEE ALSO + + L, L, L +diff --git a/doc/man1/req.pod b/doc/man1/req.pod +index 539b843..e117ec6 100644 +--- a/doc/man1/req.pod ++++ b/doc/man1/req.pod +@@ -50,6 +50,8 @@ B B + [B<-batch>] + [B<-verbose>] + [B<-engine id>] ++[B<-sm2-id string>] ++[B<-sm2-hex-id hex-string>] + + =head1 DESCRIPTION + +@@ -339,6 +341,16 @@ for all available algorithms. + Specifies an engine (by its unique B string) which would be used + for key generation operations. + ++=item B<-sm2-id> ++ ++Specify the ID string to use when verifying an SM2 certificate request. The ID ++string is required by the SM2 signature algorithm for signing and verification. ++ ++=item B<-sm2-hex-id> ++ ++Specify a binary ID string to use when verifying an SM2 certificate request. The ++argument for this option is string of hexadecimal digits. ++ + =back + + =head1 CONFIGURATION FILE FORMAT +@@ -534,6 +546,15 @@ Generate a self signed root certificate: + + openssl req -x509 -newkey rsa:2048 -keyout key.pem -out req.pem + ++Create an SM2 private key and then generate a certificate request from it: ++ ++ openssl ecparam -genkey -name SM2 -out sm2.key ++ openssl req -new -key sm2.key -out sm2.csr -sm3 -sigopt "sm2_id:1234567812345678" ++ ++Examine and verify an SM2 certificate request: ++ ++ openssl req -verify -in sm2.csr -sm3 -sm2-id 1234567812345678 ++ + Example of a file pointed to by the B option: + + 1.2.3.4 shortName A longer Name +diff --git a/doc/man1/verify.pod b/doc/man1/verify.pod +index da2b702..a6b6b2b 100644 +--- a/doc/man1/verify.pod ++++ b/doc/man1/verify.pod +@@ -50,6 +50,8 @@ B B + [B<-verify_name name>] + [B<-x509_strict>] + [B<-show_chain>] ++[B<-sm2-id string>] ++[B<-sm2-hex-id hex-string>] + [B<->] + [certificates] + +@@ -319,6 +321,16 @@ Display information about the certificate chain that has been built (if + successful). Certificates in the chain that came from the untrusted list will be + flagged as "untrusted". + ++=item B<-sm2-id> ++ ++Specify the ID string to use when verifying an SM2 certificate. The ID string is ++required by the SM2 signature algorithm for signing and verification. ++ ++=item B<-sm2-hex-id> ++ ++Specify a binary ID string to use when signing or verifying using an SM2 ++certificate. The argument for this option is string of hexadecimal digits. ++ + =item B<-> + + Indicates the last option. All arguments following this are assumed to be +@@ -774,6 +786,8 @@ The B<-show_chain> option was added in OpenSSL 1.1.0. + The B<-issuer_checks> option is deprecated as of OpenSSL 1.1.0 and + is silently ignored. + ++The B<-sm2-id> and B<-sm2-hex-id> options were added in OpenSSL 3.0.0. ++ + =head1 COPYRIGHT + + Copyright 2000-2020 The OpenSSL Project Authors. All Rights Reserved. +diff --git a/doc/man3/X509_get0_sm2_id.pod b/doc/man3/X509_get0_sm2_id.pod +new file mode 100644 +index 0000000..d8a85d7 +--- /dev/null ++++ b/doc/man3/X509_get0_sm2_id.pod +@@ -0,0 +1,55 @@ ++=pod ++ ++=head1 NAME ++ ++X509_get0_sm2_id, X509_set0_sm2_id, ++X509_REQ_get0_sm2_id, X509_REQ_set0_sm2_id ++- get or set SM2 ID for certificate operations ++ ++=head1 SYNOPSIS ++ ++ #include ++ ++ ASN1_OCTET_STRING *X509_get0_sm2_id(X509 *x); ++ void X509_set0_sm2_id(X509 *x, ASN1_OCTET_STRING *sm2_id); ++ ASN1_OCTET_STRING *X509_REQ_get0_sm2_id(X509_REQ *x); ++ void X509_REQ_set0_sm2_id(X509_REQ *x, ASN1_OCTET_STRING *sm2_id); ++ ++=head1 DESCRIPTION ++ ++X509_get0_sm2_id() gets the ID value of an SM2 certificate B by returning an ++B object which should not be freed by the caller. ++ ++X509_set0_sm2_id() sets the B value to an SM2 certificate B. Calling ++this function transfers the memory management of the value to the X509 object, ++and therefore the value that has been passed in should not be freed by the ++caller after this function has been called. ++ ++X509_REQ_get0_sm2_id() and X509_REQ_set0_sm2_id() have the same functionality ++as X509_get0_sm2_id() and X509_set0_sm2_id() except that they deal with ++B objects instead of B. ++ ++=head1 NOTES ++ ++SM2 signature algorithm requires an ID value when generating and verifying a ++signature. The functions described in this manual provide the user with the ++ability to set and retrieve the SM2 ID value. ++ ++=head1 RETURN VALUES ++ ++X509_set0_sm2_id() and X509_REQ_set0_sm2_id() do not return a value. ++ ++=head1 SEE ALSO ++ ++L, L ++ ++=head1 COPYRIGHT ++ ++Copyright 2019 The OpenSSL Project Authors. All Rights Reserved. ++ ++Licensed under the Apache License 2.0 (the "License"). You may not use ++this file except in compliance with the License. You can obtain a copy ++in the file LICENSE in the source distribution or at ++L. ++ ++=cut +diff --git a/fuzz/oids.txt b/fuzz/oids.txt +index eda55e4..8dfdea9 100644 +--- a/fuzz/oids.txt ++++ b/fuzz/oids.txt +@@ -1063,3 +1063,4 @@ OBJ_id_tc26_gost_3410_2012_256_paramSetC="\x2A\x85\x03\x07\x01\x02\x01\x01\x03" + OBJ_id_tc26_gost_3410_2012_256_paramSetD="\x2A\x85\x03\x07\x01\x02\x01\x01\x04" + OBJ_hmacWithSHA512_224="\x2A\x86\x48\x86\xF7\x0D\x02\x0C" + OBJ_hmacWithSHA512_256="\x2A\x86\x48\x86\xF7\x0D\x02\x0D" ++OBJ_SM2_with_SM3="\x2A\x81\x1C\xCF\x55\x01\x83\x75" +diff --git a/include/crypto/x509.h b/include/crypto/x509.h +index 243ea74..a6e812a 100644 +--- a/include/crypto/x509.h ++++ b/include/crypto/x509.h +@@ -73,6 +73,9 @@ struct X509_req_st { + ASN1_BIT_STRING *signature; /* signature */ + CRYPTO_REF_COUNT references; + CRYPTO_RWLOCK *lock; ++# ifndef OPENSSL_NO_SM2 ++ ASN1_OCTET_STRING *sm2_id; ++# endif + }; + + struct X509_crl_info_st { +@@ -177,7 +180,7 @@ struct x509_st { + STACK_OF(DIST_POINT) *crldp; + STACK_OF(GENERAL_NAME) *altname; + NAME_CONSTRAINTS *nc; +-#ifndef OPENSSL_NO_RFC3779 ++# ifndef OPENSSL_NO_RFC3779 + STACK_OF(IPAddressFamily) *rfc3779_addr; + struct ASIdentifiers_st *rfc3779_asid; + # endif +@@ -185,6 +188,9 @@ struct x509_st { + X509_CERT_AUX *aux; + CRYPTO_RWLOCK *lock; + volatile int ex_cached; ++# ifndef OPENSSL_NO_SM2 ++ ASN1_OCTET_STRING *sm2_id; ++# endif + } /* X509 */ ; + + /* +diff --git a/include/openssl/ec.h b/include/openssl/ec.h +index 24baf53..e8c8869 100644 +--- a/include/openssl/ec.h ++++ b/include/openssl/ec.h +@@ -1444,7 +1444,6 @@ void EC_KEY_METHOD_get_verify(const EC_KEY_METHOD *meth, + # define EVP_PKEY_CTX_set1_id(ctx, id, id_len) \ + EVP_PKEY_CTX_ctrl(ctx, -1, -1, \ + EVP_PKEY_CTRL_SET1_ID, (int)id_len, (void*)(id)) +- + # define EVP_PKEY_CTX_get1_id(ctx, id) \ + EVP_PKEY_CTX_ctrl(ctx, -1, -1, \ + EVP_PKEY_CTRL_GET1_ID, 0, (void*)(id)) +diff --git a/include/openssl/obj_mac.h b/include/openssl/obj_mac.h +index eb812ed..9b125c1 100644 +--- a/include/openssl/obj_mac.h ++++ b/include/openssl/obj_mac.h +@@ -2,7 +2,7 @@ + * WARNING: do not edit! + * Generated by crypto/objects/objects.pl + * +- * Copyright 2000-2021 The OpenSSL Project Authors. All Rights Reserved. ++ * Copyright 2000-2022 The OpenSSL Project Authors. All Rights Reserved. + * Licensed under the OpenSSL license (the "License"). You may not use + * this file except in compliance with the License. You can obtain a copy + * in the file LICENSE in the source distribution or at +@@ -1179,6 +1179,11 @@ + #define NID_sm3WithRSAEncryption 1144 + #define OBJ_sm3WithRSAEncryption OBJ_sm_scheme,504L + ++#define SN_SM2_with_SM3 "SM2-SM3" ++#define LN_SM2_with_SM3 "SM2-with-SM3" ++#define NID_SM2_with_SM3 1195 ++#define OBJ_SM2_with_SM3 OBJ_sm_scheme,501L ++ + #define LN_hmacWithSHA224 "hmacWithSHA224" + #define NID_hmacWithSHA224 798 + #define OBJ_hmacWithSHA224 OBJ_rsadsi,2L,8L +diff --git a/include/openssl/x509.h b/include/openssl/x509.h +index 3ff86ec..42e9eee 100644 +--- a/include/openssl/x509.h ++++ b/include/openssl/x509.h +@@ -573,6 +573,13 @@ void X509_get0_signature(const ASN1_BIT_STRING **psig, + const X509_ALGOR **palg, const X509 *x); + int X509_get_signature_nid(const X509 *x); + ++# ifndef OPENSSL_NO_SM2 ++void X509_set0_sm2_id(X509 *x, ASN1_OCTET_STRING *sm2_id); ++ASN1_OCTET_STRING *X509_get0_sm2_id(X509 *x); ++void X509_REQ_set0_sm2_id(X509_REQ *x, ASN1_OCTET_STRING *sm2_id); ++ASN1_OCTET_STRING *X509_REQ_get0_sm2_id(X509_REQ *x); ++# endif ++ + int X509_trusted(const X509 *x); + int X509_alias_set1(X509 *x, const unsigned char *name, int len); + int X509_keyid_set1(X509 *x, const unsigned char *id, int len); +diff --git a/include/openssl/x509err.h b/include/openssl/x509err.h +index cd08673..0a84ef0 100644 +--- a/include/openssl/x509err.h ++++ b/include/openssl/x509err.h +@@ -26,6 +26,7 @@ int ERR_load_X509_strings(void); + # define X509_F_BY_FILE_CTRL 101 + # define X509_F_CHECK_NAME_CONSTRAINTS 149 + # define X509_F_CHECK_POLICY 145 ++# define X509_F_COMMON_VERIFY_SM2 165 + # define X509_F_DANE_I2D 107 + # define X509_F_DIR_CTRL 102 + # define X509_F_GET_CERT_BY_SUBJECT 103 +@@ -70,6 +71,8 @@ int ERR_load_X509_strings(void); + # define X509_F_X509_REQ_PRINT_EX 121 + # define X509_F_X509_REQ_PRINT_FP 122 + # define X509_F_X509_REQ_TO_X509 123 ++# define X509_F_X509_REQ_VERIFY 163 ++# define X509_F_X509_REQ_VERIFY_SM2 164 + # define X509_F_X509_STORE_ADD_CERT 124 + # define X509_F_X509_STORE_ADD_CRL 125 + # define X509_F_X509_STORE_ADD_LOOKUP 157 +@@ -81,8 +84,10 @@ int ERR_load_X509_strings(void); + # define X509_F_X509_TO_X509_REQ 126 + # define X509_F_X509_TRUST_ADD 133 + # define X509_F_X509_TRUST_SET 141 ++# define X509_F_X509_VERIFY 161 + # define X509_F_X509_VERIFY_CERT 127 + # define X509_F_X509_VERIFY_PARAM_NEW 159 ++# define X509_F_X509_VERIFY_SM2 162 + + /* + * X509 reason codes. +diff --git a/test/certs/sm2-ca-cert.pem b/test/certs/sm2-ca-cert.pem +new file mode 100644 +index 0000000..5677ac6 +--- /dev/null ++++ b/test/certs/sm2-ca-cert.pem +@@ -0,0 +1,14 @@ ++-----BEGIN CERTIFICATE----- ++MIICJDCCAcqgAwIBAgIJAOlkpDpSrmVbMAoGCCqBHM9VAYN1MGgxCzAJBgNVBAYT ++AkNOMQswCQYDVQQIDAJMTjERMA8GA1UEBwwIU2hlbnlhbmcxETAPBgNVBAoMCFRl ++c3QgT3JnMRAwDgYDVQQLDAdUZXN0IE9VMRQwEgYDVQQDDAtUZXN0IFNNMiBDQTAe ++Fw0xOTAyMTkwNzA1NDhaFw0yMzAzMzAwNzA1NDhaMGgxCzAJBgNVBAYTAkNOMQsw ++CQYDVQQIDAJMTjERMA8GA1UEBwwIU2hlbnlhbmcxETAPBgNVBAoMCFRlc3QgT3Jn ++MRAwDgYDVQQLDAdUZXN0IE9VMRQwEgYDVQQDDAtUZXN0IFNNMiBDQTBZMBMGByqG ++SM49AgEGCCqBHM9VAYItA0IABHRYnqErofBdXPptvvO7+BSVJxcpHuTGnZ+UPrbU ++5kVEUMaUnNOeMJZl/vRGimZCm/AkReJmRfnb15ESHR+ssp6jXTBbMB0GA1UdDgQW ++BBTFjcWu/zJgSZ5SKUlU5Vx4/0W5dDAfBgNVHSMEGDAWgBTFjcWu/zJgSZ5SKUlU ++5Vx4/0W5dDAMBgNVHRMEBTADAQH/MAsGA1UdDwQEAwIBBjAKBggqgRzPVQGDdQNI ++ADBFAiEAs6byi1nSQtFELOw/2tQIv5AEsZFR5MJ/oB2ztXzs2LYCIEfIw4xlUH6X ++YFhs4RnIa0K9Ng1ebsGPrifYkudwBIk3 ++-----END CERTIFICATE----- +diff --git a/test/certs/sm2-csr.pem b/test/certs/sm2-csr.pem +new file mode 100644 +index 0000000..a6dcca8 +--- /dev/null ++++ b/test/certs/sm2-csr.pem +@@ -0,0 +1,9 @@ ++-----BEGIN CERTIFICATE REQUEST----- ++MIIBMTCB1wIBADB1MQswCQYDVQQGEwJDTjERMA8GA1UECAwITGlhb25pbmcxETAP ++BgNVBAcMCFNoZW55YW5nMQwwCgYDVQQKDANUZXQxDDAKBgNVBAsMA1RldDELMAkG ++A1UEAwwCb28xFzAVBgkqhkiG9w0BCQEWCG9vQG9vLm9vMFkwEwYHKoZIzj0CAQYI ++KoEcz1UBgi0DQgAE1NjdOpldcjTkuZpdGDNyHAnhK9cB2RZ7jAmFzt7jgEs9OHSg ++rb3crjz+qGZfqyJ5AyZulQ7gdARzb1H55jvw5qAAMAoGCCqBHM9VAYN1A0kAMEYC ++IQCacUXA8kyTTDwEm89Yz9qjsbfd8/N32lnzKxuKCcXJwQIhAIpugCbfeWuPxUQO ++7AvQS3yxBp1yn0FbTT2XVSyYy6To ++-----END CERTIFICATE REQUEST----- +diff --git a/test/certs/sm2-root.crt b/test/certs/sm2-root.crt +new file mode 100644 +index 0000000..5677ac6 +--- /dev/null ++++ b/test/certs/sm2-root.crt +@@ -0,0 +1,14 @@ ++-----BEGIN CERTIFICATE----- ++MIICJDCCAcqgAwIBAgIJAOlkpDpSrmVbMAoGCCqBHM9VAYN1MGgxCzAJBgNVBAYT ++AkNOMQswCQYDVQQIDAJMTjERMA8GA1UEBwwIU2hlbnlhbmcxETAPBgNVBAoMCFRl ++c3QgT3JnMRAwDgYDVQQLDAdUZXN0IE9VMRQwEgYDVQQDDAtUZXN0IFNNMiBDQTAe ++Fw0xOTAyMTkwNzA1NDhaFw0yMzAzMzAwNzA1NDhaMGgxCzAJBgNVBAYTAkNOMQsw ++CQYDVQQIDAJMTjERMA8GA1UEBwwIU2hlbnlhbmcxETAPBgNVBAoMCFRlc3QgT3Jn ++MRAwDgYDVQQLDAdUZXN0IE9VMRQwEgYDVQQDDAtUZXN0IFNNMiBDQTBZMBMGByqG ++SM49AgEGCCqBHM9VAYItA0IABHRYnqErofBdXPptvvO7+BSVJxcpHuTGnZ+UPrbU ++5kVEUMaUnNOeMJZl/vRGimZCm/AkReJmRfnb15ESHR+ssp6jXTBbMB0GA1UdDgQW ++BBTFjcWu/zJgSZ5SKUlU5Vx4/0W5dDAfBgNVHSMEGDAWgBTFjcWu/zJgSZ5SKUlU ++5Vx4/0W5dDAMBgNVHRMEBTADAQH/MAsGA1UdDwQEAwIBBjAKBggqgRzPVQGDdQNI ++ADBFAiEAs6byi1nSQtFELOw/2tQIv5AEsZFR5MJ/oB2ztXzs2LYCIEfIw4xlUH6X ++YFhs4RnIa0K9Ng1ebsGPrifYkudwBIk3 ++-----END CERTIFICATE----- +diff --git a/test/certs/sm2-root.key b/test/certs/sm2-root.key +new file mode 100644 +index 0000000..4bda65b +--- /dev/null ++++ b/test/certs/sm2-root.key +@@ -0,0 +1,5 @@ ++-----BEGIN PRIVATE KEY----- ++MIGHAgEAMBMGByqGSM49AgEGCCqBHM9VAYItBG0wawIBAQQglktdVbLA5tyXMc+9 ++KV4ikyDaFZNnXqfNAzUVqTlqn8GhRANCAAR0WJ6hK6HwXVz6bb7zu/gUlScXKR7k ++xp2flD621OZFRFDGlJzTnjCWZf70RopmQpvwJEXiZkX529eREh0frLKe ++-----END PRIVATE KEY----- +diff --git a/test/certs/sm2.key b/test/certs/sm2.key +new file mode 100644 +index 0000000..1efd364 +--- /dev/null ++++ b/test/certs/sm2.key +@@ -0,0 +1,5 @@ ++-----BEGIN PRIVATE KEY----- ++MIGHAgEAMBMGByqGSM49AgEGCCqBHM9VAYItBG0wawIBAQQgSKhk+4xGyDI+IS2H ++WVfFPDxh1qv5+wtrddaIsGNXGZihRANCAAQwqeNkWp7fiu1KZnuDkAucpM8piEzE ++TL1ymrcrOBvv8mhNNkeb20asbWgFQI2zOrSM99/sXGn9rM2/usM/Mlca ++-----END PRIVATE KEY----- +diff --git a/test/certs/sm2.pem b/test/certs/sm2.pem +new file mode 100644 +index 0000000..189abb1 +--- /dev/null ++++ b/test/certs/sm2.pem +@@ -0,0 +1,13 @@ ++-----BEGIN CERTIFICATE----- ++MIIB6DCCAY6gAwIBAgIJAKH2BR6ITHZeMAoGCCqBHM9VAYN1MGgxCzAJBgNVBAYT ++AkNOMQswCQYDVQQIDAJMTjERMA8GA1UEBwwIU2hlbnlhbmcxETAPBgNVBAoMCFRl ++c3QgT3JnMRAwDgYDVQQLDAdUZXN0IE9VMRQwEgYDVQQDDAtUZXN0IFNNMiBDQTAe ++Fw0xOTAyMTkwNzA1NDhaFw0yMzAzMzAwNzA1NDhaMG8xCzAJBgNVBAYTAkNOMQsw ++CQYDVQQIDAJMTjERMA8GA1UEBwwIU2hlbnlhbmcxETAPBgNVBAoMCFRlc3QgT3Jn ++MRAwDgYDVQQLDAdUZXN0IE9VMRswGQYDVQQDDBJUZXN0IFNNMiBTaWduIENlcnQw ++WTATBgcqhkjOPQIBBggqgRzPVQGCLQNCAAQwqeNkWp7fiu1KZnuDkAucpM8piEzE ++TL1ymrcrOBvv8mhNNkeb20asbWgFQI2zOrSM99/sXGn9rM2/usM/MlcaoxowGDAJ ++BgNVHRMEAjAAMAsGA1UdDwQEAwIGwDAKBggqgRzPVQGDdQNIADBFAiEA9edBnAqT ++TNuGIUIvXsj6/nP+AzXA9HGtAIY4nrqW8LkCIHyZzhRTlxYtgfqkDl0OK5QQRCZH ++OZOfmtx613VyzXwc ++-----END CERTIFICATE----- +diff --git a/test/recipes/20-test_pkeyutl.t b/test/recipes/20-test_pkeyutl.t +new file mode 100644 +index 0000000..a36d41e +--- /dev/null ++++ b/test/recipes/20-test_pkeyutl.t +@@ -0,0 +1,41 @@ ++#! /usr/bin/env perl ++# Copyright 2018 The OpenSSL Project Authors. All Rights Reserved. ++# ++# Licensed under the Apache License 2.0 (the "License"). You may not use ++# this file except in compliance with the License. You can obtain a copy ++# in the file LICENSE in the source distribution or at ++# https://www.openssl.org/source/license.html ++ ++use strict; ++use warnings; ++ ++use File::Spec; ++use OpenSSL::Test qw/:DEFAULT srctop_file/; ++use OpenSSL::Test::Utils; ++ ++setup("test_pkeyutl"); ++ ++plan tests => 2; ++ ++# For the tests below we use the cert itself as the TBS file ++ ++SKIP: { ++ skip "Skipping tests that require EC, SM2 or SM3", 2 ++ if disabled("ec") || disabled("sm2") || disabled("sm3"); ++ ++ # SM2 ++ ok(run(app(([ 'openssl', 'pkeyutl', '-sign', ++ '-in', srctop_file('test', 'certs', 'sm2.pem'), ++ '-inkey', srctop_file('test', 'certs', 'sm2.key'), ++ '-out', 'signature.dat', '-rawin', ++ '-digest', 'sm3', '-pkeyopt', 'sm2_id:someid']))), ++ "Sign a piece of data using SM2"); ++ ok(run(app(([ 'openssl', 'pkeyutl', '-verify', '-certin', ++ '-in', srctop_file('test', 'certs', 'sm2.pem'), ++ '-inkey', srctop_file('test', 'certs', 'sm2.pem'), ++ '-sigfile', 'signature.dat', '-rawin', ++ '-digest', 'sm3', '-pkeyopt', 'sm2_id:someid']))), ++ "Verify an SM2 signature against a piece of data"); ++} ++ ++unlink 'signature.dat'; +diff --git a/test/recipes/25-test_req.t b/test/recipes/25-test_req.t +index 383120c..d53e577 100644 +--- a/test/recipes/25-test_req.t ++++ b/test/recipes/25-test_req.t +@@ -15,7 +15,7 @@ use OpenSSL::Test qw/:DEFAULT srctop_file/; + + setup("test_req"); + +-plan tests => 14; ++plan tests => 15; + + require_ok(srctop_file('test','recipes','tconversion.pl')); + +@@ -181,6 +181,36 @@ subtest "generating certificate requests" => sub { + "Verifying signature on request"); + }; + ++subtest "generating SM2 certificate requests" => sub { ++ plan tests => 4; ++ ++ SKIP: { ++ skip "SM2 is not supported by this OpenSSL build", 4 ++ if disabled("sm2"); ++ ok(run(app(["openssl", "req", "-config", srctop_file("test", "test.cnf"), ++ "-new", "-key", srctop_file("test", "certs", "sm2.key"), ++ "-sigopt", "sm2_id:1234567812345678", ++ "-out", "testreq.pem", "-sm3"])), ++ "Generating SM2 certificate request"); ++ ++ ok(run(app(["openssl", "req", "-config", srctop_file("test", "test.cnf"), ++ "-verify", "-in", "testreq.pem", "-noout", ++ "-sm2-id", "1234567812345678", "-sm3"])), ++ "Verifying signature on SM2 certificate request"); ++ ++ ok(run(app(["openssl", "req", "-config", srctop_file("test", "test.cnf"), ++ "-new", "-key", srctop_file("test", "certs", "sm2.key"), ++ "-sigopt", "sm2_hex_id:DEADBEEF", ++ "-out", "testreq.pem", "-sm3"])), ++ "Generating SM2 certificate request with hex id"); ++ ++ ok(run(app(["openssl", "req", "-config", srctop_file("test", "test.cnf"), ++ "-verify", "-in", "testreq.pem", "-noout", ++ "-sm2-hex-id", "DEADBEEF", "-sm3"])), ++ "Verifying signature on SM2 certificate request"); ++ } ++}; ++ + my @openssl_args = ("req", "-config", srctop_file("apps", "openssl.cnf")); + + run_conversion('req conversions', +diff --git a/test/recipes/25-test_verify.t b/test/recipes/25-test_verify.t +index ffa48ed..d254bd8 100644 +--- a/test/recipes/25-test_verify.t ++++ b/test/recipes/25-test_verify.t +@@ -27,7 +27,7 @@ sub verify { + run(app([@args])); + } + +-plan tests => 146; ++plan tests => 148; + + # Canonical success + ok(verify("ee-cert", "sslserver", ["root-cert"], ["ca-cert"]), +@@ -409,3 +409,15 @@ SKIP: { + "ED25519 signature"); + + } ++ ++SKIP: { ++ skip "SM2 is not supported by this OpenSSL build", 2 ++ if disabled("sm2"); ++ ++ # Test '-sm2-id' and '-sm2-hex-id' option ++ ok(verify("sm2", "any", ["sm2-ca-cert"], [], "-sm2-id", "1234567812345678"), ++ "SM2 ID test"); ++ ok(verify("sm2", "any", ["sm2-ca-cert"], [], "-sm2-hex-id", ++ "31323334353637383132333435363738"), ++ "SM2 hex ID test"); ++} +diff --git a/test/recipes/70-test_verify_extra.t b/test/recipes/70-test_verify_extra.t +index 8c7c957..1571115 100644 +--- a/test/recipes/70-test_verify_extra.t ++++ b/test/recipes/70-test_verify_extra.t +@@ -17,4 +17,5 @@ ok(run(test(["verify_extra_test", + srctop_file("test", "certs", "roots.pem"), + srctop_file("test", "certs", "untrusted.pem"), + srctop_file("test", "certs", "bad.pem"), +- srctop_file("test", "certs", "rootCA.pem")]))); ++ srctop_file("test", "certs", "rootCA.pem"), ++ srctop_file("test", "certs", "sm2-csr.pem")]))); +diff --git a/test/recipes/80-test_ca.t b/test/recipes/80-test_ca.t +index 557777e..92557cf 100644 +--- a/test/recipes/80-test_ca.t ++++ b/test/recipes/80-test_ca.t +@@ -23,7 +23,7 @@ my $std_openssl_cnf = + + rmtree("demoCA", { safe => 0 }); + +-plan tests => 5; ++plan tests => 6; + SKIP: { + $ENV{OPENSSL_CONFIG} = '-config "'.srctop_file("test", "CAss.cnf").'"'; + skip "failed creating CA structure", 4 +@@ -51,9 +51,25 @@ plan tests => 5; + 'creating new pre-certificate'); + } + ++SKIP: { ++ skip "SM2 is not supported by this OpenSSL build", 1 ++ if disabled("sm2"); ++ ++ is(yes(cmdstr(app(["openssl", "ca", "-config", ++ srctop_file("test", "CAss.cnf"), ++ "-in", srctop_file("test", "certs", "sm2-csr.pem"), ++ "-out", "sm2-test.crt", ++ "-sigopt", "sm2_id:1234567812345678", ++ "-sm2-id", "1234567812345678", ++ "-md", "sm3", ++ "-cert", srctop_file("test", "certs", "sm2-root.crt"), ++ "-keyfile", srctop_file("test", "certs", "sm2-root.key")]))), ++ 0, ++ "Signing SM2 certificate request"); ++} + + rmtree("demoCA", { safe => 0 }); +-unlink "newcert.pem", "newreq.pem", "newkey.pem"; ++unlink "newcert.pem", "newreq.pem", "newkey.pem", "sm2-test.crt"; + + + sub yes { +diff --git a/test/verify_extra_test.c b/test/verify_extra_test.c +index b9959e0..d69653c 100644 +--- a/test/verify_extra_test.c ++++ b/test/verify_extra_test.c +@@ -8,6 +8,7 @@ + */ + + #include ++#include + #include + #include + #include +@@ -19,6 +20,7 @@ static const char *roots_f; + static const char *untrusted_f; + static const char *bad_f; + static const char *good_f; ++static const char *req_f; + + static X509 *load_cert_pem(const char *file) + { +@@ -231,12 +233,95 @@ static int test_self_signed_bad(void) + return test_self_signed(bad_f, 0); + } + ++#ifndef OPENSSL_NO_SM2 ++static int test_sm2_id(void) ++{ ++ /* we only need an X509 structure, no matter if it's a real SM2 cert */ ++ X509 *x = NULL; ++ BIO *bio = NULL; ++ int ret = 0; ++ ASN1_OCTET_STRING *v = NULL, *v2 = NULL; ++ char *sm2id = "this is an ID"; ++ ++ bio = BIO_new_file(bad_f, "r"); ++ if (bio == NULL) ++ goto err; ++ ++ x = PEM_read_bio_X509(bio, NULL, 0, NULL); ++ if (x == NULL) ++ goto err; ++ ++ v = ASN1_OCTET_STRING_new(); ++ if (v == NULL) ++ goto err; ++ ++ if (!ASN1_OCTET_STRING_set(v, (unsigned char *)sm2id, (int)strlen(sm2id))) { ++ ASN1_OCTET_STRING_free(v); ++ goto err; ++ } ++ ++ X509_set0_sm2_id(x, v); ++ ++ v2 = X509_get0_sm2_id(x); ++ if (!TEST_ptr(v2) ++ || !TEST_int_eq(ASN1_OCTET_STRING_cmp(v, v2), 0)) ++ goto err; ++ ++ ret = 1; ++ err: ++ X509_free(x); ++ BIO_free(bio); ++ return ret; ++} ++ ++static int test_req_sm2_id(void) ++{ ++ /* we only need an X509_REQ structure, no matter if it's a real SM2 cert */ ++ X509_REQ *x = NULL; ++ BIO *bio = NULL; ++ int ret = 0; ++ ASN1_OCTET_STRING *v = NULL, *v2 = NULL; ++ char *sm2id = "this is an ID"; ++ ++ bio = BIO_new_file(req_f, "r"); ++ if (bio == NULL) ++ goto err; ++ ++ x = PEM_read_bio_X509_REQ(bio, NULL, 0, NULL); ++ if (x == NULL) ++ goto err; ++ ++ v = ASN1_OCTET_STRING_new(); ++ if (v == NULL) ++ goto err; ++ ++ if (!ASN1_OCTET_STRING_set(v, (unsigned char *)sm2id, (int)strlen(sm2id))) { ++ ASN1_OCTET_STRING_free(v); ++ goto err; ++ } ++ ++ X509_REQ_set0_sm2_id(x, v); ++ ++ v2 = X509_REQ_get0_sm2_id(x); ++ if (!TEST_ptr(v2) ++ || !TEST_int_eq(ASN1_OCTET_STRING_cmp(v, v2), 0)) ++ goto err; ++ ++ ret = 1; ++ err: ++ X509_REQ_free(x); ++ BIO_free(bio); ++ return ret; ++} ++#endif ++ + int setup_tests(void) + { + if (!TEST_ptr(roots_f = test_get_argument(0)) + || !TEST_ptr(untrusted_f = test_get_argument(1)) + || !TEST_ptr(bad_f = test_get_argument(2)) +- || !TEST_ptr(good_f = test_get_argument(3))) { ++ || !TEST_ptr(good_f = test_get_argument(3)) ++ || !TEST_ptr(req_f = test_get_argument(4))) { + TEST_error("usage: verify_extra_test roots.pem untrusted.pem bad.pem good.pem\n"); + return 0; + } +@@ -245,5 +330,9 @@ int setup_tests(void) + ADD_TEST(test_store_ctx); + ADD_TEST(test_self_signed_good); + ADD_TEST(test_self_signed_bad); ++#ifndef OPENSSL_NO_SM2 ++ ADD_TEST(test_sm2_id); ++ ADD_TEST(test_req_sm2_id); ++#endif + return 1; + } +diff --git a/util/libcrypto.num b/util/libcrypto.num +index 1566231..81a6388 100644 +--- a/util/libcrypto.num ++++ b/util/libcrypto.num +@@ -4626,3 +4626,7 @@ FIPS_drbg_get_strength 6379 1_1_0g EXIST::FUNCTION: + FIPS_rand_strength 6380 1_1_0g EXIST::FUNCTION: + FIPS_drbg_get_blocklength 6381 1_1_0g EXIST::FUNCTION: + FIPS_drbg_init 6382 1_1_0g EXIST::FUNCTION: ++X509_set0_sm2_id 6383 1_1_1m EXIST::FUNCTION:SM2 ++X509_get0_sm2_id 6384 1_1_1m EXIST::FUNCTION:SM2 ++X509_REQ_get0_sm2_id 6385 1_1_1m EXIST::FUNCTION:SM2 ++X509_REQ_set0_sm2_id 6386 1_1_1m EXIST::FUNCTION:SM2 +-- +2.20.1 (Apple Git-117) + diff --git a/Feature-Support-TLCP-protocol.patch b/Feature-Support-TLCP-protocol.patch new file mode 100644 index 0000000..e8c3255 --- /dev/null +++ b/Feature-Support-TLCP-protocol.patch @@ -0,0 +1,6090 @@ +From ea8c3279747a4bec4b0da58663eeb2c2ce938445 Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?=E6=96=BD=E6=A5=9A=E6=BD=AE?= <463779137@qq.com> +Date: Wed, 8 Jun 2022 19:35:25 +0800 +Subject: [PATCH] Support TLCP protocol + +TLCP_method(), TLCP_server_method(), TLCP_client_method() are the GM version-specific methods for TLCP protocol. +Valid TLCP ciphersuite names are ECDHE-SM4-CBC-SM3 and ECC-SM4-CBC-SM3. Additionally enable-tlcp(argument to Configure) was required. +--- + Configure | 7 +- + apps/s_client.c | 60 +- + crypto/dh/dh_err.c | 8 +- + crypto/dsa/dsa_err.c | 8 +- + crypto/err/openssl.txt | 27 +- + crypto/evp/evp_err.c | 6 +- + crypto/evp/p_lib.c | 18 + + crypto/rsa/rsa_err.c | 23 +- + crypto/sm2/build.info | 2 +- + crypto/sm2/sm2_err.c | 4 +- + crypto/sm2/sm2_kep.c | 254 ++++++++ + crypto/sm2/sm2_pmeth.c | 5 + + doc/man1/s_client.pod | 9 + + doc/man3/EVP_PKEY_set1_RSA.pod | 9 +- + doc/man3/SSL_CTX_new.pod | 19 +- + doc/man3/SSL_CTX_set_options.pod | 4 +- + doc/man3/SSL_CTX_use_certificate.pod | 56 +- + doc/man7/ssl.pod | 40 ++ + include/crypto/sm2.h | 1 + + include/crypto/sm2err.h | 12 +- + include/openssl/dherr.h | 15 +- + include/openssl/dsaerr.h | 18 +- + include/openssl/evp.h | 4 + + include/openssl/evperr.h | 17 +- + include/openssl/rsaerr.h | 32 +- + include/openssl/sm2.h | 20 + + include/openssl/ssl.h | 71 +++ + include/openssl/sslerr.h | 32 +- + include/openssl/tls1.h | 20 + + include/openssl/x509.h | 4 + + include/openssl/x509err.h | 4 +- + ssl/methods.c | 36 ++ + ssl/record/ssl3_record.c | 4 + + ssl/s3_lib.c | 125 ++++ + ssl/ssl_asn1.c | 3 +- + ssl/ssl_cert.c | 18 + + ssl/ssl_cert_table.h | 6 +- + ssl/ssl_ciph.c | 46 +- + ssl/ssl_err.c | 53 +- + ssl/ssl_lib.c | 86 ++- + ssl/ssl_local.h | 68 ++- + ssl/ssl_rsa.c | 541 ++++++++++++++++++ + ssl/ssl_sess.c | 3 + + ssl/ssl_stat.c | 28 + + ssl/statem/extensions.c | 6 +- + ssl/statem/extensions_clnt.c | 3 + + ssl/statem/extensions_srvr.c | 6 +- + ssl/statem/statem.c | 4 + + ssl/statem/statem_clnt.c | 428 ++++++++++++++ + ssl/statem/statem_lib.c | 162 +++++- + ssl/statem/statem_srvr.c | 444 +++++++++++++- + ssl/t1_enc.c | 84 +++ + ssl/t1_lib.c | 71 ++- + ssl/tlcp_lib.c | 119 ++++ + test/build.info | 6 +- + test/certs/embeddedSCTs1-key.pem | 38 +- + test/certs/embeddedSCTs1.pem | 35 +- + test/certs/embeddedSCTs1.sct | 12 +- + test/certs/embeddedSCTs1_issuer-key.pem | 15 + + test/certs/embeddedSCTs1_issuer.pem | 30 +- + test/ciphername_test.c | 3 + + test/ct_test.c | 2 +- + test/recipes/85-test_tlcp.t | 34 ++ + .../85-test_tlcp_data/ecdsa-client-cert.pem | 12 + + .../85-test_tlcp_data/ecdsa-client-key.pem | 5 + + .../85-test_tlcp_data/ecdsa-root-cert.pem | 14 + + .../85-test_tlcp_data/ecdsa-server-cert.pem | 12 + + .../85-test_tlcp_data/ecdsa-server-key.pem | 5 + + .../85-test_tlcp_data/sm2-client-enc-cert.pem | 12 + + .../85-test_tlcp_data/sm2-client-enc-key.pem | 5 + + .../85-test_tlcp_data/sm2-client-sig-cert.pem | 12 + + .../85-test_tlcp_data/sm2-client-sig-key.pem | 5 + + .../85-test_tlcp_data/sm2-root-cert.pem | 14 + + .../85-test_tlcp_data/sm2-server-enc-cert.pem | 12 + + .../85-test_tlcp_data/sm2-server-enc-key.pem | 5 + + .../85-test_tlcp_data/sm2-server-sig-cert.pem | 12 + + .../85-test_tlcp_data/sm2-server-sig-key.pem | 5 + + test/tlcptest.c | 434 ++++++++++++++ + util/libcrypto.num | 2 + + util/libssl.num | 17 + + 80 files changed, 3750 insertions(+), 161 deletions(-) + create mode 100644 crypto/sm2/sm2_kep.c + create mode 100644 include/openssl/sm2.h + create mode 100644 ssl/tlcp_lib.c + create mode 100644 test/certs/embeddedSCTs1_issuer-key.pem + create mode 100644 test/recipes/85-test_tlcp.t + create mode 100644 test/recipes/85-test_tlcp_data/ecdsa-client-cert.pem + create mode 100644 test/recipes/85-test_tlcp_data/ecdsa-client-key.pem + create mode 100644 test/recipes/85-test_tlcp_data/ecdsa-root-cert.pem + create mode 100644 test/recipes/85-test_tlcp_data/ecdsa-server-cert.pem + create mode 100644 test/recipes/85-test_tlcp_data/ecdsa-server-key.pem + create mode 100644 test/recipes/85-test_tlcp_data/sm2-client-enc-cert.pem + create mode 100644 test/recipes/85-test_tlcp_data/sm2-client-enc-key.pem + create mode 100644 test/recipes/85-test_tlcp_data/sm2-client-sig-cert.pem + create mode 100644 test/recipes/85-test_tlcp_data/sm2-client-sig-key.pem + create mode 100644 test/recipes/85-test_tlcp_data/sm2-root-cert.pem + create mode 100644 test/recipes/85-test_tlcp_data/sm2-server-enc-cert.pem + create mode 100644 test/recipes/85-test_tlcp_data/sm2-server-enc-key.pem + create mode 100644 test/recipes/85-test_tlcp_data/sm2-server-sig-cert.pem + create mode 100644 test/recipes/85-test_tlcp_data/sm2-server-sig-key.pem + create mode 100644 test/tlcptest.c + +diff --git a/Configure b/Configure +index 4236e6c..a41c897 100755 +--- a/Configure ++++ b/Configure +@@ -425,6 +425,7 @@ my @disablables = ( + "stdio", + "tests", + "threads", ++ "tlcp", + "tls", + "ts", + "ubsan", +@@ -469,6 +470,7 @@ our %disabled = ( # "what" => "comment" + "ssl-trace" => "default", + "ssl3" => "default", + "ssl3-method" => "default", ++ "tlcp" => "default", + "ubsan" => "default", + "unit-test" => "default", + "weak-ssl-ciphers" => "default", +@@ -512,8 +514,9 @@ my @disable_cascades = ( + "apps" => [ "tests" ], + "tests" => [ "external-tests" ], + "comp" => [ "zlib" ], +- "ec" => [ "tls1_3", "sm2" ], +- "sm3" => [ "sm2" ], ++ "ec" => [ "tls1_3", "sm2", "tlcp" ], ++ "sm3" => [ "sm2", "tlcp" ], ++ "sm2" => [ "tlcp" ], + sub { !$disabled{"unit-test"} } => [ "heartbeats" ], + + sub { !$disabled{"msan"} } => [ "asm" ], +diff --git a/apps/s_client.c b/apps/s_client.c +index 121cd14..a41f98a 100644 +--- a/apps/s_client.c ++++ b/apps/s_client.c +@@ -578,6 +578,7 @@ typedef enum OPTION_choice { + OPT_SRPUSER, OPT_SRPPASS, OPT_SRP_STRENGTH, OPT_SRP_LATEUSER, + OPT_SRP_MOREGROUPS, + #endif ++ OPT_TLCP, OPT_DCERT, OPT_DKEY, OPT_DPASS, + OPT_SSL3, OPT_SSL_CONFIG, + OPT_TLS1_3, OPT_TLS1_2, OPT_TLS1_1, OPT_TLS1, OPT_DTLS, OPT_DTLS1, + OPT_DTLS1_2, OPT_SCTP, OPT_TIMEOUT, OPT_MTU, OPT_KEYFORM, OPT_PASS, +@@ -738,6 +739,12 @@ const OPTIONS s_client_options[] = { + #ifndef OPENSSL_NO_TLS1_3 + {"tls1_3", OPT_TLS1_3, '-', "Just use TLSv1.3"}, + #endif ++#ifndef OPENSSL_NO_TCLP ++ {"tlcp", OPT_TLCP, '-', "Just use TLCP"}, ++ {"dcert", OPT_DCERT, '<', "Encryption certificate file to use (usually for TLCP)"}, ++ {"dkey", OPT_DKEY, '<', "Encryption private key file to use (usually for TLCP)"}, ++ {"dpass", OPT_DPASS, 's', "Encryption private key file pass phrase source"}, ++#endif + #ifndef OPENSSL_NO_DTLS + {"dtls", OPT_DTLS, '-', "Use any version of DTLS"}, + {"timeout", OPT_TIMEOUT, '-', +@@ -836,7 +843,7 @@ static const OPT_PAIR services[] = { + + #define IS_PROT_FLAG(o) \ + (o == OPT_SSL3 || o == OPT_TLS1 || o == OPT_TLS1_1 || o == OPT_TLS1_2 \ +- || o == OPT_TLS1_3 || o == OPT_DTLS || o == OPT_DTLS1 || o == OPT_DTLS1_2) ++ || o == OPT_TLS1_3 || o == OPT_DTLS || o == OPT_DTLS1 || o == OPT_DTLS1_2 || o == OPT_TLCP) + + /* Free |*dest| and optionally set it to a copy of |source|. */ + static void freeandcopy(char **dest, const char *source) +@@ -982,6 +989,10 @@ int s_client_main(int argc, char **argv) + #ifndef OPENSSL_NO_SCTP + int sctp_label_bug = 0; + #endif ++ char *s_dcert_file = NULL, *s_dkey_file = NULL; ++ char *dpassarg = NULL, *dpass = NULL; ++ X509 *s_dcert = NULL; ++ EVP_PKEY *s_dkey = NULL; + + FD_ZERO(&readfds); + FD_ZERO(&writefds); +@@ -1318,6 +1329,14 @@ int s_client_main(int argc, char **argv) + socket_type = SOCK_STREAM; + #ifndef OPENSSL_NO_DTLS + isdtls = 0; ++#endif ++ break; ++ case OPT_TLCP: ++ min_version = TLCP_VERSION; ++ max_version = TLCP_VERSION; ++ socket_type = SOCK_STREAM; ++#ifndef OPENSSL_NO_DTLS ++ isdtls = 0; + #endif + break; + case OPT_DTLS: +@@ -1381,6 +1400,15 @@ int s_client_main(int argc, char **argv) + case OPT_KEY: + key_file = opt_arg(); + break; ++ case OPT_DCERT: ++ s_dcert_file = opt_arg(); ++ break; ++ case OPT_DPASS: ++ dpassarg = opt_arg(); ++ break; ++ case OPT_DKEY: ++ s_dkey_file = opt_arg(); ++ break; + case OPT_RECONNECT: + reconnect = 5; + break; +@@ -1650,7 +1678,7 @@ int s_client_main(int argc, char **argv) + next_proto.data = NULL; + #endif + +- if (!app_passwd(passarg, NULL, &pass, NULL)) { ++ if (!app_passwd(passarg, dpassarg, &pass, &dpass)) { + BIO_printf(bio_err, "Error getting password\n"); + goto end; + } +@@ -1681,6 +1709,26 @@ int s_client_main(int argc, char **argv) + goto end; + } + ++ if (s_dcert_file != NULL) { ++ if (s_dkey_file == NULL) ++ s_dkey_file = s_dcert_file; ++ ++ s_dkey = load_key(s_dkey_file, key_format, 0, dpass, e, ++ "Encrypt certificate private key file"); ++ if (s_dkey == NULL) { ++ ERR_print_errors(bio_err); ++ goto end; ++ } ++ ++ s_dcert = load_cert(s_dcert_file, key_format, ++ "Encrypt server certificate file"); ++ ++ if (s_dcert == NULL) { ++ ERR_print_errors(bio_err); ++ goto end; ++ } ++ } ++ + if (crl_file != NULL) { + X509_CRL *crl; + crl = load_crl(crl_file, crl_format); +@@ -1932,6 +1980,11 @@ int s_client_main(int argc, char **argv) + + if (!set_cert_key_stuff(ctx, cert, key, chain, build_chain)) + goto end; ++ ++ if (s_dcert != NULL) { ++ if (!set_cert_key_stuff(ctx, s_dcert, s_dkey, chain, build_chain)) ++ goto end; ++ } + + if (!noservername) { + tlsextcbp.biodebug = bio_err; +@@ -3146,6 +3199,9 @@ int s_client_main(int argc, char **argv) + EVP_PKEY_free(key); + sk_X509_pop_free(chain, X509_free); + OPENSSL_free(pass); ++ X509_free(s_dcert); ++ EVP_PKEY_free(s_dkey); ++ OPENSSL_free(dpass); + #ifndef OPENSSL_NO_SRP + OPENSSL_free(srp_arg.srppassin); + #endif +diff --git a/crypto/dh/dh_err.c b/crypto/dh/dh_err.c +index 9778138..c7ac6ae 100644 +--- a/crypto/dh/dh_err.c ++++ b/crypto/dh/dh_err.c +@@ -1,6 +1,6 @@ + /* + * Generated by util/mkerr.pl DO NOT EDIT +- * Copyright 1995-2018 The OpenSSL Project Authors. All Rights Reserved. ++ * Copyright 1995-2022 The OpenSSL Project Authors. All Rights Reserved. + * + * Licensed under the OpenSSL license (the "License"). You may not use + * this file except in compliance with the License. You can obtain a copy +@@ -26,8 +26,8 @@ static const ERR_STRING_DATA DH_str_functs[] = { + {ERR_PACK(ERR_LIB_DH, DH_F_DH_CMS_SET_SHARED_INFO, 0), + "dh_cms_set_shared_info"}, + {ERR_PACK(ERR_LIB_DH, DH_F_DH_COMPUTE_KEY, 0), "DH_compute_key"}, +- {ERR_PACK(ERR_LIB_DH, DH_F_DH_GENERATE_KEY, 0), "DH_generate_key"}, +- {ERR_PACK(ERR_LIB_DH, DH_F_DH_GENERATE_PARAMETERS_EX, 0), "DH_generate_parameters_ex"}, ++ {ERR_PACK(ERR_LIB_DH, DH_F_DH_GENERATE_PARAMETERS_EX, 0), ++ "DH_generate_parameters_ex"}, + {ERR_PACK(ERR_LIB_DH, DH_F_DH_METH_DUP, 0), "DH_meth_dup"}, + {ERR_PACK(ERR_LIB_DH, DH_F_DH_METH_NEW, 0), "DH_meth_new"}, + {ERR_PACK(ERR_LIB_DH, DH_F_DH_METH_SET1_NAME, 0), "DH_meth_set1_name"}, +@@ -78,11 +78,11 @@ static const ERR_STRING_DATA DH_str_reasons[] = { + {ERR_PACK(ERR_LIB_DH, 0, DH_R_KEY_SIZE_TOO_SMALL), "key size too small"}, + {ERR_PACK(ERR_LIB_DH, 0, DH_R_MISSING_PUBKEY), "missing pubkey"}, + {ERR_PACK(ERR_LIB_DH, 0, DH_R_MODULUS_TOO_LARGE), "modulus too large"}, ++ {ERR_PACK(ERR_LIB_DH, 0, DH_R_NON_FIPS_METHOD), "non fips method"}, + {ERR_PACK(ERR_LIB_DH, 0, DH_R_NOT_SUITABLE_GENERATOR), + "not suitable generator"}, + {ERR_PACK(ERR_LIB_DH, 0, DH_R_NO_PARAMETERS_SET), "no parameters set"}, + {ERR_PACK(ERR_LIB_DH, 0, DH_R_NO_PRIVATE_VALUE), "no private value"}, +- {ERR_PACK(ERR_LIB_DH, 0, DH_R_NON_FIPS_METHOD), "non FIPS method"}, + {ERR_PACK(ERR_LIB_DH, 0, DH_R_PARAMETER_ENCODING_ERROR), + "parameter encoding error"}, + {ERR_PACK(ERR_LIB_DH, 0, DH_R_PEER_KEY_ERROR), "peer key error"}, +diff --git a/crypto/dsa/dsa_err.c b/crypto/dsa/dsa_err.c +index d85d221..26210c5 100644 +--- a/crypto/dsa/dsa_err.c ++++ b/crypto/dsa/dsa_err.c +@@ -1,6 +1,6 @@ + /* + * Generated by util/mkerr.pl DO NOT EDIT +- * Copyright 1995-2019 The OpenSSL Project Authors. All Rights Reserved. ++ * Copyright 1995-2022 The OpenSSL Project Authors. All Rights Reserved. + * + * Licensed under the OpenSSL license (the "License"). You may not use + * this file except in compliance with the License. You can obtain a copy +@@ -24,7 +24,8 @@ static const ERR_STRING_DATA DSA_str_functs[] = { + {ERR_PACK(ERR_LIB_DSA, DSA_F_DSA_DO_SIGN, 0), "DSA_do_sign"}, + {ERR_PACK(ERR_LIB_DSA, DSA_F_DSA_DO_VERIFY, 0), "DSA_do_verify"}, + {ERR_PACK(ERR_LIB_DSA, DSA_F_DSA_GENERATE_KEY, 0), "DSA_generate_key"}, +- {ERR_PACK(ERR_LIB_DSA, DSA_F_DSA_GENERATE_PARAMETERS_EX, 0), "DSA_generate_parameters_ex"}, ++ {ERR_PACK(ERR_LIB_DSA, DSA_F_DSA_GENERATE_PARAMETERS_EX, 0), ++ "DSA_generate_parameters_ex"}, + {ERR_PACK(ERR_LIB_DSA, DSA_F_DSA_METH_DUP, 0), "DSA_meth_dup"}, + {ERR_PACK(ERR_LIB_DSA, DSA_F_DSA_METH_NEW, 0), "DSA_meth_new"}, + {ERR_PACK(ERR_LIB_DSA, DSA_F_DSA_METH_SET1_NAME, 0), "DSA_meth_set1_name"}, +@@ -60,8 +61,9 @@ static const ERR_STRING_DATA DSA_str_reasons[] = { + {ERR_PACK(ERR_LIB_DSA, 0, DSA_R_MISSING_PRIVATE_KEY), + "missing private key"}, + {ERR_PACK(ERR_LIB_DSA, 0, DSA_R_MODULUS_TOO_LARGE), "modulus too large"}, ++ {ERR_PACK(ERR_LIB_DSA, 0, DSA_R_NON_FIPS_DSA_METHOD), ++ "non fips dsa method"}, + {ERR_PACK(ERR_LIB_DSA, 0, DSA_R_NO_PARAMETERS_SET), "no parameters set"}, +- {ERR_PACK(ERR_LIB_DSA, 0, DSA_R_NON_FIPS_DSA_METHOD), "non FIPS DSA method"}, + {ERR_PACK(ERR_LIB_DSA, 0, DSA_R_PARAMETER_ENCODING_ERROR), + "parameter encoding error"}, + {ERR_PACK(ERR_LIB_DSA, 0, DSA_R_Q_NOT_PRIME), "q not prime"}, +diff --git a/crypto/err/openssl.txt b/crypto/err/openssl.txt +index b93cace..7e918bb 100644 +--- a/crypto/err/openssl.txt ++++ b/crypto/err/openssl.txt +@@ -1,4 +1,4 @@ +-# Copyright 1999-2021 The OpenSSL Project Authors. All Rights Reserved. ++# Copyright 1999-2022 The OpenSSL Project Authors. All Rights Reserved. + # + # Licensed under the OpenSSL license (the "License"). You may not use + # this file except in compliance with the License. You can obtain a copy +@@ -1184,7 +1184,7 @@ SSL_F_OSSL_STATEM_SERVER_CONSTRUCT_MESSAGE:431:* + SSL_F_OSSL_STATEM_SERVER_POST_PROCESS_MESSAGE:601:\ + ossl_statem_server_post_process_message + SSL_F_OSSL_STATEM_SERVER_POST_WORK:602:ossl_statem_server_post_work +-SSL_F_OSSL_STATEM_SERVER_PRE_WORK:640: ++SSL_F_OSSL_STATEM_SERVER_PRE_WORK:640:ossl_statem_server_pre_work + SSL_F_OSSL_STATEM_SERVER_PROCESS_MESSAGE:603:ossl_statem_server_process_message + SSL_F_OSSL_STATEM_SERVER_READ_TRANSITION:418:ossl_statem_server_read_transition + SSL_F_OSSL_STATEM_SERVER_WRITE_TRANSITION:604:\ +@@ -1270,6 +1270,10 @@ SSL_F_SSL_CTX_SET_TLSEXT_MAX_FRAGMENT_LENGTH:551:\ + SSL_F_SSL_CTX_USE_CERTIFICATE:171:SSL_CTX_use_certificate + SSL_F_SSL_CTX_USE_CERTIFICATE_ASN1:172:SSL_CTX_use_certificate_ASN1 + SSL_F_SSL_CTX_USE_CERTIFICATE_FILE:173:SSL_CTX_use_certificate_file ++SSL_F_SSL_CTX_USE_GM_CERTIFICATE:641:SSL_CTX_use_gm_certificate ++SSL_F_SSL_CTX_USE_GM_CERTIFICATE_ASN1:642:SSL_CTX_use_gm_certificate_ASN1 ++SSL_F_SSL_CTX_USE_GM_PRIVATEKEY:643:SSL_CTX_use_gm_PrivateKey ++SSL_F_SSL_CTX_USE_GM_PRIVATEKEY_ASN1:644:SSL_CTX_use_gm_PrivateKey_ASN1 + SSL_F_SSL_CTX_USE_PRIVATEKEY:174:SSL_CTX_use_PrivateKey + SSL_F_SSL_CTX_USE_PRIVATEKEY_ASN1:175:SSL_CTX_use_PrivateKey_ASN1 + SSL_F_SSL_CTX_USE_PRIVATEKEY_FILE:176:SSL_CTX_use_PrivateKey_file +@@ -1296,7 +1300,9 @@ SSL_F_SSL_GET_SIGN_PKEY:183:* + SSL_F_SSL_HANDSHAKE_HASH:560:ssl_handshake_hash + SSL_F_SSL_INIT_WBIO_BUFFER:184:ssl_init_wbio_buffer + SSL_F_SSL_KEY_UPDATE:515:SSL_key_update ++SSL_F_SSL_LOAD_CERT_FILE:645:ssl_load_cert_file + SSL_F_SSL_LOAD_CLIENT_CA_FILE:185:SSL_load_client_CA_file ++SSL_F_SSL_LOAD_PKEY_FILE:646:ssl_load_pkey_file + SSL_F_SSL_LOG_MASTER_SECRET:498:* + SSL_F_SSL_LOG_RSA_CLIENT_KEY_EXCHANGE:499:ssl_log_rsa_client_key_exchange + SSL_F_SSL_MODULE_INIT:392:ssl_module_init +@@ -1330,11 +1336,14 @@ SSL_F_SSL_SET_CERT_AND_KEY:621:ssl_set_cert_and_key + SSL_F_SSL_SET_CIPHER_LIST:271:SSL_set_cipher_list + SSL_F_SSL_SET_CT_VALIDATION_CALLBACK:399:SSL_set_ct_validation_callback + SSL_F_SSL_SET_FD:192:SSL_set_fd ++SSL_F_SSL_SET_GM_CERT_AND_KEY:647:ssl_set_gm_cert_and_key + SSL_F_SSL_SET_PKEY:193:ssl_set_pkey + SSL_F_SSL_SET_RFD:194:SSL_set_rfd + SSL_F_SSL_SET_SESSION:195:SSL_set_session + SSL_F_SSL_SET_SESSION_ID_CONTEXT:218:SSL_set_session_id_context + SSL_F_SSL_SET_SESSION_TICKET_EXT:294:SSL_set_session_ticket_ext ++SSL_F_SSL_SET_SIGN_ENC_CERT:648:ssl_set_sign_enc_cert ++SSL_F_SSL_SET_SIGN_ENC_PKEY:649:ssl_set_sign_enc_pkey + SSL_F_SSL_SET_TLSEXT_MAX_FRAGMENT_LENGTH:550:SSL_set_tlsext_max_fragment_length + SSL_F_SSL_SET_WFD:196:SSL_set_wfd + SSL_F_SSL_SHUTDOWN:224:SSL_shutdown +@@ -1345,6 +1354,10 @@ SSL_F_SSL_UNDEFINED_VOID_FUNCTION:244:ssl_undefined_void_function + SSL_F_SSL_USE_CERTIFICATE:198:SSL_use_certificate + SSL_F_SSL_USE_CERTIFICATE_ASN1:199:SSL_use_certificate_ASN1 + SSL_F_SSL_USE_CERTIFICATE_FILE:200:SSL_use_certificate_file ++SSL_F_SSL_USE_GM_CERTIFICATE:650:SSL_use_gm_certificate ++SSL_F_SSL_USE_GM_CERTIFICATE_ASN1:651:SSL_use_gm_certificate_ASN1 ++SSL_F_SSL_USE_GM_PRIVATEKEY:652:SSL_use_gm_PrivateKey ++SSL_F_SSL_USE_GM_PRIVATEKEY_ASN1:653:SSL_use_gm_PrivateKey_ASN1 + SSL_F_SSL_USE_PRIVATEKEY:201:SSL_use_PrivateKey + SSL_F_SSL_USE_PRIVATEKEY_ASN1:202:SSL_use_PrivateKey_ASN1 + SSL_F_SSL_USE_PRIVATEKEY_FILE:203:SSL_use_PrivateKey_file +@@ -1361,6 +1374,14 @@ SSL_F_SSL_WRITE_EARLY_FINISH:527:* + SSL_F_SSL_WRITE_EX:433:SSL_write_ex + SSL_F_SSL_WRITE_INTERNAL:524:ssl_write_internal + SSL_F_STATE_MACHINE:353:state_machine ++SSL_F_TLCP_CONSTRUCT_CKE_SM2ECC:658:tlcp_construct_cke_sm2ecc ++SSL_F_TLCP_CONSTRUCT_CLIENT_KEY_EXCHANGE:654:tlcp_construct_client_key_exchange ++SSL_F_TLCP_CONSTRUCT_SERVER_KEY_EXCHANGE:655:tlcp_construct_server_key_exchange ++SSL_F_TLCP_CONSTRUCT_SKE_SM2ECC:659:tlcp_construct_ske_sm2ecc ++SSL_F_TLCP_PROCESS_CKE_SM2ECC:660:tlcp_process_cke_sm2ecc ++SSL_F_TLCP_PROCESS_CLIENT_KEY_EXCHANGE:656:tlcp_process_client_key_exchange ++SSL_F_TLCP_PROCESS_KEY_EXCHANGE:657:tlcp_process_key_exchange ++SSL_F_TLCP_PROCESS_SKE_SM2ECC:661:tlcp_process_ske_sm2ecc + SSL_F_TLS12_CHECK_PEER_SIGALG:333:tls12_check_peer_sigalg + SSL_F_TLS12_COPY_SIGALGS:533:tls12_copy_sigalgs + SSL_F_TLS13_CHANGE_CIPHER_STATE:440:tls13_change_cipher_state +@@ -1769,7 +1790,7 @@ X509_F_X509_STORE_NEW:158:X509_STORE_new + X509_F_X509_TO_X509_REQ:126:X509_to_X509_REQ + X509_F_X509_TRUST_ADD:133:X509_TRUST_add + X509_F_X509_TRUST_SET:141:X509_TRUST_set +-X509_F_X509_VERIFY:161:X509_verify ++X509_F_X509_VERIFY:166:X509_verify + X509_F_X509_VERIFY_CERT:127:X509_verify_cert + X509_F_X509_VERIFY_PARAM_NEW:159:X509_VERIFY_PARAM_new + X509_F_X509_VERIFY_SM2:162:x509_verify_sm2 +diff --git a/crypto/evp/evp_err.c b/crypto/evp/evp_err.c +index daf7fdc..e3c9e05 100644 +--- a/crypto/evp/evp_err.c ++++ b/crypto/evp/evp_err.c +@@ -1,6 +1,6 @@ + /* + * Generated by util/mkerr.pl DO NOT EDIT +- * Copyright 1995-2021 The OpenSSL Project Authors. All Rights Reserved. ++ * Copyright 1995-2022 The OpenSSL Project Authors. All Rights Reserved. + * + * Licensed under the OpenSSL license (the "License"). You may not use + * this file except in compliance with the License. You can obtain a copy +@@ -187,7 +187,7 @@ static const ERR_STRING_DATA EVP_str_reasons[] = { + "different key types"}, + {ERR_PACK(ERR_LIB_EVP, 0, EVP_R_DIFFERENT_PARAMETERS), + "different parameters"}, +- {ERR_PACK(ERR_LIB_EVP, 0, EVP_R_DISABLED_FOR_FIPS), "disabled for FIPS"}, ++ {ERR_PACK(ERR_LIB_EVP, 0, EVP_R_DISABLED_FOR_FIPS), "disabled for fips"}, + {ERR_PACK(ERR_LIB_EVP, 0, EVP_R_ERROR_LOADING_SECTION), + "error loading section"}, + {ERR_PACK(ERR_LIB_EVP, 0, EVP_R_ERROR_SETTING_FIPS_MODE), +@@ -279,8 +279,6 @@ static const ERR_STRING_DATA EVP_str_reasons[] = { + "wrap mode not allowed"}, + {ERR_PACK(ERR_LIB_EVP, 0, EVP_R_WRONG_FINAL_BLOCK_LENGTH), + "wrong final block length"}, +- {ERR_PACK(ERR_LIB_EVP, 0, EVP_R_XTS_DATA_UNIT_IS_TOO_LARGE), +- "xts data unit is too large"}, + {ERR_PACK(ERR_LIB_EVP, 0, EVP_R_XTS_DUPLICATED_KEYS), + "xts duplicated keys"}, + {0, NULL} +diff --git a/crypto/evp/p_lib.c b/crypto/evp/p_lib.c +index 1f36cb2..9e25ae1 100644 +--- a/crypto/evp/p_lib.c ++++ b/crypto/evp/p_lib.c +@@ -459,6 +459,24 @@ const unsigned char *EVP_PKEY_get0_siphash(const EVP_PKEY *pkey, size_t *len) + } + #endif + ++# ifndef OPENSSL_NO_SM2 ++int EVP_PKEY_is_sm2(EVP_PKEY *pkey) ++{ ++ EC_KEY *eckey; ++ const EC_GROUP *group; ++ if (pkey == NULL) { ++ return 0; ++ } ++ if (EVP_PKEY_id(pkey) == EVP_PKEY_EC ++ && (eckey = EVP_PKEY_get0_EC_KEY(pkey)) != NULL ++ && (group = EC_KEY_get0_group(eckey)) != NULL ++ && EC_GROUP_get_curve_name(group) == NID_sm2) { ++ return 1; ++ } ++ return EVP_PKEY_id(pkey) == EVP_PKEY_SM2; ++} ++# endif ++ + #ifndef OPENSSL_NO_RSA + int EVP_PKEY_set1_RSA(EVP_PKEY *pkey, RSA *key) + { +diff --git a/crypto/rsa/rsa_err.c b/crypto/rsa/rsa_err.c +index cf43265..888fd07 100644 +--- a/crypto/rsa/rsa_err.c ++++ b/crypto/rsa/rsa_err.c +@@ -1,6 +1,6 @@ + /* + * Generated by util/mkerr.pl DO NOT EDIT +- * Copyright 1995-2019 The OpenSSL Project Authors. All Rights Reserved. ++ * Copyright 1995-2022 The OpenSSL Project Authors. All Rights Reserved. + * + * Licensed under the OpenSSL license (the "License"). You may not use + * this file except in compliance with the License. You can obtain a copy +@@ -34,7 +34,8 @@ static const ERR_STRING_DATA RSA_str_functs[] = { + {ERR_PACK(ERR_LIB_RSA, RSA_F_RSA_CHECK_KEY_EX, 0), "RSA_check_key_ex"}, + {ERR_PACK(ERR_LIB_RSA, RSA_F_RSA_CMS_DECRYPT, 0), "rsa_cms_decrypt"}, + {ERR_PACK(ERR_LIB_RSA, RSA_F_RSA_CMS_VERIFY, 0), "rsa_cms_verify"}, +- {ERR_PACK(ERR_LIB_RSA, RSA_F_RSA_GENERATE_KEY_EX, 0), "RSA_generate_key_ex"}, ++ {ERR_PACK(ERR_LIB_RSA, RSA_F_RSA_GENERATE_KEY_EX, 0), ++ "RSA_generate_key_ex"}, + {ERR_PACK(ERR_LIB_RSA, RSA_F_RSA_GENERATE_MULTI_PRIME_KEY, 0), + "RSA_generate_multi_prime_key"}, + {ERR_PACK(ERR_LIB_RSA, RSA_F_RSA_ITEM_VERIFY, 0), "rsa_item_verify"}, +@@ -93,16 +94,21 @@ static const ERR_STRING_DATA RSA_str_functs[] = { + {ERR_PACK(ERR_LIB_RSA, RSA_F_RSA_PARAM_DECODE, 0), "rsa_param_decode"}, + {ERR_PACK(ERR_LIB_RSA, RSA_F_RSA_PRINT, 0), "RSA_print"}, + {ERR_PACK(ERR_LIB_RSA, RSA_F_RSA_PRINT_FP, 0), "RSA_print_fp"}, ++ {ERR_PACK(ERR_LIB_RSA, RSA_F_RSA_PRIVATE_DECRYPT, 0), ++ "RSA_private_decrypt"}, ++ {ERR_PACK(ERR_LIB_RSA, RSA_F_RSA_PRIVATE_ENCRYPT, 0), ++ "RSA_private_encrypt"}, + {ERR_PACK(ERR_LIB_RSA, RSA_F_RSA_PRIV_DECODE, 0), "rsa_priv_decode"}, + {ERR_PACK(ERR_LIB_RSA, RSA_F_RSA_PRIV_ENCODE, 0), "rsa_priv_encode"}, +- {ERR_PACK(ERR_LIB_RSA, RSA_F_RSA_PRIVATE_DECRYPT, 0), "RSA_private_decrypt"}, +- {ERR_PACK(ERR_LIB_RSA, RSA_F_RSA_PRIVATE_ENCRYPT, 0), "RSA_private_encrypt"}, + {ERR_PACK(ERR_LIB_RSA, RSA_F_RSA_PSS_GET_PARAM, 0), "rsa_pss_get_param"}, + {ERR_PACK(ERR_LIB_RSA, RSA_F_RSA_PSS_TO_CTX, 0), "rsa_pss_to_ctx"}, +- {ERR_PACK(ERR_LIB_RSA, RSA_F_RSA_PUB_DECODE, 0), "rsa_pub_decode"}, + {ERR_PACK(ERR_LIB_RSA, RSA_F_RSA_PUBLIC_DECRYPT, 0), "RSA_public_decrypt"}, + {ERR_PACK(ERR_LIB_RSA, RSA_F_RSA_PUBLIC_ENCRYPT, 0), "RSA_public_encrypt"}, ++ {ERR_PACK(ERR_LIB_RSA, RSA_F_RSA_PUB_DECODE, 0), "rsa_pub_decode"}, + {ERR_PACK(ERR_LIB_RSA, RSA_F_RSA_SETUP_BLINDING, 0), "RSA_setup_blinding"}, ++ {ERR_PACK(ERR_LIB_RSA, RSA_F_RSA_SET_DEFAULT_METHOD, 0), ++ "RSA_set_default_method"}, ++ {ERR_PACK(ERR_LIB_RSA, RSA_F_RSA_SET_METHOD, 0), "RSA_set_method"}, + {ERR_PACK(ERR_LIB_RSA, RSA_F_RSA_SIGN, 0), "RSA_sign"}, + {ERR_PACK(ERR_LIB_RSA, RSA_F_RSA_SIGN_ASN1_OCTET_STRING, 0), + "RSA_sign_ASN1_OCTET_STRING"}, +@@ -111,8 +117,6 @@ static const ERR_STRING_DATA RSA_str_functs[] = { + "RSA_verify_ASN1_OCTET_STRING"}, + {ERR_PACK(ERR_LIB_RSA, RSA_F_RSA_VERIFY_PKCS1_PSS_MGF1, 0), + "RSA_verify_PKCS1_PSS_mgf1"}, +- {ERR_PACK(ERR_LIB_RSA, RSA_F_RSA_SET_DEFAULT_METHOD, 0), "RSA_set_default_method"}, +- {ERR_PACK(ERR_LIB_RSA, RSA_F_RSA_SET_METHOD, 0), "RSA_set_method"}, + {ERR_PACK(ERR_LIB_RSA, RSA_F_SETUP_TBUF, 0), "setup_tbuf"}, + {0, NULL} + }; +@@ -193,8 +197,9 @@ static const ERR_STRING_DATA RSA_str_reasons[] = { + {ERR_PACK(ERR_LIB_RSA, 0, RSA_R_MP_EXPONENT_NOT_CONGRUENT_TO_D), + "mp exponent not congruent to d"}, + {ERR_PACK(ERR_LIB_RSA, 0, RSA_R_MP_R_NOT_PRIME), "mp r not prime"}, ++ {ERR_PACK(ERR_LIB_RSA, 0, RSA_R_NON_FIPS_RSA_METHOD), ++ "non fips rsa method"}, + {ERR_PACK(ERR_LIB_RSA, 0, RSA_R_NO_PUBLIC_EXPONENT), "no public exponent"}, +- {ERR_PACK(ERR_LIB_RSA, 0, RSA_R_NON_FIPS_RSA_METHOD), "non FIPS rsa method"}, + {ERR_PACK(ERR_LIB_RSA, 0, RSA_R_NULL_BEFORE_BLOCK_MISSING), + "null before block missing"}, + {ERR_PACK(ERR_LIB_RSA, 0, RSA_R_N_DOES_NOT_EQUAL_PRODUCT_OF_PRIMES), +@@ -204,7 +209,7 @@ static const ERR_STRING_DATA RSA_str_reasons[] = { + {ERR_PACK(ERR_LIB_RSA, 0, RSA_R_OAEP_DECODING_ERROR), + "oaep decoding error"}, + {ERR_PACK(ERR_LIB_RSA, 0, RSA_R_OPERATION_NOT_ALLOWED_IN_FIPS_MODE), +- "operation not allowed in FIPS mode"}, ++ "operation not allowed in fips mode"}, + {ERR_PACK(ERR_LIB_RSA, 0, RSA_R_OPERATION_NOT_SUPPORTED_FOR_THIS_KEYTYPE), + "operation not supported for this keytype"}, + {ERR_PACK(ERR_LIB_RSA, 0, RSA_R_PADDING_CHECK_FAILED), +diff --git a/crypto/sm2/build.info b/crypto/sm2/build.info +index be76d96..adaf5f3 100644 +--- a/crypto/sm2/build.info ++++ b/crypto/sm2/build.info +@@ -1,5 +1,5 @@ + LIBS=../../libcrypto + SOURCE[../../libcrypto]=\ +- sm2_sign.c sm2_crypt.c sm2_err.c sm2_pmeth.c ++ sm2_sign.c sm2_crypt.c sm2_err.c sm2_pmeth.c sm2_kep.c + + +diff --git a/crypto/sm2/sm2_err.c b/crypto/sm2/sm2_err.c +index e5973e9..f5f75cb 100644 +--- a/crypto/sm2/sm2_err.c ++++ b/crypto/sm2/sm2_err.c +@@ -1,6 +1,6 @@ + /* + * Generated by util/mkerr.pl DO NOT EDIT +- * Copyright 1995-2018 The OpenSSL Project Authors. All Rights Reserved. ++ * Copyright 1995-2022 The OpenSSL Project Authors. All Rights Reserved. + * + * Licensed under the OpenSSL license (the "License"). You may not use + * this file except in compliance with the License. You can obtain a copy +@@ -21,6 +21,7 @@ static const ERR_STRING_DATA SM2_str_functs[] = { + "pkey_sm2_digest_custom"}, + {ERR_PACK(ERR_LIB_SM2, SM2_F_PKEY_SM2_INIT, 0), "pkey_sm2_init"}, + {ERR_PACK(ERR_LIB_SM2, SM2_F_PKEY_SM2_SIGN, 0), "pkey_sm2_sign"}, ++ {ERR_PACK(ERR_LIB_SM2, SM2_F_SM2_COMPUTE_KEY, 0), "SM2_compute_key"}, + {ERR_PACK(ERR_LIB_SM2, SM2_F_SM2_COMPUTE_MSG_HASH, 0), + "sm2_compute_msg_hash"}, + {ERR_PACK(ERR_LIB_SM2, SM2_F_SM2_COMPUTE_USERID_DIGEST, 0), +@@ -51,6 +52,7 @@ static const ERR_STRING_DATA SM2_str_reasons[] = { + {ERR_PACK(ERR_LIB_SM2, 0, SM2_R_INVALID_ENCODING), "invalid encoding"}, + {ERR_PACK(ERR_LIB_SM2, 0, SM2_R_INVALID_FIELD), "invalid field"}, + {ERR_PACK(ERR_LIB_SM2, 0, SM2_R_NO_PARAMETERS_SET), "no parameters set"}, ++ {ERR_PACK(ERR_LIB_SM2, 0, SM2_R_NO_PRIVATE_VALUE), "no private value"}, + {ERR_PACK(ERR_LIB_SM2, 0, SM2_R_USER_ID_TOO_LARGE), "user id too large"}, + {0, NULL} + }; +diff --git a/crypto/sm2/sm2_kep.c b/crypto/sm2/sm2_kep.c +new file mode 100644 +index 0000000..a7bd681 +--- /dev/null ++++ b/crypto/sm2/sm2_kep.c +@@ -0,0 +1,254 @@ ++/* ++ * Copyright 2019 The BabaSSL Project Authors. All Rights Reserved. ++ */ ++ ++#include "internal/cryptlib.h" ++#include ++#include ++#include ++#include "crypto/sm2.h" ++#include "crypto/ec.h" /* ecdh_KDF_X9_63() */ ++#include "crypto/sm2err.h" ++ ++ ++#ifndef OPENSSL_NO_SM2 ++int SM2_compute_key(void *out, size_t outlen, int server, ++ const char *peer_uid, int peer_uid_len, ++ const char *self_uid, int self_uid_len, ++ const EC_KEY *peer_ecdhe_key, const EC_KEY *self_ecdhe_key, ++ const EC_KEY *peer_pub_key, const EC_KEY *self_eckey, ++ const EVP_MD *md) ++{ ++ BN_CTX *ctx = NULL; ++ EC_POINT *UorV = NULL; ++ const EC_POINT *Rs, *Rp; ++ BIGNUM *Xs = NULL, *Xp = NULL, *h = NULL, *t = NULL, *two_power_w = NULL, *order = NULL; ++ const BIGNUM *priv_key, *r; ++ const EC_GROUP *group; ++ int w; ++ int ret = -1; ++ size_t buflen, len; ++ unsigned char *buf = NULL; ++ size_t elemet_len, idx; ++ ++ if (outlen > INT_MAX) { ++ SM2err(SM2_F_SM2_COMPUTE_KEY, ERR_R_MALLOC_FAILURE); ++ goto err; ++ } ++ ++ if (peer_pub_key == NULL || self_eckey == NULL) { ++ SM2err(SM2_F_SM2_COMPUTE_KEY, SM2_R_NO_PRIVATE_VALUE); ++ goto err; ++ } ++ ++ priv_key = EC_KEY_get0_private_key(self_eckey); ++ if (priv_key == NULL) { ++ SM2err(SM2_F_SM2_COMPUTE_KEY, SM2_R_NO_PRIVATE_VALUE); ++ goto err; ++ } ++ ++ if (peer_ecdhe_key == NULL || self_ecdhe_key == NULL) { ++ SM2err(SM2_F_SM2_COMPUTE_KEY, ERR_R_PASSED_NULL_PARAMETER); ++ goto err; ++ } ++ ++ Rs = EC_KEY_get0_public_key(self_ecdhe_key); ++ Rp = EC_KEY_get0_public_key(peer_ecdhe_key); ++ r = EC_KEY_get0_private_key(self_ecdhe_key); ++ ++ if (Rs == NULL || Rp == NULL || r == NULL) { ++ SM2err(SM2_F_SM2_COMPUTE_KEY, ERR_R_PASSED_NULL_PARAMETER); ++ goto err; ++ } ++ ++ ctx = BN_CTX_new(); ++ if (ctx == NULL) { ++ SM2err(SM2_F_SM2_COMPUTE_KEY, ERR_R_MALLOC_FAILURE); ++ goto err; ++ } ++ ++ BN_CTX_start(ctx); ++ Xs = BN_CTX_get(ctx); ++ Xp = BN_CTX_get(ctx); ++ h = BN_CTX_get(ctx); ++ t = BN_CTX_get(ctx); ++ two_power_w = BN_CTX_get(ctx); ++ order = BN_CTX_get(ctx); ++ ++ if (order == NULL) { ++ SM2err(SM2_F_SM2_COMPUTE_KEY, ERR_R_MALLOC_FAILURE); ++ goto err; ++ } ++ ++ group = EC_KEY_get0_group(self_eckey); ++ ++ if (!EC_GROUP_get_order(group, order, ctx) ++ || !EC_GROUP_get_cofactor(group, h, ctx)) { ++ SM2err(SM2_F_SM2_COMPUTE_KEY, ERR_R_MALLOC_FAILURE); ++ goto err; ++ } ++ ++ w = (BN_num_bits(order) + 1) / 2 - 1; ++ if (!BN_lshift(two_power_w, BN_value_one(), w)) { ++ SM2err(SM2_F_SM2_COMPUTE_KEY, ERR_R_BN_LIB); ++ goto err; ++ } ++ ++ /*Third: Caculate -- X = 2 ^ w + (x & (2 ^ w - 1)) = 2 ^ w + (x mod 2 ^ w)*/ ++ UorV = EC_POINT_new(group); ++ if (UorV == NULL) { ++ SM2err(SM2_F_SM2_COMPUTE_KEY, ERR_R_MALLOC_FAILURE); ++ goto err; ++ } ++ ++ /*Test peer public key On curve*/ ++ if (!EC_POINT_is_on_curve(group, Rp, ctx)) { ++ SM2err(SM2_F_SM2_COMPUTE_KEY, ERR_R_EC_LIB); ++ goto err; ++ } ++ ++ /*Get x*/ ++ if (EC_METHOD_get_field_type(EC_GROUP_method_of(group)) ++ == NID_X9_62_prime_field) { ++ if (!EC_POINT_get_affine_coordinates_GFp(group, Rs, Xs, NULL, ctx)) { ++ SM2err(SM2_F_SM2_COMPUTE_KEY, ERR_R_EC_LIB); ++ goto err; ++ } ++ ++ if (!EC_POINT_get_affine_coordinates_GFp(group, Rp, Xp, NULL, ctx)) { ++ SM2err(SM2_F_SM2_COMPUTE_KEY, ERR_R_EC_LIB); ++ goto err; ++ } ++ } ++ ++ /*x mod 2 ^ w*/ ++ /*Caculate Self x*/ ++ if (!BN_nnmod(Xs, Xs, two_power_w, ctx)) { ++ SM2err(SM2_F_SM2_COMPUTE_KEY, ERR_R_BN_LIB); ++ goto err; ++ } ++ ++ if (!BN_add(Xs, Xs, two_power_w)) { ++ SM2err(SM2_F_SM2_COMPUTE_KEY, ERR_R_BN_LIB); ++ goto err; ++ } ++ ++ /*Caculate Peer x*/ ++ if (!BN_nnmod(Xp, Xp, two_power_w, ctx)) { ++ SM2err(SM2_F_SM2_COMPUTE_KEY, ERR_R_BN_LIB); ++ goto err; ++ } ++ ++ if (!BN_add(Xp, Xp, two_power_w)) { ++ SM2err(SM2_F_SM2_COMPUTE_KEY, ERR_R_BN_LIB); ++ goto err; ++ } ++ ++ /*Forth: Caculate t*/ ++ if (!BN_mod_mul(t, Xs, r, order, ctx)) { ++ SM2err(SM2_F_SM2_COMPUTE_KEY, ERR_R_BN_LIB); ++ goto err; ++ } ++ ++ if (!BN_mod_add(t, t, priv_key, order, ctx)) { ++ SM2err(SM2_F_SM2_COMPUTE_KEY, ERR_R_BN_LIB); ++ goto err; ++ } ++ ++ /*Fifth: Caculate V or U*/ ++ if (!BN_mul(t, t, h, ctx)) { ++ SM2err(SM2_F_SM2_COMPUTE_KEY, ERR_R_BN_LIB); ++ goto err; ++ } ++ ++ /* [x]R */ ++ if (!EC_POINT_mul(group, UorV, NULL, Rp, Xp, ctx)) { ++ SM2err(SM2_F_SM2_COMPUTE_KEY, ERR_R_EC_LIB); ++ goto err; ++ } ++ ++ /* P + [x]R */ ++ if (!EC_POINT_add(group, UorV, UorV, ++ EC_KEY_get0_public_key(peer_pub_key), ctx)) { ++ SM2err(SM2_F_SM2_COMPUTE_KEY, ERR_R_EC_LIB); ++ goto err; ++ } ++ ++ if (!EC_POINT_mul(group, UorV, NULL, UorV, t, ctx)) { ++ SM2err(SM2_F_SM2_COMPUTE_KEY, ERR_R_EC_LIB); ++ goto err; ++ } ++ ++ if (EC_POINT_is_at_infinity(group, UorV)) { ++ SM2err(SM2_F_SM2_COMPUTE_KEY, ERR_R_EC_LIB); ++ goto err; ++ } ++ ++ /*Sixth: Caculate Key -- Need Xuorv, Yuorv, Zc, Zs, klen*/ ++ ++ elemet_len = (size_t)((EC_GROUP_get_degree(group) + 7) / 8); ++ buflen = elemet_len * 2 + 32 * 2 + 1; /*add 1 byte tag*/ ++ buf = (unsigned char *)OPENSSL_zalloc(buflen + 10); ++ if (buf == NULL) { ++ SM2err(SM2_F_SM2_COMPUTE_KEY, ERR_R_MALLOC_FAILURE); ++ goto err; ++ } ++ ++ /*1 : Get public key for UorV, Notice: the first byte is a tag, not a valid char*/ ++ idx = EC_POINT_point2oct(group, UorV, 4, buf, buflen, ctx); ++ if (!idx) { ++ SM2err(SM2_F_SM2_COMPUTE_KEY, ERR_R_EC_LIB); ++ goto err; ++ } ++ ++ len = EVP_MD_size(md); ++ ++ /* Z_A || Z_B, server is initiator(Z_A), client is responder(Z_B) */ ++ if (server) { ++ if (!sm2_compute_z_digest((uint8_t *)(buf + idx), md, ++ (const uint8_t *)self_uid, ++ self_uid_len, self_eckey)) { ++ SM2err(SM2_F_SM2_COMPUTE_KEY, ERR_R_INTERNAL_ERROR); ++ goto err; ++ } ++ ++ idx += len; ++ } ++ ++ if (!sm2_compute_z_digest((uint8_t *)(buf + idx), md, ++ (const uint8_t *)peer_uid, peer_uid_len, ++ peer_pub_key)) { ++ SM2err(SM2_F_SM2_COMPUTE_KEY, ERR_R_INTERNAL_ERROR); ++ goto err; ++ } ++ idx += len; ++ ++ if (!server) { ++ if (!sm2_compute_z_digest((uint8_t *)(buf + idx), md, ++ (const uint8_t *)self_uid, ++ self_uid_len, self_eckey)) { ++ SM2err(SM2_F_SM2_COMPUTE_KEY, ERR_R_INTERNAL_ERROR); ++ goto err; ++ } ++ idx += len; ++ } ++ ++ if (!ecdh_KDF_X9_63(out, outlen, (const unsigned char *)(buf + 1), idx - 1, ++ NULL, 0, md)) { ++ SM2err(SM2_F_SM2_COMPUTE_KEY, ERR_R_INTERNAL_ERROR); ++ goto err; ++ } ++ ++ ret = outlen; ++ ++ err: ++ EC_POINT_free(UorV); ++ OPENSSL_free(buf); ++ if (ctx != NULL) ++ BN_CTX_end(ctx); ++ BN_CTX_free(ctx); ++ ++ return ret; ++} ++ ++#endif +diff --git a/crypto/sm2/sm2_pmeth.c b/crypto/sm2/sm2_pmeth.c +index 9551d70..33010b8 100644 +--- a/crypto/sm2/sm2_pmeth.c ++++ b/crypto/sm2/sm2_pmeth.c +@@ -287,6 +287,11 @@ static int pkey_sm2_digest_custom(EVP_PKEY_CTX *ctx, EVP_MD_CTX *mctx) + const EVP_MD *md = EVP_MD_CTX_md(mctx); + int mdlen = EVP_MD_size(md); + ++#ifndef OPENSSL_NO_SM2 ++ if (!smctx->id_set) ++ (void)pkey_sm2_ctrl(ctx, EVP_PKEY_CTRL_SET1_ID, SM2_DEFAULT_USERID_LEN ++ , (void *)SM2_DEFAULT_USERID); ++#endif + if (!smctx->id_set) { + /* + * An ID value must be set. The specifications are not clear whether a +diff --git a/doc/man1/s_client.pod b/doc/man1/s_client.pod +index f1a2c4a..8fa82a1 100644 +--- a/doc/man1/s_client.pod ++++ b/doc/man1/s_client.pod +@@ -20,8 +20,10 @@ B B + [B<-verify depth>] + [B<-verify_return_error>] + [B<-cert filename>] ++[B<-dcert filename>] + [B<-certform DER|PEM>] + [B<-key filename>] ++[B<-dkey filename>] + [B<-keyform DER|PEM>] + [B<-cert_chain filename>] + [B<-build_chain>] +@@ -32,6 +34,7 @@ B B + [B<-xcertform PEM|DER>] + [B<-xkeyform PEM|DER>] + [B<-pass arg>] ++[B<-dpass arg>] + [B<-CApath directory>] + [B<-CAfile filename>] + [B<-chainCApath directory>] +@@ -91,6 +94,7 @@ B B + [B<-tls1_1>] + [B<-tls1_2>] + [B<-tls1_3>] ++[B<-tlcp>] + [B<-no_ssl3>] + [B<-no_tls1>] + [B<-no_tls1_1>] +@@ -214,6 +218,11 @@ ClientHello message. Cannot be used in conjunction with the B<-servername> or + The certificate to use, if one is requested by the server. The default is + not to use a certificate. + ++=item B<-dcert infile>, B<-dkey infile>, B<-dpass val> ++ ++Specify an encryption certificate, private key and passphrase ++respectively, usually for TLCP. ++ + =item B<-certform format> + + The certificate format to use: DER or PEM. PEM is the default. +diff --git a/doc/man3/EVP_PKEY_set1_RSA.pod b/doc/man3/EVP_PKEY_set1_RSA.pod +index d571e58..f9ee16d 100644 +--- a/doc/man3/EVP_PKEY_set1_RSA.pod ++++ b/doc/man3/EVP_PKEY_set1_RSA.pod +@@ -9,7 +9,7 @@ EVP_PKEY_assign_RSA, EVP_PKEY_assign_DSA, EVP_PKEY_assign_DH, + EVP_PKEY_assign_EC_KEY, EVP_PKEY_assign_POLY1305, EVP_PKEY_assign_SIPHASH, + EVP_PKEY_get0_hmac, EVP_PKEY_get0_poly1305, EVP_PKEY_get0_siphash, + EVP_PKEY_type, EVP_PKEY_id, EVP_PKEY_base_id, EVP_PKEY_set_alias_type, +-EVP_PKEY_set1_engine, EVP_PKEY_get0_engine - EVP_PKEY assignment functions ++EVP_PKEY_is_sm2, EVP_PKEY_set1_engine, EVP_PKEY_get0_engine - EVP_PKEY assignment functions + + =head1 SYNOPSIS + +@@ -45,6 +45,8 @@ EVP_PKEY_set1_engine, EVP_PKEY_get0_engine - EVP_PKEY assignment functions + int EVP_PKEY_type(int type); + int EVP_PKEY_set_alias_type(EVP_PKEY *pkey, int type); + ++ int EVP_PKEY_is_sm2(EVP_PKEY *pkey); ++ + ENGINE *EVP_PKEY_get0_engine(const EVP_PKEY *pkey); + int EVP_PKEY_set1_engine(EVP_PKEY *pkey, ENGINE *engine); + +@@ -93,6 +95,9 @@ EVP_PKEY_set_alias_type() allows modifying a EVP_PKEY to use a + different set of algorithms than the default. This is currently used + to support SM2 keys, which use an identical encoding to ECDSA. + ++EVP_PKEY_is_sm2() can be used to determine whether the B is ++SM2 curve. ++ + =head1 NOTES + + In accordance with the OpenSSL naming convention the key obtained +@@ -134,6 +139,8 @@ EVP_PKEY_set1_engine() returns 1 for success and 0 for failure. + + EVP_PKEY_set_alias_type() returns 1 for success and 0 for error. + ++EVP_PKEY_is_sm2() returns 1 for success and 0 for error. ++ + =head1 EXAMPLES + + After loading an ECC key, it is possible to convert it to using SM2 +diff --git a/doc/man3/SSL_CTX_new.pod b/doc/man3/SSL_CTX_new.pod +index a6c036c..23f93f6 100644 +--- a/doc/man3/SSL_CTX_new.pod ++++ b/doc/man3/SSL_CTX_new.pod +@@ -9,7 +9,8 @@ TLSv1_1_method, TLSv1_1_server_method, TLSv1_1_client_method, TLS_method, + TLS_server_method, TLS_client_method, SSLv23_method, SSLv23_server_method, + SSLv23_client_method, DTLS_method, DTLS_server_method, DTLS_client_method, + DTLSv1_method, DTLSv1_server_method, DTLSv1_client_method, +-DTLSv1_2_method, DTLSv1_2_server_method, DTLSv1_2_client_method ++DTLSv1_2_method, DTLSv1_2_server_method, DTLSv1_2_client_method, ++TLCP_method, TLCP_server_method, TLCP_client_method, + - create a new SSL_CTX object as framework for TLS/SSL or DTLS enabled + functions + +@@ -68,6 +69,12 @@ functions + const SSL_METHOD *DTLSv1_2_client_method(void); + #endif + ++ #ifndef OPENSSL_NO_TLCP ++ const SSL_METHOD *TLCP_method(void); ++ const SSL_METHOD *TLCP_server_method(void); ++ const SSL_METHOD *TLCP_client_method(void); ++ #endif ++ + =head1 DESCRIPTION + + SSL_CTX_new() creates a new B object as framework to +@@ -93,6 +100,8 @@ These are the general-purpose I SSL/TLS methods. + The actual protocol version used will be negotiated to the highest version + mutually supported by the client and the server. + The supported protocols are SSLv3, TLSv1, TLSv1.1, TLSv1.2 and TLSv1.3. ++TLS_method() and TLS_server_method() can aslo support TLCP protocol ++by using TLCP_client_method(). + Applications should use these methods, and avoid the version-specific + methods described below, which are deprecated. + +@@ -141,6 +150,12 @@ These methods are deprecated. + These are the version-specific methods for DTLSv1. + These methods are deprecated. + ++=item TLCP_method(), TLCP_server_method(), TLCP_client_method() ++ ++These are the GM version-specific methods for TLCP protocol. ++Valid TLCP ciphersuite names are ECDHE-SM4-CBC-SM3 and ECC-SM4-CBC-SM3. ++B(argument to Configure) was required. ++ + =back + + SSL_CTX_new() initializes the list of ciphers, the session cache setting, the +@@ -162,7 +177,7 @@ allow newer protocols like TLS 1.0, TLS 1.1, TLS 1.2 or TLS 1.3. + + The list of protocols available can also be limited using the + B, B, B, +-B, B and B ++B, B, B and B + options of the + L or L functions, but this approach + is not recommended. Clients should avoid creating "holes" in the set of +diff --git a/doc/man3/SSL_CTX_set_options.pod b/doc/man3/SSL_CTX_set_options.pod +index 969e036..304e966 100644 +--- a/doc/man3/SSL_CTX_set_options.pod ++++ b/doc/man3/SSL_CTX_set_options.pod +@@ -114,11 +114,11 @@ preferences. When not set, the SSL server will always follow the clients + preferences. When set, the SSL/TLS server will choose following its + own preferences. + +-=item SSL_OP_NO_SSLv3, SSL_OP_NO_TLSv1, SSL_OP_NO_TLSv1_1, ++=item SSL_OP_NO_SSLv3, SSL_OP_NO_TLSv1, SSL_OP_NO_TLSv1_1, SSL_OP_NO_TLCP + SSL_OP_NO_TLSv1_2, SSL_OP_NO_TLSv1_3, SSL_OP_NO_DTLSv1, SSL_OP_NO_DTLSv1_2 + + These options turn off the SSLv3, TLSv1, TLSv1.1, TLSv1.2 or TLSv1.3 protocol +-versions with TLS or the DTLSv1, DTLSv1.2 versions with DTLS, ++versions with TLS or the DTLSv1, DTLSv1.2 versions with DTLS, TLCP + respectively. + As of OpenSSL 1.1.0, these options are deprecated, use + L and +diff --git a/doc/man3/SSL_CTX_use_certificate.pod b/doc/man3/SSL_CTX_use_certificate.pod +index b065d8f..7a717e7 100644 +--- a/doc/man3/SSL_CTX_use_certificate.pod ++++ b/doc/man3/SSL_CTX_use_certificate.pod +@@ -12,7 +12,12 @@ SSL_CTX_use_RSAPrivateKey_ASN1, SSL_CTX_use_RSAPrivateKey_file, + SSL_use_PrivateKey_file, SSL_use_PrivateKey_ASN1, SSL_use_PrivateKey, + SSL_use_RSAPrivateKey, SSL_use_RSAPrivateKey_ASN1, + SSL_use_RSAPrivateKey_file, SSL_CTX_check_private_key, SSL_check_private_key, +-SSL_CTX_use_cert_and_key, SSL_use_cert_and_key ++SSL_CTX_use_cert_and_key, SSL_use_cert_and_key, ++SSL_CTX_use_gm_certificate, SSL_CTX_use_gm_certificate_ASN1, SSL_CTX_use_gm_certificate_file, ++SSL_use_gm_certificate, SSL_use_gm_certificate_ASN1, SSL_use_gm_certificate_file, ++SSL_CTX_use_gm_PrivateKey, SSL_CTX_use_gm_PrivateKey_ASN1, SSL_CTX_use_gm_PrivateKey_file, ++SSL_use_gm_PrivateKey, SSL_use_gm_PrivateKey_ASN1, SSL_use_gm_PrivateKey_file, ++SSL_CTX_use_gm_cert_and_key, SSL_use_gm_cert_and_key + - load certificate and key data + + =head1 SYNOPSIS +@@ -26,6 +31,13 @@ SSL_CTX_use_cert_and_key, SSL_use_cert_and_key + int SSL_use_certificate_ASN1(SSL *ssl, unsigned char *d, int len); + int SSL_use_certificate_file(SSL *ssl, const char *file, int type); + ++ int SSL_CTX_use_gm_certificate(SSL_CTX *ctx, X509 *x, int usage); ++ int SSL_CTX_use_gm_certificate_ASN1(SSL_CTX *ctx, int len, unsigned char *d, int usage); ++ int SSL_CTX_use_gm_certificate_file(SSL_CTX *ctx, const char *file, int type, int usage); ++ int SSL_use_gm_certificate(SSL *ssl, X509 *x, int usage); ++ int SSL_use_gm_certificate_ASN1(SSL *ssl, unsigned char *d, int len, int usage); ++ int SSL_use_gm_certificate_file(SSL *ssl, const char *file, int type, int usage); ++ + int SSL_CTX_use_certificate_chain_file(SSL_CTX *ctx, const char *file); + int SSL_use_certificate_chain_file(SSL *ssl, const char *file); + +@@ -43,12 +55,23 @@ SSL_CTX_use_cert_and_key, SSL_use_cert_and_key + int SSL_use_RSAPrivateKey_ASN1(SSL *ssl, unsigned char *d, long len); + int SSL_use_RSAPrivateKey_file(SSL *ssl, const char *file, int type); + ++ int SSL_CTX_use_gm_PrivateKey(SSL_CTX *ctx, EVP_PKEY *pkey, int usage); ++ int SSL_CTX_use_gm_PrivateKey_ASN1(int pk, SSL_CTX *ctx, unsigned char *d, ++ long len, int usage); ++ int SSL_CTX_use_gm_PrivateKey_file(SSL_CTX *ctx, const char *file, int type, int usage); ++ int SSL_use_gm_PrivateKey(SSL *ssl, EVP_PKEY *pkey, int usage); ++ int SSL_use_gm_PrivateKey_ASN1(int pk, SSL *ssl, unsigned char *d, long len, int usage); ++ int SSL_use_gm_PrivateKey_file(SSL *ssl, const char *file, int type, int usage); ++ + int SSL_CTX_check_private_key(const SSL_CTX *ctx); + int SSL_check_private_key(const SSL *ssl); + + int SSL_CTX_use_cert_and_key(SSL_CTX *ctx, X509 *x, EVP_PKEY *pkey, STACK_OF(X509) *chain, int override); + int SSL_use_cert_and_key(SSL *ssl, X509 *x, EVP_PKEY *pkey, STACK_OF(X509) *chain, int override); + ++ int SSL_CTX_use_gm_cert_and_key(SSL_CTX *ctx, X509 *x, EVP_PKEY *pkey, STACK_OF(X509) *chain, int override, int usage); ++ int SSL_use_gm_cert_and_key(SSL *ssl, X509 *x, EVP_PKEY *pkey, STACK_OF(X509) *chain, int override, int usage); ++ + =head1 DESCRIPTION + + These functions load the certificates and private keys into the SSL_CTX +@@ -81,6 +104,21 @@ SSL_use_certificate_file() loads the certificate from B into B. + See the NOTES section on why SSL_CTX_use_certificate_chain_file() + should be preferred. + ++SSL_CTX_use_gm_certificate() loads the certificate B into B ++and specify B. SSL_use_gm_certificate() loads B into B ++and specify B. The B should be SSL_USAGE_SIG or SSL_USAGE_ENC. ++ ++SSL_CTX_use_gm_certificate_ASN1() loads the ASN1 encoded certificate from ++the memory location B (with length B) into B and specify B, ++SSL_use_gm_certificate_ASN1() loads the ASN1 encoded certificate into B ++and specify B. ++ ++SSL_CTX_use_gm_certificate_file() loads the first certificate stored in B ++into B and specify B. The formatting B of the certificate must ++be specified from the known types SSL_FILETYPE_PEM, SSL_FILETYPE_ASN1. ++SSL_use_gm_certificate_file() loads the certificate from B into B ++and specify B. ++ + SSL_CTX_use_certificate_chain_file() loads a certificate chain from + B into B. The certificates must be in PEM format and must + be sorted starting with the subject's certificate (actual client or server +@@ -127,6 +165,22 @@ B to B. SSL_use_PrivateKey_file() adds the first private key found + in B to B; SSL_use_RSAPrivateKey_file() adds the first private + RSA key found to B. + ++SSL_CTX_use_gm_PrivateKey() adds B as private key to B and ++specify B. SSL_CTX_use_gm_PrivateKey_ASN1() adds the private key of ++type B stored at memory location B (length B) to B and ++specify B. SSL_CTX_use_gm_PrivateKey_file() adds the first private ++key found in B to B. The formatting B of the private key ++must be specified from the known types SSL_FILETYPE_PEM, SSL_FILETYPE_ASN1. ++ ++SSL_use_PrivateKey() adds B as private key to B and sprcify B. ++SSL_use_gm_PrivateKey_ASN1() adds the private key to B and sprcify B. ++SSL_use_gm_PrivateKey_file() adds the first private key found in B to B ++and sprcify B. ++ ++SSL_CTX_use_gm_cert_and_key() and SSL_use_gm_cert_and_key() assign the X.509 ++certificate B, private key B, and certificate B onto the ++corresponding B or B and specify B. ++ + SSL_CTX_check_private_key() checks the consistency of a private key with + the corresponding certificate loaded into B. If more than one + key/certificate pair (RSA/DSA) is installed, the last item installed will +diff --git a/doc/man7/ssl.pod b/doc/man7/ssl.pod +index d439860..8d7293a 100644 +--- a/doc/man7/ssl.pod ++++ b/doc/man7/ssl.pod +@@ -183,6 +183,18 @@ Constructor for the SSLv3 SSL_METHOD structure for clients. + + Constructor for the SSLv3 SSL_METHOD structure for servers. + ++=item const SSL_METHOD *B(void); ++ ++Constructor for the TLCP SSL_METHOD structure for clients, servers or both. ++ ++=item const SSL_METHOD *B(void); ++ ++Constructor for the TLCP SSL_METHOD structure for clients. ++ ++=item const SSL_METHOD *B(void); ++ ++Constructor for the TLCP SSL_METHOD structure for servers. ++ + =back + + =head2 Dealing with Ciphers +@@ -393,6 +405,12 @@ Use the file path to locate trusted CA certificates. + + =item int B(SSL_CTX *ctx, const char *file, int type); + ++=item int B(SSL_CTX *ctx, EVP_PKEY *pkey, int usage); ++ ++=item int B(int type, SSL_CTX *ctx, unsigned char *d, long len, int usage); ++ ++=item int B(SSL_CTX *ctx, const char *file, int type, int usage); ++ + =item int B(SSL_CTX *ctx, X509 *x); + + =item int B(SSL_CTX *ctx, int len, unsigned char *d); +@@ -401,6 +419,14 @@ Use the file path to locate trusted CA certificates. + + =item int B(SSL_CTX *ctx, X509 *x, EVP_PKEY *pkey, STACK_OF(X509) *chain, int override); + ++=item int B(SSL_CTX *ctx, X509 *x, int usage); ++ ++=item int B(SSL_CTX *ctx, int len, unsigned char *d, int usage); ++ ++=item int B(SSL_CTX *ctx, const char *file, int type, int usage); ++ ++=item int B(SSL_CTX *ctx, X509 *x, EVP_PKEY *pkey, STACK_OF(X509) *chain, int override, int usage); ++ + =item X509 *B(const SSL_CTX *ctx); + + =item EVP_PKEY *B(const SSL_CTX *ctx); +@@ -704,6 +730,12 @@ Returns the current handshake state. + + =item int B(SSL *ssl, const char *file, int type); + ++=item int B(SSL *ssl, EVP_PKEY *pkey, int usage); ++ ++=item int B(int type, SSL *ssl, unsigned char *d, long len, int usage); ++ ++=item int B(SSL *ssl, const char *file, int type, int usage); ++ + =item int B(SSL *ssl, X509 *x); + + =item int B(SSL *ssl, int len, unsigned char *d); +@@ -712,6 +744,14 @@ Returns the current handshake state. + + =item int B(SSL *ssl, X509 *x, EVP_PKEY *pkey, STACK_OF(X509) *chain, int override); + ++=item int B(SSL *ssl, X509 *x, int usage); ++ ++=item int B(SSL *ssl, int len, unsigned char *d, int usage); ++ ++=item int B(SSL *ssl, const char *file, int type, int usage); ++ ++=item int B(SSL *ssl, X509 *x, EVP_PKEY *pkey, STACK_OF(X509) *chain, int override, int usage); ++ + =item int B(const SSL *ssl); + + =item int B(const SSL *ssl); +diff --git a/include/crypto/sm2.h b/include/crypto/sm2.h +index a7f5548..720bdd4 100644 +--- a/include/crypto/sm2.h ++++ b/include/crypto/sm2.h +@@ -19,6 +19,7 @@ + + /* The default user id as specified in GM/T 0009-2012 */ + # define SM2_DEFAULT_USERID "1234567812345678" ++# define SM2_DEFAULT_USERID_LEN 16 + + int sm2_compute_z_digest(uint8_t *out, + const EVP_MD *digest, +diff --git a/include/crypto/sm2err.h b/include/crypto/sm2err.h +index d1c0ee2..251c4f9 100644 +--- a/include/crypto/sm2err.h ++++ b/include/crypto/sm2err.h +@@ -1,6 +1,6 @@ + /* + * Generated by util/mkerr.pl DO NOT EDIT +- * Copyright 1995-2019 The OpenSSL Project Authors. All Rights Reserved. ++ * Copyright 1995-2022 The OpenSSL Project Authors. All Rights Reserved. + * + * Licensed under the OpenSSL license (the "License"). You may not use + * this file except in compliance with the License. You can obtain a copy +@@ -8,12 +8,10 @@ + * https://www.openssl.org/source/license.html + */ + +-#ifndef OSSL_CRYPTO_SM2ERR_H +-# define OSSL_CRYPTO_SM2ERR_H ++#ifndef HEADER_SM2ERR_H ++# define HEADER_SM2ERR_H + +-# ifndef HEADER_SYMHACKS_H +-# include +-# endif ++# include + + # include + +@@ -33,6 +31,7 @@ int ERR_load_SM2_strings(void); + # define SM2_F_PKEY_SM2_DIGEST_CUSTOM 114 + # define SM2_F_PKEY_SM2_INIT 111 + # define SM2_F_PKEY_SM2_SIGN 112 ++# define SM2_F_SM2_COMPUTE_KEY 116 + # define SM2_F_SM2_COMPUTE_MSG_HASH 100 + # define SM2_F_SM2_COMPUTE_USERID_DIGEST 101 + # define SM2_F_SM2_COMPUTE_Z_DIGEST 113 +@@ -59,6 +58,7 @@ int ERR_load_SM2_strings(void); + # define SM2_R_INVALID_ENCODING 104 + # define SM2_R_INVALID_FIELD 105 + # define SM2_R_NO_PARAMETERS_SET 109 ++# define SM2_R_NO_PRIVATE_VALUE 113 + # define SM2_R_USER_ID_TOO_LARGE 106 + + # endif +diff --git a/include/openssl/dherr.h b/include/openssl/dherr.h +index b2d62eb..e7fdb21 100644 +--- a/include/openssl/dherr.h ++++ b/include/openssl/dherr.h +@@ -1,6 +1,6 @@ + /* + * Generated by util/mkerr.pl DO NOT EDIT +- * Copyright 1995-2019 The OpenSSL Project Authors. All Rights Reserved. ++ * Copyright 1995-2022 The OpenSSL Project Authors. All Rights Reserved. + * + * Licensed under the OpenSSL license (the "License"). You may not use + * this file except in compliance with the License. You can obtain a copy +@@ -11,9 +11,7 @@ + #ifndef HEADER_DHERR_H + # define HEADER_DHERR_H + +-# ifndef HEADER_SYMHACKS_H +-# include +-# endif ++# include + + # include + +@@ -36,9 +34,8 @@ int ERR_load_DH_strings(void); + # define DH_F_DH_CMS_DECRYPT 114 + # define DH_F_DH_CMS_SET_PEERKEY 115 + # define DH_F_DH_CMS_SET_SHARED_INFO 116 +-# define DH_F_DH_COMPUTE_KEY 203 +-# define DH_F_DH_GENERATE_KEY 202 +-# define DH_F_DH_GENERATE_PARAMETERS_EX 201 ++# define DH_F_DH_COMPUTE_KEY 126 ++# define DH_F_DH_GENERATE_PARAMETERS_EX 127 + # define DH_F_DH_METH_DUP 117 + # define DH_F_DH_METH_NEW 118 + # define DH_F_DH_METH_SET1_NAME 119 +@@ -76,14 +73,14 @@ int ERR_load_DH_strings(void); + # define DH_R_INVALID_PARAMETER_NID 114 + # define DH_R_INVALID_PUBKEY 102 + # define DH_R_KDF_PARAMETER_ERROR 112 +-# define DH_R_KEY_SIZE_TOO_SMALL 201 + # define DH_R_KEYS_NOT_SET 108 ++# define DH_R_KEY_SIZE_TOO_SMALL 126 + # define DH_R_MISSING_PUBKEY 125 + # define DH_R_MODULUS_TOO_LARGE 103 ++# define DH_R_NON_FIPS_METHOD 127 + # define DH_R_NOT_SUITABLE_GENERATOR 120 + # define DH_R_NO_PARAMETERS_SET 107 + # define DH_R_NO_PRIVATE_VALUE 100 +-# define DH_R_NON_FIPS_METHOD 202 + # define DH_R_PARAMETER_ENCODING_ERROR 105 + # define DH_R_PEER_KEY_ERROR 111 + # define DH_R_SHARED_INFO_ERROR 113 +diff --git a/include/openssl/dsaerr.h b/include/openssl/dsaerr.h +index 19f650a..83f1b68 100644 +--- a/include/openssl/dsaerr.h ++++ b/include/openssl/dsaerr.h +@@ -1,6 +1,6 @@ + /* + * Generated by util/mkerr.pl DO NOT EDIT +- * Copyright 1995-2019 The OpenSSL Project Authors. All Rights Reserved. ++ * Copyright 1995-2022 The OpenSSL Project Authors. All Rights Reserved. + * + * Licensed under the OpenSSL license (the "License"). You may not use + * this file except in compliance with the License. You can obtain a copy +@@ -11,9 +11,7 @@ + #ifndef HEADER_DSAERR_H + # define HEADER_DSAERR_H + +-# ifndef HEADER_SYMHACKS_H +-# include +-# endif ++# include + + # include + +@@ -29,13 +27,13 @@ int ERR_load_DSA_strings(void); + */ + # define DSA_F_DSAPARAMS_PRINT 100 + # define DSA_F_DSAPARAMS_PRINT_FP 101 +-# define DSA_F_DSA_BUILTIN_KEYGEN 202 ++# define DSA_F_DSA_BUILTIN_KEYGEN 108 + # define DSA_F_DSA_BUILTIN_PARAMGEN 125 + # define DSA_F_DSA_BUILTIN_PARAMGEN2 126 +-# define DSA_F_DSA_GENERATE_KEY 201 +-# define DSA_F_DSA_GENERATE_PARAMETERS_EX 200 + # define DSA_F_DSA_DO_SIGN 112 + # define DSA_F_DSA_DO_VERIFY 113 ++# define DSA_F_DSA_GENERATE_KEY 109 ++# define DSA_F_DSA_GENERATE_PARAMETERS_EX 110 + # define DSA_F_DSA_METH_DUP 127 + # define DSA_F_DSA_METH_NEW 128 + # define DSA_F_DSA_METH_SET1_NAME 129 +@@ -63,13 +61,13 @@ int ERR_load_DSA_strings(void); + # define DSA_R_DECODE_ERROR 104 + # define DSA_R_INVALID_DIGEST_TYPE 106 + # define DSA_R_INVALID_PARAMETERS 112 +-# define DSA_R_KEY_SIZE_INVALID 201 +-# define DSA_R_KEY_SIZE_TOO_SMALL 202 ++# define DSA_R_KEY_SIZE_INVALID 114 ++# define DSA_R_KEY_SIZE_TOO_SMALL 115 + # define DSA_R_MISSING_PARAMETERS 101 + # define DSA_R_MISSING_PRIVATE_KEY 111 + # define DSA_R_MODULUS_TOO_LARGE 103 ++# define DSA_R_NON_FIPS_DSA_METHOD 116 + # define DSA_R_NO_PARAMETERS_SET 107 +-# define DSA_R_NON_FIPS_DSA_METHOD 200 + # define DSA_R_PARAMETER_ENCODING_ERROR 105 + # define DSA_R_Q_NOT_PRIME 113 + # define DSA_R_SEED_LEN_SMALL 110 +diff --git a/include/openssl/evp.h b/include/openssl/evp.h +index 0f7fbd1..3116c1b 100644 +--- a/include/openssl/evp.h ++++ b/include/openssl/evp.h +@@ -1011,6 +1011,10 @@ const unsigned char *EVP_PKEY_get0_poly1305(const EVP_PKEY *pkey, size_t *len); + const unsigned char *EVP_PKEY_get0_siphash(const EVP_PKEY *pkey, size_t *len); + # endif + ++# ifndef OPENSSL_NO_SM2 ++int EVP_PKEY_is_sm2(EVP_PKEY *pkey); ++# endif ++ + # ifndef OPENSSL_NO_RSA + struct rsa_st; + int EVP_PKEY_set1_RSA(EVP_PKEY *pkey, struct rsa_st *key); +diff --git a/include/openssl/evperr.h b/include/openssl/evperr.h +index bfa2e68..da604ca 100644 +--- a/include/openssl/evperr.h ++++ b/include/openssl/evperr.h +@@ -1,6 +1,6 @@ + /* + * Generated by util/mkerr.pl DO NOT EDIT +- * Copyright 1995-2021 The OpenSSL Project Authors. All Rights Reserved. ++ * Copyright 1995-2022 The OpenSSL Project Authors. All Rights Reserved. + * + * Licensed under the OpenSSL license (the "License"). You may not use + * this file except in compliance with the License. You can obtain a copy +@@ -22,15 +22,15 @@ int ERR_load_EVP_strings(void); + * EVP function codes. + */ + # define EVP_F_AESNI_INIT_KEY 165 +-# define EVP_F_AESNI_XTS_INIT_KEY 233 ++# define EVP_F_AESNI_XTS_INIT_KEY 207 + # define EVP_F_AES_GCM_CTRL 196 + # define EVP_F_AES_INIT_KEY 133 + # define EVP_F_AES_OCB_CIPHER 169 + # define EVP_F_AES_T4_INIT_KEY 178 +-# define EVP_F_AES_T4_XTS_INIT_KEY 234 ++# define EVP_F_AES_T4_XTS_INIT_KEY 208 + # define EVP_F_AES_WRAP_CIPHER 170 +-# define EVP_F_AES_XTS_CIPHER 229 +-# define EVP_F_AES_XTS_INIT_KEY 235 ++# define EVP_F_AES_XTS_CIPHER 210 ++# define EVP_F_AES_XTS_INIT_KEY 209 + # define EVP_F_ALG_MODULE_INIT 177 + # define EVP_F_ARIA_CCM_INIT_KEY 175 + # define EVP_F_ARIA_GCM_CTRL 197 +@@ -141,9 +141,9 @@ int ERR_load_EVP_strings(void); + # define EVP_R_CTRL_OPERATION_NOT_IMPLEMENTED 133 + # define EVP_R_DATA_NOT_MULTIPLE_OF_BLOCK_LENGTH 138 + # define EVP_R_DECODE_ERROR 114 +-# define EVP_R_DISABLED_FOR_FIPS 200 + # define EVP_R_DIFFERENT_KEY_TYPES 101 + # define EVP_R_DIFFERENT_PARAMETERS 153 ++# define EVP_R_DISABLED_FOR_FIPS 185 + # define EVP_R_ERROR_LOADING_SECTION 165 + # define EVP_R_ERROR_SETTING_FIPS_MODE 166 + # define EVP_R_EXPECTING_AN_HMAC_KEY 174 +@@ -186,7 +186,7 @@ int ERR_load_EVP_strings(void); + # define EVP_R_PRIVATE_KEY_DECODE_ERROR 145 + # define EVP_R_PRIVATE_KEY_ENCODE_ERROR 146 + # define EVP_R_PUBLIC_KEY_NOT_RSA 106 +-# define EVP_R_TOO_LARGE 201 ++# define EVP_R_TOO_LARGE 186 + # define EVP_R_UNKNOWN_CIPHER 160 + # define EVP_R_UNKNOWN_DIGEST 161 + # define EVP_R_UNKNOWN_OPTION 169 +@@ -202,7 +202,6 @@ int ERR_load_EVP_strings(void); + # define EVP_R_UNSUPPORTED_SALT_TYPE 126 + # define EVP_R_WRAP_MODE_NOT_ALLOWED 170 + # define EVP_R_WRONG_FINAL_BLOCK_LENGTH 109 +-# define EVP_R_XTS_DATA_UNIT_IS_TOO_LARGE 191 +-# define EVP_R_XTS_DUPLICATED_KEYS 192 ++# define EVP_R_XTS_DUPLICATED_KEYS 183 + + #endif +diff --git a/include/openssl/rsaerr.h b/include/openssl/rsaerr.h +index a8bcfdf..6bbd265 100644 +--- a/include/openssl/rsaerr.h ++++ b/include/openssl/rsaerr.h +@@ -1,6 +1,6 @@ + /* + * Generated by util/mkerr.pl DO NOT EDIT +- * Copyright 1995-2019 The OpenSSL Project Authors. All Rights Reserved. ++ * Copyright 1995-2022 The OpenSSL Project Authors. All Rights Reserved. + * + * Licensed under the OpenSSL license (the "License"). You may not use + * this file except in compliance with the License. You can obtain a copy +@@ -11,9 +11,7 @@ + #ifndef HEADER_RSAERR_H + # define HEADER_RSAERR_H + +-# ifndef HEADER_SYMHACKS_H +-# include +-# endif ++# include + + # ifdef __cplusplus + extern "C" +@@ -25,7 +23,7 @@ int ERR_load_RSA_strings(void); + */ + # define RSA_F_CHECK_PADDING_MD 140 + # define RSA_F_ENCODE_PKCS1 146 +-# define RSA_F_FIPS_RSA_BUILTIN_KEYGEN 206 ++# define RSA_F_FIPS_RSA_BUILTIN_KEYGEN 168 + # define RSA_F_INT_RSA_VERIFY 145 + # define RSA_F_OLD_RSA_PRIV_DECODE 147 + # define RSA_F_PKEY_PSS_INIT 165 +@@ -40,8 +38,8 @@ int ERR_load_RSA_strings(void); + # define RSA_F_RSA_CHECK_KEY_EX 160 + # define RSA_F_RSA_CMS_DECRYPT 159 + # define RSA_F_RSA_CMS_VERIFY 158 +-# define RSA_F_RSA_GENERATE_KEY_EX 204 +-# define RSA_F_RSA_GENERATE_MULTI_PRIME_KEY 207 ++# define RSA_F_RSA_GENERATE_KEY_EX 169 ++# define RSA_F_RSA_GENERATE_MULTI_PRIME_KEY 170 + # define RSA_F_RSA_ITEM_VERIFY 148 + # define RSA_F_RSA_METH_DUP 161 + # define RSA_F_RSA_METH_NEW 162 +@@ -77,18 +75,18 @@ int ERR_load_RSA_strings(void); + # define RSA_F_RSA_PARAM_DECODE 164 + # define RSA_F_RSA_PRINT 115 + # define RSA_F_RSA_PRINT_FP 116 ++# define RSA_F_RSA_PRIVATE_DECRYPT 171 ++# define RSA_F_RSA_PRIVATE_ENCRYPT 172 + # define RSA_F_RSA_PRIV_DECODE 150 + # define RSA_F_RSA_PRIV_ENCODE 138 +-# define RSA_F_RSA_PRIVATE_DECRYPT 200 +-# define RSA_F_RSA_PRIVATE_ENCRYPT 201 + # define RSA_F_RSA_PSS_GET_PARAM 151 + # define RSA_F_RSA_PSS_TO_CTX 155 ++# define RSA_F_RSA_PUBLIC_DECRYPT 173 ++# define RSA_F_RSA_PUBLIC_ENCRYPT 174 + # define RSA_F_RSA_PUB_DECODE 139 +-# define RSA_F_RSA_PUBLIC_DECRYPT 202 +-# define RSA_F_RSA_PUBLIC_ENCRYPT 203 + # define RSA_F_RSA_SETUP_BLINDING 136 +-# define RSA_F_RSA_SET_DEFAULT_METHOD 205 +-# define RSA_F_RSA_SET_METHOD 204 ++# define RSA_F_RSA_SET_DEFAULT_METHOD 175 ++# define RSA_F_RSA_SET_METHOD 176 + # define RSA_F_RSA_SIGN 117 + # define RSA_F_RSA_SIGN_ASN1_OCTET_STRING 118 + # define RSA_F_RSA_VERIFY 119 +@@ -139,19 +137,19 @@ int ERR_load_RSA_strings(void); + # define RSA_R_KEY_PRIME_NUM_INVALID 165 + # define RSA_R_KEY_SIZE_TOO_SMALL 120 + # define RSA_R_LAST_OCTET_INVALID 134 +-# define RSA_R_MISSING_PRIVATE_KEY 179 + # define RSA_R_MGF1_DIGEST_NOT_ALLOWED 152 ++# define RSA_R_MISSING_PRIVATE_KEY 179 + # define RSA_R_MODULUS_TOO_LARGE 105 + # define RSA_R_MP_COEFFICIENT_NOT_INVERSE_OF_R 168 + # define RSA_R_MP_EXPONENT_NOT_CONGRUENT_TO_D 169 + # define RSA_R_MP_R_NOT_PRIME 170 ++# define RSA_R_NON_FIPS_RSA_METHOD 171 + # define RSA_R_NO_PUBLIC_EXPONENT 140 +-# define RSA_R_NON_FIPS_RSA_METHOD 200 + # define RSA_R_NULL_BEFORE_BLOCK_MISSING 113 + # define RSA_R_N_DOES_NOT_EQUAL_PRODUCT_OF_PRIMES 172 + # define RSA_R_N_DOES_NOT_EQUAL_P_Q 127 + # define RSA_R_OAEP_DECODING_ERROR 121 +-# define RSA_R_OPERATION_NOT_ALLOWED_IN_FIPS_MODE 201 ++# define RSA_R_OPERATION_NOT_ALLOWED_IN_FIPS_MODE 173 + # define RSA_R_OPERATION_NOT_SUPPORTED_FOR_THIS_KEYTYPE 148 + # define RSA_R_PADDING_CHECK_FAILED 114 + # define RSA_R_PKCS_DECODING_ERROR 159 +@@ -171,7 +169,7 @@ int ERR_load_RSA_strings(void); + # define RSA_R_UNSUPPORTED_LABEL_SOURCE 163 + # define RSA_R_UNSUPPORTED_MASK_ALGORITHM 153 + # define RSA_R_UNSUPPORTED_MASK_PARAMETER 154 +-# define RSA_R_UNSUPPORTED_PARAMETERS 202 ++# define RSA_R_UNSUPPORTED_PARAMETERS 174 + # define RSA_R_UNSUPPORTED_SIGNATURE_TYPE 155 + # define RSA_R_VALUE_MISSING 147 + # define RSA_R_WRONG_SIGNATURE_LENGTH 119 +diff --git a/include/openssl/sm2.h b/include/openssl/sm2.h +new file mode 100644 +index 0000000..505ebfc +--- /dev/null ++++ b/include/openssl/sm2.h +@@ -0,0 +1,20 @@ ++#ifndef HEADER_SM2_H ++# define HEADER_SM2_H ++ ++#include "ossl_typ.h" ++ ++# ifdef __cplusplus ++extern "C" { ++# endif ++ ++int SM2_compute_key(void *out, size_t outlen, ++ int server, const char *peer_uid, int peer_uid_len, ++ const char *self_uid, int self_uid_len, ++ const EC_KEY *peer_ecdhe_key, const EC_KEY *self_ecdhe_key, ++ const EC_KEY *peer_pub_key, const EC_KEY *self_eckey, ++ const EVP_MD *md); ++ ++# ifdef __cplusplus ++} ++# endif ++#endif +diff --git a/include/openssl/ssl.h b/include/openssl/ssl.h +index fd0c5a9..a6acbc4 100644 +--- a/include/openssl/ssl.h ++++ b/include/openssl/ssl.h +@@ -300,6 +300,11 @@ typedef int (*SSL_verify_cb)(int preverify_ok, X509_STORE_CTX *x509_ctx); + * Reserved value (until OpenSSL 1.2.0) 0x00000001U + * Reserved value (until OpenSSL 1.2.0) 0x00000002U + */ ++#ifndef OPENSSL_NO_TLCP ++/* Use reserved value for the position of enc cert, default is placed at the end */ ++# define SSL_OP_ENCCERT_SECOND_POSITION 0x00000002U ++#endif ++ + /* Allow initial connection to servers that don't support RI */ + # define SSL_OP_LEGACY_SERVER_CONNECT 0x00000004U + +@@ -383,8 +388,15 @@ typedef int (*SSL_verify_cb)(int preverify_ok, X509_STORE_CTX *x509_ctx); + # define SSL_OP_NO_DTLSv1 0x04000000U + # define SSL_OP_NO_DTLSv1_2 0x08000000U + ++#ifndef OPENSSL_NO_TLCP ++/* Use reserved value for TCLP(GB/T 38636-2020) */ ++# define SSL_OP_NO_TLCP 0x00000001U ++# define SSL_OP_NO_SSL_MASK (SSL_OP_NO_TLCP|SSL_OP_NO_SSLv3|\ ++ SSL_OP_NO_TLSv1|SSL_OP_NO_TLSv1_1|SSL_OP_NO_TLSv1_2|SSL_OP_NO_TLSv1_3) ++#else + # define SSL_OP_NO_SSL_MASK (SSL_OP_NO_SSLv3|\ + SSL_OP_NO_TLSv1|SSL_OP_NO_TLSv1_1|SSL_OP_NO_TLSv1_2|SSL_OP_NO_TLSv1_3) ++#endif + # define SSL_OP_NO_DTLS_MASK (SSL_OP_NO_DTLSv1|SSL_OP_NO_DTLSv1_2) + + /* Disallow all renegotiation */ +@@ -1041,6 +1053,11 @@ typedef enum { + TLS_ST_SR_END_OF_EARLY_DATA + } OSSL_HANDSHAKE_STATE; + ++#ifndef OPENSSL_NO_TLCP ++# define SSL_USAGE_SIG 0 ++# define SSL_USAGE_ENC 1 ++#endif ++ + /* + * Most of the following state values are no longer used and are defined to be + * the closest equivalent value in the current state machine code. Not all +@@ -1177,6 +1194,19 @@ DECLARE_PEM_rw(SSL_SESSION, SSL_SESSION) + /* fatal */ + # define SSL_AD_INAPPROPRIATE_FALLBACK TLS1_AD_INAPPROPRIATE_FALLBACK + # define SSL_AD_NO_APPLICATION_PROTOCOL TLS1_AD_NO_APPLICATION_PROTOCOL ++ ++/* These alert types are for TLCP */ ++# define SSL_AD_UNSUPPORTED_SITE2SITE TLCP_AD_UNSUPPORTED_SITE2SITE ++/* fatal */ ++# define SSL_AD_NO_AREA TLCP_AD_NO_AREA ++# define SSL_AD_UNSUPPORTED_AREATYPE TLCP_AD_UNSUPPORTED_AREATYPE ++# define SSL_AD_BAD_IBCPARAM TLCP_AD_BAD_IBCPARAM ++/* fatal */ ++# define SSL_AD_UNSUPPORTED_IBCPARAM TLCP_AD_UNSUPPORTED_IBCPARAM ++/* fatal */ ++# define SSL_AD_IDENTITY_NEED TLCP_AD_IDENTITY_NEED ++/* fatal */ ++ + # define SSL_ERROR_NONE 0 + # define SSL_ERROR_SSL 1 + # define SSL_ERROR_WANT_READ 2 +@@ -1560,9 +1590,20 @@ __owur int SSL_use_RSAPrivateKey(SSL *ssl, RSA *rsa); + __owur int SSL_use_RSAPrivateKey_ASN1(SSL *ssl, const unsigned char *d, + long len); + # endif ++# ifndef OPENSSL_NO_TLCP ++__owur int SSL_use_gm_PrivateKey(SSL *ssl, EVP_PKEY *pkey, int usage); ++__owur int SSL_use_gm_PrivateKey_ASN1(int pk, SSL *ssl, const unsigned char *d, ++ long len, int usage); ++# endif + __owur int SSL_use_PrivateKey(SSL *ssl, EVP_PKEY *pkey); + __owur int SSL_use_PrivateKey_ASN1(int pk, SSL *ssl, const unsigned char *d, + long len); ++# ifndef OPENSSL_NO_TLCP ++__owur int SSL_use_gm_certificate(SSL *ssl, X509 *x, int usage); ++__owur int SSL_use_gm_certificate_ASN1(SSL *ssl, const unsigned char *d, int len, int usage); ++__owur int SSL_use_gm_cert_and_key(SSL *ssl, X509 *x509, EVP_PKEY *privatekey, ++ STACK_OF(X509) *chain, int override, int usage); ++# endif + __owur int SSL_use_certificate(SSL *ssl, X509 *x); + __owur int SSL_use_certificate_ASN1(SSL *ssl, const unsigned char *d, int len); + __owur int SSL_use_cert_and_key(SSL *ssl, X509 *x509, EVP_PKEY *privatekey, +@@ -1585,6 +1626,11 @@ __owur int SSL_CTX_use_serverinfo_file(SSL_CTX *ctx, const char *file); + __owur int SSL_use_RSAPrivateKey_file(SSL *ssl, const char *file, int type); + #endif + ++#ifndef OPENSSL_NO_TLCP ++__owur int SSL_use_gm_PrivateKey_file(SSL *ssl, const char *file, int type, int usage); ++__owur int SSL_use_gm_certificate_file(SSL *ssl, const char *file, int type, int usage); ++#endif ++ + __owur int SSL_use_PrivateKey_file(SSL *ssl, const char *file, int type); + __owur int SSL_use_certificate_file(SSL *ssl, const char *file, int type); + +@@ -1592,6 +1638,13 @@ __owur int SSL_use_certificate_file(SSL *ssl, const char *file, int type); + __owur int SSL_CTX_use_RSAPrivateKey_file(SSL_CTX *ctx, const char *file, + int type); + #endif ++ ++#ifndef OPENSSL_NO_TLCP ++__owur int SSL_CTX_use_gm_PrivateKey_file(SSL_CTX *ctx, const char *file, ++ int type, int usage); ++__owur int SSL_CTX_use_gm_certificate_file(SSL_CTX *ctx, const char *file, ++ int type, int usage); ++#endif + __owur int SSL_CTX_use_PrivateKey_file(SSL_CTX *ctx, const char *file, + int type); + __owur int SSL_CTX_use_certificate_file(SSL_CTX *ctx, const char *file, +@@ -1695,6 +1748,18 @@ __owur int SSL_CTX_use_RSAPrivateKey(SSL_CTX *ctx, RSA *rsa); + __owur int SSL_CTX_use_RSAPrivateKey_ASN1(SSL_CTX *ctx, const unsigned char *d, + long len); + # endif ++ ++# ifndef OPENSSL_NO_TLCP ++__owur int SSL_CTX_use_gm_PrivateKey(SSL_CTX *ctx, EVP_PKEY *pkey, int usage); ++__owur int SSL_CTX_use_gm_PrivateKey_ASN1(int pk, SSL_CTX *ctx, ++ const unsigned char *d, long len, int usage); ++__owur int SSL_CTX_use_gm_certificate(SSL_CTX *ctx, X509 *x, int usage); ++__owur int SSL_CTX_use_gm_certificate_ASN1(SSL_CTX *ctx, int len, ++ const unsigned char *d, int usage); ++__owur int SSL_CTX_use_gm_cert_and_key(SSL_CTX *ctx, X509 *x509, EVP_PKEY *privatekey, ++ STACK_OF(X509) *chain, int override, int usage); ++# endif ++ + __owur int SSL_CTX_use_PrivateKey(SSL_CTX *ctx, EVP_PKEY *pkey); + __owur int SSL_CTX_use_PrivateKey_ASN1(int pk, SSL_CTX *ctx, + const unsigned char *d, long len); +@@ -1873,6 +1938,12 @@ __owur const SSL_METHOD *TLS_method(void); + __owur const SSL_METHOD *TLS_server_method(void); + __owur const SSL_METHOD *TLS_client_method(void); + ++#ifndef OPENSSL_NO_TLCP ++__owur const SSL_METHOD *TLCP_method(void); ++__owur const SSL_METHOD *TLCP_server_method(void); ++__owur const SSL_METHOD *TLCP_client_method(void); ++#endif ++ + # ifndef OPENSSL_NO_TLS1_METHOD + DEPRECATEDIN_1_1_0(__owur const SSL_METHOD *TLSv1_method(void)) /* TLSv1.0 */ + DEPRECATEDIN_1_1_0(__owur const SSL_METHOD *TLSv1_server_method(void)) +diff --git a/include/openssl/sslerr.h b/include/openssl/sslerr.h +index 701d61c..7742cec 100644 +--- a/include/openssl/sslerr.h ++++ b/include/openssl/sslerr.h +@@ -1,6 +1,6 @@ + /* + * Generated by util/mkerr.pl DO NOT EDIT +- * Copyright 1995-2021 The OpenSSL Project Authors. All Rights Reserved. ++ * Copyright 1995-2022 The OpenSSL Project Authors. All Rights Reserved. + * + * Licensed under the OpenSSL license (the "License"). You may not use + * this file except in compliance with the License. You can obtain a copy +@@ -11,9 +11,7 @@ + #ifndef HEADER_SSLERR_H + # define HEADER_SSLERR_H + +-# ifndef HEADER_SYMHACKS_H +-# include +-# endif ++# include + + # ifdef __cplusplus + extern "C" +@@ -171,6 +169,10 @@ int ERR_load_SSL_strings(void); + # define SSL_F_SSL_CTX_USE_CERTIFICATE 171 + # define SSL_F_SSL_CTX_USE_CERTIFICATE_ASN1 172 + # define SSL_F_SSL_CTX_USE_CERTIFICATE_FILE 173 ++# define SSL_F_SSL_CTX_USE_GM_CERTIFICATE 641 ++# define SSL_F_SSL_CTX_USE_GM_CERTIFICATE_ASN1 642 ++# define SSL_F_SSL_CTX_USE_GM_PRIVATEKEY 643 ++# define SSL_F_SSL_CTX_USE_GM_PRIVATEKEY_ASN1 644 + # define SSL_F_SSL_CTX_USE_PRIVATEKEY 174 + # define SSL_F_SSL_CTX_USE_PRIVATEKEY_ASN1 175 + # define SSL_F_SSL_CTX_USE_PRIVATEKEY_FILE 176 +@@ -197,7 +199,9 @@ int ERR_load_SSL_strings(void); + # define SSL_F_SSL_HANDSHAKE_HASH 560 + # define SSL_F_SSL_INIT_WBIO_BUFFER 184 + # define SSL_F_SSL_KEY_UPDATE 515 ++# define SSL_F_SSL_LOAD_CERT_FILE 645 + # define SSL_F_SSL_LOAD_CLIENT_CA_FILE 185 ++# define SSL_F_SSL_LOAD_PKEY_FILE 646 + # define SSL_F_SSL_LOG_MASTER_SECRET 498 + # define SSL_F_SSL_LOG_RSA_CLIENT_KEY_EXCHANGE 499 + # define SSL_F_SSL_MODULE_INIT 392 +@@ -231,11 +235,14 @@ int ERR_load_SSL_strings(void); + # define SSL_F_SSL_SET_CIPHER_LIST 271 + # define SSL_F_SSL_SET_CT_VALIDATION_CALLBACK 399 + # define SSL_F_SSL_SET_FD 192 ++# define SSL_F_SSL_SET_GM_CERT_AND_KEY 647 + # define SSL_F_SSL_SET_PKEY 193 + # define SSL_F_SSL_SET_RFD 194 + # define SSL_F_SSL_SET_SESSION 195 + # define SSL_F_SSL_SET_SESSION_ID_CONTEXT 218 + # define SSL_F_SSL_SET_SESSION_TICKET_EXT 294 ++# define SSL_F_SSL_SET_SIGN_ENC_CERT 648 ++# define SSL_F_SSL_SET_SIGN_ENC_PKEY 649 + # define SSL_F_SSL_SET_TLSEXT_MAX_FRAGMENT_LENGTH 550 + # define SSL_F_SSL_SET_WFD 196 + # define SSL_F_SSL_SHUTDOWN 224 +@@ -246,6 +253,10 @@ int ERR_load_SSL_strings(void); + # define SSL_F_SSL_USE_CERTIFICATE 198 + # define SSL_F_SSL_USE_CERTIFICATE_ASN1 199 + # define SSL_F_SSL_USE_CERTIFICATE_FILE 200 ++# define SSL_F_SSL_USE_GM_CERTIFICATE 650 ++# define SSL_F_SSL_USE_GM_CERTIFICATE_ASN1 651 ++# define SSL_F_SSL_USE_GM_PRIVATEKEY 652 ++# define SSL_F_SSL_USE_GM_PRIVATEKEY_ASN1 653 + # define SSL_F_SSL_USE_PRIVATEKEY 201 + # define SSL_F_SSL_USE_PRIVATEKEY_ASN1 202 + # define SSL_F_SSL_USE_PRIVATEKEY_FILE 203 +@@ -262,6 +273,19 @@ int ERR_load_SSL_strings(void); + # define SSL_F_SSL_WRITE_EX 433 + # define SSL_F_SSL_WRITE_INTERNAL 524 + # define SSL_F_STATE_MACHINE 353 ++# define SSL_F_TLCP_CONSTRUCT_CKE_SM2DHE 662 ++# define SSL_F_TLCP_CONSTRUCT_CKE_SM2ECC 658 ++# define SSL_F_TLCP_CONSTRUCT_CLIENT_KEY_EXCHANGE 654 ++# define SSL_F_TLCP_CONSTRUCT_SERVER_KEY_EXCHANGE 655 ++# define SSL_F_TLCP_CONSTRUCT_SKE_SM2DHE 663 ++# define SSL_F_TLCP_CONSTRUCT_SKE_SM2ECC 659 ++# define SSL_F_TLCP_DERIVE 664 ++# define SSL_F_TLCP_PROCESS_CKE_SM2DHE 665 ++# define SSL_F_TLCP_PROCESS_CKE_SM2ECC 660 ++# define SSL_F_TLCP_PROCESS_CLIENT_KEY_EXCHANGE 656 ++# define SSL_F_TLCP_PROCESS_KEY_EXCHANGE 657 ++# define SSL_F_TLCP_PROCESS_SKE_SM2DHE 666 ++# define SSL_F_TLCP_PROCESS_SKE_SM2ECC 661 + # define SSL_F_TLS12_CHECK_PEER_SIGALG 333 + # define SSL_F_TLS12_COPY_SIGALGS 533 + # define SSL_F_TLS13_CHANGE_CIPHER_STATE 440 +diff --git a/include/openssl/tls1.h b/include/openssl/tls1.h +index 76d9fda..f05382a 100644 +--- a/include/openssl/tls1.h ++++ b/include/openssl/tls1.h +@@ -24,6 +24,7 @@ extern "C" { + # define OPENSSL_TLS_SECURITY_LEVEL 1 + # endif + ++# define TLCP_VERSION 0x0101 + # define TLS1_VERSION 0x0301 + # define TLS1_1_VERSION 0x0302 + # define TLS1_2_VERSION 0x0303 +@@ -33,6 +34,9 @@ extern "C" { + /* Special value for method supporting multiple versions */ + # define TLS_ANY_VERSION 0x10000 + ++# define TLCP_VERSION_MAJOR 0x01 ++# define TLCP_VERSION_MINOR 0x01 ++ + # define TLS1_VERSION_MAJOR 0x03 + # define TLS1_VERSION_MINOR 0x01 + +@@ -73,6 +77,14 @@ extern "C" { + # define TLS1_AD_UNKNOWN_PSK_IDENTITY 115/* fatal */ + # define TLS1_AD_NO_APPLICATION_PROTOCOL 120 /* fatal */ + ++/* TLCP(GB/T 38636-2020) alerts */ ++# define TLCP_AD_UNSUPPORTED_SITE2SITE 200 /* fatal */ ++# define TLCP_AD_NO_AREA 201 ++# define TLCP_AD_UNSUPPORTED_AREATYPE 202 ++# define TLCP_AD_BAD_IBCPARAM 203 /* fatal */ ++# define TLCP_AD_UNSUPPORTED_IBCPARAM 204 /* fatal */ ++# define TLCP_AD_IDENTITY_NEED 205 /* fatal */ ++ + /* ExtensionType values from RFC3546 / RFC4366 / RFC6066 */ + # define TLSEXT_TYPE_server_name 0 + # define TLSEXT_TYPE_max_fragment_length 1 +@@ -641,6 +653,10 @@ __owur int SSL_check_chain(SSL *s, X509 *x, EVP_PKEY *pk, STACK_OF(X509) *chain) + # define TLS1_CK_RSA_PSK_WITH_ARIA_128_GCM_SHA256 0x0300C06E + # define TLS1_CK_RSA_PSK_WITH_ARIA_256_GCM_SHA384 0x0300C06F + ++/* some TLCP ciphersuites from GB/T 38636-2020 */ ++# define TLCP_CK_ECDHE_SM2_WITH_SM4_CBC_SM3 0x0300E011 ++# define TLCP_CK_ECC_SM2_WITH_SM4_CBC_SM3 0x0300E013 ++ + /* a bundle of RFC standard cipher names, generated from ssl3_ciphers[] */ + # define TLS1_RFC_RSA_WITH_AES_128_SHA "TLS_RSA_WITH_AES_128_CBC_SHA" + # define TLS1_RFC_DHE_DSS_WITH_AES_128_SHA "TLS_DHE_DSS_WITH_AES_128_CBC_SHA" +@@ -1127,6 +1143,10 @@ __owur int SSL_check_chain(SSL *s, X509 *x, EVP_PKEY *pk, STACK_OF(X509) *chain) + # define TLS1_TXT_RSA_PSK_WITH_ARIA_128_GCM_SHA256 "RSA-PSK-ARIA128-GCM-SHA256" + # define TLS1_TXT_RSA_PSK_WITH_ARIA_256_GCM_SHA384 "RSA-PSK-ARIA256-GCM-SHA384" + ++/* some TLCP ciphersuites from GB/T 38636-2020 */ ++# define TLCP_TXT_ECDHE_SM2_WITH_SM4_CBC_SM3 "ECDHE-SM4-CBC-SM3" ++# define TLCP_TXT_ECC_SM2_WITH_SM4_CBC_SM3 "ECC-SM4-CBC-SM3" ++ + # define TLS_CT_RSA_SIGN 1 + # define TLS_CT_DSS_SIGN 2 + # define TLS_CT_RSA_FIXED_DH 3 +diff --git a/include/openssl/x509.h b/include/openssl/x509.h +index 42e9eee..f6e82f1 100644 +--- a/include/openssl/x509.h ++++ b/include/openssl/x509.h +@@ -55,6 +55,10 @@ extern "C" { + # define X509v3_KU_ENCIPHER_ONLY 0x0001 + # define X509v3_KU_DECIPHER_ONLY 0x8000 + # define X509v3_KU_UNDEF 0xffff ++/* For TLCP sm2 certificates */ ++# define X509v3_KU_SM2_SIGN (X509v3_KU_DIGITAL_SIGNATURE | X509v3_KU_NON_REPUDIATION) ++# define X509v3_KU_SM2_ENC_ENCIPHERMENT (X509v3_KU_KEY_ENCIPHERMENT | X509v3_KU_DATA_ENCIPHERMENT) ++# define X509v3_KU_SM2_ENC_CIPHER_ONLY (X509v3_KU_ENCIPHER_ONLY | X509v3_KU_DECIPHER_ONLY) + + struct X509_algor_st { + ASN1_OBJECT *algorithm; +diff --git a/include/openssl/x509err.h b/include/openssl/x509err.h +index 0a84ef0..1e51e04 100644 +--- a/include/openssl/x509err.h ++++ b/include/openssl/x509err.h +@@ -1,6 +1,6 @@ + /* + * Generated by util/mkerr.pl DO NOT EDIT +- * Copyright 1995-2020 The OpenSSL Project Authors. All Rights Reserved. ++ * Copyright 1995-2022 The OpenSSL Project Authors. All Rights Reserved. + * + * Licensed under the OpenSSL license (the "License"). You may not use + * this file except in compliance with the License. You can obtain a copy +@@ -84,7 +84,7 @@ int ERR_load_X509_strings(void); + # define X509_F_X509_TO_X509_REQ 126 + # define X509_F_X509_TRUST_ADD 133 + # define X509_F_X509_TRUST_SET 141 +-# define X509_F_X509_VERIFY 161 ++# define X509_F_X509_VERIFY 166 + # define X509_F_X509_VERIFY_CERT 127 + # define X509_F_X509_VERIFY_PARAM_NEW 159 + # define X509_F_X509_VERIFY_SM2 162 +diff --git a/ssl/methods.c b/ssl/methods.c +index c5e8898..2a6cd73 100644 +--- a/ssl/methods.c ++++ b/ssl/methods.c +@@ -109,6 +109,25 @@ IMPLEMENT_tls_meth_func(TLS1_VERSION, SSL_METHOD_NO_SUITEB, SSL_OP_NO_TLSv1, + IMPLEMENT_ssl3_meth_func(sslv3_client_method, + ssl_undefined_function, ossl_statem_connect) + #endif ++/*- ++ * TLCP methods ++ */ ++#ifndef OPENSSL_NO_TLCP ++IMPLEMENT_tls_meth_func(TLCP_VERSION, 0, SSL_OP_NO_TLCP, ++ tlcp_method, ++ ossl_statem_accept, ++ ossl_statem_connect, TLCP_enc_data) ++ ++IMPLEMENT_tls_meth_func(TLCP_VERSION, 0, SSL_OP_NO_TLCP, ++ tlcp_server_method, ++ ossl_statem_accept, ++ ssl_undefined_function, TLCP_enc_data) ++ ++IMPLEMENT_tls_meth_func(TLCP_VERSION, 0, SSL_OP_NO_TLCP, ++ tlcp_client_method, ++ ssl_undefined_function, ++ ossl_statem_connect, TLCP_enc_data) ++#endif + /*- + * DTLS methods + */ +@@ -207,6 +226,23 @@ const SSL_METHOD *TLSv1_1_client_method(void) + } + # endif + ++# ifndef OPENSSL_NO_TLCP ++const SSL_METHOD *TLCP_method(void) ++{ ++ return tlcp_method(); ++} ++ ++const SSL_METHOD *TLCP_server_method(void) ++{ ++ return tlcp_server_method(); ++} ++ ++const SSL_METHOD *TLCP_client_method(void) ++{ ++ return tlcp_client_method(); ++} ++# endif ++ + # ifndef OPENSSL_NO_TLS1_METHOD + const SSL_METHOD *TLSv1_method(void) + { +diff --git a/ssl/record/ssl3_record.c b/ssl/record/ssl3_record.c +index f158544..af825b1 100644 +--- a/ssl/record/ssl3_record.c ++++ b/ssl/record/ssl3_record.c +@@ -309,7 +309,11 @@ int ssl3_get_record(SSL *s) + return -1; + } + ++#ifndef OPENSSL_NO_TLCP ++ if ((version >> 8) != SSL3_VERSION_MAJOR && (version != TLCP_VERSION)) { ++#else + if ((version >> 8) != SSL3_VERSION_MAJOR) { ++#endif + if (RECORD_LAYER_is_first_record(&s->rlayer)) { + /* Go back to start of packet, look at the five bytes + * that we have. */ +diff --git a/ssl/s3_lib.c b/ssl/s3_lib.c +index 918cab0..2bb0f54 100644 +--- a/ssl/s3_lib.c ++++ b/ssl/s3_lib.c +@@ -15,6 +15,7 @@ + #include "ssl_local.h" + #include + #include ++#include + #include + #include "internal/cryptlib.h" + +@@ -2667,6 +2668,43 @@ static SSL_CIPHER ssl3_ciphers[] = { + }, + #endif /* OPENSSL_NO_GOST */ + ++#ifndef OPENSSL_NO_TLCP ++ { ++ 1, ++ TLCP_TXT_ECDHE_SM2_WITH_SM4_CBC_SM3, ++ NULL, ++ TLCP_CK_ECDHE_SM2_WITH_SM4_CBC_SM3, ++ SSL_kSM2DHE, ++ SSL_aSM2, ++ SSL_SM4CBC, ++ SSL_SM3, ++ TLCP_VERSION, ++ TLS1_2_VERSION, ++ 0, 0, ++ SSL_HIGH, ++ SSL_HANDSHAKE_MAC_SM3 | TLS1_PRF_SM3, ++ 128, ++ 128, ++ }, ++ { ++ 1, ++ TLCP_TXT_ECC_SM2_WITH_SM4_CBC_SM3, ++ NULL, ++ TLCP_CK_ECC_SM2_WITH_SM4_CBC_SM3, ++ SSL_kSM2ECC, ++ SSL_aSM2, ++ SSL_SM4CBC, ++ SSL_SM3, ++ TLCP_VERSION, ++ TLS1_2_VERSION, ++ 0, 0, ++ SSL_HIGH, ++ SSL_HANDSHAKE_MAC_SM3 | TLS1_PRF_SM3, ++ 128, ++ 128, ++ }, ++#endif /* OPENSSL_NO_TLCP */ ++ + #ifndef OPENSSL_NO_IDEA + { + 1, +@@ -4313,6 +4351,20 @@ const SSL_CIPHER *ssl3_choose_cipher(SSL *s, STACK_OF(SSL_CIPHER) *clnt, + ret = tmp; + continue; + } ++#ifndef OPENSSL_NO_TLCP ++ /* Prefer ECC-SM4-CBC-SM3 while enabling TLCP */ ++ if (!(s->options & SSL_OP_NO_TLCP)) { ++ const SSL_CIPHER *tmp = sk_SSL_CIPHER_value(allow, ii); ++ ++ if (tmp->id == TLCP_CK_ECC_SM2_WITH_SM4_CBC_SM3) { ++ ret = tmp; ++ break; ++ } ++ if (ret == NULL) ++ ret = tmp; ++ continue; ++ } ++#endif + ret = sk_SSL_CIPHER_value(allow, ii); + break; + } +@@ -4856,3 +4908,76 @@ EVP_PKEY *ssl_dh_to_pkey(DH *dh) + return ret; + } + #endif ++ ++#ifndef OPENSSL_NO_TLCP ++int tlcp_derive(SSL *s, EVP_PKEY *privkey, EVP_PKEY *pubkey) ++{ ++ unsigned char *pms; ++ int pmslen = SSL_MAX_MASTER_KEY_LENGTH; ++ char *id = "1234567812345678"; ++ EC_KEY *tmp_peer_pub_key, *tmp_self_priv_key; ++ EC_KEY *self_priv_key, *peer_pub_key; ++ X509 *peer_enc_cert; ++ int ret; ++ ++ if ((tmp_self_priv_key = EVP_PKEY_get0_EC_KEY(privkey)) == NULL ++ || (tmp_peer_pub_key = EVP_PKEY_get0_EC_KEY(pubkey)) == NULL) { ++ SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLCP_DERIVE, ++ ERR_R_INTERNAL_ERROR); ++ return 0; ++ } ++ ++ if (s->cert->pkeys[SSL_PKEY_SM2_ENC].privatekey == NULL) { ++ SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLCP_DERIVE, ++ ERR_R_INTERNAL_ERROR); ++ return 0; ++ } ++ ++ if ((self_priv_key = EVP_PKEY_get0_EC_KEY(s->cert->pkeys[SSL_PKEY_SM2_ENC].privatekey)) == NULL) { ++ SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLCP_DERIVE, ++ ERR_R_EC_LIB); ++ return 0; ++ } ++ ++ peer_enc_cert = ssl_get_sm2_enc_cert(s, s->session->peer_chain); ++ if (peer_enc_cert == NULL) { ++ SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLCP_DERIVE, ++ ERR_R_INTERNAL_ERROR); ++ return 0; ++ } ++ ++ if ((peer_pub_key = EVP_PKEY_get0_EC_KEY(X509_get0_pubkey(peer_enc_cert))) == NULL) { ++ SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLCP_DERIVE, ++ ERR_R_INTERNAL_ERROR); ++ return 0; ++ } ++ ++ pms = OPENSSL_malloc(pmslen); ++ if (pms == NULL) { ++ SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLCP_DERIVE, ++ ERR_R_MALLOC_FAILURE); ++ return 0; ++ } ++ ++ if (SM2_compute_key(pms, pmslen, s->server, ++ id, strlen(id), id, strlen(id), ++ tmp_peer_pub_key, tmp_self_priv_key, ++ peer_pub_key, self_priv_key, ++ EVP_sm3()) != pmslen) { ++ SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLCP_DERIVE, ++ ERR_R_INTERNAL_ERROR); ++ OPENSSL_free(pms); ++ return 0; ++ } ++ ++ if (s->server) { ++ ret = ssl_generate_master_secret(s, pms, (size_t)pmslen, 1); ++ } else { ++ s->s3->tmp.pms = pms; ++ s->s3->tmp.pmslen = pmslen; ++ ret = 1; ++ } ++ ++ return ret; ++} ++#endif +diff --git a/ssl/ssl_asn1.c b/ssl/ssl_asn1.c +index 9264364..beb3c3b 100644 +--- a/ssl/ssl_asn1.c ++++ b/ssl/ssl_asn1.c +@@ -265,7 +265,8 @@ SSL_SESSION *d2i_SSL_SESSION(SSL_SESSION **a, const unsigned char **pp, + + if ((as->ssl_version >> 8) != SSL3_VERSION_MAJOR + && (as->ssl_version >> 8) != DTLS1_VERSION_MAJOR +- && as->ssl_version != DTLS1_BAD_VER) { ++ && as->ssl_version != DTLS1_BAD_VER ++ && as->ssl_version != TLCP_VERSION) { + SSLerr(SSL_F_D2I_SSL_SESSION, SSL_R_UNSUPPORTED_SSL_VERSION); + goto err; + } +diff --git a/ssl/ssl_cert.c b/ssl/ssl_cert.c +index e7feda8..73d76a5 100644 +--- a/ssl/ssl_cert.c ++++ b/ssl/ssl_cert.c +@@ -937,18 +937,31 @@ static int ssl_security_default_callback(const SSL *s, const SSL_CTX *ctx, + return 0; + /* Level 3: forward secure ciphersuites only */ + if (level >= 3 && c->min_tls != TLS1_3_VERSION && ++#ifndef OPENSSL_NO_TLCP ++ !(c->algorithm_mkey & (SSL_kEDH | SSL_kEECDH | SSL_kSM2DHE))) ++#else + !(c->algorithm_mkey & (SSL_kEDH | SSL_kEECDH))) ++#endif + return 0; + break; + } + case SSL_SECOP_VERSION: + if (!SSL_IS_DTLS(s)) { ++#ifndef OPENSSL_NO_TLCP ++ /* SSLv3 not allowed at level 2 */ ++ if (nid <= SSL3_VERSION && nid != TLCP_VERSION && level >= 2) ++ return 0; ++ /* TLS v1.1 and above only for level 3 */ ++ if (nid <= TLS1_VERSION && nid != TLCP_VERSION && level >= 3) ++ return 0; ++#else + /* SSLv3 not allowed at level 2 */ + if (nid <= SSL3_VERSION && level >= 2) + return 0; + /* TLS v1.1 and above only for level 3 */ + if (nid <= TLS1_VERSION && level >= 3) + return 0; ++#endif + /* TLS v1.2 only for level 4 and above */ + if (nid <= TLS1_1_VERSION && level >= 4) + return 0; +@@ -1003,6 +1016,11 @@ const SSL_CERT_LOOKUP *ssl_cert_lookup_by_pkey(const EVP_PKEY *pk, size_t *pidx) + { + int nid = EVP_PKEY_id(pk); + size_t tmpidx; ++#ifndef OPENSSL_NO_TLCP ++ if (EVP_PKEY_is_sm2((EVP_PKEY *)pk)) { ++ nid = NID_sm2; ++ } ++#endif + + if (nid == NID_undef) + return NULL; +diff --git a/ssl/ssl_cert_table.h b/ssl/ssl_cert_table.h +index 0c47241..1e1864f 100644 +--- a/ssl/ssl_cert_table.h ++++ b/ssl/ssl_cert_table.h +@@ -19,5 +19,9 @@ static const SSL_CERT_LOOKUP ssl_cert_info [] = { + {NID_id_GostR3410_2012_256, SSL_aGOST12}, /* SSL_PKEY_GOST12_256 */ + {NID_id_GostR3410_2012_512, SSL_aGOST12}, /* SSL_PKEY_GOST12_512 */ + {EVP_PKEY_ED25519, SSL_aECDSA}, /* SSL_PKEY_ED25519 */ +- {EVP_PKEY_ED448, SSL_aECDSA} /* SSL_PKEY_ED448 */ ++ {EVP_PKEY_ED448, SSL_aECDSA}, /* SSL_PKEY_ED448 */ ++#ifndef OPENSSL_NO_TLCP ++ {EVP_PKEY_SM2, SSL_aSM2}, /* SSL_PKEY_SM2_SIGN */ ++ {EVP_PKEY_SM2, SSL_aSM2} /* SSL_PKEY_SM2_ENC */ ++#endif + }; +diff --git a/ssl/ssl_ciph.c b/ssl/ssl_ciph.c +index b8eba0c..b0d50b5 100644 +--- a/ssl/ssl_ciph.c ++++ b/ssl/ssl_ciph.c +@@ -43,7 +43,12 @@ + #define SSL_ENC_CHACHA_IDX 19 + #define SSL_ENC_ARIA128GCM_IDX 20 + #define SSL_ENC_ARIA256GCM_IDX 21 ++#ifndef OPENSSL_NO_TLCP ++#define SSL_ENC_SM4CBC_IDX 22 ++#define SSL_ENC_NUM_IDX 23 ++#else + #define SSL_ENC_NUM_IDX 22 ++#endif + + /* NB: make sure indices in these tables match values above */ + +@@ -76,6 +81,9 @@ static const ssl_cipher_table ssl_cipher_table_cipher[SSL_ENC_NUM_IDX] = { + {SSL_CHACHA20POLY1305, NID_chacha20_poly1305}, /* SSL_ENC_CHACHA_IDX 19 */ + {SSL_ARIA128GCM, NID_aria_128_gcm}, /* SSL_ENC_ARIA128GCM_IDX 20 */ + {SSL_ARIA256GCM, NID_aria_256_gcm}, /* SSL_ENC_ARIA256GCM_IDX 21 */ ++#ifndef OPENSSL_NO_TLCP ++ {SSL_SM4CBC, NID_sm4_cbc}, /* SSL_ENC_SM4CBC_IDX 22*/ ++#endif + }; + + static const EVP_CIPHER *ssl_cipher_methods[SSL_ENC_NUM_IDX]; +@@ -110,11 +118,17 @@ static const ssl_cipher_table ssl_cipher_table_mac[SSL_MD_NUM_IDX] = { + {SSL_GOST12_512, NID_id_GostR3411_2012_512}, /* SSL_MD_GOST12_512_IDX 8 */ + {0, NID_md5_sha1}, /* SSL_MD_MD5_SHA1_IDX 9 */ + {0, NID_sha224}, /* SSL_MD_SHA224_IDX 10 */ +- {0, NID_sha512} /* SSL_MD_SHA512_IDX 11 */ ++ {0, NID_sha512}, /* SSL_MD_SHA512_IDX 11 */ ++#ifndef OPENSSL_NO_TLCP ++ {SSL_SM3, NID_sm3} /* SSL_MD_SM3_IDX 12 */ ++#endif + }; + + static const EVP_MD *ssl_digest_methods[SSL_MD_NUM_IDX] = { +- NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL ++ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, ++#ifndef OPENSSL_NO_TLCP ++ NULL ++#endif + }; + + /* *INDENT-OFF* */ +@@ -172,7 +186,10 @@ static int ssl_mac_pkey_id[SSL_MD_NUM_IDX] = { + /* GOST2012_512 */ + EVP_PKEY_HMAC, + /* MD5/SHA1, SHA224, SHA512 */ +- NID_undef, NID_undef, NID_undef ++ NID_undef, NID_undef, NID_undef, ++#ifndef OPENSSL_NO_TLCP ++ EVP_PKEY_HMAC ++#endif + }; + + static size_t ssl_mac_secret_size[SSL_MD_NUM_IDX]; +@@ -1696,6 +1713,14 @@ char *SSL_CIPHER_description(const SSL_CIPHER *cipher, char *buf, int len) + case SSL_kANY: + kx = "any"; + break; ++#ifndef OPENSSL_NO_TLCP ++ case SSL_kSM2ECC: ++ kx = "SM2ECC"; ++ break; ++ case SSL_kSM2DHE: ++ kx = "SM2DHE"; ++ break; ++#endif + default: + kx = "unknown"; + } +@@ -1729,6 +1754,11 @@ char *SSL_CIPHER_description(const SSL_CIPHER *cipher, char *buf, int len) + case SSL_aANY: + au = "any"; + break; ++#ifndef OPENSSL_NO_TLCP ++ case SSL_aSM2: ++ au = "SM2"; ++ break; ++#endif + default: + au = "unknown"; + break; +@@ -1799,6 +1829,11 @@ char *SSL_CIPHER_description(const SSL_CIPHER *cipher, char *buf, int len) + case SSL_CHACHA20POLY1305: + enc = "CHACHA20/POLY1305(256)"; + break; ++#ifndef OPENSSL_NO_TLCP ++ case SSL_SM4CBC: ++ enc = "SM4CBC"; ++ break; ++#endif + default: + enc = "unknown"; + break; +@@ -1831,6 +1866,11 @@ char *SSL_CIPHER_description(const SSL_CIPHER *cipher, char *buf, int len) + case SSL_GOST12_512: + mac = "GOST2012"; + break; ++#ifndef OPENSSL_NO_TLCP ++ case SSL_SM3: ++ mac = "SM3"; ++ break; ++#endif + default: + mac = "unknown"; + break; +diff --git a/ssl/ssl_err.c b/ssl/ssl_err.c +index 324f2cc..8acc48d 100644 +--- a/ssl/ssl_err.c ++++ b/ssl/ssl_err.c +@@ -1,6 +1,6 @@ + /* + * Generated by util/mkerr.pl DO NOT EDIT +- * Copyright 1995-2021 The OpenSSL Project Authors. All Rights Reserved. ++ * Copyright 1995-2022 The OpenSSL Project Authors. All Rights Reserved. + * + * Licensed under the OpenSSL license (the "License"). You may not use + * this file except in compliance with the License. You can obtain a copy +@@ -113,6 +113,8 @@ static const ERR_STRING_DATA SSL_str_functs[] = { + "ossl_statem_server_post_process_message"}, + {ERR_PACK(ERR_LIB_SSL, SSL_F_OSSL_STATEM_SERVER_POST_WORK, 0), + "ossl_statem_server_post_work"}, ++ {ERR_PACK(ERR_LIB_SSL, SSL_F_OSSL_STATEM_SERVER_PRE_WORK, 0), ++ "ossl_statem_server_pre_work"}, + {ERR_PACK(ERR_LIB_SSL, SSL_F_OSSL_STATEM_SERVER_PROCESS_MESSAGE, 0), + "ossl_statem_server_process_message"}, + {ERR_PACK(ERR_LIB_SSL, SSL_F_OSSL_STATEM_SERVER_READ_TRANSITION, 0), +@@ -244,6 +246,14 @@ static const ERR_STRING_DATA SSL_str_functs[] = { + "SSL_CTX_use_certificate_ASN1"}, + {ERR_PACK(ERR_LIB_SSL, SSL_F_SSL_CTX_USE_CERTIFICATE_FILE, 0), + "SSL_CTX_use_certificate_file"}, ++ {ERR_PACK(ERR_LIB_SSL, SSL_F_SSL_CTX_USE_GM_CERTIFICATE, 0), ++ "SSL_CTX_use_gm_certificate"}, ++ {ERR_PACK(ERR_LIB_SSL, SSL_F_SSL_CTX_USE_GM_CERTIFICATE_ASN1, 0), ++ "SSL_CTX_use_gm_certificate_ASN1"}, ++ {ERR_PACK(ERR_LIB_SSL, SSL_F_SSL_CTX_USE_GM_PRIVATEKEY, 0), ++ "SSL_CTX_use_gm_PrivateKey"}, ++ {ERR_PACK(ERR_LIB_SSL, SSL_F_SSL_CTX_USE_GM_PRIVATEKEY_ASN1, 0), ++ "SSL_CTX_use_gm_PrivateKey_ASN1"}, + {ERR_PACK(ERR_LIB_SSL, SSL_F_SSL_CTX_USE_PRIVATEKEY, 0), + "SSL_CTX_use_PrivateKey"}, + {ERR_PACK(ERR_LIB_SSL, SSL_F_SSL_CTX_USE_PRIVATEKEY_ASN1, 0), +@@ -285,8 +295,10 @@ static const ERR_STRING_DATA SSL_str_functs[] = { + {ERR_PACK(ERR_LIB_SSL, SSL_F_SSL_INIT_WBIO_BUFFER, 0), + "ssl_init_wbio_buffer"}, + {ERR_PACK(ERR_LIB_SSL, SSL_F_SSL_KEY_UPDATE, 0), "SSL_key_update"}, ++ {ERR_PACK(ERR_LIB_SSL, SSL_F_SSL_LOAD_CERT_FILE, 0), "ssl_load_cert_file"}, + {ERR_PACK(ERR_LIB_SSL, SSL_F_SSL_LOAD_CLIENT_CA_FILE, 0), + "SSL_load_client_CA_file"}, ++ {ERR_PACK(ERR_LIB_SSL, SSL_F_SSL_LOAD_PKEY_FILE, 0), "ssl_load_pkey_file"}, + {ERR_PACK(ERR_LIB_SSL, SSL_F_SSL_LOG_MASTER_SECRET, 0), ""}, + {ERR_PACK(ERR_LIB_SSL, SSL_F_SSL_LOG_RSA_CLIENT_KEY_EXCHANGE, 0), + "ssl_log_rsa_client_key_exchange"}, +@@ -331,6 +343,8 @@ static const ERR_STRING_DATA SSL_str_functs[] = { + {ERR_PACK(ERR_LIB_SSL, SSL_F_SSL_SET_CT_VALIDATION_CALLBACK, 0), + "SSL_set_ct_validation_callback"}, + {ERR_PACK(ERR_LIB_SSL, SSL_F_SSL_SET_FD, 0), "SSL_set_fd"}, ++ {ERR_PACK(ERR_LIB_SSL, SSL_F_SSL_SET_GM_CERT_AND_KEY, 0), ++ "ssl_set_gm_cert_and_key"}, + {ERR_PACK(ERR_LIB_SSL, SSL_F_SSL_SET_PKEY, 0), "ssl_set_pkey"}, + {ERR_PACK(ERR_LIB_SSL, SSL_F_SSL_SET_RFD, 0), "SSL_set_rfd"}, + {ERR_PACK(ERR_LIB_SSL, SSL_F_SSL_SET_SESSION, 0), "SSL_set_session"}, +@@ -338,6 +352,10 @@ static const ERR_STRING_DATA SSL_str_functs[] = { + "SSL_set_session_id_context"}, + {ERR_PACK(ERR_LIB_SSL, SSL_F_SSL_SET_SESSION_TICKET_EXT, 0), + "SSL_set_session_ticket_ext"}, ++ {ERR_PACK(ERR_LIB_SSL, SSL_F_SSL_SET_SIGN_ENC_CERT, 0), ++ "ssl_set_sign_enc_cert"}, ++ {ERR_PACK(ERR_LIB_SSL, SSL_F_SSL_SET_SIGN_ENC_PKEY, 0), ++ "ssl_set_sign_enc_pkey"}, + {ERR_PACK(ERR_LIB_SSL, SSL_F_SSL_SET_TLSEXT_MAX_FRAGMENT_LENGTH, 0), + "SSL_set_tlsext_max_fragment_length"}, + {ERR_PACK(ERR_LIB_SSL, SSL_F_SSL_SET_WFD, 0), "SSL_set_wfd"}, +@@ -355,6 +373,14 @@ static const ERR_STRING_DATA SSL_str_functs[] = { + "SSL_use_certificate_ASN1"}, + {ERR_PACK(ERR_LIB_SSL, SSL_F_SSL_USE_CERTIFICATE_FILE, 0), + "SSL_use_certificate_file"}, ++ {ERR_PACK(ERR_LIB_SSL, SSL_F_SSL_USE_GM_CERTIFICATE, 0), ++ "SSL_use_gm_certificate"}, ++ {ERR_PACK(ERR_LIB_SSL, SSL_F_SSL_USE_GM_CERTIFICATE_ASN1, 0), ++ "SSL_use_gm_certificate_ASN1"}, ++ {ERR_PACK(ERR_LIB_SSL, SSL_F_SSL_USE_GM_PRIVATEKEY, 0), ++ "SSL_use_gm_PrivateKey"}, ++ {ERR_PACK(ERR_LIB_SSL, SSL_F_SSL_USE_GM_PRIVATEKEY_ASN1, 0), ++ "SSL_use_gm_PrivateKey_ASN1"}, + {ERR_PACK(ERR_LIB_SSL, SSL_F_SSL_USE_PRIVATEKEY, 0), "SSL_use_PrivateKey"}, + {ERR_PACK(ERR_LIB_SSL, SSL_F_SSL_USE_PRIVATEKEY_ASN1, 0), + "SSL_use_PrivateKey_ASN1"}, +@@ -380,6 +406,31 @@ static const ERR_STRING_DATA SSL_str_functs[] = { + {ERR_PACK(ERR_LIB_SSL, SSL_F_SSL_WRITE_EX, 0), "SSL_write_ex"}, + {ERR_PACK(ERR_LIB_SSL, SSL_F_SSL_WRITE_INTERNAL, 0), "ssl_write_internal"}, + {ERR_PACK(ERR_LIB_SSL, SSL_F_STATE_MACHINE, 0), "state_machine"}, ++ {ERR_PACK(ERR_LIB_SSL, SSL_F_TLCP_CONSTRUCT_CKE_SM2DHE, 0), ++ "tlcp_construct_cke_sm2dhe"}, ++ {ERR_PACK(ERR_LIB_SSL, SSL_F_TLCP_CONSTRUCT_CKE_SM2ECC, 0), ++ "tlcp_construct_cke_sm2ecc"}, ++ {ERR_PACK(ERR_LIB_SSL, SSL_F_TLCP_CONSTRUCT_CLIENT_KEY_EXCHANGE, 0), ++ "tlcp_construct_client_key_exchange"}, ++ {ERR_PACK(ERR_LIB_SSL, SSL_F_TLCP_CONSTRUCT_SERVER_KEY_EXCHANGE, 0), ++ "tlcp_construct_server_key_exchange"}, ++ {ERR_PACK(ERR_LIB_SSL, SSL_F_TLCP_CONSTRUCT_SKE_SM2DHE, 0), ++ "tlcp_construct_ske_sm2dhe"}, ++ {ERR_PACK(ERR_LIB_SSL, SSL_F_TLCP_CONSTRUCT_SKE_SM2ECC, 0), ++ "tlcp_construct_ske_sm2ecc"}, ++ {ERR_PACK(ERR_LIB_SSL, SSL_F_TLCP_DERIVE, 0), "tlcp_derive"}, ++ {ERR_PACK(ERR_LIB_SSL, SSL_F_TLCP_PROCESS_CKE_SM2DHE, 0), ++ "tlcp_process_cke_sm2dhe"}, ++ {ERR_PACK(ERR_LIB_SSL, SSL_F_TLCP_PROCESS_CKE_SM2ECC, 0), ++ "tlcp_process_cke_sm2ecc"}, ++ {ERR_PACK(ERR_LIB_SSL, SSL_F_TLCP_PROCESS_CLIENT_KEY_EXCHANGE, 0), ++ "tlcp_process_client_key_exchange"}, ++ {ERR_PACK(ERR_LIB_SSL, SSL_F_TLCP_PROCESS_KEY_EXCHANGE, 0), ++ "tlcp_process_key_exchange"}, ++ {ERR_PACK(ERR_LIB_SSL, SSL_F_TLCP_PROCESS_SKE_SM2DHE, 0), ++ "tlcp_process_ske_sm2dhe"}, ++ {ERR_PACK(ERR_LIB_SSL, SSL_F_TLCP_PROCESS_SKE_SM2ECC, 0), ++ "tlcp_process_ske_sm2ecc"}, + {ERR_PACK(ERR_LIB_SSL, SSL_F_TLS12_CHECK_PEER_SIGALG, 0), + "tls12_check_peer_sigalg"}, + {ERR_PACK(ERR_LIB_SSL, SSL_F_TLS12_COPY_SIGALGS, 0), "tls12_copy_sigalgs"}, +diff --git a/ssl/ssl_lib.c b/ssl/ssl_lib.c +index 78c4f99..3719c8c 100644 +--- a/ssl/ssl_lib.c ++++ b/ssl/ssl_lib.c +@@ -560,8 +560,14 @@ static int ssl_check_allowed_versions(int min_version, int max_version) + #ifdef OPENSSL_NO_TLS1_3 + || (min_version <= TLS1_3_VERSION && TLS1_3_VERSION <= max_version) + #endif +- ) ++ ) { ++#ifndef OPENSSL_NO_TLCP ++ if (min_version == TLCP_VERSION || max_version == TLCP_VERSION) { ++ return 1; ++ } ++#endif + return 0; ++ } + } + return 1; + } +@@ -3365,6 +3371,9 @@ void ssl_set_masks(SSL *s) + unsigned long mask_k, mask_a; + #ifndef OPENSSL_NO_EC + int have_ecc_cert, ecdsa_ok; ++#endif ++#ifndef OPENSSL_NO_TLCP ++ int tlcp_sm2_sign, tlcp_sm2_enc; + #endif + if (c == NULL) + return; +@@ -3380,14 +3389,23 @@ void ssl_set_masks(SSL *s) + dsa_sign = pvalid[SSL_PKEY_DSA_SIGN] & CERT_PKEY_VALID; + #ifndef OPENSSL_NO_EC + have_ecc_cert = pvalid[SSL_PKEY_ECC] & CERT_PKEY_VALID; ++#endif ++#ifndef OPENSSL_NO_TLCP ++ tlcp_sm2_sign = ssl_has_cert(s, SSL_PKEY_SM2_SIGN); ++ tlcp_sm2_enc = ssl_has_cert(s, SSL_PKEY_SM2_ENC); + #endif + mask_k = 0; + mask_a = 0; + + #ifdef CIPHER_DEBUG ++#ifndef OPENSSL_NO_TLCP ++ fprintf(stderr, "dht=%d re=%d rs=%d ds=%d tss=%d tse=%d\n", ++ dh_tmp, rsa_enc, rsa_sign, dsa_sign, tlcp_sm2_sign, tlcp_sm2_enc); ++#else + fprintf(stderr, "dht=%d re=%d rs=%d ds=%d\n", + dh_tmp, rsa_enc, rsa_sign, dsa_sign); + #endif ++#endif + + #ifndef OPENSSL_NO_GOST + if (ssl_has_cert(s, SSL_PKEY_GOST12_512)) { +@@ -3457,6 +3475,14 @@ void ssl_set_masks(SSL *s) + mask_k |= SSL_kECDHE; + #endif + ++#ifndef OPENSSL_NO_TLCP ++ if (tlcp_sm2_sign) ++ mask_a |= SSL_aSM2; ++ ++ if (tlcp_sm2_enc) ++ mask_k |= SSL_kSM2ECC | SSL_kSM2DHE; ++#endif ++ + #ifndef OPENSSL_NO_PSK + mask_k |= SSL_kPSK; + mask_a |= SSL_aPSK; +@@ -3786,6 +3812,11 @@ const char *ssl_protocol_to_string(int version) + case TLS1_VERSION: + return "TLSv1"; + ++#ifndef OPENSSL_NO_TLCP ++ case TLCP_VERSION: ++ return "TLCP"; ++#endif ++ + case SSL3_VERSION: + return "SSLv3"; + +@@ -5700,3 +5731,56 @@ void SSL_set_allow_early_data_cb(SSL *s, + s->allow_early_data_cb = cb; + s->allow_early_data_cb_data = arg; + } ++ ++#ifndef OPENSSL_NO_TLCP ++int ssl_is_sm2_cert(X509 *x) ++{ ++ return x && EVP_PKEY_is_sm2(X509_get0_pubkey(x)); ++} ++ ++int ssl_is_sm2_sign_usage(X509 *x) ++{ ++ return x && (X509_get_extension_flags(x) & EXFLAG_KUSAGE) && ++ (X509_get_key_usage(x) & X509v3_KU_SM2_SIGN); ++} ++ ++int ssl_is_sm2_enc_usage(X509 *x) ++{ ++ return x && (X509_get_extension_flags(x) & EXFLAG_KUSAGE) && ++ ((X509_get_key_usage(x) & X509v3_KU_SM2_ENC_ENCIPHERMENT) || ++ ((X509_get_key_usage(x) & X509v3_KU_SM2_ENC_CIPHER_ONLY) && ++ (X509_get_key_usage(x) & X509v3_KU_KEY_AGREEMENT)) ++ ); ++} ++ ++int ssl_newcipher_is_tlcp(SSL *s) ++{ ++ return s->s3->tmp.new_cipher->algorithm_mkey & (SSL_kSM2ECC | SSL_kSM2DHE); ++} ++ ++X509 *ssl_get_sm2_enc_cert(SSL *s, STACK_OF(X509) *chain) ++{ ++ X509 *x; ++ int i; ++ ++ for (i = sk_X509_num(chain) - 1; i >= 0 ; --i) { ++ x = sk_X509_value(chain, i); ++ if (ssl_is_sm2_cert(x) && ssl_is_sm2_enc_usage(x)) { ++ return x; ++ } ++ } ++ return NULL; ++} ++ ++int ssl_get_sm2_cert_id(X509 *x, size_t *id) ++{ ++ if (ssl_is_sm2_sign_usage(x) && !ssl_is_sm2_enc_usage(x)) { ++ *id = SSL_PKEY_SM2_SIGN; ++ return x; ++ } else if (!ssl_is_sm2_sign_usage(x) && ssl_is_sm2_enc_usage(x)) { ++ *id = SSL_PKEY_SM2_ENC; ++ return x; ++ } ++ return NULL; ++} ++#endif +\ No newline at end of file +diff --git a/ssl/ssl_local.h b/ssl/ssl_local.h +index a33cb9a..5caa491 100644 +--- a/ssl/ssl_local.h ++++ b/ssl/ssl_local.h +@@ -177,6 +177,13 @@ + # define SSL_kECDHEPSK 0x00000080U + # define SSL_kDHEPSK 0x00000100U + ++#ifndef OPENSSL_NO_TLCP ++/* TLCP ECC*/ ++# define SSL_kSM2ECC 0x00000800U ++/* TLCP ECDHE */ ++# define SSL_kSM2DHE 0x00001000U ++#endif ++ + /* all PSK */ + + # define SSL_PSK (SSL_kPSK | SSL_kRSAPSK | SSL_kECDHEPSK | SSL_kDHEPSK) +@@ -203,9 +210,21 @@ + # define SSL_aGOST12 0x00000080U + /* Any appropriate signature auth (for TLS 1.3 ciphersuites) */ + # define SSL_aANY 0x00000000U ++ ++#ifndef OPENSSL_NO_TLCP ++/* SM2 auth */ ++# define SSL_aSM2 0x00000100U ++#endif ++ ++#ifndef OPENSSL_NO_TLCP ++/* All bits requiring a certificate */ ++#define SSL_aCERT \ ++ (SSL_aRSA | SSL_aDSS | SSL_aECDSA | SSL_aGOST01 | SSL_aGOST12 | SSL_aSM2) ++#else + /* All bits requiring a certificate */ + #define SSL_aCERT \ + (SSL_aRSA | SSL_aDSS | SSL_aECDSA | SSL_aGOST01 | SSL_aGOST12) ++#endif + + /* Bits for algorithm_enc (symmetric encryption) */ + # define SSL_DES 0x00000001U +@@ -231,6 +250,10 @@ + # define SSL_ARIA128GCM 0x00100000U + # define SSL_ARIA256GCM 0x00200000U + ++#ifndef OPENSSL_NO_TLCP ++# define SSL_SM4CBC 0x00800000U ++#endif ++ + # define SSL_AESGCM (SSL_AES128GCM | SSL_AES256GCM) + # define SSL_AESCCM (SSL_AES128CCM | SSL_AES256CCM | SSL_AES128CCM8 | SSL_AES256CCM8) + # define SSL_AES (SSL_AES128|SSL_AES256|SSL_AESGCM|SSL_AESCCM) +@@ -253,6 +276,10 @@ + # define SSL_GOST89MAC12 0x00000100U + # define SSL_GOST12_512 0x00000200U + ++#ifndef OPENSSL_NO_TLCP ++# define SSL_SM3 0x00000400U ++#endif ++ + /* + * When adding new digest in the ssl_ciph.c and increment SSL_MD_NUM_IDX make + * sure to update this constant too +@@ -270,8 +297,12 @@ + # define SSL_MD_MD5_SHA1_IDX 9 + # define SSL_MD_SHA224_IDX 10 + # define SSL_MD_SHA512_IDX 11 ++#ifndef OPENSSL_NO_TLCP ++# define SSL_MD_SM3_IDX 12 ++# define SSL_MAX_DIGEST 13 ++#else + # define SSL_MAX_DIGEST 12 +- ++#endif + /* Bits for algorithm2 (handshake digests and other extra flags) */ + + /* Bits 0-7 are handshake MAC */ +@@ -283,6 +314,9 @@ + # define SSL_HANDSHAKE_MAC_GOST12_256 SSL_MD_GOST12_256_IDX + # define SSL_HANDSHAKE_MAC_GOST12_512 SSL_MD_GOST12_512_IDX + # define SSL_HANDSHAKE_MAC_DEFAULT SSL_HANDSHAKE_MAC_MD5_SHA1 ++#ifndef OPENSSL_NO_TLCP ++# define SSL_HANDSHAKE_MAC_SM3 SSL_MD_SM3_IDX ++#endif + + /* Bits 8-15 bits are PRF */ + # define TLS1_PRF_DGST_SHIFT 8 +@@ -293,6 +327,9 @@ + # define TLS1_PRF_GOST12_256 (SSL_MD_GOST12_256_IDX << TLS1_PRF_DGST_SHIFT) + # define TLS1_PRF_GOST12_512 (SSL_MD_GOST12_512_IDX << TLS1_PRF_DGST_SHIFT) + # define TLS1_PRF (SSL_MD_MD5_SHA1_IDX << TLS1_PRF_DGST_SHIFT) ++#ifndef OPENSSL_NO_TLCP ++# define TLS1_PRF_SM3 (SSL_MD_SM3_IDX << TLS1_PRF_DGST_SHIFT) ++#endif + + /* + * Stream MAC for GOST ciphersuites from cryptopro draft (currently this also +@@ -383,7 +420,13 @@ + # define SSL_PKEY_GOST12_512 6 + # define SSL_PKEY_ED25519 7 + # define SSL_PKEY_ED448 8 ++#ifndef OPENSSL_NO_TLCP ++# define SSL_PKEY_SM2_SIGN 9 ++# define SSL_PKEY_SM2_ENC 10 ++# define SSL_PKEY_NUM 11 ++#else + # define SSL_PKEY_NUM 9 ++#endif + + /*- + * SSL_kRSA <- RSA_ENC +@@ -2027,6 +2070,9 @@ typedef enum downgrade_en { + #define TLSEXT_SIGALG_ecdsa_secp521r1_sha512 0x0603 + #define TLSEXT_SIGALG_ecdsa_sha224 0x0303 + #define TLSEXT_SIGALG_ecdsa_sha1 0x0203 ++#ifndef OPENSSL_NO_TLCP ++#define TLSEXT_SIGALG_sm2dsa_sm3 0x0708 ++#endif + #define TLSEXT_SIGALG_rsa_pss_rsae_sha256 0x0804 + #define TLSEXT_SIGALG_rsa_pss_rsae_sha384 0x0805 + #define TLSEXT_SIGALG_rsa_pss_rsae_sha512 0x0806 +@@ -2096,6 +2142,19 @@ __owur const SSL_METHOD *dtls_bad_ver_client_method(void); + __owur const SSL_METHOD *dtlsv1_2_method(void); + __owur const SSL_METHOD *dtlsv1_2_server_method(void); + __owur const SSL_METHOD *dtlsv1_2_client_method(void); ++# ifndef OPENSSL_NO_TLCP ++__owur const SSL_METHOD *tlcp_method(void); ++__owur const SSL_METHOD *tlcp_server_method(void); ++__owur const SSL_METHOD *tlcp_client_method(void); ++ ++/* TLCP helper functions */ ++__owur int ssl_is_sm2_cert(X509 *x); ++__owur int ssl_is_sm2_sign_usage(X509 *x); ++__owur int ssl_is_sm2_enc_usage(X509 *x); ++__owur int ssl_newcipher_is_tlcp(SSL *s); ++__owur X509 *ssl_get_sm2_enc_cert(SSL *s, STACK_OF(X509) *chain); ++__owur int ssl_get_sm2_cert_id(X509 *x, size_t *id); ++# endif + + extern const SSL3_ENC_METHOD TLSv1_enc_data; + extern const SSL3_ENC_METHOD TLSv1_1_enc_data; +@@ -2104,6 +2163,9 @@ extern const SSL3_ENC_METHOD TLSv1_3_enc_data; + extern const SSL3_ENC_METHOD SSLv3_enc_data; + extern const SSL3_ENC_METHOD DTLSv1_enc_data; + extern const SSL3_ENC_METHOD DTLSv1_2_enc_data; ++# ifndef OPENSSL_NO_TLCP ++extern const SSL3_ENC_METHOD TLCP_enc_data; ++# endif + + /* + * Flags for SSL methods +@@ -2331,6 +2393,7 @@ __owur int ssl_generate_master_secret(SSL *s, unsigned char *pms, size_t pmslen, + __owur EVP_PKEY *ssl_generate_pkey(EVP_PKEY *pm); + __owur int ssl_derive(SSL *s, EVP_PKEY *privkey, EVP_PKEY *pubkey, + int genmaster); ++__owur int tlcp_derive(SSL *s, EVP_PKEY *privkey, EVP_PKEY *pubkey); + __owur EVP_PKEY *ssl_dh_to_pkey(DH *dh); + __owur unsigned int ssl_get_max_send_fragment(const SSL *ssl); + __owur unsigned int ssl_get_split_send_fragment(const SSL *ssl); +@@ -2502,6 +2565,9 @@ __owur int tls13_export_keying_material_early(SSL *s, unsigned char *out, + __owur int tls1_alert_code(int code); + __owur int tls13_alert_code(int code); + __owur int ssl3_alert_code(int code); ++# ifndef OPENSSL_NO_TLCP ++__owur int tlcp_alert_code(int code); ++# endif + + # ifndef OPENSSL_NO_EC + __owur int ssl_check_srvr_ecc_cert_and_alg(X509 *x, SSL *s); +diff --git a/ssl/ssl_rsa.c b/ssl/ssl_rsa.c +index 6457c0c..5a495ec 100644 +--- a/ssl/ssl_rsa.c ++++ b/ssl/ssl_rsa.c +@@ -19,6 +19,15 @@ + static int ssl_set_cert(CERT *c, X509 *x509); + static int ssl_set_pkey(CERT *c, EVP_PKEY *pkey); + ++#ifndef OPENSSL_NO_TLCP ++#include ++ ++static int ssl_set_sign_enc_pkey(CERT *c, EVP_PKEY *pkey, size_t id); ++static int ssl_set_sign_enc_cert(CERT *c, X509 *x, size_t id); ++static int ssl_load_pkey_file(SSL *ssl, SSL_CTX *ctx, const char *file, int type, EVP_PKEY **pkey); ++static int ssl_load_cert_file(SSL *ssl, SSL_CTX *ctx, const char *file, int type, X509 **x); ++#endif ++ + #define SYNTHV1CONTEXT (SSL_EXT_TLS1_2_AND_BELOW_ONLY \ + | SSL_EXT_CLIENT_HELLO \ + | SSL_EXT_TLS1_2_SERVER_HELLO \ +@@ -97,6 +106,99 @@ int SSL_use_certificate_ASN1(SSL *ssl, const unsigned char *d, int len) + return ret; + } + ++#ifndef OPENSSL_NO_TLCP ++static int ssl_load_cert_file(SSL *ssl, SSL_CTX *ctx, const char *file, int type, X509 **x) ++{ ++ int j; ++ BIO *in; ++ int ret = 0; ++ *x = NULL; ++ ++ in = BIO_new(BIO_s_file()); ++ if (in == NULL) { ++ SSLerr(SSL_F_SSL_LOAD_CERT_FILE, ERR_R_BUF_LIB); ++ goto end; ++ } ++ ++ if (BIO_read_filename(in, file) <= 0) { ++ SSLerr(SSL_F_SSL_LOAD_CERT_FILE, ERR_R_SYS_LIB); ++ goto end; ++ } ++ if (type == SSL_FILETYPE_ASN1) { ++ j = ERR_R_ASN1_LIB; ++ *x = d2i_X509_bio(in, NULL); ++ } else if (type == SSL_FILETYPE_PEM) { ++ j = ERR_R_PEM_LIB; ++ pem_password_cb *cb = (ssl != NULL) ? ssl->default_passwd_callback : ++ ctx->default_passwd_callback; ++ void *userdata = (ssl != NULL) ? ssl->default_passwd_callback_userdata : ++ ctx->default_passwd_callback_userdata; ++ *x = PEM_read_bio_X509(in, NULL, cb, userdata); ++ } else { ++ SSLerr(SSL_F_SSL_LOAD_CERT_FILE, SSL_R_BAD_SSL_FILETYPE); ++ goto end; ++ } ++ ++ if (*x == NULL) { ++ SSLerr(SSL_F_SSL_LOAD_CERT_FILE, j); ++ goto end; ++ } ++ ret = 1; ++end: ++ BIO_free(in); ++ return ret; ++} ++ ++int SSL_use_gm_certificate(SSL *ssl, X509 *x, int usage) ++{ ++ int rv; ++ if (x == NULL) { ++ SSLerr(SSL_F_SSL_USE_GM_CERTIFICATE, ERR_R_PASSED_NULL_PARAMETER); ++ return 0; ++ } ++ rv = ssl_security_cert(ssl, NULL, x, 0, 1); ++ if (rv != 1) { ++ SSLerr(SSL_F_SSL_USE_GM_CERTIFICATE, rv); ++ return 0; ++ } ++ if (usage == SSL_USAGE_SIG) { ++ return ssl_set_sign_enc_cert(ssl->cert, x, SSL_PKEY_SM2_SIGN); ++ } else if (usage == SSL_USAGE_ENC) { ++ return ssl_set_sign_enc_cert(ssl->cert, x, SSL_PKEY_SM2_ENC); ++ } ++ SSLerr(SSL_F_SSL_USE_GM_CERTIFICATE, ERR_R_PASSED_INVALID_ARGUMENT); ++ return 0; ++} ++ ++int SSL_use_gm_certificate_ASN1(SSL *ssl, const unsigned char *d, int len, int usage) ++{ ++ X509 *x; ++ int ret; ++ ++ x = d2i_X509(NULL, &d, (long)len); ++ if (x == NULL) { ++ SSLerr(SSL_F_SSL_USE_GM_CERTIFICATE_ASN1, ERR_R_ASN1_LIB); ++ return 0; ++ } ++ ++ ret = SSL_use_gm_certificate(ssl, x, usage); ++ X509_free(x); ++ return ret; ++} ++ ++int SSL_use_gm_certificate_file(SSL *ssl, const char *file, int type, int usage) ++{ ++ int ret; ++ X509 *x = NULL; ++ ret = ssl_load_cert_file(ssl, NULL, file, type, &x); ++ if (ret == 1) { ++ ret = SSL_use_gm_certificate(ssl, x, usage); ++ } ++ X509_free(x); ++ return ret; ++} ++#endif ++ + #ifndef OPENSSL_NO_RSA + int SSL_use_RSAPrivateKey(SSL *ssl, RSA *rsa) + { +@@ -162,6 +264,50 @@ static int ssl_set_pkey(CERT *c, EVP_PKEY *pkey) + return 1; + } + ++#ifndef OPENSSL_NO_TLCP ++int ssl_set_sign_enc_pkey(CERT *c, EVP_PKEY *pkey, size_t id) ++{ ++ if (id != SSL_PKEY_SM2_SIGN && id != SSL_PKEY_SM2_ENC) { ++ SSLerr(SSL_F_SSL_SET_SIGN_ENC_PKEY, ERR_R_PASSED_INVALID_ARGUMENT); ++ return 0; ++ } ++ ++ if (EVP_PKEY_is_sm2(pkey) == 0) { ++ SSLerr(SSL_F_SSL_SET_SIGN_ENC_PKEY, SSL_R_UNKNOWN_PKEY_TYPE); ++ return 0; ++ } ++ ++ if (c->pkeys[id].x509 != NULL) { ++ EVP_PKEY *pktmp; ++ pktmp = X509_get0_pubkey(c->pkeys[id].x509); ++ if (pktmp == NULL) { ++ SSLerr(SSL_F_SSL_SET_SIGN_ENC_PKEY, ERR_R_MALLOC_FAILURE); ++ return 0; ++ } ++ /* ++ * The return code from EVP_PKEY_copy_parameters is deliberately ++ * ignored. Some EVP_PKEY types cannot do this. ++ */ ++ EVP_PKEY_copy_parameters(pktmp, pkey); ++ ERR_clear_error(); ++ ++ if (!X509_check_private_key(c->pkeys[id].x509, pkey)) { ++ X509_free(c->pkeys[id].x509); ++ c->pkeys[id].x509 = NULL; ++ return 0; ++ } ++ } ++ ++ EVP_PKEY_free(c->pkeys[id].privatekey); ++ EVP_PKEY_up_ref(pkey); ++ c->pkeys[id].privatekey = pkey; ++ if (id != SSL_PKEY_SM2_ENC) { ++ c->key = &(c->pkeys[id]); ++ } ++ return 1; ++} ++#endif ++ + #ifndef OPENSSL_NO_RSA + int SSL_use_RSAPrivateKey_file(SSL *ssl, const char *file, int type) + { +@@ -228,6 +374,17 @@ int SSL_use_PrivateKey(SSL *ssl, EVP_PKEY *pkey) + SSLerr(SSL_F_SSL_USE_PRIVATEKEY, ERR_R_PASSED_NULL_PARAMETER); + return 0; + } ++#ifndef OPENSSL_NO_TLCP ++ if (EVP_PKEY_is_sm2(pkey)) { ++ if (X509_check_private_key(ssl->cert->pkeys[SSL_PKEY_SM2_SIGN].x509, pkey)) { ++ return ssl_set_sign_enc_pkey(ssl->cert, pkey, SSL_PKEY_SM2_SIGN); ++ } else if (X509_check_private_key(ssl->cert->pkeys[SSL_PKEY_SM2_ENC].x509, pkey)) { ++ return ssl_set_sign_enc_pkey(ssl->cert, pkey, SSL_PKEY_SM2_ENC); ++ } ++ SSLerr(SSL_F_SSL_USE_PRIVATEKEY, ERR_R_PASSED_INVALID_ARGUMENT); ++ return 0; ++ } ++#endif + ret = ssl_set_pkey(ssl->cert, pkey); + return ret; + } +@@ -289,6 +446,94 @@ int SSL_use_PrivateKey_ASN1(int type, SSL *ssl, const unsigned char *d, + return ret; + } + ++#ifndef OPENSSL_NO_TLCP ++static int ssl_load_pkey_file(SSL *ssl, SSL_CTX *ctx, const char *file, int type, EVP_PKEY **pkey) ++{ ++ int j, ret = 0; ++ BIO *in; ++ *pkey = NULL; ++ ++ in = BIO_new(BIO_s_file()); ++ if (in == NULL) { ++ SSLerr(SSL_F_SSL_LOAD_PKEY_FILE, ERR_R_BUF_LIB); ++ goto end; ++ } ++ ++ if (BIO_read_filename(in, file) <= 0) { ++ SSLerr(SSL_F_SSL_LOAD_PKEY_FILE, ERR_R_SYS_LIB); ++ goto end; ++ } ++ if (type == SSL_FILETYPE_PEM) { ++ j = ERR_R_PEM_LIB; ++ pem_password_cb *cb = (ssl != NULL) ? ssl->default_passwd_callback : ++ ctx->default_passwd_callback; ++ void *userdata = (ssl != NULL) ? ssl->default_passwd_callback_userdata : ++ ctx->default_passwd_callback_userdata; ++ *pkey = PEM_read_bio_PrivateKey(in, NULL, cb, userdata); ++ } else if (type == SSL_FILETYPE_ASN1) { ++ j = ERR_R_ASN1_LIB; ++ *pkey = d2i_PrivateKey_bio(in, NULL); ++ } else { ++ SSLerr(SSL_F_SSL_LOAD_PKEY_FILE, SSL_R_BAD_SSL_FILETYPE); ++ goto end; ++ } ++ if (*pkey == NULL) { ++ SSLerr(SSL_F_SSL_LOAD_PKEY_FILE, j); ++ goto end; ++ } ++ ret = 1; ++end: ++ BIO_free(in); ++ return ret; ++} ++ ++int SSL_use_gm_PrivateKey(SSL *ssl, EVP_PKEY *pkey, int usage) ++{ ++ if (pkey == NULL) { ++ SSLerr(SSL_F_SSL_USE_GM_PRIVATEKEY, ERR_R_PASSED_NULL_PARAMETER); ++ return 0; ++ } ++ if (usage == SSL_USAGE_SIG) { ++ return ssl_set_sign_enc_pkey(ssl->cert, pkey, SSL_PKEY_SM2_SIGN); ++ } else if (usage == SSL_USAGE_ENC) { ++ return ssl_set_sign_enc_pkey(ssl->cert, pkey, SSL_PKEY_SM2_ENC); ++ } ++ SSLerr(SSL_F_SSL_USE_GM_PRIVATEKEY, ERR_R_PASSED_INVALID_ARGUMENT); ++ return 0; ++} ++ ++int SSL_use_gm_PrivateKey_ASN1(int type, SSL *ssl, const unsigned char *d, ++ long len, int usage) ++{ ++ int ret; ++ const unsigned char *p; ++ EVP_PKEY *pkey; ++ ++ p = d; ++ if ((pkey = d2i_PrivateKey(type, NULL, &p, (long)len)) == NULL) { ++ SSLerr(SSL_F_SSL_USE_GM_PRIVATEKEY_ASN1, ERR_R_ASN1_LIB); ++ return 0; ++ } ++ ++ ret = SSL_use_gm_PrivateKey(ssl, pkey, usage); ++ EVP_PKEY_free(pkey); ++ return ret; ++} ++ ++int SSL_use_gm_PrivateKey_file(SSL *ssl, const char *file, int type, int usage) ++{ ++ int ret; ++ EVP_PKEY *pkey = NULL; ++ ++ ret = ssl_load_pkey_file(ssl, NULL, file, type, &pkey); ++ if (ret == 1) { ++ ret = SSL_use_gm_PrivateKey(ssl, pkey, usage); ++ } ++ EVP_PKEY_free(pkey); ++ return ret; ++} ++#endif ++ + int SSL_CTX_use_certificate(SSL_CTX *ctx, X509 *x) + { + int rv; +@@ -319,6 +564,12 @@ static int ssl_set_cert(CERT *c, X509 *x) + SSLerr(SSL_F_SSL_SET_CERT, SSL_R_UNKNOWN_CERTIFICATE_TYPE); + return 0; + } ++#ifndef OPENSSL_NO_TLCP ++ if (i == SSL_PKEY_SM2_SIGN && !ssl_get_sm2_cert_id(x, &i)) { ++ SSLerr(SSL_F_SSL_SET_CERT, SSL_R_UNKNOWN_CERTIFICATE_TYPE); ++ return 0; ++ } ++#endif + #ifndef OPENSSL_NO_EC + if (i == SSL_PKEY_ECC && !EC_KEY_can_sign(EVP_PKEY_get0_EC_KEY(pkey))) { + SSLerr(SSL_F_SSL_SET_CERT, SSL_R_ECC_CERT_NOT_FOR_SIGNING); +@@ -349,7 +600,13 @@ static int ssl_set_cert(CERT *c, X509 *x) + X509_free(c->pkeys[i].x509); + X509_up_ref(x); + c->pkeys[i].x509 = x; ++#ifndef OPENSSL_NO_TLCP ++ if (i != SSL_PKEY_SM2_ENC) { ++ c->key = &(c->pkeys[i]); ++ } ++#else + c->key = &(c->pkeys[i]); ++#endif + + return 1; + } +@@ -411,6 +668,109 @@ int SSL_CTX_use_certificate_ASN1(SSL_CTX *ctx, int len, const unsigned char *d) + return ret; + } + ++#ifndef OPENSSL_NO_TLCP ++static int ssl_set_sign_enc_cert(CERT *c, X509 *x, size_t id) ++{ ++ EVP_PKEY *pkey; ++ ++ pkey = X509_get0_pubkey(x); ++ if (pkey == NULL) { ++ SSLerr(SSL_F_SSL_SET_SIGN_ENC_CERT, SSL_R_X509_LIB); ++ return 0; ++ } ++ ++ if (ssl_is_sm2_cert(x) == 0 || ++ (id == SSL_PKEY_SM2_ENC && !ssl_is_sm2_enc_usage(x)) || ++ (id == SSL_PKEY_SM2_SIGN && !ssl_is_sm2_sign_usage(x))) { ++ SSLerr(SSL_F_SSL_SET_SIGN_ENC_CERT, SSL_R_UNKNOWN_CERTIFICATE_TYPE); ++ return 0; ++ } ++ ++ if (id == SSL_PKEY_SM2_SIGN && !EC_KEY_can_sign(EVP_PKEY_get0_EC_KEY(pkey))) { ++ SSLerr(SSL_F_SSL_SET_SIGN_ENC_CERT, SSL_R_ECC_CERT_NOT_FOR_SIGNING); ++ return 0; ++ } ++ ++ if (c->pkeys[id].privatekey != NULL) { ++ /* ++ * The return code from EVP_PKEY_copy_parameters is deliberately ++ * ignored. Some EVP_PKEY types cannot do this. ++ */ ++ EVP_PKEY_copy_parameters(pkey, c->pkeys[id].privatekey); ++ ERR_clear_error(); ++ ++ if (!X509_check_private_key(x, c->pkeys[id].privatekey)) { ++ /* ++ * don't fail for a cert/key mismatch, just free current private ++ * key (when switching to a different cert & key, first this ++ * function should be used, then ssl_set_pkey ++ */ ++ EVP_PKEY_free(c->pkeys[id].privatekey); ++ c->pkeys[id].privatekey = NULL; ++ /* clear error queue */ ++ ERR_clear_error(); ++ } ++ } ++ ++ X509_free(c->pkeys[id].x509); ++ X509_up_ref(x); ++ c->pkeys[id].x509 = x; ++ if (id != SSL_PKEY_SM2_ENC) { ++ c->key = &(c->pkeys[id]); ++ } ++ return 1; ++} ++ ++int SSL_CTX_use_gm_certificate(SSL_CTX *ctx, X509 *x, int usage) ++{ ++ int rv; ++ if (x == NULL) { ++ SSLerr(SSL_F_SSL_CTX_USE_GM_CERTIFICATE, ERR_R_PASSED_NULL_PARAMETER); ++ return 0; ++ } ++ rv = ssl_security_cert(NULL, ctx, x, 0, 1); ++ if (rv != 1) { ++ SSLerr(SSL_F_SSL_CTX_USE_GM_CERTIFICATE, rv); ++ return 0; ++ } ++ if (usage == SSL_USAGE_SIG) { ++ return ssl_set_sign_enc_cert(ctx->cert, x, SSL_PKEY_SM2_SIGN); ++ } else if (usage == SSL_USAGE_ENC) { ++ return ssl_set_sign_enc_cert(ctx->cert, x, SSL_PKEY_SM2_ENC); ++ } ++ SSLerr(SSL_F_SSL_CTX_USE_GM_CERTIFICATE, ERR_R_PASSED_INVALID_ARGUMENT); ++ return 0; ++} ++ ++int SSL_CTX_use_gm_certificate_file(SSL_CTX *ctx, const char *file, int type, int usage) ++{ ++ int ret; ++ X509 *x = NULL; ++ ret = ssl_load_cert_file(NULL, ctx, file, type, &x); ++ if (ret == 1) { ++ ret = SSL_CTX_use_gm_certificate(ctx, x, usage); ++ } ++ X509_free(x); ++ return ret; ++} ++ ++int SSL_CTX_use_gm_certificate_ASN1(SSL_CTX *ctx, int len, const unsigned char *d, int usage) ++{ ++ X509 *x; ++ int ret; ++ ++ x = d2i_X509(NULL, &d, (long)len); ++ if (x == NULL) { ++ SSLerr(SSL_F_SSL_CTX_USE_GM_CERTIFICATE_ASN1, ERR_R_ASN1_LIB); ++ return 0; ++ } ++ ++ ret = SSL_CTX_use_gm_certificate(ctx, x, usage); ++ X509_free(x); ++ return ret; ++} ++#endif ++ + #ifndef OPENSSL_NO_RSA + int SSL_CTX_use_RSAPrivateKey(SSL_CTX *ctx, RSA *rsa) + { +@@ -502,6 +862,17 @@ int SSL_CTX_use_PrivateKey(SSL_CTX *ctx, EVP_PKEY *pkey) + SSLerr(SSL_F_SSL_CTX_USE_PRIVATEKEY, ERR_R_PASSED_NULL_PARAMETER); + return 0; + } ++#ifndef OPENSSL_NO_TLCP ++ if (EVP_PKEY_is_sm2(pkey)) { ++ if (X509_check_private_key(ctx->cert->pkeys[SSL_PKEY_SM2_SIGN].x509, pkey)) { ++ return ssl_set_sign_enc_pkey(ctx->cert, pkey, SSL_PKEY_SM2_SIGN); ++ } else if (X509_check_private_key(ctx->cert->pkeys[SSL_PKEY_SM2_ENC].x509, pkey)) { ++ return ssl_set_sign_enc_pkey(ctx->cert, pkey, SSL_PKEY_SM2_ENC); ++ } ++ SSLerr(SSL_F_SSL_CTX_USE_PRIVATEKEY, ERR_R_PASSED_INVALID_ARGUMENT); ++ return 0; ++ } ++#endif + return ssl_set_pkey(ctx->cert, pkey); + } + +@@ -562,6 +933,54 @@ int SSL_CTX_use_PrivateKey_ASN1(int type, SSL_CTX *ctx, + return ret; + } + ++#ifndef OPENSSL_NO_TLCP ++int SSL_CTX_use_gm_PrivateKey(SSL_CTX *ctx, EVP_PKEY *pkey, int usage) ++{ ++ if (pkey == NULL) { ++ SSLerr(SSL_F_SSL_CTX_USE_GM_PRIVATEKEY, ERR_R_PASSED_NULL_PARAMETER); ++ return 0; ++ } ++ if (usage == SSL_USAGE_SIG) { ++ return ssl_set_sign_enc_pkey(ctx->cert, pkey, SSL_PKEY_SM2_SIGN); ++ } else if (usage == SSL_USAGE_ENC) { ++ return ssl_set_sign_enc_pkey(ctx->cert, pkey, SSL_PKEY_SM2_ENC); ++ } ++ SSLerr(SSL_F_SSL_CTX_USE_GM_PRIVATEKEY, ERR_R_PASSED_INVALID_ARGUMENT); ++ return 0; ++} ++ ++int SSL_CTX_use_gm_PrivateKey_file(SSL_CTX *ctx, const char *file, int type, int usage) ++{ ++ int ret; ++ EVP_PKEY *pkey = NULL; ++ ++ ret = ssl_load_pkey_file(NULL, ctx, file, type, &pkey); ++ if (ret == 1) { ++ ret = SSL_CTX_use_gm_PrivateKey(ctx, pkey, usage); ++ } ++ EVP_PKEY_free(pkey); ++ return ret; ++} ++ ++int SSL_CTX_use_gm_PrivateKey_ASN1(int type, SSL_CTX *ctx, ++ const unsigned char *d, long len, int usage) ++{ ++ int ret; ++ const unsigned char *p; ++ EVP_PKEY *pkey; ++ ++ p = d; ++ if ((pkey = d2i_PrivateKey(type, NULL, &p, (long)len)) == NULL) { ++ SSLerr(SSL_F_SSL_CTX_USE_GM_PRIVATEKEY_ASN1, ERR_R_ASN1_LIB); ++ return 0; ++ } ++ ++ ret = SSL_CTX_use_gm_PrivateKey(ctx, pkey, usage); ++ EVP_PKEY_free(pkey); ++ return ret; ++} ++#endif ++ + /* + * Read a file that contains our certificate in "PEM" format, possibly + * followed by a sequence of CA certificates that should be sent to the peer +@@ -1073,6 +1492,12 @@ static int ssl_set_cert_and_key(SSL *ssl, SSL_CTX *ctx, X509 *x509, EVP_PKEY *pr + SSLerr(SSL_F_SSL_SET_CERT_AND_KEY, SSL_R_UNKNOWN_CERTIFICATE_TYPE); + goto out; + } ++#ifndef OPENSSL_NO_TLCP ++ if (i == SSL_PKEY_SM2_SIGN && !ssl_get_sm2_cert_id(x509, &i)) { ++ SSLerr(SSL_F_SSL_SET_CERT_AND_KEY, SSL_R_UNKNOWN_CERTIFICATE_TYPE); ++ return 0; ++ } ++#endif + + if (!override && (c->pkeys[i].x509 != NULL + || c->pkeys[i].privatekey != NULL +@@ -1101,7 +1526,13 @@ static int ssl_set_cert_and_key(SSL *ssl, SSL_CTX *ctx, X509 *x509, EVP_PKEY *pr + EVP_PKEY_up_ref(privatekey); + c->pkeys[i].privatekey = privatekey; + ++#ifndef OPENSSL_NO_TLCP ++ if (i != SSL_PKEY_SM2_ENC) { ++ c->key = &(c->pkeys[i]); ++ } ++#else + c->key = &(c->pkeys[i]); ++#endif + + ret = 1; + out: +@@ -1120,3 +1551,113 @@ int SSL_CTX_use_cert_and_key(SSL_CTX *ctx, X509 *x509, EVP_PKEY *privatekey, + { + return ssl_set_cert_and_key(NULL, ctx, x509, privatekey, chain, override); + } ++ ++#ifndef OPENSSL_NO_TLCP ++static int ssl_set_gm_cert_and_key(SSL *ssl, SSL_CTX *ctx, X509 *x509, EVP_PKEY *privatekey, ++ STACK_OF(X509) *chain, int override, int usage) ++{ ++ int ret = 0; ++ size_t id; ++ int j; ++ int rv; ++ CERT *c = ssl != NULL ? ssl->cert : ctx->cert; ++ STACK_OF(X509) *dup_chain = NULL; ++ EVP_PKEY *pubkey = NULL; ++ ++ /* Do all security checks before anything else */ ++ rv = ssl_security_cert(ssl, ctx, x509, 0, 1); ++ if (rv != 1) { ++ SSLerr(SSL_F_SSL_SET_GM_CERT_AND_KEY, rv); ++ goto out; ++ } ++ for (j = 0; j < sk_X509_num(chain); j++) { ++ rv = ssl_security_cert(ssl, ctx, sk_X509_value(chain, j), 0, 0); ++ if (rv != 1) { ++ SSLerr(SSL_F_SSL_SET_GM_CERT_AND_KEY, rv); ++ goto out; ++ } ++ } ++ ++ pubkey = X509_get_pubkey(x509); /* bumps reference */ ++ if (pubkey == NULL) ++ goto out; ++ if (privatekey == NULL) { ++ privatekey = pubkey; ++ } else { ++ /* For RSA, which has no parameters, missing returns 0 */ ++ if (EVP_PKEY_missing_parameters(privatekey)) { ++ if (EVP_PKEY_missing_parameters(pubkey)) { ++ /* nobody has parameters? - error */ ++ SSLerr(SSL_F_SSL_SET_GM_CERT_AND_KEY, SSL_R_MISSING_PARAMETERS); ++ goto out; ++ } else { ++ /* copy to privatekey from pubkey */ ++ EVP_PKEY_copy_parameters(privatekey, pubkey); ++ } ++ } else if (EVP_PKEY_missing_parameters(pubkey)) { ++ /* copy to pubkey from privatekey */ ++ EVP_PKEY_copy_parameters(pubkey, privatekey); ++ } /* else both have parameters */ ++ ++ /* check that key <-> cert match */ ++ if (EVP_PKEY_cmp(pubkey, privatekey) != 1) { ++ SSLerr(SSL_F_SSL_SET_GM_CERT_AND_KEY, SSL_R_PRIVATE_KEY_MISMATCH); ++ goto out; ++ } ++ } ++ if (usage == SSL_USAGE_SIG) { ++ id = SSL_PKEY_SM2_SIGN; ++ } else if (usage == SSL_USAGE_ENC) { ++ id = SSL_PKEY_SM2_ENC; ++ } else { ++ SSLerr(SSL_F_SSL_SET_GM_CERT_AND_KEY, ERR_R_PASSED_INVALID_ARGUMENT); ++ goto out; ++ } ++ ++ if (!override && (c->pkeys[id].x509 != NULL ++ || c->pkeys[id].privatekey != NULL ++ || c->pkeys[id].chain != NULL)) { ++ /* No override, and something already there */ ++ SSLerr(SSL_F_SSL_SET_GM_CERT_AND_KEY, SSL_R_NOT_REPLACING_CERTIFICATE); ++ goto out; ++ } ++ ++ if (chain != NULL) { ++ dup_chain = X509_chain_up_ref(chain); ++ if (dup_chain == NULL) { ++ SSLerr(SSL_F_SSL_SET_GM_CERT_AND_KEY, ERR_R_MALLOC_FAILURE); ++ goto out; ++ } ++ } ++ ++ sk_X509_pop_free(c->pkeys[id].chain, X509_free); ++ c->pkeys[id].chain = dup_chain; ++ ++ X509_free(c->pkeys[id].x509); ++ X509_up_ref(x509); ++ c->pkeys[id].x509 = x509; ++ ++ EVP_PKEY_free(c->pkeys[id].privatekey); ++ EVP_PKEY_up_ref(privatekey); ++ c->pkeys[id].privatekey = privatekey; ++ if (id != SSL_PKEY_SM2_ENC) { ++ c->key = &(c->pkeys[id]); ++ } ++ ret = 1; ++ out: ++ EVP_PKEY_free(pubkey); ++ return ret; ++} ++ ++int SSL_use_gm_cert_and_key(SSL *ssl, X509 *x509, EVP_PKEY *privatekey, ++ STACK_OF(X509) *chain, int override, int usage) ++{ ++ return ssl_set_gm_cert_and_key(ssl, NULL, x509, privatekey, chain, override, usage); ++} ++ ++int SSL_CTX_use_gm_cert_and_key(SSL_CTX *ctx, X509 *x509, EVP_PKEY *privatekey, ++ STACK_OF(X509) *chain, int override, int usage) ++{ ++ return ssl_set_gm_cert_and_key(NULL, ctx, x509, privatekey, chain, override, usage); ++} ++#endif +\ No newline at end of file +diff --git a/ssl/ssl_sess.c b/ssl/ssl_sess.c +index cda6b7c..fb354e6 100644 +--- a/ssl/ssl_sess.c ++++ b/ssl/ssl_sess.c +@@ -283,6 +283,9 @@ int ssl_generate_session_id(SSL *s, SSL_SESSION *ss) + GEN_SESSION_CB cb = def_generate_session_id; + + switch (s->version) { ++#ifndef OPENSSL_NO_TLCP ++ case TLCP_VERSION: ++#endif + case SSL3_VERSION: + case TLS1_VERSION: + case TLS1_1_VERSION: +diff --git a/ssl/ssl_stat.c b/ssl/ssl_stat.c +index ca51c03..1750bdb 100644 +--- a/ssl/ssl_stat.c ++++ b/ssl/ssl_stat.c +@@ -312,6 +312,20 @@ const char *SSL_alert_desc_string(int value) + return "BH"; + case TLS1_AD_UNKNOWN_PSK_IDENTITY: + return "UP"; ++#ifndef OPENSSL_NO_TLCP ++ case TLCP_AD_UNSUPPORTED_SITE2SITE: ++ return "U2"; ++ case TLCP_AD_NO_AREA: ++ return "NA"; ++ case TLCP_AD_UNSUPPORTED_AREATYPE: ++ return "AT"; ++ case TLCP_AD_BAD_IBCPARAM: ++ return "BI"; ++ case TLCP_AD_UNSUPPORTED_IBCPARAM: ++ return "UI"; ++ case TLCP_AD_IDENTITY_NEED: ++ return "IN"; ++#endif + default: + return "UK"; + } +@@ -382,6 +396,20 @@ const char *SSL_alert_desc_string_long(int value) + return "unknown PSK identity"; + case TLS1_AD_NO_APPLICATION_PROTOCOL: + return "no application protocol"; ++#ifndef OPENSSL_NO_TLCP ++ case TLCP_AD_UNSUPPORTED_SITE2SITE: ++ return "unsupported site2site"; ++ case TLCP_AD_NO_AREA: ++ return "no area"; ++ case TLCP_AD_UNSUPPORTED_AREATYPE: ++ return "unsupported areatype"; ++ case TLCP_AD_BAD_IBCPARAM: ++ return "bad ibcparam"; ++ case TLCP_AD_UNSUPPORTED_IBCPARAM: ++ return "unsupported ibcparam"; ++ case TLCP_AD_IDENTITY_NEED: ++ return "identity need"; ++#endif + default: + return "unknown"; + } +diff --git a/ssl/statem/extensions.c b/ssl/statem/extensions.c +index 0f39275..a03b6cd 100644 +--- a/ssl/statem/extensions.c ++++ b/ssl/statem/extensions.c +@@ -1056,7 +1056,11 @@ static int final_ec_pt_formats(SSL *s, unsigned int context, int sent) + && s->ext.ecpointformats_len > 0 + && s->ext.peer_ecpointformats != NULL + && s->ext.peer_ecpointformats_len > 0 +- && ((alg_k & SSL_kECDHE) || (alg_a & SSL_aECDSA))) { ++ && ((alg_k & SSL_kECDHE) || (alg_a & SSL_aECDSA) ++#ifndef OPENSSL_NO_TLCP ++ || (alg_k & SSL_kSM2DHE) || (alg_a & SSL_aSM2) ++#endif ++ )) { + /* we are using an ECC cipher */ + size_t i; + unsigned char *list = s->ext.peer_ecpointformats; +diff --git a/ssl/statem/extensions_clnt.c b/ssl/statem/extensions_clnt.c +index 9d38ac2..23ca93e 100644 +--- a/ssl/statem/extensions_clnt.c ++++ b/ssl/statem/extensions_clnt.c +@@ -132,6 +132,9 @@ static int use_ecc(SSL *s) + alg_a = c->algorithm_auth; + if ((alg_k & (SSL_kECDHE | SSL_kECDHEPSK)) + || (alg_a & SSL_aECDSA) ++#ifndef OPENSSL_NO_TLCP ++ || (alg_k & SSL_kSM2DHE) || (alg_a & SSL_aSM2) ++#endif + || c->min_tls >= TLS1_3_VERSION) { + ret = 1; + break; +diff --git a/ssl/statem/extensions_srvr.c b/ssl/statem/extensions_srvr.c +index 04f64f8..7c5e3bf 100644 +--- a/ssl/statem/extensions_srvr.c ++++ b/ssl/statem/extensions_srvr.c +@@ -1386,7 +1386,11 @@ EXT_RETURN tls_construct_stoc_ec_pt_formats(SSL *s, WPACKET *pkt, + { + unsigned long alg_k = s->s3->tmp.new_cipher->algorithm_mkey; + unsigned long alg_a = s->s3->tmp.new_cipher->algorithm_auth; +- int using_ecc = ((alg_k & SSL_kECDHE) || (alg_a & SSL_aECDSA)) ++ int using_ecc = ((alg_k & SSL_kECDHE) || (alg_a & SSL_aECDSA) ++#ifndef OPENSSL_NO_TLCP ++ || (alg_k & SSL_kSM2DHE) || (alg_a & SSL_aSM2) ++#endif ++ ) + && (s->ext.peer_ecpointformats != NULL); + const unsigned char *plist; + size_t plistlen; +diff --git a/ssl/statem/statem.c b/ssl/statem/statem.c +index 20f5bd5..d1fc2cc 100644 +--- a/ssl/statem/statem.c ++++ b/ssl/statem/statem.c +@@ -361,7 +361,11 @@ static int state_machine(SSL *s, int server) + goto end; + } + } else { ++#ifndef OPENSSL_NO_TLCP ++ if ((s->version >> 8) != SSL3_VERSION_MAJOR && s->version != TLCP_VERSION) { ++#else + if ((s->version >> 8) != SSL3_VERSION_MAJOR) { ++#endif + SSLfatal(s, SSL_AD_NO_ALERT, SSL_F_STATE_MACHINE, + ERR_R_INTERNAL_ERROR); + goto end; +diff --git a/ssl/statem/statem_clnt.c b/ssl/statem/statem_clnt.c +index d1a3969..8631092 100644 +--- a/ssl/statem/statem_clnt.c ++++ b/ssl/statem/statem_clnt.c +@@ -61,6 +61,10 @@ static int key_exchange_expected(SSL *s) + { + long alg_k = s->s3->tmp.new_cipher->algorithm_mkey; + ++#ifndef OPENSSL_NO_TLCP ++ if (ssl_newcipher_is_tlcp(s)) ++ return 1; ++#endif + /* + * Can't skip server key exchange if this is an ephemeral + * ciphersuite or for SRP +@@ -2252,8 +2256,271 @@ static int tls_process_ske_ecdhe(SSL *s, PACKET *pkt, EVP_PKEY **pkey) + #endif + } + ++#ifndef OPENSSL_NO_TLCP ++static int tlcp_process_ske_sm2ecc(SSL *s, PACKET *pkt) ++{ ++ EVP_MD_CTX *md_ctx = NULL; ++ EVP_PKEY_CTX *pctx = NULL; ++ unsigned char *encbuf = NULL; ++ unsigned char *tbs = NULL; ++ ++ PACKET signature; ++ X509 *peer_sign_cert; ++ X509 *peer_enc_cert; ++ EVP_PKEY *peer_sign_pkey; ++ const EVP_MD *md; ++ unsigned char *tmp; ++ int rv, ebuflen, tbslen; ++ ++ rv = 0; ++ peer_sign_cert = s->session->peer; ++ peer_enc_cert = ssl_get_sm2_enc_cert(s, s->session->peer_chain); ++ if (peer_sign_cert == NULL || peer_enc_cert == NULL ++ || !ssl_is_sm2_cert(peer_sign_cert) ++ || !ssl_is_sm2_sign_usage(peer_sign_cert)) { ++ SSLfatal(s, SSL_AD_INTERNAL_ERROR, ++ SSL_F_TLCP_PROCESS_SKE_SM2ECC, ERR_R_INTERNAL_ERROR); ++ goto err; ++ } ++ ++ peer_sign_pkey = X509_get0_pubkey(peer_sign_cert); ++ if (!EVP_PKEY_set_alias_type(peer_sign_pkey, EVP_PKEY_SM2)) { ++ SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLCP_PROCESS_SKE_SM2ECC, ++ ERR_R_INTERNAL_ERROR); ++ goto err; ++ } ++ /* Get the signature algorithm according to the peer sign key */ ++ if (SSL_USE_SIGALGS(s)) { ++ unsigned int sigalg; ++ ++ if (!PACKET_get_net_2(pkt, &sigalg)) { ++ SSLfatal(s, SSL_AD_DECODE_ERROR, SSL_F_TLCP_PROCESS_SKE_SM2ECC, ++ SSL_R_LENGTH_TOO_SHORT); ++ goto err; ++ } ++ if (tls12_check_peer_sigalg(s, sigalg, peer_sign_pkey) <=0) { ++ /* SSLfatal() already called */ ++ goto err; ++ } ++ } else if (!tls1_set_peer_legacy_sigalg(s, peer_sign_pkey)) { ++ SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLCP_PROCESS_SKE_SM2ECC, ++ ERR_R_INTERNAL_ERROR); ++ goto err; ++ } ++ if (!tls1_lookup_md(s->s3->tmp.peer_sigalg, &md) ++ || EVP_PKEY_size(peer_sign_pkey) < 0) { ++ SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLCP_PROCESS_SKE_SM2ECC, ++ ERR_R_INTERNAL_ERROR); ++ goto err; ++ } ++ ++ if (!PACKET_get_length_prefixed_2(pkt, &signature) ++ || PACKET_remaining(pkt) != 0 ++ || PACKET_remaining(&signature) > EVP_PKEY_size(peer_sign_pkey)) { ++ SSLfatal(s, SSL_AD_DECODE_ERROR, SSL_F_TLCP_PROCESS_SKE_SM2ECC, ++ SSL_R_LENGTH_MISMATCH); ++ goto err; ++ } ++ ++ ebuflen = i2d_X509(peer_enc_cert, NULL); ++ if (ebuflen < 0) { ++ SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLCP_PROCESS_SKE_SM2ECC, ++ ERR_R_BUF_LIB); ++ goto err; ++ } ++ ++ md_ctx = EVP_MD_CTX_new(); ++ encbuf = OPENSSL_malloc(ebuflen + 3); ++ if (md_ctx == NULL || encbuf == NULL) { ++ SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLCP_PROCESS_SKE_SM2ECC, ++ ERR_R_MALLOC_FAILURE); ++ goto err; ++ } ++ /* Encode the DER encoding of an X509 structure, reserve 3 bytes for length */ ++ tmp = encbuf; ++ l2n3(ebuflen, tmp); ++ ebuflen = i2d_X509(peer_enc_cert, &tmp); ++ if (ebuflen < 0) { ++ SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLCP_PROCESS_SKE_SM2ECC, ++ ERR_R_BUF_LIB); ++ goto err; ++ } ++ ebuflen += 3; ++ ++ if (EVP_DigestVerifyInit(md_ctx, &pctx, md, NULL, peer_sign_pkey) <= 0) { ++ SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLCP_PROCESS_SKE_SM2ECC, ++ ERR_R_EVP_LIB); ++ goto err; ++ } ++ ++ tbslen = construct_key_exchange_tbs(s, &tbs, encbuf, ebuflen); ++ if (tbslen == 0) { ++ goto err; ++ } ++ ++ rv = EVP_DigestVerify(md_ctx, PACKET_data(&signature), ++ PACKET_remaining(&signature), tbs, tbslen); ++ if (rv <= 0) { ++ SSLfatal(s, SSL_AD_DECRYPT_ERROR, SSL_F_TLCP_PROCESS_SKE_SM2ECC, ++ SSL_R_BAD_SIGNATURE); ++ } ++err: ++ OPENSSL_free(encbuf); ++ OPENSSL_free(tbs); ++ EVP_MD_CTX_free(md_ctx); ++ return rv; ++} ++ ++static int tlcp_process_ske_sm2dhe(SSL *s, PACKET *pkt) ++{ ++ unsigned char *ecparams; ++ int ecparams_len; ++ PACKET pt_encoded; ++ PACKET signature; ++ EVP_PKEY *pkey; ++ EVP_PKEY_CTX *pctx; ++ EVP_PKEY_CTX *verify_ctx; ++ EVP_MD_CTX *md_ctx; ++ char *id = "1234567812345678"; ++ int ret = 0; ++ int max_sig_len; ++ ++ if(!PACKET_get_bytes(pkt, (const unsigned char**)&ecparams, 3) ++ || !PACKET_get_length_prefixed_1(pkt, &pt_encoded) ++ || !PACKET_get_length_prefixed_2(pkt, &signature) ++ ) { ++ SSLfatal(s, SSL_AD_INTERNAL_ERROR, ++ SSL_F_TLCP_PROCESS_SKE_SM2DHE, SSL_R_LENGTH_TOO_SHORT); ++ return 0; ++ } ++ ++ if (PACKET_remaining(pkt) != 0) { ++ SSLfatal(s, SSL_AD_INTERNAL_ERROR, ++ SSL_F_TLCP_PROCESS_SKE_SM2DHE, SSL_R_LENGTH_TOO_LONG); ++ return 0; ++ } ++ ++ // generate tmp pkey s->s3->peer_tmp with peer pub key ++ if ((pctx = EVP_PKEY_CTX_new_id(EVP_PKEY_EC, NULL)) == NULL) { ++ SSLfatal(s, SSL_AD_INTERNAL_ERROR, ++ SSL_F_TLCP_PROCESS_SKE_SM2DHE, ERR_R_MALLOC_FAILURE); ++ return 0; ++ } ++ ++ if (EVP_PKEY_paramgen_init(pctx) <= 0 ++ || EVP_PKEY_CTX_set_ec_paramgen_curve_nid(pctx, NID_sm2) <= 0 ++ || EVP_PKEY_paramgen(pctx, &s->s3->peer_tmp) <= 0) { ++ SSLfatal(s, SSL_AD_INTERNAL_ERROR, ++ SSL_F_TLCP_PROCESS_SKE_SM2DHE, ERR_R_EVP_LIB); ++ goto end; ++ } ++ ++ if (s->s3->peer_tmp == NULL) { ++ SSLfatal(s, SSL_AD_INTERNAL_ERROR, ++ SSL_F_TLCP_PROCESS_SKE_SM2DHE, ERR_R_INTERNAL_ERROR); ++ goto end; ++ } ++ ++ if (!EVP_PKEY_set1_tls_encodedpoint(s->s3->peer_tmp, ++ PACKET_data(&pt_encoded), PACKET_remaining(&pt_encoded))) { ++ SSLfatal(s, SSL_AD_INTERNAL_ERROR, ++ SSL_F_TLCP_PROCESS_SKE_SM2DHE, SSL_R_BAD_ECPOINT); ++ goto end; ++ } ++ ++ // verify the msg using peer sign cert's pubkey ++ if ((pkey = X509_get0_pubkey(s->session->peer)) == NULL) { ++ SSLfatal(s, SSL_AD_INTERNAL_ERROR, ++ SSL_F_TLCP_PROCESS_SKE_SM2DHE, ERR_R_INTERNAL_ERROR); ++ goto end; ++ } ++ ++ max_sig_len = EVP_PKEY_size(pkey); ++ if (PACKET_remaining(&signature) > max_sig_len) { ++ SSLfatal(s, SSL_AD_INTERNAL_ERROR, ++ SSL_F_TLCP_PROCESS_SKE_SM2DHE, SSL_R_LENGTH_TOO_LONG); ++ goto end; ++ } ++ ++ if (!EVP_PKEY_set_alias_type(pkey, EVP_PKEY_SM2)) { ++ SSLfatal(s, SSL_AD_INTERNAL_ERROR, ++ SSL_F_TLCP_PROCESS_SKE_SM2DHE, ERR_R_EVP_LIB); ++ goto end; ++ } ++ ++ if ((md_ctx = EVP_MD_CTX_new()) == NULL) { ++ SSLfatal(s, SSL_AD_INTERNAL_ERROR, ++ SSL_F_TLCP_PROCESS_SKE_SM2DHE, ERR_R_MALLOC_FAILURE); ++ goto end; ++ } ++ ++ if (EVP_DigestVerifyInit(md_ctx, &verify_ctx, EVP_sm3(), NULL, pkey) <= 0) { ++ SSLfatal(s, SSL_AD_INTERNAL_ERROR, ++ SSL_F_TLCP_PROCESS_SKE_SM2DHE, ERR_R_EVP_LIB); ++ goto end; ++ } ++ ++ if (EVP_PKEY_CTX_set1_id(verify_ctx, id, strlen(id)) <= 0) { ++ SSLfatal(s, SSL_AD_INTERNAL_ERROR, ++ SSL_F_TLCP_PROCESS_SKE_SM2DHE, ERR_R_EVP_LIB); ++ goto end; ++ } ++ ++ ecparams_len = PACKET_data(&pt_encoded) + PACKET_remaining(&pt_encoded) - ecparams; ++ if (EVP_DigestVerifyUpdate(md_ctx, s->s3->client_random, SSL3_RANDOM_SIZE) <= 0 ++ || EVP_DigestVerifyUpdate(md_ctx, s->s3->server_random, SSL3_RANDOM_SIZE) <= 0 ++ || EVP_DigestVerifyUpdate(md_ctx, ecparams, ecparams_len) <= 0) { ++ SSLfatal(s, SSL_AD_INTERNAL_ERROR, ++ SSL_F_TLCP_PROCESS_SKE_SM2DHE, ERR_R_EVP_LIB); ++ goto end; ++ } ++ ++ if (EVP_DigestVerifyFinal(md_ctx, ++ PACKET_data(&signature), PACKET_remaining(&signature)) <= 0) { ++ SSLfatal(s, SSL_AD_INTERNAL_ERROR, ++ SSL_F_TLCP_PROCESS_SKE_SM2DHE, SSL_R_BAD_SIGNATURE); ++ goto end; ++ } ++ ++ ret = 1; ++ ++end: ++ EVP_PKEY_CTX_free(pctx); ++ EVP_MD_CTX_free(md_ctx); ++ ++ return ret; ++} ++ ++static MSG_PROCESS_RETURN tlcp_process_key_exchange(SSL *s, PACKET *pkt) ++{ ++ unsigned long alg_k; ++ ++ alg_k = s->s3->tmp.new_cipher->algorithm_mkey; ++ ++ if (alg_k & SSL_kSM2ECC) { ++ if (!tlcp_process_ske_sm2ecc(s, pkt)) ++ goto err; ++ } else if (alg_k & SSL_kSM2DHE) { ++ if (!tlcp_process_ske_sm2dhe(s, pkt)) ++ goto err; ++ } else { ++ SSLfatal(s, SSL_AD_INTERNAL_ERROR, ++ SSL_F_TLCP_PROCESS_KEY_EXCHANGE, ERR_R_INTERNAL_ERROR); ++ goto err; ++ } ++ ++ return MSG_PROCESS_CONTINUE_READING; ++err: ++ return MSG_PROCESS_ERROR; ++} ++#endif ++ + MSG_PROCESS_RETURN tls_process_key_exchange(SSL *s, PACKET *pkt) + { ++#ifndef OPENSSL_NO_TLCP ++ if (ssl_newcipher_is_tlcp(s)) ++ return tlcp_process_key_exchange(s, pkt); ++#endif + long alg_k; + EVP_PKEY *pkey = NULL; + EVP_MD_CTX *md_ctx = NULL; +@@ -3315,8 +3582,169 @@ static int tls_construct_cke_srp(SSL *s, WPACKET *pkt) + #endif + } + ++#ifndef OPENSSL_NO_TLCP ++static int tlcp_construct_cke_sm2ecc(SSL *s, WPACKET *pkt) ++{ ++ unsigned char *encdata = NULL; ++ EVP_PKEY_CTX *pctx = NULL; ++ unsigned char *pms = NULL; ++ size_t pmslen = 0; ++ ++ X509 *peer_enc_cert; ++ EVP_PKEY *peer_enc_pkey; ++ size_t enclen; ++ ++ peer_enc_cert = ssl_get_sm2_enc_cert(s, s->session->peer_chain); ++ peer_enc_pkey = X509_get0_pubkey(peer_enc_cert); ++ if (peer_enc_cert == NULL || peer_enc_pkey == NULL ++ || !EVP_PKEY_set_alias_type(peer_enc_pkey, EVP_PKEY_SM2)) { ++ SSLfatal(s, SSL_AD_INTERNAL_ERROR, ++ SSL_F_TLCP_CONSTRUCT_CKE_SM2ECC, ERR_R_INTERNAL_ERROR); ++ goto err; ++ } ++ ++ pmslen = SSL_MAX_MASTER_KEY_LENGTH; ++ pms = OPENSSL_malloc(pmslen); ++ if (pms == NULL) { ++ SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLCP_CONSTRUCT_CKE_SM2ECC, ++ ERR_R_MALLOC_FAILURE); ++ goto err; ++ } ++ ++ pms[0] = s->client_version >> 8; ++ pms[1] = s->client_version & 0xff; ++ if (RAND_bytes(pms + 2, (int)(pmslen - 2)) <= 0) { ++ SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLCP_CONSTRUCT_CKE_SM2ECC, ++ ERR_R_INTERNAL_ERROR); ++ goto err; ++ } ++ ++ if (!WPACKET_start_sub_packet_u16(pkt)) { ++ SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLCP_CONSTRUCT_CKE_SM2ECC, ++ ERR_R_INTERNAL_ERROR); ++ goto err; ++ } ++ /* Encrypt premaster secret { client_version, random[46] }*/ ++ pctx = EVP_PKEY_CTX_new(peer_enc_pkey, NULL); ++ if (pctx == NULL || EVP_PKEY_encrypt_init(pctx) <= 0 ++ || EVP_PKEY_encrypt(pctx, NULL, &enclen, pms, pmslen) <= 0) { ++ SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLCP_CONSTRUCT_CKE_SM2ECC, ++ ERR_R_EVP_LIB); ++ goto err; ++ } ++ if (!WPACKET_reserve_bytes(pkt, enclen, &encdata) ++ || EVP_PKEY_encrypt(pctx, encdata, &enclen, pms, pmslen) <= 0) { ++ SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLCP_CONSTRUCT_CKE_SM2ECC, ++ ERR_R_EVP_LIB); ++ goto err; ++ } ++ pkt->written += enclen; ++ pkt->curr += enclen; ++ EVP_PKEY_CTX_free(pctx); ++ pctx = NULL; ++ ++ if (!WPACKET_close(pkt)) { ++ SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLCP_CONSTRUCT_CKE_SM2ECC, ++ ERR_R_INTERNAL_ERROR); ++ goto err; ++ } ++ ++ s->s3->tmp.pms = pms; ++ s->s3->tmp.pmslen = pmslen; ++ ++ return 1; ++err: ++ OPENSSL_clear_free(pms, pmslen); ++ EVP_PKEY_CTX_free(pctx); ++ return 0; ++} ++ ++static int tlcp_construct_cke_sm2dhe(SSL *s, WPACKET *pkt) ++{ ++ EVP_PKEY *skey, *ckey; ++ unsigned char * pt_encoded = NULL; ++ int pt_encoded_len; ++ int ret = 0; ++ ++ if ((skey = s->s3->peer_tmp) == NULL) { ++ SSLfatal(s, SSL_AD_INTERNAL_ERROR, ++ SSL_F_TLCP_CONSTRUCT_CKE_SM2DHE, ERR_R_INTERNAL_ERROR); ++ return 0; ++ } ++ ++ if (!WPACKET_put_bytes_u8(pkt, NAMED_CURVE_TYPE) ++ || !WPACKET_put_bytes_u8(pkt, 0) ++ || !WPACKET_put_bytes_u8(pkt, 31)) { ++ SSLfatal(s, SSL_AD_INTERNAL_ERROR, ++ SSL_F_TLCP_CONSTRUCT_CKE_SM2DHE, ERR_R_INTERNAL_ERROR); ++ return 0; ++ } ++ ++ if ((ckey = ssl_generate_pkey(skey)) == NULL) { ++ SSLfatal(s, SSL_AD_INTERNAL_ERROR, ++ SSL_F_TLCP_CONSTRUCT_CKE_SM2DHE, ERR_R_INTERNAL_ERROR); ++ return 0; ++ } ++ ++ if ((pt_encoded_len = EVP_PKEY_get1_tls_encodedpoint(ckey, &pt_encoded)) <= 0) { ++ SSLfatal(s, SSL_AD_INTERNAL_ERROR, ++ SSL_F_TLCP_CONSTRUCT_CKE_SM2DHE, ERR_R_EC_LIB); ++ goto end; ++ } ++ ++ if (!WPACKET_sub_memcpy_u8(pkt, pt_encoded, pt_encoded_len)) { ++ SSLfatal(s, SSL_AD_INTERNAL_ERROR, ++ SSL_F_TLCP_CONSTRUCT_CKE_SM2DHE, ERR_R_INTERNAL_ERROR); ++ goto end; ++ } ++ ++ if (!tlcp_derive(s, ckey, skey)) { ++ SSLfatal(s, SSL_AD_INTERNAL_ERROR, ++ SSL_F_TLCP_CONSTRUCT_CKE_SM2DHE, ERR_R_INTERNAL_ERROR); ++ goto end; ++ } ++ ++ ret = 1; ++ ++end: ++ EVP_PKEY_free(ckey); ++ if (pt_encoded) { ++ OPENSSL_free(pt_encoded); ++ } ++ ++ return ret; ++} ++ ++static int tlcp_construct_client_key_exchange(SSL *s, WPACKET *pkt) ++{ ++ unsigned long alg_k; ++ ++ alg_k = s->s3->tmp.new_cipher->algorithm_mkey; ++ ++ if (alg_k & SSL_kSM2ECC) { ++ if (!tlcp_construct_cke_sm2ecc(s, pkt)) ++ goto err; ++ } else if (alg_k & SSL_kSM2DHE) { ++ if (!tlcp_construct_cke_sm2dhe(s, pkt)) ++ goto err; ++ } else { ++ SSLfatal(s, SSL_AD_INTERNAL_ERROR, ++ SSL_F_TLCP_CONSTRUCT_CLIENT_KEY_EXCHANGE, ERR_R_INTERNAL_ERROR); ++ goto err; ++ } ++ ++ return 1; ++err: ++ return 0; ++} ++#endif ++ + int tls_construct_client_key_exchange(SSL *s, WPACKET *pkt) + { ++#ifndef OPENSSL_NO_TLCP ++ if (ssl_newcipher_is_tlcp(s)) ++ return tlcp_construct_client_key_exchange(s, pkt); ++#endif + unsigned long alg_k; + + alg_k = s->s3->tmp.new_cipher->algorithm_mkey; +diff --git a/ssl/statem/statem_lib.c b/ssl/statem/statem_lib.c +index 695caab..06c9a2f 100644 +--- a/ssl/statem/statem_lib.c ++++ b/ssl/statem/statem_lib.c +@@ -227,6 +227,28 @@ static int get_cert_verify_tbs_data(SSL *s, unsigned char *tls13tbs, + return 1; + } + ++#ifndef OPENSSL_NO_TLCP ++static int get_tbs_hash_data(const EVP_MD *md, void *hdata, size_t hdatalen, unsigned char *out, size_t *outlen) ++{ ++ EVP_MD_CTX *md_ctx; ++ int rv = 0; ++ ++ md_ctx = EVP_MD_CTX_new(); ++ if (md_ctx == NULL) ++ goto err; ++ ++ if (!EVP_DigestInit(md_ctx, md) ++ || !EVP_DigestUpdate(md_ctx, (const void *)hdata, hdatalen) ++ || !EVP_DigestFinal(md_ctx, out, (unsigned int *)outlen)) { ++ goto err; ++ } ++ rv = 1; ++err: ++ EVP_MD_CTX_free(md_ctx); ++ return rv; ++} ++#endif ++ + int tls_construct_cert_verify(SSL *s, WPACKET *pkt) + { + EVP_PKEY *pkey = NULL; +@@ -238,6 +260,9 @@ int tls_construct_cert_verify(SSL *s, WPACKET *pkt) + unsigned char *sig = NULL; + unsigned char tls13tbs[TLS13_TBS_PREAMBLE_SIZE + EVP_MAX_MD_SIZE]; + const SIGALG_LOOKUP *lu = s->s3->tmp.sigalg; ++#ifndef OPENSSL_NO_TLCP ++ unsigned char out[EVP_MAX_MD_SIZE] = {0}; ++#endif + + if (lu == NULL || s->s3->tmp.cert == NULL) { + SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLS_CONSTRUCT_CERT_VERIFY, +@@ -251,6 +276,14 @@ int tls_construct_cert_verify(SSL *s, WPACKET *pkt) + ERR_R_INTERNAL_ERROR); + goto err; + } ++#ifndef OPENSSL_NO_TLCP ++ if (ssl_newcipher_is_tlcp(s) && ++ (!EVP_PKEY_is_sm2(pkey) || !EVP_PKEY_set_alias_type(pkey, EVP_PKEY_SM2))) { ++ SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLS_CONSTRUCT_CERT_VERIFY, ++ ERR_R_INTERNAL_ERROR); ++ goto err; ++ } ++#endif + + mctx = EVP_MD_CTX_new(); + if (mctx == NULL) { +@@ -264,7 +297,17 @@ int tls_construct_cert_verify(SSL *s, WPACKET *pkt) + /* SSLfatal() already called */ + goto err; + } +- ++#ifndef OPENSSL_NO_TLCP ++ if (ssl_newcipher_is_tlcp(s)) { ++ if (!get_tbs_hash_data(md, hdata, hdatalen, out, &hdatalen)) { ++ SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLS_CONSTRUCT_CERT_VERIFY, ++ ERR_R_INTERNAL_ERROR); ++ goto err; ++ } ++ /* Use new hash data for sign */ ++ hdata = out; ++ } ++#endif + if (SSL_USE_SIGALGS(s) && !WPACKET_put_bytes_u16(pkt, lu->sigalg)) { + SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLS_CONSTRUCT_CERT_VERIFY, + ERR_R_INTERNAL_ERROR); +@@ -359,6 +402,9 @@ MSG_PROCESS_RETURN tls_process_cert_verify(SSL *s, PACKET *pkt) + unsigned char tls13tbs[TLS13_TBS_PREAMBLE_SIZE + EVP_MAX_MD_SIZE]; + EVP_MD_CTX *mctx = EVP_MD_CTX_new(); + EVP_PKEY_CTX *pctx = NULL; ++#ifndef OPENSSL_NO_TLCP ++ unsigned char out[EVP_MAX_MD_SIZE] = {0}; ++#endif + + if (mctx == NULL) { + SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLS_PROCESS_CERT_VERIFY, +@@ -373,6 +419,14 @@ MSG_PROCESS_RETURN tls_process_cert_verify(SSL *s, PACKET *pkt) + ERR_R_INTERNAL_ERROR); + goto err; + } ++#ifndef OPENSSL_NO_TLCP ++ if (ssl_newcipher_is_tlcp(s) && ++ (!EVP_PKEY_is_sm2(pkey) || !EVP_PKEY_set_alias_type(pkey, EVP_PKEY_SM2))) { ++ SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLS_PROCESS_CERT_VERIFY, ++ ERR_R_INTERNAL_ERROR); ++ goto err; ++ } ++#endif + + if (ssl_cert_lookup_by_pkey(pkey, NULL) == NULL) { + SSLfatal(s, SSL_AD_ILLEGAL_PARAMETER, SSL_F_TLS_PROCESS_CERT_VERIFY, +@@ -448,6 +502,17 @@ MSG_PROCESS_RETURN tls_process_cert_verify(SSL *s, PACKET *pkt) + /* SSLfatal() already called */ + goto err; + } ++#ifndef OPENSSL_NO_TLCP ++ if (ssl_newcipher_is_tlcp(s)) { ++ if (!get_tbs_hash_data(md, hdata, hdatalen, out, &hdatalen)) { ++ SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLS_PROCESS_CERT_VERIFY, ++ ERR_R_INTERNAL_ERROR); ++ goto err; ++ } ++ /* Use new hash data for verify */ ++ hdata = out; ++ } ++#endif + + #ifdef SSL_DEBUG + fprintf(stderr, "Using client verify alg %s\n", +@@ -907,6 +972,43 @@ static int ssl_add_cert_to_wpacket(SSL *s, WPACKET *pkt, X509 *x, int chain) + return 1; + } + ++#ifndef OPENSSL_NO_TLCP ++static int ssl_add_sm2_cert_for_tlcp(SSL *s, STACK_OF(X509) *chain, WPACKET *pkt, X509 *sign_cert) ++{ ++ CERT_PKEY *enc_cpk; ++ X509 *x; ++ int i, idx; ++ int count, enc_idx; ++ ++ enc_cpk = &s->cert->pkeys[SSL_PKEY_SM2_ENC]; ++ if (enc_cpk == NULL || enc_cpk->x509 == NULL) ++ return 0; ++ ++ count = sk_X509_num(chain); ++ if (sign_cert == NULL) // sign cert is in the chain ++ count--; ++ ++ enc_idx = (s->options & SSL_OP_ENCCERT_SECOND_POSITION) ? 1 : (count + 1); // maybe last ++ i = idx = 0; ++ ++ while (idx < count + 2) { ++ if (idx == 0) { // sign cert is always the first ++ x = (sign_cert != NULL) ? sign_cert : sk_X509_value(chain, i++); ++ } else if (idx == enc_idx) { ++ x = enc_cpk->x509; ++ } else { ++ x = sk_X509_value(chain, i++); ++ } ++ ++ if (!ssl_add_cert_to_wpacket(s, pkt, x, idx)) { ++ return 0; ++ } ++ ++idx; ++ } ++ return 1; ++} ++#endif ++ + /* Add certificate chain to provided WPACKET */ + static int ssl_add_cert_chain(SSL *s, WPACKET *pkt, CERT_PKEY *cpk) + { +@@ -972,6 +1074,14 @@ static int ssl_add_cert_chain(SSL *s, WPACKET *pkt, CERT_PKEY *cpk) + SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_SSL_ADD_CERT_CHAIN, i); + return 0; + } ++#ifndef OPENSSL_NO_TLCP ++ if (ssl_newcipher_is_tlcp(s)) { ++ if (!ssl_add_sm2_cert_for_tlcp(s, chain, pkt, NULL)) { ++ X509_STORE_CTX_free(xs_ctx); ++ return 0; ++ } ++ } else { ++#endif + chain_count = sk_X509_num(chain); + for (i = 0; i < chain_count; i++) { + x = sk_X509_value(chain, i); +@@ -982,6 +1092,9 @@ static int ssl_add_cert_chain(SSL *s, WPACKET *pkt, CERT_PKEY *cpk) + return 0; + } + } ++#ifndef OPENSSL_NO_TLCP ++ } ++#endif + X509_STORE_CTX_free(xs_ctx); + } else { + i = ssl_security_cert_chain(s, extra_certs, x, 0); +@@ -989,6 +1102,11 @@ static int ssl_add_cert_chain(SSL *s, WPACKET *pkt, CERT_PKEY *cpk) + SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_SSL_ADD_CERT_CHAIN, i); + return 0; + } ++#ifndef OPENSSL_NO_TLCP ++ if (ssl_newcipher_is_tlcp(s)) { ++ return ssl_add_sm2_cert_for_tlcp(s, extra_certs, pkt, x); ++ } else { ++#endif + if (!ssl_add_cert_to_wpacket(s, pkt, x, 0)) { + /* SSLfatal() already called */ + return 0; +@@ -1000,6 +1118,9 @@ static int ssl_add_cert_chain(SSL *s, WPACKET *pkt, CERT_PKEY *cpk) + return 0; + } + } ++#ifndef OPENSSL_NO_TLCP ++ } ++#endif + } + return 1; + } +@@ -1444,6 +1565,9 @@ static const version_info tls_version_table[] = { + #else + {TLS1_VERSION, NULL, NULL}, + #endif ++#ifndef OPENSSL_NO_TLCP ++ {TLCP_VERSION, tlcp_client_method, tlcp_server_method}, ++#endif + #ifndef OPENSSL_NO_SSL3 + {SSL3_VERSION, sslv3_client_method, sslv3_server_method}, + #else +@@ -1596,7 +1720,10 @@ int ssl_version_supported(const SSL *s, int version, const SSL_METHOD **meth) + } + + for (vent = table; +- vent->version != 0 && version_cmp(s, version, vent->version) <= 0; ++#ifndef OPENSSL_NO_TLCP ++ ((version == SSL3_VERSION) && (vent->version == TLCP_VERSION)) || ++#endif ++ (vent->version != 0 && version_cmp(s, version, vent->version) <= 0); + ++vent) { + if (vent->cmeth != NULL + && version_cmp(s, version, vent->version) == 0 +@@ -1675,8 +1802,11 @@ int ssl_set_version_bound(int method_version, int version, int *bound) + *bound = version; + return 1; + } +- ++#ifndef OPENSSL_NO_TLCP ++ valid_tls = version >= TLCP_VERSION && version <= TLS_MAX_VERSION; ++#else + valid_tls = version >= SSL3_VERSION && version <= TLS_MAX_VERSION; ++#endif + valid_dtls = + DTLS_VERSION_LE(version, DTLS_MAX_VERSION) && + DTLS_VERSION_GE(version, DTLS1_BAD_VER); +@@ -1868,6 +1998,9 @@ int ssl_choose_server_version(SSL *s, CLIENTHELLO_MSG *hello, DOWNGRADE *dgrd) + const SSL_METHOD *method; + + if (vent->smeth == NULL || ++#ifndef OPENSSL_NO_TLCP ++ ((client_version != TLCP_VERSION) && (vent->version == TLCP_VERSION)) || ++#endif + version_cmp(s, client_version, vent->version) < 0) + continue; + method = vent->smeth(); +@@ -2097,6 +2230,11 @@ int ssl_get_min_max_version(const SSL *s, int *min_version, int *max_version, + * A table entry with a NULL client method is still a hole in the + * "version capability" vector. + */ ++#ifndef OPENSSL_NO_TLCP ++ if (vent->version == TLCP_VERSION) { ++ continue; ++ } ++#endif + if (vent->cmeth == NULL) { + hole = 1; + tmp_real_max = 0; +@@ -2120,7 +2258,23 @@ int ssl_get_min_max_version(const SSL *s, int *min_version, int *max_version, + hole = 0; + } + } +- ++#ifndef OPENSSL_NO_TLCP ++ if (version == 0 && s->method->version == TLS_ANY_VERSION) { ++ /* ++ * enable tlcp condition (when only sslv3 version, dont choose tlcp): ++ * 1. version is TLS_ANY_VERSION, and all tls/ssl protocol disabled ++ * 2. max version > sslv3 or max version == tlcp_version ++ * 3. s->options not set SSL_OP_NO_TLCP ++ */ ++ if (s->max_proto_version > SSL3_VERSION ++ || s->max_proto_version == TLCP_VERSION ++ || s->max_proto_version == 0 ++ && (s->options & SSL_OP_NO_TLCP) == 0) { ++ *min_version = *max_version = TLCP_VERSION; ++ return 0; ++ } ++ } ++#endif + *max_version = version; + + /* Fail if everything is disabled */ +diff --git a/ssl/statem/statem_srvr.c b/ssl/statem/statem_srvr.c +index d701c46..3544214 100644 +--- a/ssl/statem/statem_srvr.c ++++ b/ssl/statem/statem_srvr.c +@@ -325,6 +325,11 @@ static int send_server_key_exchange(SSL *s) + { + unsigned long alg_k = s->s3->tmp.new_cipher->algorithm_mkey; + ++#ifndef OPENSSL_NO_TLCP ++ /* TLCP: send ServerKeyExchange */ ++ if (ssl_newcipher_is_tlcp(s)) ++ return 1; ++#endif + /* + * only send a ServerKeyExchange if DH or fortezza but we have a + * sign only certificate PSK: may send PSK identity hints For +@@ -2356,7 +2361,17 @@ WORK_STATE tls_post_process_client_hello(SSL *s, WORK_STATE wst) + } + } + #endif +- ++#ifndef OPENSSL_NO_TLCP ++ /* ++ * As described by TLCP, when using ecdhe algorithm, ++ * client is required to send a certificate, ++ * so we set VEERFY_PEER mode. ++ */ ++ if (s->s3->tmp.new_cipher->algorithm_mkey & SSL_kSM2DHE) { ++ SSL_set_verify(s, SSL_VERIFY_PEER | SSL_VERIFY_FAIL_IF_NO_PEER_CERT ++ | SSL_VERIFY_CLIENT_ONCE, NULL); ++ } ++#endif + return WORK_FINISHED_STOP; + err: + return WORK_ERROR; +@@ -2485,8 +2500,269 @@ int tls_construct_server_done(SSL *s, WPACKET *pkt) + return 1; + } + ++#ifndef OPENSSL_NO_TLCP ++static int tlcp_construct_ske_sm2ecc(SSL *s, WPACKET *pkt) ++{ ++ EVP_MD_CTX *md_ctx = NULL; ++ EVP_PKEY_CTX *pctx = NULL; ++ unsigned char *encbuf = NULL; ++ unsigned char *tbs = NULL; ++ ++ const SIGALG_LOOKUP *lu; ++ EVP_PKEY *sign_pkey; ++ X509 *enc_cert; ++ const EVP_MD *md; ++ unsigned char *sigbytes1, *sigbytes2, *tmp; ++ size_t siglen, tbslen; ++ int rv, ebuflen; ++ ++ rv = 0; ++ lu = s->s3->tmp.sigalg; ++ sign_pkey = s->cert->pkeys[SSL_PKEY_SM2_SIGN].privatekey; ++ enc_cert = s->cert->pkeys[SSL_PKEY_SM2_ENC].x509; ++ ++ if (lu == NULL || sign_pkey == NULL || enc_cert == NULL ++ || !tls1_lookup_md(lu, &md)) { ++ SSLfatal(s, SSL_AD_INTERNAL_ERROR, ++ SSL_F_TLCP_CONSTRUCT_SKE_SM2ECC, ++ ERR_R_INTERNAL_ERROR); ++ goto err; ++ } ++ ++ if (!EVP_PKEY_is_sm2(sign_pkey) ++ || !EVP_PKEY_set_alias_type(sign_pkey, EVP_PKEY_SM2)) { ++ SSLfatal(s, SSL_AD_INTERNAL_ERROR, ++ SSL_F_TLCP_CONSTRUCT_SKE_SM2ECC, ++ ERR_R_INTERNAL_ERROR); ++ goto err; ++ } ++ ++ /* send signature algorithm */ ++ if (SSL_USE_SIGALGS(s) && !WPACKET_put_bytes_u16(pkt, lu->sigalg)) { ++ SSLfatal(s, SSL_AD_INTERNAL_ERROR, ++ SSL_F_TLCP_CONSTRUCT_SKE_SM2ECC, ++ ERR_R_INTERNAL_ERROR); ++ goto err; ++ } ++ ++ ebuflen = i2d_X509(enc_cert, NULL); ++ if (ebuflen < 0) { ++ SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLCP_CONSTRUCT_SKE_SM2ECC, ++ ERR_R_BUF_LIB); ++ goto err; ++ } ++ ++ md_ctx = EVP_MD_CTX_new(); ++ encbuf = OPENSSL_malloc(ebuflen + 3); ++ if (md_ctx == NULL || encbuf == NULL) { ++ SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLCP_CONSTRUCT_SKE_SM2ECC, ++ ERR_R_MALLOC_FAILURE); ++ goto err; ++ } ++ /* Encode the DER encoding of an X509 structure, reserve 3 bytes for length */ ++ tmp = encbuf; ++ l2n3(ebuflen, tmp); ++ ebuflen = i2d_X509(enc_cert, &tmp); ++ if (ebuflen < 0) { ++ SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLCP_CONSTRUCT_SKE_SM2ECC, ++ ERR_R_BUF_LIB); ++ goto err; ++ } ++ ebuflen += 3; ++ ++ siglen = EVP_PKEY_size(sign_pkey); ++ if (!WPACKET_sub_reserve_bytes_u16(pkt, siglen, &sigbytes1) ++ || EVP_DigestSignInit(md_ctx, &pctx, md, NULL, sign_pkey) <= 0) { ++ SSLfatal(s, SSL_AD_INTERNAL_ERROR, ++ SSL_F_TLCP_CONSTRUCT_SKE_SM2ECC, ++ ERR_R_INTERNAL_ERROR); ++ goto err; ++ } ++ /* ++ * As described by TLCP, client_random, server_random and encryption ++ * certificate are signed. ++ */ ++ tbslen = construct_key_exchange_tbs(s, &tbs, encbuf, ebuflen); ++ if (tbslen == 0) { ++ goto err; ++ } ++ ++ rv = EVP_DigestSign(md_ctx, sigbytes1, &siglen, tbs, tbslen); ++ ++ if (rv <= 0 || !WPACKET_sub_allocate_bytes_u16(pkt, siglen, &sigbytes2) ++ || sigbytes1 != sigbytes2) { ++ SSLfatal(s, SSL_AD_INTERNAL_ERROR, ++ SSL_F_TLCP_CONSTRUCT_SKE_SM2ECC, ++ ERR_R_INTERNAL_ERROR); ++ goto err; ++ } ++err: ++ OPENSSL_free(encbuf); ++ OPENSSL_free(tbs); ++ EVP_MD_CTX_free(md_ctx); ++ return rv; ++} ++ ++static int tlcp_construct_ske_sm2dhe(SSL *s, WPACKET *pkt) ++{ ++ EVP_PKEY_CTX *ctx; ++ EVP_PKEY *pkey; ++ unsigned char *pt; ++ int ptLen; ++ char *id = "1234567812345678"; ++ unsigned char *ecparam; ++ size_t ecparam_len = 0; ++ int ret = 0; ++ size_t siglen; ++ unsigned char *sig; ++ ++ ecparam = WPACKET_get_curr(pkt); ++ ++ // ECParam: NameCurved, curvedtype {NameCurved(3), curveid(41, rfc8898 defined, but this msg is ignored) ++ if (!WPACKET_put_bytes_u8(pkt, NAMED_CURVE_TYPE) ++ || !WPACKET_put_bytes_u8(pkt, 0) ++ || !WPACKET_put_bytes_u8(pkt, 41)) { ++ SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLCP_CONSTRUCT_SKE_SM2DHE, ++ ERR_R_INTERNAL_ERROR); ++ return 0; ++ } ++ ++ pkey = s->cert->pkeys[SSL_PKEY_SM2_SIGN].privatekey; ++ if (pkey == NULL) { ++ SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLCP_CONSTRUCT_SKE_SM2DHE, ++ ERR_R_INTERNAL_ERROR); ++ return 0; ++ } ++ ++ if (s->s3->tmp.pkey != NULL) { ++ SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLCP_CONSTRUCT_SKE_SM2DHE, ++ ERR_R_INTERNAL_ERROR); ++ return 0; ++ } ++ s->s3->tmp.pkey = ssl_generate_pkey_group(s, 31); ++ if (s->s3->tmp.pkey == NULL) { ++ SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLCP_CONSTRUCT_SKE_SM2DHE, ++ ERR_R_INTERNAL_ERROR); ++ return 0; ++ } ++ ++ ptLen = EVP_PKEY_get1_tls_encodedpoint(s->s3->tmp.pkey, &pt); ++ if (ptLen == 0) { ++ SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLCP_CONSTRUCT_SKE_SM2DHE, ++ ERR_R_EC_LIB); ++ return 0; ++ } ++ ++ if (!WPACKET_sub_memcpy_u8(pkt, pt, ptLen)) { ++ SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLCP_CONSTRUCT_SKE_SM2DHE, ++ ERR_R_INTERNAL_ERROR); ++ OPENSSL_free(pt); ++ return 0; ++ } ++ OPENSSL_free(pt); ++ ecparam_len = WPACKET_get_curr(pkt) - ecparam; ++ ++ if (!EVP_PKEY_is_sm2(pkey) || !EVP_PKEY_set_alias_type(pkey, EVP_PKEY_SM2)) { ++ SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLCP_CONSTRUCT_SKE_SM2DHE, ++ ERR_R_EC_LIB); ++ goto err; ++ } ++ ++ EVP_MD_CTX *md_ctx = EVP_MD_CTX_new(); ++ if (md_ctx == NULL) { ++ SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLCP_CONSTRUCT_SKE_SM2DHE, ++ ERR_R_MALLOC_FAILURE); ++ return 0; ++ } ++ ++ if (EVP_DigestSignInit(md_ctx, &ctx, EVP_sm3(), NULL, pkey) <= 0) { ++ SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLCP_CONSTRUCT_SKE_SM2DHE, ++ ERR_R_INTERNAL_ERROR); ++ goto err; ++ } ++ ++ if (EVP_PKEY_CTX_set1_id(ctx, id, strlen(id)) <= 0) { ++ SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLCP_CONSTRUCT_SKE_SM2DHE, ++ ERR_R_EC_LIB); ++ return 0; ++ } ++ ++ if (EVP_DigestSignUpdate(md_ctx, s->s3->client_random, SSL3_RANDOM_SIZE) <= 0 ++ || EVP_DigestSignUpdate(md_ctx, s->s3->server_random, SSL3_RANDOM_SIZE) <= 0 ++ || EVP_DigestSignUpdate(md_ctx, ecparam, ecparam_len) <= 0 ++ ) { ++ SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLCP_CONSTRUCT_SKE_SM2DHE, ++ ERR_R_EVP_LIB); ++ goto err; ++ } ++ ++ if ((siglen = EVP_PKEY_size(pkey)) <= 0) { ++ SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLCP_CONSTRUCT_SKE_SM2DHE, ++ ERR_R_INTERNAL_ERROR); ++ goto err; ++ } ++ ++ if (!WPACKET_sub_reserve_bytes_u16(pkt, siglen, &sig)) { ++ SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLCP_CONSTRUCT_SKE_SM2DHE, ++ ERR_R_INTERNAL_ERROR); ++ goto err; ++ } ++ ++ if (EVP_DigestSignFinal(md_ctx, sig, &siglen) <= 0) { ++ SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLCP_CONSTRUCT_SKE_SM2DHE, ++ SSL_R_SIGNATURE_ALGORITHMS_ERROR); ++ goto err; ++ } ++ ++ unsigned char* sig2 = NULL; ++ if (!WPACKET_sub_allocate_bytes_u16(pkt, siglen, &sig2) || sig != sig2) { ++ SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLCP_CONSTRUCT_SKE_SM2DHE, ++ ERR_R_INTERNAL_ERROR); ++ goto err; ++ } ++ ++ ret = 1; ++ ++err: ++ EVP_MD_CTX_free(md_ctx); ++ if (!ret && s->s3->tmp.pkey) { ++ EVP_PKEY_free(s->s3->tmp.pkey); ++ s->s3->tmp.pkey = NULL; ++ } ++ ++ return ret; ++} ++ ++static int tlcp_construct_server_key_exchange(SSL *s, WPACKET *pkt) ++{ ++ unsigned long alg_k; ++ ++ alg_k = s->s3->tmp.new_cipher->algorithm_mkey; ++ ++ if (alg_k & SSL_kSM2ECC) { ++ if (!tlcp_construct_ske_sm2ecc(s, pkt)) ++ goto err; ++ } else if (alg_k & SSL_kSM2DHE) { ++ if (!tlcp_construct_ske_sm2dhe(s, pkt)) ++ goto err; ++ } else { ++ SSLfatal(s, SSL_AD_INTERNAL_ERROR, ++ SSL_F_TLCP_CONSTRUCT_SERVER_KEY_EXCHANGE, ERR_R_INTERNAL_ERROR); ++ goto err; ++ } ++ ++ return 1; ++err: ++ return 0; ++} ++#endif ++ + int tls_construct_server_key_exchange(SSL *s, WPACKET *pkt) + { ++#ifndef OPENSSL_NO_TLCP ++ if (ssl_newcipher_is_tlcp(s)) ++ return tlcp_construct_server_key_exchange(s, pkt); ++#endif + #ifndef OPENSSL_NO_DH + EVP_PKEY *pkdh = NULL; + #endif +@@ -3455,8 +3731,174 @@ static int tls_process_cke_gost(SSL *s, PACKET *pkt) + #endif + } + ++#ifndef OPENSSL_NO_TLCP ++static int tlcp_process_cke_sm2ecc(SSL *s, PACKET *pkt) ++{ ++ EVP_PKEY_CTX *pctx = NULL; ++ int ret = 0; ++ ++ unsigned char premaster_secret[SSL_MAX_MASTER_KEY_LENGTH]; ++ EVP_PKEY *enc_prv_pkey; ++ PACKET enc_premaster; ++ size_t decrypt_len; ++ ++ enc_prv_pkey = s->cert->pkeys[SSL_PKEY_SM2_ENC].privatekey; ++ if (enc_prv_pkey == NULL || !EVP_PKEY_is_sm2(enc_prv_pkey) ++ || !EVP_PKEY_set_alias_type(enc_prv_pkey, EVP_PKEY_SM2)) { ++ SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLCP_PROCESS_CKE_SM2ECC, ++ SSL_R_NO_PRIVATE_KEY_ASSIGNED); ++ return 0; ++ } ++ ++ if (!PACKET_get_length_prefixed_2(pkt, &enc_premaster) ++ || PACKET_remaining(pkt) != 0) { ++ SSLfatal(s, SSL_AD_DECODE_ERROR, SSL_F_TLCP_PROCESS_CKE_SM2ECC, ++ SSL_R_LENGTH_MISMATCH); ++ return 0; ++ } ++ ++ pctx = EVP_PKEY_CTX_new(enc_prv_pkey, NULL); ++ if (pctx == NULL || EVP_PKEY_decrypt_init(pctx) <= 0) { ++ SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLCP_PROCESS_CKE_SM2ECC, ++ ERR_R_EVP_LIB); ++ goto err; ++ } ++ ++ /* Decrypt premaster secret { client_version, random[46] }*/ ++ decrypt_len = sizeof(premaster_secret); ++ if (EVP_PKEY_decrypt(pctx, premaster_secret, &decrypt_len, ++ PACKET_data(&enc_premaster), PACKET_remaining(&enc_premaster)) <= 0) { ++ SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLCP_PROCESS_CKE_SM2ECC, ++ ERR_R_EVP_LIB); ++ goto err; ++ } ++ if (decrypt_len != SSL_MAX_MASTER_KEY_LENGTH) { ++ SSLfatal(s, SSL_AD_DECRYPT_ERROR, SSL_F_TLCP_PROCESS_CKE_SM2ECC, ++ SSL_R_DECRYPTION_FAILED); ++ goto err; ++ } ++ ++ /* Check client version */ ++ if (constant_time_eq_8(premaster_secret[0], (unsigned)(s->client_version >> 8)) == 0 || ++ constant_time_eq_8(premaster_secret[1], (unsigned)(s->client_version & 0xff)) == 0) { ++ SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLCP_PROCESS_CKE_SM2ECC, ++ ERR_R_INTERNAL_ERROR); ++ goto err; ++ } ++ ++ if (!ssl_generate_master_secret(s, premaster_secret, ++ sizeof(premaster_secret), 0)) { ++ /* SSLfatal() already called */ ++ goto err; ++ } ++ ++ ret = 1; ++ err: ++ OPENSSL_cleanse(premaster_secret, sizeof(premaster_secret)); ++ EVP_PKEY_CTX_free(pctx); ++ return ret; ++} ++ ++static int tlcp_process_cke_sm2dhe(SSL *s, PACKET *pkt) ++{ ++ int ret = 0; ++ const unsigned char *ecparams; ++ PACKET pt_encoded; ++ EVP_PKEY *skey; ++ EVP_PKEY *ckey = NULL; ++ ++ if ((skey = s->s3->tmp.pkey) == NULL) { ++ SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLCP_PROCESS_CKE_SM2DHE, ++ ERR_R_INTERNAL_ERROR); ++ return 0; ++ } ++ ++ if (!PACKET_get_bytes(pkt, &ecparams, 3)) { ++ SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLCP_PROCESS_CKE_SM2DHE, ++ SSL_R_LENGTH_TOO_SHORT); ++ goto end; ++ } ++ ++ if (!PACKET_get_length_prefixed_1(pkt, &pt_encoded)) { ++ SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLCP_PROCESS_CKE_SM2DHE, ++ SSL_R_LENGTH_TOO_SHORT); ++ goto end; ++ } ++ ++ if (PACKET_remaining(pkt) != 0) { ++ SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLCP_PROCESS_CKE_SM2DHE, ++ SSL_R_LENGTH_TOO_LONG); ++ goto end; ++ } ++ ++ if ((ckey = EVP_PKEY_new()) == NULL) { ++ SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLCP_PROCESS_CKE_SM2DHE, ++ ERR_R_MALLOC_FAILURE); ++ goto end; ++ } ++ ++ if (EVP_PKEY_copy_parameters(ckey, skey) <= 0) { ++ SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLCP_PROCESS_CKE_SM2DHE, ++ ERR_R_INTERNAL_ERROR); ++ goto end; ++ } ++ ++ if (EVP_PKEY_set1_tls_encodedpoint(ckey, ++ PACKET_data(&pt_encoded), PACKET_remaining(&pt_encoded)) <= 0) { ++ SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLCP_PROCESS_CKE_SM2DHE, ++ ERR_R_EC_LIB); ++ goto end; ++ } ++ ++ if (!tlcp_derive(s, skey, ckey)) { ++ SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLCP_PROCESS_CKE_SM2DHE, ++ ERR_R_INTERNAL_ERROR); ++ goto end; ++ } ++ ++ ret = 1; ++ ++end: ++ EVP_PKEY_free(ckey); ++ EVP_PKEY_free(skey); ++ s->s3->tmp.pkey = NULL; ++ ++ return ret; ++} ++ ++static MSG_PROCESS_RETURN tlcp_process_client_key_exchange(SSL *s, PACKET *pkt) ++{ ++ unsigned long alg_k; ++ ++ alg_k = s->s3->tmp.new_cipher->algorithm_mkey; ++ ++ if (alg_k & SSL_kSM2ECC) { ++ if (!tlcp_process_cke_sm2ecc(s, pkt)) { ++ goto err; ++ } ++ } else if (alg_k & SSL_kSM2DHE) { ++ if (!tlcp_process_cke_sm2dhe(s, pkt)) { ++ goto err; ++ } ++ } else { ++ SSLfatal(s, SSL_AD_INTERNAL_ERROR, ++ SSL_F_TLCP_PROCESS_CLIENT_KEY_EXCHANGE, ++ SSL_R_UNKNOWN_CIPHER_TYPE); ++ goto err; ++ } ++ ++ return MSG_PROCESS_CONTINUE_PROCESSING; ++err: ++ return MSG_PROCESS_ERROR; ++} ++#endif ++ + MSG_PROCESS_RETURN tls_process_client_key_exchange(SSL *s, PACKET *pkt) + { ++#ifndef OPENSSL_NO_TLCP ++ if (ssl_newcipher_is_tlcp(s)) ++ return tlcp_process_client_key_exchange(s, pkt); ++#endif + unsigned long alg_k; + + alg_k = s->s3->tmp.new_cipher->algorithm_mkey; +diff --git a/ssl/t1_enc.c b/ssl/t1_enc.c +index c85c0b0..e86a663 100644 +--- a/ssl/t1_enc.c ++++ b/ssl/t1_enc.c +@@ -676,3 +676,87 @@ int tls1_alert_code(int code) + return -1; + } + } ++ ++#ifndef OPENSSL_NO_TLCP ++int tlcp_alert_code(int code) ++{ ++ switch (code) { ++ case SSL_AD_CLOSE_NOTIFY: ++ return (SSL3_AD_CLOSE_NOTIFY); ++ case SSL_AD_UNEXPECTED_MESSAGE: ++ return (SSL3_AD_UNEXPECTED_MESSAGE); ++ case SSL_AD_BAD_RECORD_MAC: ++ return (SSL3_AD_BAD_RECORD_MAC); ++ case SSL_AD_DECRYPTION_FAILED: ++ return (TLS1_AD_DECRYPTION_FAILED); ++ case SSL_AD_RECORD_OVERFLOW: ++ return (TLS1_AD_RECORD_OVERFLOW); ++ case SSL_AD_DECOMPRESSION_FAILURE: ++ return (SSL3_AD_DECOMPRESSION_FAILURE); ++ case SSL_AD_HANDSHAKE_FAILURE: ++ return (SSL3_AD_HANDSHAKE_FAILURE); ++ case SSL_AD_BAD_CERTIFICATE: ++ return (SSL3_AD_BAD_CERTIFICATE); ++ case SSL_AD_UNSUPPORTED_CERTIFICATE: ++ return (SSL3_AD_UNSUPPORTED_CERTIFICATE); ++ case SSL_AD_CERTIFICATE_REVOKED: ++ return (SSL3_AD_CERTIFICATE_REVOKED); ++ case SSL_AD_CERTIFICATE_EXPIRED: ++ return (SSL3_AD_CERTIFICATE_EXPIRED); ++ case SSL_AD_CERTIFICATE_UNKNOWN: ++ return (SSL3_AD_CERTIFICATE_UNKNOWN); ++ case SSL_AD_ILLEGAL_PARAMETER: ++ return (SSL3_AD_ILLEGAL_PARAMETER); ++ case SSL_AD_UNKNOWN_CA: ++ return (TLS1_AD_UNKNOWN_CA); ++ case SSL_AD_ACCESS_DENIED: ++ return (TLS1_AD_ACCESS_DENIED); ++ case SSL_AD_DECODE_ERROR: ++ return (TLS1_AD_DECODE_ERROR); ++ case SSL_AD_DECRYPT_ERROR: ++ return (TLS1_AD_DECRYPT_ERROR); ++ case SSL_AD_EXPORT_RESTRICTION: ++ return (TLS1_AD_EXPORT_RESTRICTION); ++ case SSL_AD_PROTOCOL_VERSION: ++ return (TLS1_AD_PROTOCOL_VERSION); ++ case SSL_AD_INSUFFICIENT_SECURITY: ++ return (TLS1_AD_INSUFFICIENT_SECURITY); ++ case SSL_AD_INTERNAL_ERROR: ++ return (TLS1_AD_INTERNAL_ERROR); ++ case SSL_AD_USER_CANCELLED: ++ return (TLS1_AD_USER_CANCELLED); ++ case SSL_AD_NO_RENEGOTIATION: ++ return (TLS1_AD_NO_RENEGOTIATION); ++ case SSL_AD_UNSUPPORTED_EXTENSION: ++ return (TLS1_AD_UNSUPPORTED_EXTENSION); ++ case SSL_AD_CERTIFICATE_UNOBTAINABLE: ++ return (TLS1_AD_CERTIFICATE_UNOBTAINABLE); ++ case SSL_AD_UNRECOGNIZED_NAME: ++ return (TLS1_AD_UNRECOGNIZED_NAME); ++ case SSL_AD_BAD_CERTIFICATE_STATUS_RESPONSE: ++ return (TLS1_AD_BAD_CERTIFICATE_STATUS_RESPONSE); ++ case SSL_AD_BAD_CERTIFICATE_HASH_VALUE: ++ return (TLS1_AD_BAD_CERTIFICATE_HASH_VALUE); ++ case SSL_AD_INAPPROPRIATE_FALLBACK: ++ return (TLS1_AD_INAPPROPRIATE_FALLBACK); ++ case SSL_AD_NO_APPLICATION_PROTOCOL: ++ return (TLS1_AD_NO_APPLICATION_PROTOCOL); ++ case SSL_AD_CERTIFICATE_REQUIRED: ++ return (SSL_AD_HANDSHAKE_FAILURE); ++ case SSL_AD_UNSUPPORTED_SITE2SITE: ++ return (TLCP_AD_UNSUPPORTED_SITE2SITE); ++ case SSL_AD_NO_AREA: ++ return (TLCP_AD_NO_AREA); ++ case SSL_AD_UNSUPPORTED_AREATYPE: ++ return (TLCP_AD_UNSUPPORTED_AREATYPE); ++ case SSL_AD_BAD_IBCPARAM: ++ return (TLCP_AD_BAD_IBCPARAM); ++ case SSL_AD_UNSUPPORTED_IBCPARAM: ++ return (TLCP_AD_UNSUPPORTED_IBCPARAM); ++ case SSL_AD_IDENTITY_NEED: ++ return (TLCP_AD_IDENTITY_NEED); ++ default: ++ return (-1); ++ } ++} ++#endif +\ No newline at end of file +diff --git a/ssl/t1_lib.c b/ssl/t1_lib.c +index 841feec..35211a3 100644 +--- a/ssl/t1_lib.c ++++ b/ssl/t1_lib.c +@@ -93,6 +93,25 @@ SSL3_ENC_METHOD const TLSv1_3_enc_data = { + ssl3_handshake_write + }; + ++#ifndef OPENSSL_NO_TLCP ++SSL3_ENC_METHOD const TLCP_enc_data = { ++ tls1_enc, ++ tls1_mac, ++ tls1_setup_key_block, ++ tls1_generate_master_secret, ++ tls1_change_cipher_state, ++ tls1_final_finish_mac, ++ TLS_MD_CLIENT_FINISH_CONST, TLS_MD_CLIENT_FINISH_CONST_SIZE, ++ TLS_MD_SERVER_FINISH_CONST, TLS_MD_SERVER_FINISH_CONST_SIZE, ++ tlcp_alert_code, ++ tls1_export_keying_material, ++ SSL_ENC_FLAG_EXPLICIT_IV, ++ ssl3_set_handshake_header, ++ tls_close_construct_packet, ++ ssl3_handshake_write ++}; ++#endif ++ + long tls1_default_timeout(void) + { + /* +@@ -169,6 +188,9 @@ static const TLS_GROUP_INFO nid_list[] = { + {NID_brainpoolP512r1, 256, TLS_CURVE_PRIME}, /* brainpool512r1 (28) */ + {EVP_PKEY_X25519, 128, TLS_CURVE_CUSTOM}, /* X25519 (29) */ + {EVP_PKEY_X448, 224, TLS_CURVE_CUSTOM}, /* X448 (30) */ ++#ifndef OPENSSL_NO_TLCP ++ {EVP_PKEY_SM2, 128, TLS_CURVE_PRIME} /* sm2 (31) */ ++#endif + }; + + static const unsigned char ecformats_default[] = { +@@ -184,6 +206,9 @@ static const uint16_t eccurves_default[] = { + 30, /* X448 (30) */ + 25, /* secp521r1 (25) */ + 24, /* secp384r1 (24) */ ++#ifndef OPENSSL_NO_TLCP ++ 31, /* sm2 (31) */ ++#endif + }; + + static const uint16_t suiteb_curves[] = { +@@ -260,6 +285,11 @@ int tls_curve_allowed(SSL *s, uint16_t curve, int op) + # endif + if (FIPS_mode() && !(cinfo->flags & TLS_CURVE_FIPS)) + return 0; ++#ifndef OPENSSL_NO_TLCP ++ if (s->version == TLCP_VERSION && cinfo->nid != NID_sm2) { ++ return 0; ++ } ++#endif + ctmp[0] = curve >> 8; + ctmp[1] = curve & 0xff; + return ssl_security(s, op, cinfo->secbits, cinfo->nid, (void *)ctmp); +@@ -547,6 +577,10 @@ void tls1_get_formatlist(SSL *s, const unsigned char **pformats, + /* For Suite B we don't support char2 fields */ + if (tls1_suiteb(s)) + *num_formats = sizeof(ecformats_default) - 1; ++#ifndef OPENSSL_NO_TLCP ++ else if (s->version == TLCP_VERSION) // TLCP version only support uncompressed ++ *num_formats = sizeof(ecformats_default) - 2; ++#endif + else + *num_formats = sizeof(ecformats_default); + } +@@ -639,6 +673,9 @@ static int tls1_check_cert_param(SSL *s, X509 *x, int set_ee_md) + /* Default sigalg schemes */ + static const uint16_t tls12_sigalgs[] = { + #ifndef OPENSSL_NO_EC ++#ifndef OPENSSL_NO_TLCP ++ TLSEXT_SIGALG_sm2dsa_sm3, ++#endif + TLSEXT_SIGALG_ecdsa_secp256r1_sha256, + TLSEXT_SIGALG_ecdsa_secp384r1_sha384, + TLSEXT_SIGALG_ecdsa_secp521r1_sha512, +@@ -687,6 +724,11 @@ static const uint16_t suiteb_sigalgs[] = { + + static const SIGALG_LOOKUP sigalg_lookup_tbl[] = { + #ifndef OPENSSL_NO_EC ++#ifndef OPENSSL_NO_TLCP ++ {"sm2dsa_sm3", TLSEXT_SIGALG_sm2dsa_sm3, ++ NID_sm3, SSL_MD_SM3_IDX, NID_sm2, SSL_PKEY_SM2_SIGN, ++ NID_SM2_with_SM3, NID_sm2}, ++#endif + {"ecdsa_secp256r1_sha256", TLSEXT_SIGALG_ecdsa_secp256r1_sha256, + NID_sha256, SSL_MD_SHA256_IDX, EVP_PKEY_EC, SSL_PKEY_ECC, + NID_ecdsa_with_SHA256, NID_X9_62_prime256v1}, +@@ -796,6 +838,10 @@ static const uint16_t tls_default_sigalg[] = { + TLSEXT_SIGALG_gostr34102012_512_gostr34112012_512, /* SSL_PKEY_GOST12_512 */ + 0, /* SSL_PKEY_ED25519 */ + 0, /* SSL_PKEY_ED448 */ ++#ifndef OPENSSL_NO_TLCP ++ TLSEXT_SIGALG_sm2dsa_sm3, /* SSL_PKEY_SM2_SIGN */ ++ 0, /* SSL_PKEY_SM2_ENC */ ++#endif + }; + + /* Lookup TLS signature algorithm */ +@@ -983,7 +1029,7 @@ int tls_check_sigalg_curve(const SSL *s, int curve) + + if (lu == NULL) + continue; +- if (lu->sig == EVP_PKEY_EC ++ if ((lu->sig == EVP_PKEY_EC || lu->sig == EVP_PKEY_SM2) + && lu->curve != NID_undef + && curve == lu->curve) + return 1; +@@ -1055,6 +1101,9 @@ int tls12_check_peer_sigalg(SSL *s, uint16_t sig, EVP_PKEY *pkey) + if (lu == NULL + || (SSL_IS_TLS13(s) && (lu->hash == NID_sha1 || lu->hash == NID_sha224)) + || (pkeyid != lu->sig ++#ifndef OPENSSL_NO_TCLP ++ && (lu->sig != EVP_PKEY_SM2) ++#endif + && (lu->sig != EVP_PKEY_RSA_PSS || pkeyid != EVP_PKEY_RSA))) { + SSLfatal(s, SSL_AD_ILLEGAL_PARAMETER, SSL_F_TLS12_CHECK_PEER_SIGALG, + SSL_R_WRONG_SIGNATURE_TYPE); +@@ -1199,6 +1248,13 @@ int ssl_set_client_disabled(SSL *s) + s->s3->tmp.mask_a |= SSL_aSRP; + s->s3->tmp.mask_k |= SSL_kSRP; + } ++#endif ++#ifndef OPENSSL_NO_TLCP ++ /* TLCP ciphersuites will be disabled while using other protocols */ ++ if (s->version != TLCP_VERSION) { ++ s->s3->tmp.mask_a |= SSL_aSM2; ++ s->s3->tmp.mask_k |= SSL_kSM2ECC | SSL_kSM2DHE; ++ } + #endif + return 1; + } +@@ -1319,7 +1375,11 @@ SSL_TICKET_STATUS tls_get_ticket_from_client(SSL *s, CLIENTHELLO_MSG *hello, + * (e.g. TLSv1.3) behave as if no ticket present to permit stateful + * resumption. + */ ++#ifndef OPENSSL_NO_GMTLS ++ if ((s->version <= SSL3_VERSION && s->version != TLCP_VERSION) || !tls_use_ticket(s)) ++#else + if (s->version <= SSL3_VERSION || !tls_use_ticket(s)) ++#endif + return SSL_TICKET_NONE; + + ticketext = &hello->pre_proc_exts[TLSEXT_IDX_session_ticket]; +@@ -2430,6 +2490,10 @@ void tls1_set_cert_validity(SSL *s) + tls1_check_chain(s, NULL, NULL, NULL, SSL_PKEY_GOST12_512); + tls1_check_chain(s, NULL, NULL, NULL, SSL_PKEY_ED25519); + tls1_check_chain(s, NULL, NULL, NULL, SSL_PKEY_ED448); ++#ifndef OPENSSL_NO_TLCP ++ tls1_check_chain(s, NULL, NULL, NULL, SSL_PKEY_SM2_ENC); ++ tls1_check_chain(s, NULL, NULL, NULL, SSL_PKEY_SM2_SIGN); ++#endif + } + + /* User level utility function to check a chain is suitable */ +@@ -2766,6 +2830,11 @@ int tls_choose_sigalg(SSL *s, int fatalerrs) + /* If ciphersuite doesn't require a cert nothing to do */ + if (!(s->s3->tmp.new_cipher->algorithm_auth & SSL_aCERT)) + return 1; ++#ifndef OPENSSL_NO_TLCP ++ /* Resetting s->cert prevents it from being modified when other certificates are loaded */ ++ if (ssl_newcipher_is_tlcp(s)) ++ s->cert->key = &(s->cert->pkeys[SSL_PKEY_SM2_SIGN]); ++#endif + if (!s->server && !ssl_has_cert(s, s->cert->key - s->cert->pkeys)) + return 1; + +diff --git a/ssl/tlcp_lib.c b/ssl/tlcp_lib.c +new file mode 100644 +index 0000000..622f857 +--- /dev/null ++++ b/ssl/tlcp_lib.c +@@ -0,0 +1,119 @@ ++#ifndef OPENSSL_NO_TLCP ++ ++#include "ssl_local.h" ++ ++int tlcp_alert_code(int code) ++{ ++ switch (code) { ++ case SSL_AD_CLOSE_NOTIFY: ++ return (SSL3_AD_CLOSE_NOTIFY); ++ case SSL_AD_UNEXPECTED_MESSAGE: ++ return (SSL3_AD_UNEXPECTED_MESSAGE); ++ case SSL_AD_BAD_RECORD_MAC: ++ return (SSL3_AD_BAD_RECORD_MAC); ++ case SSL_AD_DECRYPTION_FAILED: ++ return (TLS1_AD_DECRYPTION_FAILED); ++ case SSL_AD_RECORD_OVERFLOW: ++ return (TLS1_AD_RECORD_OVERFLOW); ++ case SSL_AD_DECOMPRESSION_FAILURE: ++ return (SSL3_AD_DECOMPRESSION_FAILURE); ++ case SSL_AD_HANDSHAKE_FAILURE: ++ return (SSL3_AD_HANDSHAKE_FAILURE); ++ case SSL_AD_BAD_CERTIFICATE: ++ return (SSL3_AD_BAD_CERTIFICATE); ++ case SSL_AD_UNSUPPORTED_CERTIFICATE: ++ return (SSL3_AD_UNSUPPORTED_CERTIFICATE); ++ case SSL_AD_CERTIFICATE_REVOKED: ++ return (SSL3_AD_CERTIFICATE_REVOKED); ++ case SSL_AD_CERTIFICATE_EXPIRED: ++ return (SSL3_AD_CERTIFICATE_EXPIRED); ++ case SSL_AD_CERTIFICATE_UNKNOWN: ++ return (SSL3_AD_CERTIFICATE_UNKNOWN); ++ case SSL_AD_ILLEGAL_PARAMETER: ++ return (SSL3_AD_ILLEGAL_PARAMETER); ++ case SSL_AD_UNKNOWN_CA: ++ return (TLS1_AD_UNKNOWN_CA); ++ case SSL_AD_ACCESS_DENIED: ++ return (TLS1_AD_ACCESS_DENIED); ++ case SSL_AD_DECODE_ERROR: ++ return (TLS1_AD_DECODE_ERROR); ++ case SSL_AD_DECRYPT_ERROR: ++ return (TLS1_AD_DECRYPT_ERROR); ++ case SSL_AD_EXPORT_RESTRICTION: ++ return (TLS1_AD_EXPORT_RESTRICTION); ++ case SSL_AD_PROTOCOL_VERSION: ++ return (TLS1_AD_PROTOCOL_VERSION); ++ case SSL_AD_INSUFFICIENT_SECURITY: ++ return (TLS1_AD_INSUFFICIENT_SECURITY); ++ case SSL_AD_INTERNAL_ERROR: ++ return (TLS1_AD_INTERNAL_ERROR); ++ case SSL_AD_USER_CANCELLED: ++ return (TLS1_AD_USER_CANCELLED); ++ case SSL_AD_NO_RENEGOTIATION: ++ return (TLS1_AD_NO_RENEGOTIATION); ++ case SSL_AD_UNSUPPORTED_EXTENSION: ++ return (TLS1_AD_UNSUPPORTED_EXTENSION); ++ case SSL_AD_CERTIFICATE_UNOBTAINABLE: ++ return (TLS1_AD_CERTIFICATE_UNOBTAINABLE); ++ case SSL_AD_UNRECOGNIZED_NAME: ++ return (TLS1_AD_UNRECOGNIZED_NAME); ++ case SSL_AD_BAD_CERTIFICATE_STATUS_RESPONSE: ++ return (TLS1_AD_BAD_CERTIFICATE_STATUS_RESPONSE); ++ case SSL_AD_BAD_CERTIFICATE_HASH_VALUE: ++ return (TLS1_AD_BAD_CERTIFICATE_HASH_VALUE); ++ case SSL_AD_INAPPROPRIATE_FALLBACK: ++ return (TLS1_AD_INAPPROPRIATE_FALLBACK); ++ case SSL_AD_NO_APPLICATION_PROTOCOL: ++ return (TLS1_AD_NO_APPLICATION_PROTOCOL); ++ case SSL_AD_CERTIFICATE_REQUIRED: ++ return (SSL_AD_HANDSHAKE_FAILURE); ++ case SSL_AD_UNSUPPORTED_SITE2SITE: ++ return (TLCP_AD_UNSUPPORTED_SITE2SITE); ++ case SSL_AD_NO_AREA: ++ return (TLCP_AD_NO_AREA); ++ case SSL_AD_UNSUPPORTED_AREATYPE: ++ return (TLCP_AD_UNSUPPORTED_AREATYPE); ++ case SSL_AD_BAD_IBCPARAM: ++ return (TLCP_AD_BAD_IBCPARAM); ++ case SSL_AD_UNSUPPORTED_IBCPARAM: ++ return (TLCP_AD_UNSUPPORTED_IBCPARAM); ++ case SSL_AD_IDENTITY_NEED: ++ return (TLCP_AD_IDENTITY_NEED); ++ default: ++ return (-1); ++ } ++} ++ ++SSL3_ENC_METHOD const TLCP_enc_data = { ++ tls1_enc, ++ tls1_mac, ++ tls1_setup_key_block, ++ tls1_generate_master_secret, ++ tls1_change_cipher_state, ++ tls1_final_finish_mac, ++ TLS_MD_CLIENT_FINISH_CONST, TLS_MD_CLIENT_FINISH_CONST_SIZE, ++ TLS_MD_SERVER_FINISH_CONST, TLS_MD_SERVER_FINISH_CONST_SIZE, ++ tlcp_alert_code, ++ tls1_export_keying_material, ++ SSL_ENC_FLAG_EXPLICIT_IV, ++ ssl3_set_handshake_header, ++ tls_close_construct_packet, ++ ssl3_handshake_write ++}; ++ ++const SSL_METHOD *TLCP_method(void) ++{ ++ return tlcp_method(); ++} ++ ++const SSL_METHOD *TLCP_server_method(void) ++{ ++ return tlcp_server_method(); ++} ++ ++const SSL_METHOD *TLCP_client_method(void) ++{ ++ return tlcp_client_method(); ++} ++ ++#endif +\ No newline at end of file +diff --git a/test/build.info b/test/build.info +index 726bd22..db16a1f 100644 +--- a/test/build.info ++++ b/test/build.info +@@ -51,7 +51,7 @@ INCLUDE_MAIN___test_libtestutil_OLB = /INCLUDE=MAIN + recordlentest drbgtest drbg_cavs_test sslbuffertest \ + time_offset_test pemtest ssl_cert_table_internal_test ciphername_test \ + servername_test ocspapitest rsa_mp_test fatalerrtest tls13ccstest \ +- sysdefaulttest errtest ssl_ctx_test gosttest ++ sysdefaulttest errtest ssl_ctx_test gosttest tlcptest + + SOURCE[versions]=versions.c + INCLUDE[versions]=../include +@@ -320,6 +320,10 @@ INCLUDE_MAIN___test_libtestutil_OLB = /INCLUDE=MAIN + INCLUDE[dtlstest]=../include + DEPEND[dtlstest]=../libcrypto ../libssl libtestutil.a + ++ SOURCE[tlcptest]=tlcptest.c ssltestlib.c ++ INCLUDE[tlcptest]=.. ../include ++ DEPEND[tlcptest]=../libcrypto ../libssl libtestutil.a ++ + SOURCE[sslcorrupttest]=sslcorrupttest.c ssltestlib.c + INCLUDE[sslcorrupttest]=../include + DEPEND[sslcorrupttest]=../libcrypto ../libssl libtestutil.a +diff --git a/test/certs/embeddedSCTs1-key.pem b/test/certs/embeddedSCTs1-key.pem +index e3e66d5..28dd206 100644 +--- a/test/certs/embeddedSCTs1-key.pem ++++ b/test/certs/embeddedSCTs1-key.pem +@@ -1,15 +1,27 @@ + -----BEGIN RSA PRIVATE KEY----- +-MIICWwIBAAKBgQC+75jnwmh3rjhfdTJaDB0ym+3xj6r015a/BH634c4VyVui+A7k +-WL19uG+KSyUhkaeb1wDDjpwDibRc1NyaEgqyHgy0HNDnKAWkEM2cW9tdSSdyba8X +-EPYBhzd+olsaHjnu0LiBGdwVTcaPfajjDK8VijPmyVCfSgWwFAn/Xdh+tQIDAQAB +-AoGAK/daG0vt6Fkqy/hdrtSJSKUVRoGRmS2nnba4Qzlwzh1+x2kdbMFuaOu2a37g +-PvmeQclheKZ3EG1+Jb4yShwLcBCV6pkRJhOKuhvqGnjngr6uBH4gMCjpZVj7GDMf +-flYHhdJCs3Cz/TY0wKN3o1Fldil2DHR/AEOc1nImeSp5/EUCQQDjKS3W957kYtTU +-X5BeRjvg03Ug8tJq6IFuhTFvUJ+XQ5bAc0DmxAbQVKqRS7Wje59zTknVvS+MFdeQ +-pz4dGuV7AkEA1y0X2yarIls+0A/S1uwkvwRTIkfS+QwFJ1zVya8sApRdKAcidIzA +-b70hkKLilU9+LrXg5iZdFp8l752qJiw9jwJAXjItN/7mfH4fExGto+or2kbVQxxt +-9LcFNPc2UJp2ExuL37HrL8YJrUnukOF8KJaSwBWuuFsC5GwKP4maUCdfEQJAUwBR +-83c3DEmmMRvpeH4erpA8gTyzZN3+HvDwhpvLnjMcvBQEdnDUykVqbSBnxrCjO+Fs +-n1qtDczWFVf8Cj2GgQJAQ14Awx32Cn9sF+3M+sEVtlAf6CqiEbkYeYdSCbsplMmZ +-1UoaxiwXY3z+B7epsRnnPR3KaceAlAxw2/zQJMFNOQ== ++MIIEpQIBAAKCAQEAuIjpA4/iCpDA2mjywI5zG6IBX6bNcRQYDsB7Cv0VonNXtJBw ++XxMENP4jVpvEmWpJ5iMBknGHV+XWBkngYapczIsY4LGn6aMU6ySABBVQpNOQSRfT ++48xGGPR9mzOBG/yplmpFOVq1j+b65lskvAXKYaLFpFn3oY/pBSdcCNBP8LypVXAJ ++b3IqEXsBL/ErgHG9bgIRP8VxBAaryCz77kLzAXkfHL2LfSGIfNONyEKB3xI94S4L ++eouOSoWL1VkEfJs87vG4G5xoXw3KOHyiueQUUlMnu8p+Bx0xPVKPEsLje3R9k0rG ++a5ca7dXAn9UypKKp25x4NXpnjGX5txVEYfNvqQIDAQABAoIBAE0zqhh9Z5n3+Vbm ++tTht4CZdXqm/xQ9b0rzJNjDgtN5j1vuJuhlsgUQSVoJzZIqydvw7BPtZV8AkPagf ++3Cm/9lb0kpHegVsziRrfCFes+zIZ+LE7sMAKxADIuIvnvkoRKHnvN8rI8lCj16/r ++zbCD06mJSZp6sSj8ZgZr8wsU63zRGt1TeGM67uVW4agphfzuKGlXstPLsSMwknpF ++nxFS2TYbitxa9oH76oCpEk5fywYsYgUP4TdzOzfVAgMzNSu0FobvWl0CECB+G3RQ ++XQ5VWbYkFoj5XbE5kYz6sYHMQWL1NQpglUp+tAQ1T8Nca0CvbSpD77doRGm7UqYw ++ziVQKokCgYEA6BtHwzyD1PHdAYtOcy7djrpnIMaiisSxEtMhctoxg8Vr2ePEvMpZ ++S1ka8A1Pa9GzjaUk+VWKWsTf+VkmMHGtpB1sv8S7HjujlEmeQe7p8EltjstvLDmi ++BhAA7ixvZpXXjQV4GCVdUVu0na6gFGGueZb2FHEXB8j1amVwleJj2lcCgYEAy4f3 ++2wXqJfz15+YdJPpG9BbH9d/plKJm5ID3p2ojAGo5qvVuIJMNJA4elcfHDwzCWVmn ++MtR/WwtxYVVmy1BAnmk6HPSYc3CStvv1800vqN3fyJWtZ1P+8WBVZWZzIQdjdiaU ++JSRevPnjQGc+SAZQQIk1yVclbz5790yuXsdIxf8CgYEApqlABC5lsvfga4Vt1UMn ++j57FAkHe4KmPRCcZ83A88ZNGd/QWhkD9kR7wOsIz7wVqWiDkxavoZnjLIi4jP9HA ++jwEZ3zER8wl70bRy0IEOtZzj8A6fSzAu6Q+Au4RokU6yse3lZ+EcepjQvhBvnXLu ++ZxxAojj6AnsHzVf9WYJvlI0CgYEAoATIw/TEgRV/KNHs/BOiEWqP0Co5dVix2Nnk ++3EVAO6VIrbbE3OuAm2ZWeaBWSujXLHSmVfpoHubCP6prZVI1W9aTkAxmh+xsDV3P ++o3h+DiBTP1seuGx7tr7spQqFXeR3OH9gXktYCO/W0d3aQ7pjAjpehWv0zJ+ty2MI ++fQ/lkXUCgYEAgbP+P5UmY7Fqm/mi6TprEJ/eYktji4Ne11GDKGFQCfjF5RdKhdw1 ++5+elGhZes+cpzu5Ak6zBDu4bviT+tRTWJu5lVLEzlHHv4nAU7Ks5Aj67ApH21AnP ++RtlATdhWOt5Dkdq1WSpDfz5bvWgvyBx9D66dSmQdbKKe2dH327eQll4= + -----END RSA PRIVATE KEY----- +diff --git a/test/certs/embeddedSCTs1.pem b/test/certs/embeddedSCTs1.pem +index d1e8512..d2a111f 100644 +--- a/test/certs/embeddedSCTs1.pem ++++ b/test/certs/embeddedSCTs1.pem +@@ -1,20 +1,21 @@ + -----BEGIN CERTIFICATE----- +-MIIDWTCCAsKgAwIBAgIBBzANBgkqhkiG9w0BAQUFADBVMQswCQYDVQQGEwJHQjEk ++MIIDeDCCAuGgAwIBAgIBAjANBgkqhkiG9w0BAQsFADBVMQswCQYDVQQGEwJHQjEk + MCIGA1UEChMbQ2VydGlmaWNhdGUgVHJhbnNwYXJlbmN5IENBMQ4wDAYDVQQIEwVX +-YWxlczEQMA4GA1UEBxMHRXJ3IFdlbjAeFw0xMjA2MDEwMDAwMDBaFw0yMjA2MDEw +-MDAwMDBaMFIxCzAJBgNVBAYTAkdCMSEwHwYDVQQKExhDZXJ0aWZpY2F0ZSBUcmFu +-c3BhcmVuY3kxDjAMBgNVBAgTBVdhbGVzMRAwDgYDVQQHEwdFcncgV2VuMIGfMA0G +-CSqGSIb3DQEBAQUAA4GNADCBiQKBgQC+75jnwmh3rjhfdTJaDB0ym+3xj6r015a/ +-BH634c4VyVui+A7kWL19uG+KSyUhkaeb1wDDjpwDibRc1NyaEgqyHgy0HNDnKAWk +-EM2cW9tdSSdyba8XEPYBhzd+olsaHjnu0LiBGdwVTcaPfajjDK8VijPmyVCfSgWw +-FAn/Xdh+tQIDAQABo4IBOjCCATYwHQYDVR0OBBYEFCAxVBryXAX/2GWLaEN5T16Q +-Nve0MH0GA1UdIwR2MHSAFF+diA3Ic+ZU1PgN2OawwSS0R8NVoVmkVzBVMQswCQYD +-VQQGEwJHQjEkMCIGA1UEChMbQ2VydGlmaWNhdGUgVHJhbnNwYXJlbmN5IENBMQ4w +-DAYDVQQIEwVXYWxlczEQMA4GA1UEBxMHRXJ3IFdlboIBADAJBgNVHRMEAjAAMIGK +-BgorBgEEAdZ5AgQCBHwEegB4AHYA3xwuwRUAlFJHqWFoMl3cXHlZ6PfG04j8AC4L +-vT9012QAAAE92yffkwAABAMARzBFAiBIL2dRrzXbplQ2vh/WZA89v5pBQpSVkkUw +-KI+j5eI+BgIhAOTtwNs6xXKx4vXoq2poBlOYfc9BAn3+/6EFUZ2J7b8IMA0GCSqG +-SIb3DQEBBQUAA4GBAIoMS+8JnUeSea+goo5on5HhxEIb4tJpoupspOghXd7dyhUE +-oR58h8S3foDw6XkDUmjyfKIOFmgErlVvMWmB+Wo5Srer/T4lWsAERRP+dlcMZ5Wr +-5HAxM9MD+J86+mu8/FFzGd/ZW5NCQSEfY0A1w9B4MHpoxgdaLiDInza4kQyg ++YWxlczEQMA4GA1UEBxMHRXJ3IFdlbjAgFw0yMDAxMjUxMTUwMTNaGA8yMTIwMDEy ++NjExNTAxM1owGTEXMBUGA1UEAwwOc2VydmVyLmV4YW1wbGUwggEiMA0GCSqGSIb3 ++DQEBAQUAA4IBDwAwggEKAoIBAQC4iOkDj+IKkMDaaPLAjnMbogFfps1xFBgOwHsK ++/RWic1e0kHBfEwQ0/iNWm8SZaknmIwGScYdX5dYGSeBhqlzMixjgsafpoxTrJIAE ++FVCk05BJF9PjzEYY9H2bM4Eb/KmWakU5WrWP5vrmWyS8BcphosWkWfehj+kFJ1wI ++0E/wvKlVcAlvcioRewEv8SuAcb1uAhE/xXEEBqvILPvuQvMBeR8cvYt9IYh8043I ++QoHfEj3hLgt6i45KhYvVWQR8mzzu8bgbnGhfDco4fKK55BRSUye7yn4HHTE9Uo8S ++wuN7dH2TSsZrlxrt1cCf1TKkoqnbnHg1emeMZfm3FURh82+pAgMBAAGjggEMMIIB ++CDAdBgNVHQ4EFgQUtMa8XD5ylrF9AqCdnPEhXa63H2owHwYDVR0jBBgwFoAUX52I ++Dchz5lTU+A3Y5rDBJLRHw1UwCQYDVR0TBAIwADATBgNVHSUEDDAKBggrBgEFBQcD ++ATCBigYKKwYBBAHWeQIEAgR8BHoAeAB2AN8cLsEVAJRSR6lhaDJd3Fx5Wej3xtOI ++/AAuC70/dNdkAAABb15m6AAAAAQDAEcwRQIgfDPo8RArm/vcSEZ608Q1u+XQ55QB ++u67SZEuZxLpbUM0CIQDRsgcTud4PDy8Cgg+lHeAS7UxgSKBbWAznYOuorwNewzAZ ++BgNVHREEEjAQgg5zZXJ2ZXIuZXhhbXBsZTANBgkqhkiG9w0BAQsFAAOBgQCWFKKR ++RNkDRzB25NK07OLkbzebhnpKtbP4i3blRx1HAvTSamf/3uuHI7kfiPJorJymJpT1 ++IuJvSVKyMu1qONWBimiBfiyGL7+le1izHEJIP5lVTbddfzSIBIvrlHHcWIOL3H+W ++YT6yTEIzJuO07Xp61qnB1CE2TrinUWlyC46Zkw== + -----END CERTIFICATE----- +diff --git a/test/certs/embeddedSCTs1.sct b/test/certs/embeddedSCTs1.sct +index 59362dc..35c9eb9 100644 +--- a/test/certs/embeddedSCTs1.sct ++++ b/test/certs/embeddedSCTs1.sct +@@ -2,11 +2,11 @@ Signed Certificate Timestamp: + Version : v1 (0x0) + Log ID : DF:1C:2E:C1:15:00:94:52:47:A9:61:68:32:5D:DC:5C: + 79:59:E8:F7:C6:D3:88:FC:00:2E:0B:BD:3F:74:D7:64 +- Timestamp : Apr 5 17:04:16.275 2013 GMT ++ Timestamp : Jan 1 00:00:00.000 2020 GMT + Extensions: none + Signature : ecdsa-with-SHA256 +- 30:45:02:20:48:2F:67:51:AF:35:DB:A6:54:36:BE:1F: +- D6:64:0F:3D:BF:9A:41:42:94:95:92:45:30:28:8F:A3: +- E5:E2:3E:06:02:21:00:E4:ED:C0:DB:3A:C5:72:B1:E2: +- F5:E8:AB:6A:68:06:53:98:7D:CF:41:02:7D:FE:FF:A1: +- 05:51:9D:89:ED:BF:08 +\ No newline at end of file ++ 30:45:02:20:7C:33:E8:F1:10:2B:9B:FB:DC:48:46:7A: ++ D3:C4:35:BB:E5:D0:E7:94:01:BB:AE:D2:64:4B:99:C4: ++ BA:5B:50:CD:02:21:00:D1:B2:07:13:B9:DE:0F:0F:2F: ++ 02:82:0F:A5:1D:E0:12:ED:4C:60:48:A0:5B:58:0C:E7: ++ 60:EB:A8:AF:03:5E:C3 +\ No newline at end of file +diff --git a/test/certs/embeddedSCTs1_issuer-key.pem b/test/certs/embeddedSCTs1_issuer-key.pem +new file mode 100644 +index 0000000..9326e38 +--- /dev/null ++++ b/test/certs/embeddedSCTs1_issuer-key.pem +@@ -0,0 +1,15 @@ ++-----BEGIN RSA PRIVATE KEY----- ++MIICXAIBAAKBgQDVimhTYhCicRmTbneDIRgcKkATxtB7jHbrkVfT0PtLO1FuzsvR ++yY2RxS90P6tjXVUJnNE6uvMa5UFEJFGnTHgW8iQ8+EjPKDHM5nugSlojgZ88ujfm ++JNnDvbKZuDnd/iYx0ss6hPx7srXFL8/BT/9Ab1zURmnLsvfP34b7arnRsQIDAQAB ++AoGAJLR6xEJp+5IXRFlLn7WTkFvO0ddtxJ7bXhiIkTctyruyfqp7LF9Jv1G2m3PK ++QPUtBc73w/GYkfnwIwdfJbOmPHL7XyEGHZYmEXgIgEtw6LXvAv0G5JpUnNwsSBfL ++GfSQqI5Z5ytyzlJXkMcTGA2kTgNAYc73h4EnU+pwUnDPdAECQQD2aj+4LtYk1XPq ++r3gjgI6MoGvgYJfPmAtZhxxVbhXQKciFUCAcBiwlQdHIdLWE9j65ctmZRWidKifr ++4O4nz+TBAkEA3djNW/rTQq5fKZy+mCF1WYnIU/3yhJaptzRqLm7AHqe7+hdrGXJw +++mCtU8T3L/Ms8bH1yFBZhmkp1PbR8gl48QJAQo70YyWThiN5yfxXcQ96cZWrTdIJ ++b3NcLXSHPLQdhDqlBQ1dfvRT3ERpC8IqfZ2d162kBPhwh3MpkVcSPQK0gQJAC/dY ++xGBYKt2a9nSk9zG+0bCT5Kvq++ngh6hFHfINXNnxUsEWns3EeEzkrIMQTj7QqszN ++lBt5aL2dawZRNrv6EQJBAOo4STF9KEwQG0HLC/ryh1FeB0OBA5yIepXze+eJVKei ++T0cCECOQJKfWHEzYJYDJhyEFF/sYp9TXwKSDjOifrsU= ++-----END RSA PRIVATE KEY----- +diff --git a/test/certs/embeddedSCTs1_issuer.pem b/test/certs/embeddedSCTs1_issuer.pem +index 1fa449d..6aa9455 100644 +--- a/test/certs/embeddedSCTs1_issuer.pem ++++ b/test/certs/embeddedSCTs1_issuer.pem +@@ -1,18 +1,18 @@ + -----BEGIN CERTIFICATE----- +-MIIC0DCCAjmgAwIBAgIBADANBgkqhkiG9w0BAQUFADBVMQswCQYDVQQGEwJHQjEk ++MIIC0jCCAjugAwIBAgIBADANBgkqhkiG9w0BAQsFADBVMQswCQYDVQQGEwJHQjEk + MCIGA1UEChMbQ2VydGlmaWNhdGUgVHJhbnNwYXJlbmN5IENBMQ4wDAYDVQQIEwVX +-YWxlczEQMA4GA1UEBxMHRXJ3IFdlbjAeFw0xMjA2MDEwMDAwMDBaFw0yMjA2MDEw +-MDAwMDBaMFUxCzAJBgNVBAYTAkdCMSQwIgYDVQQKExtDZXJ0aWZpY2F0ZSBUcmFu +-c3BhcmVuY3kgQ0ExDjAMBgNVBAgTBVdhbGVzMRAwDgYDVQQHEwdFcncgV2VuMIGf +-MA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQDVimhTYhCicRmTbneDIRgcKkATxtB7 +-jHbrkVfT0PtLO1FuzsvRyY2RxS90P6tjXVUJnNE6uvMa5UFEJFGnTHgW8iQ8+EjP +-KDHM5nugSlojgZ88ujfmJNnDvbKZuDnd/iYx0ss6hPx7srXFL8/BT/9Ab1zURmnL +-svfP34b7arnRsQIDAQABo4GvMIGsMB0GA1UdDgQWBBRfnYgNyHPmVNT4DdjmsMEk +-tEfDVTB9BgNVHSMEdjB0gBRfnYgNyHPmVNT4DdjmsMEktEfDVaFZpFcwVTELMAkG +-A1UEBhMCR0IxJDAiBgNVBAoTG0NlcnRpZmljYXRlIFRyYW5zcGFyZW5jeSBDQTEO +-MAwGA1UECBMFV2FsZXMxEDAOBgNVBAcTB0VydyBXZW6CAQAwDAYDVR0TBAUwAwEB +-/zANBgkqhkiG9w0BAQUFAAOBgQAGCMxKbWTyIF4UbASydvkrDvqUpdryOvw4BmBt +-OZDQoeojPUApV2lGOwRmYef6HReZFSCa6i4Kd1F2QRIn18ADB8dHDmFYT9czQiRy +-f1HWkLxHqd81TbD26yWVXeGJPE3VICskovPkQNJ0tU4b03YmnKliibduyqQQkOFP +-OwqULg== ++YWxlczEQMA4GA1UEBxMHRXJ3IFdlbjAgFw0yMjA2MDExMDM4MDJaGA8yMTIyMDUw ++ODEwMzgwMlowVTELMAkGA1UEBhMCR0IxJDAiBgNVBAoTG0NlcnRpZmljYXRlIFRy ++YW5zcGFyZW5jeSBDQTEOMAwGA1UECBMFV2FsZXMxEDAOBgNVBAcTB0VydyBXZW4w ++gZ8wDQYJKoZIhvcNAQEBBQADgY0AMIGJAoGBANWKaFNiEKJxGZNud4MhGBwqQBPG ++0HuMduuRV9PQ+0s7UW7Oy9HJjZHFL3Q/q2NdVQmc0Tq68xrlQUQkUadMeBbyJDz4 ++SM8oMczme6BKWiOBnzy6N+Yk2cO9spm4Od3+JjHSyzqE/HuytcUvz8FP/0BvXNRG ++acuy98/fhvtqudGxAgMBAAGjga8wgawwHQYDVR0OBBYEFF+diA3Ic+ZU1PgN2Oaw ++wSS0R8NVMH0GA1UdIwR2MHSAFF+diA3Ic+ZU1PgN2OawwSS0R8NVoVmkVzBVMQsw ++CQYDVQQGEwJHQjEkMCIGA1UEChMbQ2VydGlmaWNhdGUgVHJhbnNwYXJlbmN5IENB ++MQ4wDAYDVQQIEwVXYWxlczEQMA4GA1UEBxMHRXJ3IFdlboIBADAMBgNVHRMEBTAD ++AQH/MA0GCSqGSIb3DQEBCwUAA4GBAD0aYh9OkFYfXV7kBfhrtD0PJG2U47OV/1qq +++uFpqB0S1WO06eJT0pzYf1ebUcxjBkajbJZm/FHT85VthZ1lFHsky87aFD8XlJCo ++2IOhKOkvvWKPUdFLoO/ZVXqEVKkcsS1eXK1glFvb07eJZya3JVG0KdMhV2YoDg6c ++Doud4XrO + -----END CERTIFICATE----- +diff --git a/test/ciphername_test.c b/test/ciphername_test.c +index 303e28f..5c9edf4 100644 +--- a/test/ciphername_test.c ++++ b/test/ciphername_test.c +@@ -434,6 +434,9 @@ static int test_cipher_name(void) + if ((id == 0xFF85) || (id == 0xFF87)) + /* skip GOST2012-GOST8912-GOST891 and GOST2012-NULL-GOST12 */ + continue; ++ if ((id == 0xE011) || (id == 0xE013)) ++ /* skip ECDHE_SM2_WITH_SM4_CBC_SM3 and ECC_SM2_WITH_SM4_CBC_SM3 */ ++ continue; + p = SSL_CIPHER_standard_name(c); + q = get_std_name_by_id(id); + if (!TEST_ptr(p)) { +diff --git a/test/ct_test.c b/test/ct_test.c +index 78d11ca..535897d 100644 +--- a/test/ct_test.c ++++ b/test/ct_test.c +@@ -63,7 +63,7 @@ static CT_TEST_FIXTURE *set_up(const char *const test_case_name) + if (!TEST_ptr(fixture = OPENSSL_zalloc(sizeof(*fixture)))) + goto end; + fixture->test_case_name = test_case_name; +- fixture->epoch_time_in_ms = 1473269626000ULL; /* Sep 7 17:33:46 2016 GMT */ ++ fixture->epoch_time_in_ms = 1580335307000ULL; /* Wed 29 Jan 2020 10:01:47 PM UTC */ + if (!TEST_ptr(fixture->ctlog_store = CTLOG_STORE_new()) + || !TEST_int_eq( + CTLOG_STORE_load_default_file(fixture->ctlog_store), 1)) +diff --git a/test/recipes/85-test_tlcp.t b/test/recipes/85-test_tlcp.t +new file mode 100644 +index 0000000..eb87123 +--- /dev/null ++++ b/test/recipes/85-test_tlcp.t +@@ -0,0 +1,34 @@ ++#! /usr/bin/env perl ++# Copyright 2022 Huawei Technologies Co., Ltd. All Rights Reserved. ++# ++# Licensed under the OpenSSL license (the "License"). You may not use ++# this file except in compliance with the License. You can obtain a copy ++# in the file LICENSE in the source distribution or at ++# https://www.openssl.org/source/license.html ++ ++use OpenSSL::Test::Utils; ++use OpenSSL::Test qw/:DEFAULT data_file/; ++ ++setup("test_tlcp"); ++ ++plan skip_all => "TLCP is not supported by this OpenSSL build" ++ if disabled("tlcp"); ++ ++plan tests => 1; ++ ++ok(run(test(["tlcptest", ++ data_file("sm2-root-cert.pem"), # 0 ++ data_file("sm2-server-sig-cert.pem"), # 1 ++ data_file("sm2-server-sig-key.pem"), # 2 ++ data_file("sm2-server-enc-cert.pem"), # 3 ++ data_file("sm2-server-enc-key.pem"), # 4 ++ data_file("sm2-client-sig-cert.pem"), # 5 ++ data_file("sm2-client-sig-key.pem"), # 6 ++ data_file("sm2-client-enc-cert.pem"), # 7 ++ data_file("sm2-client-enc-key.pem"), # 8 ++ data_file("ecdsa-root-cert.pem"), # 9 ++ data_file("ecdsa-server-cert.pem"), # 10 ++ data_file("ecdsa-server-key.pem"), # 11 ++ data_file("ecdsa-client-cert.pem"), # 12 ++ data_file("ecdsa-client-key.pem") # 13 ++ ]))); +\ No newline at end of file +diff --git a/test/recipes/85-test_tlcp_data/ecdsa-client-cert.pem b/test/recipes/85-test_tlcp_data/ecdsa-client-cert.pem +new file mode 100644 +index 0000000..4f41232 +--- /dev/null ++++ b/test/recipes/85-test_tlcp_data/ecdsa-client-cert.pem +@@ -0,0 +1,12 @@ ++-----BEGIN CERTIFICATE----- ++MIIB2zCCAYGgAwIBAgIUIxUR+f5s2IPkP5kd86umC0jtOy0wCgYIKoZIzj0EAwIw ++YDELMAkGA1UEBhMCQ04xEjAQBgNVBAgMCUd1YW5nZG9uZzERMA8GA1UECgwIVGVz ++dCBPcmcxEDAOBgNVBAsMB1Rlc3QgT1UxGDAWBgNVBAMMD1Rlc3QgQ0EgKEVDRFNB ++KTAeFw0yMjA1MTkwOTI3MTVaFw0yNjA2MjcwOTI3MTVaMF8xCzAJBgNVBAYTAkNO ++MRIwEAYDVQQIDAlHdWFuZ2RvbmcxETAPBgNVBAoMCFRlc3QgT3JnMRAwDgYDVQQL ++DAdUZXN0IE9VMRcwFQYDVQQDDA5jbGllbnQgKEVDRFNBKTBZMBMGByqGSM49AgEG ++CCqGSM49AwEHA0IABJg2jl8qqQkLHwcqKC+gu8SWpDNHl8x2xSlsNkS8hm2edlsJ ++5QHfMPw7b138CmEE2FEtMqCtpRtsQnb5JRcxfTajGjAYMAkGA1UdEwQCMAAwCwYD ++VR0PBAQDAgbAMAoGCCqGSM49BAMCA0gAMEUCICBPe4rSKQdIWdB3u8EZ9+AR6Slu ++wsqdPm8p2mE409x4AiEAx513RsVDYohfejrvJmEL9ELIHmqTHjX+WjTjfMR/qrY= ++-----END CERTIFICATE----- +diff --git a/test/recipes/85-test_tlcp_data/ecdsa-client-key.pem b/test/recipes/85-test_tlcp_data/ecdsa-client-key.pem +new file mode 100644 +index 0000000..8a356ba +--- /dev/null ++++ b/test/recipes/85-test_tlcp_data/ecdsa-client-key.pem +@@ -0,0 +1,5 @@ ++-----BEGIN PRIVATE KEY----- ++MIGHAgEAMBMGByqGSM49AgEGCCqGSM49AwEHBG0wawIBAQQgj/hA8kscmW1VDMMn ++jWDNu/JrGrZ5Xr1kH0Q61zpRhIShRANCAASYNo5fKqkJCx8HKigvoLvElqQzR5fM ++dsUpbDZEvIZtnnZbCeUB3zD8O29d/AphBNhRLTKgraUbbEJ2+SUXMX02 ++-----END PRIVATE KEY----- +diff --git a/test/recipes/85-test_tlcp_data/ecdsa-root-cert.pem b/test/recipes/85-test_tlcp_data/ecdsa-root-cert.pem +new file mode 100644 +index 0000000..80d8c06 +--- /dev/null ++++ b/test/recipes/85-test_tlcp_data/ecdsa-root-cert.pem +@@ -0,0 +1,14 @@ ++-----BEGIN CERTIFICATE----- ++MIICHzCCAcWgAwIBAgIUcxkoWsrQfKvdPzNFeZt9sUACCv8wCgYIKoZIzj0EAwIw ++YDELMAkGA1UEBhMCQ04xEjAQBgNVBAgMCUd1YW5nZG9uZzERMA8GA1UECgwIVGVz ++dCBPcmcxEDAOBgNVBAsMB1Rlc3QgT1UxGDAWBgNVBAMMD1Rlc3QgQ0EgKEVDRFNB ++KTAeFw0yMjA1MTkwOTI3MTVaFw0yNjA2MjcwOTI3MTVaMGAxCzAJBgNVBAYTAkNO ++MRIwEAYDVQQIDAlHdWFuZ2RvbmcxETAPBgNVBAoMCFRlc3QgT3JnMRAwDgYDVQQL ++DAdUZXN0IE9VMRgwFgYDVQQDDA9UZXN0IENBIChFQ0RTQSkwWTATBgcqhkjOPQIB ++BggqhkjOPQMBBwNCAAQb8M+p/ywfaaLb6y5jP/6essKMw+HBYIzluA8JpAyuSEag ++hiiIegi/fJA9tONUKGGQrE92gFIjsyrGvwPnYqF1o10wWzAdBgNVHQ4EFgQU+BnE ++9UFgm03egYusuG7wtBeF12kwHwYDVR0jBBgwFoAU+BnE9UFgm03egYusuG7wtBeF ++12kwDAYDVR0TBAUwAwEB/zALBgNVHQ8EBAMCAQYwCgYIKoZIzj0EAwIDSAAwRQIh ++AO3LVs9OBinihB4W22ju3zoqfXTtHGdF0d9nbHbZEYqdAiAum1ZhMbtyWo/3YLDR ++2DqMuw5al5FbOlCIwrMbqcL+qQ== ++-----END CERTIFICATE----- +diff --git a/test/recipes/85-test_tlcp_data/ecdsa-server-cert.pem b/test/recipes/85-test_tlcp_data/ecdsa-server-cert.pem +new file mode 100644 +index 0000000..7e0d8d7 +--- /dev/null ++++ b/test/recipes/85-test_tlcp_data/ecdsa-server-cert.pem +@@ -0,0 +1,12 @@ ++-----BEGIN CERTIFICATE----- ++MIIB2zCCAYGgAwIBAgIUIxUR+f5s2IPkP5kd86umC0jtOywwCgYIKoZIzj0EAwIw ++YDELMAkGA1UEBhMCQ04xEjAQBgNVBAgMCUd1YW5nZG9uZzERMA8GA1UECgwIVGVz ++dCBPcmcxEDAOBgNVBAsMB1Rlc3QgT1UxGDAWBgNVBAMMD1Rlc3QgQ0EgKEVDRFNB ++KTAeFw0yMjA1MTkwOTI3MTVaFw0yNjA2MjcwOTI3MTVaMF8xCzAJBgNVBAYTAkNO ++MRIwEAYDVQQIDAlHdWFuZ2RvbmcxETAPBgNVBAoMCFRlc3QgT3JnMRAwDgYDVQQL ++DAdUZXN0IE9VMRcwFQYDVQQDDA5zZXJ2ZXIgKEVDRFNBKTBZMBMGByqGSM49AgEG ++CCqGSM49AwEHA0IABAAmT2rADtfh1M/AW6n3cgLm2kEq/StWWcFDQ/AmTz54nFMp ++9AHt7xAqnizKl2UcdzUcDbhyBeNwjZ+80Eavvx2jGjAYMAkGA1UdEwQCMAAwCwYD ++VR0PBAQDAgbAMAoGCCqGSM49BAMCA0gAMEUCIQC70m1KUdKAsLI8zq78azjV2r/Z ++Oc6vwXfAqLKgF7EhtQIgYvh0XrMU9ETKKbfHORqJK+BD9DmFnAkxNpc9KVmN/D8= ++-----END CERTIFICATE----- +diff --git a/test/recipes/85-test_tlcp_data/ecdsa-server-key.pem b/test/recipes/85-test_tlcp_data/ecdsa-server-key.pem +new file mode 100644 +index 0000000..9d9af8d +--- /dev/null ++++ b/test/recipes/85-test_tlcp_data/ecdsa-server-key.pem +@@ -0,0 +1,5 @@ ++-----BEGIN PRIVATE KEY----- ++MIGHAgEAMBMGByqGSM49AgEGCCqGSM49AwEHBG0wawIBAQQgqMLQcziYtVwg+30u ++MvCIb3bYAfxAazvxQ8I69Jtml9uhRANCAAQAJk9qwA7X4dTPwFup93IC5tpBKv0r ++VlnBQ0PwJk8+eJxTKfQB7e8QKp4sypdlHHc1HA24cgXjcI2fvNBGr78d ++-----END PRIVATE KEY----- +diff --git a/test/recipes/85-test_tlcp_data/sm2-client-enc-cert.pem b/test/recipes/85-test_tlcp_data/sm2-client-enc-cert.pem +new file mode 100644 +index 0000000..4a3e3f0 +--- /dev/null ++++ b/test/recipes/85-test_tlcp_data/sm2-client-enc-cert.pem +@@ -0,0 +1,12 @@ ++-----BEGIN CERTIFICATE----- ++MIIB2DCCAYCgAwIBAgIUMsQnTMiHshN4IOMc/ydgCOWB3WQwCgYIKoEcz1UBg3Uw ++XjELMAkGA1UEBhMCQ04xEjAQBgNVBAgMCUd1YW5nZG9uZzERMA8GA1UECgwIVGVz ++dCBPcmcxEDAOBgNVBAsMB1Rlc3QgT1UxFjAUBgNVBAMMDVRlc3QgQ0EgKFNNMikw ++HhcNMjIwNTE5MDkyNzEwWhcNMjYwNjI3MDkyNzEwWjBgMQswCQYDVQQGEwJDTjES ++MBAGA1UECAwJR3Vhbmdkb25nMREwDwYDVQQKDAhUZXN0IE9yZzEQMA4GA1UECwwH ++VGVzdCBPVTEYMBYGA1UEAwwPY2xpZW50IGVuYyhTTTIpMFkwEwYHKoZIzj0CAQYI ++KoEcz1UBgi0DQgAEsjxuZnSYi2M2iL4vUqHFdegJqxALkFxq+XiA/C8vQSMOCDaz ++8ZH1XrCwU3kMShiQyNM8AkjufKgCOGSB3B58qKMaMBgwCQYDVR0TBAIwADALBgNV ++HQ8EBAMCAzgwCgYIKoEcz1UBg3UDRgAwQwIgcwaVeJ3pa/WUuR28r9+tGRg2EIEO ++IOlzRUlo6mwqcDACHxugAc0CFsB1dUWLOJuwJtpYsEmNpNHwLzxa16cfW3w= ++-----END CERTIFICATE----- +diff --git a/test/recipes/85-test_tlcp_data/sm2-client-enc-key.pem b/test/recipes/85-test_tlcp_data/sm2-client-enc-key.pem +new file mode 100644 +index 0000000..7a03991 +--- /dev/null ++++ b/test/recipes/85-test_tlcp_data/sm2-client-enc-key.pem +@@ -0,0 +1,5 @@ ++-----BEGIN PRIVATE KEY----- ++MIGHAgEAMBMGByqGSM49AgEGCCqBHM9VAYItBG0wawIBAQQg5xwdNhYtjBcZ5YEd ++VNu5609rYpePHUZUlQvlAJIqMB2hRANCAASyPG5mdJiLYzaIvi9SocV16AmrEAuQ ++XGr5eID8Ly9BIw4INrPxkfVesLBTeQxKGJDI0zwCSO58qAI4ZIHcHnyo ++-----END PRIVATE KEY----- +diff --git a/test/recipes/85-test_tlcp_data/sm2-client-sig-cert.pem b/test/recipes/85-test_tlcp_data/sm2-client-sig-cert.pem +new file mode 100644 +index 0000000..ce539a6 +--- /dev/null ++++ b/test/recipes/85-test_tlcp_data/sm2-client-sig-cert.pem +@@ -0,0 +1,12 @@ ++-----BEGIN CERTIFICATE----- ++MIIB3DCCAYKgAwIBAgIUMsQnTMiHshN4IOMc/ydgCOWB3WMwCgYIKoEcz1UBg3Uw ++XjELMAkGA1UEBhMCQ04xEjAQBgNVBAgMCUd1YW5nZG9uZzERMA8GA1UECgwIVGVz ++dCBPcmcxEDAOBgNVBAsMB1Rlc3QgT1UxFjAUBgNVBAMMDVRlc3QgQ0EgKFNNMikw ++HhcNMjIwNTE5MDkyNzEwWhcNMjYwNjI3MDkyNzEwWjBiMQswCQYDVQQGEwJDTjES ++MBAGA1UECAwJR3Vhbmdkb25nMREwDwYDVQQKDAhUZXN0IE9yZzEQMA4GA1UECwwH ++VGVzdCBPVTEaMBgGA1UEAwwRY2xpZW50IHNpZ24gKFNNMikwWTATBgcqhkjOPQIB ++BggqgRzPVQGCLQNCAAQDr0xTp4anFz8UHoMWyAWq/yYpiXdysF1dvciTvgET7CAA ++PydlOnKQw2K1NguwiecT4/XCpZMmbvhthMcCsyywoxowGDAJBgNVHRMEAjAAMAsG ++A1UdDwQEAwIGwDAKBggqgRzPVQGDdQNIADBFAiEA1pxw3tMJ6epz6r/wonHMWBE/ ++3MBbRIsOq9xxhOhqhyECIBR0V+O51j3gsuDwSqSU81rYLXPaE0RGuhbdWOHi4bII ++-----END CERTIFICATE----- +diff --git a/test/recipes/85-test_tlcp_data/sm2-client-sig-key.pem b/test/recipes/85-test_tlcp_data/sm2-client-sig-key.pem +new file mode 100644 +index 0000000..d2c537d +--- /dev/null ++++ b/test/recipes/85-test_tlcp_data/sm2-client-sig-key.pem +@@ -0,0 +1,5 @@ ++-----BEGIN PRIVATE KEY----- ++MIGHAgEAMBMGByqGSM49AgEGCCqBHM9VAYItBG0wawIBAQQg0x2USJzgAonYJeiQ ++VkBw/u6/uo6B9M88YVL3A1OmorKhRANCAAQDr0xTp4anFz8UHoMWyAWq/yYpiXdy ++sF1dvciTvgET7CAAPydlOnKQw2K1NguwiecT4/XCpZMmbvhthMcCsyyw ++-----END PRIVATE KEY----- +diff --git a/test/recipes/85-test_tlcp_data/sm2-root-cert.pem b/test/recipes/85-test_tlcp_data/sm2-root-cert.pem +new file mode 100644 +index 0000000..a20df8c +--- /dev/null ++++ b/test/recipes/85-test_tlcp_data/sm2-root-cert.pem +@@ -0,0 +1,14 @@ ++-----BEGIN CERTIFICATE----- ++MIICGjCCAcGgAwIBAgIUV3TWPlV09Vqm5/FpSqR7ryeGrfEwCgYIKoEcz1UBg3Uw ++XjELMAkGA1UEBhMCQ04xEjAQBgNVBAgMCUd1YW5nZG9uZzERMA8GA1UECgwIVGVz ++dCBPcmcxEDAOBgNVBAsMB1Rlc3QgT1UxFjAUBgNVBAMMDVRlc3QgQ0EgKFNNMikw ++HhcNMjIwNTE5MDkyNzEwWhcNMjYwNjI3MDkyNzEwWjBeMQswCQYDVQQGEwJDTjES ++MBAGA1UECAwJR3Vhbmdkb25nMREwDwYDVQQKDAhUZXN0IE9yZzEQMA4GA1UECwwH ++VGVzdCBPVTEWMBQGA1UEAwwNVGVzdCBDQSAoU00yKTBZMBMGByqGSM49AgEGCCqB ++HM9VAYItA0IABHsTJfkk1NiaYrPidOIQHCGWBs77fKEhXoG1uONGTfHEDhhhA3EX ++QZBL9cVO//farVmKF9ipYR9GA4pk0wHtGEKjXTBbMB0GA1UdDgQWBBQ9YT+D7/Cv ++3KqG4b9YxuWOSbMRRzAfBgNVHSMEGDAWgBQ9YT+D7/Cv3KqG4b9YxuWOSbMRRzAM ++BgNVHRMEBTADAQH/MAsGA1UdDwQEAwIBBjAKBggqgRzPVQGDdQNHADBEAiAOJ4al ++v3c1AHBohqZQkAAZsY9+LSH/3/e3C4Q4jQsDUQIgUDJFXbXSUrsMoKFmkvHONmz+ ++9zGXND9ctJ1Dineo9dI= ++-----END CERTIFICATE----- +diff --git a/test/recipes/85-test_tlcp_data/sm2-server-enc-cert.pem b/test/recipes/85-test_tlcp_data/sm2-server-enc-cert.pem +new file mode 100644 +index 0000000..c7a5ef2 +--- /dev/null ++++ b/test/recipes/85-test_tlcp_data/sm2-server-enc-cert.pem +@@ -0,0 +1,12 @@ ++-----BEGIN CERTIFICATE----- ++MIIB2jCCAYGgAwIBAgIUMsQnTMiHshN4IOMc/ydgCOWB3WIwCgYIKoEcz1UBg3Uw ++XjELMAkGA1UEBhMCQ04xEjAQBgNVBAgMCUd1YW5nZG9uZzERMA8GA1UECgwIVGVz ++dCBPcmcxEDAOBgNVBAsMB1Rlc3QgT1UxFjAUBgNVBAMMDVRlc3QgQ0EgKFNNMikw ++HhcNMjIwNTE5MDkyNzEwWhcNMjYwNjI3MDkyNzEwWjBhMQswCQYDVQQGEwJDTjES ++MBAGA1UECAwJR3Vhbmdkb25nMREwDwYDVQQKDAhUZXN0IE9yZzEQMA4GA1UECwwH ++VGVzdCBPVTEZMBcGA1UEAwwQc2VydmVyIGVuYyAoU00yKTBZMBMGByqGSM49AgEG ++CCqBHM9VAYItA0IABCWsJ/Vs/68DYkqIgoTdE8zoOA86UMHLASZriw+AF0lbmiOD ++dngO7RvDd55OOAmFK6sY7d+vzsIeMNQus4YLkc2jGjAYMAkGA1UdEwQCMAAwCwYD ++VR0PBAQDAgM4MAoGCCqBHM9VAYN1A0cAMEQCICZgP6OiaVyAbYTX5yJpiwusEvDU ++bMB/+hpnNA0ors3zAiB4EkZEBWZkd0su+umAXpO44IYaDvUumPSaGZLBbg7m1w== ++-----END CERTIFICATE----- +diff --git a/test/recipes/85-test_tlcp_data/sm2-server-enc-key.pem b/test/recipes/85-test_tlcp_data/sm2-server-enc-key.pem +new file mode 100644 +index 0000000..ae509ec +--- /dev/null ++++ b/test/recipes/85-test_tlcp_data/sm2-server-enc-key.pem +@@ -0,0 +1,5 @@ ++-----BEGIN PRIVATE KEY----- ++MIGHAgEAMBMGByqGSM49AgEGCCqBHM9VAYItBG0wawIBAQQgE32DrOaCm3ai/cPZ ++/9nnxJoCH171qVL7ignjIrMBGdGhRANCAAQlrCf1bP+vA2JKiIKE3RPM6DgPOlDB ++ywEma4sPgBdJW5ojg3Z4Du0bw3eeTjgJhSurGO3fr87CHjDULrOGC5HN ++-----END PRIVATE KEY----- +diff --git a/test/recipes/85-test_tlcp_data/sm2-server-sig-cert.pem b/test/recipes/85-test_tlcp_data/sm2-server-sig-cert.pem +new file mode 100644 +index 0000000..8238bad +--- /dev/null ++++ b/test/recipes/85-test_tlcp_data/sm2-server-sig-cert.pem +@@ -0,0 +1,12 @@ ++-----BEGIN CERTIFICATE----- ++MIIB2zCCAYKgAwIBAgIUMsQnTMiHshN4IOMc/ydgCOWB3WEwCgYIKoEcz1UBg3Uw ++XjELMAkGA1UEBhMCQ04xEjAQBgNVBAgMCUd1YW5nZG9uZzERMA8GA1UECgwIVGVz ++dCBPcmcxEDAOBgNVBAsMB1Rlc3QgT1UxFjAUBgNVBAMMDVRlc3QgQ0EgKFNNMikw ++HhcNMjIwNTE5MDkyNzEwWhcNMjYwNjI3MDkyNzEwWjBiMQswCQYDVQQGEwJDTjES ++MBAGA1UECAwJR3Vhbmdkb25nMREwDwYDVQQKDAhUZXN0IE9yZzEQMA4GA1UECwwH ++VGVzdCBPVTEaMBgGA1UEAwwRc2VydmVyIHNpZ24gKFNNMikwWTATBgcqhkjOPQIB ++BggqgRzPVQGCLQNCAAQgP2f+HnNb6BWCGscITDpf53BwVvpj3gxrlHz05Po3i2IA ++qyL5yL2VE+bqTrxCFpQOHupjW3f5Bkihv7IUW/zMoxowGDAJBgNVHRMEAjAAMAsG ++A1UdDwQEAwIGwDAKBggqgRzPVQGDdQNHADBEAiA63GVhHaDzcVJ9DMLK/53wQZvg ++HR+tj4MCBtb6F9hL9QIgbojf0R49GnO6VYHHUx0fe+4+2DfAcMdVIutOmbpRc60= ++-----END CERTIFICATE----- +diff --git a/test/recipes/85-test_tlcp_data/sm2-server-sig-key.pem b/test/recipes/85-test_tlcp_data/sm2-server-sig-key.pem +new file mode 100644 +index 0000000..f7fa712 +--- /dev/null ++++ b/test/recipes/85-test_tlcp_data/sm2-server-sig-key.pem +@@ -0,0 +1,5 @@ ++-----BEGIN PRIVATE KEY----- ++MIGHAgEAMBMGByqGSM49AgEGCCqBHM9VAYItBG0wawIBAQQgr9nuyaNIE7aSQw/I ++sc7JhizpuCPUNKBF9zZy1on8BHShRANCAAQgP2f+HnNb6BWCGscITDpf53BwVvpj ++3gxrlHz05Po3i2IAqyL5yL2VE+bqTrxCFpQOHupjW3f5Bkihv7IUW/zM ++-----END PRIVATE KEY----- +diff --git a/test/tlcptest.c b/test/tlcptest.c +new file mode 100644 +index 0000000..057d3a9 +--- /dev/null ++++ b/test/tlcptest.c +@@ -0,0 +1,434 @@ ++/* ++ * Copyright 2022 Huawei Technologies Co., Ltd. All Rights Reserved. ++ * ++ * Licensed under the OpenSSL license (the "License"). You may not use ++ * this file except in compliance with the License. You can obtain a copy ++ * in the file LICENSE in the source distribution or at ++ * https://www.openssl.org/source/license.html ++ */ ++ ++#include ++#include ++#include ++#include ++#include ++ ++#include "internal/nelem.h" ++#include "ssltestlib.h" ++#include "testutil.h" ++ ++#ifndef OPENSSL_NO_TLCP ++ ++typedef enum { ++ IDX_SM2_ROOT_CERT = 0, ++ IDX_SM2_SERVER_SIG_CERT, ++ IDX_SM2_SERVER_SIG_KEY, ++ IDX_SM2_SERVER_ENC_CERT, ++ IDX_SM2_SERVER_ENC_KEY, ++ IDX_SM2_CLIENT_SIG_CERT, ++ IDX_SM2_CLIENT_SIG_KEY, ++ IDX_SM2_CLIENT_ENC_CERT, ++ IDX_SM2_CLIENT_ENC_KEY, ++ IDX_ECDSA_ROOT_CERT, ++ IDX_ECDSA_SERVER_CERT, ++ IDX_ECDSA_SERVER_KEY, ++ IDX_ECDSA_CLIENT_CERT, ++ IDX_ECDSA_CLIENT_KEY, ++ IDX_MAX ++} TEST_FILES_IDX; ++ ++#define OPTION_IS_CA 0x00000001U ++#define OPTION_IS_CERT 0x00000002U ++#define OPTION_IS_KEY 0x00000004U ++#define OPTION_USE_NEWAPI 0x00000008U ++#define OPTION_USE_EXTRA 0x00000010U ++#define OPTION_IS_SIG 0x00000020U ++#define OPTION_IS_ENC 0x00000040U ++ ++typedef struct { ++ TEST_FILES_IDX idx; ++ int flag; ++} LOAD_OPTION; ++ ++typedef struct { ++ const char *method_name; ++ int verify_mode; ++ int ssl_options; ++ int set_version; ++ LOAD_OPTION load_options[IDX_MAX]; ++} SSL_CTX_OPTION; ++ ++typedef struct { ++ const char *case_name; ++ SSL_CTX_OPTION server; ++ SSL_CTX_OPTION client; ++ const char *ciphersuite; ++ const char *expected_version; ++ const char *expected_cipher; ++} TLCP_TEST_CASE; ++ ++static const TLCP_TEST_CASE tlcp_test_cases[] = { ++ { "test_ecc_and_cert_position", ++ { ++ "TLS_server", SSL_VERIFY_PEER, SSL_OP_ENCCERT_SECOND_POSITION, 0, ++ { ++ {IDX_SM2_ROOT_CERT, OPTION_IS_CA}, ++ {IDX_SM2_SERVER_SIG_CERT, OPTION_USE_NEWAPI | OPTION_IS_SIG | OPTION_IS_CERT }, ++ {IDX_SM2_SERVER_SIG_KEY, OPTION_USE_NEWAPI | OPTION_IS_SIG | OPTION_IS_KEY }, ++ {IDX_SM2_SERVER_ENC_CERT, OPTION_USE_NEWAPI | OPTION_IS_ENC | OPTION_IS_CERT }, ++ {IDX_SM2_SERVER_ENC_KEY, OPTION_USE_NEWAPI | OPTION_IS_ENC | OPTION_IS_KEY } ++ } ++ }, ++ { ++ "TLCP_client", SSL_VERIFY_PEER, SSL_OP_ENCCERT_SECOND_POSITION, 0, ++ { ++ {IDX_SM2_ROOT_CERT, OPTION_IS_CA}, ++ {IDX_SM2_CLIENT_SIG_CERT, OPTION_USE_NEWAPI | OPTION_IS_SIG | OPTION_IS_CERT }, ++ {IDX_SM2_CLIENT_SIG_KEY, OPTION_USE_NEWAPI | OPTION_IS_SIG | OPTION_IS_KEY }, ++ {IDX_SM2_CLIENT_ENC_CERT, OPTION_USE_NEWAPI | OPTION_IS_ENC | OPTION_IS_CERT }, ++ {IDX_SM2_CLIENT_ENC_KEY, OPTION_USE_NEWAPI | OPTION_IS_ENC | OPTION_IS_KEY } ++ } ++ }, ++ "ECC-SM4-CBC-SM3", ++ "TLCP", ++ "ECC-SM4-CBC-SM3" ++ }, ++ { "test_extra_cert", ++ { ++ "TLS_server", SSL_VERIFY_NONE, 0, 0, ++ { ++ {IDX_SM2_ROOT_CERT, OPTION_IS_CA | OPTION_USE_EXTRA}, ++ {IDX_SM2_SERVER_SIG_CERT, OPTION_USE_NEWAPI | OPTION_IS_SIG | OPTION_IS_CERT }, ++ {IDX_SM2_SERVER_SIG_KEY, OPTION_USE_NEWAPI | OPTION_IS_SIG | OPTION_IS_KEY }, ++ {IDX_SM2_SERVER_ENC_CERT, OPTION_USE_NEWAPI | OPTION_IS_ENC | OPTION_IS_CERT }, ++ {IDX_SM2_SERVER_ENC_KEY, OPTION_USE_NEWAPI | OPTION_IS_ENC | OPTION_IS_KEY } ++ } ++ }, ++ { ++ "TLCP_client", SSL_VERIFY_NONE, 0, 0, ++ { ++ {IDX_SM2_ROOT_CERT, OPTION_IS_CA | OPTION_USE_EXTRA}, ++ {IDX_SM2_CLIENT_SIG_CERT, OPTION_USE_NEWAPI | OPTION_IS_SIG | OPTION_IS_CERT }, ++ {IDX_SM2_CLIENT_SIG_KEY, OPTION_USE_NEWAPI | OPTION_IS_SIG | OPTION_IS_KEY }, ++ {IDX_SM2_CLIENT_ENC_CERT, OPTION_USE_NEWAPI | OPTION_IS_ENC | OPTION_IS_CERT }, ++ {IDX_SM2_CLIENT_ENC_KEY, OPTION_USE_NEWAPI | OPTION_IS_ENC | OPTION_IS_KEY } ++ } ++ }, ++ "ECC-SM4-CBC-SM3", ++ "TLCP", ++ "ECC-SM4-CBC-SM3" ++ }, ++ { "test_ssl_op_no", ++ { ++ "TLS_server", SSL_VERIFY_PEER, SSL_OP_NO_TLSv1_3 | SSL_OP_NO_TLSv1_2 | SSL_OP_NO_TLSv1_1 | SSL_OP_NO_TLSv1 | SSL_OP_NO_SSLv3, 0, ++ { ++ {IDX_SM2_ROOT_CERT, OPTION_IS_CA}, ++ {IDX_SM2_SERVER_SIG_CERT, OPTION_USE_NEWAPI | OPTION_IS_SIG | OPTION_IS_CERT }, ++ {IDX_SM2_SERVER_SIG_KEY, OPTION_USE_NEWAPI | OPTION_IS_SIG | OPTION_IS_KEY }, ++ {IDX_SM2_SERVER_ENC_CERT, OPTION_USE_NEWAPI | OPTION_IS_ENC | OPTION_IS_CERT }, ++ {IDX_SM2_SERVER_ENC_KEY, OPTION_USE_NEWAPI | OPTION_IS_ENC | OPTION_IS_KEY } ++ } ++ }, ++ { ++ "TLS_client", SSL_VERIFY_PEER, SSL_OP_NO_TLSv1_3 | SSL_OP_NO_TLSv1_2 | SSL_OP_NO_TLSv1_1 | SSL_OP_NO_TLSv1 | SSL_OP_NO_SSLv3, 0, ++ { ++ {IDX_SM2_ROOT_CERT, OPTION_IS_CA}, ++ {IDX_SM2_CLIENT_SIG_CERT, OPTION_USE_NEWAPI | OPTION_IS_SIG | OPTION_IS_CERT }, ++ {IDX_SM2_CLIENT_SIG_KEY, OPTION_USE_NEWAPI | OPTION_IS_SIG | OPTION_IS_KEY }, ++ {IDX_SM2_CLIENT_ENC_CERT, OPTION_USE_NEWAPI | OPTION_IS_ENC | OPTION_IS_CERT }, ++ {IDX_SM2_CLIENT_ENC_KEY, OPTION_USE_NEWAPI | OPTION_IS_ENC | OPTION_IS_KEY } ++ } ++ }, ++ "ECC-SM4-CBC-SM3", ++ "TLCP", ++ "ECC-SM4-CBC-SM3" ++ }, ++ { "test_set_version_bound", ++ { ++ "TLCP_server", SSL_VERIFY_PEER, 0, TLCP_VERSION, ++ { ++ {IDX_SM2_ROOT_CERT, OPTION_IS_CA}, ++ {IDX_SM2_SERVER_SIG_CERT, OPTION_USE_NEWAPI | OPTION_IS_SIG | OPTION_IS_CERT }, ++ {IDX_SM2_SERVER_SIG_KEY, OPTION_USE_NEWAPI | OPTION_IS_SIG | OPTION_IS_KEY }, ++ {IDX_SM2_SERVER_ENC_CERT, OPTION_USE_NEWAPI | OPTION_IS_ENC | OPTION_IS_CERT }, ++ {IDX_SM2_SERVER_ENC_KEY, OPTION_USE_NEWAPI | OPTION_IS_ENC | OPTION_IS_KEY } ++ } ++ }, ++ { ++ "TLS_client", SSL_VERIFY_PEER, 0, TLCP_VERSION, ++ { ++ {IDX_SM2_ROOT_CERT, OPTION_IS_CA}, ++ {IDX_SM2_CLIENT_SIG_CERT, OPTION_USE_NEWAPI | OPTION_IS_SIG | OPTION_IS_CERT }, ++ {IDX_SM2_CLIENT_SIG_KEY, OPTION_USE_NEWAPI | OPTION_IS_SIG | OPTION_IS_KEY }, ++ {IDX_SM2_CLIENT_ENC_CERT, OPTION_USE_NEWAPI | OPTION_IS_ENC | OPTION_IS_CERT }, ++ {IDX_SM2_CLIENT_ENC_KEY, OPTION_USE_NEWAPI | OPTION_IS_ENC | OPTION_IS_KEY } ++ } ++ }, ++ NULL, ++ "TLCP", ++ "ECC-SM4-CBC-SM3" ++ }, ++ { "test_use_old_api_and_other_certs", ++ { ++ "TLS_server", SSL_VERIFY_PEER, 0, 0, ++ { ++ {IDX_SM2_ROOT_CERT, OPTION_IS_CA}, ++ {IDX_SM2_SERVER_SIG_CERT, OPTION_IS_SIG | OPTION_IS_CERT }, ++ {IDX_SM2_SERVER_SIG_KEY, OPTION_IS_SIG | OPTION_IS_KEY }, ++ {IDX_SM2_SERVER_ENC_CERT, OPTION_IS_ENC | OPTION_IS_CERT }, ++ {IDX_SM2_SERVER_ENC_KEY, OPTION_IS_ENC | OPTION_IS_KEY }, ++ {IDX_ECDSA_ROOT_CERT, OPTION_IS_CA}, ++ {IDX_ECDSA_SERVER_CERT, OPTION_IS_CERT}, ++ {IDX_ECDSA_SERVER_KEY, OPTION_IS_KEY} ++ } ++ }, ++ { ++ "TLCP_client", SSL_VERIFY_PEER, 0, 0, ++ { ++ {IDX_SM2_ROOT_CERT, OPTION_IS_CA}, ++ {IDX_SM2_CLIENT_SIG_CERT, OPTION_IS_SIG | OPTION_IS_CERT }, ++ {IDX_SM2_CLIENT_SIG_KEY, OPTION_IS_SIG | OPTION_IS_KEY }, ++ {IDX_SM2_CLIENT_ENC_CERT, OPTION_IS_ENC | OPTION_IS_CERT }, ++ {IDX_SM2_CLIENT_ENC_KEY, OPTION_IS_ENC | OPTION_IS_KEY }, ++ {IDX_ECDSA_ROOT_CERT, OPTION_IS_CA}, ++ {IDX_ECDSA_CLIENT_CERT, OPTION_IS_CERT}, ++ {IDX_ECDSA_CLIENT_KEY, OPTION_IS_KEY} ++ } ++ }, ++ NULL, ++ "TLCP", ++ "ECC-SM4-CBC-SM3" ++ } ++}; ++ ++static const char *test_files[IDX_MAX]; ++ ++static X509 *PEM_file_to_X509(const char *file) ++{ ++ BIO *in; ++ X509 *x = NULL; ++ ++ in = BIO_new(BIO_s_file()); ++ if (in == NULL || BIO_read_filename(in, file) <= 0) ++ goto err; ++ ++ x = PEM_read_bio_X509(in, NULL, NULL, NULL); ++err: ++ BIO_free(in); ++ return x; ++} ++ ++static EVP_PKEY *PEM_file_to_PrivateKey(const char *file) ++{ ++ BIO *in; ++ EVP_PKEY *pkey = NULL; ++ ++ in = BIO_new(BIO_s_file()); ++ if (in == NULL || BIO_read_filename(in, file) <= 0) ++ goto err; ++ ++ pkey = PEM_read_bio_PrivateKey(in, NULL, NULL, NULL); ++err: ++ BIO_free(in); ++ return pkey; ++} ++ ++static int use_extra_cert_file(SSL_CTX *ctx, const char *file) ++{ ++ X509 *x; ++ ++ x = PEM_file_to_X509(file); ++ ++ if (x == NULL) ++ return 0; ++ ++ if (!SSL_CTX_add_extra_chain_cert(ctx, x)) { ++ X509_free(x); ++ return 0; ++ } ++ return 1; ++} ++ ++static int load_test_file_by_option(SSL_CTX *ctx, LOAD_OPTION opt) ++{ ++ int usage = -1; ++ if (opt.idx >= IDX_MAX) ++ return 0; ++ ++ if (opt.flag & OPTION_IS_CA) { ++ return (opt.flag & OPTION_USE_EXTRA) ++ ? use_extra_cert_file(ctx, test_files[opt.idx]) ++ : SSL_CTX_load_verify_locations(ctx, test_files[opt.idx], NULL); ++ } ++ ++ if (opt.flag & OPTION_IS_SIG) { ++ usage = SSL_USAGE_SIG; ++ } else if (opt.flag & OPTION_IS_ENC) { ++ usage = SSL_USAGE_ENC; ++ } ++ ++ if (opt.flag & OPTION_IS_CERT) { ++ return (opt.flag & OPTION_USE_NEWAPI) ++ ? SSL_CTX_use_gm_certificate_file(ctx, test_files[opt.idx], SSL_FILETYPE_PEM, usage) ++ : SSL_CTX_use_certificate_file(ctx, test_files[opt.idx], SSL_FILETYPE_PEM); ++ } else if (opt.flag & OPTION_IS_KEY){ ++ return (opt.flag & OPTION_USE_NEWAPI) ++ ? SSL_CTX_use_gm_PrivateKey_file(ctx, test_files[opt.idx], SSL_FILETYPE_PEM, usage) ++ : SSL_CTX_use_PrivateKey_file(ctx, test_files[opt.idx], SSL_FILETYPE_PEM); ++ } ++ return 1; ++} ++ ++static int load_test_files(SSL_CTX *ctx, LOAD_OPTION *opt, size_t optlen) ++{ ++ int i; ++ for (i = 0; i < optlen; ++i) { ++ if (!load_test_file_by_option(ctx, opt[i])) { ++ return 0; ++ } ++ } ++ return 1; ++} ++ ++static SSL_CTX *SSL_CTX_create_by_option(const SSL_CTX_OPTION *opt) ++{ ++ SSL_CTX *ctx = NULL; ++ if (opt == NULL) ++ return NULL; ++ ++ if (strcmp(opt->method_name, "TLS_server") == 0) { ++ ctx = SSL_CTX_new(TLS_server_method()); ++ } else if (strcmp(opt->method_name, "TLS_client") == 0) { ++ ctx = SSL_CTX_new(TLS_client_method()); ++ } else if (strcmp(opt->method_name, "TLCP_server") == 0) { ++ ctx = SSL_CTX_new(TLCP_server_method()); ++ } else if (strcmp(opt->method_name, "TLCP_client") == 0) { ++ ctx = SSL_CTX_new(TLCP_client_method()); ++ } ++ if (ctx == NULL) ++ return NULL; ++ ++ SSL_CTX_set_verify(ctx, opt->verify_mode, NULL); ++ SSL_CTX_set_options(ctx, opt->ssl_options); ++ SSL_CTX_set_min_proto_version(ctx, opt->set_version); ++ SSL_CTX_set_max_proto_version(ctx, opt->set_version); ++ ++ if (!load_test_files(ctx, (LOAD_OPTION *)opt->load_options, OSSL_NELEM(opt->load_options))) { ++ SSL_CTX_free(ctx); ++ return NULL; ++ } ++ return ctx; ++} ++ ++static int test_tlcp_ciphersuites(int idx) ++{ ++ int result = 0; ++ SSL_CTX *server_ctx = NULL; ++ SSL_CTX *client_ctx = NULL; ++ SSL *server_ssl = NULL; ++ SSL *client_ssl = NULL; ++ const TLCP_TEST_CASE *case_ptr; ++ ++ case_ptr = &tlcp_test_cases[idx]; ++ if (!TEST_ptr(server_ctx = SSL_CTX_create_by_option(&case_ptr->server)) ++ || !TEST_ptr(client_ctx = SSL_CTX_create_by_option(&case_ptr->client))) ++ goto err; ++ ++ if (case_ptr->ciphersuite != NULL && ++ !TEST_int_eq(SSL_CTX_set_cipher_list(client_ctx, case_ptr->ciphersuite), 1)) ++ goto err; ++ ++ if (!TEST_int_eq(create_ssl_objects(server_ctx, client_ctx ++ , &server_ssl, &client_ssl, NULL, NULL), 1)) ++ goto err; ++ ++ if (!TEST_int_eq(create_ssl_connection(server_ssl, client_ssl, SSL_ERROR_NONE), 1)) ++ goto err; ++ ++ if (case_ptr->expected_version != NULL && ++ !TEST_str_eq(SSL_get_version(client_ssl), case_ptr->expected_version)) ++ goto err; ++ ++ if (case_ptr->expected_cipher && ++ !TEST_str_eq(SSL_get_cipher(client_ssl), case_ptr->expected_cipher)) ++ goto err; ++ ++ result = 1; ++err: ++ if (server_ssl != NULL) ++ SSL_shutdown(server_ssl); ++ if (client_ssl != NULL) ++ SSL_shutdown(client_ssl); ++ SSL_free(server_ssl); ++ SSL_free(client_ssl); ++ SSL_CTX_free(server_ctx); ++ SSL_CTX_free(client_ctx); ++ return result; ++} ++ ++static int test_use_certs_and_keys(void) ++{ ++ SSL_CTX *ctx = NULL; ++ SSL *ssl = NULL; ++ X509 *x = NULL; ++ EVP_PKEY *pkey = NULL; ++ int result = 0; ++ ++ ctx = SSL_CTX_new(TLCP_method()); ++ if (ctx == NULL) ++ goto err; ++ ++ ssl = SSL_new(ctx); ++ if (ssl == NULL) ++ goto err; ++ ++ if (!TEST_int_ne(SSL_use_gm_certificate_file(ssl, test_files[IDX_ECDSA_SERVER_CERT], ++ SSL_FILETYPE_PEM, SSL_USAGE_SIG), 1) ++ || !TEST_int_ne(SSL_use_gm_PrivateKey_file(ssl, test_files[IDX_ECDSA_CLIENT_KEY], ++ SSL_FILETYPE_PEM, SSL_USAGE_SIG), 1)) { ++ goto err; ++ } ++ ++ if (!TEST_int_eq(SSL_use_certificate_file(ssl, test_files[IDX_SM2_SERVER_SIG_CERT], ++ SSL_FILETYPE_PEM), 1) ++ || !TEST_int_eq(SSL_use_gm_PrivateKey_file(ssl, test_files[IDX_SM2_SERVER_SIG_KEY], ++ SSL_FILETYPE_PEM, SSL_USAGE_SIG), 1) ++ || !TEST_int_eq(SSL_use_gm_certificate_file(ssl, test_files[IDX_SM2_SERVER_ENC_CERT], ++ SSL_FILETYPE_PEM, SSL_USAGE_ENC), 1) ++ || !TEST_int_eq(SSL_use_PrivateKey_file(ssl, test_files[IDX_SM2_SERVER_ENC_KEY], ++ SSL_FILETYPE_PEM), 1)){ ++ goto err; ++ } ++ ++ if (!TEST_ptr(x = PEM_file_to_X509(test_files[IDX_SM2_CLIENT_SIG_CERT])) ++ || !TEST_ptr(pkey = PEM_file_to_PrivateKey(test_files[IDX_SM2_CLIENT_SIG_KEY])) ++ || !TEST_int_eq(SSL_use_gm_cert_and_key(ssl, x, pkey, NULL, 1, SSL_USAGE_SIG), 1)) { ++ goto err; ++ } ++ result = 1; ++err: ++ X509_free(x); ++ EVP_PKEY_free(pkey); ++ SSL_free(ssl); ++ SSL_CTX_free(ctx); ++ return result; ++} ++ ++#endif ++ ++int setup_tests(void) ++{ ++#ifndef OPENSSL_NO_TLCP ++ int argc; ++ ++ for (argc = 0; argc < IDX_MAX; ++argc) { ++ if (!TEST_ptr(test_files[argc] = test_get_argument(argc))) { ++ return 0; ++ } ++ } ++ ++ ADD_ALL_TESTS(test_tlcp_ciphersuites, OSSL_NELEM(tlcp_test_cases)); ++ ADD_TEST(test_use_certs_and_keys); ++#endif ++ return 1; ++} +diff --git a/util/libcrypto.num b/util/libcrypto.num +index 81a6388..95bccf9 100644 +--- a/util/libcrypto.num ++++ b/util/libcrypto.num +@@ -4630,3 +4630,5 @@ X509_set0_sm2_id 6383 1_1_1m EXIST::FUNCTION:SM2 + X509_get0_sm2_id 6384 1_1_1m EXIST::FUNCTION:SM2 + X509_REQ_get0_sm2_id 6385 1_1_1m EXIST::FUNCTION:SM2 + X509_REQ_set0_sm2_id 6386 1_1_1m EXIST::FUNCTION:SM2 ++EVP_PKEY_is_sm2 6387 1_1_1m EXIST::FUNCTION:SM2 ++SM2_compute_key 6388 1_1_1m EXIST::FUNCTION: +diff --git a/util/libssl.num b/util/libssl.num +index 297522c..f120bed 100644 +--- a/util/libssl.num ++++ b/util/libssl.num +@@ -498,3 +498,20 @@ SSL_CTX_get_recv_max_early_data 498 1_1_1 EXIST::FUNCTION: + SSL_CTX_set_recv_max_early_data 499 1_1_1 EXIST::FUNCTION: + SSL_CTX_set_post_handshake_auth 500 1_1_1 EXIST::FUNCTION: + SSL_get_signature_type_nid 501 1_1_1a EXIST::FUNCTION: ++SSL_use_gm_PrivateKey 502 1_1_1m EXIST::FUNCTION:TLCP ++SSL_CTX_use_gm_certificate_file 503 1_1_1m EXIST::FUNCTION:TLCP ++SSL_CTX_use_gm_certificate 504 1_1_1m EXIST::FUNCTION:TLCP ++SSL_use_gm_certificate_file 505 1_1_1m EXIST::FUNCTION:TLCP ++SSL_CTX_use_gm_certificate_ASN1 506 1_1_1m EXIST::FUNCTION:TLCP ++SSL_use_gm_PrivateKey_file 507 1_1_1m EXIST::FUNCTION:TLCP ++TLCP_method 508 1_1_1m EXIST::FUNCTION:TLCP ++SSL_CTX_use_gm_PrivateKey_file 509 1_1_1m EXIST::FUNCTION:TLCP ++SSL_use_gm_PrivateKey_ASN1 510 1_1_1m EXIST::FUNCTION:TLCP ++TLCP_client_method 511 1_1_1m EXIST::FUNCTION:TLCP ++SSL_CTX_use_gm_cert_and_key 512 1_1_1m EXIST::FUNCTION:TLCP ++SSL_CTX_use_gm_PrivateKey 513 1_1_1m EXIST::FUNCTION:TLCP ++TLCP_server_method 514 1_1_1m EXIST::FUNCTION:TLCP ++SSL_use_gm_cert_and_key 515 1_1_1m EXIST::FUNCTION:TLCP ++SSL_use_gm_certificate 516 1_1_1m EXIST::FUNCTION:TLCP ++SSL_use_gm_certificate_ASN1 517 1_1_1m EXIST::FUNCTION:TLCP ++SSL_CTX_use_gm_PrivateKey_ASN1 518 1_1_1m EXIST::FUNCTION:TLCP +-- +2.20.1 (Apple Git-117) + diff --git a/openssl.spec b/openssl.spec index 3400121..5adf721 100644 --- a/openssl.spec +++ b/openssl.spec @@ -2,7 +2,7 @@ Name: openssl Epoch: 1 Version: 1.1.1m -Release: 2 +Release: 3 Summary: Cryptography and SSL/TLS Toolkit License: OpenSSL and SSLeay URL: https://www.openssl.org/ @@ -13,6 +13,8 @@ Patch2: openssl-1.1.1-fips.patch Patch3: CVE-2022-0778-Add-a-negative-testcase-for-BN_mod_sqrt.patch Patch4: CVE-2022-0778-Fix-possible-infinite-loop-in-BN_mod_sqrt.patch Patch5: CVE-2022-1292.patch +Patch6: Backport-Support-SM2-certificate-signing-and-verification.patch +Patch7: Feature-Support-TLCP-protocol.patch BuildRequires: gcc perl make lksctp-tools-devel coreutils util-linux zlib-devel Requires: coreutils %{name}-libs%{?_isa} = %{epoch}:%{version}-%{release} @@ -75,7 +77,7 @@ RPM_OPT_FLAGS="$RPM_OPT_FLAGS -Wa,--noexecstack -DPURIFY $RPM_LD_FLAGS" zlib enable-camellia enable-seed enable-rfc3779 enable-sctp \ enable-cms enable-md2 enable-rc5 enable-ssl3 enable-ssl3-method \ enable-weak-ssl-ciphers \ - no-mdc2 no-ec2m enable-sm2 enable-sm4 \ + no-mdc2 no-ec2m enable-sm2 enable-sm4 enable-tlcp \ shared ${sslarch} $RPM_OPT_FLAGS '-DDEVRANDOM="\"/dev/urandom\""' %make_build all @@ -209,6 +211,9 @@ make test || : %ldconfig_scriptlets libs %changelog +* Tue Jun 8 2022 zhouchenchen - 1:1.1.1m-3 +- add TLCP feature + * Mon May 16 2022 zhouchenchen - 1:1.1.1m-2 - fix the CVE-2022-1292 -- Gitee