php.net |  support |  documentation |  report a bug |  advanced search |  search howto |  statistics |  random bug |  login
Return to Bug #38917
Patch spki.patch revision 2011-12-22 10:41 UTC by jason dot gerfen at gmail dot com
revision 2011-12-21 20:31 UTC by jason dot gerfen at gmail dot com
revision 2011-12-21 16:09 UTC by jason dot gerfen at gmail dot com
revision 2011-12-21 03:48 UTC by jason dot gerfen at gmail dot com
revision 2011-12-21 03:26 UTC by jason dot gerfen at gmail dot com
revision 2011-12-19 17:58 UTC by jason dot gerfen at gmail dot com
revision 2011-12-19 17:53 UTC by jason dot gerfen at gmail dot com
revision 2011-12-19 14:36 UTC by jason dot gerfen at gmail dot com
revision 2011-12-14 11:38 UTC by jason dot gerfen at gmail dot com
revision 2011-12-13 16:55 UTC by jason dot gerfen at gmail dot com
revision 2011-12-08 10:57 UTC by jason dot gerfen at gmail dot com
revision 2011-12-06 21:02 UTC by jason dot gerfen at gmail dot com
revision 2011-12-06 11:35 UTC by jason dot gerfen at gmail dot com
revision 2011-12-06 11:29 UTC by jason dot gerfen at gmail dot com

Patch spki.patch for OpenSSL related Bug #38917

Patch version 2011-12-06 11:29 UTC

Return to Bug #38917 | Download this patch
Patch Revisions:

Developer: jason.gerfen@gmail.com

diff -Naur php-5.3.8/ext/openssl/openssl.c php-5.3.8-patched/ext/openssl/openssl.c
--- php-5.3.8/ext/openssl/openssl.c	2011-07-25 05:42:53.000000000 -0600
+++ php-5.3.8-patched/ext/openssl/openssl.c	2011-12-06 04:24:32.403578621 -0700
@@ -16,7 +16,7 @@
    |          Wez Furlong <wez@thebrainroom.com>                          |
    |          Sascha Kettler <kettler@gmx.net>                            |
    |          Pierre-Alain Joye <pierre@php.net>                          |
-   |          Marc Delling <delling@silpion.de> (PKCS12 functions)        |		
+   |          Marc Delling <delling@silpion.de> (PKCS12 functions)        |
    +----------------------------------------------------------------------+
  */
 
@@ -372,11 +372,30 @@
     ZEND_ARG_INFO(0, length)
     ZEND_ARG_INFO(1, result_is_strong)
 ZEND_END_ARG_INFO()
+
+ZEND_BEGIN_ARG_INFO_EX(arginfo_openssl_spki_new, 0, 0, 0)
+    ZEND_ARG_INFO(0, privkey)
+    ZEND_ARG_INFO(0, password)
+    ZEND_ARG_INFO(0, spki_hash)
+ZEND_END_ARG_INFO()
+
+ZEND_BEGIN_ARG_INFO(arginfo_openssl_spki_verify, 0)
+    ZEND_ARG_INFO(0, spki)
+ZEND_END_ARG_INFO()
+
+ZEND_BEGIN_ARG_INFO(arginfo_openssl_spki_export, 0)
+    ZEND_ARG_INFO(0, spki)
+ZEND_END_ARG_INFO()
 /* }}} */
 
 /* {{{ openssl_functions[]
  */
 const zend_function_entry openssl_functions[] = {
+/* spki functions */
+	PHP_FE(openssl_spki_new, 		arginfo_openssl_spki_new)
+	PHP_FE(openssl_spki_verify,		arginfo_openssl_spki_verify)
+	PHP_FE(openssl_spki_export,		arginfo_openssl_spki_export)
+
 /* public/private key functions */
 	PHP_FE(openssl_pkey_free,			arginfo_openssl_pkey_free)
 	PHP_FE(openssl_pkey_new,			arginfo_openssl_pkey_new)
@@ -506,7 +525,7 @@
 	if (php_check_open_basedir(filename TSRMLS_CC)) {
 		return -1;
 	}
-	
+
 	return 0;
 }
 /* }}} */
@@ -563,7 +582,7 @@
 	} else {
 		subitem = val;
 	}
-	
+
 	for (i = 0; i < X509_NAME_entry_count(name); i++) {
 		unsigned char *to_add;
 		int to_add_len;
@@ -606,7 +625,7 @@
 			last = j;
 		}
 		i = last;
-		
+
 		if (obj_cnt > 1) {
 			add_assoc_zval_ex(subitem, sname, strlen(sname) + 1, subentries);
 		} else {
@@ -706,7 +725,7 @@
 #endif
 {
 	X509V3_CTX ctx;
-	
+
 	X509V3_set_ctx_test(&ctx);
 	X509V3_set_conf_lhash(&ctx, config);
 	if (!X509V3_EXT_add_conf(config, &ctx, (char *)section, NULL)) {
@@ -816,7 +835,7 @@
 			req->priv_key_encrypt = 1;
 		}
 	}
-	
+
 	/* digest alg */
 	if (req->digest_name == NULL) {
 		req->digest_name = CONF_get_string(req->req_config, req->section_name, "default_md");
@@ -838,7 +857,7 @@
 	}
 
 	PHP_SSL_CONFIG_SYNTAX_CHECK(request_extensions_section);
-	
+
 	return SUCCESS;
 }
 /* }}} */
@@ -991,10 +1010,10 @@
 	/* register a resource id number with OpenSSL so that we can map SSL -> stream structures in
 	 * OpenSSL callbacks */
 	ssl_stream_data_index = SSL_get_ex_new_index(0, "PHP stream index", NULL, NULL, NULL);
-	
+
 	REGISTER_STRING_CONSTANT("OPENSSL_VERSION_TEXT", OPENSSL_VERSION_TEXT, CONST_CS|CONST_PERSISTENT);
 	REGISTER_LONG_CONSTANT("OPENSSL_VERSION_NUMBER", OPENSSL_VERSION_NUMBER, CONST_CS|CONST_PERSISTENT);
-	
+
 	/* purposes for cert purpose checking */
 	REGISTER_LONG_CONSTANT("X509_PURPOSE_SSL_CLIENT", X509_PURPOSE_SSL_CLIENT, CONST_CS|CONST_PERSISTENT);
 	REGISTER_LONG_CONSTANT("X509_PURPOSE_SSL_SERVER", X509_PURPOSE_SSL_SERVER, CONST_CS|CONST_PERSISTENT);
@@ -1084,7 +1103,7 @@
 
 	php_register_url_stream_wrapper("https", &php_stream_http_wrapper TSRMLS_CC);
 	php_register_url_stream_wrapper("ftps", &php_stream_ftp_wrapper TSRMLS_CC);
-	
+
 	return SUCCESS;
 }
 /* }}} */
@@ -1252,6 +1271,151 @@
 }
 /* }}} */
 
+/* {{{ proto string openssl_spki_new(mixed priv_key, string password)
+   Creates new private key (or uses existing) and creates a new spki cert
+   outputting results to var */
+PHP_FUNCTION(openssl_spki_new)
+{
+ zval * zout, * zpkey = NULL;
+ EVP_PKEY * pkey = NULL;
+ NETSCAPE_SPKI *spki=NULL;
+ char * password, * spkstr;
+ long keyresource;
+ const char *spkac = "SPKAC=";
+
+ RETVAL_FALSE;
+
+ zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "rs|s", &zpkey, &password, &zout);
+
+ pkey = php_openssl_evp_from_zval(&zpkey, 0, password, 1, &keyresource TSRMLS_CC);
+
+ if (pkey == NULL) {
+  php_error_docref(NULL TSRMLS_CC, E_WARNING, "cannot get private key from parameter 1");
+  goto cleanup;
+ }
+
+ if ((spki = NETSCAPE_SPKI_new()) == NULL) {
+  php_error_docref(NULL TSRMLS_CC, E_WARNING, "cannot get spki interface");
+  goto cleanup;
+ }
+
+ if (password) {
+  ASN1_STRING_set(spki->spkac->challenge, password, (int)strlen(password));
+ }
+
+ if (!NETSCAPE_SPKI_set_pubkey(spki, pkey)) {
+  php_error_docref(NULL TSRMLS_CC, E_WARNING, "cannot get public key from spki");
+  goto cleanup;
+ }
+
+ if (!NETSCAPE_SPKI_sign(spki, pkey, EVP_md5())) {
+  php_error_docref(NULL TSRMLS_CC, E_WARNING, "cannot sign public key with spki");
+  goto cleanup;
+ }
+
+ spkstr = NETSCAPE_SPKI_b64_encode(spki);
+
+ char * s = malloc(snprintf(NULL, 0, "%s%s", spkac, spkstr) + 1);
+ sprintf(s, "%s%s", spkac, spkstr);
+
+ RETVAL_STRINGL(s, strlen(s), 0);
+
+cleanup:
+ if (keyresource == -1 && pkey) {
+  NETSCAPE_SPKI_free(spki);
+  EVP_PKEY_free(pkey);
+ }
+}
+/* }}} */
+
+/* {{{ proto bool openssl_spki_verify(string spki)
+   Verifies spki returns boolean */
+PHP_FUNCTION(openssl_spki_verify)
+{
+ int spkstr_len, i, x=0;
+ char *spkstr = NULL;
+ EVP_PKEY *pkey = NULL;
+ NETSCAPE_SPKI *spki = NULL;
+
+ if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s", &spkstr, &spkstr_len) == FAILURE) {
+  php_error_docref(NULL TSRMLS_CC, E_WARNING, "missing argument 1");
+  goto cleanup;
+ }
+
+ if (!spkstr) {
+  php_error_docref(NULL TSRMLS_CC, E_WARNING, "spki not found");
+  goto cleanup;
+ }
+
+ spki = NETSCAPE_SPKI_b64_decode(spkstr, -1);
+ if (!spki) {
+  php_error_docref(NULL TSRMLS_CC, E_WARNING, "error decoding spki");
+  goto cleanup;
+ }
+
+ pkey = NETSCAPE_SPKI_get_pubkey(spki);
+ if (pkey == NULL) {
+  php_error_docref(NULL TSRMLS_CC, E_WARNING, "error getting public key from spki");
+  goto cleanup;
+ }
+
+ i = NETSCAPE_SPKI_verify(spki, pkey);
+
+ if (i > 0) {
+  x = 1;
+ } else {
+  x = 0;
+ }
+ goto cleanup;
+
+cleanup:
+ EVP_PKEY_free(pkey);
+ RETVAL_BOOL(x);
+}
+/* }}} */
+
+/* {{{ proto string openssl_spki_export(string spki)
+   Exports public key from existing spki to var */
+PHP_FUNCTION(openssl_spki_export)
+{
+ int spkstr_len;
+ EVP_PKEY *pkey = NULL;
+ NETSCAPE_SPKI *spki = NULL;
+ BIO *out = BIO_new_fp(stdout, BIO_NOCLOSE);
+ char *spkstr;
+
+ RETVAL_FALSE;
+
+ if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s", &spkstr, &spkstr_len) == FAILURE) {
+  php_error_docref(NULL TSRMLS_CC, E_WARNING, "missing argument 1");
+  goto cleanup;
+ }
+
+ if (!spkstr) {
+  php_error_docref(NULL TSRMLS_CC, E_WARNING, "spki not found");
+  goto cleanup;
+ }
+
+ spki = NETSCAPE_SPKI_b64_decode(spkstr, strlen(spkstr));
+ if (!spki) {
+  php_error_docref(NULL TSRMLS_CC, E_WARNING, "error decoding spki");
+  goto cleanup;
+ }
+
+ pkey = NETSCAPE_SPKI_get_pubkey(spki);
+ if (!pkey) {
+  php_error_docref(NULL TSRMLS_CC, E_WARNING, "error getting public key from spki");
+  goto cleanup;
+ }
+
+ PEM_write_bio_PUBKEY(out, pkey);
+
+cleanup:
+ NETSCAPE_SPKI_free(spki);
+ EVP_PKEY_free(pkey);
+}
+/* }}} */
+
 /* {{{ proto bool openssl_x509_export(mixed x509, string &out [, bool notext = true])
    Exports a CERT to file or a var */
 PHP_FUNCTION(openssl_x509_export)
@@ -1304,14 +1468,14 @@
 	long certresource = -1, keyresource = -1;
 
 	RETVAL_FALSE;
-	
+
 	if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "ZZ", &zcert, &zkey) == FAILURE) {
 		return;
 	}
 	cert = php_openssl_x509_from_zval(zcert, 0, &certresource TSRMLS_CC);
 	if (cert == NULL) {
 		RETURN_FALSE;
-	}	
+	}
 	key = php_openssl_evp_from_zval(zkey, 0, "", 1, &keyresource TSRMLS_CC);
 	if (key) {
 		RETVAL_BOOL(X509_check_private_key(cert, key));
@@ -1364,11 +1528,11 @@
 		snprintf(buf, sizeof(buf), "%08lx", X509_subject_name_hash(cert));
 		add_assoc_string(return_value, "hash", buf, 1);
 	}
-	
+
 	add_assoc_name_entry(return_value, "issuer", 		X509_get_issuer_name(cert), useshortnames TSRMLS_CC);
 	add_assoc_long(return_value, "version", 			X509_get_version(cert));
 
-	add_assoc_string(return_value, "serialNumber", i2s_ASN1_INTEGER(NULL, X509_get_serialNumber(cert)), 1); 
+	add_assoc_string(return_value, "serialNumber", i2s_ASN1_INTEGER(NULL, X509_get_serialNumber(cert)), 1);
 
 	add_assoc_asn1_string(return_value, "validFrom", 	X509_get_notBefore(cert));
 	add_assoc_asn1_string(return_value, "validTo", 		X509_get_notAfter(cert));
@@ -1570,8 +1734,8 @@
 	if (certresource == 1 && cert) {
 		X509_free(cert);
 	}
-	if (cainfo) { 
-		X509_STORE_free(cainfo); 
+	if (cainfo) {
+		X509_STORE_free(cainfo);
 	}
 	if (untrustedchain) {
 		sk_X509_pop_free(untrustedchain, X509_free);
@@ -1624,7 +1788,7 @@
 				dir_lookup = X509_STORE_add_lookup(store, X509_LOOKUP_hash_dir());
 				if (dir_lookup == NULL || !X509_LOOKUP_add_dir(dir_lookup, Z_STRVAL_PP(item), X509_FILETYPE_PEM)) {
 					php_error_docref(NULL TSRMLS_CC, E_WARNING, "error loading directory %s", Z_STRVAL_PP(item));
-				} else { 
+				} else {
 					ndirs++;
 				}
 				dir_lookup = NULL;
@@ -1718,11 +1882,11 @@
 
 			if (certresource != -1) {
 				cert = X509_dup(cert);
-				
+
 				if (cert == NULL) {
 					goto clean_exit;
 				}
-				
+
 			}
 			sk_X509_push(sk, cert);
 
@@ -1731,7 +1895,7 @@
 	} else {
 		/* a single certificate */
 		cert = php_openssl_x509_from_zval(zcerts, 0, &certresource TSRMLS_CC);
-		
+
 		if (cert == NULL) {
 			goto clean_exit;
 		}
@@ -1776,7 +1940,7 @@
 	if (strlen(filename) != filename_len) {
 		return;
 	}
-	
+
 	cert = php_openssl_x509_from_zval(zcert, 0, &certresource TSRMLS_CC);
 	if (cert == NULL) {
 		php_error_docref(NULL TSRMLS_CC, E_WARNING, "cannot get cert from parameter 1");
@@ -1812,9 +1976,9 @@
 
 	p12 = PKCS12_create(pass, friendly_name, priv_key, cert, ca, 0, 0, 0, 0, 0);
 
-	bio_out = BIO_new_file(filename, "w"); 
+	bio_out = BIO_new_file(filename, "w");
 	if (bio_out) {
-		
+
 		i2d_PKCS12_bio(bio_out, p12);
 
 		RETVAL_TRUE;
@@ -1825,13 +1989,13 @@
 	BIO_free(bio_out);
 	PKCS12_free(p12);
 	php_sk_X509_free(ca);
-	
+
 cleanup:
 
 	if (keyresource == -1 && priv_key) {
 		EVP_PKEY_free(priv_key);
 	}
-	if (certresource == -1 && cert) { 
+	if (certresource == -1 && cert) {
 		X509_free(cert);
 	}
 }
@@ -1857,7 +2021,7 @@
 		return;
 
 	RETVAL_FALSE;
-	
+
 	cert = php_openssl_x509_from_zval(&zcert, 0, &certresource TSRMLS_CC);
 	if (cert == NULL) {
 		php_error_docref(NULL TSRMLS_CC, E_WARNING, "cannot get cert from parameter 1");
@@ -1880,7 +2044,7 @@
 	if (args && zend_hash_find(Z_ARRVAL_P(args), "extracerts", sizeof("extracerts"), (void**)&item) == SUCCESS)
 		ca = php_array_to_X509_sk(item TSRMLS_CC);
 	/* end parse extra config */
-	
+
 	p12 = PKCS12_create(pass, friendly_name, priv_key, cert, ca, 0, 0, 0, 0, 0);
 
 	bio_out = BIO_new(BIO_s_mem());
@@ -1897,13 +2061,13 @@
 	BIO_free(bio_out);
 	PKCS12_free(p12);
 	php_sk_X509_free(ca);
-	
+
 cleanup:
 
 	if (keyresource == -1 && priv_key) {
 		EVP_PKEY_free(priv_key);
 	}
-	if (certresource == -1 && cert) { 
+	if (certresource == -1 && cert) {
 		X509_free(cert);
 	}
 }
@@ -1927,12 +2091,12 @@
 		return;
 
 	RETVAL_FALSE;
-	
+
 	bio_in = BIO_new(BIO_s_mem());
-	
+
 	if(!BIO_write(bio_in, zp12, zp12_len))
 		goto cleanup;
-	
+
 	if(d2i_PKCS12_bio(bio_in, &p12)) {
 		if(PKCS12_parse(p12, pass, &pkey, &cert, &ca)) {
 			BIO * bio_out;
@@ -1962,12 +2126,12 @@
 
 			MAKE_STD_ZVAL(zextracerts);
 			array_init(zextracerts);
-			
+
 			for (i=0;;i++) {
 				zval * zextracert;
 				X509* aCA = sk_X509_pop(ca);
 				if (!aCA) break;
-				
+
 				bio_out = BIO_new(BIO_s_mem());
 				if (PEM_write_bio_X509(bio_out, aCA)) {
 					BUF_MEM *bio_buf;
@@ -1975,7 +2139,7 @@
 					MAKE_STD_ZVAL(zextracert);
 					ZVAL_STRINGL(zextracert, bio_buf->data, bio_buf->length, 1);
 					add_index_zval(zextracerts, i, zextracert);
-					
+
 				}
 				BIO_free(bio_out);
 
@@ -1987,13 +2151,13 @@
 			} else {
 				zval_dtor(zextracerts);
 			}
-			
+
 			RETVAL_TRUE;
-			
+
 			PKCS12_free(p12);
 		}
 	}
-	
+
   cleanup:
 	if (bio_in) {
 		BIO_free(bio_in);
@@ -2001,7 +2165,7 @@
 	if (pkey) {
 		EVP_PKEY_free(pkey);
 	}
-	if (cert) { 
+	if (cert) {
 		X509_free(cert);
 	}
 }
@@ -2020,7 +2184,7 @@
 		return FAILURE;
 	}
 	dn_sk = CONF_get_section(req->req_config, dn_sect);
-	if (dn_sk == NULL) { 
+	if (dn_sk == NULL) {
 		return FAILURE;
 	}
 	attr_sect = CONF_get_string(req->req_config, req->section_name, "attributes");
@@ -2040,15 +2204,15 @@
 		X509_NAME * subj;
 		HashPosition hpos;
 		zval ** item;
-		
+
 		subj = X509_REQ_get_subject_name(csr);
 		/* apply values from the dn hash */
 		zend_hash_internal_pointer_reset_ex(HASH_OF(dn), &hpos);
 		while(zend_hash_get_current_data_ex(HASH_OF(dn), (void**)&item, &hpos) == SUCCESS) {
-			char * strindex = NULL; 
+			char * strindex = NULL;
 			uint strindexlen = 0;
 			ulong intindex;
-			
+
 			zend_hash_get_current_key_ex(HASH_OF(dn), &strindex, &strindexlen, &intindex, 0, &hpos);
 
 			convert_to_string_ex(item);
@@ -2058,7 +2222,7 @@
 
 				nid = OBJ_txt2nid(strindex);
 				if (nid != NID_undef) {
-					if (!X509_NAME_add_entry_by_NID(subj, nid, MBSTRING_ASC, 
+					if (!X509_NAME_add_entry_by_NID(subj, nid, MBSTRING_ASC,
 								(unsigned char*)Z_STRVAL_PP(item), -1, -1, 0))
 					{
 						php_error_docref(NULL TSRMLS_CC, E_WARNING, "dn: add_entry_by_NID %d -> %s (failed)", nid, Z_STRVAL_PP(item));
@@ -2075,10 +2239,10 @@
 		for(i = 0; i < sk_CONF_VALUE_num(dn_sk); i++) {
 			int len;
 			char buffer[200 + 1]; /*200 + \0 !*/
-			
+
 			v = sk_CONF_VALUE_value(dn_sk, i);
 			type = v->name;
-			
+
 			len = strlen(type);
 			if (len < sizeof("_default")) {
 				continue;
@@ -2093,7 +2257,7 @@
 			memcpy(buffer, type, len);
 			buffer[len] = '\0';
 			type = buffer;
-		
+
 			/* Skip past any leading X. X: X, etc to allow for multiple
 			 * instances */
 			for (str = type; *str; str++) {
@@ -2170,7 +2334,7 @@
 	X509_REQ * csr = NULL;
 	char * filename = NULL;
 	BIO * in;
-	
+
 	if (resourceval) {
 		*resourceval = -1;
 	}
@@ -2315,13 +2479,13 @@
 	long csr_resource, certresource = 0, keyresource = -1;
 	int i;
 	struct php_x509_request req;
-	
+
 	if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "ZZ!Zl|a!l", &zcsr, &zcert, &zpkey, &num_days, &args, &serial) == FAILURE)
 		return;
 
 	RETVAL_FALSE;
 	PHP_SSL_REQ_INIT(&req);
-	
+
 	csr = php_openssl_csr_from_zval(zcsr, 0, &csr_resource TSRMLS_CC);
 	if (csr == NULL) {
 		php_error_docref(NULL TSRMLS_CC, E_WARNING, "cannot get CSR from parameter 1");
@@ -2343,7 +2507,7 @@
 		php_error_docref(NULL TSRMLS_CC, E_WARNING, "private key does not correspond to signing cert");
 		goto cleanup;
 	}
-	
+
 	if (PHP_SSL_REQ_PARSE(&req, args) == FAILURE) {
 		goto cleanup;
 	}
@@ -2363,9 +2527,9 @@
 		php_error_docref(NULL TSRMLS_CC, E_WARNING, "Signature did not match the certificate request");
 		goto cleanup;
 	}
-	
+
 	/* Now we can get on with it */
-	
+
 	new_cert = X509_new();
 	if (new_cert == NULL) {
 		php_error_docref(NULL TSRMLS_CC, E_WARNING, "No memory");
@@ -2376,7 +2540,7 @@
 		goto cleanup;
 
 	ASN1_INTEGER_set(X509_get_serialNumber(new_cert), serial);
-	
+
 	X509_set_subject_name(new_cert, X509_REQ_get_subject_name(csr));
 
 	if (cert == NULL) {
@@ -2393,7 +2557,7 @@
 	}
 	if (req.extensions_section) {
 		X509V3_CTX ctx;
-		
+
 		X509V3_set_ctx(&ctx, cert, new_cert, csr, NULL, 0);
 		X509V3_set_conf_lhash(&ctx, req.req_config);
 		if (!X509V3_EXT_add_conf(req.req_config, &ctx, req.extensions_section, new_cert)) {
@@ -2406,11 +2570,11 @@
 		php_error_docref(NULL TSRMLS_CC, E_WARNING, "failed to sign it");
 		goto cleanup;
 	}
-	
+
 	/* Succeeded; lets return the cert */
 	RETVAL_RESOURCE(zend_list_insert(new_cert, le_x509));
 	new_cert = NULL;
-	
+
 cleanup:
 
 	if (cert == new_cert) {
@@ -2427,7 +2591,7 @@
 	if (csr_resource == -1 && csr) {
 		X509_REQ_free(csr);
 	}
-	if (certresource == -1 && cert) { 
+	if (certresource == -1 && cert) {
 		X509_free(cert);
 	}
 	if (new_cert) {
@@ -2446,12 +2610,12 @@
 	X509_REQ * csr = NULL;
 	int we_made_the_key = 1;
 	long key_resource;
-	
+
 	if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "az|a!a!", &dn, &out_pkey, &args, &attribs) == FAILURE) {
 		return;
 	}
 	RETVAL_FALSE;
-	
+
 	PHP_SSL_REQ_INIT(&req);
 
 	if (PHP_SSL_REQ_PARSE(&req, args) == SUCCESS) {
@@ -2483,10 +2647,10 @@
 						php_error_docref(NULL TSRMLS_CC, E_WARNING, "Error loading extension section %s", req.request_extensions_section);
 					} else {
 						RETVAL_TRUE;
-						
+
 						if (X509_REQ_sign(csr, req.priv_key, req.digest)) {
 							RETVAL_RESOURCE(zend_list_insert(csr, le_csr));
-							csr = NULL;			
+							csr = NULL;
 						} else {
 							php_error_docref(NULL TSRMLS_CC, E_WARNING, "Error signing request");
 						}
@@ -2611,14 +2775,14 @@
 	}
 	if (Z_TYPE_PP(val) == IS_ARRAY) {
 		zval ** zphrase;
-		
+
 		/* get passphrase */
 
 		if (zend_hash_index_find(HASH_OF(*val), 1, (void **)&zphrase) == FAILURE) {
 			php_error_docref(NULL TSRMLS_CC, E_WARNING, "key array must be of the form array(0 => key, 1 => phrase)");
 			return NULL;
 		}
-		
+
 		if (Z_TYPE_PP(zphrase) == IS_STRING) {
 			passphrase = Z_STRVAL_PP(zphrase);
 		} else {
@@ -2643,7 +2807,7 @@
 		if (!what) {
 			TMP_CLEAN;
 		}
-		if (resourceval) { 
+		if (resourceval) {
 			*resourceval = Z_LVAL_PP(val);
 		}
 		if (type == le_x509) {
@@ -2677,8 +2841,8 @@
 		}
 	} else {
 		/* force it to be a string and check if it refers to a file */
-		/* passing non string values leaks, object uses toString, it returns NULL 
-		 * See bug38255.phpt 
+		/* passing non string values leaks, object uses toString, it returns NULL
+		 * See bug38255.phpt
 		 */
 		if (!(Z_TYPE_PP(val) == IS_STRING || Z_TYPE_PP(val) == IS_OBJECT)) {
 			TMP_CLEAN;
@@ -2752,7 +2916,7 @@
 	char * randfile = NULL;
 	int egdsocket, seeded;
 	EVP_PKEY * return_val = NULL;
-	
+
 	if (req->priv_key_bits < MIN_KEY_LENGTH) {
 		php_error_docref(NULL TSRMLS_CC, E_WARNING, "private key length is too short; it needs to be at least %d bits, not %d",
 				MIN_KEY_LENGTH, req->priv_key_bits);
@@ -2761,7 +2925,7 @@
 
 	randfile = CONF_get_string(req->req_config, req->section_name, "RANDFILE");
 	php_openssl_load_rand_file(randfile, &egdsocket, &seeded);
-	
+
 	if ((req->priv_key = EVP_PKEY_new()) != NULL) {
 		switch(req->priv_key_type) {
 			case OPENSSL_KEYTYPE_RSA:
@@ -2811,13 +2975,13 @@
 	}
 
 	php_openssl_write_rand_file(randfile, egdsocket, seeded);
-	
+
 	if (return_val == NULL) {
 		EVP_PKEY_free(req->priv_key);
 		req->priv_key = NULL;
 		return NULL;
 	}
-	
+
 	return return_val;
 }
 /* }}} */
@@ -2846,7 +3010,7 @@
 		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){ 
+			if (NULL == pkey->pkey.dsa->p || NULL == pkey->pkey.dsa->q || NULL == pkey->pkey.dsa->priv_key){
 				return 0;
 			}
 			break;
@@ -2977,7 +3141,7 @@
 			}
 			RETURN_FALSE;
 		}
-	} 
+	}
 
 	PHP_SSL_REQ_INIT(&req);
 
@@ -3006,7 +3170,7 @@
 	EVP_PKEY * key;
 	BIO * bio_out = NULL;
 	const EVP_CIPHER * cipher;
-	
+
 	if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "Zs|s!a!", &zpkey, &filename, &filename_len, &passphrase, &passphrase_len, &args) == FAILURE) {
 		return;
 	}
@@ -3022,11 +3186,11 @@
 		php_error_docref(NULL TSRMLS_CC, E_WARNING, "cannot get key from parameter 1");
 		RETURN_FALSE;
 	}
-	
+
 	if (php_openssl_safe_mode_chk(filename TSRMLS_CC)) {
 		RETURN_FALSE;
 	}
-	
+
 	PHP_SSL_REQ_INIT(&req);
 
 	if (PHP_SSL_REQ_PARSE(&req, args) == SUCCESS) {
@@ -3065,7 +3229,7 @@
 	EVP_PKEY * key;
 	BIO * bio_out = NULL;
 	const EVP_CIPHER * cipher;
-	
+
 	if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "Zz|s!a!", &zpkey, &out, &passphrase, &passphrase_len, &args) == FAILURE) {
 		return;
 	}
@@ -3077,7 +3241,7 @@
 		php_error_docref(NULL TSRMLS_CC, E_WARNING, "cannot get key from parameter 1");
 		RETURN_FALSE;
 	}
-	
+
 	PHP_SSL_REQ_INIT(&req);
 
 	if (PHP_SSL_REQ_PARSE(&req, args) == SUCCESS) {
@@ -3193,7 +3357,7 @@
 	array_init(return_value);
 	add_assoc_long(return_value, "bits", EVP_PKEY_bits(pkey));
 	add_assoc_stringl(return_value, "key", pbio, pbio_len, 1);
-	/*TODO: Use the real values once the openssl constants are used 
+	/*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)) {
@@ -3217,7 +3381,7 @@
 				add_assoc_zval(return_value, "rsa", rsa);
 			}
 
-			break;	
+			break;
 		case EVP_PKEY_DSA:
 		case EVP_PKEY_DSA2:
 		case EVP_PKEY_DSA3:
@@ -3238,7 +3402,7 @@
 			}
 			break;
 		case EVP_PKEY_DH:
-			
+
 			ktype = OPENSSL_KEYTYPE_DH;
 
 			if (pkey->pkey.dh != NULL) {
@@ -3254,7 +3418,7 @@
 			}
 
 			break;
-#ifdef EVP_PKEY_EC 
+#ifdef EVP_PKEY_EC
 		case EVP_PKEY_EC:
 			ktype = OPENSSL_KEYTYPE_EC;
 			break;
@@ -3288,7 +3452,7 @@
 	char * extracerts = NULL; int extracerts_len = 0;
 	char * signersfilename = NULL; int signersfilename_len = 0;
 	char * datafilename = NULL; int datafilename_len = 0;
-	
+
 	RETVAL_LONG(-1);
 
 	if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "sl|sass", &filename, &filename_len,
@@ -3296,7 +3460,7 @@
 				&extracerts, &extracerts_len, &datafilename, &datafilename_len) == FAILURE) {
 		return;
 	}
-	
+
 	if (extracerts) {
 		others = load_all_certs_from_file(extracerts);
 		if (others == NULL) {
@@ -3348,11 +3512,11 @@
 
 		if (signersfilename) {
 			BIO *certout;
-		
+
 			if (php_openssl_safe_mode_chk(signersfilename TSRMLS_CC)) {
 				goto clean_exit;
 			}
-		
+
 			certout = BIO_new_file(signersfilename, "w");
 			if (certout) {
 				int i;
@@ -3401,7 +3565,7 @@
 	char * strindex;
 	char * infilename = NULL;	int infilename_len;
 	char * outfilename = NULL;	int outfilename_len;
-	
+
 	RETVAL_FALSE;
 
 	if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "ssZa!|ll", &infilename, &infilename_len,
@@ -3426,7 +3590,7 @@
 	}
 
 	outfile = BIO_new_file(outfilename, "w");
-	if (outfile == NULL) { 
+	if (outfile == NULL) {
 		goto clean_exit;
 	}
 
@@ -3565,7 +3729,7 @@
 
 	if (extracertsfilename) {
 		others = load_all_certs_from_file(extracertsfilename);
-		if (others == NULL) { 
+		if (others == NULL) {
 			goto clean_exit;
 		}
 	}
@@ -3684,7 +3848,7 @@
 		php_error_docref(NULL TSRMLS_CC, E_WARNING, "unable to get private key");
 		goto clean_exit;
 	}
-	
+
 	if (php_openssl_safe_mode_chk(infilename TSRMLS_CC) || php_openssl_safe_mode_chk(outfilename TSRMLS_CC)) {
 		goto clean_exit;
 	}
@@ -3703,7 +3867,7 @@
 	if (p7 == NULL) {
 		goto clean_exit;
 	}
-	if (PKCS7_decrypt(p7, key, cert, out, PKCS7_DETACHED)) { 
+	if (PKCS7_decrypt(p7, key, cert, out, PKCS7_DETACHED)) {
 		RETVAL_TRUE;
 	}
 clean_exit:
@@ -3736,7 +3900,7 @@
 	int data_len;
 	long padding = RSA_PKCS1_PADDING;
 
-	if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "szZ|l", &data, &data_len, &crypted, &key, &padding) == FAILURE) { 
+	if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "szZ|l", &data, &data_len, &crypted, &key, &padding) == FAILURE) {
 		return;
 	}
 	RETVAL_FALSE;
@@ -3754,10 +3918,10 @@
 	switch (pkey->type) {
 		case EVP_PKEY_RSA:
 		case EVP_PKEY_RSA2:
-			successful =  (RSA_private_encrypt(data_len, 
-						(unsigned char *)data, 
-						cryptedbuf, 
-						pkey->pkey.rsa, 
+			successful =  (RSA_private_encrypt(data_len,
+						(unsigned char *)data,
+						cryptedbuf,
+						pkey->pkey.rsa,
 						padding) == cryptedlen);
 			break;
 		default:
@@ -3774,7 +3938,7 @@
 	if (cryptedbuf) {
 		efree(cryptedbuf);
 	}
-	if (keyresource == -1) { 
+	if (keyresource == -1) {
 		EVP_PKEY_free(pkey);
 	}
 }
@@ -3812,10 +3976,10 @@
 	switch (pkey->type) {
 		case EVP_PKEY_RSA:
 		case EVP_PKEY_RSA2:
-			cryptedlen = RSA_private_decrypt(data_len, 
-					(unsigned char *)data, 
-					crypttemp, 
-					pkey->pkey.rsa, 
+			cryptedlen = RSA_private_decrypt(data_len,
+					(unsigned char *)data,
+					crypttemp,
+					pkey->pkey.rsa,
 					padding);
 			if (cryptedlen != -1) {
 				cryptedbuf = emalloc(cryptedlen + 1);
@@ -3840,7 +4004,7 @@
 	if (keyresource == -1) {
 		EVP_PKEY_free(pkey);
 	}
-	if (cryptedbuf) { 
+	if (cryptedbuf) {
 		efree(cryptedbuf);
 	}
 }
@@ -3864,7 +4028,7 @@
 		return;
 
 	RETVAL_FALSE;
-	
+
 	pkey = php_openssl_evp_from_zval(key, 1, NULL, 0, &keyresource TSRMLS_CC);
 	if (pkey == NULL) {
 		php_error_docref(NULL TSRMLS_CC, E_WARNING, "key parameter is not a valid public key");
@@ -3877,10 +4041,10 @@
 	switch (pkey->type) {
 		case EVP_PKEY_RSA:
 		case EVP_PKEY_RSA2:
-			successful = (RSA_public_encrypt(data_len, 
-						(unsigned char *)data, 
-						cryptedbuf, 
-						pkey->pkey.rsa, 
+			successful = (RSA_public_encrypt(data_len,
+						(unsigned char *)data,
+						cryptedbuf,
+						pkey->pkey.rsa,
 						padding) == cryptedlen);
 			break;
 		default:
@@ -3923,7 +4087,7 @@
 		return;
 	}
 	RETVAL_FALSE;
-	
+
 	pkey = php_openssl_evp_from_zval(key, 1, NULL, 0, &keyresource TSRMLS_CC);
 	if (pkey == NULL) {
 		php_error_docref(NULL TSRMLS_CC, E_WARNING, "key parameter is not a valid public key");
@@ -3936,10 +4100,10 @@
 	switch (pkey->type) {
 		case EVP_PKEY_RSA:
 		case EVP_PKEY_RSA2:
-			cryptedlen = RSA_public_decrypt(data_len, 
-					(unsigned char *)data, 
-					crypttemp, 
-					pkey->pkey.rsa, 
+			cryptedlen = RSA_public_decrypt(data_len,
+					(unsigned char *)data,
+					crypttemp,
+					pkey->pkey.rsa,
 					padding);
 			if (cryptedlen != -1) {
 				cryptedbuf = emalloc(cryptedlen + 1);
@@ -3947,10 +4111,10 @@
 				successful = 1;
 			}
 			break;
-			
+
 		default:
 			php_error_docref(NULL TSRMLS_CC, E_WARNING, "key type not supported in this PHP build!");
-		 
+
 	}
 
 	efree(crypttemp);
@@ -4068,7 +4232,7 @@
 	char * signature;	int signature_len;
 	zval *method = NULL;
 	long signature_algo = OPENSSL_ALGO_SHA1;
-	
+
 	if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "ssZ|z", &data, &data_len, &signature, &signature_len, &key, &method) == FAILURE) {
 		return;
 	}
@@ -4127,7 +4291,7 @@
 	if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "szza/|s", &data, &data_len, &sealdata, &ekeys, &pubkeys, &method, &method_len) == FAILURE) {
 		return;
 	}
-	
+
 	pubkeysht = HASH_OF(pubkeys);
 	nkeys = pubkeysht ? zend_hash_num_elements(pubkeysht) : 0;
 	if (!nkeys) {
@@ -4222,7 +4386,7 @@
 		if (key_resources[i] == -1) {
 			EVP_PKEY_free(pkeys[i]);
 		}
-		if (eks[i]) { 
+		if (eks[i]) {
 			efree(eks[i]);
 		}
 	}
@@ -4268,13 +4432,13 @@
 	} else {
 		cipher = EVP_rc4();
 	}
-	
+
 	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)) {
 			efree(buf);
-			if (keyresource == -1) { 
+			if (keyresource == -1) {
 				EVP_PKEY_free(pkey);
 			}
 			RETURN_FALSE;
@@ -4511,7 +4675,7 @@
 				if (SSL_CTX_use_PrivateKey_file(ctx, resolved_path_buff, SSL_FILETYPE_PEM) != 1) {
 					php_error_docref(NULL TSRMLS_CC, E_WARNING, "Unable to set private key file `%s'", resolved_path_buff);
 					return NULL;
-				}		
+				}
 			}
 
 			tmpssl = SSL_new(ctx);
@@ -4568,7 +4732,7 @@
 	}
 	array_init(return_value);
 	OBJ_NAME_do_all_sorted(OBJ_NAME_TYPE_MD_METH,
-		aliases ? openssl_add_method_or_alias: openssl_add_method, 
+		aliases ? openssl_add_method_or_alias: openssl_add_method,
 		return_value);
 }
 /* }}} */
@@ -4584,7 +4748,7 @@
 	}
 	array_init(return_value);
 	OBJ_NAME_do_all_sorted(OBJ_NAME_TYPE_CIPHER_METH,
-		aliases ? openssl_add_method_or_alias: openssl_add_method, 
+		aliases ? openssl_add_method_or_alias: openssl_add_method,
 		return_value);
 }
 /* }}} */
diff -Naur php-5.3.8/ext/openssl/php_openssl.h php-5.3.8-patched/ext/openssl/php_openssl.h
--- php-5.3.8/ext/openssl/php_openssl.h	2010-12-31 19:19:59.000000000 -0700
+++ php-5.3.8-patched/ext/openssl/php_openssl.h	2011-12-06 04:24:56.581276358 -0700
@@ -74,6 +74,10 @@
 PHP_FUNCTION(openssl_csr_sign);
 PHP_FUNCTION(openssl_csr_get_subject);
 PHP_FUNCTION(openssl_csr_get_public_key);
+
+PHP_FUNCTION(openssl_spki_new);
+PHP_FUNCTION(openssl_spki_verify);
+PHP_FUNCTION(openssl_spki_export);
 #else
 
 #define phpext_openssl_ptr NULL
 
PHP Copyright © 2001-2014 The PHP Group
All rights reserved.
Last updated: Thu Apr 17 01:01:56 2014 UTC