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>();