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.
1975 lines
58 KiB
1975 lines
58 KiB
/*++
|
|
|
|
Copyright (C) Microsoft Corporation, 1999 - 1999
|
|
|
|
Module Name:
|
|
|
|
ISO7816
|
|
|
|
Abstract:
|
|
|
|
The ISCardISO7816 interface provides methods for implementing ISO 7816-4
|
|
functionality. With the exception of ISCardISO7816::SetDefaultClassId,
|
|
these methods create an APDU command that is encapsulated in a ISCardCmd
|
|
object.
|
|
|
|
The ISO 7816-4 specification defines standard commands available on smart
|
|
cards. The specification also defines how a smart card Application
|
|
Protocol Data Unit (APDU) command should be constructed and sent to the
|
|
smart card for execution. This interface automates the building process.
|
|
|
|
The following example shows a typical use of the ISCardISO7816 interface.
|
|
In this case, the ISCardISO7816 interface is used to build an APDU command.
|
|
|
|
To submit a transaction to a specific card
|
|
|
|
1) Create an ISCardISO7816 and ISCardCmd interface. The ISCardCmd
|
|
interface is used to encapsulate the APDU.
|
|
2) Call the appropriate method of the ISCardISO7816 interface, passing the
|
|
required parameters and the ISCardCmd interface pointer.
|
|
3) The ISO 7816-4 APDU command will be built and encapsulated in the
|
|
ISCardCmd interface.
|
|
4) Release the ISCardISO7816 and ISCardCmd interfaces.
|
|
|
|
Note
|
|
|
|
In the method reference pages, if a bit sequence in a table is not defined,
|
|
assume that bit sequence is reserved for future use or proprietary to a
|
|
specific vendor).
|
|
|
|
Author:
|
|
|
|
Doug Barlow (dbarlow) 6/24/1999
|
|
|
|
Notes:
|
|
|
|
?Notes?
|
|
|
|
--*/
|
|
|
|
#ifndef WIN32_LEAN_AND_MEAN
|
|
#define WIN32_LEAN_AND_MEAN
|
|
#endif
|
|
|
|
#include "stdafx.h"
|
|
#include "ISO7816.h"
|
|
|
|
/////////////////////////////////////////////////////////////////////////////
|
|
// CSCardISO7816
|
|
|
|
|
|
/*++
|
|
|
|
CSCardISO7816::AppendRecord:
|
|
|
|
The AppendRecord method constructs an APDU command that either appends a
|
|
record to the end of a linear-structured elementary file (EF) or writes
|
|
record number 1 in an cyclic-structured elementary file.
|
|
|
|
Arguments:
|
|
|
|
byRefCtrl [in, defaultvalue(NULL_BYTE)] Identifies the elementary file to
|
|
be appended:
|
|
|
|
Meaning 8 7 6 5 4 3 2 1
|
|
Current EF 0 0 0 0 0 0 0 0
|
|
Short EF ID x x x x x 0 0 0
|
|
Reserved x x x x x x x x
|
|
|
|
pData [in] Pointer to the data to be appended to the file:
|
|
|
|
Tn (1 byte)
|
|
Ln (1 or 3 bytes)
|
|
data (Ln bytes)
|
|
|
|
ppCmd [in, out] On input, a pointer to an ISCardCmd interface object or
|
|
NULL. On return, it is filled with the APDU command constructed by
|
|
this operation. If ppCmd was set to NULL, a smart card ISCardCmd
|
|
object is internally created and returned via the ppCmd pointer.
|
|
|
|
Return Value:
|
|
|
|
The return value is an HRESULT. A value of S_OK indicates the call was
|
|
successful.
|
|
|
|
Remarks:
|
|
|
|
The encapsulated command can only be performed if the security status of
|
|
the smart card satisfies the security attributes of the elementary file
|
|
read.
|
|
|
|
If another elementary file is selected at the time of issuing this command,
|
|
it may be processed without identification of the currently selected file.
|
|
|
|
Elementary files without a record structure cannot be read. The
|
|
encapsulated command aborts if applied to an elementary file without a
|
|
record structure.
|
|
|
|
Author:
|
|
|
|
Doug Barlow (dbarlow) 6/24/1999
|
|
|
|
--*/
|
|
#undef __SUBROUTINE__
|
|
#define __SUBROUTINE__ TEXT("CSCardISO7816::AppendRecord")
|
|
|
|
STDMETHODIMP
|
|
CSCardISO7816::AppendRecord(
|
|
/* [in] */ BYTE byRefCtrl,
|
|
/* [in] */ LPBYTEBUFFER pData,
|
|
/* [out][in] */ LPSCARDCMD __RPC_FAR *ppCmd)
|
|
{
|
|
HRESULT hReturn;
|
|
|
|
try
|
|
{
|
|
HRESULT hr;
|
|
|
|
if (NULL == *ppCmd)
|
|
{
|
|
*ppCmd = NewSCardCmd();
|
|
if (NULL == *ppCmd)
|
|
throw (HRESULT)E_OUTOFMEMORY;
|
|
}
|
|
|
|
hr = (*ppCmd)->BuildCmd(
|
|
m_bCla, // CLA
|
|
0xe2, // INS
|
|
0, // P1
|
|
byRefCtrl, // P2
|
|
pData,
|
|
NULL);
|
|
hReturn = hr;
|
|
}
|
|
|
|
catch (HRESULT hError)
|
|
{
|
|
hReturn = hError;
|
|
}
|
|
catch (...)
|
|
{
|
|
hReturn = E_INVALIDARG;
|
|
}
|
|
|
|
return hReturn;
|
|
}
|
|
|
|
|
|
/*++
|
|
|
|
CSCardISO7816::EraseBinary:
|
|
|
|
The EraseBinary method constructs an APDU command that sequentially sets
|
|
part of the content of an elementary file to its logical erased state,
|
|
starting from a given offset.
|
|
|
|
Arguments:
|
|
|
|
byP1, byP2 [in] RFU position.
|
|
|
|
If… Then…
|
|
b8=1 in P1 b7 and b6 of P1 are set to 0 (RFU bits), b5 to b1 of P1 are
|
|
a short EF identifier and P2 is the offset of the first
|
|
byte to be erased (in data units) from the beginning of the
|
|
file.
|
|
b8=0 in P1 then P1 || P2 is the offset of the first byte to be erased
|
|
(in data units) from the beginning of the file.
|
|
|
|
If the data field is present, it codes the offset of the first data
|
|
unit not to be erased. This offset shall be higher than the one coded
|
|
in P1-P2. When the data field is empty, the command erases up to the
|
|
end of the file.
|
|
|
|
pData [in, defaultvalue(NULL)] Pointer to the data that specifies the erase
|
|
range; may be NULL.
|
|
|
|
ppCmd [in, out] On input, a pointer to an ISCardCmd interface object or
|
|
NULL. On return, it is filled with the APDU command constructed by
|
|
this operation. If ppCmd was set to NULL, a smart card ISCardCmd
|
|
object is internally created and returned via the ppCmd pointer.
|
|
|
|
Return Value:
|
|
|
|
The return value is an HRESULT. A value of S_OK indicates the call was
|
|
successful.
|
|
|
|
Remarks:
|
|
|
|
The encapsulated command can only be performed if the security status of
|
|
the smart card satisfies the security attributes of the elementary file
|
|
being processed.
|
|
|
|
When the command contains a valid short elementary identifier, it sets the
|
|
file as current elementary file.
|
|
|
|
Elementary files without a transparent structure cannot be erased. The
|
|
encapsulated command aborts if applied to an elementary file without a
|
|
transparent structure.
|
|
|
|
Author:
|
|
|
|
Doug Barlow (dbarlow) 6/24/1999
|
|
|
|
--*/
|
|
#undef __SUBROUTINE__
|
|
#define __SUBROUTINE__ TEXT("CSCardISO7816::EraseBinary")
|
|
|
|
STDMETHODIMP
|
|
CSCardISO7816::EraseBinary(
|
|
/* [in] */ BYTE byP1,
|
|
/* [in] */ BYTE byP2,
|
|
/* [in] */ LPBYTEBUFFER pData,
|
|
/* [out][in] */ LPSCARDCMD __RPC_FAR *ppCmd)
|
|
{
|
|
HRESULT hReturn;
|
|
|
|
try
|
|
{
|
|
HRESULT hr;
|
|
|
|
if (NULL == *ppCmd)
|
|
{
|
|
*ppCmd = NewSCardCmd();
|
|
if (NULL == *ppCmd)
|
|
throw (HRESULT)E_OUTOFMEMORY;
|
|
}
|
|
|
|
hr = (*ppCmd)->BuildCmd(
|
|
m_bCla, // CLA
|
|
0x0e, // INS
|
|
byP1, // P1
|
|
byP2, // P2
|
|
pData,
|
|
NULL);
|
|
hReturn = hr;
|
|
}
|
|
|
|
catch (HRESULT hError)
|
|
{
|
|
hReturn = hError;
|
|
}
|
|
catch (...)
|
|
{
|
|
hReturn = E_INVALIDARG;
|
|
}
|
|
|
|
return hReturn;
|
|
}
|
|
|
|
|
|
/*++
|
|
|
|
CSCardISO7816::ExternalAuthenticate:
|
|
|
|
The ExternalAuthenticate method constructs an APDU command that
|
|
conditionally updates security status, verifying the identity of the
|
|
computer when the smart card does not trust it.
|
|
|
|
The command uses the result (yes or no) of the computation by the card
|
|
(based on a challenge previously issued by the card — for example, by the
|
|
INS_GET_CHALLENGE command), a key (possibly secret) stored in the card, and
|
|
authentication data transmitted by the interface device.
|
|
|
|
Arguments:
|
|
|
|
byAlgorithmRef [in, defaultvalue(NULL_BYTE)] Reference of the algorithm in
|
|
the card. If this value is zero, this indicates that no information is
|
|
given. The reference of the algorithm is known either before issuing
|
|
the command or is provided in the data field.
|
|
|
|
bySecretRef [in, defaultvalue(NULL_BYTE)] Reference of the secret:
|
|
|
|
Meaning 8 7 6 5 4 3 2 1
|
|
No Info 0 0 0 0 0 0 0 0
|
|
Global ref 0 - - - - - - -
|
|
Specific ref 1 - - - - - - -
|
|
RFU - x x - - - - -
|
|
Secret - - - x x x x x
|
|
|
|
No Info = No information is given. The reference of the secret is known
|
|
either before issuing the command or is provided in the data field.
|
|
|
|
Global ref = Global reference data (an MF specific key).
|
|
|
|
Specific ref = Specific reference data (a DF specific key).
|
|
|
|
RFU = 00 (other values are RFU).
|
|
|
|
Secret = Number of the secret.
|
|
|
|
pChallenge [in, defaultvalue(NULL)] Pointer to the authentication-related
|
|
data; may be NULL.
|
|
|
|
ppCmd [in, out] On input, a pointer to an ISCardCmd interface object or
|
|
NULL. On return, it is filled with the APDU command constructed by
|
|
this operation. If ppCmd was set to NULL, a smart card ISCardCmd
|
|
object is internally created and returned via the ppCmd pointer.
|
|
|
|
Return Value:
|
|
|
|
The return value is an HRESULT. A value of S_OK indicates the call was
|
|
successful.
|
|
|
|
Remarks:
|
|
|
|
For the encapsulated command to be successful, the last challenge obtained
|
|
from the card must be valid.
|
|
|
|
Unsuccessful comparisons may be recorded in the card (for example, to limit
|
|
the number of further attempts of the use of the reference data).
|
|
|
|
Author:
|
|
|
|
Doug Barlow (dbarlow) 6/24/1999
|
|
|
|
--*/
|
|
#undef __SUBROUTINE__
|
|
#define __SUBROUTINE__ TEXT("CSCardISO7816::ExternalAuthenticate")
|
|
|
|
STDMETHODIMP
|
|
CSCardISO7816::ExternalAuthenticate(
|
|
/* [in] */ BYTE byAlgorithmRef,
|
|
/* [in] */ BYTE bySecretRef,
|
|
/* [in] */ LPBYTEBUFFER pChallenge,
|
|
/* [out][in] */ LPSCARDCMD __RPC_FAR *ppCmd)
|
|
{
|
|
HRESULT hReturn;
|
|
|
|
try
|
|
{
|
|
HRESULT hr;
|
|
|
|
if (NULL == *ppCmd)
|
|
{
|
|
*ppCmd = NewSCardCmd();
|
|
if (NULL == *ppCmd)
|
|
throw (HRESULT)E_OUTOFMEMORY;
|
|
}
|
|
|
|
hr = (*ppCmd)->BuildCmd(
|
|
m_bCla, // CLA
|
|
0x82, // INS
|
|
byAlgorithmRef, // P1
|
|
bySecretRef, // P2
|
|
pChallenge, // data
|
|
NULL);
|
|
hReturn = hr;
|
|
}
|
|
|
|
catch (HRESULT hError)
|
|
{
|
|
hReturn = hError;
|
|
}
|
|
catch (...)
|
|
{
|
|
hReturn = E_INVALIDARG;
|
|
}
|
|
|
|
return hReturn;
|
|
}
|
|
|
|
|
|
/*++
|
|
|
|
CSCardISO7816::GetChallenge:
|
|
|
|
The GetChallenge method constructs an APDU command that issue a challenge
|
|
(for example, a random number) for use in a security-related procedure.
|
|
|
|
Arguments:
|
|
|
|
lBytesExpected [in, defaultvalue(0)] Maximum length of the expected response.
|
|
|
|
ppCmd [in, out] On input, a pointer to an ISCardCmd interface object or
|
|
NULL. On return, it is filled with the APDU command constructed by
|
|
this operation. If ppCmd was set to NULL, a smart card ISCardCmd object
|
|
is internally created and returned via the ppCmd pointer.
|
|
|
|
Return Value:
|
|
|
|
The return value is an HRESULT. A value of S_OK indicates the call was
|
|
successful.
|
|
|
|
Remarks:
|
|
|
|
The challenge is valid at least for the next command.
|
|
|
|
Author:
|
|
|
|
Doug Barlow (dbarlow) 6/24/1999
|
|
|
|
--*/
|
|
#undef __SUBROUTINE__
|
|
#define __SUBROUTINE__ TEXT("CSCardISO7816::GetChallenge")
|
|
|
|
STDMETHODIMP
|
|
CSCardISO7816::GetChallenge(
|
|
/* [in] */ LONG lBytesExpected,
|
|
/* [out][in] */ LPSCARDCMD __RPC_FAR *ppCmd)
|
|
{
|
|
HRESULT hReturn;
|
|
|
|
try
|
|
{
|
|
HRESULT hr;
|
|
|
|
if (NULL == *ppCmd)
|
|
{
|
|
*ppCmd = NewSCardCmd();
|
|
if (NULL == *ppCmd)
|
|
throw (HRESULT)E_OUTOFMEMORY;
|
|
}
|
|
|
|
hr = (*ppCmd)->BuildCmd(
|
|
m_bCla, // CLA
|
|
0x84, // INS
|
|
0x00, // P1
|
|
0x00, // P2
|
|
NULL,
|
|
&lBytesExpected);
|
|
hReturn = hr;
|
|
}
|
|
|
|
catch (HRESULT hError)
|
|
{
|
|
hReturn = hError;
|
|
}
|
|
catch (...)
|
|
{
|
|
hReturn = E_INVALIDARG;
|
|
}
|
|
|
|
return hReturn;
|
|
}
|
|
|
|
|
|
/*++
|
|
|
|
CSCardISO7816::GetData:
|
|
|
|
The GetData method constructs an APDU command that retrieves either a
|
|
single primitive data object or a set of data objects (contained in a
|
|
constructed data object), depending on the type of file selected.
|
|
|
|
Arguments:
|
|
|
|
byP1, byP2 [in] Parameters:
|
|
|
|
Value Meaning
|
|
0000 - 003F RFU
|
|
0040 - 00FF BER-TLV tag (1 byte) in P2
|
|
0100 - 01FF Application data (proprietary coding)
|
|
0200 - 02FF SIMPLE-TLV tag in P2
|
|
0300 - 03FF RFU
|
|
0400 - 04FF BER-TLV tag (2 bytes) in P1-P2
|
|
|
|
lBytesToGet [in, defaultvalue(0)] Number of bytes expected in the response.
|
|
|
|
ppCmd [in, out] On input, a pointer to an ISCardCmd interface object or
|
|
NULL. On return, it is filled with the APDU command constructed by
|
|
this operation. If ppCmd was set to NULL, a smart card ISCardCmd
|
|
object is internally created and returned via the ppCmd pointer.
|
|
|
|
Return Value:
|
|
|
|
The return value is an HRESULT. A value of S_OK indicates the call was
|
|
successful.
|
|
|
|
Remarks:
|
|
|
|
The encapsulated command can only be performed if the security status of
|
|
the smart card satisfies the security attributes of the elementary file
|
|
being read. Security conditions are dependent on the policy of the card,
|
|
and may be manipulated through ExternalAuthenticate, InternalAuthenticate,
|
|
ISCardAuth, etc.
|
|
|
|
To select a file, call SelectFile.
|
|
|
|
Author:
|
|
|
|
Doug Barlow (dbarlow) 6/24/1999
|
|
|
|
--*/
|
|
#undef __SUBROUTINE__
|
|
#define __SUBROUTINE__ TEXT("CSCardISO7816::GetData")
|
|
|
|
STDMETHODIMP
|
|
CSCardISO7816::GetData(
|
|
/* [in] */ BYTE byP1,
|
|
/* [in] */ BYTE byP2,
|
|
/* [in] */ LONG lBytesToGet,
|
|
/* [out][in] */ LPSCARDCMD __RPC_FAR *ppCmd)
|
|
{
|
|
HRESULT hReturn;
|
|
|
|
try
|
|
{
|
|
HRESULT hr;
|
|
|
|
if (NULL == *ppCmd)
|
|
{
|
|
*ppCmd = NewSCardCmd();
|
|
if (NULL == *ppCmd)
|
|
throw (HRESULT)E_OUTOFMEMORY;
|
|
}
|
|
|
|
hr = (*ppCmd)->BuildCmd(
|
|
m_bCla, // CLA
|
|
0xca, // INS
|
|
byP1, // P1
|
|
byP2, // P2
|
|
NULL,
|
|
&lBytesToGet);
|
|
hReturn = hr;
|
|
}
|
|
|
|
catch (HRESULT hError)
|
|
{
|
|
hReturn = hError;
|
|
}
|
|
catch (...)
|
|
{
|
|
hReturn = E_INVALIDARG;
|
|
}
|
|
|
|
return hReturn;
|
|
}
|
|
|
|
|
|
/*++
|
|
|
|
CSCardISO7816::GetResponse:
|
|
|
|
The GetResponse method constructs an APDU command that transmits APDU
|
|
commands (or part of an APDU command) which otherwise could not be
|
|
transmitted by the available protocols.
|
|
|
|
Arguments:
|
|
|
|
byP1, byP2 [in, defaultvalue(0)] Per the ISO 7816-4, P1 and P2 should be 0
|
|
(RFU).
|
|
|
|
lDataLength [in, defaultvalue(0)] Length of data transmitted.
|
|
|
|
ppCmd [in, out] On input, a pointer to an ISCardCmd interface object or
|
|
NULL. On return, it is filled with the APDU command constructed by
|
|
this operation. If ppCmd was set to NULL, a smart card ISCardCmd
|
|
object is internally created and returned via the ppCmd pointer.
|
|
|
|
Return Value:
|
|
|
|
The return value is an HRESULT. A value of S_OK indicates the call was
|
|
successful.
|
|
|
|
Remarks:
|
|
|
|
Author:
|
|
|
|
Doug Barlow (dbarlow) 6/24/1999
|
|
|
|
--*/
|
|
#undef __SUBROUTINE__
|
|
#define __SUBROUTINE__ TEXT("CSCardISO7816::GetResponse")
|
|
|
|
STDMETHODIMP
|
|
CSCardISO7816::GetResponse(
|
|
/* [in] */ BYTE byP1,
|
|
/* [in] */ BYTE byP2,
|
|
/* [in] */ LONG lDataLength,
|
|
/* [out][in] */ LPSCARDCMD __RPC_FAR *ppCmd)
|
|
{
|
|
HRESULT hReturn;
|
|
|
|
try
|
|
{
|
|
HRESULT hr;
|
|
|
|
if (NULL == *ppCmd)
|
|
{
|
|
*ppCmd = NewSCardCmd();
|
|
if (NULL == *ppCmd)
|
|
throw (HRESULT)E_OUTOFMEMORY;
|
|
}
|
|
|
|
hr = (*ppCmd)->BuildCmd(
|
|
m_bCla, // CLA
|
|
0xc0, // INS
|
|
0x00, // P1
|
|
0x00, // P2
|
|
NULL,
|
|
&lDataLength);
|
|
hReturn = hr;
|
|
}
|
|
|
|
catch (HRESULT hError)
|
|
{
|
|
hReturn = hError;
|
|
}
|
|
catch (...)
|
|
{
|
|
hReturn = E_INVALIDARG;
|
|
}
|
|
|
|
return hReturn;
|
|
}
|
|
|
|
|
|
/*++
|
|
|
|
CSCardISO7816::InternalAuthenticate:
|
|
|
|
The InternalAuthenticate method constructs an APDU command that initiates
|
|
the computation of the authentication data by the card using the challenge
|
|
data sent from the interface device and a relevant secret (for example, a
|
|
key) stored in the card.
|
|
|
|
When the relevant secret is attached to the MF, the command may be used to
|
|
authenticate the card as a whole.
|
|
|
|
When the relevant secret is attached to another DF, the command may be used
|
|
to authenticate that DF.
|
|
|
|
Arguments:
|
|
|
|
byAlgorithmRef [in, defaultvalue(NULL_BYTE)] Reference of the algorithm in
|
|
the card. If this value is zero, this indicates that no information is
|
|
given. The reference of the algorithm is known either before issuing
|
|
the command or is provided in the data field.
|
|
|
|
bySecretRef [in, defaultvalue(NULL_BYTE)] Reference of the secret:
|
|
|
|
Meaning 8 7 6 5 4 3 2 1
|
|
No Info 0 0 0 0 0 0 0 0
|
|
Global ref 0 - - - - - - -
|
|
Specific ref 1 - - - - - - -
|
|
RFU - x x - - - - -
|
|
Secret - - - x x x x x
|
|
|
|
No Info = No information is given.
|
|
|
|
Global ref = Global reference data (an MF specific key).
|
|
|
|
Specific ref = Specific reference data (a DF specific key).
|
|
|
|
RFU = 00 (other values are RFU).
|
|
|
|
Secret = Number of the secret.
|
|
|
|
pChallenge [in] Pointer to the authentication-related data (for example,
|
|
challenge).
|
|
|
|
lReplyBytes [in, defaultvalue(0)] Maximum number of bytes expected in
|
|
response.
|
|
|
|
ppCmd [in, out] On input, a pointer to an ISCardCmd interface object or
|
|
NULL. On return, it is filled with the APDU command constructed by
|
|
this operation. If ppCmd was set to NULL, a smart card ISCardCmd
|
|
object is internally created and returned via the ppCmd pointer.
|
|
|
|
Return Value:
|
|
|
|
The return value is an HRESULT. A value of S_OK indicates the call was
|
|
successful.
|
|
|
|
Remarks:
|
|
|
|
The successful execution of the command may be subject to successful
|
|
completion of prior commands (for example, VERIFY or SELECT FILE) or
|
|
selections (for example, the relevant secret).
|
|
|
|
If a key and an algorithm are currently selected when issuing the command,
|
|
then the command may implicitly use the key and the algorithm.
|
|
|
|
The number of times the command is issued may be recorded in the card to
|
|
limit the number of further attempts of using the relevant secret or the
|
|
algorithm.
|
|
|
|
Author:
|
|
|
|
Doug Barlow (dbarlow) 6/24/1999
|
|
|
|
--*/
|
|
#undef __SUBROUTINE__
|
|
#define __SUBROUTINE__ TEXT("CSCardISO7816::InternalAuthenticate")
|
|
|
|
STDMETHODIMP
|
|
CSCardISO7816::InternalAuthenticate(
|
|
/* [in] */ BYTE byAlgorithmRef,
|
|
/* [in] */ BYTE bySecretRef,
|
|
/* [in] */ LPBYTEBUFFER pChallenge,
|
|
/* [in] */ LONG lReplyBytes,
|
|
/* [out][in] */ LPSCARDCMD __RPC_FAR *ppCmd)
|
|
{
|
|
HRESULT hReturn;
|
|
|
|
try
|
|
{
|
|
HRESULT hr;
|
|
|
|
if (NULL == *ppCmd)
|
|
{
|
|
*ppCmd = NewSCardCmd();
|
|
if (NULL == *ppCmd)
|
|
throw (HRESULT)E_OUTOFMEMORY;
|
|
}
|
|
|
|
hr = (*ppCmd)->BuildCmd(
|
|
m_bCla, // CLA
|
|
0x88, // INS
|
|
byAlgorithmRef, // P1
|
|
bySecretRef, // P2
|
|
pChallenge,
|
|
&lReplyBytes);
|
|
hReturn = hr;
|
|
}
|
|
|
|
catch (HRESULT hError)
|
|
{
|
|
hReturn = hError;
|
|
}
|
|
catch (...)
|
|
{
|
|
hReturn = E_INVALIDARG;
|
|
}
|
|
|
|
return hReturn;
|
|
}
|
|
|
|
|
|
/*++
|
|
|
|
CSCardISO7816::ManageChannel:
|
|
|
|
The ManageChannel method constructs an APDU command that opens and closes
|
|
logical channels.
|
|
|
|
The open function opens a new logical channel other than the basic one.
|
|
Options are provided for the card to assign a logical channel number, or
|
|
for the logical channel number to be supplied to the card.
|
|
|
|
The close function explicitly closes a logical channel other than the basic
|
|
one. After the successful closing, the logical channel shall be available
|
|
for re-use.
|
|
|
|
Arguments:
|
|
|
|
byChannelState [in, defaultvalue(ISO_CLOSE_LOGICAL_CHANNEL)] Bit b8 of P1
|
|
is used to indicate the open function or the close function; if b8 is 0
|
|
then MANAGE CHANNEL shall open a logical channel and if b8 is 1 then
|
|
MANAGE CHANNEL shall close a logical channel:
|
|
|
|
P1 = '00' to open
|
|
|
|
P1 = '80' to close
|
|
|
|
Other values are RFU
|
|
|
|
byChannel [in, defaultvalue(ISO_LOGICAL_CHANNEL_0)] For the open function
|
|
(P1 = '00'), the bits b1 and b2 of P2 are used to code the logical
|
|
channel number in the same manner as in the class byte, the other bits
|
|
of P2 are RFU. When b1 and b2 of P2 are NULL, then the card will
|
|
assign a logical channel number that will be returned in bits b1 and
|
|
b2 of the data field.
|
|
|
|
When b1 and/or b2 of P2 are not NULL, they code a logical channel
|
|
number other than the basic one; then the card will open the externally
|
|
assigned logical channel number.
|
|
|
|
ppCmd [in, out] On input, a pointer to an ISCardCmd interface object or
|
|
NULL. On return, it is filled with the APDU command constructed by
|
|
this operation. If ppCmd was set to NULL, a smart card ISCardCmd
|
|
object is internally created and returned via the ppCmd pointer.
|
|
|
|
Return Value:
|
|
|
|
The return value is an HRESULT. A value of S_OK indicates the call was
|
|
successful.
|
|
|
|
Remarks:
|
|
|
|
When the open function is successfully performed from the basic logical
|
|
channel, the MF shall be implicitly selected as the current DF and the
|
|
security status of the new logical channel should be the same as the basic
|
|
logical channel after ATR. The security status of the new logical channel
|
|
should be separate from that of any other logical channel.
|
|
|
|
When the open function is successfully performed from a logical channel,
|
|
which is not the basic one, the current DF of the logical channel that
|
|
issued the command will be selected as the current DF. In addition, the
|
|
security status for the new logical channel should be the same as the
|
|
security status of the logical channel from which the open function was
|
|
performed.
|
|
|
|
After a successful close function, the security status related to this
|
|
logical channel is lost.
|
|
|
|
Author:
|
|
|
|
Doug Barlow (dbarlow) 6/24/1999
|
|
|
|
--*/
|
|
#undef __SUBROUTINE__
|
|
#define __SUBROUTINE__ TEXT("CSCardISO7816::ManageChannel")
|
|
|
|
STDMETHODIMP
|
|
CSCardISO7816::ManageChannel(
|
|
/* [in] */ BYTE byChannelState,
|
|
/* [in] */ BYTE byChannel,
|
|
/* [out][in] */ LPSCARDCMD __RPC_FAR *ppCmd)
|
|
{
|
|
HRESULT hReturn;
|
|
|
|
try
|
|
{
|
|
HRESULT hr;
|
|
LONG lLe = 1;
|
|
|
|
if (NULL == *ppCmd)
|
|
{
|
|
*ppCmd = NewSCardCmd();
|
|
if (NULL == *ppCmd)
|
|
throw (HRESULT)E_OUTOFMEMORY;
|
|
}
|
|
|
|
hr = (*ppCmd)->BuildCmd(
|
|
m_bCla, // CLA
|
|
0x70, // INS
|
|
byChannelState, // P1
|
|
byChannel, // P2
|
|
NULL,
|
|
0 == (byChannelState | byChannel)
|
|
? &lLe
|
|
: NULL);
|
|
hReturn = hr;
|
|
}
|
|
|
|
catch (HRESULT hError)
|
|
{
|
|
hReturn = hError;
|
|
}
|
|
catch (...)
|
|
{
|
|
hReturn = E_INVALIDARG;
|
|
}
|
|
|
|
return hReturn;
|
|
}
|
|
|
|
|
|
/*++
|
|
|
|
CSCardISO7816::PutData:
|
|
|
|
The PutData method constructs an APDU command that stores a single
|
|
primitive data object or the set of data objects contained in a constructed
|
|
data object, depending on the file selected.
|
|
|
|
How the objects are stored (writing once and/or updating and/or appending)
|
|
depends on the definition or the nature of the data objects.
|
|
|
|
Arguments:
|
|
|
|
byP1, byP2 [in] Coding of P1-P2:
|
|
|
|
Value Meaning
|
|
0000 - 003F RFU
|
|
0040 - 00FF BER-TLV tag (1 byte) in P2
|
|
0100 - 01FF Application data (proprietary coding)
|
|
0200 - 02FF SIMPLE-TLV tag in P2
|
|
0300 - 03FF RFU
|
|
0400 - 04FF BER-TLV tag (2 bytes) in P1-P2
|
|
|
|
pData [in] Pointer to a byte buffer that contains the parameters and data to be
|
|
written.
|
|
|
|
ppCmd [in, out] On input, a pointer to an ISCardCmd interface object or
|
|
NULL. On return, it is filled with the APDU command constructed by
|
|
this operation. If ppCmd was set to NULL, a smart card ISCardCmd
|
|
object is internally created and returned via the ppCmd pointer.
|
|
|
|
Return Value:
|
|
|
|
The return value is an HRESULT. A value of S_OK indicates the call was
|
|
successful.
|
|
|
|
Remarks:
|
|
|
|
The command can be performed only if the security status satisfies the
|
|
security conditions defined by the application within the context for the
|
|
function.
|
|
|
|
Store Application Data
|
|
When the value of P1-P2 lies in the range from 0100 to 01FF, the value
|
|
of P1-P2 shall be an identifier reserved for card internal tests and
|
|
for proprietary services meaningful within a given application context.
|
|
|
|
Store Data Objects
|
|
When the value P1-P2 lies in the range from 0040 to 00FF, the value of
|
|
P2 shall be a BER-TLV tag on a single byte. The value of 00FF is
|
|
reserved for indicating that the data field carries BER-TLV data
|
|
objects.
|
|
|
|
When the value of P1-P2 lies in the range 0200 to 02FF, the value of P2
|
|
shall be a SIMPLE-TLV tag. The value 0200 is RFU. The value 02FF is
|
|
reserved for indicating that the data field carries SIMPLE-TLV data
|
|
objects.
|
|
|
|
When the value of P1-P2 lies in the range from 4000 to FFFF, the value
|
|
of P1-P2 shall be a BER-TLV tag on two bytes. The values 4000 to FFFF
|
|
are RFU.
|
|
|
|
When a primitive data object is provided, the data field of the command
|
|
message shall contain the value of the corresponding primitive data
|
|
object.
|
|
|
|
When a constructed data object is provided, the data field of the
|
|
command message shall contain the value of the constructed data object
|
|
(that is, data objects including their tag, length, and value).
|
|
|
|
Author:
|
|
|
|
Doug Barlow (dbarlow) 6/24/1999
|
|
|
|
--*/
|
|
#undef __SUBROUTINE__
|
|
#define __SUBROUTINE__ TEXT("CSCardISO7816::PutData")
|
|
|
|
STDMETHODIMP
|
|
CSCardISO7816::PutData(
|
|
/* [in] */ BYTE byP1,
|
|
/* [in] */ BYTE byP2,
|
|
/* [in] */ LPBYTEBUFFER pData,
|
|
/* [out][in] */ LPSCARDCMD __RPC_FAR *ppCmd)
|
|
{
|
|
HRESULT hReturn;
|
|
|
|
try
|
|
{
|
|
HRESULT hr;
|
|
|
|
if (NULL == *ppCmd)
|
|
{
|
|
*ppCmd = NewSCardCmd();
|
|
if (NULL == *ppCmd)
|
|
throw (HRESULT)E_OUTOFMEMORY;
|
|
}
|
|
|
|
hr = (*ppCmd)->BuildCmd(
|
|
m_bCla, // CLA
|
|
0xda, // INS
|
|
byP1, // P1
|
|
byP2, // P2
|
|
pData,
|
|
NULL);
|
|
hReturn = hr;
|
|
}
|
|
|
|
catch (HRESULT hError)
|
|
{
|
|
hReturn = hError;
|
|
}
|
|
catch (...)
|
|
{
|
|
hReturn = E_INVALIDARG;
|
|
}
|
|
|
|
return hReturn;
|
|
}
|
|
|
|
|
|
/*++
|
|
|
|
CSCardISO7816::ReadBinary:
|
|
|
|
The ReadBinary method constructs an APDU command that acquires a response
|
|
message that gives that part of the contents of a transparent-structured
|
|
elementary file.
|
|
|
|
Arguments:
|
|
|
|
byP1, byP2 [in] The P1-P2 field, offset to the first byte to be read from
|
|
the beginning of the file.
|
|
|
|
If b8=1 in P1, then b7 and b6 of P1 are set to 0 (RFU bits), b5 to b1
|
|
of P1 are a short EF identifier and P2 is the offset of the first byte
|
|
to be read in data units from the beginning of the file.
|
|
|
|
If b8=0 in P1, then P1||P2 is the offset of the first byte to be read
|
|
in data units from the beginning of the file.
|
|
|
|
lBytesToRead [in, defaultvalue(0)] Number of bytes to read from the
|
|
transparent EF. If the Le field contains only zeroes, then within the
|
|
limit of 256 for short length or 65536 for extended length, all the bytes
|
|
until the end of the file should be read.
|
|
|
|
ppCmd [in, out] On input, a pointer to an ISCardCmd interface object or
|
|
NULL. On return, it is filled with the APDU command constructed by
|
|
this operation. If ppCmd was set to NULL, a smart card ISCardCmd
|
|
object is internally created and returned via the ppCmd pointer.
|
|
|
|
Return Value:
|
|
|
|
The return value is an HRESULT. A value of S_OK indicates the call was
|
|
successful.
|
|
|
|
Remarks:
|
|
|
|
The encapsulated command can only be performed if the security status of
|
|
the smart card satisfies the security attributes of the elementary file
|
|
being processed.
|
|
|
|
When the command contains a valid short elementary identifier, it sets the
|
|
file as current elementary file.
|
|
|
|
Elementary files without a transparent structure cannot be erased. The
|
|
encapsulated command aborts if applied to an elementary file without a
|
|
transparent structure.
|
|
|
|
Author:
|
|
|
|
Doug Barlow (dbarlow) 6/24/1999
|
|
|
|
--*/
|
|
#undef __SUBROUTINE__
|
|
#define __SUBROUTINE__ TEXT("CSCardISO7816::ReadBinary")
|
|
|
|
STDMETHODIMP
|
|
CSCardISO7816::ReadBinary(
|
|
/* [in] */ BYTE byP1,
|
|
/* [in] */ BYTE byP2,
|
|
/* [in] */ LONG lBytesToRead,
|
|
/* [out][in] */ LPSCARDCMD __RPC_FAR *ppCmd)
|
|
{
|
|
HRESULT hReturn;
|
|
|
|
try
|
|
{
|
|
HRESULT hr;
|
|
|
|
if (NULL == *ppCmd)
|
|
{
|
|
*ppCmd = NewSCardCmd();
|
|
if (NULL == *ppCmd)
|
|
throw (HRESULT)E_OUTOFMEMORY;
|
|
}
|
|
|
|
hr = (*ppCmd)->BuildCmd(
|
|
m_bCla, // CLA
|
|
0xb0, // INS
|
|
byP1, // P1
|
|
byP2, // P2
|
|
NULL,
|
|
&lBytesToRead);
|
|
hReturn = hr;
|
|
}
|
|
|
|
catch (HRESULT hError)
|
|
{
|
|
hReturn = hError;
|
|
}
|
|
catch (...)
|
|
{
|
|
hReturn = E_INVALIDARG;
|
|
}
|
|
|
|
return hReturn;
|
|
}
|
|
|
|
|
|
/*++
|
|
|
|
CSCardISO7816::ReadRecord:
|
|
|
|
The ReadRecord method constructs an APDU command that reads either the
|
|
contents of the specified record(s) or the beginning part of one record of
|
|
an elementary file.
|
|
|
|
Arguments:
|
|
|
|
byRecordId [in, defaultvalue(NULL_BYTE)] Record number or ID of the first
|
|
record to be read (00 indicates the current record).
|
|
|
|
byRefCtrl [in] Coding of the reference control:
|
|
|
|
Meaning 8 7 6 5 4 3 2 1
|
|
Current EF 0 0 0 0 0 - - -
|
|
Short EF ID x x x x x - - -
|
|
RFU 1 1 1 1 1 - - -
|
|
Record - - - - - 1 x x
|
|
Read Record - - - - - 1 0 0
|
|
Up to Last - - - - - 1 0 1
|
|
Up to P1 - - - - - 1 1 0
|
|
RFU - - - - - 1 1 1
|
|
Record ID - - - - - 0 x x
|
|
First Occur - - - - - 0 0 0
|
|
Last Occur - - - - - 0 0 1
|
|
Next Occur - - - - - 0 1 0
|
|
Previous - - - - - 0 1 1
|
|
Secret - - - x x x x x
|
|
|
|
Current EF = Currently selected EF.
|
|
|
|
Short EF ID = Short EF identifier.
|
|
|
|
Record # = Usage of record number in P1.
|
|
|
|
Read Record = Read record P1.
|
|
|
|
Up to Last = Read all records from P1 up to the last.
|
|
|
|
Up to P1 = Read all records from the last up to P1.
|
|
|
|
Record ID = Usage of record ID in P1.
|
|
|
|
First Occur = Read first occurrence.
|
|
|
|
Last Occur = Read last occurrence.
|
|
|
|
Next Occur = Read next occurrence.
|
|
|
|
Previous = Read previous occurrence.
|
|
|
|
lBytesToRead [in, defaultvalue(0)] Number of bytes to read from the
|
|
transparent EF. If the Le field contains only zeroes, then depending
|
|
on b3b2b1 of P2 and within the limit of 256 for short length or 65536
|
|
for extended length, the command should read completely either the
|
|
single requested record or the requested sequence of records.
|
|
|
|
ppCmd [in, out] On input, a pointer to an ISCardCmd interface object or
|
|
NULL. On return, it is filled with the APDU command constructed by
|
|
this operation. If ppCmd was set to NULL, a smart card ISCardCmd
|
|
object is internally created and returned via the ppCmd pointer.
|
|
|
|
Return Value:
|
|
|
|
The return value is an HRESULT. A value of S_OK indicates the call was
|
|
successful.
|
|
|
|
Remarks:
|
|
|
|
The encapsulated command can only be performed if the security status of
|
|
the smart card satisfies the security attributes of the elementary file
|
|
being read.
|
|
|
|
If another elementary file is currently selected at the time of issuing
|
|
this command, it may be processed without identification of the currently
|
|
selected file.
|
|
|
|
When the command contains a valid short elementary identifier, it sets the
|
|
file as current elementary file.
|
|
|
|
Elementary files without a record structure cannot be read. The
|
|
encapsulated command aborts if applied to an elementary file without a
|
|
record structure.
|
|
|
|
Author:
|
|
|
|
Doug Barlow (dbarlow) 6/24/1999
|
|
|
|
--*/
|
|
#undef __SUBROUTINE__
|
|
#define __SUBROUTINE__ TEXT("CSCardISO7816::ReadRecord")
|
|
|
|
STDMETHODIMP
|
|
CSCardISO7816::ReadRecord(
|
|
/* [in] */ BYTE byRecordId,
|
|
/* [in] */ BYTE byRefCtrl,
|
|
/* [in] */ LONG lBytesToRead,
|
|
/* [out][in] */ LPSCARDCMD __RPC_FAR *ppCmd)
|
|
{
|
|
HRESULT hReturn;
|
|
|
|
try
|
|
{
|
|
HRESULT hr;
|
|
|
|
if (NULL == *ppCmd)
|
|
{
|
|
*ppCmd = NewSCardCmd();
|
|
if (NULL == *ppCmd)
|
|
throw (HRESULT)E_OUTOFMEMORY;
|
|
}
|
|
|
|
hr = (*ppCmd)->BuildCmd(
|
|
m_bCla, // CLA
|
|
0xb2, // INS
|
|
byRecordId, // P1
|
|
byRefCtrl, // P2
|
|
NULL,
|
|
&lBytesToRead);
|
|
hReturn = hr;
|
|
}
|
|
|
|
catch (HRESULT hError)
|
|
{
|
|
hReturn = hError;
|
|
}
|
|
catch (...)
|
|
{
|
|
hReturn = E_INVALIDARG;
|
|
}
|
|
|
|
return hReturn;
|
|
}
|
|
|
|
|
|
/*++
|
|
|
|
CSCardISO7816::SelectFile:
|
|
|
|
The SelectFile method constructs an APDU command that sets a current
|
|
elementary file within a logical channel. Subsequent commands may
|
|
implicitly refer to the current file through the logical channel.
|
|
|
|
Selecting a directory (DF) within the card filestore — which may be the
|
|
root (MF) of the filestore — makes it the current DF. After such a
|
|
selection, an implicit current elementary file may be referred to through
|
|
that logical channel.
|
|
|
|
Selecting an elementary file sets the selected file and its parent as
|
|
current files.
|
|
|
|
After the answer to reset, the MF is implicitly selected through the basic
|
|
logical channel, unless specified differently in the historical bytes or in
|
|
the initial data string.
|
|
|
|
Arguments:
|
|
|
|
byP1, byP2 [in] Selection control.
|
|
|
|
P1 (upper byte in word):
|
|
Meaning 8 7 6 5 4 3 2 1
|
|
Select File ID 0 0 0 0 0 0 x x
|
|
EF, DF, or MF 0 0 0 0 0 0 0 0
|
|
child DF 0 0 0 0 0 0 0 1
|
|
EF under DF 0 0 0 0 0 0 1 0
|
|
parent DF of current DF 0 0 0 0 0 0 1 1
|
|
|
|
Select by DF Name 0 0 0 0 0 1 x x
|
|
DFname 0 0 0 0 0 1 0 0
|
|
RFU 0 0 0 0 0 1 0 1
|
|
RFU 0 0 0 0 0 1 1 0
|
|
RFU 0 0 0 0 0 1 1 1
|
|
|
|
Select by path 0 0 0 0 1 0 x x
|
|
from MF 0 0 0 0 1 0 0 0
|
|
current DF 0 0 0 0 1 0 0 1
|
|
RFU 0 0 0 0 1 0 1 0
|
|
RFU 0 0 0 0 1 0 1 1
|
|
|
|
When P1=00, the card knows either because of a specific coding of
|
|
the file ID or because of the context of execution of the command
|
|
if the file to select is the MF, a DF, or an EF.
|
|
|
|
When P1-P2=0000, if a file ID is provided, then it shall be unique
|
|
in the following environments:
|
|
|
|
the immediate children of the current DF
|
|
the parent DF
|
|
the immediate children of the parent DF
|
|
|
|
If P1-P2=0000 and if the data field is empty or equal to 3F00, then
|
|
select the MF.
|
|
|
|
When P1=04, the data field is a DF name, possibly right truncated.
|
|
|
|
When supported, successive such commands with the same data field
|
|
shall select DFs whose names match with the data field (that is,
|
|
start with the command data field). If the card accepts the
|
|
command with an empty data field, then all or a subset of the DFs
|
|
can be successively selected.
|
|
|
|
P2 (lower byte of word):
|
|
Meaning 8 7 6 5 4 3 2 1
|
|
First occur 0 0 0 0 - - 0 0
|
|
Last occur 0 0 0 0 - - 0 1
|
|
Next occur 0 0 0 0 - - 1 0
|
|
Previous occur 0 0 0 0 - - 1 1
|
|
|
|
File Control 0 0 0 0 x x - -
|
|
Return FCI 0 0 0 0 0 0 - -
|
|
Return FCP 0 0 0 0 0 1 - -
|
|
Return FMD 0 0 0 0 1 0 - -
|
|
|
|
pData [in, defaultvalue(NULL)] Data for operation if needed; else, NULL.
|
|
Types of data that are passed in this parameter include:
|
|
|
|
file ID
|
|
path from the MF
|
|
path from the current DF
|
|
DF name
|
|
|
|
lBytesToRead [in, defaultvalue(0)] Empty (that is, 0) or maximum length of
|
|
data expected in response.
|
|
|
|
ppCmd [in, out] On input, a pointer to an ISCardCmd interface object or
|
|
NULL. On return, it is filled with the APDU command constructed by
|
|
this operation. If ppCmd was set to NULL, a smart card ISCardCmd
|
|
object is internally created and returned via the ppCmd pointer.
|
|
|
|
Return Value:
|
|
|
|
The return value is an HRESULT. A value of S_OK indicates the call was
|
|
successful.
|
|
|
|
Remarks:
|
|
|
|
Unless otherwise specified, the correct execution of the encapsulated
|
|
command modifies the security status according to the following rules:
|
|
|
|
* When the current elementary file is changed, or when there is no
|
|
current elementary file, the security status specific to a former
|
|
current elementary file is lost.
|
|
|
|
* When the current filestore directory (DF) is descendant of, or
|
|
identical to the former current DF, the security status specific to the
|
|
former current DF is lost. The security status common to all common
|
|
ancestors of the previous and new current DF is maintained.
|
|
|
|
Author:
|
|
|
|
Doug Barlow (dbarlow) 6/24/1999
|
|
|
|
--*/
|
|
#undef __SUBROUTINE__
|
|
#define __SUBROUTINE__ TEXT("CSCardISO7816::SelectFile")
|
|
|
|
STDMETHODIMP
|
|
CSCardISO7816::SelectFile(
|
|
/* [in] */ BYTE byP1,
|
|
/* [in] */ BYTE byP2,
|
|
/* [in] */ LPBYTEBUFFER pData,
|
|
/* [in] */ LONG lBytesToRead,
|
|
/* [out][in] */ LPSCARDCMD __RPC_FAR *ppCmd)
|
|
{
|
|
HRESULT hReturn;
|
|
|
|
try
|
|
{
|
|
HRESULT hr;
|
|
|
|
if (NULL == *ppCmd)
|
|
{
|
|
*ppCmd = NewSCardCmd();
|
|
if (NULL == *ppCmd)
|
|
throw (HRESULT)E_OUTOFMEMORY;
|
|
}
|
|
|
|
hr = (*ppCmd)->BuildCmd(
|
|
m_bCla, // CLA
|
|
0xa4, // INS
|
|
byP1, // P1
|
|
byP2, // P2
|
|
pData,
|
|
0 == lBytesToRead ? NULL : &lBytesToRead);
|
|
hReturn = hr;
|
|
}
|
|
|
|
catch (HRESULT hError)
|
|
{
|
|
hReturn = hError;
|
|
}
|
|
catch (...)
|
|
{
|
|
hReturn = E_INVALIDARG;
|
|
}
|
|
|
|
return hReturn;
|
|
}
|
|
|
|
|
|
/*++
|
|
|
|
CSCardISO7816::SetDefaultClassId:
|
|
|
|
The SetDefaultClassId method assigns a standard class identifier byte that
|
|
will be used in all operations when constructing an ISO 7816-4 command
|
|
APDU. By default, the standard class identifier byte is 0x00.
|
|
|
|
Arguments:
|
|
|
|
byClass [in] Class ID byte.
|
|
|
|
Return Value:
|
|
|
|
The return value is an HRESULT. A value of S_OK indicates the call was
|
|
successful.
|
|
|
|
Remarks:
|
|
|
|
Author:
|
|
|
|
Doug Barlow (dbarlow) 6/24/1999
|
|
|
|
--*/
|
|
#undef __SUBROUTINE__
|
|
#define __SUBROUTINE__ TEXT("CSCardISO7816::SetDefaultClassId")
|
|
|
|
STDMETHODIMP
|
|
CSCardISO7816::SetDefaultClassId(
|
|
/* [in] */ BYTE byClass)
|
|
{
|
|
m_bCla = byClass;
|
|
return S_OK;
|
|
}
|
|
|
|
|
|
/*++
|
|
|
|
CSCardISO7816::UpdateBinary:
|
|
|
|
The UpdateBinary method constructs an APDU command that updates the bits
|
|
present in an elementary file with the bits given in the APDU command.
|
|
|
|
Arguments:
|
|
|
|
byP1, byP2 [in] Offset to the write (update) location into the binary from
|
|
the start of the binary.
|
|
|
|
If b8=1 in P1, then b7 and b6 of P1 are set to 0 (RFU bits), b5 to b1
|
|
of P1 are a short EF identifier and P2 is the offset of the first byte
|
|
to be updated in data units from the beginning of the file.
|
|
|
|
If b8=0 in P1, then P1 || P2 is the offset of the first byte to be
|
|
updated in data units from the beginning of the file.
|
|
|
|
pData [in] Pointer to the string of data units to be updated.
|
|
|
|
ppCmd [in, out] On input, a pointer to an ISCardCmd interface object or
|
|
NULL. On return, it is filled with the APDU command constructed by
|
|
this operation. If ppCmd was set to NULL, a smart card ISCardCmd
|
|
object is internally created and returned via the ppCmd pointer.
|
|
|
|
Return Value:
|
|
|
|
The return value is an HRESULT. A value of S_OK indicates the call was
|
|
successful.
|
|
|
|
Remarks:
|
|
|
|
The encapsulated command can only be performed if the security status of
|
|
the smart card satisfies the security attributes of the elementary file
|
|
being processed.
|
|
|
|
When the command contains a valid short elementary identifier, it sets the
|
|
file as current elementary file.
|
|
|
|
Elementary files without a transparent structure cannot be erased. The
|
|
encapsulated command aborts if applied to an elementary file without a
|
|
transparent structure.
|
|
|
|
Author:
|
|
|
|
Doug Barlow (dbarlow) 6/24/1999
|
|
|
|
--*/
|
|
#undef __SUBROUTINE__
|
|
#define __SUBROUTINE__ TEXT("CSCardISO7816::UpdateBinary")
|
|
|
|
STDMETHODIMP
|
|
CSCardISO7816::UpdateBinary(
|
|
/* [in] */ BYTE byP1,
|
|
/* [in] */ BYTE byP2,
|
|
/* [in] */ LPBYTEBUFFER pData,
|
|
/* [out][in] */ LPSCARDCMD __RPC_FAR *ppCmd)
|
|
{
|
|
HRESULT hReturn;
|
|
|
|
try
|
|
{
|
|
HRESULT hr;
|
|
|
|
if (NULL == *ppCmd)
|
|
{
|
|
*ppCmd = NewSCardCmd();
|
|
if (NULL == *ppCmd)
|
|
throw (HRESULT)E_OUTOFMEMORY;
|
|
}
|
|
|
|
hr = (*ppCmd)->BuildCmd(
|
|
m_bCla, // CLA
|
|
0xd6, // INS
|
|
byP1, // P1
|
|
byP2, // P2
|
|
pData,
|
|
NULL);
|
|
hReturn = hr;
|
|
}
|
|
|
|
catch (HRESULT hError)
|
|
{
|
|
hReturn = hError;
|
|
}
|
|
catch (...)
|
|
{
|
|
hReturn = E_INVALIDARG;
|
|
}
|
|
|
|
return hReturn;
|
|
}
|
|
|
|
|
|
/*++
|
|
|
|
CSCardISO7816::UpdateRecord:
|
|
|
|
The UpdateRecord method constructs an APDU command that updates a specific
|
|
record with the bits given in the APDU command.
|
|
|
|
Note When using current record addressing, the command sets the record
|
|
pointer on the successfully updated record.
|
|
|
|
Arguments:
|
|
|
|
byRecordId [in, defaultvalue(NULL_BYTE)] P1 value:
|
|
|
|
P1 = 00 designates the current record
|
|
P1 != '00' is the number of the specified record
|
|
|
|
byRefCtrl [in, defaultvalue(NULL_BYTE)] Coding of the reference control P2:
|
|
|
|
Meaning 8 7 6 5 4 3 2 1
|
|
Current EF 0 0 0 0 0 - - -
|
|
Short EF ID x x x x x - - -
|
|
First Record - - - - - 0 0 0
|
|
Last Record - - - - - 0 0 1
|
|
Next Record - - - - - 0 1 0
|
|
Previous Record - - - - - 0 1 1
|
|
Record # in P1 - - - - - 1 0 0
|
|
|
|
pData [in] Pointer to the record to be updated.
|
|
|
|
ppCmd [in, out] On input, a pointer to an ISCardCmd interface object or
|
|
NULL. On return, it is filled with the APDU command constructed by
|
|
this operation. If ppCmd was set to NULL, a smart card ISCardCmd
|
|
object is internally created and returned via the ppCmd pointer.
|
|
|
|
Return Value:
|
|
|
|
The return value is an HRESULT. A value of S_OK indicates the call was
|
|
successful.
|
|
|
|
Remarks:
|
|
|
|
The encapsulated command can only be performed if the security status of
|
|
the smart card satisfies the security attributes of the elementary file
|
|
being processed.
|
|
|
|
When the command contains a valid short elementary identifier, it sets the
|
|
file as current elementary file. If another elementary file is currently
|
|
selected at the time of issuing this command, this command may be processed
|
|
without identification of the currently selected file.
|
|
|
|
If the constructed command applies to a linear-fixed or cyclic-structured
|
|
elementary file, it will abort if the record length is different from the
|
|
length of the existing record.
|
|
|
|
If the command applies to a linear-variable structured elementary file, it
|
|
may be carried out when the record length is different from the length of
|
|
the existing record.
|
|
|
|
The "previous" option of the command (P2=xxxxx011), applied to a cyclic
|
|
file, has the same behavior as a command constructed by AppendRecord.
|
|
|
|
Elementary files without a record structure cannot be read. The
|
|
constructed command aborts if applied to an elementary file without record
|
|
structure.
|
|
|
|
Author:
|
|
|
|
Doug Barlow (dbarlow) 6/24/1999
|
|
|
|
--*/
|
|
#undef __SUBROUTINE__
|
|
#define __SUBROUTINE__ TEXT("CSCardISO7816::UpdateRecord")
|
|
|
|
STDMETHODIMP
|
|
CSCardISO7816::UpdateRecord(
|
|
/* [in] */ BYTE byRecordId,
|
|
/* [in] */ BYTE byRefCtrl,
|
|
/* [in] */ LPBYTEBUFFER pData,
|
|
/* [out][in] */ LPSCARDCMD __RPC_FAR *ppCmd)
|
|
{
|
|
HRESULT hReturn;
|
|
|
|
try
|
|
{
|
|
HRESULT hr;
|
|
|
|
if (NULL == *ppCmd)
|
|
{
|
|
*ppCmd = NewSCardCmd();
|
|
if (NULL == *ppCmd)
|
|
throw (HRESULT)E_OUTOFMEMORY;
|
|
}
|
|
|
|
hr = (*ppCmd)->BuildCmd(
|
|
m_bCla, // CLA
|
|
0xdc, // INS
|
|
byRecordId, // P1
|
|
byRefCtrl, // P2
|
|
pData,
|
|
NULL);
|
|
hReturn = hr;
|
|
}
|
|
|
|
catch (HRESULT hError)
|
|
{
|
|
hReturn = hError;
|
|
}
|
|
catch (...)
|
|
{
|
|
hReturn = E_INVALIDARG;
|
|
}
|
|
|
|
return hReturn;
|
|
}
|
|
|
|
|
|
/*++
|
|
|
|
CSCardISO7816::Verify:
|
|
|
|
The Verify method constructs an APDU command that initiates the comparison
|
|
(in the card) of the verification data sent from the interface device with
|
|
the reference data stored in the card (for example, password).
|
|
|
|
Arguments:
|
|
|
|
byRefCtrl [in, defaultvalue(NULL_BYTE)] Quantifier of the reference data;
|
|
coding of the reference control P2:
|
|
|
|
Meaning 8 7 6 5 4 3 2 1
|
|
No Info 0 0 0 0 0 0 0 0
|
|
Global Ref 0 - - - - - - -
|
|
Specific Ref 1 - - - - - - -
|
|
RFU - x x - - - - -
|
|
Ref Data # - - - x x x x x
|
|
|
|
An example of Global Ref would be a password.
|
|
|
|
An example of Specific Ref is DF specific password.
|
|
|
|
P2=00 is reserved to indicate that no particular qualifier is used in
|
|
those cards where the verify command references the secret data
|
|
unambiguously.
|
|
|
|
The reference data number may be for example a password number or a
|
|
short EF identifier.
|
|
|
|
When the body is empty, the command may be used either to retrieve the
|
|
number 'X' of further allowed retries (SW1-SW2=63CX) or to check
|
|
whether the verification is not required (SW1-SW2=9000).
|
|
|
|
pData [in, defaultvalue(NULL)] Pointer to the verification data, or can be
|
|
NULL.
|
|
|
|
ppCmd [in, out] On input, a pointer to an ISCardCmd interface object or
|
|
NULL. On return, it is filled with the APDU command constructed by
|
|
this operation. If ppCmd was set to NULL, a smart card ISCardCmd object
|
|
is internally created and returned via the ppCmd pointer.
|
|
|
|
Return Value:
|
|
|
|
The return value is an HRESULT. A value of S_OK indicates the call was
|
|
successful.
|
|
|
|
Remarks:
|
|
|
|
The security status may be modified as a result of a comparison.
|
|
Unsuccessful comparisons may be recorded in the card (for example, to limit
|
|
the number of further attempts of the use of the reference data).
|
|
|
|
Author:
|
|
|
|
Doug Barlow (dbarlow) 6/24/1999
|
|
|
|
--*/
|
|
#undef __SUBROUTINE__
|
|
#define __SUBROUTINE__ TEXT("CSCardISO7816::Verify")
|
|
|
|
STDMETHODIMP
|
|
CSCardISO7816::Verify(
|
|
/* [in] */ BYTE byRefCtrl,
|
|
/* [in] */ LPBYTEBUFFER pData,
|
|
/* [out][in] */ LPSCARDCMD __RPC_FAR *ppCmd)
|
|
{
|
|
HRESULT hReturn;
|
|
|
|
try
|
|
{
|
|
HRESULT hr;
|
|
|
|
if (NULL == *ppCmd)
|
|
{
|
|
*ppCmd = NewSCardCmd();
|
|
if (NULL == *ppCmd)
|
|
throw (HRESULT)E_OUTOFMEMORY;
|
|
}
|
|
|
|
hr = (*ppCmd)->BuildCmd(
|
|
m_bCla, // CLA
|
|
0x20, // INS
|
|
0x00, // P1
|
|
byRefCtrl, // P2
|
|
pData,
|
|
NULL);
|
|
hReturn = hr;
|
|
}
|
|
|
|
catch (HRESULT hError)
|
|
{
|
|
hReturn = hError;
|
|
}
|
|
catch (...)
|
|
{
|
|
hReturn = E_INVALIDARG;
|
|
}
|
|
|
|
return hReturn;
|
|
}
|
|
|
|
|
|
/*++
|
|
|
|
CSCardISO7816::WriteBinary:
|
|
|
|
The WriteBinary method constructs an APDU command that writes binary values
|
|
into an elementary file.
|
|
|
|
Depending upon the file attributes, the command performs one of the
|
|
following operations:
|
|
|
|
* The logical OR of the bits already present in the card with the bits
|
|
given in the command APDU (logical erased state of the bits of the file
|
|
is 0).
|
|
|
|
* The logical AND of the bits already present in the card with the bits
|
|
given in the command APDU (logical erased state of the bits of the file
|
|
is 1).
|
|
|
|
* The one-time write in the card of the bits given in the command APDU.
|
|
|
|
When no indication is given in the data coding byte, the logical OR
|
|
behavior applies.
|
|
|
|
Arguments:
|
|
|
|
byP1, byP2 [in] Offset to the write location from the beginning of the
|
|
binary file (EF).
|
|
|
|
If b8=1 in P1, then b7 and b6 of P1 are set to 0 (RFU bits), b5 to b1
|
|
of P1 are a short EF identifier and P2 is the offset of the first byte
|
|
to be written in data units from the beginning of the file.
|
|
|
|
If b8=0 in P1, then P1||P2 is the offset of the first byte to be
|
|
written in data units from the beginning of the file.
|
|
|
|
pData [in] Pointer to the string of data units to be written.
|
|
|
|
ppCmd [in, out] On input, a pointer to an ISCardCmd interface object or
|
|
NULL. On return, it is filled with the APDU command constructed by
|
|
this operation. If ppCmd was set to NULL, a smart card ISCardCmd
|
|
object is internally created and returned via the ppCmd pointer.
|
|
|
|
Return Value:
|
|
|
|
The return value is an HRESULT. A value of S_OK indicates the call was
|
|
successful.
|
|
|
|
Remarks:
|
|
|
|
The encapsulated command can only be performed if the security status of
|
|
the smart card satisfies the security attributes of the elementary file
|
|
being processed.
|
|
|
|
When the command contains a valid short elementary identifier, it sets the
|
|
file as current elementary file.
|
|
|
|
Once a write binary operation has been applied to a data unit of a one-time
|
|
write EF, any further write operation referring to this data unit will be
|
|
aborted if the content of the data unit or the logical erased state
|
|
indicator (if any) attached to this data unit is different from the logical
|
|
erased state.
|
|
|
|
Elementary files without a transparent structure cannot be written to. The
|
|
encapsulated command aborts if applied to an elementary file without a
|
|
transparent structure.
|
|
|
|
Author:
|
|
|
|
Doug Barlow (dbarlow) 6/24/1999
|
|
|
|
--*/
|
|
#undef __SUBROUTINE__
|
|
#define __SUBROUTINE__ TEXT("CSCardISO7816::WriteBinary")
|
|
|
|
STDMETHODIMP
|
|
CSCardISO7816::WriteBinary(
|
|
/* [in] */ BYTE byP1,
|
|
/* [in] */ BYTE byP2,
|
|
/* [in] */ LPBYTEBUFFER pData,
|
|
/* [out][in] */ LPSCARDCMD __RPC_FAR *ppCmd)
|
|
{
|
|
HRESULT hReturn;
|
|
|
|
try
|
|
{
|
|
HRESULT hr;
|
|
|
|
if (NULL == *ppCmd)
|
|
{
|
|
*ppCmd = NewSCardCmd();
|
|
if (NULL == *ppCmd)
|
|
throw (HRESULT)E_OUTOFMEMORY;
|
|
}
|
|
|
|
hr = (*ppCmd)->BuildCmd(
|
|
m_bCla, // CLA
|
|
0xd0, // INS
|
|
byP1, // P1
|
|
byP2, // P2
|
|
pData,
|
|
NULL);
|
|
hReturn = hr;
|
|
}
|
|
|
|
catch (HRESULT hError)
|
|
{
|
|
hReturn = hError;
|
|
}
|
|
catch (...)
|
|
{
|
|
hReturn = E_INVALIDARG;
|
|
}
|
|
|
|
return hReturn;
|
|
}
|
|
|
|
|
|
/*++
|
|
|
|
CSCardISO7816::WriteRecord:
|
|
|
|
The WriteRecord method constructs an APDU command that initiates one of the
|
|
following operations:
|
|
|
|
* The write once of a record.
|
|
|
|
* The logical OR of the data bytes of a record already present in the
|
|
card with the data bytes of the record given in the command APDU.
|
|
|
|
* The logical AND of the data bytes of a record already present in the
|
|
card with the data bytes of the record given in the command APDU.
|
|
|
|
When no indication is given in the data coding byte, the logical OR behavior applies.
|
|
|
|
Note: When using current record addressing, the command sets the record
|
|
pointer on the successfully updated record.
|
|
|
|
Arguments:
|
|
|
|
byRecordId [in, defaultvalue(NULL_BYTE)] Record identification. This is the
|
|
P1 value:
|
|
|
|
P1 = '00' designates the current record.
|
|
|
|
P1 != '00' is the number of the specified record.
|
|
|
|
byRefCtrl [in, defaultvalue(NULL_BYTE)] Coding of the reference control P2:
|
|
|
|
Meaning 8 7 6 5 4 3 2 1
|
|
Current EF 0 0 0 0 0 - - -
|
|
Short EF ID x x x x x - - -
|
|
First Record - - - - - 0 0 0
|
|
Last Record - - - - - 0 0 1
|
|
Next Record - - - - - 0 1 0
|
|
Previous Record - - - - - 0 1 1
|
|
Record # in P1 - - - - - 1 0 0
|
|
|
|
pData [in] Pointer to the record to be written.
|
|
|
|
ppCmd [in, out] On input, a pointer to an ISCardCmd interface object or
|
|
NULL. On return, it is filled with the APDU command constructed by
|
|
this operation. If ppCmd was set to NULL, a smart card ISCardCmd
|
|
object is internally created and returned via the ppCmd pointer.
|
|
|
|
Return Value:
|
|
|
|
The return value is an HRESULT. A value of S_OK indicates the call was
|
|
successful.
|
|
|
|
Remarks:
|
|
|
|
The encapsulated command can only be performed if the security status of
|
|
the smart card satisfies the security attributes of the elementary file
|
|
being processed.
|
|
|
|
When the command contains a valid short elementary identifier, it sets the
|
|
file as current elementary file. If another elementary file is currently
|
|
selected at the time of issuing this command, this command may be processed
|
|
without identification of the currently selected file.
|
|
|
|
If the encapsulated command applies to a linear-fixed or cyclic-structured
|
|
elementary file, it will abort if the record length is different from the
|
|
length of the existing record. If it applies to a linear-variable
|
|
structured elementary file, it may be carried out when the record length is
|
|
different from the length of the existing record.
|
|
|
|
If P2=xxxxx011 and the elementary file is cyclic file, this command has the
|
|
same behavior a command constructed using AppendRecord.
|
|
|
|
Elementary files without a record structure cannot be written to. The
|
|
constructed command aborts if applied to an elementary file without a
|
|
record structure.
|
|
|
|
Author:
|
|
|
|
Doug Barlow (dbarlow) 6/24/1999
|
|
|
|
--*/
|
|
#undef __SUBROUTINE__
|
|
#define __SUBROUTINE__ TEXT("CSCardISO7816::WriteRecord")
|
|
|
|
STDMETHODIMP
|
|
CSCardISO7816::WriteRecord(
|
|
/* [in] */ BYTE byRecordId,
|
|
/* [in] */ BYTE byRefCtrl,
|
|
/* [in] */ LPBYTEBUFFER pData,
|
|
/* [out][in] */ LPSCARDCMD __RPC_FAR *ppCmd)
|
|
{
|
|
HRESULT hReturn;
|
|
|
|
try
|
|
{
|
|
HRESULT hr;
|
|
|
|
if (NULL == *ppCmd)
|
|
{
|
|
*ppCmd = NewSCardCmd();
|
|
if (NULL == *ppCmd)
|
|
throw (HRESULT)E_OUTOFMEMORY;
|
|
}
|
|
|
|
hr = (*ppCmd)->BuildCmd(
|
|
m_bCla, // CLA
|
|
0xd2, // INS
|
|
byRecordId, // P1
|
|
byRefCtrl, // P2
|
|
pData,
|
|
NULL);
|
|
hReturn = hr;
|
|
}
|
|
|
|
catch (HRESULT hError)
|
|
{
|
|
hReturn = hError;
|
|
}
|
|
catch (...)
|
|
{
|
|
hReturn = E_INVALIDARG;
|
|
}
|
|
|
|
return hReturn;
|
|
}
|
|
|