atrhandler.c

Go to the documentation of this file.
00001 /*
00002  * MUSCLE SmartCard Development ( http://www.linuxnet.com )
00003  *
00004  * Copyright (C) 1999-2004
00005  *  David Corcoran <corcoran@linuxnet.com>
00006  *  Ludovic Rousseau <ludovic.rousseau@free.fr>
00007  *
00008  * $Id: atrhandler.c 2891 2008-04-21 13:14:46Z rousseau $
00009  */
00010 
00021 #include "config.h"
00022 #include <syslog.h>
00023 #include <string.h>
00024 
00025 #include "misc.h"
00026 #include "pcsclite.h"
00027 #include "debuglog.h"
00028 #include "atrhandler.h"
00029 
00034 /* #define ATR_DEBUG */
00035 
00044 short ATRDecodeAtr(PSMARTCARD_EXTENSION psExtension,
00045     PUCHAR pucAtr, DWORD dwLength)
00046 {
00047     USHORT p;
00048     UCHAR K, TCK;               /* MSN of T0/Check Sum */
00049     UCHAR Y1i, T;               /* MSN/LSN of TDi */
00050     int i = 1;                  /* value of the index in TAi, TBi, etc. */
00051 
00052     /*
00053      * Zero out everything
00054      */
00055     p = K = TCK = Y1i = T = 0;
00056 
00057 #ifdef ATR_DEBUG
00058     if (dwLength > 0)
00059         LogXxd(PCSC_LOG_DEBUG, "ATR: ", pucAtr, dwLength);
00060 #endif
00061 
00062     if (dwLength < 2)
00063         return 0;   
00065     /*
00066      * Zero out the bitmasks
00067      */
00068     psExtension->CardCapabilities.AvailableProtocols = SCARD_PROTOCOL_UNDEFINED;
00069     psExtension->CardCapabilities.CurrentProtocol = SCARD_PROTOCOL_UNDEFINED;
00070 
00071     /*
00072      * Decode the TS byte
00073      */
00074     if (pucAtr[0] == 0x3F)
00075     {   /* Inverse convention used */
00076         psExtension->CardCapabilities.Convention = SCARD_CONVENTION_INVERSE;
00077     }
00078     else
00079         if (pucAtr[0] == 0x3B)
00080         {   /* Direct convention used */
00081             psExtension->CardCapabilities.Convention = SCARD_CONVENTION_DIRECT;
00082         }
00083         else
00084         {
00085             memset(psExtension, 0x00, sizeof(SMARTCARD_EXTENSION));
00086             return 0;   
00087         }
00088 
00089     /*
00090      * Here comes the platform dependant stuff
00091      */
00092 
00093     /*
00094      * Decode the T0 byte
00095      */
00096     Y1i = pucAtr[1] >> 4;   /* Get the MSN in Y1 */
00097     K = pucAtr[1] & 0x0F;   /* Get the LSN in K */
00098 
00099     p = 2;
00100 
00101 #ifdef ATR_DEBUG
00102     Log4(PCSC_LOG_DEBUG, "Conv: %02X, Y1: %02X, K: %02X",
00103         psExtension->CardCapabilities.Convention, Y1i, K);
00104 #endif
00105 
00106     /*
00107      * Examine Y1
00108      */
00109     do
00110     {
00111         short TAi, TBi, TCi, TDi;   /* Interface characters */
00112 
00113         TAi = (Y1i & 0x01) ? pucAtr[p++] : -1;
00114         TBi = (Y1i & 0x02) ? pucAtr[p++] : -1;
00115         TCi = (Y1i & 0x04) ? pucAtr[p++] : -1;
00116         TDi = (Y1i & 0x08) ? pucAtr[p++] : -1;
00117 
00118 #ifdef ATR_DEBUG
00119         Log9(PCSC_LOG_DEBUG,
00120             "TA%d: %02X, TB%d: %02X, TC%d: %02X, TD%d: %02X",
00121             i, TAi, i, TBi, i, TCi, i, TDi);
00122 #endif
00123 
00124         /*
00125          * Examine TDi to determine protocol and more
00126          */
00127         if (TDi >= 0)
00128         {
00129             Y1i = TDi >> 4; /* Get the MSN in Y1 */
00130             T = TDi & 0x0F; /* Get the LSN in K */
00131 
00132             /*
00133              * Set the current protocol TD1 (first TD only)
00134              */
00135             if (psExtension->CardCapabilities.CurrentProtocol == SCARD_PROTOCOL_UNDEFINED)
00136             {
00137                 switch (T)
00138                 {
00139                     case 0:
00140                         psExtension->CardCapabilities.CurrentProtocol =
00141                             SCARD_PROTOCOL_T0;
00142                         break;
00143                     case 1:
00144                         psExtension->CardCapabilities.CurrentProtocol =
00145                             SCARD_PROTOCOL_T1;
00146                         break;
00147                     default:
00148                         return 0; 
00149                 }
00150             }
00151 
00152 #ifdef ATR_DEBUG
00153             Log2(PCSC_LOG_DEBUG, "T=%d Protocol Found", T);
00154 #endif
00155             if (0 == T)
00156             {
00157                 psExtension->CardCapabilities.AvailableProtocols |=
00158                     SCARD_PROTOCOL_T0;
00159             }
00160             else
00161                 if (1 == T)
00162                 {
00163                     psExtension->CardCapabilities.AvailableProtocols |=
00164                         SCARD_PROTOCOL_T1;
00165                 }
00166                 else
00167                     if (15 == T)
00168                     {
00169                         psExtension->CardCapabilities.AvailableProtocols |=
00170                             SCARD_PROTOCOL_T15;
00171                     }
00172                     else
00173                     {
00174                         /*
00175                          * Do nothing for now since other protocols are not
00176                          * supported at this time
00177                          */
00178                     }
00179 
00180             /* test presence of TA2 */
00181             if ((2 == i) && (TAi >= 0))
00182             {
00183                 T = TAi & 0x0F;
00184 #ifdef ATR_DEBUG
00185                 Log2(PCSC_LOG_DEBUG, "Specific mode: T=%d", T);
00186 #endif
00187                 switch (T)
00188                 {
00189                     case 0:
00190                         psExtension->CardCapabilities.CurrentProtocol =
00191                             psExtension->CardCapabilities.AvailableProtocols =
00192                             SCARD_PROTOCOL_T0;
00193                         break;
00194 
00195                     case 1:
00196                         psExtension->CardCapabilities.CurrentProtocol =
00197                             psExtension->CardCapabilities.AvailableProtocols =
00198                             SCARD_PROTOCOL_T1;
00199                         break;
00200 
00201                     default:
00202                         return 0; 
00203                 }
00204             }
00205         } else
00206             Y1i = 0;
00207 
00208         if (p > MAX_ATR_SIZE)
00209         {
00210             memset(psExtension, 0x00, sizeof(SMARTCARD_EXTENSION));
00211             return 0;   
00212         }
00213 
00214         /* next interface characters index */
00215         i++;
00216     }
00217     while (Y1i != 0);
00218 
00219     /*
00220      * If TDx is not set then the current must be T0
00221      */
00222     if (psExtension->CardCapabilities.CurrentProtocol == SCARD_PROTOCOL_UNDEFINED)
00223     {
00224         psExtension->CardCapabilities.CurrentProtocol = SCARD_PROTOCOL_T0;
00225         psExtension->CardCapabilities.AvailableProtocols |= SCARD_PROTOCOL_T0;
00226     }
00227 
00228     /*
00229      * Take care of the historical characters
00230      */
00231     psExtension->ATR.HistoryLength = K;
00232     memcpy(psExtension->ATR.HistoryValue, &pucAtr[p], K);
00233 
00234     p = p + K;
00235 
00236     /*
00237      * Check to see if TCK character is included It will be included if
00238      * more than T=0 is supported
00239      */
00240     if (psExtension->CardCapabilities.AvailableProtocols & SCARD_PROTOCOL_T1)
00241         TCK = pucAtr[p++];
00242 
00243     memcpy(psExtension->ATR.Value, pucAtr, p);
00244     psExtension->ATR.Length = p;    /* modified from p-1 */
00245 
00246 #ifdef ATR_DEBUG
00247     Log3(PCSC_LOG_DEBUG, "CurrentProtocol: %d, AvailableProtocols: %d",
00248         psExtension->CardCapabilities.CurrentProtocol,
00249         psExtension->CardCapabilities.AvailableProtocols);
00250 #endif
00251 
00252     return 1; 
00253 }
00254 

Generated on Thu Aug 28 20:14:13 2008 for pcsc-lite by  doxygen 1.5.6