From d323c591cd88b057282094882a7e1996c411aa3f Mon Sep 17 00:00:00 2001 From: "(no author)" <(no author)@ff987cc8-cf2f-4642-8568-d52cce064691> Date: Tue, 22 Dec 2009 04:24:31 +0000 Subject: [PATCH] =?UTF-8?q?=E3=82=BD=E3=83=BC=E3=82=B9=E3=82=B3=E3=83=BC?= =?UTF-8?q?=E3=83=89=E3=81=AE=E5=88=86=E5=89=B2=E3=80=82?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit git-svn-id: file:///Volumes/Transfer/gigaleak_20231201/2020-09-30%20-%20paladin.7z/paladin/ctr_eFuse@16 ff987cc8-cf2f-4642-8568-d52cce064691 --- Makefile | 3 +- cr_deviceCert.c | 248 +++++++++++++ cr_enc_id.c | 24 +- cr_generate_id.c | 749 +++------------------------------------ cr_generate_id_private.h | 59 ++- cr_hsm_util.c | 312 ++++++++++++++++ cr_keyPair.c | 270 ++++++++++++++ 7 files changed, 948 insertions(+), 717 deletions(-) create mode 100644 cr_deviceCert.c create mode 100644 cr_hsm_util.c create mode 100644 cr_keyPair.c diff --git a/Makefile b/Makefile index 0bbfc8f..dc5cdb9 100644 --- a/Makefile +++ b/Makefile @@ -71,7 +71,8 @@ TARGET = gen_id KEYS_C = cr_gen_id_rsa_key_priv.c cr_gen_id_rsa_key_pub.c KEYS_H = $(KEYS_C:.c=.h) -SRCS = main.c cr_generate_id.c cr_enc_id.c cr_alloc.c cr_hsm_code.c $(KEYS_C) +SRCS = main.c cr_generate_id.c cr_hsm_util.c cr_keyPair.c \ + cr_deviceCert.c cr_enc_id.c cr_alloc.c cr_hsm_code.c $(KEYS_C) ifeq ($(USE_SFMT),TRUE) SRCS += $(SFMT_DIR)/SFMT.c diff --git a/cr_deviceCert.c b/cr_deviceCert.c new file mode 100644 index 0000000..af8c97c --- /dev/null +++ b/cr_deviceCert.c @@ -0,0 +1,248 @@ +/* ==================================================================== + * Copyright (c) 1998-2008 The OpenSSL Project. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * + * 3. All advertising materials mentioning features or use of this + * software must display the following acknowledgment: + * "This product includes software developed by the OpenSSL Project + * for use in the OpenSSL Toolkit. (http://www.openssl.org/)" + * + * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to + * endorse or promote products derived from this software without + * prior written permission. For written permission, please contact + * openssl-core@openssl.org. + * + * 5. Products derived from this software may not be called "OpenSSL" + * nor may "OpenSSL" appear in their names without prior written + * permission of the OpenSSL Project. + * + * 6. Redistributions of any form whatsoever must retain the following + * acknowledgment: + * "This product includes software developed by the OpenSSL Project + * for use in the OpenSSL Toolkit (http://www.openssl.org/)" + * + * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY + * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE OpenSSL PROJECT OR + * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED + * OF THE POSSIBILITY OF SUCH DAMAGE. + * ==================================================================== + * + * This product includes cryptographic software written by Eric Young + * (eay@cryptsoft.com). This product includes software written by Tim + * Hudson (tjh@cryptsoft.com). + * + */ + +/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com) + * All rights reserved. + * + * This package is an SSL implementation written + * by Eric Young (eay@cryptsoft.com). + * The implementation was written so as to conform with Netscapes SSL. + * + * This library is free for commercial and non-commercial use as long as + * the following conditions are aheared to. The following conditions + * apply to all code found in this distribution, be it the RC4, RSA, + * lhash, DES, etc., code; not just the SSL code. The SSL documentation + * included with this distribution is covered by the same copyright terms + * except that the holder is Tim Hudson (tjh@cryptsoft.com). + * + * Copyright remains Eric Young's, and as such any Copyright notices in + * the code are not to be removed. + * If this package is used in a product, Eric Young should be given attribution + * as the author of the parts of the library used. + * This can be in the form of a textual message at program startup or + * in documentation (online or textual) provided with the package. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * "This product includes cryptographic software written by + * Eric Young (eay@cryptsoft.com)" + * The word 'cryptographic' can be left out if the rouines from the library + * being used are not cryptographic related :-). + * 4. If you include any Windows specific code (or a derivative thereof) from + * the apps directory (application code) you must include an acknowledgement: + * "This product includes software written by Tim Hudson (tjh@cryptsoft.com)" + * + * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * The licence and distribution terms for any publically available version or + * derivative of this code cannot be changed. i.e. this code cannot simply be + * copied and put under another distribution licence + * [including the GNU Public Licence.] + */ + +#include +#include +#include +#include +#include +#include +#include + +#ifdef USE_HSM +// nShield +#include "nfastapp.h" +#include "nfkm.h" +#include "rqcard-applic.h" +#include "rqcard-fips.h" +// nShield optional +#include "simplebignum.h" +#endif // USE_HSM + +// openssl +#include +#include +#include +#include +#include +#include + +#include "ec_lcl.h" // ec_key_st構造体の参照に必要 + + +#include "cr_generate_id.h" +#include "cr_generate_id_private.h" +#include "cr_alloc.h" + +#define CR_CERT_EXPIRE_SECS ( 60*60*24*365* 20 ) // デバイス証明書期限=20年 + +#define CA_FILE "dummyCA/NintendoCTR2_dummy.crt" +#define CA_KEY "dummyCA/NintendoCTR2_priv_dummy.pem" + +const char *issuerNameDev = "NintendoCA - G2_NintendoCTR2dev"; +const char *issuerNameProd = "NintendoCA - G2_NintendoCTR2prod"; + +// 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; + + + +// create CTR Custom cert +static int generate_CTRCustom_cert( CTR_Device_Cert *cert, u32 deviceId, u8 bondingOption, u32 timestamp ) +{ + int result = 0; + char str[80]; + + if ( sizeof( CTR_Device_Cert ) > 384 ) + { + //ret_code = CR_GENID_ERROR_CERT_BUF_SIZE; // ATODE + return 255; + } + + // 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 +#ifdef USE_HSM + result = hsm_get_rtc( &cert->expiryDate ); + if ( result != 0 ) + { + printf( "error(%d) : hsm_get_rtc\n", result ); + return result; + } +#else // !USE_HSM + { + struct timeval tv; + struct timezone tz; + gettimeofday(&tv,&tz); + cert->expiryDate = tv.tv_sec; + } +#endif // USE_HSM + +#if 0 + if ( cr_print_flag ) + { + int i; + printf( "CTR custom cert\n" ); + printf( "sigType : 0x%08X\n", *(unsigned int*)cert->sigType ); + DEBUG_PRINT_ARRAY( "eccSignature:", (const char *)cert->eccSignature, sizeof(cert->eccSignature) ); + DEBUG_PRINT_ARRAY( "padding0:", (const char *)cert->padding0, sizeof(cert->padding0) ); + printf( "issuerName : " ); + for ( i = 0; i < sizeof(cert->issuerName); i++ ) printf( "%c", cert->issuerName[i] ); + printf( "\n" ); + printf( "keyType : 0x%08X\n", *(unsigned int*)cert->keyType ); + printf( "subject : " ); + for ( i = 0; i < sizeof(cert->subject); i++ ) printf( "%c", cert->subject[i] ); + printf( "\n" ); + printf( "expiryDate : 0x%08X\n", (unsigned int)cert->expiryDate ); + DEBUG_PRINT_ARRAY( "eccPubKey :", (const char *)cert->eccPubKey, sizeof(cert->eccPubKey) ); + DEBUG_PRINT_ARRAY( "padding1:", (const char *)cert->padding1, sizeof(cert->padding1) ); + + // 証明書の書き込みテスト + 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 result; +} // generate_CTRCustom_cert + diff --git a/cr_enc_id.c b/cr_enc_id.c index 0a697bb..bd7581b 100644 --- a/cr_enc_id.c +++ b/cr_enc_id.c @@ -119,20 +119,9 @@ #include #include -#ifdef USE_HSM -// nShield -#include "nfastapp.h" -#include "nfkm.h" -#include "rqcard-applic.h" -#include "rqcard-fips.h" -// nShield optional -#include "simplebignum.h" - -#else // !USE_HSM +#ifndef USE_HSM // openssl #include -#include -#include #include #include #include "cr_gen_id_rsa_key_priv.h" @@ -146,6 +135,17 @@ static unsigned char local_buf_1[CR_ID_BUF_SIZE]; static unsigned char local_buf_2[CR_ID_BUF_SIZE]; +// ビルドスイッチに応じて、IDバッファをAES/RSAで暗号化 +int EncryptID( unsigned char *dst_buf, unsigned char *org_buf ) +{ +#ifdef ENCRYPT_AES + return crypto_aes_enc_dec( dst_buf, org_buf ); // AES +#else // !ENCRYPT_AES + return crypto_rsa_enc_dec( dst_buf, org_buf ); // RSA pubKey enc +#endif // ENCRYPT_AES +} + + #ifdef ENCRYPT_AES // AES暗号化 -> 復号化 -> ベリファイ diff --git a/cr_generate_id.c b/cr_generate_id.c index e24f505..2e5d82d 100644 --- a/cr_generate_id.c +++ b/cr_generate_id.c @@ -120,531 +120,42 @@ #ifdef USE_HSM #include "cr_hsm_code.h" #endif // USE_HSM - // openssl #include -#include #include #include #include #include #include -#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_generate_id_private.h" #include "cr_alloc.h" -#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 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"; - -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" } -}; - -// 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; - - 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 */ + u32 magic_number; /* 0x00 - 0x03 0x01234567 確定!*/ + u32 serial0; /* 0x04 - 0x07 */ + u32 openssl_err_code; /* 0x08 - 0x0b */ + s32 top; /* 0x0c - 0x0f */ + s32 bottom; /* 0x10 - 0x13 */ -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 */ + /* #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 = 0; - BIGNUM *bn_privkey = NULL; - -#ifdef USE_HSM - ret_code = hsm_generate_random( privKey, EC_PRIVATE_KEY_LENGTH ); - if ( ret_code != CR_GENID_SUCCESS ) - { - printf( "error(%d) : hsm_generate_random\n", ret_code ); - return ret_code; - } -#else // !USE_HSM - { - int i; - for ( i = 0; i < EC_PRIVATE_KEY_LENGTH; i++ ) - { - privKey[i] = (u8)rand(); - } - } -#endif // USE_HSM - - // 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; - - DEBUG_PRINT_ARRAY( "ec private key:", (const char *)privKey, EC_PRIVATE_KEY_LENGTH ); - - return ret_code; -} // 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 - DEBUG_PRINT_ARRAY( "eccSignature:", (const char *)cert->signature->data, cert->signature->length ); -#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 = 0; - 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 -#ifdef USE_HSM - result = hsm_get_rtc( &cert->expiryDate ); - if ( result != 0 ) - { - printf( "error(%d) : hsm_get_rtc\n", result ); - return result; - } -#else // !USE_HSM - { - struct timeval tv; - struct timezone tz; - gettimeofday(&tv,&tz); - cert->expiryDate = tv.tv_sec; - } -#endif // USE_HSM - -#if 0 - if ( cr_print_flag ) - { - int i; - printf( "CTR custom cert\n" ); - printf( "sigType : 0x%08X\n", *(unsigned int*)cert->sigType ); - DEBUG_PRINT_ARRAY( "eccSignature:", (const char *)cert->eccSignature, sizeof(cert->eccSignature) ); - DEBUG_PRINT_ARRAY( "padding0:", (const char *)cert->padding0, sizeof(cert->padding0) ); - printf( "issuerName : " ); - for ( i = 0; i < sizeof(cert->issuerName); i++ ) printf( "%c", cert->issuerName[i] ); - printf( "\n" ); - printf( "keyType : 0x%08X\n", *(unsigned int*)cert->keyType ); - printf( "subject : " ); - for ( i = 0; i < sizeof(cert->subject); i++ ) printf( "%c", cert->subject[i] ); - printf( "\n" ); - printf( "expiryDate : 0x%08X\n", (unsigned int)cert->expiryDate ); - DEBUG_PRINT_ARRAY( "eccPubKey :", (const char *)cert->eccPubKey, sizeof(cert->eccPubKey) ); - DEBUG_PRINT_ARRAY( "padding1:", (const char *)cert->padding1, sizeof(cert->padding1) ); - - // 証明書の書き込みテスト - 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 result; -} // generate_CTRCustom_cert int cr_generate_id_initialize( void ) { int ret_code = 0; - FILE *fp; - + #ifdef USE_HSM ret_code = hsm_initialize(); if ( ret_code != CR_GENID_SUCCESS ) @@ -654,49 +165,13 @@ int cr_generate_id_initialize( void ) } #endif - // 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 + +// generate_id関数のファイナライズ int cr_generate_id_finalize( void ) { int ok = 0; @@ -721,19 +196,14 @@ int cr_generate_id_finalize( void ) エラーが起こったとき id_buf にエラーログを返すか? */ + +// generate_id 関数 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; - - X509_REQ *req = NULL; - X509 *cert = NULL; - CR_ID_BUFFER *cr_id_buf; - u8 hash[SHA256_DIGEST_LENGTH]; /* SHA256 check */ - CTR_Device_Cert ctr_dev_cert; + EC_KEY *my_eckey = NULL; if( sizeof(CR_ID_BUFFER) != 256 ) { ret_code = CR_GENID_ERROR_ID_BUF_SIZE; @@ -745,12 +215,6 @@ int cr_generate_id( u32 serial[CR_NUM_OF_SERIAL], u8 id_buf[CR_ID_BUF_SIZE], u8 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 */ #if 0 @@ -792,13 +256,12 @@ int cr_generate_id( u32 serial[CR_NUM_OF_SERIAL], u8 id_buf[CR_ID_BUF_SIZE], u8 //-------------------------------------------------------------- // 引数のボンディングオプションをセット //-------------------------------------------------------------- - cr_id_buf->bondingOption = bondingOption; + cr_id_buf->bondingOption = bondingOption; //-------------------------------------------------------------- // serialNo.セット //-------------------------------------------------------------- - for( i = 0 ; i < CR_NUM_OF_SERIAL ; i++ ) - { + for( i = 0 ; i < CR_NUM_OF_SERIAL ; i++ ) { cr_id_buf->serial[i] = serial[i]; /* serial[0] => ec priv key */ } @@ -809,7 +272,7 @@ int cr_generate_id( u32 serial[CR_NUM_OF_SERIAL], u8 id_buf[CR_ID_BUF_SIZE], u8 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] ); + else printf("%08x\n", (unsigned int)serial[i] ); } printf("\n"); } @@ -818,153 +281,46 @@ int cr_generate_id( u32 serial[CR_NUM_OF_SERIAL], u8 id_buf[CR_ID_BUF_SIZE], u8 //-------------------------------------------------------------- // タイムスタンプセット //-------------------------------------------------------------- - { - struct tm *tm_time; - struct timeval tv; - struct timezone tz; - -#ifdef USE_HSM - hsm_get_rtc( &tv.tv_sec ); -#else // !USE_HSM - gettimeofday(&tv,&tz); -#endif // USE_HSM - - tm_time = gmtime( &tv.tv_sec ); - - cr_id_buf->year = (u8)tm_time->tm_year; - cr_id_buf->month = (u8)tm_time->tm_mon+1; - cr_id_buf->mday = (u8)tm_time->tm_mday; - cr_id_buf->hour = (u8)tm_time->tm_hour; - cr_id_buf->min = (u8)tm_time->tm_min; - cr_id_buf->sec = (u8)tm_time->tm_sec; - -#ifdef DEBUG_PRINT - 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 */ + ret_code = GetTimestamp( &cr_id_buf->year, + &cr_id_buf->month, + &cr_id_buf->mday, + &cr_id_buf->hour, + &cr_id_buf->min, + &cr_id_buf->sec, + &cr_id_buf->deviceCertExpiryDate ); + if ( ret_code != 0 ) { + goto end; } + //-------------------------------------------------------------- // 乱数を生成してセット //-------------------------------------------------------------- -#ifdef USE_HSM - ret_code = hsm_generate_random( cr_id_buf->random, CR_RANDOM_LENGTH ); - if ( ret_code != CR_GENID_SUCCESS ) - { - printf( "error(%d) : hsm_generate_random\n", ret_code ); - return ret_code; + ret_code = GenerateRandom( cr_id_buf->random, CR_RANDOM_LENGTH ); + if ( ret_code != CR_GENID_SUCCESS ) { + goto end; } -#else // !USE_HSM - { - u16 buffer[ CR_RANDOM_LENGTH / sizeof(u16) ]; - for( i = 0 ; i < CR_RANDOM_LENGTH / sizeof(u16); i++ ) { - buffer[i] = (u16)rand(); - } - memcpy( cr_id_buf->random, buffer, CR_RANDOM_LENGTH ); - } -#endif // USE_HSM - DEBUG_PRINT_ARRAY( "rand:", (const char *)cr_id_buf->random, CR_RANDOM_LENGTH ); //-------------------------------------------------------------- // 楕円曲線鍵ペアを生成 //-------------------------------------------------------------- - // 楕円を選択 ( 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; + ret_code = GenarateECCKeyPair( my_eckey, cr_id_buf->devicePrivKey ); + if ( ret_code != CR_GENID_SUCCESS ) { 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で動作確認 //-------------------------------------------------------------- +#if 0 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 ) ); -#if 1 - //-------------------------------------------------------------- - // デバイス証明書要求生成 - //-------------------------------------------------------------- - 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] ); - //-------------------------------------------------------------- - // デバイス証明書の署名をセット + // デバイス証明書生成&署名+証明書期限セット //-------------------------------------------------------------- +#if 0 int padding = ECDSA_SIGN_LENGTH % cert->signature->length; printf( "padding = %d\n", padding ); for ( i = 0; i < padding; i++ ) @@ -986,7 +342,6 @@ int cr_generate_id( u32 serial[CR_NUM_OF_SERIAL], u8 id_buf[CR_ID_BUF_SIZE], u8 len = BN_bn2bin( &my_eckey->pub_key->Y, buf ); memcpy( &ctr_dev_cert.eccPubKey[30], buf, len ); free( buf ); -#endif // copy sign to Custom cert //#define SHOW_SIG @@ -1032,38 +387,32 @@ int cr_generate_id( u32 serial[CR_NUM_OF_SERIAL], u8 id_buf[CR_ID_BUF_SIZE], u8 #if 0 DEBUG_PRINT_ARRAY( "deviceCertSign:", (const char *)cr_id_buf->deviceCertSign, ECDSA_SIGN_LENGTH ); +#endif + #endif //-------------------------------------------------------------- // 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 ); DEBUG_PRINT_ARRAY( "SHA256 Digest:", (const char *)cr_id_buf->hash, SHA256_DIGEST_LENGTH ); //-------------------------------------------------------------- - // FuseIDバッファ全体を暗号化 + // FuseIDバッファ全体をAES or RSAで暗号化 //-------------------------------------------------------------- DEBUG_PRINT_ARRAY( "ORG buf:", (const char *)id_buf, CR_ID_BUF_SIZE ); - -#ifdef ENCRYPT_AES - ret_code = crypto_aes_enc_dec( id_buf, id_buf ); // AES -#else // !ENCRYPT_AES - ret_code = crypto_rsa_enc_dec( id_buf, id_buf ); // RSA pubKey enc -#endif // ENCRYPT_AES - - if( ret_code != 0 ) { + ret_code = EncryptID( id_buf, id_buf ); + if( ret_code != CR_GENID_SUCCESS ) { goto end; } - DEBUG_PRINT_ARRAY( "encrypted:", (const char *)id_buf, CR_ID_BUF_SIZE ); //-------------------------------------------------------------- // 終了処理 //-------------------------------------------------------------- - end: +end: /* id_buf[]にエラーログを書き込む。 */ - if( ret_code != 0 ) { + if( ret_code != CR_GENID_SUCCESS ) { ERR_STATE *es = NULL; CR_ERR_BUFFER *cr_err_buf = (CR_ERR_BUFFER *)id_buf; memset( cr_err_buf, 0, sizeof(CR_ERR_BUFFER) ); @@ -1081,8 +430,6 @@ int cr_generate_id( u32 serial[CR_NUM_OF_SERIAL], u8 id_buf[CR_ID_BUF_SIZE], u8 // リソースの解放 if ( my_eckey ) EC_KEY_free( my_eckey ); - if ( my_evppkey ) EVP_PKEY_free( my_evppkey ); - if ( req ) X509_REQ_free( req ); ERR_remove_state(0); EVP_cleanup(); diff --git a/cr_generate_id_private.h b/cr_generate_id_private.h index d4bace9..e499343 100644 --- a/cr_generate_id_private.h +++ b/cr_generate_id_private.h @@ -116,7 +116,21 @@ extern "C" { #endif -//#define DEBUG_PRINT 1 +#ifdef USE_HSM +// nShield +#include "nfastapp.h" +#include "nfkm.h" +#include "rqcard-applic.h" +#include "rqcard-fips.h" +// nShield optional +#include "simplebignum.h" +#endif // USE_HSM + +#include +#include + + +#define DEBUG_PRINT 1 #ifdef DEBUG_PRINT #define DEBUG_PRINT_ARRAY DebugPrintArray @@ -124,8 +138,47 @@ extern "C" { #define DEBUG_PRINT_ARRAY( ... ) ((void)0) #endif // DEBUG_PRINT -extern int crypto_aes_enc_dec( unsigned char *dst_buf, unsigned char *org_buf ); -extern int crypto_rsa_enc_dec( unsigned char *dst_buf, unsigned char *org_buf ); + +#define CR_GEN_ID_VERSION 1 +#define CR_RANDOM_LENGTH 0x50 +#define EC_PRIVATE_KEY_LENGTH 0x20 +#define ECDSA_SIGN_LENGTH 0x44 +#define CR_RSV_LENGTH 0x08 +#define EC_CURVE_NAME NID_sect233r1 + +typedef struct { + u32 magic_number; /* 0x00 - 0x03 = 0xdeadb00f mI*/ + u32 serial[CR_NUM_OF_SERIAL]; /* 0x04 - 0x07 32bit device ID + (32bitB1ŒJEgAbvBj + ({ID{random̐擪0x1C bytesgݍ킹āAfoCX閧ƂB) + 0x08 - 0x0F 64bit CTRԍ seed + (34bit̂ݎgpB1`4̗JEgAbv) + 0x10 - 0x17 64bit \ID + (64bittɎgpB1`0x100000000̗JEgAbv) + */ + u8 version; /* 0x18 = CR_GEN_ID_VERSION = 1 */ + u8 bondingOption; /* 0x19 {fBOIvV */ + u8 year; /* 0x1A foCXؖs iHSM擾j */ + 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) j[Nۏ؂Ȃ */ + u8 deviceCertSign[ ECDSA_SIGN_LENGTH ]; + /* 0x40 - 0x83 ECC233 ECDSA signature (big endian) */ + u32 deviceCertExpiryDate; /* 0x84 - 0x87 \ */ + u8 reserved[ CR_RSV_LENGTH ]; /* 0x88 - 0x8F \ */ + u8 random[ CR_RANDOM_LENGTH ]; /* 0x90 - 0xDF */ + u8 hash[ SHA256_DIGEST_LENGTH ]; /* 0xE0 - 0xFF "0x00-0xDF"̈SHA256nbV */ +} CR_ID_BUFFER; /* v256bytes = 2048bit */ + + +extern int GetTimestamp( u8 *pYear, u8 *pMonth, u8 *pMday, u8 *pHour, u8 *pMin, u8 *pSec, time_t *pTime); +extern int GenerateRandom( u8 *pDst, int length ); +extern int GenarateECCKeyPair( EC_KEY *pECkey, u8 *pECPrivkey ); +extern int EncryptID( unsigned char *dst_buf, unsigned char *org_buf ); extern void DebugPrintArray( char *pStr, const u8 *pData, int length ); #ifdef __cplusplus diff --git a/cr_hsm_util.c b/cr_hsm_util.c new file mode 100644 index 0000000..dc10c7c --- /dev/null +++ b/cr_hsm_util.c @@ -0,0 +1,312 @@ +/* ==================================================================== + * Copyright (c) 1998-2008 The OpenSSL Project. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * + * 3. All advertising materials mentioning features or use of this + * software must display the following acknowledgment: + * "This product includes software developed by the OpenSSL Project + * for use in the OpenSSL Toolkit. (http://www.openssl.org/)" + * + * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to + * endorse or promote products derived from this software without + * prior written permission. For written permission, please contact + * openssl-core@openssl.org. + * + * 5. Products derived from this software may not be called "OpenSSL" + * nor may "OpenSSL" appear in their names without prior written + * permission of the OpenSSL Project. + * + * 6. Redistributions of any form whatsoever must retain the following + * acknowledgment: + * "This product includes software developed by the OpenSSL Project + * for use in the OpenSSL Toolkit (http://www.openssl.org/)" + * + * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY + * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE OpenSSL PROJECT OR + * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED + * OF THE POSSIBILITY OF SUCH DAMAGE. + * ==================================================================== + * + * This product includes cryptographic software written by Eric Young + * (eay@cryptsoft.com). This product includes software written by Tim + * Hudson (tjh@cryptsoft.com). + * + */ + +/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com) + * All rights reserved. + * + * This package is an SSL implementation written + * by Eric Young (eay@cryptsoft.com). + * The implementation was written so as to conform with Netscapes SSL. + * + * This library is free for commercial and non-commercial use as long as + * the following conditions are aheared to. The following conditions + * apply to all code found in this distribution, be it the RC4, RSA, + * lhash, DES, etc., code; not just the SSL code. The SSL documentation + * included with this distribution is covered by the same copyright terms + * except that the holder is Tim Hudson (tjh@cryptsoft.com). + * + * Copyright remains Eric Young's, and as such any Copyright notices in + * the code are not to be removed. + * If this package is used in a product, Eric Young should be given attribution + * as the author of the parts of the library used. + * This can be in the form of a textual message at program startup or + * in documentation (online or textual) provided with the package. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * "This product includes cryptographic software written by + * Eric Young (eay@cryptsoft.com)" + * The word 'cryptographic' can be left out if the rouines from the library + * being used are not cryptographic related :-). + * 4. If you include any Windows specific code (or a derivative thereof) from + * the apps directory (application code) you must include an acknowledgement: + * "This product includes software written by Tim Hudson (tjh@cryptsoft.com)" + * + * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * The licence and distribution terms for any publically available version or + * derivative of this code cannot be changed. i.e. this code cannot simply be + * copied and put under another distribution licence + * [including the GNU Public Licence.] + */ + +#include +#include +#include +#include +#include +#include +#include + +#ifdef USE_HSM +// nShield +#include "nfastapp.h" +#include "nfkm.h" +#include "rqcard-applic.h" +#include "rqcard-fips.h" +// nShield optional +#include "simplebignum.h" +#endif // USE_HSM + +#include "cr_generate_id.h" +#include "cr_generate_id_private.h" + +#ifdef USE_HSM +// functions +static int hsm_get_rtc( time_t *time ); +static int hsm_set_rtc( struct timeval time ); +static int hsm_generate_random( unsigned char *buf, int bytes ); +#endif // USE_HSM + + +// タイムスタンプの取得 +int GetTimestamp( u8 *pYear, u8 *pMonth, u8 *pMday, u8 *pHour, u8 *pMin, u8 *pSec, time_t *pTime) +{ + int ret_code = 0; + struct tm *tm_time; + struct timeval tv; + struct timezone tz; + +#ifdef USE_HSM + ret_code = hsm_get_rtc( &tv.tv_sec ); + if( ret_code != Status_OK ) { + return ret_code; + } +#else // !USE_HSM + gettimeofday(&tv,&tz); +#endif // USE_HSM + + tm_time = gmtime( &tv.tv_sec ); + + *pYear = (u8)tm_time->tm_year; + *pMonth = (u8)tm_time->tm_mon+1; + *pMday = (u8)tm_time->tm_mday; + *pHour = (u8)tm_time->tm_hour; + *pMin = (u8)tm_time->tm_min; + *pSec = (u8)tm_time->tm_sec; + +#ifdef DEBUG_PRINT + if( cr_print_flag ) { + printf("GMT:%d-%02d-%02d %02d:%02d:%02d\n", + *pYear+1900, /* 年 */ + *pMonth, /* 月 */ + *pMday, /* 日 */ + *pHour, /* 時 */ + *pMin, /* 分 */ + *pSec /* 秒 */ + ); + } +#endif /* DEBUG_PRINT */ + + return ret_code; +} + + +#ifdef USE_HSM +// HSMのRTC値取得 +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 + + +#if 0 +// HSMのRTC値セット +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 + +#endif // USE_HSM + + +// ランダム値の生成 +int GenerateRandom( u8 *pDst, int length ) +{ + int ret_code = 0; + +#ifdef USE_HSM + ret_code = hsm_generate_random( pDst, CR_RANDOM_LENGTH ); + if ( ret_code != Status_OK ) + { + printf( "error(%d) : hsm_generate_random\n", ret_code ); + return ret_code; + } +#else // !USE_HSM + int i; + for( i = 0 ; i < length; i++ ) { + *pDst++ = (u8)rand(); + } +#endif // USE_HSM + + return ret_code; +} + + +#ifdef USE_HSM +// HSMから乱数を取得 +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 +#endif // USE_HSM + diff --git a/cr_keyPair.c b/cr_keyPair.c new file mode 100644 index 0000000..bdf7355 --- /dev/null +++ b/cr_keyPair.c @@ -0,0 +1,270 @@ +/* ==================================================================== + * Copyright (c) 1998-2008 The OpenSSL Project. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * + * 3. All advertising materials mentioning features or use of this + * software must display the following acknowledgment: + * "This product includes software developed by the OpenSSL Project + * for use in the OpenSSL Toolkit. (http://www.openssl.org/)" + * + * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to + * endorse or promote products derived from this software without + * prior written permission. For written permission, please contact + * openssl-core@openssl.org. + * + * 5. Products derived from this software may not be called "OpenSSL" + * nor may "OpenSSL" appear in their names without prior written + * permission of the OpenSSL Project. + * + * 6. Redistributions of any form whatsoever must retain the following + * acknowledgment: + * "This product includes software developed by the OpenSSL Project + * for use in the OpenSSL Toolkit (http://www.openssl.org/)" + * + * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY + * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE OpenSSL PROJECT OR + * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED + * OF THE POSSIBILITY OF SUCH DAMAGE. + * ==================================================================== + * + * This product includes cryptographic software written by Eric Young + * (eay@cryptsoft.com). This product includes software written by Tim + * Hudson (tjh@cryptsoft.com). + * + */ + +/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com) + * All rights reserved. + * + * This package is an SSL implementation written + * by Eric Young (eay@cryptsoft.com). + * The implementation was written so as to conform with Netscapes SSL. + * + * This library is free for commercial and non-commercial use as long as + * the following conditions are aheared to. The following conditions + * apply to all code found in this distribution, be it the RC4, RSA, + * lhash, DES, etc., code; not just the SSL code. The SSL documentation + * included with this distribution is covered by the same copyright terms + * except that the holder is Tim Hudson (tjh@cryptsoft.com). + * + * Copyright remains Eric Young's, and as such any Copyright notices in + * the code are not to be removed. + * If this package is used in a product, Eric Young should be given attribution + * as the author of the parts of the library used. + * This can be in the form of a textual message at program startup or + * in documentation (online or textual) provided with the package. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * "This product includes cryptographic software written by + * Eric Young (eay@cryptsoft.com)" + * The word 'cryptographic' can be left out if the rouines from the library + * being used are not cryptographic related :-). + * 4. If you include any Windows specific code (or a derivative thereof) from + * the apps directory (application code) you must include an acknowledgement: + * "This product includes software written by Tim Hudson (tjh@cryptsoft.com)" + * + * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * The licence and distribution terms for any publically available version or + * derivative of this code cannot be changed. i.e. this code cannot simply be + * copied and put under another distribution licence + * [including the GNU Public Licence.] + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include "ec_lcl.h" // ec_key_st構造体の参照に必要 +#include "cr_generate_id.h" +#include "cr_generate_id_private.h" + +static int generate_EC_private_key( EC_KEY *eckey, u8 *privKey ); +static int generate_EC_public_key( EC_KEY *eckey ); + + +// ECCキーペアの生成 +int GenarateECCKeyPair( EC_KEY *pECkey, u8 *pECPrivkey ) +{ + int ret_code = 0; + + // 楕円を選択 ( NID_X9_62_prime256v1 -> 32bytesまで、 NID_sect571r1 -> 71bytesまで 署名にデータを含められる ) + pECkey = EC_KEY_new_by_curve_name( NID_sect233r1 ); + if( pECkey == NULL ) + { + return CR_GENID_ERROR_EC_KEY_NEW_1; + } + + // 秘密鍵生成 + ret_code = generate_EC_private_key( pECkey, pECPrivkey ); + if( ret_code != 0 ) + { + return CR_GENID_ERROR_EC_GENERATE_PRIVATE_KEY; + } + + // 公開鍵生成 + ret_code = generate_EC_public_key( pECkey ); + if ( ret_code == 0 ) + { + return CR_GENID_ERROR_EC_GENERATE_PUBLIC_KEY; + } + + // ASN.1 形式指定フラグをセットする + // (これをセットしないと色々変なフィールドが入ってしまうため) + EC_KEY_set_asn1_flag( pECkey, 1 ); + + return 0; +} + + +// EC秘密鍵を生成 +static int generate_EC_private_key( EC_KEY *eckey, u8 *privKey ) +{ + int ret_code = 0; + BIGNUM *bn_privkey = NULL; + + // 乱数を取得して、秘密鍵にする。 + ret_code = GenerateRandom( privKey, EC_PRIVATE_KEY_LENGTH ); + if ( ret_code != 0 ) { + return ret_code; + } + + // 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; + + DEBUG_PRINT_ARRAY( "ec private key:", (const char *)privKey, EC_PRIVATE_KEY_LENGTH ); + + return ret_code; +} // 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 + +