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
ECDH and DH secret derivation: openssl_pkey_derive() #3197
Conversation
commercebyte
commented
Mar 26, 2018
string openssl_dh_compute_key(resource ec_pub_key,resource ec_priv_key) [new] string openssl_dh_compute_key(resource dh_pub_key,resource dh_priv_key) [new] string openssl_dh_compute_key(string dh_pub,resource dh_priv_key) [original]
Apparently, this does not compile on Windows, see https://ci.appveyor.com/project/php/php-src/build/master.build.6583/job/72ja8je11sgdwbut#L2529. |
/cc @bukka |
@cmb69 thanks for the heads up - fixed |
First of all, thanks for the PR! There are couple of things:
|
Alternatively possibly even better solution would to do it on EVP level and use EVP_PKEY_derive. It means introducing something like |
@bukka The latter definitely makes sense. Just an observation - when the optional keylen argument is supplied and is less then the maximum secret length, ECDH truncates the derived secret, while DH fails. It appears to be the normal behavior of the openssl lib. |
ext/openssl/openssl.c
Outdated
if (zend_parse_parameters(ZEND_NUM_ARGS(), "rr|l", &peer_pub_key, &priv_key, &keylen) == FAILURE) { | ||
return; | ||
} | ||
if ((pkey = (EVP_PKEY *)zend_fetch_resource(Z_RES_P(priv_key), "OpenSSL key", le_key)) == 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.
To be a bit more flexible and consistent with other functions in openssl ext, it might be better to fetch it using php_openssl_evp_from_zval and changing ZPP to "zz|l".
ext/openssl/openssl.c
Outdated
if (!ctx) RETURN_FALSE; | ||
if (EVP_PKEY_derive_init(ctx) > 0 | ||
&& EVP_PKEY_derive_set_peer(ctx, peer_key) > 0 | ||
&& (keylen > 0 || EVP_PKEY_derive(ctx, NULL, &keylen) > 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.
we should probably check keylen
before and warn if it's negative.
ext/openssl/openssl.c
Outdated
RETURN_FALSE; | ||
} | ||
EVP_PKEY_CTX *ctx = EVP_PKEY_CTX_new(pkey, NULL); | ||
if (!ctx) RETURN_FALSE; |
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.
CS:
if (!ctx) {
RETURN_FALSE;
}
ext/openssl/openssl.c
Outdated
EVP_PKEY_CTX *ctx = EVP_PKEY_CTX_new(pkey, NULL); | ||
if (!ctx) RETURN_FALSE; | ||
if (EVP_PKEY_derive_init(ctx) > 0 | ||
&& EVP_PKEY_derive_set_peer(ctx, peer_key) > 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.
NIT CS: usually tab should used for indent of &&
on the next line
if (EVP_PKEY_derive_init(ctx) > 0
&& EVP_PKEY_derive_set_peer(ctx, peer_key) > 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.
@bukka Thanks for the feedback!
As for padding for a wrapped line - wanted to make it distinct from the padding on the following block,
changed to tabs now as it's consistent with other places in the code
It looks good! Just added couple of comments about minor things.. About the name I would really prefer |
@bukka Looks like everything's good, Note - The function does not accept two private keys anymore, because of the way php_openssl_evp_from_zval() works. It should not be a problem because deriving a secret from 2 private keys is not a normal use case, one of the private keys can be explicitly converted to public |
ext/openssl/openssl.c
Outdated
if (keylen < 0) { | ||
php_error_docref(NULL, E_WARNING, "keylen < 0, assuming NULL"); | ||
} | ||
if ((pkey = php_openssl_evp_from_zval(priv_key,0,"",0,0,NULL)) == 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.
NIT - CS: space after comma...
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.
Same for following line ;)
All looks good (just one small NIT)! As it's a new function, it would be good to message to internals mailing list. I don't think we need an RFC for this unless there are some objections. Are you ok to that (just a short description of the function and link to the PR should be enough)? |
@commercebyte Just wanted to check if you are ok to message internals or if you want me to do it? I'm happy to do that if you want. |
@bukka Sorry but it doesn't look like i have a post permission for http://news.php.net/php.internals |
@commercebyte I think you would need to be subscribed to be able to post but not really sure. Anyway I just emailed the mailing lists which should fine: http://news.php.net/php.internals/102068 If no one objects and I don't forget (in that case please ping me :) ), I will merge it in the next 2 weeks. Thanks |
Thank You @bukka ! The description of the function might've been lost in the thread conversation, let me summarize once again - string openssl_pkey_derive($peer_pub_key, $priv_key, int $keylen=NULL) Derives a negotiated secret- DH, ECDH, or any future algorithm supported by EVP_PKEY_derive() $peer_pub_key: peer's public key, string or resource (currently supported: DH or EC) $priv_key: owner's private key, string or resource (currently supported: DH or EC, with same domain parameters as $peer_pub_key) $keylen: requested length of the derived secret, NULL or 0 to use the default for the algorithm Returns: derived secret string, or false on error |
Nice work. Looking forward for this capability. Use official test vectors to test your code. https://csrc.nist.gov/csrc/media/projects/cryptographic-algorithm-validation-program/documents/components/ecccdhtestvectors.zip for ECDH. Example: https://3v4l.org/DsrpG And for DH: https://csrc.nist.gov/projects/cryptographic-algorithm-validation-program/key-management#Testing |
Comment on behalf of bukka at php.net: Merged via 897133f |
@commercebyte I have just tested and merged it. Just one small thing with arginfo that I fixed. Otherwise all seems good! Thanks for you work! @dol That would be really cool to add! I merged it with the supplied test as I don't want to have it as a requirement for the PR but if you or someone has time to create a PR, will be more than happy to merge it ;) |
@@ -1,7 +1,7 @@ | |||
--TEST-- | |||
openssl_*() with OPENSSL_KEYTYPE_EC | |||
--SKIPIF-- | |||
<?php if (!extension_loaded("openssl") && !defined("OPENSSL_KEYTYPE_EC")) print "skip"; ?> | |||
<?php if (!extension_loaded("openssl") || !defined("OPENSSL_KEYTYPE_EC")) print "skip"; ?> |
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.
Thanks for fixing this. Was introduced 2 years ago. 9688138#diff-a2ffa4ffa39980a4fe2fb9a7cb455e6eR4 ;-)
@bukka Not sure I find time. But I add it to my todo list. |