Accepting request 512692 from security:chipcard

1

OBS-URL: https://build.opensuse.org/request/show/512692
OBS-URL: https://build.opensuse.org/package/show/openSUSE:Factory/coolkey?expand=0&rev=22
This commit is contained in:
Dominique Leuenberger 2017-07-28 07:48:01 +00:00 committed by Git OBS Bridge
commit 867b3951d2
17 changed files with 10645 additions and 77 deletions

View File

@ -1,11 +0,0 @@
--- coolkey-1.1.0/src/install/pk11install.c~ 2007-02-06 14:40:36.000000000 -0500
+++ coolkey-1.1.0/src/install/pk11install.c 2007-09-05 15:01:57.000000000 -0400
@@ -150,6 +150,8 @@ DirList dirList[] = {
{ HomeDir, ".mozilla/*", NULL },
{ HomeDir, ".thunderbird/*", NULL },
{ HomeDir, ".netscape", NULL },
+ { HomeDir, ".evolution", NULL },
+ { HomeDir, ".ooo-2.0/user", NULL },
#endif
#endif
#ifdef MAC

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 {

View File

@ -1,3 +0,0 @@
version https://git-lfs.github.com/spec/v1
oid sha256:214381ab404b69ef59276a33ab5786848b005ceaa8f199f280ccb66c806a9cde
size 313668

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

Binary file not shown.

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;

View File

@ -1,22 +0,0 @@
https://bugzilla.redhat.com/show_bug.cgi?id=356971
coolkey.cpp:37:1: error: "NULL" redefined
In file included from /usr/include/alloca.h:25,
from /usr/include/stdlib.h:612,
from /usr/include/c++/4.3.0/cstdlib:73,
from /usr/include/c++/4.3.0/bits/stl_algo.h:65,
from /usr/include/c++/4.3.0/algorithm:67,
from slot.h:27,
from coolkey.cpp:33:
/usr/lib64/gcc/x86_64-suse-linux/4.3.0/include/stddef.h:400:1: error: this is the location of the previous definition
================================================================================
--- src/coolkey/coolkey.cpp
+++ src/coolkey/coolkey.cpp
@@ -34,8 +34,6 @@
#include "cky_base.h"
#include "params.h"
-#define NULL 0
-
/* static module data -------------------------------- */
static Log *log = NULL;

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

File diff suppressed because it is too large Load Diff

View File

@ -1,3 +1,37 @@
-------------------------------------------------------------------
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

View File

@ -1,7 +1,7 @@
#
# spec file for package coolkey
#
# Copyright (c) 2016 SUSE LINUX GmbH, Nuernberg, Germany.
# Copyright (c) 2017 SUSE LINUX GmbH, Nuernberg, Germany.
#
# All modifications and additions to the file contributed by third parties
# remain the property of their copyright owners, unless otherwise agreed
@ -16,6 +16,8 @@
#
%define coolkey_module "CoolKey PKCS #11 Module"
%define nssdb %{_sysconfdir}/pki/nssdb
Name: coolkey
Version: 1.1.0
Release: 0
@ -23,10 +25,12 @@ Summary: CoolKey and CAC PKCS #11 PKI Module for Smart Cards
License: LGPL-2.1
Group: Productivity/Security
Url: http://directory.fedoraproject.org/wiki/CoolKey
Source: %{name}-%{version}.tar.bz2
Source1: %{name}-rpmlintrc
Source: %{name}-%{version}.tar.gz
Source1: %{name}.rpmlintrc
Source2: baselibs.conf
# Patches imported from Fedora:
# 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.
@ -41,19 +45,23 @@ Patch6: coolkey-cac.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
# SUSE specific patches:
# PATCH-FEATURE-SLES coolkey-1.1.0-evoandooo.patch jberkman@novell.com -- Teach pk11install about evolution and openoffice.
Patch53: coolkey-1.1.0-evoandooo.patch
# PATCH-FIX-SECURITY coolkey-cache-dir-move.patch sbrabec@suse.cz bnc304180 CVE-2007-4129 -- Fix file and directory permission flaw.
Patch54: coolkey-cache-dir-move.patch
# PATCH-FIX-UPSTREAM coolkey-null.patch redhat356971 sbrabec@suse.cz -- Fix invalid NULL declaration.
Patch55: coolkey-null.patch
BuildRoot: %{_tmppath}/%{name}-%{version}-build
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: pkg-config
BuildRequires: pkgconfig
BuildRequires: zlib-devel
#Requires: pcsc-lite
# Requires: ifd-egate
@ -71,14 +79,8 @@ 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. Using a
CoolKey should be as easy as starting a car. To accomplish that vision,
we are focusing on building complete support for CoolKey on exactly one
token. As the system is built out, we can add token support. CoolKeys
are based on JavaCard 1.2. We are testing with Axalto Egate Cyberflex
cards, which are available in both smart card and USB Fob form factors.
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
@ -97,18 +99,13 @@ 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. Using a CoolKey should be as easy as starting a car.
To accomplish that vision we are focusing on building complete support
for CoolKey on exactly one token. As the system is built out, we can
add token support. CoolKeys are based on JavaCard 1.2. We are testing
with Axalto Egate Cyberflex cards, which are available in both smart
card and USB Fob form factors.
communication.
CoolKeys are based on JavaCard 1.2.
%prep
%setup -q
%patch1
%patch2
%patch3
%patch4
@ -116,29 +113,64 @@ card and USB Fob form factors.
%patch6
%patch7
%patch8
%patch53 -p1
%patch54
%patch55
%patch9 -p1
%patch10
%patch20
%patch21
%patch22
%patch23
%patch24
%patch25
%patch26
%patch27
%build
autoreconf -f -i
export CFLAGS="$RPM_OPT_FLAGS -fno-strict-aliasing"
export CXXFLAGS="$RPM_OPT_FLAGS -fno-strict-aliasing"
export CFLAGS="%{optflags} -fno-strict-aliasing"
export CXXFLAGS="%{optflags} -fno-strict-aliasing"
%configure\
--disable-dependency-tracking \
--with-debug\
--disable-dependency-tracking\
--enable-pk11install
make %{?_smp_mflags}
%install
%makeinstall
ln -s pkcs11/libcoolkeypk11.so $RPM_BUILD_ROOT/%{_libdir}
%make_install
ln -s pkcs11/libcoolkeypk11.so %{buildroot}/%{_libdir}
%post -p /sbin/ldconfig
%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
%postun -p /sbin/ldconfig
%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
%defattr(-,root,root)
%doc ChangeLog LICENSE README
%{_bindir}/pk11install
%{_libdir}/libcoolkeypk11.so
@ -148,7 +180,6 @@ ln -s pkcs11/libcoolkeypk11.so $RPM_BUILD_ROOT/%{_libdir}
%dir %{_libdir}/pkcs11
%files devel
%defattr(-,root,root)
%{_libdir}/libckyapplet.so
%{_libdir}/pkgconfig/*.pc
%{_includedir}/*.h