Skip site navigation (1)Skip section navigation (2)
Date:      Thu, 11 Oct 2018 08:02:32 +0000 (UTC)
From:      Alex Dupre <ale@FreeBSD.org>
To:        ports-committers@freebsd.org, svn-ports-all@freebsd.org, svn-ports-head@freebsd.org
Subject:   svn commit: r481790 - head/security/php56-openssl/files
Message-ID:  <201810110802.w9B82WS1019138@repo.freebsd.org>

next in thread | raw e-mail | index | archive | help
Author: ale
Date: Thu Oct 11 08:02:31 2018
New Revision: 481790
URL: https://svnweb.freebsd.org/changeset/ports/481790

Log:
  Fix build with openssl 1.1.x.
  
  PR:		228897
  Submitted by:	brnrd

Added:
  head/security/php56-openssl/files/
  head/security/php56-openssl/files/patch-openssl11   (contents, props changed)

Added: head/security/php56-openssl/files/patch-openssl11
==============================================================================
--- /dev/null	00:00:00 1970	(empty, because file is newly added)
+++ head/security/php56-openssl/files/patch-openssl11	Thu Oct 11 08:02:31 2018	(r481790)
@@ -0,0 +1,1203 @@
+diff -rupN openssl.c openssl.c
+--- openssl.c	2017-07-06 00:25:00.000000000 +0200
++++ openssl.c	2017-08-01 10:55:28.108819344 +0200
+@@ -42,6 +42,12 @@
+ 
+ /* OpenSSL includes */
+ #include <openssl/evp.h>
++#if OPENSSL_VERSION_NUMBER >= 0x10002000L
++#include <openssl/bn.h>
++#include <openssl/rsa.h>
++#include <openssl/dsa.h>
++#include <openssl/dh.h>
++#endif
+ #include <openssl/x509.h>
+ #include <openssl/x509v3.h>
+ #include <openssl/crypto.h>
+@@ -531,6 +537,133 @@ 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)
++#define EVP_PKEY_id(_pkey) _pkey->type
++#define EVP_PKEY_base_id(_key) EVP_PKEY_type(_key->type)
++
++static int X509_get_signature_nid(const X509 *x)
++{
++	return OBJ_obj2nid(x->sig_alg->algorithm);
++}
++
++#endif
++
++#endif
++/* }}} */
++
+ static int le_key;
+ static int le_x509;
+ static int le_csr;
+@@ -825,7 +958,7 @@ static int add_oid_section(struct php_x5
+ 	}
+ 	for (i = 0; i < sk_CONF_VALUE_num(sktmp); i++) {
+ 		cnf = sk_CONF_VALUE_value(sktmp, i);
+-		if (OBJ_create(cnf->value, cnf->name, cnf->name) == NID_undef) {
++		if (OBJ_sn2nid(cnf->name) == NID_undef && OBJ_ln2nid(cnf->name) == NID_undef && OBJ_create(cnf->value, cnf->name, cnf->name) == NID_undef) {
+ 			php_error_docref(NULL TSRMLS_CC, E_WARNING, "problem creating object %s=%s", cnf->name, cnf->value);
+ 			return FAILURE;
+ 		}
+@@ -967,7 +1100,7 @@ static void php_openssl_dispose_config(s
+ }
+ /* }}} */
+ 
+-#ifdef PHP_WIN32
++#if defined(PHP_WIN32) || (OPENSSL_VERSION_NUMBER >= 0x10100000L && !defined(LIBRESSL_VERSION_NUMBER))
+ #define PHP_OPENSSL_RAND_ADD_TIME() ((void) 0)
+ #else
+ #define PHP_OPENSSL_RAND_ADD_TIME() php_openssl_rand_add_timeval()
+@@ -1053,9 +1186,11 @@ static EVP_MD * php_openssl_get_evp_md_f
+ 			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();
+@@ -1146,6 +1281,12 @@ PHP_MINIT_FUNCTION(openssl)
+ 	OpenSSL_add_all_digests();
+ 	OpenSSL_add_all_algorithms();
+ 
++#if !defined(OPENSSL_NO_AES) && defined(EVP_CIPH_CCM_MODE) && OPENSSL_VERSION_NUMBER < 0x100020000
++	EVP_add_cipher(EVP_aes_128_ccm());
++	EVP_add_cipher(EVP_aes_192_ccm());
++	EVP_add_cipher(EVP_aes_256_ccm());
++#endif
++
+ 	SSL_load_error_strings();
+ 
+ 	/* register a resource id number with OpenSSL so that we can map SSL -> stream structures in
+@@ -1173,7 +1314,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);
+@@ -1251,7 +1394,9 @@ PHP_MINIT_FUNCTION(openssl)
+ 	}
+ 
+ 	php_stream_xport_register("ssl", php_openssl_ssl_socket_factory TSRMLS_CC);
++#ifndef OPENSSL_NO_SSL3
+ 	php_stream_xport_register("sslv3", php_openssl_ssl_socket_factory TSRMLS_CC);
++#endif
+ #ifndef OPENSSL_NO_SSL2
+ 	php_stream_xport_register("sslv2", php_openssl_ssl_socket_factory TSRMLS_CC);
+ #endif
+@@ -1308,7 +1453,9 @@ PHP_MSHUTDOWN_FUNCTION(openssl)
+ #ifndef OPENSSL_NO_SSL2
+ 	php_stream_xport_unregister("sslv2" TSRMLS_CC);
+ #endif
++#ifndef OPENSSL_NO_SSL3
+ 	php_stream_xport_unregister("sslv3" TSRMLS_CC);
++#endif
+ 	php_stream_xport_unregister("tls" TSRMLS_CC);
+ 	php_stream_xport_unregister("tlsv1.0" TSRMLS_CC);
+ #if OPENSSL_VERSION_NUMBER >= 0x10001001L
+@@ -1893,6 +2040,7 @@ static int openssl_x509v3_subjectAltName
+ {
+ 	GENERAL_NAMES *names;
+ 	const X509V3_EXT_METHOD *method = NULL;
++	ASN1_OCTET_STRING *extension_data;
+ 	long i, length, num;
+ 	const unsigned char *p;
+ 
+@@ -1901,8 +2049,9 @@ static int openssl_x509v3_subjectAltName
+ 		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)));
+@@ -1965,6 +2114,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;
+@@ -1979,10 +2130,10 @@ PHP_FUNCTION(openssl_x509_parse)
+ 	}
+ 	array_init(return_value);
+ 
+-	if (cert->name) {
+-		add_assoc_string(return_value, "name", cert->name, 1);
+-	}
+-/*	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, 1);
++	OPENSSL_free(cert_name);
+ 
+ 	add_assoc_name_entry(return_value, "subject", 		X509_get_subject_name(cert), useshortnames TSRMLS_CC);
+ 	/* hash as used in CA directories to lookup cert by subject name */
+@@ -2008,7 +2159,7 @@ PHP_FUNCTION(openssl_x509_parse)
+ 		add_assoc_string(return_value, "alias", tmpstr, 1);
+ 	}
+ 
+-	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), 1);
+ 	add_assoc_string(return_value, "signatureTypeLN", (char*)OBJ_nid2ln(sig_nid), 1);
+ 	add_assoc_long(return_value, "signatureTypeNID", sig_nid);
+@@ -3217,7 +3368,21 @@ 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
+ 	RETVAL_RESOURCE(zend_list_insert(tpubkey, le_key TSRMLS_CC));
+ 	return;
+ }
+@@ -3482,13 +3647,20 @@ static int php_openssl_is_private_key(EV
+ {
+ 	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
+@@ -3498,28 +3670,51 @@ static int php_openssl_is_private_key(EV
+ 		case EVP_PKEY_DSA2:
+ 		case EVP_PKEY_DSA3:
+ 		case EVP_PKEY_DSA4:
+-			assert(pkey->pkey.dsa != NULL);
+-
+-			if (NULL == pkey->pkey.dsa->p || NULL == pkey->pkey.dsa->q || NULL == pkey->pkey.dsa->priv_key){ 
+-				return 0;
++			{
++				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;
++					}
++ 
++					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);
+-
+-			if (NULL == pkey->pkey.dh->p || NULL == pkey->pkey.dh->priv_key) {
+-				return 0;
++			{
++				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;
++					}
++ 
++					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
+@@ -3531,34 +3726,80 @@ static int php_openssl_is_private_key(EV
+ }
+ /* }}} */
+ 
+-#define OPENSSL_PKEY_GET_BN(_type, _name) do {							\
+-		if (pkey->pkey._type->_name != NULL) {							\
+-			int len = BN_num_bytes(pkey->pkey._type->_name);			\
+-			char *str = emalloc(len + 1);								\
+-			BN_bn2bin(pkey->pkey._type->_name, (unsigned char*)str);	\
+-			str[len] = 0;                                           	\
+-			add_assoc_stringl(_type, #_name, str, len, 0);				\
+-		}																\
+-	} while (0)
+-
+-#define OPENSSL_PKEY_SET_BN(_ht, _type, _name) do {						\
+-		zval **bn;														\
+-		if (zend_hash_find(_ht, #_name, sizeof(#_name),	(void**)&bn) == SUCCESS && \
+-				Z_TYPE_PP(bn) == IS_STRING) {							\
+-			_type->_name = BN_bin2bn(									\
+-				(unsigned char*)Z_STRVAL_PP(bn),						\
+-	 			Z_STRLEN_PP(bn), NULL);									\
+-	    }                                                               \
++#define OPENSSL_GET_BN(_array, _bn, _name) do { \
++		if (_bn != NULL) { \
++			int len = BN_num_bytes(_bn); \
++			char *str = emalloc(len + 1); \
++			BN_bn2bin(_bn, (unsigned char*)str); \
++			str[len] = 0; \
++			add_assoc_stringl(_array, #_name, str, len, 0); \
++		} \
+ 	} 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 (zend_hash_find(Z_ARRVAL_P(_data), #_name, sizeof(#_name),(void**)&bn) == SUCCESS && \
++				Z_TYPE_PP(bn) == IS_STRING) { \
++			_name = BN_bin2bn( \
++				(unsigned char*)Z_STRVAL_PP(bn), \
++				Z_STRLEN_PP(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);
+ 	}
+ 	PHP_OPENSSL_RAND_ADD_TIME();
+ 	if (!DSA_generate_key(dsa)) {
+@@ -3566,7 +3807,8 @@ zend_bool php_openssl_pkey_init_dsa(DSA
+ 	}
+ 	/* 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 */
+@@ -3574,14 +3816,66 @@ zend_bool php_openssl_pkey_init_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);
+ 	}
+ 	PHP_OPENSSL_RAND_ADD_TIME();
+ 	if (!DH_generate_key(dh)) {
+@@ -3614,18 +3908,8 @@ PHP_FUNCTION(openssl_pkey_new)
+ 		    if (pkey) {
+ 				RSA *rsa = RSA_new();
+ 				if (rsa) {
+-					OPENSSL_PKEY_SET_BN(Z_ARRVAL_PP(data), rsa, n);
+-					OPENSSL_PKEY_SET_BN(Z_ARRVAL_PP(data), rsa, e);
+-					OPENSSL_PKEY_SET_BN(Z_ARRVAL_PP(data), rsa, d);
+-					OPENSSL_PKEY_SET_BN(Z_ARRVAL_PP(data), rsa, p);
+-					OPENSSL_PKEY_SET_BN(Z_ARRVAL_PP(data), rsa, q);
+-					OPENSSL_PKEY_SET_BN(Z_ARRVAL_PP(data), rsa, dmp1);
+-					OPENSSL_PKEY_SET_BN(Z_ARRVAL_PP(data), rsa, dmq1);
+-					OPENSSL_PKEY_SET_BN(Z_ARRVAL_PP(data), rsa, iqmp);
+-					if (rsa->n && rsa->d) {
+-						if (EVP_PKEY_assign_RSA(pkey, rsa)) {
+-							RETURN_RESOURCE(zend_list_insert(pkey, le_key TSRMLS_CC));
+-						}
++					if (php_openssl_pkey_init_and_assign_rsa(pkey, rsa, *data)) {
++						RETURN_RESOURCE(zend_list_insert(pkey, le_key TSRMLS_CC));
+ 					}
+ 					RSA_free(rsa);
+ 				}
+@@ -3638,12 +3922,7 @@ PHP_FUNCTION(openssl_pkey_new)
+ 		    if (pkey) {
+ 				DSA *dsa = DSA_new();
+ 				if (dsa) {
+-					OPENSSL_PKEY_SET_BN(Z_ARRVAL_PP(data), dsa, p);
+-					OPENSSL_PKEY_SET_BN(Z_ARRVAL_PP(data), dsa, q);
+-					OPENSSL_PKEY_SET_BN(Z_ARRVAL_PP(data), dsa, g);
+-					OPENSSL_PKEY_SET_BN(Z_ARRVAL_PP(data), dsa, priv_key);
+-					OPENSSL_PKEY_SET_BN(Z_ARRVAL_PP(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_RESOURCE(zend_list_insert(pkey, le_key TSRMLS_CC));
+ 						}
+@@ -3659,11 +3938,7 @@ PHP_FUNCTION(openssl_pkey_new)
+ 		    if (pkey) {
+ 				DH *dh = DH_new();
+ 				if (dh) {
+-					OPENSSL_PKEY_SET_BN(Z_ARRVAL_PP(data), dh, p);
+-					OPENSSL_PKEY_SET_BN(Z_ARRVAL_PP(data), dh, g);
+-					OPENSSL_PKEY_SET_BN(Z_ARRVAL_PP(data), dh, priv_key);
+-					OPENSSL_PKEY_SET_BN(Z_ARRVAL_PP(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)) {
+ 							RETURN_RESOURCE(zend_list_insert(pkey, le_key TSRMLS_CC));
+ 						}
+@@ -3738,10 +4013,10 @@ 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, passphrase_len, NULL, NULL);
++				pem_write = PEM_write_bio_ECPrivateKey(bio_out, EVP_PKEY_get0_EC_KEY(key), cipher, (unsigned char *)passphrase, passphrase_len, NULL, NULL);
+ 				break;
+ #endif
+ 			default:
+@@ -3807,7 +4082,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, passphrase_len, NULL, NULL);
+@@ -3928,25 +4203,33 @@ 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;
+-
+-				ALLOC_INIT_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);
++
++					ALLOC_INIT_ZVAL(z_rsa);
++					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;	
+@@ -3954,42 +4237,55 @@ 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;
+-
+-				ALLOC_INIT_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);
++
++					ALLOC_INIT_ZVAL(z_dsa);
++					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;
+-
+-				ALLOC_INIT_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);
++
++					ALLOC_INIT_ZVAL(z_dh);
++					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;
+@@ -4546,13 +4842,13 @@ PHP_FUNCTION(openssl_private_encrypt)
+ 	cryptedlen = EVP_PKEY_size(pkey);
+ 	cryptedbuf = emalloc(cryptedlen + 1);
+ 
+-	switch (pkey->type) {
++	switch (EVP_PKEY_id(pkey)) {
+ 		case EVP_PKEY_RSA:
+ 		case EVP_PKEY_RSA2:
+ 			successful =  (RSA_private_encrypt(data_len, 
+ 						(unsigned char *)data, 
+ 						cryptedbuf, 
+-						pkey->pkey.rsa, 
++						EVP_PKEY_get0_RSA(pkey), 
+ 						padding) == cryptedlen);
+ 			break;
+ 		default:
+@@ -4604,13 +4900,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(data_len, 
+ 					(unsigned char *)data, 
+ 					crypttemp, 
+-					pkey->pkey.rsa, 
++					EVP_PKEY_get0_RSA(pkey), 
+ 					padding);
+ 			if (cryptedlen != -1) {
+ 				cryptedbuf = emalloc(cryptedlen + 1);
+@@ -4669,13 +4965,13 @@ PHP_FUNCTION(openssl_public_encrypt)
+ 	cryptedlen = EVP_PKEY_size(pkey);
+ 	cryptedbuf = emalloc(cryptedlen + 1);
+ 
+-	switch (pkey->type) {
++	switch (EVP_PKEY_id(pkey)) {
+ 		case EVP_PKEY_RSA:
+ 		case EVP_PKEY_RSA2:
+ 			successful = (RSA_public_encrypt(data_len, 
+ 						(unsigned char *)data, 
+ 						cryptedbuf, 
+-						pkey->pkey.rsa, 
++						EVP_PKEY_get0_RSA(pkey), 
+ 						padding) == cryptedlen);
+ 			break;
+ 		default:
+@@ -4728,13 +5024,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(data_len, 
+ 					(unsigned char *)data, 
+ 					crypttemp, 
+-					pkey->pkey.rsa, 
++					EVP_PKEY_get0_RSA(pkey), 
+ 					padding);
+ 			if (cryptedlen != -1) {
+ 				cryptedbuf = emalloc(cryptedlen + 1);
+@@ -4798,7 +5094,7 @@ PHP_FUNCTION(openssl_sign)
+ 	long keyresource = -1;
+ 	char * data;
+ 	int data_len;
+-	EVP_MD_CTX md_ctx;
++	EVP_MD_CTX *md_ctx;
+ 	zval *method = NULL;
+ 	long signature_algo = OPENSSL_ALGO_SHA1;
+ 	const EVP_MD *mdtype;
+@@ -4831,9 +5127,10 @@ PHP_FUNCTION(openssl_sign)
+ 	siglen = EVP_PKEY_size(pkey);
+ 	sigbuf = emalloc(siglen + 1);
+ 
+-	EVP_SignInit(&md_ctx, mdtype);
+-	EVP_SignUpdate(&md_ctx, data, data_len);
+-	if (EVP_SignFinal (&md_ctx, sigbuf,(unsigned int *)&siglen, pkey)) {
++	md_ctx = EVP_MD_CTX_create();
++	EVP_SignInit(md_ctx, mdtype);
++	EVP_SignUpdate(md_ctx, data, data_len);
++	if (EVP_SignFinal (md_ctx, sigbuf,(unsigned int *)&siglen, pkey)) {
+ 		zval_dtor(signature);
+ 		sigbuf[siglen] = '\0';
+ 		ZVAL_STRINGL(signature, (char *)sigbuf, siglen, 0);
+@@ -4842,7 +5139,7 @@ PHP_FUNCTION(openssl_sign)
+ 		efree(sigbuf);
+ 		RETVAL_FALSE;
+ 	}
+-	EVP_MD_CTX_cleanup(&md_ctx);
++	EVP_MD_CTX_destroy(md_ctx);
+ 	if (keyresource == -1) {
+ 		EVP_PKEY_free(pkey);
+ 	}
+@@ -4856,7 +5153,7 @@ PHP_FUNCTION(openssl_verify)
+ 	zval **key;
+ 	EVP_PKEY *pkey;
+ 	int err;
+-	EVP_MD_CTX     md_ctx;
++	EVP_MD_CTX     *md_ctx;
+ 	const EVP_MD *mdtype;
+ 	long keyresource = -1;
+ 	char * data;	int data_len;
+@@ -4890,10 +5187,11 @@ 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, signature_len, pkey);
+-	EVP_MD_CTX_cleanup(&md_ctx);
++	md_ctx = EVP_MD_CTX_create();
++	EVP_VerifyInit   (md_ctx, mdtype);
++	EVP_VerifyUpdate (md_ctx, data, data_len);
++	err = EVP_VerifyFinal (md_ctx, (unsigned char *)signature, signature_len, pkey);
++	EVP_MD_CTX_destroy(md_ctx);
+ 
+ 	if (keyresource == -1) {
+ 		EVP_PKEY_free(pkey);
+@@ -4917,7 +5215,7 @@ PHP_FUNCTION(openssl_seal)
+ 	char *method =NULL;
+ 	int method_len = 0;
+ 	const EVP_CIPHER *cipher;
+-	EVP_CIPHER_CTX ctx;
++	EVP_CIPHER_CTX *ctx;
+ 
+ 	if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "szza/|s", &data, &data_len, &sealdata, &ekeys, &pubkeys, &method, &method_len) == FAILURE) {
+ 		return;
+@@ -4950,6 +5248,7 @@ PHP_FUNCTION(openssl_seal)
+ 	memset(eks, 0, sizeof(*eks) * nkeys);
+ 	key_resources = safe_emalloc(nkeys, sizeof(long), 0);
+ 	memset(key_resources, 0, sizeof(*key_resources) * nkeys);
++	memset(pkeys, 0, sizeof(*pkeys) * nkeys);
+ 
+ 	/* get the public keys we are using to seal this data */
+ 	zend_hash_internal_pointer_reset_ex(pubkeysht, &pos);
+@@ -4967,27 +5266,28 @@ PHP_FUNCTION(openssl_seal)
+ 		i++;
+ 	}
+ 
+-	if (!EVP_EncryptInit(&ctx,cipher,NULL,NULL)) {
++	ctx = EVP_CIPHER_CTX_new();
++	if (ctx == NULL || !EVP_EncryptInit(ctx,cipher,NULL,NULL)) {
+ 		RETVAL_FALSE;
+-		EVP_CIPHER_CTX_cleanup(&ctx);
++		EVP_CIPHER_CTX_free(ctx);
+ 		goto clean_exit;
+ 	}
+ 
+ #if 0
+ 	/* Need this if allow ciphers that require initialization vector */
+-	ivlen = EVP_CIPHER_CTX_iv_length(&ctx);
++	ivlen = EVP_CIPHER_CTX_iv_length(ctx);
+ 	iv = ivlen ? emalloc(ivlen + 1) : NULL;
+ #endif
+ 	/* 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, NULL, pkeys, nkeys) <= 0 ||
+-			!EVP_SealUpdate(&ctx, buf, &len1, (unsigned char *)data, data_len) ||
+-			!EVP_SealFinal(&ctx, buf + len1, &len2)) {
++	if (EVP_SealInit(ctx, cipher, eks, eksl, NULL, pkeys, nkeys) <= 0 ||
++			!EVP_SealUpdate(ctx, buf, &len1, (unsigned char *)data, 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;
+ 	}
+ 
+@@ -5018,7 +5318,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++) {
+@@ -5045,7 +5345,7 @@ PHP_FUNCTION(openssl_open)
+ 	int len1, len2;
+ 	unsigned char *buf;
+ 	long keyresource = -1;
+-	EVP_CIPHER_CTX ctx;
++	EVP_CIPHER_CTX *ctx;
+ 	char * data;	int data_len;
+ 	char * ekey;	int ekey_len;
+ 	char *method =NULL;
+@@ -5074,8 +5374,9 @@ PHP_FUNCTION(openssl_open)
+ 	
+ 	buf = emalloc(data_len + 1);
+ 
+-	if (EVP_OpenInit(&ctx, cipher, (unsigned char *)ekey, ekey_len, NULL, pkey) && EVP_OpenUpdate(&ctx, buf, &len1, (unsigned char *)data, data_len)) {
+-		if (!EVP_OpenFinal(&ctx, buf + len1, &len2) || (len1 + len2 == 0)) {
++	ctx = EVP_CIPHER_CTX_new();
++	if (EVP_OpenInit(ctx, cipher, (unsigned char *)ekey, ekey_len, NULL, pkey) && EVP_OpenUpdate(ctx, buf, &len1, (unsigned char *)data, data_len)) {
++		if (!EVP_OpenFinal(ctx, buf + len1, &len2) || (len1 + len2 == 0)) {
+ 			efree(buf);
+ 			RETVAL_FALSE;
+ 		} else {
+@@ -5091,7 +5392,7 @@ PHP_FUNCTION(openssl_open)
+ 	if (keyresource == -1) {
+ 		EVP_PKEY_free(pkey);
+ 	}
+-	EVP_CIPHER_CTX_cleanup(&ctx);
++	EVP_CIPHER_CTX_free(ctx);
+ }
+ /* }}} */
+ 
+@@ -5151,7 +5452,7 @@ PHP_FUNCTION(openssl_digest)
+ 	char *data, *method;
+ 	int data_len, method_len;
+ 	const EVP_MD *mdtype;
+-	EVP_MD_CTX md_ctx;
++	EVP_MD_CTX *md_ctx;

*** DIFF OUTPUT TRUNCATED AT 1000 LINES ***



Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?201810110802.w9B82WS1019138>