mirror of https://github.com/tongzx/nt5src
You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
2383 lines
79 KiB
2383 lines
79 KiB
/*******************************************************************************
|
|
* 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 <ntddk.h>
|
|
#include <ntddser.h>
|
|
/*------------------------------------------------------------------------------
|
|
- smclib.h: smart card library definitions.
|
|
------------------------------------------------------------------------------*/
|
|
#define SMARTCARD_POOL_TAG 'cGCS'
|
|
#include <smclib.h>
|
|
|
|
/*------------------------------------------------------------------------------
|
|
- 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
|
|
);
|
|
}
|