Merge "Adding device ID attestation to KeyGenParameterSpec" am: 3faed136d5
Original change: https://android-review.googlesource.com/c/platform/frameworks/base/+/1554667 MUST ONLY BE SUBMITTED BY AUTOMERGER Change-Id: I2736d762f4b3675a2c6471c07ec79e0fd09c2864
This commit is contained in:
@@ -8435,10 +8435,12 @@ package android.security.keystore {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public final class KeyGenParameterSpec implements java.security.spec.AlgorithmParameterSpec {
|
public final class KeyGenParameterSpec implements java.security.spec.AlgorithmParameterSpec {
|
||||||
|
method @Nullable public int[] getAttestationIds();
|
||||||
method public int getNamespace();
|
method public int getNamespace();
|
||||||
}
|
}
|
||||||
|
|
||||||
public static final class KeyGenParameterSpec.Builder {
|
public static final class KeyGenParameterSpec.Builder {
|
||||||
|
method @NonNull public android.security.keystore.KeyGenParameterSpec.Builder setAttestationIds(@NonNull int[]);
|
||||||
method @NonNull public android.security.keystore.KeyGenParameterSpec.Builder setNamespace(int);
|
method @NonNull public android.security.keystore.KeyGenParameterSpec.Builder setNamespace(int);
|
||||||
method @Deprecated @NonNull public android.security.keystore.KeyGenParameterSpec.Builder setUid(int);
|
method @Deprecated @NonNull public android.security.keystore.KeyGenParameterSpec.Builder setUid(int);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -17,6 +17,7 @@
|
|||||||
package android.security.keystore;
|
package android.security.keystore;
|
||||||
|
|
||||||
import android.annotation.Nullable;
|
import android.annotation.Nullable;
|
||||||
|
import android.content.Context;
|
||||||
import android.os.Build;
|
import android.os.Build;
|
||||||
import android.security.Credentials;
|
import android.security.Credentials;
|
||||||
import android.security.KeyPairGeneratorSpec;
|
import android.security.KeyPairGeneratorSpec;
|
||||||
@@ -25,6 +26,8 @@ import android.security.keymaster.KeyCharacteristics;
|
|||||||
import android.security.keymaster.KeymasterArguments;
|
import android.security.keymaster.KeymasterArguments;
|
||||||
import android.security.keymaster.KeymasterCertificateChain;
|
import android.security.keymaster.KeymasterCertificateChain;
|
||||||
import android.security.keymaster.KeymasterDefs;
|
import android.security.keymaster.KeymasterDefs;
|
||||||
|
import android.telephony.TelephonyManager;
|
||||||
|
import android.util.ArraySet;
|
||||||
|
|
||||||
import com.android.internal.org.bouncycastle.asn1.ASN1EncodableVector;
|
import com.android.internal.org.bouncycastle.asn1.ASN1EncodableVector;
|
||||||
import com.android.internal.org.bouncycastle.asn1.ASN1InputStream;
|
import com.android.internal.org.bouncycastle.asn1.ASN1InputStream;
|
||||||
@@ -477,11 +480,11 @@ public abstract class AndroidKeyStoreKeyPairGeneratorSpi extends KeyPairGenerato
|
|||||||
|
|
||||||
success = true;
|
success = true;
|
||||||
return keyPair;
|
return keyPair;
|
||||||
} catch (ProviderException e) {
|
} catch (ProviderException | IllegalArgumentException | DeviceIdAttestationException e) {
|
||||||
if ((mSpec.getPurposes() & KeyProperties.PURPOSE_WRAP_KEY) != 0) {
|
if ((mSpec.getPurposes() & KeyProperties.PURPOSE_WRAP_KEY) != 0) {
|
||||||
throw new SecureKeyImportUnavailableException(e);
|
throw new SecureKeyImportUnavailableException(e);
|
||||||
} else {
|
} else {
|
||||||
throw e;
|
throw new ProviderException(e);
|
||||||
}
|
}
|
||||||
} finally {
|
} finally {
|
||||||
if (!success) {
|
if (!success) {
|
||||||
@@ -491,7 +494,7 @@ public abstract class AndroidKeyStoreKeyPairGeneratorSpi extends KeyPairGenerato
|
|||||||
}
|
}
|
||||||
|
|
||||||
private Iterable<byte[]> createCertificateChain(final String privateKeyAlias, KeyPair keyPair)
|
private Iterable<byte[]> createCertificateChain(final String privateKeyAlias, KeyPair keyPair)
|
||||||
throws ProviderException {
|
throws ProviderException, DeviceIdAttestationException {
|
||||||
byte[] challenge = mSpec.getAttestationChallenge();
|
byte[] challenge = mSpec.getAttestationChallenge();
|
||||||
if (challenge != null) {
|
if (challenge != null) {
|
||||||
KeymasterArguments args = new KeymasterArguments();
|
KeymasterArguments args = new KeymasterArguments();
|
||||||
@@ -510,6 +513,60 @@ public abstract class AndroidKeyStoreKeyPairGeneratorSpi extends KeyPairGenerato
|
|||||||
Build.MODEL.getBytes(StandardCharsets.UTF_8));
|
Build.MODEL.getBytes(StandardCharsets.UTF_8));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int[] idTypes = mSpec.getAttestationIds();
|
||||||
|
if (idTypes != null) {
|
||||||
|
final Set<Integer> idTypesSet = new ArraySet<>(idTypes.length);
|
||||||
|
for (int idType : idTypes) {
|
||||||
|
idTypesSet.add(idType);
|
||||||
|
}
|
||||||
|
TelephonyManager telephonyService = null;
|
||||||
|
if (idTypesSet.contains(AttestationUtils.ID_TYPE_IMEI)
|
||||||
|
|| idTypesSet.contains(AttestationUtils.ID_TYPE_MEID)) {
|
||||||
|
telephonyService =
|
||||||
|
(TelephonyManager) KeyStore.getApplicationContext().getSystemService(
|
||||||
|
Context.TELEPHONY_SERVICE);
|
||||||
|
if (telephonyService == null) {
|
||||||
|
throw new DeviceIdAttestationException(
|
||||||
|
"Unable to access telephony service");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
for (final Integer idType : idTypesSet) {
|
||||||
|
switch (idType) {
|
||||||
|
case AttestationUtils.ID_TYPE_SERIAL:
|
||||||
|
args.addBytes(KeymasterDefs.KM_TAG_ATTESTATION_ID_SERIAL,
|
||||||
|
Build.getSerial().getBytes(StandardCharsets.UTF_8)
|
||||||
|
);
|
||||||
|
break;
|
||||||
|
case AttestationUtils.ID_TYPE_IMEI: {
|
||||||
|
final String imei = telephonyService.getImei(0);
|
||||||
|
if (imei == null) {
|
||||||
|
throw new DeviceIdAttestationException("Unable to retrieve IMEI");
|
||||||
|
}
|
||||||
|
args.addBytes(KeymasterDefs.KM_TAG_ATTESTATION_ID_IMEI,
|
||||||
|
imei.getBytes(StandardCharsets.UTF_8)
|
||||||
|
);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case AttestationUtils.ID_TYPE_MEID: {
|
||||||
|
final String meid = telephonyService.getMeid(0);
|
||||||
|
if (meid == null) {
|
||||||
|
throw new DeviceIdAttestationException("Unable to retrieve MEID");
|
||||||
|
}
|
||||||
|
args.addBytes(KeymasterDefs.KM_TAG_ATTESTATION_ID_MEID,
|
||||||
|
meid.getBytes(StandardCharsets.UTF_8)
|
||||||
|
);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case AttestationUtils.USE_INDIVIDUAL_ATTESTATION: {
|
||||||
|
args.addBoolean(KeymasterDefs.KM_TAG_DEVICE_UNIQUE_ATTESTATION);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
default:
|
||||||
|
throw new IllegalArgumentException("Unknown device ID type " + idType);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
return getAttestationChain(privateKeyAlias, keyPair, args);
|
return getAttestationChain(privateKeyAlias, keyPair, args);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -547,7 +604,8 @@ public abstract class AndroidKeyStoreKeyPairGeneratorSpi extends KeyPairGenerato
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private KeymasterArguments constructKeyGenerationArguments() {
|
private KeymasterArguments constructKeyGenerationArguments()
|
||||||
|
throws IllegalArgumentException, DeviceIdAttestationException {
|
||||||
KeymasterArguments args = new KeymasterArguments();
|
KeymasterArguments args = new KeymasterArguments();
|
||||||
args.addUnsignedInt(KeymasterDefs.KM_TAG_KEY_SIZE, mKeySizeBits);
|
args.addUnsignedInt(KeymasterDefs.KM_TAG_KEY_SIZE, mKeySizeBits);
|
||||||
args.addEnum(KeymasterDefs.KM_TAG_ALGORITHM, mKeymasterAlgorithm);
|
args.addEnum(KeymasterDefs.KM_TAG_ALGORITHM, mKeymasterAlgorithm);
|
||||||
@@ -565,9 +623,9 @@ public abstract class AndroidKeyStoreKeyPairGeneratorSpi extends KeyPairGenerato
|
|||||||
mSpec.getKeyValidityForConsumptionEnd());
|
mSpec.getKeyValidityForConsumptionEnd());
|
||||||
addAlgorithmSpecificParameters(args);
|
addAlgorithmSpecificParameters(args);
|
||||||
|
|
||||||
if (mSpec.isUniqueIdIncluded())
|
if (mSpec.isUniqueIdIncluded()) {
|
||||||
args.addBoolean(KeymasterDefs.KM_TAG_INCLUDE_UNIQUE_ID);
|
args.addBoolean(KeymasterDefs.KM_TAG_INCLUDE_UNIQUE_ID);
|
||||||
|
}
|
||||||
return args;
|
return args;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -34,6 +34,14 @@ public abstract class ArrayUtils {
|
|||||||
return ((array != null) && (array.length > 0)) ? array.clone() : array;
|
return ((array != null) && (array.length > 0)) ? array.clone() : array;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Clones an array if it is not null and has a length greater than 0. Otherwise, returns the
|
||||||
|
* array.
|
||||||
|
*/
|
||||||
|
public static int[] cloneIfNotEmpty(int[] array) {
|
||||||
|
return ((array != null) && (array.length > 0)) ? array.clone() : array;
|
||||||
|
}
|
||||||
|
|
||||||
public static byte[] cloneIfNotEmpty(byte[] array) {
|
public static byte[] cloneIfNotEmpty(byte[] array) {
|
||||||
return ((array != null) && (array.length > 0)) ? array.clone() : array;
|
return ((array != null) && (array.length > 0)) ? array.clone() : array;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -267,6 +267,7 @@ public final class KeyGenParameterSpec implements AlgorithmParameterSpec, UserAu
|
|||||||
private final boolean mUserPresenceRequired;
|
private final boolean mUserPresenceRequired;
|
||||||
private final byte[] mAttestationChallenge;
|
private final byte[] mAttestationChallenge;
|
||||||
private final boolean mDevicePropertiesAttestationIncluded;
|
private final boolean mDevicePropertiesAttestationIncluded;
|
||||||
|
private final int[] mAttestationIds;
|
||||||
private final boolean mUniqueIdIncluded;
|
private final boolean mUniqueIdIncluded;
|
||||||
private final boolean mUserAuthenticationValidWhileOnBody;
|
private final boolean mUserAuthenticationValidWhileOnBody;
|
||||||
private final boolean mInvalidatedByBiometricEnrollment;
|
private final boolean mInvalidatedByBiometricEnrollment;
|
||||||
@@ -308,6 +309,7 @@ public final class KeyGenParameterSpec implements AlgorithmParameterSpec, UserAu
|
|||||||
boolean userPresenceRequired,
|
boolean userPresenceRequired,
|
||||||
byte[] attestationChallenge,
|
byte[] attestationChallenge,
|
||||||
boolean devicePropertiesAttestationIncluded,
|
boolean devicePropertiesAttestationIncluded,
|
||||||
|
int[] attestationIds,
|
||||||
boolean uniqueIdIncluded,
|
boolean uniqueIdIncluded,
|
||||||
boolean userAuthenticationValidWhileOnBody,
|
boolean userAuthenticationValidWhileOnBody,
|
||||||
boolean invalidatedByBiometricEnrollment,
|
boolean invalidatedByBiometricEnrollment,
|
||||||
@@ -361,6 +363,7 @@ public final class KeyGenParameterSpec implements AlgorithmParameterSpec, UserAu
|
|||||||
mUserAuthenticationType = userAuthenticationType;
|
mUserAuthenticationType = userAuthenticationType;
|
||||||
mAttestationChallenge = Utils.cloneIfNotNull(attestationChallenge);
|
mAttestationChallenge = Utils.cloneIfNotNull(attestationChallenge);
|
||||||
mDevicePropertiesAttestationIncluded = devicePropertiesAttestationIncluded;
|
mDevicePropertiesAttestationIncluded = devicePropertiesAttestationIncluded;
|
||||||
|
mAttestationIds = attestationIds;
|
||||||
mUniqueIdIncluded = uniqueIdIncluded;
|
mUniqueIdIncluded = uniqueIdIncluded;
|
||||||
mUserAuthenticationValidWhileOnBody = userAuthenticationValidWhileOnBody;
|
mUserAuthenticationValidWhileOnBody = userAuthenticationValidWhileOnBody;
|
||||||
mInvalidatedByBiometricEnrollment = invalidatedByBiometricEnrollment;
|
mInvalidatedByBiometricEnrollment = invalidatedByBiometricEnrollment;
|
||||||
@@ -719,6 +722,25 @@ public final class KeyGenParameterSpec implements AlgorithmParameterSpec, UserAu
|
|||||||
return mDevicePropertiesAttestationIncluded;
|
return mDevicePropertiesAttestationIncluded;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @hide
|
||||||
|
* Allows the caller to specify device IDs to be attested to in the certificate for the
|
||||||
|
* generated key pair. These values are the enums specified in
|
||||||
|
* {@link android.security.keystore.AttestationUtils}
|
||||||
|
*
|
||||||
|
* @see android.security.keystore.AttestationUtils#ID_TYPE_SERIAL
|
||||||
|
* @see android.security.keystore.AttestationUtils#ID_TYPE_IMEI
|
||||||
|
* @see android.security.keystore.AttestationUtils#ID_TYPE_MEID
|
||||||
|
* @see android.security.keystore.AttestationUtils#USE_INDIVIDUAL_ATTESTATION
|
||||||
|
*
|
||||||
|
* @return integer array representing the requested device IDs to attest.
|
||||||
|
*/
|
||||||
|
@SystemApi
|
||||||
|
@Nullable
|
||||||
|
public int[] getAttestationIds() {
|
||||||
|
return Utils.cloneIfNotNull(mAttestationIds);
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @hide This is a system-only API
|
* @hide This is a system-only API
|
||||||
*
|
*
|
||||||
@@ -834,6 +856,7 @@ public final class KeyGenParameterSpec implements AlgorithmParameterSpec, UserAu
|
|||||||
private boolean mUserPresenceRequired = false;
|
private boolean mUserPresenceRequired = false;
|
||||||
private byte[] mAttestationChallenge = null;
|
private byte[] mAttestationChallenge = null;
|
||||||
private boolean mDevicePropertiesAttestationIncluded = false;
|
private boolean mDevicePropertiesAttestationIncluded = false;
|
||||||
|
private int[] mAttestationIds = null;
|
||||||
private boolean mUniqueIdIncluded = false;
|
private boolean mUniqueIdIncluded = false;
|
||||||
private boolean mUserAuthenticationValidWhileOnBody;
|
private boolean mUserAuthenticationValidWhileOnBody;
|
||||||
private boolean mInvalidatedByBiometricEnrollment = true;
|
private boolean mInvalidatedByBiometricEnrollment = true;
|
||||||
@@ -902,6 +925,7 @@ public final class KeyGenParameterSpec implements AlgorithmParameterSpec, UserAu
|
|||||||
mAttestationChallenge = sourceSpec.getAttestationChallenge();
|
mAttestationChallenge = sourceSpec.getAttestationChallenge();
|
||||||
mDevicePropertiesAttestationIncluded =
|
mDevicePropertiesAttestationIncluded =
|
||||||
sourceSpec.isDevicePropertiesAttestationIncluded();
|
sourceSpec.isDevicePropertiesAttestationIncluded();
|
||||||
|
mAttestationIds = sourceSpec.getAttestationIds();
|
||||||
mUniqueIdIncluded = sourceSpec.isUniqueIdIncluded();
|
mUniqueIdIncluded = sourceSpec.isUniqueIdIncluded();
|
||||||
mUserAuthenticationValidWhileOnBody = sourceSpec.isUserAuthenticationValidWhileOnBody();
|
mUserAuthenticationValidWhileOnBody = sourceSpec.isUserAuthenticationValidWhileOnBody();
|
||||||
mInvalidatedByBiometricEnrollment = sourceSpec.isInvalidatedByBiometricEnrollment();
|
mInvalidatedByBiometricEnrollment = sourceSpec.isInvalidatedByBiometricEnrollment();
|
||||||
@@ -1472,6 +1496,26 @@ public final class KeyGenParameterSpec implements AlgorithmParameterSpec, UserAu
|
|||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @hide
|
||||||
|
* Sets which IDs to attest in the attestation certificate for the key. The acceptable
|
||||||
|
* values in this integer array are the enums specified in
|
||||||
|
* {@link android.security.keystore.AttestationUtils}
|
||||||
|
*
|
||||||
|
* @param attestationIds the array of ID types to attest to in the certificate.
|
||||||
|
*
|
||||||
|
* @see android.security.keystore.AttestationUtils#ID_TYPE_SERIAL
|
||||||
|
* @see android.security.keystore.AttestationUtils#ID_TYPE_IMEI
|
||||||
|
* @see android.security.keystore.AttestationUtils#ID_TYPE_MEID
|
||||||
|
* @see android.security.keystore.AttestationUtils#USE_INDIVIDUAL_ATTESTATION
|
||||||
|
*/
|
||||||
|
@SystemApi
|
||||||
|
@NonNull
|
||||||
|
public Builder setAttestationIds(@NonNull int[] attestationIds) {
|
||||||
|
mAttestationIds = attestationIds;
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @hide Only system apps can use this method.
|
* @hide Only system apps can use this method.
|
||||||
*
|
*
|
||||||
@@ -1638,6 +1682,7 @@ public final class KeyGenParameterSpec implements AlgorithmParameterSpec, UserAu
|
|||||||
mUserPresenceRequired,
|
mUserPresenceRequired,
|
||||||
mAttestationChallenge,
|
mAttestationChallenge,
|
||||||
mDevicePropertiesAttestationIncluded,
|
mDevicePropertiesAttestationIncluded,
|
||||||
|
mAttestationIds,
|
||||||
mUniqueIdIncluded,
|
mUniqueIdIncluded,
|
||||||
mUserAuthenticationValidWhileOnBody,
|
mUserAuthenticationValidWhileOnBody,
|
||||||
mInvalidatedByBiometricEnrollment,
|
mInvalidatedByBiometricEnrollment,
|
||||||
|
|||||||
@@ -101,6 +101,7 @@ public final class ParcelableKeyGenParameterSpec implements Parcelable {
|
|||||||
out.writeBoolean(mSpec.isUserPresenceRequired());
|
out.writeBoolean(mSpec.isUserPresenceRequired());
|
||||||
out.writeByteArray(mSpec.getAttestationChallenge());
|
out.writeByteArray(mSpec.getAttestationChallenge());
|
||||||
out.writeBoolean(mSpec.isDevicePropertiesAttestationIncluded());
|
out.writeBoolean(mSpec.isDevicePropertiesAttestationIncluded());
|
||||||
|
out.writeIntArray(mSpec.getAttestationIds());
|
||||||
out.writeBoolean(mSpec.isUniqueIdIncluded());
|
out.writeBoolean(mSpec.isUniqueIdIncluded());
|
||||||
out.writeBoolean(mSpec.isUserAuthenticationValidWhileOnBody());
|
out.writeBoolean(mSpec.isUserAuthenticationValidWhileOnBody());
|
||||||
out.writeBoolean(mSpec.isInvalidatedByBiometricEnrollment());
|
out.writeBoolean(mSpec.isInvalidatedByBiometricEnrollment());
|
||||||
@@ -160,6 +161,7 @@ public final class ParcelableKeyGenParameterSpec implements Parcelable {
|
|||||||
final boolean userPresenceRequired = in.readBoolean();
|
final boolean userPresenceRequired = in.readBoolean();
|
||||||
final byte[] attestationChallenge = in.createByteArray();
|
final byte[] attestationChallenge = in.createByteArray();
|
||||||
final boolean devicePropertiesAttestationIncluded = in.readBoolean();
|
final boolean devicePropertiesAttestationIncluded = in.readBoolean();
|
||||||
|
final int[] attestationIds = in.createIntArray();
|
||||||
final boolean uniqueIdIncluded = in.readBoolean();
|
final boolean uniqueIdIncluded = in.readBoolean();
|
||||||
final boolean userAuthenticationValidWhileOnBody = in.readBoolean();
|
final boolean userAuthenticationValidWhileOnBody = in.readBoolean();
|
||||||
final boolean invalidatedByBiometricEnrollment = in.readBoolean();
|
final boolean invalidatedByBiometricEnrollment = in.readBoolean();
|
||||||
@@ -195,6 +197,7 @@ public final class ParcelableKeyGenParameterSpec implements Parcelable {
|
|||||||
userPresenceRequired,
|
userPresenceRequired,
|
||||||
attestationChallenge,
|
attestationChallenge,
|
||||||
devicePropertiesAttestationIncluded,
|
devicePropertiesAttestationIncluded,
|
||||||
|
attestationIds,
|
||||||
uniqueIdIncluded,
|
uniqueIdIncluded,
|
||||||
userAuthenticationValidWhileOnBody,
|
userAuthenticationValidWhileOnBody,
|
||||||
invalidatedByBiometricEnrollment,
|
invalidatedByBiometricEnrollment,
|
||||||
|
|||||||
@@ -33,4 +33,8 @@ abstract class Utils {
|
|||||||
static byte[] cloneIfNotNull(byte[] value) {
|
static byte[] cloneIfNotNull(byte[] value) {
|
||||||
return (value != null) ? value.clone() : null;
|
return (value != null) ? value.clone() : null;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static int[] cloneIfNotNull(int[] value) {
|
||||||
|
return (value != null) ? value.clone() : null;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -18,16 +18,20 @@ package android.security.keystore2;
|
|||||||
|
|
||||||
import android.annotation.NonNull;
|
import android.annotation.NonNull;
|
||||||
import android.annotation.Nullable;
|
import android.annotation.Nullable;
|
||||||
|
import android.content.Context;
|
||||||
import android.hardware.security.keymint.KeyParameter;
|
import android.hardware.security.keymint.KeyParameter;
|
||||||
import android.hardware.security.keymint.SecurityLevel;
|
import android.hardware.security.keymint.SecurityLevel;
|
||||||
import android.os.Build;
|
import android.os.Build;
|
||||||
import android.security.KeyPairGeneratorSpec;
|
import android.security.KeyPairGeneratorSpec;
|
||||||
|
import android.security.KeyStore;
|
||||||
import android.security.KeyStore2;
|
import android.security.KeyStore2;
|
||||||
import android.security.KeyStoreException;
|
import android.security.KeyStoreException;
|
||||||
import android.security.KeyStoreSecurityLevel;
|
import android.security.KeyStoreSecurityLevel;
|
||||||
import android.security.keymaster.KeymasterArguments;
|
import android.security.keymaster.KeymasterArguments;
|
||||||
import android.security.keymaster.KeymasterDefs;
|
import android.security.keymaster.KeymasterDefs;
|
||||||
import android.security.keystore.ArrayUtils;
|
import android.security.keystore.ArrayUtils;
|
||||||
|
import android.security.keystore.AttestationUtils;
|
||||||
|
import android.security.keystore.DeviceIdAttestationException;
|
||||||
import android.security.keystore.KeyGenParameterSpec;
|
import android.security.keystore.KeyGenParameterSpec;
|
||||||
import android.security.keystore.KeyProperties;
|
import android.security.keystore.KeyProperties;
|
||||||
import android.security.keystore.KeymasterUtils;
|
import android.security.keystore.KeymasterUtils;
|
||||||
@@ -38,6 +42,8 @@ import android.system.keystore2.IKeystoreSecurityLevel;
|
|||||||
import android.system.keystore2.KeyDescriptor;
|
import android.system.keystore2.KeyDescriptor;
|
||||||
import android.system.keystore2.KeyMetadata;
|
import android.system.keystore2.KeyMetadata;
|
||||||
import android.system.keystore2.ResponseCode;
|
import android.system.keystore2.ResponseCode;
|
||||||
|
import android.telephony.TelephonyManager;
|
||||||
|
import android.util.ArraySet;
|
||||||
import android.util.Log;
|
import android.util.Log;
|
||||||
|
|
||||||
import libcore.util.EmptyArray;
|
import libcore.util.EmptyArray;
|
||||||
@@ -478,7 +484,8 @@ public abstract class AndroidKeyStoreKeyPairGeneratorSpi extends KeyPairGenerato
|
|||||||
}
|
}
|
||||||
throw p;
|
throw p;
|
||||||
}
|
}
|
||||||
} catch (UnrecoverableKeyException e) {
|
} catch (UnrecoverableKeyException | IllegalArgumentException
|
||||||
|
| DeviceIdAttestationException e) {
|
||||||
throw new ProviderException(
|
throw new ProviderException(
|
||||||
"Failed to construct key object from newly generated key pair.", e);
|
"Failed to construct key object from newly generated key pair.", e);
|
||||||
} finally {
|
} finally {
|
||||||
@@ -496,7 +503,7 @@ public abstract class AndroidKeyStoreKeyPairGeneratorSpi extends KeyPairGenerato
|
|||||||
}
|
}
|
||||||
|
|
||||||
private void addAttestationParameters(@NonNull List<KeyParameter> params)
|
private void addAttestationParameters(@NonNull List<KeyParameter> params)
|
||||||
throws ProviderException {
|
throws ProviderException, IllegalArgumentException, DeviceIdAttestationException {
|
||||||
byte[] challenge = mSpec.getAttestationChallenge();
|
byte[] challenge = mSpec.getAttestationChallenge();
|
||||||
|
|
||||||
if (challenge != null) {
|
if (challenge != null) {
|
||||||
@@ -526,15 +533,69 @@ public abstract class AndroidKeyStoreKeyPairGeneratorSpi extends KeyPairGenerato
|
|||||||
Build.MODEL.getBytes(StandardCharsets.UTF_8)
|
Build.MODEL.getBytes(StandardCharsets.UTF_8)
|
||||||
));
|
));
|
||||||
}
|
}
|
||||||
} else {
|
|
||||||
if (mSpec.isDevicePropertiesAttestationIncluded()) {
|
int[] idTypes = mSpec.getAttestationIds();
|
||||||
throw new ProviderException("An attestation challenge must be provided when "
|
if (idTypes == null) {
|
||||||
+ "requesting device properties attestation.");
|
return;
|
||||||
|
}
|
||||||
|
final Set<Integer> idTypesSet = new ArraySet<>(idTypes.length);
|
||||||
|
for (int idType : idTypes) {
|
||||||
|
idTypesSet.add(idType);
|
||||||
|
}
|
||||||
|
TelephonyManager telephonyService = null;
|
||||||
|
if (idTypesSet.contains(AttestationUtils.ID_TYPE_IMEI)
|
||||||
|
|| idTypesSet.contains(AttestationUtils.ID_TYPE_MEID)) {
|
||||||
|
telephonyService =
|
||||||
|
(TelephonyManager) KeyStore.getApplicationContext().getSystemService(
|
||||||
|
Context.TELEPHONY_SERVICE);
|
||||||
|
if (telephonyService == null) {
|
||||||
|
throw new DeviceIdAttestationException("Unable to access telephony service");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
for (final Integer idType : idTypesSet) {
|
||||||
|
switch (idType) {
|
||||||
|
case AttestationUtils.ID_TYPE_SERIAL:
|
||||||
|
params.add(KeyStore2ParameterUtils.makeBytes(
|
||||||
|
KeymasterDefs.KM_TAG_ATTESTATION_ID_SERIAL,
|
||||||
|
Build.getSerial().getBytes(StandardCharsets.UTF_8)
|
||||||
|
));
|
||||||
|
break;
|
||||||
|
case AttestationUtils.ID_TYPE_IMEI: {
|
||||||
|
final String imei = telephonyService.getImei(0);
|
||||||
|
if (imei == null) {
|
||||||
|
throw new DeviceIdAttestationException("Unable to retrieve IMEI");
|
||||||
|
}
|
||||||
|
params.add(KeyStore2ParameterUtils.makeBytes(
|
||||||
|
KeymasterDefs.KM_TAG_ATTESTATION_ID_IMEI,
|
||||||
|
imei.getBytes(StandardCharsets.UTF_8)
|
||||||
|
));
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case AttestationUtils.ID_TYPE_MEID: {
|
||||||
|
final String meid = telephonyService.getMeid(0);
|
||||||
|
if (meid == null) {
|
||||||
|
throw new DeviceIdAttestationException("Unable to retrieve MEID");
|
||||||
|
}
|
||||||
|
params.add(KeyStore2ParameterUtils.makeBytes(
|
||||||
|
KeymasterDefs.KM_TAG_ATTESTATION_ID_MEID,
|
||||||
|
meid.getBytes(StandardCharsets.UTF_8)
|
||||||
|
));
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case AttestationUtils.USE_INDIVIDUAL_ATTESTATION: {
|
||||||
|
params.add(KeyStore2ParameterUtils.makeBool(
|
||||||
|
KeymasterDefs.KM_TAG_DEVICE_UNIQUE_ATTESTATION));
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
default:
|
||||||
|
throw new IllegalArgumentException("Unknown device ID type " + idType);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private Collection<KeyParameter> constructKeyGenerationArguments() {
|
private Collection<KeyParameter> constructKeyGenerationArguments()
|
||||||
|
throws DeviceIdAttestationException, IllegalArgumentException {
|
||||||
List<KeyParameter> params = new ArrayList<>();
|
List<KeyParameter> params = new ArrayList<>();
|
||||||
params.add(KeyStore2ParameterUtils.makeInt(KeymasterDefs.KM_TAG_KEY_SIZE, mKeySizeBits));
|
params.add(KeyStore2ParameterUtils.makeInt(KeymasterDefs.KM_TAG_KEY_SIZE, mKeySizeBits));
|
||||||
params.add(KeyStore2ParameterUtils.makeEnum(
|
params.add(KeyStore2ParameterUtils.makeEnum(
|
||||||
|
|||||||
Reference in New Issue
Block a user