Coverage Report

Created: 2025-11-24 06:43

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/opensc/src/libopensc/iso7816.c
Line
Count
Source
1
/*
2
 * iso7816.c: Functions specified by the ISO 7816 standard
3
 *
4
 * Copyright (C) 2001, 2002  Juha Yrjölä <juha.yrjola@iki.fi>
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
#include "config.h"
22
23
#include <assert.h>
24
#include <ctype.h>
25
#include <stdlib.h>
26
#include <string.h>
27
28
#include "internal.h"
29
#include "asn1.h"
30
#include "iso7816.h"
31
#include "sm/sm-iso.h"
32
33
void
34
iso7816_fixup_transceive_length(const struct sc_card *card,
35
    struct sc_apdu *apdu)
36
49.4k
{
37
49.4k
  if (card == NULL || apdu == NULL) {
38
0
    return;
39
0
  }
40
41
49.4k
  if (apdu->lc > sc_get_max_send_size(card)) {
42
    /* The lower layers will automatically do chaining */
43
635
    apdu->flags |= SC_APDU_FLAGS_CHAINING;
44
635
  }
45
46
49.4k
  if (apdu->le > sc_get_max_recv_size(card)) {
47
    /* The lower layers will automatically do a GET RESPONSE, if possible.
48
     * All other workarounds must be carried out by the upper layers. */
49
2.25k
    apdu->le = sc_get_max_recv_size(card);
50
2.25k
  }
51
49.4k
}
52
53
54
static const struct sc_card_error iso7816_errors[] = {
55
  { 0x6200, SC_ERROR_CARD_CMD_FAILED, "Warning: no information given, non-volatile memory is unchanged" },
56
  { 0x6281, SC_ERROR_CORRUPTED_DATA,  "Part of returned data may be corrupted" },
57
  { 0x6282, SC_ERROR_FILE_END_REACHED,  "End of file/record reached before reading Le bytes" },
58
  { 0x6283, SC_ERROR_CARD_CMD_FAILED, "Selected file invalidated" },
59
  { 0x6284, SC_ERROR_CARD_CMD_FAILED, "FCI not formatted according to ISO 7816-4" },
60
  { 0x6285, SC_ERROR_CARD_CMD_FAILED, "Selected file in termination state" },
61
  { 0x6286, SC_ERROR_CARD_CMD_FAILED, "No input data available from a sensor on the card" },
62
63
  { 0x6300, SC_ERROR_CARD_CMD_FAILED, "Warning: no information given, non-volatile memory has changed" },
64
  { 0x6381, SC_ERROR_CARD_CMD_FAILED, "Warning: file filled up by last write" },
65
66
  { 0x6400, SC_ERROR_CARD_CMD_FAILED, "Execution error" },
67
  { 0x6401, SC_ERROR_CARD_CMD_FAILED, "Immediate response required by the card" },
68
69
  { 0x6581, SC_ERROR_MEMORY_FAILURE,  "Memory failure" },
70
71
  { 0x6700, SC_ERROR_WRONG_LENGTH,  "Wrong length" },
72
73
  { 0x6800, SC_ERROR_NO_CARD_SUPPORT, "Functions in CLA not supported" },
74
  { 0x6881, SC_ERROR_NO_CARD_SUPPORT, "Logical channel not supported" },
75
  { 0x6882, SC_ERROR_NO_CARD_SUPPORT, "Secure messaging not supported" },
76
  { 0x6883, SC_ERROR_CARD_CMD_FAILED, "Last command of the chain expected" },
77
  { 0x6884, SC_ERROR_NO_CARD_SUPPORT, "Command chaining not supported" },
78
79
  { 0x6900, SC_ERROR_NOT_ALLOWED,   "Command not allowed" },
80
  { 0x6981, SC_ERROR_CARD_CMD_FAILED, "Command incompatible with file structure" },
81
  { 0x6982, SC_ERROR_SECURITY_STATUS_NOT_SATISFIED,"Security status not satisfied" },
82
  { 0x6983, SC_ERROR_AUTH_METHOD_BLOCKED, "Authentication method blocked" },
83
  { 0x6984, SC_ERROR_REF_DATA_NOT_USABLE, "Referenced data not usable" },
84
  { 0x6985, SC_ERROR_NOT_ALLOWED,   "Conditions of use not satisfied" },
85
  { 0x6986, SC_ERROR_NOT_ALLOWED,   "Command not allowed (no current EF)" },
86
  { 0x6987, SC_ERROR_INCORRECT_PARAMETERS,"Expected SM data objects missing" },
87
  { 0x6988, SC_ERROR_INCORRECT_PARAMETERS,"Incorrect SM data objects" },
88
89
  { 0x6A00, SC_ERROR_INCORRECT_PARAMETERS,"Wrong parameter(s) P1-P2" },
90
  { 0x6A80, SC_ERROR_INCORRECT_PARAMETERS,"Incorrect parameters in the data field" },
91
  { 0x6A81, SC_ERROR_NO_CARD_SUPPORT, "Function not supported" },
92
  { 0x6A82, SC_ERROR_FILE_NOT_FOUND,  "File or application not found" },
93
  { 0x6A83, SC_ERROR_RECORD_NOT_FOUND,  "Record not found" },
94
  { 0x6A84, SC_ERROR_NOT_ENOUGH_MEMORY, "Not enough memory space in the file" },
95
  { 0x6A85, SC_ERROR_INCORRECT_PARAMETERS,"Lc inconsistent with TLV structure" },
96
  { 0x6A86, SC_ERROR_INCORRECT_PARAMETERS,"Incorrect parameters P1-P2" },
97
  { 0x6A87, SC_ERROR_INCORRECT_PARAMETERS,"Lc inconsistent with P1-P2" },
98
  { 0x6A88, SC_ERROR_DATA_OBJECT_NOT_FOUND,"Referenced data not found" },
99
  { 0x6A89, SC_ERROR_FILE_ALREADY_EXISTS, "File already exists"},
100
  { 0x6A8A, SC_ERROR_FILE_ALREADY_EXISTS, "DF name already exists"},
101
102
  { 0x6B00, SC_ERROR_INCORRECT_PARAMETERS,"Wrong parameter(s) P1-P2" },
103
  { 0x6D00, SC_ERROR_INS_NOT_SUPPORTED, "Instruction code not supported or invalid" },
104
  { 0x6E00, SC_ERROR_CLASS_NOT_SUPPORTED, "Class not supported" },
105
  { 0x6F00, SC_ERROR_CARD_CMD_FAILED, "No precise diagnosis" },
106
};
107
108
109
static int
110
iso7816_check_sw(struct sc_card *card, unsigned int sw1, unsigned int sw2)
111
469k
{
112
469k
  const int err_count = sizeof(iso7816_errors)/sizeof(iso7816_errors[0]);
113
469k
  int i;
114
115
  /* Handle special cases here */
116
469k
  if (sw1 == 0x6C) {
117
132
    sc_log(card->ctx, "Wrong length; correct length is %d", sw2);
118
132
    return SC_ERROR_WRONG_LENGTH;
119
132
  }
120
468k
  if (sw1 == 0x90 && sw2 == 0x00)
121
207k
    return SC_SUCCESS;
122
261k
  if (sw1 == 0x63U && (sw2 & ~0x0fU) == 0xc0U) {
123
167
    sc_log(card->ctx, "PIN not verified (remaining tries: %d)", (sw2 & 0x0f));
124
167
    return SC_ERROR_PIN_CODE_INCORRECT;
125
167
  }
126
10.6M
  for (i = 0; i < err_count; i++)   {
127
10.6M
    if (iso7816_errors[i].SWs == ((sw1 << 8) | sw2)) {
128
234k
      sc_log(card->ctx, "%s", iso7816_errors[i].errorstr);
129
234k
      return iso7816_errors[i].errorno;
130
234k
    }
131
10.6M
  }
132
133
26.2k
  sc_log(card->ctx, "Unknown SWs; SW1=%02X, SW2=%02X", sw1, sw2);
134
26.2k
  return SC_ERROR_CARD_CMD_FAILED;
135
260k
}
136
137
138
static int
139
iso7816_read_binary(struct sc_card *card, unsigned int idx, u8 *buf, size_t count, unsigned long *flags)
140
24.4k
{
141
24.4k
  struct sc_context *ctx = card->ctx;
142
24.4k
  struct sc_apdu apdu;
143
24.4k
  int r;
144
145
24.4k
  if (idx > 0x7FFF) {
146
4
    sc_log(ctx, "invalid EF offset: 0x%X > 0x7FFF", idx);
147
4
    return SC_ERROR_OFFSET_TOO_LARGE;
148
4
  }
149
150
24.3k
  sc_format_apdu(card, &apdu, SC_APDU_CASE_2, 0xB0, (idx >> 8) & 0x7F, idx & 0xFF);
151
24.3k
  apdu.le = count;
152
24.3k
  apdu.resplen = count;
153
24.3k
  apdu.resp = buf;
154
155
24.3k
  iso7816_fixup_transceive_length(card, &apdu);
156
24.3k
  r = sc_transmit_apdu(card, &apdu);
157
24.3k
  LOG_TEST_RET(ctx, r, "APDU transmit failed");
158
159
23.9k
  r = sc_check_sw(card, apdu.sw1, apdu.sw2);
160
23.9k
  if (r == SC_ERROR_FILE_END_REACHED)
161
23.9k
    LOG_FUNC_RETURN(ctx, (int)apdu.resplen);
162
22.6k
  LOG_TEST_RET(ctx, r, "Check SW error");
163
164
20.6k
  LOG_FUNC_RETURN(ctx, (int)apdu.resplen);
165
20.6k
}
166
167
168
const struct sc_asn1_entry c_asn1_do_data[] = {
169
  { "Offset Data Object", SC_ASN1_OCTET_STRING, SC_ASN1_APP|0x14, SC_ASN1_OPTIONAL, NULL, NULL },
170
  { "Discretionary Data Object", SC_ASN1_OCTET_STRING, SC_ASN1_APP|0x13, SC_ASN1_ALLOC|SC_ASN1_UNSIGNED|SC_ASN1_OPTIONAL, NULL, NULL },
171
  { NULL, 0, 0, 0, NULL, NULL }
172
};
173
174
int encode_do_data(struct sc_context *ctx,
175
    unsigned int idx, const unsigned char *data, size_t data_len,
176
    u8 **out, size_t *outlen)
