代码拉取完成,页面将自动刷新
同步操作将从 src-openEuler/openssl 强制同步,此操作会覆盖自 Fork 仓库以来所做的任何修改,且无法恢复!!!
确定后同步将在后台操作,完成时将刷新页面,请耐心等待。
From 0bacd53ecedfef3ca8af4a8884c46ec8e47c83fa Mon Sep 17 00:00:00 2001
From: Paul Yang <yang.yang@baishancloud.com>
Date: Wed, 5 Jun 2019 14:46:48 +0800
Subject: [PATCH 10/15] Support SM2 certificate signing
SM2 certificate signing request can be created and signed by OpenSSL
now, both in library and apps.
Documentation and test cases are added.
Reviewed-by: Tim Hudson <tjh@openssl.org>
Reviewed-by: Shane Lontis <shane.lontis@oracle.com>
(Merged from https://github.com/openssl/openssl/pull/9085)
---
CHANGES | 3 +
apps/ca.c | 68 ++++++++++++-
apps/req.c | 149 ++++++++++++++++++++++++++--
crypto/asn1/a_sign.c | 13 ++-
crypto/ec/ec_pmeth.c | 3 +-
crypto/err/openssl.txt | 3 +
crypto/x509/x509_err.c | 4 +
crypto/x509/x_all.c | 85 ++++++++++++----
crypto/x509/x_req.c | 38 ++++++-
crypto/x509/x_x509.c | 3 +
doc/man1/ca.pod | 16 +++
doc/man1/req.pod | 21 ++++
doc/man3/X509_get0_sm2_id.pod | 12 ++-
include/crypto/x509.h | 3 +
include/openssl/x509.h | 2 +
include/openssl/x509err.h | 3 +
test/certs/sm2-csr.pem | 9 ++
test/certs/sm2-root.crt | 14 +++
test/certs/sm2-root.key | 5 +
test/recipes/25-test_req.t | 21 +++-
test/recipes/70-test_verify_extra.t | 3 +-
test/recipes/80-test_ca.t | 20 +++-
test/verify_extra_test.c | 45 ++++++++-
util/libcrypto.num | 2 +
24 files changed, 501 insertions(+), 44 deletions(-)
create mode 100644 test/certs/sm2-csr.pem
create mode 100644 test/certs/sm2-root.crt
create mode 100644 test/certs/sm2-root.key
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/req.c b/apps/req.c
index a603907..96f1edd 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,20 @@ 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)
rv = X509_sign_ctx(x, mctx);
+#ifndef OPENSSL_NO_SM2
+ /* only in SM2 case we need to free the pctx explicitly */
+ 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 +1774,20 @@ 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)
rv = X509_REQ_sign_ctx(x, mctx);
+#ifndef OPENSSL_NO_SM2
+ /* only in SM2 case we need to free the pctx explicitly */
+ 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 +1797,20 @@ 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)
rv = X509_CRL_sign_ctx(x, mctx);
+#ifndef OPENSSL_NO_SM2
+ /* only in SM2 case we need to free the pctx explicitly */
+ 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/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/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 5e71e65..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
diff --git a/crypto/x509/x509_err.c b/crypto/x509/x509_err.c
index c91ad7c..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),
diff --git a/crypto/x509/x_all.c b/crypto/x509/x_all.c
index 9c8aea5..5c371f5 100644
--- a/crypto/x509/x_all.c
+++ b/crypto/x509/x_all.c
@@ -24,86 +24,105 @@
# include "crypto/asn1.h"
# include "crypto/evp.h"
-static int x509_verify_sm2(X509 *x, EVP_PKEY *pkey, int mdnid, int pknid)
+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_X509_VERIFY_SM2,
+ X509err(X509_F_COMMON_VERIFY_SM2,
ASN1_R_UNKNOWN_MESSAGE_DIGEST_ALGORITHM);
goto err;
}
if (pkey == NULL) {
- X509err(X509_F_X509_VERIFY_SM2, ERR_R_PASSED_NULL_PARAMETER);
+ X509err(X509_F_COMMON_VERIFY_SM2, ERR_R_PASSED_NULL_PARAMETER);
return -1;
}
- if (x->signature.type == V_ASN1_BIT_STRING && x->signature.flags & 0x7) {
- X509err(X509_F_X509_VERIFY_SM2, ASN1_R_INVALID_BIT_STRING_BITS_LEFT);
+ 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_X509_VERIFY_SM2, ERR_R_MALLOC_FAILURE);
+ 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_X509_VERIFY_SM2, ASN1_R_WRONG_PUBLIC_KEY_TYPE);
+ 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_X509_VERIFY_SM2, ERR_R_EVP_LIB);
+ 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_X509_VERIFY_SM2, ERR_R_EVP_LIB);
+ 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 (x->sm2_id != NULL
- && EVP_PKEY_CTX_set1_id(pctx, x->sm2_id->data,
- x->sm2_id->length) != 1) {
- X509err(X509_F_X509_VERIFY_SM2, ERR_R_EVP_LIB);
+ 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_X509_VERIFY_SM2, ERR_R_EVP_LIB);
+ X509err(X509_F_COMMON_VERIFY_SM2, ERR_R_EVP_LIB);
ret = 0;
goto err;
}
- inl = ASN1_item_i2d((ASN1_VALUE *)&x->cert_info, &buf_in,
+ 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_X509_VERIFY_SM2, ERR_R_INTERNAL_ERROR);
+ X509err(X509_F_COMMON_VERIFY_SM2, ERR_R_INTERNAL_ERROR);
goto err;
}
if (buf_in == NULL) {
- X509err(X509_F_X509_VERIFY_SM2, ERR_R_MALLOC_FAILURE);
+ X509err(X509_F_COMMON_VERIFY_SM2, ERR_R_MALLOC_FAILURE);
goto err;
}
inll = inl;
- ret = EVP_DigestVerify(ctx, x->signature.data,
- (size_t)x->signature.length, buf_in, inl);
+ ret = EVP_DigestVerify(ctx, signature->data,
+ (size_t)signature->length, buf_in, inl);
if (ret <= 0) {
- X509err(X509_F_X509_VERIFY_SM2, ERR_R_EVP_LIB);
+ X509err(X509_F_COMMON_VERIFY_SM2, ERR_R_EVP_LIB);
goto err;
}
ret = 1;
@@ -113,6 +132,18 @@ static int x509_verify_sm2(X509 *x, EVP_PKEY *pkey, int mdnid, int pknid)
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)
@@ -142,6 +173,20 @@ int X509_verify(X509 *a, EVP_PKEY *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 fb03bb2..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 */
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<openssl> B<ca>
[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<file> 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/req.pod b/doc/man1/req.pod
index 539b843..3b9fcc3 100644
--- a/doc/man1/req.pod
+++ b/doc/man1/req.pod
@@ -50,6 +50,8 @@ B<openssl> B<req>
[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<id> string) which would be used
for key generation operations.
+=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 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<oid_file> option:
1.2.3.4 shortName A longer Name
diff --git a/doc/man3/X509_get0_sm2_id.pod b/doc/man3/X509_get0_sm2_id.pod
index 9698c86..d8a85d7 100644
--- a/doc/man3/X509_get0_sm2_id.pod
+++ b/doc/man3/X509_get0_sm2_id.pod
@@ -2,7 +2,9 @@
=head1 NAME
-X509_get0_sm2_id, X509_set0_sm2_id - get or set SM2 ID for certificate operations
+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
@@ -10,6 +12,8 @@ X509_get0_sm2_id, X509_set0_sm2_id - get or set SM2 ID for certificate operation
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
@@ -21,6 +25,10 @@ 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<X509_REQ> objects instead of B<X509>.
+
=head1 NOTES
SM2 signature algorithm requires an ID value when generating and verifying a
@@ -29,7 +37,7 @@ ability to set and retrieve the SM2 ID value.
=head1 RETURN VALUES
-X509_set0_sm2_id() does not return a value.
+X509_set0_sm2_id() and X509_REQ_set0_sm2_id() do not return a value.
=head1 SEE ALSO
diff --git a/include/crypto/x509.h b/include/crypto/x509.h
index 5c314a8..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 {
diff --git a/include/openssl/x509.h b/include/openssl/x509.h
index a02cf50..42e9eee 100644
--- a/include/openssl/x509.h
+++ b/include/openssl/x509.h
@@ -576,6 +576,8 @@ 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);
diff --git a/include/openssl/x509err.h b/include/openssl/x509err.h
index 06d75f0..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
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/recipes/25-test_req.t b/test/recipes/25-test_req.t
index 383120c..8289959 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,25 @@ subtest "generating certificate requests" => sub {
"Verifying signature on request");
};
+subtest "generating SM2 certificate requests" => sub {
+ plan tests => 2;
+
+ SKIP: {
+ skip "SM2 is not supported by this OpenSSL build", 2
+ 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");
+ }
+};
+
my @openssl_args = ("req", "-config", srctop_file("apps", "openssl.cnf"));
run_conversion('req conversions',
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 763ea4f..d69653c 100644
--- a/test/verify_extra_test.c
+++ b/test/verify_extra_test.c
@@ -20,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)
{
@@ -272,6 +273,46 @@ static int test_sm2_id(void)
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)
@@ -279,7 +320,8 @@ 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;
}
@@ -290,6 +332,7 @@ int setup_tests(void)
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 d7abe91..81a6388 100644
--- a/util/libcrypto.num
+++ b/util/libcrypto.num
@@ -4628,3 +4628,5 @@ 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)
此处可能存在不合适展示的内容,页面不予展示。您可通过相关编辑功能自查并修改。
如您确认内容无涉及 不当用语 / 纯广告导流 / 暴力 / 低俗色情 / 侵权 / 盗版 / 虚假 / 无价值内容或违法国家有关法律法规的内容,可点击提交进行申诉,我们将尽快为您处理。