]> granicus.if.org Git - php/commitdiff
OpenSSL extension. So far it implements assymetric encryption functions.
authorStig Venaas <venaas@php.net>
Mon, 13 Nov 2000 19:47:20 +0000 (19:47 +0000)
committerStig Venaas <venaas@php.net>
Mon, 13 Nov 2000 19:47:20 +0000 (19:47 +0000)
ext/openssl/Makefile.in [new file with mode: 0644]
ext/openssl/config.m4 [new file with mode: 0644]
ext/openssl/openssl.c [new file with mode: 0644]
ext/openssl/php_openssl.h [new file with mode: 0644]

diff --git a/ext/openssl/Makefile.in b/ext/openssl/Makefile.in
new file mode 100644 (file)
index 0000000..306e6c6
--- /dev/null
@@ -0,0 +1,7 @@
+# $Id$
+
+LTLIBRARY_NAME        = libopenssl.la
+LTLIBRARY_SOURCES     = openssl.c
+LTLIBRARY_SHARED_NAME = openssl.la
+
+include $(top_srcdir)/build/dynlib.mk
diff --git a/ext/openssl/config.m4 b/ext/openssl/config.m4
new file mode 100644 (file)
index 0000000..cc84211
--- /dev/null
@@ -0,0 +1,7 @@
+dnl $Id$
+dnl config.m4 for extension OpenSSL
+
+if test "$OPENSSL_DIR"; then
+  PHP_EXTENSION(openssl, $ext_shared)
+  AC_DEFINE(HAVE_OPENSSL_EXT,1,[ ])
+fi
diff --git a/ext/openssl/openssl.c b/ext/openssl/openssl.c
new file mode 100644 (file)
index 0000000..c4ca7d4
--- /dev/null
@@ -0,0 +1,496 @@
+/*
+   +----------------------------------------------------------------------+
+   | PHP version 4.0                                                      |
+   +----------------------------------------------------------------------+
+   | Copyright (c) 1997, 1998, 1999, 2000 The PHP Group                   |
+   +----------------------------------------------------------------------+
+   | This source file is subject to version 2.02 of the PHP license,      |
+   | that is bundled with this package in the file LICENSE, and is        |
+   | available at through the world-wide-web at                           |
+   | http://www.php.net/license/2_02.txt.                                 |
+   | If you did not receive a copy of the PHP license and are unable to   |
+   | obtain it through the world-wide-web, please send a note to          |
+   | license@php.net so we can mail you a copy immediately.               |
+   +----------------------------------------------------------------------+
+   | Authors: Stig Venaas <venaas@php.net>                                |
+   +----------------------------------------------------------------------+
+ */
+/* $Id$ */
+
+#include "php.h"
+#include "php_openssl.h"
+
+/* PHP Includes */
+#include "ext/standard/file.h"
+#include "ext/standard/info.h"
+
+/* OpenSSL includes */
+#include <openssl/evp.h>
+#include <openssl/x509.h>
+
+static unsigned char second_argument_force_ref[] = { 3, BYREF_NONE, BYREF_FORCE, BYREF_NONE };
+static unsigned char second_to_fourth_argument_force_ref[] = { 5, BYREF_NONE, BYREF_FORCE, BYREF_FORCE, BYREF_FORCE, BYREF_NONE };
+
+function_entry openssl_functions[] = {
+       PHP_FE(openssl_read_privatekey,    NULL)
+       PHP_FE(openssl_read_publickey,     NULL)
+       PHP_FE(openssl_free_key,           NULL)
+       PHP_FE(openssl_read_x509,          NULL)
+       PHP_FE(openssl_free_x509,          NULL)
+       PHP_FE(openssl_sign,               second_argument_force_ref)
+       PHP_FE(openssl_verify,             NULL)
+       PHP_FE(openssl_seal,               second_to_fourth_argument_force_ref)
+       PHP_FE(openssl_open,               second_argument_force_ref)
+       {NULL, NULL, NULL}
+};
+
+zend_module_entry openssl_module_entry = {
+       "openssl",
+       openssl_functions,
+       PHP_MINIT(openssl),
+       NULL,
+       NULL,   
+       NULL,
+       PHP_MINFO(openssl),
+       STANDARD_MODULE_PROPERTIES
+};
+
+#ifdef COMPILE_DL_OPENSSL
+ZEND_GET_MODULE(openssl)
+#endif
+
+static void _php_pkey_free(zend_rsrc_list_entry *rsrc);
+static void _php_x509_free(zend_rsrc_list_entry *rsrc);
+
+static int le_key, le_x509;
+
+PHP_MINIT_FUNCTION(openssl)
+{
+       le_key = zend_register_list_destructors_ex(_php_pkey_free, NULL,
+                                                  "OpenSSL key",
+                                                  module_number);
+       le_x509 = zend_register_list_destructors_ex(_php_x509_free, NULL,
+                                                   "OpenSSL X.509",
+                                                   module_number);
+       return SUCCESS;
+}
+
+PHP_MINFO_FUNCTION(openssl)
+{
+       php_info_print_table_start();
+       php_info_print_table_row(2, "OpenSSL support", "enabled");
+       php_info_print_table_row(2, "OpenSSL Version", OPENSSL_VERSION_TEXT);
+       php_info_print_table_end();
+}
+
+/* {{{ proto int openssl_read_privatekey(int fp)
+   Read private key */
+PHP_FUNCTION(openssl_read_privatekey)
+{
+       zval **file;
+       EVP_PKEY *pkey;
+       FILE *fp;
+       
+       if (ZEND_NUM_ARGS() != 1 ||
+           zend_get_parameters_ex(1, &file) == FAILURE) {
+               WRONG_PARAM_COUNT;
+       }
+       
+       ZEND_FETCH_RESOURCE(fp, FILE *, file, -1, "File-Handle", php_file_le_fopen());
+       
+       pkey = (EVP_PKEY *) PEM_read_PrivateKey(fp, NULL, NULL, NULL);
+       if (pkey == NULL) { 
+               RETURN_FALSE;
+       }
+
+       ZEND_REGISTER_RESOURCE(return_value, pkey, le_key);
+}
+/* }}} */
+
+/* {{{ proto int openssl_read_publickey(int x509)
+   Read public key */
+PHP_FUNCTION(openssl_read_publickey)
+{
+       zval **x509;
+       X509 *cert;
+       EVP_PKEY *pkey;
+
+       if (ZEND_NUM_ARGS() != 1 ||
+           zend_get_parameters_ex(1, &x509) == FAILURE) {
+               WRONG_PARAM_COUNT;
+       }
+       ZEND_FETCH_RESOURCE(cert, X509 *, x509, -1, "OpenSSL X.509", le_x509);
+
+       pkey = (EVP_PKEY *) X509_get_pubkey(cert);
+       if (pkey == NULL) { 
+               RETURN_FALSE;
+       }
+
+       ZEND_REGISTER_RESOURCE(return_value, pkey, le_key);
+}
+/* }}} */
+
+/* {{{ proto void openssl_free_key(int key)
+   Free key */
+PHP_FUNCTION(openssl_free_key)
+{
+       zval **key;
+       EVP_PKEY *pkey;
+
+       if (ZEND_NUM_ARGS() != 1 ||
+           zend_get_parameters_ex(1, &key) == FAILURE) {
+               WRONG_PARAM_COUNT;
+       }
+       
+       ZEND_FETCH_RESOURCE(pkey, EVP_PKEY *, key, -1, "OpenSSL key", le_key);
+       zend_list_delete((*key)->value.lval);
+}
+/* }}} */
+
+/* {{{ proto int openssl_read_x509(int fp)
+   Read X.509 certificate */
+PHP_FUNCTION(openssl_read_x509)
+{
+       zval **file;
+       X509 *x509;
+       FILE *fp;
+
+       if (ZEND_NUM_ARGS() != 1 ||
+           zend_get_parameters_ex(1, &file) == FAILURE) {
+               WRONG_PARAM_COUNT;
+       }
+
+       ZEND_FETCH_RESOURCE(fp, FILE *, file, -1, "File-Handle",
+                           php_file_le_fopen());
+
+       x509 = (X509 *) PEM_read_X509(fp, NULL, NULL, NULL);
+       if (x509 == NULL) { 
+               RETURN_FALSE;
+       }
+       
+       ZEND_REGISTER_RESOURCE(return_value, x509, le_x509);
+}
+/* }}} */
+
+/* {{{ proto void openssl_free_x509(int x509)
+   Free X.509 certificate */
+PHP_FUNCTION(openssl_free_x509)
+{
+       zval **x509;
+       X509 *cert;
+
+       if (ZEND_NUM_ARGS() != 1 ||
+           zend_get_parameters_ex(1, &x509) == FAILURE) {
+               WRONG_PARAM_COUNT;
+       }
+       ZEND_FETCH_RESOURCE(cert, X509 *, x509, -1, "OpenSSL X.509", le_x509);
+
+       zend_list_delete((*x509)->value.lval);
+}
+/* }}} */
+
+/* {{{ proto bool openssl_sign(string data, string signature, int key)
+   Sign data */
+PHP_FUNCTION(openssl_sign)
+{
+       zval **key, **data, **signature;
+       EVP_PKEY *pkey;
+       int siglen;
+       unsigned char *sigbuf;
+       EVP_MD_CTX md_ctx;
+
+       if (ZEND_NUM_ARGS() != 3 ||
+           zend_get_parameters_ex(3, &data, &signature, &key) == FAILURE) {
+               WRONG_PARAM_COUNT;
+       }
+       convert_to_string_ex(data);
+       
+       ZEND_FETCH_RESOURCE(pkey, EVP_PKEY *, key, -1, "OpenSSL key", le_key);
+       siglen = EVP_PKEY_size(pkey);
+       sigbuf = emalloc(siglen + 1);
+       if (sigbuf == NULL) {
+               RETURN_FALSE;
+       }
+
+       EVP_SignInit(&md_ctx, EVP_sha1());
+       EVP_SignUpdate(&md_ctx, (*data)->value.str.val,
+                      (*data)->value.str.len);
+       if (EVP_SignFinal (&md_ctx, sigbuf, &siglen, pkey)) {
+               zval_dtor(*signature);
+               sigbuf[siglen] = '\0';
+               ZVAL_STRINGL(*signature, sigbuf, siglen, 0);
+               RETURN_TRUE;
+       } else {
+               RETURN_FALSE;
+               efree(sigbuf);
+       }
+}
+/* }}} */
+
+/* {{{ proto int openssl_verify(string data, string signature, int key)
+   Verify data */
+PHP_FUNCTION(openssl_verify)
+{
+       zval **key, **data, **signature;
+       EVP_PKEY *pkey;
+       int err;
+       EVP_MD_CTX     md_ctx;
+
+       if (ZEND_NUM_ARGS() != 3 ||
+        zend_get_parameters_ex(3, &data, &signature, &key) == FAILURE) {
+               WRONG_PARAM_COUNT;
+       }
+       convert_to_string_ex(data);
+       convert_to_string_ex(signature);
+
+       ZEND_FETCH_RESOURCE(pkey, EVP_PKEY *, key, -1, "OpenSSL key", le_key);
+
+       EVP_VerifyInit   (&md_ctx, EVP_sha1());
+       EVP_VerifyUpdate (&md_ctx, (*data)->value.str.val,
+                         (*data)->value.str.len);
+       err = EVP_VerifyFinal (&md_ctx, (*signature)->value.str.val,
+                              (*signature)->value.str.len, pkey);
+       RETURN_LONG(err);
+}
+/* }}} */
+
+/* {{{ proto int openssl_seal(string data, string sealdata, array ekeys,
+                              string ivec, array pubkeys)
+   Seal data */
+PHP_FUNCTION(openssl_seal)
+{
+       zval **pubkeys, **pubkey, **data, **sealdata, **ekeys, **ivec;
+       HashTable *pubkeysht;
+        HashPosition pos;
+       EVP_PKEY **pkeys;
+       int i, len1, len2, *eksl, ivlen, nkeys;
+       unsigned char *buf, **eks, *iv;
+
+       EVP_CIPHER_CTX ctx;
+
+       if (ZEND_NUM_ARGS() != 5 ||
+               zend_get_parameters_ex(5, &data, &sealdata, &ekeys, &ivec,
+                                      &pubkeys) == FAILURE) {
+               WRONG_PARAM_COUNT;
+       }
+
+       SEPARATE_ZVAL(pubkeys);
+        pubkeysht = HASH_OF(*pubkeys);
+       nkeys = pubkeysht ? zend_hash_num_elements(pubkeysht) : 0;
+       if (!nkeys) {
+                php_error(E_WARNING,
+                "Fifth argument to openssl_seal() must be a non-empty array");
+                RETURN_FALSE;
+       }
+
+       pkeys = emalloc(nkeys * sizeof(*pkeys));
+       if (pkeys == NULL) {
+               RETURN_FALSE;
+       }
+       eksl = emalloc(nkeys * sizeof(*eksl));
+       if (eksl == NULL) {
+               efree(pkeys);
+               RETURN_FALSE;
+       }
+       eks = emalloc(nkeys * sizeof(*eks));
+       if (eks == NULL) {
+               efree(eksl);
+               efree(pkeys);
+               RETURN_FALSE;
+       }
+       
+       convert_to_string_ex(data);
+
+        zend_hash_internal_pointer_reset_ex(pubkeysht, &pos);
+       i = 0;
+        while (zend_hash_get_current_data_ex(pubkeysht, (void **) &pubkey,
+                                            &pos) == SUCCESS) {
+               ZEND_FETCH_RESOURCE(pkeys[i], EVP_PKEY *, pubkey, -1,
+                                   "OpenSSL key", le_key);
+               eks[i] = emalloc(EVP_PKEY_size(pkeys[i]) + 1);
+               if (eks[i] == NULL) {
+                       while (i--) {
+                               efree(eks[i]);
+                       }
+                       efree(eks);
+                       efree(eksl);
+                       efree(pkeys);
+                       RETURN_FALSE;
+               }
+                zend_hash_move_forward_ex(pubkeysht, &pos);
+               i++;
+       }
+
+       if (!EVP_EncryptInit(&ctx,EVP_rc4(),NULL,NULL)) {
+               for (i=0; i<nkeys; i++) {
+                       efree(eks[i]);
+               }
+               efree(eks);
+               efree(eksl);
+               efree(pkeys);
+               RETURN_FALSE;
+       }
+
+       ivlen = EVP_CIPHER_CTX_iv_length(&ctx);
+       if (ivlen) {
+               iv = emalloc(ivlen + 1);
+               if (iv == NULL) {
+                       for (i=0; i<nkeys; i++) {
+                               efree(eks[i]);
+                       }
+                       efree(eks);
+                       efree(eksl);
+                       efree(pkeys);
+                       RETURN_FALSE;
+               }
+       } else {
+               iv = NULL;
+       }
+       /* allocate one byte extra to make room for \0 */
+       buf = emalloc((*data)->value.str.len + EVP_CIPHER_CTX_block_size(&ctx));
+       if (buf == NULL) {
+               efree(iv);
+               for (i=0; i<nkeys; i++) {
+                       efree(eks[i]);
+               }
+               efree(eks);
+               efree(eksl);
+               efree(pkeys);
+               RETURN_FALSE;
+       }
+
+       if (!EVP_SealInit(&ctx, EVP_rc4(), eks, eksl, iv, pkeys, nkeys) ||
+           !EVP_SealUpdate(&ctx, buf, &len1, (*data)->value.str.val,
+                           (*data)->value.str.len)) {
+               efree(buf);
+               efree(iv);
+               for (i=0; i<nkeys; i++) {
+                       efree(eks[i]);
+               }
+               efree(eks);
+               efree(eksl);
+               efree(pkeys);
+               RETURN_FALSE;
+       }
+
+       EVP_SealFinal(&ctx, buf + len1, &len2);
+
+       efree(pkeys);
+
+       if (len1 + len2 > 0) {
+               zval_dtor(*sealdata);
+               buf[len1 + len2] = '\0';
+               ZVAL_STRINGL(*sealdata, erealloc(buf, len1 + len2 + 1),
+                            len1 + len2, 0);
+
+               zval_dtor(*ekeys);
+               if (array_init(*ekeys) == FAILURE) {
+                       php_error(E_ERROR, "Cannot initialize return value");
+                       efree(iv);
+                       for (i=0; i<nkeys; i++) {
+                               efree(eks[i]);
+                       }
+                       efree(eks);
+                       efree(eksl);
+                       RETURN_FALSE;
+               }
+               for (i=0; i<nkeys; i++) {
+                       eks[i][eksl[i]] = '\0';
+                       add_next_index_stringl(*ekeys,
+                                              erealloc(eks[i], eksl[i] + 1),
+                                              eksl[i], 0);
+               }
+               efree(eks);
+               efree(eksl);
+
+               zval_dtor(*ivec);
+               if (ivlen) {
+                       iv[ivlen] = '\0';
+                       ZVAL_STRINGL(*ivec, erealloc(iv, ivlen + 1), ivlen, 0);
+               } else {
+                       ZVAL_EMPTY_STRING(*ivec);
+               }
+       } else {
+               efree(buf);
+               efree(iv);
+               for (i=0; i<nkeys; i++) {
+                       efree(eks[i]);
+               }
+               efree(eks);
+               efree(eksl);
+       }
+       
+       RETURN_LONG(len1 + len2);
+}
+/* }}} */
+
+/* {{{ proto bool openssl_open(string data, string opendata, string ekey,
+                              string ivec, int privkey)
+   Open data */
+PHP_FUNCTION(openssl_open)
+{
+       zval **privkey, **data, **opendata, **ekey, **ivec;
+       EVP_PKEY *pkey;
+       int len1, len2, ekl, ivlen;
+       unsigned char *buf, *ek, *iv;
+
+       EVP_CIPHER_CTX ctx;
+
+       if (ZEND_NUM_ARGS() != 5 ||
+           zend_get_parameters_ex(5, &data, &opendata, &ekey, &ivec,
+                                  &privkey) == FAILURE) {
+               WRONG_PARAM_COUNT;
+       }
+       convert_to_string_ex(data);
+       convert_to_string_ex(ekey);
+       convert_to_string_ex(ivec);
+       
+       ZEND_FETCH_RESOURCE(pkey, EVP_PKEY *, privkey, -1, "OpenSSL key",
+                           le_key);
+
+       buf = emalloc((*data)->value.str.len + 1);
+       if (buf == NULL) {
+               RETURN_FALSE;
+       }
+
+       if (!EVP_OpenInit(&ctx, EVP_rc4(), (*ekey)->value.str.val,
+                         (*ekey)->value.str.len, (*ivec)->value.str.val,
+                         pkey) ||
+           !EVP_OpenUpdate(&ctx, buf, &len1, (*data)->value.str.val,
+                           (*data)->value.str.len) ||
+           !EVP_OpenFinal(&ctx, buf + len1, &len2) ||
+           (len1 + len2 == 0)) {
+               efree(buf);
+               RETURN_FALSE;
+       }
+
+       zval_dtor(*opendata);
+       buf[len1 + len2] = '\0';
+       ZVAL_STRINGL(*opendata, erealloc(buf, len1 + len2 + 1), len1 + len2, 0);
+       RETURN_TRUE;
+}
+/* }}} */
+
+/* {{{ _php_pkey_free() */
+static void _php_pkey_free(zend_rsrc_list_entry *rsrc)
+{
+       EVP_PKEY *pkey = (EVP_PKEY *)rsrc->ptr;
+       EVP_PKEY_free(pkey);
+}
+/* }}} */
+
+/* {{{ _php_x509_free() */
+static void _php_x509_free(zend_rsrc_list_entry *rsrc)
+{
+       X509 *x509 = (X509 *)rsrc->ptr;
+       X509_free(x509);
+}
+/* }}} */
+
+/*
+ * Local variables:
+ * tab-width: 8
+ * c-basic-offset: 8
+ * End:
+ */
diff --git a/ext/openssl/php_openssl.h b/ext/openssl/php_openssl.h
new file mode 100644 (file)
index 0000000..5512c24
--- /dev/null
@@ -0,0 +1,53 @@
+/*
+   +----------------------------------------------------------------------+
+   | PHP version 4.0                                                      |
+   +----------------------------------------------------------------------+
+   | Copyright (c) 1997, 1998, 1999, 2000 The PHP Group                   |
+   +----------------------------------------------------------------------+
+   | This source file is subject to version 2.02 of the PHP license,      |
+   | that is bundled with this package in the file LICENSE, and is        |
+   | available at through the world-wide-web at                           |
+   | http://www.php.net/license/2_02.txt.                                 |
+   | If you did not receive a copy of the PHP license and are unable to   |
+   | obtain it through the world-wide-web, please send a note to          |
+   | license@php.net so we can mail you a copy immediately.               |
+   +----------------------------------------------------------------------+
+   | Authors: Stig Venaas <venaas@php.net>                                |
+   +----------------------------------------------------------------------+
+ */
+
+/* $Id$ */
+
+#ifndef PHP_OPENSSL_H
+#define PHP_OPENSSL_H
+/* HAVE_OPENSSL would include SSL MySQL stuff */
+#if HAVE_OPENSSL_EXT
+extern zend_module_entry openssl_module_entry;
+#define phpext_openssl_ptr &openssl_module_entry
+
+PHP_MINIT_FUNCTION(openssl);
+PHP_MINFO_FUNCTION(openssl);
+PHP_FUNCTION(openssl_read_privatekey);
+PHP_FUNCTION(openssl_read_publickey);
+PHP_FUNCTION(openssl_free_key);
+PHP_FUNCTION(openssl_read_x509);
+PHP_FUNCTION(openssl_free_x509);
+PHP_FUNCTION(openssl_sign);
+PHP_FUNCTION(openssl_verify);
+PHP_FUNCTION(openssl_seal);
+PHP_FUNCTION(openssl_open);
+
+#else
+
+#define phpext_extname_ptr NULL
+
+#endif
+
+#endif
+
+/*
+ * Local variables:
+ * tab-width: 4
+ * c-basic-offset: 4
+ * End:
+ */