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

📄 smcutil.c

📁 ARM9基于WINDOWSCE的BSP源代码
💻 C
📖 第 1 页 / 共 2 页
字号:
//
// 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:

    smcutil.c

Abstract:

    This module contains some utility functions

Environment:

    Kernel mode only.

Notes:

--*/

#define _ISO_TABLES_
#ifdef SMCLIB_VXD

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

#else
#if !defined(SMCLIB_CE)

#include <stdarg.h>
#include <stdio.h>
#include <string.h>
#include <ntddk.h>

#endif
#endif

#define _SMCUTIL_
#include "smclib.h"

#define IS_VENDOR(a) (memcmp(SmartcardExtension->VendorAttr.VendorName.Buffer, a, SmartcardExtension->VendorAttr.VendorName.Length) == 0)
#define IS_IFDTYPE(a) (memcmp(SmartcardExtension->VendorAttr.IfdType.Buffer, a, SmartcardExtension->VendorAttr.IfdType.Length) == 0)

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

//
// This is the time resolution.
// We calculate all times not in seconds, but in micro seconds
//
#define TR ((ULONG)(1000l * 1000l))

static ULONG 
Pow2(
	UCHAR Exponent
	)
{
	ULONG result = 1;

	while(Exponent--)
		result *= 2;

	return result;
}	

#ifdef _X86_ 
#pragma optimize("", off) 
#endif 

#if (DBG && DEBUG_VERBOSE) || (DEBUG && DEBUG_VERBOSE)
#pragma message("Debug Verbose is turned on")
ULONG DebugLevel = DEBUG_ALL;
#else
ULONG DebugLevel;
#endif

