/* ==================================================================== * Copyright (c) 1998-2008 The OpenSSL Project. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in * the documentation and/or other materials provided with the * distribution. * * 3. All advertising materials mentioning features or use of this * software must display the following acknowledgment: * "This product includes software developed by the OpenSSL Project * for use in the OpenSSL Toolkit. (http://www.openssl.org/)" * * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to * endorse or promote products derived from this software without * prior written permission. For written permission, please contact * openssl-core@openssl.org. * * 5. Products derived from this software may not be called "OpenSSL" * nor may "OpenSSL" appear in their names without prior written * permission of the OpenSSL Project. * * 6. Redistributions of any form whatsoever must retain the following * acknowledgment: * "This product includes software developed by the OpenSSL Project * for use in the OpenSSL Toolkit (http://www.openssl.org/)" * * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE OpenSSL PROJECT OR * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED * OF THE POSSIBILITY OF SUCH DAMAGE. * ==================================================================== * * This product includes cryptographic software written by Eric Young * (eay@cryptsoft.com). This product includes software written by Tim * Hudson (tjh@cryptsoft.com). * */ /* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com) * All rights reserved. * * This package is an SSL implementation written * by Eric Young (eay@cryptsoft.com). * The implementation was written so as to conform with Netscapes SSL. * * This library is free for commercial and non-commercial use as long as * the following conditions are aheared to. The following conditions * apply to all code found in this distribution, be it the RC4, RSA, * lhash, DES, etc., code; not just the SSL code. The SSL documentation * included with this distribution is covered by the same copyright terms * except that the holder is Tim Hudson (tjh@cryptsoft.com). * * Copyright remains Eric Young's, and as such any Copyright notices in * the code are not to be removed. * If this package is used in a product, Eric Young should be given attribution * as the author of the parts of the library used. * This can be in the form of a textual message at program startup or * in documentation (online or textual) provided with the package. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * 3. All advertising materials mentioning features or use of this software * must display the following acknowledgement: * "This product includes cryptographic software written by * Eric Young (eay@cryptsoft.com)" * The word 'cryptographic' can be left out if the rouines from the library * being used are not cryptographic related :-). * 4. If you include any Windows specific code (or a derivative thereof) from * the apps directory (application code) you must include an acknowledgement: * "This product includes software written by Tim Hudson (tjh@cryptsoft.com)" * * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * * The licence and distribution terms for any publically available version or * derivative of this code cannot be changed. i.e. this code cannot simply be * copied and put under another distribution licence * [including the GNU Public Licence.] */ #include #include #include #include #include #include #include // nShield #include "nfastapp.h" #include "nfkm.h" #include "rqcard-applic.h" #include "rqcard-fips.h" // nShield optional #include "simplebignum.h" // openssl #include #include #include #include #include #include #include // openssl optional #include "ec_lcl.h" // ec_key_st構造体の参照に必要 #include "openssl-0.9.8k/crypto/pem/pem.h" // for PEM_read_X509 関数 #include "cr_generate_id.h" #include "cr_alloc.h" #include "cr_gen_id_rsa_key_priv.h" #include "cr_gen_id_rsa_key_pub.h" // #define DEBUG_PRINT 1 #define CR_GEN_ID_VERSION 1 #define CR_NUM_OF_SERIAL 5 #define CR_RSV_LENGTH 0x0C #define CR_RANDOM_LENGTH 0x50 #define EC_PRIVATE_KEY_LENGTH 0x20 #define ECDSA_SIGN_LENGTH 0x44 //#define SHA256_DIGEST_LENGTH 0x20 // OpenSSL側で定義済み #define EC_CURVE_NAME NID_sect233r1 #define CA_FILE "dummyCA/NintendoCTR2_dummy.crt" #define CA_KEY "dummyCA/NintendoCTR2_priv_dummy.pem" #define DAYS_TILL_EXPIRE (365*10) #define EXPIRE_SECS (60*60*24*DAYS_TILL_EXPIRE) #define AES_PASS_PHRASE "foo1foo2foo3foo4" // TORIAEZU #define HSM_MODULE_ID 1 const char *issuerNameDev = "NintendoCA - G2_NintendoCTR2dev"; const char *issuerNameProd = "NintendoCA - G2_NintendoCTR2prod"; // TORIAEZU : nFast variables NFast_AppHandle hsmHandle; NFastApp_Connection hsmConnection; NFKM_WorldInfo *hsmWorld = NULL; // allocate RQCard hsmCard; RQCard_FIPS hsmFips; M_KeyID hsmLtid; // AES M_KeyID hsmAeskeyid; const NFKM_KeyIdent hsmAeskeyident = { (char*)"simple", (char*)"aes-test-key" }; NFKM_Key *hsmAeskeyinfo = NULL; // allocate // RSA Private M_KeyID hsmRsaPrivkeyid, hsmRsaPubkeyid; const NFKM_KeyIdent hsmRsakeyident = { (char*)"simple", (char*)"rsa-priv-key-2048" }; NFKM_Key *hsmRsakeyinfo = NULL; // allocate NFKM_ModuleInfo *hsmModuleinfo = NULL; M_ByteBlock *hsmBlobptr = NULL; // functions static int hsm_generate_random( unsigned char *buf, int bytes ); static int hsm_get_rtc( time_t *time ); static struct _caInfo { X509 *cert; // 証明書 EVP_PKEY *privKey; // 秘密鍵 } caInfo; typedef struct _certEntry { char *key; char *value; } certEntry; #define ENTRY_COUNT 6 certEntry certEntries[ENTRY_COUNT] = { { "countryName", "JP" }, { "stateOrProvinceName", "KYOTO" }, { "localityName", "KYOTO" }, { "organizationName", "NINTENDO" }, { "organizationalUnitName", "CTR" }, { "commonName", "Device" } }; #if 0 typedef struct CTR_Device_Cert { u32 deviceID; u8 bonding_option; // u8 signatureAlgorithmIdentifier[x]; // openssl/crypto/objects/obj_dat.h辺りで定義? // u8 publicKeyAlgorithmIdentifier[x]; u8 timestamp[ 8 ]; u8 ca_name[ 16 ]; u8 public_key[ 61 ]; u8 signature[ 64 ]; } CTR_Device_Cert; #else // 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; #endif typedef struct { u32 magic_number; /* 0x00 - 0x03 = 0xdeadb00f 確定!*/ u32 serial[CR_NUM_OF_SERIAL]; /* 0x04 - 0x07 32bit device ID (32bit。1固定カウントアップ。) (本ID+randomの先頭0x1C bytesを組み合わせて、デバイス秘密鍵とする。) 0x08 - 0x0F 64bit CTR番号 seed (34bitのみ使用。1~4の乱数カウントアップ) 0x10 - 0x17 64bit 予備ID (64bitフルに使用。1~0x100000000の乱数カウントアップ) */ u8 version; /* 0x18 = CR_GEN_ID_VERSION = 1 */ u8 bondingOption; /* 0x19 ボンディングオプション */ u8 year; /* 0x1A デバイス証明書発行時間 (HSMから取得) */ u8 month; /* 0x1B */ u8 mday; /* 0x1C */ u8 hour; /* 0x1D */ u8 min; /* 0x1E */ u8 sec; /* 0x1F */ u8 devicePrivKey[ EC_PRIVATE_KEY_LENGTH ]; /* 0x20 - 0x3F ECC233 private key (big endian) ユニーク性保証なし */ u8 deviceCertSign[ ECDSA_SIGN_LENGTH ]; /* 0x40 - 0x83 ECC233 ECDSA signature (big endian) */ u8 reserved[ CR_RSV_LENGTH ]; /* 0x84 - 0x8F 予約 */ u8 random[ CR_RANDOM_LENGTH ]; /* 0x90 - 0xDF 乱数 */ u8 hash[ SHA256_DIGEST_LENGTH ]; /* 0xE0 - 0xFF "0x00-0xDF"領域のSHA256ハッシュ */ } CR_ID_BUFFER; /* 合計256bytes = 2048bit */ typedef struct { u32 magic_number; /* 0x00 - 0x03 0x01234567 確定!*/ u32 serial0; /* 0x04 - 0x07 */ u32 openssl_err_code; /* 0x08 - 0x0b */ s32 top; /* 0x0c - 0x0f */ s32 bottom; /* 0x10 - 0x13 */ /* #define ERR_NUM_ERRORS 16 */ u32 err_buffer[ERR_NUM_ERRORS]; /* 0x14 - 0x17 .... 0x50 - 0x53 */ //#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_REASON(l) (int)((l)&0xfffL) //#define ERR_FATAL_ERROR(l) (int)((l)&ERR_R_FATAL) s32 err_line[ERR_NUM_ERRORS]; /* 0x54 - 0x57 .... 0x90 - 0x93 */ } CR_ERR_BUFFER; int cr_print_flag = 0; // EC秘密鍵を生成 static int generate_EC_private_key( EC_KEY *eckey, u8 *privKey ) { int ret_code; BIGNUM *bn_privkey = NULL; #ifdef USE_SFMT // メルセンヌ・ツイスタ for ( i = 0; i < EC_PRIVATE_KEY_LENGTH; i++ ) { privKey[i] = (u8)gen_rand32(); } #else /* USE_SFMT */ ret_code = hsm_generate_random( privKey, EC_PRIVATE_KEY_LENGTH ); if ( ret_code != Status_OK ) { printf( "error(%d) : hsm_generate_random\n", ret_code ); return ret_code; } #endif /* USE_SFMT */ // ECC233 で30バイトだけ利用するので、後ろ2バイトは0で埋める // (DER(BER) が big endian なので、ここでは先頭2byte) // + 7bit clear privKey[ 0 ] = 0; privKey[ 1 ] = 0; privKey[ 2 ] &= 0x01; // 生成した秘密鍵をBNに変換して、eckeyにセット // ※bn_privkeyは、生成に成功した場合、ここではBN_freeされずにeckey要素の一つになって引き渡されます。 bn_privkey = BN_new(); if( bn_privkey == NULL ) { return CR_GENID_ERROR_BN_NEW_0; } BN_init( bn_privkey ); /* memset(a,0,sizeof(BIGNUM)); */ (void)BN_bin2bn( privKey, EC_PRIVATE_KEY_LENGTH, bn_privkey ); eckey->priv_key = bn_privkey; #ifdef DEBUG_PRINT 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 0; } // generate_EC_private_key // EC公開鍵を生成 static int generate_EC_public_key( EC_KEY *eckey ) { int ok = 0; BN_CTX *ctx = NULL; BIGNUM *priv_key = NULL, *order = NULL; EC_POINT *pub_key = NULL; if (!eckey || !eckey->group) { ECerr(EC_F_EC_KEY_GENERATE_KEY, ERR_R_PASSED_NULL_PARAMETER); return 0; } if ((order = BN_new()) == NULL) goto err; if ((ctx = BN_CTX_new()) == NULL) goto err; if (eckey->priv_key == NULL) { priv_key = BN_new(); if (priv_key == NULL) { goto err; } } else { priv_key = eckey->priv_key; } if (!EC_GROUP_get_order(eckey->group, order, ctx)) { goto err; } #if 0 // 2009.09.25 これが実行されると、秘密鍵が乱数化されてしまい、指定した秘密鍵と変わってしまうためコメントアウトする。 do if (!BN_rand_range(priv_key, order)) goto err; while (BN_is_zero(priv_key)); #endif if (eckey->pub_key == NULL) { pub_key = EC_POINT_new(eckey->group); if (pub_key == NULL) { goto err; } } else pub_key = eckey->pub_key; if (!EC_POINT_mul(eckey->group, pub_key, priv_key, NULL, NULL, ctx)) { goto err; } eckey->priv_key = priv_key; eckey->pub_key = pub_key; ok=1; err: if (order) BN_free(order); if (pub_key != NULL && eckey->pub_key == NULL) EC_POINT_free(pub_key); if (priv_key != NULL && eckey->priv_key == NULL) BN_free(priv_key); if (ctx != NULL) BN_CTX_free(ctx); return(ok); } // generate_EC_public_key // X.509 証明書要求を生成 static int generate_X509_csr( EVP_PKEY *evp_pkey, X509_REQ *req ) { int i = 0; int ok = 0; X509_NAME *subj; X509_REQ_set_pubkey( req, evp_pkey ); // subjectName 割り当て subj = X509_NAME_new(); if ( !subj ) { printf( "error : X509_NAME_new\n" ); return 0; // error } for ( i = 0; i < ENTRY_COUNT; i++ ) { int nid; X509_NAME_ENTRY *ent; nid = OBJ_txt2nid( certEntries[i].key ); if ( nid == NID_undef ) { printf( "Error finding NID for %s\n", certEntries[i].key ); return 0; // error } ent = X509_NAME_ENTRY_create_by_NID( NULL, nid, MBSTRING_ASC, certEntries[i].value, -1 ); if ( !ent ) { printf( "error : X509_NAME_ENTRY_create_by_NID\n" ); return 0; // error } if ( X509_NAME_add_entry( subj, ent, -1, 0 ) != 1 ) { printf( "error : X509_NAME_add_entry\n" ); return 0; // error } } if ( X509_REQ_set_subject_name( req, subj ) != 1 ) { printf( "error : X509_REQ_set_subject_name\n" ); return 0; // error } // todo : ここで v3 拡張領域をがんばる #if 0 // EVP_PKEYのタイプがECであるか確認 u16 type = EVP_PKEY_type( evp_pkey->type ); if ( type != EVP_PKEY_EC ) { printf( "error : EVP_PKEY_type, %d\n", type ); return 0; // error } #endif // 要求に署名する : ECDSA if ( !(X509_REQ_sign( req, evp_pkey, EVP_ecdsa() )) ) { printf( "error : X509_REQ_sign\n" ); return 0; // error } #if 0 // CSRの確認 if( cr_print_flag ) { X509_REQ_print_fp( stdout, req ); } #endif ok = 1; return ( ok ); } // generate_X509_csr // X.509 証明書を生成 static int generate_X509_cert( EVP_PKEY *evp_pkey, X509_REQ *req, X509 *cert, u32 deviceId ) { int ok = 0; X509_NAME *name; #if 1 // 要求書に付いている署名の検証を行う EVP_PKEY *pkey; pkey = X509_REQ_get_pubkey( req ); if ( !pkey ) { printf( "error : X509_REQ_get_pubkey\n" ); return 0; // error } if ( X509_REQ_verify( req, pkey ) != 1 ) { printf( "error : X509_REQ_verify\n" ); return 0; // error } EVP_PKEY_free( pkey ); #endif #if 0 // show subjectName name = X509_REQ_get_subject_name( req ); if ( !name ) { printf( "error : X509_REQ_get_subject_name\n" ); return 0; // error } X509_NAME_print_ex_fp( stdout, name, 0, 0 ); printf( "\n" ); #endif // set version = 3 (0x2) if ( X509_set_version( cert, 2L ) != 1 ) { printf( "error : X509_set_version\n" ); return 0; // error } ASN1_INTEGER_set( X509_get_serialNumber( cert ), deviceId ); // 証明書の発行者名と所有者名を設定 name = X509_REQ_get_subject_name( req ); if ( !name ) { printf( "error : X509_REQ_get_subject_name\n" ); return 0; // error } if ( X509_set_subject_name( cert, name ) != 1 ) { printf( "error : X509_set_subject_name\n" ); return 0; // error } name = X509_get_subject_name( caInfo.cert ); if ( !name ) { printf( "error : X509_get_subject_name\n" ); return 0; // error } if ( X509_set_issuer_name( cert, name ) != 1 ) { printf( "error : X509_set_issuer_name\n" ); return 0; // error } // 証明書に公開鍵を設定する if ( X509_set_pubkey( cert, evp_pkey ) != 1 ) { printf( "error : X509_set_pubkey\n" ); return 0; // error } // 証明書の有効期間を設定する if ( !(X509_gmtime_adj( X509_get_notBefore( cert ), 0 )) ) { printf( "error : X509_gmtime_adj before\n" ); return 0; // error } if ( !(X509_gmtime_adj( X509_get_notAfter( cert ), EXPIRE_SECS )) ) { printf( "error : X509_gmtime_adj after\n" ); return 0; // error } // CAの秘密鍵を使って証明書に署名する //EVP_MD *dgst = EVP_ecdsa(); //printf( "dgst length : %d\n", dgst->md_size ); if ( !(X509_sign( cert, caInfo.privKey, EVP_ecdsa() )) ) { printf( "error : X509_sign\n" ); return 0; // error } #if 0 // 証明書確認 if ( cr_print_flag ) { X509_print_fp( stdout, cert ); } #endif #if 0 if ( cr_print_flag ) { 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 #if 0 // 証明書の書き込みテスト FILE *fp; char fn[256]; sprintf( fn, "output/0x%08x.crt", deviceId ); fp = fopen( fn, "w" ); PEM_write_X509( fp, cert ); fclose( fp ); #endif ok = 1; return (ok); } // generate_X509_cert // create CTR Custom cert static int generate_CTRCustom_cert( CTR_Device_Cert *cert, u32 deviceId, u8 bondingOption ) { int result; char str[80]; // 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 result = hsm_get_rtc( &cert->expiryDate ); if ( result != 0 ) { printf( "error(%d) : hsm_get_rtc\n", result ); return result; } #if 0 if ( cr_print_flag ) { int i; printf( "CTR custom cert\n" ); printf( "sigType : 0x%08X\n", *(unsigned int*)cert->sigType ); printf( "eccSignature :" ); for ( i = 0; i < 60; i++ ) { if ( i % 16 == 0 ) 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( "keyType : 0x%08X\n", *(unsigned int*)cert->keyType ); printf( "subject : " ); for ( i = 0; i < 64; i++ ) printf( "%c", cert->subject[i] ); printf( "\n" ); printf( "expiryDate : 0x%08X\n", (unsigned int)cert->expiryDate ); printf( "eccPubKey :" ); for ( i = 0; i < 60; i++ ) { 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; 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 ); } #endif return 0; } // generate_CTRCustom_cert #ifndef ENCRYPT_AES // RSA暗号化->復号化->ベリファイ static unsigned char local_rsa_buf_1[CR_ID_BUF_SIZE]; static unsigned char local_rsa_buf_2[CR_ID_BUF_SIZE]; #ifdef DEV_CYGWIN static int crypto_rsa_enc_dec( RSA *rsa_key_pub, RSA *rsa_key_priv, unsigned char *dst_buf,unsigned char *org_buf) { int rsa_outlen = 0; memset(local_rsa_buf_1, 0,CR_ID_BUF_SIZE); memset(local_rsa_buf_2, 0,CR_ID_BUF_SIZE); if( (rsa_outlen = RSA_private_encrypt(CR_ID_BUF_SIZE, org_buf, local_rsa_buf_1, rsa_key_priv, RSA_NO_PADDING)) == -1) { return CR_GENID_ERROR_RSA_ENC; } else { if((rsa_outlen = RSA_public_decrypt(rsa_outlen, local_rsa_buf_1, local_rsa_buf_2, rsa_key_pub, RSA_NO_PADDING)) == -1) { return CR_GENID_ERROR_RSA_DEC; } else { int i; int error_flag = 0; for( i = 0 ; i < CR_ID_BUF_SIZE ; i++ ) { if( org_buf[i] != local_rsa_buf_2[i] ) { error_flag++; } } if( error_flag ) { return CR_GENID_ERROR_RSA_VERIFY; } } } memcpy(dst_buf,local_rsa_buf_1,CR_ID_BUF_SIZE); return 0; } #else // cygwin static int hsm_crypto_rsa_enc_dec( unsigned char *dst_buf,unsigned char *org_buf ) { int i, ret_code; M_Command cmd; M_Reply reply; M_IV enc_iv, dec_iv; ret_code = 0; memset( &cmd, 0, sizeof( cmd ) ); memset( &reply, 0, sizeof( reply ) ); // iv enc_iv.mech = dec_iv.mech = Mech_RSApPKCS1; 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; for ( i = 0; i < 256; i++ ) { if ( i % 16 == 0 ) printf( "\n" ); printf( "0x%02X ", org_buf[i] ); } printf( "\n" ); // encrypt cmd.cmd = Cmd_Encrypt; cmd.args.encrypt.flags = Cmd_Encrypt_Args_flags_given_iv_present; cmd.args.encrypt.key = hsmRsaPubkeyid; cmd.args.encrypt.mech = Mech_RSApPKCS1; cmd.args.encrypt.plain.type = PlainTextType_Bytes; cmd.args.encrypt.plain.data.bytes.data.len = CR_ID_BUF_SIZE; cmd.args.encrypt.plain.data.bytes.data.ptr = org_buf; cmd.args.encrypt.given_iv = &enc_iv; ret_code = NFastApp_Transact( hsmConnection, NULL, &cmd, &reply, NULL ); if ( ret_code != Status_OK ) { printf( "error(%d) : Encryption by HSM\n", ret_code ); } ret_code = reply.status; if ( ret_code != Status_OK ) { printf( "error(%d) : Encrypt Reply Status by HSM\n", ret_code ); } memcpy( local_rsa_buf_1, reply.reply.encrypt.cipher.data.generic128.cipher.ptr, CR_ID_BUF_SIZE ); //NFastApp_Free_Command( hsmHandle, NULL, NULL, &cmd ); NFastApp_Free_Reply( hsmHandle, NULL, NULL, &reply ); memset( &cmd, 0, sizeof( cmd ) ); memset( &reply, 0, sizeof( reply ) ); // decyrpt cmd.cmd = Cmd_Decrypt; cmd.args.decrypt.flags = 0; cmd.args.decrypt.key = hsmAeskeyid; cmd.args.decrypt.mech = Mech_RijndaelmCBCpNONE; cmd.args.decrypt.cipher.mech = Mech_RijndaelmCBCpNONE; cmd.args.decrypt.cipher.data.generic128.cipher.len = CR_ID_BUF_SIZE; cmd.args.decrypt.cipher.data.generic128.cipher.ptr = local_rsa_buf_1; cmd.args.decrypt.cipher.iv = dec_iv.iv; cmd.args.decrypt.reply_type = PlainTextType_Bytes; ret_code = NFastApp_Transact( hsmConnection, NULL, &cmd, &reply, NULL ); if ( ret_code != Status_OK ) { printf( "error(%d) : Decryption by HSM\n", ret_code ); } ret_code = reply.status; if ( ret_code != Status_OK ) { printf( "error(%d) : Decrypt Reply Status by HSM\n", ret_code ); } memcpy( local_rsa_buf_2, reply.reply.decrypt.plain.data.bytes.data.ptr, CR_ID_BUF_SIZE ); //NFastApp_Free_Command( hsmHandle, NULL, NULL, &cmd ); NFastApp_Free_Reply( hsmHandle, NULL, NULL, &reply ); // ベリファイ for ( i = 0 ; i < CR_ID_BUF_SIZE ; i++ ) { if( org_buf[i] != local_rsa_buf_2[i] ) { printf( "error : aes verify\n" ); return 0; } } // バッファコピー memcpy( dst_buf, local_rsa_buf_1, CR_ID_BUF_SIZE ); return 0; } // hsm_crypto_rsa_enc_dec #endif // linux #else // AES暗号化 -> 復号化 -> ベリファイ static unsigned char local_aes_buf_1[ CR_ID_BUF_SIZE ]; static unsigned char local_aes_buf_2[ CR_ID_BUF_SIZE ]; #ifdef DEV_CYGWIN static int crypto_aes_enc_dec( unsigned char *dst_buf, unsigned char *org_buf ) { int i; AES_KEY aesEncKey; AES_KEY aesDecKey; u8 temp_iv[16]; memset( local_aes_buf_1, 0, CR_ID_BUF_SIZE ); memset( local_aes_buf_2, 0, CR_ID_BUF_SIZE ); // AES 暗号化用鍵 作成 if ( AES_set_encrypt_key( AES_PASS_PHRASE, 128, &aesEncKey ) != 0 ) { printf( "error : AES_set_encrypt_key\n" ); return 0; } // AES 復号化用鍵 作成 if ( AES_set_decrypt_key( AES_PASS_PHRASE, 128, &aesDecKey ) != 0 ) { printf( "error : AES_set_decrypt_key\n" ); return 0; } // iv 初期化 for ( i = 0; i < 16; i++ ) { temp_iv[i] = i; } // AES 暗号化 AES_cbc_encrypt ( org_buf, local_aes_buf_1, CR_ID_BUF_SIZE, &aesEncKey, temp_iv, AES_ENCRYPT ); // iv 初期化 for ( i = 0; i < 16; i++ ) { temp_iv[i] = i; } // AES 復号化 AES_cbc_encrypt ( local_aes_buf_1, local_aes_buf_2, CR_ID_BUF_SIZE, &aesDecKey, temp_iv, AES_DECRYPT ); // ベリファイ for ( i = 0 ; i < CR_ID_BUF_SIZE ; i++ ) { if( org_buf[i] != local_aes_buf_2[i] ) { printf( "error : aes verify\n" ); return 0; } } // バッファコピー memcpy( dst_buf, local_aes_buf_1, CR_ID_BUF_SIZE ); return 0; } // crypto_aes_enc_dec #else // DEV_CYGWIN(openssl) static int hsm_crypto_aes_enc_dec( unsigned char *dst_buf, unsigned char *org_buf ) { int i, ret_code; M_Command cmd; M_Reply reply; M_IV enc_iv, dec_iv; ret_code = 0; memset( &cmd, 0, sizeof( cmd ) ); memset( &reply, 0, sizeof( reply ) ); // iv enc_iv.mech = dec_iv.mech = Mech_RijndaelmCBCpNONE; for ( i = 0; i < 16; i++ ) enc_iv.iv.generic128.iv.bytes[i] = dec_iv.iv.generic128.iv.bytes[i] = i; // encrypt cmd.cmd = Cmd_Encrypt; cmd.args.encrypt.key = hsmAeskeyid; cmd.args.encrypt.mech = Mech_RijndaelmCBCpNONE; cmd.args.encrypt.plain.type = PlainTextType_Bytes; cmd.args.encrypt.plain.data.bytes.data.len = CR_ID_BUF_SIZE; cmd.args.encrypt.plain.data.bytes.data.ptr = org_buf; cmd.args.encrypt.flags = Cmd_Encrypt_Args_flags_given_iv_present; cmd.args.encrypt.given_iv = &enc_iv; ret_code = NFastApp_Transact( hsmConnection, NULL, &cmd, &reply, NULL ); if ( ret_code != Status_OK ) { printf( "error(%d) : Encryption by HSM\n", ret_code ); } ret_code = reply.status; if ( ret_code != Status_OK ) { printf( "error(%d) : Encrypt Reply Status by HSM\n", ret_code ); } memcpy( local_aes_buf_1, reply.reply.encrypt.cipher.data.generic128.cipher.ptr, CR_ID_BUF_SIZE ); //NFastApp_Free_Command( hsmHandle, NULL, NULL, &cmd ); NFastApp_Free_Reply( hsmHandle, NULL, NULL, &reply ); memset( &cmd, 0, sizeof( cmd ) ); memset( &reply, 0, sizeof( reply ) ); // decyrpt cmd.cmd = Cmd_Decrypt; cmd.args.decrypt.flags = 0; cmd.args.decrypt.key = hsmAeskeyid; cmd.args.decrypt.mech = Mech_RijndaelmCBCpNONE; cmd.args.decrypt.cipher.mech = Mech_RijndaelmCBCpNONE; cmd.args.decrypt.cipher.data.generic128.cipher.len = CR_ID_BUF_SIZE; cmd.args.decrypt.cipher.data.generic128.cipher.ptr = local_aes_buf_1; cmd.args.decrypt.cipher.iv = dec_iv.iv; cmd.args.decrypt.reply_type = PlainTextType_Bytes; ret_code = NFastApp_Transact( hsmConnection, NULL, &cmd, &reply, NULL ); if ( ret_code != Status_OK ) { printf( "error(%d) : Decryption by HSM\n", ret_code ); } ret_code = reply.status; if ( ret_code != Status_OK ) { printf( "error(%d) : Decrypt Reply Status by HSM\n", ret_code ); } memcpy( local_aes_buf_2, reply.reply.decrypt.plain.data.bytes.data.ptr, CR_ID_BUF_SIZE ); //NFastApp_Free_Command( hsmHandle, NULL, NULL, &cmd ); NFastApp_Free_Reply( hsmHandle, NULL, NULL, &reply ); // ベリファイ for ( i = 0 ; i < CR_ID_BUF_SIZE ; i++ ) { if( org_buf[i] != local_aes_buf_2[i] ) { printf( "error : aes verify\n" ); return 0; } } // バッファコピー memcpy( dst_buf, local_aes_buf_1, CR_ID_BUF_SIZE ); return 0; } // hsm_crypto_aes_enc_dec #endif // HSM #endif static int hsm_generate_random( unsigned char *buf, int bytes ) { int ret_code; M_Command cmd; M_Reply reply; memset( &cmd, 0, sizeof( cmd ) ); memset( &reply, 0, sizeof( reply ) ); cmd.cmd = Cmd_GenerateRandom; cmd.args.generaterandom.lenbytes = bytes; ret_code = NFastApp_Transact( hsmConnection, NULL, &cmd, &reply, NULL ); if ( ret_code != Status_OK ) { printf( "error(%d) : generate random\n", ret_code ); return ret_code; } ret_code = reply.status; if ( ret_code != Status_OK ) { printf( "error(%d) : generate random reply\n", ret_code ); return ret_code; } // buffer copy memcpy( buf, reply.reply.generaterandom.data.ptr, bytes ); NFastApp_Free_Command( hsmHandle, NULL, NULL, &cmd ); NFastApp_Free_Reply( hsmHandle, NULL, NULL, &reply ); return 0; } // hsm_generate_rand #if 0 static int hsm_set_rtc( struct timeval time ) { int result; M_Command cmd; M_Reply reply; memset( &cmd, 0, sizeof( cmd ) ); memset( &reply, 0, sizeof( reply ) ); cmd.cmd = Cmd_SetRTC; cmd.args.setrtc.module = HSM_MODULE_ID; cmd.args.setrtc.time.currenttimelow = time.tv_sec; result = NFastApp_Transact( hsmConnection, NULL, &cmd, &reply, NULL ); if ( result != Status_OK ) { printf( "error(%d) : set rtc(transaction)\n", result ); return result; } result = reply.status; if ( result != Status_OK ) { printf( "error(%d) : set rtc(reply status)\n", result ); return result; } return 0; } #endif static int hsm_get_rtc( time_t *time ) { int result; M_Command cmd; M_Reply reply; memset( &cmd, 0, sizeof( cmd ) ); memset( &reply, 0, sizeof( reply ) ); cmd.cmd = Cmd_GetRTC; cmd.args.getrtc.module = HSM_MODULE_ID; result = NFastApp_Transact( hsmConnection, NULL, &cmd, &reply, NULL ); if ( result != Status_OK ) { printf( "error(%d) : get rtc(transaction)\n", result ); return result; } result = reply.status; if ( result != Status_OK ) { printf( "error(%d) : get rtc(reply status)\n", result ); return result; } *time = (int)reply.reply.getrtc.time.currenttimelow; return 0; } // hsm_get_rtc int cr_generate_id_initialize( void ) { int ret_code = 0; FILE *fp; // init HSM ret_code = NFastApp_InitEx( &hsmHandle, NULL, NULL ); if ( ret_code != Status_OK ) { printf( "error(%d) : NFastApp_InitEx\n", ret_code ); return ret_code; } // set BigNum upcalls for HSM ret_code = NFastApp_SetBignumUpcalls( hsmHandle, sbn_bignumreceiveupcall, sbn_bignumsendlenupcall, sbn_bignumsendupcall, sbn_bignumfreeupcall, sbn_bignumformatupcall, NULL ); if ( ret_code != Status_OK ) { printf( "error(%d) : NFastApp_SetBignumUpcalls\n", ret_code ); } // connect HSM // arg3 is flag // NFastApp_ConnectionFlags_Privileged flag need to run by nfast user. ret_code = NFastApp_Connect( hsmHandle, &hsmConnection, 0, NULL ); if ( ret_code != Status_OK ) { printf( "error(%d) : NFastApp_Connect\n", ret_code ); } // get NFKM info ret_code = NFKM_getinfo( hsmHandle, &hsmWorld, NULL ); if ( ret_code != Status_OK ) { printf( "error(%d) : NFKM_getinfo\n", ret_code ); } // init Card-Loading Lib(RQCard) ret_code = RQCard_init( &hsmCard, hsmHandle, hsmConnection, hsmWorld, NULL ); if ( ret_code != Status_OK ) { printf( "error(%d) : RQCard_init\n", ret_code ); } // init FIPS state ret_code = RQCard_fips_init( &hsmCard, &hsmFips ); if ( ret_code != Status_OK ) { printf( "error(%d) : RQCard_fips_init\n", ret_code ); } // select Card-Auth UI ret_code = RQCard_ui_scroll( &hsmCard ); if ( ret_code != Status_OK ) { printf( "error(%d) : RQCard_ui_scroll\n", ret_code ); } // load AES key object { // find key ret_code = NFKM_findkey( hsmHandle, hsmAeskeyident, &hsmAeskeyinfo, NULL ); if ( ret_code != Status_OK ) { printf( "error(%d) : NFKM_findkey\n", ret_code ); } // if Key_flags_ProtectionCardSet is enable, eventloop is an essential. if ( hsmAeskeyinfo->flags & Key_flags_ProtectionCardSet ) { // load specific OCS ret_code = RQCard_logic_ocs_specific( &hsmCard, &hsmAeskeyinfo->cardset, NULL ); if ( ret_code != Status_OK ) { printf( "error(%d) : RQCard_logic_ocs_specific\n", ret_code ); } // use specific Module ret_code = RQCard_whichmodule_specific( &hsmCard, HSM_MODULE_ID, &hsmLtid ); if ( ret_code != Status_OK ) { printf( "error(%d) : RQCard_whichmodule_specific\n", ret_code ); } // eventloop ret_code = hsmCard.uf->eventloop( &hsmCard ); if ( ret_code != Status_OK ) { printf( "error(%d) : Card eventloop\n", ret_code ); } } // get usable Module hsmModuleinfo = hsmWorld->modules[0]; ret_code = NFKM_getusablemodule( hsmWorld, HSM_MODULE_ID, &hsmModuleinfo ); if ( ret_code != Status_OK ) { printf( "error(%d) : NFKM_getusablemodule\n", ret_code ); } // load key blob if ( hsmAeskeyinfo->pubblob.len ) hsmBlobptr = &hsmAeskeyinfo->pubblob; else hsmBlobptr = &hsmAeskeyinfo->privblob; ret_code = NFKM_cmd_loadblob( hsmHandle, hsmConnection, hsmModuleinfo->module, hsmBlobptr, hsmLtid, &hsmAeskeyid, "loading key blob", NULL ); if ( ret_code != Status_OK ) { printf( "error(%d) : NFKM_cmd_loadblob\n", ret_code ); } printf( "AES key object load : ok\n" ); } // load AES key object // load RSA private key object { // find key ret_code = NFKM_findkey( hsmHandle, hsmRsakeyident, &hsmRsakeyinfo, NULL ); if ( ret_code != Status_OK ) { printf( "error(%d) : NFKM_findkey\n", ret_code ); } // if Key_flags_ProtectionCardSet is enable, eventloop is an essential. if ( hsmRsakeyinfo->flags & Key_flags_ProtectionCardSet ) { // load specific OCS ret_code = RQCard_logic_ocs_specific( &hsmCard, &hsmRsakeyinfo->cardset, NULL ); if ( ret_code != Status_OK ) { printf( "error(%d) : RQCard_logic_ocs_specific\n", ret_code ); } // use specific Module ret_code = RQCard_whichmodule_specific( &hsmCard, HSM_MODULE_ID, &hsmLtid ); if ( ret_code != Status_OK ) { printf( "error(%d) : RQCard_whichmodule_specific\n", ret_code ); } // eventloop ret_code = hsmCard.uf->eventloop( &hsmCard ); if ( ret_code != Status_OK ) { printf( "error(%d) : Card eventloop\n", ret_code ); } } // get usable Module hsmModuleinfo = hsmWorld->modules[0]; ret_code = NFKM_getusablemodule( hsmWorld, HSM_MODULE_ID, &hsmModuleinfo ); if ( ret_code != Status_OK ) { printf( "error(%d) : NFKM_getusablemodule\n", ret_code ); } // load key blob printf( "pubblob.len : %d, privblob.len : %d\n", (int)hsmRsakeyinfo->pubblob.len, (int)hsmRsakeyinfo->privblob.len ); hsmBlobptr = &hsmRsakeyinfo->privblob; ret_code = NFKM_cmd_loadblob( hsmHandle, hsmConnection, hsmModuleinfo->module, hsmBlobptr, hsmLtid, &hsmRsaPrivkeyid, "loading priv-key blob", NULL ); if ( ret_code != Status_OK ) { printf( "error(%d) : NFKM_cmd_loadblob(priv-key)\n", ret_code ); } printf( "RSA private key object load : ok\n" ); hsmBlobptr = &hsmRsakeyinfo->pubblob; ret_code = NFKM_cmd_loadblob( hsmHandle, hsmConnection, hsmModuleinfo->module, hsmBlobptr, hsmLtid, &hsmRsaPubkeyid, "loading pub-key blob", NULL ); if ( ret_code != Status_OK ) { printf( "error(%d) : NFKM_cmd_loadblob(pub-key)\n", ret_code ); } printf( "RSA public key object load : ok\n" ); // get key info { M_Command cmd; M_Reply reply; memset( &cmd, 0, sizeof( cmd ) ); memset( &reply, 0, sizeof( reply ) ); cmd.cmd = Cmd_GetKeyInfo; cmd.args.getkeyinfo.key = hsmRsaPrivkeyid; ret_code = NFastApp_Transact( hsmConnection, NULL, &cmd, &reply, NULL ); if ( ret_code != Status_OK ) { printf( "error(%d) : FastApp_Transact(Cmd_GetKeyInfo)\n", ret_code ); } } #if 0 // get & set key acl { int i, j; M_Command cmd; M_Reply reply; M_ACL newACL; memset( &cmd, 0, sizeof( cmd ) ); memset( &reply, 0, sizeof( reply ) ); // GetACL cmd.cmd = Cmd_GetACL; cmd.args.getacl.key = hsmRsaPrivkeyid; ret_code = NFastApp_Transact( hsmConnection, NULL, &cmd, &reply, NULL ); if ( ret_code != Status_OK ) { printf( "error(%d) : FastApp_Transact(Cmd_GetKeyInfo)\n", ret_code ); } printf( "n_groups : %d\n", reply.reply.getacl.acl.n_groups ); for ( i = 0; i < reply.reply.getacl.acl.n_groups; i++ ) { printf( "group[%d] : %d actions ok.\n", i, reply.reply.getacl.acl.groups[i].n_actions ); for ( j = 0; j < reply.reply.getacl.acl.groups[i].n_actions; j++ ) { if ( reply.reply.getacl.acl.groups[i].actions[j].type == 1 ) // Act_OpPermissions printf( "OpPermissions : %08X\n", (int)reply.reply.getacl.acl.groups[i].actions[j].details.oppermissions.perms ); } } newACL = reply.reply.getacl.acl; memset( &cmd, 0, sizeof( cmd ) ); memset( &reply, 0, sizeof( reply ) ); NFastApp_Free_Reply( hsmHandle, NULL, NULL, &reply ); // find cardsets NFKM_CardSet *cardset = NULL; ret_code = NFKM_findcardset( hsmHandle, &(hsmRsakeyinfo->cardset), &cardset, NULL ); if ( ret_code != Status_OK ) { printf( "error(%d) : NFKM_findcardset\n", ret_code ); } #if 0 // make new ACL NFKM_MakeACLParams map; NFKM_MakeBlobsParams mbp; M_ACL newACL; memset( &map, 0, sizeof( map ) ); map.f = NFKM_NKF_RecoveryEnabled | NFKM_NKF_ProtectionCardSet; map.op_base = (NFKM_DEFOPPERMS_SIGN | NFKM_DEFOPPERMS_VERIFY | NFKM_DEFOPPERMS_ENCRYPT | NFKM_DEFOPPERMS_DECRYPT ); map.cs = cardset; ret_code = NFKM_newkey_makeaclx( hsmHandle, hsmConnection, hsmWorld, &map, &newACL, NULL ); if ( ret_code != Status_OK ) { printf( "error(%d) : NFKM_newkey_makeaclx\n", ret_code ); } #endif // SetACL cmd.cmd = Cmd_SetACL; cmd.args.setacl.key = hsmRsaPrivkeyid; cmd.args.setacl.newacl = newACL; ret_code = NFastApp_Transact( hsmConnection, NULL, &cmd, &reply, NULL ); if ( ret_code != Status_OK ) { printf( "error(%d) : set acl(transaction)\n", ret_code ); } ret_code = reply.status; if ( ret_code != Status_OK ) { printf( "error(%d) : set acl(reply status)\n", ret_code ); } } #endif } // load RSA private key object // CAの証明書を読み込む fp = fopen( CA_FILE, "r" ); if ( !fp ) { printf( "error : read CA_Cert file\n" ); return 0; // error } caInfo.cert = PEM_read_X509( fp, NULL, NULL, NULL ); if ( !(caInfo.cert) ) { printf( "error : read CA_Cert in file\n" ); return 0; // error } fclose( fp ); #if 0 // CAの証明書確認 if ( cr_print_flag ) { X509_print_fp( stdout, caCert ); } #endif // CAの秘密鍵を読み込む fp = fopen( CA_KEY, "r" ); if ( !fp ) { printf( "error : read CA_KEY file\n" ); return 0; // error } caInfo.privKey = PEM_read_PrivateKey( fp, NULL, NULL, NULL ); if ( !(caInfo.privKey) ) { printf( "error : read CA_KEY in file\n" ); return 0; // error } fclose( fp ); ret_code = 1; return ( ret_code ); } // cr_generate_id_initialize int cr_generate_id_finalize( void ) { int ok = 0; // openssl ERR_remove_state(0); EVP_cleanup(); CRYPTO_cleanup_all_ex_data(); // HSM RQCard_fips_free( &hsmCard, &hsmFips ); RQCard_destroy( &hsmCard ); NFKM_freekey( hsmHandle, hsmAeskeyinfo, NULL ); NFKM_freeinfo( hsmHandle, &hsmWorld, NULL ); NFastApp_Disconnect( hsmConnection, NULL ); NFastApp_Finish( hsmHandle, NULL ); ok = 1; return ( ok ); } // cr_generate_id_finalize /* unsigned long ERR_get_error(void); エラーが起こったとき id_buf にエラーログを返すか? */ int cr_generate_id( u32 serial[CR_NUM_OF_SERIAL], u8 id_buf[CR_ID_BUF_SIZE], u8 bondingOption ) { int i; int ret_code; EC_KEY *my_eckey = NULL; EVP_PKEY *my_evppkey = NULL; RSA *rsa_privkey = NULL; RSA *rsa_pubkey = NULL; X509_REQ *req = NULL; X509 *cert = NULL; struct tm *tm_time; struct timeval tv; struct timezone tz; CR_ID_BUFFER *cr_id_buf; u8 hash[SHA256_DIGEST_LENGTH]; /* SHA256 check */ CTR_Device_Cert ctr_dev_cert; if( sizeof(CR_ID_BUFFER) != 256 ) { ret_code = CR_GENID_ERROR_ID_BUF_SIZE; goto end; } if( sizeof(CR_ERR_BUFFER) > 256 ) { ret_code = CR_GENID_ERROR_ERR_BUF_SIZE; goto end; } if ( sizeof( CTR_Device_Cert ) > 384 ) { //ret_code = CR_GENID_ERROR_CERT_BUF_SIZE; // ATODE goto end; } 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 ) ); // 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 ) ); // ダイジェストアルゴリズムを追加する #if 0 OpenSSL_add_all_digests(); #else EVP_add_digest( EVP_ecdsa() ); #endif //-------------------------------------------------------------- // 暗号処理初期化 //-------------------------------------------------------------- // メモリリーク防止のため、オリジナルのアロケータを使用。 CRYPTO_set_mem_functions(cr_mem_malloc, cr_mem_realloc, cr_mem_free); cr_mem_bufmgr_initialize(); #ifdef MY_CRYPTO_DEBUG ERR_load_crypto_strings(); #endif /* MY_CRYPTO_DEBUG */ //-------------------------------------------------------------- // FuseIDバッファに固定データセット //-------------------------------------------------------------- memset(id_buf, 0, CR_ID_BUF_SIZE); cr_id_buf = (CR_ID_BUFFER *)id_buf; cr_id_buf->magic_number = 0xdeadb00f; /* 0xdeadbeefにするとRSAでコケる。 */ cr_id_buf->version = CR_GEN_ID_VERSION; //-------------------------------------------------------------- // 引数のボンディングオプションをセット //-------------------------------------------------------------- cr_id_buf->bondingOption = bondingOption; //-------------------------------------------------------------- // serialNo.セット //-------------------------------------------------------------- for( i = 0 ; i < CR_NUM_OF_SERIAL ; i++ ) { cr_id_buf->serial[i] = serial[i]; /* serial[0] => ec priv key */ } //#ifdef DEBUG_PRINT #if 1 if( cr_print_flag ) { printf("serialNo:\n"); for( i = 0 ; i < CR_NUM_OF_SERIAL ; i++ ) { if( i == 0 ) printf(" 0x%08x\n", (unsigned int)serial[i] ); else if( i & 0x01 ) printf(" 0x%08x", (unsigned int)serial[i] ); else printf("%08x\n", (unsigned int)serial[i] ); } printf("\n"); } #endif /* DEBUG_PRINT */ //-------------------------------------------------------------- // タイムスタンプセット //-------------------------------------------------------------- hsm_get_rtc( &tv.tv_sec ); tm_time = gmtime( &tv.tv_sec ); #ifdef DEBUG_PRINT if( cr_print_flag ) { printf("GMT:%d-%02d-%02d %02d:%02d:%02d\n", tm_time->tm_year+1900, /* 年 */ tm_time->tm_mon+1, /* 月 */ tm_time->tm_mday, /* 日 */ tm_time->tm_hour, /* 時 */ tm_time->tm_min, /* 分 */ tm_time->tm_sec /* 秒 */ ); } #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; //-------------------------------------------------------------- // 乱数を生成してセット //-------------------------------------------------------------- ret_code = hsm_generate_random( cr_id_buf->random, CR_RANDOM_LENGTH ); if ( ret_code != Status_OK ) { printf( "error(%d) : hsm_generate_random\n", ret_code ); return ret_code; } #ifdef DEBUG_PRINT 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 */ //-------------------------------------------------------------- // 楕円曲線鍵ペアを生成 //-------------------------------------------------------------- // 楕円を選択 ( NID_X9_62_prime256v1 -> 32bytesまで、 NID_sect571r1 -> 71bytesまで 署名にデータを含められる ) my_eckey = EC_KEY_new_by_curve_name( NID_sect233r1 ); if( my_eckey == NULL ) { ret_code = CR_GENID_ERROR_EC_KEY_NEW_1; goto end; } // 秘密鍵生成 ret_code = generate_EC_private_key( my_eckey, cr_id_buf->devicePrivKey ); if( ret_code != 0 ) { ret_code = CR_GENID_ERROR_EC_GENERATE_PRIVATE_KEY; goto end; } // 公開鍵生成 ret_code = generate_EC_public_key( my_eckey ); if ( ret_code == 0 ) { ret_code = CR_GENID_ERROR_EC_GENERATE_PUBLIC_KEY; goto end; } // ASN.1 形式指定フラグをセットする // (これをセットしないと色々変なフィールドが入ってしまうため) EC_KEY_set_asn1_flag( my_eckey, 1 ); ret_code = CR_GENID_ERROR_NON; // TORIAEZU #if 0 //-------------------------------------------------------------- // 生成した鍵ペアをECDSAで動作確認 //-------------------------------------------------------------- ret_code = TestECDSA( hoge hoge ); // 当然やるべき #endif //-------------------------------------------------------------- // 証明書の発行に先立ってEVP_PKEYオブジェクトを生成する //-------------------------------------------------------------- // EC_KEYを元にEVP_PKEYを生成 my_evppkey = EVP_PKEY_new(); if ( !my_evppkey ) { printf( "error : EVP_PKEY_new\n" ); return 0; // error } // assign_EC_KEY だと、鍵オブジェクトを所有するため、メモリリークする? #if 1 if ( !EVP_PKEY_set1_EC_KEY( my_evppkey, my_eckey ) ) { printf( "error : EVP_PKEY_set1_EC_KEY\n" ); return 0; // error } #else if ( !EVP_PKEY_assign_EC_KEY( my_evppkey, my_eckey) ) { printf( "error : EVP_PKEY_assign_EC_KEY\n" ); return 0; // error } #endif //printf( "evp_pkey size : %d\n", EVP_PKEY_size( my_evppkey ) ); //-------------------------------------------------------------- // デバイス証明書要求生成 //-------------------------------------------------------------- req = X509_REQ_new(); // 呼び出し先で new すると正しくメモリ確保されない? if ( !req ) { printf( "error : X509_REQ_new\n" ); return 0; // error } generate_X509_csr( my_evppkey, req ); //-------------------------------------------------------------- // デバイス証明書発行 (X.509 v3) //-------------------------------------------------------------- cert = X509_new(); // 呼び出し先で new すると正しくメモリ確保されない? if ( !cert ) { printf( "error : X509_new\n" ); return 0; // error } generate_X509_cert( my_evppkey, req, cert, cr_id_buf->serial[0] ); //-------------------------------------------------------------- // デバイス証明書の署名をセット //-------------------------------------------------------------- int padding = ECDSA_SIGN_LENGTH % cert->signature->length; for ( i = 0; i < padding; i++ ) cr_id_buf->deviceCertSign[i] = 0; for ( i = 0; i < cert->signature->length; i++ ) cr_id_buf->deviceCertSign[ i + padding ] = cert->signature->data[i]; // mistake!! // TORIAEZU : create Custom cert memset( &ctr_dev_cert, 0, sizeof( ctr_dev_cert ) ); // copy ecpubkey to Custom cert int len = BN_num_bytes( &my_eckey->pub_key->X ); u8 *buf = (u8*)malloc( len ); len = BN_bn2bin( &my_eckey->pub_key->X, buf ); memcpy( ctr_dev_cert.eccPubKey, buf, len ); free( buf ); len = BN_num_bytes( &my_eckey->pub_key->Y ); buf = (u8*)malloc( len ); len = BN_bn2bin( &my_eckey->pub_key->Y, buf ); memcpy( &ctr_dev_cert.eccPubKey[30], buf, len ); free( buf ); // copy sign to Custom cert //#define SHOW_SIG u8 *ptr = cert->signature->data; #ifdef SHOW_SIG printf( "signature\n" ); printf( "SEQUENCE : 0x%02X\n", *(ptr++) ); printf( "ALL_LEN : 0x%02X\n", *(ptr++) ); printf( "INTEGER : 0x%02X\n", *(ptr++) ); len = *(ptr++); printf( "r LEN : 0x%02X\n", len ); printf( "r :" ); for ( i = 0; i < len; i++ ) { if ( i % 8 == 0 ) printf( "\n" ); printf( "0x%02X ", *(ptr++) ); } printf( "\n" ); printf( "INTEGER : 0x%02X\n", *(ptr++) ); len = *(ptr++); printf( "s LEN : 0x%02X\n", len ); printf( "s :" ); for ( i = 0; i < len; i++ ) { if ( i % 8 == 0 ) printf( "\n" ); printf( "0x%02X ", *(ptr++) ); } printf( "\n" ); #else ptr += 3; int r_len = *(ptr++); for ( i = 0; i < r_len; i++ ) ctr_dev_cert.eccSignature[i] = *(ptr++); ptr++; int s_len = *(ptr++); for ( i = 0; i < r_len; i++ ) ctr_dev_cert.eccSignature[i+30] = *(ptr++); // create CTR Custom cert ret_code = generate_CTRCustom_cert( &ctr_dev_cert, cr_id_buf->serial[0], cr_id_buf->bondingOption ); #endif #if 0 if( cr_print_flag ) { 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ハッシュを算出してセット //-------------------------------------------------------------- SHA256(id_buf, CR_ID_BUF_SIZE - SHA256_DIGEST_LENGTH, cr_id_buf->hash); memcpy( hash, cr_id_buf->hash, SHA256_DIGEST_LENGTH ); #ifdef DEBUG_PRINT if( cr_print_flag ) { printf("SHA256 Digest:"); for( i = 0 ; i < SHA256_DIGEST_LENGTH ; i++ ) { if( (i%8) == 0 ) { printf("\n "); } printf("0x%02x ", cr_id_buf->hash[i] ); } printf("\n"); } #endif /* DEBUG_PRINT */ #ifndef ENCRYPT_AES //-------------------------------------------------------------- // FuseIDバッファ全体をRSA秘密鍵で暗号化 //-------------------------------------------------------------- #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 DEV_CYGWIN // DERフォーマットのRSA鍵を読み込み { const unsigned char *der_priv = cr_gen_id_rsa_key_priv_DER + 0x10; // ヘッダ部分を除外してKEY実体を指定 const unsigned char *der_pub = cr_gen_id_rsa_key_pub_DER + 0x10; // 同上 int priv_len = cr_gen_id_rsa_key_priv_DER[ 8 ] | cr_gen_id_rsa_key_priv_DER[ 9 ] << 8; // KEY長を取り出し int pub_len = cr_gen_id_rsa_key_pub_DER [ 8 ] | cr_gen_id_rsa_key_pub_DER [ 9 ] << 8; // 同上 // コマンドラインのopensslが出力する秘密鍵は、PKCS#1 RSAPublicKeyフォーマットなので、この関数を使う。 rsa_privkey = d2i_RSAPrivateKey( NULL, &der_priv, priv_len ); if( rsa_privkey == NULL ) { ret_code = CR_GENID_ERROR_RSA_READ_PRIVATE_KEY; goto end; } // コマンドラインのopensslが出力する公開鍵は、SubjectPublicKeyInfo形式なので、この関数を使う。 rsa_pubkey = d2i_RSA_PUBKEY( NULL, &der_pub, pub_len ); if( rsa_pubkey == NULL ) { ret_code = CR_GENID_ERROR_RSA_READ_PUBLIC_KEY; goto end; } } // RSA暗号化 -> 復号化 -> ベリファイ if( 0 != (ret_code = crypto_rsa_enc_dec( rsa_pubkey, rsa_privkey, id_buf, id_buf)) ) { switch( ret_code ) { case CR_GENID_ERROR_RSA_ENC: break; case CR_GENID_ERROR_RSA_DEC: break; case CR_GENID_ERROR_RSA_VERIFY: break; } goto end; } #else // Cygwin ret_code = hsm_crypto_rsa_enc_dec( id_buf, id_buf ); if ( ret_code != 0 ) { printf( "error(%d) : hsm_crypto_aes_enc_dec\n", ret_code ); } #endif // Linux #ifdef DEBUG_PRINT if( cr_print_flag ) { printf("RSA 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 */ #else //-------------------------------------------------------------- // FuseIDバッファ全体をAES共通鍵で暗号化 //-------------------------------------------------------------- // AES暗号化 -> 復号化 -> ベリファイ #ifdef DEV_CYGWIN if( 0 != (ret_code = crypto_aes_enc_dec( id_buf, id_buf )) ) { switch( ret_code ) { case CR_GENID_ERROR_RSA_ENC: break; case CR_GENID_ERROR_RSA_DEC: break; case CR_GENID_ERROR_RSA_VERIFY: break; } goto end; } #else // DEV_CYGWIN(openssl) ret_code = hsm_crypto_aes_enc_dec( id_buf, id_buf ); if ( ret_code != 0 ) { printf( "error(%d) : hsm_crypto_aes_enc_dec\n", ret_code ); } #endif // HSM #ifdef DEBUG_PRINT if( cr_print_flag ) { printf("AES 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 #endif // ENCRYPT_AES //-------------------------------------------------------------- // 終了処理 //-------------------------------------------------------------- end: /* id_buf[]にエラーログを書き込む。 */ if( ret_code != 0 ) { ERR_STATE *es = NULL; CR_ERR_BUFFER *cr_err_buf = (CR_ERR_BUFFER *)id_buf; memset( cr_err_buf, 0, sizeof(CR_ERR_BUFFER) ); cr_err_buf->magic_number = 0x01234567; cr_err_buf->serial0 = serial[0]; cr_err_buf->openssl_err_code = ERR_get_error(); es=ERR_get_state(); cr_err_buf->top = es->top; cr_err_buf->bottom = es->bottom; for( i = 0 ; i < ERR_NUM_ERRORS ; i++ ) { cr_err_buf->err_buffer[i] = es->err_buffer[i]; cr_err_buf->err_line[i] = es->err_line[i]; } } // リソースの解放 if ( my_eckey ) EC_KEY_free( my_eckey ); if ( my_evppkey ) EVP_PKEY_free( my_evppkey ); if ( req ) X509_REQ_free( req ); if ( rsa_privkey ) RSA_free( rsa_privkey ); if ( rsa_pubkey ) RSA_free( rsa_pubkey ); ERR_remove_state(0); EVP_cleanup(); CRYPTO_cleanup_all_ex_data(); #ifdef MY_CRYPTO_DEBUG ERR_free_strings(); #endif /* MY_CRYPTO_DEBUG */ return ret_code; /* success */ }