FsCrypt update: support fscrypt policies v1 and v2

This patchset introduces support decryption for Android 11.

In this update we deprecate ext4crypt. To specify the
policy version to use, use TW_USE_FSCRYPT_POLICY := 1 or
TW_USE_FSCRYPT_POLICY := 2. By default policy version will
be set to 2 if this variable is omitted.

Change-Id: I62a29c1bef36c259ec4b11259f71be613d20a112
diff --git a/crypto/fscrypt/Decrypt.cpp b/crypto/fscrypt/Decrypt.cpp
index 44eae08..5878d15 100755
--- a/crypto/fscrypt/Decrypt.cpp
+++ b/crypto/fscrypt/Decrypt.cpp
@@ -16,6 +16,7 @@
 
 #include "Decrypt.h"
 #include "FsCrypt.h"
+#include <fscrypt/fscrypt.h>
 
 #include <map>
 #include <string>
@@ -72,39 +73,37 @@
 #include <keystore/OperationResult.h>
 #include "keystore_client.pb.h"
 
-#include <keymasterV4_0/authorization_set.h>
-#include <keymasterV4_0/keymaster_utils.h>
+#include <keymasterV4_1/authorization_set.h>
+#include <keymasterV4_1/keymaster_utils.h>
 
 extern "C" {
 #include "crypto_scrypt.h"
 }
 
 #include "fscrypt_policy.h"
+#include "fscrypt-common.h"
 #include "HashPassword.h"
 #include "KeyStorage.h"
+#include "android/os/IVold.h"
 
 using android::security::keystore::IKeystoreService;
 using keystore::KeystoreResponsePromise;
 using keystore::OperationResultPromise;
 using android::security::keymaster::OperationResult;
-using android::hardware::keymaster::V4_0::support::blob2hidlVec;
+using android::hardware::keymaster::V4_1::support::blob2hidlVec;
 
-// Store main DE raw ref / policy
-extern std::string de_raw_ref;
-extern std::map<userid_t, std::string> s_de_key_raw_refs;
-extern std::map<userid_t, std::string> s_ce_key_raw_refs;
 
 inline std::string hidlVec2String(const ::keystore::hidl_vec<uint8_t>& value) {
     return std::string(reinterpret_cast<const std::string::value_type*>(&value[0]), value.size());
 }
 
-static bool lookup_ref_key_internal(std::map<userid_t, std::string>& key_map, const uint8_t* policy, userid_t* user_id) {
-	char policy_string_hex[FS_KEY_DESCRIPTOR_SIZE_HEX];
-	char key_map_hex[FS_KEY_DESCRIPTOR_SIZE_HEX];
-	policy_to_hex(policy, policy_string_hex);
+static bool lookup_ref_key_internal(std::map<userid_t, android::fscrypt::EncryptionPolicy> key_map, const uint8_t* policy, userid_t* user_id) {
+	char policy_string_hex[FSCRYPT_KEY_IDENTIFIER_HEX_SIZE];
+	char key_map_hex[FSCRYPT_KEY_IDENTIFIER_HEX_SIZE];
+	bytes_to_hex(policy, FSCRYPT_KEY_IDENTIFIER_SIZE, policy_string_hex);
 
-    for (std::map<userid_t, std::string>::iterator it=key_map.begin(); it!=key_map.end(); ++it) {
-		policy_to_hex(reinterpret_cast<const uint8_t*>(&it->second[0]), key_map_hex);
+    for (std::map<userid_t, android::fscrypt::EncryptionPolicy>::iterator it=key_map.begin(); it!=key_map.end(); ++it) {
+		bytes_to_hex(reinterpret_cast<const uint8_t*>(&it->second.key_raw_ref[0]), FSCRYPT_KEY_IDENTIFIER_SIZE, key_map_hex);
 		std::string key_map_hex_string = std::string(key_map_hex);
 		if (key_map_hex_string == policy_string_hex) {
             *user_id = it->first;
@@ -114,65 +113,72 @@
     return false;
 }
 
-extern "C" bool lookup_ref_key(const uint8_t* policy, uint8_t* policy_type) {
-    userid_t user_id = 0;
-	char policy_string_hex[FS_KEY_DESCRIPTOR_SIZE_HEX];
-	char de_raw_ref_hex[FS_KEY_DESCRIPTOR_SIZE_HEX];
-	policy_to_hex(policy, policy_string_hex);
-	policy_to_hex(reinterpret_cast<const uint8_t*>(&de_raw_ref[0]), de_raw_ref_hex);
-	std::string de_raw_ref_hex_string = std::string(de_raw_ref_hex);
-
+#ifdef USE_FSCRYPT_POLICY_V1
+extern "C" bool lookup_ref_key(fscrypt_policy_v1* v1, uint8_t* policy_type) {
+#else
+extern "C" bool lookup_ref_key(fscrypt_policy_v2* v2, uint8_t* policy_type) {
+#endif
+	userid_t user_id = 0;
 	std::string policy_type_string;
-	if (policy_string_hex == de_raw_ref_hex_string) {
+
+	char policy_hex[FSCRYPT_KEY_IDENTIFIER_HEX_SIZE];
+	bytes_to_hex(v2->master_key_identifier, FSCRYPT_KEY_IDENTIFIER_SIZE, policy_hex);
+	if (std::strncmp((const char*) v2->master_key_identifier, de_key_raw_ref.c_str(), FSCRYPT_KEY_IDENTIFIER_SIZE) == 0) {
 		policy_type_string = "0DK";
 		memcpy(policy_type, policy_type_string.data(), policy_type_string.size());
 		return true;
 	}
-
-    if (!lookup_ref_key_internal(s_de_key_raw_refs, policy, &user_id)) {
-        if (!lookup_ref_key_internal(s_ce_key_raw_refs, policy, &user_id)) {
+    if (!lookup_ref_key_internal(s_de_policies, v2->master_key_identifier, &user_id)) {
+        if (!lookup_ref_key_internal(s_ce_policies, v2->master_key_identifier, &user_id)) {
             return false;
-		} else
+		} else {
 			policy_type_string = "0CE" + std::to_string(user_id);
-    } else
+		}
+    } else {
 			policy_type_string = "0DE" + std::to_string(user_id);
+	}
 	memcpy(policy_type, policy_type_string.data(), policy_type_string.size());
+	LOG(INFO) << "storing policy type: " << policy_type;
     return true;
 }
 
 extern "C" bool lookup_ref_tar(const uint8_t* policy_type, uint8_t* policy) {
 	std::string policy_type_string = std::string((char *) policy_type);
-	char policy_hex[FS_KEY_DESCRIPTOR_SIZE_HEX];
-	policy_to_hex(policy_type, policy_hex);
+	char policy_hex[FSCRYPT_KEY_IDENTIFIER_HEX_SIZE];
+	bytes_to_hex(policy_type, FSCRYPT_KEY_IDENTIFIER_SIZE, policy_hex);
 
-	// Current encryption fscrypt policy is v1 (which is stored as version 0e)
+	userid_t user_id = atoi(policy_type_string.substr(3, 4).c_str());
+
+	// TODO Update version # and make magic strings
 	if (policy_type_string.substr(0,1) != "0") {
-        printf("Unexpected version %c\n", policy_type[0]);
+        LOG(ERROR) << "Unexpected version:" << policy_type[0];
         return false;
     }
 
 	if (policy_type_string.substr(1, 2) == "DK") {
-        memcpy(policy, de_raw_ref.data(), de_raw_ref.size());
+        memcpy(policy, de_key_raw_ref.data(), de_key_raw_ref.size());
         return true;
     }
 
-	userid_t user_id = atoi(policy_type_string.substr(3, 4).c_str());
     std::string raw_ref;
 
 	if (policy_type_string.substr(1, 1) == "D") {
-        if (lookup_key_ref(s_de_key_raw_refs, user_id, &raw_ref)) {
+        if (lookup_key_ref(s_de_policies, user_id, &raw_ref)) {
             memcpy(policy, raw_ref.data(), raw_ref.size());
         } else
             return false;
     } else if (policy_type_string.substr(1, 1) == "C") {
-        if (lookup_key_ref(s_ce_key_raw_refs, user_id, &raw_ref)) {
+        if (lookup_key_ref(s_ce_policies, user_id, &raw_ref)) {
             memcpy(policy, raw_ref.data(), raw_ref.size());
         } else
             return false;
     } else {
-        printf("unknown policy type '%s'\n", policy_type);
+        LOG(ERROR) << "unknown policy type: " << policy_type;
         return false;
     }
+
+	char found_policy_hex[FSCRYPT_KEY_IDENTIFIER_HEX_SIZE];
+	bytes_to_hex(policy, FSCRYPT_KEY_IDENTIFIER_SIZE, found_policy_hex);
     return true;
 }
 
@@ -688,14 +694,16 @@
         	return disk_decryption_secret_key;
     	}
 		OperationResult result = future.get();
-		auto handle = std::move(result.token);
+		std::map<uint64_t, android::sp<android::IBinder>> active_operations_;
+		uint64_t next_virtual_handle_ = 1;
+		active_operations_[next_virtual_handle_] = result.token;
 
 		// The cipher.doFinal call triggers an update to the keystore followed by a finish https://android.googlesource.com/platform/frameworks/base/+/android-8.0.0_r23/services/core/java/com/android/server/locksettings/SyntheticPasswordCrypto.java#64
 		// See also https://android.googlesource.com/platform/frameworks/base/+/android-8.0.0_r23/keystore/java/android/security/keystore/KeyStoreCryptoOperationChunkedStreamer.java#208
 		future = {};
 		promise = new OperationResultPromise();
 	    future = promise->get_future();
-		binder_result = service->update(promise, handle, empty_params, cipher_text_hidlvec, &error_code);
+		binder_result = service->update(promise, active_operations_[next_virtual_handle_], empty_params, cipher_text_hidlvec, &error_code);
 		rc = ::keystore::KeyStoreNativeReturnCode(error_code);
         if (!rc.isOk()) {
             printf("Keystore update returned: %d\n", error_code);
@@ -717,11 +725,10 @@
 		future = {};
 		promise = new OperationResultPromise();
 		future = promise->get_future();
-		std::tie(rc, keyBlob, charBlob, lockedEntry) = mKeyStore->getKeyForName(name8, callingUid, TYPE_KEYMASTER_10);
-		
-		auto hidlInput = blob2hidlVec(input_data);
-		::keystore::hidl_vec<uint8_t> signature;
-		binder_result = service->finish(promise, handle, empty_params, hidlInput, signature, entropy, &error_code);
+
+		auto hidlSignature = blob2hidlVec("");
+		auto hidlInput = blob2hidlVec(disk_decryption_secret_key);
+		binder_result = service->finish(promise, active_operations_[next_virtual_handle_], empty_params, hidlInput, hidlSignature, ::keystore::hidl_vec<uint8_t>(), &error_code);
 		if (!binder_result.isOk()) {
 			printf("communication error while calling keystore\n");
 			free(keystore_result);
@@ -844,11 +851,7 @@
 
 	std::string secret; // this will be the disk decryption key that is sent to vold
 	std::string token = "!"; // there is no token used for this kind of decrypt, key escrow is handled by weaver
-	int flags = FLAG_STORAGE_DE;
-    if (user_id == 0)
-		flags = FLAG_STORAGE_DE;
-	else
-		flags = FLAG_STORAGE_CE;
+	int flags = android::os::IVold::STORAGE_FLAG_CE;
 	char spblob_path_char[PATH_MAX];
 	sprintf(spblob_path_char, "/data/system_de/%d/spblob/", user_id);
 	std::string spblob_path = spblob_path_char;
@@ -1091,11 +1094,8 @@
 		printf("Unknown password type\n");
 		return false;
 	}
-    int flags = FLAG_STORAGE_DE;
-    if (user_id == 0)
-		flags = FLAG_STORAGE_DE;
-	else
-		flags = FLAG_STORAGE_CE;
+
+	int flags = android::os::IVold::STORAGE_FLAG_CE;
 
 	if (Default_Password) {
 		if (!fscrypt_unlock_user_key(user_id, 0, "!", "!")) {