📄 parseatr.cpp
字号:
//adapt from wince driver smcutil.c
#include "stdafx.h"
#include "parseATR.h"
static ULONG
Pow2(
UCHAR Exponent
)
{
ULONG result = 1;
while(Exponent--)
result *= 2;
return result;
}
VOID
SmartcardInvertData(
PUCHAR Buffer,
ULONG Length
)
{
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);
}
}
CString parseATR(
PUCHAR atrString, ULONG atrLength,PSCARD_CARD_CAPABILITIES cardCapabilities ,ULONG fs
)
{
UCHAR Y, Tck, TA[MAXIMUM_ATR_CODES], TB[MAXIMUM_ATR_CODES];
UCHAR TC[MAXIMUM_ATR_CODES], TD[MAXIMUM_ATR_CODES];
ULONG i,numProtocols = 0, protocolTypes = 0;
BOOLEAN TA2Present = FALSE;
if (atrLength < 2)
return _T("ATR is too short (Min. length is 2)");
if (atrString[0] != 0x3b && atrString[0] != 0x3f && atrString[0] != 0x03)
return _T("Initial character of ATR is invalid");
// 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
);
TRACE(_T("Card uses Inverse Convention\n"));
}
//
// 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;
memset(TA,0, sizeof(TA));
memset(TB,0, sizeof(TB));
memset(TC,0, sizeof(TC));
memset(TD,0, 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)
return _T("ATR Checksum is invalid");
}
if (atrLength < 0 ||
atrLength != cardCapabilities->HistoricalChars.Length) {
return _T("ATR length is inconsistent");
}
// store historical characters
memcpy(
cardCapabilities->HistoricalChars.Buffer,
atrString,
cardCapabilities->HistoricalChars.Length
);
//
// Now convert TA - TD values to global interface bytes
//
// Clock rate conversion
cardCapabilities->Fl = (TA[0] & 0xf0) >> 4;
// bit rate adjustment
cardCapabilities->Dl = (TA[0] & 0x0f);
// Maximum programming current factor
cardCapabilities->II = (TB[0] & 0xc0) >> 6;
// Programming voltage in 0.1 Volts
cardCapabilities->P = (TB[1] ? TB[1] : (TB[0] & 0x1f) * 10);
// Extra guard time
cardCapabilities->N = TC[0];
//
// Check if the Dl and Fl values are valid
//
if (BitRateAdjustment[cardCapabilities->Dl].DNumerator == 0 ||
ClockRateConversion[cardCapabilities->Fl].F == 0) {
return _T("Dl or Fl invalid");
}
TRACE(
_T("Card parameters from ATR:\n Fl = %02x (%ld KHz), Dl = %02x, I = %02x, P = %02x, N = %02x\n"),
cardCapabilities->Fl,
ClockRateConversion[cardCapabilities->Fl].fs / 1000,
cardCapabilities->Dl,
cardCapabilities->II,
cardCapabilities->P,
cardCapabilities->N
);
//
// assume default clock frequency
//
if (fs == 0)
fs = 372 * 9600l;
cardCapabilities->PtsData.Fl = cardCapabilities->Fl;
cardCapabilities->PtsData.Dl = cardCapabilities->Dl;
//
// We calculate the ETU on basis of the timing supplied by the
// clk-frequency of the reader
//
//
// Work etu in units of time resolution(TR) (NOT in seconds)
//
cardCapabilities->etu =
1 + // required to round up
(TR *
BitRateAdjustment[cardCapabilities->Dl].DDivisor *
ClockRateConversion[cardCapabilities->Fl].F) /
(BitRateAdjustment[cardCapabilities->Dl].DNumerator *
fs);
//
// guard time in micro seconds
// the guard time is the gap between the end of the
// current character and the beginning of the next character
//
cardCapabilities->GT = 0;
if (cardCapabilities->N == 0)
cardCapabilities->PtsData.StopBits = 2;
else if (cardCapabilities->N == 255)
cardCapabilities->PtsData.StopBits = 1;
else
cardCapabilities->GT = cardCapabilities->N * cardCapabilities->etu;
TRACE(
_T("Calculated timing values:\n Work etu = %ld micro sec, Guard time = %ld micro sec\n"),
cardCapabilities->etu,
cardCapabilities->GT);
//
// Now find protocol specific data
//
if (TD[0] == 0) {
cardCapabilities->Protocol.Supported |=
SCARD_PROTOCOL_T0;
cardCapabilities->T0.WI = TC[1];
if (cardCapabilities->PtsData.Dl > 0 &&
cardCapabilities->PtsData.Dl < 6) {
cardCapabilities->T0.WT = 1 +
cardCapabilities->T0.WI *
960 * cardCapabilities->etu *
Pow2((UCHAR) (cardCapabilities->PtsData.Dl - 1));
} else {
cardCapabilities->T0.WT = 1+
cardCapabilities->T0.WI *
960 * cardCapabilities->etu /
Pow2((UCHAR) (cardCapabilities->PtsData.Dl - 1));
}
TRACE(
_T("T=0 Values from ATR:\n WI = %ld\n"),
cardCapabilities->T0.WI
);
TRACE(
_T("T=0 Timing from ATR:\n WT = %ld ms\n"),
cardCapabilities->T0.WT / 1000
);
}
if (protocolTypes & SCARD_PROTOCOL_T1) {
for (i = 0; TD[i] != 1 && i < MAXIMUM_ATR_CODES; i++)
;
for (; TD[i] == 1 && i < MAXIMUM_ATR_CODES; i++)
;
if (i == MAXIMUM_ATR_CODES) {
return _T("Parse T1 error");
}
cardCapabilities->Protocol.Supported |=
SCARD_PROTOCOL_T1;
cardCapabilities->T1.IFSC =
(TA[i] ? TA[i] : 32);
cardCapabilities->T1.CWI =
((TB[i] & 0x0f) ? (TB[i] & 0x0f) : T1_CWI_DEFAULT);
cardCapabilities->T1.BWI =
((TB[i] & 0xf0) >> 4 ? (TB[i] & 0xf0) >> 4 : T1_BWI_DEFAULT);
cardCapabilities->T1.EDC =
(TC[i] & 0x01);
cardCapabilities->T1.CWT = 1 +
(Pow2(cardCapabilities->T1.CWI) + 11) * cardCapabilities->etu;
cardCapabilities->T1.BWT = 1 +
((Pow2(cardCapabilities->T1.BWI) * TR) / 10) +
11 * cardCapabilities->etu;
TRACE(
_T(" T=1 Values from ATR:\n IFSC = %ld, CWI = %ld, BWI = %ld, EDC = %02x\n"),
cardCapabilities->T1.IFSC,
cardCapabilities->T1.CWI,
cardCapabilities->T1.BWI,
cardCapabilities->T1.EDC
);
TRACE(
_T(" T=1 Timing from ATR:\n CWT = %ld ms, BWT = %ld ms\n"),
cardCapabilities->T1.CWT / 1000,
cardCapabilities->T1.BWT / 1000
);
}
return _T("");
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -