Identity Credential: Add method to accept verification token.

This is to facilitate HAL implementations using a TA existing in a
different environment than where auth tokens are minted. This method
will be used by credstore in a companion CL.

This modifies version 2 of the Identity Credential API (which was
never been released) to add a new method and creates version 2 of the
Keymaster types-only AIDL API to include the new VerificationToken
parcelable and SecurityLevel enum.

Bug: 156076333
Test: atest VtsHalIdentityTargetTest
Test: atest android.security.identity.cts

Change-Id: I7d05413a9ec70225ce419079f3cc9daf026cf744
diff --git a/identity/aidl/default/IdentityCredential.cpp b/identity/aidl/default/IdentityCredential.cpp
index ff4107a..381eb84 100644
--- a/identity/aidl/default/IdentityCredential.cpp
+++ b/identity/aidl/default/IdentityCredential.cpp
@@ -198,15 +198,8 @@
     return false;
 }
 
-Timestamp clockGetTime() {
-    struct timespec time;
-    clock_gettime(CLOCK_MONOTONIC, &time);
-    Timestamp ts;
-    ts.milliSeconds = time.tv_sec * 1000 + time.tv_nsec / 1000000;
-    return ts;
-}
-
 bool checkUserAuthentication(const SecureAccessControlProfile& profile,
+                             const VerificationToken& verificationToken,
                              const HardwareAuthToken& authToken, uint64_t authChallenge) {
     if (profile.secureUserId != authToken.userId) {
         LOG(ERROR) << "secureUserId in profile (" << profile.secureUserId
@@ -214,6 +207,15 @@
         return false;
     }
 
+    if (verificationToken.timestamp.milliSeconds == 0) {
+        LOG(ERROR) << "VerificationToken is not set";
+        return false;
+    }
+    if (authToken.timestamp.milliSeconds == 0) {
+        LOG(ERROR) << "AuthToken is not set";
+        return false;
+    }
+
     if (profile.timeoutMillis == 0) {
         if (authToken.challenge == 0) {
             LOG(ERROR) << "No challenge in authToken";
@@ -227,19 +229,11 @@
         return true;
     }
 
-    // Note that the Epoch for timestamps in HardwareAuthToken is at the
-    // discretion of the vendor:
+    // Timeout-based user auth follows. The verification token conveys what the
+    // time is right now in the environment which generated the auth token. This
+    // is what makes it possible to do timeout-based checks.
     //
-    //   "[...] since some starting point (generally the most recent device
-    //    boot) which all of the applications within one secure environment
-    //    must agree upon."
-    //
-    // Therefore, if this software implementation is used on a device which isn't
-    // the emulator then the assumption that the epoch is the same as used in
-    // clockGetTime above will not hold. This is OK as this software
-    // implementation should never be used on a real device.
-    //
-    Timestamp now = clockGetTime();
+    const Timestamp now = verificationToken.timestamp;
     if (authToken.timestamp.milliSeconds > now.milliSeconds) {
         LOG(ERROR) << "Timestamp in authToken (" << authToken.timestamp.milliSeconds
                    << ") is in the future (now: " << now.milliSeconds << ")";
@@ -261,6 +255,12 @@
     return ndk::ScopedAStatus::ok();
 }
 
+ndk::ScopedAStatus IdentityCredential::setVerificationToken(
+        const VerificationToken& verificationToken) {
+    verificationToken_ = verificationToken;
+    return ndk::ScopedAStatus::ok();
+}
+
 ndk::ScopedAStatus IdentityCredential::startRetrieval(
         const vector<SecureAccessControlProfile>& accessControlProfiles,
         const HardwareAuthToken& authToken, const vector<uint8_t>& itemsRequest,
@@ -483,7 +483,8 @@
         }
         int accessControlCheck = IIdentityCredentialStore::STATUS_OK;
         if (profile.userAuthenticationRequired) {
-            if (!haveAuthToken || !checkUserAuthentication(profile, authToken, authChallenge_)) {
+            if (!haveAuthToken ||
+                !checkUserAuthentication(profile, verificationToken_, authToken, authChallenge_)) {
                 accessControlCheck = IIdentityCredentialStore::STATUS_USER_AUTHENTICATION_FAILED;
             }
         } else if (profile.readerCertificate.encodedCertificate.size() > 0) {
diff --git a/identity/aidl/default/IdentityCredential.h b/identity/aidl/default/IdentityCredential.h
index a8bad88..a82531d 100644
--- a/identity/aidl/default/IdentityCredential.h
+++ b/identity/aidl/default/IdentityCredential.h
@@ -19,6 +19,7 @@
 
 #include <aidl/android/hardware/identity/BnIdentityCredential.h>
 #include <aidl/android/hardware/keymaster/HardwareAuthToken.h>
+#include <aidl/android/hardware/keymaster/VerificationToken.h>
 #include <android/hardware/identity/support/IdentityCredentialSupport.h>
 
 #include <map>
@@ -31,6 +32,7 @@
 namespace aidl::android::hardware::identity {
 
 using ::aidl::android::hardware::keymaster::HardwareAuthToken;
+using ::aidl::android::hardware::keymaster::VerificationToken;
 using ::std::map;
 using ::std::set;
 using ::std::string;
@@ -55,6 +57,7 @@
     ndk::ScopedAStatus createAuthChallenge(int64_t* outChallenge) override;
     ndk::ScopedAStatus setRequestedNamespaces(
             const vector<RequestNamespace>& requestNamespaces) override;
+    ndk::ScopedAStatus setVerificationToken(const VerificationToken& verificationToken) override;
     ndk::ScopedAStatus startRetrieval(
             const vector<SecureAccessControlProfile>& accessControlProfiles,
             const HardwareAuthToken& authToken, const vector<uint8_t>& itemsRequest,
@@ -93,6 +96,9 @@
     // Set by setRequestedNamespaces()
     vector<RequestNamespace> requestNamespaces_;
 
+    // Set by setVerificationToken().
+    VerificationToken verificationToken_;
+
     // Set at startRetrieval() time.
     map<int32_t, int> profileIdToAccessCheckResult_;
     vector<uint8_t> signingKeyBlob_;
diff --git a/identity/aidl/default/service.cpp b/identity/aidl/default/service.cpp
index f05c615..bf95df5 100644
--- a/identity/aidl/default/service.cpp
+++ b/identity/aidl/default/service.cpp
@@ -22,9 +22,14 @@
 
 #include "IdentityCredentialStore.h"
 
+using ::android::base::InitLogging;
+using ::android::base::StderrLogger;
+
 using aidl::android::hardware::identity::IdentityCredentialStore;
 
-int main() {
+int main(int /*argc*/, char* argv[]) {
+    InitLogging(argv, StderrLogger);
+
     ABinderProcess_setThreadPoolMaxThreadCount(0);
     std::shared_ptr<IdentityCredentialStore> store =
             ndk::SharedRefBase::make<IdentityCredentialStore>();