Skip to content

Commit a5973f3

Browse files
committed
openssl: Add validation for XOF digests requiring explicit output length
1 parent 6249b46 commit a5973f3

4 files changed

Lines changed: 71 additions & 8 deletions

File tree

‎NEWS‎

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -41,6 +41,11 @@ PHP NEWS
4141
. Fixed OSS-Fuzz #545352966 (default value AST of an SHM-persisted partial).
4242
(ndossche)
4343

44+
- OpenSSL:
45+
. openssl_digest() and openssl_x509_fingerprint() now emit a warning for
46+
digest algorithms with no default output length (SHAKE128, SHAKE256 on
47+
OpenSSL 3.4 and later) instead of failing silently. (Alexander Danilov)
48+
4449
- PDO:
4550
. Fixed PDOStatement::getColumnMeta() reading out of bounds for an invalid
4651
column index. (Ilia Alshanetsky)

‎ext/openssl/openssl.c‎

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4984,6 +4984,9 @@ PHP_FUNCTION(openssl_digest)
49844984
}
49854985
} else {
49864986
php_openssl_store_errors();
4987+
if (EVP_MD_flags(mdtype) & EVP_MD_FLAG_XOF) {
4988+
php_error_docref(NULL, E_WARNING, "Unsupported digest algorithm: output length must be specified");
4989+
}
49874990
zend_string_release_ex(sigbuf, 0);
49884991
RETVAL_FALSE;
49894992
}

‎ext/openssl/openssl_backend_common.c‎

Lines changed: 18 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -581,6 +581,15 @@ X509 *php_openssl_x509_from_zval(
581581
return cert;
582582
}
583583

584+
static void php_openssl_fingerprint_warn(php_stream *stream, zend_enum_StreamErrorCode code, const char *msg)
585+
{
586+
if (stream != NULL) {
587+
php_stream_error(stream, NULL, E_WARNING, true, code, "%s", msg);
588+
} else {
589+
php_error_docref(NULL, E_WARNING, "%s", msg);
590+
}
591+
}
592+
584593
zend_string* php_openssl_x509_fingerprint(X509 *peer, const char *method, bool raw, php_stream *stream)
585594
{
586595
unsigned char md[EVP_MAX_MD_SIZE];
@@ -589,19 +598,20 @@ zend_string* php_openssl_x509_fingerprint(X509 *peer, const char *method, bool r
589598
zend_string *ret;
590599

591600
if (!(mdtype = php_openssl_get_evp_md_by_name(method))) {
592-
if (stream != NULL) {
593-
php_stream_warn(stream, Generic, "Unknown digest algorithm");
594-
} else {
595-
php_error_docref(NULL, E_WARNING, "Unknown digest algorithm");
596-
}
601+
php_openssl_fingerprint_warn(stream, PHP_STREAM_EC(Generic), "Unknown digest algorithm");
597602
return NULL;
598603
} else if (!X509_digest(peer, mdtype, md, &n)) {
604+
bool is_xof = EVP_MD_flags(mdtype) & EVP_MD_FLAG_XOF;
599605
php_openssl_release_evp_md(mdtype);
600606
php_openssl_store_errors();
601-
if (stream != NULL) {
602-
php_stream_warn(stream, EncodingFailed, "Could not generate signature");
607+
if (is_xof) {
608+
php_openssl_fingerprint_warn(
609+
stream,
610+
PHP_STREAM_EC(Generic),
611+
"Unsupported digest algorithm: output length must be specified"
612+
);
603613
} else {
604-
php_error_docref(NULL, E_WARNING, "Could not generate signature");
614+
php_openssl_fingerprint_warn(stream, PHP_STREAM_EC(EncodingFailed), "Could not generate signature");
605615
}
606616
return NULL;
607617
}
Lines changed: 45 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,45 @@
1+
--TEST--
2+
openssl_digest() and openssl_x509_fingerprint() with XOF digests that have no default length
3+
--EXTENSIONS--
4+
openssl
5+
--SKIPIF--
6+
<?php
7+
if (OPENSSL_VERSION_NUMBER < 0x30400000) die("skip OpenSSL 3.4 or later required: SHAKE has a default length before");
8+
?>
9+
--FILE--
10+
<?php
11+
12+
$cert = "file://" . __DIR__ . "/cert.crt";
13+
14+
foreach (['shake128', 'shake256'] as $algo) {
15+
var_dump(openssl_digest('abc', $algo));
16+
var_dump(openssl_digest('abc', $algo, true));
17+
var_dump(openssl_x509_fingerprint($cert, $algo));
18+
}
19+
20+
echo "Fixed length digests are not affected\n";
21+
var_dump(openssl_digest('abc', 'sha3-256'));
22+
var_dump(strlen(openssl_x509_fingerprint($cert, 'sha3-256')));
23+
24+
?>
25+
--EXPECTF--
26+
Warning: openssl_digest(): Unsupported digest algorithm: output length must be specified in %s on line %d
27+
bool(false)
28+
29+
Warning: openssl_digest(): Unsupported digest algorithm: output length must be specified in %s on line %d
30+
bool(false)
31+
32+
Warning: openssl_x509_fingerprint(): Unsupported digest algorithm: output length must be specified in %s on line %d
33+
bool(false)
34+
35+
Warning: openssl_digest(): Unsupported digest algorithm: output length must be specified in %s on line %d
36+
bool(false)
37+
38+
Warning: openssl_digest(): Unsupported digest algorithm: output length must be specified in %s on line %d
39+
bool(false)
40+
41+
Warning: openssl_x509_fingerprint(): Unsupported digest algorithm: output length must be specified in %s on line %d
42+
bool(false)
43+
Fixed length digests are not affected
44+
string(64) "3a985da74fe225b2045c172d6bd390bd855f086e3e9d525b46bfe24511431532"
45+
int(64)

0 commit comments

Comments
 (0)