Files
Project_CTR/makerom/crypto.c
T
applestash 6d3ad5cfe4 implementation fixes
cleaned AES interface, corrected some header files, other misc
2014-09-07 21:10:55 +10:00

357 lines
8.3 KiB
C

#include "lib.h"
#include "crypto.h"
bool VerifySha256(void *data, u64 size, u8 hash[32])
{
u8 calchash[32];
ctr_sha(data, size, calchash, CTR_SHA_256);
return memcmp(hash,calchash,32) == 0;
}
void ctr_sha(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 AesCtr(u8 *key, u8 *ctr, u8 *input, u8 *output, u64 length, u64 offset)
{
u8 stream[16];
aes_context aes;
u64 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 AesCbc(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;
}
}
void ctr_rsa_free(ctr_rsa_context* ctx)
{
rsa_free(&ctx->rsa);
}
int ctr_rsa_init(ctr_rsa_context* ctx, u8 *modulus, u8 *private_exp, u8 *exponent, u8 rsa_type, u8 mode)
{
// Sanity Check
if(ctx == NULL || modulus == NULL ||(private_exp == NULL && mode == RSAKEY_PRIV) || (exponent == NULL && mode == RSAKEY_PUB))
return Fail;
rsa_init(&ctx->rsa, RSA_PKCS_V15, 0);
u16 n_size = 0;
u16 d_size = 0;
u16 e_size = 0;
switch(rsa_type){
case RSA_2048:
ctx->rsa.len = 0x100;
n_size = 0x100;
d_size = 0x100;
e_size = 3;
break;
case RSA_4096:
ctx->rsa.len = 0x200;
n_size = 0x200;
d_size = 0x200;
e_size = 3;
break;
default: return Fail;
}
switch(mode){
case(RSAKEY_PUB):
if (mpi_read_binary(&ctx->rsa.N, modulus, n_size))
goto clean;
if (mpi_read_binary(&ctx->rsa.E, exponent, e_size))
goto clean;
break;
case(RSAKEY_PRIV):
if (mpi_read_binary(&ctx->rsa.N, modulus, n_size))
goto clean;
if (mpi_read_binary(&ctx->rsa.D, private_exp, d_size))
goto clean;
break;
default: return Fail;
}
return Good;
clean:
ctr_rsa_free(ctx);
return Fail;
}
int ctr_sig(void *data, u64 size, u8 *signature, u8 *modulus, u8 *private_exp, u32 type, u8 mode)
{
int result = 0;
int hashtype, hashlen, sigtype;
if(data == NULL || signature == NULL || modulus == NULL ||(private_exp == NULL && mode == CTR_RSA_SIGN))
return Fail;
switch(type){
case RSA_4096_SHA1:
hashtype = CTR_SHA_1;
hashlen = 0x14;
sigtype = RSA_4096;
case RSA_4096_SHA256:
hashtype = CTR_SHA_256;
hashlen = 0x20;
sigtype = RSA_4096;
break;
case RSA_2048_SHA1:
hashtype = CTR_SHA_1;
hashlen = 0x14;
sigtype = RSA_2048;
case RSA_2048_SHA256:
hashtype = CTR_SHA_256;
hashlen = 0x20;
sigtype = RSA_2048;
break;
case ECC_SHA1:
hashtype = CTR_SHA_1;
hashlen = 0x14;
sigtype = ECC;
case ECC_SHA256:
hashtype = CTR_SHA_256;
hashlen = 0x20;
sigtype = ECC;
break;
default: return Fail;
}
u8 hash[hashlen];
memset(hash,0,hashlen);
ctr_sha(data,size,hash,hashtype);
//memdump(stdout,"Data: ",data,size);
//memdump(stdout,"HashFor Sig: ",hash,hashlen);
if(sigtype == RSA_2048 || sigtype == RSA_4096)
result = ctr_rsa(hash,signature,modulus,private_exp,type,mode);
else if(sigtype == ECC){
printf("[!] ECC is not yet implemented\n");
result = Fail;
}
return result;
}
int ctr_rsa(u8 *hash, u8 *signature, u8 *modulus, u8 *private_exp, u32 type, u8 mode)
{
int result = 0;
// Sanity Check
if(hash == NULL || signature == NULL || modulus == NULL ||(private_exp == NULL && mode == CTR_RSA_SIGN))
return Fail;
// Getting details from sig type
int hashtype;
int hashlen;
int sigtype;
switch(type){
case RSA_4096_SHA1:
hashtype = SIG_RSA_SHA1;
hashlen = 0x14;
sigtype = RSA_4096;
break;
case RSA_4096_SHA256:
hashtype = SIG_RSA_SHA256;
hashlen = 0x14;
sigtype = RSA_4096;
break;
case RSA_2048_SHA1:
hashtype = SIG_RSA_SHA1;
hashlen = 0x20;
sigtype = RSA_2048;
break;
case RSA_2048_SHA256:
hashtype = SIG_RSA_SHA256;
hashlen = 0x20;
sigtype = RSA_2048;
break;
default: return Fail;
}
// Setting up
ctr_rsa_context ctx;
u8 exponent[3] = {0x01,0x00,0x01};
switch(mode){
case CTR_RSA_VERIFY:
result = ctr_rsa_init(&ctx,modulus,NULL,(u8*)exponent,sigtype,RSAKEY_PUB);
break;
case CTR_RSA_SIGN:
result = ctr_rsa_init(&ctx,modulus,private_exp,NULL,sigtype,RSAKEY_PRIV);
break;
}
if(result)return result;
switch(mode){
case CTR_RSA_VERIFY:
return rsa_pkcs1_verify(&ctx.rsa,RSA_PUBLIC,hashtype,hashlen,hash,signature);
case CTR_RSA_SIGN:
return ctr_rsa_rsassa_pkcs1_v15_sign(&ctx.rsa,RSA_PRIVATE,hashtype,hashlen,hash,signature);
}
return Fail;
}
/**
* Hacked from rsa.c, polarssl doesn't like generating signatures when only D and N are present
**/
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 )
{
size_t nb_pad, olen, ret;
unsigned char *p = sig;
if( ctx->padding != RSA_PKCS_V15 )
return( POLARSSL_ERR_RSA_BAD_INPUT_DATA );
olen = ctx->len;
switch( hash_id )
{
case SIG_RSA_RAW:
nb_pad = olen - 3 - hashlen;
break;
case SIG_RSA_MD2:
case SIG_RSA_MD4:
case SIG_RSA_MD5:
nb_pad = olen - 3 - 34;
break;
case SIG_RSA_SHA1:
nb_pad = olen - 3 - 35;
break;
case SIG_RSA_SHA224:
nb_pad = olen - 3 - 47;
break;
case SIG_RSA_SHA256:
nb_pad = olen - 3 - 51;
break;
case SIG_RSA_SHA384:
nb_pad = olen - 3 - 67;
break;
case SIG_RSA_SHA512:
nb_pad = olen - 3 - 83;
break;
default:
return( POLARSSL_ERR_RSA_BAD_INPUT_DATA );
}
if( ( nb_pad < 8 ) || ( nb_pad > olen ) )
return( POLARSSL_ERR_RSA_BAD_INPUT_DATA );
*p++ = 0;
*p++ = RSA_SIGN;
memset( p, 0xFF, nb_pad );
p += nb_pad;
*p++ = 0;
switch( hash_id )
{
case SIG_RSA_RAW:
memcpy( p, hash, hashlen );
break;
case SIG_RSA_MD2:
memcpy( p, ASN1_HASH_MDX, 18 );
memcpy( p + 18, hash, 16 );
p[13] = 2; break;
case SIG_RSA_MD4:
memcpy( p, ASN1_HASH_MDX, 18 );
memcpy( p + 18, hash, 16 );
p[13] = 4; break;
case SIG_RSA_MD5:
memcpy( p, ASN1_HASH_MDX, 18 );
memcpy( p + 18, hash, 16 );
p[13] = 5; break;
case SIG_RSA_SHA1:
memcpy( p, ASN1_HASH_SHA1, 15 );
memcpy( p + 15, hash, 20 );
break;
case SIG_RSA_SHA224:
memcpy( p, ASN1_HASH_SHA2X, 19 );
memcpy( p + 19, hash, 28 );
p[1] += 28; p[14] = 4; p[18] += 28; break;
case SIG_RSA_SHA256:
memcpy( p, ASN1_HASH_SHA2X, 19 );
memcpy( p + 19, hash, 32 );
p[1] += 32; p[14] = 1; p[18] += 32; break;
case SIG_RSA_SHA384:
memcpy( p, ASN1_HASH_SHA2X, 19 );
memcpy( p + 19, hash, 48 );
p[1] += 48; p[14] = 2; p[18] += 48; break;
case SIG_RSA_SHA512:
memcpy( p, ASN1_HASH_SHA2X, 19 );
memcpy( p + 19, hash, 64 );
p[1] += 64; p[14] = 3; p[18] += 64; break;
default:
return( POLARSSL_ERR_RSA_BAD_INPUT_DATA );
}
mpi T, T1, T2;
mpi_init( &T ); mpi_init( &T1 ); mpi_init( &T2 );
MPI_CHK( mpi_read_binary( &T, sig, ctx->len ) );
if( mpi_cmp_mpi( &T, &ctx->N ) >= 0 )
{
mpi_free( &T );
return( POLARSSL_ERR_RSA_BAD_INPUT_DATA );
}
MPI_CHK( mpi_exp_mod( &T, &T, &ctx->D, &ctx->N, &ctx->RN ) );
MPI_CHK( mpi_write_binary( &T, sig, olen ) );
cleanup:
mpi_free( &T ); mpi_free( &T1 ); mpi_free( &T2 );
return( 0 );
}