|
version 1.1.1.3, 2013/07/22 01:31:57
|
version 1.1.1.5, 2014/06/15 20:03:52
|
|
Line 2
|
Line 2
|
| +----------------------------------------------------------------------+ |
+----------------------------------------------------------------------+ |
| | PHP Version 5 | |
| PHP Version 5 | |
| +----------------------------------------------------------------------+ |
+----------------------------------------------------------------------+ |
| | Copyright (c) 1997-2013 The PHP Group | | | Copyright (c) 1997-2014 The PHP Group | |
| +----------------------------------------------------------------------+ |
+----------------------------------------------------------------------+ |
| | This source file is subject to version 3.01 of the PHP license, | |
| This source file is subject to version 3.01 of the PHP license, | |
| | that is bundled with this package in the file LICENSE, and is | |
| that is bundled with this package in the file LICENSE, and is | |
|
Line 78
|
Line 78
|
| #endif |
#endif |
| #define DEBUG_SMIME 0 |
#define DEBUG_SMIME 0 |
| |
|
| |
#if !defined(OPENSSL_NO_EC) && defined(EVP_PKEY_EC) |
| |
#define HAVE_EVP_PKEY_EC 1 |
| |
#endif |
| |
|
| /* FIXME: Use the openssl constants instead of |
/* FIXME: Use the openssl constants instead of |
| * enum. It is now impossible to match real values |
* enum. It is now impossible to match real values |
| * against php constants. Also sorry to break the |
* against php constants. Also sorry to break the |
|
Line 88 enum php_openssl_key_type {
|
Line 92 enum php_openssl_key_type {
|
| OPENSSL_KEYTYPE_DSA, |
OPENSSL_KEYTYPE_DSA, |
| OPENSSL_KEYTYPE_DH, |
OPENSSL_KEYTYPE_DH, |
| OPENSSL_KEYTYPE_DEFAULT = OPENSSL_KEYTYPE_RSA, |
OPENSSL_KEYTYPE_DEFAULT = OPENSSL_KEYTYPE_RSA, |
| #ifdef EVP_PKEY_EC | #ifdef HAVE_EVP_PKEY_EC |
| OPENSSL_KEYTYPE_EC = OPENSSL_KEYTYPE_DH +1 |
OPENSSL_KEYTYPE_EC = OPENSSL_KEYTYPE_DH +1 |
| #endif |
#endif |
| }; |
}; |
|
Line 561 static EVP_PKEY * php_openssl_generate_private_key(str
|
Line 565 static EVP_PKEY * php_openssl_generate_private_key(str
|
| |
|
| static void add_assoc_name_entry(zval * val, char * key, X509_NAME * name, int shortname TSRMLS_DC) /* {{{ */ |
static void add_assoc_name_entry(zval * val, char * key, X509_NAME * name, int shortname TSRMLS_DC) /* {{{ */ |
| { |
{ |
| |
zval **data; |
| zval *subitem, *subentries; |
zval *subitem, *subentries; |
| int i, j = -1, last = -1, obj_cnt = 0; |
int i, j = -1, last = -1, obj_cnt = 0; |
| char *sname; |
char *sname; |
|
Line 578 static void add_assoc_name_entry(zval * val, char * ke
|
Line 583 static void add_assoc_name_entry(zval * val, char * ke
|
| |
|
| for (i = 0; i < X509_NAME_entry_count(name); i++) { |
for (i = 0; i < X509_NAME_entry_count(name); i++) { |
| unsigned char *to_add; |
unsigned char *to_add; |
| int to_add_len; | int to_add_len = 0; |
| |
|
| |
|
| ne = X509_NAME_get_entry(name, i); |
ne = X509_NAME_get_entry(name, i); |
|
Line 592 static void add_assoc_name_entry(zval * val, char * ke
|
Line 597 static void add_assoc_name_entry(zval * val, char * ke
|
| sname = (char *) OBJ_nid2ln(nid); |
sname = (char *) OBJ_nid2ln(nid); |
| } |
} |
| |
|
| MAKE_STD_ZVAL(subentries); | str = X509_NAME_ENTRY_get_data(ne); |
| array_init(subentries); | if (ASN1_STRING_type(str) != V_ASN1_UTF8STRING) { |
| | to_add_len = ASN1_STRING_to_UTF8(&to_add, str); |
| | } else { |
| | to_add = ASN1_STRING_data(str); |
| | to_add_len = ASN1_STRING_length(str); |
| | } |
| |
|
| last = -1; | if (to_add_len != -1) { |
| for (;;) { | if (zend_hash_find(Z_ARRVAL_P(subitem), sname, strlen(sname)+1, (void**)&data) == SUCCESS) { |
| j = X509_NAME_get_index_by_OBJ(name, obj, last); | if (Z_TYPE_PP(data) == IS_ARRAY) { |
| if (j < 0) { | subentries = *data; |
| if (last != -1) break; | |
| } else { | |
| obj_cnt++; | |
| ne = X509_NAME_get_entry(name, j); | |
| str = X509_NAME_ENTRY_get_data(ne); | |
| if (ASN1_STRING_type(str) != V_ASN1_UTF8STRING) { | |
| to_add_len = ASN1_STRING_to_UTF8(&to_add, str); | |
| if (to_add_len != -1) { | |
| add_next_index_stringl(subentries, (char *)to_add, to_add_len, 1); | |
| } | |
| } else { | |
| to_add = ASN1_STRING_data(str); | |
| to_add_len = ASN1_STRING_length(str); | |
| add_next_index_stringl(subentries, (char *)to_add, to_add_len, 1); |
add_next_index_stringl(subentries, (char *)to_add, to_add_len, 1); |
| |
} else if (Z_TYPE_PP(data) == IS_STRING) { |
| |
MAKE_STD_ZVAL(subentries); |
| |
array_init(subentries); |
| |
add_next_index_stringl(subentries, Z_STRVAL_PP(data), Z_STRLEN_PP(data), 1); |
| |
add_next_index_stringl(subentries, (char *)to_add, to_add_len, 1); |
| |
zend_hash_update(Z_ARRVAL_P(subitem), sname, strlen(sname)+1, &subentries, sizeof(zval*), NULL); |
| } |
} |
| } | } else { |
| last = j; | |
| } | |
| i = last; | |
| |
| if (obj_cnt > 1) { | |
| add_assoc_zval_ex(subitem, sname, strlen(sname) + 1, subentries); | |
| } else { | |
| zval_dtor(subentries); | |
| FREE_ZVAL(subentries); | |
| if (obj_cnt && str && to_add_len > -1) { | |
| add_assoc_stringl(subitem, sname, (char *)to_add, to_add_len, 1); |
add_assoc_stringl(subitem, sname, (char *)to_add, to_add_len, 1); |
| } |
} |
| } |
} |
|
Line 656 static time_t asn1_time_to_time_t(ASN1_UTCTIME * times
|
Line 649 static time_t asn1_time_to_time_t(ASN1_UTCTIME * times
|
| char * thestr; |
char * thestr; |
| long gmadjust = 0; |
long gmadjust = 0; |
| |
|
| if (timestr->length < 13) { | if (ASN1_STRING_type(timestr) != V_ASN1_UTCTIME) { |
| php_error_docref(NULL TSRMLS_CC, E_WARNING, "extension author too lazy to parse %s correctly", timestr->data); | php_error_docref(NULL TSRMLS_CC, E_WARNING, "illegal ASN1 data type for timestamp"); |
| return (time_t)-1; |
return (time_t)-1; |
| } |
} |
| |
|
| strbuf = estrdup((char *)timestr->data); | if (ASN1_STRING_length(timestr) != strlen(ASN1_STRING_data(timestr))) { |
| | php_error_docref(NULL TSRMLS_CC, E_WARNING, "illegal length in timestamp"); |
| | return (time_t)-1; |
| | } |
| |
|
| |
if (ASN1_STRING_length(timestr) < 13) { |
| |
php_error_docref(NULL TSRMLS_CC, E_WARNING, "unable to parse time string %s correctly", timestr->data); |
| |
return (time_t)-1; |
| |
} |
| |
|
| |
strbuf = estrdup((char *)ASN1_STRING_data(timestr)); |
| |
|
| memset(&thetime, 0, sizeof(thetime)); |
memset(&thetime, 0, sizeof(thetime)); |
| |
|
| /* we work backwards so that we can use atoi more easily */ |
/* we work backwards so that we can use atoi more easily */ |
| |
|
| thestr = strbuf + timestr->length - 3; | thestr = strbuf + ASN1_STRING_length(timestr) - 3; |
| |
|
| thetime.tm_sec = atoi(thestr); |
thetime.tm_sec = atoi(thestr); |
| *thestr = '\0'; |
*thestr = '\0'; |
|
Line 855 static int php_openssl_parse_config(struct php_x509_re
|
Line 858 static int php_openssl_parse_config(struct php_x509_re
|
| req->digest = req->md_alg = EVP_get_digestbyname(req->digest_name); |
req->digest = req->md_alg = EVP_get_digestbyname(req->digest_name); |
| } |
} |
| if (req->md_alg == NULL) { |
if (req->md_alg == NULL) { |
| req->md_alg = req->digest = EVP_md5(); | req->md_alg = req->digest = EVP_sha1(); |
| } |
} |
| |
|
| PHP_SSL_CONFIG_SYNTAX_CHECK(extensions_section); |
PHP_SSL_CONFIG_SYNTAX_CHECK(extensions_section); |
|
Line 1117 PHP_MINIT_FUNCTION(openssl)
|
Line 1120 PHP_MINIT_FUNCTION(openssl)
|
| REGISTER_LONG_CONSTANT("OPENSSL_KEYTYPE_DSA", OPENSSL_KEYTYPE_DSA, CONST_CS|CONST_PERSISTENT); |
REGISTER_LONG_CONSTANT("OPENSSL_KEYTYPE_DSA", OPENSSL_KEYTYPE_DSA, CONST_CS|CONST_PERSISTENT); |
| #endif |
#endif |
| REGISTER_LONG_CONSTANT("OPENSSL_KEYTYPE_DH", OPENSSL_KEYTYPE_DH, CONST_CS|CONST_PERSISTENT); |
REGISTER_LONG_CONSTANT("OPENSSL_KEYTYPE_DH", OPENSSL_KEYTYPE_DH, CONST_CS|CONST_PERSISTENT); |
| #ifdef EVP_PKEY_EC | #ifdef HAVE_EVP_PKEY_EC |
| REGISTER_LONG_CONSTANT("OPENSSL_KEYTYPE_EC", OPENSSL_KEYTYPE_EC, CONST_CS|CONST_PERSISTENT); |
REGISTER_LONG_CONSTANT("OPENSSL_KEYTYPE_EC", OPENSSL_KEYTYPE_EC, CONST_CS|CONST_PERSISTENT); |
| #endif |
#endif |
| |
|
|
Line 1398 PHP_FUNCTION(openssl_x509_check_private_key)
|
Line 1401 PHP_FUNCTION(openssl_x509_check_private_key)
|
| } |
} |
| /* }}} */ |
/* }}} */ |
| |
|
| |
/* Special handling of subjectAltName, see CVE-2013-4073 |
| |
* Christian Heimes |
| |
*/ |
| |
|
| |
static int openssl_x509v3_subjectAltName(BIO *bio, X509_EXTENSION *extension) |
| |
{ |
| |
GENERAL_NAMES *names; |
| |
const X509V3_EXT_METHOD *method = NULL; |
| |
long i, length, num; |
| |
const unsigned char *p; |
| |
|
| |
method = X509V3_EXT_get(extension); |
| |
if (method == NULL) { |
| |
return -1; |
| |
} |
| |
|
| |
p = extension->value->data; |
| |
length = extension->value->length; |
| |
if (method->it) { |
| |
names = (GENERAL_NAMES*)(ASN1_item_d2i(NULL, &p, length, |
| |
ASN1_ITEM_ptr(method->it))); |
| |
} else { |
| |
names = (GENERAL_NAMES*)(method->d2i(NULL, &p, length)); |
| |
} |
| |
if (names == NULL) { |
| |
return -1; |
| |
} |
| |
|
| |
num = sk_GENERAL_NAME_num(names); |
| |
for (i = 0; i < num; i++) { |
| |
GENERAL_NAME *name; |
| |
ASN1_STRING *as; |
| |
name = sk_GENERAL_NAME_value(names, i); |
| |
switch (name->type) { |
| |
case GEN_EMAIL: |
| |
BIO_puts(bio, "email:"); |
| |
as = name->d.rfc822Name; |
| |
BIO_write(bio, ASN1_STRING_data(as), |
| |
ASN1_STRING_length(as)); |
| |
break; |
| |
case GEN_DNS: |
| |
BIO_puts(bio, "DNS:"); |
| |
as = name->d.dNSName; |
| |
BIO_write(bio, ASN1_STRING_data(as), |
| |
ASN1_STRING_length(as)); |
| |
break; |
| |
case GEN_URI: |
| |
BIO_puts(bio, "URI:"); |
| |
as = name->d.uniformResourceIdentifier; |
| |
BIO_write(bio, ASN1_STRING_data(as), |
| |
ASN1_STRING_length(as)); |
| |
break; |
| |
default: |
| |
/* use builtin print for GEN_OTHERNAME, GEN_X400, |
| |
* GEN_EDIPARTY, GEN_DIRNAME, GEN_IPADD and GEN_RID |
| |
*/ |
| |
GENERAL_NAME_print(bio, name); |
| |
} |
| |
/* trailing ', ' except for last element */ |
| |
if (i < (num - 1)) { |
| |
BIO_puts(bio, ", "); |
| |
} |
| |
} |
| |
sk_GENERAL_NAME_pop_free(names, GENERAL_NAME_free); |
| |
|
| |
return 0; |
| |
} |
| |
|
| /* {{{ proto array openssl_x509_parse(mixed x509 [, bool shortnames=true]) |
/* {{{ proto array openssl_x509_parse(mixed x509 [, bool shortnames=true]) |
| Returns an array of the fields/values of the CERT */ |
Returns an array of the fields/values of the CERT */ |
| PHP_FUNCTION(openssl_x509_parse) |
PHP_FUNCTION(openssl_x509_parse) |
|
Line 1494 PHP_FUNCTION(openssl_x509_parse)
|
Line 1565 PHP_FUNCTION(openssl_x509_parse)
|
| |
|
| |
|
| for (i = 0; i < X509_get_ext_count(cert); i++) { |
for (i = 0; i < X509_get_ext_count(cert); i++) { |
| |
int nid; |
| extension = X509_get_ext(cert, i); |
extension = X509_get_ext(cert, i); |
| if (OBJ_obj2nid(X509_EXTENSION_get_object(extension)) != NID_undef) { | nid = OBJ_obj2nid(X509_EXTENSION_get_object(extension)); |
| | if (nid != NID_undef) { |
| extname = (char *)OBJ_nid2sn(OBJ_obj2nid(X509_EXTENSION_get_object(extension))); |
extname = (char *)OBJ_nid2sn(OBJ_obj2nid(X509_EXTENSION_get_object(extension))); |
| } else { |
} else { |
| OBJ_obj2txt(buf, sizeof(buf)-1, X509_EXTENSION_get_object(extension), 1); |
OBJ_obj2txt(buf, sizeof(buf)-1, X509_EXTENSION_get_object(extension), 1); |
| extname = buf; |
extname = buf; |
| } |
} |
| bio_out = BIO_new(BIO_s_mem()); |
bio_out = BIO_new(BIO_s_mem()); |
| if (X509V3_EXT_print(bio_out, extension, 0, 0)) { | if (nid == NID_subject_alt_name) { |
| | if (openssl_x509v3_subjectAltName(bio_out, extension) == 0) { |
| | BIO_get_mem_ptr(bio_out, &bio_buf); |
| | add_assoc_stringl(subitem, extname, bio_buf->data, bio_buf->length, 1); |
| | } else { |
| | zval_dtor(return_value); |
| | if (certresource == -1 && cert) { |
| | X509_free(cert); |
| | } |
| | BIO_free(bio_out); |
| | RETURN_FALSE; |
| | } |
| | } |
| | else if (X509V3_EXT_print(bio_out, extension, 0, 0)) { |
| BIO_get_mem_ptr(bio_out, &bio_buf); |
BIO_get_mem_ptr(bio_out, &bio_buf); |
| add_assoc_stringl(subitem, extname, bio_buf->data, bio_buf->length, 1); |
add_assoc_stringl(subitem, extname, bio_buf->data, bio_buf->length, 1); |
| } else { |
} else { |
|
Line 2932 static int php_openssl_is_private_key(EVP_PKEY* pkey T
|
Line 3018 static int php_openssl_is_private_key(EVP_PKEY* pkey T
|
| } |
} |
| break; |
break; |
| #endif |
#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; |
| |
} |
| |
break; |
| |
#endif |
| default: |
default: |
| php_error_docref(NULL TSRMLS_CC, E_WARNING, "key type not supported in this PHP build!"); |
php_error_docref(NULL TSRMLS_CC, E_WARNING, "key type not supported in this PHP build!"); |
| break; |
break; |
|
Line 3332 PHP_FUNCTION(openssl_pkey_get_details)
|
Line 3427 PHP_FUNCTION(openssl_pkey_get_details)
|
| } |
} |
| |
|
| break; |
break; |
| #ifdef EVP_PKEY_EC | #ifdef HAVE_EVP_PKEY_EC |
| case EVP_PKEY_EC: |
case EVP_PKEY_EC: |
| ktype = OPENSSL_KEYTYPE_EC; |
ktype = OPENSSL_KEYTYPE_EC; |
| break; |
break; |
|
Line 4226 PHP_FUNCTION(openssl_seal)
|
Line 4321 PHP_FUNCTION(openssl_seal)
|
| |
|
| if (!EVP_EncryptInit(&ctx,cipher,NULL,NULL)) { |
if (!EVP_EncryptInit(&ctx,cipher,NULL,NULL)) { |
| RETVAL_FALSE; |
RETVAL_FALSE; |
| |
EVP_CIPHER_CTX_cleanup(&ctx); |
| goto clean_exit; |
goto clean_exit; |
| } |
} |
| |
|
|
Line 4236 PHP_FUNCTION(openssl_seal)
|
Line 4332 PHP_FUNCTION(openssl_seal)
|
| #endif |
#endif |
| /* allocate one byte extra to make room for \0 */ |
/* allocate one byte extra to make room for \0 */ |
| buf = emalloc(data_len + EVP_CIPHER_CTX_block_size(&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) || !EVP_SealUpdate(&ctx, buf, &len1, (unsigned char *)data, data_len)) { |
if (!EVP_SealInit(&ctx, cipher, eks, eksl, NULL, pkeys, nkeys) || !EVP_SealUpdate(&ctx, buf, &len1, (unsigned char *)data, data_len)) { |
| RETVAL_FALSE; |
RETVAL_FALSE; |
| efree(buf); |
efree(buf); |
| |
EVP_CIPHER_CTX_cleanup(&ctx); |
| goto clean_exit; |
goto clean_exit; |
| } |
} |
| |
|
|
Line 4272 PHP_FUNCTION(openssl_seal)
|
Line 4370 PHP_FUNCTION(openssl_seal)
|
| efree(buf); |
efree(buf); |
| } |
} |
| RETVAL_LONG(len1 + len2); |
RETVAL_LONG(len1 + len2); |
| |
EVP_CIPHER_CTX_cleanup(&ctx); |
| |
|
| clean_exit: |
clean_exit: |
| for (i=0; i<nkeys; i++) { |
for (i=0; i<nkeys; i++) { |
|
Line 4330 PHP_FUNCTION(openssl_open)
|
Line 4429 PHP_FUNCTION(openssl_open)
|
| if (EVP_OpenInit(&ctx, cipher, (unsigned char *)ekey, ekey_len, NULL, pkey) && EVP_OpenUpdate(&ctx, buf, &len1, (unsigned char *)data, data_len)) { |
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)) { |
if (!EVP_OpenFinal(&ctx, buf + len1, &len2) || (len1 + len2 == 0)) { |
| efree(buf); |
efree(buf); |
| if (keyresource == -1) { | RETVAL_FALSE; |
| EVP_PKEY_free(pkey); | } else { |
| } | zval_dtor(opendata); |
| RETURN_FALSE; | buf[len1 + len2] = '\0'; |
| | ZVAL_STRINGL(opendata, erealloc(buf, len1 + len2 + 1), len1 + len2, 0); |
| | RETVAL_TRUE; |
| } |
} |
| } else { |
} else { |
| efree(buf); |
efree(buf); |
| if (keyresource == -1) { | RETVAL_FALSE; |
| EVP_PKEY_free(pkey); | |
| } | |
| RETURN_FALSE; | |
| } |
} |
| if (keyresource == -1) { |
if (keyresource == -1) { |
| EVP_PKEY_free(pkey); |
EVP_PKEY_free(pkey); |
| } |
} |
| zval_dtor(opendata); | EVP_CIPHER_CTX_cleanup(&ctx); |
| buf[len1 + len2] = '\0'; | |
| ZVAL_STRINGL(opendata, erealloc(buf, len1 + len2 + 1), len1 + len2, 0); | |
| RETURN_TRUE; | |
| } |
} |
| /* }}} */ |
/* }}} */ |
| |
|
|
Line 4541 SSL *php_SSL_new_from_context(SSL_CTX *ctx, php_stream
|
Line 4636 SSL *php_SSL_new_from_context(SSL_CTX *ctx, php_stream
|
| |
|
| GET_VER_OPT_STRING("local_cert", certfile); |
GET_VER_OPT_STRING("local_cert", certfile); |
| if (certfile) { |
if (certfile) { |
| X509 *cert = NULL; |
|
| EVP_PKEY *key = NULL; |
|
| SSL *tmpssl; |
|
| char resolved_path_buff[MAXPATHLEN]; |
char resolved_path_buff[MAXPATHLEN]; |
| const char * private_key = NULL; |
const char * private_key = NULL; |
| |
|
|
Line 4570 SSL *php_SSL_new_from_context(SSL_CTX *ctx, php_stream
|
Line 4662 SSL *php_SSL_new_from_context(SSL_CTX *ctx, php_stream
|
| } |
} |
| } |
} |
| |
|
| tmpssl = SSL_new(ctx); | #if OPENSSL_VERSION_NUMBER < 0x10001001L |
| cert = SSL_get_certificate(tmpssl); | do { |
| | /* Unnecessary as of OpenSSLv1.0.1 (will segfault if used with >= 10001001 ) */ |
| | X509 *cert = NULL; |
| | EVP_PKEY *key = NULL; |
| | SSL *tmpssl = SSL_new(ctx); |
| | cert = SSL_get_certificate(tmpssl); |
| |
|
| if (cert) { | if (cert) { |
| key = X509_get_pubkey(cert); | key = X509_get_pubkey(cert); |
| EVP_PKEY_copy_parameters(key, SSL_get_privatekey(tmpssl)); | EVP_PKEY_copy_parameters(key, SSL_get_privatekey(tmpssl)); |
| EVP_PKEY_free(key); | EVP_PKEY_free(key); |
| } | } |
| SSL_free(tmpssl); | SSL_free(tmpssl); |
| } while (0); |
| | #endif |
| if (!SSL_CTX_check_private_key(ctx)) { |
if (!SSL_CTX_check_private_key(ctx)) { |
| php_error_docref(NULL TSRMLS_CC, E_WARNING, "Private key does not match certificate!"); |
php_error_docref(NULL TSRMLS_CC, E_WARNING, "Private key does not match certificate!"); |
| } |
} |
|
Line 4916 PHP_FUNCTION(openssl_cipher_iv_length)
|
Line 5014 PHP_FUNCTION(openssl_cipher_iv_length)
|
| |
|
| |
|
| /* {{{ proto string openssl_dh_compute_key(string pub_key, resource dh_key) |
/* {{{ proto string openssl_dh_compute_key(string pub_key, resource dh_key) |
| Computes shared sicret for public value of remote DH key and local DH key */ | Computes shared secret for public value of remote DH key and local DH key */ |
| PHP_FUNCTION(openssl_dh_compute_key) |
PHP_FUNCTION(openssl_dh_compute_key) |
| { |
{ |
| zval *key; |
zval *key; |