summaryrefslogtreecommitdiffstats
path: root/utils/nwztools/upgtools/mg.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'utils/nwztools/upgtools/mg.cpp')
-rw-r--r--utils/nwztools/upgtools/mg.cpp191
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