Merge "Fix keystore wifi concurrency issue." am: dece12434d am: fe8fb1fc2c
am: 9a9794408c
Change-Id: Ic9c42a6876f056f70d25751c9feb2e650f753ac9
diff --git a/keystore/Android.bp b/keystore/Android.bp
index 9bd363f..356ac1b 100644
--- a/keystore/Android.bp
+++ b/keystore/Android.bp
@@ -9,7 +9,16 @@
],
sanitize: {
- misc_undefined: ["integer"],
+ misc_undefined: [
+ "signed-integer-overflow",
+ "unsigned-integer-overflow",
+ "shift",
+ "integer-divide-by-zero",
+ "implicit-unsigned-integer-truncation",
+ // BUG: 123630767
+ //"implicit-signed-integer-truncation",
+ "implicit-integer-sign-change",
+ ],
},
clang: true,
diff --git a/keystore/KeyStore.cpp b/keystore/KeyStore.cpp
index 6e8a4b2..d4219bd 100644
--- a/keystore/KeyStore.cpp
+++ b/keystore/KeyStore.cpp
@@ -309,8 +309,8 @@
auto dev = getDevice(keyBlob);
if (keyBlob.getType() == ::TYPE_KEYMASTER_10) {
- dev->deleteKey(blob2hidlVec(keyBlob), [alias, uid](Return<ErrorCode> rc) {
- auto ret = KS_HANDLE_HIDL_ERROR(rc);
+ dev->deleteKey(blob2hidlVec(keyBlob), [dev, alias, uid](Return<ErrorCode> rc) {
+ auto ret = KS_HANDLE_HIDL_ERROR(dev, rc);
// A device doesn't have to implement delete_key.
bool success = ret == ErrorCode::OK || ret == ErrorCode::UNIMPLEMENTED;
if (__android_log_security()) {
diff --git a/keystore/blob.cpp b/keystore/blob.cpp
index 9dd85d6..eac8f11 100644
--- a/keystore/blob.cpp
+++ b/keystore/blob.cpp
@@ -676,10 +676,27 @@
}
bool KeyBlobEntry::hasKeyBlob() const {
- return !access(getKeyBlobPath().c_str(), R_OK | W_OK);
+ int trys = 3;
+ while (trys--) {
+ if (!access(getKeyBlobPath().c_str(), R_OK | W_OK)) return true;
+ if (errno == ENOENT) return false;
+ LOG(WARNING) << "access encountered " << strerror(errno) << " (" << errno << ")"
+ << " while checking for key blob";
+ if (errno != EAGAIN) break;
+ }
+ return false;
}
+
bool KeyBlobEntry::hasCharacteristicsBlob() const {
- return !access(getCharacteristicsBlobPath().c_str(), R_OK | W_OK);
+ int trys = 3;
+ while (trys--) {
+ if (!access(getCharacteristicsBlobPath().c_str(), R_OK | W_OK)) return true;
+ if (errno == ENOENT) return false;
+ LOG(WARNING) << "access encountered " << strerror(errno) << " (" << errno << ")"
+ << " while checking for key characteristics blob";
+ if (errno != EAGAIN) break;
+ }
+ return false;
}
static std::tuple<bool, uid_t, std::string> filename2UidAlias(const std::string& filepath) {
diff --git a/keystore/include/keystore/keystore_hidl_support.h b/keystore/include/keystore/keystore_hidl_support.h
index 781b153..d1d7f16 100644
--- a/keystore/include/keystore/keystore_hidl_support.h
+++ b/keystore/include/keystore/keystore_hidl_support.h
@@ -52,17 +52,20 @@
return s.str();
}
-template <typename... Msgs>
-inline static ErrorCode ksHandleHidlError(const Return<ErrorCode>& error, Msgs&&... msgs) {
+template <typename KMDevice, typename... Msgs>
+inline static ErrorCode ksHandleHidlError(KMDevice dev, const Return<ErrorCode>& error,
+ Msgs&&... msgs) {
if (!error.isOk()) {
- ALOGE("HIDL call failed with %s @ %s", error.description().c_str(),
- argsToString(msgs...).c_str());
+ LOG(ERROR) << "HIDL call failed with " << error.description().c_str() << " @ "
+ << argsToString(msgs...);
return ErrorCode::UNKNOWN_ERROR;
}
- return ErrorCode(error);
+ auto ec = ErrorCode(error);
+ dev->logIfKeymasterVendorError(ec);
+ return ec;
}
-template <typename... Msgs>
-inline static ErrorCode ksHandleHidlError(const Return<void>& error, Msgs&&... msgs) {
+template <typename KMDevice, typename... Msgs>
+inline static ErrorCode ksHandleHidlError(KMDevice, const Return<void>& error, Msgs&&... msgs) {
if (!error.isOk()) {
ALOGE("HIDL call failed with %s @ %s", error.description().c_str(),
argsToString(msgs...).c_str());
@@ -71,8 +74,8 @@
return ErrorCode::OK;
}
-#define KS_HANDLE_HIDL_ERROR(rc) \
- ::keystore::ksHandleHidlError(rc, __FILE__, ":", __LINE__, ":", __PRETTY_FUNCTION__)
+#define KS_HANDLE_HIDL_ERROR(dev, rc) \
+ ::keystore::ksHandleHidlError(dev, rc, __FILE__, ":", __LINE__, ":", __PRETTY_FUNCTION__)
template <typename T, typename OutIter>
inline static OutIter copy_bytes_to_iterator(const T& value, OutIter dest) {
diff --git a/keystore/key_store_service.cpp b/keystore/key_store_service.cpp
index 8efc7c7..5e7efab 100644
--- a/keystore/key_store_service.cpp
+++ b/keystore/key_store_service.cpp
@@ -69,8 +69,6 @@
constexpr double kIdRotationPeriod = 30 * 24 * 60 * 60; /* Thirty days, in seconds */
const char* kTimestampFilePath = "timestamp";
-const int ID_ATTESTATION_REQUEST_GENERIC_INFO = 1 << 0;
-const int ID_ATTESTATION_REQUEST_UNIQUE_DEVICE_ID = 1 << 1;
struct BIGNUM_Delete {
void operator()(BIGNUM* p) const { BN_free(p); }
@@ -374,17 +372,13 @@
return Status::ok();
}
- const String8 password8(password);
- // Flush the auth token table to prevent stale tokens from sticking
- // around.
- mKeyStore->getAuthTokenTable().Clear();
-
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,
@@ -644,8 +638,8 @@
return AIDL_RETURN(ErrorCode::HARDWARE_TYPE_UNAVAILABLE);
}
- device->addRngEntropy(entropy, [cb](Return<ErrorCode> rc) {
- cb->onFinished(KeyStoreServiceReturnCode(KS_HANDLE_HIDL_ERROR(rc)));
+ device->addRngEntropy(entropy, [device, cb](Return<ErrorCode> rc) {
+ cb->onFinished(KeyStoreServiceReturnCode(KS_HANDLE_HIDL_ERROR(device, rc)));
});
return AIDL_RETURN(ResponseCode::NO_ERROR);
@@ -996,9 +990,8 @@
return Status::ok();
}
-int isDeviceIdAttestationRequested(const KeymasterArguments& params) {
+bool isDeviceIdAttestationRequested(const KeymasterArguments& params) {
const hardware::hidl_vec<KeyParameter>& paramsVec = params.getParameters();
- int result = 0;
for (size_t i = 0; i < paramsVec.size(); ++i) {
switch (paramsVec[i].tag) {
case Tag::ATTESTATION_ID_BRAND:
@@ -1006,18 +999,15 @@
case Tag::ATTESTATION_ID_MANUFACTURER:
case Tag::ATTESTATION_ID_MODEL:
case Tag::ATTESTATION_ID_PRODUCT:
- result |= ID_ATTESTATION_REQUEST_GENERIC_INFO;
- break;
case Tag::ATTESTATION_ID_IMEI:
case Tag::ATTESTATION_ID_MEID:
case Tag::ATTESTATION_ID_SERIAL:
- result |= ID_ATTESTATION_REQUEST_UNIQUE_DEVICE_ID;
- break;
+ return true;
default:
continue;
}
}
- return result;
+ return false;
}
Status KeyStoreService::attestKey(
@@ -1031,15 +1021,7 @@
uid_t callingUid = IPCThreadState::self()->getCallingUid();
- int needsIdAttestation = isDeviceIdAttestationRequested(params);
- bool needsUniqueIdAttestation = needsIdAttestation & ID_ATTESTATION_REQUEST_UNIQUE_DEVICE_ID;
- bool isPrimaryUserSystemUid = (callingUid == AID_SYSTEM);
- bool isSomeUserSystemUid = (get_app_id(callingUid) == AID_SYSTEM);
- // Allow system context from any user to request attestation with basic device information,
- // while only allow system context from user 0 (device owner) to request attestation with
- // unique device ID.
- if ((needsIdAttestation && !isSomeUserSystemUid) ||
- (needsUniqueIdAttestation && !isPrimaryUserSystemUid)) {
+ if (isDeviceIdAttestationRequested(params) && (get_app_id(callingUid) != AID_SYSTEM)) {
return AIDL_RETURN(KeyStoreServiceReturnCode(ErrorCode::INVALID_ARGUMENT));
}
@@ -1061,11 +1043,13 @@
auto hidlKey = blob2hidlVec(keyBlob);
dev->attestKey(
std::move(hidlKey), mutableParams.hidl_data(),
- [cb](Return<void> rc, std::tuple<ErrorCode, hidl_vec<hidl_vec<uint8_t>>>&& hidlResult) {
+ [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),
@@ -1144,6 +1128,7 @@
return;
}
if (ret != ErrorCode::OK) {
+ dev->logIfKeymasterVendorError(ret);
cb->onFinished(KeyStoreServiceReturnCode(ret), {});
return;
}
@@ -1154,9 +1139,9 @@
std::tuple<ErrorCode, hidl_vec<hidl_vec<uint8_t>>>&& hidlResult) {
auto& [ret, certChain] = hidlResult;
// schedule temp key for deletion
- dev->deleteKey(std::move(hidlKeyBlob), [](Return<ErrorCode> rc) {
+ dev->deleteKey(std::move(hidlKeyBlob), [dev](Return<ErrorCode> rc) {
// log error but don't return an error
- KS_HANDLE_HIDL_ERROR(rc);
+ KS_HANDLE_HIDL_ERROR(dev, rc);
});
if (!rc.isOk()) {
cb->onFinished(KeyStoreServiceReturnCode(ResponseCode::SYSTEM_ERROR), {});
@@ -1167,6 +1152,7 @@
KeyStoreServiceReturnCode(ret),
::android::security::keymaster::KeymasterCertificateChain(certChain));
} else {
+ dev->logIfKeymasterVendorError(ret);
cb->onFinished(KeyStoreServiceReturnCode(ret), {});
}
});
@@ -1273,7 +1259,8 @@
bool KeyStoreService::checkBinderPermission(perm_t permission, int32_t targetUid) {
uid_t callingUid = IPCThreadState::self()->getCallingUid();
pid_t spid = IPCThreadState::self()->getCallingPid();
- if (!has_permission(callingUid, permission, spid)) {
+ 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;
}
@@ -1291,7 +1278,8 @@
bool KeyStoreService::checkBinderPermissionSelfOrSystem(perm_t permission, int32_t targetUid) {
uid_t callingUid = IPCThreadState::self()->getCallingUid();
pid_t spid = IPCThreadState::self()->getCallingPid();
- if (!has_permission(callingUid, permission, spid)) {
+ 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;
}
diff --git a/keystore/keymaster_worker.cpp b/keystore/keymaster_worker.cpp
index d2175b8..922ef0a 100644
--- a/keystore/keymaster_worker.cpp
+++ b/keystore/keymaster_worker.cpp
@@ -70,6 +70,10 @@
if (keymasterDevice_) keymasterDevice_->halVersion();
}
+void KeymasterWorker::logIfKeymasterVendorError(ErrorCode ec) const {
+ keymasterDevice_->logIfKeymasterVendorError(ec);
+}
+
std::tuple<KeyStoreServiceReturnCode, Blob>
KeymasterWorker::upgradeKeyBlob(const LockedKeyBlobEntry& lockedEntry,
const AuthorizationSet& params) {
@@ -98,6 +102,7 @@
auto& dev = keymasterDevice_;
auto hidlCb = [&](ErrorCode ret, const ::std::vector<uint8_t>& upgradedKeyBlob) {
+ dev->logIfKeymasterVendorError(ret);
error = ret;
if (!error.isOk()) {
if (error == ErrorCode::INVALID_KEY_BLOB) {
@@ -128,7 +133,7 @@
};
KeyStoreServiceReturnCode error2;
- error2 = KS_HANDLE_HIDL_ERROR(dev->upgradeKey(hidlKey, params.hidl_data(), hidlCb));
+ error2 = KS_HANDLE_HIDL_ERROR(dev, dev->upgradeKey(hidlKey, params.hidl_data(), hidlCb));
if (!error2.isOk()) {
return error = error2, result;
}
@@ -171,6 +176,7 @@
}
auto hidlCb = [&](ErrorCode ret, const KeyCharacteristics& keyCharacteristics) {
+ dev->logIfKeymasterVendorError(ret);
error = ret;
if (!error.isOk()) {
if (error == ErrorCode::INVALID_KEY_BLOB) {
@@ -207,7 +213,7 @@
// this updates the key characteristics cache file to the new format or creates one in
// in the first place
rc = KS_HANDLE_HIDL_ERROR(
- dev->getKeyCharacteristics(hidlKeyBlob, clientId, appData, hidlCb));
+ dev, dev->getKeyCharacteristics(hidlKeyBlob, clientId, appData, hidlCb));
if (!rc.isOk()) {
return result;
}
@@ -228,7 +234,7 @@
auto upgradedHidlKeyBlob = blob2hidlVec(keyBlob);
rc = KS_HANDLE_HIDL_ERROR(
- dev->getKeyCharacteristics(upgradedHidlKeyBlob, clientId, appData, hidlCb));
+ dev, dev->getKeyCharacteristics(upgradedHidlKeyBlob, clientId, appData, hidlCb));
if (!rc.isOk()) {
return result;
}
@@ -299,7 +305,7 @@
auto op = operationMap_.removeOperation(token, false /* wasOpSuccessful */);
if (op) {
keyStore_->getAuthTokenTable().MarkCompleted(op->handle);
- return KS_HANDLE_HIDL_ERROR(keymasterDevice_->abort(op->handle));
+ return KS_HANDLE_HIDL_ERROR(keymasterDevice_, keymasterDevice_->abort(op->handle));
} else {
return ErrorCode::INVALID_OPERATION_HANDLE;
}
@@ -376,7 +382,7 @@
// Add entropy to the device first.
if (entropy.size()) {
- rc = KS_HANDLE_HIDL_ERROR(dev->addRngEntropy(entropy));
+ rc = KS_HANDLE_HIDL_ERROR(dev, dev->addRngEntropy(entropy));
if (!rc.isOk()) {
return worker_cb(operationFailed(rc));
}
@@ -414,6 +420,7 @@
auto hidlCb = [&](ErrorCode ret, const hidl_vec<KeyParameter>& outParams,
uint64_t operationHandle) {
+ dev->logIfKeymasterVendorError(ret);
result.resultCode = ret;
if (!result.resultCode.isOk()) {
if (result.resultCode == ErrorCode::INVALID_KEY_BLOB) {
@@ -426,8 +433,8 @@
};
do {
- rc = KS_HANDLE_HIDL_ERROR(dev->begin(purpose, blob2hidlVec(keyBlob),
- opParams.hidl_data(), authToken, hidlCb));
+ rc = KS_HANDLE_HIDL_ERROR(dev, dev->begin(purpose, blob2hidlVec(keyBlob),
+ opParams.hidl_data(), authToken, hidlCb));
if (!rc.isOk()) {
LOG(ERROR) << "Got error " << rc << " from begin()";
return worker_cb(operationFailed(ResponseCode::SYSTEM_ERROR));
@@ -439,8 +446,8 @@
return worker_cb(operationFailed(rc));
}
- rc = KS_HANDLE_HIDL_ERROR(dev->begin(purpose, blob2hidlVec(keyBlob),
- opParams.hidl_data(), authToken, hidlCb));
+ rc = KS_HANDLE_HIDL_ERROR(dev, dev->begin(purpose, blob2hidlVec(keyBlob),
+ opParams.hidl_data(), authToken, hidlCb));
if (!rc.isOk()) {
LOG(ERROR) << "Got error " << rc << " from begin()";
return worker_cb(operationFailed(ResponseCode::SYSTEM_ERROR));
@@ -557,7 +564,7 @@
Finalize abort_operation_in_case_of_error([&] {
operationMap_.removeOperation(token, false);
keyStore_->getAuthTokenTable().MarkCompleted(op->handle);
- KS_HANDLE_HIDL_ERROR(keymasterDevice_->abort(op->handle));
+ KS_HANDLE_HIDL_ERROR(keymasterDevice_, keymasterDevice_->abort(op->handle));
});
rc = getOperationAuthTokenIfNeeded(op);
@@ -577,6 +584,7 @@
auto hidlCb = [&](ErrorCode ret, uint32_t inputConsumed,
const hidl_vec<KeyParameter>& outParams,
const ::std::vector<uint8_t>& output) {
+ op->device->logIfKeymasterVendorError(ret);
result.resultCode = ret;
if (result.resultCode.isOk()) {
result.inputConsumed = inputConsumed;
@@ -585,7 +593,8 @@
}
};
- rc = KS_HANDLE_HIDL_ERROR(op->device->update(op->handle, params.hidl_data(), data,
+ rc = KS_HANDLE_HIDL_ERROR(op->device,
+ op->device->update(op->handle, params.hidl_data(), data,
op->authToken, op->verificationToken, hidlCb));
// just a reminder: on success result->resultCode was set in the callback. So we only
@@ -634,7 +643,8 @@
Finalize abort_operation_in_case_of_error([&] {
operationMap_.removeOperation(token, finished && rc.isOk());
keyStore_->getAuthTokenTable().MarkCompleted(op->handle);
- if (!finished) KS_HANDLE_HIDL_ERROR(keymasterDevice_->abort(op->handle));
+ if (!finished)
+ KS_HANDLE_HIDL_ERROR(keymasterDevice_, keymasterDevice_->abort(op->handle));
});
if (!checkAllowedOperationParams(params.begin(), params.end())) {
@@ -665,7 +675,7 @@
if (!rc.isOk()) return worker_cb(operationFailed(rc));
if (entropy.size()) {
- rc = KS_HANDLE_HIDL_ERROR(op->device->addRngEntropy(entropy));
+ rc = KS_HANDLE_HIDL_ERROR(op->device, op->device->addRngEntropy(entropy));
if (!rc.isOk()) {
return worker_cb(operationFailed(rc));
}
@@ -674,6 +684,7 @@
OperationResult result;
auto hidlCb = [&](ErrorCode ret, const hidl_vec<KeyParameter>& outParams,
const ::std::vector<uint8_t>& output) {
+ op->device->logIfKeymasterVendorError(ret);
result.resultCode = ret;
if (result.resultCode.isOk()) {
result.outParams = outParams;
@@ -681,9 +692,9 @@
}
};
- rc = KS_HANDLE_HIDL_ERROR(op->device->finish(op->handle, params.hidl_data(), input,
- signature, op->authToken,
- op->verificationToken, hidlCb));
+ rc = KS_HANDLE_HIDL_ERROR(op->device, op->device->finish(op->handle, params.hidl_data(),
+ input, signature, op->authToken,
+ op->verificationToken, hidlCb));
if (rc.isOk()) {
// inform the finalizer that the finish call went through
@@ -709,11 +720,14 @@
CAPTURE_MOVE(worker_cb)]() {
KeyStoreServiceReturnCode error;
VerificationToken verificationToken;
- KeyStoreServiceReturnCode rc = KS_HANDLE_HIDL_ERROR(keymasterDevice_->verifyAuthorization(
- challenge, params, token, [&](ErrorCode error_, const VerificationToken& vToken) {
- error = error_;
- verificationToken = vToken;
- }));
+ KeyStoreServiceReturnCode rc = KS_HANDLE_HIDL_ERROR(
+ keymasterDevice_,
+ keymasterDevice_->verifyAuthorization(
+ challenge, params, token, [&](ErrorCode ret, const VerificationToken& vToken) {
+ keymasterDevice_->logIfKeymasterVendorError(ret);
+ error = ret;
+ verificationToken = vToken;
+ }));
worker_cb(rc.isOk() ? error : rc, std::move(token), std::move(verificationToken));
});
}
@@ -739,7 +753,7 @@
Worker::addRequest([this, CAPTURE_MOVE(lockedEntry), CAPTURE_MOVE(keyParams),
CAPTURE_MOVE(entropy), CAPTURE_MOVE(worker_cb), flags]() mutable {
KeyStoreServiceReturnCode rc =
- KS_HANDLE_HIDL_ERROR(keymasterDevice_->addRngEntropy(entropy));
+ KS_HANDLE_HIDL_ERROR(keymasterDevice_, keymasterDevice_->addRngEntropy(entropy));
if (!rc.isOk()) {
return worker_cb(rc, {});
}
@@ -757,6 +771,7 @@
KeyStoreServiceReturnCode error;
auto hidl_cb = [&](ErrorCode ret, const hidl_vec<uint8_t>& hidlKeyBlob,
const KeyCharacteristics& keyCharacteristics) {
+ keymasterDevice_->logIfKeymasterVendorError(ret);
error = ret;
if (!error.isOk()) {
return;
@@ -788,7 +803,8 @@
error = keyStore_->put(lockedEntry, std::move(keyBlob), std::move(keyCharBlob));
};
- rc = KS_HANDLE_HIDL_ERROR(keymasterDevice_->generateKey(keyParams, hidl_cb));
+ rc = KS_HANDLE_HIDL_ERROR(keymasterDevice_,
+ keymasterDevice_->generateKey(keyParams, hidl_cb));
if (!rc.isOk()) {
return worker_cb(rc, {});
}
@@ -859,6 +875,7 @@
KeyStoreServiceReturnCode error;
auto hidl_cb = [&](ErrorCode ret, const hidl_vec<uint8_t>& hidlKeyBlob,
const KeyCharacteristics& keyCharacteristics) {
+ keymasterDevice_->logIfKeymasterVendorError(ret);
error = ret;
if (!error.isOk()) {
LOG(INFO) << "importKey failed";
@@ -892,7 +909,7 @@
};
KeyStoreServiceReturnCode rc = KS_HANDLE_HIDL_ERROR(
- keymasterDevice_->importKey(keyParams, keyFormat, keyData, hidl_cb));
+ keymasterDevice_, keymasterDevice_->importKey(keyParams, keyFormat, keyData, hidl_cb));
if (!rc.isOk()) {
return worker_cb(rc, {});
}
@@ -949,6 +966,7 @@
auto hidlCb = [&](ErrorCode ret, const hidl_vec<uint8_t>& hidlKeyBlob,
const KeyCharacteristics& keyCharacteristics) {
+ keymasterDevice_->logIfKeymasterVendorError(ret);
error = ret;
if (!error.isOk()) {
return;
@@ -972,9 +990,10 @@
error = keyStore_->put(wrapppedLockedEntry, std::move(keyBlob), std::move(keyCharBlob));
};
- KeyStoreServiceReturnCode rc = KS_HANDLE_HIDL_ERROR(keymasterDevice_->importWrappedKey(
- wrappedKeyData, hidlWrappingKey, maskingKey, unwrappingParams, passwordSid,
- biometricSid, hidlCb));
+ KeyStoreServiceReturnCode rc = KS_HANDLE_HIDL_ERROR(
+ keymasterDevice_, keymasterDevice_->importWrappedKey(
+ wrappedKeyData, hidlWrappingKey, maskingKey, unwrappingParams,
+ passwordSid, biometricSid, hidlCb));
// possible hidl error
if (!rc.isOk()) {
@@ -989,9 +1008,10 @@
auto upgradedHidlKeyBlob = blob2hidlVec(wrappingBlob);
- rc = KS_HANDLE_HIDL_ERROR(keymasterDevice_->importWrappedKey(
- wrappedKeyData, upgradedHidlKeyBlob, maskingKey, unwrappingParams, passwordSid,
- biometricSid, hidlCb));
+ rc = KS_HANDLE_HIDL_ERROR(keymasterDevice_,
+ keymasterDevice_->importWrappedKey(
+ wrappedKeyData, upgradedHidlKeyBlob, maskingKey,
+ unwrappingParams, passwordSid, biometricSid, hidlCb));
if (!rc.isOk()) {
error = rc;
}
@@ -1011,6 +1031,7 @@
ExportResult result;
auto hidlCb = [&](ErrorCode ret,
const ::android::hardware::hidl_vec<uint8_t>& keyMaterial) {
+ keymasterDevice_->logIfKeymasterVendorError(ret);
result.resultCode = ret;
if (!result.resultCode.isOk()) {
if (result.resultCode == ErrorCode::INVALID_KEY_BLOB) {
@@ -1021,6 +1042,7 @@
result.exportData = keyMaterial;
};
KeyStoreServiceReturnCode rc = KS_HANDLE_HIDL_ERROR(
+ keymasterDevice_,
keymasterDevice_->exportKey(exportFormat, key, clientId, appData, hidlCb));
// Overwrite result->resultCode only on HIDL error. Otherwise we want the result set in the
@@ -1044,7 +1066,8 @@
auto upgradedHidlKeyBlob = blob2hidlVec(keyBlob);
- rc = KS_HANDLE_HIDL_ERROR(keymasterDevice_->exportKey(exportFormat, upgradedHidlKeyBlob,
+ rc = KS_HANDLE_HIDL_ERROR(keymasterDevice_,
+ keymasterDevice_->exportKey(exportFormat, upgradedHidlKeyBlob,
clientId, appData, hidlCb));
if (!rc.isOk()) {
result.resultCode = rc;
@@ -1058,21 +1081,10 @@
addRequest(&Keymaster::attestKey, std::move(worker_cb), std::move(keyToAttest),
std::move(attestParams));
}
-void KeymasterWorker::upgradeKey(hidl_vec<uint8_t> keyBlobToUpgrade,
- hidl_vec<KeyParameter> upgradeParams, upgradeKey_cb _hidl_cb) {
- addRequest(&Keymaster::upgradeKey, std::move(_hidl_cb), std::move(keyBlobToUpgrade),
- std::move(upgradeParams));
-}
void KeymasterWorker::deleteKey(hidl_vec<uint8_t> keyBlob, deleteKey_cb _hidl_cb) {
addRequest(&Keymaster::deleteKey, std::move(_hidl_cb), std::move(keyBlob));
}
-void KeymasterWorker::deleteAllKeys(deleteAllKeys_cb _hidl_cb) {
- addRequest(&Keymaster::deleteAllKeys, std::move(_hidl_cb));
-}
-void KeymasterWorker::destroyAttestationIds(destroyAttestationIds_cb _hidl_cb) {
- addRequest(&Keymaster::destroyAttestationIds, move(_hidl_cb));
-}
void KeymasterWorker::binderDied(android::wp<IBinder> who) {
Worker::addRequest([this, who]() {
diff --git a/keystore/keymaster_worker.h b/keystore/keymaster_worker.h
index c02d389..e1a1c02 100644
--- a/keystore/keymaster_worker.h
+++ b/keystore/keymaster_worker.h
@@ -207,6 +207,8 @@
public:
KeymasterWorker(sp<Keymaster> keymasterDevice, KeyStore* keyStore);
+ void logIfKeymasterVendorError(ErrorCode ec) const;
+
using worker_begin_cb = std::function<void(::android::security::keymaster::OperationResult)>;
void begin(LockedKeyBlobEntry, sp<IBinder> appToken, Blob keyBlob, Blob charBlob,
bool pruneable, KeyPurpose purpose, AuthorizationSet opParams,
@@ -279,19 +281,9 @@
void attestKey(hidl_vec<uint8_t> keyToAttest, hidl_vec<KeyParameter> attestParams,
attestKey_cb _hidl_cb);
- using upgradeKey_cb = MakeKeymasterWorkerCB_t<Return<void>, Keymaster::upgradeKey_cb>;
- void upgradeKey(hidl_vec<uint8_t> keyBlobToUpgrade, hidl_vec<KeyParameter> upgradeParams,
- upgradeKey_cb _hidl_cb);
-
using deleteKey_cb = MakeKeymasterWorkerCB_t<Return<ErrorCode>>;
void deleteKey(hidl_vec<uint8_t> keyBlob, deleteKey_cb _hidl_cb);
- using deleteAllKeys_cb = MakeKeymasterWorkerCB_t<Return<ErrorCode>>;
- void deleteAllKeys(deleteAllKeys_cb _hidl_cb);
-
- using destroyAttestationIds_cb = MakeKeymasterWorkerCB_t<Return<ErrorCode>>;
- void destroyAttestationIds(destroyAttestationIds_cb _hidl_cb);
-
using begin_cb = MakeKeymasterWorkerCB_t<Return<void>, Keymaster::begin_cb>;
void begin(KeyPurpose purpose, hidl_vec<uint8_t> key, hidl_vec<KeyParameter> inParams,
HardwareAuthToken authToken, begin_cb _hidl_cb);
diff --git a/keystore/keystore_client.proto b/keystore/keystore_client.proto
index cd520dc..cbafd54 100644
--- a/keystore/keystore_client.proto
+++ b/keystore/keystore_client.proto
@@ -12,6 +12,8 @@
// See the License for the specific language governing permissions and
// limitations under the License.
+syntax = "proto2";
+
package keystore;
option optimize_for = LITE_RUNTIME;
diff --git a/keystore/keystore_main.cpp b/keystore/keystore_main.cpp
index 70f38cc..f3eadd7 100644
--- a/keystore/keystore_main.cpp
+++ b/keystore/keystore_main.cpp
@@ -156,6 +156,7 @@
keyStore->initialize();
android::sp<android::IServiceManager> sm = android::defaultServiceManager();
android::sp<keystore::KeyStoreService> service = new keystore::KeyStoreService(keyStore);
+ service->setRequestingSid(true);
android::status_t ret = sm->addService(android::String16("android.security.keystore"), service);
CHECK(ret == android::OK) << "Couldn't register binder service!";
diff --git a/keystore/permissions.cpp b/keystore/permissions.cpp
index a172761..05454cb 100644
--- a/keystore/permissions.cpp
+++ b/keystore/permissions.cpp
@@ -92,6 +92,7 @@
struct audit_data {
pid_t pid;
uid_t uid;
+ const char* sid;
};
const char* get_perm_label(perm_t perm) {
@@ -111,7 +112,8 @@
return 0;
}
- snprintf(buf, len, "pid=%d uid=%d", ad->pid, ad->uid);
+ const char* sid = ad->sid ? ad->sid : "N/A";
+ snprintf(buf, len, "pid=%d uid=%d sid=%s", ad->pid, ad->uid, sid);
return 0;
}
@@ -131,7 +133,7 @@
return 0;
}
-static bool keystore_selinux_check_access(uid_t uid, perm_t perm, pid_t spid) {
+static bool keystore_selinux_check_access(uid_t uid, perm_t perm, pid_t spid, const char* ssid) {
audit_data ad;
char* sctx = nullptr;
const char* selinux_class = "keystore_key";
@@ -141,15 +143,18 @@
return false;
}
- if (getpidcon(spid, &sctx) != 0) {
+ if (ssid == nullptr && getpidcon(spid, &sctx) != 0) {
ALOGE("SELinux: Failed to get source pid context.\n");
return false;
}
+ const char* use_sid = ssid ? ssid : sctx;
+
ad.pid = spid;
ad.uid = uid;
+ ad.sid = use_sid;
- bool allowed = selinux_check_access(sctx, tctx, selinux_class, str_perm,
+ bool allowed = selinux_check_access(use_sid, tctx, selinux_class, str_perm,
reinterpret_cast<void*>(&ad)) == 0;
freecon(sctx);
return allowed;
@@ -171,20 +176,24 @@
return uid;
}
-bool has_permission(uid_t uid, perm_t perm, pid_t spid) {
+bool has_permission(uid_t uid, perm_t perm, pid_t spid, const char* sid) {
// All system users are equivalent for multi-user support.
if (get_app_id(uid) == AID_SYSTEM) {
uid = AID_SYSTEM;
}
+ if (sid == nullptr) {
+ android_errorWriteLog(0x534e4554, "121035042");
+ }
+
for (size_t i = 0; i < sizeof(user_perms) / sizeof(user_perms[0]); i++) {
struct user_perm user = user_perms[i];
if (user.uid == uid) {
- return (user.perms & perm) && keystore_selinux_check_access(uid, perm, spid);
+ return (user.perms & perm) && keystore_selinux_check_access(uid, perm, spid, sid);
}
}
- return (DEFAULT_PERMS & perm) && keystore_selinux_check_access(uid, perm, spid);
+ return (DEFAULT_PERMS & perm) && keystore_selinux_check_access(uid, perm, spid, sid);
}
/**
diff --git a/keystore/permissions.h b/keystore/permissions.h
index 1f7b7a6..1dd0089 100644
--- a/keystore/permissions.h
+++ b/keystore/permissions.h
@@ -51,7 +51,12 @@
*/
uid_t get_keystore_euid(uid_t uid);
-bool has_permission(uid_t uid, perm_t perm, pid_t spid);
+/**
+ * Returns true if the uid/pid/sid has a permission. Checks based on sid if available.
+ *
+ * sid may be null on older kernels
+ */
+bool has_permission(uid_t uid, perm_t perm, pid_t spid, const char* sid);
/**
* Returns true if the callingUid is allowed to interact in the targetUid's
diff --git a/keystore/tests/Android.bp b/keystore/tests/Android.bp
index 1ce1210..25fa10b 100644
--- a/keystore/tests/Android.bp
+++ b/keystore/tests/Android.bp
@@ -37,3 +37,33 @@
cfi: false,
}
}
+
+cc_test {
+ cflags: [
+ "-Wall",
+ "-Werror",
+ "-Wextra",
+ "-O0",
+ ],
+ srcs: [
+ "confirmationui_invocation_test.cpp",
+ "gtest_main.cpp",
+ ],
+ name: "confirmationui_invocation_test",
+ static_libs: [
+ "android.hardware.confirmationui@1.0",
+ "libbase",
+ "libgtest_main",
+ "libutils",
+ "liblog",
+ ],
+ shared_libs: [
+ "libbinder",
+ "libkeystore_aidl", // for IKeyStoreService.asInterface()
+ "libkeystore_binder",
+ "libkeystore_parcelables",
+ ],
+ sanitize: {
+ cfi: false,
+ }
+}
diff --git a/keystore/tests/confirmationui_invocation_test.cpp b/keystore/tests/confirmationui_invocation_test.cpp
new file mode 100644
index 0000000..f5182b5
--- /dev/null
+++ b/keystore/tests/confirmationui_invocation_test.cpp
@@ -0,0 +1,92 @@
+/*
+**
+** Copyright 2019, 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.
+*/
+
+#include <android/hardware/confirmationui/1.0/types.h>
+#include <android/security/BnConfirmationPromptCallback.h>
+#include <android/security/keystore/IKeystoreService.h>
+#include <binder/IPCThreadState.h>
+#include <binder/IServiceManager.h>
+
+#include <gtest/gtest.h>
+
+#include <chrono>
+#include <future>
+#include <tuple>
+#include <vector>
+
+using ConfirmationResponseCode = android::hardware::confirmationui::V1_0::ResponseCode;
+using android::IBinder;
+using android::IServiceManager;
+using android::sp;
+using android::String16;
+using android::security::keystore::IKeystoreService;
+
+using namespace std::literals::chrono_literals;
+
+class ConfirmationListener
+ : public android::security::BnConfirmationPromptCallback,
+ public std::promise<std::tuple<ConfirmationResponseCode, std::vector<uint8_t>>> {
+ public:
+ ConfirmationListener() {}
+
+ virtual ::android::binder::Status
+ onConfirmationPromptCompleted(int32_t result,
+ const ::std::vector<uint8_t>& dataThatWasConfirmed) override {
+ this->set_value({static_cast<ConfirmationResponseCode>(result), dataThatWasConfirmed});
+ return ::android::binder::Status::ok();
+ }
+};
+
+TEST(ConfirmationInvocationTest, InvokeAndCancel) {
+ android::ProcessState::self()->startThreadPool();
+
+ sp<IServiceManager> sm = android::defaultServiceManager();
+ sp<IBinder> binder = sm->getService(String16("android.security.keystore"));
+ sp<IKeystoreService> service = android::interface_cast<IKeystoreService>(binder);
+ ASSERT_TRUE(service);
+
+ String16 promptText16("Just a little test!");
+ String16 locale16("en");
+ std::vector<uint8_t> extraData{0xaa, 0xff, 0x00, 0x55};
+
+ sp<ConfirmationListener> listener = new ConfirmationListener();
+
+ auto future = listener->get_future();
+ int32_t aidl_return;
+
+ android::binder::Status status = service->presentConfirmationPrompt(
+ listener, promptText16, extraData, locale16, 0, &aidl_return);
+ ASSERT_TRUE(status.isOk()) << "Presenting confirmation prompt failed with binder status '"
+ << status.toString8().c_str() << "'.\n";
+ ConfirmationResponseCode responseCode = static_cast<ConfirmationResponseCode>(aidl_return);
+ ASSERT_EQ(responseCode, ConfirmationResponseCode::OK)
+ << "Presenting confirmation prompt failed with response code " << aidl_return << ".\n";
+
+ auto fstatus = future.wait_for(2s);
+ EXPECT_EQ(fstatus, std::future_status::timeout);
+
+ status = service->cancelConfirmationPrompt(listener, &aidl_return);
+ ASSERT_TRUE(status.isOk());
+
+ responseCode = static_cast<ConfirmationResponseCode>(aidl_return);
+ ASSERT_EQ(responseCode, ConfirmationResponseCode::OK);
+
+ future.wait();
+ auto [rc, dataThatWasConfirmed] = future.get();
+
+ ASSERT_EQ(rc, ConfirmationResponseCode::Aborted);
+}