diff options
author | Amaury Pouly <amaury.pouly@gmail.com> | 2020-06-17 23:31:31 +0200 |
---|---|---|
committer | Amaury Pouly <amaury.pouly@gmail.com> | 2020-10-11 13:08:03 +0200 |
commit | 1f338f70789fdb7d6bbd954cc1444f59a156e83c (patch) | |
tree | 272b9bcc571929293053e3cc2680ab27a8fae23a /utils/nwztools/upgtools/mg.cpp | |
parent | 05fa8fc3435c74090430108001afeafe2d1e9d42 (diff) | |
download | rockbox-1f338f7078.tar.gz rockbox-1f338f7078.tar.bz2 rockbox-1f338f7078.zip |
nwztools/upgtools: add support for windows
In order to avoid the crypto++ mess, the code uses the Windows Cryptography API,
which is standard. There is also some makefile magic to cross-compile:
make PREFIX=i686-w64-mingw32- EXE_EXT=.exe
I selected the option so that it should statically link supports libraries used
by gcc (slsj and libwinpthread).
Change-Id: Iaf07da23afe81ed217fb3921ce13367c5441514d
Diffstat (limited to 'utils/nwztools/upgtools/mg.cpp')
-rw-r--r-- | utils/nwztools/upgtools/mg.cpp | 191 |
1 files changed, 190 insertions, 1 deletions
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 <windows.h> +#include <wincrypt.h> +#include <stdio.h> + +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 <cryptopp/cryptlib.h> #include <cryptopp/modes.h> #include <cryptopp/des.h> #include <cryptopp/aes.h> -#include <stdio.h> +#include <cryptopp/md5.h> 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 |