1/* 2 atr.c 3 ISO 7816 ICC's answer to reset abstract data type implementation 4 5 This file is part of the Unix driver for Towitoko smartcard readers 6 Copyright (C) 2000 Carlos Prados <cprados@yahoo.com> 7 8 This library is free software; you can redistribute it and/or 9 modify it under the terms of the GNU Lesser General Public 10 License as published by the Free Software Foundation; either 11 version 2 of the License, or (at your option) any later version. 12 13 This library is distributed in the hope that it will be useful, 14 but WITHOUT ANY WARRANTY; without even the implied warranty of 15 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 16 Lesser General Public License for more details. 17 18 You should have received a copy of the GNU Lesser General Public License 19 along with this library; if not, write to the Free Software Foundation, 20 Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. 21*/ 22 23#include "atr.h" 24#include <stdlib.h> 25#include <string.h> 26#include "debug.h" 27 28/* 29 * Not exported variables definition 30 */ 31 32static unsigned 33atr_num_ib_table[16] = 34{ 35 0, 1, 1, 2, 1, 2, 2, 3, 1, 2, 2, 3, 2, 3, 3, 4 36}; 37 38/* 39 * Exported variables definition 40 */ 41 42static unsigned 43atr_f_table[16] = 44{ 45 372, 372, 558, 744, 1116, 1488, 1860, 0, 0, 512, 768, 1024, 1536, 2048, 0, 0 46}; 47 48static unsigned 49atr_d_table[16] = 50{ 51 0, 1, 2, 4, 8, 16, 32, 64, 12, 20, 0, 0, 0, 0, 0, 0 52}; 53 54static unsigned 55atr_i_table[4] = 56{ 57 25, 50, 100, 0 58}; 59 60/* 61 * Exported functions definition 62 */ 63 64int 65ATR_InitFromArray (ATR_t * atr, const BYTE atr_buffer[ATR_MAX_SIZE], unsigned length) 66{ 67 BYTE TDi; 68 unsigned pointer = 0, pn = 0; 69 70 /* Check size of buffer */ 71 if (length < 2) 72 return (ATR_MALFORMED); 73 74 /* Store T0 and TS */ 75 atr->TS = atr_buffer[0]; 76 77 atr->T0 = TDi = atr_buffer[1]; 78 pointer = 1; 79 80 /* Store number of historical bytes */ 81 atr->hbn = TDi & 0x0F; 82 83 /* TCK is not present by default */ 84 (atr->TCK).present = FALSE; 85 86 /* Extract interface bytes */ 87 while (pointer < length) 88 { 89 /* Check buffer is long enought */ 90 if (pointer + atr_num_ib_table[(0xF0 & TDi) >> 4] >= length) 91 { 92 return (ATR_MALFORMED); 93 } 94 /* Check TAi is present */ 95 if ((TDi | 0xEF) == 0xFF) 96 { 97 pointer++; 98 atr->ib[pn][ATR_INTERFACE_BYTE_TA].value = atr_buffer[pointer]; 99 atr->ib[pn][ATR_INTERFACE_BYTE_TA].present = TRUE; 100 } 101 else 102 atr->ib[pn][ATR_INTERFACE_BYTE_TA].present = FALSE; 103 /* Check TBi is present */ 104 if ((TDi | 0xDF) == 0xFF) 105 { 106 pointer++; 107 atr->ib[pn][ATR_INTERFACE_BYTE_TB].value = atr_buffer[pointer]; 108 atr->ib[pn][ATR_INTERFACE_BYTE_TB].present = TRUE; 109 } 110 else 111 atr->ib[pn][ATR_INTERFACE_BYTE_TB].present = FALSE; 112 113 /* Check TCi is present */ 114 if ((TDi | 0xBF) == 0xFF) 115 { 116 pointer++; 117 atr->ib[pn][ATR_INTERFACE_BYTE_TC].value = atr_buffer[pointer]; 118 atr->ib[pn][ATR_INTERFACE_BYTE_TC].present = TRUE; 119 } 120 else 121 atr->ib[pn][ATR_INTERFACE_BYTE_TC].present = FALSE; 122 123 /* Read TDi if present */ 124 if ((TDi | 0x7F) == 0xFF) 125 { 126 pointer++; 127 TDi = atr->ib[pn][ATR_INTERFACE_BYTE_TD].value = atr_buffer[pointer]; 128 atr->ib[pn][ATR_INTERFACE_BYTE_TD].present = TRUE; 129 (atr->TCK).present = ((TDi & 0x0F) != ATR_PROTOCOL_TYPE_T0); 130 pn++; 131 if (pn >= ATR_MAX_PROTOCOLS) 132 return (ATR_MALFORMED); 133 } 134 else 135 { 136 atr->ib[pn][ATR_INTERFACE_BYTE_TD].present = FALSE; 137 break; 138 } 139 } 140 141 /* Store number of protocols */ 142 atr->pn = pn + 1; 143 144 /* Store historical bytes */ 145 if (pointer + atr->hbn >= length) 146 return (ATR_MALFORMED); 147 148 memcpy (atr->hb, atr_buffer + pointer + 1, atr->hbn); 149 pointer += (atr->hbn); 150 151 /* Store TCK */ 152 if ((atr->TCK).present) 153 { 154 155 if (pointer + 1 >= length) 156 return (ATR_MALFORMED); 157 158 pointer++; 159 160 (atr->TCK).value = atr_buffer[pointer]; 161 } 162 163 atr->length = pointer + 1; 164 return (ATR_OK); 165} 166 167int 168ATR_GetConvention (ATR_t * atr, int *convention) 169{ 170 if (atr->TS == 0x3B) 171 (*convention) = ATR_CONVENTION_DIRECT; 172 else if (atr->TS == 0x3F) 173 (*convention) = ATR_CONVENTION_INVERSE; 174 else 175 return (ATR_MALFORMED); 176 return (ATR_OK); 177} 178 179int 180ATR_GetIntegerValue (ATR_t * atr, int name, BYTE * value) 181{ 182 int ret; 183 184 if (name == ATR_INTEGER_VALUE_FI) 185 { 186 if (atr->ib[0][ATR_INTERFACE_BYTE_TA].present) 187 { 188 (*value) = (atr->ib[0][ATR_INTERFACE_BYTE_TA].value & 0xF0) >> 4; 189 ret = ATR_OK; 190 } 191 else 192 ret = ATR_NOT_FOUND; 193 } 194 195 else if (name == ATR_INTEGER_VALUE_DI) 196 { 197 if (atr->ib[0][ATR_INTERFACE_BYTE_TA].present) 198 { 199 (*value) = (atr->ib[0][ATR_INTERFACE_BYTE_TA].value & 0x0F); 200 ret = ATR_OK; 201 } 202 else 203 ret = ATR_NOT_FOUND; 204 } 205 206 else if (name == ATR_INTEGER_VALUE_II) 207 { 208 if (atr->ib[0][ATR_INTERFACE_BYTE_TB].present) 209 { 210 (*value) = (atr->ib[0][ATR_INTERFACE_BYTE_TB].value & 0x60) >> 5; 211 ret = ATR_OK; 212 } 213 else 214 ret = ATR_NOT_FOUND; 215 } 216 217 else if (name == ATR_INTEGER_VALUE_PI1) 218 { 219 if (atr->ib[0][ATR_INTERFACE_BYTE_TB].present) 220 { 221 (*value) = (atr->ib[0][ATR_INTERFACE_BYTE_TB].value & 0x1F); 222 ret = ATR_OK; 223 } 224 else 225 ret = ATR_NOT_FOUND; 226 } 227 228 else if (name == ATR_INTEGER_VALUE_PI2) 229 { 230 if (atr->ib[1][ATR_INTERFACE_BYTE_TB].present) 231 { 232 (*value) = atr->ib[1][ATR_INTERFACE_BYTE_TB].value; 233 ret = ATR_OK; 234 } 235 else 236 ret = ATR_NOT_FOUND; 237 } 238 239 else if (name == ATR_INTEGER_VALUE_N) 240 { 241 if (atr->ib[0][ATR_INTERFACE_BYTE_TC].present) 242 { 243 (*value) = atr->ib[0][ATR_INTERFACE_BYTE_TC].value; 244 ret = ATR_OK; 245 } 246 else 247 ret = ATR_NOT_FOUND; 248 } 249 else 250 ret = ATR_NOT_FOUND; 251 252 return ret; 253} 254 255int 256ATR_GetParameter (ATR_t * atr, int name, double *parameter) 257{ 258 BYTE FI, DI, II, PI1, PI2, N; 259 260 if (name == ATR_PARAMETER_F) 261 { 262 if (ATR_GetIntegerValue (atr, ATR_INTEGER_VALUE_FI, &FI) == ATR_OK) 263 (*parameter) = (double) (atr_f_table[FI]); 264 else 265 (*parameter) = (double) ATR_DEFAULT_F; 266 return (ATR_OK); 267 } 268 269 else if (name == ATR_PARAMETER_D) 270 { 271 if (ATR_GetIntegerValue (atr, ATR_INTEGER_VALUE_DI, &DI) == ATR_OK) 272 (*parameter) = (double) (atr_d_table[DI]); 273 else 274 (*parameter) = (double) ATR_DEFAULT_D; 275 return (ATR_OK); 276 } 277 278 else if (name == ATR_PARAMETER_I) 279 { 280 if (ATR_GetIntegerValue (atr, ATR_INTEGER_VALUE_II, &II) == ATR_OK) 281 (*parameter) = (double) (atr_i_table[II]); 282 else 283 (*parameter) = ATR_DEFAULT_I; 284 return (ATR_OK); 285 } 286 287 else if (name == ATR_PARAMETER_P) 288 { 289 if (ATR_GetIntegerValue (atr, ATR_INTEGER_VALUE_PI2, &PI2) == ATR_OK) 290 (*parameter) = (double) PI2; 291 else if (ATR_GetIntegerValue (atr, ATR_INTEGER_VALUE_PI1, &PI1) == ATR_OK) 292 (*parameter) = (double) PI1; 293 else 294 (*parameter) = (double) ATR_DEFAULT_P; 295 return (ATR_OK); 296 } 297 298 else if (name == ATR_PARAMETER_N) 299 { 300 if (ATR_GetIntegerValue (atr, ATR_INTEGER_VALUE_N, &N) == ATR_OK) 301 (*parameter) = (double) N; 302 else 303 (*parameter) = (double) ATR_DEFAULT_N; 304 return (ATR_OK); 305 } 306 307 return (ATR_NOT_FOUND); 308} 309 310/* 311 * This function was greatly inspired by ATRDecodeAtr() and 312 * PHGetDefaultProtocol() from pcsc-lite 313 * 314 * It was rewritten by Ludovic Rousseau, 2004 315 */ 316#define PROTOCOL_UNSET -1 317int ATR_GetDefaultProtocol(ATR_t * atr, int *protocol) 318{ 319 int i; 320 321 /* default value */ 322 *protocol = PROTOCOL_UNSET; 323 324 for (i=0; i<ATR_MAX_PROTOCOLS; i++) 325 if (atr->ib[i][ATR_INTERFACE_BYTE_TD].present && (PROTOCOL_UNSET == *protocol)) 326 { 327 /* set to the first protocol byte found */ 328 *protocol = atr->ib[i][ATR_INTERFACE_BYTE_TD].value & 0x0F; 329 DEBUG_COMM2("default protocol: T=%d", *protocol); 330 } 331 332 /* specific mode if TA2 present */ 333 if (atr->ib[1][ATR_INTERFACE_BYTE_TA].present) 334 { 335 *protocol = atr->ib[1][ATR_INTERFACE_BYTE_TA].value & 0x0F; 336 DEBUG_COMM2("specific mode found: T=%d", *protocol); 337 } 338 339 if (PROTOCOL_UNSET == *protocol) 340 { 341 DEBUG_INFO("no default protocol found in ATR. Using T=0"); 342 *protocol = ATR_PROTOCOL_TYPE_T0; 343 } 344 345 return ATR_OK; 346} 347 348