Merge "Store password in vold"
diff --git a/CommandListener.cpp b/CommandListener.cpp
index 9ef29f9..1177602 100644
--- a/CommandListener.cpp
+++ b/CommandListener.cpp
@@ -662,10 +662,20 @@
cli->sendMsg(ResponseCode::OpFailedStorageNotFound, "Error", false);
return 0;
}
- } else if (!strcmp(argv[1], "justdecrypted")) {
- SLOGD("cryptfs justdecrypted");
+ } else if (!strcmp(argv[1], "getpw")) {
+ SLOGD("cryptfs getpw");
dumpArgs(argc, argv, -1);
- rc = cryptfs_just_decrypted();
+ char* password = cryptfs_get_password();
+ if (password) {
+ cli->sendMsg(ResponseCode::CommandOkay, password, false);
+ return 0;
+ }
+ rc = -1;
+ } else if (!strcmp(argv[1], "clearpw")) {
+ SLOGD("cryptfs clearpw");
+ dumpArgs(argc, argv, -1);
+ cryptfs_clear_password();
+ rc = 0;
} else {
dumpArgs(argc, argv, -1);
cli->sendMsg(ResponseCode::CommandSyntaxError, "Unknown cryptfs cmd", false);
diff --git a/cryptfs.c b/cryptfs.c
index 30e13a3..5a9a4da 100644
--- a/cryptfs.c
+++ b/cryptfs.c
@@ -79,11 +79,23 @@
static int master_key_saved = 0;
static struct crypt_persist_data *persist_data = NULL;
-/* Set when userdata is successfully decrypted and mounted.
- * Reset whenever read (via cryptfs_just_decrypted)
- * (Read by keyguard to avoid a double prompt.)
+/* Store password when userdata is successfully decrypted and mounted.
+ * Cleared by cryptfs_clear_password
+ *
+ * To avoid a double prompt at boot, we need to store the CryptKeeper
+ * password and pass it to KeyGuard, which uses it to unlock KeyStore.
+ * Since the entire framework is torn down and rebuilt after encryption,
+ * we have to use a daemon or similar to store the password. Since vold
+ * is secured against IPC except from system processes, it seems a reasonable
+ * place to store this.
+ *
+ * password should be cleared once it has been used.
+ *
+ * password is aged out after password_max_age_seconds seconds.
*/
-static int just_decrypted = 0;
+static char* password = 0;
+static int password_expiry_time = 0;
+static const int password_max_age_seconds = 60;
extern struct fstab *fstab;
@@ -1482,7 +1494,11 @@
DATA_MNT_POINT, "userdata");
if (rc == 0 && crypt_ftr.crypt_type != CRYPT_TYPE_DEFAULT) {
- just_decrypted = 1;
+ cryptfs_clear_password();
+ password = strdup(passwd);
+ struct timespec now;
+ clock_gettime(CLOCK_BOOTTIME, &now);
+ password_expiry_time = now.tv_sec + password_max_age_seconds;
}
return rc;
@@ -2631,9 +2647,25 @@
return crypt_ftr.crypt_type;
}
-int cryptfs_just_decrypted(void)
+char* cryptfs_get_password()
{
- int rc = just_decrypted;
- just_decrypted = 0;
- return rc;
+ struct timespec now;
+ clock_gettime(CLOCK_MONOTONIC, &now);
+ if (now.tv_sec < password_expiry_time) {
+ return password;
+ } else {
+ cryptfs_clear_password();
+ return 0;
+ }
+}
+
+void cryptfs_clear_password()
+{
+ if (password) {
+ size_t len = strlen(password);
+ memset(password, 0, len);
+ free(password);
+ password = 0;
+ password_expiry_time = 0;
+ }
}
diff --git a/cryptfs.h b/cryptfs.h
index 5fbfaef..0e60d77 100644
--- a/cryptfs.h
+++ b/cryptfs.h
@@ -173,7 +173,8 @@
int cryptfs_setfield(char *fieldname, char *value);
int cryptfs_mount_default_encrypted(void);
int cryptfs_get_password_type(void);
- int cryptfs_just_decrypted(void);
+ char* cryptfs_get_password(void);
+ void cryptfs_clear_password(void);
#ifdef __cplusplus
}
#endif