mirror of
https://github.com/php/php-src.git
synced 2025-08-20 09:24:05 +02:00
Merge branch 'PHP-8.0'
* PHP-8.0: Fix bug #79983: Add support for OCB mode
This commit is contained in:
commit
ec82c2067e
4 changed files with 199 additions and 7 deletions
|
@ -6888,6 +6888,7 @@ PHP_FUNCTION(openssl_digest)
|
|||
/* Cipher mode info */
|
||||
struct php_openssl_cipher_mode {
|
||||
zend_bool is_aead;
|
||||
zend_bool should_set_tag_length;
|
||||
zend_bool is_single_run_aead;
|
||||
int aead_get_tag_flag;
|
||||
int aead_set_tag_flag;
|
||||
|
@ -6896,24 +6897,41 @@ struct php_openssl_cipher_mode {
|
|||
|
||||
static void php_openssl_load_cipher_mode(struct php_openssl_cipher_mode *mode, const EVP_CIPHER *cipher_type) /* {{{ */
|
||||
{
|
||||
switch (EVP_CIPHER_mode(cipher_type)) {
|
||||
#ifdef EVP_CIPH_GCM_MODE
|
||||
int cipher_mode = EVP_CIPHER_mode(cipher_type);
|
||||
switch (cipher_mode) {
|
||||
#if PHP_OPENSSL_API_VERSION >= 0x10100
|
||||
case EVP_CIPH_GCM_MODE:
|
||||
case EVP_CIPH_OCB_MODE:
|
||||
case EVP_CIPH_CCM_MODE:
|
||||
mode->is_aead = 1;
|
||||
mode->should_set_tag_length =
|
||||
cipher_mode == EVP_CIPH_CCM_MODE || cipher_mode == EVP_CIPH_OCB_MODE;
|
||||
mode->is_single_run_aead = cipher_mode == EVP_CIPH_CCM_MODE;
|
||||
mode->aead_get_tag_flag = EVP_CTRL_AEAD_GET_TAG;
|
||||
mode->aead_set_tag_flag = EVP_CTRL_AEAD_SET_TAG;
|
||||
mode->aead_ivlen_flag = EVP_CTRL_AEAD_SET_IVLEN;
|
||||
break;
|
||||
#else
|
||||
# ifdef EVP_CIPH_GCM_MODE
|
||||
case EVP_CIPH_GCM_MODE:
|
||||
mode->is_aead = 1;
|
||||
mode->should_set_tag_length = 0;
|
||||
mode->is_single_run_aead = 0;
|
||||
mode->aead_get_tag_flag = EVP_CTRL_GCM_GET_TAG;
|
||||
mode->aead_set_tag_flag = EVP_CTRL_GCM_SET_TAG;
|
||||
mode->aead_ivlen_flag = EVP_CTRL_GCM_SET_IVLEN;
|
||||
break;
|
||||
#endif
|
||||
#ifdef EVP_CIPH_CCM_MODE
|
||||
# endif
|
||||
# ifdef EVP_CIPH_CCM_MODE
|
||||
case EVP_CIPH_CCM_MODE:
|
||||
mode->is_aead = 1;
|
||||
mode->should_set_tag_length = 1;
|
||||
mode->is_single_run_aead = 1;
|
||||
mode->aead_get_tag_flag = EVP_CTRL_CCM_GET_TAG;
|
||||
mode->aead_set_tag_flag = EVP_CTRL_CCM_SET_TAG;
|
||||
mode->aead_ivlen_flag = EVP_CTRL_CCM_SET_IVLEN;
|
||||
break;
|
||||
# endif
|
||||
#endif
|
||||
default:
|
||||
memset(mode, 0, sizeof(struct php_openssl_cipher_mode));
|
||||
|
@ -6998,12 +7016,15 @@ static int php_openssl_cipher_init(const EVP_CIPHER *cipher_type,
|
|||
if (php_openssl_validate_iv(piv, piv_len, max_iv_len, free_iv, cipher_ctx, mode) == FAILURE) {
|
||||
return FAILURE;
|
||||
}
|
||||
if (mode->is_single_run_aead && enc) {
|
||||
if (mode->should_set_tag_length) {
|
||||
/* Explicitly set the tag length even when decrypting,
|
||||
* see https://github.com/openssl/openssl/issues/8331. */
|
||||
if (!EVP_CIPHER_CTX_ctrl(cipher_ctx, mode->aead_set_tag_flag, tag_len, NULL)) {
|
||||
php_error_docref(NULL, E_WARNING, "Setting tag length for AEAD cipher failed");
|
||||
return FAILURE;
|
||||
}
|
||||
} else if (!enc && tag && tag_len > 0) {
|
||||
}
|
||||
if (!enc && tag && tag_len > 0) {
|
||||
if (!mode->is_aead) {
|
||||
php_error_docref(NULL, E_WARNING, "The tag cannot be used because the cipher algorithm does not support AEAD");
|
||||
} else if (!EVP_CIPHER_CTX_ctrl(cipher_ctx, mode->aead_set_tag_flag, tag_len, (unsigned char *) tag)) {
|
||||
|
|
|
@ -108,7 +108,58 @@ $php_openssl_cipher_tests = array(
|
|||
'01e4a9a4fba43c90ccdcb281d48c7c6f' .
|
||||
'd62875d2aca417034c34aee5',
|
||||
),
|
||||
)
|
||||
),
|
||||
// First few test vectors from RFC 7253.
|
||||
'aes-128-ocb' => array(
|
||||
array(
|
||||
'key' => '000102030405060708090A0B0C0D0E0F',
|
||||
'iv' => 'BBAA99887766554433221100',
|
||||
'aad' => '',
|
||||
'pt' => '',
|
||||
'tag' => '785407BFFFC8AD9EDCC5520AC9111EE6',
|
||||
'ct' => '',
|
||||
),
|
||||
array(
|
||||
'key' => '000102030405060708090A0B0C0D0E0F',
|
||||
'iv' => 'BBAA99887766554433221101',
|
||||
'aad' => '0001020304050607',
|
||||
'pt' => '0001020304050607',
|
||||
'tag' => '5725BDA0D3B4EB3A257C9AF1F8F03009',
|
||||
'ct' => '6820B3657B6F615A',
|
||||
),
|
||||
array(
|
||||
'key' => '000102030405060708090A0B0C0D0E0F',
|
||||
'iv' => 'BBAA99887766554433221102',
|
||||
'aad' => '0001020304050607',
|
||||
'pt' => '',
|
||||
'tag' => '81017F8203F081277152FADE694A0A00',
|
||||
'ct' => '',
|
||||
),
|
||||
array(
|
||||
'key' => '000102030405060708090A0B0C0D0E0F',
|
||||
'iv' => 'BBAA99887766554433221103',
|
||||
'aad' => '',
|
||||
'pt' => '0001020304050607',
|
||||
'tag' => '14054CD1F35D82760B2CD00D2F99BFA9',
|
||||
'ct' => '45DD69F8F5AAE724',
|
||||
),
|
||||
array(
|
||||
'key' => '000102030405060708090A0B0C0D0E0F',
|
||||
'iv' => 'BBAA99887766554433221104',
|
||||
'aad' => '000102030405060708090A0B0C0D0E0F',
|
||||
'pt' => '000102030405060708090A0B0C0D0E0F',
|
||||
'tag' => '3AD7A4FF3835B8C5701C1CCEC8FC3358',
|
||||
'ct' => '571D535B60B277188BE5147170A9A22C',
|
||||
),
|
||||
array(
|
||||
'key' => '0F0E0D0C0B0A09080706050403020100',
|
||||
'iv' => 'BBAA9988776655443322110D',
|
||||
'aad' => '000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C1D1E1F2021222324252627',
|
||||
'pt' => '000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C1D1E1F2021222324252627',
|
||||
'tag' => 'D0C515F4D1CDD4FDAC4F02AA',
|
||||
'ct' => '1792A4E31E0755FB03E31B22116E6C2DDF9EFD6E33D536F1A0124B0A55BAE884ED93481529C76B6A',
|
||||
),
|
||||
),
|
||||
);
|
||||
|
||||
function openssl_get_cipher_tests($method)
|
||||
|
|
60
ext/openssl/tests/openssl_decrypt_ocb.phpt
Normal file
60
ext/openssl/tests/openssl_decrypt_ocb.phpt
Normal file
|
@ -0,0 +1,60 @@
|
|||
--TEST--
|
||||
openssl_decrypt() with OCB cipher algorithm tests
|
||||
--SKIPIF--
|
||||
<?php
|
||||
if (!extension_loaded("openssl"))
|
||||
die("skip");
|
||||
if (!in_array('aes-128-ocb', openssl_get_cipher_methods()))
|
||||
die("skip: aes-128-ocb not available");
|
||||
?>
|
||||
--FILE--
|
||||
<?php
|
||||
require_once __DIR__ . "/cipher_tests.inc";
|
||||
$method = 'aes-128-ocb';
|
||||
$tests = openssl_get_cipher_tests($method);
|
||||
|
||||
foreach ($tests as $idx => $test) {
|
||||
echo "TEST $idx\n";
|
||||
$pt = openssl_decrypt($test['ct'], $method, $test['key'], OPENSSL_RAW_DATA,
|
||||
$test['iv'], $test['tag'], $test['aad']);
|
||||
var_dump($test['pt'] === $pt);
|
||||
}
|
||||
|
||||
// no IV
|
||||
var_dump(openssl_decrypt($test['ct'], $method, $test['key'], OPENSSL_RAW_DATA,
|
||||
NULL, $test['tag'], $test['aad']));
|
||||
|
||||
// IV too long
|
||||
var_dump(openssl_decrypt($test['ct'], $method, $test['key'], OPENSSL_RAW_DATA,
|
||||
str_repeat('x', 32), $test['tag'], $test['aad']));
|
||||
|
||||
// failed because no AAD
|
||||
var_dump(openssl_decrypt($test['ct'], $method, $test['key'], OPENSSL_RAW_DATA,
|
||||
$test['iv'], $test['tag']));
|
||||
|
||||
// failed because wrong tag
|
||||
var_dump(openssl_decrypt($test['ct'], $method, $test['key'], OPENSSL_RAW_DATA,
|
||||
$test['iv'], str_repeat('x', 16), $test['aad']));
|
||||
|
||||
?>
|
||||
--EXPECTF--
|
||||
TEST 0
|
||||
bool(true)
|
||||
TEST 1
|
||||
bool(true)
|
||||
TEST 2
|
||||
bool(true)
|
||||
TEST 3
|
||||
bool(true)
|
||||
TEST 4
|
||||
bool(true)
|
||||
TEST 5
|
||||
bool(true)
|
||||
|
||||
Warning: openssl_decrypt(): Setting of IV length for AEAD mode failed in %s on line %d
|
||||
bool(false)
|
||||
|
||||
Warning: openssl_decrypt(): Setting of IV length for AEAD mode failed in %s on line %d
|
||||
bool(false)
|
||||
bool(false)
|
||||
bool(false)
|
60
ext/openssl/tests/openssl_encrypt_ocb.phpt
Normal file
60
ext/openssl/tests/openssl_encrypt_ocb.phpt
Normal file
|
@ -0,0 +1,60 @@
|
|||
--TEST--
|
||||
openssl_encrypt() with OCB cipher algorithm tests
|
||||
--SKIPIF--
|
||||
<?php
|
||||
if (!extension_loaded("openssl"))
|
||||
die("skip");
|
||||
if (!in_array('aes-128-ocb', openssl_get_cipher_methods()))
|
||||
die("skip: aes-128-ocb not available");
|
||||
?>
|
||||
--FILE--
|
||||
<?php
|
||||
require_once __DIR__ . "/cipher_tests.inc";
|
||||
$method = 'aes-128-ocb';
|
||||
$tests = openssl_get_cipher_tests($method);
|
||||
|
||||
foreach ($tests as $idx => $test) {
|
||||
echo "TEST $idx\n";
|
||||
$ct = openssl_encrypt($test['pt'], $method, $test['key'], OPENSSL_RAW_DATA,
|
||||
$test['iv'], $tag, $test['aad'], strlen($test['tag']));
|
||||
var_dump($test['ct'] === $ct);
|
||||
var_dump($test['tag'] === $tag);
|
||||
}
|
||||
|
||||
// Empty IV error
|
||||
var_dump(openssl_encrypt('data', $method, 'password', 0, NULL, $tag, ''));
|
||||
|
||||
// Failing to retrieve tag (must be at most 16 bytes)
|
||||
var_dump(openssl_encrypt('data', $method, 'password', 0, str_repeat('x', 12), $tag, '', 20));
|
||||
|
||||
// Failing when no tag supplied
|
||||
var_dump(openssl_encrypt('data', $method, 'password', 0, str_repeat('x', 12)));
|
||||
?>
|
||||
--EXPECTF--
|
||||
TEST 0
|
||||
bool(true)
|
||||
bool(true)
|
||||
TEST 1
|
||||
bool(true)
|
||||
bool(true)
|
||||
TEST 2
|
||||
bool(true)
|
||||
bool(true)
|
||||
TEST 3
|
||||
bool(true)
|
||||
bool(true)
|
||||
TEST 4
|
||||
bool(true)
|
||||
bool(true)
|
||||
TEST 5
|
||||
bool(true)
|
||||
bool(true)
|
||||
|
||||
Warning: openssl_encrypt(): Setting of IV length for AEAD mode failed in %s on line %d
|
||||
bool(false)
|
||||
|
||||
Warning: openssl_encrypt(): Setting tag length for AEAD cipher failed in %s on line %d
|
||||
bool(false)
|
||||
|
||||
Warning: openssl_encrypt(): A tag should be provided when using AEAD mode in %s on line %d
|
||||
bool(false)
|
Loading…
Add table
Add a link
Reference in a new issue