177
12.0k
{
178
12.0k
  unsigned char offset_buffer[2];
179
12.0k
  size_t offset_buffer_len = sizeof offset_buffer;
180
12.0k
  struct sc_asn1_entry asn1_do_data[sizeof c_asn1_do_data / sizeof *c_asn1_do_data];
181
12.0k
  sc_copy_asn1_entry(c_asn1_do_data, asn1_do_data);
182
183
12.0k
  if (idx > 0xFFFF)
184
12.0k
    LOG_TEST_RET(ctx, SC_ERROR_INTERNAL, "Offset beyond 0xFFFF not supported");
185
12.0k
  offset_buffer[0] = (u8) (idx >> 8);
186
12.0k
  offset_buffer[1] = (u8) (idx & 0x00FF);
187
12.0k
  sc_format_asn1_entry(asn1_do_data + 0, offset_buffer, &offset_buffer_len, 1);
188
189
12.0k
  if (data && data_len) {
190
0
    sc_format_asn1_entry(asn1_do_data + 1, (void *) &data, &data_len, 1);
191
12.0k
  } else {
192
12.0k
    sc_format_asn1_entry(asn1_do_data + 1, NULL, NULL, 0);
193
12.0k
  }
194
195
12.0k
  LOG_TEST_RET(ctx,
196
12.0k
      sc_asn1_encode(ctx, asn1_do_data, out, outlen),
197
12.0k
      "sc_asn1_encode() failed");
198
199
12.0k
  return SC_SUCCESS;
200
12.0k
}
201
202
int decode_do_data(struct sc_context *ctx,
203
    const unsigned char *encoded_data, size_t encoded_data_len,
204
    u8 **out, size_t *outlen)
205
9.24k
{
206
9.24k
  struct sc_asn1_entry asn1_do_data[sizeof c_asn1_do_data / sizeof *c_asn1_do_data];
207
9.24k
  sc_copy_asn1_entry(c_asn1_do_data, asn1_do_data);
208
209
9.24k
  sc_format_asn1_entry(asn1_do_data + 0, NULL, NULL, 0);
210
9.24k
  sc_format_asn1_entry(asn1_do_data + 1, out, outlen, 0);
211
212
9.24k
  LOG_TEST_RET(ctx,
213
8.19k
      sc_asn1_decode(ctx, asn1_do_data, encoded_data, encoded_data_len, NULL, NULL),
214
8.19k
      "sc_asn1_decode() failed");
215
216
8.19k
  if (!(asn1_do_data[1].flags & SC_ASN1_PRESENT))
217
6.77k
    return SC_ERROR_INVALID_ASN1_OBJECT;
218
219
1.41k
  return SC_SUCCESS;
220
8.19k
}
221
222
static int
223
iso7816_read_record(struct sc_card *card, unsigned int rec_nr, unsigned int idx,
224
    u8 *buf, size_t count, unsigned long flags)
225
24.8k
{
226
24.8k
  struct sc_apdu apdu;
227
24.8k
  int r;
228
  /* XXX maybe use some bigger buffer */
229
24.8k
  unsigned char resp[SC_MAX_APDU_RESP_SIZE];
230
24.8k
  unsigned char *encoded_data = NULL, *decoded_data = NULL;
231
24.8k
  size_t encoded_data_len = 0, decoded_data_len = 0;
232
233
24.8k
  if (rec_nr > 0xFF)
234
24.8k
    LOG_FUNC_RETURN(card->ctx, SC_ERROR_INVALID_ARGUMENTS);
235
236
24.8k
  if (idx == 0) {
237
12.8k
    sc_format_apdu(card, &apdu, SC_APDU_CASE_2, 0xB2, rec_nr, 0);
238
12.8k
    apdu.le = count;
239
12.8k
    apdu.resplen = count;
240
12.8k
    apdu.resp = buf;
241
12.8k
  } else {
242
12.0k
    r = encode_do_data(card->ctx, idx, NULL, 0, &encoded_data, &encoded_data_len);
243
12.0k
    LOG_TEST_GOTO_ERR(card->ctx, r, "Could not encode data objects");
244
245
12.0k
    sc_format_apdu(card, &apdu, SC_APDU_CASE_4, 0xB3, rec_nr, 0);
246
12.0k
    apdu.lc = encoded_data_len;
247
12.0k
    apdu.datalen = encoded_data_len;
248
12.0k
    apdu.data = encoded_data;
249
12.0k
    apdu.le = sizeof resp;
250
12.0k
    apdu.resplen = sizeof resp;
251
12.0k
    apdu.resp = resp;
252
12.0k
  }
253
24.8k
  apdu.p2 = (flags & SC_RECORD_EF_ID_MASK) << 3;
254
24.8k
  if (flags & SC_RECORD_BY_REC_NR)
255
24.8k
    apdu.p2 |= 0x04;
256
257
24.8k
  iso7816_fixup_transceive_length(card, &apdu);
258
24.8k
  r = sc_transmit_apdu(card, &apdu);
259
24.8k
  LOG_TEST_GOTO_ERR(card->ctx, r, "APDU transmit failed");
260
23.5k
  r = sc_check_sw(card, apdu.sw1, apdu.sw2);
261
23.5k
  LOG_TEST_GOTO_ERR(card->ctx, r, "Card returned error");
262
263
20.5k
  if (idx == 0) {
264
11.3k
    r = (int)apdu.resplen;
265
11.3k
  } else {
266
9.24k
    r = decode_do_data(card->ctx, apdu.resp, apdu.resplen,
267
9.24k
        &decoded_data, &decoded_data_len);
268
9.24k
    LOG_TEST_GOTO_ERR(card->ctx, r, "Could not decode data objects");
269
1.41k
    if (decoded_data_len <= count) {
270
1.30k
      count = decoded_data_len;
271
1.30k
    }
272
1.41k
    memcpy(buf, decoded_data, count);
273
1.41k
    r = (int)count;
274
1.41k
  }
275
276
24.8k
err:
277
24.8k
  free(encoded_data);
278
24.8k
  free(decoded_data);
279
24.8k
  LOG_FUNC_RETURN(card->ctx, r);
280
24.8k
}
281
282
283
static int
284
iso7816_write_record(struct sc_card *card, unsigned int rec_nr,
285
    const u8 *buf, size_t count, unsigned long flags)
286
0
{
287
0
  struct sc_apdu apdu;
288
0
  int r;
289
290
0
  sc_format_apdu(card, &apdu, SC_APDU_CASE_3, 0xD2, rec_nr, 0);
291
0
  apdu.lc = count;
292
0
  apdu.datalen = count;
293
0
  apdu.data = buf;
294
0
  apdu.p2 = (flags & SC_RECORD_EF_ID_MASK) << 3;
295
0
  if (flags & SC_RECORD_BY_REC_NR)
296
0
    apdu.p2 |= 0x04;
297
298
0
  iso7816_fixup_transceive_length(card, &apdu);
299
0
  r = sc_transmit_apdu(card, &apdu);
300
0
  LOG_TEST_RET(card->ctx, r, "APDU transmit failed");
301
0
  r = sc_check_sw(card, apdu.sw1, apdu.sw2);
302
0
  LOG_TEST_RET(card->ctx, r, "Card returned error");
303
304
0
  LOG_FUNC_RETURN(card->ctx, (int)count);
305
0
}
306
307
308
static int
309
iso7816_append_record(struct sc_card *card,
310
    const u8 *buf, size_t count, unsigned long flags)
311
0
{
312
0
  struct sc_apdu apdu;
313
0
  int r;
314
315
0
  sc_format_apdu(card, &apdu, SC_APDU_CASE_3, 0xE2, 0, 0);
316
0
  apdu.lc = count;
317
0
  apdu.datalen = count;
318
0
  apdu.data = buf;
319
0
  apdu.p2 = (flags & SC_RECORD_EF_ID_MASK) << 3;
320
321
0
  iso7816_fixup_transceive_length(card, &apdu);
322
0
  r = sc_transmit_apdu(card, &apdu);
323
0
  LOG_TEST_RET(card->ctx, r, "APDU transmit failed");
324
0
  r = sc_check_sw(card, apdu.sw1, apdu.sw2);
325
0
  LOG_TEST_RET(card->ctx, r, "Card returned error");
326
327
0
  LOG_FUNC_RETURN(card->ctx, (int)count);
328
0
}
329
330
331
static int
332
iso7816_update_record(struct sc_card *card, unsigned int rec_nr, unsigned int idx,
333
    const u8 *buf, size_t count, unsigned long flags)
334
0
{
335
0
  struct sc_apdu apdu;
336
0
  int r;
337
0
  unsigned char *encoded_data = NULL;
338
0
  size_t encoded_data_len = 0;
339
340
0
  if (rec_nr > 0xFF)
341
0
    LOG_FUNC_RETURN(card->ctx, SC_ERROR_INVALID_ARGUMENTS);
342
343
0
  if (idx == 0) {
344
0
    sc_format_apdu(card, &apdu, SC_APDU_CASE_3, 0xDC, rec_nr, 0);
345
0
    apdu.lc = count;
346
0
    apdu.datalen = count;
347
0
    apdu.data = buf;
348
0
  } else {
349
0
    r = encode_do_data(card->ctx, idx, buf, count, &encoded_data, &encoded_data_len);
350
0
    LOG_TEST_GOTO_ERR(card->ctx, r, "Could not encode data objects");
351
352
0
    sc_format_apdu(card, &apdu, SC_APDU_CASE_3, 0xDD, rec_nr, 0);
353
0
    apdu.lc = encoded_data_len;
354
0
    apdu.datalen = encoded_data_len;
355
0
    apdu.data = encoded_data;
356
0
  }
357
0
  apdu.p2 = (flags & SC_RECORD_EF_ID_MASK) << 3;
358
0
  if (flags & SC_RECORD_BY_REC_NR)
359
0
    apdu.p2 |= 0x04;
360
361
0
  iso7816_fixup_transceive_length(card, &apdu);
362
0
  r = sc_transmit_apdu(card, &apdu);
363
0
  LOG_TEST_GOTO_ERR(card->ctx, r, "APDU transmit failed");
364
0
  r = sc_check_sw(card, apdu.sw1, apdu.sw2);
365
0
  LOG_TEST_GOTO_ERR(card->ctx, r, "Card returned error");
366
0
  r = (int)count;
367
368
0
err:
369
0
  free(encoded_data);
370
0
  LOG_FUNC_RETURN(card->ctx, r);
371
0
}
372
373
static int
374
iso7816_write_binary(struct sc_card *card,
375
    unsigned int idx, const u8 *buf, size_t count, unsigned long flags)
