Coverage Report

Created: 2026-10-28 06:52

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/opensc/src/libopensc/reader-tr03119.c
Line
Count
Source
1
/*
2
 * reader-escape.c: implementation related to escape commands with pseudo APDUs
3
 *
4
 * Copyright (C) 2013-2018  Frank Morgner
5
 *
6
 * This library is free software; you can redistribute it and/or
7
 * modify it under the terms of the GNU Lesser General Public
8
 * License as published by the Free Software Foundation; either
9
 * version 2.1 of the License, or (at your option) any later version.
10
 *
11
 * This library is distributed in the hope that it will be useful,
12
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
14
 * Lesser General Public License for more details.
15
 *
16
 * You should have received a copy of the GNU Lesser General Public
17
 * License along with this library; if not, write to the Free Software
18
 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
19
 */
20
21
#ifdef HAVE_CONFIG_H
22
#include "config.h"
23
#endif
24
25
#include "reader-tr03119.h"
26
#include "ccid-types.h"
27
#include "internal.h"
28
#include "libopensc/asn1.h"
29
#include "libopensc/log.h"
30
#include "libopensc/opensc.h"
31
#include "libopensc/pace.h"
32
#include <stdlib.h>
33
#include <string.h>
34
35
#if _WIN32
36
/* FIXME might not always work */
37
#define htole16(x) (x)
38
#define htole32(x) (x)
39
#elif __APPLE__
40
#include <libkern/OSByteOrder.h>
41
#define htole16(x) OSSwapHostToLittleInt16(x)
42
#define htole32(x) OSSwapHostToLittleInt32(x)
43
#else
44
#ifndef _BSD_SOURCE
45
#define _BSD_SOURCE             /* See feature_test_macros(7) */
46
#endif
47
#ifdef HAVE_SYS_ENDIAN_H
48
#include <sys/endian.h>
49
#endif
50
#ifdef HAVE_ENDIAN_H
51
#include <endian.h>
52
#endif
53
#endif
54
55
int get_pace_capabilities(u8 *bitmap)
56
0
{
57
0
  if (!bitmap)
58
0
    return SC_ERROR_INVALID_ARGUMENTS;
59
60
  /* BitMap */
61
0
  *bitmap = EAC_BITMAP_PACE|EAC_BITMAP_EID|EAC_BITMAP_ESIGN;
62
63
0
  return SC_SUCCESS;
64
0
}
65
66
const u8 escape_cla                          = 0xff;
67
const u8 escape_ins                          = 0x9a;
68
69
const u8 escape_p1_PIN                       = 0x04;
70
const u8 escape_p2_GetReaderPACECapabilities = 0x01;
71
const u8 escape_p2_EstablishPACEChannel      = 0x02;
72
/*const u8 escape_p2_DestroyPACEChannel        = 0x03;*/
73
const u8 escape_p2_PC_to_RDR_Secure          = 0x10;
74
75
const u8 escape_p1_IFD                       = 0x01;
76
const u8 escape_p2_vendor                    = 0x01;
77
/*const u8 escape_p2_product                   = 0x03;*/
78
const u8 escape_p2_version_firmware          = 0x06;
79
/*const u8 escape_p2_version_driver            = 0x07;*/
80
81
struct sc_asn1_entry g_boolean[] = {
82
  { "boolean",
83
    SC_ASN1_BOOLEAN, SC_ASN1_TAG_BOOLEAN, 0, NULL, NULL },
84
  { NULL , 0 , 0 , 0 , NULL , NULL }
85
};
86
struct sc_asn1_entry g_int_as_octet_string[] = {
87
  { "int as octet string",
88
    SC_ASN1_OCTET_STRING, SC_ASN1_TAG_INTEGER, 0, NULL, NULL },
89
  { NULL , 0 , 0 , 0 , NULL , NULL }
90
};
91
struct sc_asn1_entry g_octet_string[] = {
92
  { "octet string",
93
    SC_ASN1_OCTET_STRING, SC_ASN1_TAG_OCTET_STRING, SC_ASN1_ALLOC, NULL, NULL },
94
  { NULL , 0 , 0 , 0 , NULL , NULL }
95
};
96
struct sc_asn1_entry g_numeric_string_as_octet_string[] = {
97
  { "utf8string",
98
    SC_ASN1_OCTET_STRING, SC_ASN1_TAG_NUMERICSTRING, SC_ASN1_ALLOC, NULL, NULL },
99
  { NULL , 0 , 0 , 0 , NULL , NULL }
100
};
101
102
const struct sc_asn1_entry g_EstablishPACEChannelInput_data[] = {
103
  { "passwordID",
104
    /* use an OCTET STRING to avoid a conversion to int */
105
    SC_ASN1_STRUCT, SC_ASN1_CTX|0x01|SC_ASN1_CONS, 0, NULL, NULL },
106
  { "transmittedPassword",
107
    SC_ASN1_STRUCT, SC_ASN1_CTX|0x02|SC_ASN1_CONS, SC_ASN1_OPTIONAL|SC_ASN1_ALLOC, NULL, NULL },
108
  { "cHAT",
109
    SC_ASN1_STRUCT, SC_ASN1_CTX|0x03|SC_ASN1_CONS, SC_ASN1_OPTIONAL|SC_ASN1_ALLOC, NULL, NULL },
110
  { "certificateDescription",
111
    SC_ASN1_OCTET_STRING, SC_ASN1_CTX|0x04|SC_ASN1_CONS, SC_ASN1_OPTIONAL|SC_ASN1_ALLOC, NULL, NULL },
112
  { "hashOID",
113
    /* use an OCTET STRING to avoid a conversion to struct sc_object_id */
114
    SC_ASN1_STRUCT, SC_ASN1_CTX|0x05|SC_ASN1_CONS, SC_ASN1_OPTIONAL|SC_ASN1_ALLOC, NULL, NULL },
115
  { NULL , 0 , 0 , 0 , NULL , NULL }
116
};
117
const struct sc_asn1_entry g_EstablishPACEChannelOutput_data[] = {
118
  { "errorCode",
119
    SC_ASN1_STRUCT, SC_ASN1_CTX|0x01|SC_ASN1_CONS, 0, NULL, NULL },
120
  { "statusMSESetAT",
121
    SC_ASN1_STRUCT, SC_ASN1_CTX|0x02|SC_ASN1_CONS, 0, NULL, NULL },
122
  { "efCardAccess",
123
    SC_ASN1_OCTET_STRING, SC_ASN1_CTX|0x03|SC_ASN1_CONS, SC_ASN1_ALLOC, NULL, NULL },
124
  { "idPICC",
125
    SC_ASN1_STRUCT, SC_ASN1_CTX|0x04|SC_ASN1_CONS, SC_ASN1_OPTIONAL|SC_ASN1_ALLOC, NULL, NULL },
126
  { "curCAR",
127
    SC_ASN1_STRUCT, SC_ASN1_CTX|0x05|SC_ASN1_CONS, SC_ASN1_OPTIONAL|SC_ASN1_ALLOC, NULL, NULL },
128
  { "prevCAR",
129
    SC_ASN1_STRUCT, SC_ASN1_CTX|0x06|SC_ASN1_CONS, SC_ASN1_OPTIONAL|SC_ASN1_ALLOC, NULL, NULL },
130
  { NULL , 0 , 0 , 0 , NULL , NULL }
131
};
132
const struct sc_asn1_entry g_EstablishPACEChannel[] = {
133
  { "EstablishPACEChannel",
134
    SC_ASN1_STRUCT, SC_ASN1_TAG_SEQUENCE|SC_ASN1_CONS, 0, NULL, NULL },
135
  { NULL , 0 , 0 , 0 , NULL , NULL }
136
};
137
138
int escape_pace_input_to_buf(sc_context_t *ctx,
139
    const struct establish_pace_channel_input *input,
140
    unsigned char **asn1, size_t *asn1_len)
