summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--system/coolkey/coolkey.SlackBuild20
-rw-r--r--system/coolkey/gcc-4.3.patch95
-rw-r--r--system/coolkey/patches/coolkey-cac-1.patch28
-rw-r--r--system/coolkey/patches/coolkey-cac.patch1013
-rw-r--r--system/coolkey/patches/coolkey-cache-dir-move.patch177
-rw-r--r--system/coolkey/patches/coolkey-gcc43.patch54
-rw-r--r--system/coolkey/patches/coolkey-latest.patch685
-rw-r--r--system/coolkey/patches/coolkey-pcsc-lite-fix.patch69
-rw-r--r--system/coolkey/patches/coolkey-simple-bugs.patch71
-rw-r--r--system/coolkey/patches/coolkey-thread-fix.patch158
-rw-r--r--system/coolkey/slack-desc16
11 files changed, 2279 insertions, 107 deletions
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 <rousseau@imac.maison.bogus>
-##
-## 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 <rousseau@imac.maison.bogus>
-##
-## 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 <stdlib.h>
-+#include <string.h>
- #include <string>
- #include "mypkcs11.h"
- #include <assert.h>
-#! /bin/sh /usr/share/dpatch/dpatch-run
-## 03_machdep_cpp.dpatch by <rousseau@imac.maison.bogus>
-##
-## 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 <stdlib.h>
-+#include <string.h>
- #include "machdep.h"
- #include "mypkcs11.h"
- #include "PKCS11Exception.h"
-#! /bin/sh /usr/share/dpatch/dpatch-run
-## 04_object_cpp.dpatch by <rousseau@imac.maison.bogus>
-##
-## 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 <string.h>
- #include "mypkcs11.h"
- #include "PKCS11Exception.h"
- #include "object.h"
-#! /bin/sh /usr/share/dpatch/dpatch-run
-## 05_slot_cpp.dpatch by <rousseau@imac.maison.bogus>
-##
-## 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 <class C>
+@@ -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<ListObjectInfo> fetchCombinedObjects(const CKYBuffer *header);
+ list<ListObjectInfo> 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 <winscard.h>
+ #include "slot.h"
+-#include <memory.h>
+ #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 <sys/stat.h>
+ #include <sys/mman.h>
+ #include <pthread.h>
++#include <string.h>
++#include <stdlib.h>
+ #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 <string>
++#include <string.h>
++#include <stdlib.h>
+ #include "mypkcs11.h"
+ #include <assert.h>
+ #include <stdio.h>
+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 <algorithm>
++#include <string.h>
+
+ 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 <stdlib.h>
+ #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: