Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 1e9863f0 authored by Vinit Deshapnde's avatar Vinit Deshapnde Committed by Android Git Automerger
Browse files

am 90a5192c: am e72aa641: am 3eb6e4b4: Merge "Fix EAP-TLS reconnect after...

am 90a5192c: am e72aa641: am 3eb6e4b4: Merge "Fix EAP-TLS reconnect after reboot issue" into klp-dev

* commit '90a5192c':
  Fix EAP-TLS reconnect after reboot issue
parents 1ff5ad87 90a5192c
Loading
Loading
Loading
Loading
+14 −0
Original line number Original line Diff line number Diff line
@@ -57,6 +57,7 @@ class WifiController extends StateMachine {
    private int mStayAwakeConditions;
    private int mStayAwakeConditions;
    private long mIdleMillis;
    private long mIdleMillis;
    private int mSleepPolicy;
    private int mSleepPolicy;
    private boolean mFirstUserSignOnSeen = false;


    private AlarmManager mAlarmManager;
    private AlarmManager mAlarmManager;
    private PendingIntent mIdleIntent;
    private PendingIntent mIdleIntent;
@@ -113,6 +114,7 @@ class WifiController extends StateMachine {
    static final int CMD_AIRPLANE_TOGGLED           = BASE + 9;
    static final int CMD_AIRPLANE_TOGGLED           = BASE + 9;
    static final int CMD_SET_AP                     = BASE + 10;
    static final int CMD_SET_AP                     = BASE + 10;
    static final int CMD_DEFERRED_TOGGLE            = BASE + 11;
    static final int CMD_DEFERRED_TOGGLE            = BASE + 11;
    static final int CMD_USER_PRESENT               = BASE + 12;


    private DefaultState mDefaultState = new DefaultState();
    private DefaultState mDefaultState = new DefaultState();
    private StaEnabledState mStaEnabledState = new StaEnabledState();
    private StaEnabledState mStaEnabledState = new StaEnabledState();
@@ -361,6 +363,9 @@ class WifiController extends StateMachine {
                case CMD_AIRPLANE_TOGGLED:
                case CMD_AIRPLANE_TOGGLED:
                case CMD_EMERGENCY_MODE_CHANGED:
                case CMD_EMERGENCY_MODE_CHANGED:
                    break;
                    break;
                case CMD_USER_PRESENT:
                    mFirstUserSignOnSeen = true;
                    break;
                case CMD_DEFERRED_TOGGLE:
                case CMD_DEFERRED_TOGGLE:
                    log("DEFERRED_TOGGLE ignored due to state change");
                    log("DEFERRED_TOGGLE ignored due to state change");
                    break;
                    break;
@@ -639,6 +644,15 @@ class WifiController extends StateMachine {
            if (msg.what == CMD_DEVICE_IDLE) {
            if (msg.what == CMD_DEVICE_IDLE) {
                checkLocksAndTransitionWhenDeviceIdle();
                checkLocksAndTransitionWhenDeviceIdle();
                // We let default state handle the rest of work
                // We let default state handle the rest of work
            } else if (msg.what == CMD_USER_PRESENT) {
                // TLS networks can't connect until user unlocks keystore. KeyStore
                // unlocks when the user punches PIN after the reboot. So use this
                // trigger to get those networks connected.
                if (mFirstUserSignOnSeen == false) {
                    mWifiStateMachine.reloadTlsNetworksAndReconnect();
                }
                mFirstUserSignOnSeen = true;
                return HANDLED;
            }
            }
            return NOT_HANDLED;
            return NOT_HANDLED;
        }
        }
+4 −0
Original line number Original line Diff line number Diff line
@@ -83,6 +83,7 @@ import static com.android.server.wifi.WifiController.CMD_SCAN_ALWAYS_MODE_CHANGE
import static com.android.server.wifi.WifiController.CMD_SCREEN_OFF;
import static com.android.server.wifi.WifiController.CMD_SCREEN_OFF;
import static com.android.server.wifi.WifiController.CMD_SCREEN_ON;
import static com.android.server.wifi.WifiController.CMD_SCREEN_ON;
import static com.android.server.wifi.WifiController.CMD_SET_AP;
import static com.android.server.wifi.WifiController.CMD_SET_AP;
import static com.android.server.wifi.WifiController.CMD_USER_PRESENT;
import static com.android.server.wifi.WifiController.CMD_WIFI_TOGGLED;
import static com.android.server.wifi.WifiController.CMD_WIFI_TOGGLED;
/**
/**
 * WifiService handles remote WiFi operation requests by implementing
 * WifiService handles remote WiFi operation requests by implementing
@@ -1084,6 +1085,8 @@ public final class WifiService extends IWifiManager.Stub {
            String action = intent.getAction();
            String action = intent.getAction();
            if (action.equals(Intent.ACTION_SCREEN_ON)) {
            if (action.equals(Intent.ACTION_SCREEN_ON)) {
                mWifiController.sendMessage(CMD_SCREEN_ON);
                mWifiController.sendMessage(CMD_SCREEN_ON);
            } else if (action.equals(Intent.ACTION_USER_PRESENT)) {
                mWifiController.sendMessage(CMD_USER_PRESENT);
            } else if (action.equals(Intent.ACTION_SCREEN_OFF)) {
            } else if (action.equals(Intent.ACTION_SCREEN_OFF)) {
                mWifiController.sendMessage(CMD_SCREEN_OFF);
                mWifiController.sendMessage(CMD_SCREEN_OFF);
            } else if (action.equals(Intent.ACTION_BATTERY_CHANGED)) {
            } else if (action.equals(Intent.ACTION_BATTERY_CHANGED)) {
@@ -1120,6 +1123,7 @@ public final class WifiService extends IWifiManager.Stub {
    private void registerForBroadcasts() {
    private void registerForBroadcasts() {
        IntentFilter intentFilter = new IntentFilter();
        IntentFilter intentFilter = new IntentFilter();
        intentFilter.addAction(Intent.ACTION_SCREEN_ON);
        intentFilter.addAction(Intent.ACTION_SCREEN_ON);
        intentFilter.addAction(Intent.ACTION_USER_PRESENT);
        intentFilter.addAction(Intent.ACTION_SCREEN_OFF);
        intentFilter.addAction(Intent.ACTION_SCREEN_OFF);
        intentFilter.addAction(Intent.ACTION_BATTERY_CHANGED);
        intentFilter.addAction(Intent.ACTION_BATTERY_CHANGED);
        intentFilter.addAction(WifiManager.NETWORK_STATE_CHANGED_ACTION);
        intentFilter.addAction(WifiManager.NETWORK_STATE_CHANGED_ACTION);
+22 −1
Original line number Original line Diff line number Diff line
@@ -57,6 +57,7 @@ import java.io.IOException;
import java.io.PrintWriter;
import java.io.PrintWriter;
import java.net.InetAddress;
import java.net.InetAddress;
import java.net.UnknownHostException;
import java.net.UnknownHostException;
import java.security.PublicKey;
import java.util.ArrayList;
import java.util.ArrayList;
import java.util.BitSet;
import java.util.BitSet;
import java.util.Collection;
import java.util.Collection;
@@ -742,6 +743,26 @@ class WifiConfigStore {
        markAllNetworksDisabledExcept(INVALID_NETWORK_ID);
        markAllNetworksDisabledExcept(INVALID_NETWORK_ID);
    }
    }


    boolean needsUnlockedKeyStore() {

        // Any network using certificates to authenticate access requires
        // unlocked key store; unless the certificates can be stored with
        // hardware encryption

        for(WifiConfiguration config : mConfiguredNetworks.values()) {

            if (config.allowedKeyManagement.get(KeyMgmt.WPA_EAP)
                    && config.allowedKeyManagement.get(KeyMgmt.IEEE8021X)) {

                if (config.enterpriseConfig.needsSoftwareBackedKeyStore()) {
                    return true;
                }
            }
        }

        return false;
    }

    private void writeIpAndProxyConfigurations() {
    private void writeIpAndProxyConfigurations() {


        /* Make a copy */
        /* Make a copy */
@@ -1223,7 +1244,6 @@ class WifiConfigStore {
                     * Keyguard settings may eventually be controlled by device policy.
                     * Keyguard settings may eventually be controlled by device policy.
                     * We check here if keystore is unlocked before installing
                     * We check here if keystore is unlocked before installing
                     * credentials.
                     * credentials.
                     * TODO: Figure a way to store these credentials for wifi alone
                     * TODO: Do we need a dialog here ?
                     * TODO: Do we need a dialog here ?
                     */
                     */
                    if (mKeyStore.state() != KeyStore.State.UNLOCKED) {
                    if (mKeyStore.state() != KeyStore.State.UNLOCKED) {
@@ -1583,6 +1603,7 @@ class WifiConfigStore {
        }
        }


        config.enterpriseConfig.migrateCerts(mKeyStore);
        config.enterpriseConfig.migrateCerts(mKeyStore);
        config.enterpriseConfig.initializeSoftwareKeystoreFlag(mKeyStore);
    }
    }


    private String removeDoubleQuotes(String string) {
    private String removeDoubleQuotes(String string) {
+93 −3
Original line number Original line Diff line number Diff line
@@ -19,8 +19,10 @@ import android.os.Parcel;
import android.os.Parcelable;
import android.os.Parcelable;
import android.os.Process;
import android.os.Process;
import android.security.Credentials;
import android.security.Credentials;
import android.security.KeyChain;
import android.security.KeyStore;
import android.security.KeyStore;
import android.text.TextUtils;
import android.text.TextUtils;
import android.util.Slog;


import java.io.ByteArrayInputStream;
import java.io.ByteArrayInputStream;
import java.io.IOException;
import java.io.IOException;
@@ -43,6 +45,7 @@ import java.util.Map;
 */
 */
public class WifiEnterpriseConfig implements Parcelable {
public class WifiEnterpriseConfig implements Parcelable {
    private static final String TAG = "WifiEnterpriseConfig";
    private static final String TAG = "WifiEnterpriseConfig";
    private static final boolean DBG = false;
    /**
    /**
     * In old configurations, the "private_key" field was used. However, newer
     * In old configurations, the "private_key" field was used. However, newer
     * configurations use the key_id field with the engine_id set to "keystore".
     * configurations use the key_id field with the engine_id set to "keystore".
@@ -91,6 +94,7 @@ public class WifiEnterpriseConfig implements Parcelable {
    private X509Certificate mCaCert;
    private X509Certificate mCaCert;
    private PrivateKey mClientPrivateKey;
    private PrivateKey mClientPrivateKey;
    private X509Certificate mClientCertificate;
    private X509Certificate mClientCertificate;
    private boolean mNeedsSoftwareKeystore = false;


    /** This represents an empty value of an enterprise field.
    /** This represents an empty value of an enterprise field.
     * NULL is used at wpa_supplicant to indicate an empty value
     * NULL is used at wpa_supplicant to indicate an empty value
@@ -509,6 +513,18 @@ public class WifiEnterpriseConfig implements Parcelable {
        return true;
        return true;
    }
    }


    static boolean isHardwareBackedKey(PrivateKey key) {
        return KeyChain.isBoundKeyAlgorithm(key.getAlgorithm());
    }

    static boolean hasHardwareBackedKey(Certificate certificate) {
        return KeyChain.isBoundKeyAlgorithm(certificate.getPublicKey().getAlgorithm());
    }

    boolean needsSoftwareBackedKeyStore() {
        return mNeedsSoftwareKeystore;
    }

    boolean installKeys(android.security.KeyStore keyStore, String name) {
    boolean installKeys(android.security.KeyStore keyStore, String name) {
        boolean ret = true;
        boolean ret = true;
        String privKeyName = Credentials.USER_PRIVATE_KEY + name;
        String privKeyName = Credentials.USER_PRIVATE_KEY + name;
@@ -516,8 +532,23 @@ public class WifiEnterpriseConfig implements Parcelable {
        String caCertName = Credentials.CA_CERTIFICATE + name;
        String caCertName = Credentials.CA_CERTIFICATE + name;
        if (mClientCertificate != null) {
        if (mClientCertificate != null) {
            byte[] privKeyData = mClientPrivateKey.getEncoded();
            byte[] privKeyData = mClientPrivateKey.getEncoded();
            if (isHardwareBackedKey(mClientPrivateKey)) {
                // Hardware backed key store is secure enough to store keys un-encrypted, this
                // removes the need for user to punch a PIN to get access to these keys
                if (DBG) Slog.d(TAG, "importing keys " + name + " in hardware backed " +
                        "store");
                ret = keyStore.importKey(privKeyName, privKeyData, Process.WIFI_UID,
                                KeyStore.FLAG_NONE);
            } else {
                // Software backed key store is NOT secure enough to store keys un-encrypted.
                // Save keys encrypted so they are protected with user's PIN. User will
                // have to unlock phone before being able to use these keys and connect to
                // networks.
                if (DBG) Slog.d(TAG, "importing keys " + name + " in software backed store");
                ret = keyStore.importKey(privKeyName, privKeyData, Process.WIFI_UID,
                ret = keyStore.importKey(privKeyName, privKeyData, Process.WIFI_UID,
                        KeyStore.FLAG_ENCRYPTED);
                        KeyStore.FLAG_ENCRYPTED);
                mNeedsSoftwareKeystore = true;
            }
            if (ret == false) {
            if (ret == false) {
                return ret;
                return ret;
            }
            }
@@ -561,7 +592,9 @@ public class WifiEnterpriseConfig implements Parcelable {
            Certificate cert) {
            Certificate cert) {
        try {
        try {
            byte[] certData = Credentials.convertToPem(cert);
            byte[] certData = Credentials.convertToPem(cert);
            return keyStore.put(name, certData, Process.WIFI_UID, KeyStore.FLAG_ENCRYPTED);
            if (DBG) Slog.d(TAG, "putting certificate " + name + " in keystore");
            return keyStore.put(name, certData, Process.WIFI_UID, KeyStore.FLAG_NONE);

        } catch (IOException e1) {
        } catch (IOException e1) {
            return false;
            return false;
        } catch (CertificateException e2) {
        } catch (CertificateException e2) {
@@ -573,6 +606,7 @@ public class WifiEnterpriseConfig implements Parcelable {
        String client = getFieldValue(CLIENT_CERT_KEY, CLIENT_CERT_PREFIX);
        String client = getFieldValue(CLIENT_CERT_KEY, CLIENT_CERT_PREFIX);
        // a valid client certificate is configured
        // a valid client certificate is configured
        if (!TextUtils.isEmpty(client)) {
        if (!TextUtils.isEmpty(client)) {
            if (DBG) Slog.d(TAG, "removing client private key and user cert");
            keyStore.delKey(Credentials.USER_PRIVATE_KEY + client, Process.WIFI_UID);
            keyStore.delKey(Credentials.USER_PRIVATE_KEY + client, Process.WIFI_UID);
            keyStore.delete(Credentials.USER_CERTIFICATE + client, Process.WIFI_UID);
            keyStore.delete(Credentials.USER_CERTIFICATE + client, Process.WIFI_UID);
        }
        }
@@ -580,6 +614,7 @@ public class WifiEnterpriseConfig implements Parcelable {
        String ca = getFieldValue(CA_CERT_KEY, CA_CERT_PREFIX);
        String ca = getFieldValue(CA_CERT_KEY, CA_CERT_PREFIX);
        // a valid ca certificate is configured
        // a valid ca certificate is configured
        if (!TextUtils.isEmpty(ca)) {
        if (!TextUtils.isEmpty(ca)) {
            if (DBG) Slog.d(TAG, "removing CA cert");
            keyStore.delete(Credentials.CA_CERTIFICATE + ca, Process.WIFI_UID);
            keyStore.delete(Credentials.CA_CERTIFICATE + ca, Process.WIFI_UID);
        }
        }
    }
    }
@@ -684,6 +719,61 @@ public class WifiEnterpriseConfig implements Parcelable {
        }
        }
    }
    }


    void initializeSoftwareKeystoreFlag(android.security.KeyStore keyStore) {
        String client = getFieldValue(CLIENT_CERT_KEY, CLIENT_CERT_PREFIX);
        if (!TextUtils.isEmpty(client)) {
            // a valid client certificate is configured

            // BUGBUG: keyStore.get() never returns certBytes; because it is not
            // taking WIFI_UID as a parameter. It always looks for certificate
            // with SYSTEM_UID, and never finds any Wifi certificates. Assuming that
            // all certificates need software keystore until we get the get() API
            // fixed.

            mNeedsSoftwareKeystore = true;

            /*
            try {

                if (DBG) Slog.d(TAG, "Loading client certificate " + Credentials
                        .USER_CERTIFICATE + client);

                CertificateFactory factory = CertificateFactory.getInstance("X.509");
                if (factory == null) {
                    Slog.e(TAG, "Error getting certificate factory");
                    return;
                }

                byte[] certBytes = keyStore.get(Credentials.USER_CERTIFICATE + client);
                if (certBytes != null) {
                    Certificate cert = (X509Certificate) factory.generateCertificate(
                            new ByteArrayInputStream(certBytes));

                    if (cert != null) {
                        mNeedsSoftwareKeystore = hasHardwareBackedKey(cert);

                        if (DBG) Slog.d(TAG, "Loaded client certificate " + Credentials
                                .USER_CERTIFICATE + client);
                        if (DBG) Slog.d(TAG, "It " + (mNeedsSoftwareKeystore ? "needs" :
                                "does not need" ) + " software key store");
                    } else {
                        Slog.d(TAG, "could not generate certificate");
                    }
                } else {
                    Slog.e(TAG, "Could not load client certificate " + Credentials
                            .USER_CERTIFICATE + client);
                    mNeedsSoftwareKeystore = true;
                }

            } catch(CertificateException e) {
                Slog.e(TAG, "Could not read certificates");
                mCaCert = null;
                mClientCertificate = null;
            }
            */
        }
    }

    private String removeDoubleQuotes(String string) {
    private String removeDoubleQuotes(String string) {
        if (TextUtils.isEmpty(string)) return "";
        if (TextUtils.isEmpty(string)) return "";
        int length = string.length();
        int length = string.length();
+18 −0
Original line number Original line Diff line number Diff line
@@ -426,6 +426,8 @@ public class WifiStateMachine extends StateMachine {
    static final int CMD_IP_ADDRESS_UPDATED               = BASE + 140;
    static final int CMD_IP_ADDRESS_UPDATED               = BASE + 140;
    /* An IP address was removed from our interface */
    /* An IP address was removed from our interface */
    static final int CMD_IP_ADDRESS_REMOVED               = BASE + 141;
    static final int CMD_IP_ADDRESS_REMOVED               = BASE + 141;
    /* Reload all networks and reconnect */
    static final int CMD_RELOAD_TLS_AND_RECONNECT         = BASE + 142;


    /* Wifi state machine modes of operation */
    /* Wifi state machine modes of operation */
    /* CONNECT_MODE - connect to any 'known' AP when it becomes available */
    /* CONNECT_MODE - connect to any 'known' AP when it becomes available */
@@ -1319,6 +1321,14 @@ public class WifiStateMachine extends StateMachine {
        sendMessage(CMD_REASSOCIATE);
        sendMessage(CMD_REASSOCIATE);
    }
    }


    /**
     * Reload networks and then reconnect; helps load correct data for TLS networks
     */

    public void reloadTlsNetworksAndReconnect() {
        sendMessage(CMD_RELOAD_TLS_AND_RECONNECT);
    }

    /**
    /**
     * Add a network synchronously
     * Add a network synchronously
     *
     *
@@ -2445,6 +2455,7 @@ public class WifiStateMachine extends StateMachine {
                case CMD_DISCONNECT:
                case CMD_DISCONNECT:
                case CMD_RECONNECT:
                case CMD_RECONNECT:
                case CMD_REASSOCIATE:
                case CMD_REASSOCIATE:
                case CMD_RELOAD_TLS_AND_RECONNECT:
                case WifiMonitor.SUP_CONNECTION_EVENT:
                case WifiMonitor.SUP_CONNECTION_EVENT:
                case WifiMonitor.SUP_DISCONNECTION_EVENT:
                case WifiMonitor.SUP_DISCONNECTION_EVENT:
                case WifiMonitor.NETWORK_CONNECTION_EVENT:
                case WifiMonitor.NETWORK_CONNECTION_EVENT:
@@ -3395,6 +3406,13 @@ public class WifiStateMachine extends StateMachine {
                case CMD_REASSOCIATE:
                case CMD_REASSOCIATE:
                    mWifiNative.reassociate();
                    mWifiNative.reassociate();
                    break;
                    break;
                case CMD_RELOAD_TLS_AND_RECONNECT:
                    if (mWifiConfigStore.needsUnlockedKeyStore()) {
                        logd("Reconnecting to give a chance to un-connected TLS networks");
                        mWifiNative.disconnect();
                        mWifiNative.reconnect();
                    }
                    break;
                case WifiManager.CONNECT_NETWORK:
                case WifiManager.CONNECT_NETWORK:
                    /* The connect message can contain a network id passed as arg1 on message or
                    /* The connect message can contain a network id passed as arg1 on message or
                     * or a config passed as obj on message.
                     * or a config passed as obj on message.