summaryrefslogtreecommitdiffstats
path: root/crypto
diff options
context:
space:
mode:
authorPaul Yang <yang.yang@baishancloud.com>2019-06-05 14:46:48 +0800
committerPaul Yang <yang.yang@baishancloud.com>2019-06-28 18:58:19 +0800
commitbc42bd6298702a1abf70aa6383d36886dd5af4b3 (patch)
treef75b4cdda42ccc9ebeb01cf9d1d4bc5c0c05764e /crypto
parent53a11c6da09988efba93eccfdd10bf7edf1d53b2 (diff)
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)
Diffstat (limited to 'crypto')
-rw-r--r--crypto/asn1/a_sign.c13
-rw-r--r--crypto/ec/ec_pmeth.c3
-rw-r--r--crypto/err/openssl.txt3
-rw-r--r--crypto/include/internal/x509_int.h3
-rw-r--r--crypto/x509/x509_err.c4
-rw-r--r--crypto/x509/x_all.c85
-rw-r--r--crypto/x509/x_req.c38
-rw-r--r--crypto/x509/x_x509.c3
8 files changed, 126 insertions, 26 deletions
diff --git a/crypto/asn1/a_sign.c b/crypto/asn1/a_sign.c
index 97e8efcbe8..e2ef60f773 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 45798b4f39..e581741fca 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 23c0ddae4f..c463acecad 100644
--- a/crypto/err/openssl.txt
+++ b/crypto/err/openssl.txt
@@ -1832,6 +1832,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
@@ -1875,6 +1876,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/include/internal/x509_int.h b/crypto/include/internal/x509_int.h
index 7c40b159cc..f6897e1421 100644
--- a/crypto/include/internal/x509_int.h
+++ b/crypto/include/internal/x509_int.h
@@ -71,6 +71,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/crypto/x509/x509_err.c b/crypto/x509/x509_err.c
index fbd2cf8e01..c87d74daea 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),
@@ -86,6 +87,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 9c9e8ffad0..392f47e8dc 100644
--- a/crypto/x509/x_all.c
+++ b/crypto/x509/x_all.c
@@ -24,86 +24,105 @@
# include "internal/asn1_int.h"
# include "internal/evp_int.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 7fb844827e..5bda794a82 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 78e1a7569e..d91c2d24da 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 */