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);