summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorScott MacVicar <scottmac@php.net>2012-06-11 07:16:30 (GMT)
committerScott MacVicar <scottmac@php.net>2012-06-11 07:24:44 (GMT)
commitf4847efc5d58b3375fa0f3269158d5e6ab625c21 (patch)
treea6c62e3725d1a6b721071326773fd83a6ccf3be5
parentb55e69285bdfa280b94673e8a9434be6c08c65dc (diff)
downloadphp-f4847efc5d58b3375fa0f3269158d5e6ab625c21.tar.gz
Add PBKDF2 support via openssl()
Summary: No easy way to put these in the hash extension since we don't really support optional parameters to certain algorithms. Implemented in openssl for now since it has it already and is pretty stable. Only SHA1 is confirmed to work as an algorithm but openssl has a parameter so it can be changed in the future. Will backport to 5.4 potentially with Stas' approval. Test Plan: Ran newly added tests which came from RFC 6070
-rw-r--r--ext/openssl/openssl.c57
-rw-r--r--ext/openssl/php_openssl.h2
-rw-r--r--ext/openssl/tests/openssl_pkcs5_pbkdf2_hmac.phpt26
3 files changed, 85 insertions, 0 deletions
diff --git a/ext/openssl/openssl.c b/ext/openssl/openssl.c
index 7187a96..46f60b2 100644
--- a/ext/openssl/openssl.c
+++ b/ext/openssl/openssl.c
@@ -242,6 +242,14 @@ ZEND_BEGIN_ARG_INFO(arginfo_openssl_pkey_get_details, 0)
ZEND_ARG_INFO(0, key)
ZEND_END_ARG_INFO()
+ZEND_BEGIN_ARG_INFO_EX(arginfo_openssl_pkcs5_pbkdf2_hmac, 0, 0, 4)
+ ZEND_ARG_INFO(0, password)
+ ZEND_ARG_INFO(0, salt)
+ ZEND_ARG_INFO(0, key_length)
+ ZEND_ARG_INFO(0, iterations)
+ ZEND_ARG_INFO(0, digest_algorithm)
+ZEND_END_ARG_INFO()
+
ZEND_BEGIN_ARG_INFO_EX(arginfo_openssl_pkcs7_verify, 0, 0, 2)
ZEND_ARG_INFO(0, filename)
ZEND_ARG_INFO(0, flags)
@@ -428,6 +436,8 @@ const zend_function_entry openssl_functions[] = {
PHP_FE(openssl_seal, arginfo_openssl_seal)
PHP_FE(openssl_open, arginfo_openssl_open)
+ PHP_FE(openssl_pkcs5_pbkdf2_hmac, arginfo_openssl_pkcs5_pbkdf2_hmac)
+
/* for S/MIME handling */
PHP_FE(openssl_pkcs7_verify, arginfo_openssl_pkcs7_verify)
PHP_FE(openssl_pkcs7_decrypt, arginfo_openssl_pkcs7_decrypt)
@@ -3317,6 +3327,53 @@ PHP_FUNCTION(openssl_pkey_get_details)
/* }}} */
+/* {{{ proto string openssl_pkcs5_pbkdf2_hmac(string password, string salt, long key_length, long iterations [, string digest_method = "sha1"])
+ Generates a PKCS5 v2 PBKDF2 string, defaults to sha1 */
+PHP_FUNCTION(openssl_pkcs5_pbkdf2_hmac)
+{
+ long key_length = 0, iterations = 0;
+ char *password; int password_len;
+ char *salt; int salt_len;
+ char *method; int method_len = 0;
+ unsigned char *out_buffer;
+
+ const EVP_MD *digest;
+
+ if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "ssll|s",
+ &password, &password_len,
+ &salt, &salt_len,
+ &key_length, &iterations,
+ &method, &method_len) == FAILURE) {
+ return;
+ }
+
+ if (key_length <= 0) {
+ RETURN_FALSE;
+ }
+
+ if (method_len) {
+ digest = EVP_get_digestbyname(method);
+ } else {
+ digest = EVP_sha1();
+ }
+
+ if (!digest) {
+ php_error_docref(NULL TSRMLS_CC, E_WARNING, "Unknown signature algorithm");
+ RETURN_FALSE;
+ }
+
+ out_buffer = emalloc(key_length + 1);
+ out_buffer[key_length] = '\0';
+
+ if (PKCS5_PBKDF2_HMAC(password, password_len, (unsigned char *)salt, salt_len, iterations, digest, key_length, out_buffer) == 1) {
+ RETVAL_STRINGL((char *)out_buffer, key_length, 0);
+ } else {
+ efree(out_buffer);
+ RETURN_FALSE;
+ }
+}
+/* }}} */
+
/* {{{ PKCS7 S/MIME functions */
/* {{{ proto bool openssl_pkcs7_verify(string filename, long flags [, string signerscerts [, array cainfo [, string extracerts [, string content]]]])
diff --git a/ext/openssl/php_openssl.h b/ext/openssl/php_openssl.h
index fc118db..0dbe7d2 100644
--- a/ext/openssl/php_openssl.h
+++ b/ext/openssl/php_openssl.h
@@ -52,6 +52,8 @@ PHP_FUNCTION(openssl_private_decrypt);
PHP_FUNCTION(openssl_public_encrypt);
PHP_FUNCTION(openssl_public_decrypt);
+PHP_FUNCTION(openssl_pkcs5_pbkdf2_hmac);
+
PHP_FUNCTION(openssl_pkcs7_verify);
PHP_FUNCTION(openssl_pkcs7_decrypt);
PHP_FUNCTION(openssl_pkcs7_sign);
diff --git a/ext/openssl/tests/openssl_pkcs5_pbkdf2_hmac.phpt b/ext/openssl/tests/openssl_pkcs5_pbkdf2_hmac.phpt
new file mode 100644
index 0000000..348d399
--- /dev/null
+++ b/ext/openssl/tests/openssl_pkcs5_pbkdf2_hmac.phpt
@@ -0,0 +1,26 @@
+--TEST--
+openssl_pkcs5_pbkdf2_hmac() tests
+--SKIPIF--
+<?php if (!extension_loaded("openssl")) print "skip"; ?>
+--FILE--
+<?php
+// official test vectors
+var_dump(bin2hex(openssl_pkcs5_pbkdf2_hmac('password', 'salt', 20, 1)));
+var_dump(bin2hex(openssl_pkcs5_pbkdf2_hmac('password', 'salt', 20, 2)));
+var_dump(bin2hex(openssl_pkcs5_pbkdf2_hmac('password', 'salt', 20, 4096)));
+
+/* really slow but should be:
+string(40) "eefe3d61cd4da4e4e9945b3d6ba2158c2634e984"
+var_dump(bin2hex(openssl_pkcs5_pbkdf2_hmac('password', 'salt', 20, 16777216)));
+*/
+
+var_dump(bin2hex(openssl_pkcs5_pbkdf2_hmac('passwordPASSWORDpassword', 'saltSALTsaltSALTsaltSALTsaltSALTsalt', 25, 4096)));
+var_dump(bin2hex(openssl_pkcs5_pbkdf2_hmac("pass\0word", "sa\0lt", 16, 4096)));
+
+?>
+--EXPECTF--
+string(40) "0c60c80f961f0e71f3a9b524af6012062fe037a6"
+string(40) "ea6c014dc72d6f8ccd1ed92ace1d41f0d8de8957"
+string(40) "4b007901b765489abead49d926f721d065a429c1"
+string(50) "3d2eec4fe41c849b80c8d83662c0e44a8b291a964cf2f07038"
+string(32) "56fa6aa75548099dcc37d7f03425e0c3"