diff options
author | Ade Lee <alee@redhat.com> | 2012-08-15 14:10:08 -0400 |
---|---|---|
committer | Ade Lee <alee@redhat.com> | 2012-08-15 14:10:08 -0400 |
commit | 3b1ca60d799ca02305b8a2c61eb279f74787cff0 (patch) | |
tree | d1ec49f3d77cb77fc6043580b23c371508fea802 | |
parent | 87b5eaa5b1409bc362867e3849fe16c8f205afa9 (diff) | |
parent | 75e1c66acb48e67951fc0ce5680328773fe837ae (diff) | |
download | pki-3b1ca60d799ca02305b8a2c61eb279f74787cff0.tar.gz pki-3b1ca60d799ca02305b8a2c61eb279f74787cff0.tar.xz pki-3b1ca60d799ca02305b8a2c61eb279f74787cff0.zip |
Merge branch 'my_tpsclient'
-rw-r--r-- | base/tps/src/CMakeLists.txt | 1 | ||||
-rw-r--r-- | base/tps/src/apdu/Generate_Key_ECC_APDU.cpp | 62 | ||||
-rw-r--r-- | base/tps/src/include/apdu/APDU.h | 3 | ||||
-rw-r--r-- | base/tps/src/include/apdu/Generate_Key_ECC_APDU.h | 60 | ||||
-rw-r--r-- | base/tps/tools/raclient/RA_Conn.cpp | 14 | ||||
-rw-r--r-- | base/tps/tools/raclient/RA_Token.cpp | 562 | ||||
-rw-r--r-- | base/tps/tools/raclient/RA_Token.h | 64 | ||||
-rwxr-xr-x | base/tps/tools/raclient/enroll.tps.ec | 43 |
8 files changed, 762 insertions, 47 deletions
diff --git a/base/tps/src/CMakeLists.txt b/base/tps/src/CMakeLists.txt index 5f588663c..b0276f8e2 100644 --- a/base/tps/src/CMakeLists.txt +++ b/base/tps/src/CMakeLists.txt @@ -79,6 +79,7 @@ set(tps_library_SRCS apdu/Get_Data_APDU.cpp apdu/External_Authenticate_APDU.cpp apdu/Generate_Key_APDU.cpp + apdu/Generate_Key_ECC_APDU.cpp apdu/Read_Buffer_APDU.cpp apdu/Read_Object_APDU.cpp apdu/Write_Object_APDU.cpp diff --git a/base/tps/src/apdu/Generate_Key_ECC_APDU.cpp b/base/tps/src/apdu/Generate_Key_ECC_APDU.cpp new file mode 100644 index 000000000..0e6069a00 --- /dev/null +++ b/base/tps/src/apdu/Generate_Key_ECC_APDU.cpp @@ -0,0 +1,62 @@ +// --- BEGIN COPYRIGHT BLOCK --- +// This library is free software; you can redistribute it and/or +// modify it under the terms of the GNU Lesser General Public +// License as published by the Free Software Foundation; +// version 2.1 of the License. +// +// This library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +// Lesser General Public License for more details. +// +// You should have received a copy of the GNU Lesser General Public +// License along with this library; if not, write to the Free Software +// Foundation, Inc., 51 Franklin Street, Fifth Floor, +// Boston, MA 02110-1301 USA +// +// Copyright (C) 2007 Red Hat, Inc. +// All rights reserved. +// --- END COPYRIGHT BLOCK --- + +#include <stdio.h> +#include "apdu/APDU.h" +#include "apdu/Generate_Key_ECC_APDU.h" +#include "main/Memory.h" + +#ifdef XP_WIN32 +#define TPS_PUBLIC __declspec(dllexport) +#else /* !XP_WIN32 */ +#define TPS_PUBLIC +#endif /* !XP_WIN32 */ + +/** + * Constructs Generate Key ECC APDU. + */ +TPS_PUBLIC Generate_Key_ECC_APDU::Generate_Key_ECC_APDU (BYTE p1, BYTE p2, BYTE alg, int keysize, BYTE option, +BYTE type, Buffer &wrapped_challenge, Buffer &key_check) +{ + SetCLA(0x84); + SetINS(0x0D); + SetP1(p1); + SetP2(p2); + + Buffer data1; + + data1 = Buffer(1,alg) + Buffer(1,(BYTE)(keysize/256)) + Buffer(1,(BYTE)(keysize%256)) + Buffer(1,option) + Buffer(1,type) + Buffer(1,(BYTE)wrapped_challenge.size()) + Buffer(wrapped_challenge) + Buffer(1,(BYTE)key_check.size()); + + if(key_check.size() > 0) { + data1 = data1 + Buffer(key_check); + } + + SetData(data1); + +} + +TPS_PUBLIC Generate_Key_ECC_APDU::~Generate_Key_ECC_APDU () +{ +} + +TPS_PUBLIC APDU_Type Generate_Key_ECC_APDU::GetType() +{ + return APDU_GENERATE_KEY_ECC; +} diff --git a/base/tps/src/include/apdu/APDU.h b/base/tps/src/include/apdu/APDU.h index e0f778a19..cfb66ad19 100644 --- a/base/tps/src/include/apdu/APDU.h +++ b/base/tps/src/include/apdu/APDU.h @@ -75,7 +75,8 @@ enum APDU_Type { APDU_IMPORT_KEY = 24, APDU_IMPORT_KEY_ENC = 25, APDU_SET_ISSUERINFO = 26, - APDU_GET_ISSUERINFO = 27 + APDU_GET_ISSUERINFO = 27, + APDU_GENERATE_KEY_ECC = 28 }; class APDU diff --git a/base/tps/src/include/apdu/Generate_Key_ECC_APDU.h b/base/tps/src/include/apdu/Generate_Key_ECC_APDU.h new file mode 100644 index 000000000..c1a4e3764 --- /dev/null +++ b/base/tps/src/include/apdu/Generate_Key_ECC_APDU.h @@ -0,0 +1,60 @@ +/* --- BEGIN COPYRIGHT BLOCK --- + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; + * version 2.1 of the License. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301 USA + * + * Copyright (C) 2007 Red Hat, Inc. + * All rights reserved. + * --- END COPYRIGHT BLOCK --- + */ + +#ifndef GENERATE_KEY_ECC_APDU_H +#define GENERATE_KEY_ECC_APDU_H + +#ifdef HAVE_CONFIG_H +#ifndef AUTOTOOLS_CONFIG_H +#define AUTOTOOLS_CONFIG_H + +/* Eliminate warnings when using Autotools */ +#undef PACKAGE_BUGREPORT +#undef PACKAGE_NAME +#undef PACKAGE_STRING +#undef PACKAGE_TARNAME +#undef PACKAGE_VERSION + +#include <config.h> +#endif /* AUTOTOOLS_CONFIG_H */ +#endif /* HAVE_CONFIG_H */ + +#include "main/Base.h" +#include "main/Buffer.h" +#include "apdu/APDU.h" + +#ifdef XP_WIN32 +#define TPS_PUBLIC __declspec(dllexport) +#else /* !XP_WIN32 */ +#define TPS_PUBLIC +#endif /* !XP_WIN32 */ + +class Generate_Key_ECC_APDU : public APDU +{ + public: + TPS_PUBLIC Generate_Key_ECC_APDU (BYTE p1, BYTE p2, BYTE alg, + int keysize, BYTE option, + BYTE type, Buffer &wrapped_challenge, Buffer &key_check); + TPS_PUBLIC ~Generate_Key_ECC_APDU(); + TPS_PUBLIC APDU_Type GetType(); +}; + +#endif /* GENERATE_KEY_ECC_APDU_H */ diff --git a/base/tps/tools/raclient/RA_Conn.cpp b/base/tps/tools/raclient/RA_Conn.cpp index 17a3ed34f..8e7f30e51 100644 --- a/base/tps/tools/raclient/RA_Conn.cpp +++ b/base/tps/tools/raclient/RA_Conn.cpp @@ -30,6 +30,7 @@ #include "apdu/List_Objects_APDU.h" #include "apdu/Create_Object_APDU.h" #include "apdu/Generate_Key_APDU.h" +#include "apdu/Generate_Key_ECC_APDU.h" #include "apdu/External_Authenticate_APDU.h" #include "apdu/Initialize_Update_APDU.h" #include "apdu/Lifecycle_APDU.h" @@ -583,7 +584,7 @@ RA_Conn::CreateAPDU (RA_Token * tok, Buffer & in_apdu_data, Buffer & mac) } } - else if (((BYTE *) apdu_data)[1] == 0x0C) + else if ((((BYTE *) apdu_data)[1] == 0x0C) || (((BYTE *) apdu_data)[1] == 0x0D)) // for both RSA (0x0C) and ECC (0x0D) { /* Generate_Key_APDU */ BYTE p[2]; @@ -602,9 +603,16 @@ RA_Conn::CreateAPDU (RA_Token * tok, Buffer & in_apdu_data, Buffer & mac) ((BYTE *) apdu_data)[11 + wc_len + 1], (unsigned int) ((BYTE *) apdu_data)[11 + wc_len]); - apdu = - new Generate_Key_APDU (p[0], p[1], alg, keysize, option, type, + if (((BYTE *) apdu_data)[1] == 0x0D) { + apdu = + new Generate_Key_ECC_APDU (p[0], p[1], alg, keysize, option, type, *wrapped_challenge, *key_check); + } else { + apdu = + new Generate_Key_APDU (p[0], p[1], alg, keysize, option, type, + *wrapped_challenge, *key_check); + } + if (wrapped_challenge != NULL) { delete wrapped_challenge; diff --git a/base/tps/tools/raclient/RA_Token.cpp b/base/tps/tools/raclient/RA_Token.cpp index 069d6c23c..85de6f6d0 100644 --- a/base/tps/tools/raclient/RA_Token.cpp +++ b/base/tps/tools/raclient/RA_Token.cpp @@ -25,6 +25,7 @@ #include "apdu/APDU_Response.h" #include "apdu/Initialize_Update_APDU.h" #include "apdu/Generate_Key_APDU.h" +#include "apdu/Generate_Key_ECC_APDU.h" #include "apdu/Put_Key_APDU.h" #include "apdu/Select_APDU.h" #include "apdu/Get_Data_APDU.h" @@ -39,9 +40,103 @@ #include "keyhi.h" #include "nss.h" #include "cert.h" +#include "secoidt.h" +#define VERBOSE //#define VERIFY_PROOF +#define DEFAULT_CURVE_OID_TAG SEC_OID_SECG_EC_SECP192R1 +/* #define DEFAULT_CURVE_OID_TAG SEC_OID_SECG_EC_SECP160R1 */ + +/* curveNameTagPair is borrowed from certutil */ +typedef struct curveNameTagPairStr { + char *curveName; + SECOidTag curveOidTag; +} CurveNameTagPair; + +static CurveNameTagPair nameTagPair[] = +{ + { "sect163k1", SEC_OID_SECG_EC_SECT163K1}, + { "nistk163", SEC_OID_SECG_EC_SECT163K1}, + { "sect163r1", SEC_OID_SECG_EC_SECT163R1}, + { "sect163r2", SEC_OID_SECG_EC_SECT163R2}, + { "nistb163", SEC_OID_SECG_EC_SECT163R2}, + { "sect193r1", SEC_OID_SECG_EC_SECT193R1}, + { "sect193r2", SEC_OID_SECG_EC_SECT193R2}, + { "sect233k1", SEC_OID_SECG_EC_SECT233K1}, + { "nistk233", SEC_OID_SECG_EC_SECT233K1}, + { "sect233r1", SEC_OID_SECG_EC_SECT233R1}, + { "nistb233", SEC_OID_SECG_EC_SECT233R1}, + { "sect239k1", SEC_OID_SECG_EC_SECT239K1}, + { "sect283k1", SEC_OID_SECG_EC_SECT283K1}, + { "nistk283", SEC_OID_SECG_EC_SECT283K1}, + { "sect283r1", SEC_OID_SECG_EC_SECT283R1}, + { "nistb283", SEC_OID_SECG_EC_SECT283R1}, + { "sect409k1", SEC_OID_SECG_EC_SECT409K1}, + { "nistk409", SEC_OID_SECG_EC_SECT409K1}, + { "sect409r1", SEC_OID_SECG_EC_SECT409R1}, + { "nistb409", SEC_OID_SECG_EC_SECT409R1}, + { "sect571k1", SEC_OID_SECG_EC_SECT571K1}, + { "nistk571", SEC_OID_SECG_EC_SECT571K1}, + { "sect571r1", SEC_OID_SECG_EC_SECT571R1}, + { "nistb571", SEC_OID_SECG_EC_SECT571R1}, + { "secp160k1", SEC_OID_SECG_EC_SECP160K1}, + { "secp160r1", SEC_OID_SECG_EC_SECP160R1}, + { "secp160r2", SEC_OID_SECG_EC_SECP160R2}, + { "secp192k1", SEC_OID_SECG_EC_SECP192K1}, + { "secp192r1", SEC_OID_SECG_EC_SECP192R1}, + { "nistp192", SEC_OID_SECG_EC_SECP192R1}, + { "secp224k1", SEC_OID_SECG_EC_SECP224K1}, + { "secp224r1", SEC_OID_SECG_EC_SECP224R1}, + { "nistp224", SEC_OID_SECG_EC_SECP224R1}, + { "secp256k1", SEC_OID_SECG_EC_SECP256K1}, + { "secp256r1", SEC_OID_SECG_EC_SECP256R1}, + { "nistp256", SEC_OID_SECG_EC_SECP256R1}, + { "secp384r1", SEC_OID_SECG_EC_SECP384R1}, + { "nistp384", SEC_OID_SECG_EC_SECP384R1}, + { "secp521r1", SEC_OID_SECG_EC_SECP521R1}, + { "nistp521", SEC_OID_SECG_EC_SECP521R1}, + + { "prime192v1", SEC_OID_ANSIX962_EC_PRIME192V1 }, + { "prime192v2", SEC_OID_ANSIX962_EC_PRIME192V2 }, + { "prime192v3", SEC_OID_ANSIX962_EC_PRIME192V3 }, + { "prime239v1", SEC_OID_ANSIX962_EC_PRIME239V1 }, + { "prime239v2", SEC_OID_ANSIX962_EC_PRIME239V2 }, + { "prime239v3", SEC_OID_ANSIX962_EC_PRIME239V3 }, + + { "c2pnb163v1", SEC_OID_ANSIX962_EC_C2PNB163V1 }, + { "c2pnb163v2", SEC_OID_ANSIX962_EC_C2PNB163V2 }, + { "c2pnb163v3", SEC_OID_ANSIX962_EC_C2PNB163V3 }, + { "c2pnb176v1", SEC_OID_ANSIX962_EC_C2PNB176V1 }, + { "c2tnb191v1", SEC_OID_ANSIX962_EC_C2TNB191V1 }, + { "c2tnb191v2", SEC_OID_ANSIX962_EC_C2TNB191V2 }, + { "c2tnb191v3", SEC_OID_ANSIX962_EC_C2TNB191V3 }, + { "c2onb191v4", SEC_OID_ANSIX962_EC_C2ONB191V4 }, + { "c2onb191v5", SEC_OID_ANSIX962_EC_C2ONB191V5 }, + { "c2pnb208w1", SEC_OID_ANSIX962_EC_C2PNB208W1 }, + { "c2tnb239v1", SEC_OID_ANSIX962_EC_C2TNB239V1 }, + { "c2tnb239v2", SEC_OID_ANSIX962_EC_C2TNB239V2 }, + { "c2tnb239v3", SEC_OID_ANSIX962_EC_C2TNB239V3 }, + { "c2onb239v4", SEC_OID_ANSIX962_EC_C2ONB239V4 }, + { "c2onb239v5", SEC_OID_ANSIX962_EC_C2ONB239V5 }, + { "c2pnb272w1", SEC_OID_ANSIX962_EC_C2PNB272W1 }, + { "c2pnb304w1", SEC_OID_ANSIX962_EC_C2PNB304W1 }, + { "c2tnb359v1", SEC_OID_ANSIX962_EC_C2TNB359V1 }, + { "c2pnb368w1", SEC_OID_ANSIX962_EC_C2PNB368W1 }, + { "c2tnb431r1", SEC_OID_ANSIX962_EC_C2TNB431R1 }, + + { "secp112r1", SEC_OID_SECG_EC_SECP112R1}, + { "secp112r2", SEC_OID_SECG_EC_SECP112R2}, + { "secp128r1", SEC_OID_SECG_EC_SECP128R1}, + { "secp128r2", SEC_OID_SECG_EC_SECP128R2}, + + { "sect113r1", SEC_OID_SECG_EC_SECT113R1}, + { "sect113r2", SEC_OID_SECG_EC_SECT113R2}, + { "sect131r1", SEC_OID_SECG_EC_SECT131R1}, + { "sect131r2", SEC_OID_SECG_EC_SECT131R2}, +}; + + static BYTE ToVal (char c) { @@ -134,6 +229,7 @@ RA_Token::RA_Token () m_pin = PL_strdup ("password"); m_object_len = 0; m_object = NULL; + m_tokenpassword = NULL; } @@ -833,36 +929,71 @@ GetMusclePublicKeyData (SECKEYPublicKey * pubKey, int keylen) } static Buffer -Sign (SECKEYPrivateKey * privKey, Buffer & blob) +GetMusclePublicKeyDataEC (SECKEYPublicKey * pubKey, int keylen) +{ + Buffer pk = + Buffer ((BYTE *) pubKey->u.ec.publicValue.data, pubKey->u.ec.publicValue.len); + + Buffer blob = Buffer (1, (BYTE) 0) + + Buffer (1, (BYTE) 0x0a) + /* key type EC */ + Buffer (1, (BYTE) (keylen / 256)) + /* key size */ + Buffer (1, (BYTE) (keylen % 256)) + + Buffer (1, (BYTE) (pk.size() >> 8) & 0xff) + /*pubkey blob len*/ + Buffer (1, (BYTE) pk.size() & 0xff) + pk; +Output("pk ="); + printBuf(&pk); + return pk; +} + +static Buffer +Sign (SECOidTag sigAlg, SECKEYPrivateKey * privKey, Buffer & blob) { - SECStatus status; + SECStatus status = SECFailure; SECItem sigitem; - int signature_len; + int signature_len = 0;; signature_len = PK11_SignatureLen (privKey); sigitem.len = signature_len; sigitem.data = (unsigned char *) PORT_Alloc (signature_len); status = SEC_SignData (&sigitem, (BYTE *) blob, blob.size (), privKey, - SEC_OID_ISO_SHA_WITH_RSA_SIGNATURE); - if (status != SECSuccess) - { - printf ("Signing error\n"); - if (sigitem.data != NULL) - { - PORT_Free (sigitem.data); - sigitem.data = NULL; - } - return Buffer (16, (BYTE) 0); // sucks - } + sigAlg); + + if (status != SECSuccess) { + char buffer[1024]; + PR_GetErrorText (buffer); + + printf ("Signing error:%d %s\n",PR_GetError(), buffer); + if (sigitem.data != NULL) { + PORT_Free (sigitem.data); + sigitem.data = NULL; + } + + /*fake proof for ECC until it works*/ + char fake_proof [] = { + 0x30 ,0x44 ,0x02 ,0x20 ,0x00, + 0xd6 ,0xc2 ,0x08 ,0x34 ,0x79 ,0x28 ,0x2e ,0x5f ,0x70 ,0xe5, + 0x38 ,0x1d ,0x84 ,0xa9 ,0x40 ,0x05 ,0x65 ,0x67 ,0x0f ,0x65, + 0x46 ,0x5d ,0xf7 ,0x68 ,0x37 ,0x86 ,0x0b ,0x66 ,0xf7 ,0x71, + 0x0e ,0x02 ,0x20 ,0x3f ,0x48 ,0xdf ,0x29 ,0xa1 ,0x0e ,0xfb, + 0xdf ,0x38 ,0x26 ,0x9d ,0x54 ,0x01 ,0xbc ,0xb6 ,0x9d ,0xc0, + 0xbf ,0x27 ,0x29 ,0x95 ,0x97 ,0x3c ,0x2f ,0xef ,0xb1 ,0xd2, + 0xdc ,0x9f ,0xcb ,0x03 ,0x8d + }; + +/* return Buffer (16, (BYTE) 0); // sucks*/ + + Output("returning fake proof"); + return Buffer ((BYTE *)fake_proof, (unsigned int)sizeof(fake_proof)); + } Buffer proof = Buffer (sigitem.data, signature_len); - if (sigitem.data != NULL) - { + if (sigitem.data != NULL) { PORT_Free (sigitem.data); sigitem.data = NULL; - } + } + Output("returning real proof"); return proof; } @@ -884,6 +1015,31 @@ GetKeyBlob (int keysize, SECKEYPublicKey * pubKey) } static Buffer +GetKeyBlobEC (int keysize, SECKEYPublicKey * pubKey) +{ + Buffer pubKeyBlob = + Buffer ((BYTE *) pubKey->u.ec.publicValue.data, pubKey->u.ec.publicValue.len); +#ifdef VERBOSE +Output("in GetKeyBlobEC, pubkey blob len =%d", pubKeyBlob.size()); +#endif + + Buffer blob = Buffer (1, (BYTE) 0) + + Buffer (1, (BYTE) 0x0a) + /* key type EC */ + Buffer (1, (BYTE) (keysize / 256)) + /* key size */ + Buffer (1, (BYTE) (keysize % 256)) + + Buffer (1, (BYTE) (pubKeyBlob.size() >> 8) & 0xff) + /*pubkey blob len*/ + Buffer (1, (BYTE) pubKeyBlob.size() & 0xff) + + pubKeyBlob; + +#ifdef VERBOSE +Output("GetKeyBlobEC: blob ="); +printBuf(&blob); +#endif + return blob; + +} + +static Buffer GetSignBlob (Buffer & muscle_public_key, Buffer & challenge) { int i, j; @@ -898,9 +1054,14 @@ GetSignBlob (Buffer & muscle_public_key, Buffer & challenge) { ((BYTE *) data)[i] = ((BYTE *) challenge)[j]; } +Output("datablob ="); + printBuf(&data); return data; } +/* + * for RSA keys + */ APDU_Response * RA_Token::ProcessGenerateKey (Generate_Key_APDU * apdu, NameValueSet * vars, NameValueSet * params) @@ -957,8 +1118,10 @@ RA_Token::ProcessGenerateKey (Generate_Key_APDU * apdu, /* generate key pair */ char *keygen_param = params->GetValue ("keygen"); + if (keygen_param == NULL || (strcmp (keygen_param, "true") == 0)) { + Output("keygen is true"); privKey = PK11_GenerateKeyPair (slot, mechanism, x_params, &pubKey, PR_FALSE /*isPerm */ , @@ -966,12 +1129,14 @@ RA_Token::ProcessGenerateKey (Generate_Key_APDU * apdu, NULL /*wincx */ ); if (privKey == NULL) { + Output("privKey NULL"); // printf("privKey == NULL\n"); buffer_size = 1024; /* testing */ } else { + Output("privKey not NULL"); /* put key in the buffer */ // printf("modulus len %d\n", pubKey->u.rsa.modulus.len); // printf("exponent len %d\n", pubKey->u.rsa.publicExponent.len); @@ -1001,7 +1166,7 @@ RA_Token::ProcessGenerateKey (Generate_Key_APDU * apdu, Buffer data_blob = GetSignBlob ( /*muscle_public_key */ blob, challenge); // printf("after getsignblob, blob size =%d",blob.size()); - Buffer proof = Sign (privKey, data_blob); + Buffer proof = Sign (SEC_OID_ISO_SHA_WITH_RSA_SIGNATURE, privKey, data_blob); // printf("begin verifying proof"); unsigned char *pkeyb = (unsigned char *) (BYTE *) data_blob; int pkeyb_len = data_blob.size (); @@ -1036,6 +1201,7 @@ RA_Token::ProcessGenerateKey (Generate_Key_APDU * apdu, return apdu_resp; } + Output("after VerifyProof"); m_buffer = Buffer (1, (BYTE) (blob.size () / 256)) + @@ -1049,8 +1215,9 @@ RA_Token::ProcessGenerateKey (Generate_Key_APDU * apdu, } else { - // fake key - BYTE fake_key[] = { + Output("keygen is false"); + // fake RSA key + BYTE fake_RSA_key[] = { 0x00, 0x8b, 0x00, 0x01, 0x04, 0x00, 0x00, 0x80, 0x9f, 0xf9, 0x6e, 0xa6, 0x6c, 0xd9, 0x4b, 0x5c, 0x1a, 0xb6, 0xd8, 0x78, 0xd2, 0xaf, 0x45, 0xd5, 0xce, 0x8a, 0xee, 0x69, 0xfc, 0xdb, @@ -1068,18 +1235,365 @@ RA_Token::ProcessGenerateKey (Generate_Key_APDU * apdu, 0x01, 0x00, 0x80, 0x58, 0x06, 0x40, 0x4e, 0x05, 0xd8, 0x54, 0x87, 0xb1, 0x5b, 0xfc, 0x67, 0x95, 0xe5 }; - m_buffer = Buffer ((BYTE *) fake_key, sizeof fake_key); + + m_buffer = Buffer ((BYTE *) fake_RSA_key, sizeof fake_RSA_key); buffer_size = m_buffer.size (); } - + Output("creating new APDU_Response, data = "); Buffer data = Buffer (1, (BYTE) (buffer_size >> 8) & 0xff) + // key length Buffer (1, (BYTE) buffer_size & 0xff) + // key length Buffer (1, (BYTE) 0x90) + Buffer (1, (BYTE) 0x00); + printBuf(&data); + APDU_Response *apdu_resp = new APDU_Response (data); return apdu_resp; } + +SECKEYECParams * +RA_Token::getECParams(const char *curve) +{ +/*This function is borrowed from certutil*/ + SECKEYECParams *ecparams = NULL; + SECOidData *oidData = NULL; + SECOidTag curveOidTag = SEC_OID_UNKNOWN; /* default */ + int i, numCurves; + + if (curve != NULL) { + numCurves = sizeof(nameTagPair)/sizeof(CurveNameTagPair); + for (i = 0; ((i < numCurves) && (curveOidTag == SEC_OID_UNKNOWN)); + i++) { + if (PL_strcmp(curve, nameTagPair[i].curveName) == 0) + curveOidTag = nameTagPair[i].curveOidTag; + } + } + + /* Return NULL if curve name is not recognized */ + if ((curveOidTag == SEC_OID_UNKNOWN) || + (oidData = SECOID_FindOIDByTag(curveOidTag)) == NULL) { + fprintf(stderr, "Unrecognized elliptic curve %s\n", curve); + return NULL; + } + + ecparams = SECITEM_AllocItem(NULL, NULL, (2 + oidData->oid.len)); + + /* + * ecparams->data needs to contain the ASN encoding of an object ID (OID) + * representing the named curve. The actual OID is in + * oidData->oid.data so we simply prepend 0x06 and OID length + */ + ecparams->data[0] = SEC_ASN1_OBJECT_ID; + ecparams->data[1] = oidData->oid.len; + memcpy(ecparams->data + 2, oidData->oid.data, oidData->oid.len); + + return ecparams; +} + +static int ReadLine(PRFileDesc *f, char *buf, int buf_len, int *removed_return) +{ + char *cur = buf; + int sum = 0; + PRInt32 rc; + + if (removed_return != NULL) { + *removed_return = 0; + } + while (1) { + rc = PR_Read(f, cur, 1); + if (rc == -1 || rc == 0) + break; + if (*cur == '\r') { + continue; + } + if (*cur == '\n') { + *cur = '\0'; + if (removed_return != NULL) { + *removed_return = 1; + } + break; + } + sum++; + cur++; + } + return sum; +} + + +char * +RA_Token::getModulePasswordText(PK11SlotInfo *slot, PRBool retry, void *arg) { + secuPWData *pwdata = (secuPWData *)arg; + if (pwdata->data != NULL) { + return PL_strdup(pwdata->data); + } else { + Output("getModulePasswordText: password not found"); + return NULL; + } +} + +/* + * for EC keys + */ +APDU_Response * +RA_Token::ProcessGenerateKeyECC (Generate_Key_ECC_APDU * apdu, + NameValueSet * vars, NameValueSet * params) +{ + CK_MECHANISM_TYPE mechanism = CKM_EC_KEY_PAIR_GEN; + SECKEYPrivateKey *privKey = NULL; + SECKEYPublicKey *pubKey = NULL; + PK11SlotInfo *slot = NULL; + int buffer_size = 0; + + // for testing only +#ifdef VERBOSE + Output ("RA_Token::ProcessGenerateKeyECC"); +#endif + if (vars->GetValueAsBool("test_enable", 0) == 1) { + if (vars->GetValueAsBool("test_apdu_gk_return_enable", 0) == 1) { + Buffer *data = ToBuffer (vars->GetValue ("test_apdu_gk_return")); + APDU_Response *apdu_resp = new APDU_Response (*data); + return apdu_resp; + } + } + + if (VerifyMAC (apdu) != 1) { + Buffer data = Buffer (1, (BYTE) 0x6a) + Buffer (1, (BYTE) 0x88); + APDU_Response *apdu_resp = new APDU_Response (data); + return apdu_resp; + } + + Buffer req = apdu->GetData (); + BYTE *raw = (BYTE *) req; + int keysize = (((BYTE *) req)[1] << 8) + ((BYTE *) req)[2]; +#ifdef VERBOSE + Output("Requested key size: %d", keysize); +#endif + char *keycurve = NULL; + /* only three curves are supported by token */ + if (keysize == 256) { + keycurve = "nistp256"; + } else if (keysize == 384) { + keycurve = "nistp384"; + } else if (keysize == 521) { + keycurve = "nistp521"; + } else { + Output("unsupported key size: %d, default to nistp256", keysize); + keycurve = "nistp256"; + } + + int wrapped_challenge_len = ((BYTE *) req)[5]; +#ifdef VERBOSE + printf("Challenged Size=%d\n", wrapped_challenge_len); +#endif + Buffer wrapped_challenge = Buffer ((BYTE *) & raw[6], + wrapped_challenge_len); + + PK11AttrFlags attrFlags = 0; + + /* generate key pair */ + char *keygen_param = params->GetValue ("keygen"); + + if (keygen_param == NULL || (strcmp (keygen_param, "true") == 0)) { +#ifdef VERBOSE + Output("EC keygen is true"); +#endif + /* + * slotnamefile contains the actual slot name. + * This is to overcome the issue with spaces in a token name + */ + char *slotnamefile = params->GetValue("slotnamefile"); + int removed_return = 0; + char slotname[500] = "internal"; + PRFileDesc *fd_slotname = (PRFileDesc *) NULL; + if (slotnamefile == NULL) { + slot = PK11_GetInternalKeySlot(); + } else { + fd_slotname = PR_Open(slotnamefile, PR_RDWR, 00400|00200); + int n = ReadLine(fd_slotname, slotname, 500, &removed_return); + slot = PK11_FindSlotByName(slotname); + } + + Output("slotname=%s ",slotname); + if (slot == NULL) { + Output("slot NULL"); + exit(1); + } else { + Output("using slot : %s", slotname); + } + + RA_Token::m_tokenpassword = params->GetValue("tokpasswd"); + /* log into token using plaintext*/ + secuPWData pwdata = {pwdata.PW_NONE, 0}; + pwdata.source = pwdata.PW_PLAINTEXT; + pwdata.data = RA_Token::m_tokenpassword; + PK11_SetPasswordFunc(RA_Token::getModulePasswordText); + + if (PK11_NeedLogin(slot)) { + Output("slot needs login"); + SECStatus rv = SECFailure; + rv = PK11_Authenticate(slot, PR_TRUE, &pwdata); + Output("after PK11_Authenticate"); + if (rv == SECSuccess) { + Output("token authenticated\n"); + } else { + Output("Could not get password for %s", + PK11_GetTokenName(slot)); + } + if (PK11_IsLoggedIn(slot, &pwdata)) { + Output("token logged in"); + } else { + Output("token not logged in"); + } + } + + SECKEYECParams *ecparams = getECParams(keycurve); + if (ecparams == NULL) { + Output("getECParams() returns NULL"); + exit(1); + } else { + Output("getECParams() returns not NULL"); + } + + Output("before calling PK11_GenerateKeyPair"); + privKey = PK11_GenerateKeyPair(slot, + mechanism, + ecparams, + &pubKey, + PR_TRUE /*isPerm*/, + PR_TRUE /*isSensitive*/, + &pwdata /*wincx*/); + Output("after calling PK11_GenerateKeyPair"); + + if (ecparams) { + SECITEM_FreeItem((SECItem *)ecparams, PR_TRUE); + } + if ((privKey == NULL) || (pubKey == NULL)) { + /*not good. should bail*/ + Output("privKey == NULL, fatal error."); + exit(1); + } else { +#ifdef VERBOSE +Output("privKey not NULL"); +#endif + /* put key in the buffer */ + Buffer blob = GetKeyBlobEC (keysize, pubKey); + +/* + * The key generation operation creates a proof-of-location for the + * newly generated key. This proof is a signature computed with the + * new private key using the ECDSA_SHA1signature algorithm. The + * signature is computed over the Muscle Key Blob representation of + * the new public key and the challenge sent in the key generation + * request. These two data fields are concatenated together to form + * the input to the signature, without any other data or length fields. + */ + + Buffer challenge = Buffer (16, (BYTE) 0x00); +#ifdef VERBOSE + printf("Encrypted Enrollment Challenge:\n"); + wrapped_challenge.dump(); +#endif + Util::DecryptData (m_kek_key, wrapped_challenge, challenge); + +#ifdef VERBOSE + printf("Enrollment Challenge:\n"); + challenge.dump(); + printf("after challenge dump"); +#endif + Buffer muscle_public_key = GetMusclePublicKeyDataEC (pubKey, keysize); +#ifdef VERBOSE + printf("after muscle_public_key get, muscle_public_key size=%d", muscle_public_key.size()); +#endif + Buffer data_blob = GetSignBlob ( /*muscle_public_key */ blob, + challenge); + Output("after getsignblob, blob size =%d",blob.size()); + Buffer proof = Sign (SEC_OID_ANSIX962_ECDSA_SHA1_SIGNATURE, privKey, data_blob); + +#ifdef VERBOSE + printf("begin verifying proof"); +#endif + unsigned char *pkeyb = (unsigned char *) (BYTE *) data_blob; + int pkeyb_len = data_blob.size (); + +Output("skipping VerifyProof"); +#ifdef VERIFY_PROOF + SECItem siProof; + siProof.type = (SECItemType) 0; + siProof.data = (unsigned char *) proof; + siProof.len = proof.size (); + + if (VerifyProof (pubKey, &siProof, pkeyb_len, pkeyb, &challenge) != 1) + { + + Output ("VerifyProof failed"); + Buffer data = Buffer (1, (BYTE) 0x6a) + Buffer (1, (BYTE) 0x88); + APDU_Response *apdu_resp = new APDU_Response (data); + return apdu_resp; + + } + +Output("after VerifyProof"); +Output("blob.size=%d", blob.size()); +Output("pkeyb_len=", pkeyb_len); +Output("proof.size=", proof.size()); +#endif /*VERIFY_PROOF */ + + /* ECC format */ + m_buffer = + Buffer (1, (BYTE) (blob.size () / 256)) + + Buffer (1, (BYTE) (blob.size () % 256)) + + Buffer (blob) + + Buffer (1, (BYTE) (proof.size () / 256)) + + Buffer (1, (BYTE) (proof.size () % 256)) + Buffer (proof); + buffer_size = m_buffer.size (); + } // if private key not NULL + + } else { + Output("keygen is false, using fake EC key with nistp256"); + + // fake/static EC key + BYTE fake_EC_key[] = { + 0x00, 0x47, // total length + 0x00, 0x0a, // EC + 0x01, 0x00, // keysize == 256 + 0x00, 0x41, // length of pubkey + // pubkey + 0x04, 0xd2, + 0x26 ,0x83 ,0x36 ,0x80 ,0x33 ,0x2d ,0x26 ,0xda ,0x76 ,0x97, + 0xbb ,0x0b ,0xc8 ,0xc3 ,0x86 ,0xc9 ,0x70 ,0x36 ,0x9b ,0x40, + 0x4c ,0xa4 ,0xec ,0x3a ,0x0b ,0xa5 ,0x89 ,0x67 ,0xde ,0xc4, + 0x89 ,0x47 ,0x28 ,0x15 ,0xdd ,0x74 ,0x4b ,0xf8 ,0x21 ,0x18, + 0x40 ,0x06 ,0xf9 ,0x28 ,0xc4 ,0x62 ,0x26 ,0xa1 ,0x59 ,0x59, + 0x85 ,0x62 ,0xaf ,0xd0 ,0x5d ,0x43 ,0xde ,0xd7 ,0xb4 ,0xcf, + 0xc5 ,0x5b ,0xee, + // proof size + 0x00, 0x46, + //proof + 0x30 ,0x44 ,0x02 ,0x20 ,0x00, + 0xd6 ,0xc2 ,0x08 ,0x34 ,0x79 ,0x28 ,0x2e ,0x5f ,0x70 ,0xe5, + 0x38 ,0x1d ,0x84 ,0xa9 ,0x40 ,0x05 ,0x65 ,0x67 ,0x0f ,0x65, + 0x46 ,0x5d ,0xf7 ,0x68 ,0x37 ,0x86 ,0x0b ,0x66 ,0xf7 ,0x71, + 0x0e ,0x02 ,0x20 ,0x3f ,0x48 ,0xdf ,0x29 ,0xa1 ,0x0e ,0xfb, + 0xdf ,0x38 ,0x26 ,0x9d ,0x54 ,0x01 ,0xbc ,0xb6 ,0x9d ,0xc0, + 0xbf ,0x27 ,0x29 ,0x95 ,0x97 ,0x3c ,0x2f ,0xef ,0xb1 ,0xd2, + 0xdc ,0x9f ,0xcb ,0x03 ,0x8d + }; + + m_buffer = Buffer ((BYTE *) fake_EC_key, sizeof fake_EC_key); + buffer_size = m_buffer.size (); + } + + Output("creating new APDU_Response, data = "); + Buffer data = + Buffer (1, (BYTE) (buffer_size >> 8) & 0xff) + // key length + Buffer (1, (BYTE) buffer_size & 0xff) + // key length + Buffer (1, (BYTE) 0x90) + Buffer (1, (BYTE) 0x00); + printBuf(&data); + + APDU_Response *apdu_resp = new APDU_Response (data); + return apdu_resp; +} + APDU_Response * RA_Token::ProcessCreateObject (Create_Object_APDU * apdu, NameValueSet * vars, NameValueSet * params) @@ -1995,6 +2509,10 @@ RA_Token::Process (APDU * apdu, NameValueSet * vars, NameValueSet * params) { resp = ProcessGenerateKey ((Generate_Key_APDU *) apdu, vars, params); } + else if (apdu->GetType () == APDU_GENERATE_KEY_ECC) + { + resp = ProcessGenerateKeyECC ((Generate_Key_ECC_APDU *) apdu, vars, params); + } else if (apdu->GetType () == APDU_IMPORT_KEY_ENC) { resp = ProcessImportKeyEnc ((Import_Key_Enc_APDU *) apdu, vars, params); diff --git a/base/tps/tools/raclient/RA_Token.h b/base/tps/tools/raclient/RA_Token.h index bf92e4e89..de60857da 100644 --- a/base/tps/tools/raclient/RA_Token.h +++ b/base/tps/tools/raclient/RA_Token.h @@ -62,6 +62,7 @@ #include "apdu/List_Objects_APDU.h" #include "apdu/Create_Pin_APDU.h" #include "apdu/Generate_Key_APDU.h" +#include "apdu/Generate_Key_ECC_APDU.h" #include "apdu/Select_APDU.h" #include "apdu/Delete_File_APDU.h" #include "apdu/Get_Version_APDU.h" @@ -76,6 +77,7 @@ typedef enum { kek } keyType; + class RA_Token { public: @@ -103,6 +105,17 @@ class RA_Token void SetMinorVersion(int v); BYTE GetLifeCycleState(); public: +typedef struct { + enum { + PW_NONE = 0, + PW_FROMFILE = 1, + PW_PLAINTEXT = 2, + PW_EXTERNAL = 3 + } source; + char *data; +} secuPWData; + + static char *getModulePasswordText(PK11SlotInfo *slot, PRBool retry, void *arg); int VerifyMAC(APDU *apdu); void ComputeAPDUMac(APDU *apdu, Buffer &new_mac); PK11SymKey *CreateSessionKey(keyType keytype, @@ -189,6 +202,9 @@ class RA_Token APDU_Response *ProcessGenerateKey(Generate_Key_APDU *apdu, NameValueSet *vars, NameValueSet *params); + APDU_Response *ProcessGenerateKeyECC(Generate_Key_ECC_APDU *apdu, + NameValueSet *vars, + NameValueSet *params); APDU_Response *ProcessImportKeyEnc(Import_Key_Enc_APDU *apdu, NameValueSet *vars, NameValueSet *params); @@ -198,28 +214,34 @@ class RA_Token APDU_Response *ProcessPutKey(Put_Key_APDU *apdu, NameValueSet *vars, NameValueSet *params); + +#define DEFAULT_CURVE_OID_TAG SEC_OID_SECG_EC_SECP192R1 +/* #define DEFAULT_CURVE_OID_TAG SEC_OID_SECG_EC_SECP160R1 */ + + static SECKEYECParams *getECParams(const char *curve); public: - Buffer m_card_challenge; - Buffer m_host_challenge; - PK11SymKey *m_session_key; - PK11SymKey *m_enc_session_key; - Buffer m_icv; - Buffer m_cuid; - Buffer m_msn; - Buffer m_version; - Buffer m_key_info; - Buffer m_auth_key; - Buffer m_mac_key; - Buffer m_kek_key; - Buffer m_buffer; - BYTE m_lifecycle_state; - char *m_pin; - Buffer* m_object; - int m_major_version; - int m_minor_version; - int m_object_len; - int m_chunk_len; - char m_objectid[3]; + Buffer m_card_challenge; + Buffer m_host_challenge; + PK11SymKey *m_session_key; + PK11SymKey *m_enc_session_key; + Buffer m_icv; + Buffer m_cuid; + Buffer m_msn; + Buffer m_version; + Buffer m_key_info; + Buffer m_auth_key; + Buffer m_mac_key; + Buffer m_kek_key; + Buffer m_buffer; + BYTE m_lifecycle_state; + char *m_pin; + Buffer* m_object; + int m_major_version; + int m_minor_version; + int m_object_len; + int m_chunk_len; + char m_objectid[3]; + char *m_tokenpassword; }; #endif /* RA_TOKEN_H */ diff --git a/base/tps/tools/raclient/enroll.tps.ec b/base/tps/tools/raclient/enroll.tps.ec new file mode 100755 index 000000000..b6e25069d --- /dev/null +++ b/base/tps/tools/raclient/enroll.tps.ec @@ -0,0 +1,43 @@ +# --- BEGIN COPYRIGHT BLOCK --- +# This library is free software; you can redistribute it and/or +# modify it under the terms of the GNU Lesser General Public +# License as published by the Free Software Foundation; +# version 2.1 of the License. +# +# This library is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +# Lesser General Public License for more details. +# +# You should have received a copy of the GNU Lesser General Public +# License along with this library; if not, write to the Free Software +# Foundation, Inc., 51 Franklin Street, Fifth Floor, +# Boston, MA 02110-1301 USA +# +# Copyright (C) 2007 Red Hat, Inc. +# All rights reserved. +# --- END COPYRIGHT BLOCK --- +# +######################################################## +# Description: +# This data file tests enrollment operation. +# +# Execution: +# tpsclient < enroll.test +# +######################################################## +op=var_set name=ra_host value=host1 +op=var_set name=ra_port value=7891 +op=var_set name=ra_uri value=/nk_service +# print original token status +op=token_set cuid=a00192030405060708c9 msn=01020304 app_ver=6FBBC105 key_info=0101 major_ver=0 minor_ver=0 +op=token_set auth_key=404142434445464748494a4b4c4d4e4f +op=token_set mac_key=404142434445464748494a4b4c4d4e4f +op=token_set kek_key=404142434445464748494a4b4c4d4e4f +op=token_status +# slotnamefile is the file name which contains the name of the token +op=ra_enroll uid=pinmanager num_threads=1 pwd=netscape new_pin=netscape extensions=tokenType=userKey keygen=true slotnamefile=tokenname tokpasswd=redhat +# print changed token status +op=token_status +op=exit + |