📄 smcprot.c
字号:
} else {
//
// Case 4E, Lc = B(2,3), Le = B(L - 1, L)
//
LENGTH length;
length.l.l0 = 0;
length.b.b0 = requestBuffer[L - 1];
length.b.b1 = requestBuffer[L - 2];
SmartcardExtension->T0.Le = (length.l.l0 ? length.l.l0 : 65536);
}
}
}
}
#endif
}
return STATUS_SUCCESS;
}
NTSTATUS
#ifdef SMCLIB_VXD
SMCLIB_SmartcardT0Reply(
#else
SmartcardT0Reply(
#endif
PSMARTCARD_EXTENSION SmartcardExtension
)
/*++
Routine Description:
Arguments:
Return Value:
-
--*/
{
PSMARTCARD_REPLY smartcardReply = &SmartcardExtension->SmartcardReply;
//
// The reply must be at least to 2 bytes long. These 2 bytes are
// the return value (StatusWord) from the smart card
//
if (smartcardReply->BufferLength < 2) {
return STATUS_DEVICE_PROTOCOL_ERROR;
}
if (SmartcardExtension->IoRequest.ReplyBufferLength <
smartcardReply->BufferLength + sizeof(SCARD_IO_REQUEST)) {
SmartcardDebug(
DEBUG_ERROR,
(TEXT("%s!SmartcardT0Request: ReplyBuffer too small\n"),
DRIVER_NAME)
);
return STATUS_BUFFER_TOO_SMALL;
}
// Copy protocol header to user buffer
RtlCopyMemory(
SmartcardExtension->IoRequest.ReplyBuffer,
SmartcardExtension->IoRequest.RequestBuffer,
sizeof(SCARD_IO_REQUEST)
);
// If the card uses invers convention invert the data
if (SmartcardExtension->CardCapabilities.InversConvention) {
SmartcardInvertData(
smartcardReply->Buffer,
smartcardReply->BufferLength
);
}
// Copy all data to user buffer
RtlCopyMemory(
SmartcardExtension->IoRequest.ReplyBuffer + sizeof(SCARD_IO_REQUEST),
smartcardReply->Buffer,
smartcardReply->BufferLength
);
// Length of answer
*SmartcardExtension->IoRequest.Information =
smartcardReply->BufferLength +
sizeof(SCARD_IO_REQUEST);
return STATUS_SUCCESS;
}
BOOLEAN
SmartcardT1Chksum(
PUCHAR Block,
UCHAR Edc,
BOOLEAN Verify
)
/*++
Routine Description:
This routine calculates the epilogue field for a T1 block. It calculates the LRC
for all the data in the IBlock.
Arguments:
Block - T1 Information block, to be sent, or just read, from the card.
Edc - ErrorDetectionCode as described in ISO
Verify - If this is a block that was recieved form the card, TRUE will cause this routine
to check the epilogue field, included with this buffer, against the calculated one
Return Value:
TRUE if Verify = TRUE and epilogue fields match or Verify = FALSE
FALSE if Verify = TRUE and an error was detected (mismatch)
--*/
{
BOOLEAN fRet = TRUE;
USHORT i;
UCHAR lrc;
USHORT crc = 0;
UCHAR offset = Block[2] + SCARD_T1_PROLOGUE_LENGTH;
unsigned short crc16a[] = {
0000000, 0140301, 0140601, 0000500,
0141401, 0001700, 0001200, 0141101,
0143001, 0003300, 0003600, 0143501,
0002400, 0142701, 0142201, 0002100,
};
unsigned short crc16b[] = {
0000000, 0146001, 0154001, 0012000,
0170001, 0036000, 0024000, 0162001,
0120001, 0066000, 0074000, 0132001,
0050000, 0116001, 0104001, 0043000,
};
if (Edc & T1_CRC_CHECK) {
UCHAR tmp;
// Calculate CRC using tables.
for ( i = 0; i < offset; i++) {
tmp = Block[i] ^ (UCHAR) crc;
crc = (crc >> 8) ^ crc16a[tmp & 0x0f] ^ crc16b[tmp >> 4];
}
if (Verify) {
if (crc == (Block[offset + 1] | (Block[offset] << 8))) {
return TRUE;
} else {
return FALSE;
}
} else {
Block[offset] = (UCHAR) (crc >> 8 ); //MSB of crc
Block[offset + 1] = (UCHAR) (crc & 0x00ff); //LSB of crc
}
} else {
// Calculate LRC by X-Oring all the bytes.
lrc = Block[0];
for(i = 1; i < offset; i++){
lrc ^= Block[i];
}
if (Verify) {
return (lrc == Block[offset] ? TRUE : FALSE);
} else {
Block[offset] = lrc;
}
}
return fRet;
}
#if (DBG || DEBUG)
static
void
DumpT1Block(
PUCHAR Buffer,
UCHAR Edc
)
{
SmartcardDebug(
DEBUG_PROTOCOL,
(TEXT(" NAD: %02X\n PCB: %02X\n LEN: %02X\n INF: "),
Buffer[0], Buffer[1], Buffer[2])
);
if (Buffer[2] == 0) {
SmartcardDebug(
DEBUG_PROTOCOL,
(TEXT("- "))
);
}
DumpData(
DEBUG_PROTOCOL,
Buffer + 3,
Buffer[2]
);
if (Edc & T1_CRC_CHECK) {
SmartcardDebug(
DEBUG_PROTOCOL,
(TEXT("\n CRC: %02X %02X"),
Buffer[Buffer[2] + 3],
Buffer[Buffer[2] + 4])
);
} else {
SmartcardDebug(
DEBUG_PROTOCOL,
(TEXT("\n LRC: %02X"),
Buffer[Buffer[2] + 3])
);
}
SmartcardDebug(
DEBUG_PROTOCOL,
(TEXT("\n"))
);
}
#endif
#if DBG
#pragma optimize( "", off )
#endif
NTSTATUS
#ifdef SMCLIB_VXD
SMCLIB_SmartcardT1Request(
#else
SmartcardT1Request(
#endif
PSMARTCARD_EXTENSION SmartcardExtension
)
/*++
Routine Description:
Arguments:
SmartcardExtension - Supplies a pointer to the smart card data
Return Value:
--*/
{
PSMARTCARD_REQUEST smartcardRequest = &(SmartcardExtension->SmartcardRequest);
PIO_HEADER IoHeader = (PIO_HEADER) SmartcardExtension->IoRequest.RequestBuffer;
T1_BLOCK_FRAME t1SendFrame;
#if (DBG || DEBUG)
ULONG headerSize = smartcardRequest->BufferLength;
#endif
if (SmartcardExtension->T1.WaitForReply) {
// we did not get an answer to our last request
SmartcardExtension->T1.State = T1_INIT;
}
SmartcardExtension->T1.WaitForReply = TRUE;
switch (SmartcardExtension->T1.State) {
case T1_INIT:
SmartcardExtension->T1.State = T1_IFS_REQUEST;
// NO break here !!!
case T1_START:
//
// Since this is the very first block in a
// transmission we reset the resynch counter
//
SmartcardExtension->T1.Resynch = 0;
//
// Allocate a buffer that receives the result.
// This is necessary since we otherwise overwite our
// request data which we might wish to resend in case
// of an error
//
if (SmartcardExtension->T1.ReplyData != NULL) {
#ifdef SMCLIB_VXD
_HeapFree(SmartcardExtension->T1.ReplyData, 0);
#elif defined(SMCLIB_CE)
LocalFree(SmartcardExtension->T1.ReplyData);
#else
ExFreePool(SmartcardExtension->T1.ReplyData);
#endif
SmartcardExtension->T1.ReplyData = NULL;
}
if (SmartcardExtension->IoRequest.ReplyBufferLength <
IoHeader->ScardIoRequest.cbPciLength + 2) {
//
// We should at least be able to store
// the io-header plus SW1 and SW2
//
return STATUS_BUFFER_TOO_SMALL;
}
#ifdef SMCLIB_VXD
SmartcardExtension->T1.ReplyData = (PUCHAR) _HeapAllocate(
SmartcardExtension->IoRequest.ReplyBufferLength,
0
);
#elif defined(SMCLIB_CE)
SmartcardExtension->T1.ReplyData = (PUCHAR) LocalAlloc(LPTR,
SmartcardExtension->IoRequest.ReplyBufferLength
);
#else
SmartcardExtension->T1.ReplyData = ExAllocatePool(
NonPagedPool,
SmartcardExtension->IoRequest.ReplyBufferLength
);
#endif
ASSERT(SmartcardExtension->T1.ReplyData != NULL);
if (SmartcardExtension->T1.ReplyData == NULL) {
return STATUS_INSUFFICIENT_RESOURCES;
}
// No break here !!!
case T1_RESTART:
SmartcardDebug(
DEBUG_PROTOCOL,
(TEXT("%s!SmartcardT1Request: T1_%s\n"),
DRIVER_NAME,
(SmartcardExtension->T1.State == T1_START ? TEXT("START") : TEXT("RESTART")))
);
// Copy protocol header back to user buffer
RtlCopyMemory(
SmartcardExtension->T1.ReplyData,
SmartcardExtension->IoRequest.RequestBuffer,
IoHeader->ScardIoRequest.cbPciLength
);
//
// Check for the special case where the io-header is followed
// by asn1 data that contains the NAD value to be used.
// The NAD is ASN1 encoded as 81h 00h NAD 00h
//
if (IoHeader->ScardIoRequest.cbPciLength > sizeof(SCARD_IO_REQUEST) &&
IoHeader->Asn1Data[0] == 0x81 &&
IoHeader->Asn1Data[1] == 0x01 &&
IoHeader->Asn1Data[3] == 0x00) {
SmartcardExtension->T1.NAD = IoHeader->Asn1Data[2];
SmartcardDebug(
DEBUG_PROTOCOL,
(TEXT("%s!SmartcardT1Request: NAD set to %02xh\n"),
DRIVER_NAME,
SmartcardExtension->T1.NAD)
);
}
// Initialize the T1 protocol data
SmartcardExtension->T1.BytesToSend =
SmartcardExtension->IoRequest.RequestBufferLength -
IoHeader->ScardIoRequest.cbPciLength;
SmartcardExtension->T1.BytesSent = 0;
SmartcardExtension->T1.BytesReceived = 0;
//
// This is the maximum number of bytes that the smartcard can
// accept in a single block. The smartcard can extend this size
// during the transmission
//
SmartcardExtension->T1.IFSC =
SmartcardExtension->CardCapabilities.T1.IFSC;
//
// Since this is the first block in a transmission we reset
// the re-transmission counter.
//
SmartcardExtension->T1.Resend = 0;
SmartcardExtension->T1.OriginalState = 0;
SmartcardExtension->T1.MoreData = FALSE;
//
// NO break here !!!
//
// After a card reset we first send an IFS-Request to the card.
// Otherwise we start with an I-Block
//
case T1_IFS_REQUEST:
if (SmartcardExtension->T1.State == T1_IFS_REQUEST) {
SmartcardDebug(
DEBUG_PROTOCOL,
(TEXT("%s!SmartcardT1Request: T1_IFS_REQUEST\n"),
DRIVER_NAME)
);
SmartcardExtension->T1.State =
T1_IFS_REQUEST;
t1SendFrame.Nad = SmartcardExtension->T1.NAD;
//
// IFS request.
// Send our IFSD size to the card
//
t1SendFrame.Pcb = 0xC1;
t1SendFrame.Len = 1;
t1SendFrame.Inf = &SmartcardExtension->T1.IFSD;
break;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -