1--TEST-- 2openssl_error_string() tests (OpenSSL < 3.0) 3--EXTENSIONS-- 4openssl 5--SKIPIF-- 6<?php 7if (OPENSSL_VERSION_NUMBER >= 0x30000000) die('skip For OpenSSL < 3.0'); 8?> 9--FILE-- 10<?php 11// helper function to check openssl errors 12function 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 48function 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 78openssl_encrypt($data, $method, $enc_key); 79$enc_error = openssl_error_string(); 80var_dump($enc_error); 81// make sure that error is cleared now 82var_dump(openssl_error_string()); 83// internally OpenSSL ERR won't save more than 15 (16 - 1) errors so lets test it 84for ($i = 0; $i < 20; $i++) { 85 openssl_encrypt($data, $method, $enc_key); 86} 87$error_queue_size = 0; 88while (($enc_error_new = openssl_error_string()) !== false) { 89 if ($enc_error_new !== $enc_error) { 90 echo "The new encoding error doesn't match the expected one\n"; 91 } 92 ++$error_queue_size; 93} 94var_dump($error_queue_size); 95echo "\n"; 96 97$is_111 = OPENSSL_VERSION_NUMBER >= 0x10101000; 98$err_pem_no_start_line = $is_111 ? '0909006C': '0906D06C'; 99 100// PKEY 101echo "PKEY errors\n"; 102// file for pkey (file:///) fails when opennig (BIO_new_file) 103@openssl_pkey_export_to_file("file://" . $invalid_file_for_read, $output_file); 104expect_openssl_errors('openssl_pkey_export_to_file opening', ['02001002', '2006D080']); 105// file or private pkey is not correct PEM - failing PEM_read_bio_PrivateKey 106@openssl_pkey_export_to_file($csr_file, $output_file); 107expect_openssl_errors('openssl_pkey_export_to_file pem', [$err_pem_no_start_line]); 108// file to export cannot be written 109@openssl_pkey_export_to_file($private_key_file, $invalid_file_for_write); 110expect_openssl_errors('openssl_pkey_export_to_file write', ['2006D002']); 111// successful export 112@openssl_pkey_export($private_key_file_with_pass, $out, 'wrong pwd'); 113expect_openssl_errors('openssl_pkey_export', ['06065064', '0906A065']); 114// invalid x509 for getting public key 115@openssl_pkey_get_public($private_key_file); 116expect_openssl_errors('openssl_pkey_get_public', [$err_pem_no_start_line]); 117// private encrypt with unknown padding 118@openssl_private_encrypt("data", $crypted, $private_key_file, 1000); 119expect_openssl_errors('openssl_private_encrypt', ['0408F090']); 120// private decrypt with failed padding check 121@openssl_private_decrypt("data", $crypted, $private_key_file, OPENSSL_PKCS1_OAEP_PADDING); 122expect_openssl_errors('openssl_private_decrypt', ['04099079']); 123// public encrypt and decrypt with failed padding check and padding 124@openssl_public_encrypt("data", $crypted, $public_key_file, 1000); 125@openssl_public_decrypt("data", $crypted, $public_key_file, OPENSSL_PKCS1_OAEP_PADDING); 126expect_openssl_errors('openssl_private_(en|de)crypt padding', [$err_pem_no_start_line, '0408F090', '06089093']); 127 128// X509 129echo "X509 errors\n"; 130// file for x509 (file:///) fails when opennig (BIO_new_file) 131@openssl_x509_export_to_file("file://" . $invalid_file_for_read, $output_file); 132expect_openssl_errors('openssl_x509_export_to_file open', ['02001002']); 133// file or str cert is not correct PEM - failing PEM_read_bio_X509 or PEM_ASN1_read_bio 134@openssl_x509_export_to_file($csr_file, $output_file); 135expect_openssl_errors('openssl_x509_export_to_file pem', [$err_pem_no_start_line]); 136// file to export cannot be written 137@openssl_x509_export_to_file($crt_file, $invalid_file_for_write); 138expect_openssl_errors('openssl_x509_export_to_file write', ['2006D002']); 139// checking purpose fails because there is no such purpose 1000 140@openssl_x509_checkpurpose($crt_file, 1000); 141expect_openssl_errors('openssl_x509_checkpurpose purpose', ['0B086079']); 142 143// CSR 144echo "CSR errors\n"; 145// file for csr (file:///) fails when opennig (BIO_new_file) 146@openssl_csr_get_subject("file://" . $invalid_file_for_read); 147expect_openssl_errors('openssl_csr_get_subject open', ['02001002', '2006D080']); 148// file or str csr is not correct PEM - failing PEM_read_bio_X509_REQ 149@openssl_csr_get_subject($crt_file); 150expect_openssl_errors('openssl_csr_get_subjec pem', [$err_pem_no_start_line]); 151 152// other possible causes that are difficult to catch: 153// - ASN1_STRING_to_UTF8 fails in add_assoc_name_entry 154// - invalid php_x509_request field (NULL) would cause error with CONF_get_string 155 156?> 157--CLEAN-- 158<?php 159$output_file = __DIR__ . "/openssl_error_string_basic_output.tmp"; 160if (is_file($output_file)) { 161 unlink($output_file); 162} 163?> 164--EXPECT-- 165string(89) "error:0607A082:digital envelope routines:EVP_CIPHER_CTX_set_key_length:invalid key length" 166bool(false) 167int(15) 168 169PKEY errors 170openssl_pkey_export_to_file opening: ok 171openssl_pkey_export_to_file pem: ok 172openssl_pkey_export_to_file write: ok 173openssl_pkey_export: ok 174openssl_pkey_get_public: ok 175openssl_private_encrypt: ok 176openssl_private_decrypt: ok 177openssl_private_(en|de)crypt padding: ok 178X509 errors 179openssl_x509_export_to_file open: ok 180openssl_x509_export_to_file pem: ok 181openssl_x509_export_to_file write: ok 182openssl_x509_checkpurpose purpose: ok 183CSR errors 184openssl_csr_get_subject open: ok 185openssl_csr_get_subjec pem: ok 186