Fix EAP-TLS reconnect after reboot issue
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
This commit is contained in:
@@ -25,6 +25,7 @@ import android.content.res.Resources;
|
|||||||
import android.os.AsyncTask;
|
import android.os.AsyncTask;
|
||||||
import android.os.Bundle;
|
import android.os.Bundle;
|
||||||
import android.os.RemoteException;
|
import android.os.RemoteException;
|
||||||
|
import android.os.Process;
|
||||||
import android.security.Credentials;
|
import android.security.Credentials;
|
||||||
import android.security.KeyChain.KeyChainConnection;
|
import android.security.KeyChain.KeyChainConnection;
|
||||||
import android.security.KeyChain;
|
import android.security.KeyChain;
|
||||||
@@ -39,6 +40,14 @@ import android.widget.TextView;
|
|||||||
import android.widget.Toast;
|
import android.widget.Toast;
|
||||||
import com.android.internal.widget.LockPatternUtils;
|
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.
|
* CredentialStorage handles KeyStore reset, unlock, and install.
|
||||||
*
|
*
|
||||||
@@ -182,6 +191,20 @@ public final class CredentialStorage extends Activity {
|
|||||||
return (quality >= MIN_PASSWORD_QUALITY);
|
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.
|
* 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);
|
String key = bundle.getString(Credentials.EXTRA_USER_PRIVATE_KEY_NAME);
|
||||||
byte[] value = bundle.getByteArray(Credentials.EXTRA_USER_PRIVATE_KEY_DATA);
|
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);
|
Log.e(TAG, "Failed to install " + key + " as user " + uid);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int flags = (uid == Process.WIFI_UID) ? KeyStore.FLAG_NONE : KeyStore.FLAG_ENCRYPTED;
|
||||||
|
|
||||||
if (bundle.containsKey(Credentials.EXTRA_USER_CERTIFICATE_NAME)) {
|
if (bundle.containsKey(Credentials.EXTRA_USER_CERTIFICATE_NAME)) {
|
||||||
String certName = bundle.getString(Credentials.EXTRA_USER_CERTIFICATE_NAME);
|
String certName = bundle.getString(Credentials.EXTRA_USER_CERTIFICATE_NAME);
|
||||||
byte[] certData = bundle.getByteArray(Credentials.EXTRA_USER_CERTIFICATE_DATA);
|
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);
|
Log.e(TAG, "Failed to install " + certName + " as user " + uid);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@@ -216,7 +249,7 @@ public final class CredentialStorage extends Activity {
|
|||||||
String caListName = bundle.getString(Credentials.EXTRA_CA_CERTIFICATES_NAME);
|
String caListName = bundle.getString(Credentials.EXTRA_CA_CERTIFICATES_NAME);
|
||||||
byte[] caListData = bundle.getByteArray(Credentials.EXTRA_CA_CERTIFICATES_DATA);
|
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);
|
Log.e(TAG, "Failed to install " + caListName + " as user " + uid);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
Reference in New Issue
Block a user