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

📄 smcprot.c

📁 ARM9基于WINDOWSCE的BSP源代码
💻 C
📖 第 1 页 / 共 4 页
字号:
//
// Copyright (c) Microsoft Corporation.  All rights reserved.
//
//
// Use of this source code is subject to the terms of the Microsoft end-user
// license agreement (EULA) under which you licensed this SOFTWARE PRODUCT.
// If you did not accept the terms of the EULA, you are not authorized to use
// this source code. For a copy of the EULA, please see the LICENSE.RTF on your
// install media.
//
/*++


Module Name:

    smcprot.c

Environment:

    Kernel mode only.


--*/

#ifdef SMCLIB_VXD

#define try 
#define leave goto __label
#define finally __label:

#else
#ifndef SMCLIB_CE
#include <stdarg.h>
#include <stdio.h>
#include <string.h>
#include <ntddk.h>
#endif
#endif

#include "smclib.h"
#define SMARTCARD_POOL_TAG 'bLCS'

void
DumpData(
    const ULONG DebugLevel,
    PUCHAR Data,
    ULONG DataLen
    );

//
// Usually an io-request consists only of the SCARD_IO_REQUEST header
// followed by the data to be transmitted. To allow modification of 
// protocol data, it is possible to pass down the data to be modified.
// These data are ASN1 encoded.
//
typedef struct _IO_HEADER {
    SCARD_IO_REQUEST ScardIoRequest;
    UCHAR Asn1Data[1];     	
} IO_HEADER, *PIO_HEADER;

