Skip to content

Improve parameter handling in ext/openssl #6025

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

Closed
wants to merge 4 commits into from

Conversation

kocsismate
Copy link
Member

@kocsismate kocsismate commented Aug 20, 2020

This PR:

  • gets rid of the UNKNOWN default values
  • improves parameter names
  • uses string|int ZPP when possible
  • promotes a warning to an exception that was missed previously
  • adapts a few error messages to the new parameter names

@kocsismate kocsismate marked this pull request as draft August 20, 2020 14:06
@kocsismate kocsismate force-pushed the openssl-param-handling branch 6 times, most recently from ef48987 to 3399178 Compare August 20, 2020 18:22
@kocsismate kocsismate marked this pull request as ready for review August 20, 2020 18:22
@kocsismate kocsismate requested a review from bukka August 20, 2020 18:22
@kocsismate
Copy link
Member Author

@bukka Can you please have a look at this PR, especially at the parameter names? There are quite a few cases where I'm not very confident, so please take the current names just as a starting point.

*/
function openssl_pkey_export($key, &$out, ?string $passphrase = null, ?array $configargs = null): bool {}
function openssl_pkey_export($private_key, &$output, ?string $passphrase = null, ?array $options = null): bool {}
Copy link
Member

@bukka bukka Aug 22, 2020

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

isn't this working for public_key as well? Maybe we should just call it pkey in the same way as it's called internally and in openssl.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

