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:
@@ -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
|
||||
|
||||
Reference in New Issue
Block a user