Merge "Relink adbd needed in android 8.1" into android-8.1
diff --git a/crypto/ext4crypt/Android.mk b/crypto/ext4crypt/Android.mk
index af5ab3a..693b675 100644
--- a/crypto/ext4crypt/Android.mk
+++ b/crypto/ext4crypt/Android.mk
@@ -28,6 +28,7 @@
         LOCAL_CFLAGS += -DHAVE_LIBKEYUTILS
         LOCAL_SHARED_LIBRARIES += libkeyutils
     endif
+    LOCAL_ADDITIONAL_DEPENDENCIES := keystore_auth
 else
     LOCAL_SRC_FILES += Keymaster.cpp KeyStorage.cpp
 endif
@@ -58,4 +59,15 @@
 
 include $(BUILD_EXECUTABLE)
 
+include $(CLEAR_VARS)
+LOCAL_MODULE := keystore_auth
+LOCAL_MODULE_TAGS := optional
+LOCAL_MODULE_CLASS := RECOVERY_EXECUTABLES
+LOCAL_MODULE_PATH := $(TARGET_RECOVERY_ROOT_OUT)/sbin
+LOCAL_SRC_FILES := keystore_auth.cpp
+LOCAL_SHARED_LIBRARIES := libc libkeystore_binder libutils libbinder liblog
+LOCAL_LDFLAGS += -Wl,-dynamic-linker,/sbin/linker64
+
+include $(BUILD_EXECUTABLE)
+
 endif
diff --git a/crypto/ext4crypt/Decrypt.cpp b/crypto/ext4crypt/Decrypt.cpp
index 2dab166..4a8494e 100644
--- a/crypto/ext4crypt/Decrypt.cpp
+++ b/crypto/ext4crypt/Decrypt.cpp
@@ -287,10 +287,27 @@
 			return false;
 		}
 		memcpy(pwd->salt, intptr + 1, pwd->salt_len);
+		intptr++;
+		byteptr = (const unsigned char*)intptr;
+		byteptr += pwd->salt_len;
 	} else {
 		printf("Get_Password_Data salt_len is 0\n");
 		return false;
 	}
+	intptr = (const int*)byteptr;
+	pwd->handle_len = *intptr;
+	endianswap(&pwd->handle_len);
+	if (pwd->handle_len != 0) {
+		pwd->password_handle = malloc(pwd->handle_len);
+		if (!pwd->password_handle) {
+			printf("Get_Password_Data malloc password_handle\n");
+			return false;
+		}
+		memcpy(pwd->password_handle, intptr + 1, pwd->handle_len);
+	} else {
+		printf("Get_Password_Data handle_len is 0\n");
+		// Not an error if using weaver
+	}
 	return true;
 }
 
@@ -496,7 +513,7 @@
 /* C++ replacement for function of the same name
  * https://android.googlesource.com/platform/frameworks/base/+/android-8.0.0_r23/services/core/java/com/android/server/locksettings/SyntheticPasswordManager.java#867
  * returning an empty string indicates an error */
-std::string unwrapSyntheticPasswordBlob(const std::string& spblob_path, const std::string& handle_str, const userid_t user_id, const void* application_id, const size_t application_id_size) {
+std::string unwrapSyntheticPasswordBlob(const std::string& spblob_path, const std::string& handle_str, const userid_t user_id, const void* application_id, const size_t application_id_size, uint32_t auth_token_len) {
 	std::string disk_decryption_secret_key = "";
 
 	std::string keystore_alias_subid;
@@ -513,6 +530,11 @@
 		return disk_decryption_secret_key;
 	}
 
+	if (auth_token_len > 0) {
+		printf("Starting keystore_auth service...\n");
+		property_set("ctl.start", "keystore_auth");
+	}
+
 	// Read the data from the .spblob file per: https://android.googlesource.com/platform/frameworks/base/+/android-8.0.0_r23/services/core/java/com/android/server/locksettings/SyntheticPasswordManager.java#869
 	std::string spblob_file = spblob_path + handle_str + ".spblob";
 	std::string spblob_data;
@@ -579,6 +601,36 @@
     intermediate_key.resize(actual_size + final_size - 16, '\0');// not sure why we have to trim the size by 16 as I don't see where this is done in Java side
     //printf("intermediate key: "); output_hex((const unsigned char*)intermediate_key.data(), intermediate_key.size()); printf("\n");
 
+	// When using secdis (aka not weaver) you must supply an auth token to the keystore prior to the begin operation
+	if (auth_token_len > 0) {
+		/*::keystore::KeyStoreServiceReturnCode auth_result = service->addAuthToken(auth_token, auth_token_len);
+		if (!auth_result.isOk()) {
+			// The keystore checks the uid of the calling process and will return a permission denied on this operation for user 0
+			printf("keystore error adding auth token\n");
+			return disk_decryption_secret_key;
+		}*/
+		// The keystore refuses to allow the root user to supply auth tokens, so we write the auth token to a file earlier and
+		// run a separate service that runs user the system user to add the auth token. We wait for the auth token file to be
+		// deleted by the keymaster_auth service and check for a /auth_error file in case of errors. We quit after after a while if
+		// the /auth_token file never gets deleted.
+		int auth_wait_count = 20;
+		while (access("/auth_token", F_OK) == 0 && auth_wait_count-- > 0)
+			usleep(5000);
+		if (auth_wait_count == 0 || access("/auth_error", F_OK) == 0) {
+			printf("error during keymaster_auth service\n");
+			/* If you are getting this error, make sure that you have the keymaster_auth service defined in your init scripts, preferrably in init.recovery.{ro.hardware}.rc
+			 * service keystore_auth /sbin/keystore_auth
+			 *     disabled
+			 *     oneshot
+			 *     user system
+			 *     group root
+			 *     seclabel u:r:recovery:s0
+			 *
+			 * And check dmesg for error codes regarding this service if needed. */
+			return disk_decryption_secret_key;
+		}
+	}
+
 	int32_t ret;
 
 	/* We only need a keyAlias which is USRSKEY_synthetic_password_b6f71045af7bd042 which we find and a uid which is -1 or 1000, I forget which
@@ -677,11 +729,40 @@
 
 #define PASSWORD_TOKEN_SIZE 32
 
-bool Free_Return(bool retval, void* weaver_key, void* pwd_salt) {
+/* C++ replacement for
+ * https://android.googlesource.com/platform/frameworks/base/+/android-8.0.0_r23/services/core/java/com/android/server/locksettings/SyntheticPasswordManager.java#992
+ * called here
+ * https://android.googlesource.com/platform/frameworks/base/+/android-8.0.0_r23/services/core/java/com/android/server/locksettings/SyntheticPasswordManager.java#813 */
+bool Get_Secdis(const std::string& spblob_path, const std::string& handle_str, std::string& secdis_data) {
+	std::string secdis_file = spblob_path + handle_str + ".secdis";
+	if (!android::base::ReadFileToString(secdis_file, &secdis_data)) {
+		printf("Failed to read '%s'\n", secdis_file.c_str());
+		return false;
+	}
+	//output_hex(secdis_data.data(), secdis_data.size());printf("\n");
+	return true;
+}
+
+// C++ replacement for https://android.googlesource.com/platform/frameworks/base/+/android-8.0.0_r23/services/core/java/com/android/server/locksettings/SyntheticPasswordManager.java#1033
+userid_t fakeUid(const userid_t uid) {
+    return 100000 + uid;
+}
+
+bool Is_Weaver(const std::string& spblob_path, const std::string& handle_str) {
+	std::string weaver_file = spblob_path + handle_str + ".weaver";
+	struct stat st;
+	if (stat(weaver_file.c_str(), &st) == 0)
+		return true;
+	return false;
+}
+
+bool Free_Return(bool retval, void* weaver_key, password_data_struct* pwd) {
 	if (weaver_key)
 		free(weaver_key);
-	if (pwd_salt)
-		free(pwd_salt);
+	if (pwd->salt)
+		free(pwd->salt);
+	if (pwd->password_handle)
+		free(pwd->password_handle);
 	return retval;
 }
 
@@ -692,6 +773,12 @@
 	void* weaver_key = NULL;
 	password_data_struct pwd;
 	pwd.salt = NULL;
+	pwd.salt_len = 0;
+	pwd.password_handle = NULL;
+	pwd.handle_len = 0;
+	char application_id[PASSWORD_TOKEN_SIZE + SHA512_DIGEST_LENGTH];
+
+    uint32_t auth_token_len = 0;
 
 	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
@@ -708,14 +795,14 @@
 	// Get the handle: https://android.googlesource.com/platform/frameworks/base/+/android-8.0.0_r23/services/core/java/com/android/server/locksettings/LockSettingsService.java#2017
 	if (!Find_Handle(spblob_path, handle_str)) {
 		printf("Error getting handle\n");
-		return Free_Return(retval, weaver_key, pwd.salt);
+		return Free_Return(retval, weaver_key, &pwd);
 	}
 	printf("Handle is '%s'\n", handle_str.c_str());
 	// Now we begin driving unwrapPasswordBasedSyntheticPassword from: https://android.googlesource.com/platform/frameworks/base/+/android-8.0.0_r23/services/core/java/com/android/server/locksettings/SyntheticPasswordManager.java#758
 	// First we read the password data which contains scrypt parameters
 	if (!Get_Password_Data(spblob_path, handle_str, &pwd)) {
 		printf("Failed to Get_Password_Data\n");
-		return Free_Return(retval, weaver_key, pwd.salt);
+		return Free_Return(retval, weaver_key, &pwd);
 	}
 	//printf("pwd N %i R %i P %i salt ", pwd.scryptN, pwd.scryptR, pwd.scryptP); output_hex((char*)pwd.salt, pwd.salt_len); printf("\n");
 	unsigned char password_token[PASSWORD_TOKEN_SIZE];
@@ -723,81 +810,152 @@
 	// The password token is the password scrypted with the parameters from the password data file
 	if (!Get_Password_Token(&pwd, Password, &password_token[0])) {
 		printf("Failed to Get_Password_Token\n");
-		return Free_Return(retval, weaver_key, pwd.salt);
+		return Free_Return(retval, weaver_key, &pwd);
 	}
 	//output_hex(&password_token[0], PASSWORD_TOKEN_SIZE);printf("\n");
-	// BEGIN PIXEL 2 WEAVER
-	// Get the weaver data from the .weaver file which tells us which slot to use when we ask weaver for the escrowed key
-	// https://android.googlesource.com/platform/frameworks/base/+/android-8.0.0_r23/services/core/java/com/android/server/locksettings/SyntheticPasswordManager.java#768
-	weaver_data_struct wd;
-	if (!Get_Weaver_Data(spblob_path, handle_str, &wd)) {
-		printf("Failed to get weaver data\n");
-		// Fail over to gatekeeper path for Pixel 1???
-		return Free_Return(retval, weaver_key, pwd.salt);
-	}
-	// The weaver key is the the password token prefixed with "weaver-key" padded to 128 with nulls with the password token appended then SHA512
-	// https://android.googlesource.com/platform/frameworks/base/+/android-8.0.0_r23/services/core/java/com/android/server/locksettings/SyntheticPasswordManager.java#1059
-	weaver_key = PersonalizedHashBinary(PERSONALISATION_WEAVER_KEY, (char*)&password_token[0], PASSWORD_TOKEN_SIZE);
-	if (!weaver_key) {
-		printf("malloc error getting weaver_key\n");
-		return Free_Return(retval, weaver_key, pwd.salt);
-	}
-	// Now we start driving weaverVerify: https://android.googlesource.com/platform/frameworks/base/+/android-8.0.0_r23/services/core/java/com/android/server/locksettings/SyntheticPasswordManager.java#343
-	// Called from https://android.googlesource.com/platform/frameworks/base/+/android-8.0.0_r23/services/core/java/com/android/server/locksettings/SyntheticPasswordManager.java#776
-	android::vold::Weaver weaver;
-    if (!weaver) {
-		printf("Failed to get weaver service\n");
-		return Free_Return(retval, weaver_key, pwd.salt);
-	}
-	// Get the key size from weaver service
-	uint32_t weaver_key_size = 0;
-	if (!weaver.GetKeySize(&weaver_key_size)) {
-		printf("Failed to get weaver key size\n");
-		return Free_Return(retval, weaver_key, pwd.salt);
+	if (Is_Weaver(spblob_path, handle_str)) {
+		printf("using weaver\n");
+		// BEGIN PIXEL 2 WEAVER
+		// Get the weaver data from the .weaver file which tells us which slot to use when we ask weaver for the escrowed key
+		// https://android.googlesource.com/platform/frameworks/base/+/android-8.0.0_r23/services/core/java/com/android/server/locksettings/SyntheticPasswordManager.java#768
+		weaver_data_struct wd;
+		if (!Get_Weaver_Data(spblob_path, handle_str, &wd)) {
+			printf("Failed to get weaver data\n");
+			return Free_Return(retval, weaver_key, &pwd);
+		}
+		// The weaver key is the the password token prefixed with "weaver-key" padded to 128 with nulls with the password token appended then SHA512
+		// https://android.googlesource.com/platform/frameworks/base/+/android-8.0.0_r23/services/core/java/com/android/server/locksettings/SyntheticPasswordManager.java#1059
+		weaver_key = PersonalizedHashBinary(PERSONALISATION_WEAVER_KEY, (char*)&password_token[0], PASSWORD_TOKEN_SIZE);
+		if (!weaver_key) {
+			printf("malloc error getting weaver_key\n");
+			return Free_Return(retval, weaver_key, &pwd);
+		}
+		// Now we start driving weaverVerify: https://android.googlesource.com/platform/frameworks/base/+/android-8.0.0_r23/services/core/java/com/android/server/locksettings/SyntheticPasswordManager.java#343
+		// Called from https://android.googlesource.com/platform/frameworks/base/+/android-8.0.0_r23/services/core/java/com/android/server/locksettings/SyntheticPasswordManager.java#776
+		android::vold::Weaver weaver;
+		if (!weaver) {
+			printf("Failed to get weaver service\n");
+			return Free_Return(retval, weaver_key, &pwd);
+		}
+		// Get the key size from weaver service
+		uint32_t weaver_key_size = 0;
+		if (!weaver.GetKeySize(&weaver_key_size)) {
+			printf("Failed to get weaver key size\n");
+			return Free_Return(retval, weaver_key, &pwd);
+		} else {
+			//printf("weaver key size is %u\n", weaver_key_size);
+		}
+		//printf("weaver key: "); output_hex((unsigned char*)weaver_key, weaver_key_size); printf("\n");
+		// Send the slot from the .weaver file, the computed weaver key, and get the escrowed key data
+		std::vector<uint8_t> weaver_payload;
+		// TODO: we should return more information about the status including time delays before the next retry
+		if (!weaver.WeaverVerify(wd.slot, weaver_key, &weaver_payload)) {
+			printf("failed to weaver verify\n");
+			return Free_Return(retval, weaver_key, &pwd);
+		}
+		//printf("weaver payload: "); output_hex(&weaver_payload); printf("\n");
+		// Done with weaverVerify
+		// Now we will compute the application ID
+		// https://android.googlesource.com/platform/frameworks/base/+/android-8.0.0_r23/services/core/java/com/android/server/locksettings/SyntheticPasswordManager.java#964
+		// Called from https://android.googlesource.com/platform/frameworks/base/+/android-8.0.0_r23/services/core/java/com/android/server/locksettings/SyntheticPasswordManager.java#780
+		// The escrowed weaver key data is prefixed with "weaver-pwd" padded to 128 with nulls with the weaver payload appended then SHA512
+		void* weaver_secret = PersonalizedHashBinary(PERSONALISATION_WEAVER_PASSWORD, (const char*)weaver_payload.data(), weaver_payload.size());
+		//printf("weaver secret: "); output_hex((unsigned char*)weaver_secret, SHA512_DIGEST_LENGTH); printf("\n");
+		// The application ID is the password token and weaver secret appended to each other
+		memcpy((void*)&application_id[0], (void*)&password_token[0], PASSWORD_TOKEN_SIZE);
+		memcpy((void*)&application_id[PASSWORD_TOKEN_SIZE], weaver_secret, SHA512_DIGEST_LENGTH);
+		//printf("application ID: "); output_hex((unsigned char*)application_id, PASSWORD_TOKEN_SIZE + SHA512_DIGEST_LENGTH); printf("\n");
+		// END PIXEL 2 WEAVER
 	} else {
-		//printf("weaver key size is %u\n", weaver_key_size);
+		printf("using secdis\n");
+		std::string secdis_data;
+		if (!Get_Secdis(spblob_path, handle_str, secdis_data)) {
+			printf("Failed to get secdis data\n");
+			return Free_Return(retval, weaver_key, &pwd);
+		}
+		void* secdiscardable = PersonalizedHashBinary(PERSONALISATION_SECDISCARDABLE, (char*)secdis_data.data(), secdis_data.size());
+		if (!secdiscardable) {
+			printf("malloc error getting secdiscardable\n");
+			return Free_Return(retval, weaver_key, &pwd);
+		}
+		memcpy((void*)&application_id[0], (void*)&password_token[0], PASSWORD_TOKEN_SIZE);
+		memcpy((void*)&application_id[PASSWORD_TOKEN_SIZE], secdiscardable, SHA512_DIGEST_LENGTH);
+
+		int ret = -1;
+		bool request_reenroll = false;
+		android::sp<android::hardware::gatekeeper::V1_0::IGatekeeper> gk_device;
+		gk_device = ::android::hardware::gatekeeper::V1_0::IGatekeeper::getService();
+		if (gk_device == nullptr) {
+			printf("failed to get gatekeeper service\n");
+			return Free_Return(retval, weaver_key, &pwd);
+		}
+		if (pwd.handle_len <= 0) {
+			printf("no password handle supplied\n");
+			return Free_Return(retval, weaver_key, &pwd);
+		}
+		android::hardware::hidl_vec<uint8_t> pwd_handle_hidl;
+		pwd_handle_hidl.setToExternal(const_cast<uint8_t *>((const uint8_t *)pwd.password_handle), pwd.handle_len);
+		void* gk_pwd_token = PersonalizedHashBinary(PERSONALIZATION_USER_GK_AUTH, (char*)&password_token[0], PASSWORD_TOKEN_SIZE);
+		if (!gk_pwd_token) {
+			printf("malloc error getting gatekeeper_key\n");
+			return Free_Return(retval, weaver_key, &pwd);
+		}
+		android::hardware::hidl_vec<uint8_t> gk_pwd_token_hidl;
+		gk_pwd_token_hidl.setToExternal(const_cast<uint8_t *>((const uint8_t *)gk_pwd_token), SHA512_DIGEST_LENGTH);
+		android::hardware::Return<void> hwRet =
+			gk_device->verify(fakeUid(user_id), 0 /* challange */,
+							  pwd_handle_hidl,
+							  gk_pwd_token_hidl,
+							  [&ret, &request_reenroll, &auth_token_len]
+								(const android::hardware::gatekeeper::V1_0::GatekeeperResponse &rsp) {
+									ret = static_cast<int>(rsp.code); // propagate errors
+									if (rsp.code >= android::hardware::gatekeeper::V1_0::GatekeeperStatusCode::STATUS_OK) {
+										auth_token_len = rsp.data.size();
+										request_reenroll = (rsp.code == android::hardware::gatekeeper::V1_0::GatekeeperStatusCode::STATUS_REENROLL);
+										ret = 0; // all success states are reported as 0
+										// The keystore refuses to allow the root user to supply auth tokens, so we write the auth token to a file here and later
+										// run a separate service that runs as the system user to add the auth token. We wait for the auth token file to be
+										// deleted by the keymaster_auth service and check for a /auth_error file in case of errors. We quit after a while seconds if
+										// the /auth_token file never gets deleted.
+										unlink("/auth_token");
+										FILE* auth_file = fopen("/auth_token","wb");
+										if (auth_file != NULL) {
+											fwrite(rsp.data.data(), sizeof(uint8_t), rsp.data.size(), auth_file);
+											fclose(auth_file);
+										} else {
+											printf("failed to open /auth_token for writing\n");
+											ret = -2;
+										}
+									} else if (rsp.code == android::hardware::gatekeeper::V1_0::GatekeeperStatusCode::ERROR_RETRY_TIMEOUT && rsp.timeout > 0) {
+										ret = rsp.timeout;
+									}
+								}
+							 );
+		free(gk_pwd_token);
+		if (!hwRet.isOk() || ret != 0) {
+			printf("gatekeeper verification failed\n");
+			return Free_Return(retval, weaver_key, &pwd);
+		}
 	}
-	//printf("weaver key: "); output_hex((unsigned char*)weaver_key, weaver_key_size); printf("\n");
-	// Send the slot from the .weaver file, the computed weaver key, and get the escrowed key data
-	std::vector<uint8_t> weaver_payload;
-	// TODO: we should return more information about the status including time delays before the next retry
-	if (!weaver.WeaverVerify(wd.slot, weaver_key, &weaver_payload)) {
-		printf("failed to weaver verify\n");
-		return Free_Return(retval, weaver_key, pwd.salt);
-	}
-	//printf("weaver payload: "); output_hex(&weaver_payload); printf("\n");
-	// Done with weaverVerify
-	// Now we will compute the application ID
-	// https://android.googlesource.com/platform/frameworks/base/+/android-8.0.0_r23/services/core/java/com/android/server/locksettings/SyntheticPasswordManager.java#964
-	// Called from https://android.googlesource.com/platform/frameworks/base/+/android-8.0.0_r23/services/core/java/com/android/server/locksettings/SyntheticPasswordManager.java#780
-	// The escrowed weaver key data is prefixed with "weaver-pwd" padded to 128 with nulls with the weaver payload appended then SHA512
-	void* weaver_secret = PersonalizedHashBinary(PERSONALISATION_WEAVER_PASSWORD, (const char*)weaver_payload.data(), weaver_payload.size());
-	//printf("weaver secret: "); output_hex((unsigned char*)weaver_secret, SHA512_DIGEST_LENGTH); printf("\n");
-	// The application ID is the password token and weaver secret appended to each other
-	char application_id[PASSWORD_TOKEN_SIZE + SHA512_DIGEST_LENGTH];
-	memcpy((void*)&application_id[0], (void*)&password_token[0], PASSWORD_TOKEN_SIZE);
-	memcpy((void*)&application_id[PASSWORD_TOKEN_SIZE], weaver_secret, SHA512_DIGEST_LENGTH);
-	//printf("application ID: "); output_hex((unsigned char*)application_id, PASSWORD_TOKEN_SIZE + SHA512_DIGEST_LENGTH); printf("\n");
-	// END PIXEL 2 WEAVER
 	// Now we will handle https://android.googlesource.com/platform/frameworks/base/+/android-8.0.0_r23/services/core/java/com/android/server/locksettings/SyntheticPasswordManager.java#816
 	// Plus we will include the last bit that computes the disk decrypt key found in:
 	// https://android.googlesource.com/platform/frameworks/base/+/android-8.0.0_r23/services/core/java/com/android/server/locksettings/SyntheticPasswordManager.java#153
-	secret = android::keystore::unwrapSyntheticPasswordBlob(spblob_path, handle_str, user_id, (const void*)&application_id[0], PASSWORD_TOKEN_SIZE + SHA512_DIGEST_LENGTH);
+	secret = android::keystore::unwrapSyntheticPasswordBlob(spblob_path, handle_str, user_id, (const void*)&application_id[0], PASSWORD_TOKEN_SIZE + SHA512_DIGEST_LENGTH, auth_token_len);
 	if (!secret.size()) {
 		printf("failed to unwrapSyntheticPasswordBlob\n");
-		return Free_Return(retval, weaver_key, pwd.salt);
+		return Free_Return(retval, weaver_key, &pwd);
 	}
 	if (!e4crypt_unlock_user_key(user_id, 0, token.c_str(), secret.c_str())) {
 		printf("e4crypt_unlock_user_key returned fail\n");
-		return Free_Return(retval, weaver_key, pwd.salt);
+		return Free_Return(retval, weaver_key, &pwd);
 	}
 	if (!e4crypt_prepare_user_storage(nullptr, user_id, 0, flags)) {
 		printf("failed to e4crypt_prepare_user_storage\n");
-		return Free_Return(retval, weaver_key, pwd.salt);
+		return Free_Return(retval, weaver_key, &pwd);
 	}
 	printf("Decrypted Successfully!\n");
 	retval = true;
-	return Free_Return(retval, weaver_key, pwd.salt);
+	return Free_Return(retval, weaver_key, &pwd);
 }
 #endif //HAVE_SYNTH_PWD_SUPPORT
 
diff --git a/crypto/ext4crypt/HashPassword.h b/crypto/ext4crypt/HashPassword.h
index 8abd0de..4be107b 100644
--- a/crypto/ext4crypt/HashPassword.h
+++ b/crypto/ext4crypt/HashPassword.h
@@ -24,6 +24,8 @@
 #define PERSONALISATION_WEAVER_PASSWORD "weaver-pwd"
 #define PERSONALISATION_APPLICATION_ID "application-id"
 #define PERSONALIZATION_FBE_KEY "fbe-key"
+#define PERSONALIZATION_USER_GK_AUTH "user-gk-authentication"
+#define PERSONALISATION_SECDISCARDABLE "secdiscardable-transform"
 
 void* PersonalizedHashBinary(const char* prefix, const char* key, const size_t key_size);
 
diff --git a/crypto/ext4crypt/keystore_auth.cpp b/crypto/ext4crypt/keystore_auth.cpp
new file mode 100644
index 0000000..7d6eb24
--- /dev/null
+++ b/crypto/ext4crypt/keystore_auth.cpp
@@ -0,0 +1,90 @@
+/*
+	Copyright 2018 bigbiff/Dees_Troy TeamWin
+	This file is part of TWRP/TeamWin Recovery Project.
+
+	TWRP is free software: you can redistribute it and/or modify
+	it under the terms of the GNU General Public License as published by
+	the Free Software Foundation, either version 3 of the License, or
+	(at your option) any later version.
+
+	TWRP is distributed in the hope that it will be useful,
+	but WITHOUT ANY WARRANTY; without even the implied warranty of
+	MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+	GNU General Public License for more details.
+
+	You should have received a copy of the GNU General Public License
+	along with TWRP.  If not, see <http://www.gnu.org/licenses/>.
+*/
+
+/* The keystore refuses to allow the root user to supply auth tokens, so
+ * we write the auth token to a file in TWRP and run a separate service
+ * (this) that runs as the system user to add the auth token. TWRP waits
+ * for /auth_token to be deleted and also looks for /auth_error to check
+ * for errors. TWRP will error out after a while if /auth_token does not
+ * get deleted. */
+
+#include <stdio.h>
+#include <string>
+
+#include <keystore/IKeystoreService.h>
+#include <binder/IPCThreadState.h>
+#include <binder/IServiceManager.h>
+
+#include <keystore/keystore.h>
+#include <keystore/authorization_set.h>
+
+#define LOG_TAG "keystore_auth"
+
+using namespace android;
+
+void create_error_file() {
+	FILE* error_file = fopen("/auth_error", "wb");
+	if (error_file == NULL) {
+		printf("Failed to open /auth_error\n");
+		ALOGE("Failed to open /auth_error\n");
+		return;
+	}
+	fwrite("1", 1, 1, error_file);
+	fclose(error_file);
+	unlink("/auth_token");
+}
+
+int main(int argc, char *argv[]) {
+	unlink("/auth_error");
+	FILE* auth_file = fopen("/auth_token", "rb");
+	if (auth_file == NULL) {
+		printf("Failed to open /auth_token\n");
+		ALOGE("Failed to open /auth_token\n");
+		create_error_file();
+		return -1;
+	}
+	// Get the file size
+	fseek(auth_file, 0, SEEK_END);
+	int size = ftell(auth_file);
+	fseek(auth_file, 0, SEEK_SET);
+	uint8_t auth_token[size];
+	fread(auth_token , sizeof(uint8_t), size, auth_file);
+	fclose(auth_file);
+	// First get the keystore service
+	sp<IServiceManager> sm = defaultServiceManager();
+	sp<IBinder> binder = sm->getService(String16("android.security.keystore"));
+	sp<IKeystoreService> service = interface_cast<IKeystoreService>(binder);
+	if (service == NULL) {
+		printf("error: could not connect to keystore service\n");
+		ALOGE("error: could not connect to keystore service\n");
+		create_error_file();
+		return -2;
+	}
+	::keystore::KeyStoreServiceReturnCode auth_result = service->addAuthToken(auth_token, size);
+	if (!auth_result.isOk()) {
+		// The keystore checks the uid of the calling process and will return a permission denied on this operation for user 0
+		printf("keystore error adding auth token\n");
+		ALOGE("keystore error adding auth token\n");
+		create_error_file();
+		return -3;
+	}
+	printf("successfully added auth token to keystore\n");
+	ALOGD("successfully added auth token to keystore\n");
+	unlink("/auth_token");
+	return 0;
+}
diff --git a/minuitwrp/Android.mk b/minuitwrp/Android.mk
index 3f83c97..09bdb8d 100644
--- a/minuitwrp/Android.mk
+++ b/minuitwrp/Android.mk
@@ -48,7 +48,11 @@
 ifneq ($(wildcard external/libdrm/Android.mk),)
   LOCAL_CFLAGS += -DHAS_DRM
   LOCAL_SRC_FILES += graphics_drm.cpp
-  LOCAL_WHOLE_STATIC_LIBRARIES += libdrm
+  ifneq ($(wildcard external/libdrm/Android.common.mk),)
+    LOCAL_WHOLE_STATIC_LIBRARIES += libdrm_platform
+  else
+    LOCAL_WHOLE_STATIC_LIBRARIES += libdrm
+  endif
 endif
 
 LOCAL_C_INCLUDES += \