Move keystore to Keymaster4
Test: CTS
Change-Id: I6b7fa300f505ee685b1fe503edea3188225a98e3
diff --git a/keystore/key_store_service.cpp b/keystore/key_store_service.cpp
index 9459520..137ab48 100644
--- a/keystore/key_store_service.cpp
+++ b/keystore/key_store_service.cpp
@@ -1172,16 +1172,12 @@
return Status::ok();
}
-static inline void addAuthTokenToParams(AuthorizationSet* params, const HardwareAuthToken* token) {
- if (token) {
- params->push_back(TAG_AUTH_TOKEN, authToken2HidlVec(*token));
- }
-}
-
Status KeyStoreService::begin(const sp<IBinder>& appToken, const String16& name, int32_t purpose,
bool pruneable, const KeymasterArguments& params,
const ::std::vector<uint8_t>& entropy, int32_t uid,
OperationResult* result) {
+ auto keyPurpose = static_cast<KeyPurpose>(purpose);
+
uid_t callingUid = IPCThreadState::self()->getCallingUid();
uid_t targetUid = getEffectiveUid(uid);
if (!is_granted_to(callingUid, targetUid)) {
@@ -1198,15 +1194,14 @@
result->resultCode = ErrorCode::INVALID_ARGUMENT;
return Status::ok();
}
+
Blob keyBlob;
String8 name8(name);
result->resultCode = mKeyStore->getKeyForName(&keyBlob, name8, targetUid, TYPE_KEYMASTER_10);
if (result->resultCode == ResponseCode::LOCKED && keyBlob.isSuperEncrypted()) {
result->resultCode = ErrorCode::KEY_USER_NOT_AUTHENTICATED;
}
- if (!result->resultCode.isOk()) {
- return Status::ok();
- }
+ if (!result->resultCode.isOk()) return Status::ok();
auto key = blob2hidlVec(keyBlob);
auto& dev = mKeyStore->getDevice(keyBlob);
@@ -1226,8 +1221,6 @@
return Status::ok();
}
- const HardwareAuthToken* authToken = NULL;
-
// Merge these characteristics with the ones cached when the key was generated or imported
Blob charBlob;
AuthorizationSet persistedCharacteristics;
@@ -1245,13 +1238,17 @@
// Replace the sw_enforced set with those persisted to disk, minus hw_enforced
AuthorizationSet softwareEnforced = characteristics.softwareEnforced;
- AuthorizationSet teeEnforced = characteristics.teeEnforced;
+ AuthorizationSet hardwareEnforced = characteristics.hardwareEnforced;
persistedCharacteristics.Union(softwareEnforced);
- persistedCharacteristics.Subtract(teeEnforced);
+ persistedCharacteristics.Subtract(hardwareEnforced);
characteristics.softwareEnforced = persistedCharacteristics.hidl_data();
- auto authResult = getAuthToken(characteristics, 0, KeyPurpose(purpose), &authToken,
- /*failOnTokenMissing*/ false);
+ KeyStoreServiceReturnCode authResult;
+ HardwareAuthToken authToken;
+ std::tie(authResult, authToken) =
+ getAuthToken(characteristics, 0 /* no challenge */, keyPurpose,
+ /*failOnTokenMissing*/ false);
+
// If per-operation auth is needed we need to begin the operation and
// the client will need to authorize that operation before calling
// update. Any other auth issues stop here.
@@ -1260,8 +1257,6 @@
return Status::ok();
}
- addAuthTokenToParams(&opParams, authToken);
-
// Add entropy to the device first.
if (entropy.size()) {
int32_t resultCode;
@@ -1281,12 +1276,12 @@
}
// Check that all key authorization policy requirements are met.
- AuthorizationSet key_auths = characteristics.teeEnforced;
- key_auths.append(&characteristics.softwareEnforced[0],
- &characteristics.softwareEnforced[characteristics.softwareEnforced.size()]);
+ AuthorizationSet key_auths = characteristics.hardwareEnforced;
+ key_auths.append(characteristics.softwareEnforced.begin(),
+ characteristics.softwareEnforced.end());
result->resultCode =
- enforcement_policy.AuthorizeOperation(KeyPurpose(purpose), keyid, key_auths, opParams,
+ enforcement_policy.AuthorizeOperation(keyPurpose, keyid, key_auths, opParams, authToken,
0 /* op_handle */, true /* is_begin_operation */);
if (!result->resultCode.isOk()) {
return Status::ok();
@@ -1312,7 +1307,7 @@
};
ErrorCode rc =
- KS_HANDLE_HIDL_ERROR(dev->begin(KeyPurpose(purpose), key, opParams.hidl_data(), hidlCb));
+ KS_HANDLE_HIDL_ERROR(dev->begin(keyPurpose, key, opParams.hidl_data(), authToken, hidlCb));
if (rc != ErrorCode::OK) {
ALOGW("Got error %d from begin()", rc);
}
@@ -1325,7 +1320,7 @@
break;
}
rc = KS_HANDLE_HIDL_ERROR(
- dev->begin(KeyPurpose(purpose), key, opParams.hidl_data(), hidlCb));
+ dev->begin(keyPurpose, key, opParams.hidl_data(), authToken, hidlCb));
}
if (rc != ErrorCode::OK) {
result->resultCode = rc;
@@ -1334,16 +1329,14 @@
// Note: The operation map takes possession of the contents of "characteristics".
// It is safe to use characteristics after the following line but it will be empty.
- sp<IBinder> operationToken =
- mOperationMap.addOperation(result->handle, keyid, KeyPurpose(purpose), dev, appToken,
- std::move(characteristics), pruneable);
- assert(characteristics.teeEnforced.size() == 0);
+ sp<IBinder> operationToken = mOperationMap.addOperation(
+ result->handle, keyid, keyPurpose, dev, appToken, std::move(characteristics), pruneable);
+ assert(characteristics.hardwareEnforced.size() == 0);
assert(characteristics.softwareEnforced.size() == 0);
result->token = operationToken;
- if (authToken) {
- mOperationMap.setOperationAuthToken(operationToken, *authToken);
- }
+ mOperationMap.setOperationAuthToken(operationToken, std::move(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
// application should get an auth token using the handle before the
@@ -1371,17 +1364,18 @@
}
const auto& op = getOpResult.value();
- AuthorizationSet opParams = params.getParameters();
- result->resultCode = addOperationAuthTokenIfNeeded(token, &opParams);
+ HardwareAuthToken authToken;
+ std::tie(result->resultCode, authToken) = getOperationAuthTokenIfNeeded(token);
if (!result->resultCode.isOk()) return Status::ok();
// Check that all key authorization policy requirements are met.
- AuthorizationSet key_auths(op.characteristics.teeEnforced);
+ AuthorizationSet key_auths(op.characteristics.hardwareEnforced);
key_auths.append(op.characteristics.softwareEnforced.begin(),
op.characteristics.softwareEnforced.end());
result->resultCode = enforcement_policy.AuthorizeOperation(
- op.purpose, op.keyid, key_auths, opParams, op.handle, false /* is_begin_operation */);
+ op.purpose, op.keyid, key_auths, params.getParameters(), authToken, op.handle,
+ false /* is_begin_operation */);
if (!result->resultCode.isOk()) return Status::ok();
auto hidlCb = [&](ErrorCode ret, uint32_t inputConsumed,
@@ -1395,8 +1389,8 @@
}
};
- KeyStoreServiceReturnCode rc =
- KS_HANDLE_HIDL_ERROR(op.device->update(op.handle, opParams.hidl_data(), data, hidlCb));
+ KeyStoreServiceReturnCode rc = KS_HANDLE_HIDL_ERROR(op.device->update(
+ op.handle, params.getParameters(), data, authToken, VerificationToken(), hidlCb));
// just a reminder: on success result->resultCode was set in the callback. So we only overwrite
// it if there was a communication error indicated by the ErrorCode.
@@ -1419,8 +1413,8 @@
return Status::ok();
}
- AuthorizationSet opParams = params.getParameters();
- result->resultCode = addOperationAuthTokenIfNeeded(token, &opParams);
+ HardwareAuthToken authToken;
+ std::tie(result->resultCode, authToken) = getOperationAuthTokenIfNeeded(token);
if (!result->resultCode.isOk()) return Status::ok();
if (entropy.size()) {
@@ -1433,12 +1427,13 @@
}
// Check that all key authorization policy requirements are met.
- AuthorizationSet key_auths(op.characteristics.teeEnforced);
+ AuthorizationSet key_auths(op.characteristics.hardwareEnforced);
key_auths.append(op.characteristics.softwareEnforced.begin(),
op.characteristics.softwareEnforced.end());
result->resultCode = enforcement_policy.AuthorizeOperation(
- op.purpose, op.keyid, key_auths, opParams, op.handle, false /* is_begin_operation */);
+ op.purpose, op.keyid, key_auths, params.getParameters(), authToken, op.handle,
+ false /* is_begin_operation */);
if (!result->resultCode.isOk()) return Status::ok();
auto hidlCb = [&](ErrorCode ret, const hidl_vec<KeyParameter>& outParams,
@@ -1451,9 +1446,9 @@
};
KeyStoreServiceReturnCode rc = KS_HANDLE_HIDL_ERROR(
- op.device->finish(op.handle, opParams.hidl_data(),
+ op.device->finish(op.handle, params.getParameters(),
::std::vector<uint8_t>() /* TODO(swillden): wire up input to finish() */,
- signature, hidlCb));
+ signature, authToken, VerificationToken(), hidlCb));
mOperationMap.removeOperation(token);
mAuthTokenTable.MarkCompleted(op.handle);
@@ -1481,8 +1476,9 @@
Status KeyStoreService::isOperationAuthorized(const sp<IBinder>& token, bool* aidl_return) {
AuthorizationSet ignored;
- auto authResult = addOperationAuthTokenIfNeeded(token, &ignored);
- *aidl_return = authResult.isOk();
+ KeyStoreServiceReturnCode rc;
+ std::tie(rc, std::ignore) = getOperationAuthTokenIfNeeded(token);
+ *aidl_return = rc.isOk();
return Status::ok();
}
@@ -1509,19 +1505,7 @@
return Status::ok();
}
- 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());
-
- mAuthTokenTable.AddAuthenticationToken(std::move(hidlAuthToken));
+ mAuthTokenTable.AddAuthenticationToken(hidlVec2AuthToken(hidl_vec<uint8_t>(authTokenAsVector)));
*aidl_return = static_cast<int32_t>(ResponseCode::NO_ERROR);
return Status::ok();
}
@@ -1814,14 +1798,13 @@
}
/**
- * Check that all KeyParameter's provided by the application are
- * allowed. Any parameter that keystore adds itself should be disallowed here.
+ * Check that all KeyParameters provided by the application are allowed. Any parameter that keystore
+ * adds itself should be disallowed here.
*/
bool KeyStoreService::checkAllowedOperationParams(const hidl_vec<KeyParameter>& params) {
for (size_t i = 0; i < params.size(); ++i) {
switch (params[i].tag) {
case Tag::ATTESTATION_APPLICATION_ID:
- case Tag::AUTH_TOKEN:
case Tag::RESET_SINCE_ID_ROTATION:
return false;
default:
@@ -1871,36 +1854,44 @@
* 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 HardwareAuthToken** authToken,
- bool failOnTokenMissing) {
+std::pair<KeyStoreServiceReturnCode, HardwareAuthToken>
+KeyStoreService::getAuthToken(const KeyCharacteristics& characteristics, uint64_t handle,
+ KeyPurpose purpose, bool failOnTokenMissing) {
- AuthorizationSet allCharacteristics;
- for (size_t i = 0; i < characteristics.softwareEnforced.size(); i++) {
- allCharacteristics.push_back(characteristics.softwareEnforced[i]);
- }
- for (size_t i = 0; i < characteristics.teeEnforced.size(); i++) {
- allCharacteristics.push_back(characteristics.teeEnforced[i]);
- }
+ AuthorizationSet allCharacteristics(characteristics.softwareEnforced);
+ allCharacteristics.append(characteristics.hardwareEnforced.begin(),
+ characteristics.hardwareEnforced.end());
+
+ const HardwareAuthToken* authToken = nullptr;
AuthTokenTable::Error err = mAuthTokenTable.FindAuthorization(
- allCharacteristics, KeyPurpose(purpose), handle, authToken);
+ allCharacteristics, static_cast<KeyPurpose>(purpose), handle, &authToken);
+
+ KeyStoreServiceReturnCode rc;
+
switch (err) {
case AuthTokenTable::OK:
case AuthTokenTable::AUTH_NOT_REQUIRED:
- return ResponseCode::NO_ERROR;
+ rc = ResponseCode::NO_ERROR;
+ break;
+
case AuthTokenTable::AUTH_TOKEN_NOT_FOUND:
case AuthTokenTable::AUTH_TOKEN_EXPIRED:
case AuthTokenTable::AUTH_TOKEN_WRONG_SID:
ALOGE("getAuthToken failed: %d", err); // STOPSHIP: debug only, to be removed
- return ErrorCode::KEY_USER_NOT_AUTHENTICATED;
+ rc = ErrorCode::KEY_USER_NOT_AUTHENTICATED;
+ break;
+
case AuthTokenTable::OP_HANDLE_REQUIRED:
- return failOnTokenMissing ? KeyStoreServiceReturnCode(ErrorCode::KEY_USER_NOT_AUTHENTICATED)
- : KeyStoreServiceReturnCode(ResponseCode::OP_AUTH_NEEDED);
+ rc = failOnTokenMissing ? KeyStoreServiceReturnCode(ErrorCode::KEY_USER_NOT_AUTHENTICATED)
+ : KeyStoreServiceReturnCode(ResponseCode::OP_AUTH_NEEDED);
+ break;
+
default:
ALOGE("Unexpected FindAuthorization return value %d", err);
- return ErrorCode::INVALID_ARGUMENT;
+ rc = ErrorCode::INVALID_ARGUMENT;
}
+
+ return {rc, authToken ? std::move(*authToken) : HardwareAuthToken()};
}
/**
@@ -1914,21 +1905,23 @@
* KM_ERROR_INVALID_OPERATION_HANDLE if token is not a valid
* operation token.
*/
-KeyStoreServiceReturnCode KeyStoreService::addOperationAuthTokenIfNeeded(const sp<IBinder>& token,
- AuthorizationSet* params) {
+std::pair<KeyStoreServiceReturnCode, const HardwareAuthToken&>
+KeyStoreService::getOperationAuthTokenIfNeeded(const sp<IBinder>& token) {
+ static HardwareAuthToken emptyToken = {};
+
auto getOpResult = mOperationMap.getOperation(token);
- if (!getOpResult.isOk()) return ErrorCode::INVALID_OPERATION_HANDLE;
+ if (!getOpResult.isOk()) return {ErrorCode::INVALID_OPERATION_HANDLE, emptyToken};
const auto& op = getOpResult.value();
- if (!op.authToken) {
- const HardwareAuthToken* found = nullptr;
- auto result = getAuthToken(op.characteristics, op.handle, op.purpose, &found);
- if (!result.isOk()) return result;
- if (found) mOperationMap.setOperationAuthToken(token, *found);
- assert(*op.authToken == *found);
+ if (!op.hasAuthToken()) {
+ KeyStoreServiceReturnCode rc;
+ HardwareAuthToken found;
+ std::tie(rc, found) = getAuthToken(op.characteristics, op.handle, op.purpose);
+ if (!rc.isOk()) return {rc, emptyToken};
+ mOperationMap.setOperationAuthToken(token, std::move(found));
}
- addAuthTokenToParams(params, op.authToken.get());
- return ResponseCode::NO_ERROR;
+
+ return {ResponseCode::NO_ERROR, op.authToken};
}
/**
@@ -1936,23 +1929,19 @@
* preserved and keymaster errors become SYSTEM_ERRORs
*/
KeyStoreServiceReturnCode KeyStoreService::translateResultToLegacyResult(int32_t result) {
- if (result > 0) {
- return static_cast<ResponseCode>(result);
- }
+ if (result > 0) return static_cast<ResponseCode>(result);
return ResponseCode::SYSTEM_ERROR;
}
static NullOr<const Algorithm&> getKeyAlgoritmFromKeyCharacteristics(
const ::android::security::keymaster::KeyCharacteristics& characteristics) {
- for (size_t i = 0; i < characteristics.teeEnforced.getParameters().size(); ++i) {
- auto algo =
- authorizationValue(TAG_ALGORITHM, characteristics.teeEnforced.getParameters()[i]);
- if (algo.isOk()) return algo.value();
+ for (const auto& param : characteristics.hardwareEnforced.getParameters()) {
+ auto algo = authorizationValue(TAG_ALGORITHM, param);
+ if (algo.isOk()) return algo;
}
- for (size_t i = 0; i < characteristics.softwareEnforced.getParameters().size(); ++i) {
- auto algo =
- authorizationValue(TAG_ALGORITHM, characteristics.softwareEnforced.getParameters()[i]);
- if (algo.isOk()) return algo.value();
+ for (const auto& param : characteristics.softwareEnforced.getParameters()) {
+ auto algo = authorizationValue(TAG_ALGORITHM, param);
+ if (algo.isOk()) return algo;
}
return {};
}