Merge "vold: Idle-maint issues discards fully"
diff --git a/cryptfs.cpp b/cryptfs.cpp
index 234899e..09e67af 100644
--- a/cryptfs.cpp
+++ b/cryptfs.cpp
@@ -72,7 +72,15 @@
 #define DM_CRYPT_BUF_SIZE 4096
 
 #define HASH_COUNT 2000
-#define IV_LEN_BYTES 16
+
+constexpr size_t INTERMEDIATE_KEY_LEN_BYTES = 16;
+constexpr size_t INTERMEDIATE_IV_LEN_BYTES = 16;
+constexpr size_t INTERMEDIATE_BUF_SIZE =
+    (INTERMEDIATE_KEY_LEN_BYTES + INTERMEDIATE_IV_LEN_BYTES);
+
+// SCRYPT_LEN is used by struct crypt_mnt_ftr for its intermediate key.
+static_assert(INTERMEDIATE_BUF_SIZE == SCRYPT_LEN,
+              "Mismatch of intermediate key sizes");
 
 #define KEY_IN_FOOTER  "footer"
 
@@ -97,11 +105,6 @@
 
 #define CREATE_CRYPTO_BLK_DEV_FLAGS_ALLOW_ENCRYPT_OVERRIDE (1)
 
-// EVP_DecryptUpdate() requires not just our key length, but up to
-// block length - 1 additional bytes for its work.  We provide a buffer
-// size that will work for all possible ciphers.
-#define DECRYPTED_MASTER_KEY_BUF_SIZE (MAX_KEY_LEN + EVP_MAX_BLOCK_LENGTH - 1)
-
 static int put_crypt_ftr_and_key(struct crypt_mnt_ftr* crypt_ftr);
 
 static unsigned char saved_master_key[MAX_KEY_LEN];