376
0
{
377
0
  struct sc_apdu apdu;
378
0
  int r;
379
380
0
  if (idx > 0x7fff) {
381
0
    sc_log(card->ctx, "invalid EF offset: 0x%X > 0x7FFF", idx);
382
0
    return SC_ERROR_OFFSET_TOO_LARGE;
383
0
  }
384
385
0
  sc_format_apdu(card, &apdu, SC_APDU_CASE_3, 0xD0,
386
0
           (idx >> 8) & 0x7F, idx & 0xFF);
387
0
  apdu.lc = count;
388
0
  apdu.datalen = count;
389
0
  apdu.data = buf;
390
391
0
  iso7816_fixup_transceive_length(card, &apdu);
392
0
  r = sc_transmit_apdu(card, &apdu);
393
0
  LOG_TEST_RET(card->ctx, r, "APDU transmit failed");
394
0
  r = sc_check_sw(card, apdu.sw1, apdu.sw2);
395
0
  LOG_TEST_RET(card->ctx, r, "Card returned error");
396
397
0
  LOG_FUNC_RETURN(card->ctx, (int)count);
398
0
}
399
400
401
static int
402
iso7816_update_binary(struct sc_card *card,
403
    unsigned int idx, const u8 *buf, size_t count, unsigned long flags)
404
0
{
405
0
  struct sc_apdu apdu;
406
0
  int r;
407
408
0
  if (idx > 0x7fff) {
409
0
    sc_log(card->ctx, "invalid EF offset: 0x%X > 0x7FFF", idx);
410
0
    return SC_ERROR_OFFSET_TOO_LARGE;
411
0
  }
412
413
0
  sc_format_apdu(card, &apdu, SC_APDU_CASE_3, 0xD6, (idx >> 8) & 0x7F, idx & 0xFF);
414
0
  apdu.lc = count;
415
0
  apdu.datalen = count;
416
0
  apdu.data = buf;
417
418
0
  iso7816_fixup_transceive_length(card, &apdu);
419
0
  r = sc_transmit_apdu(card, &apdu);
420
0
  LOG_TEST_RET(card->ctx, r, "APDU transmit failed");
421
0
  r = sc_check_sw(card, apdu.sw1, apdu.sw2);
422
0
  LOG_TEST_RET(card->ctx, r, "Card returned error");
423
424
0
  LOG_FUNC_RETURN(card->ctx, (int)count);
425
0
}
426
427
428
static int
429
iso7816_process_fci(struct sc_card *card, struct sc_file *file,
430
    const unsigned char *buf, size_t buflen)
431
8.23k
{
432
8.23k
  struct sc_context *ctx = card->ctx;
433
8.23k
  const unsigned char *p, *end;
434
8.23k
  unsigned int cla = 0, tag = 0;
435
8.23k
  size_t length;
436
437
8.23k
  file->status = SC_FILE_STATUS_UNKNOWN;
438
439
8.23k
  for (p = buf, length = buflen, end = buf + buflen;
440
23.4k
      p < end;
441
20.6k
      p += length, length = end - p) {
442
443
20.6k
    if (SC_SUCCESS != sc_asn1_read_tag(&p, length, &cla, &tag, &length)
444
16.8k
        || p == NULL) {
445
5.44k
      break;
446
5.44k
    }
447
15.1k
    switch (cla | tag) {
448
1.48k
      case 0x81:
449
1.48k
        if (file->size != 0) {
450
          /* don't overwrite existing file size excluding structural information */
451
84
          break;
452
84
        }
453
        /* fall through */
454
3.27k
      case 0x80:
455
        /* determine the file size */
456
3.27k
        file->size = 0;
457
3.27k
        if (p && length <= sizeof(size_t)) {
458
3.24k
          size_t size = 0, i;
459
10.5k
          for (i = 0; i < length; i++) {
460
7.32k
            size <<= 8;
461
7.32k
            size |= p[i];
462
7.32k
          }
463
3.24k
          if (size > MAX_FILE_SIZE) {
464
418
            file->size = MAX_FILE_SIZE;
465
418
            sc_log(ctx, "  file size truncated, encoded length: %"SC_FORMAT_LEN_SIZE_T"u", size);
466
2.82k
          } else {
467
2.82k
            file->size = size;
468
2.82k
          }
469
3.24k
        }
470
471
3.27k
        sc_log(ctx, "  bytes in file: %"SC_FORMAT_LEN_SIZE_T"u", file->size);
472
3.27k
        break;
473
474
1.80k
      case 0x82:
475
1.80k
        if (length > 0) {
476
1.55k
          unsigned char byte = p[0];
477
1.55k
          const char *type;
478
479
1.55k
          file->shareable = byte & 0x40 ? 1 : 0;
480
1.55k
          sc_log(ctx, "  shareable: %s", (byte & 0x40) ? "yes" : "no");
481
1.55k
          file->ef_structure = byte & 0x07;
482
1.55k
          switch ((byte >> 3) & 7) {
483
788
            case 0:
484
788
              type = "working EF";
485
788
              file->type = SC_FILE_TYPE_WORKING_EF;
486
788
              break;
487
271
            case 1:
488
271
              type = "internal EF";
489
271
              file->type = SC_FILE_TYPE_INTERNAL_EF;
490
271
              break;
491
237
            case 7:
492
237
              type = "DF";
493
237
              file->type = SC_FILE_TYPE_DF;
494
237
              break;
495
263
            default:
496
263
              file->type = SC_FILE_TYPE_UNKNOWN;
497
263
              type = "unknown";
498
263
              break;
499
1.55k
          }
500
1.55k
          sc_log(ctx, "  type: %s", type);
501
1.55k
          sc_log(ctx, "  EF structure: %d", byte & 0x07);
502
1.55k
          sc_log(ctx, "  tag 0x82: 0x%02x", byte);
503
504
          /* if possible, get additional information for non-DFs */
505
1.55k
          if (file->type != SC_FILE_TYPE_DF) {
506
            /* max. record length for fixed- & variable-sized records */
507
1.32k
            if (length > 2 && byte & 0x06) {
508
464
              file->record_length = (length > 3)
509
464
                ? bebytes2ushort(p+2)
510
464
                : p[2];
511
464
              sc_log(ctx, "  record length: %"SC_FORMAT_LEN_SIZE_T"u",
512
464
                file->record_length);
513
464
            }
514
515
            /* number of records */
516
1.32k
            if (length > 4) {
517
233
              file->record_count = (length > 5)
518
233
                ? bebytes2ushort(p+4)
519
233
                : p[4];
520
233
              sc_log(ctx, "  records: %"SC_FORMAT_LEN_SIZE_T"u",
521
233
                file->record_count);
522
233
            }
523
1.32k
          }
524
525
1.55k
          if (SC_SUCCESS != sc_file_set_type_attr(file, p, length))
526
0
            sc_log(ctx, "Warning: Could not set file attributes");
527
1.55k
        }
528
1.80k
        break;
529
530
1.80k
      case 0x83:
531
895
        if (length == 2) {
532
710
          file->id = (p[0] << 8) | p[1];
533
710
          sc_log(ctx, "  file identifier: 0x%02X%02X", p[0], p[1]);
534
710
        }
535
895
        break;
536
537
392
      case 0x84:
538
392
        if (length > 0 && length <= 16) {
539
306
          memcpy(file->name, p, length);
540
306
          file->namelen = length;
541
542
306
          sc_log_hex(ctx, "  File name:", file->name, file->namelen);
543
306
          if (!file->type)
544
173
            file->type = SC_FILE_TYPE_DF;
545
306
        }
546
392
        break;
547
548
829
      case 0x85:
549
1.06k
      case 0xA5:
550
1.06k
        if (SC_SUCCESS != sc_file_set_prop_attr(file, p, length)) {
551
0
          sc_log(ctx, "Warning: Could not set proprietary file properties");
552
0
        }
553
1.06k
        break;
554
555
1.15k
      case 0x86:
556
1.15k
        if (SC_SUCCESS != sc_file_set_sec_attr(file, p, length)) {
557
0
          sc_log(ctx, "Warning: Could not set file security properties");
558
0
        }
559
1.15k
        break;
560
561
380
      case 0x88:
562
380
        if (length == 1) {
563
87
          file->sid = *p;
564
87
          sc_log(ctx, "  short file identifier: 0x%02X", *p);
565
87
        }
566
380
        break;
567
568
1.30k
      case 0x8A:
569
1.30k
        if (length == 1) {
570
1.17k
          switch (p[0]) {
571
68
            case 0:
572
68
              file->status =SC_FILE_STATUS_NO_INFO;
573
68
              break;
574
70
            case 1:
575
70
              file->status = SC_FILE_STATUS_CREATION;
576
70
              break;
577
68
            case 3:
578
68
              file->status = SC_FILE_STATUS_INITIALISATION;
579
68
              break;
580
69
            case 4:
581
135
            case 6:
582
135
              file->status = SC_FILE_STATUS_INVALIDATED;
583
135
              break;
584
139
            case 5:
585
205
            case 7:
586
205
              file->status = SC_FILE_STATUS_ACTIVATED;
587
205
              break;
588
66
            case 12:
589
132
            case 13:
590
206
            case 14:
591
272
            case 15:
592
272
              file->status = SC_FILE_STATUS_TERMINATION;
593
272
              break;
594
34
            case 2:
595
34
              file->status = SC_FILE_STATUS_RFU_2;
596
34
              break;
597
66
            case 8:
598
66
              file->status = SC_FILE_STATUS_RFU_8;
599
66
              break;
600
36
            case 9:
601
36
              file->status = SC_FILE_STATUS_RFU_9;
602
36
              break;
603
66
            case 10:
604
66
              file->status = SC_FILE_STATUS_RFU_10;
605
66
              break;
606
72
            case 11:
607
72
              file->status = SC_FILE_STATUS_RFU_11;
608
72
              break;
609
78
            default:
610
78
              file->status = SC_FILE_STATUS_PROPRIETARY;
611
1.17k
          }
612
1.17k
        }
613
1.30k
        break;
614
615
1.30k
      case 0x62:
616
955
      case 0x64:
617
1.25k
      case 0x6F:
618
        /* allow nested FCP/FMD/FCI templates */
619
1.25k
        iso7816_process_fci(card, file, p, length);
620
15.1k
    }
621
15.1k
  }
622
623
8.23k
  file->magic = SC_FILE_MAGIC;
624
625
8.23k
  return SC_SUCCESS;
626
8.23k
}
627
628
629
static int
630
iso7816_select_file(struct sc_card *card, const struct sc_path *in_path, struct sc_file **file_out)
631
47.4k
{
632
47.4k
  struct sc_context *ctx;
633
47.4k
  struct sc_apdu apdu;
634
47.4k
  unsigned char buf[SC_MAX_APDU_BUFFER_SIZE];
635
47.4k
  unsigned char pathbuf[SC_MAX_PATH_SIZE], *path = pathbuf;
636
47.4k
  int r, pathtype;
637
47.4k
  size_t pathlen;
638
47.4k
  int select_mf = 0;
639
47.4k
  struct sc_file *file = NULL;
640
47.4k
  const u8 *buffer;
641
47.4k
  size_t buffer_len;
642
47.4k
  unsigned int cla, tag;
643
644
47.4k
  if (card == NULL || in_path == NULL) {
645
0
    return SC_ERROR_INVALID_ARGUMENTS;
646
0
  }
647
47.4k
  ctx = card->ctx;
648
47.4k
  memcpy(path, in_path->value, in_path->len);
649
47.4k
  pathlen = in_path->len;
650
47.4k
  pathtype = in_path->type;
651
652
47.4k
  if (in_path->aid.len) {
653
1.70k
    if (!pathlen) {
654
1.22k
      memcpy(path, in_path->aid.value, in_path->aid.len);
655
1.22k
      pathlen = in_path->aid.len;
656
1.22k
      pathtype = SC_PATH_TYPE_DF_NAME;
657
1.22k
    } else {
658
      /* First, select the application */
659
477
      sc_format_apdu(card, &apdu, SC_APDU_CASE_3_SHORT, 0xA4, 4, 0);
660
477
      apdu.data = in_path->aid.value;
661
477
      apdu.datalen = in_path->aid.len;
662
477
      apdu.lc = in_path->aid.len;
663
664
477
      r = sc_transmit_apdu(card, &apdu);
665
477
      LOG_TEST_RET(ctx, r, "APDU transmit failed");
666
474
      r = sc_check_sw(card, apdu.sw1, apdu.sw2);
667
474
      if (r)
668
474
        LOG_FUNC_RETURN(ctx, r);
669
670
133
      if (pathtype == SC_PATH_TYPE_PATH
671
0
          || pathtype == SC_PATH_TYPE_DF_NAME)
672
133
        pathtype = SC_PATH_TYPE_FROM_CURRENT;
673
133
    }
674
1.70k
  }
675
676
47.1k
  sc_format_apdu(card, &apdu, SC_APDU_CASE_4_SHORT, 0xA4, 0, 0);
677
678
47.1k
  switch (pathtype) {
679
10.0k
  case SC_PATH_TYPE_FILE_ID:
680
10.0k
    apdu.p1 = 0;
681
10.0k
    if (pathlen != 2)
682
0
      return SC_ERROR_INVALID_ARGUMENTS;
683
10.0k
    break;
684
19.7k
  case SC_PATH_TYPE_DF_NAME:
685
19.7k
    apdu.p1 = 4;
686
19.7k
    break;
687
17.0k
  case SC_PATH_TYPE_PATH:
688
17.0k
    apdu.p1 = 8;
689
17.0k
    if (pathlen >= 2 && memcmp(path, "\x3F\x00", 2) == 0) {
690
11.8k
      if (pathlen == 2) { /* only 3F00 supplied */
691
3.32k
        select_mf = 1;
692
3.32k
        apdu.p1 = 0;
693
3.32k
        break;
694
3.32k
      }
695
8.55k
      path += 2;
696
8.55k
      pathlen -= 2;
697
8.55k
    }
698
13.7k
    break;
699
13.7k
  case SC_PATH_TYPE_FROM_CURRENT:
700
133
    apdu.p1 = 9;
701
133
    break;
702
117
  case SC_PATH_TYPE_PARENT:
703
117
    apdu.p1 = 3;
704
117
    pathlen = 0;
705
117
    apdu.cse = SC_APDU_CASE_2_SHORT;
706
117
    break;
707
0
  default:
708
0
    LOG_FUNC_RETURN(ctx, SC_ERROR_INVALID_ARGUMENTS);
709
47.1k
  }
710
47.1k
  apdu.lc = pathlen;
711
47.1k
  apdu.data = path;
712
47.1k
  apdu.datalen = pathlen;
713
714
47.1k
  if (file_out != NULL) {
715
30.9k
    apdu.p2 = 0;    /* first record, return FCI */
716
30.9k
    apdu.resp = buf;
717
30.9k
    apdu.resplen = sizeof(buf);
718
30.9k
    apdu.le = sc_get_max_recv_size(card) < 256 ? sc_get_max_recv_size(card) : 256;
719
30.9k
  }
720
16.1k
  else {
721
16.1k
    apdu.p2 = 0x0C;   /* first record, return nothing */
722
16.1k
    apdu.cse = (apdu.lc == 0) ? SC_APDU_CASE_1 : SC_APDU_CASE_3_SHORT;
723
16.1k
  }
724
725
47.1k
  r = sc_transmit_apdu(card, &apdu);
726
47.1k
  LOG_TEST_RET(ctx, r, "APDU transmit failed");
727
46.7k
  if (file_out == NULL) {
728
    /* For some cards 'SELECT' can be only with request to return FCI/FCP. */
729
16.1k
    r = sc_check_sw(card, apdu.sw1, apdu.sw2);
730
16.1k
    if (apdu.sw1 == 0x6A && apdu.sw2 == 0x86)   {
731
22
      apdu.p2 = 0x00;
732
22
      if (sc_transmit_apdu(card, &apdu) == SC_SUCCESS)
733
12
        r = sc_check_sw(card, apdu.sw1, apdu.sw2);
734
22
    }
735
16.1k
    if (apdu.sw1 == 0x61)
736
16.1k
      LOG_FUNC_RETURN(ctx, SC_SUCCESS);
737
16.1k
    LOG_FUNC_RETURN(ctx, r);
738
16.1k
  }
739
740
30.6k
  r = sc_check_sw(card, apdu.sw1, apdu.sw2);
741
30.6k
  if (r)
742
30.6k
    LOG_FUNC_RETURN(ctx, r);
743
744
13.5k
  if (file_out && (apdu.resplen == 0))   {
745
    /* For some cards 'SELECT' MF or DF_NAME do not return FCI. */
746
2.48k
    if (select_mf || pathtype == SC_PATH_TYPE_DF_NAME)   {
747
1.57k
      file = sc_file_new();
748
1.57k
      if (file == NULL)
749
1.57k
        LOG_FUNC_RETURN(ctx, SC_ERROR_OUT_OF_MEMORY);
750
1.57k
      file->path = *in_path;
751
752
1.57k
      *file_out = file;
753
1.57k
      LOG_FUNC_RETURN(ctx, SC_SUCCESS);
754
1.57k
    }
755
2.48k
  }
756
757
11.9k
  if (apdu.resplen < 2)
758
11.9k
    LOG_FUNC_RETURN(ctx, SC_ERROR_UNKNOWN_DATA_RECEIVED);
759
11.0k
  switch (apdu.resp[0]) {
760
9.99k
  case ISO7816_TAG_FCI:
761
10.7k
  case ISO7816_TAG_FCP:
762
10.7k
    file = sc_file_new();
763
10.7k
    if (file == NULL)
764
10.7k
      LOG_FUNC_RETURN(ctx, SC_ERROR_OUT_OF_MEMORY);
765
10.7k
    file->path = *in_path;
766
10.7k
    if (card->ops->process_fci == NULL) {
767
0
      sc_file_free(file);
768
0
      LOG_FUNC_RETURN(ctx, SC_ERROR_NOT_SUPPORTED);
769
0
    }
770
10.7k
    buffer = apdu.resp;
771
10.7k
    r = sc_asn1_read_tag(&buffer, apdu.resplen, &cla, &tag, &buffer_len);
772
10.7k
    if (r == SC_SUCCESS)
773
9.94k
      card->ops->process_fci(card, file, buffer, buffer_len);
774
10.7k
    *file_out = file;
775
10.7k
    break;
776
98
  case 0x00: /* proprietary coding */
777
98
    LOG_FUNC_RETURN(ctx, SC_ERROR_UNKNOWN_DATA_RECEIVED);
778
202
  default:
779
202
    LOG_FUNC_RETURN(ctx, SC_ERROR_UNKNOWN_DATA_RECEIVED);
780
11.0k
  }
781
782
10.7k
  return SC_SUCCESS;
783
11.0k
}
784
785
786
static int
787
iso7816_get_challenge(struct sc_card *card, u8 *rnd, size_t len)
788
0
{
789
0
  int r;
790
0
  struct sc_apdu apdu;
791
792
0
  sc_format_apdu(card, &apdu, SC_APDU_CASE_2, 0x84, 0x00, 0x00);
793
0
  apdu.le = len;
794
0
  apdu.resp = rnd;
795
0
  apdu.resplen = len;
796
797
0
  r = sc_transmit_apdu(card, &apdu);
798
0
  LOG_TEST_RET(card->ctx, r, "APDU transmit failed");
799
800
0
  r = sc_check_sw(card, apdu.sw1, apdu.sw2);
801
0
  LOG_TEST_RET(card->ctx, r, "GET CHALLENGE failed");
802
803
0
  if (len < apdu.resplen) {
804
0
    return (int) len;
805
0
  }
806
807
0
  return (int) apdu.resplen;
808
0
}
809
810
811
static int
812
iso7816_construct_fci(struct sc_card *card, const sc_file_t *file,
813
    u8 *out, size_t *outlen)
814
0
{
815
0
  u8 *p = out;
816
0
  u8 buf[64];
817
818
0
  if (*outlen < 2)
819
0
    return SC_ERROR_BUFFER_TOO_SMALL;
820
0
  *p++ = 0x6F;
821
0
  p++;
822
823
0
  buf[0] = (file->size >> 8) & 0xFF;
824
0
  buf[1] = file->size & 0xFF;
825
0
  sc_asn1_put_tag(0x81, buf, 2, p, *outlen - (p - out), &p);
826
827
0
  if (file->type_attr_len) {
828
0
    assert(sizeof(buf) >= file->type_attr_len);
829
0
    memcpy(buf, file->type_attr, file->type_attr_len);
830
0
    sc_asn1_put_tag(0x82, buf, file->type_attr_len,
831
0
        p, *outlen - (p - out), &p);
832
0
  } else {
833
0
    buf[0] = file->shareable ? 0x40 : 0;
834
0
    switch (file->type) {
835
0
    case SC_FILE_TYPE_INTERNAL_EF:
836
0
      buf[0] |= 0x08;
837
      /* fall through */
838
0
    case SC_FILE_TYPE_WORKING_EF:
839
0
      buf[0] |= file->ef_structure & 7;
840
0
      break;
841
0
    case SC_FILE_TYPE_DF:
842
0
      buf[0] |= 0x38;
843
0
      break;
844
0
    default:
845
0
      return SC_ERROR_NOT_SUPPORTED;
846
0
    }
847
0
    sc_asn1_put_tag(0x82, buf, 1, p, *outlen - (p - out), &p);
848
0
  }
849
0
  buf[0] = (file->id >> 8) & 0xFF;
850
0
  buf[1] = file->id & 0xFF;
851
0
  sc_asn1_put_tag(0x83, buf, 2, p, *outlen - (p - out), &p);
852
  /* 0x84 = DF name */
853
0
  if (file->prop_attr_len) {
854
0
    assert(sizeof(buf) >= file->prop_attr_len);
855
0
    memcpy(buf, file->prop_attr, file->prop_attr_len);
856
0
    sc_asn1_put_tag(0x85, buf, file->prop_attr_len,
857
0
        p, *outlen - (p - out), &p);
858
0
  }
859
0
  if (file->sec_attr_len) {
860
0
    assert(sizeof(buf) >= file->sec_attr_len);
861
0
    memcpy(buf, file->sec_attr, file->sec_attr_len);
862
0
    sc_asn1_put_tag(0x86, buf, file->sec_attr_len,
863
0
        p, *outlen - (p - out), &p);
864
0
  }
865
0
  out[1] = p - out - 2;
866
867
0
  *outlen = p - out;
868
0
  return 0;
869
0
}
870
871
872
static int
873
iso7816_create_file(struct sc_card *card, sc_file_t *file)
874
0
{
875
0
  int r;
876
0
  size_t len;
877
0
  u8 sbuf[SC_MAX_APDU_BUFFER_SIZE];
878
0
  struct sc_apdu apdu;
879
880
0
  len = SC_MAX_APDU_BUFFER_SIZE;
881
882
0
  if (card->ops->construct_fci == NULL)
883
0
    LOG_FUNC_RETURN(card->ctx, SC_ERROR_NOT_SUPPORTED);
884
0
  r = card->ops->construct_fci(card, file, sbuf, &len);
885
0
  LOG_TEST_RET(card->ctx, r, "construct_fci() failed");
886
887
0
  sc_format_apdu(card, &apdu, SC_APDU_CASE_3_SHORT, 0xE0, 0x00, 0x00);
888
0
  apdu.lc = len;
889
0
  apdu.datalen = len;
890
0
  apdu.data = sbuf;
891
892
0
  r = sc_transmit_apdu(card, &apdu);
893
0
  LOG_TEST_RET(card->ctx, r, "APDU transmit failed");
894
0
  r = sc_check_sw(card, apdu.sw1, apdu.sw2);
895
0
  LOG_TEST_RET(card->ctx, r, "Card returned error");
896
897
0
  return r;
898
0
}
899
900
901
static int
902
iso7816_get_response(struct sc_card *card, size_t *count, u8 *buf)
903
56.8k
{
904
56.8k
  struct sc_apdu apdu = {0};
905
56.8k
  int r;
906
56.8k
  size_t rlen;
907
908
  /* request at most max_recv_size bytes */
909
56.8k
  if (*count > sc_get_max_recv_size(card))
910
8.64k
    rlen = sc_get_max_recv_size(card);
911
48.2k
  else
912
48.2k
    rlen = *count;
913
914
56.8k
  sc_format_apdu(card, &apdu, SC_APDU_CASE_2, 0xC0, 0x00, 0x00);
915
56.8k
  apdu.le      = rlen;
916
56.8k
  apdu.resplen = rlen;
917
56.8k
  apdu.resp    = buf;
918
  /* don't call GET RESPONSE recursively */
919
56.8k
  apdu.flags  |= SC_APDU_FLAGS_NO_GET_RESP;
920
921
56.8k
  r = sc_transmit_apdu(card, &apdu);
922
56.8k
  LOG_TEST_RET(card->ctx, r, "APDU transmit failed");
923
924
56.4k
  *count = apdu.resplen;
925
926
56.4k
  if (apdu.resplen == 0) {
927
7.88k
    LOG_FUNC_RETURN(card->ctx, sc_check_sw(card, apdu.sw1, apdu.sw2));
928
7.88k
  }
929
48.5k
  if (apdu.sw1 == 0x90 && apdu.sw2 == 0x00)
930
15.8k
    r = 0;          /* no more data to read */
931
32.7k
  else if (apdu.sw1 == 0x61)
932
29.2k
    r = apdu.sw2 == 0 ? 256 : apdu.sw2;  /* more data to read    */
933
3.47k
  else if (apdu.sw1 == 0x62 && apdu.sw2 == 0x82)
934
196
    r = 0; /* Le not reached but file/record ended */
935
3.27k
  else
936
3.27k
    r = sc_check_sw(card, apdu.sw1, apdu.sw2);
937
938
48.5k
  return r;
939
56.4k
}
940
941
942
static int
943
iso7816_delete_file(struct sc_card *card, const sc_path_t *path)
944
0
{
945
0
  int r;
946
0
  u8 sbuf[2];
947
0
  struct sc_apdu apdu;
948
949
0
  SC_FUNC_CALLED(card->ctx, SC_LOG_DEBUG_VERBOSE);
950
0
  if (path->type != SC_PATH_TYPE_FILE_ID || (path->len != 0 && path->len != 2)) {
951
0
    sc_log(card->ctx, "File type has to be SC_PATH_TYPE_FILE_ID");
952
0
    LOG_FUNC_RETURN(card->ctx, SC_ERROR_INVALID_ARGUMENTS);
953
0
  }
954
955
0
  if (path->len == 2) {
956
0
    sbuf[0] = path->value[0];
957
0
    sbuf[1] = path->value[1];
958
0
    sc_format_apdu(card, &apdu, SC_APDU_CASE_3_SHORT, 0xE4, 0x00, 0x00);
959
0
    apdu.lc = 2;
960
0
    apdu.datalen = 2;
961
0
    apdu.data = sbuf;
962
0
  }
963
0
  else   {
964
    /* No file ID given: means currently selected file */
965
0
    sc_format_apdu(card, &apdu, SC_APDU_CASE_1, 0xE4, 0x00, 0x00);
966
0
  }
967
968
0
  r = sc_transmit_apdu(card, &apdu);
969
0
  LOG_TEST_RET(card->ctx, r, "APDU transmit failed");
970
0
  r = sc_check_sw(card, apdu.sw1, apdu.sw2);
971
0
  LOG_TEST_RET(card->ctx, r, "Card returned error");
972
973
0
  return r;
974
0
}
975
976
977
static int
978
iso7816_set_security_env(struct sc_card *card,
979
    const struct sc_security_env *env, int se_num)
