Blame SOURCES/coolkey-1.1.0-rhel7-alt-cac.patch

41c127
diff -up ./src/coolkey/coolkey.cpp.alt-cac ./src/coolkey/coolkey.cpp
41c127
--- ./src/coolkey/coolkey.cpp.alt-cac	2016-12-01 15:37:49.106167768 -0800
41c127
+++ ./src/coolkey/coolkey.cpp	2016-12-01 15:37:49.113167892 -0800
41c127
@@ -80,9 +80,16 @@ ecMechanismList[] = {
41c127
     {CKM_ECDSA,{256,521,CKF_HW | CKF_SIGN | CKF_EC_F_P}},
41c127
     {CKM_ECDH1_DERIVE,{256, 521, CKF_HW | CKF_DERIVE | CKF_EC_F_P} }
41c127
 };
41c127
+static const MechInfo
41c127
+allMechanismList[] = {
41c127
+    {CKM_RSA_PKCS, { 1024, 4096, CKF_HW | CKF_SIGN | CKF_DECRYPT } },
41c127
+    {CKM_ECDSA,{256,521,CKF_HW | CKF_SIGN | CKF_EC_F_P}},
41c127
+    {CKM_ECDH1_DERIVE,{256, 521, CKF_HW | CKF_DERIVE | CKF_EC_F_P} }
41c127
+};
41c127
 
41c127
 unsigned int numRSAMechanisms = sizeof(rsaMechanismList)/sizeof(MechInfo);
41c127
 unsigned int numECMechanisms = sizeof(ecMechanismList)/sizeof(MechInfo);
41c127
+unsigned int numAllMechanisms = sizeof(allMechanismList)/sizeof(MechInfo);
41c127
 
41c127
 /* ------------------------------------------------------------ */
41c127
 
41c127
@@ -382,13 +389,22 @@ C_GetMechanismList(CK_SLOT_ID slotID, CK
41c127
             return CKR_TOKEN_NOT_PRESENT;
41c127
         }
41c127
 
41c127
-        if ( slot->getIsECC()) {
41c127
+	switch (slot->getAlgs()) {
41c127
+	case ALG_ECC|ALG_RSA:
41c127
+            mechanismList = allMechanismList;
41c127
+            numMechanisms = numAllMechanisms;
41c127
+	    break;
41c127
+	case ALG_ECC:
41c127
             mechanismList = ecMechanismList;
41c127
             numMechanisms = numECMechanisms;
41c127
-        } else {
41c127
+	    break;
41c127
+	case ALG_NONE:
41c127
+	case ALG_RSA:
41c127
+	default:
41c127
             mechanismList = rsaMechanismList;
41c127
             numMechanisms = numRSAMechanisms;
41c127
-        }
41c127
+	    break;
41c127
+	}
41c127
   
41c127
         if( pMechanismList != NULL ) {
41c127
             if( *pulCount < numMechanisms ) {
41c127
@@ -438,13 +454,22 @@ C_GetMechanismInfo(CK_SLOT_ID slotID, CK
41c127
             return CKR_TOKEN_NOT_PRESENT;
41c127
         }
41c127
 
41c127
-        if ( slot->getIsECC()) {
41c127
+	switch (slot->getAlgs()) {
41c127
+	case ALG_ECC|ALG_RSA:
41c127
+            mechanismList = allMechanismList;
41c127
+            numMechanisms = numAllMechanisms;
41c127
+	    break;
41c127
+	case ALG_ECC:
41c127
             mechanismList = ecMechanismList;
41c127
             numMechanisms = numECMechanisms;
41c127
-        } else {
41c127
+	    break;
41c127
+	case ALG_NONE:
41c127
+	case ALG_RSA:
41c127
+	default:
41c127
             mechanismList = rsaMechanismList;
41c127
             numMechanisms = numRSAMechanisms;
41c127
-        }
41c127
+	    break;
41c127
+	}
41c127
 
41c127
         for(unsigned int i=0; i < numMechanisms; ++i ) {
41c127
             if( mechanismList[i].mech == type ) {
41c127
diff -up ./src/coolkey/object.cpp.alt-cac ./src/coolkey/object.cpp
41c127
--- ./src/coolkey/object.cpp.alt-cac	2016-12-01 15:37:49.097167608 -0800
41c127
+++ ./src/coolkey/object.cpp	2016-12-01 15:37:49.114167910 -0800
41c127
@@ -1232,7 +1232,7 @@ Reader::Reader(unsigned long muscleObjID
41c127
 }
41c127
 
41c127
 
41c127
-CACPrivKey::CACPrivKey(CKYByte instance, const PKCS11Object &cert) : 
41c127
+CACPrivKey::CACPrivKey(CKYByte instance, const PKCS11Object &cert,bool isPIV) : 
41c127
         PKCS11Object( ((int)'k') << 24 | ((int)instance+'0') << 16,
41c127
                          instance | 0x400)
41c127
 {
41c127
@@ -1242,7 +1242,9 @@ CACPrivKey::CACPrivKey(CKYByte instance,
41c127
 
41c127
     /* So we know what the key is supposed to be used for based on
41c127
      * the instance */
41c127
-    if (instance == 2) {
41c127
+    /* instance 2 is usually a decryption cert. >2 are usually old decryption 
41c127
+     * certs */
41c127
+    if (instance == 2 || (instance > (isPIV ? 3 : 2))) {
41c127
         decrypt = TRUE;
41c127
     }
41c127
 
41c127
@@ -1305,8 +1307,8 @@ CACPrivKey::CACPrivKey(CKYByte instance,
41c127
      CKYBuffer_FreeData(&param2);
41c127
 }
41c127
 
41c127
-CACPubKey::CACPubKey(CKYByte instance, const PKCS11Object &cert) : 
41c127
-        PKCS11Object( ((int)'k') << 24 | ((int)(instance+'5')) << 16,
41c127
+CACPubKey::CACPubKey(CKYByte instance, const PKCS11Object &cert, bool isPIV) : 
41c127
+        PKCS11Object( ((int)'k') << 24 | ((int)(instance+'a')) << 16,
41c127
                        instance | 0x500)
41c127
 {
41c127
     CKYBuffer id;
41c127
@@ -1315,7 +1317,7 @@ CACPubKey::CACPubKey(CKYByte instance, c
41c127
 
41c127
     /* So we know what the key is supposed to be used for based on
41c127
      * the instance */
41c127
-    if (instance == 2) {
41c127
+    if (instance == 2 || (instance > (isPIV ? 3 : 2))) {
41c127
         encrypt = TRUE;
41c127
     }
41c127
 
41c127
@@ -1359,6 +1361,9 @@ CACPubKey::CACPubKey(CKYByte instance, c
41c127
             setAttribute(CKA_EC_POINT, &param1);
41c127
             setAttribute(CKA_EC_PARAMS, &param2);
41c127
 	    setAttributeULong(CKA_KEY_TYPE, CKK_EC);
41c127
+    	    setAttributeBool(CKA_VERIFY_RECOVER, FALSE);
41c127
+    	    setAttributeBool(CKA_ENCRYPT, FALSE);
41c127
+    	    setAttributeBool(CKA_DERIVE, encrypt);
41c127
             break;
41c127
         default:
41c127
             break;
41c127
@@ -1376,6 +1381,26 @@ static const char *CAC_Label[] = {
41c127
         "CAC ID Certificate",
41c127
         "CAC Email Signature Certificate",
41c127
         "CAC Email Encryption Certificate",
41c127
+        "CAC Cert 3",
41c127
+        "CAC Cert 4",
41c127
+        "CAC Cert 5",
41c127
+        "CAC Cert 6",
41c127
+        "CAC Cert 7",
41c127
+        "CAC Cert 8",
41c127
+        "CAC Cert 9",
41c127
+};
41c127
+
41c127
+static const char *PIV_Label[] = {
41c127
+        "PIV ID Certificate",
41c127
+        "PIV Email Signature Certificate",
41c127
+        "PIV Email Encryption Certificate",
41c127
+        "PIV Card Authentication Certificate",
41c127
+        "PIV Cert 4",
41c127
+        "PIV Cert 5",
41c127
+        "PIV Cert 6",
41c127
+        "PIV Cert 7",
41c127
+        "PIV Cert 8",
41c127
+        "PIV Cert 9",
41c127
 };
41c127
 
41c127
 static const unsigned char CN_DATA[] = { 0x55, 0x4, 0x3 };
41c127
@@ -1454,7 +1479,7 @@ GetUserName(const CKYBuffer *dn)
41c127
     return string;
41c127
 }
41c127
 
41c127
-CACCert::CACCert(CKYByte instance, const CKYBuffer *derCert) : 
41c127
+CACCert::CACCert(CKYByte instance, const CKYBuffer *derCert, bool isPIV) : 
41c127
         PKCS11Object( ((int)'c') << 24 | ((int)instance+'0') << 16, 
41c127
                         instance | 0x600)
41c127
 {
41c127
@@ -1471,7 +1496,7 @@ CACCert::CACCert(CKYByte instance, const
41c127
     setAttribute(CKA_ID, &id;;
41c127
     CKYBuffer_FreeData(&id;;
41c127
     setAttributeULong(CKA_CERTIFICATE_TYPE, CKC_X_509);
41c127
-    setAttribute(CKA_LABEL, CAC_Label[instance]);
41c127
+    setAttribute(CKA_LABEL, isPIV ? PIV_Label[instance] : CAC_Label[instance]);
41c127
 
41c127
     CKYBuffer derSerial; CKYBuffer_InitEmpty(&derSerial);
41c127
     CKYBuffer derSubject; CKYBuffer_InitEmpty(&derSubject);
41c127
diff -up ./src/coolkey/object.h.alt-cac ./src/coolkey/object.h
41c127
--- ./src/coolkey/object.h.alt-cac	2016-12-01 15:37:49.087167430 -0800
41c127
+++ ./src/coolkey/object.h	2016-12-01 15:37:49.115167928 -0800
41c127
@@ -219,17 +219,17 @@ class Cert : public PKCS11Object {
41c127
 
41c127
 class CACPrivKey : public PKCS11Object {
41c127
   public:
41c127
-    CACPrivKey(CKYByte instance, const PKCS11Object &cert);
41c127
+    CACPrivKey(CKYByte instance, const PKCS11Object &cert, bool isPIV);
41c127
 };
41c127
 
41c127
 class CACPubKey : public PKCS11Object {
41c127
   public:
41c127
-    CACPubKey(CKYByte instance, const PKCS11Object &cert);
41c127
+    CACPubKey(CKYByte instance, const PKCS11Object &cert, bool isPIV);
41c127
 };
41c127
 
41c127
 class CACCert : public PKCS11Object {
41c127
   public:
41c127
-    CACCert(CKYByte instance, const CKYBuffer *derCert);
41c127
+    CACCert(CKYByte instance, const CKYBuffer *derCert, bool isPIV);
41c127
 };
41c127
 
41c127
 typedef enum { PK15StateInit, PK15StateNeedObject, 
41c127
diff -up ./src/coolkey/slot.cpp.alt-cac ./src/coolkey/slot.cpp
41c127
--- ./src/coolkey/slot.cpp.alt-cac	2016-12-01 15:37:49.110167839 -0800
41c127
+++ ./src/coolkey/slot.cpp	2016-12-01 15:57:37.307994776 -0800
41c127
@@ -415,8 +415,9 @@ Slot::Slot(const char *readerName_, Log
41c127
 	slotInfoFound(false), context(context_), conn(NULL), state(UNKNOWN), 
41c127
 	isVersion1Key(false), needLogin(false), fullTokenName(false), 
41c127
 	mCoolkey(false), mOldCAC(false), mCACLocalLogin(false),
41c127
-	pivContainer(-1), pivKey(-1), mECC(false), p15aid(0), p15odfAddr(0),
41c127
-	p15tokenInfoAddr(0), p15Instance(0),
41c127
+	pivContainer(-1), pivKey(-1), maxCacCerts(MAX_CERT_SLOTS), 
41c127
+	algs(ALG_NONE), p15aid(0), p15odfAddr(0), p15tokenInfoAddr(0),
41c127
+	p15Instance(0),
41c127
 #ifdef USE_SHMEM
41c127
 	shmem(readerName_),
41c127
 #endif
41c127
@@ -776,6 +777,7 @@ Slot::connectToToken()
41c127
 	 state |= PIV_CARD | APPLET_SELECTABLE | APPLET_PERSONALIZED;
41c127
 	 isVersion1Key = 0;
41c127
 	 needLogin = true;
41c127
+	 maxCacCerts = MAX_CERT_SLOTS;
41c127
          mCoolkey = 0;
41c127
 	 mOldCAC = 0;
41c127
 	 mCACLocalLogin = getPIVLoginType();
41c127
@@ -927,8 +929,12 @@ Slot::getCACAid()
41c127
 	}
41c127
 	/* yes, fill in the old applets */
41c127
 	mOldCAC = true;
41c127
+	maxCacCerts = 1;
41c127
 	for (i=1; i< MAX_CERT_SLOTS; i++) {
41c127
-	    CACApplet_SelectPKI(conn, &cardAID[i], i, NULL);
41c127
+	    status = CACApplet_SelectPKI(conn, &cardAID[i], i, NULL);
41c127
+	    if (status == CKYSUCCESS) {
41c127
+		maxCacCerts = i+1;
41c127
+	    }
41c127
 	}
41c127
 	return CKYSUCCESS;
41c127
     }
41c127
@@ -986,6 +992,7 @@ Slot::getCACAid()
41c127
     if (certSlot == 0) {
41c127
 	status = CKYAPDUFAIL; /* probably neeed a beter error code */
41c127
     }
41c127
+    maxCacCerts = certSlot;
41c127
 
41c127
 done:
41c127
     CKYBuffer_FreeData(&tBuf);
41c127
@@ -2168,12 +2175,11 @@ Slot::addKeyObject(list<PKCS11Object>& o
41c127
         }
41c127
         keyObj.completeKey(*iter);
41c127
 
41c127
-        /* For now this is how we determine what type of key.
41c127
-           Also for now, allow only one or the other */
41c127
+        /*  use key object to determine what algorithms we support */
41c127
         if ( keyObj.getKeyType() == PKCS11Object::ecc) {
41c127
-            mECC = true;
41c127
+            algs = (SlotAlgs) (algs | ALG_ECC);
41c127
         } else {
41c127
-            mECC = false;
41c127
+            algs = (SlotAlgs) (algs | ALG_RSA);
41c127
         }
41c127
        
41c127
     }
41c127
@@ -2205,7 +2211,7 @@ Slot::addCertObject(list<PKCS11Object>&
41c127
 void
41c127
 Slot::unloadObjects()
41c127
 {
41c127
-    mECC = false;
41c127
+    algs = ALG_NONE;
41c127
     tokenObjects.clear();
41c127
     free(personName);
41c127
     personName = NULL;
41c127
@@ -2269,29 +2275,42 @@ Slot::unloadObjects()
41c127
 // Shared memory segments are fixed size (equal to the object memory size of
41c127
 // the token). 
41c127
 //
41c127
+//
41c127
+//
41c127
+
41c127
+struct SlotDataPair {
41c127
+    unsigned long dataOffset;
41c127
+    unsigned long  dataSize;
41c127
+};
41c127
 
41c127
 struct SlotSegmentHeader {
41c127
     unsigned short version;
41c127
     unsigned short headerSize;
41c127
     unsigned char  valid;
41c127
-    unsigned char  reserved;
41c127
+    unsigned char  firstCacCert;
41c127
     unsigned char  cuid[10];
41c127
-    unsigned short reserved2;
41c127
+
41c127
+    unsigned short reserved; 
41c127
     unsigned short dataVersion;
41c127
     unsigned short dataHeaderOffset;
41c127
     unsigned short dataOffset;
41c127
     unsigned long  dataHeaderSize;
41c127
     unsigned long  dataSize;
41c127
-    unsigned long  cert2Offset;
41c127
-    unsigned long  cert2Size;
41c127
+    unsigned long  nextDataOffset;
41c127
+    SlotDataPair cacCerts[MAX_CERT_SLOTS];
41c127
 };
41c127
 
41c127
+const unsigned char NOT_A_CAC=0xff; /* place in firstCacCert field */
41c127
+const unsigned short CAC_DATA_VERSION=2;
41c127
+
41c127
+
41c127
 #define MAX_OBJECT_STORE_SIZE 15000
41c127
 //
41c127
 // previous development versions used a segment prefix of
41c127
 // "coolkeypk11s"
41c127
 //
41c127
-#define SEGMENT_PREFIX "coolkeypk11s"
41c127
+#define SEGMENT_PREFIX "coolkeypk11t" // update segment since the old cache was
41c127
+                                      // incompatible
41c127
 #define CAC_FAKE_CUID "CAC Certs"
41c127
 SlotMemSegment::SlotMemSegment(const char *readerName): 
41c127
 	segmentAddr(NULL),  segmentSize(0), segment(NULL)
41c127
@@ -2320,9 +2339,8 @@ SlotMemSegment::SlotMemSegment(const cha
41c127
 	return;
41c127
     }
41c127
 
41c127
-    SlotSegmentHeader *segmentHeader = (SlotSegmentHeader *)segmentAddr;
41c127
     if (needInit) {
41c127
-	segmentHeader->valid = 0;
41c127
+	clearValid(0);
41c127
     }
41c127
     segmentSize = segment->getSHMemSize();
41c127
 }
41c127
@@ -2396,6 +2414,18 @@ SlotMemSegment::getDataVersion() const
41c127
     return segmentHeader->dataVersion;
41c127
 }
41c127
 
41c127
+unsigned char
41c127
+SlotMemSegment::getFirstCacCert() const
41c127
+{
41c127
+    if (!segment) {
41c127
+	return NOT_A_CAC;
41c127
+    }
41c127
+
41c127
+    SlotSegmentHeader *segmentHeader = (SlotSegmentHeader *)segmentAddr;
41c127
+
41c127
+    return segmentHeader->firstCacCert;
41c127
+}
41c127
+
41c127
 void
41c127
 SlotMemSegment::setVersion(unsigned short version)
41c127
 {
41c127
@@ -2419,6 +2449,18 @@ SlotMemSegment::setDataVersion(unsigned
41c127
     segmentHeader->dataVersion = version;
41c127
 }
41c127
 
41c127
+void
41c127
+SlotMemSegment::setFirstCacCert(unsigned char firstCacCert)
41c127
+{
41c127
+    if (!segment) {
41c127
+	return;
41c127
+    }
41c127
+
41c127
+    SlotSegmentHeader *segmentHeader = (SlotSegmentHeader *)segmentAddr;
41c127
+
41c127
+    segmentHeader->firstCacCert = firstCacCert;
41c127
+}
41c127
+
41c127
 bool
41c127
 SlotMemSegment::isValid() const
41c127
 {
41c127
@@ -2493,23 +2535,13 @@ SlotMemSegment::readCACCert(CKYBuffer *o
41c127
     int size;
41c127
     CKYByte *data;
41c127
 
41c127
-    switch (instance) {
41c127
-    case 0:
41c127
-	data  = (CKYByte *) &segmentAddr[segmentHeader->dataHeaderOffset];
41c127
-	size = segmentHeader->dataHeaderSize;
41c127
-	break;
41c127
-    case 1:
41c127
-	data  = (CKYByte *) &segmentAddr[segmentHeader->dataOffset];
41c127
-	size = segmentHeader->dataSize;
41c127
-	break;
41c127
-    case 2:
41c127
-	data  = (CKYByte *) &segmentAddr[segmentHeader->cert2Offset];
41c127
-	size = segmentHeader->cert2Size;
41c127
-	break;
41c127
-    default:
41c127
+    if (instance >= MAX_CERT_SLOTS) {
41c127
 	CKYBuffer_Resize(objData, 0);
41c127
 	return;
41c127
     }
41c127
+    data = (CKYByte *) &segmentAddr[segmentHeader->cacCerts[instance]
41c127
+								.dataOffset];
41c127
+    size = segmentHeader->cacCerts[instance].dataSize;
41c127
     CKYBuffer_Replace(objData, 0, data, size);
41c127
 }
41c127
 
41c127
@@ -2523,30 +2555,20 @@ SlotMemSegment::writeCACCert(const CKYBu
41c127
     SlotSegmentHeader *segmentHeader = (SlotSegmentHeader *)segmentAddr;
41c127
     int size = CKYBuffer_Size(data);
41c127
     CKYByte *shmData;
41c127
-    switch (instance) {
41c127
-    case 0:
41c127
-	segmentHeader->headerSize = sizeof *segmentHeader;
41c127
-	segmentHeader->dataHeaderOffset = sizeof *segmentHeader;
41c127
-	segmentHeader->dataHeaderSize = size;
41c127
-	segmentHeader->dataOffset = segmentHeader->dataHeaderOffset + size;
41c127
-	segmentHeader->dataSize = 0;
41c127
-	segmentHeader->cert2Offset = segmentHeader->dataOffset;
41c127
-	segmentHeader->cert2Size = 0;
41c127
-	shmData = (CKYByte *) &segmentAddr[segmentHeader->dataHeaderOffset];
41c127
-	break;
41c127
-    case 1:
41c127
-	segmentHeader->dataSize = size;
41c127
-	segmentHeader->cert2Offset = segmentHeader->dataOffset + size;
41c127
-	segmentHeader->cert2Size = 0;
41c127
-	shmData = (CKYByte *) &segmentAddr[segmentHeader->dataOffset];
41c127
-	break;
41c127
-    case 2:
41c127
-	segmentHeader->cert2Size = size;
41c127
-	shmData = (CKYByte *) &segmentAddr[segmentHeader->cert2Offset];
41c127
-	break;
41c127
-    default:
41c127
+
41c127
+    if (instance >= MAX_CERT_SLOTS) {
41c127
 	return;
41c127
     }
41c127
+
41c127
+    if (segmentHeader->firstCacCert == NOT_A_CAC) {
41c127
+	segmentHeader->firstCacCert = instance;
41c127
+    }
41c127
+    unsigned long dataOffset = segmentHeader->nextDataOffset;
41c127
+    segmentHeader->cacCerts[instance].dataOffset = dataOffset;
41c127
+    segmentHeader->nextDataOffset += size;
41c127
+    segmentHeader->cacCerts[instance].dataSize = size;
41c127
+    shmData = (CKYByte *) &segmentAddr[dataOffset];
41c127
+
41c127
     memcpy(shmData, CKYBuffer_Data(data), size);
41c127
 }
41c127
 
41c127
@@ -2558,15 +2580,18 @@ SlotMemSegment::clearValid(CKYByte insta
41c127
 	return;
41c127
     }
41c127
     SlotSegmentHeader *segmentHeader = (SlotSegmentHeader *)segmentAddr;
41c127
-    switch (instance) {
41c127
-    case 0:
41c127
-	segmentHeader->headerSize = 0;
41c127
-	segmentHeader->dataHeaderSize = 0;
41c127
-	/* fall through */
41c127
-    case 1:
41c127
-	segmentHeader->dataSize = 0;
41c127
+
41c127
+    segmentHeader->headerSize = sizeof *segmentHeader;
41c127
+    segmentHeader->dataHeaderOffset = sizeof *segmentHeader;
41c127
+    segmentHeader->dataHeaderSize = 0;
41c127
+    segmentHeader->dataSize = 0;
41c127
+    for (int i=0; i < MAX_CERT_SLOTS; i++) {
41c127
+	segmentHeader->cacCerts[i].dataSize = 0;
41c127
     }
41c127
+    segmentHeader->dataOffset = sizeof *segmentHeader;
41c127
+    segmentHeader->nextDataOffset = sizeof *segmentHeader;
41c127
     segmentHeader->valid = 0;
41c127
+    segmentHeader->firstCacCert = NOT_A_CAC;
41c127
 }
41c127
 
41c127
 void
41c127
@@ -2882,8 +2907,7 @@ berProcess(CKYBuffer *buf, int matchTag,
41c127
 
41c127
 
41c127
 CKYStatus
41c127
-Slot::readCACCertificateFirst(CKYBuffer *cert, CKYSize *nextSize, 
41c127
-			      bool throwException)
41c127
+Slot::readCACCertificateFirst(CKYBuffer *cert, CKYSize *nextSize)
41c127
 {
41c127
     CKYStatus status;
41c127
     CKYISOStatus apduRC;
41c127
@@ -2897,9 +2921,6 @@ Slot::readCACCertificateFirst(CKYBuffer
41c127
 	CKYBuffer_InitEmpty(&certInfo);
41c127
 	CKYBuffer_Resize(cert, 0);
41c127
 	status = PIVApplet_GetCertificate(conn, cert, pivContainer, &apduRC);
41c127
-	if (throwException && (status != CKYSUCCESS)) {
41c127
-	    handleConnectionError();
41c127
-	}
41c127
 	/* actually, on success, we need to parse the certificate and find the
41c127
 	 * propper tag */
41c127
 	if (status == CKYSUCCESS) {
41c127
@@ -2940,10 +2961,10 @@ Slot::readCACCertificateFirst(CKYBuffer
41c127
     if (mOldCAC) {
41c127
 	/* get the first 100 bytes of the cert */
41c127
 	status = CACApplet_GetCertificateFirst(conn, cert, nextSize, &apduRC);
41c127
-	if (throwException && (status != CKYSUCCESS)) {
41c127
-	    handleConnectionError();
41c127
+	if (status == CKYSUCCESS) {
41c127
+	    return status;
41c127
 	}
41c127
-	return status;
41c127
+	/* try to use CACApplet_ReadFile before we give up */
41c127
     }
41c127
 
41c127
     CKYBuffer tBuf;
41c127
@@ -2959,11 +2980,11 @@ Slot::readCACCertificateFirst(CKYBuffer
41c127
 
41c127
     /* handle the new CAC card read */
41c127
     /* read the TLV */
41c127
-    status = CACApplet_ReadFile(conn, CAC_TAG_FILE, &tBuf, NULL);
41c127
+    status = CACApplet_ReadFile(conn, CAC_TAG_FILE, &tBuf, &apduRC);
41c127
     if (status != CKYSUCCESS) {
41c127
 	goto done;
41c127
     }
41c127
-    status = CACApplet_ReadFile(conn, CAC_VALUE_FILE, &vBuf, NULL);
41c127
+    status = CACApplet_ReadFile(conn, CAC_VALUE_FILE, &vBuf, &apduRC);
41c127
     if (status != CKYSUCCESS) {
41c127
 	goto done;
41c127
     }
41c127
@@ -3199,14 +3220,12 @@ Slot::loadCACCert(CKYByte instance)
41c127
     CKYStatus status = CKYSUCCESS;
41c127
     CKYBuffer cert;
41c127
     CKYBuffer rawCert;
41c127
-    CKYBuffer shmCert;
41c127
     CKYSize  nextSize;
41c127
 
41c127
     OSTime time = OSTimeNow();
41c127
 
41c127
     CKYBuffer_InitEmpty(&cert);
41c127
     CKYBuffer_InitEmpty(&rawCert);
41c127
-    CKYBuffer_InitEmpty(&shmCert);
41c127
 
41c127
     //
41c127
     // not all CAC cards have all the PKI instances
41c127
@@ -3215,78 +3234,24 @@ Slot::loadCACCert(CKYByte instance)
41c127
     try {
41c127
         selectCACApplet(instance, false);
41c127
     } catch(PKCS11Exception& e) {
41c127
-	// all CAC's must have instance '0', throw the error it
41c127
-	// they don't.
41c127
-	if (instance == 0) throw e;
41c127
-	// If the CAC doesn't have instance '2', and we were updating
41c127
-	// the shared memory, set it to valid now.
41c127
-	if ((instance == 2) && !shmem.isValid()) {
41c127
-	    shmem.setValid();
41c127
-	}
41c127
 	return;
41c127
     }
41c127
 
41c127
     log->log("CAC Cert %d: select CAC applet:  %d ms\n",
41c127
 						 instance, OSTimeNow() - time);
41c127
 
41c127
-    if (instance == 0) {
41c127
-	readCACCertificateFirst(&rawCert, &nextSize, true);
41c127
-
41c127
-        if(CKYBuffer_Size(&rawCert) <= 1) {
41c127
-             handleConnectionError();
41c127
-        }
41c127
-	log->log("CAC Cert %d: fetch CAC Cert:  %d ms\n", 
41c127
-						instance, OSTimeNow() - time);
41c127
-    }
41c127
-
41c127
-    unsigned short dataVersion = 1;
41c127
-    CKYBool needRead = 1;
41c127
-
41c127
     /* see if it matches the shared memory */
41c127
-    if (shmem.isValid() &&  shmem.getDataVersion() == dataVersion) {
41c127
-	shmem.readCACCert(&shmCert, instance);
41c127
-	CKYSize certSize = CKYBuffer_Size(&rawCert);
41c127
-	CKYSize shmCertSize = CKYBuffer_Size(&shmCert);
41c127
-	const CKYByte *shmData = CKYBuffer_Data(&shmCert);
41c127
-
41c127
-	if (instance != 0) {
41c127
-	    needRead = 0;
41c127
-	}
41c127
-
41c127
-	if (shmCertSize >= certSize) {
41c127
-	    if (memcmp(shmData, CKYBuffer_Data(&rawCert), certSize) == 0) {
41c127
-		/* yes it does, no need to read the rest of the cert, use
41c127
-		 * the cache */
41c127
-		CKYBuffer_Replace(&rawCert, 0, shmData, shmCertSize);
41c127
-		needRead = 0;
41c127
-	    }
41c127
-	}
41c127
-	if (!needRead && (shmCertSize == 0)) {	
41c127
+    if (shmem.isValid() &&  shmem.getDataVersion() == CAC_DATA_VERSION) {
41c127
+	shmem.readCACCert(&rawCert, instance);
41c127
+	if (CKYBuffer_Size(&rawCert) == 0) {
41c127
 	    /* no cert of this type, just return */
41c127
 	    return;
41c127
 	}
41c127
-    }
41c127
-    CKYBuffer_FreeData(&shmCert);
41c127
-
41c127
-    if (needRead) {
41c127
-	/* it doesn't, read the new cert and update the cache */
41c127
-	if (instance == 0) {
41c127
-	    shmem.clearValid(0);
41c127
-	    shmem.setVersion(SHMEM_VERSION);
41c127
-	    shmem.setDataVersion(dataVersion);
41c127
-	} else {
41c127
-	    status = readCACCertificateFirst(&rawCert, &nextSize, false);
41c127
-	
41c127
-	    if ((status != CKYSUCCESS) || (CKYBuffer_Size(&rawCert) <= 1)) {
41c127
-		/* CAC only requires the Certificate in pki '0' */
41c127
-		/* if pki '1' or '2' are empty, treat it as a non-fatal error*/
41c127
-		if (instance == 2) {
41c127
-		    /* we've attempted to read all the certs, shared memory
41c127
-		     * is now valid */
41c127
-		    shmem.setValid();
41c127
-		}
41c127
-		return;
41c127
-	    }
41c127
+    } else {
41c127
+	status = readCACCertificateFirst(&rawCert, &nextSize);
41c127
+	if ((status != CKYSUCCESS) || (CKYBuffer_Size(&rawCert) <= 1)) {
41c127
+	    /*this cert doesn't exist, go to the next one */
41c127
+	    return;
41c127
 	}
41c127
 
41c127
 	if (nextSize) {
41c127
@@ -3298,9 +3263,6 @@ Slot::loadCACCert(CKYByte instance)
41c127
 	    handleConnectionError();
41c127
 	}
41c127
 	shmem.writeCACCert(&rawCert, instance);
41c127
-	if (instance == 2) {
41c127
-	    shmem.setValid();
41c127
-	}
41c127
     }
41c127
 
41c127
 
41c127
@@ -3368,14 +3330,17 @@ Slot::loadCACCert(CKYByte instance)
41c127
     log->log("CAC Cert %d: Cert has been uncompressed:  %d ms\n",
41c127
 						instance, OSTimeNow() - time);
41c127
 
41c127
-    CACCert certObj(instance, &cert);
41c127
-    CACPrivKey privKey(instance, certObj);
41c127
-    CACPubKey pubKey(instance, certObj);
41c127
+    bool isPIV = (bool)((state & PIV_CARD) == PIV_CARD);
41c127
+    CACCert certObj(instance, &cert, isPIV);
41c127
+    CACPrivKey privKey(instance, certObj, isPIV);
41c127
+    CACPubKey pubKey(instance, certObj, isPIV);
41c127
     tokenObjects.push_back(privKey);
41c127
     tokenObjects.push_back(pubKey);
41c127
     tokenObjects.push_back(certObj);
41c127
     if ( pubKey.getKeyType() == PKCS11Object::ecc) {
41c127
-	mECC = 1;
41c127
+        algs = (SlotAlgs) (algs | ALG_ECC);
41c127
+    } else {
41c127
+        algs = (SlotAlgs) (algs | ALG_RSA);
41c127
     }
41c127
 
41c127
     if (personName == NULL) {
41c127
@@ -3388,6 +3353,94 @@ Slot::loadCACCert(CKYByte instance)
41c127
 }
41c127
 
41c127
 void
41c127
+Slot::initCACShMem(void)
41c127
+{
41c127
+    bool failed = false;
41c127
+
41c127
+    unsigned char firstCert = shmem.getFirstCacCert();
41c127
+
41c127
+    log->log("init CACShMem: \n");
41c127
+    /* check to make sure the shared memory is initialized with a CAC card */
41c127
+    if (shmem.isValid() && shmem.getDataVersion() ==  CAC_DATA_VERSION
41c127
+				&& firstCert != NOT_A_CAC) {
41c127
+	CKYBuffer rawCert;
41c127
+	CKYBuffer shmCert;
41c127
+	CKYSize  nextSize;
41c127
+
41c127
+        log->log("init CACShMem: valid CAC cache found firstCert = %d\n",
41c127
+						 firstCert);
41c127
+	CKYBuffer_InitEmpty(&rawCert);
41c127
+	CKYBuffer_InitEmpty(&shmCert);
41c127
+
41c127
+
41c127
+	/* yes, see if it's this cac card by comparing the first cert 
41c127
+	 * in the chain */
41c127
+
41c127
+	/* see if the first cert is in the expected slot */
41c127
+	try {
41c127
+	    selectCACApplet(firstCert, false);
41c127
+ 	} catch(PKCS11Exception& e) {
41c127
+	    failed = true;
41c127
+            log->log("init CACShMem: applet select failed firstCert = %d\n",
41c127
+							firstCert);
41c127
+	}
41c127
+	if (!failed) {
41c127
+	    CKYStatus status = readCACCertificateFirst(&rawCert, &nextSize);
41c127
+	    if ((status != CKYSUCCESS) || CKYBuffer_Size(&rawCert) <= 1) {
41c127
+		failed = true;
41c127
+                log->log("init CACShMem: read Cert failed firstCert = %d\n",
41c127
+			 				firstCert);
41c127
+	    }
41c127
+	}
41c127
+	if (!failed) {
41c127
+	    shmem.readCACCert(&shmCert, firstCert);
41c127
+	    CKYSize certSize = CKYBuffer_Size(&rawCert);
41c127
+	    CKYSize shmCertSize = CKYBuffer_Size(&shmCert);
41c127
+	    const CKYByte *shmData = CKYBuffer_Data(&shmCert);
41c127
+
41c127
+	    if (shmCertSize >= certSize) {
41c127
+		if (memcmp(shmData, CKYBuffer_Data(&rawCert), certSize) == 0) {
41c127
+		    /* this card is cached, go on and use the cache */
41c127
+            	    log->log("init CACShMem: entries match, using cache\n");
41c127
+		    CKYBuffer_FreeData(&rawCert);
41c127
+		    CKYBuffer_FreeData(&shmCert);
41c127
+		    return;
41c127
+		}
41c127
+            }		
41c127
+            log->log("init CACShMem: no entry match certSize=%d"
41c127
+				" shmCertSize=%d\n",certSize, shmCertSize);
41c127
+	}
41c127
+	CKYBuffer_FreeData(&rawCert);
41c127
+	CKYBuffer_FreeData(&shmCert);
41c127
+    }
41c127
+
41c127
+    log->log("init CACShMem: starting new cache valid=%d version=%d "
41c127
+		" firstCert=%d\n",shmem.isValid(), shmem.getDataVersion(), 
41c127
+				firstCert);
41c127
+    /* cache is either invalid or for another card, start initializing it */
41c127
+    shmem.clearValid(0);
41c127
+    shmem.setVersion(SHMEM_VERSION);
41c127
+    shmem.setDataVersion(CAC_DATA_VERSION);
41c127
+}
41c127
+
41c127
+void
41c127
+Slot::verifyCACShMem(void)
41c127
+{
41c127
+    /* if the memory is valid, then nothing to do */
41c127
+    if (shmem.isValid()) {
41c127
+	return;
41c127
+    }
41c127
+    /* if we didn't find any cert fail */
41c127
+    if (shmem.getFirstCacCert() == NOT_A_CAC) {
41c127
+	shmem.clearValid(0);
41c127
+	disconnect();
41c127
+        throw PKCS11Exception(CKR_DEVICE_REMOVED);
41c127
+    }
41c127
+    /* we're all set, let others see our results */
41c127
+    shmem.setValid(); 
41c127
+}
41c127
+
41c127
+void
41c127
 Slot::loadObjects()
41c127
 {
41c127
     // throw away all token objects!
41c127
@@ -3406,9 +3459,11 @@ Slot::loadObjects()
41c127
     std::list<ListObjectInfo>::iterator iter;
41c127
 
41c127
     if (state & GOV_CARD) {
41c127
-	loadCACCert(0);
41c127
-	loadCACCert(1);
41c127
-	loadCACCert(2);
41c127
+	initCACShMem();
41c127
+	for (int i=0; i < maxCacCerts; i++) {
41c127
+	   loadCACCert(i);
41c127
+	}
41c127
+	verifyCACShMem();
41c127
 	status = trans.end();
41c127
 	loadReaderObject();
41c127
 	return;
41c127
@@ -4720,10 +4775,6 @@ Slot::performECCSignature(CKYBuffer *out
41c127
     CKYStatus status = trans.begin(conn);
41c127
     if( status != CKYSUCCESS ) handleConnectionError();
41c127
 
41c127
-    if (!mECC) {
41c127
-        throw PKCS11Exception(CKR_FUNCTION_NOT_SUPPORTED);
41c127
-    }
41c127
-
41c127
     CKYISOStatus result;
41c127
     bool loginAttempted = false;
41c127
 
41c127
@@ -4790,9 +4841,6 @@ Slot::performRSAOp(CKYBuffer *output, co
41c127
 		unsigned int keySize, const PKCS11Object *key, 
41c127
 		CKYByte direction)
41c127
 {
41c127
-    if ( mECC ) {
41c127
-        throw PKCS11Exception(CKR_FUNCTION_NOT_SUPPORTED);
41c127
-    }
41c127
 
41c127
     //
41c127
     // establish a transaction
41c127
@@ -5145,10 +5193,6 @@ Slot::performECCKeyAgreement(CK_MECHANIS
41c127
 	CKYBuffer *publicDataBuffer, CKYBuffer *secretKeyBuffer, 
41c127
 	const PKCS11Object *key, unsigned int keySize)
41c127
 {
41c127
-    if (!mECC) {
41c127
-       throw PKCS11Exception(CKR_FUNCTION_NOT_SUPPORTED);
41c127
-    }
41c127
-
41c127
     Transaction trans;
41c127
     CKYStatus status = trans.begin(conn);
41c127
     if( status != CKYSUCCESS ) handleConnectionError();
41c127
diff -up ./src/coolkey/slot.h.alt-cac ./src/coolkey/slot.h
41c127
--- ./src/coolkey/slot.h.alt-cac	2016-12-01 15:37:49.104167732 -0800
41c127
+++ ./src/coolkey/slot.h	2016-12-01 15:37:49.117167964 -0800
41c127
@@ -79,9 +79,11 @@ public:
41c127
     bool CUIDIsEqual(const CKYBuffer *cuid) const;
41c127
     unsigned short getVersion() const;
41c127
     unsigned short getDataVersion() const;
41c127
+    unsigned char  getFirstCacCert() const;
41c127
     void setCUID(const CKYBuffer *cuid);
41c127
     void setVersion(unsigned short version);
41c127
     void setDataVersion(unsigned short version);
41c127
+    void setFirstCacCert(unsigned char firstCacCert);
41c127
     bool isValid() const;
41c127
     int size() const;
41c127
     const unsigned char *getCUID() const;
41c127
@@ -90,6 +92,7 @@ public:
41c127
     void setSize(int size);
41c127
     void readData(CKYBuffer *data) const;
41c127
     void writeData(const CKYBuffer *data);
41c127
+    void initCACHeaders(void);
41c127
     void readCACCert(CKYBuffer *data, CKYByte instance) const;
41c127
     void writeCACCert(const CKYBuffer *data, CKYByte instance);
41c127
     void clearValid(CKYByte instance);
41c127
@@ -294,7 +297,13 @@ class CryptParams {
41c127
 				 const CKYBuffer *paddedOutput) const = 0;
41c127
 };
41c127
 
41c127
-#define MAX_CERT_SLOTS 3
41c127
+#define MAX_CERT_SLOTS 10
41c127
+typedef enum {
41c127
+	ALG_NONE= 0x0,
41c127
+	ALG_ECC = 0x1,
41c127
+	ALG_RSA = 0x2
41c127
+} SlotAlgs;
41c127
+
41c127
 #define MAX_AUTH_USERS 3
41c127
 class Slot {
41c127
 
41c127
@@ -349,7 +358,8 @@ class Slot {
41c127
     bool mCACLocalLogin;
41c127
     int pivContainer;
41c127
     int pivKey;
41c127
-    bool mECC;
41c127
+    int maxCacCerts;
41c127
+    SlotAlgs algs;
41c127
     unsigned short p15aid;
41c127
     unsigned short p15odfAddr;
41c127
     unsigned short p15tokenInfoAddr;
41c127
@@ -424,8 +434,7 @@ class Slot {
41c127
     list<ListObjectInfo> fetchSeparateObjects();
41c127
 
41c127
     CKYStatus getCACAid();
41c127
-    CKYStatus readCACCertificateFirst(CKYBuffer *cert, CKYSize *nextSize,
41c127
-                              bool throwException);
41c127
+    CKYStatus readCACCertificateFirst(CKYBuffer *cert, CKYSize *nextSize);
41c127
     CKYStatus readCACCertificateAppend(CKYBuffer *cert, CKYSize nextSize);
41c127
 
41c127
     CKYStatus getP15Params();
41c127
@@ -485,6 +494,8 @@ class Slot {
41c127
     void processComputeCrypt(CKYBuffer *result, const CKYAPDU *apdu);
41c127
 
41c127
     CKYByte objectToKeyNum(const PKCS11Object *key);
41c127
+    void initCACShMem(void);
41c127
+    void verifyCACShMem(void);
41c127
     Slot(const Slot &cpy)
41c127
 #ifdef USE_SHMEM
41c127
 	: shmem(readerName)
41c127
@@ -580,7 +591,7 @@ class Slot {
41c127
        CK_OBJECT_HANDLE hBaseKey, CK_ATTRIBUTE_PTR pTemplate, 
41c127
        CK_ULONG ulAttributeCount, CK_OBJECT_HANDLE_PTR phKey, CryptParams& params);
41c127
 
41c127
-    bool getIsECC() { return mECC; }
41c127
+    SlotAlgs getAlgs() { return algs; }
41c127
 };
41c127
 
41c127
 class SlotList {