summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorRobin Lee <rgl@google.com>2014-08-19 17:37:55 +0100
committerRobin Lee <rgl@google.com>2014-08-29 23:10:18 +0100
commit4e865753346fc6a075966972a7a98051818859db (patch)
tree4d13f58ba1c43ceb7303d2489eb16eb47143a523
parent50122db50bcb6c1aab50ef235c8f9d264b50e97a (diff)
downloadsecurity-4e865753346fc6a075966972a7a98051818859db.tar.gz
APIs for syncing password between profiles
Bug: 16233206. Change-Id: I7941707ca66ac25bd122fd22e5e0f639e7af697e
-rw-r--r--keystore/IKeystoreService.cpp85
-rw-r--r--keystore/include/keystore/IKeystoreService.h9
-rw-r--r--keystore/keystore.cpp124
3 files changed, 201 insertions, 17 deletions
diff --git a/keystore/IKeystoreService.cpp b/keystore/IKeystoreService.cpp
index 727e746d..40fbe0ef 100644
--- a/keystore/IKeystoreService.cpp
+++ b/keystore/IKeystoreService.cpp
@@ -579,6 +579,65 @@ public:
}
return ret;
}
+
+ virtual int32_t reset_uid(int32_t uid) {
+ Parcel data, reply;
+ data.writeInterfaceToken(IKeystoreService::getInterfaceDescriptor());
+ data.writeInt32(uid);
+ status_t status = remote()->transact(BnKeystoreService::RESET_UID, data, &reply);
+ if (status != NO_ERROR) {
+ ALOGD("reset_uid() could not contact remote: %d\n", status);
+ return -1;
+ }
+ int32_t err = reply.readExceptionCode();
+ int32_t ret = reply.readInt32();
+ if (err < 0) {
+ ALOGD("reset_uid() caught exception %d\n", err);
+ return -1;
+ }
+ return ret;
+
+ }
+
+ virtual int32_t sync_uid(int32_t sourceUid, int32_t targetUid)
+ {
+ Parcel data, reply;
+ data.writeInterfaceToken(IKeystoreService::getInterfaceDescriptor());
+ data.writeInt32(sourceUid);
+ data.writeInt32(targetUid);
+ status_t status = remote()->transact(BnKeystoreService::SYNC_UID, data, &reply);
+ if (status != NO_ERROR) {
+ ALOGD("sync_uid() could not contact remote: %d\n", status);
+ return -1;
+ }
+ int32_t err = reply.readExceptionCode();
+ int32_t ret = reply.readInt32();
+ if (err < 0) {
+ ALOGD("sync_uid() caught exception %d\n", err);
+ return -1;
+ }
+ return ret;
+ }
+
+ virtual int32_t password_uid(const String16& password, int32_t uid)
+ {
+ Parcel data, reply;
+ data.writeInterfaceToken(IKeystoreService::getInterfaceDescriptor());
+ data.writeString16(password);
+ data.writeInt32(uid);
+ status_t status = remote()->transact(BnKeystoreService::PASSWORD_UID, data, &reply);
+ if (status != NO_ERROR) {
+ ALOGD("password_uid() could not contact remote: %d\n", status);
+ return -1;
+ }
+ int32_t err = reply.readExceptionCode();
+ int32_t ret = reply.readInt32();
+ if (err < 0) {
+ ALOGD("password_uid() caught exception %d\n", err);
+ return -1;
+ }
+ return ret;
+ }
};
IMPLEMENT_META_INTERFACE(KeystoreService, "android.security.keystore");
@@ -875,6 +934,32 @@ status_t BnKeystoreService::onTransact(
reply->writeInt32(ret);
return NO_ERROR;
}
+ case RESET_UID: {
+ CHECK_INTERFACE(IKeystoreService, data, reply);
+ int32_t uid = data.readInt32();
+ int32_t ret = reset_uid(uid);
+ reply->writeNoException();
+ reply->writeInt32(ret);
+ return NO_ERROR;
+ }
+ case SYNC_UID: {
+ CHECK_INTERFACE(IKeystoreService, data, reply);
+ int32_t sourceUid = data.readInt32();
+ int32_t targetUid = data.readInt32();
+ int32_t ret = sync_uid(sourceUid, targetUid);
+ reply->writeNoException();
+ reply->writeInt32(ret);
+ return NO_ERROR;
+ }
+ case PASSWORD_UID: {
+ CHECK_INTERFACE(IKeystoreService, data, reply);
+ String16 password = data.readString16();
+ int32_t uid = data.readInt32();
+ int32_t ret = password_uid(password, uid);
+ reply->writeNoException();
+ reply->writeInt32(ret);
+ return NO_ERROR;
+ }
default:
return BBinder::onTransact(code, data, reply, flags);
}
diff --git a/keystore/include/keystore/IKeystoreService.h b/keystore/include/keystore/IKeystoreService.h
index d7281e3c..afdff8df 100644
--- a/keystore/include/keystore/IKeystoreService.h
+++ b/keystore/include/keystore/IKeystoreService.h
@@ -65,6 +65,9 @@ public:
DUPLICATE = IBinder::FIRST_CALL_TRANSACTION + 20,
IS_HARDWARE_BACKED = IBinder::FIRST_CALL_TRANSACTION + 21,
CLEAR_UID = IBinder::FIRST_CALL_TRANSACTION + 22,
+ RESET_UID = IBinder::FIRST_CALL_TRANSACTION + 23,
+ SYNC_UID = IBinder::FIRST_CALL_TRANSACTION + 24,
+ PASSWORD_UID = IBinder::FIRST_CALL_TRANSACTION + 25,
};
DECLARE_META_INTERFACE(KeystoreService);
@@ -120,6 +123,12 @@ public:
virtual int32_t is_hardware_backed(const String16& keyType) = 0;
virtual int32_t clear_uid(int64_t uid) = 0;
+
+ virtual int32_t reset_uid(int32_t uid) = 0;
+
+ virtual int32_t sync_uid(int32_t sourceUid, int32_t targetUid) = 0;
+
+ virtual int32_t password_uid(const String16& password, int32_t uid) = 0;
};
// ----------------------------------------------------------------------------
diff --git a/keystore/keystore.cpp b/keystore/keystore.cpp
index bda69488..9e460d77 100644
--- a/keystore/keystore.cpp
+++ b/keystore/keystore.cpp
@@ -136,22 +136,25 @@ static void keymaster_device_release(keymaster_device_t* dev) {
/* Here are the permissions, actions, users, and the main function. */
typedef enum {
- P_TEST = 1 << 0,
- P_GET = 1 << 1,
- P_INSERT = 1 << 2,
- P_DELETE = 1 << 3,
- P_EXIST = 1 << 4,
- P_SAW = 1 << 5,
- P_RESET = 1 << 6,
- P_PASSWORD = 1 << 7,
- P_LOCK = 1 << 8,
- P_UNLOCK = 1 << 9,
- P_ZERO = 1 << 10,
- P_SIGN = 1 << 11,
- P_VERIFY = 1 << 12,
- P_GRANT = 1 << 13,
- P_DUPLICATE = 1 << 14,
- P_CLEAR_UID = 1 << 15,
+ P_TEST = 1 << 0,
+ P_GET = 1 << 1,
+ P_INSERT = 1 << 2,
+ P_DELETE = 1 << 3,
+ P_EXIST = 1 << 4,
+ P_SAW = 1 << 5,
+ P_RESET = 1 << 6,
+ P_PASSWORD = 1 << 7,
+ P_LOCK = 1 << 8,
+ P_UNLOCK = 1 << 9,
+ P_ZERO = 1 << 10,
+ P_SIGN = 1 << 11,
+ P_VERIFY = 1 << 12,
+ P_GRANT = 1 << 13,
+ P_DUPLICATE = 1 << 14,
+ P_CLEAR_UID = 1 << 15,
+ P_RESET_UID = 1 << 16,
+ P_SYNC_UID = 1 << 17,
+ P_PASSWORD_UID = 1 << 18,
} perm_t;
static struct user_euid {
@@ -180,7 +183,10 @@ const char *perm_labels[] = {
"verify",
"grant",
"duplicate",
- "clear_uid"
+ "clear_uid",
+ "reset_uid",
+ "sync_uid",
+ "password_uid",
};
static struct user_perm {
@@ -761,6 +767,18 @@ public:
return ::NO_ERROR;
}
+ ResponseCode copyMasterKey(UserState* src) {
+ if (mState != STATE_UNINITIALIZED) {
+ return ::SYSTEM_ERROR;
+ }
+ if (src->getState() != STATE_NO_ERROR) {
+ return ::SYSTEM_ERROR;
+ }
+ memcpy(mMasterKey, src->mMasterKey, MASTER_KEY_SIZE_BYTES);
+ setupMasterKeys();
+ return ::NO_ERROR;
+ }
+
ResponseCode writeMasterKey(const android::String8& pw, Entropy* entropy) {
uint8_t passwordKey[MASTER_KEY_SIZE_BYTES];
generateKeyFromPassword(passwordKey, MASTER_KEY_SIZE_BYTES, pw, mSalt);
@@ -969,11 +987,18 @@ public:
return userState->initialize(pw, mEntropy);
}
+ ResponseCode copyMasterKey(uid_t src, uid_t uid) {
+ UserState *userState = getUserState(uid);
+ UserState *initState = getUserState(src);
+ return userState->copyMasterKey(initState);
+ }
+
ResponseCode writeMasterKey(const android::String8& pw, uid_t uid) {
UserState* userState = getUserState(uid);
return userState->writeMasterKey(pw, mEntropy);
}
+
ResponseCode readMasterKey(const android::String8& pw, uid_t uid) {
UserState* userState = getUserState(uid);
return userState->readMasterKey(pw, mEntropy);
@@ -2381,6 +2406,71 @@ public:
return rc;
}
+ int32_t reset_uid(int32_t uid) {
+ 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);
+ return ::PERMISSION_DENIED;
+ }
+ if (callingUid != AID_SYSTEM) {
+ ALOGW("permission denied for %d: reset_uid %d", callingUid, uid);
+ return ::PERMISSION_DENIED;
+ }
+
+ return mKeyStore->reset(uid) ? ::NO_ERROR : ::SYSTEM_ERROR;
+ }
+
+ int32_t sync_uid(int32_t sourceUid, int32_t targetUid) {
+ uid_t callingUid = IPCThreadState::self()->getCallingUid();
+ pid_t spid = IPCThreadState::self()->getCallingPid();
+ if (!has_permission(callingUid, P_SYNC_UID, spid)) {
+ ALOGW("permission denied for %d: sync_uid %d -> %d", callingUid, sourceUid, targetUid);
+ return ::PERMISSION_DENIED;
+ }
+ if (callingUid != AID_SYSTEM) {
+ ALOGW("permission denied for %d: sync_uid %d -> %d", callingUid, sourceUid, targetUid);
+ return ::PERMISSION_DENIED;
+ }
+ if (sourceUid == targetUid) {
+ return ::SYSTEM_ERROR;
+ }
+
+ // Initialise user keystore with existing master key held in-memory
+ return mKeyStore->copyMasterKey(sourceUid, targetUid);
+ }
+
+ int32_t password_uid(const String16& pw, int32_t targetUid) {
+ uid_t callingUid = IPCThreadState::self()->getCallingUid();
+ pid_t spid = IPCThreadState::self()->getCallingPid();
+ if (!has_permission(callingUid, P_PASSWORD_UID, spid)) {
+ ALOGW("permission denied for %d: password_uid %d", callingUid, targetUid);
+ return ::PERMISSION_DENIED;
+ }
+ if (callingUid != AID_SYSTEM) {
+ ALOGW("permission denied for %d: password_uid %d", callingUid, targetUid);
+ return ::PERMISSION_DENIED;
+ }
+
+ const String8 password8(pw);
+
+ switch (mKeyStore->getState(targetUid)) {
+ case ::STATE_UNINITIALIZED: {
+ // generate master key, encrypt with password, write to file, initialize mMasterKey*.
+ return mKeyStore->initializeUser(password8, targetUid);
+ }
+ case ::STATE_NO_ERROR: {
+ // rewrite master key with new password.
+ return mKeyStore->writeMasterKey(password8, targetUid);
+ }
+ case ::STATE_LOCKED: {
+ // read master key, decrypt with password, initialize mMasterKey*.
+ return mKeyStore->readMasterKey(password8, targetUid);
+ }
+ }
+ return ::SYSTEM_ERROR;
+ }
+
private:
inline bool isKeystoreUnlocked(State state) {
switch (state) {