Merge "Modify AttestationUtils to use public Keystore API" am: 7a46c3c1fd am: a1d687e0e5 am: 0ce87eacbb

Original change: https://android-review.googlesource.com/c/platform/frameworks/base/+/1622922

MUST ONLY BE SUBMITTED BY AUTOMERGER

Change-Id: I6e7fab5ec09589a2fc5da0548f5f2a48e7130baf
This commit is contained in:
Janis Danisevskis
2021-03-11 08:13:02 +00:00
committed by Automerger Merge Worker

View File

@@ -22,7 +22,6 @@ import android.annotation.RequiresPermission;
import android.annotation.SystemApi;
import android.content.Context;
import android.os.Build;
import android.security.KeyStore;
import android.security.keymaster.KeymasterArguments;
import android.security.keymaster.KeymasterCertificateChain;
import android.security.keymaster.KeymasterDefs;
@@ -32,9 +31,14 @@ import android.util.ArraySet;
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;
/**
@@ -223,24 +227,49 @@ public abstract class AttestationUtils {
@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