Keystore 2.0: Make CertinstallerHelper use public keystore API.
Also VpnFacade.java uses LegacyVpnStore instead of Keystore.
Test: N/A
Bug: 171305607
Merged-In: I8daa1a4d0e1a441f23776cee421842f14ff32359
Change-Id: I8daa1a4d0e1a441f23776cee421842f14ff32359
diff --git a/Common/src/com/googlecode/android_scripting/facade/CertInstallerHelper.java b/Common/src/com/googlecode/android_scripting/facade/CertInstallerHelper.java
index 99c7ddf..d3d69c0 100644
--- a/Common/src/com/googlecode/android_scripting/facade/CertInstallerHelper.java
+++ b/Common/src/com/googlecode/android_scripting/facade/CertInstallerHelper.java
@@ -17,8 +17,6 @@
package com.googlecode.android_scripting.facade;
import android.os.Environment;
-import android.security.Credentials;
-import android.security.KeyStore;
import android.util.Log;
import com.android.internal.net.VpnProfile;
@@ -27,23 +25,23 @@
import com.android.internal.org.bouncycastle.asn1.DEROctetString;
import com.android.internal.org.bouncycastle.asn1.x509.BasicConstraints;
-import junit.framework.Assert;
-
import libcore.io.Streams;
+import junit.framework.Assert;
+
import java.io.ByteArrayInputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStream;
-import java.security.KeyStoreException;
-import java.security.NoSuchAlgorithmException;
+import java.security.KeyStore;
import java.security.KeyStore.PasswordProtection;
import java.security.KeyStore.PrivateKeyEntry;
+import java.security.KeyStoreException;
+import java.security.NoSuchAlgorithmException;
import java.security.PrivateKey;
import java.security.UnrecoverableEntryException;
import java.security.cert.Certificate;
-import java.security.cert.CertificateEncodingException;
import java.security.cert.CertificateException;
import java.security.cert.X509Certificate;
import java.util.ArrayList;
@@ -58,21 +56,27 @@
public class CertInstallerHelper {
private static final String TAG = "CertInstallerHelper";
/* Define a password to unlock keystore after it is reset */
- private static final String CERT_STORE_PASSWORD = "password";
- private final int mUid = KeyStore.UID_SELF;
private PrivateKey mUserKey; // private key
private X509Certificate mUserCert; // user certificate
private List<X509Certificate> mCaCerts = new ArrayList<X509Certificate>();
- private KeyStore mKeyStore = KeyStore.getInstance();
+ private final KeyStore mKeyStore;
/**
- * Unlock keystore and set password
+ * Delete all key for caller.
*/
public CertInstallerHelper() {
- for (String key : mKeyStore.list("")) {
- mKeyStore.delete(key, KeyStore.UID_SELF);
+ try {
+ mKeyStore = KeyStore.getInstance("AndroidKeyStore");
+ mKeyStore.load(null);
+ final Enumeration<String> aliases = mKeyStore.aliases();
+ while (aliases.hasMoreElements()) {
+ mKeyStore.deleteEntry(aliases.nextElement());
+ }
+ } catch (KeyStoreException | CertificateException | NoSuchAlgorithmException
+ | IOException e) {
+ Log.e(TAG, "Failed to open and cleanup Keystore.", e);
+ throw new RuntimeException("Failed to open and cleanup Keystore.", e);
}
- mKeyStore.onUserPasswordChanged(CERT_STORE_PASSWORD);
}
private void extractCertificate(String certFile, String password) {
@@ -166,7 +170,7 @@
/**
* Extract certificate from the given file, and install it to keystore
- * @param name certificate name
+ * @param profile VpnProfile
* @param certFile .p12 file which includes certificates
* @param password password to extract the .p12 file
*/
@@ -174,51 +178,39 @@
// extract private keys, certificates from the provided file
extractCertificate(certFile, password);
// install certificate to the keystore
- int flags = KeyStore.FLAG_ENCRYPTED;
try {
+ boolean caInstalledWithUserKey = false;
+
if (mUserKey != null) {
Log.v(TAG, "has private key");
- String key = Credentials.USER_PRIVATE_KEY + profile.ipsecUserCert;
- byte[] value = mUserKey.getEncoded();
-
- if (!mKeyStore.importKey(key, value, mUid, flags)) {
- Log.e(TAG, "Failed to install " + key + " as user " + mUid);
- return;
+ if (mUserCert == null) {
+ throw new AssertionError("Must have user cert if user key is installed.");
}
- Log.v(TAG, "install " + key + " as user " + mUid + " is successful");
+ final List<Certificate> certChain = new ArrayList<Certificate>();
+ certChain.add(mUserCert);
+ if (profile.ipsecUserCert.equals(profile.ipsecCaCert)) {
+ // If the CA certs should be installed under the same alias they have to be
+ // added to the end of the certificate chain.
+ certChain.addAll(mCaCerts);
+ // Make a note that we have installed the CA cert chain along with the
+ // user key and cert.
+ caInstalledWithUserKey = true;
+ }
+ mKeyStore.setKeyEntry(profile.ipsecUserCert, mUserKey, null,
+ certChain.toArray(new Certificate[0]));
+ Log.v(TAG, "install " + profile.ipsecUserCert + " is successful");
}
- if (mUserCert != null) {
- String certName = Credentials.USER_CERTIFICATE + profile.ipsecUserCert;
- byte[] certData = Credentials.convertToPem(mUserCert);
-
- if (!mKeyStore.put(certName, certData, mUid, flags)) {
- Log.e(TAG, "Failed to install " + certName + " as user " + mUid);
- return;
+ if (!(mCaCerts.isEmpty() || caInstalledWithUserKey)) {
+ if (mCaCerts.size() != 1) {
+ throw new AssertionError("Trusted certificate cannot be a cert chain.");
}
- Log.v(TAG, "install " + certName + " as user" + mUid + " is successful.");
+ mKeyStore.setCertificateEntry(profile.ipsecCaCert, mCaCerts.get(0));
+ Log.v(TAG, " install " + profile.ipsecCaCert + " is successful");
}
-
- if (!mCaCerts.isEmpty()) {
- String caListName = Credentials.CA_CERTIFICATE + profile.ipsecCaCert;
- X509Certificate[] caCerts = mCaCerts.toArray(new X509Certificate[mCaCerts.size()]);
- byte[] caListData = Credentials.convertToPem(caCerts);
-
- if (!mKeyStore.put(caListName, caListData, mUid, flags)) {
- Log.e(TAG, "Failed to install " + caListName + " as user " + mUid);
- return;
- }
- Log.v(TAG, " install " + caListName + " as user " + mUid + " is successful");
- }
- } catch (CertificateEncodingException e) {
- Log.e(TAG, "Exception while convert certificates to pem " + e);
+ } catch (KeyStoreException e) {
+ Log.e(TAG, "Exception trying to import certificates. " + e);
throw new AssertionError(e);
- } catch (IOException e) {
- Log.e(TAG, "IOException while convert to pem: " + e);
}
}
-
- public int getUid() {
- return mUid;
- }
}
diff --git a/Common/src/com/googlecode/android_scripting/facade/VpnFacade.java b/Common/src/com/googlecode/android_scripting/facade/VpnFacade.java
index e0f4299..bed8cc8 100644
--- a/Common/src/com/googlecode/android_scripting/facade/VpnFacade.java
+++ b/Common/src/com/googlecode/android_scripting/facade/VpnFacade.java
@@ -16,10 +16,12 @@
package com.googlecode.android_scripting.facade;
-import java.util.ArrayList;
-import java.util.List;
-
-import org.json.JSONObject;
+import android.app.Service;
+import android.net.VpnManager;
+import android.os.RemoteException;
+import android.security.Credentials;
+import android.security.KeyStore;
+import android.security.LegacyVpnProfileStore;
import com.android.internal.net.LegacyVpnInfo;
import com.android.internal.net.VpnConfig;
@@ -31,11 +33,10 @@
import com.googlecode.android_scripting.rpc.Rpc;
import com.googlecode.android_scripting.rpc.RpcParameter;
-import android.app.Service;
-import android.net.VpnManager;
-import android.os.RemoteException;
-import android.security.Credentials;
-import android.security.KeyStore;
+import org.json.JSONObject;
+
+import java.util.ArrayList;
+import java.util.List;
/**
* Access VPN functions.
@@ -56,8 +57,9 @@
static List<VpnProfile> loadVpnProfiles(KeyStore keyStore, int... excludeTypes) {
final ArrayList<VpnProfile> result = Lists.newArrayList();
- for (String key : keyStore.list(Credentials.VPN)) {
- final VpnProfile profile = VpnProfile.decode(key, keyStore.get(Credentials.VPN + key));
+ for (String key : LegacyVpnProfileStore.list(Credentials.VPN)) {
+ final VpnProfile profile = VpnProfile.decode(key,
+ LegacyVpnProfileStore.get(Credentials.VPN + key));
if (profile != null && !ArrayUtils.contains(excludeTypes, profile.type)) {
result.add(profile);
}