summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorChad Brubaker <cbrubaker@google.com>2015-09-09 20:34:09 -0700
committerChad Brubaker <cbrubaker@google.com>2015-10-09 13:31:18 -0700
commit410ba59a76a8feb48ffb5bde3045ac6f76db0c36 (patch)
treed38d1afece977ce4515b9da8f809eb38b40dee6d
parentc2120744da8d0612ad54484b314f94e1e6e3a167 (diff)
downloadandroid_system_security-410ba59a76a8feb48ffb5bde3045ac6f76db0c36.tar.gz
android_system_security-410ba59a76a8feb48ffb5bde3045ac6f76db0c36.tar.bz2
android_system_security-410ba59a76a8feb48ffb5bde3045ac6f76db0c36.zip
Fix failure to save master key on new profile
New profiles use the master key of the parent user for keystore. Unfortunately copyMasterKey only copies the key from the parent to the user in memory but doesn't save it to disk, causing the child user to be uninitialized after a reboot. Bug: 23889443 (cherry picked from commit 79e0f6440aee69659bc01a0669a329dbaeaf471c) Change-Id: I1f148fde3862d22292dfce217aacdc3f70f9c2ef
-rw-r--r--keystore/keystore.cpp52
1 files changed, 48 insertions, 4 deletions
diff --git a/keystore/keystore.cpp b/keystore/keystore.cpp
index 0906abf..bb5a411 100644
--- a/keystore/keystore.cpp
+++ b/keystore/keystore.cpp
@@ -920,6 +920,38 @@ public:
}
memcpy(mMasterKey, src->mMasterKey, MASTER_KEY_SIZE_BYTES);
setupMasterKeys();
+ return copyMasterKeyFile(src);
+ }
+
+ ResponseCode copyMasterKeyFile(UserState* src) {
+ /* Copy the master key file to the new user.
+ * Unfortunately we don't have the src user's password so we cannot
+ * generate a new file with a new salt.
+ */
+ int in = TEMP_FAILURE_RETRY(open(src->getMasterKeyFileName(), O_RDONLY));
+ if (in < 0) {
+ return ::SYSTEM_ERROR;
+ }
+ blob rawBlob;
+ size_t length = readFully(in, (uint8_t*) &rawBlob, sizeof(rawBlob));
+ if (close(in) != 0) {
+ return ::SYSTEM_ERROR;
+ }
+ int out = TEMP_FAILURE_RETRY(open(mMasterKeyFile,
+ O_WRONLY | O_TRUNC | O_CREAT, S_IRUSR | S_IWUSR));
+ if (out < 0) {
+ return ::SYSTEM_ERROR;
+ }
+ size_t outLength = writeFully(out, (uint8_t*) &rawBlob, length);
+ if (close(out) != 0) {
+ return ::SYSTEM_ERROR;
+ }
+ if (outLength != length) {
+ ALOGW("blob not fully written %zu != %zu", outLength, length);
+ unlink(mMasterKeyFile);
+ return ::SYSTEM_ERROR;
+ }
+
return ::NO_ERROR;
}
@@ -1980,10 +2012,12 @@ public:
}
// Unconditionally clear the keystore, just to be safe.
mKeyStore->resetUser(userId, false);
-
- // If the user has a parent user then use the parent's
- // masterkey/password, otherwise there's nothing to do.
if (parentId != -1) {
+ // This profile must share the same master key password as the parent
+ // profile. Because the password of the parent profile is not known
+ // here, the best we can do is copy the parent's master key and master
+ // key file. This makes this profile use the same master key as the
+ // parent profile, forever.
return mKeyStore->copyMasterKey(parentId, userId);
} else {
return ::NO_ERROR;
@@ -2021,7 +2055,17 @@ public:
State state = mKeyStore->getState(userId);
if (state != ::STATE_LOCKED) {
- ALOGI("calling unlock when not locked, ignoring.");
+ switch (state) {
+ case ::STATE_NO_ERROR:
+ ALOGI("calling unlock when already unlocked, ignoring.");
+ break;
+ case ::STATE_UNINITIALIZED:
+ ALOGE("unlock called on uninitialized keystore.");
+ break;
+ default:
+ ALOGE("unlock called on keystore in unknown state: %d", state);
+ break;
+ }
return state;
}