Files
Project_CTR/makerom/crypto.c
T
2016-02-15 13:42:56 +08:00

196 lines
4.0 KiB
C

#include "lib.h"
#include "crypto.h"
const u8 RSA_PUB_EXP[0x3] = {0x01,0x00,0x01};
const int HASH_MAX_LEN = 0x20;
int ctr_rsa_rsassa_pkcs1_v15_sign( rsa_context *ctx,
int mode,
int hash_id,
unsigned int hashlen,
const unsigned char *hash,
unsigned char *sig );
bool VerifySha256(void *data, u64 size, u8 hash[32])
{
u8 calchash[32];
ShaCalc(data, size, calchash, CTR_SHA_256);
return memcmp(hash,calchash,32) == 0;
}
void ShaCalc(void *data, u64 size, u8 *hash, int mode)
{
switch(mode){
case(CTR_SHA_1): sha1((u8*)data, size, hash); break;
case(CTR_SHA_256): sha2((u8*)data, size, hash, 0); break;
}
}
void SetAesCtrOffset(u8 *ctr, u64 offset)
{
u64_to_u8(ctr+8,u8_to_u64(ctr+8,BE)|align(offset,16)/16,BE);
}
void AesCtrCrypt(u8 *key, u8 *ctr, u8 *input, u8 *output, u64 length, u64 offset)
{
u8 stream[16];
aes_context aes;
size_t nc_off = 0;
clrmem(&aes,sizeof(aes_context));
aes_setkey_enc(&aes, key, 128);
SetAesCtrOffset(ctr,offset);
aes_crypt_ctr(&aes, length, &nc_off, ctr, stream, input, output);
return;
}
void AesCbcCrypt(u8 *key, u8 *iv, u8 *input, u8 *output, u64 length, u8 mode)
{
aes_context aes;
clrmem(&aes,sizeof(aes_context));
switch(mode){
case(ENC):
aes_setkey_enc(&aes, key, 128);
aes_crypt_cbc(&aes, AES_ENCRYPT, length, iv, input, output);
return;
case(DEC):
aes_setkey_dec(&aes, key, 128);
aes_crypt_cbc(&aes, AES_DECRYPT, length, iv, input, output);
return;
default:
return;
}
}
bool RsaKeyInit(rsa_context* ctx, u8 *modulus, u8 *private_exp, u8 *exponent, u8 rsa_type)
{
// Sanity Check
if(!ctx)
return false;
rsa_init(ctx, RSA_PKCS_V15, 0);
u16 n_size = 0;
u16 d_size = 0;
u16 e_size = 0;
switch(rsa_type){
case RSA_2048:
ctx->len = 0x100;
n_size = 0x100;
d_size = 0x100;
e_size = 3;
break;
case RSA_4096:
ctx->len = 0x200;
n_size = 0x200;
d_size = 0x200;
e_size = 3;
break;
default: return false;
}
if (modulus && mpi_read_binary(&ctx->N, modulus, n_size))
goto clean;
if (exponent && mpi_read_binary(&ctx->E, exponent, e_size))
goto clean;
if (private_exp && mpi_read_binary(&ctx->D, private_exp, d_size))
goto clean;
return true;
clean:
rsa_free(ctx);
return false;
}
u8 GetRsaType(u32 sig_type)
{
switch(sig_type){
case RSA_4096_SHA1:
case RSA_4096_SHA256:
return RSA_4096;
case RSA_2048_SHA1:
case RSA_2048_SHA256:
return RSA_2048;
}
return INVALID_SIG_TYPE;
}
u32 GetSigHashType(u32 sig_type)
{
switch(sig_type){
case RSA_4096_SHA1:
case RSA_2048_SHA1:
case ECC_SHA1:
return CTR_SHA_1;
case RSA_4096_SHA256:
case RSA_2048_SHA256:
case ECC_SHA256:
return CTR_SHA_256;
}
return 0;
}
int GetRsaHashType(u32 sig_type)
{
switch(sig_type){
case RSA_4096_SHA1:
case RSA_2048_SHA1:
return SIG_RSA_SHA1;
case RSA_4096_SHA256:
case RSA_2048_SHA256:
return SIG_RSA_SHA256;
}
return 0;
}
u32 GetSigHashLen(u32 sig_type)
{
switch(sig_type){
case RSA_4096_SHA1:
case RSA_2048_SHA1:
case ECC_SHA1:
return SHA_1_LEN;
case RSA_4096_SHA256:
case RSA_2048_SHA256:
case ECC_SHA256:
return SHA_256_LEN;
}
return 0;
}
bool CalcHashForSign(void *data, u64 len, u8 *hash, u32 sig_type)
{
if(GetSigHashType(sig_type) == 0)
return false;
ShaCalc(data, len, hash, GetSigHashType(sig_type));
return true;
}
int RsaSignVerify(void *data, u64 len, u8 *sign, u8 *mod, u8 *priv_exp, u32 sig_type, u8 rsa_mode)
{
int rsa_result = 0;
rsa_context ctx;
u8 hash[HASH_MAX_LEN];
if(!RsaKeyInit(&ctx, mod, priv_exp, (u8*)RSA_PUB_EXP, GetRsaType(sig_type)))
return -1;
if(!CalcHashForSign(data, len, hash, sig_type))
return -1;
if(rsa_mode == CTR_RSA_VERIFY)
rsa_result = rsa_pkcs1_verify(&ctx, RSA_PUBLIC, GetRsaHashType(sig_type), 0, hash, sign);
else // CTR_RSA_SIGN
rsa_result = rsa_rsassa_pkcs1_v15_sign(&ctx, RSA_PRIVATE, GetRsaHashType(sig_type), 0, hash, sign);
rsa_free(&ctx);
return rsa_result;
}