diff --git a/core/includes/form.inc b/core/includes/form.inc
index 362d0d5..48597f1 100644
--- a/core/includes/form.inc
+++ b/core/includes/form.inc
@@ -2854,6 +2854,86 @@ function theme_radios($variables) {
 }
 
 /**
+ * Expand certain fields with the #confirm property set into two text boxes.
+ */
+function form_process_confirm($element) {
+
+  // Only act on elements with the #confirm property set TRUE.
+  if (empty($element['#confirm'])) {
+    return $element;
+  }
+
+  $orig_attr = $conf_attr = isset($element['#attributes']) ? $element['#attributes'] : array('class' => '');
+  $orig_attr['class'][] = 'confirm-original-field';
+  $conf_attr['class'][] = 'confirm-confirm-field';
+
+  $value = empty($element['#value']) ? NULL : $element['#value'];
+
+  $element['original'] = array(
+    '#type' => $element['#type'],
+    '#title' => $element['#title'],
+    '#value' => is_array($value) ? (isset($value['original']) ? $value['original'] : NULL) : $value,
+    '#required' => $element['#required'],
+    '#attributes' => $orig_attr,
+    '#id' => $element['#id'],
+  );
+  $element['confirm'] = array(
+    '#type' => $element['#type'],
+    '#title' => t('Confirm !name', array('!name' => $element['#title'])),
+    '#value' => is_array($value) ? (isset($value['confirm']) ? $value['confirm'] : NULL) : $value,
+    '#required' => $element['#required'],
+    '#attributes' => $conf_attr,
+    '#states' => array(
+      'visible' => array(
+        '#' . $element['#id'] => array('filled' => TRUE),
+      ),
+    ),
+  );
+
+  // We need to fix the following properties on $element so that FAPI no longer
+  // treats this as a typical field.
+  $element['#element_validate'] = array('confirm_field_validate');
+  $element['#tree'] = TRUE;
+  $element['#validate'] = FALSE;
+  $element['#title'] = FALSE;
+  $element['#required'] = FALSE;
+  // Set #id to make sure FAPI doesn't bust us for a conflicting DOM id.
+  $element['#id'] = 'rand' . rand();
+  unset($element['#theme'], $element['#type'], $element['#maxlength']);
+
+  if (isset($element['#size'])) {
+    $element['original']['#size'] = $element['confirm']['#size'] = $element['#size'];
+  }
+
+  return $element;
+
+}
+
+/**
+ * Validate element with #confirm property.
+ */
+function confirm_field_validate($element, &$form_state) {
+  $original = trim($element['original']['#value']);
+  if (!empty($original)) {
+    $confirm = trim($element['confirm']['#value']);
+    if ($confirm != $original) {
+      form_error($element, t('!name values do not match.', array('!name' => $element['original']['#title'])));
+    }
+  }
+  elseif ($element['#required'] && !empty($form_state['input'])) {
+    form_error($element, t('!name field is required.', array('!name' => $element['original']['#title'])));
+  }
+
+  // Confirm field must be converted from a two-element array into a single
+  // string regardless of validation results.
+  form_set_value($element['original'], NULL, $form_state);
+  form_set_value($element['confirm'], NULL, $form_state);
+  form_set_value($element, $original, $form_state);
+
+  return $element;
+}
+
+/**
  * Expand a password_confirm field into two text boxes.
  */
 function form_process_password_confirm($element) {
diff --git a/core/modules/system/system.module b/core/modules/system/system.module
index de7241f..a8d07a1 100644
--- a/core/modules/system/system.module
+++ b/core/modules/system/system.module
@@ -367,7 +367,7 @@ function system_element_info() {
     '#size' => 60,
     '#maxlength' => 128,
     '#autocomplete_path' => FALSE,
-    '#process' => array('form_process_autocomplete', 'ajax_process_form', 'form_process_pattern'),
+    '#process' => array('form_process_autocomplete', 'ajax_process_form', 'form_process_pattern', 'form_process_confirm'),
     '#theme' => 'textfield',
     '#theme_wrappers' => array('form_element'),
   );
@@ -376,7 +376,7 @@ function system_element_info() {
     '#size' => 30,
     '#maxlength' => 128,
     '#autocomplete_path' => FALSE,
-    '#process' => array('form_process_autocomplete', 'ajax_process_form', 'form_process_pattern'),
+    '#process' => array('form_process_autocomplete', 'ajax_process_form', 'form_process_pattern', 'form_process_confirm'),
     '#theme' => 'tel',
     '#theme_wrappers' => array('form_element'),
   );
@@ -386,7 +386,7 @@ function system_element_info() {
     // user.module is not loaded in case of early bootstrap errors.
     '#maxlength' => defined('EMAIL_MAX_LENGTH') ? EMAIL_MAX_LENGTH : 255,
     '#autocomplete_path' => FALSE,
-    '#process' => array('form_process_autocomplete', 'ajax_process_form', 'form_process_pattern'),
+    '#process' => array('form_process_autocomplete', 'ajax_process_form', 'form_process_pattern', 'form_process_confirm'),
     '#element_validate' => array('form_validate_email'),
     '#theme' => 'email',
     '#theme_wrappers' => array('form_element'),
@@ -451,7 +451,7 @@ function system_element_info() {
     '#input' => TRUE,
     '#size' => 60,
     '#maxlength' => 128,
-    '#process' => array('ajax_process_form', 'form_process_pattern'),
+    '#process' => array('ajax_process_form', 'form_process_pattern', 'form_process_confirm'),
     '#theme' => 'password',
     '#theme_wrappers' => array('form_element'),
   );
diff --git a/core/modules/user/lib/Drupal/user/AccountFormController.php b/core/modules/user/lib/Drupal/user/AccountFormController.php
index 31ca843..80bcbc0 100644
--- a/core/modules/user/lib/Drupal/user/AccountFormController.php
+++ b/core/modules/user/lib/Drupal/user/AccountFormController.php
@@ -54,6 +54,7 @@ abstract class AccountFormController extends EntityFormController {
       '#required' => !(empty($account->mail) && user_access('administer users')),
       '#default_value' => (!$register ? $account->mail : ''),
       '#attributes' => array('autocomplete' => 'off'),
+      '#confirm' => variable_get('user_confirm_email_on_register', FALSE),
     );
 
     // Display password field only for existing users or when user is allowed to
diff --git a/core/modules/user/user.admin.inc b/core/modules/user/user.admin.inc
index fac9723..46f504e 100644
--- a/core/modules/user/user.admin.inc
+++ b/core/modules/user/user.admin.inc
@@ -310,6 +310,12 @@ function user_admin_settings() {
       USER_REGISTER_VISITORS_ADMINISTRATIVE_APPROVAL => t('Visitors, but administrator approval is required'),
     )
   );
+  $form['registration']['user_confirm_email_on_register'] = array(
+    '#type' => 'checkbox',
+    '#title' => t('Use an e-mail confirmation input on user registration form.'),
+    '#default_value' => variable_get('user_confirm_email_on_register', FALSE),
+    '#description' => t('If this box is checked, a "Confirm E-mail address" input will be added to the user registration form. The registrant will be required to enter their email address twice when registering, to prevent typos.'),
+  );
   $form['registration_cancellation']['user_email_verification'] = array(
     '#type' => 'checkbox',
     '#title' => t('Require e-mail verification when a visitor creates an account.'),
