mirror of
https://github.com/rvtr/ctr_eFuse.git
synced 2025-11-02 00:11:04 -04:00
git-svn-id: file:///Volumes/Transfer/gigaleak_20231201/2020-09-30%20-%20paladin.7z/paladin/ctr_eFuse@5 ff987cc8-cf2f-4642-8568-d52cce064691
1970 lines
55 KiB
C
1970 lines
55 KiB
C
/* ====================================================================
|
||
* 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固定カウントアップ。)
|
||
(本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 */
|
||
}
|