diff options
author | Robin Lee <rgl@google.com> | 2014-08-19 17:37:55 +0100 |
---|---|---|
committer | Robin Lee <rgl@google.com> | 2014-08-29 23:10:18 +0100 |
commit | 4e865753346fc6a075966972a7a98051818859db (patch) | |
tree | 4d13f58ba1c43ceb7303d2489eb16eb47143a523 | |
parent | 50122db50bcb6c1aab50ef235c8f9d264b50e97a (diff) | |
download | security-4e865753346fc6a075966972a7a98051818859db.tar.gz |
APIs for syncing password between profiles
Bug: 16233206.
Change-Id: I7941707ca66ac25bd122fd22e5e0f639e7af697e
-rw-r--r-- | keystore/IKeystoreService.cpp | 85 | ||||
-rw-r--r-- | keystore/include/keystore/IKeystoreService.h | 9 | ||||
-rw-r--r-- | keystore/keystore.cpp | 124 |
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) { |