diff --git a/app/src/main/java/app/attestation/auditor/AttestationProtocol.java b/app/src/main/java/app/attestation/auditor/AttestationProtocol.java index 40148c25..0d80f404 100644 --- a/app/src/main/java/app/attestation/auditor/AttestationProtocol.java +++ b/app/src/main/java/app/attestation/auditor/AttestationProtocol.java @@ -263,6 +263,11 @@ private static class DeviceInfo { this.enforceStrongBox = enforceStrongBox; this.osName = osName; } + + // Generic device info always have false rollback resistance, and skips boot and vendor patch level checks. + boolean isGeneric() { + return GENERIC_DEVICE_STOCK.equals(this) || GENERIC_DEVICE_STRONGBOX_STOCK.equals(this); + } } private static final boolean isStrongBoxSupported = ImmutableSet.of( @@ -580,6 +585,13 @@ private static class DeviceInfo { new DeviceInfo(R.string.device_sm_n975u, 3, 4, false, true, R.string.os_stock)) .build(); + // Some Android 10 devices, including past supported devices above, has attestationVersion, keymasterVersion of 1. + // TODO: Remove non-generic device support past EoL with latest Android version lower than Android 10. + private static final DeviceInfo GENERIC_DEVICE_STOCK = + new DeviceInfo(R.string.generic_device_name_unknown, 1, 1, false, false, R.string.generic_device_os_stock); + private static final DeviceInfo GENERIC_DEVICE_STRONGBOX_STOCK = + new DeviceInfo(R.string.generic_device_name_unknown, 1, 1, false, true, R.string.generic_device_os_stock); + private static byte[] getChallengeIndex(final Context context) { final SharedPreferences global = PreferenceManager.getDefaultSharedPreferences(context); final String challengeIndexSerialized = global.getString(KEY_CHALLENGE_INDEX, null); @@ -752,16 +764,16 @@ private static Verified verifyStateless(final Certificate[] certificates, } } else if (verifiedBootState == RootOfTrust.VerifiedBootState.VERIFIED) { if (attestationSecurityLevelEnum == ParsedAttestationRecord.SecurityLevel.STRONG_BOX) { - device = fingerprintsStrongBoxStock.get(verifiedBootKey); + device = fingerprintsStrongBoxStock.getOrDefault(verifiedBootKey, GENERIC_DEVICE_STRONGBOX_STOCK); } else { - device = fingerprintsStock.get(verifiedBootKey); + device = fingerprintsStock.getOrDefault(verifiedBootKey, GENERIC_DEVICE_STOCK); } } else { throw new GeneralSecurityException("verified boot state is not verified or self signed"); } if (device == null) { - throw new GeneralSecurityException("invalid verified boot key fingerprint: " + verifiedBootKey); + throw new GeneralSecurityException("invalid self-signed verified boot key fingerprint: " + verifiedBootKey); } // enforce StrongBox for new pairings with devices supporting it @@ -780,11 +792,13 @@ private static Verified verifyStateless(final Certificate[] certificates, throw new GeneralSecurityException("OS patch level too old: " + osPatchLevel); } final int vendorPatchLevel = teeEnforced.vendorPatchLevel.orElse(0); - if (vendorPatchLevel < VENDOR_PATCH_LEVEL_MINIMUM && !extraPatchLevelMissing.contains(device.name)) { + if (vendorPatchLevel < VENDOR_PATCH_LEVEL_MINIMUM && !extraPatchLevelMissing.contains(device.name) + && !device.isGeneric()) { throw new GeneralSecurityException("Vendor patch level too old: " + vendorPatchLevel); } final int bootPatchLevel = teeEnforced.bootPatchLevel.orElse(0); - if (bootPatchLevel < BOOT_PATCH_LEVEL_MINIMUM && !extraPatchLevelMissing.contains(device.name)) { + if (bootPatchLevel < BOOT_PATCH_LEVEL_MINIMUM && !extraPatchLevelMissing.contains(device.name) + && !device.isGeneric()) { throw new GeneralSecurityException("Boot patch level too old: " + bootPatchLevel); } diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml index f59b3622..a606cf7b 100644 --- a/app/src/main/res/values/strings.xml +++ b/app/src/main/res/values/strings.xml @@ -176,4 +176,7 @@ Stock GrapheneOS + + Unknown non-Pixel device + Stock (Generic)