141
0
{
142
0
  size_t pin_id_len = sizeof input->pin_id;
143
0
  struct sc_asn1_entry EstablishPACEChannelInput_data[
144
0
    sizeof g_EstablishPACEChannelInput_data/
145
0
    sizeof *g_EstablishPACEChannelInput_data];
146
0
  struct sc_asn1_entry EstablishPACEChannel[
147
0
    sizeof g_EstablishPACEChannel/
148
0
    sizeof *g_EstablishPACEChannel];
149
0
  struct sc_asn1_entry passwordID[
150
0
    sizeof g_int_as_octet_string/
151
0
    sizeof *g_int_as_octet_string];
152
0
  struct sc_asn1_entry transmittedPassword[
153
0
    sizeof g_numeric_string_as_octet_string/
154
0
    sizeof *g_numeric_string_as_octet_string];
155
0
  struct sc_asn1_entry cHAT[
156
0
    sizeof g_octet_string/
157
0
    sizeof *g_octet_string];
158
159
0
  sc_copy_asn1_entry(g_EstablishPACEChannel,
160
0
      EstablishPACEChannel);
161
0
  sc_format_asn1_entry(EstablishPACEChannel,
162
0
      EstablishPACEChannelInput_data, 0, 1);
163
164
0
  sc_copy_asn1_entry(g_EstablishPACEChannelInput_data,
165
0
      EstablishPACEChannelInput_data);
166
167
0
  sc_format_asn1_entry(EstablishPACEChannelInput_data+0,
168
0
      passwordID, 0, 1);
169
0
  sc_copy_asn1_entry(g_int_as_octet_string,
170
0
      passwordID);
171
0
  sc_format_asn1_entry(passwordID,
172
0
      (unsigned char *) &input->pin_id, &pin_id_len, 1);
173
174
0
  if (input->pin) {
175
0
    sc_format_asn1_entry(EstablishPACEChannelInput_data+1,
176
0
        transmittedPassword,
177
0
        0, 1);
178
0
    sc_copy_asn1_entry(g_numeric_string_as_octet_string,
179
0
        transmittedPassword);
180
0
    sc_format_asn1_entry(transmittedPassword,
181
0
        (unsigned char *) input->pin,
182
0
        (size_t *) &input->pin_length, 1);
183
0
  }
184
185
0
  if (input->chat) {
186
0
    sc_format_asn1_entry(EstablishPACEChannelInput_data+2,
187
0
        cHAT,
188
0
        0, 1);
189
0
    sc_copy_asn1_entry(g_octet_string,
190
0
        cHAT);
191
0
    sc_format_asn1_entry(cHAT,
192
0
        (unsigned char *) input->chat,
193
0
        (size_t *) &input->chat_length, 1);
194
0
  }
195
196
0
  if (input->certificate_description) {
197
0
    sc_format_asn1_entry(EstablishPACEChannelInput_data+3,
198
0
        (unsigned char *) input->certificate_description,
199
0
        (size_t *) &input->certificate_description_length, 1);
200
0
  }
201
202
0
  return sc_asn1_encode(ctx, EstablishPACEChannel, asn1, asn1_len);
203
0
}
204
205
int escape_buf_to_pace_input(sc_context_t *ctx,
206
    const unsigned char *asn1, size_t asn1_len,
207
    struct establish_pace_channel_input *input)
208
0
{
209
0
  size_t pin_id_len = sizeof input->pin_id;
210
0
  struct sc_asn1_entry EstablishPACEChannelInput_data[
211
0
    sizeof g_EstablishPACEChannelInput_data/
212
0
    sizeof *g_EstablishPACEChannelInput_data];
213
0
  struct sc_asn1_entry EstablishPACEChannel[
214
0
    sizeof g_EstablishPACEChannel/
215
0
    sizeof *g_EstablishPACEChannel];
216
0
  struct sc_asn1_entry passwordID[
217
0
    sizeof g_int_as_octet_string/
218
0
    sizeof *g_int_as_octet_string];
219
0
  struct sc_asn1_entry transmittedPassword[
220
0
    sizeof g_numeric_string_as_octet_string/
221
0
    sizeof *g_numeric_string_as_octet_string];
222
0
  struct sc_asn1_entry cHAT[
223
0
    sizeof g_octet_string/
224
0
    sizeof *g_octet_string];
225
  /* FIXME handle hashOID */
226
227
0
  sc_copy_asn1_entry(g_EstablishPACEChannel,
228
0
      EstablishPACEChannel);
229
0
  sc_format_asn1_entry(EstablishPACEChannel,
230
0
      EstablishPACEChannelInput_data, 0, 0);
231
232
0
  sc_copy_asn1_entry(g_EstablishPACEChannelInput_data,
233
0
      EstablishPACEChannelInput_data);
234
235
0
  sc_format_asn1_entry(EstablishPACEChannelInput_data+0,
236
0
      passwordID, 0, 0);
237
0
  sc_copy_asn1_entry(g_int_as_octet_string,
238
0
      passwordID);
239
0
  sc_format_asn1_entry(passwordID,
240
0
      &input->pin_id, &pin_id_len, 0);
241
242
0
  if (input->pin) {
243
0
    sc_format_asn1_entry(EstablishPACEChannelInput_data+1,
244
0
        transmittedPassword, 0, 0);
245
0
    sc_copy_asn1_entry(g_numeric_string_as_octet_string,
246
0
        transmittedPassword);
247
0
    sc_format_asn1_entry(transmittedPassword,
248
0
        (unsigned char *) &input->pin, &input->pin_length, 0);
249
0
  }
250
251
0
  if (input->chat) {
252
0
    sc_format_asn1_entry(EstablishPACEChannelInput_data+2,
253
0
        cHAT, 0, 0);
254
0
    sc_copy_asn1_entry(g_octet_string,
255
0
        cHAT);
256
0
    sc_format_asn1_entry(cHAT,
257
0
        (unsigned char *) &input->chat, &input->chat_length, 0);
258
0
  }
259
260
0
  if (input->certificate_description) {
261
0
    sc_format_asn1_entry(EstablishPACEChannelInput_data+3,
262
0
        (unsigned char *) &input->certificate_description,
263
0
        &input->certificate_description_length, 0);
264
0
  }
265
266
0
  LOG_TEST_RET(ctx,
267
0
      sc_asn1_decode(ctx, EstablishPACEChannel, asn1, asn1_len, NULL, NULL),
268
0
      "Error decoding EstablishPACEChannel");
269
270
0
  if (pin_id_len != sizeof input->pin_id)
271
0
    return SC_ERROR_UNKNOWN_DATA_RECEIVED;
272
273
0
  return SC_SUCCESS;
274
0
}
275
276
int escape_pace_output_to_buf(sc_context_t *ctx,
277
    const struct establish_pace_channel_output *output,
278
    unsigned char **asn1, size_t *asn1_len)
279
0
{
280
0
  uint16_t status_mse_set_at = ((output->mse_set_at_sw1 & 0xff) << 8) | output->mse_set_at_sw2;
281
0
  size_t result_len = sizeof output->result,
282
0
       status_mse_set_at_len = sizeof status_mse_set_at;
283
0
  struct sc_asn1_entry EstablishPACEChannelOutput_data[
284
0
    sizeof g_EstablishPACEChannelOutput_data/
285
0
    sizeof *g_EstablishPACEChannelOutput_data];
286
0
  struct sc_asn1_entry EstablishPACEChannel[
287
0
    sizeof g_EstablishPACEChannel/
288
0
    sizeof *g_EstablishPACEChannel];
289
0
  struct sc_asn1_entry errorCode[
290
0
    sizeof g_octet_string/
291
0
    sizeof *g_octet_string];
292
0
  struct sc_asn1_entry statusMSESetAT[
293
0
    sizeof g_octet_string/
294
0
    sizeof *g_octet_string];
295
0
  struct sc_asn1_entry idPICC[
296
0
    sizeof g_octet_string/
297
0
    sizeof *g_octet_string];
298
0
  struct sc_asn1_entry curCAR[
299
0
    sizeof g_octet_string/
300
0
    sizeof *g_octet_string];
301
0
  struct sc_asn1_entry prevCAR[
302
0
    sizeof g_octet_string/
303
0
    sizeof *g_octet_string];
304
305
0
  sc_copy_asn1_entry(g_EstablishPACEChannel,
306
0
      EstablishPACEChannel);
307
0
  sc_format_asn1_entry(EstablishPACEChannel,
308
0
      EstablishPACEChannelOutput_data, 0, 1);
309
310
0
  sc_copy_asn1_entry(g_EstablishPACEChannelOutput_data,
311
0
      EstablishPACEChannelOutput_data);
312
313
0
  sc_format_asn1_entry(EstablishPACEChannelOutput_data+0,
314
0
      errorCode, 0, 1);
315
0
  sc_copy_asn1_entry(g_octet_string,
316
0
      errorCode);
317
0
  sc_format_asn1_entry(errorCode,
318
0
      (unsigned char *) &output->result, &result_len, 1);
319
320
0
  sc_format_asn1_entry(EstablishPACEChannelOutput_data+1,
321
0
      statusMSESetAT, 0, 1);
322
0
  sc_copy_asn1_entry(g_octet_string,
323
0
      statusMSESetAT);
324
0
  sc_format_asn1_entry(statusMSESetAT,
325
0
      &status_mse_set_at, &status_mse_set_at_len, 1);
326
327
0
  if (output->ef_cardaccess) {
328
0
    sc_format_asn1_entry(EstablishPACEChannelOutput_data+2,
329
0
        output->ef_cardaccess, (size_t *) &output->ef_cardaccess_length, 1);
330
0
  }
331
332
0
  if (output->id_icc) {
333
0
    sc_format_asn1_entry(EstablishPACEChannelOutput_data+3,
334
0
        idPICC, 0, 1);
335
0
    sc_copy_asn1_entry(g_octet_string,
336
0
        idPICC);
337
0
    sc_format_asn1_entry(idPICC,
338
0
        output->id_icc, (size_t *) &output->id_icc_length, 1);
339
0
  }
340
341
0
  if (output->recent_car) {
342
0
    sc_format_asn1_entry(EstablishPACEChannelOutput_data+4,
343
0
        curCAR, 0, 1);
344
0
    sc_copy_asn1_entry(g_octet_string,
345
0
        curCAR);
346
0
    sc_format_asn1_entry(curCAR,
347
0
        output->recent_car, (size_t *) &output->recent_car_length, 1);
348
0
  }
349
350
0
  if (output->previous_car) {
351
0
    sc_format_asn1_entry(EstablishPACEChannelOutput_data+5,
352
0
      prevCAR, 0, 1);
353
0
    sc_copy_asn1_entry(g_octet_string,
354
0
        prevCAR);
355
0
    sc_format_asn1_entry(prevCAR,
356
0
      output->previous_car, (size_t *) &output->previous_car_length, 1);
357
0
  }
358
359
0
  return sc_asn1_encode(ctx, EstablishPACEChannel, asn1, asn1_len);
360
0
}
361
362
int escape_buf_to_pace_output(sc_context_t *ctx,
363
    const unsigned char *asn1, size_t asn1_len,
364
    struct establish_pace_channel_output *output)
365
0
{
366
0
  uint16_t status_mse_set_at;
367
0
  size_t result_len = sizeof output->result,
368
0
       status_mse_set_at_len = sizeof status_mse_set_at;
369
0
  struct sc_asn1_entry EstablishPACEChannelOutput_data[
370
0
    sizeof g_EstablishPACEChannelOutput_data/
371
0
    sizeof *g_EstablishPACEChannelOutput_data];
372
0
  struct sc_asn1_entry EstablishPACEChannel[
373
0
    sizeof g_EstablishPACEChannel/
374
0
    sizeof *g_EstablishPACEChannel];
375
0
  struct sc_asn1_entry errorCode[
376
0
    sizeof g_octet_string/
377
0
    sizeof *g_octet_string];
378
0
  struct sc_asn1_entry statusMSESetAT[
379
0
    sizeof g_octet_string/
380
0
    sizeof *g_octet_string];
381
0
  struct sc_asn1_entry idPICC[
382
0
    sizeof g_octet_string/
383
0
    sizeof *g_octet_string];
384
0
  struct sc_asn1_entry curCAR[
385
0
    sizeof g_octet_string/
386
0
    sizeof *g_octet_string];
387
0
  struct sc_asn1_entry prevCAR[
388
0
    sizeof g_octet_string/
389
0
    sizeof *g_octet_string];
390
391
0
  sc_copy_asn1_entry(g_EstablishPACEChannel,
392
0
      EstablishPACEChannel);
393
0
  sc_format_asn1_entry(EstablishPACEChannel,
394
0
      EstablishPACEChannelOutput_data, 0, 0);
395
396
0
  sc_copy_asn1_entry(g_EstablishPACEChannelOutput_data,
397
0
      EstablishPACEChannelOutput_data);
398
0
  sc_format_asn1_entry(EstablishPACEChannelOutput_data+0,
399
0
      errorCode, 0, 0);
400
0
  sc_format_asn1_entry(EstablishPACEChannelOutput_data+1,
401
0
      statusMSESetAT, 0, 0);
402
0
  sc_format_asn1_entry(EstablishPACEChannelOutput_data+2,
403
0
      &output->ef_cardaccess, &output->ef_cardaccess_length, 0);
404
0
  sc_format_asn1_entry(EstablishPACEChannelOutput_data+3,
405
0
      idPICC, 0, 0);
406
0
  sc_format_asn1_entry(EstablishPACEChannelOutput_data+4,
407
0
      curCAR, 0, 0);
408
0
  sc_format_asn1_entry(EstablishPACEChannelOutput_data+5,
409
0
      prevCAR, 0, 0);
410
411
0
  sc_copy_asn1_entry(g_octet_string,
412
0
      errorCode);
413
0
  sc_format_asn1_entry(errorCode,
414
0
      &output->result, &result_len, 0);
415
  /* we already allocated memory for the result */
416
0
  errorCode->flags = 0;
417
418
0
  sc_copy_asn1_entry(g_octet_string,
419
0
      statusMSESetAT);
420
0
  sc_format_asn1_entry(statusMSESetAT,
421
0
      &status_mse_set_at, &status_mse_set_at_len, 0);
422
  /* we already allocated memory for the result */
423
0
  statusMSESetAT->flags = 0;
424
425
0
  sc_copy_asn1_entry(g_octet_string,
426
0
      idPICC);
427
0
  sc_format_asn1_entry(idPICC,
428
0
      &output->id_icc, &output->id_icc_length, 0);
429
430
0
  sc_copy_asn1_entry(g_octet_string,
431
0
      curCAR);
432
0
  sc_format_asn1_entry(curCAR,
433
0
      &output->recent_car, &output->recent_car_length, 0);
434
435
0
  sc_copy_asn1_entry(g_octet_string,
436
0
      prevCAR);
437
0
  sc_format_asn1_entry(prevCAR,
438
0
      &output->previous_car, &output->previous_car_length, 0);
439
440
0
  LOG_TEST_RET(ctx,
441
0
      sc_asn1_decode(ctx, EstablishPACEChannel,
442
0
        asn1, asn1_len, NULL, NULL),
443
0
      "Error decoding EstablishPACEChannel");
444
445
0
  if (status_mse_set_at_len != sizeof status_mse_set_at
446
0
      || result_len != sizeof output->result)
447
0
    return SC_ERROR_UNKNOWN_DATA_RECEIVED;
448
449
0
  output->mse_set_at_sw1 = (status_mse_set_at >> 8) & 0xff;
450
0
  output->mse_set_at_sw2 =  status_mse_set_at       & 0xff;
451
452
0
  return SC_SUCCESS;
453
0
}
454
455
0
#define CCID_PIN_TIMEOUT  30
456
0
#define CCID_DISPLAY_DEFAULT    0xff
457
static int escape_pin_cmd_to_buf(sc_context_t *ctx,
458
    const struct sc_pin_cmd_data *data,
459
    unsigned char **pc_to_rdr_secure, size_t *pc_to_rdr_secure_len)
