Skip to content

Use custom OpenSSL libctx in md and cipher handling code #18516

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Draft
wants to merge 1 commit into
base: master
Choose a base branch
from
Draft
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
2 changes: 1 addition & 1 deletion ext/openssl/openssl.c
Original file line number Diff line number Diff line change
Expand Up @@ -4323,7 +4323,7 @@ PHP_FUNCTION(openssl_digest)
if (zend_parse_parameters(ZEND_NUM_ARGS(), "ss|b", &data, &data_len, &method, &method_len, &raw_output) == FAILURE) {
RETURN_THROWS();
}
mdtype = EVP_get_digestbyname(method);
mdtype = php_openssl_get_evp_md_by_name(method);
if (!mdtype) {
php_error_docref(NULL, E_WARNING, "Unknown digest algorithm");
RETURN_FALSE;
Expand Down
98 changes: 6 additions & 92 deletions ext/openssl/openssl_backend_common.c
Original file line number Diff line number Diff line change
Expand Up @@ -469,92 +469,6 @@ zend_result php_openssl_write_rand_file(const char * file, int egdsocket, int se
return SUCCESS;
}

EVP_MD * php_openssl_get_evp_md_from_algo(zend_long algo) {
EVP_MD *mdtype;

switch (algo) {
case OPENSSL_ALGO_SHA1:
mdtype = (EVP_MD *) EVP_sha1();
break;
case OPENSSL_ALGO_MD5:
mdtype = (EVP_MD *) EVP_md5();
break;
#ifndef OPENSSL_NO_MD4
case OPENSSL_ALGO_MD4:
mdtype = (EVP_MD *) EVP_md4();
break;
#endif
#ifndef OPENSSL_NO_MD2
case OPENSSL_ALGO_MD2:
mdtype = (EVP_MD *) EVP_md2();
break;
#endif
case OPENSSL_ALGO_SHA224:
mdtype = (EVP_MD *) EVP_sha224();
break;
case OPENSSL_ALGO_SHA256:
mdtype = (EVP_MD *) EVP_sha256();
break;
case OPENSSL_ALGO_SHA384:
mdtype = (EVP_MD *) EVP_sha384();
break;
case OPENSSL_ALGO_SHA512:
mdtype = (EVP_MD *) EVP_sha512();
break;
#ifndef OPENSSL_NO_RMD160
case OPENSSL_ALGO_RMD160:
mdtype = (EVP_MD *) EVP_ripemd160();
break;
#endif
default:
return NULL;
break;
}
return mdtype;
}

const EVP_CIPHER * php_openssl_get_evp_cipher_from_algo(zend_long algo) {
switch (algo) {
#ifndef OPENSSL_NO_RC2
case PHP_OPENSSL_CIPHER_RC2_40:
return EVP_rc2_40_cbc();
break;
case PHP_OPENSSL_CIPHER_RC2_64:
return EVP_rc2_64_cbc();
break;
case PHP_OPENSSL_CIPHER_RC2_128:
return EVP_rc2_cbc();
break;
#endif

#ifndef OPENSSL_NO_DES
case PHP_OPENSSL_CIPHER_DES:
return EVP_des_cbc();
break;
case PHP_OPENSSL_CIPHER_3DES:
return EVP_des_ede3_cbc();
break;
#endif

#ifndef OPENSSL_NO_AES
case PHP_OPENSSL_CIPHER_AES_128_CBC:
return EVP_aes_128_cbc();
break;
case PHP_OPENSSL_CIPHER_AES_192_CBC:
return EVP_aes_192_cbc();
break;
case PHP_OPENSSL_CIPHER_AES_256_CBC:
return EVP_aes_256_cbc();
break;
#endif


default:
return NULL;
break;
}
}

void php_openssl_backend_init(void)
{
#ifdef LIBRESSL_VERSION_NUMBER
Expand Down Expand Up @@ -1931,7 +1845,7 @@ PHP_OPENSSL_API zend_string* php_openssl_encrypt(
PHP_OPENSSL_CHECK_LONG_TO_INT_NULL_RETURN(tag_len, tag_len);


cipher_type = EVP_get_cipherbyname(method);
cipher_type = php_openssl_get_evp_cipher_by_name(method);
if (!cipher_type) {
php_error_docref(NULL, E_WARNING, "Unknown cipher algorithm");
return NULL;
Expand Down Expand Up @@ -2023,7 +1937,7 @@ PHP_OPENSSL_API zend_string* php_openssl_decrypt(
PHP_OPENSSL_CHECK_SIZE_T_TO_INT_NULL_RETURN(tag_len, tag);


cipher_type = EVP_get_cipherbyname(method);
cipher_type = php_openssl_get_evp_cipher_by_name(method);
if (!cipher_type) {
php_error_docref(NULL, E_WARNING, "Unknown cipher algorithm");
return NULL;
Expand Down Expand Up @@ -2079,11 +1993,11 @@ PHP_OPENSSL_API zend_string* php_openssl_decrypt(
return outbuf;
}

const EVP_CIPHER *php_openssl_get_evp_cipher_by_name(const char *method)
const EVP_CIPHER *php_openssl_get_evp_cipher_by_name_with_warning(const char *method)
{
const EVP_CIPHER *cipher_type;

cipher_type = EVP_get_cipherbyname(method);
cipher_type = php_openssl_get_evp_cipher_by_name(method);
if (!cipher_type) {
php_error_docref(NULL, E_WARNING, "Unknown cipher algorithm");
return NULL;
Expand All @@ -2095,14 +2009,14 @@ const EVP_CIPHER *php_openssl_get_evp_cipher_by_name(const char *method)

PHP_OPENSSL_API zend_long php_openssl_cipher_iv_length(const char *method)
{
const EVP_CIPHER *cipher_type = php_openssl_get_evp_cipher_by_name(method);
const EVP_CIPHER *cipher_type = php_openssl_get_evp_cipher_by_name_with_warning(method);

return cipher_type == NULL ? -1 : EVP_CIPHER_iv_length(cipher_type);
}

PHP_OPENSSL_API zend_long php_openssl_cipher_key_length(const char *method)
{
const EVP_CIPHER *cipher_type = php_openssl_get_evp_cipher_by_name(method);
const EVP_CIPHER *cipher_type = php_openssl_get_evp_cipher_by_name_with_warning(method);

return cipher_type == NULL ? -1 : EVP_CIPHER_key_length(cipher_type);
}
Expand Down
98 changes: 98 additions & 0 deletions ext/openssl/openssl_backend_v1.c
Original file line number Diff line number Diff line change
Expand Up @@ -561,6 +561,104 @@ zend_string *php_openssl_dh_compute_key(EVP_PKEY *pkey, char *pub_str, size_t pu
return data;
}

const EVP_MD *php_openssl_get_evp_md_by_name(const char *name)
{
return EVP_get_digestbyname(name);
}

const EVP_MD *php_openssl_get_evp_md_from_algo(zend_long algo)
{
EVP_MD *mdtype;

switch (algo) {
case OPENSSL_ALGO_SHA1:
mdtype = (EVP_MD *) EVP_sha1();
break;
case OPENSSL_ALGO_MD5:
mdtype = (EVP_MD *) EVP_md5();
break;
#ifndef OPENSSL_NO_MD4
case OPENSSL_ALGO_MD4:
mdtype = (EVP_MD *) EVP_md4();
break;
#endif
#ifndef OPENSSL_NO_MD2
case OPENSSL_ALGO_MD2:
mdtype = (EVP_MD *) EVP_md2();
break;
#endif
case OPENSSL_ALGO_SHA224:
mdtype = (EVP_MD *) EVP_sha224();
break;
case OPENSSL_ALGO_SHA256:
mdtype = (EVP_MD *) EVP_sha256();
break;
case OPENSSL_ALGO_SHA384:
mdtype = (EVP_MD *) EVP_sha384();
break;
case OPENSSL_ALGO_SHA512:
mdtype = (EVP_MD *) EVP_sha512();
break;
#ifndef OPENSSL_NO_RMD160
case OPENSSL_ALGO_RMD160:
mdtype = (EVP_MD *) EVP_ripemd160();
break;
#endif
default:
return NULL;
break;
}
return mdtype;
}

const EVP_CIPHER *php_openssl_get_evp_cipher_by_name(const char *name)
{
return EVP_get_cipherbyname(name);
}

const EVP_CIPHER *php_openssl_get_evp_cipher_from_algo(zend_long algo)
{
switch (algo) {
#ifndef OPENSSL_NO_RC2
case PHP_OPENSSL_CIPHER_RC2_40:
return EVP_rc2_40_cbc();
break;
case PHP_OPENSSL_CIPHER_RC2_64:
return EVP_rc2_64_cbc();
break;
case PHP_OPENSSL_CIPHER_RC2_128:
return EVP_rc2_cbc();
break;
#endif

#ifndef OPENSSL_NO_DES
case PHP_OPENSSL_CIPHER_DES:
return EVP_des_cbc();
break;
case PHP_OPENSSL_CIPHER_3DES:
return EVP_des_ede3_cbc();
break;
#endif

#ifndef OPENSSL_NO_AES
case PHP_OPENSSL_CIPHER_AES_128_CBC:
return EVP_aes_128_cbc();
break;
case PHP_OPENSSL_CIPHER_AES_192_CBC:
return EVP_aes_192_cbc();
break;
case PHP_OPENSSL_CIPHER_AES_256_CBC:
return EVP_aes_256_cbc();
break;
#endif


default:
return NULL;
break;
}
}

void php_openssl_get_cipher_methods(zval *return_value, bool aliases)
{
array_init(return_value);
Expand Down
69 changes: 68 additions & 1 deletion ext/openssl/openssl_backend_v3.c
Original file line number Diff line number Diff line change
Expand Up @@ -696,6 +696,73 @@ zend_string *php_openssl_dh_compute_key(EVP_PKEY *pkey, char *pub_str, size_t pu
return result;
}

const EVP_MD *php_openssl_get_evp_md_by_name(const char *name)
{
return EVP_MD_fetch(OPENSSL_G(libctx), name, OPENSSL_G(propq));
}

static const char *php_openssl_digest_names[] = {
[OPENSSL_ALGO_SHA1] = "SHA1",
[OPENSSL_ALGO_MD5] = "MD5",
#ifndef OPENSSL_NO_MD4
[OPENSSL_ALGO_MD4] = "MD4",
#endif
#ifndef OPENSSL_NO_MD2
[OPENSSL_ALGO_MD2] = "MD2",
#endif
[OPENSSL_ALGO_SHA224] = "SHA224",
[OPENSSL_ALGO_SHA256] = "SHA256",
[OPENSSL_ALGO_SHA384] = "SHA384",
[OPENSSL_ALGO_SHA512] = "SHA512",
#ifndef OPENSSL_NO_RMD160
[OPENSSL_ALGO_RMD160] = "RIPEMD160",
#endif
};

const EVP_MD *php_openssl_get_evp_md_from_algo(zend_long algo)
{
if (algo < 0 || algo >= (zend_long)(sizeof(php_openssl_digest_names) / sizeof(*php_openssl_digest_names))) {
return NULL;
}

const char *name = php_openssl_digest_names[algo];
if (!name) {
return NULL;
}

return php_openssl_get_evp_md_by_name(name);
}

static const char *php_openssl_cipher_names[] = {
[PHP_OPENSSL_CIPHER_RC2_40] = "RC2-40-CBC",
[PHP_OPENSSL_CIPHER_RC2_128] = "RC2-CBC",
[PHP_OPENSSL_CIPHER_RC2_64] = "RC2-64-CBC",
[PHP_OPENSSL_CIPHER_DES] = "DES-CBC",
[PHP_OPENSSL_CIPHER_3DES] = "DES-EDE3-CBC",
[PHP_OPENSSL_CIPHER_AES_128_CBC]= "AES-128-CBC",
[PHP_OPENSSL_CIPHER_AES_192_CBC]= "AES-192-CBC",
[PHP_OPENSSL_CIPHER_AES_256_CBC]= "AES-256-CBC",
};

const EVP_CIPHER *php_openssl_get_evp_cipher_by_name(const char *name)
{
return EVP_CIPHER_fetch(OPENSSL_G(libctx), name, OPENSSL_G(propq));
}

const EVP_CIPHER *php_openssl_get_evp_cipher_from_algo(zend_long algo)
{
if (algo < 0 || algo >= (zend_long)(sizeof(php_openssl_cipher_names) / sizeof(*php_openssl_cipher_names))) {
return NULL;
}

const char *name = php_openssl_cipher_names[algo];
if (!name) {
return NULL;
}

return php_openssl_get_evp_cipher_by_name(name);
}

static void php_openssl_add_cipher_name(const char *name, void *arg)
{
size_t len = strlen(name);
Expand All @@ -722,7 +789,7 @@ static int php_openssl_compare_func(Bucket *a, Bucket *b)
void php_openssl_get_cipher_methods(zval *return_value, bool aliases)
{
array_init(return_value);
EVP_CIPHER_do_all_provided(NULL,
EVP_CIPHER_do_all_provided(OPENSSL_G(libctx),
aliases ? php_openssl_add_cipher_or_alias : php_openssl_add_cipher,
return_value);
zend_hash_sort(Z_ARRVAL_P(return_value), php_openssl_compare_func, 1);
Expand Down
22 changes: 14 additions & 8 deletions ext/openssl/php_openssl_backend.h
Original file line number Diff line number Diff line change
Expand Up @@ -75,14 +75,17 @@ enum php_openssl_key_type {
OPENSSL_KEYTYPE_RSA,
OPENSSL_KEYTYPE_DSA,
OPENSSL_KEYTYPE_DH,
OPENSSL_KEYTYPE_EC,
OPENSSL_KEYTYPE_X25519,
OPENSSL_KEYTYPE_ED25519,
OPENSSL_KEYTYPE_X448,
OPENSSL_KEYTYPE_ED448,

OPENSSL_KEYTYPE_DEFAULT = OPENSSL_KEYTYPE_RSA,
OPENSSL_KEYTYPE_EC = OPENSSL_KEYTYPE_DH +1,
OPENSSL_KEYTYPE_X25519 = OPENSSL_KEYTYPE_DH +2,
OPENSSL_KEYTYPE_ED25519 = OPENSSL_KEYTYPE_DH +3,
OPENSSL_KEYTYPE_X448 = OPENSSL_KEYTYPE_DH +4,
OPENSSL_KEYTYPE_ED448 = OPENSSL_KEYTYPE_DH +5,
};

/* Cipher constants, do not forget to update php_openssl_cipher_names in
* openssl_backend_v3.c if new constant added. */
enum php_openssl_cipher_type {
PHP_OPENSSL_CIPHER_RC2_40,
PHP_OPENSSL_CIPHER_RC2_128,
Expand All @@ -106,10 +109,10 @@ enum php_openssl_encoding {
ENCODING_PEM,
};


#define MIN_KEY_LENGTH 384

/* constants used in ext/phar/util.c, keep in sync */
/* Constants used in ext/phar/util.c, keep in sync and do not forget to update
* php_openssl_digest_names in openssl_backend_v3.c if new constant added. */
#define OPENSSL_ALGO_SHA1 1
#define OPENSSL_ALGO_MD5 2
#ifndef OPENSSL_NO_MD4
Expand All @@ -126,6 +129,7 @@ enum php_openssl_encoding {
#ifndef OPENSSL_NO_RMD160
#define OPENSSL_ALGO_RMD160 10
#endif

#define DEBUG_SMIME 0

#if !defined(OPENSSL_NO_EC) && defined(EVP_PKEY_EC)
Expand Down Expand Up @@ -221,7 +225,9 @@ void php_openssl_dispose_config(struct php_x509_request * req);
zend_result php_openssl_load_rand_file(const char * file, int *egdsocket, int *seeded);
zend_result php_openssl_write_rand_file(const char * file, int egdsocket, int seeded);

EVP_MD * php_openssl_get_evp_md_from_algo(zend_long algo);
const EVP_MD *php_openssl_get_evp_md_by_name(const char *name);
const EVP_MD *php_openssl_get_evp_md_from_algo(zend_long algo);
const EVP_CIPHER * php_openssl_get_evp_cipher_by_name(const char *name);
const EVP_CIPHER * php_openssl_get_evp_cipher_from_algo(zend_long algo);

void php_openssl_backend_init(void);
Expand Down
Loading