According to the php_openssl_pkey_from_zval(zpkey, 0, passphrase, passphrase_len); invocation, it isn't. But I'll double check it.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes, even in the ext/openssl/tests/openssl_pkey_export_basic.phpt test, a public key is used with openssl_pkey_get_details()

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ok I see it in the code but it's a bit artificial as it could be possible to extend it and support pubkey using PEM_write_bio_PUBKEY. Then the name wouldn't be correct and we couldn't easily change it. As pkey is already in the function name, I think it should be fine to rename the argument to pkey. It should be done for other cases as well.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think this is the last remaining (important) question. @nikic Do you have any preference? To be honest, I don't like the pkey name at all, because it made me google for quite long whether it refers to a private or a public key when I was working on the resource migration. :( So I'd favor a $key, $asymmetric_key name if we really want to support public keys too.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Just $key sounds reasonable to me here. But really, no particular preference. I do think we should use $public_key and $private_key in the APIs that only accept one of them.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I went with $key in case of openssl_pkey_export() and openssl_pkey_export_to_file() to be a bit more forward-compatible :)

@kocsismate kocsismate force-pushed the openssl-param-handling branch 2 times, most recently from 87c9016 to ec9c9ea Compare August 25, 2020 08:15
@kocsismate kocsismate force-pushed the openssl-param-handling branch 2 times, most recently from 9f4874b to 33343b3 Compare September 8, 2020 19:27
@kocsismate kocsismate force-pushed the openssl-param-handling branch from 33343b3 to 69366ac Compare September 8, 2020 21:35
Copy link
Member

@nikic nikic left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The code changes look good, the parameter names have too few abbreviations :P

@@ -7296,7 +7292,7 @@ PHP_FUNCTION(openssl_decrypt)
size_t data_len, method_len, password_len, iv_len = 0, tag_len = 0, aad_len = 0;
zend_string *ret;

if (zend_parse_parameters(ZEND_NUM_ARGS(), "sss|lsss", &data, &data_len, &method, &method_len,
if (zend_parse_parameters(ZEND_NUM_ARGS(), "sss|lss!s", &data, &data_len, &method, &method_len,
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is it possible to use $tag = "" instead?

Copy link
Member Author

@kocsismate kocsismate Sep 9, 2020

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes, it is, based on } else if (!enc && tag && tag_len > 0) { in php_openssl_cipher_init().

*/
function openssl_seal(string $data, &$sealdata, &$ekeys, array $pubkeys, string $method, &$iv = UNKNOWN): int|false {}
function openssl_seal(string $data, &$sealed_data, &$encrypted_keys, array $public_key, string $cipher_algorithm, &$initialization_vector = null): int|false {}
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
function openssl_seal(string $data, &$sealed_data, &$encrypted_keys, array $public_key, string $cipher_algorithm, &$initialization_vector = null): int|false {}
function openssl_seal(string $data, &$sealed_data, &$encrypted_keys, array $public_key, string $cipher_algorithm, &$iv = null): int|false {}

IV is typically not spelled out.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I don't feel particularly strongly about this one though. Maybe @bukka has a preference.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes this should be changed to iv

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'll do it soon

@kocsismate kocsismate force-pushed the openssl-param-handling branch from e17d3a4 to f96620d Compare September 10, 2020 11:51
Copy link
Member

@nikic nikic left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This looks good to me. Any further comments from @bukka?

@@ -4847,7 +4849,7 @@ PHP_FUNCTION(openssl_pkcs7_verify)

RETVAL_LONG(-1);

if (zend_parse_parameters(ZEND_NUM_ARGS(), "pl|pappp", &filename, &filename_len,
if (zend_parse_parameters(ZEND_NUM_ARGS(), "pl|p!a!p!p!p!", &filename, &filename_len,
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

As far as I can see $cainfo = [] should work.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Though looking at other signatures, I see that this parameter is declared as ?array in other cases, so this makes sense for consistency. Though the default is sometimes null and sometimes []...

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

You are right, so I'll change the default value of all of them to [].

@php-pulls php-pulls closed this in e8e4ddc Sep 12, 2020
@kocsismate kocsismate deleted the openssl-param-handling branch September 12, 2020 20:13
/** @param OpenSSLAsymmetricKey $privkey */
function openssl_csr_new(array $dn, &$privkey, ?array $configargs = null, ?array $extraattribs = null): OpenSSLCertificateSigningRequest|false {}
/** @param OpenSSLAsymmetricKey $private_key */
function openssl_csr_new(array $distinguished_names, &$private_key, ?array $options = null, ?array $extra_options = null): OpenSSLCertificateSigningRequest|false {}
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

So in this case, we are really talking about extra attributes (not options) because those are CSR attributes.


function openssl_pkcs7_verify(string $filename, int $flags, string $signerscerts = UNKNOWN, array $cainfo = UNKNOWN, string $extracerts = UNKNOWN, string $content = UNKNOWN, string $pk7 = UNKNOWN): bool|int {}
function openssl_pkcs7_verify(string $filename, int $flags, ?string $output_filename = null, array $ca_info = [], ?string $untrusted_certificates_filename = null, ?string $content = null, ?string $pk7_filename = null): bool|int {}
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

If you are already changing that parameter, then pk7 is of course incorrect as it doesn't mean anything. It should be pkcs7_filename

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

From the really quick look I'm not 100% sure what's the use case of that param. It's a bit confusing because output_filename is not really right name here. It should be probably called signers_certificates_filename and the last one should be probably pkcs7_output_filename. Although it's a bit inconsistent with other naming.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

also first param should be then pkcs7_input_filename which will make it a bit more consistent.

/** @param OpenSSLCertificate|array|string $recipcerts */
function openssl_pkcs7_encrypt(string $infile, string $outfile, $recipcerts, ?array $headers, int $flags = 0, int $cipher = OPENSSL_CIPHER_RC2_40): bool {}
/** @param OpenSSLCertificate|array|string $certificate */
function openssl_pkcs7_encrypt(string $filename, string $output_filename, $certificate, ?array $headers, int $flags = 0, int $cipher_algorithm = OPENSSL_CIPHER_RC2_40): bool {}
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Maybe we should make clear what's pkcs7 and name output_filename as pkcs7_output_filename. The first param should be input_filename then.

/** @param OpenSSLAsymmetricKey|OpenSSLCertificate|array|string $signkey */
function openssl_pkcs7_sign(string $infile, string $outfile, OpenSSLCertificate|string $signcert, $signkey, ?array $headers, int $flags = PKCS7_DETACHED, ?string $extracertsfilename = null): bool {}
/** @param OpenSSLAsymmetricKey|OpenSSLCertificate|array|string $private_key */
function openssl_pkcs7_sign(string $filename, string $output_filename, OpenSSLCertificate|string $certificate, $private_key, ?array $headers, int $flags = PKCS7_DETACHED, ?string $untrusted_certificates_filename = null): bool {}
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Here again input_filename and then pkcs7_output_filename

*/
function openssl_pkcs7_decrypt(string $infilename, string $outfilename, $recipcert, $recipkey = null): bool {}
function openssl_pkcs7_decrypt(string $filename, string $output_filename, $certificate, $private_key = null): bool {}
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

pkcs7_input_filename

/** @param array $certs */
function openssl_pkcs7_read(string $infilename, &$certs): bool {}
/** @param array $certificates */
function openssl_pkcs7_read(string $filename, &$certificates): bool {}
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

pkcs7_input_filename

Comment on lines -128 to +140
function openssl_cms_verify(string $filename, int $flags = 0, ?string $signerscerts = null, ?array $cainfo = null, ?string $extracerts = null, ?string $content = null, ?string $pk7 = null, ?string $sigfile = null, int $encoding = OPENSSL_ENCODING_SMIME): bool {}
function openssl_cms_verify(string $filename, int $flags = 0, ?string $certificates = null, array $ca_info = [], ?string $untrusted_certificates_filename = null, ?string $content = null, ?string $pk7 = null, ?string $sigfile = null, int $encoding = OPENSSL_ENCODING_SMIME): bool {}

/** @param OpenSSLCertificate|array|string $recipcerts */
function openssl_cms_encrypt(string $infile, string $outfile, $recipcerts, ?array $headers, int $flags = 0, int $encoding = OPENSSL_ENCODING_SMIME, int $cipher = OPENSSL_CIPHER_RC2_40): bool {}
/** @param OpenSSLCertificate|array|string $certificate */
function openssl_cms_encrypt(string $filename, string $output_filename, $certificate, ?array $headers, int $flags = 0, int $encoding = OPENSSL_ENCODING_SMIME, int $cipher_algorithm = OPENSSL_CIPHER_RC2_40): bool {}

/** @param OpenSSLAsymmetricKey|OpenSSLCertificate|array|string $signkey */
function openssl_cms_sign(string $infile, string $outfile, OpenSSLCertificate|string $signcert, $signkey, ?array $headers, int $flags = 0, int $encoding = OPENSSL_ENCODING_SMIME, ?string $extracertsfilename = null): bool {}
/** @param OpenSSLAsymmetricKey|OpenSSLCertificate|array|string $private_key */
function openssl_cms_sign(string $filename, string $output_filename, OpenSSLCertificate|string $certificate, $private_key, ?array $headers, int $flags = 0, int $encoding = OPENSSL_ENCODING_SMIME, ?string $untrusted_certificates_filename = null): bool {}

/**
* @param OpenSSLCertificate|string $recipcert
* @param OpenSSLAsymmetricKey|OpenSSLCertificate|array|string $recipkey
* @param OpenSSLCertificate|string $certificate
* @param OpenSSLAsymmetricKey|OpenSSLCertificate|array|string|null $private_key
*/
function openssl_cms_decrypt(string $infilename, string $outfilename, $recipcert, $recipkey = UNKNOWN, int $encoding = OPENSSL_ENCODING_SMIME): bool {}
function openssl_cms_decrypt(string $filename, string $output_filename, $certificate, $private_key = null, int $encoding = OPENSSL_ENCODING_SMIME): bool {}

/** @param array $certs */
function openssl_cms_read(string $infilename, &$certs): bool {}
/** @param array $certificates */
function openssl_cms_read(string $filename, &$certificates): bool {}
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

basically the same names like for pkcs7 but using cms instead.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Do adding the pkcs7 and cms prefixes make the meaning of $input_filename/$output_filename more clear?

*/
function openssl_open(string $data, &$opendata, string $ekey, $privkey, string $method, string $iv = UNKNOWN): bool {}
function openssl_open(string $data, &$output, string $encrypted_key, $private_key, string $cipher_algorithm, ?string $initialization_vector = null): bool {}
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

iv should be used


/** @param string $tag */
function openssl_encrypt(string $data, string $method, string $password, int $options = 0, string $iv = '', &$tag = UNKNOWN, string $aad = '', int $tag_length = 16): string|false {}
function openssl_encrypt(string $data, string $cipher_algorithm, string $passphrase, int $options = 0, string $initialization_vector = "", &$tag = null, string $additional_authentication_data = "", int $tag_length = 16): string|false {}
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

please use iv and aad as they are standard terms.


function openssl_decrypt(string $data, string $method, string $password, int $options = 0, string $iv = '', string $tag = UNKNOWN, string $aad = ''): string|false {}
function openssl_decrypt(string $data, string $cipher_algorithm, string $passphrase, int $options = 0, string $initialization_vector = "", string $tag = "", string $additional_authentication_data = ""): string|false {}
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

please use iv and aad as they are standard terms.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm waiting for the end of your review, and commit the changes together.

@bukka
Copy link
Member

bukka commented Sep 12, 2020

@kocsismate Nice work in general but this still needs some additional changes. Please let me know if you are able to create a PR or if I need to do that.

@kocsismate
Copy link
Member Author

@bukka I can create one!

@bukka
Copy link
Member

bukka commented Sep 12, 2020

Nice thanks

*/
function openssl_private_decrypt(string $data, &$crypted, $key, int $padding = OPENSSL_PKCS1_PADDING): bool {}
function openssl_private_decrypt(string $data, &$encrypted_data, $private_key, int $padding = OPENSSL_PKCS1_PADDING): bool {}
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is really other way round. First param is from (encrypted data) and the second param is to which is decrypted data. If you want to keep first as data, then the second one should be decrypted_data.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Oops, it's very fortunate that you had another look :) Thank you!

*/
function openssl_public_decrypt(string $data, &$crypted, $key, int $padding = OPENSSL_PKCS1_PADDING): bool {}
function openssl_public_decrypt(string $data, &$encrypted_data, $public_key, int $padding = OPENSSL_PKCS1_PADDING): bool {}
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Again the second one should be decrypted_data

@bukka
Copy link
Member

bukka commented Sep 12, 2020

@kocsismate I think that's everything for today. It's a bit hard to get the correct naming as even the names in C code are a bit confusing. Will take another look when you create the next PR.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

4 participants