From: Jack Lloyd Date: Mon, 18 Jun 2018 19:51:56 +0000 (-0400) Subject: Move SM2 algos to SM2 specific PKEY method X-Git-Tag: OpenSSL_1_1_1-pre8~9 X-Git-Url: https://git.openssl.org/?p=openssl.git;a=commitdiff_plain;h=ddb634fe6f9aeea34fe036cf804903b4240d38ac Move SM2 algos to SM2 specific PKEY method Use EVP_PKEY_set_alias_type to access Reviewed-by: Andy Polyakov Reviewed-by: Matt Caswell (Merged from https://github.com/openssl/openssl/pull/6443) --- diff --git a/crypto/asn1/standard_methods.h b/crypto/asn1/standard_methods.h index 0dcd6b8cc9..e74de55ffe 100644 --- a/crypto/asn1/standard_methods.h +++ b/crypto/asn1/standard_methods.h @@ -54,5 +54,8 @@ static const EVP_PKEY_ASN1_METHOD *standard_methods[] = { &ed25519_asn1_meth, &ed448_asn1_meth, #endif +#ifndef OPENSSL_NO_SM2 + &sm2_asn1_meth, +#endif }; diff --git a/crypto/ec/ec_ameth.c b/crypto/ec/ec_ameth.c index 0682bc3d1d..4096cb3294 100644 --- a/crypto/ec/ec_ameth.c +++ b/crypto/ec/ec_ameth.c @@ -602,6 +602,14 @@ const EVP_PKEY_ASN1_METHOD eckey_asn1_meth = { ec_pkey_param_check }; +#if !defined(OPENSSL_NO_SM2) +const EVP_PKEY_ASN1_METHOD sm2_asn1_meth = { + EVP_PKEY_SM2, + EVP_PKEY_EC, + ASN1_PKEY_ALIAS +}; +#endif + int EC_KEY_print(BIO *bp, const EC_KEY *x, int off) { int private = EC_KEY_get0_private_key(x) != NULL; diff --git a/crypto/ec/ec_err.c b/crypto/ec/ec_err.c index 94a72072ce..6a1be2eb3b 100644 --- a/crypto/ec/ec_err.c +++ b/crypto/ec/ec_err.c @@ -259,6 +259,12 @@ static const ERR_STRING_DATA EC_str_functs[] = { {ERR_PACK(ERR_LIB_EC, EC_F_PKEY_EC_KEYGEN, 0), "pkey_ec_keygen"}, {ERR_PACK(ERR_LIB_EC, EC_F_PKEY_EC_PARAMGEN, 0), "pkey_ec_paramgen"}, {ERR_PACK(ERR_LIB_EC, EC_F_PKEY_EC_SIGN, 0), "pkey_ec_sign"}, + {ERR_PACK(ERR_LIB_EC, EC_F_PKEY_SM2_CTRL, 0), "pkey_sm2_ctrl"}, + {ERR_PACK(ERR_LIB_EC, EC_F_PKEY_SM2_CTRL_STR, 0), "pkey_sm2_ctrl_str"}, + {ERR_PACK(ERR_LIB_EC, EC_F_PKEY_SM2_INIT, 0), "pkey_sm2_init"}, + {ERR_PACK(ERR_LIB_EC, EC_F_PKEY_SM2_KEYGEN, 0), "pkey_sm2_keygen"}, + {ERR_PACK(ERR_LIB_EC, EC_F_PKEY_SM2_PARAMGEN, 0), "pkey_sm2_paramgen"}, + {ERR_PACK(ERR_LIB_EC, EC_F_PKEY_SM2_SIGN, 0), "pkey_sm2_sign"}, {ERR_PACK(ERR_LIB_EC, EC_F_VALIDATE_ECX_DERIVE, 0), "validate_ecx_derive"}, {0, NULL} }; diff --git a/crypto/ec/ec_pmeth.c b/crypto/ec/ec_pmeth.c index 0187adfa2b..f4ea8b56c1 100644 --- a/crypto/ec/ec_pmeth.c +++ b/crypto/ec/ec_pmeth.c @@ -16,10 +16,6 @@ #include #include "internal/evp_int.h" -#if !defined(OPENSSL_NO_SM2) -# include "internal/sm2.h" -#endif - /* EC pkey context structure */ typedef struct { @@ -107,7 +103,6 @@ static int pkey_ec_sign(EVP_PKEY_CTX *ctx, unsigned char *sig, size_t *siglen, unsigned int sltmp; EC_PKEY_CTX *dctx = ctx->data; EC_KEY *ec = ctx->pkey->pkey.ec; - const int ec_nid = EC_GROUP_get_curve_name(EC_KEY_get0_group(ec)); if (!sig) { *siglen = ECDSA_size(ec); @@ -122,15 +117,7 @@ static int pkey_ec_sign(EVP_PKEY_CTX *ctx, unsigned char *sig, size_t *siglen, else type = NID_sha1; - if (ec_nid == NID_sm2) { -#if defined(OPENSSL_NO_SM2) - return -1; -#else - ret = sm2_sign(type, tbs, tbslen, sig, &sltmp, ec); -#endif - } else { - ret = ECDSA_sign(type, tbs, tbslen, sig, &sltmp, ec); - } + ret = ECDSA_sign(type, tbs, tbslen, sig, &sltmp, ec); if (ret <= 0) return ret; @@ -145,22 +132,13 @@ static int pkey_ec_verify(EVP_PKEY_CTX *ctx, int ret, type; EC_PKEY_CTX *dctx = ctx->data; EC_KEY *ec = ctx->pkey->pkey.ec; - const int ec_nid = EC_GROUP_get_curve_name(EC_KEY_get0_group(ec)); if (dctx->md) type = EVP_MD_type(dctx->md); else type = NID_sha1; - if (ec_nid == NID_sm2) { -#if defined(OPENSSL_NO_SM2) - ret = -1; -#else - ret = sm2_verify(type, tbs, tbslen, sig, siglen, ec); -#endif - } else { - ret = ECDSA_verify(type, tbs, tbslen, sig, siglen, ec); - } + ret = ECDSA_verify(type, tbs, tbslen, sig, siglen, ec); return ret; } @@ -202,86 +180,6 @@ static int pkey_ec_derive(EVP_PKEY_CTX *ctx, unsigned char *key, size_t *keylen) return 1; } -static int pkey_ecies_encrypt(EVP_PKEY_CTX *ctx, - unsigned char *out, size_t *outlen, - const unsigned char *in, size_t inlen) -{ - int ret; - EC_KEY *ec = ctx->pkey->pkey.ec; - const int ec_nid = EC_GROUP_get_curve_name(EC_KEY_get0_group(ec)); - - if (ec_nid == NID_sm2) { -# if defined(OPENSSL_NO_SM2) - ret = -1; -# else - int md_type; - EC_PKEY_CTX *dctx = ctx->data; - - if (dctx->md) - md_type = EVP_MD_type(dctx->md); - else - md_type = NID_sm3; - - if (out == NULL) { - if (!sm2_ciphertext_size(ec, EVP_get_digestbynid(md_type), inlen, - outlen)) - ret = -1; - else - ret = 1; - } - else { - ret = sm2_encrypt(ec, EVP_get_digestbynid(md_type), - in, inlen, out, outlen); - } -# endif - } else { - /* standard ECIES not implemented */ - ret = -1; - } - - return ret; -} - -static int pkey_ecies_decrypt(EVP_PKEY_CTX *ctx, - unsigned char *out, size_t *outlen, - const unsigned char *in, size_t inlen) -{ - int ret; - EC_KEY *ec = ctx->pkey->pkey.ec; - const int ec_nid = EC_GROUP_get_curve_name(EC_KEY_get0_group(ec)); - - if (ec_nid == NID_sm2) { -# if defined(OPENSSL_NO_SM2) - ret = -1; -# else - int md_type; - EC_PKEY_CTX *dctx = ctx->data; - - if (dctx->md) - md_type = EVP_MD_type(dctx->md); - else - md_type = NID_sm3; - - if (out == NULL) { - if (!sm2_plaintext_size(ec, EVP_get_digestbynid(md_type), inlen, - outlen)) - ret = -1; - else - ret = 1; - } - else { - ret = sm2_decrypt(ec, EVP_get_digestbynid(md_type), - in, inlen, out, outlen); - } -# endif - } else { - /* standard ECIES not implemented */ - ret = -1; - } - - return ret; -} - static int pkey_ec_kdf_derive(EVP_PKEY_CTX *ctx, unsigned char *key, size_t *keylen) { @@ -420,8 +318,7 @@ static int pkey_ec_ctrl(EVP_PKEY_CTX *ctx, int type, int p1, void *p2) EVP_MD_type((const EVP_MD *)p2) != NID_sha224 && EVP_MD_type((const EVP_MD *)p2) != NID_sha256 && EVP_MD_type((const EVP_MD *)p2) != NID_sha384 && - EVP_MD_type((const EVP_MD *)p2) != NID_sha512 && - EVP_MD_type((const EVP_MD *)p2) != NID_sm3) { + EVP_MD_type((const EVP_MD *)p2) != NID_sha512) { ECerr(EC_F_PKEY_EC_CTRL, EC_R_INVALID_DIGEST_TYPE); return 0; } @@ -552,10 +449,10 @@ const EVP_PKEY_METHOD ec_pkey_meth = { 0, 0, 0, 0, 0, - pkey_ecies_encrypt, + 0, 0, - pkey_ecies_decrypt, + 0, 0, #ifndef OPENSSL_NO_EC diff --git a/crypto/err/openssl.txt b/crypto/err/openssl.txt index 363cca7337..23671a0f26 100644 --- a/crypto/err/openssl.txt +++ b/crypto/err/openssl.txt @@ -1068,6 +1068,10 @@ RSA_F_RSA_VERIFY:119:RSA_verify RSA_F_RSA_VERIFY_ASN1_OCTET_STRING:120:RSA_verify_ASN1_OCTET_STRING RSA_F_RSA_VERIFY_PKCS1_PSS_MGF1:126:RSA_verify_PKCS1_PSS_mgf1 RSA_F_SETUP_TBUF:167:setup_tbuf +SM2_F_PKEY_SM2_CTRL:109:pkey_sm2_ctrl +SM2_F_PKEY_SM2_CTRL_STR:110:pkey_sm2_ctrl_str +SM2_F_PKEY_SM2_INIT:111:pkey_sm2_init +SM2_F_PKEY_SM2_SIGN:112:pkey_sm2_sign SM2_F_SM2_COMPUTE_MSG_HASH:100:sm2_compute_msg_hash SM2_F_SM2_COMPUTE_USERID_DIGEST:101:sm2_compute_userid_digest SM2_F_SM2_DECRYPT:102:sm2_decrypt @@ -2528,10 +2532,13 @@ RSA_R_VALUE_MISSING:147:value missing RSA_R_WRONG_SIGNATURE_LENGTH:119:wrong signature length SM2_R_ASN1_ERROR:100:asn1 error SM2_R_BAD_SIGNATURE:101:bad signature +SM2_R_BUFFER_TOO_SMALL:107:buffer too small +SM2_R_INVALID_CURVE:108:invalid curve SM2_R_INVALID_DIGEST:102:invalid digest SM2_R_INVALID_DIGEST_TYPE:103:invalid digest type SM2_R_INVALID_ENCODING:104:invalid encoding SM2_R_INVALID_FIELD:105:invalid field +SM2_R_NO_PARAMETERS_SET:109:no parameters set SM2_R_USER_ID_TOO_LARGE:106:user id too large SSL_R_APP_DATA_IN_HANDSHAKE:100:app data in handshake SSL_R_ATTEMPT_TO_REUSE_SESSION_IN_DIFFERENT_CONTEXT:272:\ diff --git a/crypto/evp/pmeth_lib.c b/crypto/evp/pmeth_lib.c index c7dc453308..6a0fc81f1f 100644 --- a/crypto/evp/pmeth_lib.c +++ b/crypto/evp/pmeth_lib.c @@ -64,6 +64,9 @@ static const EVP_PKEY_METHOD *standard_methods[] = { &ed25519_pkey_meth, &ed448_pkey_meth, #endif +#ifndef OPENSSL_NO_SM2 + &sm2_pkey_meth, +#endif }; DECLARE_OBJ_BSEARCH_CMP_FN(const EVP_PKEY_METHOD *, const EVP_PKEY_METHOD *, diff --git a/crypto/include/internal/asn1_int.h b/crypto/include/internal/asn1_int.h index b8a6762aa1..9c9b4d8974 100644 --- a/crypto/include/internal/asn1_int.h +++ b/crypto/include/internal/asn1_int.h @@ -76,6 +76,7 @@ extern const EVP_PKEY_ASN1_METHOD ecx25519_asn1_meth; extern const EVP_PKEY_ASN1_METHOD ecx448_asn1_meth; extern const EVP_PKEY_ASN1_METHOD ed25519_asn1_meth; extern const EVP_PKEY_ASN1_METHOD ed448_asn1_meth; +extern const EVP_PKEY_ASN1_METHOD sm2_asn1_meth; extern const EVP_PKEY_ASN1_METHOD poly1305_asn1_meth; extern const EVP_PKEY_ASN1_METHOD hmac_asn1_meth; diff --git a/crypto/include/internal/evp_int.h b/crypto/include/internal/evp_int.h index 691b28b3b4..daf2e459e2 100644 --- a/crypto/include/internal/evp_int.h +++ b/crypto/include/internal/evp_int.h @@ -90,6 +90,7 @@ extern const EVP_PKEY_METHOD dh_pkey_meth; extern const EVP_PKEY_METHOD dhx_pkey_meth; extern const EVP_PKEY_METHOD dsa_pkey_meth; extern const EVP_PKEY_METHOD ec_pkey_meth; +extern const EVP_PKEY_METHOD sm2_pkey_meth; extern const EVP_PKEY_METHOD ecx25519_pkey_meth; extern const EVP_PKEY_METHOD ecx448_pkey_meth; extern const EVP_PKEY_METHOD ed25519_pkey_meth; diff --git a/crypto/include/internal/sm2.h b/crypto/include/internal/sm2.h index e0e2d756d5..613fa34022 100644 --- a/crypto/include/internal/sm2.h +++ b/crypto/include/internal/sm2.h @@ -42,15 +42,15 @@ int sm2_do_verify(const EC_KEY *key, const char *user_id, const uint8_t *msg, size_t msg_len); /* - * SM2 signature generation. Assumes input is an SM3 digest + * SM2 signature generation. */ -int sm2_sign(int type, const unsigned char *dgst, int dgstlen, +int sm2_sign(const unsigned char *dgst, int dgstlen, unsigned char *sig, unsigned int *siglen, EC_KEY *eckey); /* - * SM2 signature verification. Assumes input is an SM3 digest + * SM2 signature verification. */ -int sm2_verify(int type, const unsigned char *dgst, int dgstlen, +int sm2_verify(const unsigned char *dgst, int dgstlen, const unsigned char *sig, int siglen, EC_KEY *eckey); diff --git a/crypto/include/internal/sm2err.h b/crypto/include/internal/sm2err.h index f2d60e1744..9a7e2b6275 100644 --- a/crypto/include/internal/sm2err.h +++ b/crypto/include/internal/sm2err.h @@ -23,6 +23,10 @@ int ERR_load_SM2_strings(void); /* * SM2 function codes. */ +# define SM2_F_PKEY_SM2_CTRL 109 +# define SM2_F_PKEY_SM2_CTRL_STR 110 +# define SM2_F_PKEY_SM2_INIT 111 +# define SM2_F_PKEY_SM2_SIGN 112 # define SM2_F_SM2_COMPUTE_MSG_HASH 100 # define SM2_F_SM2_COMPUTE_USERID_DIGEST 101 # define SM2_F_SM2_DECRYPT 102 @@ -38,10 +42,13 @@ int ERR_load_SM2_strings(void); */ # define SM2_R_ASN1_ERROR 100 # define SM2_R_BAD_SIGNATURE 101 +# define SM2_R_BUFFER_TOO_SMALL 107 +# define SM2_R_INVALID_CURVE 108 # define SM2_R_INVALID_DIGEST 102 # define SM2_R_INVALID_DIGEST_TYPE 103 # define SM2_R_INVALID_ENCODING 104 # define SM2_R_INVALID_FIELD 105 +# define SM2_R_NO_PARAMETERS_SET 109 # define SM2_R_USER_ID_TOO_LARGE 106 # endif diff --git a/crypto/sm2/build.info b/crypto/sm2/build.info index fbf8dba10f..c1e84f4800 100644 --- a/crypto/sm2/build.info +++ b/crypto/sm2/build.info @@ -1,6 +1,5 @@ LIBS=../../libcrypto SOURCE[../../libcrypto]=\ - sm2_za.c sm2_sign.c sm2_crypt.c sm2_err.c - + sm2_za.c sm2_sign.c sm2_crypt.c sm2_err.c sm2_pmeth.c diff --git a/crypto/sm2/sm2_err.c b/crypto/sm2/sm2_err.c index e36975f4da..035abdc49e 100644 --- a/crypto/sm2/sm2_err.c +++ b/crypto/sm2/sm2_err.c @@ -14,6 +14,10 @@ #ifndef OPENSSL_NO_ERR static const ERR_STRING_DATA SM2_str_functs[] = { + {ERR_PACK(ERR_LIB_SM2, SM2_F_PKEY_SM2_CTRL, 0), "pkey_sm2_ctrl"}, + {ERR_PACK(ERR_LIB_SM2, SM2_F_PKEY_SM2_CTRL_STR, 0), "pkey_sm2_ctrl_str"}, + {ERR_PACK(ERR_LIB_SM2, SM2_F_PKEY_SM2_INIT, 0), "pkey_sm2_init"}, + {ERR_PACK(ERR_LIB_SM2, SM2_F_PKEY_SM2_SIGN, 0), "pkey_sm2_sign"}, {ERR_PACK(ERR_LIB_SM2, SM2_F_SM2_COMPUTE_MSG_HASH, 0), "sm2_compute_msg_hash"}, {ERR_PACK(ERR_LIB_SM2, SM2_F_SM2_COMPUTE_USERID_DIGEST, 0), @@ -31,11 +35,14 @@ static const ERR_STRING_DATA SM2_str_functs[] = { static const ERR_STRING_DATA SM2_str_reasons[] = { {ERR_PACK(ERR_LIB_SM2, 0, SM2_R_ASN1_ERROR), "asn1 error"}, {ERR_PACK(ERR_LIB_SM2, 0, SM2_R_BAD_SIGNATURE), "bad signature"}, + {ERR_PACK(ERR_LIB_SM2, 0, SM2_R_BUFFER_TOO_SMALL), "buffer too small"}, + {ERR_PACK(ERR_LIB_SM2, 0, SM2_R_INVALID_CURVE), "invalid curve"}, {ERR_PACK(ERR_LIB_SM2, 0, SM2_R_INVALID_DIGEST), "invalid digest"}, {ERR_PACK(ERR_LIB_SM2, 0, SM2_R_INVALID_DIGEST_TYPE), "invalid digest type"}, {ERR_PACK(ERR_LIB_SM2, 0, SM2_R_INVALID_ENCODING), "invalid encoding"}, {ERR_PACK(ERR_LIB_SM2, 0, SM2_R_INVALID_FIELD), "invalid field"}, + {ERR_PACK(ERR_LIB_SM2, 0, SM2_R_NO_PARAMETERS_SET), "no parameters set"}, {ERR_PACK(ERR_LIB_SM2, 0, SM2_R_USER_ID_TOO_LARGE), "user id too large"}, {0, NULL} }; diff --git a/crypto/sm2/sm2_pmeth.c b/crypto/sm2/sm2_pmeth.c new file mode 100644 index 0000000000..b027131889 --- /dev/null +++ b/crypto/sm2/sm2_pmeth.c @@ -0,0 +1,245 @@ +/* + * Copyright 2006-2018 The OpenSSL Project Authors. All Rights Reserved. + * + * Licensed under the OpenSSL license (the "License"). You may not use + * this file except in compliance with the License. You can obtain a copy + * in the file LICENSE in the source distribution or at + * https://www.openssl.org/source/license.html + */ + +#include "internal/cryptlib.h" +#include +#include +#include +#include "internal/evp_int.h" +#include "internal/sm2.h" +#include "internal/sm2err.h" + +/* EC pkey context structure */ + +typedef struct { + /* Key and paramgen group */ + EC_GROUP *gen_group; + /* message digest */ + const EVP_MD *md; +} SM2_PKEY_CTX; + +static int pkey_sm2_init(EVP_PKEY_CTX *ctx) +{ + SM2_PKEY_CTX *dctx; + + if ((dctx = OPENSSL_zalloc(sizeof(*dctx))) == NULL) { + SM2err(SM2_F_PKEY_SM2_INIT, ERR_R_MALLOC_FAILURE); + return 0; + } + + ctx->data = dctx; + return 1; +} + +static void pkey_sm2_cleanup(EVP_PKEY_CTX *ctx) +{ + SM2_PKEY_CTX *dctx = ctx->data; + + if (dctx != NULL) { + EC_GROUP_free(dctx->gen_group); + OPENSSL_free(dctx); + ctx->data = NULL; + } +} + +static int pkey_sm2_copy(EVP_PKEY_CTX *dst, EVP_PKEY_CTX *src) +{ + SM2_PKEY_CTX *dctx, *sctx; + + if (!pkey_sm2_init(dst)) + return 0; + sctx = src->data; + dctx = dst->data; + if (sctx->gen_group != NULL) { + dctx->gen_group = EC_GROUP_dup(sctx->gen_group); + if (dctx->gen_group == NULL) { + pkey_sm2_cleanup(dst); + return 0; + } + } + dctx->md = sctx->md; + + return 1; +} + +static int pkey_sm2_sign(EVP_PKEY_CTX *ctx, unsigned char *sig, size_t *siglen, + const unsigned char *tbs, size_t tbslen) +{ + int ret; + unsigned int sltmp; + EC_KEY *ec = ctx->pkey->pkey.ec; + const int sig_sz = ECDSA_size(ctx->pkey->pkey.ec); + + if (sig_sz <= 0) { + return 0; + } + + if (sig == NULL) { + *siglen = (size_t)sig_sz; + return 1; + } + + if (*siglen < (size_t)sig_sz) { + SM2err(SM2_F_PKEY_SM2_SIGN, SM2_R_BUFFER_TOO_SMALL); + return 0; + } + + ret = sm2_sign(tbs, tbslen, sig, &sltmp, ec); + + if (ret <= 0) + return ret; + *siglen = (size_t)sltmp; + return 1; +} + +static int pkey_sm2_verify(EVP_PKEY_CTX *ctx, + const unsigned char *sig, size_t siglen, + const unsigned char *tbs, size_t tbslen) +{ + EC_KEY *ec = ctx->pkey->pkey.ec; + + return sm2_verify(tbs, tbslen, sig, siglen, ec); +} + +static int pkey_sm2_encrypt(EVP_PKEY_CTX *ctx, + unsigned char *out, size_t *outlen, + const unsigned char *in, size_t inlen) +{ + EC_KEY *ec = ctx->pkey->pkey.ec; + SM2_PKEY_CTX *dctx = ctx->data; + const EVP_MD *md = (dctx->md == NULL) ? EVP_sm3() : dctx->md; + + if (out == NULL) { + if (!sm2_ciphertext_size(ec, md, inlen, outlen)) + return -1; + else + return 1; + } + + return sm2_encrypt(ec, md, in, inlen, out, outlen); +} + +static int pkey_sm2_decrypt(EVP_PKEY_CTX *ctx, + unsigned char *out, size_t *outlen, + const unsigned char *in, size_t inlen) +{ + EC_KEY *ec = ctx->pkey->pkey.ec; + SM2_PKEY_CTX *dctx = ctx->data; + const EVP_MD *md = (dctx->md == NULL) ? EVP_sm3() : dctx->md; + + if (out == NULL) { + if (!sm2_plaintext_size(ec, md, inlen, outlen)) + return -1; + else + return 1; + } + + return sm2_decrypt(ec, md, in, inlen, out, outlen); +} + +static int pkey_sm2_ctrl(EVP_PKEY_CTX *ctx, int type, int p1, void *p2) +{ + SM2_PKEY_CTX *dctx = ctx->data; + EC_GROUP *group; + + switch (type) { + case EVP_PKEY_CTRL_EC_PARAMGEN_CURVE_NID: + group = EC_GROUP_new_by_curve_name(p1); + if (group == NULL) { + SM2err(SM2_F_PKEY_SM2_CTRL, SM2_R_INVALID_CURVE); + return 0; + } + EC_GROUP_free(dctx->gen_group); + dctx->gen_group = group; + return 1; + + case EVP_PKEY_CTRL_EC_PARAM_ENC: + if (dctx->gen_group == NULL) { + SM2err(SM2_F_PKEY_SM2_CTRL, SM2_R_NO_PARAMETERS_SET); + return 0; + } + EC_GROUP_set_asn1_flag(dctx->gen_group, p1); + return 1; + + case EVP_PKEY_CTRL_MD: + dctx->md = p2; + return 1; + + case EVP_PKEY_CTRL_GET_MD: + *(const EVP_MD **)p2 = dctx->md; + return 1; + + default: + return -2; + + } +} + +static int pkey_sm2_ctrl_str(EVP_PKEY_CTX *ctx, + const char *type, const char *value) +{ + if (strcmp(type, "ec_paramgen_curve") == 0) { + int nid = NID_undef; + + if (((nid = EC_curve_nist2nid(value)) == NID_undef) + && ((nid = OBJ_sn2nid(value)) == NID_undef) + && ((nid = OBJ_ln2nid(value)) == NID_undef)) { + SM2err(SM2_F_PKEY_SM2_CTRL_STR, SM2_R_INVALID_CURVE); + return 0; + } + return EVP_PKEY_CTX_set_ec_paramgen_curve_nid(ctx, nid); + } else if (strcmp(type, "ec_param_enc") == 0) { + int param_enc; + + if (strcmp(value, "explicit") == 0) + param_enc = 0; + else if (strcmp(value, "named_curve") == 0) + param_enc = OPENSSL_EC_NAMED_CURVE; + else + return -2; + return EVP_PKEY_CTX_set_ec_param_enc(ctx, param_enc); + } + + return -2; +} + +const EVP_PKEY_METHOD sm2_pkey_meth = { + EVP_PKEY_SM2, + 0, + pkey_sm2_init, + pkey_sm2_copy, + pkey_sm2_cleanup, + + 0, + 0, + + 0, + 0, + + 0, + pkey_sm2_sign, + + 0, + pkey_sm2_verify, + + 0, 0, + + 0, 0, 0, 0, + + 0, + pkey_sm2_encrypt, + + 0, + pkey_sm2_decrypt, + + 0, + 0, + pkey_sm2_ctrl, + pkey_sm2_ctrl_str +}; diff --git a/crypto/sm2/sm2_sign.c b/crypto/sm2/sm2_sign.c index 4ca0ca8006..9d1905439a 100644 --- a/crypto/sm2/sm2_sign.c +++ b/crypto/sm2/sm2_sign.c @@ -282,7 +282,7 @@ int sm2_do_verify(const EC_KEY *key, return ret; } -int sm2_sign(int type, const unsigned char *dgst, int dgstlen, +int sm2_sign(const unsigned char *dgst, int dgstlen, unsigned char *sig, unsigned int *siglen, EC_KEY *eckey) { BIGNUM *e = NULL; @@ -290,11 +290,6 @@ int sm2_sign(int type, const unsigned char *dgst, int dgstlen, int sigleni; int ret = -1; - if (type != NID_sm3 || dgstlen != 32) { - SM2err(SM2_F_SM2_SIGN, SM2_R_INVALID_DIGEST_TYPE); - goto done; - } - e = BN_bin2bn(dgst, dgstlen, NULL); if (e == NULL) { SM2err(SM2_F_SM2_SIGN, ERR_R_BN_LIB); @@ -318,7 +313,7 @@ int sm2_sign(int type, const unsigned char *dgst, int dgstlen, return ret; } -int sm2_verify(int type, const unsigned char *dgst, int dgstlen, +int sm2_verify(const unsigned char *dgst, int dgstlen, const unsigned char *sig, int sig_len, EC_KEY *eckey) { ECDSA_SIG *s = NULL; @@ -328,11 +323,6 @@ int sm2_verify(int type, const unsigned char *dgst, int dgstlen, int derlen = -1; int ret = -1; - if (type != NID_sm3) { - SM2err(SM2_F_SM2_VERIFY, SM2_R_INVALID_DIGEST_TYPE); - goto done; - } - s = ECDSA_SIG_new(); if (s == NULL) { SM2err(SM2_F_SM2_VERIFY, ERR_R_MALLOC_FAILURE); diff --git a/include/openssl/ecerr.h b/include/openssl/ecerr.h index fd5ce84ce7..603efccaa3 100644 --- a/include/openssl/ecerr.h +++ b/include/openssl/ecerr.h @@ -182,6 +182,12 @@ int ERR_load_EC_strings(void); # define EC_F_PKEY_EC_KEYGEN 199 # define EC_F_PKEY_EC_PARAMGEN 219 # define EC_F_PKEY_EC_SIGN 218 +# define EC_F_PKEY_SM2_CTRL 284 +# define EC_F_PKEY_SM2_CTRL_STR 285 +# define EC_F_PKEY_SM2_INIT 287 +# define EC_F_PKEY_SM2_KEYGEN 288 +# define EC_F_PKEY_SM2_PARAMGEN 289 +# define EC_F_PKEY_SM2_SIGN 290 # define EC_F_VALIDATE_ECX_DERIVE 278 /* diff --git a/test/evp_extra_test.c b/test/evp_extra_test.c index 640da7c765..deb8cfd95d 100644 --- a/test/evp_extra_test.c +++ b/test/evp_extra_test.c @@ -477,6 +477,127 @@ static int test_EVP_PKCS82PKEY(void) } #endif +#ifndef OPENSSL_NO_SM2 + +static int test_EVP_SM2(void) +{ + int ret = 0; + EVP_PKEY *pkey = NULL; + EVP_PKEY *params = NULL; + EVP_PKEY_CTX *pctx = NULL; + EVP_PKEY_CTX *kctx = NULL; + size_t sig_len = 0; + unsigned char *sig = NULL; + EVP_MD_CTX *md_ctx = NULL; + EVP_MD_CTX *md_ctx_verify = NULL; + EVP_PKEY_CTX *cctx = NULL; + + uint8_t ciphertext[128]; + size_t ctext_len = sizeof(ciphertext); + + uint8_t plaintext[8]; + size_t ptext_len = sizeof(plaintext); + + pctx = EVP_PKEY_CTX_new_id(EVP_PKEY_EC, NULL); + if (!TEST_ptr(pctx)) + goto done; + + if (!TEST_true(EVP_PKEY_paramgen_init(pctx) == 1)) + goto done; + + if (!TEST_true(EVP_PKEY_CTX_set_ec_paramgen_curve_nid(pctx, NID_sm2))) + goto done; + + if (!TEST_true(EVP_PKEY_paramgen(pctx, ¶ms))) + goto done; + + kctx = EVP_PKEY_CTX_new(params, NULL); + if (!TEST_ptr(kctx)) + goto done; + + if (!TEST_true(EVP_PKEY_keygen_init(kctx))) + goto done; + + if (!TEST_true(EVP_PKEY_keygen(kctx, &pkey))) + goto done; + + if (!TEST_true(EVP_PKEY_set_alias_type(pkey, EVP_PKEY_SM2))) + goto done; + + if (!TEST_ptr(md_ctx = EVP_MD_CTX_new())) + goto done; + + if (!TEST_ptr(md_ctx_verify = EVP_MD_CTX_new())) + goto done; + + if (!TEST_true(EVP_DigestSignInit(md_ctx, NULL, EVP_sm3(), NULL, pkey))) + goto done; + + if(!TEST_true(EVP_DigestSignUpdate(md_ctx, kMsg, sizeof(kMsg)))) + goto done; + + /* Determine the size of the signature. */ + if (!TEST_true(EVP_DigestSignFinal(md_ctx, NULL, &sig_len))) + goto done; + + if (!TEST_size_t_eq(sig_len, (size_t)EVP_PKEY_size(pkey))) + goto done; + + if (!TEST_ptr(sig = OPENSSL_malloc(sig_len))) + goto done; + + if (!TEST_true(EVP_DigestSignFinal(md_ctx, sig, &sig_len))) + goto done; + + /* Ensure that the signature round-trips. */ + + if (!TEST_true(EVP_DigestVerifyInit(md_ctx_verify, NULL, EVP_sm3(), NULL, pkey))) + goto done; + + if (!TEST_true(EVP_DigestVerifyUpdate(md_ctx_verify, kMsg, sizeof(kMsg)))) + goto done; + + if (!TEST_true(EVP_DigestVerifyFinal(md_ctx_verify, sig, sig_len))) + goto done; + + /* now check encryption/decryption */ + + if (!TEST_ptr(cctx = EVP_PKEY_CTX_new(pkey, NULL))) + goto done; + + if (!TEST_true(EVP_PKEY_encrypt_init(cctx))) + goto done; + + if (!TEST_true(EVP_PKEY_encrypt(cctx, ciphertext, &ctext_len, kMsg, sizeof(kMsg)))) + goto done; + + if (!TEST_true(EVP_PKEY_decrypt_init(cctx))) + goto done; + + if (!TEST_true(EVP_PKEY_decrypt(cctx, plaintext, &ptext_len, ciphertext, ctext_len))) + goto done; + + if (!TEST_true(ptext_len == sizeof(kMsg))) + goto done; + + if (!TEST_true(memcmp(plaintext, kMsg, sizeof(kMsg)) == 0)) + goto done; + + ret = 1; +done: + EVP_PKEY_CTX_free(pctx); + EVP_PKEY_CTX_free(kctx); + EVP_PKEY_CTX_free(cctx); + EVP_PKEY_free(pkey); + EVP_PKEY_free(params); + EVP_MD_CTX_free(md_ctx); + EVP_MD_CTX_free(md_ctx_verify); + OPENSSL_free(sig); + return ret; +} + +#endif + static struct keys_st { int type; char *priv; @@ -663,6 +784,9 @@ int setup_tests(void) ADD_ALL_TESTS(test_d2i_AutoPrivateKey, OSSL_NELEM(keydata)); #ifndef OPENSSL_NO_EC ADD_TEST(test_EVP_PKCS82PKEY); +#endif +#ifndef OPENSSL_NO_SM2 + ADD_TEST(test_EVP_SM2); #endif ADD_ALL_TESTS(test_set_get_raw_keys, OSSL_NELEM(keys)); custom_pmeth = EVP_PKEY_meth_new(0xdefaced, 0); diff --git a/test/evp_test.c b/test/evp_test.c index e2274d9632..97239f2260 100644 --- a/test/evp_test.c +++ b/test/evp_test.c @@ -2530,6 +2530,11 @@ top: if (!TEST_ptr(key = OPENSSL_malloc(sizeof(*key)))) return 0; key->name = take_value(pp); + + /* Hack to detect SM2 keys */ + if(strstr(key->name, "SM2")) + EVP_PKEY_set_alias_type(pkey, EVP_PKEY_SM2); + key->key = pkey; key->next = *klist; *klist = key; diff --git a/test/recipes/30-test_evp_data/evppkey.txt b/test/recipes/30-test_evp_data/evppkey.txt index 6b5045252e..e191b6f933 100644 --- a/test/recipes/30-test_evp_data/evppkey.txt +++ b/test/recipes/30-test_evp_data/evppkey.txt @@ -18384,6 +18384,16 @@ Ctrl = digest:SM3 Input = D7AD397F6FFA5D4F7F11E7217F241607DC30618C236D2C09C1B9EA8FDADEE2E8 Output = 3046022100AB1DB64DE7C40EDBDE6651C9B8EBDB804673DB836E5D5C7FE15DCF9ED2725037022100EBA714451FF69B0BB930B379E192E7CD5FA6E3C41C7FBD8303B799AB54A54621 +Verify = SM2_key1 +Ctrl = digest:SM3 +Input = B1139602C6ECC9E15E2F3F9C635A1AFE737058BC15387479C1EA0D0B3D90E9E5 +Output = 3045022100E6E0414EBD3A656C35602AF14AB20287DBF30D57AF75C49A188ED4B42391F22402202F54F277C606F4605E1CE9514947FFDDF94C67A539804A4ED17F852288BDBE2E + +Verify = SM2_key1 +Ctrl = digest:SHA512 +Input = 40AA1B203C9D8EE150B21C3C7CDA8261492E5420C5F2B9F7380700E094C303B48E62F319C1DA0E32EB40D113C5F1749CC61AEB499167890AB82F2CC9BB706971 +Output = 3046022100AE018933B9BA041784380069F2DDF609694DCD299FDBF23D09F4B711FBC103EC0221008440BB1A48C132DE4FB91BE9F43B958142FDD29FB9DABE01B17514023A2F638C + Decrypt = SM2_key1 Input = 30818A0220466BE2EF5C11782EC77864A0055417F407A5AFC11D653C6BCE69E417BB1D05B6022062B572E21FF0DDF5C726BD3F9FF2EAE56E6294713A607E9B9525628965F62CC804203C1B5713B5DB2728EB7BF775E44F4689FC32668BDC564F52EA45B09E8DF2A5F40422084A9D0CC2997092B7D3C404FCE95956EB604D732B2307A8E5B8900ED6608CA5B197 Output = "The floofy bunnies hop at midnight"