3 Handling of ISO 7816 T=0 protocol
5 This file is part of the Unix driver for Towitoko smartcard readers
6 Copyright (C) 2000 Carlos Prados <cprados@yahoo.com>
8 This version is modified by doz21 to work in a special manner ;)
10 This library is free software; you can redistribute it and/or
11 modify it under the terms of the GNU Lesser General Public
12 License as published by the Free Software Foundation; either
13 version 2 of the License, or (at your option) any later version.
15 This library is distributed in the hope that it will be useful,
16 but WITHOUT ANY WARRANTY; without even the implied warranty of
17 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
18 Lesser General Public License for more details.
20 You should have received a copy of the GNU Lesser General Public
21 License along with this library; if not, write to the Free Software
22 Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
25 #include "../globals.h"
27 #ifdef WITH_CARDREADER
28 #include "../oscam-time.h"
29 #include "icc_async.h"
30 #include "protocol_t0.h"
32 * Not exported constants definition
38 #define PROTOCOL_T0_MAX_NULLS 200
39 #define PROTOCOL_T0_DEFAULT_WI 10
40 #define PROTOCOL_T0_MAX_SHORT_COMMAND 260
41 #define PROTOCOL_T0_MAX_SHORT_RESPONSE 258
43 #define PROTOCOL_T14_MAX_NULLS 200
44 #define PROTOCOL_T14_DEFAULT_WI 10
45 #define PROTOCOL_T14_MAX_SHORT_COMMAND 260
46 #define PROTOCOL_T14_MAX_SHORT_RESPONSE 258
49 #define APDU_CASE_1 0x0001 /* Nor send neither receive data */
50 #define APDU_CASE_2S 0x0002 /* Receive data (1..256) */
51 #define APDU_CASE_3S 0x0003 /* Send data (1..255) */
52 #define APDU_CASE_4S 0x0004 /* Send data (1..255) and receive data (1..256) */
53 #define APDU_CASE_2E 0x0102 /* Receive data (1..65536) */
54 #define APDU_CASE_3E 0x0103 /* Send data (1..65535) */
55 #define APDU_CASE_4E 0x0104 /* Send data (1..65535) and receive data (1..65536) */
56 #define APDU_MALFORMED 5 /* Malformed APDU */
58 /* Timings in ATR are not used in T=0 cards */
59 /* #undef PROTOCOL_T0_USE_DEFAULT_TIMINGS */
62 * Not exported functions declaration
65 static int32_t Protocol_T0_Case2E(struct s_reader
*reader
, unsigned char *command
, uint16_t command_len
, unsigned char *rsp
, uint16_t *lr
);
66 static int32_t Protocol_T0_Case3E(struct s_reader
*reader
, unsigned char *command
, unsigned char *rsp
, uint16_t *lr
);
67 static int32_t Protocol_T0_Case4E(struct s_reader
*reader
, unsigned char *command
, uint16_t command_len
, unsigned char *rsp
, uint16_t *lr
);
68 static int32_t Protocol_T0_ExchangeTPDU(struct s_reader
*reader
, unsigned char *command
, uint16_t command_len
, unsigned char *rsp
, uint16_t *lr
);
70 static int32_t APDU_Cmd_Case(unsigned char *command
, uint16_t command_len
){
76 /* Calculate length of body */
77 L
= MAX(command_len
- 4, 0);
81 { res
= APDU_CASE_1
; }
84 /* Get first byte of body */
87 if((B1
!= 0) && (L
== (uint32_t)B1
+ 1))
88 { res
= APDU_CASE_2S
; }
90 { res
= APDU_CASE_3S
; }
91 else if((B1
!= 0) && (L
== (uint32_t)B1
+ 2))
92 { res
= APDU_CASE_4S
; }
93 else if((B1
== 0) && (L
> 2))
95 /* Get second and third byte of body */
96 B2B3
= (((uint16_t)(command
[5]) << 8) | command
[6]);
98 if((B2B3
!= 0) && (L
== (uint32_t)B2B3
+ 3))
99 { res
= APDU_CASE_2E
; }
101 { res
= APDU_CASE_3E
; }
102 else if((B2B3
!= 0) && (L
== (uint32_t)B2B3
+ 5))
103 { res
= APDU_CASE_4E
; }
105 { res
= APDU_MALFORMED
; }
108 { res
= APDU_MALFORMED
; }
114 * Exported funtions definition
117 int32_t Protocol_T0_Command(struct s_reader
*reader
, unsigned char *command
, uint16_t command_len
, unsigned char *rsp
, uint16_t *lr
)
119 *lr
= 0; //will be returned in case of error
120 if(command_len
< 5) //APDU_CASE_1 or malformed
122 int32_t cmd_case
= APDU_Cmd_Case(command
, command_len
);
126 return Protocol_T0_Case2E(reader
, command
, command_len
, rsp
, lr
); /* fallthrough */
128 return Protocol_T0_Case3E(reader
, command
, rsp
, lr
); /* fallthrough */
130 return Protocol_T0_Case4E(reader
, command
, command_len
, rsp
, lr
); /* fallthrough */
132 command_len
--; /* fallthrough */ //FIXME this should change 4S to 2S/3S command
133 case APDU_CASE_2S
: /* fallthrough */
135 return Protocol_T0_ExchangeTPDU(reader
, command
, command_len
, rsp
, lr
); /* fallthrough */
137 rdr_log_dbg(reader
, D_IFD
, "Protocol: T=0: Invalid APDU");
143 * Not exported functions definition
147 static int32_t Protocol_T0_Case2E(struct s_reader
*reader
, unsigned char *command
, uint16_t command_len
, unsigned char *rsp
, uint16_t *lr
)
149 unsigned char buffer
[PROTOCOL_T0_MAX_SHORT_COMMAND
];
150 unsigned char tpdu_rsp
[CTA_RES_LEN
];
151 uint16_t tpdu_lr
= 0;
154 uint32_t Lc
= (((uint32_t)(command
[5]) << 8) | command
[6]);
157 /* MAP APDU onto command TPDU */
158 memcpy(buffer
, command
, 4);
159 buffer
[4] = (unsigned char) Lc
;
160 memcpy(buffer
+ 5, command
+ 7, buffer
[4]);
161 return Protocol_T0_ExchangeTPDU(reader
, buffer
, buffer
[4] + 5, rsp
, lr
);
164 /* Prepare envelope TPDU */
165 buffer
[0] = command
[0];
170 for(i
= 0; i
< command_len
; i
+= buffer
[4])
172 /* Create envelope command TPDU */
173 buffer
[4] = MIN(255, command_len
- i
);
174 memcpy(buffer
+ 5, command
+ i
, buffer
[4]);
175 call(Protocol_T0_ExchangeTPDU(reader
, buffer
, buffer
[4] + 5, tpdu_rsp
, &tpdu_lr
));
176 /* Card does support envelope command */
177 if(tpdu_rsp
[tpdu_lr
- 2] == 0x90)
179 /* This is not the last segment */
180 if(buffer
[4] + i
< command_len
)
184 memcpy(rsp
, tpdu_rsp
, tpdu_lr
); // Map response TPDU onto APDU
188 else /* Card does not support envelope command or error */
190 memcpy(rsp
, tpdu_rsp
, tpdu_lr
); // Map response TPDU onto APDU
199 static int32_t Protocol_T0_Case3E(struct s_reader
*reader
, unsigned char *command
, unsigned char *rsp
, uint16_t *lr
)
202 unsigned char buffer
[5];
203 unsigned char tpdu_rsp
[CTA_RES_LEN
];
204 uint16_t tpdu_lr
= 0;
207 uint32_t Le
= ((((uint32_t)(command
[5]) << 8) | command
[6]) == 0 ? 65536 : (((uint32_t)(command
[5]) << 8) | command
[6]));
208 memcpy(buffer
, command
, 4);//Map APDU command onto TPDU
212 buffer
[4] = (unsigned char)Le
;
213 return Protocol_T0_ExchangeTPDU(reader
, buffer
, 5, rsp
, lr
); //this was Case3S !!!
216 /* Map APDU onto command TPDU */
218 call(Protocol_T0_ExchangeTPDU(reader
, buffer
, 5 , tpdu_rsp
, &tpdu_lr
));
220 if(tpdu_rsp
[tpdu_lr
- 2] == 0x6C) /* Le not accepted, La indicated */
222 /* Map command APDU onto TPDU */
223 memcpy(buffer
, command
, 4);
224 buffer
[4] = tpdu_rsp
[tpdu_lr
- 1];
226 /* Delete response TPDU */
229 return Protocol_T0_ExchangeTPDU(reader
, buffer
, 5, rsp
, lr
); //Reissue command
232 memcpy(rsp
, tpdu_rsp
, tpdu_lr
);//Map response TPDU onto APDU without change , also for SW1 = 0x67
235 if(tpdu_rsp
[tpdu_lr
- 2] == 0x61) /* Command processed, Lx indicated */
237 Lx
= (tpdu_rsp
[tpdu_lr
- 1] == 0x00) ? 256 : tpdu_rsp
[tpdu_lr
- 1];
240 /* Prepare Get Response TPDU */
241 buffer
[0] = command
[0];
248 buffer
[4] = (unsigned char) MIN(Lm
, Lx
);
249 call(Protocol_T0_ExchangeTPDU(reader
, buffer
, 5, tpdu_rsp
, &tpdu_lr
));
251 /* Append response TPDU to APDU */
252 if((*lr
+ tpdu_lr
) > CTA_RES_LEN
)
254 rdr_log(reader
, "TPDU Append error, new length %i exceeds max length %i", *lr
+ tpdu_lr
, CTA_RES_LEN
);
257 memcpy(rsp
+ (*lr
- 2), tpdu_rsp
, tpdu_lr
);
260 /* Delete response TPDU */
270 static int32_t Protocol_T0_Case4E(struct s_reader
*reader
, unsigned char *command
, uint16_t command_len
, unsigned char *rsp
, uint16_t *lr
)
273 unsigned char buffer
[PROTOCOL_T0_MAX_SHORT_COMMAND
];
274 unsigned char tpdu_rsp
[CTA_RES_LEN
];
275 memset(tpdu_rsp
, 0, sizeof(tpdu_rsp
));
276 uint16_t tpdu_lr
= 0;
279 uint32_t Lc
= (((uint32_t)(command
[5]) << 8) | command
[6]);
283 /* Map APDU onto command TPDU */
284 memcpy(buffer
, command
, 4);
285 buffer
[4] = (unsigned char) Lc
;
286 memcpy(buffer
+ 5, command
, buffer
[4]);
287 ret
= Protocol_T0_ExchangeTPDU(reader
, buffer
, buffer
[4] + 5, tpdu_rsp
, &tpdu_lr
);
290 { ret
= Protocol_T0_Case2E(reader
, command
, command_len
, tpdu_rsp
, &tpdu_lr
); }
292 /* 4E1 a) b) and c) */
295 Le
= ((((uint32_t)(command
[command_len
- 2]) << 8) | command
[command_len
- 1]) == 0 ? 65536 : (((uint32_t)(command
[command_len
- 2]) << 8) | command
[command_len
- 1]));
296 if(tpdu_lr
> 1 && tpdu_rsp
[tpdu_lr
- 2] == 0x61)
298 /* Lm == (Le - APDU_Rsp_RawLen (tpdu_rsp)) == 0 */
299 if(tpdu_rsp
[tpdu_lr
- 1] != 0x00)
300 { Le
= MIN(tpdu_rsp
[tpdu_lr
- 1], Le
); }
302 /* Delete response TPDU */
305 /* Prepare extended Get Response APDU command */
306 buffer
[0] = command
[0];
310 buffer
[4] = 0x00; /* B1 = 0x00 */
311 buffer
[5] = (unsigned char)(Le
>> 8); /* B2 = BL-1 */
312 buffer
[6] = (unsigned char)(Le
& 0x00FF); /* B3 = BL */
313 ret
= Protocol_T0_Case3E(reader
, buffer
, rsp
, lr
);
315 else if(tpdu_lr
> 1 && (tpdu_rsp
[tpdu_lr
- 2] & 0xF0) == 0x60)
317 /* Map response TPDU onto APDU without change */
318 memcpy(rsp
, tpdu_rsp
, tpdu_lr
);
323 /* Delete response TPDU */
326 /* Prepare extended Get Response APDU command */
327 buffer
[0] = command
[0];
331 buffer
[4] = 0x00; /* B1 = 0x00 */
332 buffer
[5] = (unsigned char) Le
>> 8; /* B2 = BL-1 */
333 buffer
[6] = (unsigned char) Le
& 0x00FF; /* B3 = BL */
334 ret
= Protocol_T0_Case3E(reader
, buffer
, rsp
, lr
);
341 static int32_t Protocol_T0_ExchangeTPDU(struct s_reader
*reader
, unsigned char *command
, uint16_t command_len
, unsigned char *rsp
, uint16_t *lr
)
343 unsigned char buffer
[PROTOCOL_T0_MAX_SHORT_RESPONSE
];
345 int32_t Lc
, Le
, sent
, recved
, expectedlen
;
346 int32_t nulls
, cmd_case
;
348 *lr
= 0; //in case of error this will be returned
350 cmd_case
= APDU_Cmd_Case(command
, command_len
);
365 { expectedlen
= 1 + Le
+ 2; }
369 rdr_log_dbg(reader
, D_TRACE
, "ERROR: invalid cmd_case = %i in Protocol_T0_ExchangeTPDU", cmd_case
);
372 timeout
= ICC_Async_GetTimings(reader
, reader
->char_delay
); // we are going to send: char delay timeout
373 if(ICC_Async_Transmit(reader
, 5, expectedlen
, command
, 0, timeout
) != OK
) { return ERROR
; } //Send header bytes
375 /* Initialise counters */
381 * Let's be a bit paranoid with buffer sizes within this loop
382 * so it doesn't overflow reception and transmission buffers
383 * if card does not strictly respect the protocol
386 while(recved
< PROTOCOL_T0_MAX_SHORT_RESPONSE
)
388 timeout
= ICC_Async_GetTimings(reader
, reader
->read_timeout
); // we are going to receive: WWT timeout
389 if(ICC_Async_Receive(reader
, 1, buffer
+ recved
, 0, timeout
) != OK
) { return ERROR
; } //Read one procedure byte
391 /* NULL byte received */
392 if(buffer
[recved
] == 0x60)
395 if(nulls
>= PROTOCOL_T0_MAX_NULLS
) //Maximum number of nulls reached
397 rdr_log_dbg(reader
, D_TRACE
, "ERROR: %s: Maximum number of nulls reached: %d", __func__
, nulls
);
401 else if((buffer
[recved
] & 0xF0) == 0x60 || (buffer
[recved
] & 0xF0) == 0x90) /* SW1 byte received */
403 rdr_log_dbg(reader
, D_TRACE
, "SW1: %02X", buffer
[recved
] & 0xf0);
405 if(recved
>= PROTOCOL_T0_MAX_SHORT_RESPONSE
)
407 rdr_log_dbg(reader
, D_TRACE
, "ERROR: %s: Maximum short response exceeded: %d", __func__
, recved
);
410 timeout
= ICC_Async_GetTimings(reader
, reader
->read_timeout
); // we are going to receive: WWT timeout
411 if(ICC_Async_Receive(reader
, 1, buffer
+ recved
, 0, timeout
) != OK
) { return ERROR
; } //Read SW2 byte
412 rdr_log_dbg(reader
, D_TRACE
, "SW2: %02X", buffer
[recved
] & 0xf0);
416 else if((buffer
[recved
] & 0x0E) == (command
[1] & 0x0E)) /* ACK byte received */
419 /* Reset null's counter */
422 /* Case 2 command: send data */
423 if(cmd_case
== APDU_CASE_2S
)
427 rdr_log_dbg(reader
, D_TRACE
, "ERROR: %s: ACK byte: sent=%d exceeds Lc=%d", __func__
, sent
, Lc
);
430 timeout
= ICC_Async_GetTimings(reader
, reader
->char_delay
); // we are going to send: char delay timeout
431 if(ICC_Async_Transmit(reader
, MAX(Lc
- sent
, 0), 2, data
+ sent
, 0, timeout
) != OK
) { return ERROR
; } /* Send remaining data bytes */
435 else /* Case 3 command: receive data */
437 if(recved
> PROTOCOL_T0_MAX_SHORT_RESPONSE
)
439 rdr_log_dbg(reader
, D_TRACE
, "ERROR: %s: Case 3 ACK - maximum short response exceeded: %d", __func__
, recved
);
444 * Le <= PROTOCOL_T0_MAX_SHORT_RESPONSE - 2 for short commands
447 /* Read remaining data bytes */
448 timeout
= ICC_Async_GetTimings(reader
, reader
->read_timeout
); // we are going to receive: WWT timeout
449 if(ICC_Async_Receive(reader
, MAX(Le
- recved
, 0), buffer
+ recved
, 0, timeout
) != OK
) { return ERROR
; }
454 else if((buffer
[recved
] & 0x0E) == ((~command
[1]) & 0x0E)) /* ~ACK byte received */
457 nulls
= 0; //Reset null's counter
459 /* Case 2 command: send data */
460 if(cmd_case
== APDU_CASE_2S
)
464 rdr_log_dbg(reader
, D_TRACE
, "ERROR: %s: ~ACK byte: sent=%d exceeds Lc=%d", __func__
, sent
, Lc
);
467 timeout
= ICC_Async_GetTimings(reader
, reader
->char_delay
); // we are going to send: char delay timeout
468 if(ICC_Async_Transmit(reader
, 1, 1, data
+ sent
, 0, timeout
) != OK
) { return ERROR
; } //Send next data byte
472 else /* Case 3 command: receive data */
474 if(recved
> PROTOCOL_T0_MAX_SHORT_RESPONSE
)
476 rdr_log_dbg(reader
, D_TRACE
, "ERROR: %s: Case 3 ~ACK - maximum short response exceeded: %d", __func__
, recved
);
479 timeout
= ICC_Async_GetTimings(reader
, reader
->read_timeout
); // we are going to receive: WWT timeout
480 if(ICC_Async_Receive(reader
, 1, buffer
+ recved
, 0, timeout
) != OK
) { return ERROR
; } //Read next data byte
485 else /* Anything else received */
487 rdr_log_dbg(reader
, D_TRACE
, "ERROR: %s: Received unexpected character: %02X", __func__
, buffer
[recved
]);
492 memcpy(rsp
, buffer
, recved
);
497 int32_t Protocol_T14_ExchangeTPDU(struct s_reader
*reader
, unsigned char *cmd_raw
, uint16_t command_len
, unsigned char *rsp
, uint16_t *lr
)
499 unsigned char buffer
[PROTOCOL_T14_MAX_SHORT_RESPONSE
];
503 unsigned char ixor
= 0x3E;
504 unsigned char ixor1
= 0x3F;
506 int32_t cmd_len
= (int32_t) command_len
;
507 *lr
= 0; //in case of error this is returned
510 cmd_case
= APDU_Cmd_Case(cmd_raw
, cmd_len
);
511 for(i
= 0; i
< cmd_len
; i
++)
512 { ixor
^= cmd_raw
[i
]; }
514 /* Check case of command */
515 if((cmd_case
!= APDU_CASE_2S
) && (cmd_case
!= APDU_CASE_3S
))
517 rdr_log_dbg(reader
, D_TRACE
, "ERROR: invalid cmd_case = %i in Protocol_T14_ExchangeTPDU", cmd_case
);
521 buffer
[0] = 0x01; //send 0x01 byte
522 memcpy(buffer
+ 1, cmd_raw
, cmd_len
); // apdu
523 buffer
[cmd_len
+ 1] = ixor
; // xor byte
526 timeout
= ICC_Async_GetTimings(reader
, reader
->char_delay
); // we are going to send: char delay timeout
527 if(ICC_Async_Transmit(reader
, cmd_len
+ 2, 0, buffer
, 0, timeout
) != OK
) { return ERROR
; } //send apdu
528 if(cmd_raw
[0] == 0x02 && cmd_raw
[1] == 0x09) { cs_sleepms(2500); } //FIXME why wait? -> needed for init on overclocked T14 cards
530 timeout
= ICC_Async_GetTimings(reader
, reader
->read_timeout
); // we are going to receive: WWT timeout
531 // if ((reader->typ == R_SMART) && (reader->smart_type >= 2)) timeout *= 1.1;
532 if(ICC_Async_Receive(reader
, 8, buffer
, 0, timeout
) != OK
) { return ERROR
; } //Read one procedure byte
533 recved
= (int32_t)buffer
[7];
536 timeout
= ICC_Async_GetTimings(reader
, reader
->read_timeout
); // we are going to receive: WWT timeout
537 // if ((reader->typ == R_SMART) && (reader->smart_type >= 2)) timeout *= 1.1;
538 if(ICC_Async_Receive(reader
, recved
, buffer
+ 8, 0 , timeout
) != OK
) {return ERROR
; }
540 timeout
= ICC_Async_GetTimings(reader
, reader
->read_timeout
); // we are going to receive: WWT timeout
541 // if ((reader->typ == R_SMART) && (reader->smart_type >= 2)) timeout *= 1.1;
542 if(ICC_Async_Receive(reader
, 1, &ixor
, 0, timeout
) != OK
) {return ERROR
; }
543 for(i
= 0; i
< 8 + recved
; i
++)
544 { ixor1
^= buffer
[i
]; }
547 rdr_log_dbg(reader
, D_TRACE
, "ERROR: invalid checksum = %02X expected %02X", ixor1
, ixor
);
550 memcpy(buffer
+ 8 + recved
, buffer
+ 2, 2);
552 memcpy(rsp
, buffer
+ 8, *lr
);