diff -up ./esc/opensc.esc.conf.fix1 ./esc/opensc.esc.conf
--- ./esc/opensc.esc.conf.fix1 2018-04-26 11:44:38.429986239 -0700
+++ ./esc/opensc.esc.conf 2018-04-26 11:44:38.429986239 -0700
@@ -0,0 +1,48 @@
+app default {
+ enable_default_driver = true;
+
+ card_atr
+ 3B:FF:14:00:FF:81:31:FE:45:80:25:A0:00:00:00:56:57:53:43:36:35:30:03:03:38 {
+ pkcs11_enable_InitToken = yes;
+ }
+
+ card_atr
+ 3B:FF:14:00:FF:81:31:FE:45:80:25:A0:00:00:00:56:57:53:43:36:35:30:01:00:39 {
+ pkcs11_enable_InitToken = yes;
+ }
+
+ card_atr
+ 3B:FF:14:00:FF:81:31:FE:45:80:25:A0:00:00:00:56:57:53:43:36:35:30:03:00:3B {
+ pkcs11_enable_InitToken = yes;
+ }
+ reader_driver ctapi {
+ }
+ reader_driver pcsc {
+ }
+ reader_driver openct {
+ };
+ card_drivers = coolkey, cac, piv, default;
+ secure_messaging local_authentic {
+ module_path = /usr/lib64;
+ }
+ framework pkcs15 {
+ builtin_emulators = coolkey, cac, piv;
+ }
+}
+app opensc-pkcs11 {
+ pkcs11 {
+ }
+}
+app onepin-opensc-pkcs11 {
+ pkcs11 {
+ slots_per_card = 1;
+ }
+}
+app tokend {
+ framework tokend {
+ }
+}
+app cardmod {
+ reader_driver cardmod {
+ }
+}
diff -up ./esc/src/app/daemon/manifest.mn.fix1 ./esc/src/app/daemon/manifest.mn
--- ./esc/src/app/daemon/manifest.mn.fix1 2017-07-24 16:46:36.000000000 -0700
+++ ./esc/src/app/daemon/manifest.mn 2018-04-26 14:55:48.926180480 -0700
@@ -30,13 +30,13 @@ endif
-DEFINES += -I$(SYS_INC)/nspr4 -I$(SYS_INC)/nss3 -I$(SYS_INC)/$(MOZ_OFFSET)/nspr -I$(SYS_INC)/$(MOZ_OFFSET)/nss
+DEFINES += -I$(SYS_INC)/nspr4 -I$(SYS_INC)/nss3 -I$(SYS_INC)/$(MOZ_OFFSET)/nspr -I$(SYS_INC)/$(MOZ_OFFSET)/nss -I$(SYS_INC)/PCSC -I$(CORE_DEPTH)/src/lib/coolkey
DEFINES += $(shell pkg-config --cflags xft)
CPPFLAGS += $(DEFINES) -g
-LDFLAGS += -lstdc++ -L$(CORE_DIST)/$(OBJDIR)/lib -L$(XULRUNNER_LIBS_LDFLAGS) -lnss3 -lnspr4 -lssl3 -lckyapplet $(shell pkg-config --libs xft)
+LDFLAGS += -lstdc++ -L$(CORE_DIST)/$(OBJDIR)/lib -L$(XULRUNNER_LIBS_LDFLAGS) -lnss3 -lnspr4 -lssl3 $(shell pkg-config --libs xft)
LDFLAGS += -lckymanager -lhttpchunked -lm -lnss3 -lplc4 -lplds4 -lX11
# MODULE public and private header directories are implicitly REQUIRED.
diff -up ./esc/src/app/xpcom/Makefile.sdk.fix1 ./esc/src/app/xpcom/Makefile.sdk
--- ./esc/src/app/xpcom/Makefile.sdk.fix1 2017-07-24 16:46:36.000000000 -0700
+++ ./esc/src/app/xpcom/Makefile.sdk 2018-04-26 11:44:38.430986233 -0700
@@ -144,8 +144,8 @@ NSPR_INCLUDE = /usr/include/nspr4
GECKO_INCLUDES = -I $(GECKO_SDK_PATH)/include -I $(GECKO_INCLUDE_PATH) -I $(NSPR_INCLUDE) -I $(NSS_INCLUDE) -I $(GECKO_INCLUDE_PATH)/xpcom
-COOL_INCLUDES = -I $(CORE_INC)/ckymanager -I $(CORE_INC)/httpchuncked
-COOL_LDFLAGS = -L$(CORE_DIST)/lib -lckymanager -lhttpchunked $(CKY_LIB_LDD) -lckyapplet
+COOL_INCLUDES = -I $(CORE_INC)/ckymanager -I $(CORE_INC)/httpchuncked -I /usr/include/PCSC -I $(CORE_DEPTH)/src/lib/coolkey
+COOL_LDFLAGS = -L$(CORE_DIST)/lib -lckymanager -lhttpchunked
OBJECT = rhCoolKey.o
@@ -258,6 +258,7 @@ $(DEPLOY_OBJDIR):
cd $(CORE_DEPTH)/$(DEPLOY_OFFSET)/app/xul/esc; zip -r test.zip * -x *\CVS\* \*.fix*; unzip -d esc test.zip ; rm -f test.zip
$(PYTHON_BIN) $(GECKO_SDK_PATH)/bin/install_app.py $(CORE_DEPTH)$(DEPLOY_OFFSET)/app/xul/esc/esc $(DEPLOY_OBJDIR)/esc --appName esc
+ $(NSINSTALL) $(CORE_DEPTH)/opensc.esc.conf $(DEPLOY_OBJDIR)/esc
ifeq ($(OS_ARCH), Darwin)
mkdir $(DEPLOY_OBJDIR)/$(XULRUNNER_FRAME_BASE)
diff -up ./esc/src/app/xul/esc/application.ini.fix1 ./esc/src/app/xul/esc/application.ini
--- ./esc/src/app/xul/esc/application.ini.fix1 2017-07-24 16:46:36.000000000 -0700
+++ ./esc/src/app/xul/esc/application.ini 2018-04-26 11:44:38.431986227 -0700
@@ -25,7 +25,7 @@ Vendor=RedHat
Name=ESC
;
; This field specifies your application's version. This field is optional.
-Version=1.1.0-24
+Version=1.1.1-1
;
; This field specifies your application's build ID (timestamp). This field is
; required.
@@ -47,6 +47,6 @@ MinVersion=6.0.0
; application requires. It should be specified if your application uses
; unfrozen interfaces. Specifying 1.8 matches all releases with a version
; prefixed by 1.8 (e.g., 1.8a4, 1.8b, 1.8.2).
-MaxVersion=50.0.0
+MaxVersion=60.0.0
[Shell]
diff -up ./esc/src/app/xul/esc/chrome/content/esc/advancedinfo.xul.fix1 ./esc/src/app/xul/esc/chrome/content/esc/advancedinfo.xul
--- ./esc/src/app/xul/esc/chrome/content/esc/advancedinfo.xul.fix1 2017-07-24 16:46:36.000000000 -0700
+++ ./esc/src/app/xul/esc/chrome/content/esc/advancedinfo.xul 2018-04-26 11:44:38.431986227 -0700
@@ -33,7 +33,6 @@
-
diff -up ./esc/src/app/xul/esc/chrome/content/esc/config.xul.fix1 ./esc/src/app/xul/esc/chrome/content/esc/config.xul
--- ./esc/src/app/xul/esc/chrome/content/esc/config.xul.fix1 2017-07-24 16:46:36.000000000 -0700
+++ ./esc/src/app/xul/esc/chrome/content/esc/config.xul 2018-04-26 11:44:38.432986221 -0700
@@ -30,7 +30,6 @@
onunload="cleanup();"
xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul">
-
diff -up ./esc/src/app/xul/esc/chrome/content/esc/ESC.js.fix1 ./esc/src/app/xul/esc/chrome/content/esc/ESC.js
--- ./esc/src/app/xul/esc/chrome/content/esc/ESC.js.fix1 2017-07-24 16:46:36.000000000 -0700
+++ ./esc/src/app/xul/esc/chrome/content/esc/ESC.js 2018-04-26 11:44:38.433986216 -0700
@@ -151,7 +151,6 @@ jsNotify.prototype = {
//
function cleanup()
{
- TrayRemoveWindow(null);
try {
netkey.rhCoolKeyUnSetNotifyCallback(gNotify);
} catch(e) {
@@ -1881,11 +1880,6 @@ function hiddenWindowStartup()
// We do want notify events though
var doPreserveNotify = true;
-
-
- SetMenuItemsText();
- HideWindow();
- TrayRemoveWindow(doPreserveNotify);
}
function IdentifyWindow()
@@ -2950,7 +2944,6 @@ function DoFormatCoolKey(type)
var screennamepwd = null;
var tokencode = null;
-
if (!FormatCoolKey(keyType, keyID, lType, screenname, pin,screennamepwd,tokencode))
{
failed = 1;
@@ -2997,10 +2990,6 @@ function OnCoolKeyInserted(keyType, keyI
var allowNotify = DoCoolKeyGetConfigValue(ESC_ALLOW_NOTIFICATIONS);
recordMessage("Key inserted!" + "Window " + IdentifyWindow());
- if(gHiddenPage)
- {
- TrayShowNotificationIcon();
- }
if (!GetCoolKeyIsEnrolled(keyType, keyID) )
{
@@ -3024,7 +3013,6 @@ function OnCoolKeyInserted(keyType, keyI
SelectRowByKeyID(keyType, keyID);
}
-
if(gHiddenPage)
{
var phoneHomeSuccess = 1;
@@ -3269,12 +3257,11 @@ function Validate()
function OnCoolKeyStateChange(keyType, keyID, keyState, data,strData)
{
- // alert("KeyID: " + keyID + "\n" +
- // "KeyState: " + keyState + "\n" +
- // "Data: " + data);
+ //alert("KeyID: " + keyID + "\n" +
+ // "KeyState: " + keyState + "\n" +
+ // "Data: " + data);
//alert("State Change ="+keyState);
-
switch(keyState)
{
case 1000: // KeyInserted
@@ -4804,3 +4791,8 @@ function GetESCLogPathName(aName)
}
+
+function TraySendNotificationMessage(aTitle,aMessage,aSeverity,aTimeout,aIcon)
+{
+ //alert(aMessage);
+}
diff -up ./esc/src/app/xul/esc/chrome/content/esc/esc.xul.fix1 ./esc/src/app/xul/esc/chrome/content/esc/esc.xul
--- ./esc/src/app/xul/esc/chrome/content/esc/esc.xul.fix1 2017-07-24 16:46:36.000000000 -0700
+++ ./esc/src/app/xul/esc/chrome/content/esc/esc.xul 2018-04-26 11:44:38.433986216 -0700
@@ -30,7 +30,6 @@
xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul">
-
diff -up ./esc/src/app/xul/esc/chrome/content/esc/hiddenWindow.xul.fix1 ./esc/src/app/xul/esc/chrome/content/esc/hiddenWindow.xul
--- ./esc/src/app/xul/esc/chrome/content/esc/hiddenWindow.xul.fix1 2017-07-24 16:46:36.000000000 -0700
+++ ./esc/src/app/xul/esc/chrome/content/esc/hiddenWindow.xul 2018-04-26 11:44:38.434986210 -0700
@@ -21,6 +21,5 @@
onload="hiddenWindowStartup();"
xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul">
-
diff -up ./esc/src/app/xul/esc/chrome/content/esc/security.xul.fix1 ./esc/src/app/xul/esc/chrome/content/esc/security.xul
--- ./esc/src/app/xul/esc/chrome/content/esc/security.xul.fix1 2017-07-24 16:46:36.000000000 -0700
+++ ./esc/src/app/xul/esc/chrome/content/esc/security.xul 2018-04-26 11:44:38.434986210 -0700
@@ -31,7 +31,6 @@
xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul">
-
diff -up ./esc/src/app/xul/esc/chrome/content/esc/settings.xul.fix1 ./esc/src/app/xul/esc/chrome/content/esc/settings.xul
--- ./esc/src/app/xul/esc/chrome/content/esc/settings.xul.fix1 2017-07-24 16:46:36.000000000 -0700
+++ ./esc/src/app/xul/esc/chrome/content/esc/settings.xul 2018-04-26 11:44:38.435986204 -0700
@@ -32,7 +32,6 @@
xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul">
-
diff -up ./esc/src/lib/coolkey/cky_applet.c.fix1 ./esc/src/lib/coolkey/cky_applet.c
--- ./esc/src/lib/coolkey/cky_applet.c.fix1 2018-04-26 11:44:38.436986198 -0700
+++ ./esc/src/lib/coolkey/cky_applet.c 2018-04-26 11:44:38.436986198 -0700
@@ -0,0 +1,2119 @@
+/* ***** BEGIN COPYRIGHT BLOCK *****
+ * Copyright (C) 2005 Red Hat, Inc.
+ * All rights reserved.
+ *
+ * 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 St, Fifth Floor, Boston, MA 02110-1301 USA
+ * ***** END COPYRIGHT BLOCK ***** */
+
+#include
+#include "cky_applet.h"
+#include
+
+#define MIN(x, y) ((x) < (y) ? (x) : (y))
+
+/*****************************************************************
+ *
+ * Generic factorys are used by the generic APDU processing
+ * to customize the formatting of APDU. Typically APDUs are formatted
+ * using parameterized calls of the form CKYAPDUFactory_ADPUNAME.
+ * The generic processing code, however needs calls with a common
+ * Signature. To accomplish the conversion, we build generic versions
+ * which take a void * parameter. Trivial APDU's can pass NULL or a pointer
+ * to the single parameter that they need. More complicated APDU's use
+ * CKYAppletArg* data structures defined above to pass more arguments.
+ *
+ * Generic factorys then call the standard CKYAPDUFactor_ADPUNAME() functions
+ * to build the APDUs. These functions are intended only as arguments
+ * to the generic ADPU calls, and not to be called directly.
+ *
+ *****************************************************************/
+CKYStatus
+CKYAppletFactory_SelectFile(CKYAPDU *apdu, const void *param)
+{
+ return CKYAPDUFactory_SelectFile(apdu, 4, 0, (const CKYBuffer *)param);
+}
+
+CKYStatus
+CACAppletFactory_SelectFile(CKYAPDU *apdu, const void *param)
+{
+ return CKYAPDUFactory_SelectFile(apdu, 2, 12, (const CKYBuffer *)param);
+}
+
+CKYStatus
+P15AppletFactory_SelectFile(CKYAPDU *apdu, const void *param)
+{
+ return CKYAPDUFactory_SelectFile(apdu, 0, 0, (const CKYBuffer *)param);
+}
+
+CKYStatus
+CKYAppletFactory_SelectCardManager(CKYAPDU *apdu, const void *param)
+{
+ return CKYAPDUFactory_SelectCardManager(apdu);
+}
+
+CKYStatus
+CKYAppletFactory_GetCPLCData(CKYAPDU *apdu, const void *param)
+{
+ return CKYAPDUFactory_GetCPLCData(apdu);
+}
+
+CKYStatus
+CKYAppletFactory_ListKeys(CKYAPDU *apdu, const void *param)
+{
+ return CKYAPDUFactory_ListKeys(apdu, *( CKYByte *)param);
+}
+
+CKYStatus
+CKYAppletFactory_ComputeCryptInit(CKYAPDU *apdu, const void *param)
+{
+ const CKYAppletArgComputeCrypt *ccs=(const CKYAppletArgComputeCrypt *)param;
+ return CKYAPDUFactory_ComputeCryptInit(apdu, ccs->keyNumber, ccs->mode,
+ ccs->direction, ccs->location);
+
+}
+
+CKYStatus
+CKYAppletFactory_ComputeCryptProcess(CKYAPDU *apdu, const void *param)
+{
+ const CKYAppletArgComputeCrypt *ccs=(const CKYAppletArgComputeCrypt *)param;
+ return CKYAPDUFactory_ComputeCryptProcess(apdu, ccs->keyNumber,
+ ccs->location, ccs->data);
+
+}
+
+CKYStatus
+CKYAppletFactory_ComputeCryptFinal(CKYAPDU *apdu, const void *param)
+{
+ const CKYAppletArgComputeCrypt *ccs=(const CKYAppletArgComputeCrypt *)param;
+ return CKYAPDUFactory_ComputeCryptFinal(apdu, ccs->keyNumber,
+ ccs->location, ccs->data, ccs->sig);
+}
+
+CKYStatus
+CKYAppletFactory_ComputeCryptOneStep(CKYAPDU *apdu, const void *param)
+{
+ const CKYAppletArgComputeCrypt *ccs=(const CKYAppletArgComputeCrypt *)param;
+ return CKYAPDUFactory_ComputeCryptOneStep(apdu, ccs->keyNumber,ccs->mode,
+ ccs->direction, ccs->location, ccs->data, ccs->sig);
+}
+
+CKYStatus
+CKYAppletFactory_ComputeECCSignatureOneStep(CKYAPDU *apdu, const void *param)
+{
+ const CKYAppletArgComputeECCSignature *ccs=(const CKYAppletArgComputeECCSignature *)param;
+ return CKYAPDUFactory_ComputeECCSignatureOneStep(apdu, ccs->keyNumber,
+ ccs->location, ccs->data, ccs->sig);
+}
+
+CKYStatus
+CKYAppletFactory_ComputeECCKeyAgreementOneStep(CKYAPDU *apdu, const void *param)
+{
+
+ const CKYAppletArgComputeECCKeyAgreement *ccs=(const CKYAppletArgComputeECCKeyAgreement *)param;
+ return CKYAPDUFactory_ComputeECCKeyAgreementOneStep(apdu, ccs->keyNumber, ccs->location, ccs->publicValue, ccs->secretKey);
+}
+
+CKYStatus
+CKYAppletFactory_CreatePIN(CKYAPDU *apdu, const void *param)
+{
+ const CKYAppletArgCreatePIN *cps = (const CKYAppletArgCreatePIN *)param;
+ return CKYAPDUFactory_CreatePIN(apdu, cps->pinNumber, cps->maxAttempts,
+ cps->pinValue);
+}
+
+CKYStatus
+CKYAppletFactory_VerifyPIN(CKYAPDU *apdu, const void *param)
+{
+ const CKYAppletArgVerifyPIN *vps = (const CKYAppletArgVerifyPIN *)param;
+ return CKYAPDUFactory_VerifyPIN(apdu, vps->pinNumber, vps->pinValue);
+}
+
+CKYStatus
+CKYAppletFactory_ChangePIN(CKYAPDU *apdu, const void *param)
+{
+ const CKYAppletArgChangePIN *cps = (const CKYAppletArgChangePIN *)param;
+ return CKYAPDUFactory_ChangePIN(apdu, cps->pinNumber, cps->oldPin,
+ cps->newPin);
+}
+
+CKYStatus
+CKYAppletFactory_ListPINs(CKYAPDU *apdu, const void *param)
+{
+ return CKYAPDUFactory_ListPINs(apdu);
+}
+
+CKYStatus
+CKYAppletFactory_Logout(CKYAPDU *apdu, const void *param)
+{
+ return CKYAPDUFactory_Logout(apdu, *(const CKYByte *)param);
+}
+
+/* Future add WriteObject */
+
+CKYStatus
+CKYAppletFactory_WriteObject(CKYAPDU *apdu, const void *param)
+{
+ const CKYAppletArgWriteObject *wos = (const CKYAppletArgWriteObject *)param;
+ return CKYAPDUFactory_WriteObject(apdu,wos->objectID,wos->offset,wos->size,wos->data);
+}
+
+CKYStatus
+CKYAppletFactory_CreateObject(CKYAPDU *apdu, const void *param)
+{
+ const CKYAppletArgCreateObject *cos=(const CKYAppletArgCreateObject *)param;
+ return CKYAPDUFactory_CreateObject(apdu, cos->objectID, cos->size,
+ cos->readACL, cos->writeACL, cos->deleteACL);
+}
+
+CKYStatus
+CKYAppletFactory_DeleteObject(CKYAPDU *apdu, const void *param)
+{
+ const CKYAppletArgDeleteObject *dos=(const CKYAppletArgDeleteObject *)param;
+ return CKYAPDUFactory_DeleteObject(apdu, dos->objectID, dos->zero);
+
+}
+
+CKYStatus
+CKYAppletFactory_ReadObject(CKYAPDU *apdu, const void *param)
+{
+ const CKYAppletArgReadObject *ros = (const CKYAppletArgReadObject *)param;
+ return CKYAPDUFactory_ReadObject(apdu, ros->objectID,
+ ros->offset, ros->size);
+}
+
+CKYStatus
+CKYAppletFactory_ListObjects(CKYAPDU *apdu, const void *param)
+{
+ return CKYAPDUFactory_ListObjects(apdu, *(const CKYByte *)param);
+}
+
+CKYStatus
+CKYAppletFactory_GetStatus(CKYAPDU *apdu, const void *param)
+{
+ return CKYAPDUFactory_GetStatus(apdu);
+}
+
+CKYStatus
+CKYAppletFactory_Noop(CKYAPDU *apdu, const void *param)
+{
+ return CKYAPDUFactory_Noop(apdu);
+}
+
+CKYStatus
+CKYAppletFactory_GetBuildID(CKYAPDU *apdu, const void *param)
+{
+ return CKYAPDUFactory_GetBuildID(apdu);
+}
+
+CKYStatus
+CKYAppletFactory_GetLifeCycle(CKYAPDU *apdu, const void *param)
+{
+ return CKYAPDUFactory_GetLifeCycle(apdu);
+}
+
+CKYStatus
+CKYAppletFactory_GetLifeCycleV2(CKYAPDU *apdu, const void *param)
+{
+ return CKYAPDUFactory_GetLifeCycleV2(apdu);
+}
+CKYStatus
+CKYAppletFactory_GetRandom(CKYAPDU *apdu, const void *param)
+{
+ return CKYAPDUFactory_GetRandom(apdu, *(CKYByte *)param);
+}
+
+CKYStatus
+CKYAppletFactory_SeedRandom(CKYAPDU *apdu, const void *param)
+{
+ const CKYBuffer *buf=(CKYBuffer *)param;
+ return CKYAPDUFactory_SeedRandom(apdu, buf);
+}
+
+CKYStatus
+CKYAppletFactory_GetIssuerInfo(CKYAPDU *apdu, const void *param)
+{
+ return CKYAPDUFactory_GetIssuerInfo(apdu);
+}
+
+CKYStatus
+CKYAppletFactory_GetBuiltinACL(CKYAPDU *apdu, const void *param)
+{
+ return CKYAPDUFactory_GetBuiltinACL(apdu);
+}
+
+CKYStatus
+CACAppletFactory_SignDecryptStep(CKYAPDU *apdu, const void *param)
+{
+ const CKYBuffer *buf=(CKYBuffer *)param;
+ return CACAPDUFactory_SignDecrypt(apdu, CAC_P1_STEP, buf);
+}
+
+CKYStatus
+CACAppletFactory_SignDecryptFinal(CKYAPDU *apdu, const void *param)
+{
+ const CKYBuffer *buf=(CKYBuffer *)param;
+ return CACAPDUFactory_SignDecrypt(apdu, CAC_P1_FINAL, buf);
+}
+
+CKYStatus
+PIVAppletFactory_SignDecrypt(CKYAPDU *apdu, const void *param)
+{
+ const PIVAppletArgSignDecrypt *psd = (const PIVAppletArgSignDecrypt *)param;
+ return PIVAPDUFactory_SignDecrypt(apdu, psd->chain, psd->alg, psd->key,
+ psd->len, psd->buf);
+}
+
+CKYStatus
+P15AppletFactory_VerifyPIN(CKYAPDU *apdu, const void *param)
+{
+ const P15AppletArgVerifyPIN *vps = (const P15AppletArgVerifyPIN *)param;
+ return P15APDUFactory_VerifyPIN(apdu, vps->pinRef, vps->pinVal);
+}
+
+CKYStatus
+CACAppletFactory_GetCertificate(CKYAPDU *apdu, const void *param)
+{
+ CKYSize *size=(CKYSize*)param;
+ return CACAPDUFactory_GetCertificate(apdu, *size);
+}
+
+CKYStatus
+PIVAppletFactory_GetCertificate(CKYAPDU *apdu, const void *param)
+{
+ CKYBuffer *tag =(CKYBuffer*)param;
+ return PIVAPDUFactory_GetData(apdu, tag, 0);
+}
+
+CKYStatus
+CACAppletFactory_ReadFile(CKYAPDU *apdu, const void *param)
+{
+ const CACAppletArgReadFile *rfs = (const CACAppletArgReadFile *)param;
+ return CACAPDUFactory_ReadFile(apdu, rfs->offset, rfs->type, rfs->count);
+}
+
+CKYStatus
+CACAppletFactory_GetProperties(CKYAPDU *apdu, const void *param)
+{
+ return CACAPDUFactory_GetProperties(apdu);
+}
+
+/*
+ * deprecates 0.x functions
+ */
+CKYStatus
+CKYAppletFactory_LogoutAllV0(CKYAPDU *apdu, const void *param)
+{
+ CKYByte data[2] = { 0, 0};
+ CKYAPDU_SetCLA(apdu, CKY_CLASS_COOLKEY);
+ CKYAPDU_SetINS(apdu, CKY_INS_LOGOUT_ALL);
+ CKYAPDU_SetP1(apdu, 0x00);
+ CKYAPDU_SetP2(apdu, 0x00);
+ return CKYAPDU_SetSendData(apdu, data, sizeof(data));
+}
+
+CKYStatus
+P15AppletFactory_ReadRecord(CKYAPDU *apdu, const void *param)
+{
+ const P15AppletArgReadRecord *rrs = (const P15AppletArgReadRecord *)param;
+ return P15APDUFactory_ReadRecord(apdu, rrs->record,
+ rrs->short_ef, rrs->flags, rrs->size);
+}
+
+CKYStatus
+P15AppletFactory_ReadBinary(CKYAPDU *apdu, const void *param)
+{
+ const P15AppletArgReadBinary *res = (const P15AppletArgReadBinary *)param;
+ return P15APDUFactory_ReadBinary(apdu, res->offset,
+ res->short_ef, res->flags, res->size);
+}
+
+CKYStatus
+P15AppletFactory_ManageSecurityEnvironment(CKYAPDU *apdu, const void *param)
+{
+ const P15AppletArgManageSecurityEnvironment *mse =
+ (const P15AppletArgManageSecurityEnvironment *)param;
+ return P15APDUFactory_ManageSecurityEnvironment(apdu, mse->p1,
+ mse->p2, mse->keyRef);
+}
+
+CKYStatus
+P15AppletFactory_PerformSecurityOperation(CKYAPDU *apdu, const void *param)
+{
+ const P15AppletArgPerformSecurityOperation *pso =
+ (const P15AppletArgPerformSecurityOperation *)param;
+ return P15APDUFactory_PerformSecurityOperation(apdu, pso->dir, pso->chain,
+ pso->retLen, pso->data);
+}
+/*****************************************************************
+ *
+ * Generic Fill routines used by several calls in common
+ * and globally accessible
+ *
+ *****************************************************************/
+
+/* a null fill function for those APDU's which do not return data */
+CKYStatus
+CKYAppletFill_Null(const CKYBuffer *response, CKYSize size, void *param)
+{
+ return CKYSUCCESS;
+}
+
+/* a Buffer Replace fill function for those APDU's which return unformated
+ * chunks of data */
+CKYStatus
+CKYAppletFill_ReplaceBuffer(const CKYBuffer *response, CKYSize size, void *param)
+{
+ CKYBuffer *buf = (CKYBuffer *)param;
+
+ if (buf == NULL) {
+ return CKYSUCCESS;
+ }
+ return CKYBuffer_Replace(buf, 0, CKYBuffer_Data(response),
+ CKYBuffer_Size(response) -2);
+}
+
+/* a Buffer Append fill function. Can be used with any APDU that uses Buffer
+ * Replace. Repeated calls continuously fill the buffer. Most useful for read.
+ */
+CKYStatus
+CKYAppletFill_AppendBuffer(const CKYBuffer *response, CKYSize size, void *param)
+{
+ CKYBuffer *buf = (CKYBuffer *)param;
+
+ return CKYBuffer_AppendData(buf, CKYBuffer_Data(response),
+ CKYBuffer_Size(response) -2);
+}
+
+
+CKYStatus
+CKYAppletFill_Byte(const CKYBuffer *response, CKYSize size, void *param)
+{
+ CKYByte *v = (CKYByte *)param;
+
+ *v = CKYBuffer_GetChar(response, 0);
+ return CKYSUCCESS;
+}
+
+CKYStatus
+CKYAppletFill_Short(const CKYBuffer *response, CKYSize size, void *param)
+{
+ unsigned short *v = (unsigned short *)param;
+
+ *v = CKYBuffer_GetShort(response, 0);
+ return CKYSUCCESS;
+}
+
+CKYStatus
+CKYAppletFill_Long(const CKYBuffer *response, CKYSize size, void *param)
+{
+ unsigned long *v = (unsigned long *)param;
+
+ *v = CKYBuffer_GetLong(response, 0);
+ return CKYSUCCESS;
+}
+
+/*****************************************************************
+ *
+ * Utilities shared by all the fetch Cards.
+ *
+ *****************************************************************/
+/*
+ * verify the we got a successful response. Responses should include
+ * the expected data returned plus a 2 byte return code. This return
+ * code should be 0x9000 on success.
+ */
+CKYBool
+CKYApplet_VerifyResponse(const CKYBuffer *buf, CKYSize dataSize,
+ CKYISOStatus *apduRC) {
+ CKYSize size = CKYBuffer_Size(buf);
+ CKYISOStatus rc = CKYISO_INVRESPONSE;
+ CKYBool valid = 0;
+
+ /* is there enough size for the return code ? */
+ if (size < 2) {
+ goto done;
+ }
+ /* fetch the data */
+ rc = CKYBuffer_GetShort(buf, size-2);
+
+ /* is there enough size for the expected data ? */
+ if ((dataSize != CKY_SIZE_UNKNOWN) && (size != dataSize+2)) {
+ goto done;
+ }
+
+ /* did we return successfully? */
+ valid = (rc == CKYISO_SUCCESS) || ((rc & CKYISO_MORE_MASK) == CKYISO_MORE);
+
+done:
+ if (apduRC) {
+ *apduRC = rc;
+ }
+ return valid;
+}
+
+
+/*
+ * most commands have identical operations. Isolate the differences in
+ * call back functions, and create a generic APDU handler which Creates
+ * APDU's, Does the exchange, and fills in the results.
+ */
+CKYStatus
+CKYApplet_HandleAPDU(CKYCardConnection *conn,
+ CKYAppletFactory afFunc, const void *afArg,
+ const CKYBuffer *nonce, CKYSize size,
+ CKYFillFunction fillFunc, void *fillArg, CKYISOStatus *apduRC)
+{
+ CKYAPDU apdu;
+ CKYBuffer response;
+ CKYStatus ret;
+
+ if (apduRC) {
+ *apduRC = CKYISO_NORESPONSE;
+ }
+
+ /* initialize the response and APDU buffers */
+ CKYBuffer_InitEmpty(&response);
+ ret = CKYAPDU_Init(&apdu);
+ if (ret != CKYSUCCESS) {
+ goto done;
+ }
+
+ /* fill in the APDU buffer with the correct values */
+ ret = (*afFunc)(&apdu, afArg);
+ if (ret != CKYSUCCESS) {
+ goto done;
+ }
+ /* if NONCE supplied, add it to the end of the apdu */
+ if (nonce) {
+ /*
+ * Local Secured commands need the nonce returned from Login to
+ * verify that they are valid. Nonce's are just added to the end
+ * of the APDU much like
+ */
+ ret = CKYAPDU_AppendSendDataBuffer(&apdu, nonce);
+ if (ret != CKYSUCCESS) {
+ goto done;
+ }
+ }
+
+ /* send it to the card */
+ ret = CKYCardConnection_ExchangeAPDU(conn, &apdu, &response);
+ if (ret != CKYSUCCESS) {
+ goto done;
+ }
+
+ /* verify we got the expected response */
+ if (!CKYApplet_VerifyResponse(&response, size, apduRC)) {
+ ret = CKYAPDUFAIL;
+ goto done;
+ }
+
+ /* Fill in our output data structure */
+ ret = (*fillFunc)(&response, size, fillArg);
+done:
+ CKYBuffer_FreeData(&response);
+ CKYAPDU_FreeData(&apdu);
+ return ret;
+}
+
+
+/*****************************************************************
+ *
+ * The following convience functions convert APDU calls
+ * into function calls, with input and output parameters.
+ * The application is still responsible for 1) creating a connection
+ * to the card, 2) Getting a tranaction long, then 3) selecting
+ * the appropriate applet (or Card manager). Except for those
+ * calls that have been noted, the appropriate applet is the CoolKey
+ * applet.
+ *
+ *****************************************************************/
+/*
+ * Select an applet. Must happen after we start a transaction and before
+ * we issue any applet specific command.
+ */
+CKYStatus
+CKYApplet_SelectFile(CKYCardConnection *conn, const CKYBuffer *AID,
+ CKYISOStatus *apduRC)
+{
+ return CKYApplet_HandleAPDU(conn, CKYAppletFactory_SelectFile, AID, NULL,
+ CKY_SIZE_UNKNOWN, CKYAppletFill_Null, NULL, apduRC);
+}
+
+static CKYByte coolkeyid[] = {0x62, 0x76, 0x01, 0xff, 0x00, 0x00, 0x00 };
+/*
+ * Select the CoolKey applet. Must happen after we start a transaction and
+ * before we issue any applet specific command.
+ */
+CKYStatus
+CKYApplet_SelectCoolKeyManager(CKYCardConnection *conn, CKYISOStatus *apduRC)
+{
+ CKYStatus ret;
+ CKYBuffer COOLKEYAID;
+ CKYBuffer_InitFromData(&COOLKEYAID, coolkeyid, sizeof(coolkeyid));
+ ret = CKYApplet_HandleAPDU(conn, CKYAppletFactory_SelectFile, &COOLKEYAID,
+ NULL, 0, CKYAppletFill_Null, NULL, apduRC);
+ CKYBuffer_FreeData(&COOLKEYAID);
+ return ret;
+}
+
+static CKYByte CACPKIid[] = { 0xa0, 0x00, 0x00, 0x00, 0x79, 0x01 };
+/*
+ * Select the CoolKey applet. Must happen after we start a transaction and
+ * before we issue any applet specific command.
+ */
+CKYStatus
+CACApplet_SelectPKI(CKYCardConnection *conn, CKYBuffer *cacAID,
+ CKYByte instance, CKYISOStatus *apduRC)
+{
+ CKYStatus ret;
+ CKYBuffer_AppendData(cacAID, CACPKIid, sizeof(CACPKIid));
+ CKYBuffer_AppendChar(cacAID, instance);
+ ret = CKYApplet_HandleAPDU(conn, CKYAppletFactory_SelectFile, cacAID,
+ NULL, CKY_SIZE_UNKNOWN, CKYAppletFill_Null, NULL, apduRC);
+ if (ret != CKYSUCCESS) {
+ CKYBuffer_Resize(cacAID, 0);
+ }
+ return ret;
+}
+
+/*
+ * Select the card manager. Must happen after we start a transaction and before
+ * we issue any card manager commands.
+ */
+CKYStatus
+CKYApplet_SelectCardManager(CKYCardConnection *conn, CKYISOStatus *apduRC)
+{
+ return CKYApplet_HandleAPDU(conn, CKYAppletFactory_SelectCardManager, NULL,
+ NULL, CKY_SIZE_UNKNOWN, CKYAppletFill_Null, NULL, apduRC);
+}
+
+static CKYByte cacmgrid[] = {0xa0, 0x00, 0x00, 0x00, 0x30, 0x00, 0x00 };
+CKYStatus
+CACApplet_SelectCardManager(CKYCardConnection *conn, CKYISOStatus *apduRC)
+{
+ CKYStatus ret;
+ CKYBuffer CAC_CM_AID;
+ CKYBuffer_InitFromData(&CAC_CM_AID, cacmgrid, sizeof(cacmgrid));
+ ret = CKYApplet_HandleAPDU(conn, CKYAppletFactory_SelectFile, &CAC_CM_AID,
+ NULL, CKY_SIZE_UNKNOWN, CKYAppletFill_Null, NULL, apduRC);
+ CKYBuffer_FreeData(&CAC_CM_AID);
+ return ret;
+}
+
+static CKYByte cacCCCid[] = {0xa0, 0x00, 0x00, 0x01, 0x16, 0xdb, 0x00 };
+CKYStatus
+CACApplet_SelectCCC(CKYCardConnection *conn, CKYISOStatus *apduRC)
+{
+ CKYStatus ret;
+ CKYBuffer CAC_CM_AID;
+ CKYBuffer_InitFromData(&CAC_CM_AID, cacCCCid, sizeof(cacCCCid));
+ ret = CKYApplet_HandleAPDU(conn, CKYAppletFactory_SelectFile, &CAC_CM_AID,
+ NULL, CKY_SIZE_UNKNOWN, CKYAppletFill_Null, NULL, apduRC);
+ CKYBuffer_FreeData(&CAC_CM_AID);
+ return ret;
+}
+
+CKYStatus
+CACApplet_SelectFile(CKYCardConnection *conn, unsigned short ef,
+ CKYISOStatus *apduRC)
+{
+ CKYStatus ret;
+ CKYBuffer efBuf;
+ CKYBuffer_InitEmpty(&efBuf);
+ CKYBuffer_AppendShortLE(&efBuf, ef);
+ ret = CKYApplet_HandleAPDU(conn, CACAppletFactory_SelectFile, &efBuf,
+ NULL, CKY_SIZE_UNKNOWN, CKYAppletFill_Null, NULL, apduRC);
+ CKYBuffer_FreeData(&efBuf);
+ return ret;
+}
+
+/*
+ * GetCPLC cluster -- must be called with CM selected
+ */
+static CKYStatus
+ckyAppletFill_GetCPLCData(const CKYBuffer *response, CKYSize size, void *param)
+{
+ CKYAppletRespGetCPLCData *gcdp = (CKYAppletRespGetCPLCData *)param;
+
+ gcdp->CPLCtag = CKYBuffer_GetShort(response, 0);
+ gcdp->length = CKYBuffer_GetChar(response, 2);
+ gcdp->fabricator = CKYBuffer_GetShort(response, 3);
+ gcdp->romType = CKYBuffer_GetShort(response, 5);
+ gcdp->romOSID = CKYBuffer_GetShort(response, 7);
+ gcdp->romOSDate = CKYBuffer_GetShort(response, 9);
+ gcdp->romOSLevel = CKYBuffer_GetShort(response, 11);
+ gcdp->eepromFabricationDate = CKYBuffer_GetShort(response, 13);
+ gcdp->eepromSerialNumber = CKYBuffer_GetLong(response, 15);
+ gcdp->eepromBatchID = CKYBuffer_GetShort(response, 19);
+ gcdp->eepromModuleFabricator = CKYBuffer_GetShort(response, 21);
+ gcdp->eepromModuleDate = CKYBuffer_GetShort(response, 23);
+ gcdp->eepromICManufacturer = CKYBuffer_GetShort(response, 25);
+ gcdp->eepromEmbeddingDate = CKYBuffer_GetShort(response, 27);
+ gcdp->eepromPrePersonalizer = CKYBuffer_GetShort(response, 29);
+ gcdp->eepromPrePersonalizeDate = CKYBuffer_GetShort(response, 31);
+ gcdp->eepromPrePersonalizeID = CKYBuffer_GetLong(response, 33);
+ gcdp->eepromPersonalizer = CKYBuffer_GetShort(response, 37);
+ gcdp->eepromPersonalizeDate = CKYBuffer_GetShort(response, 39);
+ gcdp->eepromPersonalizeID = CKYBuffer_GetLong(response, 41);
+ return CKYSUCCESS;
+}
+
+CKYStatus
+CKYApplet_GetCPLCData(CKYCardConnection *conn, CKYAppletRespGetCPLCData *cplc,
+ CKYISOStatus *apduRC)
+{
+ return CKYApplet_HandleAPDU(conn, CKYAppletFactory_GetCPLCData, NULL, NULL,
+ CKY_SIZE_GET_CPLCDATA, ckyAppletFill_GetCPLCData, cplc, apduRC);
+}
+
+/*
+ * Get CUID. The CUID exists in the CPLC data. We use the same basic
+ * APDU, but use a differ fill function to collect it.
+ */
+static CKYStatus
+ckyAppletFill_GetCUID(const CKYBuffer *response, CKYSize size, void *param)
+{
+ CKYBuffer *cuid = (CKYBuffer *)param;
+ CKYStatus ret;
+
+ ret = CKYBuffer_Resize(cuid,10);
+ if (ret != CKYSUCCESS) {
+ return ret;
+ }
+ /* fabricator 2 bytes */
+ CKYBuffer_SetChar(cuid, 0, CKYBuffer_GetChar(response, 3));
+ CKYBuffer_SetChar(cuid, 1, CKYBuffer_GetChar(response, 4));
+ /* IC Type 2 bytes */
+ CKYBuffer_SetChar(cuid, 2, CKYBuffer_GetChar(response, 5));
+ CKYBuffer_SetChar(cuid, 3, CKYBuffer_GetChar(response, 6));
+ /* Batch ID 2 bytes */
+ CKYBuffer_SetChar(cuid, 4, CKYBuffer_GetChar(response, 19));
+ CKYBuffer_SetChar(cuid, 5, CKYBuffer_GetChar(response, 20));
+ /* IC Serial Number 4 bytes */
+ CKYBuffer_SetChar(cuid, 6, CKYBuffer_GetChar(response, 15));
+ CKYBuffer_SetChar(cuid, 7, CKYBuffer_GetChar(response, 16));
+ CKYBuffer_SetChar(cuid, 8, CKYBuffer_GetChar(response, 17));
+ CKYBuffer_SetChar(cuid, 9, CKYBuffer_GetChar(response, 18));
+ return CKYSUCCESS;
+}
+
+CKYStatus
+CKYApplet_GetCUID(CKYCardConnection *conn, CKYBuffer *cuid, CKYISOStatus *apduRC)
+{
+ return CKYApplet_HandleAPDU(conn, CKYAppletFactory_GetCPLCData, NULL, NULL,
+ CKY_SIZE_GET_CPLCDATA, ckyAppletFill_GetCUID, cuid, apduRC);
+}
+
+/*
+ * Get MSN. The MSN exists in the CPLC data. We use the same basic
+ * APDU, but use a differ fill function to collect it.
+ */
+static CKYStatus
+ckyAppletFill_GetMSN(const CKYBuffer *response, CKYSize size, void *param)
+{
+ unsigned long *msn = (unsigned long *)param;
+ *msn = CKYBuffer_GetLong(response, 41);
+
+ return CKYSUCCESS;
+}
+
+CKYStatus
+CKYApplet_GetMSN(CKYCardConnection *conn, unsigned long *msn,
+ CKYISOStatus *apduRC)
+{
+ return CKYApplet_HandleAPDU(conn, CKYAppletFactory_GetCPLCData, NULL, NULL,
+ CKY_SIZE_GET_CPLCDATA, ckyAppletFill_GetMSN, msn, apduRC);
+}
+
+/*
+ * ListKeys cluster
+ */
+static CKYStatus
+ckyAppletFill_ListKeys(const CKYBuffer *response, CKYSize size, void *param)
+{
+ CKYAppletRespListKeys *lkp = (CKYAppletRespListKeys *)param;
+
+ lkp->keyNum = CKYBuffer_GetChar(response, 0);
+ lkp->keyType = CKYBuffer_GetChar(response, 1);
+ lkp->keyPartner = CKYBuffer_GetChar(response, 2);
+ lkp->keySize = CKYBuffer_GetShort(response, 3);
+ lkp->readACL = CKYBuffer_GetShort(response, 5);
+ lkp->writeACL = CKYBuffer_GetShort(response, 7);
+ lkp->useACL = CKYBuffer_GetShort(response, 9);
+ return CKYSUCCESS;
+}
+
+CKYStatus
+CKYApplet_ListKeys(CKYCardConnection *conn, CKYByte seq,
+ CKYAppletRespListKeys *lkp, CKYISOStatus *apduRC)
+{
+ return CKYApplet_HandleAPDU(conn, CKYAppletFactory_ListKeys, &seq, NULL,
+ CKY_SIZE_LIST_KEYS, ckyAppletFill_ListKeys, lkp, apduRC);
+}
+
+/*
+ * Compute Crypt Cluster.
+ *
+ * Compute Crypt takes 3 types: Init, Process, Final.
+ *
+ */
+CKYStatus
+CKYApplet_ComputeCryptInit(CKYCardConnection *conn, CKYByte keyNumber,
+ CKYByte mode, CKYByte direction, CKYByte location,
+ const CKYBuffer *nonce, CKYISOStatus *apduRC)
+{
+ CKYAppletArgComputeCrypt ccd;
+ ccd.keyNumber = keyNumber;
+ ccd.mode = mode;
+ ccd.direction = direction;
+ ccd.location = location;
+ return CKYApplet_HandleAPDU(conn, CKYAppletFactory_ComputeCryptInit, &ccd,
+ nonce, 0, CKYAppletFill_Null, NULL, apduRC);
+}
+
+CKYStatus
+CKYApplet_ComputeCryptProcess(CKYCardConnection *conn, CKYByte keyNumber,
+ CKYByte location, const CKYBuffer *data,
+ const CKYBuffer *nonce, CKYISOStatus *apduRC)
+{
+ CKYAppletArgComputeCrypt ccd;
+ ccd.keyNumber = keyNumber;
+ ccd.location = location;
+ ccd.data = data;
+ return CKYApplet_HandleAPDU(conn, CKYAppletFactory_ComputeCryptProcess,
+ &ccd, nonce, 0, CKYAppletFill_Null, NULL, apduRC);
+}
+
+/* computeECCValue returns data in the form :
+ * len: short
+ * data: byte[len]
+ * This fill routine returns A buffer with a copy of data and a length of len */
+static CKYStatus
+ckyAppletFill_ComputeECCValueFinal(const CKYBuffer *response,
+ CKYSize size, void *param)
+{
+ CKYBuffer *cbuf = (CKYBuffer *)param;
+ CKYSize respSize = CKYBuffer_Size(response);
+ CKYSize dataLen;
+
+ if (cbuf == 0) {
+ return CKYSUCCESS; /* app didn't want the result */
+ }
+ /* data response code + length code */
+ if (respSize < 4) {
+ return CKYAPDUFAIL;
+ }
+ dataLen = CKYBuffer_GetShort(response, 0);
+ if (dataLen > (respSize-4)) {
+ return CKYAPDUFAIL;
+ }
+ return CKYBuffer_Replace(cbuf, 0, CKYBuffer_Data(response)+2, dataLen);
+}
+
+/* computeCrypt returns data in the form :
+ * len: short
+ * data: byte[len]
+ * This fill routine returns A buffer with a copy of data and a length of len */
+static CKYStatus
+ckyAppletFill_ComputeCryptFinal(const CKYBuffer *response,
+ CKYSize size, void *param)
+{
+ CKYBuffer *cbuf = (CKYBuffer *)param;
+ CKYSize respSize = CKYBuffer_Size(response);
+ CKYSize dataLen;
+
+ if (cbuf == 0) {
+ return CKYSUCCESS; /* app didn't want the result */
+ }
+ /* data response code + length code */
+ if (respSize < 4) {
+ return CKYAPDUFAIL;
+ }
+ dataLen = CKYBuffer_GetShort(response, 0);
+ if (dataLen > (respSize-4)) {
+ return CKYAPDUFAIL;
+ }
+ return CKYBuffer_Replace(cbuf, 0, CKYBuffer_Data(response)+2, dataLen);
+}
+
+CKYStatus
+CKYApplet_ComputeCryptFinal(CKYCardConnection *conn, CKYByte keyNumber,
+ CKYByte location, const CKYBuffer *data, CKYBuffer *sig, CKYBuffer *result,
+ const CKYBuffer *nonce, CKYISOStatus *apduRC)
+{
+ CKYAppletArgComputeCrypt ccd;
+ ccd.keyNumber = keyNumber;
+ ccd.location = location;
+ ccd.data = data;
+ ccd.data = sig;
+ return CKYApplet_HandleAPDU(conn, CKYAppletFactory_ComputeCryptFinal, &ccd,
+ nonce, CKY_SIZE_UNKNOWN, ckyAppletFill_ComputeCryptFinal, result, apduRC);
+}
+
+/*
+ * do a complete ComputeCrypt operation
+ * ...look to data size to see if we should read/write the data to
+ * the on card buffer. (future)
+ */
+CKYStatus
+CKYApplet_ComputeCrypt(CKYCardConnection *conn, CKYByte keyNumber,
+ CKYByte mode, CKYByte direction, const CKYBuffer *data, CKYBuffer *sig,
+ CKYBuffer *result, const CKYBuffer *nonce, CKYISOStatus *apduRC)
+{
+ CKYStatus ret;
+ CKYAppletArgComputeCrypt ccd;
+ CKYBuffer empty;
+ CKYISOStatus status;
+ short dataSize = 0;
+ int use2APDUs = 0;
+ int use_dl_object = CKYBuffer_Size(data) > 200 ;
+
+ CKYBuffer_InitEmpty(&empty);
+ ccd.keyNumber = keyNumber;
+ ccd.mode = mode;
+ ccd.direction = direction;
+ ccd.location = use_dl_object ? CKY_DL_OBJECT : CKY_DL_APDU;
+
+ if (!apduRC)
+ apduRC = &status;
+
+ if (use_dl_object) {
+ CKYBuffer sizeBuf;
+
+ CKYBuffer_InitEmpty(&sizeBuf);
+ CKYBuffer_AppendShort(&sizeBuf, CKYBuffer_Size(data));
+
+ ret = CKYApplet_WriteObjectFull(conn, 0xffffffff,
+ 0, CKYBuffer_Size(&sizeBuf), nonce,
+ &sizeBuf, apduRC);
+
+ CKYBuffer_FreeData(&sizeBuf);
+ if( ret != CKYSUCCESS)
+ goto fail;
+
+ ret = CKYApplet_WriteObjectFull(conn, 0xffffffff,
+ 2, CKYBuffer_Size(data), nonce,
+ data, apduRC);
+
+ if(ret != CKYSUCCESS)
+ goto fail;
+ }
+
+ if (mode == CKY_RSA_NO_PAD) {
+ ccd.data = use_dl_object ? &empty : data;
+ ccd.sig = sig;
+ ret = CKYApplet_HandleAPDU(conn,
+ CKYAppletFactory_ComputeCryptOneStep, &ccd, nonce,
+ CKY_SIZE_UNKNOWN, ckyAppletFill_ComputeCryptFinal,
+ use_dl_object ? NULL : result, apduRC);
+ if (ret == CKYAPDUFAIL && *apduRC == CKYISO_INCORRECT_P2) {
+ use2APDUs = 1; /* maybe it's an old applet */
+ }
+ } else {
+ use2APDUs = 1;
+ }
+ if (use2APDUs) {
+ /* future, if data is to big write it to the internal object
+ * and set location to DL_OBJECT */
+ ccd.data = ∅
+ ccd.sig = sig;
+
+ ret = CKYApplet_HandleAPDU(conn,
+ CKYAppletFactory_ComputeCryptInit, &ccd, nonce,
+ 0, CKYAppletFill_Null, NULL, apduRC);
+ if (ret == CKYSUCCESS) {
+ ccd.data = use_dl_object ? &empty : data;
+ ret = CKYApplet_HandleAPDU(conn,
+ CKYAppletFactory_ComputeCryptFinal, &ccd, nonce,
+ CKY_SIZE_UNKNOWN, ckyAppletFill_ComputeCryptFinal,
+ use_dl_object ? NULL : result, apduRC);
+ }
+ }
+
+ if (use_dl_object && ret == CKYSUCCESS) {
+ CKYBuffer sizeOutBuf;
+ CKYBuffer_InitEmpty(&sizeOutBuf);
+
+ ret = CKYApplet_ReadObjectFull(conn,0xffffffff,
+ 0, 2,
+ nonce,&sizeOutBuf,apduRC);
+
+ if(ret != CKYSUCCESS) {
+ CKYBuffer_FreeData(&sizeOutBuf);
+ goto fail;
+ }
+
+ dataSize = CKYBuffer_GetShort(&sizeOutBuf, 0);
+
+ CKYBuffer_FreeData(&sizeOutBuf);
+
+ ret = CKYApplet_ReadObjectFull(conn,0xffffffff,
+ 2, dataSize,
+ nonce,result,apduRC);
+ }
+
+fail:
+
+ return ret;
+}
+
+CKYStatus
+CKYApplet_ComputeECCKeyAgreement(CKYCardConnection *conn, CKYByte keyNumber,
+ const CKYBuffer *publicValue, CKYBuffer *sharedSecret,
+ CKYBuffer *result, const CKYBuffer *nonce, CKYISOStatus *apduRC)
+{
+ CKYStatus ret = CKYAPDUFAIL;
+ CKYAppletArgComputeECCKeyAgreement ccd;
+ CKYBuffer empty;
+ CKYISOStatus status;
+ /* Routine creates a sym key, should easily fit in one apdu */
+
+ CKYBuffer_InitEmpty(&empty);
+ ccd.keyNumber = keyNumber;
+ ccd.location = CKY_DL_APDU;
+
+ if (!apduRC)
+ apduRC = &status;
+
+ if (ccd.location == CKY_DL_APDU) {
+ ccd.publicValue = publicValue;
+ ccd.secretKey = sharedSecret;
+ ret = CKYApplet_HandleAPDU(conn,
+ CKYAppletFactory_ComputeECCKeyAgreementOneStep, &ccd, nonce,
+ CKY_SIZE_UNKNOWN, ckyAppletFill_ComputeECCValueFinal,
+ result, apduRC);
+ if (ret == CKYAPDUFAIL && *apduRC == CKYISO_INCORRECT_P2) {
+ return ret;
+ }
+ }
+
+ return ret;
+}
+
+CKYStatus
+CKYApplet_ComputeECCSignature(CKYCardConnection *conn, CKYByte keyNumber,
+ const CKYBuffer *data, CKYBuffer *sig,
+ CKYBuffer *result, const CKYBuffer *nonce, CKYISOStatus *apduRC)
+{
+ CKYStatus ret = CKYAPDUFAIL;
+ CKYAppletArgComputeECCSignature ccd;
+ CKYBuffer empty;
+ CKYISOStatus status;
+
+ CKYBuffer_InitEmpty(&empty);
+ ccd.keyNumber = keyNumber;
+
+ /* Assume APDU, the signature can only get so big with our key sizes, ~ 130 for 521 bit key. */
+ ccd.location = CKY_DL_APDU;
+
+ if (!apduRC)
+ apduRC = &status;
+
+ if (ccd.location == CKY_DL_APDU) {
+ ccd.data = data;
+ ccd.sig = sig;
+ ret = CKYApplet_HandleAPDU(conn,
+ CKYAppletFactory_ComputeECCSignatureOneStep, &ccd, nonce,
+ CKY_SIZE_UNKNOWN, ckyAppletFill_ComputeECCValueFinal,
+ result, apduRC);
+ if (ret == CKYAPDUFAIL && *apduRC == CKYISO_INCORRECT_P2) {
+ return ret;
+ }
+
+ }
+
+ return ret;
+}
+
+/*
+ * do a CAC Sign/Decrypt
+ */
+CKYStatus
+CACApplet_SignDecrypt(CKYCardConnection *conn, const CKYBuffer *data,
+ CKYBuffer *result, CKYISOStatus *apduRC)
+{
+ CKYStatus ret;
+ CKYSize dataSize = CKYBuffer_Size(data);
+ CKYOffset offset = 0;
+ CKYBuffer tmp;
+
+ CKYBuffer_InitEmpty(&tmp);
+
+ CKYBuffer_Resize(result, 0);
+ for(offset = 0; (dataSize-offset) > CKY_MAX_WRITE_CHUNK_SIZE;
+ offset += CKY_MAX_WRITE_CHUNK_SIZE) {
+ CKYBuffer_Resize(&tmp,0);
+ CKYBuffer_AppendBuffer(&tmp, data, offset, CKY_MAX_WRITE_CHUNK_SIZE);
+ ret = CKYApplet_HandleAPDU(conn, CACAppletFactory_SignDecryptStep,
+ &tmp, NULL, CKY_SIZE_UNKNOWN,
+ CKYAppletFill_AppendBuffer,
+ result, apduRC);
+ if (ret != CKYSUCCESS) {
+ goto done;
+ }
+ }
+ CKYBuffer_Resize(&tmp,0);
+ CKYBuffer_AppendBuffer(&tmp, data, offset, dataSize - offset);
+ ret = CKYApplet_HandleAPDU(conn, CACAppletFactory_SignDecryptFinal,
+ &tmp, NULL, CKY_SIZE_UNKNOWN,
+ CKYAppletFill_AppendBuffer,
+ result, apduRC);
+
+ if ((ret == CKYSUCCESS) && (CKYBuffer_Size(result) != dataSize)) {
+ /* RSA returns the same data size as input, didn't happen, so
+ * something is wrong. */
+ }
+
+done:
+ CKYBuffer_FreeData(&tmp);
+ return ret;
+}
+
+const P15PinInfo CACPinInfo =
+ { P15PinInitialized|P15PinNeedsPadding, P15PinUTF8, 0, 8, 8, 0, 0xff };
+const P15PinInfo PIVPinInfo =
+ { P15PinLocal|P15PinInitialized|P15PinNeedsPadding,
+ P15PinUTF8, 0, 8, 8, 0, 0xff };
+/*
+ * do a CAC VerifyPIN
+ */
+CKYStatus
+CACApplet_VerifyPIN(CKYCardConnection *conn, const char *pin, int local,
+ CKYISOStatus *apduRC)
+{
+ return P15Applet_VerifyPIN(conn, pin,
+ local ? &PIVPinInfo: &CACPinInfo, apduRC);
+}
+
+
+/*
+ * Get a CAC Certificate
+ */
+CKYStatus
+CACApplet_GetCertificate(CKYCardConnection *conn, CKYBuffer *cert,
+ CKYISOStatus *apduRC)
+{
+ CKYStatus ret;
+ CKYISOStatus status;
+ CKYSize size = 100;
+
+ CKYBuffer_Resize(cert,0);
+ if (apduRC == NULL) {
+ apduRC = &status;
+ }
+
+ ret = CKYApplet_HandleAPDU(conn,
+ CACAppletFactory_GetCertificate, &size, NULL,
+ CKY_SIZE_UNKNOWN, CKYAppletFill_AppendBuffer, cert,
+ apduRC);
+ while ((*apduRC & CKYISO_MORE_MASK) == CKYISO_MORE) {
+ size = *apduRC & ~CKYISO_MORE_MASK;
+ ret = CKYApplet_HandleAPDU(conn,
+ CACAppletFactory_GetCertificate, &size, NULL,
+ CKY_SIZE_UNKNOWN, CKYAppletFill_AppendBuffer, cert,
+ apduRC);
+ }
+ return ret;
+}
+
+/*
+ * Read a CAC Tag/Value file
+ */
+CKYStatus
+CACApplet_ReadFile(CKYCardConnection *conn, CKYByte type, CKYBuffer *buffer,
+ CKYISOStatus *apduRC)
+{
+ CKYStatus ret;
+ CKYISOStatus status;
+ CKYByte maxtransfer;
+ unsigned short offset = 0;
+ unsigned short size;
+ CACAppletArgReadFile rfs;
+
+ CKYBuffer_Resize(buffer,0);
+ if (apduRC == NULL) {
+ apduRC = &status;
+ }
+ rfs.offset = 0;
+ rfs.count = 2;
+ rfs.type = type;
+
+ /* APDU's are expensive, Grab a big chunk of the file first if possible */
+ ret = CKYApplet_HandleAPDU(conn,
+ CACAppletFactory_ReadFile, &rfs, NULL,
+ rfs.count, CKYAppletFill_AppendBuffer,
+ buffer, apduRC);
+ /* file is probably smaller than 100 bytes, get the actual size first */
+ if (ret != CKYSUCCESS) {
+ return ret;
+ }
+ size = CKYBuffer_GetShortLE(buffer, 0) + 2 /* include the length itself */;
+ maxtransfer = CKY_MAX_READ_CHUNK_SIZE;
+ /* get the rest of the buffer if necessary */
+ for (offset = CKYBuffer_Size(buffer); size > offset;
+ offset = CKYBuffer_Size(buffer)) {
+ rfs.offset = offset;
+ rfs.count = MIN(size - offset, maxtransfer);
+ ret = CKYApplet_HandleAPDU(conn,
+ CACAppletFactory_ReadFile, &rfs, NULL,
+ rfs.count, CKYAppletFill_AppendBuffer,
+ buffer, apduRC);
+ if (ret != CKYSUCCESS) {
+ if (*apduRC == CAC_INVALID_PARAMS) {
+ maxtransfer = maxtransfer/2;
+ if (maxtransfer == 0) {
+ return ret;
+ }
+ } else {
+ return ret;
+ }
+ }
+ }
+ return ret;
+}
+
+/*
+ * Select a EF
+ */
+CKYStatus
+P15Applet_SelectFile(CKYCardConnection *conn, unsigned short ef,
+ CKYISOStatus *apduRC)
+{
+ CKYStatus ret;
+ CKYBuffer efBuf;
+ CKYBuffer_InitEmpty(&efBuf);
+ CKYBuffer_AppendShort(&efBuf, ef);
+ ret = CKYApplet_HandleAPDU(conn, P15AppletFactory_SelectFile, &efBuf,
+ NULL, CKY_SIZE_UNKNOWN, CKYAppletFill_Null, NULL, apduRC);
+ CKYBuffer_FreeData(&efBuf);
+ return ret;
+}
+
+CKYStatus
+P15Applet_SelectRootFile(CKYCardConnection *conn, unsigned short ef,
+ CKYISOStatus *apduRC)
+{
+ CKYStatus ret;
+ CKYBuffer efBuf;
+ CKYBuffer_InitEmpty(&efBuf);
+ CKYBuffer_AppendShort(&efBuf, ef);
+ ret = CKYApplet_HandleAPDU(conn, CKYAppletFactory_SelectFile, &efBuf,
+ NULL, CKY_SIZE_UNKNOWN, CKYAppletFill_Null, NULL, apduRC);
+ CKYBuffer_FreeData(&efBuf);
+ return ret;
+}
+
+CKYStatus
+P15Applet_VerifyPIN(CKYCardConnection *conn, const char *pin,
+ const P15PinInfo *pinInfo, CKYISOStatus *apduRC)
+{
+ CKYStatus ret;
+ CKYISOStatus status;
+ CKYSize size;
+ CKYBuffer encodedPin;
+ P15AppletArgVerifyPIN vps;
+
+ CKYBuffer_InitEmpty(&encodedPin);
+
+ if (apduRC == NULL) {
+ apduRC = &status;
+ }
+
+ size = strlen(pin);
+ if (pinInfo->pinFlags & P15PinNeedsPadding) {
+ if (size > pinInfo->storedLength) {
+ size = pinInfo->storedLength;
+ }
+ ret=CKYBuffer_Reserve(&encodedPin, pinInfo->storedLength);
+ if (ret != CKYSUCCESS) { goto fail; }
+ }
+ /* This is where we would do upcase processing for the case insensitive
+ * flag. It's also where we would do mapping for bcd pins */
+ ret = CKYBuffer_Replace(&encodedPin, 0, (const CKYByte *)pin, size);
+ if (ret != CKYSUCCESS) { goto fail; }
+ if (pinInfo->pinFlags & P15PinNeedsPadding) {
+ int i;
+ int padSize = pinInfo->storedLength - size;
+ for (i=0; i < padSize; i++) {
+ CKYBuffer_AppendChar(&encodedPin, pinInfo->padChar);
+ }
+ }
+
+ vps.pinRef = pinInfo->pinRef |
+ ((pinInfo->pinFlags & P15PinLocal) ? ISO_LOGIN_LOCAL : ISO_LOGIN_GLOBAL);
+ vps.pinVal = &encodedPin;
+ ret = CKYApplet_HandleAPDU(conn, P15AppletFactory_VerifyPIN, &vps, NULL,
+ 0, CKYAppletFill_Null,
+ NULL, apduRC);
+ /* it's unfortunate that the same code that means 'more data to follow' for
+ * GetCertificate also means, auth failure, you only have N more attempts
+ * left in the verify PIN call */
+ if ((*apduRC & CKYISO_MORE_MASK) == CKYISO_MORE) {
+ ret = CKYAPDUFAIL;
+ }
+fail:
+ CKYBuffer_FreeData(&encodedPin);
+ return ret;
+}
+
+
+/*
+ * Read Record
+ */
+CKYStatus
+P15Applet_ReadRecord(CKYCardConnection *conn, CKYByte record, CKYByte short_ef,
+ CKYByte flags, CKYByte size, CKYBuffer *data, CKYISOStatus *apduRC)
+{
+ P15AppletArgReadRecord rrd;
+
+ rrd.record = record;
+ rrd.short_ef = short_ef;
+ rrd.flags = flags;
+ rrd.size = size;
+ return CKYApplet_HandleAPDU(conn, P15AppletFactory_ReadRecord, &rrd, NULL,
+ CKY_SIZE_UNKNOWN, CKYAppletFill_ReplaceBuffer, data, apduRC);
+}
+
+static CKYStatus
+P15Applet_ManageSecurityEnvironment(CKYCardConnection *conn, CKYByte key,
+ CKYByte direction, CKYByte p1,
+ CKYISOStatus *apduRC)
+{
+ P15AppletArgManageSecurityEnvironment mse;
+
+ mse.p1 = p1; /* this appears to be where most cards disagree */
+ mse.p2 = (direction == CKY_DIR_DECRYPT) ? ISO_MSE_KEA : ISO_MSE_SIGN;
+ mse.keyRef = key; /* should be CKYBuffer in the future? */
+ return CKYApplet_HandleAPDU(conn,
+ P15AppletFactory_ManageSecurityEnvironment, &mse, NULL,
+ CKY_SIZE_UNKNOWN, CKYAppletFill_Null, NULL, apduRC);
+}
+
+CKYStatus
+P15Applet_SignDecrypt(CKYCardConnection *conn, CKYByte key,
+ unsigned int keySize, CKYByte direction,
+ const CKYBuffer *data, CKYBuffer *result, CKYISOStatus *apduRC)
+{
+ CKYStatus ret;
+ P15AppletArgPerformSecurityOperation pso;
+ CKYSize dataSize = CKYBuffer_Size(data);
+ CKYOffset offset = 0;
+ CKYBuffer tmp;
+ int length = dataSize;
+ int appendLength = length;
+ int hasPad = 0;
+
+ /* Hack, lie and say we are always doing encipherment */
+ direction = CKY_DIR_DECRYPT;
+ CKYBuffer_Resize(result,0);
+ /*
+ * first set the security environment
+ */
+ ret = P15Applet_ManageSecurityEnvironment(conn, key, direction,
+ ISO_MSE_SET|ISO_MSE_QUAL_COMPUTE, apduRC);
+ if (ret != CKYSUCCESS) {
+ return ret;
+ }
+
+ CKYBuffer_InitEmpty(&tmp);
+
+ pso.data = &tmp;
+ pso.dir = direction;
+ if (direction == CKY_DIR_DECRYPT) {
+ length++;
+ CKYBuffer_AppendChar(&tmp, 0x00); /* pad byte */
+ hasPad = 1;
+ }
+ if (CKYCardConnection_GetProtocol(conn) == SCARD_PROTOCOL_T0) {
+ ret = CKYBuffer_Reserve(&tmp, CKY_MAX_WRITE_CHUNK_SIZE);
+ if (ret != CKYSUCCESS) {
+ goto done;
+ }
+ for(offset = 0; length > CKY_MAX_WRITE_CHUNK_SIZE;
+ hasPad = 0,
+ offset += CKY_MAX_WRITE_CHUNK_SIZE,
+ length -= CKY_MAX_WRITE_CHUNK_SIZE) {
+ pso.chain = 1;
+ pso.retLen = 0;
+ CKYBuffer_AppendBuffer(&tmp, data, offset,
+ hasPad ? (CKY_MAX_WRITE_CHUNK_SIZE-1) : CKY_MAX_WRITE_CHUNK_SIZE);
+ ret = CKYApplet_HandleAPDU(conn,
+ P15AppletFactory_PerformSecurityOperation, &pso, NULL,
+ CKY_SIZE_UNKNOWN, CKYAppletFill_Null, NULL, apduRC);
+ if (ret != CKYSUCCESS) {
+ goto done;
+ }
+ CKYBuffer_Resize(&tmp, 0);
+ }
+ appendLength = length;
+ } else {
+ ret = CKYBuffer_Reserve(&tmp, length);
+ if (ret != CKYSUCCESS) {
+ goto done;
+ }
+ }
+ CKYBuffer_AppendBuffer(&tmp, data, offset, appendLength);
+ pso.chain = 0;
+ pso.retLen = dataSize;
+
+ ret = CKYApplet_HandleAPDU(conn,
+ P15AppletFactory_PerformSecurityOperation, &pso, NULL,
+ CKY_SIZE_UNKNOWN, CKYAppletFill_ReplaceBuffer, result, apduRC);
+
+done:
+ CKYBuffer_FreeData(&tmp);
+ return ret;
+}
+
+/*
+ * Read Binary
+ */
+CKYStatus
+P15Applet_ReadBinary(CKYCardConnection *conn, unsigned short offset,
+ CKYByte short_ef, CKYByte flags, CKYByte size,
+ CKYBuffer *data, CKYISOStatus *apduRC)
+{
+ P15AppletArgReadBinary red;
+
+ red.offset = offset;
+ red.short_ef = short_ef;
+ red.flags = flags;
+ red.size = size;
+ return CKYApplet_HandleAPDU(conn, P15AppletFactory_ReadBinary, &red, NULL,
+ CKY_SIZE_UNKNOWN, CKYAppletFill_AppendBuffer, data, apduRC);
+}
+
+CKYStatus
+CACApplet_GetCertificateFirst(CKYCardConnection *conn, CKYBuffer *cert,
+ CKYSize *nextSize, CKYISOStatus *apduRC)
+{
+ CKYStatus ret;
+ CKYISOStatus status;
+ CKYSize size = 100;
+
+ CKYBuffer_Resize(cert,0);
+ if (apduRC == NULL) {
+ apduRC = &status;
+ }
+ *nextSize = 0;
+
+ ret = CKYApplet_HandleAPDU(conn,
+ CACAppletFactory_GetCertificate, &size, NULL,
+ CKY_SIZE_UNKNOWN, CKYAppletFill_AppendBuffer, cert,
+ apduRC);
+ if ((*apduRC & CKYISO_MORE_MASK) == CKYISO_MORE) {
+ *nextSize = *apduRC & ~CKYISO_MORE_MASK;
+ }
+ return ret;
+}
+
+CKYStatus
+CACApplet_GetCertificateAppend(CKYCardConnection *conn, CKYBuffer *cert,
+ CKYSize nextSize, CKYISOStatus *apduRC)
+{
+ CKYStatus ret;
+ CKYISOStatus status;
+ CKYSize size = nextSize;
+
+ if (apduRC == NULL) {
+ apduRC = &status;
+ }
+
+ ret = CKYApplet_HandleAPDU(conn,
+ CACAppletFactory_GetCertificate, &size, NULL,
+ CKY_SIZE_UNKNOWN, CKYAppletFill_AppendBuffer, cert,
+ apduRC);
+ while ((*apduRC & CKYISO_MORE_MASK) == CKYISO_MORE) {
+ size = *apduRC & ~CKYISO_MORE_MASK;
+ ret = CKYApplet_HandleAPDU(conn,
+ CACAppletFactory_GetCertificate, &size, NULL,
+ CKY_SIZE_UNKNOWN, CKYAppletFill_AppendBuffer, cert,
+ apduRC);
+ }
+ return ret;
+}
+
+/* Select the PIV applet */
+static CKYByte pivAid[] = {0xa0, 0x00, 0x00, 0x03, 0x08, 0x00, 0x00,
+ 0x10, 0x00};
+CKYStatus
+PIVApplet_Select(CKYCardConnection *conn, CKYISOStatus *apduRC)
+{
+ CKYStatus ret;
+ CKYBuffer PIV_Applet_AID,return_AID;
+
+ CKYBuffer_InitEmpty(&return_AID);
+ CKYBuffer_InitFromData(&PIV_Applet_AID, pivAid, sizeof(pivAid));
+ ret = CKYApplet_HandleAPDU(conn, CKYAppletFactory_SelectFile,
+ &PIV_Applet_AID,
+ NULL, CKY_SIZE_UNKNOWN, CKYAppletFill_AppendBuffer,
+ &return_AID, apduRC);
+ /* Some cards return OK, but don't switch to our applet */
+ /* PIV has a well defined return for it's select, check to see if we have
+ * a PIV card here */
+ if (CKYBuffer_GetChar(&return_AID,0) != 0x61) {
+ /* not an application property template, so not a PIV. We could
+ * check that the aid tag (0x4f) and theallocation authority tag (0x79)
+ * are present, but what we are really avoiding is broken cards that
+ * lie about being able to switch to a particular applet, so the first
+ * tag should be sufficient */
+ ret = CKYAPDUFAIL; /* what we should have gotten */
+ }
+ CKYBuffer_FreeData(&PIV_Applet_AID);
+ CKYBuffer_FreeData(&return_AID);
+ return ret;
+}
+
+/*
+ * Get a PIV Certificate
+ */
+CKYStatus
+PIVApplet_GetCertificate(CKYCardConnection *conn, CKYBuffer *cert, int tag,
+ CKYISOStatus *apduRC)
+{
+ CKYStatus ret;
+ CKYISOStatus status;
+ CKYBuffer tagBuf;
+
+ CKYBuffer_InitEmpty(&tagBuf);
+ CKYBuffer_Reserve(&tagBuf,4); /* can be up to 4 bytes */
+
+ CKYBuffer_Resize(cert,0);
+ if (apduRC == NULL) {
+ apduRC = &status;
+ }
+ if (tag >= 0x01000000) {
+ ret = CKYBuffer_AppendChar(&tagBuf, (tag >> 24) & 0xff);
+ if (ret != CKYSUCCESS) { goto loser; }
+ }
+ if (tag >= 0x010000) {
+ ret = CKYBuffer_AppendChar(&tagBuf, (tag >> 16) & 0xff);
+ if (ret != CKYSUCCESS) { goto loser; }
+ }
+ if (tag >= 0x0100) {
+ ret =CKYBuffer_AppendChar(&tagBuf, (tag >> 8) & 0xff);
+ if (ret != CKYSUCCESS) { goto loser; }
+ }
+ ret = CKYBuffer_AppendChar(&tagBuf, tag & 0xff);
+ if (ret != CKYSUCCESS) { goto loser; }
+
+
+ ret = CKYApplet_HandleAPDU(conn,
+ PIVAppletFactory_GetCertificate, &tagBuf, NULL,
+ CKY_SIZE_UNKNOWN, CKYAppletFill_AppendBuffer, cert,
+ apduRC);
+loser:
+ CKYBuffer_FreeData(&tagBuf);
+
+ return ret;
+}
+
+
+/*
+ * record the next ber tag and length. NOTE: this is a state machine.
+ * we can handle the case where we are passed the data just one byte
+ * at a time.
+ */
+static CKYStatus
+pivUnwrap(const CKYBuffer *buf, CKYOffset *offset,
+ CKYSize *dataSize, PIVUnwrapState *unwrap)
+{
+ if (unwrap->tag == 0) {
+ unwrap->tag = CKYBuffer_GetChar(buf, *offset);
+ if (unwrap->tag == 0) unwrap->tag = 0xff;
+ (*offset)++;
+ (*dataSize)--;
+ }
+ if (*dataSize == 0) {
+ return CKYSUCCESS;
+ }
+ if (unwrap->length_bytes != 0) {
+ int len;
+ if (unwrap->length_bytes == -1) {
+ len = CKYBuffer_GetChar(buf, *offset);
+ unwrap->length_bytes = 0;
+ unwrap->length = len;
+ (*offset)++;
+ (*dataSize)--;
+ if (len & 0x80) {
+ unwrap->length = 0;
+ unwrap->length_bytes = len & 0x7f;
+ }
+ }
+ while ((*dataSize != 0) && (unwrap->length_bytes != 0)) {
+ len = CKYBuffer_GetChar(buf, *offset);
+ (*offset) ++;
+ (*dataSize) --;
+ unwrap->length = ((unwrap->length) << 8 | len);
+ unwrap->length_bytes--;
+ }
+ }
+ return CKYSUCCESS;
+}
+
+/*
+ * Remove the BER wrapping first...
+ */
+static CKYStatus
+pivAppletFill_AppendUnwrapBuffer(const CKYBuffer *response,
+ CKYSize size, void *param)
+{
+ PIVAppletRespSignDecrypt *prsd = (PIVAppletRespSignDecrypt *)param;
+ CKYBuffer *buf = prsd->buf;
+ CKYSize dataSize = CKYBuffer_Size(response);
+ CKYOffset offset = 0;
+
+ if (dataSize <= 2) {
+ return CKYSUCCESS;
+ }
+ dataSize -= 2;
+ /* remove the first tag */
+ (void) pivUnwrap(response, &offset, &dataSize, &prsd->tag_1);
+ if (dataSize == 0) {
+ return CKYSUCCESS;
+ }
+ /* remove the second tag */
+ (void) pivUnwrap(response, &offset, &dataSize, &prsd->tag_2);
+ if (dataSize == 0) {
+ return CKYSUCCESS;
+ }
+ /* the rest is real data */
+ return CKYBuffer_AppendData(buf, CKYBuffer_Data(response) + offset,
+ dataSize);
+}
+
+static CKYStatus
+piv_wrapEncodeLength(CKYBuffer *buf, int length, int ber_len)
+{
+ if (ber_len== 1) {
+ CKYBuffer_AppendChar(buf,length);
+ } else {
+ ber_len--;
+ CKYBuffer_AppendChar(buf,0x80+ber_len);
+ while(ber_len--) {
+ CKYBuffer_AppendChar(buf,(length >> (8*ber_len)) & 0xff);
+ }
+ }
+ return CKYSUCCESS;
+}
+/*
+ * do a PIV Sign/Decrypt
+ */
+CKYStatus
+PIVApplet_SignDecrypt(CKYCardConnection *conn, CKYByte key, unsigned int keySize, int derive,
+ const CKYBuffer *data, CKYBuffer *result, CKYISOStatus *apduRC)
+{
+ CKYStatus ret;
+ CKYSize dataSize = CKYBuffer_Size(data);
+ CKYSize outputSize = keySize;
+ CKYOffset offset = 0;
+ CKYBuffer tmp;
+ CKYByte alg;
+ int ber_len_1;
+ int ber_len_2;
+ int length;
+ PIVAppletArgSignDecrypt pasd;
+ PIVAppletRespSignDecrypt prsd;
+
+ /* PIV only defines RSA 1024 and 2048, ECC 256 and ECC 384!!! */
+ if (keySize == 128) { /* 1024 bit == 128 bytes */
+ ber_len_2 = 2;
+ ber_len_1 = 2;
+ alg = 0x6;
+ } else if (keySize == 256) { /* 2048 bits == 256 bytes */
+ ber_len_2 = 3;
+ ber_len_1 = 3;
+ alg = 0x7;
+ } else if (keySize == 32) { /* 256 bits = 32 bytes */
+ ber_len_2 = 1;
+ ber_len_1 = 1;
+ alg = 0x11;
+ if (!derive) outputSize = keySize*2;
+ } else if (keySize == 48) { /* 384 bits = 48 bytes */
+ ber_len_2 = 1;
+ ber_len_1 = 1;
+ alg = 0x14;
+ if (!derive) outputSize = keySize*2;
+ } else {
+ return CKYINVALIDARGS;
+ }
+
+ CKYBuffer_InitEmpty(&tmp);
+ ret = CKYBuffer_Reserve(&tmp, CKY_MAX_WRITE_CHUNK_SIZE);
+ if (ret != CKYSUCCESS) {
+ goto done;
+ }
+ CKYBuffer_AppendChar(&tmp,0x7c);
+ piv_wrapEncodeLength(&tmp,dataSize + ber_len_2 + 3,ber_len_1);
+ CKYBuffer_AppendChar(&tmp,0x82);
+ CKYBuffer_AppendChar(&tmp,0x0);
+ CKYBuffer_AppendChar(&tmp, derive ? 0x85 : 0x81);
+ piv_wrapEncodeLength(&tmp,dataSize,ber_len_2);
+
+ /* now length == header length from here to the end*/
+ length = CKYBuffer_Size(&tmp);
+
+ if (length + dataSize > CKY_MAX_WRITE_CHUNK_SIZE) {
+ CKYBuffer_AppendBuffer(&tmp, data, 0, CKY_MAX_WRITE_CHUNK_SIZE-length);
+ } else {
+ CKYBuffer_AppendBuffer(&tmp, data, 0, dataSize);
+ }
+
+ prsd.tag_1.tag = 0;
+ prsd.tag_1.length_bytes = -1;
+ prsd.tag_1.length = 0;
+ prsd.tag_2.tag = 0;
+ prsd.tag_2.length_bytes = -1;
+ prsd.tag_2.length = 0;
+ prsd.buf = result;
+ pasd.alg = alg;
+ pasd.key = key;
+ pasd.buf = &tmp;
+
+ CKYBuffer_Resize(result,0);
+ for(offset = -length; (dataSize-offset) > CKY_MAX_WRITE_CHUNK_SIZE; ) {
+ pasd.chain = 1;
+ pasd.len = 0;
+ ret = CKYApplet_HandleAPDU(conn, PIVAppletFactory_SignDecrypt,
+ &pasd, NULL, CKY_SIZE_UNKNOWN,
+ pivAppletFill_AppendUnwrapBuffer,
+ &prsd, apduRC);
+ if (ret != CKYSUCCESS) {
+ goto done;
+ }
+ CKYBuffer_Resize(&tmp,0);
+ /* increment before we append the next tmp buffer */
+ offset += CKY_MAX_WRITE_CHUNK_SIZE;
+ CKYBuffer_AppendBuffer(&tmp, data, offset,
+ MIN(dataSize-offset, CKY_MAX_WRITE_CHUNK_SIZE));
+ }
+
+ pasd.chain = 0;
+ pasd.len = outputSize;
+
+ ret = CKYApplet_HandleAPDU(conn, PIVAppletFactory_SignDecrypt,
+ &pasd, NULL, CKY_SIZE_UNKNOWN,
+ pivAppletFill_AppendUnwrapBuffer,
+ &prsd, apduRC);
+
+ if ((ret == CKYSUCCESS) && (CKYBuffer_Size(result) != outputSize)) {
+ /* RSA returns the same data size as input, didn't happen, so
+ * something is wrong. */
+ }
+
+done:
+ CKYBuffer_FreeData(&tmp);
+ return ret;
+}
+
+/*
+ * PIN cluster
+ */
+CKYStatus
+CKYApplet_CreatePIN(CKYCardConnection *conn, CKYByte pinNumber,
+ CKYByte maxAttempts, const char *pinValue,
+ const CKYBuffer *nonce, CKYISOStatus *apduRC)
+{
+ CKYAppletArgCreatePIN cpd;
+ cpd.pinValue = pinValue;
+ cpd.maxAttempts = maxAttempts;
+ cpd.pinValue = pinValue;
+ return CKYApplet_HandleAPDU(conn, CKYAppletFactory_CreatePIN, &cpd, nonce,
+ 0, CKYAppletFill_Null, NULL, apduRC);
+
+}
+
+CKYStatus
+CKYApplet_VerifyPIN(CKYCardConnection *conn, CKYByte pinNumber,
+ const char *pinValue, CKYBuffer *nonce, CKYISOStatus *apduRC)
+{
+ CKYAppletArgVerifyPIN vpd;
+ vpd.pinValue = pinValue;
+ vpd.pinNumber = pinNumber;
+ return CKYApplet_HandleAPDU(conn, CKYAppletFactory_VerifyPIN, &vpd, NULL,
+ 8, CKYAppletFill_ReplaceBuffer, nonce, apduRC);
+}
+
+CKYStatus
+CKYApplet_ChangePIN(CKYCardConnection *conn, const char *oldPin,
+ const char *newPin, const CKYBuffer *nonce, CKYISOStatus *apduRC)
+{
+ CKYAppletArgChangePIN cpd;
+ cpd.oldPin = oldPin;
+ cpd.newPin = newPin;
+ return CKYApplet_HandleAPDU(conn, CKYAppletFactory_ChangePIN, &cpd, nonce,
+ 0, CKYAppletFill_Null, NULL, apduRC);
+}
+
+CKYStatus
+CKYApplet_ListPINs(CKYCardConnection *conn, unsigned short *pins,
+ CKYISOStatus *apduRC)
+{
+ return CKYApplet_HandleAPDU(conn, CKYAppletFactory_ListPINs, NULL, NULL,
+ CKY_SIZE_LIST_PINS, CKYAppletFill_Short, pins, apduRC);
+}
+
+CKYStatus
+CKYApplet_Logout(CKYCardConnection *conn, CKYByte pinNumber,
+ const CKYBuffer *nonce, CKYISOStatus *apduRC)
+{
+ return CKYApplet_HandleAPDU(conn, CKYAppletFactory_Logout, &pinNumber, nonce,
+ 0, CKYAppletFill_Null, NULL, apduRC);
+}
+
+CKYStatus
+CKYApplet_CreateObject(CKYCardConnection *conn, unsigned long objectID,
+ CKYSize size, unsigned short readACL, unsigned short writeACL,
+ unsigned short deleteACL, const CKYBuffer *nonce, CKYISOStatus *apduRC)
+{
+ CKYAppletArgCreateObject cod;
+ cod.objectID = objectID;
+ cod.size = size;
+ cod.readACL = readACL;
+ cod.writeACL = writeACL;
+ cod.deleteACL = deleteACL;
+ return CKYApplet_HandleAPDU(conn, CKYAppletFactory_CreateObject, &cod,
+ nonce, 0, CKYAppletFill_Null, NULL, apduRC);
+}
+
+CKYStatus
+CKYApplet_DeleteObject(CKYCardConnection *conn, unsigned long objectID,
+ CKYByte zero, const CKYBuffer *nonce, CKYISOStatus *apduRC)
+{
+ CKYAppletArgDeleteObject dod;
+ dod.objectID = objectID;
+ dod.zero = zero;
+ return CKYApplet_HandleAPDU(conn, CKYAppletFactory_DeleteObject, &dod,
+ nonce, 0, CKYAppletFill_Null, NULL, apduRC);
+}
+
+/*
+ * Read Object cluster...
+ * This is the raw version that goes issues a single APDU.
+ */
+CKYStatus
+CKYApplet_ReadObject(CKYCardConnection *conn, unsigned long objectID,
+ CKYOffset offset, CKYByte size, const CKYBuffer *nonce,
+ CKYBuffer *data, CKYISOStatus *apduRC)
+{
+ CKYAppletArgReadObject rod;
+
+ rod.objectID = objectID;
+ rod.offset = offset;
+ rod.size = size;
+ return CKYApplet_HandleAPDU(conn, CKYAppletFactory_ReadObject, &rod, nonce,
+ size, CKYAppletFill_ReplaceBuffer, data, apduRC);
+}
+
+/*
+ * Read Object Append cluster...
+ * This is also issues a single APDU, but appends the resulting data
+ * to an existing buffer.
+ */
+
+CKYStatus
+CKYApplet_ReadObjectAppend(CKYCardConnection *conn, unsigned long objectID,
+ CKYOffset offset, CKYByte size, const CKYBuffer *nonce,
+ CKYBuffer *data, CKYISOStatus *apduRC)
+{
+ CKYAppletArgReadObject rod;
+
+ rod.objectID = objectID;
+ rod.offset = offset;
+ rod.size = size;
+ return CKYApplet_HandleAPDU(conn, CKYAppletFactory_ReadObject, &rod, nonce,
+ size, CKYAppletFill_AppendBuffer, data, apduRC);
+}
+
+/*
+ * Read Object
+ * This is makes multiple APDU calls to read the entire object.
+ */
+CKYStatus
+CKYApplet_ReadObjectFull(CKYCardConnection *conn, unsigned long objectID,
+ CKYOffset offset, CKYSize size, const CKYBuffer *nonce,
+ CKYBuffer *data, CKYISOStatus *apduRC)
+{
+ CKYAppletArgReadObject rod;
+ CKYStatus ret = CKYSUCCESS;
+
+ rod.objectID = objectID;
+ rod.offset = offset;
+ do {
+ rod.size = (CKYByte) MIN(size, CKY_MAX_READ_CHUNK_SIZE);
+ ret = CKYApplet_HandleAPDU(conn, CKYAppletFactory_ReadObject, &rod,
+ nonce, rod.size, CKYAppletFill_AppendBuffer, data, apduRC);
+ size -= rod.size;
+ rod.offset += rod.size;
+ } while ((size > 0) && (ret == CKYSUCCESS));
+
+ return ret;
+}
+
+
+/*
+ * Write Object
+ * This makes multiple APDU calls to write the entire object.
+ *
+ */
+
+CKYStatus
+CKYApplet_WriteObjectFull(CKYCardConnection *conn, unsigned long objectID,
+ CKYOffset offset, CKYSize size, const CKYBuffer *nonce,
+ const CKYBuffer *data, CKYISOStatus *apduRC)
+{
+
+ CKYBuffer chunk;
+ CKYOffset srcOffset = 0;
+ CKYAppletArgWriteObject wod;
+ CKYStatus ret = CKYSUCCESS;
+
+ wod.objectID = objectID;
+ wod.offset = offset;
+ do {
+ wod.size = (CKYByte) MIN(size, 220);
+ ret = CKYBuffer_InitFromBuffer(&chunk, data,
+ srcOffset, wod.size);
+ if(ret == CKYSUCCESS) {
+ wod.data = &chunk;
+ ret = CKYApplet_HandleAPDU(conn, CKYAppletFactory_WriteObject, &wod,
+ nonce, 0, CKYAppletFill_Null, NULL, apduRC);
+ size -= wod.size;
+ wod.offset += wod.size;
+ srcOffset += wod.size;
+ CKYBuffer_FreeData(&chunk);
+ }
+
+ } while ((size > 0) && (ret == CKYSUCCESS));
+
+ return ret;
+}
+
+/*
+ * List Object cluster
+ */
+static CKYStatus
+ckyAppletFill_ListObjects(const CKYBuffer *response, CKYSize size, void *param)
+{
+ CKYAppletRespListObjects *lop = (CKYAppletRespListObjects *)param;
+
+ lop->objectID = CKYBuffer_GetLong(response, 0);
+ lop->objectSize = CKYBuffer_GetLong(response, 4);
+ lop->readACL = CKYBuffer_GetShort(response, 8);
+ lop->writeACL = CKYBuffer_GetShort(response, 10);
+ lop->deleteACL = CKYBuffer_GetShort(response, 12);
+ return CKYSUCCESS;
+}
+
+CKYStatus
+CKYApplet_ListObjects(CKYCardConnection *conn, CKYByte seq,
+ CKYAppletRespListObjects *lop, CKYISOStatus *apduRC)
+{
+ return CKYApplet_HandleAPDU(conn, CKYAppletFactory_ListObjects, &seq, NULL,
+ CKY_SIZE_LIST_OBJECTS, ckyAppletFill_ListObjects, lop, apduRC);
+}
+
+/*
+ * GetStatus cluster
+ */
+static CKYStatus
+ckyAppletFill_GetStatus(const CKYBuffer *response, CKYSize size, void *param)
+{
+ CKYAppletRespGetStatus *gsp = (CKYAppletRespGetStatus *)param;
+
+ gsp->protocolMajorVersion = CKYBuffer_GetChar(response, 0);
+ gsp->protocolMinorVersion = CKYBuffer_GetChar(response, 1);
+ gsp->appletMajorVersion = CKYBuffer_GetChar(response, 2);
+ gsp->appletMinorVersion = CKYBuffer_GetChar(response, 3);
+ gsp->totalObjectMemory = CKYBuffer_GetLong(response, 4);
+ gsp->freeObjectMemory = CKYBuffer_GetLong(response, 8);
+ gsp->numberPins = CKYBuffer_GetChar(response, 12);
+ gsp->numberKeys = CKYBuffer_GetChar(response, 13);
+ gsp->loggedInMask = CKYBuffer_GetShort(response, 14);
+ return CKYSUCCESS;
+}
+
+CKYStatus
+CKYApplet_GetStatus(CKYCardConnection *conn, CKYAppletRespGetStatus *status,
+ CKYISOStatus *apduRC)
+{
+ return CKYApplet_HandleAPDU(conn, CKYAppletFactory_GetStatus, NULL, NULL,
+ CKY_SIZE_GET_STATUS, ckyAppletFill_GetStatus, status, apduRC);
+}
+
+CKYStatus
+CKYApplet_Noop(CKYCardConnection *conn, CKYISOStatus *apduRC)
+{
+ return CKYApplet_HandleAPDU(conn, CKYAppletFactory_Noop, NULL, NULL,
+ 0, CKYAppletFill_Null, NULL, apduRC);
+}
+
+CKYStatus
+CKYApplet_GetBuildID(CKYCardConnection *conn, unsigned long *buildID,
+ CKYISOStatus *apduRC)
+{
+ return CKYApplet_HandleAPDU(conn, CKYAppletFactory_GetBuildID, NULL, NULL,
+ CKY_SIZE_GET_BUILDID, CKYAppletFill_Long, buildID, apduRC);
+}
+
+/*
+ * GetLifeCycle cluster
+ */
+static CKYStatus
+ckyAppletFill_GetLifeCycle(const CKYBuffer *response, CKYSize size, void *param)
+{
+ *(CKYByte *)param= CKYBuffer_GetChar(response,0);
+ return CKYSUCCESS;
+}
+
+CKYStatus
+CKYApplet_GetLifeCycle(CKYCardConnection *conn, CKYByte *personalized,
+ CKYISOStatus *apduRC)
+{
+ return CKYApplet_HandleAPDU(conn, CKYAppletFactory_GetLifeCycle, NULL, NULL,
+ CKY_SIZE_GET_LIFE_CYCLE, ckyAppletFill_GetLifeCycle, personalized, apduRC);
+}
+
+static CKYStatus
+ckyAppletFill_GetLifeCycleV2(const CKYBuffer *response, CKYSize size, void *param)
+{
+ CKYAppletRespGetLifeCycleV2 *ext = (CKYAppletRespGetLifeCycleV2 *) param;
+ ext->lifeCycle = CKYBuffer_GetChar(response,0);
+ ext->pinCount = CKYBuffer_GetChar(response,1);
+ ext->protocolMajorVersion = CKYBuffer_GetChar(response,2);
+ ext->protocolMinorVersion = CKYBuffer_GetChar(response,3);
+ return CKYSUCCESS;
+}
+
+/*
+ * GetStatus cluster
+ */
+static CKYStatus
+ckyAppletFill_LifeCycleStatus(const CKYBuffer *response, CKYSize size, void *param)
+{
+ CKYAppletRespGetLifeCycleV2 *ext = (CKYAppletRespGetLifeCycleV2 *) param;
+ ext->pinCount = CKYBuffer_GetChar(response,12);
+ ext->protocolMajorVersion = CKYBuffer_GetChar(response,0);
+ ext->protocolMinorVersion = CKYBuffer_GetChar(response,1);
+ return CKYSUCCESS;
+}
+
+CKYStatus
+CKYApplet_GetLifeCycleV2(CKYCardConnection *conn,
+ CKYAppletRespGetLifeCycleV2 *ext, CKYISOStatus *apduRC)
+{
+ CKYStatus status;
+ status = CKYApplet_HandleAPDU(conn, CKYAppletFactory_GetLifeCycleV2,
+ NULL,NULL, CKY_SIZE_GET_LIFE_CYCLE_V2, ckyAppletFill_GetLifeCycleV2,
+ ext, apduRC);
+
+ /* Get Life Cycle Version 2 is a new APDU with combines data from
+ * two other APDUs. Older tokens don't have this APDU, so use
+ * the old method to get the data */
+ if (status == CKYAPDUFAIL) {
+ status = CKYApplet_GetLifeCycle(conn,&ext->lifeCycle, apduRC);
+ if (status != CKYSUCCESS) {
+ return status;
+ }
+ status = CKYApplet_HandleAPDU(conn, CKYAppletFactory_GetStatus, NULL,
+ NULL, CKY_SIZE_GET_STATUS, ckyAppletFill_LifeCycleStatus, ext, apduRC);
+ }
+ return status;
+}
+
+/*
+ * GetBuiltin cluster
+ */
+static CKYStatus
+ckyAppletFill_GetBuiltinACL(const CKYBuffer *response,CKYSize size,void *param)
+{
+ CKYAppletRespGetBuiltinACL *gba = (CKYAppletRespGetBuiltinACL *) param;
+ gba->create_object_ACL = CKYBuffer_GetShort(response,0);
+ gba->create_object_ACL = CKYBuffer_GetShort(response,2);
+ gba->create_object_ACL = CKYBuffer_GetShort(response,4);
+ gba->enable_ACL_change = CKYBuffer_GetChar(response,6);
+ return CKYSUCCESS;
+}
+
+CKYStatus
+CKYApplet_GetBuiltinACL(CKYCardConnection *conn,
+ CKYAppletRespGetBuiltinACL *gba, CKYISOStatus *apduRC)
+{
+ return CKYApplet_HandleAPDU(conn, CKYAppletFactory_GetBuiltinACL, NULL,
+ NULL, CKY_SIZE_GET_BUILTIN_ACL, ckyAppletFill_GetBuiltinACL, gba,
+ apduRC);
+}
+
+CKYStatus
+CKYApplet_GetIssuerInfo(CKYCardConnection *conn, CKYBuffer *info,
+ CKYISOStatus *apduRC)
+{
+ return CKYApplet_HandleAPDU(conn, CKYAppletFactory_GetIssuerInfo, NULL,
+ NULL, CKY_SIZE_GET_ISSUER_INFO, CKYAppletFill_ReplaceBuffer,
+ info, apduRC);
+}
+
+CKYStatus
+CKYApplet_GetRandom(CKYCardConnection *conn, CKYBuffer *data, CKYByte len,
+ CKYISOStatus *apduRC)
+{
+ return CKYApplet_HandleAPDU(conn, CKYAppletFactory_GetRandom, &len,
+ NULL, len, CKYAppletFill_ReplaceBuffer, data, apduRC);
+}
+
+CKYStatus
+CKYApplet_GetRandomAppend(CKYCardConnection *conn, CKYBuffer *data, CKYByte len,
+ CKYISOStatus *apduRC)
+{
+ return CKYApplet_HandleAPDU(conn, CKYAppletFactory_GetRandom, &len,
+ NULL, len, CKYAppletFill_AppendBuffer, data, apduRC);
+}
+
+CKYStatus
+CKYApplet_SeedRandom(CKYCardConnection *conn, const CKYBuffer *data,
+ CKYISOStatus *apduRC)
+{
+ return CKYApplet_HandleAPDU(conn, CKYAppletFactory_SeedRandom, data,
+ NULL, 0, CKYAppletFill_Null, NULL, apduRC);
+}
+
+
+
+/*
+ * deprecates 0.x functions
+ */
+/* old applet verify pin call (no nonce returned) */
+CKYStatus
+CKYApplet_VerifyPinV0(CKYCardConnection *conn, CKYByte pinNumber,
+ const char *pinValue, CKYISOStatus *apduRC)
+{
+ CKYAppletArgVerifyPIN vpd;
+ vpd.pinValue = pinValue;
+ vpd.pinNumber = pinNumber;
+
+ vpd.pinValue = pinValue;
+ vpd.pinNumber = pinNumber;
+ return CKYApplet_HandleAPDU(conn, CKYAppletFactory_VerifyPIN, &vpd, NULL,
+ 0, CKYAppletFill_Null, NULL, apduRC);
+}
+
+/* logout all */
+CKYStatus
+CKYApplet_LogoutAllV0(CKYCardConnection *conn, CKYISOStatus *apduRC)
+{
+ return CKYApplet_HandleAPDU(conn, CKYAppletFactory_LogoutAllV0, NULL, NULL,
+ 0, CKYAppletFill_Null, NULL, apduRC);
+}
diff -up ./esc/src/lib/coolkey/cky_applet.h.fix1 ./esc/src/lib/coolkey/cky_applet.h
--- ./esc/src/lib/coolkey/cky_applet.h.fix1 2018-04-26 11:44:38.436986198 -0700
+++ ./esc/src/lib/coolkey/cky_applet.h 2018-04-26 11:44:38.436986198 -0700
@@ -0,0 +1,680 @@
+/* ***** BEGIN COPYRIGHT BLOCK *****
+ * Copyright (C) 2005 Red Hat, Inc.
+ * All rights reserved.
+ *
+ * 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 St, Fifth Floor, Boston, MA 02110-1301 USA
+ * ***** END COPYRIGHT BLOCK ***** */
+
+#ifndef CKY_APPLET_H
+#define CKY_APPLET_H 1
+
+#include "cky_base.h"
+#include "cky_card.h"
+#include "cky_factory.h"
+
+/*
+ * base typdefs
+ */
+/*
+ * ISO and applet response codes.
+ */
+typedef unsigned short CKYISOStatus; /* applet return status */
+/* Psuedo return codes created by the library software */
+#define CKYISO_INVRESPONSE 0xffff /* code returned by library to
+ * indicate no valid response
+ * received */
+#define CKYISO_NORESPONSE 0x0000 /* code returned by the library if
+ * operation failed before
+ * attempting to read a response */
+/* ISO defined Return codes */
+#define CKYISO_SUCCESS 0x9000 /* SUCCESS! */
+#define CKYISO_MORE_MASK 0xff00 /* More data mask */
+#define CKYISO_MORE 0x6300 /* More data available */
+#define CKYISO_DATA_INVALID 0x6984
+#define CKYISO_CONDITION_NOT_SATISFIED 0x6985 /* AKA not logged in (CAC)*/
+#define CKYISO_SECURITY_NOT_SATISFIED 0x6982 /* AKA not logged in (PIV)*/
+/* Applet Defined Return codes */
+#define CKYISO_NO_MEMORY_LEFT 0x9c01 /* There have been memory
+ * problems on the card */
+#define CKYISO_AUTH_FAILED 0x9c02 /* Entered PIN is not correct */
+#define CKYISO_OPERATION_NOT_ALLOWED 0x9c03 /* Required operation is not
+ * allowed in actual
+ * circumstances */
+#define CKYISO_UNSUPPORTED_FEATURE 0x9c05 /* Required feature is not (yet)
+ * supported */
+#define CKYISO_UNAUTHORIZED 0x9c06 /* Required operation was not
+ * authorized because of a lack of
+ * privileges */
+#define CKYISO_OBJECT_NOT_FOUND 0x9c07 /* Required object is missing */
+#define CKYISO_OBJECT_EXISTS 0x9c08 /* New object ID already in use */
+#define CKYISO_INCORRECT_ALG 0x9c09 /* Algorithm specified is not
+ * correct */
+#define CKYISO_SIGNATURE_INVALID 0x9c0b /* Verify operation detected an
+ * invalid signature */
+#define CKYISO_IDENTITY_BLOCKED 0x9c0c /* Operation has been blocked for
+ * security reason */
+#define CKYISO_INVALID_PARAMETER 0x9c0f /* Invalid input parameter to
+ * command */
+#define CKYISO_INCORRECT_P1 0x9c10 /* Incorrect P1 parameter */
+#define CKYISO_INCORRECT_P2 0x9c11 /* Incorrect P2 parameter */
+#define CKYISO_SEQUENCE_END 0x9c12 /* No more data available */
+#define CKYISO_INTERNAL_ERROR 0x9cff /* Reserved for debugging,
+ * shouldn't happen */
+
+#define CAC_INVALID_PARAMS 0x6a83
+#define CAC_TAG_FILE 1
+#define CAC_VALUE_FILE 2
+
+
+#define CAC_TAG_CARDURL 0xf3
+#define CAC_TAG_CERTIFICATE 0x70
+#define CAC_TAG_CERTINFO 0x71
+#define CAC_TLV_APP_PKI 0x04
+
+/*
+ * Pin Constants as used by our applet
+ */
+#define CKY_OLD_USER_PIN_NUM 1 /* version 0 and earlier */
+#define CKY_USER_PIN_NUM 0
+
+/*
+ * special size that tells the Verify Function not to verify the size because
+ * the ADPU can return variable size.
+ */
+#define CKY_SIZE_UNKNOWN 0xffffffff
+
+/*
+ * structures for returning Applet responses
+ */
+typedef struct _CKYAppletRespGetStatus {
+ CKYByte protocolMajorVersion;
+ CKYByte protocolMinorVersion;
+ CKYByte appletMajorVersion;
+ CKYByte appletMinorVersion;
+ unsigned long totalObjectMemory;
+ unsigned long freeObjectMemory;
+ CKYByte numberPins;
+ CKYByte numberKeys;
+ unsigned short loggedInMask;
+} CKYAppletRespGetStatus;
+
+typedef struct _CKYAppletRespGetLifeCycleV2 {
+ CKYByte lifeCycle;
+ CKYByte pinCount;
+ CKYByte protocolMajorVersion;
+ CKYByte protocolMinorVersion;
+} CKYAppletRespGetLifeCycleV2;
+
+typedef struct _CKYAppletRespGetBuiltinACL {
+ unsigned short create_object_ACL;
+ unsigned short create_key_ACL;
+ unsigned short create_pin_ACL;
+ CKYByte enable_ACL_change;
+} CKYAppletRespGetBuiltinACL;
+
+typedef struct _CKYAppletRespGetCPLCData {
+ unsigned short CPLCtag;
+ CKYByte length;
+ unsigned short fabricator;
+ unsigned short romType;
+ unsigned short romOSID;
+ unsigned short romOSDate;
+ unsigned short romOSLevel;
+ unsigned short eepromFabricationDate;
+ unsigned long eepromSerialNumber;
+ unsigned short eepromBatchID;
+ unsigned short eepromModuleFabricator;
+ unsigned short eepromModuleDate;
+ unsigned short eepromICManufacturer;
+ unsigned short eepromEmbeddingDate;
+ unsigned short eepromPrePersonalizer;
+ unsigned short eepromPrePersonalizeDate;
+ unsigned long eepromPrePersonalizeID;
+ unsigned short eepromPersonalizer;
+ unsigned short eepromPersonalizeDate;
+ unsigned long eepromPersonalizeID;
+} CKYAppletRespGetCPLCData;
+
+typedef struct _CKYAppletRespListObjects {
+ unsigned long objectID;
+ CKYSize objectSize;
+ unsigned short readACL;
+ unsigned short writeACL;
+ unsigned short deleteACL;
+} CKYAppletRespListObjects;
+
+typedef struct _CKYAppletRespListKeys {
+ CKYByte keyNum;
+ CKYByte keyType;
+ CKYByte keyPartner;
+ unsigned short keySize;
+ unsigned short readACL;
+ unsigned short writeACL;
+ unsigned short useACL;
+} CKYAppletRespListKeys;
+
+/*
+ * structures for the generic factories
+ */
+typedef struct _CKYAppletArgCreatePIN {
+ const char *pinValue;
+ CKYByte pinNumber;
+ CKYByte maxAttempts;
+} CKYAppletArgCreatePIN;
+
+typedef struct _CKYAppletArgVerifyPIN {
+ const char *pinValue;
+ CKYByte pinNumber;
+} CKYAppletArgVerifyPIN;
+
+typedef struct _CKYAppletArgChangePIN {
+ const char *oldPin;
+ const char *newPin;
+ CKYByte pinNumber;
+} CKYAppletArgChangePIN;
+
+typedef struct _CKYAppletArgCreateObject {
+ unsigned long objectID;
+ CKYSize size;
+ unsigned short readACL;
+ unsigned short writeACL;
+ unsigned short deleteACL;
+} CKYAppletArgCreateObject;
+
+typedef struct _CKYAppletArgDeleteObject {
+ unsigned long objectID;
+ CKYByte zero;
+} CKYAppletArgDeleteObject;
+
+typedef struct _CKYAppletArgReadObject {
+ unsigned long objectID;
+ CKYOffset offset;
+ CKYByte size;
+} CKYAppletArgReadObject;
+
+
+typedef struct _CKYAppletArgWriteObject {
+ unsigned long objectID;
+ CKYOffset offset;
+ CKYByte size;
+ CKYBuffer *data;
+
+} CKYAppletArgWriteObject;
+
+typedef struct _CKYAppletArgComputeCrypt {
+ CKYByte keyNumber;
+ CKYByte mode;
+ CKYByte direction;
+ CKYByte location;
+ const CKYBuffer *data;
+ const CKYBuffer *sig;
+} CKYAppletArgComputeCrypt;
+
+typedef struct _CKYAppletArgComputeECCSignature {
+ CKYByte keyNumber;
+ CKYByte location;
+ const CKYBuffer *data;
+ const CKYBuffer *sig;
+} CKYAppletArgComputeECCSignature;
+
+typedef struct _CKYAppletArgComputeECCKeyAgreement {
+ CKYByte keyNumber;
+ CKYByte location;
+ const CKYBuffer *publicValue;
+ const CKYBuffer *secretKey;
+} CKYAppletArgComputeECCKeyAgreement;
+
+
+typedef struct _CACAppletArgReadFile {
+ CKYByte type;
+ CKYByte count;
+ unsigned short offset;
+} CACAppletArgReadFile;
+
+typedef struct _PIVAppletArgSignDecrypt {
+ CKYByte alg;
+ CKYByte key;
+ CKYByte chain;
+ CKYSize len;
+ CKYBuffer *buf;
+} PIVAppletArgSignDecrypt;
+
+typedef struct _pivUnwrapState {
+ CKYByte tag;
+ CKYByte length;
+ int length_bytes;
+} PIVUnwrapState;
+
+typedef struct _PIVAppletRespSignDecrypt {
+ PIVUnwrapState tag_1;
+ PIVUnwrapState tag_2;
+ CKYBuffer *buf;
+} PIVAppletRespSignDecrypt;
+
+typedef struct _P15AppletArgReadRecord {
+ CKYByte record;
+ CKYByte short_ef;
+ CKYByte flags;
+ CKYByte size;
+} P15AppletArgReadRecord;
+
+typedef struct _P15AppletArgReadBinary {
+ unsigned short offset;
+ CKYByte short_ef;
+ CKYByte flags;
+ CKYByte size;
+} P15AppletArgReadBinary;
+
+typedef struct _P15AppletArgVerifyPIN {
+ const CKYBuffer *pinVal;
+ CKYByte pinRef;
+} P15AppletArgVerifyPIN;
+
+typedef struct _P15AppletArgManageSecurityEnvironment {
+ CKYByte p1;
+ CKYByte p2;
+ CKYByte keyRef;
+}
+ P15AppletArgManageSecurityEnvironment;
+
+typedef struct _P15AppletArgPerformSecurityOperation {
+ CKYByte dir;
+ int chain;
+ CKYSize retLen;
+ const CKYBuffer *data;
+} P15AppletArgPerformSecurityOperation;
+
+/* fills in an APDU from a structure -- form of all the generic factories*/
+typedef CKYStatus (*CKYAppletFactory)(CKYAPDU *apdu, const void *param);
+/* fills in an a structure from a response -- form of all the fill structures*/
+typedef CKYStatus (*CKYFillFunction)(const CKYBuffer *response,
+ CKYSize size, void *param);
+
+CKY_BEGIN_PROTOS
+/*****************************************************************
+ *
+ * Generic factorys are used by the generic APDU processing
+ * to customize the formatting of APDU. The all have the same signature
+ * as CKYAppletFactory. Typically APDUs are formatted
+ * using parameterized calls of the form CKYAPDUFactory_ADPUNAME.
+ * The generic processing code, however needs calls with a common
+ * Signature. To accomplish the conversion, we build generic versions
+ * which take a void * parameter. Trivial APDU's can pass NULL or a pointer
+ * to the single parameter that they need. More complicated APDU's use
+ * CKYAppletArg* data structures defined above to pass more arguments.
+ *
+ * Generic factorys then call the standard CKYAPDUFactor_ADPUNAME() functions
+ * to build the APDUs. These functions are intended only as arguments
+ * to the generic ADPU calls, and not to be called directly.
+ *
+ *****************************************************************/
+/* param == CKYBuffer * (AID) */
+CKYStatus CKYAppletFactory_SelectFile(CKYAPDU *apdu, const void *param);
+/* param == NULL */
+CKYStatus CKYAppletFactory_SelectCardManager(CKYAPDU *apdu, const void *param);
+/* param == NULL */
+CKYStatus CKYAppletFactory_GetCPLCData(CKYAPDU *apdu, const void *param);
+/* param == CKYByte * (pointer to seq) */
+CKYStatus CKYAppletFactory_ListKeys(CKYAPDU *apdu, const void *param);
+/* param == CKYAppletArgComputeCrypt */
+CKYStatus CKYAppletFactory_ComputeCryptInit(CKYAPDU *apdu, const void *param);
+/* param == CKYAppletArgComputeCrypt */
+CKYStatus CKYAppletFactory_ComputeCryptProcess(CKYAPDU *apdu, const void *param);
+/* param == CKYAppletArgComputeCrypt */
+CKYStatus CKYAppletFactory_ComputeCryptFinal(CKYAPDU *apdu, const void *param);
+/* param == CKYAppletArgCreatePIN */
+CKYStatus CKYAppletFactory_CreatePIN(CKYAPDU *apdu, const void *param);
+/* param == CKYAppletArgVeriryPIN */
+CKYStatus CKYAppletFactory_VerifyPIN(CKYAPDU *apdu, const void *param);
+/* param == CKYAppletArgChangePIN */
+CKYStatus CKYAppletFactory_ChangePIN(CKYAPDU *apdu, const void *param);
+/* param == NULL */
+CKYStatus CKYAppletFactory_ListPINs(CKYAPDU *apdu, const void *param);
+/* param == CKYByte * (pointer to pinNumber) */
+CKYStatus CKYAppletFactory_Logout(CKYAPDU *apdu, const void *param);
+/* Future add WriteObject */
+/* parm == CKYAppletArgWriteObject */
+CKYStatus CKYAppletFactory_WriteObject(CKYAPDU *apdu, const void *param);
+/* param == CKYAppletArgCreateObject */
+CKYStatus CKYAppletFactory_CreateObject(CKYAPDU *apdu, const void *param);
+/* param == CKYAppletArgDeleteObject */
+CKYStatus CKYAppletFactory_DeleteObject(CKYAPDU *apdu, const void *param);
+/* param == CKYAppletArgReadObject */
+CKYStatus CKYAppletFactory_ReadObject(CKYAPDU *apdu, const void *param);
+/* param == CKYByte * (pointer to seq) */
+CKYStatus CKYAppletFactory_ListObjects(CKYAPDU *apdu, const void *param);
+/* param == NULL */
+CKYStatus CKYAppletFactory_GetStatus(CKYAPDU *apdu, const void *param);
+/* param == NULL */
+CKYStatus CKYAppletFactory_Noop(CKYAPDU *apdu, const void *param);
+/* param == NULL */
+CKYStatus CKYAppletFactory_GetBuildID(CKYAPDU *apdu, const void *param);
+/* param == NULL */
+CKYStatus CKYAppletFactory_GetLifeCycle(CKYAPDU *apdu, const void *param);
+/* param == NULL */
+CKYStatus CKYAppletFactory_GetLifeCycleV2(CKYAPDU *apdu, const void *param);
+/* param == CKYByte * */
+CKYStatus CKYAppletFactory_GetRandom(CKYAPDU *apdu, const void *param);
+/* param == CKY_Buffer */
+CKYStatus CKYAppletFactory_SeedRandom(CKYAPDU *apdu, const void *param);
+/* param == NULL */
+CKYStatus CKYAppletFactory_GetIssuerInfo(CKYAPDU *apdu, const void *param);
+/* param == NULL */
+CKYStatus CKYAppletFactory_GetBuiltinACL(CKYAPDU *apdu, const void *param);
+/* deprecates 0.x functions */
+/* param == NULL */
+CKYStatus CKYAppletFactory_LogoutAllV0(CKYAPDU *apdu, const void *param);
+
+/*****************************************************************
+ *
+ * Generic Fill routines used by the generic APDU processing
+ * to customize how the response data is returned to the application.
+ * generally the param points to some structure which is filled in
+ * by the Fill function from the response data. Each APDU command
+ * can potentially have it's own fill function. Different appearent
+ * functions can be accomplished by calling the same APDU with a different
+ * fill function. The fill functions below are considered globally interesting
+ * to applications that wish to make custom APDU calls using the
+ * applet generic processing. Fill functions are never called directly,
+ * but through callback, and all have the same signature (CKYFillFunction)
+ *
+ *****************************************************************/
+/* a null fill function for those APDU's which do not return data */
+CKYStatus CKYAppletFill_Null(const CKYBuffer *response, CKYSize size, void *param);
+/* Buffer Fills: */
+/* Replace fill function for those APDU's which return raw data */
+/* param == CKYBuffer * */
+CKYStatus CKYAppletFill_ReplaceBuffer(const CKYBuffer *response, CKYSize size,
+ void *param);
+/* Append fill function can be used with any APDU that uses Buffer
+ * Replace. Repeated calls continuously adds more data to the buffer.
+ * Useful for repeated operations like read. */
+/* param == CKYBuffer * */
+CKYStatus CKYAppletFill_AppendBuffer(const CKYBuffer *response,
+ CKYSize size, void *param);
+/* Single value fills: Byte, Short, & Long */
+/* param == CKYByte * */
+CKYStatus CKYAppletFill_Byte(const CKYBuffer *response, CKYSize size, void *param);
+CKYStatus CKYAppletFill_Short(const CKYBuffer *response, CKYSize size, void *param);
+CKYStatus CKYAppletFill_Long(const CKYBuffer *response, CKYSize size, void *param);
+
+/*****************************************************************
+ *
+ * Utilities shared by all the fetch Cards.
+ *
+ *****************************************************************/
+/*
+ * verify the we got a successful response. Responses should include
+ * the expected data returned plus a 2 byte return code. This return
+ * code should be 0x9000 on success. The function copies the return code
+ * to apduRC if apduRC is not NULL.
+ */
+CKYBool CKYApplet_VerifyResponse(const CKYBuffer *response, CKYSize dataSize,
+ CKYISOStatus *apduRC);
+/*
+ * most commands have identical operations. This function
+ * handles these operations, isolating the differences in
+ * call back functions.
+ * It creates the ADPU using afFunc with afArg.
+ * Adds nonce if it exists.
+ * Sends the ADPU to the card through the connection conn.
+ * Checks that the response was valid (returning the responce code in apduRC.
+ * Formats the response data into fillArg with fillFunc
+ * nonce and apduRC can be NULL (no nonce is added, no status returned
+ * legal values for afArg are depened on afFunc.
+ * legal values for fillArg are depened on fillFunc.
+ */
+CKYStatus CKYApplet_HandleAPDU(CKYCardConnection *conn,
+ CKYAppletFactory afFunc, const void *afArg,
+ const CKYBuffer *nonce, CKYSize size,
+ CKYFillFunction fillFunc, void *fillArg, CKYISOStatus *apduRC);
+
+
+/*****************************************************************
+ *
+ * The following convience functions convert APDU calls
+ * into function calls, with input and output parameters.
+ * The application is still responsible for
+ * 1) creating a connection to the card,
+ * 2) Getting a transaction lock, then
+ * 3) selecting the appropriate applet (or Card manager).
+ * Except for those calls that have been noted, the appropriate applet
+ * is the CoolKey applet.
+ *
+ *****************************************************************/
+/* Select an applet. Can happen with either applet selected */
+CKYStatus CKYApplet_SelectFile(CKYCardConnection *conn, const CKYBuffer *AID,
+ CKYISOStatus *apduRC);
+
+/* Select the CoolKey applet. Special case of the above command */
+/* Can happen with either applet selected */
+CKYStatus CKYApplet_SelectCoolKeyManager(CKYCardConnection *conn,
+ CKYISOStatus *apduRC);
+
+/* Select the card manager. Can happen with either applet selected */
+CKYStatus CKYApplet_SelectCardManager(CKYCardConnection *conn,
+ CKYISOStatus *apduRC);
+/* GetCPLC data -- must be called with CM selected */
+/* fills in cplc */
+CKYStatus CKYApplet_GetCPLCData(CKYCardConnection *conn,
+ CKYAppletRespGetCPLCData *cplc, CKYISOStatus *apduRC);
+/* Get CUID. -- must be called with CM selected */
+/* special case of GetCPLCData */
+/* fills in cuid */
+CKYStatus CKYApplet_GetCUID(CKYCardConnection *conn,
+ CKYBuffer *cuid, CKYISOStatus *apduRC);
+/* Get MSN. -- must be called with CM selected */
+/* special case of GetCPLCData */
+/* returns msn */
+CKYStatus CKYApplet_GetMSN(CKYCardConnection *conn, unsigned long *msn,
+ CKYISOStatus *apduRC);
+
+/* List Keys -- see applet documentation */
+CKYStatus CKYApplet_ListKeys(CKYCardConnection *conn, CKYByte seq,
+ CKYAppletRespListKeys *lkp, CKYISOStatus *apduRC);
+/*
+ * Compute Crypt Cluster.
+ *
+ * Compute Crypt takes 3 phases: Init, Process, Final.
+ * Applications can call each phase separately using:
+ * CKYApplet_ComputeCryptInit
+ * CKYApplet_ComputeCryptProcess
+ * CKYApplet_ComputeCryptFinal
+ * or call all three in one set with:
+ * CKYApplet_ComputeCrypt
+ * Buffer values passed to Compute crypt should be raw data.
+ * The helper functions format the 2 byte length data required by the
+ * applet automatically.
+ */
+CKYStatus CKYApplet_ComputeCryptInit(CKYCardConnection *conn, CKYByte keyNumber,
+ CKYByte mode, CKYByte direction, CKYByte location,
+ const CKYBuffer *nonce, CKYISOStatus *apduRC);
+CKYStatus CKYApplet_ComputeCryptProcess(CKYCardConnection *conn, CKYByte keyNumber,
+ CKYByte location, const CKYBuffer *data, const CKYBuffer *nonce,
+ CKYISOStatus *apduRC);
+CKYStatus CKYApplet_ComputeCryptFinal(CKYCardConnection *conn, CKYByte keyNumber,
+ CKYByte location, const CKYBuffer *data, CKYBuffer *sig, CKYBuffer *result,
+ const CKYBuffer *nonce, CKYISOStatus *apduRC);
+/** ...look to data size to see if we should read/write the data to
+ * the on card buffer. (future) */
+CKYStatus CKYApplet_ComputeCrypt(CKYCardConnection *conn, CKYByte keyNumber,
+ CKYByte mode, CKYByte direction, const CKYBuffer *data, CKYBuffer *sig,
+ CKYBuffer *result, const CKYBuffer *nonce, CKYISOStatus *apduRC);
+/* Pin Command -- see applet documentation for use */
+CKYStatus CKYApplet_CreatePIN(CKYCardConnection *conn, CKYByte pinNumber,
+ CKYByte maxAttempts, const char *pinValue,
+ const CKYBuffer *nonce, CKYISOStatus *apduRC);
+CKYStatus CKYApplet_VerifyPIN(CKYCardConnection *conn, CKYByte pinNumber,
+ const char *pinValue, CKYBuffer *nonce, CKYISOStatus *apduRC);
+CKYStatus CKYApplet_ChangePIN(CKYCardConnection *conn, const char *oldPin,
+ const char *newPin, const CKYBuffer *nonce,
+ CKYISOStatus *apduRC);
+CKYStatus CKYApplet_ListPINs(CKYCardConnection *conn, unsigned short *pins,
+ CKYISOStatus *apduRC);
+CKYStatus CKYApplet_Logout(CKYCardConnection *conn, CKYByte pinNumber,
+ const CKYBuffer *nonce, CKYISOStatus *apduRC);
+/* Object Commands -- see applet documentation for use */
+CKYStatus CKYApplet_CreateObject(CKYCardConnection *conn, unsigned long objectID,
+ CKYSize size, unsigned short readACL, unsigned short writeACL,
+ unsigned short deleteACL, const CKYBuffer *nonce, CKYISOStatus *apduRC);
+CKYStatus CKYApplet_DeleteObject(CKYCardConnection *conn, unsigned long objectID,
+ CKYByte zero, const CKYBuffer *nonce, CKYISOStatus *apduRC);
+
+/* CAC commands */
+/* Select one of the CAC PKI applets. Special case of CKYApplet_SelectFile */
+/* Select the CAC card manager. Can happen with either applet selected */
+CKYStatus CACApplet_SelectCardManager(CKYCardConnection *conn,
+ CKYISOStatus *apduRC);
+/* Select the CAC CC container. Can happen with either applet selected */
+CKYStatus CACApplet_SelectCCC(CKYCardConnection *conn, CKYISOStatus *apduRC);
+/* Select an old CAC applet and fill in the cardAID */
+CKYStatus CACApplet_SelectPKI(CKYCardConnection *conn, CKYBuffer *cardAid,
+ CKYByte instance, CKYISOStatus *apduRC);
+/* read a TLV file */
+CKYStatus CACApplet_ReadFile(CKYCardConnection *conn, CKYByte type,
+ CKYBuffer *buffer, CKYISOStatus *apduRC);
+CKYStatus CACApplet_SelectFile(CKYCardConnection *conn, unsigned short ef,
+ CKYISOStatus *apduRC);
+
+
+/* must happen with PKI applet selected */
+CKYStatus CACApplet_SignDecrypt(CKYCardConnection *conn, const CKYBuffer *data,
+ CKYBuffer *result, CKYISOStatus *apduRC);
+CKYStatus CACApplet_GetCertificate(CKYCardConnection *conn, CKYBuffer *cert,
+ CKYISOStatus *apduRC);
+CKYStatus CACApplet_GetCertificateFirst(CKYCardConnection *conn,
+ CKYBuffer *cert, CKYSize *nextSize,
+ CKYISOStatus *apduRC);
+CKYStatus CACApplet_GetCertificateAppend(CKYCardConnection *conn,
+ CKYBuffer *cert, CKYSize nextSize,
+ CKYISOStatus *apduRC);
+
+/*CKYStatus CACApplet_GetProperties(); */
+CKYStatus CACApplet_VerifyPIN(CKYCardConnection *conn, const char *pin,
+ int local, CKYISOStatus *apduRC);
+
+/* Select a PIV applet */
+CKYStatus PIVApplet_Select(CKYCardConnection *conn, CKYISOStatus *apduRC);
+
+CKYStatus PIVApplet_GetCertificate(CKYCardConnection *conn, CKYBuffer *cert,
+ int tag, CKYISOStatus *apduRC);
+CKYStatus PIVApplet_SignDecrypt(CKYCardConnection *conn, CKYByte key,
+ unsigned int keySize, int derive,
+ const CKYBuffer *data, CKYBuffer *result,
+ CKYISOStatus *apduRC);
+
+/* PKCS Commands 15 */
+CKYStatus P15Applet_SelectFile(CKYCardConnection *conn, unsigned short ef,
+ CKYISOStatus *apduRC);
+CKYStatus P15Applet_SelectRootFile(CKYCardConnection *conn, unsigned short ef,
+ CKYISOStatus *apduRC);
+CKYStatus P15Applet_ReadRecord(CKYCardConnection *conn, CKYByte record,
+ CKYByte short_ef, CKYByte flags, CKYByte size, CKYBuffer *data,
+ CKYISOStatus *apduRC);
+CKYStatus P15Applet_ReadBinary(CKYCardConnection *conn, unsigned short offset,
+ CKYByte short_ef, CKYByte flags, CKYByte size, CKYBuffer *data,
+ CKYISOStatus *apduRC);
+CKYStatus P15Applet_VerifyPIN(CKYCardConnection *conn, const char *pin,
+ const P15PinInfo *pinInfo, CKYISOStatus *apduRC);
+
+CKYStatus P15Applet_SignDecrypt(CKYCardConnection *conn, CKYByte key,
+ unsigned int keySize, CKYByte direction,
+ const CKYBuffer *data, CKYBuffer *result,
+ CKYISOStatus *apduRC);
+
+/*
+ * There are 3 read commands:
+ *
+ * CKYApplet_ReadObject issues a single Read APDU call. Supplied data buffer
+ * is overwritten. This function is limited to reading 240 bytes.
+ * CKYApplet_ReadObjectAppend also issues a single Read APDU call. However,
+ * the result is appended to the data buffer. Again, this function is limited
+ * to reading 240 bytes.
+ * CKYApplet_ReadObjectFull can read an entire data object. It makes multiple
+ * apdu calls in order to read the full amount into the buffer. The buffer
+ * is overwriten.
+ */
+CKYStatus CKYApplet_ReadObject(CKYCardConnection *conn, unsigned long objectID,
+ CKYOffset offset, CKYByte size, const CKYBuffer *nonce,
+ CKYBuffer *data, CKYISOStatus *apduRC);
+
+CKYStatus CKYApplet_ReadObjectAppend(CKYCardConnection *conn,
+ unsigned long objectID, CKYOffset offset, CKYByte size,
+ const CKYBuffer *nonce, CKYBuffer *data, CKYISOStatus *apduRC);
+CKYStatus CKYApplet_ReadObjectFull(CKYCardConnection *conn,
+ unsigned long objectID, CKYOffset offset, CKYSize size,
+ const CKYBuffer *nonce, CKYBuffer *data, CKYISOStatus *apduRC);
+/*
+ * There is 1 write command:
+ * CKYApplet_WriteObjectFull can write an entire data object. It makes multiple
+ * apdu calls in order to write the full amount into the buffer. The buffer is
+ * overwritten.
+*/
+
+CKYStatus CKYApplet_WriteObjectFull(CKYCardConnection *conn,
+ unsigned long objectID, CKYOffset offset, CKYSize size,
+ const CKYBuffer *nonce, const CKYBuffer *data, CKYISOStatus *apduRC);
+
+CKYStatus CKYApplet_ListObjects(CKYCardConnection *conn, CKYByte seq,
+ CKYAppletRespListObjects *lop, CKYISOStatus *apduRC);
+CKYStatus CKYApplet_GetStatus(CKYCardConnection *conn,
+ CKYAppletRespGetStatus *status, CKYISOStatus *apduRC);
+CKYStatus CKYApplet_Noop(CKYCardConnection *conn, CKYISOStatus *apduRC);
+CKYStatus CKYApplet_GetBuildID(CKYCardConnection *conn, unsigned long *buildID,
+ CKYISOStatus *apduRC);
+CKYStatus CKYApplet_GetLifeCycle(CKYCardConnection *conn, CKYByte *personalized,
+ CKYISOStatus *apduRC);
+CKYStatus CKYApplet_GetLifeCycleV2(CKYCardConnection *conn,
+ CKYAppletRespGetLifeCycleV2 *ext, CKYISOStatus *apduRC);
+
+CKYStatus CKYApplet_GetRandom(CKYCardConnection *conn,
+ CKYBuffer *buf, CKYByte len, CKYISOStatus *apduRC);
+
+CKYStatus CKYApplet_GetRandomAppend(CKYCardConnection *conn,
+ CKYBuffer *buf, CKYByte len, CKYISOStatus *apduRC);
+
+CKYStatus CKYApplet_SeedRandom(CKYCardConnection *conn,
+ const CKYBuffer *buf, CKYISOStatus *apduRC);
+
+CKYStatus CKYApplet_GetIssuerInfo(CKYCardConnection *conn,
+ CKYBuffer *buf, CKYISOStatus *apduRC);
+
+CKYStatus CKYApplet_GetBuiltinACL(CKYCardConnection *conn,
+ CKYAppletRespGetBuiltinACL *gba, CKYISOStatus *apduRC);
+
+/** ECC commands
+ * * */
+
+CKYStatus CKYApplet_ComputeECCSignature(CKYCardConnection *conn, CKYByte keyNumber,
+ const CKYBuffer *data, CKYBuffer *sig,
+ CKYBuffer *result, const CKYBuffer *nonce, CKYISOStatus *apduRC);
+
+CKYStatus
+CKYApplet_ComputeECCKeyAgreement(CKYCardConnection *conn, CKYByte keyNumber,
+ const CKYBuffer *publicValue, CKYBuffer *sharedSecret,
+ CKYBuffer *result, const CKYBuffer *nonce, CKYISOStatus *apduRC);
+
+
+/*
+ * deprecates 0.x functions
+ */
+/* old applet verify pin call (no nonce returned) */
+CKYStatus CKYApplet_VerifyPinV0(CKYCardConnection *conn, CKYByte pinNumber,
+ const char *pinValue, CKYISOStatus *apduRC);
+/* logout all */
+CKYStatus CKYApplet_LogoutAllV0(CKYCardConnection *conn, CKYISOStatus *apduRC);
+
+CKY_END_PROTOS
+#endif /* CKY_APPLET_H */
diff -up ./esc/src/lib/coolkey/cky_base.c.fix1 ./esc/src/lib/coolkey/cky_base.c
--- ./esc/src/lib/coolkey/cky_base.c.fix1 2018-04-26 11:44:38.436986198 -0700
+++ ./esc/src/lib/coolkey/cky_base.c 2018-04-26 11:44:38.436986198 -0700
@@ -0,0 +1,835 @@
+/* ***** BEGIN COPYRIGHT BLOCK *****
+ * Copyright (C) 2005 Red Hat, Inc.
+ * All rights reserved.
+ *
+ * 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 St, Fifth Floor, Boston, MA 02110-1301 USA
+ * ***** END COPYRIGHT BLOCK ***** */
+
+#include
+#include
+#include
+#include "cky_basei.h"
+#include "cky_base.h"
+
+/*
+ * generic buffer management functions
+ *
+ * These functions allow simple buffer management used in the CoolKey
+ * library and it's clients.
+ */
+
+/* initialize a new buffer to a known state */
+static void
+ckyBuffer_initBuffer(CKYBuffer *buf)
+{
+#ifdef DEBUG
+ assert(sizeof(CKYBuffer) == sizeof(CKYBufferPublic));
+#endif
+ buf->data = NULL;
+ buf->size = 0;
+ buf->len = 0;
+ buf->reserved = NULL; /* make coverity happy */
+}
+
+/*
+ * Init functions clobbers the current contents and allocates the required
+ * space. Active buffers should call CKYBuffer_FreerData before
+ * calling an init function. All init functions copies the supplied data
+ * into newly allocated space.
+ */
+/* init an empty buffer that will later be filled in. */
+CKYStatus
+CKYBuffer_InitEmpty(CKYBuffer *buf)
+{
+ ckyBuffer_initBuffer(buf);
+ return CKYSUCCESS;
+}
+
+/* Create a buffer of length len all initialized to '0' */
+CKYStatus
+CKYBuffer_InitFromLen(CKYBuffer *buf, CKYSize len)
+{
+ CKYStatus ret;
+
+ ckyBuffer_initBuffer(buf);
+ ret = CKYBuffer_Reserve(buf, len);
+ if (ret != CKYSUCCESS) {
+ return ret;
+ }
+ buf->len = len;
+ memset(buf->data, 0, buf->len);
+ return CKYSUCCESS;
+}
+
+static CKYByte
+fromHex(const char *cp)
+{
+ if (*cp >= '0' && *cp <= '9') {
+ return (CKYByte) *cp - '0';
+ }
+ if (*cp >= 'a' && *cp <= 'f') {
+ return (CKYByte) *cp - 'a' + 0xa;
+ }
+ if (*cp >= 'A' && *cp <= 'F') {
+ return (CKYByte) *cp - 'A' + 0xA;
+ }
+ return 0;
+}
+
+/* Create a buffer by decoding a hex string. hexString is NULL terminated. */
+CKYStatus
+CKYBuffer_InitFromHex(CKYBuffer *buf, const char *hexString)
+{
+ int len = strlen(hexString);
+ int dataHalf = 0;
+ CKYByte lastDigit = 0;
+ CKYByte digit;
+ const char *cp;
+ CKYByte *bp;
+ CKYStatus ret;
+
+ if (len & 1) {
+ len++;
+ dataHalf++;
+ }
+ ckyBuffer_initBuffer(buf);
+ ret = CKYBuffer_Reserve(buf, len/2);
+ if (ret != CKYSUCCESS) {
+ return ret;
+ }
+ buf->len = len/2;
+ bp = buf->data;
+ for (cp = hexString; *cp; cp++) {
+ digit = fromHex(cp);
+ /* check for error? */
+ if (dataHalf) {
+ *bp++= lastDigit << 4 | digit;
+ }
+ dataHalf ^= 1;
+ lastDigit = digit;
+ }
+ return CKYSUCCESS;
+}
+
+/* Create a buffer from data */
+CKYStatus
+CKYBuffer_InitFromData(CKYBuffer *buf, const CKYByte *data, CKYSize len)
+{
+ CKYStatus ret;
+
+ ckyBuffer_initBuffer(buf);
+ ret = CKYBuffer_Reserve(buf, len);
+ if (ret != CKYSUCCESS) {
+ return ret;
+ }
+ buf->len = len;
+ memcpy(buf->data, data, buf->len);
+ return CKYSUCCESS;
+}
+
+
+/* Create a buffer from part of another buffer. Start indicates the
+ * offset in the old buffer to start in, and len specifies how many bytes
+ * to copy */
+CKYStatus
+CKYBuffer_InitFromBuffer(CKYBuffer *buf,
+ const CKYBuffer *src, CKYOffset start, CKYSize len)
+{
+ CKYStatus ret;
+
+ ckyBuffer_initBuffer(buf);
+ if (src->len < start) {
+ len = 0;
+ } else if (src->len < start+len) {
+ len = src->len -start;
+ }
+ ret = CKYBuffer_Reserve(buf, len);
+ if (ret != CKYSUCCESS) {
+ return ret;
+ }
+ buf->len = len;
+ if (len == 0) {
+ return CKYSUCCESS;
+ }
+ memcpy(buf->data, src->data+start, buf->len);
+ return CKYSUCCESS;
+}
+
+/* Create a buffer from and exact copy of another buffer. */
+CKYStatus
+CKYBuffer_InitFromCopy(CKYBuffer *buf, const CKYBuffer *src)
+{
+ CKYStatus ret;
+
+ ckyBuffer_initBuffer(buf);
+ /* src buffer has no length, make sure the dest is empty */
+ if (src->len == 0) {
+ return CKYSUCCESS;
+ }
+ ret = CKYBuffer_Reserve(buf, src->len);
+ if (ret != CKYSUCCESS) {
+ return ret;
+ }
+ buf->len = src->len;
+ memcpy(buf->data, src->data, buf->len);
+ return CKYSUCCESS;
+}
+
+/*
+ * append functions increase the buffer size if necessary
+ */
+CKYStatus
+CKYBuffer_AppendChar(CKYBuffer *buf, CKYByte val)
+{
+ CKYStatus ret;
+
+ ret = CKYBuffer_Reserve(buf, buf->len + 1);
+ if (ret != CKYSUCCESS) {
+ return ret;
+ }
+ buf->data[buf->len] = val;
+ buf->len += 1;
+ return CKYSUCCESS;
+}
+
+/* append a short in network order */
+CKYStatus
+CKYBuffer_AppendShort(CKYBuffer *buf, unsigned short val)
+{
+ CKYStatus ret;
+
+ ret = CKYBuffer_Reserve(buf, buf->len + 2);
+ if (ret != CKYSUCCESS) {
+ return ret;
+ }
+ buf->data[buf->len+0] = (CKYByte) ((val >> 8) & 0xff);
+ buf->data[buf->len+1] = (CKYByte) ((val >> 0) & 0xff);
+ buf->len += 2;
+ return CKYSUCCESS;
+}
+
+/* append a short in network order */
+CKYStatus
+CKYBuffer_AppendShortLE(CKYBuffer *buf, unsigned short val)
+{
+ CKYStatus ret;
+
+ ret = CKYBuffer_Reserve(buf, buf->len + 2);
+ if (ret != CKYSUCCESS) {
+ return ret;
+ }
+ buf->data[buf->len+1] = (CKYByte) ((val >> 8) & 0xff);
+ buf->data[buf->len+0] = (CKYByte) ((val >> 0) & 0xff);
+ buf->len += 2;
+ return CKYSUCCESS;
+}
+
+/* append a long in applet order */
+CKYStatus
+CKYBuffer_AppendLong(CKYBuffer *buf, unsigned long val)
+{
+ CKYStatus ret;
+
+ ret = CKYBuffer_Reserve(buf, buf->len + 4);
+ if (ret != CKYSUCCESS) {
+ return ret;
+ }
+ buf->data[buf->len+0] = (CKYByte) ((val >> 24) & 0xff);
+ buf->data[buf->len+1] = (CKYByte) ((val >> 16) & 0xff);
+ buf->data[buf->len+2] = (CKYByte) ((val >> 8) & 0xff);
+ buf->data[buf->len+3] = (CKYByte) ((val >> 0) & 0xff);
+ buf->len += 4;
+ return CKYSUCCESS;
+}
+
+/* append a long in applet order */
+CKYStatus
+CKYBuffer_AppendLongLE(CKYBuffer *buf, unsigned long val)
+{
+ CKYStatus ret;
+
+ ret = CKYBuffer_Reserve(buf, buf->len + 4);
+ if (ret != CKYSUCCESS) {
+ return ret;
+ }
+ buf->data[buf->len+3] = (CKYByte) ((val >> 24) & 0xff);
+ buf->data[buf->len+2] = (CKYByte) ((val >> 16) & 0xff);
+ buf->data[buf->len+1] = (CKYByte) ((val >> 8) & 0xff);
+ buf->data[buf->len+0] = (CKYByte) ((val >> 0) & 0xff);
+ buf->len += 4;
+ return CKYSUCCESS;
+}
+
+CKYStatus
+CKYBuffer_Replace(CKYBuffer *buf, CKYOffset offset, const CKYByte *data, CKYSize len)
+{
+ CKYStatus ret;
+
+ ret = CKYBuffer_Reserve(buf, offset+len);
+ if (ret != CKYSUCCESS) {
+ return ret;
+ }
+ if (buf->len < offset + len) {
+ buf->len = offset + len;
+ }
+ memcpy(buf->data+offset, data, len);
+ return CKYSUCCESS;
+}
+
+/* append data with length of len bytes */
+CKYStatus
+CKYBuffer_AppendData(CKYBuffer *buf, const CKYByte *data, CKYSize len)
+{
+ CKYStatus ret;
+
+ ret = CKYBuffer_Reserve(buf, buf->len + len);
+ if (ret != CKYSUCCESS) {
+ return ret;
+ }
+ memcpy(buf->data+buf->len, data, len);
+ buf->len += len;
+ return CKYSUCCESS;
+}
+
+/* append data with length of len bytes */
+CKYStatus
+CKYBuffer_AppendBuffer(CKYBuffer *buf, const CKYBuffer *src,
+ CKYOffset offset, CKYSize len)
+{
+ unsigned long maxlen = src->len - offset;
+ if ((maxlen < len) || (src->len < offset)) {
+ return CKYDATATOOLONG;
+ }
+ return CKYBuffer_AppendData(buf, src->data+offset, len);
+}
+
+/* append data with length of len bytes */
+CKYStatus
+CKYBuffer_AppendCopy(CKYBuffer *buf, const CKYBuffer *src)
+{
+ return CKYBuffer_AppendData(buf, src->data, src->len);
+}
+
+CKYStatus
+CKYBuffer_Reserve(CKYBuffer *buf, CKYSize newSize)
+{
+ if (buf->size >= newSize) {
+ return CKYSUCCESS;
+ }
+ buf->data = (CKYByte *)realloc(buf->data, newSize);
+ if (buf->data == NULL) {
+ buf->size = 0;
+ buf->len = 0;
+ return CKYNOMEM;
+ }
+ buf->size = newSize;
+ return CKYSUCCESS;
+}
+
+CKYStatus
+CKYBuffer_SetChar(CKYBuffer *buf, CKYOffset offset, CKYByte val)
+{
+ CKYStatus ret;
+
+ if (buf->len < offset+1) {
+ ret = CKYBuffer_Resize(buf,offset+1);
+ if (ret != CKYSUCCESS) {
+ return ret;
+ }
+ }
+ buf->data[offset] = val;
+ return CKYSUCCESS;
+}
+
+CKYStatus
+CKYBuffer_SetChars(CKYBuffer *buf, CKYOffset offset, CKYByte val, CKYSize len)
+{
+ CKYStatus ret;
+
+ if (buf->len < offset+len) {
+ ret = CKYBuffer_Resize(buf,offset+len);
+ if (ret != CKYSUCCESS) {
+ return ret;
+ }
+ }
+ memset(buf->data+offset,val, len);
+ return CKYSUCCESS;
+}
+
+CKYStatus
+CKYBuffer_SetShort(CKYBuffer *buf, CKYOffset offset, unsigned short val)
+{
+ CKYStatus ret;
+
+ if (buf->len < offset+2) {
+ ret = CKYBuffer_Resize(buf,offset+2);
+ if (ret != CKYSUCCESS) {
+ return ret;
+ }
+ }
+ buf->data[offset+0] = (CKYByte) ((val >> 8) & 0xff);
+ buf->data[offset+1] = (CKYByte) ((val >> 0) & 0xff);
+ return CKYSUCCESS;
+}
+
+CKYStatus
+CKYBuffer_SetShortLE(CKYBuffer *buf, CKYOffset offset, unsigned short val)
+{
+ CKYStatus ret;
+
+ if (buf->len < offset+2) {
+ ret = CKYBuffer_Resize(buf,offset+2);
+ if (ret != CKYSUCCESS) {
+ return ret;
+ }
+ }
+ buf->data[offset+1] = (CKYByte) ((val >> 8) & 0xff);
+ buf->data[offset+0] = (CKYByte) ((val >> 0) & 0xff);
+ return CKYSUCCESS;
+}
+
+CKYStatus
+CKYBuffer_SetLong(CKYBuffer *buf, CKYOffset offset, unsigned long val)
+{
+ CKYStatus ret;
+
+ if (buf->len < offset+4) {
+ ret = CKYBuffer_Resize(buf,offset+4);
+ if (ret != CKYSUCCESS) {
+ return ret;
+ }
+ }
+ buf->data[offset+0] = (CKYByte) ((val >> 24) & 0xff);
+ buf->data[offset+1] = (CKYByte) ((val >> 16) & 0xff);
+ buf->data[offset+2] = (CKYByte) ((val >> 8) & 0xff);
+ buf->data[offset+3] = (CKYByte) ((val >> 0) & 0xff);
+ return CKYSUCCESS;
+}
+
+CKYStatus
+CKYBuffer_SetLongLE(CKYBuffer *buf, CKYOffset offset, unsigned long val)
+{
+ CKYStatus ret;
+
+ if (buf->len < offset+4) {
+ ret = CKYBuffer_Resize(buf,offset+4);
+ if (ret != CKYSUCCESS) {
+ return ret;
+ }
+ }
+ buf->data[offset+3] = (CKYByte) ((val >> 24) & 0xff);
+ buf->data[offset+2] = (CKYByte) ((val >> 16) & 0xff);
+ buf->data[offset+1] = (CKYByte) ((val >> 8) & 0xff);
+ buf->data[offset+0] = (CKYByte) ((val >> 0) & 0xff);
+ return CKYSUCCESS;
+}
+
+CKYByte
+CKYBuffer_GetChar(const CKYBuffer *buf, CKYOffset offset)
+{
+ if (buf->len < offset+1) {
+ return 0;
+ }
+ return buf->data[offset];
+}
+
+unsigned short
+CKYBuffer_GetShort(const CKYBuffer *buf, CKYOffset offset)
+{
+ unsigned short val;
+ if (buf->len < offset+2) {
+ return 0;
+ }
+ val = ((unsigned short)buf->data[offset+0]) << 8;
+ val |= ((unsigned short)buf->data[offset+1]) << 0;
+ return val;
+}
+
+unsigned short
+CKYBuffer_GetShortLE(const CKYBuffer *buf, CKYOffset offset)
+{
+ unsigned short val;
+ if (buf->len < offset+2) {
+ return 0;
+ }
+ val = ((unsigned short)buf->data[offset+1]) << 8;
+ val |= ((unsigned short)buf->data[offset+0]) << 0;
+ return val;
+}
+
+unsigned long
+CKYBuffer_GetLong(const CKYBuffer *buf, CKYOffset offset)
+{
+ unsigned long val;
+ if (buf->len < offset+4) {
+ return 0;
+ }
+ val = ((unsigned long)buf->data[offset+0]) << 24;
+ val |= ((unsigned long)buf->data[offset+1]) << 16;
+ val |= ((unsigned long)buf->data[offset+2]) << 8;
+ val |= ((unsigned long)buf->data[offset+3]) << 0;
+ return val;
+}
+
+unsigned long
+CKYBuffer_GetLongLE(const CKYBuffer *buf, CKYOffset offset)
+{
+ unsigned long val;
+ if (buf->len < offset+4) {
+ return 0;
+ }
+ val = ((unsigned long)buf->data[offset+3]) << 24;
+ val |= ((unsigned long)buf->data[offset+2]) << 16;
+ val |= ((unsigned long)buf->data[offset+1]) << 8;
+ val |= ((unsigned long)buf->data[offset+0]) << 0;
+ return val;
+}
+
+CKYStatus
+CKYBuffer_Resize(CKYBuffer *buf, CKYSize newLen)
+{
+ CKYStatus ret;
+
+ if (buf->len < newLen) {
+ ret = CKYBuffer_Reserve(buf, newLen);
+ if (ret != CKYSUCCESS) {
+ return ret;
+ }
+ memset(buf->data+buf->len, 0, newLen - buf->len);
+ }
+ buf->len = newLen;
+ return CKYSUCCESS;
+}
+
+/* clear out a memory buffer... including unallocated space, then
+ * set the buffer length to '0' */
+void
+CKYBuffer_Zero(CKYBuffer *buf)
+{
+ if (buf->size != 0) {
+ memset(buf->data, 0, buf->size);
+ }
+ buf->len = 0;;
+}
+
+CKYSize
+CKYBuffer_Size(const CKYBuffer *buf)
+{
+ return buf->len;
+}
+
+const CKYByte *
+CKYBuffer_Data(const CKYBuffer *buf)
+{
+ return buf->data;
+}
+
+CKYBool
+CKYBuffer_DataIsEqual(const CKYBuffer *buf1, const CKYByte *buf2, CKYSize buf2Len)
+{
+ if (buf1->len != buf2Len) {
+ return 0;
+ }
+
+ /* all zero length buffers are equal, whether or not they have pointers
+ * allocated */
+ if (buf1->len == 0) {
+ return 1;
+ }
+
+ return memcmp(buf1->data, buf2, buf1->len) == 0;
+}
+
+CKYBool
+CKYBuffer_IsEqual(const CKYBuffer *buf1, const CKYBuffer *buf2)
+{
+ return CKYBuffer_DataIsEqual(buf1, buf2->data, buf2->len);
+}
+
+CKYStatus
+CKYBuffer_FreeData(CKYBuffer *buf)
+{
+ free(buf->data);
+ ckyBuffer_initBuffer(buf);
+ return CKYSUCCESS;
+}
+
+CKYStatus
+CKYAPDU_Init(CKYAPDU *apdu)
+{
+#ifdef DEBUG
+ assert(sizeof(CKYAPDU) == sizeof(CKYAPDUPublic));
+#endif
+ ckyBuffer_initBuffer(&apdu->apduBuf);
+ apdu->reserved = NULL;
+ return CKYBuffer_Resize(&apdu->apduBuf, CKYAPDU_MIN_LEN);
+}
+
+CKYStatus
+CKYAPDU_InitFromData(CKYAPDU *apdu, const CKYByte *data, CKYSize len)
+{
+#ifdef DEBUG
+ assert(sizeof(CKYAPDU) == sizeof(CKYAPDUPublic));
+#endif
+ ckyBuffer_initBuffer(&apdu->apduBuf);
+ apdu->reserved = NULL;
+ if (len > CKYAPDU_MAX_DATA_LEN) {
+ return CKYDATATOOLONG;
+ }
+ return CKYBuffer_InitFromData(&apdu->apduBuf, data, len);
+}
+
+CKYStatus
+CKYAPDU_FreeData(CKYAPDU *apdu)
+{
+ return CKYBuffer_FreeData(&apdu->apduBuf);
+}
+
+
+CKYByte
+CKYAPDU_GetCLA(const CKYAPDU *apdu)
+{
+ return CKYBuffer_GetChar(&apdu->apduBuf, CKY_CLA_OFFSET);
+}
+
+CKYStatus
+CKYAPDU_SetCLA(CKYAPDU *apdu, CKYByte b)
+{
+ return CKYBuffer_SetChar(&apdu->apduBuf, CKY_CLA_OFFSET, b);
+}
+
+CKYByte
+CKYAPDU_GetINS(const CKYAPDU *apdu)
+{
+ return CKYBuffer_GetChar(&apdu->apduBuf, CKY_INS_OFFSET);
+}
+
+CKYStatus
+CKYAPDU_SetINS(CKYAPDU *apdu, CKYByte b)
+{
+ return CKYBuffer_SetChar(&apdu->apduBuf, CKY_INS_OFFSET, b);
+}
+
+CKYByte
+CKYAPDU_GetP1(const CKYAPDU *apdu)
+{
+ return CKYBuffer_GetChar(&apdu->apduBuf, CKY_P1_OFFSET);
+}
+
+CKYStatus
+CKYAPDU_SetP1(CKYAPDU *apdu, CKYByte b)
+{
+ return CKYBuffer_SetChar(&apdu->apduBuf, CKY_P1_OFFSET, b);
+}
+
+CKYByte
+CKYAPDU_GetP2(const CKYAPDU *apdu)
+{
+ return CKYBuffer_GetChar(&apdu->apduBuf, CKY_P2_OFFSET);
+}
+
+CKYStatus
+CKYAPDU_SetP2(CKYAPDU *apdu, CKYByte b)
+{
+ return CKYBuffer_SetChar(&apdu->apduBuf, CKY_P2_OFFSET, b);
+}
+
+CKYStatus
+CKYAPDU_SetSendData(CKYAPDU *apdu, const CKYByte *data, CKYSize len)
+{
+ CKYStatus ret;
+ CKYOffset offset = 0;
+
+ /* Encode with T1 if necessary */
+
+ if (len < CKYAPDU_MAX_DATA_LEN) {
+ offset = 0;
+ ret = CKYBuffer_Resize(&apdu->apduBuf, len+offset+CKYAPDU_HEADER_LEN);
+ if (ret != CKYSUCCESS ) {
+ return ret;
+ }
+ ret = CKYBuffer_SetChar(&apdu->apduBuf, CKY_LC_OFFSET, (CKYByte) len);
+ } else if (len < CKYAPDU_MAX_T1_DATA_LEN) {
+ offset = 2;
+ ret = CKYBuffer_Resize(&apdu->apduBuf, len+offset+CKYAPDU_HEADER_LEN);
+ if (ret != CKYSUCCESS ) {
+ return ret;
+ }
+ ret = CKYBuffer_SetChar(&apdu->apduBuf, CKY_LC_OFFSET, (CKYByte) 0);
+ if (ret != CKYSUCCESS) {
+ return ret;
+ }
+ ret = CKYBuffer_SetShort(&apdu->apduBuf,CKY_LC_OFFSET+1,
+ (unsigned short)len);
+ } else {
+ return CKYDATATOOLONG;
+ }
+
+ if (ret != CKYSUCCESS) {
+ return ret;
+ }
+ return CKYBuffer_Replace(&apdu->apduBuf,
+ CKYAPDU_HEADER_LEN + offset , data, len);
+}
+
+CKYStatus
+CKYAPDU_SetSendDataBuffer(CKYAPDU *apdu, const CKYBuffer *buf)
+{
+ return CKYAPDU_SetSendData(apdu, buf->data, buf->len);
+}
+
+CKYStatus
+CKYAPDU_AppendSendData(CKYAPDU *apdu, const CKYByte *data, CKYSize len)
+{
+ CKYStatus ret;
+ CKYSize dataLen;
+
+ if (CKYBuffer_Size(&apdu->apduBuf) <= CKYAPDU_MIN_LEN) {
+ return CKYAPDU_SetSendData(apdu,data, len);
+ }
+
+ dataLen = CKYBuffer_Size(&apdu->apduBuf) + len - CKYAPDU_HEADER_LEN;
+ /* only handles T0 encoding, not T1 encoding */
+ if (dataLen >= CKYAPDU_MAX_DATA_LEN) {
+ return CKYDATATOOLONG;
+ }
+ ret = CKYBuffer_AppendData(&apdu->apduBuf, data, len);
+ if (ret != CKYSUCCESS) {
+ return ret;
+ }
+ return CKYBuffer_SetChar(&apdu->apduBuf, CKY_LC_OFFSET, (CKYByte) dataLen);
+}
+
+CKYStatus
+CKYAPDU_AppendSendDataBuffer(CKYAPDU *apdu, const CKYBuffer *buf)
+{
+ return CKYAPDU_AppendSendData(apdu, buf->data, buf->len);
+}
+
+CKYStatus
+CKYAPDU_SetReceiveLen(CKYAPDU *apdu, CKYByte recvlen)
+{
+ CKYStatus ret;
+ ret = CKYBuffer_Resize(&apdu->apduBuf, CKYAPDU_HEADER_LEN);
+ if (ret != CKYSUCCESS) {
+ return ret;
+ }
+ return CKYBuffer_SetChar(&apdu->apduBuf, CKY_LE_OFFSET, recvlen);
+}
+
+CKYStatus
+CKYAPDU_SetShortReceiveLen(CKYAPDU *apdu, unsigned short recvlen)
+{
+ CKYStatus ret;
+
+ if (recvlen <= CKYAPDU_MAX_DATA_LEN) {
+ return CKYAPDU_SetReceiveLen(apdu, (CKYByte)(recvlen & 0xff));
+ }
+ ret = CKYBuffer_Resize(&apdu->apduBuf, CKYAPDU_HEADER_LEN+2);
+ if (ret != CKYSUCCESS) {
+ return ret;
+ }
+ ret = CKYBuffer_SetChar(&apdu->apduBuf, CKY_LE_OFFSET, 0);
+ if (ret != CKYSUCCESS) {
+ return ret;
+ }
+ return CKYBuffer_SetShort(&apdu->apduBuf, CKY_LE_OFFSET+1, recvlen);
+}
+
+CKYStatus
+CKYAPDU_SetReceiveLength(CKYAPDU *apdu, CKYSize recvlen)
+{
+ if (recvlen <= CKYAPDU_MAX_T1_DATA_LEN) {
+ return CKYAPDU_SetShortReceiveLen(apdu, (unsigned short)
+ (recvlen & 0xffff));
+ }
+ return CKYDATATOOLONG;
+}
+
+/*
+ * Append Le, If Le=0, treat it as 256 (CKYAPD_MAX_DATA_LEN)
+ */
+CKYStatus
+CKYAPDU_AppendReceiveLen(CKYAPDU *apdu, CKYByte recvlen)
+{
+ /* If we already have a data buffer, make sure that we aren't already
+ * using T1 encoding */
+ if (CKYBuffer_Size(&apdu->apduBuf) > CKYAPDU_MIN_LEN) {
+ if (CKYBuffer_GetChar(&apdu->apduBuf, CKY_LC_OFFSET) == 0) {
+ /* we are using T1 encoding, use AppendShort*/
+ return CKYBuffer_AppendShort(&apdu->apduBuf,
+ recvlen ? (unsigned short) recvlen: CKYAPDU_MAX_DATA_LEN);
+ }
+ }
+ return CKYBuffer_AppendChar(&apdu->apduBuf, recvlen);
+}
+
+/*
+ * Append a short Le. If Le be encoded with just T0, do so. If Le=0 treat
+ * it as 65536 (CKYAPDU_MAX_T1_DATA_LEN)
+ */
+CKYStatus
+CKYAPDU_AppendShortReceiveLen(CKYAPDU *apdu, unsigned short recvlen)
+{
+ CKYStatus ret;
+ /* If we already have a data buffer, it's encoding affects ours */
+ if (CKYBuffer_Size(&apdu->apduBuf) > CKYAPDU_MIN_LEN) {
+ /* CKY_LC_OFFSET == 0 means T1, otherwise it's T0 */
+ if (CKYBuffer_GetChar(&apdu->apduBuf, CKY_LC_OFFSET) != 0) {
+ /* remember 0 is 65536 here */
+ if ((recvlen == 0) || (recvlen > CKYAPDU_MAX_DATA_LEN)) {
+ /* we can't a encode T1 receive length if we already have a
+ * T0 encoded buffer data */
+ return CKYDATATOOLONG;
+ }
+ /* T0 encoding */
+ return CKYBuffer_AppendChar(&apdu->apduBuf, (CKYByte)recvlen&0xff);
+ }
+ /* T1 encoding */
+ return CKYBuffer_AppendShort(&apdu->apduBuf, recvlen);
+ }
+ /* if length fits in a bit and we aren't forced into T1 encoding, use
+ * T0 */
+ if ((recvlen != 0) && (recvlen <= CKYAPDU_MAX_DATA_LEN)) {
+ return CKYBuffer_AppendChar(&apdu->apduBuf, (CKYByte)recvlen&0xff);
+ }
+ /* write the T1 encoding marker */
+ ret = CKYBuffer_AppendChar(&apdu->apduBuf, (CKYByte)0);
+ if (ret != CKYSUCCESS) {
+ return ret;
+ }
+ /* T1 encoded length */
+ return CKYBuffer_AppendShort(&apdu->apduBuf, recvlen);
+}
+
+CKYStatus
+CKYAPDU_AppendReceiveLength(CKYAPDU *apdu, CKYSize recvlen)
+{
+ if (recvlen > CKYAPDU_MAX_T1_DATA_LEN) {
+ return CKYDATATOOLONG;
+ }
+ return CKYAPDU_AppendShortReceiveLen(apdu,
+ (unsigned short)(recvlen & 0xffff));
+}
+
+
+void
+CKY_SetName(const char *p)
+{
+}
+
+
+
+
diff -up ./esc/src/lib/coolkey/cky_base.h.fix1 ./esc/src/lib/coolkey/cky_base.h
--- ./esc/src/lib/coolkey/cky_base.h.fix1 2018-04-26 11:44:38.437986192 -0700
+++ ./esc/src/lib/coolkey/cky_base.h 2018-04-26 11:44:38.437986192 -0700
@@ -0,0 +1,340 @@
+/* ***** BEGIN COPYRIGHT BLOCK *****
+ * Copyright (C) 2005 Red Hat, Inc.
+ * All rights reserved.
+ *
+ * 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 St, Fifth Floor, Boston, MA 02110-1301 USA
+ * ***** END COPYRIGHT BLOCK ***** */
+
+#ifndef CKY_BASE_H
+#define CKY_BASE_H 1
+
+/*
+ * Common types and structs
+ */
+/* buffer sizes */
+typedef unsigned long CKYSize;
+/* offsets into buffers are data */
+typedef unsigned long CKYOffset;
+/* bytes, buffers */
+typedef unsigned char CKYByte;
+/* Bool type */
+typedef unsigned char CKYBool;
+
+typedef unsigned long CKYBitFlags;
+
+#define CKYBUFFER_PUBLIC \
+ unsigned long reserved1;\
+ unsigned long reserved2;\
+ void *reserved3;\
+ void *reserved4;
+
+#define CKYAPDU_PUBLIC \
+ unsigned long reserved1;\
+ unsigned long reserved2;\
+ void *reserved3;\
+ void *reserved4; \
+ void *reserved5;
+
+
+typedef struct _CKYBuffer {
+#ifdef CKYBUFFER_PRIVATE
+ CKYBUFFER_PRIVATE
+#else
+ CKYBUFFER_PUBLIC
+#endif
+} CKYBuffer;
+
+typedef struct _CKYAPDU {
+#ifdef CKYAPDU_PRIVATE
+ CKYAPDU_PRIVATE
+#else
+ CKYAPDU_PUBLIC
+#endif
+} CKYAPDU;
+
+/*
+ * the following is just to make sure the sizes match
+ */
+#ifdef DEBUG
+#ifdef CKYBUFFER_PRIVATE
+typedef struct _CKYBufferPublic {
+ CKYBUFFER_PUBLIC
+} CKYBufferPublic;
+
+typedef struct _CKYAPDUPublic {
+ CKYAPDU_PUBLIC
+} CKYAPDUPublic;
+#endif
+#endif
+
+typedef enum {
+ CKYSUCCESS, /* operation completed successfully */
+ CKYNOMEM, /* failed to allocate memory */
+ CKYDATATOOLONG, /* index or length exceeded a buffer or device size */
+ CKYNOSCARD, /* Scard library does not exist */
+ CKYSCARDERR, /* I/O Error in the SCard interface level. */
+ /* more specific error values can be queried from
+ * the context or connection with the
+ * GetLastError() call */
+ CKYLIBFAIL, /* error is shared library. no additional
+ * error is available. Only returned from internal
+ * SHlib calls (not surfaced in public APIs */
+ CKYAPDUFAIL, /* processing worked, but applet rejected the APDU
+ * (command) sent. ADPUIOStatus has more info on
+ * why the APDU failed */
+ CKYINVALIDARGS, /* Caller passed in bad args */
+ CKYINVALIDDATA, /* Data supplied was invalid */
+ CKYUNSUPPORTED, /* Requested Operation or feature is not supported */
+} CKYStatus;
+
+/*
+ * defines related to APDU's
+ */
+#define CKY_CLA_OFFSET 0
+#define CKY_INS_OFFSET 1
+#define CKY_P1_OFFSET 2
+#define CKY_P2_OFFSET 3
+#define CKY_P3_OFFSET 4 /* P3 is P3, LC, and LE depending on usage */
+#define CKY_LC_OFFSET 4
+#define CKY_LE_OFFSET 4
+
+#define CKYAPDU_MAX_DATA_LEN 256
+#define CKYAPDU_MAX_T1_DATA_LEN 65536
+#define CKYAPDU_MIN_LEN 4
+#define CKYAPDU_HEADER_LEN 5
+#define CKYAPDU_MAX_LEN (CKYAPDU_HEADER_LEN+CKYAPDU_MAX_DATA_LEN)
+#define CKY_MAX_ATR_LEN 32
+#define CKY_OUTRAGEOUS_MALLOC_SIZE (1024*1024)
+
+#define P15FlagsPrivate 0x00000001
+#define P15FlagsModifiable 0x00000002
+
+#define P15UsageEncrypt 0x00000001
+#define P15UsageDecrypt 0x00000002
+#define P15UsageSign 0x00000004
+#define P15UsageSignRecover 0x00000008
+#define P15UsageWrap 0x00000010
+#define P15UsageUnwrap 0x00000020
+#define P15UsageVerify 0x00000040
+#define P15UsageVerifyRecover 0x00000080
+#define P15UsageDerive 0x00000100
+#define P15UsageNonRepudiation 0x00000200
+
+#define P15AccessSensitive 0x00000001
+#define P15AccessExtractable 0x00000002
+#define P15AccessAlwaysSenstive 0x00000004
+#define P15AccessNeverExtractable 0x00000008
+#define P15AccessLocal 0x00000010
+
+#define P15PinCaseSensitive 0x00000001
+#define P15PinLocal 0x00000002
+#define P15PinChangeDisabled 0x00000004
+#define P15PinUnblockDisabled 0x00000008
+#define P15PinInitialized 0x00000010
+#define P15PinNeedsPadding 0x00000020
+#define P15PinUnblockingPin 0x00000040
+#define P15PinSOPin 0x00000080
+#define P15PinDisableAllowed 0x00000100
+
+typedef enum {P15PinBCD=0, P15PinASCIINum=1, P15PinUTF8=2} P15PinType;
+
+typedef struct _P15PinInfo {
+ CKYBitFlags pinFlags;
+ P15PinType pinType;
+ CKYByte minLength;
+ CKYByte storedLength;
+ unsigned long maxLength;
+ CKYByte pinRef;
+ CKYByte padChar;
+} P15PinInfo;
+
+
+/*
+ * allow direct inclusion in C++ files
+ */
+#ifdef __cplusplus
+#define CKY_BEGIN_PROTOS extern "C" {
+#define CKY_END_PROTOS }
+#else
+#define CKY_BEGIN_PROTOS
+#define CKY_END_PROTOS
+#endif
+
+CKY_BEGIN_PROTOS
+/*
+ * generic buffer management functions
+ *
+ * These functions allow simple buffer management used in the CoolKey
+ * library and it's clients.
+ */
+
+/*
+ * Init functions clobbers the current contents and allocates the required
+ * space.
+ * - Active buffers should call CKYBuffer_FreeData before calling an init
+ * function.
+ * - New buffers should call some CKYBuffer_Init function before any use.
+ * - All init functions copies the supplied data into newly allocated space.
+ */
+/* Create an empty buffer with no memory allocated to it. This is sufficient
+ * to begin using a buffer. Note that new calls will probably allocate memory.
+ * It is safe to free an empty buffer. */
+CKYStatus CKYBuffer_InitEmpty(CKYBuffer *buf);
+
+/* Create a buffer of length len all initialized to '0' */
+CKYStatus CKYBuffer_InitFromLen(CKYBuffer *buf, CKYSize len);
+
+/* Create a buffer by decoding a hex string. hexString is NULL terminated. */
+CKYStatus CKYBuffer_InitFromHex(CKYBuffer *buf, const char *hexString);
+
+/* Create a buffer from data */
+CKYStatus CKYBuffer_InitFromData(CKYBuffer *buf, const CKYByte *data, CKYSize len);
+
+/* Create a buffer from part of another buffer. Start indicates the
+ * offset in the old buffer to start in, and len specifies how many bytes
+ * to copy */
+CKYStatus CKYBuffer_InitFromBuffer(CKYBuffer *buf, const CKYBuffer *src,
+ CKYOffset start, CKYSize len);
+/* Create a buffer from an exact copy of another buffer */
+CKYStatus CKYBuffer_InitFromCopy(CKYBuffer *buf, const CKYBuffer *src);
+/*
+ * append functions increase the buffer size if necessary
+ */
+/* append a short in applet order */
+CKYStatus CKYBuffer_AppendChar(CKYBuffer *buf, CKYByte b);
+
+/* append a short in applet order */
+CKYStatus CKYBuffer_AppendShort(CKYBuffer *buf, unsigned short val);
+
+/* append a short in little endian order */
+CKYStatus CKYBuffer_AppendShortLE(CKYBuffer *buf, unsigned short val);
+
+/* append a long in applet order */
+CKYStatus CKYBuffer_AppendLong(CKYBuffer *buf, unsigned long val);
+
+/* append a long in little endian order */
+CKYStatus CKYBuffer_AppendLongLE(CKYBuffer *buf, unsigned long val);
+
+/* append data. the data starts at data and extends len bytes */
+CKYStatus CKYBuffer_AppendData(CKYBuffer *buf, const CKYByte *data, CKYSize len);
+
+/* append buffer fragment. the data starts at buffer[offset]
+ * and extends len bytes */
+CKYStatus CKYBuffer_AppendBuffer(CKYBuffer *buf, const CKYBuffer *src,
+ CKYOffset offset, CKYSize len);
+
+/* append a full buffer */
+CKYStatus CKYBuffer_AppendCopy(CKYBuffer *buf, const CKYBuffer *src );
+
+/* reserve increases the space allocated for the buffer, but does not
+ * increase the actual buffer size. If the buffer already newSize or more
+ * space allocated, Reserve is a no op.
+ */
+CKYStatus CKYBuffer_Reserve(CKYBuffer *buf, CKYSize newSize) ;
+
+/* resize affects the buffer's size. If the buffer len increases,
+ * the new date will be zero'ed out. If the buffer shrinks, the buffer
+ * is truncated, but the space is not removed.
+ */
+CKYStatus CKYBuffer_Resize(CKYBuffer *buf, CKYSize newLen);
+
+/* replace bytes starting at 'offset'. If the buffer needs to be extended,
+ * it will be automatically */
+CKYStatus CKYBuffer_Replace(CKYBuffer *buf, CKYOffset offset, const CKYByte *data,
+ CKYSize len);
+
+/* set byte at ofset. The buffer is extended to offset if necessary */
+CKYStatus CKYBuffer_SetChar(CKYBuffer *buf, CKYOffset offset, CKYByte c);
+/* set several copies of 'c' at from offset to offset+ len */
+CKYStatus CKYBuffer_SetChars(CKYBuffer *buf, CKYOffset offset,
+ CKYByte c, CKYSize len);
+/* These functions work in applet order */
+CKYStatus CKYBuffer_SetShort(CKYBuffer *buf, CKYOffset offset, unsigned short val);
+CKYStatus CKYBuffer_SetLong(CKYBuffer *buf, CKYOffset offset, unsigned long val);
+
+/* These functions work in little endian order */
+CKYStatus CKYBuffer_SetShortLE(CKYBuffer *buf, CKYOffset offset, unsigned short val);
+CKYStatus CKYBuffer_SetLongLE(CKYBuffer *buf, CKYOffset offset, unsigned long val);
+/* read a character from offset. If offset is beyond the end of the buffer,
+ * then the function returns '0' */
+CKYByte CKYBuffer_GetChar(const CKYBuffer *buf, CKYOffset offset);
+/* These functions work in applet order */
+unsigned short CKYBuffer_GetShort(const CKYBuffer *buf, CKYOffset offset);
+unsigned long CKYBuffer_GetLong(const CKYBuffer *buf, CKYOffset offset);
+/* These functions work in little endian order */
+unsigned short CKYBuffer_GetShortLE(const CKYBuffer *buf, CKYOffset offset);
+unsigned long CKYBuffer_GetLongLE(const CKYBuffer *buf, CKYOffset offset);
+
+/* clear out all the data in a buffer */
+void CKYBuffer_Zero(CKYBuffer *buf);
+
+/* return the size (length) of a buffer. This is only the portion of the
+ * buffer that has valid data set. */
+CKYSize CKYBuffer_Size(const CKYBuffer *buf);
+
+/* return a pointer to the data buffer */
+const CKYByte *CKYBuffer_Data(const CKYBuffer *buf);
+
+/* compare two buffers return :
+ * 1 if the two buffers are equal,
+ * 0 if they are not */
+CKYBool CKYBuffer_IsEqual(const CKYBuffer *buf1, const CKYBuffer *buf2);
+/* compares raw data with a buffer or equality */
+CKYBool CKYBuffer_DataIsEqual(const CKYBuffer *buf1,
+ const CKYByte *buf2, CKYSize buf2Len);
+
+/* free all the data associated with a buffer and initialize the buffer */
+CKYStatus CKYBuffer_FreeData(CKYBuffer *buf);
+
+/*
+ * APDU's are buffers that know about the APDU structure
+ */
+CKYStatus CKYAPDU_Init(CKYAPDU *apdu);
+CKYStatus CKYAPDU_InitFromData(CKYAPDU *apdu, const CKYByte *data, CKYSize size);
+CKYStatus CKYAPDU_FreeData(CKYAPDU *apdu);
+
+/* Access APDU header bytes */
+CKYByte CKYAPDU_GetCLA(const CKYAPDU *apdu);
+CKYStatus CKYAPDU_SetCLA(CKYAPDU *apdu, CKYByte b);
+CKYByte CKYAPDU_GetINS(const CKYAPDU *apdu);
+CKYStatus CKYAPDU_SetINS(CKYAPDU *apdu, CKYByte b);
+CKYByte CKYAPDU_GetP1(const CKYAPDU *apdu);
+CKYStatus CKYAPDU_SetP1(CKYAPDU *apdu, CKYByte b);
+CKYByte CKYAPDU_GetP2(const CKYAPDU *apdu);
+CKYStatus CKYAPDU_SetP2(CKYAPDU *apdu, CKYByte b);
+
+/* add sending date to the APDU */
+/* Set resets the buffer, append, adds the data to the end. Lc in
+ * the APDU header is automaticallu updated */
+CKYStatus CKYAPDU_SetSendData(CKYAPDU *apdu, const CKYByte *data, CKYSize len);
+CKYStatus CKYAPDU_SetSendDataBuffer(CKYAPDU *apdu, const CKYBuffer *buf);
+CKYStatus CKYAPDU_AppendSendData(CKYAPDU *apdu, const CKYByte *data, CKYSize len);
+CKYStatus CKYAPDU_AppendSendDataBuffer(CKYAPDU *apdu, const CKYBuffer *buf);
+
+/* set Le in the APDU header to the amount of bytes expected to be
+ * returned. */
+CKYStatus CKYAPDU_SetReceiveLen(CKYAPDU *apdu, CKYByte recvlen);
+CKYStatus CKYAPDU_SetShortReceiveLen(CKYAPDU *apdu, unsigned short recvlen);
+CKYStatus CKYAPDU_SetReceiveLength(CKYAPDU *apdu, CKYSize recvlen);
+CKYStatus CKYAPDU_AppendReceiveLen(CKYAPDU *apdu, CKYByte recvlen);
+CKYStatus CKYAPDU_AppendShortReceiveLen(CKYAPDU *apdu, unsigned short recvlen);
+CKYStatus CKYAPDU_AppendReceiveLength(CKYAPDU *apdu, CKYSize recvlen);
+
+/* set the parent loadmodule name */
+void CKY_SetName(const char *name);
+
+CKY_END_PROTOS
+
+#endif /* CKY_BASE_H */
diff -up ./esc/src/lib/coolkey/cky_basei.h.fix1 ./esc/src/lib/coolkey/cky_basei.h
--- ./esc/src/lib/coolkey/cky_basei.h.fix1 2018-04-26 11:44:38.437986192 -0700
+++ ./esc/src/lib/coolkey/cky_basei.h 2018-04-26 11:44:38.437986192 -0700
@@ -0,0 +1,35 @@
+/* ***** BEGIN COPYRIGHT BLOCK *****
+ * Copyright (C) 2005 Red Hat, Inc.
+ * All rights reserved.
+ *
+ * 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 St, Fifth Floor, Boston, MA 02110-1301 USA
+ * ***** END COPYRIGHT BLOCK ***** */
+
+#ifndef CKY_BASE_H
+#ifndef CKY_BASEI_H
+#define CKY_BASEI_H 1
+
+#define CKYBUFFER_PRIVATE \
+ CKYSize len; \
+ CKYSize size; \
+ CKYByte *data; \
+ void *reserved;
+
+#define CKYAPDU_PRIVATE \
+ CKYBuffer apduBuf; \
+ void *reserved;
+
+#endif /* CKY_BASE_H */
+#endif /* CKY_BASEI_H */
diff -up ./esc/src/lib/coolkey/cky_card.c.fix1 ./esc/src/lib/coolkey/cky_card.c
--- ./esc/src/lib/coolkey/cky_card.c.fix1 2018-04-26 11:44:38.437986192 -0700
+++ ./esc/src/lib/coolkey/cky_card.c 2018-04-26 11:44:38.437986192 -0700
@@ -0,0 +1,1226 @@
+/* ***** BEGIN COPYRIGHT BLOCK *****
+ * Copyright (C) 2005 Red Hat, Inc.
+ * All rights reserved.
+ *
+ * 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 St, Fifth Floor, Boston, MA 02110-1301 USA
+ * ***** END COPYRIGHT BLOCK ***** */
+
+#include
+#include
+#include
+#include "cky_basei.h" /* friend class */
+#include "cky_base.h"
+#include "cky_card.h"
+#include "dynlink.h"
+
+#ifndef WINAPI
+#define WINAPI
+typedef SCARD_READERSTATE *LPSCARD_READERSTATE;
+#endif
+
+#ifndef SCARD_E_NO_READERS_AVAILABLE
+#define SCARD_E_NO_READERS_AVAILABLE ((unsigned long)0x8010002EL)
+#endif
+
+#define NEW(type,count) (type *)malloc((count)*sizeof(type))
+
+/*
+ * protect against scard API not being installed.
+ */
+
+typedef long (WINAPI * SCardEstablishContextFn) (
+ unsigned long dwScope,
+ const void * pvReserved1,
+ const void * pvReserved2,
+ LPSCARDCONTEXT phContext);
+
+typedef long (WINAPI * SCardReleaseContextFn) (
+ SCARDCONTEXT hContext);
+
+typedef long (WINAPI * SCardBeginTransactionFn) (
+ long hCard);
+
+typedef long (WINAPI * SCardEndTransactionFn) (
+ long hCard,
+ unsigned long dwDisposition);
+
+typedef long (WINAPI * SCardConnectFn) (
+ SCARDCONTEXT hContext,
+ const char *szReader,
+ unsigned long dwShareMode,
+ unsigned long dwPreferredProtocols,
+ long *phCard,
+ unsigned long *pdwActiveProtocol);
+
+typedef long (WINAPI * SCardDisconnectFn) (
+ long hCard,
+ unsigned long dwDisposition);
+
+typedef long (WINAPI * SCardTransmitFn) (
+ long hCard,
+ LPCSCARD_IO_REQUEST pioSendPci,
+ const unsigned char *pbSendBuffer,
+ unsigned long cbSendLength,
+ LPSCARD_IO_REQUEST pioRecvPci,
+ unsigned char *pbRecvBuffer,
+ unsigned long *pcbRecvLength);
+
+typedef long (WINAPI * SCardReconnectFn) (
+ long hCard,
+ unsigned long dwShareMode,
+ unsigned long dwPreferredProtocols,
+ unsigned long dwInitialization,
+ unsigned long *pdwActiveProtocol);
+
+typedef long (WINAPI * SCardListReadersFn) (
+ SCARDCONTEXT hContext,
+ const char *mszGroups,
+ char *mszReaders,
+ unsigned long *pcchReaders);
+
+typedef long (WINAPI * SCardStatusFn) (
+ long hCard,
+ char *mszReaderNames,
+ unsigned long *pcchReaderLen,
+ unsigned long *pdwState,
+ unsigned long *pdwProtocol,
+ unsigned char *pbAtr,
+ unsigned long *pcbAtrLen);
+
+typedef long (WINAPI * SCardGetAttribFn) (
+ long hCard,
+ unsigned long dwAttId,
+ char *pbAttr,
+ unsigned long *pchAttrLen);
+
+typedef long (WINAPI * SCardGetStatusChangeFn) (
+ SCARDCONTEXT hContext,
+ unsigned long dwTimeout,
+ LPSCARD_READERSTATE rgReaderStates,
+ unsigned long cReaders);
+
+typedef long (WINAPI * SCardCancelFn) (
+ SCARDCONTEXT hContext);
+
+typedef struct _SCard {
+ SCardEstablishContextFn SCardEstablishContext;
+ SCardReleaseContextFn SCardReleaseContext;
+ SCardBeginTransactionFn SCardBeginTransaction;
+ SCardEndTransactionFn SCardEndTransaction;
+ SCardConnectFn SCardConnect;
+ SCardDisconnectFn SCardDisconnect;
+ SCardTransmitFn SCardTransmit;
+ SCardReconnectFn SCardReconnect;
+ SCardListReadersFn SCardListReaders;
+ SCardStatusFn SCardStatus;
+ SCardGetAttribFn SCardGetAttrib;
+ SCardGetStatusChangeFn SCardGetStatusChange;
+ SCardCancelFn SCardCancel;
+ SCARD_IO_REQUEST *SCARD_PCI_T0_;
+ SCARD_IO_REQUEST *SCARD_PCI_T1_;
+} SCard;
+
+#define GET_ADDRESS(library, scard, name) \
+ status= ckyShLibrary_getAddress(library, \
+ (void**) &scard->name, MAKE_DLL_SYMBOL(name)); \
+ if (status != CKYSUCCESS) { \
+ goto fail; \
+ }
+
+#ifdef WIN32
+#define SCARD_LIB_NAME "winscard.dll"
+#else
+#ifdef MAC
+#define SCARD_LIB_NAME "PCSC.Framework/PCSC"
+#else
+#ifdef LINUX
+#define SCARD_LIB_NAME "libpcsclite.so"
+#else
+#ifndef SCARD_LIB_NAME
+#error "define wincard library for this platform"
+#endif
+#endif
+#endif
+#endif
+
+static SCard *
+ckySCard_Init(void)
+{
+ ckyShLibrary library;
+ CKYStatus status;
+ SCard *scard = NEW(SCard, 1);
+
+ if (!scard) {
+ return NULL;
+ }
+
+ library = ckyShLibrary_open(SCARD_LIB_NAME);
+ if (!library) {
+ goto fail;
+ }
+
+ GET_ADDRESS(library, scard, SCardEstablishContext);
+ GET_ADDRESS(library, scard, SCardReleaseContext);
+ GET_ADDRESS(library, scard, SCardBeginTransaction);
+ GET_ADDRESS(library, scard, SCardEndTransaction);
+ /* expands to SCardConnectA on Windows */
+ GET_ADDRESS(library, scard, SCardConnect);
+ GET_ADDRESS(library, scard, SCardDisconnect);
+ GET_ADDRESS(library, scard, SCardTransmit);
+ GET_ADDRESS(library, scard, SCardReconnect);
+ /* expands to SCardListReadersA on Windows */
+ GET_ADDRESS(library, scard, SCardListReaders);
+ /* expands to SCardStatusA on Windows */
+ GET_ADDRESS(library, scard, SCardStatus);
+#ifdef WIN32
+ GET_ADDRESS(library, scard, SCardGetAttrib);
+#endif
+ /* SCardGetStatusChangeA */
+ GET_ADDRESS(library, scard, SCardGetStatusChange);
+ GET_ADDRESS(library, scard, SCardCancel);
+
+ status = ckyShLibrary_getAddress( library,
+ (void**) &scard->SCARD_PCI_T0_, MAKE_DLL_SYMBOL(g_rgSCardT0Pci));
+ if( status != CKYSUCCESS ) {
+ goto fail;
+ }
+
+ status = ckyShLibrary_getAddress( library,
+ (void**) &scard->SCARD_PCI_T1_, MAKE_DLL_SYMBOL(g_rgSCardT1Pci));
+ if( status != CKYSUCCESS ) {
+ goto fail;
+ }
+ return scard;
+
+fail:
+ if (library) {
+ ckyShLibrary_close(library);
+ }
+ free(scard);
+ return NULL;
+}
+/*
+ * Implement CKYReaderNameLists and CKYCardConnectionLists
+ */
+/* make the list code happy */
+static void
+CKYReaderName_Destroy(char *data) {
+ free(data);
+}
+
+#include "cky_list.i" /* implemnentation of the lists define by cky_list.h */
+CKYLIST_IMPLEMENT(CKYReaderName, char *)
+CKYLIST_IMPLEMENT(CKYCardConnection, CKYCardConnection *)
+
+
+/*
+ * CKReader objects represent Readers attached to the system.
+ * The objects themselves are really SCard SCARD_READERSTATE objects.
+ * These objects are used in 2 ways:
+ * 1) the application creates static SCARD_READERSTATE's and use
+ * CKYReader_Init() to initialize the structure. In this case
+ * the application can call any of the reader 'methods' (functions
+ * starting with CKReader) on these objects. When finished the
+ * application is responsible for calling CKYReader_FreeData() to free
+ * any data held by the reader object.
+ * 2) Acquire an array of readers with CKYReader_CreateArray(). In this
+ * case the application can call any method on any particular array member
+ * In the end the Application is responsible for calling
+ * CKYReader_DestroyArray() to free the entire array.
+ */
+
+void
+CKYReader_Init(SCARD_READERSTATE *reader)
+{
+ reader->szReader = NULL;
+ reader->pvUserData = 0;
+ reader->cbAtr = 0;
+ reader->dwCurrentState = SCARD_STATE_UNAWARE;
+}
+
+void
+CKYReader_FreeData(SCARD_READERSTATE *reader)
+{
+ if (reader->szReader) {
+ free((void *)reader->szReader);
+ }
+ CKYReader_Init(reader);
+}
+
+CKYStatus
+CKYReader_SetReaderName(SCARD_READERSTATE *reader, const char *name)
+{
+ free((void *)reader->szReader);
+ reader->szReader = strdup(name);
+ return (reader->szReader)? CKYSUCCESS: CKYNOMEM;
+}
+
+const char *
+CKYReader_GetReaderName(const SCARD_READERSTATE *reader)
+{
+ return reader->szReader;
+}
+
+/* see openSC or PCSC for the semantics of Known State and Event States */
+CKYStatus
+CKYReader_SetKnownState(SCARD_READERSTATE *reader, unsigned long state)
+{
+ reader->dwCurrentState = state;
+ return CKYSUCCESS;
+}
+
+unsigned long
+CKYReader_GetKnownState(const SCARD_READERSTATE *reader)
+{
+ return reader->dwCurrentState;
+}
+
+unsigned long
+CKYReader_GetEventState(const SCARD_READERSTATE *reader)
+{
+ return reader->dwEventState;
+}
+
+/* Caller must have init'ed the buffer before calling
+ * any data in the existing buffer is overwritten */
+CKYStatus
+CKYReader_GetATR(const SCARD_READERSTATE *reader, CKYBuffer *buf)
+{
+ CKYStatus ret;
+
+ ret = CKYBuffer_Resize(buf, reader->cbAtr);
+ if (ret != CKYSUCCESS) {
+ return ret;
+ }
+ return CKYBuffer_Replace(buf, 0, reader->rgbAtr, reader->cbAtr);
+}
+
+SCARD_READERSTATE *
+CKYReader_CreateArray(const CKYReaderNameList readerNames,
+ unsigned long *returnReaderCount)
+{
+ unsigned long i,j;
+ unsigned long readerCount;
+ SCARD_READERSTATE *readers;
+ CKYStatus ret;
+
+ readerCount=CKYReaderNameList_GetCount(readerNames);
+ if (readerCount == 0) {
+ return NULL;
+ }
+ readers = NEW(SCARD_READERSTATE, readerCount);
+ if (readers == NULL) {
+ return NULL;
+ }
+
+ for (i=0; i < readerCount; i++) {
+ CKYReader_Init(&readers[i]);
+ ret = CKYReader_SetReaderName(&readers[i],
+ CKYReaderNameList_GetValue(readerNames,i));
+ if (ret != CKYSUCCESS) {
+ break;
+ }
+ }
+ if (ret != CKYSUCCESS) {
+ for (j=0; j < i; j++) {
+ CKYReader_FreeData(&readers[j]);
+ }
+ free(readers);
+ return NULL;
+ }
+ if (returnReaderCount) {
+ *returnReaderCount=readerCount;
+ }
+
+ return readers;
+}
+
+/*
+ * add more reader states to an existing reader state array.
+ * The existing reader will have a new pointer, which will be updated only
+ * after the new one is complete, and before the old one is freed. The 'add'
+ * array is not modified or freed.
+ */
+CKYStatus
+CKYReader_AppendArray(SCARD_READERSTATE **array, unsigned long arraySize,
+ const char **readerNames, unsigned long numReaderNames)
+{
+ unsigned long i,j;
+ SCARD_READERSTATE *readers;
+ SCARD_READERSTATE *old;
+ CKYStatus ret = CKYSUCCESS;
+
+ readers = NEW(SCARD_READERSTATE, arraySize+numReaderNames);
+ if (readers == NULL) {
+ return CKYNOMEM;
+ }
+ /* copy the original readers, inheriting all the pointer memory */
+ memcpy(readers, *array, arraySize*sizeof(SCARD_READERSTATE));
+
+ /* initialize and add the new reader states. */
+ for (i=0; i < numReaderNames; i++) {
+ CKYReader_Init(&readers[i+arraySize]);
+ ret = CKYReader_SetReaderName(&readers[i+arraySize],readerNames[i]);
+ if (ret != CKYSUCCESS) {
+ break;
+ }
+ }
+
+ /* we failed, only free the new reader states, ownership of the new
+ * ones will revert back to the original */
+ if (ret != CKYSUCCESS) {
+ for (j=0; j < i; j++) {
+ CKYReader_FreeData(&readers[j+arraySize]);
+ }
+ free(readers);
+ return ret;
+ }
+
+ /* Now we swap the readers states */
+ old = *array;
+ *array = readers;
+ /* it's now safe to free the old one */
+ free(old);
+
+ return CKYSUCCESS;
+}
+
+void
+CKYReader_DestroyArray(SCARD_READERSTATE *reader, unsigned long readerCount)
+{
+ unsigned long i;
+
+ for (i=0; i < readerCount; i++) {
+ CKYReader_FreeData(&reader[i]);
+ }
+ free(reader);
+}
+
+/*
+ * CKYCardContexts are wrapped access to the SCard Context, which is
+ * part of the openSC/ Microsoft PCSC interface. Applications will
+ * typically open one context to get access to the SCard Subsystem.
+ *
+ * To protect ourselves from systems without the SCard library installed,
+ * the SCard calls are looked up from the library and called through
+ * a function pointer.
+ */
+struct _CKYCardContext {
+ SCARDCONTEXT context;
+ SCard *scard;
+ unsigned long scope;
+ unsigned long lastError;
+};
+
+
+static CKYStatus
+ckyCardContext_init(CKYCardContext *ctx)
+{
+ static SCard *scard;
+
+ ctx->lastError = 0;
+ ctx->context = 0;
+ if (!scard) {
+ scard = ckySCard_Init();
+ if (!scard) {
+ return CKYNOSCARD;
+ }
+ }
+ ctx->scard = scard;
+ return CKYSUCCESS;
+}
+
+static CKYStatus
+ckyCardContext_release(CKYCardContext *ctx)
+{
+ unsigned long rv = ctx->scard->SCardReleaseContext(ctx->context);
+ ctx->context = 0;
+ if (rv != SCARD_S_SUCCESS) {
+ ctx->lastError = rv;
+ return CKYSCARDERR;
+ }
+ return CKYSUCCESS;
+}
+
+static CKYStatus
+ckyCardContext_establish(CKYCardContext *ctx, unsigned long scope)
+{
+ unsigned long rv;
+
+ if (ctx->context) {
+ ckyCardContext_release(ctx);
+ }
+ rv = ctx->scard->SCardEstablishContext(scope, NULL, NULL, &ctx->context);
+ if (rv != SCARD_S_SUCCESS) {
+ ctx->lastError = rv;
+ return CKYSCARDERR;
+ }
+ return CKYSUCCESS;
+}
+
+CKYCardContext *
+CKYCardContext_Create(unsigned long scope)
+{
+ CKYCardContext *ctx;
+ CKYStatus ret;
+
+ ctx = NEW(CKYCardContext, 1);
+ if (ctx == NULL) {
+ return NULL;
+ }
+ ret = ckyCardContext_init(ctx);
+ if (ret != CKYSUCCESS) {
+ CKYCardContext_Destroy(ctx);
+ return NULL;
+ }
+ ctx->scope = scope;
+ ret = ckyCardContext_establish(ctx, scope);
+#ifdef MAC
+/* Apple won't establish a connnection if pcscd is not running. Because of
+ * the way securityd controls pcscd, this may not necessarily be an error
+ * condition. Detect this case and continue. We'll establish the connection
+ * later..
+ */
+ if (ctx->lastError == SCARD_F_INTERNAL_ERROR) {
+ ctx->context = 0; /* make sure it's not established */
+ return ctx;
+ }
+#endif
+ if (ret != CKYSUCCESS) {
+ CKYCardContext_Destroy(ctx);
+ return NULL;
+ }
+ return ctx;
+}
+
+CKYStatus
+CKYCardContext_Destroy(CKYCardContext *ctx)
+{
+ CKYStatus ret = CKYSUCCESS;
+ if (ctx == NULL) {
+ return CKYSUCCESS;
+ }
+ if (ctx->context) {
+ ret = ckyCardContext_release(ctx);
+ }
+ free(ctx);
+ return ret;
+}
+
+SCARDCONTEXT
+CKYCardContext_GetContext(const CKYCardContext *ctx)
+{
+ return ctx->context;
+}
+
+CKYStatus
+CKYCardContext_ListReaders(CKYCardContext *ctx, CKYReaderNameList *readerNames)
+{
+ unsigned long readerLen;
+ unsigned long rv;
+ char * readerStr = NULL;
+ char *cur;
+ char ** readerList;
+ int count,i;
+
+
+ /* return NULL in the case nothing is found, or there is an error */
+ *readerNames = NULL;
+
+ /* if we aren't established yet, do so now */
+ if (!ctx->context) {
+ CKYStatus ret = ckyCardContext_establish(ctx, ctx->scope);
+ if (ret != CKYSUCCESS) {
+
+#ifdef MAC
+ if (ctx->lastError == SCARD_F_INTERNAL_ERROR) {
+ /* Still can't establish, just treat it as 'zero' readers */
+ return CKYSUCCESS;
+ }
+#endif
+ return ret;
+ }
+ }
+
+ /* get the initial length */
+ readerLen = 0;
+ rv = ctx->scard->SCardListReaders(ctx->context, NULL /*groups*/,
+ NULL, &readerLen);
+ /* handle the other errors from SCardListReaders */
+ if (rv == SCARD_E_NO_READERS_AVAILABLE) {
+ /* not really an error: there are no readers */
+ return CKYSUCCESS;
+ }
+
+ if( rv != SCARD_S_SUCCESS ) {
+ ctx->lastError = rv;
+ return CKYSCARDERR;
+ }
+
+ /* if no readers, return OK and a NULL list */
+ if (readerLen == 0) {
+ return CKYSUCCESS;
+ }
+
+ /*
+ * Keep trying to read in the buffer, allowing that the required buffer
+ * length may change between calls to SCardListReaders.
+ */
+ do {
+ if (readerLen < 1 || readerLen > CKY_OUTRAGEOUS_MALLOC_SIZE) {
+ return CKYNOMEM;
+ }
+ readerStr = NEW(char,readerLen);
+ if (readerStr == NULL) {
+ return CKYNOMEM;
+ }
+
+ rv = ctx->scard->SCardListReaders(ctx->context, NULL /*groups*/,
+ readerStr, &readerLen);
+
+ /* we've found it, pop out with readerStr allocated */
+ if (rv == SCARD_S_SUCCESS) {
+ break;
+ }
+
+ /* Nope, free the reader we allocated */
+ free(readerStr);
+ readerStr = NULL;
+
+ } while( rv == SCARD_E_INSUFFICIENT_BUFFER );
+
+ /* handle the other errors from SCardListReaders */
+ if (rv == SCARD_E_NO_READERS_AVAILABLE) {
+ /* not really an error: there are no readers */
+ ctx->lastError = SCARD_E_NO_READERS_AVAILABLE;
+ return CKYSUCCESS;
+ }
+ if (rv != SCARD_S_SUCCESS) {
+ /* stash the error and fail */
+ ctx->lastError = rv;
+ return CKYSCARDERR;
+ }
+
+ /*
+ * Windows returns the list of readers as a series of null terminated
+ * strings, terminated with an additional NULL. For example, if there
+ * are three readers name "Reader 1", "Reader 2", "Reader 3", the returned
+ * readerStr would look like: "Reader 1\0Reader 2\0Reader N\0\0".
+ *
+ * We need to return a list of ReaderNames. This is currently a pointer
+ * to an array of string pointers, terminated by a NULL.
+ *
+ * +--------------+
+ * | Reader 1 ptr | -> "Reader 1"
+ * +--------------+
+ * | Reader 2 ptr | -> "Reader 2"
+ * +--------------+
+ * | Reader N ptr | -> "Reader N"
+ * +--------------+
+ * | NULL |
+ * +--------------+
+ *
+ * NOTE: This code explicitly knows the underlying format for
+ * CKYReaderNameLists defined in cky_list.i. If cky_list.i is changes,
+ * this code will need to be changed as well.
+ */
+ /* find the count of readers */
+ for (cur = readerStr, count = 0; *cur; cur += strlen(cur)+1, count++ )
+ /* Empty */ ;
+ readerList = NEW(char *,count+1);
+ if (readerList == NULL) {
+ goto fail;
+ }
+
+ /* now copy the readers into the array */
+ for (i=0, cur=readerStr; i < count ; cur+=strlen(cur) +1, i++) {
+ readerList[i] = strdup(cur);
+ if (readerList[i] == NULL) {
+ goto fail;
+ }
+ }
+ readerList[count] = NULL;
+ free(readerStr);;
+ *readerNames = (CKYReaderNameList) readerList;
+ return CKYSUCCESS;
+
+fail:
+ if (readerStr) {
+ free(readerStr);
+ }
+ if (readerList) {
+ CKYReaderNameList_Destroy((CKYReaderNameList) readerList);
+ }
+ return CKYNOMEM;
+}
+
+/*
+ * The original C++ API had to very similiar functions that returned
+ * either reader names or connections based on ATR. This is a single
+ * function that can return both. The exported interface calls this
+ * one with one of the lists set to NULL.
+ *
+ * NOTE: this function "knows" the underlying format for lists and
+ * hand builds the related lists.
+ */
+CKYStatus
+ckyCardContext_findReadersByATR(CKYCardContext *ctx,
+ CKYReaderNameList *returnReaders,
+ CKYCardConnectionList *returnConn,
+ const CKYBuffer *targetATR)
+{
+ CKYReaderNameList readerNames;
+ CKYBuffer ATR;
+ CKYCardConnection **connList = NULL;
+ CKYCardConnection **connPtr = NULL;
+ char **readerList = NULL;
+ char **readerPtr = NULL;
+ int readerCount, i;
+ CKYStatus ret;
+
+ CKYBuffer_InitEmpty(&ATR);
+
+ /* if we aren't established yet, do so now */
+ if (!ctx->context) {
+ ret = ckyCardContext_establish(ctx, ctx->scope);
+ if (ret != CKYSUCCESS) {
+ return ret;
+ }
+ }
+
+ /* initialize our returned values to empty */
+ if (returnReaders) {
+ *returnReaders = NULL;
+ }
+ if (returnConn) {
+ *returnConn = NULL;
+ }
+
+ ret = CKYCardContext_ListReaders(ctx, &readerNames);
+ if (ret != CKYSUCCESS) {
+ return ret;
+ }
+
+ readerCount = CKYReaderNameList_GetCount(readerNames);
+
+ /* none found, return success */
+ if (readerCount == 0) {
+ CKYReaderNameList_Destroy(readerNames);
+ return CKYSUCCESS;
+ }
+
+ /* now initialize our name and connection lists */
+ if (returnConn) {
+ connList = NEW(CKYCardConnection *, readerCount);
+ connPtr = connList;
+ if (connList == NULL) {
+ goto fail;
+ }
+ }
+ if (returnReaders) {
+ readerList = NEW(char *, readerCount);
+ readerPtr = readerList;
+ if (readerList == NULL) {
+ goto fail;
+ }
+ }
+
+ ret = CKYBuffer_Resize(&ATR, CKY_MAX_ATR_LEN);
+ if (ret != CKYSUCCESS) {
+ goto fail;
+ }
+
+ /* now walk the reader list trying to get connections */
+ for (i=0; i < readerCount ; i++) {
+ CKYCardConnection * conn = CKYCardConnection_Create(ctx);
+ unsigned long state;
+ const char *thisReader = CKYReaderNameList_GetValue(readerNames, i);
+
+
+ if (!conn) {
+ goto loop;
+ }
+ ret = CKYCardConnection_Connect(conn, thisReader);
+ if (ret != CKYSUCCESS) {
+ goto loop;
+ }
+ ret = CKYCardConnection_GetStatus(conn, &state, &ATR);
+ if (ret != CKYSUCCESS) {
+ goto loop;
+ }
+ if (CKYBuffer_IsEqual(targetATR, &ATR)) {
+ if (connPtr) {
+ *connPtr++ = conn; /* adopt */
+ conn = NULL;
+ }
+ if (readerPtr) {
+ *readerPtr++ = strdup(thisReader);
+ }
+ }
+
+loop:
+ /* must happen each time through the loop */
+ if (conn) {
+ CKYCardConnection_Destroy(conn);
+ }
+ }
+
+ /* done with the reader names now */
+ CKYReaderNameList_Destroy(readerNames);
+ /* and the ATR buffer */
+ CKYBuffer_FreeData(&ATR);
+
+ /* terminate out lists and return them */
+ if (readerPtr) {
+ *readerPtr = NULL;
+ *returnReaders = (CKYReaderNameList) readerList;
+ }
+ if (connPtr) {
+ *connPtr = NULL;
+ *returnConn = (CKYCardConnectionList) connList;
+ }
+ return CKYSUCCESS;
+
+fail:
+ if (readerNames) {
+ CKYReaderNameList_Destroy(readerNames);
+ }
+ if (connList) {
+ free(connList);
+ }
+ if (readerList) {
+ free(readerList);
+ }
+ CKYBuffer_FreeData(&ATR);
+ return CKYNOMEM;
+}
+
+CKYStatus
+CKYCardContext_FindCardsByATR(CKYCardContext *ctx,
+ CKYCardConnectionList *cardList, const CKYBuffer *targetATR)
+{
+ return ckyCardContext_findReadersByATR(ctx, NULL, cardList, targetATR);
+}
+
+CKYStatus
+CKYCardContext_FindReadersByATR(CKYCardContext *ctx,
+ CKYReaderNameList *readerNames, const CKYBuffer *targetATR)
+{
+ return ckyCardContext_findReadersByATR(ctx, readerNames, NULL, targetATR);
+}
+
+CKYCardConnection *
+CKYCardContext_CreateConnection(CKYCardContext *ctx)
+{
+ return CKYCardConnection_Create(ctx);
+}
+
+CKYStatus
+CKYCardContext_WaitForStatusChange(CKYCardContext *ctx,
+ SCARD_READERSTATE *readers, unsigned long readerCount,
+ unsigned long timeout)
+{
+ unsigned long rv;
+
+ /* if we aren't established yet, do so now */
+ if (!ctx->context) {
+ CKYStatus ret = ckyCardContext_establish(ctx, ctx->scope);
+ if (ret != CKYSUCCESS) {
+ return ret;
+ }
+ }
+ rv = ctx->scard->SCardGetStatusChange(ctx->context, timeout,
+ readers, readerCount);
+ if (rv != SCARD_S_SUCCESS) {
+ if ((rv == SCARD_E_NO_SERVICE) || (rv == SCARD_E_SERVICE_STOPPED)) {
+ /* if we were stopped, don't reuse the old context,
+ * pcsc-lite hangs */
+ ckyCardContext_release(ctx);
+ }
+ ctx->lastError = rv;
+ return CKYSCARDERR;
+ }
+ return CKYSUCCESS;
+}
+
+CKYStatus
+CKYCardContext_Cancel(CKYCardContext *ctx)
+{
+ unsigned long rv;
+
+ /* if we aren't established yet, we can't be in change status then */
+ if (!ctx->context) {
+ return CKYSUCCESS;
+ }
+ rv = ctx->scard->SCardCancel(ctx->context);
+
+ if (rv != SCARD_S_SUCCESS) {
+ ctx->lastError = rv;
+ return CKYSCARDERR;
+ }
+ return CKYSUCCESS;
+}
+
+unsigned long
+CKYCardContext_GetLastError(const CKYCardContext *ctx)
+{
+ return ctx->lastError;
+}
+
+/*
+ * Connections represent the connection to the actual smart cards.
+ * Applications usually has one of these for each card inserted in
+ * the system. Connections are where we can get information about
+ * each card, as well as transmit commands (APDU's) to the card.
+ */
+/* In the originaly C++ library, lastError was set to the last return
+ * code from any SCARD call. In this C version of the library, lastError
+ * is the last non-successful SCARD call. lastError will be set
+ * if the function returns CKYSCARDERR.
+ */
+struct _CKYCardConnection {
+ const CKYCardContext *ctx;
+ SCard *scard; /* cache a copy from the context */
+ SCARDHANDLE cardHandle;
+ unsigned long lastError;
+ CKYBool inTransaction;
+ unsigned long protocol;
+};
+
+static void
+ckyCardConnection_init(CKYCardConnection *conn, const CKYCardContext *ctx)
+{
+ conn->ctx = ctx;
+ conn->scard = ctx->scard;
+ conn->cardHandle = 0;
+ conn->lastError = 0;
+ conn->inTransaction = 0;
+ conn->protocol = SCARD_PROTOCOL_T0;
+}
+
+
+CKYCardConnection *
+CKYCardConnection_Create(const CKYCardContext *ctx)
+{
+ CKYCardConnection *conn;
+
+ /* don't even try if we don't have a Card Context */
+ if (ctx == NULL) {
+ return NULL;
+ }
+
+ conn = NEW(CKYCardConnection, 1);
+ if (conn == NULL) {
+ return NULL;
+ }
+ ckyCardConnection_init(conn, ctx);
+ return conn;
+}
+
+
+CKYStatus
+CKYCardConnection_Destroy(CKYCardConnection *conn)
+{
+ if (conn == NULL) {
+ return CKYSUCCESS;
+ }
+ if (conn->inTransaction) {
+ CKYCardConnection_EndTransaction(conn);
+ }
+ CKYCardConnection_Disconnect(conn);
+ free(conn);
+ return CKYSUCCESS;
+}
+
+CKYStatus
+CKYCardConnection_Connect(CKYCardConnection *conn, const char *readerName)
+{
+ CKYStatus ret;
+ unsigned long rv;
+
+ ret = CKYCardConnection_Disconnect(conn);
+ if (ret != CKYSUCCESS) {
+ return ret;
+ }
+ rv = conn->scard->SCardConnect( conn->ctx->context, readerName,
+ SCARD_SHARE_SHARED, SCARD_PROTOCOL_T0 | SCARD_PROTOCOL_T1, &conn->cardHandle, &conn->protocol);
+ if (rv != SCARD_S_SUCCESS) {
+ conn->lastError = rv;
+ return CKYSCARDERR;
+ }
+ return CKYSUCCESS;
+}
+
+CKYStatus
+CKYCardConnection_Disconnect(CKYCardConnection *conn)
+{
+ unsigned long rv;
+ if (conn->cardHandle == 0) {
+ return CKYSUCCESS;
+ }
+ rv = conn->scard->SCardDisconnect( conn->cardHandle, SCARD_LEAVE_CARD);
+ conn->cardHandle = 0;
+ if (rv != SCARD_S_SUCCESS) {
+ conn->lastError = rv;
+ return CKYSCARDERR;
+ }
+ return CKYSUCCESS;
+}
+
+CKYBool
+CKYCardConnection_IsConnected(const CKYCardConnection *conn)
+{
+ return (conn->cardHandle != 0);
+}
+
+unsigned long
+CKYCardConnection_GetProtocol(const CKYCardConnection *conn)
+{
+ return conn->protocol;
+}
+
+CKYStatus
+ckyCardConnection_reconnectRaw(CKYCardConnection *conn, unsigned long init)
+{
+ unsigned long rv;
+ unsigned long protocol;
+
+ rv = conn->scard->SCardReconnect(conn->cardHandle,
+ SCARD_SHARE_SHARED, SCARD_PROTOCOL_T0 | SCARD_PROTOCOL_T1 , init, &protocol);
+ if (rv != SCARD_S_SUCCESS) {
+ conn->lastError = rv;
+ return CKYSCARDERR;
+ }
+ conn->protocol = protocol;
+ return CKYSUCCESS;
+}
+
+CKYStatus
+CKYCardConnection_Reconnect(CKYCardConnection *conn)
+{
+ return ckyCardConnection_reconnectRaw(conn, SCARD_LEAVE_CARD);
+}
+
+CKYStatus CKYCardConnection_Reset(CKYCardConnection *conn)
+{
+ return ckyCardConnection_reconnectRaw(conn, SCARD_RESET_CARD);
+}
+
+CKYStatus
+CKYCardConnection_BeginTransaction(CKYCardConnection *conn)
+{
+ unsigned long rv;
+ rv = conn->scard->SCardBeginTransaction(conn->cardHandle);
+ if (rv != SCARD_S_SUCCESS) {
+ conn->lastError = rv;
+ return CKYSCARDERR;
+ }
+ conn->inTransaction = 1;
+ return CKYSUCCESS;
+}
+
+CKYStatus
+CKYCardConnection_EndTransaction(CKYCardConnection *conn)
+{
+ unsigned long rv;
+ if (!conn->inTransaction) {
+ return CKYSUCCESS; /* C++ library returns success in this case, but
+ * it may be better to return an error ? */
+ }
+ rv = conn->scard->SCardEndTransaction(conn->cardHandle, SCARD_LEAVE_CARD);
+ conn->inTransaction = 0;
+ if (rv != SCARD_S_SUCCESS) {
+ conn->lastError = rv;
+ return CKYSCARDERR;
+ }
+ return CKYSUCCESS;
+}
+
+CKYStatus
+CKYCardConnection_TransmitAPDU(CKYCardConnection *conn, CKYAPDU *apdu,
+ CKYBuffer *response)
+{
+ CKYStatus ret;
+ unsigned long rv;
+
+ ret = CKYBuffer_Resize(response, CKYAPDU_MAX_LEN);
+ if (ret != CKYSUCCESS) {
+ return ret;
+ }
+
+ if( conn->protocol == SCARD_PROTOCOL_T0 ) {
+ rv = conn->scard->SCardTransmit(conn->cardHandle,
+ conn->scard->SCARD_PCI_T0_,
+ CKYBuffer_Data(&apdu->apduBuf), CKYBuffer_Size(&apdu->apduBuf),
+ NULL, response->data, &response->len);
+ } else {
+ rv = conn->scard->SCardTransmit(conn->cardHandle,
+ conn->scard->SCARD_PCI_T1_,
+ CKYBuffer_Data(&apdu->apduBuf), CKYBuffer_Size(&apdu->apduBuf),
+ NULL, response->data, &response->len);
+ }
+
+ if (rv != SCARD_S_SUCCESS) {
+ conn->lastError =rv;
+ return CKYSCARDERR;
+ }
+
+ return CKYSUCCESS;
+}
+
+CKYStatus
+CKYCardConnection_ExchangeAPDU(CKYCardConnection *conn, CKYAPDU *apdu,
+ CKYBuffer *response)
+{
+ CKYStatus ret;
+ CKYBuffer getResponse;
+ CKYSize size = 0;
+
+ ret = CKYCardConnection_TransmitAPDU(conn, apdu, response);
+ if (ret != CKYSUCCESS) {
+ return ret;
+ }
+ CKYBuffer_InitEmpty(&getResponse);
+
+ /* automatically handle the response data protocol */
+ while ((ret == CKYSUCCESS) &&
+ (size = CKYBuffer_Size(response)) >= 2 &&
+ (CKYBuffer_GetChar(response,size-2) == 0x61)) {
+ /* get the response */
+ CKYAPDU getResponseAPDU;
+
+ CKYBuffer_Zero(&getResponse);
+ CKYAPDU_Init(&getResponseAPDU);
+ CKYAPDU_SetCLA(&getResponseAPDU, 0x00);
+ CKYAPDU_SetINS(&getResponseAPDU, 0xc0);
+ CKYAPDU_SetP1(&getResponseAPDU, 0x00);
+ CKYAPDU_SetP2(&getResponseAPDU, 0x00);
+ CKYAPDU_SetReceiveLen(&getResponseAPDU,
+ CKYBuffer_GetChar(response,size-1));
+ ret = CKYCardConnection_TransmitAPDU(conn, &getResponseAPDU,
+ &getResponse);
+ CKYAPDU_FreeData(&getResponseAPDU);
+ if ((ret == CKYSUCCESS) && (CKYBuffer_Size(&getResponse) >= 2)) {
+ CKYBuffer_Resize(response, size-2);
+ CKYBuffer_AppendCopy(response,&getResponse);
+ }
+ }
+ CKYBuffer_FreeData(&getResponse);
+ return ret;
+}
+
+CKYStatus
+CKYCardConnection_GetStatus(CKYCardConnection *conn,
+ unsigned long *state, CKYBuffer *ATR)
+{
+ unsigned long readerLen = 0;
+ unsigned long protocol;
+ unsigned long rv;
+ CKYSize atrLen;
+ char *readerStr;
+ CKYStatus ret;
+
+
+ /*
+ * Get initial length. We have to do all this because the Muscle
+ * implementation of PCSC requires us to supply a non-NULL argument
+ * for readerName before it will tell us the ATR, which is all we really
+ * care about.
+ */
+ rv = conn->scard->SCardStatus(conn->cardHandle,
+ NULL /*readerName*/, &readerLen, state, &protocol, NULL, &atrLen);
+ if ( rv != SCARD_S_SUCCESS ) {
+ conn->lastError = rv;
+ return CKYSCARDERR;
+ }
+
+ do {
+ if (readerLen < 1 || readerLen > CKY_OUTRAGEOUS_MALLOC_SIZE) {
+ return CKYNOMEM;
+ }
+ /* Mac & Linux return '0' or ATR length, just use the max value */
+ if (atrLen == 0) {
+ atrLen = CKY_MAX_ATR_LEN;
+ }
+ if (atrLen < 1 || atrLen > CKY_OUTRAGEOUS_MALLOC_SIZE) {
+ return CKYNOMEM;
+ }
+ ret = CKYBuffer_Resize(ATR, atrLen);
+ if (ret != CKYSUCCESS) {
+ return ret;
+ }
+ readerStr = NEW(char, readerLen);
+ if (readerStr == NULL) {
+ return CKYNOMEM;
+ }
+
+ rv = conn->scard->SCardStatus(conn->cardHandle, readerStr, &readerLen,
+ state, &protocol, ATR->data, &atrLen);
+ ATR->len = atrLen;
+ free(readerStr);
+ } while (rv == SCARD_E_INSUFFICIENT_BUFFER);
+
+ if (rv != SCARD_S_SUCCESS) {
+ conn->lastError = rv;
+ return CKYSCARDERR;
+ }
+ return CKYSUCCESS;
+}
+
+CKYStatus
+CKYCardConnection_GetAttribute(CKYCardConnection *conn,
+ unsigned long attrID, CKYBuffer *attrBuf)
+{
+#ifdef WIN32
+ unsigned long len = 0;
+ unsigned long rv;
+
+ /*
+ * Get initial length. We have to do all this because the Muscle
+ * implementation of PCSC requires us to supply a non-NULL argument
+ * for readerName before it will tell us the ATR, which is all we really
+ * care about.
+ */
+ rv = conn->scard->SCardGetAttrib(conn->cardHandle, attrID, NULL, &len);
+ if ( rv != SCARD_S_SUCCESS ) {
+ conn->lastError = rv;
+ return CKYSCARDERR;
+ }
+ CKYBuffer_Resize(attrBuf, len);
+
+ rv = conn->scard->SCardGetAttrib(conn->cardHandle, attrID,
+ attrBuf->data, &attrBuf->len);
+ if( rv != SCARD_S_SUCCESS ) {
+ conn->lastError = rv;
+ return CKYSCARDERR;
+ }
+ return CKYSUCCESS;
+#else
+ conn->lastError = -1;
+ return CKYSCARDERR;
+#endif
+}
+
+const CKYCardContext *
+CKYCardConnection_GetContext(const CKYCardConnection *conn)
+{
+ return conn->ctx;
+}
+
+unsigned long
+CKYCardConnection_GetLastError(const CKYCardConnection *conn)
+{
+ return conn->lastError;
+}
diff -up ./esc/src/lib/coolkey/cky_card.h.fix1 ./esc/src/lib/coolkey/cky_card.h
--- ./esc/src/lib/coolkey/cky_card.h.fix1 2018-04-26 11:44:38.439986181 -0700
+++ ./esc/src/lib/coolkey/cky_card.h 2018-04-26 11:44:38.439986181 -0700
@@ -0,0 +1,132 @@
+/* ***** BEGIN COPYRIGHT BLOCK *****
+ * Copyright (C) 2005 Red Hat, Inc.
+ * All rights reserved.
+ *
+ * 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 St, Fifth Floor, Boston, MA 02110-1301 USA
+ * ***** END COPYRIGHT BLOCK ***** */
+
+#ifndef CKY_CARD_H
+#define CKY_CARD_H 1
+
+#include
+
+#include "cky_base.h"
+#include "cky_list.h"
+
+/*
+ * hide the structure of CardConnections and CardContexts
+ */
+typedef struct _CKYCardContext CKYCardContext;
+typedef struct _CKYCardConnection CKYCardConnection;
+
+/*
+ * define CKYReaderNameList, CKYReaderNameIterator, CKYCardConnectionList, and
+ * CKYCardConnectionIterator, and their associated functions.
+ * See cky_list.h for these functions .
+ */
+
+CKYLIST_DECLARE(CKYReaderName, char *)
+CKYLIST_DECLARE(CKYCardConnection, CKYCardConnection *)
+
+CKY_BEGIN_PROTOS
+void CKYReader_Init(SCARD_READERSTATE *reader);
+void CKYReader_FreeData(SCARD_READERSTATE *reader);
+
+/*
+ * "Accessors": for SCARD_READERSTATE structure as a class.
+ * These functions take an SCARD_READERSTATE which can also be referenced
+ * directly.
+ */
+CKYStatus CKYReader_SetReaderName(SCARD_READERSTATE *reader, const char *name);
+const char *CKYReader_GetReaderName(const SCARD_READERSTATE *reader);
+CKYStatus CKYReader_SetKnownState(SCARD_READERSTATE *reader,
+ unsigned long state);
+unsigned long CKYReader_GetKnownState(const SCARD_READERSTATE *reader);
+unsigned long CKYReader_GetEventState(const SCARD_READERSTATE *reader);
+CKYStatus CKYReader_GetATR(const SCARD_READERSTATE *reader, CKYBuffer *buf);
+/* create an array of READERSTATEs from a LIST of Readers */
+SCARD_READERSTATE *CKYReader_CreateArray(const CKYReaderNameList readerNames,
+ unsigned long *readerCount);
+/* frees the reader, then the full array */
+void CKYReader_DestroyArray(SCARD_READERSTATE *reader, unsigned long count);
+/* add more elements to a ReaderState array*/
+CKYStatus
+CKYReader_AppendArray(SCARD_READERSTATE **array, unsigned long arraySize,
+ const char **readerNames, unsigned long numReaderNames);
+
+/*
+ * card contexts wrap Microsoft's SCARDCONTEXT.
+ */
+/* create a new one. SCOPE must be SCOPE_USER */
+CKYCardContext *CKYCardContext_Create(unsigned long scope);
+/* destroy an existing one */
+CKYStatus CKYCardContext_Destroy(CKYCardContext *context);
+/* get the Windows handle associated with this context */
+SCARDCONTEXT CKYCardContext_GetContext(const CKYCardContext *context);
+/* Get a list of the installed readers */
+CKYStatus CKYCardContext_ListReaders(CKYCardContext *context,
+ CKYReaderNameList *readerNames);
+/* get a list of card connections for cards matching our target ATR */
+CKYStatus CKYCardContext_FindCardsByATR(CKYCardContext *context,
+ CKYCardConnectionList *cardList,
+ const CKYBuffer *targetATR);
+/* get a list of readers with attached cards that match our target ATR */
+CKYStatus CKYCardContext_FindReadersByATR(CKYCardContext *context,
+ CKYReaderNameList *readerNames,
+ const CKYBuffer *targetATR);
+/* return if any of the readers in our array has changed in status */
+CKYStatus CKYCardContext_WaitForStatusChange(CKYCardContext *context,
+ SCARD_READERSTATE *readers,
+ unsigned long readerCount,
+ unsigned long timeout);
+/* cancel any current operation (such as wait for status change) on this
+ * context */
+CKYStatus CKYCardContext_Cancel(CKYCardContext *context);
+/* get the last underlying Windows SCARD error */
+unsigned long CKYCardContext_GetLastError(const CKYCardContext *context);
+
+/*
+ * manage the actual connection to a card.
+ */
+/* create a connection. A connection is not associated with a reader
+ * until CKYCardConnection_Connect() is called.
+ */
+CKYCardConnection *CKYCardConnection_Create(const CKYCardContext *context);
+CKYStatus CKYCardConnection_Destroy(CKYCardConnection *connection);
+CKYStatus CKYCardConnection_BeginTransaction(CKYCardConnection *connection);
+CKYStatus CKYCardConnection_EndTransaction(CKYCardConnection *connection);
+CKYStatus CKYCardConnection_TransmitAPDU(CKYCardConnection *connection,
+ CKYAPDU *apdu,
+ CKYBuffer *response);
+CKYStatus CKYCardConnection_ExchangeAPDU(CKYCardConnection *connection,
+ CKYAPDU *apdu,
+ CKYBuffer *response);
+CKYStatus CKYCardConnection_Connect(CKYCardConnection *connection,
+ const char *readerName);
+CKYStatus CKYCardConnection_Disconnect(CKYCardConnection *connection);
+unsigned long CKYCardConnection_GetProtocol(const CKYCardConnection *conn);
+CKYBool CKYCardConnection_IsConnected(const CKYCardConnection *connection);
+CKYStatus CKYCardConnection_Reconnect(CKYCardConnection *connection);
+CKYStatus CKYCardConnection_GetStatus(CKYCardConnection *connection,
+ unsigned long *state, CKYBuffer *ATR);
+CKYStatus CKYCardConnection_GetAttribute(CKYCardConnection *connection,
+ unsigned long attrID, CKYBuffer *attrBuf);
+CKYStatus CKYCardConnection_Reset(CKYCardConnection *connection);
+const CKYCardContext *CKYCardConnection_GetContext(const CKYCardConnection *cxt);
+unsigned long CKYCardConnection_GetLastError(const CKYCardConnection *context);
+
+CKY_END_PROTOS
+
+#endif /* CKY_CARD_H */
diff -up ./esc/src/lib/coolkey/cky_factory.c.fix1 ./esc/src/lib/coolkey/cky_factory.c
--- ./esc/src/lib/coolkey/cky_factory.c.fix1 2018-04-26 11:44:38.439986181 -0700
+++ ./esc/src/lib/coolkey/cky_factory.c 2018-04-26 11:44:38.439986181 -0700
@@ -0,0 +1,885 @@
+/* ***** BEGIN COPYRIGHT BLOCK *****
+ * Copyright (C) 2005 Red Hat, Inc.
+ * All rights reserved.
+ *
+ * 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 St, Fifth Floor, Boston, MA 02110-1301 USA
+ * ***** END COPYRIGHT BLOCK ***** */
+
+#include "string.h"
+#include "cky_base.h"
+#include "cky_factory.h"
+
+/*
+ * special commands can be issued at any time
+ */
+CKYStatus
+CKYAPDUFactory_SelectFile(CKYAPDU *apdu, CKYByte p1, CKYByte p2,
+ const CKYBuffer *AID)
+{
+ CKYAPDU_SetCLA(apdu, CKY_CLASS_ISO7816);
+ CKYAPDU_SetINS(apdu, ISO_INS_SELECT_FILE);
+ CKYAPDU_SetP1(apdu, p1);
+ CKYAPDU_SetP2(apdu, p2);
+ return CKYAPDU_SetSendDataBuffer(apdu, AID);
+}
+
+CKYStatus
+CKYAPDUFactory_SelectCardManager(CKYAPDU *apdu)
+{
+ CKYByte c = 0;
+ CKYAPDU_SetCLA(apdu, CKY_CLASS_ISO7816);
+ CKYAPDU_SetINS(apdu, ISO_INS_SELECT_FILE);
+ CKYAPDU_SetP1(apdu, 0x04);
+ CKYAPDU_SetP2(apdu, 0x00);
+ /* I can't find the documentation for this, but if you pass an empty
+ * AID to SelectFile on the Cyberflex Access 32k, it selects the
+ * CardManager applet. Good thing, because I couldn't find any other
+ * way to accomplish this without knowing the AID of the CardManager. */
+ return CKYAPDU_SetSendData(apdu,&c,0);
+}
+
+/*
+ * card manager commands must be issued with the card manager selected.
+ */
+CKYStatus
+CKYAPDUFactory_GetCPLCData(CKYAPDU *apdu)
+{
+ CKYAPDU_SetCLA(apdu, CKY_CLASS_GLOBAL_PLATFORM);
+ CKYAPDU_SetINS(apdu, ISO_INS_GET_DATA);
+ CKYAPDU_SetP1(apdu, 0x9f);
+ CKYAPDU_SetP2(apdu, 0x7f);
+ return CKYAPDU_SetReceiveLen(apdu, CKY_SIZE_GET_CPLCDATA);
+}
+/*
+ * applet commands must be issued with the appplet selected.
+ */
+CKYStatus
+CKYAPDUFactory_ListKeys(CKYAPDU *apdu, CKYByte sequence)
+{
+ CKYAPDU_SetCLA(apdu, CKY_CLASS_COOLKEY);
+ CKYAPDU_SetINS(apdu, CKY_INS_LIST_KEYS);
+ CKYAPDU_SetP1(apdu, sequence);
+ CKYAPDU_SetP2(apdu, 0x00);
+ return CKYAPDU_SetReceiveLen(apdu, CKY_SIZE_LIST_KEYS);
+}
+
+CKYStatus
+CKYAPDUFactory_ComputeCryptInit(CKYAPDU *apdu, CKYByte keyNumber, CKYByte mode,
+ CKYByte direction, CKYByte location)
+{
+ CKYByte data[5];
+
+ CKYAPDU_SetCLA(apdu, CKY_CLASS_COOLKEY);
+ CKYAPDU_SetINS(apdu, CKY_INS_COMPUTE_CRYPT);
+ CKYAPDU_SetP1(apdu, keyNumber);
+ CKYAPDU_SetP2(apdu, CKY_CIPHER_INIT);
+ data[0] = mode;
+ data[1] = direction;
+ data[2] = location;
+ data[3] = 0; /* future provide for init data */
+ data[4] = 0;
+ return CKYAPDU_SetSendData(apdu, data, sizeof(data));
+}
+
+CKYStatus
+CKYAPDUFactory_ComputeCryptProcess(CKYAPDU *apdu, CKYByte keyNumber,
+ CKYByte location, const CKYBuffer *data)
+{
+ CKYStatus ret;
+ CKYBuffer buf;
+
+ CKYBuffer_InitEmpty(&buf);
+ CKYAPDU_SetCLA(apdu, CKY_CLASS_COOLKEY);
+ CKYAPDU_SetINS(apdu, CKY_INS_COMPUTE_CRYPT);
+ CKYAPDU_SetP1(apdu, keyNumber);
+ CKYAPDU_SetP2(apdu, CKY_CIPHER_PROCESS);
+ if (data) {
+ ret = CKYBuffer_Reserve(&buf, 3);
+ if (ret != CKYSUCCESS) {
+ goto fail;
+ }
+ ret = CKYBuffer_AppendChar(&buf, location);
+ if (ret != CKYSUCCESS) {
+ goto fail;
+ }
+ ret = CKYBuffer_AppendShort(&buf, (unsigned short)CKYBuffer_Size(data));
+ if (ret != CKYSUCCESS) {
+ goto fail;
+ }
+ ret = CKYAPDU_SetSendDataBuffer(apdu, &buf);
+ if (ret != CKYSUCCESS) {
+ goto fail;
+ }
+ ret = CKYAPDU_AppendSendDataBuffer(apdu, data);
+ } else {
+ ret = CKYAPDU_SetSendData(apdu, &location, 1);
+ }
+fail:
+ CKYBuffer_FreeData(&buf);
+ return ret;
+}
+
+
+CKYStatus
+CKYAPDUFactory_ComputeCryptFinal(CKYAPDU *apdu, CKYByte keyNumber,
+ CKYByte location, const CKYBuffer *data, const CKYBuffer *sig)
+{
+ CKYStatus ret;
+ CKYBuffer buf;
+
+ CKYBuffer_InitEmpty(&buf);
+ CKYAPDU_SetCLA(apdu, CKY_CLASS_COOLKEY);
+ CKYAPDU_SetINS(apdu, CKY_INS_COMPUTE_CRYPT);
+ CKYAPDU_SetP1(apdu, keyNumber);
+ CKYAPDU_SetP2(apdu, CKY_CIPHER_FINAL);
+ if (data) {
+ ret = CKYBuffer_Reserve(&buf, 3);
+ if (ret != CKYSUCCESS) {
+ goto fail;
+ }
+ ret = CKYBuffer_AppendChar(&buf, location);
+ if (ret != CKYSUCCESS) {
+ goto fail;
+ }
+ ret = CKYBuffer_AppendShort(&buf, (unsigned short)CKYBuffer_Size(data));
+ if (ret != CKYSUCCESS) {
+ goto fail;
+ }
+ ret = CKYAPDU_SetSendDataBuffer(apdu, &buf);
+ if (ret != CKYSUCCESS) {
+ goto fail;
+ }
+ ret = CKYAPDU_AppendSendDataBuffer(apdu, data);
+ if (ret != CKYSUCCESS) {
+ goto fail;
+ }
+ if (sig) {
+ CKYBuffer_Resize(&buf,2);
+ CKYBuffer_SetShort(&buf, 0, (unsigned short)CKYBuffer_Size(sig));
+ ret = CKYAPDU_AppendSendDataBuffer(apdu, &buf);
+ if (ret != CKYSUCCESS) {
+ goto fail;
+ }
+ ret = CKYAPDU_AppendSendDataBuffer(apdu, sig);
+ }
+ } else {
+ ret = CKYAPDU_SetSendData(apdu, &location, 1);
+ }
+fail:
+ CKYBuffer_FreeData(&buf);
+ return ret;
+}
+
+CKYStatus
+CKYAPDUFactory_ComputeECCKeyAgreementOneStep(CKYAPDU *apdu, CKYByte keyNumber,
+ CKYByte location,
+ const CKYBuffer *publicData, const CKYBuffer *secretKey)
+{
+ CKYStatus ret = CKYINVALIDARGS;
+ CKYSize len;
+ CKYBuffer buf;
+
+ if (!publicData)
+ return ret;
+
+ if (!(len = CKYBuffer_Size(publicData)))
+ return ret;
+
+ CKYAPDU_SetCLA(apdu, CKY_CLASS_COOLKEY);
+ CKYAPDU_SetINS(apdu, CKY_INS_COMPUTE_ECC_KEY_AGREEMENT);
+ CKYAPDU_SetP1(apdu, keyNumber);
+ CKYAPDU_SetP2(apdu, CKY_CIPHER_ONE_STEP);
+
+ CKYBuffer_InitEmpty(&buf);
+
+ ret = CKYBuffer_Reserve(&buf, 3);
+
+ if (ret == CKYSUCCESS)
+ ret = CKYBuffer_AppendChar(&buf, location);
+ if (ret == CKYSUCCESS)
+ ret = CKYBuffer_AppendShort(&buf, (unsigned short)len);
+ if (ret == CKYSUCCESS)
+ ret = CKYAPDU_SetSendDataBuffer(apdu, &buf);
+ if (ret == CKYSUCCESS)
+ ret = CKYAPDU_AppendSendDataBuffer(apdu, publicData);
+ if (ret == CKYSUCCESS && secretKey && 0 < (len = CKYBuffer_Size(secretKey))) {
+ CKYBuffer_Resize(&buf,2);
+ CKYBuffer_SetShort(&buf, 0, (unsigned short)len);
+ ret = CKYAPDU_AppendSendDataBuffer(apdu, &buf);
+ if (ret == CKYSUCCESS)
+ ret = CKYAPDU_AppendSendDataBuffer(apdu, secretKey);
+ }
+ CKYBuffer_FreeData(&buf);
+ return ret;
+}
+
+CKYStatus
+CKYAPDUFactory_ComputeCryptOneStep(CKYAPDU *apdu, CKYByte keyNumber, CKYByte mode,
+ CKYByte direction, CKYByte location,
+ const CKYBuffer *idata, const CKYBuffer *sig)
+{
+ CKYStatus ret = CKYINVALIDARGS;
+ CKYSize len;
+ CKYBuffer buf;
+
+ if (!idata)
+ return ret;
+
+ if (!(len = CKYBuffer_Size(idata)) && location != CKY_DL_OBJECT)
+ return ret;
+
+ CKYAPDU_SetCLA(apdu, CKY_CLASS_COOLKEY);
+ CKYAPDU_SetINS(apdu, CKY_INS_COMPUTE_CRYPT);
+ CKYAPDU_SetP1(apdu, keyNumber);
+ CKYAPDU_SetP2(apdu, CKY_CIPHER_ONE_STEP);
+
+ CKYBuffer_InitEmpty(&buf);
+
+ ret = CKYBuffer_Reserve(&buf, 5);
+ if (ret == CKYSUCCESS)
+ ret = CKYBuffer_AppendChar(&buf, mode);
+ if (ret == CKYSUCCESS)
+ ret = CKYBuffer_AppendChar(&buf, direction);
+ if (ret == CKYSUCCESS)
+ ret = CKYBuffer_AppendChar(&buf, location);
+ if (ret == CKYSUCCESS)
+ ret = CKYBuffer_AppendShort(&buf, (unsigned short)len);
+ if (ret == CKYSUCCESS)
+ ret = CKYAPDU_SetSendDataBuffer(apdu, &buf);
+ if (ret == CKYSUCCESS)
+ ret = CKYAPDU_AppendSendDataBuffer(apdu, idata);
+ if (ret == CKYSUCCESS && sig && 0 < (len = CKYBuffer_Size(sig))) {
+ CKYBuffer_Resize(&buf,2);
+ CKYBuffer_SetShort(&buf, 0, (unsigned short)len);
+ ret = CKYAPDU_AppendSendDataBuffer(apdu, &buf);
+ if (ret == CKYSUCCESS)
+ ret = CKYAPDU_AppendSendDataBuffer(apdu, sig);
+ }
+ CKYBuffer_FreeData(&buf);
+ return ret;
+}
+
+CKYStatus
+CKYAPDUFactory_CreatePIN(CKYAPDU *apdu, CKYByte pinNumber, CKYByte maxAttempts,
+ const char *pinValue)
+{
+ CKYSize len;
+
+ CKYAPDU_SetCLA(apdu, CKY_CLASS_COOLKEY);
+ CKYAPDU_SetINS(apdu, CKY_INS_CREATE_PIN);
+ CKYAPDU_SetP1(apdu, pinNumber);
+ CKYAPDU_SetP2(apdu, maxAttempts);
+ len = strlen(pinValue);
+ return CKYAPDU_SetSendData(apdu, (unsigned char *)pinValue, len);
+}
+
+CKYStatus
+CKYAPDUFactory_VerifyPIN(CKYAPDU *apdu, CKYByte pinNumber, const char *pinValue)
+{
+ CKYSize len;
+
+ CKYAPDU_SetCLA(apdu, CKY_CLASS_COOLKEY);
+ CKYAPDU_SetINS(apdu, CKY_INS_VERIFY_PIN);
+ CKYAPDU_SetP1(apdu, pinNumber);
+ CKYAPDU_SetP2(apdu, 0x00);
+ len = strlen(pinValue);
+ return CKYAPDU_SetSendData(apdu, (unsigned char *)pinValue, len);
+}
+
+CKYStatus
+CKYAPDUFactory_ChangePIN(CKYAPDU *apdu, CKYByte pinNumber, const char *oldPin,
+ const char *newPin)
+{
+ CKYSize oldLen, newLen;
+ CKYBuffer buf;
+ CKYStatus ret;
+
+ CKYAPDU_SetCLA(apdu, CKY_CLASS_COOLKEY);
+ CKYAPDU_SetINS(apdu, CKY_INS_CHANGE_PIN);
+ CKYAPDU_SetP1(apdu, pinNumber);
+ CKYAPDU_SetP2(apdu, 0x00);
+
+ CKYBuffer_InitEmpty(&buf);
+ oldLen = strlen(oldPin);
+ newLen = strlen(newPin);
+ /* optimization, do a single malloc for the whole block */
+ ret = CKYBuffer_Reserve(&buf, oldLen+newLen+4);
+ if (ret != CKYSUCCESS) {
+ goto fail;
+ }
+ ret = CKYBuffer_AppendShort(&buf, (unsigned short)oldLen);
+ if (ret != CKYSUCCESS) {
+ goto fail;
+ }
+ ret = CKYBuffer_AppendData(&buf, (unsigned char *)oldPin, oldLen);
+ if (ret != CKYSUCCESS) {
+ goto fail;
+ }
+ ret = CKYBuffer_AppendShort(&buf, (unsigned short)newLen);
+ if (ret != CKYSUCCESS) {
+ goto fail;
+ }
+ ret = CKYBuffer_AppendData(&buf, (unsigned char *)newPin, newLen);
+ if (ret != CKYSUCCESS) {
+ goto fail;
+ }
+ ret = CKYAPDU_SetSendDataBuffer(apdu, &buf);
+fail:
+ CKYBuffer_FreeData(&buf);
+ return ret;
+}
+
+CKYStatus
+CKYAPDUFactory_ListPINs(CKYAPDU *apdu)
+{
+ CKYAPDU_SetCLA(apdu, CKY_CLASS_COOLKEY);
+ CKYAPDU_SetINS(apdu, CKY_INS_LIST_PINS);
+ CKYAPDU_SetP1(apdu, 0x00);
+ CKYAPDU_SetP2(apdu, 0x00);
+ return CKYAPDU_SetReceiveLen(apdu, CKY_SIZE_LIST_PINS);
+}
+
+CKYStatus
+CKYAPDUFactory_Logout(CKYAPDU *apdu, CKYByte pinNumber)
+{
+ CKYAPDU_SetCLA(apdu, CKY_CLASS_COOLKEY);
+ CKYAPDU_SetINS(apdu, CKY_INS_LOGOUT);
+ CKYAPDU_SetP1(apdu, pinNumber);
+ CKYAPDU_SetP2(apdu, 0x00);
+ return CKYSUCCESS;
+}
+
+CKYStatus
+CKYAPDUFactory_CreateObject(CKYAPDU *apdu, unsigned long objectID, CKYSize size,
+ unsigned short readACL, unsigned short writeACL, unsigned short deleteACL)
+{
+ CKYBuffer buf;
+ CKYStatus ret;
+
+ CKYAPDU_SetCLA(apdu, CKY_CLASS_COOLKEY);
+ CKYAPDU_SetINS(apdu, CKY_INS_CREATE_OBJ);
+ CKYAPDU_SetP1(apdu, 0x00);
+ CKYAPDU_SetP2(apdu, 0x00);
+ CKYBuffer_InitEmpty(&buf);
+ /* optimization, do a single malloc for the whole block */
+ ret = CKYBuffer_Reserve(&buf,0x0e);
+ if (ret != CKYSUCCESS) {
+ goto fail;
+ }
+ ret = CKYBuffer_AppendLong(&buf,objectID);
+ if (ret != CKYSUCCESS) {
+ goto fail;
+ }
+ ret = CKYBuffer_AppendLong(&buf,size);
+ if (ret != CKYSUCCESS) {
+ goto fail;
+ }
+ ret = CKYBuffer_AppendShort(&buf,readACL);
+ if (ret != CKYSUCCESS) {
+ goto fail;
+ }
+ ret = CKYBuffer_AppendShort(&buf,writeACL);
+ if (ret != CKYSUCCESS) {
+ goto fail;
+ }
+ ret = CKYBuffer_AppendShort(&buf,deleteACL);
+ if (ret != CKYSUCCESS) {
+ goto fail;
+ }
+ ret = CKYAPDU_SetSendDataBuffer(apdu, &buf);
+fail:
+ CKYBuffer_FreeData(&buf);
+ return ret;
+
+}
+
+CKYStatus
+CKYAPDUFactory_DeleteObject(CKYAPDU *apdu, unsigned long objectID, CKYByte zero)
+{
+ CKYBuffer buf;
+ CKYStatus ret;
+
+ CKYAPDU_SetCLA(apdu, CKY_CLASS_COOLKEY);
+ CKYAPDU_SetINS(apdu, CKY_INS_DELETE_OBJ);
+ CKYAPDU_SetP1(apdu, zero);
+ CKYAPDU_SetP2(apdu, 0x00);
+ CKYBuffer_InitEmpty(&buf);
+ ret = CKYBuffer_AppendLong(&buf,objectID);
+ if (ret != CKYSUCCESS) {
+ goto fail;
+ }
+ ret = CKYAPDU_SetSendDataBuffer(apdu, &buf);
+fail:
+ CKYBuffer_FreeData(&buf);
+ return ret;
+
+}
+
+CKYStatus
+CKYAPDUFactory_ComputeECCSignatureOneStep(CKYAPDU *apdu, CKYByte keyNumber,
+ CKYByte location,
+ const CKYBuffer *idata, const CKYBuffer *sig)
+{
+ CKYStatus ret = CKYINVALIDARGS;
+ CKYSize len;
+ CKYBuffer buf;
+
+ if (!idata)
+ return ret;
+
+ if (!(len = CKYBuffer_Size(idata)) && location != CKY_DL_OBJECT)
+ return ret;
+
+ CKYAPDU_SetCLA(apdu, CKY_CLASS_COOLKEY);
+ CKYAPDU_SetINS(apdu, CKY_INS_COMPUTE_ECC_SIGNATURE);
+ CKYAPDU_SetP1(apdu, keyNumber);
+ CKYAPDU_SetP2(apdu, CKY_CIPHER_ONE_STEP);
+
+ CKYBuffer_InitEmpty(&buf);
+
+ ret = CKYBuffer_Reserve(&buf, 3);
+
+ if (ret == CKYSUCCESS)
+ ret = CKYBuffer_AppendChar(&buf, location);
+ if (ret == CKYSUCCESS)
+ ret = CKYBuffer_AppendShort(&buf, (unsigned short)len);
+ if (ret == CKYSUCCESS)
+ ret = CKYAPDU_SetSendDataBuffer(apdu, &buf);
+ if (ret == CKYSUCCESS)
+ ret = CKYAPDU_AppendSendDataBuffer(apdu, idata);
+ if (ret == CKYSUCCESS && sig && 0 < (len = CKYBuffer_Size(sig))) {
+ CKYBuffer_Resize(&buf,2);
+ CKYBuffer_SetShort(&buf, 0, (unsigned short)len);
+ ret = CKYAPDU_AppendSendDataBuffer(apdu, &buf);
+ if (ret == CKYSUCCESS)
+ ret = CKYAPDU_AppendSendDataBuffer(apdu, sig);
+ }
+ CKYBuffer_FreeData(&buf);
+ return ret;
+}
+
+CKYStatus
+CKYAPDUFactory_ReadObject(CKYAPDU *apdu, unsigned long objectID,
+ CKYOffset offset, CKYByte size)
+{
+ CKYBuffer buf;
+ CKYStatus ret;
+
+ CKYAPDU_SetCLA(apdu, CKY_CLASS_COOLKEY);
+ CKYAPDU_SetINS(apdu, CKY_INS_READ_OBJ);
+ CKYAPDU_SetP1(apdu, 0x00);
+ CKYAPDU_SetP2(apdu, 0x00);
+ CKYBuffer_InitEmpty(&buf);
+ /* optimization, do a single malloc for the whole block */
+ ret = CKYBuffer_Reserve(&buf,0x09);
+ if (ret != CKYSUCCESS) {
+ goto fail;
+ }
+ ret = CKYBuffer_AppendLong(&buf,objectID);
+ if (ret != CKYSUCCESS) {
+ goto fail;
+ }
+ ret = CKYBuffer_AppendLong(&buf,offset);
+ if (ret != CKYSUCCESS) {
+ goto fail;
+ }
+ ret = CKYBuffer_AppendChar(&buf, size);
+ if (ret != CKYSUCCESS) {
+ goto fail;
+ }
+ ret = CKYAPDU_SetSendDataBuffer(apdu, &buf);
+fail:
+ CKYBuffer_FreeData(&buf);
+ return ret;
+
+}
+
+CKYStatus
+CKYAPDUFactory_WriteObject(CKYAPDU *apdu, unsigned long objectID,
+ CKYOffset offset,CKYSize size,CKYBuffer *data)
+{
+ CKYBuffer buf;
+ CKYStatus ret = CKYSUCCESS;
+ unsigned short dataSize = 0;
+
+ CKYAPDU_SetCLA(apdu, CKY_CLASS_COOLKEY);
+ CKYAPDU_SetINS(apdu, CKY_INS_WRITE_OBJ);
+ CKYAPDU_SetP1(apdu, 0x00);
+ CKYAPDU_SetP2(apdu, 0x00);
+ CKYBuffer_InitEmpty(&buf);
+
+ dataSize = (unsigned short) CKYBuffer_Size(data);
+
+ if(!dataSize) {
+ ret = CKYINVALIDARGS;
+ goto fail;
+ }
+
+ ret = CKYBuffer_AppendLong(&buf,objectID);
+ if (ret != CKYSUCCESS) {
+ goto fail;
+ }
+ ret = CKYBuffer_AppendLong(&buf,offset);
+ if (ret != CKYSUCCESS) {
+ goto fail;
+ }
+ ret = CKYBuffer_AppendChar(&buf, size);
+ if (ret != CKYSUCCESS) {
+ goto fail;
+ }
+
+ ret = CKYAPDU_SetSendDataBuffer(apdu,&buf);
+
+ if (ret != CKYSUCCESS) {
+ goto fail;
+ }
+
+ ret = CKYAPDU_AppendSendDataBuffer(apdu, data);
+
+ if (ret != CKYSUCCESS) {
+ goto fail;
+ }
+
+fail:
+ CKYBuffer_FreeData(&buf);
+ return ret;
+
+}
+
+CKYStatus
+CKYAPDUFactory_ListObjects(CKYAPDU *apdu, CKYByte sequence)
+{
+ CKYAPDU_SetCLA(apdu, CKY_CLASS_COOLKEY);
+ CKYAPDU_SetINS(apdu, CKY_INS_LIST_OBJECTS);
+ CKYAPDU_SetP1(apdu, sequence);
+ CKYAPDU_SetP2(apdu, 0x00);
+ return CKYAPDU_SetReceiveLen(apdu, CKY_SIZE_LIST_OBJECTS);
+}
+
+CKYStatus
+CKYAPDUFactory_GetStatus(CKYAPDU *apdu)
+{
+ CKYAPDU_SetCLA(apdu, CKY_CLASS_COOLKEY);
+ CKYAPDU_SetINS(apdu, CKY_INS_GET_STATUS);
+ CKYAPDU_SetP1(apdu, 0x00);
+ CKYAPDU_SetP2(apdu, 0x00);
+ return CKYAPDU_SetReceiveLen(apdu, CKY_SIZE_GET_STATUS);
+}
+
+CKYStatus
+CKYAPDUFactory_Noop(CKYAPDU *apdu)
+{
+ CKYAPDU_SetCLA(apdu, CKY_CLASS_COOLKEY);
+ CKYAPDU_SetINS(apdu, CKY_INS_NOP);
+ CKYAPDU_SetP1(apdu, 0x00);
+ CKYAPDU_SetP2(apdu, 0x00);
+ return CKYSUCCESS;
+}
+
+CKYStatus
+CKYAPDUFactory_GetBuildID(CKYAPDU *apdu)
+{
+ CKYAPDU_SetCLA(apdu, CKY_CLASS_COOLKEY);
+ CKYAPDU_SetINS(apdu, CKY_INS_GET_BUILDID);
+ CKYAPDU_SetP1(apdu, 0x00);
+ CKYAPDU_SetP2(apdu, 0x00);
+ return CKYAPDU_SetReceiveLen(apdu, CKY_SIZE_GET_BUILDID);
+}
+
+CKYStatus
+CKYAPDUFactory_GetLifeCycle(CKYAPDU *apdu)
+{
+ CKYAPDU_SetCLA(apdu, CKY_CLASS_COOLKEY);
+ CKYAPDU_SetINS(apdu, CKY_INS_GET_LIFECYCLE);
+ CKYAPDU_SetP1(apdu, 0x00);
+ CKYAPDU_SetP2(apdu, 0x00);
+ return CKYAPDU_SetReceiveLen(apdu, CKY_SIZE_GET_LIFE_CYCLE);
+}
+
+CKYStatus
+CKYAPDUFactory_GetLifeCycleV2(CKYAPDU *apdu)
+{
+ CKYAPDU_SetCLA(apdu, CKY_CLASS_COOLKEY);
+ CKYAPDU_SetINS(apdu, CKY_INS_GET_LIFECYCLE);
+ CKYAPDU_SetP1(apdu, 0x00);
+ CKYAPDU_SetP2(apdu, 0x00);
+ return CKYAPDU_SetReceiveLen(apdu, CKY_SIZE_GET_LIFE_CYCLE_V2);
+}
+
+CKYStatus
+CKYAPDUFactory_GetRandom(CKYAPDU *apdu, CKYByte len)
+{
+ CKYAPDU_SetCLA(apdu, CKY_CLASS_COOLKEY);
+ CKYAPDU_SetINS(apdu, CKY_INS_GET_RANDOM);
+ CKYAPDU_SetP1(apdu, 0x00);
+ CKYAPDU_SetP2(apdu, 0x00);
+ return CKYAPDU_SetReceiveLen(apdu, len);
+}
+
+CKYStatus
+CKYAPDUFactory_SeedRandom(CKYAPDU *apdu, const CKYBuffer *data)
+{
+ CKYAPDU_SetCLA(apdu, CKY_CLASS_COOLKEY);
+ CKYAPDU_SetINS(apdu, CKY_INS_SEED_RANDOM);
+ CKYAPDU_SetP1(apdu, 0x00);
+ CKYAPDU_SetP2(apdu, 0x00);
+ return CKYAPDU_SetSendDataBuffer(apdu, data);
+}
+
+CKYStatus
+CKYAPDUFactory_GetIssuerInfo(CKYAPDU *apdu)
+{
+ CKYAPDU_SetCLA(apdu, CKY_CLASS_COOLKEY);
+ CKYAPDU_SetINS(apdu, CKY_INS_GET_ISSUER_INFO);
+ CKYAPDU_SetP1(apdu, 0x00);
+ CKYAPDU_SetP2(apdu, 0x00);
+ return CKYAPDU_SetReceiveLen(apdu, CKY_SIZE_GET_ISSUER_INFO);
+}
+
+CKYStatus
+CKYAPDUFactory_GetBuiltinACL(CKYAPDU *apdu)
+{
+ CKYAPDU_SetCLA(apdu, CKY_CLASS_COOLKEY);
+ CKYAPDU_SetINS(apdu, CKY_INS_GET_BUILTIN_ACL);
+ CKYAPDU_SetP1(apdu, 0x00);
+ CKYAPDU_SetP2(apdu, 0x00);
+ return CKYAPDU_SetReceiveLen(apdu, CKY_SIZE_GET_BUILTIN_ACL);
+}
+
+CKYStatus
+CACAPDUFactory_SignDecrypt(CKYAPDU *apdu, CKYByte type, const CKYBuffer *data)
+{
+ CKYAPDU_SetCLA(apdu, CKY_CLASS_ISO7816);
+ CKYAPDU_SetINS(apdu, CAC_INS_SIGN_DECRYPT);
+ CKYAPDU_SetP1(apdu, type);
+ CKYAPDU_SetP2(apdu, 0x00);
+ return CKYAPDU_SetSendDataBuffer(apdu, data);
+}
+
+CKYStatus
+CACAPDUFactory_GetCertificate(CKYAPDU *apdu, CKYSize size)
+{
+ CKYAPDU_SetCLA(apdu, CKY_CLASS_ISO7816);
+ CKYAPDU_SetINS(apdu, CAC_INS_GET_CERTIFICATE);
+ CKYAPDU_SetP1(apdu, 0x00);
+ CKYAPDU_SetP2(apdu, 0x00);
+ return CKYAPDU_SetReceiveLen(apdu, size);
+}
+
+CKYStatus
+CACAPDUFactory_ReadFile(CKYAPDU *apdu, unsigned short offset,
+ CKYByte type, CKYByte count)
+{
+ CKYStatus ret;
+ CKYBuffer buf;
+
+ CKYBuffer_InitEmpty(&buf);
+ CKYAPDU_SetCLA(apdu, CKY_CLASS_GLOBAL_PLATFORM);
+ CKYAPDU_SetINS(apdu, CAC_INS_READ_FILE);
+ CKYAPDU_SetP1(apdu, (offset >> 8) & 0xff);
+ CKYAPDU_SetP2(apdu, offset & 0xff);
+ ret = CKYBuffer_Reserve(&buf, 2);
+ if (ret != CKYSUCCESS) {
+ goto fail;
+ }
+ ret = CKYBuffer_AppendChar(&buf, type);
+ if (ret != CKYSUCCESS) {
+ goto fail;
+ }
+ ret = CKYBuffer_AppendChar(&buf, count);
+ if (ret != CKYSUCCESS) {
+ goto fail;
+ }
+ ret = CKYAPDU_SetSendDataBuffer(apdu, &buf);
+fail:
+ CKYBuffer_FreeData(&buf);
+ return ret;
+}
+
+CKYStatus
+CACAPDUFactory_GetProperties(CKYAPDU *apdu)
+{
+ CKYAPDU_SetCLA(apdu, CKY_CLASS_ISO7816);
+ CKYAPDU_SetINS(apdu, CAC_INS_GET_PROPERTIES);
+ CKYAPDU_SetP1(apdu, 0x00);
+ CKYAPDU_SetP2(apdu, 0x00);
+ return CKYAPDU_SetReceiveLen(apdu, CAC_SIZE_GET_PROPERTIES);
+}
+
+CKYStatus
+PIVAPDUFactory_SignDecrypt(CKYAPDU *apdu, CKYByte chain, CKYByte alg,
+ CKYByte key, int len, const CKYBuffer *data)
+{
+ CKYStatus ret;
+ CKYAPDU_SetCLA(apdu, chain ? CKY_CLASS_ISO7816_CHAIN :
+ CKY_CLASS_ISO7816);
+ CKYAPDU_SetINS(apdu, PIV_INS_GEN_AUTHENTICATE);
+ CKYAPDU_SetP1(apdu, alg);
+ CKYAPDU_SetP2(apdu, key);
+ ret = CKYAPDU_SetSendDataBuffer(apdu, data);
+ if (ret == CKYSUCCESS && chain == 0 && len != 0) {
+ if (len >= 256) len = 0;
+ ret = CKYAPDU_AppendReceiveLen(apdu, len);
+ }
+ return ret;
+}
+
+CKYStatus
+PIVAPDUFactory_GetData(CKYAPDU *apdu, const CKYBuffer *object, CKYByte count)
+{
+ CKYStatus ret;
+ CKYBuffer buf;
+ CKYByte objectSize;
+
+ CKYBuffer_InitEmpty(&buf);
+ CKYAPDU_SetCLA(apdu, CKY_CLASS_ISO7816);
+ CKYAPDU_SetINS(apdu, 0xcb);
+ CKYAPDU_SetP1(apdu, 0x3f);
+ CKYAPDU_SetP2(apdu, 0xff);
+
+ objectSize = CKYBuffer_Size(object);
+
+ ret = CKYBuffer_Reserve(&buf, 2+objectSize);
+ if (ret != CKYSUCCESS) {
+ goto fail;
+ }
+ ret = CKYBuffer_AppendChar(&buf, 0x5c);
+ if (ret != CKYSUCCESS) {
+ goto fail;
+ }
+ ret = CKYBuffer_AppendChar(&buf, objectSize);
+ if (ret != CKYSUCCESS) {
+ goto fail;
+ }
+ ret = CKYBuffer_AppendCopy(&buf, object);
+ if (ret != CKYSUCCESS) {
+ goto fail;
+ }
+ ret = CKYAPDU_SetSendDataBuffer(apdu, &buf);
+ if (ret != CKYSUCCESS) {
+ goto fail;
+ }
+ ret = CKYAPDU_AppendReceiveLen(apdu, count);
+fail:
+ CKYBuffer_FreeData(&buf);
+ return ret;
+}
+
+CKYStatus
+P15APDUFactory_VerifyPIN(CKYAPDU *apdu, CKYByte keyRef, const CKYBuffer *pin)
+{
+ CKYStatus ret;
+
+ CKYAPDU_SetCLA(apdu, CKY_CLASS_ISO7816);
+ CKYAPDU_SetINS(apdu, CAC_INS_VERIFY_PIN);
+ CKYAPDU_SetP1(apdu, 0x00);
+ CKYAPDU_SetP2(apdu, keyRef);
+ /* no pin, send an empty buffer */
+ if (CKYBuffer_Size(pin) == 0) {
+ return CKYAPDU_SetReceiveLen(apdu, 0);
+ }
+
+ /* all CAC pins are 8 bytes exactly. If to long, truncate it */
+ ret = CKYAPDU_SetSendDataBuffer(apdu, pin);
+ return ret;
+
+}
+
+CKYStatus
+P15APDUFactory_ReadRecord(CKYAPDU *apdu, CKYByte record, CKYByte short_ef,
+ CKYByte flags, CKYByte count)
+{
+ CKYByte control;
+
+ control = (short_ef << 3) & 0xf8;
+ control |= flags & 0x07;
+
+ CKYAPDU_SetCLA(apdu, CKY_CLASS_ISO7816);
+ CKYAPDU_SetINS(apdu, ISO_INS_READ_RECORD);
+ CKYAPDU_SetP1(apdu, record);
+ CKYAPDU_SetP2(apdu, control);
+ return CKYAPDU_SetReceiveLen(apdu, count);
+}
+
+CKYStatus
+P15APDUFactory_ReadBinary(CKYAPDU *apdu, unsigned short offset,
+ CKYByte short_ef, CKYByte flags, CKYByte count)
+{
+ CKYByte p1 = 0,p2 = 0;
+ unsigned short max_offset = 0;
+
+ if (flags & P15_USE_SHORT_EF) {
+ max_offset = 0xff;
+ p1 = P15_USE_SHORT_EF | (short_ef & 0x7);
+ p2 = offset & 0xff;
+ } else {
+ max_offset = 0x7fff;
+ p1 = (offset >> 8) & 0x7f;
+ p2 = offset & 0xff;
+ }
+ if (offset > max_offset) {
+ return CKYINVALIDARGS;
+ }
+
+ CKYAPDU_SetCLA(apdu, CKY_CLASS_ISO7816);
+ CKYAPDU_SetINS(apdu, ISO_INS_READ_BINARY);
+ CKYAPDU_SetP1(apdu, p1);
+ CKYAPDU_SetP2(apdu, p2);
+ return CKYAPDU_SetReceiveLen(apdu, count);
+}
+
+CKYStatus
+P15APDUFactory_ManageSecurityEnvironment(CKYAPDU *apdu, CKYByte p1, CKYByte p2,
+ CKYByte keyRef)
+{
+ CKYByte param[3];
+
+ CKYAPDU_SetCLA(apdu, CKY_CLASS_ISO7816);
+ CKYAPDU_SetINS(apdu, ISO_INS_MANAGE_SECURITY_ENVIRONMENT);
+ CKYAPDU_SetP1(apdu, p1);
+ CKYAPDU_SetP2(apdu, p2);
+ param[0] = 0x83;
+ param[1] = 1;
+ param[2] = keyRef;
+ return CKYAPDU_SetSendData(apdu, param, sizeof param);
+}
+
+CKYStatus
+P15APDUFactory_PerformSecurityOperation(CKYAPDU *apdu, CKYByte dir,
+ int chain, CKYSize retLen, const CKYBuffer *data)
+{
+ CKYByte p1,p2;
+ CKYStatus ret;
+
+ CKYAPDU_SetCLA(apdu, chain ? CKY_CLASS_ISO7816_CHAIN :
+ CKY_CLASS_ISO7816);
+ CKYAPDU_SetINS(apdu, ISO_INS_PERFORM_SECURITY_OPERATION);
+ if (dir == CKY_DIR_DECRYPT) {
+ p1 = ISO_PSO_DECRYPT_P1;
+ p2 = ISO_PSO_DECRYPT_P2;
+ } else {
+ p1 = ISO_PSO_SIGN_P1;
+ p2 = ISO_PSO_SIGN_P2;
+ }
+ CKYAPDU_SetP1(apdu, p1);
+ CKYAPDU_SetP2(apdu, p2);
+ ret = CKYAPDU_SetSendDataBuffer(apdu, data);
+ if (ret == CKYSUCCESS && (chain == 0) && retLen != 0) {
+ ret = CKYAPDU_AppendReceiveLength(apdu, retLen);
+ }
+ return ret;
+}
+
+
diff -up ./esc/src/lib/coolkey/cky_factory.h.fix1 ./esc/src/lib/coolkey/cky_factory.h
--- ./esc/src/lib/coolkey/cky_factory.h.fix1 2018-04-26 11:44:38.442986163 -0700
+++ ./esc/src/lib/coolkey/cky_factory.h 2018-04-26 11:44:38.441986169 -0700
@@ -0,0 +1,294 @@
+/* ***** BEGIN COPYRIGHT BLOCK *****
+ * Copyright (C) 2005 Red Hat, Inc.
+ * All rights reserved.
+ *
+ * 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 St, Fifth Floor, Boston, MA 02110-1301 USA
+ * ***** END COPYRIGHT BLOCK ***** */
+
+#ifndef CKY_FACTORY_H
+#define CKY_FACTORY_H 1
+
+#include "cky_base.h"
+
+/*
+ * Various Class bytes
+ */
+#define CKY_CLASS_ISO7816 0x00
+#define CKY_CLASS_ISO7816_CHAIN 0x10
+#define CKY_CLASS_GLOBAL_PLATFORM 0x80
+#define CKY_CLASS_SECURE 0x84
+#define CKY_CLASS_COOLKEY 0xb0
+
+/*
+ * Applet Instruction Bytes
+ */
+/* Card Manager */
+#define ISO_INS_SELECT_FILE 0xa4
+#define ISO_INS_GET_DATA 0xca
+#define ISO_INS_READ_BINARY 0xb0
+#define ISO_INS_READ_RECORD 0xb2
+#define ISO_INS_MANAGE_SECURITY_ENVIRONMENT 0x22
+#define ISO_INS_PERFORM_SECURITY_OPERATION 0x2a
+
+/* ISO Parameters: */
+#define ISO_LOGIN_LOCAL 0x80
+#define ISO_LOGIN_GLOBAL 0x00
+#define ISO_MSE_SET 0x01
+#define ISO_MSE_STORE 0xf2
+#define ISO_MSE_RESTORE 0xf3
+#define ISO_MSE_ERASE 0xf4
+#define ISO_MSE_QUAL_VERIFY 0x80
+#define ISO_MSE_QUAL_COMPUTE 0x40
+#define ISO_MSE_AUTH 0xa4
+#define ISO_MSE_SIGN 0xb6
+#define ISO_MSE_KEA 0xb8
+#define ISO_PSO_SIGN_P1 0x9e
+#define ISO_PSO_SIGN_P2 0x9a
+#define ISO_PSO_ENCRYPT_P1 0x86
+#define ISO_PSO_ENCRYPT_P2 0x80
+#define ISO_PSO_DECRYPT_P1 0x80
+#define ISO_PSO_DECRYPT_P2 0x86
+
+/* deprecated */
+#define CKY_INS_SETUP 0x2A
+#define CKY_INS_GEN_KEYPAIR 0x30
+#define CKY_INS_EXPORT_KEY 0x34
+#define CKY_INS_UNBLOCK_PIN 0x46
+#define CKY_INS_GET_CHALLENGE 0x62
+#define CKY_INS_CAC_EXT_AUTH 0x38
+#define CKY_INS_LOGOUT_ALL 0x60
+
+/* public */
+#define CKY_INS_VERIFY_PIN 0x42
+#define CKY_INS_LIST_OBJECTS 0x58
+#define CKY_INS_LIST_KEYS 0x3A
+#define CKY_INS_LIST_PINS 0x48
+#define CKY_INS_GET_STATUS 0x3C
+#define CKY_INS_GET_LIFECYCLE 0xF2
+#define CKY_INS_GET_ISSUER_INFO 0xF6
+#define CKY_INS_GET_BUILTIN_ACL 0xFA
+#define CKY_INS_GET_BUILDID 0x70
+#define CKY_INS_GET_RANDOM 0x72
+#define CKY_INS_SEED_RANDOM 0x73
+#define CKY_INS_NOP 0x71
+
+/* nonce validated only */
+#define CKY_INS_LOGOUT 0x61
+
+/* nonce validated & Secure Channel */
+#define CKY_INS_IMPORT_KEY 0x32
+#define CKY_INS_COMPUTE_CRYPT 0x36
+#define CKY_INS_COMPUTE_ECC_SIGNATURE 0x37
+#define CKY_INS_COMPUTE_ECC_KEY_AGREEMENT 0x38
+#define CKY_INS_CREATE_PIN 0x40
+#define CKY_INS_CHANGE_PIN 0x44
+#define CKY_INS_CREATE_OBJ 0x5A
+#define CKY_INS_DELETE_OBJ 0x52
+#define CKY_INS_READ_OBJ 0x56
+#define CKY_INS_WRITE_OBJ 0x54
+
+/* Secure channel only */
+#define CKY_INS_INIT_UPDATE 0x50
+#define CKY_INS_SEC_EXT_AUTH 0x82
+#define CKY_INS_SEC_SET_LIFECYCLE 0xF0
+#define CKY_INS_SEC_SET_PIN 0x04
+#define CKY_INS_SEC_READ_IOBUF 0x08
+#define CKY_INS_SEC_START_ENROLLMENT 0x0C
+
+
+/* CAC */
+#define CAC_INS_GET_CERTIFICATE 0x36
+#define CAC_INS_SIGN_DECRYPT 0x42
+#define CAC_INS_VERIFY_PIN 0x20
+#define CAC_INS_GET_PROPERTIES 0x56
+#define CAC_INS_READ_FILE 0x52
+
+#define CAC_SIZE_GET_PROPERTIES 48
+#define CAC_P1_STEP 0x80
+#define CAC_P1_FINAL 0x00
+
+/* PIV */
+#define PIV_INS_GEN_AUTHENTICATE 0x87
+
+/*
+ * Fixed return sized from various commands
+ */
+#define CKY_SIZE_GET_CPLCDATA 45
+#define CKY_SIZE_LIST_KEYS 11
+#define CKY_SIZE_LIST_PINS 2
+#define CKY_SIZE_LIST_OBJECTS 14
+#define CKY_SIZE_GET_STATUS 16
+#define CKY_SIZE_GET_LIFE_CYCLE 1
+#define CKY_SIZE_GET_LIFE_CYCLE_V2 4
+#define CKY_SIZE_GET_BUILDID 4
+#define CKY_SIZE_GET_ISSUER_INFO 0xe0
+#define CKY_SIZE_GET_BUILTIN_ACL 7
+
+/*
+ * Crypt functions
+ */
+/* functions */
+#define CKY_CIPHER_INIT 1
+#define CKY_CIPHER_PROCESS 2
+#define CKY_CIPHER_FINAL 3
+#define CKY_CIPHER_ONE_STEP 4 /* init and final in one APDU */
+
+/* modes */
+#define CKY_RSA_NO_PAD 0x00
+#define CKY_RSA_PAD_PKCS1 0x01
+#define CKY_DSA_SHA 0x10
+#define CKY_DES_CBC_NOPAD 0x20
+#define CKY_DES_ECB_NOPAD 0x21
+
+/* operations (Cipher Direction) */
+#define CKY_DIR_NONE 0x00
+#define CKY_DIR_SIGN 0x01
+#define CKY_DIR_VERIFY 0x02
+#define CKY_DIR_ENCRYPT 0x03
+#define CKY_DIR_DECRYPT 0x04
+
+/* Data Location */
+#define CKY_DL_APDU 0x01
+#define CKY_DL_OBJECT 0x02
+
+/* Key Types */
+#define CKY_KEY_RSA_PUBLIC 0x01
+#define CKY_KEY_RSA_PRIVATE 0x02
+#define CKY_KEY_RSA_PRIVATE_CRT 0x03
+#define CKY_KEY_DSA_PUBLIC 0x04
+#define CKY_KEY_DSA_PRIVATE 0x05
+#define CKY_KEY_DES 0x06
+#define CKY_KEY_3DES 0x07
+#define CKY_KEY_3DES3 0x08
+
+/* List Operators */
+#define CKY_LIST_RESET 0x00
+#define CKY_LIST_NEXT 0x01
+
+/* Max Size for a read block */
+#define CKY_MAX_READ_CHUNK_SIZE 255
+#define CKY_MAX_WRITE_CHUNK_SIZE 240
+
+/* Life Cycle State */
+#define CKY_APPLICATION_LOGICALLY_DELETED 0x00
+#define CKY_APPLICATION_INSTALLED 0x03
+#define CKY_APPLICATION_SELECTABLE 0x07
+#define CKY_APPLICATION_PERSONALIZED 0x0f
+#define CKY_APPLICATION_BLOCKED 0x7f
+#define CKY_APPLICATION_LOCKED 0xff
+#define CKY_CARDM_MANAGER_OP_READER 0x01
+#define CKY_CARDM_MANAGER_INITIALIZED 0x03
+#define CKY_CARDM_MANAGER_SECURED 0x0f
+#define CKY_CARDM_MANAGER_LOCKED 0x7f
+#define CKY_CARDM_MANAGER_TERMINATED 0xff
+
+/* Read Record Flags */
+#define P15_READ_P1 0x4
+#define P15_READ_P1_TO_LAST 0x5
+#define P15_READ_LAST_TO_P1 0x6
+#define P15_READ_FIRST 0x0
+#define P15_READ_LAST 0x1
+#define P15_READ_NEXT 0x2
+#define P15_READ_PREV 0x3
+
+/* Read Binary Flags */
+#define P15_USE_SHORT_EF 0x80
+
+/*
+ * The following factories 'Fill in' APDUs for each of the
+ * functions described below. Nonces are not automatically added.
+ * APDU's are for COOLKEY version 1.0 protocol. Callers should pass
+ * in Already inited apdu's . Callers are responsible for freeing.
+ * the APDU data, even in event of failure.
+ */
+CKY_BEGIN_PROTOS
+
+/* function based factorys */
+CKYStatus CKYAPDUFactory_SelectFile(CKYAPDU *apdu, CKYByte p1, CKYByte p2,
+ const CKYBuffer *AID);
+CKYStatus CKYAPDUFactory_SelectCardManager(CKYAPDU *apdu);
+CKYStatus CKYAPDUFactory_GetCPLCData(CKYAPDU *apdu);
+CKYStatus CKYAPDUFactory_ListKeys(CKYAPDU *apdu, CKYByte sequence);
+CKYStatus CKYAPDUFactory_ComputeCryptInit(CKYAPDU *apdu, CKYByte keyNumber,
+ CKYByte mode, CKYByte direction, CKYByte location);
+CKYStatus CKYAPDUFactory_ComputeCryptProcess(CKYAPDU *apdu, CKYByte keyNumber,
+ CKYByte location, const CKYBuffer *data);
+CKYStatus CKYAPDUFactory_ComputeCryptFinal(CKYAPDU *apdu, CKYByte keyNumber,
+ CKYByte location, const CKYBuffer *data, const CKYBuffer *sig);
+CKYStatus CKYAPDUFactory_ComputeCryptOneStep(CKYAPDU *apdu, CKYByte keyNumber,
+ CKYByte mode, CKYByte direction, CKYByte location,
+ const CKYBuffer *data, const CKYBuffer *sig);
+CKYStatus CKYAPDUFactory_ComputeECCSignatureOneStep(CKYAPDU *apdu, CKYByte keyNumber,
+ CKYByte location,
+ const CKYBuffer *data, const CKYBuffer *sig);
+CKYStatus CKYAPDUFactory_ComputeECCKeyAgreementOneStep(CKYAPDU *apdu, CKYByte keyNumber,
+ CKYByte location,
+ const CKYBuffer *publicData, const CKYBuffer *secretKey);
+CKYStatus CKYAPDUFactory_CreatePIN(CKYAPDU *apdu, CKYByte pinNumber,
+ CKYByte maxAttempts, const char *pinValue);
+CKYStatus CKYAPDUFactory_VerifyPIN(CKYAPDU *apdu, CKYByte pinNumber,
+ const char *pinValue);
+CKYStatus CKYAPDUFactory_ChangePIN(CKYAPDU *apdu, CKYByte pinNUmber,
+ const char *oldPin, const char *newPin);
+CKYStatus CKYAPDUFactory_ListPINs(CKYAPDU *apdu);
+CKYStatus CKYAPDUFactory_Logout(CKYAPDU *apdu, CKYByte pinNumber);
+CKYStatus CKYAPDUFactory_WriteObject(CKYAPDU *apdu, unsigned long objectID,
+ CKYOffset offset,CKYSize size,CKYBuffer *data);
+/* Future add WriteObject */
+CKYStatus CKYAPDUFactory_CreateObject(CKYAPDU *apdu, unsigned long objectID,
+ CKYSize size, unsigned short readACL, unsigned short writeACL,
+ unsigned short deleteACL);
+CKYStatus CKYAPDUFactory_DeleteObject(CKYAPDU *apdu, unsigned long objectID,
+ CKYByte zero);
+CKYStatus CKYAPDUFactory_ReadObject(CKYAPDU *apdu, unsigned long objectID,
+ CKYOffset offset, CKYByte size);
+CKYStatus CKYAPDUFactory_ListObjects(CKYAPDU *apdu, CKYByte sequence);
+CKYStatus CKYAPDUFactory_GetStatus(CKYAPDU *apdu);
+CKYStatus CKYAPDUFactory_Noop(CKYAPDU *apdu);
+CKYStatus CKYAPDUFactory_GetBuildID(CKYAPDU *apdu);
+CKYStatus CKYAPDUFactory_GetLifeCycle(CKYAPDU *apdu);
+CKYStatus CKYAPDUFactory_GetLifeCycleV2(CKYAPDU *apdu);
+CKYStatus CKYAPDUFactory_GetRandom(CKYAPDU *apdu, CKYByte len);
+CKYStatus CKYAPDUFactory_SeedRandom(CKYAPDU *apdu, const CKYBuffer *data);
+CKYStatus CKYAPDUFactory_GetIssuerInfo(CKYAPDU *apdu);
+CKYStatus CKYAPDUFactory_GetBuiltinACL(CKYAPDU *apdu);
+
+CKYStatus CACAPDUFactory_SignDecrypt(CKYAPDU *apdu, CKYByte type,
+ const CKYBuffer *data);
+CKYStatus CACAPDUFactory_GetCertificate(CKYAPDU *apdu, CKYSize size);
+CKYStatus CACAPDUFactory_ReadFile(CKYAPDU *apdu, unsigned short offset,
+ CKYByte type, CKYByte count);
+CKYStatus CACAPDUFactory_GetProperties(CKYAPDU *apdu);
+
+CKYStatus PIVAPDUFactory_GetData(CKYAPDU *apdu, const CKYBuffer *object,
+ CKYByte count);
+CKYStatus PIVAPDUFactory_SignDecrypt(CKYAPDU *apdu, CKYByte chain, CKYByte alg,
+ CKYByte key, int len, const CKYBuffer *data);
+
+CKYStatus P15APDUFactory_VerifyPIN(CKYAPDU *apdu, CKYByte keyRef,
+ const CKYBuffer *pin);
+CKYStatus P15APDUFactory_ReadRecord(CKYAPDU *apdu, CKYByte record,
+ CKYByte short_ef, CKYByte flags, CKYByte count);
+CKYStatus P15APDUFactory_ReadBinary(CKYAPDU *apdu, unsigned short offset,
+ CKYByte short_ef, CKYByte flags, CKYByte count);
+CKYStatus P15APDUFactory_ManageSecurityEnvironment(CKYAPDU *apdu,
+ CKYByte p1, CKYByte p2, CKYByte key);
+CKYStatus P15APDUFactory_PerformSecurityOperation(CKYAPDU *apdu, CKYByte dir,
+ int chain, CKYSize retLen, const CKYBuffer *data);
+
+
+CKY_END_PROTOS
+
+#endif /* CKY_FACTORY_H */
diff -up ./esc/src/lib/coolkey/cky_list.h.fix1 ./esc/src/lib/coolkey/cky_list.h
--- ./esc/src/lib/coolkey/cky_list.h.fix1 2018-04-26 11:44:38.442986163 -0700
+++ ./esc/src/lib/coolkey/cky_list.h 2018-04-26 11:44:38.442986163 -0700
@@ -0,0 +1,75 @@
+/* ***** BEGIN COPYRIGHT BLOCK *****
+ * Copyright (C) 2005 Red Hat, Inc.
+ * All rights reserved.
+ *
+ * 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 St, Fifth Floor, Boston, MA 02110-1301 USA
+ * ***** END COPYRIGHT BLOCK ***** */
+
+#ifndef CKY_LIST_H
+#define CKY_LIST_H 1
+/*
+ * Macro to declare methods and types for CoolKey Lists.
+ */
+#define CKYLIST_DECLARE(name, type) \
+typedef void *name##List; \
+typedef void *name##Iterator; \
+ \
+CKY_BEGIN_PROTOS \
+/* get the number of elements in the name##List */ \
+unsigned long name##List_GetCount(name##List list); \
+ \
+/* returns the 'index'th element of the list. \
+ * This provides one way of walking the list... \
+ * \
+ * // acquire name##List list \
+ * int count; \
+ * int i; \
+ * \
+ * count = name##List_GetCount(list); \
+ * for (i=0; i < count; i++) { \
+ * const type value = name##List_GetValue(list, i); \
+ * \
+ * // Process value \
+ * } \
+ */ \
+const type name##List_GetValue(name##List list, unsigned long index); \
+ \
+/* * Destroy a list */ \
+void name##List_Destroy(name##List list); \
+ \
+/* \
+ * The following iterators allows someone to easily walk the list using \
+ * the following sample code. These functions hide the underlying \
+ * implementation. \
+ * \
+ * // acquire name##List list \
+ * name##Iterator iter; \
+ * \
+ * for (iter = name##List_GetIterator(list); !name##Iterator_End(inter); \
+ * iter = name##Interator_Next(iter) ) { \
+ * const type value = name##Interator_GetValue(iter); \
+ * \
+ * // Process value \
+ * } \
+ * \
+ */ \
+name##Iterator name##List_GetIterator(name##List list); \
+CKYBool name##Iterator_End(name##Iterator iter); \
+name##Iterator name##Iterator_Next(name##Iterator iter); \
+const type name##Iterator_GetValue(name##Iterator iter); \
+CKY_END_PROTOS \
+/* end of Declarations */
+
+#endif /* CKY_LIST_H */
diff -up ./esc/src/lib/coolkey/cky_list.i.fix1 ./esc/src/lib/coolkey/cky_list.i
--- ./esc/src/lib/coolkey/cky_list.i.fix1 2018-04-26 11:44:38.442986163 -0700
+++ ./esc/src/lib/coolkey/cky_list.i 2018-04-26 11:44:38.442986163 -0700
@@ -0,0 +1,145 @@
+/* ***** BEGIN COPYRIGHT BLOCK *****
+ * Copyright (C) 2005 Red Hat, Inc.
+ * All rights reserved.
+ *
+ * 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 St, Fifth Floor, Boston, MA 02110-1301 USA
+ * ***** END COPYRIGHT BLOCK ***** */
+
+#ifndef CKY_LIST_I
+#define CKY_LIST_I 1
+
+#define CKYLIST_IMPLEMENT(name,type) \
+ \
+/* \
+ * name##List is implemented as a pointer to a NULL terminated array of \
+ * type##s. A NULL name##List is valid and means a list with '0' elements \
+ * The actual type is a void * and the follow functions are designed to \
+ * hide the underlying structure of name##List. \
+ */ \
+ \
+/* get the number of elements in the reader List */ \
+unsigned long \
+name##List_GetCount(name##List list) \
+{ \
+ type *current; \
+ int count; \
+ \
+ if (list == NULL) { \
+ return 0; \
+ } \
+ \
+ for (count=0, current = (type *)list; *current; current++, count++) { \
+ /* EMPTY */ ; \
+ } \
+ \
+ return count; \
+} \
+ \
+ \
+/* returns the 'index'th element of the list. \
+ * index is not checked for overruns in this implementation. \
+ * \
+ * This provides one way of walking the list... \
+ * \
+ * // acquire name##List list \
+ * int count; \
+ * int i; \
+ * \
+ * count = name##List_GetCount(list); \
+ * for (i=0; i < count; i++) { \
+ * const type value = name##List_GetValue(list, i); \
+ * \
+ * // Process value \
+ * } \
+ */ \
+const type \
+name##List_GetValue(name##List list, unsigned long index) \
+{ \
+ type *array = (type *)list; \
+ \
+ /* should probably be an assert */ \
+ if (list == NULL) { \
+ return NULL; \
+ } \
+ return array[index]; \
+} \
+ \
+/* Destroy a list */ \
+void \
+name##List_Destroy(name##List list) \
+{ \
+ type *cur; \
+ if (list == NULL) { \
+ return ; \
+ } \
+ \
+ for (cur =(type *)list; *cur; cur++) { \
+ name##_Destroy(*cur); \
+ } \
+ free(list); \
+} \
+ \
+/* \
+ * The following iterators allows someone to easily walk the list using \
+ * the following sample code. These functions hide the underlying \
+ * implementation. \
+ * \
+ * // acquire name##List list \
+ * name##Iterator iter; \
+ * \
+ * for (iter = name##List_GetIterator(list); !name##Iterator_End(inter); \
+ * iter = name##Iterator_Next(iter) ) { \
+ * const type value = name##Iterator_GetValue(iter); \
+ * // process value \
+ * } \
+ * \
+ */ \
+name##Iterator \
+name##List_GetIterator(name##List list) \
+{ \
+ return (name##Iterator) list; \
+} \
+ \
+CKYBool \
+name##Iterator_End(name##Iterator iter) \
+{ \
+ if (iter == NULL) { \
+ return 1; \
+ } \
+ return *(type *)iter == NULL; \
+} \
+ \
+name##Iterator \
+name##Iterator_Next(name##Iterator iter) \
+{ \
+ if (iter == NULL) { \
+ return NULL; \
+ } \
+ return (name##Iterator) (((type *)iter)+1); \
+} \
+ \
+const type \
+name##Iterator_GetValue(name##Iterator iter) \
+{ \
+ /* assert(iter != NULL); */ \
+ return *(type *)iter; \
+} \
+ \
+/* \
+ * add functions to create lists, & add elements to lists \
+ */ \
+
+
+#endif /* CKY_LIST_I */
diff -up ./esc/src/lib/coolkey/CoolKey.cpp.fix1 ./esc/src/lib/coolkey/CoolKey.cpp
--- ./esc/src/lib/coolkey/CoolKey.cpp.fix1 2017-07-24 16:46:36.000000000 -0700
+++ ./esc/src/lib/coolkey/CoolKey.cpp 2018-04-26 11:44:38.443986158 -0700
@@ -22,8 +22,6 @@
#include "prthread.h"
#include "pk11func.h"
-#include "cky_base.h"
-#include "cky_applet.h"
#include "NSSManager.h"
#include "CoolKeyHandler.h"
@@ -475,6 +473,268 @@ HRESULT CoolKeyNotify(const CoolKey *aKe
return S_OK;
}
+HRESULT CoolKeyGetCUIDDirectly(char *aBuff, int aBuffLen, const char *readerName) {
+
+ CKYBuffer cuid;
+ CKYBuffer_InitEmpty(&cuid);
+ CKYCardConnection *conn = NULL;
+ CKYStatus status;
+ HRESULT result = E_FAIL;
+ CKYCardContext *cardCtxt = NULL;
+ CKYISOStatus apduRC = 0;
+
+ const CKYByte * cuidBytes = NULL;
+
+
+ if ( !aBuff || aBuffLen < 25 || !readerName)
+ {
+ goto done;
+ }
+
+ cardCtxt = CKYCardContext_Create(SCARD_SCOPE_USER);
+ assert(cardCtxt);
+ if (!cardCtxt) {
+ goto done;
+ }
+
+ conn = CKYCardConnection_Create(cardCtxt);
+ assert(conn);
+ if (!conn) {
+ goto done;
+ }
+
+ status = CKYCardConnection_Connect(conn, readerName);
+ if (status != CKYSUCCESS) {
+ goto done;
+ }
+
+ CKYCardConnection_BeginTransaction(conn);
+
+ status = CKYApplet_GetCUID(conn, &cuid, &apduRC);
+ if (status != CKYSUCCESS) {
+ goto done;
+ }
+
+ cuidBytes = CKYBuffer_Data(&cuid);
+
+ result = CoolKeyBinToHex(cuidBytes,
+ CKYBuffer_Size(&cuid),
+ (unsigned char *) aBuff,
+ aBuffLen,
+ 1);
+
+ result = S_OK;
+done:
+
+ if (conn) {
+ CKYCardConnection_EndTransaction(conn);
+ CKYCardConnection_Disconnect(conn);
+ CKYCardConnection_Destroy(conn);
+ }
+ if (cardCtxt) {
+ CKYCardContext_Destroy(cardCtxt);
+ }
+
+ CKYBuffer_FreeData(&cuid);
+
+ return result;
+
+
+}
+
+HRESULT CoolKeyGetATRDirectly(char *aBuff, int aBuffLen,const char *readerName) {
+
+ CKYBuffer ATR;
+ CKYBuffer_InitEmpty(&ATR);
+ CKYCardConnection *conn = NULL;
+ CKYStatus status;
+ HRESULT result = E_FAIL;
+ CKYCardContext *cardCtxt = NULL;
+
+ const CKYByte * atrBytes = NULL;
+
+ if ( !aBuff || aBuffLen < 25 || !readerName)
+ {
+ goto done;
+ }
+
+ cardCtxt = CKYCardContext_Create(SCARD_SCOPE_USER);
+ assert(cardCtxt);
+ if (!cardCtxt) {
+ goto done;
+ }
+
+ conn = CKYCardConnection_Create(cardCtxt);
+ assert(conn);
+ if (!conn) {
+ goto done;
+ }
+
+ status = CKYCardConnection_Connect(conn, readerName);
+ if (status != CKYSUCCESS) {
+ goto done;
+ }
+
+ CKYCardConnection_BeginTransaction(conn);
+ unsigned long state;
+
+ status = CKYCardConnection_GetStatus(conn, &state, &ATR);
+ if (status != CKYSUCCESS) {
+ result = E_FAIL;
+ goto done;
+ }
+
+ atrBytes = CKYBuffer_Data(&ATR);
+
+ result = CoolKeyBinToHex(atrBytes,
+ CKYBuffer_Size(&ATR),
+ (unsigned char *) aBuff,
+ aBuffLen,
+ 1);
+
+
+ if(result != CKYSUCCESS) {
+ goto done;
+ }
+
+ result = S_OK;
+ done:
+
+ if (conn) {
+ CKYCardConnection_EndTransaction(conn);
+ CKYCardConnection_Disconnect(conn);
+ CKYCardConnection_Destroy(conn);
+ }
+ if (cardCtxt) {
+ CKYCardContext_Destroy(cardCtxt);
+ }
+
+ CKYBuffer_FreeData(&ATR);
+
+ return result;
+}
+
+HRESULT CoolKeyGetLifeCycleDirectly(CKYByte *personalized,const char *readerName) {
+ CKYCardConnection *conn = NULL;
+ CKYStatus status;
+ HRESULT result = E_FAIL;
+
+ CKYISOStatus apduRC = 0;
+
+ CKYCardContext *cardCtxt = NULL;
+
+ if ( personalized == NULL || !readerName)
+ {
+ goto done;
+ }
+
+ cardCtxt = CKYCardContext_Create(SCARD_SCOPE_USER);
+ assert(cardCtxt);
+ if (!cardCtxt) {
+ goto done;
+ }
+
+ conn = CKYCardConnection_Create(cardCtxt);
+ assert(conn);
+ if (!conn) {
+ goto done;
+ }
+
+ status = CKYCardConnection_Connect(conn, readerName);
+ if (status != CKYSUCCESS) {
+ goto done;
+ }
+
+ CKYCardConnection_BeginTransaction(conn);
+ unsigned long state;
+ status = CKYApplet_SelectCoolKeyManager(conn, &apduRC);
+ if (status != CKYSUCCESS) {
+ *personalized = 0xff;
+ goto done;
+ }
+
+ //We know we have selected the applet, even if the subsequent
+ // LifeCycle call fails.
+ *personalized = 0x7;
+ status = CKYApplet_GetLifeCycle(conn, personalized,&apduRC);
+
+ if(result != CKYSUCCESS) {
+ goto done;
+ }
+
+ result = S_OK;
+ done:
+
+ if (conn) {
+ CKYCardConnection_EndTransaction(conn);
+ CKYCardConnection_Disconnect(conn);
+ CKYCardConnection_Destroy(conn);
+ }
+ if (cardCtxt) {
+ CKYCardContext_Destroy(cardCtxt);
+ }
+
+ return result;
+}
+
+HRESULT CoolKeyGetCPLCDataDirectly(CKYAppletRespGetCPLCData *cplc,const char *readerName) {
+
+ CKYCardConnection *conn = NULL;
+ CKYStatus status;
+ HRESULT result = E_FAIL;
+ CKYISOStatus apduRC = 0;
+ CKYCardContext *cardCtxt = NULL;
+
+ if ( cplc == NULL || !readerName)
+ {
+ goto done;
+ }
+
+ cardCtxt = CKYCardContext_Create(SCARD_SCOPE_USER);
+ assert(cardCtxt);
+ if (!cardCtxt) {
+ goto done;
+ }
+
+ conn = CKYCardConnection_Create(cardCtxt);
+ assert(conn);
+ if (!conn) {
+ goto done;
+ }
+
+ status = CKYCardConnection_Connect(conn, readerName);
+ if (status != CKYSUCCESS) {
+ goto done;
+ }
+
+ CKYCardConnection_BeginTransaction(conn);
+ unsigned long state;
+
+ status = CKYApplet_SelectCardManager(conn, &apduRC);
+ if (status != CKYSUCCESS) {
+ goto done;
+ }
+
+ status = CKYApplet_GetCPLCData(conn, cplc,
+ &apduRC);
+ if (status != CKYSUCCESS) {
+ goto done;
+ }
+
+ result = S_OK;
+ done:
+
+ if (conn) {
+ CKYCardConnection_EndTransaction(conn);
+ CKYCardConnection_Disconnect(conn);
+ CKYCardConnection_Destroy(conn);
+ }
+ if (cardCtxt) {
+ CKYCardContext_Destroy(cardCtxt);
+ }
+
+ return result;
+}
static std::list g_ActiveKeyList;
diff -up ./esc/src/lib/coolkey/CoolKeyHandler.cpp.fix1 ./esc/src/lib/coolkey/CoolKeyHandler.cpp
--- ./esc/src/lib/coolkey/CoolKeyHandler.cpp.fix1 2017-07-24 16:46:36.000000000 -0700
+++ ./esc/src/lib/coolkey/CoolKeyHandler.cpp 2018-04-26 11:44:38.445986146 -0700
@@ -44,6 +44,8 @@
#include "CoolKeyHandler.h"
#include "SlotUtils.h"
+static const char *cac_manu_id= "Common Access Card";
+static const char *piv_manu_id= "piv II ";
//static char *test_extended_login = "s=325&msg_type=13&invalid_login=0&blocked=0&error=&required_parameter0=id%3DUSER%5FID%26name%3DUser+ID%26desc%3DUser+ID%26type%3Dstring%26option%3Doption1%2Coption2%2Coption3&required_parameter1=id%3DUSER%5FPWD%26name%3DUser+Password%26desc%3DUser+Password%26type%3Dpassword%26option%3D&required_parameter2=id%3DUSER%5FPIN%26name%3DPIN%26desc%3DOne+time+PIN+received+via+mail%26type%3Dpassword%26option%3D";
@@ -1141,12 +1143,10 @@ HRESULT CoolKeyHandler::HttpBeginOpReque
const char *atr = GetATRForKeyID(&mKey);
if (!atr )
{
- HttpDisconnect();
- RemoveKeyFromActiveKeyList(&mKey);
- return E_FAIL;
+ sprintf(buffer,"tokenATR=%s","unknown-atr");
+ } else {
+ sprintf(buffer,"tokenATR=%s",atr);
}
-
- sprintf(buffer,"tokenATR=%s",atr);
ext_buffer = buffer;
@@ -1190,6 +1190,41 @@ HRESULT CoolKeyHandler::HttpBeginOpReque
}
}
+CKYBuffer *CoolKeyHandler::processTokenPDU(CoolKeyHandler *context, CKYAPDU *apdu)
+{
+ char tBuff[56];
+ CKYStatus status = CKYSUCCESS;
+ PR_LOG( coolKeyLogHN, PR_LOG_DEBUG, ("%s CoolKeyHandler::processTokenPDU:\n",GetTStamp(tBuff,56)));
+ if(!apdu || !context)
+ {
+ CoolKeyLogMsg( PR_LOG_ERROR, "%s apdu message. Bad input data. \n",GetTStamp(tBuff,56));
+ return NULL;
+ }
+
+ CKYBuffer *response = NULL;
+ status = CKYBuffer_InitEmpty(response);
+
+ if(status != CKYSUCCESS) {
+ CoolKeyLogMsg( PR_LOG_ERROR, "%s apdu message. Out of memory. \n",GetTStamp(tBuff,56));
+ return NULL;
+ }
+
+ status = CKYCardConnection_ExchangeAPDU(context->GetCardConnection(),
+ apdu, response);
+
+ if (status != CKYSUCCESS) {
+ CoolKeyLogMsg( PR_LOG_ERROR,
+ "%s Processing apdu message. Can't write apdu to card! status %d response[0] %x response[1] %x error %d \n"
+ ,GetTStamp(tBuff,56) ,status,CKYBuffer_GetChar(response,0),CKYBuffer_GetChar(response,1),
+ CKYCardConnection_GetLastError(context->GetCardConnection()));
+
+ return response;
+ }
+
+ return response;
+
+}
+
void CoolKeyHandler::HttpProcessTokenPDU(CoolKeyHandler *context,eCKMessage_TOKEN_PDU_REQUEST *req)
{
char tBuff[56];
@@ -1606,7 +1641,12 @@ void CoolKeyHandler::HttpProcessEndOp(Co
void NotifyEndResult(CoolKeyHandler* context, int operation, int result, int description)
{
char tBuff[56];
- RefreshInfoFlagsForKeyID(context->GetAutoCoolKey());
+
+ CoolKeyInfo *info = GetCoolKeyInfoByKeyID(context->GetAutoCoolKey());
+ CKHGetCoolKeyInfo(info->mSlot,info);
+
+
+ //RefreshInfoFlagsForKeyID(context->GetAutoCoolKey());
PR_LOG( coolKeyLogHN, PR_LOG_DEBUG, ("%s CoolKeyHandler::NotifyEndResult context %p op %d result %d description %d:\n",GetTStamp(tBuff,56),context,operation,result,description));
@@ -2024,14 +2064,14 @@ getCUIDFromTokenInfo(CK_TOKEN_INFO *toke
isxdigit(tokenInfo->manufacturerID[3]) ) {
// one format has top 2 bytes of CUID (4 hex digits) in manufacturer,
// and the rest in the module
- cp = copySerialNumber(cp, (const char *)tokenInfo->manufacturerID, 4);
- cp = copySerialNumber(cp,(const char *)tokenInfo->model,
- sizeof(tokenInfo->model));
+ cp = copySerialNumber(cp, (const char *)tokenInfo->manufacturerID, 2);
+ cp = copySerialNumber(cp,(const char *)tokenInfo->serialNumber,
+ sizeof(tokenInfo->serialNumber));
} else {
// otherwise it's just the concatenation of the model and serial
// fields
cp = copySerialNumber(cp, (const char *)tokenInfo->model,
- sizeof(tokenInfo->model));
+ 2);
cp = copySerialNumber(cp, (const char *)tokenInfo->serialNumber,
sizeof(tokenInfo->serialNumber));
}
@@ -2055,126 +2095,155 @@ CKHGetInfoFlags(PK11SlotInfo *aSlot)
}
CoolKeyInfo *
-CKHGetCoolKeyInfo(PK11SlotInfo *aSlot)
+CKHGetCoolKeyInfo(PK11SlotInfo *aSlot,CoolKeyInfo *currentInfo)
{
char tBuff[56];
PR_LOG( coolKeyLogHN, PR_LOG_DEBUG, ("%s CKHGetCoolKeyInfo:\n",GetTStamp(tBuff,56)));
- PK11GenericObject *obj = NULL;
SECItem label, ATR;
CK_TOKEN_INFO tokenInfo;
CoolKeyInfo *info = NULL;
SECStatus status;
- HRESULT hres;
- int atrSize;
- char *atrString;
- SECItem isCOOLKey;
+ HRESULT hres,atrRes,cuidRes,cycleRes;
+ CKYBuffer cardATR;
+ CKYBuffer_InitEmpty(&cardATR);
+ char *readerName = PK11_GetSlotName(aSlot);
+
memset((void *) &tokenInfo,0,sizeof(tokenInfo));
ATR.data = NULL; // initialize for error processing
label.data = NULL; // initialize for error processing
- isCOOLKey.data = NULL;
int isACOOLKey = 0;
+ int isACAC = 0;
+ int isAPIV = 0;
- /* if it's one of "ours" it'll have a reader object */
- obj = PK11_FindGenericObjects(aSlot, CKO_MOZILLA_READER);
- if (obj == NULL) {
- goto failed;
- }
+ int hasApplet = 0;
+ int isPersonalized = 0;
- // get the reader name (though we probably don't need it anymore
- status = PK11_ReadRawAttribute(PK11_TypeGeneric, obj, CKA_LABEL, &label);
- if (status != SECSuccess) {
- goto failed;
- }
+ CKYByte lifeCycle = 0;
+
+ char atrChar[100];
+ memset((void*) atrChar,0,sizeof(atrChar));
+
+ char cuidChar[100];
+ memset((void*) cuidChar,0 ,sizeof(cuidChar));
- // get the ATR (though, again, we probably don't need it
- status = PK11_ReadRawAttribute(PK11_TypeGeneric, obj, CKA_MOZILLA_ATR, &ATR);
- // PK11_DestroyGenericObjects(obj);
- if (status != SECSuccess) {
- goto failed;
- }
// get the CUID/Serial number (we *WILL* continue to need it )
status = PK11_GetTokenInfo(aSlot,&tokenInfo);
if (status != SECSuccess) {
goto failed;
}
- //get the are we a CoolKey value
+ tokenInfo.flags=0; //Ignore what opensc says, get the info ourselves later.
+ //Get the life cycle state:
- status = PK11_ReadRawAttribute(PK11_TypeGeneric, obj, CKA_MOZILLA_IS_COOL_KEY, &isCOOLKey);
+ cycleRes = CoolKeyGetLifeCycleDirectly(&lifeCycle,readerName);
- PK11_DestroyGenericObjects(obj);
- obj = NULL;
+ if(lifeCycle == 0x7) { // applet only
+ hasApplet = 1;
+ }
- if (status != SECSuccess) {
- goto failed;
+ if(lifeCycle == 0xF) { //personalized
+ hasApplet = 1;
+ isPersonalized = 1;
}
- if(isCOOLKey.len == 1)
- {
- PR_LOG( coolKeyLogHN, PR_LOG_DEBUG, ("%s CKHGetCoolKeyInfo: CKA_MOZILLA_IS_COOL_KEY %d.\n",GetTStamp(tBuff,56),(int) isCOOLKey.data[0]));
+ //Let's see if we can get the ATR by force explicitly
+
+ atrRes = CoolKeyGetATRDirectly(atrChar,100,readerName);
- isACOOLKey=(int) isCOOLKey.data[0];
- }
+ if(atrRes == E_FAIL) {
+ goto failed;
+ }
- PR_LOG( coolKeyLogHN, PR_LOG_DEBUG, ("%s CKHGetCoolKeyInfo: info->flags %u.\n",GetTStamp(tBuff,56),tokenInfo.flags));
-
- PR_LOG( coolKeyLogHN, PR_LOG_DEBUG, ("%s CKHGetCoolKeyInfo: info->label %s.\n",GetTStamp(tBuff,56),(char *)tokenInfo.label));
- PR_LOG( coolKeyLogHN, PR_LOG_DEBUG, ("%s CKHGetCoolKeyInfo: info->manufacturerID %s.\n",GetTStamp(tBuff,56),(char *)tokenInfo.manufacturerID));
- PR_LOG( coolKeyLogHN, PR_LOG_DEBUG, ("%s CKHGetCoolKeyInfo: info->model %s.\n",GetTStamp(tBuff,56),(char *)tokenInfo.model));
- PR_LOG( coolKeyLogHN, PR_LOG_DEBUG, ("%s CKHGetCoolKeyInfo: info->serialNumber %s.\n",GetTStamp(tBuff,56),(char *)tokenInfo.serialNumber));
+ // Figure out the token type by process of elimination
+ // CAC has a manu id of "Common Access Card" and
+ // PIV has a manu id of "piv II "
+
+ // Since we are configured to only be notified of coolkey's, cac's and piv's
+ // non blank coolkeys will be identified by NOT being cac or piv in the manu id field.
+
+ if(!strcmp((const char *) tokenInfo.manufacturerID,cac_manu_id)) {
+ isACAC = 1;
+ } else if(!strcmp((const char *) tokenInfo.manufacturerID, piv_manu_id)) {
+ isAPIV = 1;
+ } else {
+ isACOOLKey = 1;
+ }
- PR_LOG( coolKeyLogHN, PR_LOG_DEBUG, ("%s CKHGetCoolKeyInfo: info->firmwareVersion.major %d info->firmwareVersion.minor %d \n",GetTStamp(tBuff,56),(int)tokenInfo.firmwareVersion.major,(int) tokenInfo.firmwareVersion.minor));
+ // OK, we have everything we need, now build the COOLKEYInfo structure.
+ // either create a new one or use the one we have already and refresh it
+ if(currentInfo == NULL) {
+ info = new CoolKeyInfo();
+ } else {
+ info = currentInfo;
+ if(info->mReaderName) {
+ free(info->mReaderName);
+ }
+ if(info->mCUID) {
+ free(info->mCUID);
+ }
+ if(info->mATR) {
+ free(info->mATR);
+ }
+ info->mInfoFlags = 0;
+ }
- // OK, we have everything we need, now build the COOLKEYInfo structure.
- info = new CoolKeyInfo();
if (!info) {
goto failed;
}
- atrSize = ATR.len*2+5;
- atrString = (char *)malloc(atrSize);
- hres = CoolKeyBinToHex(ATR.data, ATR.len,
- (unsigned char *) atrString, atrSize, true);
- /* shouldn't the be != S_SUCCESS? */
- if (hres == E_FAIL) {
- free(atrString);
- goto failed;
+ //Massage the tokenInfo so it adhered to when coolkey was doing it.
+ if(hasApplet) {
+ tokenInfo.firmwareVersion.major = 1;
}
- SECITEM_FreeItem(&ATR,PR_FALSE);
- ATR.data = NULL;
+ if(isPersonalized) {
+ tokenInfo.flags |= CKF_TOKEN_INITIALIZED;
+ }
- PR_LOG( coolKeyLogHN, PR_LOG_DEBUG, ("%s CKHGetCoolKeyInfo: info->atr %s.\n",GetTStamp(tBuff,56),(char *)atrString));
+ info->mInfoFlags = MapGetFlags(&tokenInfo);
+ info->mReaderName = strdup(readerName);
- info->mATR = atrString;
- info->mReaderName= (char *)malloc(label.len+1);
- if (!info->mReaderName) {
- goto failed;
+ info->mCUID = (char *)malloc(35); /* should be a define ! */
+
+ if(strlen(atrChar) > 0) {
+ info->mATR = strdup(atrChar);
}
- memcpy(info->mReaderName, label.data, label.len);
- info->mReaderName[label.len] = 0;
- info->mInfoFlags = MapGetFlags(&tokenInfo);
- info->mCUID = (char *)malloc(35); /* should be a define ! */
if (!info->mCUID) {
goto failed;
}
+
hres = getCUIDFromTokenInfo(&tokenInfo, info->mCUID);
/* shouldn't the be != S_SUCCESS? */
if (hres == E_FAIL) {
goto failed;
}
+ //Check for blank cuid and put something there
+
+ if(isACOOLKey && strlen(info->mCUID) == 0 )
+ {
+ //Let's try to get the cuid directly from the token.
+
+ cuidRes = CoolKeyGetCUIDDirectly(cuidChar, 100, readerName);
+
+ if(cuidRes != S_OK) {
+ strcpy(info->mCUID, "blank-token");
+ } else {
+ strcpy(info->mCUID, cuidChar);
+ }
+ }
+
PR_LOG( coolKeyLogHN, PR_LOG_DEBUG, ("%s CKHGetCoolKeyInfo: tokenInfo.label length %d.\n",GetTStamp(tBuff,56),strlen((char *) tokenInfo.label)));
// Give the CAC card some sort of unique key ID
- if(strlen(info->mCUID) == 0)
+ if(isACAC && strlen(info->mCUID) == 0)
{
strncpy(info->mCUID,(char *)tokenInfo.label,35);
info->mCUID[34] = 0;
@@ -2186,26 +2255,20 @@ CKHGetCoolKeyInfo(PK11SlotInfo *aSlot)
info->mInfoFlags |= COOLKEY_INFO_IS_REALLY_A_COOLKEY_MASK;
}
- SECITEM_FreeItem(&ATR,PR_FALSE);
SECITEM_FreeItem(&label,PR_FALSE);
- SECITEM_FreeItem(&isCOOLKey,PR_FALSE);
info->mSlot = PK11_ReferenceSlot(aSlot);
info->mSeries = PK11_GetSlotSeries(aSlot);
return info;
failed:
- if (ATR.data) {
- SECITEM_FreeItem(&ATR,PR_FALSE);
- }
if (label.data) {
SECITEM_FreeItem(&label,PR_FALSE);
}
- if (obj) {
- PK11_DestroyGenericObjects(obj);
- }
if (info) {
delete info;
}
+
+ CKYBuffer_FreeData(&cardATR);
return NULL;
}
diff -up ./esc/src/lib/coolkey/CoolKeyHandler.h.fix1 ./esc/src/lib/coolkey/CoolKeyHandler.h
--- ./esc/src/lib/coolkey/CoolKeyHandler.h.fix1 2017-07-24 16:46:36.000000000 -0700
+++ ./esc/src/lib/coolkey/CoolKeyHandler.h 2018-04-26 11:44:38.445986146 -0700
@@ -115,7 +115,10 @@ class CoolKeyHandler
HRESULT Renew(void);
HRESULT Format(const char *aTokenType);
HRESULT Disconnect();
-
+
+ //APDU related
+
+ CKYBuffer *processTokenPDU(CoolKeyHandler *context, CKYAPDU *apdu);
//Http Related
@@ -259,7 +262,7 @@ eCKMessage *AllocateMessage(eCKMessage::
void DisplayEndDialog(int operation, int result, int description);
-CoolKeyInfo *CKHGetCoolKeyInfo(PK11SlotInfo *aSlot);
+CoolKeyInfo *CKHGetCoolKeyInfo(PK11SlotInfo *aSlot,CoolKeyInfo *currentInfo);
unsigned int CKHGetInfoFlags(PK11SlotInfo *aSlot);
#endif /* CoolKeyHandler.h__ */
diff -up ./esc/src/lib/coolkey/CoolKey.h.fix1 ./esc/src/lib/coolkey/CoolKey.h
--- ./esc/src/lib/coolkey/CoolKey.h.fix1 2017-07-24 16:46:36.000000000 -0700
+++ ./esc/src/lib/coolkey/CoolKey.h 2018-04-26 11:44:38.446986140 -0700
@@ -32,6 +32,9 @@
#include
#include
+#include "cky_base.h"
+#include "cky_applet.h"
+
////////////////////////////////////////////////////////////////////////
//
// Public Structures and Functions:
@@ -185,7 +188,6 @@ COOLKEY_API HRESULT CoolKeyInitializeLog
COOLKEY_API HRESULT CoolKeyLogMsg(int logLevel, const char *fmt, ...);
COOLKEY_API HRESULT CoolKeyLogNSSStatus();
-
//Utility time function
char *GetTStamp(char *aTime,int aSize);
}
@@ -262,8 +264,10 @@ const char *CoolKeyGetKeyID(const char *
const char *CoolKeyGetConfig(const char *aName);
HRESULT CoolKeySetConfig(const char *aName,const char *aValue);
CoolKeyBadCertHandler CoolKeyGetBadCertHandler();
-
-
+HRESULT CoolKeyGetATRDirectly(char *aBuff, int aBuffLen, const char *readerName);
+HRESULT CoolKeyGetCUIDDirectly(char *aBuff, int aBuffLen, const char *readerName);
+HRESULT CoolKeyGetCPLCDataDirectly(CKYAppletRespGetCPLCData *cplc,const char *readerName);
+HRESULT CoolKeyGetLifeCycleDirectly(CKYByte *personalized,const char *readerName);
}
diff -up ./esc/src/lib/coolkey/CoolKey_Message.cpp.fix1 ./esc/src/lib/coolkey/CoolKey_Message.cpp
--- ./esc/src/lib/coolkey/CoolKey_Message.cpp.fix1 2017-07-24 16:46:36.000000000 -0700
+++ ./esc/src/lib/coolkey/CoolKey_Message.cpp 2018-04-26 11:44:38.446986140 -0700
@@ -941,7 +941,7 @@ void eCKMessage_BEGIN_OP::encode(string
int size = extensions.length();
- if(aOutputVal[size -1 ] == '&')
+ if(extensions[size -1 ] == '&')
{
extensions.erase(size -1);
}
diff -up ./esc/src/lib/coolkey/dynlink.c.fix1 ./esc/src/lib/coolkey/dynlink.c
--- ./esc/src/lib/coolkey/dynlink.c.fix1 2018-04-26 11:44:38.447986134 -0700
+++ ./esc/src/lib/coolkey/dynlink.c 2018-04-26 11:44:38.447986134 -0700
@@ -0,0 +1,37 @@
+/* ***** BEGIN COPYRIGHT BLOCK *****
+ * Copyright (C) 2005 Red Hat, Inc.
+ * All rights reserved.
+ *
+ * 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 St, Fifth Floor, Boston, MA 02110-1301 USA
+ * ***** END COPYRIGHT BLOCK ***** */
+
+#ifdef HAVE_CONFIG_H
+#include
+#endif
+
+#ifdef WIN32
+#include "dynlink_win.c"
+#else
+#ifdef MAC
+#include "dynlink_mac.c"
+#else
+#ifdef HAVE_DLFCN_H
+#include "dynlink_unix.c"
+#else
+#error "Platform not supported... add dynlink_PLAT.c and update dynlink.c"
+#endif
+#endif
+#endif
+
diff -up ./esc/src/lib/coolkey/dynlink.h.fix1 ./esc/src/lib/coolkey/dynlink.h
--- ./esc/src/lib/coolkey/dynlink.h.fix1 2018-04-26 11:44:38.447986134 -0700
+++ ./esc/src/lib/coolkey/dynlink.h 2018-04-26 11:44:38.447986134 -0700
@@ -0,0 +1,54 @@
+/* ***** BEGIN COPYRIGHT BLOCK *****
+ * Copyright (C) 2005 Red Hat, Inc.
+ * All rights reserved.
+ *
+ * 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 St, Fifth Floor, Boston, MA 02110-1301 USA
+ * ***** END COPYRIGHT BLOCK ***** */
+
+/*
+ * the following header file is private to the CoolKey library.
+ * This is because CoolKey library is supposed to operate in the PKCS #11
+ * module which needs to be independent of runtimes like NSPR. Longer term
+ * there should be a generic version of this which uses the application
+ * runtime, and pkcs #11 supplies it's only copy of these functions.
+ */
+#ifndef CKY_SHLIB_H
+#define CKY_SHLIB_H 1
+
+#undef QUOTE
+#undef QUOTE_MACRO
+#define QUOTE(arg) #arg
+#define QUOTE_MACRO(arg) QUOTE(arg)
+
+/* Hmmm maybe this should be hidden in getAddress? */
+#ifdef MAC
+#define DLL_SYM_PREFIX "_"
+#else
+#define DLL_SYM_PREFIX
+#endif
+
+#define MAKE_DLL_SYMBOL(name) DLL_SYM_PREFIX QUOTE(name)
+
+typedef void *ckyShLibrary;
+
+ckyShLibrary ckyShLibrary_open(const char *libname);
+CKYStatus ckyShLibrary_close(ckyShLibrary libHandle);
+CKYStatus ckyShLibrary_getAddress(ckyShLibrary libHandle,
+ void **func, const char *funcName);
+
+#ifdef MAC
+void ckyShLibrary_setParent(char *name);
+#endif
+#endif
diff -up ./esc/src/lib/coolkey/dynlink_mac.c.fix1 ./esc/src/lib/coolkey/dynlink_mac.c
--- ./esc/src/lib/coolkey/dynlink_mac.c.fix1 2018-04-26 11:44:38.447986134 -0700
+++ ./esc/src/lib/coolkey/dynlink_mac.c 2018-04-26 11:44:38.447986134 -0700
@@ -0,0 +1,147 @@
+/* ***** BEGIN COPYRIGHT BLOCK *****
+ * Copyright (C) 2005 Red Hat, Inc.
+ * All rights reserved.
+ *
+ * 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 St, Fifth Floor, Boston, MA 02110-1301 USA
+ ***** END COPYRIGHT BLOCK *****/
+
+#include
+#include
+#include "cky_base.h"
+#include "dynlink.h"
+#include "string.h"
+#include "stdlib.h"
+
+#define EXEPATH "@executable_path/"
+#define SYSPATH "/System/Library/Frameworks/"
+
+static char *ckyShLibrary_parent = NULL;
+
+/* allow the parent library to set our name */
+void
+ckyShLibrary_setParent(char *p)
+{
+ ckyShLibrary_parent = p;
+}
+
+#ifdef nodef
+/* get the parent librarie's path */
+char *
+ckyShLibrary_getParentPath()
+{
+ char *result;
+ char *image_name;
+ int i, count = _dyld_image_count();
+
+ if (ckyShLibrary_parent == NULL) {
+ return NULL;
+ }
+
+ for (i = 0; i < count; i++) {
+ image_name = _dyld_get_image_name(i);
+ if (strstr(image_name, ckyShLibrary_parent) != NULL) {
+ result = malloc(strlen(image_name)+1);
+ if (result != NULL) {
+ char *truncate;
+ strcpy(result, image_name);
+ truncate = strrchr(result,'/');
+ if (truncate) {
+ *(truncate+1) = 0;
+ }
+ }
+ return result;
+ }
+ }
+ return NULL;
+}
+#endif
+
+ckyShLibrary
+ckyShLibrary_open(const char *libname)
+{
+ const struct mach_header *library;
+ /*char *parentPath = ckyShLibrary_getParentPath(); */
+ char *libPath = NULL;
+ int len = sizeof(SYSPATH);
+
+#ifdef notdef
+ if (parentPath) {
+ int pLen = strlen(parentPath)+1;
+ if (pLen > len) {
+ len = pLen;
+ }
+ }
+#endif
+
+ libPath = malloc(len+strlen(libname)+1);
+ /* if we couldn't get the space, just use the LD_LIBPATH */
+ if (libPath) {
+#ifdef notdef
+ /* first try the parent DLL path if known */
+ if (parentPath) {
+ /* then try the path of the shared library */
+ strcpy(libPath,parentPath);
+ strcat(libPath,libname);
+ free(parentPath);
+ library = NSAddImage(libPath,
+ NSADDIMAGE_OPTION_RETURN_ON_ERROR |
+ NSADDIMAGE_OPTION_WITH_SEARCHING);
+ if (library) {
+ free(libPath);
+ return (ckyShLibrary)library;
+ }
+ }
+#endif
+ /* the try the executable's lib path */
+ strcpy(libPath,SYSPATH);
+ strcat(libPath,libname);
+ library = NSAddImage(libPath,
+ NSADDIMAGE_OPTION_RETURN_ON_ERROR |
+ NSADDIMAGE_OPTION_WITH_SEARCHING);
+ free(libPath);
+ if (library) {
+ return (ckyShLibrary)library;
+ }
+ }
+
+ /* finally grab it from the system libpath */
+ library = NSAddImage(libname,
+ NSADDIMAGE_OPTION_RETURN_ON_ERROR |
+ NSADDIMAGE_OPTION_WITH_SEARCHING);
+ return (ckyShLibrary)library;
+}
+
+CKYStatus
+ckyShLibrary_close(ckyShLibrary _lib)
+{
+ // Can't unload an image on Mac OS X.
+ return CKYSUCCESS;
+}
+
+CKYStatus
+ckyShLibrary_getAddress(const ckyShLibrary _lib, void ** func,
+ const char *funcName)
+{
+ const struct mach_header *library = (const struct mach_header *)_lib;
+ NSSymbol symbol;
+ symbol = NSLookupSymbolInImage(library, funcName,
+ NSLOOKUPSYMBOLINIMAGE_OPTION_BIND |
+ NSLOOKUPSYMBOLINIMAGE_OPTION_RETURN_ON_ERROR);
+ if( symbol == NULL ) {
+ return CKYLIBFAIL;
+ }
+ *func = NSAddressOfSymbol(symbol);
+ return CKYSUCCESS;
+}
diff -up ./esc/src/lib/coolkey/dynlink_unix.c.fix1 ./esc/src/lib/coolkey/dynlink_unix.c
--- ./esc/src/lib/coolkey/dynlink_unix.c.fix1 2018-04-26 11:44:38.447986134 -0700
+++ ./esc/src/lib/coolkey/dynlink_unix.c 2018-04-26 11:44:38.447986134 -0700
@@ -0,0 +1,66 @@
+/* ***** BEGIN COPYRIGHT BLOCK *****
+ * Copyright (C) 2005 Red Hat, Inc.
+ * All rights reserved.
+ *
+ * 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 St, Fifth Floor, Boston, MA 02110-1301 USA
+ * ***** END COPYRIGHT BLOCK ***** */
+
+#include
+#include
+#if !defined(MAC) && !defined(HPUX)
+#include
+#endif
+#include
+
+#include "cky_base.h"
+#include "dynlink.h"
+
+ckyShLibrary
+ckyShLibrary_open(const char *libname)
+{
+ void *library;
+
+ library = dlopen(libname, RTLD_LAZY);
+ return library;
+}
+
+CKYStatus
+ckyShLibrary_close(ckyShLibrary library)
+{
+ int rv;
+
+ if (library == NULL) {
+ return CKYSUCCESS;
+ }
+
+ rv = dlclose(library);
+ if( rv != 0 ) {
+ return CKYLIBFAIL;
+ }
+ return CKYSUCCESS;
+}
+
+CKYStatus
+ckyShLibrary_getAddress(const ckyShLibrary library, void **func,
+ const char *funcName)
+{
+ assert(library);
+ void* f = dlsym(library, funcName);
+ if( f == NULL ) {
+ return CKYLIBFAIL;
+ }
+ *func = f;
+ return CKYSUCCESS;
+}
diff -up ./esc/src/lib/coolkey/dynlink_win.c.fix1 ./esc/src/lib/coolkey/dynlink_win.c
--- ./esc/src/lib/coolkey/dynlink_win.c.fix1 2018-04-26 11:44:38.447986134 -0700
+++ ./esc/src/lib/coolkey/dynlink_win.c 2018-04-26 11:44:38.447986134 -0700
@@ -0,0 +1,66 @@
+/* ***** BEGIN COPYRIGHT BLOCK *****
+ * Copyright (C) 2005 Red Hat, Inc.
+ * All rights reserved.
+ *
+ * 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 St, Fifth Floor, Boston, MA 02110-1301 USA
+ * ***** END COPYRIGHT BLOCK ***** */
+
+#include
+#include "cky_base.h"
+#include "dynlink.h"
+
+
+ckyShLibrary
+ckyShLibrary_open(const char *libname)
+{
+ HMODULE library;
+ library = LoadLibrary(libname);
+
+ return (ckyShLibrary) library;
+}
+
+CKYStatus
+ckyShLibrary_close(ckyShLibrary _lib)
+{
+ HMODULE library = (HMODULE) _lib;
+ BOOL ret;
+
+ if( library == NULL ) {
+ return CKYSUCCESS;
+ }
+
+ ret = FreeLibrary(library);
+ library = NULL;
+
+ if (!ret) {
+ return CKYLIBFAIL;
+ }
+
+ return CKYSUCCESS;
+}
+
+CKYStatus
+ckyShLibrary_getAddress(const ckyShLibrary _lib, void **func,
+ const char *funcName)
+{
+ const HMODULE library = (const HMODULE) _lib;
+
+ *func = (void *)GetProcAddress(library, funcName);
+ if (*func == NULL) {
+ return CKYLIBFAIL;
+ }
+
+ return CKYSUCCESS;
+}
diff -up ./esc/src/lib/coolkey/manifest.mn.fix1 ./esc/src/lib/coolkey/manifest.mn
--- ./esc/src/lib/coolkey/manifest.mn.fix1 2017-07-24 16:46:36.000000000 -0700
+++ ./esc/src/lib/coolkey/manifest.mn 2018-04-26 11:44:38.448986129 -0700
@@ -22,14 +22,13 @@ XULRUNNER_BASE=$(CORE_DEPTH)/dist/$(OBJD
SYS_INC = /usr/include
MODULE = ckymanager
LIBRARY_NAME = $(MODULE)
-REQUIRES = httpchunked nss nspr ckyapplet
+REQUIRES = httpchunked nss nspr
ifndef MOZ_OFFSET
MOZ_OFFSET = mozilla-1.7.13
endif
DEFINES += -I$(CORE_DEPTH)/esc/app/xpcom -I$(SYS_INC)/nspr4 -I$(SYS_INC)/nss3 -I$(SYS_INC)/PCSC -I$(SYS_INC)/$(MOZ_OFFSET)/nspr -I$(SYS_INC)/$(MOZ_OFFSET)/nss -I$(XULRUNNER_BASE)/dist/public/nss -I$(XULRUNNER_BASE)/dist/include/nspr -I$(GECKO_SDK_PATH)/include/nspr -I$(GECKO_SDK_PATH)/include/nss -fno-strict-aliasing
MAPFILE = $(OBJDIR)/ckymanager.def
-#EXTRA_LIBS += -L$(DIST)/lib -lckyapplet
CPPSRCS = \
NSSManager.cpp \
@@ -39,7 +38,13 @@ CPPSRCS = \
CoolKey.cpp \
SmartCardMonitoringThread.cpp \
$(NULL)
-
+CSRCS =\
+ cky_applet.c \
+ cky_base.c \
+ cky_card.c \
+ cky_factory.c \
+ dynlink_unix.c \
+ $(NULL)
EXPORTS = \
CoolKey.h \
$(NULL)
diff -up ./esc/src/lib/coolkey/NSSManager.cpp.fix1 ./esc/src/lib/coolkey/NSSManager.cpp
--- ./esc/src/lib/coolkey/NSSManager.cpp.fix1 2017-07-24 16:46:36.000000000 -0700
+++ ./esc/src/lib/coolkey/NSSManager.cpp 2018-04-26 11:44:38.448986129 -0700
@@ -102,7 +102,7 @@ HRESULT NSSManager::InitNSS(const char *
char modSpec[512];
- sprintf(modSpec,"library=\"%s\" name=\"%s\" parameters=\"%s\" NSS=\"slotParams={0x00000002=[slotFlags='PublicCerts']}\"\n",COOLKEY_PKCS11_LIBRARY,COOLKEY_NAME,PROMISCUOUS_PARAMETER);
+ sprintf(modSpec,"library=\"%s\" name=\"%s\" NSS=\"slotParams={0x00000002=[slotFlags='PublicCerts']}\"\n",COOLKEY_PKCS11_LIBRARY,COOLKEY_NAME,PROMISCUOUS_PARAMETER);
PR_LOG( coolKeyLogNSS, PR_LOG_DEBUG, ("%s InitNSS: modSpec %s\n",GetTStamp(tBuff,56),modSpec));
diff -up ./esc/src/lib/coolkey/NSSManager.h.fix1 ./esc/src/lib/coolkey/NSSManager.h
--- ./esc/src/lib/coolkey/NSSManager.h.fix1 2017-07-24 16:46:36.000000000 -0700
+++ ./esc/src/lib/coolkey/NSSManager.h 2018-04-26 11:44:38.458986071 -0700
@@ -18,7 +18,7 @@
#ifdef DARWIN
#define COOLKEY_PKCS11_LIBRARY "/Library/Application Support/CoolKey/PKCS11/libcoolkeypk11.dylib"
#else
-#define COOLKEY_PKCS11_LIBRARY DLL_PREFIX"coolkeypk11."DLL_SUFFIX
+#define COOLKEY_PKCS11_LIBRARY "onepin-opensc-pkcs11."DLL_SUFFIX
#endif
#define COOLKEY_NAME "COOL Key Module"
diff -up ./esc/src/lib/coolkey/SmartCardMonitoringThread.cpp.fix1 ./esc/src/lib/coolkey/SmartCardMonitoringThread.cpp
--- ./esc/src/lib/coolkey/SmartCardMonitoringThread.cpp.fix1 2017-07-24 16:46:36.000000000 -0700
+++ ./esc/src/lib/coolkey/SmartCardMonitoringThread.cpp 2018-04-26 11:44:38.460986059 -0700
@@ -81,7 +81,7 @@ void SmartCardMonitoringThread::Insert(P
PR_LOG( coolKeyLogSC, PR_LOG_DEBUG,
("%s SmartCardMonitoringThread::Insert Key. \n",GetTStamp(tBuff,56)));
- CoolKeyInfo *info = CKHGetCoolKeyInfo(aSlot);
+ CoolKeyInfo *info = CKHGetCoolKeyInfo(aSlot,NULL);
if (info) {
if (!InsertCoolKeyInfoIntoCoolKeyList(info)) {
AutoCoolKey key(eCKType_CoolKey, info->mCUID);
diff -up ./esc/src/lib/NssHttpClient/manifest.mn.fix1 ./esc/src/lib/NssHttpClient/manifest.mn
--- ./esc/src/lib/NssHttpClient/manifest.mn.fix1 2017-07-24 16:46:36.000000000 -0700
+++ ./esc/src/lib/NssHttpClient/manifest.mn 2018-04-26 11:44:38.462986047 -0700
@@ -31,7 +31,7 @@ endif
MAPFILE = $(OBJDIR)/httpchunked.def
-DEFINES = -I$(SYS_INC)/nspr4 -I$(SYS_INC)/nss3 -I$(SYS_INC)/$(MOZ_OFFSET)/nspr -I$(SYS_INC)/$(MOZ_OFFSET)/nss -I$(XULRUNNER_BASE)/dist/public/nss -I$(XULRUNNER_BASE)/dist/include/nspr -I$(GECKO_SDK_PATH)/include/nspr -I$(GECKO_SDK_PATH)/include/nss
+DEFINES = -I$(SYS_INC)/nspr4 -I$(SYS_INC)/nss3 -I$(SYS_INC)/$(MOZ_OFFSET)/nspr -I$(SYS_INC)/$(MOZ_OFFSET)/nss -I$(XULRUNNER_BASE)/dist/public/nss -I$(XULRUNNER_BASE)/dist/include/nspr -I$(GECKO_SDK_PATH)/include/nspr -I$(GECKO_SDK_PATH)/include/nss -I$(SYS_INC)/PCSC -I$(CORE_DEPTH)/src/lib/coolkey
CPPSRCS = \
Cache.cpp \