forked from len0rd/rockbox
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
This commit is contained in:
parent
05fa8fc343
commit
1f338f7078
9 changed files with 239 additions and 90 deletions
|
@ -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
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue