/******************************************************************************* * Copyright (c) 1997-1998 Gemplus Development * * Name : GIOCTL09.C (Gemplus IOCTL Smart card Reader module 09) * * Description : This module holds: * - the IOCTL functions for a smart card reader driver * in compliance with PC/SC. * * Release : 1.00.015 * * dd/mm/yy * Last Modif : 11/02/98: V1.00.015 (GPZ) * 09/02/98: V1.00.014 (GPZ) * - GDDK_09Transmit: verify the limits. * 24/01/98: V1.00.010 (GPZ) * - GDDK_09Transmit: verify the case T=0 IsoOut with also the * initial buffer length because the SMCLIB add the P3=00 * for the T=0 case 1 (IsoIn command) and this can be * interpreted like an IsoOut command. * 19/01/98: V1.00.009 (TFB) * - GDDK_09Transmit: modify case where Lexp=0 to max. * 19/12/97: V1.00.003 (TFB) * - GDDK_09Transmit: check if buffer is too small to hold * result-data. * 04/11/97: V1.00.002 (GPZ) * - GDDK_09Transmit: the status is always updated. * 03/07/97: V1.00.001 (GPZ) * - Start of development. * ******************************************************************************** * * Warning : * * Remark : * *******************************************************************************/ /*------------------------------------------------------------------------------ Include section: ------------------------------------------------------------------------------*/ /*------------------------------------------------------------------------------ - ntddk.h: DDK Windows NT general definitons. - ntddser.h: DDK Windows NT serial management definitons. ------------------------------------------------------------------------------*/ #include #include /*------------------------------------------------------------------------------ - smclib.h: smart card library definitions. ------------------------------------------------------------------------------*/ #define SMARTCARD_POOL_TAG 'cGCS' #include /*------------------------------------------------------------------------------ - gemcore.h: Gemplus standards definitions for the Gemcore smart card reader. - gioctl09.h: public interface definition for this module. - gntser.h: public interface definition for serial management. ------------------------------------------------------------------------------*/ #include "gemcore.h" #include "gioctl09.h" #include "gntser.h" #include "gntscr09.h" #define min(a,b) (((a) < (b)) ? (a) : (b)) /*------------------------------------------------------------------------------ Static variables declaration section: - dataRatesSupported: holds all the supported data rates. ------------------------------------------------------------------------------*/ #if SMCLIB_VERSION >= 0x0130 static ULONG dataRatesSupported[] = { 9909, 13212, 14400, 15855, 19200, 19819, 26425, 28800, 31710, 38400, 39638, 52851, 57600, 76800, 79277, 105703, 115200, 158554 }; #endif /*------------------------------------------------------------------------------ Static functions declaration section: - GDDK_09IFDExchange ------------------------------------------------------------------------------*/ static NTSTATUS GDDK_09IFDExchange ( PSMARTCARD_EXTENSION SmartcardExtension, ULONG BufferInLen, BYTE *BufferIn, ULONG BufferOutLen, BYTE *BufferOut, ULONG *LengthOut ); /*------------------------------------------------------------------------------ Function definition section: ------------------------------------------------------------------------------*/ /******************************************************************************* * NTSTATUS GDDK_09ReaderPower * ( * PSMARTCARD_EXTENSION SmartcardExtension * ) * * Description : * ------------- * This function is called by the Smart card library when a * IOCTL_SMARTCARD_POWER occurs. * This function provides 3 differents functionnality, depending of the minor * IOCTL value * - Cold reset (SCARD_COLD_RESET), * - Warm reset (SCARD_WARM_RESET), * - Power down (SCARD_POWER_DOWN). * * Remarks : * ------------- * Nothing. * * In : * ------------- * - SmartcardExtension is a pointer on the SmartCardExtension structure of * the current device. * * Out : * ------------- * Nothing. * * Responses : * ------------- * NTSTATUS *******************************************************************************/ NTSTATUS GDDK_09ReaderPower ( PSMARTCARD_EXTENSION SmartcardExtension ) { NTSTATUS status; /*------------------------------------------------------------------------------ Set the reply buffer length to 0. ------------------------------------------------------------------------------*/ *SmartcardExtension->IoRequest.Information = 0; SmartcardExtension->ReaderExtension->PTSMode = IFD_DEFAULT_MODE; /*------------------------------------------------------------------------------ Call the GDDK_09xxxxxSession functions ------------------------------------------------------------------------------*/ switch(SmartcardExtension->MinorIoControlCode) { case SCARD_POWER_DOWN: status = GDDK_09CloseSession(SmartcardExtension); break; case SCARD_COLD_RESET: status = GDDK_09OpenSession(SmartcardExtension); break; case SCARD_WARM_RESET: status = GDDK_09SwitchSession(SmartcardExtension); break; default: status = STATUS_NOT_SUPPORTED; } return (status); } /******************************************************************************* * NTSTATUS GDDK_09SetProtocol * ( * PSMARTCARD_EXTENSION SmartcardExtension * ) * * Description : * ------------- * This function is called by the Smart card library when a * IOCTL_SMARTCARD_SET_PROTOCOL occurs. * The minor IOCTL value holds the protocol to set. * * Remarks : * ------------- * Nothing. * * In : * ------------- * - SmartcardExtension is a pointer on the SmartCardExtension structure of * the current device. * * Out : * ------------- * Nothing. * * Responses : * ------------- * NTSTATUS *******************************************************************************/ NTSTATUS GDDK_09SetProtocol ( PSMARTCARD_EXTENSION SmartcardExtension ) { NTSTATUS status = STATUS_NOT_SUPPORTED; /*------------------------------------------------------------------------------ Check if the card is already in specific state and if the caller wants to have the already selected protocol. We return SUCCESS if this is the case. ------------------------------------------------------------------------------*/ if ((SmartcardExtension->ReaderCapabilities.CurrentState == SCARD_SPECIFIC) && (SmartcardExtension->CardCapabilities.Protocol.Selected & SmartcardExtension->MinorIoControlCode)) { status = STATUS_SUCCESS; } /*------------------------------------------------------------------------------ Else Check if the card is absent. We return NO_MEDIA if this is the case. ------------------------------------------------------------------------------*/ else if (SmartcardExtension->ReaderCapabilities.CurrentState == SCARD_ABSENT) { status = STATUS_NO_MEDIA; } /*------------------------------------------------------------------------------ Else if the Current state is SCARD_NEGOTIABLE Check if we can support one of the specified protocols; else we return STATUS_NOT_SUPPORTED. If we want to negotiate the speed, then we set the PTS1 byte with the Fl/Dl parameters specified by the SMCLIB. Send an other reset command with the appropriate PTS request. ------------------------------------------------------------------------------*/ else if (SmartcardExtension->ReaderCapabilities.CurrentState == SCARD_NEGOTIABLE) { if (SmartcardExtension->MinorIoControlCode & SCARD_PROTOCOL_T0) { SmartcardExtension->ReaderExtension->PTS0 = IFD_NEGOTIATE_T0; } else if (SmartcardExtension->MinorIoControlCode & SCARD_PROTOCOL_T1) { SmartcardExtension->ReaderExtension->PTS0 = IFD_NEGOTIATE_T1; } else { status = STATUS_NOT_SUPPORTED; } if (status == STATUS_SUCCESS) { SmartcardExtension->ReaderExtension->PTSMode = IFD_NEGOTIATE_PTS_MANUALLY; SmartcardExtension->ReaderExtension->PTS2 = 0x00; SmartcardExtension->ReaderExtension->PTS3 = 0x00; #if (SMCLIB_VERSION >= 0x130) if ((SmartcardExtension->MinorIoControlCode & SCARD_PROTOCOL_DEFAULT) == 0) { SmartcardExtension->ReaderExtension->PTS0 |= IFD_NEGOTIATE_PTS1; SmartcardExtension->ReaderExtension->PTS1 = (0xF0 & (SmartcardExtension->CardCapabilities.PtsData.Fl<<4)) | (0x0F & SmartcardExtension->CardCapabilities.PtsData.Dl) ; } #endif status = GDDK_09OpenSession(SmartcardExtension); if (status != STATUS_SUCCESS) status = STATUS_NOT_SUPPORTED; } } /*------------------------------------------------------------------------------ Else The mask contains no known protocol. We return INVALID_DEVICE_REQUEST if this is the case. ------------------------------------------------------------------------------*/ else { status = STATUS_INVALID_DEVICE_REQUEST; } /*------------------------------------------------------------------------------ Set the reply buffer length to sizeof(ULONG). Check if status SUCCESS, store the selected protocol. ------------------------------------------------------------------------------*/ *SmartcardExtension->IoRequest.Information = sizeof(ULONG); if (status == STATUS_SUCCESS) { *(ULONG *)SmartcardExtension->IoRequest.ReplyBuffer = SmartcardExtension->CardCapabilities.Protocol.Selected; } /*------------------------------------------------------------------------------ Else Set the selected protocol to undefined. ------------------------------------------------------------------------------*/ else { *(ULONG *)SmartcardExtension->IoRequest.ReplyBuffer = SCARD_PROTOCOL_UNDEFINED; } return (status); } /******************************************************************************* * NTSTATUS GDDK_09Transmit * ( * PSMARTCARD_EXTENSION SmartcardExtension * ) * * Description : * ------------- * This function is called by the Smart card library when a * IOCTL_SMARTCARD_TRANSMIT occurs. * This function is used to transmit a command to the card. * * Remarks : * ------------- * Nothing. * * In : * ------------- * - SmartcardExtension is a pointer on the SmartCardExtension structure of * the current device. * * Out : * ------------- * Nothing. * * Responses : * ------------- * NTSTATUS *******************************************************************************/ NTSTATUS GDDK_09Transmit ( PSMARTCARD_EXTENSION SmartcardExtension ) { NTSTATUS status; PUCHAR requestBuffer = SmartcardExtension->SmartcardRequest.Buffer, replyBuffer = SmartcardExtension->SmartcardReply.Buffer; PULONG requestLength = &SmartcardExtension->SmartcardRequest.BufferLength; PSCARD_IO_REQUEST scardIoRequest = (PSCARD_IO_REQUEST) SmartcardExtension->OsData->CurrentIrp->AssociatedIrp.SystemBuffer; USHORT i, buffLen, lenExp, lenIn; UCHAR *buffIn; INT16 response; READER_EXTENSION *param = SmartcardExtension->ReaderExtension; WORD16 rlen; BYTE rbuff[HOR3GLL_BUFFER_SIZE]; /*------------------------------------------------------------------------------ Set the reply buffer length to 0. ------------------------------------------------------------------------------*/ *SmartcardExtension->IoRequest.Information = 0; status = STATUS_SUCCESS; /*------------------------------------------------------------------------------ Verify if the protocol specified is the same than the protocol selected. <== STATUS_INVALID_DEVICE_STATE ------------------------------------------------------------------------------*/ *requestLength = 0; if (SmartcardExtension->CardCapabilities.Protocol.Selected != scardIoRequest->dwProtocol) { return (STATUS_INVALID_DEVICE_STATE); } /*------------------------------------------------------------------------------ Lock the mutex to avoid a call of an other command. ------------------------------------------------------------------------------*/ GDDK_09LockExchange(SmartcardExtension); /*------------------------------------------------------------------------------ For the different protocols: ------------------------------------------------------------------------------*/ switch (SmartcardExtension->CardCapabilities.Protocol.Selected) { /*------------------------------------------------------------------------------ RAW protocol: <== STATUS_INVALID_DEVICE_STATE ------------------------------------------------------------------------------*/ case SCARD_PROTOCOL_RAW: status = STATUS_INVALID_DEVICE_STATE; break; /*------------------------------------------------------------------------------ T=0 PROTOCOL: Call the SmartCardT0Request which updates the SmartcardRequest struct. ------------------------------------------------------------------------------*/ case SCARD_PROTOCOL_T0: SmartcardExtension->SmartcardRequest.BufferLength = 0; status = SmartcardT0Request(SmartcardExtension); if (status == STATUS_SUCCESS) { rlen = HOR3GLL_BUFFER_SIZE; /*------------------------------------------------------------------------------ If the length LEx > 0 Then Is an ISO Out command. If LEx > SC_IFD_GEMCORE_T0_MAXIMUM_LEX (256) <== STATUS_BUFFER_TOO_SMALL Call the G_Oros3IsoOutput ------------------------------------------------------------------------------*/ if (SmartcardExtension->T0.Le > 0) { if (SmartcardExtension->T0.Le > SC_IFD_GEMCORE_T0_MAXIMUM_LEX) { status = STATUS_BUFFER_TOO_SMALL; } if (status == STATUS_SUCCESS) { response = G_Oros3IsoOutput ( param->Handle, param->APDUTimeOut, HOR3GLL_IFD_CMD_ICC_ISO_OUT, (BYTE *)SmartcardExtension->SmartcardRequest.Buffer, &rlen, rbuff ); } } /*------------------------------------------------------------------------------ Else Is an ISO In command. If LC > SC_IFD_GEMCORE_T0_MAXIMUM_LC (255) <== STATUS_BUFFER_TOO_SMALL Call the G_Oros3IsoInput ------------------------------------------------------------------------------*/ else { if (SmartcardExtension->T0.Lc > SC_IFD_GEMCORE_T0_MAXIMUM_LC) { status = STATUS_BUFFER_TOO_SMALL; } if (status == STATUS_SUCCESS) { response = G_Oros3IsoInput( param->Handle, param->APDUTimeOut, HOR3GLL_IFD_CMD_ICC_ISO_IN, (BYTE *)SmartcardExtension->SmartcardRequest.Buffer, (BYTE *)SmartcardExtension->SmartcardRequest.Buffer + 5, &rlen, rbuff ); } } } /*------------------------------------------------------------------------------ If the response == G_OK GE_Translate(reader status) Call the G_DDKTranslate function ------------------------------------------------------------------------------*/ if (status == STATUS_SUCCESS) { if (response == G_OK) response = GE_Translate(rbuff[0]); status = GDDK_Translate(response,RDF_TRANSMIT); } /*------------------------------------------------------------------------------ If the Status is Success Copy the response in the SmartcardReply buffer. Remove the status of the reader. Call the SmartcardT0reply function to update the IORequest struct. ------------------------------------------------------------------------------*/ if (status == STATUS_SUCCESS) { ASSERT(SmartcardExtension->SmartcardReply.BufferSize >= (ULONG) (rlen - 1) ); RtlCopyMemory( SmartcardExtension->SmartcardReply.Buffer, rbuff + 1, rlen - 1); SmartcardExtension->SmartcardReply.BufferLength = (ULONG) (rlen - 1); status = SmartcardT0Reply(SmartcardExtension); } break; /*------------------------------------------------------------------------------ T=1 PROTOCOL: We don't use the SmartCardT1Request and SmartCardT1Reply functions, then we must verify the size of the buffers and the command ourselves. ------------------------------------------------------------------------------*/ case SCARD_PROTOCOL_T1: buffLen = (USHORT)SmartcardExtension->IoRequest.RequestBufferLength - sizeof(SCARD_IO_REQUEST); buffIn = (UCHAR *)SmartcardExtension->IoRequest.RequestBuffer + sizeof(SCARD_IO_REQUEST); if (buffLen > 5) { lenIn = buffIn[4]; if (buffLen > (USHORT)(5 + lenIn)) { lenExp =((buffIn[5+ lenIn] == 0) ? 256 : buffIn[5 + lenIn]); } else { lenExp = 0; } } else if (buffLen == 5) { lenIn = 0; lenExp = ((buffIn[4] == 0) ? 256 : buffIn[4]); } else { lenExp = 0; lenIn = 0; } /*------------------------------------------------------------------------------ If LEx > SC_IFD_GEMCORE_T1_MAXIMUM_LEX (256) STATUS_BUFFER_TOO_SMALL If LC > SC_IFD_GEMCORE_T1_MAXIMUM_LC (255) STATUS_BUFFER_TOO_SMALL ------------------------------------------------------------------------------*/ if (lenExp > SC_IFD_GEMCORE_T1_MAXIMUM_LEX) { status = STATUS_BUFFER_TOO_SMALL; } else if (lenIn > SC_IFD_GEMCORE_T1_MAXIMUM_LC) { status = STATUS_BUFFER_TOO_SMALL; } /*------------------------------------------------------------------------------ Call the G_Oros3IsoT1 ------------------------------------------------------------------------------*/ if (status == STATUS_SUCCESS) { rlen = HOR3GLL_BUFFER_SIZE; response = G_Oros3IsoT1( param->Handle, param->APDUTimeOut, HOR3GLL_IFD_CMD_ICC_APDU, buffLen, buffIn, &rlen, rbuff ); } /*------------------------------------------------------------------------------ If the response == G_OK GE_Translate(reader status) Call the G_DDKTranslate function ------------------------------------------------------------------------------*/ if (status == STATUS_SUCCESS) { if (response == G_OK) response = GE_Translate(rbuff[0]); status = GDDK_Translate(response,RDF_TRANSMIT); } /*------------------------------------------------------------------------------ If the Status is Success If the length of the returned bytes is greate than the size of the reply buffer <== STATUS_BUFFER_OVERFLOW Copy the response in the IoRequest.ReplyBuffer. Remove the status of the reader. <== STATUS_SUCCESS ------------------------------------------------------------------------------*/ if (status == STATUS_SUCCESS) { if ( (rlen - 1) > (WORD16) ( SmartcardExtension->IoRequest.ReplyBufferLength - sizeof(SCARD_IO_REQUEST) ) ) { status = STATUS_BUFFER_TOO_SMALL; } if (status == STATUS_SUCCESS) { RtlCopyMemory( SmartcardExtension->IoRequest.ReplyBuffer + sizeof(SCARD_IO_REQUEST), rbuff + 1, rlen - 1 ); *(SmartcardExtension->IoRequest.Information) = (ULONG) sizeof(SCARD_IO_REQUEST) + rlen - 1; } } break; default: status = STATUS_INVALID_DEVICE_REQUEST; break; } /*------------------------------------------------------------------------------ Unlock the mutex. ------------------------------------------------------------------------------*/ GDDK_09UnlockExchange(SmartcardExtension); return (status); } /******************************************************************************* * NTSTATUS GDDK_09CardTracking * ( * PSMARTCARD_EXTENSION SmartcardExtension * ) * * Description : * ------------- * This function is called by the Smart card library when an * IOCTL_SMARTCARD_IS_PRESENT or IOCTL_SMARTCARD_IS_ABSENT occurs. * * Remarks : * ------------- * Nothing. * * In : * ------------- * - SmartcardExtension is a pointer on the SmartCardExtension structure of * the current device. * * Out : * ------------- * Nothing. * * Responses : * ------------- * NTSTATUS *******************************************************************************/ NTSTATUS GDDK_09CardTracking ( PSMARTCARD_EXTENSION SmartcardExtension ) { NTSTATUS status; KIRQL oldIrql; /*------------------------------------------------------------------------------ Check if the reader can support this function. ------------------------------------------------------------------------------*/ if (SmartcardExtension->ReaderExtension->IFDNumber != 0) { return STATUS_PENDING; } // Set cancel routine for the notification irp IoAcquireCancelSpinLock(&oldIrql); IoSetCancelRoutine(SmartcardExtension->OsData->NotificationIrp,GDDKNT_09Cleanup); IoReleaseCancelSpinLock(oldIrql); return STATUS_PENDING; } /******************************************************************************* * NTSTATUS GDDK_09SpecificIOCTL * ( * PSMARTCARD_EXTENSION SmartcardExtension, * DWORD IoControlCode, * DWORD BufferInLen, * BYTE *BufferIn, * DWORD BufferOutLen, * BYTE *BufferOut, * DWORD *LengthOut *) * * Description : * ------------- * This function is called when a specific IOCTL occurs. * * Remarks : * ------------- * Nothing. * * In : * ------------- * - SmartcardExtension is a pointer on the SmartCardExtension structure of * the current device. * - IoControlCode holds the IOCTL value. * * Out : * ------------- * Nothing. * * Responses : * ------------- * NTSTATUS *******************************************************************************/ NTSTATUS GDDK_09SpecificIOCTL ( PSMARTCARD_EXTENSION SmartcardExtension, DWORD IoControlCode, ULONG BufferInLen, BYTE *BufferIn, DWORD BufferOutLen, BYTE *BufferOut, DWORD *LengthOut ) { /*------------------------------------------------------------------------------ Set the reply buffer length to 0. ------------------------------------------------------------------------------*/ *LengthOut = 0; /*------------------------------------------------------------------------------ Switch for the different IOCTL: ------------------------------------------------------------------------------*/ switch(IoControlCode) { /*------------------------------------------------------------------------------ IOCTL_SMARTCARD_IFD_EXCHANGE: <== GDDK_09IFDExchange ------------------------------------------------------------------------------*/ case IOCTL_SMARTCARD_IFD_EXCHANGE: return GDDK_09IFDExchange( SmartcardExtension, BufferInLen, BufferIn, BufferOutLen, BufferOut, LengthOut ); break; default: return STATUS_NOT_SUPPORTED; break; } } /******************************************************************************* * NTSTATUS GDDK_09SpecificTag * ( * PSMARTCARD_EXTENSION SmartcardExtension, * DWORD IoControlCode * DWORD BufferInLen, * BYTE *BufferIn, * DWORD BufferOutLen, * BYTE *BufferOut, * DWORD *LengthOut *) * * Description : * ------------- * This function is called when a specific Tag request occurs. * * Remarks : * ------------- * Nothing. * * In : * ------------- * - SmartcardExtension is a pointer on the SmartCardExtension structure of * the current device. * - IoControlCode holds the IOCTL value. * * Out : * ------------- * Nothing. * * Responses : * ------------- * NTSTATUS *******************************************************************************/ NTSTATUS GDDK_09SpecificTag ( PSMARTCARD_EXTENSION SmartcardExtension, DWORD IoControlCode, DWORD BufferInLen, BYTE *BufferIn, DWORD BufferOutLen, BYTE *BufferOut, DWORD *LengthOut ) { ULONG i, TagValue; PREADER_EXTENSION pReaderExtension = SmartcardExtension->ReaderExtension; ASSERT(pReaderExtension != NULL); /*------------------------------------------------------------------------------ Set the reply buffer length to 0. ------------------------------------------------------------------------------*/ *LengthOut = 0; /*------------------------------------------------------------------------------ Verify the length of the Tag <== STATUS_BUFFER_TOO_SMALL ------------------------------------------------------------------------------*/ if (BufferInLen < (DWORD) sizeof(TagValue)) { return(STATUS_BUFFER_TOO_SMALL); } TagValue = (ULONG) *((PULONG)BufferIn); /*------------------------------------------------------------------------------ Switch for the different IOCTL: Get the value of one tag (IOCTL_SMARTCARD_GET_ATTRIBUTE) Switch for the different Tags: ------------------------------------------------------------------------------*/ switch(IoControlCode) { case IOCTL_SMARTCARD_GET_ATTRIBUTE: switch (TagValue) { /*------------------------------------------------------------------------------ Baud rate of the reader (SCARD_ATTR_SPEC_BAUD_RATE) Verify the length of the output buffer. <== STATUS_BUFFER_TOO_SMALL Update the output buffer and the length. <== STATUS_SUCCESS ------------------------------------------------------------------------------*/ case SCARD_ATTR_SPEC_BAUD_RATE: if ( BufferOutLen < (DWORD) sizeof(pReaderExtension->IFDBaudRate) ) { return(STATUS_BUFFER_TOO_SMALL); } memcpy( BufferOut, &pReaderExtension->IFDBaudRate, sizeof(pReaderExtension->IFDBaudRate) ); *(LengthOut) = (ULONG) sizeof(pReaderExtension->IFDBaudRate); return (STATUS_SUCCESS); break; /*------------------------------------------------------------------------------ IFD number of the reader (SCARD_ATTR_SPEC_IFD_NUMBER) Verify the length of the output buffer. <== STATUS_BUFFER_TOO_SMALL Update the output buffer and the length. <== STATUS_SUCCESS ------------------------------------------------------------------------------*/ case SCARD_ATTR_SPEC_IFD_NUMBER: if ( BufferOutLen < (DWORD) sizeof(pReaderExtension->IFDNumber) ) { return(STATUS_BUFFER_TOO_SMALL); } memcpy( BufferOut, &pReaderExtension->IFDNumber, sizeof(pReaderExtension->IFDNumber) ); *(LengthOut) = (ULONG) sizeof(pReaderExtension->IFDNumber); return STATUS_SUCCESS; break; /*------------------------------------------------------------------------------ ICC type (SCARD_ATTR_SPEC_ICC_TYPE) Verify the length of the output buffer. <== STATUS_BUFFER_TOO_SMALL Update the output buffer and the length. <== STATUS_SUCCESS ------------------------------------------------------------------------------*/ case SCARD_ATTR_SPEC_ICC_TYPE: if ( BufferOutLen < (DWORD) sizeof(pReaderExtension->ICCType) ) { return(STATUS_BUFFER_TOO_SMALL); } memcpy( BufferOut, &pReaderExtension->ICCType, sizeof(pReaderExtension->ICCType) ); *(LengthOut) = (ULONG) sizeof(pReaderExtension->ICCType); return STATUS_SUCCESS; break; /*------------------------------------------------------------------------------ Power Timeout (SCARD_ATTR_SPEC_POWER_TIMEOUT) Verify the length of the output buffer. <== STATUS_BUFFER_TOO_SMALL Update the output buffer and the length. <== STATUS_SUCCESS ------------------------------------------------------------------------------*/ case SCARD_ATTR_SPEC_POWER_TIMEOUT: if ( BufferOutLen < (DWORD) sizeof(pReaderExtension->PowerTimeOut) ) { return(STATUS_BUFFER_TOO_SMALL); } memcpy( BufferOut, &pReaderExtension->PowerTimeOut, sizeof(pReaderExtension->PowerTimeOut) ); *(LengthOut) = (ULONG) sizeof(pReaderExtension->PowerTimeOut); return STATUS_SUCCESS; break; /*------------------------------------------------------------------------------ Command Timeout (SCARD_ATTR_SPEC_CMD_TIMEOUT) Verify the length of the output buffer. <== STATUS_BUFFER_TOO_SMALL Update the output buffer and the length. <== STATUS_SUCCESS ------------------------------------------------------------------------------*/ case SCARD_ATTR_SPEC_CMD_TIMEOUT: if ( BufferOutLen < (DWORD) sizeof(pReaderExtension->CmdTimeOut) ) { return(STATUS_BUFFER_TOO_SMALL); } memcpy( BufferOut, &pReaderExtension->CmdTimeOut, sizeof(pReaderExtension->CmdTimeOut) ); *(LengthOut) = (ULONG) sizeof(pReaderExtension->CmdTimeOut); return STATUS_SUCCESS; break; /*------------------------------------------------------------------------------ APDU Timeout (SCARD_ATTR_SPEC_APDU_TIMEOUT) Verify the length of the output buffer. <== STATUS_BUFFER_TOO_SMALL Update the output buffer and the length. <== STATUS_SUCCESS ------------------------------------------------------------------------------*/ case SCARD_ATTR_SPEC_APDU_TIMEOUT: if ( BufferOutLen < (DWORD) sizeof(pReaderExtension->APDUTimeOut) ) { return(STATUS_BUFFER_TOO_SMALL); } memcpy( BufferOut, &pReaderExtension->APDUTimeOut, sizeof(pReaderExtension->APDUTimeOut) ); *(LengthOut) = (ULONG) sizeof(pReaderExtension->APDUTimeOut); return STATUS_SUCCESS; break; /*------------------------------------------------------------------------------ IFD Option (SCARD_ATTR_SPEC_IFD_OPTION) Verify the length of the output buffer. <== STATUS_BUFFER_TOO_SMALL Update the output buffer and the length. <== STATUS_SUCCESS ------------------------------------------------------------------------------*/ case SCARD_ATTR_SPEC_IFD_OPTION: if ( BufferOutLen < sizeof(pReaderExtension->IFDOption) ) { return(STATUS_BUFFER_TOO_SMALL); } memcpy( BufferOut, &pReaderExtension->IFDOption, sizeof(pReaderExtension->IFDOption) ); *(LengthOut) = (ULONG) sizeof(pReaderExtension->IFDOption); return STATUS_SUCCESS; break; /*------------------------------------------------------------------------------ IFD Option (SCARD_ATTR_SPEC_MAXIMAL_IFD) Verify the length of the output buffer. <== STATUS_BUFFER_TOO_SMALL Update the output buffer and the length. <== STATUS_SUCCESS ------------------------------------------------------------------------------*/ case SCARD_ATTR_SPEC_MAXIMAL_IFD: if ( BufferOutLen < sizeof(pReaderExtension->MaximalIFD) ) { return(STATUS_BUFFER_TOO_SMALL); } memcpy( BufferOut, &pReaderExtension->MaximalIFD, sizeof(pReaderExtension->MaximalIFD) ); *(LengthOut) = (ULONG) sizeof(pReaderExtension->MaximalIFD); return STATUS_SUCCESS; break; /*------------------------------------------------------------------------------ Unknown tag <== STATUS_NOT_SUPPORTED ------------------------------------------------------------------------------*/ default: return STATUS_NOT_SUPPORTED; break; } break; /*------------------------------------------------------------------------------ Set the value of one tag (IOCTL_SMARTCARD_SET_ATTRIBUTE) Switch for the different Tags: ------------------------------------------------------------------------------*/ case IOCTL_SMARTCARD_SET_ATTRIBUTE: switch (TagValue) { /*------------------------------------------------------------------------------ ICC type (SCARD_ATTR_SPEC_ICC_TYPE) Verify the length of the input buffer. <== STATUS_BUFFER_TOO_SMALL Update the value. <== STATUS_SUCCESS ------------------------------------------------------------------------------*/ case SCARD_ATTR_SPEC_ICC_TYPE: if ( BufferInLen < (DWORD) ( sizeof(pReaderExtension->ICCType) + sizeof(TagValue)) ) { return(STATUS_BUFFER_TOO_SMALL); } memcpy( &pReaderExtension->ICCType, BufferIn + sizeof(TagValue), sizeof(pReaderExtension->ICCType) ); return STATUS_SUCCESS; break; /*------------------------------------------------------------------------------ Power Timeout (SCARD_ATTR_SPEC_POWER_TIMEOUT) Verify the length of the input buffer. <== STATUS_BUFFER_TOO_SMALL Update the value. <== STATUS_SUCCESS ------------------------------------------------------------------------------*/ case SCARD_ATTR_SPEC_POWER_TIMEOUT: if ( BufferInLen < (DWORD) (sizeof(pReaderExtension->PowerTimeOut) + sizeof(TagValue)) ) { return(STATUS_BUFFER_TOO_SMALL); } memcpy( &pReaderExtension->PowerTimeOut, BufferIn + sizeof(TagValue), sizeof(pReaderExtension->PowerTimeOut) ); return STATUS_SUCCESS; break; /*------------------------------------------------------------------------------ Command Timeout (SCARD_ATTR_SPEC_CMD_TIMEOUT) Verify the length of the input buffer. <== STATUS_BUFFER_TOO_SMALL Update the value. <== STATUS_SUCCESS ------------------------------------------------------------------------------*/ case SCARD_ATTR_SPEC_CMD_TIMEOUT: if ( BufferInLen < (DWORD) (sizeof(pReaderExtension->CmdTimeOut) + sizeof(TagValue)) ) { return(STATUS_BUFFER_TOO_SMALL); } memcpy( &pReaderExtension->CmdTimeOut, BufferIn + sizeof(TagValue), sizeof(pReaderExtension->CmdTimeOut) ); return STATUS_SUCCESS; break; /*------------------------------------------------------------------------------ Command Timeout (SCARD_ATTR_SPEC_APDU_TIMEOUT) Verify the length of the input buffer. <== STATUS_BUFFER_TOO_SMALL Update the value. <== STATUS_SUCCESS ------------------------------------------------------------------------------*/ case SCARD_ATTR_SPEC_APDU_TIMEOUT: if ( BufferInLen < (DWORD) (sizeof(pReaderExtension->APDUTimeOut) + sizeof(TagValue)) ) { return(STATUS_BUFFER_TOO_SMALL); } memcpy( &pReaderExtension->APDUTimeOut, BufferIn + sizeof(TagValue), sizeof(pReaderExtension->APDUTimeOut) ); return STATUS_SUCCESS; break; /*------------------------------------------------------------------------------ Unknown tag <== STATUS_NOT_SUPPORTED ------------------------------------------------------------------------------*/ default: return STATUS_NOT_SUPPORTED; } break; default: return STATUS_NOT_SUPPORTED; break; } } /******************************************************************************* * NTSTATUS GDDK_09OpenChannel * ( * PSMARTCARD_EXTENSION SmartcardExtension, * CONST WORD32 DeviceNumber, * CONST WORD32 PortSerialNumber, * CONST WORD32 IFDNumber, * CONST WORD32 MaximalBaudRate * ) * Description : * ------------- * This routine try to establish a connection with a reader, and after * update the characteristic of this reader. * * Remarks : * ------------- * Nothing. * * In : * ------------- * - SmartcardExtension is a pointer on the SmartCardExtension structure of * the current device. * - DeviceNumber holds the current device number (0 to MAX_DEVICES). * - PortSerialNumber holds the port serial number (0 to HGTSER_MAX_PORT). * - IFDNumber holds the numero of the IFD in the reader (0 to MAX_IFD_BY_READER) * - MaximalBaudRate holds the maximal speed specified for the reader. * * Out : * ------------- * - SmartcardExtension is updated. * * Responses : * ------------- * If everything is Ok: * G_OK *******************************************************************************/ NTSTATUS GDDK_09OpenChannel ( PSMARTCARD_EXTENSION SmartcardExtension, CONST WORD32 DeviceNumber, CONST WORD32 PortSerialNumber, CONST WORD32 IFDNumber, CONST WORD32 MaximalBaudRate ) { /*------------------------------------------------------------------------------ Local variables: - handle holds the communication handle to associate to the channel. - channel_nb holds the number associated to the channel. - lmod_name and lmod_release are used to control the called library version. - response holds the called function responses. - os_string and os_length are used to recognized an OROS2.x IFD on the channel. - oros_version holds the minor version value of the IFD. - user, comm and br are used to optimizes the baudrate. ------------------------------------------------------------------------------*/ NTSTATUS status = STATUS_SUCCESS; INT16 handle, portcom, channel_nb, i, oros_version, response; char G_FAR *oros_info; char os_string[HOR3GLL_OS_STRING_SIZE]; WORD16 os_length = HOR3GLL_OS_STRING_SIZE; WORD16 user; TGTSER_PORT comm; WORD32 br; BYTE minorVersion, majorVersion; BOOL b_compare = TRUE; G4_CHANNEL_PARAM g4_channel; WORD16 rlen; BYTE cmd[5], rbuff[HOR3GLL_BUFFER_SIZE]; /*------------------------------------------------------------------------------ Update the serial communication channel information: ------------------------------------------------------------------------------*/ g4_channel.Comm.Serial.Port = PortSerialNumber + G_COM1; g4_channel.Comm.Serial.BaudRate = MaximalBaudRate; g4_channel.Comm.Serial.ITNumber = DEFAULT_IT; g4_channel.pSmartcardExtension = SmartcardExtension; /*------------------------------------------------------------------------------ Initializes a mutex object (in a high level) for the exchange commands with the smart card reader. ------------------------------------------------------------------------------*/ KeInitializeMutex( &SmartcardExtension->ReaderExtension->ExchangeMutex, 3 ); /*------------------------------------------------------------------------------ Initializes a mutex object (in a high level) for the long APDU commands with the smart card reader. ------------------------------------------------------------------------------*/ KeInitializeMutex( &SmartcardExtension->ReaderExtension->LongAPDUMutex, 3 ); /*------------------------------------------------------------------------------ Opens a serial communication channel: Open a communication channel (G_Oros3OpenComm). The reader baudrate is automatically detected by this function. If the port is already opened Then Adds a user on this port (G_SerPortAddUser) <= Test the last received status (>= G_OK): G_Oros3OpenComm/G_SerPortAddUser ------------------------------------------------------------------------------*/ handle = (INT16)DeviceNumber; response = G_Oros3OpenComm(&g4_channel,handle); if (response == GE_HOST_PORT_OPEN) { response = portcom = G_SerPortAddUser((WORD16) g4_channel.Comm.Serial.Port); if (response < G_OK) { return (GDDK_Translate(response,(const ULONG) NULL)); } G_GBPOpen(handle,2,4,portcom); } if (response < G_OK) { return (GDDK_Translate(response,(const ULONG) NULL)); } /*------------------------------------------------------------------------------ Verifies that an OROS3.x IFD is connected to the selected port. Sets the command according to the parameters. Read OROS memory type 0x05, 13 bytes from 0x3FE0. <= G_Oros3Exchange status. ------------------------------------------------------------------------------*/ cmd[0] = (BYTE) HOR3GLL_IFD_CMD_MEM_RD; cmd[1] = (BYTE)HOR3GLL_IFD_TYP_VERSION; cmd[2] = HIBYTE(HOR3GLL_IFD_ADD_VERSION); cmd[3] = LOBYTE(HOR3GLL_IFD_ADD_VERSION); cmd[4] = (BYTE)HOR3GLL_IFD_LEN_VERSION; response = G_Oros3Exchange( handle, HOR3GLL_LOW_TIME, 5, cmd, &os_length, os_string ); if (response < G_OK) { G_Oros3CloseComm(handle); return (GDDK_Translate(response,(const ULONG) NULL)); } /*------------------------------------------------------------------------------ Verify the Firmware version: this driver support only the GemCore based readers. Read the minor version of the reader. ------------------------------------------------------------------------------*/ if (os_length >= (WORD16)strlen(IFD_FIRMWARE_VERSION)) { if (memcmp(os_string + 1,IFD_FIRMWARE_VERSION,strlen(IFD_FIRMWARE_VERSION))) { G_Oros3CloseComm(handle); return (GDDK_Translate(GE_IFD_UNKNOWN,(const ULONG) NULL)); } } else { G_Oros3CloseComm(handle); return (GDDK_Translate(GE_IFD_UNKNOWN,(const ULONG) NULL)); } majorVersion = os_string[strlen(IFD_FIRMWARE_VERSION)-1] - '0'; minorVersion = 10 * (os_string[strlen(IFD_FIRMWARE_VERSION)+1] - '0') + os_string[strlen(IFD_FIRMWARE_VERSION)+2] - '0'; /*------------------------------------------------------------------------------ Verify if the reader can support a security module ------------------------------------------------------------------------------*/ if (IFDNumber > 0) { rlen = HOR3GLL_BUFFER_SIZE; response = G_Oros3IccPowerDown ( handle, HOR3GLL_DEFAULT_TIME, &rlen, rbuff ); if ((response != G_OK) || (rlen != 1) || ((rbuff[0] != 0x00) && (rbuff[0] != 0xFB))) { G_Oros3CloseComm(handle); return STATUS_NO_MEDIA; } } /*------------------------------------------------------------------------------ Optimizes the baudrate: Initializes the comm variable to modify the used baud rate. The optimization start at the given baudrate, then the used value is divised by 2 until the communication is possible or the tried baudrate is lower than 9600. ------------------------------------------------------------------------------*/ comm.Port = (WORD16) g4_channel.Comm.Serial.Port; response = G_SerPortGetState(&comm,&user); comm.BaudRate = g4_channel.Comm.Serial.BaudRate; for(br = g4_channel.Comm.Serial.BaudRate; br >= 9600lu; br = br / 2) { /*------------------------------------------------------------------------------ The reader is switched to the selected value (G_Oros3SIOConfigure). The function status is not tested because, as the IFD has switched immediatly, it is not possible to read its response. ------------------------------------------------------------------------------*/ comm.BaudRate = br; rlen = HOR3GLL_BUFFER_SIZE; G_Oros3SIOConfigure( handle, HOR3GLL_LOW_TIME, 0, 8, comm.BaudRate, &rlen, rbuff ); /*------------------------------------------------------------------------------ Host is switched to the selected value (G_SerPortSetState). If this call is successful, Then The last SIO command is re-sent to read the IFD response. response is optionnaly initialized with the translated IFD status. ------------------------------------------------------------------------------*/ response = G_SerPortSetState(&comm); if (response == G_OK) { rlen = HOR3GLL_BUFFER_SIZE; response = G_Oros3SIOConfigure( handle, HOR3GLL_LOW_TIME, 0, 8, comm.BaudRate, &rlen, rbuff ); if (response >= G_OK) { response = GE_Translate(rbuff[0]); break; } } } /*------------------------------------------------------------------------------ If the loop is ended without a good communication with IFD, Then The port is closed. <= GE_HI_COMM. ------------------------------------------------------------------------------*/ if ((br < 9600) || (response != G_OK)) { G_Oros3CloseComm(handle); return (GDDK_Translate(GE_HI_COMM,(const ULONG) NULL)); } /*------------------------------------------------------------------------------ Removes the TLP compatibility mode. <= Sends the SetMode command with parameter 0 to disable TLP compatibility. Closes the opened port (G_Oros3CloseComm). ------------------------------------------------------------------------------*/ rlen = HOR3GLL_BUFFER_SIZE; response = G_Oros3SetMode(handle,HOR3GLL_LOW_TIME,0x00,&rlen,rbuff); if (response < G_OK) { G_Oros3CloseComm(handle); return (GDDK_Translate(response,(const ULONG) NULL)); } /*------------------------------------------------------------------------------ Reader capabilities: - the type of the reader (SCARD_READER_TYPE_SERIAL) - the channel for the reader (PortSerialNumber) - the protocols supported by the reader (SCARD_PROTOCOL_T0, SCARD_PROTOCOL_T1) - the mechanical characteristic of the reader: Verify if the reader can supports the detection of the card insertion/removal. Only the main reader supports this functionnality. ------------------------------------------------------------------------------*/ SmartcardExtension->ReaderCapabilities.ReaderType = SCARD_READER_TYPE_SERIAL; SmartcardExtension->ReaderCapabilities.Channel = PortSerialNumber; #if SMCLIB_VERSION >= 0x0130 SmartcardExtension->ReaderCapabilities.SupportedProtocols = SCARD_PROTOCOL_T0 | SCARD_PROTOCOL_T1; #else SmartcardExtension->ReaderCapabilities.SupportedProtocols.Async = SCARD_PROTOCOL_T0 | SCARD_PROTOCOL_T1; #endif SmartcardExtension->ReaderCapabilities.MechProperties = 0; /*------------------------------------------------------------------------------ Reader capabilities (continue): - the default clock frequency (SC_IFD_GEMCORE_DEFAULT_CLK_FREQUENCY) - the maximum clock frequency (SC_IFD_GEMCORE_MAXIMUM_CLK_FREQUENCY) - the default data rate (SC_IFD_GEMCORE_DEFAULT_DATA_RATE) - the maximum data rate (SC_IFD_GEMCORE_MAXIMUM_DATA_RATE) - the maximum IFSD (SC_IFD_GEMCORE_MAXIMUM_IFSD) - the power management is set to 0. ------------------------------------------------------------------------------*/ SmartcardExtension->ReaderCapabilities.CLKFrequency.Default = SC_IFD_GEMCORE_DEFAULT_CLK_FREQUENCY; SmartcardExtension->ReaderCapabilities.CLKFrequency.Max = SC_IFD_GEMCORE_MAXIMUM_CLK_FREQUENCY; SmartcardExtension->ReaderCapabilities.DataRate.Default = SC_IFD_GEMCORE_DEFAULT_DATA_RATE; SmartcardExtension->ReaderCapabilities.DataRate.Max = SC_IFD_GEMCORE_MAXIMUM_DATA_RATE; SmartcardExtension->ReaderCapabilities.MaxIFSD = SC_IFD_GEMCORE_MAXIMUM_IFSD; SmartcardExtension->ReaderCapabilities.PowerMgmtSupport = 0; #if SMCLIB_VERSION >= 0x0130 /*------------------------------------------------------------------------------ Reader capabilities (continue): - List all the supported data rates ------------------------------------------------------------------------------*/ SmartcardExtension->ReaderCapabilities.DataRatesSupported.List = dataRatesSupported; SmartcardExtension->ReaderCapabilities.DataRatesSupported.Entries = sizeof(dataRatesSupported) / sizeof(dataRatesSupported[0]); #endif /*------------------------------------------------------------------------------ Vendor Attributes: - the vendor information (SC_VENDOR_NAME) ------------------------------------------------------------------------------*/ strcpy( SmartcardExtension->VendorAttr.VendorName.Buffer, SC_VENDOR_NAME ); SmartcardExtension->VendorAttr.VendorName.Length = strlen(SmartcardExtension->VendorAttr.VendorName.Buffer); /*------------------------------------------------------------------------------ Vendor Attributes (continue): - the IFD Type information (SC_IFD_SAM_TYPE or SC_IFD_TYPE) ------------------------------------------------------------------------------*/ if (IFDNumber > 0) { strcpy(SmartcardExtension->VendorAttr.IfdType.Buffer,SC_IFD_SAM_TYPE); } else { strcpy(SmartcardExtension->VendorAttr.IfdType.Buffer,SC_IFD_TYPE); } SmartcardExtension->VendorAttr.IfdType.Length = strlen(SmartcardExtension->VendorAttr.IfdType.Buffer); /*------------------------------------------------------------------------------ Vendor Attributes (continue): - the UnitNo information. Is set to the device number. - the IFD serial number (is set to a NULL string). - the IFD version is set. ------------------------------------------------------------------------------*/ SmartcardExtension->VendorAttr.UnitNo = DeviceNumber; SmartcardExtension->VendorAttr.IfdSerialNo.Length = 0; SmartcardExtension->VendorAttr.IfdVersion.VersionMajor = (UCHAR)majorVersion; SmartcardExtension->VendorAttr.IfdVersion.VersionMinor = (UCHAR)minorVersion; SmartcardExtension->VendorAttr.IfdVersion.BuildNumber = 0; /*------------------------------------------------------------------------------ Reader Extension: - the Handle of the reader. - the IFD number of the reader. - the ICCType (ISOCARD). - the ICCVpp (HOR3GLL_DEFAULT_VPP). - the ICCPresence. - the command timeout for the reader (HOR3GLL_DEFAULT_TIME). - the IFD baud rate. - the power timeout (0). - the selected VCC power supply voltage value. - the PTS negotiate mode. - the parameter PTS0. - the parameter PTS1. - the parameter PTS2. - the parameter PTS3. ------------------------------------------------------------------------------*/ SmartcardExtension->ReaderExtension->Handle = handle; SmartcardExtension->ReaderExtension->IFDNumber = IFDNumber; SmartcardExtension->ReaderExtension->ICCType = ISOCARD; SmartcardExtension->ReaderExtension->ICCVpp = HOR3GLL_DEFAULT_VPP; SmartcardExtension->ReaderExtension->APDUTimeOut = HOR3GLL_DEFAULT_TIME * 24; SmartcardExtension->ReaderExtension->CmdTimeOut = HOR3GLL_DEFAULT_TIME; SmartcardExtension->ReaderExtension->IFDBaudRate = br; SmartcardExtension->ReaderExtension->PowerTimeOut = ICC_DEFAULT_POWER_TIMOUT; SmartcardExtension->ReaderExtension->ICCVcc = ICC_VCC_5V; SmartcardExtension->ReaderExtension->PTSMode = IFD_DEFAULT_MODE; SmartcardExtension->ReaderExtension->PTS0 = 0; SmartcardExtension->ReaderExtension->PTS1 = 0; SmartcardExtension->ReaderExtension->PTS2 = 0; SmartcardExtension->ReaderExtension->PTS3 = 0; SmartcardExtension->ReaderExtension->ICCPresence = HOR3GLL_DEFAULT_PRESENCE; /*------------------------------------------------------------------------------ Define the type of the card (ISOCARD) and set the card presence ------------------------------------------------------------------------------*/ rlen = HOR3GLL_BUFFER_SIZE; response = G_Oros3IccDefineType( handle, HOR3GLL_LOW_TIME, ISOCARD, HOR3GLL_DEFAULT_VPP, SmartcardExtension->ReaderExtension->ICCPresence, &rlen, rbuff ); /*------------------------------------------------------------------------------ Verify the response of the reader ------------------------------------------------------------------------------*/ if (response == G_OK) { response = GE_Translate(rbuff[0]); } if (response != G_OK) { G_Oros3CloseComm(handle); return(GDDK_Translate(response,(const ULONG) NULL)); } /*------------------------------------------------------------------------------ Update the status of the card (only for the main reader). If a card is inserted: Set the detection on the remove of the card. else Set the detection on the insertion of the card. ------------------------------------------------------------------------------*/ if (IFDNumber == 0) { GDDK_09UpdateCardStatus(SmartcardExtension); } else { /*------------------------------------------------------------------------------ <= Security Module is powered up. The function status and the IFD status are tested. ------------------------------------------------------------------------------*/ rlen = HOR3GLL_BUFFER_SIZE; response = G_Oros3IccPowerUp( SmartcardExtension->ReaderExtension->Handle, HOR3GLL_LOW_TIME, SmartcardExtension->ReaderExtension->ICCVcc, SmartcardExtension->ReaderExtension->PTSMode, SmartcardExtension->ReaderExtension->PTS0, SmartcardExtension->ReaderExtension->PTS1, SmartcardExtension->ReaderExtension->PTS2, SmartcardExtension->ReaderExtension->PTS3, &rlen, rbuff ); // Verify the response of the reader if (response >= G_OK) { response = GE_Translate(rbuff[0]); } if (response < G_OK) { // The card is absent SmartcardExtension->ReaderCapabilities.CurrentState = SCARD_ABSENT; SmartcardExtension->CardCapabilities.Protocol.Selected = SCARD_PROTOCOL_UNDEFINED; SmartcardExtension->CardCapabilities.ATR.Length = 0; } else { // The card is present for use but not powered SmartcardExtension->ReaderCapabilities.CurrentState = SCARD_SWALLOWED; SmartcardExtension->CardCapabilities.Protocol.Selected = SCARD_PROTOCOL_UNDEFINED; SmartcardExtension->CardCapabilities.ATR.Length = 0; // Security module is powered off. rlen = HOR3GLL_BUFFER_SIZE; response = G_Oros3IccPowerDown( SmartcardExtension->ReaderExtension->Handle, HOR3GLL_LOW_TIME, &rlen, rbuff ); } } return(GDDK_Translate(G_OK,(const ULONG) NULL)); } /******************************************************************************* * NTSTATUS GDDK_09CloseChannel * ( * PSMARTCARD_EXTENSION SmartcardExtension * ) * Description : * ------------- * This routine close a conection previously opened with a reader. * * Remarks : * ------------- * Nothing. * * In : * ------------- * - SmartcardExtension is a pointer on the SmartCardExtension structure of * the current device. * * Out : * ------------- * - SmartcardExtension is updated. * * Responses : * ------------- * If everything is Ok: * STATUS_SUCCESS *******************************************************************************/ NTSTATUS GDDK_09CloseChannel ( PSMARTCARD_EXTENSION SmartcardExtension ) { /*------------------------------------------------------------------------------ Local variables: - response holds the called function responses. ------------------------------------------------------------------------------*/ INT16 response; READER_EXTENSION *param = SmartcardExtension->ReaderExtension; WORD16 rlen; BYTE rbuff[HOR3GLL_BUFFER_SIZE]; /*------------------------------------------------------------------------------ Call power down function: ------------------------------------------------------------------------------*/ rlen = HOR3GLL_BUFFER_SIZE; response = G_Oros3IccPowerDown( param->Handle, HOR3GLL_LOW_TIME, &rlen, rbuff ); /*------------------------------------------------------------------------------ <= G_Oros3CloseComm status. ------------------------------------------------------------------------------*/ return (GDDK_Translate(G_Oros3CloseComm(param->Handle),(const ULONG) NULL)); } /******************************************************************************* * NTSTATUS GDDK_09OpenSession * ( * PSMARTCARD_EXTENSION SmartcardExtension * ) * Description : * ------------- * Opens a cold session with the selected ICC type. * A power off is made on ICC before the call to power up function. * For the ISO card, during the power up this function negotiates with the * ICC speed and protocole in accordance with PTS mode and sets the ICC power * supply voltage. * The session structure is updated with values found in ATR. * * Remarks : * ------------- * - The security module in OROS 3.x IFD only support the sames cards that main * reader interface (ISO card T=0, T=1 and Synchronous card). * - To change PTS mode and parameters used the function G4_09ICCSetPTS. * - To change ICC power supply voltage used the function G4_09ICCSetVoltage. * - For a specific card not supported by the OROS system, you must have * in the GEMPLUS_LIB_PATH directory, or the current directory, the Card driver * for this card. * For example ICCDRV04.ORO for the GPM416 (0x04) card. * GEMPLUS_LIB_PATH is an environnement variable used to defined the directory * where the Card drivers are located. * WARNING: * - The full path name of the card driver is case sensitive in UNIX target. * - The card driver name is in upper case. * * In : * ------------- * - SmartcardExtension is a pointer on the SmartCardExtension structure of * the current device. * * Out : * ------------- * - SmartcardExtension is updated. * - Status of the SCMLIB library. * * Responses : * ------------- * If everything is Ok: * G_OK *******************************************************************************/ NTSTATUS GDDK_09OpenSession ( PSMARTCARD_EXTENSION SmartcardExtension ) { /*------------------------------------------------------------------------------ Local variables: - response holds the called function responses. - ifd_type is used for ICC/SM management. - offset, l and k are used to glance through the ATR. - i is a counter. - protocol memorises the ICC protocol. It is initialized to 0 for T=0 default protocol. - protocol_set is used to detect the first protocol byte. It is initialized to FALSE because the first protocol byte has not been encountered. - end_time is used to wait for ICC to be really powered off. - icc_type holds the ICC type translated in OROS value. ------------------------------------------------------------------------------*/ INT16 response, ifd_type, icc_supported, offset, l; WORD8 k; WORD16 protocol = 0, card_driver_version, card_driver_protocol, icc_type; BOOL protocol_set = FALSE; WORD32 end_time; READER_EXTENSION *param = SmartcardExtension->ReaderExtension; NTSTATUS status; WORD16 rlen; BYTE rbuff[HOR3GLL_BUFFER_SIZE]; KEVENT event; LARGE_INTEGER timeout; /*--------------------------------------------------------------------------------- Get the ICC type ---------------------------------------------------------------------------------*/ icc_type = param->ICCType; /*------------------------------------------------------------------------------ <= ICC type is defined. The function status and the IFD status are tested. ------------------------------------------------------------------------------*/ rlen = HOR3GLL_BUFFER_SIZE; response = G_Oros3IccDefineType( param->Handle, HOR3GLL_LOW_TIME, icc_type, param->ICCVpp, param->ICCPresence, &rlen, rbuff ); if (response >= G_OK) { response = GE_Translate(rbuff[0]); } if (response < G_OK) { return (GDDK_Translate(response,RDF_CARD_POWER)); } /*------------------------------------------------------------------------------ ICC is powered Down (G_Oros3IccPowerDown). <= The function status and the IFD status are tested. ------------------------------------------------------------------------------*/ rlen = HOR3GLL_BUFFER_SIZE; response = G_Oros3IccPowerDown( param->Handle, HOR3GLL_LOW_TIME, &rlen, rbuff ); if (response >= G_OK) { response = GE_Translate(rbuff[0]); } if (response < G_OK) { return (GDDK_Translate(response,RDF_CARD_POWER)); } /*------------------------------------------------------------------------------ Waits for the Power Timeout to be elapsed. ------------------------------------------------------------------------------*/ KeInitializeEvent(&event,NotificationEvent,FALSE); timeout.QuadPart = -((LONGLONG) param->PowerTimeOut * 10 * 1000); status = KeWaitForSingleObject(&event, Suspended, KernelMode, FALSE, &timeout); /*------------------------------------------------------------------------------ ICC is powered up (G_Oros3IccPowerUp). <= The function status and the IFD status are tested. ------------------------------------------------------------------------------*/ rlen = HOR3GLL_BUFFER_SIZE; response = G_Oros3IccPowerUp( param->Handle, param->CmdTimeOut, param->ICCVcc, param->PTSMode, param->PTS0, param->PTS1, param->PTS2, param->PTS3, &rlen, rbuff ); if (response >= G_OK) { response = GE_Translate(rbuff[0]); } if (response < G_OK) { return (GDDK_Translate(response,RDF_CARD_POWER)); } /*------------------------------------------------------------------------------ Copy ATR to smart card struct (remove the reader status byte) The lib needs the ATR for evaluation of the card parameters ------------------------------------------------------------------------------*/ ASSERT(SmartcardExtension->SmartcardReply.BufferSize >= (ULONG) (rlen - 1)); memcpy( SmartcardExtension->SmartcardReply.Buffer, rbuff + 1, rlen - 1 ); SmartcardExtension->SmartcardReply.BufferLength = (ULONG) (rlen - 1); ASSERT(sizeof(SmartcardExtension->CardCapabilities.ATR.Buffer) >= (UCHAR) SmartcardExtension->SmartcardReply.BufferLength); memcpy( SmartcardExtension->CardCapabilities.ATR.Buffer, SmartcardExtension->SmartcardReply.Buffer, SmartcardExtension->SmartcardReply.BufferLength ); SmartcardExtension->CardCapabilities.ATR.Length = (UCHAR) SmartcardExtension->SmartcardReply.BufferLength; SmartcardExtension->CardCapabilities.Protocol.Selected = SCARD_PROTOCOL_UNDEFINED; /*------------------------------------------------------------------------------ Parse the ATR string in order to check if it as valid and to find out if the card uses invers convention ------------------------------------------------------------------------------*/ status = SmartcardUpdateCardCapabilities(SmartcardExtension); if (status == STATUS_SUCCESS) { ASSERT(SmartcardExtension->IoRequest.ReplyBufferLength >= SmartcardExtension->SmartcardReply.BufferLength ); memcpy( SmartcardExtension->IoRequest.ReplyBuffer, SmartcardExtension->CardCapabilities.ATR.Buffer, SmartcardExtension->CardCapabilities.ATR.Length ); *SmartcardExtension->IoRequest.Information = SmartcardExtension->SmartcardReply.BufferLength; } /*------------------------------------------------------------------------------ <= Return the last received status. ------------------------------------------------------------------------------*/ return (status); } /******************************************************************************* * NTSTATUS GDDK_09SwitchSession * ( * PSMARTCARD_EXTENSION SmartcardExtension * ) * Description : * ------------- * Description : * ------------- * Opens a warm session with the selected ICC type. * Only a reset is sent to ICC. * For the ISO card, during the power up this function negotiates with the * ICC speed and protocole in accordance with PTS mode and sets the ICC power * supply voltage. * The session structure is updated with values found in ATR. * * Remarks : * ------------- * This command is possible only if a G4_09OpenSession has been called before and * if the ICC type is not changed. * For the ISO card today, we assumes that only T=0, T=1 or T=0/1 are supported. * So we memorised the first founded protocol which must be T=0 for bi-protocol * card according to ISO standard. * * In : * ------------- * - SmartcardExtension is a pointer on the SmartCardExtension structure of * the current device. * * Out : * ------------- * - SmartcardExtension is updated. * * Responses : * ------------- * If everything is Ok: * STATUS_SUCCESS *******************************************************************************/ NTSTATUS GDDK_09SwitchSession ( PSMARTCARD_EXTENSION SmartcardExtension ) { /*------------------------------------------------------------------------------ Local variables: - response holds the called function responses. - ifd_type is used for ICC/SM management. - icc_type holds the ICC type translated in OROS value. ------------------------------------------------------------------------------*/ INT16 response, ifd_type, icc_supported; WORD16 icc_type; BOOL protocol_set = FALSE; WORD32 end_time; READER_EXTENSION *param = SmartcardExtension->ReaderExtension; NTSTATUS status; WORD16 rlen; BYTE rbuff[HOR3GLL_BUFFER_SIZE]; /*--------------------------------------------------------------------------------- Get the ICC type ---------------------------------------------------------------------------------*/ icc_type = param->ICCType; /*------------------------------------------------------------------------------ <= ICC is powered up. The function status and the IFD status are tested. ------------------------------------------------------------------------------*/ rlen = HOR3GLL_BUFFER_SIZE; response = G_Oros3IccPowerUp( param->Handle, param->CmdTimeOut, param->ICCVcc, param->PTSMode, param->PTS0, param->PTS1, param->PTS2, param->PTS3, &rlen, rbuff ); if (response >= G_OK) { response = GE_Translate(rbuff[0]); } if (response < G_OK) { return (GDDK_Translate(response,RDF_CARD_POWER)); } /*------------------------------------------------------------------------------ Copy ATR to smart card struct (remove the reader status byte) The lib needs the ATR for evaluation of the card parameters ------------------------------------------------------------------------------*/ ASSERT(SmartcardExtension->SmartcardReply.BufferSize >= (ULONG) (rlen - 1)); memcpy( SmartcardExtension->SmartcardReply.Buffer, rbuff + 1, rlen - 1 ); SmartcardExtension->SmartcardReply.BufferLength = (ULONG) (rlen - 1); ASSERT(sizeof(SmartcardExtension->CardCapabilities.ATR.Buffer) >= (UCHAR) SmartcardExtension->SmartcardReply.BufferLength); memcpy( SmartcardExtension->CardCapabilities.ATR.Buffer, SmartcardExtension->SmartcardReply.Buffer, SmartcardExtension->SmartcardReply.BufferLength ); SmartcardExtension->CardCapabilities.ATR.Length = (UCHAR) SmartcardExtension->SmartcardReply.BufferLength; SmartcardExtension->CardCapabilities.Protocol.Selected = SCARD_PROTOCOL_UNDEFINED; /*------------------------------------------------------------------------------ Parse the ATR string in order to check if it as valid and to find out if the card uses invers convention ------------------------------------------------------------------------------*/ status = SmartcardUpdateCardCapabilities(SmartcardExtension); if (status == STATUS_SUCCESS) { ASSERT(SmartcardExtension->IoRequest.ReplyBufferLength >= SmartcardExtension->SmartcardReply.BufferLength ); memcpy( SmartcardExtension->IoRequest.ReplyBuffer, SmartcardExtension->CardCapabilities.ATR.Buffer, SmartcardExtension->CardCapabilities.ATR.Length ); *SmartcardExtension->IoRequest.Information = SmartcardExtension->SmartcardReply.BufferLength; } /*------------------------------------------------------------------------------ <= Return the last received status. ------------------------------------------------------------------------------*/ return (status); } /******************************************************************************* * NTSTATUS GDDK_09CloseSession * ( * PSMARTCARD_EXTENSION SmartcardExtension * ) * * Description : * ------------- * Closes a session and requests IFD to remove the power from ICC. * * Remarks : * ------------- * Nothing. * * In : * ------------- * - SmartcardExtension is a pointer on the SmartCardExtension structure of * the current device. * * Out : * ------------- * Nothing. * * Responses : * ------------- * If everything is Ok: * STATUS_SUCCESS *******************************************************************************/ NTSTATUS GDDK_09CloseSession ( PSMARTCARD_EXTENSION SmartcardExtension ) { /*------------------------------------------------------------------------------ Local variables: - response holds the called function responses. ------------------------------------------------------------------------------*/ INT16 response; READER_EXTENSION *param = SmartcardExtension->ReaderExtension; WORD16 rlen; BYTE rbuff[HOR3GLL_BUFFER_SIZE]; /*------------------------------------------------------------------------------ If the dispatcher is used to send command and the command is found in the ORO file. Then Send the command Icc Power Down with the micro-code via the dispatcher. Else ICC is powered Down (G_Oros3IccPowerDown). <= The function status and the IFD status are tested. ------------------------------------------------------------------------------*/ rlen = HOR3GLL_BUFFER_SIZE; response = G_Oros3IccPowerDown( param->Handle, HOR3GLL_LOW_TIME, &rlen, rbuff ); if (response >= G_OK) { response = GE_Translate(rbuff[0]); } /*------------------------------------------------------------------------------ Updates card status for ICC or reset Protocol and ATR for Security Module. ------------------------------------------------------------------------------*/ if (param->IFDNumber > 0) { SmartcardExtension->CardCapabilities.ATR.Length = 0; SmartcardExtension->CardCapabilities.Protocol.Selected = SCARD_PROTOCOL_UNDEFINED; } else { GDDK_09UpdateCardStatus(SmartcardExtension); } /*------------------------------------------------------------------------------ <= Returns the last status. ------------------------------------------------------------------------------*/ return(GDDK_Translate(response,RDF_CARD_POWER)); } /******************************************************************************* * void GDDK_09UpdateCardStatus * ( * PSMARTCARD_EXTENSION pSmartcardExtension * ) * * Description : * ------------- * This function send a command to the reader to known the state of the card. * Available only for the main reader. * * Remarks : * ------------- * Nothing. * * In : * ------------- * - pSmartcardExtension is a pointer on the SmartCardExtension structure of * the current device. * * Out : * ------------- * - pSmartcardExtension is updated. * * Responses : * ------------- * NTSTATUS *******************************************************************************/ void GDDK_09UpdateCardStatus ( PSMARTCARD_EXTENSION pSmartcardExtension ) { INT16 response; WORD8 cmd[1]; READER_EXTENSION *param = pSmartcardExtension->ReaderExtension; WORD16 rlen; BYTE rbuff[HOR3GLL_BUFFER_SIZE]; /*------------------------------------------------------------------------------ On an OROS 3.x reader we can know the status only on the main IFD ------------------------------------------------------------------------------*/ if (param->IFDNumber == 0) { /*------------------------------------------------------------------------------ Read the status of the reader ------------------------------------------------------------------------------*/ cmd[0] = HOR3GLL_IFD_CMD_ICC_STATUS; rlen = HOR3GLL_BUFFER_SIZE; response = G_Oros3Exchange( param->Handle, HOR3GLL_LOW_TIME, (const WORD16)1, (const BYTE *)cmd, &rlen, rbuff ); /*------------------------------------------------------------------------------ Verify the response of the reader ------------------------------------------------------------------------------*/ if (response >= G_OK) { response = GE_Translate(rbuff[0]); } if (response < G_OK) { return; } if ((rbuff[1] & 0x04) == 0) { /*------------------------------------------------------------------------------ The card is absent ------------------------------------------------------------------------------*/ pSmartcardExtension->ReaderCapabilities.CurrentState = SCARD_ABSENT; pSmartcardExtension->CardCapabilities.Protocol.Selected = SCARD_PROTOCOL_UNDEFINED; pSmartcardExtension->CardCapabilities.ATR.Length = 0; } else if ((rbuff[1] & 0x02) == 0) { /*------------------------------------------------------------------------------ The card is present ------------------------------------------------------------------------------*/ pSmartcardExtension->ReaderCapabilities.CurrentState = SCARD_SWALLOWED; pSmartcardExtension->CardCapabilities.Protocol.Selected = SCARD_PROTOCOL_UNDEFINED; pSmartcardExtension->CardCapabilities.ATR.Length = 0; } } } /******************************************************************************* * static NTSTATUS GDDK_09IFDExchange * ( * PSMARTCARD_EXTENSION SmartcardExtension, * ULONG BufferInLen, * BYTE *BufferIn, * ULONG BufferOutLen, * BYTE *BufferOut, * ULONG *LengthOut *) * * Description : * ------------- * This is the system entry point to send a command to the IFD. * The device-specific handler is invoked to perform any validation * necessary. The number of bytes in the request are checked against * the maximum byte counts that the reader supports. * * Remarks : * ------------- * Nothing. * * In : * ------------- * - SmartcardExtension is a pointer on the SmartCardExtension structure of * the current device. * * Out : * ------------- * Nothing. * * Responses : * ------------- * NTSTATUS *******************************************************************************/ static NTSTATUS GDDK_09IFDExchange ( PSMARTCARD_EXTENSION SmartcardExtension, ULONG BufferInLen, BYTE *BufferIn, ULONG BufferOutLen, BYTE *BufferOut, ULONG *LengthOut ) { INT16 response; NTSTATUS status; READER_EXTENSION *param = SmartcardExtension->ReaderExtension; WORD16 rlen; BYTE rbuff[HOR3GLL_BUFFER_SIZE]; *LengthOut = 0; /*------------------------------------------------------------------------------ Send the command to the reader ------------------------------------------------------------------------------*/ rlen = (USHORT) BufferOutLen; response = G_Oros3Exchange( param->Handle, HOR3GLL_LOW_TIME, (USHORT)BufferInLen, (BYTE *)BufferIn, &rlen, rbuff ); /*------------------------------------------------------------------------------ If the response <> G_OK <== G_DDKTranslate(response) ------------------------------------------------------------------------------*/ if (response != G_OK) { return(GDDK_Translate(response,RDF_IOCTL_VENDOR)); } /*------------------------------------------------------------------------------ Copy the response of the reader in the reply buffer ------------------------------------------------------------------------------*/ ASSERT(*LengthOut >= (ULONG)rlen); memcpy(BufferOut,rbuff,rlen); *(LengthOut) = (ULONG)rlen; return(GDDK_Translate(response,RDF_IOCTL_VENDOR)); } /******************************************************************************* * void GDDK_09LockExchange * ( * PSMARTCARD_EXTENSION SmartcardExtension *) * * Description : * ------------- * Wait the release of the ExchangeMutex and take this. * * Remarks : * ------------- * Nothing. * * In : * ------------- * - SmartcardExtension is a pointer on the SmartCardExtension structure of * the current device. * * Out : * ------------- * Nothing. * * Responses : * ------------- * Nothing *******************************************************************************/ void GDDK_09LockExchange ( PSMARTCARD_EXTENSION SmartcardExtension ) { KeWaitForMutexObject( &SmartcardExtension->ReaderExtension->LongAPDUMutex, Executive, KernelMode, FALSE, NULL ); } /******************************************************************************* * void GDDK_09UnlockExchange * ( * PSMARTCARD_EXTENSION SmartcardExtension *) * * Description : * ------------- * Release of the Exchange mutex. * * Remarks : * ------------- * Nothing. * * In : * ------------- * - SmartcardExtension is a pointer on the SmartCardExtension structure of * the current device. * * Out : * ------------- * Nothing. * * Responses : * ------------- * Nothing *******************************************************************************/ void GDDK_09UnlockExchange ( PSMARTCARD_EXTENSION SmartcardExtension ) { KeReleaseMutex( &SmartcardExtension->ReaderExtension->LongAPDUMutex, FALSE ); }