mirror of
https://github.com/rvtr/ctr_eFuse.git
synced 2025-11-02 00:11:04 -04:00
デバッグプリントの整理。
generate_id内ではSFMTを使用しないよう変更。(通常のrandを使用) git-svn-id: file:///Volumes/Transfer/gigaleak_20231201/2020-09-30%20-%20paladin.7z/paladin/ctr_eFuse@10 ff987cc8-cf2f-4642-8568-d52cce064691
This commit is contained in:
parent
27a69561bb
commit
19d5af715d
@ -325,14 +325,6 @@ int crypto_rsa_enc_dec( unsigned char *dst_buf,unsigned char *org_buf )
|
|||||||
for ( i = 0; i < sizeof( enc_iv.iv.generic256.iv.bytes ); i++ )
|
for ( i = 0; i < sizeof( enc_iv.iv.generic256.iv.bytes ); i++ )
|
||||||
enc_iv.iv.generic256.iv.bytes[i] = dec_iv.iv.generic256.iv.bytes[i] = i;
|
enc_iv.iv.generic256.iv.bytes[i] = dec_iv.iv.generic256.iv.bytes[i] = i;
|
||||||
|
|
||||||
for ( i = 0; i < 256; i++ )
|
|
||||||
{
|
|
||||||
if ( i % 16 == 0 )
|
|
||||||
printf( "\n" );
|
|
||||||
printf( "0x%02X ", org_buf[i] );
|
|
||||||
}
|
|
||||||
printf( "\n" );
|
|
||||||
|
|
||||||
// encrypt
|
// encrypt
|
||||||
cmd.cmd = Cmd_Encrypt;
|
cmd.cmd = Cmd_Encrypt;
|
||||||
cmd.args.encrypt.flags = Cmd_Encrypt_Args_flags_given_iv_present;
|
cmd.args.encrypt.flags = Cmd_Encrypt_Args_flags_given_iv_present;
|
||||||
|
|||||||
422
cr_generate_id.c
422
cr_generate_id.c
@ -144,15 +144,12 @@
|
|||||||
#include "cr_generate_id_private.h"
|
#include "cr_generate_id_private.h"
|
||||||
#include "cr_alloc.h"
|
#include "cr_alloc.h"
|
||||||
|
|
||||||
// #define DEBUG_PRINT 1
|
|
||||||
|
|
||||||
#define CR_GEN_ID_VERSION 1
|
#define CR_GEN_ID_VERSION 1
|
||||||
#define CR_NUM_OF_SERIAL 5
|
#define CR_NUM_OF_SERIAL 5
|
||||||
#define CR_RSV_LENGTH 0x0C
|
#define CR_RSV_LENGTH 0x0C
|
||||||
#define CR_RANDOM_LENGTH 0x50
|
#define CR_RANDOM_LENGTH 0x50
|
||||||
#define EC_PRIVATE_KEY_LENGTH 0x20
|
#define EC_PRIVATE_KEY_LENGTH 0x20
|
||||||
#define ECDSA_SIGN_LENGTH 0x44
|
#define ECDSA_SIGN_LENGTH 0x44
|
||||||
//#define SHA256_DIGEST_LENGTH 0x20 // OpenSSL側で定義済み
|
|
||||||
#define EC_CURVE_NAME NID_sect233r1
|
#define EC_CURVE_NAME NID_sect233r1
|
||||||
|
|
||||||
#define CA_FILE "dummyCA/NintendoCTR2_dummy.crt"
|
#define CA_FILE "dummyCA/NintendoCTR2_dummy.crt"
|
||||||
@ -220,15 +217,15 @@ certEntry certEntries[ENTRY_COUNT] =
|
|||||||
// TWL device cert base
|
// TWL device cert base
|
||||||
typedef struct CTR_Device_Cert
|
typedef struct CTR_Device_Cert
|
||||||
{
|
{
|
||||||
u8 sigType[4]; // 0x000 - 0x003 : 0x00010002, signature type is ECDSA
|
u8 sigType[ 4 ]; // 0x000 - 0x003 : 0x00010002, signature type is ECDSA
|
||||||
u8 eccSignature[60]; // 0x004 - 0x03F : ECDSA using SHA-1 and CA key
|
u8 eccSignature[ 60 ]; // 0x004 - 0x03F : ECDSA using SHA-1 and CA key
|
||||||
u8 padding0[64]; // 0x040 - 0x07F : zero-filled
|
u8 padding0[ 64 ]; // 0x040 - 0x07F : zero-filled
|
||||||
u8 issuerName[64]; // 0x080 - 0x0BF : issuer name, "Root-CA00000002-MS00000008"
|
u8 issuerName[ 64 ]; // 0x080 - 0x0BF : issuer name, "Root-CA00000002-MS00000008"
|
||||||
u8 keyType[4]; // 0x0C0 - 0x0C3 : 0x00000002, cert public key type is ECC233
|
u8 keyType[ 4 ]; // 0x0C0 - 0x0C3 : 0x00000002, cert public key type is ECC233
|
||||||
u8 subject[64]; // 0x0C4 - 0x103 : subject field, "CTxxxxxxxx-yyyyyyyyyyyyyyyy"
|
u8 subject[ 64 ]; // 0x0C4 - 0x103 : subject field, "CTxxxxxxxx-yyyyyyyyyyyyyyyy"
|
||||||
u32 expiryDate; // 0x104 - 0x107 : second from Epoch (Jan 1, 1970 00:00)
|
u32 expiryDate; // 0x104 - 0x107 : second from Epoch (Jan 1, 1970 00:00)
|
||||||
u8 eccPubKey[60]; // 0x108 - 0x143 : cert public key (openssl sect233r1)
|
u8 eccPubKey[ 60 ]; // 0x108 - 0x143 : cert public key (openssl sect233r1)
|
||||||
u8 padding1[60]; // 0x144 - 0x17F : zero-filled
|
u8 padding1[ 60 ]; // 0x144 - 0x17F : zero-filled
|
||||||
} CTR_Device_Cert;
|
} CTR_Device_Cert;
|
||||||
|
|
||||||
|
|
||||||
@ -239,7 +236,7 @@ typedef struct {
|
|||||||
(本ID+randomの先頭0x1C bytesを組み合わせて、デバイス秘密鍵とする。)
|
(本ID+randomの先頭0x1C bytesを組み合わせて、デバイス秘密鍵とする。)
|
||||||
0x08 - 0x0F 64bit CTR番号 seed
|
0x08 - 0x0F 64bit CTR番号 seed
|
||||||
(34bitのみ使用。1~4の乱数カウントアップ)
|
(34bitのみ使用。1~4の乱数カウントアップ)
|
||||||
0x10 - 0x17 64bit 予備ID
|
0x10 - 0x17 64bit 予備ID
|
||||||
(64bitフルに使用。1~0x100000000の乱数カウントアップ)
|
(64bitフルに使用。1~0x100000000の乱数カウントアップ)
|
||||||
*/
|
*/
|
||||||
u8 version; /* 0x18 = CR_GEN_ID_VERSION = 1 */
|
u8 version; /* 0x18 = CR_GEN_ID_VERSION = 1 */
|
||||||
@ -251,9 +248,9 @@ typedef struct {
|
|||||||
u8 min; /* 0x1E */
|
u8 min; /* 0x1E */
|
||||||
u8 sec; /* 0x1F */
|
u8 sec; /* 0x1F */
|
||||||
u8 devicePrivKey[ EC_PRIVATE_KEY_LENGTH ];
|
u8 devicePrivKey[ EC_PRIVATE_KEY_LENGTH ];
|
||||||
/* 0x20 - 0x3F ECC233 private key (big endian) ユニーク性保証なし */
|
/* 0x20 - 0x3F ECC233 private key (big endian) ユニーク性保証なし */
|
||||||
u8 deviceCertSign[ ECDSA_SIGN_LENGTH ];
|
u8 deviceCertSign[ ECDSA_SIGN_LENGTH ];
|
||||||
/* 0x40 - 0x83 ECC233 ECDSA signature (big endian) */
|
/* 0x40 - 0x83 ECC233 ECDSA signature (big endian) */
|
||||||
u8 reserved[ CR_RSV_LENGTH ]; /* 0x84 - 0x8F 予約 */
|
u8 reserved[ CR_RSV_LENGTH ]; /* 0x84 - 0x8F 予約 */
|
||||||
u8 random[ CR_RANDOM_LENGTH ]; /* 0x90 - 0xDF 乱数 */
|
u8 random[ CR_RANDOM_LENGTH ]; /* 0x90 - 0xDF 乱数 */
|
||||||
u8 hash[ SHA256_DIGEST_LENGTH ]; /* 0xE0 - 0xFF "0x00-0xDF"領域のSHA256ハッシュ */
|
u8 hash[ SHA256_DIGEST_LENGTH ]; /* 0xE0 - 0xFF "0x00-0xDF"領域のSHA256ハッシュ */
|
||||||
@ -266,12 +263,12 @@ typedef struct {
|
|||||||
s32 top; /* 0x0c - 0x0f */
|
s32 top; /* 0x0c - 0x0f */
|
||||||
s32 bottom; /* 0x10 - 0x13 */
|
s32 bottom; /* 0x10 - 0x13 */
|
||||||
|
|
||||||
/* #define ERR_NUM_ERRORS 16 */
|
/* #define ERR_NUM_ERRORS 16 */
|
||||||
u32 err_buffer[ERR_NUM_ERRORS]; /* 0x14 - 0x17 .... 0x50 - 0x53 */
|
u32 err_buffer[ERR_NUM_ERRORS]; /* 0x14 - 0x17 .... 0x50 - 0x53 */
|
||||||
//#define ERR_GET_LIB(l) (int)((((unsigned long)l)>>24L)&0xffL)
|
//#define ERR_GET_LIB(l) (int)((((unsigned long)l)>>24L)&0xffL)
|
||||||
//#define ERR_GET_FUNC(l) (int)((((unsigned long)l)>>12L)&0xfffL)
|
//#define ERR_GET_FUNC(l) (int)((((unsigned long)l)>>12L)&0xfffL)
|
||||||
//#define ERR_GET_REASON(l) (int)((l)&0xfffL)
|
//#define ERR_GET_REASON(l) (int)((l)&0xfffL)
|
||||||
//#define ERR_FATAL_ERROR(l) (int)((l)&ERR_R_FATAL)
|
//#define ERR_FATAL_ERROR(l) (int)((l)&ERR_R_FATAL)
|
||||||
s32 err_line[ERR_NUM_ERRORS]; /* 0x54 - 0x57 .... 0x90 - 0x93 */
|
s32 err_line[ERR_NUM_ERRORS]; /* 0x54 - 0x57 .... 0x90 - 0x93 */
|
||||||
} CR_ERR_BUFFER;
|
} CR_ERR_BUFFER;
|
||||||
|
|
||||||
@ -295,7 +292,7 @@ static int generate_EC_private_key( EC_KEY *eckey, u8 *privKey )
|
|||||||
int i;
|
int i;
|
||||||
for ( i = 0; i < EC_PRIVATE_KEY_LENGTH; i++ )
|
for ( i = 0; i < EC_PRIVATE_KEY_LENGTH; i++ )
|
||||||
{
|
{
|
||||||
privKey[i] = (u8)gen_rand32();
|
privKey[i] = (u8)rand();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
#endif // USE_HSM
|
#endif // USE_HSM
|
||||||
@ -318,19 +315,7 @@ static int generate_EC_private_key( EC_KEY *eckey, u8 *privKey )
|
|||||||
(void)BN_bin2bn( privKey, EC_PRIVATE_KEY_LENGTH, bn_privkey );
|
(void)BN_bin2bn( privKey, EC_PRIVATE_KEY_LENGTH, bn_privkey );
|
||||||
eckey->priv_key = bn_privkey;
|
eckey->priv_key = bn_privkey;
|
||||||
|
|
||||||
#ifdef DEBUG_PRINT
|
DEBUG_PRINT_ARRAY( "ec private key:", (const char *)privKey, EC_PRIVATE_KEY_LENGTH );
|
||||||
if( cr_print_flag ) {
|
|
||||||
int i;
|
|
||||||
printf("ec private key:");
|
|
||||||
for( i = 0 ; i < EC_PRIVATE_KEY_LENGTH ; i++ ) {
|
|
||||||
if( (i%8) == 0 ) {
|
|
||||||
printf("\n ");
|
|
||||||
}
|
|
||||||
printf("0x%02x ", privKey[i] );
|
|
||||||
}
|
|
||||||
printf("\n");
|
|
||||||
}
|
|
||||||
#endif /* DEBUG_PRINT */
|
|
||||||
|
|
||||||
return ret_code;
|
return ret_code;
|
||||||
} // generate_EC_private_key
|
} // generate_EC_private_key
|
||||||
@ -594,17 +579,7 @@ static int generate_X509_cert( EVP_PKEY *evp_pkey, X509_REQ *req, X509 *cert, u3
|
|||||||
#endif
|
#endif
|
||||||
|
|
||||||
#if 0
|
#if 0
|
||||||
if ( cr_print_flag )
|
DEBUG_PRINT_ARRAY( "eccSignature:", (const char *)cert->signature->data, cert->signature->length );
|
||||||
{
|
|
||||||
int i;
|
|
||||||
for ( i = 0; i < cert->signature->length; i++ )
|
|
||||||
{
|
|
||||||
if ( i % 8 == 0 )
|
|
||||||
printf( "\n" );
|
|
||||||
printf( "0x%02X ", cert->signature->data[i] );
|
|
||||||
}
|
|
||||||
printf( "\n" );
|
|
||||||
}
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#if 0
|
#if 0
|
||||||
@ -670,48 +645,18 @@ static int generate_CTRCustom_cert( CTR_Device_Cert *cert, u32 deviceId, u8 bond
|
|||||||
int i;
|
int i;
|
||||||
printf( "CTR custom cert\n" );
|
printf( "CTR custom cert\n" );
|
||||||
printf( "sigType : 0x%08X\n", *(unsigned int*)cert->sigType );
|
printf( "sigType : 0x%08X\n", *(unsigned int*)cert->sigType );
|
||||||
printf( "eccSignature :" );
|
DEBUG_PRINT_ARRAY( "eccSignature:", (const char *)cert->eccSignature, sizeof(cert->eccSignature) );
|
||||||
for ( i = 0; i < 60; i++ )
|
DEBUG_PRINT_ARRAY( "padding0:", (const char *)cert->padding0, sizeof(cert->padding0) );
|
||||||
{
|
printf( "issuerName : " );
|
||||||
if ( i % 16 == 0 )
|
for ( i = 0; i < sizeof(cert->issuerName); i++ ) printf( "%c", cert->issuerName[i] );
|
||||||
printf( "\n" );
|
|
||||||
printf( "0x%02X ", cert->eccSignature[i] );
|
|
||||||
}
|
|
||||||
printf( "\n" );
|
|
||||||
printf( "padding :" );
|
|
||||||
for ( i = 0; i < 60; i++ )
|
|
||||||
{
|
|
||||||
if ( i % 16 == 0 )
|
|
||||||
printf( "\n" );
|
|
||||||
printf( "0x%02X ", cert->padding0[i] );
|
|
||||||
}
|
|
||||||
printf( "\n" );
|
|
||||||
printf( "subject : " );
|
|
||||||
for ( i = 0; i < 64; i++ )
|
|
||||||
printf( "%c", cert->issuerName[i] );
|
|
||||||
printf( "\n" );
|
printf( "\n" );
|
||||||
printf( "keyType : 0x%08X\n", *(unsigned int*)cert->keyType );
|
printf( "keyType : 0x%08X\n", *(unsigned int*)cert->keyType );
|
||||||
printf( "subject : " );
|
printf( "subject : " );
|
||||||
for ( i = 0; i < 64; i++ )
|
for ( i = 0; i < sizeof(cert->subject); i++ ) printf( "%c", cert->subject[i] );
|
||||||
printf( "%c", cert->subject[i] );
|
|
||||||
printf( "\n" );
|
printf( "\n" );
|
||||||
printf( "expiryDate : 0x%08X\n", (unsigned int)cert->expiryDate );
|
printf( "expiryDate : 0x%08X\n", (unsigned int)cert->expiryDate );
|
||||||
printf( "eccPubKey :" );
|
DEBUG_PRINT_ARRAY( "eccPubKey :", (const char *)cert->eccPubKey, sizeof(cert->eccPubKey) );
|
||||||
for ( i = 0; i < 60; i++ )
|
DEBUG_PRINT_ARRAY( "padding1:", (const char *)cert->padding1, sizeof(cert->padding1) );
|
||||||
{
|
|
||||||
if ( i % 16 == 0 )
|
|
||||||
printf( "\n" );
|
|
||||||
printf( "0x%02X ", cert->eccPubKey[i] );
|
|
||||||
}
|
|
||||||
printf( "\n" );
|
|
||||||
printf( "padding :" );
|
|
||||||
for ( i = 0; i < 60; i++ )
|
|
||||||
{
|
|
||||||
if ( i % 16 == 0 )
|
|
||||||
printf( "\n" );
|
|
||||||
printf( "0x%02X ", cert->padding1[i] );
|
|
||||||
}
|
|
||||||
printf( "\n" );
|
|
||||||
|
|
||||||
// 証明書の書き込みテスト
|
// 証明書の書き込みテスト
|
||||||
FILE *fp;
|
FILE *fp;
|
||||||
@ -1191,31 +1136,27 @@ int cr_generate_id_finalize( void )
|
|||||||
|
|
||||||
int cr_generate_id( u32 serial[CR_NUM_OF_SERIAL], u8 id_buf[CR_ID_BUF_SIZE], u8 bondingOption )
|
int cr_generate_id( u32 serial[CR_NUM_OF_SERIAL], u8 id_buf[CR_ID_BUF_SIZE], u8 bondingOption )
|
||||||
{
|
{
|
||||||
int i;
|
int i;
|
||||||
int ret_code;
|
int ret_code;
|
||||||
EC_KEY *my_eckey = NULL;
|
EC_KEY *my_eckey = NULL;
|
||||||
EVP_PKEY *my_evppkey = NULL;
|
EVP_PKEY *my_evppkey = NULL;
|
||||||
|
|
||||||
X509_REQ *req = NULL;
|
X509_REQ *req = NULL;
|
||||||
X509 *cert = NULL;
|
X509 *cert = NULL;
|
||||||
|
|
||||||
struct tm *tm_time;
|
CR_ID_BUFFER *cr_id_buf;
|
||||||
struct timeval tv;
|
u8 hash[SHA256_DIGEST_LENGTH]; /* SHA256 check */
|
||||||
struct timezone tz;
|
CTR_Device_Cert ctr_dev_cert;
|
||||||
|
|
||||||
CR_ID_BUFFER *cr_id_buf;
|
if( sizeof(CR_ID_BUFFER) != 256 ) {
|
||||||
u8 hash[SHA256_DIGEST_LENGTH]; /* SHA256 check */
|
ret_code = CR_GENID_ERROR_ID_BUF_SIZE;
|
||||||
CTR_Device_Cert ctr_dev_cert;
|
goto end;
|
||||||
|
}
|
||||||
|
|
||||||
if( sizeof(CR_ID_BUFFER) != 256 ) {
|
if( sizeof(CR_ERR_BUFFER) > 256 ) {
|
||||||
ret_code = CR_GENID_ERROR_ID_BUF_SIZE;
|
ret_code = CR_GENID_ERROR_ERR_BUF_SIZE;
|
||||||
goto end;
|
goto end;
|
||||||
}
|
}
|
||||||
|
|
||||||
if( sizeof(CR_ERR_BUFFER) > 256 ) {
|
|
||||||
ret_code = CR_GENID_ERROR_ERR_BUF_SIZE;
|
|
||||||
goto end;
|
|
||||||
}
|
|
||||||
|
|
||||||
if ( sizeof( CTR_Device_Cert ) > 384 )
|
if ( sizeof( CTR_Device_Cert ) > 384 )
|
||||||
{
|
{
|
||||||
@ -1223,12 +1164,15 @@ int cr_generate_id( u32 serial[CR_NUM_OF_SERIAL], u8 id_buf[CR_ID_BUF_SIZE], u8
|
|||||||
goto end;
|
goto end;
|
||||||
}
|
}
|
||||||
|
|
||||||
ret_code = CR_GENID_ERROR_NON; /* CR_GENID_ERROR_NON = 0 */
|
ret_code = CR_GENID_ERROR_NON; /* CR_GENID_ERROR_NON = 0 */
|
||||||
// printf("sizeof(CR_ID_BUFFER) = %d bytes\n",sizeof(CR_ID_BUFFER) );
|
|
||||||
// printf("offset(factory, CR_ID_BUFFER) = 0x%02x bytes\n", offsetof(CR_ID_BUFFER,factory ) );
|
#if 0
|
||||||
// printf("sizeof(CR_ERR_BUFFER) = 0x%02x bytes\n",sizeof(CR_ERR_BUFFER) );
|
printf("sizeof(CR_ID_BUFFER) = %d bytes\n",sizeof(CR_ID_BUFFER) );
|
||||||
// printf("offset(err_buffer, CR_ERR_BUFFER) = 0x%02x bytes\n", offsetof(CR_ERR_BUFFER,err_buffer ) );
|
printf("offset(factory, CR_ID_BUFFER) = 0x%02x bytes\n", offsetof(CR_ID_BUFFER,factory ) );
|
||||||
// printf("offset(err_line, CR_ERR_BUFFER) = 0x%02x bytes\n", offsetof(CR_ERR_BUFFER,err_line ) );
|
printf("sizeof(CR_ERR_BUFFER) = 0x%02x bytes\n",sizeof(CR_ERR_BUFFER) );
|
||||||
|
printf("offset(err_buffer, CR_ERR_BUFFER) = 0x%02x bytes\n", offsetof(CR_ERR_BUFFER,err_buffer ) );
|
||||||
|
printf("offset(err_line, CR_ERR_BUFFER) = 0x%02x bytes\n", offsetof(CR_ERR_BUFFER,err_line ) );
|
||||||
|
#endif
|
||||||
|
|
||||||
// ダイジェストアルゴリズムを追加する
|
// ダイジェストアルゴリズムを追加する
|
||||||
#if 0
|
#if 0
|
||||||
@ -1237,26 +1181,26 @@ int cr_generate_id( u32 serial[CR_NUM_OF_SERIAL], u8 id_buf[CR_ID_BUF_SIZE], u8
|
|||||||
EVP_add_digest( EVP_ecdsa() );
|
EVP_add_digest( EVP_ecdsa() );
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
//--------------------------------------------------------------
|
//--------------------------------------------------------------
|
||||||
// 暗号処理初期化
|
// 暗号処理初期化
|
||||||
//--------------------------------------------------------------
|
//--------------------------------------------------------------
|
||||||
|
|
||||||
// メモリリーク防止のため、オリジナルのアロケータを使用。
|
// メモリリーク防止のため、オリジナルのアロケータを使用。
|
||||||
CRYPTO_set_mem_functions(cr_mem_malloc, cr_mem_realloc, cr_mem_free);
|
CRYPTO_set_mem_functions(cr_mem_malloc, cr_mem_realloc, cr_mem_free);
|
||||||
cr_mem_bufmgr_initialize();
|
cr_mem_bufmgr_initialize();
|
||||||
|
|
||||||
#ifdef MY_CRYPTO_DEBUG
|
#ifdef MY_CRYPTO_DEBUG
|
||||||
ERR_load_crypto_strings();
|
ERR_load_crypto_strings();
|
||||||
#endif /* MY_CRYPTO_DEBUG */
|
#endif /* MY_CRYPTO_DEBUG */
|
||||||
|
|
||||||
//--------------------------------------------------------------
|
//--------------------------------------------------------------
|
||||||
// FuseIDバッファに固定データセット
|
// FuseIDバッファに固定データセット
|
||||||
//--------------------------------------------------------------
|
//--------------------------------------------------------------
|
||||||
memset(id_buf, 0, CR_ID_BUF_SIZE);
|
memset(id_buf, 0, CR_ID_BUF_SIZE);
|
||||||
|
|
||||||
cr_id_buf = (CR_ID_BUFFER *)id_buf;
|
cr_id_buf = (CR_ID_BUFFER *)id_buf;
|
||||||
cr_id_buf->magic_number = 0xdeadb00f; /* 0xdeadbeefにするとRSAでコケる。 */
|
cr_id_buf->magic_number = 0xdeadb00f; /* 0xdeadbeefにするとRSAでコケる。 */
|
||||||
cr_id_buf->version = CR_GEN_ID_VERSION;
|
cr_id_buf->version = CR_GEN_ID_VERSION;
|
||||||
|
|
||||||
//--------------------------------------------------------------
|
//--------------------------------------------------------------
|
||||||
// 引数のボンディングオプションをセット
|
// 引数のボンディングオプションをセット
|
||||||
@ -1284,41 +1228,45 @@ int cr_generate_id( u32 serial[CR_NUM_OF_SERIAL], u8 id_buf[CR_ID_BUF_SIZE], u8
|
|||||||
}
|
}
|
||||||
#endif /* DEBUG_PRINT */
|
#endif /* DEBUG_PRINT */
|
||||||
|
|
||||||
//--------------------------------------------------------------
|
//--------------------------------------------------------------
|
||||||
// タイムスタンプセット
|
// タイムスタンプセット
|
||||||
//--------------------------------------------------------------
|
//--------------------------------------------------------------
|
||||||
|
{
|
||||||
|
struct tm *tm_time;
|
||||||
|
struct timeval tv;
|
||||||
|
struct timezone tz;
|
||||||
|
|
||||||
#ifdef USE_HSM
|
#ifdef USE_HSM
|
||||||
hsm_get_rtc( &tv.tv_sec );
|
hsm_get_rtc( &tv.tv_sec );
|
||||||
#else // !USE_HSM
|
#else // !USE_HSM
|
||||||
gettimeofday(&tv,&tz);
|
gettimeofday(&tv,&tz);
|
||||||
#endif // USE_HSM
|
#endif // USE_HSM
|
||||||
|
|
||||||
tm_time = gmtime( &tv.tv_sec );
|
tm_time = gmtime( &tv.tv_sec );
|
||||||
|
|
||||||
|
cr_id_buf->year = (u8)tm_time->tm_year;
|
||||||
|
cr_id_buf->month = (u8)tm_time->tm_mon+1;
|
||||||
|
cr_id_buf->mday = (u8)tm_time->tm_mday;
|
||||||
|
cr_id_buf->hour = (u8)tm_time->tm_hour;
|
||||||
|
cr_id_buf->min = (u8)tm_time->tm_min;
|
||||||
|
cr_id_buf->sec = (u8)tm_time->tm_sec;
|
||||||
|
|
||||||
#ifdef DEBUG_PRINT
|
#ifdef DEBUG_PRINT
|
||||||
if( cr_print_flag )
|
if( cr_print_flag ) {
|
||||||
{
|
printf("GMT:%d-%02d-%02d %02d:%02d:%02d\n",
|
||||||
printf("GMT:%d-%02d-%02d %02d:%02d:%02d\n",
|
tm_time->tm_year+1900, /* 年 */
|
||||||
tm_time->tm_year+1900, /* 年 */
|
tm_time->tm_mon+1, /* 月 */
|
||||||
tm_time->tm_mon+1, /* 月 */
|
tm_time->tm_mday, /* 日 */
|
||||||
tm_time->tm_mday, /* 日 */
|
tm_time->tm_hour, /* 時 */
|
||||||
tm_time->tm_hour, /* 時 */
|
tm_time->tm_min, /* 分 */
|
||||||
tm_time->tm_min, /* 分 */
|
tm_time->tm_sec /* 秒 */
|
||||||
tm_time->tm_sec /* 秒 */
|
);
|
||||||
);
|
}
|
||||||
}
|
|
||||||
#endif /* DEBUG_PRINT */
|
#endif /* DEBUG_PRINT */
|
||||||
|
}
|
||||||
cr_id_buf->year = (u8)tm_time->tm_year;
|
//--------------------------------------------------------------
|
||||||
cr_id_buf->month = (u8)tm_time->tm_mon+1;
|
// 乱数を生成してセット
|
||||||
cr_id_buf->mday = (u8)tm_time->tm_mday;
|
//--------------------------------------------------------------
|
||||||
cr_id_buf->hour = (u8)tm_time->tm_hour;
|
|
||||||
cr_id_buf->min = (u8)tm_time->tm_min;
|
|
||||||
cr_id_buf->sec = (u8)tm_time->tm_sec;
|
|
||||||
|
|
||||||
//--------------------------------------------------------------
|
|
||||||
// 乱数を生成してセット
|
|
||||||
//--------------------------------------------------------------
|
|
||||||
#ifdef USE_HSM
|
#ifdef USE_HSM
|
||||||
ret_code = hsm_generate_random( cr_id_buf->random, CR_RANDOM_LENGTH );
|
ret_code = hsm_generate_random( cr_id_buf->random, CR_RANDOM_LENGTH );
|
||||||
if ( ret_code != Status_OK )
|
if ( ret_code != Status_OK )
|
||||||
@ -1327,31 +1275,16 @@ int cr_generate_id( u32 serial[CR_NUM_OF_SERIAL], u8 id_buf[CR_ID_BUF_SIZE], u8
|
|||||||
return ret_code;
|
return ret_code;
|
||||||
}
|
}
|
||||||
#else // !USE_HSM
|
#else // !USE_HSM
|
||||||
#ifdef USE_SFMT // メルセンヌ・ツイスタ
|
|
||||||
for ( i = 0; i < CR_RANDOM_LENGTH; i += 4 )
|
|
||||||
{
|
{
|
||||||
*(u32*)&(cr_id_buf->random[i]) = gen_rand32();
|
u16 buffer[ CR_RANDOM_LENGTH / sizeof(u16) ];
|
||||||
|
for( i = 0 ; i < CR_RANDOM_LENGTH / sizeof(u16); i++ ) {
|
||||||
|
buffer[i] = (u16)rand();
|
||||||
|
}
|
||||||
|
memcpy( cr_id_buf->random, buffer, CR_RANDOM_LENGTH );
|
||||||
}
|
}
|
||||||
#else /* USE_SFMT */
|
|
||||||
for( i = 0 ; i < CR_NUM_OF_RANDOM ; i++ ) {
|
|
||||||
cr_id_buf->random[i] = (u16)rand(); /* 範囲は0から32767 */
|
|
||||||
}
|
|
||||||
#endif /* USE_SFMT */
|
|
||||||
#endif // USE_HSM
|
#endif // USE_HSM
|
||||||
|
|
||||||
#ifdef DEBUG_PRINT
|
DEBUG_PRINT_ARRAY( "rand:", (const char *)cr_id_buf->random, CR_RANDOM_LENGTH );
|
||||||
if( cr_print_flag ) {
|
|
||||||
unsigned char *p = (unsigned char *)cr_id_buf->random;
|
|
||||||
printf("rand:" );
|
|
||||||
for( i = 0 ; i < CR_RANDOM_LENGTH; i++ ) {
|
|
||||||
if( (i % 16) == 0 ) {
|
|
||||||
printf("\n ");
|
|
||||||
}
|
|
||||||
printf("0x%02x ", p[ i ] );
|
|
||||||
}
|
|
||||||
printf("\n");
|
|
||||||
}
|
|
||||||
#endif /* DEBUG_PRINT */
|
|
||||||
|
|
||||||
//--------------------------------------------------------------
|
//--------------------------------------------------------------
|
||||||
// 楕円曲線鍵ペアを生成
|
// 楕円曲線鍵ペアを生成
|
||||||
@ -1452,7 +1385,6 @@ int cr_generate_id( u32 serial[CR_NUM_OF_SERIAL], u8 id_buf[CR_ID_BUF_SIZE], u8
|
|||||||
for ( i = 0; i < cert->signature->length; i++ )
|
for ( i = 0; i < cert->signature->length; i++ )
|
||||||
cr_id_buf->deviceCertSign[ i + padding ] = cert->signature->data[i];
|
cr_id_buf->deviceCertSign[ i + padding ] = cert->signature->data[i];
|
||||||
// mistake!!
|
// mistake!!
|
||||||
#endif
|
|
||||||
|
|
||||||
// TORIAEZU : create Custom cert
|
// TORIAEZU : create Custom cert
|
||||||
memset( &ctr_dev_cert, 0, sizeof( ctr_dev_cert ) );
|
memset( &ctr_dev_cert, 0, sizeof( ctr_dev_cert ) );
|
||||||
@ -1467,6 +1399,7 @@ int cr_generate_id( u32 serial[CR_NUM_OF_SERIAL], u8 id_buf[CR_ID_BUF_SIZE], u8
|
|||||||
len = BN_bn2bin( &my_eckey->pub_key->Y, buf );
|
len = BN_bn2bin( &my_eckey->pub_key->Y, buf );
|
||||||
memcpy( &ctr_dev_cert.eccPubKey[30], buf, len );
|
memcpy( &ctr_dev_cert.eccPubKey[30], buf, len );
|
||||||
free( buf );
|
free( buf );
|
||||||
|
#endif
|
||||||
|
|
||||||
// copy sign to Custom cert
|
// copy sign to Custom cert
|
||||||
//#define SHOW_SIG
|
//#define SHOW_SIG
|
||||||
@ -1481,8 +1414,7 @@ int cr_generate_id( u32 serial[CR_NUM_OF_SERIAL], u8 id_buf[CR_ID_BUF_SIZE], u8
|
|||||||
printf( "r :" );
|
printf( "r :" );
|
||||||
for ( i = 0; i < len; i++ )
|
for ( i = 0; i < len; i++ )
|
||||||
{
|
{
|
||||||
if ( i % 8 == 0 )
|
if ( i % 8 == 0 ) printf( "\n" );
|
||||||
printf( "\n" );
|
|
||||||
printf( "0x%02X ", *(ptr++) );
|
printf( "0x%02X ", *(ptr++) );
|
||||||
}
|
}
|
||||||
printf( "\n" );
|
printf( "\n" );
|
||||||
@ -1492,8 +1424,7 @@ int cr_generate_id( u32 serial[CR_NUM_OF_SERIAL], u8 id_buf[CR_ID_BUF_SIZE], u8
|
|||||||
printf( "s :" );
|
printf( "s :" );
|
||||||
for ( i = 0; i < len; i++ )
|
for ( i = 0; i < len; i++ )
|
||||||
{
|
{
|
||||||
if ( i % 8 == 0 )
|
if ( i % 8 == 0 ) printf( "\n" );
|
||||||
printf( "\n" );
|
|
||||||
printf( "0x%02X ", *(ptr++) );
|
printf( "0x%02X ", *(ptr++) );
|
||||||
}
|
}
|
||||||
printf( "\n" );
|
printf( "\n" );
|
||||||
@ -1511,117 +1442,84 @@ int cr_generate_id( u32 serial[CR_NUM_OF_SERIAL], u8 id_buf[CR_ID_BUF_SIZE], u8
|
|||||||
ret_code = generate_CTRCustom_cert( &ctr_dev_cert,
|
ret_code = generate_CTRCustom_cert( &ctr_dev_cert,
|
||||||
cr_id_buf->serial[0], cr_id_buf->bondingOption );
|
cr_id_buf->serial[0], cr_id_buf->bondingOption );
|
||||||
#endif
|
#endif
|
||||||
printf("3\n");
|
|
||||||
|
|
||||||
#if 0
|
#if 0
|
||||||
if( cr_print_flag )
|
DEBUG_PRINT_ARRAY( "deviceCertSign:", (const char *)cr_id_buf->deviceCertSign, ECDSA_SIGN_LENGTH );
|
||||||
{
|
#endif
|
||||||
for( i = 0 ; i < ECDSA_SIGN_LENGTH; i++ )
|
|
||||||
{
|
|
||||||
if( (i%8) == 0 )
|
|
||||||
{
|
|
||||||
printf( "\n ");
|
|
||||||
}
|
|
||||||
printf("0x%02x ", cr_id_buf->deviceCertSign[i] );
|
|
||||||
}
|
|
||||||
printf("\n");
|
|
||||||
}
|
|
||||||
#endif /* DEBUG_PRINT */
|
|
||||||
|
|
||||||
//--------------------------------------------------------------
|
//--------------------------------------------------------------
|
||||||
// FuseIDバッファ全体のSHA256ハッシュを算出してセット
|
// FuseIDバッファ全体のSHA256ハッシュを算出してセット
|
||||||
//--------------------------------------------------------------
|
//--------------------------------------------------------------
|
||||||
SHA256(id_buf, CR_ID_BUF_SIZE - SHA256_DIGEST_LENGTH, cr_id_buf->hash);
|
SHA256(id_buf, CR_ID_BUF_SIZE - SHA256_DIGEST_LENGTH, cr_id_buf->hash);
|
||||||
|
|
||||||
memcpy( hash, cr_id_buf->hash, SHA256_DIGEST_LENGTH );
|
memcpy( hash, cr_id_buf->hash, SHA256_DIGEST_LENGTH );
|
||||||
|
DEBUG_PRINT_ARRAY( "SHA256 Digest:", (const char *)cr_id_buf->hash, SHA256_DIGEST_LENGTH );
|
||||||
|
|
||||||
#ifdef DEBUG_PRINT
|
//--------------------------------------------------------------
|
||||||
if( cr_print_flag ) {
|
// FuseIDバッファ全体を暗号化
|
||||||
printf("SHA256 Digest:");
|
//--------------------------------------------------------------
|
||||||
for( i = 0 ; i < SHA256_DIGEST_LENGTH ; i++ ) {
|
DEBUG_PRINT_ARRAY( "ORG buf:", (const char *)id_buf, CR_ID_BUF_SIZE );
|
||||||
if( (i%8) == 0 ) {
|
|
||||||
printf("\n ");
|
|
||||||
}
|
|
||||||
printf("0x%02x ", cr_id_buf->hash[i] );
|
|
||||||
}
|
|
||||||
printf("\n");
|
|
||||||
}
|
|
||||||
#endif /* DEBUG_PRINT */
|
|
||||||
|
|
||||||
//--------------------------------------------------------------
|
|
||||||
// FuseIDバッファ全体を暗号化
|
|
||||||
//--------------------------------------------------------------
|
|
||||||
#ifdef DEBUG_PRINT
|
|
||||||
if( cr_print_flag ) {
|
|
||||||
printf("ORG buf:");
|
|
||||||
for( i = 0 ; i < CR_ID_BUF_SIZE ; i++ ) {
|
|
||||||
if( (i%16) == 0 ) {
|
|
||||||
printf("\n ");
|
|
||||||
}
|
|
||||||
printf("0x%02x ", id_buf[i] );
|
|
||||||
}
|
|
||||||
printf("\n");
|
|
||||||
}
|
|
||||||
#endif /* DEBUG_PRINT */
|
|
||||||
|
|
||||||
#ifdef ENCRYPT_AES
|
#ifdef ENCRYPT_AES
|
||||||
// AES暗号化 -> 復号化 -> ベリファイ
|
ret_code = crypto_aes_enc_dec( id_buf, id_buf ); // AES
|
||||||
ret_code = crypto_aes_enc_dec( id_buf, id_buf );
|
|
||||||
#else // !ENCRYPT_AES
|
#else // !ENCRYPT_AES
|
||||||
ret_code = crypto_rsa_enc_dec( id_buf, id_buf);
|
ret_code = crypto_rsa_enc_dec( id_buf, id_buf ); // RSA pubKey enc
|
||||||
#endif // ENCRYPT_AES
|
#endif // ENCRYPT_AES
|
||||||
|
|
||||||
if( ret_code != 0 )
|
if( ret_code != 0 ) {
|
||||||
{
|
|
||||||
goto end;
|
goto end;
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifdef DEBUG_PRINT
|
DEBUG_PRINT_ARRAY( "encrypted:", (const char *)id_buf, CR_ID_BUF_SIZE );
|
||||||
if( cr_print_flag ) {
|
|
||||||
printf("encrypted:");
|
|
||||||
for( i = 0 ; i < CR_ID_BUF_SIZE ; i++ ) {
|
|
||||||
if( (i%16) == 0 ) {
|
|
||||||
printf("\n ");
|
|
||||||
}
|
|
||||||
printf("0x%02x ", id_buf[i] );
|
|
||||||
}
|
|
||||||
printf("\n");
|
|
||||||
}
|
|
||||||
#endif /* DEBUG_PRINT */
|
|
||||||
|
|
||||||
//--------------------------------------------------------------
|
//--------------------------------------------------------------
|
||||||
// 終了処理
|
// 終了処理
|
||||||
//--------------------------------------------------------------
|
//--------------------------------------------------------------
|
||||||
end:
|
end:
|
||||||
/* id_buf[]にエラーログを書き込む。 */
|
/* id_buf[]にエラーログを書き込む。 */
|
||||||
if( ret_code != 0 ) {
|
if( ret_code != 0 ) {
|
||||||
ERR_STATE *es = NULL;
|
ERR_STATE *es = NULL;
|
||||||
CR_ERR_BUFFER *cr_err_buf = (CR_ERR_BUFFER *)id_buf;
|
CR_ERR_BUFFER *cr_err_buf = (CR_ERR_BUFFER *)id_buf;
|
||||||
memset( cr_err_buf, 0, sizeof(CR_ERR_BUFFER) );
|
memset( cr_err_buf, 0, sizeof(CR_ERR_BUFFER) );
|
||||||
cr_err_buf->magic_number = 0x01234567;
|
cr_err_buf->magic_number = 0x01234567;
|
||||||
cr_err_buf->serial0 = serial[0];
|
cr_err_buf->serial0 = serial[0];
|
||||||
cr_err_buf->openssl_err_code = ERR_get_error();
|
cr_err_buf->openssl_err_code = ERR_get_error();
|
||||||
es=ERR_get_state();
|
es=ERR_get_state();
|
||||||
cr_err_buf->top = es->top;
|
cr_err_buf->top = es->top;
|
||||||
cr_err_buf->bottom = es->bottom;
|
cr_err_buf->bottom = es->bottom;
|
||||||
for( i = 0 ; i < ERR_NUM_ERRORS ; i++ ) {
|
for( i = 0 ; i < ERR_NUM_ERRORS ; i++ ) {
|
||||||
cr_err_buf->err_buffer[i] = es->err_buffer[i];
|
cr_err_buf->err_buffer[i] = es->err_buffer[i];
|
||||||
cr_err_buf->err_line[i] = es->err_line[i];
|
cr_err_buf->err_line[i] = es->err_line[i];
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// リソースの解放
|
// リソースの解放
|
||||||
if ( my_eckey ) EC_KEY_free( my_eckey );
|
if ( my_eckey ) EC_KEY_free( my_eckey );
|
||||||
if ( my_evppkey ) EVP_PKEY_free( my_evppkey );
|
if ( my_evppkey ) EVP_PKEY_free( my_evppkey );
|
||||||
if ( req ) X509_REQ_free( req );
|
if ( req ) X509_REQ_free( req );
|
||||||
|
|
||||||
ERR_remove_state(0);
|
ERR_remove_state(0);
|
||||||
EVP_cleanup();
|
EVP_cleanup();
|
||||||
CRYPTO_cleanup_all_ex_data();
|
CRYPTO_cleanup_all_ex_data();
|
||||||
|
|
||||||
#ifdef MY_CRYPTO_DEBUG
|
#ifdef MY_CRYPTO_DEBUG
|
||||||
ERR_free_strings();
|
ERR_free_strings();
|
||||||
#endif /* MY_CRYPTO_DEBUG */
|
#endif /* MY_CRYPTO_DEBUG */
|
||||||
|
|
||||||
return ret_code; /* success */
|
return ret_code; /* success */
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
#ifdef DEBUG_PRINT
|
||||||
|
void DebugPrintArray( char *pStr, const u8 *pData, int length )
|
||||||
|
{
|
||||||
|
int i;
|
||||||
|
if( cr_print_flag ) {
|
||||||
|
printf( "%s", pStr );
|
||||||
|
for( i = 0 ; i < length; i++ ) {
|
||||||
|
if( (i % 16) == 0 ) printf("\n ");
|
||||||
|
printf("%02X ", pData[ i ] );
|
||||||
|
}
|
||||||
|
printf("\n");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|||||||
@ -232,21 +232,15 @@
|
|||||||
extern "C" {
|
extern "C" {
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
typedef signed char s8;
|
typedef signed char s8;
|
||||||
typedef unsigned char u8;
|
typedef unsigned char u8;
|
||||||
typedef unsigned short u16;
|
typedef unsigned short u16;
|
||||||
typedef signed long s32;
|
typedef signed long s32;
|
||||||
typedef unsigned long u32;
|
typedef unsigned long u32;
|
||||||
typedef unsigned long long u64;
|
typedef unsigned long long u64;
|
||||||
|
|
||||||
//#define DEBUG_PRINT 1
|
#define CR_ID_BUF_SIZE (2048/8)
|
||||||
|
#define CR_NUM_OF_SERIAL 5
|
||||||
#ifdef USE_SFMT
|
|
||||||
#include "SFMT.h"
|
|
||||||
#endif /* USE_SFMT */
|
|
||||||
|
|
||||||
#define CR_ID_BUF_SIZE (2048/8)
|
|
||||||
#define CR_NUM_OF_SERIAL 5
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
serial と 実際のID との関係は、下記のようになっています。
|
serial と 実際のID との関係は、下記のようになっています。
|
||||||
@ -256,17 +250,16 @@ typedef unsigned long long u64;
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
// Nintendo ID 仕様
|
// Nintendo ID 仕様
|
||||||
#define CR_ID0_BIT_NUM 32
|
#define CR_ID0_BIT_NUM 32
|
||||||
#define CR_ID1_BIT_NUM 34
|
#define CR_ID1_BIT_NUM 34
|
||||||
#define CR_ID2_BIT_NUM 64
|
#define CR_ID2_BIT_NUM 64
|
||||||
#define CR_ID0_MASK 0xFFFFFFFF // 32bit
|
#define CR_ID0_MASK 0xFFFFFFFF // 32bit
|
||||||
#define CR_ID1_MASK 0x00000003FFFFFFFFll // 34bit
|
#define CR_ID1_MASK 0x00000003FFFFFFFFll // 34bit
|
||||||
#define CR_ID2_MASK 0xFFFFFFFFFFFFFFFFll // 64bit
|
#define CR_ID2_MASK 0xFFFFFFFFFFFFFFFFll // 64bit
|
||||||
|
|
||||||
int cr_generate_id_initialize( void );
|
extern int cr_generate_id_initialize( void );
|
||||||
int cr_generate_id_finalize( void );
|
extern int cr_generate_id( u32 serial[CR_NUM_OF_SERIAL], u8 id[CR_ID_BUF_SIZE], u8 bondingOption );
|
||||||
|
extern int cr_generate_id_finalize( void );
|
||||||
int cr_generate_id( u32 serial[CR_NUM_OF_SERIAL], u8 id[CR_ID_BUF_SIZE], u8 bondingOption );
|
|
||||||
|
|
||||||
extern int cr_print_flag;
|
extern int cr_print_flag;
|
||||||
|
|
||||||
|
|||||||
@ -116,9 +116,17 @@
|
|||||||
extern "C" {
|
extern "C" {
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
//#define DEBUG_PRINT 1
|
||||||
|
|
||||||
int crypto_aes_enc_dec( unsigned char *dst_buf, unsigned char *org_buf );
|
#ifdef DEBUG_PRINT
|
||||||
int crypto_rsa_enc_dec( unsigned char *dst_buf, unsigned char *org_buf );
|
#define DEBUG_PRINT_ARRAY DebugPrintArray
|
||||||
|
#else // !DEBUG_PRINT
|
||||||
|
#define DEBUG_PRINT_ARRAY( ... ) ((void)0)
|
||||||
|
#endif // DEBUG_PRINT
|
||||||
|
|
||||||
|
extern int crypto_aes_enc_dec( unsigned char *dst_buf, unsigned char *org_buf );
|
||||||
|
extern int crypto_rsa_enc_dec( unsigned char *dst_buf, unsigned char *org_buf );
|
||||||
|
extern void DebugPrintArray( char *pStr, const u8 *pData, int length );
|
||||||
|
|
||||||
#ifdef __cplusplus
|
#ifdef __cplusplus
|
||||||
}
|
}
|
||||||
|
|||||||
4
main.c
4
main.c
@ -14,6 +14,10 @@
|
|||||||
#include <unistd.h>
|
#include <unistd.h>
|
||||||
#endif // Linux
|
#endif // Linux
|
||||||
|
|
||||||
|
#ifdef USE_SFMT
|
||||||
|
#include "SFMT.h"
|
||||||
|
#endif /* USE_SFMT */
|
||||||
|
|
||||||
#include "cr_generate_id.h"
|
#include "cr_generate_id.h"
|
||||||
|
|
||||||
#define T_BONDING_OPTION 0 // TORIAEZU bondingOption = 0
|
#define T_BONDING_OPTION 0 // TORIAEZU bondingOption = 0
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user