3434#include <openssl/ssl.h>
3535#include <openssl/pkcs12.h>
3636#else
37- static zend_result phar_call_openssl_signverify (bool is_sign , php_stream * fp , zend_off_t end , const char * key , size_t key_len , char * * signature , size_t * signature_len , uint32_t sig_type );
37+ ZEND_ATTRIBUTE_NONNULL static bool phar_call_openssl_verify (php_stream * fp , zend_off_t end , zend_string * public_key , const char * signature , size_t signature_len , uint32_t sig_type );
38+ static zend_result phar_call_openssl_sign (php_stream * fp , zend_off_t end , const char * key , size_t key_len , char * * signature , size_t * signature_len , uint32_t sig_type );
3839#endif
3940
4041/* for links to relative location, prepend cwd of the entry */
@@ -1372,36 +1373,44 @@ static int phar_hex_str(const char *digest, size_t digest_len, char **signature)
13721373/* }}} */
13731374
13741375#ifndef PHAR_HAVE_OPENSSL
1375- static zend_result phar_call_openssl_signverify (bool is_sign , php_stream * fp , zend_off_t end , const char * key , size_t key_len , char * * signature , size_t * signature_len , uint32_t sig_type ) /* {{{ */
1376- {
1377- zval retval , zp [4 ];
1378- zend_string * str ;
1379-
1380- zend_function * fn = NULL ;
1381- if (is_sign ) {
1382- fn = zend_hash_str_find_ptr (CG (function_table ), ZEND_STRL ("openssl_sign" ));
1383- } else {
1384- fn = zend_hash_str_find_ptr (CG (function_table ), ZEND_STRL ("openssl_verify" ));
1385- }
1376+ ZEND_ATTRIBUTE_NONNULL static bool phar_call_openssl_verify (
1377+ php_stream * fp ,
1378+ zend_off_t end ,
1379+ zend_string * public_key ,
1380+ const char * signature ,
1381+ size_t signature_len ,
1382+ uint32_t sig_type
1383+ ) {
1384+ ZEND_ASSERT (signature_len != 0 );
1385+ zend_function * fn = zend_hash_str_find_ptr (CG (function_table ), ZEND_STRL ("openssl_verify" ));
13861386
13871387 /* OpenSSL is not available, even as a shared module */
1388- if (fn == NULL ) {
1389- return FAILURE ;
1388+ if (UNEXPECTED ( fn == NULL ) ) {
1389+ return false ;
13901390 }
13911391
1392- if (* signature_len ) {
1393- ZVAL_STRINGL (& zp [1 ], * signature , * signature_len );
1394- } else {
1395- ZVAL_EMPTY_STRING (& zp [1 ]);
1396- }
1397- ZVAL_STRINGL (& zp [2 ], key , key_len );
1392+ /* Read and copy stream content */
13981393 php_stream_rewind (fp );
1399- str = php_stream_copy_to_mem (fp , (size_t ) end , 0 );
1400- if (str ) {
1401- ZVAL_STR (& zp [0 ], str );
1402- } else {
1403- ZVAL_EMPTY_STRING (& zp [0 ]);
1404- }
1394+ zend_string * str = php_stream_copy_to_mem (fp , (size_t ) end , false);
1395+ /* No content thus signing must fail */
1396+ if (UNEXPECTED (str == NULL )) {
1397+ return false;
1398+ }
1399+
1400+ /* Set up parameters for call to openssl_verify()
1401+ * openssl_verify(
1402+ * string $data,
1403+ * string $signature,
1404+ * OpenSSLAsymmetricKey|OpenSSLCertificate|array|string $public_key,
1405+ * string|int $algorithm = OPENSSL_ALGO_SHA1,
1406+ * int $padding = 0
1407+ * ): int|false
1408+ */
1409+ zval retval , zp [4 ];
1410+ ZVAL_STR (& zp [0 ], str );
1411+ ZVAL_STRINGL (& zp [1 ], signature , signature_len );
1412+ /* Note we do not own the lifetime of the public key, but it is fine as calling the function will increase the refcount) */
1413+ ZVAL_STR (& zp [2 ], public_key );
14051414 if (sig_type == PHAR_SIG_OPENSSL_SHA512 ) {
14061415 ZVAL_LONG (& zp [3 ], 9 ); /* value from openssl.c #define OPENSSL_ALGO_SHA512 9 */
14071416 } else if (sig_type == PHAR_SIG_OPENSSL_SHA256 ) {
@@ -1410,60 +1419,92 @@ static zend_result phar_call_openssl_signverify(bool is_sign, php_stream *fp, ze
14101419 /* don't rely on default value which may change in the future */
14111420 ZVAL_LONG (& zp [3 ], 1 ); /* value from openssl.c #define OPENSSL_ALGO_SHA1 1 */
14121421 }
1422+ zend_call_known_function (fn , NULL , NULL , & retval , /* param_count */ 4 , zp , NULL );
1423+ /* Free string arguments that we own */
1424+ zval_ptr_dtor_str (& zp [0 ]);
1425+ zval_ptr_dtor_str (& zp [1 ]);
1426+
1427+ /* Returns 1 if the signature is correct, 0 if it is incorrect, and -1 or false on error. */
1428+ switch (Z_TYPE (retval )) {
1429+ case IS_LONG :
1430+ if (1 == Z_LVAL (retval )) {
1431+ return true;
1432+ }
1433+ ZEND_FALLTHROUGH ;
1434+ default :
1435+ /* Unlikely, but the openssl_verify() function may be disabled and redefined in userland and return bollocks */
1436+ zval_ptr_dtor (& retval );
1437+ return false;
1438+ }
1439+ }
1440+
1441+ static zend_result phar_call_openssl_sign (php_stream * fp , zend_off_t end , const char * key , size_t key_len , char * * signature , size_t * signature_len , uint32_t sig_type ) /* {{{ */
1442+ {
1443+ ZEND_ASSERT (end != 0 );
1444+ ZEND_ASSERT (* signature_len == 0 );
1445+ zval retval , zp [4 ];
14131446
1414- if ((size_t )end != Z_STRLEN (zp [0 ])) {
1415- zval_ptr_dtor_str (& zp [0 ]);
1416- zval_ptr_dtor_str (& zp [1 ]);
1417- zval_ptr_dtor_str (& zp [2 ]);
1447+ zend_function * fn = zend_hash_str_find_ptr (CG (function_table ), ZEND_STRL ("openssl_sign" ));
1448+
1449+ /* OpenSSL is not available, even as a shared module */
1450+ if (fn == NULL ) {
1451+ return FAILURE ;
1452+ }
1453+
1454+ /* Read and copy stream content */
1455+ php_stream_rewind (fp );
1456+ zend_string * str = php_stream_copy_to_mem (fp , (size_t ) end , false);
1457+ /* No content thus signing must fail */
1458+ if (!str || (size_t )end != ZSTR_LEN (str )) {
14181459 return FAILURE ;
14191460 }
14201461
1421- Z_ADDREF (zp [0 ]);
1422- if (is_sign ) {
1423- ZVAL_NEW_REF (& zp [1 ], & zp [1 ]);
1462+ /* Set up parameters for call to openssl_sign()
1463+ * openssl_sign(
1464+ * string $data,
1465+ * string &$signature,
1466+ * #[\SensitiveParameter] OpenSSLAsymmetricKey|OpenSSLCertificate|array|string $private_key,
1467+ * string|int $algorithm = OPENSSL_ALGO_SHA1,
1468+ * int $padding = 0
1469+ * ): bool
1470+ */
1471+ ZVAL_STR (& zp [0 ], str );
1472+ ZVAL_EMPTY_STRING (& zp [1 ]);
1473+ ZVAL_NEW_REF (& zp [1 ], & zp [1 ]);
1474+ ZVAL_STRINGL (& zp [2 ], key , key_len );
1475+ if (sig_type == PHAR_SIG_OPENSSL_SHA512 ) {
1476+ ZVAL_LONG (& zp [3 ], 9 ); /* value from openssl.c #define OPENSSL_ALGO_SHA512 9 */
1477+ } else if (sig_type == PHAR_SIG_OPENSSL_SHA256 ) {
1478+ ZVAL_LONG (& zp [3 ], 7 ); /* value from openssl.c #define OPENSSL_ALGO_SHA256 7 */
14241479 } else {
1425- Z_ADDREF (zp [1 ]);
1480+ /* don't rely on default value which may change in the future */
1481+ ZVAL_LONG (& zp [3 ], 1 ); /* value from openssl.c #define OPENSSL_ALGO_SHA1 1 */
14261482 }
1427- Z_ADDREF (zp [2 ]);
14281483
14291484 zend_call_known_function (fn , NULL , NULL , & retval , /* param_count */ 4 , zp , NULL );
14301485
1431- Z_DELREF (zp [0 ]);
1432-
1433- if (is_sign ) {
1434- ZVAL_UNREF (& zp [1 ]);
1435- } else {
1436- Z_DELREF (zp [1 ]);
1437- }
1438- Z_DELREF (zp [2 ]);
1486+ ZVAL_UNREF (& zp [1 ]);
14391487
14401488 zval_ptr_dtor_str (& zp [0 ]);
14411489 zval_ptr_dtor_str (& zp [2 ]);
14421490
14431491 switch (Z_TYPE (retval )) {
1444- case IS_LONG :
1445- zval_ptr_dtor (& zp [1 ]);
1446- if (1 == Z_LVAL (retval )) {
1447- return SUCCESS ;
1448- }
1449- return FAILURE ;
14501492 case IS_TRUE :
14511493 * signature = estrndup (Z_STRVAL (zp [1 ]), Z_STRLEN (zp [1 ]));
14521494 * signature_len = Z_STRLEN (zp [1 ]);
14531495 zval_ptr_dtor (& zp [1 ]);
14541496 return SUCCESS ;
14551497 default :
1498+ /* Unlikely, but the openssl_sign() function may be disabled and redefined in userland and return bollocks */
14561499 zval_ptr_dtor (& retval );
1457- ZEND_FALLTHROUGH ;
1458- case IS_FALSE :
14591500 zval_ptr_dtor (& zp [1 ]);
14601501 return FAILURE ;
14611502 }
14621503}
14631504/* }}} */
14641505#endif /* #ifndef PHAR_HAVE_OPENSSL */
14651506
1466- zend_result phar_verify_signature (php_stream * fp , size_t end_of_phar , uint32_t sig_type , char * sig , size_t sig_len , const char * fname , char * * signature , size_t * signature_len , char * * error ) /* {{{ */
1507+ zend_result phar_verify_signature (php_stream * fp , size_t end_of_phar , uint32_t sig_type , const char * sig , size_t sig_len , const char * fname , char * * signature , size_t * signature_len , char * * error ) /* {{{ */
14671508{
14681509 size_t read_size , len ;
14691510 zend_off_t read_len ;
@@ -1488,8 +1529,6 @@ zend_result phar_verify_signature(php_stream *fp, size_t end_of_phar, uint32_t s
14881529 } else {
14891530 mdtype = EVP_sha1 ();
14901531 }
1491- #else
1492- size_t tempsig ;
14931532#endif
14941533 zend_string * pubkey = NULL ;
14951534 char * pfile ;
@@ -1524,9 +1563,7 @@ zend_result phar_verify_signature(php_stream *fp, size_t end_of_phar, uint32_t s
15241563 }
15251564
15261565#ifndef PHAR_HAVE_OPENSSL
1527- tempsig = sig_len ;
1528-
1529- if (FAILURE == phar_call_openssl_signverify (false, fp , end_of_phar , ZSTR_VAL (pubkey ), ZSTR_LEN (pubkey ), & sig , & tempsig , sig_type )) {
1566+ if (!phar_call_openssl_verify (fp , end_of_phar , pubkey , sig , sig_len , sig_type )) {
15301567 zend_string_release_ex (pubkey , 0 );
15311568
15321569 if (error ) {
@@ -1536,9 +1573,7 @@ zend_result phar_verify_signature(php_stream *fp, size_t end_of_phar, uint32_t s
15361573 return FAILURE ;
15371574 }
15381575
1539- zend_string_release_ex (pubkey , 0 );
1540-
1541- sig_len = tempsig ;
1576+ zend_string_release_ex (pubkey , false);
15421577#else
15431578 in = BIO_new_mem_buf (ZSTR_VAL (pubkey ), ZSTR_LEN (pubkey ));
15441579
@@ -1610,7 +1645,7 @@ zend_result phar_verify_signature(php_stream *fp, size_t end_of_phar, uint32_t s
16101645 EVP_MD_CTX_destroy (md_ctx );
16111646#endif
16121647
1613- * signature_len = phar_hex_str (( const char * ) sig , sig_len , signature );
1648+ * signature_len = phar_hex_str (sig , sig_len , signature );
16141649 }
16151650 break ;
16161651 case PHAR_SIG_SHA512 : {
@@ -1909,7 +1944,7 @@ ZEND_ATTRIBUTE_NONNULL zend_string* phar_create_signature(phar_archive_data *pha
19091944 siglen = 0 ;
19101945 php_stream_seek (fp , 0 , SEEK_END );
19111946
1912- if (FAILURE == phar_call_openssl_signverify (true, fp , php_stream_tell (fp ), PHAR_G (openssl_privatekey ), PHAR_G (openssl_privatekey_len ), (char * * )& sigbuf , & siglen , phar -> sig_flags )) {
1947+ if (FAILURE == phar_call_openssl_sign ( fp , php_stream_tell (fp ), PHAR_G (openssl_privatekey ), PHAR_G (openssl_privatekey_len ), (char * * )& sigbuf , & siglen , phar -> sig_flags )) {
19131948 spprintf (error , 0 , "unable to write phar \"%s\" with requested openssl signature" , ZSTR_VAL (phar -> fname ));
19141949 return NULL ;
19151950 }
0 commit comments