⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 smcprot.c

📁 ARM9基于WINDOWSCE的BSP源代码
💻 C
📖 第 1 页 / 共 4 页
字号:

					} 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 + -