Merge changes Ibdf23227,I3681f98c
* changes:
Update Wifi to use new keystore function
Add signing to keystore
diff --git a/keystore/java/android/security/Credentials.java b/keystore/java/android/security/Credentials.java
index f75208d..68ba2b1 100644
--- a/keystore/java/android/security/Credentials.java
+++ b/keystore/java/android/security/Credentials.java
@@ -26,11 +26,13 @@
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.InputStreamReader;
+import java.io.ObjectOutputStream;
import java.io.OutputStreamWriter;
import java.io.Reader;
import java.io.Writer;
import java.nio.charset.Charsets;
import java.security.KeyPair;
+import java.security.cert.X509Certificate;
import java.util.ArrayList;
import java.util.List;
@@ -73,6 +75,36 @@
public static final String EXTENSION_PFX = ".pfx";
/**
+ * Intent extra: name for the user's private key.
+ */
+ public static final String EXTRA_USER_PRIVATE_KEY_NAME = "user_private_key_name";
+
+ /**
+ * Intent extra: data for the user's private key in PEM-encoded PKCS#8.
+ */
+ public static final String EXTRA_USER_PRIVATE_KEY_DATA = "user_private_key_data";
+
+ /**
+ * Intent extra: name for the user's certificate.
+ */
+ public static final String EXTRA_USER_CERTIFICATE_NAME = "user_certificate_name";
+
+ /**
+ * Intent extra: data for the user's certificate in PEM-encoded X.509.
+ */
+ public static final String EXTRA_USER_CERTIFICATE_DATA = "user_certificate_data";
+
+ /**
+ * Intent extra: name for CA certificate chain
+ */
+ public static final String EXTRA_CA_CERTIFICATES_NAME = "ca_certificates_name";
+
+ /**
+ * Intent extra: data for CA certificate chain in PEM-encoded X.509.
+ */
+ public static final String EXTRA_CA_CERTIFICATES_DATA = "ca_certificates_data";
+
+ /**
* Convert objects to a PEM format, which is used for
* CA_CERTIFICATE, USER_CERTIFICATE, and USER_PRIVATE_KEY
* entries.
diff --git a/keystore/java/android/security/IKeyChainService.aidl b/keystore/java/android/security/IKeyChainService.aidl
index f38f6ce..60fd7f7 100644
--- a/keystore/java/android/security/IKeyChainService.aidl
+++ b/keystore/java/android/security/IKeyChainService.aidl
@@ -23,7 +23,7 @@
*/
interface IKeyChainService {
// APIs used by KeyChain
- byte[] getPrivateKey(String alias);
+ String requestPrivateKey(String alias);
byte[] getCertificate(String alias);
// APIs used by CertInstaller
diff --git a/keystore/java/android/security/KeyChain.java b/keystore/java/android/security/KeyChain.java
index fe03437..483ccb2 100644
--- a/keystore/java/android/security/KeyChain.java
+++ b/keystore/java/android/security/KeyChain.java
@@ -27,6 +27,7 @@
import java.io.ByteArrayInputStream;
import java.io.Closeable;
import java.io.IOException;
+import java.security.InvalidKeyException;
import java.security.KeyPair;
import java.security.Principal;
import java.security.PrivateKey;
@@ -39,6 +40,8 @@
import java.util.concurrent.BlockingQueue;
import java.util.concurrent.LinkedBlockingQueue;
import libcore.util.Objects;
+
+import org.apache.harmony.xnet.provider.jsse.OpenSSLEngine;
import org.apache.harmony.xnet.provider.jsse.TrustedCertificateStore;
/**
@@ -301,14 +304,21 @@
}
KeyChainConnection keyChainConnection = bind(context);
try {
- IKeyChainService keyChainService = keyChainConnection.getService();
- byte[] privateKeyBytes = keyChainService.getPrivateKey(alias);
- return toPrivateKey(privateKeyBytes);
+ final IKeyChainService keyChainService = keyChainConnection.getService();
+ final String keyId = keyChainService.requestPrivateKey(alias);
+ if (keyId == null) {
+ throw new KeyChainException("keystore had a problem");
+ }
+
+ final OpenSSLEngine engine = OpenSSLEngine.getInstance("keystore");
+ return engine.getPrivateKeyById(keyId);
} catch (RemoteException e) {
throw new KeyChainException(e);
} catch (RuntimeException e) {
// only certain RuntimeExceptions can be propagated across the IKeyChainService call
throw new KeyChainException(e);
+ } catch (InvalidKeyException e) {
+ throw new KeyChainException(e);
} finally {
keyChainConnection.close();
}
@@ -356,18 +366,6 @@
}
}
- private static PrivateKey toPrivateKey(byte[] bytes) {
- if (bytes == null) {
- throw new IllegalArgumentException("bytes == null");
- }
- try {
- KeyPair keyPair = (KeyPair) Credentials.convertFromPem(bytes).get(0);
- return keyPair.getPrivate();
- } catch (IOException e) {
- throw new AssertionError(e);
- }
- }
-
private static X509Certificate toCertificate(byte[] bytes) {
if (bytes == null) {
throw new IllegalArgumentException("bytes == null");
diff --git a/keystore/java/android/security/KeyStore.java b/keystore/java/android/security/KeyStore.java
index 9058cae..a32e469 100644
--- a/keystore/java/android/security/KeyStore.java
+++ b/keystore/java/android/security/KeyStore.java
@@ -155,6 +155,78 @@
return mError == KEY_NOT_FOUND;
}
+ private boolean generate(byte[] key) {
+ execute('a', key);
+ return mError == NO_ERROR;
+ }
+
+ public boolean generate(String key) {
+ return generate(getBytes(key));
+ }
+
+ private boolean importKey(byte[] keyName, byte[] key) {
+ execute('m', keyName, key);
+ return mError == NO_ERROR;
+ }
+
+ public boolean importKey(String keyName, byte[] key) {
+ return importKey(getBytes(keyName), key);
+ }
+
+ private byte[] getPubkey(byte[] key) {
+ ArrayList<byte[]> values = execute('b', key);
+ return (values == null || values.isEmpty()) ? null : values.get(0);
+ }
+
+ public byte[] getPubkey(String key) {
+ return getPubkey(getBytes(key));
+ }
+
+ private boolean delKey(byte[] key) {
+ execute('k', key);
+ return mError == NO_ERROR;
+ }
+
+ public boolean delKey(String key) {
+ return delKey(getBytes(key));
+ }
+
+ private byte[] sign(byte[] keyName, byte[] data) {
+ final ArrayList<byte[]> values = execute('n', keyName, data);
+ return (values == null || values.isEmpty()) ? null : values.get(0);
+ }
+
+ public byte[] sign(String key, byte[] data) {
+ return sign(getBytes(key), data);
+ }
+
+ private boolean verify(byte[] keyName, byte[] data, byte[] signature) {
+ execute('v', keyName, data, signature);
+ return mError == NO_ERROR;
+ }
+
+ public boolean verify(String key, byte[] data, byte[] signature) {
+ return verify(getBytes(key), data, signature);
+ }
+
+ private boolean grant(byte[] key, byte[] uid) {
+ execute('x', key, uid);
+ return mError == NO_ERROR;
+ }
+
+ public boolean grant(String key, int uid) {
+ return grant(getBytes(key), Integer.toString(uid).getBytes());
+ }
+
+ private boolean ungrant(byte[] key, byte[] uid) {
+ execute('y', key, uid);
+ return mError == NO_ERROR;
+ }
+
+ public boolean ungrant(String key, int uid) {
+ return ungrant(getBytes(key), Integer.toString(uid).getBytes());
+ }
+
public int getLastError() {
return mError;
}
diff --git a/keystore/tests/src/android/security/KeyStoreTest.java b/keystore/tests/src/android/security/KeyStoreTest.java
index 15e253c..008d682 100755
--- a/keystore/tests/src/android/security/KeyStoreTest.java
+++ b/keystore/tests/src/android/security/KeyStoreTest.java
@@ -44,19 +44,73 @@
private static final String TEST_I18N_KEY = "\u4F60\u597D, \u4E16\u754C";
private static final byte[] TEST_I18N_VALUE = TEST_I18N_KEY.getBytes(Charsets.UTF_8);
+ // Test vector data for signatures
+ private static final byte[] TEST_DATA = {
+ (byte) 0x00, (byte) 0xA0, (byte) 0xFF, (byte) 0x0A, (byte) 0x00, (byte) 0xFF,
+ (byte) 0xAA, (byte) 0x55, (byte) 0x05, (byte) 0x5A,
+ };
+
private KeyStore mKeyStore = null;
public KeyStoreTest() {
super(Activity.class);
}
+ private static final byte[] PRIVKEY_BYTES = hexToBytes(
+ "308204BE020100300D06092A864886F70D0101010500048204A8308204A4020100028201" +
+ "0100E0473E8AB8F2284FEB9E742FF9748FA118ED98633C92F52AEB7A2EBE0D3BE60329BE" +
+ "766AD10EB6A515D0D2CFD9BEA7930F0C306537899F7958CD3E85B01F8818524D312584A9" +
+ "4B251E3625B54141EDBFEE198808E1BB97FC7CB49B9EAAAF68E9C98D7D0EDC53BBC0FA00" +
+ "34356D6305FBBCC3C7001405386ABBC873CB0F3EF7425F3D33DF7B315AE036D2A0B66AFD" +
+ "47503B169BF36E3B5162515B715FDA83DEAF2C58AEB9ABFB3097C3CC9DD9DBE5EF296C17" +
+ "6139028E8A671E63056D45F40188D2C4133490845DE52C2534E9C6B2478C07BDAE928823" +
+ "B62D066C7770F9F63F3DBA247F530844747BE7AAA85D853B8BD244ACEC3DE3C89AB46453" +
+ "AB4D24C3AC6902030100010282010037784776A5F17698F5AC960DFB83A1B67564E648BD" +
+ "0597CF8AB8087186F2669C27A9ECBDD480F0197A80D07309E6C6A96F925331E57F8B4AC6" +
+ "F4D45EDA45A23269C09FC428C07A4E6EDF738A15DEC97FABD2F2BB47A14F20EA72FCFE4C" +
+ "36E01ADA77BD137CD8D4DA10BB162E94A4662971F175F985FA188F056CB97EE2816F43AB" +
+ "9D3747612486CDA8C16196C30818A995EC85D38467791267B3BF21F273710A6925862576" +
+ "841C5B6712C12D4BD20A2F3299ADB7C135DA5E9515ABDA76E7CAF2A3BE80551D073B78BF" +
+ "1162C48AD2B7F4743A0238EE4D252F7D5E7E6533CCAE64CCB39360075A2FD1E034EC3AE5" +
+ "CE9C408CCBF0E25E4114021687B3DD4754AE8102818100F541884BC3737B2922D4119EF4" +
+ "5E2DEE2CD4CBB75F45505A157AA5009F99C73A2DF0724AC46024306332EA898177634546" +
+ "5DC6DF1E0A6F140AFF3B7396E6A8994AC5DAA96873472FE37749D14EB3E075E629DBEB35" +
+ "83338A6F3649D0A2654A7A42FD9AB6BFA4AC4D481D390BB229B064BDC311CC1BE1B63189" +
+ "DA7C40CDECF2B102818100EA1A742DDB881CEDB7288C87E38D868DD7A409D15A43F445D5" +
+ "377A0B5731DDBFCA2DAF28A8E13CD5C0AFCEC3347D74A39E235A3CD9633F274DE2B94F92" +
+ "DF43833911D9E9F1CF58F27DE2E08FF45964C720D3EC2139DC7CAFC912953CDECB2F355A" +
+ "2E2C35A50FAD754CB3B23166424BA3B6E3112A2B898C38C5C15EDB238693390281805182" +
+ "8F1EC6FD996029901BAF1D7E337BA5F0AF27E984EAD895ACE62BD7DF4EE45A224089F2CC" +
+ "151AF3CD173FCE0474BCB04F386A2CDCC0E0036BA2419F54579262D47100BE931984A3EF" +
+ "A05BECF141574DC079B3A95C4A83E6C43F3214D6DF32D512DE198085E531E616B83FD7DD" +
+ "9D1F4E2607C3333D07C55D107D1D3893587102818100DB4FB50F50DE8EDB53FF34C80931" +
+ "88A0512867DA2CCA04897759E587C244010DAF8664D59E8083D16C164789301F67A9F078" +
+ "060D834A2ADBD367575B68A8A842C2B02A89B3F31FCCEC8A22FE395795C5C6C7422B4E5D" +
+ "74A1E9A8F30E7759B9FC2D639C1F15673E84E93A5EF1506F4315383C38D45CBD1B14048F" +
+ "4721DC82326102818100D8114593AF415FB612DBF1923710D54D07486205A76A3B431949" +
+ "68C0DFF1F11EF0F61A4A337D5FD3741BBC9640E447B8B6B6C47C3AC1204357D3B0C55BA9" +
+ "286BDA73F629296F5FA9146D8976357D3C751E75148696A40B74685C82CE30902D639D72" +
+ "4FF24D5E2E9407EE34EDED2E3B4DF65AA9BCFEB6DF28D07BA6903F165768");
+
+
+ private static byte[] hexToBytes(String s) {
+ int len = s.length();
+ byte[] data = new byte[len / 2];
+ for (int i = 0; i < len; i += 2) {
+ data[i / 2] = (byte) ((Character.digit(s.charAt(i), 16) << 4) + Character.digit(
+ s.charAt(i + 1), 16));
+ }
+ return data;
+ }
+
@Override
protected void setUp() throws Exception {
mKeyStore = KeyStore.getInstance();
if (mKeyStore.state() != KeyStore.State.UNINITIALIZED) {
mKeyStore.reset();
}
- assertEquals(KeyStore.State.UNINITIALIZED, mKeyStore.state());
+ assertEquals("KeyStore should be in an uninitialized state",
+ KeyStore.State.UNINITIALIZED, mKeyStore.state());
super.setUp();
}
@@ -164,4 +218,183 @@
mKeyStore.reset();
assertTrue(mKeyStore.isEmpty());
}
+
+ public void testGenerate_NotInitialized_Fail() throws Exception {
+ assertFalse("Should fail when keystore is not initialized",
+ mKeyStore.generate(TEST_KEYNAME));
+ }
+
+ public void testGenerate_Locked_Fail() throws Exception {
+ mKeyStore.password(TEST_PASSWD);
+ mKeyStore.lock();
+ assertFalse("Should fail when keystore is locked", mKeyStore.generate(TEST_KEYNAME));
+ }
+
+ public void testGenerate_Success() throws Exception {
+ mKeyStore.password(TEST_PASSWD);
+
+ assertTrue("Should be able to generate key when unlocked",
+ mKeyStore.generate(TEST_KEYNAME));
+ }
+
+ public void testImport_Success() throws Exception {
+ mKeyStore.password(TEST_PASSWD);
+
+ assertTrue("Should be able to import key when unlocked",
+ mKeyStore.importKey(TEST_KEYNAME, PRIVKEY_BYTES));
+ }
+
+ public void testImport_Failure_BadEncoding() throws Exception {
+ mKeyStore.password(TEST_PASSWD);
+
+ assertFalse("Invalid DER-encoded key should not be imported",
+ mKeyStore.importKey(TEST_KEYNAME, TEST_DATA));
+ }
+
+ public void testSign_Success() throws Exception {
+ mKeyStore.password(TEST_PASSWD);
+
+ assertTrue(mKeyStore.generate(TEST_KEYNAME));
+ final byte[] signature = mKeyStore.sign(TEST_KEYNAME, TEST_DATA);
+
+ assertNotNull("Signature should not be null", signature);
+ }
+
+ public void testVerify_Success() throws Exception {
+ mKeyStore.password(TEST_PASSWD);
+
+ assertTrue(mKeyStore.generate(TEST_KEYNAME));
+ final byte[] signature = mKeyStore.sign(TEST_KEYNAME, TEST_DATA);
+
+ assertNotNull("Signature should not be null", signature);
+
+ assertTrue("Signature should verify with same data",
+ mKeyStore.verify(TEST_KEYNAME, TEST_DATA, signature));
+ }
+
+ public void testSign_NotInitialized_Failure() throws Exception {
+ assertNull("Should not be able to sign without first initializing the keystore",
+ mKeyStore.sign(TEST_KEYNAME, TEST_DATA));
+ }
+
+ public void testSign_NotGenerated_Failure() throws Exception {
+ mKeyStore.password(TEST_PASSWD);
+
+ assertNull("Should not be able to sign without first generating keys",
+ mKeyStore.sign(TEST_KEYNAME, TEST_DATA));
+ }
+
+ public void testGrant_Generated_Success() throws Exception {
+ assertTrue("Password should work for keystore",
+ mKeyStore.password(TEST_PASSWD));
+
+ assertTrue("Should be able to generate key for testcase",
+ mKeyStore.generate(TEST_KEYNAME));
+
+ assertTrue("Should be able to grant key to other user",
+ mKeyStore.grant(TEST_KEYNAME, 0));
+ }
+
+ public void testGrant_Imported_Success() throws Exception {
+ assertTrue("Password should work for keystore", mKeyStore.password(TEST_PASSWD));
+
+ assertTrue("Should be able to import key for testcase",
+ mKeyStore.importKey(TEST_KEYNAME, PRIVKEY_BYTES));
+
+ assertTrue("Should be able to grant key to other user", mKeyStore.grant(TEST_KEYNAME, 0));
+ }
+
+ public void testGrant_NoKey_Failure() throws Exception {
+ assertTrue("Should be able to unlock keystore for test",
+ mKeyStore.password(TEST_PASSWD));
+
+ assertFalse("Should not be able to grant without first initializing the keystore",
+ mKeyStore.grant(TEST_KEYNAME, 0));
+ }
+
+ public void testGrant_NotInitialized_Failure() throws Exception {
+ assertFalse("Should not be able to grant without first initializing the keystore",
+ mKeyStore.grant(TEST_KEYNAME, 0));
+ }
+
+ public void testUngrant_Generated_Success() throws Exception {
+ assertTrue("Password should work for keystore",
+ mKeyStore.password(TEST_PASSWD));
+
+ assertTrue("Should be able to generate key for testcase",
+ mKeyStore.generate(TEST_KEYNAME));
+
+ assertTrue("Should be able to grant key to other user",
+ mKeyStore.grant(TEST_KEYNAME, 0));
+
+ assertTrue("Should be able to ungrant key to other user",
+ mKeyStore.ungrant(TEST_KEYNAME, 0));
+ }
+
+ public void testUngrant_Imported_Success() throws Exception {
+ assertTrue("Password should work for keystore",
+ mKeyStore.password(TEST_PASSWD));
+
+ assertTrue("Should be able to import key for testcase",
+ mKeyStore.importKey(TEST_KEYNAME, PRIVKEY_BYTES));
+
+ assertTrue("Should be able to grant key to other user",
+ mKeyStore.grant(TEST_KEYNAME, 0));
+
+ assertTrue("Should be able to ungrant key to other user",
+ mKeyStore.ungrant(TEST_KEYNAME, 0));
+ }
+
+ public void testUngrant_NotInitialized_Failure() throws Exception {
+ assertFalse("Should fail to ungrant key when keystore not initialized",
+ mKeyStore.ungrant(TEST_KEYNAME, 0));
+ }
+
+ public void testUngrant_NoGrant_Failure() throws Exception {
+ assertTrue("Password should work for keystore",
+ mKeyStore.password(TEST_PASSWD));
+
+ assertTrue("Should be able to generate key for testcase",
+ mKeyStore.generate(TEST_KEYNAME));
+
+ assertFalse("Should not be able to revoke not existent grant",
+ mKeyStore.ungrant(TEST_KEYNAME, 0));
+ }
+
+ public void testUngrant_DoubleUngrant_Failure() throws Exception {
+ assertTrue("Password should work for keystore",
+ mKeyStore.password(TEST_PASSWD));
+
+ assertTrue("Should be able to generate key for testcase",
+ mKeyStore.generate(TEST_KEYNAME));
+
+ assertTrue("Should be able to grant key to other user",
+ mKeyStore.grant(TEST_KEYNAME, 0));
+
+ assertTrue("Should be able to ungrant key to other user",
+ mKeyStore.ungrant(TEST_KEYNAME, 0));
+
+ assertFalse("Should fail to ungrant key to other user second time",
+ mKeyStore.ungrant(TEST_KEYNAME, 0));
+ }
+
+ public void testUngrant_DoubleGrantUngrant_Failure() throws Exception {
+ assertTrue("Password should work for keystore",
+ mKeyStore.password(TEST_PASSWD));
+
+ assertTrue("Should be able to generate key for testcase",
+ mKeyStore.generate(TEST_KEYNAME));
+
+ assertTrue("Should be able to grant key to other user",
+ mKeyStore.grant(TEST_KEYNAME, 0));
+
+ assertTrue("Should be able to grant key to other user a second time",
+ mKeyStore.grant(TEST_KEYNAME, 0));
+
+ assertTrue("Should be able to ungrant key to other user",
+ mKeyStore.ungrant(TEST_KEYNAME, 0));
+
+ assertFalse("Should fail to ungrant key to other user second time",
+ mKeyStore.ungrant(TEST_KEYNAME, 0));
+ }
}
diff --git a/wifi/java/android/net/wifi/WifiConfigStore.java b/wifi/java/android/net/wifi/WifiConfigStore.java
index 5dec269..a9dbd10 100644
--- a/wifi/java/android/net/wifi/WifiConfigStore.java
+++ b/wifi/java/android/net/wifi/WifiConfigStore.java
@@ -25,6 +25,7 @@
import android.net.NetworkInfo.DetailedState;
import android.net.ProxyProperties;
import android.net.RouteInfo;
+import android.net.wifi.WifiConfiguration.EnterpriseField;
import android.net.wifi.WifiConfiguration.IpAssignment;
import android.net.wifi.WifiConfiguration.KeyMgmt;
import android.net.wifi.WifiConfiguration.ProxySettings;
@@ -1140,7 +1141,7 @@
String varName = field.varName();
String value = field.value();
if (value != null) {
- if (field != config.eap) {
+ if (field != config.eap && field != config.engine) {
value = (value.length() == 0) ? "NULL" : convertToQuotedString(value);
}
if (!mWifiNative.setNetworkVariable(
@@ -1449,10 +1450,68 @@
value = mWifiNative.getNetworkVariable(netId,
field.varName());
if (!TextUtils.isEmpty(value)) {
- if (field != config.eap) value = removeDoubleQuotes(value);
+ if (field != config.eap && field != config.engine) {
+ value = removeDoubleQuotes(value);
+ }
field.setValue(value);
}
}
+
+ migrateOldEapTlsIfNecessary(config, netId);
+ }
+
+ /**
+ * Migration code for old EAP-TLS configurations. This should only be used
+ * when restoring an old wpa_supplicant.conf or upgrading from a previous
+ * platform version.
+ *
+ * @param config the configuration to be migrated
+ * @param netId the wpa_supplicant's net ID
+ * @param value the old private_key value
+ */
+ private void migrateOldEapTlsIfNecessary(WifiConfiguration config, int netId) {
+ String value = mWifiNative.getNetworkVariable(netId,
+ WifiConfiguration.OLD_PRIVATE_KEY_NAME);
+ /*
+ * If the old configuration value is not present, then there is nothing
+ * to do.
+ */
+ if (TextUtils.isEmpty(value)) {
+ return;
+ } else {
+ // Also ignore it if it's empty quotes.
+ value = removeDoubleQuotes(value);
+ if (TextUtils.isEmpty(value)) {
+ return;
+ }
+ }
+
+ config.engine.setValue(WifiConfiguration.ENGINE_ENABLE);
+ config.engine_id.setValue(convertToQuotedString(WifiConfiguration.KEYSTORE_ENGINE_ID));
+
+ /*
+ * The old key started with the keystore:// URI prefix, but we don't
+ * need that anymore. Trim it off if it exists.
+ */
+ final String keyName;
+ if (value.startsWith(WifiConfiguration.KEYSTORE_URI)) {
+ keyName = new String(value.substring(WifiConfiguration.KEYSTORE_URI.length()));
+ } else {
+ keyName = value;
+ }
+ config.key_id.setValue(convertToQuotedString(keyName));
+
+ // Now tell the wpa_supplicant the new configuration values.
+ final EnterpriseField needsUpdate[] = { config.engine, config.engine_id, config.key_id };
+ for (EnterpriseField field : needsUpdate) {
+ mWifiNative.setNetworkVariable(netId, field.varName(), field.value());
+ }
+
+ // Remove old private_key string so we don't run this again.
+ mWifiNative.setNetworkVariable(netId, WifiConfiguration.OLD_PRIVATE_KEY_NAME,
+ convertToQuotedString(""));
+
+ saveConfig();
}
private String removeDoubleQuotes(String string) {
diff --git a/wifi/java/android/net/wifi/WifiConfiguration.java b/wifi/java/android/net/wifi/WifiConfiguration.java
index 85a6f27..dfc1b18 100644
--- a/wifi/java/android/net/wifi/WifiConfiguration.java
+++ b/wifi/java/android/net/wifi/WifiConfiguration.java
@@ -29,6 +29,33 @@
*/
public class WifiConfiguration implements Parcelable {
+ /**
+ * In old configurations, the "private_key" field was used. However, newer
+ * configurations use the key_id field with the engine_id set to "keystore".
+ * If this field is found in the configuration, the migration code is
+ * triggered.
+ * @hide
+ */
+ public static final String OLD_PRIVATE_KEY_NAME = "private_key";
+
+ /**
+ * String representing the keystore OpenSSL ENGINE's ID.
+ * @hide
+ */
+ public static final String KEYSTORE_ENGINE_ID = "keystore";
+
+ /**
+ * String representing the keystore URI used for wpa_supplicant.
+ * @hide
+ */
+ public static final String KEYSTORE_URI = "keystore://";
+
+ /**
+ * String to set the engine value to when it should be enabled.
+ * @hide
+ */
+ public static final String ENGINE_ENABLE = "1";
+
/** {@hide} */
public static final String ssidVarName = "ssid";
/** {@hide} */
@@ -82,14 +109,18 @@
/** {@hide} */
public EnterpriseField client_cert = new EnterpriseField("client_cert");
/** {@hide} */
- public EnterpriseField private_key = new EnterpriseField("private_key");
+ public EnterpriseField engine = new EnterpriseField("engine");
+ /** {@hide} */
+ public EnterpriseField engine_id = new EnterpriseField("engine_id");
+ /** {@hide} */
+ public EnterpriseField key_id = new EnterpriseField("key_id");
/** {@hide} */
public EnterpriseField ca_cert = new EnterpriseField("ca_cert");
/** {@hide} */
public EnterpriseField[] enterpriseFields = {
eap, phase2, identity, anonymous_identity, password, client_cert,
- private_key, ca_cert };
+ engine, engine_id, key_id, ca_cert };
/**
* Recognized key management schemes.