From fb32aac1ea60bf267ff013f6e1023641736c6de5 Mon Sep 17 00:00:00 2001 From: Prashant Patil Date: Wed, 22 Feb 2023 10:40:46 +0000 Subject: [PATCH] Keystore: Attestation fix for AOSP and GSI builds Device ID attestation was failing in AOSP and GSI images due to properties mismatch in Build.java and actual device properties. (For example, the value of Build.DEVICE on a Raven device running an AOSP build would be 'aosp_raven', but KeyMint was provisioned with the value 'raven'.) To fix above issue, properties ro.product.*_for_attestation were introduced in AOSP build files (eg. aosp_raven.mk) only. But this was not sufficient for both AOSP and GSI. The same solution does not work for GSI images: GSI images are generic and so we cannot set device-specific properties in them. So, if ro.product.*_for_attestation properties are empty or unknown, they are read from ro.product.vendor because these values are not changed after flashing GSI images also. This fix will work for both AOSP and GSI images. Device ID properties preferences for eg. Build.BRAND_FOR_ATTESTATION = ro.product.brand_for_attestation -> ro.product.vendor.brand -> UNKNOWN. Bug: 268294752 Bug: 110779648 Bug: 259376922 Test: atest VtsAidlKeyMintTargetTest:PerInstance/NewKeyGenerationTest#EcdsaAttestationIdTags/0_android_hardware_security_keymint_IKeyMintDevice_default Test: atest VtsAidlKeyMintTargetTest:PerInstance/NewKeyGenerationTest#EcdsaAttestationIdTags/1_android_hardware_security_keymint_IKeyMintDevice_strongbox Test: atest CtsKeystoreTestCases:android.keystore.cts.KeyAttestationTest CtsKeystoreTestCases:DeviceOwnerKeyManagementTest Change-Id: I574eca430cd2022cb9c270ca23ad33f6e5423cd4 --- core/api/test-current.txt | 2 + core/java/android/os/Build.java | 48 +++++++++++++++---- .../AndroidKeyStoreKeyPairGeneratorSpi.java | 10 +++- 3 files changed, 49 insertions(+), 11 deletions(-) diff --git a/core/api/test-current.txt b/core/api/test-current.txt index 11ae86edfb2bc..9f3f80d692a4e 100644 --- a/core/api/test-current.txt +++ b/core/api/test-current.txt @@ -1698,7 +1698,9 @@ package android.os { method public static boolean is64BitAbi(String); method public static boolean isDebuggable(); field @Nullable public static final String BRAND_FOR_ATTESTATION; + field @Nullable public static final String DEVICE_FOR_ATTESTATION; field public static final boolean IS_EMULATOR; + field @Nullable public static final String MANUFACTURER_FOR_ATTESTATION; field @Nullable public static final String MODEL_FOR_ATTESTATION; field @Nullable public static final String PRODUCT_FOR_ATTESTATION; } diff --git a/core/java/android/os/Build.java b/core/java/android/os/Build.java index 832f23cdb3e28..735a0689be5e9 100755 --- a/core/java/android/os/Build.java +++ b/core/java/android/os/Build.java @@ -64,17 +64,27 @@ public class Build { /** * The product name for attestation. In non-default builds (like the AOSP build) the value of * the 'PRODUCT' system property may be different to the one provisioned to KeyMint, - * and Keymint attestation would still attest to the product name, it's running on. + * and Keymint attestation would still attest to the product name which was provisioned. * @hide */ @Nullable @TestApi - public static final String PRODUCT_FOR_ATTESTATION = - getString("ro.product.name_for_attestation"); + public static final String PRODUCT_FOR_ATTESTATION = getVendorDeviceIdProperty("name"); /** The name of the industrial design. */ public static final String DEVICE = getString("ro.product.device"); + /** + * The device name for attestation. In non-default builds (like the AOSP build) the value of + * the 'DEVICE' system property may be different to the one provisioned to KeyMint, + * and Keymint attestation would still attest to the device name which was provisioned. + * @hide + */ + @Nullable + @TestApi + public static final String DEVICE_FOR_ATTESTATION = + getVendorDeviceIdProperty("device"); + /** The name of the underlying board, like "goldfish". */ public static final String BOARD = getString("ro.product.board"); @@ -97,19 +107,29 @@ public class Build { /** The manufacturer of the product/hardware. */ public static final String MANUFACTURER = getString("ro.product.manufacturer"); + /** + * The manufacturer name for attestation. In non-default builds (like the AOSP build) the value + * of the 'MANUFACTURER' system property may be different to the one provisioned to KeyMint, + * and Keymint attestation would still attest to the manufacturer which was provisioned. + * @hide + */ + @Nullable + @TestApi + public static final String MANUFACTURER_FOR_ATTESTATION = + getVendorDeviceIdProperty("manufacturer"); + /** The consumer-visible brand with which the product/hardware will be associated, if any. */ public static final String BRAND = getString("ro.product.brand"); /** * The product brand for attestation. In non-default builds (like the AOSP build) the value of * the 'BRAND' system property may be different to the one provisioned to KeyMint, - * and Keymint attestation would still attest to the product brand, it's running on. + * and Keymint attestation would still attest to the product brand which was provisioned. * @hide */ @Nullable @TestApi - public static final String BRAND_FOR_ATTESTATION = - getString("ro.product.brand_for_attestation"); + public static final String BRAND_FOR_ATTESTATION = getVendorDeviceIdProperty("brand"); /** The end-user-visible name for the end product. */ public static final String MODEL = getString("ro.product.model"); @@ -117,13 +137,12 @@ public class Build { /** * The product model for attestation. In non-default builds (like the AOSP build) the value of * the 'MODEL' system property may be different to the one provisioned to KeyMint, - * and Keymint attestation would still attest to the product model, it's running on. + * and Keymint attestation would still attest to the product model which was provisioned. * @hide */ @Nullable @TestApi - public static final String MODEL_FOR_ATTESTATION = - getString("ro.product.model_for_attestation"); + public static final String MODEL_FOR_ATTESTATION = getVendorDeviceIdProperty("model"); /** The manufacturer of the device's primary system-on-chip. */ @NonNull @@ -1530,6 +1549,17 @@ public class Build { private static String getString(String property) { return SystemProperties.get(property, UNKNOWN); } + /** + * Return attestation specific proerties. + * @param property model, name, brand, device or manufacturer. + * @return property value or UNKNOWN + */ + private static String getVendorDeviceIdProperty(String property) { + String attestProp = getString( + TextUtils.formatSimple("ro.product.%s_for_attestation", property)); + return attestProp.equals(UNKNOWN) + ? getString(TextUtils.formatSimple("ro.product.vendor.%s", property)) : UNKNOWN; + } private static String[] getStringList(String property, String separator) { String value = SystemProperties.get(property); diff --git a/keystore/java/android/security/keystore2/AndroidKeyStoreKeyPairGeneratorSpi.java b/keystore/java/android/security/keystore2/AndroidKeyStoreKeyPairGeneratorSpi.java index c1f6c29ca86e6..c3b0f9bc16d3d 100644 --- a/keystore/java/android/security/keystore2/AndroidKeyStoreKeyPairGeneratorSpi.java +++ b/keystore/java/android/security/keystore2/AndroidKeyStoreKeyPairGeneratorSpi.java @@ -808,9 +808,12 @@ public abstract class AndroidKeyStoreKeyPairGeneratorSpi extends KeyPairGenerato KeymasterDefs.KM_TAG_ATTESTATION_ID_BRAND, platformReportedBrand.getBytes(StandardCharsets.UTF_8) )); + final String platformReportedDevice = + isPropertyEmptyOrUnknown(Build.DEVICE_FOR_ATTESTATION) + ? Build.DEVICE : Build.DEVICE_FOR_ATTESTATION; params.add(KeyStore2ParameterUtils.makeBytes( KeymasterDefs.KM_TAG_ATTESTATION_ID_DEVICE, - Build.DEVICE.getBytes(StandardCharsets.UTF_8) + platformReportedDevice.getBytes(StandardCharsets.UTF_8) )); final String platformReportedProduct = isPropertyEmptyOrUnknown(Build.PRODUCT_FOR_ATTESTATION) @@ -819,9 +822,12 @@ public abstract class AndroidKeyStoreKeyPairGeneratorSpi extends KeyPairGenerato KeymasterDefs.KM_TAG_ATTESTATION_ID_PRODUCT, platformReportedProduct.getBytes(StandardCharsets.UTF_8) )); + final String platformReportedManufacturer = + isPropertyEmptyOrUnknown(Build.MANUFACTURER_FOR_ATTESTATION) + ? Build.MANUFACTURER : Build.MANUFACTURER_FOR_ATTESTATION; params.add(KeyStore2ParameterUtils.makeBytes( KeymasterDefs.KM_TAG_ATTESTATION_ID_MANUFACTURER, - Build.MANUFACTURER.getBytes(StandardCharsets.UTF_8) + platformReportedManufacturer.getBytes(StandardCharsets.UTF_8) )); final String platformReportedModel = isPropertyEmptyOrUnknown(Build.MODEL_FOR_ATTESTATION)