8238 lines
262 KiB
Diff
8238 lines
262 KiB
Diff
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 @@
|
|
<stringbundle id="esc_strings" src="chrome://esc/locale/esc.properties"/>
|
|
<script src="AdvancedInfo.js"/>
|
|
<script src="ESC.js"/>
|
|
-<script src="TRAY.js"/>
|
|
<grid class="logoBox">
|
|
<rows >
|
|
<row>
|
|
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">
|
|
<stringbundle id="esc_strings" src="chrome://esc/locale/esc.properties"/>
|
|
-<script src="TRAY.js"/>
|
|
<script src="ESC.js"/>
|
|
<hbox class="logoBox" >
|
|
<image id="logoImage"/>
|
|
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">
|
|
|
|
<stringbundle id="esc_strings" src="chrome://esc/locale/esc.properties"/>
|
|
- <script src= "TRAY.js"/>
|
|
<script src="ESC.js"/>
|
|
<vbox flex ="1" >
|
|
<hbox class="logoBox" >
|
|
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">
|
|
<stringbundle id="esc_strings" src="chrome://esc/locale/esc.properties"/>
|
|
-<script src="TRAY.js"/>
|
|
<script src="ESC.js"/>
|
|
</window>
|
|
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">
|
|
|
|
<stringbundle id="esc_strings" src="chrome://esc/locale/esc.properties"/>
|
|
- <script src= "TRAY.js"/>
|
|
<script src="ESC.js"/>
|
|
|
|
<groupbox flex="1">
|
|
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">
|
|
|
|
<stringbundle id="esc_strings" src="chrome://esc/locale/esc.properties"/>
|
|
- <script src="TRAY.js"/>
|
|
<script src="ESC.js"/>
|
|
<tabbox id="tablist" hidden="true">
|
|
<tabs>
|
|
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 <stdio.h>
|
|
+#include "cky_applet.h"
|
|
+#include <string.h>
|
|
+
|
|
+#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 <string.h>
|
|
+#include <stdlib.h>
|
|
+#include <assert.h>
|
|
+#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 <winscard.h>
|
|
+#include <stdlib.h>
|
|
+#include <string.h>
|
|
+#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 <winscard.h>
|
|
+
|
|
+#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<ActiveKeyNode *> 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 <vector>
|
|
#include <string>
|
|
|
|
+#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 <config.h>
|
|
+#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 <mach-o/dyld.h>
|
|
+#include <stdio.h>
|
|
+#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 <dlfcn.h>
|
|
+#include <unistd.h>
|
|
+#if !defined(MAC) && !defined(HPUX)
|
|
+#include <link.h>
|
|
+#endif
|
|
+#include <assert.h>
|
|
+
|
|
+#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 <Windows.h>
|
|
+#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 \
|