summaryrefslogtreecommitdiffstats
path: root/pki/base/tps/src/processor/RA_Processor.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'pki/base/tps/src/processor/RA_Processor.cpp')
-rw-r--r--pki/base/tps/src/processor/RA_Processor.cpp3506
1 files changed, 3506 insertions, 0 deletions
diff --git a/pki/base/tps/src/processor/RA_Processor.cpp b/pki/base/tps/src/processor/RA_Processor.cpp
new file mode 100644
index 000000000..a9947555b
--- /dev/null
+++ b/pki/base/tps/src/processor/RA_Processor.cpp
@@ -0,0 +1,3506 @@
+// --- 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 <stdlib.h>
+#include <string.h>
+#include <math.h>
+#include "plstr.h"
+#include "engine/RA.h"
+#include "main/Buffer.h"
+#include "main/Base.h"
+#include "main/Util.h"
+#include "main/RA_Session.h"
+#include "main/RA_Msg.h"
+#include "main/Login.h"
+#include "main/SecureId.h"
+#include "main/Util.h"
+#include "httpClient/httpc/http.h"
+#include "httpClient/httpc/request.h"
+#include "httpClient/httpc/response.h"
+#include "httpClient/httpc/engine.h"
+#include "processor/RA_Processor.h"
+#include "cms/HttpConnection.h"
+#include "cms/CertEnroll.h"
+#include "msg/RA_Status_Update_Request_Msg.h"
+#include "msg/RA_Status_Update_Response_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_ASQ_Request_Msg.h"
+#include "msg/RA_ASQ_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_Token_PDU_Request_Msg.h"
+#include "msg/RA_Token_PDU_Response_Msg.h"
+#include "apdu/Lifecycle_APDU.h"
+#include "apdu/Format_Muscle_Applet_APDU.h"
+#include "apdu/Initialize_Update_APDU.h"
+#include "apdu/Get_Version_APDU.h"
+#include "apdu/External_Authenticate_APDU.h"
+#include "apdu/Create_Object_APDU.h"
+#include "apdu/Get_Status_APDU.h"
+#include "apdu/Get_Data_APDU.h"
+#include "apdu/Set_Pin_APDU.h"
+#include "apdu/Read_Buffer_APDU.h"
+#include "apdu/Write_Object_APDU.h"
+#include "apdu/List_Objects_APDU.h"
+#include "apdu/Generate_Key_APDU.h"
+#include "apdu/List_Pins_APDU.h"
+#include "apdu/Create_Pin_APDU.h"
+#include "apdu/Put_Key_APDU.h"
+#include "apdu/Select_APDU.h"
+#include "apdu/APDU_Response.h"
+#include "channel/Secure_Channel.h"
+#include "main/Memory.h"
+
+#if 0
+#ifdef __cplusplus
+extern "C"
+{
+#endif
+#include "tus/tus_db.h"
+#ifdef __cplusplus
+}
+#endif
+#endif
+
+/**
+ * Constructs a base processor.
+ */
+RA_Processor::RA_Processor ()
+{
+ totalAvailableMemory = 0;
+ totalFreeMemory = 0;
+}
+
+
+/**
+ * Destructs processor.
+ */
+RA_Processor::~RA_Processor ()
+{
+}
+
+AuthenticationEntry *RA_Processor::GetAuthenticationEntry(
+ const char *prefix, const char * a_configname, const char *a_tokenType)
+{
+ AuthenticationEntry *auth = NULL;
+
+ if (!RA::GetConfigStore()->GetConfigAsBool(a_configname, false))
+ return NULL;
+
+ RA::Debug("RA_Enroll_Processor::AuthenticateUser",
+ "Authentication enabled");
+ char configname[256];
+ PR_snprintf((char *)configname, 256, "%s.%s.auth.id", prefix, a_tokenType);
+ const char *authid = RA::GetConfigStore()->GetConfigAsString(configname);
+ if (authid == NULL) {
+ goto loser;
+ }
+ auth = RA::GetAuth(authid);
+ return auth;
+loser:
+ return NULL;
+}
+
+
+void RA_Processor::StatusUpdate(RA_Session *a_session,
+ NameValueSet *a_extensions,
+ int a_status, const char *a_info)
+{
+ if (a_extensions != NULL) {
+ if (a_extensions->GetValue("statusUpdate") != NULL) {
+ StatusUpdate(a_session, a_status, a_info);
+ }
+ }
+}
+
+void RA_Processor::StatusUpdate(RA_Session *session,
+ int status, const char *info)
+{
+ RA_Status_Update_Request_Msg *status_update_request_msg = NULL;
+ RA_Status_Update_Response_Msg *status_update_response_msg = NULL;
+
+ RA::Debug(LL_PER_PDU, "RA_Processor::StatusUpdate",
+ "RA_Processor::StatusUpdate");
+
+ status_update_request_msg = new RA_Status_Update_Request_Msg(
+ status, info);
+ session->WriteMsg(status_update_request_msg);
+
+ RA::Debug(LL_PER_PDU, "RA_Processor::StatusUpdate",
+ "Sent status_update_msg");
+
+ status_update_response_msg = (RA_Status_Update_Response_Msg *)
+ session->ReadMsg();
+ if (status_update_response_msg == NULL)
+ {
+ RA::Error(LL_PER_PDU, "RA_Processor::StatusUpdate",
+ "No Status Update Response Msg Received");
+ goto loser;
+ }
+ if (status_update_response_msg->GetType() != MSG_STATUS_UPDATE_RESPONSE) {
+ RA::Error("Secure_Channel::StatusUpdate",
+ "Invalid Msg Type");
+ goto loser;
+ }
+
+loser:
+ if( status_update_request_msg != NULL ) {
+ delete status_update_request_msg;
+ status_update_request_msg = NULL;
+ }
+ if( status_update_response_msg != NULL ) {
+ delete status_update_response_msg;
+ status_update_response_msg = NULL;
+ }
+
+} /* StatusUpdate */
+
+/**
+ * Requests login ID and password from user.
+ */
+AuthParams *RA_Processor::RequestExtendedLogin(RA_Session *session,
+ int invalid_pw, int blocked,
+ char **parameters, int len, char *title, char *description)
+{
+ RA_Extended_Login_Request_Msg *login_request_msg = NULL;
+ RA_Extended_Login_Response_Msg *login_response_msg = NULL;
+ AuthParams *login = NULL;
+ AuthParams *c = NULL;
+ int i = 0;
+
+ RA::Debug(LL_PER_PDU, "RA_Processor::RequestExtendedLogin",
+ "RA_Processor::RequestExtendedLogin %s %s",
+ title, description);
+
+ login_request_msg = new RA_Extended_Login_Request_Msg(
+ invalid_pw, blocked, parameters, len, title, description);
+ session->WriteMsg(login_request_msg);
+ RA::Debug(LL_PER_PDU, "RA_Processor::RequestExtendedLogin",
+ "Sent login_request_msg");
+
+ login_response_msg = (RA_Extended_Login_Response_Msg *)
+ session->ReadMsg();
+ if (login_response_msg == NULL)
+ {
+ RA::Error(LL_PER_PDU, "RA_Processor::RequestExtendedLogin",
+ "No Extended Login Response Msg Received");
+ goto loser;
+ }
+ if (login_response_msg->GetType() != MSG_EXTENDED_LOGIN_RESPONSE) {
+ RA::Error("Secure_Channel::Login_Request",
+ "Invalid Msg Type");
+ goto loser;
+ }
+
+ login = new AuthParams();
+ c = login_response_msg->GetAuthParams();
+ for (i = 0; i < c->Size(); i++) {
+ login->Add(c->GetNameAt(i), c->GetValue(c->GetNameAt(i)));
+ }
+
+loser:
+ if( login_request_msg != NULL ) {
+ delete login_request_msg;
+ login_request_msg = NULL;
+ }
+ if( login_response_msg != NULL ) {
+ delete login_response_msg;
+ login_response_msg = NULL;
+ }
+
+ return login;
+} /* RequestExtendedLogin */
+
+/**
+ * Requests login ID and password from user.
+ */
+AuthParams *RA_Processor::RequestLogin(RA_Session *session,
+ int invalid_pw, int blocked)
+{
+ RA_Login_Request_Msg *login_request_msg = NULL;
+ RA_Login_Response_Msg *login_response_msg = NULL;
+ AuthParams *login = NULL;
+
+ RA::Debug(LL_PER_PDU, "RA_Processor::Login_Request",
+ "RA_Processor::Login_Request");
+
+ login_request_msg = new RA_Login_Request_Msg(
+ invalid_pw, blocked);
+ session->WriteMsg(login_request_msg);
+ RA::Debug(LL_PER_PDU, "RA_Processor::Login_Request",
+ "Sent login_request_msg");
+
+ login_response_msg = (RA_Login_Response_Msg *)
+ session->ReadMsg();
+ if (login_response_msg == NULL)
+ {
+ RA::Error(LL_PER_PDU, "RA_Processor::Login_Request",
+ "No Login Response Msg Received");
+ goto loser;
+ }
+ if (login_response_msg->GetType() != MSG_LOGIN_RESPONSE) {
+ RA::Error("Secure_Channel::Login_Request",
+ "Invalid Msg Type");
+ goto loser;
+ }
+ login = new AuthParams();
+ login->Add("UID", login_response_msg->GetUID());
+ login->Add("PASSWORD", login_response_msg->GetPassword());
+
+loser:
+ if( login_request_msg != NULL ) {
+ delete login_request_msg;
+ login_request_msg = NULL;
+ }
+ if( login_response_msg != NULL ) {
+ delete login_response_msg;
+ login_response_msg = NULL;
+ }
+
+ return login;
+} /* RequestLogin */
+
+/**
+ * Upgrade the applet to the current session with the new version.
+ */
+int RA_Processor::UpgradeApplet(RA_Session *session, char *prefix, char *tokenType, BYTE major_version, BYTE minor_version, const char *new_version, const char *applet_dir, SecurityLevel security_level, const char *connid,
+ NameValueSet *extensions,
+ int start_progress,
+ int end_progress,
+ char **key_version)
+{
+ Buffer *NetKeyAID = RA::GetConfigStore()->GetConfigAsBuffer(
+ RA::CFG_APPLET_NETKEY_INSTANCE_AID,
+ RA::CFG_DEF_NETKEY_INSTANCE_AID);
+ Buffer *OldAAID = RA::GetConfigStore()->GetConfigAsBuffer(
+ RA::CFG_APPLET_NETKEY_OLD_INSTANCE_AID,
+ RA::CFG_DEF_NETKEY_OLD_INSTANCE_AID);
+ Buffer *OldPAID = RA::GetConfigStore()->GetConfigAsBuffer(
+ RA::CFG_APPLET_NETKEY_OLD_FILE_AID,
+ RA::CFG_DEF_NETKEY_OLD_FILE_AID);
+ Buffer *NetKeyPAID = RA::GetConfigStore()->GetConfigAsBuffer(
+ RA::CFG_APPLET_NETKEY_FILE_AID,
+ RA::CFG_DEF_NETKEY_FILE_AID);
+ Buffer *PIN = RA::GetConfigStore()->GetConfigAsBuffer(
+ RA::CFG_APPLET_SO_PIN,
+ RA::CFG_DEF_APPLET_SO_PIN);
+ Buffer empty;
+ PRFileDesc *f = NULL;
+ char path[4096];
+ char configname[4096];
+ PRFileInfo info;
+ PRStatus status;
+ int rc = 0;
+ Secure_Channel *channel = NULL;
+ int size_to_send = 0;
+ char *dataf = NULL;
+ int block_size;
+ BYTE refControl;
+ int count;
+ Buffer programFile;
+ Buffer tag;
+ Buffer length;
+ Buffer tbsProgramFile;
+ unsigned int totalLen;
+ int num_loops;
+ float progress_block_size;
+ int x_blocksize;
+ int instance_size;
+ int applet_memory_size;
+ int defKeyVer;
+ int defKeyIndex;
+ char *ext;
+
+ if (applet_dir == NULL) {
+ RA::Error(LL_PER_PDU, "RA_Processor::UpgradeApplet",
+ "Failed to get upgrade.directory");
+ goto loser;
+ }
+ sprintf(configname, "general.applet_ext");
+ ext = (char*)RA::GetConfigStore()->GetConfigAsString(configname, "ijc");
+ sprintf(path, "%s/%s.%s", applet_dir, new_version, ext);
+ RA::Debug("RA_Processor::UpgradeApplet", "path = %s", path);
+ status = PR_GetFileInfo(path, &info);
+ if (status != PR_SUCCESS) {
+ RA::Error(LL_PER_PDU, "RA_Processor::UpgradeApplet",
+ "Failed to get file info");
+ goto loser;
+ }
+ f = PR_Open(path, PR_RDONLY, 400);
+ if (f == NULL) {
+ RA::Error(LL_PER_PDU, "RA_Processor::UpgradeApplet",
+ "Failed to open '%s'", path);
+ goto loser;
+ }
+ dataf = (char *)malloc(info.size);
+ PR_Read(f, dataf, info.size);
+ if( f != NULL ) {
+ PR_Close( f );
+ f = NULL;
+ }
+
+ /* Select Applet - Select Card manager */
+ SelectCardManager(session, prefix, tokenType);
+
+ PR_snprintf((char *)configname, 256,"channel.blockSize");
+ x_blocksize = RA::GetConfigStore()->GetConfigAsInt(configname, 0xf8);
+ PR_snprintf((char *)configname, 256,"channel.instanceSize");
+ instance_size = RA::GetConfigStore()->GetConfigAsInt(configname, 18000);
+
+ PR_snprintf((char *)configname, 256,"channel.appletMemorySize");
+
+ applet_memory_size = RA::GetConfigStore()->GetConfigAsInt(configname, 5000);
+
+ PR_snprintf((char *)configname, 256,"channel.defKeyVersion");
+ defKeyVer = RA::GetConfigStore()->GetConfigAsInt(configname, 0x0);
+ PR_snprintf((char *)configname, 256,"channel.defKeyIndex");
+ defKeyIndex = RA::GetConfigStore()->GetConfigAsInt(configname, 0x0);
+ channel = SetupSecureChannel(session, defKeyVer, defKeyIndex, security_level, connid);
+ if (channel == NULL) {
+ RA::Error(LL_PER_PDU, "RA_Processor::UpgradeApplet",
+ "channel creation failure");
+ rc = -1;
+ goto loser;
+ }
+
+ // get keyVersion
+ if (channel != NULL) {
+ *key_version = Util::Buffer2String(channel->GetKeyInfoData());
+ }
+
+ if (channel->ExternalAuthenticate() == -1) {
+ RA::Error(LL_PER_PDU, "RA_Processor::UpgradeApplet",
+ "failed to external authenticate during upgrade");
+ goto loser;
+ }
+
+ /* Delete File - Delete 627601ff000000 (CoolKey Instance) */
+ rc = channel->DeleteFileX(session, NetKeyAID);
+ if (rc != 1) {
+ /* it is ok to fail to delete file */
+ RA::DebugBuffer(LL_PER_PDU, "RA_Processor::UpgradeApplet",
+ "Warning: failed to delete file", NetKeyAID);
+ }
+
+ if (RA::GetConfigStore()->GetConfigAsBool(RA::CFG_APPLET_DELETE_NETKEY_OLD, true)) {
+ /* Delete File - Delete a00000000101 */
+ rc = channel->DeleteFileX(session, OldAAID);
+ if (rc != 1) {
+ /* it is ok to fail to delete file */
+ RA::DebugBuffer(LL_PER_PDU, "RA_Processor::UpgradeApplet",
+ "Warning: failed to delete file", OldAAID);
+ }
+ /* Delete File - Delete a000000001 */
+ rc = channel->DeleteFileX(session, OldPAID);
+ if (rc != 1) {
+ RA::DebugBuffer(LL_PER_PDU, "RA_Processor::UpgradeApplet",
+ "Warning: failed to delete file", OldPAID);
+ }
+ }
+
+ /* Delete File - Delete 627601ff0000 */
+ channel->DeleteFileX(session, NetKeyPAID);
+
+ /* Install Applet - Install applet instance */
+ channel->InstallLoad(session,
+ *NetKeyPAID,
+ empty,
+ info.size);
+
+ /* Multiple Load Program File - Load 627601ff0000 */
+ programFile = Buffer ((BYTE *)dataf, info.size);
+ if( dataf != NULL ) {
+ free( dataf );
+ dataf = NULL;
+ }
+ tag = Buffer(1, 0xC4);
+ tbsProgramFile = tag + length + programFile;
+ totalLen = tbsProgramFile.size();
+ if( programFile.size() < 128 ) {
+ length = Buffer(1, programFile.size());
+ } else if( programFile.size() <= 255 ) {
+ length = Buffer(2, 0);
+ ((BYTE*)length)[0] = 0x81;
+ ((BYTE*)length)[1] = programFile.size();
+ } else {
+ length = Buffer(3, 0);
+ ((BYTE*)length)[0] = 0x82;
+ ((BYTE*)length)[1] = (programFile.size() >> 8) & 0xff;
+ ((BYTE*)length)[2] = programFile.size() & 0xff;
+ }
+ tbsProgramFile = tag + length + programFile;
+ totalLen = tbsProgramFile.size();
+
+ size_to_send = totalLen;
+ if (security_level == SECURE_MSG_MAC_ENC) {
+ // need leave room for possible encryption padding
+ block_size = x_blocksize - 0x10;
+ } else {
+ block_size = x_blocksize - 8;
+ }
+
+ // rough number is good enough
+ num_loops = size_to_send / block_size;
+ progress_block_size = (float) (end_progress - start_progress) / num_loops;
+
+ count = 0;
+ refControl = 0x00; // intermediate block
+ do {
+ if (size_to_send < block_size) {
+ block_size = size_to_send;
+ // last block
+ refControl = 0x80;
+ }
+ if (size_to_send - block_size == 0) {
+ // last block
+ refControl = 0x80;
+ }
+ Buffer d = tbsProgramFile.substr(totalLen - size_to_send, block_size);
+ channel->LoadFile(session, (BYTE)refControl, (BYTE)count, &d);
+
+ size_to_send -= block_size;
+
+ // send status update to the client
+ if (extensions != NULL &&
+ extensions->GetValue("statusUpdate") != NULL) {
+ StatusUpdate(session,
+ start_progress + (count * progress_block_size) /* progress */,
+ "PROGRESS_APPLET_BLOCK");
+ }
+ count++;
+ } while (size_to_send > 0);
+
+
+ /* Install Applet - Install applet instance */
+ channel->InstallApplet(session,
+ *NetKeyPAID,
+ *NetKeyAID,
+ 0 /* appPrivileges */,
+ instance_size /* instanceSize */,
+ applet_memory_size /* appletMemorySize */);
+
+ /* Select File - Select 627601ff000000 */
+ SelectApplet(session, 0x04, 0x00, NetKeyAID);
+
+ rc = 1;
+loser:
+ if( NetKeyAID != NULL ) {
+ delete NetKeyAID;
+ NetKeyAID = NULL;
+ }
+ if( OldAAID != NULL ) {
+ delete OldAAID;
+ OldAAID = NULL;
+ }
+ if( OldPAID != NULL ) {
+ delete OldPAID;
+ OldPAID = NULL;
+ }
+ if( NetKeyPAID != NULL ) {
+ delete NetKeyPAID;
+ NetKeyPAID = NULL;
+ }
+ if( PIN != NULL ) {
+ delete PIN;
+ PIN = NULL;
+ }
+ if( channel != NULL ) {
+ delete channel;
+ channel = NULL;
+ }
+ if( dataf != NULL ) {
+ free( dataf );
+ dataf = NULL;
+ }
+
+ return rc;
+}
+
+char *RA_Processor::MapPattern(NameValueSet *nv, char *pattern)
+{
+ int i=0,x=0,j=0,z=0;
+ unsigned int q = 0;
+ char token[4096];
+ char result[4096];
+ char *value;
+
+ if (pattern == NULL)
+ return NULL;
+ i = strlen(pattern);
+ for (x = 0; x < i; x++) {
+ if (pattern[x] == '$') {
+ if (pattern[x+1] == '$') {
+ result[z] = pattern[x];
+ z++;
+ x++;
+ } else {
+ x++;
+ j = 0;
+ while (pattern[x] != '$') {
+ token[j] = pattern[x];
+ j++;
+ x++;
+ }
+ token[j] = '\0';
+ value = nv->GetValue(token);
+ if (value != NULL) {
+ for (q = 0; q < strlen(value); q++) {
+ result[z] = value[q];
+ z++;
+ }
+
+ }
+ }
+ } else {
+ result[z] = pattern[x];
+ z++;
+ }
+ }
+ result[z] = '\0';
+
+ return PL_strdup(result);
+}
+
+int RA_Processor::FormatMuscleApplet(RA_Session *session,
+ unsigned short memSize,
+ Buffer &PIN0, BYTE pin0Tries,
+ Buffer &unblockPIN0, BYTE unblock0Tries,
+ Buffer &PIN1, BYTE pin1Tries,
+ Buffer &unblockPIN1, BYTE unblock1Tries,
+ unsigned short objCreationPermissions,
+ unsigned short keyCreationPermissions,
+ unsigned short pinCreationPermissions)
+{
+ int rc = 0;
+ APDU_Response *format_response = NULL;
+ RA_Token_PDU_Request_Msg *format_request_msg = NULL;
+ RA_Token_PDU_Response_Msg *format_response_msg = NULL;
+ Format_Muscle_Applet_APDU *format_apdu = NULL;
+ // Buffer *mac = NULL;
+
+ RA::Debug(LL_PER_PDU, "RA_Processor::FormatMuscle",
+ "RA_Processor::FormatMuscle");
+
+ format_apdu = new Format_Muscle_Applet_APDU(memSize, PIN0, pin0Tries,
+ unblockPIN0, unblock0Tries,
+ PIN1, pin1Tries,
+ unblockPIN1, unblock1Tries,
+ objCreationPermissions,
+ keyCreationPermissions,
+ pinCreationPermissions);
+ format_request_msg =
+ new RA_Token_PDU_Request_Msg(format_apdu);
+ session->WriteMsg(format_request_msg);
+
+ RA::Debug(LL_PER_PDU, "RA_Processor::FormatMuscle",
+ "Sent format_request_msg");
+
+ format_response_msg = (RA_Token_PDU_Response_Msg *)
+ session->ReadMsg();
+ if (format_response_msg == NULL)
+ {
+ RA::Error(LL_PER_PDU, "RA_Processor::FormatMuscle",
+ "No Token PDU Response Msg Received");
+ goto loser;
+ }
+ if (format_response_msg->GetType() != MSG_TOKEN_PDU_RESPONSE) {
+ RA::Error(LL_PER_PDU, "RA_Processor::FormatMuscle",
+ "Invalid Message Type");
+ goto loser;
+ }
+ format_response = format_response_msg->GetResponse();
+ if (!(format_response->GetSW1() == 0x90 &&
+ format_response->GetSW2() == 0x00)) {
+ RA::Error(LL_PER_PDU, "RA_Processor::FormatMuscle",
+ "Bad Response");
+ goto loser;
+ }
+ rc = 1;
+
+loser:
+ if( format_request_msg != NULL ) {
+ delete format_request_msg;
+ format_request_msg = NULL;
+ }
+ if( format_response_msg != NULL ) {
+ delete format_response_msg;
+ format_response_msg = NULL;
+ }
+
+ return rc;
+}
+
+/**
+ * Determine the Token Type. The user can set up mapping rules in the
+ * config file which allow different operations depending on the
+ * CUID, applet version, ATR, etc.
+ */
+bool RA_Processor::GetTokenType(const char *prefix, int major_version, int minor_version, const char *cuid, const char *msn, NameValueSet *extensions,
+ RA_Status &o_status /* out */, const char *&o_tokenType /* out */)
+{
+ const char *e_tokenATR = NULL;
+ const char *tokenATR = NULL;
+ const char *e_tokenType = NULL;
+ const char *tokenType = NULL;
+ const char *tokenCUIDStart = NULL;
+ const char *tokenCUIDEnd = NULL;
+ const char *targetTokenType = NULL;
+ const char *majorVersion = NULL;
+ const char *minorVersion = NULL;
+ const char *order = NULL;
+ char *order_x = NULL;
+ const char *mappingId = NULL;
+ char configname[256];
+ int start_pos = 0, done = 0;
+ unsigned int end_pos = 0;
+ const char *cuid_x = NULL;
+ int rc=0;
+
+ cuid_x = cuid;
+
+ sprintf(configname, "%s.mapping.order", prefix);
+ order = RA::GetConfigStore()->GetConfigAsString(configname);
+ if (order == NULL) {
+ RA::Error("RA_Processor::GetTokenType", "Token type is not found");
+ o_status = STATUS_ERROR_DEFAULT_TOKENTYPE_NOT_FOUND;
+ RA::Debug(LL_PER_PDU, "RA_Processor::GetTokenType",
+ "cannot find config ", configname);
+ return false; /* no mapping found */
+ }
+
+ RA::Debug(LL_PER_PDU, "RA_Processor::GetTokenType",
+ "Starting:");
+ order_x = PL_strdup(order);
+
+ start_pos = 0;
+ end_pos = 0;
+ done = 0;
+ while (1)
+ {
+ if (done) {
+ break;
+ }
+ end_pos = start_pos;
+ while ((end_pos < strlen(order)) && (order_x[end_pos] != ',')) {
+ end_pos++;
+ }
+ if (end_pos < strlen(order)) {
+ order_x[end_pos] = '\0';
+ done = 0;
+ } else {
+ done = 1;
+ }
+ mappingId = &order_x[start_pos];
+ RA::Debug(LL_PER_PDU, "RA_Processor::GetTokenType",
+ "mappingId='%s'", mappingId);
+
+ start_pos = end_pos + 1;
+
+ sprintf(configname, "%s.mapping.%s.target.tokenType", prefix,
+ mappingId);
+ targetTokenType = RA::GetConfigStore()->GetConfigAsString(configname);
+
+
+ if (targetTokenType == NULL) {
+ break;
+ }
+ sprintf(configname, "%s.mapping.%s.filter.tokenType", prefix,
+ mappingId);
+ tokenType = RA::GetConfigStore()->GetConfigAsString(configname);
+
+ RA::Debug(LL_PER_PDU, "RA_Processor::GetTokenType",
+ "tokenType: %s",tokenType);
+
+ if (tokenType != NULL && strlen(tokenType) > 0) {
+ if (extensions == NULL) {
+ continue; /* mapping not matched, next mapping */
+ }
+ e_tokenType = extensions->GetValue("tokenType");
+ if (e_tokenType == NULL) {
+ continue; /* mapping not matched, next mapping */
+ }
+ if (strcmp(tokenType, e_tokenType) != 0) {
+ continue; /* mapping not matched, next mapping */
+ }
+ }
+ sprintf(configname, "%s.mapping.%s.filter.tokenATR", prefix,
+ mappingId);
+ tokenATR = RA::GetConfigStore()->GetConfigAsString(configname);
+ if (tokenATR != NULL && strlen(tokenATR) > 0) {
+ if (extensions == NULL) {
+ continue; /* mapping not matched, next mapping */
+ }
+ e_tokenATR = extensions->GetValue("tokenATR");
+ if (e_tokenATR == NULL) {
+ continue; /* mapping not matched, next mapping */
+ }
+ if (strcmp(tokenATR, e_tokenATR) != 0) {
+ continue; /* mapping not matched, next mapping */
+ }
+ }
+ sprintf(configname, "%s.mapping.%s.filter.tokenCUID.start", prefix,
+ mappingId);
+ tokenCUIDStart = RA::GetConfigStore()->GetConfigAsString(configname);
+ if (tokenCUIDStart != NULL && strlen(tokenCUIDStart) > 0) {
+ if (cuid_x == NULL) {
+ continue; /* mapping not matched, next mapping */
+ }
+ RA::Debug(LL_PER_PDU, "RA_Processor::GetTokenType",
+ "cuid_x=%s tokenCUIDStart=%s %d", cuid_x, tokenCUIDStart,
+ PL_strcasecmp(cuid_x, tokenCUIDStart));
+
+ if(strlen(tokenCUIDStart) != 20)
+ {
+ RA::Debug(LL_PER_PDU, "RA_Processor::GetTokenType",
+ "Invalid tokenCUIDStart: %s",tokenCUIDStart);
+ continue;
+ }
+
+ char *pend = NULL;
+ rc = strtol((const char *) tokenCUIDStart, &pend, 16);
+
+ if(*pend != '\0')
+ {
+ RA::Debug(LL_PER_PDU, "RA_Processor::GetTokenType",
+ "Invalid tokenCUIDStart: %s",tokenCUIDStart);
+
+ continue;
+ }
+
+ if (PL_strcasecmp(cuid_x, tokenCUIDStart) < 0) {
+ continue; /* mapping not matched, next mapping */
+ }
+ }
+ sprintf(configname, "%s.mapping.%s.filter.tokenCUID.end", prefix,
+ mappingId);
+ tokenCUIDEnd = RA::GetConfigStore()->GetConfigAsString(configname);
+ if (tokenCUIDEnd != NULL && strlen(tokenCUIDEnd) > 0) {
+ if (cuid_x == NULL) {
+ continue; /* mapping not matched, next mapping */
+ }
+ RA::Debug(LL_PER_PDU, "RA_Processor::GetTokenType",
+ "cuid_x=%s tokenCUIDEnd=%s %d", cuid_x, tokenCUIDEnd,
+ PL_strcasecmp(cuid_x, tokenCUIDEnd));
+
+ if(strlen(tokenCUIDEnd) != 20)
+ {
+ RA::Debug(LL_PER_PDU, "RA_Processor::GetTokenType",
+ "Invalid tokenCUIDEnd: %s",tokenCUIDEnd);
+ continue;
+ }
+
+ char *pend = NULL;
+ rc = strtol((const char *) tokenCUIDEnd, &pend, 16);
+
+ if(*pend != '\0')
+ {
+
+ RA::Debug(LL_PER_PDU, "RA_Processor::GetTokenType",
+ "Invalid tokenCUIDEnd: %s",tokenCUIDEnd);
+
+ continue;
+ }
+
+ if (PL_strcasecmp(cuid_x, tokenCUIDEnd) > 0) {
+ continue; /* mapping not matched, next mapping */
+ }
+ }
+ sprintf(configname, "%s.mapping.%s.filter.appletMajorVersion",
+ prefix, mappingId);
+ majorVersion = RA::GetConfigStore()->GetConfigAsString(configname);
+ if (majorVersion != NULL && strlen(majorVersion) > 0) {
+ if (major_version != atoi(majorVersion)) {
+ continue; /* mapping not matched, next mapping */
+ }
+ }
+ sprintf(configname, "%s.mapping.%s.filter.appletMinorVersion",
+ prefix, mappingId);
+ minorVersion = RA::GetConfigStore()->GetConfigAsString(configname);
+ if (minorVersion != NULL && strlen(minorVersion) > 0) {
+ if (minor_version != atoi(minorVersion)) {
+ continue; /* mapping not matched, next mapping */
+ }
+ }
+
+ if( order_x != NULL ) {
+ PL_strfree( order_x );
+ order_x = NULL;
+ }
+ RA::Debug("RA_Processor::GetTokenType",
+ "Selected Token type is '%s'", targetTokenType);
+ o_tokenType = targetTokenType;
+ return true;
+ }
+
+
+ if( order_x != NULL ) {
+ PL_strfree( order_x );
+ order_x = NULL;
+ }
+ RA::Error("RA_Processor::GetTokenType", "Token type is not found");
+ o_status = STATUS_ERROR_DEFAULT_TOKENTYPE_NOT_FOUND;
+
+ return false;
+}
+
+int RA_Processor::SelectCardManager(RA_Session *session, char *prefix, char *tokenType)
+{
+ char configname[256];
+ int rc;
+ PR_snprintf((char *)configname, 256, "%s.%s.cardmgr_instance", prefix, tokenType);
+ const char *cardmgr_instance =
+ RA::GetConfigStore()->GetConfigAsString(configname);
+ Buffer *CardManagerAID = RA::GetConfigStore()->GetConfigAsBuffer(
+ cardmgr_instance, RA::CFG_DEF_CARDMGR_INSTANCE_AID);
+ rc = SelectApplet(session, 0x04, 0x00, CardManagerAID);
+ if( CardManagerAID != NULL ) {
+ delete CardManagerAID;
+ CardManagerAID = NULL;
+ }
+ return rc;
+}
+
+/**
+ * GetData
+ */
+Buffer *RA_Processor::GetData(RA_Session *session)
+{
+ Buffer data;
+ Buffer *status = NULL;
+ APDU_Response *get_data_response = NULL;
+ RA_Token_PDU_Request_Msg *get_data_request_msg = NULL;
+ RA_Token_PDU_Response_Msg *get_data_response_msg = NULL;
+ Get_Data_APDU *get_data_apdu = NULL;
+ Buffer get_status_data;
+
+ get_data_apdu =
+ new Get_Data_APDU();
+ get_data_request_msg =
+ new RA_Token_PDU_Request_Msg(get_data_apdu);
+ session->WriteMsg(get_data_request_msg);
+ RA::Debug(LL_PER_PDU, "RA_Processor::GetData",
+ "Sent get_data_request_msg");
+
+ get_data_response_msg = (RA_Token_PDU_Response_Msg *)
+ session->ReadMsg();
+ if (get_data_response_msg == NULL)
+ {
+ RA::Error(LL_PER_PDU, "RA_Processor::GetData",
+ "No Token PDU Response Msg Received");
+ goto loser;
+ }
+ if (get_data_response_msg->GetType() != MSG_TOKEN_PDU_RESPONSE) {
+ RA::Error(LL_PER_PDU, "RA_Processor::GetData",
+ "Invalid Message Type");
+ goto loser;
+ }
+ get_data_response =
+ get_data_response_msg->GetResponse();
+ if (get_data_response == NULL) {
+ RA::Error(LL_PER_PDU, "Secure_Channel::GetData",
+ "No Response From Token");
+ goto loser;
+ }
+ data = get_data_response->GetData();
+
+ if (!(get_data_response->GetSW1() == 0x90 &&
+ get_data_response->GetSW2() == 0x00)) {
+ RA::Error(LL_PER_PDU, "RA_Processor::GetData",
+ "Bad Response");
+ goto loser;
+ }
+
+ status = new Buffer(data.substr(0, data.size()));
+
+loser:
+
+ if( get_data_request_msg != NULL ) {
+ delete get_data_request_msg;
+ get_data_request_msg = NULL;
+ }
+ if( get_data_response_msg != NULL ) {
+ delete get_data_response_msg;
+ get_data_response_msg = NULL;
+ }
+
+ return status;
+}
+
+Buffer *RA_Processor::ListObjects(RA_Session *session, BYTE seq)
+{
+ Buffer data;
+ Buffer *status = NULL;
+ APDU_Response *response = NULL;
+ RA_Token_PDU_Request_Msg *request_msg = NULL;
+ RA_Token_PDU_Response_Msg *response_msg = NULL;
+ List_Objects_APDU *list_objects_apdu = NULL;
+ Buffer get_status_data;
+
+ list_objects_apdu =
+ new List_Objects_APDU(seq);
+ request_msg =
+ new RA_Token_PDU_Request_Msg(list_objects_apdu);
+ session->WriteMsg(request_msg);
+ RA::Debug(LL_PER_PDU, "RA_Processor::ListObjects",
+ "Sent request_msg");
+
+ response_msg = (RA_Token_PDU_Response_Msg *)
+ session->ReadMsg();
+ if (response_msg == NULL)
+ {
+ RA::Error(LL_PER_PDU, "RA_Processor::ListObjects",
+ "No Token PDU Response Msg Received");
+ goto loser;
+ }
+ if (response_msg->GetType() != MSG_TOKEN_PDU_RESPONSE) {
+ RA::Error(LL_PER_PDU, "RA_Processor::ListObjects",
+ "Invalid Message Type");
+ goto loser;
+ }
+ response = response_msg->GetResponse();
+ if (response == NULL) {
+ RA::Error(LL_PER_PDU, "Secure_Channel::ListObjects",
+ "No Response From Token");
+ goto loser;
+ }
+
+ if (!(response->GetSW1() == 0x90 &&
+ response->GetSW2() == 0x00)) {
+ // RA::Error(LL_PER_PDU, "RA_Processor::ListObjects",
+ // "Bad Response");
+ goto loser;
+ }
+
+ data = response->GetData();
+
+ status = new Buffer(data.substr(0, data.size()));
+
+loser:
+
+ if( request_msg != NULL ) {
+ delete request_msg;
+ request_msg = NULL;
+ }
+ if( response_msg != NULL ) {
+ delete response_msg;
+ response_msg = NULL;
+ }
+
+ return status;
+}
+
+/**
+ * GetStatus
+ */
+Buffer *RA_Processor::GetStatus(RA_Session *session, BYTE p1, BYTE p2)
+{
+ Buffer data;
+ Buffer *status = NULL;
+ APDU_Response *get_status_response = NULL;
+ RA_Token_PDU_Request_Msg *get_status_request_msg = NULL;
+ RA_Token_PDU_Response_Msg *get_status_response_msg = NULL;
+ Get_Status_APDU *get_status_apdu = NULL;
+ Buffer get_status_data;
+
+ get_status_apdu =
+ new Get_Status_APDU();
+ get_status_request_msg =
+ new RA_Token_PDU_Request_Msg(get_status_apdu);
+ session->WriteMsg(get_status_request_msg);
+ RA::Debug(LL_PER_PDU, "RA_Processor::GetStatus",
+ "Sent get_status_request_msg");
+
+ get_status_response_msg = (RA_Token_PDU_Response_Msg *)
+ session->ReadMsg();
+ if (get_status_response_msg == NULL)
+ {
+ RA::Error(LL_PER_PDU, "RA_Processor::GetStatus",
+ "No Token PDU Response Msg Received");
+ goto loser;
+ }
+ if (get_status_response_msg->GetType() != MSG_TOKEN_PDU_RESPONSE) {
+ RA::Error(LL_PER_PDU, "RA_Processor::GetStatus",
+ "Invalid Message Type");
+ goto loser;
+ }
+ get_status_response =
+ get_status_response_msg->GetResponse();
+ if (get_status_response == NULL) {
+ RA::Error(LL_PER_PDU, "Secure_Channel::GetStatus",
+ "No Response From Token");
+ goto loser;
+ }
+ data = get_status_response->GetData();
+
+ if (!(get_status_response->GetSW1() == 0x90 &&
+ get_status_response->GetSW2() == 0x00)) {
+ RA::Error(LL_PER_PDU, "RA_Processor::GetStatus",
+ "Bad Response");
+ goto loser;
+ }
+
+ status = new Buffer(data.substr(0, data.size()));
+
+loser:
+
+ if( get_status_request_msg != NULL ) {
+ delete get_status_request_msg;
+ get_status_request_msg = NULL;
+ }
+ if( get_status_response_msg != NULL ) {
+ delete get_status_response_msg;
+ get_status_response_msg = NULL;
+ }
+
+ return status;
+}
+
+int RA_Processor::CreatePin(RA_Session *session, BYTE pin_number,
+ BYTE max_retries, char *pin)
+{
+ int rc = -1;
+ Create_Pin_APDU *create_pin_apdu = NULL;
+ APDU_Response *response = NULL;
+ RA_Token_PDU_Request_Msg *token_pdu_request_msg = NULL;
+ RA_Token_PDU_Response_Msg *token_pdu_response_msg = NULL;
+ Buffer *mac = NULL;
+
+ RA::Debug("Secure_Channel::IsPinPresent",
+ "Secure_Channel::IsPinPresent");
+ Buffer pin_buffer = Buffer((BYTE*)pin, strlen(pin));
+ create_pin_apdu = new Create_Pin_APDU(pin_number, max_retries,
+ pin_buffer);
+
+ /*
+ mac = ComputeAPDUMac(set_pin_apdu);
+ set_pin_apdu->SetMAC(*mac);
+ */
+ token_pdu_request_msg = new RA_Token_PDU_Request_Msg(
+ create_pin_apdu);
+ session->WriteMsg(token_pdu_request_msg);
+ RA::Debug("Secure_Channel::CreatePin",
+ "Sent token_pdu_request_msg");
+
+ token_pdu_response_msg = (RA_Token_PDU_Response_Msg *)
+ session->ReadMsg();
+ if (token_pdu_response_msg == NULL)
+ {
+ RA::Error("Secure_Channel::CreatePin",
+ "No Token PDU Response Msg Received");
+ goto loser;
+ }
+ if (token_pdu_response_msg->GetType() != MSG_TOKEN_PDU_RESPONSE) {
+ RA::Error(LL_PER_PDU, "RA_Processor::CreatePin",
+ "Invalid Message Type");
+ goto loser;
+ }
+ response = token_pdu_response_msg->GetResponse();
+ if (response == NULL) {
+ RA::Error("Secure_Channel::CreatePin",
+ "No Response From Token");
+ goto loser;
+ }
+
+ rc = 1;
+loser:
+ if( mac != NULL ) {
+ delete mac;
+ mac = NULL;
+ }
+ if( token_pdu_request_msg != NULL ) {
+ delete token_pdu_request_msg;
+ token_pdu_request_msg = NULL;
+ }
+ if( token_pdu_response_msg != NULL ) {
+ delete token_pdu_response_msg;
+ token_pdu_response_msg = NULL;
+ }
+
+ return rc;
+}
+int RA_Processor::IsPinPresent(RA_Session *session, BYTE pin_number)
+{
+ int rc = -1;
+ Buffer data;
+ List_Pins_APDU *list_pins_apdu = NULL;
+ APDU_Response *response = NULL;
+ RA_Token_PDU_Request_Msg *token_pdu_request_msg = NULL;
+ RA_Token_PDU_Response_Msg *token_pdu_response_msg = NULL;
+ Buffer *mac = NULL;
+
+ RA::Debug("Secure_Channel::IsPinPresent",
+ "Secure_Channel::IsPinPresent");
+ list_pins_apdu = new List_Pins_APDU(2);
+
+ /*
+ mac = ComputeAPDUMac(set_pin_apdu);
+ set_pin_apdu->SetMAC(*mac);
+ */
+ token_pdu_request_msg = new RA_Token_PDU_Request_Msg(
+ list_pins_apdu);
+ session->WriteMsg(token_pdu_request_msg);
+ RA::Debug("Secure_Channel::IsPinPresent",
+ "Sent token_pdu_request_msg");
+
+ token_pdu_response_msg = (RA_Token_PDU_Response_Msg *)
+ session->ReadMsg();
+ if (token_pdu_response_msg == NULL)
+ {
+ RA::Error("Secure_Channel::IsPinReset",
+ "No Token PDU Response Msg Received");
+ goto loser;
+ }
+ if (token_pdu_response_msg->GetType() != MSG_TOKEN_PDU_RESPONSE) {
+ RA::Error(LL_PER_PDU, "RA_Processor::IsPinReset",
+ "Invalid Message Type");
+ goto loser;
+ }
+ response = token_pdu_response_msg->GetResponse();
+ if (response == NULL) {
+ RA::Error("Secure_Channel::IsPinReset",
+ "No Response From Token");
+ goto loser;
+ }
+ data = response->GetData();
+ if (data.size() < 2) {
+ RA::Error(LL_PER_PDU, "Secure_Channel::IsPinReset",
+ "Invalid Response From Token");
+ goto loser;
+ }
+
+ if (pin_number < 8) {
+ rc = ((((BYTE*)data)[1] & (1 << pin_number)) > 0);
+ } else {
+ rc = ((((BYTE*)data)[0] & (1 << (pin_number - 8))) > 0);
+ }
+
+loser:
+ if( mac != NULL ) {
+ delete mac;
+ mac = NULL;
+ }
+ if( token_pdu_request_msg != NULL ) {
+ delete token_pdu_request_msg;
+ token_pdu_request_msg = NULL;
+ }
+ if( token_pdu_response_msg != NULL ) {
+ delete token_pdu_response_msg;
+ token_pdu_response_msg = NULL;
+ }
+
+ return rc;
+}
+
+/**
+ * Select applet.
+ *
+ * Global Platform Open Platform Card Specification
+ * Version 2.0.1 Page 9-22
+ *
+ * Sample Data:
+ *
+ * _____________ CLA
+ * | __________ INS
+ * | | _______ P1
+ * | | | ____ P2
+ * | | | | _ Len
+ * | | | | |
+ * 00 A4 04 00 07
+ * 53 4C 42 47 49 4E 41
+ */
+int RA_Processor::SelectApplet(RA_Session *session, BYTE p1, BYTE p2, Buffer *aid)
+{
+ int rc = 0;
+ APDU_Response *select_response = NULL;
+ RA_Token_PDU_Request_Msg *select_request_msg = NULL;
+ RA_Token_PDU_Response_Msg *select_response_msg = NULL;
+ Select_APDU *select_apdu = NULL;
+
+ if (aid != NULL) {
+ RA::DebugBuffer(LL_PER_PDU, "RA_Processor::SelectApplet",
+ "RA_Processor::SelectApplet with aid= ", aid);
+ }
+
+ select_apdu = new Select_APDU(p1, p2, *aid);
+ select_request_msg =
+ new RA_Token_PDU_Request_Msg(select_apdu);
+ session->WriteMsg(select_request_msg);
+
+ RA::Debug(LL_PER_PDU, "RA_Processor::SelectApplet",
+ "Sent select_request_msg");
+
+ select_response_msg = (RA_Token_PDU_Response_Msg *)
+ session->ReadMsg();
+ if (select_response_msg == NULL)
+ {
+ RA::Error(LL_PER_PDU, "RA_Processor::SelectApplet",
+ "No Token PDU Response Msg Received");
+ goto loser;
+ }
+ if (select_response_msg->GetType() != MSG_TOKEN_PDU_RESPONSE) {
+ RA::Error(LL_PER_PDU, "Secure_Channel::SelectApplet",
+ "Invalid Message Type");
+ goto loser;
+ }
+ select_response = select_response_msg->GetResponse();
+ if (select_response == NULL) {
+ RA::Error(LL_PER_PDU, "Secure_Channel::SelectApplet",
+ "No Response From Token");
+ goto loser;
+ }
+ if (select_response->GetData().size() < 2) {
+ RA::Error(LL_PER_PDU, "Secure_Channel::SelectApplet",
+ "Invalid Response From Token");
+ goto loser;
+ }
+ if (!(select_response->GetSW1() == 0x90 &&
+ select_response->GetSW2() == 0x00)) {
+ RA::Error(LL_PER_PDU, "RA_Processor::SelectApplet",
+ "Bad Response");
+ goto loser;
+ }
+
+
+loser:
+ if( select_request_msg != NULL ) {
+ delete select_request_msg;
+ select_request_msg = NULL;
+ }
+ if( select_response_msg != NULL ) {
+ delete select_response_msg;
+ select_response_msg = NULL;
+ }
+
+ return rc;
+}
+
+/**
+ * Get Build ID from Net Key Applet.
+ * @returns a buffer with 4 bytes of data. This is the applet ID.
+ * The caller is responsible for freeing the buffer with
+ * the 'delete' operator.
+ */
+Buffer *RA_Processor::GetAppletVersion(RA_Session *session)
+{
+ Buffer data;
+ Buffer *buildID = NULL;
+ APDU_Response *get_version_response = NULL;
+ RA_Token_PDU_Request_Msg *get_version_request_msg = NULL;
+ RA_Token_PDU_Response_Msg *get_version_response_msg = NULL;
+ Get_Version_APDU *get_version_apdu = NULL;
+ Buffer get_version_data;
+
+ get_version_apdu =
+ new Get_Version_APDU();
+ get_version_request_msg =
+ new RA_Token_PDU_Request_Msg(get_version_apdu);
+ session->WriteMsg(get_version_request_msg);
+ RA::Debug(LL_PER_PDU, "RA_Processor::GetAppletVersion",
+ "Sent get_version_request_msg");
+
+ get_version_response_msg = (RA_Token_PDU_Response_Msg *)
+ session->ReadMsg();
+ if (get_version_response_msg == NULL)
+ {
+ RA::Error(LL_PER_PDU, "RA_Processor::GetAppletVersion",
+ "No Token PDU Response Msg Received");
+ goto loser;
+ }
+ if (get_version_response_msg->GetType() != MSG_TOKEN_PDU_RESPONSE) {
+ RA::Error(LL_PER_PDU, "RA_Processor::GetAppletVersion",
+ "Invalid Message Type");
+ goto loser;
+ }
+ get_version_response =
+ get_version_response_msg->GetResponse();
+ if (get_version_response == NULL) {
+ RA::Error(LL_PER_PDU, "Secure_Channel::GetAppletVersion",
+ "No Response From Token");
+ goto loser;
+ }
+ data = get_version_response->GetData();
+ if (!(get_version_response->GetSW1() == 0x90 &&
+ get_version_response->GetSW2() == 0x00)) {
+ RA::Error(LL_PER_PDU, "RA_Processor::GetAppletVersion",
+ "Bad Response");
+ goto loser;
+ }
+
+ /* Sample: 3FBAB4BF9000 */
+ if (data.size() != 6) {
+ RA::Error(LL_PER_PDU, "Secure_Channel::GetAppletVersion",
+ "Invalid Applet Version");
+ RA::DebugBuffer(LL_PER_PDU, "RA_Processor::GetAppletVersion",
+ "Bad Applet Version: ",
+ &data);
+ goto loser;
+ }
+
+ buildID = new Buffer(data.substr(0, 4));
+
+/*
+ buildID = (get_version_data[0] << 24) | (get_version_data[1] << 16) |
+ (get_version_data[2] << 8) | get_version_data[3];
+
+*/
+
+loser:
+
+ if( get_version_request_msg != NULL ) {
+ delete get_version_request_msg;
+ get_version_request_msg = NULL;
+ }
+ if( get_version_response_msg != NULL ) {
+ delete get_version_response_msg;
+ get_version_response_msg = NULL;
+ }
+ return buildID;
+}
+
+/*
+ * this one sets the security level
+ */
+Secure_Channel *RA_Processor::SetupSecureChannel(RA_Session *session,
+ BYTE key_version, BYTE key_index, SecurityLevel security_level,
+ const char *connId)
+{
+ Secure_Channel *channel = SetupSecureChannel(session, key_version, key_index, connId);
+ RA::Debug(LL_PER_PDU, "RA_Processor::Setup_Secure_Channel","Resetting security level ...");
+
+ /* Bugscape Bug #55774: Prevent NetKey RA from crashing . . . */
+ if( channel != NULL ) {
+ channel->SetSecurityLevel(security_level);
+ } else {
+ RA::Error( LL_PER_PDU, "RA_Processor::SetupSecureChannel", "%s %s",
+ "Failed to create a secure channel - potentially due to an",
+ "RA/TKS key mismatch or differing RA/TKS key versions." );
+ }
+ return channel;
+
+}
+
+int RA_Processor::InitializeUpdate(RA_Session *session,
+ BYTE key_version, BYTE key_index,
+ Buffer &key_diversification_data,
+ Buffer &key_info_data,
+ Buffer &card_challenge,
+ Buffer &card_cryptogram,
+ Buffer &host_challenge, const char *connId)
+{
+ int rc = -1;
+ APDU_Response *initialize_update_response = NULL;
+ RA_Token_PDU_Request_Msg *initialize_update_request_msg = NULL;
+ RA_Token_PDU_Response_Msg *initialize_update_response_msg = NULL;
+ Initialize_Update_APDU *initialize_update_apdu = NULL;
+ Buffer update_response_data;
+ char configname[256];
+
+ RA::Debug(LL_PER_PDU, "RA_Processor::InitializeUpdate",
+ "RA_Processor::InitializeUpdate");
+
+
+ PR_snprintf((char *) configname, 256, "conn.%s.generateHostChallenge", connId);
+ bool gen_host_challenge_tks = RA::GetConfigStore()->GetConfigAsBool(configname, true);
+
+ if(gen_host_challenge_tks) {
+ RA::Debug(LL_PER_PDU, "RA_Processor::InitializeUpdate",
+ "Generate host challenge on TKS.");
+ rc = ComputeRandomData(host_challenge, (int) host_challenge.size(), connId);
+ } else {
+ rc = Util::GetRandomChallenge(host_challenge);
+ }
+
+ if(rc == -1) {
+ RA::Debug(LL_PER_PDU, "RA_Processor::InitializeUpdate",
+ "Failed to generate host challenge");
+ goto loser;
+
+ }
+
+ RA::DebugBuffer(LL_PER_PDU, "RA_Processor::InitializeUpdate",
+ "Generated Host Challenge",
+ &host_challenge);
+
+ initialize_update_apdu =
+ new Initialize_Update_APDU(key_version, key_index, host_challenge);
+ initialize_update_request_msg =
+ new RA_Token_PDU_Request_Msg(initialize_update_apdu);
+ session->WriteMsg(initialize_update_request_msg);
+ RA::Debug(LL_PER_PDU, "RA_Processor::InitializeUpdate",
+ "Sent initialize_update_request_msg");
+
+ initialize_update_response_msg = (RA_Token_PDU_Response_Msg *)
+ session->ReadMsg();
+ if (initialize_update_response_msg == NULL)
+ {
+ RA::Error(LL_PER_PDU, "RA_Processor::InitializeUpdate",
+ "No Token PDU Response Msg Received");
+ goto loser;
+ }
+ if (initialize_update_response_msg->GetType() != MSG_TOKEN_PDU_RESPONSE) {
+ RA::Error(LL_PER_PDU, "RA_Processor::InitializeUpdate",
+ "Invalid Message Type");
+ goto loser;
+ }
+ initialize_update_response =
+ initialize_update_response_msg->GetResponse();
+ update_response_data = initialize_update_response->GetData();
+
+ if (!(initialize_update_response->GetSW1() == 0x90 &&
+ initialize_update_response->GetSW2() == 0x00)) {
+ RA::Debug(LL_PER_PDU, "RA_Processor::InitializeUpdate",
+ "Key version mismatch - key changeover to follow");
+ goto loser;
+ }
+
+ RA::DebugBuffer(LL_PER_PDU, "RA_Processor::InitializeUpdate",
+ "Update Response Data", &update_response_data);
+
+ /**
+ * Initialize Update response:
+ * Key Diversification Data - 10 bytes
+ * Key Information Data - 2 bytes
+ * Card Challenge - 8 bytes
+ * Card Cryptogram - 8 bytes
+ */
+ if (initialize_update_response->GetData().size() < 10) {
+ RA::Error(LL_PER_PDU, "RA_Processor::InitializeUpdate",
+ "Invalid Initialize Update Response Size");
+ goto loser;
+ }
+ key_diversification_data = Buffer(update_response_data.substr(0, 10));
+ RA::DebugBuffer(LL_PER_PDU, "RA_Processor::InitializeUpdate",
+ "Key Diversification Data", &key_diversification_data);
+ key_info_data = Buffer(update_response_data.substr(10, 2));
+ RA::DebugBuffer(LL_PER_PDU, "RA_Processor::InitializeUpdate",
+ "Key Info Data", &key_info_data);
+ card_challenge = Buffer(update_response_data.substr(12, 8));
+ RA::DebugBuffer(LL_PER_PDU, "RA_Processor::InitializeUpdate",
+ "Card Challenge", &card_challenge);
+ card_cryptogram = Buffer(update_response_data.substr(20, 8));
+ RA::DebugBuffer(LL_PER_PDU, "RA_Processor::InitializeUpdate",
+ "Card Cryptogram", &card_cryptogram);
+
+ rc = 1;
+
+loser:
+ if( initialize_update_request_msg != NULL ) {
+ delete initialize_update_request_msg;
+ initialize_update_request_msg = NULL;
+ }
+ if( initialize_update_response_msg != NULL ) {
+ delete initialize_update_response_msg;
+ initialize_update_response_msg = NULL;
+ }
+
+ return rc;
+}
+
+/**
+ * Setup secure channel between RA and the token.
+ */
+Secure_Channel *RA_Processor::SetupSecureChannel(RA_Session *session,
+ BYTE key_version, BYTE key_index, const char *connId)
+{
+ Secure_Channel *channel = NULL;
+ APDU_Response *initialize_update_response = NULL;
+ RA_Token_PDU_Request_Msg *initialize_update_request_msg = NULL;
+ RA_Token_PDU_Response_Msg *initialize_update_response_msg = NULL;
+ Initialize_Update_APDU *initialize_update_apdu = NULL;
+ Buffer update_response_data;
+ Buffer host_challenge = Buffer(8, (BYTE)0);
+ Buffer key_diversification_data;
+ Buffer key_info_data;
+ Buffer card_challenge;
+ Buffer card_cryptogram;
+ char configname[256];
+
+ RA::Debug(LL_PER_PDU, "RA_Processor::Setup_Secure_Channel",
+ "RA_Processor::Setup_Secure_Channel");
+
+ PR_snprintf((char *) configname, 256, "conn.%s.generateHostChallenge", connId);
+ bool gen_host_challenge_tks = RA::GetConfigStore()->GetConfigAsBool(configname, false);
+
+ int rc = 0;
+ if(gen_host_challenge_tks) {
+ RA::Debug(LL_PER_PDU, "RA_Processor::Setup_Secure_Channel",
+ "Generate host challenge on TKS.");
+ rc = ComputeRandomData(host_challenge, (int) host_challenge.size(), connId);
+ } else {
+ rc = Util::GetRandomChallenge(host_challenge);
+ }
+
+ if(rc == -1) {
+ RA::Debug(LL_PER_PDU, "RA_Processor::SetupSecureChannel",
+ "Failed to generate host challenge");
+ goto loser;
+
+ }
+
+
+
+ /* if (Util::GetRandomChallenge(host_challenge) != PR_SUCCESS)
+ {
+ RA::Debug(LL_PER_PDU, "RA_Processor::Setup_Secure_Channel",
+ "Failed to generate host challenge");
+ goto loser;
+ }
+
+*/
+ RA::DebugBuffer(LL_PER_PDU, "RA_Processor::Setup_Secure_Channel",
+ "Generated Host Challenge",
+ &host_challenge);
+
+ initialize_update_apdu =
+ new Initialize_Update_APDU(key_version, key_index, host_challenge);
+ initialize_update_request_msg =
+ new RA_Token_PDU_Request_Msg(initialize_update_apdu);
+ session->WriteMsg(initialize_update_request_msg);
+ RA::Debug(LL_PER_PDU, "RA_Processor::Setup_Secure_Channel",
+ "Sent initialize_update_request_msg");
+
+ initialize_update_response_msg = (RA_Token_PDU_Response_Msg *)
+ session->ReadMsg();
+ if (initialize_update_response_msg == NULL)
+ {
+ RA::Error(LL_PER_PDU, "RA_Processor::Setup_Secure_Channel",
+ "No Token PDU Response Msg Received");
+ goto loser;
+ }
+ if (initialize_update_response_msg->GetType() != MSG_TOKEN_PDU_RESPONSE) {
+ RA::Error(LL_PER_PDU, "RA_Processor::Setup_Secure_Channel",
+ "Invalid Message Type");
+ goto loser;
+ }
+ initialize_update_response =
+ initialize_update_response_msg->GetResponse();
+ update_response_data = initialize_update_response->GetData();
+
+ if (!(initialize_update_response->GetSW1() == 0x90 &&
+ initialize_update_response->GetSW2() == 0x00)) {
+ RA::Debug(LL_PER_PDU, "RA_Processor::Setup_Secure_Channel",
+ "Key version mismatch - key changeover to follow");
+ goto loser;
+ }
+
+ RA::DebugBuffer(LL_PER_PDU, "RA_Processor::Setup_Secure_Channel",
+ "Update Response Data", &update_response_data);
+
+ /**
+ * Initialize Update response:
+ * Key Diversification Data - 10 bytes
+ * Key Information Data - 2 bytes
+ * Card Challenge - 8 bytes
+ * Card Cryptogram - 8 bytes
+ */
+ if (initialize_update_response->GetData().size() < 28) {
+ RA::Error(LL_PER_PDU, "RA_Processor::Setup_Secure_Channel",
+ "Invalid Initialize Update Response Size");
+ goto loser;
+ }
+ key_diversification_data = Buffer(update_response_data.substr(0, 10));
+ RA::DebugBuffer(LL_PER_PDU, "RA_Processor::Setup_Secure_Channel",
+ "Key Diversification Data", &key_diversification_data);
+ key_info_data = Buffer(update_response_data.substr(10, 2));
+ RA::DebugBuffer(LL_PER_PDU, "RA_Processor::Setup_Secure_Channel",
+ "Key Info Data", &key_info_data);
+ card_challenge = Buffer(update_response_data.substr(12, 8));
+ RA::DebugBuffer(LL_PER_PDU, "RA_Processor::Setup_Secure_Channel",
+ "Card Challenge", &card_challenge);
+ card_cryptogram = Buffer(update_response_data.substr(20, 8));
+ RA::DebugBuffer(LL_PER_PDU, "RA_Processor::Setup_Secure_Channel",
+ "Card Cryptogram", &card_cryptogram);
+
+ channel = GenerateSecureChannel(
+ session, connId,
+ key_diversification_data,
+ key_info_data,
+ card_challenge,
+ card_cryptogram,
+ host_challenge);
+
+loser:
+ if( initialize_update_request_msg != NULL ) {
+ delete initialize_update_request_msg;
+ initialize_update_request_msg = NULL;
+ }
+ if( initialize_update_response_msg != NULL ) {
+ delete initialize_update_response_msg;
+ initialize_update_response_msg = NULL;
+ }
+
+ return channel;
+} /* SetupSecureChannel */
+
+/**
+ * Requests secure ID.
+ */
+SecureId *RA_Processor::RequestSecureId(RA_Session *session)
+{
+ SecureId *secure_id = NULL;
+ RA_SecureId_Request_Msg *secureid_request_msg = NULL;
+ RA_SecureId_Response_Msg *secureid_response_msg = NULL;
+ char *value;
+ char *pin;
+
+ RA::Debug(LL_PER_PDU, "RA_Processor::SecureId_Request",
+ "RA_Processor::SecureId_Request");
+
+ secureid_request_msg = new RA_SecureId_Request_Msg(
+ 0 /* pin_required */, 0 /* next_value */);
+ session->WriteMsg(secureid_request_msg);
+ RA::Debug(LL_PER_PDU, "RA_Processor::SecureId_Request",
+ "Sent secureid_request_msg");
+
+ secureid_response_msg = (RA_SecureId_Response_Msg *)
+ session->ReadMsg();
+ if (secureid_response_msg == NULL)
+ {
+ RA::Error(LL_PER_PDU, "RA_Processor::SecureId_Request",
+ "No SecureID Response Msg Received");
+ goto loser;
+ }
+
+ if (secureid_response_msg->GetType() != MSG_SECUREID_RESPONSE) {
+ RA::Error("Secure_Channel::SecureId_Request",
+ "Invalid Msg Type");
+ goto loser;
+ }
+
+ value = secureid_response_msg->GetValue();
+ pin = secureid_response_msg->GetPIN();
+
+ secure_id = new SecureId(value, pin);
+
+loser:
+
+ if( secureid_request_msg != NULL ) {
+ delete secureid_request_msg;
+ secureid_request_msg = NULL;
+ }
+ if( secureid_response_msg != NULL ) {
+ delete secureid_response_msg;
+ secureid_response_msg = NULL;
+ }
+ return secure_id;
+} /* RequestSecureId */
+
+/**
+ * Requests new pin for token.
+ */
+char *RA_Processor::RequestNewPin(RA_Session *session, unsigned int min, unsigned int max)
+{
+ char *new_pin = NULL;
+ RA_New_Pin_Request_Msg *new_pin_request_msg = NULL;
+ RA_New_Pin_Response_Msg *new_pin_response_msg = NULL;
+
+ RA::Debug(LL_PER_PDU, "RA_Processor::New_Pin_Request",
+ "RA_Processor::New_Pin_Request");
+
+ new_pin_request_msg = new RA_New_Pin_Request_Msg(
+ min, max);
+ session->WriteMsg(new_pin_request_msg);
+ RA::Debug(LL_PER_PDU, "RA_Processor::New_Pin_Request",
+ "Sent new_pin_request_msg");
+
+ new_pin_response_msg = (RA_New_Pin_Response_Msg *)
+ session->ReadMsg();
+ if (new_pin_response_msg == NULL)
+ {
+ RA::Error(LL_PER_PDU, "RA_Processor::New_Pin_Request",
+ "No New Pin Response Msg Received");
+ goto loser;
+ }
+
+ if (new_pin_response_msg->GetType() != MSG_NEW_PIN_RESPONSE) {
+ RA::Error(LL_PER_PDU, "RA_Processor::New_Pin_Request",
+ "Invalid Message Type");
+ goto loser;
+ }
+
+ if (new_pin_response_msg->GetNewPIN() == NULL) {
+ RA::Error(LL_PER_PDU, "RA_Processor::New_Pin_Request",
+ "No New Pin");
+ goto loser;
+ }
+
+ new_pin = PL_strdup(new_pin_response_msg->GetNewPIN());
+
+ if (strlen(new_pin) < min) {
+ RA::Error(LL_PER_PDU, "RA_Pin_Reset_Processor::Process",
+ "The length of the new pin is shorter than the mininum length (%d)", min);
+ if( new_pin != NULL ) {
+ PL_strfree( new_pin );
+ new_pin = NULL;
+ }
+ new_pin = NULL;
+ goto loser;
+ } else if (strlen(new_pin) > max) {
+ RA::Error(LL_PER_PDU, "RA_Pin_Reset_Processor::Process",
+ "The length of the new pin is longer than the maximum length (%d)", max);
+ if( new_pin != NULL ) {
+ PL_strfree( new_pin );
+ new_pin = NULL;
+ }
+ new_pin = NULL;
+ goto loser;
+ }
+
+loser:
+
+ if( new_pin_request_msg != NULL ) {
+ delete new_pin_request_msg;
+ new_pin_request_msg = NULL;
+ }
+ if( new_pin_response_msg != NULL ) {
+ delete new_pin_response_msg;
+ new_pin_response_msg = NULL;
+ }
+
+ return new_pin;
+} /* RequestNewPin */
+
+/**
+ * Requests A Security Question (ASQ) from user.
+ */
+char *RA_Processor::RequestASQ(RA_Session *session, char *question)
+{
+ char *answer = NULL;
+ RA_ASQ_Request_Msg *asq_request_msg = NULL;
+ RA_ASQ_Response_Msg *asq_response_msg = NULL;
+
+ RA::Debug(LL_PER_PDU, "RA_Processor::ASQ_Request",
+ "RA_Processor::ASQ_Request");
+
+ asq_request_msg = new RA_ASQ_Request_Msg(question);
+ session->WriteMsg(asq_request_msg);
+ RA::Debug(LL_PER_PDU, "RA_Processor::ASQ_Request",
+ "Sent asq_request_msg");
+
+ asq_response_msg = (RA_ASQ_Response_Msg *)
+ session->ReadMsg();
+ if (asq_response_msg == NULL)
+ {
+ RA::Error(LL_PER_PDU, "RA_Processor::ASQ_Request",
+ "No ASQ Response Msg Received");
+ goto loser;
+ }
+ if (asq_response_msg->GetType() != MSG_ASQ_RESPONSE) {
+ RA::Error(LL_PER_PDU, "RA_Processor::ASQ_Request",
+ "Invalid Message Type");
+ goto loser;
+ }
+
+ if (asq_response_msg->GetAnswer() == NULL) {
+ RA::Error(LL_PER_PDU, "RA_Processor::ASQ_Request",
+ "No ASQ Answer");
+ goto loser;
+ }
+ answer = PL_strdup(asq_response_msg->GetAnswer());
+
+loser:
+ if( asq_request_msg != NULL ) {
+ delete asq_request_msg;
+ asq_request_msg = NULL;
+ }
+ if( asq_response_msg != NULL ) {
+ delete asq_response_msg;
+ asq_response_msg = NULL;
+ }
+
+ return answer;
+} /* RequestASQ */
+
+/**
+ * Creates a secure channel between RA and the token.
+ * challenges are sent to TKS which generates
+ * host cryptogram, and session key.
+ */
+Secure_Channel *RA_Processor::GenerateSecureChannel(
+ RA_Session *session, const char *connId,
+ Buffer &key_diversification_data, /* CUID */
+ Buffer &key_info_data,
+ Buffer &card_challenge,
+ Buffer &card_cryptogram,
+ Buffer &host_challenge)
+{
+ PK11SymKey *session_key = NULL;
+ Buffer *host_cryptogram = NULL;
+ char configname[256];
+
+ RA::Debug(LL_PER_PDU, "RA_Processor::Setup_Secure_Channel",
+ "RA_Processor::GenerateSecureChannel");
+
+ PK11SymKey *enc_session_key = NULL;
+
+
+ // desKey_s will be assigned to channel and will be destroyed when channel closed
+ char *drm_desKey_s = NULL;
+ char *kek_desKey_s = NULL;
+ char *keycheck_s = NULL;
+
+ session_key = RA::ComputeSessionKey(session, key_diversification_data,
+ key_info_data, card_challenge,
+ host_challenge, &host_cryptogram,
+ card_cryptogram, &enc_session_key,
+ &drm_desKey_s, &kek_desKey_s,
+ &keycheck_s, connId);
+ if (session_key == NULL) {
+ RA::Debug(LL_PER_PDU, "RA_Processor::Setup_Secure_Channel",
+ "RA_Processor::GenerateSecureChannel - did not get session_key");
+ return NULL;
+ }
+
+ // is serversideKeygen on?
+ PR_snprintf((char *) configname, 256, "conn.%s.serverKeygen", connId);
+ bool serverKeygen = RA::GetConfigStore()->GetConfigAsBool(configname, false);
+
+ if (serverKeygen) {
+ if ((drm_desKey_s == NULL) || (strcmp(drm_desKey_s, "")==0)) {
+ RA::Debug(LL_PER_PDU, "RA_Processor::Setup_Secure_Channel",
+ "RA_Processor::GenerateSecureChannel - did not get drm_desKey_s");
+ return NULL;
+ } else {
+ RA::Debug(LL_PER_PDU, "RA_Processor::Setup_Secure_Channel",
+ "RA_Processor::GenerateSecureChannel - drm_desKey_s = %s", drm_desKey_s);
+ }
+ if ((kek_desKey_s == NULL) || (strcmp(kek_desKey_s,"")==0)) {
+ RA::Debug(LL_PER_PDU, "RA_Processor::Setup_Secure_Channel",
+ "RA_Processor::GenerateSecureChannel - did not get kek_desKey_s");
+ return NULL;
+ } else {
+ RA::Debug(LL_PER_PDU, "RA_Processor::Setup_Secure_Channel",
+ "RA_Processor::GenerateSecureChannel - kek_desKey_s = %s", kek_desKey_s);
+ }
+ if ((keycheck_s == NULL) || (strcmp(keycheck_s,"")==0)) {
+ RA::Debug(LL_PER_PDU, "RA_Processor::Setup_Secure_Channel",
+ "RA_Processor::GenerateSecureChannel - did not get keycheck_s");
+ return NULL;
+ }
+
+ if (enc_session_key == NULL) {
+ RA::Debug(LL_PER_PDU, "RA_Processor::Setup_Secure_Channel",
+ "RA_Processor::GenerateSecureChannel - did not get enc_session_key");
+ return NULL;
+ }
+ if (host_cryptogram == NULL) {
+ RA::Debug(LL_PER_PDU, "RA_Processor::Setup_Secure_Channel",
+ "RA_Processor::GenerateSecureChannel - did not get host_cryptogram");
+ return NULL;
+ } else {
+ RA::Debug(LL_PER_PDU, "RA_Processor::Setup_Secure_Channel",
+ "RA_Processor::GenerateSecureChannel - keycheck_s = %s", keycheck_s);
+ }
+ }
+/*
+ host_cryptogram = RA::ComputeHostCryptogram(
+ card_challenge, host_challenge);
+*/
+
+
+ Secure_Channel *channel = new Secure_Channel(session, session_key,
+ enc_session_key,
+ drm_desKey_s, kek_desKey_s, keycheck_s,
+ key_diversification_data, key_info_data,
+ card_challenge, card_cryptogram,
+ host_challenge, *host_cryptogram);
+
+ if( host_cryptogram != NULL ) {
+ delete host_cryptogram;
+ host_cryptogram = NULL;
+ }
+
+ if (channel != NULL) {
+ // this can be overridden by individual processor later
+ channel->SetSecurityLevel(RA::GetGlobalSecurityLevel());
+ } else {
+ if( session_key != NULL ) {
+ PK11_FreeSymKey( session_key );
+ session_key = NULL;
+ }
+ if( enc_session_key != NULL ) {
+ PK11_FreeSymKey( enc_session_key );
+ enc_session_key = NULL;
+ }
+
+ }
+
+ RA::Debug(LL_PER_PDU, "RA_Processor::GenerateSecureChannel", "complete");
+ return channel;
+} /* GenerateSecureChannel */
+
+int RA_Processor::CreateKeySetData(Buffer &CUID, Buffer &version,
+ Buffer &NewMasterVer, Buffer &out, const char *connid)
+{
+ char body[5000];
+ char configname[256];
+ HttpConnection *tksConn = NULL;
+ tksConn = RA::GetTKSConn(connid);
+ if (tksConn == NULL) {
+ RA::Debug(LL_PER_PDU, "RA_Processor::CreateKeySetData", "Failed to get TKSConnection %s", connid);
+ RA::Error(LL_PER_PDU, "RA_Processor::CreateKeySetData", "Failed to get TKSConnection %s", connid);
+ return -1;
+ } else {
+ // PRLock *tks_lock = RA::GetTKSLock();
+ int tks_curr = RA::GetCurrentIndex(tksConn);
+ int currRetries = 0;
+ char *cuid = Util::SpecialURLEncode(CUID);
+ char *versionID = Util::SpecialURLEncode(version);
+ char *masterV = Util::SpecialURLEncode(NewMasterVer);
+
+ PR_snprintf((char *)configname, 256, "conn.%s.keySet", connid);
+ const char *keySet = RA::GetConfigStore()->GetConfigAsString(configname);
+
+ PR_snprintf((char *)body, 5000,
+ "newKeyInfo=%s&CUID=%s&KeyInfo=%s&keySet=%s", masterV, cuid, versionID,keySet);
+
+ PR_snprintf((char *)configname, 256, "conn.%s.servlet.createKeySetData", connid);
+ const char *servletID = RA::GetConfigStore()->GetConfigAsString(configname);
+
+ if( cuid != NULL ) {
+ PR_Free( cuid );
+ cuid = NULL;
+ }
+ if( versionID != NULL ) {
+ PR_Free( versionID );
+ versionID = NULL;
+ }
+ if( masterV != NULL ) {
+ PR_Free( masterV );
+ masterV = NULL;
+ }
+
+ tks_curr = RA::GetCurrentIndex(tksConn);
+
+ PSHttpResponse * response = tksConn->getResponse(tks_curr, servletID, body);
+ ConnectionInfo *connInfo = tksConn->GetFailoverList();
+ char **hostport = connInfo->GetHostPortList();
+
+ if (response == NULL)
+ RA::Debug(LL_PER_PDU, "The CreateKeySetData response from TKS ",
+ "at %s is NULL.", hostport[tks_curr]);
+ else
+ RA::Debug(LL_PER_PDU, "The CreateKeySetData response from TKS ",
+ "at % is not NULL.", hostport[tks_curr]);
+
+ while (response == NULL) {
+ RA::Failover(tksConn, connInfo->GetHostPortListLen());
+ tks_curr = RA::GetCurrentIndex(tksConn);
+
+ RA::Debug(LL_PER_PDU, "RA is reconnecting to TKS ",
+ "at %s for createKeySetData.", hostport[tks_curr]);
+
+ if (++currRetries >= tksConn->GetNumOfRetries()) {
+ RA::Debug(LL_PER_PDU, "Used up all the retries. Response is NULL","");
+ RA::Error(LL_PER_PDU, "RA_Processor::CreateKeySetData","Failed connecting to TKS after %d retries", currRetries);
+ if (tksConn != NULL) {
+ RA::ReturnTKSConn(tksConn);
+ }
+ return -1;
+ }
+ response = tksConn->getResponse(tks_curr, servletID, body);
+ }
+
+ int status = 0;
+
+ Buffer *keydataset = NULL;
+ if (response != NULL) {
+ RA::Debug(LL_PER_PDU,"Response is not ","NULL");
+ char * content = response->getContent();
+ if (content == NULL) {
+ RA::Debug(LL_PER_PDU,"TKSConnection::CreateKeySetData","Content Is NULL");
+ } else {
+ RA::Debug(LL_PER_PDU,"TKSConnection::CreateKeySetData","Content Is '%s'",
+ content);
+ }
+ if (content != NULL) {
+ char *statusStr = strstr((char *)content, "status=0&");
+ if (statusStr == NULL) {
+ status = 1;
+ char *p = strstr((char *)content, "status=");
+ if(p != NULL) {
+ status = int(p[7]) - 48;
+ } else {
+ status = 4;
+ return -1;
+ }
+ } else {
+ status = 0;
+ char *p = &content[9];
+ char *rcStr = strstr((char *)p, "keySetData=");
+ if (rcStr != NULL) {
+ rcStr = &rcStr[11];
+ if (!strcmp(rcStr, "%00")) {
+ return -1;
+ }
+ keydataset = Util::URLDecode(rcStr);
+ }
+ }
+ }
+ }
+
+ if (keydataset == NULL)
+ {
+ RA::Debug(LL_PER_PDU, "RA_Processor:CreateKeySetData",
+ "Key Set Data is NULL");
+
+ return -1;
+ }
+
+ RA::Debug(LL_PER_PDU, "RA_Processor:CreateKeySetData", "Status of CreateKeySetData=%d", status);
+ RA::Debug(LL_PER_PDU, "finish CreateKeySetData", "");
+
+ if (status > 0) {
+ if (tksConn != NULL) {
+ RA::ReturnTKSConn(tksConn);
+ }
+ return -1;
+ } else {
+ out = *keydataset;
+ if( keydataset != NULL ) {
+ delete keydataset;
+ keydataset = NULL;
+ }
+ }
+
+ if( response != NULL ) {
+ response->freeContent();
+ delete response;
+ response = NULL;
+ }
+
+ if (tksConn != NULL) {
+ RA::ReturnTKSConn(tksConn);
+ }
+ return 1;
+ }
+ BYTE kek_key[] = {
+ 0x40, 0x41, 0x42, 0x43,
+ 0x44, 0x45, 0x46, 0x47,
+ 0x48, 0x49, 0x4a, 0x4b,
+ 0x4c, 0x4d, 0x4e, 0x4f
+ };
+ BYTE key[] = {
+ 0x40, 0x41, 0x42, 0x43,
+ 0x44, 0x45, 0x46, 0x47,
+ 0x48, 0x49, 0x4a, 0x4b,
+ 0x4c, 0x4d, 0x4e, 0x4f
+ };
+ Buffer old_kek_key(kek_key, 16);
+ Buffer new_auth_key(key, 16);
+ Buffer new_mac_key(key, 16);
+ Buffer new_kek_key(key, 16);
+
+
+ Util::CreateKeySetData(
+ NewMasterVer,
+ old_kek_key,
+ new_auth_key,
+ new_mac_key,
+ new_kek_key,
+ out);
+
+ if (tksConn != NULL) {
+ RA::ReturnTKSConn(tksConn);
+ }
+ return 1;
+}
+
+
+/**
+ * Input data wrapped by KEK key in TKS.
+ */
+int RA_Processor::EncryptData(Buffer &CUID, Buffer &version, Buffer &in, Buffer &out, const char *connid)
+{
+ char body[5000];
+ char configname[256];
+#define PLAINTEXT_CHALLENGE_SIZE 16
+ // khai, here we wrap the input with the KEK key
+ // in TKS
+ HttpConnection *tksConn = NULL;
+ char kek_key[16] = {
+ 0x40, 0x41, 0x42, 0x43,
+ 0x44, 0x45, 0x46, 0x47,
+ 0x48, 0x49, 0x4a, 0x4b,
+ 0x4c, 0x4d, 0x4e, 0x4f
+ };
+ int status = 0;
+
+ tksConn = RA::GetTKSConn(connid);
+ if (tksConn == NULL) {
+ RA::Debug(LL_PER_PDU, "RA_Processor::EncryptData", "Failed to get TKSConnection %s", connid);
+ RA::Debug(LL_PER_PDU, "RA_Processor::EncryptData", "Failed to get TKSConnection %s", connid);
+ return -1;
+ } else {
+ int tks_curr = RA::GetCurrentIndex(tksConn);
+ int currRetries = 0;
+ char *data = NULL;
+ Buffer *zerob = new Buffer(PLAINTEXT_CHALLENGE_SIZE, (BYTE)0);
+ if (!(in == *zerob))
+ data = Util::SpecialURLEncode(in);
+ else
+ RA::Debug(LL_PER_PDU, "RA_Processor::EncryptData","Challenge to be generated on TKS");
+
+ if (zerob != NULL) {
+ delete zerob;
+ }
+
+ char *cuid = Util::SpecialURLEncode(CUID);
+ char *versionID = Util::SpecialURLEncode(version);
+
+ PR_snprintf((char *)configname, 256, "conn.%s.keySet", connid);
+ const char *keySet = RA::GetConfigStore()->GetConfigAsString(configname);
+
+ PR_snprintf((char *)body, 5000, "data=%s&CUID=%s&KeyInfo=%s&keySet=%s",
+ ((data != NULL)? data:""), cuid, versionID,keySet);
+ PR_snprintf((char *)configname, 256, "conn.%s.servlet.encryptData", connid);
+ const char *servletID = RA::GetConfigStore()->GetConfigAsString(configname);
+
+ if( cuid != NULL ) {
+ PR_Free( cuid );
+ cuid = NULL;
+ }
+ if( versionID != NULL ) {
+ PR_Free( versionID );
+ versionID = NULL;
+ }
+
+ PSHttpResponse *response = tksConn->getResponse(tks_curr, servletID, body);
+ ConnectionInfo *connInfo = tksConn->GetFailoverList();
+ char **hostport = connInfo->GetHostPortList();
+ if (response == NULL)
+ RA::Debug(LL_PER_PDU, "The encryptedData response from TKS ",
+ "at %s is NULL.", hostport[tks_curr]);
+ else
+ RA::Debug(LL_PER_PDU, "The encryptedData response from TKS ",
+ "at %s is not NULL.", hostport[tks_curr]);
+
+ while (response == NULL) {
+ RA::Failover(tksConn, connInfo->GetHostPortListLen());
+ tks_curr = RA::GetCurrentIndex(tksConn);
+ RA::Debug(LL_PER_PDU, "RA is reconnecting to TKS ",
+ "at %s for encryptData.", hostport[tks_curr]);
+
+ if (++currRetries >= tksConn->GetNumOfRetries()) {
+ RA::Debug(LL_PER_PDU, "Used up all the retries. Response is NULL","");
+ RA::Error(LL_PER_PDU, "RA_Processor::EncryptData", "Failed connecting to TKS after %d retries", currRetries);
+ if (tksConn != NULL) {
+ RA::ReturnTKSConn(tksConn);
+ }
+ return -1;
+ }
+ response = tksConn->getResponse(tks_curr, servletID, body);
+ }
+
+ Buffer *encryptedData = NULL;
+ // preEncData is only useful when data is null, and data is to be randomly
+ // generated on TKS
+ Buffer *preEncData = NULL;
+ status = 0;
+ if (response != NULL) {
+ RA::Debug(LL_PER_PDU, "EncryptData Response is not ","NULL");
+ char *content = response->getContent();
+ if (content != NULL) {
+ char *statusStr = strstr((char *)content, "status=0&");
+ if (statusStr == NULL) {
+ char *p = strstr((char *)content, "status=");
+
+ if(p != NULL) {
+ status = int(p[7]) - 48;
+ } else {
+ status = 4;
+ return -1;
+ }
+ } else {
+ status = 0;
+ char *p = &content[9];
+ // get pre-encryption data
+ char *preStr = strstr((char *)p, "data=");
+ if (preStr != NULL) {
+ p = &preStr[5];
+ char pstr[PLAINTEXT_CHALLENGE_SIZE*3+1];
+ strncpy(pstr, p, PLAINTEXT_CHALLENGE_SIZE*3);
+ pstr[PLAINTEXT_CHALLENGE_SIZE*3] = '\0';
+ preEncData = Util::URLDecode(pstr);
+//RA::DebugBuffer("RA_Processor::EncryptData", "preEncData=", preEncData);
+ }
+
+ // get encrypted data
+ p = &content[9];
+ char *rcStr = strstr((char *)p, "encryptedData=");
+ if (rcStr != NULL) {
+ rcStr = &rcStr[14];
+ encryptedData = Util::URLDecode(rcStr);
+//RA::DebugBuffer("RA_Processor::EncryptData", "encryptedData=", encryptedData);
+ }
+ }
+ }
+ }
+ if (encryptedData == NULL)
+ RA::Debug(LL_PER_PDU, "RA_Processor:GetEncryptedData",
+ "Encrypted Data is NULL");
+
+ RA::Debug(LL_PER_PDU, "EncryptedData ", "status=%d", status);
+ RA::Debug(LL_PER_PDU, "finish EncryptedData", "");
+ if ((status > 0) || (preEncData == NULL) || (encryptedData == NULL)) {
+ if (tksConn != NULL) {
+ RA::ReturnTKSConn(tksConn);
+ }
+ if( data != NULL ) {
+ PR_Free( data );
+ data = NULL;
+ }
+ return -1;
+ } else {
+ out = *encryptedData;
+ if( encryptedData != NULL ) {
+ delete encryptedData;
+ encryptedData = NULL;
+ }
+ if (data != NULL) {
+ RA::Debug(LL_PER_PDU, "EncryptedData ", "challenge overwritten by TKS");
+ PR_Free( data );
+ data = NULL;
+ }
+ in = *preEncData;
+
+ if( preEncData != NULL ) {
+ delete preEncData;
+ preEncData = NULL;
+ }
+ }
+ if( response != NULL ) {
+ response->freeContent();
+ delete response;
+ response = NULL;
+ }
+
+ if (tksConn != NULL) {
+ RA::ReturnTKSConn(tksConn);
+ }
+ return 1;
+ }
+
+ Buffer kek_buffer = Buffer((BYTE*)kek_key, 16);
+ status = Util::EncryptData(kek_buffer, in, out);
+#if 0
+ RA::DebugBuffer(LL_PER_PDU, "RA_Processor::EncryptData", "Encrypted Data",
+ &out);
+ Buffer out1 = Buffer(16, (BYTE)0);
+ status = Util::DecryptData(kek_buffer, out, out1);
+ RA::DebugBuffer(LL_PER_PDU, "RA_Processor::EncryptData", "Clear Data",
+ &out1);
+#endif
+ if (tksConn != NULL) {
+ RA::ReturnTKSConn(tksConn);
+ }
+ return status;
+}
+
+int RA_Processor::ComputeRandomData(Buffer &data_out, int dataSize, const char *connid)
+{
+ char body[5000];
+ char configname[256];
+ HttpConnection *tksConn = NULL;
+ int status = -1;
+ Buffer *decodedRandomData = NULL;
+ PSHttpResponse *response = NULL;
+
+ //check for absurd dataSize values
+ if(dataSize <= 0 || dataSize > 1024) {
+ RA::Debug(LL_PER_PDU, "RA_Processor::ComputeRandomData", "Invalid dataSize requested %d", dataSize);
+ return -1;
+ }
+
+ tksConn = RA::GetTKSConn(connid);
+ if (tksConn == NULL) {
+ RA::Debug(LL_PER_PDU, "RA_Processor::ComputeRandomData", "Failed to get TKSConnection %s", connid);
+ return -1;
+ } else {
+ int tks_curr = RA::GetCurrentIndex(tksConn);
+ int currRetries = 0;
+
+ PR_snprintf((char *)body, 5000, "dataNumBytes=%d"
+ , dataSize );
+
+ PR_snprintf((char *)configname, 256, "conn.%s.servlet.computeRandomData", connid);
+ const char *servletID = RA::GetConfigStore()->GetConfigAsString(configname);
+
+ response = tksConn->getResponse(tks_curr, servletID, body);
+ ConnectionInfo *connInfo = tksConn->GetFailoverList();
+ char **hostport = connInfo->GetHostPortList();
+ if (response == NULL)
+ RA::Debug(LL_PER_PDU, "The ComputeRandomData response from TKS ",
+ "at %s is NULL.", hostport[tks_curr]);
+ else
+ RA::Debug(LL_PER_PDU, "The ComputeRandomData response from TKS ",
+ "at %s is not NULL.", hostport[tks_curr]);
+
+ while (response == NULL) {
+ RA::Failover(tksConn, connInfo->GetHostPortListLen());
+ tks_curr = RA::GetCurrentIndex(tksConn);
+ RA::Debug(LL_PER_PDU, "RA_Processor::ComputeRandomData: RA is reconnecting to TKS ",
+ "at %s for ComputeRandomData.", hostport[tks_curr]);
+
+ if (++currRetries >= tksConn->GetNumOfRetries()) {
+ RA::Debug(LL_PER_PDU, "RA_Processor::ComputeRandomData: Used up all the retries. Response is NULL","");
+ RA::Error(LL_PER_PDU, "RA_Processor::ComputeRandomData", "Failed connecting to TKS after %d retries", currRetries);
+ if (tksConn != NULL) {
+ RA::ReturnTKSConn(tksConn);
+ }
+ status = -1;
+ goto loser;
+ }
+ response = tksConn->getResponse(tks_curr, servletID, body);
+ }
+
+ status = 0;
+ if (response != NULL) {
+ RA::Debug(LL_PER_PDU, "RA_Processor::ComputeRandomData Response is not ","NULL");
+ char *content = response->getContent();
+ if (content != NULL) {
+ char *statusStr = strstr((char *)content, "status=0&");
+ if (statusStr == NULL) {
+ char *p = strstr((char *)content, "status=");
+
+ if(p != NULL) {
+ status = int(p[7]) - 48;
+
+ RA::Debug(LL_PER_PDU, "RA_Processor::ComputeRandomData status from TKS is ","status %d",status);
+ status = -1;
+ } else {
+ status = -1;
+ goto loser;
+ }
+ } else {
+ status = 0;
+ // skip over "status=0&"
+ char *p = &content[9];
+
+ // get random data
+ char *dataStr = strstr((char *)p, "DATA=");
+ if (dataStr != NULL) {
+ // skip over "DATA="
+ p = &dataStr[5];
+
+ char *dstr = new char[ dataSize *3 + 1];
+ if(!dstr) {
+ status = -1;
+ goto loser;
+ }
+ strncpy(dstr, p, dataSize * 3);
+ dstr[dataSize*3] = '\0';
+ decodedRandomData = Util::URLDecode(dstr);
+ RA::DebugBuffer("RA_Processor::ComputeRandomData", "decodedRandomData=", decodedRandomData);
+
+ if(dstr) {
+ data_out = *decodedRandomData;
+ delete [] dstr;
+ dstr = NULL;
+ }
+ if(decodedRandomData) {
+ delete decodedRandomData;
+ decodedRandomData = NULL;
+ }
+ }
+ }
+ }
+ }
+ }
+loser:
+ if( response != NULL ) {
+ response->freeContent();
+ delete response;
+ response = NULL;
+ }
+
+ if (tksConn != NULL) {
+ RA::ReturnTKSConn(tksConn);
+ }
+
+ return status;
+}
+
+bool RA_Processor::RevokeCertificates(RA_Session *session, char *cuid,char *audit_msg,
+ char *final_applet_version,
+ char *keyVersion,
+ char *tokenType,
+ char *userid,
+ RA_Status &status )
+{
+ const char *OP_PREFIX = "op.format";
+ char *statusString = NULL;
+ char configname[256];
+ char filter[512];
+ char activity_msg[512];
+ char serial[100];
+ int rc = 0;
+ int statusNum;
+ LDAPMessage *result = NULL;
+ LDAPMessage *e = NULL;
+ bool revocation_failed = false;
+
+ RA::Debug("RA_Processor::RevokeCertificates","RevokeCertificates! cuid %s",cuid);
+ PR_snprintf((char *)filter, 256, "(tokenID=%s)", cuid);
+ rc = RA::ra_find_tus_certificate_entries_by_order(filter, 100, &result, 1);
+ if (rc == 0) {
+ CertEnroll *certEnroll = new CertEnroll();
+ for (e = RA::ra_get_first_entry(result); e != NULL; e = RA::ra_get_next_entry(e)) {
+ char *attr_status = RA::ra_get_cert_status(e);
+ if (strcmp(attr_status, "revoked") == 0) {
+ if (attr_status != NULL) {
+ PL_strfree(attr_status);
+ attr_status = NULL;
+ }
+ rc = RA::ra_delete_certificate_entry(e);
+ continue;
+ }
+ char *attr_serial= RA::ra_get_cert_serial(e);
+ /////////////////////////////////////////////////
+ // Raidzilla Bug #57803:
+ // If the certificate is not originally created for this
+ // token, we should not revoke the certificate here.
+ //
+ // To figure out if this certificate is originally created
+ // for this token, we check the tokenOrigin attribute.
+ /////////////////////////////////////////////////
+ char *origin = RA::ra_get_cert_attr_byname(e, "tokenOrigin");
+ if (origin != NULL) {
+ RA::Debug("RA_Processor::RevokeCertificates", "Origin is %s, Current is %s", origin, cuid);
+ if (strcmp(origin, cuid) != 0) {
+ // skip this certificate, no need to do nothing
+ // We did not create this originally
+
+ rc = RA::ra_delete_certificate_entry(e);
+ continue;
+ }
+ } else {
+ RA::Debug("RA_Processor::RevokeCertificates", "Origin is not present");
+ }
+
+ PR_snprintf((char *)configname, 256, "%s.%s.revokeCert", OP_PREFIX, tokenType);
+ bool revokeCert = RA::GetConfigStore()->GetConfigAsBool(configname, true);
+ if (revokeCert) {
+ char *attr_cn = RA::ra_get_cert_cn(e);
+ PR_snprintf((char *)configname, 256, "%s.%s.ca.conn", OP_PREFIX,
+ tokenType);
+ char *connid = (char *)(RA::GetConfigStore()->GetConfigAsString(configname));
+ if (connid == NULL) {
+ RA::Debug(LL_PER_PDU, "RA_Processor::RevokeCertificates", "Failed to get connection.");
+ status = STATUS_ERROR_REVOKE_CERTIFICATES_FAILED;
+ PR_snprintf(audit_msg, 512, "Failed to connect to CA, status = STATUS_ERROR_REVOKE_CERTIFICATES_FAILED");
+
+ revocation_failed = true;
+ goto loser;
+ }
+ PR_snprintf(serial, 100, "0x%s", attr_serial);
+
+ // if the certificates are revoked_on_hold, dont do
+ // anything because the certificates may be referenced
+ // by more than one token.
+ if (strcmp(attr_status, "revoked_on_hold") == 0) {
+ RA::Debug("RA_Processor::RevokeCertificates", "This is revoked_on_hold certificate, skip it.");
+ if (attr_status != NULL) {
+ PL_strfree(attr_status);
+ attr_status = NULL;
+ }
+ if (attr_serial != NULL) {
+ PL_strfree(attr_serial);
+ attr_serial = NULL;
+ }
+ if (attr_cn != NULL) {
+ PL_strfree(attr_cn);
+ attr_cn = NULL;
+ }
+
+ rc = RA::ra_delete_certificate_entry(e);
+ continue;
+ }
+ statusNum = certEnroll->RevokeCertificate("1", serial, connid, statusString);
+ RA::Debug("RA_Processor::RevokeCertificates", "Revoke cert %s status %d",serial,statusNum);
+
+ if (statusNum == 0) {
+ RA::Audit(EV_FORMAT, AUDIT_MSG_CERT_STATUS_CHANGE, userid,
+ "Success", "revoke", serial, connid, "");
+ PR_snprintf(activity_msg, 512, "certificate %s revoked", serial);
+ RA::tdb_activity(session->GetRemoteIP(), cuid, "format", "success", activity_msg, "", tokenType);
+ RA::ra_update_cert_status(attr_cn, "revoked");
+ } else {
+ RA::Audit(EV_FORMAT, AUDIT_MSG_CERT_STATUS_CHANGE, userid,
+ "Failure", "revoke", serial, connid, statusString);
+ PR_snprintf(activity_msg, 512, "error in revoking certificate %s: %s", serial, statusString);
+ RA::tdb_activity(session->GetRemoteIP(), cuid, "format", "failure", activity_msg, "", tokenType);
+ revocation_failed = true;
+ }
+
+ if (attr_status != NULL) {
+ PL_strfree(attr_status);
+ attr_status = NULL;
+ }
+ if (attr_serial != NULL) {
+ PL_strfree(attr_serial);
+ attr_serial = NULL;
+ }
+ if (attr_cn != NULL) {
+ PL_strfree(attr_cn);
+ attr_cn = NULL;
+ }
+ if (statusString != NULL) {
+ PR_Free(statusString);
+ statusString = NULL;
+ }
+ }
+ rc = RA::ra_delete_certificate_entry(e);
+ }
+ if (result != NULL)
+ ldap_msgfree(result);
+ if (certEnroll != NULL)
+ delete certEnroll;
+ } else {
+ RA::Debug(LL_PER_PDU, "RA_Processor::RevokeCertificates", "Failed to revoke certificates on this token. Certs not found.");
+ status = STATUS_ERROR_REVOKE_CERTIFICATES_FAILED;
+ PR_snprintf(audit_msg, 512, "Failed to revoke certificates on this token. Certs not found. status = STATUS_ERROR_REVOKE_CERTIFICATES_FAILED");
+ revocation_failed = true;
+ goto loser;
+ }
+
+ rc = 0;
+ if (keyVersion != NULL) {
+ rc = RA::tdb_update("", cuid, (char *)final_applet_version, keyVersion, "uninitialized", "", tokenType);
+ }
+
+ if (rc != 0) {
+ RA::Debug(LL_PER_PDU, "RA_Processor::RevokeCertificates",
+ "Failed to update the token database");
+ status = STATUS_ERROR_UPDATE_TOKENDB_FAILED;
+ PR_snprintf(audit_msg, 512, "Revoked certificates but failed to update the token database, status = STATUS_ERROR_UPDATE_TOKENDB_FAILED");
+ goto loser;
+ }
+
+loser:
+
+ return !revocation_failed;
+}
+
+RA_Status RA_Processor::Format(RA_Session *session, NameValueSet *extensions, bool skipAuth)
+{
+ const char *OP_PREFIX="op.format";
+ char configname[256];
+ char *cuid = NULL;
+ char *msn = NULL;
+ const char *tokenType = NULL;
+ PRIntervalTime start, end;
+ RA_Status status = STATUS_NO_ERROR;
+ int rc = -1;
+ Secure_Channel *channel = NULL;
+ Buffer kdd;
+ AuthParams *login = NULL;
+ // char *new_pin = NULL;
+ const char *applet_dir;
+ bool upgrade_enc = false;
+ SecurityLevel security_level = SECURE_MSG_MAC_ENC;
+
+ Buffer *buildID = NULL;
+ Buffer *token_status = NULL;
+ const char* required_version = NULL;
+ const char *appletVersion = NULL;
+ const char *final_applet_version = NULL;
+ const char *userid = PL_strdup( "" );
+ // BYTE se_p1 = 0x00;
+ // BYTE se_p2 = 0x00;
+ const char *expected_version;
+ int requiredV = 0;
+ const char *tksid = NULL;
+ const char *authid = NULL;
+ AuthParams *authParams = NULL;
+ Buffer host_challenge = Buffer(8, (BYTE)0);
+ Buffer key_diversification_data;
+ Buffer key_info_data;
+ Buffer card_challenge;
+ Buffer card_cryptogram;
+ Buffer *cplc_data = NULL;
+ char activity_msg[4096];
+ LDAPMessage *ldapResult = NULL;
+ LDAPMessage *e = NULL;
+ LDAPMessage *result = NULL;
+ char filter[512];
+ Buffer curKeyInfo;
+ BYTE curVersion;
+ char *curKeyInfoStr = NULL;
+ char *newVersionStr = NULL;
+ bool tokenFound = false;
+ int finalKeyVersion = 0;
+ char *keyVersion = NULL;
+ char *xuserid = NULL;
+ char audit_msg[512] = "";
+ char *profile_state = NULL;
+
+ Buffer *CardManagerAID = RA::GetConfigStore()->GetConfigAsBuffer(
+ RA::CFG_APPLET_CARDMGR_INSTANCE_AID,
+ RA::CFG_DEF_CARDMGR_INSTANCE_AID);
+ Buffer *NetKeyAID = RA::GetConfigStore()->GetConfigAsBuffer(
+ RA::CFG_APPLET_NETKEY_INSTANCE_AID,
+ RA::CFG_DEF_NETKEY_INSTANCE_AID);
+ Buffer key_data_set;
+ Buffer token_cuid;
+ Buffer token_msn;
+ RA::Debug(LL_PER_PDU, "RA_Processor::Format",
+ "Begin upgrade process");
+
+ BYTE major_version = 0x0;
+ BYTE minor_version = 0x0;
+ BYTE app_major_version = 0x0;
+ BYTE app_minor_version = 0x0;
+ const char *connid = NULL;
+ int upgrade_rc;
+
+ start = PR_IntervalNow();
+
+ RA::Debug("RA__Processor::Format", "Client %s", session->GetRemoteIP());
+
+
+ SelectApplet(session, 0x04, 0x00, CardManagerAID);
+ cplc_data = GetData(session);
+ if (cplc_data == NULL) {
+ RA::Error("RA_Format_Processor::Process",
+ "Get Data Failed");
+ status = STATUS_ERROR_SECURE_CHANNEL;
+ PR_snprintf(audit_msg, 512, "Get Data Failed, status = STATUS_ERROR_SECURE_CHANNEL");
+ goto loser;
+ }
+ RA::DebugBuffer("RA_Processor::Format", "CPLC Data = ",
+ cplc_data);
+ if (cplc_data->size() < 47) {
+ RA::Error("RA_Format_Processor::Process",
+ "Invalid CPLC Size");
+ status = STATUS_ERROR_SECURE_CHANNEL;
+ PR_snprintf(audit_msg, 512, "Invalid CPLC Size, status = STATUS_ERROR_SECURE_CHANNEL");
+ goto loser;
+ }
+ token_cuid = Buffer(cplc_data->substr(3,4)) +
+ Buffer(cplc_data->substr(19,2)) +
+ Buffer(cplc_data->substr(15,4));
+ RA::DebugBuffer("RA_Processor::Format", "Token CUID= ",
+ &token_cuid);
+ cuid = Util::Buffer2String(token_cuid);
+
+ token_msn = Buffer(cplc_data->substr(41, 4));
+ RA::DebugBuffer("RA_Processor::Format", "Token MSN= ",
+ &token_msn);
+ msn = Util::Buffer2String(token_msn);
+
+
+ /**
+ * Checks if the netkey has the required applet version.
+ */
+ SelectApplet(session, 0x04, 0x00, NetKeyAID);
+ token_status = GetStatus(session, 0x00, 0x00);
+ if (token_status == NULL) {
+ major_version = 0;
+ minor_version = 0;
+ app_major_version = 0x0;
+ app_minor_version = 0x0;
+ } else {
+ major_version = ((BYTE*)*token_status)[0];
+ minor_version = ((BYTE*)*token_status)[1];
+ app_major_version = ((BYTE*)*token_status)[2];
+ app_minor_version = ((BYTE*)*token_status)[3];
+ }
+
+ RA::Debug(LL_PER_PDU, "RA_Processor::Format",
+ "Major=%d Minor=%d", major_version, minor_version);
+ RA::Debug(LL_PER_PDU, "RA_Processor::Format",
+ "Applet Major=%d Applet Minor=%d", app_major_version, app_minor_version);
+
+ if (!GetTokenType(OP_PREFIX, major_version,
+ minor_version, cuid, msn,
+ extensions, status, tokenType)) {
+ PR_snprintf(audit_msg, 512, "Failed to get token type");
+ goto loser;
+ }
+
+ // check if profile is enabled
+ PR_snprintf((char *)configname, 256, "config.Profiles.%s.state", tokenType);
+ profile_state = (char *) RA::GetConfigStore()->GetConfigAsString(configname);
+ if ((profile_state != NULL) && (PL_strcmp(profile_state, "Enabled") != 0)) {
+ RA::Error("RA_Format_Processor::Process", "Profile %s Disabled for CUID %s", tokenType, cuid);
+ status = STATUS_ERROR_DEFAULT_TOKENTYPE_PARAMS_NOT_FOUND;
+ PR_snprintf(audit_msg, 512, "profile %s disabled", tokenType);
+ goto loser;
+ }
+
+ if (RA::ra_is_token_present(cuid)) {
+ RA::Debug("RA_Processor::Format",
+ "Found token %s", cuid);
+
+ if (RA::ra_is_tus_db_entry_disabled(cuid)) {
+ RA::Error("RA_Format_Processor::Process",
+ "CUID %s Disabled", cuid);
+ status = STATUS_ERROR_DISABLED_TOKEN;
+ PR_snprintf(audit_msg, 512, "CUID %s Disabled, status=STATUS_ERROR_DISABLED_TOKEN", cuid);
+ goto loser;
+ }
+ } else {
+ RA::Debug("RA_Processor::Format",
+ "Not Found token %s", cuid);
+ // This is a new token. We need to check our policy to see
+ // if we should allow enrollment. raidzilla #57414
+ PR_snprintf((char *)configname, 256, "%s.allowUnknownToken",
+ OP_PREFIX);
+ if (!RA::GetConfigStore()->GetConfigAsBool(configname, 1)) {
+ RA::Error("Process", "CUID %s Format Unknown Token", cuid);
+ status = STATUS_ERROR_DISABLED_TOKEN;
+ PR_snprintf(audit_msg, 512, "Unknown token disallowed, status=STATUS_ERROR_DISABLED_TOKEN");
+ goto loser;
+ }
+
+ }
+
+ // we know cuid and msn here
+ RA::Audit(EV_FORMAT, AUDIT_MSG_PROC,
+ userid != NULL ? userid : "",
+ cuid != NULL ? cuid : "",
+ msn != NULL ? msn : "",
+ "success",
+ "format",
+ final_applet_version != NULL ? final_applet_version : "",
+ keyVersion != NULL? keyVersion : "",
+ "token enabled");
+
+ PR_snprintf((char *)configname, 256, "%s.%s.tks.conn",
+ OP_PREFIX, tokenType);
+ tksid = RA::GetConfigStore()->GetConfigAsString(configname);
+ if (tksid == NULL) {
+ RA::Error("RA_Format_Processor::Process",
+ "TKS Connection Parameter %s Not Found", configname);
+ status = STATUS_ERROR_DEFAULT_TOKENTYPE_NOT_FOUND;
+ PR_snprintf(audit_msg, 512, "TKS Connection Parameter %s Not Found, status = STATUS_ERROR_DEFAULT_TOKENTYPE_NOT_FOUND", configname);
+ goto loser;
+ }
+
+ buildID = GetAppletVersion(session);
+ if (buildID == NULL) {
+ PR_snprintf((char *)configname, 256, "%s.%s.update.applet.emptyToken.enable", OP_PREFIX, tokenType);
+ if (RA::GetConfigStore()->GetConfigAsBool(configname, 0)) {
+ appletVersion = PL_strdup( "" );
+ } else {
+ RA::Error("RA_Format_Processor::Process",
+ "no applet found and applet upgrade not enabled");
+ status = STATUS_ERROR_SECURE_CHANNEL;
+ PR_snprintf(audit_msg, 512, "No applet found and applet upgrade not enabled, status = STATUS_ERROR_SECURE_CHANNEL");
+ goto loser;
+ }
+ } else {
+ char * buildid = Util::Buffer2String(*buildID);
+ RA::Debug("RA_Processor::Format", "buildid = %s", buildid);
+ char version[13];
+ PR_snprintf((char *) version, 13,
+ "%x.%x.%s", app_major_version, app_minor_version,
+ buildid);
+ appletVersion = strdup(version);
+ if (buildid != NULL) {
+ PR_Free(buildid);
+ buildid=NULL;
+ }
+ }
+
+ final_applet_version = strdup(appletVersion);
+ RA::Debug("RA_Processor::Format", "final_applet_version = %s", final_applet_version);
+
+ /**
+ * Checks if we need to upgrade applet.
+ */
+ PR_snprintf((char *)configname, 256, "%s.%s.update.applet.requiredVersion", OP_PREFIX, tokenType);
+
+ required_version = RA::GetConfigStore()->GetConfigAsString(
+ configname);
+ expected_version = PL_strdup(required_version);
+
+ if (expected_version == NULL) {
+ RA::Error("RA_Format_Processor::Process",
+ "upgrade.version not found");
+ status = STATUS_ERROR_MISCONFIGURATION;
+ PR_snprintf(audit_msg, 512, "Upgrade version not found, status = STATUS_ERROR_MISCONFIGURATION");
+ goto loser;
+ }
+ /* upgrade applet */
+ PR_snprintf((char *)configname, 256, "%s.%s.update.applet.directory", OP_PREFIX, tokenType);
+ applet_dir = RA::GetConfigStore()->GetConfigAsString(configname);
+ if (applet_dir == NULL || strlen(applet_dir) == 0) {
+ RA::Error(LL_PER_PDU, "RA_Processor::UpdateApplet",
+ "Failed to get %s", applet_dir);
+ status = STATUS_ERROR_MISCONFIGURATION;
+ PR_snprintf(audit_msg, 512, "Failed to get %s, status = STATUS_ERROR_MISCONFIGURATION", applet_dir);
+ goto loser;
+ }
+
+ PR_snprintf((char *)configname, 256, "%s.%s.loginRequest.enable", OP_PREFIX, tokenType);
+ if (RA::GetConfigStore()->GetConfigAsBool(configname, 1) && !skipAuth) {
+ if (extensions != NULL &&
+ extensions->GetValue("extendedLoginRequest") != NULL)
+ {
+ RA::Debug("RA_rocessor::Format",
+ "Extended Login Request detected");
+ AuthenticationEntry *entry = GetAuthenticationEntry(
+ OP_PREFIX, configname, tokenType);
+ char **params = NULL;
+ char pb[1024];
+ char *locale = NULL;
+ if (extensions != NULL &&
+ extensions->GetValue("locale") != NULL)
+ {
+ locale = extensions->GetValue("locale");
+ } else {
+ locale = ( char * ) "en"; /* default to english */
+ }
+ int n = entry->GetAuthentication()->GetNumOfParamNames();
+ if (n > 0) {
+ RA::Debug("RA_Processor::Format",
+ "Extended Login Request detected n=%d", n);
+ params = (char **) PR_Malloc(n);
+ for (int i = 0; i < n; i++) {
+ sprintf(pb,"id=%s&name=%s&desc=%s&type=%s&option=%s",
+ entry->GetAuthentication()->GetParamID(i),
+ entry->GetAuthentication()->GetParamName(i, locale),
+ entry->GetAuthentication()->GetParamDescription(i,
+locale),
+ entry->GetAuthentication()->GetParamType(i),
+ entry->GetAuthentication()->GetParamOption(i)
+ );
+ params[i] = PL_strdup(pb);
+ RA::Debug("RA_Processor::Format",
+ "params[i]=%s", params[i]);
+ }
+ }
+ RA::Debug("RA_rocessor::Format", "Extended Login Request detected calling RequestExtendedLogin() locale=%s", locale);
+
+ char *title = PL_strdup(entry->GetAuthentication()->GetTitle(locale));
+ RA::Debug("RA_Processor::Format", "title=%s", title);
+ char *description = PL_strdup(entry->GetAuthentication()->GetDescription(locale));
+ RA::Debug("RA_Processor::Format", "description=%s", description);
+ login = RequestExtendedLogin(session, 0 /* invalid_pw */, 0 /* blocked */, params, n, title, description);
+
+ if (params != NULL) {
+ for (int nn=0; nn < n; nn++) {
+ if (params[nn] != NULL) {
+ PL_strfree(params[nn]);
+ params[nn] = NULL;
+ }
+ }
+ free(params);
+ params = NULL;
+ }
+
+ if (title != NULL) {
+ PL_strfree(title);
+ title = NULL;
+ }
+
+ if (description != NULL) {
+ PL_strfree(description);
+ description = NULL;
+ }
+
+
+ RA::Debug("RA_Processor::Format",
+ "Extended Login Request detected calling RequestExtendedLogin() login=%x", login);
+ } else {
+ login = RequestLogin(session, 0 /* invalid_pw */, 0 /* blocked */);
+ }
+ if (login == NULL) {
+ RA::Error("RA_Format_Processor::Process",
+ "login not provided");
+ status = STATUS_ERROR_LOGIN;
+ PR_snprintf(audit_msg, 512, "login not provided, status = STATUS_ERROR_LOGIN");
+ goto loser;
+ }
+ if( userid != NULL ) {
+ PR_Free( (char *) userid );
+ userid = NULL;
+ }
+ if (login->GetUID() == NULL) {
+ userid = NULL;
+ } else {
+ userid = PL_strdup( login->GetUID() );
+ }
+ }
+
+ // send status update to the client
+ if (extensions != NULL &&
+ extensions->GetValue("statusUpdate") != NULL) {
+ StatusUpdate(session, 2 /* progress */,
+ "PROGRESS_START_AUTHENTICATION");
+ }
+
+ PR_snprintf((char *)configname, 256, "%s.%s.auth.enable", OP_PREFIX, tokenType);
+ if (RA::GetConfigStore()->GetConfigAsBool(configname, false) && !skipAuth) {
+ if (login == NULL) {
+ RA::Error("RA_Format_Processor::Process", "Login Request Disabled. Authentication failed.");
+ status = STATUS_ERROR_LOGIN;
+ PR_snprintf(audit_msg, 512, "login request disabled, status = STATUS_ERROR_LOGIN");
+ goto loser;
+ }
+
+ PR_snprintf((char *)configname, 256, "%s.%s.auth.id", OP_PREFIX, tokenType);
+ authid = RA::GetConfigStore()->GetConfigAsString(configname);
+ if (authid == NULL) {
+ status = STATUS_ERROR_LOGIN;
+ PR_snprintf(audit_msg, 512, "login not found, status = STATUS_ERROR_LOGIN");
+ goto loser;
+ }
+ AuthenticationEntry *auth = RA::GetAuth(authid);
+
+ if(auth == NULL)
+ {
+ RA::Error("RA_Format_Processor::Process", "Authentication manager is NULL . Authentication failed.");
+ status = STATUS_ERROR_LOGIN;
+ PR_snprintf(audit_msg, 512, "authentication manager is NULL, status = STATUS_ERROR_LOGIN");
+ goto loser;
+ }
+
+ char *type = auth->GetType();
+ if (type == NULL) {
+ status = STATUS_ERROR_LOGIN;
+ PR_snprintf(audit_msg, 512, "authentication is missing param type, status = STATUS_ERROR_LOGIN");
+ goto loser;
+ }
+ if (strcmp(type, "LDAP_Authentication") == 0) {
+ RA::Debug(LL_PER_PDU, "RA_Format_Processor::Process",
+ "LDAP_Authentication is invoked.");
+ int passwd_retries = auth->GetAuthentication()->GetNumOfRetries();
+ int retries = 0;
+ authParams = new AuthParams();
+ authParams->SetUID(login->GetUID());
+ authParams->SetPassword(login->GetPassword());
+ rc = auth->GetAuthentication()->Authenticate(authParams);
+
+ RA::Debug("RA_Format_Processor::Process",
+ "Authenticate returns: %d", rc);
+
+ while ((rc == -2 || rc == -3) && (retries < passwd_retries)) {
+ login = RequestLogin(session, 0 /* invalid_pw */, 0 /* blocked */);
+ retries++;
+ if (login == NULL || login->GetUID() == NULL) {
+ RA::Error("RA_Format_Processor::Process", "Authentication failed.");
+ status = STATUS_ERROR_LOGIN;
+ PR_snprintf(audit_msg, 512, "authentication failed, status = STATUS_ERROR_LOGIN");
+ goto loser;
+ }
+ authParams->SetUID(login->GetUID());
+ authParams->SetPassword(login->GetPassword());
+ rc = auth->GetAuthentication()->Authenticate(authParams);
+ }
+
+ if (rc == -1) {
+ RA::Error("RA_Format_Processor::Process", "Authentication failed.");
+ status = STATUS_ERROR_LDAP_CONN;
+ RA::Debug(LL_PER_PDU, "RA_Processor::Format", "Authentication status = %d", status);
+ PR_snprintf(audit_msg, 512, "Authentication failed, status = STATUS_ERROR_LDAP_CONN");
+ goto loser;
+ }
+
+ if (rc == -2 || rc == -3) {
+ RA::Error("RA_Format_Processor::Process", "Authentication failed.");
+ status = STATUS_ERROR_LOGIN;
+ RA::Debug(LL_PER_PDU, "RA_Processor::Format", "Authentication status = %d", status);
+ PR_snprintf(audit_msg, 512, "Authentication failed, rc=-2 or -3, status = STATUS_ERROR_LOGIN");
+ goto loser;
+ }
+
+ RA::Debug(LL_PER_PDU, "RA_Processor::Format", "Authentication successful.");
+ } else {
+ RA::Error("RA_Format_Processor::Process", "No Authentication type was found.");
+ status = STATUS_ERROR_LOGIN;
+ PR_snprintf(audit_msg, 512, "No Authentication type found, status = STATUS_ERROR_LOGIN");
+ goto loser;
+ }
+ } else {
+ RA::Debug(LL_PER_PDU, "RA_Processor::Format",
+ "Authentication has been disabled.");
+ }
+
+ // check if it is the token owner
+ xuserid = RA::ra_get_token_userid(cuid);
+ if (xuserid != NULL && strcmp(xuserid, "") != 0) {
+ if (login != NULL) {
+ if (strcmp(login->GetUID(), xuserid) != 0) {
+ RA::Debug(LL_PER_PDU, "RA_Processor::Format",
+ "Token owner mismatched");
+ status = STATUS_ERROR_NOT_TOKEN_OWNER;
+ PR_snprintf(audit_msg, 512, "Token owner mismatched, status = STATUS_ERROR_NOT_TOKEN_OWNER");
+ goto loser;
+ }
+ }
+ }
+
+ // we know cuid, msn and userid here
+ RA::Audit(EV_FORMAT, AUDIT_MSG_PROC,
+ userid != NULL ? userid : "",
+ cuid != NULL ? cuid : "",
+ msn != NULL ? msn : "",
+ "success",
+ "format",
+ final_applet_version != NULL ? final_applet_version : "",
+ keyVersion != NULL? keyVersion : "",
+ "logged into token");
+
+ if (extensions != NULL &&
+ extensions->GetValue("statusUpdate") != NULL) {
+ StatusUpdate(session, 10 /* progress */,
+ "PROGRESS_APPLET_UPGRADE");
+ }
+
+ PR_snprintf((char *)configname, 256, "%s.%s.update.applet.encryption", OP_PREFIX, tokenType);
+ upgrade_enc = RA::GetConfigStore()->GetConfigAsBool(configname, true);
+ if (!upgrade_enc)
+ security_level = SECURE_MSG_MAC;
+ PR_snprintf((char *)configname, 256, "%s.%s.tks.conn", OP_PREFIX, tokenType);
+ connid = RA::GetConfigStore()->GetConfigAsString(configname);
+ upgrade_rc = UpgradeApplet(session,(char *) OP_PREFIX, (char*)tokenType, major_version,
+ minor_version, expected_version, applet_dir, security_level, connid,
+ extensions, 10, 90, &keyVersion);
+ if (upgrade_rc != 1) {
+ RA::Debug("RA_Processor::Format",
+ "applet upgrade failed");
+ status = STATUS_ERROR_UPGRADE_APPLET;
+ /**
+ * Bugscape #55709: Re-select Net Key Applet ONLY on failure.
+ */
+ SelectApplet(session, 0x04, 0x00, NetKeyAID);
+ RA::tdb_activity(session->GetRemoteIP(), cuid, "format", "failure", "applet upgrade error", "", tokenType);
+ // rc = -1 denotes Secure Channel Failure
+
+ if (rc == -1) {
+ RA::Audit(EV_APPLET_UPGRADE, AUDIT_MSG_APPLET_UPGRADE,
+ userid, cuid, msn, "Failure", "format",
+ keyVersion != NULL? keyVersion : "", appletVersion, expected_version, "failed to setup secure channel");
+ } else {
+
+ RA::Audit(EV_APPLET_UPGRADE, AUDIT_MSG_APPLET_UPGRADE,
+ userid, cuid, msn, "Success", "format",
+ keyVersion != NULL? keyVersion : "", appletVersion, expected_version, "setup secure channel");
+ }
+
+ RA::Audit(EV_APPLET_UPGRADE, AUDIT_MSG_APPLET_UPGRADE,
+ userid, cuid, msn, "Failure", "format",
+ keyVersion != NULL? keyVersion : "", appletVersion, expected_version, "applet upgrade");
+
+ goto loser;
+ }
+
+ RA::Audit(EV_APPLET_UPGRADE, AUDIT_MSG_APPLET_UPGRADE,
+ userid, cuid, msn, "Success", "format",
+ keyVersion != NULL? keyVersion : "", appletVersion, expected_version, "setup secure channel");
+
+ RA::Audit(EV_APPLET_UPGRADE, AUDIT_MSG_APPLET_UPGRADE,
+ userid, cuid, msn, "Success", "format",
+ keyVersion != NULL? keyVersion : "", appletVersion, expected_version, "applet upgrade");
+
+ if( final_applet_version != NULL ) {
+ PR_Free( (char *) final_applet_version );
+ final_applet_version = NULL;
+ }
+
+ final_applet_version = expected_version;
+
+ if (extensions != NULL &&
+ extensions->GetValue("statusUpdate") != NULL) {
+ StatusUpdate(session, 90 /* progress */,
+ "PROGRESS_KEY_UPGRADE");
+ }
+
+ // add issuer info to the token
+ PR_snprintf((char *)configname, 256, "%s.%s.issuerinfo.enable",
+ OP_PREFIX, tokenType);
+ if (RA::GetConfigStore()->GetConfigAsBool(configname, 0)) {
+ PR_snprintf((char *)configname, 256,"channel.defKeyIndex");
+ int defKeyIndex = RA::GetConfigStore()->GetConfigAsInt(configname, 0x0);
+ channel = SetupSecureChannel(session, 0x00,
+ defKeyIndex /* default key index */, connid);
+ rc = channel->ExternalAuthenticate();
+ if (channel != NULL) {
+ char issuer[224];
+ for (int i = 0; i < 224; i++) {
+ issuer[i] = 0;
+ }
+ PR_snprintf((char *)configname, 256, "%s.%s.issuerinfo.value",
+ OP_PREFIX, tokenType);
+ char *issuer_val = (char*)RA::GetConfigStore()->GetConfigAsString(
+ configname);
+ sprintf(issuer, "%s", issuer_val);
+ RA::Debug("RA_Processor::Format", "Set Issuer Info %s", issuer_val);
+ Buffer *info = new Buffer((BYTE*)issuer, 224);
+ rc = channel->SetIssuerInfo(info);
+
+ if (info != NULL) {
+ delete info;
+ info = NULL;
+ }
+ }
+ }
+
+ /**
+ * Checks if the netkey has the required key version.
+ */
+ PR_snprintf((char *)configname, 256, "%s.%s.update.symmetricKeys.enable", OP_PREFIX, tokenType);
+ if (RA::GetConfigStore()->GetConfigAsBool(configname, 1)) {
+
+ PR_snprintf((char *)configname, 256, "%s.%s.update.symmetricKeys.requiredVersion", OP_PREFIX, tokenType);
+ requiredV = RA::GetConfigStore()->GetConfigAsInt(configname, 0x00);
+ PR_snprintf((char *)configname, 256, "%s.%s.tks.conn", OP_PREFIX, tokenType);
+ tksid = RA::GetConfigStore()->GetConfigAsString(configname);
+ PR_snprintf((char *)configname, 256,"channel.defKeyIndex");
+ int defKeyIndex = RA::GetConfigStore()->GetConfigAsInt(configname, 0x0);
+ channel = SetupSecureChannel(session, requiredV,
+ defKeyIndex /* default key index */, tksid);
+ if (channel == NULL) {
+ /**
+ * Select Card Manager for Put Key operation.
+ */
+ SelectApplet(session, 0x04, 0x00, CardManagerAID);
+ // send status update to the client
+ if (extensions != NULL &&
+ extensions->GetValue("statusUpdate") != NULL) {
+ StatusUpdate(session, 92 /* progress */,
+ "PROGRESS_SETUP_SECURE_CHANNEL");
+ }
+ /* if the key of the required version is
+ * not found, create them.
+ */
+ PR_snprintf((char *)configname, 256,"channel.defKeyVersion");
+ int defKeyVer = RA::GetConfigStore()->GetConfigAsInt(configname, 0x0);
+ PR_snprintf((char *)configname, 256,"channel.defKeyIndex");
+ int defKeyIndex = RA::GetConfigStore()->GetConfigAsInt(configname, 0x0);
+ channel = SetupSecureChannel(session,
+ defKeyVer, /* default key version */
+ defKeyIndex /* default key index */, tksid);
+
+ if (channel == NULL) {
+ RA::Error("RA_Upgrade_Processor::Process",
+ "failed to establish secure channel");
+ status = STATUS_ERROR_SECURE_CHANNEL;
+ PR_snprintf(audit_msg, 512, "Failed to establish secure channel");
+ goto loser;
+ }
+
+ // send status update to the client
+ if (extensions != NULL &&
+ extensions->GetValue("statusUpdate") != NULL) {
+ StatusUpdate(session, 94 /* progress */,
+ "PROGRESS_EXTERNAL_AUTHENTICATE");
+ }
+
+ rc = channel->ExternalAuthenticate();
+
+ PR_snprintf((char *)configname, 256, "%s.%s.update.symmetricKeys.requiredVersion", OP_PREFIX, tokenType);
+ int v = RA::GetConfigStore()->GetConfigAsInt(configname, 0x00);
+ curKeyInfo = channel->GetKeyInfoData();
+ BYTE nv[2] = { v, 0x01 };
+ Buffer newVersion(nv, 2);
+ PR_snprintf((char *)configname, 256,"%s.%s.tks.conn", OP_PREFIX, tokenType);
+ connid = RA::GetConfigStore()->GetConfigAsString(configname);
+ rc = CreateKeySetData(
+ channel->GetKeyDiversificationData(),
+ curKeyInfo,
+ newVersion,
+ key_data_set, connid);
+ if (rc != 1) {
+ RA::Error("RA_Format_Processor::Process",
+ "failed to create new key set");
+ status = STATUS_ERROR_CREATE_CARDMGR;
+ PR_snprintf(audit_msg, 512, "create key set error, status = STATUS_ERROR_CREATE_CARDMGR");
+ goto loser;
+ }
+
+ curVersion = ((BYTE*)curKeyInfo)[0];
+
+
+ // send status update to the client
+ if (extensions != NULL &&
+ extensions->GetValue("statusUpdate") != NULL) {
+ StatusUpdate(session, 96 /* progress */,
+ "PROGRESS_PUT_KEYS");
+ }
+
+ BYTE curIndex = ((BYTE*)curKeyInfo)[1];
+ rc = channel->PutKeys(session,
+ curVersion,
+ curIndex,
+ &key_data_set);
+
+
+ // need to check return value of rc
+ // and create audit log for failure
+
+ curKeyInfoStr = Util::Buffer2String(curKeyInfo);
+ newVersionStr = Util::Buffer2String(newVersion);
+
+ char curVer[10];
+ char newVer[10];
+
+ if(curKeyInfoStr != NULL && strlen(curKeyInfoStr) >= 2) {
+ curVer[0] = curKeyInfoStr[0]; curVer[1] = curKeyInfoStr[1]; curVer[2] = 0;
+ }
+ else {
+ curVer[0] = 0;
+ }
+
+ if(newVersionStr != NULL && strlen(newVersionStr) >= 2) {
+ newVer[0] = newVersionStr[0] ; newVer[1] = newVersionStr[1] ; newVer[2] = 0;
+ }
+ else {
+ newVer[0] = 0;
+ }
+
+ if (rc != 0) {
+ RA::Audit(EV_KEY_CHANGEOVER, AUDIT_MSG_KEY_CHANGEOVER,
+ userid != NULL ? userid : "", cuid != NULL ? cuid : "", msn != NULL ? msn : "", "Failure", "format",
+ final_applet_version != NULL ? final_applet_version : "", curVer, newVer,
+ "key changeover failed");
+ // do we goto loser here?
+ }
+
+ finalKeyVersion = ((int) ((BYTE *)newVersion)[0]);
+ /**
+ * Re-select Net Key Applet.
+ */
+ SelectApplet(session, 0x04, 0x00, NetKeyAID);
+ PR_snprintf((char *)configname, 256, "%s.%s.update.symmetricKeys.requiredVersion", OP_PREFIX, tokenType);
+ requiredV = RA::GetConfigStore()->GetConfigAsInt(configname, 0x00);
+ PR_snprintf((char *)configname, 256, "%s.%s.tks.conn", OP_PREFIX, tokenType);
+ tksid = RA::GetConfigStore()->GetConfigAsString(configname);
+ if( channel != NULL ) {
+ delete channel;
+ channel = NULL;
+ }
+ // send status update to the client
+ if (extensions != NULL &&
+ extensions->GetValue("statusUpdate") != NULL) {
+ StatusUpdate(session, 98 /* progress */,
+ "PROGRESS_SETUP_SECURE_CHANNEL");
+ }
+
+
+ channel = SetupSecureChannel(session, requiredV,
+ defKeyIndex /* default key index */, tksid);
+ if (channel == NULL) {
+ RA::Error("RA_Format_Processor::Process",
+ "failed to establish secure channel after reselect");
+ status = STATUS_ERROR_CREATE_CARDMGR;
+ PR_snprintf(audit_msg, 512,"failed to establish secure channel after reselect, status = STATUS_ERROR_CREATE_CARDMGR");
+ goto loser;
+ }
+
+ RA::Audit(EV_KEY_CHANGEOVER, AUDIT_MSG_KEY_CHANGEOVER,
+ userid != NULL ? userid : "", cuid != NULL ? cuid : "", msn != NULL ? msn : "", "Success", "format",
+ final_applet_version != NULL ? final_applet_version : "", curVer, newVer,
+ "key changeover");
+
+ }
+ }
+
+ PR_snprintf((char *)filter, 256, "(cn=%s)", cuid);
+ rc = RA::ra_find_tus_token_entries(filter, 100, &result, 0);
+ if (rc == 0) {
+ for (e = RA::ra_get_first_entry(result); e != NULL; e = RA::ra_get_next_entry(e)) {
+ tokenFound = true;
+ break;
+ }
+ if (result != NULL)
+ ldap_msgfree(result);
+ }
+
+ // get keyVersion
+ if (channel != NULL) {
+ if (keyVersion != NULL) {
+ PR_Free( (char *) keyVersion );
+ keyVersion = NULL;
+ }
+ keyVersion = Util::Buffer2String(channel->GetKeyInfoData());
+ }
+
+ // need to revoke all the certificates on this token
+ if (tokenFound) {
+
+ //Now we call a separate function, the audit_msg will get filled in there if needed.
+
+ bool success = RevokeCertificates(session, cuid,audit_msg,(char *)final_applet_version,
+ keyVersion,(char *)tokenType,(char *)userid,status
+ );
+
+ if(!success) {
+ goto loser;
+ }
+
+ } else {
+ rc = RA::tdb_update("", cuid, (char *)final_applet_version, keyVersion, "uninitialized", "", tokenType);
+ if (rc != 0) {
+ RA::Debug(LL_PER_PDU, "RA_Processor::Format",
+ "Failed to update the token database");
+ status = STATUS_ERROR_UPDATE_TOKENDB_FAILED;
+ PR_snprintf(audit_msg, 512, "Failed to update the token database, status = STATUS_ERROR_UPDATE_TOKENDB_FAILED");
+ goto loser;
+ }
+ }
+
+ // send status update to the client
+ if (extensions != NULL &&
+ extensions->GetValue("statusUpdate") != NULL) {
+ StatusUpdate(session, 100 /* progress */,
+ "PROGRESS_DONE");
+ }
+
+ status = STATUS_NO_ERROR;
+ rc = 1;
+
+ end = PR_IntervalNow();
+
+ sprintf(activity_msg, "applet_version=%s tokenType=%s",
+ final_applet_version, tokenType);
+ RA::tdb_activity(session->GetRemoteIP(), cuid, "format", "success", activity_msg, userid, tokenType);
+
+ /* audit log for successful format */
+ if (authid != NULL) {
+ sprintf(activity_msg, "format processing complete, authid = %s", authid);
+ } else {
+ sprintf(activity_msg, "format processing complete");
+ }
+ RA::Audit(EV_FORMAT, AUDIT_MSG_PROC,
+ userid, cuid, msn, "success", "format", final_applet_version,
+ keyVersion != NULL? keyVersion : "", activity_msg);
+
+loser:
+ if (strlen(audit_msg) > 0) { // a failure occurred
+ RA::Audit(EV_FORMAT, AUDIT_MSG_PROC,
+ userid != NULL ? userid : "",
+ cuid != NULL ? cuid : "",
+ msn != NULL ? msn : "",
+ "failure",
+ "format",
+ final_applet_version != NULL ? final_applet_version : "",
+ keyVersion != NULL? keyVersion : "",
+ audit_msg);
+
+ if ((cuid != NULL) && (tokenType != NULL)) {
+ RA::tdb_activity(session->GetRemoteIP(),
+ cuid,
+ "format",
+ "failure",
+ audit_msg,
+ userid != NULL? userid : "",
+ tokenType);
+ }
+ }
+
+ if (curKeyInfoStr != NULL) {
+ PR_Free( (char *) curKeyInfoStr);
+ curKeyInfoStr = NULL;
+ }
+
+ if (newVersionStr != NULL) {
+ PR_Free( (char *) newVersionStr);
+ newVersionStr = NULL;
+ }
+
+ if (keyVersion != NULL) {
+ PR_Free( (char *) keyVersion );
+ keyVersion = NULL;
+ }
+
+ if (ldapResult != NULL) {
+ ldap_msgfree(ldapResult);
+ }
+
+ if( cplc_data != NULL ) {
+ delete cplc_data;
+ cplc_data = NULL;
+ }
+ if( CardManagerAID != NULL ) {
+ delete CardManagerAID;
+ CardManagerAID = NULL;
+ }
+ if( NetKeyAID != NULL ) {
+ delete NetKeyAID;
+ NetKeyAID = NULL;
+ }
+ if( channel != NULL ) {
+ delete channel;
+ channel = NULL;
+ }
+ if( token_status != NULL ) {
+ delete token_status;
+ token_status = NULL;
+ }
+ if( buildID != NULL ) {
+ delete buildID;
+ buildID = NULL;
+ }
+ if( appletVersion != NULL ) {
+ PR_Free( (char *) appletVersion );
+ appletVersion = NULL;
+ }
+ if( final_applet_version != NULL ) {
+ PR_Free( (char *) final_applet_version );
+ final_applet_version = NULL;
+ }
+ if( userid != NULL ) {
+ PR_Free( (char *) userid );
+ userid = NULL;
+ }
+ if( cuid != NULL ) {
+ PR_Free( cuid );
+ cuid = NULL;
+ }
+ if( msn != NULL ) {
+ PR_Free( msn );
+ msn = NULL;
+ }
+ if( authParams != NULL ) {
+ delete authParams;
+ authParams = NULL;
+ }
+ if( login != NULL ) {
+ delete login;
+ login = NULL;
+ }
+
+#ifdef MEM_PROFILING
+ MEM_dump_unfree();
+#endif
+
+ RA::Debug("RA_Processor::Format"," returning status %d", status);
+ return status;
+}
+
+/**
+ * Process the current session. It does nothing in the base
+ * class.
+ */
+RA_Status RA_Processor::Process(RA_Session *session, NameValueSet *extensions)
+{
+ return STATUS_NO_ERROR;
+} /* Process */
+