@@ -261,92 +264,120 @@
 
 namespace {
 
-struct CryptType;
+struct CryptoType;
 
-// Use to get the CryptType in use on this device.
-const CryptType &get_crypt_type();
+// Use to get the CryptoType in use on this device.
+const CryptoType &get_crypto_type();
 
-struct CryptType {
-    const char * name;
-    __le32 keysize;
+struct CryptoType {
+    // We should only be constructing CryptoTypes as part of
+    // supported_crypto_types[].  We do it via this pseudo-builder pattern,
+    // which isn't pure or fully protected as a concession to being able to
+    // do it all at compile time.  Add new CryptoTypes in
+    // supported_crypto_types[] below.
+    constexpr CryptoType() : CryptoType(nullptr, nullptr, 0xFFFFFFFF) {}
+    constexpr CryptoType set_keysize(uint32_t size) const {
+        return CryptoType(this->property_name, this->crypto_name, size);
+    }
+    constexpr CryptoType set_property_name(const char *property) const {
+        return CryptoType(property, this->crypto_name, this->keysize);
+    }
+    constexpr CryptoType set_crypto_name(const char *crypto) const {
+        return CryptoType(this->property_name, crypto, this->keysize);
+    }
 
-    constexpr CryptType(const char *n, size_t size) : name(n), keysize(size) {}
+    constexpr const char *get_property_name() const { return property_name; }
+    constexpr const char *get_crypto_name() const { return crypto_name; }
+    constexpr uint32_t get_keysize() const { return keysize; }
 
  private:
-    friend const CryptType &get_crypt_type();
-    static const CryptType &get_device_crypt_name();
+    const char *property_name;
+    const char *crypto_name;
+    uint32_t keysize;
+
+    constexpr CryptoType(const char *property, const char *crypto,
+                         uint32_t ksize)
+        : property_name(property), crypto_name(crypto), keysize(ksize) {}
+    friend const CryptoType &get_crypto_type();
+    static const CryptoType &get_device_crypto_algorithm();
 };
 
 // We only want to parse this read-only property once.  But we need to wait
 // until the system is initialized before we can read it.  So we use a static
 // scoped within this function to get it only once.
-const CryptType &get_crypt_type() {
-    static CryptType crypt_type = CryptType::get_device_crypt_name();
-    return crypt_type;
+const CryptoType &get_crypto_type() {
+    static CryptoType crypto_type = CryptoType::get_device_crypto_algorithm();
+    return crypto_type;
 }
 
-__le32 get_keysize() {
-    return get_crypt_type().keysize;
-}
+constexpr CryptoType default_crypto_type = CryptoType()
+    .set_property_name("AES-128-CBC")
+    .set_crypto_name("aes-cbc-essiv:sha256")
+    .set_keysize(16);
 
-const char *get_crypt_name() {
-    return get_crypt_type().name;
-}
-
-
-
-constexpr CryptType default_crypt_type = CryptType("aes-cbc-essiv:sha256", 16);
-
-constexpr CryptType supported_crypt_types[] = {
-    default_crypt_type,
-    CryptType("speck128-xts-plain64", 32),
-    // Add new CryptTypes here.  Order is not important.
+constexpr CryptoType supported_crypto_types[] = {
+    default_crypto_type,
+    CryptoType()
+        .set_property_name("Speck128/128-XTS")
+        .set_crypto_name("speck128-xts-plain64")
+        .set_keysize(32),
+    // Add new CryptoTypes here.  Order is not important.
 };
 
 
 // ---------- START COMPILE-TIME SANITY CHECK BLOCK -------------------------
-// We confirm all supported_crypt_types have a small enough keysize.
+// We confirm all supported_crypto_types have a small enough keysize and
+// had both set_property_name() and set_crypto_name() called.
 
 template <typename T, size_t N>
 constexpr size_t array_length(T (&)[N]) { return N; }
 
-constexpr bool indexOutOfBoundsForCryptTypes(size_t index) {
-    return (index >= array_length(supported_crypt_types));
+constexpr bool indexOutOfBoundsForCryptoTypes(size_t index) {
+    return (index >= array_length(supported_crypto_types));
+}
+
+constexpr bool isValidCryptoType(const CryptoType &crypto_type) {
+    return ((crypto_type.get_property_name() != nullptr) &&
+            (crypto_type.get_crypto_name() != nullptr) &&
+            (crypto_type.get_keysize() <= MAX_KEY_LEN));
 }
 
 // Note in C++11 that constexpr functions can only have a single line.
 // So our code is a bit convoluted (using recursion instead of a loop),
 // but it's asserting at compile time that all of our key lengths are valid.
-constexpr bool validateSupportedCryptTypes(size_t index) {
-    return indexOutOfBoundsForCryptTypes(index) ||
-        ((supported_crypt_types[index].keysize <= MAX_KEY_LEN) &&
-         validateSupportedCryptTypes(index + 1));
+constexpr bool validateSupportedCryptoTypes(size_t index) {
+    return indexOutOfBoundsForCryptoTypes(index) ||
+        (isValidCryptoType(supported_crypto_types[index]) &&
+         validateSupportedCryptoTypes(index + 1));
 }
 
-static_assert(validateSupportedCryptTypes(0),
-              "We have a CryptType with keysize > MAX_KEYSIZE");
+static_assert(validateSupportedCryptoTypes(0),
+              "We have a CryptoType with keysize > MAX_KEY_LEN or which was "
+              "incompletely constructed.");
 //  ---------- END COMPILE-TIME SANITY CHECK BLOCK -------------------------
 
 
-// Don't call this directly, use get_crypt_type(), which caches this result.
-const CryptType &CryptType::get_device_crypt_name() {
-    constexpr char CRYPT_TYPE_PROP[] = "ro.crypto.crypt_type_name";
+// Don't call this directly, use get_crypto_type(), which caches this result.
+const CryptoType &CryptoType::get_device_crypto_algorithm() {
+    constexpr char CRYPT_ALGO_PROP[] = "ro.crypto.fde_algorithm";
     char paramstr[PROPERTY_VALUE_MAX];
 
-    property_get(CRYPT_TYPE_PROP, paramstr, default_crypt_type.name);
-    for (auto const &ctype : supported_crypt_types) {
-        if (strcmp(paramstr, ctype.name) == 0) {
+    property_get(CRYPT_ALGO_PROP, paramstr,
+                 default_crypto_type.get_property_name());
+    for (auto const &ctype : supported_crypto_types) {
+        if (strcmp(paramstr, ctype.get_property_name()) == 0) {
             return ctype;
         }
     }
     ALOGE("Invalid name (%s) for %s.  Defaulting to %s\n", paramstr,
-          CRYPT_TYPE_PROP, default_crypt_type.name);
-    return default_crypt_type;
+          CRYPT_ALGO_PROP, default_crypto_type.get_property_name());
+    return default_crypto_type;
 }
 
 }  // namespace
 
 
+
 /**
  * Gets the default device scrypt parameters for key derivation time tuning.
  * The parameters should lead to about one second derivation time for the
@@ -366,6 +397,14 @@
     ftr->p_factor = pf;
 }
 
+uint32_t cryptfs_get_keysize() {
+    return get_crypto_type().get_keysize();
+}
+
+const char *cryptfs_get_crypto_name() {
+    return get_crypto_type().get_crypto_name();
+}
+
 static unsigned int get_fs_size(char *dev)
 {
     int fd, block_size;
@@ -669,6 +708,17 @@
     goto errout;
   }
 
+  // We risk buffer overflows with oversized keys, so we just reject them.
+  // 0-sized keys are problematic (essentially by-passing encryption), and
+  // AES-CBC key wrapping only works for multiples of 16 bytes.
+  if ((crypt_ftr->keysize == 0) || ((crypt_ftr->keysize % 16) != 0) ||
+      (crypt_ftr->keysize > MAX_KEY_LEN)) {
+    SLOGE("Invalid keysize (%u) for block device %s; Must be non-zero, "
+          "divisible by 16, and <= %d\n", crypt_ftr->keysize, fname,
+          MAX_KEY_LEN);
+    goto errout;
+  }
+
   if (crypt_ftr->minor_version > CURRENT_MINOR_VERSION) {
     SLOGW("Warning: crypto footer minor version %d, expected <= %d, continuing...\n",
           crypt_ftr->minor_version, CURRENT_MINOR_VERSION);
@@ -938,10 +988,9 @@
   struct dm_ioctl *io;
   struct dm_target_spec *tgt;
   char *crypt_params;
-  // We can't assume the key is only get_keysize().  But we do know its limit
-  // due to the crypt_mnt_ftr struct.  We need two ASCII characters to represent
-  // each byte, and need space for the '\0' terminator.
-  char master_key_ascii[sizeof(crypt_ftr->master_key) * 2 + 1];
+  // We need two ASCII characters to represent each byte, and need space for
+  // the '\0' terminator.
+  char master_key_ascii[MAX_KEY_LEN * 2 + 1];
   size_t buff_offset;
   int i;
 
@@ -1135,7 +1184,7 @@
 
     /* Turn the password into a key and IV that can decrypt the master key */
     return PKCS5_PBKDF2_HMAC_SHA1(passwd, strlen(passwd), salt, SALT_LEN,
-                                  HASH_COUNT, get_keysize() + IV_LEN_BYTES,
+                                  HASH_COUNT, INTERMEDIATE_BUF_SIZE,
                                   ikey) != 1;
 }
 
@@ -1153,7 +1202,7 @@
     /* Turn the password into a key and IV that can decrypt the master key */
     crypto_scrypt((const uint8_t*)passwd, strlen(passwd),
                   salt, SALT_LEN, N, r, p, ikey,
-                  get_keysize() + IV_LEN_BYTES);
+                  INTERMEDIATE_BUF_SIZE);
 
    return 0;
 }
@@ -1174,21 +1223,21 @@
 
     rc = crypto_scrypt((const uint8_t*)passwd, strlen(passwd),
                        salt, SALT_LEN, N, r, p, ikey,
-                       get_keysize() + IV_LEN_BYTES);
+                       INTERMEDIATE_BUF_SIZE);
 
     if (rc) {
         SLOGE("scrypt failed");
         return -1;
     }
 
-    if (keymaster_sign_object(ftr, ikey, get_keysize() + IV_LEN_BYTES,
+    if (keymaster_sign_object(ftr, ikey, INTERMEDIATE_BUF_SIZE,
                               &signature, &signature_size)) {
         SLOGE("Signing failed");
         return -1;
     }
 
     rc = crypto_scrypt(signature, signature_size, salt, SALT_LEN,
-                       N, r, p, ikey, get_keysize() + IV_LEN_BYTES);
+                       N, r, p, ikey, INTERMEDIATE_BUF_SIZE);
     free(signature);
 
     if (rc) {
@@ -1204,7 +1253,7 @@
                               unsigned char *encrypted_master_key,
                               struct crypt_mnt_ftr *crypt_ftr)
 {
-    unsigned char ikey[MAX_KEY_LEN+IV_LEN_BYTES] = { 0 };
+    unsigned char ikey[INTERMEDIATE_BUF_SIZE] = { 0 };
     EVP_CIPHER_CTX e_ctx;
     int encrypted_len, final_len;
     int rc = 0;
@@ -1239,7 +1288,8 @@
 
     /* Initialize the decryption engine */
     EVP_CIPHER_CTX_init(&e_ctx);
-    if (! EVP_EncryptInit_ex(&e_ctx, EVP_aes_128_cbc(), NULL, ikey, ikey+get_keysize())) {
+    if (! EVP_EncryptInit_ex(&e_ctx, EVP_aes_128_cbc(), NULL, ikey,
+                             ikey+INTERMEDIATE_KEY_LEN_BYTES)) {
         SLOGE("EVP_EncryptInit failed\n");
         return -1;
     }
@@ -1247,7 +1297,7 @@
 
     /* Encrypt the master key */
     if (! EVP_EncryptUpdate(&e_ctx, encrypted_master_key, &encrypted_len,
-                            decrypted_master_key, get_keysize())) {
+                            decrypted_master_key, crypt_ftr->keysize)) {
         SLOGE("EVP_EncryptUpdate failed\n");
         return -1;
     }
@@ -1256,7 +1306,7 @@
         return -1;
     }
 
-    if (encrypted_len + final_len != static_cast<int>(get_keysize())) {
+    if (encrypted_len + final_len != static_cast<int>(crypt_ftr->keysize)) {
         SLOGE("EVP_Encryption length check failed with %d, %d bytes\n", encrypted_len, final_len);
         return -1;
     }
@@ -1270,7 +1320,7 @@
     int r = 1 << crypt_ftr->r_factor;
     int p = 1 << crypt_ftr->p_factor;
 
-    rc = crypto_scrypt(ikey, get_keysize(),
+    rc = crypto_scrypt(ikey, INTERMEDIATE_KEY_LEN_BYTES,
                        crypt_ftr->salt, sizeof(crypt_ftr->salt), N, r, p,
                        crypt_ftr->scrypted_intermediate_key,
                        sizeof(crypt_ftr->scrypted_intermediate_key));
@@ -1285,13 +1335,14 @@
 }
 
 static int decrypt_master_key_aux(const char *passwd, unsigned char *salt,
-                                  unsigned char *encrypted_master_key,
+                                  const unsigned char *encrypted_master_key,
+                                  size_t keysize,
                                   unsigned char *decrypted_master_key,
                                   kdf_func kdf, void *kdf_params,
                                   unsigned char** intermediate_key,
                                   size_t* intermediate_key_size)
 {
-  unsigned char ikey[MAX_KEY_LEN+IV_LEN_BYTES] = { 0 };
+  unsigned char ikey[INTERMEDIATE_BUF_SIZE] = { 0 };
   EVP_CIPHER_CTX d_ctx;
   int decrypted_len, final_len;
 
@@ -1304,29 +1355,29 @@
 
   /* Initialize the decryption engine */
   EVP_CIPHER_CTX_init(&d_ctx);
-  if (! EVP_DecryptInit_ex(&d_ctx, EVP_aes_128_cbc(), NULL, ikey, ikey+get_keysize())) {
+  if (! EVP_DecryptInit_ex(&d_ctx, EVP_aes_128_cbc(), NULL, ikey, ikey+INTERMEDIATE_KEY_LEN_BYTES)) {
     return -1;
   }
   EVP_CIPHER_CTX_set_padding(&d_ctx, 0); /* Turn off padding as our data is block aligned */
   /* Decrypt the master key */
   if (! EVP_DecryptUpdate(&d_ctx, decrypted_master_key, &decrypted_len,
-                            encrypted_master_key, get_keysize())) {
+                            encrypted_master_key, keysize)) {
     return -1;
   }
   if (! EVP_DecryptFinal_ex(&d_ctx, decrypted_master_key + decrypted_len, &final_len)) {
     return -1;
   }
 
-  if (decrypted_len + final_len != static_cast<int>(get_keysize())) {
+  if (decrypted_len + final_len != static_cast<int>(keysize)) {
     return -1;
   }
 
   /* Copy intermediate key if needed by params */
   if (intermediate_key && intermediate_key_size) {
-    *intermediate_key = (unsigned char*) malloc(get_keysize());
+    *intermediate_key = (unsigned char*) malloc(INTERMEDIATE_KEY_LEN_BYTES);
     if (*intermediate_key) {
-      memcpy(*intermediate_key, ikey, get_keysize());
-      *intermediate_key_size = get_keysize();
+      memcpy(*intermediate_key, ikey, INTERMEDIATE_KEY_LEN_BYTES);
+      *intermediate_key_size = INTERMEDIATE_KEY_LEN_BYTES;
     }
   }
 
@@ -1360,6 +1411,7 @@
 
     get_kdf_func(crypt_ftr, &kdf, &kdf_params);
     ret = decrypt_master_key_aux(passwd, crypt_ftr->salt, crypt_ftr->master_key,
+                                 crypt_ftr->keysize,
                                  decrypted_master_key, kdf, kdf_params,
                                  intermediate_key, intermediate_key_size);
     if (ret != 0) {
@@ -1687,7 +1739,7 @@
 static int test_mount_encrypted_fs(struct crypt_mnt_ftr* crypt_ftr,
                                    const char *passwd, const char *mount_point, const char *label)
 {
-  unsigned char decrypted_master_key[DECRYPTED_MASTER_KEY_BUF_SIZE];
+  unsigned char decrypted_master_key[MAX_KEY_LEN];
   char crypto_blkdev[MAXPATHLEN];
   char real_blkdev[MAXPATHLEN];
   char tmp_mount_point[64];
@@ -1770,7 +1822,7 @@
 
     /* Also save a the master key so we can reencrypted the key
      * the key when we want to change the password on it. */
-    memcpy(saved_master_key, decrypted_master_key, get_keysize());
+    memcpy(saved_master_key, decrypted_master_key, crypt_ftr->keysize);
     saved_mount_point = strdup(mount_point);
     master_key_saved = 1;
     SLOGD("%s(): Master key saved\n", __FUNCTION__);
@@ -1820,12 +1872,13 @@
 /*
  * Called by vold when it's asked to mount an encrypted external
  * storage volume. The incoming partition has no crypto header/footer,
- * as any metadata is been stored in a separate, small partition.
+ * as any metadata is been stored in a separate, small partition.  We
+ * assume it must be using our same crypt type and keysize.
  *
  * out_crypto_blkdev must be MAXPATHLEN.
  */
 int cryptfs_setup_ext_volume(const char* label, const char* real_blkdev,
-        const unsigned char* key, int keysize, char* out_crypto_blkdev) {
+        const unsigned char* key, char* out_crypto_blkdev) {
     int fd = open(real_blkdev, O_RDONLY|O_CLOEXEC);
     if (fd == -1) {
         SLOGE("Failed to open %s: %s", real_blkdev, strerror(errno));
@@ -1844,8 +1897,8 @@
     struct crypt_mnt_ftr ext_crypt_ftr;
     memset(&ext_crypt_ftr, 0, sizeof(ext_crypt_ftr));
     ext_crypt_ftr.fs_size = nr_sec;
-    ext_crypt_ftr.keysize = keysize;
-    strlcpy((char*) ext_crypt_ftr.crypto_type_name, get_crypt_name(),
+    ext_crypt_ftr.keysize = cryptfs_get_keysize();
+    strlcpy((char*) ext_crypt_ftr.crypto_type_name, cryptfs_get_crypto_name(),
             MAX_CRYPTO_TYPE_NAME_LEN);
 
     return create_crypto_blk_dev(
@@ -1944,7 +1997,7 @@
 int cryptfs_verify_passwd(const char *passwd)
 {
     struct crypt_mnt_ftr crypt_ftr;
-    unsigned char decrypted_master_key[DECRYPTED_MASTER_KEY_BUF_SIZE];
+    unsigned char decrypted_master_key[MAX_KEY_LEN];
     char encrypted_state[PROPERTY_VALUE_MAX];
     int rc;
 
@@ -1988,7 +2041,7 @@
 }
 
 /* Initialize a crypt_mnt_ftr structure.  The keysize is
- * defaulted to get_keysize(), and the filesystem size to 0.
+ * defaulted to cryptfs_get_keysize() bytes, and the filesystem size to 0.
  * Presumably, at a minimum, the caller will update the
  * filesystem size and crypto_type_name after calling this function.
  */
@@ -2001,7 +2054,7 @@
     ftr->major_version = CURRENT_MAJOR_VERSION;
     ftr->minor_version = CURRENT_MINOR_VERSION;
     ftr->ftr_size = sizeof(struct crypt_mnt_ftr);
-    ftr->keysize = get_keysize();
+    ftr->keysize = cryptfs_get_keysize();
 
     switch (keymaster_check_compatibility()) {
     case 1:
@@ -2094,7 +2147,7 @@
 
 int cryptfs_enable_internal(int crypt_type, const char* passwd, int no_ui) {
     char crypto_blkdev[MAXPATHLEN], real_blkdev[MAXPATHLEN];
-    unsigned char decrypted_master_key[DECRYPTED_MASTER_KEY_BUF_SIZE];
+    unsigned char decrypted_master_key[MAX_KEY_LEN];
     int rc=-1, i;
     struct crypt_mnt_ftr crypt_ftr;
     struct crypt_persist_data *pdata;
@@ -2133,6 +2186,9 @@
             crypt_ftr.flags |= CRYPT_FORCE_COMPLETE;
             rebootEncryption = true;
         }
+    } else {
+        // We don't want to accidentally reference invalid data.
+        memset(&crypt_ftr, 0, sizeof(crypt_ftr));
     }
 
     property_get("ro.crypto.state", encrypted_state, "");
@@ -2253,7 +2309,7 @@
             crypt_ftr.flags |= CRYPT_INCONSISTENT_STATE;
         }
         crypt_ftr.crypt_type = crypt_type;
-        strlcpy((char *)crypt_ftr.crypto_type_name, get_crypt_name(), MAX_CRYPTO_TYPE_NAME_LEN);
+        strlcpy((char *)crypt_ftr.crypto_type_name, cryptfs_get_crypto_name(), MAX_CRYPTO_TYPE_NAME_LEN);
 
         /* Make an encrypted master key */
         if (create_encrypted_random_key(onlyCreateHeader ? DEFAULT_PASSWORD : passwd,
diff --git a/cryptfs.h b/cryptfs.h
index bf4b405..d6c7dc5 100644
--- a/cryptfs.h
+++ b/cryptfs.h
@@ -30,6 +30,7 @@
  */
 
 #include <stdbool.h>
+#include <stdint.h>
 #include <cutils/properties.h>
 
 /* The current cryptfs version */
@@ -235,7 +236,7 @@
 int cryptfs_changepw(int type, const char* newpw);
 int cryptfs_enable_default(int no_ui);
 int cryptfs_setup_ext_volume(const char* label, const char* real_blkdev, const unsigned char* key,
-                             int keysize, char* out_crypto_blkdev);
+                             char* out_crypto_blkdev);
 int cryptfs_revert_ext_volume(const char* label);
 int cryptfs_getfield(const char* fieldname, char* value, int len);
 int cryptfs_setfield(const char* fieldname, const char* value);
@@ -245,4 +246,7 @@
 void cryptfs_clear_password(void);
 int cryptfs_isConvertibleToFBE(void);
 
+uint32_t cryptfs_get_keysize();
+const char* cryptfs_get_crypto_name();
+
 #endif /* ANDROID_VOLD_CRYPTFS_H */
diff --git a/model/Disk.cpp b/model/Disk.cpp
index becf8b7..9fcf5e1 100644
--- a/model/Disk.cpp
+++ b/model/Disk.cpp
@@ -30,6 +30,8 @@
 #include <android-base/parseint.h>
 #include <ext4_utils/ext4_crypt.h>
 
+#include "cryptfs.h"
+
 #include <vector>
 #include <fcntl.h>
 #include <inttypes.h>
@@ -480,7 +482,7 @@
     }
 
     std::string keyRaw;
-    if (ReadRandomBytes(16, keyRaw) != OK) {
+    if (ReadRandomBytes(cryptfs_get_keysize(), keyRaw) != OK) {
         LOG(ERROR) << "Failed to generate key";
         return -EIO;
     }
diff --git a/model/EmulatedVolume.cpp b/model/EmulatedVolume.cpp
index 7f5c4ff..31c3924 100644
--- a/model/EmulatedVolume.cpp
+++ b/model/EmulatedVolume.cpp
@@ -114,7 +114,8 @@
         }
     }
     /* sdcardfs will have exited already. FUSE will still be running */
-    TEMP_FAILURE_RETRY(waitpid(mFusePid, nullptr, WNOHANG));
+    if (TEMP_FAILURE_RETRY(waitpid(mFusePid, nullptr, WNOHANG)) == mFusePid)
+        mFusePid = 0;
 
     return OK;
 }
diff --git a/model/PrivateVolume.cpp b/model/PrivateVolume.cpp
index 48d041b..cf21577 100644
--- a/model/PrivateVolume.cpp
+++ b/model/PrivateVolume.cpp
@@ -65,6 +65,11 @@
     if (CreateDeviceNode(mRawDevPath, mRawDevice)) {
         return -EIO;
     }
+    if (mKeyRaw.size() != cryptfs_get_keysize()) {
+      PLOG(ERROR) << getId() << " Raw keysize " << mKeyRaw.size() <<
+          " does not match crypt keysize " << cryptfs_get_keysize();
+      return -EIO;
+    }
 
     // Recover from stale vold by tearing down any old mappings
     cryptfs_revert_ext_volume(getId().c_str());
@@ -74,7 +79,7 @@
     unsigned char* key = (unsigned char*) mKeyRaw.data();
     char crypto_blkdev[MAXPATHLEN];
     int res = cryptfs_setup_ext_volume(getId().c_str(), mRawDevPath.c_str(),
-            key, mKeyRaw.size(), crypto_blkdev);
+            key, crypto_blkdev);
     mDmDevPath = crypto_blkdev;
     if (res != 0) {
         PLOG(ERROR) << getId() << " failed to setup cryptfs";
diff --git a/model/PublicVolume.cpp b/model/PublicVolume.cpp
index efdb687..fc7e96f 100644
--- a/model/PublicVolume.cpp
+++ b/model/PublicVolume.cpp
@@ -211,7 +211,8 @@
         }
     }
     /* sdcardfs will have exited already. FUSE will still be running */
-    TEMP_FAILURE_RETRY(waitpid(mFusePid, nullptr, WNOHANG));
+    if (TEMP_FAILURE_RETRY(waitpid(mFusePid, nullptr, WNOHANG)) == mFusePid)
+        mFusePid = 0;
 
     return OK;
 }