NTSTATUS
#ifdef SMCLIB_VXD
SMCLIB_SmartcardRawRequest(
#else
SmartcardRawRequest(
#endif
    PSMARTCARD_EXTENSION SmartcardExtension
    )
    
/*++

Routine Description:

Arguments:

Return Value:

   -

--*/
{
    PSMARTCARD_REQUEST smartcardRequest = &(SmartcardExtension->SmartcardRequest);

	if (smartcardRequest->BufferLength + 
		SmartcardExtension->IoRequest.RequestBufferLength >=
		smartcardRequest->BufferSize) {

		return STATUS_BUFFER_TOO_SMALL;
	}
    
    //
    // Copy request data to the buffer
    //        
    RtlCopyMemory(
        &smartcardRequest->Buffer[smartcardRequest->BufferLength],
        SmartcardExtension->IoRequest.RequestBuffer,
        SmartcardExtension->IoRequest.RequestBufferLength
        );
        
	//
	// If the card uses invers convention invert the data
	// 
	if (SmartcardExtension->CardCapabilities.InversConvention) {

		SmartcardInvertData(
			&smartcardRequest->Buffer[smartcardRequest->BufferLength],
	        SmartcardExtension->IoRequest.RequestBufferLength
			);
	}

    //
    // number of bytes to send to the reader 
    //    
    smartcardRequest->BufferLength += 
        SmartcardExtension->IoRequest.RequestBufferLength;

	return STATUS_SUCCESS;
}    

NTSTATUS
#ifdef SMCLIB_VXD
SMCLIB_SmartcardRawReply(
#else
SmartcardRawReply(
#endif
    PSMARTCARD_EXTENSION SmartcardExtension
    )
    
/*++

Routine Description:

Arguments:

Return Value:

   -

--*/
{
    if (SmartcardExtension->IoRequest.ReplyBufferLength <
        SmartcardExtension->SmartcardReply.BufferLength) {
        
        return STATUS_BUFFER_TOO_SMALL;
    }
    
    //
    // Copy data to user buffer
    //
    RtlCopyMemory(
        SmartcardExtension->IoRequest.ReplyBuffer,
        SmartcardExtension->SmartcardReply.Buffer,
        SmartcardExtension->SmartcardReply.BufferLength
        );

    // 
    // Length of data to return
    //        
    *SmartcardExtension->IoRequest.Information = 
        SmartcardExtension->SmartcardReply.BufferLength;
              
    return STATUS_SUCCESS;
}   

NTSTATUS
#ifdef SMCLIB_VXD
SMCLIB_SmartcardT0Request(
#else
SmartcardT0Request(
#endif
    PSMARTCARD_EXTENSION SmartcardExtension
    )
    
/*++

Routine Description:

    Prepares the buffer SmartcardExtension->SmartcardRequest.Buffer 
    to send data to the smart card

Arguments:

    NOTE: On input SmartcardExtension->SmartcardRequest.BufferLenght indicates
          the offset where we should copy the data to. This is usually
          used by readers that needs to have some bytes as header bytes
          to send to the reader before the data bytes for the card

Return Value:

   -

--*/
{
    PSMARTCARD_REQUEST smartcardRequest = &SmartcardExtension->SmartcardRequest;
    PSCARD_IO_REQUEST scardIoRequest;
    PUCHAR ioRequestData;
    ULONG ioRequestDataLength, headerSize;
    
	if (smartcardRequest->BufferLength + 
		SmartcardExtension->IoRequest.RequestBufferLength >=
		smartcardRequest->BufferSize) {

        SmartcardDebug(
            DEBUG_ERROR,
            (TEXT("%s!SmartcardT0Request: IoRequest.RequestBuffer too big\n"),
            DRIVER_NAME)
            );

		return STATUS_BUFFER_OVERFLOW;
	}

    scardIoRequest = (PSCARD_IO_REQUEST) 
    	SmartcardExtension->IoRequest.RequestBuffer;

	ioRequestData = 
		SmartcardExtension->IoRequest.RequestBuffer + 
		sizeof(SCARD_IO_REQUEST);

	ioRequestDataLength = 
		SmartcardExtension->IoRequest.RequestBufferLength - 
		sizeof(SCARD_IO_REQUEST);

    //
    // Copy T=0 protocol-info into buffer
	//
	RtlCopyMemory(
        &smartcardRequest->Buffer[smartcardRequest->BufferLength],
		ioRequestData,
		ioRequestDataLength
		);
		
    //
    // Remember number of bytes for the header offset
    //
    headerSize = 
        smartcardRequest->BufferLength;

    //
    // Number of bytes to send to the reader 
    //    
    smartcardRequest->BufferLength += 
        ioRequestDataLength;

	if (ioRequestDataLength < 4) {

		//
		// A T=0 request needs at least 4 bytes
		//
        SmartcardDebug(
            DEBUG_ERROR,
            (TEXT("%s!SmartcardT0Request: TPDU is too short (%d). Must be at least 4 bytes\n"),
            DRIVER_NAME,
            ioRequestDataLength)
            );

		return STATUS_INVALID_PARAMETER;

	} else {

		PUCHAR requestBuffer = SmartcardExtension->SmartcardRequest.Buffer;

		if (ioRequestDataLength <= 5) {

            //
            // We request to read data from the card
            //
			SmartcardExtension->T0.Lc = 0;

            if (ioRequestDataLength == 4) {

                //
                // This is a special case where a 4 byte APDU is mapped to 
                // a 5 byte TPDU (ISO 7816 - Part 4, Annex A, A.1 Case 1)
                // This case requires that we append a 0 to the 
                // APDU to make it a TPDU
                //
                SmartcardExtension->T0.Le = 0;
             	smartcardRequest->Buffer[headerSize + 4] = 0;
                smartcardRequest->BufferLength += 1;

            } else {
             	
                SmartcardExtension->T0.Le = 
                    (requestBuffer[headerSize + 4] ? requestBuffer[headerSize + 4] : 256);
            }

		} else {
			
            //
            // We want to send data to the card
            //
			SmartcardExtension->T0.Lc = requestBuffer[headerSize + 4];
			SmartcardExtension->T0.Le = 0;

			if (SmartcardExtension->T0.Lc != ioRequestDataLength - 5) {

                SmartcardDebug(
                    DEBUG_ERROR,
                    (TEXT("%s!SmartcardT0Request: Lc(%d) in TPDU doesn't match number of bytes to send(%d).\n"),
                    DRIVER_NAME,
                    SmartcardExtension->T0.Lc,
                    ioRequestDataLength - 5)
                    );

				return STATUS_INVALID_PARAMETER;
			}
		}

#if DBG
        {
            PUCHAR T0Data = requestBuffer + headerSize;

	        SmartcardDebug(
		        DEBUG_PROTOCOL,
		        (TEXT(" CLA:  %02X\n INS:  %02X\n P1:   %02X\n P2:   %02X\n Lc:   %02X\n Le:   %02X\n"), 
		        T0Data[0], T0Data[1], T0Data[2], T0Data[3],
                SmartcardExtension->T0.Lc,
                SmartcardExtension->T0.Le)
		        );

            if (SmartcardExtension->T0.Lc) {

	            SmartcardDebug(
		            DEBUG_PROTOCOL,
		            (TEXT(" Data: ")), 
		            );

                DumpData(
                    DEBUG_PROTOCOL,
                    T0Data + 5, 
                    SmartcardExtension->T0.Lc
                    );
            }
        }
#endif 

	    //
	    // If the card uses invers convention invert the data
	    // 
	    if (SmartcardExtension->CardCapabilities.InversConvention) {

		    SmartcardInvertData(
			    &smartcardRequest->Buffer[headerSize], 
	            smartcardRequest->BufferLength - headerSize
			    );
	    }

		return STATUS_SUCCESS;

#ifdef APDU_SUPPORT
		ULONG requestLength = SmartcardExtension->SmartcardRequest.BufferLength;
		ULONG L;

		//
		// Figure out Lc and Le
		// (See 'Decoding of the command APDUs' in ISO Part 4, 5.3.2)
		// (Variable names used are according to ISO designations)
		//
		L = requestLength - 4;

		if (L > 65536) {

			return STATUS_INVALID_PARAMETER;
		}

		if (L == 0) {

			//
			// Lc = 0, No Data, Le = 0;
			//
			SmartcardExtension->T0.Lc = 0;
			SmartcardExtension->T0.Le = 0;

		} else if (L == 1) {
			
			//
			// Case 2S, Lc = 0, Le = B1
			//
			SmartcardExtension->T0.Lc = 0;
			SmartcardExtension->T0.Le = requestBuffer[4];

		} else {

			UCHAR B1 = requestBuffer[4];

		   	if (B1 != 0) {

				//
				// Short form
				//
				if (L == (ULONG) (1 + B1)) {

					//
					// Case 3S, Lc = B1, Le = 0
					//
					SmartcardExtension->T0.Lc = B1;
					SmartcardExtension->T0.Le = 0;

				} else {
					
					//
					// Case 4S, Lc = B1, Le = BL
					// 
					SmartcardExtension->T0.Lc = B1;
					SmartcardExtension->T0.Le = requestBuffer[L - 1];
				}

		   	} else {
		   		
				//
				// Extended form
				//
				if (L == 3) {

					//
					// Case 2E, Lc = 0, 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.Lc = 0;
					SmartcardExtension->T0.Le = (length.l.l0 ? length.l.l0 : 65536);

				} else {

					LENGTH length;
					
					length.l.l0 = 0;
					length.b.b0 = requestBuffer[6];
					length.b.b1 = requestBuffer[5];

					SmartcardExtension->T0.Lc = length.l.l0;

					if (L == 3 + length.l.l0) {

						//
						// Case 3E, Lc = B(2,3)
						//
					    SmartcardExtension->T0.Le = 0;

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -