[Date Prev][Date Next] [Thread Prev][Thread Next] [Date Index] [Thread Index]

Bug#670367: pu: package coolkey/1.1.0-6 debdiff attached



OK. The handling of auto* tools in the coolkey 1.1.0-6 package in stable
means that the clean target in debian/rules doesn't restore the files
to pre-built state. So there was too much autotools cruft in the 
previous coolkeyspu2.debdiff. Please ignore it.

The attached coolkeyspu3.debdiff is much closer to the first atttempt,
while still elaborating upstream patch descriptions as requested.

I did not change debian/rules, so this coolkey 1.1.0-6+squeeze1 is
packaging bug compatible with the current version in stable.

-Maitland

diff -u coolkey-1.1.0/debian/changelog coolkey-1.1.0/debian/changelog
--- coolkey-1.1.0/debian/changelog
+++ coolkey-1.1.0/debian/changelog
@@ -1,3 +1,31 @@
+coolkey (1.1.0-6+squeeze1) stable; urgency=low
+
+  * updated to follow the new Card Compatibility Container (CCC) specification
+    to support recently issued smartcards in Debian stable.
+  * upstream patches added to debian/patches/
+    07_coolkey_latest.dpatch
+    (in RHEL coolkey-cac.fix + coolkey-safenet + coolkey-1.1.0-gemalto.64k)
+    * Fri Sep 11 2009 Jack Magne <jmagne@redhat.com> - 1.1.0-10
+    - Include latest changes for Gemalto 64K and Safenet 330J.
+    08_coolkey_simple_bugs.dpatch
+    * Wed Sep 16 2009 Jack magne <jmagne@redhat.com> - 1.1.0-11
+    - Misc bug fixes. Resolves: 485032, #250738, #497758. (redhat bugs)
+    09_coolkey_thread_fix.dpatch
+    * Wed Dec 18 2009 Robert Relyea <rrelyea@redhat.com> - 1.1.0-12
+    - Fix threading issue. Coolkey will now work with non-threaded applications
+      that don't link with libpthread.
+    10_coolkey_cac_rhl5.dpatch
+    * Wed Jul 20 2010 Robert Relyea <rrelyea@redhat.com> - 1.1.0-15
+    - work with new piv-like CAC cards
+    11_empty_certificates.dpatch
+    * Mon, 23 May 2011 17:17:43 +0300 Vladimir Kravets <vova.kravets@gmail.com>
+    - Fix working with empty certificates in not zero slots.
+    12_pcscd_restarting.dpatch
+    * Wed Jul 13 22:19:42 2011 +0000 rrelyea <rrelyea@fedoraproject.org>
+    - Handle pcscd restarting.
+  
+ -- A. Maitland Bottoms <bottoms@debian.org>  Mon, 30 Apr 2012 17:15:35 -0400
+
 coolkey (1.1.0-6) unstable; urgency=low
 
   * debian/control: Standards-Version: 3.7.3 => 3.8.3
diff -u coolkey-1.1.0/debian/patches/00list coolkey-1.1.0/debian/patches/00list
--- coolkey-1.1.0/debian/patches/00list
+++ coolkey-1.1.0/debian/patches/00list
@@ -6,0 +7,6 @@
+07_coolkey_latest.dpatch
+08_coolkey_simple_bugs.dpatch
+09_coolkey_thread_fix.dpatch
+10_coolkey_cac_rhl5.dpatch
+11_empty_certificates.dpatch
+12_pcscd_restarting.dpatch
only in patch2:
unchanged:
--- coolkey-1.1.0.orig/debian/patches/12_pcscd_restarting.dpatch
+++ coolkey-1.1.0/debian/patches/12_pcscd_restarting.dpatch
@@ -0,0 +1,83 @@
+#! /bin/sh /usr/share/dpatch/dpatch-run
+## 12_pcscd_restarting.dpatch by  <bottoms@petros.rf.org>
+##
+## All lines beginning with `## DP:' are a description of the patch.
+## DP: Handle pcscd restarting.
+
+@DPATCH@
+
+Description: Handle pcscd restarting.
+Author: rrelyea <rrelyea@fedoraproject.org>
+Date:   Wed Jul 13 22:19:42 2011 +0000
+Origin: https://fedorahosted.org/coolkey/changeset?reponame=&new=95%40%2F&old=94%40%2F
+ svn.fedorahosted.org/svn/coolkey@95
+
+--- a/src/libckyapplet/cky_card.c
++++ b/src/libckyapplet/cky_card.c
+@@ -843,6 +843,11 @@
+     rv = ctx->scard->SCardGetStatusChange(ctx->context, timeout, 
+ 							readers, readerCount);
+     if (rv != SCARD_S_SUCCESS) {
++	if ((rv == SCARD_E_NO_SERVICE) || (rv == SCARD_E_SERVICE_STOPPED)) {
++	    /* if we were stopped, don't reuse the old context, 
++	     * pcsc-lite hangs */
++	    ckyCardContext_release(ctx); 
++	} 
+ 	ctx->lastError = rv;
+ 	return CKYSCARDERR;
+     }
+--- a/src/coolkey/slot.cpp
++++ b/src/coolkey/slot.cpp
+@@ -237,9 +237,14 @@
+ 
+     CKYStatus status = CKYCardContext_ListReaders(context, &readerNames);
+     if ( status != CKYSUCCESS ) {
+-	throw PKCS11Exception(CKR_GENERAL_ERROR,
+-                "Failed to list readers: 0x%x\n", 
+-				CKYCardContext_GetLastError(context));
++	/* if the service is stopped, treat it as if we have no readers */
++ 	if ((CKYCardContext_GetLastError(context) != SCARD_E_NO_SERVICE) && 
++	    (CKYCardContext_GetLastError(context) != SCARD_E_SERVICE_STOPPED)) {
++	    throw PKCS11Exception(CKR_GENERAL_ERROR,
++                 "Failed to list readers: 0x%x\n", 
++ 				CKYCardContext_GetLastError(context));
++	}
++
+     }
+ 
+     if (!readerStates) {
+@@ -1282,7 +1287,9 @@
+         #endif
+     } while ((status == CKYSUCCESS) ||
+        (CKYCardContext_GetLastError(context) == SCARD_E_TIMEOUT) ||
+-        ( CKYCardContext_GetLastError(context) == SCARD_E_READER_UNAVAILABLE));
++       (CKYCardContext_GetLastError(context) == SCARD_E_READER_UNAVAILABLE) ||
++       (CKYCardContext_GetLastError(context) == SCARD_E_NO_SERVICE) ||
++       (CKYCardContext_GetLastError(context) == SCARD_E_SERVICE_STOPPED) );
+ #else
+     do {
+ 	OSSleep(100);
+@@ -3398,10 +3405,12 @@
+         status = CKYApplet_ComputeCrypt(conn, keyNum, CKY_RSA_NO_PAD, direction,
+ 		input, NULL, output, getNonce(), &result);
+     } 
++#ifdef notdef /* CAC pin cachine is incomplete, don't enable it */
+     /* map the ISO not logged in code to the coolkey one */
+     if (status == CKYISO_CONDITION_NOT_SATISFIED) {
+ 	status = (CKYStatus) CKYISO_UNAUTHORIZED;
+     }
++#endif
+     if (status != CKYSUCCESS) {
+ 	if ( status == CKYSCARDERR ) {
+ 	    handleConnectionError();
+--- a/src/coolkey/Makefile.am
++++ b/src/coolkey/Makefile.am
+@@ -64,7 +64,7 @@
+ # coreconf .def file to a simplistic but acceptable libtool .sym file
+ #
+ coolkeypk11.sym: coolkeypk11.def
+-	grep -v ';+' $< | grep -v ';-' | sed -e 's; DATA ;;' -e 's,;;,,' -e 's,;.*,,' > $@
++	grep -v ';+' $< | grep -v ';-' | sed -e 's; DATA ;;' -e 's,;;,,' -e 's,;.*,,' | grep -v '^$$'> $@
+ 
+ clean-generic:
+ 	rm -f coolkeypk11.sym
only in patch2:
unchanged:
--- coolkey-1.1.0.orig/debian/patches/07_coolkey_latest.dpatch
+++ coolkey-1.1.0/debian/patches/07_coolkey_latest.dpatch
@@ -0,0 +1,694 @@
+#! /bin/sh /usr/share/dpatch/dpatch-run
+## 07_coolkey_latest.dpatch by  <bottoms@petros.rf.org>
+##
+## All lines beginning with `## DP:' are a description of the patch.
+## DP: Latest fixes for Safenet 330J and Gemalto 64K cards.
+
+@DPATCH@
+
+Description: Latest fixes for Safenet 330J and Gemalto 64K cards.
+Origin: http://pkgs.fedoraproject.org/gitweb/?p=coolkey.git;a=commit;h=e23c66c534b9cef842bb74e373a1582684de2920
+Author: Jack Magne <jmagne@fedoraproject.org>
+Date:   Tue Sep 15 20:52:45 2009 +0000
+
+ SVN revisions 73-77
+ https://fedorahosted.org/coolkey/changeset?reponame=&new=77%40%2F&old=73%40%2F
+
+--- a/src/coolkey/slot.cpp
++++ b/src/coolkey/slot.cpp
+@@ -203,6 +203,29 @@
+     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 @@
+      * 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 @@
+ void
+ Slot::connectToToken()
+ {
+-    CKYStatus status;
++    CKYStatus status = CKYSCARDERR;
+     OSTime time = OSTimeNow();
+ 
+     mCoolkey = 0;
+@@ -537,13 +581,31 @@
+ 
+     // 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 @@
+         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 @@
+          * unfriendly */
+ 	isVersion1Key = 0;
+ 	needLogin = 1;
+-
++        mCoolkey = 0;
+ 	return;
+     }
+     mCoolkey = 1;
+@@ -1077,6 +1134,7 @@
+ 	    }
+ 	    throw;
+ 	}
++
+ 	if (myNumReaders != numReaders) {
+ 	    if (myReaderStates) {
+ 		delete [] myReaderStates;
+@@ -1103,6 +1161,7 @@
+ 		}
+ 	    }
+ 	}
++
+         if (found || (flag == CKF_DONT_BLOCK) || shuttingDown) {
+             break;
+         }
+@@ -1272,6 +1331,19 @@
+     }
+ };
+ 
++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 @@
+         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 @@
+         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 @@
+     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 @@
+ 	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;
++}
+--- a/src/coolkey/slot.h
++++ b/src/coolkey/slot.h
+@@ -270,10 +270,9 @@
+   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 @@
+ 
+     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 @@
+         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 @@
+      * 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);
+--- a/src/libckyapplet/cky_applet.c
++++ b/src/libckyapplet/cky_applet.c
+@@ -134,6 +134,13 @@
+ /* 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 @@
+ {
+     return CKYAPDUFactory_GetLifeCycleV2(apdu);
+ }
+-
+ CKYStatus
+ CKYAppletFactory_GetRandom(CKYAPDU *apdu, const void *param)
+ {
+@@ -725,24 +731,48 @@
+     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 @@
+ 			    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;
+ }
+ 
+@@ -1033,6 +1088,44 @@
+     } while ((size > 0) && (ret == CKYSUCCESS));
+ 
+     return ret;
++}
++
++/*
++ * Write Object
++ * This makes multiple APDU calls to write the entire object.
++ *
++ */
++
++CKYStatus 
++CKYApplet_WriteObjectFull(CKYCardConnection *conn, unsigned long objectID,
++                  CKYOffset offset, CKYSize size, const CKYBuffer *nonce,
++                  const CKYBuffer *data, CKYISOStatus *apduRC)
++{
++
++    CKYBuffer chunk;
++    CKYOffset srcOffset = 0;
++    CKYAppletArgWriteObject wod;
++    CKYStatus ret = CKYSUCCESS;
++
++    wod.objectID = objectID;
++    wod.offset = offset;
++    do {
++        wod.size = (CKYByte) MIN(size, 220);
++        ret = CKYBuffer_InitFromBuffer(&chunk, data,
++                                       srcOffset, wod.size);
++        if(ret == CKYSUCCESS)  {
++            wod.data = &chunk;
++            ret = CKYApplet_HandleAPDU(conn, CKYAppletFactory_WriteObject, &wod,
++               nonce, 0, CKYAppletFill_Null, NULL, apduRC);
++            size -= wod.size;
++            wod.offset += wod.size;
++            srcOffset  += wod.size;
++            CKYBuffer_FreeData(&chunk);
++       }
++
++    } while ((size > 0) && (ret == CKYSUCCESS));
++
++    return ret;
+ }
+ 
+ /*
+--- a/src/libckyapplet/cky_applet.h
++++ b/src/libckyapplet/cky_applet.h
+@@ -192,6 +192,14 @@
+     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 @@
+ /* 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_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, 
+--- a/src/libckyapplet/cky_card.c
++++ b/src/libckyapplet/cky_card.c
+@@ -128,6 +128,7 @@
+     SCardGetStatusChangeFn SCardGetStatusChange;
+     SCardCancelFn SCardCancel;
+     SCARD_IO_REQUEST *SCARD_PCI_T0_;
++    SCARD_IO_REQUEST *SCARD_PCI_T1_;
+ } SCard;
+ 
+ #define GET_ADDRESS(library, scard, name) \
+@@ -194,6 +195,12 @@
+     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:
+@@ -883,6 +890,7 @@
+     SCARDHANDLE      cardHandle;
+     unsigned long    lastError;
+     CKYBool           inTransaction;
++    unsigned long    protocol;
+ };
+ 
+ static void
+@@ -893,6 +901,7 @@
+     conn->cardHandle = 0;
+     conn->lastError = 0;
+     conn->inTransaction = 0;
++    conn->protocol = SCARD_PROTOCOL_T0;
+ }
+ 
+ CKYCardConnection *
+@@ -933,14 +942,13 @@
+ {
+     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;
+@@ -977,7 +985,7 @@
+     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;
+@@ -1038,10 +1046,17 @@
+ 	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;
+--- a/src/libckyapplet/cky_factory.c
++++ b/src/libckyapplet/cky_factory.c
+@@ -190,8 +190,11 @@
+     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 @@
+     return CKYSUCCESS;
+ }
+ 
+-/* Future add WriteObject */
+-
+ CKYStatus
+ CKYAPDUFactory_CreateObject(CKYAPDU *apdu, unsigned long objectID, CKYSize size,
+     unsigned short readACL, unsigned short writeACL, unsigned short deleteACL)
+@@ -415,6 +416,58 @@
+ fail:
+     CKYBuffer_FreeData(&buf);
+     return ret;
++
++}
++
++CKYStatus
++CKYAPDUFactory_WriteObject(CKYAPDU *apdu, unsigned long objectID,
++                                    CKYOffset offset,CKYSize size,CKYBuffer *data)
++{
++    CKYBuffer buf;
++    CKYStatus ret = CKYSUCCESS;
++    unsigned short dataSize = 0;
++
++    CKYAPDU_SetCLA(apdu, CKY_CLASS_COOLKEY);
++    CKYAPDU_SetINS(apdu, CKY_INS_WRITE_OBJ);
++    CKYAPDU_SetP1(apdu, 0x00);
++    CKYAPDU_SetP2(apdu, 0x00);
++    CKYBuffer_InitEmpty(&buf);
++
++    dataSize = (unsigned short) CKYBuffer_Size(data);
++
++    if(!dataSize) {
++        ret = CKYINVALIDARGS;
++        goto fail;
++    }
++
++    ret = CKYBuffer_AppendLong(&buf,objectID);
++    if (ret != CKYSUCCESS) {
++        goto fail;
++    }
++    ret = CKYBuffer_AppendLong(&buf,offset);
++    if (ret != CKYSUCCESS) {
++        goto fail;
++    }
++    ret = CKYBuffer_AppendChar(&buf, size);
++    if (ret != CKYSUCCESS) {
++        goto fail;
++    }
++
++    ret = CKYAPDU_SetSendDataBuffer(apdu,&buf);
++
++    if (ret != CKYSUCCESS) {
++        goto fail;
++    }
++
++    ret = CKYAPDU_AppendSendDataBuffer(apdu, data);
++
++    if (ret != CKYSUCCESS) {
++        goto fail;
++    }
++
++fail:
++    CKYBuffer_FreeData(&buf);
++    return ret;
+ 
+ }
+ 
+--- a/src/libckyapplet/cky_factory.h
++++ b/src/libckyapplet/cky_factory.h
+@@ -190,7 +190,8 @@
+ 				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, 
only in patch2:
unchanged:
--- coolkey-1.1.0.orig/debian/patches/09_coolkey_thread_fix.dpatch
+++ coolkey-1.1.0/debian/patches/09_coolkey_thread_fix.dpatch
@@ -0,0 +1,164 @@
+#! /bin/sh /usr/share/dpatch/dpatch-run
+## 09_coolkey_thread_fix.dpatch by  <bottoms@petros.rf.org>
+##
+## All lines beginning with `## DP:' are a description of the patch.
+## DP: Fix coolkey thread issues
+
+@DPATCH@
+
+Description: Fix coolkey thread issues
+Origin: http://pkgs.fedoraproject.org/gitweb/?p=coolkey.git;a=commit;h=4099f2251ffdf1e8be0e96ede91183557ba1aaba
+Author: Robert Relyea <rrelyea@fedoraproject.org>
+Date:   Fri Dec 18 23:37:45 2009 +0000
+
+ SVN 86 https://fedorahosted.org/coolkey/changeset?reponame=&new=86%40%2F&old=85%40%2F
+
+    Fix coolkey thread issues:
+    1) Coolkey returned errors when ever thread safety was requested, even
+        though coolkey was thread safe.
+    2) Coolkey would hang if used with non-threaded applications which did not
+        link with -lpthreads
+
+--- a/src/coolkey/coolkey.cpp
++++ b/src/coolkey/coolkey.cpp
+@@ -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);
+--- a/src/coolkey/machdep.cpp
++++ b/src/coolkey/machdep.cpp
+@@ -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);
+@@ -439,6 +445,9 @@
+     int rc;
+ 
+     lockData = NULL;
++    if (!needThread) {
++	return;
++    }
+ #ifdef MAC
+     if (!OSLock_attr_init) {
+ 	rc = pthread_mutexattr_init(&OSLock_attr);
+--- a/src/coolkey/machdep.h
++++ b/src/coolkey/machdep.h
+@@ -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;
only in patch2:
unchanged:
--- coolkey-1.1.0.orig/debian/patches/10_coolkey_cac_rhl5.dpatch
+++ coolkey-1.1.0/debian/patches/10_coolkey_cac_rhl5.dpatch
@@ -0,0 +1,1040 @@
+#! /bin/sh /usr/share/dpatch/dpatch-run
+## 10_coolkey_cac_rhl5.dpatch by  <bottoms@petros.rf.org>
+##
+## All lines beginning with `## DP:' are a description of the patch.
+## DP: work with new piv-like CAC cards
+
+@DPATCH@
+
+Date: Wed Jul 20 2010 Robert Relyea <rrelyea@redhat.com> - 1.1.0-15
+Description: work with new piv-like CAC cards
+Author: Robert Relyea <rrelyea@redhat.com>
+Last-Update: 2011-01-13 http://rhn.redhat.com/errata/RHEA-2011-0111.html
+
+ * The coolkey package provides support for CoolKey and Common Access Card (CAC)
+   smart card products.
+
+ * The coolkey device driver has been updated to follow the new Card
+   Compatibility Container (CCC) specification, so that Gemalto TOPDLGX4 144K CAC
+   cards are now supported. (BZ#593017)
+
+--- a/src/coolkey/slot.cpp
++++ b/src/coolkey/slot.cpp
+@@ -372,7 +372,7 @@
+     : 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 @@
+     }
+     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 @@
+     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>
+@@ -583,6 +589,7 @@
+     if( ! CKYCardConnection_IsConnected(conn) ) {
+         int i = 0;
+     //for cranky readers try again a few more times
++	status = CKYSCARDERR;
+         while( i++ < 5 && status != CKYSUCCESS )
+         {
+             status = CKYCardConnection_Connect(conn, readerName);
+@@ -671,12 +678,12 @@
+     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);
++	    log->log("CAC Select failed 0x%x\n", status);
+ 	    if (status == CKYSCARDERR) {
+-		log->log("CAC Card Failure 0x%x\n", 
+-			CKYCardConnection_GetLastError(conn));
++		log->log("CAC Card Failure 0x%x\n",
++				CKYCardConnection_GetLastError(conn));
+ 		disconnect();
+ 	    }
+ 	    return;
+@@ -771,17 +778,111 @@
+     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 +1120,7 @@
+ 
+ struct _manList {
+      unsigned short type;
+-     char *string;
++     const char *string;
+ };
+ 
+ static const struct _manList  manList[] = {
+@@ -1280,13 +1381,30 @@
+ 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 +2177,90 @@
+     return objInfoList;
+ }
+ 
++CKYStatus
++Slot::readCACCertificateFirst(CKYBuffer *cert, CKYSize *nextSize, 
++			      bool throwException)
++{
++    CKYStatus status;
++    CKYISOStatus apduRC;
++    *nextSize = 0;
++
++    if (mOldCAC) {
++	/* get the first 100 bytes of the cert */
++	status = CACApplet_GetCertificateFirst(conn, cert, nextSize, &apduRC);
++	if (throwException && (status != CKYSUCCESS)) {
++	    handleConnectionError();
++	}
++        
++        if(CKYBuffer_Size(cert) == 0) {
++            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 +2295,7 @@
+ 						 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 +2336,7 @@
+ 	    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 +2351,7 @@
+ 	}
+ 
+ 	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 +2367,10 @@
+ 
+     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 +2381,8 @@
+ 	    }
+ 	    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 +2719,7 @@
+     switch( result ) {
+       case CKYISO_SUCCESS:
+         break;
+-      case 6981:
++      case 0x6981:
+         throw PKCS11Exception(CKR_PIN_LOCKED);
+       default:
+ 	if ((result & 0xff00) == 0x6300) {
+@@ -3205,6 +3398,10 @@
+         status = CKYApplet_ComputeCrypt(conn, keyNum, CKY_RSA_NO_PAD, direction,
+ 		input, NULL, output, getNonce(), &result);
+     } 
++    /* map the ISO not logged in code to the coolkey one */
++    if (status == CKYISO_CONDITION_NOT_SATISFIED) {
++	status = (CKYStatus) CKYISO_UNAUTHORIZED;
++    }
+     if (status != CKYSUCCESS) {
+ 	if ( status == CKYSCARDERR ) {
+ 	    handleConnectionError();
+--- a/src/coolkey/slot.h
++++ b/src/coolkey/slot.h
+@@ -294,6 +294,7 @@
+ 				 const CKYBuffer *paddedOutput) const = 0;
+ };
+ 
++#define MAX_CERT_SLOTS 3
+ class Slot {
+ 
+   public:
+@@ -328,6 +329,8 @@
+     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 @@
+     long privateFree;
+     bool fullTokenName;
+     bool mCoolkey;
++    bool mOldCAC;
+ 
+     //enum { RW_SESSION_HANDLE = 1, RO_SESSION_HANDLE = 2 };
+ 
+@@ -398,6 +402,11 @@
+     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();
+--- a/src/libckyapplet/cky_applet.c
++++ b/src/libckyapplet/cky_applet.c
+@@ -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 @@
+ }
+ 
+ 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 @@
+ }
+ 
+ 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 @@
+ 							 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 @@
+     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 @@
+     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 @@
+     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 @@
+ 	 	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 @@
+     }
+     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)
+--- a/src/libckyapplet/cky_applet.h
++++ b/src/libckyapplet/cky_applet.h
+@@ -43,6 +43,7 @@
+ #define CKYISO_MORE_MASK	    0xff00  /* More data mask */
+ #define CKYISO_MORE		    0x6300  /* More data available */
+ #define CKYISO_DATA_INVALID	    0x6984
++#define CKYISO_CONDITION_NOT_SATISFIED 0x6985  /* AKA not logged in */
+ /* Applet Defined Return codes */
+ #define CKYISO_NO_MEMORY_LEFT        0x9c01  /* There have been memory 
+                                              * problems on the card */
+@@ -71,6 +72,15 @@
+ #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 +219,12 @@
+     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 +467,17 @@
+ /* 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);
+--- a/src/libckyapplet/cky_base.c
++++ b/src/libckyapplet/cky_base.c
+@@ -220,6 +220,22 @@
+     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 @@
+     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 @@
+ }
+ 
+ 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 @@
+     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 @@
+     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 @@
+     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)
+--- a/src/libckyapplet/cky_base.h
++++ b/src/libckyapplet/cky_base.h
+@@ -170,9 +170,15 @@
+ /* 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_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);
+--- a/src/libckyapplet/cky_factory.c
++++ b/src/libckyapplet/cky_factory.c
+@@ -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 @@
+     return ret;
+ }
+ 
++
+ CKYStatus
+ CKYAPDUFactory_ComputeCryptFinal(CKYAPDU *apdu, CKYByte keyNumber, 
+ 		CKYByte location, const CKYBuffer *data, const CKYBuffer *sig)
+@@ -572,11 +574,11 @@
+ }
+ 
+ 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 @@
+ }
+ 
+ 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);
+--- a/src/libckyapplet/cky_factory.h
++++ b/src/libckyapplet/cky_factory.h
+@@ -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_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
only in patch2:
unchanged:
--- coolkey-1.1.0.orig/debian/patches/11_empty_certificates.dpatch
+++ coolkey-1.1.0/debian/patches/11_empty_certificates.dpatch
@@ -0,0 +1,28 @@
+#! /bin/sh /usr/share/dpatch/dpatch-run
+## 11_empty_certificates.dpatch by  <bottoms@petros.rf.org>
+##
+## All lines beginning with `## DP:' are a description of the patch.
+## DP: Fix working with empty certificates in not zero slots.
+
+@DPATCH@
+
+From f184e5a538caa9412fa3b0e99afe92473fbd6739 Mon Sep 17 00:00:00 2001
+From: Vladimir Kravets <vova.kravets@gmail.com>
+Date: Mon, 23 May 2011 17:17:43 +0300
+Subject: [PATCH] Fix working with empty certificates in not zero slots.
+
+---
+ coolkey-1.1.0/src/coolkey/slot.cpp |    2 +-
+ 1 files changed, 1 insertions(+), 1 deletions(-)
+
+--- a/src/coolkey/slot.cpp
++++ b/src/coolkey/slot.cpp
+@@ -2192,7 +2192,7 @@
+ 	    handleConnectionError();
+ 	}
+         
+-        if(CKYBuffer_Size(cert) == 0) {
++        if(throwException && CKYBuffer_Size(cert) == 0) {
+             handleConnectionError();
+         }
+ 	return status;
only in patch2:
unchanged:
--- coolkey-1.1.0.orig/debian/patches/08_coolkey_simple_bugs.dpatch
+++ coolkey-1.1.0/debian/patches/08_coolkey_simple_bugs.dpatch
@@ -0,0 +1,80 @@
+#! /bin/sh /usr/share/dpatch/dpatch-run
+## 08_coolkey_simple_bugs.dpatch by  <bottoms@petros.rf.org>
+##
+## All lines beginning with `## DP:' are a description of the patch.
+## DP: Misc bug fixes. Resolves: #485032, #250738, #497758.
+
+@DPATCH@
+
+Description: Misc bug fixes. Resolves: #485032, #250738, #497758.
+Origin: http://pkgs.fedoraproject.org/gitweb/?p=coolkey.git;a=commit;h=35fc0905e715f5851f0093726e1f5d5fd335e390
+Author: Jack Magne <jmagne@fedoraproject.org>
+Date:   Thu Sep 17 00:09:52 2009 +0000
+ SVN rev 81
+
+--- a/Makefile.am
++++ b/Makefile.am
+@@ -25,7 +25,6 @@
+ SUBDIRS += src/install
+ endif
+ 
+-ACLOCAL_AMFLAGS = -I m4
+ 
+ EXTRA_DIST = cookey.spec LICENSE
+ 
+--- a/configure.in
++++ b/configure.in
+@@ -124,9 +124,9 @@
+ 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
+ 
+--- a/src/coolkey/object.cpp
++++ b/src/coolkey/object.cpp
+@@ -397,7 +397,7 @@
+ {
+     // clean up old one
+     if (label) {
+-	delete label;
++	delete [] label;
+ 	label = NULL;
+     }
+     // find matching attribute
+--- a/src/coolkey/object.h
++++ b/src/coolkey/object.h
+@@ -82,7 +82,7 @@
+     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),
+--- a/src/coolkey/slot.cpp
++++ b/src/coolkey/slot.cpp
+@@ -979,7 +979,7 @@
+ //
+ #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 @@
+     }
+     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;
-----BEGIN PGP SIGNATURE-----
Version: GnuPG v1.4.10 (GNU/Linux)

iEYEABECAAYFAk+fMRMACgkQkwbJvNrxBUz+yQCgjgcOLnT0HzBdegyGKWZsDdQe
uAoAniVDSy9yLkH6F20MmNIu4spXaQxZ
=pXaB
-----END PGP SIGNATURE-----

Reply to: