summaryrefslogtreecommitdiffstats
path: root/pki/base/tps/tools/raclient/RA_Token.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'pki/base/tps/tools/raclient/RA_Token.cpp')
-rw-r--r--pki/base/tps/tools/raclient/RA_Token.cpp2008
1 files changed, 2008 insertions, 0 deletions
diff --git a/pki/base/tps/tools/raclient/RA_Token.cpp b/pki/base/tps/tools/raclient/RA_Token.cpp
new file mode 100644
index 000000000..069d6c23c
--- /dev/null
+++ b/pki/base/tps/tools/raclient/RA_Token.cpp
@@ -0,0 +1,2008 @@
+// --- 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 "cryptohi.h"
+#include "plstr.h"
+#include "main/Util.h"
+#include "RA_Token.h"
+#include "apdu/APDU_Response.h"
+#include "apdu/Initialize_Update_APDU.h"
+#include "apdu/Generate_Key_APDU.h"
+#include "apdu/Put_Key_APDU.h"
+#include "apdu/Select_APDU.h"
+#include "apdu/Get_Data_APDU.h"
+#include "apdu/List_Objects_APDU.h"
+#include "apdu/Get_IssuerInfo_APDU.h"
+#include "apdu/Set_IssuerInfo_APDU.h"
+#include "apdu/Read_Object_APDU.h"
+#include "apdu/Get_Version_APDU.h"
+#include "apdu/Get_Status_APDU.h"
+#include "apdu/List_Pins_APDU.h"
+#include "apdu/Create_Pin_APDU.h"
+#include "keyhi.h"
+#include "nss.h"
+#include "cert.h"
+
+//#define VERIFY_PROOF
+
+static BYTE
+ToVal (char c)
+{
+ if (c >= '0' && c <= '9')
+ {
+ return c - '0';
+ }
+ else if (c >= 'A' && c <= 'Z')
+ {
+ return c - 'A' + 10;
+ }
+ else if (c >= 'a' && c <= 'z')
+ {
+ return c - 'a' + 10;
+ }
+
+ /* The following return is needed to suppress compiler warnings on Linux. */
+ return 0;
+}
+
+static Buffer *
+ToBuffer (char *input)
+{
+ int len = strlen (input) / 2;
+ BYTE *buffer = NULL;
+
+ buffer = (BYTE *) malloc (len);
+ if (buffer == NULL)
+ {
+ return NULL;
+ }
+
+ for (int i = 0; i < len; i++)
+ {
+ buffer[i] = (ToVal (input[i * 2]) * 16) + ToVal (input[i * 2 + 1]);
+ }
+ Buffer *j;
+ j = new Buffer (buffer, len);
+
+ if (buffer != NULL)
+ {
+ free (buffer);
+ buffer = NULL;
+ }
+
+ return j;
+}
+
+/**
+ * Constructs a virtual token.
+ */
+RA_Token::RA_Token ()
+{
+ m_session_key = NULL;
+ m_enc_session_key = NULL;
+ BYTE key_info[] = {
+ 0x01, 0x01
+ };
+ BYTE version[] = {
+ 0x00, 0x01, 0x02, 0x03
+ };
+ BYTE cuid[] = {
+ 0x00, 0x01, 0x02, 0x03,
+ 0x04, 0x05, 0x06, 0x07,
+ 0x08, 0x09
+ };
+ BYTE msn[] = {
+ 0x00, 0x00, 0x00, 0x00
+ };
+ BYTE key[] = {
+ 0x40, 0x41, 0x42, 0x43,
+ 0x44, 0x45, 0x46, 0x47,
+ 0x48, 0x49, 0x4a, 0x4b,
+ 0x4c, 0x4d, 0x4e, 0x4f
+ };
+
+ m_major_version = 0;
+ m_minor_version = 0;
+
+ /* default setting */
+ m_lifecycle_state = 0;
+ m_icv = Buffer (8, (BYTE) 0);
+ m_auth_key = Buffer (key, sizeof key);
+ m_mac_key = Buffer (key, sizeof key);
+ m_kek_key = Buffer (key, sizeof key);
+ m_cuid = Buffer (cuid, sizeof cuid);
+ m_msn = Buffer (msn, sizeof msn);
+ m_version = Buffer (version, sizeof version);
+ m_key_info = Buffer (key_info, sizeof key_info);
+ m_pin = PL_strdup ("password");
+ m_object_len = 0;
+ m_object = NULL;
+}
+
+
+/**
+ * Destructs token.
+ */
+RA_Token::~RA_Token ()
+{
+ if (m_pin != NULL)
+ {
+ PL_strfree (m_pin);
+ m_pin = NULL;
+ }
+ if (m_session_key != NULL)
+ {
+ PORT_Free (m_session_key);
+ m_session_key = NULL;
+ }
+ if (m_enc_session_key != NULL)
+ {
+ PORT_Free (m_enc_session_key);
+ m_enc_session_key = NULL;
+ }
+ if (m_object != NULL)
+ {
+ delete (m_object);
+ m_object = NULL;
+ }
+}
+
+RA_Token *
+RA_Token::Clone ()
+{
+ RA_Token *token = new RA_Token ();
+ token->m_icv = m_icv;
+ /*
+ token->m_session_key = m_session_key;
+ token->m_enc_session_key = m_enc_session_key;
+ */
+ token->m_session_key = NULL;
+ token->m_enc_session_key = NULL;
+ token->m_lifecycle_state = m_lifecycle_state;
+ token->m_auth_key = m_auth_key;
+ token->m_major_version = m_major_version;
+ token->m_minor_version = m_minor_version;
+ token->m_mac_key = m_mac_key;
+ token->m_kek_key = m_kek_key;
+ token->m_cuid = m_cuid;
+ token->m_version = m_version;
+ token->m_key_info = m_key_info;
+ PL_strfree (token->m_pin);
+ token->m_pin = PL_strdup (m_pin);
+ token->m_object_len = m_object_len;
+ return token;
+}
+
+static void
+Output (const char *fmt, ...)
+{
+ va_list ap;
+ va_start (ap, fmt);
+ printf ("Output> ");
+ vprintf (fmt, ap);
+ printf ("\n");
+ va_end (ap);
+}
+
+void
+printBuf (Buffer * buf)
+{
+ int sum = 0;
+
+ BYTE *data = *buf;
+ int i = 0;
+ if (buf->size () > 255)
+ {
+ Output ("printBuf: TOO BIG to print");
+ return;
+ }
+ Output ("Begin printing buffer =====");
+ for (i = 0; i < (int) buf->size (); i++)
+ {
+ printf ("%02x ", (unsigned char) data[i]);
+ sum++;
+ if (sum == 10)
+ {
+ printf ("\n");
+ sum = 0;
+ }
+ }
+ Output ("End printing buffer =====");
+}
+
+Buffer & RA_Token::GetCUID ()
+{
+ return m_cuid;
+}
+
+Buffer & RA_Token::GetMSN ()
+{
+ return m_msn;
+}
+
+void
+RA_Token::SetCUID (Buffer & cuid)
+{
+ m_cuid = cuid;
+}
+
+void
+RA_Token::SetMSN (Buffer & msn)
+{
+ m_msn = msn;
+}
+
+Buffer & RA_Token::GetAppletVersion ()
+{
+ return m_version;
+}
+
+void
+RA_Token::SetAppletVersion (Buffer & version)
+{
+ m_version = version;
+}
+
+void
+RA_Token::SetMajorVersion (int v)
+{
+ m_major_version = v;
+}
+
+void
+RA_Token::SetMinorVersion (int v)
+{
+ m_minor_version = v;
+}
+
+void
+RA_Token::SetAuthKey (Buffer & key)
+{
+ m_auth_key = key;
+}
+
+void
+RA_Token::SetMacKey (Buffer & key)
+{
+ m_mac_key = key;
+}
+
+void
+RA_Token::SetKekKey (Buffer & key)
+{
+ m_kek_key = key;
+}
+
+Buffer & RA_Token::GetKeyInfo ()
+{
+ return m_key_info;
+}
+
+void
+RA_Token::SetKeyInfo (Buffer & key_info)
+{
+ m_key_info = key_info;
+}
+
+int
+RA_Token::GetMajorVersion ()
+{
+ return m_major_version;
+}
+
+int
+RA_Token::GetMinorVersion ()
+{
+ return m_minor_version;
+}
+
+BYTE
+RA_Token::GetLifeCycleState ()
+{
+ return m_lifecycle_state;
+}
+
+char *
+RA_Token::GetPIN ()
+{
+ return m_pin;
+}
+
+Buffer & RA_Token::GetAuthKey ()
+{
+ return m_auth_key;
+}
+
+Buffer & RA_Token::GetMacKey ()
+{
+ return m_mac_key;
+}
+
+Buffer & RA_Token::GetKekKey ()
+{
+ return m_kek_key;
+}
+
+int
+RA_Token::NoOfPrivateKeys ()
+{
+ SECKEYPrivateKeyList *list = NULL;
+ SECKEYPrivateKeyListNode *node;
+ PK11SlotInfo *slot = PK11_GetInternalKeySlot ();
+ int count;
+
+ list = PK11_ListPrivateKeysInSlot (slot);
+ for (count = 0, node = PRIVKEY_LIST_HEAD (list);
+ !PRIVKEY_LIST_END (node, list);
+ node = PRIVKEY_LIST_NEXT (node), count++)
+ {
+ /* nothing */
+ }
+ if (list != NULL)
+ {
+ SECKEY_DestroyPrivateKeyList (list);
+ list = NULL;
+ }
+
+ return count;
+}
+
+SECKEYPrivateKey *
+RA_Token::GetPrivateKey (int pos)
+{
+ SECKEYPrivateKeyList *list = NULL;
+ SECKEYPrivateKeyListNode *node;
+ PK11SlotInfo *slot = PK11_GetInternalKeySlot ();
+ int count;
+
+ list = PK11_ListPrivateKeysInSlot (slot);
+ for (count = 0, node = PRIVKEY_LIST_HEAD (list);
+ !PRIVKEY_LIST_END (node, list);
+ node = PRIVKEY_LIST_NEXT (node), count++)
+ {
+ if (pos == count)
+ {
+ return node->key;
+ }
+ }
+ if (list != NULL)
+ {
+ SECKEY_DestroyPrivateKeyList (list);
+ list = NULL;
+ }
+
+ return NULL;
+}
+
+int
+RA_Token::NoOfCertificates ()
+{
+ CERTCertList *clist = NULL;
+ CERTCertListNode *cln;
+ PK11SlotInfo *slot = PK11_GetInternalKeySlot ();
+ int count = 0;
+
+ clist = PK11_ListCertsInSlot (slot);
+ for (cln = CERT_LIST_HEAD (clist); !CERT_LIST_END (cln, clist);
+ cln = CERT_LIST_NEXT (cln))
+ {
+ count++;
+ }
+
+ return count;
+}
+
+CERTCertificate *
+RA_Token::GetCertificate (int pos)
+{
+ CERTCertList *clist = NULL;
+ CERTCertListNode *cln;
+ PK11SlotInfo *slot = PK11_GetInternalKeySlot ();
+ int count = 0;
+
+ clist = PK11_ListCertsInSlot (slot);
+ for (cln = CERT_LIST_HEAD (clist); !CERT_LIST_END (cln, clist);
+ cln = CERT_LIST_NEXT (cln))
+ {
+ if (count == pos)
+ {
+ CERTCertificate *cert = cln->cert;
+ return cert;
+ }
+ count++;
+ }
+
+ return NULL;
+}
+
+void
+RA_Token::decryptMsg (Buffer & in_data, Buffer & out_data)
+{
+ Output ("RA_Token::decryptMsg: decryption about to proceed");
+
+ //add this header back later...does not include lc, since it might change
+ Buffer header = in_data.substr (0, 4);
+#ifdef VERBOSE
+ Output ("input data =");
+ printBuf (&in_data);
+ Output ("length = %d", in_data.size ());
+#endif
+
+ //add this mac back later
+ Buffer mac = in_data.substr (in_data.size () - 8, 8);
+
+#ifdef VERBOSE
+ Output ("mac=");
+ printBuf (&mac);
+#endif
+
+ // encrypted data area is the part without header and mac
+ Buffer enc_in_data = in_data.substr (5, in_data.size () - 8 - 5);
+
+#ifdef VERBOSE
+ Output ("RA_Token::decryptMsg: enc_in_data size: %d", enc_in_data.size ());
+ Output ("encrypted in_data =");
+ printBuf (&enc_in_data);
+#endif
+
+ Buffer d_apdu_data;
+ PRStatus status = Util::DecryptData (GetEncSessionKey (),
+ enc_in_data, d_apdu_data);
+#ifdef VERBOSE
+ Output ("RA_Token::decryptMsg: decrypted data size = %d, data=",
+ d_apdu_data.size ());
+ printBuf (&d_apdu_data);
+#endif
+
+ if (status == PR_SUCCESS)
+ {
+ Output ("RA_Token::decryptMsg: decrypt success");
+ }
+ else
+ {
+ Output ("RA_Token::decryptMsg: decrypt failure");
+ // return NULL;
+ }
+
+ /*
+ * the original (pre-encrypted) data would look like the following
+ * orig. Length | Data... | <80> | <padding>
+ * where orig. Length is one byte,
+ * if orig Length + 1byte length is multiple of 8,
+ * it wasn't padded
+ * if orig Length + 1byte length is not multiple of 8,
+ * '80' was appended to the right of data field
+ * if that was multiple was 8, it's done, otherwise
+ * it was padded with 0 until the data len is a multiple of 8
+ */
+ int origLen = (int) ((BYTE *) d_apdu_data)[0];
+ Output ("RA_Token::decryptMsg: origLen = %d", origLen);
+
+ Buffer orig_data;
+
+ // this should perfectly skip the paddings, if was any
+ orig_data = d_apdu_data.substr (1, origLen);
+ out_data = header;
+ out_data += Buffer (1, ((BYTE *) d_apdu_data)[0] + 0x08);
+ out_data += orig_data;
+ out_data += mac;
+
+#ifdef VERBOSE
+ Output ("decrypted pdu data:");
+ printBuf (&out_data);
+#endif
+}
+
+APDU_Response *
+RA_Token::ProcessInitializeUpdate (Initialize_Update_APDU * apdu,
+ NameValueSet * vars, NameValueSet * params)
+{
+ BYTE requested_version = apdu->GetP1 ();
+ //BYTE requested_index = apdu->GetP2();
+ Buffer host_challenge = apdu->GetHostChallenge ();
+ m_host_challenge = host_challenge;
+// printf("Host Challenge: \n");
+// host_challenge.dump();
+
+ Buffer ki = GetKeyInfo ();
+ BYTE current_version = ((BYTE *) ki)[0];
+ //BYTE current_index = ((BYTE*)ki)[1];
+
+ // for testing only
+ if (vars->GetValueAsBool("test_enable", 0) == 1) {
+ if (vars->GetValueAsBool("test_apdu_iu_return_enable", 0) == 1) {
+ Buffer *data = ToBuffer (vars->GetValue ("test_apdu_iu_return"));
+ APDU_Response *apdu_resp = new APDU_Response (*data);
+ return apdu_resp;
+ }
+ }
+
+ if (requested_version != 0x00 && requested_version != current_version)
+ {
+ // return an error
+ Buffer data = Buffer (1, (BYTE) 0x6a) + Buffer (1, (BYTE) 0x88);
+ APDU_Response *apdu_resp = new APDU_Response (data);
+ return apdu_resp;
+ }
+
+ m_icv = Buffer (8, (BYTE) 0);
+
+ /**
+ * Initialize Update response:
+ * Key Diversification Data - 10 bytes
+ * Key Information Data - 2 bytes
+ * Card Challenge - 8 bytes
+ * Card Cryptogram - 8 bytes
+ */
+ Buffer card_challenge (8, (BYTE) 0);
+ Util::GetRandomChallenge (card_challenge);
+ m_card_challenge = card_challenge;
+
+ /* compute cryptogram */
+ Buffer icv = Buffer (8, (BYTE) 0);
+ Buffer input = host_challenge + card_challenge;
+ Buffer cryptogram (8, (BYTE) 0);
+
+ Buffer authkey = GetAuthKey ();
+ if (authkey == NULL)
+ {
+ return NULL;
+ }
+ PK11SymKey *encAuthKey = Util::DeriveKey (GetAuthKey (),
+ host_challenge, card_challenge);
+ Util::ComputeMAC (encAuthKey, input, icv, cryptogram);
+
+ // printf("Cryptogram: \n");
+ // cryptogram.dump();
+ //
+ // establish session key
+ m_session_key = CreateSessionKey (mac, m_card_challenge, m_host_challenge);
+ // establish Encryption session key
+ m_enc_session_key = CreateSessionKey (auth, m_card_challenge,
+ m_host_challenge);
+
+ Buffer data = GetCUID () + GetKeyInfo () +
+ card_challenge + cryptogram +
+ Buffer (1, (BYTE) 0x90) + Buffer (1, (BYTE) 0x00);
+ APDU_Response *apdu_resp = new APDU_Response (data);
+
+ return apdu_resp;
+}
+
+int
+RA_Token::VerifyMAC (APDU * apdu)
+{
+ Buffer data;
+ Buffer mac = apdu->GetMAC ();
+
+ Output ("RA_Token::VerifyMAC: Begins==== apdu type =%d", apdu->GetType ());
+ if (mac.size () != 8)
+ {
+ Output ("RA_Token::VerifyMAC: no mac? ok");
+ return 1;
+ }
+
+ Buffer new_mac = Buffer (8, (BYTE) 0);
+
+ ComputeAPDUMac (apdu, new_mac);
+ if (new_mac != mac)
+ {
+#ifdef VERBOSE
+ Output ("old mac: ");
+ printBuf (&mac);
+ Output ("new mac: ");
+ printBuf (&new_mac);
+#endif
+ Output ("RA_Token::VerifyMAC: *** failed ***");
+ return 0;
+ }
+ else
+ {
+ Output ("RA_Token::VerifyMAC: passed");
+ return 1;
+ }
+}
+
+void
+RA_Token::ComputeAPDUMac (APDU * apdu, Buffer & new_mac)
+{
+ Buffer data;
+
+ apdu->GetDataToMAC (data);
+
+#ifdef VERBOSE
+ Output ("RA_Token::ComputeAPDUMac: data to mac =");
+ printBuf (&data);
+ Output ("RA_Token::ComputeAPDUMac: current m_icv =");
+ printBuf (&m_icv);
+#endif
+
+
+ Util::ComputeMAC (m_session_key, data, m_icv, new_mac);
+#ifdef VERBOSE
+ Output ("RA_Token::ComputeAPDUMac: got new mac =");
+#endif
+ printBuf (&new_mac);
+
+
+ m_icv = new_mac;
+} /* EncodeAPDUMac */
+
+PK11SymKey *
+RA_Token::GetEncSessionKey ()
+{
+ return m_enc_session_key;
+}
+
+PK11SymKey *
+RA_Token::CreateSessionKey (keyType keytype, Buffer & card_challenge,
+ Buffer & host_challenge)
+{
+ BYTE *key = NULL;
+ char input[16];
+ int i;
+ BYTE *cc = (BYTE *) card_challenge;
+ int cc_len = card_challenge.size ();
+ BYTE *hc = (BYTE *) host_challenge;
+ int hc_len = host_challenge.size ();
+
+ if (keytype == mac)
+ key = (BYTE *) m_mac_key;
+ else if (keytype == auth)
+ key = (BYTE *) m_auth_key;
+ else
+ key = (BYTE *) m_mac_key; // for now
+
+ /* copy card and host challenge into input buffer */
+ for (i = 0; i < 8; i++)
+ {
+ input[i] = cc[i];
+ }
+ for (i = 0; i < 8; i++)
+ {
+ input[8 + i] = hc[i];
+ }
+
+ PK11SymKey *session_key =
+ Util::DeriveKey (Buffer (key, 16), Buffer (hc, hc_len),
+ Buffer (cc, cc_len));
+
+ //printf("XXX mac key\n");
+ //m_mac_key.dump();
+ //printf("XXX card challenge\n");
+ //card_challenge.dump();
+ //printf("XXX host challenge\n");
+ //host_challenge.dump();
+ SECItem *data = PK11_GetKeyData (session_key);
+ Buffer db = Buffer (data->data, data->len);
+ // printf("session key:\n");
+ // db.dump();
+
+ return session_key;
+}
+
+APDU_Response *
+RA_Token::ProcessExternalAuthenticate (External_Authenticate_APDU * apdu,
+ NameValueSet * vars,
+ NameValueSet * params)
+{
+ Buffer host_cryptogram = apdu->GetHostCryptogram ();
+
+#ifdef VERBOSE
+ Output ("RA_Token::ProcessExternalAuthenticate");
+#endif
+ // printf("Host Cryptogram: \n");
+ // host_cryptogram.dump();
+
+ // for testing only
+ if (vars->GetValueAsBool("test_enable", 0) == 1) {
+ if (vars->GetValueAsBool("test_apdu_ea_return_enable", 0) == 1) {
+ Buffer *data = ToBuffer (vars->GetValue ("test_apdu_ea_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 data = Buffer (1, (BYTE) 0x90) + Buffer (1, (BYTE) 0x00);
+ APDU_Response *apdu_resp = new APDU_Response (data);
+ return apdu_resp;
+}
+
+static int
+VerifyProof (SECKEYPublicKey * pk, SECItem * siProof,
+ unsigned short pkeyb_len, unsigned char *pkeyb,
+ Buffer * challenge)
+{
+ // this doesn't work, and not needed anymore
+ return 1;
+
+ int rs = 1;
+ unsigned short i = 0;
+ unsigned int j = 0;
+ unsigned char *chal = NULL;
+
+ VFYContext *vc = VFY_CreateContext (pk, siProof,
+ SEC_OID_ISO_SHA_WITH_RSA_SIGNATURE,
+ NULL);
+ if (vc == NULL)
+ {
+ Output ("VerifyProof: CreateContext failed");
+ return 0; // error
+ }
+
+ SECStatus vs = VFY_Begin (vc);
+ if (vs == SECFailure)
+ {
+ rs = -1;
+ Output ("VerifyProof: Begin failed");
+ goto loser;
+ }
+ unsigned char proof[1024];
+
+ for (i = 0; i < pkeyb_len; i++)
+ {
+ proof[i] = pkeyb[i];
+ }
+ chal = (unsigned char *) (BYTE *) (*challenge);
+
+ for (j = 0; j < challenge->size (); i++, j++)
+ {
+ proof[i] = chal[j];
+ }
+ vs =
+ VFY_Update (vc, (unsigned char *) proof, pkeyb_len + challenge->size ());
+ if (vs == SECFailure)
+ {
+ rs = -1;
+ Output ("VerifyProof: Update failed");
+ goto loser;
+ }
+ vs = VFY_End (vc);
+ if (vs == SECFailure)
+ {
+ rs = -1;
+ Output ("VerifyProof: End failed");
+ goto loser;
+ }
+ else
+ {
+ Output ("VerifyProof good");
+ }
+
+loser:
+ if (vc != NULL)
+ {
+ VFY_DestroyContext (vc, PR_TRUE);
+ vc = NULL;
+ }
+ return rs;
+
+}
+
+static Buffer
+GetMusclePublicKeyData (SECKEYPublicKey * pubKey, int keylen)
+{
+ int i, j;
+
+ Buffer pk = Buffer (4 /* header len */ +
+ pubKey->u.rsa.modulus.len +
+ pubKey->u.rsa.publicExponent.len);
+
+ ((BYTE *) pk)[0] = 0; /* BLOB_ENC_PLAIN */
+ ((BYTE *) pk)[1] = 0x01; /* Public RSA Key */
+ ((BYTE *) pk)[2] = keylen / 256;
+ ((BYTE *) pk)[3] = keylen % 256;
+ ((BYTE *) pk)[4] = pubKey->u.rsa.modulus.len / 256;
+ ((BYTE *) pk)[5] = pubKey->u.rsa.modulus.len % 256;
+ for (i = 0; i < (int) pubKey->u.rsa.modulus.len; i++)
+ {
+ ((BYTE *) pk)[6 + i] = pubKey->u.rsa.modulus.data[i];
+ }
+ ((BYTE *) pk)[i++] = pubKey->u.rsa.publicExponent.len / 256;
+ ((BYTE *) pk)[i++] = pubKey->u.rsa.publicExponent.len % 256;
+ for (j = 0; j < (int) pubKey->u.rsa.publicExponent.len; j++)
+ {
+ ((BYTE *) pk)[i++] = pubKey->u.rsa.publicExponent.data[j];
+ }
+ return pk;
+}
+
+static Buffer
+Sign (SECKEYPrivateKey * privKey, Buffer & blob)
+{
+ SECStatus status;
+
+ SECItem sigitem;
+ int signature_len;
+
+ 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
+ }
+
+ Buffer proof = Buffer (sigitem.data, signature_len);
+ if (sigitem.data != NULL)
+ {
+ PORT_Free (sigitem.data);
+ sigitem.data = NULL;
+ }
+ return proof;
+}
+
+static Buffer
+GetKeyBlob (int keysize, SECKEYPublicKey * pubKey)
+{
+ Buffer blob = Buffer (1, (BYTE) 0) + /* encoding */
+ Buffer (1, (BYTE) 1) + /* key type */
+ Buffer (1, (BYTE) (keysize >> 8) & 0xff) + /* key size */
+ Buffer (1, (BYTE) keysize & 0xff) + /* key size */
+ Buffer (1, (BYTE) (pubKey->u.rsa.modulus.len >> 8) & 0xff) +
+ Buffer (1, (BYTE) pubKey->u.rsa.modulus.len & 0xff) +
+ Buffer ((BYTE *) pubKey->u.rsa.modulus.data, pubKey->u.rsa.modulus.len) +
+ Buffer (1, (BYTE) (pubKey->u.rsa.publicExponent.len >> 8) & 0xff) +
+ Buffer (1, (BYTE) pubKey->u.rsa.publicExponent.len & 0xff) +
+ Buffer ((BYTE *) pubKey->u.rsa.publicExponent.data,
+ pubKey->u.rsa.publicExponent.len);
+ return blob;
+}
+
+static Buffer
+GetSignBlob (Buffer & muscle_public_key, Buffer & challenge)
+{
+ int i, j;
+
+ Buffer data = Buffer (muscle_public_key.size () +
+ challenge.size (), (BYTE) 0);
+ for (i = 0; i < (int) muscle_public_key.size (); i++)
+ {
+ ((BYTE *) data)[i] = ((BYTE *) muscle_public_key)[i];
+ }
+ for (j = 0; j < (int) challenge.size (); j++, i++)
+ {
+ ((BYTE *) data)[i] = ((BYTE *) challenge)[j];
+ }
+ return data;
+}
+
+APDU_Response *
+RA_Token::ProcessGenerateKey (Generate_Key_APDU * apdu,
+ NameValueSet * vars, NameValueSet * params)
+{
+ CK_MECHANISM_TYPE mechanism;
+ SECOidTag algtag;
+ PK11RSAGenParams rsaparams;
+ void *x_params;
+ SECKEYPrivateKey *privKey;
+ SECKEYPublicKey *pubKey;
+ PK11SlotInfo *slot = PK11_GetInternalKeySlot ();
+ int publicExponent = 0x010001;
+ int buffer_size;
+ // RA::Debug( LL_PER_PDU,
+ // "RA_Token::ProcessGenerateKey: ",
+ // "=====ProcessGenerateKey():in ProcessGenerateKey====" );
+
+ // for testing only
+#ifdef VERBOSE
+ Output ("RA_Token::ProcessGenerateKey");
+#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;
+ // BYTE alg = (BYTE)req[5];
+ int keysize = (((BYTE *) req)[1] << 8) + ((BYTE *) req)[2];
+// printf("Requested key size %d\n", keysize);
+
+ int wrapped_challenge_len = ((BYTE *) req)[5];
+// printf("Challenged Size=%d\n", wrapped_challenge_len);
+ Buffer wrapped_challenge = Buffer ((BYTE *) & raw[6],
+ wrapped_challenge_len);
+
+ rsaparams.keySizeInBits = keysize;
+ rsaparams.pe = publicExponent;
+ mechanism = CKM_RSA_PKCS_KEY_PAIR_GEN;
+ algtag = SEC_OID_PKCS1_MD5_WITH_RSA_ENCRYPTION;
+ x_params = &rsaparams;
+
+ /* generate key pair */
+ char *keygen_param = params->GetValue ("keygen");
+ if (keygen_param == NULL || (strcmp (keygen_param, "true") == 0))
+ {
+ privKey = PK11_GenerateKeyPair (slot, mechanism,
+ x_params, &pubKey,
+ PR_FALSE /*isPerm */ ,
+ PR_TRUE /*isSensitive */ ,
+ NULL /*wincx */ );
+ if (privKey == NULL)
+ {
+ // printf("privKey == NULL\n");
+ buffer_size = 1024; /* testing */
+ }
+ else
+ {
+
+ /* 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);
+
+ Buffer blob = GetKeyBlob (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 RSA-with-MD5 signature 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);
+ // printf("Encrypted Enrollment Challenge:\n");
+ // wrapped_challenge.dump();
+ Util::DecryptData (m_kek_key, wrapped_challenge, challenge);
+
+// printf("Enrollment Challenge:\n");
+// challenge.dump();
+// printf("after challenge dump");
+ Buffer muscle_public_key = GetMusclePublicKeyData (pubKey, keysize);
+// printf("after muscle_public_key get, muscle_public_key size=%d", muscle_public_key.size());
+ Buffer data_blob = GetSignBlob ( /*muscle_public_key */ blob,
+ challenge);
+// printf("after getsignblob, blob size =%d",blob.size());
+ Buffer proof = Sign (privKey, data_blob);
+// printf("begin verifying proof");
+ unsigned char *pkeyb = (unsigned char *) (BYTE *) data_blob;
+ int pkeyb_len = data_blob.size ();
+
+ SECItem siProof;
+ siProof.type = (SECItemType) 0;
+ siProof.data = (unsigned char *) proof;
+ siProof.len = proof.size ();
+
+ // int size = data_blob.size();
+ // RA::Debug( LL_PER_PDU,
+ // "RA_Token::ProcessGenerateKey: ",
+ // "==== proof size =%d, data_blob size=%d",
+ // siProof.len,
+ // data_blob.size() );
+ // RA::Debug( LL_PER_PDU,
+ // "RA_Token::ProcessGenerateKey: ",
+ // "==== === printing blob. size=%d",
+ // size );
+ // RA::Debug( LL_PER_PDU,
+ // "RA_Token::ProcessGenerateKey: ",
+ // "pubKey->u.rsa.publicExponent.data[37] =%d",
+ // pubKey->u.rsa.publicExponent.data[37] );
+
+ 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;
+
+ }
+
+ 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
+ {
+ // fake key
+ BYTE fake_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,
+ 0x16, 0x21, 0x46, 0x61, 0xb9, 0x91, 0x5d, 0xa8, 0x41, 0x3f,
+ 0x5c, 0xce, 0xce, 0x16, 0x0b, 0xc3, 0x16, 0x99, 0xb7, 0x81,
+ 0xe9, 0x9c, 0xe5, 0x31, 0x04, 0x6d, 0xab, 0xb2, 0xa3, 0xac,
+ 0x91, 0x2b, 0xbd, 0x9b, 0x48, 0xa8, 0xd7, 0xd8, 0x34, 0x67,
+ 0x4d, 0x58, 0xd3, 0xb9, 0x81, 0x4f, 0x8c, 0xf1, 0x2c, 0x92,
+ 0xfa, 0xe7, 0x98, 0x72, 0xea, 0x52, 0xbb, 0x43, 0x73, 0x9e,
+ 0x88, 0xdc, 0x6c, 0x44, 0xf3, 0x6d, 0xfd, 0x36, 0xa6, 0x5c,
+ 0x61, 0x7d, 0x88, 0x51, 0xc7, 0x32, 0x14, 0x64, 0xf3, 0xe0,
+ 0x6f, 0xfa, 0x86, 0x1d, 0xad, 0x6c, 0xdb, 0x8a, 0x1c, 0x30,
+ 0xb2, 0x46, 0x26, 0xba, 0x3c, 0x71, 0x2c, 0x03, 0x45, 0x97,
+ 0x7f, 0xb0, 0x10, 0x24, 0xf4, 0x45, 0x00, 0x03, 0x01, 0x00,
+ 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);
+ buffer_size = m_buffer.size ();
+ }
+
+
+ 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);
+ APDU_Response *apdu_resp = new APDU_Response (data);
+ return apdu_resp;
+}
+
+APDU_Response *
+RA_Token::ProcessCreateObject (Create_Object_APDU * apdu,
+ NameValueSet * vars, NameValueSet * params)
+{
+ Buffer inputdata;
+ m_chunk_len = 0;
+ m_object_len = 0;
+
+#ifdef VERBOSE
+ Output ("RA_Token::ProcessCreateObject");
+#endif
+ // for testing only
+ if (vars->GetValueAsBool("test_enable", 0) == 1) {
+ if (vars->GetValueAsBool("test_apdu_co_return_enable", 0) == 1) {
+ Buffer *data = ToBuffer (vars->GetValue ("test_apdu_co_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;
+ }
+
+ inputdata = apdu->GetData ();
+// inputdata.dump();
+ m_objectid[0] = (char) (((BYTE *) inputdata)[0]);
+ m_objectid[1] = (char) (((BYTE *) inputdata)[1]);
+ m_objectid[2] = '\0';
+
+// skip permissions
+
+ m_object_len += (((BYTE *) inputdata)[4]) << 24;
+ m_object_len += (((BYTE *) inputdata)[5]) << 16;
+ m_object_len += (((BYTE *) inputdata)[6]) << 8;
+ m_object_len += ((BYTE *) inputdata)[7];
+
+ Buffer data = Buffer (1, (BYTE) 0x90) + Buffer (1, (BYTE) 0x00);
+ APDU_Response *apdu_resp = new APDU_Response (data);
+ if (m_object != NULL)
+ {
+ delete m_object;
+ m_object = NULL;
+ }
+ m_object = new Buffer (m_object_len, (BYTE) 0);
+ return apdu_resp;
+}
+
+APDU_Response *
+RA_Token::ProcessLifecycle (Lifecycle_APDU * apdu,
+ NameValueSet * vars, NameValueSet * params)
+{
+
+#ifdef VERBOSE
+ Output ("RA_Token::ProcessLifecycle");
+#endif
+ // for testing only
+ if (vars->GetValueAsBool("test_enable", 0) == 1) {
+ if (vars->GetValueAsBool("test_apdu_lc_return_enable", 0) == 1) {
+ Buffer *data = ToBuffer (vars->GetValue ("test_apdu_lc_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 data = Buffer (1, (BYTE) 0x90) + Buffer (1, (BYTE) 0x00);
+ APDU_Response *apdu_resp = new APDU_Response (data);
+ return apdu_resp;
+}
+
+APDU_Response *
+RA_Token::ProcessDeleteFile (Delete_File_APDU * apdu,
+ NameValueSet * vars, NameValueSet * params)
+{
+#ifdef VERBOSE
+ Output ("RA_Token::ProcessDeleteFile");
+#endif
+ // for testing only
+ if (vars->GetValueAsBool("test_enable", 0) == 1) {
+ if (vars->GetValueAsBool("test_apdu_df_return_enable", 0) == 1) {
+ Buffer *data = ToBuffer (vars->GetValue ("test_apdu_df_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 data = Buffer (1, (BYTE) 0x90) + Buffer (1, (BYTE) 0x00);
+ APDU_Response *apdu_resp = new APDU_Response (data);
+ return apdu_resp;
+}
+
+APDU_Response *
+RA_Token::ProcessInstallApplet (Install_Applet_APDU * apdu,
+ NameValueSet * vars, NameValueSet * params)
+{
+#ifdef VERBOSE
+ Output ("RA_Token::InstallApplet");
+#endif
+ // for testing only
+ if (vars->GetValueAsBool("test_enable", 0) == 1) {
+ if (vars->GetValueAsBool("test_apdu_ia_return_enable", 0) == 1) {
+ Buffer *data = ToBuffer (vars->GetValue ("test_apdu_ia_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 data = Buffer (1, (BYTE) 0x90) + Buffer (1, (BYTE) 0x00);
+ APDU_Response *apdu_resp = new APDU_Response (data);
+ return apdu_resp;
+}
+
+APDU_Response *
+RA_Token::ProcessInstallLoad (Install_Load_APDU * apdu,
+ NameValueSet * vars, NameValueSet * params)
+{
+#ifdef VERBOSE
+ Output ("RA_Token::InstallLoad");
+#endif
+ // for testing only
+ if (vars->GetValueAsBool("test_enable", 0) == 1) {
+ if (vars->GetValueAsBool("test_apdu_il_return_enable", 0) == 1) {
+ Buffer *data = ToBuffer (vars->GetValue ("test_apdu_il_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 data = Buffer (1, (BYTE) 0x90) + Buffer (1, (BYTE) 0x00);
+ APDU_Response *apdu_resp = new APDU_Response (data);
+ return apdu_resp;
+}
+
+APDU_Response *
+RA_Token::ProcessLoadFile (Load_File_APDU * apdu,
+ NameValueSet * vars, NameValueSet * params)
+{
+#ifdef VERBOSE
+ Output ("RA_Token::ProcessLoadFile");
+#endif
+ // for testing only
+ if (vars->GetValueAsBool("test_enable", 0) == 1) {
+ if (vars->GetValueAsBool("test_apdu_lf_return_enable", 0) == 1) {
+ Buffer *data = ToBuffer (vars->GetValue ("test_apdu_lf_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 data = Buffer (1, (BYTE) 0x90) + Buffer (1, (BYTE) 0x00);
+ APDU_Response *apdu_resp = new APDU_Response (data);
+ return apdu_resp;
+}
+
+APDU_Response *
+RA_Token::ProcessFormatMuscleApplet (Format_Muscle_Applet_APDU * apdu,
+ NameValueSet * vars,
+ NameValueSet * params)
+{
+
+ 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 data = Buffer (1, (BYTE) 0x90) + Buffer (1, (BYTE) 0x00);
+ APDU_Response *apdu_resp = new APDU_Response (data);
+ return apdu_resp;
+}
+
+APDU_Response *
+RA_Token::ProcessSelect (Select_APDU * apdu,
+ NameValueSet * vars, NameValueSet * params)
+{
+ // for testing only
+ if (vars->GetValueAsBool("test_enable", 0) == 1) {
+ if (vars->GetValueAsBool("test_apdu_se_return_enable", 0) == 1) {
+ Buffer *data = ToBuffer (vars->GetValue ("test_apdu_se_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 data = Buffer (1, (BYTE) 0x90) + Buffer (1, (BYTE) 0x00);
+ APDU_Response *apdu_resp = new APDU_Response (data);
+ return apdu_resp;
+}
+
+APDU_Response *
+RA_Token::ProcessListPins (List_Pins_APDU * apdu,
+ NameValueSet * vars, NameValueSet * params)
+{
+ // for testing only
+ if (vars->GetValueAsBool("test_enable", 0) == 1) {
+ if (vars->GetValueAsBool("test_apdu_lp_return_enable", 0) == 1) {
+ Buffer *data = ToBuffer (vars->GetValue ("test_apdu_lp_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 data = m_version + Buffer (1, (BYTE) 0x90) + Buffer (1, (BYTE) 0x00);
+ APDU_Response *apdu_resp = new APDU_Response (data);
+ return apdu_resp;
+}
+
+APDU_Response *
+RA_Token::ProcessGetIssuerInfo (Get_IssuerInfo_APDU * apdu,
+ NameValueSet * vars, NameValueSet * params)
+{
+ // for testing only
+ if (vars->GetValueAsBool("test_enable", 0) == 1) {
+ if (vars->GetValueAsBool("test_apdu_cp_return_enable", 0) == 1) {
+ Buffer *data = ToBuffer (vars->GetValue ("test_apdu_cp_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 data = m_version + Buffer (1, (BYTE) 0x90) + Buffer (1, (BYTE) 0x00);
+ APDU_Response *apdu_resp = new APDU_Response (data);
+ return apdu_resp;
+}
+
+APDU_Response *
+RA_Token::ProcessSetIssuerInfo (Set_IssuerInfo_APDU * apdu,
+ NameValueSet * vars, NameValueSet * params)
+{
+ // for testing only
+ if (vars->GetValueAsBool("test_enable", 0) == 1) {
+ if (vars->GetValueAsBool("test_apdu_cp_return_enable", 0) == 1) {
+ Buffer *data = ToBuffer (vars->GetValue ("test_apdu_cp_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 data = m_version + Buffer (1, (BYTE) 0x90) + Buffer (1, (BYTE) 0x00);
+ APDU_Response *apdu_resp = new APDU_Response (data);
+ return apdu_resp;
+}
+
+APDU_Response *
+RA_Token::ProcessCreatePin (Create_Pin_APDU * apdu,
+ NameValueSet * vars, NameValueSet * params)
+{
+ // for testing only
+ if (vars->GetValueAsBool("test_enable", 0) == 1) {
+ if (vars->GetValueAsBool("test_apdu_cp_return_enable", 0) == 1) {
+ Buffer *data = ToBuffer (vars->GetValue ("test_apdu_cp_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 data = m_version + Buffer (1, (BYTE) 0x90) + Buffer (1, (BYTE) 0x00);
+ APDU_Response *apdu_resp = new APDU_Response (data);
+ return apdu_resp;
+}
+
+APDU_Response *
+RA_Token::ProcessGetVersion (Get_Version_APDU * apdu,
+ NameValueSet * vars, NameValueSet * params)
+{
+ // for testing only
+ if (vars->GetValueAsBool("test_enable", 0) == 1) {
+ if (vars->GetValueAsBool("test_apdu_gv_return_enable", 0) == 1) {
+ Buffer *data = ToBuffer (vars->GetValue ("test_apdu_gv_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 data = m_version + Buffer (1, (BYTE) 0x90) + Buffer (1, (BYTE) 0x00);
+ APDU_Response *apdu_resp = new APDU_Response (data);
+ return apdu_resp;
+}
+
+APDU_Response *
+RA_Token::ProcessGetData (Get_Data_APDU * apdu,
+ NameValueSet * vars, NameValueSet * params)
+{
+ // for testing only
+ if (vars->GetValueAsBool("test_enable", 0) == 1) {
+ if (vars->GetValueAsBool("test_apdu_gd_return_enable", 0) == 1) {
+ Buffer *data = ToBuffer (vars->GetValue ("test_apdu_gd_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 data =
+ Buffer (1, (BYTE) 0x01) + Buffer (1, (BYTE) 0x00) +
+ Buffer (1, (BYTE) 0x01) +
+ m_cuid.substr (0, 4) +
+ Buffer (1, (BYTE) 0x01) + Buffer (1, (BYTE) 0x00) +
+ Buffer (1, (BYTE) 0x01) + Buffer (1, (BYTE) 0x00) +
+ Buffer (1, (BYTE) 0x01) + Buffer (1, (BYTE) 0x00) +
+ Buffer (1, (BYTE) 0x01) + Buffer (1, (BYTE) 0x00) +
+ m_cuid.substr (6, 4) +
+ m_cuid.substr (4, 2) +
+ Buffer (1, (BYTE) 0x01) + Buffer (1, (BYTE) 0x00) +
+ Buffer (1, (BYTE) 0x01) + Buffer (1, (BYTE) 0x00) +
+ Buffer (1, (BYTE) 0x00) + Buffer (1, (BYTE) 0x00) +
+ Buffer (1, (BYTE) 0x01) + Buffer (1, (BYTE) 0x00) +
+ Buffer (1, (BYTE) 0x01) + Buffer (1, (BYTE) 0x00) +
+ Buffer (1, (BYTE) 0x01) + Buffer (1, (BYTE) 0x00) +
+ Buffer (1, (BYTE) 0x01) + Buffer (1, (BYTE) 0x00) +
+ Buffer (1, (BYTE) 0x00) + Buffer (1, (BYTE) 0x00) +
+ Buffer (1, (BYTE) 0x01) + Buffer (1, (BYTE) 0x00) +
+ Buffer (1, (BYTE) 0x01) + Buffer (1, (BYTE) 0x00) +
+ m_msn.substr (0, 4) + Buffer (1, (BYTE) 0x90) + Buffer (1, (BYTE) 0x00);
+ APDU_Response *apdu_resp = new APDU_Response (data);
+ return apdu_resp;
+}
+
+APDU_Response *
+RA_Token::ProcessGetStatus (Get_Status_APDU * apdu,
+ NameValueSet * vars, NameValueSet * params)
+{
+ // for testing only
+ if (vars->GetValueAsBool("test_enable", 0) == 1) {
+ if (vars->GetValueAsBool("test_apdu_gs_return_enable", 0) == 1) {
+ Buffer *data = ToBuffer (vars->GetValue ("test_apdu_gs_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;
+ }
+
+ //Return a reasonable value for available applet memory.
+ //Free mem - 8192
+ //Tot mem - 8447
+ BYTE free_mem_high = 0x20;
+ BYTE free_mem_low = 0x00;
+ BYTE tot_mem_high = 0x20;
+ BYTE tot_mem_low = 0xff;
+ Buffer data =
+ Buffer (1, (BYTE) m_major_version) + Buffer (1, (BYTE) m_minor_version) +
+ Buffer (1, (BYTE) 0x00) + Buffer (1, (BYTE) 0x00) +
+ Buffer (1, (BYTE) 0x01) + Buffer (1, (BYTE) 0x00) +
+ Buffer (1, (BYTE) tot_mem_high) + Buffer (1, (BYTE) tot_mem_low) +
+ Buffer (1, (BYTE) 0x01) + Buffer (1, (BYTE) 0x00) +
+ Buffer (1, (BYTE) free_mem_high) + Buffer (1, (BYTE) free_mem_low) +
+ Buffer (1, (BYTE) 0x01) + Buffer (1, (BYTE) 0x00) +
+ Buffer (1, (BYTE) 0x01) + Buffer (1, (BYTE) 0x00) +
+ Buffer (1, (BYTE) 0x90) + Buffer (1, (BYTE) 0x00);
+ APDU_Response *apdu_resp = new APDU_Response (data);
+ return apdu_resp;
+}
+
+APDU_Response *
+RA_Token::ProcessPutKey (Put_Key_APDU * apdu,
+ NameValueSet * vars, NameValueSet * params)
+{
+#ifdef VERBOSE
+ Output ("RA_Token::ProcessPutKey");
+#endif
+ Buffer key_set_data = apdu->GetData ();
+ BYTE current_version = ((BYTE *) key_set_data)[0];
+ BYTE current_index = (apdu->GetP2 () & 0x0f);
+
+ BYTE ki[2] = { current_version, current_index };
+ Buffer kib (ki, 2);
+ SetKeyInfo (kib);
+
+ // for testing only
+ if (vars->GetValueAsBool("test_enable", 0) == 1) {
+ if (vars->GetValueAsBool("test_apdu_pk_return_enable", 0) == 1) {
+ Buffer *data = ToBuffer (vars->GetValue ("test_apdu_pk_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;
+ }
+
+ //BYTE new_version = key_set_data[0];
+ Buffer e_auth = key_set_data.substr (3, 16);
+ Buffer e_mac = key_set_data.substr (25, 16);
+ Buffer e_kek = key_set_data.substr (47, 16);
+
+ // need to retrieve the old kek, and decrypt the data
+ // with it
+ Buffer auth;
+ Buffer mac;
+ Buffer kek;
+ Util::DecryptData (m_kek_key, e_auth, auth);
+ Util::DecryptData (m_kek_key, e_mac, mac);
+ Util::DecryptData (m_kek_key, e_kek, kek);
+
+ m_kek_key = kek;
+ m_mac_key = mac;
+ m_auth_key = auth;
+
+ Buffer data = Buffer (1, (BYTE) 0x90) + Buffer (1, (BYTE) 0x00);
+ APDU_Response *apdu_resp = new APDU_Response (data);
+ return apdu_resp;
+}
+
+APDU_Response *
+RA_Token::ProcessImportKeyEnc (Import_Key_Enc_APDU * apdu,
+ NameValueSet * vars, NameValueSet * params)
+{
+#ifdef VERBOSE
+ Output ("RA_Token::ProcessImportKeyEnc");
+#endif
+ Buffer data;
+
+ // for testing only
+ if (vars->GetValueAsBool("test_enable", 0) == 1) {
+ if (vars->GetValueAsBool("test_apdu_ik_return_enable", 0) == 1) {
+ Buffer *data = ToBuffer (vars->GetValue ("test_apdu_ik_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;
+ }
+ data = apdu->GetData ();
+
+ data = Buffer (1, (BYTE) 0x90) + Buffer (1, (BYTE) 0x00);
+ APDU_Response *apdu_resp = new APDU_Response (data);
+ return apdu_resp;
+}
+
+APDU_Response *
+RA_Token::ProcessReadBuffer (Read_Buffer_APDU * apdu,
+ NameValueSet * vars, NameValueSet * params)
+{
+ Buffer buffer;
+
+#ifdef VERBOSE
+ Output ("RA_Token::ProcessReadBuffer");
+#endif
+ // for testing only
+ if (vars->GetValueAsBool("test_enable", 0) == 1) {
+ if (vars->GetValueAsBool("test_apdu_rb_return_enable", 0) == 1) {
+ Buffer *data = ToBuffer (vars->GetValue ("test_apdu_rb_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;
+ }
+
+ int len = apdu->GetLen ();
+ int offset = apdu->GetOffset ();
+
+ if (offset + len <= (int) m_buffer.size ())
+ {
+ buffer = m_buffer.substr (offset, len);
+ }
+ else
+ {
+ Output ("TESTING offset = %d, len = %d, m_buffer.size = %d",
+ offset, len, m_buffer.size ());
+ buffer = Buffer (len, (BYTE) 0); /* for testing */
+ }
+ Buffer data = buffer + Buffer (1, (BYTE) 0x90) + Buffer (1, (BYTE) 0x00);
+ APDU_Response *apdu_resp = new APDU_Response (data);
+ return apdu_resp;
+}
+
+APDU_Response *
+RA_Token::ProcessUnblockPin (Unblock_Pin_APDU * apdu,
+ NameValueSet * vars, NameValueSet * params)
+{
+#ifdef VERBOSE
+ Output ("RA_Token::ProcessUnblockPin");
+#endif
+ // for testing only
+ if (vars->GetValueAsBool("test_enable", 0) == 1) {
+ if (vars->GetValueAsBool("test_apdu_up_return_enable", 0) == 1) {
+ Buffer *data = ToBuffer (vars->GetValue ("test_apdu_up_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 data = Buffer (1, (BYTE) 0x90) + Buffer (1, (BYTE) 0x00);
+ APDU_Response *apdu_resp = new APDU_Response (data);
+ return apdu_resp;
+}
+
+APDU_Response *
+RA_Token::ProcessListObjects (List_Objects_APDU * apdu,
+ NameValueSet * vars, NameValueSet * params)
+{
+ // for testing only
+ if (vars->GetValueAsBool("test_enable", 0) == 1) {
+ if (vars->GetValueAsBool("test_apdu_lo_return_enable", 0) == 1) {
+ Buffer *data = ToBuffer (vars->GetValue ("test_apdu_lo_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 data = Buffer (1, (BYTE) 0x9C) + Buffer (1, (BYTE) 0x00);
+ APDU_Response *apdu_resp = new APDU_Response (data);
+ return apdu_resp;
+}
+
+APDU_Response *
+RA_Token::ProcessReadObject (Read_Object_APDU * apdu,
+ NameValueSet * vars, NameValueSet * params)
+{
+ Buffer buffer;
+
+#ifdef VERBOSE
+ Output ("RA_Token::ProcessReadObject");
+#endif
+ // for testing only
+ if (vars->GetValueAsBool("test_enable", 0) == 1) {
+ if (vars->GetValueAsBool("test_apdu_ro_return_enable", 0) == 1) {
+ Buffer *data = ToBuffer (vars->GetValue ("test_apdu_ro_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 buf = apdu->GetData();
+ int len = ((BYTE*)buf)[8];
+ int offset = (((BYTE*)buf)[4] << 24) + (((BYTE*)buf)[5] << 16) +
+ (((BYTE*)buf)[6] << 8) + ((BYTE*)buf)[7];
+
+ if (offset + len <= (int) m_buffer.size ())
+ {
+ buffer = m_buffer.substr (offset, len);
+ }
+ else
+ {
+ Output ("TESTING offset = %d, len = %d, m_buffer.size = %d",
+ offset, len, m_buffer.size ());
+ buffer = Buffer (len, (BYTE) 0); /* for testing */
+ }
+
+ Buffer data = buffer + Buffer (1, (BYTE) 0x90) + Buffer (1, (BYTE) 0x00);
+ APDU_Response *apdu_resp = new APDU_Response (data);
+ return apdu_resp;
+}
+
+APDU_Response *
+RA_Token::ProcessWriteBuffer (Write_Object_APDU * apdu,
+ NameValueSet * vars, NameValueSet * params)
+{
+#ifdef VERBOSE
+ Output ("RA_Token::ProcessWriteBuffer");
+#endif
+#define MAX_WRITE_BUFFER_SIZE 0x40
+ int num = 0;
+ int rv = -1;
+ int index = MAX_WRITE_BUFFER_SIZE + 2;
+ PK11SlotInfo *slot;
+ CERTCertificate *cert = NULL;
+
+ // for testing only
+ if (vars->GetValueAsBool("test_enable", 0) == 1) {
+ if (vars->GetValueAsBool("test_apdu_wb_return_enable", 0) == 1) {
+ Buffer *data = ToBuffer (vars->GetValue ("test_apdu_wb_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 inputdata = apdu->GetData ();
+ num = m_object_len - m_chunk_len;
+ if (num > MAX_WRITE_BUFFER_SIZE)
+ {
+ for (int i = 2; i < index; i++)
+ {
+ BYTE data = ((BYTE *) inputdata)[i];
+ ((BYTE *) * m_object)[m_chunk_len] = data;
+ m_chunk_len++;
+ }
+ }
+ else
+ {
+ for (int i = 2; i < num + 2; i++)
+ {
+ ((BYTE *) * m_object)[m_chunk_len] = ((BYTE *) inputdata)[i];
+ m_chunk_len++;
+ }
+
+ if (strcmp (m_objectid, "C0") == 0)
+ {
+ // printf("RA_Token::ProcessWriteBuffer objectid = %s\n", m_objectid);
+ // we got the whole certificate, import to the db.
+ cert = CERT_DecodeCertFromPackage ((char *) ((BYTE *) * m_object),
+ m_object->size ());
+ if (cert == NULL)
+ {
+ // printf("cert is NULL\n");
+ }
+ else
+ {
+ slot = PK11_GetInternalKeySlot ();
+
+ rv = PK11_Authenticate (slot, PR_TRUE, NULL);
+ if (rv != SECSuccess)
+ {
+ // printf("Failed to authenticate to the internal token\n");
+ }
+ else
+ {
+ rv = PK11_ImportCert (slot, cert, CK_INVALID_HANDLE,
+ (char *) "testcert", PR_FALSE);
+ if (rv != SECSuccess)
+ {
+ printf
+ ("Failed to import the cert to the internal token\n");
+ }
+ }
+ }
+ }
+ }
+
+ Buffer data = Buffer (1, (BYTE) 0x90) + Buffer (1, (BYTE) 0x00);
+ APDU_Response *apdu_resp = new APDU_Response (data);
+ return apdu_resp;
+}
+
+APDU_Response *
+RA_Token::ProcessSetPin (Set_Pin_APDU * apdu,
+ NameValueSet * vars, NameValueSet * params)
+{
+ Buffer new_pin_buf = apdu->GetNewPIN ();
+#ifdef VERBOSE
+ Output ("RA_Token::ProcessSetPin");
+#endif
+
+ // for testing only
+ if (vars->GetValueAsBool("test_enable", 0) == 1) {
+ if (vars->GetValueAsBool("test_apdu_sp_return_enable", 0) == 1) {
+ Buffer *data = ToBuffer (vars->GetValue ("test_apdu_sp_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;
+ }
+#if 0
+ printf ("New PIN: \n");
+ new_pin_buf.dump ();
+#endif
+
+ /* replace current pin */
+ int i;
+ char *new_pin = (char *) malloc (new_pin_buf.size () + 1);
+ for (i = 0; i < (int) new_pin_buf.size (); i++)
+ {
+ new_pin[i] = ((BYTE *) new_pin_buf)[i];
+ }
+ new_pin[new_pin_buf.size ()] = '\0';
+
+ if (m_pin != NULL)
+ {
+ PL_strfree (m_pin);
+ m_pin = NULL;
+ }
+ m_pin = new_pin;
+
+ Buffer data = Buffer (1, (BYTE) 0x90) + Buffer (1, (BYTE) 0x00);
+ APDU_Response *apdu_resp = new APDU_Response (data);
+ return apdu_resp;
+}
+
+APDU_Response *
+RA_Token::Process (APDU * apdu, NameValueSet * vars, NameValueSet * params)
+{
+ APDU_Response *resp = NULL;
+
+ if (apdu->GetType () == APDU_INITIALIZE_UPDATE)
+ {
+ resp = ProcessInitializeUpdate ((Initialize_Update_APDU *) apdu, vars,
+ params);
+ }
+ else if (apdu->GetType () == APDU_EXTERNAL_AUTHENTICATE)
+ {
+ resp = ProcessExternalAuthenticate ((External_Authenticate_APDU *) apdu,
+ vars, params);
+ }
+ else if (apdu->GetType () == APDU_SET_PIN)
+ {
+ resp = ProcessSetPin ((Set_Pin_APDU *) apdu, vars, params);
+ }
+ else if (apdu->GetType () == APDU_LOAD_FILE)
+ {
+ resp = ProcessLoadFile ((Load_File_APDU *) apdu, vars, params);
+ }
+ else if (apdu->GetType () == APDU_FORMAT_MUSCLE_APPLET)
+ {
+ resp = ProcessFormatMuscleApplet ((Format_Muscle_Applet_APDU *) apdu,
+ vars, params);
+ }
+ else if (apdu->GetType () == APDU_INSTALL_LOAD)
+ {
+ resp = ProcessInstallLoad ((Install_Load_APDU *) apdu, vars, params);
+ }
+ else if (apdu->GetType () == APDU_INSTALL_APPLET)
+ {
+ resp = ProcessInstallApplet ((Install_Applet_APDU *) apdu, vars,
+ params);
+ }
+ else if (apdu->GetType () == APDU_DELETE_FILE)
+ {
+ resp = ProcessDeleteFile ((Delete_File_APDU *) apdu, vars, params);
+ }
+ else if (apdu->GetType () == APDU_CREATE_OBJECT)
+ {
+ resp = ProcessCreateObject ((Create_Object_APDU *) apdu, vars, params);
+ }
+ else if (apdu->GetType () == APDU_LIFECYCLE)
+ {
+ resp = ProcessLifecycle ((Lifecycle_APDU *) apdu, vars, params);
+ }
+ else if (apdu->GetType () == APDU_READ_BUFFER)
+ {
+ resp = ProcessReadBuffer ((Read_Buffer_APDU *) apdu, vars, params);
+ }
+ else if (apdu->GetType () == APDU_UNBLOCK_PIN)
+ {
+ resp = ProcessUnblockPin ((Unblock_Pin_APDU *) apdu, vars, params);
+ }
+ else if (apdu->GetType () == APDU_LIST_OBJECTS)
+ {
+ resp = ProcessListObjects ((List_Objects_APDU *) apdu, vars, params);
+ }
+ else if (apdu->GetType () == APDU_READ_OBJECT)
+ {
+ resp = ProcessReadObject ((Read_Object_APDU *) apdu, vars, params);
+ }
+ else if (apdu->GetType () == APDU_WRITE_OBJECT)
+ {
+ resp = ProcessWriteBuffer ((Write_Object_APDU *) apdu, vars, params);
+ }
+ else if (apdu->GetType () == APDU_SELECT)
+ {
+ resp = ProcessSelect ((Select_APDU *) apdu, vars, params);
+ }
+ else if (apdu->GetType () == APDU_GET_VERSION)
+ {
+ resp = ProcessGetVersion ((Get_Version_APDU *) apdu, vars, params);
+ }
+ else if (apdu->GetType () == APDU_PUT_KEY)
+ {
+ resp = ProcessPutKey ((Put_Key_APDU *) apdu, vars, params);
+ }
+ else if (apdu->GetType () == APDU_GET_STATUS)
+ {
+ resp = ProcessGetStatus ((Get_Status_APDU *) apdu, vars, params);
+ }
+ else if (apdu->GetType () == APDU_GET_ISSUERINFO)
+ {
+ resp = ProcessGetIssuerInfo ((Get_IssuerInfo_APDU *) apdu, vars, params);
+ }
+ else if (apdu->GetType () == APDU_SET_ISSUERINFO)
+ {
+ resp = ProcessSetIssuerInfo ((Set_IssuerInfo_APDU *) apdu, vars, params);
+ }
+ else if (apdu->GetType () == APDU_GET_DATA)
+ {
+ resp = ProcessGetData ((Get_Data_APDU *) apdu, vars, params);
+ }
+ else if (apdu->GetType () == APDU_LIST_PINS)
+ {
+ resp = ProcessListPins ((List_Pins_APDU *) apdu, vars, params);
+ }
+ else if (apdu->GetType () == APDU_CREATE_PIN)
+ {
+ resp = ProcessCreatePin ((Create_Pin_APDU *) apdu, vars, params);
+ }
+ else if (apdu->GetType () == APDU_GENERATE_KEY)
+ {
+ resp = ProcessGenerateKey ((Generate_Key_APDU *) apdu, vars, params);
+ }
+ else if (apdu->GetType () == APDU_IMPORT_KEY_ENC)
+ {
+ resp = ProcessImportKeyEnc ((Import_Key_Enc_APDU *) apdu, vars, params);
+ }
+ else
+ {
+ printf ("RA_Token: Unknown APDU (%d)\n", apdu->GetType ());
+ /* error */
+ }
+ return resp;
+}