980
1.46k
{
981
1.46k
  struct sc_apdu apdu;
982
1.46k
  u8 sbuf[SC_MAX_APDU_BUFFER_SIZE];
983
1.46k
  u8 *p;
984
1.46k
  int r, locked = 0;
985
986
1.46k
  if (card == NULL || env == NULL) {
987
0
    return SC_ERROR_INVALID_ARGUMENTS;
988
0
  }
989
1.46k
  sc_format_apdu(card, &apdu, SC_APDU_CASE_3_SHORT, 0x22, 0x41, 0);
990
1.46k
  switch (env->operation) {
991
0
  case SC_SEC_OPERATION_AUTHENTICATE:
992
0
    apdu.p2 = 0xA4;
993
0
    break;
994
367
  case SC_SEC_OPERATION_DECIPHER:
995
367
  case SC_SEC_OPERATION_DERIVE:
996
367
    apdu.p2 = 0xB8;
997
367
    break;
998
1.09k
  case SC_SEC_OPERATION_SIGN:
999
1.09k
    apdu.p2 = 0xB6;
1000
1.09k
    break;
1001
0
  default:
1002
0
    return SC_ERROR_INVALID_ARGUMENTS;
1003
1.46k
  }
1004
1.46k
  p = sbuf;
1005
1.46k
  if (env->flags & SC_SEC_ENV_ALG_REF_PRESENT) {
1006
1.00k
    *p++ = 0x80;  /* algorithm reference */
1007
1.00k
    *p++ = 0x01;
1008
1.00k
    *p++ = env->algorithm_ref & 0xFF;
1009
1.00k
  }
1010
1.46k
  if (env->flags & SC_SEC_ENV_FILE_REF_PRESENT) {
1011
0
    if (env->file_ref.len > SC_MAX_PATH_SIZE)
1012
0
      return SC_ERROR_INVALID_ARGUMENTS;
1013
0
    if (sizeof(sbuf) - (p - sbuf) < env->file_ref.len + 2)
1014
0
      return SC_ERROR_OFFSET_TOO_LARGE;
1015
1016
0
    *p++ = 0x81;
1017
0
    *p++ = (u8) env->file_ref.len;
1018
0
    memcpy(p, env->file_ref.value, env->file_ref.len);
1019
0
    p += env->file_ref.len;
1020
0
  }
1021
1.46k
  if (env->flags & SC_SEC_ENV_KEY_REF_PRESENT) {
1022
1.46k
    if (sizeof(sbuf) - (p - sbuf) < env->key_ref_len + 2)
1023
0
      return SC_ERROR_OFFSET_TOO_LARGE;
1024
1025
1.46k
    if (env->flags & SC_SEC_ENV_KEY_REF_SYMMETRIC)
1026
0
      *p++ = 0x83;
1027
1.46k
    else
1028
1.46k
      *p++ = 0x84;
1029
1.46k
    if (env->key_ref_len > SC_MAX_KEYREF_SIZE)
1030
0
      return SC_ERROR_INVALID_ARGUMENTS;
1031
1.46k
    *p++ = env->key_ref_len & 0xFF;
1032
1.46k
    memcpy(p, env->key_ref, env->key_ref_len);
1033
1.46k
    p += env->key_ref_len;
1034
1.46k
  }
1035
1.46k
  r = (int)(p - sbuf);
1036
1.46k
  apdu.lc = r;
1037
1.46k
  apdu.datalen = r;
1038
1.46k
  apdu.data = sbuf;
1039
1.46k
  if (se_num > 0) {
1040
0
    r = sc_lock(card);
1041
0
    LOG_TEST_RET(card->ctx, r, "sc_lock() failed");
1042
0
    locked = 1;
1043
0
  }
1044
1.46k
  if (apdu.datalen != 0) {
1045
1.46k
    r = sc_transmit_apdu(card, &apdu);
1046
1.46k
    if (r) {
1047
18
      sc_log(card->ctx, "%s: APDU transmit failed", sc_strerror(r));
1048
18
      goto err;
1049
18
    }
1050
1.44k
    r = sc_check_sw(card, apdu.sw1, apdu.sw2);
1051
1.44k
    if (r) {
1052
1.16k
      sc_log(card->ctx, "%s: Card returned error", sc_strerror(r));
1053
1.16k
      goto err;
1054
1.16k
    }
1055
1.44k
  }
1056
280
  if (se_num <= 0) {
1057
280
    r = SC_SUCCESS;
1058
280
    goto err;
1059
280
  }
1060
0
  sc_format_apdu(card, &apdu, SC_APDU_CASE_3_SHORT, 0x22, 0xF2, se_num);
1061
0
  r = sc_transmit_apdu(card, &apdu);
1062
0
  sc_unlock(card);
1063
0
  LOG_TEST_RET(card->ctx, r, "APDU transmit failed");
1064
1065
0
  return sc_check_sw(card, apdu.sw1, apdu.sw2);
1066
1.46k
err:
1067
1.46k
  if (locked)
1068
0
    sc_unlock(card);
1069
1.46k
  return r;
1070
0
}
1071
1072
1073
static int
1074
iso7816_restore_security_env(struct sc_card *card, int se_num)
1075
49
{
1076
49
  struct sc_apdu apdu;
1077
49
  int r;
1078
1079
49
  if (card == NULL) {
1080
0
    return SC_ERROR_INVALID_ARGUMENTS;
1081
0
  }
1082
1083
49
  sc_format_apdu(card, &apdu, SC_APDU_CASE_1, 0x22, 0xF3, se_num);
1084
1085
49
  r = sc_transmit_apdu(card, &apdu);
1086
49
  LOG_TEST_RET(card->ctx, r, "APDU transmit failed");
1087
46
  r = sc_check_sw(card, apdu.sw1, apdu.sw2);
1088
46
  LOG_TEST_RET(card->ctx, r, "Card returned error");
1089
1090
32
  return r;
1091
46
}
1092
1093
1094
static int
1095
iso7816_compute_signature(struct sc_card *card,
1096
    const u8 * data, size_t datalen,
1097
    u8 * out, size_t outlen)
1098
164
{
1099
164
  int r;
1100
164
  struct sc_apdu apdu;
1101
1102
164
  if (card == NULL || data == NULL || out == NULL) {
1103
0
    return SC_ERROR_INVALID_ARGUMENTS;
1104
0
  }
1105
164
  LOG_FUNC_CALLED(card->ctx);
1106
164
  sc_log(card->ctx,
1107
164
         "ISO7816 compute signature: in-len %"SC_FORMAT_LEN_SIZE_T"u, out-len %"SC_FORMAT_LEN_SIZE_T"u",
1108
164
         datalen, outlen);
1109
1110
  /* INS: 0x2A  PERFORM SECURITY OPERATION
1111
   * P1:  0x9E  Resp: Digital Signature
1112
   * P2:  0x9A  Cmd: Input for Digital Signature */
1113
164
  sc_format_apdu(card, &apdu, SC_APDU_CASE_4, 0x2A, 0x9E, 0x9A);
1114
164
  apdu.resp = out;
1115
164
  apdu.resplen = outlen;
1116
164
  apdu.le = outlen;
1117
1118
164
  apdu.data = data;
1119
164
  apdu.lc = datalen;
1120
164
  apdu.datalen = datalen;
1121
1122
164
  iso7816_fixup_transceive_length(card, &apdu);
1123
164
  r = sc_transmit_apdu(card, &apdu);
1124
164
  LOG_TEST_RET(card->ctx, r, "APDU transmit failed");
1125
128
  if (apdu.sw1 == 0x90 && apdu.sw2 == 0x00)
1126
128
    LOG_FUNC_RETURN(card->ctx, (int)apdu.resplen);
1127
1128
64
  r = sc_check_sw(card, apdu.sw1, apdu.sw2);
1129
64
  LOG_TEST_RET(card->ctx, r, "Card returned error");
1130
1131
0
  LOG_FUNC_RETURN(card->ctx, r);
1132
0
}
1133
1134
1135
static int
1136
iso7816_decipher(struct sc_card *card,
1137
    const u8 * crgram, size_t crgram_len,
1138
    u8 * out, size_t outlen)
1139
34
{
1140
34
  int r;
1141
34
  struct sc_apdu apdu;
1142
34
  u8 *sbuf = NULL;
1143
1144
34
  if (card == NULL || crgram == NULL || out == NULL) {
1145
0
    return SC_ERROR_INVALID_ARGUMENTS;
1146
0
  }
1147
34
  LOG_FUNC_CALLED(card->ctx);
1148
34
  sc_log(card->ctx,
1149
34
         "ISO7816 decipher: in-len %"SC_FORMAT_LEN_SIZE_T"u, out-len %"SC_FORMAT_LEN_SIZE_T"u",
1150
34
         crgram_len, outlen);
1151
1152
34
  sbuf = malloc(crgram_len + 1);
1153
34
  if (sbuf == NULL)
1154
0
    return SC_ERROR_OUT_OF_MEMORY;
1155
1156
  /* INS: 0x2A  PERFORM SECURITY OPERATION
1157
   * P1:  0x80  Resp: Plain value
1158
   * P2:  0x86  Cmd: Padding indicator byte followed by cryptogram */
1159
34
  sc_format_apdu(card, &apdu, SC_APDU_CASE_4, 0x2A, 0x80, 0x86);
1160
34
  apdu.resp    = out;
1161
34
  apdu.resplen = outlen;
1162
34
  apdu.le      = outlen;
1163
1164
34
  sbuf[0] = 0; /* padding indicator byte, 0x00 = No further indication */
1165
34
  memcpy(sbuf + 1, crgram, crgram_len);
1166
34
  apdu.data = sbuf;
1167
34
  apdu.lc = crgram_len + 1;
1168
34
  apdu.datalen = crgram_len + 1;
1169
1170
34
  iso7816_fixup_transceive_length(card, &apdu);
1171
34
  r = sc_transmit_apdu(card, &apdu);
1172
34
  sc_mem_clear(sbuf, crgram_len + 1);
1173
34
  free(sbuf);
1174
34
  LOG_TEST_RET(card->ctx, r, "APDU transmit failed");
1175
1176
29
  if (apdu.sw1 == 0x90 && apdu.sw2 == 0x00)
1177
29
    LOG_FUNC_RETURN(card->ctx, (int)apdu.resplen);
1178
8
  else
1179
29
    LOG_FUNC_RETURN(card->ctx, sc_check_sw(card, apdu.sw1, apdu.sw2));
1180
29
}
1181
1182
1183
int
1184
iso7816_build_pin_apdu(struct sc_card *card, struct sc_apdu *apdu,
1185
    struct sc_pin_cmd_data *data, u8 *buf, size_t buf_len)
