fs_mgr_fstab: support specifying encryption policy version in fstab

Allow the encryption policy version to be specified as a third field in
the "fileencryption=" fstab option, and expose it through the fstab
record so that vold can use it.

Bug: 140500999
Test: tested as series; see If64028d8580584b2c33c614cabd5d6b93657f608.
      Also updated and ran the fs_mgr unit tests.
Change-Id: If5d56f4c84c4cd51e3f14c0a861c3e3ab6ff903f
diff --git a/fs_mgr/fs_mgr_fstab.cpp b/fs_mgr/fs_mgr_fstab.cpp
index e50f7c3..c1a8dae 100644
--- a/fs_mgr/fs_mgr_fstab.cpp
+++ b/fs_mgr/fs_mgr_fstab.cpp
@@ -112,13 +112,16 @@
 };
 
 void ParseFileEncryption(const std::string& arg, FstabEntry* entry) {
-    // The fileencryption flag is followed by an = and the mode of contents encryption, then
-    // optionally a and the mode of filenames encryption (defaults to aes-256-cts).  Get it and
-    // return it.
+    // The fileencryption flag is followed by an = and 1 to 3 colon-separated fields:
+    //
+    // 1. Contents encryption mode
+    // 2. Filenames encryption mode (defaults to "aes-256-cts" or "adiantum"
+    //    depending on the contents encryption mode)
+    // 3. Encryption policy version (defaults to "v1". Use "v2" on new devices.)
     entry->fs_mgr_flags.file_encryption = true;
 
     auto parts = Split(arg, ":");
-    if (parts.empty() || parts.size() > 2) {
+    if (parts.empty() || parts.size() > 3) {
         LWARNING << "Warning: fileencryption= flag malformed: " << arg;
         return;
     }
@@ -137,7 +140,7 @@
 
     entry->file_contents_mode = parts[0];
 
-    if (parts.size() == 2) {
+    if (parts.size() >= 2) {
         if (std::find(kFileNamesEncryptionMode.begin(), kFileNamesEncryptionMode.end(), parts[1]) ==
             kFileNamesEncryptionMode.end()) {
             LWARNING << "fileencryption= flag malformed, file names encryption mode not found: "
@@ -151,6 +154,16 @@
     } else {
         entry->file_names_mode = "aes-256-cts";
     }
+
+    if (parts.size() >= 3) {
+        if (!android::base::StartsWith(parts[2], 'v') ||
+            !android::base::ParseInt(&parts[2][1], &entry->file_policy_version)) {
+            LWARNING << "fileencryption= flag malformed, unknown options: " << arg;
+            return;
+        }
+    } else {
+        entry->file_policy_version = 1;
+    }
 }
 
 bool SetMountFlag(const std::string& flag, FstabEntry* entry) {
@@ -288,6 +301,7 @@
             entry->key_loc = arg;
             entry->file_contents_mode = "aes-256-xts";
             entry->file_names_mode = "aes-256-cts";
+            entry->file_policy_version = 1;
         } else if (StartsWith(flag, "max_comp_streams=")) {
             if (!ParseInt(arg, &entry->max_comp_streams)) {
                 LWARNING << "Warning: max_comp_streams= flag malformed: " << arg;
diff --git a/fs_mgr/include_fstab/fstab/fstab.h b/fs_mgr/include_fstab/fstab/fstab.h
index d999ae1..3c517dc 100644
--- a/fs_mgr/include_fstab/fstab/fstab.h
+++ b/fs_mgr/include_fstab/fstab/fstab.h
@@ -47,6 +47,7 @@
     off64_t reserved_size = 0;
     std::string file_contents_mode;
     std::string file_names_mode;
+    int file_policy_version = 0;
     off64_t erase_blk_size = 0;
     off64_t logical_blk_size = 0;
     std::string sysfs_path;
diff --git a/fs_mgr/tests/fs_mgr_test.cpp b/fs_mgr/tests/fs_mgr_test.cpp
index 6d87594..a7ea817 100644
--- a/fs_mgr/tests/fs_mgr_test.cpp
+++ b/fs_mgr/tests/fs_mgr_test.cpp
@@ -467,6 +467,7 @@
     }
     EXPECT_EQ("aes-256-xts", entry->file_contents_mode);
     EXPECT_EQ("aes-256-cts", entry->file_names_mode);
+    EXPECT_EQ(1, entry->file_policy_version);
     EXPECT_EQ("", entry->key_loc);
 }
 
@@ -682,6 +683,7 @@
     EXPECT_EQ("/dir/key", entry->key_loc);
     EXPECT_EQ("aes-256-xts", entry->file_contents_mode);
     EXPECT_EQ("aes-256-cts", entry->file_names_mode);
+    EXPECT_EQ(1, entry->file_policy_version);
 }
 
 TEST(fs_mgr, ReadFstabFromFile_FsMgrOptions_FileEncryption) {
@@ -698,14 +700,18 @@
 source none7       swap   defaults      fileencryption=ice:aes-256-cts
 source none8       swap   defaults      fileencryption=ice:aes-256-heh
 source none9       swap   defaults      fileencryption=ice:adiantum
-source none10      swap   defaults      fileencryption=ice:adiantum:
+source none10      swap   defaults      fileencryption=aes-256-xts:aes-256-cts:v1
+source none11      swap   defaults      fileencryption=aes-256-xts:aes-256-cts:v2
+source none12      swap   defaults      fileencryption=aes-256-xts:aes-256-cts:v2:
+source none13      swap   defaults      fileencryption=aes-256-xts:aes-256-cts:blah
+source none14      swap   defaults      fileencryption=aes-256-xts:aes-256-cts:vblah
 )fs";
 
     ASSERT_TRUE(android::base::WriteStringToFile(fstab_contents, tf.path));
 
     Fstab fstab;
     EXPECT_TRUE(ReadFstabFromFile(tf.path, &fstab));
-    ASSERT_EQ(11U, fstab.size());
+    ASSERT_EQ(15U, fstab.size());
 
     FstabEntry::FsMgrFlags flags = {};
     flags.file_encryption = true;
@@ -715,66 +721,105 @@
     EXPECT_TRUE(CompareFlags(flags, entry->fs_mgr_flags));
     EXPECT_EQ("", entry->file_contents_mode);
     EXPECT_EQ("", entry->file_names_mode);
+    EXPECT_EQ(0, entry->file_policy_version);
 
     entry++;
     EXPECT_EQ("none1", entry->mount_point);
     EXPECT_TRUE(CompareFlags(flags, entry->fs_mgr_flags));
     EXPECT_EQ("aes-256-xts", entry->file_contents_mode);
     EXPECT_EQ("aes-256-cts", entry->file_names_mode);
+    EXPECT_EQ(1, entry->file_policy_version);
 
     entry++;
     EXPECT_EQ("none2", entry->mount_point);
     EXPECT_TRUE(CompareFlags(flags, entry->fs_mgr_flags));
     EXPECT_EQ("aes-256-xts", entry->file_contents_mode);
     EXPECT_EQ("aes-256-cts", entry->file_names_mode);
+    EXPECT_EQ(1, entry->file_policy_version);
 
     entry++;
     EXPECT_EQ("none3", entry->mount_point);
     EXPECT_TRUE(CompareFlags(flags, entry->fs_mgr_flags));
     EXPECT_EQ("adiantum", entry->file_contents_mode);
     EXPECT_EQ("adiantum", entry->file_names_mode);
+    EXPECT_EQ(1, entry->file_policy_version);
 
     entry++;
     EXPECT_EQ("none4", entry->mount_point);
     EXPECT_TRUE(CompareFlags(flags, entry->fs_mgr_flags));
     EXPECT_EQ("adiantum", entry->file_contents_mode);
     EXPECT_EQ("aes-256-heh", entry->file_names_mode);
+    EXPECT_EQ(1, entry->file_policy_version);
 
     entry++;
     EXPECT_EQ("none5", entry->mount_point);
     EXPECT_TRUE(CompareFlags(flags, entry->fs_mgr_flags));
     EXPECT_EQ("ice", entry->file_contents_mode);
     EXPECT_EQ("aes-256-cts", entry->file_names_mode);
+    EXPECT_EQ(1, entry->file_policy_version);
 
     entry++;
     EXPECT_EQ("none6", entry->mount_point);
     EXPECT_TRUE(CompareFlags(flags, entry->fs_mgr_flags));
     EXPECT_EQ("ice", entry->file_contents_mode);
     EXPECT_EQ("", entry->file_names_mode);
+    EXPECT_EQ(0, entry->file_policy_version);
 
     entry++;
     EXPECT_EQ("none7", entry->mount_point);
     EXPECT_TRUE(CompareFlags(flags, entry->fs_mgr_flags));
     EXPECT_EQ("ice", entry->file_contents_mode);
     EXPECT_EQ("aes-256-cts", entry->file_names_mode);
+    EXPECT_EQ(1, entry->file_policy_version);
 
     entry++;
     EXPECT_EQ("none8", entry->mount_point);
     EXPECT_TRUE(CompareFlags(flags, entry->fs_mgr_flags));
     EXPECT_EQ("ice", entry->file_contents_mode);
     EXPECT_EQ("aes-256-heh", entry->file_names_mode);
+    EXPECT_EQ(1, entry->file_policy_version);
 
     entry++;
     EXPECT_EQ("none9", entry->mount_point);
     EXPECT_TRUE(CompareFlags(flags, entry->fs_mgr_flags));
     EXPECT_EQ("ice", entry->file_contents_mode);
     EXPECT_EQ("adiantum", entry->file_names_mode);
+    EXPECT_EQ(1, entry->file_policy_version);
 
     entry++;
     EXPECT_EQ("none10", entry->mount_point);
     EXPECT_TRUE(CompareFlags(flags, entry->fs_mgr_flags));
+    EXPECT_EQ("aes-256-xts", entry->file_contents_mode);
+    EXPECT_EQ("aes-256-cts", entry->file_names_mode);
+    EXPECT_EQ(1, entry->file_policy_version);
+
+    entry++;
+    EXPECT_EQ("none11", entry->mount_point);
+    EXPECT_TRUE(CompareFlags(flags, entry->fs_mgr_flags));
+    EXPECT_EQ("aes-256-xts", entry->file_contents_mode);
+    EXPECT_EQ("aes-256-cts", entry->file_names_mode);
+    EXPECT_EQ(2, entry->file_policy_version);
+
+    entry++;
+    EXPECT_EQ("none12", entry->mount_point);
+    EXPECT_TRUE(CompareFlags(flags, entry->fs_mgr_flags));
     EXPECT_EQ("", entry->file_contents_mode);
     EXPECT_EQ("", entry->file_names_mode);
+    EXPECT_EQ(0, entry->file_policy_version);
+
+    entry++;
+    EXPECT_EQ("none13", entry->mount_point);
+    EXPECT_TRUE(CompareFlags(flags, entry->fs_mgr_flags));
+    EXPECT_EQ("aes-256-xts", entry->file_contents_mode);
+    EXPECT_EQ("aes-256-cts", entry->file_names_mode);
+    EXPECT_EQ(0, entry->file_policy_version);
+
+    entry++;
+    EXPECT_EQ("none14", entry->mount_point);
+    EXPECT_TRUE(CompareFlags(flags, entry->fs_mgr_flags));
+    EXPECT_EQ("aes-256-xts", entry->file_contents_mode);
+    EXPECT_EQ("aes-256-cts", entry->file_names_mode);
+    EXPECT_EQ(0, entry->file_policy_version);
 }
 
 TEST(fs_mgr, ReadFstabFromFile_FsMgrOptions_MaxCompStreams) {