@@ -3,10 +3,13 @@ #endif #ifdef HAVE_PCSCLITE_H # include #endif +#ifdef HAVE_WINSCARD_H +# include +#endif #ifdef HAVE_STDINT_H # include #endif #ifdef HAVE_INTTYPES_H # include @@ -129,16 +132,20 @@ CK_MECHANISM_TYPE decrypt_mechanism; CK_VOID_PTR decrypt_mech_parm; CK_ULONG decrypt_mech_parmlen; }; +/* CACKEY Global Handles */ static void *cackey_biglock = NULL; -static struct cackey_session cackey_sessions[8]; +static struct cackey_session cackey_sessions[128]; static int cackey_initialized = 0; static int cackey_biglock_init = 0; CK_C_INITIALIZE_ARGS cackey_args; +/* PCSC Global Handles */ +static LPSCARDCONTEXT cackey_pcsc_handle = NULL; + static unsigned long cackey_getversion(void) { static unsigned long retval = 255; unsigned long major = 0; unsigned long minor = 0; char *major_str = NULL; @@ -169,10 +176,60 @@ CACKEY_DEBUG_PRINTF("Returning 0x%lx", retval); return(retval); } + +/* APDU Related Functions */ +static int cackey_send_apdu(unsigned char class, unsigned char instruction, unsigned char p1, unsigned char p2, unsigned char lc, unsigned char *data, unsigned char *resp, unsigned char resplen) { + LONG scard_est_context_ret; +#ifdef HAVE_SCARDISVALIDCONTEXT + LONG scard_isvalid_ret; +#endif + + CACKEY_DEBUG_PRINTF("Called."); + + if (cackey_pcsc_handle == NULL) { + cackey_pcsc_handle = malloc(sizeof(*cackey_pcsc_handle)); + if (cackey_pcsc_handle == NULL) { + CACKEY_DEBUG_PRINTF("Call to malloc() failed, returning in failure"); + + return(-1); + } + + scard_est_context_ret = SCardEstablishContext(SCARD_SCOPE_SYSTEM, NULL, NULL, cackey_pcsc_handle); + if (scard_est_context_ret != SCARD_S_SUCCESS) { + CACKEY_DEBUG_PRINTF("Call to SCardEstablishContext failed (returned %li), returning in failure", (long) scard_est_context_ret); + + free(cackey_pcsc_handle); + + return(-1); + } + } + +#ifdef HAVE_SCARDISVALIDCONTEXT + scard_isvalid_ret = SCardIsValidContext(*cackey_pcsc_handle); + if (scard_isvalid_ret != SCARD_S_SUCCESS) { + CACKEY_DEBUG_PRINTF("Handle has become invalid, trying to re-establish..."); + + scard_est_context_ret = SCardEstablishContext(SCARD_SCOPE_SYSTEM, NULL, NULL, cackey_pcsc_handle); + if (scard_est_context_ret != SCARD_S_SUCCESS) { + CACKEY_DEBUG_PRINTF("Call to SCardEstablishContext failed (returned %li), returning in failure", (long) scard_est_context_ret); + + free(cackey_pcsc_handle); + + return(-1); + } + + CACKEY_DEBUG_PRINTF("Handle has been re-established"); + } +#endif + + /* Connect to a reader, if needed */ + + /* Transmit */ +} /* Returns 0 on success */ static int cackey_mutex_create(void **mutex) { pthread_mutex_t *pthread_mutex; int pthread_retval; @@ -292,12 +349,11 @@ CK_OBJECT_CLASS ck_object_class; CK_CERTIFICATE_TYPE ck_certificate_type; CK_KEY_TYPE ck_key_type; CK_UTF8CHAR ucTmpBuf[1024]; unsigned char certificate[16384]; - ssize_t getcert_ret, certificate_len = -1, x509_read_ret; - int fd; + ssize_t certificate_len = -1, x509_read_ret; int pValue_free; CACKEY_DEBUG_PRINTF("Called (objectClass = %lu, identity_num = %lu).", (unsigned long) objectclass, identity_num); if (objectclass != CKO_CERTIFICATE && objectclass != CKO_PUBLIC_KEY && objectclass != CKO_PRIVATE_KEY) { @@ -697,11 +753,11 @@ return(CKR_OK); } CK_DEFINE_FUNCTION(CK_RV, C_GetInfo)(CK_INFO_PTR pInfo) { static CK_UTF8CHAR manufacturerID[] = "U.S. Government"; - static CK_UTF8CHAR libraryDescription[] = "SSH Agent PKCS#11"; + static CK_UTF8CHAR libraryDescription[] = "CACKey"; CACKEY_DEBUG_PRINTF("Called."); if (pInfo == NULL) { CACKEY_DEBUG_PRINTF("Error. pInfo is NULL."); @@ -735,11 +791,10 @@ } /* We only support 1 slot. If the slot exists, the token exists. */ CK_DEFINE_FUNCTION(CK_RV, C_GetSlotList)(CK_BBOOL tokenPresent, CK_SLOT_ID_PTR pSlotList, CK_ULONG_PTR pulCount) { CK_ULONG count, slot_present = 0, currslot; - int fd; CACKEY_DEBUG_PRINTF("Called."); if (pulCount == NULL) { CACKEY_DEBUG_PRINTF("Error. pulCount is NULL."); @@ -783,11 +838,11 @@ tokenPresent = tokenPresent; /* Supress unused variable warning */ } CK_DEFINE_FUNCTION(CK_RV, C_GetSlotInfo)(CK_SLOT_ID slotID, CK_SLOT_INFO_PTR pInfo) { static CK_UTF8CHAR manufacturerID[] = "U.S. Government"; - static CK_UTF8CHAR slotDescription[] = "SSH Agent Slot"; + static CK_UTF8CHAR slotDescription[] = "CACKey Slot"; CACKEY_DEBUG_PRINTF("Called."); if (pInfo == NULL) { CACKEY_DEBUG_PRINTF("Error. pInfo is NULL."); @@ -828,12 +883,11 @@ } CK_DEFINE_FUNCTION(CK_RV, C_GetTokenInfo)(CK_SLOT_ID slotID, CK_TOKEN_INFO_PTR pInfo) { static CK_UTF8CHAR manufacturerID[] = "U.S. Government"; static CK_UTF8CHAR defaultLabel[] = "Unknown Token"; - static CK_UTF8CHAR model[] = "SSH Agent Token"; - int fd, bytestocopy; + static CK_UTF8CHAR model[] = "CAC Token"; CACKEY_DEBUG_PRINTF("Called."); if (pInfo == NULL) { CACKEY_DEBUG_PRINTF("Error. pInfo is NULL."); @@ -854,11 +908,11 @@ return(CKR_CRYPTOKI_NOT_INITIALIZED); } /* XXX: Verify connection is valid */ if (0) { - CACKEY_DEBUG_PRINTF("Error. Tried to connect to slot, but failed. fd = %i", fd); + CACKEY_DEBUG_PRINTF("Error. Tried to connect to slot, but failed."); return(CKR_SLOT_ID_INVALID); } /* XXX: Get list of identities */ @@ -1057,16 +1111,15 @@ return(CKR_FUNCTION_NOT_SUPPORTED); } CK_DEFINE_FUNCTION(CK_RV, C_OpenSession)(CK_SLOT_ID slotID, CK_FLAGS flags, CK_VOID_PTR pApplication, CK_NOTIFY notify, CK_SESSION_HANDLE_PTR phSession) { struct cackey_identity *identities; - unsigned long idx, num_ids, id_idx, curr_id_type, curr_ssh_id_idx; + unsigned long idx, num_ids, id_idx, curr_id_type; CK_BYTE sigbuf[1024]; ssize_t sigbuflen; int mutex_retval; int found_session = 0; - int fd; CACKEY_DEBUG_PRINTF("Called."); if (slotID != 0) { /* We only support one slot -- slot 0 */ @@ -2126,11 +2179,10 @@ CK_DEFINE_FUNCTION(CK_RV, C_DecryptUpdate)(CK_SESSION_HANDLE hSession, CK_BYTE_PTR pEncryptedPart, CK_ULONG ulEncryptedPartLen, CK_BYTE_PTR pPart, CK_ULONG_PTR pulPartLen) { static CK_BYTE buf[16384]; ssize_t buflen; CK_RV retval = CKR_GENERAL_ERROR; int mutex_retval; - int fd; CACKEY_DEBUG_PRINTF("Called."); if (!cackey_initialized) { CACKEY_DEBUG_PRINTF("Error. Not initialized."); @@ -2579,11 +2631,10 @@ static CK_BYTE sigbuf[1024]; ssize_t sigbuflen; CK_RV retval = CKR_GENERAL_ERROR; int terminate_sign = 1; int mutex_retval; - int fd; CACKEY_DEBUG_PRINTF("Called."); if (!cackey_initialized) { CACKEY_DEBUG_PRINTF("Error. Not initialized.");