diff options
author | Janis Danisevskis <jdanis@google.com> | 2021-03-11 06:47:41 +0000 |
---|---|---|
committer | Gerrit Code Review <noreply-gerritcodereview@google.com> | 2021-03-11 06:47:41 +0000 |
commit | 7a46c3c1fdac37255d84316e860cfa09503ca0a3 (patch) | |
tree | 00f19c76c23e593b7cd2f551f43b2e1298b24739 | |
parent | 6c165b2da9b7bd8e4c9726d6b57568789164a1fa (diff) | |
parent | 0306b1ced8325ebb4d7e3b31bd1e183e88a21688 (diff) |
Merge "Modify AttestationUtils to use public Keystore API"
-rw-r--r-- | keystore/java/android/security/keystore/AttestationUtils.java | 53 |
1 files changed, 41 insertions, 12 deletions
diff --git a/keystore/java/android/security/keystore/AttestationUtils.java b/keystore/java/android/security/keystore/AttestationUtils.java index f1eea820829c..11c36893d984 100644 --- a/keystore/java/android/security/keystore/AttestationUtils.java +++ b/keystore/java/android/security/keystore/AttestationUtils.java @@ -23,7 +23,6 @@ import android.annotation.SystemApi; 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 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; /** @@ -256,22 +260,47 @@ 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(); } /** |