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)