diff --git a/Android.mk b/Android.mk index 1a5782b2..71b2b55e 100755 --- a/Android.mk +++ b/Android.mk @@ -866,6 +866,11 @@ ifeq ($(shell test $(PLATFORM_SDK_VERSION) -lt 24; echo $$?),0) 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 0f743f5b..0c7a02c4 100755 --- a/gui/Android.mk +++ b/gui/Android.mk @@ -76,7 +76,11 @@ endif 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 350b6301..3432f477 100644 --- a/gui/action.cpp +++ b/gui/action.cpp @@ -1029,6 +1029,17 @@ void GUIAction::reinject_after_flash() } } +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 @@ int GUIAction::flash(std::string arg) 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 3f724183..24e9d247 100644 --- a/gui/objects.hpp +++ b/gui/objects.hpp @@ -288,6 +288,7 @@ protected: 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 85b65b84..67c8f911 100755 --- a/gui/theme/common/landscape.xml +++ b/gui/theme/common/landscape.xml @@ -310,7 +310,7 @@ %tw_zip_location% - + diff --git a/gui/theme/common/languages/en.xml b/gui/theme/common/languages/en.xml index ac9472ea..478f88d6 100755 --- a/gui/theme/common/languages/en.xml +++ b/gui/theme/common/languages/en.xml @@ -724,5 +724,7 @@ Failed unmounting System Flashing A/B zip to inactive slot: {1} To flash additional zips, please reboot recovery to switch to the updated slot. + Starting Ozip Decryption... + Ozip Decryption Finished! diff --git a/gui/theme/common/portrait.xml b/gui/theme/common/portrait.xml index b3b43127..31aef466 100755 --- a/gui/theme/common/portrait.xml +++ b/gui/theme/common/portrait.xml @@ -267,7 +267,7 @@ %tw_zip_location% - + diff --git a/gui/theme/common/watch.xml b/gui/theme/common/watch.xml index 71cce197..5312cf53 100755 --- a/gui/theme/common/watch.xml +++ b/gui/theme/common/watch.xml @@ -398,7 +398,7 @@ %tw_zip_location% - + diff --git a/ozip_decrypt/Android.mk b/ozip_decrypt/Android.mk new file mode 100644 index 00000000..161cae88 --- /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 00000000..97826ec1 --- /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 . +*/ + +#include +#include +#include +#include +#define _FILE_OFFSET_BITS 64 +//extern "C" __int64 __cdecl _ftelli64(FILE*); + +using namespace std; +typedef std::basic_string 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 f547139a..a092f54a 100755 --- a/prebuilt/Android.mk +++ b/prebuilt/Android.mk @@ -74,6 +74,9 @@ RELINK_SOURCE_FILES += $(TARGET_OUT_EXECUTABLES)/mke2fs 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