Newsgroups: php.internals Path: news.php.net Xref: news.php.net php.internals:31349 Return-Path: Mailing-List: contact internals-help@lists.php.net; run by ezmlm Delivered-To: mailing list internals@lists.php.net Received: (qmail 79141 invoked by uid 1010); 1 Aug 2007 08:57:08 -0000 Delivered-To: ezmlm-scan-internals@lists.php.net Delivered-To: ezmlm-internals@lists.php.net Received: (qmail 79126 invoked from network); 1 Aug 2007 08:57:08 -0000 Received: from unknown (HELO lists.php.net) (127.0.0.1) by localhost with SMTP; 1 Aug 2007 08:57:08 -0000 Authentication-Results: pb1.pair.com smtp.mail=dmitry@zend.com; spf=pass; sender-id=pass Authentication-Results: pb1.pair.com header.from=dmitry@zend.com; sender-id=pass Received-SPF: pass (pb1.pair.com: domain zend.com designates 212.25.124.162 as permitted sender) X-PHP-List-Original-Sender: dmitry@zend.com X-Host-Fingerprint: 212.25.124.162 mail.zend.com Linux 2.5 (sometimes 2.4) (4) Received: from [212.25.124.162] ([212.25.124.162:23091] helo=mail.zend.com) by pb1.pair.com (ecelerity 2.1.1.9-wez r(12769M)) with ESMTP id D3/94-39533-EDA40B64 for ; Wed, 01 Aug 2007 04:57:07 -0400 Received: (qmail 26868 invoked from network); 1 Aug 2007 08:56:56 -0000 Received: from internal.zend.office (HELO thinkpad) (10.1.1.1) by internal.zend.office with SMTP; 1 Aug 2007 08:56:56 -0000 To: "Wez Furlong" , "Sara Golemon" , "Andi Gutmans" , "Stanislav Malyshev" , "Zeev Suraski" Cc: Date: Wed, 1 Aug 2007 12:56:47 +0400 Message-ID: <002b01c7d419$e6914720$6e02a8c0@thinkpad> MIME-Version: 1.0 Content-Type: multipart/mixed; boundary="----=_NextPart_000_002C_01C7D43B.6DA2E720" X-Priority: 3 (Normal) X-MSMail-Priority: Normal X-Mailer: Microsoft Outlook, Build 10.0.6626 X-MimeOLE: Produced By Microsoft MimeOLE V6.00.2900.3138 Importance: Normal Subject: Ext/OpenSSL patch From: dmitry@zend.com ("Dmitry Stogov") ------=_NextPart_000_002C_01C7D43B.6DA2E720 Content-Type: text/plain; charset="US-ASCII" Content-Transfer-Encoding: quoted-printable Hi, I propose a patch for ext/openssl that extends support for crypto API. - it provides access to openSSL digest functions function openssl_get_md_methods(); function openssl_digest(string $data, string $method [, bool $raw]); - it provides access to openSSL digest functions function openssl_get_cipher_methods(); function openssl_encrypt(string $data, string $method, $string $password [, bool $raw]); function openssl_decrypt(string $data, string $method, $string $password [, bool $raw]); - It extends existing functions openssl_pkey_new() and openssl_pkey_get_details() to access internal values of DSA, RSA and DH keys. For example you can create DH key and then access its internal = values using the following code: array( 'p' =3D> pack('H*', 'dcf93a0b883972ec'), 'g' =3D> pack(H*', '02'))); $details =3D openssl_pkey_get_details($dh); var_dump(base64_encode($deteils['dh']['p'])); var_dump(base64_encode($deteils['dh']['g'])); var_dump(base64_encode($deteils['dh']['priv_key'])); var_dump(base64_encode($deteils['dh']['pub_key'])); ?> - it provides new function that computes shared secret for two DH keys function openssl_dh_compute_key(string $pub_key, resource $dh) - it also extend some functions to support string name of crypto = algorith in addition to numeric constants. This patch was written to implement OpenID protocol in PHP. It is similar to patch by Wez http://netevil.org/blog/2007/feb/openid-and-typekey-using-native-openssl-= fun ctions-in-php but it provides less additional functions and works with big numbers as = with strings (instead of resources). I would like to commit the path to PHP_5_2 and HEAD. Any objections? Thanks. Dmitry.=20 ------=_NextPart_000_002C_01C7D43B.6DA2E720 Content-Type: text/plain; name="openssl-2.diff.txt" Content-Transfer-Encoding: quoted-printable Content-Disposition: attachment; filename="openssl-2.diff.txt" Index: ext/openssl/openssl.c=0A= =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D= =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D= =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=0A= RCS file: /repository/php-src/ext/openssl/openssl.c,v=0A= retrieving revision 1.98.2.5.2.38=0A= diff -u -p -d -r1.98.2.5.2.38 openssl.c=0A= --- ext/openssl/openssl.c 11 Jul 2007 12:18:14 -0000 1.98.2.5.2.38=0A= +++ ext/openssl/openssl.c 1 Aug 2007 07:20:18 -0000=0A= @@ -33,6 +33,8 @@=0A= #include "ext/standard/file.h"=0A= #include "ext/standard/info.h"=0A= #include "ext/standard/php_fopen_wrappers.h"=0A= +#include "ext/standard/md5.h"=0A= +#include "ext/standard/base64.h"=0A= =0A= /* OpenSSL includes */=0A= #include =0A= @@ -88,6 +90,15 @@ enum php_openssl_cipher_type {=0A= PHP_OPENSSL_CIPHER_DEFAULT =3D PHP_OPENSSL_CIPHER_RC2_40=0A= };=0A= =0A= +PHP_FUNCTION(openssl_get_md_methods);=0A= +PHP_FUNCTION(openssl_get_cipher_methods);=0A= +=0A= +PHP_FUNCTION(openssl_digest);=0A= +PHP_FUNCTION(openssl_encrypt);=0A= +PHP_FUNCTION(openssl_decrypt);=0A= +=0A= +PHP_FUNCTION(openssl_dh_compute_key);=0A= +=0A= /* {{{ openssl_functions[]=0A= */=0A= zend_function_entry openssl_functions[] =3D {=0A= @@ -126,10 +137,13 @@ zend_function_entry openssl_functions[] =0A= PHP_FE(openssl_csr_get_subject, NULL)=0A= PHP_FE(openssl_csr_get_public_key, NULL)=0A= =0A= - PHP_FE(openssl_sign, second_arg_force_ref)=0A= - PHP_FE(openssl_verify, NULL)=0A= - PHP_FE(openssl_seal, arg2and3_force_ref)=0A= - PHP_FE(openssl_open, second_arg_force_ref)=0A= + PHP_FE(openssl_digest, NULL)=0A= + PHP_FE(openssl_encrypt, NULL)=0A= + PHP_FE(openssl_decrypt, NULL)=0A= + PHP_FE(openssl_sign, second_arg_force_ref)=0A= + PHP_FE(openssl_verify, NULL)=0A= + PHP_FE(openssl_seal, arg2and3_force_ref)=0A= + PHP_FE(openssl_open, second_arg_force_ref)=0A= =0A= /* for S/MIME handling */=0A= PHP_FE(openssl_pkcs7_verify, NULL)=0A= @@ -142,6 +156,11 @@ zend_function_entry openssl_functions[] =0A= PHP_FE(openssl_public_encrypt, second_arg_force_ref)=0A= PHP_FE(openssl_public_decrypt, second_arg_force_ref)=0A= =0A= + PHP_FE(openssl_get_md_methods, NULL)=0A= + PHP_FE(openssl_get_cipher_methods, NULL)=0A= +=0A= + PHP_FE(openssl_dh_compute_key, NULL)=0A= +=0A= PHP_FE(openssl_error_string, NULL)=0A= {NULL, NULL, NULL}=0A= };=0A= @@ -645,6 +664,34 @@ static EVP_MD * php_openssl_get_evp_md_f=0A= return mdtype;=0A= }=0A= /* }}} */=0A= +=0A= +static const EVP_CIPHER * php_openssl_get_evp_cipher_from_algo(long = algo) { /* {{{ */=0A= + switch (algo) {=0A= +#ifndef OPENSSL_NO_RC2=0A= + case PHP_OPENSSL_CIPHER_RC2_40:=0A= + return EVP_rc2_40_cbc();=0A= + break;=0A= + case PHP_OPENSSL_CIPHER_RC2_64:=0A= + return EVP_rc2_64_cbc();=0A= + break;=0A= + case PHP_OPENSSL_CIPHER_RC2_128:=0A= + return EVP_rc2_cbc();=0A= + break;=0A= +#endif=0A= +=0A= +#ifndef OPENSSL_NO_DES=0A= + case PHP_OPENSSL_CIPHER_DES:=0A= + return EVP_des_cbc();=0A= + break;=0A= + case PHP_OPENSSL_CIPHER_3DES:=0A= + return EVP_des_ede3_cbc();=0A= + break;=0A= +#endif=0A= + default:=0A= + return NULL;=0A= + break;=0A= + }=0A= +}=0A= /* }}} */=0A= =0A= /* {{{ PHP_MINIT_FUNCTION=0A= @@ -2431,6 +2478,25 @@ static EVP_PKEY * php_openssl_generate_p=0A= }=0A= break;=0A= #endif=0A= +#if !defined(NO_DH)=0A= + case OPENSSL_KEYTYPE_DH:=0A= + {=0A= + DH *dhpar =3D DH_generate_parameters(req->priv_key_bits, 2, NULL, = NULL);=0A= + int codes =3D 0;=0A= +=0A= + if (dhpar) {=0A= + DH_set_method(dhpar, DH_get_default_method());=0A= + if (DH_check(dhpar, &codes) && codes =3D=3D 0 && = DH_generate_key(dhpar)) {=0A= + if (EVP_PKEY_assign_DH(req->priv_key, dhpar)) {=0A= + return_val =3D req->priv_key;=0A= + }=0A= + } else {=0A= + DH_free(dhpar);=0A= + }=0A= + }=0A= + }=0A= + break;=0A= +#endif=0A= default:=0A= php_error_docref(NULL TSRMLS_CC, E_WARNING, "Unsupported private = key type");=0A= }=0A= @@ -2495,18 +2561,111 @@ static int php_openssl_is_private_key(EV=0A= }=0A= /* }}} */=0A= =0A= +#define OPENSSL_PKEY_GET_BN(_type, _name) do { \=0A= + if (pkey->pkey._type->_name !=3D NULL) { \=0A= + int len =3D BN_num_bytes(pkey->pkey._type->_name); \=0A= + char *str =3D emalloc(len + 1); \=0A= + BN_bn2bin(pkey->pkey._type->_name, (unsigned char*)str); \=0A= + str[len] =3D 0; \=0A= + add_assoc_stringl(_type, #_name, str, len, 0); \=0A= + } \=0A= + } while (0)=0A= +=0A= +#define OPENSSL_PKEY_SET_BN(_ht, _type, _name) do { \=0A= + zval **bn; \=0A= + if (zend_hash_find(_ht, #_name, sizeof(#_name), (void**)&bn) =3D=3D = SUCCESS && \=0A= + Z_TYPE_PP(bn) =3D=3D IS_STRING) { \=0A= + _type->_name =3D BN_bin2bn( \=0A= + (unsigned char*)Z_STRVAL_PP(bn), \=0A= + Z_STRLEN_PP(bn), NULL); \=0A= + } \=0A= + } while (0);=0A= +=0A= +=0A= /* {{{ proto resource openssl_pkey_new([array configargs])=0A= Generates a new private key */=0A= PHP_FUNCTION(openssl_pkey_new)=0A= {=0A= struct php_x509_request req;=0A= zval * args =3D NULL;=0A= + zval **data;=0A= =0A= if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "|a!", &args) = =3D=3D FAILURE) {=0A= return;=0A= }=0A= RETVAL_FALSE;=0A= - =0A= +=0A= + if (args && Z_TYPE_P(args) =3D=3D IS_ARRAY) {=0A= + EVP_PKEY *pkey;=0A= +=0A= + if (zend_hash_find(Z_ARRVAL_P(args), "rsa", sizeof("rsa"), = (void**)&data) =3D=3D SUCCESS &&=0A= + Z_TYPE_PP(data) =3D=3D IS_ARRAY) {=0A= + pkey =3D EVP_PKEY_new();=0A= + if (pkey) {=0A= + RSA *rsa =3D RSA_new();=0A= + if (rsa) {=0A= + OPENSSL_PKEY_SET_BN(Z_ARRVAL_PP(data), rsa, n);=0A= + OPENSSL_PKEY_SET_BN(Z_ARRVAL_PP(data), rsa, e);=0A= + OPENSSL_PKEY_SET_BN(Z_ARRVAL_PP(data), rsa, d);=0A= + OPENSSL_PKEY_SET_BN(Z_ARRVAL_PP(data), rsa, p);=0A= + OPENSSL_PKEY_SET_BN(Z_ARRVAL_PP(data), rsa, q);=0A= + OPENSSL_PKEY_SET_BN(Z_ARRVAL_PP(data), rsa, dmp1);=0A= + OPENSSL_PKEY_SET_BN(Z_ARRVAL_PP(data), rsa, dmq1);=0A= + OPENSSL_PKEY_SET_BN(Z_ARRVAL_PP(data), rsa, iqmp);=0A= + if (EVP_PKEY_assign_RSA(pkey, rsa)) {=0A= + RETURN_RESOURCE(zend_list_insert(pkey, le_key));=0A= + }=0A= + RSA_free(rsa);=0A= + }=0A= + EVP_PKEY_free(pkey);=0A= + }=0A= + RETURN_FALSE;=0A= + } else if (zend_hash_find(Z_ARRVAL_P(args), "dsa", sizeof("dsa"), = (void**)&data) =3D=3D SUCCESS &&=0A= + Z_TYPE_PP(data) =3D=3D IS_ARRAY) {=0A= + pkey =3D EVP_PKEY_new();=0A= + if (pkey) {=0A= + DSA *dsa =3D DSA_new();=0A= + if (dsa) {=0A= + OPENSSL_PKEY_SET_BN(Z_ARRVAL_PP(data), dsa, p);=0A= + OPENSSL_PKEY_SET_BN(Z_ARRVAL_PP(data), dsa, q);=0A= + OPENSSL_PKEY_SET_BN(Z_ARRVAL_PP(data), dsa, g);=0A= + OPENSSL_PKEY_SET_BN(Z_ARRVAL_PP(data), dsa, priv_key);=0A= + OPENSSL_PKEY_SET_BN(Z_ARRVAL_PP(data), dsa, pub_key);=0A= + if (!dsa->priv_key && !dsa->pub_key) {=0A= + DSA_generate_key(dsa);=0A= + }=0A= + if (EVP_PKEY_assign_DSA(pkey, dsa)) {=0A= + RETURN_RESOURCE(zend_list_insert(pkey, le_key));=0A= + }=0A= + DSA_free(dsa);=0A= + }=0A= + EVP_PKEY_free(pkey);=0A= + }=0A= + RETURN_FALSE;=0A= + } else if (zend_hash_find(Z_ARRVAL_P(args), "dh", sizeof("dh"), = (void**)&data) =3D=3D SUCCESS &&=0A= + Z_TYPE_PP(data) =3D=3D IS_ARRAY) {=0A= + pkey =3D EVP_PKEY_new();=0A= + if (pkey) {=0A= + DH *dh =3D DH_new();=0A= + if (dh) {=0A= + OPENSSL_PKEY_SET_BN(Z_ARRVAL_PP(data), dh, p);=0A= + OPENSSL_PKEY_SET_BN(Z_ARRVAL_PP(data), dh, g);=0A= + OPENSSL_PKEY_SET_BN(Z_ARRVAL_PP(data), dh, priv_key);=0A= + OPENSSL_PKEY_SET_BN(Z_ARRVAL_PP(data), dh, pub_key);=0A= + if (!dh->priv_key && !dh->pub_key) {=0A= + DH_generate_key(dh);=0A= + }=0A= + if (EVP_PKEY_assign_DH(pkey, dh)) {=0A= + RETURN_RESOURCE(zend_list_insert(pkey, le_key));=0A= + }=0A= + DH_free(dh);=0A= + }=0A= + EVP_PKEY_free(pkey);=0A= + }=0A= + RETURN_FALSE;=0A= + }=0A= + } =0A= +=0A= PHP_SSL_REQ_INIT(&req);=0A= =0A= if (PHP_SSL_REQ_PARSE(&req, args) =3D=3D SUCCESS)=0A= @@ -2724,15 +2883,59 @@ PHP_FUNCTION(openssl_pkey_get_details)=0A= case EVP_PKEY_RSA:=0A= case EVP_PKEY_RSA2:=0A= ktype =3D OPENSSL_KEYTYPE_RSA;=0A= +=0A= + if (pkey->pkey.rsa !=3D NULL) {=0A= + zval *rsa;=0A= +=0A= + ALLOC_INIT_ZVAL(rsa);=0A= + array_init(rsa);=0A= + OPENSSL_PKEY_GET_BN(rsa, n);=0A= + OPENSSL_PKEY_GET_BN(rsa, e);=0A= + OPENSSL_PKEY_GET_BN(rsa, d);=0A= + OPENSSL_PKEY_GET_BN(rsa, p);=0A= + OPENSSL_PKEY_GET_BN(rsa, q);=0A= + OPENSSL_PKEY_GET_BN(rsa, dmp1);=0A= + OPENSSL_PKEY_GET_BN(rsa, dmq1);=0A= + OPENSSL_PKEY_GET_BN(rsa, iqmp);=0A= + add_assoc_zval(return_value, "rsa", rsa);=0A= + }=0A= +=0A= break; =0A= case EVP_PKEY_DSA:=0A= case EVP_PKEY_DSA2:=0A= case EVP_PKEY_DSA3:=0A= case EVP_PKEY_DSA4:=0A= ktype =3D OPENSSL_KEYTYPE_DSA;=0A= +=0A= + if (pkey->pkey.dsa !=3D NULL) {=0A= + zval *dsa;=0A= +=0A= + ALLOC_INIT_ZVAL(dsa);=0A= + array_init(dsa);=0A= + OPENSSL_PKEY_GET_BN(dsa, p);=0A= + OPENSSL_PKEY_GET_BN(dsa, q);=0A= + OPENSSL_PKEY_GET_BN(dsa, g);=0A= + OPENSSL_PKEY_GET_BN(dsa, priv_key);=0A= + OPENSSL_PKEY_GET_BN(dsa, pub_key);=0A= + add_assoc_zval(return_value, "dsa", dsa);=0A= + }=0A= break;=0A= case EVP_PKEY_DH:=0A= + =0A= ktype =3D OPENSSL_KEYTYPE_DH;=0A= +=0A= + if (pkey->pkey.dh !=3D NULL) {=0A= + zval *dh;=0A= +=0A= + ALLOC_INIT_ZVAL(dh);=0A= + array_init(dh);=0A= + OPENSSL_PKEY_GET_BN(dh, p);=0A= + OPENSSL_PKEY_GET_BN(dh, g);=0A= + OPENSSL_PKEY_GET_BN(dh, priv_key);=0A= + OPENSSL_PKEY_GET_BN(dh, pub_key);=0A= + add_assoc_zval(return_value, "dh", dh);=0A= + }=0A= +=0A= break;=0A= #ifdef EVP_PKEY_EC =0A= case EVP_PKEY_EC:=0A= @@ -2949,32 +3152,7 @@ PHP_FUNCTION(openssl_pkcs7_encrypt)=0A= }=0A= =0A= /* sanity check the cipher */=0A= - switch (cipherid) {=0A= -#ifndef OPENSSL_NO_RC2=0A= - case PHP_OPENSSL_CIPHER_RC2_40:=0A= - cipher =3D EVP_rc2_40_cbc();=0A= - break;=0A= - case PHP_OPENSSL_CIPHER_RC2_64:=0A= - cipher =3D EVP_rc2_64_cbc();=0A= - break;=0A= - case PHP_OPENSSL_CIPHER_RC2_128:=0A= - cipher =3D EVP_rc2_cbc();=0A= - break;=0A= -#endif=0A= -=0A= -#ifndef OPENSSL_NO_DES=0A= - case PHP_OPENSSL_CIPHER_DES:=0A= - cipher =3D EVP_des_cbc();=0A= - break;=0A= - case PHP_OPENSSL_CIPHER_3DES:=0A= - cipher =3D EVP_des_ede3_cbc();=0A= - break;=0A= -#endif=0A= -=0A= - default:=0A= - php_error_docref(NULL TSRMLS_CC, E_WARNING, "Invalid cipher type = `%ld'", cipherid);=0A= - goto clean_exit;=0A= - }=0A= + cipher =3D php_openssl_get_evp_cipher_from_algo(cipherid);=0A= if (cipher =3D=3D NULL) {=0A= /* shouldn't happen */=0A= php_error_docref(NULL TSRMLS_CC, E_WARNING, "Failed to get cipher");=0A= @@ -3473,7 +3651,7 @@ PHP_FUNCTION(openssl_error_string)=0A= }=0A= /* }}} */=0A= =0A= -/* {{{ proto bool openssl_sign(string data, &string signature, mixed = key[, int signature_alg])=0A= +/* {{{ proto bool openssl_sign(string data, &string signature, mixed = key[, mixed method])=0A= Signs data */=0A= PHP_FUNCTION(openssl_sign)=0A= {=0A= @@ -3485,10 +3663,11 @@ PHP_FUNCTION(openssl_sign)=0A= char * data;=0A= int data_len;=0A= EVP_MD_CTX md_ctx;=0A= + zval *method =3D NULL;=0A= long signature_algo =3D OPENSSL_ALGO_SHA1;=0A= - EVP_MD *mdtype;=0A= + const EVP_MD *mdtype;=0A= =0A= - if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "szZ|l", &data, = &data_len, &signature, &key, &signature_algo) =3D=3D FAILURE) {=0A= + if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "szZ|z", &data, = &data_len, &signature, &key, &method) =3D=3D FAILURE) {=0A= return;=0A= }=0A= pkey =3D php_openssl_evp_from_zval(key, 0, "", 0, &keyresource = TSRMLS_CC);=0A= @@ -3497,7 +3676,17 @@ PHP_FUNCTION(openssl_sign)=0A= RETURN_FALSE;=0A= }=0A= =0A= - mdtype =3D php_openssl_get_evp_md_from_algo(signature_algo);=0A= + if (method =3D=3D NULL || Z_TYPE_P(method) =3D=3D IS_LONG) {=0A= + if (Z_TYPE_P(method) =3D=3D IS_LONG) {=0A= + signature_algo =3D Z_LVAL_P(method);=0A= + }=0A= + mdtype =3D php_openssl_get_evp_md_from_algo(signature_algo);=0A= + } else if (Z_TYPE_P(method) =3D=3D IS_STRING) {=0A= + mdtype =3D EVP_get_digestbyname(Z_STRVAL_P(method));=0A= + } else {=0A= + php_error_docref(NULL TSRMLS_CC, E_WARNING, "Unknown signature = algorithm.");=0A= + RETURN_FALSE;=0A= + }=0A= if (!mdtype) {=0A= php_error_docref(NULL TSRMLS_CC, E_WARNING, "Unknown signature = algorithm.");=0A= RETURN_FALSE;=0A= @@ -3523,7 +3712,7 @@ PHP_FUNCTION(openssl_sign)=0A= }=0A= /* }}} */=0A= =0A= -/* {{{ proto int openssl_verify(string data, string signature, mixed = key)=0A= +/* {{{ proto int openssl_verify(string data, string signature, mixed = key[, mixed method])=0A= Verifys data */=0A= PHP_FUNCTION(openssl_verify)=0A= {=0A= @@ -3531,17 +3720,28 @@ PHP_FUNCTION(openssl_verify)=0A= EVP_PKEY *pkey;=0A= int err;=0A= EVP_MD_CTX md_ctx;=0A= - EVP_MD *mdtype;=0A= + const EVP_MD *mdtype;=0A= long keyresource =3D -1;=0A= char * data; int data_len;=0A= char * signature; int signature_len;=0A= + zval *method =3D NULL;=0A= long signature_algo =3D OPENSSL_ALGO_SHA1;=0A= =0A= - if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "ssZ|l", &data, = &data_len, &signature, &signature_len, &key, &signature_algo) =3D=3D = FAILURE) {=0A= + if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "ssZ|z", &data, = &data_len, &signature, &signature_len, &key, &method) =3D=3D FAILURE) {=0A= return;=0A= }=0A= =0A= - mdtype =3D php_openssl_get_evp_md_from_algo(signature_algo);=0A= + if (method =3D=3D NULL || Z_TYPE_P(method) =3D=3D IS_LONG) {=0A= + if (Z_TYPE_P(method) =3D=3D IS_LONG) {=0A= + signature_algo =3D Z_LVAL_P(method);=0A= + }=0A= + mdtype =3D php_openssl_get_evp_md_from_algo(signature_algo);=0A= + } else if (Z_TYPE_P(method) =3D=3D IS_STRING) {=0A= + mdtype =3D EVP_get_digestbyname(Z_STRVAL_P(method));=0A= + } else {=0A= + php_error_docref(NULL TSRMLS_CC, E_WARNING, "Unknown signature = algorithm.");=0A= + RETURN_FALSE;=0A= + }=0A= if (!mdtype) {=0A= php_error_docref(NULL TSRMLS_CC, E_WARNING, "Unknown signature = algorithm.");=0A= RETURN_FALSE;=0A= @@ -3576,9 +3776,12 @@ PHP_FUNCTION(openssl_seal)=0A= int i, len1, len2, *eksl, nkeys;=0A= unsigned char *buf =3D NULL, **eks;=0A= char * data; int data_len;=0A= + char *method =3DNULL;=0A= + int method_len;=0A= + const EVP_CIPHER *cipher;=0A= EVP_CIPHER_CTX ctx;=0A= =0A= - if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "szza/", &data, = &data_len, &sealdata, &ekeys, &pubkeys) =3D=3D FAILURE) {=0A= + if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "szza/|s", &data, = &data_len, &sealdata, &ekeys, &pubkeys, &method, &method_len) =3D=3D = FAILURE) {=0A= return;=0A= }=0A= =0A= @@ -3589,6 +3792,16 @@ PHP_FUNCTION(openssl_seal)=0A= RETURN_FALSE;=0A= }=0A= =0A= + if (method) {=0A= + cipher =3D EVP_get_cipherbyname(method);=0A= + if (!cipher) {=0A= + php_error_docref(NULL TSRMLS_CC, E_WARNING, "Unknown signature = algorithm.");=0A= + RETURN_FALSE;=0A= + }=0A= + } else {=0A= + cipher =3D EVP_rc4();=0A= + }=0A= +=0A= pkeys =3D safe_emalloc(nkeys, sizeof(*pkeys), 0);=0A= eksl =3D safe_emalloc(nkeys, sizeof(*eksl), 0);=0A= eks =3D safe_emalloc(nkeys, sizeof(*eks), 0);=0A= @@ -3612,7 +3825,7 @@ PHP_FUNCTION(openssl_seal)=0A= i++;=0A= }=0A= =0A= - if (!EVP_EncryptInit(&ctx,EVP_rc4(),NULL,NULL)) {=0A= + if (!EVP_EncryptInit(&ctx,cipher,NULL,NULL)) {=0A= RETVAL_FALSE;=0A= goto clean_exit;=0A= }=0A= @@ -3625,7 +3838,7 @@ PHP_FUNCTION(openssl_seal)=0A= /* allocate one byte extra to make room for \0 */=0A= buf =3D emalloc(data_len + EVP_CIPHER_CTX_block_size(&ctx));=0A= =0A= - if (!EVP_SealInit(&ctx, EVP_rc4(), eks, eksl, NULL, pkeys, nkeys) || = !EVP_SealUpdate(&ctx, buf, &len1, (unsigned char *)data, data_len)) {=0A= + if (!EVP_SealInit(&ctx, cipher, eks, eksl, NULL, pkeys, nkeys) || = !EVP_SealUpdate(&ctx, buf, &len1, (unsigned char *)data, data_len)) {=0A= RETVAL_FALSE;=0A= efree(buf);=0A= goto clean_exit;=0A= @@ -3689,8 +3902,11 @@ PHP_FUNCTION(openssl_open)=0A= EVP_CIPHER_CTX ctx;=0A= char * data; int data_len;=0A= char * ekey; int ekey_len;=0A= + char *method =3DNULL;=0A= + int method_len;=0A= + const EVP_CIPHER *cipher;=0A= =0A= - if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "szsZ", &data, = &data_len, &opendata, &ekey, &ekey_len, &privkey) =3D=3D FAILURE) {=0A= + if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "szsZ|s", &data, = &data_len, &opendata, &ekey, &ekey_len, &privkey, &method, &method_len) = =3D=3D FAILURE) {=0A= return;=0A= }=0A= =0A= @@ -3699,9 +3915,20 @@ PHP_FUNCTION(openssl_open)=0A= php_error_docref(NULL TSRMLS_CC, E_WARNING, "unable to coerce = parameter 4 into a private key");=0A= RETURN_FALSE;=0A= }=0A= +=0A= + if (method) {=0A= + cipher =3D EVP_get_cipherbyname(method);=0A= + if (!cipher) {=0A= + php_error_docref(NULL TSRMLS_CC, E_WARNING, "Unknown signature = algorithm.");=0A= + RETURN_FALSE;=0A= + }=0A= + } else {=0A= + cipher =3D EVP_rc4();=0A= + }=0A= + =0A= buf =3D emalloc(data_len + 1);=0A= =0A= - if (EVP_OpenInit(&ctx, EVP_rc4(), (unsigned char *)ekey, ekey_len, = NULL, pkey) && EVP_OpenUpdate(&ctx, buf, &len1, (unsigned char *)data, = data_len)) {=0A= + if (EVP_OpenInit(&ctx, cipher, (unsigned char *)ekey, ekey_len, NULL, = pkey) && EVP_OpenUpdate(&ctx, buf, &len1, (unsigned char *)data, = data_len)) {=0A= if (!EVP_OpenFinal(&ctx, buf + len1, &len2) || (len1 + len2 =3D=3D = 0)) {=0A= efree(buf);=0A= if (keyresource =3D=3D -1) { =0A= @@ -3951,6 +4178,250 @@ SSL *php_SSL_new_from_context(SSL_CTX *c=0A= }=0A= /* }}} */=0A= =0A= +static void openssl_add_method_or_alias(const OBJ_NAME *name, void *arg)=0A= +{=0A= + add_next_index_string((zval*)arg, (char*)name->name, 1);=0A= +}=0A= +=0A= +static void openssl_add_method(const OBJ_NAME *name, void *arg)=0A= +{=0A= + if (name->alias =3D=3D 0) {=0A= + add_next_index_string((zval*)arg, (char*)name->name, 1);=0A= + }=0A= +}=0A= +=0A= +PHP_FUNCTION(openssl_get_md_methods)=0A= +{=0A= + zend_bool aliases =3D 0;=0A= +=0A= + if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "|b", &aliases) = =3D=3D FAILURE) {=0A= + return;=0A= + }=0A= + array_init(return_value);=0A= + OBJ_NAME_do_all_sorted(OBJ_NAME_TYPE_MD_METH,=0A= + aliases ? openssl_add_method_or_alias: openssl_add_method, =0A= + return_value);=0A= +}=0A= +=0A= +PHP_FUNCTION(openssl_get_cipher_methods)=0A= +{=0A= + zend_bool aliases =3D 0;=0A= +=0A= + if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "|b", &aliases) = =3D=3D FAILURE) {=0A= + return;=0A= + }=0A= + array_init(return_value);=0A= + OBJ_NAME_do_all_sorted(OBJ_NAME_TYPE_CIPHER_METH,=0A= + aliases ? openssl_add_method_or_alias: openssl_add_method, =0A= + return_value);=0A= +}=0A= +=0A= +PHP_FUNCTION(openssl_digest)=0A= +{=0A= + zend_bool raw_output =3D 0;=0A= + char *data, *method;=0A= + int data_len, method_len;=0A= + const EVP_MD *mdtype;=0A= + EVP_MD_CTX md_ctx;=0A= + int siglen;=0A= + unsigned char *sigbuf;=0A= +=0A= + if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "ss|b", &data, = &data_len, &method, &method_len, &raw_output) =3D=3D FAILURE) {=0A= + return;=0A= + }=0A= + mdtype =3D EVP_get_digestbyname(method);=0A= + if (!mdtype) {=0A= + php_error_docref(NULL TSRMLS_CC, E_WARNING, "Unknown signature = algorithm.");=0A= + RETURN_FALSE;=0A= + }=0A= +=0A= + siglen =3D EVP_MD_size(mdtype);=0A= + sigbuf =3D emalloc(siglen + 1);=0A= +=0A= + EVP_DigestInit(&md_ctx, mdtype);=0A= + EVP_DigestUpdate(&md_ctx, (unsigned char *)data, data_len);=0A= + if (EVP_DigestFinal (&md_ctx, (unsigned char *)sigbuf, (unsigned int = *)&siglen)) {=0A= + if (raw_output) {=0A= + sigbuf[siglen] =3D '\0';=0A= + RETVAL_STRINGL((char *)sigbuf, siglen, 0);=0A= + } else {=0A= + int digest_str_len =3D siglen * 2;=0A= + char *digest_str =3D emalloc(digest_str_len + 1);=0A= +=0A= + make_digest_ex(digest_str, sigbuf, siglen);=0A= + efree(sigbuf);=0A= + RETVAL_STRINGL(digest_str, digest_str_len, 0);=0A= + }=0A= + } else {=0A= + efree(sigbuf);=0A= + RETVAL_FALSE;=0A= + }=0A= +}=0A= +=0A= +/* {{{ proto array openssl_encryp(string data, string method, string = password [, bool raw_output=3Dfalse])=0A= + Returns an array of the fields/values of the CERT */=0A= +PHP_FUNCTION(openssl_encrypt)=0A= +{=0A= + zend_bool raw_output =3D 0;=0A= + char *data, *method, *password;=0A= + int data_len, method_len, password_len;=0A= + const EVP_CIPHER *cipher_type;=0A= + EVP_CIPHER_CTX cipher_ctx;=0A= + int i, outlen, keylen, ivlen;=0A= + unsigned char *outbuf, *key, *iv;=0A= +=0A= + if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "sss|b", &data, = &data_len, &method, &method_len, &password, &password_len, &raw_output) = =3D=3D FAILURE) {=0A= + return;=0A= + }=0A= + cipher_type =3D EVP_get_cipherbyname(method);=0A= + if (!cipher_type) {=0A= + php_error_docref(NULL TSRMLS_CC, E_WARNING, "Unknown signature = algorithm.");=0A= + RETURN_FALSE;=0A= + }=0A= +=0A= + keylen =3D EVP_CIPHER_key_length(cipher_type);=0A= + if (keylen > password_len) {=0A= + key =3D emalloc(keylen);=0A= + memset(key, 0, keylen);=0A= + memcpy(key, password, password_len);=0A= + } else {=0A= + key =3D (unsigned char*)password;=0A= + }=0A= +=0A= + ivlen =3D EVP_CIPHER_iv_length(cipher_type);=0A= + iv =3D emalloc(ivlen);=0A= + memset(iv, 0, ivlen);=0A= +=0A= + outlen =3D data_len + EVP_CIPHER_block_size(cipher_type);=0A= + outbuf =3D emalloc(outlen + 1);=0A= +=0A= + EVP_EncryptInit(&cipher_ctx, cipher_type, key, iv);=0A= + EVP_EncryptUpdate(&cipher_ctx, outbuf, &i, (unsigned char *)data, = data_len);=0A= + outlen =3D i;=0A= + if (EVP_EncryptFinal(&cipher_ctx, (unsigned char *)outbuf + i, &i)) {=0A= + outlen +=3D i;=0A= + if (raw_output) {=0A= + outbuf[outlen] =3D '\0';=0A= + RETVAL_STRINGL((char *)outbuf, outlen, 0);=0A= + } else {=0A= + int base64_str_len;=0A= + char *base64_str;=0A= +=0A= + base64_str =3D (char*)php_base64_encode(outbuf, outlen, = &base64_str_len);=0A= + efree(outbuf);=0A= + RETVAL_STRINGL(base64_str, base64_str_len, 0);=0A= + }=0A= + } else {=0A= + efree(outbuf);=0A= + RETVAL_FALSE;=0A= + }=0A= + if (key !=3D (unsigned char*)password) {=0A= + efree(key);=0A= + }=0A= + efree(iv);=0A= +}=0A= +/* }}} */=0A= +=0A= +PHP_FUNCTION(openssl_decrypt)=0A= +{=0A= + zend_bool raw_input =3D 0;=0A= + char *data, *method, *password;=0A= + int data_len, method_len, password_len;=0A= + const EVP_CIPHER *cipher_type;=0A= + EVP_CIPHER_CTX cipher_ctx;=0A= + int i, outlen, keylen, ivlen;=0A= + unsigned char *outbuf, *key, *iv;=0A= + int base64_str_len;=0A= + char *base64_str =3D NULL;=0A= +=0A= + if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "sss|b", &data, = &data_len, &method, &method_len, &password, &password_len, &raw_input) = =3D=3D FAILURE) {=0A= + return;=0A= + }=0A= +=0A= + if (!raw_input) {=0A= + base64_str =3D (char*)php_base64_decode((unsigned char*)data, = data_len, &base64_str_len);=0A= + data_len =3D base64_str_len;=0A= + data =3D base64_str;=0A= + }=0A= +=0A= + cipher_type =3D EVP_get_cipherbyname(method);=0A= + if (!cipher_type) {=0A= + php_error_docref(NULL TSRMLS_CC, E_WARNING, "Unknown signature = algorithm.");=0A= + RETURN_FALSE;=0A= + }=0A= +=0A= + keylen =3D EVP_CIPHER_key_length(cipher_type);=0A= + if (keylen > password_len) {=0A= + key =3D emalloc(keylen);=0A= + memset(key, 0, keylen);=0A= + memcpy(key, password, password_len);=0A= + } else {=0A= + key =3D (unsigned char*)password;=0A= + }=0A= +=0A= + ivlen =3D EVP_CIPHER_iv_length(cipher_type);=0A= + iv =3D emalloc(ivlen);=0A= + memset(iv, 0, ivlen);=0A= +=0A= + outlen =3D data_len + EVP_CIPHER_block_size(cipher_type);=0A= + outbuf =3D emalloc(outlen + 1);=0A= +=0A= + EVP_DecryptInit(&cipher_ctx, cipher_type, key, iv);=0A= + EVP_DecryptUpdate(&cipher_ctx, outbuf, &i, (unsigned char *)data, = data_len);=0A= + outlen =3D i;=0A= + if (EVP_DecryptFinal(&cipher_ctx, (unsigned char *)outbuf + i, &i)) {=0A= + outlen +=3D i;=0A= + outbuf[outlen] =3D '\0';=0A= + RETVAL_STRINGL((char *)outbuf, outlen, 0);=0A= + } else {=0A= + efree(outbuf);=0A= + RETVAL_FALSE;=0A= + }=0A= + if (key !=3D (unsigned char*)password) {=0A= + efree(key);=0A= + }=0A= + efree(iv);=0A= + if (base64_str) {=0A= + efree(base64_str);=0A= + }=0A= +}=0A= +/* }}} */=0A= +=0A= +=0A= +PHP_FUNCTION(openssl_dh_compute_key)=0A= +{=0A= + zval *key;=0A= + char *pub_str;=0A= + int pub_len;=0A= + EVP_PKEY *pkey;=0A= + BIGNUM *pub;=0A= + char *data;=0A= + int len;=0A= +=0A= + if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "sr", &pub_str, = &pub_len, &key) =3D=3D FAILURE) {=0A= + return;=0A= + }=0A= + ZEND_FETCH_RESOURCE(pkey, EVP_PKEY *, &key, -1, "OpenSSL key", le_key);=0A= + if (!pkey || EVP_PKEY_type(pkey->type) !=3D EVP_PKEY_DH || = !pkey->pkey.dh) {=0A= + RETURN_FALSE;=0A= + }=0A= +=0A= + pub =3D BN_bin2bn((unsigned char*)pub_str, pub_len, NULL);=0A= +=0A= + data =3D emalloc(DH_size(pkey->pkey.dh) + 1);=0A= + len =3D DH_compute_key((unsigned char*)data, pub, pkey->pkey.dh);=0A= +=0A= + if (len >=3D 0) {=0A= + data[len] =3D 0;=0A= + RETVAL_STRINGL(data, len, 0);=0A= + } else {=0A= + efree(data);=0A= + RETVAL_FALSE;=0A= + }=0A= +=0A= + BN_free(pub);=0A= +}=0A= +/* }}} */=0A= /*=0A= * Local variables:=0A= * tab-width: 8=0A= ------=_NextPart_000_002C_01C7D43B.6DA2E720--