Index: src/coolkey/slot.h =================================================================== RCS file: /cvs/dirsec/coolkey/src/coolkey/slot.h,v retrieving revision 1.3 retrieving revision 1.4 diff -u -b -B -r1.3 -r1.4 --- src/coolkey/slot.h 19 Feb 2009 02:04:13 -0000 1.3 +++ src/coolkey/slot.h 8 Sep 2010 20:14:41 -0000 1.4 @@ -294,6 +294,7 @@ const CKYBuffer *paddedOutput) const = 0; }; +#define MAX_CERT_SLOTS 3 class Slot { public: @@ -328,6 +329,8 @@ CKYBuffer nonce; CKYBuffer cardATR; CKYBuffer mCUID; + CKYBuffer cardAID[MAX_CERT_SLOTS]; + unsigned short cardEF[MAX_CERT_SLOTS]; bool isVersion1Key; bool needLogin; long publicFree; @@ -335,6 +338,7 @@ long privateFree; bool fullTokenName; bool mCoolkey; + bool mOldCAC; //enum { RW_SESSION_HANDLE = 1, RO_SESSION_HANDLE = 2 }; @@ -398,6 +402,11 @@ list fetchCombinedObjects(const CKYBuffer *header); list fetchSeparateObjects(); + CKYStatus getCACAid(); + CKYStatus readCACCertificateFirst(CKYBuffer *cert, CKYSize *nextSize, + bool throwException); + CKYStatus readCACCertificateAppend(CKYBuffer *cert, CKYSize nextSize); + void selectApplet(); void selectCACApplet(CKYByte instance); void unloadObjects(); Index: src/coolkey/object.cpp =================================================================== RCS file: /cvs/dirsec/coolkey/src/coolkey/object.cpp,v retrieving revision 1.4 retrieving revision 1.5 diff -u -b -B -r1.4 -r1.5 --- src/coolkey/object.cpp 14 Feb 2008 23:48:19 -0000 1.3 +++ src/coolkey/object.cpp 8 Sep 2010 20:14:40 -0000 1.5 @@ -505,6 +505,10 @@ unsigned char tag; unsigned int used_length= 0; + if(!buf) { + return NULL; + } + tag = buf[used_length++]; /* blow out when we come to the end */ Index: src/libckyapplet/cky_base.c =================================================================== RCS file: /cvs/dirsec/coolkey/src/libckyapplet/cky_base.c,v retrieving revision 1.1 retrieving revision 1.2 diff -u -b -B -r1.1 -r1.2 --- src/libckyapplet/cky_base.c 9 Jun 2006 18:44:17 -0000 1.1 +++ src/libckyapplet/cky_base.c 8 Sep 2010 20:14:41 -0000 1.2 @@ -220,6 +220,22 @@ return CKYSUCCESS; } +/* append a short in network order */ +CKYStatus +CKYBuffer_AppendShortLE(CKYBuffer *buf, unsigned short val) +{ + CKYStatus ret; + + ret = CKYBuffer_Reserve(buf, buf->len + 2); + if (ret != CKYSUCCESS) { + return ret; + } + buf->data[buf->len+1] = (CKYByte) ((val >> 8) & 0xff); + buf->data[buf->len+0] = (CKYByte) ((val >> 0) & 0xff); + buf->len += 2; + return CKYSUCCESS; +} + /* append a long in applet order */ CKYStatus CKYBuffer_AppendLong(CKYBuffer *buf, unsigned long val) @@ -238,6 +254,24 @@ return CKYSUCCESS; } +/* append a long in applet order */ +CKYStatus +CKYBuffer_AppendLongLE(CKYBuffer *buf, unsigned long val) +{ + CKYStatus ret; + + ret = CKYBuffer_Reserve(buf, buf->len + 4); + if (ret != CKYSUCCESS) { + return ret; + } + buf->data[buf->len+3] = (CKYByte) ((val >> 24) & 0xff); + buf->data[buf->len+2] = (CKYByte) ((val >> 16) & 0xff); + buf->data[buf->len+1] = (CKYByte) ((val >> 8) & 0xff); + buf->data[buf->len+0] = (CKYByte) ((val >> 0) & 0xff); + buf->len += 4; + return CKYSUCCESS; +} + CKYStatus CKYBuffer_Replace(CKYBuffer *buf, CKYOffset offset, const CKYByte *data, CKYSize len) { @@ -351,6 +385,22 @@ } CKYStatus +CKYBuffer_SetShortLE(CKYBuffer *buf, CKYOffset offset, unsigned short val) +{ + CKYStatus ret; + + if (buf->len < offset+2) { + ret = CKYBuffer_Resize(buf,offset+2); + if (ret != CKYSUCCESS) { + return ret; + } + } + buf->data[offset+1] = (CKYByte) ((val >> 8) & 0xff); + buf->data[offset+0] = (CKYByte) ((val >> 0) & 0xff); + return CKYSUCCESS; +} + +CKYStatus CKYBuffer_SetLong(CKYBuffer *buf, CKYOffset offset, unsigned long val) { CKYStatus ret; @@ -368,6 +418,24 @@ return CKYSUCCESS; } +CKYStatus +CKYBuffer_SetLongLE(CKYBuffer *buf, CKYOffset offset, unsigned long val) +{ + CKYStatus ret; + + if (buf->len < offset+4) { + ret = CKYBuffer_Resize(buf,offset+4); + if (ret != CKYSUCCESS) { + return ret; + } + } + buf->data[offset+3] = (CKYByte) ((val >> 24) & 0xff); + buf->data[offset+2] = (CKYByte) ((val >> 16) & 0xff); + buf->data[offset+1] = (CKYByte) ((val >> 8) & 0xff); + buf->data[offset+0] = (CKYByte) ((val >> 0) & 0xff); + return CKYSUCCESS; +} + CKYByte CKYBuffer_GetChar(const CKYBuffer *buf, CKYOffset offset) { @@ -389,6 +457,18 @@ return val; } +unsigned short +CKYBuffer_GetShortLE(const CKYBuffer *buf, CKYOffset offset) +{ + unsigned short val; + if (buf->len < offset+2) { + return 0; + } + val = ((unsigned short)buf->data[offset+1]) << 8; + val |= ((unsigned short)buf->data[offset+0]) << 0; + return val; +} + unsigned long CKYBuffer_GetLong(const CKYBuffer *buf, CKYOffset offset) { @@ -403,6 +483,20 @@ return val; } +unsigned long +CKYBuffer_GetLongLE(const CKYBuffer *buf, CKYOffset offset) +{ + unsigned long val; + if (buf->len < offset+4) { + return 0; + } + val = ((unsigned long)buf->data[offset+3]) << 24; + val |= ((unsigned long)buf->data[offset+2]) << 16; + val |= ((unsigned long)buf->data[offset+1]) << 8; + val |= ((unsigned long)buf->data[offset+0]) << 0; + return val; +} + CKYStatus CKYBuffer_Resize(CKYBuffer *buf, CKYSize newLen) { Index: src/libckyapplet/cky_base.h =================================================================== RCS file: /cvs/dirsec/coolkey/src/libckyapplet/cky_base.h,v retrieving revision 1.1 retrieving revision 1.2 diff -u -b -B -r1.1 -r1.2 --- src/libckyapplet/cky_base.h 9 Jun 2006 18:44:17 -0000 1.1 +++ src/libckyapplet/cky_base.h 8 Sep 2010 20:14:41 -0000 1.2 @@ -170,9 +170,15 @@ /* append a short in applet order */ CKYStatus CKYBuffer_AppendShort(CKYBuffer *buf, unsigned short val); +/* append a short in little endian order */ +CKYStatus CKYBuffer_AppendShortLE(CKYBuffer *buf, unsigned short val); + /* append a long in applet order */ CKYStatus CKYBuffer_AppendLong(CKYBuffer *buf, unsigned long val); +/* append a long in little endian order */ +CKYStatus CKYBuffer_AppendLongLE(CKYBuffer *buf, unsigned long val); + /* append data. the data starts at data and extends len bytes */ CKYStatus CKYBuffer_AppendData(CKYBuffer *buf, const CKYByte *data, CKYSize len); @@ -210,12 +216,18 @@ CKYStatus CKYBuffer_SetShort(CKYBuffer *buf, CKYOffset offset, unsigned short val); CKYStatus CKYBuffer_SetLong(CKYBuffer *buf, CKYOffset offset, unsigned long val); +/* These functions work in little endian order */ +CKYStatus CKYBuffer_SetShortLE(CKYBuffer *buf, CKYOffset offset, unsigned short val); +CKYStatus CKYBuffer_SetLongLE(CKYBuffer *buf, CKYOffset offset, unsigned long val); /* read a character from offset. If offset is beyond the end of the buffer, * then the function returns '0' */ CKYByte CKYBuffer_GetChar(const CKYBuffer *buf, CKYOffset offset); /* These functions work in applet order */ unsigned short CKYBuffer_GetShort(const CKYBuffer *buf, CKYOffset offset); unsigned long CKYBuffer_GetLong(const CKYBuffer *buf, CKYOffset offset); +/* These functions work in little endian order */ +unsigned short CKYBuffer_GetShortLE(const CKYBuffer *buf, CKYOffset offset); +unsigned long CKYBuffer_GetLongLE(const CKYBuffer *buf, CKYOffset offset); /* clear out all the data in a buffer */ void CKYBuffer_Zero(CKYBuffer *buf); Index: src/libckyapplet/cky_card.h =================================================================== RCS file: /cvs/dirsec/coolkey/src/libckyapplet/cky_card.h,v retrieving revision 1.1 retrieving revision 1.2 diff -u -b -B -r1.1 -r1.2 --- src/libckyapplet/cky_card.h 9 Jun 2006 18:44:17 -0000 1.1 +++ src/libckyapplet/cky_card.h 8 Sep 2010 20:56:55 -0000 1.2 @@ -41,23 +41,23 @@ CKYLIST_DECLARE(CKYCardConnection, CKYCardConnection *) CKY_BEGIN_PROTOS -void CKYReader_Init(SCARD_READERSTATE_A *reader); -void CKYReader_FreeData(SCARD_READERSTATE_A *reader); +void CKYReader_Init(SCARD_READERSTATE *reader); +void CKYReader_FreeData(SCARD_READERSTATE *reader); /* - * "Accessors": for SCARD_READERSTATE_A structure as a class. - * These functions take an SCARD_READERSTATE_A which can also be referenced + * "Accessors": for SCARD_READERSTATE structure as a class. + * These functions take an SCARD_READERSTATE which can also be referenced * directly. */ -CKYStatus CKYReader_SetReaderName(SCARD_READERSTATE_A *reader, const char *name); -const char *CKYReader_GetReaderName(const SCARD_READERSTATE_A *reader); -CKYStatus CKYReader_SetKnownState(SCARD_READERSTATE_A *reader, +CKYStatus CKYReader_SetReaderName(SCARD_READERSTATE *reader, const char *name); +const char *CKYReader_GetReaderName(const SCARD_READERSTATE *reader); +CKYStatus CKYReader_SetKnownState(SCARD_READERSTATE *reader, unsigned long state); -unsigned long CKYReader_GetKnownState(const SCARD_READERSTATE_A *reader); -unsigned long CKYReader_GetEventState(const SCARD_READERSTATE_A *reader); -CKYStatus CKYReader_GetATR(const SCARD_READERSTATE_A *reader, CKYBuffer *buf); +unsigned long CKYReader_GetKnownState(const SCARD_READERSTATE *reader); +unsigned long CKYReader_GetEventState(const SCARD_READERSTATE *reader); +CKYStatus CKYReader_GetATR(const SCARD_READERSTATE *reader, CKYBuffer *buf); /* create an array of READERSTATEs from a LIST of Readers */ -SCARD_READERSTATE_A *CKYReader_CreateArray(const CKYReaderNameList readerNames, +SCARD_READERSTATE *CKYReader_CreateArray(const CKYReaderNameList readerNames, unsigned long *readerCount); /* frees the reader, then the full array */ void CKYReader_DestroyArray(SCARD_READERSTATE *reader, unsigned long count); @@ -88,7 +88,7 @@ const CKYBuffer *targetATR); /* return if any of the readers in our array has changed in status */ CKYStatus CKYCardContext_WaitForStatusChange(CKYCardContext *context, - SCARD_READERSTATE_A *readers, + SCARD_READERSTATE *readers, unsigned long readerCount, unsigned long timeout); /* cancel any current operation (such as wait for status change) on this Index: src/libckyapplet/cky_applet.c =================================================================== RCS file: /cvs/dirsec/coolkey/src/libckyapplet/cky_applet.c,v retrieving revision 1.2 retrieving revision 1.3 diff -u -b -B -r1.2 -r1.3 --- src/libckyapplet/cky_applet.c 19 Feb 2009 02:03:08 -0000 1.2 +++ src/libckyapplet/cky_applet.c 8 Sep 2010 20:14:41 -0000 1.3 @@ -41,7 +41,13 @@ CKYStatus CKYAppletFactory_SelectFile(CKYAPDU *apdu, const void *param) { - return CKYAPDUFactory_SelectFile(apdu,(const CKYBuffer *)param); + return CKYAPDUFactory_SelectFile(apdu, 4, 0, (const CKYBuffer *)param); +} + +CKYStatus +CACAppletFactory_SelectFile(CKYAPDU *apdu, const void *param) +{ + return CKYAPDUFactory_SelectFile(apdu, 2, 12, (const CKYBuffer *)param); } CKYStatus @@ -225,10 +231,17 @@ } CKYStatus -CACAppletFactory_SignDecrypt(CKYAPDU *apdu, const void *param) +CACAppletFactory_SignDecryptStep(CKYAPDU *apdu, const void *param) +{ + const CKYBuffer *buf=(CKYBuffer *)param; + return CACAPDUFactory_SignDecrypt(apdu, CAC_P1_STEP, buf); +} + +CKYStatus +CACAppletFactory_SignDecryptFinal(CKYAPDU *apdu, const void *param) { const CKYBuffer *buf=(CKYBuffer *)param; - return CACAPDUFactory_SignDecrypt(apdu, buf); + return CACAPDUFactory_SignDecrypt(apdu, CAC_P1_FINAL, buf); } CKYStatus @@ -246,6 +259,13 @@ } CKYStatus +CACAppletFactory_ReadFile(CKYAPDU *apdu, const void *param) +{ + const CACAppletArgReadFile *rfs = (const CACAppletArgReadFile *)param; + return CACAPDUFactory_ReadFile(apdu, rfs->offset, rfs->type, rfs->count); +} + +CKYStatus CACAppletFactory_GetProperties(CKYAPDU *apdu, const void *param) { return CACAPDUFactory_GetProperties(apdu); @@ -457,7 +477,7 @@ CKYISOStatus *apduRC) { return CKYApplet_HandleAPDU(conn, CKYAppletFactory_SelectFile, AID, NULL, - 0, CKYAppletFill_Null, NULL, apduRC); + CKY_SIZE_UNKNOWN, CKYAppletFill_Null, NULL, apduRC); } static CKYByte coolkeyid[] = {0x62, 0x76, 0x01, 0xff, 0x00, 0x00, 0x00 }; @@ -477,22 +497,23 @@ return ret; } -static CKYByte CACPKIid[] = {0xa0, 0x00, 0x00, 0x00, 0x79, 0x01, 0x00 }; +static CKYByte CACPKIid[] = { 0xa0, 0x00, 0x00, 0x00, 0x79, 0x01 }; /* * Select the CoolKey applet. Must happen after we start a transaction and * before we issue any applet specific command. */ CKYStatus -CACApplet_SelectPKI(CKYCardConnection *conn, CKYByte instance, - CKYISOStatus *apduRC) +CACApplet_SelectPKI(CKYCardConnection *conn, CKYBuffer *cacAID, + CKYByte instance, CKYISOStatus *apduRC) { CKYStatus ret; - CKYBuffer CACPKIAID; - CKYBuffer_InitFromData(&CACPKIAID, CACPKIid, sizeof(CACPKIid)); - CKYBuffer_SetChar(&CACPKIAID, 6, instance); - ret = CKYApplet_HandleAPDU(conn, CKYAppletFactory_SelectFile, &CACPKIAID, + CKYBuffer_AppendData(cacAID, CACPKIid, sizeof(CACPKIid)); + CKYBuffer_AppendChar(cacAID, instance); + ret = CKYApplet_HandleAPDU(conn, CKYAppletFactory_SelectFile, cacAID, NULL, CKY_SIZE_UNKNOWN, CKYAppletFill_Null, NULL, apduRC); - CKYBuffer_FreeData(&CACPKIAID); + if (ret != CKYSUCCESS) { + CKYBuffer_Resize(cacAID, 0); + } return ret; } @@ -515,11 +536,38 @@ CKYBuffer CAC_CM_AID; CKYBuffer_InitFromData(&CAC_CM_AID, cacmgrid, sizeof(cacmgrid)); ret = CKYApplet_HandleAPDU(conn, CKYAppletFactory_SelectFile, &CAC_CM_AID, - NULL, 0, CKYAppletFill_Null, NULL, apduRC); + NULL, CKY_SIZE_UNKNOWN, CKYAppletFill_Null, NULL, apduRC); CKYBuffer_FreeData(&CAC_CM_AID); return ret; } +static CKYByte cacCCCid[] = {0xa0, 0x00, 0x00, 0x01, 0x16, 0xdb, 0x00 }; +CKYStatus +CACApplet_SelectCCC(CKYCardConnection *conn, CKYISOStatus *apduRC) +{ + CKYStatus ret; + CKYBuffer CAC_CM_AID; + CKYBuffer_InitFromData(&CAC_CM_AID, cacCCCid, sizeof(cacCCCid)); + ret = CKYApplet_HandleAPDU(conn, CKYAppletFactory_SelectFile, &CAC_CM_AID, + NULL, CKY_SIZE_UNKNOWN, CKYAppletFill_Null, NULL, apduRC); + CKYBuffer_FreeData(&CAC_CM_AID); + return ret; +} + +CKYStatus +CACApplet_SelectFile(CKYCardConnection *conn, unsigned short ef, + CKYISOStatus *apduRC) +{ + CKYStatus ret; + CKYBuffer efBuf; + CKYBuffer_InitEmpty(&efBuf); + CKYBuffer_AppendShortLE(&efBuf, ef); + ret = CKYApplet_HandleAPDU(conn, CACAppletFactory_SelectFile, &efBuf, + NULL, CKY_SIZE_UNKNOWN, CKYAppletFill_Null, NULL, apduRC); + CKYBuffer_FreeData(&efBuf); + return ret; +} + /* * GetCPLC cluster -- must be called with CM selected */ @@ -673,8 +721,8 @@ ccd.keyNumber = keyNumber; ccd.location = location; ccd.data = data; - return CKYApplet_HandleAPDU(conn, CKYAppletFactory_ComputeCryptProcess, &ccd, - nonce, 0, CKYAppletFill_Null, NULL, apduRC); + return CKYApplet_HandleAPDU(conn, CKYAppletFactory_ComputeCryptProcess, + &ccd, nonce, 0, CKYAppletFill_Null, NULL, apduRC); } /* computeCrypt returns data in the form : @@ -832,11 +880,39 @@ CKYBuffer *result, CKYISOStatus *apduRC) { CKYStatus ret; - - ret = CKYApplet_HandleAPDU(conn, - CACAppletFactory_SignDecrypt, data, NULL, - CKYBuffer_Size(data), CKYAppletFill_ReplaceBuffer, + CKYSize dataSize = CKYBuffer_Size(data); + CKYOffset offset = 0; + CKYBuffer tmp; + + CKYBuffer_InitEmpty(&tmp); + + CKYBuffer_Resize(result, 0); + for(offset = 0; (dataSize-offset) > CKY_MAX_WRITE_CHUNK_SIZE; + offset += CKY_MAX_WRITE_CHUNK_SIZE) { + CKYBuffer_Resize(&tmp,0); + CKYBuffer_AppendBuffer(&tmp, data, offset, CKY_MAX_WRITE_CHUNK_SIZE); + ret = CKYApplet_HandleAPDU(conn, CACAppletFactory_SignDecryptStep, + &tmp, NULL, CKY_SIZE_UNKNOWN, + CKYAppletFill_AppendBuffer, + result, apduRC); + if (ret != CKYSUCCESS) { + goto done; + } + } + CKYBuffer_Resize(&tmp,0); + CKYBuffer_AppendBuffer(&tmp, data, offset, dataSize - offset); + ret = CKYApplet_HandleAPDU(conn, CACAppletFactory_SignDecryptFinal, + &tmp, NULL, CKY_SIZE_UNKNOWN, + CKYAppletFill_AppendBuffer, result, apduRC); + + if ((ret == CKYSUCCESS) && (CKYBuffer_Size(result) != dataSize)) { + /* RSA returns the same data size as input, didn't happen, so + * something is wrong. */ + } + +done: + CKYBuffer_FreeData(&tmp); return ret; } @@ -895,6 +971,63 @@ } return ret; } + +/* + * Read a CAC Tag/Value file + */ +CKYStatus +CACApplet_ReadFile(CKYCardConnection *conn, CKYByte type, CKYBuffer *buffer, + CKYISOStatus *apduRC) +{ + CKYStatus ret; + CKYISOStatus status; + CKYByte maxtransfer; + unsigned short offset = 0; + unsigned short size; + CACAppletArgReadFile rfs; + + CKYBuffer_Resize(buffer,0); + if (apduRC == NULL) { + apduRC = &status; + } + rfs.offset = 0; + rfs.count = 2; + rfs.type = type; + + /* APDU's are expensive, Grab a big chunk of the file first if possible */ + ret = CKYApplet_HandleAPDU(conn, + CACAppletFactory_ReadFile, &rfs, NULL, + rfs.count, CKYAppletFill_AppendBuffer, + buffer, apduRC); + /* file is probably smaller than 100 bytes, get the actual size first */ + if (ret != CKYSUCCESS) { + return ret; + } + size = CKYBuffer_GetShortLE(buffer, 0) + 2 /* include the length itself */; + maxtransfer = CKY_MAX_READ_CHUNK_SIZE; + /* get the rest of the buffer if necessary */ + for (offset = CKYBuffer_Size(buffer); size > offset; + offset = CKYBuffer_Size(buffer)) { + rfs.offset = offset; + rfs.count = MIN(size - offset, maxtransfer); + ret = CKYApplet_HandleAPDU(conn, + CACAppletFactory_ReadFile, &rfs, NULL, + rfs.count, CKYAppletFill_AppendBuffer, + buffer, apduRC); + if (ret != CKYSUCCESS) { + if (*apduRC == CAC_INVALID_PARAMS) { + maxtransfer = maxtransfer/2; + if (maxtransfer == 0) { + return ret; + } + } else { + return ret; + } + } + } + return ret; +} + CKYStatus CACApplet_GetCertificateFirst(CKYCardConnection *conn, CKYBuffer *cert, CKYSize *nextSize, CKYISOStatus *apduRC) Index: src/libckyapplet/cky_applet.h =================================================================== RCS file: /cvs/dirsec/coolkey/src/libckyapplet/cky_applet.h,v retrieving revision 1.2 retrieving revision 1.3 diff -u -b -B -r1.2 -r1.3 --- src/libckyapplet/cky_applet.h 19 Feb 2009 02:03:08 -0000 1.2 +++ src/libckyapplet/cky_applet.h 8 Sep 2010 20:14:41 -0000 1.3 @@ -43,6 +43,7 @@ #define CKYISO_MORE_MASK 0xff00 /* More data mask */ #define CKYISO_MORE 0x6300 /* More data available */ #define CKYISO_DATA_INVALID 0x6984 +#define CKYISO_CONDITION_NOT_SATISFIED 0x6985 /* AKA not logged in */ /* Applet Defined Return codes */ #define CKYISO_NO_MEMORY_LEFT 0x9c01 /* There have been memory * problems on the card */ @@ -71,6 +72,15 @@ #define CKYISO_INTERNAL_ERROR 0x9cff /* Reserved for debugging, * shouldn't happen */ +#define CAC_INVALID_PARAMS 0x6a83 +#define CAC_TAG_FILE 1 +#define CAC_VALUE_FILE 2 + + +#define CAC_TAG_CARDURL 0xf3 +#define CAC_TAG_CERTIFICATE 0x70 +#define CAC_TLV_APP_PKI 0x04 + /* * Pin Constants as used by our applet */ @@ -209,6 +219,12 @@ const CKYBuffer *sig; } CKYAppletArgComputeCrypt; +typedef struct _CACAppletArgReadFile { + CKYByte type; + CKYByte count; + unsigned short offset; +} CACAppletArgReadFile; + /* fills in an APDU from a structure -- form of all the generic factories*/ typedef CKYStatus (*CKYAppletFactory)(CKYAPDU *apdu, const void *param); /* fills in an a structure from a response -- form of all the fill structures*/ @@ -451,9 +467,17 @@ /* Select the CAC card manager. Can happen with either applet selected */ CKYStatus CACApplet_SelectCardManager(CKYCardConnection *conn, CKYISOStatus *apduRC); -/* Can happen with either applet selected */ -CKYStatus CACApplet_SelectPKI(CKYCardConnection *conn, CKYByte instance, +/* Select the CAC CC container. Can happen with either applet selected */ +CKYStatus CACApplet_SelectCCC(CKYCardConnection *conn, CKYISOStatus *apduRC); +/* Select an old CAC applet and fill in the cardAID */ +CKYStatus CACApplet_SelectPKI(CKYCardConnection *conn, CKYBuffer *cardAid, + CKYByte instance, CKYISOStatus *apduRC); +/* read a TLV file */ +CKYStatus CACApplet_ReadFile(CKYCardConnection *conn, CKYByte type, + CKYBuffer *buffer, CKYISOStatus *apduRC); +CKYStatus CACApplet_SelectFile(CKYCardConnection *conn, unsigned short ef, CKYISOStatus *apduRC); + /* must happen with PKI applet selected */ CKYStatus CACApplet_SignDecrypt(CKYCardConnection *conn, const CKYBuffer *data, CKYBuffer *result, CKYISOStatus *apduRC); Index: src/libckyapplet/cky_factory.h =================================================================== RCS file: /cvs/dirsec/coolkey/src/libckyapplet/cky_factory.h,v retrieving revision 1.2 retrieving revision 1.3 diff -u -b -B -r1.2 -r1.3 --- src/libckyapplet/cky_factory.h 19 Feb 2009 02:03:08 -0000 1.2 +++ src/libckyapplet/cky_factory.h 8 Sep 2010 20:14:41 -0000 1.3 @@ -86,7 +86,11 @@ #define CAC_INS_SIGN_DECRYPT 0x42 #define CAC_INS_VERIFY_PIN 0x20 #define CAC_INS_GET_PROPERTIES 0x56 +#define CAC_INS_READ_FILE 0x52 + #define CAC_SIZE_GET_PROPERTIES 48 +#define CAC_P1_STEP 0x80 +#define CAC_P1_FINAL 0x00 /* * Fixed return sized from various commands @@ -169,7 +173,8 @@ CKY_BEGIN_PROTOS /* function based factorys */ -CKYStatus CKYAPDUFactory_SelectFile(CKYAPDU *apdu, const CKYBuffer *AID); +CKYStatus CKYAPDUFactory_SelectFile(CKYAPDU *apdu, CKYByte p1, CKYByte p2, + const CKYBuffer *AID); CKYStatus CKYAPDUFactory_SelectCardManager(CKYAPDU *apdu); CKYStatus CKYAPDUFactory_GetCPLCData(CKYAPDU *apdu); CKYStatus CKYAPDUFactory_ListKeys(CKYAPDU *apdu, CKYByte sequence); @@ -211,9 +216,12 @@ CKYStatus CKYAPDUFactory_GetIssuerInfo(CKYAPDU *apdu); CKYStatus CKYAPDUFactory_GetBuiltinACL(CKYAPDU *apdu); -CKYStatus CACAPDUFactory_SignDecrypt(CKYAPDU *apdu, const CKYBuffer *data); +CKYStatus CACAPDUFactory_SignDecrypt(CKYAPDU *apdu, CKYByte type, + const CKYBuffer *data); CKYStatus CACAPDUFactory_VerifyPIN(CKYAPDU *apdu, const char *pin); CKYStatus CACAPDUFactory_GetCertificate(CKYAPDU *apdu, CKYSize size); +CKYStatus CACAPDUFactory_ReadFile(CKYAPDU *apdu, unsigned short offset, + CKYByte type, CKYByte count); CKYStatus CACAPDUFactory_GetProperties(CKYAPDU *apdu); CKY_END_PROTOS Index: src/libckyapplet/cky_factory.c =================================================================== RCS file: /cvs/dirsec/coolkey/src/libckyapplet/cky_factory.c,v retrieving revision 1.2 retrieving revision 1.3 diff -u -b -B -r1.2 -r1.3 --- src/libckyapplet/cky_factory.c 19 Feb 2009 02:03:08 -0000 1.2 +++ src/libckyapplet/cky_factory.c 8 Sep 2010 20:14:41 -0000 1.3 @@ -25,12 +25,13 @@ * special commands can be issued at any time */ CKYStatus -CKYAPDUFactory_SelectFile(CKYAPDU *apdu, const CKYBuffer *AID) +CKYAPDUFactory_SelectFile(CKYAPDU *apdu, CKYByte p1, CKYByte p2, + const CKYBuffer *AID) { CKYAPDU_SetCLA(apdu, CKY_CLASS_ISO7816); CKYAPDU_SetINS(apdu, CKY_INS_SELECT_FILE); - CKYAPDU_SetP1(apdu, 0x04); - CKYAPDU_SetP2(apdu, 0x00); + CKYAPDU_SetP1(apdu, p1); + CKYAPDU_SetP2(apdu, p2); return CKYAPDU_SetSendDataBuffer(apdu, AID); } @@ -572,11 +574,11 @@ } CKYStatus -CACAPDUFactory_SignDecrypt(CKYAPDU *apdu, const CKYBuffer *data) +CACAPDUFactory_SignDecrypt(CKYAPDU *apdu, CKYByte type, const CKYBuffer *data) { CKYAPDU_SetCLA(apdu, CKY_CLASS_ISO7816); CKYAPDU_SetINS(apdu, CAC_INS_SIGN_DECRYPT); - CKYAPDU_SetP1(apdu, 0x00); + CKYAPDU_SetP1(apdu, type); CKYAPDU_SetP2(apdu, 0x00); return CKYAPDU_SetSendDataBuffer(apdu, data); } @@ -592,6 +594,36 @@ } CKYStatus +CACAPDUFactory_ReadFile(CKYAPDU *apdu, unsigned short offset, + CKYByte type, CKYByte count) +{ + CKYStatus ret; + CKYBuffer buf; + + CKYBuffer_InitEmpty(&buf); + CKYAPDU_SetCLA(apdu, CKY_CLASS_GLOBAL_PLATFORM); + CKYAPDU_SetINS(apdu, CAC_INS_READ_FILE); + CKYAPDU_SetP1(apdu, (offset >> 8) & 0xff); + CKYAPDU_SetP2(apdu, offset & 0xff); + ret = CKYBuffer_Reserve(&buf, 2); + if (ret != CKYSUCCESS) { + goto fail; + } + ret = CKYBuffer_AppendChar(&buf, type); + if (ret != CKYSUCCESS) { + goto fail; + } + ret = CKYBuffer_AppendChar(&buf, count); + if (ret != CKYSUCCESS) { + goto fail; + } + ret = CKYAPDU_SetSendDataBuffer(apdu, &buf); +fail: + CKYBuffer_FreeData(&buf); + return ret; +} + +CKYStatus CACAPDUFactory_GetProperties(CKYAPDU *apdu) { CKYAPDU_SetCLA(apdu, CKY_CLASS_ISO7816); Index: src/libckyapplet/cky_card.c =================================================================== RCS file: /cvs/dirsec/coolkey/src/libckyapplet/cky_card.c,v retrieving revision 1.2 retrieving revision 1.4 diff -u -b -B -r1.2 -r1.4 --- src/libckyapplet/cky_card.c 24 Jan 2009 00:08:01 -0000 1.2 +++ src/libckyapplet/cky_card.c 19 Feb 2010 00:10:17 -0000 1.4 @@ -50,10 +50,10 @@ SCARDCONTEXT hContext); typedef long (WINAPI * SCardBeginTransactionFn) ( - long hCard); + SCARDHANDLE hCard); typedef long (WINAPI * SCardEndTransactionFn) ( - long hCard, + SCARDHANDLE hCard, unsigned long dwDisposition); typedef long (WINAPI * SCardConnectFn) ( @@ -61,15 +61,15 @@ const char *szReader, unsigned long dwShareMode, unsigned long dwPreferredProtocols, - long *phCard, + SCARDHANDLE *phCard, unsigned long *pdwActiveProtocol); typedef long (WINAPI * SCardDisconnectFn) ( - long hCard, + SCARDHANDLE hCard, unsigned long dwDisposition); typedef long (WINAPI * SCardTransmitFn) ( - long hCard, + SCARDHANDLE hCard, LPCSCARD_IO_REQUEST pioSendPci, const unsigned char *pbSendBuffer, unsigned long cbSendLength, @@ -78,7 +78,7 @@ unsigned long *pcbRecvLength); typedef long (WINAPI * SCardReconnectFn) ( - long hCard, + SCARDHANDLE hCard, unsigned long dwShareMode, unsigned long dwPreferredProtocols, unsigned long dwInitialization, @@ -91,7 +91,7 @@ unsigned long *pcchReaders); typedef long (WINAPI * SCardStatusFn) ( - long hCard, + SCARDHANDLE hCard, char *mszReaderNames, unsigned long *pcchReaderLen, unsigned long *pdwState, @@ -100,7 +100,7 @@ unsigned long *pcbAtrLen); typedef long (WINAPI * SCardGetAttribFn) ( - long hCard, + SCARDHANDLE hCard, unsigned long dwAttId, char *pbAttr, unsigned long *pchAttrLen); @@ -493,7 +493,7 @@ * condition. Detect this case and continue. We'll establish the connection * later.. */ - if (ctx->lastError == SCARD_F_INTERNAL_ERROR) { + if (ctx->lastError == SCARD_F_INTERNAL_ERROR || ctx->lastError == SCARD_E_NO_SERVICE) { ctx->context = 0; /* make sure it's not established */ return ctx; } @@ -545,7 +545,7 @@ if (ret != CKYSUCCESS) { #ifdef MAC - if (ctx->lastError == SCARD_F_INTERNAL_ERROR) { + if (ctx->lastError == SCARD_F_INTERNAL_ERROR || ctx->lastError == SCARD_E_NO_SERVICE) { /* Still can't establish, just treat it as 'zero' readers */ return CKYSUCCESS; }