am 3d25b314: Implement CACert retrieval in KeyChainService

* commit '3d25b3144669ceb787dfd00f1e312516c8fe6173':
  Implement CACert retrieval in KeyChainService
diff --git a/src/com/android/keychain/KeyChainService.java b/src/com/android/keychain/KeyChainService.java
index 6e77357..58531ac 100644
--- a/src/com/android/keychain/KeyChainService.java
+++ b/src/com/android/keychain/KeyChainService.java
@@ -21,6 +21,7 @@
 import android.content.Context;
 import android.content.Intent;
 import android.content.pm.PackageManager;
+import android.content.pm.ParceledListSlice;
 import android.database.Cursor;
 import android.database.DatabaseUtils;
 import android.database.sqlite.SQLiteDatabase;
@@ -35,11 +36,17 @@
 import android.security.KeyChain;
 import android.security.KeyStore;
 import android.util.Log;
+import com.android.internal.util.ParcelableString;
 import java.io.ByteArrayInputStream;
 import java.io.IOException;
 import java.security.cert.CertificateException;
+import java.security.cert.CertificateEncodingException;
 import java.security.cert.CertificateFactory;
 import java.security.cert.X509Certificate;
+import java.util.Set;
+import java.util.List;
+import java.util.ArrayList;
+import java.util.Collections;
 
 import com.android.org.conscrypt.TrustedCertificateStore;
 
@@ -229,6 +236,82 @@
             setGrantInternal(mDatabaseHelper.getWritableDatabase(), uid, alias, value);
             broadcastStorageChange();
         }
+
+        private ParceledListSlice<ParcelableString> makeAliasesParcelableSynchronised(
+                Set<String> aliasSet) {
+            List<ParcelableString> aliases = new ArrayList<ParcelableString>(aliasSet.size());
+            for (String alias : aliasSet) {
+                ParcelableString parcelableString = new ParcelableString();
+                parcelableString.string = alias;
+                aliases.add(parcelableString);
+            }
+            return new ParceledListSlice<ParcelableString>(aliases);
+        }
+
+        @Override
+        public ParceledListSlice<ParcelableString> getUserCaAliases() {
+            synchronized (mTrustedCertificateStore) {
+                Set<String> aliasSet = mTrustedCertificateStore.userAliases();
+                return makeAliasesParcelableSynchronised(aliasSet);
+            }
+        }
+
+        @Override
+        public ParceledListSlice<ParcelableString> getSystemCaAliases() {
+            synchronized (mTrustedCertificateStore) {
+                Set<String> aliasSet = mTrustedCertificateStore.allSystemAliases();
+                return makeAliasesParcelableSynchronised(aliasSet);
+            }
+        }
+
+        @Override
+        public boolean containsCaAlias(String alias) {
+            return mTrustedCertificateStore.containsAlias(alias);
+        }
+
+        @Override
+        public byte[] getEncodedCaCertificate(String alias, boolean includeDeletedSystem) {
+            synchronized (mTrustedCertificateStore) {
+                X509Certificate certificate = (X509Certificate) mTrustedCertificateStore
+                        .getCertificate(alias, includeDeletedSystem);
+                if (certificate == null) {
+                    Log.w(TAG, "Could not find CA certificate " + alias);
+                    return null;
+                }
+                try {
+                    return certificate.getEncoded();
+                } catch (CertificateEncodingException e) {
+                    Log.w(TAG, "Error while encoding CA certificate " + alias);
+                    return null;
+                }
+            }
+        }
+
+        @Override
+        public List<String> getCaCertificateChainAliases(String rootAlias,
+                boolean includeDeletedSystem) {
+            synchronized (mTrustedCertificateStore) {
+                X509Certificate root = (X509Certificate) mTrustedCertificateStore.getCertificate(
+                        rootAlias, includeDeletedSystem);
+                try {
+                    List<X509Certificate> chain = mTrustedCertificateStore.getCertificateChain(
+                            root);
+                    List<String> aliases = new ArrayList<String>(chain.size());
+                    final int n = chain.size();
+                    for (int i = 0; i < n; ++i) {
+                        String alias = mTrustedCertificateStore.getCertificateAlias(chain.get(i),
+                                true);
+                        if (alias != null) {
+                            aliases.add(alias);
+                        }
+                    }
+                    return aliases;
+                } catch (CertificateException e) {
+                    Log.w(TAG, "Error retrieving cert chain for root " + rootAlias);
+                    return Collections.emptyList();
+                }
+            }
+        }
     };
 
     private boolean hasGrantInternal(final SQLiteDatabase db, final int uid, final String alias) {