DO NOT MERGE - Merge qt-dev-plus-aosp-without-vendor (5699924) into stage-aosp-master

Bug: 134405016
Change-Id: I7b2848c7eff8a193adc998d4d2dfea0ec05b7b73
This commit is contained in:
Xin Li 2019-07-01 21:00:30 +00:00
commit 76206993e4
9 changed files with 185 additions and 36 deletions

View file

@ -9,7 +9,16 @@ cc_defaults {
],
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,

View file

@ -704,10 +704,27 @@ std::string KeyBlobEntry::getCharacteristicsBlobPath() const {
}
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) {

View file

@ -69,8 +69,6 @@ using ::android::security::keystore::KeystoreResponse;
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 @@ Status KeyStoreService::onUserPasswordChanged(int32_t userId, const String16& pa
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,
@ -996,9 +990,8 @@ Status KeyStoreService::addAuthToken(const ::std::vector<uint8_t>& authTokenAsVe
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 @@ int isDeviceIdAttestationRequested(const KeymasterArguments& params) {
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 @@ Status KeyStoreService::attestKey(
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));
}
@ -1277,7 +1259,8 @@ uid_t KeyStoreService::getEffectiveUid(int32_t targetUid) {
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;
}
@ -1295,7 +1278,8 @@ bool KeyStoreService::checkBinderPermission(perm_t permission, int32_t targetUid
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;
}

View file

@ -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;

View file

@ -156,6 +156,7 @@ int main(int argc, char* argv[]) {
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!";

View file

@ -92,6 +92,7 @@ static const perm_t DEFAULT_PERMS = static_cast<perm_t>(
struct audit_data {
pid_t pid;
uid_t uid;
const char* sid;
};
const char* get_perm_label(perm_t perm) {
@ -111,7 +112,8 @@ static int audit_callback(void* data, security_class_t /* cls */, char* buf, siz
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 @@ int configure_selinux() {
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 @@ static bool keystore_selinux_check_access(uid_t uid, perm_t perm, pid_t spid) {
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 @@ uid_t get_keystore_euid(uid_t uid) {
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);
}
/**

View file

@ -51,7 +51,12 @@ const char* get_perm_label(perm_t perm);
*/
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

View file

@ -37,3 +37,33 @@ cc_test {
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,
}
}

View file

@ -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);
}