1186
6.58k
{
1187
6.58k
  int r, len = 0, pad = 0, use_pin_pad = 0, ins, p1 = 0;
1188
6.58k
  int cse = SC_APDU_CASE_3_SHORT;
1189
1190
6.58k
  switch (data->pin_type) {
1191
6.58k
  case SC_AC_CHV:
1192
    /* fall through */
1193
6.58k
  case SC_AC_SESSION:
1194
6.58k
  case SC_AC_CONTEXT_SPECIFIC:
1195
6.58k
    break;
1196
0
  default:
1197
0
    return SC_ERROR_INVALID_ARGUMENTS;
1198
6.58k
  }
1199
1200
6.58k
  if (data->flags & SC_PIN_CMD_NEED_PADDING)
1201
1.32k
    pad = 1;
1202
6.58k
  if (data->flags & SC_PIN_CMD_USE_PINPAD)
1203
0
    use_pin_pad = 1;
1204
1205
6.58k
  data->pin1.offset = 5;
1206
1207
6.58k
  switch (data->cmd) {
1208
680
  case SC_PIN_CMD_VERIFY:
1209
680
    ins = 0x20;
1210
    /* detect overloaded APDU with SC_PIN_CMD_GET_INFO */
1211
680
    if (data->pin1.len == 0 && !use_pin_pad)
1212
0
      return SC_ERROR_INVALID_PIN_LENGTH;
1213
680
    if ((r = sc_build_pin(buf, buf_len, &data->pin1, pad)) < 0)
1214
28
      return r;
1215
652
    len = r;
1216
652
    break;
1217
151
  case SC_PIN_CMD_CHANGE:
1218
151
    ins = 0x24;
1219
151
    if (data->pin1.len != 0 || (use_pin_pad && !( data->flags & SC_PIN_CMD_IMPLICIT_CHANGE))) {
1220
149
      if ((r = sc_build_pin(buf, buf_len, &data->pin1, pad)) < 0)
1221
10
        return r;
1222
139
      len += r;
1223
139
    }
1224
2
    else {
1225
      /* implicit test */
1226
2
      p1 = 1;
1227
2
    }
1228
1229
141
    data->pin2.offset = data->pin1.offset + len;
1230
141
    if ((r = sc_build_pin(buf+len, buf_len-len, &data->pin2, pad)) < 0)
1231
2
      return r;
1232
    /* Special case - where provided the old PIN on the command line
1233
     * but expect the new one to be entered on the keypad.
1234
     */
1235
139
    if (data->pin1.len && data->pin2.len == 0) {
1236
0
      sc_log(card->ctx, "Special case - initial pin provided - but new pin asked on keypad");
1237
0
      data->flags |= SC_PIN_CMD_IMPLICIT_CHANGE;
1238
0
    };
1239
139
    len += r;
1240
139
    break;
1241
220
  case SC_PIN_CMD_UNBLOCK:
1242
220
    ins = 0x2C;
1243
220
    if (data->pin1.len != 0 || (use_pin_pad && !( data->flags & SC_PIN_CMD_IMPLICIT_CHANGE))) {
1244
220
      if ((r = sc_build_pin(buf, buf_len, &data->pin1, pad)) < 0)
1245
5
        return r;
1246
215
      len += r;
1247
215
    } else {
1248
0
      p1 |= 0x02;
1249
0
    }
1250
1251
215
    if (data->pin2.len != 0 || use_pin_pad) {
1252
215
      data->pin2.offset = data->pin1.offset + len;
1253
215
      if ((r = sc_build_pin(buf+len, buf_len-len, &data->pin2, pad)) < 0)
1254
2
        return r;
1255
213
      len += r;
1256
213
    } else {
1257
0
      p1 |= 0x01;
1258
0
    }
1259
213
    if (p1 == 0x03) {
1260
      /* No data to send or to receive */
1261
0
      cse = SC_APDU_CASE_1;
1262
0
    }
1263
213
    break;
1264
5.53k
  case SC_PIN_CMD_GET_INFO:
1265
5.53k
    ins = 0x20;
1266
    /* No data to send or to receive */
1267
5.53k
    cse = SC_APDU_CASE_1;
1268
5.53k
    break;
1269
0
  default:
1270
0
    return SC_ERROR_NOT_SUPPORTED;
1271
6.58k
  }
1272
1273
6.53k
  sc_format_apdu(card, apdu, cse, ins, p1, data->pin_reference);
1274
6.53k
  apdu->lc = len;
1275
6.53k
  apdu->datalen = len;
1276
6.53k
  apdu->data = buf;
1277
6.53k
  apdu->resplen = 0;
1278
1279
6.53k
  return 0;
1280
6.58k
}
1281
1282
1283
static int
1284
iso7816_pin_cmd(struct sc_card *card, struct sc_pin_cmd_data *data, int *tries_left)
1285
6.73k
{
1286
6.73k
  struct sc_apdu local_apdu, *apdu;
1287
6.73k
  int r;
1288
6.73k
  u8  sbuf[SC_MAX_APDU_BUFFER_SIZE];
1289
1290
6.73k
  data->pin1.tries_left = -1;
1291
6.73k
  if (tries_left != NULL) {
1292
1.05k
    *tries_left = data->pin1.tries_left;
1293
1.05k
  }
1294
1295
  /* Many cards do support PIN status queries, but some cards don't and
1296
   * mistakenly count the command as a failed PIN attempt, so for now we
1297
   * allow cards with this flag.  In future this may be reduced to a
1298
   * blocklist, subject to testing more cards. */
1299
6.73k
  if (data->cmd == SC_PIN_CMD_GET_INFO &&
1300
5.68k
      !(card->caps & SC_CARD_CAP_ISO7816_PIN_INFO)) {
1301
149
    sc_log(card->ctx, "Card does not support PIN status queries");
1302
149
    return SC_ERROR_NOT_SUPPORTED;
1303
149
  }
1304
1305
  /* See if we've been called from another card driver, which is
1306
   * passing an APDU to us (this allows to write card drivers
1307
   * whose PIN functions behave "mostly like ISO" except in some
1308
   * special circumstances.
1309
   */
1310
6.58k
  if (data->apdu == NULL) {
1311
6.57k
    r = iso7816_build_pin_apdu(card, &local_apdu, data, sbuf, sizeof(sbuf));
1312
6.57k
    if (r < 0)
1313
47
      return r;
1314
6.53k
    data->apdu = &local_apdu;
1315
6.53k
  }
1316
6.53k
  apdu = data->apdu;
1317
1318
6.53k
  if (!(data->flags & SC_PIN_CMD_USE_PINPAD) || data->cmd == SC_PIN_CMD_GET_INFO) {
1319
    /* Transmit the APDU to the card */
1320
6.53k
    r = sc_transmit_apdu(card, apdu);
1321
1322
    /* Clear the buffer - it may contain pins */
1323
6.53k
    sc_mem_clear(sbuf, sizeof(sbuf));
1324
6.53k
  }
1325
0
  else {
1326
    /* Call the reader driver to collect
1327
     * the PIN and pass on the APDU to the card */
1328
0
    if (data->pin1.offset == 0) {
1329
0
      sc_log(card->ctx, "Card driver didn't set PIN offset");
1330
0
      return SC_ERROR_INVALID_ARGUMENTS;
1331
0
    }
1332
0
    if (card->reader && card->reader->ops && card->reader->ops->perform_verify) {
1333
0
      r = card->reader->ops->perform_verify(card->reader, data);
1334
      /* sw1/sw2 filled in by reader driver */
1335
0
    }
1336
0
    else {
1337
0
      sc_log(card->ctx, "Card reader driver does not support "
1338
0
          "PIN entry through reader key pad");
1339
0
      r = SC_ERROR_NOT_SUPPORTED;
1340
0
    }
1341
0
  }
1342
1343
  /* Don't pass references to local variables up to the caller. */
1344
6.53k
  if (data->apdu == &local_apdu)
1345
6.53k
    data->apdu = NULL;
1346
1347
6.53k
  LOG_TEST_RET(card->ctx, r, "APDU transmit failed");
1348
6.51k
  r = sc_check_sw(card, apdu->sw1, apdu->sw2);
1349
1350
6.51k
  if (r == SC_SUCCESS) {
1351
1.66k
    data->pin1.logged_in = SC_PIN_STATE_LOGGED_IN;
1352
4.84k
  } else if (r == SC_ERROR_PIN_CODE_INCORRECT) {
1353
32
    data->pin1.tries_left = apdu->sw2 & 0xF;
1354
32
    data->pin1.logged_in = SC_PIN_STATE_LOGGED_OUT;
1355
32
    if (data->cmd == SC_PIN_CMD_GET_INFO)
1356
16
      r = SC_SUCCESS;
1357
4.81k
  } else if (r == SC_ERROR_AUTH_METHOD_BLOCKED) {
1358
6
    data->pin1.tries_left = 0;
1359
6
    data->pin1.logged_in = SC_PIN_STATE_LOGGED_OUT;
1360
6
    if (data->cmd == SC_PIN_CMD_GET_INFO)
1361
3
      r = SC_SUCCESS;
1362
6
  }
1363
6.51k
  if (tries_left != NULL) {
1364
991
    *tries_left = data->pin1.tries_left;
1365
991
  }
1366
1367
6.51k
  return r;
1368
6.53k
}
1369
1370
1371
static int iso7816_get_data(struct sc_card *card, unsigned int tag,  u8 *buf, size_t len)
1372
182
{
1373
182
  int                             r, cse;
1374
182
  struct sc_apdu                  apdu;
1375
1376
182
  SC_FUNC_CALLED(card->ctx, SC_LOG_DEBUG_VERBOSE);
1377
1378
182
  if (buf && len)
1379
182
    cse = SC_APDU_CASE_2;
1380
0
  else
1381
0
    cse = SC_APDU_CASE_1;
1382
1383
182
  sc_format_apdu(card, &apdu, cse, 0xCA, (tag >> 8) & 0xff, tag & 0xff);
1384
182
  apdu.le = len;
1385
182
  apdu.resp = buf;
1386
182
  apdu.resplen = len;
1387
182
  r = sc_transmit_apdu(card, &apdu);
1388
182
  LOG_TEST_RET(card->ctx, r, "APDU transmit failed");
1389
1390
178
  r = sc_check_sw(card, apdu.sw1, apdu.sw2);
1391
178
  LOG_TEST_RET(card->ctx, r, "GET_DATA returned error");
1392
1393
139
  if (apdu.resplen > len)
1394
0
    r = SC_ERROR_WRONG_LENGTH;
1395
139
  else
1396
139
    r = (int)apdu.resplen;
1397
1398
139
  LOG_FUNC_RETURN(card->ctx, r);
1399
139
}
1400
1401
int
1402
iso7816_select_aid(struct sc_card *card, const u8 *req,
1403
    size_t reqlen, u8 *resp, size_t *resplen)
1404
17.9k
{
1405
17.9k
  struct sc_context *ctx = card->ctx;
1406
17.9k
  struct sc_apdu apdu;
1407
17.9k
  int rv;
1408
1409
17.9k
  SC_FUNC_CALLED(ctx, SC_LOG_DEBUG_VERBOSE);
1410
1411
17.9k
  sc_format_apdu(card, &apdu, resp == NULL ? SC_APDU_CASE_3_SHORT : SC_APDU_CASE_4_SHORT, 0xA4, 0x04, resp == NULL ? 0x0C : 0x00);
1412
17.9k
  apdu.lc = reqlen;
1413
17.9k
  apdu.data = req;
1414
17.9k
  apdu.datalen = reqlen;
1415
17.9k
  apdu.resp = resp;
1416
17.9k
  apdu.resplen = resp == NULL ? 0 : *resplen;
1417
17.9k
  apdu.le = resp == NULL ? 0 : 256;
1418
1419
17.9k
  rv = sc_transmit_apdu(card, &apdu);
1420
17.9k
  if (resplen)
1421
11.9k
    *resplen = apdu.resplen;
1422
17.9k
  LOG_TEST_RET(card->ctx, rv, "APDU transmit failed");
1423
1424
17.7k
  rv = sc_check_sw(card, apdu.sw1, apdu.sw2);
1425
17.7k
  LOG_FUNC_RETURN(ctx, rv);
1426
17.7k
}
1427
1428
static int
1429
iso7816_init(struct sc_card *card)
1430
0
{
1431
0
#if ENABLE_SM
1432
0
  memset(&card->sm_ctx, 0, sizeof card->sm_ctx);
1433
0
#endif
1434
0
  return SC_SUCCESS;
1435
0
}
1436
1437
1438
static int
1439
no_match(struct sc_card *card)
1440
0
{
1441
0
  return 0;
1442
0
}
1443
1444
static struct sc_card_operations iso_ops = {
1445
  no_match,
1446
  iso7816_init, /* init   */
1447
  NULL,     /* finish */
1448
  iso7816_read_binary,
1449
  iso7816_write_binary,
1450
  iso7816_update_binary,
1451
  NULL,     /* erase_binary */
1452
  iso7816_read_record,
1453
  iso7816_write_record,
1454
  iso7816_append_record,
1455
  iso7816_update_record,
1456
  iso7816_select_file,
1457
  iso7816_get_response,
1458
  iso7816_get_challenge,
1459
  NULL,     /* verify */
1460
  NULL,     /* logout */
1461
  iso7816_restore_security_env,
1462
  iso7816_set_security_env,
1463
  iso7816_decipher,
1464
  iso7816_compute_signature,
1465
  NULL,     /* change_reference_data */
1466
  NULL,     /* reset_retry_counter   */
1467
  iso7816_create_file,
1468
  iso7816_delete_file,
1469
  NULL,     /* list_files */
1470
  iso7816_check_sw,
1471
  NULL,     /* card_ctl */
1472
  iso7816_process_fci,
1473
  iso7816_construct_fci,
1474
  iso7816_pin_cmd,
1475
  iso7816_get_data,
1476
  NULL,     /* put_data */
1477
  NULL,     /* delete_record */
1478
  NULL,     /* read_public_key */
1479
  NULL,     /* card_reader_lock_obtained */
1480
  NULL,     /* wrap */
1481
  NULL,     /* unwrap */
1482
  NULL,     /* encrypt_sym */
1483
  NULL      /* decrypt_sym */
1484
};
1485
1486
static struct sc_card_driver iso_driver = {
1487
  "ISO 7816 reference driver",
1488
  "iso7816",
1489
  &iso_ops,
1490
  NULL, 0, NULL
1491
};
1492
1493
struct sc_card_driver * sc_get_iso7816_driver(void)
1494
485k
{
1495
485k
  return &iso_driver;
1496
485k
}
1497
1498
0
#define ISO_READ_BINARY  0xB0
1499
0
#define ISO_P1_FLAG_SFID 0x80
1500
int iso7816_read_binary_sfid(sc_card_t *card, unsigned char sfid,
1501
    u8 **ef, size_t *ef_len)
