OSDN Git Service

Fix EAP-TLS reconnect after reboot issue
authorVinit Deshapnde <vinitd@google.com>
Mon, 30 Sep 2013 17:41:27 +0000 (10:41 -0700)
committerVinit Deshapnde <vinitd@google.com>
Mon, 30 Sep 2013 17:41:39 +0000 (10:41 -0700)
After a reboot, KeyStore is locked, and certificates encrypted with user
PIN are not accessible. So statemachines are not able to connect to
EAP-TLS networks. This change makes the problem less severe by

1. Not signing certificates with user PIN on devices with hardware backed
KeyStore.
2. Issuing a reconnect upon first USER_PRESENT event.

This means HH (which has a hardware backed keystore) will connect to
EAP-TLS networks without requiring user intervention; and other devices
will automatically connect to those networks after user punches PIN.

Bug: 10325089

Change-Id: I023d60e58d8214152f051bd9ec84b85b702d829a

src/com/android/settings/CredentialStorage.java

index 9173e39..fcf208a 100644 (file)
@@ -25,6 +25,7 @@ import android.content.res.Resources;
 import android.os.AsyncTask;
 import android.os.Bundle;
 import android.os.RemoteException;
+import android.os.Process;
 import android.security.Credentials;
 import android.security.KeyChain.KeyChainConnection;
 import android.security.KeyChain;
@@ -39,6 +40,14 @@ import android.widget.TextView;
 import android.widget.Toast;
 import com.android.internal.widget.LockPatternUtils;
 
+import com.android.org.bouncycastle.asn1.ASN1InputStream;
+import com.android.org.bouncycastle.asn1.pkcs.PrivateKeyInfo;
+
+import org.apache.harmony.security.utils.AlgNameMapper;
+
+import java.io.ByteArrayInputStream;
+import java.io.IOException;
+
 /**
  * CredentialStorage handles KeyStore reset, unlock, and install.
  *
@@ -182,6 +191,20 @@ public final class CredentialStorage extends Activity {
         return (quality >= MIN_PASSWORD_QUALITY);
     }
 
+    private boolean isHardwareBackedKey(byte[] keyData) {
+        try {
+            ASN1InputStream bIn = new ASN1InputStream(new ByteArrayInputStream(keyData));
+            PrivateKeyInfo pki = PrivateKeyInfo.getInstance(bIn.readObject());
+            String algId = pki.getAlgorithmId().getAlgorithm().getId();
+            String algName = AlgNameMapper.map2AlgName(algId);
+
+            return KeyChain.isBoundKeyAlgorithm(algName);
+        } catch (IOException e) {
+            Log.e(TAG, "Failed to parse key data");
+            return false;
+        }
+    }
+
     /**
      * Install credentials if available, otherwise do nothing.
      */
@@ -196,17 +219,27 @@ public final class CredentialStorage extends Activity {
                 String key = bundle.getString(Credentials.EXTRA_USER_PRIVATE_KEY_NAME);
                 byte[] value = bundle.getByteArray(Credentials.EXTRA_USER_PRIVATE_KEY_DATA);
 
-                if (!mKeyStore.importKey(key, value, uid, KeyStore.FLAG_ENCRYPTED)) {
+                int flags = KeyStore.FLAG_ENCRYPTED;
+                if (uid == Process.WIFI_UID && isHardwareBackedKey(value)) {
+                    // Hardware backed keystore is secure enough to allow for WIFI stack
+                    // to enable access to secure networks without user intervention
+                    Log.d(TAG, "Saving private key with FLAG_NONE for WIFI_UID");
+                    flags = KeyStore.FLAG_NONE;
+                }
+
+                if (!mKeyStore.importKey(key, value, uid, flags)) {
                     Log.e(TAG, "Failed to install " + key + " as user " + uid);
                     return;
                 }
             }
 
+            int flags = (uid == Process.WIFI_UID) ? KeyStore.FLAG_NONE : KeyStore.FLAG_ENCRYPTED;
+
             if (bundle.containsKey(Credentials.EXTRA_USER_CERTIFICATE_NAME)) {
                 String certName = bundle.getString(Credentials.EXTRA_USER_CERTIFICATE_NAME);
                 byte[] certData = bundle.getByteArray(Credentials.EXTRA_USER_CERTIFICATE_DATA);
 
-                if (!mKeyStore.put(certName, certData, uid, KeyStore.FLAG_ENCRYPTED)) {
+                if (!mKeyStore.put(certName, certData, uid, flags)) {
                     Log.e(TAG, "Failed to install " + certName + " as user " + uid);
                     return;
                 }
@@ -216,7 +249,7 @@ public final class CredentialStorage extends Activity {
                 String caListName = bundle.getString(Credentials.EXTRA_CA_CERTIFICATES_NAME);
                 byte[] caListData = bundle.getByteArray(Credentials.EXTRA_CA_CERTIFICATES_DATA);
 
-                if (!mKeyStore.put(caListName, caListData, uid, KeyStore.FLAG_ENCRYPTED)) {
+                if (!mKeyStore.put(caListName, caListData, uid, flags)) {
                     Log.e(TAG, "Failed to install " + caListName + " as user " + uid);
                     return;
                 }