Delete user's keys only after keystore reset
Original behaviour deletes all keys on the device, not just those for
the caller. We use the clear_uid routine to call delete_keypair on all
known keys instead.
Bug: 17403144
Change-Id: If43465ed593153a557b2129968a3adf12d2749cb
diff --git a/keystore/keystore.cpp b/keystore/keystore.cpp
index 50e2ed4..a24feba 100644
--- a/keystore/keystore.cpp
+++ b/keystore/keystore.cpp
@@ -998,7 +998,6 @@
return userState->writeMasterKey(pw, mEntropy);
}
-
ResponseCode readMasterKey(const android::String8& pw, uid_t uid) {
UserState* userState = getUserState(uid);
return userState->readMasterKey(pw, mEntropy);
@@ -1024,7 +1023,20 @@
}
bool reset(uid_t uid) {
+ android::String8 prefix("");
+ android::Vector<android::String16> aliases;
+ if (saw(prefix, &aliases, uid) != ::NO_ERROR) {
+ return ::SYSTEM_ERROR;
+ }
+
UserState* userState = getUserState(uid);
+ for (uint32_t i = 0; i < aliases.size(); i++) {
+ android::String8 filename(aliases[i]);
+ filename = android::String8::format("%s/%s", userState->getUserDirName(),
+ getKeyName(filename).string());
+ del(filename, ::TYPE_ANY, uid);
+ }
+
userState->zeroizeMasterKeysInMemory();
userState->setState(STATE_UNINITIALIZED);
return userState->reset();
@@ -1121,6 +1133,71 @@
mEntropy);
}
+ ResponseCode del(const char *filename, const BlobType type, uid_t uid) {
+ Blob keyBlob;
+ ResponseCode rc = get(filename, &keyBlob, type, uid);
+ if (rc != ::NO_ERROR) {
+ return rc;
+ }
+
+ if (keyBlob.getType() == ::TYPE_KEY_PAIR) {
+ // A device doesn't have to implement delete_keypair.
+ if (mDevice->delete_keypair != NULL && !keyBlob.isFallback()) {
+ if (mDevice->delete_keypair(mDevice, keyBlob.getValue(), keyBlob.getLength())) {
+ rc = ::SYSTEM_ERROR;
+ }
+ }
+ }
+ if (rc != ::NO_ERROR) {
+ return rc;
+ }
+
+ return (unlink(filename) && errno != ENOENT) ? ::SYSTEM_ERROR : ::NO_ERROR;
+ }
+
+ ResponseCode saw(const android::String8& prefix, android::Vector<android::String16> *matches,
+ uid_t uid) {
+
+ UserState* userState = getUserState(uid);
+ size_t n = prefix.length();
+
+ DIR* dir = opendir(userState->getUserDirName());
+ if (!dir) {
+ ALOGW("can't open directory for user: %s", strerror(errno));
+ return ::SYSTEM_ERROR;
+ }
+
+ struct dirent* file;
+ while ((file = readdir(dir)) != NULL) {
+ // We only care about files.
+ if (file->d_type != DT_REG) {
+ continue;
+ }
+
+ // Skip anything that starts with a "."
+ if (file->d_name[0] == '.') {
+ continue;
+ }
+
+ if (!strncmp(prefix.string(), file->d_name, n)) {
+ const char* p = &file->d_name[n];
+ size_t plen = strlen(p);
+
+ size_t extra = decode_key_length(p, plen);
+ char *match = (char*) malloc(extra + 1);
+ if (match != NULL) {
+ decode_key(match, p, plen);
+ matches->push(android::String16(match, extra));
+ free(match);
+ } else {
+ ALOGW("could not allocate match of size %zd", extra);
+ }
+ }
+ }
+ closedir(dir);
+ return ::NO_ERROR;
+ }
+
void addGrant(const char* filename, uid_t granteeUid) {
const grant_t* existing = getGrant(filename, granteeUid);
if (existing == NULL) {
@@ -1595,14 +1672,7 @@
String8 name8(name);
String8 filename(mKeyStore->getKeyNameForUidWithDir(name8, targetUid));
-
- Blob keyBlob;
- ResponseCode responseCode = mKeyStore->get(filename.string(), &keyBlob, TYPE_GENERIC,
- targetUid);
- if (responseCode != ::NO_ERROR) {
- return responseCode;
- }
- return (unlink(filename) && errno != ENOENT) ? ::SYSTEM_ERROR : ::NO_ERROR;
+ return mKeyStore->del(filename.string(), ::TYPE_GENERIC, targetUid);
}
int32_t exist(const String16& name, int targetUid) {
@@ -1642,46 +1712,12 @@
return ::PERMISSION_DENIED;
}
- UserState* userState = mKeyStore->getUserState(targetUid);
- DIR* dir = opendir(userState->getUserDirName());
- if (!dir) {
- ALOGW("can't open directory for user: %s", strerror(errno));
- return ::SYSTEM_ERROR;
- }
-
const String8 prefix8(prefix);
String8 filename(mKeyStore->getKeyNameForUid(prefix8, targetUid));
- size_t n = filename.length();
- struct dirent* file;
- while ((file = readdir(dir)) != NULL) {
- // We only care about files.
- if (file->d_type != DT_REG) {
- continue;
- }
-
- // Skip anything that starts with a "."
- if (file->d_name[0] == '.') {
- continue;
- }
-
- if (!strncmp(filename.string(), file->d_name, n)) {
- const char* p = &file->d_name[n];
- size_t plen = strlen(p);
-
- size_t extra = decode_key_length(p, plen);
- char *match = (char*) malloc(extra + 1);
- if (match != NULL) {
- decode_key(match, p, plen);
- matches->push(String16(match, extra));
- free(match);
- } else {
- ALOGW("could not allocate match of size %zd", extra);
- }
- }
+ if (mKeyStore->saw(filename, matches, targetUid) != ::NO_ERROR) {
+ return ::SYSTEM_ERROR;
}
- closedir(dir);
-
return ::NO_ERROR;
}
@@ -1693,25 +1729,7 @@
return ::PERMISSION_DENIED;
}
- ResponseCode rc = mKeyStore->reset(callingUid) ? ::NO_ERROR : ::SYSTEM_ERROR;
-
- const keymaster_device_t* device = mKeyStore->getDevice();
- if (device == NULL) {
- ALOGE("No keymaster device!");
- return ::SYSTEM_ERROR;
- }
-
- if (device->delete_all == NULL) {
- ALOGV("keymaster device doesn't implement delete_all");
- return rc;
- }
-
- if (device->delete_all(device)) {
- ALOGE("Problem calling keymaster's delete_all");
- return ::SYSTEM_ERROR;
- }
-
- return rc;
+ return mKeyStore->reset(callingUid) ? ::NO_ERROR : ::SYSTEM_ERROR;
}
/*
@@ -2148,33 +2166,7 @@
String8 name8(name);
String8 filename(mKeyStore->getKeyNameForUidWithDir(name8, targetUid));
-
- Blob keyBlob;
- ResponseCode responseCode = mKeyStore->get(filename.string(), &keyBlob, ::TYPE_KEY_PAIR,
- targetUid);
- if (responseCode != ::NO_ERROR) {
- return responseCode;
- }
-
- ResponseCode rc = ::NO_ERROR;
-
- const keymaster_device_t* device = mKeyStore->getDevice();
- if (device == NULL) {
- rc = ::SYSTEM_ERROR;
- } else {
- // A device doesn't have to implement delete_keypair.
- if (device->delete_keypair != NULL && !keyBlob.isFallback()) {
- if (device->delete_keypair(device, keyBlob.getValue(), keyBlob.getLength())) {
- rc = ::SYSTEM_ERROR;
- }
- }
- }
-
- if (rc != ::NO_ERROR) {
- return rc;
- }
-
- return (unlink(filename) && errno != ENOENT) ? ::SYSTEM_ERROR : ::NO_ERROR;
+ return mKeyStore->del(filename.string(), ::TYPE_KEY_PAIR, targetUid);
}
int32_t grant(const String16& name, int32_t granteeUid) {
@@ -2345,75 +2337,34 @@
return ::SYSTEM_ERROR;
}
- UserState* userState = mKeyStore->getUserState(targetUid);
- DIR* dir = opendir(userState->getUserDirName());
- if (!dir) {
- ALOGW("can't open user directory: %s", strerror(errno));
+ String8 prefix = String8::format("%u_", targetUid);
+ Vector<String16> aliases;
+ if (mKeyStore->saw(prefix, &aliases, targetUid) != ::NO_ERROR) {
return ::SYSTEM_ERROR;
}
- char prefix[NAME_MAX];
- int n = snprintf(prefix, NAME_MAX, "%u_", targetUid);
-
- ResponseCode rc = ::NO_ERROR;
-
- struct dirent* file;
- while ((file = readdir(dir)) != NULL) {
- // We only care about files.
- if (file->d_type != DT_REG) {
- continue;
- }
-
- // Skip anything that starts with a "."
- if (file->d_name[0] == '.') {
- continue;
- }
-
- if (strncmp(prefix, file->d_name, n)) {
- continue;
- }
-
- String8 filename(String8::format("%s/%s", userState->getUserDirName(), file->d_name));
- Blob keyBlob;
- if (mKeyStore->get(filename.string(), &keyBlob, ::TYPE_ANY, targetUid)
- != ::NO_ERROR) {
- ALOGW("couldn't open %s", filename.string());
- continue;
- }
-
- if (keyBlob.getType() == ::TYPE_KEY_PAIR) {
- // A device doesn't have to implement delete_keypair.
- if (device->delete_keypair != NULL && !keyBlob.isFallback()) {
- if (device->delete_keypair(device, keyBlob.getValue(), keyBlob.getLength())) {
- rc = ::SYSTEM_ERROR;
- ALOGW("device couldn't remove %s", filename.string());
- }
- }
- }
-
- if (unlinkat(dirfd(dir), file->d_name, 0) && errno != ENOENT) {
- rc = ::SYSTEM_ERROR;
- ALOGW("couldn't unlink %s", filename.string());
- }
+ for (uint32_t i = 0; i < aliases.size(); i++) {
+ String8 name8(aliases[i]);
+ String8 filename(mKeyStore->getKeyNameForUidWithDir(name8, targetUid));
+ mKeyStore->del(filename.string(), ::TYPE_ANY, targetUid);
}
- closedir(dir);
-
- return rc;
+ return ::NO_ERROR;
}
- int32_t reset_uid(int32_t uid) {
+ int32_t reset_uid(int32_t targetUid) {
uid_t callingUid = IPCThreadState::self()->getCallingUid();
pid_t spid = IPCThreadState::self()->getCallingPid();
+
if (!has_permission(callingUid, P_RESET_UID, spid)) {
- ALOGW("permission denied for %d: reset_uid %d", callingUid, uid);
+ ALOGW("permission denied for %d: reset_uid %d", callingUid, targetUid);
return ::PERMISSION_DENIED;
}
- if (callingUid != AID_SYSTEM) {
- ALOGW("permission denied for %d: reset_uid %d", callingUid, uid);
+ if (!is_self_or_system(callingUid, targetUid)) {
+ ALOGW("permission denied for %d: reset_uid %d", callingUid, targetUid);
return ::PERMISSION_DENIED;
}
- return mKeyStore->reset(uid) ? ::NO_ERROR : ::SYSTEM_ERROR;
+ return mKeyStore->reset(targetUid) ? ::NO_ERROR : ::SYSTEM_ERROR;
}
int32_t sync_uid(int32_t sourceUid, int32_t targetUid) {