php.net |  support |  documentation |  report a bug |  advanced search |  search howto |  statistics |  random bug |  login
Bug #69882 OpenSSL error “key values mismatch” after openssl_pkcs12_read with extra cer
Submitted: 2015-06-19 10:30 UTC Modified: 2016-06-19 16:35 UTC
From: falundir at gmail dot com Assigned: bukka
Status: Closed Package: OpenSSL related
PHP Version: 5.6.7 OS: Debian 8.0
Private report: No CVE-ID:
 [2015-06-19 10:30 UTC] falundir at gmail dot com
Description:
------------
Following scenario:
1. Call some SOAP method with HTTPS endpoint.
2. Call openssl_pkcs12_read on PKCS#12 file with extra certificates.
3. Call some SOAP method with HTTPS endpoint again. It will cause warning.

Causes warning:

Warning: SoapClient::__doRequest(): SSL operation failed with code 1. OpenSSL Error messages: 
error:0B080074:x509 certificate routines:X509_check_private_key:key values mismatch

followed by:

Fatal error: Uncaught SoapFault exception: [HTTP] Error Fetching http headers

Versions affected are at least PHP 5.6.9 (Debian 8) and PHP 7.0.0-dev (tested on Rasmus's php7dev Vagrant box image from https://github.com/rlerdorf/php7dev.git). It worked OK in Debian 7 (PHP 5.4).

More details and full working test case with certificate and public SOAP webservice available at http://stackoverflow.com/questions/30730846.

Test script:
---------------
$p12 = file_get_contents('certificate_with_private_key_and_extra_certs.p12');
$p12_password = 'password';

$sc = new SoapClient('URL to SOAP webservice with HTTPS endpoint');

var_dump($sc->method());

$result = openssl_pkcs12_read($p12, $cert_data, $p12_password);

var_dump($sc->method()); //this causes warning and soap exception

Expected result:
----------------
<var dumped result of $sc->method()>

<var dumped result of $sc->method()>

Actual result:
--------------
<var dumped result of $sc->method()>

Warning: SoapClient::__doRequest(): SSL operation failed with code 1. OpenSSL Error messages: 
error:0B080074:x509 certificate routines:X509_check_private_key:key values mismatch

Fatal error: Uncaught SoapFault exception: [HTTP] Error Fetching http headers

Patches

Add a Patch

Pull Requests

Pull requests:

Add a Pull Request

History

AllCommentsChangesGit/SVN commitsRelated reports
 [2015-06-19 10:31 UTC] falundir at gmail dot com
-Summary: OpenSSL “key values mismatch” on SOAP HTTPS call mixed with openssl_pkcs12_r +Summary: OpenSSL “key values mismatch” on SOAP HTTPS mixed with openssl_pkcs12_read
 [2015-06-19 10:31 UTC] falundir at gmail dot com
Fixed summary.
 [2015-06-19 12:24 UTC] kalle@php.net
-PHP Version: 7.0.0alpha1 +PHP Version: 5.6.9
 [2015-06-21 20:16 UTC] falundir at gmail dot com
-PHP Version: 5.6.9 +PHP Version: 5.6.7
 [2015-06-21 20:16 UTC] falundir at gmail dot com
Verified that PHP 5.6.7 is the first version with this bug. Tested by compiling from the source, so it's not a problem in Debian packaged version.
 [2015-06-22 08:49 UTC] falundir at gmail dot com
-Package: SOAP related +Package: OpenSSL related
 [2015-06-22 08:49 UTC] falundir at gmail dot com
I've located the specific commit which indroduced the bug: fd4641696cc67fedf494717b5e4d452019f04d6f (together with next 1482ed2d5660c3875add40706a18fe29e2b3ff70).
 [2015-06-22 19:48 UTC] falundir at gmail dot com
I have been able to "fix" this error by calling ERR_get_error() at the cleanup section of openssl_pkcs12_read method. Something in there is producing this "key values mismatch" error and since it's not consumed in this method, it is picked up by php_openssl_sockop_io.
Change in this commit introduced a line:
int err = SSL_get_error(sslsock->ssl_handle, nr_bytes );
before:
retry = handle_ssl_error(stream, nr_bytes, 0 TSRMLS_CC);
which effectively cleared SSL error from handle_ssl_error and made handle_ssl_error go to default section of switch where ERR_get_error() is handled.

If this change is OK or not is another case, but primary case would be to check what is producing "key values mismatch" error at openssl_pkcs12_read and handle it there properly.
 [2015-06-23 07:09 UTC] falundir at gmail dot com
The "key values mismatch" is triggered in openssl_pkcs12_read by PKCS12_parse, because it uses X509_check_private_key to separate main certificate (which corresponds to private key) from extra certificates. Extra certificates usually comes first (p12 contents are reversed as stack) and X509_check_private_key triggers X509_R_KEY_VALUES_MISMATCH error.
I guess, the fix will be to pop any X509_R_KEY_VALUES_MISMATCH errors when there are extra certificates. Will try that.
 [2015-06-23 08:28 UTC] falundir at gmail dot com
-Summary: OpenSSL “key values mismatch” on SOAP HTTPS mixed with openssl_pkcs12_read +Summary: OpenSSL error “key values mismatch” after openssl_pkcs12_read with extra certs
 [2015-06-23 08:28 UTC] falundir at gmail dot com
Changed summary to properly reflect source of problem.
 [2015-06-23 09:42 UTC] falundir at gmail dot com
Reported as bug in OpenSSL:
https://rt.openssl.org/Ticket/Display.html?id=3923
 [2015-06-24 10:00 UTC] falundir at gmail dot com
The workaround is to call openssl_error_string() after 
openssl_pkcs12_read().
 [2015-06-25 22:04 UTC] datibbaw@php.net
Automatic comment on behalf of datibbaw
Revision: http://git.php.net/?p=php-src.git;a=commit;h=2ff3dafccfa4fd0bc031d5165f84593d092148d2
Log: Fixed #69882: OpenSSL error &quot;key values mismatch&quot; after openssl_pkcs12_read with extra certs
 [2015-06-25 22:04 UTC] datibbaw@php.net
-Status: Open +Status: Closed
 [2015-07-07 23:37 UTC] ab@php.net
Automatic comment on behalf of datibbaw
Revision: http://git.php.net/?p=php-src.git;a=commit;h=2ff3dafccfa4fd0bc031d5165f84593d092148d2
Log: Fixed #69882: OpenSSL error &quot;key values mismatch&quot; after openssl_pkcs12_read with extra certs
 [2016-06-19 16:35 UTC] bukka@php.net
-Assigned To: +Assigned To: bukka
 [2016-06-19 16:35 UTC] bukka@php.net
The fix for this bug was very incomplete as it addresses issue just for PKCS#12 but it would likely failed if there was any other error in the queue. It also just dropped the error (cleared the queue) without saving it so it wasn't possibly get that error from openssl_error_string.

The more complete fix is more complex and requires storing errors to the queue which won't affect openssl_error_string. Due to the size it will land in 7.1. The test was also removed because it was relying on the empty queue which is not needed.

I assigned it to myself and kept it closed just to be notified if there are any further questions.
 
PHP Copyright © 2001-2017 The PHP Group
All rights reserved.
Last updated: Fri Feb 24 01:01:37 2017 UTC