Edit report at https://bugs.php.net/bug.php?id=71519&edit=1
ID: 71519
Comment by: xrobau at gmail dot com
Reported by: xrobau at gmail dot com
Summary: SSL Serial Number wildly wrong
Status: Open
Type: Bug
Package: OpenSSL related
Operating System: CentOS 7.2
PHP Version: 5.6.17
Block user comment: N
Private report: N
New Comment:
Thinking more about this, this isn't really a bug, but more of a feature request. As you
can't trust php to dechex() the returned serial number, the hex serial number (as per moises
patch, above) should probably be returned as an *additional* field - for example
'serialNumberHex' - when parsing the x509 cert.
As the code for translating it to hex is then done by OpenSSL in https://www.openssl.org/docs/manmaster/crypto/BN_bn2bin.html
you can be sure that the serial number is authoritatively correct.
Previous Comments:
------------------------------------------------------------------------
[2016-02-04 07:15:32] moises dot silva at gmail dot com
Heh, I should read twice before jumping into fixing mode at midnight. This isn't a bug. The
problem is just the returned string is in decimal and represents an integer larger than PHP_INTMAX,
and hence you cannot use dec2hex as you just found out.
If you want to convert it to hex you can do something like this:
http://stackoverflow.com/questions/14539727/how-to-convert-a-huge-integer-to-hex-in-php
------------------------------------------------------------------------
[2016-02-04 05:57:49] moises dot silva at gmail dot com
I'm awfully rusty on php internals and openssl API, but here is a patch that seems to solve the
issue. It may very well break something else or blow up your machine, but at least should point the
devs in the right direction to find the problem. It seems to me like some sort of integer overflow
problem.
For reference on the way to convert the serial to string:
http://stackoverflow.com/questions/9646929/asn1-integer-to-asn1-string
And the openssl multiprecision integer arithmetics API:
https://www.openssl.org/docs/manmaster/crypto/bn.html
https://www.openssl.org/docs/manmaster/crypto/BN_bn2bin.html
Finally, I apologize for the inline patch, I didn't find an option to attach a file to this
issue:
--- php-5.6.17/ext/openssl/openssl.c 2016-01-06 10:14:47.000000000 -0500
+++ php-5.6.17-patched/ext/openssl/openssl.c 2016-02-04 00:46:30.763746683 -0500
@@ -1944,6 +1944,7 @@
char *extname;
BIO *bio_out;
BUF_MEM *bio_buf;
+ char * serial;
char buf[256];
if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "Z|b", &zcert,
&useshortnames) == FAILURE) {
@@ -1971,7 +1972,12 @@
add_assoc_name_entry(return_value, "issuer", X509_get_issuer_name(cert), useshortnames
TSRMLS_CC);
add_assoc_long(return_value, "version", X509_get_version(cert));
- add_assoc_string(return_value, "serialNumber", i2s_ASN1_INTEGER(NULL,
X509_get_serialNumber(cert)), 1);
+ serial = BN_bn2hex(ASN1_INTEGER_to_BN(X509_get_serialNumber(cert), NULL));
+ if (!serial) {
+ RETURN_FALSE;
+ }
+ add_assoc_string(return_value, "serialNumber", serial, 1);
+ OPENSSL_free(serial);
add_assoc_asn1_string(return_value, "validFrom", X509_get_notBefore(cert));
add_assoc_asn1_string(return_value, "validTo", X509_get_notAfter(cert));
------------------------------------------------------------------------
[2016-02-04 04:22:40] xrobau at gmail dot com
Additional information:
This appears to be related to long-forgotten bug https://bugs.php.net/bug.php?id=52093
After doing some further diagnosis after reporting the bug, I tried doing a dechex on the number
provided by serialNumber, and that immediately exposed an overflow there:
$ php fail.php
Serial should be 9044D9A928D1A1BC4E6134311DD7EB4AE96B1468 or
009044D9A928D1A1BC4E6134311DD7EB4AE96B1468:
Serial reported as: '7fffffffffffffff'
$
Additionally, as I didn't make it clear in the original report, the leading byte of a serial
number being zero means that the serial number is to be reported as hex, not interpreted as a
decimal number.
------------------------------------------------------------------------
[2016-02-04 04:17:07] xrobau at gmail dot com
Appears to be related to 2010-era-bug
https://bugs.php.net/bug.php?id=52093
------------------------------------------------------------------------
[2016-02-04 04:14:42] xrobau at gmail dot com
Note to clarify: The first byte of the serial number being 00 specifically means that the serial
number is a hex digit, and should be reported as such.
However, there is an overflow in the serial number code. This is obvious when doing a dechex() on
the number returned:
$ php fail.php
Serial should be 9044D9A928D1A1BC4E6134311DD7EB4AE96B1468 or
009044D9A928D1A1BC4E6134311DD7EB4AE96B1468:
Serial reported as: '7fffffffffffffff'
------------------------------------------------------------------------
The remainder of the comments for this report are too long. To view
the rest of the comments, please view the bug report online at
https://bugs.php.net/bug.php?id=71519
--
Edit this bug report at https://bugs.php.net/bug.php?id=71519&edit=1