fscrypt-crypt-util: fix maximum IV size
authorEric Biggers <ebiggers@google.com>
Sun, 15 Nov 2020 03:15:36 +0000 (19:15 -0800)
committerEryu Guan <guaneryu@gmail.com>
Sun, 15 Nov 2020 06:53:06 +0000 (14:53 +0800)
In commit 65cd8e8a8e81 ("fscrypt-crypt-util: fix IV incrementing for
--iv-ino-lblk-32") I mistakenly decreased the size of fscrypt_iv to 24
bytes, which is the most that is explicitly needed by any of the IV
generation methods.  However, Adiantum encryption takes a 32-byte IV, so
the buffer still needs to be 32 bytes, with any extra bytes zeroed.

So restore the size to 32 bytes.

This fixes a buffer overread that caused generic/550 and generic/584 to
sometimes fail, depending on the build of the fscrypt-crypt-util binary.
(Most of the time it still worked by chance.)

Fixes: 65cd8e8a8e81 ("fscrypt-crypt-util: fix IV incrementing for --iv-ino-lblk-32")
Signed-off-by: Eric Biggers <ebiggers@google.com>
Signed-off-by: Eryu Guan <guaneryu@gmail.com>
src/fscrypt-crypt-util.c

index 26698d7a30e7fe9c26650410b8423555c9c80e0f..03cc3c4a12997734195a455c1bfd2ba249525c5c 100644 (file)
@@ -1642,6 +1642,7 @@ static u64 siphash_1u64(const u64 key[2], u64 data)
 #define FILE_NONCE_SIZE                16
 #define UUID_SIZE              16
 #define MAX_KEY_SIZE           64
+#define MAX_IV_SIZE            ADIANTUM_IV_SIZE
 
 static const struct fscrypt_cipher {
        const char *name;
@@ -1715,6 +1716,8 @@ union fscrypt_iv {
                /* IV_INO_LBLK_64: inode number */
                __le32 inode_number;
        };
+       /* Any extra bytes up to the algorithm's IV size must be zeroed */
+       u8 bytes[MAX_IV_SIZE];
 };
 
 static void crypt_loop(const struct fscrypt_cipher *cipher, const u8 *key,
@@ -1736,9 +1739,9 @@ static void crypt_loop(const struct fscrypt_cipher *cipher, const u8 *key,
                memset(&buf[res], 0, crypt_len - res);
 
                if (decrypting)
-                       cipher->decrypt(key, (u8 *)iv, buf, buf, crypt_len);
+                       cipher->decrypt(key, iv->bytes, buf, buf, crypt_len);
                else
-                       cipher->encrypt(key, (u8 *)iv, buf, buf, crypt_len);
+                       cipher->encrypt(key, iv->bytes, buf, buf, crypt_len);
 
                full_write(STDOUT_FILENO, buf, crypt_len);