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

Commit 547aeb27 authored by Dorin Drimus's avatar Dorin Drimus Committed by Gerrit Code Review
Browse files

Merge "Attest device base properties"

parents 2b0ac97d 9d5b804e
Loading
Loading
Loading
Loading
+2 −0
Original line number Diff line number Diff line
@@ -41304,6 +41304,7 @@ package android.security.keystore {
    method public int getPurposes();
    method @NonNull public String[] getSignaturePaddings();
    method public int getUserAuthenticationValidityDurationSeconds();
    method public boolean isDevicePropertiesAttestationIncluded();
    method @NonNull public boolean isDigestsSpecified();
    method public boolean isInvalidatedByBiometricEnrollment();
    method public boolean isRandomizedEncryptionRequired();
@@ -41325,6 +41326,7 @@ package android.security.keystore {
    method @NonNull public android.security.keystore.KeyGenParameterSpec.Builder setCertificateNotBefore(@NonNull java.util.Date);
    method @NonNull public android.security.keystore.KeyGenParameterSpec.Builder setCertificateSerialNumber(@NonNull java.math.BigInteger);
    method @NonNull public android.security.keystore.KeyGenParameterSpec.Builder setCertificateSubject(@NonNull javax.security.auth.x500.X500Principal);
    method @NonNull public android.security.keystore.KeyGenParameterSpec.Builder setDevicePropertiesAttestationIncluded(boolean);
    method @NonNull public android.security.keystore.KeyGenParameterSpec.Builder setDigests(java.lang.String...);
    method @NonNull public android.security.keystore.KeyGenParameterSpec.Builder setEncryptionPaddings(java.lang.String...);
    method @NonNull public android.security.keystore.KeyGenParameterSpec.Builder setInvalidatedByBiometricEnrollment(boolean);
+24 −4
Original line number Diff line number Diff line
@@ -17,11 +17,10 @@
package android.security.keystore;

import android.annotation.Nullable;
import android.os.Build;
import android.security.Credentials;
import android.security.GateKeeper;
import android.security.KeyPairGeneratorSpec;
import android.security.KeyStore;
import android.security.KeyStoreException;
import android.security.keymaster.KeyCharacteristics;
import android.security.keymaster.KeymasterArguments;
import android.security.keymaster.KeymasterCertificateChain;
@@ -52,6 +51,7 @@ import libcore.util.EmptyArray;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.math.BigInteger;
import java.nio.charset.StandardCharsets;
import java.security.InvalidAlgorithmParameterException;
import java.security.KeyPair;
import java.security.KeyPairGenerator;
@@ -494,6 +494,20 @@ public abstract class AndroidKeyStoreKeyPairGeneratorSpi extends KeyPairGenerato
        if (challenge != null) {
            KeymasterArguments args = new KeymasterArguments();
            args.addBytes(KeymasterDefs.KM_TAG_ATTESTATION_CHALLENGE, challenge);

            if (mSpec.isDevicePropertiesAttestationIncluded()) {
                args.addBytes(KeymasterDefs.KM_TAG_ATTESTATION_ID_BRAND,
                        Build.BRAND.getBytes(StandardCharsets.UTF_8));
                args.addBytes(KeymasterDefs.KM_TAG_ATTESTATION_ID_DEVICE,
                        Build.DEVICE.getBytes(StandardCharsets.UTF_8));
                args.addBytes(KeymasterDefs.KM_TAG_ATTESTATION_ID_PRODUCT,
                        Build.PRODUCT.getBytes(StandardCharsets.UTF_8));
                args.addBytes(KeymasterDefs.KM_TAG_ATTESTATION_ID_MANUFACTURER,
                        Build.MANUFACTURER.getBytes(StandardCharsets.UTF_8));
                args.addBytes(KeymasterDefs.KM_TAG_ATTESTATION_ID_MODEL,
                        Build.MODEL.getBytes(StandardCharsets.UTF_8));
            }

            return getAttestationChain(privateKeyAlias, keyPair, args);
        }

@@ -603,8 +617,14 @@ public abstract class AndroidKeyStoreKeyPairGeneratorSpi extends KeyPairGenerato
    private Iterable<byte[]> getAttestationChain(String privateKeyAlias,
            KeyPair keyPair, KeymasterArguments args)
                    throws ProviderException {
        KeymasterCertificateChain outChain = new KeymasterCertificateChain();
        int errorCode = mKeyStore.attestKey(privateKeyAlias, args, outChain);
        final KeymasterCertificateChain outChain = new KeymasterCertificateChain();
        final int errorCode;
        if (mSpec.isDevicePropertiesAttestationIncluded()
                && mSpec.getAttestationChallenge() == null) {
            throw new ProviderException("An attestation challenge must be provided when requesting "
                    + "device properties attestation.");
        }
        errorCode = mKeyStore.attestKey(privateKeyAlias, args, outChain);
        if (errorCode != KeyStore.NO_ERROR) {
            throw new ProviderException("Failed to generate attestation certificate chain",
                    KeyStore.getKeyStoreException(errorCode));
+48 −0
Original line number Diff line number Diff line
@@ -24,6 +24,7 @@ import android.app.KeyguardManager;
import android.compat.annotation.UnsupportedAppUsage;
import android.hardware.biometrics.BiometricManager;
import android.hardware.biometrics.BiometricPrompt;
import android.os.Build;
import android.security.GateKeeper;
import android.security.KeyStore;
import android.text.TextUtils;
@@ -264,6 +265,7 @@ public final class KeyGenParameterSpec implements AlgorithmParameterSpec, UserAu
    private final int mUserAuthenticationValidityDurationSeconds;
    private final boolean mUserPresenceRequired;
    private final byte[] mAttestationChallenge;
    private final boolean mDevicePropertiesAttestationIncluded;
    private final boolean mUniqueIdIncluded;
    private final boolean mUserAuthenticationValidWhileOnBody;
    private final boolean mInvalidatedByBiometricEnrollment;
@@ -301,6 +303,7 @@ public final class KeyGenParameterSpec implements AlgorithmParameterSpec, UserAu
            int userAuthenticationValidityDurationSeconds,
            boolean userPresenceRequired,
            byte[] attestationChallenge,
            boolean devicePropertiesAttestationIncluded,
            boolean uniqueIdIncluded,
            boolean userAuthenticationValidWhileOnBody,
            boolean invalidatedByBiometricEnrollment,
@@ -350,6 +353,7 @@ public final class KeyGenParameterSpec implements AlgorithmParameterSpec, UserAu
        mUserPresenceRequired = userPresenceRequired;
        mUserAuthenticationValidityDurationSeconds = userAuthenticationValidityDurationSeconds;
        mAttestationChallenge = Utils.cloneIfNotNull(attestationChallenge);
        mDevicePropertiesAttestationIncluded = devicePropertiesAttestationIncluded;
        mUniqueIdIncluded = uniqueIdIncluded;
        mUserAuthenticationValidWhileOnBody = userAuthenticationValidWhileOnBody;
        mInvalidatedByBiometricEnrollment = invalidatedByBiometricEnrollment;
@@ -643,6 +647,21 @@ public final class KeyGenParameterSpec implements AlgorithmParameterSpec, UserAu
        return Utils.cloneIfNotNull(mAttestationChallenge);
    }

    /**
     * Returns {@code true} if attestation for the base device properties ({@link Build#BRAND},
     * {@link Build#DEVICE}, {@link Build#MANUFACTURER}, {@link Build#MODEL}, {@link Build#PRODUCT})
     * was requested to be added in the attestation certificate for the generated key.
     *
     * {@link javax.crypto.KeyGenerator#generateKey()} will throw
     * {@link java.security.ProviderException} if device properties attestation fails or is not
     * supported.
     *
     * @see Builder#setDevicePropertiesAttestationIncluded(boolean)
     */
    public boolean isDevicePropertiesAttestationIncluded() {
        return mDevicePropertiesAttestationIncluded;
    }

    /**
     * @hide This is a system-only API
     *
@@ -734,6 +753,7 @@ public final class KeyGenParameterSpec implements AlgorithmParameterSpec, UserAu
        private int mUserAuthenticationValidityDurationSeconds = -1;
        private boolean mUserPresenceRequired = false;
        private byte[] mAttestationChallenge = null;
        private boolean mDevicePropertiesAttestationIncluded = false;
        private boolean mUniqueIdIncluded = false;
        private boolean mUserAuthenticationValidWhileOnBody;
        private boolean mInvalidatedByBiometricEnrollment = true;
@@ -797,6 +817,8 @@ public final class KeyGenParameterSpec implements AlgorithmParameterSpec, UserAu
                sourceSpec.getUserAuthenticationValidityDurationSeconds();
            mUserPresenceRequired = sourceSpec.isUserPresenceRequired();
            mAttestationChallenge = sourceSpec.getAttestationChallenge();
            mDevicePropertiesAttestationIncluded =
                    sourceSpec.isDevicePropertiesAttestationIncluded();
            mUniqueIdIncluded = sourceSpec.isUniqueIdIncluded();
            mUserAuthenticationValidWhileOnBody = sourceSpec.isUserAuthenticationValidWhileOnBody();
            mInvalidatedByBiometricEnrollment = sourceSpec.isInvalidatedByBiometricEnrollment();
@@ -1251,6 +1273,31 @@ public final class KeyGenParameterSpec implements AlgorithmParameterSpec, UserAu
            return this;
        }

        /**
         * Sets whether to include the base device properties in the attestation certificate.
         *
         * <p>If {@code attestationChallenge} is not {@code null}, the public key certificate for
         * this key pair will contain an extension that describes the details of the key's
         * configuration and authorizations, including the device properties values (brand, device,
         * manufacturer, model, product). These should be the same as in ({@link Build#BRAND},
         * {@link Build#DEVICE}, {@link Build#MANUFACTURER}, {@link Build#MODEL},
         * {@link Build#PRODUCT}). The attestation certificate chain can
         * be retrieved with {@link java.security.KeyStore#getCertificateChain(String)}.
         *
         * <p> If {@code attestationChallenge} is {@code null}, the public key certificate for
         * this key pair will not contain the extension with the requested attested values.
         *
         * <p> {@link javax.crypto.KeyGenerator#generateKey()} will throw
         * {@link java.security.ProviderException} if device properties attestation fails or is not
         * supported.
         */
        @NonNull
        public Builder setDevicePropertiesAttestationIncluded(
                boolean devicePropertiesAttestationIncluded) {
            mDevicePropertiesAttestationIncluded = devicePropertiesAttestationIncluded;
            return this;
        }

        /**
         * @hide Only system apps can use this method.
         *
@@ -1360,6 +1407,7 @@ public final class KeyGenParameterSpec implements AlgorithmParameterSpec, UserAu
                    mUserAuthenticationValidityDurationSeconds,
                    mUserPresenceRequired,
                    mAttestationChallenge,
                    mDevicePropertiesAttestationIncluded,
                    mUniqueIdIncluded,
                    mUserAuthenticationValidWhileOnBody,
                    mInvalidatedByBiometricEnrollment,
+4 −1
Original line number Diff line number Diff line
@@ -16,8 +16,8 @@

package android.security.keystore;

import android.os.Parcelable;
import android.os.Parcel;
import android.os.Parcelable;

import java.math.BigInteger;
import java.security.spec.AlgorithmParameterSpec;
@@ -99,6 +99,7 @@ public final class ParcelableKeyGenParameterSpec implements Parcelable {
        out.writeInt(mSpec.getUserAuthenticationValidityDurationSeconds());
        out.writeBoolean(mSpec.isUserPresenceRequired());
        out.writeByteArray(mSpec.getAttestationChallenge());
        out.writeBoolean(mSpec.isDevicePropertiesAttestationIncluded());
        out.writeBoolean(mSpec.isUniqueIdIncluded());
        out.writeBoolean(mSpec.isUserAuthenticationValidWhileOnBody());
        out.writeBoolean(mSpec.isInvalidatedByBiometricEnrollment());
@@ -154,6 +155,7 @@ public final class ParcelableKeyGenParameterSpec implements Parcelable {
        final int userAuthenticationValidityDurationSeconds = in.readInt();
        final boolean userPresenceRequired = in.readBoolean();
        final byte[] attestationChallenge = in.createByteArray();
        final boolean devicePropertiesAttestationIncluded = in.readBoolean();
        final boolean uniqueIdIncluded = in.readBoolean();
        final boolean userAuthenticationValidWhileOnBody = in.readBoolean();
        final boolean invalidatedByBiometricEnrollment = in.readBoolean();
@@ -185,6 +187,7 @@ public final class ParcelableKeyGenParameterSpec implements Parcelable {
                userAuthenticationValidityDurationSeconds,
                userPresenceRequired,
                attestationChallenge,
                devicePropertiesAttestationIncluded,
                uniqueIdIncluded,
                userAuthenticationValidWhileOnBody,
                invalidatedByBiometricEnrollment,