summaryrefslogtreecommitdiffstats
path: root/base/tps/tools
diff options
context:
space:
mode:
authorEndi Sukma Dewata <edewata@redhat.com>2012-03-24 02:27:47 -0500
committerEndi Sukma Dewata <edewata@redhat.com>2012-03-26 11:43:54 -0500
commit621d9e5c413e561293d7484b93882d985b3fe15f (patch)
tree638f3d75761c121d9a8fb50b52a12a6686c5ac5c /base/tps/tools
parent40d3643b8d91886bf210aa27f711731c81a11e49 (diff)
downloadpki-621d9e5c413e561293d7484b93882d985b3fe15f.tar.gz
pki-621d9e5c413e561293d7484b93882d985b3fe15f.tar.xz
pki-621d9e5c413e561293d7484b93882d985b3fe15f.zip
Removed unnecessary pki folder.
Previously the source code was located inside a pki folder. This folder was created during svn migration and is no longer needed. This folder has now been removed and the contents have been moved up one level. Ticket #131
Diffstat (limited to 'base/tps/tools')
-rw-r--r--base/tps/tools/CMakeLists.txt1
-rw-r--r--base/tps/tools/raclient/CMakeLists.txt47
-rw-r--r--base/tps/tools/raclient/RA_Client.cpp1645
-rw-r--r--base/tps/tools/raclient/RA_Client.h78
-rw-r--r--base/tps/tools/raclient/RA_Conn.cpp1037
-rw-r--r--base/tps/tools/raclient/RA_Conn.h71
-rw-r--r--base/tps/tools/raclient/RA_Token.cpp2008
-rw-r--r--base/tps/tools/raclient/RA_Token.h225
-rw-r--r--base/tps/tools/raclient/enroll.tps42
-rw-r--r--base/tps/tools/raclient/enroll1.test43
-rw-r--r--base/tps/tools/raclient/format.tps45
-rw-r--r--base/tps/tools/raclient/nt_enroll.test212
-rw-r--r--base/tps/tools/raclient/readme.txt247
-rw-r--r--base/tps/tools/raclient/reset_pin.tps42
-rw-r--r--base/tps/tools/raclient/reset_pin1.test40
-rw-r--r--base/tps/tools/raclient/reset_pin2.test39
-rw-r--r--base/tps/tools/tus/add.c117
-rw-r--r--base/tps/tools/tus/test.c117
18 files changed, 6056 insertions, 0 deletions
diff --git a/base/tps/tools/CMakeLists.txt b/base/tps/tools/CMakeLists.txt
new file mode 100644
index 000000000..6ed05c43d
--- /dev/null
+++ b/base/tps/tools/CMakeLists.txt
@@ -0,0 +1 @@
+add_subdirectory(raclient)
diff --git a/base/tps/tools/raclient/CMakeLists.txt b/base/tps/tools/raclient/CMakeLists.txt
new file mode 100644
index 000000000..8f01b34d8
--- /dev/null
+++ b/base/tps/tools/raclient/CMakeLists.txt
@@ -0,0 +1,47 @@
+project(tpsclient CXX)
+
+set(TPS_PRIVATE_INCLUDE_DIRS
+ ${TPS_PUBLIC_INCLUDE_DIRS}
+ ${CMAKE_BINARY_DIR}
+ ${NSPR_INCLUDE_DIRS}
+ ${NSS_INCLUDE_DIRS}
+)
+
+set(TPS_EXECUTABLE
+ tpsclient
+ CACHE INTERNAL "tpsclient executable"
+)
+
+set(TPS_LINK_LIBRARIES
+ ${TPS_SHARED_LIBRARY}
+ ${NSPR_LIBRARIES}
+ ${NSS_LIBRARIES}
+)
+
+set(tpsclient_SRCS
+ RA_Client.cpp
+ RA_Conn.cpp
+ RA_Token.cpp
+)
+
+include_directories(${TPS_PRIVATE_INCLUDE_DIRS})
+
+add_executable(${TPS_EXECUTABLE} ${tpsclient_SRCS})
+target_link_libraries(${TPS_EXECUTABLE} ${TPS_LINK_LIBRARIES})
+
+install(
+ TARGETS
+ ${TPS_EXECUTABLE}
+ RUNTIME DESTINATION ${BIN_INSTALL_DIR}
+ LIBRARY DESTINATION ${LIB_INSTALL_DIR}/tps
+ ARCHIVE DESTINATION ${LIB_INSTALL_DIR}/tps
+)
+
+install(
+ FILES
+ enroll.tps
+ format.tps
+ reset_pin.tps
+ DESTINATION
+ ${SHARE_INSTALL_PREFIX}/${APPLICATION_NAME}/tps/samples
+)
diff --git a/base/tps/tools/raclient/RA_Client.cpp b/base/tps/tools/raclient/RA_Client.cpp
new file mode 100644
index 000000000..c2a610e33
--- /dev/null
+++ b/base/tps/tools/raclient/RA_Client.cpp
@@ -0,0 +1,1645 @@
+// --- 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 <string.h>
+#include <stdarg.h>
+#include "prinrval.h"
+
+#include "prmem.h"
+#include "prsystem.h"
+#include "plstr.h"
+#include "prio.h"
+#include "prprf.h"
+#include "pk11func.h"
+
+#include "main/NameValueSet.h"
+#include "main/Util.h"
+#include "main/RA_Msg.h"
+#include "authentication/AuthParams.h"
+#include "apdu/APDU_Response.h"
+#include "apdu/Initialize_Update_APDU.h"
+#include "apdu/External_Authenticate_APDU.h"
+#include "apdu/Set_Pin_APDU.h"
+#include "msg/RA_Begin_Op_Msg.h"
+#include "msg/RA_End_Op_Msg.h"
+#include "msg/RA_Login_Request_Msg.h"
+#include "msg/RA_Login_Response_Msg.h"
+#include "msg/RA_Extended_Login_Request_Msg.h"
+#include "msg/RA_Extended_Login_Response_Msg.h"
+#include "msg/RA_Token_PDU_Request_Msg.h"
+#include "msg/RA_Token_PDU_Response_Msg.h"
+#include "msg/RA_New_Pin_Request_Msg.h"
+#include "msg/RA_New_Pin_Response_Msg.h"
+#include "msg/RA_SecureId_Request_Msg.h"
+#include "msg/RA_SecureId_Response_Msg.h"
+#include "msg/RA_ASQ_Request_Msg.h"
+#include "msg/RA_ASQ_Response_Msg.h"
+#include "msg/RA_Status_Update_Request_Msg.h"
+#include "msg/RA_Status_Update_Response_Msg.h"
+#include "RA_Token.h"
+#include "RA_Client.h"
+
+#include "nss.h"
+
+static PRFileDesc *m_fd_debug = (PRFileDesc *) NULL;
+PRBool old_style = PR_TRUE;
+
+/**
+ * Constructs a RA client that talks to RA.
+ */
+RA_Client::RA_Client ()
+{
+ /* default global variables */
+ m_vars.Add ("ra_host", "air");
+ m_vars.Add ("ra_port", "8000");
+ m_vars.Add ("ra_uri", "/nk_service");
+}
+
+/**
+ * Destructs this RA client.
+ */
+RA_Client::~RA_Client ()
+{
+ if (m_fd_debug != NULL)
+ {
+ PR_Close (m_fd_debug);
+ m_fd_debug = NULL;
+ }
+}
+
+static void
+PrintHeader ()
+{
+ printf ("Registration Authority Client\n");
+ printf ("'op=help' for Help\n");
+}
+
+static void
+Output (const char *fmt, ...)
+{
+ va_list ap;
+ va_start (ap, fmt);
+ printf ("Output> ");
+ vprintf (fmt, ap);
+ printf ("\n");
+ va_end (ap);
+}
+
+static void
+PrintPrompt ()
+{
+ printf ("Command>");
+}
+
+static void
+OutputSuccess (const char *fmt, ...)
+{
+ va_list ap;
+ va_start (ap, fmt);
+ printf ("Result> Success - ");
+ vprintf (fmt, ap);
+ printf ("\n");
+ va_end (ap);
+}
+
+static void
+OutputError (const char *fmt, ...)
+{
+ va_list ap;
+ va_start (ap, fmt);
+ printf ("Result> Error - ");
+ vprintf (fmt, ap);
+ printf ("\n");
+ va_end (ap);
+}
+
+static int
+ReadLine (char *buf, int len)
+{
+ char *cur = buf;
+
+ while (1)
+ {
+ *cur = getchar ();
+ if (*cur == '\r')
+ {
+ continue;
+ }
+ if (*cur == '\n')
+ {
+ *cur = '\0';
+ return 1;
+ }
+ cur++;
+ }
+ return 0;
+}
+
+void
+RA_Client::Debug (const char *func_name, const char *fmt, ...)
+{
+ PRTime now;
+ const char *time_fmt = "%Y-%m-%d %H:%M:%S";
+ char datetime[1024];
+ PRExplodedTime time;
+
+ if (m_fd_debug == NULL)
+ return;
+ va_list ap;
+ va_start (ap, fmt);
+ now = PR_Now ();
+ PR_ExplodeTime (now, PR_LocalTimeParameters, &time);
+ PR_FormatTimeUSEnglish (datetime, 1024, time_fmt, &time);
+ PR_fprintf (m_fd_debug, "[%s] %s - ", datetime, func_name);
+ PR_vfprintf (m_fd_debug, fmt, ap);
+ va_end (ap);
+ PR_Write (m_fd_debug, "\n", 1);
+}
+
+int
+RA_Client::OpHelp (NameValueSet * params)
+{
+ Output ("Available Operations:");
+ Output ("op=debug filename=<filename> - enable debugging");
+ Output ("op=help");
+ Output
+ ("op=ra_enroll uid=<uid> pwd=<pwd> num_threads=<number of threads> secureid_pin=<secureid_pin> keygen=<true|false> - Enrollment Via RA");
+ Output
+ ("op=ra_reset_pin uid=<uid> pwd=<pwd> num_threads=<number of threads> secureid_pin=<secureid_pin> new_pin=<new_pin> - Reset Pin Via RA");
+ Output
+ ("op=ra_update uid=<uid> pwd=<pwd> num_threads=<number of threads> secureid_pin=<secureid_pin> new_pin=<new_pin> - Reset Pin Via RA");
+ Output ("op=token_set <name>=<value> - Set Token Value");
+ Output ("op=token_status - Print Token Status");
+ Output ("op=var_get name=<name> - Get Value of Variable");
+ Output ("op=var_list - List All Variables");
+ Output ("op=var_set name=<name> value=<value> - Set Value to Variable");
+
+ return 1;
+}
+
+static void
+GetBuffer (Buffer & buf, char *output, int len)
+{
+ int i;
+
+ output[0] = '\0';
+ for (i = 0; i < (int) buf.size (); ++i)
+ {
+ sprintf (output, "%s%02x", output, ((BYTE *) buf)[i]);
+ }
+}
+
+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;
+}
+
+int
+RA_Client::OpTokenStatus (NameValueSet * params)
+{
+ int i;
+ char output[2048];
+
+ Output ("life_cycle_state : '%x'", m_token.GetLifeCycleState ());
+ Output ("pin : '%s'", m_token.GetPIN ());
+ GetBuffer (m_token.GetAppletVersion (), output, 2048);
+ Output ("app_ver : '%s' (%d bytes)", output,
+ m_token.GetAppletVersion ().size ());
+ Output ("major_ver : '%x'", m_token.GetMajorVersion ());
+ Output ("minor_ver : '%x'", m_token.GetMinorVersion ());
+ GetBuffer (m_token.GetCUID (), output, 2048);
+ Output ("cuid : '%s' (%d bytes)", output, m_token.GetCUID ().size ());
+ GetBuffer (m_token.GetMSN (), output, 2048);
+ Output ("msn : '%s' (%d bytes)", output, m_token.GetMSN ().size ());
+ GetBuffer (m_token.GetKeyInfo (), output, 2048);
+ Output ("key_info : '%s' (%d bytes)", output,
+ m_token.GetKeyInfo ().size ());
+ GetBuffer (m_token.GetAuthKey (), output, 2048);
+ Output ("auth_key : '%s' (%d bytes)", output,
+ m_token.GetAuthKey ().size ());
+ GetBuffer (m_token.GetMacKey (), output, 2048);
+ Output ("mac_key : '%s' (%d bytes)", output, m_token.GetMacKey ().size ());
+ GetBuffer (m_token.GetKekKey (), output, 2048);
+ Output ("kek_key : '%s' (%d bytes)", output, m_token.GetKekKey ().size ());
+
+ /* print all the public/private keys */
+ if (params->GetValue ("print_cert") != NULL)
+ {
+ for (i = 0; i < m_token.NoOfCertificates (); i++)
+ {
+ CERTCertificate *cert = m_token.GetCertificate (i);
+ Output ("Certificate #%d: '%s'", i, cert->nickname);
+ }
+ }
+
+ if (params->GetValue ("print_private") != NULL)
+ {
+ for (i = 0; i < m_token.NoOfPrivateKeys (); i++)
+ {
+ SECKEYPrivateKey *key = m_token.GetPrivateKey (i);
+#if 0
+ SECKEYPublicKey *pubKey = SECKEY_ConvertToPublicKey (key);
+ Buffer modulus = Buffer (pubKey->u.rsa.modulus.data,
+ pubKey->u.rsa.modulus.len);
+ Buffer exponent = Buffer (pubKey->u.rsa.publicExponent.data,
+ pubKey->u.rsa.publicExponent.len);
+#endif
+ Output ("Private Key #%d: '%s'", i,
+ PK11_GetPrivateKeyNickname (key));
+ }
+ }
+
+ return 1;
+}
+
+int
+RA_Client::OpTokenSet (NameValueSet * params)
+{
+ if (params->GetValue ("cuid") != NULL)
+ {
+ Buffer *CUID = ToBuffer (params->GetValue ("cuid"));
+ m_token.SetCUID (*CUID);
+ if (CUID != NULL)
+ {
+ delete CUID;
+ CUID = NULL;
+ }
+ }
+ if (params->GetValue ("msn") != NULL)
+ {
+ Buffer *MSN = ToBuffer (params->GetValue ("msn"));
+ m_token.SetMSN (*MSN);
+ if (MSN != NULL)
+ {
+ delete MSN;
+ MSN = NULL;
+ }
+ }
+ if (params->GetValue ("app_ver") != NULL)
+ {
+ Buffer *Version = ToBuffer (params->GetValue ("app_ver"));
+ m_token.SetAppletVersion (*Version);
+ if (Version != NULL)
+ {
+ delete Version;
+ Version = NULL;
+ }
+ }
+ if (params->GetValue ("major_ver") != NULL)
+ {
+ m_token.SetMajorVersion (atoi (params->GetValue ("major_ver")));
+ }
+ if (params->GetValue ("minor_ver") != NULL)
+ {
+ m_token.SetMinorVersion (atoi (params->GetValue ("minor_ver")));
+ }
+ if (params->GetValue ("key_info") != NULL)
+ {
+ Buffer *KeyInfo = ToBuffer (params->GetValue ("key_info"));
+ m_token.SetKeyInfo (*KeyInfo);
+ if (KeyInfo != NULL)
+ {
+ delete KeyInfo;
+ KeyInfo = NULL;
+ }
+ }
+ if (params->GetValue ("auth_key") != NULL)
+ {
+ Buffer *Key = ToBuffer (params->GetValue ("auth_key"));
+ m_token.SetAuthKey (*Key);
+ if (Key != NULL)
+ {
+ delete Key;
+ Key = NULL;
+ }
+ }
+ if (params->GetValue ("mac_key") != NULL)
+ {
+ Buffer *Key = ToBuffer (params->GetValue ("mac_key"));
+ m_token.SetMacKey (*Key);
+ if (Key != NULL)
+ {
+ delete Key;
+ Key = NULL;
+ }
+ }
+ if (params->GetValue ("kek_key") != NULL)
+ {
+ Buffer *Key = ToBuffer (params->GetValue ("kek_key"));
+ m_token.SetKekKey (*Key);
+ if (Key != NULL)
+ {
+ delete Key;
+ Key = NULL;
+ }
+ }
+ return 1;
+}
+
+static int
+HandleStatusUpdateRequest (RA_Client * client,
+ RA_Status_Update_Request_Msg * req,
+ RA_Token * token, RA_Conn * conn,
+ NameValueSet * vars, NameValueSet * params)
+{
+ client->Debug ("RA_Client::HandleStatusUpdateRequest",
+ "RA_Client::HandleStatusUpdateRequest");
+ RA_Status_Update_Response_Msg resp =
+ RA_Status_Update_Response_Msg (req->GetStatus ());
+ conn->SendMsg (&resp);
+ return 1;
+}
+
+static int
+HandleExtendedLoginRequest (RA_Client * client,
+ RA_Extended_Login_Request_Msg * req,
+ RA_Token * token, RA_Conn * conn,
+ NameValueSet * vars, NameValueSet * params)
+{
+ client->Debug ("RA_Client::HandleExtendLoginRequest",
+ "RA_Client::HandleExtendedLoginRequest");
+ AuthParams *auths = new AuthParams;
+ auths->SetUID (params->GetValue ("uid"));
+ auths->SetPassword (params->GetValue ("pwd"));
+ if (vars->GetValueAsBool ("test_enable", 0) == 1)
+ {
+ if (vars->GetValueAsBool ("test_el_resp_exclude_uid", 0) == 1)
+ {
+ auths->Remove ("UID");
+ }
+ if (vars->GetValueAsBool ("test_el_resp_exclude_pwd", 0) == 1)
+ {
+ auths->Remove ("PASSWORD");
+ }
+ if (vars->GetValueAsBool ("test_el_resp_include_invalid_param", 0) == 1)
+ {
+ auths->Add ("XXX", "YYY");
+ }
+ }
+ RA_Extended_Login_Response_Msg resp =
+ RA_Extended_Login_Response_Msg (auths);
+ conn->SendMsg (&resp);
+ return 1;
+}
+
+static int
+HandleLoginRequest (RA_Client * client,
+ RA_Login_Request_Msg * req,
+ RA_Token * token, RA_Conn * conn,
+ NameValueSet * vars, NameValueSet * params)
+{
+ client->Debug ("RA_Client::HandleLoginRequest",
+ "RA_Client::HandleLoginRequest");
+ RA_Login_Response_Msg resp =
+ RA_Login_Response_Msg (params->GetValue ("uid"),
+ params->GetValue ("pwd"));
+ conn->SendMsg (&resp);
+ return 1;
+}
+
+static int
+HandleNewPinRequest (RA_Client * client,
+ RA_New_Pin_Request_Msg * req,
+ RA_Token * token, RA_Conn * conn,
+ NameValueSet * vars, NameValueSet * params)
+{
+ client->Debug ("RA_Client::HandleNewPinRequest",
+ "RA_Client::HandleNewPinRequest");
+ int min_len = req->GetMinLen ();
+ int max_len = req->GetMaxLen ();
+ Output ("Min Len: '%d' Max Len: '%d'", min_len, max_len);
+ RA_New_Pin_Response_Msg resp =
+ RA_New_Pin_Response_Msg (params->GetValue ("new_pin"));
+ conn->SendMsg (&resp);
+
+ return 1;
+}
+
+static int
+HandleASQRequest (RA_Client * client,
+ RA_ASQ_Request_Msg * req,
+ RA_Token * token, RA_Conn * conn,
+ NameValueSet * vars, NameValueSet * params)
+{
+ client->Debug ("RA_Client::HandleASQRequest",
+ "RA_Client::HandleASQRequest");
+ Output ("ASQ Question: '%s'", req->GetQuestion ());
+ RA_ASQ_Response_Msg resp =
+ RA_ASQ_Response_Msg (params->GetValue ("answer"));
+ conn->SendMsg (&resp);
+
+ return 1;
+}
+
+static int
+HandleSecureIdRequest (RA_Client * client,
+ RA_SecureId_Request_Msg * req,
+ RA_Token * token, RA_Conn * conn,
+ NameValueSet * vars, NameValueSet * params)
+{
+ client->Debug ("RA_Client::HandleSecureIdRequest",
+ "RA_Client::HandleSecureIdRequest");
+ int pin_required = req->IsPinRequired ();
+ int next_value = req->IsNextValue ();
+ Output ("Pin Required: '%d' Next Value: '%d'", pin_required, next_value);
+ RA_SecureId_Response_Msg resp =
+ RA_SecureId_Response_Msg (params->GetValue ("secureid_value"),
+ params->GetValue ("secureid_pin"));
+ conn->SendMsg (&resp);
+ return 1;
+}
+
+static int
+HandleTokenPDURequest (RA_Client * client,
+ RA_Token_PDU_Request_Msg * req,
+ RA_Token * token, RA_Conn * conn,
+ NameValueSet * vars, NameValueSet * params)
+{
+ client->Debug ("RA_Client::HandleTokenPDURequest",
+ "RA_Client::HandleTokenPDURequest");
+ APDU *apdu = req->GetAPDU ();
+ APDU_Response *apdu_resp = token->Process (apdu, vars, params);
+ if (apdu_resp == NULL)
+ {
+ return 0;
+ }
+ RA_Token_PDU_Response_Msg *resp = new RA_Token_PDU_Response_Msg (apdu_resp);
+ conn->SendMsg (resp);
+
+ if (resp != NULL)
+ {
+ delete resp;
+ resp = NULL;
+ }
+ // if( apdu_resp != NULL ) {
+ // delete apdu_resp;
+ // apdu_resp = NULL;
+ // }
+
+ return 1;
+}
+
+
+typedef struct _ThreadArg
+{
+ PRTime time; /* processing time */
+ int status; /* status result */
+ NameValueSet *params; /* parameters */
+ RA_Client *client; /* client */
+ RA_Token *token; /* token */
+
+ PRLock *donelock; /* lock */
+ int done; /* are we done? */
+} ThreadArg;
+
+#ifdef __cplusplus
+extern "C"
+{
+#endif
+
+ static void ThreadConnUpdate (void *arg)
+ {
+ PRTime start, end;
+ ThreadArg *targ = (ThreadArg *) arg;
+
+ start = PR_Now ();
+ RA_Conn conn (targ->client->m_vars.GetValue ("ra_host"),
+ atoi (targ->client->m_vars.GetValue ("ra_port")),
+ targ->client->m_vars.GetValue ("ra_uri"));
+
+ if (!conn.Connect ())
+ {
+ OutputError ("Cannot connect to %s:%d",
+ targ->client->m_vars.GetValue ("ra_host"),
+ atoi (targ->client->m_vars.GetValue ("ra_port")));
+ targ->status = 0;
+ if (!old_style)
+ {
+ PR_Lock (targ->donelock);
+ targ->done = PR_TRUE;
+ PR_Unlock (targ->donelock);
+ }
+
+ return;
+ }
+
+ NameValueSet *exts = NULL;
+ char *extensions =
+ targ->params->GetValueAsString ((char *) "extensions", NULL);
+ if (extensions != NULL)
+ {
+ exts = NameValueSet::Parse (extensions, "&");
+ }
+
+ RA_Begin_Op_Msg beginOp = RA_Begin_Op_Msg (OP_FORMAT, exts);
+ conn.SendMsg (&beginOp);
+
+ /* handle secure ID (optional) */
+ while (1)
+ {
+ RA_Msg *msg = (RA_Msg *) conn.ReadMsg (targ->token);
+ if (msg == NULL)
+ break;
+ if (msg->GetType () == MSG_LOGIN_REQUEST)
+ {
+ targ->status =
+ HandleLoginRequest (targ->client, (RA_Login_Request_Msg *) msg,
+ targ->token, &conn, &targ->client->m_vars,
+ targ->params);
+ }
+ else if (msg->GetType () == MSG_EXTENDED_LOGIN_REQUEST)
+ {
+ targ->status =
+ HandleExtendedLoginRequest (targ->client,
+ (RA_Extended_Login_Request_Msg *)
+ msg, targ->token, &conn,
+ &targ->client->m_vars,
+ targ->params);
+ }
+ else if (msg->GetType () == MSG_STATUS_UPDATE_REQUEST)
+ {
+ targ->status =
+ HandleStatusUpdateRequest (targ->client,
+ (RA_Status_Update_Request_Msg *) msg,
+ targ->token, &conn,
+ &targ->client->m_vars, targ->params);
+ }
+ else if (msg->GetType () == MSG_SECUREID_REQUEST)
+ {
+ targ->status =
+ HandleSecureIdRequest (targ->client,
+ (RA_SecureId_Request_Msg *) msg,
+ targ->token, &conn,
+ &targ->client->m_vars, targ->params);
+ }
+ else if (msg->GetType () == MSG_ASQ_REQUEST)
+ {
+ targ->status =
+ HandleASQRequest (targ->client, (RA_ASQ_Request_Msg *) msg,
+ targ->token, &conn, &targ->client->m_vars,
+ targ->params);
+ }
+ else if (msg->GetType () == MSG_TOKEN_PDU_REQUEST)
+ {
+ targ->status =
+ HandleTokenPDURequest (targ->client,
+ (RA_Token_PDU_Request_Msg *) msg,
+ targ->token, &conn,
+ &targ->client->m_vars, targ->params);
+ }
+ else if (msg->GetType () == MSG_NEW_PIN_REQUEST)
+ {
+ targ->status =
+ HandleNewPinRequest (targ->client,
+ (RA_New_Pin_Request_Msg *) msg,
+ targ->token, &conn, &targ->client->m_vars,
+ targ->params);
+ }
+ else if (msg->GetType () == MSG_END_OP)
+ {
+ RA_End_Op_Msg *endOp = (RA_End_Op_Msg *) msg;
+ if (endOp->GetResult () == 0)
+ {
+ targ->status = 1; /* error */
+ }
+ else
+ {
+ targ->status = 0;
+ }
+ if (msg != NULL)
+ {
+ delete msg;
+ msg = NULL;
+ }
+ break;
+ }
+ else
+ {
+ /* error */
+ targ->status = 0;
+ }
+ if (msg != NULL)
+ {
+ delete msg;
+ msg = NULL;
+ }
+
+ if (targ->status == 0)
+ break;
+ }
+
+ conn.Close ();
+ end = PR_Now ();
+ targ->time = (end - start) / 1000;
+
+ if (!old_style)
+ {
+ PR_Lock (targ->donelock);
+ targ->done = PR_TRUE;
+ PR_Unlock (targ->donelock);
+ }
+ }
+
+ static void ThreadConnResetPin (void *arg)
+ {
+ PRTime start, end;
+ ThreadArg *targ = (ThreadArg *) arg;
+
+ start = PR_Now ();
+ RA_Conn conn (targ->client->m_vars.GetValue ("ra_host"),
+ atoi (targ->client->m_vars.GetValue ("ra_port")),
+ targ->client->m_vars.GetValue ("ra_uri"));
+
+ if (!conn.Connect ())
+ {
+ OutputError ("Cannot connect to %s:%d",
+ targ->client->m_vars.GetValue ("ra_host"),
+ atoi (targ->client->m_vars.GetValue ("ra_port")));
+ targ->status = 0;
+
+ if (!old_style)
+ {
+ PR_Lock (targ->donelock);
+ targ->done = PR_TRUE;
+ PR_Unlock (targ->donelock);
+ }
+
+ return;
+ }
+
+ NameValueSet *exts = NULL;
+ char *extensions =
+ targ->params->GetValueAsString ((char *) "extensions", NULL);
+ if (extensions != NULL)
+ {
+ exts = NameValueSet::Parse (extensions, "&");
+ }
+
+ RA_Begin_Op_Msg beginOp = RA_Begin_Op_Msg (OP_RESET_PIN, exts);
+ conn.SendMsg (&beginOp);
+
+ /* handle secure ID (optional) */
+ while (1)
+ {
+ RA_Msg *msg = (RA_Msg *) conn.ReadMsg (targ->token);
+ if (msg == NULL)
+ break;
+ if (msg->GetType () == MSG_LOGIN_REQUEST)
+ {
+ targ->status =
+ HandleLoginRequest (targ->client, (RA_Login_Request_Msg *) msg,
+ targ->token, &conn, &targ->client->m_vars,
+ targ->params);
+ }
+ else if (msg->GetType () == MSG_EXTENDED_LOGIN_REQUEST)
+ {
+ targ->status =
+ HandleExtendedLoginRequest (targ->client,
+ (RA_Extended_Login_Request_Msg *)
+ msg, targ->token, &conn,
+ &targ->client->m_vars,
+ targ->params);
+ }
+ else if (msg->GetType () == MSG_STATUS_UPDATE_REQUEST)
+ {
+ targ->status =
+ HandleStatusUpdateRequest (targ->client,
+ (RA_Status_Update_Request_Msg *) msg,
+ targ->token, &conn,
+ &targ->client->m_vars, targ->params);
+ }
+ else if (msg->GetType () == MSG_SECUREID_REQUEST)
+ {
+ targ->status =
+ HandleSecureIdRequest (targ->client,
+ (RA_SecureId_Request_Msg *) msg,
+ targ->token, &conn,
+ &targ->client->m_vars, targ->params);
+ }
+ else if (msg->GetType () == MSG_ASQ_REQUEST)
+ {
+ targ->status =
+ HandleASQRequest (targ->client, (RA_ASQ_Request_Msg *) msg,
+ targ->token, &conn, &targ->client->m_vars,
+ targ->params);
+ }
+ else if (msg->GetType () == MSG_TOKEN_PDU_REQUEST)
+ {
+ targ->status =
+ HandleTokenPDURequest (targ->client,
+ (RA_Token_PDU_Request_Msg *) msg,
+ targ->token, &conn,
+ &targ->client->m_vars, targ->params);
+ }
+ else if (msg->GetType () == MSG_NEW_PIN_REQUEST)
+ {
+ targ->status =
+ HandleNewPinRequest (targ->client,
+ (RA_New_Pin_Request_Msg *) msg,
+ targ->token, &conn, &targ->client->m_vars,
+ targ->params);
+ }
+ else if (msg->GetType () == MSG_END_OP)
+ {
+ RA_End_Op_Msg *endOp = (RA_End_Op_Msg *) msg;
+ if (endOp->GetResult () == 0)
+ {
+ targ->status = 1; /* error */
+ }
+ else
+ {
+ targ->status = 0;
+ }
+ if (msg != NULL)
+ {
+ delete msg;
+ msg = NULL;
+ }
+ break;
+ }
+ else
+ {
+ /* error */
+ targ->status = 0;
+ }
+ if (msg != NULL)
+ {
+ delete msg;
+ msg = NULL;
+ }
+
+ if (targ->status == 0)
+ break;
+ }
+
+ conn.Close ();
+ end = PR_Now ();
+ targ->time = (end - start) / 1000;
+
+ if (!old_style)
+ {
+ PR_Lock (targ->donelock);
+ targ->done = PR_TRUE;
+ PR_Unlock (targ->donelock);
+ }
+ }
+
+#ifdef __cplusplus
+}
+#endif
+
+int
+RA_Client::OpConnUpdate (NameValueSet * params)
+{
+ int num_threads = params->GetValueAsInt ((char *) "num_threads", 1);
+ int i;
+ int status = 0;
+ PRThread **threads;
+ ThreadArg *arg;
+
+ threads = (PRThread **) malloc (sizeof (PRThread *) * num_threads);
+ if (threads == NULL)
+ {
+ return 0;
+ }
+ arg = (ThreadArg *) malloc (sizeof (ThreadArg) * num_threads);
+ if (arg == NULL)
+ {
+ return 0;
+ }
+
+ /* start threads */
+ for (i = 0; i < num_threads; i++)
+ {
+ arg[i].time = 0;
+ arg[i].status = 0;
+ arg[i].client = this;
+ if (i == 0)
+ {
+ arg[i].token = &this->m_token;
+ }
+ else
+ {
+ arg[i].token = this->m_token.Clone ();
+ }
+ arg[i].params = params;
+ threads[i] = PR_CreateThread (PR_USER_THREAD, ThreadConnUpdate, &arg[i], PR_PRIORITY_NORMAL, /* Priority */
+ PR_GLOBAL_THREAD, /* Scope */
+ PR_JOINABLE_THREAD, /* State */
+ 0 /* Stack Size */
+ );
+ }
+
+ /* join threads */
+ for (i = 0; i < num_threads; i++)
+ {
+ PR_JoinThread (threads[i]);
+ }
+
+ for (i = 0; i < num_threads; i++)
+ {
+ Output ("Thread (%d) status='%d' time='%d msec'", i,
+ arg[i].status, arg[i].time);
+ }
+
+ status = arg[0].status;
+
+ return status;
+}
+
+int
+RA_Client::OpConnResetPin (NameValueSet * params)
+{
+ int num_threads = params->GetValueAsInt ((char *) "num_threads", 1);
+ int i;
+ int status = 0;
+ PRThread **threads;
+ ThreadArg *arg;
+
+ threads = (PRThread **) malloc (sizeof (PRThread *) * num_threads);
+ if (threads == NULL)
+ {
+ return 0;
+ }
+ arg = (ThreadArg *) malloc (sizeof (ThreadArg) * num_threads);
+ if (arg == NULL)
+ {
+ return 0;
+ }
+
+ /* start threads */
+ for (i = 0; i < num_threads; i++)
+ {
+ arg[i].time = 0;
+ arg[i].status = 0;
+ arg[i].client = this;
+ if (i == 0)
+ {
+ arg[i].token = &this->m_token;
+ }
+ else
+ {
+ arg[i].token = this->m_token.Clone ();
+ }
+ arg[i].params = params;
+ threads[i] = PR_CreateThread (PR_USER_THREAD, ThreadConnResetPin, &arg[i], PR_PRIORITY_NORMAL, /* Priority */
+ PR_GLOBAL_THREAD, /* Scope */
+ PR_JOINABLE_THREAD, /* State */
+ 0 /* Stack Size */
+ );
+ }
+
+ /* join threads */
+ for (i = 0; i < num_threads; i++)
+ {
+ PR_JoinThread (threads[i]);
+ }
+
+ for (i = 0; i < num_threads; i++)
+ {
+ Output ("Thread (%d) status='%d' time='%d msec'", i,
+ arg[i].status, arg[i].time);
+ }
+
+ status = arg[0].status;
+
+ return status;
+}
+
+#ifdef __cplusplus
+extern "C"
+{
+#endif
+
+ static void ThreadConnEnroll (void *arg)
+ {
+ PRTime start, end;
+ ThreadArg *targ = (ThreadArg *) arg;
+
+ start = PR_Now ();
+ RA_Conn conn (targ->client->m_vars.GetValue ("ra_host"),
+ atoi (targ->client->m_vars.GetValue ("ra_port")),
+ targ->client->m_vars.GetValue ("ra_uri"));
+
+ if (!conn.Connect ())
+ {
+ OutputError ("Cannot connect to %s:%d",
+ targ->client->m_vars.GetValue ("ra_host"),
+ atoi (targ->client->m_vars.GetValue ("ra_port")));
+ targ->status = 0;
+
+ if (!old_style)
+ {
+ PR_Lock (targ->donelock);
+ targ->done = PR_TRUE;
+ PR_Unlock (targ->donelock);
+ }
+
+ return;
+ }
+
+ NameValueSet *exts = NULL;
+ char *extensions =
+ targ->params->GetValueAsString ((char *) "extensions", NULL);
+ if (extensions != NULL)
+ {
+ exts = NameValueSet::Parse (extensions, "&");
+ }
+
+ RA_Begin_Op_Msg beginOp = RA_Begin_Op_Msg (OP_ENROLL, exts);
+ conn.SendMsg (&beginOp);
+
+ /* handle secure ID (optional) */
+ while (1)
+ {
+ RA_Msg *msg = (RA_Msg *) conn.ReadMsg (targ->token);
+ if (msg == NULL)
+ break;
+ if (msg->GetType () == MSG_LOGIN_REQUEST)
+ {
+ targ->status = HandleLoginRequest (targ->client,
+ (RA_Login_Request_Msg *) msg,
+ targ->token, &conn,
+ &targ->client->m_vars,
+ targ->params);
+ }
+ else if (msg->GetType () == MSG_EXTENDED_LOGIN_REQUEST)
+ {
+ targ->status = HandleExtendedLoginRequest (targ->client,
+ (RA_Extended_Login_Request_Msg
+ *) msg, targ->token,
+ &conn,
+ &targ->client->m_vars,
+ targ->params);
+ }
+ else if (msg->GetType () == MSG_STATUS_UPDATE_REQUEST)
+ {
+ targ->status =
+ HandleStatusUpdateRequest (targ->client,
+ (RA_Status_Update_Request_Msg *) msg,
+ targ->token, &conn,
+ &targ->client->m_vars, targ->params);
+ }
+ else if (msg->GetType () == MSG_SECUREID_REQUEST)
+ {
+ targ->status = HandleSecureIdRequest (targ->client,
+ (RA_SecureId_Request_Msg *)
+ msg, targ->token, &conn,
+ &targ->client->m_vars,
+ targ->params);
+ }
+ else if (msg->GetType () == MSG_ASQ_REQUEST)
+ {
+ targ->status = HandleASQRequest (targ->client,
+ (RA_ASQ_Request_Msg *) msg,
+ targ->token, &conn,
+ &targ->client->m_vars,
+ targ->params);
+ }
+ else if (msg->GetType () == MSG_TOKEN_PDU_REQUEST)
+ {
+ targ->status = HandleTokenPDURequest (targ->client,
+ (RA_Token_PDU_Request_Msg *)
+ msg, targ->token, &conn,
+ &targ->client->m_vars,
+ targ->params);
+ targ->status = 1;
+ }
+ else if (msg->GetType () == MSG_NEW_PIN_REQUEST)
+ {
+ targ->status = HandleNewPinRequest (targ->client,
+ (RA_New_Pin_Request_Msg *)
+ msg, targ->token, &conn,
+ &targ->client->m_vars,
+ targ->params);
+ }
+ else if (msg->GetType () == MSG_END_OP)
+ {
+ RA_End_Op_Msg *endOp = (RA_End_Op_Msg *) msg;
+ if (endOp->GetResult () == 0)
+ {
+ targ->status = 1; /* error */
+ }
+ else
+ {
+ targ->status = 0;
+ }
+ if (msg != NULL)
+ {
+ delete msg;
+ msg = NULL;
+ }
+ break;
+ }
+ else
+ {
+ /* error */
+ targ->status = 0; /* error */
+ }
+ if (msg != NULL)
+ {
+ delete msg;
+ msg = NULL;
+ }
+ }
+
+ conn.Close ();
+ end = PR_Now ();
+ targ->time = (end - start) / 1000;
+
+ if (!old_style)
+ {
+ PR_Lock (targ->donelock);
+ targ->done = PR_TRUE;
+ PR_Unlock (targ->donelock);
+ }
+ }
+
+#ifdef __cplusplus
+}
+#endif
+
+int
+RA_Client::OpConnEnroll (NameValueSet * params)
+{
+ int num_threads = params->GetValueAsInt ((char *) "num_threads", 1);
+ int i;
+ int status = 0;
+ PRThread **threads;
+ ThreadArg *arg;
+
+ threads = (PRThread **) malloc (sizeof (PRThread *) * num_threads);
+ if (threads == NULL)
+ {
+ return 0; /* error */
+ }
+ arg = (ThreadArg *) malloc (sizeof (ThreadArg) * num_threads);
+ if (arg == NULL)
+ {
+ return 0;
+ }
+
+ /* start threads */
+ for (i = 0; i < num_threads; i++)
+ {
+ arg[i].time = 0;
+ arg[i].status = 0;
+ arg[i].client = this;
+ if (i == 0)
+ {
+ arg[i].token = &this->m_token;
+ }
+ else
+ {
+ arg[i].token = this->m_token.Clone ();
+ }
+ arg[i].params = params;
+ threads[i] = PR_CreateThread (PR_USER_THREAD, ThreadConnEnroll, &arg[i], PR_PRIORITY_NORMAL, /* Priority */
+ PR_GLOBAL_THREAD, /* Scope */
+ PR_JOINABLE_THREAD, /* State */
+ 0 /* Stack Size */
+ );
+ }
+
+ /* join threads */
+ for (i = 0; i < num_threads; i++)
+ {
+ PR_JoinThread (threads[i]);
+ }
+
+ status = 1;
+
+ for (i = 0; i < num_threads; i++)
+ {
+ Output ("Thread (%d) status='%d' time='%d msec'", i,
+ arg[i].status, arg[i].time);
+ if (arg[i].status != 1)
+ {
+ // if any thread fails, this operation
+ // is considered as failure
+ status = arg[i].status;
+ }
+ }
+
+
+ return status;
+}
+
+
+/*
+ * no more than num_threads will be running concurrently
+ * no more than a total of max_ops requests will be started
+ */
+int
+StartThreads (int num_threads, ThreadArg * arg, PRThread ** threads,
+ int max_ops, RA_Client * _this, NameValueSet * params,
+ RequestType op_type)
+{
+ int i;
+ int started = 0;
+
+ if (arg == NULL)
+ {
+ goto loser;
+ }
+
+ /* start threads */
+ for (i = 0; i < num_threads; i++)
+ {
+ if (started == max_ops)
+ {
+ break;
+ }
+ if (threads[i] == NULL)
+ {
+ arg[i].time = 0;
+ arg[i].status = 0;
+ arg[i].client = _this;
+ arg[i].done = PR_FALSE;
+
+ if (i == 0)
+ {
+ arg[i].token = &_this->m_token;
+ }
+ else
+ {
+
+ if (arg[i].token != NULL)
+ {
+ if (arg[i].token->m_pin)
+ {
+ PL_strfree (arg[i].token->m_pin);
+ arg[i].token->m_pin = NULL;
+ }
+ if (arg[i].token->m_session_key != NULL)
+ {
+ PORT_Free (arg[i].token->m_session_key);
+ arg[i].token->m_session_key = NULL;
+ }
+ if (arg[i].token->m_enc_session_key != NULL)
+ {
+ PORT_Free (arg[i].token->m_enc_session_key);
+ arg[i].token->m_enc_session_key = NULL;
+ }
+ if (arg[i].token->m_object != NULL)
+ {
+ delete (arg[i].token->m_object);
+ arg[i].token->m_object = NULL;
+ }
+
+ delete (arg[i].token);
+ arg[i].token = NULL;
+
+ }
+
+ arg[i].token = _this->m_token.Clone ();
+ }
+ arg[i].params = params;
+ Output ("WWWWWWWWW StartThreads -- thread (%d) begins", i);
+ if (op_type == OP_CLIENT_ENROLL)
+ {
+ threads[i] = PR_CreateThread (PR_USER_THREAD, ThreadConnEnroll, &arg[i], PR_PRIORITY_NORMAL, /* Priority */
+ PR_GLOBAL_THREAD, /* Scope */
+ PR_JOINABLE_THREAD, /* State */
+ 0 /* Stack Size */
+ );
+ }
+ else if (op_type == OP_CLIENT_FORMAT)
+ {
+ threads[i] = PR_CreateThread (PR_USER_THREAD, ThreadConnUpdate, &arg[i], PR_PRIORITY_NORMAL, /* Priority */
+ PR_GLOBAL_THREAD, /* Scope */
+ PR_JOINABLE_THREAD, /* State */
+ 0 /* Stack Size */
+ );
+ }
+ else
+ { // OP_CLIENT_RESET_PIN
+ threads[i] = PR_CreateThread (PR_USER_THREAD, ThreadConnResetPin, &arg[i], PR_PRIORITY_NORMAL, /* Priority */
+ PR_GLOBAL_THREAD, /* Scope */
+ PR_JOINABLE_THREAD, /* State */
+ 0 /* Stack Size */
+ );
+ }
+
+ started++;
+ }
+ else
+ {
+ Output ("thread[%d] is not NULL", i);
+ }
+ }
+
+loser:
+ Output ("StartThreads -- %d threads started", started);
+ return started;
+}
+
+/*
+ * no more than num_threads will be running concurrently
+ * no more than a total of max_ops requests will be started
+ */
+int
+RA_Client::OpConnStart (NameValueSet * params, RequestType op_type)
+{
+ // number of concurrent threads
+ int num_threads = params->GetValueAsInt ((char *) "num_threads", 1);
+ // number of total enrollments
+ int max_ops = params->GetValueAsInt ((char *) "max_ops", num_threads);
+ int count = 0;
+ int i;
+ int status = 1;
+ int started = 0;
+ PRThread **threads;
+ ThreadArg *arg;
+
+ threads = (PRThread **) malloc (sizeof (PRThread *) * num_threads);
+ if (threads == NULL)
+ {
+ return 0; /* error */
+ }
+ arg = (ThreadArg *) malloc (sizeof (ThreadArg) * num_threads);
+ if (arg == NULL)
+ {
+ return 0;
+ }
+
+ for (i = 0; i < num_threads; i++)
+ {
+ arg[i].donelock = PR_NewLock ();
+ arg[i].token = NULL;
+ threads[i] = NULL;
+ }
+
+ count = 0;
+ PRBool hasFreeThread = PR_TRUE;
+ while (count < max_ops)
+ {
+ // fully populate the thread pool
+
+ if (hasFreeThread)
+ {
+ started =
+ StartThreads (num_threads, arg, threads, max_ops - count, this,
+ params, op_type);
+ count += started;
+ Output ("OpConnStart: # requests started =%d", count);
+ hasFreeThread = PR_FALSE;
+ }
+
+ // PR_Sleep(PR_MillisecondsToInterval(500));
+ PR_Sleep (PR_SecondsToInterval (1));
+ Output ("OpConnStart: checking for free threads...");
+ // check if any threads are done
+ for (i = 0; i < num_threads; i++)
+ {
+ if (threads[i] != NULL)
+ {
+ PR_Lock (arg[i].donelock);
+ int arg_done = arg[i].done;
+ PR_Unlock (arg[i].donelock);
+ if (arg_done)
+ {
+ PR_JoinThread (threads[i]);
+ Output ("Thread (%d) status='%d' time='%d msec'", i,
+ arg[i].status, arg[i].time);
+
+ if (arg[i].status != 1)
+ {
+ // if any thread fails, this operation
+ // is considered as failure
+ status = arg[i].status;
+ }
+ threads[i] = NULL;
+
+ hasFreeThread = PR_TRUE;
+
+ }
+ }
+ }
+ Output ("OpConnStart: done checking for free threads...");
+ } // while
+
+ Output ("OpConnStart: TOTAL REQUESTS: %d", count);
+
+ for (i = 0; i < num_threads; i++)
+ {
+ if (threads[i] != NULL)
+ {
+ PR_JoinThread (threads[i]);
+ }
+ if (arg[i].donelock != NULL)
+ {
+ PR_DestroyLock (arg[i].donelock);
+ }
+ }
+
+ return status;
+
+}
+
+int
+RA_Client::OpVarSet (NameValueSet * params)
+{
+ m_vars.Add (params->GetValue ("name"), params->GetValue ("value"));
+ Output ("%s: '%s'", params->GetValue ("name"),
+ m_vars.GetValue (params->GetValue ("name")));
+ return 1;
+}
+
+int
+RA_Client::OpVarDebug (NameValueSet * params)
+{
+ if (m_fd_debug != NULL)
+ {
+ PR_Close (m_fd_debug);
+ m_fd_debug = NULL;
+ }
+ m_fd_debug = PR_Open (params->GetValue ("filename"),
+ PR_RDWR | PR_CREATE_FILE | PR_APPEND, 400 | 200);
+ return 1;
+}
+
+int
+RA_Client::OpVarGet (NameValueSet * params)
+{
+ char *value = m_vars.GetValue (params->GetValue ("name"));
+ Output ("%s: '%s'", params->GetValue ("name"), value);
+
+ return 1;
+}
+
+int
+RA_Client::OpVarList (NameValueSet * params)
+{
+ int i;
+ char *name;
+
+ for (i = 0; i < m_vars.Size (); i++)
+ {
+ name = m_vars.GetNameAt (i);
+ Output ("%s: '%s'", name, m_vars.GetValue (name));
+ }
+ return 1;
+}
+
+/**
+ * Invoke operation.
+ */
+void
+RA_Client::InvokeOperation (char *op, NameValueSet * params)
+{
+ PRTime start, end;
+ int status = 0;
+
+ start = PR_Now ();
+ Debug ("RA_Client::InvokeOperation", "op='%s'", op);
+ int max_ops = params->GetValueAsInt ((char *) "max_ops");
+ if (max_ops != 0)
+ old_style = PR_FALSE;
+
+ if (strcmp (op, "help") == 0)
+ {
+ status = OpHelp (params);
+ }
+ else if (strcmp (op, "ra_format") == 0)
+ {
+ if (old_style)
+ status = OpConnUpdate (params);
+ else
+ status = OpConnStart (params, OP_CLIENT_FORMAT);
+ }
+ else if (strcmp (op, "ra_reset_pin") == 0)
+ {
+ if (old_style)
+ status = OpConnResetPin (params);
+ else
+ status = OpConnStart (params, OP_CLIENT_RESET_PIN);
+ }
+ else if (strcmp (op, "ra_enroll") == 0)
+ {
+ if (old_style)
+ status = OpConnEnroll (params);
+ else
+ status = OpConnStart (params, OP_CLIENT_ENROLL);
+ }
+ else if (strcmp (op, "token_status") == 0)
+ {
+ status = OpTokenStatus (params);
+ }
+ else if (strcmp (op, "token_set") == 0)
+ {
+ status = OpTokenSet (params);
+ }
+ else if (strcmp (op, "debug") == 0)
+ {
+ status = OpVarDebug (params);
+ }
+ else if (strcmp (op, "var_set") == 0)
+ {
+ status = OpVarSet (params);
+ }
+ else if (strcmp (op, "var_get") == 0)
+ {
+ status = OpVarGet (params);
+ }
+ else if (strcmp (op, "var_list") == 0)
+ {
+ status = OpVarList (params);
+ }
+ end = PR_Now ();
+
+ if (status)
+ {
+ OutputSuccess ("Operation '%s' Success (%d msec)", op,
+ (end - start) / 1000);
+ }
+ else
+ {
+ OutputError ("Operation '%s' Failure (%d msec)", op,
+ (end - start) / 1000);
+ }
+}
+
+/**
+ * Execute RA client.
+ */
+void
+RA_Client::Execute ()
+{
+ char line[1024];
+ int rc;
+ char *op;
+ int done = 0;
+ char *lasts = NULL;
+
+ /* start main loop */
+ PrintHeader ();
+ while (!done)
+ {
+ PrintPrompt ();
+ rc = ReadLine (line, 1024);
+ printf ("%s\n", line);
+ if (rc <= 0)
+ {
+ break; /* exit if no more line */
+ }
+ if (line[0] == '#')
+ {
+ continue; /* ignore comment line */
+ }
+ /* format: 'op=cmd <parameters>' */
+ NameValueSet *params = NameValueSet::Parse (line, " ");
+ if (params == NULL)
+ {
+ continue;
+ }
+ op = params->GetValue ("op");
+ if (op == NULL)
+ {
+ /* user did not type op= */
+ op = PL_strtok_r (line, " ", &lasts);
+ if (op == NULL)
+ continue;
+ }
+ if (strcmp (op, "exit") == 0)
+ {
+ done = 1;
+ }
+ else
+ {
+ InvokeOperation (op, params);
+ }
+ if (params != NULL)
+ {
+ delete params;
+ params = NULL;
+ }
+ }
+} /* Execute */
+
+char *
+ownPasswd (PK11SlotInfo * slot, PRBool retry, void *arg)
+{
+ return PL_strdup ("password");
+}
+
+/**
+ * User certutil -d . -N to create a database.
+ * The database should have 'password' as the password.
+ */
+int
+main (int argc, char *argv[])
+{
+ char buffer[513];
+ SECStatus rv;
+ PK11SlotInfo *slot = NULL;
+ PRUint32 flags = 0;
+ // char *newpw = NULL;
+
+ /* Initialize NSPR & NSS */
+ PR_Init (PR_SYSTEM_THREAD, PR_PRIORITY_NORMAL, 1);
+ PK11_SetPasswordFunc (ownPasswd);
+ rv = NSS_Initialize (".", "", "", "", flags);
+ if (rv != SECSuccess)
+ {
+ PR_GetErrorText (buffer);
+ fprintf (stderr, "unable to initialize NSS library (%d - '%s')\n",
+ PR_GetError (), buffer);
+ exit (0);
+ }
+ slot = PK11_GetInternalKeySlot ();
+ if (PK11_NeedUserInit (slot))
+ {
+ rv = PK11_InitPin (slot, (char *) NULL, (char *) "password");
+ if (rv != SECSuccess)
+ {
+ PR_GetErrorText (buffer);
+ fprintf (stderr, "unable to set new PIN (%d - '%s')\n",
+ PR_GetError (), buffer);
+ exit (0);
+ }
+
+ }
+ if (PK11_NeedLogin (slot))
+ {
+ rv = PK11_Authenticate (slot, PR_TRUE, NULL);
+ if (rv != SECSuccess)
+ {
+ PR_GetErrorText (buffer);
+ fprintf (stderr, "unable to authenticate (%d - '%s')\n",
+ PR_GetError (), buffer);
+ exit (0);
+ }
+ }
+
+ /* Start RA Client */
+ RA_Client client;
+ client.Execute ();
+
+ /* Shutdown NSS and NSPR */
+ NSS_Shutdown ();
+ PR_Cleanup ();
+
+ return 1;
+}
diff --git a/base/tps/tools/raclient/RA_Client.h b/base/tps/tools/raclient/RA_Client.h
new file mode 100644
index 000000000..6ab2ecf97
--- /dev/null
+++ b/base/tps/tools/raclient/RA_Client.h
@@ -0,0 +1,78 @@
+/* --- 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 RA_CLIENT_H
+#define RA_CLIENT_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 "prthread.h"
+#include "main/NameValueSet.h"
+#include "RA_Conn.h"
+#include "RA_Token.h"
+
+enum RequestType {
+ OP_CLIENT_ENROLL = 0,
+ OP_CLIENT_FORMAT = 1,
+ OP_CLIENT_RESET_PIN = 2
+};
+
+class RA_Client
+{
+ public:
+ RA_Client();
+ ~RA_Client();
+ public:
+ int OpHelp(NameValueSet *set);
+ int OpConnStart(NameValueSet *set, RequestType);
+ int OpConnResetPin(NameValueSet *set);
+ int OpConnEnroll(NameValueSet *set);
+ int OpConnUpdate(NameValueSet *set);
+ int OpTokenStatus(NameValueSet *set);
+ int OpTokenSet(NameValueSet *set);
+ int OpVarList(NameValueSet *set);
+ int OpVarSet(NameValueSet *set);
+ int OpVarDebug(NameValueSet *set);
+ int OpVarGet(NameValueSet *set);
+ int OpExit(NameValueSet *set);
+ public:
+ void Debug(const char *func_name, const char *fmt, ...);
+ void Execute();
+ void InvokeOperation(char *op, NameValueSet *set);
+ public:
+ RA_Token m_token;
+ NameValueSet m_vars;
+};
+
+#endif /* RA_CLIENT_H */
diff --git a/base/tps/tools/raclient/RA_Conn.cpp b/base/tps/tools/raclient/RA_Conn.cpp
new file mode 100644
index 000000000..17a3ed34f
--- /dev/null
+++ b/base/tps/tools/raclient/RA_Conn.cpp
@@ -0,0 +1,1037 @@
+// --- 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 <string.h>
+#include "prnetdb.h"
+#include "prerror.h"
+#include "prio.h"
+#include "plstr.h"
+#include "main/NameValueSet.h"
+#include "main/Util.h"
+#include "RA_Conn.h"
+#include "apdu/APDU_Response.h"
+#include "apdu/List_Objects_APDU.h"
+#include "apdu/Create_Object_APDU.h"
+#include "apdu/Generate_Key_APDU.h"
+#include "apdu/External_Authenticate_APDU.h"
+#include "apdu/Initialize_Update_APDU.h"
+#include "apdu/Lifecycle_APDU.h"
+#include "apdu/Set_Pin_APDU.h"
+#include "apdu/Get_Status_APDU.h"
+#include "apdu/Get_Data_APDU.h"
+#include "apdu/Format_Muscle_Applet_APDU.h"
+#include "apdu/Load_File_APDU.h"
+#include "apdu/Get_IssuerInfo_APDU.h"
+#include "apdu/Set_IssuerInfo_APDU.h"
+#include "apdu/Install_Applet_APDU.h"
+#include "apdu/Install_Load_APDU.h"
+#include "apdu/Import_Key_APDU.h"
+#include "apdu/Import_Key_Enc_APDU.h"
+#include "apdu/Install_Load_APDU.h"
+#include "apdu/Create_Pin_APDU.h"
+#include "apdu/Read_Buffer_APDU.h"
+#include "apdu/List_Pins_APDU.h"
+#include "apdu/Write_Object_APDU.h"
+#include "apdu/Delete_File_APDU.h"
+#include "apdu/Unblock_Pin_APDU.h"
+#include "apdu/Select_APDU.h"
+#include "apdu/Get_Version_APDU.h"
+#include "apdu/Put_Key_APDU.h"
+#include "msg/RA_Begin_Op_Msg.h"
+#include "msg/RA_End_Op_Msg.h"
+#include "msg/RA_Extended_Login_Request_Msg.h"
+#include "msg/RA_Login_Request_Msg.h"
+#include "msg/RA_SecureId_Request_Msg.h"
+#include "msg/RA_ASQ_Request_Msg.h"
+#include "msg/RA_New_Pin_Request_Msg.h"
+#include "msg/RA_Status_Update_Request_Msg.h"
+#include "msg/RA_Status_Update_Response_Msg.h"
+#include "msg/RA_Token_PDU_Request_Msg.h"
+#include "msg/RA_Login_Response_Msg.h"
+#include "msg/RA_Extended_Login_Response_Msg.h"
+#include "msg/RA_SecureId_Response_Msg.h"
+#include "msg/RA_ASQ_Response_Msg.h"
+#include "msg/RA_New_Pin_Response_Msg.h"
+#include "msg/RA_Token_PDU_Response_Msg.h"
+#include "engine/RA.h"
+
+/**
+ * http parameters used in the protocol
+ */
+#define PARAM_MSG_TYPE "msg_type"
+#define PARAM_OPERATION "operation"
+#define PARAM_EXTENSIONS "extensions"
+#define PARAM_INVALID_PW "invalid_pw"
+#define PARAM_BLOCKED "blocked"
+#define PARAM_SCREEN_NAME "screen_name"
+#define PARAM_PASSWORD "password"
+#define PARAM_PIN_REQUIRED "pin_required"
+#define PARAM_NEXT_VALUE "next_value"
+#define PARAM_VALUE "value"
+#define PARAM_PIN "pin"
+#define PARAM_QUESTION "question"
+#define PARAM_ANSWER "answer"
+#define PARAM_MINIMUM_LENGTH "minimum_length"
+#define PARAM_MAXIMUM_LENGTH "maximum_length"
+#define PARAM_NEW_PIN "new_pin"
+#define PARAM_PDU_SIZE "pdu_size"
+#define PARAM_PDU_DATA "pdu_data"
+#define PARAM_RESULT "result"
+#define PARAM_MESSAGE "message"
+#define PARAM_CURRENT_STATE "current_state"
+#define PARAM_NEXT_TASK_NAME "next_task_name"
+
+#define MAX_RA_MSG_SIZE 4096
+
+/**
+ * Constructs a RA connection.
+ */
+RA_Conn::RA_Conn (char *host, int port, char *uri)
+{
+ if (host == NULL)
+ m_host = NULL;
+ else
+ m_host = PL_strdup (host);
+ if (uri == NULL)
+ m_uri = NULL;
+ else
+ m_uri = PL_strdup (uri);
+ m_port = port;
+ m_read_header = 0;
+ m_fd = NULL;
+}
+
+/**
+ * Destructs a RA connection.
+ */
+RA_Conn::~RA_Conn ()
+{
+ if (m_host != NULL)
+ {
+ PL_strfree (m_host);
+ m_host = NULL;
+ }
+ if (m_uri != NULL)
+ {
+ PL_strfree (m_uri);
+ m_uri = NULL;
+ }
+ if (m_fd != NULL)
+ {
+ PR_Close (m_fd);
+ m_fd = NULL;
+ }
+}
+
+static void
+Output (const char *fmt, ...)
+{
+ va_list ap;
+ va_start (ap, fmt);
+ printf ("Output> ");
+ vprintf (fmt, ap);
+ printf ("\n");
+ va_end (ap);
+}
+
+
+#ifdef VERBOSE
+static 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 =====");
+}
+#endif
+
+
+static PRUint32
+GetIPAddress (const char *hostName)
+{
+ const unsigned char *p;
+ char buf[PR_NETDB_BUF_SIZE];
+ PRStatus prStatus;
+ PRUint32 rv = 0;
+ PRHostEnt prHostEnt;
+
+ prStatus = PR_GetHostByName (hostName, buf, sizeof buf, &prHostEnt);
+ if (prStatus != PR_SUCCESS)
+ return rv;
+
+#undef h_addr
+#define h_addr h_addr_list[0] /* address, for backward compatibility */
+
+ p = (const unsigned char *) (prHostEnt.h_addr); /* in Network Byte order */
+ rv = (p[0] << 24) | (p[1] << 16) | (p[2] << 8) | p[3];
+ return rv;
+}
+
+/**
+ * Connects to the RA.
+ */
+int
+RA_Conn::Connect ()
+{
+ PRStatus rc;
+ char header[4096];
+
+ sprintf (header, "POST %s HTTP/1.1\r\n"
+ "Host: %s:%d\r\n"
+ "Transfer-Encoding: chunked\r\n" "\r\n", m_uri, m_host, m_port);
+
+ m_fd = PR_NewTCPSocket ();
+
+ /*
+ * Rifle through the values for the host
+ */
+
+ PRAddrInfo *ai;
+ void *iter;
+ PRNetAddr addr;
+ int family = PR_AF_INET;
+
+ ai = PR_GetAddrInfoByName(m_host, PR_AF_UNSPEC, PR_AI_ADDRCONFIG);
+ if (ai) {
+ iter = NULL;
+ while ((iter = PR_EnumerateAddrInfo(iter, ai, 0, &addr)) != NULL) {
+ family = PR_NetAddrFamily(&addr);
+ break;
+ }
+ PR_FreeAddrInfo(ai);
+ }
+
+ PR_SetNetAddr( PR_IpAddrNull, family, m_port, &addr );
+
+ m_fd = PR_OpenTCPSocket( family );
+ if( !m_fd ) {
+ return 0;
+ }
+
+ rc = PR_Connect (m_fd, &addr, PR_INTERVAL_NO_TIMEOUT /* timeout */ );
+ if (rc != PR_SUCCESS)
+ return 0;
+
+ /* Send header */
+
+ PR_Send (m_fd, header, strlen (header), 0, 1000000);
+
+ return 1;
+}
+
+static void
+CreateChunkEntity (char *msg, char *chunk, int chunk_len)
+{
+ int chunk_size;
+ int len;
+ Output ("***** msg = %s *****", msg);
+ len = strlen (msg);
+ sprintf (chunk, "s=%d&%s", len, msg);
+ chunk_size = strlen (chunk);
+ sprintf (chunk, "%x\r\ns=%d&%s\r\n", chunk_size, len, msg);
+}
+
+/**
+ * Sends message to the RA.
+ */
+int
+RA_Conn::SendMsg (RA_Msg * msg)
+{
+ char msgbuf[MAX_RA_MSG_SIZE];
+ char chunk[MAX_RA_MSG_SIZE];
+
+ /* send chunk size */
+ if (msg->GetType () == MSG_BEGIN_OP)
+ {
+ RA_Begin_Op_Msg *begin = (RA_Begin_Op_Msg *) msg;
+ sprintf (msgbuf, "%s=%d&%s=%d", PARAM_MSG_TYPE, MSG_BEGIN_OP,
+ PARAM_OPERATION, begin->GetOpType ());
+ NameValueSet *exts = begin->GetExtensions ();
+ if (exts != NULL)
+ {
+ sprintf (msgbuf, "%s&%s=", msgbuf, PARAM_EXTENSIONS);
+ for (int i = 0; i < exts->Size (); i++)
+ {
+ if (i != 0)
+ {
+ sprintf (msgbuf, "%s%%26", msgbuf);
+ }
+ char *name = exts->GetNameAt (i);
+ sprintf (msgbuf, "%s%s=%s",
+ msgbuf, name, exts->GetValueAsString (name));
+ }
+ }
+ CreateChunkEntity (msgbuf, chunk, 4096);
+ }
+ else if (msg->GetType () == MSG_LOGIN_RESPONSE)
+ {
+ RA_Login_Response_Msg *resp = (RA_Login_Response_Msg *) msg;
+ sprintf (msgbuf, "%s=%d&%s=%s&%s=%s",
+ PARAM_MSG_TYPE, MSG_LOGIN_RESPONSE,
+ PARAM_SCREEN_NAME, resp->GetUID (),
+ PARAM_PASSWORD, resp->GetPassword ());
+ CreateChunkEntity (msgbuf, chunk, 4096);
+ }
+ else if (msg->GetType () == MSG_EXTENDED_LOGIN_RESPONSE)
+ {
+ RA_Extended_Login_Response_Msg *resp =
+ (RA_Extended_Login_Response_Msg *) msg;
+ AuthParams *auth = resp->GetAuthParams ();
+ sprintf (msgbuf, "%s=%d&%s=%s&%s=%s",
+ PARAM_MSG_TYPE, MSG_EXTENDED_LOGIN_RESPONSE,
+ PARAM_SCREEN_NAME, auth->GetUID (),
+ PARAM_PASSWORD, auth->GetPassword ());
+ CreateChunkEntity (msgbuf, chunk, 4096);
+ }
+ else if (msg->GetType () == MSG_STATUS_UPDATE_RESPONSE)
+ {
+ RA_Status_Update_Response_Msg *resp =
+ (RA_Status_Update_Response_Msg *) msg;
+ int status = resp->GetStatus ();
+ sprintf (msgbuf, "%s=%d&%s=%d",
+ PARAM_MSG_TYPE, MSG_STATUS_UPDATE_RESPONSE,
+ PARAM_CURRENT_STATE, status);
+ CreateChunkEntity (msgbuf, chunk, 4096);
+ }
+ else if (msg->GetType () == MSG_SECUREID_RESPONSE)
+ {
+ RA_SecureId_Response_Msg *resp = (RA_SecureId_Response_Msg *) msg;
+ char *value = resp->GetValue ();
+ char *pin = resp->GetPIN ();
+ if (pin == NULL)
+ {
+ pin = (char *) "";
+ }
+ sprintf (msgbuf, "%s=%d&%s=%s&%s=%s",
+ PARAM_MSG_TYPE, MSG_SECUREID_RESPONSE,
+ PARAM_VALUE, value, PARAM_PIN, pin);
+ CreateChunkEntity (msgbuf, chunk, 4096);
+ }
+ else if (msg->GetType () == MSG_ASQ_RESPONSE)
+ {
+ RA_ASQ_Response_Msg *resp = (RA_ASQ_Response_Msg *) msg;
+ sprintf (msgbuf, "%s=%d&%s=%s",
+ PARAM_MSG_TYPE, MSG_ASQ_RESPONSE,
+ PARAM_ANSWER, resp->GetAnswer ());
+ CreateChunkEntity (msgbuf, chunk, 4096);
+ }
+ else if (msg->GetType () == MSG_NEW_PIN_RESPONSE)
+ {
+ RA_New_Pin_Response_Msg *resp = (RA_New_Pin_Response_Msg *) msg;
+ sprintf (msgbuf, "%s=%d&%s=%s",
+ PARAM_MSG_TYPE, MSG_NEW_PIN_RESPONSE,
+ PARAM_NEW_PIN, resp->GetNewPIN ());
+ CreateChunkEntity (msgbuf, chunk, 4096);
+ }
+ else if (msg->GetType () == MSG_TOKEN_PDU_RESPONSE)
+ {
+ RA_Token_PDU_Response_Msg *resp = (RA_Token_PDU_Response_Msg *) msg;
+ APDU_Response *apdu_resp = resp->GetResponse ();
+ Buffer pdu = apdu_resp->GetData ();
+ char *pdu_encoded = Util::URLEncode (pdu);
+ sprintf (msgbuf, "%s=%d&%s=%s&%s=%d",
+ PARAM_MSG_TYPE, MSG_TOKEN_PDU_RESPONSE,
+ PARAM_PDU_DATA, pdu_encoded, PARAM_PDU_SIZE, pdu.size ());
+ if (pdu_encoded != NULL)
+ {
+ PR_Free (pdu_encoded);
+ pdu_encoded = NULL;
+ }
+ CreateChunkEntity (msgbuf, chunk, 4096);
+ }
+ else
+ {
+ /* error */
+ }
+
+ /* send chunk */
+ Output ("sending chunk ----- %s -----", chunk);
+ PR_Send (m_fd, chunk, strlen (chunk), 0, 1000000);
+
+ return 1;
+}
+
+static int
+ReadResponseHeader (PRFileDesc * fd)
+{
+ char buf[1024];
+ PRInt32 rc;
+ char *cur = buf;
+ int i;
+
+ for (i = 0; i < 1024; i++)
+ {
+ buf[i] = 0;
+ }
+ while (1)
+ {
+ rc = PR_Recv (fd, cur, 1, 0, 1000000);
+ if (buf[0] == '\r' &&
+ buf[1] == '\n' && buf[2] == '\r' && buf[3] == '\n')
+ {
+ break;
+ }
+ if (*cur == '\r')
+ {
+ cur++;
+ }
+ else if (*cur == '\n')
+ {
+ cur++;
+ }
+ else
+ {
+ cur = buf;
+ }
+ }
+ return 1;
+}
+
+static int
+GetChunkSize (PRFileDesc * fd)
+{
+ char buf[1024];
+ char *cur = buf;
+ PRInt32 rc;
+ int i;
+ int ret;
+
+ for (i = 0; i < 1024; i++)
+ {
+ buf[i] = 0;
+ }
+ while (1)
+ {
+ rc = PR_Recv (fd, cur, 1, 0, 1000000);
+ if (rc <= 0)
+ {
+ return 0;
+ }
+ if (*cur == '\r')
+ {
+ *cur = '\0';
+ /* read \n */
+ rc = PR_Recv (fd, cur, 1, 0, 1000000);
+ if (rc <= 0)
+ {
+ return 0;
+ }
+ *cur = '\0';
+ break;
+ }
+ cur++;
+ }
+ sscanf (buf, "%x", (unsigned int *) (&ret));
+ return ret;
+}
+
+static int
+GetChunk (PRFileDesc * fd, char *buf, int buflen)
+{
+ int rc = 0;
+ int sum = 0;
+ char *cur = buf;
+
+ while (1)
+ {
+ rc = PR_Recv (fd, cur, buflen - sum, 0, 1000000);
+ if (rc <= 0)
+ {
+ return -1;
+ }
+ sum += rc;
+ cur += rc;
+ cur[sum] = '\0';
+ if (sum == buflen)
+ return sum;
+ }
+}
+
+bool
+RA_Conn::isEncrypted ()
+{
+ return m_encrypted_channel;
+}
+
+void
+RA_Conn::setEncryption (bool encrypted)
+{
+ Output ("RA_Conn::setEncryption: setting encrypted channel: %d", encrypted);
+ m_encrypted_channel = encrypted;
+}
+
+APDU *
+RA_Conn::CreateAPDU (RA_Token * tok, Buffer & in_apdu_data, Buffer & mac)
+{
+ APDU *apdu = NULL;
+ Buffer apdu_data;
+
+ if (isEncrypted () && (((BYTE *) in_apdu_data)[0] == 0x84))
+ {
+ tok->decryptMsg (in_apdu_data, apdu_data);
+ }
+ else
+ {
+ apdu_data = in_apdu_data;
+ }
+
+ if (((BYTE *) apdu_data)[1] == 0x5a)
+ {
+ /* Create_Object_APDU */
+ mac = Buffer (apdu_data.substr (apdu_data.size () - 8, 8));
+ BYTE object_id[4];
+ object_id[0] = ((BYTE *) apdu_data)[5];
+ object_id[1] = ((BYTE *) apdu_data)[6];
+ object_id[2] = ((BYTE *) apdu_data)[7];
+ object_id[3] = ((BYTE *) apdu_data)[8];
+ BYTE permissions[6];
+ permissions[0] = ((BYTE *) apdu_data)[13];
+ permissions[1] = ((BYTE *) apdu_data)[14];
+ permissions[2] = ((BYTE *) apdu_data)[15];
+ permissions[3] = ((BYTE *) apdu_data)[16];
+ permissions[4] = ((BYTE *) apdu_data)[17];
+ permissions[5] = ((BYTE *) apdu_data)[18];
+ int len =
+ (((BYTE *) apdu_data)[9] << 24) + (((BYTE *) apdu_data)[10] << 16) +
+ (((BYTE *) apdu_data)[11] << 8) + ((BYTE *) apdu_data)[12];
+ apdu = new Create_Object_APDU (object_id, permissions, len);
+ apdu->SetMAC (mac);
+ }
+ else if (((BYTE *) apdu_data)[1] == 0x82)
+ {
+ /* External_Authenticate_APDU */
+ BYTE encryption = ((BYTE *) apdu_data)[2]; // P1 is sec level
+ if (encryption == (BYTE) 0x03)
+ {
+ setEncryption (true);
+ }
+ else
+ {
+ Output ("RA_Conn::CreateAPDU(): not encrypted");
+ }
+
+ // mac is last 8 bytes
+ mac = Buffer (apdu_data.substr (apdu_data.size () - 8, 8));
+ Buffer *data = new Buffer (apdu_data.substr (5, 8));
+
+ if (isEncrypted () == true)
+ {
+ apdu = new External_Authenticate_APDU (*data, SECURE_MSG_MAC_ENC);
+ }
+ else
+ {
+ apdu = new External_Authenticate_APDU (*data, SECURE_MSG_ANY);
+ }
+ if (data != NULL)
+ {
+ delete data;
+ data = NULL;
+ }
+ apdu->SetMAC (mac);
+ }
+ else if (((BYTE *) apdu_data)[1] == 0x0A)
+ {
+ /* ImportKeyEnc APDU */
+ mac = Buffer (apdu_data.substr (apdu_data.size () - 8, 8));
+ BYTE p[2];
+ p[0] = ((BYTE *) apdu_data)[2]; /* p1 */
+ p[1] = ((BYTE *) apdu_data)[3]; /* p2 */
+ Buffer *data =
+ new Buffer (apdu_data.substr (5, apdu_data.size () - 8 - 5));
+ Buffer a;
+ apdu = new Import_Key_Enc_APDU ((BYTE) p[0], (BYTE) p[1], *data);
+ apdu->SetMAC (mac);
+ if (data != NULL)
+ {
+ delete data;
+ data = NULL;
+ }
+
+ }
+ else if (((BYTE *) apdu_data)[1] == 0x0C)
+ {
+ /* Generate_Key_APDU */
+ BYTE p[2];
+ p[0] = ((BYTE *) apdu_data)[2]; /* p1 */
+ p[1] = ((BYTE *) apdu_data)[3]; /* p2 */
+ mac = Buffer (apdu_data.substr (apdu_data.size () - 8, 8));
+ BYTE alg = ((BYTE *) apdu_data)[5];
+ int keysize = (((BYTE *) apdu_data)[6] << 8) + ((BYTE *) apdu_data)[7];
+ BYTE option = ((BYTE *) apdu_data)[8];
+ BYTE type = ((BYTE *) apdu_data)[9];
+ unsigned int wc_len = (unsigned int) ((BYTE *) apdu_data)[10];
+ Buffer *wrapped_challenge = new Buffer ((BYTE *) &
+ ((BYTE *) apdu_data)[11],
+ wc_len);
+ Buffer *key_check = new Buffer ((BYTE *) &
+ ((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,
+ *wrapped_challenge, *key_check);
+ if (wrapped_challenge != NULL)
+ {
+ delete wrapped_challenge;
+ wrapped_challenge = NULL;
+ }
+ if (key_check != NULL)
+ {
+ delete key_check;
+ key_check = NULL;
+ }
+ apdu->SetMAC (mac);
+ }
+ else if (((BYTE *) apdu_data)[1] == 0x50)
+ {
+ /* Initialize_Update_APDU */
+
+ setEncryption (false);
+ BYTE p[2];
+ p[0] = ((BYTE *) apdu_data)[2]; /* p1 */
+ p[1] = ((BYTE *) apdu_data)[3]; /* p2 */
+ Buffer *data = new Buffer (apdu_data.substr (5, 8));
+ apdu = new Initialize_Update_APDU (p[0], p[1], *data);
+ if (data != NULL)
+ {
+ delete data;
+ data = NULL;
+ }
+ }
+ else if (((BYTE *) apdu_data)[1] == 0x56)
+ { /* Read Objects */
+ BYTE p[4];
+ int offset = 0;
+ int size = 0;
+ p[0] = ((BYTE *) apdu_data)[5];
+ p[1] = ((BYTE *) apdu_data)[6];
+ p[2] = ((BYTE *) apdu_data)[7];
+ p[3] = ((BYTE *) apdu_data)[8];
+ offset = (((BYTE *) apdu_data)[9] << 24) +
+ (((BYTE *) apdu_data)[10] << 16) +
+ (((BYTE *) apdu_data)[11] << 8) + ((BYTE *) apdu_data)[12];
+ size = ((BYTE *) apdu_data)[13]; /* p2 */
+ apdu = new Read_Object_APDU (p, offset, size);
+ mac = Buffer (apdu_data.substr (apdu_data.size () - 8, 8));
+ apdu->SetMAC (mac);
+ }
+ else if (((BYTE *) apdu_data)[1] == 0x58)
+ { /* List Objects */
+ apdu = new List_Objects_APDU (((BYTE *) apdu_data)[2]);
+ }
+ else if (((BYTE *) apdu_data)[1] == 0xf0)
+ {
+ /* Lifecycle_APDU */
+ mac = Buffer (apdu_data.substr (apdu_data.size () - 8, 8));
+ apdu = new Lifecycle_APDU (((BYTE *) apdu_data)[2]);
+ apdu->SetMAC (mac);
+ }
+ else if (((BYTE *) apdu_data)[1] == 0x08)
+ {
+ /* Read_BufferAPDU */
+ mac = Buffer (apdu_data.substr (apdu_data.size () - 8, 8));
+ int len = ((BYTE *) apdu_data)[2];
+ int offset = (((BYTE *) apdu_data)[5] << 8) + ((BYTE *) apdu_data)[6];
+ apdu = new Read_Buffer_APDU (len, offset);
+ apdu->SetMAC (mac);
+ }
+ else if (((BYTE *) apdu_data)[1] == 0x04)
+ {
+ /* Set_Pin_APDU */
+ BYTE p[2];
+ p[0] = ((BYTE *) apdu_data)[2]; /* p1 */
+ p[1] = ((BYTE *) apdu_data)[3]; /* p2 */
+ mac = Buffer (apdu_data.substr (apdu_data.size () - 8, 8));
+ Buffer *data =
+ new Buffer (apdu_data.substr (5, apdu_data.size () - 8 - 5));
+ apdu = new Set_Pin_APDU (p[0], p[1], *data);
+ if (data != NULL)
+ {
+ delete data;
+ data = NULL;
+ }
+ apdu->SetMAC (mac);
+ }
+ else if (((BYTE *) apdu_data)[1] == 0x2a)
+ {
+ Buffer dummy;
+ apdu = new Format_Muscle_Applet_APDU (0,
+ dummy, 0,
+ dummy, 0,
+ dummy, 0, dummy, 0, 0, 0, 0);
+ }
+ else if (((BYTE *) apdu_data)[1] == 0xe6)
+ {
+ BYTE p1 = ((BYTE *) apdu_data)[2]; /* p1 */
+ mac = Buffer (apdu_data.substr (apdu_data.size () - 8, 8));
+/* Why was it ignored?
+ Buffer dummy;
+ if (p1 == 0x02) {
+ apdu = new Install_Load_APDU(dummy, dummy, 0);
+ } else {
+ apdu = new Install_Applet_APDU(dummy, dummy, 0,0);
+ }
+*/
+ Buffer *data =
+ new Buffer (apdu_data.substr (5, apdu_data.size () - 8 - 5));
+ if (p1 == 0x02)
+ {
+ apdu = new Install_Load_APDU (*data);
+ }
+ else
+ {
+ apdu = new Install_Applet_APDU (*data);
+ }
+ apdu->SetMAC (mac);
+ if (data != NULL)
+ {
+ delete data;
+ data = NULL;
+ }
+ }
+ else if (((BYTE *) apdu_data)[1] == 0xe8)
+ {
+ BYTE p[2];
+ p[0] = ((BYTE *) apdu_data)[2]; /* p1 */
+ p[1] = ((BYTE *) apdu_data)[3]; /* p2 */
+ mac = Buffer (apdu_data.substr (apdu_data.size () - 8, 8));
+ Buffer *data =
+ new Buffer (apdu_data.substr (5, apdu_data.size () - 8 - 5));
+ apdu = new Load_File_APDU (p[0], p[1], *data);
+ if (data != NULL)
+ {
+ delete data;
+ data = NULL;
+ }
+ apdu->SetMAC (mac);
+ }
+ else if (((BYTE *) apdu_data)[1] == 0xe4)
+ {
+ mac = Buffer (apdu_data.substr (apdu_data.size () - 8, 8));
+ // Delete File apdu has two extra bytes after header
+ // remove before proceed
+ Buffer *data =
+ new Buffer (apdu_data.substr (7, apdu_data.size () - 8 - 5 - 2));
+ apdu = new Delete_File_APDU (*data);
+ if (data != NULL)
+ {
+ delete data;
+ data = NULL;
+ }
+ apdu->SetMAC (mac);
+ }
+ else if (((BYTE *) apdu_data)[1] == 0x02)
+ {
+ /* Unblock_Pin_APDU */
+ mac = Buffer (apdu_data.substr (apdu_data.size () - 8, 8));
+ apdu = new Unblock_Pin_APDU ();
+ apdu->SetMAC (mac);
+ }
+ else if (((BYTE *) apdu_data)[1] == 0xa4)
+ { /* Select */
+ BYTE p[2];
+ p[0] = ((BYTE *) apdu_data)[2]; /* p1 */
+ p[1] = ((BYTE *) apdu_data)[3]; /* p2 */
+ Buffer *data = NULL;
+ if (apdu_data.size () == 5)
+ {
+ data = new Buffer ();
+ }
+ else
+ {
+ data = new Buffer (apdu_data.substr (5, apdu_data.size () - 5));
+ }
+ apdu = new Select_APDU (p[0], p[1], *data);
+ if (data != NULL)
+ {
+ delete data;
+ data = NULL;
+ }
+ }
+ else if (((BYTE *) apdu_data)[1] == 0x3C)
+ { /* Get Status */
+ apdu = new Get_Status_APDU ();
+ }
+ else if (((BYTE *) apdu_data)[1] == 0x70)
+ { /* Get Version */
+ apdu = new Get_Version_APDU ();
+ }
+ else if (((BYTE *) apdu_data)[1] == 0x48)
+ {
+ apdu = new List_Pins_APDU (0x02);
+ }
+ else if (((BYTE *) apdu_data)[1] == 0x40)
+ { /* Put Key */
+ BYTE p[2];
+ p[0] = ((BYTE *) apdu_data)[2]; /* p1 */
+ p[1] = ((BYTE *) apdu_data)[3]; /* p2 */
+ mac = Buffer (apdu_data.substr (apdu_data.size () - 8, 8));
+ Buffer *data =
+ new Buffer (apdu_data.substr (5, apdu_data.size () - 8 - 5));
+ apdu = new Create_Pin_APDU (p[0], p[1], *data);
+ apdu->SetMAC (mac);
+ if (data != NULL)
+ {
+ delete data;
+ data = NULL;
+ }
+ }
+ else if (((BYTE *) apdu_data)[1] == 0xca)
+ { /* Get Data */
+ apdu = new Get_Data_APDU ();
+ }
+ else if (((BYTE *) apdu_data)[1] == 0xf6)
+ { /* Get_IssuerInfo */
+ apdu = new Get_IssuerInfo_APDU ();
+ }
+ else if (((BYTE *) apdu_data)[1] == 0xf4)
+ { /* Set_IssuerInfo */
+ BYTE p[2];
+ p[0] = ((BYTE *) apdu_data)[2]; /* p1 */
+ p[1] = ((BYTE *) apdu_data)[3]; /* p2 */
+ mac = Buffer (apdu_data.substr (apdu_data.size () - 8, 8));
+ Buffer *data =
+ new Buffer (apdu_data.substr (5, apdu_data.size () - 8 - 5));
+ apdu = new Set_IssuerInfo_APDU (p[0], p[1], *data);
+ apdu->SetMAC (mac);
+ if (data != NULL)
+ {
+ delete data;
+ data = NULL;
+ }
+ }
+ else if (((BYTE *) apdu_data)[1] == 0xd8)
+ { /* Put Key */
+ BYTE p[2];
+ p[0] = ((BYTE *) apdu_data)[2]; /* p1 */
+ p[1] = ((BYTE *) apdu_data)[3]; /* p2 */
+ mac = Buffer (apdu_data.substr (apdu_data.size () - 8, 8));
+ Buffer *data =
+ new Buffer (apdu_data.substr (5, apdu_data.size () - 8 - 5));
+ apdu = new Put_Key_APDU (p[0], p[1], *data);
+ apdu->SetMAC (mac);
+ if (data != NULL)
+ {
+ delete data;
+ data = NULL;
+ }
+ }
+ else if (((BYTE *) apdu_data)[1] == 0x54)
+ {
+ /* Write_Object_APDU */
+ BYTE object_id[4];
+ object_id[0] = ((BYTE *) apdu_data)[5];
+ object_id[1] = ((BYTE *) apdu_data)[6];
+ object_id[2] = ((BYTE *) apdu_data)[7];
+ object_id[3] = ((BYTE *) apdu_data)[8];
+ mac = Buffer (apdu_data.substr (apdu_data.size () - 8, 8));
+ int offset =
+ (((BYTE *) apdu_data)[9] << 24) + (((BYTE *) apdu_data)[10] << 16) +
+ (((BYTE *) apdu_data)[11] << 8) + ((BYTE *) apdu_data)[12];
+ Buffer *data =
+ new Buffer (apdu_data.substr (14, apdu_data.size () - 8 - 11 - 3));
+ apdu = new Write_Object_APDU (object_id, offset, *data);
+ apdu->SetMAC (mac);
+ if (data != NULL)
+ {
+ delete data;
+ data = NULL;
+ }
+ }
+ else
+ {
+ /* error */
+ }
+ return apdu;
+}
+
+/**
+ * Retrieves message from the RA.
+ */
+RA_Msg *
+RA_Conn::ReadMsg (RA_Token * token)
+{
+ int len = 0;
+ char buf[4096];
+ PRInt32 rc;
+ int i;
+ char *msg_type_s = NULL;
+ int msg_type;
+ RA_Msg *msg = NULL;
+
+ if (!m_read_header)
+ {
+ ReadResponseHeader (m_fd);
+ m_read_header = 1;
+ }
+
+ /* read chunk size */
+ len = GetChunkSize (m_fd);
+ if (len <= 0)
+ {
+ return NULL;
+ }
+
+ for (i = 0; i < 4096; i++)
+ {
+ buf[i] = 0;
+ }
+
+ /* read chunk */
+ rc = GetChunk (m_fd, buf, len + 2);
+ if (rc <= 0)
+ {
+ return NULL;
+ }
+ buf[len] = '\0';
+
+ /* parse name value pair */
+ NameValueSet *params = NameValueSet::Parse (buf, "&");
+ if (params == NULL)
+ return NULL;
+ msg_type_s = params->GetValue (PARAM_MSG_TYPE);
+ if (msg_type_s == NULL)
+ {
+ if (params != NULL)
+ {
+ delete params;
+ params = NULL;
+ }
+ return NULL;
+ }
+ msg_type = atoi (msg_type_s);
+
+ if (msg_type == MSG_LOGIN_REQUEST)
+ {
+ msg =
+ new RA_Login_Request_Msg (atoi (params->GetValue (PARAM_INVALID_PW)),
+ atoi (params->GetValue (PARAM_BLOCKED)));
+ }
+ else if (msg_type == MSG_EXTENDED_LOGIN_REQUEST)
+ {
+ msg = new RA_Extended_Login_Request_Msg (0, 0, NULL, 0, NULL, NULL);
+ }
+ else if (msg_type == MSG_END_OP)
+ {
+ msg = new RA_End_Op_Msg ((RA_Op_Type)
+ atoi (params->GetValue (PARAM_OPERATION)),
+ atoi (params->GetValue (PARAM_RESULT)),
+ atoi (params->GetValue (PARAM_MESSAGE)));
+ }
+ else if (msg_type == MSG_SECUREID_REQUEST)
+ {
+ msg =
+ new
+ RA_SecureId_Request_Msg (atoi (params->GetValue (PARAM_PIN_REQUIRED)),
+ atoi (params->GetValue (PARAM_NEXT_VALUE)));
+ }
+ else if (msg_type == MSG_STATUS_UPDATE_REQUEST)
+ {
+ msg =
+ new
+ RA_Status_Update_Request_Msg (atoi
+ (params->
+ GetValue (PARAM_CURRENT_STATE)),
+ params->
+ GetValue (PARAM_NEXT_TASK_NAME));
+ }
+ else if (msg_type == MSG_ASQ_REQUEST)
+ {
+ msg = new RA_ASQ_Request_Msg (params->GetValue (PARAM_QUESTION));
+ }
+ else if (msg_type == MSG_NEW_PIN_REQUEST)
+ {
+ msg =
+ new
+ RA_New_Pin_Request_Msg (atoi
+ (params->GetValue (PARAM_MINIMUM_LENGTH)),
+ atoi (params->
+ GetValue (PARAM_MAXIMUM_LENGTH)));
+ }
+ else if (msg_type == MSG_TOKEN_PDU_REQUEST)
+ {
+ char *pdu_encoded = params->GetValue (PARAM_PDU_DATA);
+ Buffer *apdu_data = Util::URLDecode (pdu_encoded);
+
+#ifdef VERBOSE
+ Output ("ReadMsg: URLDecoded apdu = ");
+ printBuf (apdu_data);
+#endif
+
+ Buffer mac;
+ APDU *apdu = CreateAPDU (token, *apdu_data, mac);
+ msg = new RA_Token_PDU_Request_Msg (apdu);
+ if (apdu_data != NULL)
+ {
+ delete apdu_data;
+ apdu_data = NULL;
+ }
+ }
+ else
+ {
+ /* error */
+ if (params != NULL)
+ {
+ delete params;
+ params = NULL;
+ }
+ return NULL;
+ }
+
+ if (params != NULL)
+ {
+ delete params;
+ params = NULL;
+ }
+
+ return msg;
+}
+
+/**
+ * Terminates this connection.
+ */
+int
+RA_Conn::Close ()
+{
+ if (m_fd != NULL)
+ {
+ PR_Close (m_fd);
+ m_fd = NULL;
+ }
+ return 1;
+}
diff --git a/base/tps/tools/raclient/RA_Conn.h b/base/tps/tools/raclient/RA_Conn.h
new file mode 100644
index 000000000..307166eaf
--- /dev/null
+++ b/base/tps/tools/raclient/RA_Conn.h
@@ -0,0 +1,71 @@
+/* --- 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 RA_CONN_H
+#define RA_CONN_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 <stdio.h>
+#include "prio.h"
+#include "RA_Token.h"
+#include "main/RA_Msg.h"
+#include "main/Buffer.h"
+#include "apdu/APDU.h"
+
+class RA_Conn
+{
+ public:
+ RA_Conn(char *host, int port, char *uri);
+ ~RA_Conn();
+ public:
+ int SendMsg(RA_Msg *msg);
+ RA_Msg *ReadMsg();
+ RA_Msg *ReadMsg(RA_Token *token);
+ int Connect();
+ int Close();
+ void setEncryption(bool encrypted);
+ bool isEncrypted();
+ public:
+ APDU *CreateAPDU(RA_Token *tok, Buffer &data, Buffer &mac);
+ private:
+ char *m_host;
+ int m_port;
+ char *m_uri;
+ PRFileDesc *m_fd;
+ int m_read_header;
+ bool m_encrypted_channel;
+};
+
+#endif /* RA_MSG_H */
diff --git a/base/tps/tools/raclient/RA_Token.cpp b/base/tps/tools/raclient/RA_Token.cpp
new file mode 100644
index 000000000..069d6c23c
--- /dev/null
+++ b/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;
+}
diff --git a/base/tps/tools/raclient/RA_Token.h b/base/tps/tools/raclient/RA_Token.h
new file mode 100644
index 000000000..bf92e4e89
--- /dev/null
+++ b/base/tps/tools/raclient/RA_Token.h
@@ -0,0 +1,225 @@
+/* --- 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 RA_TOKEN_H
+#define RA_TOKEN_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 <stdio.h>
+#include "main/Buffer.h"
+#include "main/NameValueSet.h"
+#include "apdu/APDU_Response.h"
+#include "apdu/APDU.h"
+#include "apdu/Initialize_Update_APDU.h"
+#include "apdu/External_Authenticate_APDU.h"
+#include "apdu/Set_Pin_APDU.h"
+#include "apdu/Get_Status_APDU.h"
+#include "apdu/Create_Object_APDU.h"
+#include "apdu/Lifecycle_APDU.h"
+#include "apdu/Read_Buffer_APDU.h"
+#include "apdu/Get_IssuerInfo_APDU.h"
+#include "apdu/Set_IssuerInfo_APDU.h"
+#include "apdu/Load_File_APDU.h"
+#include "apdu/Format_Muscle_Applet_APDU.h"
+#include "apdu/Install_Applet_APDU.h"
+#include "apdu/Install_Load_APDU.h"
+#include "apdu/Unblock_Pin_APDU.h"
+#include "apdu/Write_Object_APDU.h"
+#include "apdu/Read_Object_APDU.h"
+#include "apdu/List_Pins_APDU.h"
+#include "apdu/List_Objects_APDU.h"
+#include "apdu/Create_Pin_APDU.h"
+#include "apdu/Generate_Key_APDU.h"
+#include "apdu/Select_APDU.h"
+#include "apdu/Delete_File_APDU.h"
+#include "apdu/Get_Version_APDU.h"
+#include "apdu/Get_Data_APDU.h"
+#include "apdu/Put_Key_APDU.h"
+#include "apdu/Import_Key_APDU.h"
+#include "apdu/Import_Key_Enc_APDU.h"
+
+typedef enum {
+ auth,
+ mac,
+ kek
+ } keyType;
+
+class RA_Token
+{
+ public:
+ RA_Token();
+ ~RA_Token();
+ public:
+ char *GetPIN();
+ Buffer &GetAuthKey();
+ Buffer &GetMacKey();
+ Buffer &GetKekKey();
+ Buffer &GetAppletVersion();
+ void SetAppletVersion(Buffer &version);
+ Buffer &GetCUID();
+ void SetCUID(Buffer &cuid);
+ Buffer &GetMSN();
+ void SetMSN(Buffer &msn);
+ Buffer &GetKeyInfo();
+ int GetMajorVersion();
+ int GetMinorVersion();
+ void SetKeyInfo(Buffer &key_info);
+ void SetAuthKey(Buffer &key);
+ void SetMacKey(Buffer &key);
+ void SetKekKey(Buffer &key);
+ void SetMajorVersion(int v);
+ void SetMinorVersion(int v);
+ BYTE GetLifeCycleState();
+ public:
+ int VerifyMAC(APDU *apdu);
+ void ComputeAPDUMac(APDU *apdu, Buffer &new_mac);
+ PK11SymKey *CreateSessionKey(keyType keytype,
+ Buffer &card_challenge,
+ Buffer &host_challenge);
+ RA_Token *Clone();
+ void decryptMsg(Buffer &in_data, Buffer &out_data);
+ PK11SymKey *GetEncSessionKey();
+ public:
+ int NoOfCertificates();
+ CERTCertificate *GetCertificate(int pos);
+ int NoOfPrivateKeys();
+ SECKEYPrivateKey *GetPrivateKey(int pos);
+ public:
+ APDU_Response *Process(APDU *apdu, NameValueSet *vars, NameValueSet *params);
+ APDU_Response *ProcessInitializeUpdate(
+ Initialize_Update_APDU *apdu,
+ NameValueSet *vars,
+ NameValueSet *params);
+ APDU_Response *ProcessExternalAuthenticate(
+ External_Authenticate_APDU *apdu,
+ NameValueSet *vars,
+ NameValueSet *params);
+ APDU_Response *ProcessReadObject(Read_Object_APDU *apdu,
+ NameValueSet *vars,
+ NameValueSet *params);
+ APDU_Response *ProcessListObjects(List_Objects_APDU *apdu,
+ NameValueSet *vars,
+ NameValueSet *params);
+ APDU_Response *ProcessDeleteFile(Delete_File_APDU *apdu,
+ NameValueSet *vars,
+ NameValueSet *params);
+ APDU_Response *ProcessSetPin(Set_Pin_APDU *apdu,
+ NameValueSet *vars,
+ NameValueSet *params);
+ APDU_Response *ProcessInstallApplet(Install_Applet_APDU *apdu,
+ NameValueSet *vars,
+ NameValueSet *params);
+ APDU_Response *ProcessInstallLoad(Install_Load_APDU *apdu,
+ NameValueSet *vars,
+ NameValueSet *params);
+ APDU_Response *ProcessLoadFile(Load_File_APDU *apdu,
+ NameValueSet *vars,
+ NameValueSet *params);
+ APDU_Response *ProcessFormatMuscleApplet(Format_Muscle_Applet_APDU *apdu,
+ NameValueSet *vars,
+ NameValueSet *params);
+ APDU_Response *ProcessGetVersion(Get_Version_APDU *apdu,
+ NameValueSet *vars,
+ NameValueSet *params);
+ APDU_Response *ProcessListPins(List_Pins_APDU *apdu,
+ NameValueSet *vars,
+ NameValueSet *params);
+ APDU_Response *ProcessCreatePin(Create_Pin_APDU *apdu,
+ NameValueSet *vars,
+ NameValueSet *params);
+ APDU_Response *ProcessGetData(Get_Data_APDU *apdu,
+ NameValueSet *vars,
+ NameValueSet *params);
+ APDU_Response *ProcessGetStatus(Get_Status_APDU *apdu,
+ NameValueSet *vars,
+ NameValueSet *params);
+ APDU_Response *ProcessCreateObject(Create_Object_APDU *apdu,
+ NameValueSet *vars,
+ NameValueSet *params);
+ APDU_Response *ProcessLifecycle(Lifecycle_APDU *apdu,
+ NameValueSet *vars,
+ NameValueSet *params);
+ APDU_Response *ProcessReadBuffer(Read_Buffer_APDU *apdu,
+ NameValueSet *vars,
+ NameValueSet *params);
+ APDU_Response *ProcessUnblockPin(Unblock_Pin_APDU *apdu,
+ NameValueSet *vars,
+ NameValueSet *params);
+ APDU_Response *ProcessGetIssuerInfo(Get_IssuerInfo_APDU *apdu,
+ NameValueSet *vars,
+ NameValueSet *params);
+ APDU_Response *ProcessSetIssuerInfo(Set_IssuerInfo_APDU *apdu,
+ NameValueSet *vars,
+ NameValueSet *params);
+ APDU_Response *ProcessWriteBuffer(Write_Object_APDU *apdu,
+ NameValueSet *vars,
+ NameValueSet *params);
+ APDU_Response *ProcessGenerateKey(Generate_Key_APDU *apdu,
+ NameValueSet *vars,
+ NameValueSet *params);
+ APDU_Response *ProcessImportKeyEnc(Import_Key_Enc_APDU *apdu,
+ NameValueSet *vars,
+ NameValueSet *params);
+ APDU_Response *ProcessSelect(Select_APDU *apdu,
+ NameValueSet *vars,
+ NameValueSet *params);
+ APDU_Response *ProcessPutKey(Put_Key_APDU *apdu,
+ NameValueSet *vars,
+ NameValueSet *params);
+ 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];
+};
+
+#endif /* RA_TOKEN_H */
diff --git a/base/tps/tools/raclient/enroll.tps b/base/tps/tools/raclient/enroll.tps
new file mode 100644
index 000000000..08e40b6e1
--- /dev/null
+++ b/base/tps/tools/raclient/enroll.tps
@@ -0,0 +1,42 @@
+# --- 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=air
+op=var_set name=ra_port value=8099
+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
+#op=ra_enroll uid=test pwd=password new_pin=password
+op=ra_enroll uid=sectest13 num_threads=1 pwd=home-boy new_pin=password
+# print changed token status
+op=token_status
+op=exit
diff --git a/base/tps/tools/raclient/enroll1.test b/base/tps/tools/raclient/enroll1.test
new file mode 100644
index 000000000..fdd54f704
--- /dev/null
+++ b/base/tps/tools/raclient/enroll1.test
@@ -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 enrollent.
+#
+# Execution:
+# tpsclient < enroll.test
+#
+########################################################
+op=var_set name=ra_host value=air
+op=var_set name=ra_port value=8000
+op=var_set name=ra_uri value=/nk_service
+# print original token status
+op=token_status
+###set token params
+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
+op=ra_enroll uid=sectest13 pwd=home-boy new_pin=password
+# print changed token status
+op=token_status
+op=exit
diff --git a/base/tps/tools/raclient/format.tps b/base/tps/tools/raclient/format.tps
new file mode 100644
index 000000000..f087a2d25
--- /dev/null
+++ b/base/tps/tools/raclient/format.tps
@@ -0,0 +1,45 @@
+# --- 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 token format operation.
+#
+# Execution:
+# tpsclient < format.test
+#
+########################################################
+op=var_set name=ra_host value=air
+op=var_set name=ra_port value=8000
+op=var_set name=ra_uri value=/nk_service
+op=var_list
+# print original token status
+op=token_status
+### set token params
+op=token_set cuid=a00192030405060708c9 app_ver=6FBBC105 key_info=0101
+op=token_set auth_key=404142434445464748494a4b4c4d4e4f
+op=token_set mac_key=404142434445464748494a4b4c4d4e4f
+op=token_set kek_key=404142434445464748494a4b4c4d4e4f
+op=token_status
+## perform format operation
+op=ra_format uid=test pwd=password num_threads=1 new_pin=password
+# print changed token status
+op=token_status
+op=exit
diff --git a/base/tps/tools/raclient/nt_enroll.test b/base/tps/tools/raclient/nt_enroll.test
new file mode 100644
index 000000000..f4faf18fe
--- /dev/null
+++ b/base/tps/tools/raclient/nt_enroll.test
@@ -0,0 +1,212 @@
+# --- 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=water
+op=var_set name=ra_port value=7888
+op=var_set name=ra_uri value=/nk_service
+########################################################
+# Possible return codes:
+#
+# General errors:
+# 6400 - No specific diagnosis
+# 6700 - Wrong length in Lc
+# 6982 - Security status not satisfied
+# 6985 - Conditions of use not satisified
+# 6a86 - Incorrect P1 P2
+# 6d00 - Invalid instruction
+# 6e00 - Invalid class
+#
+# Install Load errors:
+# 6581 - Memory Failure
+# 6a80 - Incorrect parameters in data field
+# 6a84 - Not enough memory space
+# 6a88 - Referenced data not found
+#
+# Delete errors:
+# 6200 - Application has been logically deleted
+# 6581 - Memory failure
+# 6985 - Referenced data cannot be deleted
+# 6a88 - Referenced data not found
+# 6a82 - Application not found
+# 6a80 - Incorrect values in command data
+#
+# Get Data errors:
+# 6a88 - Referenced data not found
+#
+# Get Status errors:
+# 6310 - More data available
+# 6a88 - Referenced data not found
+# 6a80 - Incorrect values in command data
+#
+# Load errors:
+# 6581 - Memory failure
+# 6a84 - Not enough memory space
+# 6a86 - Incorrect P1/P2
+# 6985 - Conditions of use not satisified
+########################################################
+#
+########################################################
+# Negative Test Cases Testing:
+#
+# To enable the testing, you need to uncomment
+# the following:
+#
+#op=var_set name=test_enable value=true
+#
+# Init Update APDU:
+#
+#op=var_set name=test_apdu_iu_return_enable value=true
+#op=var_set name=test_apdu_iu_return value=6a88
+#
+# External Authenticate APDU:
+#
+#op=var_set name=test_apdu_ea_return_enable value=true
+#op=var_set name=test_apdu_ea_return value=6a88
+#
+# Generate Key APDU:
+#
+#op=var_set name=test_apdu_gk_return_enable value=true
+#op=var_set name=test_apdu_gk_return value=6a88
+#
+# Create Object APDU:
+#
+#op=var_set name=test_apdu_co_return_enable value=true
+#op=var_set name=test_apdu_co_return value=6a88
+#
+# Life Cycle APDU:
+#
+#op=var_set name=test_apdu_lc_return_enable value=true
+#op=var_set name=test_apdu_lc_return value=6a88
+#
+# Delete File APDU:
+#
+#op=var_set name=test_apdu_df_return_enable value=true
+#op=var_set name=test_apdu_df_return value=6a88
+#
+# Install Applet APDU:
+#
+#op=var_set name=test_apdu_ia_return_enable value=true
+#op=var_set name=test_apdu_ia_return value=6a88
+#
+# Install Load APDU:
+#
+#op=var_set name=test_apdu_il_return_enable value=true
+#op=var_set name=test_apdu_il_return value=6a88
+#
+# Load File APDU:
+#
+#op=var_set name=test_apdu_lf_return_enable value=true
+#op=var_set name=test_apdu_lf_return value=6a88
+#
+# Select Applet APDU:
+#
+#op=var_set name=test_apdu_se_return_enable value=true
+#op=var_set name=test_apdu_se_return value=6a88
+#
+# List PINs APDU:
+#
+#op=var_set name=test_apdu_lp_return_enable value=true
+#op=var_set name=test_apdu_lp_return value=6a88
+#
+# Create PIN APDU:
+#
+#op=var_set name=test_apdu_cp_return_enable value=true
+#op=var_set name=test_apdu_cp_return value=6a88
+#
+# Get Version APDU:
+#
+#op=var_set name=test_apdu_gv_return_enable value=true
+#op=var_set name=test_apdu_gv_return value=6a88
+#
+# Get Data APDU:
+#op=var_set name=test_apdu_gd_return_enable value=true
+#op=var_set name=test_apdu_gd_return value=6a88
+#
+# Get Status APDU:
+#
+#op=var_set name=test_apdu_gs_return_enable value=true
+#op=var_set name=test_apdu_gs_return value=6a88
+#
+# Put Key APDU:
+#
+#op=var_set name=test_apdu_pk_return_enable value=true
+#op=var_set name=test_apdu_pk_return value=6a88
+#
+# Import Key Enc APDU:
+#
+#op=var_set name=test_apdu_ik_return_enable value=true
+#op=var_set name=test_apdu_ik_return value=6a88
+#
+# Read Buffer APDU:
+#
+#op=var_set name=test_apdu_rb_return_enable value=true
+#op=var_set name=test_apdu_rb_return value=6a88
+#
+# Unblock PIN APDU:
+#
+#op=var_set name=test_apdu_up_return_enable value=true
+#op=var_set name=test_apdu_up_return value=6a88
+#
+# List Objects APDU:
+#
+#op=var_set name=test_apdu_lo_return_enable value=true
+#op=var_set name=test_apdu_lo_return value=6a88
+#
+# Read Object APDU:
+#
+#op=var_set name=test_apdu_ro_return_enable value=true
+#op=var_set name=test_apdu_ro_return value=6a88
+#
+# Write Buffer APDU:
+#
+#op=var_set name=test_apdu_wb_return_enable value=true
+#op=var_set name=test_apdu_wb_return value=6a88
+#
+# Set PIN APDU:
+#
+#op=var_set name=test_apdu_sp_return_enable value=true
+#op=var_set name=test_apdu_sp_return value=6a88
+#
+# ExtendedLoginRequest Message:
+#
+#op=var_set name=test_msg_el_resp_exclude_uid value=true
+#op=var_set name=test_msg_el_resp_exclude_pwd value=true
+#op=var_set name=test_msg_el_resp_add_invalid_param value=true
+#
+########################################################
+# 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
+#op=ra_enroll uid=test pwd=password new_pin=password
+op=ra_enroll uid=testuser1 num_threads=1 pwd=netscape new_pin=password
+# print changed token status
+op=token_status
+op=exit
diff --git a/base/tps/tools/raclient/readme.txt b/base/tps/tools/raclient/readme.txt
new file mode 100644
index 000000000..8997544ac
--- /dev/null
+++ b/base/tps/tools/raclient/readme.txt
@@ -0,0 +1,247 @@
+# --- 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 ---
+#
+Overview
+========
+
+tpsclient is a test utility that talks to the TPS
+directly using HTTP protocol.
+
+It is a software-based token. It can be used as a driver
+for stress/scalability testing.
+
+It can be used for the following operations:
+
+ enrollment - This is for getting a certificate
+ into the token.
+ pin reset - This is for changing the token's pin.
+ format - This is for formatting the token to
+ remove the certificates from the token
+ and load fresh applets.
+
+Configuration
+=============
+
+The tpsclient utility accepts a test script file. Each script
+file contains a sequence of operations. Each operation
+is composed of a set of name value pairs. For example,
+
+ op=var_set name=ra_host value=familiar
+
+It starts with an operation type such as 'op=var_set' and
+follows by a list of parameters as 'name=ra_host value=familiar'.
+
+The currently supported operation types are as follows:
+
+ op=var_list - list all TPS connection parameters
+ op=var_get - retrieve the value of a TPS connection parameter
+ op=var_set - set the value of a TPS conection parameter
+
+ op=exit - exit this utility
+ op=help - get more information about each operation
+
+ op=token_status - list all token parameters
+ op=token_set - set the value of a token parameter
+
+ op=ra_enroll - perform an enrollment operation
+ op=ra_reset_pin - perform a pin reset operation
+ op=ra_format - perform a format operation
+
+Configuration Examples
+======================
+
+Setup TPS's connection information:
+
+ op=var_set name=ra_host value=familiar
+ op=var_set name=ra_port value=9003
+ op=var_set name=ra_uri value=/nk_service
+
+Setup token's ID, Applet ID, and Key Set Version:
+
+ op=token_set cuid=a00192030405060708c9 app_ver=6FBBC105 key_info=0101
+
+Setup Key Data: (Note that '404142434445464748494a4b4c4d4e4f' is the
+default key created by the manufacturer in the real token)
+
+ op=token_set auth_key=404142434445464748494a4b4c4d4e4f
+ op=token_set mac_key=404142434445464748494a4b4c4d4e4f
+ op=token_set kek_key=404142434445464748494a4b4c4d4e4f
+
+Perform an enrollment operation:
+
+ op=ra_enroll uid=sectest13 pwd=home-boy new_pin=password
+
+Perform a pin reset operation:
+
+ op=ra_reset_pin uid=test pwd=password new_pin=newpassw
+
+Perform a format operation:
+
+ op=ra_format uid=test pwd=password new_pin=newpassw
+
+Print the information inside token:
+
+ op=token_status
+
+Applet Upgrade Example
+======================
+
+To test applet upgrade, you should first setup TPS to enable
+applet upgrade. Please consult the TPS documentation for those
+details.
+
+You should try to do an enrollment operation with an applet
+version that's different from the one that's configured in
+the TPS's configuration file. For example, you should have
+the following in the test script.
+
+ op=token_set cuid=18888883333300000004 app_ver=402428AD key_info=0101
+
+This indicates that the token's applet version is currently at
+40248AD.
+
+
+After execution, you should see an audit event logged on the
+TPS's audit log file like this,
+
+
+ ...
+ [2004-11-15 16:56:38] 847f220 Enrollment - op='applet_upgrade'
+ app_ver='0.0.402428AD' new_app_ver='1.2.416DA155'
+ ...
+ ...
+ [2004-11-15 16:56:43] 847f220 Enrollment - status='success'
+ app_ver='1.2.416DA155' key_ver='0101' cuid='18888883333300000004'
+ msn='00000000' uid='user1' auth='ldap1' time='7243 msec'
+
+Key Change Over Example
+=======================
+
+To test key change over, you should setup a version 2 master key
+in TKS and enable the key change over feature in TPS. Please
+consult the TPS documentation for details.
+
+You should try to do an enrollment with a version 1 key in the
+token. TPS should change the key in your token to
+version 2. For example, you should have the following in
+the test script:
+
+ op=token_set cuid=a00192030405060708c9 app_ver=6FBBC105 key_info=0101
+ op=token_set auth_key=404142434445464748494a4b4c4d4e4f
+ op=token_set mac_key=404142434445464748494a4b4c4d4e4f
+ op=token_set kek_key=404142434445464748494a4b4c4d4e4f
+
+Note 'key_info=0101' indicates a version 1 key set.
+
+After the execution, you should see the following in the output:
+
+ ...
+ Output> cuid : 'a00192030405060708c9' (10 bytes)
+ Output> key_info : '0201' (2 bytes)
+ Output> auth_key : 'a3523ec8c0740b621e18e9cdd99f75fc' (16 bytes)
+ Output> mac_key : '903af964eb7ede26ea189243a5caad9c' (16 bytes)
+ Output> kek_key : '44ef9de3775121a871c152563d9b9860' (16 bytes)
+ ...
+
+'key_info: 0201' indicates that the current key set in the
+token now changed from '0101' to '0201'. And as you noticed,
+the key data for auth, mac, and kek keys are all different.
+
+If you check the TPS's log, you should see an audit event for
+the key change over operation.
+
+After this, you should try to enroll with a version 2 keys.
+For example, create a new test script that contains:
+
+ op=token_set cuid=a00192030405060708c9 app_ver=6FBBC105 key_info=0201
+ op=token_set auth_key=a3523ec8c0740b621e18e9cdd99f75fc
+ op=token_set mac_key=903af964eb7ede26ea189243a5caad9c
+ op=token_set kek_key=44ef9de3775121a871c152563d9b9860
+
+Execute this test script, and you should NOT see an audit
+event for key change over. It is because your token already
+has a version 2 key set.
+
+You can also try to key change over from version 2 back to
+version 1 with appropriate TPS configuration and test
+script.
+
+Choose a specific profile in TPS
+================================
+
+TPS can be configured to support several profiles like
+
+ 1) devicekey profile - used to issue only signing certs
+ 2) userKey profile - used to issue signing and encryption certs
+
+the tpsclient can be configured to tell TPS to select the right
+profile by adding the following to the op=ra_enroll line in the
+test script
+
+ op=ra_enroll uid=user1 num_threads=1 pwd=password new_pin=newpassw
+ extensions=tokenType=userKey
+
+ (OR)
+
+ op=ra_enroll uid=user1 num_threads=1 pwd=password new_pin=newpassw
+ extensions=tokenType=deviceKey
+
+Stress test Example
+===================
+
+tpsclient can be configured to start multiple threads to perform
+enrollment or pin reset or format operations, to stress the TPS
+installation.
+
+ op=ra_enroll uid=user1 num_threads=1 pwd=password new_pin=newpassw
+ extensions=tokenType=userKey
+
+In the above test script line, the num_threads parameter indicates
+the number of threads that will be started.
+
+Also , to control the number of operations being performed, the
+following parameter should be set in the test script line.
+
+ op=ra_enroll uid=user1 num_threads=1 pwd=password new_pin=newpassw
+ extensions=tokenType=userKey max_ops=10
+
+max_ops, indicates the number of operations that will be performed
+by all the threads.
+
+
+
+
+Execution
+=========
+
+For Enrollment Operation:
+
+ tpsclient < enroll.test
+
+For Reset Pin Operation:
+
+ tpsclient < reset_pin.test
+
+Note
+====
+
+You may need to setup LD_LIBRARY_PATH (On Linux, and Solaris) to
+point to the directory where you have NSPR, NSS, TPS shared libraries.
+
diff --git a/base/tps/tools/raclient/reset_pin.tps b/base/tps/tools/raclient/reset_pin.tps
new file mode 100644
index 000000000..1a81fd2a7
--- /dev/null
+++ b/base/tps/tools/raclient/reset_pin.tps
@@ -0,0 +1,42 @@
+# --- 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 pin reset operation.
+#
+# Execution:
+# tpsclient < reset_pin.test
+#
+########################################################
+op=var_set name=ra_host value=air
+op=var_set name=ra_port value=8000
+op=var_set name=ra_uri value=/nk_service
+op=var_list
+# print original token status
+op=token_set cuid=a00192030405060708c9 app_ver=6FBBC105 key_info=0101
+op=token_set auth_key=404142434445464748494a4b4c4d4e4f
+op=token_set mac_key=404142434445464748494a4b4c4d4e4f
+op=token_set kek_key=404142434445464748494a4b4c4d4e4f
+op=token_status
+op=ra_reset_pin uid=test pwd=password num_threads=1 new_pin=password
+# print changed token status
+op=token_status
+op=exit
diff --git a/base/tps/tools/raclient/reset_pin1.test b/base/tps/tools/raclient/reset_pin1.test
new file mode 100644
index 000000000..2169e7ce2
--- /dev/null
+++ b/base/tps/tools/raclient/reset_pin1.test
@@ -0,0 +1,40 @@
+# --- 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 pin reset.
+#
+# Execution:
+# tpsclient < reset_pin.test
+#
+# This one is failure case. The sectest12 requires securid but
+# the test doesnt provide one.
+########################################################
+op=var_set name=ra_host value=broom
+op=var_set name=ra_port value=2020
+op=var_set name=ra_uri value=/nk_service
+op=var_list
+# print original token status
+op=token_status
+op=ra_reset_pin uid=sectest12 pwd=blue77 new_pin=password
+# print changed token status
+op=token_status
+op=exit
diff --git a/base/tps/tools/raclient/reset_pin2.test b/base/tps/tools/raclient/reset_pin2.test
new file mode 100644
index 000000000..77b5d20d2
--- /dev/null
+++ b/base/tps/tools/raclient/reset_pin2.test
@@ -0,0 +1,39 @@
+# --- 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 pin reset.
+#
+# Execution:
+# tpsclient < reset_pin.test
+#
+# This one is success case. The sectest13 does not require securid.
+########################################################
+op=var_set name=ra_host value=broom
+op=var_set name=ra_port value=2020
+op=var_set name=ra_uri value=/nk_service
+op=var_list
+# print original token status
+op=token_status
+op=ra_reset_pin uid=sectest13 pwd=home-boy new_pin=password
+# print changed token status
+op=token_status
+op=exit
diff --git a/base/tps/tools/tus/add.c b/base/tps/tools/tus/add.c
new file mode 100644
index 000000000..f88ae9753
--- /dev/null
+++ b/base/tps/tools/tus/add.c
@@ -0,0 +1,117 @@
+/* --- 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 ---
+ */
+
+#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 "nsapi.h"
+
+#include <time.h>
+#include <stdlib.h>
+#include <stdio.h>
+#include "ldap.h"
+
+#include "tus/tus_db.h"
+
+/* Specify the search criteria here. */
+static char *host = "localhost";
+static int port = 389;
+static char *baseDN = "ou=Tokens,dc=mcom,dc=com";
+static char *prefix = "0000";
+static char *suffix = "0000";
+static int start = 1;
+static int len = 0;
+static char *who = NULL;
+static char *password = NULL;
+static char *token_type = NULL;
+
+
+#define SCOPE LDAP_SCOPE_SUBTREE
+#define FILTER "(cn=*)"
+
+int main (int argc, char **argv)
+{
+ int i, h, rc;
+ char cn[256];
+ char *errorMsg = NULL;
+
+ if (argc < 9 || argc > 11) {
+ printf ("Usage:\n %s baseDN prefix suffix start len who password token_type host port", argv[0]);
+ return 1;
+ }
+
+ baseDN = argv[1];
+ prefix = argv[2];
+ suffix = argv[3];
+ start = atoi(argv[4]);
+ len = atoi(argv[5]);
+ who = argv[6];
+ password = argv[7];
+ token_type = argv[8];
+
+ if (argc > 9) {
+ host = argv[9];
+ }
+
+ if (argc > 10) {
+ port = atoi(argv[10]);
+ }
+
+ set_tus_db_baseDN(baseDN);
+ set_tus_db_port(port);
+ set_tus_db_host(host);
+ set_tus_db_bindDN(who);
+ set_tus_db_bindPass(password);
+ rc = tus_db_init(errorMsg);
+ if (rc != LDAP_SUCCESS) {
+ fprintf(stderr, "tus_db_init: (%d) %s\n", rc, errorMsg);
+ return 1;
+ }
+
+ for (i = 0; i < len; i++) {
+ h = start + i;
+ sprintf(cn, "%s%08X%s", prefix, h, suffix);
+ printf ("Adding %s\n", cn);
+
+ rc = add_default_tus_db_entry (NULL, "", cn, "active", "", "", token_type);
+ if (rc != LDAP_SUCCESS) {
+ fprintf( stderr, "ldap_add_ext_s: %s\n", ldap_err2string( rc ) );
+ return 1;
+ }
+ }
+
+ /* STEP 4: Disconnect from the server. */
+ tus_db_end();
+
+ return( 0 );
+}
diff --git a/base/tps/tools/tus/test.c b/base/tps/tools/tus/test.c
new file mode 100644
index 000000000..a307d1ccc
--- /dev/null
+++ b/base/tps/tools/tus/test.c
@@ -0,0 +1,117 @@
+/* --- 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 ---
+ */
+
+#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 <stdio.h>
+#include "ldap.h"
+#include "ldappr.h"
+
+/* Specify the search criteria here. */
+#define HOSTNAME "localhost"
+#define PORTNUMBER 389
+#define BASEDN "ou=Tokens,dc=mcom,dc=com"
+#define SCOPE LDAP_SCOPE_SUBTREE
+#define FILTER "(cn=*)"
+
+int
+main( int argc, char **argv )
+{
+ char ldapuri[1024];
+ LDAP *ld;
+ LDAPMessage *result = NULL, *e;
+ char *dn = NULL;
+ int version, rc;
+ /* Print out an informational message. */
+ printf( "Connecting to host %s at port %d...\n\n", HOSTNAME,
+ PORTNUMBER );
+
+ /* STEP 1: Get a handle to an LDAP connection and
+ set any session preferences. */
+ snprintf(ldapuri, 1024, "ldap://%s:%i", HOSTNAME, PORTNUMBER);
+ rc = ldap_initialize(&ld, ldapuri);
+
+ if ( ld == NULL ) {
+ perror( "ldap_initialize" );
+ return( 1 );
+ }
+
+ /* Use the LDAP_OPT_PROTOCOL_VERSION session preference to specify
+ that the client is an LDAPv3 client. */
+ version = LDAP_VERSION3;
+ ldap_set_option( ld, LDAP_OPT_PROTOCOL_VERSION, &version );
+
+ /* STEP 2: Bind to the server.
+ In this example, the client binds anonymously to the server
+ (no DN or credentials are specified). */
+ rc = ldap_sasl_bind_s(ld, NULL, LDAP_SASL_SIMPLE, NULL, NULL, NULL, NULL);
+ if ( rc != LDAP_SUCCESS ) {
+ fprintf(stderr, "ldap_simple_bind_s: %s\n", ldap_err2string(rc));
+ return( 1 );
+ }
+
+ /* Print out an informational message. */
+ printf( "Searching the directory for entries\n"
+ " starting from the base DN %s\n"
+ " within the scope %d\n"
+ " matching the search filter %s...\n\n",
+ BASEDN, SCOPE, FILTER );
+
+ /* STEP 3: Perform the LDAP operations.
+ In this example, a simple search operation is performed.
+ The client iterates through each of the entries returned and
+ prints out the DN of each entry. */
+ rc = ldap_search_ext_s( ld, BASEDN, SCOPE, FILTER, NULL, 0,
+ NULL, NULL, NULL, 0, &result );
+ if ( rc != LDAP_SUCCESS ) {
+ fprintf(stderr, "ldap_search_ext_s: %s\n", ldap_err2string(rc));
+ return( 1 );
+ }
+ for ( e = ldap_first_entry( ld, result ); e != NULL;
+ e = ldap_next_entry( ld, e ) ) {
+ if ( (dn = ldap_get_dn( ld, e )) != NULL ) {
+ printf( "dn: %s\n", dn );
+ ldap_memfree( dn );
+ dn = NULL;
+ }
+ }
+ if( result != NULL ) {
+ ldap_msgfree( result );
+ result = NULL;
+ }
+
+ /* STEP 4: Disconnect from the server. */
+ ldap_unbind_ext_s( ld, NULL, NULL );
+ return( 0 );
+}