Change UserAuthType to Enum.

Change-Id: I69ed59331f49a7d0d7fb7eccb9879c6abfa5afa5
diff --git a/server/src/main/java/com/google/android/attestation/AuthorizationList.java b/server/src/main/java/com/google/android/attestation/AuthorizationList.java
index 012a994..81c35ec 100644
--- a/server/src/main/java/com/google/android/attestation/AuthorizationList.java
+++ b/server/src/main/java/com/google/android/attestation/AuthorizationList.java
@@ -15,6 +15,10 @@
 
 package com.google.android.attestation;
 
+import static com.google.android.attestation.AuthorizationList.UserAuthType.FINGERPRINT;
+import static com.google.android.attestation.AuthorizationList.UserAuthType.PASSWORD;
+import static com.google.android.attestation.AuthorizationList.UserAuthType.USER_AUTH_TYPE_ANY;
+import static com.google.android.attestation.AuthorizationList.UserAuthType.USER_AUTH_TYPE_NONE;
 import static com.google.android.attestation.Constants.KM_TAG_ACTIVE_DATE_TIME;
 import static com.google.android.attestation.Constants.KM_TAG_ALGORITHM;
 import static com.google.android.attestation.Constants.KM_TAG_ALLOW_WHILE_ON_BODY;
@@ -52,6 +56,7 @@
 import static com.google.android.attestation.Constants.KM_TAG_USAGE_EXPIRE_DATE_TIME;
 import static com.google.android.attestation.Constants.KM_TAG_USER_AUTH_TYPE;
 import static com.google.android.attestation.Constants.KM_TAG_VENDOR_PATCH_LEVEL;
+import static com.google.android.attestation.Constants.UINT32_MAX;
 
 import java.time.Duration;
 import java.time.Instant;
@@ -76,6 +81,13 @@
  */
 @SuppressWarnings("OptionalUsedAsFieldOrParameterType")
 public class AuthorizationList {
+  /** Specifies the types of user authenticators that may be used to authorize this key. */
+  public enum UserAuthType {
+    USER_AUTH_TYPE_NONE,
+    PASSWORD,
+    FINGERPRINT,
+    USER_AUTH_TYPE_ANY
+  }
 
   public final Optional<Set<Integer>> purpose;
   public final Optional<Integer> algorithm;
@@ -89,7 +101,7 @@
   public final Optional<Instant> originationExpireDateTime;
   public final Optional<Instant> usageExpireDateTime;
   public final boolean noAuthRequired;
-  public final Optional<Integer> userAuthType;
+  public final Optional<UserAuthType> userAuthType;
   public final Optional<Duration> authTimeout;
   public final boolean allowWhileOnBody;
   public final boolean trustedUserPresenceRequired;
@@ -138,8 +150,7 @@
             authorizationMap, KM_TAG_USAGE_EXPIRE_DATE_TIME);
     this.noAuthRequired =
         findBooleanAuthorizationListEntry(authorizationMap, KM_TAG_NO_AUTH_REQUIRED);
-    this.userAuthType =
-        findOptionalIntegerAuthorizationListEntry(authorizationMap, KM_TAG_USER_AUTH_TYPE);
+    this.userAuthType = findOptionalUserAuthType(authorizationMap, KM_TAG_USER_AUTH_TYPE);
     this.authTimeout =
         findOptionalDurationSecondsAuthorizationListEntry(authorizationMap, KM_TAG_AUTH_TIMEOUT);
     this.allowWhileOnBody =
@@ -268,4 +279,24 @@
     ASN1OctetString entry = (ASN1OctetString) findAuthorizationListEntry(authorizationMap, tag);
     return Optional.ofNullable(entry).map(ASN1OctetString::getOctets);
   }
+
+  private static Optional<UserAuthType> findOptionalUserAuthType(
+      Map<Integer, ASN1Primitive> authorizationMap, int tag) {
+    Optional<Long> userAuthType = findOptionalLongAuthorizationListEntry(authorizationMap, tag);
+    return userAuthType.map(AuthorizationList::userAuthTypeToEnum);
+  }
+
+  // Visible for testing.
+  static UserAuthType userAuthTypeToEnum(long userAuthType) {
+    if (userAuthType == 0L) {
+      return USER_AUTH_TYPE_NONE;
+    } else if (userAuthType == 1L) {
+      return PASSWORD;
+    } else if (userAuthType == 2L) {
+      return FINGERPRINT;
+    } else if (userAuthType == UINT32_MAX) {
+      return USER_AUTH_TYPE_ANY;
+    }
+    throw new IllegalArgumentException("Invalid User Auth Type.");
+  }
 }
diff --git a/server/src/main/java/com/google/android/attestation/Constants.java b/server/src/main/java/com/google/android/attestation/Constants.java
index 3464003..6f0a5f1 100644
--- a/server/src/main/java/com/google/android/attestation/Constants.java
+++ b/server/src/main/java/com/google/android/attestation/Constants.java
@@ -119,4 +119,6 @@
   static final int KM_VERIFIED_BOOT_STATE_SELF_SIGNED = 1;
   static final int KM_VERIFIED_BOOT_STATE_UNVERIFIED = 2;
   static final int KM_VERIFIED_BOOT_STATE_FAILED = 3;
+  // Unsigned max value of 32-bit integer, 2^32 - 1
+  static final long UINT32_MAX = (((long) Integer.MAX_VALUE) << 1) + 1;
 }
diff --git a/server/src/test/java/com/google/android/attestation/AuthorizationListTest.java b/server/src/test/java/com/google/android/attestation/AuthorizationListTest.java
index b5c61d4..1265c46 100644
--- a/server/src/test/java/com/google/android/attestation/AuthorizationListTest.java
+++ b/server/src/test/java/com/google/android/attestation/AuthorizationListTest.java
@@ -15,8 +15,15 @@
 
 package com.google.android.attestation;
 
+import static com.google.android.attestation.AuthorizationList.UserAuthType.FINGERPRINT;
+import static com.google.android.attestation.AuthorizationList.UserAuthType.PASSWORD;
+import static com.google.android.attestation.AuthorizationList.UserAuthType.USER_AUTH_TYPE_ANY;
+import static com.google.android.attestation.AuthorizationList.UserAuthType.USER_AUTH_TYPE_NONE;
+import static com.google.android.attestation.AuthorizationList.userAuthTypeToEnum;
+import static com.google.android.attestation.Constants.UINT32_MAX;
 import static com.google.common.truth.Truth.assertThat;
 import static com.google.common.truth.Truth8.assertThat;
+import static org.junit.Assert.fail;
 
 import com.google.common.collect.ImmutableSet;
 import java.io.IOException;
@@ -124,4 +131,19 @@
     assertThat(authorizationList.vendorPatchLevel).hasValue(EXPECTED_TEE_VENDOR_PATCH_LEVEL);
     assertThat(authorizationList.bootPatchLevel).hasValue(EXPECTED_TEE_BOOT_PATCH_LEVEL);
   }
+
+  @Test
+  public void testUserAuthTypeToEnum() {
+    assertThat(userAuthTypeToEnum(0L)).isEqualTo(USER_AUTH_TYPE_NONE);
+    assertThat(userAuthTypeToEnum(1L)).isEqualTo(PASSWORD);
+    assertThat(userAuthTypeToEnum(2L)).isEqualTo(FINGERPRINT);
+    assertThat(userAuthTypeToEnum(UINT32_MAX)).isEqualTo(USER_AUTH_TYPE_ANY);
+
+    try {
+      userAuthTypeToEnum(3L);
+      fail();
+    } catch (IllegalArgumentException expected) {
+      assertThat(expected).hasMessageThat().contains("Invalid User Auth Type.");
+    }
+  }
 }