Newsgroups: php.internals Path: news.php.net Xref: news.php.net php.internals:23348 Return-Path: Mailing-List: contact internals-help@lists.php.net; run by ezmlm Delivered-To: mailing list internals@lists.php.net Received: (qmail 72661 invoked by uid 1010); 14 May 2006 22:29:54 -0000 Delivered-To: ezmlm-scan-internals@lists.php.net Delivered-To: ezmlm-internals@lists.php.net Received: (qmail 72645 invoked from network); 14 May 2006 22:29:54 -0000 Received: from unknown (HELO lists.php.net) (127.0.0.1) by localhost with SMTP; 14 May 2006 22:29:54 -0000 X-PHP-List-Original-Sender: kingwez@gmail.com X-Host-Fingerprint: 64.233.166.180 py-out-1112.google.com Linux 2.4/2.6 Received: from ([64.233.166.180:11795] helo=py-out-1112.google.com) by pb1.pair.com (ecelerity 2.0 beta r(6323M)) with SMTP id DB/CA-19568-26FA7644 for ; Sun, 14 May 2006 18:29:54 -0400 Received: by py-out-1112.google.com with SMTP id z59so967017pyg for ; Sun, 14 May 2006 15:29:51 -0700 (PDT) DomainKey-Signature: a=rsa-sha1; q=dns; c=nofws; s=beta; d=gmail.com; h=received:message-id:date:from:to:subject:cc:in-reply-to:mime-version:content-type:content-transfer-encoding:content-disposition:references; b=gRiKpkJUT0gu5SEcL/7rk72F8glOPa528tIjuJGoANwbp4mCzp8iO1AX+bpwB+/9KUIDLImcIRL7pfqB4wQ/44xrkchVvZg0Bta6V4+nZbckf7oWigPCA8y21fz+XSbw6m/cWY0WgEiW42hntM84sO8ng2CSKp0nIOZwbpvgh6w= Received: by 10.35.66.12 with SMTP id t12mr2009923pyk; Sun, 14 May 2006 15:29:51 -0700 (PDT) Received: by 10.35.40.20 with HTTP; Sun, 14 May 2006 15:29:51 -0700 (PDT) Message-ID: <4e89b4260605141529h8136efao904fc1bfb23393ea@mail.gmail.com> Date: Sun, 14 May 2006 18:29:51 -0400 To: "Brandon Fosdick" Cc: internals@lists.php.net In-Reply-To: <44651CAC.4080007@bfoz.net> MIME-Version: 1.0 Content-Type: text/plain; charset=ISO-8859-1; format=flowed Content-Transfer-Encoding: quoted-printable Content-Disposition: inline References: <44651CAC.4080007@bfoz.net> Subject: Re: [PHP-DEV] [PATCH] Preliminary OpenSSL Changes (PEM) From: kingwez@gmail.com ("Wez Furlong") Probably the biggest problem is that it requires C++. We mentioned to you that C++ was something we avoided in PHP because it tends to create more problems than it's worth, particularly so in something that is part of the core distribution. Can you write it in C instead? --Wez. On 5/12/06, Brandon Fosdick wrote: > I'm not finished yet, but I'm at a decent check point, so I thought I'd s= end out what I've done so far with the hope of getting some feedback. > > The attached files contain the patches and new files (wrt 5.1.4) for impl= ementing import and export of PEM strings for both public and private keys = using an OO interface. BTW, I know the code doesn't conform to the CS very = well, I plan to run everything through astyle at the very end. > > One of my initial goals was to avoid modifying existing code as much as p= ossible to avoid introducing new breakage. In hindsight that might have bee= n more trouble than it was worth because I ended up doing a lot more than I= had originally planned. But it was a good learning experience. I decided o= n an OO interface because it seemed like it could be most easily accomplish= ed w/o touching existing code. > > At present the new interface adds two classes, described below. I wasn't = sure what to name them, so feel free to offer suggestions. > > class PrivateKey > constructor( [string pem [, string passphrase]] ) > constructor( [array configargs]] ) > string pem( [ string passphrase [, encrypt_key]] ) > PublicKey public() > > class PublicKey > constructor(string pem) > string pem() > > I'm not sure about the second constructor for PrivateKey, since it really= only needs two of the configarg values. I'm thinking about having it take = just those two as separate arguments. > > Most of the changes are in the new files. In openssl.c I added a call to = init_object() in the MINIT function and moved struct php_x509_request to op= enssl.h so I could use it elsewhere. I also made a few functions non-static= so they could be called from the other files. > > From here I think I might as well add an object for certificates (X509, X= 509Certificate, Certificate...?) and then I'll add PKCS12 support. > > Thoughts, suggestions? Problems? > > > --- config0.m4.orig Sat Jan 1 06:32:58 2005 > +++ config.m4 Wed May 10 15:14:22 2006 > @@ -9,8 +9,10 @@ > [ --with-kerberos[=3DDIR] OPENSSL: Include Kerberos support], no, n= o) > > if test "$PHP_OPENSSL" !=3D "no"; then > - PHP_NEW_EXTENSION(openssl, openssl.c xp_ssl.c, $ext_shared) > + PHP_REQUIRE_CXX() > + PHP_NEW_EXTENSION(openssl, openssl.c xp_ssl.c init_oo.cc pubkey.cc pri= vkey.cc, $ext_shared) > PHP_SUBST(OPENSSL_SHARED_LIBADD) > + PHP_ADD_LIBRARY(stdc++, 1, OPENSSL_SHARED_LIBADD) > > if test "$PHP_KERBEROS" !=3D "no"; then > PHP_SETUP_KERBEROS(OPENSSL_SHARED_LIBADD) > > > /* Filename: init_oo.cc > Object oriented OpenSSL interface for PHP5 > > 200600505 Created by Brandon Fosdick > */ > > #include "privkey.h" > #include "pubkey.h" > > //Make storage for static members of ObjectBase > // These are the members that don't need type-specific defaults > template zend_class_entry* php::ObjectBase::class_entry = =3D NULL; > template zend_object_handlers php::ObjectBase::handlers; > template zend_internal_function php::ObjectBase::construct= or_function; > > namespace php > { > namespace openssl > { > extern "C" void init_objects(TSRMLS_D) > { > PrivateKey::register_class(TSRMLS_C); > PublicKey::register_class(TSRMLS_C); > } > } > } > > > /* Filename: objbase.h > Base class for wrapping PHP5 Object Oriented interface > > 20060501 Created by Brandon Fosdick > */ > > extern "C" > { > #include "php.h" > } > > #ifndef OBJBASE_H > #define OBJBASE_H > > namespace php > { > template > class ObjectBase : public zend_object > { > typedef T obj_t; > > protected: > static const char *const name; > static zend_class_entry* class_entry; //A Class= Entry for every derived type > static zend_object_handlers handlers; //Handler= s for every derived type > static zend_internal_function constructor_function; /= /Function entry for the new-handler > static zend_function_entry methods[]; //Handler= s for derived type userland-methods > > public: > //Base constructor > ObjectBase(zend_class_entry *zce) > { > ce =3D zce; > ALLOC_HASHTABLE(properties); > zend_hash_init(properties, 0, NULL, ZVAL_PTR_DTOR= , 0); > > guards =3D NULL; //Init unused pointer > > zval *tmp; > zend_hash_copy(properties, &zce->default_properti= es, (copy_ctor_func_t)zval_add_ref, (void *)&tmp, sizeof(zval*)); > } > > ~ObjectBase() > { > //Explicitly destroy the zend_object base (it doe= sn't have its own destructor) > zend_object_std_dtor(static_cast(th= is) TSRMLS_CC); > } > void* operator new(size_t s) { return emalloc(s)= ; } > void operator delete(void* p, size_t) { e= free(p); } > > //Register the class > static void register_class(TSRMLS_D) > { > zend_class_entry ce; > > memset(&ce, NULL, sizeof(ce)); > INIT_CLASS_ENTRY(ce, name, methods); > ce.name_length =3D strlen(name); //Work-= a-round for "feature" in INIT_CLASS_ENTRY > ce.create_object =3D &construct; //psued= o-constructor > class_entry =3D zend_register_internal_class(&ce = TSRMLS_CC); > if( class_entry !=3D NULL ) > class_entry->ce_flags |=3D ZEND_ACC_FINAL= _CLASS; > > handlers =3D *zend_get_std_object_handlers(); > handlers.clone_obj =3D NULL; //No cloning > handlers.get_constructor =3D &get_constructor; > } > > //Construct and register a new unitialized object in a zv= al > // Used by handlers that need to return a new object > // Uses the static zend_class_entry object, so regis= ter_class() must be called first > // *** This is a bare-minimum psuedo-contructor = that calls the simplest constructor > // possible, and may leave t= he class mostly uninitialized. The class probably > // still needs to be initial= ized in the new()-handler. > static obj_t* construct(zval *z TSRMLS_DC) > { > if(class_entry =3D=3D NULL) = //Ignore calls prior to register_class() > return NULL; > obj_t* obj =3D new obj_t(class_entry); //New o= bject with registered zend_class_entry > z->type =3D IS_OBJECT; > z->value.obj =3D obj->store(TSRMLS_C); > return obj; > } > > private: > //Construct and then put on the object store > // This is function passed to the ZE by get_construc= tor() > // *** This is a bare-minimum psuedo-contructor = that calls the simplest constructor > // possible, and may leave t= he class mostly uninitialized. The class probably > // still needs to be initial= ized in the new()-handler. > static zend_object_value construct(zend_class_entry *zce = TSRMLS_DC) > { > return (new obj_t(zce))->store(TSRMLS_C); > } > > //A destructor for every derived type > static void destroy(void* object TSRMLS_DC) > { > delete static_cast(static_cast(object)); > } > > //Make a zend_function for the derived class' constructor= handler > static zend_function* get_constructor(zval* object TSRMLS= _DC) > { > zend_object* obj =3D zend_objects_get_address(obj= ect TSRMLS_CC); > > if(obj =3D=3D NULL) > return NULL; > > memset(&constructor_function, NULL, sizeof(constr= uctor_function)); > constructor_function.type =3D ZEND_INTERNAL_FUNCT= ION; > constructor_function.function_name =3D obj->ce->n= ame; > constructor_function.scope =3D obj->ce; > constructor_function.handler =3D &obj_t::ZEND_FN(= construct); > > return reinterpret_cast(&construc= tor_function); > } > > //Register the object with the ZE object store > // This function is private to help prevent being ca= lled more than once per object > zend_object_value store(TSRMLS_D) > { > zend_object_value r; > //Downcast to a zend_object* to appease the stand= ard object handlers > r.handle =3D zend_objects_store_put((zend_object*= )this, NULL, &destroy, NULL TSRMLS_CC); > r.handlers =3D &handlers; > return r; > } > > }; > > template > inline T* get_object(zval* z TSRMLS_DC) > { > return static_cast(static_cast(zend_obj= ect_store_get_object(z TSRMLS_CC))); > } > > inline zend_object* get_object(zval* z TSRMLS_DC) > { > return static_cast(zend_object_store_get_ob= ject(z TSRMLS_CC)); > } > > } //namespace php > > #endif //OBJBASE_H > > > --- openssl.c.orig Sun Apr 30 16:43:40 2006 > +++ openssl.c Fri May 12 15:53:46 2006 > @@ -41,7 +41,8 @@ > #include > #include > #include > -#include > + > +#include "openssl.h" > > #define DEFAULT_KEY_LENGTH 512 > #define MIN_KEY_LENGTH 384 > @@ -202,32 +203,13 @@ > /* true global; readonly after module startup */ > static char default_ssl_conf_filename[MAXPATHLEN]; > > -struct php_x509_request { > - LHASH * global_config; /* Global SSL config */ > - LHASH * req_config; /* SSL config for this request */ > - const EVP_MD * md_alg; > - const EVP_MD * digest; > - char * section_name, > - * config_filename, > - * digest_name, > - * extensions_section, > - * request_extensions_section; > - int priv_key_bits; > - int priv_key_type; > - > - int priv_key_encrypt; > - > - EVP_PKEY * priv_key; > -}; > - > - > static X509 * php_openssl_x509_from_zval(zval ** val, int makeresource, = long * resourceval TSRMLS_DC); > static EVP_PKEY * php_openssl_evp_from_zval(zval ** val, int public_key,= char * passphrase, int makeresource, long * resourceval TSRMLS_DC); > static int php_openssl_is_private_key(EVP_PKEY* pkey TSRMLS_DC); > static X509_STORE * setup_verify(zval * calist TSRMLS_DC); > static STACK_OF(X509) * load_all_certs_from_file(char *certfile); > static X509_REQ * php_openssl_csr_from_zval(zval ** val, int makeresourc= e, long * resourceval TSRMLS_DC); > -static EVP_PKEY * php_openssl_generate_private_key(struct php_x509_reque= st * req TSRMLS_DC); > +EVP_PKEY * php_openssl_generate_private_key(struct php_x509_request * re= q TSRMLS_DC); > > > static void add_assoc_name_entry(zval * val, char * key, X509_NAME * nam= e, int shortname TSRMLS_DC) > @@ -427,7 +409,7 @@ > > > > -static int php_openssl_parse_config( > +int php_openssl_parse_config( > struct php_x509_request * req, > zval * optional_args > TSRMLS_DC > @@ -589,6 +571,8 @@ > le_x509 =3D zend_register_list_destructors_ex(php_x509_free, NULL= , "OpenSSL X.509", module_number); > le_csr =3D zend_register_list_destructors_ex(php_csr_free, NULL, = "OpenSSL X.509 CSR", module_number); > > + init_objects(TSRMLS_C); /* Initialize the OO interface *= / > + > SSL_library_init(); > OpenSSL_add_all_ciphers(); > OpenSSL_add_all_digests(); > @@ -1873,7 +1857,7 @@ > /* }}} */ > > /* {{{ php_openssl_generate_private_key */ > -static EVP_PKEY * php_openssl_generate_private_key(struct php_x509_reque= st * req TSRMLS_DC) > +EVP_PKEY * php_openssl_generate_private_key(struct php_x509_request * re= q TSRMLS_DC) > { > char * randfile =3D NULL; > int egdsocket, seeded; > > > /* Filename: openssl.h > Most of this was moved from openssl.c > > 20060510 Created by Brandon Fosdick > */ > > #include > #include > > #ifndef OPENSSL_H > #define OPENSSL_H > > struct php_x509_request { > LHASH * global_config; /* Global SSL config */ > LHASH * req_config; /* SSL config for this request */ > const EVP_MD * md_alg; > const EVP_MD * digest; > char * section_name, > * config_filename, > * digest_name, > * extensions_section, > * request_extensions_section; > int priv_key_bits; > int priv_key_type; > > int priv_key_encrypt; > > EVP_PKEY * priv_key; > }; > > #ifdef __cplusplus > extern "C" > { > #endif > int php_openssl_parse_config(struct php_x509_request*, zval* TSRMLS_DC); > EVP_PKEY* php_openssl_generate_private_key(struct php_x509_request* TSRML= S_DC); > #ifdef __cplusplus > } > > namespace php > { > namespace openssl > { > class X509Request : public php_x509_request > { > public: > X509Request() > { > global_config =3D NULL; > req_config =3D NULL; > md_alg =3D NULL; > digest =3D NULL;; > section_name =3D NULL; > config_filename =3D NULL; > digest_name =3D NULL; > extensions_section =3D NULL; > request_extensions_section =3D NULL; > priv_key_bits =3D 0; > priv_key_type =3D 0; > priv_key_encrypt =3D 0; > EVP_PKEY * priv_key =3D NULL; > } > //This doesn't call php_openssl_dispose_config() = because there's no way to pass > // TSRMLS_* to a destructor > // *** This assumes that the EVP_PKEY is= managed elsewhere > ~X509Request() > { > if( global_config !=3D NULL ) > { > CONF_free(global_config); > global_config =3D NULL; > } > if( req_config !=3D NULL ) > { > CONF_free(req_config); > req_config =3D NULL; > } > } > bool parse_config(zval* z) > { > return php_openssl_parse_config(&base(), = z TSRMLS_CC) =3D=3D SUCCESS; > } > EVP_PKEY* generate_private_key(TSRMLS_D) > { > return php_openssl_generate_private_key(&= base() TSRMLS_CC); > } > php_x509_request& base() { return *t= his; } > }; > } > } > > #endif //__cplusplus > > #endif //OPENSSL_H > > > /* Filename: privkey.cc > Private key interface class for PHP5 > > 20060429 Created by Brandon Fosdick > */ > > #include "privkey.h" > > #include "openssl.h" > > namespace php > { > namespace openssl > { > template<> > const char *const ObjectBase::name =3D "Priva= teKey"; //Set the class's userland name > > //Do the actual construction in response to a userland ca= ll to 'new PrivateKey()' > // The first argument can be a config_args array > // It could also be a PEM string, in which case the = 2nd arg is an optional passphrase > // The passphrase could be a zero-length string, whi= ch isn't considered to be a passphrase > PHP_NAMED_FUNCTION(PrivateKey::ZEND_FN(construct)) > { > zval *z =3D NULL; > unsigned char* pass =3D NULL; > int pass_len =3D 0; > > if( zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_= CC, "|z!s", &z, &pass, &pass_len) =3D=3D FAILURE ) > { > RETURN_FALSE; > } > > //Get the mostly-unitialized object off the objec= t store > PrivateKey* key =3D get_object(getThi= s() TSRMLS_CC); > if( key =3D=3D NULL ) > { > RETURN_FALSE; > } > > //Now behave like a constructor > if( (z !=3D NULL) && (Z_TYPE_P(z) =3D=3D IS_STRIN= G) ) //Create the key from a PEM string > { > BIO *in =3D BIO_new_mem_buf(Z_STRVAL_P(z)= , Z_STRLEN_P(z)); > if(in =3D=3D NULL) > { > RETURN_FALSE; > } > > pass =3D (pass_len=3D=3D0)?NULL:pass; //I= gnore zero-length passphrases > key->key =3D PEM_read_bio_PrivateKey(in, = NULL, NULL, pass); > BIO_free(in); > } > else //Generate a new key > { > X509Request req; > req.parse_config(z); > key->numBits =3D req.priv_key_bits; = //Save the number of key bits > key->key =3D req.generate_private_key(TSR= MLS_C); > } > } > > namespace privatekey > { > //Return the private key as PEM formatted text > PHP_FUNCTION(pem) > { > unsigned char* pass =3D NULL; > int pass_len =3D 0; > zend_bool encrypt =3D false; > > RETVAL_FALSE; //Default retval to false= (speedup) > > if( zend_parse_parameters(ZEND_NUM_ARGS()= TSRMLS_CC, "|s!b", &pass, &pass_len, &encrypt) =3D=3D FAILURE) > { > return; > } > > PrivateKey* key =3D get_object(getThis() TSRMLS_CC); > if( key =3D=3D NULL ) > { > return; > } > > key->pem(return_value, pass, pass_len, en= crypt); > } > > //Return a PublicKey object for this private key > PHP_FUNCTION(public) > { > PrivateKey* key =3D get_object(getThis() TSRMLS_CC); > > if( key =3D=3D NULL ) > { > RETURN_FALSE; > } > > key->get_public(return_value); > // RETURN_STRING("this is public()\n", 1); > } > } //namespace privatekey > > #define PRIVKEY_ME(func_name, handler_name) ZEND_FENTRY(func_= name, &openssl::privatekey:: PHP_FN(handler_name), NULL, 0) > template<> zend_function_entry ObjectBase::me= thods[] =3D > { > // PRIVKEY_ME(csr, csr) /= /Return a CSR object > PRIVKEY_ME(pem, pem) /= /Return the private key as PEM formatted text > PRIVKEY_ME(public, public) //Return = a PublicKey object for this private key > {NULL, NULL, NULL} > }; > } //namespace openssl > } //namespace php > > > /* Filename: privkey.h > Private key interface class for PHP5 > > 20060501 Created by Brandon Fosdick > */ > > #include > > #include > > #include "objbase.h" > #include "pubkey.h" > > #ifndef PRIVKEY_H > #define PRIVKEY_H > > namespace php > { > namespace openssl > { > class PrivateKey : public ObjectBase > { > EVP_PKEY* key; > unsigned numBits; > > PrivateKey(const PrivateKey&); //No copying > public: > //Bare-minimum constructor > PrivateKey(zend_class_entry *zce) : key(NULL), nu= mBits(0), ObjectBase(zce) {} > ~PrivateKey() > { > if( key !=3D NULL ) > { > EVP_PKEY_free(key); > } > } > > static PHP_FUNCTION(construct); //Handle userland= new() > > bool pem(zval *const out, unsigned char *const pa= ss, size_t len, const bool encrypt) > { > const EVP_CIPHER* cipher =3D (pass && enc= rypt && (len!=3D0)) ? EVP_des_ede3_cbc() : NULL; > BIO* bio_out =3D BIO_new(BIO_s_mem()); > if( PEM_write_bio_PrivateKey(bio_out, key= , cipher, pass, len, NULL, NULL) ) > { > char* bio_mem_ptr; > long bio_mem_len =3D BIO_get_m= em_data(bio_out, &bio_mem_ptr); > ZVAL_STRINGL(out, bio_mem_ptr, bi= o_mem_len, 1); > } > > if( bio_out ) > { > BIO_free(bio_out); > } > return true; > } > > void get_public(zval* z) > { > PublicKey* pub =3D PublicKey::construct(z= , key); > if( pub =3D=3D NULL ) > return; > ++key->references; //Inc the ref cou= nt to prevent early deletion > } > }; > } //namespace openssl > } //namespace php > > #endif //PRIVKEY_H > > > /* Filename: pubkey.cc > Public key interface class for PHP5 > > 20060429 Created by Brandon Fosdick > */ > > #include "pubkey.h" > > #define RSA_PUBLIC_HEADER "-----BEGIN RSA PUBLIC KEY-----" > > namespace php > { > namespace openssl > { > template<> const char *const ObjectBase::name = =3D "PublicKey"; //Set the class's userland name > > PHP_NAMED_FUNCTION(PublicKey::ZEND_FN(construct)) > { > zval *z; > unsigned char* pem =3D NULL; > int pem_len =3D 0; > > if( zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_= CC, "s", &pem, &pem_len) =3D=3D FAILURE ) > { > RETURN_FALSE; > } > > //Get the mostly-unitialized object off the objec= t store > PublicKey* key =3D get_object(getThis(= ) TSRMLS_CC); > if( key =3D=3D NULL ) > { > RETURN_FALSE; > } > > //Now behave like a constructor > if( (pem !=3D NULL) && (pem_len !=3D 0) ) //Cre= ate the key from a PEM string > { > BIO *in =3D BIO_new_mem_buf(pem, pem_len)= ; //Init the input buffer > if( in =3D=3D NULL) > { > RETURN_FALSE; > } > key->key =3D PEM_read_bio_PUBKEY(in, NULL= , NULL, NULL); > BIO_free(in); > } > } > > namespace publickey > { > //Return the public key as PEM formatted text > PHP_FUNCTION(pem) > { > PublicKey* key =3D get_object(= getThis() TSRMLS_CC); > if( key =3D=3D NULL ) > { > RETURN_FALSE; > } > > key->pem(return_value); > } > } //namespace publickey > > #define PUBKEY_ME(func_name, handler_name) ZEND_FENTRY(func_= name, &openssl::publickey:: ZEND_FN(handler_name), NULL, 0) > template<> zend_function_entry ObjectBase::met= hods[] =3D > { > PUBKEY_ME(pem, pem) /= /Return the public key as PEM formatted text > // PUBKEY_ME(spawn, spawn, NULL) > {NULL, NULL, NULL} > }; > } //namespace openssl > } //namespace php > > > /* Filename: pubkey.h > Public key interface class for PHP5 > > 20060501 Created by Brandon Fosdick > */ > > #include > > #include "objbase.h" > > #ifndef PUBKEY_H > #define PUBKEY_H > > namespace php > { > namespace openssl > { > class PublicKey : public ObjectBase > { > EVP_PKEY* key; > > PublicKey(const PublicKey&); //No copying > public: > //Bare-minimum constructor > PublicKey(zend_class_entry *zce) : key(NULL), Obj= ectBase(zce) {} > ~PublicKey() > { > if( key !=3D NULL ) > { > EVP_PKEY_free(key); > } > } > > bool init(EVP_PKEY* k) > { > if(key =3D=3D NULL) > { > key =3D k; > return true; > } > return false; > } > > static PHP_FUNCTION(construct); //Handle userland= new() > > //Construct and register a new unitialized object= in a zval given an existing key > // Used by handlers that need to return a ne= w object > // Uses the static zend_class_entry object, = so register_class() must be called first > static PublicKey* construct(zval *z, EVP_PKEY* ne= w_key TSRMLS_DC) > { > PublicKey* obj =3D ObjectBase:= :construct(z); > if( obj =3D=3D NULL ) > return NULL; > obj->init(new_key); > return obj; > } > > bool pem(zval *const out) > { > if( (key->type !=3D EVP_PKEY_RSA) && (key= ->type !=3D EVP_PKEY_RSA2) ) > return false; > > BIO* bio_out =3D BIO_new(BIO_s_mem()); > if( PEM_write_bio_RSA_PUBKEY(bio_out, key= ->pkey.rsa) ) > { > char* bio_mem_ptr; > long bio_mem_len =3D BIO_get_m= em_data(bio_out, &bio_mem_ptr); > ZVAL_STRINGL(out, bio_mem_ptr, bi= o_mem_len, 1); > } > > if( bio_out ) > { > BIO_free(bio_out); > } > return true; > } > }; > } //namespace openssl > } //namespace php > > #endif //PUBKEY_H > > > > -- > PHP Internals - PHP Runtime Development Mailing List > To unsubscribe, visit: http://www.php.net/unsub.php > >