-
-
Notifications
You must be signed in to change notification settings - Fork 10.1k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
An alternative to address the SM2 ID issues #7113
Conversation
Resolving the travis failures |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Looks good. My initial review comments below. Also if I understood you correctly some of the test stuff was lifted from the other PR. Can that bit be in a separate commit with appropriate git author attribution?
crypto/sm2/sm2_pmeth.c
Outdated
@@ -22,28 +22,35 @@ typedef struct { | |||
EC_GROUP *gen_group; | |||
/* message digest */ | |||
const EVP_MD *md; | |||
/* Distinguishing Identifier, ISO/IEC 15946-3 */ | |||
uint8_t *id; | |||
int id_len; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Probably this should be size_t
crypto/sm2/sm2_pmeth.c
Outdated
SM2err(SM2_F_PKEY_SM2_INIT, ERR_R_MALLOC_FAILURE); | ||
return 0; | ||
} | ||
|
||
ctx->data = dctx; | ||
/* -1 indicates there is no ID set yet */ | ||
smctx->id_len = -1; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
...but this is problematic if it were to be size_t
. I still think it should be though...I had too much pain sorting out the "it's a size_t, no it's a long, no it's an int" mess that we used to have in libssl (casts everywhere).
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Actually I used size_t initially and changed that to int in 7659f41. Because without the -1 value, it can distinguish if the ID is set or not, any ideas on this?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Perhaps just add an additional flag into the ctx?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Perhaps just add an additional flag into the ctx?
That is workable
crypto/sm2/sm2_pmeth.c
Outdated
return 0; | ||
} | ||
memcpy(dctx->id, sctx->id, sctx->id_len); | ||
dctx->id_len = sctx->id_len; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Probably you need to copy id_len
unconditionally to pick up the -1
initialisation
crypto/sm2/sm2_pmeth.c
Outdated
*(const EVP_MD **)p2 = smctx->md; | ||
return 1; | ||
|
||
case EVP_PKEY_CTRL_SM2_SET_ID: |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Probably this should be ...SET1_ID
?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I am a little confused with the number after get/set
, so 1
here stands for the caller could free the passed-in parameter at his will?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yes. The number is supposed to give you a hint about the memory management:
get0 == returns a pointer to the internal data. The caller should therefore not free it
get1 == creates a copy of the data or ups a ref count. The caller should free.
set0 == the caller passes ownership of the pointer to the library, so the caller should not subsequently free it
set1 == the caller does not pass ownership of the pointer to the library. The library will take a copy or up a ref count. The caller should free the original pointer.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Understood, thanks for the clear explanation.
crypto/sm2/sm2_pmeth.c
Outdated
/* | ||
* If no ID is set, reject to compute the 'Z' value. This allows to | ||
* set a null-ID to SM2, although which is not clear in the relevant | ||
* specifications. We implement as this to stay flexibility. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Perhaps reword as: "An ID value must be set. The specifications are not clear whether a NULL is allowed. We only allow it if set explicitly for maximum flexibility"
include/openssl/ec.h
Outdated
@@ -1429,6 +1429,19 @@ void EC_KEY_METHOD_get_verify(const EC_KEY_METHOD *meth, | |||
EVP_PKEY_OP_DERIVE, \ | |||
EVP_PKEY_CTRL_GET_EC_KDF_UKM, 0, (void *)(p)) | |||
|
|||
/* SM2 will skip the operation check so no need to pass operation here */ | |||
# define EVP_PKEY_CTX_set_sm2_id(ctx, id, id_len) \ |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
...set1_sm2_id
?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Actually, I wonder whether we should lose the sm2
bit altogether. This seems like a fairly general concept that might be needed for other algs in the future. Similarly for the macros below.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
There should be no sm2 in the name ...
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
But how to deal with the EVP_PKEY_SM2
parameter in EVP_PKEY_CTX_ctrl(ctx, EVP_PKEY_SM2, ...
?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Perhaps set that to -1
?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yes, that is what is done elsewhere.
include/openssl/evp.h
Outdated
@@ -181,6 +181,9 @@ int (*EVP_MD_meth_get_ctrl(const EVP_MD *md))(EVP_MD_CTX *ctx, int cmd, | |||
*/ | |||
# define EVP_MD_CTX_FLAG_FINALISE 0x0200 | |||
|
|||
/* Don't free up ctx->pctx in EVP_MD_CTX_reset */ | |||
# define EVP_MD_CTX_FLAG_NEGLECT_PCTX 0x0400 |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This feels misplaced in the public header - although I understand why you put it there.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It should also have a different name - it is do-not-free and neglect isn't the right name to use.
Perhaps EVP_MD_CTX_FLAG_KEEP_PKEY_CTX ... I'd also not abbreviate to PCTX ...
include/openssl/evp.h
Outdated
@@ -1321,6 +1325,8 @@ void EVP_PKEY_asn1_set_security_bits(EVP_PKEY_ASN1_METHOD *ameth, | |||
* Method handles all operations: don't assume any digest related defaults. | |||
*/ | |||
# define EVP_PKEY_FLAG_SIGCTX_CUSTOM 4 | |||
/* Do a customized hashing process */ | |||
# define EVP_PKEY_FLAG_DIGEST_CUSTOM 8 |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Similarly this seems misplaced.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Hmm, if this is placed in an internal header file, then the value of the flag should be chosen safe...
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I'd suggest a comment in the public header stating that the value 8 is reserved for internal use. In the internal header file where we put the definition we add a reference to the public header values.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Why is this flag even needed? If there's a non-NULL digest_custom
in a EVP_PKEY_METHOD
, then it has a digest custom function... isn't that enough?
(I know that we have sometimes used flags to tell if certain pointers are defined or not, but that's from the time when all structures were public, so flagging was done to allow for a certain level of ABI backward compatibility, to tell if added fields could be relied upon. Since EVP_PKEY_METHOD
is opaque, this methodology is no longer needed)
test/sm2_internal_test.c
Outdated
@@ -294,7 +294,8 @@ static int test_sm2_sign(const EC_GROUP *group, | |||
goto done; | |||
|
|||
start_fake_rand(k_hex); | |||
sig = sm2_do_sign(key, EVP_sm3(), userid, (const uint8_t *)message, msg_len); | |||
sig = sm2_do_sign(key, EVP_sm3(), (const uint8_t *)userid, (int)strlen(userid), |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
If the type were size_t
the int cast would not be needed here.
test/sm2_internal_test.c
Outdated
ok = sm2_do_verify(key, EVP_sm3(), sig, userid, (const uint8_t *)message, | ||
msg_len); | ||
ok = sm2_do_verify(key, EVP_sm3(), sig, (const uint8_t *)userid, | ||
(int)strlen(userid), (const uint8_t *)message, msg_len); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
...and here
Makes sense, will do that. |
include/openssl/evp.h
Outdated
@@ -1321,6 +1325,8 @@ void EVP_PKEY_asn1_set_security_bits(EVP_PKEY_ASN1_METHOD *ameth, | |||
* Method handles all operations: don't assume any digest related defaults. | |||
*/ | |||
# define EVP_PKEY_FLAG_SIGCTX_CUSTOM 4 | |||
/* Do a customized hashing process */ | |||
# define EVP_PKEY_FLAG_DIGEST_CUSTOM 8 |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Why is this flag even needed? If there's a non-NULL digest_custom
in a EVP_PKEY_METHOD
, then it has a digest custom function... isn't that enough?
(I know that we have sometimes used flags to tell if certain pointers are defined or not, but that's from the time when all structures were public, so flagging was done to allow for a certain level of ABI backward compatibility, to tell if added fields could be relied upon. Since EVP_PKEY_METHOD
is opaque, this methodology is no longer needed)
crypto/evp/digest.c
Outdated
EVP_PKEY_CTX_free(ctx->pctx); | ||
/* | ||
* pctx should be freed by the user of EVP_MD_CTX | ||
* if EVP_MD_CTX_FLAG_NEGLECT_PCTX is set |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This comment needs editing, since that flag doesn't exist.
crypto/evp/m_sigver.c
Outdated
@@ -75,6 +75,14 @@ static int do_sigver_init(EVP_MD_CTX *ctx, EVP_PKEY_CTX **pctx, | |||
return 1; | |||
if (!EVP_DigestInit_ex(ctx, type, e)) | |||
return 0; | |||
if (ctx->pctx->pmeth->flags & EVP_PKEY_FLAG_DIGEST_CUSTOM) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
EVP_PKEY_FLAG_DIGEST_CUSTOM
is unnecessary, it should be enough to check that digest_custom
is non-NULL
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Ahh, makes sense
crypto/evp/pmeth_lib.c
Outdated
if (!ctx || !ctx->pmeth || !ctx->pmeth->ctrl) { | ||
EVPerr(EVP_F_EVP_PKEY_CTX_CTRL, EVP_R_COMMAND_NOT_SUPPORTED); | ||
return -2; | ||
} | ||
if ((keytype != -1) && (ctx->pmeth->pkey_id != keytype)) | ||
return -1; | ||
|
||
/* Skip the operation checks since this is called in a very early stage */ | ||
if (ctx->pmeth->flags & EVP_PKEY_FLAG_DIGEST_CUSTOM) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Check that digest_custom
is non-NULL instead
crypto/include/internal/evp_int.h
Outdated
@@ -10,6 +10,14 @@ | |||
#include <openssl/evp.h> | |||
#include "internal/refcount.h" | |||
|
|||
/* Do a customized hashing process, use the reserved flag value in evp.h */ | |||
#define EVP_PKEY_FLAG_DIGEST_CUSTOM 8 |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
As I argued before, not necessary, just throw it away
include/openssl/evp.h
Outdated
@@ -1321,6 +1323,7 @@ void EVP_PKEY_asn1_set_security_bits(EVP_PKEY_ASN1_METHOD *ameth, | |||
* Method handles all operations: don't assume any digest related defaults. | |||
*/ | |||
# define EVP_PKEY_FLAG_SIGCTX_CUSTOM 4 | |||
/* NOTE: 8 is reserved for internal usage in evp_int.h */ |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Remove this line
Document is updated to reflect the modification in this PR |
crypto/evp/pmeth_lib.c
Outdated
int (**pdigest_custom) (EVP_PKEY_CTX *ctx, | ||
EVP_MD_CTX *mctx)) | ||
{ | ||
if (*pdigest_custom) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
So that void *foo(EVP_PKEY_METHOD *pmeth) { void *p; EVP_PKEY_meth_get_digest_custom(pmeth, &p); return p; }
might return sensible or garbage value. But even if corrected, the check is arguably inappropriate. In sense that it's more appropriate to punish caller with crash if programmer didn't care to arrange proper location that would receive the value, than to let caller believe that everything is fine. "Is fine" means that there is no way of telling it's not fine.
The remark applies to multiple cases. [Which in turn effectively means review process failure.]
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
These checks exist in other (not all???) method function getters, but are implemented differently in some. I don't think it's a fix to do in this PR, but it would be good to clean this up.
In my opinion, the check should be this:
if (pdigest_custom)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I agree to the form that Richard suggested
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I don't think it's a fix to do in this PR,
So suggestion is to perpetuate bugs?
but it would be good to clean this up.
??? "Good" to "clean up"? It's not something that would be "good to do". They are bugs that has to be fixed.
the check should be this:
It's equivalent to demanding NULL-check in memcpy(NULL, p, 1).
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I opened an issue (#7130) to keep track of this.
doc/man3/EVP_PKEY_meth_new.pod
Outdated
@@ -334,6 +342,15 @@ key-pair, the public component and parameters respectively for a given B<pkey>. | |||
They could be called by L<EVP_PKEY_check(3)>, L<EVP_PKEY_public_check(3)> and | |||
L<EVP_PKEY_param_check(3)> respectively. | |||
|
|||
int (*digest_custom) (EVP_PKEY_CTX *ctx, EVP_MD_CTX *mctx); | |||
|
|||
The digest_custom() method is used to generate customzied degest content before |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
s/degest/digest/
Looking at this had me stumble on stuff I haven't looked at before, the custom |
@@ -460,6 +460,13 @@ EVP_PKEY_CTX *EVP_MD_CTX_pkey_ctx(const EVP_MD_CTX *ctx) | |||
return ctx->pctx; | |||
} | |||
|
|||
void EVP_MD_CTX_set_pkey_ctx(EVP_MD_CTX *ctx, EVP_PKEY_CTX *pctx) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Can this function be called with a NULL pctx (e.g. say if you want to clear one that was previously set)?
What should happen if ctx->pctx
is not NULL when this function is called?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Good question. TBH I didn't consider the 'set to NULL' or the 'clear' scenario. But after a quick thinking, I think it would be useful to allow users to set ctx->pctx
to NULL (for instance someone wants to reuse the MD_CTX). So the current implementation supports that already.
If ctx->pctx
is not NULL when this function is called, then I think it should be the user's responsibility to free the old pctx attached in MD_CTX, makes sense?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
If ctx->pctx is not NULL when this function is called, then I think it should be the user's responsibility to free the old pctx attached in MD_CTX, makes sense?
Yes, if EVP_MD_CTX_FLAG_KEEP_PKEY_CTX
is set - but not otherwise.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Ahh, nah, the flag should also be cleared if the ctx->pctx
is set to NULL if someone wants to reuse the MD_CTX. So I think there should be a separated EVP_MD_CTX_clr_pkey_ctx` function to do this?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Or we could mix the set/clr behavior into one function by doing something like:
if (pctx == NULL) {
/* clear the flag... */
}
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Hmm..I'm not sure that is necessary. Surely all we need is something like this:
if (!EVP_MD_CTX_test_flags(ctx, EVP_MD_CTX_FLAG_KEEP_PKEY_CTX))
EVP_PKEY_CTX_free(ctx->pctx);
ctx->pctx = pctx;
if (pctx != NULL)
EVP_MD_CTX_set_flags(ctx, EVP_MD_CTX_FLAG_KEEP_PKEY_CTX);
else
EVP_MD_CTX_clear_flags(out, EVP_MD_CTX_FLAG_KEEP_PKEY_CTX);
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Okay, I get the point - It's complicated to deal with such stuffs: one pointer holds two different memory management strategy objects...
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
In my experience, another way is to have two pointers containing system-created and user-created objects respectively - if the user-created on is used, the the system one will always be NULL. Thus it would make it simpler. But this time let's just mix them together
crypto/evp/m_sigver.c
Outdated
* This indicates the current algorithm requires | ||
* special treatment before hashing the tbs-message. | ||
*/ | ||
if (ctx->pctx->pmeth->digest_custom) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Add != NULL
crypto/evp/pmeth_lib.c
Outdated
int (**pdigest_custom) (EVP_PKEY_CTX *ctx, | ||
EVP_MD_CTX *mctx)) | ||
{ | ||
if (*pdigest_custom) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
!= NULL
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Facepalm.
crypto/sm2/sm2_pmeth.c
Outdated
case EVP_PKEY_CTRL_SET1_ID: | ||
OPENSSL_free(smctx->id); | ||
if (p1 > 0) { | ||
smctx->id = OPENSSL_malloc(p1); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Should we free any pre-existing id?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Ahh, you mean if malloc fails, then we should not touch the original previous set smctx->id
?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
No I mean if there was a pre-existing id then we just introduced a mem leak because we didn't free the old one. So I think you need to add OPENSSL_free(smctx->id);
before the malloc.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It seems that is already there. But I improved the logical to defer OPNESSL_free to a more suitable position in the new version of this function.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Duh...why did I not see that?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
;-)
doc/man3/EVP_DigestSignInit.pod
Outdated
@@ -31,6 +31,10 @@ B<*pctx> is overwritten. The EVP_PKEY_CTX value returned must not be freed | |||
directly by the application (it will be freed automatically when the EVP_MD_CTX | |||
is freed). The digest B<type> may be NULL if the signing algorithm supports it. | |||
|
|||
There is no B<EVP_PKEY_CTX> will be created by EVP_DigestSignInit() if the passed | |||
B<ctx> is already assigned with an B<EVP_PKEY_CTX>, take L<EVP_MD_CTX_set_pkey_ctx(3)> | |||
and L<SM2(7)> as references. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
"No B<EVP_PKEY_CTX> will be created by EVP_DigsetSignInit() if the passed B<ctx> has already been assigned one via L<EVP_MD_CTX_set_ctx(3)>. See also L<SM2(7)>."
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Oh...but wait...there is no SM2(7)!? There probably needs to be something (maybe not in this PR) - otherwise how will people know about the special hoops they need to jump through to be able to use SM2?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
In fact I forgot to include that SM2(7)... I used 'git add -u' so the new SM2.pod file is left on my disk...now added
doc/man3/EVP_PKEY_CTX_ctrl.pod
Outdated
are used to manipulate special identifier field for specific signature algorithm | ||
such as SM2. The EVP_PKEY_CTX_get1_id_len() returns the length of the ID set in | ||
algorihtm related context. The length is usually used to allocate adequate memory | ||
for further calls to EVP_PKEY_CTX_get1_id(). |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
There is no description here of how EVP_PKEY_CTX_set1_id() and EVP_PKEY_get1_id() actually work and what the parameters mean. There should at least be a sentence about the memory management aspects I think.
doc/man3/EVP_PKEY_CTX_ctrl.pod
Outdated
@@ -179,7 +191,8 @@ L<EVP_PKEY_keygen(3)> | |||
|
|||
=head1 HISTORY | |||
|
|||
These functions were first added to OpenSSL 1.0.0. | |||
EVP_PKEY_CTX_set1_id(), EVP_PKEY_CTX_get1_id() and EVP_PKEY_CTX_get1_id_len() are | |||
added in 1.1.1, other functions were first added to OpenSSL 1.0.0. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
s/are added/were added/
doc/man3/EVP_PKEY_meth_new.pod
Outdated
@@ -334,6 +342,15 @@ key-pair, the public component and parameters respectively for a given B<pkey>. | |||
They could be called by L<EVP_PKEY_check(3)>, L<EVP_PKEY_public_check(3)> and | |||
L<EVP_PKEY_param_check(3)> respectively. | |||
|
|||
int (*digest_custom) (EVP_PKEY_CTX *ctx, EVP_MD_CTX *mctx); | |||
|
|||
The digest_custom() method is used to generate customzied degest content before |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
typo: customized
doc/man3/EVP_PKEY_meth_new.pod
Outdated
the real message is passed to functions like L<EVP_DigestSignUpdate(3)> or | ||
L<EVP_DigestVerifyInit(3)>. This is usually required by some public key | ||
signature algorithms like SM2 which requires a hashed prefix to the message to | ||
be signed. The digest_custom() could be called by L<EVP_DigestSignInit(3)> and |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
s/could/will/ ?
crypto/sm2/sm2_pmeth.c
Outdated
* NULL is allowed. We only allow it if set explicitly for maximum | ||
* flexibility. | ||
*/ | ||
return 0; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Probably there needs to be a call to SM2err here.
The real difference is the position of triggering for signctx (or other function pointers) and digest_custom. Actually we need a calling point right after the 'digest' is initialized and before the 'DigestSign/Verify' is initialized. There is no such thing yet, which makes it's very hard to be fit in some scenarios... |
I forgot to include a man(7) page of SM2, now updated... |
Good, so you looked at least. I gotta admit, signctx is new to me, and seems to have multiple applications (depending on the flag It does worry me, though, that we seems to add more hooks for almost, but not quite the same the same things. I guess that's a future clean-up job 😉 |
Right. The concept behind this is the 'calling points' for these hooks should be considered and defined carefully and precisely. A very challenging job to design a decent framework as current EVP... |
crypto/sm2/sm2_pmeth.c
Outdated
if (sctx->id != NULL) { | ||
dctx->id = OPENSSL_malloc(sctx->id_len); | ||
if (dctx->id == NULL) { | ||
pkey_sm2_cleanup(dst); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This looks like it is missing an SM2err(SM2_F_PKEY_SM2_COPY, ERR_R_MALLOC_FAILURE) call ... for consistency with the other error handling.
crypto/sm2/sm2_pmeth.c
Outdated
if (p1 > 0) { | ||
tmp_id = OPENSSL_malloc(p1); | ||
if (tmp_id == NULL) | ||
return 0; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This looks like it is missing an SM2err(SM2_F_PKEY_SM2_CTRL, ERR_R_MALLOC_FAILURE) call ... for consistency with the other error handling.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Once you have added the SM2err calls for malloc failures and fixed the typo in the SM2.pod file this is good to go.
doc/man7/SM2.pod
Outdated
|
||
B<SM2> algorithm is first defined by the Chinese national standard GM/T 0003-2012 | ||
and is standardized by ISO as ISO/IEC 14888. B<SM2> is actually an elliptic curve | ||
based algorithm. Currnet implementation in OpenSSL supports both signature and |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Currnet -> The current
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
LGTM
Oops, a nit is fixed |
Travis failures are not related. Force a push to re-trigger it... |
There is adequate approvals for merging this PR. I would squash and cleanup the commits soon. |
I squashed the commits into proper styles - no actual code modified after the 'ready' label is assigned so I don't think this needs to re-approve for the approval by Tim |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Lots of comments but I think they're all minor nits in the documentation which should be easy to fix. This looks almost ready.
doc/man3/EVP_PKEY_CTX_ctrl.pod
Outdated
@@ -160,6 +166,17 @@ For maximum compatibility the named curve form should be used. Note: the | |||
B<OPENSSL_EC_NAMED_CURVE> value was only added to OpenSSL 1.1.0; previous | |||
versions should use 0 instead. | |||
|
|||
The EVP_PKEY_CTX_set1_id(), EVP_PKEY_CTX_get1_id() and EVP_PKEY_CTX_get1_id_len() | |||
are used to manipulate special identifier field for specific signature algorithm |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Nit: manipulate the special identifier field
Nit: for specific signature algorithms
doc/man3/EVP_DigestInit.pod
Outdated
Assigns an B<EVP_PKEY_CTX> to B<EVP_MD_CTX>. This is usually used to provide | ||
a customzied B<EVP_PKEY_CTX> to L<EVP_DigestSignInit(3)> or | ||
L<EVP_DigestVerifyInit(3)>. The B<pctx> passed to this function should be freed | ||
by the caller. A null B<pctx> pointer is also allowed to clear the B<EVP_PKEY_CTX> |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Nit: s/null/NULL/
doc/man3/EVP_PKEY_CTX_ctrl.pod
Outdated
such as SM2. The EVP_PKEY_set1_id() sets an ID pointed by B<id> with the length | ||
B<id_len> to the library. The library maintains the memory management stuffs so | ||
the caller can safely free the original memory pointed by B<id>. The | ||
EVP_PKEY_CTX_get1_id_len() returns the length of the ID set via a previous call |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
insert the word "macro" before "returns"
doc/man3/EVP_PKEY_CTX_ctrl.pod
Outdated
B<id_len> to the library. The library maintains the memory management stuffs so | ||
the caller can safely free the original memory pointed by B<id>. The | ||
EVP_PKEY_CTX_get1_id_len() returns the length of the ID set via a previous call | ||
to EVP_PKEY_set1_id(). The length is usually used to allocate adequate memory for |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Typo: EVP_PKEY_CTX_set1_id()
doc/man3/EVP_PKEY_CTX_ctrl.pod
Outdated
the caller can safely free the original memory pointed by B<id>. The | ||
EVP_PKEY_CTX_get1_id_len() returns the length of the ID set via a previous call | ||
to EVP_PKEY_set1_id(). The length is usually used to allocate adequate memory for | ||
further calls to EVP_PKEY_CTX_get1_id(). The EVP_PKEY_CTX_get1_id() returns the |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Insert the word "macro" before "returns"
doc/man7/SM2.pod
Outdated
|
||
EVP_MD_CTX_set_pkey_ctx(mctx, pctx); | ||
|
||
And normally there is no need to pass a B<pctx> parameter to EVP_DeigestSignInit() |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Typo: EVP_DigestSignInit()
doc/man7/SM2.pod
Outdated
EVP_MD_CTX_set_pkey_ctx(mctx, pctx); | ||
|
||
And normally there is no need to pass a B<pctx> parameter to EVP_DeigestSignInit() | ||
or EVP_DigestVerifyInit() in such scenario. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
such a scenario
doc/man7/SM2.pod
Outdated
|
||
=head1 EXAMPLE | ||
|
||
This example demonstrates the calling sequence on how to use an B<EVP_PKEY> to |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
calling sequence for using an B<EVP_PKEY>...
doc/man7/SM2.pod
Outdated
=head1 EXAMPLE | ||
|
||
This example demonstrates the calling sequence on how to use an B<EVP_PKEY> to | ||
sign a message with SM2 signature algorithm and SM3 hash algorithm: |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
with the SM2....and the SM3
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Perhaps add this sentence. "The example below omits error checking code for clarity. Application code should check the return codes of function calls for errors."
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The text above says this is an example for signing. But actually its an example for verifying a signature.
doc/man7/SM2.pod
Outdated
|
||
#include <openssl/evp.h> | ||
|
||
/* obtain an EVP_PKEY from whatever methods... */ |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
using whatever method
Sounds like things here moved much, much faster here compared to at #6757 . Our unfamiliarity with OpenSSL internals is apparent. Happy to see this merged with appropriate attribution. Thanks @InfoHunter ! |
Approval still stands after @mattcaswell suggested doc changes applied. |
Doc nits are all fixed |
@mattcaswell , it seems I could merge this now, right? |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Sorry a few more nits. Approved assuming you fix those.
doc/man3/EVP_PKEY_CTX_ctrl.pod
Outdated
@@ -160,6 +166,17 @@ For maximum compatibility the named curve form should be used. Note: the | |||
B<OPENSSL_EC_NAMED_CURVE> value was only added to OpenSSL 1.1.0; previous | |||
versions should use 0 instead. | |||
|
|||
The EVP_PKEY_CTX_set1_id(), EVP_PKEY_CTX_get1_id() and EVP_PKEY_CTX_get1_id_len() | |||
are used to manipulate the special identifier field for specific signature |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Insert the word "macros" before "are used"
doc/man3/EVP_PKEY_CTX_ctrl.pod
Outdated
@@ -160,6 +166,17 @@ For maximum compatibility the named curve form should be used. Note: the | |||
B<OPENSSL_EC_NAMED_CURVE> value was only added to OpenSSL 1.1.0; previous | |||
versions should use 0 instead. | |||
|
|||
The EVP_PKEY_CTX_set1_id(), EVP_PKEY_CTX_get1_id() and EVP_PKEY_CTX_get1_id_len() | |||
are used to manipulate the special identifier field for specific signature | |||
algorithms such as SM2. The EVP_PKEY_set1_id() sets an ID pointed by B<id> with |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Typo: EVP_PKEY_CTX_set1_id()
doc/man3/EVP_PKEY_CTX_ctrl.pod
Outdated
are used to manipulate the special identifier field for specific signature | ||
algorithms such as SM2. The EVP_PKEY_set1_id() sets an ID pointed by B<id> with | ||
the length B<id_len> to the library. The library maintains the memory management | ||
stuffs so the caller can safely free the original memory pointed by B<id>. The |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Change this to "The library takes a copy of the id so that the caller can safely free the original memory pointed to by B<id>"
doc/man3/EVP_PKEY_CTX_ctrl.pod
Outdated
EVP_PKEY_CTX_get1_id_len() macro returns the length of the ID set via a previous | ||
call to EVP_PKEY_CTX_set1_id(). The length is usually used to allocate adequate | ||
memory for further calls to EVP_PKEY_CTX_get1_id(). The EVP_PKEY_CTX_get1_id() | ||
macro returns the previously set ID value to caller into B<id>, caller should |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
to the caller in B<id>. The caller should...
doc/man7/SM2.pod
Outdated
signature. | ||
|
||
The B<EVP_PKEY> structure will default to using ECDSA for signatures when it is | ||
created. Itshould be set to B<EVP_PKEY_SM2> by calling: |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
typo: missing space "It should"
doc/man7/SM2.pod
Outdated
|
||
EVP_PKEY_CTX_set1_id(pctx, id, id_len); | ||
|
||
When calling the EVP_DeigestSignInit() or EVP_DigestVerifyInit() functions, a |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Typo: EVP_DigestSignInit(()
doc/man7/SM2.pod
Outdated
|
||
=head1 EXAMPLE | ||
|
||
This example demonstrates the calling sequence for using an B<EVP_PKEY> to sign |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
s/sign/verify/
Reviewed-by: Tim Hudson <tjh@openssl.org> Reviewed-by: Matt Caswell <matt@openssl.org> (Merged from #7113)
Thus users can use this function to set customized EVP_PKEY_CTX to EVP_MD_CTX structure. Reviewed-by: Tim Hudson <tjh@openssl.org> Reviewed-by: Matt Caswell <matt@openssl.org> (Merged from #7113)
Reviewed-by: Tim Hudson <tjh@openssl.org> Reviewed-by: Matt Caswell <matt@openssl.org> (Merged from #7113)
Reviewed-by: Tim Hudson <tjh@openssl.org> Reviewed-by: Matt Caswell <matt@openssl.org> (Merged from #7113)
This test case is originally submitted in #6757, by Jack Lloyd. The test case has been modified to use the a different method to set the ID when computing the Z hash of SM2 signature. Reviewed-by: Tim Hudson <tjh@openssl.org> Reviewed-by: Matt Caswell <matt@openssl.org> Reviewed-by: Paul Yang <yang.yang@baishancloud.com> (Merged from #7113)
Reviewed-by: Tim Hudson <tjh@openssl.org> Reviewed-by: Matt Caswell <matt@openssl.org> (Merged from #7113)
Reviewed-by: Tim Hudson <tjh@openssl.org> Reviewed-by: Matt Caswell <matt@openssl.org> (Merged from #7113)
Reviewed-by: Tim Hudson <tjh@openssl.org> Reviewed-by: Matt Caswell <matt@openssl.org> (Merged from #7113)
Reviewed-by: Tim Hudson <tjh@openssl.org> Reviewed-by: Matt Caswell <matt@openssl.org> (Merged from #7113)
This is an alternative to #6757 , to fix some SM2 ID relevant issues. Comments are very appreciated.
The idea in this PR is:
EVP_DigestSign/VerifyInit
. Introduce a method to pass anEVP_PKEY_CTX
to MD and make it configurable before callingEVP_DigestSign/VerifyInit
, so the current sequence of calls is something as follows:Document is not updated and test cases are not complete, if this concept is accepted then it should be very easy to complete them.
I borrowed some test code from #6757 to test the correctness of the ID involved signature verification process.
Actually there is another much simpler way of doing this, by using the EVP_ctrl stuffs to set the ID and compute the 'Z' digest after the calls to
EVP_DigestSign/VerifyInit
. But that will cut the whole algorithm into separated parts so I finally abandoned that idea.Checklist