|
|
//+-------------------------------------------------------------------------
//
// Microsoft Windows
//
// Copyright (C) Microsoft Corporation, 1998 - 1999
//
// File: ibm.cpp
//
//--------------------------------------------------------------------------
/*++
Module Name:
ibmmfc41.cpp
Abstract:
This is a plug-in for the smart card driver test suite. This plug-in is smart card dependent
Environment:
Win32 application
Revision History :
Jan 1998 - initial version
--*/
#include <stdarg.h>
#include <stdio.h>
#include <string.h>
#include <afx.h>
#include <afxtempl.h>
#include <winioctl.h>
#include <winsmcrd.h>
#include "ifdtest.h"
void MyCardEntry(class CCardProvider& in_CCardProvider);
//
// Create a card provider object
// Note: all global varibales and all functions have to be static
//
static class CCardProvider MyCard(MyCardEntry); static ULONG MyCardSetProtocol( class CCardProvider& in_CCardProvider, class CReader& in_CReader ) /*++
Routine Description: This function will be called after the card has been correctly identified. We should here set the protocol that we need for further transmissions
Arguments:
in_CCardProvider - ref. to our card provider object in_CReader - ref. to the reader object
Return Value:
IFDSTATUS_FAILED - we were unable to set the protocol correctly IFDSTATUS_SUCCESS - protocol set correctly
--*/ { ULONG l_lResult;
TestStart("Try to set incorrect protocol T=0"); l_lResult = in_CReader.SetProtocol(SCARD_PROTOCOL_T0);
// The test MUST fail with the incorrect protocol
TEST_CHECK_NOT_SUPPORTED("Set protocol failed", l_lResult); TestEnd();
// Now set the correct protocol
TestStart("Set protocol T=1"); l_lResult = in_CReader.SetProtocol(SCARD_PROTOCOL_T1); TEST_CHECK_SUCCESS("Set protocol failed", l_lResult); TestEnd();
if (l_lResult != ERROR_SUCCESS) {
return IFDSTATUS_FAILED; }
return IFDSTATUS_SUCCESS; }
static ULONG MyCardTest( class CCardProvider& in_CCardProvider, class CReader& in_CReader ) /*++
Routine Description: This serves as the test function for a particular smart card
Arguments:
in_CReader - ref. to class that provides all information for the test
Return Value:
IFDSTATUS value
--*/ { ULONG l_lResult; ULONG l_uResultLength, l_uExpectedLength, l_uIndex; PUCHAR l_pchResult; UCHAR l_rgchBuffer[512], l_rgchBuffer2[512];
switch (in_CCardProvider.GetTestNo()) {
case 1: { //
// select a file 0007 and write data pattern 0 to N-1 to the card.
// Then read the data back and verify correctness.
// Check IFSC and IFSD above card limits
//
//
// Select a file
//
TestStart("SELECT FILE 0007");
l_lResult = in_CReader.Transmit( (PUCHAR) "\xa4\xa4\x00\x00\x02\x00\x07", 7, &l_pchResult, &l_uResultLength );
TestCheck( l_lResult, "==", ERROR_SUCCESS, l_uResultLength, 16, l_pchResult[14], l_pchResult[15], 0x90, 0x00, l_pchResult, (PUCHAR) "\x63\x0c\x03\xe8\x00\x07\x00\x00\x00\xff\xff\x11\x01\x00\x90\x00", l_uResultLength );
TEST_END();
if (TestFailed()) { return IFDSTATUS_FAILED; }
//
// Do a couple of writes and reads up to maximum size
// Check behaviour above IFSC and IFSD Limits
//
//
// Generate a 'test' pattern which will be written to the card
//
for (l_uIndex = 0; l_uIndex < 254; l_uIndex++) {
l_rgchBuffer[5 + l_uIndex] = (UCHAR) l_uIndex; }
//
// This is the amount of bytes we write to the card in each loop
//
ULONG l_auNumBytes[] = { 1 , 25, 50, 75, 100, 125, 128, 150, 175, 200, 225, 250, 254 }; time_t l_TimeStart; time(&l_TimeStart);
for (ULONG l_uTest = 0; l_uTest < sizeof(l_auNumBytes) / sizeof(l_auNumBytes[0]); l_uTest++) {
ULONG l_uNumBytes = l_auNumBytes[l_uTest]; //
// Write
//
TestStart("WRITE BINARY %3d Byte(s)", l_uNumBytes); //
// Tpdu for write binary
//
memcpy(l_rgchBuffer, "\xa4\xd6\x00\x00", 4);
//
// Append number of bytes (note: the buffer contains the pattern already)
//
l_rgchBuffer[4] = (UCHAR) l_uNumBytes;
l_lResult = in_CReader.Transmit( l_rgchBuffer, 5 + l_uNumBytes, &l_pchResult, &l_uResultLength );
if (l_uNumBytes <= 128) {
TestCheck( l_lResult, "==", ERROR_SUCCESS, l_uResultLength, 2, l_pchResult[0], l_pchResult[1], 0x90, 0x00, NULL, NULL, NULL );
} else { TestCheck( l_lResult, "==", ERROR_SUCCESS, l_uResultLength, 2, l_pchResult[0], l_pchResult[1], 0x67, 0x00, NULL, NULL, NULL ); }
TEST_END();
//
// Read
//
TestStart("READ BINARY %3d Byte(s)", l_uNumBytes);
//
// tpdu for read binary
//
memcpy(l_rgchBuffer, "\xa4\xB0\x00\x00", 4);
//
// Append number of bytes
//
l_rgchBuffer[4] = (UCHAR) l_uNumBytes;
l_lResult = in_CReader.Transmit( l_rgchBuffer, 5, &l_pchResult, &l_uResultLength );
//
// check if the right number of bytes has been returned
//
l_uExpectedLength = min(128, l_uNumBytes);
TestCheck( l_lResult, "==", ERROR_SUCCESS, l_uResultLength, l_uExpectedLength + 2, l_pchResult[l_uExpectedLength], l_pchResult[l_uExpectedLength + 1], 0x90, 0x00, l_pchResult, l_rgchBuffer + 5, l_uExpectedLength );
TEST_END(); }
time_t l_TimeEnd; time(&l_TimeEnd); CTime l_CTimeStart(l_TimeStart); CTime l_CTimeEnd(l_TimeEnd); CTimeSpan l_CTimeElapsed = l_CTimeEnd - l_CTimeStart; if (l_CTimeElapsed.GetTotalSeconds() < 10) {
LogMessage( "Reader performance is good (%u sec)", l_CTimeElapsed.GetTotalSeconds() ); } else if (l_CTimeElapsed.GetTotalSeconds() < 30) {
LogMessage( "Reader performance is average (%u sec)", l_CTimeElapsed.GetTotalSeconds() ); } else {
LogMessage( "Reader performance is bad (%u sec)", l_CTimeElapsed.GetTotalSeconds() ); } break; }
case 2: { //
// Select a file 0007 and write alternately pattern 55 and AA
// to the card.
// Read the data back and verify correctness after each write.
//
//
// Select a file
//
TestStart("SELECT FILE 0007");
l_lResult = in_CReader.Transmit( (PUCHAR) "\xa4\xa4\x00\x00\x02\x00\x07", 7, &l_pchResult, &l_uResultLength );
TestCheck( l_lResult, "==", ERROR_SUCCESS, l_uResultLength, 16, l_pchResult[14], l_pchResult[15], 0x90, 0x00, l_pchResult, (PUCHAR) "\x63\x0c\x03\xe8\x00\x07\x00\x00\x00\xff\xff\x11\x01\x00\x90\x00", l_uResultLength );
TEST_END(); //
// Do a couple of writes and reads alternately
// with patterns 55h and AAh
//
//
// Generate a 'test' pattern which will be written to the card
//
for (l_uIndex = 0; l_uIndex < 254; l_uIndex++) {
l_rgchBuffer[5 + l_uIndex] = (UCHAR) 0x55; l_rgchBuffer2[5 + l_uIndex] = (UCHAR) 0xAA; }
//
// This is the amount of bytes we write to the card in each loop
//
ULONG l_uNumBytes = 128;
for (ULONG l_uTest = 0; l_uTest < 2; l_uTest++) {
//
// Write
//
TestStart("WRITE BINARY %3d Byte(s) Pattern 55h", l_uNumBytes); //
// Tpdu for write binary
//
memcpy(l_rgchBuffer, "\xa4\xd6\x00\x00", 4);
//
// Append number of bytes (note: the buffer contains the pattern already)
//
l_rgchBuffer[4] = (UCHAR) l_uNumBytes;
l_lResult = in_CReader.Transmit( l_rgchBuffer, 5 + l_uNumBytes, &l_pchResult, &l_uResultLength );
TestCheck( l_lResult, "==", ERROR_SUCCESS, l_uResultLength, 2, l_pchResult[0], l_pchResult[1], 0x90, 0x00, NULL, NULL, NULL );
TEST_END();
//
// Read
//
TestStart("READ BINARY %3d Byte(s) Pattern 55h", l_uNumBytes);
//
// tpdu for read binary
//
memcpy(l_rgchBuffer, "\xa4\xB0\x00\x00", 4);
//
// Append number of bytes
//
l_rgchBuffer[4] = (UCHAR) l_uNumBytes;
l_lResult = in_CReader.Transmit( l_rgchBuffer, 5, &l_pchResult, &l_uResultLength );
l_uExpectedLength = min(128, l_uNumBytes);
TestCheck( l_lResult, "==", ERROR_SUCCESS, l_uResultLength, l_uExpectedLength + 2, l_pchResult[l_uNumBytes], l_pchResult[l_uNumBytes + 1], 0x90, 0x00, l_pchResult, l_rgchBuffer + 5, l_uExpectedLength );
TEST_END();
//
// Write
//
TestStart("WRITE BINARY %3d Byte(s) Pattern AAh", l_uNumBytes); //
// Tpdu for write binary
//
memcpy(l_rgchBuffer2, "\xa4\xd6\x00\x00", 4);
//
// Append number of bytes (note: the buffer contains the pattern already)
//
l_rgchBuffer2[4] = (UCHAR) l_uNumBytes;
l_lResult = in_CReader.Transmit( l_rgchBuffer2, 5 + l_uNumBytes, &l_pchResult, &l_uResultLength );
TestCheck( l_lResult, "==", ERROR_SUCCESS, l_uResultLength, 2, l_pchResult[0], l_pchResult[1], 0x90, 0x00, NULL, NULL, NULL );
TEST_END();
//
// Read
//
TestStart("READ BINARY %3d Byte(s) Pattern AAh", l_uNumBytes);
//
// tpdu for read binary
//
memcpy(l_rgchBuffer2, "\xa4\xB0\x00\x00", 4);
//
// Append number of bytes
//
l_rgchBuffer2[4] = (UCHAR) l_uNumBytes;
l_lResult = in_CReader.Transmit( l_rgchBuffer2, 5, &l_pchResult, &l_uResultLength );
l_uExpectedLength = min(128, l_uNumBytes);
TestCheck( l_lResult, "==", ERROR_SUCCESS, l_uResultLength, l_uExpectedLength + 2, l_pchResult[l_uNumBytes], l_pchResult[l_uNumBytes + 1], 0x90, 0x00, l_pchResult, l_rgchBuffer2 + 5, min(l_uExpectedLength,125) );
TEST_END(); }
break; }
case 3: { // select a file 0007 and write alternately pattern 00 and FF
// to the card.
// Read the data back and verify correctness after each write.
//
// Select a file
//
TestStart("SELECT FILE 0007");
l_lResult = in_CReader.Transmit( (PUCHAR) "\xa4\xa4\x00\x00\x02\x00\x07", 7, &l_pchResult, &l_uResultLength );
TestCheck( l_lResult, "==", ERROR_SUCCESS, l_uResultLength, 16, l_pchResult[14], l_pchResult[15], 0x90, 0x00, l_pchResult, (PUCHAR) "\x63\x0c\x03\xe8\x00\x07\x00\x00\x00\xff\xff\x11\x01\x00\x90\x00", l_uResultLength );
TEST_END();
//
// Do a couple of writes and reads alternately
// with patterns 00h and FFh
//
//
// Generate a 'test' pattern which will be written to the card
//
for (l_uIndex = 0; l_uIndex < 254; l_uIndex++) {
l_rgchBuffer[5 + l_uIndex] = (UCHAR) 0x00; l_rgchBuffer2[5 + l_uIndex] = (UCHAR) 0xFF; }
//
// This is the amount of bytes we write to the card in each loop
//
ULONG l_uNumBytes = 128;
for (ULONG l_uTest = 0; l_uTest < 2; l_uTest++) {
//
// Write
//
TestStart("WRITE BINARY %3d Byte(s) Pattern 00h", l_uNumBytes); //
// Tpdu for write binary
//
memcpy(l_rgchBuffer, "\xa4\xd6\x00\x00", 4);
//
// Append number of bytes (note: the buffer contains the pattern already)
//
l_rgchBuffer[4] = (UCHAR) l_uNumBytes;
l_lResult = in_CReader.Transmit( l_rgchBuffer, 5 + l_uNumBytes, &l_pchResult, &l_uResultLength );
TestCheck( l_lResult, "==", ERROR_SUCCESS, l_uResultLength, 2, l_pchResult[0], l_pchResult[1], 0x90, 0x00, NULL, NULL, NULL );
TEST_END();
//
// Read
//
TestStart("READ BINARY %3d Byte(s) Pattern 00h", l_uNumBytes);
//
// tpdu for read binary
//
memcpy(l_rgchBuffer, "\xa4\xB0\x00\x00", 4);
//
// Append number of bytes
//
l_rgchBuffer[4] = (UCHAR) l_uNumBytes;
l_lResult = in_CReader.Transmit( l_rgchBuffer, 5, &l_pchResult, &l_uResultLength );
l_uExpectedLength = min(128, l_uNumBytes);
TestCheck( l_lResult, "==", ERROR_SUCCESS, l_uResultLength, l_uExpectedLength + 2, l_pchResult[l_uNumBytes], l_pchResult[l_uNumBytes + 1], 0x90, 0x00, l_pchResult, l_rgchBuffer + 5, l_uExpectedLength );
TEST_END();
//
// Write
//
TestStart("WRITE BINARY %3d Byte(s) Pattern FFh", l_uNumBytes); //
// Tpdu for write binary
//
memcpy(l_rgchBuffer2, "\xa4\xd6\x00\x00", 4);
//
// Append number of bytes (note: the buffer contains the pattern already)
//
l_rgchBuffer2[4] = (UCHAR) l_uNumBytes;
l_lResult = in_CReader.Transmit( l_rgchBuffer2, 5 + l_uNumBytes, &l_pchResult, &l_uResultLength );
TestCheck( l_lResult, "==", ERROR_SUCCESS, l_uResultLength, 2, l_pchResult[0], l_pchResult[1], 0x90, 0x00, NULL, NULL, NULL );
TEST_END();
//
// Read
//
TestStart("READ BINARY %3d Byte(s) Pattern FFh", l_uNumBytes);
//
// tpdu for read binary
//
memcpy(l_rgchBuffer2, "\xa4\xB0\x00\x00", 4);
//
// Append number of bytes
//
l_rgchBuffer2[4] = (UCHAR) l_uNumBytes;
l_lResult = in_CReader.Transmit( l_rgchBuffer2, 5, &l_pchResult, &l_uResultLength );
l_uExpectedLength = min(128, l_uNumBytes);
TestCheck( l_lResult, "==", ERROR_SUCCESS, l_uResultLength, l_uExpectedLength + 2, l_pchResult[l_uNumBytes], l_pchResult[l_uNumBytes + 1], 0x90, 0x00, l_pchResult, l_rgchBuffer2 + 5, min(l_uExpectedLength,125) );
TEST_END(); } break; }
case 4: { //
// Select Command for Nonexisting File
//
TestStart("SELECT NONEXISTING FILE");
l_lResult = in_CReader.Transmit( (PUCHAR) "\xa4\xa4\x00\x00\x02\x77\x77", 7, &l_pchResult, &l_uResultLength );
TestCheck( l_lResult, "==", ERROR_SUCCESS, l_uResultLength, 2, l_pchResult[0], l_pchResult[1], 0x94, 0x04, NULL, NULL, NULL );
TEST_END(); break; }
case 5: { //
// Select Command without Fileid
//
TestStart("SELECT COMMAND WITHOUT FILEID");
l_lResult = in_CReader.Transmit( (PUCHAR) "\xa4\xa4\x00\x00", 4, &l_pchResult, &l_uResultLength );
TestCheck( l_lResult, "==", ERROR_SUCCESS, l_uResultLength, 2, l_pchResult[0], l_pchResult[1], 0x67, 0x00, NULL, NULL, NULL );
TEST_END(); break; }
case 6: { //
// Select Command with path too short
//
TestStart("SELECT COMMAND PATH WITH PATH TOO SHORT");
l_lResult = in_CReader.Transmit( (PUCHAR) "\xa4\xa4\x00\x00\x01\x77", 6, &l_pchResult, &l_uResultLength );
TestCheck( l_lResult, "==", ERROR_SUCCESS, l_uResultLength, 2, l_pchResult[0], l_pchResult[1], 0x67, 0x00, NULL, NULL, NULL );
TEST_END(); break; }
case 7: { //
// Select Command with wrong Lc
//
TestStart("SELECT COMMAND PATH WITH WRONG LC");
l_lResult = in_CReader.Transmit( (PUCHAR) "\xa4\xa4\x00\x00\x08\x00", 6, &l_pchResult, &l_uResultLength );
TestCheck( l_lResult, "==", ERROR_SUCCESS, l_uResultLength, 2, l_pchResult[0], l_pchResult[1], 0x67, 0x00, NULL, NULL, NULL );
TEST_END(); break; }
case 8: { //
// Select Command too short
//
TestStart("SELECT COMMAND TOO SHORT");
l_lResult = in_CReader.Transmit( (PUCHAR) "\xa4\xa4\x00", 3, &l_pchResult, &l_uResultLength );
TestCheck( l_lResult, "==", ERROR_SUCCESS, l_uResultLength, 2, l_pchResult[0], l_pchResult[1], 0x6f, 0x00, NULL, NULL, NULL );
TEST_END(); break; }
case 9: { //
// Select Command with invalid P2
//
TestStart("SELECT COMMAND WITH INVALID P2");
l_lResult = in_CReader.Transmit( (PUCHAR) "\xa4\xa4\x00\x02\x02\x00\x07", 7, &l_pchResult, &l_uResultLength );
TestCheck( l_lResult, "==", ERROR_SUCCESS, l_uResultLength, 2, l_pchResult[0], l_pchResult[1], 0x6b, 0x00, NULL, NULL, NULL );
TEST_END(); break; }
case 10: { //
// Select command without fileid but with Le
//
TestStart("SELECT COMMAND WITHOUT FILEID BUT WITH Le");
l_lResult = in_CReader.Transmit( (PUCHAR) "\xa4\xa4\x00\x00\x00", 5, &l_pchResult, &l_uResultLength );
TestCheck( l_lResult, "==", ERROR_SUCCESS, l_uResultLength, 2, l_pchResult[0], l_pchResult[1], 0x67, 0x00, NULL, NULL, NULL );
TEST_END(); break; }
case 11: { //
// Use Change Speed command to simulate unresponsive card
//
//
// Select a file
//
TestStart("SELECT FILE 0007");
l_lResult = in_CReader.Transmit( (PUCHAR) "\xa4\xa4\x00\x00\x02\x00\x07", 7, &l_pchResult, &l_uResultLength );
TestCheck( l_lResult, "==", ERROR_SUCCESS, l_uResultLength, 16, l_pchResult[14], l_pchResult[15], 0x90, 0x00, l_pchResult, (PUCHAR) "\x63\x0c\x03\xe8\x00\x07\x00\x00\x00\xff\xff\x11\x01\x00\x90\x00", l_uResultLength );
TEST_END();
//
// Perform change speed command to simulate unresponsive card
//
TestStart("CHANGE SPEED");
l_lResult = in_CReader.Transmit( (PUCHAR) "\xb6\x42\x00\x40", 4, &l_pchResult, &l_uResultLength );
TestCheck( l_lResult, "==", ERROR_SUCCESS, l_uResultLength, 2, l_pchResult[0], l_pchResult[1], 0x90, 0x00, NULL, NULL, NULL );
TEST_END();
//
// Select a file to verify bad return code
//
TestStart("SELECT FILE 0007 WILL GET NO VALID RESPONSE");
l_lResult = in_CReader.Transmit( (PUCHAR) "\xa4\xa4\x00\x00\x02\x00\x07", 7, &l_pchResult, &l_uResultLength );
TestCheck( l_lResult, "!=", ERROR_SUCCESS, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL );
TEST_END(); return IFDSTATUS_END; }
default: return IFDSTATUS_FAILED; } return IFDSTATUS_SUCCESS; }
static void MyCardEntry( class CCardProvider& in_CCardProvider ) /*++
Routine Description: This function registers all callbacks from the test suite Arguments:
CCardProvider - ref. to card provider class
Return Value:
-
--*/ { // Set protocol callback
in_CCardProvider.SetProtocol(MyCardSetProtocol);
// Card test callback
in_CCardProvider.SetCardTest(MyCardTest);
// Name of our card
in_CCardProvider.SetCardName("IBM");
in_CCardProvider.SetAtr((PBYTE) "\x3b\xef\x00\xff\x81\x31\x86\x45\x49\x42\x4d\x20\x4d\x46\x43\x34\x30\x30\x30\x30\x38\x33\x31\x43", 24); }
|