]> granicus.if.org Git - php/commitdiff
Add OpenSSL 1.1.0 support to PHP 7.0
authorJakub Zelenka <bukka@php.net>
Fri, 7 Apr 2017 18:20:11 +0000 (19:20 +0100)
committerJakub Zelenka <bukka@php.net>
Fri, 7 Apr 2017 18:21:33 +0000 (19:21 +0100)
acinclude.m4
ext/openssl/openssl.c
ext/openssl/tests/001.phpt
ext/openssl/tests/bug41033.phpt
ext/openssl/tests/bug66501.phpt
ext/openssl/tests/openssl_error_string_basic.phpt
ext/openssl/tests/openssl_free_key.phpt
ext/openssl/xp_ssl.c
ext/phar/util.c

index 25c3c7d66b9cd1a6cdeccc16f3e5cb3c600d7c41..36bd1c22e5817e65107efe3fc3e9cebe6237071d 100644 (file)
@@ -2337,15 +2337,13 @@ AC_DEFUN([PHP_SETUP_OPENSSL],[
 
   dnl If pkg-config is found try using it
   if test "$PHP_OPENSSL_DIR" = "yes" && test -x "$PKG_CONFIG" && $PKG_CONFIG --exists openssl; then
-    if $PKG_CONFIG --atleast-version=1.1 openssl; then
-      AC_MSG_ERROR([OpenSSL version >= 1.1 is not supported.])
-    elif $PKG_CONFIG --atleast-version=0.9.8 openssl; then
+    if $PKG_CONFIG --atleast-version=0.9.8 openssl; then
       found_openssl=yes
       OPENSSL_LIBS=`$PKG_CONFIG --libs openssl`
       OPENSSL_INCS=`$PKG_CONFIG --cflags-only-I openssl`
       OPENSSL_INCDIR=`$PKG_CONFIG --variable=includedir openssl`
     else
-      AC_MSG_ERROR([OpenSSL version >= 0.9.8 and < 1.1 required.])
+      AC_MSG_ERROR([OpenSSL version 0.9.8 or greater required.])
     fi
 
     if test -n "$OPENSSL_LIBS"; then
index 51f2667e8214bde7955315123b2cd70b1cd59658..7a8ccc0a99d34b9cc7b97fd0261c2a3344bcdb25 100644 (file)
@@ -17,6 +17,7 @@
    |          Sascha Kettler <kettler@gmx.net>                            |
    |          Pierre-Alain Joye <pierre@php.net>                          |
    |          Marc Delling <delling@silpion.de> (PKCS12 functions)        |
+   |          Jakub Zelenka <bukka@php.net>                               |
    +----------------------------------------------------------------------+
  */
 
@@ -72,7 +73,9 @@
 #ifdef HAVE_OPENSSL_MD2_H
 #define OPENSSL_ALGO_MD2       4
 #endif
+#if OPENSSL_VERSION_NUMBER < 0x10100000L || defined (LIBRESSL_VERSION_NUMBER)
 #define OPENSSL_ALGO_DSS1      5
+#endif
 #if OPENSSL_VERSION_NUMBER >= 0x0090708fL
 #define OPENSSL_ALGO_SHA224 6
 #define OPENSSL_ALGO_SHA256 7
@@ -537,6 +540,145 @@ zend_module_entry openssl_module_entry = {
 ZEND_GET_MODULE(openssl)
 #endif
 
+/* {{{ OpenSSL compatibility functions and macros */
+#if OPENSSL_VERSION_NUMBER < 0x10100000L || defined (LIBRESSL_VERSION_NUMBER)
+#define EVP_PKEY_get0_RSA(_pkey) _pkey->pkey.rsa
+#define EVP_PKEY_get0_DH(_pkey) _pkey->pkey.dh
+#define EVP_PKEY_get0_DSA(_pkey) _pkey->pkey.dsa
+#define EVP_PKEY_get0_EC_KEY(_pkey) _pkey->pkey.ec
+
+static int RSA_set0_key(RSA *r, BIGNUM *n, BIGNUM *e, BIGNUM *d)
+{
+       r->n = n;
+       r->e = e;
+       r->d = d;
+
+       return 1;
+}
+
+static int RSA_set0_factors(RSA *r, BIGNUM *p, BIGNUM *q)
+{
+       r->p = p;
+       r->q = q;
+
+       return 1;
+}
+
+static int RSA_set0_crt_params(RSA *r, BIGNUM *dmp1, BIGNUM *dmq1, BIGNUM *iqmp)
+{
+       r->dmp1 = dmp1;
+       r->dmq1 = dmq1;
+       r->iqmp = iqmp;
+
+       return 1;
+}
+
+static void RSA_get0_key(const RSA *r, const BIGNUM **n, const BIGNUM **e, const BIGNUM **d)
+{
+       *n = r->n;
+       *e = r->e;
+       *d = r->d;
+}
+
+static void RSA_get0_factors(const RSA *r, const BIGNUM **p, const BIGNUM **q)
+{
+       *p = r->p;
+       *q = r->q;
+}
+
+static void RSA_get0_crt_params(const RSA *r, const BIGNUM **dmp1, const BIGNUM **dmq1, const BIGNUM **iqmp)
+{
+       *dmp1 = r->dmp1;
+       *dmq1 = r->dmq1;
+       *iqmp = r->iqmp;
+}
+
+static void DH_get0_pqg(const DH *dh, const BIGNUM **p, const BIGNUM **q, const BIGNUM **g)
+{
+       *p = dh->p;
+       *q = dh->q;
+       *g = dh->g;
+}
+
+static int DH_set0_pqg(DH *dh, BIGNUM *p, BIGNUM *q, BIGNUM *g)
+{
+       dh->p = p;
+       dh->q = q;
+       dh->g = g;
+
+       return 1;
+}
+
+static void DH_get0_key(const DH *dh, const BIGNUM **pub_key, const BIGNUM **priv_key)
+{
+       *pub_key = dh->pub_key;
+       *priv_key = dh->priv_key;
+}
+
+static int DH_set0_key(DH *dh, BIGNUM *pub_key, BIGNUM *priv_key)
+{
+       dh->pub_key = pub_key;
+       dh->priv_key = priv_key;
+
+       return 1;
+}
+
+static void DSA_get0_pqg(const DSA *d, const BIGNUM **p, const BIGNUM **q, const BIGNUM **g)
+{
+       *p = d->p;
+       *q = d->q;
+       *g = d->g;
+}
+
+int DSA_set0_pqg(DSA *d, BIGNUM *p, BIGNUM *q, BIGNUM *g)
+{
+       d->p = p;
+       d->q = q;
+       d->g = g;
+
+       return 1;
+}
+
+static void DSA_get0_key(const DSA *d, const BIGNUM **pub_key, const BIGNUM **priv_key)
+{
+       *pub_key = d->pub_key;
+       *priv_key = d->priv_key;
+}
+
+int DSA_set0_key(DSA *d, BIGNUM *pub_key, BIGNUM *priv_key)
+{
+       d->pub_key = pub_key;
+       d->priv_key = priv_key;
+
+       return 1;
+}
+
+#if OPENSSL_VERSION_NUMBER < 0x10002000L || defined (LIBRESSL_VERSION_NUMBER)
+
+static int X509_get_signature_nid(const X509 *x)
+{
+       return OBJ_obj2nid(x->sig_alg->algorithm);
+}
+
+#if OPENSSL_VERSION_NUMBER < 0x10000000L
+
+int EVP_PKEY_id(const EVP_PKEY *pkey)
+{
+       return pkey->type;
+}
+
+int EVP_PKEY_base_id(const EVP_PKEY *pkey)
+{
+       return EVP_PKEY_type(pkey->type);
+}
+
+#endif
+
+#endif
+
+#endif
+/* }}} */
+
 /* number conversion flags checks */
 #define PHP_OPENSSL_CHECK_NUMBER_CONVERSION(_cond, _name) \
        do { \
@@ -1107,9 +1249,11 @@ static EVP_MD * php_openssl_get_evp_md_from_algo(zend_long algo) { /* {{{ */
                        mdtype = (EVP_MD *) EVP_md2();
                        break;
 #endif
+#if OPENSSL_VERSION_NUMBER < 0x10100000L || defined (LIBRESSL_VERSION_NUMBER)
                case OPENSSL_ALGO_DSS1:
                        mdtype = (EVP_MD *) EVP_dss1();
                        break;
+#endif
 #if OPENSSL_VERSION_NUMBER >= 0x0090708fL
                case OPENSSL_ALGO_SHA224:
                        mdtype = (EVP_MD *) EVP_sha224();
@@ -1227,7 +1371,9 @@ PHP_MINIT_FUNCTION(openssl)
 #ifdef HAVE_OPENSSL_MD2_H
        REGISTER_LONG_CONSTANT("OPENSSL_ALGO_MD2", OPENSSL_ALGO_MD2, CONST_CS|CONST_PERSISTENT);
 #endif
+#if OPENSSL_VERSION_NUMBER < 0x10100000L || defined (LIBRESSL_VERSION_NUMBER)
        REGISTER_LONG_CONSTANT("OPENSSL_ALGO_DSS1", OPENSSL_ALGO_DSS1, CONST_CS|CONST_PERSISTENT);
+#endif
 #if OPENSSL_VERSION_NUMBER >= 0x0090708fL
        REGISTER_LONG_CONSTANT("OPENSSL_ALGO_SHA224", OPENSSL_ALGO_SHA224, CONST_CS|CONST_PERSISTENT);
        REGISTER_LONG_CONSTANT("OPENSSL_ALGO_SHA256", OPENSSL_ALGO_SHA256, CONST_CS|CONST_PERSISTENT);
@@ -1945,6 +2091,7 @@ static int openssl_x509v3_subjectAltName(BIO *bio, X509_EXTENSION *extension)
 {
        GENERAL_NAMES *names;
        const X509V3_EXT_METHOD *method = NULL;
+       ASN1_OCTET_STRING *extension_data;
        long i, length, num;
        const unsigned char *p;
 
@@ -1953,8 +2100,9 @@ static int openssl_x509v3_subjectAltName(BIO *bio, X509_EXTENSION *extension)
                return -1;
        }
 
-       p = extension->value->data;
-       length = extension->value->length;
+       extension_data = X509_EXTENSION_get_data(extension);
+       p = extension_data->data;
+       length = extension_data->length;
        if (method->it) {
                names = (GENERAL_NAMES*) (ASN1_item_d2i(NULL, &p, length,
                        ASN1_ITEM_ptr(method->it)));
@@ -2017,6 +2165,8 @@ PHP_FUNCTION(openssl_x509_parse)
        char * tmpstr;
        zval subitem;
        X509_EXTENSION *extension;
+       X509_NAME *subject_name;
+       char *cert_name;
        char *extname;
        BIO *bio_out;
        BUF_MEM *bio_buf;
@@ -2035,12 +2185,12 @@ PHP_FUNCTION(openssl_x509_parse)
        }
        array_init(return_value);
 
-       if (cert->name) {
-               add_assoc_string(return_value, "name", cert->name);
-       }
-/*     add_assoc_bool(return_value, "valid", cert->valid); */
+       subject_name = X509_get_subject_name(cert);
+       cert_name = X509_NAME_oneline(subject_name, NULL, 0);
+       add_assoc_string(return_value, "name", cert_name);
+       OPENSSL_free(cert_name);
 
-       add_assoc_name_entry(return_value, "subject",           X509_get_subject_name(cert), useshortnames);
+       add_assoc_name_entry(return_value, "subject",           subject_name, useshortnames);
        /* hash as used in CA directories to lookup cert by subject name */
        {
                char buf[32];
@@ -2085,7 +2235,7 @@ PHP_FUNCTION(openssl_x509_parse)
                add_assoc_string(return_value, "alias", tmpstr);
        }
 
-       sig_nid = OBJ_obj2nid((cert)->sig_alg->algorithm);
+       sig_nid = X509_get_signature_nid(cert);
        add_assoc_string(return_value, "signatureTypeSN", (char*)OBJ_nid2sn(sig_nid));
        add_assoc_string(return_value, "signatureTypeLN", (char*)OBJ_nid2ln(sig_nid));
        add_assoc_long(return_value, "signatureTypeNID", sig_nid);
@@ -3274,7 +3424,26 @@ PHP_FUNCTION(openssl_csr_get_public_key)
                RETURN_FALSE;
        }
 
-       tpubkey=X509_REQ_get_pubkey(csr);
+#if OPENSSL_VERSION_NUMBER >= 0x10100000L && !defined(LIBRESSL_VERSION_NUMBER)
+       /* Due to changes in OpenSSL 1.1 related to locking when decoding CSR,
+        * the pub key is not changed after assigning. It means if we pass
+        * a private key, it will be returned including the private part.
+        * If we duplicate it, then we get just the public part which is
+        * the same behavior as for OpenSSL 1.0 */
+       csr = X509_REQ_dup(csr);
+#endif
+       /* Retrieve the public key from the CSR */
+       tpubkey = X509_REQ_get_pubkey(csr);
+
+#if OPENSSL_VERSION_NUMBER >= 0x10100000L && !defined(LIBRESSL_VERSION_NUMBER)
+       /* We need to free the CSR as it was duplicated */
+       X509_REQ_free(csr);
+#endif
+
+       if (tpubkey == NULL) {
+               RETURN_FALSE;
+       }
+
        RETURN_RES(zend_register_resource(tpubkey, le_key));
 }
 /* }}} */
@@ -3567,13 +3736,20 @@ static int php_openssl_is_private_key(EVP_PKEY* pkey)
 {
        assert(pkey != NULL);
 
-       switch (pkey->type) {
+       switch (EVP_PKEY_id(pkey)) {
 #ifndef NO_RSA
                case EVP_PKEY_RSA:
                case EVP_PKEY_RSA2:
-                       assert(pkey->pkey.rsa != NULL);
-                       if (pkey->pkey.rsa != NULL && (NULL == pkey->pkey.rsa->p || NULL == pkey->pkey.rsa->q)) {
-                               return 0;
+                       {
+                               RSA *rsa = EVP_PKEY_get0_RSA(pkey);
+                               if (rsa != NULL) {
+                                       const BIGNUM *p, *q;
+
+                                       RSA_get0_factors(rsa, &p, &q);
+                                        if (p == NULL || q == NULL) {
+                                               return 0;
+                                        }
+                               }
                        }
                        break;
 #endif
@@ -3583,28 +3759,51 @@ static int php_openssl_is_private_key(EVP_PKEY* pkey)
                case EVP_PKEY_DSA2:
                case EVP_PKEY_DSA3:
                case EVP_PKEY_DSA4:
-                       assert(pkey->pkey.dsa != NULL);
+                       {
+                               DSA *dsa = EVP_PKEY_get0_DSA(pkey);
+                               if (dsa != NULL) {
+                                       const BIGNUM *p, *q, *g, *pub_key, *priv_key;
+
+                                       DSA_get0_pqg(dsa, &p, &q, &g);
+                                       if (p == NULL || q == NULL) {
+                                               return 0;
+                                       }
 
-                       if (NULL == pkey->pkey.dsa->p || NULL == pkey->pkey.dsa->q || NULL == pkey->pkey.dsa->priv_key){
-                               return 0;
+                                       DSA_get0_key(dsa, &pub_key, &priv_key);
+                                       if (priv_key == NULL) {
+                                               return 0;
+                                       }
+                               }
                        }
                        break;
 #endif
 #ifndef NO_DH
                case EVP_PKEY_DH:
-                       assert(pkey->pkey.dh != NULL);
+                       {
+                               DH *dh = EVP_PKEY_get0_DH(pkey);
+                               if (dh != NULL) {
+                                       const BIGNUM *p, *q, *g, *pub_key, *priv_key;
+
+                                       DH_get0_pqg(dh, &p, &q, &g);
+                                       if (p == NULL) {
+                                               return 0;
+                                       }
 
-                       if (NULL == pkey->pkey.dh->p || NULL == pkey->pkey.dh->priv_key) {
-                               return 0;
+                                       DH_get0_key(dh, &pub_key, &priv_key);
+                                       if (priv_key == NULL) {
+                                               return 0;
+                                       }
+                               }
                        }
                        break;
 #endif
 #ifdef HAVE_EVP_PKEY_EC
                case EVP_PKEY_EC:
-                       assert(pkey->pkey.ec != NULL);
-
-                       if ( NULL == EC_KEY_get0_private_key(pkey->pkey.ec)) {
-                               return 0;
+                       {
+                               EC_KEY *ec = EVP_PKEY_get0_EC_KEY(pkey);
+                               if (ec != NULL && NULL == EC_KEY_get0_private_key(ec)) {
+                                       return 0;
+                               }
                        }
                        break;
 #endif
@@ -3616,42 +3815,91 @@ static int php_openssl_is_private_key(EVP_PKEY* pkey)
 }
 /* }}} */
 
-#define OPENSSL_PKEY_GET_BN(_type, _name) do {                                                 \
-               if (pkey->pkey._type->_name != NULL) {                                                  \
-                       int len = BN_num_bytes(pkey->pkey._type->_name);                        \
-                       zend_string *str = zend_string_alloc(len, 0);                           \
-                       BN_bn2bin(pkey->pkey._type->_name, (unsigned char*)ZSTR_VAL(str));      \
-                       ZSTR_VAL(str)[len] = 0;                                                                         \
-                       add_assoc_str(&_type, #_name, str);                                                     \
-               }                                                                                                                               \
-       } while (0)
-
-#define OPENSSL_PKEY_SET_BN(_ht, _type, _name) do {                                            \
-               zval *bn;                                                                                                               \
-               if ((bn = zend_hash_str_find(_ht, #_name, sizeof(#_name)-1)) != NULL && \
-                               Z_TYPE_P(bn) == IS_STRING) {                                                    \
-                       _type->_name = BN_bin2bn(                                                                       \
-                               (unsigned char*)Z_STRVAL_P(bn),                                                 \
-                               (int)Z_STRLEN_P(bn), NULL);                                                                     \
-           }                                                               \
+#define OPENSSL_GET_BN(_array, _bn, _name) do { \
+               if (_bn != NULL) { \
+                       int len = BN_num_bytes(_bn); \
+                       zend_string *str = zend_string_alloc(len, 0); \
+                       BN_bn2bin(_bn, (unsigned char*)ZSTR_VAL(str)); \
+                       ZSTR_VAL(str)[len] = 0; \
+                       add_assoc_str(&_array, #_name, str); \
+               } \
+       } while (0);
+
+#define OPENSSL_PKEY_GET_BN(_type, _name) OPENSSL_GET_BN(_type, _name, _name)
+
+#define OPENSSL_PKEY_SET_BN(_data, _name) do { \
+               zval *bn; \
+               if ((bn = zend_hash_str_find(Z_ARRVAL_P(_data), #_name, sizeof(#_name)-1)) != NULL && \
+                               Z_TYPE_P(bn) == IS_STRING) { \
+                       _name = BN_bin2bn( \
+                               (unsigned char*)Z_STRVAL_P(bn), \
+                               (int)Z_STRLEN_P(bn), NULL); \
+               } else { \
+                       _name = NULL; \
+               } \
        } while (0);
 
+/* {{{ php_openssl_pkey_init_rsa */
+zend_bool php_openssl_pkey_init_and_assign_rsa(EVP_PKEY *pkey, RSA *rsa, zval *data)
+{
+       BIGNUM *n, *e, *d, *p, *q, *dmp1, *dmq1, *iqmp;
+
+       OPENSSL_PKEY_SET_BN(data, n);
+       OPENSSL_PKEY_SET_BN(data, e);
+       OPENSSL_PKEY_SET_BN(data, d);
+       if (!n || !d || !RSA_set0_key(rsa, n, e, d)) {
+               return 0;
+       }
+
+       OPENSSL_PKEY_SET_BN(data, p);
+       OPENSSL_PKEY_SET_BN(data, q);
+       if ((p || q) && !RSA_set0_factors(rsa, p, q)) {
+               return 0;
+       }
+
+       OPENSSL_PKEY_SET_BN(data, dmp1);
+       OPENSSL_PKEY_SET_BN(data, dmq1);
+       OPENSSL_PKEY_SET_BN(data, iqmp);
+       if ((dmp1 || dmq1 || iqmp) && !RSA_set0_crt_params(rsa, dmp1, dmq1, iqmp)) {
+               return 0;
+       }
+
+       if (!EVP_PKEY_assign_RSA(pkey, rsa)) {
+               return 0;
+       }
+
+       return 1;
+}
+
 /* {{{ php_openssl_pkey_init_dsa */
-zend_bool php_openssl_pkey_init_dsa(DSA *dsa)
+zend_bool php_openssl_pkey_init_dsa(DSA *dsa, zval *data)
 {
-       if (!dsa->p || !dsa->q || !dsa->g) {
+       BIGNUM *p, *q, *g, *priv_key, *pub_key;
+       const BIGNUM *priv_key_const, *pub_key_const;
+
+       OPENSSL_PKEY_SET_BN(data, p);
+       OPENSSL_PKEY_SET_BN(data, q);
+       OPENSSL_PKEY_SET_BN(data, g);
+       if (!p || !q || !g || !DSA_set0_pqg(dsa, p, q, g)) {
                return 0;
        }
-       if (dsa->priv_key || dsa->pub_key) {
-               return 1;
+
+       OPENSSL_PKEY_SET_BN(data, pub_key);
+       OPENSSL_PKEY_SET_BN(data, priv_key);
+       if (pub_key) {
+               return DSA_set0_key(dsa, pub_key, priv_key);
        }
+
+       /* generate key */
        PHP_OPENSSL_RAND_ADD_TIME();
        if (!DSA_generate_key(dsa)) {
                return 0;
        }
+
        /* if BN_mod_exp return -1, then DSA_generate_key succeed for failed key
         * so we need to double check that public key is created */
-       if (!dsa->pub_key || BN_is_zero(dsa->pub_key)) {
+       DSA_get0_key(dsa, &pub_key_const, &priv_key_const);
+       if (!pub_key_const || BN_is_zero(pub_key_const)) {
                return 0;
        }
        /* all good */
@@ -3659,15 +3907,69 @@ zend_bool php_openssl_pkey_init_dsa(DSA *dsa)
 }
 /* }}} */
 
+/* {{{ php_openssl_dh_pub_from_priv */
+static BIGNUM *php_openssl_dh_pub_from_priv(BIGNUM *priv_key, BIGNUM *g, BIGNUM *p)
+{
+       BIGNUM *pub_key, *priv_key_const_time;
+       BN_CTX *ctx;
+
+       pub_key = BN_new();
+       if (pub_key == NULL) {
+               return NULL;
+       }
+
+       priv_key_const_time = BN_new();
+       if (priv_key_const_time == NULL) {
+               BN_free(pub_key);
+               return NULL;
+       }
+       ctx = BN_CTX_new();
+       if (ctx == NULL) {
+               BN_free(pub_key);
+               BN_free(priv_key_const_time);
+               return NULL;
+       }
+
+       BN_with_flags(priv_key_const_time, priv_key, BN_FLG_CONSTTIME);
+
+       if (!BN_mod_exp_mont(pub_key, g, priv_key_const_time, p, ctx, NULL)) {
+               BN_free(pub_key);
+               pub_key = NULL;
+       }
+
+       BN_free(priv_key_const_time);
+       BN_CTX_free(ctx);
+
+       return pub_key;
+}
+/* }}} */
+
 /* {{{ php_openssl_pkey_init_dh */
-zend_bool php_openssl_pkey_init_dh(DH *dh)
+zend_bool php_openssl_pkey_init_dh(DH *dh, zval *data)
 {
-       if (!dh->p || !dh->g) {
+       BIGNUM *p, *q, *g, *priv_key, *pub_key;
+
+       OPENSSL_PKEY_SET_BN(data, p);
+       OPENSSL_PKEY_SET_BN(data, q);
+       OPENSSL_PKEY_SET_BN(data, g);
+       if (!p || !g || !DH_set0_pqg(dh, p, q, g)) {
                return 0;
        }
-       if (dh->pub_key) {
-               return 1;
+
+       OPENSSL_PKEY_SET_BN(data, priv_key);
+       OPENSSL_PKEY_SET_BN(data, pub_key);
+       if (pub_key) {
+               return DH_set0_key(dh, pub_key, priv_key);
        }
+       if (priv_key) {
+               pub_key = php_openssl_dh_pub_from_priv(priv_key, g, p);
+               if (pub_key == NULL) {
+                       return 0;
+               }
+               return DH_set0_key(dh, pub_key, priv_key);
+       }
+
+       /* generate key */
        PHP_OPENSSL_RAND_ADD_TIME();
        if (!DH_generate_key(dh)) {
                return 0;
@@ -3699,18 +4001,8 @@ PHP_FUNCTION(openssl_pkey_new)
                        if (pkey) {
                                RSA *rsa = RSA_new();
                                if (rsa) {
-                                       OPENSSL_PKEY_SET_BN(Z_ARRVAL_P(data), rsa, n);
-                                       OPENSSL_PKEY_SET_BN(Z_ARRVAL_P(data), rsa, e);
-                                       OPENSSL_PKEY_SET_BN(Z_ARRVAL_P(data), rsa, d);
-                                       OPENSSL_PKEY_SET_BN(Z_ARRVAL_P(data), rsa, p);
-                                       OPENSSL_PKEY_SET_BN(Z_ARRVAL_P(data), rsa, q);
-                                       OPENSSL_PKEY_SET_BN(Z_ARRVAL_P(data), rsa, dmp1);
-                                       OPENSSL_PKEY_SET_BN(Z_ARRVAL_P(data), rsa, dmq1);
-                                       OPENSSL_PKEY_SET_BN(Z_ARRVAL_P(data), rsa, iqmp);
-                                       if (rsa->n && rsa->d) {
-                                               if (EVP_PKEY_assign_RSA(pkey, rsa)) {
-                                                       RETURN_RES(zend_register_resource(pkey, le_key));
-                                               }
+                                       if (php_openssl_pkey_init_and_assign_rsa(pkey, rsa, data)) {
+                                               RETURN_RES(zend_register_resource(pkey, le_key));
                                        }
                                        RSA_free(rsa);
                                }
@@ -3723,12 +4015,7 @@ PHP_FUNCTION(openssl_pkey_new)
                        if (pkey) {
                                DSA *dsa = DSA_new();
                                if (dsa) {
-                                       OPENSSL_PKEY_SET_BN(Z_ARRVAL_P(data), dsa, p);
-                                       OPENSSL_PKEY_SET_BN(Z_ARRVAL_P(data), dsa, q);
-                                       OPENSSL_PKEY_SET_BN(Z_ARRVAL_P(data), dsa, g);
-                                       OPENSSL_PKEY_SET_BN(Z_ARRVAL_P(data), dsa, priv_key);
-                                       OPENSSL_PKEY_SET_BN(Z_ARRVAL_P(data), dsa, pub_key);
-                                       if (php_openssl_pkey_init_dsa(dsa)) {
+                                       if (php_openssl_pkey_init_dsa(dsa, data)) {
                                                if (EVP_PKEY_assign_DSA(pkey, dsa)) {
                                                        RETURN_RES(zend_register_resource(pkey, le_key));
                                                }
@@ -3744,11 +4031,7 @@ PHP_FUNCTION(openssl_pkey_new)
                        if (pkey) {
                                DH *dh = DH_new();
                                if (dh) {
-                                       OPENSSL_PKEY_SET_BN(Z_ARRVAL_P(data), dh, p);
-                                       OPENSSL_PKEY_SET_BN(Z_ARRVAL_P(data), dh, g);
-                                       OPENSSL_PKEY_SET_BN(Z_ARRVAL_P(data), dh, priv_key);
-                                       OPENSSL_PKEY_SET_BN(Z_ARRVAL_P(data), dh, pub_key);
-                                       if (php_openssl_pkey_init_dh(dh)) {
+                                       if (php_openssl_pkey_init_dh(dh, data)) {
                                                if (EVP_PKEY_assign_DH(pkey, dh)) {
                                                        ZVAL_COPY_VALUE(return_value, zend_list_insert(pkey, le_key));
                                                        return;
@@ -3826,7 +4109,7 @@ PHP_FUNCTION(openssl_pkey_export_to_file)
                        cipher = NULL;
                }
 
-               switch (EVP_PKEY_type(key->type)) {
+               switch (EVP_PKEY_base_id(key)) {
 #ifdef HAVE_EVP_PKEY_EC
                        case EVP_PKEY_EC:
                                pem_write = PEM_write_bio_ECPrivateKey(bio_out, EVP_PKEY_get1_EC_KEY(key), cipher, (unsigned char *)passphrase, (int)passphrase_len, NULL, NULL);
@@ -3896,7 +4179,7 @@ PHP_FUNCTION(openssl_pkey_export)
                        cipher = NULL;
                }
 
-               switch (EVP_PKEY_type(key->type)) {
+               switch (EVP_PKEY_base_id(key)) {
 #ifdef HAVE_EVP_PKEY_EC
                        case EVP_PKEY_EC:
                                pem_write = PEM_write_bio_ECPrivateKey(bio_out, EVP_PKEY_get1_EC_KEY(key), cipher, (unsigned char *)passphrase, (int)passphrase_len, NULL, NULL);
@@ -4019,24 +4302,32 @@ PHP_FUNCTION(openssl_pkey_get_details)
        /*TODO: Use the real values once the openssl constants are used
         * See the enum at the top of this file
         */
-       switch (EVP_PKEY_type(pkey->type)) {
+       switch (EVP_PKEY_base_id(pkey)) {
                case EVP_PKEY_RSA:
                case EVP_PKEY_RSA2:
-                       ktype = OPENSSL_KEYTYPE_RSA;
-
-                       if (pkey->pkey.rsa != NULL) {
-                               zval rsa;
-
-                               array_init(&rsa);
-                               OPENSSL_PKEY_GET_BN(rsa, n);
-                               OPENSSL_PKEY_GET_BN(rsa, e);
-                               OPENSSL_PKEY_GET_BN(rsa, d);
-                               OPENSSL_PKEY_GET_BN(rsa, p);
-                               OPENSSL_PKEY_GET_BN(rsa, q);
-                               OPENSSL_PKEY_GET_BN(rsa, dmp1);
-                               OPENSSL_PKEY_GET_BN(rsa, dmq1);
-                               OPENSSL_PKEY_GET_BN(rsa, iqmp);
-                               add_assoc_zval(return_value, "rsa", &rsa);
+                       {
+                               RSA *rsa = EVP_PKEY_get0_RSA(pkey);
+                               ktype = OPENSSL_KEYTYPE_RSA;
+
+                               if (rsa != NULL) {
+                                       zval z_rsa;
+                                       const BIGNUM *n, *e, *d, *p, *q, *dmp1, *dmq1, *iqmp;
+
+                                       RSA_get0_key(rsa, &n, &e, &d);
+                                       RSA_get0_factors(rsa, &p, &q);
+                                       RSA_get0_crt_params(rsa, &dmp1, &dmq1, &iqmp);
+
+                                       array_init(&z_rsa);
+                                       OPENSSL_PKEY_GET_BN(z_rsa, n);
+                                       OPENSSL_PKEY_GET_BN(z_rsa, e);
+                                       OPENSSL_PKEY_GET_BN(z_rsa, d);
+                                       OPENSSL_PKEY_GET_BN(z_rsa, p);
+                                       OPENSSL_PKEY_GET_BN(z_rsa, q);
+                                       OPENSSL_PKEY_GET_BN(z_rsa, dmp1);
+                                       OPENSSL_PKEY_GET_BN(z_rsa, dmq1);
+                                       OPENSSL_PKEY_GET_BN(z_rsa, iqmp);
+                                       add_assoc_zval(return_value, "rsa", &z_rsa);
+                               }
                        }
 
                        break;
@@ -4044,40 +4335,53 @@ PHP_FUNCTION(openssl_pkey_get_details)
                case EVP_PKEY_DSA2:
                case EVP_PKEY_DSA3:
                case EVP_PKEY_DSA4:
-                       ktype = OPENSSL_KEYTYPE_DSA;
-
-                       if (pkey->pkey.dsa != NULL) {
-                               zval dsa;
-
-                               array_init(&dsa);
-                               OPENSSL_PKEY_GET_BN(dsa, p);
-                               OPENSSL_PKEY_GET_BN(dsa, q);
-                               OPENSSL_PKEY_GET_BN(dsa, g);
-                               OPENSSL_PKEY_GET_BN(dsa, priv_key);
-                               OPENSSL_PKEY_GET_BN(dsa, pub_key);
-                               add_assoc_zval(return_value, "dsa", &dsa);
+                       {
+                               DSA *dsa = EVP_PKEY_get0_DSA(pkey);
+                               ktype = OPENSSL_KEYTYPE_DSA;
+
+                               if (dsa != NULL) {
+                                       zval z_dsa;
+                                       const BIGNUM *p, *q, *g, *priv_key, *pub_key;
+
+                                       DSA_get0_pqg(dsa, &p, &q, &g);
+                                       DSA_get0_key(dsa, &pub_key, &priv_key);
+
+                                       array_init(&z_dsa);
+                                       OPENSSL_PKEY_GET_BN(z_dsa, p);
+                                       OPENSSL_PKEY_GET_BN(z_dsa, q);
+                                       OPENSSL_PKEY_GET_BN(z_dsa, g);
+                                       OPENSSL_PKEY_GET_BN(z_dsa, priv_key);
+                                       OPENSSL_PKEY_GET_BN(z_dsa, pub_key);
+                                       add_assoc_zval(return_value, "dsa", &z_dsa);
+                               }
                        }
                        break;
                case EVP_PKEY_DH:
-
-                       ktype = OPENSSL_KEYTYPE_DH;
-
-                       if (pkey->pkey.dh != NULL) {
-                               zval dh;
-
-                               array_init(&dh);
-                               OPENSSL_PKEY_GET_BN(dh, p);
-                               OPENSSL_PKEY_GET_BN(dh, g);
-                               OPENSSL_PKEY_GET_BN(dh, priv_key);
-                               OPENSSL_PKEY_GET_BN(dh, pub_key);
-                               add_assoc_zval(return_value, "dh", &dh);
+                       {
+                               DH *dh = EVP_PKEY_get0_DH(pkey);
+                               ktype = OPENSSL_KEYTYPE_DH;
+
+                               if (dh != NULL) {
+                                       zval z_dh;
+                                       const BIGNUM *p, *q, *g, *priv_key, *pub_key;
+
+                                       DH_get0_pqg(dh, &p, &q, &g);
+                                       DH_get0_key(dh, &pub_key, &priv_key);
+
+                                       array_init(&z_dh);
+                                       OPENSSL_PKEY_GET_BN(z_dh, p);
+                                       OPENSSL_PKEY_GET_BN(z_dh, g);
+                                       OPENSSL_PKEY_GET_BN(z_dh, priv_key);
+                                       OPENSSL_PKEY_GET_BN(z_dh, pub_key);
+                                       add_assoc_zval(return_value, "dh", &z_dh);
+                               }
                        }
 
                        break;
 #ifdef HAVE_EVP_PKEY_EC
                case EVP_PKEY_EC:
                        ktype = OPENSSL_KEYTYPE_EC;
-                       if (pkey->pkey.ec != NULL) {
+                       if (EVP_PKEY_get0_EC_KEY(pkey) != NULL) {
                                zval ec;
                                const EC_GROUP *ec_group;
                                int nid;
@@ -4634,13 +4938,13 @@ PHP_FUNCTION(openssl_private_encrypt)
        cryptedlen = EVP_PKEY_size(pkey);
        cryptedbuf = zend_string_alloc(cryptedlen, 0);
 
-       switch (pkey->type) {
+       switch (EVP_PKEY_id(pkey)) {
                case EVP_PKEY_RSA:
                case EVP_PKEY_RSA2:
                        successful = (RSA_private_encrypt((int)data_len,
                                                (unsigned char *)data,
                                                (unsigned char *)ZSTR_VAL(cryptedbuf),
-                                               pkey->pkey.rsa,
+                                               EVP_PKEY_get0_RSA(pkey),
                                                (int)padding) == cryptedlen);
                        break;
                default:
@@ -4694,13 +4998,13 @@ PHP_FUNCTION(openssl_private_decrypt)
        cryptedlen = EVP_PKEY_size(pkey);
        crypttemp = emalloc(cryptedlen + 1);
 
-       switch (pkey->type) {
+       switch (EVP_PKEY_id(pkey)) {
                case EVP_PKEY_RSA:
                case EVP_PKEY_RSA2:
                        cryptedlen = RSA_private_decrypt((int)data_len,
                                        (unsigned char *)data,
                                        crypttemp,
-                                       pkey->pkey.rsa,
+                                       EVP_PKEY_get0_RSA(pkey),
                                        (int)padding);
                        if (cryptedlen != -1) {
                                cryptedbuf = zend_string_alloc(cryptedlen, 0);
@@ -4760,13 +5064,13 @@ PHP_FUNCTION(openssl_public_encrypt)
        cryptedlen = EVP_PKEY_size(pkey);
        cryptedbuf = zend_string_alloc(cryptedlen, 0);
 
-       switch (pkey->type) {
+       switch (EVP_PKEY_id(pkey)) {
                case EVP_PKEY_RSA:
                case EVP_PKEY_RSA2:
                        successful = (RSA_public_encrypt((int)data_len,
                                                (unsigned char *)data,
                                                (unsigned char *)ZSTR_VAL(cryptedbuf),
-                                               pkey->pkey.rsa,
+                                               EVP_PKEY_get0_RSA(pkey),
                                                (int)padding) == cryptedlen);
                        break;
                default:
@@ -4821,13 +5125,13 @@ PHP_FUNCTION(openssl_public_decrypt)
        cryptedlen = EVP_PKEY_size(pkey);
        crypttemp = emalloc(cryptedlen + 1);
 
-       switch (pkey->type) {
+       switch (EVP_PKEY_id(pkey)) {
                case EVP_PKEY_RSA:
                case EVP_PKEY_RSA2:
                        cryptedlen = RSA_public_decrypt((int)data_len,
                                        (unsigned char *)data,
                                        crypttemp,
-                                       pkey->pkey.rsa,
+                                       EVP_PKEY_get0_RSA(pkey),
                                        (int)padding);
                        if (cryptedlen != -1) {
                                cryptedbuf = zend_string_alloc(cryptedlen, 0);
@@ -4891,7 +5195,7 @@ PHP_FUNCTION(openssl_sign)
        zend_resource *keyresource = NULL;
        char * data;
        size_t data_len;
-       EVP_MD_CTX md_ctx;
+       EVP_MD_CTX *md_ctx;
        zval *method = NULL;
        zend_long signature_algo = OPENSSL_ALGO_SHA1;
        const EVP_MD *mdtype;
@@ -4924,9 +5228,11 @@ PHP_FUNCTION(openssl_sign)
        siglen = EVP_PKEY_size(pkey);
        sigbuf = zend_string_alloc(siglen, 0);
 
-       EVP_SignInit(&md_ctx, mdtype);
-       EVP_SignUpdate(&md_ctx, data, data_len);
-       if (EVP_SignFinal (&md_ctx, (unsigned char*)ZSTR_VAL(sigbuf), &siglen, pkey)) {
+       md_ctx = EVP_MD_CTX_create();
+       if (md_ctx != NULL &&
+                       EVP_SignInit(md_ctx, mdtype) &&
+                       EVP_SignUpdate(md_ctx, data, data_len) &&
+                       EVP_SignFinal(md_ctx, (unsigned char*)ZSTR_VAL(sigbuf), &siglen, pkey)) {
                zval_dtor(signature);
                ZSTR_VAL(sigbuf)[siglen] = '\0';
                ZSTR_LEN(sigbuf) = siglen;
@@ -4936,7 +5242,7 @@ PHP_FUNCTION(openssl_sign)
                efree(sigbuf);
                RETVAL_FALSE;
        }
-       EVP_MD_CTX_cleanup(&md_ctx);
+       EVP_MD_CTX_destroy(md_ctx);
        if (keyresource == NULL) {
                EVP_PKEY_free(pkey);
        }
@@ -4949,8 +5255,8 @@ PHP_FUNCTION(openssl_verify)
 {
        zval *key;
        EVP_PKEY *pkey;
-       int err;
-       EVP_MD_CTX md_ctx;
+       int err = 0;
+       EVP_MD_CTX *md_ctx;
        const EVP_MD *mdtype;
        zend_resource *keyresource = NULL;
        char * data;
@@ -4988,10 +5294,13 @@ PHP_FUNCTION(openssl_verify)
                RETURN_FALSE;
        }
 
-       EVP_VerifyInit (&md_ctx, mdtype);
-       EVP_VerifyUpdate (&md_ctx, data, data_len);
-       err = EVP_VerifyFinal(&md_ctx, (unsigned char *)signature, (unsigned int)signature_len, pkey);
-       EVP_MD_CTX_cleanup(&md_ctx);
+       md_ctx = EVP_MD_CTX_create();
+       if (md_ctx != NULL) {
+               EVP_VerifyInit(md_ctx, mdtype);
+               EVP_VerifyUpdate (md_ctx, data, data_len);
+               err = EVP_VerifyFinal(md_ctx, (unsigned char *)signature, (unsigned int)signature_len, pkey);
+       }
+       EVP_MD_CTX_destroy(md_ctx);
 
        if (keyresource == NULL) {
                EVP_PKEY_free(pkey);
@@ -5015,7 +5324,7 @@ PHP_FUNCTION(openssl_seal)
        char *method =NULL;
        size_t method_len = 0;
        const EVP_CIPHER *cipher;
-       EVP_CIPHER_CTX ctx;
+       EVP_CIPHER_CTX *ctx;
 
        if (zend_parse_parameters(ZEND_NUM_ARGS(), "sz/z/a/|sz/", &data, &data_len,
                                &sealdata, &ekeys, &pubkeys, &method, &method_len, &iv) == FAILURE) {
@@ -5068,22 +5377,23 @@ PHP_FUNCTION(openssl_seal)
                i++;
        } ZEND_HASH_FOREACH_END();
 
-       if (!EVP_EncryptInit(&ctx,cipher,NULL,NULL)) {
+       ctx = EVP_CIPHER_CTX_new();
+       if (ctx == NULL || !EVP_EncryptInit(ctx,cipher,NULL,NULL)) {
+               EVP_CIPHER_CTX_free(ctx);
                RETVAL_FALSE;
-               EVP_CIPHER_CTX_cleanup(&ctx);
                goto clean_exit;
        }
 
        /* allocate one byte extra to make room for \0 */
-       buf = emalloc(data_len + EVP_CIPHER_CTX_block_size(&ctx));
-       EVP_CIPHER_CTX_cleanup(&ctx);
+       buf = emalloc(data_len + EVP_CIPHER_CTX_block_size(ctx));
+       EVP_CIPHER_CTX_cleanup(ctx);
 
-       if (!EVP_SealInit(&ctx, cipher, eks, eksl, &iv_buf[0], pkeys, nkeys) ||
-                       !EVP_SealUpdate(&ctx, buf, &len1, (unsigned char *)data, (int)data_len) ||
-                       !EVP_SealFinal(&ctx, buf + len1, &len2)) {
+       if (!EVP_SealInit(ctx, cipher, eks, eksl, &iv_buf[0], pkeys, nkeys) ||
+                       !EVP_SealUpdate(ctx, buf, &len1, (unsigned char *)data, (int)data_len) ||
+                       !EVP_SealFinal(ctx, buf + len1, &len2)) {
                RETVAL_FALSE;
                efree(buf);
-               EVP_CIPHER_CTX_cleanup(&ctx);
+               EVP_CIPHER_CTX_free(ctx);
                goto clean_exit;
        }
 
@@ -5111,7 +5421,7 @@ PHP_FUNCTION(openssl_seal)
                efree(buf);
        }
        RETVAL_LONG(len1 + len2);
-       EVP_CIPHER_CTX_cleanup(&ctx);
+       EVP_CIPHER_CTX_free(ctx);
 
 clean_exit:
        for (i=0; i<nkeys; i++) {
@@ -5138,7 +5448,7 @@ PHP_FUNCTION(openssl_open)
        int len1, len2, cipher_iv_len;
        unsigned char *buf, *iv_buf;
        zend_resource *keyresource = NULL;
-       EVP_CIPHER_CTX ctx;
+       EVP_CIPHER_CTX *ctx;
        char * data;
        size_t data_len;
        char * ekey;
@@ -5189,26 +5499,23 @@ PHP_FUNCTION(openssl_open)
 
        buf = emalloc(data_len + 1);
 
-       if (EVP_OpenInit(&ctx, cipher, (unsigned char *)ekey, (int)ekey_len, iv_buf, pkey) &&
-                       EVP_OpenUpdate(&ctx, buf, &len1, (unsigned char *)data, (int)data_len)) {
-               if (!EVP_OpenFinal(&ctx, buf + len1, &len2) || (len1 + len2 == 0)) {
-                       efree(buf);
-                       RETVAL_FALSE;
-               } else {
-                       zval_dtor(opendata);
-                       buf[len1 + len2] = '\0';
-                       ZVAL_NEW_STR(opendata, zend_string_init((char*)buf, len1 + len2, 0));
-                       efree(buf);
-                       RETVAL_TRUE;
-               }
+       ctx = EVP_CIPHER_CTX_new();
+       if (ctx != NULL && EVP_OpenInit(ctx, cipher, (unsigned char *)ekey, (int)ekey_len, iv_buf, pkey) &&
+                       EVP_OpenUpdate(ctx, buf, &len1, (unsigned char *)data, (int)data_len) &&
+                       EVP_OpenFinal(ctx, buf + len1, &len2) && (len1 + len2 > 0)) {
+               zval_dtor(opendata);
+               buf[len1 + len2] = '\0';
+               ZVAL_NEW_STR(opendata, zend_string_init((char*)buf, len1 + len2, 0));
+               RETVAL_TRUE;
        } else {
-               efree(buf);
                RETVAL_FALSE;
        }
+
+       efree(buf);
        if (keyresource == NULL) {
                EVP_PKEY_free(pkey);
        }
-       EVP_CIPHER_CTX_cleanup(&ctx);
+       EVP_CIPHER_CTX_free(ctx);
 }
 /* }}} */
 
@@ -5266,7 +5573,7 @@ PHP_FUNCTION(openssl_digest)
        char *data, *method;
        size_t data_len, method_len;
        const EVP_MD *mdtype;
-       EVP_MD_CTX md_ctx;
+       EVP_MD_CTX *md_ctx;
        unsigned int siglen;
        zend_string *sigbuf;
 
@@ -5282,9 +5589,10 @@ PHP_FUNCTION(openssl_digest)
        siglen = EVP_MD_size(mdtype);
        sigbuf = zend_string_alloc(siglen, 0);
 
-       EVP_DigestInit(&md_ctx, mdtype);
-       EVP_DigestUpdate(&md_ctx, (unsigned char *)data, data_len);
-       if (EVP_DigestFinal (&md_ctx, (unsigned char *)ZSTR_VAL(sigbuf), &siglen)) {
+       md_ctx = EVP_MD_CTX_create();
+       if (EVP_DigestInit(md_ctx, mdtype) &&
+                       EVP_DigestUpdate(md_ctx, (unsigned char *)data, data_len) &&
+                       EVP_DigestFinal (md_ctx, (unsigned char *)ZSTR_VAL(sigbuf), &siglen)) {
                if (raw_output) {
                        ZSTR_VAL(sigbuf)[siglen] = '\0';
                        ZSTR_LEN(sigbuf) = siglen;
@@ -5302,6 +5610,8 @@ PHP_FUNCTION(openssl_digest)
                zend_string_release(sigbuf);
                RETVAL_FALSE;
        }
+
+       EVP_MD_CTX_destroy(md_ctx);
 }
 /* }}} */
 
@@ -5347,7 +5657,7 @@ PHP_FUNCTION(openssl_encrypt)
        char *data, *method, *password, *iv = "";
        size_t data_len, method_len, password_len, iv_len = 0, max_iv_len;
        const EVP_CIPHER *cipher_type;
-       EVP_CIPHER_CTX cipher_ctx;
+       EVP_CIPHER_CTX *cipher_ctx;
        int i=0, keylen;
        size_t outlen;
        zend_string *outbuf;
@@ -5365,6 +5675,12 @@ PHP_FUNCTION(openssl_encrypt)
 
        PHP_OPENSSL_CHECK_SIZE_T_TO_INT(data_len, data);
 
+       cipher_ctx = EVP_CIPHER_CTX_new();
+       if (!cipher_ctx) {
+               php_error_docref(NULL, E_WARNING, "Failed to create cipher context");
+               RETURN_FALSE;
+       }
+
        keylen = EVP_CIPHER_key_length(cipher_type);
        if (keylen > password_len) {
                key = emalloc(keylen);
@@ -5383,20 +5699,20 @@ PHP_FUNCTION(openssl_encrypt)
        outlen = data_len + EVP_CIPHER_block_size(cipher_type);
        outbuf = zend_string_alloc(outlen, 0);
 
-       EVP_EncryptInit(&cipher_ctx, cipher_type, NULL, NULL);
+       EVP_EncryptInit(cipher_ctx, cipher_type, NULL, NULL);
        if (password_len > keylen) {
                PHP_OPENSSL_CHECK_SIZE_T_TO_INT(password_len, password);
-               EVP_CIPHER_CTX_set_key_length(&cipher_ctx, (int)password_len);
+               EVP_CIPHER_CTX_set_key_length(cipher_ctx, (int)password_len);
        }
-       EVP_EncryptInit_ex(&cipher_ctx, NULL, NULL, key, (unsigned char *)iv);
+       EVP_EncryptInit_ex(cipher_ctx, NULL, NULL, key, (unsigned char *)iv);
        if (options & OPENSSL_ZERO_PADDING) {
-               EVP_CIPHER_CTX_set_padding(&cipher_ctx, 0);
+               EVP_CIPHER_CTX_set_padding(cipher_ctx, 0);
        }
        if (data_len > 0) {
-               EVP_EncryptUpdate(&cipher_ctx, (unsigned char*)ZSTR_VAL(outbuf), &i, (unsigned char *)data, (int)data_len);
+               EVP_EncryptUpdate(cipher_ctx, (unsigned char*)ZSTR_VAL(outbuf), &i, (unsigned char *)data, (int)data_len);
        }
        outlen = i;
-       if (EVP_EncryptFinal(&cipher_ctx, (unsigned char *)ZSTR_VAL(outbuf) + i, &i)) {
+       if (EVP_EncryptFinal(cipher_ctx, (unsigned char *)ZSTR_VAL(outbuf) + i, &i)) {
                outlen += i;
                if (options & OPENSSL_RAW_DATA) {
                        ZSTR_VAL(outbuf)[outlen] = '\0';
@@ -5419,7 +5735,7 @@ PHP_FUNCTION(openssl_encrypt)
        if (free_iv) {
                efree(iv);
        }
-       EVP_CIPHER_CTX_cleanup(&cipher_ctx);
+       EVP_CIPHER_CTX_free(cipher_ctx);
 }
 /* }}} */
 
@@ -5431,7 +5747,7 @@ PHP_FUNCTION(openssl_decrypt)
        char *data, *method, *password, *iv = "";
        size_t data_len, method_len, password_len, iv_len = 0;
        const EVP_CIPHER *cipher_type;
-       EVP_CIPHER_CTX cipher_ctx;
+       EVP_CIPHER_CTX *cipher_ctx;
        int i, keylen;
        size_t outlen;
        zend_string *outbuf;
@@ -5456,10 +5772,17 @@ PHP_FUNCTION(openssl_decrypt)
                RETURN_FALSE;
        }
 
+       cipher_ctx = EVP_CIPHER_CTX_new();
+       if (!cipher_ctx) {
+               php_error_docref(NULL, E_WARNING, "Failed to create cipher context");
+               RETURN_FALSE;
+       }
+
        if (!(options & OPENSSL_RAW_DATA)) {
                base64_str = php_base64_decode((unsigned char*)data, data_len);
                if (!base64_str) {
                        php_error_docref(NULL, E_WARNING, "Failed to base64 decode the input");
+                       EVP_CIPHER_CTX_free(cipher_ctx);
                        RETURN_FALSE;
                }
                data_len = ZSTR_LEN(base64_str);
@@ -5480,18 +5803,18 @@ PHP_FUNCTION(openssl_decrypt)
        outlen = data_len + EVP_CIPHER_block_size(cipher_type);
        outbuf = zend_string_alloc(outlen, 0);
 
-       EVP_DecryptInit(&cipher_ctx, cipher_type, NULL, NULL);
+       EVP_DecryptInit(cipher_ctx, cipher_type, NULL, NULL);
        if (password_len > keylen) {
                PHP_OPENSSL_CHECK_SIZE_T_TO_INT(password_len, password);
-               EVP_CIPHER_CTX_set_key_length(&cipher_ctx, (int)password_len);
+               EVP_CIPHER_CTX_set_key_length(cipher_ctx, (int)password_len);
        }
-       EVP_DecryptInit_ex(&cipher_ctx, NULL, NULL, key, (unsigned char *)iv);
+       EVP_DecryptInit_ex(cipher_ctx, NULL, NULL, key, (unsigned char *)iv);
        if (options & OPENSSL_ZERO_PADDING) {
-               EVP_CIPHER_CTX_set_padding(&cipher_ctx, 0);
+               EVP_CIPHER_CTX_set_padding(cipher_ctx, 0);
        }
-       EVP_DecryptUpdate(&cipher_ctx, (unsigned char*)ZSTR_VAL(outbuf), &i, (unsigned char *)data, (int)data_len);
+       EVP_DecryptUpdate(cipher_ctx, (unsigned char*)ZSTR_VAL(outbuf), &i, (unsigned char *)data, (int)data_len);
        outlen = i;
-       if (EVP_DecryptFinal(&cipher_ctx, (unsigned char *)ZSTR_VAL(outbuf) + i, &i)) {
+       if (EVP_DecryptFinal(cipher_ctx, (unsigned char *)ZSTR_VAL(outbuf) + i, &i)) {
                outlen += i;
                ZSTR_VAL(outbuf)[outlen] = '\0';
                ZSTR_LEN(outbuf) = outlen;
@@ -5509,7 +5832,7 @@ PHP_FUNCTION(openssl_decrypt)
        if (base64_str) {
                zend_string_release(base64_str);
        }
-       EVP_CIPHER_CTX_cleanup(&cipher_ctx);
+       EVP_CIPHER_CTX_free(cipher_ctx);
 }
 /* }}} */
 
@@ -5547,6 +5870,7 @@ PHP_FUNCTION(openssl_dh_compute_key)
        zval *key;
        char *pub_str;
        size_t pub_len;
+       DH *dh;
        EVP_PKEY *pkey;
        BIGNUM *pub;
        zend_string *data;
@@ -5558,15 +5882,19 @@ PHP_FUNCTION(openssl_dh_compute_key)
        if ((pkey = (EVP_PKEY *)zend_fetch_resource(Z_RES_P(key), "OpenSSL key", le_key)) == NULL) {
                RETURN_FALSE;
        }
-       if (EVP_PKEY_type(pkey->type) != EVP_PKEY_DH || !pkey->pkey.dh) {
+       if (EVP_PKEY_base_id(pkey) != EVP_PKEY_DH) {
+               RETURN_FALSE;
+       }
+       dh = EVP_PKEY_get0_DH(pkey);
+       if (dh == NULL) {
                RETURN_FALSE;
        }
 
        PHP_OPENSSL_CHECK_SIZE_T_TO_INT(pub_len, pub_key);
        pub = BN_bin2bn((unsigned char*)pub_str, (int)pub_len, NULL);
 
-       data = zend_string_alloc(DH_size(pkey->pkey.dh), 0);
-       len = DH_compute_key((unsigned char*)ZSTR_VAL(data), pub, pkey->pkey.dh);
+       data = zend_string_alloc(DH_size(dh), 0);
+       len = DH_compute_key((unsigned char*)ZSTR_VAL(data), pub, dh);
 
        if (len >= 0) {
                ZSTR_LEN(data) = len;
index 4ca9970bca2afb279e536c2893fc3ac191a96f07..627077e8f4f952618600cceb378de269ec120a1e 100644 (file)
@@ -18,7 +18,8 @@ for ($z = "", $i = 0; $i < 1024; $i++) {
                usleep($i);
 }
 
-$privkey = openssl_pkey_new();
+$conf = array('config' => dirname(__FILE__) . DIRECTORY_SEPARATOR . 'openssl.cnf');
+$privkey = openssl_pkey_new($conf);
 
 if ($privkey === false)
        die("failed to create private key");
@@ -30,7 +31,7 @@ if ($key_file_name === false)
 
 echo "Export key to file\n";
 
-openssl_pkey_export_to_file($privkey, $key_file_name, $passphrase) or die("failed to export to file $key_file_name");
+openssl_pkey_export_to_file($privkey, $key_file_name, $passphrase, $conf) or die("failed to export to file $key_file_name");
 
 echo "Load key from file - array syntax\n";
 
index 4aeae66f41367d048e89b6b840856f7ed40a98dc..c665be527312dc6e5004378cef831a87e820562b 100644 (file)
@@ -10,14 +10,14 @@ if (OPENSSL_VERSION_NUMBER < 0x009070af) die("skip");
 $prv = 'file://' . dirname(__FILE__) . '/' . 'bug41033.pem';
 $pub = 'file://' . dirname(__FILE__) . '/' . 'bug41033pub.pem';
 
-
+$alg = (OPENSSL_VERSION_NUMBER < 0x10000000) ? OPENSSL_ALGO_DSS1 : OPENSSL_ALGO_SHA1;
 $prkeyid = openssl_get_privatekey($prv, "1234");
 $ct = "Hello I am some text!";
-openssl_sign($ct, $signature, $prkeyid, OPENSSL_ALGO_DSS1);
+openssl_sign($ct, $signature, $prkeyid, $alg);
 echo "Signature: ".base64_encode($signature) . "\n";
 
 $pukeyid = openssl_get_publickey($pub);
-$valid = openssl_verify($ct, $signature, $pukeyid, OPENSSL_ALGO_DSS1);
+$valid = openssl_verify($ct, $signature, $pukeyid, $alg);
 echo "Signature validity: " . $valid . "\n";
 
 
index 7ad5e21749ff1e4d2a46916ff8ad3fcfbe9355e9..a9d1359cd82a129e7c257638cca064e0562bfc47 100644 (file)
@@ -16,7 +16,8 @@ AwEHoUQDQgAEPq4hbIWHvB51rdWr8ejrjWo4qVNWVugYFtPg/xLQw0mHkIPZ4DvK
 sqOTOnMoezkbSmVVMuwz9flvnqHGmQvmug==\r
 -----END EC PRIVATE KEY-----';\r
 $key = openssl_pkey_get_private($pkey);\r
-$res = openssl_sign($data ='alpha', $sign, $key, 'ecdsa-with-SHA1');\r
+$sigalg = (OPENSSL_VERSION_NUMBER < 0x10000000) ? 'ecdsa-with-SHA1' : 'SHA1';\r
+$res = openssl_sign($data ='alpha', $sign, $key, $sigalg);\r
 var_dump($res);\r
 --EXPECTF--\r
 bool(true)\r
index 82f3099264ea776762fe62a2643583b523597f2c..04cc5508a4af4f6b212f10e7340baad4f52babc6 100644 (file)
@@ -89,7 +89,7 @@ expect_openssl_errors('openssl_pkey_export_to_file opening', ['02001002', '2006D
 expect_openssl_errors('openssl_pkey_export_to_file pem', ['0906D06C']);
 // file to export cannot be written
 @openssl_pkey_export_to_file($private_key_file, $invalid_file_for_write);
-expect_openssl_errors('openssl_pkey_export_to_file write', ['2006D002', '09072007']);
+expect_openssl_errors('openssl_pkey_export_to_file write', ['2006D002']);
 // succesful export
 @openssl_pkey_export($private_key_file_with_pass, $out, 'wrong pwd');
 expect_openssl_errors('openssl_pkey_export', ['06065064', '0906A065']);
@@ -105,7 +105,7 @@ expect_openssl_errors('openssl_private_decrypt', ['04065072']);
 // public encrypt and decrypt with failed padding check and padding
 @openssl_public_encrypt("data", $crypted, $public_key_file, 1000);
 @openssl_public_decrypt("data", $crypted, $public_key_file);
-expect_openssl_errors('openssl_private_(en|de)crypt padding', ['0906D06C', '04068076', '0407006A', '04067072']);
+expect_openssl_errors('openssl_private_(en|de)crypt padding', ['0906D06C', '04068076', '04067072']);
 
 // X509
 echo "X509 errors\n";
@@ -126,7 +126,7 @@ expect_openssl_errors('openssl_x509_checkpurpose purpose', ['0B086079']);
 echo "CSR errors\n";
 // file for csr (file:///) fails when opennig (BIO_new_file)
 @openssl_csr_get_subject("file://" . $invalid_file_for_read);
-expect_openssl_errors('openssl_csr_get_subject open', ['02001002', '2006D080', '20068079', '0906D06C']);
+expect_openssl_errors('openssl_csr_get_subject open', ['02001002', '2006D080']);
 // file or str csr is not correct PEM - failing PEM_read_bio_X509_REQ
 @openssl_csr_get_subject($crt_file);
 expect_openssl_errors('openssl_csr_get_subjec pem', ['0906D06C']);
index 816f7cf5eb183307f67b299a7c9dc8e4a206ceec..ea79ce703a98aa67a32449da06cb402c06898d14 100644 (file)
@@ -22,7 +22,8 @@ for ($z = "", $i = 0; $i < 1024; $i++) {
         usleep($i);
 }
 
-$privkey = openssl_pkey_new();
+$conf = array('config' => dirname(__FILE__) . DIRECTORY_SEPARATOR . 'openssl.cnf');
+$privkey = openssl_pkey_new($conf);
 
 if ($privkey === false)
     die("failed to create private key");
@@ -34,7 +35,7 @@ if ($key_file_name === false)
 
 echo "Export key to file\n";
 
-openssl_pkey_export_to_file($privkey, $key_file_name, $passphrase) or die("failed to export to file $key_file_name");
+openssl_pkey_export_to_file($privkey, $key_file_name, $passphrase, $conf) or die("failed to export to file $key_file_name");
 
 echo "Load key from file - array syntax\n";
 
index 7db219ddecfc3abcdc0b2147562b2e6686eab047..193eb531ee2de8840b9c6f4b683ea680244404bf 100644 (file)
@@ -996,6 +996,21 @@ static const SSL_METHOD *php_select_crypto_method(zend_long method_value, int is
 }
 /* }}} */
 
+#define PHP_SSL_MAX_VERSION_LEN 32
+
+static char *php_ssl_cipher_get_version(const SSL_CIPHER *c, char *buffer, size_t max_len) /* {{{ */
+{
+       const char *version = SSL_CIPHER_get_version(c);
+
+       strncpy(buffer, version, max_len);
+       if (max_len <= strlen(version)) {
+               buffer[max_len - 1] = 0;
+       }
+
+       return buffer;
+}
+/* }}} */
+
 static int php_get_crypto_method_ctx_flags(int method_flags) /* {{{ */
 {
        int ssl_ctx_options = SSL_OP_ALL;
@@ -1210,7 +1225,7 @@ static int set_server_dh_param(php_stream * stream, SSL_CTX *ctx) /* {{{ */
 /* }}} */
 #endif
 
-#ifdef HAVE_ECDH
+#if defined(HAVE_ECDH) && (OPENSSL_VERSION_NUMBER < 0x10100000L || defined (LIBRESSL_VERSION_NUMBER))
 static int set_server_ecdh_curve(php_stream *stream, SSL_CTX *ctx) /* {{{ */
 {
        zval *zvcurve;
@@ -1253,7 +1268,7 @@ static int set_server_specific_opts(php_stream *stream, SSL_CTX *ctx) /* {{{ */
        zval *zv;
        long ssl_ctx_options = SSL_CTX_get_options(ctx);
 
-#ifdef HAVE_ECDH
+#if defined(HAVE_ECDH) && (OPENSSL_VERSION_NUMBER < 0x10100000L || defined (LIBRESSL_VERSION_NUMBER))
        if (set_server_ecdh_curve(stream, ctx) == FAILURE) {
                return FAILURE;
        }
@@ -1684,6 +1699,7 @@ static zend_array *capture_session_meta(SSL *ssl_handle) /* {{{ */
        char *proto_str;
        long proto = SSL_version(ssl_handle);
        const SSL_CIPHER *cipher = SSL_get_current_cipher(ssl_handle);
+       char version_str[PHP_SSL_MAX_VERSION_LEN];
 
        switch (proto) {
 #ifdef HAVE_TLS12
@@ -1716,7 +1732,7 @@ static zend_array *capture_session_meta(SSL *ssl_handle) /* {{{ */
        add_assoc_string(&meta_arr, "protocol", proto_str);
        add_assoc_string(&meta_arr, "cipher_name", (char *) SSL_CIPHER_get_name(cipher));
        add_assoc_long(&meta_arr, "cipher_bits", SSL_CIPHER_get_bits(cipher, NULL));
-       add_assoc_string(&meta_arr, "cipher_version", SSL_CIPHER_get_version(cipher));
+       add_assoc_string(&meta_arr, "cipher_version", php_ssl_cipher_get_version(cipher, version_str, PHP_SSL_MAX_VERSION_LEN));
 
        return Z_ARR(meta_arr);
 }
@@ -2292,6 +2308,7 @@ static int php_openssl_sockop_set_option(php_stream *stream, int option, int val
                        if (sslsock->ssl_active) {
                                zval tmp;
                                char *proto_str;
+                               char version_str[PHP_SSL_MAX_VERSION_LEN];
                                const SSL_CIPHER *cipher;
 
                                array_init(&tmp);
@@ -2318,7 +2335,7 @@ static int php_openssl_sockop_set_option(php_stream *stream, int option, int val
                                add_assoc_string(&tmp, "protocol", proto_str);
                                add_assoc_string(&tmp, "cipher_name", (char *) SSL_CIPHER_get_name(cipher));
                                add_assoc_long(&tmp, "cipher_bits", SSL_CIPHER_get_bits(cipher, NULL));
-                               add_assoc_string(&tmp, "cipher_version", SSL_CIPHER_get_version(cipher));
+                               add_assoc_string(&tmp, "cipher_version", php_ssl_cipher_get_version(cipher, version_str, PHP_SSL_MAX_VERSION_LEN));
 
 #ifdef HAVE_TLS_ALPN
                                {
index 9f7fcaed795e730e4740f0df7731e3449d2e1910..f571429beedc3d970b47aaee1194347bb2467b32 100644 (file)
@@ -1494,7 +1494,7 @@ int phar_verify_signature(php_stream *fp, size_t end_of_phar, php_uint32 sig_typ
                        BIO *in;
                        EVP_PKEY *key;
                        EVP_MD *mdtype = (EVP_MD *) EVP_sha1();
-                       EVP_MD_CTX md_ctx;
+                       EVP_MD_CTX *md_ctx;
 #else
                        int tempsig;
 #endif
@@ -1567,7 +1567,8 @@ int phar_verify_signature(php_stream *fp, size_t end_of_phar, php_uint32 sig_typ
                                return FAILURE;
                        }
 
-                       EVP_VerifyInit(&md_ctx, mdtype);
+                       md_ctx = EVP_MD_CTX_create();
+                       EVP_VerifyInit(md_ctx, mdtype);
                        read_len = end_of_phar;
 
                        if (read_len > sizeof(buf)) {
@@ -1579,7 +1580,7 @@ int phar_verify_signature(php_stream *fp, size_t end_of_phar, php_uint32 sig_typ
                        php_stream_seek(fp, 0, SEEK_SET);
 
                        while (read_size && (len = php_stream_read(fp, (char*)buf, read_size)) > 0) {
-                               EVP_VerifyUpdate (&md_ctx, buf, len);
+                               EVP_VerifyUpdate (md_ctx, buf, len);
                                read_len -= (zend_off_t)len;
 
                                if (read_len < read_size) {
@@ -1587,9 +1588,9 @@ int phar_verify_signature(php_stream *fp, size_t end_of_phar, php_uint32 sig_typ
                                }
                        }
 
-                       if (EVP_VerifyFinal(&md_ctx, (unsigned char *)sig, sig_len, key) != 1) {
+                       if (EVP_VerifyFinal(md_ctx, (unsigned char *)sig, sig_len, key) != 1) {
                                /* 1: signature verified, 0: signature does not match, -1: failed signature operation */
-                               EVP_MD_CTX_cleanup(&md_ctx);
+                               EVP_MD_CTX_destroy(md_ctx);
 
                                if (error) {
                                        spprintf(error, 0, "broken openssl signature");
@@ -1598,7 +1599,7 @@ int phar_verify_signature(php_stream *fp, size_t end_of_phar, php_uint32 sig_typ
                                return FAILURE;
                        }
 
-                       EVP_MD_CTX_cleanup(&md_ctx);
+                       EVP_MD_CTX_destroy(md_ctx);
 #endif
 
                        *signature_len = phar_hex_str((const char*)sig, sig_len, signature);