Skip to content

Commit e5f53e1

Browse files
committed
Fork openssl_error_string() test for OpenSSL
The used error code differ signficantly, so use a separate test file. openssl_encrypt() no longer throws an error for invalid key length, which looks like an upstream bug.
1 parent 98184af commit e5f53e1

File tree

2 files changed

+188
-1
lines changed

2 files changed

+188
-1
lines changed

ext/openssl/tests/openssl_error_string_basic.phpt

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,11 @@
11
--TEST--
2-
openssl_error_string() tests
2+
openssl_error_string() tests (OpenSSL < 3.0)
33
--EXTENSIONS--
44
openssl
5+
--SKIPIF--
6+
<?php
7+
if (OPENSSL_VERSION_NUMBER >= 0x30000000) die('skip For OpenSSL < 3.0');
8+
?>
59
--FILE--
610
<?php
711
// helper function to check openssl errors
Lines changed: 183 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,183 @@
1+
--TEST--
2+
openssl_error_string() tests (OpenSSL >= 3.0)
3+
--EXTENSIONS--
4+
openssl
5+
--SKIPIF--
6+
<?php
7+
if (OPENSSL_VERSION_NUMBER < 0x30000000) die('skip For OpenSSL >= 3.0');
8+
?>
9+
--FILE--
10+
<?php
11+
// helper function to check openssl errors
12+
function expect_openssl_errors($name, $expected_error_codes) {
13+
$expected_errors = array_fill_keys($expected_error_codes, false);
14+
$all_errors = array();
15+
while (($error_string = openssl_error_string()) !== false) {
16+
if (preg_match(",.+:([0-9A-F]+):.+,", $error_string, $m) > 0) {
17+
$error_code = $m[1];
18+
if (isset($expected_errors[$error_code])) {
19+
$expected_errors[$error_code] = true;
20+
}
21+
$all_errors[$error_code] = $error_string;
22+
} else {
23+
$all_errors[] = $error_string;
24+
}
25+
}
26+
27+
$fail = false;
28+
foreach ($expected_errors as $error_code => $error_code_found) {
29+
if (!$error_code_found) {
30+
$fail = true;
31+
echo "$name: no error code $error_code\n";
32+
}
33+
}
34+
35+
if (!$fail) {
36+
echo "$name: ok\n";
37+
} else {
38+
echo "$name: uncaught errors\n";
39+
foreach ($all_errors as $code => $str) {
40+
if (!isset($expected_errors[$code]) || !$expected_errors[$code]) {
41+
echo "\t", $code, ": ", $str, "\n";
42+
}
43+
}
44+
}
45+
}
46+
47+
// helper for debugging errors
48+
function dump_openssl_errors($name) {
49+
echo "\n$name\n";
50+
while (($error_string = openssl_error_string()) !== false) {
51+
var_dump($error_string);
52+
}
53+
}
54+
55+
// common output file
56+
$output_file = __DIR__ . "/openssl_error_string_basic_output.tmp";
57+
// invalid file for read is something that does not exist in current directory
58+
$invalid_file_for_read = __DIR__ . "/invalid_file_for_read_operation.txt";
59+
// invalid file for is the test dir as writing file to existing dir should always fail
60+
$invalid_file_for_write = __DIR__;
61+
// crt file
62+
$crt_file = "file://" . __DIR__ . "/cert.crt";
63+
// csr file
64+
$csr_file = "file://" . __DIR__ . "/cert.csr";
65+
// public key file
66+
$public_key_file = "file://" .__DIR__ . "/public.key";
67+
// private key file
68+
$private_key_file = "file://" .__DIR__ . "/private_rsa_1024.key";
69+
// private key file with password (password is 'php')
70+
$private_key_file_with_pass = "file://" .__DIR__ . "/private_rsa_2048_pass_php.key";
71+
72+
// ENCRYPTION
73+
$data = "test";
74+
$method = "AES-128-ECB";
75+
$enc_key = str_repeat('x', 40);
76+
// error because password is longer then key length and
77+
// EVP_CIPHER_CTX_set_key_length fails for AES
78+
if (0) {
79+
// TODO: This no longer errors!
80+
openssl_encrypt($data, $method, $enc_key);
81+
$enc_error = openssl_error_string();
82+
var_dump($enc_error);
83+
// make sure that error is cleared now
84+
var_dump(openssl_error_string());
85+
// internally OpenSSL ERR won't save more than 15 (16 - 1) errors so lets test it
86+
for ($i = 0; $i < 20; $i++) {
87+
openssl_encrypt($data, $method, $enc_key);
88+
}
89+
$error_queue_size = 0;
90+
while (($enc_error_new = openssl_error_string()) !== false) {
91+
if ($enc_error_new !== $enc_error) {
92+
echo "The new encoding error doesn't match the expected one\n";
93+
}
94+
++$error_queue_size;
95+
}
96+
var_dump($error_queue_size);
97+
echo "\n";
98+
}
99+
100+
$err_pem_no_start_line = '0480006C';
101+
102+
// PKEY
103+
echo "PKEY errors\n";
104+
// file for pkey (file:///) fails when opennig (BIO_new_file)
105+
@openssl_pkey_export_to_file("file://" . $invalid_file_for_read, $output_file);
106+
expect_openssl_errors('openssl_pkey_export_to_file opening', ['10000080']);
107+
// file or private pkey is not correct PEM - failing PEM_read_bio_PrivateKey
108+
@openssl_pkey_export_to_file($csr_file, $output_file);
109+
expect_openssl_errors('openssl_pkey_export_to_file pem', ['1E08010C']);
110+
// file to export cannot be written
111+
@openssl_pkey_export_to_file($private_key_file, $invalid_file_for_write);
112+
expect_openssl_errors('openssl_pkey_export_to_file write', ['10080002']);
113+
// successful export
114+
@openssl_pkey_export($private_key_file_with_pass, $out, 'wrong pwd');
115+
expect_openssl_errors('openssl_pkey_export', ['1C800064', '04800065']);
116+
// invalid x509 for getting public key
117+
@openssl_pkey_get_public($private_key_file);
118+
expect_openssl_errors('openssl_pkey_get_public', [$err_pem_no_start_line]);
119+
// private encrypt with unknown padding
120+
@openssl_private_encrypt("data", $crypted, $private_key_file, 1000);
121+
expect_openssl_errors('openssl_private_encrypt', ['1C8000A5']);
122+
// private decrypt with failed padding check
123+
@openssl_private_decrypt("data", $crypted, $private_key_file);
124+
expect_openssl_errors('openssl_private_decrypt', ['0200009F', '02000072']);
125+
// public encrypt and decrypt with failed padding check and padding
126+
@openssl_public_encrypt("data", $crypted, $public_key_file, 1000);
127+
@openssl_public_decrypt("data", $crypted, $public_key_file);
128+
expect_openssl_errors('openssl_private_(en|de)crypt padding', [$err_pem_no_start_line, '02000076', '0200008A', '02000072', '1C880004']);
129+
130+
// X509
131+
echo "X509 errors\n";
132+
// file for x509 (file:///) fails when opennig (BIO_new_file)
133+
@openssl_x509_export_to_file("file://" . $invalid_file_for_read, $output_file);
134+
expect_openssl_errors('openssl_x509_export_to_file open', ['10000080']);
135+
// file or str cert is not correct PEM - failing PEM_read_bio_X509 or PEM_ASN1_read_bio
136+
@openssl_x509_export_to_file($csr_file, $output_file);
137+
expect_openssl_errors('openssl_x509_export_to_file pem', [$err_pem_no_start_line]);
138+
// file to export cannot be written
139+
@openssl_x509_export_to_file($crt_file, $invalid_file_for_write);
140+
expect_openssl_errors('openssl_x509_export_to_file write', ['10080002']);
141+
// checking purpose fails because there is no such purpose 1000
142+
@openssl_x509_checkpurpose($crt_file, 1000);
143+
expect_openssl_errors('openssl_x509_checkpurpose purpose', ['05800079']);
144+
145+
// CSR
146+
echo "CSR errors\n";
147+
// file for csr (file:///) fails when opennig (BIO_new_file)
148+
@openssl_csr_get_subject("file://" . $invalid_file_for_read);
149+
expect_openssl_errors('openssl_csr_get_subject open', ['10000080']);
150+
// file or str csr is not correct PEM - failing PEM_read_bio_X509_REQ
151+
@openssl_csr_get_subject($crt_file);
152+
expect_openssl_errors('openssl_csr_get_subjec pem', [$err_pem_no_start_line]);
153+
154+
// other possible causes that are difficult to catch:
155+
// - ASN1_STRING_to_UTF8 fails in add_assoc_name_entry
156+
// - invalid php_x509_request field (NULL) would cause error with CONF_get_string
157+
158+
?>
159+
--CLEAN--
160+
<?php
161+
$output_file = __DIR__ . "/openssl_error_string_basic_output.tmp";
162+
if (is_file($output_file)) {
163+
unlink($output_file);
164+
}
165+
?>
166+
--EXPECT--
167+
PKEY errors
168+
openssl_pkey_export_to_file opening: ok
169+
openssl_pkey_export_to_file pem: ok
170+
openssl_pkey_export_to_file write: ok
171+
openssl_pkey_export: ok
172+
openssl_pkey_get_public: ok
173+
openssl_private_encrypt: ok
174+
openssl_private_decrypt: ok
175+
openssl_private_(en|de)crypt padding: ok
176+
X509 errors
177+
openssl_x509_export_to_file open: ok
178+
openssl_x509_export_to_file pem: ok
179+
openssl_x509_export_to_file write: ok
180+
openssl_x509_checkpurpose purpose: ok
181+
CSR errors
182+
openssl_csr_get_subject open: ok
183+
openssl_csr_get_subjec pem: ok

0 commit comments

Comments
 (0)