PSARC/2016/219 Coolkey PKCS#11 provider for smartcard devices
22017764 Add Coolkey v1.1.0 to Userland consolidation
Upstream fixes already included in the latest community updates to coolkey v1.1.0
Adds header definitions for newer CAC and PIV card support.
--- ORIGINAL/./src/coolkey/slot.h 2016-06-24 16:07:28.549068021 -0400
+++ ././src/coolkey/slot.h 2016-06-27 14:01:31.527689321 -0400
@@ -79,9 +79,11 @@
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 @@
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);
@@ -211,24 +214,27 @@
State state;
CKYByte keyNum;
CKYBuffer result;
+ PKCS11Object::KeyType keyType;
- CryptOpState() : state(NOT_INITIALIZED), keyNum(0)
+ CryptOpState() : state(NOT_INITIALIZED), keyNum(0), keyType(PKCS11Object::unknown)
{ CKYBuffer_InitEmpty(&result); }
CryptOpState(const CryptOpState &cpy) :
- state(cpy.state), keyNum(cpy.keyNum) {
+ state(cpy.state), keyNum(cpy.keyNum), keyType(cpy.keyType) {
CKYBuffer_InitFromCopy(&result, &cpy.result);
}
CryptOpState &operator=(const CryptOpState &cpy) {
state = cpy.state,
keyNum = cpy.keyNum;
+ keyType = cpy.keyType;
CKYBuffer_Replace(&result, 0, CKYBuffer_Data(&cpy.result),
CKYBuffer_Size(&cpy.result));
return *this;
}
~CryptOpState() { CKYBuffer_FreeData(&result); }
- void initialize(CKYByte keyNum) {
+ void initialize(CKYByte keyNum, PKCS11Object::KeyType theKeyType) {
state = IN_PROCESS;
this->keyNum = keyNum;
+ this->keyType = theKeyType;
CKYBuffer_Resize(&result, 0);
}
};
@@ -258,6 +264,7 @@
CryptOpState signatureState;
CryptOpState decryptionState;
+ CryptOpState keyAgreementState;
};
typedef list<Session> SessionList;
@@ -267,13 +274,11 @@
class CryptParams {
private:
unsigned int keySize; // in bits
- protected:
- unsigned int getKeySize() const { return keySize; }
public:
- // !!!XXX hack. The right way to get the key size is to get all the
- // key information from the token with MSCListKeys, the same way
- // we get all the object information with MSCListObjects.
- enum { FIXED_KEY_SIZE = 1024 };
+ // set the actual key size obtained from the card
+ void setKeySize(unsigned int newKeySize) { keySize = newKeySize; }
+ unsigned int getKeySize() const { return keySize; }
+ enum { DEFAULT_KEY_SIZE = 1024, ECC_DEFAULT_KEY_SIZE=256 };
CryptParams(unsigned int keySize_) : keySize(keySize_) { }
@@ -295,6 +300,13 @@
const CKYBuffer *paddedOutput) const = 0;
};
+#define MAX_CERT_SLOTS 10
+typedef enum {
+ ALG_NONE= 0x0,
+ ALG_ECC = 0x1,
+ ALG_RSA = 0x2
+} SlotAlgs;
+
class Slot {
public:
@@ -304,12 +316,15 @@
ATR_MATCH = 0x04,
APPLET_SELECTABLE = 0x08,
APPLET_PERSONALIZED = 0x10,
- CAC_CARD = 0x20
+ CAC_CARD = 0x20,
+ PIV_CARD = 0x40
};
enum {
NONCE_SIZE = 8
};
+ static const SlotState GOV_CARD = (SlotState)(CAC_CARD|PIV_CARD);
+
private:
Log *log;
char *readerName;
@@ -329,6 +344,8 @@
CKYBuffer nonce;
CKYBuffer cardATR;
CKYBuffer mCUID;
+ CKYBuffer cardAID[MAX_CERT_SLOTS];
+ unsigned short cardEF[MAX_CERT_SLOTS];
bool isVersion1Key;
bool needLogin;
long publicFree;
@@ -336,7 +353,12 @@
long privateFree;
bool fullTokenName;
bool mCoolkey;
-
+ bool mOldCAC;
+ bool mCACLocalLogin;
+ int pivContainer;
+ int pivKey;
+ int maxCacCerts;
+ SlotAlgs algs;
//enum { RW_SESSION_HANDLE = 1, RO_SESSION_HANDLE = 2 };
#ifdef USE_SHMEM
@@ -383,6 +405,7 @@
const CKYBuffer *getATR();
bool isLoggedIn();
bool needLoggedIn();
+ bool getPIVLoginType();
void testNonce();
void addKeyObject(list<PKCS11Object>& objectList,
@@ -392,6 +415,7 @@
const CKYBuffer *derCert, CK_OBJECT_HANDLE handle);
void addObject(list<PKCS11Object>& objectList,
const ListObjectInfo& info, CK_OBJECT_HANDLE handle);
+ PKCS11Object *createSecretKeyObject(CK_OBJECT_HANDLE handle, CKYBuffer *secretKeyBuffer,CK_ATTRIBUTE_PTR pTemplate, CK_ULONG ulAttributeCount);
void ensureValidSession(SessionHandleSuffix suffix);
@@ -399,8 +423,12 @@
list<ListObjectInfo> fetchCombinedObjects(const CKYBuffer *header);
list<ListObjectInfo> fetchSeparateObjects();
+ CKYStatus getCACAid();
+ CKYStatus readCACCertificateFirst(CKYBuffer *cert, CKYSize *nextSize);
+ CKYStatus readCACCertificateAppend(CKYBuffer *cert, CKYSize nextSize);
+
void selectApplet();
- void selectCACApplet(CKYByte instance);
+ void selectCACApplet(CKYByte instance,bool do_disconnect);
void unloadObjects();
void loadCACObjects();
void loadCACCert(CKYByte instance);
@@ -422,14 +450,27 @@
void cryptRSA(SessionHandleSuffix suffix, CK_BYTE_PTR pInput,
CK_ULONG ulInputLen, CK_BYTE_PTR pOutput,
- CK_ULONG_PTR pulOutputLen, const CryptParams& params);
+ CK_ULONG_PTR pulOutputLen, CryptParams& params);
- void performRSAOp(CKYBuffer *out, const CKYBuffer *input, CKYByte keyNum,
- CKYByte direction);
+ void performRSAOp(CKYBuffer *out, const CKYBuffer *input, unsigned int keySize,
+ CKYByte keyNum, CKYByte direction);
+
+ void signECC(SessionHandleSuffix suffix, CK_BYTE_PTR pInput,
+ CK_ULONG ulInputLen, CK_BYTE_PTR pOutput,
+ CK_ULONG_PTR pulOutputLen, CryptParams& params);
+
+ void performECCSignature(CKYBuffer *out, const CKYBuffer *input,
+ unsigned int keySize, CKYByte keyNum);
+ void performECCKeyAgreement(CK_MECHANISM_TYPE deriveMech,
+ CKYBuffer *publicDataBuffer,
+ CKYBuffer *secretKeyBuffer, CKYByte keyNum, unsigned int keySize);
void processComputeCrypt(CKYBuffer *result, const CKYAPDU *apdu);
CKYByte objectHandleToKeyNum(CK_OBJECT_HANDLE hKey);
+ unsigned int calcECCKeySize(CKYByte keyNum);
+ void initCACShMem(void);
+ void verifyCACShMem(void);
Slot(const Slot &cpy)
#ifdef USE_SHMEM
: shmem(readerName)
@@ -460,6 +501,11 @@
return (char )((objectID >> 16) & 0xff) - '0';
}
+ // actually get the size of a key in bits from the card
+ unsigned int getRSAKeySize(CKYByte keyNum);
+ unsigned int getECCKeySize(CKYByte keyNum);
+
+ PKCS11Object::KeyType getKeyTypeFromHandle(CK_OBJECT_HANDLE hKey);
SessionHandleSuffix openSession(Session::Type type);
void closeSession(SessionHandleSuffix handleSuffix);
@@ -501,6 +547,16 @@
CK_ULONG len);
void generateRandom(SessionHandleSuffix suffix, CK_BYTE_PTR data,
CK_ULONG len);
+
+ void derive(SessionHandleSuffix suffix, CK_MECHANISM_PTR pMechanism,
+ CK_OBJECT_HANDLE hKey, CK_ATTRIBUTE_PTR pTemplate,
+ CK_ULONG ulAttributeCount, CK_OBJECT_HANDLE_PTR phKey);
+
+ void 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);
+
+ SlotAlgs getAlgs() { return algs; }
};
class SlotList {
@@ -527,6 +583,8 @@
* has called 'C_GetSlotList' with a NULL parameter */
void updateReaderList();
+ /* see if a reader name exists in a caller provided reader name list. */
+ bool readerNameExistsInList(const char *readerName,CKYReaderNameList *readerNameList );
bool readerExists(const char *readerName, unsigned int *hint = 0);
public:
SlotList(Log *log);
@@ -592,6 +650,10 @@
void seedRandom(CK_SESSION_HANDLE hSession, CK_BYTE_PTR pData,
CK_ULONG ulDataLen);
+ void derive(CK_SESSION_HANDLE hSession, CK_MECHANISM_PTR pMechanism,
+ CK_OBJECT_HANDLE hKey, CK_ATTRIBUTE_PTR pTemplate,
+ CK_ULONG ulAttributeCount, CK_OBJECT_HANDLE_PTR phKey);
+
};
#endif