Skip to content

Commit

Permalink
add generic biometrics support (face, iris, etc.)
Browse files Browse the repository at this point in the history
  • Loading branch information
thestinger committed Mar 18, 2021
1 parent 361848b commit 5862678
Show file tree
Hide file tree
Showing 4 changed files with 19 additions and 26 deletions.
1 change: 1 addition & 0 deletions app/build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,7 @@ dependencies {
implementation fileTree(include: ['*.jar'], dir: 'libs')
implementation 'androidx.appcompat:appcompat:1.2.0'
implementation 'androidx.preference:preference:1.1.1'
implementation 'androidx.biometric:biometric:1.1.0'
implementation 'com.google.android.material:material:1.3.0'
implementation 'com.google.guava:guava:30.1-android'
implementation 'com.google.zxing:core:3.4.1'
Expand Down
3 changes: 2 additions & 1 deletion app/src/main/AndroidManifest.xml
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,8 @@
<uses-permission android:name="android.permission.CAMERA" />
<uses-permission android:name="android.permission.INTERNET" />
<uses-permission android:name="android.permission.RECEIVE_BOOT_COMPLETED" />
<uses-permission android:name="android.permission.USE_FINGERPRINT" />
<uses-permission android:name="android.permission.USE_FINGERPRINT" android:maxSdkVersion="28" />
<uses-permission android:name="android.permission.USE_BIOMETRIC" />
<uses-permission android:name="android.permission.QUERY_ALL_PACKAGES" />

<application android:label="@string/app_name"
Expand Down
40 changes: 15 additions & 25 deletions app/src/main/java/app/attestation/auditor/AttestationProtocol.java
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@
import android.util.Log;
import android.view.accessibility.AccessibilityManager;

import androidx.biometric.BiometricManager;
import androidx.preference.PreferenceManager;

import com.google.common.collect.ImmutableMap;
Expand Down Expand Up @@ -74,6 +75,9 @@
import static android.security.keystore.KeyProperties.DIGEST_SHA256;
import static android.security.keystore.KeyProperties.KEY_ALGORITHM_EC;

import static androidx.biometric.BiometricManager.Authenticators.BIOMETRIC_WEAK;
import static androidx.biometric.BiometricManager.BIOMETRIC_SUCCESS;

class AttestationProtocol {
private static final String TAG = "AttestationProtocol";

Expand Down Expand Up @@ -203,7 +207,7 @@ class AttestationProtocol {
private static final int OS_ENFORCED_FLAGS_DEVICE_ADMIN = 1 << 2;
private static final int OS_ENFORCED_FLAGS_ADB_ENABLED = 1 << 3;
private static final int OS_ENFORCED_FLAGS_ADD_USERS_WHEN_LOCKED = 1 << 4;
private static final int OS_ENFORCED_FLAGS_ENROLLED_FINGERPRINTS = 1 << 5;
private static final int OS_ENFORCED_FLAGS_ENROLLED_BIOMETRICS = 1 << 5;
private static final int OS_ENFORCED_FLAGS_DENY_NEW_USB = 1 << 6;
private static final int OS_ENFORCED_FLAGS_DEVICE_ADMIN_NON_SYSTEM = 1 << 7;
private static final int OS_ENFORCED_FLAGS_OEM_UNLOCK_ALLOWED = 1 << 8;
Expand All @@ -214,7 +218,7 @@ class AttestationProtocol {
OS_ENFORCED_FLAGS_DEVICE_ADMIN |
OS_ENFORCED_FLAGS_ADB_ENABLED |
OS_ENFORCED_FLAGS_ADD_USERS_WHEN_LOCKED |
OS_ENFORCED_FLAGS_ENROLLED_FINGERPRINTS |
OS_ENFORCED_FLAGS_ENROLLED_BIOMETRICS |
OS_ENFORCED_FLAGS_DENY_NEW_USB |
OS_ENFORCED_FLAGS_DEVICE_ADMIN_NON_SYSTEM |
OS_ENFORCED_FLAGS_OEM_UNLOCK_ALLOWED |
Expand Down Expand Up @@ -828,7 +832,7 @@ private static VerificationResult verify(final Context context, final byte[] fin
final Certificate[] attestationCertificates, final boolean userProfileSecure,
final boolean accessibility, final boolean deviceAdmin,
final boolean deviceAdminNonSystem, final boolean adbEnabled,
final boolean addUsersWhenLocked, final boolean enrolledFingerprints,
final boolean addUsersWhenLocked, final boolean enrolledBiometrics,
final boolean denyNewUsb, final boolean oemUnlockAllowed, final boolean systemUser)
throws GeneralSecurityException, IOException {
final String fingerprintHex = BaseEncoding.base16().encode(fingerprint);
Expand Down Expand Up @@ -958,8 +962,8 @@ private static VerificationResult verify(final Context context, final byte[] fin
osEnforced.append(context.getString(R.string.auditor_app_version, verified.appVersion));
osEnforced.append(context.getString(R.string.user_profile_secure,
toYesNoString(context, userProfileSecure)));
osEnforced.append(context.getString(R.string.enrolled_fingerprints,
toYesNoString(context, enrolledFingerprints)));
osEnforced.append(context.getString(verified.appVersion < 26 ? R.string.enrolled_fingerprints : R.string.enrolled_biometrics,
toYesNoString(context, enrolledBiometrics)));
osEnforced.append(context.getString(R.string.accessibility,
toYesNoString(context, accessibility)));

Expand Down Expand Up @@ -1040,7 +1044,7 @@ static VerificationResult verifySerialized(final Context context, final byte[] a
final boolean deviceAdminNonSystem = (osEnforcedFlags & OS_ENFORCED_FLAGS_DEVICE_ADMIN_NON_SYSTEM) != 0;
final boolean adbEnabled = (osEnforcedFlags & OS_ENFORCED_FLAGS_ADB_ENABLED) != 0;
final boolean addUsersWhenLocked = (osEnforcedFlags & OS_ENFORCED_FLAGS_ADD_USERS_WHEN_LOCKED) != 0;
final boolean enrolledFingerprints = (osEnforcedFlags & OS_ENFORCED_FLAGS_ENROLLED_FINGERPRINTS) != 0;
final boolean enrolledBiometrics = (osEnforcedFlags & OS_ENFORCED_FLAGS_ENROLLED_BIOMETRICS) != 0;
final boolean denyNewUsb = (osEnforcedFlags & OS_ENFORCED_FLAGS_DENY_NEW_USB) != 0;
final boolean oemUnlockAllowed = (osEnforcedFlags & OS_ENFORCED_FLAGS_OEM_UNLOCK_ALLOWED) != 0;
final boolean systemUser = (osEnforcedFlags & OS_ENFORCED_FLAGS_SYSTEM_USER) != 0;
Expand All @@ -1059,7 +1063,7 @@ static VerificationResult verifySerialized(final Context context, final byte[] a
final byte[] challenge = Arrays.copyOfRange(challengeMessage, 1 + CHALLENGE_LENGTH, 1 + CHALLENGE_LENGTH * 2);
return verify(context, fingerprint, challenge, deserializer.asReadOnlyBuffer(), signature,
certificates, userProfileSecure, accessibility, deviceAdmin, deviceAdminNonSystem,
adbEnabled, addUsersWhenLocked, enrolledFingerprints, denyNewUsb, oemUnlockAllowed,
adbEnabled, addUsersWhenLocked, enrolledBiometrics, denyNewUsb, oemUnlockAllowed,
systemUser);
}

Expand All @@ -1078,21 +1082,6 @@ static void enableStrongBox(final KeyGenParameterSpec.Builder builder) {
builder.setIsStrongBoxBacked(true);
}

// Need FingerprintManager until BiometricManager is available in API 29+
@SuppressWarnings("deprecation")
static boolean hasEnrolledFingerprints(final Context context) throws GeneralSecurityException {
final android.hardware.fingerprint.FingerprintManager manager =
context.getSystemService(android.hardware.fingerprint.FingerprintManager.class);
// buggy devices don't always set FEATURE_FINGERPRINT so it can't be checked directly
if (manager == null) {
if (context.getPackageManager().hasSystemFeature(PackageManager.FEATURE_FINGERPRINT)) {
throw new GeneralSecurityException("expected non-null FingerprintManager");
}
return false;
}
return manager.hasEnrolledFingerprints();
}

static AttestationResult generateSerialized(final Context context, final byte[] challengeMessage,
String index, final String statePrefix) throws GeneralSecurityException, IOException {
if (challengeMessage.length < CHALLENGE_MESSAGE_LENGTH) {
Expand Down Expand Up @@ -1198,7 +1187,8 @@ static AttestationResult generateSerialized(final Context context, final byte[]
if (userProfileSecure && !keyguard.isKeyguardSecure()) {
throw new GeneralSecurityException("keyguard state inconsistent");
}
final boolean enrolledFingerprints = hasEnrolledFingerprints(context);
final BiometricManager biometricManager = BiometricManager.from(context);
final boolean enrolledBiometrics = biometricManager.canAuthenticate(BIOMETRIC_WEAK) == BIOMETRIC_SUCCESS;

final AccessibilityManager am = context.getSystemService(AccessibilityManager.class);
final boolean accessibility = am.isEnabled();
Expand Down Expand Up @@ -1284,8 +1274,8 @@ static AttestationResult generateSerialized(final Context context, final byte[]
if (addUsersWhenLocked) {
osEnforcedFlags |= OS_ENFORCED_FLAGS_ADD_USERS_WHEN_LOCKED;
}
if (enrolledFingerprints) {
osEnforcedFlags |= OS_ENFORCED_FLAGS_ENROLLED_FINGERPRINTS;
if (enrolledBiometrics) {
osEnforcedFlags |= OS_ENFORCED_FLAGS_ENROLLED_BIOMETRICS;
}
if (denyNewUsb) {
osEnforcedFlags |= OS_ENFORCED_FLAGS_DENY_NEW_USB;
Expand Down
1 change: 1 addition & 0 deletions app/src/main/res/values/strings.xml
Original file line number Diff line number Diff line change
Expand Up @@ -59,6 +59,7 @@
<string name="auditor_app_version">Auditor app version: %d\n</string>
<string name="user_profile_secure">User profile secure: %s\n</string>
<string name="enrolled_fingerprints">Enrolled fingerprints: %s\n</string>
<string name="enrolled_biometrics">Enrolled biometrics: %s\n</string>
<string name="accessibility">Accessibility service(s) enabled: %s\n</string>
<string name="device_admin">Device administrator(s) enabled: %s\n</string>
<string name="device_admin_system">yes, but only system apps</string>
Expand Down

0 comments on commit 5862678

Please sign in to comment.