460
0
{
461
0
  PC_to_RDR_Secure_t *secure;
462
0
  abPINDataStucture_Modification_t *modify;
463
0
  abPINDataStucture_Verification_t *verify;
464
0
  uint16_t wLangId = 0,
465
0
       bTeoPrologue2 = 0,
466
0
       wPINMaxExtraDigit;
467
0
  uint8_t bTimeOut = CCID_PIN_TIMEOUT,
468
0
      bNumberMessage = CCID_DISPLAY_DEFAULT,
469
0
      bTeoPrologue1 = 0,
470
0
      bMsgIndex = 0,
471
0
      bMessageType = 0x69,
472
0
      bSlot = 0,
473
0
      bSeq = 0,
474
0
      bBWI = 0xff,
475
0
      wLevelParameter = 0,
476
0
      bEntryValidationCondition = CCID_ENTRY_VALIDATE,
477
0
      bmFormatString, bmPINLengthFormat, bmPINBlockString;
478
0
  const struct sc_pin_cmd_pin *pin_ref;
479
0
  int r;
480
0
  unsigned char *pinapdu = NULL;
481
0
  size_t pinapdu_len = 0;
482
483
0
  if (!data || !pc_to_rdr_secure || !pc_to_rdr_secure_len) {
484
0
    r = SC_ERROR_INVALID_ARGUMENTS;
485
0
    goto err;
486
0
  }
487
488
0
  pin_ref = data->flags & SC_PIN_CMD_IMPLICIT_CHANGE ?
489
0
    &data->pin2 : &data->pin1;
490
491
0
  wPINMaxExtraDigit = htole16(
492
0
      (0xff & pin_ref->min_length) << 8)
493
0
      | (pin_ref->max_length & 0xff);
494
495
0
  bmFormatString = CCID_PIN_UNITS_BYTES
496
0
    | ((pin_ref->offset & 0xf) << 3);
497
0
  switch (pin_ref->encoding) {
498
0
    case SC_PIN_ENCODING_ASCII:
499
0
      bmFormatString |= CCID_PIN_ENCODING_ASCII;
500
0
      break;
501
0
    case SC_PIN_ENCODING_BCD:
502
0
      bmFormatString |= CCID_PIN_ENCODING_BCD;
503
0
      break;
504
0
    default:
505
0
      r = SC_ERROR_INVALID_ARGUMENTS;
506
0
      goto err;
507
0
  }
508
509
  /* GLP PINs expect the effective PIN length from bit 4 */
510
0
  bmPINLengthFormat = pin_ref->encoding == SC_PIN_ENCODING_GLP ?
511
0
    0x04 : 0x00;
512
513
0
  if (pin_ref->encoding == SC_PIN_ENCODING_GLP) {
514
    /* GLP PIN length is encoded in 4 bits and block size is always 8 bytes */
515
0
    bmPINBlockString = 0x40 | 0x08;
516
0
  } else if (pin_ref->encoding == SC_PIN_ENCODING_ASCII && data->flags & SC_PIN_CMD_NEED_PADDING) {
517
0
    bmPINBlockString = (uint8_t) pin_ref->pad_length;
518
0
  } else {
519
0
    bmPINBlockString = 0x00;
520
0
  }
521
522
0
  r = sc_apdu_get_octets(ctx, data->apdu, &pinapdu, &pinapdu_len,
523
0
      SC_PROTO_T1);
524
0
  if (r < 0)
525
0
    goto err;
526
527
0
  switch (data->cmd) {
528
0
    case SC_PIN_CMD_VERIFY:
529
0
      *pc_to_rdr_secure_len = sizeof *secure + 1
530
0
        + sizeof *verify + pinapdu_len;
531
0
      break;
532
533
0
    case SC_PIN_CMD_CHANGE:
534
0
      *pc_to_rdr_secure_len = sizeof *secure + 1
535
0
        + sizeof *modify + 3 + pinapdu_len;
536
0
      break;
537
538
0
    default:
539
0
      r = SC_ERROR_INVALID_ARGUMENTS;
540
0
      goto err;
541
0
  }
542
543
0
  *pc_to_rdr_secure = malloc(*pc_to_rdr_secure_len);
544
0
  if (!*pc_to_rdr_secure) {
545
0
    r = SC_ERROR_OUT_OF_MEMORY;
546
0
    goto err;
547
0
  }
548
0
  secure = (PC_to_RDR_Secure_t *) *pc_to_rdr_secure;
549
0
  secure->bMessageType = bMessageType;
550
0
  secure->dwLength = htole32((*pc_to_rdr_secure_len) - sizeof *secure);
551
0
  secure->bSlot = bSlot;
552
0
  secure->bSeq = bSeq;
553
0
  secure->bBWI = bBWI;
554
0
  secure->wLevelParameter = wLevelParameter;
555
556
0
  switch (data->cmd) {
557
0
    case SC_PIN_CMD_VERIFY:
558
      /* bPINOperation */
559
0
      *((*pc_to_rdr_secure) + sizeof *secure) = CCID_OPERATION_VERIFY;
560
0
      verify = (abPINDataStucture_Verification_t *)
561
0
        ((*pc_to_rdr_secure) + sizeof *secure + 1);
562
0
      verify->bTimeOut = bTimeOut;
563
0
      verify->bmFormatString = bmFormatString;
564
0
      verify->bmPINBlockString = bmPINBlockString;
565
0
      verify->bmPINLengthFormat = bmPINLengthFormat;
566
0
      verify->wPINMaxExtraDigit = wPINMaxExtraDigit;
567
0
      verify->bEntryValidationCondition = bEntryValidationCondition;
568
0
      verify->bNumberMessage = bNumberMessage;
569
0
      verify->wLangId = wLangId;
570
0
      verify->bMsgIndex = bMsgIndex;
571
0
      verify->bTeoPrologue1 = bTeoPrologue1;
572
0
      verify->bTeoPrologue2 = bTeoPrologue2;
573
574
0
      memcpy((*pc_to_rdr_secure) + sizeof *secure + 1 + sizeof *verify,
575
0
          pinapdu, pinapdu_len);
576
0
      break;
577
578
0
    case SC_PIN_CMD_CHANGE:
579
      /* bPINOperation */
580
0
      *((*pc_to_rdr_secure) + sizeof *secure) = CCID_OPERATION_MODIFY;
581
0
      modify = (abPINDataStucture_Modification_t *)
582
0
        ((*pc_to_rdr_secure) + sizeof *secure + 1);
583
0
      modify->bTimeOut = bTimeOut;
584
0
      modify->bmFormatString = bmFormatString;
585
0
      modify->bmPINBlockString = bmPINBlockString;
586
0
      modify->bmPINLengthFormat = bmPINLengthFormat;
587
0
      if (!(data->flags & SC_PIN_CMD_IMPLICIT_CHANGE)
588
0
          && data->pin1.offset) {
589
0
        modify->bInsertionOffsetOld = (uint8_t) data->pin1.offset - 5;
590
0
      } else {
591
0
        modify->bInsertionOffsetOld = 0;
592
0
      }
593
0
      modify->bInsertionOffsetNew = data->pin2.offset ? (uint8_t) data->pin2.offset - 5 : 0;
594
0
      modify->wPINMaxExtraDigit = wPINMaxExtraDigit;
595
0
      modify->bConfirmPIN = CCID_PIN_CONFIRM_NEW
596
0
        | (data->flags & SC_PIN_CMD_IMPLICIT_CHANGE ? 0 : CCID_PIN_INSERT_OLD);
597
0
      modify->bEntryValidationCondition = bEntryValidationCondition;
598
0
      modify->bNumberMessage = bNumberMessage;
599
0
      modify->wLangId = wLangId;
600
0
      modify->bMsgIndex1 = bMsgIndex;
601
0
      *((*pc_to_rdr_secure) + sizeof *secure + 1 + sizeof *modify + 0) =
602
0
        bTeoPrologue1;
603
0
      *((*pc_to_rdr_secure) + sizeof *secure + 1 + sizeof *modify + 1) =
604
0
        bTeoPrologue1;
605
0
      *((*pc_to_rdr_secure) + sizeof *secure + 1 + sizeof *modify + 2) =
606
0
        bTeoPrologue1;
607
608
0
      memcpy((*pc_to_rdr_secure) + sizeof *secure + 1 + sizeof *modify + 3,
609
0
          pinapdu, pinapdu_len);
610
0
      break;
611
612
0
    default:
613
0
      r = SC_ERROR_INVALID_ARGUMENTS;
614
0
      goto err;
615
0
  }
616
617
0
  r = SC_SUCCESS;
618
619
0
err:
620
0
  free(pinapdu);
621
0
  if (r < 0 && pc_to_rdr_secure && *pc_to_rdr_secure) {
622
0
    free(*pc_to_rdr_secure);
623
0
    *pc_to_rdr_secure = NULL;
624
0
  }
625
626
0
  return r;
627
0
}
628
629
0
#define CCID_BSTATUS_OK_ACTIVE 0x00 /** No error. An ICC is present and active */
630
static int escape_buf_to_verify_result(sc_context_t *ctx,
631
    const unsigned char *rdr_to_pc_datablock,
632
    size_t rdr_to_pc_datablock_len,
633
    sc_apdu_t *apdu)
634
0
{
635
0
  RDR_to_PC_DataBlock_t *datablock =
636
0
    (RDR_to_PC_DataBlock_t *) rdr_to_pc_datablock;
637
638
0
  if (!rdr_to_pc_datablock
639
0
      || rdr_to_pc_datablock_len < sizeof *datablock
640
0
      || datablock->bMessageType != 0x80)
641
0
    return SC_ERROR_UNKNOWN_DATA_RECEIVED;
642
643
0
  if (datablock->bStatus != CCID_BSTATUS_OK_ACTIVE)
644
0
    return SC_ERROR_TRANSMIT_FAILED;
645
646
0
  return sc_apdu_set_resp(ctx, apdu,
647
0
      rdr_to_pc_datablock + sizeof *datablock,
648
0
      htole32(datablock->dwLength));
649
0
}
650
651
static int escape_perform_verify(struct sc_reader *reader,
652
    struct sc_pin_cmd_data *data)
653
0
{
654
0
  u8 rbuf[0xff];
655
0
  sc_apdu_t apdu;
656
0
  int r;
657
658
0
  memset(&apdu, 0, sizeof(apdu));
659
0
  apdu.cse     = SC_APDU_CASE_4_SHORT;
660
0
  apdu.cla     = escape_cla;
661
0
  apdu.ins     = escape_ins;
662
0
  apdu.p1      = escape_p1_PIN;
663
0
  apdu.p2      = escape_p2_PC_to_RDR_Secure;
664
0
  apdu.resp    = rbuf;
665
0
  apdu.resplen = sizeof rbuf;
666
0
  apdu.le      = sizeof rbuf;
667
668
0
  if (!reader || !reader->ops || !reader->ops->transmit) {
669
0
    r = SC_ERROR_NOT_SUPPORTED;
670
0
    goto err;
671
0
  }
672
673
0
  r = escape_pin_cmd_to_buf(reader->ctx, data,
674
0
      (unsigned char **) &apdu.data, &apdu.datalen);
675
0
  if (r < 0) {
676
0
    sc_log(reader->ctx,
677
0
        "Error encoding PC_to_RDR_Secure");
678
0
    goto err;
679
0
  }
680
0
  apdu.lc = apdu.datalen;
681
682
0
  r = reader->ops->transmit(reader, &apdu);
683
0
  if (r < 0) {
684
0
    sc_log(reader->ctx,
685
0
        "Error performing PC_to_RDR_Secure");
686
0
    goto err;
687
0
  }
688
689
0
  if (apdu.sw1 != 0x90 && apdu.sw2 != 0x00) {
690
0
    sc_log(reader->ctx,
691
0
        "Error decoding PC_to_RDR_Secure");
692
0
    r = SC_ERROR_NOT_SUPPORTED;
693
0
    goto err;
694
0
  }
695
696
0
  r = escape_buf_to_verify_result(reader->ctx, apdu.resp, apdu.resplen,
697
0
      data->apdu);
698
699
0
err:
700
0
  free((unsigned char *) apdu.data);
701
702
0
  return r;
703
0
}
704
705
static int escape_perform_pace(struct sc_reader *reader,
706
    void *establish_pace_channel_input,
707
    void *establish_pace_channel_output)
708
0
{
709
0
  u8 rbuf[0xffff];
710
0
  sc_apdu_t apdu;
711
0
  int r;
712
0
  struct establish_pace_channel_input  *input  =
713
0
    establish_pace_channel_input;
714
0
  struct establish_pace_channel_output *output =
715
0
    establish_pace_channel_output;
716
717
0
  memset(&apdu, 0, sizeof(apdu));
718
0
  apdu.cse     = SC_APDU_CASE_4_EXT;
719
0
  apdu.cla     = escape_cla;
720
0
  apdu.ins     = escape_ins;
721
0
  apdu.p1      = escape_p1_PIN;
722
0
  apdu.p2      = escape_p2_EstablishPACEChannel;
723
0
  apdu.resp    = rbuf;
724
0
  apdu.resplen = sizeof rbuf;
725
0
  apdu.le      = sizeof rbuf;
726
727
0
  if (!reader || !reader->ops || !reader->ops->transmit) {
728
0
    r = SC_ERROR_NOT_SUPPORTED;
729
0
    goto err;
730
0
  }
731
732
0
  r = escape_pace_input_to_buf(reader->ctx, input,
733
0
      (unsigned char **) &apdu.data, &apdu.datalen);
734
0
  if (r < 0) {
735
0
    sc_log(reader->ctx,
736
0
        "Error encoding EstablishPACEChannel");
737
0
    goto err;
738
0
  }
739
0
  apdu.lc = apdu.datalen;
740
741
0
  r = reader->ops->transmit(reader, &apdu);
742
0
  if (r < 0) {
743
0
    sc_log(reader->ctx,
744
0
        "Error performing EstablishPACEChannel");
745
0
    goto err;
746
0
  }
747
748
0
  if (apdu.sw1 != 0x90 && apdu.sw2 != 0x00) {
749
0
    sc_log(reader->ctx,
750
0
        "Error decoding EstablishPACEChannel");
751
0
    r = SC_ERROR_NOT_SUPPORTED;
752
0
    goto err;
753
0
  }
754
755
0
  r = escape_buf_to_pace_output(reader->ctx, apdu.resp, apdu.resplen,
756
0
      output);
757
758
0
err:
759
0
  free((unsigned char *) apdu.data);
760
761
0
  return r;
762
0
}
763
764
struct sc_asn1_entry g_PACECapabilities_data[] = {
765
  { "capabilityPACE",
766
    SC_ASN1_STRUCT, SC_ASN1_CTX|0x01|SC_ASN1_CONS, SC_ASN1_ALLOC, NULL, NULL },
767
  { "capabilityEID",
768
    SC_ASN1_STRUCT, SC_ASN1_CTX|0x02|SC_ASN1_CONS, SC_ASN1_ALLOC, NULL, NULL },
769
  { "capabilityESign",
770
    SC_ASN1_STRUCT, SC_ASN1_CTX|0x03|SC_ASN1_CONS, SC_ASN1_ALLOC, NULL, NULL },
771
  { "capabilityDestroy",
772
    SC_ASN1_STRUCT, SC_ASN1_CTX|0x04|SC_ASN1_CONS, SC_ASN1_ALLOC, NULL, NULL },
773
  { NULL , 0 , 0 , 0 , NULL , NULL }
774
};
775
struct sc_asn1_entry g_PACECapabilities[] = {
776
  { "PACECapabilities",
777
    SC_ASN1_STRUCT, SC_ASN1_TAG_SEQUENCE|SC_ASN1_CONS, 0, NULL, NULL },
778
  { NULL , 0 , 0 , 0 , NULL , NULL }
779
};
780
781
int escape_buf_to_pace_capabilities(sc_context_t *ctx,
782
    const unsigned char *asn1, size_t asn1_len,
783
    unsigned long *sc_reader_t_capabilities)
784
0
{
785
0
  int pace = 0, eid = 0, esign = 0, destroy = 0;
786
0
  struct sc_asn1_entry PACECapabilities_data[
787
0
    sizeof g_PACECapabilities_data/
788
0
    sizeof *g_PACECapabilities_data];
789
0
  struct sc_asn1_entry PACECapabilities[
790
0
    sizeof g_PACECapabilities/
791
0
    sizeof *g_PACECapabilities];
792
0
  struct sc_asn1_entry capabilityPACE[
793
0
    sizeof g_boolean/
794
0
    sizeof *g_boolean];
795
0
  struct sc_asn1_entry capabilityEID[
796
0
    sizeof g_boolean/
797
0
    sizeof *g_boolean];
798
0
  struct sc_asn1_entry capabilityESign[
799
0
    sizeof g_boolean/
800
0
    sizeof *g_boolean];
801
0
  struct sc_asn1_entry capabilityDestroy[
802
0
    sizeof g_boolean/
803
0
    sizeof *g_boolean];
804
805
0
  sc_copy_asn1_entry(g_PACECapabilities,
806
0
      PACECapabilities);
807
0
  sc_format_asn1_entry(PACECapabilities,
808
0
      PACECapabilities_data, 0, 1);
809
810
0
  sc_copy_asn1_entry(g_PACECapabilities_data,
811
0
      PACECapabilities_data);
812
0
  sc_format_asn1_entry(PACECapabilities_data+0,
813
0
      &capabilityPACE, NULL, 1);
814
0
  sc_format_asn1_entry(PACECapabilities_data+1,
815
0
      &capabilityEID, NULL, 1);
816
0
  sc_format_asn1_entry(PACECapabilities_data+2,
817
0
      &capabilityESign, NULL, 1);
818
0
  sc_format_asn1_entry(PACECapabilities_data+3,
819
0
      &capabilityDestroy, NULL, 1);
820
821
0
  sc_copy_asn1_entry(g_boolean,
822
0
      capabilityPACE);
823
0
  sc_format_asn1_entry(capabilityPACE+0,
824
0
      &pace, NULL, 0);
825
826
0
  sc_copy_asn1_entry(g_boolean,
827
0
      capabilityEID);
828
0
  sc_format_asn1_entry(capabilityEID+0,
829
0
      &eid, NULL, 0);
830
831
0
  sc_copy_asn1_entry(g_boolean,
832
0
      capabilityESign);
833
0
  sc_format_asn1_entry(capabilityESign+0,
834
0
      &esign, NULL, 0);
835
836
0
  sc_copy_asn1_entry(g_boolean,
837
0
      capabilityDestroy);
838
0
  sc_format_asn1_entry(capabilityDestroy+0,
839
0
      &destroy, NULL, 0);
840
841
0
  LOG_TEST_RET(ctx,
842
0
      sc_asn1_decode(ctx, PACECapabilities,
843
0
        asn1, asn1_len, NULL, NULL),
844
0
      "Error decoding PACECapabilities");
845
846
  /* We got a valid PACE Capabilities reply. There is currently no mechanism
847
   * to determine support PIN verification/modification with a escape
848
   * command. Since the reader implements this mechanism it is reasonable to
849
   * assume that PIN verification/modification is available. */
850
0
  *sc_reader_t_capabilities = SC_READER_CAP_PIN_PAD;
851
852
0
  if (pace)
853
0
    *sc_reader_t_capabilities |= SC_READER_CAP_PACE_GENERIC;
854
0
  if (eid)
855
0
    *sc_reader_t_capabilities |= SC_READER_CAP_PACE_EID;
856
0
  if (esign)
857
0
    *sc_reader_t_capabilities |= SC_READER_CAP_PACE_ESIGN;
858
0
  if (destroy)
859
0
    *sc_reader_t_capabilities |= SC_READER_CAP_PACE_DESTROY_CHANNEL;
860
861
0
  return SC_SUCCESS;
862
0
}
863
864
int escape_pace_capabilities_to_buf(sc_context_t *ctx,
865
    const unsigned long sc_reader_t_capabilities,
866
    unsigned char **asn1, size_t *asn1_len)
867
0
{
868
0
  int yes = 1, no = 0;
869
0
  struct sc_asn1_entry PACECapabilities_data[
870
0
    sizeof g_PACECapabilities_data/
871
0
    sizeof *g_PACECapabilities_data];
872
0
  struct sc_asn1_entry PACECapabilities[
873
0
    sizeof g_PACECapabilities/
874
0
    sizeof *g_PACECapabilities];
875
0
  struct sc_asn1_entry capabilityPACE[
876
0
    sizeof g_boolean/
877
0
    sizeof *g_boolean];
878
0
  struct sc_asn1_entry capabilityEID[
879
0
    sizeof g_boolean/
880
0
    sizeof *g_boolean];
881
0
  struct sc_asn1_entry capabilityESign[
882
0
    sizeof g_boolean/
883
0
    sizeof *g_boolean];
884
0
  struct sc_asn1_entry capabilityDestroy[
885
0
    sizeof g_boolean/
886
0
    sizeof *g_boolean];
887
888
0
  sc_copy_asn1_entry(g_EstablishPACEChannel,
889
0
      PACECapabilities);
890
0
  sc_format_asn1_entry(PACECapabilities,
891
0
      PACECapabilities_data, 0, 1);
892
893
0
  sc_copy_asn1_entry(g_PACECapabilities_data,
894
0
      PACECapabilities_data);
895
0
  sc_format_asn1_entry(PACECapabilities_data+0,
896
0
      &capabilityPACE, NULL, 1);
897
0
  sc_format_asn1_entry(PACECapabilities_data+1,
898
0
      &capabilityEID, NULL, 1);
899
0
  sc_format_asn1_entry(PACECapabilities_data+2,
900
0
      &capabilityESign, NULL, 1);
901
0
  sc_format_asn1_entry(PACECapabilities_data+3,
902
0
      &capabilityDestroy, NULL, 1);
903
904
0
  sc_copy_asn1_entry(g_boolean,
905
0
      capabilityPACE);
906
0
  sc_format_asn1_entry(capabilityPACE,
907
0
      sc_reader_t_capabilities & SC_READER_CAP_PACE_GENERIC
908
0
      ? &yes : &no, NULL, 1);
909
910
0
  sc_copy_asn1_entry(g_boolean,
911
0
      capabilityEID);
912
0
  sc_format_asn1_entry(capabilityEID,
913
0
      sc_reader_t_capabilities & SC_READER_CAP_PACE_EID
914
0
      ? &yes : &no, NULL, 1);
915
916
0
  sc_copy_asn1_entry(g_boolean,
917
0
      capabilityESign);
918
0
  sc_format_asn1_entry(capabilityESign,
919
0
      sc_reader_t_capabilities & SC_READER_CAP_PACE_ESIGN
920
0
      ? &yes : &no, NULL, 1);
921
922
0
  sc_copy_asn1_entry(g_boolean,
923
0
      capabilityDestroy);
924
0
  sc_format_asn1_entry(capabilityDestroy,
925
0
      sc_reader_t_capabilities & SC_READER_CAP_PACE_DESTROY_CHANNEL
926
0
      ? &yes : &no, NULL, 1);
927
928
0
  return sc_asn1_encode(ctx, PACECapabilities, asn1, asn1_len);
929
0
}
930
931
0
#define MAX_RESPLEN 0xFF
932
void sc_detect_escape_cmds(sc_reader_t *reader)
933
0
{
934
0
  int error = 0;
935
0
  u8 rbuf[MAX_RESPLEN + 1];
936
0
  sc_apdu_t apdu;
937
0
  unsigned long capabilities;
938
939
0
  if (reader && reader->ops && reader->ops->transmit) {
940
0
    memset(&apdu, 0, sizeof(apdu));
941
0
    apdu.cse     = SC_APDU_CASE_2_SHORT;
942
0
    apdu.cla     = escape_cla;
943
0
    apdu.ins     = escape_ins;
944
0
    apdu.p1      = escape_p1_PIN;
945
0
    apdu.p2      = escape_p2_GetReaderPACECapabilities;
946
0
    apdu.resp    = rbuf;
947
0
    apdu.resplen = MAX_RESPLEN;
948
0
    apdu.le      = MAX_RESPLEN;
949
950
0
    if (reader->ops->transmit(reader, &apdu) == SC_SUCCESS
951
0
        && apdu.sw1 == 0x90 && apdu.sw2 == 0x00
952
0
        && escape_buf_to_pace_capabilities(reader->ctx,
953
0
          apdu.resp, apdu.resplen, &capabilities) == SC_SUCCESS) {
954
0
      if (capabilities & SC_READER_CAP_PIN_PAD
955
0
          && !(reader->capabilities & SC_READER_CAP_PIN_PAD)) {
956
0
        ((struct sc_reader_operations *) reader->ops)->perform_verify =
957
0
          escape_perform_verify;
958
0
        sc_log(reader->ctx,
959
0
            "Added escape command wrappers for PIN verification/modification to '%s'", reader->name);
960
0
      }
961
962
0
      if (capabilities & SC_READER_CAP_PACE_GENERIC
963
0
          && !(reader->capabilities & SC_READER_CAP_PACE_GENERIC)) {
964
0
        ((struct sc_reader_operations *) reader->ops)->perform_pace =
965
0
          escape_perform_pace;
966
0
        sc_log(reader->ctx,
967
0
            "Added escape command wrappers for PACE to '%s'", reader->name);
968
0
      }
969
970
0
      reader->capabilities |= capabilities;
971
0
    } else {
972
0
      error++;
973
0
      sc_log(reader->ctx,
974
0
          "%s does not support escape commands", reader->name);
975
0
    }
976
977
0
    apdu.p1      = escape_p1_IFD;
978
0
    apdu.p2      = escape_p2_vendor;
979
0
    apdu.resplen = MAX_RESPLEN;
980
0
    if (reader->ops->transmit(reader, &apdu) == SC_SUCCESS
981
0
        && apdu.sw1 == 0x90 && apdu.sw2 == 0x00) {
982
0
      if (!reader->vendor) {
983
        /* add NUL termination, just in case... */
984
0
        rbuf[apdu.resplen] = '\0';
985
0
        reader->vendor = strdup((const char *) rbuf);
986
0
      }
987
0
    } else {
988
0
      error++;
989
0
    }
990
991
0
    apdu.p1      = escape_p1_IFD;
992
0
    apdu.p2      = escape_p2_version_firmware;
993
0
    apdu.resplen = MAX_RESPLEN;
994
0
    if (reader->ops->transmit(reader, &apdu) == SC_SUCCESS
995
0
        && apdu.sw1 == 0x90 && apdu.sw2 == 0x00) {
996
0
      if (!reader->version_major && !reader->version_minor) {
997
0
        unsigned int major = 0, minor = 0;
998
        /* add NUL termination, just in case... */
999
0
        rbuf[apdu.resplen] = '\0';
1000
0
        sscanf((const char *) rbuf, "%u.%u", &major, &minor);
1001
0
        reader->version_major = major>0xff ? 0xff : major;
1002
0
        reader->version_minor = minor>0xff ? 0xff : minor;
1003
0
      }
1004
0
    } else {
1005
0
      error++;
1006
0
    }
1007
0
  }
1008
1009
0
  if (error && reader) {
1010
0
    sc_log(reader->ctx,
1011
0
        "%d escape command%s failed, need to reset the card",
1012
0
        error, error == 1 ? "" : "s");
1013
0
    if (reader->ops && reader->ops->transmit) {
1014
0
      memset(&apdu, 0, sizeof(apdu));
1015
0
      apdu.cse     = SC_APDU_CASE_3_SHORT;
1016
0
      apdu.cla     = 0x00;
1017
0
      apdu.ins     = 0xA4;
1018
0
      apdu.p1      = 8;
1019
0
      apdu.p2      = 0x0C;
1020
0
      apdu.data    = rbuf;
1021
0
      rbuf[0] = 0x3F;
1022
0
      rbuf[1] = 0x00;
1023
0
      apdu.datalen = 2;
1024
0
      apdu.lc      = 2;
1025
      apdu.resp    = NULL;
1026
0
      apdu.resplen = 0;
1027
0
      apdu.le      = 0;
1028
0
      reader->ops->transmit(reader, &apdu);
1029
0
    }
1030
0
  }
1031
0
}