cellog Fri Jun 13 06:34:41 2008 UTC
Modified files: (Branch: PHP_5_3)
/php-src/ext/phar phar.c phar.phar phar_internal.h util.c
Log:
partial refactor - move signature verification into its own function, in
preparation for tar/zip signature support.
next is signature creation
http://cvs.php.net/viewvc.cgi/php-src/ext/phar/phar.c?r1=1.370.2.12&r2=1.370.2.13&diff_format=u
Index: php-src/ext/phar/phar.c
diff -u php-src/ext/phar/phar.c:1.370.2.12 php-src/ext/phar/phar.c:1.370.2.13
--- php-src/ext/phar/phar.c:1.370.2.12 Thu Jun 12 18:56:23 2008
+++ php-src/ext/phar/phar.c Fri Jun 13 06:34:41 2008
@@ -17,7 +17,7 @@
+----------------------------------------------------------------------+
*/
-/* $Id: phar.c,v 1.370.2.12 2008/06/12 18:56:23 cellog Exp $ */
+/* $Id: phar.c,v 1.370.2.13 2008/06/13 06:34:41 cellog Exp $ */
#define PHAR_MAIN 1
#include "phar_internal.h"
@@ -726,8 +726,6 @@
/* The lowest nibble contains the phar wide flags. The compression
flags can */
/* be ignored on reading because it is being generated anyways. */
if (manifest_flags & PHAR_HDR_SIGNATURE) {
- unsigned char buf[1024];
- int read_size, len;
char sig_buf[8], *sig_ptr = sig_buf;
off_t read_len;
size_t end_of_phar;
@@ -746,27 +744,10 @@
PHAR_GET_32(sig_ptr, sig_flags);
switch(sig_flags) {
case PHAR_SIG_OPENSSL: {
-#ifdef PHAR_HAVE_OPENSSL
- BIO *in;
- EVP_PKEY *key;
- EVP_MD *mdtype = (EVP_MD *) EVP_sha1();
- EVP_MD_CTX md_ctx;
-#else
- int tempsig;
-#endif
- php_uint32 signature_len, pubkey_len;
- char *sig, *pubkey = NULL, *pfile;
+ php_uint32 signature_len;
+ char *sig;
off_t whence;
- php_stream *pfp;
- if (!zend_hash_exists(&module_registry, "openssl",
sizeof("openssl"))) {
- efree(savebuf);
- php_stream_close(fp);
- if (error) {
- spprintf(error, 0, "phar \"%s\" openssl
signature cannot be verified, openssl not loaded", fname);
- }
- return FAILURE;
- }
/* we store the signature followed by the signature
length */
if (-1 == php_stream_seek(fp, -12, SEEK_CUR)
|| 4 != php_stream_read(fp, sig_buf, 4)) {
@@ -781,7 +762,7 @@
sig_ptr = sig_buf;
PHAR_GET_32(sig_ptr, signature_len);
- sig = (char *)emalloc(signature_len);
+ sig = (char *) emalloc(signature_len);
whence = signature_len + 4;
whence = -whence;
@@ -796,125 +777,54 @@
}
return FAILURE;
}
-
- /* use __FILE__ . '.pubkey' for public key file */
- spprintf(&pfile, 0, "%s.pubkey", fname);
- pfp = php_stream_open_wrapper(pfile, "rb", 0, NULL);
- efree(pfile);
- if (!pfp || !(pubkey_len = php_stream_copy_to_mem(pfp,
&pubkey, PHP_STREAM_COPY_ALL, 0)) || !pubkey) {
- efree(savebuf);
- efree(sig);
- if (pubkey) {
- efree(pubkey);
- }
- php_stream_close(fp);
- if (error) {
- spprintf(error, 0, "phar \"%s\" openssl
public key could not be read", fname);
- }
- return FAILURE;
- }
- php_stream_close(pfp);
-#ifndef PHAR_HAVE_OPENSSL
- tempsig = signature_len;
- if (FAILURE == phar_call_openssl_signverify(0, fp,
end_of_phar, pubkey, pubkey_len, &sig, &tempsig TSRMLS_CC)) {
- efree(savebuf);
- efree(sig);
- if (pubkey) {
- efree(pubkey);
- }
- php_stream_close(fp);
- if (error) {
- spprintf(error, 0, "phar \"%s\" openssl
signature could not be verified", fname);
- }
- return FAILURE;
- }
- if (pubkey) {
- efree(pubkey);
- }
- signature_len = tempsig;
-#else
- in = BIO_new_mem_buf(pubkey, pubkey_len);
- if (NULL == in) {
+ if (FAILURE == phar_verify_signature(fp, end_of_phar,
PHAR_SIG_OPENSSL, sig, signature_len, fname, &signature, &sig_len, error
TSRMLS_CC)) {
efree(savebuf);
efree(sig);
- efree(pubkey);
php_stream_close(fp);
if (error) {
- spprintf(error, 0, "phar \"%s\" openssl
signature could not be processed", fname);
+ char *save = *error;
+ spprintf(error, 0, "phar \"%s\" openssl
signature could not be verified: %s", fname, *error);
+ efree(save);
}
return FAILURE;
}
- key = PEM_read_bio_PUBKEY(in, NULL,NULL, NULL);
- BIO_free(in);
- efree(pubkey);
- if (NULL == key) {
+ efree(sig);
+ }
+ break;
+#if HAVE_HASH_EXT
+ case PHAR_SIG_SHA512: {
+ unsigned char digest[64];
+
+ php_stream_seek(fp, -(8 + 64), SEEK_END);
+ read_len = php_stream_tell(fp);
+ if (php_stream_read(fp, (char*)digest, sizeof(digest))
!= sizeof(digest)) {
efree(savebuf);
- efree(sig);
php_stream_close(fp);
if (error) {
- spprintf(error, 0, "phar \"%s\" openssl
signature could not be processed", fname);
+ spprintf(error, 0, "phar \"%s\" has a
broken signature", fname);
}
return FAILURE;
}
- EVP_VerifyInit(&md_ctx, mdtype);
-
- read_len -= signature_len + 4;
- if (read_len > sizeof(buf)) {
- read_size = sizeof(buf);
- } else {
- read_size = (int)read_len;
- }
- php_stream_seek(fp, 0, SEEK_SET);
- while (read_size && (len = php_stream_read(fp,
(char*)buf, read_size)) > 0) {
- EVP_VerifyUpdate (&md_ctx, buf, len);
- read_len -= (off_t)len;
- if (read_len < read_size) {
- read_size = (int)read_len;
- }
- }
- if (!EVP_VerifyFinal (&md_ctx, (unsigned char *)sig,
signature_len, key)) {
- EVP_MD_CTX_cleanup(&md_ctx);
- efree(sig);
+ if (FAILURE == phar_verify_signature(fp, read_len,
PHAR_SIG_SHA512, (char *)digest, 64, fname, &signature, &sig_len, error
TSRMLS_CC)) {
efree(savebuf);
php_stream_close(fp);
if (error) {
- spprintf(error, 0, "phar \"%s\" has a
broken signature", fname);
+ char *save = *error;
+ spprintf(error, 0, "phar \"%s\" SHA512
signature could not be verified: %s", fname, *error);
+ efree(save);
}
return FAILURE;
}
- EVP_MD_CTX_cleanup(&md_ctx);
-#endif
-
- sig_len = phar_hex_str((const char*)sig, signature_len,
&signature);
- efree(sig);
+ break;
}
- break;
-#if HAVE_HASH_EXT
- case PHAR_SIG_SHA512: {
- unsigned char digest[64], saved[64];
- PHP_SHA512_CTX context;
+ case PHAR_SIG_SHA256: {
+ unsigned char digest[32];
- php_stream_rewind(fp);
- PHP_SHA512Init(&context);
- read_len -= sizeof(digest);
- if (read_len > sizeof(buf)) {
- read_size = sizeof(buf);
- } else {
- read_size = (int)read_len;
- }
- while ((len = php_stream_read(fp, (char*)buf,
read_size)) > 0) {
- PHP_SHA512Update(&context, buf, len);
- read_len -= (off_t)len;
- if (read_len < read_size) {
- read_size = (int)read_len;
- }
- }
- PHP_SHA512Final(digest, &context);
+ php_stream_seek(fp, -(8 + 32), SEEK_END);
+ read_len = php_stream_tell(fp);
- if (read_len > 0
- || php_stream_read(fp, (char*)saved, sizeof(saved)) !=
sizeof(saved)
- || memcmp(digest, saved, sizeof(digest))) {
+ if (php_stream_read(fp, (char*)digest, sizeof(digest))
!= sizeof(digest)) {
efree(savebuf);
php_stream_close(fp);
if (error) {
@@ -923,42 +833,16 @@
return FAILURE;
}
- sig_len = phar_hex_str((const char*)digest,
sizeof(digest), &signature);
- break;
- }
- case PHAR_SIG_SHA256: {
- unsigned char digest[32], saved[32];
- PHP_SHA256_CTX context;
-
- php_stream_rewind(fp);
- PHP_SHA256Init(&context);
- read_len -= sizeof(digest);
- if (read_len > sizeof(buf)) {
- read_size = sizeof(buf);
- } else {
- read_size = (int)read_len;
- }
- while ((len = php_stream_read(fp, (char*)buf,
read_size)) > 0) {
- PHP_SHA256Update(&context, buf, len);
- read_len -= (off_t)len;
- if (read_len < read_size) {
- read_size = (int)read_len;
- }
- }
- PHP_SHA256Final(digest, &context);
-
- if (read_len > 0
- || php_stream_read(fp, (char*)saved, sizeof(saved)) !=
sizeof(saved)
- || memcmp(digest, saved, sizeof(digest))) {
+ if (FAILURE == phar_verify_signature(fp, read_len,
PHAR_SIG_SHA256, (char *)digest, 32, fname, &signature, &sig_len, error
TSRMLS_CC)) {
efree(savebuf);
php_stream_close(fp);
if (error) {
- spprintf(error, 0, "phar \"%s\" has a
broken signature", fname);
+ char *save = *error;
+ spprintf(error, 0, "phar \"%s\" SHA256
signature could not be verified: %s", fname, *error);
+ efree(save);
}
return FAILURE;
}
-
- sig_len = phar_hex_str((const char*)digest,
sizeof(digest), &signature);
break;
}
#else
@@ -972,29 +856,12 @@
return FAILURE;
#endif
case PHAR_SIG_SHA1: {
- unsigned char digest[20], saved[20];
- PHP_SHA1_CTX context;
+ unsigned char digest[20];
- php_stream_rewind(fp);
- PHP_SHA1Init(&context);
- read_len -= sizeof(digest);
- if (read_len > sizeof(buf)) {
- read_size = sizeof(buf);
- } else {
- read_size = (int)read_len;
- }
- while ((len = php_stream_read(fp, (char*)buf,
read_size)) > 0) {
- PHP_SHA1Update(&context, buf, len);
- read_len -= (off_t)len;
- if (read_len < read_size) {
- read_size = (int)read_len;
- }
- }
- PHP_SHA1Final(digest, &context);
+ php_stream_seek(fp, -(8 + 20), SEEK_END);
+ read_len = php_stream_tell(fp);
- if (read_len > 0
- || php_stream_read(fp, (char*)saved, sizeof(saved)) !=
sizeof(saved)
- || memcmp(digest, saved, sizeof(digest))) {
+ if (php_stream_read(fp, (char*)digest, sizeof(digest))
!= sizeof(digest)) {
efree(savebuf);
php_stream_close(fp);
if (error) {
@@ -1003,33 +870,25 @@
return FAILURE;
}
- sig_len = phar_hex_str((const char*)digest,
sizeof(digest), &signature);
+ if (FAILURE == phar_verify_signature(fp, read_len,
PHAR_SIG_SHA1, (char *)digest, 20, fname, &signature, &sig_len, error
TSRMLS_CC)) {
+ efree(savebuf);
+ php_stream_close(fp);
+ if (error) {
+ char *save = *error;
+ spprintf(error, 0, "phar \"%s\" SHA1
signature could not be verified: %s", fname, *error);
+ efree(save);
+ }
+ return FAILURE;
+ }
break;
}
case PHAR_SIG_MD5: {
- unsigned char digest[16], saved[16];
- PHP_MD5_CTX context;
+ unsigned char digest[16];
- php_stream_rewind(fp);
- PHP_MD5Init(&context);
- read_len -= sizeof(digest);
- if (read_len > sizeof(buf)) {
- read_size = sizeof(buf);
- } else {
- read_size = (int)read_len;
- }
- while ((len = php_stream_read(fp, (char*)buf,
read_size)) > 0) {
- PHP_MD5Update(&context, buf, len);
- read_len -= (off_t)len;
- if (read_len < read_size) {
- read_size = (int)read_len;
- }
- }
- PHP_MD5Final(digest, &context);
+ php_stream_seek(fp, -(8 + 16), SEEK_END);
+ read_len = php_stream_tell(fp);
- if (read_len > 0
- || php_stream_read(fp, (char*)saved, sizeof(saved)) !=
sizeof(saved)
- || memcmp(digest, saved, sizeof(digest))) {
+ if (php_stream_read(fp, (char*)digest, sizeof(digest))
!= sizeof(digest)) {
efree(savebuf);
php_stream_close(fp);
if (error) {
@@ -1038,7 +897,16 @@
return FAILURE;
}
- sig_len = phar_hex_str((const char*)digest,
sizeof(digest), &signature);
+ if (FAILURE == phar_verify_signature(fp, read_len,
PHAR_SIG_MD5, (char *)digest, 16, fname, &signature, &sig_len, error
TSRMLS_CC)) {
+ efree(savebuf);
+ php_stream_close(fp);
+ if (error) {
+ char *save = *error;
+ spprintf(error, 0, "phar \"%s\" MD5
signature could not be verified: %s", fname, *error);
+ efree(save);
+ }
+ return FAILURE;
+ }
break;
}
default:
@@ -3665,7 +3533,7 @@
php_info_print_table_header(2, "Phar: PHP Archive support", "enabled");
php_info_print_table_row(2, "Phar EXT version", PHP_PHAR_VERSION);
php_info_print_table_row(2, "Phar API version", PHP_PHAR_API_VERSION);
- php_info_print_table_row(2, "CVS revision", "$Revision: 1.370.2.12 $");
+ php_info_print_table_row(2, "CVS revision", "$Revision: 1.370.2.13 $");
php_info_print_table_row(2, "Phar-based phar archives", "enabled");
php_info_print_table_row(2, "Tar-based phar archives", "enabled");
php_info_print_table_row(2, "ZIP-based phar archives", "enabled");
http://cvs.php.net/viewvc.cgi/php-src/ext/phar/phar.phar?r1=1.7.2.11&r2=1.7.2.12&diff_format=u
Index: php-src/ext/phar/phar.phar
http://cvs.php.net/viewvc.cgi/php-src/ext/phar/phar_internal.h?r1=1.109.2.7&r2=1.109.2.8&diff_format=u
Index: php-src/ext/phar/phar_internal.h
diff -u php-src/ext/phar/phar_internal.h:1.109.2.7
php-src/ext/phar/phar_internal.h:1.109.2.8
--- php-src/ext/phar/phar_internal.h:1.109.2.7 Thu Jun 12 18:56:23 2008
+++ php-src/ext/phar/phar_internal.h Fri Jun 13 06:34:41 2008
@@ -17,7 +17,7 @@
+----------------------------------------------------------------------+
*/
-/* $Id: phar_internal.h,v 1.109.2.7 2008/06/12 18:56:23 cellog Exp $ */
+/* $Id: phar_internal.h,v 1.109.2.8 2008/06/13 06:34:41 cellog Exp $ */
#ifdef HAVE_CONFIG_H
#include "config.h"
@@ -416,6 +416,7 @@
int phar_free_alias(phar_archive_data *phar, char *alias, int alias_len
TSRMLS_DC);
int phar_get_archive(phar_archive_data **archive, char *fname, int fname_len,
char *alias, int alias_len, char **error TSRMLS_DC);
int phar_open_parsed_phar(char *fname, int fname_len, char *alias, int
alias_len, int is_data, int options, phar_archive_data** pphar, char **error
TSRMLS_DC);
+int phar_verify_signature(php_stream *fp, size_t end_of_phar, int sig_type,
char *sig, int sig_len, char *fname, char **signature, int *signature_len, char
**error TSRMLS_DC);
/* utility functions */
char *phar_create_default_stub(const char *index_php, const char *web_index,
size_t *len, char **error TSRMLS_DC);
http://cvs.php.net/viewvc.cgi/php-src/ext/phar/util.c?r1=1.55.2.4&r2=1.55.2.5&diff_format=u
Index: php-src/ext/phar/util.c
diff -u php-src/ext/phar/util.c:1.55.2.4 php-src/ext/phar/util.c:1.55.2.5
--- php-src/ext/phar/util.c:1.55.2.4 Tue Jun 10 17:58:09 2008
+++ php-src/ext/phar/util.c Fri Jun 13 06:34:41 2008
@@ -18,9 +18,27 @@
+----------------------------------------------------------------------+
*/
-/* $Id: util.c,v 1.55.2.4 2008/06/10 17:58:09 cellog Exp $ */
+/* $Id: util.c,v 1.55.2.5 2008/06/13 06:34:41 cellog Exp $ */
#include "phar_internal.h"
+#ifdef PHAR_HAVE_OPENSSL
+
+/* OpenSSL includes */
+#include <openssl/evp.h>
+#include <openssl/x509.h>
+#include <openssl/x509v3.h>
+#include <openssl/crypto.h>
+#include <openssl/pem.h>
+#include <openssl/err.h>
+#include <openssl/conf.h>
+#include <openssl/rand.h>
+#include <openssl/ssl.h>
+#include <openssl/pkcs12.h>
+
+#endif
+#ifndef PHAR_HAVE_OPENSSL
+static int phar_call_openssl_signverify(int is_sign, php_stream *fp, off_t
end, char *key, int key_len, char **signature, int *signature_len TSRMLS_DC);
+#endif
#if !defined(PHP_VERSION_ID) || PHP_VERSION_ID < 50300
extern php_stream_wrapper php_stream_phar_wrapper;
#endif
@@ -1319,3 +1337,373 @@
return NULL;
}
/* }}} */
+
+static const char hexChars[] = "0123456789ABCDEF";
+
+static int phar_hex_str(const char *digest, size_t digest_len, char **
signature)
+{
+ int pos = -1;
+ size_t len = 0;
+
+ *signature = (char*)safe_pemalloc(digest_len, 2, 1, PHAR_G(persist));
+
+ for (; len < digest_len; ++len) {
+ (*signature)[++pos] = hexChars[((const unsigned char
*)digest)[len] >> 4];
+ (*signature)[++pos] = hexChars[((const unsigned char
*)digest)[len] & 0x0F];
+ }
+ (*signature)[++pos] = '\0';
+ return pos;
+}
+#ifndef PHAR_HAVE_OPENSSL
+static int phar_call_openssl_signverify(int is_sign, php_stream *fp, off_t
end, char *key, int key_len, char **signature, int *signature_len TSRMLS_DC)
+{
+ zend_fcall_info fci;
+ zend_fcall_info_cache fcc;
+ zval *zdata, *zsig, *zkey, *retval_ptr, **zp[3], *openssl;
+
+ MAKE_STD_ZVAL(zdata);
+ MAKE_STD_ZVAL(openssl);
+ ZVAL_STRINGL(openssl, is_sign ? "openssl_sign" : "openssl_verify",
is_sign ? sizeof("openssl_sign")-1 : sizeof("openssl_verify")-1, 1);
+ MAKE_STD_ZVAL(zsig);
+ ZVAL_STRINGL(zsig, *signature, *signature_len, 1);
+ MAKE_STD_ZVAL(zkey);
+ ZVAL_STRINGL(zkey, key, key_len, 1);
+ zp[0] = &zdata;
+ zp[1] = &zsig;
+ zp[2] = &zkey;
+
+ php_stream_rewind(fp);
+ Z_TYPE_P(zdata) = IS_STRING;
+ Z_STRLEN_P(zdata) = end;
+ if (end != (off_t) php_stream_copy_to_mem(fp, &(Z_STRVAL_P(zdata)),
(size_t) end, 0)) {
+ zval_dtor(zdata);
+ zval_dtor(zsig);
+ zval_dtor(zkey);
+ return FAILURE;
+ }
+
+#if PHP_VERSION_ID < 50300
+ if (FAILURE == zend_fcall_info_init(openssl, &fci, &fcc TSRMLS_CC)) {
+#else
+ if (FAILURE == zend_fcall_info_init(openssl, 0, &fci, &fcc, NULL, NULL
TSRMLS_CC)) {
+#endif
+ zval_dtor(zdata);
+ zval_dtor(zsig);
+ zval_dtor(zkey);
+ zval_dtor(openssl);
+ return FAILURE;
+ }
+ zval_dtor(openssl);
+ efree(openssl);
+
+ fci.param_count = 3;
+ fci.params = zp;
+#if PHP_VERSION_ID < 50300
+ ++(zdata->refcount);
+ ++(zsig->refcount);
+ ++(zkey->refcount);
+#else
+ Z_ADDREF_P(zdata);
+ if (is_sign) {
+ Z_SET_ISREF_P(zsig);
+ } else {
+ Z_ADDREF_P(zsig);
+ }
+ Z_ADDREF_P(zkey);
+#endif
+ fci.retval_ptr_ptr = &retval_ptr;
+
+ if (FAILURE == zend_call_function(&fci, &fcc TSRMLS_CC)) {
+ zval_dtor(zdata);
+ zval_dtor(zsig);
+ zval_dtor(zkey);
+ efree(zdata);
+ efree(zkey);
+ efree(zsig);
+ return FAILURE;
+ }
+#if PHP_VERSION_ID < 50300
+ --(zdata->refcount);
+ --(zsig->refcount);
+ --(zkey->refcount);
+#else
+ Z_DELREF_P(zdata);
+ if (is_sign) {
+ Z_UNSET_ISREF_P(zsig);
+ } else {
+ Z_DELREF_P(zsig);
+ }
+ Z_DELREF_P(zkey);
+#endif
+ zval_dtor(zdata);
+ efree(zdata);
+ zval_dtor(zkey);
+ efree(zkey);
+ switch (Z_TYPE_P(retval_ptr)) {
+ default:
+ case IS_LONG :
+ zval_dtor(zsig);
+ efree(zsig);
+ if (1 == Z_LVAL_P(retval_ptr)) {
+ efree(retval_ptr);
+ return SUCCESS;
+ }
+ efree(retval_ptr);
+ return FAILURE;
+ case IS_BOOL :
+ efree(retval_ptr);
+ if (Z_BVAL_P(retval_ptr)) {
+ *signature = estrndup(Z_STRVAL_P(zsig),
Z_STRLEN_P(zsig));
+ *signature_len = Z_STRLEN_P(zsig);
+ zval_dtor(zsig);
+ efree(zsig);
+ return SUCCESS;
+ }
+ zval_dtor(zsig);
+ efree(zsig);
+ return FAILURE;
+ }
+}
+#endif /* #ifndef PHAR_HAVE_OPENSSL */
+
+int phar_verify_signature(php_stream *fp, size_t end_of_phar, int sig_type,
char *sig, int sig_len, char *fname, char **signature, int *signature_len, char
**error TSRMLS_DC) /* {{{ */
+{
+ int read_size, len;
+ off_t read_len;
+ unsigned char buf[1024];
+
+ php_stream_rewind(fp);
+
+ switch (sig_type) {
+ case PHAR_SIG_OPENSSL: {
+#ifdef PHAR_HAVE_OPENSSL
+ BIO *in;
+ EVP_PKEY *key;
+ EVP_MD *mdtype = (EVP_MD *) EVP_sha1();
+ EVP_MD_CTX md_ctx;
+#else
+ int tempsig;
+#endif
+ php_uint32 pubkey_len;
+ char *pubkey = NULL, *pfile;
+ php_stream *pfp;
+
+ if (!zend_hash_exists(&module_registry, "openssl",
sizeof("openssl"))) {
+ if (error) {
+ spprintf(error, 0, "openssl not
loaded");
+ }
+ return FAILURE;
+ }
+
+ /* use __FILE__ . '.pubkey' for public key file */
+ spprintf(&pfile, 0, "%s.pubkey", fname);
+ pfp = php_stream_open_wrapper(pfile, "rb", 0, NULL);
+ efree(pfile);
+ if (!pfp || !(pubkey_len = php_stream_copy_to_mem(pfp,
&pubkey, PHP_STREAM_COPY_ALL, 0)) || !pubkey) {
+ if (error) {
+ spprintf(error, 0, "openssl public key
could not be read");
+ }
+ return FAILURE;
+ }
+ php_stream_close(pfp);
+#ifndef PHAR_HAVE_OPENSSL
+ tempsig = sig_len;
+ if (FAILURE == phar_call_openssl_signverify(0, fp,
end_of_phar, pubkey, pubkey_len, &sig, &tempsig TSRMLS_CC)) {
+ if (pubkey) {
+ efree(pubkey);
+ }
+ if (error) {
+ spprintf(error, 0, "openssl signature
could not be verified");
+ }
+ return FAILURE;
+ }
+ if (pubkey) {
+ efree(pubkey);
+ }
+ sig_len = tempsig;
+#else
+ in = BIO_new_mem_buf(pubkey, pubkey_len);
+ if (NULL == in) {
+ efree(pubkey);
+ if (error) {
+ spprintf(error, 0, "openssl signature
could not be processed");
+ }
+ return FAILURE;
+ }
+ key = PEM_read_bio_PUBKEY(in, NULL,NULL, NULL);
+ BIO_free(in);
+ efree(pubkey);
+ if (NULL == key) {
+ if (error) {
+ spprintf(error, 0, "openssl signature
could not be processed");
+ }
+ return FAILURE;
+ }
+
+ EVP_VerifyInit(&md_ctx, mdtype);
+
+ read_len = end_of_phar;
+ if (read_len > sizeof(buf)) {
+ read_size = sizeof(buf);
+ } else {
+ read_size = (int)read_len;
+ }
+ php_stream_seek(fp, 0, SEEK_SET);
+ while (read_size && (len = php_stream_read(fp,
(char*)buf, read_size)) > 0) {
+ EVP_VerifyUpdate (&md_ctx, buf, len);
+ read_len -= (off_t)len;
+ if (read_len < read_size) {
+ read_size = (int)read_len;
+ }
+ }
+ if (!EVP_VerifyFinal (&md_ctx, (unsigned char *)sig,
sig_len, key)) {
+ EVP_MD_CTX_cleanup(&md_ctx);
+ if (error) {
+ spprintf(error, 0, "broken openssl
signature");
+ }
+ return FAILURE;
+ }
+ EVP_MD_CTX_cleanup(&md_ctx);
+#endif
+
+ *signature_len = phar_hex_str((const char*)sig,
sig_len, signature);
+ }
+ break;
+#if HAVE_HASH_EXT
+ case PHAR_SIG_SHA512: {
+ unsigned char digest[64];
+ PHP_SHA512_CTX context;
+
+ PHP_SHA512Init(&context);
+ read_len = end_of_phar;
+ if (read_len > sizeof(buf)) {
+ read_size = sizeof(buf);
+ } else {
+ read_size = (int)read_len;
+ }
+ while ((len = php_stream_read(fp, (char*)buf,
read_size)) > 0) {
+ PHP_SHA512Update(&context, buf, len);
+ read_len -= (off_t)len;
+ if (read_len < read_size) {
+ read_size = (int)read_len;
+ }
+ }
+ PHP_SHA512Final(digest, &context);
+
+ if (memcmp(digest, sig, sizeof(digest))) {
+ if (error) {
+ spprintf(error, 0, "broken signature");
+ }
+ return FAILURE;
+ }
+
+ *signature_len = phar_hex_str((const char*)digest,
sizeof(digest), signature);
+ break;
+ }
+ case PHAR_SIG_SHA256: {
+ unsigned char digest[32];
+ PHP_SHA256_CTX context;
+
+ PHP_SHA256Init(&context);
+ read_len = end_of_phar;
+ if (read_len > sizeof(buf)) {
+ read_size = sizeof(buf);
+ } else {
+ read_size = (int)read_len;
+ }
+ while ((len = php_stream_read(fp, (char*)buf,
read_size)) > 0) {
+ PHP_SHA256Update(&context, buf, len);
+ read_len -= (off_t)len;
+ if (read_len < read_size) {
+ read_size = (int)read_len;
+ }
+ }
+ PHP_SHA256Final(digest, &context);
+
+ if (memcmp(digest, sig, sizeof(digest))) {
+ if (error) {
+ spprintf(error, 0, "broken signature");
+ }
+ return FAILURE;
+ }
+
+ *signature_len = phar_hex_str((const char*)digest,
sizeof(digest), signature);
+ break;
+ }
+#else
+ case PHAR_SIG_SHA512:
+ case PHAR_SIG_SHA256:
+ if (error) {
+ spprintf(error, 0, "unsupported signature");
+ }
+ return FAILURE;
+#endif
+ case PHAR_SIG_SHA1: {
+ unsigned char digest[20];
+ PHP_SHA1_CTX context;
+
+ PHP_SHA1Init(&context);
+ read_len = end_of_phar;
+ if (read_len > sizeof(buf)) {
+ read_size = sizeof(buf);
+ } else {
+ read_size = (int)read_len;
+ }
+ while ((len = php_stream_read(fp, (char*)buf,
read_size)) > 0) {
+ PHP_SHA1Update(&context, buf, len);
+ read_len -= (off_t)len;
+ if (read_len < read_size) {
+ read_size = (int)read_len;
+ }
+ }
+ PHP_SHA1Final(digest, &context);
+
+ if (memcmp(digest, sig, sizeof(digest))) {
+ if (error) {
+ spprintf(error, 0, "broken signature");
+ }
+ return FAILURE;
+ }
+
+ *signature_len = phar_hex_str((const char*)digest,
sizeof(digest), signature);
+ break;
+ }
+ case PHAR_SIG_MD5: {
+ unsigned char digest[16];
+ PHP_MD5_CTX context;
+
+ PHP_MD5Init(&context);
+ read_len = end_of_phar;
+ if (read_len > sizeof(buf)) {
+ read_size = sizeof(buf);
+ } else {
+ read_size = (int)read_len;
+ }
+ while ((len = php_stream_read(fp, (char*)buf,
read_size)) > 0) {
+ PHP_MD5Update(&context, buf, len);
+ read_len -= (off_t)len;
+ if (read_len < read_size) {
+ read_size = (int)read_len;
+ }
+ }
+ PHP_MD5Final(digest, &context);
+
+ if (memcmp(digest, sig, sizeof(digest))) {
+ if (error) {
+ spprintf(error, 0, "broken signature");
+ }
+ return FAILURE;
+ }
+
+ *signature_len = phar_hex_str((const char*)digest,
sizeof(digest), signature);
+ break;
+ }
+ default:
+ if (error) {
+ spprintf(error, 0, "broken or unsupported
signature");
+ }
+ return FAILURE;
+ }
+ return SUCCESS;
+}
+/* }}} */
--
PHP CVS Mailing List (http://www.php.net/)
To unsubscribe, visit: http://www.php.net/unsub.php