Blob Blame History Raw
diff -up ./src/coolkey/object.cpp.cardos-5-3 ./src/coolkey/object.cpp
--- ./src/coolkey/object.cpp.cardos-5-3	2017-03-16 17:14:02.415338726 -0700
+++ ./src/coolkey/object.cpp	2017-03-16 17:14:02.419338794 -0700
@@ -32,7 +32,7 @@ const CKYByte eccOID[] = {0x2a,0x86,0x48
 void dump(const char *label, const CKYBuffer *buf)
 {
     CKYSize i;
-    CKYSize size = CKYBuffer_Size(buf);
+    CKYSize size = buf ? CKYBuffer_Size(buf) : 0;
 #define ROW_LENGTH 60
     char string[ROW_LENGTH+1];
     char *bp = &string[0];
diff -up ./src/coolkey/object.h.cardos-5-3 ./src/coolkey/object.h
--- ./src/coolkey/object.h.cardos-5-3	2017-03-16 17:14:02.415338726 -0700
+++ ./src/coolkey/object.h	2017-03-16 17:14:02.419338794 -0700
@@ -200,9 +200,11 @@ class PKCS11Object {
     CK_USER_TYPE getUser(void) const { return user; }
     void setKeyType(KeyType theType) { keyType = theType; }
     void setKeySize(unsigned int keySize_) { keySize = keySize_; }
+    void setUser(CK_USER_TYPE user_) { user = user_; }
     const CKYBuffer *getAuthId(void) const { return &authId; }
     const CKYBuffer *getPinAuthId(void) const { return &pinAuthId; }
     const PK15ObjectPath &getObjectPath() const { return objectPath; }
+    void setObjectPath(const PK15ObjectPath &newPath) { objectPath = newPath; }
     void completeKey(const PKCS11Object &cert);
 };
 
@@ -308,6 +310,7 @@ class PK15Object : public PKCS11Object {
     bool isLocal(void) const { return 
 			(pinInfo.pinFlags & P15PinLocal) ? true : false; }
     const P15PinInfo *getPinInfo(void) const { return &pinInfo; }
+    void setPinRef(CK_BYTE pinRef) { pinInfo.pinRef = pinRef; }
 };
 
 class Reader : public PKCS11Object {
diff -up ./src/coolkey/slot.cpp.cardos-5-3 ./src/coolkey/slot.cpp
--- ./src/coolkey/slot.cpp.cardos-5-3	2017-03-16 17:14:02.416338743 -0700
+++ ./src/coolkey/slot.cpp	2017-03-17 13:48:26.661205327 -0700
@@ -41,6 +41,7 @@
 #define PRINTF(args)
 #endif
 // #define DISPLAY_WHOLE_GET_DATA 1
+void dump(const char *label, const CKYBuffer *buf);
 
 
 // The Cyberflex Access 32k egate ATR
@@ -467,6 +468,8 @@ Slot::Slot(const char *readerName_, Log
     }
     CKYBuffer_InitEmpty(&cardATR);
     CKYBuffer_InitEmpty(&mCUID);
+    CKYBuffer_InitEmpty(&candidateUserAuthId);
+    CKYBuffer_InitEmpty(&candidateContextSpecificAuthId);
     for (int i=0; i < MAX_CERT_SLOTS; i++) {
 	CKYBuffer_InitEmpty(&cardAID[i]);
     }
@@ -540,6 +543,8 @@ Slot::~Slot()
     CKYBuffer_FreeData(&nonce);
     CKYBuffer_FreeData(&cardATR);
     CKYBuffer_FreeData(&mCUID);
+    CKYBuffer_FreeData(&candidateUserAuthId);
+    CKYBuffer_FreeData(&candidateContextSpecificAuthId);
     CKYBuffer_FreeData(&p15AID);
     CKYBuffer_FreeData(&p15odf);
     CKYBuffer_FreeData(&p15tokenInfo);
@@ -1272,6 +1277,41 @@ class ObjectKeyCKAIDMatch {
     }
 };
 
+#ifdef DEBUG
+void
+dumpPin(const char *label, const PK15Object *pin)
+{
+    const P15PinInfo *pinInfo = pin->getPinInfo();
+    const PK15ObjectPath &pinPath=pin->getObjectPath(); 
+    unsigned int pin_type = (unsigned int) pinInfo->pinType;
+    const char *pin_name[3] = {"BCD", "ASCIINum", "UTF8" };
+
+    printf("Pin Object %s\n",label);
+    printf(" Pin flags=0x%08lx\n",pinInfo->pinFlags);
+    printf(" Pin type=%d (%s)\n",(int) pin_type, 
+		pin_type < 3U ? pin_name[pin_type] :
+		"Invalid");
+    printf(" Pin length= %d (%d - %d)\n",(int)pinInfo->storedLength,
+					(int)pinInfo->minLength, 
+					(int)pinInfo->maxLength);
+    printf(" Pin pad = 0x%02x,<%c>\n", pinInfo->padChar, pinInfo->padChar);
+    printf(" Pin Ref = 0x%02x\n", pinInfo->pinRef);
+    printf(" Pin Path index = %ld\n",(long)pinPath.getIndex());
+    printf(" Pin Path size = %ld\n",(long)pinPath.getLength());
+    dump(" Pin Path:",pinPath.getPath());
+}
+
+void
+dumpPath(const char *label, const PK15ObjectPath &path) 
+{
+    printf(" Path for %s\n", label);
+    printf(" index = %ld\n",(long)path.getIndex());
+    printf(" size = %ld\n",(long)path.getLength());
+    dump(" objPath:",path.getPath());
+}
+#endif
+
+
 CKYStatus
 Slot::parseEF_Directory(const CKYByte *current, 
 					CKYSize size, PK15ObjectType type)
@@ -1326,7 +1366,22 @@ Slot::parseEF_Directory(const CKYByte *c
 			auth[CKU_SO] = new PK15Object(obj);
 		    }
 		} else if (auth[CKU_USER] == NULL) {
+		    const CKYBuffer *authid = obj.getPinAuthId();
 		    auth[CKU_USER] = new PK15Object(obj);
+		    if ((CKYBuffer_Size(&candidateUserAuthId) != 0) 
+			&& !CKYBuffer_IsEqual(authid, &candidateUserAuthId)) {
+			/* validate our candidates */
+			if ((CKYBuffer_Size(&candidateContextSpecificAuthId)
+			     == 0) || (CKYBuffer_IsEqual(
+				&candidateContextSpecificAuthId, authid))) {
+			    CKYBuffer_Replace(&candidateContextSpecificAuthId,0,
+				CKYBuffer_Data(&candidateUserAuthId),
+			        CKYBuffer_Size(&candidateUserAuthId));
+			}
+			CKYBuffer_Replace(&candidateUserAuthId, 0,
+				CKYBuffer_Data(authid), CKYBuffer_Size(authid));
+		    }
+			
 		} else if (auth[CKU_CONTEXT_SPECIFIC] == NULL) {
 		    ObjectIter iter;
 		    const CKYBuffer *authid = obj.getPinAuthId();
@@ -1339,6 +1394,8 @@ Slot::parseEF_Directory(const CKYByte *c
 			if( CKYBuffer_IsEqual(iter->getAuthId(),authid)) {
 			    iter->setAttributeBool(CKA_ALWAYS_AUTHENTICATE,
 						   TRUE);
+			    iter->setUser(CKU_CONTEXT_SPECIFIC);
+printf("Setting Context Specific pin on key\n");
 			}
 		    }
 		}
@@ -1349,7 +1406,19 @@ Slot::parseEF_Directory(const CKYByte *c
 		{
 		    ObjectConstIter iter;
 		    const CKYBuffer *id;
+		    const CKYBuffer *authid;
 
+		    authid = obj.getAuthId();
+		    if (authid) {
+			if (CKYBuffer_Size(&candidateUserAuthId) == 0) {
+			    CKYBuffer_Replace(&candidateUserAuthId, 0,
+				CKYBuffer_Data(authid), CKYBuffer_Size(authid));
+			} else if (!CKYBuffer_IsEqual(&candidateUserAuthId, 
+							authid)) {
+			    CKYBuffer_Replace(&candidateContextSpecificAuthId,0,
+				CKYBuffer_Data(authid), CKYBuffer_Size(authid));
+			}
+		    }
 		    id = obj.getAttribute(CKA_ID);
 		    if ((!id) || (CKYBuffer_Size(id) != 1)) {
 			break;
@@ -1386,6 +1455,31 @@ Slot::parseEF_Directory(const CKYByte *c
     	    tokenObjects.push_back(obj);
   	} while ( false );
     }
+
+    /* handle the case where we have context specific with the same user pin */
+    if ((type == PK15AuthObj) 
+		&& (CKYBuffer_Size(&candidateContextSpecificAuthId) != 0)
+		&& (auth[CKU_CONTEXT_SPECIFIC] == NULL)) {
+	ObjectIter iter;
+
+	/* these should put on the individual keys */
+	auth[CKU_CONTEXT_SPECIFIC] = new PK15Object(*auth[CKU_USER]);
+	/* set the pin ref for the context specific auth */
+	auth[CKU_CONTEXT_SPECIFIC]->setPinRef(
+	    (CK_BYTE) CKYBuffer_GetChar(&candidateContextSpecificAuthId,0));
+	for( iter = tokenObjects.begin(); iter != tokenObjects.end(); ++iter) {
+	    const CKYBuffer *authid = iter->getAuthId();
+	    if(authid && 
+		CKYBuffer_IsEqual(authid,&candidateContextSpecificAuthId)) {
+		 iter->setAttributeBool(CKA_ALWAYS_AUTHENTICATE, TRUE);
+		 iter->setUser(CKU_CONTEXT_SPECIFIC);
+		 /* auth[CKU_CONTEXT_SPECIFIC]->
+				setObjectPath(iter->getObjectPath()); */
+	    }
+	}
+	
+
+    }
     CKYBuffer_FreeData(&file);
     return CKYSUCCESS;
 }
@@ -2221,6 +2315,12 @@ Slot::unloadObjects()
 	tokenManufacturer = NULL;
     }
     CKYBuffer_Resize(&p15serialNumber,0);
+    CKYBuffer_Resize(&candidateUserAuthId,0);
+    CKYBuffer_Resize(&candidateContextSpecificAuthId,0);
+    for (int i=0; i < MAX_AUTH_USERS; i++) {
+	if (auth[i]) delete auth[i];
+	auth[i]=NULL;
+    }
 }
 
 #ifdef USE_SHMEM
@@ -3766,7 +3866,6 @@ Slot::attemptLogin(CK_USER_TYPE user, bo
 	contextPinCache.clearPin();
     }
 }
-void dump(const char *label, const CKYBuffer *buf);
 
 void
 Slot::attemptP15Login(CK_USER_TYPE user)
@@ -3794,7 +3893,6 @@ Slot::attemptP15Login(CK_USER_TYPE user)
 	throw PKCS11Exception(CKR_DEVICE_ERROR, "Applet select return 0x%04x",
 								result);
     }
-
     status = P15Applet_VerifyPIN(conn, 
 		(const char *)CKYBuffer_Data(pinCachePtr->get()), 
 		auth[user]->getPinInfo(), &result);
@@ -4636,7 +4734,14 @@ Slot::cryptRSA(SessionHandleSuffix suffi
 	    params.padInput(&inputPad, &input);
             performRSAOp(&output, &inputPad, params.getKeySize(), key, 
 							params.getDirection());
-	    params.unpadOutput(result, &output);
+	    if (CKYBuffer_Size(&output) < CKYBuffer_Size(&inputPad)) {
+		/* if the size is smaller than the input, treat it as 
+	         * unpadded */
+		CKYBuffer_Replace(result, 0, CKYBuffer_Data(&output),
+					CKYBuffer_Size(&output));
+	    } else {
+		params.unpadOutput(result, &output);
+	    }
 	    CKYBuffer_FreeData(&input);
 	    CKYBuffer_FreeData(&inputPad);
 	    CKYBuffer_FreeData(&output);
@@ -4787,9 +4892,8 @@ retry:
     } else if (state & CAC_CARD) {
         status = CACApplet_SignDecrypt(conn, input, output, &result);
     } else if (state & P15_CARD) {
-	status = P15Applet_SignDecrypt(conn, key->getKeyRef(), keySize/8,
+	status = P15Applet_SignDecrypt(conn, key->getKeyRef(), (keySize/8)*2,
 				CKY_DIR_ENCRYPT, input, output, &result); 
-	
     } else {
         status = CKYApplet_ComputeECCSignature(conn, objectToKeyNum(key), 					input, NULL, output, getNonce(), &result);
     }
@@ -4861,8 +4965,32 @@ retry:
     } else if (state & CAC_CARD) {
         status = CACApplet_SignDecrypt(conn, input, output, &result);
     } else if (state & P15_CARD) {
-	status = P15Applet_SignDecrypt(conn, key->getKeyRef(), keySize/8,
-				direction, input, output, &result);
+	if (direction == CKY_DIR_DECRYPT) {
+	    status = P15Applet_SignDecrypt(conn, key->getKeyRef(), 
+			keySize/8, direction, input, output, &result);
+	} else {
+	    CKYBuffer unpadInput;
+	    CKYBuffer_InitEmpty(&unpadInput);
+            stripRSAPadding(&unpadInput, input); /* will throw exception 
+						  * on error */
+	    status = P15Applet_SignDecrypt(conn, key->getKeyRef(), keySize/8,
+				direction, &unpadInput, output, &result);
+            CKYBuffer_FreeData(&unpadInput);
+	    /* if it didn't work, try full padded the input first */
+	    if ((status != CKYSUCCESS) 
+		&& (result != CKYISO_CONDITION_NOT_SATISFIED)
+		&& (result != CKYISO_SECURITY_NOT_SATISFIED))  {
+		status = P15Applet_SignDecrypt(conn, key->getKeyRef(), 
+			keySize/8, direction, input, output, &result);
+	    }
+	    /* finally just lie and try to "decrypt" the buffer */
+	    if ((status != CKYSUCCESS) 
+		&& (result != CKYISO_CONDITION_NOT_SATISFIED) 
+		&& (result != CKYISO_SECURITY_NOT_SATISFIED))  {
+		status = P15Applet_SignDecrypt(conn, key->getKeyRef(),
+			 keySize/8, CKY_DIR_DECRYPT, input, output, &result);
+	    }
+	}
     } else {
         status = CKYApplet_ComputeCrypt(conn, objectToKeyNum(key), 
 		CKY_RSA_NO_PAD, direction, input, NULL, output, 
@@ -4883,8 +5011,7 @@ retry:
             throw PKCS11Exception(CKR_DATA_INVALID);
 	}
 	// version0 keys could be logged out in the middle by someone else,
-	// reauthenticate... This code can go away when we depricate.
-        // version0 applets.
+	// reauthenticate... 
 	if (!isVersion1Key && !loginAttempted  && 
 				userPinCache(key->getUser())->isValid() &&
 					(result == CKYISO_UNAUTHORIZED)) {
diff -up ./src/coolkey/slot.h.cardos-5-3 ./src/coolkey/slot.h
--- ./src/coolkey/slot.h.cardos-5-3	2017-03-16 17:14:02.417338760 -0700
+++ ./src/coolkey/slot.h	2017-03-16 17:14:02.421338828 -0700
@@ -368,6 +368,8 @@ class Slot {
     CKYBuffer p15tokenInfo;
     CKYBuffer p15odf;
     CKYBuffer p15serialNumber;
+    CKYBuffer candidateUserAuthId;
+    CKYBuffer candidateContextSpecificAuthId;
     //enum { RW_SESSION_HANDLE = 1, RO_SESSION_HANDLE = 2 };
 
 #ifdef USE_SHMEM
diff -up ./src/libckyapplet/cky_applet.c.cardos-5-3 ./src/libckyapplet/cky_applet.c
--- ./src/libckyapplet/cky_applet.c.cardos-5-3	2017-03-16 17:14:02.404338539 -0700
+++ ./src/libckyapplet/cky_applet.c	2017-03-16 17:14:02.422338845 -0700
@@ -1316,8 +1316,6 @@ P15Applet_SignDecrypt(CKYCardConnection
     int appendLength = length;
     int hasPad = 0;
 
-    /* Hack, lie and say we are always doing encipherment */
-    direction = CKY_DIR_DECRYPT;
     CKYBuffer_Resize(result,0);
     /*
      * first set the security environment
@@ -1367,7 +1365,7 @@ P15Applet_SignDecrypt(CKYCardConnection
     }
     CKYBuffer_AppendBuffer(&tmp, data, offset, appendLength);
     pso.chain = 0;
-    pso.retLen = dataSize;
+    pso.retLen = keySize;
 
     ret = CKYApplet_HandleAPDU(conn, 
 		P15AppletFactory_PerformSecurityOperation, &pso, NULL,