mirror of
https://github.com/openssl/openssl.git
synced 2024-12-13 20:13:53 +08:00
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:
parent
7ee511d093
commit
d0b79f8631
@ -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
|
||||
|
@ -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:
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
@ -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,
|
||||
|
@ -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;
|
||||
}
|
||||
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
@ -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 */
|
||||
|
11
providers/common/der/SM2.asn1
Normal file
11
providers/common/der/SM2.asn1
Normal 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 }
|
@ -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
|
||||
|
23
providers/common/der/der_sm2.h.in
Normal file
23
providers/common/der/der_sm2.h.in
Normal 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);
|
17
providers/common/der/der_sm2_gen.c.in
Normal file
17
providers/common/der/der_sm2_gen.c.in
Normal 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 });
|
||||
-}
|
23
providers/common/der/der_sm2_key.c
Normal file
23
providers/common/der/der_sm2_key.c
Normal 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);
|
||||
}
|
39
providers/common/der/der_sm2_sig.c
Normal file
39
providers/common/der/der_sm2_sig.c
Normal 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);
|
||||
}
|
@ -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
|
||||
|
@ -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[];
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
568
providers/implementations/signature/sm2sig.c
Normal file
568
providers/implementations/signature/sm2sig.c
Normal 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 }
|
||||
};
|
@ -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;
|
||||
|
Loading…
Reference in New Issue
Block a user