生成 ISO7816-4 APDU 命令

若要向服务提供商添加功能,需要了解如何在基本服务提供商 DLL 中生成 ISO7816-4 应用程序协议数据单元 (APDU) 。 以下过程简要概述了生成过程。

注意

此处包含的示例不一定完整;有关详细信息,请参阅示例应用程序和 DLL。

 

生成 ISO7816-4 APDU 命令

  1. 创建 ISCardCmd 对象和 ISCardISO7816 对象。

    //  Create an ISCardCmd object.
    HRESULT hresult = CoCreateInstance(CLSID_CSCardCmd,
                               NULL,
                               CLSCTX_ALL,
                               IID_ISCardCmd,
                               (LPVOID*) &g_pISCardCmd);
    //  Create an ISCardISO7816 object.
    HRESULT hresult = CoCreateInstance(CLSID_CSCardISO7816,
                               NULL,
                               CLSCTX_ALL,
                               IID_ISCardISO7816,
                               (LPVOID*) &g_pISCardISO7816);
    

    ISCardCmd 接口包含两个 IByteBuffer 缓冲区。 一个缓冲区包含实际的 APDU 命令字符串 (以及要随命令) 发送的任何数据。 另一个包含命令执行后卡返回的任何回复信息。

  2. 使用这些对象创建有效的 ISO7816-4 命令,如下所示:

    //  Do challenge.
    HRESULT hresult = g_pISCardISO7816->GetChallenge(dwLengthOfChallenge,
                                             &g_pISCardCmd);
    

    下面是 GetChallenge 方法中使用的代码:

    #include <windows.h>
    
    STDMETHODIMP CSCardISO7816::GetChallenge(IN DWORD dwBytesExpected /*= 0*/,
                                IN OUT LPSCARDCMD *ppCmd)
    {
        //  Locals.
        HRESULT hr = S_OK;
    
        try
        {
            //  Is the ISCardCmd object okay?
            hr = IsSCardCmdValid(ppCmd);
            if (FAILED(hr))
                throw (hr);
    
            //  Do it.
            hr = (*ppCmd)->BuildCmd(m_byClassId,
                                    (BYTE) INS_GET_CHALLENGE,
                                    (BYTE) INS_NULL,  // P1 = 0x00
                                    (BYTE) INS_NULL,  // P2 = 0x00
                                    NULL,
                                    &dwBytesExpected);
            if (FAILED(hr))
                throw (hr);
        }
    }
    

    ISCardISO7816::GetChallenge 方法使用 ISCardCmd::BuildCmd 方法生成请求的 APDU。 这是通过在以下语句中将相应信息写入 ISCardCmd APDU 缓冲区来完成的:

    hr = (*ppCmd)->BuildCmd;
    
  3. 使用生成的 ISCardCmd 对象,使用卡执行事务,解释结果并继续。

扩展到 ISO7816-4 之外

扩展上述服务提供程序生成/执行过程的建议方法是创建新的 COM 对象。 此 COM 对象应支持允许创建非 ISO7816-4 命令的新接口,并应聚合 ISCardISO7816 接口。

生成 ISO7816-4 APDU 命令的示例

以下示例演示上述过程中使用的代码。

//  Create an ISCardCmd object.
hresult = CoCreateInstance(CLSID_CSCardCmd,
                           NULL,
                           CLSCTX_ALL,
                           IID_ISCardCmd,
                           (LPVOID*) &g_pISCardCmd);
//  Create an ISCardISO7816 object.
hresult = CoCreateInstance(CLSID_CSCardISO7816,
                           NULL,
                           CLSCTX_ALL,
                           IID_ISCardISO7816,
                           (LPVOID*) &g_pISCardISO7816);
//  Do challenge.
hresult = g_pISCardISO7816->GetChallenge(dwLengthOfChallenge,
                                         &g_pISCardCmd);

STDMETHODIMP
CSCardISO7816::GetChallenge(IN DWORD dwBytesExpected /*= 0*/,
                            IN OUT LPSCARDCMD *ppCmd)
{
    //  Locals.
    HRESULT hr = S_OK;
    
    try
    {
        //  Is the ISCardCmd object okay?
        hr = IsSCardCmdValid(ppCmd);
        if (FAILED(hr))
            throw (hr);

        //  Do it.
        hr = (*ppCmd)->BuildCmd(m_byClassId,
                                (BYTE) INS_GET_CHALLENGE,
                                (BYTE) INS_NULL,  // P1 = 0x00
                                (BYTE) INS_NULL,  // P2 = 0x00
                                NULL,
                                &dwBytesExpected);
        if (FAILED(hr))
            throw (hr);
    }
}