diff options
| author | 2019-09-04 11:35:50 +0100 | |
|---|---|---|
| committer | 2019-09-24 18:14:05 +0100 | |
| commit | da05c80d6b8b95ef77059adc114009b75e14f535 (patch) | |
| tree | 81ee3458cb57a8001889361625601cca604fad9c | |
| parent | efb5b79fcd4bbecbac0e803623a3037d02750da8 (diff) | |
API for individual attestation
Introduce a new API to request use of individual attestation
certificate for attesting keys generated by the
DevicePolicyManager.generateKeyPair method.
It builds on existing device ID attestation capabilities in two ways:
(1) Eligibility check: Assuming similar privacy requirements for the use
of individual attestation certificates, enforce the same conditions
for using them as the conditions for requesting device identifiers
in the attestation record.
(2) Keymaster interaction: Passing the right Keymaster tag to the
attestKey call, which is easily done in AttestationUtils.
Bug: 136494773
Test: CTS test to be added.
Change-Id: Idb5cee66d986a521c17e1955532d0bfae66c035d
| -rw-r--r-- | api/current.txt | 2 | ||||
| -rw-r--r-- | api/system-current.txt | 1 | ||||
| -rw-r--r-- | api/test-current.txt | 1 | ||||
| -rw-r--r-- | core/java/android/app/admin/DevicePolicyManager.java | 73 | ||||
| -rw-r--r-- | core/java/android/content/pm/PackageManager.java | 11 | ||||
| -rw-r--r-- | keystore/java/android/security/keystore/AttestationUtils.java | 14 | ||||
| -rw-r--r-- | services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java | 3 |
7 files changed, 92 insertions, 13 deletions
diff --git a/api/current.txt b/api/current.txt index d688220fd17b..9a9f591f2ef4 100644 --- a/api/current.txt +++ b/api/current.txt @@ -6799,6 +6799,7 @@ package android.app.admin { method public boolean isResetPasswordTokenActive(android.content.ComponentName); method public boolean isSecurityLoggingEnabled(@Nullable android.content.ComponentName); method public boolean isUninstallBlocked(@Nullable android.content.ComponentName, String); + method public boolean isUniqueDeviceAttestationSupported(); method public boolean isUsingUnifiedPassword(@NonNull android.content.ComponentName); method public void lockNow(); method public void lockNow(int); @@ -6980,6 +6981,7 @@ package android.app.admin { field public static final int FLAG_PARENT_CAN_ACCESS_MANAGED = 1; // 0x1 field public static final int ID_TYPE_BASE_INFO = 1; // 0x1 field public static final int ID_TYPE_IMEI = 4; // 0x4 + field public static final int ID_TYPE_INDIVIDUAL_ATTESTATION = 16; // 0x10 field public static final int ID_TYPE_MEID = 8; // 0x8 field public static final int ID_TYPE_SERIAL = 2; // 0x2 field public static final int INSTALLKEY_REQUEST_CREDENTIALS_ACCESS = 1; // 0x1 diff --git a/api/system-current.txt b/api/system-current.txt index d31bfeb9138d..ba33f5b55efd 100644 --- a/api/system-current.txt +++ b/api/system-current.txt @@ -6171,6 +6171,7 @@ package android.security.keystore { field public static final int ID_TYPE_IMEI = 2; // 0x2 field public static final int ID_TYPE_MEID = 3; // 0x3 field public static final int ID_TYPE_SERIAL = 1; // 0x1 + field public static final int USE_INDIVIDUAL_ATTESTATION = 4; // 0x4 } public class DeviceIdAttestationException extends java.lang.Exception { diff --git a/api/test-current.txt b/api/test-current.txt index 51b569f029d0..dcc3329e4979 100644 --- a/api/test-current.txt +++ b/api/test-current.txt @@ -2431,6 +2431,7 @@ package android.security.keystore { field public static final int ID_TYPE_IMEI = 2; // 0x2 field public static final int ID_TYPE_MEID = 3; // 0x3 field public static final int ID_TYPE_SERIAL = 1; // 0x1 + field public static final int USE_INDIVIDUAL_ATTESTATION = 4; // 0x4 } public class DeviceIdAttestationException extends java.lang.Exception { diff --git a/core/java/android/app/admin/DevicePolicyManager.java b/core/java/android/app/admin/DevicePolicyManager.java index 64ddfc106dcf..ae872168e425 100644 --- a/core/java/android/app/admin/DevicePolicyManager.java +++ b/core/java/android/app/admin/DevicePolicyManager.java @@ -2079,7 +2079,8 @@ public class DevicePolicyManager { ID_TYPE_BASE_INFO, ID_TYPE_SERIAL, ID_TYPE_IMEI, - ID_TYPE_MEID + ID_TYPE_MEID, + ID_TYPE_INDIVIDUAL_ATTESTATION }) public @interface AttestationIdType {} @@ -2114,6 +2115,14 @@ public class DevicePolicyManager { public static final int ID_TYPE_MEID = 8; /** + * Specifies that the device should attest using an individual attestation certificate. + * For use with {@link #generateKeyPair}. + * + * @see #generateKeyPair + */ + public static final int ID_TYPE_INDIVIDUAL_ATTESTATION = 16; + + /** * Service-specific error code for {@link #generateKeyPair}: * Indicates the call has failed due to StrongBox unavailability. * @hide @@ -4892,24 +4901,47 @@ public class DevicePolicyManager { * have been given to access the key and certificates associated with this alias will be * revoked. * + * <p>Attestation: to enable attestation, set an attestation challenge in {@code keySpec} via + * {@link KeyGenParameterSpec.Builder#setAttestationChallenge}. By specifying flags to the + * {@code idAttestationFlags} parameter, it is possible to request the device's unique + * identity to be included in the attestation record. + * + * <p>Specific identifiers can be included in the attestation record, and an individual + * attestation certificate can be used to sign the attestation record. To find out if the device + * supports these features, refer to {@link #isDeviceIdAttestationSupported()} and + * {@link #isUniqueDeviceAttestationSupported()}. + * + * <p>Device owner, profile owner and their delegated certificate installer can use + * {@link #ID_TYPE_BASE_INFO} to request inclusion of the general device information + * including manufacturer, model, brand, device and product in the attestation record. + * Only device owner and their delegated certificate installer can use + * {@link #ID_TYPE_SERIAL}, {@link #ID_TYPE_IMEI} and {@link #ID_TYPE_MEID} to request + * unique device identifiers to be attested (the serial number, IMEI and MEID correspondingly), + * if supported by the device (see {@link #isDeviceIdAttestationSupported()}). + * Additionally, device owner and their delegated certificate installer can also request the + * attestation record to be signed using an individual attestation certificate by specifying + * the {@link #ID_TYPE_INDIVIDUAL_ATTESTATION} flag (if supported by the device, see + * {@link #isUniqueDeviceAttestationSupported()}). + * <p> + * If any of {@link #ID_TYPE_SERIAL}, {@link #ID_TYPE_IMEI} and {@link #ID_TYPE_MEID} + * is set, it is implicitly assumed that {@link #ID_TYPE_BASE_INFO} is also set. + * <p> + * Attestation using {@link #ID_TYPE_INDIVIDUAL_ATTESTATION} can only be requested if + * key generation is done in StrongBox. + * * @param admin Which {@link DeviceAdminReceiver} this request is associated with, or * {@code null} if calling from a delegated certificate installer. * @param algorithm The key generation algorithm, see {@link java.security.KeyPairGenerator}. * @param keySpec Specification of the key to generate, see * {@link java.security.KeyPairGenerator}. - * @param idAttestationFlags A bitmask of all the identifiers that should be included in the + * @param idAttestationFlags A bitmask of the identifiers that should be included in the * attestation record ({@code ID_TYPE_BASE_INFO}, {@code ID_TYPE_SERIAL}, - * {@code ID_TYPE_IMEI} and {@code ID_TYPE_MEID}), or {@code 0} if no device - * identification is required in the attestation record. - * Device owner, profile owner and their delegated certificate installer can use - * {@link #ID_TYPE_BASE_INFO} to request inclusion of the general device information - * including manufacturer, model, brand, device and product in the attestation record. - * Only device owner and their delegated certificate installer can use - * {@link #ID_TYPE_SERIAL}, {@link #ID_TYPE_IMEI} and {@link #ID_TYPE_MEID} to request - * unique device identifiers to be attested. + * {@code ID_TYPE_IMEI} and {@code ID_TYPE_MEID}), and + * {@code ID_TYPE_INDIVIDUAL_ATTESTATION} if the attestation record should be signed + * using an individual attestation certificate. * <p> - * If any of {@link #ID_TYPE_SERIAL}, {@link #ID_TYPE_IMEI} and {@link #ID_TYPE_MEID} - * is set, it is implicitly assumed that {@link #ID_TYPE_BASE_INFO} is also set. + * {@code 0} should be passed in if no device identification is required in the + * attestation record and the batch attestation certificate should be used. * <p> * If any flag is specified, then an attestation challenge must be included in the * {@code keySpec}. @@ -5051,7 +5083,8 @@ public class DevicePolicyManager { /** * Returns {@code true} if the device supports attestation of device identifiers in addition - * to key attestation. + * to key attestation. See + * {@link #generateKeyPair(ComponentName, String, KeyGenParameterSpec, int)} * @return {@code true} if Device ID attestation is supported. */ public boolean isDeviceIdAttestationSupported() { @@ -5060,6 +5093,20 @@ public class DevicePolicyManager { } /** + * Returns {@code true} if the StrongBox Keymaster implementation on the device was provisioned + * with an individual attestation certificate and can sign attestation records using it (as + * attestation using an individual attestation certificate is a feature only Keymaster + * implementations with StrongBox security level can implement). + * For use prior to calling + * {@link #generateKeyPair(ComponentName, String, KeyGenParameterSpec, int)}. + * @return {@code true} if individual attestation is supported. + */ + public boolean isUniqueDeviceAttestationSupported() { + PackageManager pm = mContext.getPackageManager(); + return pm.hasSystemFeature(PackageManager.FEATURE_DEVICE_UNIQUE_ATTESTATION); + } + + /** * Called by a device or profile owner, or delegated certificate installer, to associate * certificates with a key pair that was generated using {@link #generateKeyPair}, and * set whether the key is available for the user to choose in the certificate selection diff --git a/core/java/android/content/pm/PackageManager.java b/core/java/android/content/pm/PackageManager.java index 6d88fea9c4b9..fafb56d20ba0 100644 --- a/core/java/android/content/pm/PackageManager.java +++ b/core/java/android/content/pm/PackageManager.java @@ -2849,6 +2849,17 @@ public abstract class PackageManager { /** * Feature for {@link #getSystemAvailableFeatures} and {@link #hasSystemFeature}: + * The device supports device-unique Keystore attestations. Only available on devices that + * also support {@link #FEATURE_STRONGBOX_KEYSTORE}, and can only be used by device owner + * apps (see {@link android.app.admin.DevicePolicyManager#generateKeyPair}). + * @hide + */ + @SdkConstant(SdkConstantType.FEATURE) + public static final String FEATURE_DEVICE_UNIQUE_ATTESTATION = + "android.hardware.device_unique_attestation"; + + /** + * Feature for {@link #getSystemAvailableFeatures} and {@link #hasSystemFeature}: * The device has a Keymaster implementation that supports Device ID attestation. * * @see DevicePolicyManager#isDeviceIdAttestationSupported diff --git a/keystore/java/android/security/keystore/AttestationUtils.java b/keystore/java/android/security/keystore/AttestationUtils.java index bd497c1e4efa..94499ce24ed0 100644 --- a/keystore/java/android/security/keystore/AttestationUtils.java +++ b/keystore/java/android/security/keystore/AttestationUtils.java @@ -74,6 +74,13 @@ public abstract class AttestationUtils { public static final int ID_TYPE_MEID = 3; /** + * Specifies that the device should attest its MEIDs. For use with {@link #attestDeviceIds}. + * + * @see #attestDeviceIds + */ + public static final int USE_INDIVIDUAL_ATTESTATION = 4; + + /** * Creates an array of X509Certificates from the provided KeymasterCertificateChain. * * @hide Only called by the DevicePolicyManager. @@ -196,6 +203,13 @@ public abstract class AttestationUtils { meid.getBytes(StandardCharsets.UTF_8)); break; } + case USE_INDIVIDUAL_ATTESTATION: { + //TODO: Add the Keymaster tag for requesting the use of individual + //attestation certificate, which should be + //KeymasterDefs.KM_TAG_DEVICE_UNIQUE_ATTESTATION + attestArgs.addBoolean(720); + break; + } default: throw new IllegalArgumentException("Unknown device ID type " + idType); } diff --git a/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java b/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java index 555968a31ca8..3734650adc78 100644 --- a/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java +++ b/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java @@ -50,6 +50,7 @@ import static android.app.admin.DevicePolicyManager.DELEGATION_PACKAGE_ACCESS; import static android.app.admin.DevicePolicyManager.DELEGATION_PERMISSION_GRANT; import static android.app.admin.DevicePolicyManager.ID_TYPE_BASE_INFO; import static android.app.admin.DevicePolicyManager.ID_TYPE_IMEI; +import static android.app.admin.DevicePolicyManager.ID_TYPE_INDIVIDUAL_ATTESTATION; import static android.app.admin.DevicePolicyManager.ID_TYPE_MEID; import static android.app.admin.DevicePolicyManager.ID_TYPE_SERIAL; import static android.app.admin.DevicePolicyManager.LEAVE_ALL_SYSTEM_APPS_ENABLED; @@ -5816,6 +5817,8 @@ public class DevicePolicyManagerService extends BaseIDevicePolicyManager { idTypeToAttestationFlag.put(ID_TYPE_SERIAL, AttestationUtils.ID_TYPE_SERIAL); idTypeToAttestationFlag.put(ID_TYPE_IMEI, AttestationUtils.ID_TYPE_IMEI); idTypeToAttestationFlag.put(ID_TYPE_MEID, AttestationUtils.ID_TYPE_MEID); + idTypeToAttestationFlag.put( + ID_TYPE_INDIVIDUAL_ATTESTATION, AttestationUtils.USE_INDIVIDUAL_ATTESTATION); int numFlagsSet = Integer.bitCount(idAttestationFlags); // No flags are set - return null to indicate no device ID attestation information should |