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.cpp2227
1 files changed, 2227 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..ca04b573e
--- /dev/null
+++ b/pki/base/tps/src/processor/RA_Processor.cpp
@@ -0,0 +1,2227 @@
+// --- 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 "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 ()
+{
+}
+
+
+/**
+ * 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)
+{
+ 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 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.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");
+ goto loser;
+ }
+
+ 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 */);
+
+ /* 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;
+
+ 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;
+ 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;
+ 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];
+ 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);
+ return SelectApplet(session, 0x04, 0x00, CardManagerAID);
+}
+
+/**
+ * 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");
+ 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)
+{
+ 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;
+
+ RA::Debug(LL_PER_PDU, "RA_Processor::InitializeUpdate",
+ "RA_Processor::InitializeUpdate");
+
+ if (Util::GetRandomChallenge(host_challenge) != PR_SUCCESS)
+ {
+ 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;
+
+ RA::Debug(LL_PER_PDU, "RA_Processor::Setup_Secure_Channel",
+ "RA_Processor::Setup_Secure_Channel");
+
+ 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 == "") || (drm_desKey_s == NULL)) {
+ 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 == "") || (kek_desKey_s == NULL)) {
+ 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 == "") || (keycheck_s == NULL)) {
+ 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];
+ // 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 = Util::SpecialURLEncode(in);
+ 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, cuid, versionID,keySet);
+ PR_snprintf((char *)configname, 256, "conn.%s.servlet.encryptData", connid);
+ const char *servletID = RA::GetConfigStore()->GetConfigAsString(configname);
+
+ if( data != NULL ) {
+ PR_Free( data );
+ data = NULL;
+ }
+ 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;
+ 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];
+ char *rcStr = strstr((char *)p, "encryptedData=");
+ if (rcStr != NULL) {
+ rcStr = &rcStr[14];
+ encryptedData = Util::URLDecode(rcStr);
+ }
+ }
+ }
+ }
+ 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 || encryptedData == NULL) {
+ if (tksConn != NULL) {
+ RA::ReturnTKSConn(tksConn);
+ }
+ return -1;
+ } else {
+ out = *encryptedData;
+ if( encryptedData != NULL ) {
+ delete encryptedData;
+ encryptedData = 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;
+}
+
+/**
+ * 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 */
+