Revert "Delegate auth token parsing to HAL."

This reverts commit 76f21b2676.

Reason for revert: b/36637075

Bug: 36637075
Change-Id: Ica737cf96d14086aae7918f8bf2f86a36555d03b
This commit is contained in:
Shawn Willden 2017-03-28 00:39:16 +00:00
parent 76f21b2676
commit d3ed3a2079
10 changed files with 143 additions and 81 deletions

View file

@ -25,6 +25,33 @@
namespace keystore {
template <typename IntType, uint32_t byteOrder> struct choose_hton;
template <typename IntType> struct choose_hton<IntType, __ORDER_LITTLE_ENDIAN__> {
inline static IntType hton(const IntType& value) {
IntType result = 0;
const unsigned char* inbytes = reinterpret_cast<const unsigned char*>(&value);
unsigned char* outbytes = reinterpret_cast<unsigned char*>(&result);
for (int i = sizeof(IntType) - 1; i >= 0; --i) {
*(outbytes++) = inbytes[i];
}
return result;
}
};
template <typename IntType> struct choose_hton<IntType, __ORDER_BIG_ENDIAN__> {
inline static IntType hton(const IntType& value) { return value; }
};
template <typename IntType> inline IntType hton(const IntType& value) {
return choose_hton<IntType, __BYTE_ORDER__>::hton(value);
}
template <typename IntType> inline IntType ntoh(const IntType& value) {
// same operation and hton
return choose_hton<IntType, __BYTE_ORDER__>::hton(value);
}
//
// Some trivial template wrappers around std algorithms, so they take containers not ranges.
//
@ -48,8 +75,8 @@ time_t clock_gettime_raw() {
return time.tv_sec;
}
void AuthTokenTable::AddAuthenticationToken(hidl_vec<uint8_t> token, HardwareAuthTokenInfo info) {
Entry new_entry(std::move(token), std::move(info), clock_function_());
void AuthTokenTable::AddAuthenticationToken(const HardwareAuthToken* auth_token) {
Entry new_entry(auth_token, clock_function_());
RemoveEntriesSupersededBy(new_entry);
if (entries_.size() >= max_entries_) {
ALOGW("Auth token table filled up; replacing oldest entry");
@ -80,7 +107,7 @@ inline bool KeyRequiresAuthPerOperation(const AuthorizationSet& key_info, KeyPur
AuthTokenTable::Error AuthTokenTable::FindAuthorization(const AuthorizationSet& key_info,
KeyPurpose purpose, uint64_t op_handle,
const hidl_vec<uint8_t>** found) {
const HardwareAuthToken** found) {
if (!KeyRequiresAuthentication(key_info, purpose)) return AUTH_NOT_REQUIRED;
auto auth_type =
@ -98,24 +125,24 @@ AuthTokenTable::Error AuthTokenTable::FindAuthorization(const AuthorizationSet&
AuthTokenTable::Error
AuthTokenTable::FindAuthPerOpAuthorization(const std::vector<uint64_t>& sids,
HardwareAuthenticatorType auth_type, uint64_t op_handle,
const hidl_vec<uint8_t>** found) {
const HardwareAuthToken** found) {
if (op_handle == 0) return OP_HANDLE_REQUIRED;
auto matching_op = find_if(
entries_, [&](Entry& e) { return e.tokenInfo().challenge == op_handle && !e.completed(); });
entries_, [&](Entry& e) { return e.token()->challenge == op_handle && !e.completed(); });
if (matching_op == entries_.end()) return AUTH_TOKEN_NOT_FOUND;
if (!matching_op->SatisfiesAuth(sids, auth_type)) return AUTH_TOKEN_WRONG_SID;
*found = &matching_op->token();
*found = matching_op->token();
return OK;
}
AuthTokenTable::Error AuthTokenTable::FindTimedAuthorization(const std::vector<uint64_t>& sids,
HardwareAuthenticatorType auth_type,
const AuthorizationSet& key_info,
const hidl_vec<uint8_t>** found) {
const HardwareAuthToken** found) {
Entry* newest_match = NULL;
for (auto& entry : entries_)
if (entry.SatisfiesAuth(sids, auth_type) && entry.is_newer_than(newest_match))
@ -137,7 +164,7 @@ AuthTokenTable::Error AuthTokenTable::FindTimedAuthorization(const std::vector<u
}
newest_match->UpdateLastUse(now);
*found = &newest_match->token();
*found = newest_match->token();
return OK;
}
@ -167,7 +194,7 @@ bool AuthTokenTable::IsSupersededBySomeEntry(const Entry& entry) {
}
void AuthTokenTable::MarkCompleted(const uint64_t op_handle) {
auto found = find_if(entries_, [&](Entry& e) { return e.tokenInfo().challenge == op_handle; });
auto found = find_if(entries_, [&](Entry& e) { return e.token()->challenge == op_handle; });
if (found == entries_.end()) return;
assert(!IsSupersededBySomeEntry(*found));
@ -176,16 +203,25 @@ void AuthTokenTable::MarkCompleted(const uint64_t op_handle) {
if (IsSupersededBySomeEntry(*found)) entries_.erase(found);
}
AuthTokenTable::Entry::Entry(hidl_vec<uint8_t>&& token, HardwareAuthTokenInfo&& tokenInfo,
time_t current_time)
: token_(std::move(token)), tokenInfo_(std::move(tokenInfo)), time_received_(current_time),
last_use_(current_time), operation_completed_(tokenInfo_.challenge == 0) {}
AuthTokenTable::Entry::Entry(const HardwareAuthToken* token, time_t current_time)
: token_(token), time_received_(current_time), last_use_(current_time),
operation_completed_(token_->challenge == 0) {}
uint32_t AuthTokenTable::Entry::timestamp_host_order() const {
return ntoh(token_->timestamp);
}
HardwareAuthenticatorType AuthTokenTable::Entry::authenticator_type() const {
HardwareAuthenticatorType result = static_cast<HardwareAuthenticatorType>(
ntoh(static_cast<uint32_t>(token_->authenticatorType)));
return result;
}
bool AuthTokenTable::Entry::SatisfiesAuth(const std::vector<uint64_t>& sids,
HardwareAuthenticatorType auth_type) {
for (auto sid : sids)
if ((sid == tokenInfo_.authenticatorId) ||
(sid == tokenInfo_.userId && (auth_type & tokenInfo_.authenticatorType) != 0))
if ((sid == token_->authenticatorId) ||
(sid == token_->userId && (auth_type & authenticator_type()) != 0))
return true;
return false;
}
@ -197,9 +233,10 @@ void AuthTokenTable::Entry::UpdateLastUse(time_t time) {
bool AuthTokenTable::Entry::Supersedes(const Entry& entry) const {
if (!entry.completed()) return false;
return (tokenInfo_.userId == entry.tokenInfo_.userId &&
tokenInfo_.authenticatorType == entry.tokenInfo_.authenticatorType &&
tokenInfo_.timestamp > entry.tokenInfo_.timestamp);
return (token_->userId == entry.token_->userId &&
token_->authenticatorType == entry.token_->authenticatorType &&
token_->authenticatorType == entry.token_->authenticatorType &&
timestamp_host_order() > entry.timestamp_host_order());
}
} // namespace keymaster

View file

@ -25,7 +25,7 @@
namespace keystore {
using android::hardware::keymaster::V3_0::HardwareAuthTokenInfo;
using android::hardware::keymaster::V3_0::HardwareAuthToken;
namespace test {
class AuthTokenTableTest;
@ -59,9 +59,9 @@ class AuthTokenTable {
};
/**
* Add an authorization token to the table.
* Add an authorization token to the table. The table takes ownership of the argument.
*/
void AddAuthenticationToken(hidl_vec<uint8_t> token, HardwareAuthTokenInfo info);
void AddAuthenticationToken(const HardwareAuthToken* token);
/**
* Find an authorization token that authorizes the operation specified by \p operation_handle on
@ -74,7 +74,7 @@ class AuthTokenTable {
* The table retains ownership of the returned object.
*/
Error FindAuthorization(const AuthorizationSet& key_info, KeyPurpose purpose,
uint64_t op_handle, const hidl_vec<uint8_t>** token_found);
uint64_t op_handle, const HardwareAuthToken** found);
/**
* Mark operation completed. This allows tokens associated with the specified operation to be
@ -97,12 +97,11 @@ class AuthTokenTable {
class Entry {
public:
Entry(hidl_vec<uint8_t>&& token, HardwareAuthTokenInfo&& tokenInfo, time_t current_time);
Entry(const HardwareAuthToken* token, time_t current_time);
Entry(Entry&& entry) { *this = std::move(entry); }
void operator=(Entry&& rhs) {
token_ = std::move(rhs.token_);
tokenInfo_ = std::move(rhs.tokenInfo_);
time_received_ = rhs.time_received_;
last_use_ = rhs.last_use_;
operation_completed_ = rhs.operation_completed_;
@ -117,19 +116,19 @@ class AuthTokenTable {
bool is_newer_than(const Entry* entry) {
if (!entry) return true;
return tokenInfo_.timestamp > entry->tokenInfo_.timestamp;
return timestamp_host_order() > entry->timestamp_host_order();
}
void mark_completed() { operation_completed_ = true; }
const hidl_vec<uint8_t>& token() { return token_; }
const HardwareAuthTokenInfo& tokenInfo() { return tokenInfo_; }
const HardwareAuthToken* token() { return token_.get(); }
time_t time_received() const { return time_received_; }
bool completed() const { return operation_completed_; }
uint32_t timestamp_host_order() const;
HardwareAuthenticatorType authenticator_type() const;
private:
hidl_vec<uint8_t> token_;
HardwareAuthTokenInfo tokenInfo_;
std::unique_ptr<const HardwareAuthToken> token_;
time_t time_received_;
time_t last_use_;
bool operation_completed_;
@ -137,10 +136,10 @@ class AuthTokenTable {
Error FindAuthPerOpAuthorization(const std::vector<uint64_t>& sids,
HardwareAuthenticatorType auth_type, uint64_t op_handle,
const hidl_vec<uint8_t>** found);
const HardwareAuthToken** found);
Error FindTimedAuthorization(const std::vector<uint64_t>& sids,
HardwareAuthenticatorType auth_type,
const AuthorizationSet& key_info, const hidl_vec<uint8_t>** found);
const AuthorizationSet& key_info, const HardwareAuthToken** found);
void ExtractSids(const AuthorizationSet& key_info, std::vector<uint64_t>* sids);
void RemoveEntriesSupersededBy(const Entry& entry);
bool IsSupersededBySomeEntry(const Entry& entry);

View file

@ -70,7 +70,7 @@ using ::android::hardware::keymaster::V3_0::BlockMode;
using ::android::hardware::keymaster::V3_0::Digest;
using ::android::hardware::keymaster::V3_0::EcCurve;
using ::android::hardware::keymaster::V3_0::ErrorCode;
using ::android::hardware::keymaster::V3_0::HardwareAuthTokenInfo;
using ::android::hardware::keymaster::V3_0::HardwareAuthToken;
using ::android::hardware::keymaster::V3_0::HardwareAuthenticatorType;
using ::android::hardware::keymaster::V3_0::IKeymasterDevice;
using ::android::hardware::keymaster::V3_0::KeyBlobUsageRequirements;

View file

@ -97,6 +97,30 @@ inline static OutIter copy_bytes_to_iterator(const T& value, OutIter dest) {
return std::copy(value_ptr, value_ptr + sizeof(value), dest);
}
inline static hidl_vec<uint8_t> authToken2HidlVec(const HardwareAuthToken& token) {
static_assert(
std::is_same<decltype(token.hmac), ::android::hardware::hidl_array<uint8_t, 32>>::value,
"This function assumes token HMAC is 32 bytes, but it might not be.");
static_assert(1 /* version size */ + sizeof(token.challenge) + sizeof(token.userId) +
sizeof(token.authenticatorId) + sizeof(token.authenticatorType) +
sizeof(token.timestamp) + 32 /* HMAC size */
== sizeof(hw_auth_token_t),
"HardwareAuthToken content size does not match hw_auth_token_t size");
hidl_vec<uint8_t> result;
result.resize(sizeof(hw_auth_token_t));
auto pos = result.begin();
*pos++ = 0; // Version byte
pos = copy_bytes_to_iterator(token.challenge, pos);
pos = copy_bytes_to_iterator(token.userId, pos);
pos = copy_bytes_to_iterator(token.authenticatorId, pos);
pos = copy_bytes_to_iterator(token.authenticatorType, pos);
pos = copy_bytes_to_iterator(token.timestamp, pos);
pos = std::copy(token.hmac.data(), token.hmac.data() + token.hmac.size(), pos);
return result;
}
inline std::string hidlVec2String(const hidl_vec<uint8_t>& value) {
return std::string(reinterpret_cast<const std::string::value_type*>(&value[0]), value.size());
}

View file

@ -893,9 +893,9 @@ void KeyStoreService::exportKey(const String16& name, KeyFormat format,
}
}
static inline void addAuthTokenToParams(AuthorizationSet* params, const hidl_vec<uint8_t>* token) {
static inline void addAuthTokenToParams(AuthorizationSet* params, const HardwareAuthToken* token) {
if (token) {
params->push_back(TAG_AUTH_TOKEN, *token);
params->push_back(TAG_AUTH_TOKEN, authToken2HidlVec(*token));
}
}
@ -944,7 +944,7 @@ void KeyStoreService::begin(const sp<IBinder>& appToken, const String16& name, K
return;
}
const hidl_vec<uint8_t>* authToken = NULL;
const HardwareAuthToken* authToken = NULL;
// Merge these characteristics with the ones cached when the key was generated or imported
Blob charBlob;
@ -1050,7 +1050,7 @@ void KeyStoreService::begin(const sp<IBinder>& appToken, const String16& name, K
assert(characteristics.softwareEnforced.size() == 0);
if (authToken) {
mOperationMap.setOperationAuthToken(operationToken, *authToken);
mOperationMap.setOperationAuthToken(operationToken, authToken);
}
// Return the authentication lookup result. If this is a per operation
// auth'd key then the resultCode will be ::OP_AUTH_NEEDED and the
@ -1197,7 +1197,7 @@ bool KeyStoreService::isOperationAuthorized(const sp<IBinder>& token) {
if (!mOperationMap.getOperation(token, &handle, &keyid, &purpose, &dev, &characteristics)) {
return false;
}
const hidl_vec<uint8_t>* authToken = NULL;
const HardwareAuthToken* authToken = NULL;
mOperationMap.getOperationAuthToken(token, &authToken);
AuthorizationSet ignored;
auto authResult = addOperationAuthTokenIfNeeded(token, &ignored);
@ -1205,25 +1205,38 @@ bool KeyStoreService::isOperationAuthorized(const sp<IBinder>& token) {
}
KeyStoreServiceReturnCode KeyStoreService::addAuthToken(const uint8_t* token, size_t length) {
// TODO(swillden): When gatekeeper and fingerprint are ready, this should be updated to
// receive a HardwareAuthToken, rather than an opaque byte array.
if (!checkBinderPermission(P_ADD_AUTH)) {
ALOGW("addAuthToken: permission denied for %d", IPCThreadState::self()->getCallingUid());
return ResponseCode::PERMISSION_DENIED;
}
if (length != sizeof(hw_auth_token_t)) {
return ErrorCode::INVALID_ARGUMENT;
}
hidl_vec<uint8_t> hidl_token;
hidl_token.setToExternal(const_cast<uint8_t*>(token), length);
hw_auth_token_t authToken;
memcpy(reinterpret_cast<void*>(&authToken), token, sizeof(hw_auth_token_t));
if (authToken.version != 0) {
return ErrorCode::INVALID_ARGUMENT;
}
ErrorCode error;
KeyStoreServiceReturnCode rc =
KS_HANDLE_HIDL_ERROR(mKeyStore->getDevice()->parseHardwareAuthToken(
hidl_token, [&](ErrorCode hidlError, const HardwareAuthTokenInfo& tokenInfo) {
error = hidlError;
if (error == ErrorCode::OK) {
mAuthTokenTable.AddAuthenticationToken(hidl_token, tokenInfo);
}
}));
if (rc.isOk()) rc = error;
return rc;
std::unique_ptr<HardwareAuthToken> hidlAuthToken(new HardwareAuthToken);
hidlAuthToken->challenge = authToken.challenge;
hidlAuthToken->userId = authToken.user_id;
hidlAuthToken->authenticatorId = authToken.authenticator_id;
hidlAuthToken->authenticatorType = authToken.authenticator_type;
hidlAuthToken->timestamp = authToken.timestamp;
static_assert(
std::is_same<decltype(hidlAuthToken->hmac),
::android::hardware::hidl_array<uint8_t, sizeof(authToken.hmac)>>::value,
"This function assumes token HMAC is 32 bytes, but it might not be.");
std::copy(authToken.hmac, authToken.hmac + sizeof(authToken.hmac), hidlAuthToken->hmac.data());
// The table takes ownership of authToken.
mAuthTokenTable.AddAuthenticationToken(hidlAuthToken.release());
return ResponseCode::NO_ERROR;
}
constexpr size_t KEY_ATTESTATION_APPLICATION_ID_MAX_SIZE = 1024;
@ -1494,20 +1507,18 @@ ErrorCode KeyStoreService::getOperationCharacteristics(const hidl_vec<uint8_t>&
}
/**
* Get the auth token for this operation from the auth token table. The caller does not acquire
* ownership of the auth token.
* Get the auth token for this operation from the auth token table.
*
* Returns:
* ResponseCode::NO_ERROR if the auth token was set or none was required.
*
* ::OP_AUTH_NEEDED if it is a per op authorization, no authorization token exists for that
* operation and failOnTokenMissing is false.
*
* KM_ERROR_KEY_USER_NOT_AUTHENTICATED if there is no valid auth token for the operation
* Returns ResponseCode::NO_ERROR if the auth token was set or none was required.
* ::OP_AUTH_NEEDED if it is a per op authorization, no
* authorization token exists for that operation and
* failOnTokenMissing is false.
* KM_ERROR_KEY_USER_NOT_AUTHENTICATED if there is no valid auth
* token for the operation
*/
KeyStoreServiceReturnCode KeyStoreService::getAuthToken(const KeyCharacteristics& characteristics,
uint64_t handle, KeyPurpose purpose,
const hidl_vec<uint8_t>** authToken,
const HardwareAuthToken** authToken,
bool failOnTokenMissing) {
AuthorizationSet allCharacteristics;
@ -1549,7 +1560,7 @@ KeyStoreServiceReturnCode KeyStoreService::getAuthToken(const KeyCharacteristics
*/
KeyStoreServiceReturnCode KeyStoreService::addOperationAuthTokenIfNeeded(const sp<IBinder>& token,
AuthorizationSet* params) {
const hidl_vec<uint8_t>* authToken = nullptr;
const HardwareAuthToken* authToken = nullptr;
mOperationMap.getOperationAuthToken(token, &authToken);
if (!authToken) {
km_device_t dev;
@ -1565,7 +1576,7 @@ KeyStoreServiceReturnCode KeyStoreService::addOperationAuthTokenIfNeeded(const s
return result;
}
if (authToken) {
mOperationMap.setOperationAuthToken(token, *authToken);
mOperationMap.setOperationAuthToken(token, authToken);
}
}
addAuthTokenToParams(params, authToken);

View file

@ -203,7 +203,7 @@ class KeyStoreService : public android::BnKeystoreService, public android::IBind
*/
KeyStoreServiceReturnCode getAuthToken(const KeyCharacteristics& characteristics,
uint64_t handle, KeyPurpose purpose,
const hidl_vec<uint8_t>** authToken,
const HardwareAuthToken** authToken,
bool failOnTokenMissing = true);
/**

View file

@ -204,13 +204,6 @@ Return<void> LegacyKeymasterDeviceWrapper::getHardwareFeatures(getHardwareFeatur
return Void();
}
Return<void>
LegacyKeymasterDeviceWrapper::parseHardwareAuthToken(const hidl_vec<uint8_t>& /* token */,
parseHardwareAuthToken_cb _hidl_cb) {
// parseHardwareAuthToken is only called on a real HAL, never on the fallback device.
_hidl_cb(ErrorCode::UNIMPLEMENTED, HardwareAuthTokenInfo());
return Void();
}
Return<ErrorCode> LegacyKeymasterDeviceWrapper::addRngEntropy(const hidl_vec<uint8_t>& data) {
return legacy_enum_conversion(
keymaster_device_->add_rng_entropy(keymaster_device_, &data[0], data.size()));

View file

@ -19,8 +19,8 @@
#define LEGACY_KEYMASTER_DEVICE_WRAPPER_H_
#include <android/hardware/keymaster/3.0/IKeymasterDevice.h>
#include <hidl/MQDescriptor.h>
#include <hidl/Status.h>
#include <hidl/MQDescriptor.h>
struct keymaster2_device;
typedef struct keymaster2_device keymaster2_device_t;
@ -29,7 +29,6 @@ namespace android {
namespace keystore {
using ::android::hardware::keymaster::V3_0::ErrorCode;
using ::android::hardware::keymaster::V3_0::HardwareAuthTokenInfo;
using ::android::hardware::keymaster::V3_0::IKeymasterDevice;
using ::android::hardware::keymaster::V3_0::KeyCharacteristics;
using ::android::hardware::keymaster::V3_0::KeyFormat;
@ -49,8 +48,6 @@ class LegacyKeymasterDeviceWrapper : public IKeymasterDevice {
// Methods from ::android::hardware::keymaster::V3_0::IKeymasterDevice follow.
Return<void> getHardwareFeatures(getHardwareFeatures_cb _hidl_cb);
Return<void> parseHardwareAuthToken(const hidl_vec<uint8_t>& token,
parseHardwareAuthToken_cb _hidl_cb);
Return<ErrorCode> addRngEntropy(const hidl_vec<uint8_t>& data) override;
Return<void> generateKey(const hidl_vec<KeyParameter>& keyParams,
generateKey_cb _hidl_cb) override;

View file

@ -117,22 +117,23 @@ sp<IBinder> OperationMap::getOldestPruneableOperation() {
}
bool OperationMap::getOperationAuthToken(const sp<IBinder>& token,
const hidl_vec<uint8_t>** outToken) {
const HardwareAuthToken** outToken) {
auto entry = mMap.find(token);
if (entry == mMap.end()) {
return false;
}
*outToken = &entry->second.authToken;
*outToken = entry->second.authToken.get();
return true;
}
bool OperationMap::setOperationAuthToken(const sp<IBinder>& token,
hidl_vec<uint8_t> authToken) {
const HardwareAuthToken* authToken) {
auto entry = mMap.find(token);
if (entry == mMap.end()) {
return false;
}
entry->second.authToken = std::move(authToken);
entry->second.authToken.reset(new HardwareAuthToken);
*entry->second.authToken = *authToken;
return true;
}

View file

@ -55,9 +55,9 @@ class OperationMap {
size_t getOperationCount() const { return mMap.size(); }
size_t getPruneableOperationCount() const;
bool getOperationAuthToken(const android::sp<android::IBinder>& token,
const hidl_vec<uint8_t>** outToken);
const HardwareAuthToken** outToken);
bool setOperationAuthToken(const android::sp<android::IBinder>& token,
hidl_vec<uint8_t> authToken);
const HardwareAuthToken* authToken);
android::sp<android::IBinder> getOldestPruneableOperation();
std::vector<android::sp<android::IBinder>>
getOperationsForToken(const android::sp<android::IBinder>& appToken);
@ -76,7 +76,7 @@ class OperationMap {
km_device_t device;
KeyCharacteristics characteristics;
android::sp<android::IBinder> appToken;
hidl_vec<uint8_t> authToken;
std::unique_ptr<HardwareAuthToken> authToken;
};
std::map<android::sp<android::IBinder>, Operation> mMap;
std::vector<android::sp<android::IBinder>> mLru;