Refurbish granting mechanism
Keystore stores key blobs in with filenames that include the symbolic
name and the uid of the owner. This behaviour should have been
completely opaque to the user keystore. However, the granting mechanism,
by which an app can allow another app to use one of its keys, leaked the
internal structure in that the grantee had to specify the key name with
the granter's uid prefix in order to use the granted key. This in turn
collided with prefix handling in other parts of the framework.
This patch refurbishes the granting mechanism such that keystore can
choose a name for the grant. It uses the original symbolic key name as
prefix and appends _KEYSTOREGRANT_<grant_no> where the grant_no is
chosen as first free slot starting from 0. Each uid has its own grant_no
space.
This changes the grant call such that it now returns a string, which is
the alias name of the newly created grant. The string is empty if the
grant operation failed.
As before apps can still mask granted keys by importing a key with the
exact same name including the added suffix. But everybody deserves the
right to shoot themselves in the foot if they really want to.
Bug: 37264540
Bug: 62237038
Test: run cts-dev --module CtsDevicePolicyManagerTestCases --test
com.android.cts.devicepolicy.DeviceOwnerTest#testKeyManagement
because it grants a key
Change-Id: I723c44c7ae6782c8de42063744717d088cd49ba1
diff --git a/keystore/keystore.cpp b/keystore/keystore.cpp
index 43bb4be..ab386ad 100644
--- a/keystore/keystore.cpp
+++ b/keystore/keystore.cpp
@@ -48,11 +48,6 @@
}
KeyStore::~KeyStore() {
- for (android::Vector<grant_t*>::iterator it(mGrants.begin()); it != mGrants.end(); it++) {
- delete *it;
- }
- mGrants.clear();
-
for (android::Vector<UserState*>::iterator it(mMasterKeys.begin()); it != mMasterKeys.end();
it++) {
delete *it;
@@ -419,26 +414,12 @@
return ResponseCode::NO_ERROR;
}
-void KeyStore::addGrant(const char* filename, uid_t granteeUid) {
- const grant_t* existing = getGrant(filename, granteeUid);
- if (existing == NULL) {
- grant_t* grant = new grant_t;
- grant->uid = granteeUid;
- grant->filename = reinterpret_cast<const uint8_t*>(strdup(filename));
- mGrants.add(grant);
- }
+std::string KeyStore::addGrant(const char* filename, const char* alias, uid_t granteeUid) {
+ return mGrants.put(granteeUid, alias, filename);
}
bool KeyStore::removeGrant(const char* filename, uid_t granteeUid) {
- for (android::Vector<grant_t*>::iterator it(mGrants.begin()); it != mGrants.end(); it++) {
- grant_t* grant = *it;
- if (grant->uid == granteeUid &&
- !strcmp(reinterpret_cast<const char*>(grant->filename), filename)) {
- mGrants.erase(it);
- return true;
- }
- }
- return false;
+ return mGrants.removeByFileName(granteeUid, filename);
}
ResponseCode KeyStore::importKey(const uint8_t* key, size_t keyLen, const char* filename,
@@ -536,17 +517,9 @@
}
// They might be using a granted key.
- android::String8 filename8 = getKeyName(keyName, type);
- char* end;
- strtoul(filename8.string(), &end, 10);
- if (end[0] != '_' || end[1] == 0) {
- return ResponseCode::KEY_NOT_FOUND;
- }
- filepath8 = android::String8::format("%s/%s", getUserState(userId)->getUserDirName(),
- filename8.string());
- if (!hasGrant(filepath8.string(), uid)) {
- return responseCode;
- }
+ auto grant = mGrants.get(uid, keyName.string());
+ if (!grant) return ResponseCode::KEY_NOT_FOUND;
+ filepath8 = grant->key_file_.c_str();
// It is a granted key. Try to load it.
return get(filepath8.string(), keyBlob, type, userId);
@@ -595,17 +568,6 @@
return getUserState(userId);
}
-const grant_t* KeyStore::getGrant(const char* filename, uid_t uid) const {
- for (android::Vector<grant_t*>::const_iterator it(mGrants.begin()); it != mGrants.end(); it++) {
- grant_t* grant = *it;
- if (grant->uid == uid &&
- !strcmp(reinterpret_cast<const char*>(grant->filename), filename)) {
- return grant;
- }
- }
- return NULL;
-}
-
bool KeyStore::upgradeBlob(const char* filename, Blob* blob, const uint8_t oldVersion,
const BlobType type, uid_t uid) {
bool updated = false;