diff --git a/tfa.admin.inc b/tfa.admin.inc
index 28319af..c063e08 100644
--- a/tfa.admin.inc
+++ b/tfa.admin.inc
@@ -25,10 +25,10 @@ function tfa_admin_settings($form, $form_state) {
}
}
- // Check if mcrypt plugin is available.
- if (!extension_loaded('mcrypt')) {
+ // Check if openssl or mcrypt extensions are available.
+ if (!extension_loaded('openssl') && !extension_loaded('mcrypt')) {
// @todo allow alter in case of other encryption libs.
- drupal_set_message(t('The TFA module requires the PHP Mcrypt extension be installed on the web server. See the TFA help documentation for setup.', array('!link' => url('admin/help/tfa'))), 'error');
+ drupal_set_message(t('The TFA module requires one of the PHP OpenSSL or MCrypt extensions to be installed on the web server. See the TFA help documentation for setup.', array('!link' => url('admin/help/tfa'))), 'error');
return array();
}
diff --git a/tfa.inc b/tfa.inc
index bb9ab82..035eb0c 100644
--- a/tfa.inc
+++ b/tfa.inc
@@ -376,6 +376,8 @@ class TfaSetup {
*/
abstract class TfaBasePlugin {
+ const CRYPT_VERSION = '1';
+
/**
* @var string
*/
@@ -502,18 +504,43 @@ abstract class TfaBasePlugin {
*
* Should be used when writing codes to storage.
*
- * @param string.
+ * @param string $text
+ * The plaintext to be encrypted.
+ *
* @return string
+ * The encrypted text.
*/
protected function encrypt($text) {
+ // Backwards compatibility with MCrypt.
+ if (!extension_loaded('openssl') && extension_loaded('mcrypt')) {
+ return $this->encryptWithMCrypt($text);
+ }
+ $iv = drupal_random_bytes(16);
+
+ return sprintf(
+ '%s|%s|%s',
+ self::CRYPT_VERSION,
+ $iv,
+ openssl_encrypt($text, 'AES-256-CBC', $this->encryptionKey, OPENSSL_RAW_DATA, $iv)
+ );
+ }
+
+ /**
+ * Encrypt using the deprecated mcrypt extension.
+ *
+ * @param string $text
+ *
+ * @return string
+ */
+ protected function encryptWithMCrypt($text, $iv = null) {
$td = mcrypt_module_open('rijndael-128', '', 'cbc', '');
- $iv = drupal_random_bytes(mcrypt_enc_get_iv_size($td));
+ $iv = $iv ?: drupal_random_bytes(mcrypt_enc_get_iv_size($td));
$key = substr($this->encryptionKey, 0, mcrypt_enc_get_key_size($td));
mcrypt_generic_init($td, $key, $iv);
- // Encrypt with message length so decryption can return message without
- // padding.
+ // Encrypt with message length so decryption can return message without
+ // padding.
$text = strlen($text) . '|' . $text;
$data = mcrypt_generic($td, $text);
@@ -528,10 +555,36 @@ abstract class TfaBasePlugin {
*
* Should be used when reading codes from storage.
*
- * @param string
+ * @param string $data
+ * The encrypted text.
+ *
* @return string
+ * The plaintext, or FALSE on failure.
*/
protected function decrypt($data) {
+ $version_prefix = self::CRYPT_VERSION . '|';
+ $version_match = strpos($data, $version_prefix) === 0;
+ // Backwards compatibility with the old MCrypt scheme.
+ if (!$version_match) {
+ if (extension_loaded('mcrypt')) {
+ return $this->decryptWithMCrypt($data);
+ }
+ return FALSE;
+ }
+
+ list(, $iv, $data) = explode('|', $data, 3);
+
+ return openssl_decrypt($data, 'AES-256-CBC', $this->encryptionKey, TRUE, $iv);
+ }
+
+ /**
+ * Decrypt using the deprecated MCrypt extension.
+ *
+ * @param string $data
+ *
+ * @return string
+ */
+ protected function decryptWithMCrypt($data) {
$td = mcrypt_module_open('rijndael-128', '', 'cbc', '');
$iv = substr($data, 0, mcrypt_enc_get_iv_size($td));
diff --git a/tfa.install b/tfa.install
index cbf7943..9bd610d 100644
--- a/tfa.install
+++ b/tfa.install
@@ -26,13 +26,19 @@ function tfa_uninstall() {
*/
function tfa_requirements($phase) {
if ($phase == 'runtime') {
- if (!extension_loaded('mcrypt')) {
- $requirement_severity = REQUIREMENT_ERROR;
- $description = t('The TFA module requires the PHP Mcrypt extension be installed on the web server.');
+ if (!extension_loaded('openssl')) {
+ if (extension_loaded('mcrypt')) {
+ $requirement_severity = REQUIREMENT_WARNING;
+ $description = t('The TFA module recommends the PHP OpenSSL extension to be installed on the web server.');
+ }
+ else {
+ $requirement_severity = REQUIREMENT_ERROR;
+ $description = t('The TFA module requires either the PHP OpenSSL or MCrypt extensions to be installed on the web server.');
+ }
}
else {
$requirement_severity = REQUIREMENT_OK;
- $description= '';
+ $description = '';
}
$enabled = variable_get('tfa_enabled', 0);