How to add additional factor to wordpress authentication

I don’t know that I would use cookies for this as the user could just modify their cookie to match their current IP. You could store the user’s IP as user meta at signup and then compare that to their IP during subsequent logins via the wp_authenticate_user filter.

Sample code (untested):

add_action( 'user_register', 'wpse157630_add_user_ip', 10, 1 );
function wpse157630_add_user_ip( $user_id ) {
  update_user_meta( $user_id, 'wpse157630_ip_address', $_SERVER['REMOTE_ADDR'] );
}

add_filter( 'wp_authenticate_user', 'wpse157630_check_user_ip', 10, 2 );
function wpse157630_check_user_ip( $user, $password ) {
  $stored_ip = get_user_meta( $user->ID, 'wpse157630_ip_address', true );
  if ( $stored_ip == $_SERVER['REMOTE_ADDR'] ) {
    return $user;
  } else {
    return new WP_Error( 'invalid_ip_address', 'Invalid IP address' );
  }
}

If you wanted to get crazy, you could store the user meta as an array of IP addresses and add a spot in the user edit screen to allow the user to add multiple IP addresses to compare against.