Support SM2 certificate verification

Reviewed-by: Tim Hudson <tjh@openssl.org>
(Merged from https://github.com/openssl/openssl/pull/8321)
This commit is contained in:
杨洋 2018-10-26 21:34:08 +08:00 committed by Paul Yang
parent 9e11fe0d85
commit 8267becb8b
18 changed files with 206 additions and 14 deletions

View File

@ -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,8 @@ 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;
if ((vpm = X509_VERIFY_PARAM_new()) == NULL)
goto end;
@ -158,6 +167,19 @@ 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_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,12 +205,13 @@ 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;
}
@ -204,7 +227,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,6 +240,17 @@ 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.data = sm2id;
v.length = sm2idlen;
X509_set_sm2_id(x, &v);
#endif
}
csc = X509_STORE_CTX_new();
if (csc == NULL) {
printf("error %s: X.509 store context allocation failed\n",

View File

@ -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);

View File

@ -1834,8 +1834,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

View File

@ -175,7 +175,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
@ -183,6 +183,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 */ ;
/*

View File

@ -10,7 +10,7 @@
*/
/* Serialized OID's */
static const unsigned char so[7767] = {
static const unsigned char so[7775] = {
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 */
@ -1077,9 +1077,10 @@ static const unsigned char so[7767] = {
0x2A,0x86,0x48,0x86,0xF7,0x0D,0x02,0x0C, /* [ 7745] OBJ_hmacWithSHA512_224 */
0x2A,0x86,0x48,0x86,0xF7,0x0D,0x02,0x0D, /* [ 7753] OBJ_hmacWithSHA512_256 */
0x28,0xCC,0x45,0x03,0x04, /* [ 7761] OBJ_gmac */
0x2A,0x81,0x1C,0xCF,0x55,0x01,0x83,0x75, /* [ 7766] OBJ_SM2_with_SM3 */
};
#define NUM_NID 1204
#define NUM_NID 1205
static const ASN1_OBJECT nid_objs[NUM_NID] = {
{"UNDEF", "undefined", NID_undef},
{"rsadsi", "RSA Data Security, Inc.", NID_rsadsi, 6, &so[0]},
@ -2285,9 +2286,10 @@ static const ASN1_OBJECT nid_objs[NUM_NID] = {
{"BLAKE2BMAC", "blake2bmac", NID_blake2bmac},
{"BLAKE2SMAC", "blake2smac", NID_blake2smac},
{"SSHKDF", "sshkdf", NID_sshkdf},
{"SM2-SM3", "SM2-with-SM3", NID_SM2_with_SM3, 8, &so[7766]},
};
#define NUM_SN 1195
#define NUM_SN 1196
static const unsigned int sn_objs[NUM_SN] = {
364, /* "AD_DVCS" */
419, /* "AES-128-CBC" */
@ -2561,6 +2563,7 @@ static const unsigned int sn_objs[NUM_SN] = {
1100, /* "SHAKE128" */
1101, /* "SHAKE256" */
1172, /* "SM2" */
1204, /* "SM2-SM3" */
1143, /* "SM3" */
1134, /* "SM4-CBC" */
1137, /* "SM4-CFB" */
@ -3486,7 +3489,7 @@ static const unsigned int sn_objs[NUM_SN] = {
1093, /* "x509ExtAdmission" */
};
#define NUM_LN 1195
#define NUM_LN 1196
static const unsigned int ln_objs[NUM_LN] = {
363, /* "AD Time Stamping" */
405, /* "ANSI X9.62" */
@ -3642,6 +3645,7 @@ static const unsigned int ln_objs[NUM_LN] = {
1119, /* "RSA-SHA3-512" */
188, /* "S/MIME" */
167, /* "S/MIME Capabilities" */
1204, /* "SM2-with-SM3" */
1006, /* "SNILS" */
387, /* "SNMPv2" */
1025, /* "SSH Client" */
@ -4685,7 +4689,7 @@ static const unsigned int ln_objs[NUM_LN] = {
125, /* "zlib compression" */
};
#define NUM_OBJ 1072
#define NUM_OBJ 1073
static const unsigned int obj_objs[NUM_OBJ] = {
0, /* OBJ_undef 0 */
181, /* OBJ_iso 1 */
@ -5155,6 +5159,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 */
1204, /* 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 */

View File

@ -1201,3 +1201,4 @@ aes_256_siv 1200
blake2bmac 1201
blake2smac 1202
sshkdf 1203
SM2_with_SM3 1204

View File

@ -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],
};

View File

@ -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

View File

@ -394,6 +394,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

View File

@ -220,6 +220,10 @@ static int pkey_sm2_ctrl(EVP_PKEY_CTX *ctx, int type, int p1, void *p2)
*(size_t *)p2 = smctx->id_len;
return 1;
case EVP_PKEY_CTRL_DIGESTINIT:
/* nothing to be inited, this is to suppress the error... */
return 1;
default:
return -2;
}

View File

@ -1,6 +1,6 @@
/*
* Generated by util/mkerr.pl DO NOT EDIT
* Copyright 1995-2018 The OpenSSL Project Authors. All Rights Reserved.
* Copyright 1995-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
@ -104,9 +104,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}
};

View File

@ -19,10 +19,120 @@
#include <openssl/dsa.h>
#include <openssl/x509v3.h>
#ifndef OPENSSL_NO_SM2
# include "internal/asn1_int.h"
# include "internal/evp_int.h"
static int x509_verify_sm2(X509 *x, EVP_PKEY *pkey, int mdnid, int pknid)
{
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);
if (type == NULL) {
X509err(X509_F_X509_VERIFY_SM2,
ASN1_R_UNKNOWN_MESSAGE_DIGEST_ALGORITHM);
goto err;
}
if (pkey == NULL) {
X509err(X509_F_X509_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);
return -1;
}
ctx = EVP_MD_CTX_new();
if (ctx == NULL) {
X509err(X509_F_X509_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);
goto err;
}
if (!EVP_PKEY_set_alias_type(pkey, EVP_PKEY_SM2)) {
X509err(X509_F_X509_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);
ret = 0;
goto err;
}
if (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);
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);
ret = 0;
goto err;
}
inl = ASN1_item_i2d((ASN1_VALUE *)&x->cert_info, &buf_in,
ASN1_ITEM_rptr(X509_CINF));
if (inl <= 0) {
X509err(X509_F_X509_VERIFY_SM2, ERR_R_INTERNAL_ERROR);
goto err;
}
if (buf_in == NULL) {
X509err(X509_F_X509_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);
if (ret <= 0) {
X509err(X509_F_X509_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;
}
#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));
}

View File

@ -244,3 +244,15 @@ int X509_get_signature_nid(const X509 *x)
{
return OBJ_obj2nid(x->sig_alg.algorithm);
}
#ifndef OPENSSL_NO_SM2
void X509_set_sm2_id(X509 *x, ASN1_OCTET_STRING *sm2_id)
{
x->sm2_id = *sm2_id;
}
ASN1_OCTET_STRING *X509_get0_sm2_id(X509 *x)
{
return &x->sm2_id;
}
#endif

View File

@ -1064,3 +1064,4 @@ 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_gmac="\x28\xCC\x45\x03\x04"
OBJ_SM2_with_SM3="\x2A\x81\x1C\xCF\x55\x01\x83\x75"

View File

@ -1200,6 +1200,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 1204
#define OBJ_SM2_with_SM3 OBJ_sm_scheme,501L
#define LN_hmacWithSHA224 "hmacWithSHA224"
#define NID_hmacWithSHA224 798
#define OBJ_hmacWithSHA224 OBJ_rsadsi,2L,8L

View File

@ -566,6 +566,9 @@ void X509_get0_signature(const ASN1_BIT_STRING **psig,
const X509_ALGOR **palg, const X509 *x);
int X509_get_signature_nid(const X509 *x);
void X509_set_sm2_id(X509 *x, ASN1_OCTET_STRING *sm2_id);
ASN1_OCTET_STRING *X509_get0_sm2_id(X509 *x);
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);

View File

@ -82,8 +82,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.

View File

@ -4788,3 +4788,5 @@ OSSL_PARAM_get_utf8_ptr 4735 3_0_0 EXIST::FUNCTION:
OSSL_PARAM_set_utf8_ptr 4736 3_0_0 EXIST::FUNCTION:
OSSL_PARAM_get_octet_ptr 4737 3_0_0 EXIST::FUNCTION:
OSSL_PARAM_set_octet_ptr 4738 3_0_0 EXIST::FUNCTION:
X509_set_sm2_id 4739 3_0_0 EXIST::FUNCTION:
X509_get0_sm2_id 4740 3_0_0 EXIST::FUNCTION: