diff --git a/SOURCES/coolkey-1.1.0-cardos-5-3.patch b/SOURCES/coolkey-1.1.0-cardos-5-3.patch
new file mode 100644
index 0000000..5f570ea
--- /dev/null
+++ b/SOURCES/coolkey-1.1.0-cardos-5-3.patch
@@ -0,0 +1,324 @@
+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, 
diff --git a/SPECS/coolkey.spec b/SPECS/coolkey.spec
index 173d287..0a948f7 100644
--- a/SPECS/coolkey.spec
+++ b/SPECS/coolkey.spec
@@ -22,7 +22,7 @@
 
 Name: coolkey
 Version: 1.1.0
-Release: 36%{?dist}
+Release: 37%{?dist}
 Summary: CoolKey PKCS #11 module
 License: LGPLv2
 URL: http://directory.fedora.redhat.com/wiki/CoolKey
@@ -46,6 +46,7 @@ Patch24: coolkey-1.1.0-more-keys.patch
 Patch25: coolkey-1.1.0-fail-on-bad-mechanisms.patch
 Patch26: coolkey-1.1.0-max-cpu-bug.patch
 Patch27: coolkey-1.1.0-rhel7-alt-cac.patch
+Patch28: coolkey-1.1.0-cardos-5-3.patch
 
 
 Group: System Environment/Libraries
@@ -95,6 +96,7 @@ Linux Driver support to access the CoolKey applet.
 %patch25 -b .fail-on-bad-mechanisms
 %patch26 -b .max-cpu-bug
 %patch27 -b .alt-cac
+%patch28 -b .cardos-5-3
 
 %build
 autoconf
@@ -153,6 +155,9 @@ fi
 
 
 %changelog
+* Tue Mar 14 2017 Robert Relyea <rrelyea@redhat.com> - 1.1.0-37
+- get Cardos 5.3 cards working properly
+
 * Thu Dec 1 2016 Robert Relyea <rrelyea@redhat.com> - 1.1.0-36
 - recognize up to 10 cac and PIV certs rather than 3