OSDN Git Service

libfscrypt: Infer flags at parse time and include in options struct
authorPaul Crowley <paulcrowley@google.com>
Fri, 25 Oct 2019 17:28:53 +0000 (10:28 -0700)
committerPaul Crowley <paulcrowley@google.com>
Mon, 28 Oct 2019 22:26:56 +0000 (15:26 -0700)
Bug: 143307095
Test: cuttlefish, policy=v1 -> flags=0, policy=v2 -> flags=2
Change-Id: I28f35a1e0ee474d07e2e2b591c84e9057ecb6acf

libfscrypt/fscrypt.cpp
libfscrypt/include/fscrypt/fscrypt.h
libfscrypt/tests/fscrypt_test.cpp

index b73f1bc..33c8249 100644 (file)
@@ -150,31 +150,6 @@ void BytesToHex(const std::string& bytes, std::string* hex) {
     }
 }
 
-static uint8_t fscrypt_get_policy_flags(const EncryptionOptions& options) {
-    uint8_t flags = 0;
-
-    // In the original setting of v1 policies and AES-256-CTS we used 4-byte
-    // padding of filenames, so we have to retain that for compatibility.
-    //
-    // For everything else, use 16-byte padding.  This is more secure (it helps
-    // hide the length of filenames), and it makes the inputs evenly divisible
-    // into cipher blocks which is more efficient for encryption and decryption.
-    if (options.version == 1 && options.filenames_mode == FS_ENCRYPTION_MODE_AES_256_CTS) {
-        flags |= FS_POLICY_FLAGS_PAD_4;
-    } else {
-        flags |= FS_POLICY_FLAGS_PAD_16;
-    }
-
-    // Use DIRECT_KEY for Adiantum, since it's much more efficient but just as
-    // secure since Android doesn't reuse the same master key for multiple
-    // encryption modes.
-    if (options.filenames_mode == FS_ENCRYPTION_MODE_ADIANTUM) {
-        flags |= FS_POLICY_FLAG_DIRECT_KEY;
-    }
-
-    return flags;
-}
-
 static bool fscrypt_is_encrypted(int fd) {
     fscrypt_policy_v1 policy;
 
@@ -238,6 +213,26 @@ bool ParseOptions(const std::string& options_string, EncryptionOptions* options)
     } else {
         options->version = 1;
     }
+    options->flags = 0;
+
+    // In the original setting of v1 policies and AES-256-CTS we used 4-byte
+    // padding of filenames, so we have to retain that for compatibility.
+    //
+    // For everything else, use 16-byte padding.  This is more secure (it helps
+    // hide the length of filenames), and it makes the inputs evenly divisible
+    // into cipher blocks which is more efficient for encryption and decryption.
+    if (options->version == 1 && options->filenames_mode == FS_ENCRYPTION_MODE_AES_256_CTS) {
+        options->flags |= FS_POLICY_FLAGS_PAD_4;
+    } else {
+        options->flags |= FS_POLICY_FLAGS_PAD_16;
+    }
+
+    // Use DIRECT_KEY for Adiantum, since it's much more efficient but just as
+    // secure since Android doesn't reuse the same master key for multiple
+    // encryption modes.
+    if (options->filenames_mode == FS_ENCRYPTION_MODE_ADIANTUM) {
+        options->flags |= FS_POLICY_FLAG_DIRECT_KEY;
+    }
     return true;
 }
 
@@ -248,6 +243,7 @@ static std::string PolicyDebugString(const EncryptionPolicy& policy) {
     ss << ref_hex;
     ss << " v" << policy.options.version;
     ss << " modes " << policy.options.contents_mode << "/" << policy.options.filenames_mode;
+    ss << std::hex << " flags 0x" << policy.options.flags;
     return ss.str();
 }
 
@@ -270,7 +266,7 @@ bool EnsurePolicy(const EncryptionPolicy& policy, const std::string& directory)
             kern_policy.v1.version = FSCRYPT_POLICY_V1;
             kern_policy.v1.contents_encryption_mode = policy.options.contents_mode;
             kern_policy.v1.filenames_encryption_mode = policy.options.filenames_mode;
-            kern_policy.v1.flags = fscrypt_get_policy_flags(policy.options);
+            kern_policy.v1.flags = policy.options.flags;
             policy.key_raw_ref.copy(reinterpret_cast<char*>(kern_policy.v1.master_key_descriptor),
                                     FSCRYPT_KEY_DESCRIPTOR_SIZE);
             break;
@@ -283,7 +279,7 @@ bool EnsurePolicy(const EncryptionPolicy& policy, const std::string& directory)
             kern_policy.v2.version = FSCRYPT_POLICY_V2;
             kern_policy.v2.contents_encryption_mode = policy.options.contents_mode;
             kern_policy.v2.filenames_encryption_mode = policy.options.filenames_mode;
-            kern_policy.v2.flags = fscrypt_get_policy_flags(policy.options);
+            kern_policy.v2.flags = policy.options.flags;
             policy.key_raw_ref.copy(reinterpret_cast<char*>(kern_policy.v2.master_key_identifier),
                                     FSCRYPT_KEY_IDENTIFIER_SIZE);
             break;
index 47fedb5..ca051f4 100644 (file)
@@ -33,7 +33,9 @@ struct EncryptionOptions {
     int version;
     int contents_mode;
     int filenames_mode;
+    int flags;
 
+    // Ensure that "version" is not valid on creation and so must be explicitly set
     EncryptionOptions() : version(0) {}
 };
 
index 13a37b7..48d092d 100644 (file)
@@ -37,6 +37,7 @@ TEST(fscrypt, ParseOptions) {
     EXPECT_EQ(1, options.version);
     EXPECT_EQ(FS_ENCRYPTION_MODE_AES_256_XTS, options.contents_mode);
     EXPECT_EQ(FS_ENCRYPTION_MODE_AES_256_CTS, options.filenames_mode);
+    EXPECT_EQ(FS_POLICY_FLAGS_PAD_4, options.flags);
     EXPECT_TRUE(OptionsToString(options, &options_string));
     EXPECT_EQ("aes-256-xts:aes-256-cts:v1", options_string);
 
@@ -44,6 +45,7 @@ TEST(fscrypt, ParseOptions) {
     EXPECT_EQ(1, options.version);
     EXPECT_EQ(FS_ENCRYPTION_MODE_AES_256_XTS, options.contents_mode);
     EXPECT_EQ(FS_ENCRYPTION_MODE_AES_256_CTS, options.filenames_mode);
+    EXPECT_EQ(FS_POLICY_FLAGS_PAD_4, options.flags);
     EXPECT_TRUE(OptionsToString(options, &options_string));
     EXPECT_EQ("aes-256-xts:aes-256-cts:v1", options_string);
 
@@ -51,6 +53,7 @@ TEST(fscrypt, ParseOptions) {
     EXPECT_EQ(1, options.version);
     EXPECT_EQ(FS_ENCRYPTION_MODE_ADIANTUM, options.contents_mode);
     EXPECT_EQ(FS_ENCRYPTION_MODE_ADIANTUM, options.filenames_mode);
+    EXPECT_EQ(FS_POLICY_FLAGS_PAD_16 | FS_POLICY_FLAG_DIRECT_KEY, options.flags);
     EXPECT_TRUE(OptionsToString(options, &options_string));
     EXPECT_EQ("adiantum:adiantum:v1", options_string);
 
@@ -58,6 +61,7 @@ TEST(fscrypt, ParseOptions) {
     EXPECT_EQ(1, options.version);
     EXPECT_EQ(FS_ENCRYPTION_MODE_ADIANTUM, options.contents_mode);
     EXPECT_EQ(FS_ENCRYPTION_MODE_AES_256_HEH, options.filenames_mode);
+    EXPECT_EQ(FS_POLICY_FLAGS_PAD_16, options.flags);
     EXPECT_TRUE(OptionsToString(options, &options_string));
     EXPECT_EQ("adiantum:aes-256-heh:v1", options_string);
 
@@ -65,6 +69,7 @@ TEST(fscrypt, ParseOptions) {
     EXPECT_EQ(1, options.version);
     EXPECT_EQ(FS_ENCRYPTION_MODE_PRIVATE, options.contents_mode);
     EXPECT_EQ(FS_ENCRYPTION_MODE_AES_256_CTS, options.filenames_mode);
+    EXPECT_EQ(FS_POLICY_FLAGS_PAD_4, options.flags);
     EXPECT_TRUE(OptionsToString(options, &options_string));
     EXPECT_EQ("ice:aes-256-cts:v1", options_string);
 
@@ -74,6 +79,7 @@ TEST(fscrypt, ParseOptions) {
     EXPECT_EQ(1, options.version);
     EXPECT_EQ(FS_ENCRYPTION_MODE_PRIVATE, options.contents_mode);
     EXPECT_EQ(FS_ENCRYPTION_MODE_AES_256_CTS, options.filenames_mode);
+    EXPECT_EQ(FS_POLICY_FLAGS_PAD_4, options.flags);
     EXPECT_TRUE(OptionsToString(options, &options_string));
     EXPECT_EQ("ice:aes-256-cts:v1", options_string);
 
@@ -81,6 +87,7 @@ TEST(fscrypt, ParseOptions) {
     EXPECT_EQ(1, options.version);
     EXPECT_EQ(FS_ENCRYPTION_MODE_PRIVATE, options.contents_mode);
     EXPECT_EQ(FS_ENCRYPTION_MODE_AES_256_HEH, options.filenames_mode);
+    EXPECT_EQ(FS_POLICY_FLAGS_PAD_16, options.flags);
     EXPECT_TRUE(OptionsToString(options, &options_string));
     EXPECT_EQ("ice:aes-256-heh:v1", options_string);
 
@@ -88,6 +95,7 @@ TEST(fscrypt, ParseOptions) {
     EXPECT_EQ(1, options.version);
     EXPECT_EQ(FS_ENCRYPTION_MODE_PRIVATE, options.contents_mode);
     EXPECT_EQ(FS_ENCRYPTION_MODE_ADIANTUM, options.filenames_mode);
+    EXPECT_EQ(FS_POLICY_FLAGS_PAD_16 | FS_POLICY_FLAG_DIRECT_KEY, options.flags);
     EXPECT_TRUE(OptionsToString(options, &options_string));
     EXPECT_EQ("ice:adiantum:v1", options_string);
 
@@ -95,6 +103,7 @@ TEST(fscrypt, ParseOptions) {
     EXPECT_EQ(1, options.version);
     EXPECT_EQ(FS_ENCRYPTION_MODE_AES_256_XTS, options.contents_mode);
     EXPECT_EQ(FS_ENCRYPTION_MODE_AES_256_CTS, options.filenames_mode);
+    EXPECT_EQ(FS_POLICY_FLAGS_PAD_4, options.flags);
     EXPECT_TRUE(OptionsToString(options, &options_string));
     EXPECT_EQ("aes-256-xts:aes-256-cts:v1", options_string);
 
@@ -102,6 +111,7 @@ TEST(fscrypt, ParseOptions) {
     EXPECT_EQ(1, options.version);
     EXPECT_EQ(FS_ENCRYPTION_MODE_AES_256_XTS, options.contents_mode);
     EXPECT_EQ(FS_ENCRYPTION_MODE_AES_256_CTS, options.filenames_mode);
+    EXPECT_EQ(FS_POLICY_FLAGS_PAD_4, options.flags);
     EXPECT_TRUE(OptionsToString(options, &options_string));
     EXPECT_EQ("aes-256-xts:aes-256-cts:v1", options_string);
 
@@ -109,6 +119,7 @@ TEST(fscrypt, ParseOptions) {
     EXPECT_EQ(2, options.version);
     EXPECT_EQ(FS_ENCRYPTION_MODE_AES_256_XTS, options.contents_mode);
     EXPECT_EQ(FS_ENCRYPTION_MODE_AES_256_CTS, options.filenames_mode);
+    EXPECT_EQ(FS_POLICY_FLAGS_PAD_16, options.flags);
     EXPECT_TRUE(OptionsToString(options, &options_string));
     EXPECT_EQ("aes-256-xts:aes-256-cts:v2", options_string);