提交 f4e4382c 编写于 作者: R Richard Levitte

EVP_PKEY_assign_EC_KEY(): detect SM2 curve and set EVP_PKEY type accordingly

This means that when loaded or created, EC EVP_PKEYs with the SM2
curve will be regarded as EVP_PKEY_SM2 type keys by default.
Applications are no longer forced to check and fix this.

It's still possible, for those who want this, to set the key type to
EVP_PKEY_EC and thereby run the normal EC computations with the SM2
curve.  This has to be done explicitly.
Reviewed-by: NMatt Caswell <matt@openssl.org>
Reviewed-by: NDmitry Belyavskiy <beldmit@gmail.com>
(Merged from https://github.com/openssl/openssl/pull/10942)
上级 658608c4
...@@ -401,8 +401,19 @@ ENGINE *EVP_PKEY_get0_engine(const EVP_PKEY *pkey) ...@@ -401,8 +401,19 @@ ENGINE *EVP_PKEY_get0_engine(const EVP_PKEY *pkey)
# endif # endif
int EVP_PKEY_assign(EVP_PKEY *pkey, int type, void *key) int EVP_PKEY_assign(EVP_PKEY *pkey, int type, void *key)
{ {
int alias = type;
if (EVP_PKEY_type(type) == EVP_PKEY_EC) {
const EC_GROUP *group = EC_KEY_get0_group(key);
if (group != NULL && EC_GROUP_get_curve_name(group) == NID_sm2)
alias = EVP_PKEY_SM2;
}
if (pkey == NULL || !EVP_PKEY_set_type(pkey, type)) if (pkey == NULL || !EVP_PKEY_set_type(pkey, type))
return 0; return 0;
if (!EVP_PKEY_set_alias_type(pkey, alias))
return 0;
pkey->pkey.ptr = key; pkey->pkey.ptr = key;
return (key != NULL); return (key != NULL);
} }
...@@ -519,7 +530,7 @@ int EVP_PKEY_set1_EC_KEY(EVP_PKEY *pkey, EC_KEY *key) ...@@ -519,7 +530,7 @@ int EVP_PKEY_set1_EC_KEY(EVP_PKEY *pkey, EC_KEY *key)
EC_KEY *EVP_PKEY_get0_EC_KEY(const EVP_PKEY *pkey) EC_KEY *EVP_PKEY_get0_EC_KEY(const EVP_PKEY *pkey)
{ {
if (pkey->type != EVP_PKEY_EC) { if (EVP_PKEY_base_id(pkey) != EVP_PKEY_EC) {
EVPerr(EVP_F_EVP_PKEY_GET0_EC_KEY, EVP_R_EXPECTING_A_EC_KEY); EVPerr(EVP_F_EVP_PKEY_GET0_EC_KEY, EVP_R_EXPECTING_A_EC_KEY);
return NULL; return NULL;
} }
......
...@@ -90,8 +90,7 @@ If B<engine> does not include an B<EVP_PKEY_METHOD> for B<pkey> an ...@@ -90,8 +90,7 @@ If B<engine> does not include an B<EVP_PKEY_METHOD> for B<pkey> an
error occurs. error occurs.
EVP_PKEY_set_alias_type() allows modifying a EVP_PKEY to use a EVP_PKEY_set_alias_type() allows modifying a EVP_PKEY to use a
different set of algorithms than the default. This is currently used different set of algorithms than the default.
to support SM2 keys, which use an identical encoding to ECDSA.
=head1 NOTES =head1 NOTES
...@@ -103,6 +102,16 @@ EVP_PKEY_assign_RSA(), EVP_PKEY_assign_DSA(), EVP_PKEY_assign_DH(), ...@@ -103,6 +102,16 @@ EVP_PKEY_assign_RSA(), EVP_PKEY_assign_DSA(), EVP_PKEY_assign_DH(),
EVP_PKEY_assign_EC_KEY(), EVP_PKEY_assign_POLY1305() EVP_PKEY_assign_EC_KEY(), EVP_PKEY_assign_POLY1305()
and EVP_PKEY_assign_SIPHASH() are implemented as macros. and EVP_PKEY_assign_SIPHASH() are implemented as macros.
EVP_PKEY_assign_EC_KEY() looks at the curve name id to determine if
the passed B<EC_KEY> is an L<SM2(7)> key, and will set the B<EVP_PKEY>
type to B<EVP_PKEY_SM2> in that case, instead of B<EVP_PKEY_EC>.
It's possible to switch back and forth between the types B<EVP_PKEY_EC>
and B<EVP_PKEY_SM2> with a call to EVP_PKEY_set_alias_type() on keys
assigned with this macro if it's desirable to do a normal EC
computations with the SM2 curve instead of the special SM2
computations, and vice versa.
Most applications wishing to know a key type will simply call Most applications wishing to know a key type will simply call
EVP_PKEY_base_id() and will not care about the actual type: EVP_PKEY_base_id() and will not care about the actual type:
which will be identical in almost all cases. which will be identical in almost all cases.
...@@ -143,7 +152,7 @@ algorithms with EVP_PKEY_set_alias_type: ...@@ -143,7 +152,7 @@ algorithms with EVP_PKEY_set_alias_type:
=head1 SEE ALSO =head1 SEE ALSO
L<EVP_PKEY_new(3)> L<EVP_PKEY_new(3)>, L<SM2(7)>
=head1 COPYRIGHT =head1 COPYRIGHT
......
...@@ -20,25 +20,17 @@ B<SM2> signatures can be generated by using the 'DigestSign' series of APIs, for ...@@ -20,25 +20,17 @@ B<SM2> signatures can be generated by using the 'DigestSign' series of APIs, for
instance, EVP_DigestSignInit(), EVP_DigestSignUpdate() and EVP_DigestSignFinal(). instance, EVP_DigestSignInit(), EVP_DigestSignUpdate() and EVP_DigestSignFinal().
Ditto for the verification process by calling the 'DigestVerify' series of APIs. Ditto for the verification process by calling the 'DigestVerify' series of APIs.
There are several special steps that need to be done before computing an B<SM2> Before computing an B<SM2> signature, an B<EVP_PKEY_CTX> needs to be created,
signature. and an B<SM2> ID must be set for it, like this:
The B<EVP_PKEY> structure will default to using ECDSA for signatures when it is
created. It should be set to B<EVP_PKEY_SM2> by calling:
EVP_PKEY_set_alias_type(pkey, EVP_PKEY_SM2);
Then an ID should be set by calling:
EVP_PKEY_CTX_set1_id(pctx, id, id_len); EVP_PKEY_CTX_set1_id(pctx, id, id_len);
When calling the EVP_DigestSignInit() or EVP_DigestVerifyInit() functions, a Before calling the EVP_DigestSignInit() or EVP_DigestVerifyInit() functions,
pre-allocated B<EVP_PKEY_CTX> should be assigned to the B<EVP_MD_CTX>. This is that B<EVP_PKEY_CTX> should be assigned to the B<EVP_MD_CTX>, like this:
done by calling:
EVP_MD_CTX_set_pkey_ctx(mctx, pctx); EVP_MD_CTX_set_pkey_ctx(mctx, pctx);
And normally there is no need to pass a B<pctx> parameter to EVP_DigestSignInit() There is normally no need to pass a B<pctx> parameter to EVP_DigestSignInit()
or EVP_DigestVerifyInit() in such a scenario. or EVP_DigestVerifyInit() in such a scenario.
SM2 can be tested with the L<openssl-speed(1)> application since version 3.0.0. SM2 can be tested with the L<openssl-speed(1)> application since version 3.0.0.
...@@ -52,11 +44,10 @@ a message with the SM2 signature algorithm and the SM3 hash algorithm: ...@@ -52,11 +44,10 @@ a message with the SM2 signature algorithm and the SM3 hash algorithm:
#include <openssl/evp.h> #include <openssl/evp.h>
/* obtain an EVP_PKEY using whatever methods... */ /* obtain an EVP_PKEY using whatever methods... */
EVP_PKEY_set_alias_type(pkey, EVP_PKEY_SM2);
mctx = EVP_MD_CTX_new(); mctx = EVP_MD_CTX_new();
pctx = EVP_PKEY_CTX_new(pkey, NULL); pctx = EVP_PKEY_CTX_new(pkey, NULL);
EVP_PKEY_CTX_set1_id(pctx, id, id_len); EVP_PKEY_CTX_set1_id(pctx, id, id_len);
EVP_MD_CTX_set_pkey_ctx(mctx, pctx);; EVP_MD_CTX_set_pkey_ctx(mctx, pctx);
EVP_DigestVerifyInit(mctx, NULL, EVP_sm3(), NULL, pkey); EVP_DigestVerifyInit(mctx, NULL, EVP_sm3(), NULL, pkey);
EVP_DigestVerifyUpdate(mctx, msg, msg_len); EVP_DigestVerifyUpdate(mctx, msg, msg_len);
EVP_DigestVerifyFinal(mctx, sig, sig_len) EVP_DigestVerifyFinal(mctx, sig, sig_len)
...@@ -64,7 +55,6 @@ a message with the SM2 signature algorithm and the SM3 hash algorithm: ...@@ -64,7 +55,6 @@ a message with the SM2 signature algorithm and the SM3 hash algorithm:
=head1 SEE ALSO =head1 SEE ALSO
L<EVP_PKEY_CTX_new(3)>, L<EVP_PKEY_CTX_new(3)>,
L<EVP_PKEY_set_alias_type(3)>,
L<EVP_DigestSignInit(3)>, L<EVP_DigestSignInit(3)>,
L<EVP_DigestVerifyInit(3)>, L<EVP_DigestVerifyInit(3)>,
L<EVP_PKEY_CTX_set1_id(3)>, L<EVP_PKEY_CTX_set1_id(3)>,
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册