You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
312 lines
7.5 KiB
312 lines
7.5 KiB
/*++
|
|
|
|
Copyright (C) Microsoft Corporation 1999
|
|
|
|
Module Name:
|
|
|
|
Proto_T0
|
|
|
|
Abstract:
|
|
|
|
This module provides the mapping from an APDU to a T=0 TPDU.
|
|
|
|
Author:
|
|
|
|
Doug Barlow (dbarlow) 6/28/1999
|
|
|
|
Notes:
|
|
|
|
?Notes?
|
|
|
|
--*/
|
|
|
|
#ifndef WIN32_LEAN_AND_MEAN
|
|
#define WIN32_LEAN_AND_MEAN
|
|
#endif
|
|
|
|
#include "stdafx.h"
|
|
#include "Conversion.h"
|
|
|
|
|
|
/*++
|
|
|
|
ApduToTpdu_T0:
|
|
|
|
This routine takes an APDU, converts it to a T=0 TPDU, and performs the
|
|
exchange to the specified card.
|
|
|
|
Arguments:
|
|
|
|
hCard supplies a handle to the card to be used in the exchange.
|
|
|
|
pbPciRqst supplies the PCI Request structure
|
|
|
|
cbPciRqst supplies the length of pbPciRqst, in bytes
|
|
|
|
pbApdu supplies the APDU to be sent to the card.
|
|
|
|
cbApdu supplies the length of the APDU in pbApdu.
|
|
|
|
dwFlags supplies any special flags used to modify the operation.
|
|
|
|
bfPciRsp receives the response PCI.
|
|
|
|
bfReply receives the response from the card.
|
|
|
|
Return Value:
|
|
|
|
None
|
|
|
|
Throws:
|
|
|
|
Errors are thrown as HRESULT status codes.
|
|
|
|
Remarks:
|
|
|
|
?Remarks?
|
|
|
|
Author:
|
|
|
|
Doug Barlow (dbarlow) 6/28/1999
|
|
|
|
--*/
|
|
#undef __SUBROUTINE__
|
|
#define __SUBROUTINE__ TEXT("ApduToTpdu_T0")
|
|
|
|
void
|
|
ApduToTpdu_T0(
|
|
IN SCARDHANDLE hCard,
|
|
IN const SCARD_IO_REQUEST *pPciRqst,
|
|
IN LPCBYTE pbApdu,
|
|
IN DWORD cbApdu,
|
|
IN DWORD dwFlags,
|
|
OUT CBuffer bfPciRsp,
|
|
OUT CBuffer &bfReply,
|
|
IN LPCBYTE pbAltCla)
|
|
{
|
|
LONG lSts;
|
|
DWORD dwLen, dwXmitFlags;
|
|
WORD wLen, wLc, wLe, wSts;
|
|
CBuffer bfXmit(264), bfRecv(264);
|
|
BYTE rgb[4];
|
|
BYTE b;
|
|
LPCBYTE pbData;
|
|
|
|
|
|
//
|
|
// Prepare for conversion.
|
|
//
|
|
|
|
bfReply.Reset();
|
|
bfPciRsp.Set((LPCBYTE)pPciRqst, pPciRqst->cbPciLength);
|
|
ParseRequest(
|
|
pbApdu,
|
|
cbApdu,
|
|
NULL,
|
|
NULL,
|
|
NULL,
|
|
NULL,
|
|
&pbData,
|
|
&wLc,
|
|
&wLe,
|
|
&dwXmitFlags);
|
|
|
|
|
|
//
|
|
// Send the data.
|
|
//
|
|
|
|
if (0 == wLc)
|
|
{
|
|
|
|
//
|
|
// Le goes into P3
|
|
//
|
|
|
|
bfXmit.Set(pbApdu, 4); // CLA, INS, P1, P2
|
|
if (0 == (dwXmitFlags & APDU_MAXIMUM_LE))
|
|
wLen = __min(255, wLe);
|
|
else
|
|
wLen = 0;
|
|
b = LeastSignificantByte(wLen);
|
|
bfXmit.Append(&b, 1);
|
|
|
|
dwLen = bfRecv.Space();
|
|
lSts = SCardTransmit(
|
|
hCard,
|
|
pPciRqst,
|
|
bfXmit.Access(),
|
|
bfXmit.Length(),
|
|
(LPSCARD_IO_REQUEST)bfPciRsp.Access(),
|
|
bfRecv.Access(),
|
|
&dwLen);
|
|
if (SCARD_S_SUCCESS != lSts)
|
|
throw (HRESULT)HRESULT_FROM_WIN32(lSts);
|
|
bfRecv.Resize(dwLen, TRUE);
|
|
if (2 > dwLen)
|
|
{
|
|
bfReply.Set(bfRecv.Access(), bfRecv.Length());
|
|
goto EndProtocol;
|
|
}
|
|
ASSERT(0x10000 > dwLen);
|
|
wLe -= (WORD)(dwLen - 2);
|
|
wSts = NetToLocal(bfRecv.Access(dwLen - 2));
|
|
}
|
|
else if (256 > wLc)
|
|
{
|
|
|
|
//
|
|
// Send the data in the short form.
|
|
//
|
|
|
|
bfXmit.Set(pbApdu, 4); // CLA, INS, P1, P2
|
|
b = LeastSignificantByte(wLc);
|
|
bfXmit.Append(&b, 1);
|
|
bfXmit.Append(pbData, wLc);
|
|
|
|
dwLen = bfRecv.Space();
|
|
lSts = SCardTransmit(
|
|
hCard,
|
|
pPciRqst,
|
|
bfXmit.Access(),
|
|
bfXmit.Length(),
|
|
(LPSCARD_IO_REQUEST)bfPciRsp.Access(),
|
|
bfRecv.Access(),
|
|
&dwLen);
|
|
if (SCARD_S_SUCCESS != lSts)
|
|
throw (HRESULT)HRESULT_FROM_WIN32(lSts);
|
|
bfRecv.Resize(dwLen, TRUE);
|
|
if (2 > dwLen)
|
|
{
|
|
bfReply.Set(bfRecv.Access(), bfRecv.Length());
|
|
goto EndProtocol;
|
|
}
|
|
wSts = NetToLocal(bfRecv.Access(dwLen - 2));
|
|
}
|
|
else
|
|
{
|
|
WORD wSent;
|
|
|
|
|
|
//
|
|
// Send the data in the enveloped form.
|
|
//
|
|
|
|
rgb[0] = (NULL != pbAltCla) ? *pbAltCla : *pbApdu; // CLA
|
|
rgb[1] = 0xc2; // envelope INS
|
|
rgb[2] = 0; // P1
|
|
rgb[3] = 0; // P2
|
|
wSent = 0;
|
|
while (wLc > wSent)
|
|
{
|
|
wLen = __min(255, wLc - wSent);
|
|
bfXmit.Set(rgb, 4);
|
|
bfXmit.Append(&pbData[wSent], wLen);
|
|
b = LeastSignificantByte(wLen);
|
|
bfXmit.Append(&b, 1);
|
|
wSent -= wLen;
|
|
|
|
dwLen = bfRecv.Space();
|
|
lSts = SCardTransmit(
|
|
hCard,
|
|
pPciRqst,
|
|
bfXmit.Access(),
|
|
bfXmit.Length(),
|
|
(LPSCARD_IO_REQUEST)bfPciRsp.Access(),
|
|
bfRecv.Access(),
|
|
&dwLen);
|
|
if (SCARD_S_SUCCESS != lSts)
|
|
throw (HRESULT)HRESULT_FROM_WIN32(lSts);
|
|
bfRecv.Resize(dwLen, TRUE);
|
|
if (2 != dwLen)
|
|
{
|
|
bfReply.Set(bfRecv.Access(), bfRecv.Length());
|
|
goto EndProtocol;
|
|
}
|
|
wSts = NetToLocal(bfRecv.Access());
|
|
if ((wSent < wLc) && (0x9000 != wSts))
|
|
{
|
|
bfReply.Set(bfRecv.Access(), bfRecv.Length());
|
|
goto EndProtocol;
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
//
|
|
// At this point, the first received buffer is in bfRecv. What do we
|
|
// have to do to bring in any more data?
|
|
//
|
|
|
|
rgb[0] = (NULL != pbAltCla) ? *pbAltCla : *pbApdu; // CLA
|
|
rgb[1] = 0xc0; // Get Response INS
|
|
rgb[2] = 0; // P1
|
|
rgb[3] = 0; // P2
|
|
|
|
for (;;)
|
|
{
|
|
ASSERT(2 <= bfRecv.Length());
|
|
BYTE bSw1 = *bfRecv.Access(bfRecv.Length() - 2);
|
|
BYTE bSw2 = *bfRecv.Access(bfRecv.Length() - 1);
|
|
|
|
switch (bSw1)
|
|
{
|
|
case 0x6c: // Wrong length
|
|
wLe = bSw2;
|
|
break;
|
|
case 0x61: // More data
|
|
bfReply.Append(bfRecv.Access(), bfRecv.Length() - 2);
|
|
if (0 == wLe)
|
|
wLe = bSw2;
|
|
else
|
|
wLe = __min(wLe, bSw2);
|
|
break;
|
|
case 0x90: // Success?
|
|
if (((0 == wLe) && (0 == (APDU_MAXIMUM_LE & dwFlags)))
|
|
|| (0x00 != bSw2))
|
|
{
|
|
bfReply.Append(bfRecv.Access(), bfRecv.Length());
|
|
goto EndProtocol;
|
|
}
|
|
if (2 < bfRecv.Length()) // Shouldn't be
|
|
bfReply.Append(bfRecv.Access(), bfRecv.Length() - 2);
|
|
break;
|
|
default: // We're done.
|
|
bfReply.Append(bfRecv.Access(), bfRecv.Length());
|
|
goto EndProtocol;
|
|
}
|
|
|
|
|
|
//
|
|
// We need to request additional data.
|
|
//
|
|
|
|
bfXmit.Set(rgb, 4);
|
|
b = LeastSignificantByte(wLe);
|
|
bfXmit.Append(&b, 1);
|
|
dwLen = bfRecv.Space();
|
|
lSts = SCardTransmit(
|
|
hCard,
|
|
pPciRqst,
|
|
bfXmit.Access(),
|
|
bfXmit.Length(),
|
|
(LPSCARD_IO_REQUEST)bfPciRsp.Access(),
|
|
bfRecv.Access(),
|
|
&dwLen);
|
|
if (SCARD_S_SUCCESS != lSts)
|
|
throw (HRESULT)HRESULT_FROM_WIN32(lSts);
|
|
bfRecv.Resize(dwLen, TRUE);
|
|
wLe -= b;
|
|
}
|
|
|
|
|
|
EndProtocol:
|
|
|
|
//
|
|
// We've completed the protocol exchange. The data is ready to be
|
|
// returned to the caller.
|
|
//
|
|
|
|
return;
|
|
}
|
|
|