diff --git a/utils/nwztools/upgtools/Makefile b/utils/nwztools/upgtools/Makefile index 5dede1447c..287fe99c65 100644 --- a/utils/nwztools/upgtools/Makefile +++ b/utils/nwztools/upgtools/Makefile @@ -1,26 +1,39 @@ DEFINES= -CC=gcc -CXX=g++ -LD=g++ -PROFILE= -PKGCONFIG := $(CROSS)pkg-config +PREFIX?= +EXE_EXT?= +CC=$(PREFIX)gcc +CXX=$(PREFIX)g++ +LD=$(PREFIX)g++ +PKGCONFIG:=$(CROSS)pkg-config +TARGET_TRIPLE:=$(shell $(CC) -dumpmachine) +ifneq ($(findstring -w64-,$(TARGET_TRIPLE)),) + TARGET_OS := Windows +endif + +ifeq ($(TARGET_OS), Windows) +# -static allows to statically include libwinpthread-1.dll if possible +CFLAGS+=-gstabs +CXXFLAGS+=-gstabs +LDFLAGS+=-static-libgcc -static +else # Distros could use different names for the crypto library. We try a list # of candidate names, only one of them should be the valid one. LIBCRYPTO_NAMES = libcryptopp libcrypto++ cryptopp crypto++ $(foreach l,$(LIBCRYPTO_NAMES),\ - $(eval LDOPTS += $(shell $(PKGCONFIG) --silence-errors --libs $(l)))) + $(eval LDLIBS += $(shell $(PKGCONFIG) --silence-errors --libs $(l)))) $(foreach l,$(LIBCRYPTO_NAMES),\ $(eval CFLAGS += $(shell $(PKGCONFIG) --silence-errors --cflags $(l)))) $(foreach l,$(LIBCRYPTO_NAMES),\ $(eval CXXFLAGS += $(shell $(PKGCONFIG) --silence-errors --cflags $(l)))) +endif -CXXFLAGS=-g $(PROFILE) -Wall $(DEFINES) -CFLAGS=-g $(PROFILE) -Wall -std=c99 $(DEFINES) -LDFLAGS=$(PROFILE) $(LDOPTS) -lpthread +CXXFLAGS+=-g -Wall $(DEFINES) +CFLAGS+=-g -Wall -std=c99 $(DEFINES) +LDLIBS+=-lpthread -BINS=upgtool +BINS=upgtool$(EXE_EXT) all: $(BINS) @@ -30,11 +43,11 @@ all: $(BINS) %.o: %.cpp $(CXX) $(CXXFLAGS) -c -o $@ $< -upgtool: upgtool.o upg.o misc.o mg.o keysig_search.o md5.o - $(LD) -o $@ $^ $(LDFLAGS) +upgtool$(EXE_EXT): upgtool.o upg.o misc.o mg.o keysig_search.o + $(LD) $(LDFLAGS) -o $@ $^ $(LDLIBS) clean: - rm -fr *.o + rm -rf *.o veryclean: rm -rf $(BINS) diff --git a/utils/nwztools/upgtools/keysig_search.h b/utils/nwztools/upgtools/keysig_search.h index 72649e042e..67461d9b2b 100644 --- a/utils/nwztools/upgtools/keysig_search.h +++ b/utils/nwztools/upgtools/keysig_search.h @@ -49,7 +49,7 @@ struct keysig_search_desc_t const char *comment; }; -struct keysig_search_desc_t keysig_search_desc[KEYSIG_SEARCH_LAST]; +extern struct keysig_search_desc_t keysig_search_desc[KEYSIG_SEARCH_LAST]; bool keysig_search(int method, uint8_t *enc_buf, size_t buf_sz, keysig_notify_fn_t notify, void *user, int nr_threads); diff --git a/utils/nwztools/upgtools/md5.cpp b/utils/nwztools/upgtools/md5.cpp deleted file mode 100644 index 301eea2d53..0000000000 --- a/utils/nwztools/upgtools/md5.cpp +++ /dev/null @@ -1,32 +0,0 @@ -/*************************************************************************** - * __________ __ ___. - * Open \______ \ ____ ____ | | _\_ |__ _______ ___ - * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ / - * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < < - * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \ - * \/ \/ \/ \/ \/ - * $Id$ - * - * Copyright (C) 2012 Amaury Pouly - * - * This program 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 2 - * of the License, or (at your option) any later version. - * - * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY - * KIND, either express or implied. - * - ****************************************************************************/ -#include "md5.h" -/* MD5 is considered insecure by crypto++ */ -#define CRYPTOPP_ENABLE_NAMESPACE_WEAK 1 -#include -#include - -using namespace CryptoPP::Weak; - -void MD5_CalculateDigest(void *digest, const void *input, size_t length) -{ - MD5().CalculateDigest((byte *)digest, (const byte *)input, length); -} diff --git a/utils/nwztools/upgtools/md5.h b/utils/nwztools/upgtools/md5.h deleted file mode 100644 index 1e4b57ab0e..0000000000 --- a/utils/nwztools/upgtools/md5.h +++ /dev/null @@ -1,37 +0,0 @@ -/*************************************************************************** - * __________ __ ___. - * Open \______ \ ____ ____ | | _\_ |__ _______ ___ - * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ / - * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < < - * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \ - * \/ \/ \/ \/ \/ - * $Id$ - * - * Copyright (C) 2016 Amaury Pouly - * - * This program 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 2 - * of the License, or (at your option) any later version. - * - * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY - * KIND, either express or implied. - * - ****************************************************************************/ -#ifndef __md5_h__ -#define __md5_h__ - -#include - -#ifdef __cplusplus -extern "C" { -#endif - -/* Compute the MD5 digest of a buffer */ -void MD5_CalculateDigest(void *digest, const void *input, size_t length); - -#ifdef __cplusplus -} -#endif - -#endif /* __md5_h__ */ diff --git a/utils/nwztools/upgtools/mg.cpp b/utils/nwztools/upgtools/mg.cpp index 4bab5d9c61..df2dbbfd4f 100644 --- a/utils/nwztools/upgtools/mg.cpp +++ b/utils/nwztools/upgtools/mg.cpp @@ -19,13 +19,201 @@ * ****************************************************************************/ #include "mg.h" + +/* on Windows, we use Cryptography API, on other platforms we rely on crypto++ */ +#if defined(_WIN32) || defined(__WIN32__) +#include +#include +#include + +static HCRYPTPROV g_hCryptProv; + +typedef struct +{ + BLOBHEADER hdr; + DWORD dwKeySize; + BYTE rgbKeyData[]; +} PLAINTEXTKEY; + +static bool check_context() +{ + if(g_hCryptProv) + return true; + return CryptAcquireContext(&g_hCryptProv, NULL, MS_ENH_RSA_AES_PROV, PROV_RSA_AES, CRYPT_VERIFYCONTEXT); +} + +static HCRYPTKEY import_key(ALG_ID algid, DWORD mode, const uint8_t *key, int key_size, const uint8_t *iv) +{ + if(!check_context()) + return 0; + DWORD blob_size = sizeof(PLAINTEXTKEY) + key_size; + PLAINTEXTKEY *key_blob = (PLAINTEXTKEY *)malloc(blob_size); + key_blob->hdr.bType = PLAINTEXTKEYBLOB; + key_blob->hdr.bVersion = CUR_BLOB_VERSION; + key_blob->hdr.reserved = 0; + key_blob->hdr.aiKeyAlg = algid; + key_blob->dwKeySize = key_size; + memcpy(key_blob->rgbKeyData, key, key_size); + HCRYPTKEY hKey; + if(!CryptImportKey(g_hCryptProv, (const BYTE *)key_blob, blob_size, 0, 0, &hKey)) + return 0; + CryptSetKeyParam(hKey, KP_MODE, (const BYTE *)&mode, 0); + if(iv) + CryptSetKeyParam(hKey, KP_IV, (const BYTE *)iv, 0); + return hKey; +} + +void MD5_CalculateDigest(void *digest, const void *input, size_t length) +{ + if(!check_context()) + return; + HCRYPTHASH hHash; + if(!CryptCreateHash(g_hCryptProv, CALG_MD5, 0, 0, &hHash)) + return; + if(!CryptHashData(hHash, (const BYTE *)input, length, 0)) + return; + DWORD dwSize = 16; + if(!CryptGetHashParam(hHash, HP_HASHVAL, (BYTE *)digest, &dwSize, 0)) + return; + CryptDestroyHash(hHash); +} + +void mg_decrypt_fw(void *in, int size, void *out, uint8_t *key) +{ + if(!check_context() || (size % 8) != 0) + abort(); /* size must be a multiple of 8 */ + HCRYPTKEY hKey = import_key(CALG_DES, CRYPT_MODE_ECB, key, 8, NULL); + memcpy(out, in, size); + DWORD dwSize = size; + CryptDecrypt(hKey, 0, FALSE, 0, (BYTE *)out, &dwSize); + CryptDestroyKey(hKey); +} + +static HCRYPTKEY g_des_ecb_dec_key; + +void des_ecb_dec_set_key(const uint8_t key[8]) +{ + if(g_des_ecb_dec_key) + CryptDestroyKey(g_des_ecb_dec_key); + g_des_ecb_dec_key = import_key(CALG_DES, CRYPT_MODE_ECB, key, 8, NULL); +} + +void des_ecb_dec(void *in, int size, void *out) +{ + if(size % 8) + abort(); /* size must be a multiple of 8 */ + memcpy(out, in, size); + DWORD dwSize = size; + CryptDecrypt(g_des_ecb_dec_key, 0, FALSE, 0, (BYTE *)out, &dwSize); +} + +static HCRYPTKEY g_des_ecb_enc_key; + +void des_ecb_enc_set_key(const uint8_t key[8]) +{ + if(g_des_ecb_enc_key) + CryptDestroyKey(g_des_ecb_enc_key); + g_des_ecb_enc_key = import_key(CALG_DES, CRYPT_MODE_ECB, key, 8, NULL); +} + +void des_ecb_enc(void *in, int size, void *out) +{ + if(size % 8) + abort(); /* size must be a multiple of 8 */ + memcpy(out, in, size); + DWORD dwSize = size; + CryptEncrypt(g_des_ecb_enc_key, 0, FALSE, 0, (BYTE *)out, &dwSize, dwSize); +} + +static HCRYPTKEY g_aes_ecb_dec_key; + +void aes_ecb_dec_set_key(const uint8_t key[16]) +{ + if(g_aes_ecb_dec_key) + CryptDestroyKey(g_aes_ecb_dec_key); + g_aes_ecb_dec_key = import_key(CALG_AES_128, CRYPT_MODE_ECB, key, 16, NULL); +} + +void aes_ecb_dec(void *in, int size, void *out) +{ + if(size % 16) + abort(); /* size must be a multiple of 16 */ + memcpy(out, in, size); + DWORD dwSize = size; + CryptDecrypt(g_aes_ecb_dec_key, 0, FALSE, 0, (BYTE *)out, &dwSize); +} + +static HCRYPTKEY g_aes_ecb_enc_key; + +void aes_ecb_enc_set_key(const uint8_t key[16]) +{ + if(g_aes_ecb_enc_key) + CryptDestroyKey(g_aes_ecb_enc_key); + g_aes_ecb_enc_key = import_key(CALG_AES_128, CRYPT_MODE_ECB, key, 16, NULL); +} + +void aes_ecb_enc(void *in, int size, void *out) +{ + if(size % 16) + abort(); /* size must be a multiple of 16 */ + memcpy(out, in, size); + DWORD dwSize = size; + CryptEncrypt(g_aes_ecb_enc_key, 0, FALSE, 0, (BYTE *)out, &dwSize, dwSize); +} + +static HCRYPTKEY g_aes_cbc_dec_key; + +void aes_cbc_dec_set_key_iv(const uint8_t key[16], const uint8_t iv[16]) +{ + if(g_aes_cbc_dec_key) + CryptDestroyKey(g_aes_cbc_dec_key); + g_aes_cbc_dec_key = import_key(CALG_AES_128, CRYPT_MODE_CBC, key, 16, iv); +} + +void aes_cbc_dec(void *in, int size, void *out) +{ + if(size % 16) + abort(); /* size must be a multiple of 16 */ + memcpy(out, in, size); + DWORD dwSize = size; + CryptDecrypt(g_aes_cbc_dec_key, 0, FALSE, 0, (BYTE *)out, &dwSize); +} + +static HCRYPTKEY g_aes_cbc_enc_key; + +void aes_cbc_enc_set_key_iv(const uint8_t key[16], const uint8_t iv[16]) +{ + if(g_aes_cbc_enc_key) + CryptDestroyKey(g_aes_cbc_enc_key); + g_aes_cbc_enc_key = import_key(CALG_AES_128, CRYPT_MODE_CBC, key, 16, iv); +} + +void aes_cbc_enc(void *in, int size, void *out) +{ + if(size % 16) + abort(); /* size must be a multiple of 16 */ + memcpy(out, in, size); + DWORD dwSize = size; + CryptEncrypt(g_aes_cbc_enc_key, 0, FALSE, 0, (BYTE *)out, &dwSize, dwSize); +} + + +#else /* Not on Windows */ +/* MD5 is considered insecure by crypto++ */ +#define CRYPTOPP_ENABLE_NAMESPACE_WEAK 1 #include #include #include #include -#include +#include using namespace CryptoPP; +using namespace CryptoPP::Weak; + +void MD5_CalculateDigest(void *digest, const void *input, size_t length) +{ + MD5().CalculateDigest((byte *)digest, (const byte *)input, length); +} void mg_decrypt_fw(void *in, int size, void *out, uint8_t *key) { @@ -119,3 +307,4 @@ void aes_cbc_enc(void *in, int size, void *out) abort(); /* size must be a multiple of 16 */ g_aes_cbc_enc.ProcessData((byte*)out, (byte*)in, size); } +#endif diff --git a/utils/nwztools/upgtools/mg.h b/utils/nwztools/upgtools/mg.h index fe6ec7c2f6..3f7de2cd9b 100644 --- a/utils/nwztools/upgtools/mg.h +++ b/utils/nwztools/upgtools/mg.h @@ -22,10 +22,15 @@ #define __mg_h__ #include +#include #ifdef __cplusplus extern "C" { #endif + +/* Compute the MD5 digest of a buffer */ +void MD5_CalculateDigest(void *digest, const void *input, size_t length); + /* size must be a multiple of 8, this function is thread-safe */ void mg_decrypt_fw(void *in, int size, void *out, uint8_t key[8]); diff --git a/utils/nwztools/upgtools/misc.c b/utils/nwztools/upgtools/misc.c index ed1ba6c788..0fc4542336 100644 --- a/utils/nwztools/upgtools/misc.c +++ b/utils/nwztools/upgtools/misc.c @@ -25,6 +25,18 @@ #include #include "misc.h" +#if defined(_WIN32) || defined(__WIN32__) + +const char OFF[] = ""; + +const char GREY[] = ""; +const char RED[] = ""; +const char GREEN[] = ""; +const char YELLOW[] = ""; +const char BLUE[] = ""; + +#else + const char OFF[] = { 0x1b, 0x5b, 0x31, 0x3b, '0', '0', 0x6d, '\0' }; const char GREY[] = { 0x1b, 0x5b, 0x31, 0x3b, '3', '0', 0x6d, '\0' }; @@ -33,6 +45,8 @@ const char GREEN[] = { 0x1b, 0x5b, 0x31, 0x3b, '3', '2', 0x6d, '\0' }; const char YELLOW[] = { 0x1b, 0x5b, 0x31, 0x3b, '3', '3', 0x6d, '\0' }; const char BLUE[] = { 0x1b, 0x5b, 0x31, 0x3b, '3', '4', 0x6d, '\0' }; +#endif + static bool g_color_enable = true; void enable_color(bool enable) diff --git a/utils/nwztools/upgtools/upg.c b/utils/nwztools/upgtools/upg.c index 910c37a9bf..47b1acb07b 100644 --- a/utils/nwztools/upgtools/upg.c +++ b/utils/nwztools/upgtools/upg.c @@ -22,7 +22,6 @@ #include #include #include -#include "md5.h" struct nwz_model_t g_model_list[] = { @@ -190,7 +189,7 @@ struct upg_file_t *upg_read_memory(void *buf, size_t size, const char *key, } else { - cprintf(GREY, "I don't know how to decrypt with a key of length %s\n", key_len); + cprintf(GREY, "I don't know how to decrypt with a key of length %d\n", key_len); return NULL; } diff --git a/utils/nwztools/upgtools/upgtool.c b/utils/nwztools/upgtools/upgtool.c index e0ccc15c48..81cb4aa939 100644 --- a/utils/nwztools/upgtools/upgtool.c +++ b/utils/nwztools/upgtools/upgtool.c @@ -28,9 +28,7 @@ #include #include #include "misc.h" -#include "elf.h" #include -#include "crypt.h" #include "keysig_search.h" #include "upg.h" @@ -197,10 +195,10 @@ static int extract_upg(int argc, char **argv) } g_in_file = argv[0]; - FILE *fin = fopen(g_in_file, "r"); + FILE *fin = fopen(g_in_file, "rb"); if(fin == NULL) { - perror("Cannot open boot file"); + perror("Cannot open UPG file"); return 1; } fseek(fin, 0, SEEK_END);