diff options
author | Hasini Gunasinghe <hasinitg@google.com> | 2021-03-02 00:34:58 +0000 |
---|---|---|
committer | Hasini Gunasinghe <hasinitg@google.com> | 2021-03-12 20:25:31 +0000 |
commit | 1b531b91c092e782d5b7959f04f0381c98575d8e (patch) | |
tree | 71abc97a766d5b531347bb279c059a39b844a2ae /identity | |
parent | b3715fb9a6ad50d0f4be942098e27d67250e344b (diff) | |
download | security-1b531b91c092e782d5b7959f04f0381c98575d8e.tar.gz |
Integrate getAuthTokensForCredStore method with credstore.
Bug: 159341610
Test: CtsVerifier
Change-Id: Ia2b7f1a27a05e92c7b5bb5da14caa423a70ac15b
Diffstat (limited to 'identity')
-rw-r--r-- | identity/Android.bp | 4 | ||||
-rw-r--r-- | identity/Credential.cpp | 167 | ||||
-rw-r--r-- | identity/main.cpp | 2 |
3 files changed, 123 insertions, 50 deletions
diff --git a/identity/Android.bp b/identity/Android.bp index ed8ff2f3..5841bf6a 100644 --- a/identity/Android.bp +++ b/identity/Android.bp @@ -39,6 +39,7 @@ cc_binary { shared_libs: [ "libbase", "libbinder", + "libbinder_ndk", "libkeystore_aidl", "libcredstore_aidl", "libutils", @@ -46,6 +47,9 @@ cc_binary { "android.hardware.identity-support-lib", "libkeymaster4support", "libkeystore-attestation-application-id", + "android.hardware.security.keymint-V1-ndk_platform", + "android.security.authorization-ndk_platform", + "PlatformProperties", ], static_libs: [ "android.hardware.identity-V3-cpp", diff --git a/identity/Credential.cpp b/identity/Credential.cpp index a3c72edc..183ddebc 100644 --- a/identity/Credential.cpp +++ b/identity/Credential.cpp @@ -17,7 +17,7 @@ #define LOG_TAG "Credential" #include <android-base/logging.h> - +#include <android/binder_manager.h> #include <android/hardware/identity/support/IdentityCredentialSupport.h> #include <android/security/identity/ICredentialStore.h> @@ -33,6 +33,12 @@ #include <future> #include <tuple> +#include <aidl/android/hardware/security/keymint/HardwareAuthToken.h> +#include <aidl/android/hardware/security/secureclock/TimeStampToken.h> +#include <aidl/android/security/authorization/AuthorizationTokens.h> +#include <aidl/android/security/authorization/IKeystoreAuthorization.h> +#include <android/sysprop/Keystore2Properties.sysprop.h> + #include "Credential.h" #include "CredentialData.h" #include "Util.h" @@ -47,6 +53,7 @@ using std::promise; using std::tuple; using android::security::keystore::IKeystoreService; +using namespace android::sysprop; using ::android::hardware::identity::IWritableIdentityCredential; @@ -55,11 +62,17 @@ using ::android::hardware::identity::support::ecKeyPairGetPrivateKey; using ::android::hardware::identity::support::ecKeyPairGetPublicKey; using ::android::hardware::identity::support::sha256; +using android::hardware::keymaster::SecurityLevel; using android::hardware::keymaster::V4_0::HardwareAuthToken; using android::hardware::keymaster::V4_0::VerificationToken; using AidlHardwareAuthToken = android::hardware::keymaster::HardwareAuthToken; using AidlVerificationToken = android::hardware::keymaster::VerificationToken; +using KeyMintAuthToken = ::aidl::android::hardware::security::keymint::HardwareAuthToken; +using ::aidl::android::hardware::security::secureclock::TimeStampToken; +using ::aidl::android::security::authorization::AuthorizationTokens; +using ::aidl::android::security::authorization::IKeystoreAuthorization; + Credential::Credential(CipherSuite cipherSuite, const std::string& dataPath, const std::string& credentialName, uid_t callingUid, HardwareInformation hwInfo, sp<IIdentityCredentialStore> halStoreBinder, @@ -168,9 +181,10 @@ class CredstoreTokenCallback : public android::security::keystore::BnCredstoreTo // Returns false if an error occurred communicating with keystore. // -bool getTokensFromKeystore(uint64_t challenge, uint64_t secureUserId, - unsigned int authTokenMaxAgeMillis, vector<uint8_t>& authToken, - vector<uint8_t>& verificationToken) { +bool getTokensFromKeystore1(uint64_t challenge, uint64_t secureUserId, + unsigned int authTokenMaxAgeMillis, + AidlHardwareAuthToken& aidlAuthToken, + AidlVerificationToken& aidlVerificationToken) { sp<IServiceManager> sm = defaultServiceManager(); sp<IBinder> binder = sm->getService(String16("android.security.keystore")); sp<IKeystoreService> keystore = interface_cast<IKeystoreService>(binder); @@ -189,19 +203,100 @@ bool getTokensFromKeystore(uint64_t challenge, uint64_t secureUserId, auto fstatus = future.wait_for(std::chrono::milliseconds(5000)); if (fstatus != std::future_status::ready) { - LOG(ERROR) << "Waited 5 seconds from tokens for credstore, aborting"; + LOG(ERROR) << "Waited 5 seconds for tokens from keystore, aborting"; return false; } auto [success, returnedAuthToken, returnedVerificationToken] = future.get(); if (!success) { - LOG(ERROR) << "Error getting tokens from credstore"; + LOG(ERROR) << "Error getting tokens from keystore1"; return false; } - authToken = returnedAuthToken; - verificationToken = returnedVerificationToken; + // It's entirely possible getTokensFromKeystore() succeeded but didn't + // return any tokens (in which case the returned byte-vectors are + // empty). For example, this can happen if no auth token is available + // which satifies e.g. |authTokenMaxAgeMillis|. + // + if (returnedAuthToken.size() > 0) { + HardwareAuthToken authToken = + android::hardware::keymaster::V4_0::support::hidlVec2AuthToken(returnedAuthToken); + // Convert from HIDL to AIDL... + aidlAuthToken.challenge = int64_t(authToken.challenge); + aidlAuthToken.userId = int64_t(authToken.userId); + aidlAuthToken.authenticatorId = int64_t(authToken.authenticatorId); + aidlAuthToken.authenticatorType = ::android::hardware::keymaster::HardwareAuthenticatorType( + int32_t(authToken.authenticatorType)); + aidlAuthToken.timestamp.milliSeconds = int64_t(authToken.timestamp); + aidlAuthToken.mac = authToken.mac; + } + + if (returnedVerificationToken.size() > 0) { + optional<VerificationToken> token = + android::hardware::keymaster::V4_0::support::deserializeVerificationToken( + returnedVerificationToken); + if (!token) { + LOG(ERROR) << "Error deserializing verification token"; + } + aidlVerificationToken.challenge = token->challenge; + aidlVerificationToken.timestamp.milliSeconds = token->timestamp; + aidlVerificationToken.securityLevel = + ::android::hardware::keymaster::SecurityLevel(token->securityLevel); + aidlVerificationToken.mac = token->mac; + } return true; } +// Returns false if an error occurred communicating with keystore. +// +bool getTokensFromKeystore2(uint64_t challenge, uint64_t secureUserId, + unsigned int authTokenMaxAgeMillis, + AidlHardwareAuthToken& aidlAuthToken, + AidlVerificationToken& aidlVerificationToken) { + // try to connect to IKeystoreAuthorization AIDL service first. + AIBinder* authzAIBinder = AServiceManager_checkService("android.security.authorization"); + ::ndk::SpAIBinder authzBinder(authzAIBinder); + auto authzService = IKeystoreAuthorization::fromBinder(authzBinder); + if (authzService) { + AuthorizationTokens authzTokens; + auto result = authzService->getAuthTokensForCredStore(challenge, secureUserId, + authTokenMaxAgeMillis, &authzTokens); + // Convert KeyMint auth token to KeyMaster authtoken, only if tokens are + // returned + if (result.isOk()) { + KeyMintAuthToken keymintAuthToken = authzTokens.authToken; + aidlAuthToken.challenge = keymintAuthToken.challenge; + aidlAuthToken.userId = keymintAuthToken.userId; + aidlAuthToken.authenticatorId = keymintAuthToken.authenticatorId; + aidlAuthToken.authenticatorType = + ::android::hardware::keymaster::HardwareAuthenticatorType( + int32_t(keymintAuthToken.authenticatorType)); + aidlAuthToken.timestamp.milliSeconds = keymintAuthToken.timestamp.milliSeconds; + aidlAuthToken.mac = keymintAuthToken.mac; + + // Convert timestamp token to KeyMaster verification token + TimeStampToken timestampToken = authzTokens.timestampToken; + aidlVerificationToken.challenge = timestampToken.challenge; + aidlVerificationToken.timestamp.milliSeconds = timestampToken.timestamp.milliSeconds; + // Legacy verification tokens were always minted by TEE. + aidlVerificationToken.securityLevel = SecurityLevel::TRUSTED_ENVIRONMENT; + aidlVerificationToken.mac = timestampToken.mac; + } else { + if (result.getServiceSpecificError() == 0) { + // Here we differentiate the errors occurred during communication + // from the service specific errors. + LOG(ERROR) << "Error getting tokens from keystore2: " << result.getDescription(); + return false; + } else { + // Log the reason for not finding auth tokens. + LOG(INFO) << "Auth tokens not found: " << result.getDescription(); + } + } + return true; + } else { + LOG(ERROR) << "Error connecting to IKeystoreAuthorization service"; + return false; + } +} + Status Credential::getEntries(const vector<uint8_t>& requestMessage, const vector<RequestNamespaceParcel>& requestNamespaces, const vector<uint8_t>& sessionTranscript, @@ -334,49 +429,23 @@ Status Credential::getEntries(const vector<uint8_t>& requestMessage, // not a guarantee and it's also not required. // - vector<uint8_t> authTokenBytes; - vector<uint8_t> verificationTokenBytes; - if (!getTokensFromKeystore(selectedChallenge_, data->getSecureUserId(), - authTokenMaxAgeMillis, authTokenBytes, verificationTokenBytes)) { - LOG(ERROR) << "Error getting tokens from keystore"; - return Status::fromServiceSpecificError(ICredentialStore::ERROR_GENERIC, - "Error getting tokens from keystore"); - } - - // It's entirely possible getTokensFromKeystore() succeeded but didn't - // return any tokens (in which case the returned byte-vectors are - // empty). For example, this can happen if no auth token is available - // which satifies e.g. |authTokenMaxAgeMillis|. - // - if (authTokenBytes.size() > 0) { - HardwareAuthToken authToken = - android::hardware::keymaster::V4_0::support::hidlVec2AuthToken(authTokenBytes); - - // Convert from HIDL to AIDL... - aidlAuthToken.challenge = int64_t(authToken.challenge); - aidlAuthToken.userId = int64_t(authToken.userId); - aidlAuthToken.authenticatorId = int64_t(authToken.authenticatorId); - aidlAuthToken.authenticatorType = - ::android::hardware::keymaster::HardwareAuthenticatorType( - int32_t(authToken.authenticatorType)); - aidlAuthToken.timestamp.milliSeconds = int64_t(authToken.timestamp); - aidlAuthToken.mac = authToken.mac; - } - - if (verificationTokenBytes.size() > 0) { - optional<VerificationToken> token = - android::hardware::keymaster::V4_0::support::deserializeVerificationToken( - verificationTokenBytes); - if (!token) { - LOG(ERROR) << "Error deserializing verification token"; + auto keystore2_status = Keystore2Properties::keystore2_enabled(); + if (keystore2_status.has_value() && keystore2_status.value()) { + if (!getTokensFromKeystore2(selectedChallenge_, data->getSecureUserId(), + authTokenMaxAgeMillis, aidlAuthToken, + aidlVerificationToken)) { + LOG(ERROR) << "Error getting tokens from keystore2"; + return Status::fromServiceSpecificError(ICredentialStore::ERROR_GENERIC, + "Error getting tokens from keystore2"); + } + } else { + if (!getTokensFromKeystore1(selectedChallenge_, data->getSecureUserId(), + authTokenMaxAgeMillis, aidlAuthToken, + aidlVerificationToken)) { + LOG(ERROR) << "Error getting tokens from keystore"; return Status::fromServiceSpecificError(ICredentialStore::ERROR_GENERIC, - "Error deserializing verification token"); + "Error getting tokens from keystore"); } - aidlVerificationToken.challenge = token->challenge; - aidlVerificationToken.timestamp.milliSeconds = token->timestamp; - aidlVerificationToken.securityLevel = - ::android::hardware::keymaster::SecurityLevel(token->securityLevel); - aidlVerificationToken.mac = token->mac; } } diff --git a/identity/main.cpp b/identity/main.cpp index 8f4968db..b51bd285 100644 --- a/identity/main.cpp +++ b/identity/main.cpp @@ -40,7 +40,7 @@ using ::android::base::StderrLogger; using ::android::security::identity::CredentialStoreFactory; int main(int argc, char* argv[]) { - InitLogging(argv, StderrLogger); + InitLogging(argv); CHECK(argc == 2) << "A directory must be specified"; string data_dir = string(argv[1]); |