Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
15 changes: 8 additions & 7 deletions ext/openssl/openssl.c
Original file line number Diff line number Diff line change
Expand Up @@ -425,7 +425,7 @@ PHP_MINIT_FUNCTION(openssl)
ssl_stream_data_index = SSL_get_ex_new_index(0, "PHP stream index", NULL, NULL, NULL);

php_stream_xport_register("ssl", php_openssl_ssl_socket_factory);
#ifndef OPENSSL_NO_SSL3
#if OPENSSL_VERSION_NUMBER < 0x40000000L && !defined(OPENSSL_NO_SSL3)
php_stream_xport_register("sslv3", php_openssl_ssl_socket_factory);
#endif
php_stream_xport_register("tls", php_openssl_ssl_socket_factory);
Expand Down Expand Up @@ -499,7 +499,7 @@ PHP_MSHUTDOWN_FUNCTION(openssl)
php_unregister_url_stream_wrapper("ftps");

php_stream_xport_unregister("ssl");
#ifndef OPENSSL_NO_SSL3
#if OPENSSL_VERSION_NUMBER < 0x40000000L && !defined(OPENSSL_NO_SSL3)
php_stream_xport_unregister("sslv3");
#endif
php_stream_xport_unregister("tls");
Expand Down Expand Up @@ -629,7 +629,7 @@ PHP_FUNCTION(openssl_spki_new)
}

