Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit a1d687e0 authored by Janis Danisevskis's avatar Janis Danisevskis Committed by Automerger Merge Worker
Browse files

Merge "Modify AttestationUtils to use public Keystore API" am: 7a46c3c1

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

MUST ONLY BE SUBMITTED BY AUTOMERGER

Change-Id: I6505041a28e1aa2d1fa9bb6e64508b7090a67777
parents 98eb9af0 7a46c3c1
Loading
Loading
Loading
Loading
+41 −12
Original line number Diff line number Diff line
@@ -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();
    }

    /**