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);
             }