From 4edd07be02d73f0ad036484787cf62ed445b45c2 Mon Sep 17 00:00:00 2001 From: "(no author)" <(no author)@ff987cc8-cf2f-4642-8568-d52cce064691> Date: Tue, 22 Dec 2009 12:12:54 +0000 Subject: [PATCH] =?UTF-8?q?=E3=83=BBTestECDSA=E3=82=92=E8=BF=BD=E5=8A=A0?= =?UTF-8?q?=E3=81=97=E3=80=81=E3=83=87=E3=83=90=E3=82=A4=E3=82=B9=E9=8D=B5?= =?UTF-8?q?=E3=83=9A=E3=82=A2=E3=81=AEECDSA=E3=83=86=E3=82=B9=E3=83=88?= =?UTF-8?q?=E3=82=92=E8=A1=8C=E3=81=86=E3=82=88=E3=81=86=E5=A4=89=E6=9B=B4?= =?UTF-8?q?=E3=80=82=20=E3=83=BB=E3=83=87=E3=83=90=E3=82=A4=E3=82=B9?= =?UTF-8?q?=E8=A8=BC=E6=98=8E=E6=9B=B8=E3=81=AE=E5=90=84=E7=A8=AE=E3=83=91?= =?UTF-8?q?=E3=83=A9=E3=83=A1=E3=83=BC=E3=82=BF=E3=81=AE=E3=82=BB=E3=83=83?= =?UTF-8?q?=E3=83=88=E3=82=92=E8=A1=8C=E3=81=86=E3=82=88=E3=81=86=E5=A4=89?= =?UTF-8?q?=E6=9B=B4=E3=80=82=EF=BC=88ECDSA=E7=BD=B2=E5=90=8D=E3=81=AE?= =?UTF-8?q?=E3=81=BF=E6=9C=AA=E5=AE=9F=E8=A3=85=EF=BC=89?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit git-svn-id: file:///Volumes/Transfer/gigaleak_20231201/2020-09-30%20-%20paladin.7z/paladin/ctr_eFuse@36 ff987cc8-cf2f-4642-8568-d52cce064691 --- cr_deviceCert.c | 262 ++++++++++++++++----------------------- cr_generate_id.c | 20 +-- cr_generate_id_private.h | 3 +- cr_keyPair.c | 36 ++++++ 4 files changed, 154 insertions(+), 167 deletions(-) diff --git a/cr_deviceCert.c b/cr_deviceCert.c index 24c703e..8c203f1 100644 --- a/cr_deviceCert.c +++ b/cr_deviceCert.c @@ -137,127 +137,102 @@ #include "cr_generate_id_private.h" #include "cr_alloc.h" -#define CR_CERT_EXPIRE_SECS ( 60*60*24*365* 20 ) // デバイス証明書期限=20年 +#define CR_CERT_EXPIRE_SECS ( 60*60*24*365* 20 ) // デバイス証明書期限 20年 ※うるう年は無視 -#define CA_FILE "dummyCA/NintendoCTR2_dummy.crt" -#define CA_KEY "dummyCA/NintendoCTR2_priv_dummy.pem" +// TWL device cert base +typedef struct CR_DeviceCert +{ + u8 sigType [ 4 ]; // 0x000 - 0x003 : 0x00010005, signature type is ECDSA + SHA256 + u8 eccSignature[ 60 ]; // 0x004 - 0x03F : ECDSA using SHA-1 and CA key + u8 padding0 [ 64 ]; // 0x040 - 0x07F : zero-filled + u8 issuerName [ 64 ]; // 0x080 - 0x0BF : issuer name, "Root-CA00000002-MS00000008" + u8 keyType [ 4 ]; // 0x0C0 - 0x0C3 : 0x00000002, cert public key type is ECC233 + u8 subject [ 64 ]; // 0x0C4 - 0x103 : subject field, "CTxxxxxxxx-yy" + u32 expiryDate; // 0x104 - 0x107 : second from Epoch (Jan 1, 1970 00:00) + u8 eccPubKey [ 60 ]; // 0x108 - 0x143 : cert public key (openssl sect233r1) + u8 padding1 [ 60 ]; // 0x144 - 0x17F : zero-filled +} CR_DeviceCert; const char *issuerNameDev = "NintendoCA - G2_NintendoCTR2dev"; const char *issuerNameProd = "NintendoCA - G2_NintendoCTR2prod"; -// TWL device cert base -typedef struct CTR_Device_Cert -{ - u8 sigType[ 4 ]; // 0x000 - 0x003 : 0x00010002, signature type is ECDSA - u8 eccSignature[ 60 ]; // 0x004 - 0x03F : ECDSA using SHA-1 and CA key - u8 padding0[ 64 ]; // 0x040 - 0x07F : zero-filled - u8 issuerName[ 64 ]; // 0x080 - 0x0BF : issuer name, "Root-CA00000002-MS00000008" - u8 keyType[ 4 ]; // 0x0C0 - 0x0C3 : 0x00000002, cert public key type is ECC233 - u8 subject[ 64 ]; // 0x0C4 - 0x103 : subject field, "CTxxxxxxxx-yyyyyyyyyyyyyyyy" - u32 expiryDate; // 0x104 - 0x107 : second from Epoch (Jan 1, 1970 00:00) - u8 eccPubKey[ 60 ]; // 0x108 - 0x143 : cert public key (openssl sect233r1) - u8 padding1[ 60 ]; // 0x144 - 0x17F : zero-filled -} CTR_Device_Cert; +static void BN2BinWithPadding( BIGNUM *pBn, u8 *pDst, int dstLen ); -// 鍵ペアをECDSAで検証(FuseIDに切り出したpubkeyのみを使用して署名検証) -static int TestECDSA2( EC_KEY *eckey, int ec_curve_name, u8 ec_pub_key_neg, u8 ec_pub_key_num_bytes, u8 *ec_pub_key ) -{ -#define CR_ECDSA_BUF_SIZE 32 -#define CR_ECDSA_SIGN_BUF_SIZE 256 - - BN_CTX *ctx = NULL; - BIGNUM *bn_pubkey = NULL; - EC_KEY *test_key = NULL; - EC_POINT *point_pubkey = NULL; - unsigned char buf[256]; - - unsigned char ecdsa_test_buf[CR_ECDSA_BUF_SIZE]; - unsigned char ecdsasig[CR_ECDSA_SIGN_BUF_SIZE]; - unsigned int ecdsasiglen = 0; - int test_ret = 0; - int ret_code = 0; - int i; - - // 署名作成 - for( i = 0 ; i < CR_ECDSA_BUF_SIZE ; i++ ) { - ecdsa_test_buf[i] = (u8)(0xff & i ); - } - memset(ecdsasig, 0, CR_ECDSA_SIGN_BUF_SIZE); - - test_ret = ECDSA_sign(0, ecdsa_test_buf, CR_ECDSA_BUF_SIZE, ecdsasig, - &ecdsasiglen, eckey); - if (test_ret == 0) { - ret_code = CR_GENID_ERROR_ECDSA_SIGN; - goto end; - } - - // 署名検証 - if( ( ctx = BN_CTX_new() ) == NULL ) { - ret_code = CR_GENID_ERROR_BN_CTX_NEW; - goto end; - } - if( ( bn_pubkey = BN_new() ) == NULL ) { - ret_code = CR_GENID_ERROR_BN_NEW_2; - goto end; - } - if( ( test_key = EC_KEY_new_by_curve_name( ec_curve_name ) ) == NULL) { - ret_code = CR_GENID_ERROR_EC_KEY_NEW_1; - goto end; - } - if( ( point_pubkey = EC_POINT_new( test_key->group ) ) == NULL ) { - ret_code = CR_GENID_ERROR_EC_POINT_NEW; - goto end; - } - memset( buf, 0, sizeof(buf) ); - if( ec_pub_key_neg ) { - // 負数の場合、先頭はそのまま - memcpy( buf, ec_pub_key, ec_pub_key_num_bytes ); - }else { - // 正の数の場合、先頭に0x00をパディングして、サイズを1増やす - memcpy( &buf[1], ec_pub_key, ec_pub_key_num_bytes ); - ec_pub_key_num_bytes++; - } - (void)BN_bin2bn( buf, ec_pub_key_num_bytes, bn_pubkey ); - - (void)EC_POINT_bn2point( test_key->group, bn_pubkey, point_pubkey , ctx ); - EC_KEY_set_public_key( test_key, point_pubkey ); - test_ret = ECDSA_verify( 0, ecdsa_test_buf, CR_ECDSA_BUF_SIZE, ecdsasig, ecdsasiglen, test_key ); - if( test_ret != 1) { - ret_code = CR_GENID_ERROR_ECDSA_VERIFY; - } - -end: - if( ctx ) BN_CTX_free( ctx ); - if( bn_pubkey ) BN_free( bn_pubkey ); - if( test_key ) EC_KEY_free( test_key ); - if( point_pubkey ) EC_POINT_free( point_pubkey ); - - return ret_code; -} // create CTR Device cert -int GenerateCTRDeviceCert( EC_KEY *eckey, u32 deviceId, u8 bondingOption ) +int GenerateCTRDeviceCert( EC_KEY *pECkey, u32 deviceId, u8 bondingOption, u8 *pDevCerSign, u32 *pExpiryDate ) { int ret_code = 0; - char str[80]; - CTR_Device_Cert cert; + CR_DeviceCert deviceCert; EC_KEY *NintendoCTR2 = NULL; - - if ( sizeof( CTR_Device_Cert ) > 384 ) + + if ( sizeof( CR_DeviceCert ) > 384 ) { printf( "err.\n" ); //ret_code = CR_GENID_ERROR_CERT_BUF_SIZE; // ATODE ret_code = 255; goto end; } - + + memset( &deviceCert, 0, sizeof(deviceCert) ); + + // sigType 0x00010005 ECDSA+SHA256 + deviceCert.sigType[0] = 0x00; + deviceCert.sigType[1] = 0x01; + deviceCert.sigType[2] = 0x00; + deviceCert.sigType[3] = 0x05; + + // issuerName + memcpy( deviceCert.issuerName, + bondingOption ? issuerNameDev : issuerNameProd, + bondingOption ? strlen( issuerNameDev ) : strlen( issuerNameProd ) ); + + // keyType 0x00000002 ECC233 + deviceCert.keyType[0] = 0x00; + deviceCert.keyType[1] = 0x00; + deviceCert.keyType[2] = 0x00; + deviceCert.keyType[3] = 0x02; + + // subject : CT + deviceID + BondingOption + sprintf( deviceCert.subject, "CT%08X-%02X", (unsigned int)deviceId, bondingOption ); + + // expiryDate +20years + *pExpiryDate += CR_CERT_EXPIRE_SECS; // ID_BUFにも証明書期限をセットする。 + deviceCert.expiryDate = *pExpiryDate; +#if 0 + { + struct tm *tmt; + tmt = gmtime( &deviceCert.expiryDate ); + printf("GMT:%d-%02d-%02d %02d:%02d:%02d\n", + tmt->tm_year+1900, tmt->tm_mon+1, tmt->tm_mday, tmt->tm_hour, tmt->tm_min, tmt->tm_sec ); + } +#endif + + // eccPubKey + BN2BinWithPadding( &pECkey->pub_key->X, &deviceCert.eccPubKey[ 0 ], 30 ); + BN2BinWithPadding( &pECkey->pub_key->Y, &deviceCert.eccPubKey[ 30 ], 30 ); +#if 0 + DEBUG_PRINT_ARRAY( "eccPubKey:", (const char *)deviceCert.eccPubKey, 60 ); + DEBUG_PRINT_ARRAY( "eccPubKey.X:", (const char *)pECkey->pub_key->X.d, pECkey->pub_key->X.dmax * 4 ); + DEBUG_PRINT_ARRAY( "eccPubKey.Y:", (const char *)pECkey->pub_key->Y.d, pECkey->pub_key->Y.dmax * 4 ); +#endif + + // signature +#ifdef USE_HSM + +#else // !USE_HSM +#if 0 + BIGNUM *bn_pubkey = NULL; + u8 ec_pub_key_neg; + u8 ec_pub_key_num_bytes; + u8 ec_pub_key[78]; + // DERフォーマットのECC鍵を読み込み { // bondingOptionによって、鍵を差し替え const unsigned char *der_priv = bondingOption ? cr_NintendoCTR2_priv_dummy_dev : cr_NintendoCTR2_priv_dummy_prod; const unsigned char *der_pub = bondingOption ? cr_NintendoCTR2_pub_dummy_dev : cr_NintendoCTR2_pub_dummy_prod; int priv_len = der_priv[ 8 ] | der_priv[ 9 ] << 8; // KEY長を取り出し -// int pub_len = der_pub [ 8 ] | der_pub [ 9 ] << 8; // 同上 der_priv += 0x10; // ヘッダ部分を除外してKEY実体を指定 der_pub += 0x10; // 同上 @@ -274,51 +249,7 @@ int GenerateCTRDeviceCert( EC_KEY *eckey, u32 deviceId, u8 bondingOption ) DEBUG_PRINT_ARRAY( "EC pub.Y:", (const char *)NintendoCTR2->pub_key->Y.d, NintendoCTR2->pub_key->Y.dmax * 4 ); #endif } - // sigType - cert.sigType[0] = 0x00; - cert.sigType[1] = 0x01; - cert.sigType[2] = 0x00; - cert.sigType[3] = 0x02; - // issuerName - memcpy( cert.issuerName, issuerNameDev, strlen( issuerNameDev ) ); - - // keyType - cert.keyType[0] = 0x00; - cert.keyType[1] = 0x00; - cert.keyType[2] = 0x00; - cert.keyType[3] = 0x01; - - // subject : CT + deviceID + BondingOption - sprintf( str, "CT%08X%02X", (unsigned int)deviceId, bondingOption ); - memcpy( cert.subject, str, strlen( str ) ); - - // expiryDate -#ifdef USE_HSM - ret_code = hsm_get_rtc( &(cert.expiryDate) ); - if ( ret_code != 0 ) - { - printf( "error(%d) : hsm_get_rtc\n", ret_code ); - goto end; - } -#else // !USE_HSM - { - struct timeval tv; - struct timezone tz; - gettimeofday(&tv,&tz); - cert.expiryDate = tv.tv_sec; - } -#endif // USE_HSM - - // signature -#ifdef USE_HSM - -#else // !USE_HSM - BIGNUM *bn_pubkey = NULL; - u8 ec_pub_key_neg; - u8 ec_pub_key_num_bytes; - u8 ec_pub_key[78]; - bn_pubkey = BN_new(); if( bn_pubkey == NULL ) { ret_code = CR_GENID_ERROR_BN_NEW_1; @@ -339,42 +270,42 @@ int GenerateCTRDeviceCert( EC_KEY *eckey, u32 deviceId, u8 bondingOption ) BN_free( bn_pubkey ); - ret_code = TestECDSA2( eckey, NID_sect233r1, ec_pub_key_neg, - ec_pub_key_num_bytes, ec_pub_key ); +// ret_code = TestECDSA2( eckey, NID_sect233r1, ec_pub_key_neg, +// ec_pub_key_num_bytes, ec_pub_key ); if ( ret_code != 0 ) { printf( "error(%d) : TestECDSA2\n", ret_code ); goto end; } - +#endif #endif // USE_HSM #if 0 if ( cr_print_flag ) { int i; - printf( "CTR custom cert\n" ); - printf( "sigType : 0x%08X\n", *(unsigned int*)cert->sigType ); - DEBUG_PRINT_ARRAY( "eccSignature:", (const char *)cert->eccSignature, sizeof(cert->eccSignature) ); - DEBUG_PRINT_ARRAY( "padding0:", (const char *)cert->padding0, sizeof(cert->padding0) ); + printf( "CTR custom deviceCert\n" ); + printf( "sigType : 0x%08X\n", *(unsigned int*)deviceCert->sigType ); + DEBUG_PRINT_ARRAY( "eccSignature:", (const char *)deviceCert->eccSignature, sizeof(deviceCert->eccSignature) ); + DEBUG_PRINT_ARRAY( "padding0:", (const char *)deviceCert->padding0, sizeof(deviceCert->padding0) ); printf( "issuerName : " ); - for ( i = 0; i < sizeof(cert->issuerName); i++ ) printf( "%c", cert->issuerName[i] ); + for ( i = 0; i < sizeof(deviceCert->issuerName); i++ ) printf( "%c", deviceCert->issuerName[i] ); printf( "\n" ); - printf( "keyType : 0x%08X\n", *(unsigned int*)cert->keyType ); + printf( "keyType : 0x%08X\n", *(unsigned int*)deviceCert->keyType ); printf( "subject : " ); - for ( i = 0; i < sizeof(cert->subject); i++ ) printf( "%c", cert->subject[i] ); + for ( i = 0; i < sizeof(deviceCert->subject); i++ ) printf( "%c", deviceCert->subject[i] ); printf( "\n" ); - printf( "expiryDate : 0x%08X\n", (unsigned int)cert->expiryDate ); - DEBUG_PRINT_ARRAY( "eccPubKey :", (const char *)cert->eccPubKey, sizeof(cert->eccPubKey) ); - DEBUG_PRINT_ARRAY( "padding1:", (const char *)cert->padding1, sizeof(cert->padding1) ); + printf( "expiryDate : 0x%08X\n", (unsigned int)deviceCert->expiryDate ); + DEBUG_PRINT_ARRAY( "eccPubKey :", (const char *)deviceCert->eccPubKey, sizeof(deviceCert->eccPubKey) ); + DEBUG_PRINT_ARRAY( "padding1:", (const char *)deviceCert->padding1, sizeof(deviceCert->padding1) ); // 証明書の書き込みテスト FILE *fp; char fn[256]; sprintf( fn, "output/0x%08x.crt", (unsigned int)deviceId ); fp = fopen( fn, "w" ); - fwrite( cert, sizeof( CTR_Device_Cert ), 1, fp ); - fclose( fp ); + fwrite( deviceCert, sizeof( CR_DeviceCert ), 1, fp ); + fclose( fp ); } #endif @@ -383,5 +314,20 @@ end: if( NintendoCTR2 ) EC_KEY_free( NintendoCTR2 ); return ret_code; -} // generate_CTRCustom_cert +} // generate_CTRCustom_deviceCert + +// 指定BIGNUMを指定長 +static void BN2BinWithPadding( BIGNUM *pBN, u8 *pDst, int dstLen ) +{ + int i; + int bnBitLen, bnByteLen; + u8 buffer[ 32 ]; + memset( buffer, 0, sizeof(buffer) ); + bnBitLen = BN_num_bits( pBN ); + bnByteLen = ( bnBitLen / 8 ) + ( ( bnBitLen % 8 ) ? 1 : 0 ); + BN_bn2bin( pBN, (u8*)buffer ); + for( i = 0; i < bnByteLen; i++ ) { + pDst[ dstLen - 1 - i ] = buffer[ bnByteLen - 1 - i ]; + } +} diff --git a/cr_generate_id.c b/cr_generate_id.c index 458da8c..d98cde8 100644 --- a/cr_generate_id.c +++ b/cr_generate_id.c @@ -202,7 +202,7 @@ int cr_generate_id( u32 serial[CR_NUM_OF_SERIAL], u8 id_buf[CR_ID_BUF_SIZE], u8 int i; int ret_code; CR_ID_BUFFER *cr_id_buf; - EC_KEY *my_eckey = NULL; + EC_KEY *deviceKeyPair = NULL; if( sizeof(CR_ID_BUFFER) != 256 ) { ret_code = CR_GENID_ERROR_ID_BUF_SIZE; @@ -300,7 +300,7 @@ int cr_generate_id( u32 serial[CR_NUM_OF_SERIAL], u8 id_buf[CR_ID_BUF_SIZE], u8 //-------------------------------------------------------------- // 楕円曲線鍵ペアを生成 //-------------------------------------------------------------- - ret_code = GenarateECCKeyPair( &my_eckey, cr_id_buf->devicePrivKey ); + ret_code = GenarateECCKeyPair( &deviceKeyPair, cr_id_buf->devicePrivKey ); if ( ret_code != CR_GENID_SUCCESS ) { goto end; } @@ -308,15 +308,19 @@ int cr_generate_id( u32 serial[CR_NUM_OF_SERIAL], u8 id_buf[CR_ID_BUF_SIZE], u8 //-------------------------------------------------------------- // 生成した鍵ペアをECDSAで動作確認 //-------------------------------------------------------------- -#if 0 - ret_code = TestECDSA( hoge hoge ); - // 当然やるべき -#endif + ret_code = TestECDSA( deviceKeyPair ); + if ( ret_code != CR_GENID_SUCCESS ) { + goto end; + } //-------------------------------------------------------------- // デバイス証明書生成 + 署名の付与 + 証明書期限セット //-------------------------------------------------------------- - ret_code = GenerateCTRDeviceCert( my_eckey, cr_id_buf->serial[0], cr_id_buf->bondingOption ); + ret_code = GenerateCTRDeviceCert( deviceKeyPair, + cr_id_buf->serial[0], + cr_id_buf->bondingOption, + cr_id_buf->deviceCertSign, + &cr_id_buf->expiryDate ); if ( ret_code != CR_GENID_SUCCESS ) { goto end; } @@ -363,7 +367,7 @@ end: } // リソースの解放 - if ( my_eckey ) EC_KEY_free( my_eckey ); + if ( deviceKeyPair ) EC_KEY_free( deviceKeyPair ); ERR_remove_state(0); EVP_cleanup(); diff --git a/cr_generate_id_private.h b/cr_generate_id_private.h index 7682915..91e2797 100644 --- a/cr_generate_id_private.h +++ b/cr_generate_id_private.h @@ -184,7 +184,8 @@ typedef struct { extern int GetTimestamp( u8 *pYear, u8 *pMonth, u8 *pMday, u8 *pHour, u8 *pMin, u8 *pSec, time_t *pTime); extern int GenerateRandom( u8 *pDst, int length ); extern int GenarateECCKeyPair( EC_KEY **ppECkey, u8 *pECPrivkey ); -extern int GenerateCTRDeviceCert( EC_KEY *key, u32 deviceId, u8 bondingOption ); +extern int TestECDSA( EC_KEY *pECkey ); +extern int GenerateCTRDeviceCert( EC_KEY *pECkey, u32 deviceId, u8 bondingOption, u8 *pDevCerSign, u32 *pExpiryDate ); extern int EncryptID( unsigned char *dst_buf, unsigned char *org_buf, u8 bondingOption ); extern void DebugPrintArray( char *pStr, const u8 *pData, int length ); diff --git a/cr_keyPair.c b/cr_keyPair.c index cdf4314..ebe99a4 100644 --- a/cr_keyPair.c +++ b/cr_keyPair.c @@ -118,6 +118,7 @@ #include #include #include +#include #include "cr_generate_id.h" #include "cr_generate_id_private.h" @@ -267,3 +268,38 @@ static int generate_EC_public_key( EC_KEY *eckey ) } // generate_EC_public_key +// 鍵ペアをECDSAで検証 +int TestECDSA( EC_KEY *pECkey ) +{ +#define CR_ECDSA_BUF_SIZE 29 +#define CR_ECDSA_SIGN_BUF_SIZE 256 + + unsigned char ecdsa_test_buf[CR_ECDSA_BUF_SIZE]; + unsigned char ecdsasig[CR_ECDSA_SIGN_BUF_SIZE]; + unsigned int ecdsasiglen = 0; + int test_ret = 0; + int ret_code = 0; + int i; + + // 署名作成 + for( i = 0 ; i < CR_ECDSA_BUF_SIZE ; i++ ) { + ecdsa_test_buf[i] = (u8)(0xff & i ); + } + memset( ecdsasig, 0, CR_ECDSA_SIGN_BUF_SIZE ); + + test_ret = ECDSA_sign( 0, ecdsa_test_buf, CR_ECDSA_BUF_SIZE, ecdsasig, + &ecdsasiglen, pECkey ); + if (test_ret == 0) { + ret_code = CR_GENID_ERROR_ECDSA_SIGN; + goto end; + } + + test_ret = ECDSA_verify( 0, ecdsa_test_buf, CR_ECDSA_BUF_SIZE, ecdsasig, ecdsasiglen, pECkey ); + if( test_ret != 1) { + ret_code = CR_GENID_ERROR_ECDSA_VERIFY; + goto end; + } + +end: + return ret_code; +}