Use OpenSSL libctx for various BIO readers (#19448)

This converts mostly PEM readers but also DER for CMS
This commit is contained in:
Jakub Zelenka 2025-08-11 17:21:38 +01:00 committed by GitHub
parent 6280dfc025
commit c5f79b8cf9
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
6 changed files with 204 additions and 30 deletions

View file

@ -2749,7 +2749,7 @@ PHP_FUNCTION(openssl_pkcs7_read)
goto clean_exit;
}
p7 = PEM_read_bio_PKCS7(bio_in, NULL, NULL, NULL);
p7 = php_openssl_pem_read_bio_pkcs7(bio_in);
if (p7 == NULL) {
php_openssl_store_errors();
goto clean_exit;
@ -3071,19 +3071,19 @@ PHP_FUNCTION(openssl_cms_verify)
switch (encoding) {
case ENCODING_PEM:
cms = PEM_read_bio_CMS(sigbio, NULL, 0, NULL);
datain = in;
break;
case ENCODING_DER:
cms = d2i_CMS_bio(sigbio, NULL);
datain = in;
break;
case ENCODING_SMIME:
cms = SMIME_read_CMS(sigbio, &datain);
break;
default:
php_error_docref(NULL, E_WARNING, "Unknown encoding");
goto clean_exit;
cms = php_openssl_pem_read_bio_cms(sigbio);
datain = in;
break;
case ENCODING_DER:
cms = php_openssl_d2i_bio_cms(sigbio);
datain = in;
break;
case ENCODING_SMIME:
cms = php_openssl_smime_read_cms(sigbio, &datain);
break;
default:
php_error_docref(NULL, E_WARNING, "Unknown encoding");
goto clean_exit;
}
if (cms == NULL) {
php_openssl_store_errors();
@ -3398,7 +3398,7 @@ PHP_FUNCTION(openssl_cms_read)
goto clean_exit;
}
cms = PEM_read_bio_CMS(bio_in, NULL, NULL, NULL);
cms = php_openssl_pem_read_bio_cms(bio_in);
if (cms == NULL) {
php_openssl_store_errors();
goto clean_exit;
@ -3703,13 +3703,13 @@ PHP_FUNCTION(openssl_cms_decrypt)
switch (encoding) {
case ENCODING_DER:
cms = d2i_CMS_bio(in, NULL);
cms = php_openssl_d2i_bio_cms(in);
break;
case ENCODING_PEM:
cms = PEM_read_bio_CMS(in, NULL, 0, NULL);
cms = php_openssl_pem_read_bio_cms(in);
break;
case ENCODING_SMIME:
cms = SMIME_read_CMS(in, &datain);
cms = php_openssl_smime_read_cms(in, &datain);
break;
default:
zend_argument_value_error(5, "must be an OPENSSL_ENCODING_* constant");

View file

@ -541,18 +541,14 @@ X509 *php_openssl_x509_from_str(
php_openssl_store_errors();
return NULL;
}
cert = PEM_read_bio_X509(in, NULL, NULL, NULL);
cert = php_openssl_pem_read_bio_x509(in);
} else {
in = BIO_new_mem_buf(ZSTR_VAL(cert_str), (int) ZSTR_LEN(cert_str));
if (in == NULL) {
php_openssl_store_errors();
return NULL;
}
#ifdef TYPEDEF_D2I_OF
cert = (X509 *) PEM_ASN1_read_bio((d2i_of_void *)d2i_X509, PEM_STRING_X509, in, NULL, NULL, NULL);
#else
cert = (X509 *) PEM_ASN1_read_bio((char *(*)())d2i_X509, PEM_STRING_X509, in, NULL, NULL, NULL);
#endif
cert = php_openssl_pem_read_asn1_bio_x509(in);
}
if (!BIO_free(in)) {
@ -1127,7 +1123,7 @@ X509_REQ *php_openssl_csr_from_str(zend_string *csr_str, uint32_t arg_num)
return NULL;
}
csr = PEM_read_bio_X509_REQ(in, NULL,NULL,NULL);
csr = php_openssl_pem_read_bio_x509_req(in);
if (csr == NULL) {
php_openssl_store_errors();
}
@ -1158,7 +1154,7 @@ EVP_PKEY *php_openssl_extract_public_key(EVP_PKEY *priv_key)
return NULL;
}
EVP_PKEY *pub_key = PEM_read_bio_PUBKEY(bio, NULL, NULL, NULL);
EVP_PKEY *pub_key = php_openssl_pem_read_bio_public_key(bio);
BIO_free(bio);
return pub_key;
}
@ -1290,7 +1286,7 @@ EVP_PKEY *php_openssl_pkey_from_zval(
zend_string_release_ex(val_str, false);
TMP_CLEAN;
}
key = PEM_read_bio_PUBKEY(in, NULL,NULL, NULL);
key = php_openssl_pem_read_bio_public_key(in);
BIO_free(in);
}
} else {
@ -1308,12 +1304,12 @@ EVP_PKEY *php_openssl_pkey_from_zval(
TMP_CLEAN;
}
if (passphrase == NULL) {
key = PEM_read_bio_PrivateKey(in, NULL, NULL, NULL);
key = php_openssl_pem_read_bio_private_key(in, NULL, NULL);
} else {
struct php_openssl_pem_password password;
password.key = passphrase;
password.len = passphrase_len;
key = PEM_read_bio_PrivateKey(in, NULL, php_openssl_pem_password_cb, &password);
key = php_openssl_pem_read_bio_private_key(in, php_openssl_pem_password_cb, &password);
}
BIO_free(in);
}

View file

@ -692,4 +692,49 @@ CONF *php_openssl_nconf_new(void)
return NCONF_new(NULL);
}
X509 *php_openssl_pem_read_asn1_bio_x509(BIO *in)
{
return PEM_ASN1_read_bio((d2i_of_void *)d2i_X509, PEM_STRING_X509, in, NULL, NULL, NULL);
}
X509 *php_openssl_pem_read_bio_x509(BIO *in)
{
return PEM_read_bio_X509(in, NULL, NULL, NULL);
}
X509_REQ *php_openssl_pem_read_bio_x509_req(BIO *in)
{
return PEM_read_bio_X509_REQ(in, NULL, NULL, NULL);
}
EVP_PKEY *php_openssl_pem_read_bio_public_key(BIO *in)
{
return PEM_read_bio_PUBKEY(in, NULL, NULL, NULL);
}
EVP_PKEY *php_openssl_pem_read_bio_private_key(BIO *in, pem_password_cb *cb, void *u)
{
return PEM_read_bio_PrivateKey(in, NULL, cb, u);
}
PKCS7 *php_openssl_pem_read_bio_pkcs7(BIO *in)
{
return PEM_read_bio_PKCS7(in, NULL, NULL, NULL);
}
CMS_ContentInfo *php_openssl_pem_read_bio_cms(BIO *in)
{
return PEM_read_bio_CMS(in, NULL, NULL, NULL);
}
CMS_ContentInfo *php_openssl_d2i_bio_cms(BIO *in)
{
return d2i_CMS_bio(in, NULL);
}
CMS_ContentInfo *php_openssl_smime_read_cms(BIO *bio, BIO **bcont)
{
return SMIME_read_CMS(bio, bcont);
}
#endif

View file

@ -843,4 +843,126 @@ CONF *php_openssl_nconf_new(void)
return NCONF_new_ex(PHP_OPENSSL_LIBCTX, NULL);
}
X509 *php_openssl_pem_read_asn1_bio_x509(BIO *in)
{
X509 *x = X509_new_ex(PHP_OPENSSL_LIBCTX, PHP_OPENSSL_PROPQ);
if (x == NULL) {
return NULL;
}
if (PEM_ASN1_read_bio((d2i_of_void *)d2i_X509, PEM_STRING_X509, in, (void **) &x, NULL, NULL) == NULL) {
X509_free(x);
return NULL;
}
return x;
}
X509 *php_openssl_pem_read_bio_x509(BIO *in)
{
X509 *x = X509_new_ex(PHP_OPENSSL_LIBCTX, PHP_OPENSSL_PROPQ);
if (x == NULL) {
return NULL;
}
if (PEM_read_bio_X509(in, &x, NULL, NULL) == NULL) {
X509_free(x);
return NULL;
}
return x;
}
X509_REQ *php_openssl_pem_read_bio_x509_req(BIO *in)
{
X509_REQ *xr = X509_REQ_new_ex(PHP_OPENSSL_LIBCTX, PHP_OPENSSL_PROPQ);
if (xr == NULL) {
return NULL;
}
if (PEM_read_bio_X509_REQ(in, &xr, NULL, NULL) == NULL) {
X509_REQ_free(xr);
return NULL;
}
return xr;
}
EVP_PKEY *php_openssl_pem_read_bio_public_key(BIO *in)
{
return PEM_read_bio_PUBKEY_ex(in, NULL, NULL, NULL, PHP_OPENSSL_LIBCTX, PHP_OPENSSL_PROPQ);
}
EVP_PKEY *php_openssl_pem_read_bio_private_key(BIO *in, pem_password_cb *cb, void *u)
{
return PEM_read_bio_PrivateKey_ex(in, NULL, cb, u, PHP_OPENSSL_LIBCTX, PHP_OPENSSL_PROPQ);
}
PKCS7 *php_openssl_pem_read_bio_pkcs7(BIO *in)
{
PKCS7 *p = PKCS7_new_ex(PHP_OPENSSL_LIBCTX, PHP_OPENSSL_PROPQ);
if (p == NULL) {
return NULL;
}
if (PEM_read_bio_PKCS7(in, &p, NULL, NULL) == NULL) {
PKCS7_free(p);
return NULL;
}
return p;
}
CMS_ContentInfo *php_openssl_pem_read_bio_cms(BIO *in)
{
CMS_ContentInfo *ci = CMS_ContentInfo_new_ex(PHP_OPENSSL_LIBCTX, PHP_OPENSSL_PROPQ);
if (ci == NULL) {
return NULL;
}
if (PEM_read_bio_CMS(in, &ci, NULL, NULL) == NULL) {
CMS_ContentInfo_free(ci);
return NULL;
}
return ci;
}
CMS_ContentInfo *php_openssl_d2i_bio_cms(BIO *in)
{
CMS_ContentInfo *ci = CMS_ContentInfo_new_ex(PHP_OPENSSL_LIBCTX, PHP_OPENSSL_PROPQ);
if (ci == NULL) {
return NULL;
}
if (d2i_CMS_bio(in, &ci) == NULL) {
CMS_ContentInfo_free(ci);
return NULL;
}
return ci;
}
CMS_ContentInfo *php_openssl_smime_read_cms(BIO *bio, BIO **bcont)
{
CMS_ContentInfo *ci = CMS_ContentInfo_new_ex(PHP_OPENSSL_LIBCTX, PHP_OPENSSL_PROPQ);
if (ci == NULL) {
return NULL;
}
if (SMIME_read_CMS_ex(bio, 0, bcont, &ci) == NULL) {
CMS_ContentInfo_free(ci);
return NULL;
}
return ci;
}
#endif

View file

@ -192,6 +192,16 @@ STACK_OF(X509) * php_openssl_load_all_certs_from_file(
EVP_PKEY * php_openssl_generate_private_key(struct php_x509_request * req);
zend_string *php_openssl_pkey_derive(EVP_PKEY *key, EVP_PKEY *peer_key, size_t requested_key_size);
X509 *php_openssl_pem_read_asn1_bio_x509(BIO *in);
X509 *php_openssl_pem_read_bio_x509(BIO *in);
X509_REQ *php_openssl_pem_read_bio_x509_req(BIO *in);
EVP_PKEY *php_openssl_pem_read_bio_public_key(BIO *in);
EVP_PKEY *php_openssl_pem_read_bio_private_key(BIO *in, pem_password_cb *cb, void *u);
PKCS7 *php_openssl_pem_read_bio_pkcs7(BIO *in);
CMS_ContentInfo *php_openssl_pem_read_bio_cms(BIO *in);
CMS_ContentInfo *php_openssl_d2i_bio_cms(BIO *in);
CMS_ContentInfo *php_openssl_smime_read_cms(BIO *bio, BIO **bcont);
#define PHP_SSL_REQ_INIT(req) memset(req, 0, sizeof(*req))
#define PHP_SSL_REQ_DISPOSE(req) php_openssl_dispose_config(req)
#define PHP_SSL_REQ_PARSE(req, zval) php_openssl_parse_config(req, zval)

View file

@ -27,6 +27,7 @@
#include "streams/php_streams_int.h"
#include "zend_smart_str.h"
#include "php_openssl.h"
#include "php_openssl_backend.h"
#include "php_network.h"
#include <openssl/ssl.h>
#include <openssl/rsa.h>
@ -850,7 +851,7 @@ static long php_openssl_load_stream_cafile(X509_STORE *cert_store, const char *c
add_cert: {
BIO_puts(buffer, line);
efree(line);
cert = PEM_read_bio_X509(buffer, NULL, 0, NULL);
cert = php_openssl_pem_read_bio_x509(buffer);
BIO_free(buffer);
buffer_active = 0;
if (cert && X509_STORE_add_cert(cert_store, cert)) {