Merge "Attest device base properties"

This commit is contained in:
Dorin Drimus
2020-05-18 09:46:48 +00:00
committed by Gerrit Code Review
4 changed files with 78 additions and 5 deletions

View File

@@ -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);

View File

@@ -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));

View File

@@ -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,

View File

@@ -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,