summaryrefslogtreecommitdiff
path: root/ext/openssl
diff options
context:
space:
mode:
authorScott MacVicar <scottmac@php.net>2012-06-11 00:16:30 -0700
committerScott MacVicar <scottmac@php.net>2012-06-11 00:24:44 -0700
commitf4847efc5d58b3375fa0f3269158d5e6ab625c21 (patch)
treea6c62e3725d1a6b721071326773fd83a6ccf3be5 /ext/openssl
parentb55e69285bdfa280b94673e8a9434be6c08c65dc (diff)
downloadphp-git-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
Diffstat (limited to 'ext/openssl')
-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 7187a9601e..46f60b2a65 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 fc118dba1e..0dbe7d2887 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 0000000000..348d3993c2
--- /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"