ULONG
#ifdef SMCLIB_VXD
SMCLIB_SmartcardGetDebugLevel(
#else
SmartcardGetDebugLevel(
#endif
	void
	)
{
	return DebugLevel;
}	

void
#ifdef SMCLIB_VXD
SMCLIB_SmartcardSetDebugLevel(
#else
SmartcardSetDebugLevel(
#endif
	ULONG Level
	)
{
	DebugLevel = Level;
}	

#ifdef _X86_ 
#pragma optimize("", on) 
#endif 

#if DBG || DEBUG
void
DumpData(
    const ULONG DebugLevel,
    PUCHAR Data,
    ULONG DataLen
    )
{
    ULONG i;

	for (i = 0; i < DataLen; i++) {

		SmartcardDebug(
			DebugLevel,
            (TEXT("%02X%c"), 
            Data[i], 
            ((i + 1)  % 8 == 0 ? '\n' : ' '))
			);
	} 	

    if (i % 8 != 0) {
     	
	    SmartcardDebug(
		    DebugLevel,
		    (TEXT("\n"))
		    );
    }
}
#endif

VOID
SmartcardInitializeCardCapabilities(
    PSMARTCARD_EXTENSION SmartcardExtension
    )
/*++

Routine Description:

    This routine initializes all fields in the CardCapabilities structure,
    which can be calculated by the SmartcardUpdateCardCapabilities function.
    
Arguments:

    SmartcardExtension 

Return Value:

    None

--*/
{
    //
    // Save the pointers to the two tables
    //
   	PCLOCK_RATE_CONVERSION ClockRateConversion = SmartcardExtension->CardCapabilities.ClockRateConversion;
	PBIT_RATE_ADJUSTMENT BitRateAdjustment = SmartcardExtension->CardCapabilities.BitRateAdjustment;

	//
	// Right now it is fine to zero the whole struct
	//
	RtlZeroMemory(
		&SmartcardExtension->CardCapabilities,
		sizeof(SmartcardExtension->CardCapabilities)
		);

    // Restore the pointers
    SmartcardExtension->CardCapabilities.ClockRateConversion = ClockRateConversion;
	SmartcardExtension->CardCapabilities.BitRateAdjustment = BitRateAdjustment;

    //
    // Every card has to support the 'raw' protocol
    // It enables the usage of cards that have their own protocol defined
    //
    SmartcardExtension->CardCapabilities.Protocol.Supported = 
        SCARD_PROTOCOL_RAW;

	//
	// Reset T=1 specific data
	//

    // force the T=1 protocol to start with an ifsd request
	SmartcardExtension->T1.State = T1_INIT;

    //
    // Initialize the send sequence number and 
    // the 'receive sequence number'
    //
	SmartcardExtension->T1.SSN = 0;
	SmartcardExtension->T1.RSN = 0;

   ASSERT(SmartcardExtension->ReaderCapabilities.MaxIFSD != 0);

    // Initialize the interface information field size
    if (SmartcardExtension->ReaderCapabilities.MaxIFSD != 0 &&
        SmartcardExtension->ReaderCapabilities.MaxIFSD < T1_IFSD) {
     	
        SmartcardExtension->T1.IFSD = 
            (UCHAR) SmartcardExtension->ReaderCapabilities.MaxIFSD;

    } else {
     	
        SmartcardExtension->T1.IFSD = T1_IFSD;
    }
}	

VOID
SmartcardInvertData(
	PUCHAR Buffer,
	ULONG Length
    )
/*++

Routine Description:

    This routine converts the passed buffer from inverse to direct or the other way

Arguments:


Return Value:

    None

--*/

{
	ULONG i;

	for (i = 0; i < Length; i++) {

		UCHAR j, inv = 0;

		for (j = 0; j < 8; j++) {

			if (Buffer[i] & (1 << j)) {

				inv |= 1 << (7 - j);
			}
		}
		Buffer[i] = (inv ^ 0xFF);
	}
}

NTSTATUS
#ifdef SMCLIB_VXD
SMCLIB_SmartcardUpdateCardCapabilities(
#else
SmartcardUpdateCardCapabilities(
#endif
    PSMARTCARD_EXTENSION SmartcardExtension
    )
/*++

Routine Description:

    This routine updates the CardCapabilities structure, which holds information about
    the smartcard that has just been reset and is currently in use. It reads the 
    ATR string and retrieves all the relevent information.

    Please refer to ISO 7816-3 ,section 6.1.4 for the format of the ATR string
    
Arguments:

    SmartcardExtension 

Return Value:

    NTSTATUS

--*/
{
	PSCARD_CARD_CAPABILITIES cardCapabilities = &SmartcardExtension->CardCapabilities;
    PSCARD_READER_CAPABILITIES readerCapabilities = &SmartcardExtension->ReaderCapabilities;
	PUCHAR atrString = cardCapabilities->ATR.Buffer;
	ULONG atrLength = (ULONG) cardCapabilities->ATR.Length;
	UCHAR Y, Tck, TA[MAXIMUM_ATR_CODES], TB[MAXIMUM_ATR_CODES];
	UCHAR TC[MAXIMUM_ATR_CODES], TD[MAXIMUM_ATR_CODES];
	ULONG i, fs, numProtocols = 0, protocolTypes = 0;
    NTSTATUS status = STATUS_SUCCESS;
    BOOLEAN TA2Present = FALSE;
#if DBG || DEBUG
    TCHAR *ptsType[] = {TEXT("PTS_TYPE_DEFAULT"), TEXT("PTS_TYPE_OPTIMAL"), TEXT("PTS_TYPE_USER")};
#endif

    SmartcardDebug(
        DEBUG_ATR,
        (TEXT("%s!SmartcardUpdateCardCapabilities:\n"),
        DRIVER_NAME)
        );

    if (atrLength < 2) {
     	
        SmartcardDebug(
            DEBUG_ATR,
            (TEXT("   ATR is too short (Min. length is 2) \n"))
            );
        return STATUS_UNRECOGNIZED_MEDIA;
    }

#if DBG || DEBUG

    SmartcardDebug(
        DEBUG_ATR,
        (TEXT("   ATR: "))
        );

    DumpData(
        DEBUG_ATR,
        atrString,
        atrLength
        );
#endif

	if (atrString[0] != 0x3b && atrString[0] != 0x3f && atrString[0] != 0x03) {

        SmartcardDebug(
            DEBUG_ATR,
            (TEXT("   Initial character %02xh of ATR is invalid\n"),
            atrString[0])
            );

        return STATUS_UNRECOGNIZED_MEDIA;
	}

	// Test for invers convention
	if (*atrString == 0x03) {

		cardCapabilities->InversConvention = TRUE;

        //
        // When the ATR starts with 0x03 then it 
        // has not been inverted already         	
        //
    	SmartcardInvertData(
            cardCapabilities->ATR.Buffer, 
            cardCapabilities->ATR.Length
            );             	

        SmartcardDebug(
            DEBUG_ATR,
            (TEXT("   Card uses Inverse Convention\n"))
            );
	} 

    try {

        //
        // The caller might be calling this function repeatedly in order to 
        // test if the ATR is valid. If the ATR we currently have here is
        // not valid then we need to be able re-invert an inverted ATR.
        //

	    atrString += 1;
	    atrLength -= 1;

	    //
	    // Calculate check char, but do not test now since if only T=0 
	    // is present the ATR doesn't contain a check char
	    //
	    for (i = 0, Tck = 0; i < atrLength; i++) {

		    Tck ^= atrString[i];
	    }

	    // Initialize various data
	    cardCapabilities->Protocol.Supported = 0;

	    RtlZeroMemory(TA, sizeof(TA));
	    RtlZeroMemory(TB, sizeof(TB));
	    RtlZeroMemory(TC, sizeof(TC));
	    RtlZeroMemory(TD, sizeof(TD));

        //
	    // Set default values as described in ISO 7816-3
        //
    
        // TA1 codes Fl in high-byte and Dl in low-byte;
	    TA[0] = 0x11;
        // TB1 codes II in bits b7/b6 and Pl1 in b5-b1. b8 has to be 0
	    TB[0] = 0x25;
        // TC2 codes T=0 WI
        TC[1] = 10;

	    // Translate ATR string to TA to TD values (See ISO)
	    cardCapabilities->HistoricalChars.Length = *atrString & 0x0f;

	    Y = *atrString++ & 0xf0;
	    atrLength -= 1;

	    for (i = 0; i < MAXIMUM_ATR_CODES; i++) {

		    if (Y & 0x10) {

                if (i == 1) {

                    TA2Present = TRUE;              	
                }

			    TA[i] = *atrString++;
        	    atrLength -= 1;
		    }

		    if (Y & 0x20) {

			    TB[i] = *atrString++;
        	    atrLength -= 1;
		    }

		    if (Y & 0x40) {

			    TC[i] = *atrString++;
        	    atrLength -= 1;
		    }

		    if (Y & 0x80) {

			    Y = *atrString & 0xf0;
			    TD[i] = *atrString++ & 0x0f;
        	    atrLength -= 1;

			    // Check if the next parameters are for a new protocol.
			    if (((1 << TD[i]) & protocolTypes) == 0) {

				    // Count the number of protocols that the card supports
				    numProtocols++;
			    }
			    protocolTypes |= 1 << TD[i];

		    } else {
			    
			    break;
		    }
	    } 

        // Check if the card supports a protocol other than T=0
        if (protocolTypes & ~1) {

            //
            // The atr contains a checksum byte.
            // Exclude that from the historical byte length check
            //
            atrLength -=1;     	

		    //
		    // This card supports more than one protocol or a protocol 
		    // other than T=0, so test if the checksum is correct
		    //
		    if (Tck != 0) {

                SmartcardDebug(
                    DEBUG_ATR,
                    (TEXT("   ATR Checksum is invalid\n"))
                    );

	            status = STATUS_UNRECOGNIZED_MEDIA;
                leave;
		    }
        }

        if (atrLength < 0 ||
            atrLength != cardCapabilities->HistoricalChars.Length) {
     	    
            SmartcardDebug(
                DEBUG_ATR,
                (TEXT("   ATR length is inconsistent\n"))
                );

⌨️ 快捷键说明

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