/* testSharpID に対応したフォーマットで ID の出力を行います。 *注意1* HSM の使える環境(Linux) で出力したファイルを Windows(Cygwin) で検証する場合、 文字コードを Shift-JIS の CR+LF として解釈するためうまくいきません(2つめのレコードでコケる) Windows 側で検証する場合は LF として保存しなおす必要があります。 *注意2* testSharpID で検証する場合は真の鍵で行う必要があります。 そのため Makefile.testSharpID において (1) dummyKey フォルダの dev, prod それぞれに対して eFuse_aesKey.bin, eFuse_privKey.der, eFuse_pubKey.der を差し替える (他はそのままで OK) (2) realKey フォルダの dev, prod それぞれに対して eFuse_aesKey.bin, eFuse_privKey.der, eFuse_pubKey.der を置く。 dummyKey フォルダの dev, prod の NCT2_priv.der, NCT2_priv.pem, NCT2_pub.pem を置く。 上記を行った上で Makefile.testSharpID の ifeq ($(USE_DUMMY_KEY),TRUE) endif の間にある DEV_DER_KEY_DIR = ./dummyKey/dev -> ./realKey/dev PROD_DER_KEY_DIR = ./dummyKey/prod -> ./realKey/prod と変更する。 のいづれかの対応をします。 */ #define RAND_MAX 0xffffffff #include #include #include #include #include #include #ifdef DEV_CYGWIN #include #else // Cygwin #include #endif // Linux #include "cr_generate_id.h" #define BONDING_OPTION_PROD 0 // 製品用ID #define BONDING_OPTION_DEV 1 // 開発用ID #define BONDING_OPTION_DEBUGGER 2 // デバッガ #define DEFAULT_OUTPUT_PATH_BASE "ID" // extern const int isDummyPrivateKey; /* gen_id.exe 0x01 0x02 gen_id.exe 0x01 0x02 ctrid090716.dat gen_id.exe 0x01 0x03 ctrid090728.dat */ #ifndef DEV_CYGWIN static struct termios initial_setting, new_setting; static int peek_character = -1; void keyboard_initialize( void ) { tcgetattr( 0, &initial_setting ); new_setting = initial_setting; new_setting.c_lflag &= ~ICANON; new_setting.c_lflag &= ~ECHO; new_setting.c_lflag &= ~ISIG; new_setting.c_cc[VMIN] = 0; new_setting.c_cc[VTIME] = 0; tcsetattr( 0, TCSANOW, &initial_setting ); } // keyboard_initialize void keyboard_finalize( void ) { tcsetattr( 0, TCSANOW, &initial_setting ); } // keyboard_finalize int kbhit( void ) { char ch; int nread; if ( peek_character != -1 ) { return 1; } new_setting.c_cc[VMIN] = 0; tcsetattr( 0, TCSANOW, &new_setting ); nread = read( 0, &ch, 1 ); new_setting.c_cc[VMIN] = 1; tcsetattr( 0, TCSANOW, &new_setting ); if ( nread == 1 ) { peek_character = ch; return 1; } return 0; } // kbhit int getch( void ) { char ch; if ( peek_character != -1 ) { ch = peek_character; peek_character = -1; return ch; } read( 0, &ch, 1 ); return ch; } // readch #endif // DEV_CYGWIN // char *str = "0x11111111"; static int str_to_u32(u32 *num, const char *str) { u32 c; int shift = 0; char *s; int hex_mode = 0; *num = 0; if( *str == '0' && *(str+1) == 'x' ) { hex_mode = 1; s = (char *)(str + 2); } else { s = (char *)str; } while( *s != '\0' ) { if( shift > 8 ) { return -1; /* error */ } if( hex_mode ) { if( '0' <= *s && *s <= '9' ) { c = (u32)(*s - '0'); } else if( 'a' <= *s && *s <= 'f' ) { c = (u32)(*s - 'a') + 10; } else if( 'A' <= *s && *s <= 'F' ) { c = (u32)(*s - 'A') + 10; } else { return -1; /* error */ } *num <<= 4; *num |= c; } else { if( '0' <= *s && *s <= '9' ) { c = (u32)(*s - '0'); } else { return -1; /* error */ } *num *= 10; *num += c; } shift++; s++; } return 0; } static double gettimeofday_sec(void) { struct timeval tv; #if 0 struct timeval { time_t tv_sec; /* 秒 */ suseconds_t tv_usec; /* マイクロ秒 */ }; struct timezone { int tz_minuteswest; /* グリニッジ標準時との差 (西方に分単位) */ int tz_dsttime; /* 夏時間調整の型 */ }; int gettimeofday(struct timeval *tv, struct timezone *tz); #endif gettimeofday(&tv, NULL); return tv.tv_sec + (double)tv.tv_usec*1e-6; } void showHelp(const char* program) { printf( "%s [OPTION]\n", program ); printf( "\t-b bonding_option : Default=0, 0(Prod) 1(Dev) 2(Dev Debugger)\n" ); printf( "\t-p output_path : Default=%s[PID]_[BONDING_OPTION].txt\n", DEFAULT_OUTPUT_PATH_BASE ); printf( "\t-n output_number : Default=4294967295(0xffffffff)\n" ); printf( "\t-h : Show this Help\n" ); } int main(int argc, char *argv[]) { u8 bonding_option = BONDING_OPTION_PROD; char output_path[512] = ""; u32 output_number = 0xffffffff; u32 device_id[CR_NUM_OF_DEVICEID]; u8 id[CR_ID_BUF_SIZE]; /* 256byte(2048bit) */ int ret_code; int c; FILE *fp; double time_start,time_end; long double time_total = 0; int time_count = 0; int myseed; time_t tloc; u32 counter0, counter0_bak; u64 counter1, counter1_bak; u64 counter2, counter2_bak; u32 i; #ifndef DEV_CYGWIN keyboard_initialize(); #endif // コマンドライン引数チェック int opt; while ((opt = getopt( argc, argv, "b:p:n:h")) != -1) { switch (opt) { case 'b' : { u32 temp; str_to_u32( &temp, optarg ); if (temp != BONDING_OPTION_PROD && temp != BONDING_OPTION_DEV && temp != BONDING_OPTION_DEBUGGER) { printf( "Invalid Bonding Option!\n" ); showHelp( argv[0] ); return 0; } bonding_option = temp; break; } case 'p' : { sprintf( output_path, "%s", optarg ); break; } case 'n' : { str_to_u32( &output_number, optarg ); break; } case 'h' : { showHelp( argv[0] ); return 0; } } } // デフォルトパス設定 if (output_path[0] == '\0') { sprintf( output_path, "%s_pid%d_bond%d.txt", DEFAULT_OUTPUT_PATH_BASE, getpid(), bonding_option ); } // 設定表示 printf( "bonding_option = %d\n", bonding_option ); printf( "output_file = %s\n", output_path ); printf( "output_number = %u\n", (unsigned int)output_number ); // ファイルを開く fp = fopen( output_path, "w" ); if( fp == NULL ) { fprintf( stderr, "failed to fopen %s\n", argv[2] ); return 0; } // ヘッダを書き込む fprintf( fp, "SerialNo, Crypto Key1, Crypto Key2, ID\n" ); fprintf( fp, "--------------------------------------\n" ); #ifdef USE_DUMMY_KEY printf( "[TEST MODE] Use dummy key.\n"); #endif time(&tloc); myseed = tloc; srand(myseed); // ID生成前にカウンタ加算をするなら、初期値は 0 で OK counter0 = 0x00000000; counter1 = 0x0000000000000000ll; counter2 = 0x0000000000000000ll; // cr_generate_id を使用する前に呼び出す ret_code = cr_generate_id_initialize( id ); if ( ret_code != CR_GENID_SUCCESS ) { printf( "error : cr_generate_id_initialize\n" ); goto end; } for( i = 0 ; i < output_number; i++ ) { u64 unit; counter0_bak = counter0; counter1_bak = counter1; counter2_bak = counter2; // counter0 は、1 ずつ加算 counter0 = i + 1; if( counter0 == 0 ) { counter0 = 1; } // counter1 は、"1~4 の乱数値" を加算 unit = (u64)( ( rand() & 0x03 ) + 1 ); counter1 += unit; // counter2 は、"0 以外の 32bit 乱数値" を加算 do { unit = ((u64)rand() & 0xffff) | ( ((u64)rand() & 0xffff) << 16 ); } while( unit == 0 ); counter2 += unit; // カウンタオーバーフローチェック if( counter0 < counter0_bak ) { fprintf(stderr,"counter0 overflow : %08x\n", (unsigned int)counter0 ); } if( counter1 < counter1_bak ) { fprintf(stderr,"counter1 overflow : %08x%08x\n", (unsigned int)( counter1 >> 32 ), (unsigned int)counter2 ); } if( counter2 < counter2_bak ) { fprintf(stderr,"counter2 overflow : %08x%08x\n", (unsigned int)( counter2 >> 32 ), (unsigned int)counter2 ); } device_id[0] = counter0; device_id[1] = (u32)(counter1 & 0xffffffff); device_id[2] = (u32)((counter1 >> 32) & 0xffffffff); device_id[3] = (u32)(counter2 & 0xffffffff); device_id[4] = (u32)((counter2 >> 32) & 0xffffffff); time_start = gettimeofday_sec(); ret_code = cr_generate_id( device_id, id, bonding_option ); if( ret_code != 0 ) { fprintf(stderr,"generate_id failed\n"); goto end; } else { time_end = gettimeofday_sec(); time_total += (long double)(time_end - time_start); time_count++; /* printf("generate_id success\n"); */ } // 書き込み { int i; fprintf( fp, "%08X, %08X %08X, %08X %08X, ", (unsigned int)device_id[0], (unsigned int)device_id[2], (unsigned int)device_id[1], (unsigned int)device_id[4], (unsigned int)device_id[3] ); for (i = 0; i < CR_ID_BUF_SIZE; i++ ) { fprintf( fp, "%02X", id[i] ); } fprintf( fp, "\n" ); } if (kbhit()) { c = getch(); if( 'p' == c ) { printf("ID[0] = 0x%08x\n", (unsigned int)device_id[0]); printf("ID[1] = 0x%08x%08x\n", (unsigned int)device_id[2], (unsigned int)device_id[1] ); printf("ID[2] = 0x%08x%08x\n", (unsigned int)device_id[4], (unsigned int)device_id[3] ); printf("time av. = %8.8f sec\n", (double)(time_total/(long double)time_count)); cr_print_flag = 1; } else if( c == 'q' ) { goto end; } } else { cr_print_flag = 0; } } end: // ファイルのクローズ if (fp) { fclose(fp); } // cr_generate_id を使用した後に呼び出す ret_code = cr_generate_id_finalize( id ); if ( ret_code != CR_GENID_SUCCESS ) { printf( "error : cr_generate_id_finalize\n" ); return 0; // error } #ifndef DEV_CYGWIN keyboard_finalize(); #endif printf("end of main\n"); return 0; }