APIs for syncing password between profiles

Bug: 16233206.
Change-Id: I7941707ca66ac25bd122fd22e5e0f639e7af697e
diff --git a/keystore/keystore.cpp b/keystore/keystore.cpp
index bda6948..9e460d7 100644
--- a/keystore/keystore.cpp
+++ b/keystore/keystore.cpp
@@ -136,22 +136,25 @@
 
 /* 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 @@
     "verify",
     "grant",
     "duplicate",
-    "clear_uid"
+    "clear_uid",
+    "reset_uid",
+    "sync_uid",
+    "password_uid",
 };
 
 static struct user_perm {
@@ -761,6 +767,18 @@
         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 @@
         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 @@
         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) {