diff --git a/system/coolkey/coolkey.SlackBuild b/system/coolkey/coolkey.SlackBuild index 443ea9f0cc..0ddbe2d2db 100644 --- a/system/coolkey/coolkey.SlackBuild +++ b/system/coolkey/coolkey.SlackBuild @@ -1,4 +1,4 @@ -#!/bin/sh +#!/bin/bash # Slackware build script for coolkey @@ -24,7 +24,7 @@ PRGNAM=coolkey VERSION=${VERSION:-1.1.0} -BUILD=${BUILD:-1} +BUILD=${BUILD:-2} TAG=${TAG:-_SBo} # Automatically determine the architecture we're building on: @@ -67,8 +67,20 @@ cd $PRGNAM-$VERSION chown -R root:root . chmod -R u+w,go+r-w,a-s . -# Fixup some build errors on gcc43 -patch -p1 < $CWD/gcc-4.3.patch +# Redhat is dallying on a post 1.1.0 coolkey release +# but the cac and pcsc-lite fixes are necessary. These +# come directly from the rawhide srpm, currently -17 + +PATCHES="cache-dir-move \ + gcc43 \ + latest + simple-bugs \ + thread-fix \ + cac \ + cac-1 \ + pcsc-lite-fix" + +for i in $PATCHES; do patch -p0 < $CWD/patches/coolkey-$i.patch; done CFLAGS="$SLKCFLAGS" \ CXXFLAGS="$SLKCFLAGS" \ diff --git a/system/coolkey/gcc-4.3.patch b/system/coolkey/gcc-4.3.patch deleted file mode 100644 index 349c074a01..0000000000 --- a/system/coolkey/gcc-4.3.patch +++ /dev/null @@ -1,95 +0,0 @@ -#! /bin/sh /usr/share/dpatch/dpatch-run -## 01_coolkey_cpp.dpatch by -## -## All lines beginning with `## DP:' are a description of the patch. -## DP: Closes: #455658 FTBFS with GCC 4.3: #define redefined - -@DPATCH@ -diff -urNad coolkey-1.1.0~/src/coolkey/coolkey.cpp coolkey-1.1.0/src/coolkey/coolkey.cpp ---- coolkey-1.1.0~/src/coolkey/coolkey.cpp 2007-02-14 20:54:01.000000000 +0100 -+++ coolkey-1.1.0/src/coolkey/coolkey.cpp 2008-01-06 14:12:35.000000000 +0100 -@@ -34,7 +34,9 @@ - #include "cky_base.h" - #include "params.h" - -+#ifndef NULL - #define NULL 0 -+#endif - - /* static module data -------------------------------- */ - -#! /bin/sh /usr/share/dpatch/dpatch-run -## 02_log_cpp.dpatch by -## -## All lines beginning with `## DP:' are a description of the patch. -## DP: fix for g++ 4.3 - -@DPATCH@ -diff -urNad coolkey-1.1.0~/src/coolkey/log.cpp coolkey-1.1.0/src/coolkey/log.cpp ---- coolkey-1.1.0~/src/coolkey/log.cpp 2007-02-14 20:54:01.000000000 +0100 -+++ coolkey-1.1.0/src/coolkey/log.cpp 2008-01-06 14:18:11.000000000 +0100 -@@ -17,6 +17,8 @@ - * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA - * ***** END COPYRIGHT BLOCK *****/ - -+#include -+#include - #include - #include "mypkcs11.h" - #include -#! /bin/sh /usr/share/dpatch/dpatch-run -## 03_machdep_cpp.dpatch by -## -## All lines beginning with `## DP:' are a description of the patch. -## DP: fix for g++ 4.3 - -@DPATCH@ -diff -urNad coolkey-1.1.0~/src/coolkey/machdep.cpp coolkey-1.1.0/src/coolkey/machdep.cpp ---- coolkey-1.1.0~/src/coolkey/machdep.cpp 2007-02-14 01:46:28.000000000 +0100 -+++ coolkey-1.1.0/src/coolkey/machdep.cpp 2008-01-06 14:19:04.000000000 +0100 -@@ -17,6 +17,8 @@ - * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA - * ***** END COPYRIGHT BLOCK *****/ - -+#include -+#include - #include "machdep.h" - #include "mypkcs11.h" - #include "PKCS11Exception.h" -#! /bin/sh /usr/share/dpatch/dpatch-run -## 04_object_cpp.dpatch by -## -## All lines beginning with `## DP:' are a description of the patch. -## DP: fix for g++ 4.3 - -@DPATCH@ -diff -urNad coolkey-1.1.0~/src/coolkey/object.cpp coolkey-1.1.0/src/coolkey/object.cpp ---- coolkey-1.1.0~/src/coolkey/object.cpp 2007-02-09 19:53:21.000000000 +0100 -+++ coolkey-1.1.0/src/coolkey/object.cpp 2008-01-06 14:22:42.000000000 +0100 -@@ -17,6 +17,7 @@ - * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA - * ***** END COPYRIGHT BLOCK *****/ - -+#include - #include "mypkcs11.h" - #include "PKCS11Exception.h" - #include "object.h" -#! /bin/sh /usr/share/dpatch/dpatch-run -## 05_slot_cpp.dpatch by -## -## All lines beginning with `## DP:' are a description of the patch. -## DP: fix for g++ 4.3 - -@DPATCH@ -diff -urNad coolkey-1.1.0.obsolete.0.590099710113467~/src/coolkey/slot.cpp coolkey-1.1.0.obsolete.0.590099710113467/src/coolkey/slot.cpp ---- coolkey-1.1.0.obsolete.0.590099710113467~/src/coolkey/slot.cpp 2008-01-06 14:27:32.000000000 +0100 -+++ coolkey-1.1.0.obsolete.0.590099710113467/src/coolkey/slot.cpp 2008-01-06 14:27:58.000000000 +0100 -@@ -33,7 +33,7 @@ - - #define MIN(x, y) ((x) < (y) ? (x) : (y)) - --using std::auto_ptr; -+//using std::auto_ptr; - - - #ifdef DEBUG diff --git a/system/coolkey/patches/coolkey-cac-1.patch b/system/coolkey/patches/coolkey-cac-1.patch new file mode 100644 index 0000000000..ea701879ed --- /dev/null +++ b/system/coolkey/patches/coolkey-cac-1.patch @@ -0,0 +1,28 @@ +diff -up ./src/coolkey/object.cpp.cac-1 ./src/coolkey/object.cpp +--- ./src/coolkey/object.cpp.cac-1 2010-06-23 04:46:35.726198827 -0700 ++++ ./src/coolkey/object.cpp 2010-06-23 04:47:28.073827862 -0700 +@@ -505,6 +505,10 @@ dataStart(const CKYByte *buf, unsigned i + unsigned char tag; + unsigned int used_length= 0; + ++ if(!buf) { ++ return NULL; ++ } ++ + tag = buf[used_length++]; + + /* blow out when we come to the end */ +diff -up ./src/coolkey/slot.cpp.cac-1 ./src/coolkey/slot.cpp +--- ./src/coolkey/slot.cpp.cac-1 2010-06-23 04:46:22.718371631 -0700 ++++ ./src/coolkey/slot.cpp 2010-06-23 04:57:04.417774402 -0700 +@@ -2192,6 +2192,10 @@ Slot::readCACCertificateFirst(CKYBuffer + if (throwException && (status != CKYSUCCESS)) { + handleConnectionError(); + } ++ ++ if(CKYBuffer_Size(cert) == 0) { ++ handleConnectionError(); ++ } + return status; + } + diff --git a/system/coolkey/patches/coolkey-cac.patch b/system/coolkey/patches/coolkey-cac.patch new file mode 100644 index 0000000000..a2a9732716 --- /dev/null +++ b/system/coolkey/patches/coolkey-cac.patch @@ -0,0 +1,1013 @@ +diff -up ./src/coolkey/slot.cpp.cac ./src/coolkey/slot.cpp +--- ./src/coolkey/slot.cpp.cac 2010-06-16 13:43:51.477181000 -0700 ++++ ./src/coolkey/slot.cpp 2010-06-16 13:43:51.535179000 -0700 +@@ -372,7 +372,7 @@ Slot::Slot(const char *readerName_, Log + : log(log_), readerName(NULL), personName(NULL), manufacturer(NULL), + slotInfoFound(false), context(context_), conn(NULL), state(UNKNOWN), + isVersion1Key(false), needLogin(false), fullTokenName(false), +- mCoolkey(false), ++ mCoolkey(false), mOldCAC(false), + #ifdef USE_SHMEM + shmem(readerName_), + #endif +@@ -412,6 +412,9 @@ Slot::Slot(const char *readerName_, Log + } + CKYBuffer_InitEmpty(&cardATR); + CKYBuffer_InitEmpty(&mCUID); ++ for (int i=0; i < MAX_CERT_SLOTS; i++) { ++ CKYBuffer_InitEmpty(&cardAID[i]); ++ } + } catch(PKCS11Exception &) { + if (conn) { + CKYCardConnection_Destroy(conn); +@@ -479,6 +482,9 @@ Slot::~Slot() + CKYBuffer_FreeData(&nonce); + CKYBuffer_FreeData(&cardATR); + CKYBuffer_FreeData(&mCUID); ++ for (int i=0; i < MAX_CERT_SLOTS; i++) { ++ CKYBuffer_FreeData(&cardAID[i]); ++ } + } + + template +@@ -671,15 +677,9 @@ Slot::connectToToken() + status = CKYApplet_SelectCoolKeyManager(conn, NULL); + if (status != CKYSUCCESS) { + log->log("CoolKey Select failed 0x%x\n", status); +- status = CACApplet_SelectPKI(conn, 0, NULL); ++ status = getCACAid(); + if (status != CKYSUCCESS) { +- log->log("CAC Select failed 0x%x\n", status); +- if (status == CKYSCARDERR) { +- log->log("CAC Card Failure 0x%x\n", +- CKYCardConnection_GetLastError(conn)); +- disconnect(); +- } +- return; ++ goto loser; + } + state |= CAC_CARD | APPLET_SELECTABLE | APPLET_PERSONALIZED; + /* skip the read of the cuid. We really don't need it and, +@@ -690,6 +690,15 @@ Slot::connectToToken() + needLogin = 1; + mCoolkey = 0; + return; ++ ++loser: ++ log->log("CAC Select failed 0x%x\n", status); ++ if (status == CKYSCARDERR) { ++ log->log("CAC Card Failure 0x%x\n", ++ CKYCardConnection_GetLastError(conn)); ++ disconnect(); ++ } ++ return; + } + mCoolkey = 1; + log->log("time connect: Select Applet %d ms\n", OSTimeNow() - time); +@@ -771,17 +780,111 @@ Slot::disconnect() + invalidateLogin(false); + } + ++CKYStatus ++Slot::getCACAid() ++{ ++ CKYBuffer tBuf; ++ CKYBuffer vBuf; ++ CKYSize tlen, vlen; ++ CKYOffset toffset, voffset; ++ int certSlot = 0; ++ int i,length = 0; ++ CKYStatus status; ++ ++ CKYBuffer_InitEmpty(&tBuf); ++ CKYBuffer_InitEmpty(&vBuf); ++ ++ /* clear out the card AID's */ ++ for (i=0; i < MAX_CERT_SLOTS; i++) { ++ CKYBuffer_Resize(&cardAID[i],0); ++ } ++ ++ status = CACApplet_SelectCCC(conn,NULL); ++ if (status != CKYSUCCESS) { ++ /* are we an old CAC */ ++ status = CACApplet_SelectPKI(conn, &cardAID[0], 0, NULL); ++ if (status != CKYSUCCESS) { ++ /* no, just fail */ ++ return status; ++ } ++ /* yes, fill in the old applets */ ++ mOldCAC = true; ++ for (i=1; i< MAX_CERT_SLOTS; i++) { ++ CACApplet_SelectPKI(conn, &cardAID[i], i, NULL); ++ } ++ return CKYSUCCESS; ++ } ++ /* definately not an old CAC */ ++ mOldCAC = false; ++ ++ /* read the TLV */ ++ status = CACApplet_ReadFile(conn, CAC_TAG_FILE, &tBuf, NULL); ++ if (status != CKYSUCCESS) { ++ goto done; ++ } ++ status = CACApplet_ReadFile(conn, CAC_VALUE_FILE, &vBuf, NULL); ++ if (status != CKYSUCCESS) { ++ goto done; ++ } ++ tlen = CKYBuffer_Size(&tBuf); ++ vlen = CKYBuffer_Size(&vBuf); ++ ++ for(toffset = 2, voffset=2; ++ certSlot < MAX_CERT_SLOTS && toffset < tlen && voffset < vlen ; ++ voffset += length) { ++ ++ CKYByte tag = CKYBuffer_GetChar(&tBuf, toffset); ++ length = CKYBuffer_GetChar(&tBuf, toffset+1); ++ toffset += 2; ++ if (length == 0xff) { ++ length = CKYBuffer_GetShortLE(&tBuf, toffset); ++ toffset +=2; ++ } ++ if (tag != CAC_TAG_CARDURL) { ++ continue; ++ } ++ /* CARDURL tags must be at least 10 bytes long */ ++ if (length < 10) { ++ continue; ++ } ++ /* check the app type, should be TLV_APP_PKI */ ++ if (CKYBuffer_GetChar(&vBuf, voffset+5) != CAC_TLV_APP_PKI) { ++ continue; ++ } ++ status = CKYBuffer_AppendBuffer(&cardAID[certSlot], &vBuf, voffset, 5); ++ if (status != CKYSUCCESS) { ++ goto done; ++ } ++ status = CKYBuffer_AppendBuffer(&cardAID[certSlot], &vBuf, ++ voffset+8, 2); ++ if (status != CKYSUCCESS) { ++ goto done; ++ } ++ cardEF[certSlot] = CKYBuffer_GetShortLE(&vBuf, voffset+6); ++ ++ certSlot++; ++ } ++ status = CKYSUCCESS; ++ if (certSlot == 0) { ++ status = CKYAPDUFAIL; /* probably neeed a beter error code */ ++ } ++ ++done: ++ CKYBuffer_FreeData(&tBuf); ++ CKYBuffer_FreeData(&vBuf); ++ return status; ++} ++ + void + Slot::refreshTokenState() + { + if( cardStateMayHaveChanged() ) { +-log->log("card changed\n"); ++ log->log("card changed\n"); + invalidateLogin(true); + closeAllSessions(); + unloadObjects(); + connectToToken(); + +- + if( state & APPLET_PERSONALIZED ) { + try { + loadObjects(); +@@ -1019,7 +1122,7 @@ Slot::makeModelString(char *model, int m + + struct _manList { + unsigned short type; +- char *string; ++ const char *string; + }; + + static const struct _manList manList[] = { +@@ -1280,13 +1383,30 @@ void + Slot::selectCACApplet(CKYByte instance) + { + CKYStatus status; +- status = CACApplet_SelectPKI(conn, instance, NULL); ++ CKYBuffer *aid = &cardAID[instance]; ++ ++ if (CKYBuffer_Size(aid) == 0) { ++ disconnect(); ++ throw PKCS11Exception(CKR_DEVICE_REMOVED); ++ return; ++ } ++ ++ status = CKYApplet_SelectFile(conn, aid, NULL); + if ( status == CKYSCARDERR ) handleConnectionError(); + if ( status != CKYSUCCESS) { + // could not select applet: this just means it's not there + disconnect(); + throw PKCS11Exception(CKR_DEVICE_REMOVED); + } ++ if (mOldCAC) { ++ return; ++ } ++ status = CACApplet_SelectFile(conn, cardEF[instance], NULL); ++ if ( status == CKYSCARDERR ) handleConnectionError(); ++ if ( status != CKYSUCCESS) { ++ disconnect(); ++ throw PKCS11Exception(CKR_DEVICE_REMOVED); ++ } + } + // assume we are already in a transaction + void +@@ -2059,10 +2179,85 @@ Slot::fetchCombinedObjects(const CKYBuff + return objInfoList; + } + ++CKYStatus ++Slot::readCACCertificateFirst(CKYBuffer *cert, CKYSize *nextSize, ++ bool throwException) ++{ ++ CKYStatus status; ++ CKYISOStatus apduRC; ++ ++ if (mOldCAC) { ++ /* get the first 100 bytes of the cert */ ++ status = CACApplet_GetCertificateFirst(conn, cert, nextSize, &apduRC); ++ if (throwException && (status != CKYSUCCESS)) { ++ handleConnectionError(); ++ } ++ return status; ++ } ++ ++ CKYBuffer tBuf; ++ CKYBuffer vBuf; ++ CKYSize tlen, vlen; ++ CKYOffset toffset, voffset; ++ int length = 0; ++ ++ CKYBuffer_InitEmpty(&tBuf); ++ CKYBuffer_InitEmpty(&vBuf); ++ CKYBuffer_Resize(cert, 0); ++ ++ /* handle the new CAC card read */ ++ /* read the TLV */ ++ status = CACApplet_ReadFile(conn, CAC_TAG_FILE, &tBuf, NULL); ++ if (status != CKYSUCCESS) { ++ goto done; ++ } ++ status = CACApplet_ReadFile(conn, CAC_VALUE_FILE, &vBuf, NULL); ++ if (status != CKYSUCCESS) { ++ goto done; ++ } ++ tlen = CKYBuffer_Size(&tBuf); ++ vlen = CKYBuffer_Size(&vBuf); ++ ++ /* look for the Cert out of the TLV */ ++ for(toffset = 2, voffset=2; toffset < tlen && voffset < vlen ; ++ voffset += length) { ++ ++ CKYByte tag = CKYBuffer_GetChar(&tBuf, toffset); ++ length = CKYBuffer_GetChar(&tBuf, toffset+1); ++ toffset += 2; ++ if (length == 0xff) { ++ length = CKYBuffer_GetShortLE(&tBuf, toffset); ++ toffset +=2; ++ } ++ if (tag != CAC_TAG_CERTIFICATE) { ++ continue; ++ } ++ CKYBuffer_AppendBuffer(cert, &vBuf, voffset, length); ++ break; ++ } ++ status = CKYSUCCESS; ++ ++done: ++ CKYBuffer_FreeData(&tBuf); ++ CKYBuffer_FreeData(&vBuf); ++ return status; ++} ++ ++/* ++ * only necessary for old CAC cards. New CAC cards have to read the ++ * whole cert in anyway above.... ++ */ ++CKYStatus ++Slot::readCACCertificateAppend(CKYBuffer *cert, CKYSize nextSize) ++{ ++ CKYISOStatus apduRC; ++ assert(mOldCAC); ++ return CACApplet_GetCertificateAppend(conn, cert, nextSize, &apduRC); ++} ++ + void + Slot::loadCACCert(CKYByte instance) + { +- CKYISOStatus apduRC; + CKYStatus status = CKYSUCCESS; + CKYBuffer cert; + CKYBuffer rawCert; +@@ -2097,12 +2292,7 @@ Slot::loadCACCert(CKYByte instance) + instance, OSTimeNow() - time); + + if (instance == 0) { +- /* get the first 100 bytes of the cert */ +- status = CACApplet_GetCertificateFirst(conn, &rawCert, +- &nextSize, &apduRC); +- if (status != CKYSUCCESS) { +- handleConnectionError(); +- } ++ readCACCertificateFirst(&rawCert, &nextSize, true); + log->log("CAC Cert %d: fetch CAC Cert: %d ms\n", + instance, OSTimeNow() - time); + } +@@ -2143,8 +2333,7 @@ Slot::loadCACCert(CKYByte instance) + shmem.setVersion(SHMEM_VERSION); + shmem.setDataVersion(dataVersion); + } else { +- status = CACApplet_GetCertificateFirst(conn, &rawCert, +- &nextSize, &apduRC); ++ status = readCACCertificateFirst(&rawCert, &nextSize, false); + + if (status != CKYSUCCESS) { + /* CAC only requires the Certificate in pki '0' */ +@@ -2159,8 +2348,7 @@ Slot::loadCACCert(CKYByte instance) + } + + if (nextSize) { +- status = CACApplet_GetCertificateAppend(conn, &rawCert, +- nextSize, &apduRC); ++ status = readCACCertificateAppend(&rawCert, nextSize); + } + log->log("CAC Cert %d: Fetch rest : %d ms\n", + instance, OSTimeNow() - time); +@@ -2176,9 +2364,10 @@ Slot::loadCACCert(CKYByte instance) + + log->log("CAC Cert %d: Cert has been read: %d ms\n", + instance, OSTimeNow() - time); +- if (CKYBuffer_GetChar(&rawCert,0) == 1) { ++ if (!mOldCAC || CKYBuffer_GetChar(&rawCert,0) == 1) { + CKYSize guessFinalSize = CKYBuffer_Size(&rawCert); + CKYSize certSize = 0; ++ CKYOffset offset = mOldCAC ? 1 : 0; + int zret = Z_MEM_ERROR; + + do { +@@ -2189,7 +2378,8 @@ Slot::loadCACCert(CKYByte instance) + } + certSize = guessFinalSize; + zret = uncompress((Bytef *)CKYBuffer_Data(&cert),&certSize, +- CKYBuffer_Data(&rawCert)+1, CKYBuffer_Size(&rawCert)-1); ++ CKYBuffer_Data(&rawCert)+offset, ++ CKYBuffer_Size(&rawCert)-offset); + } while (zret == Z_BUF_ERROR); + + if (zret != Z_OK) { +@@ -2526,7 +2716,7 @@ Slot::attemptCACLogin() + switch( result ) { + case CKYISO_SUCCESS: + break; +- case 6981: ++ case 0x6981: + throw PKCS11Exception(CKR_PIN_LOCKED); + default: + if ((result & 0xff00) == 0x6300) { +diff -up ./src/coolkey/slot.h.cac ./src/coolkey/slot.h +--- ./src/coolkey/slot.h.cac 2010-06-16 13:43:51.344185000 -0700 ++++ ./src/coolkey/slot.h 2010-06-16 13:43:51.546179000 -0700 +@@ -294,6 +294,7 @@ class CryptParams { + const CKYBuffer *paddedOutput) const = 0; + }; + ++#define MAX_CERT_SLOTS 3 + class Slot { + + public: +@@ -328,6 +329,8 @@ class Slot { + CKYBuffer nonce; + CKYBuffer cardATR; + CKYBuffer mCUID; ++ CKYBuffer cardAID[MAX_CERT_SLOTS]; ++ unsigned short cardEF[MAX_CERT_SLOTS]; + bool isVersion1Key; + bool needLogin; + long publicFree; +@@ -335,6 +338,7 @@ class Slot { + long privateFree; + bool fullTokenName; + bool mCoolkey; ++ bool mOldCAC; + + //enum { RW_SESSION_HANDLE = 1, RO_SESSION_HANDLE = 2 }; + +@@ -398,6 +402,11 @@ class Slot { + list fetchCombinedObjects(const CKYBuffer *header); + list fetchSeparateObjects(); + ++ CKYStatus getCACAid(); ++ CKYStatus readCACCertificateFirst(CKYBuffer *cert, CKYSize *nextSize, ++ bool throwException); ++ CKYStatus readCACCertificateAppend(CKYBuffer *cert, CKYSize nextSize); ++ + void selectApplet(); + void selectCACApplet(CKYByte instance); + void unloadObjects(); +diff -up ./src/libckyapplet/cky_applet.c.cac ./src/libckyapplet/cky_applet.c +--- ./src/libckyapplet/cky_applet.c.cac 2010-06-16 13:43:51.357181000 -0700 ++++ ./src/libckyapplet/cky_applet.c 2010-06-16 14:47:41.305529000 -0700 +@@ -41,7 +41,13 @@ + CKYStatus + CKYAppletFactory_SelectFile(CKYAPDU *apdu, const void *param) + { +- return CKYAPDUFactory_SelectFile(apdu,(const CKYBuffer *)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 +@@ -225,10 +231,17 @@ CKYAppletFactory_GetBuiltinACL(CKYAPDU * + } + + CKYStatus +-CACAppletFactory_SignDecrypt(CKYAPDU *apdu, const void *param) ++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, buf); ++ return CACAPDUFactory_SignDecrypt(apdu, CAC_P1_FINAL, buf); + } + + CKYStatus +@@ -246,6 +259,13 @@ CACAppletFactory_GetCertificate(CKYAPDU + } + + 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); +@@ -457,7 +477,7 @@ CKYApplet_SelectFile(CKYCardConnection * + CKYISOStatus *apduRC) + { + return CKYApplet_HandleAPDU(conn, CKYAppletFactory_SelectFile, AID, NULL, +- 0, CKYAppletFill_Null, NULL, apduRC); ++ CKY_SIZE_UNKNOWN, CKYAppletFill_Null, NULL, apduRC); + } + + static CKYByte coolkeyid[] = {0x62, 0x76, 0x01, 0xff, 0x00, 0x00, 0x00 }; +@@ -477,22 +497,23 @@ CKYApplet_SelectCoolKeyManager(CKYCardCo + return ret; + } + +-static CKYByte CACPKIid[] = {0xa0, 0x00, 0x00, 0x00, 0x79, 0x01, 0x00 }; ++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, CKYByte instance, +- CKYISOStatus *apduRC) ++CACApplet_SelectPKI(CKYCardConnection *conn, CKYBuffer *cacAID, ++ CKYByte instance, CKYISOStatus *apduRC) + { + CKYStatus ret; +- CKYBuffer CACPKIAID; +- CKYBuffer_InitFromData(&CACPKIAID, CACPKIid, sizeof(CACPKIid)); +- CKYBuffer_SetChar(&CACPKIAID, 6, instance); +- ret = CKYApplet_HandleAPDU(conn, CKYAppletFactory_SelectFile, &CACPKIAID, ++ 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); +- CKYBuffer_FreeData(&CACPKIAID); ++ if (ret != CKYSUCCESS) { ++ CKYBuffer_Resize(cacAID, 0); ++ } + return ret; + } + +@@ -515,11 +536,38 @@ CACApplet_SelectCardManager(CKYCardConne + CKYBuffer CAC_CM_AID; + CKYBuffer_InitFromData(&CAC_CM_AID, cacmgrid, sizeof(cacmgrid)); + ret = CKYApplet_HandleAPDU(conn, CKYAppletFactory_SelectFile, &CAC_CM_AID, +- NULL, 0, CKYAppletFill_Null, NULL, apduRC); ++ 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 + */ +@@ -673,8 +721,8 @@ CKYApplet_ComputeCryptProcess(CKYCardCon + ccd.keyNumber = keyNumber; + ccd.location = location; + ccd.data = data; +- return CKYApplet_HandleAPDU(conn, CKYAppletFactory_ComputeCryptProcess, &ccd, +- nonce, 0, CKYAppletFill_Null, NULL, apduRC); ++ return CKYApplet_HandleAPDU(conn, CKYAppletFactory_ComputeCryptProcess, ++ &ccd, nonce, 0, CKYAppletFill_Null, NULL, apduRC); + } + + /* computeCrypt returns data in the form : +@@ -832,11 +880,39 @@ CACApplet_SignDecrypt(CKYCardConnection + CKYBuffer *result, CKYISOStatus *apduRC) + { + CKYStatus ret; +- +- ret = CKYApplet_HandleAPDU(conn, +- CACAppletFactory_SignDecrypt, data, NULL, +- CKYBuffer_Size(data), CKYAppletFill_ReplaceBuffer, ++ 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; + } + +@@ -895,6 +971,63 @@ CACApplet_GetCertificate(CKYCardConnecti + } + 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; ++} ++ + CKYStatus + CACApplet_GetCertificateFirst(CKYCardConnection *conn, CKYBuffer *cert, + CKYSize *nextSize, CKYISOStatus *apduRC) +diff -up ./src/libckyapplet/cky_applet.h.cac ./src/libckyapplet/cky_applet.h +--- ./src/libckyapplet/cky_applet.h.cac 2010-06-16 13:43:51.370181000 -0700 ++++ ./src/libckyapplet/cky_applet.h 2010-06-16 13:43:51.572179000 -0700 +@@ -71,6 +71,15 @@ typedef unsigned short CKYISOStatus; /* + #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_TLV_APP_PKI 0x04 ++ + /* + * Pin Constants as used by our applet + */ +@@ -209,6 +218,12 @@ typedef struct _CKYAppletArgComputeCrypt + const CKYBuffer *sig; + } CKYAppletArgComputeCrypt; + ++typedef struct _CACAppletArgReadFile { ++ CKYByte type; ++ CKYByte count; ++ unsigned short offset; ++} CACAppletArgReadFile; ++ + /* 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*/ +@@ -451,9 +466,17 @@ CKYStatus CKYApplet_DeleteObject(CKYCard + /* Select the CAC card manager. Can happen with either applet selected */ + CKYStatus CACApplet_SelectCardManager(CKYCardConnection *conn, + CKYISOStatus *apduRC); +-/* Can happen with either applet selected */ +-CKYStatus CACApplet_SelectPKI(CKYCardConnection *conn, CKYByte instance, +- 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); +diff -up ./src/libckyapplet/cky_base.c.cac ./src/libckyapplet/cky_base.c +--- ./src/libckyapplet/cky_base.c.cac 2006-06-09 11:44:17.000000000 -0700 ++++ ./src/libckyapplet/cky_base.c 2010-06-16 13:43:51.583179000 -0700 +@@ -220,6 +220,22 @@ CKYBuffer_AppendShort(CKYBuffer *buf, un + 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) +@@ -238,6 +254,24 @@ CKYBuffer_AppendLong(CKYBuffer *buf, uns + 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) + { +@@ -351,6 +385,22 @@ CKYBuffer_SetShort(CKYBuffer *buf, CKYOf + } + + 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; +@@ -368,6 +418,24 @@ CKYBuffer_SetLong(CKYBuffer *buf, CKYOff + 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) + { +@@ -388,6 +456,18 @@ CKYBuffer_GetShort(const CKYBuffer *buf, + 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) +@@ -402,6 +482,20 @@ CKYBuffer_GetLong(const CKYBuffer *buf, + 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) +diff -up ./src/libckyapplet/cky_base.h.cac ./src/libckyapplet/cky_base.h +--- ./src/libckyapplet/cky_base.h.cac 2006-06-09 11:44:17.000000000 -0700 ++++ ./src/libckyapplet/cky_base.h 2010-06-16 13:43:51.592179000 -0700 +@@ -170,9 +170,15 @@ CKYStatus CKYBuffer_AppendChar(CKYBuffer + /* 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); + +@@ -210,12 +216,18 @@ CKYStatus CKYBuffer_SetChars(CKYBuffer * + 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); +diff -up ./src/libckyapplet/cky_factory.c.cac ./src/libckyapplet/cky_factory.c +--- ./src/libckyapplet/cky_factory.c.cac 2010-06-16 13:43:51.393185000 -0700 ++++ ./src/libckyapplet/cky_factory.c 2010-06-16 14:48:08.885473000 -0700 +@@ -25,12 +25,13 @@ + * special commands can be issued at any time + */ + CKYStatus +-CKYAPDUFactory_SelectFile(CKYAPDU *apdu, const CKYBuffer *AID) ++CKYAPDUFactory_SelectFile(CKYAPDU *apdu, CKYByte p1, CKYByte p2, ++ const CKYBuffer *AID) + { + CKYAPDU_SetCLA(apdu, CKY_CLASS_ISO7816); + CKYAPDU_SetINS(apdu, CKY_INS_SELECT_FILE); +- CKYAPDU_SetP1(apdu, 0x04); +- CKYAPDU_SetP2(apdu, 0x00); ++ CKYAPDU_SetP1(apdu, p1); ++ CKYAPDU_SetP2(apdu, p2); + return CKYAPDU_SetSendDataBuffer(apdu, AID); + } + +@@ -131,6 +132,7 @@ fail: + return ret; + } + ++ + CKYStatus + CKYAPDUFactory_ComputeCryptFinal(CKYAPDU *apdu, CKYByte keyNumber, + CKYByte location, const CKYBuffer *data, const CKYBuffer *sig) +@@ -572,11 +574,11 @@ CKYAPDUFactory_GetBuiltinACL(CKYAPDU *ap + } + + CKYStatus +-CACAPDUFactory_SignDecrypt(CKYAPDU *apdu, const CKYBuffer *data) ++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, 0x00); ++ CKYAPDU_SetP1(apdu, type); + CKYAPDU_SetP2(apdu, 0x00); + return CKYAPDU_SetSendDataBuffer(apdu, data); + } +@@ -592,6 +594,36 @@ CACAPDUFactory_GetCertificate(CKYAPDU *a + } + + 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); +diff -up ./src/libckyapplet/cky_factory.h.cac ./src/libckyapplet/cky_factory.h +--- ./src/libckyapplet/cky_factory.h.cac 2010-06-16 13:43:51.402181000 -0700 ++++ ./src/libckyapplet/cky_factory.h 2010-06-16 14:43:20.867049000 -0700 +@@ -86,7 +86,11 @@ + #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 + + /* + * Fixed return sized from various commands +@@ -169,7 +173,8 @@ + CKY_BEGIN_PROTOS + + /* function based factorys */ +-CKYStatus CKYAPDUFactory_SelectFile(CKYAPDU *apdu, const CKYBuffer *AID); ++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); +@@ -211,9 +216,12 @@ CKYStatus CKYAPDUFactory_SeedRandom(CKYA + CKYStatus CKYAPDUFactory_GetIssuerInfo(CKYAPDU *apdu); + CKYStatus CKYAPDUFactory_GetBuiltinACL(CKYAPDU *apdu); + +-CKYStatus CACAPDUFactory_SignDecrypt(CKYAPDU *apdu, const CKYBuffer *data); ++CKYStatus CACAPDUFactory_SignDecrypt(CKYAPDU *apdu, CKYByte type, ++ const CKYBuffer *data); + CKYStatus CACAPDUFactory_VerifyPIN(CKYAPDU *apdu, const char *pin); + CKYStatus CACAPDUFactory_GetCertificate(CKYAPDU *apdu, CKYSize size); ++CKYStatus CACAPDUFactory_ReadFile(CKYAPDU *apdu, unsigned short offset, ++ CKYByte type, CKYByte count); + CKYStatus CACAPDUFactory_GetProperties(CKYAPDU *apdu); + + CKY_END_PROTOS diff --git a/system/coolkey/patches/coolkey-cache-dir-move.patch b/system/coolkey/patches/coolkey-cache-dir-move.patch new file mode 100644 index 0000000000..1b5eaffdb8 --- /dev/null +++ b/system/coolkey/patches/coolkey-cache-dir-move.patch @@ -0,0 +1,177 @@ +Index: src/coolkey/machdep.cpp +=================================================================== +RCS file: /cvs/dirsec/coolkey/src/coolkey/machdep.cpp,v +retrieving revision 1.4 +diff -u -r1.4 machdep.cpp +--- src/coolkey/machdep.cpp 14 Feb 2007 00:46:28 -0000 1.4 ++++ src/coolkey/machdep.cpp 15 Aug 2007 01:41:11 -0000 +@@ -185,12 +185,20 @@ + #define MAP_INHERIT 0 + #endif + ++#ifndef BASEPATH ++#ifdef MAC ++#define BASEPATH "/var" ++#else ++#define BASEPATH "/var/cache" ++#endif ++#endif ++ + #ifdef FULL_CLEANUP + #define RESERVED_OFFSET 256 +-#define MEMSEGPATH "/tmp/.pk11ipc" ++#define MEMSEGPATH BASEPATH"/coolkey-lock" + #else + #define RESERVED_OFFSET 0 +-#define MEMSEGPATH "/tmp/.pk11ipc1" ++#define MEMSEGPATH BASEPATH"/coolkey" + #endif + + struct SHMemData { +@@ -208,11 +216,6 @@ + #ifdef FULL_CLEANUP + flock(fd,LOCK_EX); + unsigned long ref = --(*(unsigned long *)addr); +-#ifdef notdef +- if (ref == 0) { +- unlink(path); +- } +-#endif + flock(fd, LOCK_UN); + #endif + munmap(addr,size+RESERVED_OFFSET); +@@ -225,6 +228,73 @@ + } + } + ++/* ++ * The cache directory is shared and accessible by anyone, make ++ * sure the cache file we are opening is really a valid cache file. ++ */ ++int safe_open(char *path, int flags, int mode, int size) ++{ ++ struct stat buf; ++ int fd, ret; ++ ++ fd = open (path, flags|O_NOFOLLOW, mode); ++ ++ if (fd < 0) { ++ return fd; ++ } ++ ++ ret = fstat(fd, &buf); ++ if (ret < 0) { ++ close (fd); ++ return ret; ++ } ++ ++ /* our cache files are pretty specific, make sure we are looking ++ * at the correct one */ ++ ++ /* first, we should own the file ourselves, don't open a file ++ * that someone else wanted us to see. */ ++ if (buf.st_uid != getuid()) { ++ close(fd); ++ errno = EACCES; ++ return -1; ++ } ++ ++ /* next, there should only be one link in this file. Don't ++ * use this code to trash another file */ ++ if (buf.st_nlink != 1) { ++ close(fd); ++ errno = EMLINK; ++ return -1; ++ } ++ ++ /* next, This better be a regular file */ ++ if (!S_ISREG(buf.st_mode)) { ++ close(fd); ++ errno = EACCES; ++ return -1; ++ } ++ ++ /* if the permissions don't match, something is wrong */ ++ if ((buf.st_mode & 03777) != mode) { ++ close(fd); ++ errno = EACCES; ++ return -1; ++ } ++ ++ /* finally the file should be the correct size. This ++ * check isn't so much to protect from an attack, as it is to ++ * detect a corrupted cache file */ ++ if (buf.st_size != size) { ++ close(fd); ++ errno = EACCES; ++ return -1; ++ } ++ ++ /* OK, the file checked out, ok to continue */ ++ return fd; ++} ++ + SHMem::SHMem(): shmemData(0) {} + + SHMem * +@@ -248,7 +318,7 @@ + return NULL; + } + int mask = umask(0); +- int ret = mkdir (MEMSEGPATH, 0777); ++ int ret = mkdir (MEMSEGPATH, 01777); + umask(mask); + if ((ret == -1) && (errno != EEXIST)) { + delete shmemData; +@@ -264,21 +334,16 @@ + shmemData->path[sizeof(MEMSEGPATH)-1] = '/'; + strcpy(&shmemData->path[sizeof(MEMSEGPATH)],name); + +- int mode = 0777; +- if (strcmp(name,"token_names") != 0) { +- /* each user gets his own uid array */ +- sprintf(uid_str, "-%u",getuid()); +- strcat(shmemData->path,uid_str); +- mode = 0700; +- } ++ sprintf(uid_str, "-%u",getuid()); ++ strcat(shmemData->path,uid_str); ++ int mode = 0600; ++ + shmemData->fd = open(shmemData->path, + O_CREAT|O_RDWR|O_EXCL|O_APPEND|O_EXLOCK, mode); +- if (shmemData->fd < 0) { +- needInit = false; +- shmemData->fd = open(shmemData->path,O_RDWR|O_EXLOCK, mode); +- } else { ++ if (shmemData->fd >= 0) { + char *buf; + int len = size+RESERVED_OFFSET; ++ int ret; + + buf = (char *)calloc(1,len); + if (!buf) { +@@ -289,8 +354,22 @@ + delete shmemData; + return NULL; + } +- write(shmemData->fd,buf,len); ++ ret = write(shmemData->fd,buf,len); ++ if (ret != len) { ++ unlink(shmemData->path); ++#ifdef FULL_CLEANUP ++ flock(shmemData->fd, LOCK_UN); ++#endif ++ delete shmemData; ++ return NULL; ++ } ++ + free(buf); ++ } else if (errno == EEXIST) { ++ needInit = false; ++ ++ shmemData->fd = safe_open(shmemData->path,O_RDWR|O_EXLOCK, mode, ++ size+RESERVED_OFFSET); + } + if (shmemData->fd < 0) { + delete shmemData; diff --git a/system/coolkey/patches/coolkey-gcc43.patch b/system/coolkey/patches/coolkey-gcc43.patch new file mode 100644 index 0000000000..5e41b5ab70 --- /dev/null +++ b/system/coolkey/patches/coolkey-gcc43.patch @@ -0,0 +1,54 @@ +diff -up ./src/coolkey/slot.cpp.coolkey-gcc43 ./src/coolkey/slot.cpp +--- ./src/coolkey/slot.cpp.coolkey-gcc43 2008-02-13 18:01:45.000000000 -0800 ++++ ./src/coolkey/slot.cpp 2008-02-13 18:03:05.000000000 -0800 +@@ -25,7 +25,6 @@ + #include "PKCS11Exception.h" + #include + #include "slot.h" +-#include + #include "zlib.h" + #include "params.h" + +@@ -33,7 +32,6 @@ + + #define MIN(x, y) ((x) < (y) ? (x) : (y)) + +-using std::auto_ptr; + + + #ifdef DEBUG +diff -up ./src/coolkey/machdep.cpp.coolkey-gcc43 ./src/coolkey/machdep.cpp +--- ./src/coolkey/machdep.cpp.coolkey-gcc43 2008-02-13 18:02:06.000000000 -0800 ++++ ./src/coolkey/machdep.cpp 2008-02-13 18:04:04.000000000 -0800 +@@ -33,6 +33,8 @@ + #include + #include + #include ++#include ++#include + #endif + + #ifdef _WIN32 +diff -up ./src/coolkey/log.cpp.coolkey-gcc43 ./src/coolkey/log.cpp +--- ./src/coolkey/log.cpp.coolkey-gcc43 2008-02-13 18:01:55.000000000 -0800 ++++ ./src/coolkey/log.cpp 2008-02-13 18:03:37.000000000 -0800 +@@ -18,6 +18,8 @@ + * ***** END COPYRIGHT BLOCK *****/ + + #include ++#include ++#include + #include "mypkcs11.h" + #include + #include +diff -up ./src/coolkey/object.cpp.coolkey-gcc43 ./src/coolkey/object.cpp +--- ./src/coolkey/object.cpp.coolkey-gcc43 2008-02-13 18:02:20.000000000 -0800 ++++ ./src/coolkey/object.cpp 2008-02-13 18:04:22.000000000 -0800 +@@ -21,6 +21,7 @@ + #include "PKCS11Exception.h" + #include "object.h" + #include ++#include + + using std::find_if; + diff --git a/system/coolkey/patches/coolkey-latest.patch b/system/coolkey/patches/coolkey-latest.patch new file mode 100644 index 0000000000..bc10eb852a --- /dev/null +++ b/system/coolkey/patches/coolkey-latest.patch @@ -0,0 +1,685 @@ +diff -up ./src/coolkey/slot.cpp.coolkey-latest ./src/coolkey/slot.cpp +--- ./src/coolkey/slot.cpp.coolkey-latest 2009-09-11 13:58:24.423487305 -0700 ++++ ./src/coolkey/slot.cpp 2009-09-11 14:04:30.813488220 -0700 +@@ -203,6 +203,29 @@ SlotList::readerExists(const char *reade + return FALSE; + } + ++bool ++SlotList::readerNameExistsInList(const char *readerName,CKYReaderNameList *readerNameList) ++{ ++ if( !readerName || !readerNameList) { ++ return FALSE; ++ } ++ ++ int i = 0; ++ int readerNameCnt = CKYReaderNameList_GetCount(*readerNameList); ++ ++ const char *curReaderName = NULL; ++ for(i=0; i < readerNameCnt; i++) { ++ curReaderName = CKYReaderNameList_GetValue(*readerNameList,i); ++ ++ if(!strcmp(curReaderName,readerName)) { ++ return TRUE; ++ } ++ ++ } ++ ++ return FALSE; ++} ++ + /* + * you need to hold the ReaderList Lock before you can update the ReaderList + */ +@@ -256,6 +279,27 @@ SlotList::updateReaderList() + * don't recognize. + */ + ++ /* first though, let's check to see if any previously removed readers have ++ * come back from the dead. If the ignored bit has been set, we do not need ++ * it any more. ++ */ ++ ++ const char *curReaderName = NULL; ++ unsigned long knownState = 0; ++ for(int ri = 0 ; ri < numReaders; ri ++) { ++ ++ knownState = CKYReader_GetKnownState(&readerStates[ri]); ++ if( !(knownState & SCARD_STATE_IGNORE)) { ++ continue; ++ } ++ ++ curReaderName = CKYReader_GetReaderName(&readerStates[ri]); ++ if(readerNameExistsInList(curReaderName,&readerNames)) { ++ CKYReader_SetKnownState(&readerStates[ri], knownState & ~SCARD_STATE_IGNORE); ++ ++ } ++ } ++ + const char *newReadersData[MAX_READER_DELTA]; + const char **newReaders = &newReadersData[0]; + unsigned int newReaderCount = 0; +@@ -528,7 +572,7 @@ SlotList::getSlotList(CK_BBOOL tokenPres + void + Slot::connectToToken() + { +- CKYStatus status; ++ CKYStatus status = CKYSCARDERR; + OSTime time = OSTimeNow(); + + mCoolkey = 0; +@@ -537,13 +581,31 @@ Slot::connectToToken() + + // try to connect to the card + if( ! CKYCardConnection_IsConnected(conn) ) { +- status = CKYCardConnection_Connect(conn, readerName); +- if( status != CKYSUCCESS ) { +- log->log("Unable to connect to token\n"); ++ int i = 0; ++ //for cranky readers try again a few more times ++ while( i++ < 5 && status != CKYSUCCESS ) ++ { ++ status = CKYCardConnection_Connect(conn, readerName); ++ if( status != CKYSUCCESS && ++ CKYCardConnection_GetLastError(conn) == SCARD_E_PROTO_MISMATCH ) ++ { ++ log->log("Unable to connect to token status %d ConnGetGetLastError %x .\n",status,CKYCardConnection_GetLastError(conn)); ++ ++ } ++ else ++ { ++ break; ++ } ++ OSSleep(100000); ++ } ++ ++ if( status != CKYSUCCESS) ++ { + state = UNKNOWN; + return; + } + } ++ + log->log("time connect: Connect Time %d ms\n", OSTimeNow() - time); + if (!slotInfoFound) { + readSlotInfo(); +@@ -562,15 +624,10 @@ Slot::connectToToken() + state = CARD_PRESENT; + } + +- if ( CKYBuffer_DataIsEqual(&cardATR, ATR, sizeof (ATR)) || +- CKYBuffer_DataIsEqual(&cardATR, ATR1, sizeof(ATR1)) || +- CKYBuffer_DataIsEqual(&cardATR, ATR2, sizeof(ATR2)) ) { +- +- if (Params::hasParam("noAppletOK")) +- { +- state |= APPLET_SELECTABLE; +- mCoolkey = 1; +- } ++ if (Params::hasParam("noAppletOK")) ++ { ++ state |= APPLET_SELECTABLE; ++ mCoolkey = 1; + } + + /* support CAC card. identify the card based on applets, not the ATRS */ +@@ -631,7 +688,7 @@ Slot::connectToToken() + * unfriendly */ + isVersion1Key = 0; + needLogin = 1; +- ++ mCoolkey = 0; + return; + } + mCoolkey = 1; +@@ -1077,6 +1134,7 @@ SlotList::waitForSlotEvent(CK_FLAGS flag + } + throw; + } ++ + if (myNumReaders != numReaders) { + if (myReaderStates) { + delete [] myReaderStates; +@@ -1103,6 +1161,7 @@ SlotList::waitForSlotEvent(CK_FLAGS flag + } + } + } ++ + if (found || (flag == CKF_DONT_BLOCK) || shuttingDown) { + break; + } +@@ -1272,6 +1331,19 @@ class ObjectHandleMatch { + } + }; + ++class KeyNumMatch { ++ private: ++ CKYByte keyNum; ++ const Slot &slot; ++ public: ++ KeyNumMatch(CKYByte keyNum_, const Slot &s) : keyNum(keyNum_), slot(s) { } ++ bool operator() (const PKCS11Object& obj) { ++ unsigned long objID = obj.getMuscleObjID(); ++ return (slot.getObjectClass(objID) == 'k') ++ && (slot.getObjectIndex(objID) == keyNum); ++ } ++}; ++ + class ObjectCertCKAIDMatch { + private: + CKYByte cka_id; +@@ -3007,8 +3079,9 @@ Slot::sign(SessionHandleSuffix suffix, C + CK_ULONG ulDataLen, CK_BYTE_PTR pSignature, + CK_ULONG_PTR pulSignatureLen) + { ++ RSASignatureParams params(CryptParams::DEFAULT_KEY_SIZE); + cryptRSA(suffix, pData, ulDataLen, pSignature, pulSignatureLen, +- RSASignatureParams(CryptParams::FIXED_KEY_SIZE)); ++ params); + } + + void +@@ -3016,14 +3089,15 @@ Slot::decrypt(SessionHandleSuffix suffix + CK_ULONG ulDataLen, CK_BYTE_PTR pDecryptedData, + CK_ULONG_PTR pulDecryptedDataLen) + { ++ RSADecryptParams params(CryptParams::DEFAULT_KEY_SIZE); + cryptRSA(suffix, pData, ulDataLen, pDecryptedData, pulDecryptedDataLen, +- RSADecryptParams(CryptParams::FIXED_KEY_SIZE)); ++ params); + } + + void + Slot::cryptRSA(SessionHandleSuffix suffix, CK_BYTE_PTR pInput, + CK_ULONG ulInputLen, CK_BYTE_PTR pOutput, +- CK_ULONG_PTR pulOutputLen, const CryptParams& params) ++ CK_ULONG_PTR pulOutputLen, CryptParams& params) + { + refreshTokenState(); + SessionIter session = findSession(suffix); +@@ -3041,6 +3115,11 @@ Slot::cryptRSA(SessionHandleSuffix suffi + CKYBuffer *result = &opState.result; + CKYByte keyNum = opState.keyNum; + ++ unsigned int keySize = getKeySize(keyNum); ++ ++ if(keySize != CryptParams::DEFAULT_KEY_SIZE) ++ params.setKeySize(keySize); ++ + if( CKYBuffer_Size(result) == 0 ) { + // we haven't already peformed the decryption, so do it now. + if( pInput == NULL || ulInputLen == 0) { +@@ -3243,3 +3322,36 @@ Slot::generateRandom(SessionHandleSuffix + throw PKCS11Exception(CKR_DEVICE_ERROR); + } + } ++ ++#define MAX_NUM_KEYS 8 ++unsigned int ++Slot::getKeySize(CKYByte keyNum) ++{ ++ unsigned int keySize = CryptParams::DEFAULT_KEY_SIZE; ++ int modSize = 0; ++ ++ if(keyNum >= MAX_NUM_KEYS) { ++ return keySize; ++ } ++ ++ ObjectConstIter iter; ++ iter = find_if(tokenObjects.begin(), tokenObjects.end(), ++ KeyNumMatch(keyNum,*this)); ++ ++ if( iter == tokenObjects.end() ) { ++ return keySize; ++ } ++ ++ CKYBuffer const *modulus = iter->getAttribute(CKA_MODULUS); ++ ++ if(modulus) { ++ modSize = CKYBuffer_Size(modulus); ++ if(CKYBuffer_GetChar(modulus,0) == 0x0) { ++ modSize--; ++ } ++ if(modSize > 0) ++ keySize = modSize * 8; ++ } ++ ++ return keySize; ++} +diff -up ./src/coolkey/slot.h.coolkey-latest ./src/coolkey/slot.h +--- ./src/coolkey/slot.h.coolkey-latest 2006-06-09 11:39:11.000000000 -0700 ++++ ./src/coolkey/slot.h 2009-09-11 13:58:24.462488099 -0700 +@@ -270,10 +270,9 @@ class CryptParams { + protected: + unsigned int getKeySize() const { return keySize; } + public: +- // !!!XXX hack. The right way to get the key size is to get all the +- // key information from the token with MSCListKeys, the same way +- // we get all the object information with MSCListObjects. +- enum { FIXED_KEY_SIZE = 1024 }; ++ // set the actual key size obtained from the card ++ void setKeySize(unsigned int newKeySize) { keySize = newKeySize; } ++ enum { DEFAULT_KEY_SIZE = 1024 }; + + + CryptParams(unsigned int keySize_) : keySize(keySize_) { } +@@ -422,7 +421,7 @@ class Slot { + + void cryptRSA(SessionHandleSuffix suffix, CK_BYTE_PTR pInput, + CK_ULONG ulInputLen, CK_BYTE_PTR pOutput, +- CK_ULONG_PTR pulOutputLen, const CryptParams& params); ++ CK_ULONG_PTR pulOutputLen, CryptParams& params); + + void performRSAOp(CKYBuffer *out, const CKYBuffer *input, CKYByte keyNum, + CKYByte direction); +@@ -460,6 +459,8 @@ class Slot { + return (char )((objectID >> 16) & 0xff) - '0'; + } + ++ // actually get the size of a key in bits from the card ++ unsigned int getKeySize(CKYByte keyNum); + + SessionHandleSuffix openSession(Session::Type type); + void closeSession(SessionHandleSuffix handleSuffix); +@@ -527,6 +528,8 @@ class SlotList { + * has called 'C_GetSlotList' with a NULL parameter */ + void updateReaderList(); + ++ /* see if a reader name exists in a caller provided reader name list. */ ++ bool readerNameExistsInList(const char *readerName,CKYReaderNameList *readerNameList ); + bool readerExists(const char *readerName, unsigned int *hint = 0); + public: + SlotList(Log *log); +diff -up ./src/libckyapplet/cky_applet.c.coolkey-latest ./src/libckyapplet/cky_applet.c +--- ./src/libckyapplet/cky_applet.c.coolkey-latest 2006-06-09 11:44:17.000000000 -0700 ++++ ./src/libckyapplet/cky_applet.c 2009-09-11 13:58:24.464487796 -0700 +@@ -134,6 +134,13 @@ CKYAppletFactory_Logout(CKYAPDU *apdu, c + /* 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; +@@ -192,7 +199,6 @@ CKYAppletFactory_GetLifeCycleV2(CKYAPDU + { + return CKYAPDUFactory_GetLifeCycleV2(apdu); + } +- + CKYStatus + CKYAppletFactory_GetRandom(CKYAPDU *apdu, const void *param) + { +@@ -725,24 +731,48 @@ CKYApplet_ComputeCrypt(CKYCardConnection + 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 = CKY_DL_APDU; ++ 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 = data; ++ ccd.data = use_dl_object ? &empty : data; + ccd.sig = sig; + ret = CKYApplet_HandleAPDU(conn, + CKYAppletFactory_ComputeCryptOneStep, &ccd, nonce, + CKY_SIZE_UNKNOWN, ckyAppletFill_ComputeCryptFinal, +- result, apduRC); ++ use_dl_object ? NULL : result, apduRC); + if (ret == CKYAPDUFAIL && *apduRC == CKYISO_INCORRECT_P2) { + use2APDUs = 1; /* maybe it's an old applet */ + } +@@ -759,13 +789,38 @@ CKYApplet_ComputeCrypt(CKYCardConnection + CKYAppletFactory_ComputeCryptInit, &ccd, nonce, + 0, CKYAppletFill_Null, NULL, apduRC); + if (ret == CKYSUCCESS) { +- ccd.data = data; ++ ccd.data = use_dl_object ? &empty : data; + ret = CKYApplet_HandleAPDU(conn, + CKYAppletFactory_ComputeCryptFinal, &ccd, nonce, + CKY_SIZE_UNKNOWN, ckyAppletFill_ComputeCryptFinal, +- result, apduRC); ++ 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; + } + +@@ -1036,6 +1091,44 @@ CKYApplet_ReadObjectFull(CKYCardConnecti + } + + /* ++ * 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 +diff -up ./src/libckyapplet/cky_applet.h.coolkey-latest ./src/libckyapplet/cky_applet.h +--- ./src/libckyapplet/cky_applet.h.coolkey-latest 2006-06-09 11:44:17.000000000 -0700 ++++ ./src/libckyapplet/cky_applet.h 2009-09-11 13:58:24.466487772 -0700 +@@ -192,6 +192,14 @@ typedef struct _CKYAppletArgReadObject { + CKYByte size; + } CKYAppletArgReadObject; + ++typedef struct _CKYAppletArgWriteObject { ++ unsigned long objectID; ++ CKYOffset offset; ++ CKYByte size; ++ CKYBuffer *data; ++ ++} CKYAppletArgWriteObject; ++ + typedef struct _CKYAppletArgComputeCrypt { + CKYByte keyNumber; + CKYByte mode; +@@ -250,6 +258,8 @@ CKYStatus CKYAppletFactory_ListPINs(CKYA + /* 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 */ +@@ -482,6 +492,17 @@ CKYStatus CKYApplet_ReadObjectAppend(CKY + 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, +diff -up ./src/libckyapplet/cky_card.c.coolkey-latest ./src/libckyapplet/cky_card.c +--- ./src/libckyapplet/cky_card.c.coolkey-latest 2006-06-09 11:44:17.000000000 -0700 ++++ ./src/libckyapplet/cky_card.c 2009-09-11 13:58:24.468487469 -0700 +@@ -129,6 +129,7 @@ typedef struct _SCard { + SCardGetStatusChangeFn SCardGetStatusChange; + SCardCancelFn SCardCancel; + SCARD_IO_REQUEST *SCARD_PCI_T0_; ++ SCARD_IO_REQUEST *SCARD_PCI_T1_; + } SCard; + + #define GET_ADDRESS(library, scard, name) \ +@@ -195,6 +196,12 @@ ckySCard_Init(void) + 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: +@@ -884,6 +891,7 @@ struct _CKYCardConnection { + SCARDHANDLE cardHandle; + unsigned long lastError; + CKYBool inTransaction; ++ unsigned long protocol; + }; + + static void +@@ -894,6 +902,7 @@ ckyCardConnection_init(CKYCardConnection + conn->cardHandle = 0; + conn->lastError = 0; + conn->inTransaction = 0; ++ conn->protocol = SCARD_PROTOCOL_T0; + } + + CKYCardConnection * +@@ -934,14 +943,13 @@ CKYCardConnection_Connect(CKYCardConnect + { + CKYStatus ret; + unsigned long rv; +- unsigned long protocol; + + ret = CKYCardConnection_Disconnect(conn); + if (ret != CKYSUCCESS) { + return ret; + } + rv = conn->scard->SCardConnect( conn->ctx->context, readerName, +- SCARD_SHARE_SHARED, SCARD_PROTOCOL_T0, &conn->cardHandle, &protocol); ++ SCARD_SHARE_SHARED, SCARD_PROTOCOL_T0 | SCARD_PROTOCOL_T1, &conn->cardHandle, &conn->protocol); + if (rv != SCARD_S_SUCCESS) { + conn->lastError = rv; + return CKYSCARDERR; +@@ -978,7 +986,7 @@ ckyCardConnection_reconnectRaw(CKYCardCo + unsigned long protocol; + + rv = conn->scard->SCardReconnect(conn->cardHandle, +- SCARD_SHARE_SHARED, SCARD_PROTOCOL_T0, init, &protocol); ++ SCARD_SHARE_SHARED, SCARD_PROTOCOL_T0 | SCARD_PROTOCOL_T1 , init, &protocol); + if (rv != SCARD_S_SUCCESS) { + conn->lastError = rv; + return CKYSCARDERR; +@@ -1039,10 +1047,17 @@ CKYCardConnection_TransmitAPDU(CKYCardCo + return ret; + } + +- rv = conn->scard->SCardTransmit(conn->cardHandle, +- conn->scard->SCARD_PCI_T0_, +- CKYBuffer_Data(&apdu->apduBuf), CKYBuffer_Size(&apdu->apduBuf), +- NULL, response->data, &response->len); ++ 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; +diff -up ./src/libckyapplet/cky_factory.c.coolkey-latest ./src/libckyapplet/cky_factory.c +--- ./src/libckyapplet/cky_factory.c.coolkey-latest 2006-06-09 11:44:17.000000000 -0700 ++++ ./src/libckyapplet/cky_factory.c 2009-09-11 13:58:24.470495267 -0700 +@@ -190,8 +190,11 @@ CKYAPDUFactory_ComputeCryptOneStep(CKYAP + CKYSize len; + CKYBuffer buf; + +- if (!idata || !(len = CKYBuffer_Size(idata)) || location != CKY_DL_APDU) +- return ret; ++ 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); +@@ -314,8 +317,6 @@ CKYAPDUFactory_Logout(CKYAPDU *apdu, CKY + return CKYSUCCESS; + } + +-/* Future add WriteObject */ +- + CKYStatus + CKYAPDUFactory_CreateObject(CKYAPDU *apdu, unsigned long objectID, CKYSize size, + unsigned short readACL, unsigned short writeACL, unsigned short deleteACL) +@@ -419,6 +420,58 @@ fail: + } + + 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); +diff -up ./src/libckyapplet/cky_factory.h.coolkey-latest ./src/libckyapplet/cky_factory.h +--- ./src/libckyapplet/cky_factory.h.coolkey-latest 2006-06-09 11:44:17.000000000 -0700 ++++ ./src/libckyapplet/cky_factory.h 2009-09-11 13:58:24.472487421 -0700 +@@ -190,7 +190,8 @@ CKYStatus CKYAPDUFactory_ChangePIN(CKYAP + 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, diff --git a/system/coolkey/patches/coolkey-pcsc-lite-fix.patch b/system/coolkey/patches/coolkey-pcsc-lite-fix.patch new file mode 100644 index 0000000000..f528676bbc --- /dev/null +++ b/system/coolkey/patches/coolkey-pcsc-lite-fix.patch @@ -0,0 +1,69 @@ +diff -up ./src/coolkey/slot.cpp.reader-state-fix ./src/coolkey/slot.cpp +--- ./src/coolkey/slot.cpp.reader-state-fix 2010-09-08 13:25:14.479109000 -0700 ++++ ./src/coolkey/slot.cpp 2010-09-08 13:25:14.506109000 -0700 +@@ -2185,6 +2185,7 @@ Slot::readCACCertificateFirst(CKYBuffer + { + CKYStatus status; + CKYISOStatus apduRC; ++ *nextSize = 0; + + if (mOldCAC) { + /* get the first 100 bytes of the cert */ +diff -up ./src/libckyapplet/cky_card.c.reader-state-fix ./src/libckyapplet/cky_card.c +--- ./src/libckyapplet/cky_card.c.reader-state-fix 2010-09-08 14:05:10.859321000 -0700 ++++ ./src/libckyapplet/cky_card.c 2010-09-08 14:05:42.792257000 -0700 +@@ -27,7 +27,6 @@ + + #ifndef WINAPI + #define WINAPI +-typedef SCARD_READERSTATE *LPSCARD_READERSTATE; + #endif + + #ifndef SCARD_E_NO_READERS_AVAILABLE +diff -up ./src/libckyapplet/cky_card.h.reader-state-fix ./src/libckyapplet/cky_card.h +--- ./src/libckyapplet/cky_card.h.reader-state-fix 2006-06-09 11:44:17.000000000 -0700 ++++ ./src/libckyapplet/cky_card.h 2010-09-08 13:25:14.518109000 -0700 +@@ -41,23 +41,23 @@ CKYLIST_DECLARE(CKYReaderName, char *) + CKYLIST_DECLARE(CKYCardConnection, CKYCardConnection *) + + CKY_BEGIN_PROTOS +-void CKYReader_Init(SCARD_READERSTATE_A *reader); +-void CKYReader_FreeData(SCARD_READERSTATE_A *reader); ++void CKYReader_Init(SCARD_READERSTATE *reader); ++void CKYReader_FreeData(SCARD_READERSTATE *reader); + + /* +- * "Accessors": for SCARD_READERSTATE_A structure as a class. +- * These functions take an SCARD_READERSTATE_A which can also be referenced ++ * "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_A *reader, const char *name); +-const char *CKYReader_GetReaderName(const SCARD_READERSTATE_A *reader); +-CKYStatus CKYReader_SetKnownState(SCARD_READERSTATE_A *reader, ++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_A *reader); +-unsigned long CKYReader_GetEventState(const SCARD_READERSTATE_A *reader); +-CKYStatus CKYReader_GetATR(const SCARD_READERSTATE_A *reader, CKYBuffer *buf); ++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_A *CKYReader_CreateArray(const CKYReaderNameList readerNames, ++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); +@@ -88,7 +88,7 @@ CKYStatus CKYCardContext_FindReadersByAT + const CKYBuffer *targetATR); + /* return if any of the readers in our array has changed in status */ + CKYStatus CKYCardContext_WaitForStatusChange(CKYCardContext *context, +- SCARD_READERSTATE_A *readers, ++ SCARD_READERSTATE *readers, + unsigned long readerCount, + unsigned long timeout); + /* cancel any current operation (such as wait for status change) on this diff --git a/system/coolkey/patches/coolkey-simple-bugs.patch b/system/coolkey/patches/coolkey-simple-bugs.patch new file mode 100644 index 0000000000..f8f3ab7323 --- /dev/null +++ b/system/coolkey/patches/coolkey-simple-bugs.patch @@ -0,0 +1,71 @@ +diff -up ./configure.in.coolkey-simple-bugs ./configure.in +--- ./configure.in.coolkey-simple-bugs 2009-09-16 11:21:55.621493844 -0700 ++++ ./configure.in 2009-09-16 11:22:23.354492383 -0700 +@@ -124,9 +124,9 @@ then + if test $WINDOWS -ne 1; then + PKG_CHECK_MODULES(NSS, nss, true, [ AC_MSG_ERROR(could not find NSS Crypto libraries) ]) + fi +- enable_pk11install = "yes" ++ enable_pk11install="yes" + else +- enable_pk11install = "no" ++ enable_pk11install="no" + AC_MSG_WARN([skipping pk11install]) + fi + +diff -up ./Makefile.am.coolkey-simple-bugs ./Makefile.am +--- ./Makefile.am.coolkey-simple-bugs 2009-09-16 11:23:18.715515063 -0700 ++++ ./Makefile.am 2009-09-16 13:15:29.570492412 -0700 +@@ -25,7 +25,6 @@ if BUILD_PK11INSTALL + SUBDIRS += src/install + endif + +-ACLOCAL_AMFLAGS = -I m4 + + EXTRA_DIST = cookey.spec LICENSE + +diff -up ./src/coolkey/object.cpp.coolkey-simple-bugs ./src/coolkey/object.cpp +--- ./src/coolkey/object.cpp.coolkey-simple-bugs 2009-09-16 10:36:29.300516245 -0700 ++++ ./src/coolkey/object.cpp 2009-09-16 10:37:17.747492199 -0700 +@@ -397,7 +397,7 @@ PKCS11Object::getLabel() + { + // clean up old one + if (label) { +- delete label; ++ delete [] label; + label = NULL; + } + // find matching attribute +diff -up ./src/coolkey/object.h.coolkey-simple-bugs ./src/coolkey/object.h +--- ./src/coolkey/object.h.coolkey-simple-bugs 2009-09-16 16:05:27.233488140 -0700 ++++ ./src/coolkey/object.h 2009-09-16 16:05:54.161492421 -0700 +@@ -82,7 +82,7 @@ class PKCS11Object { + PKCS11Object(unsigned long muscleObjID, CK_OBJECT_HANDLE handle); + PKCS11Object(unsigned long muscleObjID, const CKYBuffer *data, + CK_OBJECT_HANDLE handle); +- ~PKCS11Object() { delete label; delete name; CKYBuffer_FreeData(&pubKey); } ++ ~PKCS11Object() { delete [] label; delete [] name; CKYBuffer_FreeData(&pubKey); } + + PKCS11Object(const PKCS11Object& cpy) : + attributes(cpy.attributes), muscleObjID(cpy.muscleObjID), +diff -up ./src/coolkey/slot.cpp.coolkey-simple-bugs ./src/coolkey/slot.cpp +--- ./src/coolkey/slot.cpp.coolkey-simple-bugs 2009-09-16 10:28:15.412492201 -0700 ++++ ./src/coolkey/slot.cpp 2009-09-16 10:57:27.692492487 -0700 +@@ -979,7 +979,7 @@ Slot::makeLabelString(char *label, int m + // + #define COOLKEY "CoolKey" + #define POSSESSION " for " +- if (!personName || personName == "") { ++ if (!personName || personName[0] == '\0' ) { + const int coolKeySize = sizeof(COOLKEY) ; + memcpy(label, COOLKEY, coolKeySize-1); + makeSerialString(&label[coolKeySize], maxSize-coolKeySize, cuid); +@@ -1528,7 +1528,7 @@ SlotMemSegment::SlotMemSegment(const cha + } + sprintf(segName,SEGMENT_PREFIX"%s",readerName); + segment = SHMem::initSegment(segName, MAX_OBJECT_STORE_SIZE, needInit); +- delete segName; ++ delete [] segName; + if (!segment) { + // just run without shared memory + return; diff --git a/system/coolkey/patches/coolkey-thread-fix.patch b/system/coolkey/patches/coolkey-thread-fix.patch new file mode 100644 index 0000000000..e3b552aa6a --- /dev/null +++ b/system/coolkey/patches/coolkey-thread-fix.patch @@ -0,0 +1,158 @@ +Index: src/coolkey/coolkey.cpp +=================================================================== +RCS file: /cvs/dirsec/coolkey/src/coolkey/coolkey.cpp,v +retrieving revision 1.2 +diff -u -r1.2 coolkey.cpp +--- src/coolkey/coolkey.cpp 14 Feb 2007 19:54:01 -0000 1.2 ++++ src/coolkey/coolkey.cpp 18 Dec 2009 23:22:58 -0000 +@@ -42,7 +42,9 @@ + + static SlotList *slotList = NULL; + +-static OSLock finalizeLock(false); ++static OSLock *finalizeLock = NULL; ++#define FINALIZE_GETLOCK() if (finalizeLock) finalizeLock->getLock(); ++#define FINALIZE_RELEASELOCK() if (finalizeLock) finalizeLock->releaseLock(); + + static CK_BBOOL initialized = FALSE; + static CK_BBOOL finalizing = FALSE; +@@ -208,11 +210,13 @@ + if( initialized ) { + return CKR_CRYPTOKI_ALREADY_INITIALIZED; + } +- if (!finalizeLock.isValid()) { ++ if (finalizeLock && !finalizeLock->isValid()) { + return CKR_CANT_LOCK; + } + CK_C_INITIALIZE_ARGS* initArgs = (CK_C_INITIALIZE_ARGS*) pInitArgs; ++ OSLock::setThreadSafe(0); + if( initArgs != NULL ) { ++ bool needThreads; + /* work around a bug in NSS where the library parameters are only + * send if locking is requested */ + if (initArgs->LibraryParameters) { +@@ -220,7 +224,17 @@ + } else { + Params::ClearParams(); + } +- if( (initArgs->flags & CKF_OS_LOCKING_OK) || initArgs->LockMutex ){ ++ needThreads = ((initArgs->flags & CKF_OS_LOCKING_OK) != 0); ++ OSLock::setThreadSafe(needThreads); ++ /* don't get a finalize lock unless someone initializes us asking ++ * us to use threads */ ++ if (needThreads && !finalizeLock) { ++ finalizeLock = new OSLock(true); ++ if (finalizeLock == NULL) return CKR_HOST_MEMORY; ++ } ++ /* only support OS LOCKING threads */ ++ if( ((initArgs->flags & CKF_OS_LOCKING_OK) == 0) ++ && initArgs->LockMutex ){ + throw PKCS11Exception(CKR_CANT_LOCK); + } + } +@@ -259,9 +273,9 @@ + // the finalizing call first, we know it will set waitEvent before + // we can get the lock, so we only need to protect setting finalizing + // to true. +- finalizeLock.getLock(); ++ FINALIZE_GETLOCK(); + finalizing = TRUE; +- finalizeLock.releaseLock(); ++ FINALIZE_RELEASELOCK(); + if (waitEvent) { + /* we're waiting on a slot event, shutdown first to allow + * the wait function to complete before we pull the rug out. +@@ -273,10 +287,10 @@ + } + delete slotList; + delete log; +- finalizeLock.getLock(); ++ FINALIZE_GETLOCK(); + finalizing = FALSE; + initialized = FALSE; +- finalizeLock.releaseLock(); ++ FINALIZE_RELEASELOCK(); + return CKR_OK; + } + +@@ -595,17 +609,17 @@ + CK_RV + C_WaitForSlotEvent(CK_FLAGS flags, CK_SLOT_ID_PTR pSlot, CK_VOID_PTR pReserved) + { +- finalizeLock.getLock(); ++ FINALIZE_GETLOCK(); + if( ! initialized ) { +- finalizeLock.releaseLock(); ++ FINALIZE_RELEASELOCK(); + return CKR_CRYPTOKI_NOT_INITIALIZED; + } + if (finalizing) { +- finalizeLock.releaseLock(); ++ FINALIZE_RELEASELOCK(); + return CKR_CRYPTOKI_NOT_INITIALIZED; + } + waitEvent = TRUE; +- finalizeLock.releaseLock(); ++ FINALIZE_RELEASELOCK(); + try { + log->log("C_WaitForSlotEvent called\n"); + slotList->waitForSlotEvent(flags, pSlot, pReserved); +Index: src/coolkey/machdep.cpp +=================================================================== +RCS file: /cvs/dirsec/coolkey/src/coolkey/machdep.cpp,v +retrieving revision 1.7 +diff -u -r1.7 machdep.cpp +--- src/coolkey/machdep.cpp 14 Feb 2008 23:48:19 -0000 1.7 ++++ src/coolkey/machdep.cpp 18 Dec 2009 23:22:58 -0000 +@@ -37,6 +37,8 @@ + #include + #endif + ++bool OSLock::needThread = 0; ++ + #ifdef _WIN32 + // + // Windows functions to grab a named shared memory segment of a specific size, +@@ -123,6 +125,10 @@ + + OSLock::OSLock(bool exceptionAllowed) + { ++ if (!needThread) { ++ lockData = NULL; ++ return; ++ } + lockData = new OSLockData; + if (lockData) { + InitializeCriticalSection(&lockData->mutex); +@@ -360,6 +366,9 @@ + int rc; + + lockData = NULL; ++ if (!needThread) { ++ return; ++ } + #ifdef MAC + if (!OSLock_attr_init) { + rc = pthread_mutexattr_init(&OSLock_attr); +Index: src/coolkey/machdep.h +=================================================================== +RCS file: /cvs/dirsec/coolkey/src/coolkey/machdep.h,v +retrieving revision 1.1 +diff -u -r1.1 machdep.h +--- src/coolkey/machdep.h 9 Jun 2006 18:39:11 -0000 1.1 ++++ src/coolkey/machdep.h 18 Dec 2009 23:22:58 -0000 +@@ -40,12 +40,14 @@ + class OSLock { + private: + OSLockData *lockData; ++ static bool needThread; + public: + OSLock(bool exceptionAllowed = true); + ~OSLock(); + bool isValid(); + void getLock(); + void releaseLock(); ++ static void setThreadSafe(bool thread) { needThread = thread; } + }; + + typedef unsigned long OSTime; diff --git a/system/coolkey/slack-desc b/system/coolkey/slack-desc index a9b7c011b4..148967031a 100644 --- a/system/coolkey/slack-desc +++ b/system/coolkey/slack-desc @@ -6,14 +6,14 @@ # customary to leave one space after the ':'. |-----handy-ruler---------------------------------------------------| -coolkey: coolkey -coolkey: -coolkey: Linux Driver support for the CoolKey and CAC products. +coolkey: coolkey (pkcs#11 smartcard library) +coolkey: +coolkey: coolkey is a pkcs#11 smartcard library that can be used with a US +coolkey: Government CAC (Common Access Card) in conjunction with pcsc-lite. +coolkey: It is most commonly used by pkcs#11 aware web browsers or email +coolkey: clients, to use a CAC's client certificate for authentication or +coolkey: signing. coolkey is commonly used with the DoD Configuration +coolkey: plugin for Firefox and Thunderbird, which is located at +coolkey: https://addons.mozilla.org/en-US/thunderbird/addon/3182. coolkey: coolkey: -coolkey: -coolkey: -coolkey: -coolkey: -coolkey: -coolkey: