From 9137b68d161ccb95b1019c4885d0519ebbf4678a Mon Sep 17 00:00:00 2001 From: Huaxin Lu Date: Mon, 7 Nov 2022 11:46:33 +0800 Subject: [PATCH 4/5] shim cryptlib support sm2 signature verify Co-authored-by: Yusong Gao Signed-off-by: Yusong Gao Signed-off-by: Huaxin Lu --- Cryptlib/Hash/CryptSm3.c | 231 +++++++++++++++++++++ Cryptlib/Include/openssl/crypto.h | 10 + Cryptlib/Include/openssl/ec.h | 20 ++ Cryptlib/Include/openssl/ecdsa.h | 7 + Cryptlib/Include/openssl/err.h | 6 + Cryptlib/Include/openssl/evp.h | 25 +++ Cryptlib/Include/openssl/obj_mac.h | 33 +++ Cryptlib/Include/openssl/opensslconf.h | 8 +- Cryptlib/Include/openssl/x509.h | 7 + Cryptlib/Library/BaseCryptLib.h | 111 ++++++++++ Cryptlib/Makefile | 6 + Cryptlib/OpenSSL/Makefile | 38 +++- Cryptlib/OpenSSL/crypto/asn1/a_sign.c | 11 +- Cryptlib/OpenSSL/crypto/asn1/ameth_lib.c | 8 +- Cryptlib/OpenSSL/crypto/asn1/x_req.c | 13 ++ Cryptlib/OpenSSL/crypto/asn1/x_x509.c | 6 + Cryptlib/OpenSSL/crypto/bn/bn_lib.c | 3 - Cryptlib/OpenSSL/crypto/err/err.c | 1 + Cryptlib/OpenSSL/crypto/evp/c_alld.c | 3 + Cryptlib/OpenSSL/crypto/evp/digest.c | 62 +++++- Cryptlib/OpenSSL/crypto/evp/evp_lib.c | 5 + Cryptlib/OpenSSL/crypto/evp/evp_locl.h | 10 + Cryptlib/OpenSSL/crypto/evp/m_sigver.c | 17 ++ Cryptlib/OpenSSL/crypto/evp/p_lib.c | 44 ++++ Cryptlib/OpenSSL/crypto/evp/pmeth_lib.c | 16 +- Cryptlib/OpenSSL/crypto/mem.c | 18 ++ Cryptlib/OpenSSL/crypto/o_str.c | 87 ++++++++ Cryptlib/OpenSSL/crypto/objects/obj_dat.h | 46 +++- Cryptlib/OpenSSL/crypto/objects/obj_xref.h | 2 + Cryptlib/OpenSSL/crypto/pkcs7/pk7_doit.c | 34 ++- Cryptlib/OpenSSL/crypto/x509/x_all.c | 142 +++++++++++++ Cryptlib/Pk/CryptPkcs7Verify.c | 5 + 32 files changed, 997 insertions(+), 38 deletions(-) create mode 100644 Cryptlib/Hash/CryptSm3.c diff --git a/Cryptlib/Hash/CryptSm3.c b/Cryptlib/Hash/CryptSm3.c new file mode 100644 index 0000000..c522365 --- /dev/null +++ b/Cryptlib/Hash/CryptSm3.c @@ -0,0 +1,231 @@ +/** @file + SM3 Digest Wrapper Implementation over OpenSSL. + +Copyright (c) 2009 - 2016, Intel Corporation. All rights reserved.
+This program and the accompanying materials +are licensed and made available under the terms and conditions of the BSD License +which accompanies this distribution. The full text of the license may be found at +http://opensource.org/licenses/bsd-license.php + +THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, +WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + +**/ + +#include "InternalCryptLib.h" +#include + +/** + Retrieves the size, in bytes, of the context buffer required for SM3 hash operations. + + @return The size, in bytes, of the context buffer required for SM3 hash operations. + +**/ +UINTN +EFIAPI +Sm3GetContextSize ( + VOID + ) +{ + // + // Retrieves OpenSSL SM3 Context Size + // + return (UINTN) (sizeof (SM3_CTX)); +} + +/** + Initializes user-supplied memory pointed by Sm3Context as SM3 hash context for + subsequent use. + + If Sm3Context is NULL, then return FALSE. + + @param[out] Sm3Context Pointer to SM3 context being initialized. + + @retval TRUE SM3 context initialization succeeded. + @retval FALSE SM3 context initialization failed. + +**/ +BOOLEAN +EFIAPI +Sm3Init ( + OUT VOID *Sm3Context + ) +{ + // + // Check input parameters. + // + if (Sm3Context == NULL) { + return FALSE; + } + + // + // OpenSSL SM3 Context Initialization + // + return (BOOLEAN) (sm3_init ((SM3_CTX *) Sm3Context)); +} + +/** + Makes a copy of an existing SM3 context. + + If Sm3Context is NULL, then return FALSE. + If NewSm3Context is NULL, then return FALSE. + + @param[in] Sm3Context Pointer to SM3 context being copied. + @param[out] NewSm3Context Pointer to new SM3 context. + + @retval TRUE SM3 context copy succeeded. + @retval FALSE SM3 context copy failed. + +**/ +BOOLEAN +EFIAPI +Sm3Duplicate ( + IN CONST VOID *Sm3Context, + OUT VOID *NewSm3Context + ) +{ + // + // Check input parameters. + // + if (Sm3Context == NULL || NewSm3Context == NULL) { + return FALSE; + } + + CopyMem (NewSm3Context, (void *)Sm3Context, sizeof (SM3_CTX)); + + return TRUE; +} + +/** + Digests the input data and updates SM3 context. + + This function performs SM3 digest on a data buffer of the specified size. + It can be called multiple times to compute the digest of long or discontinuous data streams. + SM3 context should be already correctly initialized by Sm3Init(), and should not be finalized + by Sm3Final(). Behavior with invalid context is undefined. + + If Sm3Context is NULL, then return FALSE. + + @param[in, out] Sm3Context Pointer to the SM3 context. + @param[in] Data Pointer to the buffer containing the data to be hashed. + @param[in] DataSize Size of Data buffer in bytes. + + @retval TRUE SM3 data digest succeeded. + @retval FALSE SM3 data digest failed. + +**/ +BOOLEAN +EFIAPI +Sm3Update ( + IN OUT VOID *Sm3Context, + IN CONST VOID *Data, + IN UINTN DataSize + ) +{ + // + // Check input parameters. + // + if (Sm3Context == NULL) { + return FALSE; + } + + // + // Check invalid parameters, in case that only DataLength was checked in OpenSSL + // + if (Data == NULL && DataSize != 0) { + return FALSE; + } + + // + // OpenSSL SM3 Hash Update + // + return (BOOLEAN) (sm3_update ((SM3_CTX *) Sm3Context, Data, DataSize)); +} + +/** + Completes computation of the SM3 digest value. + + This function completes SM3 hash computation and retrieves the digest value into + the specified memory. After this function has been called, the SM3 context cannot + be used again. + SM3 context should be already correctly initialized by Sm3Init(), and should not be + finalized by Sm3Final(). Behavior with invalid SM3 context is undefined. + + If Sm3Context is NULL, then return FALSE. + If HashValue is NULL, then return FALSE. + + @param[in, out] Sm3Context Pointer to the SM3 context. + @param[out] HashValue Pointer to a buffer that receives the SM3 digest + value (32 bytes). + + @retval TRUE SM3 digest computation succeeded. + @retval FALSE SM3 digest computation failed. + +**/ +BOOLEAN +EFIAPI +Sm3Final ( + IN OUT VOID *Sm3Context, + OUT UINT8 *HashValue + ) +{ + // + // Check input parameters. + // + if (Sm3Context == NULL || HashValue == NULL) { + return FALSE; + } + + // + // OpenSSL SM3 Hash Finalization + // + return (BOOLEAN) (sm3_final (HashValue, (SM3_CTX *) Sm3Context)); +} + +/** + Computes the SM3 message digest of a input data buffer. + + This function performs the SM3 message digest of a given data buffer, and places + the digest value into the specified memory. + + If this interface is not supported, then return FALSE. + + @param[in] Data Pointer to the buffer containing the data to be hashed. + @param[in] DataSize Size of Data buffer in bytes. + @param[out] HashValue Pointer to a buffer that receives the SM3 digest + value (32 bytes). + + @retval TRUE SM3 digest computation succeeded. + @retval FALSE SM3 digest computation failed. + @retval FALSE This interface is not supported. + +**/ +BOOLEAN +EFIAPI +Sm3HashAll ( + IN CONST VOID *Data, + IN UINTN DataSize, + OUT UINT8 *HashValue + ) +{ + // + // Check input parameters. + // + if (HashValue == NULL) { + return FALSE; + } + if (Data == NULL && DataSize != 0) { + return FALSE; + } + + // + // OpenSSL SM3 Hash Computation. + // + + SM3_CTX c; + sm3_init(&c); + sm3_update(&c, Data, DataSize); + sm3_final(HashValue, &c); + + return TRUE; +} diff --git a/Cryptlib/Include/openssl/crypto.h b/Cryptlib/Include/openssl/crypto.h index e201a12..b0fbe1c 100644 --- a/Cryptlib/Include/openssl/crypto.h +++ b/Cryptlib/Include/openssl/crypto.h @@ -380,6 +380,7 @@ int CRYPTO_is_mem_check_on(void); # define is_MemCheck_on() CRYPTO_is_mem_check_on() # define OPENSSL_malloc(num) CRYPTO_malloc((int)num,OPENSSL_FILE,OPENSSL_LINE) +# define OPENSSL_zalloc(num) CRYPTO_zalloc((int)num,OPENSSL_FILE,OPENSSL_LINE) # define OPENSSL_strdup(str) CRYPTO_strdup((str),OPENSSL_FILE,OPENSSL_LINE) # define OPENSSL_realloc(addr,num) \ CRYPTO_realloc((char *)addr,(int)num,OPENSSL_FILE,OPENSSL_LINE) @@ -389,6 +390,8 @@ int CRYPTO_is_mem_check_on(void); CRYPTO_remalloc((char **)addr,(int)num,OPENSSL_FILE,OPENSSL_LINE) # define OPENSSL_freeFunc CRYPTO_free # define OPENSSL_free(addr) CRYPTO_free(addr) +# define OPENSSL_clear_free(addr, num) \ + CRYPTO_clear_free(addr,num,OPENSSL_FILE,OPENSSL_LINE) # define OPENSSL_malloc_locked(num) \ CRYPTO_malloc_locked((int)num,OPENSSL_FILE,OPENSSL_LINE) @@ -399,6 +402,8 @@ unsigned long SSLeay(void); int OPENSSL_issetugid(void); +unsigned char *OPENSSL_hexstr2buf(const char *str, long *len); + /* An opaque type representing an implementation of "ex_data" support */ typedef struct st_CRYPTO_EX_DATA_IMPL CRYPTO_EX_DATA_IMPL; /* Return an opaque pointer to the current "ex_data" implementation */ @@ -533,12 +538,14 @@ void CRYPTO_get_mem_debug_functions(void (**m) void *CRYPTO_malloc_locked(int num, const char *file, int line); void CRYPTO_free_locked(void *ptr); void *CRYPTO_malloc(int num, const char *file, int line); +void *CRYPTO_zalloc(int num, const char *file, int line); char *CRYPTO_strdup(const char *str, const char *file, int line); void CRYPTO_free(void *ptr); void *CRYPTO_realloc(void *addr, int num, const char *file, int line); void *CRYPTO_realloc_clean(void *addr, int old_num, int num, const char *file, int line); void *CRYPTO_remalloc(void *addr, int num, const char *file, int line); +void CRYPTO_clear_free(void *ptr, int num, const char *file, int line); void OPENSSL_cleanse(void *ptr, size_t len); @@ -651,10 +658,13 @@ void ERR_load_CRYPTO_strings(void); # define CRYPTO_F_INT_DUP_EX_DATA 106 # define CRYPTO_F_INT_FREE_EX_DATA 107 # define CRYPTO_F_INT_NEW_EX_DATA 108 +# define CRYPTO_F_OPENSSL_HEXSTR2BUF 118 /* Reason codes. */ # define CRYPTO_R_FIPS_MODE_NOT_SUPPORTED 101 # define CRYPTO_R_NO_DYNLOCK_CREATE_CALLBACK 100 +# define CRYPTO_R_ILLEGAL_HEX_DIGIT 102 +# define CRYPTO_R_ODD_NUMBER_OF_DIGITS 103 #ifdef __cplusplus } diff --git a/Cryptlib/Include/openssl/ec.h b/Cryptlib/Include/openssl/ec.h index 81e6faf..e315025 100644 --- a/Cryptlib/Include/openssl/ec.h +++ b/Cryptlib/Include/openssl/ec.h @@ -254,6 +254,12 @@ BN_MONT_CTX *EC_GROUP_get_mont_data(const EC_GROUP *group); */ int EC_GROUP_get_order(const EC_GROUP *group, BIGNUM *order, BN_CTX *ctx); +/** Gets the order of an EC_GROUP + * \param group EC_GROUP object + * \return the group order + */ +const BIGNUM *EC_GROUP_get0_order(const EC_GROUP *group); + /** Gets the cofactor of a EC_GROUP * \param group EC_GROUP object * \param cofactor BIGNUM to which the cofactor is copied @@ -1053,6 +1059,17 @@ int EC_KEY_print_fp(FILE *fp, const EC_KEY *key, int off); EVP_PKEY_CTX_ctrl(ctx, EVP_PKEY_EC, \ EVP_PKEY_OP_DERIVE, \ EVP_PKEY_CTRL_GET_EC_KDF_UKM, 0, (void *)p) +# 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)) + +# define EVP_PKEY_CTX_get1_id_len(ctx, id_len) \ + EVP_PKEY_CTX_ctrl(ctx, -1, -1, \ + EVP_PKEY_CTRL_GET1_ID_LEN, 0, (void*)(id_len)) # define EVP_PKEY_CTRL_EC_PARAMGEN_CURVE_NID (EVP_PKEY_ALG_CTRL + 1) # define EVP_PKEY_CTRL_EC_PARAM_ENC (EVP_PKEY_ALG_CTRL + 2) @@ -1064,6 +1081,9 @@ int EC_KEY_print_fp(FILE *fp, const EC_KEY *key, int off); # define EVP_PKEY_CTRL_GET_EC_KDF_OUTLEN (EVP_PKEY_ALG_CTRL + 8) # define EVP_PKEY_CTRL_EC_KDF_UKM (EVP_PKEY_ALG_CTRL + 9) # define EVP_PKEY_CTRL_GET_EC_KDF_UKM (EVP_PKEY_ALG_CTRL + 10) +# define EVP_PKEY_CTRL_SET1_ID (EVP_PKEY_ALG_CTRL + 11) +# define EVP_PKEY_CTRL_GET1_ID (EVP_PKEY_ALG_CTRL + 12) +# define EVP_PKEY_CTRL_GET1_ID_LEN (EVP_PKEY_ALG_CTRL + 13) /* KDF types */ # define EVP_PKEY_ECDH_KDF_NONE 1 # define EVP_PKEY_ECDH_KDF_X9_62 2 diff --git a/Cryptlib/Include/openssl/ecdsa.h b/Cryptlib/Include/openssl/ecdsa.h index a6f0930..e51d924 100644 --- a/Cryptlib/Include/openssl/ecdsa.h +++ b/Cryptlib/Include/openssl/ecdsa.h @@ -90,6 +90,13 @@ ECDSA_SIG *ECDSA_SIG_new(void); */ void ECDSA_SIG_free(ECDSA_SIG *sig); +/** Accessor for r and s fields of ECDSA_SIG + * \param sig pointer to ECDSA_SIG structure + * \param pr pointer to BIGNUM pointer for r (may be NULL) + * \param ps pointer to BIGNUM pointer for s (may be NULL) + */ +void ECDSA_SIG_get0(const ECDSA_SIG *sig, const BIGNUM **pr, const BIGNUM **ps); + /** DER encode content of ECDSA_SIG object (note: this function modifies *pp * (*pp += length of the DER encoded signature)). * \param sig pointer to the ECDSA_SIG object diff --git a/Cryptlib/Include/openssl/err.h b/Cryptlib/Include/openssl/err.h index 5a01980..c8286e1 100644 --- a/Cryptlib/Include/openssl/err.h +++ b/Cryptlib/Include/openssl/err.h @@ -197,6 +197,8 @@ typedef struct err_state_st { # define ERR_LIB_TS 47 # define ERR_LIB_HMAC 48 # define ERR_LIB_JPAKE 49 +# define ERR_LIB_SM2 53 + # define ERR_LIB_USER 128 @@ -233,6 +235,7 @@ typedef struct err_state_st { # define TSerr(f,r) ERR_PUT_error(ERR_LIB_TS,(f),(r),OPENSSL_FILE,OPENSSL_LINE) # define HMACerr(f,r) ERR_PUT_error(ERR_LIB_HMAC,(f),(r),OPENSSL_FILE,OPENSSL_LINE) # define JPAKEerr(f,r) ERR_PUT_error(ERR_LIB_JPAKE,(f),(r),OPENSSL_FILE,OPENSSL_LINE) +# define SM2err(f,r) ERR_PUT_error(ERR_LIB_SM2,(f),(r),OPENSSL_FILE,OPENSSL_LINE) /* * Borland C seems too stupid to be able to shift and do longs in the @@ -304,6 +307,9 @@ typedef struct err_state_st { # define ERR_R_PASSED_NULL_PARAMETER (3|ERR_R_FATAL) # define ERR_R_INTERNAL_ERROR (4|ERR_R_FATAL) # define ERR_R_DISABLED (5|ERR_R_FATAL) +# define ERR_R_INIT_FAIL (6|ERR_R_FATAL) +# define ERR_R_PASSED_INVALID_ARGUMENT (7) +# define ERR_R_OPERATION_FAIL (8|ERR_R_FATAL) /* * 99 is the maximum possible ERR_R_... code, higher values are reserved for diff --git a/Cryptlib/Include/openssl/evp.h b/Cryptlib/Include/openssl/evp.h index 376f260..4e1d9bb 100644 --- a/Cryptlib/Include/openssl/evp.h +++ b/Cryptlib/Include/openssl/evp.h @@ -115,6 +115,7 @@ # define EVP_PKEY_DH NID_dhKeyAgreement # define EVP_PKEY_DHX NID_dhpublicnumber # define EVP_PKEY_EC NID_X9_62_id_ecPublicKey +# define EVP_PKEY_SM2 NID_sm2 # define EVP_PKEY_HMAC NID_hmac # define EVP_PKEY_CMAC NID_cmac @@ -122,6 +123,12 @@ extern "C" { #endif +/* + * Don't free up md_ctx->pctx in EVP_MD_CTX_reset, use the reserved flag + * values in evp.h + */ +#define EVP_MD_CTX_FLAG_KEEP_PKEY_CTX 0x0400 + /* * Type needs to be a bit field Sub-type needs to be for variations on the * method, as in, can it do arbitrary encryption.... @@ -526,6 +533,8 @@ const EVP_MD *EVP_MD_CTX_md(const EVP_MD_CTX *ctx); # define EVP_MD_CTX_block_size(e) EVP_MD_block_size(EVP_MD_CTX_md(e)) # define EVP_MD_CTX_type(e) EVP_MD_type(EVP_MD_CTX_md(e)) +void *EVP_MD_CTX_md_data(const EVP_MD_CTX *ctx); + int EVP_CIPHER_nid(const EVP_CIPHER *cipher); # define EVP_CIPHER_name(e) OBJ_nid2sn(EVP_CIPHER_nid(e)) int EVP_CIPHER_block_size(const EVP_CIPHER *cipher); @@ -583,6 +592,9 @@ int EVP_Cipher(EVP_CIPHER_CTX *c, # define EVP_delete_digest_alias(alias) \ OBJ_NAME_remove(alias,OBJ_NAME_TYPE_MD_METH|OBJ_NAME_ALIAS); +EVP_MD_CTX *EVP_MD_CTX_new(void); +int EVP_MD_CTX_reset(EVP_MD_CTX *ctx); +void EVP_MD_CTX_free(EVP_MD_CTX *ctx); void EVP_MD_CTX_init(EVP_MD_CTX *ctx); int EVP_MD_CTX_cleanup(EVP_MD_CTX *ctx); EVP_MD_CTX *EVP_MD_CTX_create(void); @@ -666,6 +678,10 @@ int EVP_DigestVerifyInit(EVP_MD_CTX *ctx, EVP_PKEY_CTX **pctx, int EVP_DigestVerifyFinal(EVP_MD_CTX *ctx, const unsigned char *sig, size_t siglen); +int EVP_DigestVerify(EVP_MD_CTX *ctx, const unsigned char *sigret, + size_t siglen, const unsigned char *tbs, + size_t tbslen); + int EVP_OpenInit(EVP_CIPHER_CTX *ctx, const EVP_CIPHER *type, const unsigned char *ek, int ekl, const unsigned char *iv, EVP_PKEY *priv); @@ -741,6 +757,9 @@ const EVP_MD *EVP_ripemd160(void); # ifndef OPENSSL_NO_WHIRLPOOL const EVP_MD *EVP_whirlpool(void); # endif +# ifndef OPENSSL_NO_SM3 +const EVP_MD *EVP_sm3(void); +# endif const EVP_CIPHER *EVP_enc_null(void); /* does nothing :-) */ # ifndef OPENSSL_NO_DES const EVP_CIPHER *EVP_des_ecb(void); @@ -954,10 +973,15 @@ int EVP_PKEY_base_id(const EVP_PKEY *pkey); int EVP_PKEY_bits(EVP_PKEY *pkey); int EVP_PKEY_size(EVP_PKEY *pkey); int EVP_PKEY_set_type(EVP_PKEY *pkey, int type); +int EVP_PKEY_set_alias_type(EVP_PKEY *pkey, int type); int EVP_PKEY_set_type_str(EVP_PKEY *pkey, const char *str, int len); int EVP_PKEY_assign(EVP_PKEY *pkey, int type, void *key); void *EVP_PKEY_get0(EVP_PKEY *pkey); +# 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); @@ -976,6 +1000,7 @@ struct dh_st *EVP_PKEY_get1_DH(EVP_PKEY *pkey); # ifndef OPENSSL_NO_EC struct ec_key_st; int EVP_PKEY_set1_EC_KEY(EVP_PKEY *pkey, struct ec_key_st *key); +struct ec_key_st *EVP_PKEY_get0_EC_KEY(EVP_PKEY *pkey); struct ec_key_st *EVP_PKEY_get1_EC_KEY(EVP_PKEY *pkey); # endif diff --git a/Cryptlib/Include/openssl/obj_mac.h b/Cryptlib/Include/openssl/obj_mac.h index 779c309..91b75e0 100644 --- a/Cryptlib/Include/openssl/obj_mac.h +++ b/Cryptlib/Include/openssl/obj_mac.h @@ -4192,3 +4192,36 @@ #define LN_jurisdictionCountryName "jurisdictionCountryName" #define NID_jurisdictionCountryName 957 #define OBJ_jurisdictionCountryName 1L,3L,6L,1L,4L,1L,311L,60L,2L,1L,3L + +#define SN_ISO_CN "ISO-CN" +#define LN_ISO_CN "ISO CN Member Body" +#define NID_ISO_CN 958 +#define OBJ_ISO_CN OBJ_member_body,156L + +#define SN_oscca "oscca" +#define NID_oscca 959 +#define OBJ_oscca OBJ_ISO_CN,10197L + +#define SN_sm_scheme "sm-scheme" +#define NID_sm_scheme 960 +#define OBJ_sm_scheme OBJ_oscca,1L + +#define SN_sm2 "SM2" +#define LN_sm2 "sm2" +#define NID_sm2 961 +#define OBJ_sm2 OBJ_sm_scheme,301L + +#define SN_sm3 "SM3" +#define LN_sm3 "sm3" +#define NID_sm3 962 +#define OBJ_sm3 OBJ_sm_scheme,401L + +#define SN_sm3WithRSAEncryption "RSA-SM3" +#define LN_sm3WithRSAEncryption "sm3WithRSAEncryption" +#define NID_sm3WithRSAEncryption 963 +#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 964 +#define OBJ_SM2_with_SM3 OBJ_sm_scheme,501L diff --git a/Cryptlib/Include/openssl/opensslconf.h b/Cryptlib/Include/openssl/opensslconf.h index 4a36e9f..6f19ce6 100644 --- a/Cryptlib/Include/openssl/opensslconf.h +++ b/Cryptlib/Include/openssl/opensslconf.h @@ -10,7 +10,6 @@ extern "C" { #endif #ifndef OPENSSL_DOING_MAKEDEPEND - #ifndef OPENSSL_NO_BF # define OPENSSL_NO_BF #endif @@ -41,8 +40,8 @@ extern "C" { #ifndef OPENSSL_NO_DYNAMIC_ENGINE # define OPENSSL_NO_DYNAMIC_ENGINE #endif -#ifndef OPENSSL_NO_EC -# define OPENSSL_NO_EC +#ifndef OPENSSL_NO_EC2M +# define OPENSSL_NO_EC2M #endif #ifndef OPENSSL_NO_EC_NISTP_64_GCC_128 # define OPENSSL_NO_EC_NISTP_64_GCC_128 @@ -50,9 +49,6 @@ extern "C" { #ifndef OPENSSL_NO_ECDH # define OPENSSL_NO_ECDH #endif -#ifndef OPENSSL_NO_ECDSA -# define OPENSSL_NO_ECDSA -#endif #ifndef OPENSSL_NO_ENGINE # define OPENSSL_NO_ENGINE #endif diff --git a/Cryptlib/Include/openssl/x509.h b/Cryptlib/Include/openssl/x509.h index 6fa28eb..eda456b 100644 --- a/Cryptlib/Include/openssl/x509.h +++ b/Cryptlib/Include/openssl/x509.h @@ -237,6 +237,9 @@ typedef struct X509_req_st { X509_ALGOR *sig_alg; ASN1_BIT_STRING *signature; int references; +# ifndef OPENSSL_NO_SM2 + ASN1_OCTET_STRING *sm2_id; +# endif } X509_REQ; typedef struct x509_cinf_st { @@ -296,6 +299,10 @@ struct x509_st { unsigned char sha1_hash[SHA_DIGEST_LENGTH]; # endif X509_CERT_AUX *aux; + volatile int ex_cached; +# ifndef OPENSSL_NO_SM2 + ASN1_OCTET_STRING *sm2_id; +# endif } /* X509 */ ; DECLARE_STACK_OF(X509) diff --git a/Cryptlib/Library/BaseCryptLib.h b/Cryptlib/Library/BaseCryptLib.h index 2df8bd2..a7fea2c 100644 --- a/Cryptlib/Library/BaseCryptLib.h +++ b/Cryptlib/Library/BaseCryptLib.h @@ -52,6 +52,11 @@ WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. /// #define SHA512_DIGEST_SIZE 64 +/// +/// SM3 digest size in bytes +/// +#define SM3_DIGEST_SIZE 32 + /// /// TDES block size in bytes /// @@ -893,6 +898,112 @@ Sha512HashAll ( OUT UINT8 *HashValue ); +/** + Retrieves the size, in bytes, of the context buffer required for SM3 hash operations. + @return The size, in bytes, of the context buffer required for SM3 hash operations. +**/ +UINTN +EFIAPI +Sm3GetContextSize ( + VOID + ); + +/** + Initializes user-supplied memory pointed by Sm3Context as SM3 hash context for + subsequent use. + If Sm3Context is NULL, then return FALSE. + @param[out] Sm3Context Pointer to SM3 context being initialized. + @retval TRUE SM3 context initialization succeeded. + @retval FALSE SM3 context initialization failed. +**/ +BOOLEAN +EFIAPI +Sm3Init ( + OUT VOID *Sm3Context + ); + +/** + Makes a copy of an existing SM3 context. + If Sm3Context is NULL, then return FALSE. + If NewSm3Context is NULL, then return FALSE. + If this interface is not supported, then return FALSE. + @param[in] Sm3Context Pointer to SM3 context being copied. + @param[out] NewSm3Context Pointer to new SM3 context. + @retval TRUE SM3 context copy succeeded. + @retval FALSE SM3 context copy failed. + @retval FALSE This interface is not supported. +**/ +BOOLEAN +EFIAPI +Sm3Duplicate ( + IN CONST VOID *Sm3Context, + OUT VOID *NewSm3Context + ); + +/** + Digests the input data and updates SM3 context. + This function performs SM3 digest on a data buffer of the specified size. + It can be called multiple times to compute the digest of long or discontinuous data streams. + SM3 context should be already correctly initialized by Sm3Init(), and should not be finalied + by Sm3Final(). Behavior with invalid context is undefined. + If Sm3Context is NULL, then return FALSE. + @param[in, out] Sm3Context Pointer to the SM3 context. + @param[in] Data Pointer to the buffer containing the data to be hashed. + @param[in] DataSize Size of Data buffer in bytes. + @retval TRUE SM3 data digest succeeded. + @retval FALSE SM3 data digest failed. +**/ +BOOLEAN +EFIAPI +Sm3Update ( + IN OUT VOID *Sm3Context, + IN CONST VOID *Data, + IN UINTN DataSize + ); + +/** + Completes computation of the SM3 digest value. + This function completes SM3 hash computation and retrieves the digest value into + the specified memory. After this function has been called, the SM3 context cannot + be used again. + SM3 context should be already correctly initialized by Sm3Init(), and should not be + finalized by Sm3Final(). Behavior with invalid SM3 context is undefined. + If Sm3Context is NULL, then return FALSE. + If HashValue is NULL, then return FALSE. + @param[in, out] Sm3Context Pointer to the SM3 context. + @param[out] HashValue Pointer to a buffer that receives the SM3 digest + value (32 bytes). + @retval TRUE SM3 digest computation succeeded. + @retval FALSE SM3 digest computation failed. +**/ +BOOLEAN +EFIAPI +Sm3Final ( + IN OUT VOID *Sm3Context, + OUT UINT8 *HashValue + ); + +/** + Computes the SM3 message digest of a input data buffer. + This function performs the SM3 message digest of a given data buffer, and places + the digest value into the specified memory. + If this interface is not supported, then return FALSE. + @param[in] Data Pointer to the buffer containing the data to be hashed. + @param[in] DataSize Size of Data buffer in bytes. + @param[out] HashValue Pointer to a buffer that receives the SM3 digest + value (32 bytes). + @retval TRUE SM3 digest computation succeeded. + @retval FALSE SM3 digest computation failed. + @retval FALSE This interface is not supported. +**/ +BOOLEAN +EFIAPI +Sm3HashAll ( + IN CONST VOID *Data, + IN UINTN DataSize, + OUT UINT8 *HashValue + ); + //===================================================================================== // MAC (Message Authentication Code) Primitive //===================================================================================== diff --git a/Cryptlib/Makefile b/Cryptlib/Makefile index 89fd5cd..7885a1a 100644 --- a/Cryptlib/Makefile +++ b/Cryptlib/Makefile @@ -66,6 +66,12 @@ OBJS = Hash/CryptMd4Null.o \ SysCall/BaseMemAllocation.o \ SysCall/BaseStrings.o +ifdef SHIM_ENABLE_SM +OBJS += Hash/CryptSm3.o +else +DEFINES += -DOPENSSL_NO_SM3 +endif + all: $(TARGET) libcryptlib.a: $(OBJS) diff --git a/Cryptlib/OpenSSL/Makefile b/Cryptlib/OpenSSL/Makefile index 795f471..32fb235 100644 --- a/Cryptlib/OpenSSL/Makefile +++ b/Cryptlib/OpenSSL/Makefile @@ -459,7 +459,43 @@ OBJS = crypto/cryptlib.o \ crypto/ocsp/ocsp_err.o \ crypto/cmac/cmac.o \ crypto/cmac/cm_ameth.o \ - crypto/cmac/cm_pmeth.o \ + crypto/cmac/cm_pmeth.o + +ifdef SHIM_ENABLE_SM +OBJS +=crypto/ec/ec_ameth.o \ + crypto/ec/ec_cvt.o \ + crypto/ec/eck_prn.o \ + crypto/ec/ec_oct.o \ + crypto/ec/ecp_smpl.o \ + crypto/ec/ec_asn1.o \ + crypto/ec/ec_err.o \ + crypto/ec/ec_pmeth.o \ + crypto/ec/ec_check.o \ + crypto/ec/ec_lib.o \ + crypto/ec/ecp_mont.o \ + crypto/ec/ecp_oct.o \ + crypto/ec/ec_curve.o \ + crypto/ec/ec_key.o \ + crypto/ec/ec_mult.o \ + crypto/ec/ecp_nist.o \ + crypto/ec/ec_print.o \ + crypto/ecdsa/ecs_asn1.o \ + crypto/ecdsa/ecs_err.o \ + crypto/ecdsa/ecs_lib.o \ + crypto/ecdsa/ecs_ossl.o \ + crypto/ecdsa/ecs_sign.o \ + crypto/ecdsa/ecs_vrf.o \ + crypto/sm3/sm3.o \ + crypto/sm3/m_sm3.o \ + crypto/sm2/sm2_err.o \ + crypto/sm2/sm2_pmeth.o \ + crypto/sm2/sm2_sign.o +else +DEFINES +=-DOPENSSL_NO_EC \ + -DOPENSSL_NO_ECDSA \ + -DOPENSSL_NO_SM2 \ + -DOPENSSL_NO_SM3 +endif all: $(TARGET) diff --git a/Cryptlib/OpenSSL/crypto/asn1/a_sign.c b/Cryptlib/OpenSSL/crypto/asn1/a_sign.c index 51c6a0c..68a2ae6 100644 --- a/Cryptlib/OpenSSL/crypto/asn1/a_sign.c +++ b/Cryptlib/OpenSSL/crypto/asn1/a_sign.c @@ -238,7 +238,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; - int rv; + int rv, pkey_id; type = EVP_MD_CTX_md(ctx); pkey = EVP_PKEY_CTX_get0_pkey(ctx->pctx); @@ -268,10 +268,17 @@ int ASN1_item_sign_ctx(const ASN1_ITEM *it, if (rv == 2) { if (type->flags & EVP_MD_FLAG_PKEY_METHOD_SIGNATURE) { + + pkey_id = +#ifndef OPENSSL_NO_SM2 + EVP_PKEY_id(pkey) == NID_sm2 ? NID_sm2 : +#endif + pkey->ameth->pkey_id; + if (!pkey->ameth || !OBJ_find_sigid_by_algs(&signid, EVP_MD_nid(type), - pkey->ameth->pkey_id)) { + pkey_id)) { ASN1err(ASN1_F_ASN1_ITEM_SIGN_CTX, ASN1_R_DIGEST_AND_KEY_TYPE_NOT_SUPPORTED); return 0; diff --git a/Cryptlib/OpenSSL/crypto/asn1/ameth_lib.c b/Cryptlib/OpenSSL/crypto/asn1/ameth_lib.c index 43ddebb..db3d27d 100644 --- a/Cryptlib/OpenSSL/crypto/asn1/ameth_lib.c +++ b/Cryptlib/OpenSSL/crypto/asn1/ameth_lib.c @@ -64,6 +64,7 @@ # include #endif #include "asn1_locl.h" +#include extern const EVP_PKEY_ASN1_METHOD rsa_asn1_meths[]; extern const EVP_PKEY_ASN1_METHOD dsa_asn1_meths[]; @@ -72,6 +73,8 @@ extern const EVP_PKEY_ASN1_METHOD dhx_asn1_meth; extern const EVP_PKEY_ASN1_METHOD eckey_asn1_meth; extern const EVP_PKEY_ASN1_METHOD hmac_asn1_meth; extern const EVP_PKEY_ASN1_METHOD cmac_asn1_meth; +extern const EVP_PKEY_ASN1_METHOD sm2_asn1_meth; + /* Keep this sorted in type order !! */ static const EVP_PKEY_ASN1_METHOD *standard_methods[] = { @@ -97,7 +100,10 @@ static const EVP_PKEY_ASN1_METHOD *standard_methods[] = { &cmac_asn1_meth, #endif #ifndef OPENSSL_NO_DH - &dhx_asn1_meth + &dhx_asn1_meth, +#endif +#ifndef OPENSSL_NO_SM2 + &sm2_asn1_meth, #endif }; diff --git a/Cryptlib/OpenSSL/crypto/asn1/x_req.c b/Cryptlib/OpenSSL/crypto/asn1/x_req.c index ae293aa..575564e 100644 --- a/Cryptlib/OpenSSL/crypto/asn1/x_req.c +++ b/Cryptlib/OpenSSL/crypto/asn1/x_req.c @@ -114,3 +114,16 @@ ASN1_SEQUENCE_ref(X509_REQ, 0, CRYPTO_LOCK_X509_REQ) = { 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/Cryptlib/OpenSSL/crypto/asn1/x_x509.c b/Cryptlib/OpenSSL/crypto/asn1/x_x509.c index aada4a8..8969918 100644 --- a/Cryptlib/OpenSSL/crypto/asn1/x_x509.c +++ b/Cryptlib/OpenSSL/crypto/asn1/x_x509.c @@ -98,6 +98,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; @@ -123,6 +126,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 if (ret->name != NULL) OPENSSL_free(ret->name); diff --git a/Cryptlib/OpenSSL/crypto/bn/bn_lib.c b/Cryptlib/OpenSSL/crypto/bn/bn_lib.c index 2671f35..10b78f5 100644 --- a/Cryptlib/OpenSSL/crypto/bn/bn_lib.c +++ b/Cryptlib/OpenSSL/crypto/bn/bn_lib.c @@ -496,9 +496,6 @@ BIGNUM *BN_copy(BIGNUM *a, const BIGNUM *b) if (bn_wexpand(a, b->top) == NULL) return (NULL); - if (!a || !b || !a->d || !b->d) - return (NULL); - #if 1 A = a->d; B = b->d; diff --git a/Cryptlib/OpenSSL/crypto/err/err.c b/Cryptlib/OpenSSL/crypto/err/err.c index e225145..aac5956 100644 --- a/Cryptlib/OpenSSL/crypto/err/err.c +++ b/Cryptlib/OpenSSL/crypto/err/err.c @@ -155,6 +155,7 @@ static ERR_STRING_DATA ERR_str_libraries[] = { {ERR_PACK(ERR_LIB_FIPS, 0, 0), "FIPS routines"}, {ERR_PACK(ERR_LIB_CMS, 0, 0), "CMS routines"}, {ERR_PACK(ERR_LIB_HMAC, 0, 0), "HMAC routines"}, + {ERR_PACK(ERR_LIB_SM2, 0, 0), "SM2 routines"}, {0, NULL}, }; diff --git a/Cryptlib/OpenSSL/crypto/evp/c_alld.c b/Cryptlib/OpenSSL/crypto/evp/c_alld.c index fdbe3ee..6cad383 100644 --- a/Cryptlib/OpenSSL/crypto/evp/c_alld.c +++ b/Cryptlib/OpenSSL/crypto/evp/c_alld.c @@ -111,4 +111,7 @@ void OpenSSL_add_all_digests(void) #ifndef OPENSSL_NO_WHIRLPOOL EVP_add_digest(EVP_whirlpool()); #endif +#ifndef OPENSSL_NO_SM3 + EVP_add_digest(EVP_sm3()); +#endif } diff --git a/Cryptlib/OpenSSL/crypto/evp/digest.c b/Cryptlib/OpenSSL/crypto/evp/digest.c index 4db1796..ffc03ef 100644 --- a/Cryptlib/OpenSSL/crypto/evp/digest.c +++ b/Cryptlib/OpenSSL/crypto/evp/digest.c @@ -122,6 +122,48 @@ # include "evp_locl.h" #endif +/* This call frees resources associated with the context */ +int EVP_MD_CTX_reset(EVP_MD_CTX *ctx) +{ + if (ctx == NULL) + return 1; + + /* + * Don't assume ctx->md_data was cleaned in EVP_Digest_Final, because + * sometimes only copies of the context are ever finalised. + */ + if (ctx->digest && ctx->digest->cleanup + && !EVP_MD_CTX_test_flags(ctx, EVP_MD_CTX_FLAG_CLEANED)) + ctx->digest->cleanup(ctx); + if (ctx->digest && ctx->digest->ctx_size && ctx->md_data + && !EVP_MD_CTX_test_flags(ctx, EVP_MD_CTX_FLAG_REUSE)) { + OPENSSL_clear_free(ctx->md_data, ctx->digest->ctx_size); + } + /* + * pctx should be freed by the user of EVP_MD_CTX + * if EVP_MD_CTX_FLAG_KEEP_PKEY_CTX is set + */ + if (!EVP_MD_CTX_test_flags(ctx, EVP_MD_CTX_FLAG_KEEP_PKEY_CTX)) + EVP_PKEY_CTX_free(ctx->pctx); +#ifndef OPENSSL_NO_ENGINE + ENGINE_finish(ctx->engine); +#endif + OPENSSL_cleanse(ctx, sizeof(*ctx)); + + return 1; +} + +EVP_MD_CTX *EVP_MD_CTX_new(void) +{ + return OPENSSL_zalloc(sizeof(EVP_MD_CTX)); +} + +void EVP_MD_CTX_free(EVP_MD_CTX *ctx) +{ + EVP_MD_CTX_reset(ctx); + OPENSSL_free(ctx); +} + void EVP_MD_CTX_init(EVP_MD_CTX *ctx) { memset(ctx, '\0', sizeof *ctx); @@ -139,7 +181,7 @@ EVP_MD_CTX *EVP_MD_CTX_create(void) int EVP_DigestInit(EVP_MD_CTX *ctx, const EVP_MD *type) { - EVP_MD_CTX_init(ctx); + EVP_MD_CTX_reset(ctx); return EVP_DigestInit_ex(ctx, type, NULL); } @@ -264,7 +306,7 @@ int EVP_DigestFinal(EVP_MD_CTX *ctx, unsigned char *md, unsigned int *size) { int ret; ret = EVP_DigestFinal_ex(ctx, md, size); - EVP_MD_CTX_cleanup(ctx); + EVP_MD_CTX_reset(ctx); return ret; } @@ -291,7 +333,7 @@ int EVP_DigestFinal_ex(EVP_MD_CTX *ctx, unsigned char *md, unsigned int *size) int EVP_MD_CTX_copy(EVP_MD_CTX *out, const EVP_MD_CTX *in) { - EVP_MD_CTX_init(out); + EVP_MD_CTX_reset(out); return EVP_MD_CTX_copy_ex(out, in); } @@ -315,9 +357,19 @@ int EVP_MD_CTX_copy_ex(EVP_MD_CTX *out, const EVP_MD_CTX *in) EVP_MD_CTX_set_flags(out, EVP_MD_CTX_FLAG_REUSE); } else tmp_buf = NULL; - EVP_MD_CTX_cleanup(out); + EVP_MD_CTX_reset(out); memcpy(out, in, sizeof *out); + /* copied EVP_MD_CTX should free the copied EVP_PKEY_CTX */ + EVP_MD_CTX_clear_flags(out, EVP_MD_CTX_FLAG_KEEP_PKEY_CTX); + + /* Null these variables, since they are getting fixed up + * properly below. Anything else may cause a memleak and/or + * double free if any of the memory allocations below fail + */ + out->md_data = NULL; + out->pctx = NULL; + if (in->md_data && out->digest->ctx_size) { if (tmp_buf) out->md_data = tmp_buf; @@ -336,7 +388,7 @@ int EVP_MD_CTX_copy_ex(EVP_MD_CTX *out, const EVP_MD_CTX *in) if (in->pctx) { out->pctx = EVP_PKEY_CTX_dup(in->pctx); if (!out->pctx) { - EVP_MD_CTX_cleanup(out); + EVP_MD_CTX_reset(out); return 0; } } diff --git a/Cryptlib/OpenSSL/crypto/evp/evp_lib.c b/Cryptlib/OpenSSL/crypto/evp/evp_lib.c index 7e0bab9..5945494 100644 --- a/Cryptlib/OpenSSL/crypto/evp/evp_lib.c +++ b/Cryptlib/OpenSSL/crypto/evp/evp_lib.c @@ -389,3 +389,8 @@ int EVP_CIPHER_CTX_test_flags(const EVP_CIPHER_CTX *ctx, int flags) { return (ctx->flags & flags); } + +void *EVP_MD_CTX_md_data(const EVP_MD_CTX *ctx) +{ + return ctx->md_data; +} diff --git a/Cryptlib/OpenSSL/crypto/evp/evp_locl.h b/Cryptlib/OpenSSL/crypto/evp/evp_locl.h index 2bb709a..1d179ef 100644 --- a/Cryptlib/OpenSSL/crypto/evp/evp_locl.h +++ b/Cryptlib/OpenSSL/crypto/evp/evp_locl.h @@ -324,6 +324,16 @@ struct evp_pkey_method_st { int (*derive) (EVP_PKEY_CTX *ctx, unsigned char *key, size_t *keylen); int (*ctrl) (EVP_PKEY_CTX *ctx, int type, int p1, void *p2); int (*ctrl_str) (EVP_PKEY_CTX *ctx, const char *type, const char *value); + int (*digestsign) (EVP_MD_CTX *ctx, unsigned char *sig, size_t *siglen, + const unsigned char *tbs, size_t tbslen); + int (*digestverify) (EVP_MD_CTX *ctx, const unsigned char *sig, + size_t siglen, const unsigned char *tbs, + size_t tbslen); + int (*check) (EVP_PKEY *pkey); + int (*public_check) (EVP_PKEY *pkey); + int (*param_check) (EVP_PKEY *pkey); + + int (*digest_custom) (EVP_PKEY_CTX *ctx, EVP_MD_CTX *mctx); } /* EVP_PKEY_METHOD */ ; void evp_pkey_set_cb_translate(BN_GENCB *cb, EVP_PKEY_CTX *ctx); diff --git a/Cryptlib/OpenSSL/crypto/evp/m_sigver.c b/Cryptlib/OpenSSL/crypto/evp/m_sigver.c index 4492d20..771b659 100644 --- a/Cryptlib/OpenSSL/crypto/evp/m_sigver.c +++ b/Cryptlib/OpenSSL/crypto/evp/m_sigver.c @@ -110,6 +110,13 @@ static int do_sigver_init(EVP_MD_CTX *ctx, EVP_PKEY_CTX **pctx, return 1; if (!EVP_DigestInit_ex(ctx, type, e)) return 0; + /* + * This indicates the current algorithm requires + * special treatment before hashing the tbs-message. + */ + if (ctx->pctx->pmeth->digest_custom != NULL) + return ctx->pctx->pmeth->digest_custom(ctx->pctx, ctx); + return 1; } @@ -201,3 +208,13 @@ int EVP_DigestVerifyFinal(EVP_MD_CTX *ctx, const unsigned char *sig, return r; return EVP_PKEY_verify(ctx->pctx, sig, siglen, md, mdlen); } + +int EVP_DigestVerify(EVP_MD_CTX *ctx, const unsigned char *sigret, + size_t siglen, const unsigned char *tbs, size_t tbslen) +{ + if (ctx->pctx->pmeth->digestverify != NULL) + return ctx->pctx->pmeth->digestverify(ctx, sigret, siglen, tbs, tbslen); + if (EVP_DigestVerifyUpdate(ctx, tbs, tbslen) <= 0) + return -1; + return EVP_DigestVerifyFinal(ctx, sigret, siglen); +} diff --git a/Cryptlib/OpenSSL/crypto/evp/p_lib.c b/Cryptlib/OpenSSL/crypto/evp/p_lib.c index 545d04f..c95d038 100644 --- a/Cryptlib/OpenSSL/crypto/evp/p_lib.c +++ b/Cryptlib/OpenSSL/crypto/evp/p_lib.c @@ -259,6 +259,24 @@ int EVP_PKEY_set_type_str(EVP_PKEY *pkey, const char *str, int len) return pkey_set_type(pkey, EVP_PKEY_NONE, str, len); } +int EVP_PKEY_set_alias_type(EVP_PKEY *pkey, int type) +{ + if (pkey->type == type) { + return 1; /* it already is that type */ + } + + /* + * The application is requesting to alias this to a different pkey type, + * but not one that resolves to the base type. + */ + if (EVP_PKEY_type(type) != EVP_PKEY_base_id(pkey)) { + return 0; + } + + pkey->type = type; + return 1; +} + int EVP_PKEY_assign(EVP_PKEY *pkey, int type, void *key) { if (pkey == NULL || !EVP_PKEY_set_type(pkey, type)) @@ -272,6 +290,24 @@ void *EVP_PKEY_get0(EVP_PKEY *pkey) return pkey->pkey.ptr; } +# 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_get1_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) { @@ -322,6 +358,14 @@ int EVP_PKEY_set1_EC_KEY(EVP_PKEY *pkey, EC_KEY *key) return ret; } +EC_KEY *EVP_PKEY_get0_EC_KEY(EVP_PKEY *pkey) +{ + if (EVP_PKEY_base_id(pkey) != EVP_PKEY_EC) { + return NULL; + } + return pkey->pkey.ec; +} + EC_KEY *EVP_PKEY_get1_EC_KEY(EVP_PKEY *pkey) { if (pkey->type != EVP_PKEY_EC) { diff --git a/Cryptlib/OpenSSL/crypto/evp/pmeth_lib.c b/Cryptlib/OpenSSL/crypto/evp/pmeth_lib.c index d066862..8e52917 100644 --- a/Cryptlib/OpenSSL/crypto/evp/pmeth_lib.c +++ b/Cryptlib/OpenSSL/crypto/evp/pmeth_lib.c @@ -75,7 +75,7 @@ STACK_OF(EVP_PKEY_METHOD) *app_pkey_methods = NULL; extern const EVP_PKEY_METHOD rsa_pkey_meth, dh_pkey_meth, dsa_pkey_meth; extern const EVP_PKEY_METHOD ec_pkey_meth, hmac_pkey_meth, cmac_pkey_meth; -extern const EVP_PKEY_METHOD dhx_pkey_meth; +extern const EVP_PKEY_METHOD dhx_pkey_meth, sm2_pkey_meth; static const EVP_PKEY_METHOD *standard_methods[] = { #ifndef OPENSSL_NO_RSA @@ -95,7 +95,10 @@ static const EVP_PKEY_METHOD *standard_methods[] = { &cmac_pkey_meth, #endif #ifndef OPENSSL_NO_DH - &dhx_pkey_meth + &dhx_pkey_meth, +#endif +#ifndef OPENSSL_NO_SM2 + &sm2_pkey_meth, #endif }; @@ -135,9 +138,9 @@ static EVP_PKEY_CTX *int_ctx_new(EVP_PKEY *pkey, ENGINE *e, int id) EVP_PKEY_CTX *ret; const EVP_PKEY_METHOD *pmeth; if (id == -1) { - if (!pkey || !pkey->ameth) + if (!pkey) return NULL; - id = pkey->ameth->pkey_id; + id = pkey->type; } #ifndef OPENSSL_NO_ENGINE if (pkey && pkey->engine) @@ -365,6 +368,10 @@ int EVP_PKEY_CTX_ctrl(EVP_PKEY_CTX *ctx, int keytype, int optype, if ((keytype != -1) && (ctx->pmeth->pkey_id != keytype)) return -1; +/* Skip the operation checks since this is called in a very early stage */ + if (ctx->pmeth->digest_custom != NULL) + goto doit; + if (ctx->operation == EVP_PKEY_OP_UNDEFINED) { EVPerr(EVP_F_EVP_PKEY_CTX_CTRL, EVP_R_NO_OPERATION_SET); return -1; @@ -375,6 +382,7 @@ int EVP_PKEY_CTX_ctrl(EVP_PKEY_CTX *ctx, int keytype, int optype, return -1; } +doit: ret = ctx->pmeth->ctrl(ctx, cmd, p1, p2); if (ret == -2) diff --git a/Cryptlib/OpenSSL/crypto/mem.c b/Cryptlib/OpenSSL/crypto/mem.c index 06c3960..ae5a165 100644 --- a/Cryptlib/OpenSSL/crypto/mem.c +++ b/Cryptlib/OpenSSL/crypto/mem.c @@ -456,3 +456,21 @@ long CRYPTO_get_mem_debug_options(void) return get_debug_options_func(); return 0; } + +void *CRYPTO_zalloc(int num, const char *file, int line) +{ + void *ret = CRYPTO_malloc(num, file, line); + + if (ret != NULL) + memset(ret, 0, num); + return ret; +} + +void CRYPTO_clear_free(void *str, int num, const char *file, int line) +{ + if (str == NULL) + return; + if (num) + OPENSSL_cleanse(str, num); + CRYPTO_free(str); +} diff --git a/Cryptlib/OpenSSL/crypto/o_str.c b/Cryptlib/OpenSSL/crypto/o_str.c index 7e61cde..c46c631 100644 --- a/Cryptlib/OpenSSL/crypto/o_str.c +++ b/Cryptlib/OpenSSL/crypto/o_str.c @@ -60,6 +60,8 @@ #include #include #include "o_str.h" +#include "openssl/crypto.h" +#include "openssl/err.h" #if !defined(OPENSSL_IMPLEMENTS_strncasecmp) && \ !defined(OPENSSL_SYSNAME_WIN32) && !defined(OPENSSL_SYSNAME_WINCE) && \ @@ -114,3 +116,88 @@ int OPENSSL_memcmp(const void *v1, const void *v2, size_t n) return ret; } + +int OPENSSL_hexchar2int(unsigned char c) +{ +#ifdef CHARSET_EBCDIC + c = os_toebcdic[c]; +#endif + + switch (c) { + case '0': + return 0; + case '1': + return 1; + case '2': + return 2; + case '3': + return 3; + case '4': + return 4; + case '5': + return 5; + case '6': + return 6; + case '7': + return 7; + case '8': + return 8; + case '9': + return 9; + case 'a': case 'A': + return 0x0A; + case 'b': case 'B': + return 0x0B; + case 'c': case 'C': + return 0x0C; + case 'd': case 'D': + return 0x0D; + case 'e': case 'E': + return 0x0E; + case 'f': case 'F': + return 0x0F; + } + return -1; +} + +/* + * Give a string of hex digits convert to a buffer + */ +unsigned char *OPENSSL_hexstr2buf(const char *str, long *len) +{ + unsigned char *hexbuf, *q; + unsigned char ch, cl; + int chi, cli; + const unsigned char *p; + size_t s; + + s = strlen(str); + if ((hexbuf = OPENSSL_malloc(s >> 1)) == NULL) { + CRYPTOerr(CRYPTO_F_OPENSSL_HEXSTR2BUF, ERR_R_MALLOC_FAILURE); + return NULL; + } + for (p = (const unsigned char *)str, q = hexbuf; *p; ) { + ch = *p++; + if (ch == ':') + continue; + cl = *p++; + if (!cl) { + CRYPTOerr(CRYPTO_F_OPENSSL_HEXSTR2BUF, + CRYPTO_R_ODD_NUMBER_OF_DIGITS); + OPENSSL_free(hexbuf); + return NULL; + } + cli = OPENSSL_hexchar2int(cl); + chi = OPENSSL_hexchar2int(ch); + if (cli < 0 || chi < 0) { + OPENSSL_free(hexbuf); + CRYPTOerr(CRYPTO_F_OPENSSL_HEXSTR2BUF, CRYPTO_R_ILLEGAL_HEX_DIGIT); + return NULL; + } + *q++ = (unsigned char)((chi << 4) | cli); + } + + if (len) + *len = q - hexbuf; + return hexbuf; +} diff --git a/Cryptlib/OpenSSL/crypto/objects/obj_dat.h b/Cryptlib/OpenSSL/crypto/objects/obj_dat.h index b7e3cf2..30ea261 100644 --- a/Cryptlib/OpenSSL/crypto/objects/obj_dat.h +++ b/Cryptlib/OpenSSL/crypto/objects/obj_dat.h @@ -62,12 +62,12 @@ * [including the GNU Public Licence.] */ -#define NUM_NID 958 -#define NUM_SN 951 -#define NUM_LN 951 -#define NUM_OBJ 890 +#define NUM_NID 965 +#define NUM_SN 958 +#define NUM_LN 958 +#define NUM_OBJ 897 -static const unsigned char lvalues[6255]={ +static const unsigned char lvalues[6301]={ 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 */ @@ -952,6 +952,13 @@ static const unsigned char lvalues[6255]={ 0x2B,0x06,0x01,0x04,0x01,0x82,0x37,0x3C,0x02,0x01,0x01,/* [6221] OBJ_jurisdictionLocalityName */ 0x2B,0x06,0x01,0x04,0x01,0x82,0x37,0x3C,0x02,0x01,0x02,/* [6232] OBJ_jurisdictionStateOrProvinceName */ 0x2B,0x06,0x01,0x04,0x01,0x82,0x37,0x3C,0x02,0x01,0x03,/* [6243] OBJ_jurisdictionCountryName */ +0x2A,0x81,0x1C, /* [6254] OBJ_ISO_CN */ +0x2A,0x81,0x1C,0xCF,0x55, /* [6257] OBJ_oscca */ +0x2A,0x81,0x1C,0xCF,0x55,0x01, /* [6262] OBJ_sm_scheme */ +0x2A,0x81,0x1C,0xCF,0x55,0x01,0x82,0x2D, /* [6268] OBJ_sm2 */ +0x2A,0x81,0x1C,0xCF,0x55,0x01,0x83,0x11, /* [6276] OBJ_sm3 */ +0x2A,0x81,0x1C,0xCF,0x55,0x01,0x83,0x78, /* [6284] OBJ_sm3WithRSAEncryption */ +0x2A,0x81,0x1C,0xCF,0x55,0x01,0x83,0x75, /* [6292] OBJ_SM2_with_SM3 */ }; static const ASN1_OBJECT nid_objs[NUM_NID]={ @@ -2514,6 +2521,14 @@ static const ASN1_OBJECT nid_objs[NUM_NID]={ NID_jurisdictionStateOrProvinceName,11,&(lvalues[6232]),0}, {"jurisdictionC","jurisdictionCountryName", NID_jurisdictionCountryName,11,&(lvalues[6243]),0}, +{"ISO-CN","ISO CN Member Body",NID_ISO_CN,3,&(lvalues[6254]),0}, +{"oscca","oscca",NID_oscca,5,&(lvalues[6257]),0}, +{"sm-scheme","sm-scheme",NID_sm_scheme,6,&(lvalues[6262]),0}, +{"SM2","sm2",NID_sm2,8,&(lvalues[6268]),0}, +{"SM3","sm3",NID_sm3,8,&(lvalues[6276]),0}, +{"RSA-SM3","sm3WithRSAEncryption",NID_sm3WithRSAEncryption,8, + &(lvalues[6284]),0}, +{"SM2-SM3","SM2-with-SM3",NID_SM2_with_SM3,8,&(lvalues[6292]),0}, }; static const unsigned int sn_objs[NUM_SN]={ @@ -2615,6 +2630,7 @@ static const unsigned int sn_objs[NUM_SN]={ 36, /* "IDEA-ECB" */ 46, /* "IDEA-OFB" */ 181, /* "ISO" */ +958, /* "ISO-CN" */ 183, /* "ISO-US" */ 645, /* "ITU-T" */ 646, /* "JOINT-ISO-ITU-T" */ @@ -2685,6 +2701,10 @@ static const unsigned int sn_objs[NUM_SN]={ 668, /* "RSA-SHA256" */ 669, /* "RSA-SHA384" */ 670, /* "RSA-SHA512" */ +963, /* "RSA-SM3" */ +961, /* "SM2" */ +964, /* "SM2-SM3" */ +962, /* "SM3" */ 919, /* "RSAES-OAEP" */ 912, /* "RSASSA-PSS" */ 777, /* "SEED-CBC" */ @@ -3176,6 +3196,7 @@ static const unsigned int sn_objs[NUM_SN]={ 77, /* "nsSslServerName" */ 681, /* "onBasis" */ 491, /* "organizationalStatus" */ +959, /* "oscca" */ 475, /* "otherMailbox" */ 876, /* "owner" */ 489, /* "pagerTelephoneNumber" */ @@ -3422,6 +3443,7 @@ static const unsigned int sn_objs[NUM_SN]={ 52, /* "signingTime" */ 454, /* "simpleSecurityObject" */ 496, /* "singleLevelQuality" */ +960, /* "sm-scheme" */ 387, /* "snmpv2" */ 660, /* "street" */ 85, /* "subjectAltName" */ @@ -3519,6 +3541,7 @@ static const unsigned int ln_objs[NUM_LN]={ 294, /* "IPSec End System" */ 295, /* "IPSec Tunnel" */ 296, /* "IPSec User" */ +958, /* "ISO CN Member Body" */ 182, /* "ISO Member Body" */ 183, /* "ISO US Member Body" */ 667, /* "Independent" */ @@ -3573,6 +3596,7 @@ static const unsigned int ln_objs[NUM_LN]={ 2, /* "RSA Data Security, Inc. PKCS" */ 188, /* "S/MIME" */ 167, /* "S/MIME Capabilities" */ +964, /* "SM2-with-SM3" */ 387, /* "SNMPv2" */ 512, /* "Secure Electronic Transactions" */ 386, /* "Security" */ @@ -4105,6 +4129,7 @@ static const unsigned int ln_objs[NUM_LN]={ 17, /* "organizationName" */ 491, /* "organizationalStatus" */ 18, /* "organizationalUnitName" */ +959, /* "oscca" */ 475, /* "otherMailbox" */ 876, /* "owner" */ 935, /* "pSpecified" */ @@ -4379,6 +4404,10 @@ static const unsigned int ln_objs[NUM_LN]={ 52, /* "signingTime" */ 454, /* "simpleSecurityObject" */ 496, /* "singleLevelQuality" */ +960, /* "sm-scheme" */ +961, /* "sm2" */ +962, /* "sm3" */ +963, /* "sm3WithRSAEncryption" */ 16, /* "stateOrProvinceName" */ 660, /* "streetAddress" */ 498, /* "subtreeMaximumQuality" */ @@ -4444,6 +4473,7 @@ static const unsigned int obj_objs[NUM_OBJ]={ 512, /* OBJ_id_set 2 23 42 */ 678, /* OBJ_wap 2 23 43 */ 435, /* OBJ_pss 0 9 2342 */ +958, /* OBJ_ISO_CN 1 2 156 */ 183, /* OBJ_ISO_US 1 2 840 */ 381, /* OBJ_iana 1 3 6 1 */ 677, /* OBJ_certicom_arc 1 3 132 */ @@ -4659,6 +4689,7 @@ static const unsigned int obj_objs[NUM_OBJ]={ 637, /* OBJ_set_brand_Diners 2 23 42 8 30 */ 638, /* OBJ_set_brand_AmericanExpress 2 23 42 8 34 */ 639, /* OBJ_set_brand_JCB 2 23 42 8 35 */ +959, /* OBJ_oscca 1 2 156 10197 */ 805, /* OBJ_cryptopro 1 2 643 2 2 */ 806, /* OBJ_cryptocom 1 2 643 2 9 */ 184, /* OBJ_X9_57 1 2 840 10040 */ @@ -4733,6 +4764,7 @@ static const unsigned int obj_objs[NUM_OBJ]={ 745, /* OBJ_wap_wsg_idm_ecid_wtls12 2 23 43 1 4 12 */ 804, /* OBJ_whirlpool 1 0 10118 3 0 55 */ 124, /* OBJ_rle_compression 1 1 1 1 666 1 */ +960, /* OBJ_sm_scheme 1 2 156 10197 1 */ 773, /* OBJ_kisa 1 2 410 200004 */ 807, /* OBJ_id_GostR3411_94_with_GostR3410_2001 1 2 643 2 2 3 */ 808, /* OBJ_id_GostR3411_94_with_GostR3410_94 1 2 643 2 2 4 */ @@ -4836,6 +4868,10 @@ static const unsigned int obj_objs[NUM_OBJ]={ 768, /* OBJ_camellia_256_ofb128 0 3 4401 5 3 1 9 43 */ 759, /* OBJ_camellia_256_cfb128 0 3 4401 5 3 1 9 44 */ 437, /* OBJ_pilot 0 9 2342 19200300 100 */ +961, /* OBJ_sm2 1 2 156 10197 1 301 */ +962, /* OBJ_sm3 1 2 156 10197 1 401 */ +964, /* OBJ_SM2_with_SM3 1 2 156 10197 1 501 */ +963, /* 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 */ 779, /* OBJ_seed_cfb128 1 2 410 200004 1 5 */ diff --git a/Cryptlib/OpenSSL/crypto/objects/obj_xref.h b/Cryptlib/OpenSSL/crypto/objects/obj_xref.h index e453e99..cf08a14 100644 --- a/Cryptlib/OpenSSL/crypto/objects/obj_xref.h +++ b/Cryptlib/OpenSSL/crypto/objects/obj_xref.h @@ -56,6 +56,7 @@ static const nid_triple sigoid_srt[] = { NID_dh_cofactor_kdf}, {NID_dhSinglePass_cofactorDH_sha512kdf_scheme, NID_sha512, NID_dh_cofactor_kdf}, + {NID_SM2_with_SM3, NID_sm3, NID_sm2}, }; static const nid_triple *const sigoid_srt_xref[] = { @@ -96,4 +97,5 @@ static const nid_triple *const sigoid_srt_xref[] = { &sigoid_srt[26], &sigoid_srt[27], &sigoid_srt[28], + &sigoid_srt[40], }; diff --git a/Cryptlib/OpenSSL/crypto/pkcs7/pk7_doit.c b/Cryptlib/OpenSSL/crypto/pkcs7/pk7_doit.c index dd6c73f..846fcf8 100644 --- a/Cryptlib/OpenSSL/crypto/pkcs7/pk7_doit.c +++ b/Cryptlib/OpenSSL/crypto/pkcs7/pk7_doit.c @@ -1036,10 +1036,10 @@ int PKCS7_signatureVerify(BIO *bio, PKCS7 *p7, PKCS7_SIGNER_INFO *si, ASN1_OCTET_STRING *os; EVP_MD_CTX mdc_tmp, *mdc; int ret = 0, i; - int md_type; + int md_type, is_sm2 = 0; STACK_OF(X509_ATTRIBUTE) *sk; BIO *btmp; - EVP_PKEY *pkey; + EVP_PKEY *pkey = NULL; EVP_MD_CTX_init(&mdc_tmp); @@ -1074,6 +1074,18 @@ int PKCS7_signatureVerify(BIO *bio, PKCS7 *p7, PKCS7_SIGNER_INFO *si, btmp = BIO_next(btmp); } +#ifndef OPENSSL_NO_SM2 + pkey = X509_get_pubkey(x509); + if (!pkey) + goto err; + + if (EVP_PKEY_is_sm2(pkey)) { + is_sm2 = 1; + if (!EVP_PKEY_set_alias_type(pkey, EVP_PKEY_SM2)) + goto err; + } +#endif + /* * mdc is the digest ctx that we want, unless there are attributes, in * which case the digest is the signed attributes @@ -1114,7 +1126,12 @@ int PKCS7_signatureVerify(BIO *bio, PKCS7 *p7, PKCS7_SIGNER_INFO *si, goto err; } - if (!EVP_VerifyInit_ex(&mdc_tmp, EVP_get_digestbynid(md_type), NULL)) + ret = is_sm2 ? EVP_DigestVerifyInit(&mdc_tmp, NULL, EVP_get_digestbynid(md_type), NULL, pkey) : + EVP_VerifyInit_ex(&mdc_tmp, EVP_get_digestbynid(md_type), NULL); + if (!ret) + goto err; + + if (!EVP_DigestVerifyInit(&mdc_tmp, NULL, EVP_get_digestbynid(md_type), NULL, pkey)) goto err; alen = ASN1_item_i2d((ASN1_VALUE *)sk, &abuf, @@ -1131,14 +1148,8 @@ int PKCS7_signatureVerify(BIO *bio, PKCS7 *p7, PKCS7_SIGNER_INFO *si, } os = si->enc_digest; - pkey = X509_get_pubkey(x509); - if (!pkey) { - ret = -1; - goto err; - } - - i = EVP_VerifyFinal(&mdc_tmp, os->data, os->length, pkey); - EVP_PKEY_free(pkey); + i = is_sm2 ? EVP_DigestVerifyFinal(&mdc_tmp, os->data, os->length) : + EVP_VerifyFinal(&mdc_tmp, os->data, os->length, pkey); if (i <= 0) { PKCS7err(PKCS7_F_PKCS7_SIGNATUREVERIFY, PKCS7_R_SIGNATURE_FAILURE); ret = -1; @@ -1146,6 +1157,7 @@ int PKCS7_signatureVerify(BIO *bio, PKCS7 *p7, PKCS7_SIGNER_INFO *si, } else ret = 1; err: + EVP_PKEY_free(pkey); EVP_MD_CTX_cleanup(&mdc_tmp); return (ret); } diff --git a/Cryptlib/OpenSSL/crypto/x509/x_all.c b/Cryptlib/OpenSSL/crypto/x509/x_all.c index 0f26c54..0228582 100644 --- a/Cryptlib/OpenSSL/crypto/x509/x_all.c +++ b/Cryptlib/OpenSSL/crypto/x509/x_all.c @@ -71,16 +71,158 @@ # include #endif +#ifndef OPENSSL_NO_SM2 + +# include "openssl/asn1.h" +# include "openssl/evp.h" +# include "crypto/asn1/asn1_locl.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; + 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) { + goto err; + } + + if (pkey == NULL) { + 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) { + return -1; + } + + EVP_MD_CTX_init(&ctx); + + /* Check public key OID matches public key type */ + if (EVP_PKEY_type(pknid) != pkey->ameth->pkey_id) { + goto err; + } + + if (!EVP_PKEY_set_type(pkey, EVP_PKEY_SM2)) { + ret = 0; + goto err; + } + pctx = EVP_PKEY_CTX_new(pkey, NULL); + if (pctx == NULL) { + 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) { + ret = 0; + goto err; + } + EVP_MD_CTX_set_flags(&ctx, EVP_MD_CTX_FLAG_KEEP_PKEY_CTX); + + if (!EVP_DigestVerifyInit(&ctx, NULL, type, NULL, pkey)) { + 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) { + goto err; + } + if (buf_in == NULL) { + goto err; + } + inll = inl; + + ret = EVP_DigestVerify(&ctx, signature->data, + (size_t)signature->length, buf_in, inl); + if (ret <= 0) { + goto err; + } + ret = 1; + err: + OPENSSL_cleanse(buf_in, inll); + EVP_MD_CTX_cleanup(&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)) { + 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)) { + 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/Cryptlib/Pk/CryptPkcs7Verify.c b/Cryptlib/Pk/CryptPkcs7Verify.c index c189384..7fa8c41 100644 --- a/Cryptlib/Pk/CryptPkcs7Verify.c +++ b/Cryptlib/Pk/CryptPkcs7Verify.c @@ -878,6 +878,11 @@ Pkcs7Verify ( if (EVP_add_digest (EVP_sha512 ()) == 0) { return FALSE; } +#ifndef OPENSSL_NO_SM3 + if (EVP_add_digest (EVP_sm3 ()) == 0) { + return FALSE; + } +#endif if (EVP_add_digest_alias (SN_sha1WithRSAEncryption, SN_sha1WithRSA) == 0) { return FALSE; } -- 2.33.0