mirror of
https://github.com/php/php-src.git
synced 2025-08-15 13:38:49 +02:00
Implement #80495: Enable to set padding in openssl_(sign|verify)
This adds support for RSA PSS padding. Closes GH-19432
This commit is contained in:
parent
8f1a627e79
commit
702d18de99
7 changed files with 92 additions and 10 deletions
2
NEWS
2
NEWS
|
@ -32,6 +32,8 @@ PHP NEWS
|
|||
algorithms appears to be broken). (Jakub Zelenka)
|
||||
. The $key_length parameter for openssl_pkey_derive() has been deprecated.
|
||||
(Girgias)
|
||||
. Implement #80495 (Enable to set padding in openssl_(sign|verify).
|
||||
(Jakub Zelenka)
|
||||
|
||||
- PDO:
|
||||
. The "uri:" DSN scheme has been deprecated due to security concerns with
|
||||
|
|
|
@ -412,6 +412,8 @@ PHP 8.5 UPGRADE NOTES
|
|||
- OpenSSL:
|
||||
. openssl_public_encrypt() and openssl_private_decrypt() have new parameter
|
||||
$digest_algo that allows specifying hash digest algorithm for OEAP padding.
|
||||
. openssl_sign() and openssl_verify() have new parameter $padding to allow
|
||||
using more secure RSA PSS padding.
|
||||
|
||||
- PCNTL:
|
||||
. pcntl_exec() now has a formal return type of false.
|
||||
|
@ -664,6 +666,9 @@ PHP 8.5 UPGRADE NOTES
|
|||
. DECIMAL_COMPACT_SHORT.
|
||||
. DECIMAL_COMPACT_LONG.
|
||||
|
||||
- OpenSSL:
|
||||
. OPENSSL_PKCS1_PSS_PADDING
|
||||
|
||||
- POSIX:
|
||||
. POSIX_SC_OPEN_MAX.
|
||||
|
||||
|
|
|
@ -3997,6 +3997,30 @@ PHP_FUNCTION(openssl_error_string)
|
|||
}
|
||||
/* }}} */
|
||||
|
||||
static zend_result php_openssl_setup_rsa_padding(EVP_PKEY_CTX *pctx, EVP_PKEY *pkey, zend_long padding)
|
||||
{
|
||||
int key_type = EVP_PKEY_type(EVP_PKEY_id(pkey));
|
||||
|
||||
if (padding != 0) { // 0 = default/unspecified
|
||||
if (key_type != EVP_PKEY_RSA) {
|
||||
php_error_docref(NULL, E_WARNING, "Padding parameter is only supported for RSA keys");
|
||||
return FAILURE;
|
||||
}
|
||||
|
||||
if (padding == RSA_PKCS1_PSS_PADDING) {
|
||||
if (EVP_PKEY_CTX_set_rsa_padding(pctx, RSA_PKCS1_PSS_PADDING) <= 0) {
|
||||
php_openssl_store_errors();
|
||||
return FAILURE;
|
||||
}
|
||||
} else if (padding != RSA_PKCS1_PADDING) {
|
||||
php_error_docref(NULL, E_WARNING, "Unknown padding type");
|
||||
return FAILURE;
|
||||
}
|
||||
}
|
||||
|
||||
return SUCCESS;
|
||||
}
|
||||
|
||||
/* {{{ Signs data */
|
||||
PHP_FUNCTION(openssl_sign)
|
||||
{
|
||||
|
@ -4009,14 +4033,17 @@ PHP_FUNCTION(openssl_sign)
|
|||
zend_string *method_str = NULL;
|
||||
zend_long method_long = OPENSSL_ALGO_SHA1;
|
||||
const EVP_MD *mdtype;
|
||||
zend_long padding = 0;
|
||||
EVP_PKEY_CTX *pctx;
|
||||
bool can_default_digest = ZEND_THREEWAY_COMPARE(PHP_OPENSSL_API_VERSION, 0x30000) >= 0;
|
||||
|
||||
ZEND_PARSE_PARAMETERS_START(3, 4)
|
||||
ZEND_PARSE_PARAMETERS_START(3, 5)
|
||||
Z_PARAM_STRING(data, data_len)
|
||||
Z_PARAM_ZVAL(signature)
|
||||
Z_PARAM_ZVAL(key)
|
||||
Z_PARAM_OPTIONAL
|
||||
Z_PARAM_STR_OR_LONG(method_str, method_long)
|
||||
Z_PARAM_LONG(padding)
|
||||
ZEND_PARSE_PARAMETERS_END();
|
||||
|
||||
pkey = php_openssl_pkey_from_zval(key, 0, "", 0, 3);
|
||||
|
@ -4041,7 +4068,8 @@ PHP_FUNCTION(openssl_sign)
|
|||
md_ctx = EVP_MD_CTX_create();
|
||||
size_t siglen;
|
||||
if (md_ctx != NULL &&
|
||||
EVP_DigestSignInit(md_ctx, NULL, mdtype, NULL, pkey) &&
|
||||
EVP_DigestSignInit(md_ctx, &pctx, mdtype, NULL, pkey) &&
|
||||
php_openssl_setup_rsa_padding(pctx, pkey, padding) == SUCCESS &&
|
||||
EVP_DigestSign(md_ctx, NULL, &siglen, (unsigned char*)data, data_len) &&
|
||||
(sigbuf = zend_string_alloc(siglen, 0)) != NULL &&
|
||||
EVP_DigestSign(md_ctx, (unsigned char*)ZSTR_VAL(sigbuf), &siglen, (unsigned char*)data, data_len)) {
|
||||
|
@ -4074,14 +4102,17 @@ PHP_FUNCTION(openssl_verify)
|
|||
size_t signature_len;
|
||||
zend_string *method_str = NULL;
|
||||
zend_long method_long = OPENSSL_ALGO_SHA1;
|
||||
zend_long padding = 0;
|
||||
EVP_PKEY_CTX *pctx;
|
||||
bool can_default_digest = ZEND_THREEWAY_COMPARE(PHP_OPENSSL_API_VERSION, 0x30000) >= 0;
|
||||
|
||||
ZEND_PARSE_PARAMETERS_START(3, 4)
|
||||
ZEND_PARSE_PARAMETERS_START(3, 5)
|
||||
Z_PARAM_STRING(data, data_len)
|
||||
Z_PARAM_STRING(signature, signature_len)
|
||||
Z_PARAM_ZVAL(key)
|
||||
Z_PARAM_OPTIONAL
|
||||
Z_PARAM_STR_OR_LONG(method_str, method_long)
|
||||
Z_PARAM_LONG(padding)
|
||||
ZEND_PARSE_PARAMETERS_END();
|
||||
|
||||
PHP_OPENSSL_CHECK_SIZE_T_TO_UINT(signature_len, signature, 2);
|
||||
|
@ -4106,11 +4137,25 @@ PHP_FUNCTION(openssl_verify)
|
|||
}
|
||||
|
||||
md_ctx = EVP_MD_CTX_create();
|
||||
if (md_ctx == NULL ||
|
||||
!EVP_DigestVerifyInit(md_ctx, NULL, mdtype, NULL, pkey) ||
|
||||
(err = EVP_DigestVerify(md_ctx, (unsigned char *)signature, signature_len, (unsigned char*)data, data_len)) < 0) {
|
||||
if (md_ctx == NULL) {
|
||||
php_openssl_store_errors();
|
||||
err = -1;
|
||||
goto cleanup;
|
||||
}
|
||||
|
||||
if (!EVP_DigestVerifyInit(md_ctx, &pctx, mdtype, NULL, pkey) ||
|
||||
php_openssl_setup_rsa_padding(pctx, pkey, padding) == FAILURE) {
|
||||
php_openssl_store_errors();
|
||||
err = -1;
|
||||
goto cleanup;
|
||||
}
|
||||
|
||||
err = EVP_DigestVerify(md_ctx, (unsigned char *)signature, signature_len, (unsigned char*)data, data_len);
|
||||
if (err < 0) {
|
||||
php_openssl_store_errors();
|
||||
}
|
||||
|
||||
cleanup:
|
||||
EVP_MD_CTX_destroy(md_ctx);
|
||||
php_openssl_release_evp_md(mdtype);
|
||||
EVP_PKEY_free(pkey);
|
||||
|
|
|
@ -236,6 +236,11 @@ const OPENSSL_NO_PADDING = UNKNOWN;
|
|||
* @cvalue RSA_PKCS1_OAEP_PADDING
|
||||
*/
|
||||
const OPENSSL_PKCS1_OAEP_PADDING = UNKNOWN;
|
||||
/**
|
||||
* @var int
|
||||
* @cvalue RSA_PKCS1_PSS_PADDING
|
||||
*/
|
||||
const OPENSSL_PKCS1_PSS_PADDING = UNKNOWN;
|
||||
|
||||
/* Informational stream wrapper constants */
|
||||
|
||||
|
@ -595,10 +600,10 @@ function openssl_error_string(): string|false {}
|
|||
* @param string $signature
|
||||
* @param OpenSSLAsymmetricKey|OpenSSLCertificate|array|string $private_key
|
||||
*/
|
||||
function openssl_sign(string $data, &$signature, #[\SensitiveParameter] $private_key, string|int $algorithm = OPENSSL_ALGO_SHA1): bool {}
|
||||
function openssl_sign(string $data, &$signature, #[\SensitiveParameter] $private_key, string|int $algorithm = OPENSSL_ALGO_SHA1, int $padding = 0): bool {}
|
||||
|
||||
/** @param OpenSSLAsymmetricKey|OpenSSLCertificate|array|string $public_key */
|
||||
function openssl_verify(string $data, string $signature, $public_key, string|int $algorithm = OPENSSL_ALGO_SHA1): int|false {}
|
||||
function openssl_verify(string $data, string $signature, $public_key, string|int $algorithm = OPENSSL_ALGO_SHA1, int $padding = 0): int|false {}
|
||||
|
||||
/**
|
||||
* @param string $sealed_data
|
||||
|
|
5
ext/openssl/openssl_arginfo.h
generated
5
ext/openssl/openssl_arginfo.h
generated
|
@ -1,5 +1,5 @@
|
|||
/* This is a generated file, edit the .stub.php file instead.
|
||||
* Stub hash: 4186e01a05ec179f1f2196a2afd1860671f793d5 */
|
||||
* Stub hash: ff620528ee3035e295099637cc9f94b78a53416b */
|
||||
|
||||
ZEND_BEGIN_ARG_WITH_RETURN_TYPE_INFO_EX(arginfo_openssl_x509_export_to_file, 0, 2, _IS_BOOL, 0)
|
||||
ZEND_ARG_OBJ_TYPE_MASK(0, certificate, OpenSSLCertificate, MAY_BE_STRING, NULL)
|
||||
|
@ -284,6 +284,7 @@ ZEND_BEGIN_ARG_WITH_RETURN_TYPE_INFO_EX(arginfo_openssl_sign, 0, 3, _IS_BOOL, 0)
|
|||
ZEND_ARG_INFO(1, signature)
|
||||
ZEND_ARG_INFO(0, private_key)
|
||||
ZEND_ARG_TYPE_MASK(0, algorithm, MAY_BE_STRING|MAY_BE_LONG, "OPENSSL_ALGO_SHA1")
|
||||
ZEND_ARG_TYPE_INFO_WITH_DEFAULT_VALUE(0, padding, IS_LONG, 0, "0")
|
||||
ZEND_END_ARG_INFO()
|
||||
|
||||
ZEND_BEGIN_ARG_WITH_RETURN_TYPE_MASK_EX(arginfo_openssl_verify, 0, 3, MAY_BE_LONG|MAY_BE_FALSE)
|
||||
|
@ -291,6 +292,7 @@ ZEND_BEGIN_ARG_WITH_RETURN_TYPE_MASK_EX(arginfo_openssl_verify, 0, 3, MAY_BE_LON
|
|||
ZEND_ARG_TYPE_INFO(0, signature, IS_STRING, 0)
|
||||
ZEND_ARG_INFO(0, public_key)
|
||||
ZEND_ARG_TYPE_MASK(0, algorithm, MAY_BE_STRING|MAY_BE_LONG, "OPENSSL_ALGO_SHA1")
|
||||
ZEND_ARG_TYPE_INFO_WITH_DEFAULT_VALUE(0, padding, IS_LONG, 0, "0")
|
||||
ZEND_END_ARG_INFO()
|
||||
|
||||
ZEND_BEGIN_ARG_WITH_RETURN_TYPE_MASK_EX(arginfo_openssl_seal, 0, 5, MAY_BE_LONG|MAY_BE_FALSE)
|
||||
|
@ -599,6 +601,7 @@ static void register_openssl_symbols(int module_number)
|
|||
#endif
|
||||
REGISTER_LONG_CONSTANT("OPENSSL_NO_PADDING", RSA_NO_PADDING, CONST_PERSISTENT);
|
||||
REGISTER_LONG_CONSTANT("OPENSSL_PKCS1_OAEP_PADDING", RSA_PKCS1_OAEP_PADDING, CONST_PERSISTENT);
|
||||
REGISTER_LONG_CONSTANT("OPENSSL_PKCS1_PSS_PADDING", RSA_PKCS1_PSS_PADDING, CONST_PERSISTENT);
|
||||
REGISTER_STRING_CONSTANT("OPENSSL_DEFAULT_STREAM_CIPHERS", OPENSSL_DEFAULT_STREAM_CIPHERS, CONST_PERSISTENT);
|
||||
#if !defined(OPENSSL_NO_RC2)
|
||||
REGISTER_LONG_CONSTANT("OPENSSL_CIPHER_RC2_40", PHP_OPENSSL_CIPHER_RC2_40, CONST_PERSISTENT);
|
||||
|
|
|
@ -8,11 +8,27 @@ $data = "Testing openssl_sign()";
|
|||
$privkey = "file://" . __DIR__ . "/private_rsa_1024.key";
|
||||
$wrong = "wrong";
|
||||
|
||||
var_dump(openssl_sign($data, $sign, $privkey, OPENSSL_ALGO_SHA256)); // no output
|
||||
var_dump(openssl_sign($data, $sign1, $privkey, OPENSSL_ALGO_SHA256));
|
||||
var_dump(bin2hex($sign1));
|
||||
var_dump(openssl_sign($data, $sign2, $privkey, OPENSSL_ALGO_SHA256));
|
||||
var_dump($sign1 === $sign2);
|
||||
var_dump(openssl_sign($data, $sign1, $privkey, OPENSSL_ALGO_SHA256, OPENSSL_PKCS1_PSS_PADDING));
|
||||
var_dump(strlen($sign1));
|
||||
var_dump(openssl_sign($data, $sign2, $privkey, OPENSSL_ALGO_SHA256, OPENSSL_PKCS1_PSS_PADDING));
|
||||
var_dump(strlen($sign2));
|
||||
var_dump($sign1 === $sign2);
|
||||
var_dump(openssl_sign($data, $sign, $wrong));
|
||||
?>
|
||||
--EXPECTF--
|
||||
bool(true)
|
||||
string(256) "5eff033d92208fcbf52edc9cbf6c9d4bd7c06b7b5a6a22c7d641d1494a09d6b0898d321c0a8fdb55c10b9bf25c2bb777c2b4660f867001f79879d089de7321a28df5f037cc02b68c47d1eb28d98a9199876961adb02524a489872a12fd3675db6a957d623ff04b9f715b565f516806cea247264c82a7569871dbd0b86cfe4689"
|
||||
bool(true)
|
||||
bool(true)
|
||||
bool(true)
|
||||
int(128)
|
||||
bool(true)
|
||||
int(128)
|
||||
bool(false)
|
||||
|
||||
Warning: openssl_sign(): Supplied key param cannot be coerced into a private key in %s on line %d
|
||||
bool(false)
|
||||
|
|
|
@ -9,6 +9,10 @@ $privkey = "file://" . __DIR__ . "/private_rsa_1024.key";
|
|||
$pubkey = "file://" . __DIR__ . "/public.key";
|
||||
$wrong = "wrong";
|
||||
|
||||
|
||||
openssl_sign($data, $sign, $privkey, OPENSSL_ALGO_SHA256, OPENSSL_PKCS1_PSS_PADDING);
|
||||
var_dump(openssl_verify($data, $sign, $pubkey, OPENSSL_ALGO_SHA256, OPENSSL_PKCS1_PSS_PADDING));
|
||||
var_dump(openssl_verify($data, $sign, $pubkey, OPENSSL_ALGO_SHA256));
|
||||
openssl_sign($data, $sign, $privkey, OPENSSL_ALGO_SHA256);
|
||||
var_dump(openssl_verify($data, $sign, $pubkey, OPENSSL_ALGO_SHA256));
|
||||
var_dump(openssl_verify($data, $sign, $privkey, OPENSSL_ALGO_SHA256));
|
||||
|
@ -18,6 +22,8 @@ var_dump(openssl_verify($wrong, $sign, $pubkey, OPENSSL_ALGO_SHA256));
|
|||
?>
|
||||
--EXPECTF--
|
||||
int(1)
|
||||
int(0)
|
||||
int(1)
|
||||
|
||||
Warning: openssl_verify(): Supplied key param cannot be coerced into a public key in %s on line %d
|
||||
bool(false)
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue