Merge "Add ozip decryption for Oppo/Realme device" into android-9.0
diff --git a/Android.mk b/Android.mk
index ab3bcc8..af49367 100755
--- a/Android.mk
+++ b/Android.mk
@@ -897,6 +897,11 @@
include $(commands_TWRP_local_path)/libmincrypt/Android.mk
endif
+ifneq ($(TW_OZIP_DECRYPT_KEY),)
+ TWRP_REQUIRED_MODULES += ozip_decrypt
+ include $(commands_TWRP_local_path)/ozip_decrypt/Android.mk
+endif
+
ifeq ($(TW_INCLUDE_CRYPTO), true)
include $(commands_TWRP_local_path)/crypto/fde/Android.mk
include $(commands_TWRP_local_path)/crypto/scrypt/Android.mk
diff --git a/gui/Android.mk b/gui/Android.mk
index b14b3d8..2243ba8 100755
--- a/gui/Android.mk
+++ b/gui/Android.mk
@@ -64,7 +64,11 @@
ifneq ($(TW_USE_KEY_CODE_TOUCH_SYNC),)
LOCAL_CFLAGS += -DTW_USE_KEY_CODE_TOUCH_SYNC=$(TW_USE_KEY_CODE_TOUCH_SYNC)
endif
-
+ifneq ($(TW_OZIP_DECRYPT_KEY),)
+ LOCAL_CFLAGS += -DTW_OZIP_DECRYPT_KEY=\"$(TW_OZIP_DECRYPT_KEY)\"
+else
+ LOCAL_CFLAGS += -DTW_OZIP_DECRYPT_KEY=0
+endif
ifneq ($(TW_NO_SCREEN_BLANK),)
LOCAL_CFLAGS += -DTW_NO_SCREEN_BLANK
endif
diff --git a/gui/action.cpp b/gui/action.cpp
index b26d55b..caa626d 100644
--- a/gui/action.cpp
+++ b/gui/action.cpp
@@ -1029,6 +1029,17 @@
}
}
+int GUIAction::ozip_decrypt(string zip_path)
+{
+ if (!TWFunc::Path_Exists("/sbin/ozip_decrypt")) {
+ return 1;
+ }
+ gui_msg("ozip_decrypt_decryption=Starting Ozip Decryption...");
+ TWFunc::Exec_Cmd("ozip_decrypt " + (string)TW_OZIP_DECRYPT_KEY + " '" + zip_path + "'");
+ gui_msg("ozip_decrypt_finish=Ozip Decryption Finished!");
+ return 0;
+}
+
int GUIAction::flash(std::string arg)
{
int i, ret_val = 0, wipe_cache = 0;
@@ -1039,6 +1050,20 @@
size_t slashpos = zip_path.find_last_of('/');
string zip_filename = (slashpos == string::npos) ? zip_path : zip_path.substr(slashpos + 1);
operation_start("Flashing");
+ if((zip_path.substr(zip_path.size() - 4, 4)) == "ozip")
+ {
+ if((ozip_decrypt(zip_path)) != 0)
+ {
+ LOGERR("Unable to find ozip_decrypt!");
+ break;
+ }
+ zip_filename = (zip_filename.substr(0, zip_filename.size() - 4)).append("zip");
+ zip_path = (zip_path.substr(0, zip_path.size() - 4)).append("zip");
+ if (!TWFunc::Path_Exists(zip_path)) {
+ LOGERR("Unable to find decrypted zip");
+ break;
+ }
+ }
DataManager::SetValue("tw_filename", zip_path);
DataManager::SetValue("tw_file", zip_filename);
DataManager::SetValue(TW_ZIP_INDEX, (i + 1));
diff --git a/gui/objects.hpp b/gui/objects.hpp
index 3f72418..24e9d24 100644
--- a/gui/objects.hpp
+++ b/gui/objects.hpp
@@ -288,6 +288,7 @@
ThreadType getThreadType(const Action& action);
void simulate_progress_bar(void);
int flash_zip(std::string filename, int* wipe_cache);
+ int ozip_decrypt(std::string zip_path);
void reinject_after_flash();
void operation_start(const string operation_name);
void operation_end(const int operation_status);
diff --git a/gui/theme/common/landscape.xml b/gui/theme/common/landscape.xml
index 7fc9980..3d8646c 100755
--- a/gui/theme/common/landscape.xml
+++ b/gui/theme/common/landscape.xml
@@ -310,7 +310,7 @@
<condition var1="tw_selectimage" var2="0"/>
<placement x="%col2_x_left%" y="%row1a_y%" w="%fileselector_install_width%" h="%fileselector_install_height%"/>
<text>%tw_zip_location%</text>
- <filter extn=".zip" folders="0" files="1"/>
+ <filter extn=".zip;.ozip;.ZIP;.OZIP" folders="0" files="1"/>
<path name="tw_zip_location" default="/sdcard"/>
<data name="tw_filename"/>
<selection name="tw_file"/>
diff --git a/gui/theme/common/languages/en.xml b/gui/theme/common/languages/en.xml
index 47ab708..fbcf436 100755
--- a/gui/theme/common/languages/en.xml
+++ b/gui/theme/common/languages/en.xml
@@ -735,5 +735,7 @@
<string name="fbe_wipe_msg">WARNING: {1} wiped. FBE device should be booted into Android and not Recovery to set initial FBE policy after wipe.</string>
<string name="flash_ab_inactive">Flashing A/B zip to inactive slot: {1}</string>
<string name="flash_ab_reboot">To flash additional zips, please reboot recovery to switch to the updated slot.</string>
+ <string name="ozip_decrypt_decryption">Starting Ozip Decryption...</string>
+ <string name="ozip_decrypt_finish">Ozip Decryption Finished!</string>
</resources>
</language>
diff --git a/gui/theme/common/portrait.xml b/gui/theme/common/portrait.xml
index a14fc43..4b8cd4a 100755
--- a/gui/theme/common/portrait.xml
+++ b/gui/theme/common/portrait.xml
@@ -267,7 +267,7 @@
<condition var1="tw_selectimage" var2="0"/>
<placement x="%indent%" y="%row3_y%" w="%content_width%" h="%fileselector_install_height%"/>
<text>%tw_zip_location%</text>
- <filter extn=".zip" folders="1" files="1"/>
+ <filter extn=".zip;.ozip;.ZIP;.OZIP" folders="1" files="1"/>
<path name="tw_zip_location" default="/sdcard"/>
<data name="tw_filename"/>
<selection name="tw_file"/>
diff --git a/gui/theme/common/watch.xml b/gui/theme/common/watch.xml
index af6a643..7b474dd 100755
--- a/gui/theme/common/watch.xml
+++ b/gui/theme/common/watch.xml
@@ -398,7 +398,7 @@
<condition var1="tw_selectimage" var2="0"/>
<placement x="%indent%" y="%row2_header_y%" w="%content_width%" h="%fileselector_install_height%"/>
<text>%tw_zip_location%</text>
- <filter extn=".zip" folders="1" files="1"/>
+ <filter extn=".zip;.ozip;.ZIP;.OZIP" folders="1" files="1"/>
<path name="tw_zip_location" default="/sdcard"/>
<data name="tw_filename"/>
<selection name="tw_file"/>
diff --git a/ozip_decrypt/Android.mk b/ozip_decrypt/Android.mk
new file mode 100644
index 0000000..161cae8
--- /dev/null
+++ b/ozip_decrypt/Android.mk
@@ -0,0 +1,11 @@
+LOCAL_PATH := $(call my-dir)
+
+include $(CLEAR_VARS)
+LOCAL_MODULE := ozip_decrypt
+LOCAL_MODULE_PATH := $(TARGET_RECOVERY_ROOT_OUT)/sbin
+LOCAL_MODULE_TAGS := optional
+
+LOCAL_SRC_FILES := ozip_decrypt.cpp
+LOCAL_C_INCLUDES := external/boringssl/src/include
+LOCAL_SHARED_LIBRARIES := libcrypto
+include $(BUILD_EXECUTABLE)
diff --git a/ozip_decrypt/ozip_decrypt.cpp b/ozip_decrypt/ozip_decrypt.cpp
new file mode 100644
index 0000000..97826ec
--- /dev/null
+++ b/ozip_decrypt/ozip_decrypt.cpp
@@ -0,0 +1,152 @@
+/*
+ Copyright 2020 Mauronofrio
+
+ This file 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.
+
+ This file 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.
+
+ GNU General Public License <http://www.gnu.org/licenses/>.
+*/
+
+#include <iostream>
+#include <string.h>
+#include <openssl/evp.h>
+#include <openssl/ssl.h>
+#define _FILE_OFFSET_BITS 64
+//extern "C" __int64 __cdecl _ftelli64(FILE*);
+
+using namespace std;
+typedef std::basic_string<unsigned char> u_string;
+
+int decrypt(unsigned char* ciphertext, int ciphertext_len, unsigned char* key,
+ unsigned char* iv, unsigned char* plaintext)
+{
+ EVP_CIPHER_CTX* ctx;
+ int len;
+ int plaintext_len;
+ ctx = EVP_CIPHER_CTX_new();
+ EVP_DecryptInit_ex(ctx, EVP_aes_128_ecb(), NULL, key, iv);
+ EVP_DecryptUpdate(ctx, plaintext, &len, ciphertext, ciphertext_len);
+ plaintext_len = len;
+ EVP_DecryptFinal_ex(ctx, plaintext + len, &len);
+ plaintext_len += len;
+ EVP_CIPHER_CTX_free(ctx);
+ return plaintext_len;
+}
+
+std::string hexToASCII(string hex)
+{
+ int len = hex.length();
+ std::string newString;
+ for (int i = 0; i < len; i += 2)
+ {
+ string byte = hex.substr(i, 2);
+ char chr = (char)(int)strtol(byte.c_str(), nullptr, 16);
+ newString.push_back(chr);
+ }
+ return newString;
+}
+
+bool testkey(const char* keyf, const char* path) {
+ u_string key = (unsigned char*)(hexToASCII(keyf)).c_str();
+ int data[17];
+ FILE* fps = fopen(path, "rb");
+ fseek(fps, 4176, SEEK_SET);
+ fread(data, sizeof(char), 16, fps);
+ fclose(fps);
+ u_string udata = (unsigned char*)data;
+ EVP_CIPHER_CTX* ctx = EVP_CIPHER_CTX_new();
+ EVP_CIPHER_CTX_init(ctx);
+ EVP_DecryptInit_ex(ctx, EVP_aes_128_ecb(), NULL, key.c_str(), NULL);
+ EVP_CIPHER_CTX_set_padding(ctx, false);
+ unsigned char buffer[1024], * pointer = buffer;
+ int outlen;
+ EVP_DecryptUpdate(ctx, pointer, &outlen, udata.c_str(), udata.length());
+ pointer += outlen;
+ EVP_DecryptFinal_ex(ctx, pointer, &outlen);
+ pointer += outlen;
+ EVP_CIPHER_CTX_free(ctx);
+ u_string test= u_string(buffer, pointer - buffer);
+ u_string checktest = test.substr(0, 4);
+ if (checktest == ((unsigned char*) "\x50\x4B\x03\x04") || checktest == ((unsigned char*) "\x41\x4E\x44\x52")) {
+ return true;
+ }
+ return false;
+}
+
+int main(int argc, char* argv[])
+{
+
+ if (argc != 3)
+ {
+ printf("Usage: ozipdecrypt key [*.ozip]\n");
+ return 0;
+ }
+ const char* key = argv[1];
+ const char* path = argv[2];
+ FILE* fp = fopen(path, "rb");
+ char magic[13];
+ fgets(magic, sizeof(magic), fp);
+ string temp(path);
+ temp = (temp.substr(0, temp.size() - 5)).append(".zip");
+ const char* destpath= temp.c_str();
+ if (strcmp(magic, "OPPOENCRYPT!") != 0)
+ {
+ printf("This is not an .ozip file!\n");
+ fclose(fp);
+ int rencheck = rename(path, destpath);
+ if (rencheck == 0) {
+ printf("Renamed .ozip file in .zip file\n");
+ }
+ else
+ {
+ printf("Unable to rename .ozip file in .zip file\n");
+ }
+ return 0;
+ }
+ if (testkey(key, path) == false)
+ {
+ printf("Key is not good!\n");
+ fclose(fp);
+ return 0;
+ }
+ else {
+ printf("Key is good!\n");
+ }
+ FILE* fp2 = fopen(destpath, "wb");
+ fseek(fp, 0L, SEEK_END);
+ unsigned long int sizetot = ftello(fp);
+ fseek(fp, 4176, SEEK_SET);
+ int bdata[16384];
+ unsigned long int sizeseek;
+ printf("Decrypting...\n");
+ while (true)
+ {
+ unsigned char data[17];
+ fread(data, sizeof(char), 16, fp);
+ decrypt(data, sizeof(data), (unsigned char*)(hexToASCII(key)).c_str(), NULL, data);
+ fwrite(data, sizeof(char), 16, fp2);
+ sizeseek = ftello(fp);
+ if ((sizetot - sizeseek) <= 16384) {
+ fread(bdata, sizeof(char), (sizetot - sizeseek), fp);
+ fwrite(bdata, sizeof(char), (sizetot - sizeseek), fp2);
+ break;
+ }
+ else
+ {
+ fread(bdata, sizeof(char), 16384, fp);
+ fwrite(bdata, sizeof(char), 16384, fp2);
+ }
+ }
+ printf("File succesfully decrypted, saved in %s\n", destpath);
+ fclose(fp2);
+ fclose(fp);
+ return 0;
+}
+
diff --git a/prebuilt/Android.mk b/prebuilt/Android.mk
index 2935113..a4f6f2e 100644
--- a/prebuilt/Android.mk
+++ b/prebuilt/Android.mk
@@ -59,6 +59,9 @@
RELINK_SOURCE_FILES += $(TARGET_OUT_EXECUTABLES)/tune2fs
RELINK_SOURCE_FILES += $(TARGET_OUT_EXECUTABLES)/resize2fs
RELINK_SOURCE_FILES += $(TARGET_RECOVERY_ROOT_OUT)/sbin/simg2img
+ifneq ($(TW_OZIP_DECRYPT_KEY),)
+ RELINK_SOURCE_FILES += $(TARGET_RECOVERY_ROOT_OUT)/sbin/ozip_decrypt
+endif
ifneq ($(TARGET_ARCH), x86_64)
RELINK_SOURCE_FILES += $(TARGET_OUT_EXECUTABLES)/linker
endif