Add SM2 signature algorithm to default provider

Reviewed-by: Richard Levitte <levitte@openssl.org>
Reviewed-by: Matt Caswell <matt@openssl.org>
(Merged from https://github.com/openssl/openssl/pull/12536)
This commit is contained in:
Paul Yang 2020-03-04 23:49:43 +08:00 committed by Matt Caswell
parent 7ee511d093
commit d0b79f8631
21 changed files with 799 additions and 175 deletions

View File

@ -1231,6 +1231,8 @@ SM2_F_SM2_COMPUTE_USERID_DIGEST:101:sm2_compute_userid_digest
SM2_F_SM2_COMPUTE_Z_DIGEST:113:sm2_compute_z_digest
SM2_F_SM2_DECRYPT:102:sm2_decrypt
SM2_F_SM2_ENCRYPT:103:sm2_encrypt
SM2_F_SM2_INTERNAL_SIGN:116:
SM2_F_SM2_INTERNAL_VERIFY:117:
SM2_F_SM2_PLAINTEXT_SIZE:104:sm2_plaintext_size
SM2_F_SM2_SIGN:105:sm2_sign
SM2_F_SM2_SIG_GEN:106:sm2_sig_gen

View File

@ -20,12 +20,6 @@
#include "crypto/evp.h"
#include "evp_local.h"
/* TODO(3.0) remove when provider SM2 key generation is implemented */
#ifdef TMP_SM2_HACK
# include <openssl/ec.h>
# include "internal/sizes.h"
#endif
static int gen_init(EVP_PKEY_CTX *ctx, int operation)
{
int ret = 0;
@ -39,12 +33,6 @@ static int gen_init(EVP_PKEY_CTX *ctx, int operation)
if (ctx->keymgmt == NULL || ctx->keymgmt->gen_init == NULL)
goto legacy;
/* TODO remove when provider SM2 key generation is implemented */
#ifdef TMP_SM2_HACK
if (ctx->pmeth != NULL && ctx->pmeth->pkey_id == EVP_PKEY_SM2)
goto legacy;
#endif
switch (operation) {
case EVP_PKEY_OP_PARAMGEN:
ctx->op.keymgmt.genctx =
@ -214,32 +202,6 @@ int EVP_PKEY_gen(EVP_PKEY_CTX *ctx, EVP_PKEY **ppkey)
*/
(*ppkey)->type = ctx->legacy_keytype;
/* TODO remove when SM2 key have been cleanly separated from EC keys */
#ifdef TMP_SM2_HACK
/*
* Legacy SM2 keys are implemented as EC_KEY with a twist. The legacy
* key generation detects the SM2 curve and "magically" changes the pkey
* id accordingly.
* Since we don't have SM2 in the provider implementation, we need to
* downgrade the generated provider side key to a legacy one under the
* same conditions.
*
* THIS IS AN UGLY BUT TEMPORARY HACK
*/
{
char curve_name[OSSL_MAX_NAME_SIZE] = "";
if (!EVP_PKEY_get_utf8_string_param(*ppkey, OSSL_PKEY_PARAM_GROUP_NAME,
curve_name, sizeof(curve_name),
NULL)
|| strcmp(curve_name, "SM2") != 0)
goto end;
}
if (!evp_pkey_downgrade(*ppkey)
|| !EVP_PKEY_set_alias_type(*ppkey, EVP_PKEY_SM2))
ret = 0;
#endif
goto end;
legacy:

View File

@ -175,28 +175,6 @@ static int get_legacy_alg_type_from_keymgmt(const EVP_KEYMGMT *keymgmt)
}
#endif /* FIPS_MODULE */
static int is_legacy_alg(int id, const char *keytype)
{
#ifndef FIPS_MODULE
/* Certain EVP_PKEY keytypes are only available in legacy form */
if (id == -1)
id = evp_pkey_name2type(keytype);
switch (id) {
/*
* TODO(3.0): Remove SM2 when they are converted to have provider
* support
*/
case EVP_PKEY_SM2:
return 1;
default:
return 0;
}
#else
return 0;
#endif
}
static EVP_PKEY_CTX *int_ctx_new(OPENSSL_CTX *libctx,
EVP_PKEY *pkey, ENGINE *e,
const char *keytype, const char *propquery,
@ -284,16 +262,8 @@ static EVP_PKEY_CTX *int_ctx_new(OPENSSL_CTX *libctx,
* implementation.
*/
if (e == NULL && keytype != NULL) {
int legacy = is_legacy_alg(id, keytype);
/* This could fail so ignore errors */
if (legacy)
ERR_set_mark();
keymgmt = EVP_KEYMGMT_fetch(libctx, keytype, propquery);
if (legacy)
ERR_pop_to_mark();
else if (keymgmt == NULL)
if (keymgmt == NULL)
return NULL; /* EVP_KEYMGMT_fetch() recorded an error */
#ifndef FIPS_MODULE

View File

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

View File

@ -104,7 +104,7 @@ static int pkey_sm2_sign(EVP_PKEY_CTX *ctx, unsigned char *sig, size_t *siglen,
return 0;
}
ret = sm2_sign(tbs, tbslen, sig, &sltmp, ec);
ret = sm2_internal_sign(tbs, tbslen, sig, &sltmp, ec);
if (ret <= 0)
return ret;
@ -118,7 +118,7 @@ static int pkey_sm2_verify(EVP_PKEY_CTX *ctx,
{
EC_KEY *ec = ctx->pkey->pkey.ec;
return sm2_verify(tbs, tbslen, sig, siglen, ec);
return sm2_internal_verify(tbs, tbslen, sig, siglen, ec);
}
static int pkey_sm2_encrypt(EVP_PKEY_CTX *ctx,

View File

@ -418,8 +418,8 @@ int sm2_do_verify(const EC_KEY *key,
return ret;
}
int sm2_sign(const unsigned char *dgst, int dgstlen,
unsigned char *sig, unsigned int *siglen, EC_KEY *eckey)
int sm2_internal_sign(const unsigned char *dgst, int dgstlen,
unsigned char *sig, unsigned int *siglen, EC_KEY *eckey)
{
BIGNUM *e = NULL;
ECDSA_SIG *s = NULL;
@ -428,19 +428,19 @@ int sm2_sign(const unsigned char *dgst, int dgstlen,
e = BN_bin2bn(dgst, dgstlen, NULL);
if (e == NULL) {
SM2err(SM2_F_SM2_SIGN, ERR_R_BN_LIB);
SM2err(SM2_F_SM2_INTERNAL_SIGN, ERR_R_BN_LIB);
goto done;
}
s = sm2_sig_gen(eckey, e);
if (s == NULL) {
SM2err(SM2_F_SM2_SIGN, ERR_R_INTERNAL_ERROR);
SM2err(SM2_F_SM2_INTERNAL_SIGN, ERR_R_INTERNAL_ERROR);
goto done;
}
sigleni = i2d_ECDSA_SIG(s, &sig);
if (sigleni < 0) {
SM2err(SM2_F_SM2_SIGN, ERR_R_INTERNAL_ERROR);
SM2err(SM2_F_SM2_INTERNAL_SIGN, ERR_R_INTERNAL_ERROR);
goto done;
}
*siglen = (unsigned int)sigleni;
@ -453,8 +453,8 @@ int sm2_sign(const unsigned char *dgst, int dgstlen,
return ret;
}
int sm2_verify(const unsigned char *dgst, int dgstlen,
const unsigned char *sig, int sig_len, EC_KEY *eckey)
int sm2_internal_verify(const unsigned char *dgst, int dgstlen,
const unsigned char *sig, int sig_len, EC_KEY *eckey)
{
ECDSA_SIG *s = NULL;
BIGNUM *e = NULL;
@ -465,23 +465,23 @@ int sm2_verify(const unsigned char *dgst, int dgstlen,
s = ECDSA_SIG_new();
if (s == NULL) {
SM2err(SM2_F_SM2_VERIFY, ERR_R_MALLOC_FAILURE);
SM2err(SM2_F_SM2_INTERNAL_VERIFY, ERR_R_MALLOC_FAILURE);
goto done;
}
if (d2i_ECDSA_SIG(&s, &p, sig_len) == NULL) {
SM2err(SM2_F_SM2_VERIFY, SM2_R_INVALID_ENCODING);
SM2err(SM2_F_SM2_INTERNAL_VERIFY, SM2_R_INVALID_ENCODING);
goto done;
}
/* Ensure signature uses DER and doesn't have trailing garbage */
derlen = i2d_ECDSA_SIG(s, &der);
if (derlen != sig_len || memcmp(sig, der, derlen) != 0) {
SM2err(SM2_F_SM2_VERIFY, SM2_R_INVALID_ENCODING);
SM2err(SM2_F_SM2_INTERNAL_VERIFY, SM2_R_INVALID_ENCODING);
goto done;
}
e = BN_bin2bn(dgst, dgstlen, NULL);
if (e == NULL) {
SM2err(SM2_F_SM2_VERIFY, ERR_R_BN_LIB);
SM2err(SM2_F_SM2_INTERNAL_VERIFY, ERR_R_BN_LIB);
goto done;
}

View File

@ -45,14 +45,14 @@ int sm2_do_verify(const EC_KEY *key,
/*
* SM2 signature generation.
*/
int sm2_sign(const unsigned char *dgst, int dgstlen,
unsigned char *sig, unsigned int *siglen, EC_KEY *eckey);
int sm2_internal_sign(const unsigned char *dgst, int dgstlen,
unsigned char *sig, unsigned int *siglen, EC_KEY *eckey);
/*
* SM2 signature verification.
*/
int sm2_verify(const unsigned char *dgst, int dgstlen,
const unsigned char *sig, int siglen, EC_KEY *eckey);
int sm2_internal_verify(const unsigned char *dgst, int dgstlen,
const unsigned char *sig, int siglen, EC_KEY *eckey);
/*
* SM2 encryption
@ -74,5 +74,6 @@ int sm2_decrypt(const EC_KEY *key,
const uint8_t *ciphertext,
size_t ciphertext_len, uint8_t *ptext_buf, size_t *ptext_len);
const unsigned char *sm2_algorithmidentifier_encoding(int md_nid, size_t *len);
# endif /* OPENSSL_NO_SM2 */
#endif

View File

@ -1,6 +1,6 @@
/*
* Generated by util/mkerr.pl DO NOT EDIT
* Copyright 1995-2019 The OpenSSL Project Authors. All Rights Reserved.
* Copyright 1995-2020 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
@ -8,8 +8,8 @@
* https://www.openssl.org/source/license.html
*/
#ifndef OSSL_CRYPTO_SM2ERR_H
# define OSSL_CRYPTO_SM2ERR_H
#ifndef OPENSSL_SM2ERR_H
# define OPENSSL_SM2ERR_H
# include <openssl/opensslconf.h>
# include <openssl/symhacks.h>
@ -39,6 +39,8 @@ int ERR_load_SM2_strings(void);
# define SM2_F_SM2_COMPUTE_Z_DIGEST 0
# define SM2_F_SM2_DECRYPT 0
# define SM2_F_SM2_ENCRYPT 0
# define SM2_F_SM2_INTERNAL_SIGN 0
# define SM2_F_SM2_INTERNAL_VERIFY 0
# define SM2_F_SM2_PLAINTEXT_SIZE 0
# define SM2_F_SM2_SIGN 0
# define SM2_F_SM2_SIG_GEN 0

View File

@ -142,6 +142,7 @@ extern "C" {
#define OSSL_DIGEST_NAME_SHA3_512 "SHA3-512"
#define OSSL_DIGEST_NAME_KECCAK_KMAC128 "KECCAK-KMAC-128"
#define OSSL_DIGEST_NAME_KECCAK_KMAC256 "KECCAK-KMAC-256"
#define OSSL_DIGEST_NAME_SM3 "SM3"
/* MAC parameters */
#define OSSL_MAC_PARAM_KEY "key" /* octet string */

View File

@ -0,0 +1,11 @@
oscca OBJECT IDENTIFIER ::= { iso(1) member-body(2) cn(156) 10197 }
sm-scheme OBJECT IDENTIFIER ::= { oscca 1 }
-- OID for SM2 signatures with SM3
sm2-with-SM3 OBJECT IDENTIFIER ::= { sm-scheme 501 }
-- Named Elliptic Curves of SM2
curveSM2 OBJECT IDENTIFIER ::= { sm-scheme 301 }

View File

@ -74,6 +74,19 @@ DEPEND[${DER_WRAP_GEN/.c/.o}]=$DER_WRAP_H
GENERATE[$DER_WRAP_H]=der_wrap.h.in
DEPEND[$DER_WRAP_H]=oids_to_c.pm
#----- SM2
$DER_SM2_H=../include/prov/der_sm2.h
$DER_SM2_GEN=der_sm2_gen.c
$DER_SM2_AUX=der_sm2_key.c der_sm2_sig.c
GENERATE[$DER_SM2_GEN]=der_sm2_gen.c.in
DEPEND[$DER_SM2_GEN]=oids_to_c.pm
DEPEND[${DER_SM2_AUX/.c/.o}]=$DER_SM2_H $DER_EC_H
DEPEND[${DER_SM2_GEN/.c/.o}]=$DER_SM2_H
GENERATE[$DER_SM2_H]=der_sm2.h.in
DEPEND[$DER_SM2_H]=oids_to_c.pm
#----- Conclusion
# TODO(3.0) $COMMON should go to libcommon.a, but this currently leads
@ -84,7 +97,8 @@ $COMMON=\
$DER_DSA_GEN $DER_DSA_AUX \
$DER_EC_GEN $DER_EC_AUX \
$DER_DIGESTS_GEN \
$DER_WRAP_GEN
$DER_WRAP_GEN \
$DER_SM2_GEN $DER_SM2_AUX
IF[{- !$disabled{ec} -}]
$COMMON = $COMMON $DER_ECX_GEN $DER_ECX_AUX

View File

@ -0,0 +1,23 @@
/*
* Copyright 2020 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
* in the file LICENSE in the source distribution or at
* https://www.openssl.org/source/license.html
*/
#include "internal/der.h"
/* Well known OIDs precompiled */
{-
$OUT = oids_to_c::process_leaves('providers/common/der/SM2.asn1',
{ dir => $config{sourcedir},
filter => \&oids_to_c::filter_to_H });
-}
/* Subject Public Key Info */
int DER_w_algorithmIdentifier_SM2(WPACKET *pkt, int cont, EC_KEY *ec);
/* Signature */
int DER_w_algorithmIdentifier_SM2_with_MD(WPACKET *pkt, int cont,
EC_KEY *ec, int mdnid);

View File

@ -0,0 +1,17 @@
/*
* Copyright 2020 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
* in the file LICENSE in the source distribution or at
* https://www.openssl.org/source/license.html
*/
#include "prov/der_sm2.h"
/* Well known OIDs precompiled */
{-
$OUT = oids_to_c::process_leaves('providers/common/der/SM2.asn1',
{ dir => $config{sourcedir},
filter => \&oids_to_c::filter_to_C });
-}

View File

@ -0,0 +1,23 @@
/*
* Copyright 2020 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
* in the file LICENSE in the source distribution or at
* https://www.openssl.org/source/license.html
*/
#include <openssl/obj_mac.h>
#include "internal/packet.h"
#include "prov/der_ec.h"
#include "prov/der_sm2.h"
int DER_w_algorithmIdentifier_SM2(WPACKET *pkt, int cont, EC_KEY *ec)
{
return DER_w_begin_sequence(pkt, cont)
/* No parameters (yet?) */
/* It seems SM2 identifier is the same to id_ecPublidKey */
&& DER_w_precompiled(pkt, -1, der_oid_id_ecPublicKey,
sizeof(der_oid_id_ecPublicKey))
&& DER_w_end_sequence(pkt, cont);
}

View File

@ -0,0 +1,39 @@
/*
* Copyright 2020 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
* in the file LICENSE in the source distribution or at
* https://www.openssl.org/source/license.html
*/
#include <openssl/obj_mac.h>
#include "internal/packet.h"
#include "prov/der_sm2.h"
/* Aliases so we can have a uniform MD_CASE */
#define der_oid_id_sm2_with_sm3 der_oid_sm2_with_SM3
#define MD_CASE(name) \
case NID_##name: \
precompiled = der_oid_id_sm2_with_##name; \
precompiled_sz = sizeof(der_oid_id_sm2_with_##name); \
break;
int DER_w_algorithmIdentifier_SM2_with_MD(WPACKET *pkt, int cont,
EC_KEY *ec, int mdnid)
{
const unsigned char *precompiled = NULL;
size_t precompiled_sz = 0;
switch (mdnid) {
MD_CASE(sm3);
default:
return 0;
}
return DER_w_begin_sequence(pkt, cont)
/* No parameters (yet?) */
&& DER_w_precompiled(pkt, -1, precompiled, precompiled_sz)
&& DER_w_end_sequence(pkt, cont);
}

View File

@ -364,6 +364,9 @@ static const OSSL_ALGORITHM deflt_signature[] = {
{ "ED25519:Ed25519", "provider=default", ed25519_signature_functions },
{ "ED448:Ed448", "provider=default", ed448_signature_functions },
{ "ECDSA", "provider=default", ecdsa_signature_functions },
# ifndef OPENSSL_NO_SM2
{ "SM2", "provider=default", sm2_signature_functions },
# endif
#endif
{ "HMAC", "provider=default", mac_legacy_hmac_signature_functions },
{ "SIPHASH", "provider=default", mac_legacy_siphash_signature_functions },
@ -413,6 +416,7 @@ static const OSSL_ALGORITHM deflt_keymgmt[] = {
#endif
#ifndef OPENSSL_NO_CMAC
{ "CMAC", "provider=default", cmac_legacy_keymgmt_functions },
#endif
#ifndef OPENSSL_NO_SM2
{ "SM2", "provider=default", sm2_keymgmt_functions },
#endif

View File

@ -303,6 +303,7 @@ extern const OSSL_DISPATCH mac_legacy_hmac_signature_functions[];
extern const OSSL_DISPATCH mac_legacy_siphash_signature_functions[];
extern const OSSL_DISPATCH mac_legacy_poly1305_signature_functions[];
extern const OSSL_DISPATCH mac_legacy_cmac_signature_functions[];
extern const OSSL_DISPATCH sm2_signature_functions[];
/* Asym Cipher */
extern const OSSL_DISPATCH rsa_asym_cipher_functions[];

View File

@ -337,7 +337,8 @@ static int ec_match(const void *keydata1, const void *keydata2, int selection)
}
static
int ec_import(void *keydata, int selection, const OSSL_PARAM params[])
int common_import(void *keydata, int selection, const OSSL_PARAM params[],
int sm2_curve)
{
EC_KEY *ec = keydata;
const EC_GROUP *ecg = NULL;
@ -368,6 +369,14 @@ int ec_import(void *keydata, int selection, const OSSL_PARAM params[])
if ((selection & OSSL_KEYMGMT_SELECT_DOMAIN_PARAMETERS) != 0)
ok = ok && ec_group_fromdata(ec, params);
/*
* sm2_curve: import the keys or domparams only on SM2 Curve
* !sm2_curve: import the keys or domparams only not on SM2 Curve
*/
if ((ecg = EC_KEY_get0_group(ec)) == NULL
|| (sm2_curve ^ (EC_GROUP_get_curve_name(ecg) == NID_sm2)))
return 0;
if ((selection & OSSL_KEYMGMT_SELECT_KEYPAIR) != 0) {
int include_private =
selection & OSSL_KEYMGMT_SELECT_PRIVATE_KEY ? 1 : 0;
@ -380,58 +389,17 @@ int ec_import(void *keydata, int selection, const OSSL_PARAM params[])
return ok;
}
static
int ec_import(void *keydata, int selection, const OSSL_PARAM params[])
{
return common_import(keydata, selection, params, 0);
}
#ifndef OPENSSL_NO_SM2
static
int sm2_import(void *keydata, int selection, const OSSL_PARAM params[])
{
EC_KEY *ec = keydata;
const EC_GROUP *ecg = NULL;
int ok = 1;
if (ec == NULL)
return 0;
/*
* In this implementation, we can export/import only keydata in the
* following combinations:
* - domain parameters only
* - public key with associated domain parameters (+optional other params)
* - private key with associated public key and domain parameters
* (+optional other params)
*
* This means:
* - domain parameters must always be requested
* - private key must be requested alongside public key
* - other parameters must be requested only alongside a key
*/
if ((selection & OSSL_KEYMGMT_SELECT_DOMAIN_PARAMETERS) == 0)
return 0;
if ((selection & OSSL_KEYMGMT_SELECT_PRIVATE_KEY) != 0
&& (selection & OSSL_KEYMGMT_SELECT_PUBLIC_KEY) == 0)
return 0;
if ((selection & OSSL_KEYMGMT_SELECT_OTHER_PARAMETERS) != 0
&& (selection & OSSL_KEYMGMT_SELECT_KEYPAIR) == 0)
return 0;
if ((selection & OSSL_KEYMGMT_SELECT_DOMAIN_PARAMETERS) != 0)
ok = ok && ec_key_domparams_fromdata(ec, params);
/* import the keys or domparams only on SM2 Curve */
if ((ecg = EC_KEY_get0_group(ec)) == NULL
|| EC_GROUP_get_curve_name(ecg) != NID_sm2) {
return 0;
}
if ((selection & OSSL_KEYMGMT_SELECT_KEYPAIR) != 0) {
int include_private =
selection & OSSL_KEYMGMT_SELECT_PRIVATE_KEY ? 1 : 0;
ok = ok && ec_key_fromdata(ec, params, include_private);
}
if ((selection & OSSL_KEYMGMT_SELECT_OTHER_PARAMETERS) != 0)
ok = ok && ec_key_otherparams_fromdata(ec, params);
return ok;
return common_import(keydata, selection, params, 1);
}
#endif
@ -857,7 +825,7 @@ static const OSSL_PARAM sm2_known_gettable_params[] = {
};
static
const OSSL_PARAM *sm2_gettable_params(void)
const OSSL_PARAM *sm2_gettable_params(ossl_unused void *provctx)
{
return sm2_known_gettable_params;
}
@ -868,7 +836,7 @@ static const OSSL_PARAM sm2_known_settable_params[] = {
};
static
const OSSL_PARAM *sm2_settable_params(void)
const OSSL_PARAM *sm2_settable_params(ossl_unused void *provctx)
{
return sm2_known_settable_params;
}
@ -1184,8 +1152,21 @@ static void *sm2_gen(void *genctx, OSSL_CALLBACK *osslcb, void *cbarg)
|| (ec = EC_KEY_new_with_libctx(gctx->libctx, NULL)) == NULL)
return NULL;
if (gctx->gen_group == NULL) {
if (!ec_gen_set_group_from_params(gctx))
goto err;
} else {
if (gctx->encoding) {
int flags = ec_encoding_name2id(gctx->encoding);
if (flags < 0)
goto err;
EC_GROUP_set_asn1_flag(gctx->gen_group, flags);
}
}
/* We must always assign a group, no matter what */
ret = ec_gen_assign_group(ec, gctx->gen_group);
/* Whether you want it or not, you get a keypair, not just one half */
if ((gctx->selection & OSSL_KEYMGMT_SELECT_KEYPAIR) != 0) {
/*
@ -1198,7 +1179,9 @@ static void *sm2_gen(void *genctx, OSSL_CALLBACK *osslcb, void *cbarg)
if (ret)
return ec;
err:
/* Something went wrong, throw the key away */
EC_KEY_free(ec);
return NULL;
}
#endif

View File

@ -3,6 +3,7 @@
$DSA_GOAL=../../libimplementations.a
$EC_GOAL=../../libimplementations.a
$SM2SIG_GOAL=../../libimplementations.a
IF[{- !$disabled{dsa} -}]
SOURCE[$DSA_GOAL]=dsa.c
@ -12,6 +13,10 @@ IF[{- !$disabled{ec} -}]
SOURCE[$EC_GOAL]=eddsa.c ecdsa.c
ENDIF
IF[{- !$disabled{sm2} -}]
SOURCE[$SM2SIG_GOAL]=sm2sig.c
ENDIF
SOURCE[../../libfips.a]=rsa.c
SOURCE[../../libnonfips.a]=rsa.c
@ -19,6 +24,7 @@ DEPEND[rsa.o]=../../common/include/prov/der_rsa.h
DEPEND[dsa.o]=../../common/include/prov/der_dsa.h
DEPEND[ecdsa.o]=../../common/include/prov/der_ec.h
DEPEND[eddsa.o]=../../common/include/prov/der_ecx.h
DEPEND[sm2sig.o]=../../common/include/prov/der_sm2.h
SOURCE[../../libfips.a]=mac_legacy.c
SOURCE[../../libnonfips.a]=mac_legacy.c

View File

@ -0,0 +1,568 @@
/*
* Copyright 2020 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
* in the file LICENSE in the source distribution or at
* https://www.openssl.org/source/license.html
*/
/*
* ECDSA low level APIs are deprecated for public use, but still ok for
* internal use - SM2 implemetation uses ECDSA_size() function.
*/
#include "internal/deprecated.h"
#include <string.h> /* memcpy */
#include <openssl/crypto.h>
#include <openssl/core_dispatch.h>
#include <openssl/core_names.h>
#include <openssl/dsa.h>
#include <openssl/params.h>
#include <openssl/evp.h>
#include <openssl/err.h>
#include "internal/nelem.h"
#include "internal/sizes.h"
#include "internal/cryptlib.h"
#include "prov/providercommonerr.h"
#include "prov/implementations.h"
#include "prov/provider_ctx.h"
#include "crypto/ec.h"
#include "crypto/sm2.h"
#include "prov/der_sm2.h"
static OSSL_FUNC_signature_newctx_fn sm2sig_newctx;
static OSSL_FUNC_signature_sign_init_fn sm2sig_signature_init;
static OSSL_FUNC_signature_verify_init_fn sm2sig_signature_init;
static OSSL_FUNC_signature_sign_fn sm2sig_sign;
static OSSL_FUNC_signature_verify_fn sm2sig_verify;
static OSSL_FUNC_signature_digest_sign_init_fn sm2sig_digest_signverify_init;
static OSSL_FUNC_signature_digest_sign_update_fn sm2sig_digest_signverify_update;
static OSSL_FUNC_signature_digest_sign_final_fn sm2sig_digest_sign_final;
static OSSL_FUNC_signature_digest_verify_init_fn sm2sig_digest_signverify_init;
static OSSL_FUNC_signature_digest_verify_update_fn sm2sig_digest_signverify_update;
static OSSL_FUNC_signature_digest_verify_final_fn sm2sig_digest_verify_final;
static OSSL_FUNC_signature_freectx_fn sm2sig_freectx;
static OSSL_FUNC_signature_dupctx_fn sm2sig_dupctx;
static OSSL_FUNC_signature_get_ctx_params_fn sm2sig_get_ctx_params;
static OSSL_FUNC_signature_gettable_ctx_params_fn sm2sig_gettable_ctx_params;
static OSSL_FUNC_signature_set_ctx_params_fn sm2sig_set_ctx_params;
static OSSL_FUNC_signature_settable_ctx_params_fn sm2sig_settable_ctx_params;
static OSSL_FUNC_signature_get_ctx_md_params_fn sm2sig_get_ctx_md_params;
static OSSL_FUNC_signature_gettable_ctx_md_params_fn sm2sig_gettable_ctx_md_params;
static OSSL_FUNC_signature_set_ctx_md_params_fn sm2sig_set_ctx_md_params;
static OSSL_FUNC_signature_settable_ctx_md_params_fn sm2sig_settable_ctx_md_params;
/*
* What's passed as an actual key is defined by the KEYMGMT interface.
* We happen to know that our KEYMGMT simply passes EC structures, so
* we use that here too.
*/
typedef struct {
OPENSSL_CTX *libctx;
char *propq;
EC_KEY *ec;
/*
* Flag to determine if the hash function can be changed (1) or not (0)
* Because it's dangerous to change during a DigestSign or DigestVerify
* operation, this flag is cleared by their Init function, and set again
* by their Final function.
*/
unsigned int flag_allow_md : 1;
/*
* Flag to termine if the 'z' digest needs to be computed and fed to the
* hash function.
* This flag should be set on initialization and the compuation should
* be performed only once, on first update.
*/
unsigned int flag_compute_z_digest : 1;
char mdname[OSSL_MAX_NAME_SIZE];
/* The Algorithm Identifier of the combined signature algorithm */
unsigned char aid_buf[OSSL_MAX_ALGORITHM_ID_SIZE];
unsigned char *aid;
size_t aid_len;
/* main digest */
EVP_MD *md;
EVP_MD_CTX *mdctx;
size_t mdsize;
/* SM2 ID used for calculating the Z value */
unsigned char *id;
size_t id_len;
} PROV_SM2_CTX;
/* TODO: it seems SM2 doesn't need this */
static int sm2sig_get_md_nid(const EVP_MD *md)
{
/*
* Because the EC library deals with NIDs, we need to translate.
* We do so using EVP_MD_is_a(), and therefore need a name to NID
* map.
*/
static const OSSL_ITEM name_to_nid[] = {
{ NID_sm3, OSSL_DIGEST_NAME_SM3 },
};
size_t i;
int mdnid = NID_undef;
if (md == NULL)
goto end;
for (i = 0; i < OSSL_NELEM(name_to_nid); i++) {
if (EVP_MD_is_a(md, name_to_nid[i].ptr)) {
mdnid = (int)name_to_nid[i].id;
break;
}
}
if (mdnid == NID_undef)
ERR_raise(ERR_LIB_PROV, PROV_R_INVALID_DIGEST);
end:
return mdnid;
}
static void *sm2sig_newctx(void *provctx, const char *propq)
{
PROV_SM2_CTX *ctx = OPENSSL_zalloc(sizeof(PROV_SM2_CTX));
if (ctx == NULL)
return NULL;
ctx->libctx = PROV_LIBRARY_CONTEXT_OF(provctx);
if (propq != NULL && (ctx->propq = OPENSSL_strdup(propq)) == NULL) {
OPENSSL_free(ctx);
ctx = NULL;
ERR_raise(ERR_LIB_PROV, ERR_R_MALLOC_FAILURE);
}
/* don't allow to change MD, and in fact there is no such need */
ctx->flag_allow_md = 0;
return ctx;
}
static int sm2sig_signature_init(void *vpsm2ctx, void *ec)
{
PROV_SM2_CTX *psm2ctx = (PROV_SM2_CTX *)vpsm2ctx;
if (psm2ctx == NULL || ec == NULL || !EC_KEY_up_ref(ec))
return 0;
EC_KEY_free(psm2ctx->ec);
psm2ctx->ec = ec;
return 1;
}
static int sm2sig_sign(void *vpsm2ctx, unsigned char *sig, size_t *siglen,
size_t sigsize, const unsigned char *tbs, size_t tbslen)
{
PROV_SM2_CTX *ctx = (PROV_SM2_CTX *)vpsm2ctx;
int ret;
unsigned int sltmp;
/* SM2 uses ECDSA_size as well */
size_t ecsize = ECDSA_size(ctx->ec);
if (sig == NULL) {
*siglen = ecsize;
return 1;
}
if (sigsize < (size_t)ecsize)
return 0;
if (ctx->mdsize != 0 && tbslen != ctx->mdsize)
return 0;
ret = sm2_internal_sign(tbs, tbslen, sig, &sltmp, ctx->ec);
if (ret <= 0)
return 0;
*siglen = sltmp;
return 1;
}
static int sm2sig_verify(void *vpsm2ctx, const unsigned char *sig, size_t siglen,
const unsigned char *tbs, size_t tbslen)
{
PROV_SM2_CTX *ctx = (PROV_SM2_CTX *)vpsm2ctx;
if (ctx->mdsize != 0 && tbslen != ctx->mdsize)
return 0;
return sm2_internal_verify(tbs, tbslen, sig, siglen, ctx->ec);
}
static void free_md(PROV_SM2_CTX *ctx)
{
EVP_MD_CTX_free(ctx->mdctx);
EVP_MD_free(ctx->md);
ctx->mdctx = NULL;
ctx->md = NULL;
ctx->mdsize = 0;
}
static int sm2sig_digest_signverify_init(void *vpsm2ctx, const char *mdname,
void *ec)
{
PROV_SM2_CTX *ctx = (PROV_SM2_CTX *)vpsm2ctx;
int md_nid = NID_undef;
WPACKET pkt;
int ret = 0;
free_md(ctx);
if (!sm2sig_signature_init(vpsm2ctx, ec))
return ret;
ctx->md = EVP_MD_fetch(ctx->libctx, mdname, ctx->propq);
if ((md_nid = sm2sig_get_md_nid(ctx->md)) == NID_undef)
goto error;
ctx->mdsize = EVP_MD_size(ctx->md);
ctx->mdctx = EVP_MD_CTX_new();
if (ctx->mdctx == NULL)
goto error;
/*
* TODO(3.0) Should we care about DER writing errors?
* All it really means is that for some reason, there's no
* AlgorithmIdentifier to be had, but the operation itself is
* still valid, just as long as it's not used to construct
* anything that needs an AlgorithmIdentifier.
*/
ctx->aid_len = 0;
if (WPACKET_init_der(&pkt, ctx->aid_buf, sizeof(ctx->aid_buf))
&& DER_w_algorithmIdentifier_SM2_with_MD(&pkt, -1, ctx->ec, md_nid)
&& WPACKET_finish(&pkt)) {
WPACKET_get_total_written(&pkt, &ctx->aid_len);
ctx->aid = WPACKET_get_curr(&pkt);
}
WPACKET_cleanup(&pkt);
if (!EVP_DigestInit_ex(ctx->mdctx, ctx->md, NULL))
goto error;
ctx->flag_compute_z_digest = 1;
ret = 1;
error:
if (!ret)
free_md(ctx);
return ret;
}
static int sm2sig_compute_z_digest(PROV_SM2_CTX *ctx)
{
uint8_t *z = NULL;
int ret = 1;
if (ctx->flag_compute_z_digest) {
/* Only do this once */
ctx->flag_compute_z_digest = 0;
if ((z = OPENSSL_zalloc(ctx->mdsize)) == NULL
/* get hashed prefix 'z' of tbs message */
|| !sm2_compute_z_digest(z, ctx->md, ctx->id, ctx->id_len, ctx->ec)
|| !EVP_DigestUpdate(ctx->mdctx, z, ctx->mdsize))
ret = 0;
OPENSSL_free(z);
}
return ret;
}
int sm2sig_digest_signverify_update(void *vpsm2ctx, const unsigned char *data,
size_t datalen)
{
PROV_SM2_CTX *psm2ctx = (PROV_SM2_CTX *)vpsm2ctx;
if (psm2ctx == NULL || psm2ctx->mdctx == NULL)
return 0;
return sm2sig_compute_z_digest(psm2ctx)
&& EVP_DigestUpdate(psm2ctx->mdctx, data, datalen);
}
int sm2sig_digest_sign_final(void *vpsm2ctx, unsigned char *sig, size_t *siglen,
size_t sigsize)
{
PROV_SM2_CTX *psm2ctx = (PROV_SM2_CTX *)vpsm2ctx;
unsigned char digest[EVP_MAX_MD_SIZE];
unsigned int dlen = 0;
if (psm2ctx == NULL || psm2ctx->mdctx == NULL)
return 0;
/*
* If sig is NULL then we're just finding out the sig size. Other fields
* are ignored. Defer to sm2sig_sign.
*/
if (sig != NULL) {
if (!(sm2sig_compute_z_digest(psm2ctx)
&& EVP_DigestFinal_ex(psm2ctx->mdctx, digest, &dlen)))
return 0;
}
return sm2sig_sign(vpsm2ctx, sig, siglen, sigsize, digest, (size_t)dlen);
}
int sm2sig_digest_verify_final(void *vpsm2ctx, const unsigned char *sig,
size_t siglen)
{
PROV_SM2_CTX *psm2ctx = (PROV_SM2_CTX *)vpsm2ctx;
unsigned char digest[EVP_MAX_MD_SIZE];
unsigned int dlen = 0;
if (psm2ctx == NULL || psm2ctx->mdctx == NULL)
return 0;
/* SM2 always use SM3 so it's not possible to exceed the limit */
if (!(sm2sig_compute_z_digest(psm2ctx)
&& EVP_DigestFinal_ex(psm2ctx->mdctx, digest, &dlen)))
return 0;
return sm2sig_verify(vpsm2ctx, sig, siglen, digest, (size_t)dlen);
}
static void sm2sig_freectx(void *vpsm2ctx)
{
PROV_SM2_CTX *ctx = (PROV_SM2_CTX *)vpsm2ctx;
free_md(ctx);
EC_KEY_free(ctx->ec);
OPENSSL_free(ctx->id);
OPENSSL_free(ctx);
}
static void *sm2sig_dupctx(void *vpsm2ctx)
{
PROV_SM2_CTX *srcctx = (PROV_SM2_CTX *)vpsm2ctx;
PROV_SM2_CTX *dstctx;
dstctx = OPENSSL_zalloc(sizeof(*srcctx));
if (dstctx == NULL)
return NULL;
*dstctx = *srcctx;
dstctx->ec = NULL;
dstctx->md = NULL;
dstctx->mdctx = NULL;
if (srcctx->ec != NULL && !EC_KEY_up_ref(srcctx->ec))
goto err;
dstctx->ec = srcctx->ec;
if (srcctx->md != NULL && !EVP_MD_up_ref(srcctx->md))
goto err;
dstctx->md = srcctx->md;
if (srcctx->mdctx != NULL) {
dstctx->mdctx = EVP_MD_CTX_new();
if (dstctx->mdctx == NULL
|| !EVP_MD_CTX_copy_ex(dstctx->mdctx, srcctx->mdctx))
goto err;
}
if (srcctx->id != NULL) {
dstctx->id = OPENSSL_malloc(srcctx->id_len);
if (dstctx->id == NULL)
goto err;
dstctx->id_len = srcctx->id_len;
memcpy(dstctx->id, srcctx->id, srcctx->id_len);
}
return dstctx;
err:
sm2sig_freectx(dstctx);
return NULL;
}
static int sm2sig_get_ctx_params(void *vpsm2ctx, OSSL_PARAM *params)
{
PROV_SM2_CTX *psm2ctx = (PROV_SM2_CTX *)vpsm2ctx;
OSSL_PARAM *p;
if (psm2ctx == NULL || params == NULL)
return 0;
p = OSSL_PARAM_locate(params, OSSL_SIGNATURE_PARAM_ALGORITHM_ID);
if (p != NULL
&& !OSSL_PARAM_set_octet_string(p, psm2ctx->aid, psm2ctx->aid_len))
return 0;
p = OSSL_PARAM_locate(params, OSSL_SIGNATURE_PARAM_DIGEST_SIZE);
if (p != NULL && !OSSL_PARAM_set_size_t(p, psm2ctx->mdsize))
return 0;
p = OSSL_PARAM_locate(params, OSSL_SIGNATURE_PARAM_DIGEST);
if (p != NULL && !OSSL_PARAM_set_utf8_string(p, psm2ctx->md == NULL
? psm2ctx->mdname
: EVP_MD_name(psm2ctx->md)))
return 0;
return 1;
}
static const OSSL_PARAM known_gettable_ctx_params[] = {
OSSL_PARAM_octet_string(OSSL_SIGNATURE_PARAM_ALGORITHM_ID, NULL, 0),
OSSL_PARAM_size_t(OSSL_SIGNATURE_PARAM_DIGEST_SIZE, NULL),
OSSL_PARAM_utf8_string(OSSL_SIGNATURE_PARAM_DIGEST, NULL, 0),
OSSL_PARAM_END
};
static const OSSL_PARAM *sm2sig_gettable_ctx_params(ossl_unused void *provctx)
{
return known_gettable_ctx_params;
}
static int sm2sig_set_ctx_params(void *vpsm2ctx, const OSSL_PARAM params[])
{
PROV_SM2_CTX *psm2ctx = (PROV_SM2_CTX *)vpsm2ctx;
const OSSL_PARAM *p;
char *mdname;
if (psm2ctx == NULL || params == NULL)
return 0;
p = OSSL_PARAM_locate_const(params, OSSL_PKEY_PARAM_DIST_ID);
if (p != NULL) {
void *tmp_id = NULL;
size_t tmp_idlen;
/*
* If the 'z' digest has already been computed, the ID is set too late
*/
if (!psm2ctx->flag_compute_z_digest)
return 0;
if (!OSSL_PARAM_get_octet_string(p, &tmp_id, 0, &tmp_idlen))
return 0;
OPENSSL_free(psm2ctx->id);
psm2ctx->id = tmp_id;
psm2ctx->id_len = tmp_idlen;
}
if (psm2ctx->md != NULL) {
/*
* You cannot set the digest name/size when doing a DigestSign or
* DigestVerify.
*/
return 1;
}
p = OSSL_PARAM_locate_const(params, OSSL_SIGNATURE_PARAM_DIGEST_SIZE);
if (p != NULL && !OSSL_PARAM_get_size_t(p, &psm2ctx->mdsize))
return 0;
/*
* We never actually use the mdname, but we do support getting it later.
* This can be useful for applications that want to know the MD that they
* previously set.
*/
p = OSSL_PARAM_locate_const(params, OSSL_SIGNATURE_PARAM_DIGEST);
mdname = psm2ctx->mdname;
if (p != NULL
&& !OSSL_PARAM_get_utf8_string(p, &mdname, sizeof(psm2ctx->mdname)))
return 0;
return 1;
}
static const OSSL_PARAM known_settable_ctx_params[] = {
OSSL_PARAM_size_t(OSSL_SIGNATURE_PARAM_DIGEST_SIZE, NULL),
OSSL_PARAM_utf8_string(OSSL_SIGNATURE_PARAM_DIGEST, NULL, 0),
OSSL_PARAM_octet_string(OSSL_PKEY_PARAM_DIST_ID, NULL, 0),
OSSL_PARAM_END
};
static const OSSL_PARAM *sm2sig_settable_ctx_params(ossl_unused void *provctx)
{
/*
* TODO(3.0): Should this function return a different set of settable ctx
* params if the ctx is being used for a DigestSign/DigestVerify? In that
* case it is not allowed to set the digest size/digest name because the
* digest is explicitly set as part of the init.
*/
return known_settable_ctx_params;
}
static int sm2sig_get_ctx_md_params(void *vpsm2ctx, OSSL_PARAM *params)
{
PROV_SM2_CTX *psm2ctx = (PROV_SM2_CTX *)vpsm2ctx;
if (psm2ctx->mdctx == NULL)
return 0;
return EVP_MD_CTX_get_params(psm2ctx->mdctx, params);
}
static const OSSL_PARAM *sm2sig_gettable_ctx_md_params(void *vpsm2ctx)
{
PROV_SM2_CTX *psm2ctx = (PROV_SM2_CTX *)vpsm2ctx;
if (psm2ctx->md == NULL)
return 0;
return EVP_MD_gettable_ctx_params(psm2ctx->md);
}
static int sm2sig_set_ctx_md_params(void *vpsm2ctx, const OSSL_PARAM params[])
{
PROV_SM2_CTX *psm2ctx = (PROV_SM2_CTX *)vpsm2ctx;
if (psm2ctx->mdctx == NULL)
return 0;
return EVP_MD_CTX_set_params(psm2ctx->mdctx, params);
}
static const OSSL_PARAM *sm2sig_settable_ctx_md_params(void *vpsm2ctx)
{
PROV_SM2_CTX *psm2ctx = (PROV_SM2_CTX *)vpsm2ctx;
if (psm2ctx->md == NULL)
return 0;
return EVP_MD_settable_ctx_params(psm2ctx->md);
}
const OSSL_DISPATCH sm2_signature_functions[] = {
{ OSSL_FUNC_SIGNATURE_NEWCTX, (void (*)(void))sm2sig_newctx },
{ OSSL_FUNC_SIGNATURE_SIGN_INIT, (void (*)(void))sm2sig_signature_init },
{ OSSL_FUNC_SIGNATURE_SIGN, (void (*)(void))sm2sig_sign },
{ OSSL_FUNC_SIGNATURE_VERIFY_INIT, (void (*)(void))sm2sig_signature_init },
{ OSSL_FUNC_SIGNATURE_VERIFY, (void (*)(void))sm2sig_verify },
{ OSSL_FUNC_SIGNATURE_DIGEST_SIGN_INIT,
(void (*)(void))sm2sig_digest_signverify_init },
{ OSSL_FUNC_SIGNATURE_DIGEST_SIGN_UPDATE,
(void (*)(void))sm2sig_digest_signverify_update },
{ OSSL_FUNC_SIGNATURE_DIGEST_SIGN_FINAL,
(void (*)(void))sm2sig_digest_sign_final },
{ OSSL_FUNC_SIGNATURE_DIGEST_VERIFY_INIT,
(void (*)(void))sm2sig_digest_signverify_init },
{ OSSL_FUNC_SIGNATURE_DIGEST_VERIFY_UPDATE,
(void (*)(void))sm2sig_digest_signverify_update },
{ OSSL_FUNC_SIGNATURE_DIGEST_VERIFY_FINAL,
(void (*)(void))sm2sig_digest_verify_final },
{ OSSL_FUNC_SIGNATURE_FREECTX, (void (*)(void))sm2sig_freectx },
{ OSSL_FUNC_SIGNATURE_DUPCTX, (void (*)(void))sm2sig_dupctx },
{ OSSL_FUNC_SIGNATURE_GET_CTX_PARAMS, (void (*)(void))sm2sig_get_ctx_params },
{ OSSL_FUNC_SIGNATURE_GETTABLE_CTX_PARAMS,
(void (*)(void))sm2sig_gettable_ctx_params },
{ OSSL_FUNC_SIGNATURE_SET_CTX_PARAMS, (void (*)(void))sm2sig_set_ctx_params },
{ OSSL_FUNC_SIGNATURE_SETTABLE_CTX_PARAMS,
(void (*)(void))sm2sig_settable_ctx_params },
{ OSSL_FUNC_SIGNATURE_GET_CTX_MD_PARAMS,
(void (*)(void))sm2sig_get_ctx_md_params },
{ OSSL_FUNC_SIGNATURE_GETTABLE_CTX_MD_PARAMS,
(void (*)(void))sm2sig_gettable_ctx_md_params },
{ OSSL_FUNC_SIGNATURE_SET_CTX_MD_PARAMS,
(void (*)(void))sm2sig_set_ctx_md_params },
{ OSSL_FUNC_SIGNATURE_SETTABLE_CTX_MD_PARAMS,
(void (*)(void))sm2sig_settable_ctx_md_params },
{ 0, NULL }
};

View File

@ -921,33 +921,23 @@ static int test_EC_keygen_with_enc(int idx)
static int test_EVP_SM2_verify(void)
{
/* From https://tools.ietf.org/html/draft-shen-sm2-ecdsa-02#appendix-A */
const char *pubkey =
"-----BEGIN PUBLIC KEY-----\n"
"MIIBMzCB7AYHKoZIzj0CATCB4AIBATAsBgcqhkjOPQEBAiEAhULWnkwETxjouSQ1\n"
"v2/33kVyg5FcRVF9ci7biwjx38MwRAQgeHlotPoyw/0kF4Quc7v+/y88hItoMdfg\n"
"7GUiizk35JgEIGPkxtOyOwyEnPhCQUhL/kj2HVmlsWugbm4S0donxSSaBEEEQh3r\n"
"1hti6rZ0ZDTrw8wxXjIiCzut1QvcTE5sFH/t1D0GgFEry7QsB9RzSdIVO3DE5df9\n"
"/L+jbqGoWEG55G4JogIhAIVC1p5MBE8Y6LkkNb9v990pdyBjBIVijVrnTufDLnm3\n"
"AgEBA0IABArkx3mKoPEZRxvuEYJb5GICu3nipYRElel8BP9N8lSKfAJA+I8c1OFj\n"
"Uqc8F7fxbwc1PlOhdtaEqf4Ma7eY6Fc=\n"
"-----END PUBLIC KEY-----\n";
"-----BEGIN PUBLIC KEY-----\n"
"MFkwEwYHKoZIzj0CAQYIKoEcz1UBgi0DQgAEp1KLWq1ZE2jmoAnnBJE1LBGxVr18\n"
"YvvqECWCpXfAQ9qUJ+UmthnUPf0iM3SaXKHe6PlLIDyNlWMWb9RUh/yU3g==\n"
"-----END PUBLIC KEY-----\n";
const char *msg = "message digest";
const char *id = "ALICE123@YAHOO.COM";
const uint8_t signature[] = {
0x30, 0x44, 0x02, 0x20,
0x40, 0xF1, 0xEC, 0x59, 0xF7, 0x93, 0xD9, 0xF4, 0x9E, 0x09, 0xDC,
0xEF, 0x49, 0x13, 0x0D, 0x41, 0x94, 0xF7, 0x9F, 0xB1, 0xEE, 0xD2,
0xCA, 0xA5, 0x5B, 0xAC, 0xDB, 0x49, 0xC4, 0xE7, 0x55, 0xD1,
0x02, 0x20,
0x6F, 0xC6, 0xDA, 0xC3, 0x2C, 0x5D, 0x5C, 0xF1, 0x0C, 0x77, 0xDF,
0xB2, 0x0F, 0x7C, 0x2E, 0xB6, 0x67, 0xA4, 0x57, 0x87, 0x2F, 0xB0,
0x9E, 0xC5, 0x63, 0x27, 0xA6, 0x7E, 0xC7, 0xDE, 0xEB, 0xE7
0x30, 0x44, 0x02, 0x20, 0x5b, 0xdb, 0xab, 0x81, 0x4f, 0xbb,
0x8b, 0x69, 0xb1, 0x05, 0x9c, 0x99, 0x3b, 0xb2, 0x45, 0x06,
0x4a, 0x30, 0x15, 0x59, 0x84, 0xcd, 0xee, 0x30, 0x60, 0x36,
0x57, 0x87, 0xef, 0x5c, 0xd0, 0xbe, 0x02, 0x20, 0x43, 0x8d,
0x1f, 0xc7, 0x77, 0x72, 0x39, 0xbb, 0x72, 0xe1, 0xfd, 0x07,
0x58, 0xd5, 0x82, 0xc8, 0x2d, 0xba, 0x3b, 0x2c, 0x46, 0x24,
0xe3, 0x50, 0xff, 0x04, 0xc7, 0xa0, 0x71, 0x9f, 0xa4, 0x70
};
int rc = 0;
@ -978,15 +968,14 @@ static int test_EVP_SM2_verify(void)
if (!TEST_ptr(pctx = EVP_PKEY_CTX_new(pkey, NULL)))
goto done;
if (!TEST_int_gt(EVP_PKEY_CTX_set1_id(pctx, (const uint8_t *)id,
strlen(id)), 0))
goto done;
EVP_MD_CTX_set_pkey_ctx(mctx, pctx);
if (!TEST_true(EVP_DigestVerifyInit(mctx, NULL, EVP_sm3(), NULL, pkey)))
goto done;
if (!TEST_int_gt(EVP_PKEY_CTX_set1_id(pctx, id, strlen(id)), 0))
goto done;
if (!TEST_true(EVP_DigestVerifyUpdate(mctx, msg, strlen(msg))))
goto done;
@ -1024,13 +1013,14 @@ static int test_EVP_SM2(void)
uint8_t sm2_id[] = {1, 2, 3, 4, 'l', 'e', 't', 't', 'e', 'r'};
pctx = EVP_PKEY_CTX_new_id(EVP_PKEY_EC, NULL);
pctx = EVP_PKEY_CTX_new_id(EVP_PKEY_SM2, NULL);
if (!TEST_ptr(pctx))
goto done;
if (!TEST_true(EVP_PKEY_paramgen_init(pctx) == 1))
goto done;
/* TODO is this even needed? */
if (!TEST_true(EVP_PKEY_CTX_set_ec_paramgen_curve_nid(pctx, NID_sm2)))
goto done;
@ -1047,9 +1037,6 @@ static int test_EVP_SM2(void)
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;
@ -1062,10 +1049,10 @@ static int test_EVP_SM2(void)
EVP_MD_CTX_set_pkey_ctx(md_ctx, sctx);
EVP_MD_CTX_set_pkey_ctx(md_ctx_verify, sctx);
if (!TEST_int_gt(EVP_PKEY_CTX_set1_id(sctx, sm2_id, sizeof(sm2_id)), 0))
if (!TEST_true(EVP_DigestSignInit(md_ctx, NULL, EVP_sm3(), NULL, pkey)))
goto done;
if (!TEST_true(EVP_DigestSignInit(md_ctx, NULL, EVP_sm3(), NULL, pkey)))
if (!TEST_int_gt(EVP_PKEY_CTX_set1_id(sctx, sm2_id, sizeof(sm2_id)), 0))
goto done;
if(!TEST_true(EVP_DigestSignUpdate(md_ctx, kMsg, sizeof(kMsg))))
@ -1086,6 +1073,9 @@ static int test_EVP_SM2(void)
if (!TEST_true(EVP_DigestVerifyInit(md_ctx_verify, NULL, EVP_sm3(), NULL, pkey)))
goto done;
if (!TEST_int_gt(EVP_PKEY_CTX_set1_id(sctx, sm2_id, sizeof(sm2_id)), 0))
goto done;
if (!TEST_true(EVP_DigestVerifyUpdate(md_ctx_verify, kMsg, sizeof(kMsg))))
goto done;
@ -1093,6 +1083,13 @@ static int test_EVP_SM2(void)
goto done;
/* now check encryption/decryption */
/*
* SM2 public key encrytion is not moved into default provider yet,
* so we make sure the key gets downgraded for the moment being.
* TODO Remove this call when provided SM2 encryption is implemented
*/
if (!TEST_ptr(EVP_PKEY_get0(pkey)))
goto done;
if (!TEST_ptr(cctx = EVP_PKEY_CTX_new(pkey, NULL)))
goto done;
@ -1914,7 +1911,7 @@ static int test_pkey_ctx_fail_without_provider(int tst)
break;
case 1:
keytype = "SM2";
expect_null = 0; /* TODO: change to 1 when we have a SM2 keymgmt */
expect_null = 1;
#ifdef OPENSSL_NO_EC
TEST_info("EC disable, skipping SM2 check...");
goto end;