TwlIPL/build/libraries_sysmenu/acsign/ARM9/src/acsign.c
yosiokat 75a9423d25 ・生産工程でNANDに書き込んで、以降はReadOnlyとなるHW情報を追加。
・HW情報や本体設定データを共通のTSFフォーマットにするため、TSF
 フォーマットのコードを追加。(現状はHW情報のみ対応)
・HW情報用のRSA鍵ペアを追加。
・acsignライブラリにRSA暗号化関数を追加。
・acsignライブラリのRSAでコード関数の値チェックを修正。
・HW情報をライトするHWInfoWriterを追加。
・NANDフラッシュマップ&フォルダツリーのフォルダ構成における各ファイルに
 ついて、RSA署名の有無と使用する鍵による色分けを行う。
・TWL_SystemMenuメモリマップにNANDファーム用バッファを記載。
 (ランチャーとメモリが重ならないように)

git-svn-id: file:///Users/lillianskinner/Downloads/platinum/twl/TwlIPL/trunk@312 b08762b0-b915-fc4b-9d8c-17b2551a87ff
2007-12-05 12:19:30 +00:00

454 lines
12 KiB
C
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

/*---------------------------------------------------------------------------*
Project: TwlIPL
File:
Copyright 2007 Nintendo. All rights reserved.
These coded instructions, statements, and computer programs contain
proprietary information of Nintendo of America Inc. and/or Nintendo
Company Ltd., and are protected by Federal copyright law. They may
not be disclosed to third parties or copied or duplicated in any form,
in whole or in part, without the prior written consent of Nintendo.
$Date:: $
$Rev$
$Author$
*---------------------------------------------------------------------------*/
#include <sysmenu/acsign.h>
#include "acmemory.h"
// SHA1
#include "sha.h"
#include "sha1dgst.c"
#define _DLENGTH_ (160/8)
#define _BLENGTH_ (512/8)
#define HASHContext SHA_CTX
#define HASHReset( _context ) (void)SHA1_Init( _context )
#define HASHSetSource( _context, _ptr, _len ) (void)SHA1_Update( _context, _ptr, _len )
#define HASHGetDigest( _context, _ptr ) (void)SHA1_Final( _ptr, _context )
// BN
#include "bn.h"
#include "bn_lib.c"
#include "bn_asm.c"
#include "bn_comba.c"
#include "bn_lsh.c"
#include "bn_rsh.c"
#include "bn_word.c"
#include "bn_add.c"
#include "bn_mul.c"
#include "bn_div.c"
#include "bn_exp.c"
#include "bn_sqr.c"
#include "bn_fm_w.c"
#include "bn_gcd.c"
#include "bn_ex_str.c"
#include "bn_ms_w.c"
//#include "bn_me.c"
#include "bn_rec.c"
#include "bn_mont.c"
#include "bn_recp.c"
#include "bn_wdiv.c"
#include "bn_r_exp.c"
#include "bn_m_exp.c"
#if !defined( RSA_ENC_DEC )
#define BER_NULL 5
#define BER_OBJECT 6
#define BER_SEQUENCE 16
#define BER_OCTET_STRING 4
#define BER_CONSTRUCTED 0x20
//
// rsa_padding_check_pkcs1_type_1ŠÖ<C5A0>Š“
//
static
int decode_padding( unsigned char* pdst_adrs, unsigned int* pdst_size,
unsigned char* psrc_adrs, unsigned int nsrc_size,
int length )
{
unsigned char* p;
unsigned char* q;
unsigned char* pe;
int i;
if (nsrc_size >= length )
return 0;
/* The leading 0 was removed by the bignum->bin conversion */
if (nsrc_size < 10)
return 0;
p = psrc_adrs;
pe = &(psrc_adrs[nsrc_size]);
/* if (p[0] != 0) goto err; */
if ( p[0] != 1 )
return 0;
p++;
for ( i = 0; i < 8; i++ )
{
if ( *(p++) != 0xFF )
return 0;
}
for ( ; p != pe; p++ )
{
if ( *p != 0xFF )
break;
}
if ( p == pe )
return 0;
if ( *(p++) != 0 )
return 0;
*pdst_size = (unsigned int)((int)pe - (int)p);
q = pdst_adrs;
while ( p != pe )
*(q++)= *(p++);
return 1;
}
//
//
//
static
int pk_skip( unsigned char **datap, unsigned int *dlenp,
unsigned char type, unsigned int *lenp)
{
unsigned char *data = *datap;
unsigned int dlen = *dlenp;
unsigned int len = 0;
unsigned char l;
if (*(data++) != type)
return 0;
if (dlen < 1)
return 0;
dlen--;
if ( (*data & 0x80) != 0 )
{
l = (unsigned char)( *data & 0x7F );
if (dlen < (unsigned int)l + 1)
return 0;
dlen -= l;
if (lenp != NULL)
{
data++;
do
{
len <<= 7;
len += (*data & 0x7f);
l--;
}
while (l > 0);
}
else
{
data += l;
}
}
else
{
len = *data;
data++;
if (dlen < 1)
return 0;
dlen--;
}
*datap = data;
*dlenp = dlen;
if (lenp != NULL)
{
*lenp = len;
}
return 1;
}
//
// PK_decode_sighashŠÖ<C5A0>Š“
//
static
int decode_sighash( unsigned char* data, unsigned int dlen,
unsigned char** ppdgst_adrs, unsigned int* pdgst_size,
unsigned char** pphash_adrs, unsigned int* phash_size )
{
#if 0
/* 01 */ OB_cmpu(BER_SEQUENCE, 0, 0),
/* 02 */ OB_down(0, 1),
/* 03 */ OB_cmpu(BER_SEQUENCE, 0, 0),
/* 04 */ OB_down(0, 1),
/* 05 */ OB_cmpu(BER_OBJECT, 0, 0),
/* 06 */ OB_call(OB_F_SET, PK_TYPE_SIG, PK_SIG_DIGEST_OID),
/* go up a level - we got all we need out of the
* sequence that contains the parameters
* - we could OB_next(0,1) and check that we have BER_NULL
* as then next item but there is no real need to do that
*/
/* 07 */ OB_up(0, 1),
/* 08 */ OB_next(0, 1),
/* 09 */ OB_cmpu(BER_OCTET_STRING, 0, 0),
/* 10 */ OB_call(OB_F_SET, PK_TYPE_SIG, PK_SIG_HASH),
/* 11 */ OB_exit(0),
/* 12 */ OB_FINISH,
#endif
unsigned int len;
if ( !pk_skip(&data, &dlen, (BER_SEQUENCE|BER_CONSTRUCTED), NULL) )
return 0;
if ( !pk_skip(&data, &dlen, (BER_SEQUENCE|BER_CONSTRUCTED), NULL) )
return 0;
if ( !pk_skip(&data, &dlen, (BER_OBJECT), &len) )
return 0;
/*
if (digest != NULL)
{
digest->adrs = data;
digest->size = len;
}
*/
if ( ppdgst_adrs ) *ppdgst_adrs = data;
if ( pdgst_size ) *pdgst_size = len;
data += len;
if (dlen < len)
return 0;
dlen -= len;
if ( !pk_skip(&data, &dlen, BER_NULL, &len) )
return 0;
data += len;
if (dlen < len)
return 0;
dlen -= len;
if ( !pk_skip(&data, &dlen, (BER_OCTET_STRING), &len) )
return 0;
/*
if (hash != NULL)
{
hash->adrs = data;
hash->size = len;
}
*/
if ( pphash_adrs ) *pphash_adrs = data;
if ( phash_size ) *phash_size = len;
return 1;
}
#endif
//
#define SGN_LEN 128
#define MOD_LEN 128
#define EXP_LEN 3
int ACSign_Decrypto(
void* buffer, // <20>o—͗̈æ
void* sgn_ptr, // ƒf<C692>[ƒ^‚ւ̃|ƒCƒ“ƒ^
void* key_ptr // ƒL<C692>[‚ւ̃|ƒCƒ“ƒ^
)
{
BN_CTX* ctx;
BIGNUM src, dst, exp, mod;
void* exp_ptr;
void* mod_ptr;
int nTmp, nWrk;
unsigned char* pAdrs = 0;
unsigned int nSize = 0;
unsigned long nDummyExp = 0x00010001; // 65537ŒÅè
unsigned long aBufferA[ 256 / sizeof (unsigned long) ];
unsigned long aBufferB[ 256 / sizeof (unsigned long) ];
if ( !buffer ) return 0;
if ( !sgn_ptr ) return 0;
if ( !key_ptr ) return 0;
//
// ACMemory_Clear( );
//
exp_ptr = &nDummyExp;
mod_ptr = key_ptr;
(void)ACMemory_Memset( aBufferA, 0, sizeof aBufferA );
(void)ACMemory_Memset( aBufferB, 0, sizeof aBufferB );
ctx=BN_CTX_new();
BN_init( &src );
BN_init( &dst );
BN_init( &exp );
BN_init( &mod );
(void)BN_bin2bn( sgn_ptr, SGN_LEN, &src );
(void)BN_bin2bn( exp_ptr, EXP_LEN, &exp );
(void)BN_bin2bn( mod_ptr, MOD_LEN, &mod );
nTmp = BN_mod_exp( &dst, &src, &exp, &mod, ctx );
nTmp = BN_bn2bin( &dst, (unsigned char*)aBufferA );
BN_free( &src );
BN_free( &dst );
BN_free( &exp );
BN_free( &mod );
if (ctx != NULL)
BN_CTX_free(ctx);
#if defined( RSA_ENC_DEC )
pAdrs = (unsigned char*)aBufferA + 4; //ƒ_ƒ~<7E>[•”SƒoƒCƒgÍ“ÇÝ”òε
nSize = nTmp;
(void)ACMemory_Memcpy( buffer, pAdrs, _DLENGTH_ * 4 );
#else
if ( !decode_padding( (unsigned char*)aBufferB, (unsigned int*)&nWrk, (unsigned char*)aBufferA, (unsigned int )nTmp, SGN_LEN ) )
return 0;
if ( !decode_sighash( (unsigned char*)aBufferB, (unsigned int)nWrk, NULL, NULL, (unsigned char**)&pAdrs, (unsigned int*)&nSize ) )
return 0;
if ( nSize != _DLENGTH_ )
return 0;
(void)ACMemory_Memcpy( buffer, pAdrs, _DLENGTH_ * 1 );
#endif
return 1;
}
//
#define ROMH_SIZE 0x0160
int ACSign_Digest(
void* buffer, // <20>o—͗̈æ
void* romh_ptr, // ƒf<C692>[ƒ^‚ւ̃|ƒCƒ“ƒ^
void* mbin_ptr, // ƒf<C692>[ƒ^‚ւ̃|ƒCƒ“ƒ^
int mbin_len, // ƒf<C692>[ƒ^‚Ì’·‚³
void* sbin_ptr, // ƒf<C692>[ƒ^‚ւ̃|ƒCƒ“ƒ^
int sbin_len, // ƒf<C692>[ƒ^‚Ì’·‚³
u32 serial_num // ƒVƒŠƒAƒƒiƒ“ƒo<C692>[
)
{
#if defined( RSA_ENC_DEC )
HASHContext context;
if ( !buffer ) return 0;
if ( !romh_ptr ) return 0;
if ( !mbin_ptr || !mbin_len ) return 0;
if ( !sbin_ptr || !sbin_len ) return 0;
HASHReset( &context );
HASHSetSource( &context, romh_ptr, ROMH_SIZE );
HASHGetDigest( &context, (unsigned char*)buffer + _DLENGTH_ * 0 );
HASHReset( &context );
HASHSetSource( &context, mbin_ptr, mbin_len );
HASHGetDigest( &context, (unsigned char*)buffer + _DLENGTH_ * 1 );
HASHReset( &context );
HASHSetSource( &context, sbin_ptr, sbin_len );
HASHGetDigest( &context, (unsigned char*)buffer + _DLENGTH_ * 2 );
HASHReset( &context );
HASHSetSource( &context, buffer, _DLENGTH_ * 3 );
HASHGetDigest( &context, (unsigned char*)buffer + _DLENGTH_ * 3 );
#else
HASHContext context;
unsigned char aBuffer[ (_DLENGTH_ * 3 + sizeof (unsigned long)) ];
if ( !buffer ) return 0;
if ( !romh_ptr ) return 0;
if ( !mbin_ptr || !mbin_len ) return 0;
if ( !sbin_ptr || !sbin_len ) return 0;
HASHReset( &context );
HASHSetSource( &context, romh_ptr, ROMH_SIZE );
HASHGetDigest( &context, (unsigned char*)aBuffer + _DLENGTH_ * 0 );
HASHReset( &context );
HASHSetSource( &context, mbin_ptr, mbin_len );
HASHGetDigest( &context, (unsigned char*)aBuffer + _DLENGTH_ * 1 );
HASHReset( &context );
HASHSetSource( &context, sbin_ptr, sbin_len );
HASHGetDigest( &context, (unsigned char*)aBuffer + _DLENGTH_ * 2 );
// ƒVƒŠƒAƒ”Ô<E2809D>†•ª <20>¡ÍOŒÅè
aBuffer[ (_DLENGTH_ * 3) + 0 ] = (unsigned char)((serial_num >> 0) & 0xFF);
aBuffer[ (_DLENGTH_ * 3) + 1 ] = (unsigned char)((serial_num >> 8) & 0xFF);
aBuffer[ (_DLENGTH_ * 3) + 2 ] = (unsigned char)((serial_num >> 16) & 0xFF);
aBuffer[ (_DLENGTH_ * 3) + 3 ] = (unsigned char)((serial_num >> 24) & 0xFF);
HASHReset( &context );
HASHSetSource( &context, (unsigned char*)aBuffer, _DLENGTH_ * 3 + sizeof (unsigned long) );
HASHGetDigest( &context, (unsigned char*)buffer );
#endif
return 1;
}
//
int ACSign_Compare(
void* decrypto, // ACSign_DecryptoÌ<E2809A>o—Í
void* digest // ACSign_DigestÌ<E2809A>o—Í
)
{
unsigned char* ptrA = (unsigned char*)decrypto;
unsigned char* ptrB = (unsigned char*)digest;
int loop;
int test = 1;
if ( !decrypto ) return 0;
if ( !digest ) return 0;
#if defined( RSA_ENC_DEC )
for ( loop = 0; loop < _DLENGTH_ * 4; loop++ )
#else
for ( loop = 0; loop < _DLENGTH_ * 1; loop++ )
#endif
{
if ( *ptrA++ != *ptrB++ )
{
test = 0;
break;
}
}
return test;
}