platform_system_security/keystore/key_store_service.cpp
Janis Danisevskis 8c4c1d6efb Fix memory leak in keystore
The operation device map needs to be cleand up on finish regardless of
whether the operations succeeds of fails. The operation lifecycle ends
in any case.

Bug: 141317862
Test: Generate key and perform repeated operations.
      Watch memory consumptoin not raise with using:
      adb shell dumpsys meminfo keystore

Change-Id: I3a25aa67f121832640848a38398c523e20a2c6df
2019-10-04 11:01:54 -07:00

1366 lines
52 KiB
C++

/*
* Copyright (C) 2016 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#define LOG_TAG "keystore"
#include "key_store_service.h"
#include <fcntl.h>
#include <sys/stat.h>
#include <algorithm>
#include <atomic>
#include <sstream>
#include <android-base/scopeguard.h>
#include <binder/IInterface.h>
#include <binder/IPCThreadState.h>
#include <binder/IPermissionController.h>
#include <binder/IServiceManager.h>
#include <cutils/multiuser.h>
#include <log/log_event_list.h>
#include <private/android_filesystem_config.h>
#include <private/android_logger.h>
#include <android/hardware/confirmationui/1.0/IConfirmationUI.h>
#include <android/hardware/keymaster/3.0/IHwKeymasterDevice.h>
#include "defaults.h"
#include "key_proto_handler.h"
#include "keystore_attestation_id.h"
#include "keystore_keymaster_enforcement.h"
#include "keystore_utils.h"
#include <keystore/keystore_hidl_support.h>
#include <keystore/keystore_return_types.h>
#include <hardware/hw_auth_token.h>
namespace keystore {
using namespace android;
namespace {
using ::android::binder::Status;
using android::security::keymaster::ExportResult;
using android::security::keymaster::KeymasterArguments;
using android::security::keymaster::KeymasterBlob;
using android::security::keymaster::KeymasterCertificateChain;
using android::security::keymaster::operationFailed;
using android::security::keymaster::OperationResult;
using ConfirmationResponseCode = android::hardware::confirmationui::V1_0::ResponseCode;
using ::android::security::keystore::IKeystoreOperationResultCallback;
using ::android::security::keystore::IKeystoreResponseCallback;
using ::android::security::keystore::KeystoreResponse;
constexpr double kIdRotationPeriod = 30 * 24 * 60 * 60; /* Thirty days, in seconds */
const char* kTimestampFilePath = "timestamp";
bool containsTag(const hidl_vec<KeyParameter>& params, Tag tag) {
return params.end() !=
std::find_if(params.begin(), params.end(),
[&](const KeyParameter& param) { return param.tag == tag; });
}
#define AIDL_RETURN(rc) (*_aidl_return = KeyStoreServiceReturnCode(rc).getErrorCode(), Status::ok())
#define KEYSTORE_SERVICE_LOCK std::lock_guard<std::mutex> keystore_lock(keystoreServiceMutex_)
std::pair<KeyStoreServiceReturnCode, bool> hadFactoryResetSinceIdRotation() {
struct stat sbuf;
if (stat(kTimestampFilePath, &sbuf) == 0) {
double diff_secs = difftime(time(nullptr), sbuf.st_ctime);
return {ResponseCode::NO_ERROR, diff_secs < kIdRotationPeriod};
}
if (errno != ENOENT) {
ALOGE("Failed to stat \"timestamp\" file, with error %d", errno);
return {ResponseCode::SYSTEM_ERROR, false /* don't care */};
}
int fd = creat(kTimestampFilePath, 0600);
if (fd < 0) {
ALOGE("Couldn't create \"timestamp\" file, with error %d", errno);
return {ResponseCode::SYSTEM_ERROR, false /* don't care */};
}
if (close(fd)) {
ALOGE("Couldn't close \"timestamp\" file, with error %d", errno);
return {ResponseCode::SYSTEM_ERROR, false /* don't care */};
}
return {ResponseCode::NO_ERROR, true};
}
using ::android::security::KEY_ATTESTATION_APPLICATION_ID_MAX_SIZE;
KeyStoreServiceReturnCode updateParamsForAttestation(uid_t callingUid, AuthorizationSet* params) {
KeyStoreServiceReturnCode responseCode;
bool factoryResetSinceIdRotation;
std::tie(responseCode, factoryResetSinceIdRotation) = hadFactoryResetSinceIdRotation();
if (!responseCode.isOk()) return responseCode;
if (factoryResetSinceIdRotation) params->push_back(TAG_RESET_SINCE_ID_ROTATION);
auto asn1_attestation_id_result = security::gather_attestation_application_id(callingUid);
if (!asn1_attestation_id_result.isOk()) {
ALOGE("failed to gather attestation_id");
// Couldn't get attestation ID; just use an empty one rather than failing.
asn1_attestation_id_result = std::vector<uint8_t>();
}
std::vector<uint8_t>& asn1_attestation_id = asn1_attestation_id_result;
/*
* The attestation application ID must not be longer than
* KEY_ATTESTATION_APPLICATION_ID_MAX_SIZE, error out if gather_attestation_application_id
* returned such an invalid vector.
*/
if (asn1_attestation_id.size() > KEY_ATTESTATION_APPLICATION_ID_MAX_SIZE) {
ALOGE("BUG: Gathered Attestation Application ID is too big (%d)",
static_cast<int32_t>(asn1_attestation_id.size()));
return ErrorCode::CANNOT_ATTEST_IDS;
}
params->push_back(TAG_ATTESTATION_APPLICATION_ID, asn1_attestation_id);
return ResponseCode::NO_ERROR;
}
} // anonymous namespace
Status KeyStoreService::getState(int32_t userId, int32_t* aidl_return) {
KEYSTORE_SERVICE_LOCK;
if (!checkBinderPermission(P_GET_STATE)) {
*aidl_return = static_cast<int32_t>(ResponseCode::PERMISSION_DENIED);
return Status::ok();
}
*aidl_return = mKeyStore->getState(userId);
return Status::ok();
}
Status KeyStoreService::get(const String16& name, int32_t uid, ::std::vector<uint8_t>* item) {
KEYSTORE_SERVICE_LOCK;
uid_t targetUid = getEffectiveUid(uid);
if (!checkBinderPermission(P_GET, targetUid)) {
// see keystore/keystore.h
return Status::fromServiceSpecificError(
static_cast<int32_t>(ResponseCode::PERMISSION_DENIED));
}
String8 name8(name);
ResponseCode rc;
Blob keyBlob;
Blob charBlob;
LockedKeyBlobEntry lockedEntry;
std::tie(rc, keyBlob, charBlob, lockedEntry) =
mKeyStore->getKeyForName(name8, targetUid, TYPE_GENERIC);
if (rc != ResponseCode::NO_ERROR) {
*item = ::std::vector<uint8_t>();
// Return empty array if key is not found
// TODO: consider having returned value nullable or parse exception on the client.
return Status::fromServiceSpecificError(static_cast<int32_t>(rc));
}
auto resultBlob = blob2hidlVec(keyBlob);
// The static_cast here is needed to prevent a move, forcing a deep copy.
if (item) *item = static_cast<const hidl_vec<uint8_t>&>(blob2hidlVec(keyBlob));
return Status::ok();
}
Status KeyStoreService::insert(const String16& name, const ::std::vector<uint8_t>& item,
int targetUid, int32_t flags, int32_t* aidl_return) {
KEYSTORE_SERVICE_LOCK;
targetUid = getEffectiveUid(targetUid);
KeyStoreServiceReturnCode result =
checkBinderPermissionAndKeystoreState(P_INSERT, targetUid, flags & KEYSTORE_FLAG_ENCRYPTED);
if (!result.isOk()) {
*aidl_return = result.getErrorCode();
return Status::ok();
}
String8 name8(name);
auto lockedEntry = mKeyStore->getLockedBlobEntryIfNotExists(name8.string(), targetUid);
if (!lockedEntry) {
ALOGE("failed to grab lock on blob entry %u_%s", targetUid, name8.string());
*aidl_return = static_cast<int32_t>(ResponseCode::KEY_ALREADY_EXISTS);
return Status::ok();
}
Blob keyBlob(&item[0], item.size(), nullptr, 0, ::TYPE_GENERIC);
keyBlob.setEncrypted(flags & KEYSTORE_FLAG_ENCRYPTED);
*aidl_return = static_cast<int32_t>(mKeyStore->put(lockedEntry, keyBlob, {}));
return Status::ok();
}
Status KeyStoreService::del(const String16& name, int targetUid, int32_t* aidl_return) {
KEYSTORE_SERVICE_LOCK;
targetUid = getEffectiveUid(targetUid);
if (!checkBinderPermission(P_DELETE, targetUid)) {
*aidl_return = static_cast<int32_t>(ResponseCode::PERMISSION_DENIED);
return Status::ok();
}
String8 name8(name);
ALOGI("del %s %d", name8.string(), targetUid);
auto lockedEntry = mKeyStore->getLockedBlobEntryIfExists(name8.string(), targetUid);
if (!lockedEntry) {
*aidl_return = static_cast<int32_t>(ResponseCode::KEY_NOT_FOUND);
return Status::ok();
}
ResponseCode result = mKeyStore->del(lockedEntry);
*aidl_return = static_cast<int32_t>(result);
return Status::ok();
}
Status KeyStoreService::exist(const String16& name, int targetUid, int32_t* aidl_return) {
KEYSTORE_SERVICE_LOCK;
targetUid = getEffectiveUid(targetUid);
if (!checkBinderPermission(P_EXIST, targetUid)) {
*aidl_return = static_cast<int32_t>(ResponseCode::PERMISSION_DENIED);
return Status::ok();
}
LockedKeyBlobEntry lockedEntry =
mKeyStore->getLockedBlobEntryIfExists(String8(name).string(), targetUid);
*aidl_return =
static_cast<int32_t>(lockedEntry ? ResponseCode::NO_ERROR : ResponseCode::KEY_NOT_FOUND);
return Status::ok();
}
Status KeyStoreService::list(const String16& prefix, int32_t targetUid,
::std::vector<::android::String16>* matches) {
KEYSTORE_SERVICE_LOCK;
targetUid = getEffectiveUid(targetUid);
if (!checkBinderPermission(P_LIST, targetUid)) {
return Status::fromServiceSpecificError(
static_cast<int32_t>(ResponseCode::PERMISSION_DENIED));
}
const String8 prefix8(prefix);
const std::string stdPrefix(prefix8.string());
ResponseCode rc;
std::list<LockedKeyBlobEntry> internal_matches;
auto userDirName = mKeyStore->getUserStateDB().getUserStateByUid(targetUid)->getUserDirName();
std::tie(rc, internal_matches) =
LockedKeyBlobEntry::list(userDirName, [&](uid_t uid, const std::string& alias) {
std::mismatch(stdPrefix.begin(), stdPrefix.end(), alias.begin(), alias.end());
return uid == static_cast<uid_t>(targetUid) &&
std::mismatch(stdPrefix.begin(), stdPrefix.end(), alias.begin(), alias.end())
.first == stdPrefix.end();
});
if (rc != ResponseCode::NO_ERROR) {
return Status::fromServiceSpecificError(static_cast<int32_t>(rc));
}
for (LockedKeyBlobEntry& entry : internal_matches) {
matches->push_back(String16(entry->alias().substr(prefix8.size()).c_str()));
}
return Status::ok();
}
/*
* This method will return the uids of all auth bound keys for the calling user.
* This is intended to be used for alerting the user about which apps will be affected
* if the password/pin is removed. Only allowed to be called by system.
* The output is bound by the initial size of uidsOut to be compatible with Java.
*/
Status KeyStoreService::listUidsOfAuthBoundKeys(std::vector<std::string>* uidsOut,
int32_t* aidl_return) {
KEYSTORE_SERVICE_LOCK;
const int32_t callingUid = IPCThreadState::self()->getCallingUid();
const int32_t userId = get_user_id(callingUid);
const int32_t appId = get_app_id(callingUid);
if (appId != AID_SYSTEM) {
ALOGE("Permission listUidsOfAuthBoundKeys denied for aid %d", appId);
*aidl_return = static_cast<int32_t>(ResponseCode::PERMISSION_DENIED);
return Status::ok();
}
const String8 prefix8("");
auto userState = mKeyStore->getUserStateDB().getUserState(userId);
const std::string userDirName = userState->getUserDirName();
auto encryptionKey = userState->getEncryptionKey();
auto state = userState->getState();
// unlock the user state
userState = {};
ResponseCode rc;
std::list<LockedKeyBlobEntry> internal_matches;
std::tie(rc, internal_matches) =
LockedKeyBlobEntry::list(userDirName, [&](uid_t, const std::string&) {
// Need to filter on auth bound state, so just return true.
return true;
});
if (rc != ResponseCode::NO_ERROR) {
ALOGE("Error listing blob entries for user %d", userId);
return Status::fromServiceSpecificError(static_cast<int32_t>(rc));
}
for (LockedKeyBlobEntry& entry : internal_matches) {
// Need to store uids as a list of strings because integer list output
// parameters is not supported in aidl-cpp.
std::string entryUid = std::to_string(entry->uid());
if (std::find(uidsOut->begin(), uidsOut->end(), entryUid) != uidsOut->end()) {
// uid already in list, skip
continue;
}
auto [rc, blob, charBlob] = entry.readBlobs(encryptionKey, state);
if (rc != ResponseCode::NO_ERROR && rc != ResponseCode::LOCKED) {
ALOGE("Error reading blob for key %s", entry->alias().c_str());
continue;
}
if (blob && blob.isEncrypted()) {
uidsOut->push_back(entryUid);
} else if (charBlob) {
auto [success, hwEnforced, swEnforced] = charBlob.getKeyCharacteristics();
if (!success) {
ALOGE("Error reading blob characteristics for key %s", entry->alias().c_str());
continue;
}
if (hwEnforced.Contains(TAG_USER_SECURE_ID) ||
swEnforced.Contains(TAG_USER_SECURE_ID)) {
uidsOut->push_back(entryUid);
}
}
}
*aidl_return = static_cast<int32_t>(ResponseCode::NO_ERROR);
return Status::ok();
}
Status KeyStoreService::reset(int32_t* aidl_return) {
KEYSTORE_SERVICE_LOCK;
if (!checkBinderPermission(P_RESET)) {
*aidl_return = static_cast<int32_t>(ResponseCode::PERMISSION_DENIED);
return Status::ok();
}
uid_t callingUid = IPCThreadState::self()->getCallingUid();
mKeyStore->resetUser(get_user_id(callingUid), false);
*aidl_return = static_cast<int32_t>(ResponseCode::NO_ERROR);
return Status::ok();
}
Status KeyStoreService::onUserPasswordChanged(int32_t userId, const String16& password,
int32_t* aidl_return) {
KEYSTORE_SERVICE_LOCK;
if (!checkBinderPermission(P_PASSWORD)) {
*aidl_return = static_cast<int32_t>(ResponseCode::PERMISSION_DENIED);
return Status::ok();
}
if (password.size() == 0) {
ALOGI("Secure lockscreen for user %d removed, deleting encrypted entries", userId);
mKeyStore->resetUser(userId, true);
*aidl_return = static_cast<int32_t>(ResponseCode::NO_ERROR);
return Status::ok();
} else {
const String8 password8(password);
switch (mKeyStore->getState(userId)) {
case ::STATE_UNINITIALIZED: {
// generate master key, encrypt with password, write to file,
// initialize mMasterKey*.
*aidl_return = static_cast<int32_t>(mKeyStore->initializeUser(password8, userId));
return Status::ok();
}
case ::STATE_NO_ERROR: {
// rewrite master key with new password.
*aidl_return = static_cast<int32_t>(mKeyStore->writeMasterKey(password8, userId));
return Status::ok();
}
case ::STATE_LOCKED: {
ALOGE("Changing user %d's password while locked, clearing old encryption", userId);
mKeyStore->resetUser(userId, true);
*aidl_return = static_cast<int32_t>(mKeyStore->initializeUser(password8, userId));
return Status::ok();
}
}
*aidl_return = static_cast<int32_t>(ResponseCode::SYSTEM_ERROR);
return Status::ok();
}
}
Status KeyStoreService::onUserAdded(int32_t userId, int32_t parentId, int32_t* aidl_return) {
KEYSTORE_SERVICE_LOCK;
if (!checkBinderPermission(P_USER_CHANGED)) {
*aidl_return = static_cast<int32_t>(ResponseCode::PERMISSION_DENIED);
return Status::ok();
}
// Sanity check that the new user has an empty keystore.
if (!mKeyStore->isEmpty(userId)) {
ALOGW("New user %d's keystore not empty. Clearing old entries.", userId);
}
// Unconditionally clear the keystore, just to be safe.
mKeyStore->resetUser(userId, false);
if (parentId != -1) {
// This profile must share the same master key password as the parent profile. Because the
// password of the parent profile is not known here, the best we can do is copy the parent's
// master key and master key file. This makes this profile use the same master key as the
// parent profile, forever.
*aidl_return = static_cast<int32_t>(mKeyStore->copyMasterKey(parentId, userId));
return Status::ok();
} else {
*aidl_return = static_cast<int32_t>(ResponseCode::NO_ERROR);
return Status::ok();
}
}
Status KeyStoreService::onUserRemoved(int32_t userId, int32_t* aidl_return) {
KEYSTORE_SERVICE_LOCK;
if (!checkBinderPermission(P_USER_CHANGED)) {
*aidl_return = static_cast<int32_t>(ResponseCode::PERMISSION_DENIED);
return Status::ok();
}
mKeyStore->resetUser(userId, false);
*aidl_return = static_cast<int32_t>(ResponseCode::NO_ERROR);
return Status::ok();
}
Status KeyStoreService::lock(int32_t userId, int32_t* aidl_return) {
KEYSTORE_SERVICE_LOCK;
if (!checkBinderPermission(P_LOCK)) {
*aidl_return = static_cast<int32_t>(ResponseCode::PERMISSION_DENIED);
return Status::ok();
}
State state = mKeyStore->getState(userId);
if (state != ::STATE_NO_ERROR) {
ALOGD("calling lock in state: %d", state);
*aidl_return = static_cast<int32_t>(ResponseCode(state));
return Status::ok();
}
mKeyStore->getEnforcementPolicy().set_device_locked(true, userId);
mKeyStore->lock(userId);
*aidl_return = static_cast<int32_t>(ResponseCode::NO_ERROR);
return Status::ok();
}
Status KeyStoreService::unlock(int32_t userId, const String16& pw, int32_t* aidl_return) {
KEYSTORE_SERVICE_LOCK;
if (!checkBinderPermission(P_UNLOCK)) {
*aidl_return = static_cast<int32_t>(ResponseCode::PERMISSION_DENIED);
return Status::ok();
}
State state = mKeyStore->getState(userId);
if (state != ::STATE_LOCKED) {
switch (state) {
case ::STATE_NO_ERROR:
ALOGI("calling unlock when already unlocked, ignoring.");
break;
case ::STATE_UNINITIALIZED:
ALOGE("unlock called on uninitialized keystore.");
break;
default:
ALOGE("unlock called on keystore in unknown state: %d", state);
break;
}
*aidl_return = static_cast<int32_t>(ResponseCode(state));
return Status::ok();
}
mKeyStore->getEnforcementPolicy().set_device_locked(false, userId);
const String8 password8(pw);
// read master key, decrypt with password, initialize mMasterKey*.
*aidl_return = static_cast<int32_t>(mKeyStore->readMasterKey(password8, userId));
return Status::ok();
}
Status KeyStoreService::isEmpty(int32_t userId, int32_t* aidl_return) {
KEYSTORE_SERVICE_LOCK;
if (!checkBinderPermission(P_IS_EMPTY)) {
*aidl_return = static_cast<int32_t>(false);
return Status::ok();
}
*aidl_return = static_cast<int32_t>(mKeyStore->isEmpty(userId));
return Status::ok();
}
Status KeyStoreService::grant(const String16& name, int32_t granteeUid,
::android::String16* aidl_return) {
KEYSTORE_SERVICE_LOCK;
uid_t callingUid = IPCThreadState::self()->getCallingUid();
auto result =
checkBinderPermissionAndKeystoreState(P_GRANT, /*targetUid=*/-1, /*checkUnlocked=*/false);
if (!result.isOk()) {
*aidl_return = String16();
return Status::ok();
}
String8 name8(name);
auto lockedEntry = mKeyStore->getLockedBlobEntryIfExists(name8.string(), callingUid);
if (!lockedEntry) {
*aidl_return = String16();
return Status::ok();
}
*aidl_return = String16(mKeyStore->addGrant(lockedEntry, granteeUid).c_str());
return Status::ok();
}
Status KeyStoreService::ungrant(const String16& name, int32_t granteeUid, int32_t* aidl_return) {
KEYSTORE_SERVICE_LOCK;
uid_t callingUid = IPCThreadState::self()->getCallingUid();
KeyStoreServiceReturnCode result =
checkBinderPermissionAndKeystoreState(P_GRANT, /*targetUid=*/-1, /*checkUnlocked=*/false);
if (!result.isOk()) {
*aidl_return = result.getErrorCode();
return Status::ok();
}
String8 name8(name);
auto lockedEntry = mKeyStore->getLockedBlobEntryIfExists(name8.string(), callingUid);
if (!lockedEntry) {
*aidl_return = static_cast<int32_t>(ResponseCode::KEY_NOT_FOUND);
}
*aidl_return = mKeyStore->removeGrant(lockedEntry, granteeUid);
return Status::ok();
}
Status KeyStoreService::getmtime(const String16& name, int32_t uid, int64_t* time) {
KEYSTORE_SERVICE_LOCK;
uid_t targetUid = getEffectiveUid(uid);
if (!checkBinderPermission(P_GET, targetUid)) {
ALOGW("permission denied for %d: getmtime", targetUid);
*time = -1L;
return Status::ok();
}
String8 name8(name);
auto lockedEntry = mKeyStore->getLockedBlobEntryIfExists(name8.string(), targetUid);
if (!lockedEntry) {
ALOGW("could not access key with alias %s for getmtime", name8.string());
*time = -1L;
return Status::ok();
}
std::string filename = lockedEntry->getKeyBlobPath();
int fd = TEMP_FAILURE_RETRY(open(filename.c_str(), O_NOFOLLOW, O_RDONLY));
if (fd < 0) {
ALOGW("could not open %s for getmtime", filename.c_str());
*time = -1L;
return Status::ok();
}
struct stat s;
int ret = fstat(fd, &s);
close(fd);
if (ret == -1) {
ALOGW("could not stat %s for getmtime", filename.c_str());
*time = -1L;
return Status::ok();
}
*time = static_cast<int64_t>(s.st_mtime);
return Status::ok();
}
Status KeyStoreService::is_hardware_backed(const String16& keyType, int32_t* aidl_return) {
KEYSTORE_SERVICE_LOCK;
*aidl_return = static_cast<int32_t>(mKeyStore->isHardwareBacked(keyType) ? 1 : 0);
return Status::ok();
}
Status KeyStoreService::clear_uid(int64_t targetUid64, int32_t* _aidl_return) {
KEYSTORE_SERVICE_LOCK;
uid_t targetUid = getEffectiveUid(targetUid64);
if (!checkBinderPermissionSelfOrSystem(P_CLEAR_UID, targetUid)) {
return AIDL_RETURN(ResponseCode::PERMISSION_DENIED);
}
ALOGI("clear_uid %" PRId64, targetUid64);
mKeyStore->removeAllGrantsToUid(targetUid);
ResponseCode rc;
std::list<LockedKeyBlobEntry> entries;
auto userDirName = mKeyStore->getUserStateDB().getUserStateByUid(targetUid)->getUserDirName();
// list has a fence making sure no workers are modifying blob files before iterating the
// data base. All returned entries are locked.
std::tie(rc, entries) = LockedKeyBlobEntry::list(
userDirName, [&](uid_t uid, const std::string&) -> bool { return uid == targetUid; });
if (rc != ResponseCode::NO_ERROR) {
return AIDL_RETURN(rc);
}
for (LockedKeyBlobEntry& lockedEntry : entries) {
if (get_app_id(targetUid) == AID_SYSTEM) {
Blob keyBlob;
Blob charBlob;
std::tie(rc, keyBlob, charBlob) = mKeyStore->get(lockedEntry);
if (rc == ResponseCode::NO_ERROR && keyBlob.isCriticalToDeviceEncryption()) {
// Do not clear keys critical to device encryption under system uid.
continue;
}
}
mKeyStore->del(lockedEntry);
}
return AIDL_RETURN(ResponseCode::NO_ERROR);
}
Status KeyStoreService::addRngEntropy(
const ::android::sp<::android::security::keystore::IKeystoreResponseCallback>& cb,
const ::std::vector<uint8_t>& entropy, int32_t flags, int32_t* _aidl_return) {
KEYSTORE_SERVICE_LOCK;
auto device = mKeyStore->getDevice(flagsToSecurityLevel(flags));
if (!device) {
return AIDL_RETURN(ErrorCode::HARDWARE_TYPE_UNAVAILABLE);
}
device->addRngEntropy(entropy, [device, cb](Return<ErrorCode> rc) {
cb->onFinished(KeyStoreServiceReturnCode(KS_HANDLE_HIDL_ERROR(device, rc)));
});
return AIDL_RETURN(ResponseCode::NO_ERROR);
}
Status KeyStoreService::generateKey(
const ::android::sp<::android::security::keystore::IKeystoreKeyCharacteristicsCallback>& cb,
const String16& name, const KeymasterArguments& params, const ::std::vector<uint8_t>& entropy,
int uid, int flags, int32_t* _aidl_return) {
KEYSTORE_SERVICE_LOCK;
// TODO(jbires): remove this getCallingUid call upon implementation of b/25646100
uid_t originalUid = IPCThreadState::self()->getCallingUid();
uid = getEffectiveUid(uid);
auto logOnScopeExit = android::base::make_scope_guard([&] {
if (__android_log_security()) {
android_log_event_list(SEC_TAG_AUTH_KEY_GENERATED)
<< int32_t(*_aidl_return == static_cast<int32_t>(ResponseCode::NO_ERROR))
<< String8(name) << int32_t(uid) << LOG_ID_SECURITY;
}
});
KeyStoreServiceReturnCode rc =
checkBinderPermissionAndKeystoreState(P_INSERT, uid, flags & KEYSTORE_FLAG_ENCRYPTED);
if (!rc.isOk()) {
return AIDL_RETURN(rc);
}
if ((flags & KEYSTORE_FLAG_CRITICAL_TO_DEVICE_ENCRYPTION) && get_app_id(uid) != AID_SYSTEM) {
ALOGE("Non-system uid %d cannot set FLAG_CRITICAL_TO_DEVICE_ENCRYPTION", uid);
return AIDL_RETURN(ResponseCode::PERMISSION_DENIED);
}
if (containsTag(params.getParameters(), Tag::INCLUDE_UNIQUE_ID)) {
// TODO(jbires): remove uid checking upon implementation of b/25646100
if (!checkBinderPermission(P_GEN_UNIQUE_ID) ||
originalUid != IPCThreadState::self()->getCallingUid()) {
return AIDL_RETURN(ResponseCode::PERMISSION_DENIED);
}
}
SecurityLevel securityLevel = flagsToSecurityLevel(flags);
auto dev = mKeyStore->getDevice(securityLevel);
if (!dev) {
return AIDL_RETURN(ErrorCode::HARDWARE_TYPE_UNAVAILABLE);
}
String8 name8(name);
auto lockedEntry = mKeyStore->getLockedBlobEntryIfNotExists(name8.string(), uid);
if (!lockedEntry) {
return AIDL_RETURN(ResponseCode::KEY_ALREADY_EXISTS);
}
logOnScopeExit.Disable();
dev->generateKey(
std::move(lockedEntry), params.getParameters(), entropy, flags,
[cb, uid, name](KeyStoreServiceReturnCode rc, KeyCharacteristics keyCharacteristics) {
if (__android_log_security()) {
android_log_event_list(SEC_TAG_AUTH_KEY_GENERATED)
<< rc.isOk() << String8(name) << int32_t(uid) << LOG_ID_SECURITY;
}
cb->onFinished(rc,
android::security::keymaster::KeyCharacteristics(keyCharacteristics));
});
return AIDL_RETURN(ResponseCode::NO_ERROR);
}
Status KeyStoreService::getKeyCharacteristics(
const ::android::sp<::android::security::keystore::IKeystoreKeyCharacteristicsCallback>& cb,
const String16& name, const ::android::security::keymaster::KeymasterBlob& clientId,
const ::android::security::keymaster::KeymasterBlob& appData, int32_t uid,
int32_t* _aidl_return) {
KEYSTORE_SERVICE_LOCK;
uid_t targetUid = getEffectiveUid(uid);
uid_t callingUid = IPCThreadState::self()->getCallingUid();
if (!is_granted_to(callingUid, targetUid)) {
ALOGW("uid %d not permitted to act for uid %d in getKeyCharacteristics", callingUid,
targetUid);
return AIDL_RETURN(ResponseCode::PERMISSION_DENIED);
}
String8 name8(name);
ResponseCode rc;
Blob keyBlob;
Blob charBlob;
LockedKeyBlobEntry lockedEntry;
std::tie(rc, keyBlob, charBlob, lockedEntry) =
mKeyStore->getKeyForName(name8, targetUid, TYPE_KEYMASTER_10);
if (rc != ResponseCode::NO_ERROR) {
return AIDL_RETURN(rc);
}
auto dev = mKeyStore->getDevice(keyBlob);
if (!dev) {
return AIDL_RETURN(ResponseCode::SYSTEM_ERROR);
}
// If the charBlob is up to date, it simply moves the argument blobs to the returned blobs
// and extracts the characteristics on the way. Otherwise it updates the cache file with data
// from keymaster. It may also upgrade the key blob.
dev->getKeyCharacteristics(
std::move(lockedEntry), clientId.getData(), appData.getData(), std::move(keyBlob),
std::move(charBlob),
[cb](KeyStoreServiceReturnCode rc, KeyCharacteristics keyCharacteristics) {
cb->onFinished(rc,
android::security::keymaster::KeyCharacteristics(keyCharacteristics));
});
return AIDL_RETURN(ResponseCode::NO_ERROR);
}
Status KeyStoreService::importKey(
const ::android::sp<::android::security::keystore::IKeystoreKeyCharacteristicsCallback>& cb,
const String16& name, const KeymasterArguments& params, int32_t format,
const ::std::vector<uint8_t>& keyData, int uid, int flags, int32_t* _aidl_return) {
KEYSTORE_SERVICE_LOCK;
uid = getEffectiveUid(uid);
auto logOnScopeExit = android::base::make_scope_guard([&] {
if (__android_log_security()) {
android_log_event_list(SEC_TAG_KEY_IMPORTED)
<< int32_t(*_aidl_return == static_cast<int32_t>(ResponseCode::NO_ERROR))
<< String8(name) << int32_t(uid) << LOG_ID_SECURITY;
}
});
KeyStoreServiceReturnCode rc =
checkBinderPermissionAndKeystoreState(P_INSERT, uid, flags & KEYSTORE_FLAG_ENCRYPTED);
if (!rc.isOk()) {
LOG(ERROR) << "permissission denied";
return AIDL_RETURN(rc);
}
if ((flags & KEYSTORE_FLAG_CRITICAL_TO_DEVICE_ENCRYPTION) && get_app_id(uid) != AID_SYSTEM) {
ALOGE("Non-system uid %d cannot set FLAG_CRITICAL_TO_DEVICE_ENCRYPTION", uid);
return AIDL_RETURN(ResponseCode::PERMISSION_DENIED);
}
SecurityLevel securityLevel = flagsToSecurityLevel(flags);
auto dev = mKeyStore->getDevice(securityLevel);
if (!dev) {
LOG(ERROR) << "importKey - cound not get keymaster device";
return AIDL_RETURN(ErrorCode::HARDWARE_TYPE_UNAVAILABLE);
}
String8 name8(name);
auto lockedEntry = mKeyStore->getLockedBlobEntryIfNotExists(name8.string(), uid);
if (!lockedEntry) {
LOG(ERROR) << "importKey - key: " << name8.string() << " " << int(uid)
<< " already exists.";
return AIDL_RETURN(ResponseCode::KEY_ALREADY_EXISTS);
}
logOnScopeExit.Disable();
dev->importKey(
std::move(lockedEntry), params.getParameters(), KeyFormat(format), keyData, flags,
[cb, uid, name](KeyStoreServiceReturnCode rc, KeyCharacteristics keyCharacteristics) {
if (__android_log_security()) {
android_log_event_list(SEC_TAG_KEY_IMPORTED)
<< rc.isOk() << String8(name) << int32_t(uid) << LOG_ID_SECURITY;
}
cb->onFinished(rc,
android::security::keymaster::KeyCharacteristics(keyCharacteristics));
});
return AIDL_RETURN(ResponseCode::NO_ERROR);
}
Status KeyStoreService::exportKey(
const ::android::sp<::android::security::keystore::IKeystoreExportKeyCallback>& cb,
const String16& name, int32_t format,
const ::android::security::keymaster::KeymasterBlob& clientId,
const ::android::security::keymaster::KeymasterBlob& appData, int32_t uid,
int32_t* _aidl_return) {
KEYSTORE_SERVICE_LOCK;
uid_t targetUid = getEffectiveUid(uid);
uid_t callingUid = IPCThreadState::self()->getCallingUid();
if (!is_granted_to(callingUid, targetUid)) {
ALOGW("uid %d not permitted to act for uid %d in exportKey", callingUid, targetUid);
return AIDL_RETURN(ResponseCode::PERMISSION_DENIED);
}
String8 name8(name);
KeyStoreServiceReturnCode rc;
Blob keyBlob;
Blob charBlob;
LockedKeyBlobEntry lockedEntry;
std::tie(rc, keyBlob, charBlob, lockedEntry) =
mKeyStore->getKeyForName(name8, targetUid, TYPE_KEYMASTER_10);
if (!rc.isOk()) {
return AIDL_RETURN(rc);
}
auto dev = mKeyStore->getDevice(keyBlob);
dev->exportKey(std::move(lockedEntry), KeyFormat(format), clientId.getData(), appData.getData(),
std::move(keyBlob), std::move(charBlob),
[cb](ExportResult exportResult) { cb->onFinished(exportResult); });
return AIDL_RETURN(ResponseCode::NO_ERROR);
}
Status KeyStoreService::begin(const sp<IKeystoreOperationResultCallback>& cb,
const sp<IBinder>& appToken, const String16& name, int32_t purpose,
bool pruneable, const KeymasterArguments& params,
const ::std::vector<uint8_t>& entropy, int32_t uid,
int32_t* _aidl_return) {
KEYSTORE_SERVICE_LOCK;
uid_t callingUid = IPCThreadState::self()->getCallingUid();
uid_t targetUid = getEffectiveUid(uid);
if (!is_granted_to(callingUid, targetUid)) {
ALOGW("uid %d not permitted to act for uid %d in begin", callingUid, targetUid);
return AIDL_RETURN(ResponseCode::PERMISSION_DENIED);
}
if (!pruneable && get_app_id(callingUid) != AID_SYSTEM) {
ALOGE("Non-system uid %d trying to start non-pruneable operation", callingUid);
return AIDL_RETURN(ResponseCode::PERMISSION_DENIED);
}
if (!checkAllowedOperationParams(params.getParameters())) {
return AIDL_RETURN(ErrorCode::INVALID_ARGUMENT);
}
String8 name8(name);
Blob keyBlob;
Blob charBlob;
LockedKeyBlobEntry lockedEntry;
ResponseCode rc;
std::tie(rc, keyBlob, charBlob, lockedEntry) =
mKeyStore->getKeyForName(name8, targetUid, TYPE_KEYMASTER_10);
if (rc == ResponseCode::LOCKED && keyBlob.isSuperEncrypted()) {
return AIDL_RETURN(ErrorCode::KEY_USER_NOT_AUTHENTICATED);
}
if (rc != ResponseCode::NO_ERROR) return AIDL_RETURN(rc);
auto dev = mKeyStore->getDevice(keyBlob);
AuthorizationSet opParams = params.getParameters();
dev->begin(std::move(lockedEntry), appToken, std::move(keyBlob), std::move(charBlob), pruneable,
static_cast<KeyPurpose>(purpose), std::move(opParams), entropy,
[this, cb, dev](OperationResult result_) {
if (result_.resultCode.isOk() ||
result_.resultCode == ResponseCode::OP_AUTH_NEEDED) {
mKeyStore->addOperationDevice(result_.token, dev);
}
cb->onFinished(result_);
});
return AIDL_RETURN(ResponseCode::NO_ERROR);
}
Status KeyStoreService::update(const ::android::sp<IKeystoreOperationResultCallback>& cb,
const ::android::sp<::android::IBinder>& token,
const ::android::security::keymaster::KeymasterArguments& params,
const ::std::vector<uint8_t>& input, int32_t* _aidl_return) {
KEYSTORE_SERVICE_LOCK;
if (!checkAllowedOperationParams(params.getParameters())) {
return AIDL_RETURN(ErrorCode::INVALID_ARGUMENT);
}
auto dev = mKeyStore->getOperationDevice(token);
if (!dev) {
return AIDL_RETURN(ErrorCode::INVALID_OPERATION_HANDLE);
}
dev->update(token, params.getParameters(), input, [this, cb, token](OperationResult result_) {
if (!result_.resultCode.isOk()) {
mKeyStore->removeOperationDevice(token);
}
cb->onFinished(result_);
});
return AIDL_RETURN(ResponseCode::NO_ERROR);
}
Status KeyStoreService::finish(const ::android::sp<IKeystoreOperationResultCallback>& cb,
const ::android::sp<::android::IBinder>& token,
const ::android::security::keymaster::KeymasterArguments& params,
const ::std::vector<uint8_t>& signature,
const ::std::vector<uint8_t>& entropy, int32_t* _aidl_return) {
KEYSTORE_SERVICE_LOCK;
if (!checkAllowedOperationParams(params.getParameters())) {
return AIDL_RETURN(ErrorCode::INVALID_ARGUMENT);
}
auto dev = mKeyStore->getOperationDevice(token);
if (!dev) {
return AIDL_RETURN(ErrorCode::INVALID_OPERATION_HANDLE);
}
dev->finish(token, params.getParameters(), {}, signature, entropy,
[this, cb, token](OperationResult result_) {
mKeyStore->removeOperationDevice(token);
cb->onFinished(result_);
});
return AIDL_RETURN(ResponseCode::NO_ERROR);
}
Status KeyStoreService::abort(const ::android::sp<IKeystoreResponseCallback>& cb,
const ::android::sp<::android::IBinder>& token,
int32_t* _aidl_return) {
KEYSTORE_SERVICE_LOCK;
auto dev = mKeyStore->getOperationDevice(token);
if (!dev) {
return AIDL_RETURN(ErrorCode::INVALID_OPERATION_HANDLE);
}
dev->abort(token, [this, cb, token](KeyStoreServiceReturnCode rc) {
mKeyStore->removeOperationDevice(token);
cb->onFinished(rc);
});
return AIDL_RETURN(ResponseCode::NO_ERROR);
}
Status KeyStoreService::addAuthToken(const ::std::vector<uint8_t>& authTokenAsVector,
int32_t* aidl_return) {
KEYSTORE_SERVICE_LOCK;
// 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());
*aidl_return = static_cast<int32_t>(ResponseCode::PERMISSION_DENIED);
return Status::ok();
}
if (authTokenAsVector.size() != sizeof(hw_auth_token_t)) {
*aidl_return = KeyStoreServiceReturnCode(ErrorCode::INVALID_ARGUMENT).getErrorCode();
return Status::ok();
}
hw_auth_token_t authToken;
memcpy(reinterpret_cast<void*>(&authToken), authTokenAsVector.data(), sizeof(hw_auth_token_t));
if (authToken.version != 0) {
*aidl_return = KeyStoreServiceReturnCode(ErrorCode::INVALID_ARGUMENT).getErrorCode();
return Status::ok();
}
mKeyStore->getAuthTokenTable().AddAuthenticationToken(
hidlVec2AuthToken(hidl_vec<uint8_t>(authTokenAsVector)));
*aidl_return = static_cast<int32_t>(ResponseCode::NO_ERROR);
return Status::ok();
}
bool isDeviceIdAttestationRequested(const KeymasterArguments& params) {
const hardware::hidl_vec<KeyParameter>& paramsVec = params.getParameters();
for (size_t i = 0; i < paramsVec.size(); ++i) {
switch (paramsVec[i].tag) {
case Tag::ATTESTATION_ID_BRAND:
case Tag::ATTESTATION_ID_DEVICE:
case Tag::ATTESTATION_ID_MANUFACTURER:
case Tag::ATTESTATION_ID_MODEL:
case Tag::ATTESTATION_ID_PRODUCT:
case Tag::ATTESTATION_ID_IMEI:
case Tag::ATTESTATION_ID_MEID:
case Tag::ATTESTATION_ID_SERIAL:
return true;
default:
continue;
}
}
return false;
}
Status KeyStoreService::attestKey(
const ::android::sp<::android::security::keystore::IKeystoreCertificateChainCallback>& cb,
const String16& name, const KeymasterArguments& params, int32_t* _aidl_return) {
KEYSTORE_SERVICE_LOCK;
// check null output if method signature is updated and return ErrorCode::OUTPUT_PARAMETER_NULL
if (!checkAllowedOperationParams(params.getParameters())) {
return AIDL_RETURN(ErrorCode::INVALID_ARGUMENT);
}
uid_t callingUid = IPCThreadState::self()->getCallingUid();
if (isDeviceIdAttestationRequested(params) && (get_app_id(callingUid) != AID_SYSTEM)) {
return AIDL_RETURN(KeyStoreServiceReturnCode(ErrorCode::INVALID_ARGUMENT));
}
AuthorizationSet mutableParams = params.getParameters();
KeyStoreServiceReturnCode rc = updateParamsForAttestation(callingUid, &mutableParams);
if (!rc.isOk()) {
return AIDL_RETURN(rc);
}
String8 name8(name);
Blob keyBlob;
Blob charBlob;
LockedKeyBlobEntry lockedEntry;
std::tie(rc, keyBlob, charBlob, lockedEntry) =
mKeyStore->getKeyForName(name8, callingUid, TYPE_KEYMASTER_10);
if (!rc.isOk()) {
return AIDL_RETURN(rc);
}
auto dev = mKeyStore->getDevice(keyBlob);
auto hidlKey = blob2hidlVec(keyBlob);
dev->attestKey(
std::move(hidlKey), mutableParams.hidl_data(),
[dev, cb](Return<void> rc,
std::tuple<ErrorCode, hidl_vec<hidl_vec<uint8_t>>>&& hidlResult) {
auto& [ret, certChain] = hidlResult;
if (!rc.isOk()) {
cb->onFinished(KeyStoreServiceReturnCode(ResponseCode::SYSTEM_ERROR), {});
} else if (ret != ErrorCode::OK) {
dev->logIfKeymasterVendorError(ret);
cb->onFinished(KeyStoreServiceReturnCode(ret), {});
} else {
cb->onFinished(KeyStoreServiceReturnCode(ret),
KeymasterCertificateChain(std::move(certChain)));
}
});
return AIDL_RETURN(ResponseCode::NO_ERROR);
}
// My IDE defines "CAPTURE_MOVE(x) x" because it does not understand generalized lambda captures.
// It should never be redefined by a build system though.
#ifndef CAPTURE_MOVE
#define CAPTURE_MOVE(x) x = std::move(x)
#endif
Status KeyStoreService::attestDeviceIds(
const ::android::sp<::android::security::keystore::IKeystoreCertificateChainCallback>& cb,
const KeymasterArguments& params, int32_t* _aidl_return) {
KEYSTORE_SERVICE_LOCK;
// check null output if method signature is updated and return ErrorCode::OUTPUT_PARAMETER_NULL
if (!checkAllowedOperationParams(params.getParameters())) {
return AIDL_RETURN(ErrorCode::INVALID_ARGUMENT);
}
if (!isDeviceIdAttestationRequested(params)) {
// There is an attestKey() method for attesting keys without device ID attestation.
return AIDL_RETURN(ErrorCode::INVALID_ARGUMENT);
}
uid_t callingUid = IPCThreadState::self()->getCallingUid();
sp<IBinder> binder = defaultServiceManager()->getService(String16("permission"));
if (binder == nullptr) {
return AIDL_RETURN(ErrorCode::CANNOT_ATTEST_IDS);
}
if (!interface_cast<IPermissionController>(binder)->checkPermission(
String16("android.permission.READ_PRIVILEGED_PHONE_STATE"),
IPCThreadState::self()->getCallingPid(), callingUid)) {
return AIDL_RETURN(ErrorCode::CANNOT_ATTEST_IDS);
}
AuthorizationSet mutableParams = params.getParameters();
KeyStoreServiceReturnCode rc = updateParamsForAttestation(callingUid, &mutableParams);
if (!rc.isOk()) {
return AIDL_RETURN(rc);
}
// Generate temporary key.
auto dev = mKeyStore->getDevice(SecurityLevel::TRUSTED_ENVIRONMENT);
if (!dev) {
return AIDL_RETURN(ResponseCode::SYSTEM_ERROR);
}
AuthorizationSet keyCharacteristics;
keyCharacteristics.push_back(TAG_PURPOSE, KeyPurpose::VERIFY);
keyCharacteristics.push_back(TAG_ALGORITHM, Algorithm::EC);
keyCharacteristics.push_back(TAG_DIGEST, Digest::SHA_2_256);
keyCharacteristics.push_back(TAG_NO_AUTH_REQUIRED);
keyCharacteristics.push_back(TAG_EC_CURVE, EcCurve::P_256);
std::promise<KeyStoreServiceReturnCode> resultPromise;
auto resultFuture = resultPromise.get_future();
dev->generateKey(
keyCharacteristics.hidl_data(),
[cb, dev, CAPTURE_MOVE(mutableParams)](
Return<void> rc,
std::tuple<ErrorCode, ::std::vector<uint8_t>, KeyCharacteristics>&& hidlResult) {
auto& [ret, hidlKeyBlob_, dummyCharacteristics] = hidlResult;
auto hidlKeyBlob = std::move(hidlKeyBlob_);
if (!rc.isOk()) {
cb->onFinished(KeyStoreServiceReturnCode(ResponseCode::SYSTEM_ERROR), {});
return;
}
if (ret != ErrorCode::OK) {
dev->logIfKeymasterVendorError(ret);
cb->onFinished(KeyStoreServiceReturnCode(ret), {});
return;
}
dev->attestKey(
hidlKeyBlob, mutableParams.hidl_data(),
[cb, dev,
hidlKeyBlob](Return<void> rc,
std::tuple<ErrorCode, hidl_vec<hidl_vec<uint8_t>>>&& hidlResult) {
auto& [ret, certChain] = hidlResult;
// schedule temp key for deletion
dev->deleteKey(std::move(hidlKeyBlob), [dev](Return<ErrorCode> rc) {
// log error but don't return an error
KS_HANDLE_HIDL_ERROR(dev, rc);
});
if (!rc.isOk()) {
cb->onFinished(KeyStoreServiceReturnCode(ResponseCode::SYSTEM_ERROR), {});
return;
}
if (ret == ErrorCode::OK) {
cb->onFinished(
KeyStoreServiceReturnCode(ret),
::android::security::keymaster::KeymasterCertificateChain(certChain));
} else {
dev->logIfKeymasterVendorError(ret);
cb->onFinished(KeyStoreServiceReturnCode(ret), {});
}
});
});
return AIDL_RETURN(ResponseCode::NO_ERROR);
}
Status KeyStoreService::onDeviceOffBody(int32_t* aidl_return) {
KEYSTORE_SERVICE_LOCK;
// TODO(tuckeris): add permission check. This should be callable from ClockworkHome only.
mKeyStore->getAuthTokenTable().onDeviceOffBody();
*aidl_return = static_cast<int32_t>(ResponseCode::NO_ERROR);
return Status::ok();
}
Status KeyStoreService::importWrappedKey(
const ::android::sp<::android::security::keystore::IKeystoreKeyCharacteristicsCallback>& cb,
const ::android::String16& wrappedKeyAlias, const ::std::vector<uint8_t>& wrappedKey,
const ::android::String16& wrappingKeyAlias, const ::std::vector<uint8_t>& maskingKey,
const KeymasterArguments& params, int64_t rootSid, int64_t fingerprintSid,
int32_t* _aidl_return) {
KEYSTORE_SERVICE_LOCK;
uid_t callingUid = IPCThreadState::self()->getCallingUid();
if (!checkBinderPermission(P_INSERT, callingUid)) {
return AIDL_RETURN(ResponseCode::PERMISSION_DENIED);
}
String8 wrappingKeyName8(wrappingKeyAlias);
KeyStoreServiceReturnCode rc;
Blob wrappingKeyBlob;
Blob wrappingCharBlob;
LockedKeyBlobEntry wrappingLockedEntry;
std::tie(rc, wrappingKeyBlob, wrappingCharBlob, wrappingLockedEntry) =
mKeyStore->getKeyForName(wrappingKeyName8, callingUid, TYPE_KEYMASTER_10);
if (!rc.isOk()) {
return AIDL_RETURN(rc);
}
String8 wrappedKeyName8(wrappedKeyAlias);
auto wrappedLockedEntry =
mKeyStore->getLockedBlobEntryIfNotExists(wrappedKeyName8.string(), callingUid);
if (!wrappedLockedEntry) {
return AIDL_RETURN(ResponseCode::KEY_ALREADY_EXISTS);
}
SecurityLevel securityLevel = wrappingKeyBlob.getSecurityLevel();
auto dev = mKeyStore->getDevice(securityLevel);
if (!dev) {
return AIDL_RETURN(ErrorCode::HARDWARE_TYPE_UNAVAILABLE);
}
dev->importWrappedKey(
std::move(wrappingLockedEntry), std::move(wrappedLockedEntry), wrappedKey, maskingKey,
params.getParameters(), std::move(wrappingKeyBlob), std::move(wrappingCharBlob), rootSid,
fingerprintSid, [cb](KeyStoreServiceReturnCode rc, KeyCharacteristics keyCharacteristics) {
cb->onFinished(rc,
::android::security::keymaster::KeyCharacteristics(keyCharacteristics));
});
return AIDL_RETURN(ResponseCode::NO_ERROR);
}
Status KeyStoreService::presentConfirmationPrompt(const sp<IBinder>& listener,
const String16& promptText,
const ::std::vector<uint8_t>& extraData,
const String16& locale, int32_t uiOptionsAsFlags,
int32_t* aidl_return) {
KEYSTORE_SERVICE_LOCK;
return mKeyStore->getConfirmationManager().presentConfirmationPrompt(
listener, promptText, extraData, locale, uiOptionsAsFlags, aidl_return);
}
Status KeyStoreService::cancelConfirmationPrompt(const sp<IBinder>& listener,
int32_t* aidl_return) {
KEYSTORE_SERVICE_LOCK;
return mKeyStore->getConfirmationManager().cancelConfirmationPrompt(listener, aidl_return);
}
Status KeyStoreService::isConfirmationPromptSupported(bool* aidl_return) {
KEYSTORE_SERVICE_LOCK;
return mKeyStore->getConfirmationManager().isConfirmationPromptSupported(aidl_return);
}
/**
* Get the effective target uid for a binder operation that takes an
* optional uid as the target.
*/
uid_t KeyStoreService::getEffectiveUid(int32_t targetUid) {
if (targetUid == UID_SELF) {
return IPCThreadState::self()->getCallingUid();
}
return static_cast<uid_t>(targetUid);
}
/**
* Check if the caller of the current binder method has the required
* permission and if acting on other uids the grants to do so.
*/
bool KeyStoreService::checkBinderPermission(perm_t permission, int32_t targetUid) {
uid_t callingUid = IPCThreadState::self()->getCallingUid();
pid_t spid = IPCThreadState::self()->getCallingPid();
const char* ssid = IPCThreadState::self()->getCallingSid();
if (!has_permission(callingUid, permission, spid, ssid)) {
ALOGW("permission %s denied for %d", get_perm_label(permission), callingUid);
return false;
}
if (!is_granted_to(callingUid, getEffectiveUid(targetUid))) {
ALOGW("uid %d not granted to act for %d", callingUid, targetUid);
return false;
}
return true;
}
/**
* Check if the caller of the current binder method has the required
* permission and the target uid is the caller or the caller is system.
*/
bool KeyStoreService::checkBinderPermissionSelfOrSystem(perm_t permission, int32_t targetUid) {
uid_t callingUid = IPCThreadState::self()->getCallingUid();
pid_t spid = IPCThreadState::self()->getCallingPid();
const char* ssid = IPCThreadState::self()->getCallingSid();
if (!has_permission(callingUid, permission, spid, ssid)) {
ALOGW("permission %s denied for %d", get_perm_label(permission), callingUid);
return false;
}
return getEffectiveUid(targetUid) == callingUid || callingUid == AID_SYSTEM;
}
/**
* Check if the caller of the current binder method has the required
* permission or the target of the operation is the caller's uid. This is
* for operation where the permission is only for cross-uid activity and all
* uids are allowed to act on their own (ie: clearing all entries for a
* given uid).
*/
bool KeyStoreService::checkBinderPermissionOrSelfTarget(perm_t permission, int32_t targetUid) {
uid_t callingUid = IPCThreadState::self()->getCallingUid();
if (getEffectiveUid(targetUid) == callingUid) {
return true;
} else {
return checkBinderPermission(permission, targetUid);
}
}
/**
* Helper method to check that the caller has the required permission as
* well as the keystore is in the unlocked state if checkUnlocked is true.
*
* Returns NO_ERROR on success, PERMISSION_DENIED on a permission error and
* otherwise the state of keystore when not unlocked and checkUnlocked is
* true.
*/
KeyStoreServiceReturnCode
KeyStoreService::checkBinderPermissionAndKeystoreState(perm_t permission, int32_t targetUid,
bool checkUnlocked) {
if (!checkBinderPermission(permission, targetUid)) {
return ResponseCode::PERMISSION_DENIED;
}
State state = mKeyStore->getState(get_user_id(getEffectiveUid(targetUid)));
if (checkUnlocked && !isKeystoreUnlocked(state)) {
// All State values coincide with ResponseCodes
return static_cast<ResponseCode>(state);
}
return ResponseCode::NO_ERROR;
}
bool KeyStoreService::isKeystoreUnlocked(State state) {
switch (state) {
case ::STATE_NO_ERROR:
return true;
case ::STATE_UNINITIALIZED:
case ::STATE_LOCKED:
return false;
}
return false;
}
/**
* 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::RESET_SINCE_ID_ROTATION:
return false;
default:
break;
}
}
return true;
}
Status KeyStoreService::onKeyguardVisibilityChanged(bool isShowing, int32_t userId,
int32_t* aidl_return) {
KEYSTORE_SERVICE_LOCK;
mKeyStore->getEnforcementPolicy().set_device_locked(isShowing, userId);
*aidl_return = static_cast<int32_t>(ResponseCode::NO_ERROR);
return Status::ok();
}
} // namespace keystore