if (challenge) {
if (!ASN1_STRING_set(spki->spkac->challenge, challenge, (int)challenge_len)) {
if (!ASN1_STRING_set1_data(spki->spkac->challenge, (const unsigned char *) challenge, challenge_len)) {
php_openssl_store_errors();
php_error_docref(NULL, E_WARNING, "Unable to set challenge data");
goto cleanup;
Expand Down Expand Up @@ -818,7 +818,8 @@ PHP_FUNCTION(openssl_spki_export_challenge)
goto cleanup;
}

RETVAL_STRING((const char *)ASN1_STRING_get0_data(spki->spkac->challenge));
RETVAL_STRINGL_FAST((const char *)ASN1_STRING_get0_data(spki->spkac->challenge),
ASN1_STRING_get_length(spki->spkac->challenge));
goto cleanup;

cleanup:
Expand Down Expand Up @@ -999,8 +1000,8 @@ PHP_FUNCTION(openssl_x509_parse)
bool useshortnames = 1;
char * tmpstr;
zval subitem;
X509_EXTENSION *extension;
X509_NAME *subject_name;
PHP_OPENSSL_X509_EXTENSION *extension;
const X509_NAME *subject_name;
char *cert_name;
char *extname;
BIO *bio_out;
Expand Down Expand Up @@ -1969,7 +1970,7 @@ PHP_FUNCTION(openssl_csr_get_subject)
zend_object *csr_obj;
zend_string *csr_str;
bool use_shortnames = 1;
X509_NAME *subject;
const X509_NAME *subject;

ZEND_PARSE_PARAMETERS_START(1, 2)
Z_PARAM_OBJ_OF_CLASS_OR_STR(csr_obj, php_openssl_request_ce, csr_str)
Expand Down
57 changes: 38 additions & 19 deletions ext/openssl/openssl_backend_common.c
Original file line number Diff line number Diff line change
Expand Up @@ -35,16 +35,16 @@
/* true global; readonly after module startup */
static char default_ssl_conf_filename[MAXPATHLEN];

void php_openssl_add_assoc_name_entry(zval * val, char * key, X509_NAME * name, int shortname)
void php_openssl_add_assoc_name_entry(zval * val, char * key, const X509_NAME * name, int shortname)
{
zval *data;
zval subitem, tmp;
int i;
char *sname;
int nid;
X509_NAME_ENTRY * ne;
ASN1_STRING * str = NULL;
ASN1_OBJECT * obj;
const X509_NAME_ENTRY * ne;
const ASN1_STRING * str = NULL;
const ASN1_OBJECT * obj;

if (key != NULL) {
array_init(&subitem);
Expand Down Expand Up @@ -75,7 +75,7 @@ void php_openssl_add_assoc_name_entry(zval * val, char * key, X509_NAME * name,
} else {
/* ASN1_STRING_get0_data(3): Since this is an internal pointer it should not be freed or modified in any way */
to_add = ASN1_STRING_get0_data(str);
to_add_len = ASN1_STRING_length(str);
to_add_len = ASN1_STRING_get_length(str);
}

if (to_add_len != -1) {
Expand Down Expand Up @@ -108,9 +108,9 @@ void php_openssl_add_assoc_name_entry(zval * val, char * key, X509_NAME * name,
}
}

void php_openssl_add_assoc_asn1_string(zval * val, char * key, ASN1_STRING * str)
void php_openssl_add_assoc_asn1_string(zval * val, char * key, const ASN1_STRING * str)
{
add_assoc_stringl(val, key, (const char *)ASN1_STRING_get0_data(str), ASN1_STRING_length(str));
add_assoc_stringl(val, key, (const char *)ASN1_STRING_get0_data(str), ASN1_STRING_get_length(str));
}

time_t php_openssl_asn1_time_to_time_t(ASN1_UTCTIME * timestr)
Expand All @@ -126,6 +126,7 @@ time_t php_openssl_asn1_time_to_time_t(ASN1_UTCTIME * timestr)
struct tm thetime;
char * strbuf;
char * thestr;
const char *timestr_data;
long gmadjust = 0;
size_t timestr_len;

Expand All @@ -134,24 +135,25 @@ time_t php_openssl_asn1_time_to_time_t(ASN1_UTCTIME * timestr)
return (time_t)-1;
}

timestr_len = (size_t)ASN1_STRING_length(timestr);
timestr_len = ASN1_STRING_get_length(timestr);
timestr_data = timestr_len ? (const char *)ASN1_STRING_get0_data(timestr) : "";

if (timestr_len != strlen((const char *)ASN1_STRING_get0_data(timestr))) {
if (memchr(timestr_data, '\0', timestr_len) != NULL) {
php_error_docref(NULL, E_WARNING, "Illegal length in timestamp");
return (time_t)-1;
}

if (timestr_len < 13) {
php_error_docref(NULL, E_WARNING, "Unable to parse time string %s correctly", ASN1_STRING_get0_data(timestr));
php_error_docref(NULL, E_WARNING, "Unable to parse time string %.*s correctly", (int)timestr_len, timestr_data);
return (time_t)-1;
}

if (ASN1_STRING_type(timestr) == V_ASN1_GENERALIZEDTIME && timestr_len < 15) {
php_error_docref(NULL, E_WARNING, "Unable to parse time string %s correctly", ASN1_STRING_get0_data(timestr));
php_error_docref(NULL, E_WARNING, "Unable to parse time string %.*s correctly", (int)timestr_len, timestr_data);
return (time_t)-1;
}

strbuf = estrdup((const char *)ASN1_STRING_get0_data(timestr));
strbuf = estrndup(timestr_data, timestr_len);

memset(&thetime, 0, sizeof(thetime));

Expand Down Expand Up @@ -618,11 +620,11 @@ zend_string* php_openssl_x509_fingerprint(X509 *peer, const char *method, bool r
/* Special handling of subjectAltName, see CVE-2013-4073
* Christian Heimes
*/
int openssl_x509v3_subjectAltName(BIO *bio, X509_EXTENSION *extension)
int openssl_x509v3_subjectAltName(BIO *bio, PHP_OPENSSL_X509_EXTENSION *extension)
{
GENERAL_NAMES *names;
const X509V3_EXT_METHOD *method = NULL;
ASN1_OCTET_STRING *extension_data;
const ASN1_OCTET_STRING *extension_data;
long i, length, num;
const unsigned char *p;

Expand All @@ -633,7 +635,7 @@ int openssl_x509v3_subjectAltName(BIO *bio, X509_EXTENSION *extension)

extension_data = X509_EXTENSION_get_data(extension);
p = ASN1_STRING_get0_data(extension_data);
length = ASN1_STRING_length(extension_data);
length = ASN1_STRING_get_length(extension_data);
if (method->it) {
names = (GENERAL_NAMES*) (ASN1_item_d2i(NULL, &p, length,
ASN1_ITEM_ptr(method->it)));
Expand All @@ -655,19 +657,19 @@ int openssl_x509v3_subjectAltName(BIO *bio, X509_EXTENSION *extension)
BIO_puts(bio, "email:");
as = name->d.rfc822Name;
BIO_write(bio, ASN1_STRING_get0_data(as),
ASN1_STRING_length(as));
ASN1_STRING_get_length(as));
break;
case GEN_DNS:
BIO_puts(bio, "DNS:");
as = name->d.dNSName;
BIO_write(bio, ASN1_STRING_get0_data(as),
ASN1_STRING_length(as));
ASN1_STRING_get_length(as));
break;
case GEN_URI:
BIO_puts(bio, "URI:");
as = name->d.uniformResourceIdentifier;
BIO_write(bio, ASN1_STRING_get0_data(as),
ASN1_STRING_length(as));
ASN1_STRING_get_length(as));
break;
default:
/* use builtin print for GEN_OTHERNAME, GEN_X400,
Expand Down Expand Up @@ -978,7 +980,12 @@ zend_result php_openssl_csr_make(struct php_x509_request * req, X509_REQ * csr,
zval *item, *subitem;
zend_string *strindex = NULL;

subj = X509_REQ_get_subject_name(csr);
subj = X509_NAME_new();
if (subj == NULL) {
php_openssl_store_errors();
return FAILURE;
}

/* apply values from the dn hash */
ZEND_HASH_FOREACH_STR_KEY_VAL(Z_ARRVAL_P(dn), strindex, item) {
if (strindex) {
Expand All @@ -987,10 +994,12 @@ zend_result php_openssl_csr_make(struct php_x509_request * req, X509_REQ * csr,
if (Z_TYPE_P(item) == IS_ARRAY) {
ZEND_HASH_FOREACH_NUM_KEY_VAL(Z_ARRVAL_P(item), i, subitem) {
if (php_openssl_csr_add_subj_entry(subitem, subj, nid) == FAILURE) {
X509_NAME_free(subj);
return FAILURE;
}
} ZEND_HASH_FOREACH_END();
} else if (php_openssl_csr_add_subj_entry(item, subj, nid) == FAILURE) {
X509_NAME_free(subj);
return FAILURE;
}
} else {
Expand Down Expand Up @@ -1041,13 +1050,23 @@ zend_result php_openssl_csr_make(struct php_x509_request * req, X509_REQ * csr,
if (!X509_NAME_add_entry_by_txt(subj, type, MBSTRING_UTF8, (unsigned char*)v->value, -1, -1, 0)) {
php_openssl_store_errors();
php_error_docref(NULL, E_WARNING, "add_entry_by_txt %s -> %s (failed)", type, v->value);
X509_NAME_free(subj);
return FAILURE;
}
if (!X509_NAME_entry_count(subj)) {
php_error_docref(NULL, E_WARNING, "No objects specified in config file");
X509_NAME_free(subj);
return FAILURE;
}
}

if (!X509_REQ_set_subject_name(csr, subj)) {
php_openssl_store_errors();
X509_NAME_free(subj);
return FAILURE;
}
X509_NAME_free(subj);

if (attribs) {
ZEND_HASH_FOREACH_STR_KEY_VAL(Z_ARRVAL_P(attribs), strindex, item) {
int nid;
Expand Down
2 changes: 1 addition & 1 deletion ext/openssl/openssl_backend_v3.c
Original file line number Diff line number Diff line change
Expand Up @@ -404,7 +404,7 @@ EVP_PKEY *php_openssl_pkey_init_ec(zval *data, bool *is_private) {
}

OPENSSL_PKEY_SET_BN(data, cofactor);
if (!OSSL_PARAM_BLD_push_BN(bld, OSSL_PKEY_PARAM_EC_COFACTOR, cofactor) ||
if ((cofactor && !OSSL_PARAM_BLD_push_BN(bld, OSSL_PKEY_PARAM_EC_COFACTOR, cofactor)) ||
!EC_GROUP_set_generator(group, point_g, order, cofactor)) {
goto cleanup;
}
Expand Down
1 change: 1 addition & 0 deletions ext/openssl/php_openssl.h
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@ extern zend_module_entry openssl_module_entry;
#include "php_version.h"
#define PHP_OPENSSL_VERSION PHP_VERSION

#include <openssl/opensslconf.h>
#include <openssl/opensslv.h>
/* OpenSSL version check */
#if OPENSSL_VERSION_NUMBER < 0x30000000L
Expand Down
17 changes: 14 additions & 3 deletions ext/openssl/php_openssl_backend.h
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,17 @@
#include <openssl/pkcs12.h>
#include <openssl/cms.h>

#if OPENSSL_VERSION_NUMBER < 0x40100000L
#define ASN1_STRING_set1_data(str, data, len) ASN1_STRING_set((str), (data), (int) (len))
#define ASN1_STRING_get_length(str) ((size_t) ASN1_STRING_length(str))
#endif

#if defined(OPENSSL_VERSION_MAJOR) && OPENSSL_VERSION_MAJOR >= 4
typedef const X509_EXTENSION PHP_OPENSSL_X509_EXTENSION;
#else
typedef X509_EXTENSION PHP_OPENSSL_X509_EXTENSION;
#endif

/* number conversion flags checks */
#define PHP_OPENSSL_CHECK_NUMBER_CONVERSION(_cond, _name, _arg_num) \
do { \
Expand Down Expand Up @@ -168,8 +179,8 @@ struct php_x509_request {
const EVP_CIPHER * priv_key_encrypt_cipher;
};

void php_openssl_add_assoc_name_entry(zval * val, char * key, X509_NAME * name, int shortname);
void php_openssl_add_assoc_asn1_string(zval * val, char * key, ASN1_STRING * str);
void php_openssl_add_assoc_name_entry(zval * val, char * key, const X509_NAME * name, int shortname);
void php_openssl_add_assoc_asn1_string(zval * val, char * key, const ASN1_STRING * str);
time_t php_openssl_asn1_time_to_time_t(ASN1_UTCTIME * timestr);
int php_openssl_config_check_syntax(const char * section_label, const char * config_filename, const char * section, CONF *config);
char *php_openssl_conf_get_string(CONF *conf, const char *group, const char *name);
Expand Down Expand Up @@ -266,7 +277,7 @@ X509 *php_openssl_x509_from_zval(

zend_string* php_openssl_x509_fingerprint(X509 *peer, const char *method, bool raw);

int openssl_x509v3_subjectAltName(BIO *bio, X509_EXTENSION *extension);
int openssl_x509v3_subjectAltName(BIO *bio, PHP_OPENSSL_X509_EXTENSION *extension);

STACK_OF(X509) *php_openssl_load_all_certs_from_file(
char *cert_file, size_t cert_file_len, uint32_t arg_num);
Expand Down
8 changes: 7 additions & 1 deletion ext/openssl/tests/bug28382.phpt
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,12 @@ openssl
<?php
$cert = file_get_contents(__DIR__ . "/bug28382cert.txt");
$ext = openssl_x509_parse($cert);

if (OPENSSL_VERSION_NUMBER >= 0x40000000) {
$extensions = &$ext['extensions'];
$extensions['crlDistributionPoints'] = preg_replace('/^Full Name:\R\s*/', '', trim($extensions['crlDistributionPoints']));
}

var_dump($ext['extensions']);
/*
* The reason for %A at the end of crlDistributionPoints and authorityKeyIdentifier is that
Expand All @@ -30,7 +36,7 @@ array(11) {
string(59) "B0:A7:FF:F9:41:15:DE:23:39:BD:DD:31:0F:97:A0:B2:A2:74:E0:FC"
["authorityKeyIdentifier"]=>
string(%d) "DirName:/C=RO/ST=Romania/L=Craiova/O=Sergiu/OU=Sergiu SRL/CN=Sergiu CA/emailAddress=n_sergiu@hotmail.com
serial:00%A"
serial:%A"
["keyUsage"]=>
string(71) "Digital Signature, Non Repudiation, Key Encipherment, Data Encipherment"
["nsBaseUrl"]=>
Expand Down
24 changes: 24 additions & 0 deletions ext/openssl/tests/ecc_custom_params.phpt
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,30 @@ openssl
--SKIPIF--
<?php
if (!defined("OPENSSL_KEYTYPE_EC")) die("skip EC disabled");

if (OPENSSL_VERSION_NUMBER >= 0x40000000) {
$d = hex2bin('8D0AC65AAEA0D6B96254C65817D4A143A9E7A03876F1A37D');
$p = hex2bin('BDB6F4FE3E8B1D9E0DA8C0D46F4C318CEFE4AFE3B6B8551F');
$a = hex2bin('BB8E5E8FBC115E139FE6A814FE48AAA6F0ADA1AA5DF91985');
$b = hex2bin('1854BEBDC31B21B7AEFC80AB0ECD10D5B1B3308E6DBF11C1');
$g_x = hex2bin('4AD5F7048DE709AD51236DE65E4D4B482C836DC6E4106640');
$g_y = hex2bin('02BB3A02D4AAADACAE24817A4CA3A1B014B5270432DB27D2');
$order = hex2bin('BDB6F4FE3E8B1D9E0DA8C0D40FC962195DFAE76F56564677');

if (@openssl_pkey_new(array(
'ec' => array(
'p' => $p,
'a' => $a,
'b' => $b,
'order' => $order,
'g_x' => $g_x,
'g_y' => $g_y,
'd' => $d,
),
)) === false) {
die("skip EC custom params unsupported with OpenSSL 4");
}
}
?>
--FILE--
<?php
Expand Down
20 changes: 18 additions & 2 deletions ext/openssl/tests/openssl_x509_parse_basic_openssl32.phpt
Original file line number Diff line number Diff line change
Expand Up @@ -8,12 +8,28 @@ if (OPENSSL_VERSION_NUMBER < 0x30200000) die('skip For OpenSSL >= 3.2');
?>
--FILE--
<?php
function normalize_openssl4_x509_parse_output(array $cert): array {
if (OPENSSL_VERSION_NUMBER < 0x40000000 || !isset($cert['serialNumberHex'], $cert['extensions']['authorityKeyIdentifier'])) {
return $cert;
}

$serial = strtoupper($cert['serialNumberHex']);
if (strlen($serial) % 2) {
$serial = '0' . $serial;
}
$serial = implode(':', str_split($serial, 2));
$cert['extensions']['authorityKeyIdentifier'] = preg_replace('/^serial:\d+$/m', 'serial:' . $serial, $cert['extensions']['authorityKeyIdentifier']);

return $cert;
}

$cert = "file://" . __DIR__ . "/cert.crt";

$parsedCert = openssl_x509_parse($cert);
var_dump($parsedCert === openssl_x509_parse(openssl_x509_read($cert)));
$parsedCert = normalize_openssl4_x509_parse_output($parsedCert);
var_dump($parsedCert === normalize_openssl4_x509_parse_output(openssl_x509_parse(openssl_x509_read($cert))));
var_dump($parsedCert);
var_dump(openssl_x509_parse($cert, false));
var_dump(normalize_openssl4_x509_parse_output(openssl_x509_parse($cert, false)));
?>
--EXPECTF--
bool(true)
Expand Down
Loading
Loading