1502
0
{
1503
0
  int r;
1504
0
  size_t read;
1505
0
  sc_apdu_t apdu;
1506
0
  u8 *p;
1507
1508
0
  if (!card || !ef || !ef_len) {
1509
0
    r = SC_ERROR_INVALID_ARGUMENTS;
1510
0
    goto err;
1511
0
  }
1512
0
  *ef_len = 0;
1513
1514
0
  read = card->max_recv_size;
1515
0
  sc_format_apdu(card, &apdu, SC_APDU_CASE_2,
1516
0
      ISO_READ_BINARY, ISO_P1_FLAG_SFID|sfid, 0);
1517
0
  p = realloc(*ef, read);
1518
0
  if (!p) {
1519
0
    r = SC_ERROR_OUT_OF_MEMORY;
1520
0
    goto err;
1521
0
  }
1522
0
  *ef = p;
1523
0
  apdu.resp = *ef;
1524
0
  apdu.resplen = read;
1525
0
  apdu.le = read;
1526
1527
0
  r = sc_transmit_apdu(card, &apdu);
1528
0
  if (r < 0)
1529
0
    goto err;
1530
0
  r = sc_check_sw(card, apdu.sw1, apdu.sw2);
1531
0
  if (r < 0 && r != SC_ERROR_FILE_END_REACHED)
1532
0
    goto err;
1533
  /* emulate the behaviour of iso7816_read_binary */
1534
0
  r = (int)apdu.resplen;
1535
1536
0
  while(1) {
1537
0
    if (r >= 0 && ((size_t) r) != read) {
1538
0
      *ef_len += r;
1539
0
      break;
1540
0
    }
1541
0
    if (r <= 0) {
1542
0
      if (*ef_len > 0)
1543
0
        break;
1544
0
      else {
1545
0
        sc_debug(card->ctx, SC_LOG_DEBUG_VERBOSE, "Could not read EF.");
1546
0
        goto err;
1547
0
      }
1548
0
    }
1549
0
    *ef_len += r;
1550
1551
0
    p = realloc(*ef, *ef_len + read);
1552
0
    if (!p) {
1553
0
      r = SC_ERROR_OUT_OF_MEMORY;
1554
0
      goto err;
1555
0
    }
1556
0
    *ef = p;
1557
1558
0
    r = iso7816_read_binary(card, (unsigned)*ef_len, *ef + *ef_len, read, 0);
1559
0
  }
1560
1561
0
  r = (int)*ef_len;
1562
1563
0
err:
1564
0
  return r;
1565
0
}
1566
1567
0
#define ISO_WRITE_BINARY  0xD0
1568
int iso7816_write_binary_sfid(sc_card_t *card, unsigned char sfid,
1569
    u8 *ef, size_t ef_len)
1570
0
{
1571
0
  int r;
1572
0
  size_t write, wrote = 0;
1573
0
  sc_apdu_t apdu;
1574
1575
0
  if (!card) {
1576
0
    r = SC_ERROR_INVALID_ARGUMENTS;
1577
0
    goto err;
1578
0
  }
1579
1580
0
  write = card->max_send_size;
1581
1582
0
  sc_format_apdu(card, &apdu, SC_APDU_CASE_3,
1583
0
      ISO_WRITE_BINARY, ISO_P1_FLAG_SFID|sfid, 0);
1584
1585
0
  if (write > ef_len) {
1586
0
    apdu.datalen = ef_len;
1587
0
    apdu.lc = ef_len;
1588
0
  } else {
1589
0
    apdu.datalen = write;
1590
0
    apdu.lc = write;
1591
0
  }
1592
0
  apdu.data = ef;
1593
1594
1595
0
  r = sc_transmit_apdu(card, &apdu);
1596
  /* emulate the behaviour of sc_write_binary */
1597
0
  if (r >= 0)
1598
0
    r = (int)apdu.datalen;
1599
1600
0
  while (1) {
1601
0
    if (r < 0 || ((size_t) r) > ef_len) {
1602
0
      sc_debug(card->ctx, SC_LOG_DEBUG_VERBOSE, "Could not write EF.");
1603
0
      goto err;
1604
0
    }
1605
0
    if (r == 0 || r == SC_ERROR_FILE_END_REACHED)
1606
0
      break;
1607
0
    wrote += r;
1608
0
    apdu.data += r;
1609
0
    if (wrote >= ef_len)
1610
0
      break;
1611
1612
0
    r = sc_write_binary(card, (unsigned)wrote, ef, write, 0);
1613
0
  }
1614
1615
0
  r = (int)wrote;
1616
1617
0
err:
1618
0
  return r;
1619
0
}
1620
1621
0
#define ISO_UPDATE_BINARY  0xD6
1622
int iso7816_update_binary_sfid(sc_card_t *card, unsigned char sfid,
1623
    u8 *ef, size_t ef_len)
1624
0
{
1625
0
  int r;
1626
0
  size_t write = MAX_SM_APDU_DATA_SIZE, wrote = 0;
1627
0
  sc_apdu_t apdu;
1628
0
#ifdef ENABLE_SM
1629
0
  struct iso_sm_ctx *iso_sm_ctx;
1630
0
#endif
1631
1632
0
  if (!card) {
1633
0
    r = SC_ERROR_INVALID_ARGUMENTS;
1634
0
    goto err;
1635
0
  }
1636
1637
0
#ifdef ENABLE_SM
1638
0
  iso_sm_ctx = card->sm_ctx.info.cmd_data;
1639
0
  if (write > SC_MAX_APDU_BUFFER_SIZE-2
1640
0
      || (card->sm_ctx.sm_mode == SM_MODE_TRANSMIT
1641
0
        && write > (((SC_MAX_APDU_BUFFER_SIZE-2
1642
          /* for encrypted APDUs we usually get authenticated status
1643
           * bytes (4B), a MAC (11B) and a cryptogram with padding
1644
           * indicator (3B without data).  The cryptogram is always
1645
           * padded to the block size. */
1646
0
          -18) / iso_sm_ctx->block_length)
1647
0
          * iso_sm_ctx->block_length - 1)))
1648
0
    sc_format_apdu(card, &apdu, SC_APDU_CASE_3_EXT,
1649
0
        ISO_UPDATE_BINARY, ISO_P1_FLAG_SFID|sfid, 0);
1650
0
  else
1651
0
#endif
1652
0
    sc_format_apdu(card, &apdu, SC_APDU_CASE_3_SHORT,
1653
0
        ISO_UPDATE_BINARY, ISO_P1_FLAG_SFID|sfid, 0);
1654
1655
0
  if (write > ef_len) {
1656
0
    apdu.datalen = ef_len;
1657
0
    apdu.lc = ef_len;
1658
0
  } else {
1659
0
    apdu.datalen = write;
1660
0
    apdu.lc = write;
1661
0
  }
1662
0
  apdu.data = ef;
1663
1664
1665
0
  r = sc_transmit_apdu(card, &apdu);
1666
  /* emulate the behaviour of sc_write_binary */
1667
0
  if (r >= 0)
1668
0
    r = (int)apdu.datalen;
1669
1670
0
  while (1) {
1671
0
    if (r < 0 || ((size_t) r) > ef_len) {
1672
0
      sc_debug(card->ctx, SC_LOG_DEBUG_VERBOSE, "Could not update EF.");
1673
0
      goto err;
1674
0
    }
1675
0
    if (r == 0 || r == SC_ERROR_FILE_END_REACHED)
1676
0
      break;
1677
0
    wrote += r;
1678
0
    apdu.data += r;
1679
0
    if (wrote >= ef_len)
1680
0
      break;
1681
1682
0
    r = sc_update_binary(card, (unsigned)wrote, ef, write, 0);
1683
0
  }
1684
1685
0
  r = (int)wrote;
1686
1687
0
err:
1688
0
  return r;
1689
0
}
1690
1691
int iso7816_logout(sc_card_t *card, unsigned char pin_reference)
1692
0
{
1693
0
  int r;
1694
0
  sc_apdu_t apdu;
1695
1696
0
  sc_format_apdu(card, &apdu, SC_APDU_CASE_1, 0x20, 0xFF, pin_reference);
1697
1698
0
  r = sc_transmit_apdu(card, &apdu);
1699
0
  if (r < 0)
1700
0
    return r;
1701
1702
0
  r = sc_check_sw(card, apdu.sw1, apdu.sw2);
1703
1704
0
  return r;
1705
0
}