Sync from SUSE:SLFO:Main coolkey revision 49a1525bab253554619a9cae784ac586

This commit is contained in:
Adrian Schröter 2024-05-03 11:50:56 +02:00
commit ba9ee4f8e8
24 changed files with 13114 additions and 0 deletions

23
.gitattributes vendored Normal file
View File

@ -0,0 +1,23 @@
## Default LFS
*.7z filter=lfs diff=lfs merge=lfs -text
*.bsp filter=lfs diff=lfs merge=lfs -text
*.bz2 filter=lfs diff=lfs merge=lfs -text
*.gem filter=lfs diff=lfs merge=lfs -text
*.gz filter=lfs diff=lfs merge=lfs -text
*.jar filter=lfs diff=lfs merge=lfs -text
*.lz filter=lfs diff=lfs merge=lfs -text
*.lzma filter=lfs diff=lfs merge=lfs -text
*.obscpio filter=lfs diff=lfs merge=lfs -text
*.oxt filter=lfs diff=lfs merge=lfs -text
*.pdf filter=lfs diff=lfs merge=lfs -text
*.png filter=lfs diff=lfs merge=lfs -text
*.rpm filter=lfs diff=lfs merge=lfs -text
*.tbz filter=lfs diff=lfs merge=lfs -text
*.tbz2 filter=lfs diff=lfs merge=lfs -text
*.tgz filter=lfs diff=lfs merge=lfs -text
*.ttf filter=lfs diff=lfs merge=lfs -text
*.txz filter=lfs diff=lfs merge=lfs -text
*.whl filter=lfs diff=lfs merge=lfs -text
*.xz filter=lfs diff=lfs merge=lfs -text
*.zip filter=lfs diff=lfs merge=lfs -text
*.zst filter=lfs diff=lfs merge=lfs -text

3
baselibs.conf Normal file
View File

@ -0,0 +1,3 @@
coolkey
+/usr/lib(64)?/pkcs11/*.so
requires "coolkey = <version>"

View File

@ -0,0 +1,109 @@
diff -up ./src/coolkey/coolkey.cpp.fail-on-bad-mechanisms ./src/coolkey/coolkey.cpp
--- ./src/coolkey/coolkey.cpp.fail-on-bad-mechanisms 2016-06-16 14:36:05.934755563 -0700
+++ ./src/coolkey/coolkey.cpp 2016-06-16 14:36:05.945755372 -0700
@@ -77,7 +77,8 @@ rsaMechanismList[] = {
static const MechInfo
ecMechanismList[] = {
- {CKM_ECDSA,{256,521,CKF_HW | CKF_SIGN | CKF_EC_F_P}},{ CKM_ECDSA_SHA1, {256, 521, CKF_HW | CKF_SIGN | CKF_EC_F_P}},{ CKM_ECDH1_DERIVE,{256, 521, CKF_HW | CKF_DERIVE | CKF_EC_F_P} }
+ {CKM_ECDSA,{256,521,CKF_HW | CKF_SIGN | CKF_EC_F_P}},
+ {CKM_ECDH1_DERIVE,{256, 521, CKF_HW | CKF_DERIVE | CKF_EC_F_P} }
};
unsigned int numRSAMechanisms = sizeof(rsaMechanismList)/sizeof(MechInfo);
diff -up ./src/coolkey/slot.cpp.fail-on-bad-mechanisms ./src/coolkey/slot.cpp
--- ./src/coolkey/slot.cpp.fail-on-bad-mechanisms 2016-06-16 14:36:05.943755407 -0700
+++ ./src/coolkey/slot.cpp 2016-06-16 15:07:40.255882660 -0700
@@ -4185,11 +4185,30 @@ Slot::signInit(SessionHandleSuffix suffi
{
refreshTokenState();
SessionIter session = findSession(suffix);
+ PKCS11Object *key = getKeyFromHandle(hKey);
if( session == sessions.end() ) {
throw PKCS11Exception(CKR_SESSION_HANDLE_INVALID);
}
+ if (pMechanism == NULL) {
+ throw PKCS11Exception(CKR_ARGUMENTS_BAD);
+ }
+
+ switch (pMechanism->mechanism) {
+ case CKM_RSA_PKCS:
+ if (key->getKeyType() != Key::rsa) {
+ throw PKCS11Exception(CKR_KEY_TYPE_INCONSISTENT);
+ }
+ break;
+ case CKM_ECDSA:
+ if (key->getKeyType() != Key::ecc) {
+ throw PKCS11Exception(CKR_KEY_TYPE_INCONSISTENT);
+ }
+ break;
+ default:
+ throw PKCS11Exception(CKR_MECHANISM_INVALID);
+ }
- session->signatureState.initialize(getKeyFromHandle(hKey));
+ session->signatureState.initialize(key);
}
void
@@ -4198,11 +4217,24 @@ Slot::decryptInit(SessionHandleSuffix su
{
refreshTokenState();
SessionIter session = findSession(suffix);
+ PKCS11Object *key = getKeyFromHandle(hKey);
if( session == sessions.end() ) {
throw PKCS11Exception(CKR_SESSION_HANDLE_INVALID);
}
+ if (pMechanism == NULL) {
+ throw PKCS11Exception(CKR_ARGUMENTS_BAD);
+ }
+ switch (pMechanism->mechanism) {
+ case CKM_RSA_PKCS:
+ if (key->getKeyType() != Key::rsa) {
+ throw PKCS11Exception(CKR_KEY_TYPE_INCONSISTENT);
+ }
+ break;
+ default:
+ throw PKCS11Exception(CKR_MECHANISM_INVALID);
+ }
- session->decryptionState.initialize(getKeyFromHandle(hKey));
+ session->decryptionState.initialize(key);
}
/**
@@ -5008,8 +5040,23 @@ Slot::derive(SessionHandleSuffix suffix,
ECCKeyAgreementParams params(CryptParams::ECC_DEFAULT_KEY_SIZE);
SessionIter session = findSession(suffix);
+ PKCS11Object *key=getKeyFromHandle(hBaseKey);
- session->keyAgreementState.initialize(getKeyFromHandle(hBaseKey));
+ if (pMechanism == NULL ) {
+ throw PKCS11Exception(CKR_ARGUMENTS_BAD);
+ }
+
+ switch (pMechanism->mechanism) {
+ case CKM_ECDH1_DERIVE:
+ if (key->getKeyType() != Key::ecc) {
+ throw PKCS11Exception(CKR_KEY_TYPE_INCONSISTENT);
+ }
+ break;
+ default:
+ throw PKCS11Exception(CKR_MECHANISM_INVALID);
+ }
+
+ session->keyAgreementState.initialize(key);
deriveECC(suffix, pMechanism, hBaseKey, pTemplate, ulAttributeCount,
phKey, params);
@@ -5018,9 +5065,6 @@ Slot::derive(SessionHandleSuffix suffix,
void Slot::deriveECC(SessionHandleSuffix suffix, CK_MECHANISM_PTR pMechanism,
CK_OBJECT_HANDLE hBaseKey, CK_ATTRIBUTE_PTR pTemplate, CK_ULONG ulAttributeCount, CK_OBJECT_HANDLE_PTR phKey, CryptParams& params)
{
- if (pMechanism == NULL ) {
- throw PKCS11Exception(CKR_ARGUMENTS_BAD);
- }
CK_ECDH1_DERIVE_PARAMS *mechParams = NULL;

View File

@ -0,0 +1,11 @@
diff -up ./src/coolkey/slot.cpp.fix-spurious ./src/coolkey/slot.cpp
--- ./src/coolkey/slot.cpp.fix-spurious 2014-09-26 15:31:17.277958895 -0700
+++ ./src/coolkey/slot.cpp 2014-09-26 15:34:33.218313227 -0700
@@ -1412,6 +1412,7 @@ SlotList::waitForSlotEvent(CK_FLAGS flag
#endif
} while ((status == CKYSUCCESS) ||
(CKYCardContext_GetLastError(context) == SCARD_E_TIMEOUT) ||
+ (CKYCardContext_GetLastError(context) == SCARD_E_UNKNOWN_READER) ||
(CKYCardContext_GetLastError(context) == SCARD_E_READER_UNAVAILABLE) ||
(CKYCardContext_GetLastError(context) == SCARD_E_NO_SERVICE) ||
(CKYCardContext_GetLastError(context) == SCARD_E_SERVICE_STOPPED) );

View File

@ -0,0 +1,12 @@
diff -up ./src/coolkey/slot.cpp.max-cpu-bug ./src/coolkey/slot.cpp
--- ./src/coolkey/slot.cpp.max-cpu-bug 2016-06-30 14:36:10.502785885 -0700
+++ ./src/coolkey/slot.cpp 2016-06-30 14:36:15.812876256 -0700
@@ -1875,6 +1875,8 @@ SlotList::waitForSlotEvent(CK_FLAGS flag
if (status != CKYSUCCESS) {
if ((CKYCardContext_GetLastError(context) ==
SCARD_E_READER_UNAVAILABLE) ||
+ (CKYCardContext_GetLastError(context) ==
+ SCARD_E_UNKNOWN_READER) ||
(CKYCardContext_GetLastError(context) == SCARD_E_TIMEOUT)) {
OSSleep(timeout*PKCS11_CARD_ERROR_LATENCY);
}

View File

@ -0,0 +1,61 @@
diff -up ./src/coolkey/slot.cpp.more_keys ./src/coolkey/slot.cpp
--- ./src/coolkey/slot.cpp.more_keys 2016-06-16 11:50:01.027432856 -0700
+++ ./src/coolkey/slot.cpp 2016-06-16 11:50:13.267224824 -0700
@@ -32,7 +32,8 @@
#define MIN(x, y) ((x) < (y) ? (x) : (y))
-
+#define MAX_NUM_KEYS 32
+#define MAX_NUM_CERTS 32
#ifdef DEBUG
#define PRINTF(args) printf args
@@ -3458,7 +3459,7 @@ Slot::loadObjects()
} else if( type == 'c' ) {
// cert attribute object. find the DER encoding
unsigned short certnum = getObjectIndex(iter->obj.objectID);
- if( certnum > 9 ) {
+ if( certnum > MAX_NUM_CERTS ) {
//invalid object id
throw PKCS11Exception(CKR_DEVICE_ERROR,
"Invalid object id %08x",iter->obj.objectID);
@@ -4154,7 +4155,7 @@ Slot::objectToKeyNum(const PKCS11Object
throw PKCS11Exception(CKR_KEY_HANDLE_INVALID);
}
unsigned short keyNum = getObjectIndex(id);
- if( keyNum > 9 ) {
+ if( keyNum > MAX_NUM_KEYS ) {
throw PKCS11Exception(CKR_KEY_HANDLE_INVALID);
}
return keyNum & 0xFF;
@@ -4911,7 +4912,6 @@ Slot::generateRandom(SessionHandleSuffix
}
}
-#define MAX_NUM_KEYS 8
unsigned int
Slot::getRSAKeySize(PKCS11Object *key)
{
diff -up ./src/coolkey/slot.h.more_keys ./src/coolkey/slot.h
--- ./src/coolkey/slot.h.more_keys 2016-06-16 11:50:08.627303984 -0700
+++ ./src/coolkey/slot.h 2016-06-16 11:54:08.872153180 -0700
@@ -512,7 +512,17 @@ class Slot {
return (char) (objectID >> 24) & 0xff;
}
unsigned short getObjectIndex(unsigned long objectID) const {
- return (char )((objectID >> 16) & 0xff) - '0';
+ char char_index = (char) ((objectID >> 16) & 0xff);
+ if (char_index >= '0' && char_index <= '9') {
+ return char_index - '0';
+ }
+ if (char_index >= 'A' && char_index <= 'Z') {
+ return char_index - 'A' + 10;
+ }
+ if (char_index >= 'a' && char_index <= 'z') {
+ return char_index - 'a' + 26 + 10;
+ }
+ return 0x0100 + char_index;
}
// actually get the size of a key in bits from the card

View File

@ -0,0 +1,18 @@
diff -up ./src/coolkey/slot.cpp.noapplet ./src/coolkey/slot.cpp
--- ./src/coolkey/slot.cpp.noapplet 2013-09-30 14:30:40.069595018 -0700
+++ ./src/coolkey/slot.cpp 2013-09-30 14:31:27.488595000 -0700
@@ -762,13 +762,7 @@ Slot::connectToToken()
CKYCardConnection_GetLastError(conn));
disconnect();
}
- /* CARD is a PIV card */
- state |= PIV_CARD | APPLET_SELECTABLE | APPLET_PERSONALIZED;
- isVersion1Key = 0;
- needLogin = 1;
- mCoolkey = 0;
- mOldCAC = 0;
- mCACLocalLogin = getPIVLoginType();
+ /* CARD is unknown */
return;
}
state |= CAC_CARD | APPLET_SELECTABLE | APPLET_PERSONALIZED;

View File

@ -0,0 +1,210 @@
diff -up ./src/coolkey/object.cpp.p15-coverity ./src/coolkey/object.cpp
--- ./src/coolkey/object.cpp.p15-coverity 2015-07-06 18:02:34.604191118 -0700
+++ ./src/coolkey/object.cpp 2015-07-06 19:06:04.432062377 -0700
@@ -1558,7 +1558,7 @@ unsigned long GetBits(const CKYByte *ent
/* turn the flags into an int */
for (i=0; i < entrySize; i++) {
CKYByte c = rev[entry[i]];
- bits = bits | (c << i*8);
+ bits = bits | (((unsigned long)c) << (i*8));
}
return bits | bitFlag;
}
@@ -1585,8 +1585,8 @@ CKYStatus PK15ObjectPath::setObjectPath(
if (entry == NULL) { return CKYINVALIDDATA; }
tagSize = entry - current;
current += entrySize + tagSize;
+ if (size < (entrySize + tagSize)) { return CKYINVALIDDATA; }
size -= (entrySize +tagSize);
- if (size < 0) { return CKYINVALIDDATA; }
status = CKYBuffer_Replace(&path, 0, entry, entrySize);
if (status != CKYSUCCESS) {
return status;
@@ -1598,8 +1598,8 @@ CKYStatus PK15ObjectPath::setObjectPath(
if (entry == NULL) { return CKYINVALIDDATA; }
tagSize = entry - current;
current += entrySize + tagSize;
+ if (size < (entrySize + tagSize)) { return CKYINVALIDDATA; }
size -= (entrySize +tagSize);
- if (size < 0) { return CKYINVALIDDATA; }
if (entrySize > 5) { return CKYINVALIDDATA; }
for (index = 0, i=0; i < entrySize; i++) {
index = (index << 8) + (unsigned int) entry[i];
@@ -1612,8 +1612,8 @@ CKYStatus PK15ObjectPath::setObjectPath(
if (entry == NULL) { return CKYINVALIDDATA; }
tagSize = entry - current;
current += entrySize + tagSize;
+ if (size < (entrySize + tagSize)) { return CKYINVALIDDATA; }
size -= (entrySize +tagSize);
- if (size < 0) { return CKYINVALIDDATA; }
if (entrySize > 5) { return CKYINVALIDDATA; }
for (length = 0, i=0; i < entrySize; i++) {
length = (length << 8) + (unsigned int) entry[i];
@@ -1741,8 +1741,8 @@ set_key_type:
/* point current to the next section (cass attributes) */
tagSize = commonAttributes - current;
current += commonSize + tagSize;
+ if (currentSize < (commonSize + tagSize)) { return CKYINVALIDDATA; }
currentSize -= (commonSize +tagSize);
- if (currentSize < 0) { return CKYINVALIDDATA; }
/* get the CKA_LABEL */
if (commonAttributes[0] != ASN1_UTF8_STRING) { return CKYINVALIDDATA; }
@@ -1835,8 +1835,8 @@ PK15Object::completeCertObject(const CKY
/* point current to the next section (type attributes) */
tagSize = commonCertAttributes - current;
current += commonSize + tagSize;
+ if (currentSize < (commonSize + tagSize)) { return CKYINVALIDDATA; }
currentSize -= (commonSize +tagSize);
- if (currentSize < 0) { return CKYINVALIDDATA; }
/* get the id */
if (commonCertAttributes[0] != ASN1_OCTET_STRING) { return CKYINVALIDDATA; }
@@ -1907,8 +1907,8 @@ PK15Object::completeAuthObject(const CKY
if (commonAuthAttributes == NULL) { return CKYINVALIDDATA; }
tagSize = commonAuthAttributes - current;
current += commonSize + tagSize;
+ if (currentSize < (commonSize + tagSize)) { return CKYINVALIDDATA; }
currentSize -= (commonSize + tagSize);
- if (currentSize < 0) { return CKYINVALIDDATA; }
if (commonAuthAttributes[0] != ASN1_OCTET_STRING) {
return CKYINVALIDDATA;
}
@@ -1930,8 +1930,8 @@ PK15Object::completeAuthObject(const CKY
if (commonAuthAttributes == NULL) { return CKYINVALIDDATA; }
tagSize = commonAuthAttributes - current;
current += commonSize + tagSize;
- currentSize -= (commonSize +tagSize);
- if (currentSize < 0) { return CKYINVALIDDATA; }
+ if (currentSize < (commonSize + tagSize)) { return CKYINVALIDDATA; }
+ currentSize -= (commonSize + tagSize);
/*
* parse the Pin Auth Attributes
* pinFlags BIT_STRING
@@ -2093,8 +2093,8 @@ PK15Object::completeKeyObject(const CKYB
/* point current to the next section (sublcass attributes) */
tagSize = commonKeyAttributes - current;
current += commonSize + tagSize;
- currentSize -= (commonSize +tagSize);
- if (currentSize < 0) { return CKYINVALIDDATA; }
+ if (currentSize < (commonSize + tagSize)) { return CKYINVALIDDATA; }
+ currentSize -= (commonSize + tagSize);
/* get the id */
if (commonKeyAttributes[0] != ASN1_OCTET_STRING) { return CKYINVALIDDATA; }
@@ -2263,8 +2263,8 @@ CKYStatus PK15Object::completePrivKeyObj
/* point current to the next section (type attributes) */
tagSize = commonPrivKeyAttributes - current;
current += commonSize + tagSize;
+ if (currentSize < (commonSize + tagSize)) { return CKYINVALIDDATA; }
currentSize -= (commonSize +tagSize);
- if (currentSize < 0) { return CKYINVALIDDATA; }
/* subjectName */
if (commonPrivKeyAttributes[0] == ASN1_SEQUENCE) {
@@ -2385,8 +2385,8 @@ PK15Object::completePubKeyObject(const C
/* point current to the next section (type attributes) */
tagSize = commonPubKeyAttributes - current;
current += commonSize + tagSize;
- currentSize -= (commonSize +tagSize);
- if (currentSize < 0) { return CKYINVALIDDATA; }
+ if (currentSize < (commonSize + tagSize)) { return CKYINVALIDDATA; }
+ currentSize -= (commonSize + tagSize);
/* subjectName */
if (commonPubKeyAttributes[0] == ASN1_SEQUENCE) {
@@ -2535,8 +2535,8 @@ PK15Object::completeRawPublicKey(const C
if (entry == NULL) { return CKYINVALIDDATA; }
tagSize = entry - current;
current += entrySize + tagSize;
+ if (size < (entrySize + tagSize)) { return CKYINVALIDDATA; }
size -= (entrySize +tagSize);
- if (size < 0) { return CKYINVALIDDATA; }
if ((entry[0] == 0) && (entrySize > 1)) {
entry++; entrySize--;
}
@@ -2548,8 +2548,8 @@ PK15Object::completeRawPublicKey(const C
if (entry == NULL) { return CKYINVALIDDATA; }
tagSize = entry - current;
current += entrySize + tagSize;
- size -= (entrySize +tagSize);
- if (size < 0) { return CKYINVALIDDATA; }
+ if (size < (entrySize + tagSize)) { return CKYINVALIDDATA; }
+ size -= (entrySize + tagSize);
if ((entry[0] == 0) && (entrySize > 1)) {
entry++; entrySize--;
}
@@ -2682,11 +2682,11 @@ DEREncodedTokenInfo::DEREncodedTokenInfo
if (entry == NULL) return;
tagSize = entry - current;
current += tagSize + entrySize;
+ if (size < tagSize + entrySize) return;
size -= tagSize + entrySize;
if (entrySize < 1) {
version = *entry;
}
- if (size < 0) return;
/* get the serial number */
if (current[0] != ASN1_OCTET_STRING) { return ; }
@@ -2729,6 +2729,8 @@ DEREncodedTokenInfo::DEREncodedTokenInfo
}
/* parsing flags */
+#ifdef notdef
+ /* we arn't using this right now, keep it for future reference */
if (current[0] == ASN1_BIT_STRING) {
/* recordinfo parsing would go here */
unsigned long bits;
@@ -2739,6 +2741,7 @@ DEREncodedTokenInfo::DEREncodedTokenInfo
size -= tagSize + entrySize;
bits = GetBits(entry, entrySize,8,2);
}
+#endif
return;
}
diff -up ./src/coolkey/slot.cpp.p15-coverity ./src/coolkey/slot.cpp
--- ./src/coolkey/slot.cpp.p15-coverity 2015-07-06 18:02:34.606191081 -0700
+++ ./src/coolkey/slot.cpp 2015-07-06 18:02:34.610191006 -0700
@@ -3714,7 +3714,6 @@ void
Slot::attemptP15Login(CK_USER_TYPE user)
{
PinCache *pinCachePtr = userPinCache(user);
- const CKYBuffer *path;
if (user == CKU_USER) {
loggedIn = false;
@@ -3729,7 +3728,6 @@ Slot::attemptP15Login(CK_USER_TYPE user)
"No PKCS #15 auth object for user %d\n", user);
}
- path = auth[user]->getObjectPath().getPath();
status = selectPath(auth[user]->getObjectPath().getPath(), &result);
if( status == CKYSCARDERR ) {
handleConnectionError();
diff -up ./src/libckyapplet/cky_applet.c.p15-coverity ./src/libckyapplet/cky_applet.c
--- ./src/libckyapplet/cky_applet.c.p15-coverity 2015-07-06 18:02:34.606191081 -0700
+++ ./src/libckyapplet/cky_applet.c 2015-07-06 18:02:34.610191006 -0700
@@ -1361,6 +1361,9 @@ P15Applet_SignDecrypt(CKYCardConnection
appendLength = length;
} else {
ret = CKYBuffer_Reserve(&tmp, length);
+ if (ret != CKYSUCCESS) {
+ goto done;
+ }
}
CKYBuffer_AppendBuffer(&tmp, data, offset, appendLength);
pso.chain = 0;
diff -up ./src/libckyapplet/cky_base.c.p15-coverity ./src/libckyapplet/cky_base.c
--- ./src/libckyapplet/cky_base.c.p15-coverity 2015-07-06 18:02:34.607191062 -0700
+++ ./src/libckyapplet/cky_base.c 2015-07-06 18:02:34.610191006 -0700
@@ -736,7 +736,7 @@ CKYAPDU_SetShortReceiveLen(CKYAPDU *apdu
CKYStatus ret;
if (recvlen <= CKYAPDU_MAX_DATA_LEN) {
- return APDU_SetReceiveLen(apdu, (CKYByte)(recvlen & 0xff));
+ return CKYAPDU_SetReceiveLen(apdu, (CKYByte)(recvlen & 0xff));
}
ret = CKYBuffer_Resize(&apdu->apduBuf, CKYAPDU_HEADER_LEN+2);
if (ret != CKYSUCCESS) {

4379
coolkey-1.1.0-p15.patch Normal file

File diff suppressed because it is too large Load Diff

View File

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

BIN
coolkey-1.1.0.tar.gz (Stored with Git LFS) Normal file

Binary file not shown.

28
coolkey-cac-1.patch Normal file
View File

@ -0,0 +1,28 @@
diff -up ./src/coolkey/object.cpp.cac-1 ./src/coolkey/object.cpp
--- ./src/coolkey/object.cpp.cac-1 2010-06-23 04:46:35.726198827 -0700
+++ ./src/coolkey/object.cpp 2010-06-23 04:47:28.073827862 -0700
@@ -505,6 +505,10 @@ dataStart(const CKYByte *buf, unsigned i
unsigned char tag;
unsigned int used_length= 0;
+ if(!buf) {
+ return NULL;
+ }
+
tag = buf[used_length++];
/* blow out when we come to the end */
diff -up ./src/coolkey/slot.cpp.cac-1 ./src/coolkey/slot.cpp
--- ./src/coolkey/slot.cpp.cac-1 2010-06-23 04:46:22.718371631 -0700
+++ ./src/coolkey/slot.cpp 2010-06-23 04:57:04.417774402 -0700
@@ -2192,6 +2192,10 @@ Slot::readCACCertificateFirst(CKYBuffer
if (throwException && (status != CKYSUCCESS)) {
handleConnectionError();
}
+
+ if(CKYBuffer_Size(cert) == 0) {
+ handleConnectionError();
+ }
return status;
}

1013
coolkey-cac.patch Normal file

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,192 @@
CVE-2007-4129 coolkey file and directory permission flaw
Steve Grubb reported: "It looks like coolkey creates /tmp/.pk11ipc1 as a
world writable directory without the sticky bit. And...it creates the files
under that potentially as world writable with the execute bit turned on or
uses the file without any sanity check. coolkey runs as root sometimes and
that makes it susceptible to doing symlink attacks."
I know some folks ship coolkey here, so we've set an embargo of 20070904,
but as it's low severity are happy to extend if anyone wishes.
CVE-2007-4129 for this issue.
Proposed patch from Bob Relyea attached.
===================================================================
Index: src/coolkey/machdep.cpp
===================================================================
RCS file: /cvs/dirsec/coolkey/src/coolkey/machdep.cpp,v
retrieving revision 1.4
diff -u -r1.4 machdep.cpp
--- src/coolkey/machdep.cpp 14 Feb 2007 00:46:28 -0000 1.4
+++ src/coolkey/machdep.cpp 15 Aug 2007 01:41:11 -0000
@@ -185,12 +185,20 @@
#define MAP_INHERIT 0
#endif
+#ifndef BASEPATH
+#ifdef MAC
+#define BASEPATH "/var"
+#else
+#define BASEPATH "/var/cache"
+#endif
+#endif
+
#ifdef FULL_CLEANUP
#define RESERVED_OFFSET 256
-#define MEMSEGPATH "/tmp/.pk11ipc"
+#define MEMSEGPATH BASEPATH"/coolkey-lock"
#else
#define RESERVED_OFFSET 0
-#define MEMSEGPATH "/tmp/.pk11ipc1"
+#define MEMSEGPATH BASEPATH"/coolkey"
#endif
struct SHMemData {
@@ -208,11 +216,6 @@
#ifdef FULL_CLEANUP
flock(fd,LOCK_EX);
unsigned long ref = --(*(unsigned long *)addr);
-#ifdef notdef
- if (ref == 0) {
- unlink(path);
- }
-#endif
flock(fd, LOCK_UN);
#endif
munmap(addr,size+RESERVED_OFFSET);
@@ -225,6 +228,73 @@
}
}
+/*
+ * The cache directory is shared and accessible by anyone, make
+ * sure the cache file we are opening is really a valid cache file.
+ */
+int safe_open(char *path, int flags, int mode, int size)
+{
+ struct stat buf;
+ int fd, ret;
+
+ fd = open (path, flags|O_NOFOLLOW, mode);
+
+ if (fd < 0) {
+ return fd;
+ }
+
+ ret = fstat(fd, &buf);
+ if (ret < 0) {
+ close (fd);
+ return ret;
+ }
+
+ /* our cache files are pretty specific, make sure we are looking
+ * at the correct one */
+
+ /* first, we should own the file ourselves, don't open a file
+ * that someone else wanted us to see. */
+ if (buf.st_uid != getuid()) {
+ close(fd);
+ errno = EACCES;
+ return -1;
+ }
+
+ /* next, there should only be one link in this file. Don't
+ * use this code to trash another file */
+ if (buf.st_nlink != 1) {
+ close(fd);
+ errno = EMLINK;
+ return -1;
+ }
+
+ /* next, This better be a regular file */
+ if (!S_ISREG(buf.st_mode)) {
+ close(fd);
+ errno = EACCES;
+ return -1;
+ }
+
+ /* if the permissions don't match, something is wrong */
+ if ((buf.st_mode & 03777) != mode) {
+ close(fd);
+ errno = EACCES;
+ return -1;
+ }
+
+ /* finally the file should be the correct size. This
+ * check isn't so much to protect from an attack, as it is to
+ * detect a corrupted cache file */
+ if (buf.st_size != size) {
+ close(fd);
+ errno = EACCES;
+ return -1;
+ }
+
+ /* OK, the file checked out, ok to continue */
+ return fd;
+}
+
SHMem::SHMem(): shmemData(0) {}
SHMem *
@@ -248,7 +318,7 @@
return NULL;
}
int mask = umask(0);
- int ret = mkdir (MEMSEGPATH, 0777);
+ int ret = mkdir (MEMSEGPATH, 01777);
umask(mask);
if ((ret == -1) && (errno != EEXIST)) {
delete shmemData;
@@ -264,21 +334,16 @@
shmemData->path[sizeof(MEMSEGPATH)-1] = '/';
strcpy(&shmemData->path[sizeof(MEMSEGPATH)],name);
- int mode = 0777;
- if (strcmp(name,"token_names") != 0) {
- /* each user gets his own uid array */
- sprintf(uid_str, "-%u",getuid());
- strcat(shmemData->path,uid_str);
- mode = 0700;
- }
+ sprintf(uid_str, "-%u",getuid());
+ strcat(shmemData->path,uid_str);
+ int mode = 0600;
+
shmemData->fd = open(shmemData->path,
O_CREAT|O_RDWR|O_EXCL|O_APPEND|O_EXLOCK, mode);
- if (shmemData->fd < 0) {
- needInit = false;
- shmemData->fd = open(shmemData->path,O_RDWR|O_EXLOCK, mode);
- } else {
+ if (shmemData->fd >= 0) {
char *buf;
int len = size+RESERVED_OFFSET;
+ int ret;
buf = (char *)calloc(1,len);
if (!buf) {
@@ -289,8 +354,22 @@
delete shmemData;
return NULL;
}
- write(shmemData->fd,buf,len);
+ ret = write(shmemData->fd,buf,len);
+ if (ret != len) {
+ unlink(shmemData->path);
+#ifdef FULL_CLEANUP
+ flock(shmemData->fd, LOCK_UN);
+#endif
+ delete shmemData;
+ return NULL;
+ }
+
free(buf);
+ } else if (errno == EEXIST) {
+ needInit = false;
+
+ shmemData->fd = safe_open(shmemData->path,O_RDWR|O_EXLOCK, mode,
+ size+RESERVED_OFFSET);
}
if (shmemData->fd < 0) {
delete shmemData;

View File

@ -0,0 +1,86 @@
Fix insertion/removal detection
pcsc now errors out of the SCardGetStatusChange call with
SCARD_E_UNKNOWN_READER if any of the passed readers aren't known.
This includes readers that were very recently forgotton about because
a user just disconnected them.
(See
http://anonscm.debian.org/viewvc/pcsclite/trunk/PCSC/src/winscard_clnt.c?r1=5858&r2=5881
for the change to pcsc)
Unfortunately, this means SECMOD_WaitForAnyTokenEvent will fail with a
SC_NO_EVENT error if a user removes their smartcard at the wrong time.
This patch changes coolkey to detect removed readers before calling
SCardGetStatusChange, so that it can handle the removal itself.
diff -up coolkey-1.1.0/src/coolkey/slot.cpp.fix coolkey-1.1.0/src/coolkey/slot.cpp
--- coolkey-1.1.0/src/coolkey/slot.cpp.fix 2013-05-22 16:23:41.728846957 -0400
+++ coolkey-1.1.0/src/coolkey/slot.cpp 2013-05-22 17:09:59.813958927 -0400
@@ -279,24 +279,22 @@ SlotList::updateReaderList()
* don't recognize.
*/
- /* first though, let's check to see if any previously removed readers have
- * come back from the dead. If the ignored bit has been set, we do not need
- * it any more.
- */
+ /* Iterate through all the readers to see if we need to make unavailable any
+ * freshly removed readers. Also, see if any previously removed
+ * readers have come back from the dead and don't need to be ignored.
+ */
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);
-
+ } else {
+ if (!(knownState & SCARD_STATE_UNAVAILABLE))
+ CKYReader_SetKnownState(&readerStates[ri], knownState | SCARD_STATE_UNAVAILABLE | SCARD_STATE_CHANGED);
}
}
@@ -1238,6 +1236,32 @@ SlotList::waitForSlotEvent(CK_FLAGS flag
throw;
}
+ /* Before round-tripping to the daemon for the duration of the
+ * timeout, first see if we lost any readers, and pick a slot
+ * from that set to return
+ */
+ for (i=0; i < numReaders; i++) {
+ unsigned long knownState = CKYReader_GetKnownState(&readerStates[i]);
+
+ if ((knownState & SCARD_STATE_UNAVAILABLE) &&
+ (knownState & SCARD_STATE_CHANGED)) {
+ CKYReader_SetKnownState(&readerStates[i], knownState & ~SCARD_STATE_CHANGED);
+ readerListLock.releaseLock();
+ *slotp = slotIndexToID(i);
+ found = TRUE;
+ break;
+ }
+ }
+
+ if (found) {
+ break;
+ }
+
+ if (shuttingDown) {
+ readerListLock.releaseLock();
+ break;
+ }
+
if (myNumReaders != numReaders) {
if (myReaderStates) {
delete [] myReaderStates;

54
coolkey-gcc43.patch Normal file
View File

@ -0,0 +1,54 @@
diff -up ./src/coolkey/slot.cpp.coolkey-gcc43 ./src/coolkey/slot.cpp
--- ./src/coolkey/slot.cpp.coolkey-gcc43 2008-02-13 18:01:45.000000000 -0800
+++ ./src/coolkey/slot.cpp 2008-02-13 18:03:05.000000000 -0800
@@ -25,7 +25,6 @@
#include "PKCS11Exception.h"
#include <winscard.h>
#include "slot.h"
-#include <memory.h>
#include "zlib.h"
#include "params.h"
@@ -33,7 +32,6 @@
#define MIN(x, y) ((x) < (y) ? (x) : (y))
-using std::auto_ptr;
#ifdef DEBUG
diff -up ./src/coolkey/machdep.cpp.coolkey-gcc43 ./src/coolkey/machdep.cpp
--- ./src/coolkey/machdep.cpp.coolkey-gcc43 2008-02-13 18:02:06.000000000 -0800
+++ ./src/coolkey/machdep.cpp 2008-02-13 18:04:04.000000000 -0800
@@ -33,6 +33,8 @@
#include <sys/stat.h>
#include <sys/mman.h>
#include <pthread.h>
+#include <string.h>
+#include <stdlib.h>
#endif
#ifdef _WIN32
diff -up ./src/coolkey/log.cpp.coolkey-gcc43 ./src/coolkey/log.cpp
--- ./src/coolkey/log.cpp.coolkey-gcc43 2008-02-13 18:01:55.000000000 -0800
+++ ./src/coolkey/log.cpp 2008-02-13 18:03:37.000000000 -0800
@@ -18,6 +18,8 @@
* ***** END COPYRIGHT BLOCK *****/
#include <string>
+#include <string.h>
+#include <stdlib.h>
#include "mypkcs11.h"
#include <assert.h>
#include <stdio.h>
diff -up ./src/coolkey/object.cpp.coolkey-gcc43 ./src/coolkey/object.cpp
--- ./src/coolkey/object.cpp.coolkey-gcc43 2008-02-13 18:02:20.000000000 -0800
+++ ./src/coolkey/object.cpp 2008-02-13 18:04:22.000000000 -0800
@@ -21,6 +21,7 @@
#include "PKCS11Exception.h"
#include "object.h"
#include <algorithm>
+#include <string.h>
using std::find_if;

685
coolkey-latest.patch Normal file
View File

@ -0,0 +1,685 @@
diff -up ./src/coolkey/slot.cpp.coolkey-latest ./src/coolkey/slot.cpp
--- ./src/coolkey/slot.cpp.coolkey-latest 2009-09-11 13:58:24.423487305 -0700
+++ ./src/coolkey/slot.cpp 2009-09-11 14:04:30.813488220 -0700
@@ -203,6 +203,29 @@ SlotList::readerExists(const char *reade
return FALSE;
}
+bool
+SlotList::readerNameExistsInList(const char *readerName,CKYReaderNameList *readerNameList)
+{
+ if( !readerName || !readerNameList) {
+ return FALSE;
+ }
+
+ int i = 0;
+ int readerNameCnt = CKYReaderNameList_GetCount(*readerNameList);
+
+ const char *curReaderName = NULL;
+ for(i=0; i < readerNameCnt; i++) {
+ curReaderName = CKYReaderNameList_GetValue(*readerNameList,i);
+
+ if(!strcmp(curReaderName,readerName)) {
+ return TRUE;
+ }
+
+ }
+
+ return FALSE;
+}
+
/*
* you need to hold the ReaderList Lock before you can update the ReaderList
*/
@@ -256,6 +279,27 @@ SlotList::updateReaderList()
* don't recognize.
*/
+ /* first though, let's check to see if any previously removed readers have
+ * come back from the dead. If the ignored bit has been set, we do not need
+ * it any more.
+ */
+
+ const char *curReaderName = NULL;
+ unsigned long knownState = 0;
+ for(int ri = 0 ; ri < numReaders; ri ++) {
+
+ knownState = CKYReader_GetKnownState(&readerStates[ri]);
+ if( !(knownState & SCARD_STATE_IGNORE)) {
+ continue;
+ }
+
+ curReaderName = CKYReader_GetReaderName(&readerStates[ri]);
+ if(readerNameExistsInList(curReaderName,&readerNames)) {
+ CKYReader_SetKnownState(&readerStates[ri], knownState & ~SCARD_STATE_IGNORE);
+
+ }
+ }
+
const char *newReadersData[MAX_READER_DELTA];
const char **newReaders = &newReadersData[0];
unsigned int newReaderCount = 0;
@@ -528,7 +572,7 @@ SlotList::getSlotList(CK_BBOOL tokenPres
void
Slot::connectToToken()
{
- CKYStatus status;
+ CKYStatus status = CKYSCARDERR;
OSTime time = OSTimeNow();
mCoolkey = 0;
@@ -537,13 +581,31 @@ Slot::connectToToken()
// try to connect to the card
if( ! CKYCardConnection_IsConnected(conn) ) {
- status = CKYCardConnection_Connect(conn, readerName);
- if( status != CKYSUCCESS ) {
- log->log("Unable to connect to token\n");
+ int i = 0;
+ //for cranky readers try again a few more times
+ while( i++ < 5 && status != CKYSUCCESS )
+ {
+ status = CKYCardConnection_Connect(conn, readerName);
+ if( status != CKYSUCCESS &&
+ CKYCardConnection_GetLastError(conn) == SCARD_E_PROTO_MISMATCH )
+ {
+ log->log("Unable to connect to token status %d ConnGetGetLastError %x .\n",status,CKYCardConnection_GetLastError(conn));
+
+ }
+ else
+ {
+ break;
+ }
+ OSSleep(100000);
+ }
+
+ if( status != CKYSUCCESS)
+ {
state = UNKNOWN;
return;
}
}
+
log->log("time connect: Connect Time %d ms\n", OSTimeNow() - time);
if (!slotInfoFound) {
readSlotInfo();
@@ -562,15 +624,10 @@ Slot::connectToToken()
state = CARD_PRESENT;
}
- if ( CKYBuffer_DataIsEqual(&cardATR, ATR, sizeof (ATR)) ||
- CKYBuffer_DataIsEqual(&cardATR, ATR1, sizeof(ATR1)) ||
- CKYBuffer_DataIsEqual(&cardATR, ATR2, sizeof(ATR2)) ) {
-
- if (Params::hasParam("noAppletOK"))
- {
- state |= APPLET_SELECTABLE;
- mCoolkey = 1;
- }
+ if (Params::hasParam("noAppletOK"))
+ {
+ state |= APPLET_SELECTABLE;
+ mCoolkey = 1;
}
/* support CAC card. identify the card based on applets, not the ATRS */
@@ -631,7 +688,7 @@ Slot::connectToToken()
* unfriendly */
isVersion1Key = 0;
needLogin = 1;
-
+ mCoolkey = 0;
return;
}
mCoolkey = 1;
@@ -1077,6 +1134,7 @@ SlotList::waitForSlotEvent(CK_FLAGS flag
}
throw;
}
+
if (myNumReaders != numReaders) {
if (myReaderStates) {
delete [] myReaderStates;
@@ -1103,6 +1161,7 @@ SlotList::waitForSlotEvent(CK_FLAGS flag
}
}
}
+
if (found || (flag == CKF_DONT_BLOCK) || shuttingDown) {
break;
}
@@ -1272,6 +1331,19 @@ class ObjectHandleMatch {
}
};
+class KeyNumMatch {
+ private:
+ CKYByte keyNum;
+ const Slot &slot;
+ public:
+ KeyNumMatch(CKYByte keyNum_, const Slot &s) : keyNum(keyNum_), slot(s) { }
+ bool operator() (const PKCS11Object& obj) {
+ unsigned long objID = obj.getMuscleObjID();
+ return (slot.getObjectClass(objID) == 'k')
+ && (slot.getObjectIndex(objID) == keyNum);
+ }
+};
+
class ObjectCertCKAIDMatch {
private:
CKYByte cka_id;
@@ -3007,8 +3079,9 @@ Slot::sign(SessionHandleSuffix suffix, C
CK_ULONG ulDataLen, CK_BYTE_PTR pSignature,
CK_ULONG_PTR pulSignatureLen)
{
+ RSASignatureParams params(CryptParams::DEFAULT_KEY_SIZE);
cryptRSA(suffix, pData, ulDataLen, pSignature, pulSignatureLen,
- RSASignatureParams(CryptParams::FIXED_KEY_SIZE));
+ params);
}
void
@@ -3016,14 +3089,15 @@ Slot::decrypt(SessionHandleSuffix suffix
CK_ULONG ulDataLen, CK_BYTE_PTR pDecryptedData,
CK_ULONG_PTR pulDecryptedDataLen)
{
+ RSADecryptParams params(CryptParams::DEFAULT_KEY_SIZE);
cryptRSA(suffix, pData, ulDataLen, pDecryptedData, pulDecryptedDataLen,
- RSADecryptParams(CryptParams::FIXED_KEY_SIZE));
+ params);
}
void
Slot::cryptRSA(SessionHandleSuffix suffix, CK_BYTE_PTR pInput,
CK_ULONG ulInputLen, CK_BYTE_PTR pOutput,
- CK_ULONG_PTR pulOutputLen, const CryptParams& params)
+ CK_ULONG_PTR pulOutputLen, CryptParams& params)
{
refreshTokenState();
SessionIter session = findSession(suffix);
@@ -3041,6 +3115,11 @@ Slot::cryptRSA(SessionHandleSuffix suffi
CKYBuffer *result = &opState.result;
CKYByte keyNum = opState.keyNum;
+ unsigned int keySize = getKeySize(keyNum);
+
+ if(keySize != CryptParams::DEFAULT_KEY_SIZE)
+ params.setKeySize(keySize);
+
if( CKYBuffer_Size(result) == 0 ) {
// we haven't already peformed the decryption, so do it now.
if( pInput == NULL || ulInputLen == 0) {
@@ -3243,3 +3322,36 @@ Slot::generateRandom(SessionHandleSuffix
throw PKCS11Exception(CKR_DEVICE_ERROR);
}
}
+
+#define MAX_NUM_KEYS 8
+unsigned int
+Slot::getKeySize(CKYByte keyNum)
+{
+ unsigned int keySize = CryptParams::DEFAULT_KEY_SIZE;
+ int modSize = 0;
+
+ if(keyNum >= MAX_NUM_KEYS) {
+ return keySize;
+ }
+
+ ObjectConstIter iter;
+ iter = find_if(tokenObjects.begin(), tokenObjects.end(),
+ KeyNumMatch(keyNum,*this));
+
+ if( iter == tokenObjects.end() ) {
+ return keySize;
+ }
+
+ CKYBuffer const *modulus = iter->getAttribute(CKA_MODULUS);
+
+ if(modulus) {
+ modSize = CKYBuffer_Size(modulus);
+ if(CKYBuffer_GetChar(modulus,0) == 0x0) {
+ modSize--;
+ }
+ if(modSize > 0)
+ keySize = modSize * 8;
+ }
+
+ return keySize;
+}
diff -up ./src/coolkey/slot.h.coolkey-latest ./src/coolkey/slot.h
--- ./src/coolkey/slot.h.coolkey-latest 2006-06-09 11:39:11.000000000 -0700
+++ ./src/coolkey/slot.h 2009-09-11 13:58:24.462488099 -0700
@@ -270,10 +270,9 @@ class CryptParams {
protected:
unsigned int getKeySize() const { return keySize; }
public:
- // !!!XXX hack. The right way to get the key size is to get all the
- // key information from the token with MSCListKeys, the same way
- // we get all the object information with MSCListObjects.
- enum { FIXED_KEY_SIZE = 1024 };
+ // set the actual key size obtained from the card
+ void setKeySize(unsigned int newKeySize) { keySize = newKeySize; }
+ enum { DEFAULT_KEY_SIZE = 1024 };
CryptParams(unsigned int keySize_) : keySize(keySize_) { }
@@ -422,7 +421,7 @@ class Slot {
void cryptRSA(SessionHandleSuffix suffix, CK_BYTE_PTR pInput,
CK_ULONG ulInputLen, CK_BYTE_PTR pOutput,
- CK_ULONG_PTR pulOutputLen, const CryptParams& params);
+ CK_ULONG_PTR pulOutputLen, CryptParams& params);
void performRSAOp(CKYBuffer *out, const CKYBuffer *input, CKYByte keyNum,
CKYByte direction);
@@ -460,6 +459,8 @@ class Slot {
return (char )((objectID >> 16) & 0xff) - '0';
}
+ // actually get the size of a key in bits from the card
+ unsigned int getKeySize(CKYByte keyNum);
SessionHandleSuffix openSession(Session::Type type);
void closeSession(SessionHandleSuffix handleSuffix);
@@ -527,6 +528,8 @@ class SlotList {
* has called 'C_GetSlotList' with a NULL parameter */
void updateReaderList();
+ /* see if a reader name exists in a caller provided reader name list. */
+ bool readerNameExistsInList(const char *readerName,CKYReaderNameList *readerNameList );
bool readerExists(const char *readerName, unsigned int *hint = 0);
public:
SlotList(Log *log);
diff -up ./src/libckyapplet/cky_applet.c.coolkey-latest ./src/libckyapplet/cky_applet.c
--- ./src/libckyapplet/cky_applet.c.coolkey-latest 2006-06-09 11:44:17.000000000 -0700
+++ ./src/libckyapplet/cky_applet.c 2009-09-11 13:58:24.464487796 -0700
@@ -134,6 +134,13 @@ CKYAppletFactory_Logout(CKYAPDU *apdu, c
/* Future add WriteObject */
CKYStatus
+CKYAppletFactory_WriteObject(CKYAPDU *apdu, const void *param)
+{
+ const CKYAppletArgWriteObject *wos = (const CKYAppletArgWriteObject *)param;
+ return CKYAPDUFactory_WriteObject(apdu,wos->objectID,wos->offset,wos->size,wos->data);
+}
+
+CKYStatus
CKYAppletFactory_CreateObject(CKYAPDU *apdu, const void *param)
{
const CKYAppletArgCreateObject *cos=(const CKYAppletArgCreateObject *)param;
@@ -192,7 +199,6 @@ CKYAppletFactory_GetLifeCycleV2(CKYAPDU
{
return CKYAPDUFactory_GetLifeCycleV2(apdu);
}
-
CKYStatus
CKYAppletFactory_GetRandom(CKYAPDU *apdu, const void *param)
{
@@ -725,24 +731,48 @@ CKYApplet_ComputeCrypt(CKYCardConnection
CKYAppletArgComputeCrypt ccd;
CKYBuffer empty;
CKYISOStatus status;
+ short dataSize = 0;
int use2APDUs = 0;
+ int use_dl_object = CKYBuffer_Size(data) > 200 ;
CKYBuffer_InitEmpty(&empty);
ccd.keyNumber = keyNumber;
ccd.mode = mode;
ccd.direction = direction;
- ccd.location = CKY_DL_APDU;
+ ccd.location = use_dl_object ? CKY_DL_OBJECT : CKY_DL_APDU;
if (!apduRC)
apduRC = &status;
+ if (use_dl_object) {
+ CKYBuffer sizeBuf;
+
+ CKYBuffer_InitEmpty(&sizeBuf);
+ CKYBuffer_AppendShort(&sizeBuf, CKYBuffer_Size(data));
+
+ ret = CKYApplet_WriteObjectFull(conn, 0xffffffff,
+ 0, CKYBuffer_Size(&sizeBuf), nonce,
+ &sizeBuf, apduRC);
+
+ CKYBuffer_FreeData(&sizeBuf);
+ if( ret != CKYSUCCESS)
+ goto fail;
+
+ ret = CKYApplet_WriteObjectFull(conn, 0xffffffff,
+ 2, CKYBuffer_Size(data), nonce,
+ data, apduRC);
+
+ if(ret != CKYSUCCESS)
+ goto fail;
+ }
+
if (mode == CKY_RSA_NO_PAD) {
- ccd.data = data;
+ ccd.data = use_dl_object ? &empty : data;
ccd.sig = sig;
ret = CKYApplet_HandleAPDU(conn,
CKYAppletFactory_ComputeCryptOneStep, &ccd, nonce,
CKY_SIZE_UNKNOWN, ckyAppletFill_ComputeCryptFinal,
- result, apduRC);
+ use_dl_object ? NULL : result, apduRC);
if (ret == CKYAPDUFAIL && *apduRC == CKYISO_INCORRECT_P2) {
use2APDUs = 1; /* maybe it's an old applet */
}
@@ -759,13 +789,38 @@ CKYApplet_ComputeCrypt(CKYCardConnection
CKYAppletFactory_ComputeCryptInit, &ccd, nonce,
0, CKYAppletFill_Null, NULL, apduRC);
if (ret == CKYSUCCESS) {
- ccd.data = data;
+ ccd.data = use_dl_object ? &empty : data;
ret = CKYApplet_HandleAPDU(conn,
CKYAppletFactory_ComputeCryptFinal, &ccd, nonce,
CKY_SIZE_UNKNOWN, ckyAppletFill_ComputeCryptFinal,
- result, apduRC);
+ use_dl_object ? NULL : result, apduRC);
}
}
+
+ if (use_dl_object && ret == CKYSUCCESS) {
+ CKYBuffer sizeOutBuf;
+ CKYBuffer_InitEmpty(&sizeOutBuf);
+
+ ret = CKYApplet_ReadObjectFull(conn,0xffffffff,
+ 0, 2,
+ nonce,&sizeOutBuf,apduRC);
+
+ if(ret != CKYSUCCESS) {
+ CKYBuffer_FreeData(&sizeOutBuf);
+ goto fail;
+ }
+
+ dataSize = CKYBuffer_GetShort(&sizeOutBuf, 0);
+
+ CKYBuffer_FreeData(&sizeOutBuf);
+
+ ret = CKYApplet_ReadObjectFull(conn,0xffffffff,
+ 2, dataSize,
+ nonce,result,apduRC);
+ }
+
+fail:
+
return ret;
}
@@ -1036,6 +1091,44 @@ CKYApplet_ReadObjectFull(CKYCardConnecti
}
/*
+ * Write Object
+ * This makes multiple APDU calls to write the entire object.
+ *
+ */
+
+CKYStatus
+CKYApplet_WriteObjectFull(CKYCardConnection *conn, unsigned long objectID,
+ CKYOffset offset, CKYSize size, const CKYBuffer *nonce,
+ const CKYBuffer *data, CKYISOStatus *apduRC)
+{
+
+ CKYBuffer chunk;
+ CKYOffset srcOffset = 0;
+ CKYAppletArgWriteObject wod;
+ CKYStatus ret = CKYSUCCESS;
+
+ wod.objectID = objectID;
+ wod.offset = offset;
+ do {
+ wod.size = (CKYByte) MIN(size, 220);
+ ret = CKYBuffer_InitFromBuffer(&chunk, data,
+ srcOffset, wod.size);
+ if(ret == CKYSUCCESS) {
+ wod.data = &chunk;
+ ret = CKYApplet_HandleAPDU(conn, CKYAppletFactory_WriteObject, &wod,
+ nonce, 0, CKYAppletFill_Null, NULL, apduRC);
+ size -= wod.size;
+ wod.offset += wod.size;
+ srcOffset += wod.size;
+ CKYBuffer_FreeData(&chunk);
+ }
+
+ } while ((size > 0) && (ret == CKYSUCCESS));
+
+ return ret;
+}
+
+/*
* List Object cluster
*/
static CKYStatus
diff -up ./src/libckyapplet/cky_applet.h.coolkey-latest ./src/libckyapplet/cky_applet.h
--- ./src/libckyapplet/cky_applet.h.coolkey-latest 2006-06-09 11:44:17.000000000 -0700
+++ ./src/libckyapplet/cky_applet.h 2009-09-11 13:58:24.466487772 -0700
@@ -192,6 +192,14 @@ typedef struct _CKYAppletArgReadObject {
CKYByte size;
} CKYAppletArgReadObject;
+typedef struct _CKYAppletArgWriteObject {
+ unsigned long objectID;
+ CKYOffset offset;
+ CKYByte size;
+ CKYBuffer *data;
+
+} CKYAppletArgWriteObject;
+
typedef struct _CKYAppletArgComputeCrypt {
CKYByte keyNumber;
CKYByte mode;
@@ -250,6 +258,8 @@ CKYStatus CKYAppletFactory_ListPINs(CKYA
/* param == CKYByte * (pointer to pinNumber) */
CKYStatus CKYAppletFactory_Logout(CKYAPDU *apdu, const void *param);
/* Future add WriteObject */
+/* parm == CKYAppletArgWriteObject */
+CKYStatus CKYAppletFactory_WriteObject(CKYAPDU *apdu, const void *param);
/* param == CKYAppletArgCreateObject */
CKYStatus CKYAppletFactory_CreateObject(CKYAPDU *apdu, const void *param);
/* param == CKYAppletArgDeleteObject */
@@ -482,6 +492,17 @@ CKYStatus CKYApplet_ReadObjectAppend(CKY
CKYStatus CKYApplet_ReadObjectFull(CKYCardConnection *conn,
unsigned long objectID, CKYOffset offset, CKYSize size,
const CKYBuffer *nonce, CKYBuffer *data, CKYISOStatus *apduRC);
+/*
+ * There is 1 write command:
+ * CKYApplet_WriteObjectFull can write an entire data object. It makes multiple
+ * apdu calls in order to write the full amount into the buffer. The buffer is
+ * overwritten.
+*/
+
+CKYStatus CKYApplet_WriteObjectFull(CKYCardConnection *conn,
+ unsigned long objectID, CKYOffset offset, CKYSize size,
+ const CKYBuffer *nonce, const CKYBuffer *data, CKYISOStatus *apduRC);
+
CKYStatus CKYApplet_ListObjects(CKYCardConnection *conn, CKYByte seq,
CKYAppletRespListObjects *lop, CKYISOStatus *apduRC);
CKYStatus CKYApplet_GetStatus(CKYCardConnection *conn,
diff -up ./src/libckyapplet/cky_card.c.coolkey-latest ./src/libckyapplet/cky_card.c
--- ./src/libckyapplet/cky_card.c.coolkey-latest 2006-06-09 11:44:17.000000000 -0700
+++ ./src/libckyapplet/cky_card.c 2009-09-11 13:58:24.468487469 -0700
@@ -129,6 +129,7 @@ typedef struct _SCard {
SCardGetStatusChangeFn SCardGetStatusChange;
SCardCancelFn SCardCancel;
SCARD_IO_REQUEST *SCARD_PCI_T0_;
+ SCARD_IO_REQUEST *SCARD_PCI_T1_;
} SCard;
#define GET_ADDRESS(library, scard, name) \
@@ -195,6 +196,12 @@ ckySCard_Init(void)
if( status != CKYSUCCESS ) {
goto fail;
}
+
+ status = ckyShLibrary_getAddress( library,
+ (void**) &scard->SCARD_PCI_T1_, MAKE_DLL_SYMBOL(g_rgSCardT1Pci));
+ if( status != CKYSUCCESS ) {
+ goto fail;
+ }
return scard;
fail:
@@ -884,6 +891,7 @@ struct _CKYCardConnection {
SCARDHANDLE cardHandle;
unsigned long lastError;
CKYBool inTransaction;
+ unsigned long protocol;
};
static void
@@ -894,6 +902,7 @@ ckyCardConnection_init(CKYCardConnection
conn->cardHandle = 0;
conn->lastError = 0;
conn->inTransaction = 0;
+ conn->protocol = SCARD_PROTOCOL_T0;
}
CKYCardConnection *
@@ -934,14 +943,13 @@ CKYCardConnection_Connect(CKYCardConnect
{
CKYStatus ret;
unsigned long rv;
- unsigned long protocol;
ret = CKYCardConnection_Disconnect(conn);
if (ret != CKYSUCCESS) {
return ret;
}
rv = conn->scard->SCardConnect( conn->ctx->context, readerName,
- SCARD_SHARE_SHARED, SCARD_PROTOCOL_T0, &conn->cardHandle, &protocol);
+ SCARD_SHARE_SHARED, SCARD_PROTOCOL_T0 | SCARD_PROTOCOL_T1, &conn->cardHandle, &conn->protocol);
if (rv != SCARD_S_SUCCESS) {
conn->lastError = rv;
return CKYSCARDERR;
@@ -978,7 +986,7 @@ ckyCardConnection_reconnectRaw(CKYCardCo
unsigned long protocol;
rv = conn->scard->SCardReconnect(conn->cardHandle,
- SCARD_SHARE_SHARED, SCARD_PROTOCOL_T0, init, &protocol);
+ SCARD_SHARE_SHARED, SCARD_PROTOCOL_T0 | SCARD_PROTOCOL_T1 , init, &protocol);
if (rv != SCARD_S_SUCCESS) {
conn->lastError = rv;
return CKYSCARDERR;
@@ -1039,10 +1047,17 @@ CKYCardConnection_TransmitAPDU(CKYCardCo
return ret;
}
- rv = conn->scard->SCardTransmit(conn->cardHandle,
- conn->scard->SCARD_PCI_T0_,
- CKYBuffer_Data(&apdu->apduBuf), CKYBuffer_Size(&apdu->apduBuf),
- NULL, response->data, &response->len);
+ if( conn->protocol == SCARD_PROTOCOL_T0 ) {
+ rv = conn->scard->SCardTransmit(conn->cardHandle,
+ conn->scard->SCARD_PCI_T0_,
+ CKYBuffer_Data(&apdu->apduBuf), CKYBuffer_Size(&apdu->apduBuf),
+ NULL, response->data, &response->len);
+ } else {
+ rv = conn->scard->SCardTransmit(conn->cardHandle,
+ conn->scard->SCARD_PCI_T1_,
+ CKYBuffer_Data(&apdu->apduBuf), CKYBuffer_Size(&apdu->apduBuf),
+ NULL, response->data, &response->len);
+ }
if (rv != SCARD_S_SUCCESS) {
conn->lastError =rv;
diff -up ./src/libckyapplet/cky_factory.c.coolkey-latest ./src/libckyapplet/cky_factory.c
--- ./src/libckyapplet/cky_factory.c.coolkey-latest 2006-06-09 11:44:17.000000000 -0700
+++ ./src/libckyapplet/cky_factory.c 2009-09-11 13:58:24.470495267 -0700
@@ -190,8 +190,11 @@ CKYAPDUFactory_ComputeCryptOneStep(CKYAP
CKYSize len;
CKYBuffer buf;
- if (!idata || !(len = CKYBuffer_Size(idata)) || location != CKY_DL_APDU)
- return ret;
+ if (!idata)
+ return ret;
+
+ if (!(len = CKYBuffer_Size(idata)) && location != CKY_DL_OBJECT)
+ return ret;
CKYAPDU_SetCLA(apdu, CKY_CLASS_COOLKEY);
CKYAPDU_SetINS(apdu, CKY_INS_COMPUTE_CRYPT);
@@ -314,8 +317,6 @@ CKYAPDUFactory_Logout(CKYAPDU *apdu, CKY
return CKYSUCCESS;
}
-/* Future add WriteObject */
-
CKYStatus
CKYAPDUFactory_CreateObject(CKYAPDU *apdu, unsigned long objectID, CKYSize size,
unsigned short readACL, unsigned short writeACL, unsigned short deleteACL)
@@ -419,6 +420,58 @@ fail:
}
CKYStatus
+CKYAPDUFactory_WriteObject(CKYAPDU *apdu, unsigned long objectID,
+ CKYOffset offset,CKYSize size,CKYBuffer *data)
+{
+ CKYBuffer buf;
+ CKYStatus ret = CKYSUCCESS;
+ unsigned short dataSize = 0;
+
+ CKYAPDU_SetCLA(apdu, CKY_CLASS_COOLKEY);
+ CKYAPDU_SetINS(apdu, CKY_INS_WRITE_OBJ);
+ CKYAPDU_SetP1(apdu, 0x00);
+ CKYAPDU_SetP2(apdu, 0x00);
+ CKYBuffer_InitEmpty(&buf);
+
+ dataSize = (unsigned short) CKYBuffer_Size(data);
+
+ if(!dataSize) {
+ ret = CKYINVALIDARGS;
+ goto fail;
+ }
+
+ ret = CKYBuffer_AppendLong(&buf,objectID);
+ if (ret != CKYSUCCESS) {
+ goto fail;
+ }
+ ret = CKYBuffer_AppendLong(&buf,offset);
+ if (ret != CKYSUCCESS) {
+ goto fail;
+ }
+ ret = CKYBuffer_AppendChar(&buf, size);
+ if (ret != CKYSUCCESS) {
+ goto fail;
+ }
+
+ ret = CKYAPDU_SetSendDataBuffer(apdu,&buf);
+
+ if (ret != CKYSUCCESS) {
+ goto fail;
+ }
+
+ ret = CKYAPDU_AppendSendDataBuffer(apdu, data);
+
+ if (ret != CKYSUCCESS) {
+ goto fail;
+ }
+
+fail:
+ CKYBuffer_FreeData(&buf);
+ return ret;
+
+}
+
+CKYStatus
CKYAPDUFactory_ListObjects(CKYAPDU *apdu, CKYByte sequence)
{
CKYAPDU_SetCLA(apdu, CKY_CLASS_COOLKEY);
diff -up ./src/libckyapplet/cky_factory.h.coolkey-latest ./src/libckyapplet/cky_factory.h
--- ./src/libckyapplet/cky_factory.h.coolkey-latest 2006-06-09 11:44:17.000000000 -0700
+++ ./src/libckyapplet/cky_factory.h 2009-09-11 13:58:24.472487421 -0700
@@ -190,7 +190,8 @@ CKYStatus CKYAPDUFactory_ChangePIN(CKYAP
const char *oldPin, const char *newPin);
CKYStatus CKYAPDUFactory_ListPINs(CKYAPDU *apdu);
CKYStatus CKYAPDUFactory_Logout(CKYAPDU *apdu, CKYByte pinNumber);
-
+CKYStatus CKYAPDUFactory_WriteObject(CKYAPDU *apdu, unsigned long objectID,
+ CKYOffset offset,CKYSize size,CKYBuffer *data);
/* Future add WriteObject */
CKYStatus CKYAPDUFactory_CreateObject(CKYAPDU *apdu, unsigned long objectID,
CKYSize size, unsigned short readACL, unsigned short writeACL,

View File

@ -0,0 +1,69 @@
diff -up ./src/coolkey/slot.cpp.reader-state-fix ./src/coolkey/slot.cpp
--- ./src/coolkey/slot.cpp.reader-state-fix 2010-09-08 13:25:14.479109000 -0700
+++ ./src/coolkey/slot.cpp 2010-09-08 13:25:14.506109000 -0700
@@ -2185,6 +2185,7 @@ Slot::readCACCertificateFirst(CKYBuffer
{
CKYStatus status;
CKYISOStatus apduRC;
+ *nextSize = 0;
if (mOldCAC) {
/* get the first 100 bytes of the cert */
diff -up ./src/libckyapplet/cky_card.c.reader-state-fix ./src/libckyapplet/cky_card.c
--- ./src/libckyapplet/cky_card.c.reader-state-fix 2010-09-08 14:05:10.859321000 -0700
+++ ./src/libckyapplet/cky_card.c 2010-09-08 14:05:42.792257000 -0700
@@ -27,7 +27,6 @@
#ifndef WINAPI
#define WINAPI
-typedef SCARD_READERSTATE *LPSCARD_READERSTATE;
#endif
#ifndef SCARD_E_NO_READERS_AVAILABLE
diff -up ./src/libckyapplet/cky_card.h.reader-state-fix ./src/libckyapplet/cky_card.h
--- ./src/libckyapplet/cky_card.h.reader-state-fix 2006-06-09 11:44:17.000000000 -0700
+++ ./src/libckyapplet/cky_card.h 2010-09-08 13:25:14.518109000 -0700
@@ -41,23 +41,23 @@ CKYLIST_DECLARE(CKYReaderName, char *)
CKYLIST_DECLARE(CKYCardConnection, CKYCardConnection *)
CKY_BEGIN_PROTOS
-void CKYReader_Init(SCARD_READERSTATE_A *reader);
-void CKYReader_FreeData(SCARD_READERSTATE_A *reader);
+void CKYReader_Init(SCARD_READERSTATE *reader);
+void CKYReader_FreeData(SCARD_READERSTATE *reader);
/*
- * "Accessors": for SCARD_READERSTATE_A structure as a class.
- * These functions take an SCARD_READERSTATE_A which can also be referenced
+ * "Accessors": for SCARD_READERSTATE structure as a class.
+ * These functions take an SCARD_READERSTATE which can also be referenced
* directly.
*/
-CKYStatus CKYReader_SetReaderName(SCARD_READERSTATE_A *reader, const char *name);
-const char *CKYReader_GetReaderName(const SCARD_READERSTATE_A *reader);
-CKYStatus CKYReader_SetKnownState(SCARD_READERSTATE_A *reader,
+CKYStatus CKYReader_SetReaderName(SCARD_READERSTATE *reader, const char *name);
+const char *CKYReader_GetReaderName(const SCARD_READERSTATE *reader);
+CKYStatus CKYReader_SetKnownState(SCARD_READERSTATE *reader,
unsigned long state);
-unsigned long CKYReader_GetKnownState(const SCARD_READERSTATE_A *reader);
-unsigned long CKYReader_GetEventState(const SCARD_READERSTATE_A *reader);
-CKYStatus CKYReader_GetATR(const SCARD_READERSTATE_A *reader, CKYBuffer *buf);
+unsigned long CKYReader_GetKnownState(const SCARD_READERSTATE *reader);
+unsigned long CKYReader_GetEventState(const SCARD_READERSTATE *reader);
+CKYStatus CKYReader_GetATR(const SCARD_READERSTATE *reader, CKYBuffer *buf);
/* create an array of READERSTATEs from a LIST of Readers */
-SCARD_READERSTATE_A *CKYReader_CreateArray(const CKYReaderNameList readerNames,
+SCARD_READERSTATE *CKYReader_CreateArray(const CKYReaderNameList readerNames,
unsigned long *readerCount);
/* frees the reader, then the full array */
void CKYReader_DestroyArray(SCARD_READERSTATE *reader, unsigned long count);
@@ -88,7 +88,7 @@ CKYStatus CKYCardContext_FindReadersByAT
const CKYBuffer *targetATR);
/* return if any of the readers in our array has changed in status */
CKYStatus CKYCardContext_WaitForStatusChange(CKYCardContext *context,
- SCARD_READERSTATE_A *readers,
+ SCARD_READERSTATE *readers,
unsigned long readerCount,
unsigned long timeout);
/* cancel any current operation (such as wait for status change) on this

4792
coolkey-piv-ecc-el7.patch Normal file

File diff suppressed because it is too large Load Diff

71
coolkey-simple-bugs.patch Normal file
View File

@ -0,0 +1,71 @@
diff -up ./configure.in.coolkey-simple-bugs ./configure.in
--- ./configure.in.coolkey-simple-bugs 2009-09-16 11:21:55.621493844 -0700
+++ ./configure.in 2009-09-16 11:22:23.354492383 -0700
@@ -124,9 +124,9 @@ then
if test $WINDOWS -ne 1; then
PKG_CHECK_MODULES(NSS, nss, true, [ AC_MSG_ERROR(could not find NSS Crypto libraries) ])
fi
- enable_pk11install = "yes"
+ enable_pk11install="yes"
else
- enable_pk11install = "no"
+ enable_pk11install="no"
AC_MSG_WARN([skipping pk11install])
fi
diff -up ./Makefile.am.coolkey-simple-bugs ./Makefile.am
--- ./Makefile.am.coolkey-simple-bugs 2009-09-16 11:23:18.715515063 -0700
+++ ./Makefile.am 2009-09-16 13:15:29.570492412 -0700
@@ -25,7 +25,6 @@ if BUILD_PK11INSTALL
SUBDIRS += src/install
endif
-ACLOCAL_AMFLAGS = -I m4
EXTRA_DIST = cookey.spec LICENSE
diff -up ./src/coolkey/object.cpp.coolkey-simple-bugs ./src/coolkey/object.cpp
--- ./src/coolkey/object.cpp.coolkey-simple-bugs 2009-09-16 10:36:29.300516245 -0700
+++ ./src/coolkey/object.cpp 2009-09-16 10:37:17.747492199 -0700
@@ -397,7 +397,7 @@ PKCS11Object::getLabel()
{
// clean up old one
if (label) {
- delete label;
+ delete [] label;
label = NULL;
}
// find matching attribute
diff -up ./src/coolkey/object.h.coolkey-simple-bugs ./src/coolkey/object.h
--- ./src/coolkey/object.h.coolkey-simple-bugs 2009-09-16 16:05:27.233488140 -0700
+++ ./src/coolkey/object.h 2009-09-16 16:05:54.161492421 -0700
@@ -82,7 +82,7 @@ class PKCS11Object {
PKCS11Object(unsigned long muscleObjID, CK_OBJECT_HANDLE handle);
PKCS11Object(unsigned long muscleObjID, const CKYBuffer *data,
CK_OBJECT_HANDLE handle);
- ~PKCS11Object() { delete label; delete name; CKYBuffer_FreeData(&pubKey); }
+ ~PKCS11Object() { delete [] label; delete [] name; CKYBuffer_FreeData(&pubKey); }
PKCS11Object(const PKCS11Object& cpy) :
attributes(cpy.attributes), muscleObjID(cpy.muscleObjID),
diff -up ./src/coolkey/slot.cpp.coolkey-simple-bugs ./src/coolkey/slot.cpp
--- ./src/coolkey/slot.cpp.coolkey-simple-bugs 2009-09-16 10:28:15.412492201 -0700
+++ ./src/coolkey/slot.cpp 2009-09-16 10:57:27.692492487 -0700
@@ -979,7 +979,7 @@ Slot::makeLabelString(char *label, int m
//
#define COOLKEY "CoolKey"
#define POSSESSION " for "
- if (!personName || personName == "") {
+ if (!personName || personName[0] == '\0' ) {
const int coolKeySize = sizeof(COOLKEY) ;
memcpy(label, COOLKEY, coolKeySize-1);
makeSerialString(&label[coolKeySize], maxSize-coolKeySize, cuid);
@@ -1528,7 +1528,7 @@ SlotMemSegment::SlotMemSegment(const cha
}
sprintf(segName,SEGMENT_PREFIX"%s",readerName);
segment = SHMem::initSegment(segName, MAX_OBJECT_STORE_SIZE, needInit);
- delete segName;
+ delete [] segName;
if (!segment) {
// just run without shared memory
return;

158
coolkey-thread-fix.patch Normal file
View File

@ -0,0 +1,158 @@
Index: src/coolkey/coolkey.cpp
===================================================================
RCS file: /cvs/dirsec/coolkey/src/coolkey/coolkey.cpp,v
retrieving revision 1.2
diff -u -r1.2 coolkey.cpp
--- src/coolkey/coolkey.cpp 14 Feb 2007 19:54:01 -0000 1.2
+++ src/coolkey/coolkey.cpp 18 Dec 2009 23:22:58 -0000
@@ -42,7 +42,9 @@
static SlotList *slotList = NULL;
-static OSLock finalizeLock(false);
+static OSLock *finalizeLock = NULL;
+#define FINALIZE_GETLOCK() if (finalizeLock) finalizeLock->getLock();
+#define FINALIZE_RELEASELOCK() if (finalizeLock) finalizeLock->releaseLock();
static CK_BBOOL initialized = FALSE;
static CK_BBOOL finalizing = FALSE;
@@ -208,11 +210,13 @@
if( initialized ) {
return CKR_CRYPTOKI_ALREADY_INITIALIZED;
}
- if (!finalizeLock.isValid()) {
+ if (finalizeLock && !finalizeLock->isValid()) {
return CKR_CANT_LOCK;
}
CK_C_INITIALIZE_ARGS* initArgs = (CK_C_INITIALIZE_ARGS*) pInitArgs;
+ OSLock::setThreadSafe(0);
if( initArgs != NULL ) {
+ bool needThreads;
/* work around a bug in NSS where the library parameters are only
* send if locking is requested */
if (initArgs->LibraryParameters) {
@@ -220,7 +224,17 @@
} else {
Params::ClearParams();
}
- if( (initArgs->flags & CKF_OS_LOCKING_OK) || initArgs->LockMutex ){
+ needThreads = ((initArgs->flags & CKF_OS_LOCKING_OK) != 0);
+ OSLock::setThreadSafe(needThreads);
+ /* don't get a finalize lock unless someone initializes us asking
+ * us to use threads */
+ if (needThreads && !finalizeLock) {
+ finalizeLock = new OSLock(true);
+ if (finalizeLock == NULL) return CKR_HOST_MEMORY;
+ }
+ /* only support OS LOCKING threads */
+ if( ((initArgs->flags & CKF_OS_LOCKING_OK) == 0)
+ && initArgs->LockMutex ){
throw PKCS11Exception(CKR_CANT_LOCK);
}
}
@@ -259,9 +273,9 @@
// the finalizing call first, we know it will set waitEvent before
// we can get the lock, so we only need to protect setting finalizing
// to true.
- finalizeLock.getLock();
+ FINALIZE_GETLOCK();
finalizing = TRUE;
- finalizeLock.releaseLock();
+ FINALIZE_RELEASELOCK();
if (waitEvent) {
/* we're waiting on a slot event, shutdown first to allow
* the wait function to complete before we pull the rug out.
@@ -273,10 +287,10 @@
}
delete slotList;
delete log;
- finalizeLock.getLock();
+ FINALIZE_GETLOCK();
finalizing = FALSE;
initialized = FALSE;
- finalizeLock.releaseLock();
+ FINALIZE_RELEASELOCK();
return CKR_OK;
}
@@ -595,17 +609,17 @@
CK_RV
C_WaitForSlotEvent(CK_FLAGS flags, CK_SLOT_ID_PTR pSlot, CK_VOID_PTR pReserved)
{
- finalizeLock.getLock();
+ FINALIZE_GETLOCK();
if( ! initialized ) {
- finalizeLock.releaseLock();
+ FINALIZE_RELEASELOCK();
return CKR_CRYPTOKI_NOT_INITIALIZED;
}
if (finalizing) {
- finalizeLock.releaseLock();
+ FINALIZE_RELEASELOCK();
return CKR_CRYPTOKI_NOT_INITIALIZED;
}
waitEvent = TRUE;
- finalizeLock.releaseLock();
+ FINALIZE_RELEASELOCK();
try {
log->log("C_WaitForSlotEvent called\n");
slotList->waitForSlotEvent(flags, pSlot, pReserved);
Index: src/coolkey/machdep.cpp
===================================================================
RCS file: /cvs/dirsec/coolkey/src/coolkey/machdep.cpp,v
retrieving revision 1.7
diff -u -r1.7 machdep.cpp
--- src/coolkey/machdep.cpp 14 Feb 2008 23:48:19 -0000 1.7
+++ src/coolkey/machdep.cpp 18 Dec 2009 23:22:58 -0000
@@ -37,6 +37,8 @@
#include <stdlib.h>
#endif
+bool OSLock::needThread = 0;
+
#ifdef _WIN32
//
// Windows functions to grab a named shared memory segment of a specific size,
@@ -123,6 +125,10 @@
OSLock::OSLock(bool exceptionAllowed)
{
+ if (!needThread) {
+ lockData = NULL;
+ return;
+ }
lockData = new OSLockData;
if (lockData) {
InitializeCriticalSection(&lockData->mutex);
@@ -360,6 +366,9 @@
int rc;
lockData = NULL;
+ if (!needThread) {
+ return;
+ }
#ifdef MAC
if (!OSLock_attr_init) {
rc = pthread_mutexattr_init(&OSLock_attr);
Index: src/coolkey/machdep.h
===================================================================
RCS file: /cvs/dirsec/coolkey/src/coolkey/machdep.h,v
retrieving revision 1.1
diff -u -r1.1 machdep.h
--- src/coolkey/machdep.h 9 Jun 2006 18:39:11 -0000 1.1
+++ src/coolkey/machdep.h 18 Dec 2009 23:22:58 -0000
@@ -40,12 +40,14 @@
class OSLock {
private:
OSLockData *lockData;
+ static bool needThread;
public:
OSLock(bool exceptionAllowed = true);
~OSLock();
bool isValid();
void getLock();
void releaseLock();
+ static void setThreadSafe(bool thread) { needThread = thread; }
};
typedef unsigned long OSTime;

89
coolkey.changes Normal file
View File

@ -0,0 +1,89 @@
-------------------------------------------------------------------
Mon Aug 15 19:50:30 UTC 2022 - Dirk Müller <dmueller@suse.com>
- light modernization of the spec file
- avoid bashism in post scripts (bsc#1195391)
-------------------------------------------------------------------
Mon Jul 24 23:02:16 UTC 2017 - jengelh@inai.de
- Remove vision statement and development methods from description.
-------------------------------------------------------------------
Fri Jul 21 14:00:08 CEST 2017 - sbrabec@suse.com
- Add nssdb installation scripts.
- Run spec-cleaner.
- Drop coolkey-1.1.0-evoandooo.patch: The patch does nothing now.
Evolution and LibreOffice changed over time. They moved its
directories and they don't use secmod.db any more.
-------------------------------------------------------------------
Mon Jul 17 20:55:48 CEST 2017 - sbrabec@suse.com
- Integrate latest Centos 7 patches [bsc#1049213]
(coolkey-fix-token-removal-failure.patch,
coolkey-piv-ecc-el7.patch, coolkey-1.1.0-noapplet.patch,
coolkey-1.1.0-fix-spurious-event.patch,
coolkey-1.1.0-p15.patch, coolkey-1.1.0-p15-coverity.patch,
coolkey-1.1.0-more-keys.patch,
coolkey-1.1.0-fail-on-bad-mechanisms.patch,
coolkey-1.1.0-max-cpu-bug.patch,
coolkey-1.1.0-rhel7-alt-cac.patch).
* PK15 support.
* Fix CAC card support.
* Fix card removal issues.
- Use original tarball
(coolkey-1.1.0.tar.bz2 -> coolkey-1.1.0.tar.gz).
- Drop patch coolkey-null.patch. It is now part of
coolkey-piv-ecc-el7.patch.
-------------------------------------------------------------------
Tue Nov 22 16:01:46 CET 2016 - sbrabec@suse.com
- Create baselibs.conf.
- Add PKCS11 module to p11-kit-32bit (bsc#996047#c39).
-------------------------------------------------------------------
Fri Sep 30 20:07:51 UTC 2011 - coolo@suse.com
- add libtool as buildrequire to make the spec file more reliable
-------------------------------------------------------------------
Sat Sep 17 23:52:06 UTC 2011 - jengelh@medozas.de
- Remove redundant tags/sections from specfile
- Use %_smp_mflags for parallel build
-------------------------------------------------------------------
Mon Jan 10 19:19:02 CET 2011 - sbrabec@suse.cz
- Merged latest Fedora patches (bnc#661643).
-------------------------------------------------------------------
Tue Apr 14 18:37:02 CEST 2009 - sbrabec@suse.cz
- Fixed wrong C++ delete (bnc#443369, Redhat#485032).
-------------------------------------------------------------------
Mon Oct 29 17:50:46 CET 2007 - sbrabec@suse.cz
- Fixed gcc 4.3 build errors.
-------------------------------------------------------------------
Mon Sep 10 13:28:16 CEST 2007 - sbrabec@suse.cz
- Fixed file and directory permission flaw (#304180,
CVE-2007-4129).
-------------------------------------------------------------------
Thu Sep 6 21:03:20 CEST 2007 - jberkman@novell.com
- install pk11install
- teach pk11install about evolution and openoffice
-------------------------------------------------------------------
Fri Aug 3 12:31:03 CEST 2007 - sbrabec@suse.cz
- New SuSE package, version 1.1.0.

2
coolkey.rpmlintrc Normal file
View File

@ -0,0 +1,2 @@
# Summary is OK.
addFilter("name-repeated-in-summary")

188
coolkey.spec Normal file
View File

@ -0,0 +1,188 @@
#
# spec file for package coolkey
#
# Copyright (c) 2022 SUSE LLC
#
# All modifications and additions to the file contributed by third parties
# remain the property of their copyright owners, unless otherwise agreed
# upon. The license for this file, and modifications and additions to the
# file, is the same license as for the pristine package itself (unless the
# license for the pristine package is not an Open Source License, in which
# case the license is the MIT License). An "Open Source License" is a
# license that conforms to the Open Source Definition (Version 1.9)
# published by the Open Source Initiative.
# Please submit bugfixes or comments via https://bugs.opensuse.org/
#
%define coolkey_module "CoolKey PKCS #11 Module"
%define nssdb %{_sysconfdir}/pki/nssdb
Name: coolkey
Version: 1.1.0
Release: 0
Summary: CoolKey and CAC PKCS #11 PKI Module for Smart Cards
License: LGPL-2.1-only
Group: Productivity/Security
URL: https://www.dogtagpki.org/wiki/CoolKey
Source: %{name}-%{version}.tar.gz
Source1: %{name}.rpmlintrc
Source2: baselibs.conf
# Patches imported from Fedora and CentOS:
# PATCH-FIX-SECURITY coolkey-cache-dir-move.patch sbrabec@suse.cz bnc304180 CVE-2007-4129 -- Fix file and directory permission flaw.
Patch1: coolkey-cache-dir-move.patch
# PATCH-FIX-FEDORA coolkey-gcc43.patch bnc661643 sbrabec@suse.cz -- Fix for gcc-4.3.
Patch2: coolkey-gcc43.patch
# PATCH-FEATURE-FEDORA coolkey-latest.patch bnc661643 sbrabec@suse.cz -- The head branch patch.
Patch3: coolkey-latest.patch
# PATCH-FIX-FEDORA coolkey-simple-bugs.patch bnc661643 sbrabec@suse.cz -- Fix imported from Fedora, mostly merging former SUSE fixes.
Patch4: coolkey-simple-bugs.patch
# PATCH-FIX-FEDORA coolkey-thread-fix.patch bnc661643 sbrabec@suse.cz -- Fix threading.
Patch5: coolkey-thread-fix.patch
# PATCH-FEATURE-FEDORA coolkey-cac.patch bnc661643 sbrabec@suse.cz -- Support for CAC cards.
Patch6: coolkey-cac.patch
# PATCH-FIX-FEDORA coolkey-cac-1.patch bnc661643 sbrabec@suse.cz -- Fixes of CAC support patch.
Patch7: coolkey-cac-1.patch
# PATCH-FIX-FEDORA coolkey-pcsc-lite-fix.patch bnc661643 sbrabec@suse.cz -- Port to the latest pcsc-lite.
Patch8: coolkey-pcsc-lite-fix.patch
Patch9: coolkey-fix-token-removal-failure.patch
Patch10: coolkey-piv-ecc-el7.patch
Patch20: coolkey-1.1.0-noapplet.patch
Patch21: coolkey-1.1.0-fix-spurious-event.patch
Patch22: coolkey-1.1.0-p15.patch
Patch23: coolkey-1.1.0-p15-coverity.patch
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
BuildRequires: gcc-c++
BuildRequires: libtool
BuildRequires: mozilla-nss-devel
BuildRequires: mozilla-nss-sysinit
BuildRequires: mozilla-nss-tools
BuildRequires: pcsc-lite-devel
BuildRequires: pkgconfig
BuildRequires: zlib-devel
#Requires: pcsc-lite
# Requires: ifd-egate
Requires: pcsc-ccid
# 390 does not have libusb or smartCards
ExcludeArch: s390 s390x
%description
Linux Driver support for the CoolKey and CAC products. CoolKeys are
part of a complete PKI solution that provides smart card login, single
sign-on, secure messaging, and secure email access. In the complete
solution, users are issued CoolKeys by their employer, ISP, bank, or
other parties. When the user plugs the keys in for the first time, the
keys are automatically provisioned with certificates, keys, and a PIN,
unique for that user by the Red Hat Certificate System. Once the
CoolKey is provisioned, the user can take the key to any system and use
it to login (authenticate), send and receive signed and encrypted
email, or participate in secure messaging or IRC communication.
CoolKeys are based on JavaCard 1.2.
%package devel
Summary: CoolKey and CAC PKCS #11 PKI Module for Smart Cards
Group: Development/Libraries/C and C++
Requires: %{name} = %{version}
%description devel
Linux Driver support for the CoolKey and CAC products.
CoolKeys are part of complete PKI solution that provides smart card
login, single sign-on, secure messaging, and secure email access. In
the complete solution, users are issued CoolKeys by their employer,
ISP, bank, or other agency. When the user plugs in the keys for the
first time, the keys are automatically provisioned with certificates,
keys, and a PIN unique to that user by the Red Hat Certificate System.
Once the CoolKey is provisioned, the user can take the key to any
system and use it to login (authenticate), send and receive signed and
encrypted email, or participate in secure messaging or IRC
communication.
CoolKeys are based on JavaCard 1.2.
%prep
%setup -q
%patch1
%patch2
%patch3
%patch4
%patch5
%patch6
%patch7
%patch8
%patch9 -p1
%patch10
%patch20
%patch21
%patch22
%patch23
%patch24
%patch25
%patch26
%patch27
%build
autoreconf -f -i
export CFLAGS="%{optflags} -fno-strict-aliasing"
export CXXFLAGS="%{optflags} -fno-strict-aliasing"
%configure\
--with-debug\
--disable-dependency-tracking\
--enable-pk11install
%make_build
%install
%make_install
ln -s pkcs11/libcoolkeypk11.so %{buildroot}/%{_libdir}
%triggerin -- mozilla-nss-sysinit mozilla-nss-tools
if [ -x %{_bindir}/pk11install -a -x %{_bindir}/modutil -a -f %{_sysconfdir}/pki/nssdb/pkcs11.txt ]; then
isThere=`modutil -rawlist -dbdir dbm:%{nssdb} | grep %{coolkey_module} || echo NO`
if [ "$isThere" = "NO" ]; then
pk11install -l -p %{nssdb} 'name=%{coolkey_module} library=libcoolkeypk11.so' ||:
fi
isThere=`modutil -rawlist -dbdir sql:%{nssdb} | grep %{coolkey_module} || echo NO`
if [ "$isThere" = "NO" ]; then
pk11install -s -p %{nssdb} 'name=%{coolkey_module} library=libcoolkeypk11.so' ||:
fi
fi
%post
/sbin/ldconfig
if [ -x %{_bindir}/pk11install -a -x %{_bindir}/modutil -a -f %{_sysconfdir}/pki/nssdb/pkcs11.txt ]; then
isThere=`modutil -rawlist -dbdir dbm:%{nssdb} | grep %{coolkey_module} || echo NO`
if [ "$isThere" = "NO" ]; then
pk11install -l -p %{nssdb} 'name=%{coolkey_module} library=libcoolkeypk11.so' ||:
fi
isThere=`modutil -rawlist -dbdir sql:%{nssdb} | grep %{coolkey_module} || echo NO`
if [ "$isThere" = "NO" ]; then
pk11install -s -p %{nssdb} 'name=%{coolkey_module} library=libcoolkeypk11.so' ||:
fi
fi
%postun
/sbin/ldconfig
if [ $1 -eq 0 -a -x %{_bindir}/modutil -a -f %{_sysconfdir}/pki/nssdb/pkcs11.txt ]; then
modutil -delete %{coolkey_module} -dbdir dbm:%{nssdb} -force || :
modutil -delete %{coolkey_module} -dbdir sql:%{nssdb} -force || :
fi
%files
%license LICENSE
%doc ChangeLog README
%{_bindir}/pk11install
%{_libdir}/libcoolkeypk11.so
%{_libdir}/pkcs11/*.so
%{_libdir}/libckyapplet.so.*
# FIXME: Find a common package owning this directory:
%dir %{_libdir}/pkcs11
%files devel
%{_libdir}/libckyapplet.so
%{_libdir}/pkgconfig/*.pc
%{_includedir}/*.h
%changelog