Modify AttestationUtils to use public Keystore API

AttestationUtils calls directly into keystore1 to generate ID
attesations.  This needs to change prior to keystore2 being enabled
and keystore1 deleted.  This CL changes the AttestationUtils to use
the public API (and one SystemAPI method) to generate ID attestations,
allowing the lower layers to handle the transition between keystore1
and keystore2.

Test: CtsKeystoreTestCases
Change-Id: I64a230b9983cc90767a60d6e7cf2abcf5dfb0108
diff --git a/keystore/java/android/security/keystore/AttestationUtils.java b/keystore/java/android/security/keystore/AttestationUtils.java
index f1eea82..11c3689 100644
--- a/keystore/java/android/security/keystore/AttestationUtils.java
+++ b/keystore/java/android/security/keystore/AttestationUtils.java
@@ -23,7 +23,6 @@
 import android.content.Context;
 import android.content.res.Resources;
 import android.os.Build;
-import android.security.KeyStore;
 import android.security.keymaster.KeymasterArguments;
 import android.security.keymaster.KeymasterCertificateChain;
 import android.security.keymaster.KeymasterDefs;
@@ -34,9 +33,14 @@
 import java.io.ByteArrayInputStream;
 import java.io.ByteArrayOutputStream;
 import java.nio.charset.StandardCharsets;
+import java.security.KeyPairGenerator;
+import java.security.KeyStore;
+import java.security.SecureRandom;
 import java.security.cert.CertificateFactory;
 import java.security.cert.X509Certificate;
+import java.security.spec.ECGenParameterSpec;
 import java.util.Collection;
+import java.util.Random;
 import java.util.Set;
 
 /**
@@ -256,24 +260,49 @@
     @NonNull public static X509Certificate[] attestDeviceIds(Context context,
             @NonNull int[] idTypes, @NonNull byte[] attestationChallenge) throws
             DeviceIdAttestationException {
-        final KeymasterArguments attestArgs = prepareAttestationArgumentsForDeviceId(
-                context, idTypes, attestationChallenge);
+        String keystoreAlias = generateRandomAlias();
+        KeyGenParameterSpec.Builder builder =
+                new KeyGenParameterSpec.Builder(keystoreAlias, KeyProperties.PURPOSE_SIGN)
+                        .setAlgorithmParameterSpec(new ECGenParameterSpec("secp256r1"))
+                        .setDigests(KeyProperties.DIGEST_SHA256)
+                        .setAttestationChallenge(attestationChallenge);
 
-        // Perform attestation.
-        final KeymasterCertificateChain outChain = new KeymasterCertificateChain();
-        final int errorCode = KeyStore.getInstance().attestDeviceIds(attestArgs, outChain);
-        if (errorCode != KeyStore.NO_ERROR) {
-            throw new DeviceIdAttestationException("Unable to perform attestation",
-                    KeyStore.getKeyStoreException(errorCode));
+        if (idTypes != null) {
+            builder.setAttestationIds(idTypes);
+            builder.setDevicePropertiesAttestationIncluded(true);
         }
 
         try {
-            return parseCertificateChain(outChain);
-        } catch (KeyAttestationException e) {
-            throw new DeviceIdAttestationException(e.getMessage(), e);
+            KeyPairGenerator keyPairGenerator = KeyPairGenerator.getInstance(
+                    KeyProperties.KEY_ALGORITHM_EC, "AndroidKeyStore");
+            keyPairGenerator.initialize(builder.build());
+            keyPairGenerator.generateKeyPair();
+
+            KeyStore keyStore = KeyStore.getInstance("AndroidKeyStore");
+            keyStore.load(null);
+
+            X509Certificate[] certificateChain =
+                    (X509Certificate[]) keyStore.getCertificateChain(keystoreAlias);
+
+            keyStore.deleteEntry(keystoreAlias);
+
+            return certificateChain;
+        } catch (Exception e) {
+            throw new DeviceIdAttestationException("Unable to perform attestation", e);
         }
     }
 
+    private static String generateRandomAlias() {
+        Random random = new SecureRandom();
+        StringBuilder builder = new StringBuilder();
+        // Pick random uppercase letters, A-Z.  20 of them gives us ~94 bits of entropy, which
+        // should prevent any conflicts with app-selected aliases, even for very unlucky users.
+        for (int i = 0; i < 20; ++i) {
+            builder.append(random.nextInt(26) + 'A');
+        }
+        return builder.toString();
+    }
+
     /**
      * Returns true if the attestation chain provided is a valid key attestation chain.
      * @hide