ctr_eFuse/cr_generate_id.c
kubodera_yuichi b1b18d7607 ビルドエラーを通すために by kuboyu
git-svn-id: file:///Volumes/Transfer/gigaleak_20231201/2020-09-30%20-%20paladin.7z/paladin/ctr_eFuse@5 ff987cc8-cf2f-4642-8568-d52cce064691
2009-12-21 09:06:53 +00:00

1970 lines
55 KiB
C
Raw Blame History

This file contains ambiguous Unicode characters

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

/* ====================================================================
* 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 <assert.h>
#include <stdio.h>
#include <stdlib.h>
#include <limits.h>
#include <time.h>
#include <sys/time.h>
#include <string.h>
// nShield
#include "nfastapp.h"
#include "nfkm.h"
#include "rqcard-applic.h"
#include "rqcard-fips.h"
// nShield optional
#include "simplebignum.h"
// openssl
#include <openssl/err.h>
#include <openssl/bn.h>
#include <openssl/ec.h>
#include <openssl/sha.h>
#include <openssl/rsa.h>
#include <openssl/x509.h>
#include <openssl/aes.h>
// 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固定カウントアップ。
(本IDrandomの先頭0x1C bytesを組み合わせて、デバイス秘密鍵とする。)
0x08 - 0x0F 64bit CTR番号 seed
(34bitのみ使用。14の乱数カウントアップ)
0x10 - 0x17 64bit 予備ID
(64bitフルに使用。10x100000000の乱数カウントアップ)
*/
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にするとでコケる。 */
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 */
}