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