📄 sci_prot.c
字号:
/*----------------------------------------------------------------------------+| This source code has been made available to you by IBM on an AS-IS| basis. Anyone receiving this source is licensed under IBM| copyrights to use it in any way he or she deems fit, including| copying it, modifying it, compiling it, and redistributing it either| with or without modifications. No license under IBM patents or| patent applications is to be implied by the copyright license.|| Any user of this software should understand that IBM cannot provide| technical support for this software and will not be responsible for| any consequences resulting from the use of this software.|| Any person who transfers this source code or any derivative work| must include the IBM copyright notice, this paragraph, and the| preceding two paragraphs in the transferred software.|| COPYRIGHT I B M CORPORATION 2001| LICENSED MATERIAL - PROGRAM PROPERTY OF I B M+----------------------------------------------------------------------------*//*----------------------------------------------------------------------------+| Author: Mike Lepore| Component: sci| File: sci_prot.c| Purpose: Smart Card protocol layer functions for the Smart Card.| Changes:|| Date: Author Comment:| ---------- ---------------- -----------------------------------------------| 03/22/2001 MAL Initial check-in.| 03/26/2001 Zongwei Liu Port to Linux| 09/26/2001 Zongwei Liu Port to pallas| 10/10/2001 Zongwei Liu Port to OS-Adaption layer| 12/03/2001 MAL, Zongwei Liu Fixed error handling bug in sc_apdu() by adding | check_incoming_data(). This fixed incorrect receive length| occurring when card responds with a two byte error-code| instead of the expected number of bytes. Also fixed error| handling problem in sc_t1_command(). Improved data handling| efficiency in sc_t0_command().+----------------------------------------------------------------------------*/#include <stdio.h>#include <fcntl.h>#include <stdio.h>#include <string.h>#include <errno.h>#include <linux/ioctl.h>#include "sci/sci_inf.h"#include "sc.h"#include "sci_prot.h"static SC_CONTROL_BLOCK sc_cb[SCI_NUMBER_OF_CONTROLLERS];/* tables from ISO/IEC 7816 */static unsigned long Fi_TABLE[] = { 372, 372, 558, 744, 1116, 1488, 1860, RFU, RFU, 512, 768, 1024, 1536, 2048, RFU, RFU};static unsigned long f_TABLE[] = { 4000000, 5000000, 6000000, 8000000, 12000000, 16000000, 20000000, RFU, RFU, 5000000, 7500000, 10000000, 15000000, 20000000, RFU, RFU};static unsigned long Di_TABLE[] = { RFU, 1, 2, 4, 8, 16, 32, RFU, 12, 20, RFU, RFU, RFU, RFU, RFU, RFU};extern int fd[2];static void check_incoming_data(unsigned char *buffer, unsigned long *length, unsigned char SW1, unsigned char SW2);/****************************************************************************** Function: sc_reset**** Purpose: Perform a reset, receive and process the ATR, and extract all** ATR parameters.**** Parameters: sc_id: zero-based number to identify smart card controller**** Returns: SCI_ERROR_OK: if successful** other error code if a failure occurs*****************************************************************************/SCI_ERROR sc_reset(unsigned long sc_id){ SCI_ERROR rc = SCI_ERROR_OK; SCI_PARAMETERS sci_parameters; I_BYTES p_ibyte[SC_MAX_ATR_SIZE]; I_BYTES *p_ibyter = 0; I_BYTES *p_ibytew = 0; unsigned long i = 0; unsigned long x = 0; unsigned long index = 0; ssize_t bytes_rec = 0; unsigned char current = 0; unsigned char lrc = 0; unsigned long Fi = 0; unsigned long Di = 0; unsigned long f = 0; unsigned long card_present; if (sc_id < SCI_NUMBER_OF_CONTROLLERS) { ioctl(fd[sc_id], IOCTL_GET_IS_CARD_PRESENT, &card_present); if (card_present == 1) { /* initialize protocol state */ sc_cb[sc_id].atr_size = 0; sc_cb[sc_id].p_historical = 0; sc_cb[sc_id].historical_size = 0; sc_cb[sc_id].TCK_present = 0; sc_cb[sc_id].firstT = SC_ATR_T; sc_cb[sc_id].currentT = SC_ATR_T; sc_cb[sc_id].NS = 0; sc_cb[sc_id].proposed_IFSD = SC_ATR_IFSD; sc_cb[sc_id].IFSD = SC_ATR_IFSD; /* set atr parameter defaults */ sc_cb[sc_id].sc_parameters.T = SC_ATR_T; sc_cb[sc_id].sc_parameters.maskT = SC_ATR_T; sc_cb[sc_id].sc_parameters.F = SC_ATR_FI; sc_cb[sc_id].sc_parameters.D = SC_ATR_DI; sc_cb[sc_id].sc_parameters.FI = SC_ATR_FI; sc_cb[sc_id].sc_parameters.DI = SC_ATR_DI; sc_cb[sc_id].sc_parameters.II = SC_ATR_II; sc_cb[sc_id].sc_parameters.PI1 = SC_ATR_PI1; sc_cb[sc_id].sc_parameters.PI2 = SC_ATR_PI2; sc_cb[sc_id].sc_parameters.WI = SC_ATR_WI; sc_cb[sc_id].sc_parameters.XI = SC_ATR_XI; sc_cb[sc_id].sc_parameters.UI = SC_ATR_UI; sc_cb[sc_id].sc_parameters.N = SC_ATR_N; sc_cb[sc_id].sc_parameters.CWI = SC_ATR_CWI; sc_cb[sc_id].sc_parameters.BWI = SC_ATR_BWI; sc_cb[sc_id].sc_parameters.IFSC = SC_ATR_IFSC; sc_cb[sc_id].sc_parameters.check = SC_ATR_CHECK; p_ibytew = p_ibyte; p_ibyter = p_ibyte; *p_ibytew = TS; p_ibytew++; if (ioctl(fd[sc_id], IOCTL_SET_RESET) == 0) { if (ioctl(fd[sc_id], IOCTL_GET_PARAMETERS, &sci_parameters) == 0) { while ((p_ibyter != p_ibytew) && (rc == SCI_ERROR_OK)) { /* read 1 ATR byte */ if ((rc = read(fd[sc_id], ¤t, 1)) > 0) { rc = SCI_ERROR_OK; sc_cb[sc_id].ATR[index] = current; index++; switch (*p_ibyter) { case TS: *p_ibytew = T0; p_ibytew++; break; case T0: /* save number of historical bytes */ sc_cb[sc_id].historical_size = (current & 0x0F); /* check for presence of TA(1) */ if ((current & 0x10) == 0x10) { *p_ibytew = TA; p_ibytew++; } /* check for presence of TB(1) */ if ((current & 0x20) == 0x20) { *p_ibytew = TB; p_ibytew++; } /* check for presence of TC(1) */ if ((current & 0x40) == 0x40) { *p_ibytew = TC; p_ibytew++; } /* check for presence of TD(1) */ if ((current & 0x80) == 0x80) { *p_ibytew = TD; p_ibytew++; } else { /* TD(1) is absent- protocol T='0' is the only offer */ sci_parameters.T = 0; sc_cb[sc_id].sc_parameters.T = 0; sc_cb[sc_id].sc_parameters.maskT = 1; /* push any TK's and TCK into queue */ for (x = 0; x < sc_cb[sc_id].historical_size; x++) { *p_ibytew = TK; p_ibytew++; } if (sc_cb[sc_id].sc_parameters. maskT != 1) { /* If T=0 isn't the only offer, a check byte is present */ *p_ibytew = TCK; p_ibytew++; } } i++; break; case TA: if (i == 1) { /* extract Fl and Dl from TA(1) to determine Fi, Di, and f */ sc_cb[sc_id].sc_parameters.FI = ((current & 0xF0) >> 4); sc_cb[sc_id].sc_parameters.DI = (current & 0x0F); Fi = Fi_TABLE[sc_cb[sc_id]. sc_parameters.FI]; Di = Di_TABLE[sc_cb[sc_id]. sc_parameters.DI]; f = f_TABLE[sc_cb[sc_id]. sc_parameters.FI]; } else if (i == 2) { /* check bit 5 of TA(2) */ if ((current & 0x10) == 0) { /* use Fi and Di from TA(1), if it is present */ if (f != 0) { sci_parameters.f = f; } if ((Fi != 0) && (Di != 0)) { sci_parameters.ETU = (Fi / Di); } /* card starts in specific mode using this protocol */ /* this overrides first offered protocol */ sci_parameters.T = (current & 0x0F); sc_cb[sc_id].sc_parameters.T = sci_parameters.T; sc_cb[sc_id].sc_parameters.F = sc_cb[sc_id].sc_parameters.FI; sc_cb[sc_id].sc_parameters.D = sc_cb[sc_id].sc_parameters.DI; } } else if (i > 2) { /* TD(i-1) must indicate T=1 for IFSC */ if (sc_cb[sc_id].currentT == 1) { /* 0x00 and 0xFF are RFU */ if ((current >= 0x01) && (current <= 0xFE)) { sc_cb[sc_id].sc_parameters. IFSC = current; } } /* check for global indication from TD(i-1) */ if (sc_cb[sc_id].currentT == 15) { /* check for class */ sc_cb[sc_id].sc_parameters.UI = (current & 0x3F); switch (sc_cb[sc_id]. sc_parameters.UI) { case 1: sci_parameters.U = SCI_CLASS_A; break; case 2: /* SCI is class A-only class A and AB cards allowed */ sci_parameters.U = SCI_CLASS_B; rc = SCI_ERROR_FAIL; // sci_deactivate(sc_id); ioctl(fd[sc_id], IOCTL_SET_DEACTIVATE); break; case 3: sci_parameters.U = SCI_CLASS_AB; break; } /* check for clock stop capabilities */ sc_cb[sc_id].sc_parameters.XI = ((current & 0xC0) >> 6); switch (sc_cb[sc_id]. sc_parameters.XI) { case 0: sci_parameters. clock_stop_polarity = SCI_CLOCK_STOP_DISABLED; break; case 1:
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -