Coverage Report

Created: 2025-11-13 06:26

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.2k
{
37
49.2k
  if (card == NULL || apdu == NULL) {
38
0
    return;
39
0
  }
40
41
49.2k
  if (apdu->lc > sc_get_max_send_size(card)) {
42
    /* The lower layers will automatically do chaining */
43
747
    apdu->flags |= SC_APDU_FLAGS_CHAINING;
44
747
  }
45
46
49.2k
  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.35k
    apdu->le = sc_get_max_recv_size(card);
50
2.35k
  }
51
49.2k
}
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
490k
{
112
490k
  const int err_count = sizeof(iso7816_errors)/sizeof(iso7816_errors[0]);
113
490k
  int i;
114
115
  /* Handle special cases here */
116
490k
  if (sw1 == 0x6C) {
117
185
    sc_log(card->ctx, "Wrong length; correct length is %d", sw2);
118
185
    return SC_ERROR_WRONG_LENGTH;
119
185
  }
120
490k
  if (sw1 == 0x90 && sw2 == 0x00)
121
217k
    return SC_SUCCESS;
122
272k
  if (sw1 == 0x63U && (sw2 & ~0x0fU) == 0xc0U) {
123
165
    sc_log(card->ctx, "PIN not verified (remaining tries: %d)", (sw2 & 0x0f));
124
165
    return SC_ERROR_PIN_CODE_INCORRECT;
125
165
  }
126
11.1M
  for (i = 0; i < err_count; i++)   {
127
11.0M
    if (iso7816_errors[i].SWs == ((sw1 << 8) | sw2)) {
128
246k
      sc_log(card->ctx, "%s", iso7816_errors[i].errorstr);
129
246k
      return iso7816_errors[i].errorno;
130
246k
    }
131
11.0M
  }
132
133
26.5k
  sc_log(card->ctx, "Unknown SWs; SW1=%02X, SW2=%02X", sw1, sw2);
134
26.5k
  return SC_ERROR_CARD_CMD_FAILED;
135
272k
}
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
23.7k
{
141
23.7k
  struct sc_context *ctx = card->ctx;
142
23.7k
  struct sc_apdu apdu;
143
23.7k
  int r;
144
145
23.7k
  if (idx > 0x7FFF) {
146
8
    sc_log(ctx, "invalid EF offset: 0x%X > 0x7FFF", idx);
147
8
    return SC_ERROR_OFFSET_TOO_LARGE;
148
8
  }
149
150
23.7k
  sc_format_apdu(card, &apdu, SC_APDU_CASE_2, 0xB0, (idx >> 8) & 0x7F, idx & 0xFF);
151
23.7k
  apdu.le = count;
152
23.7k
  apdu.resplen = count;
153
23.7k
  apdu.resp = buf;
154
155
23.7k
  iso7816_fixup_transceive_length(card, &apdu);
156
23.7k
  r = sc_transmit_apdu(card, &apdu);
157
23.7k
  LOG_TEST_RET(ctx, r, "APDU transmit failed");
158
159
23.3k
  r = sc_check_sw(card, apdu.sw1, apdu.sw2);
160
23.3k
  if (r == SC_ERROR_FILE_END_REACHED)
161
23.3k
    LOG_FUNC_RETURN(ctx, (int)apdu.resplen);
162
21.9k
  LOG_TEST_RET(ctx, r, "Check SW error");
163
164
19.8k
  LOG_FUNC_RETURN(ctx, (int)apdu.resplen);
165
19.8k
}
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.1k
{
178
12.1k
  unsigned char offset_buffer[2];
179
12.1k
  size_t offset_buffer_len = sizeof offset_buffer;
180
12.1k
  struct sc_asn1_entry asn1_do_data[sizeof c_asn1_do_data / sizeof *c_asn1_do_data];
181
12.1k
  sc_copy_asn1_entry(c_asn1_do_data, asn1_do_data);
182
183
12.1k
  if (idx > 0xFFFF)
184
12.1k
    LOG_TEST_RET(ctx, SC_ERROR_INTERNAL, "Offset beyond 0xFFFF not supported");
185
12.1k
  offset_buffer[0] = (u8) (idx >> 8);
186
12.1k
  offset_buffer[1] = (u8) (idx & 0x00FF);
187
12.1k
  sc_format_asn1_entry(asn1_do_data + 0, offset_buffer, &offset_buffer_len, 1);
188
189
12.1k
  if (data && data_len) {
190
0
    sc_format_asn1_entry(asn1_do_data + 1, (void *) &data, &data_len, 1);
191
12.1k
  } else {
192
12.1k
    sc_format_asn1_entry(asn1_do_data + 1, NULL, NULL, 0);
193
12.1k
  }
194
195
12.1k
  LOG_TEST_RET(ctx,
196
12.1k
      sc_asn1_encode(ctx, asn1_do_data, out, outlen),
197
12.1k
      "sc_asn1_encode() failed");
198
199
12.1k
  return SC_SUCCESS;
200
12.1k
}
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.11k
      sc_asn1_decode(ctx, asn1_do_data, encoded_data, encoded_data_len, NULL, NULL),
214
8.11k
      "sc_asn1_decode() failed");
215
216
8.11k
  if (!(asn1_do_data[1].flags & SC_ASN1_PRESENT))
217
6.76k
    return SC_ERROR_INVALID_ASN1_OBJECT;
218
219
1.34k
  return SC_SUCCESS;
220
8.11k
}
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
25.3k
{
226
25.3k
  struct sc_apdu apdu;
227
25.3k
  int r;
228
  /* XXX maybe use some bigger buffer */
229
25.3k
  unsigned char resp[SC_MAX_APDU_RESP_SIZE];
230
25.3k
  unsigned char *encoded_data = NULL, *decoded_data = NULL;
231
25.3k
  size_t encoded_data_len = 0, decoded_data_len = 0;
232
233
25.3k
  if (rec_nr > 0xFF)
234
25.3k
    LOG_FUNC_RETURN(card->ctx, SC_ERROR_INVALID_ARGUMENTS);
235
236
25.3k
  if (idx == 0) {
237
13.1k
    sc_format_apdu(card, &apdu, SC_APDU_CASE_2, 0xB2, rec_nr, 0);
238
13.1k
    apdu.le = count;
239
13.1k
    apdu.resplen = count;
240
13.1k
    apdu.resp = buf;
241
13.1k
  } else {
242
12.1k
    r = encode_do_data(card->ctx, idx, NULL, 0, &encoded_data, &encoded_data_len);
243
12.1k
    LOG_TEST_GOTO_ERR(card->ctx, r, "Could not encode data objects");
244
245
12.1k
    sc_format_apdu(card, &apdu, SC_APDU_CASE_4, 0xB3, rec_nr, 0);
246
12.1k
    apdu.lc = encoded_data_len;
247
12.1k
    apdu.datalen = encoded_data_len;
248
12.1k
    apdu.data = encoded_data;
249
12.1k
    apdu.le = sizeof resp;
250
12.1k
    apdu.resplen = sizeof resp;
251
12.1k
    apdu.resp = resp;
252
12.1k
  }
253
25.3k
  apdu.p2 = (flags & SC_RECORD_EF_ID_MASK) << 3;
254
25.3k
  if (flags & SC_RECORD_BY_REC_NR)
255
25.3k
    apdu.p2 |= 0x04;
256
257
25.3k
  iso7816_fixup_transceive_length(card, &apdu);
258
25.3k
  r = sc_transmit_apdu(card, &apdu);
259
25.3k
  LOG_TEST_GOTO_ERR(card->ctx, r, "APDU transmit failed");
260
23.9k
  r = sc_check_sw(card, apdu.sw1, apdu.sw2);
261
23.9k
  LOG_TEST_GOTO_ERR(card->ctx, r, "Card returned error");
262
263
20.7k
  if (idx == 0) {
264
11.5k
    r = (int)apdu.resplen;
265
11.5k
  } 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.34k
    if (decoded_data_len <= count) {
270
1.23k
      count = decoded_data_len;
271
1.23k
    }
272
1.34k
    memcpy(buf, decoded_data, count);
273
1.34k
    r = (int)count;
274
1.34k
  }
275
276
25.3k
err:
277
25.3k
  free(encoded_data);
278
25.3k
  free(decoded_data);
279
25.3k
  LOG_FUNC_RETURN(card->ctx, r);
280
25.3k
}
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.75k
{
432
8.75k
  struct sc_context *ctx = card->ctx;
433
8.75k
  const unsigned char *p, *end;
434
8.75k
  unsigned int cla = 0, tag = 0;
435
8.75k
  size_t length;
436
437
8.75k
  file->status = SC_FILE_STATUS_UNKNOWN;
438
439
8.75k
  for (p = buf, length = buflen, end = buf + buflen;
440
24.9k
      p < end;
441
21.9k
      p += length, length = end - p) {
442
443
21.9k
    if (SC_SUCCESS != sc_asn1_read_tag(&p, length, &cla, &tag, &length)
444
18.0k
        || p == NULL) {
445
5.75k
      break;
446
5.75k
    }
447
16.1k
    switch (cla | tag) {
448
1.56k
      case 0x81:
449
1.56k
        if (file->size != 0) {
450
          /* don't overwrite existing file size excluding structural information */
451
77
          break;
452
77
        }
453
        /* fall through */
454
3.43k
      case 0x80:
455
        /* determine the file size */
456
3.43k
        file->size = 0;
457
3.43k
        if (p && length <= sizeof(size_t)) {
458
3.39k
          size_t size = 0, i;
459
11.4k
          for (i = 0; i < length; i++) {
460
8.03k
            size <<= 8;
461
8.03k
            size |= p[i];
462
8.03k
          }
463
3.39k
          if (size > MAX_FILE_SIZE) {
464
491
            file->size = MAX_FILE_SIZE;
465
491
            sc_log(ctx, "  file size truncated, encoded length: %"SC_FORMAT_LEN_SIZE_T"u", size);
466
2.90k
          } else {
467
2.90k
            file->size = size;
468
2.90k
          }
469
3.39k
        }
470
471
3.43k
        sc_log(ctx, "  bytes in file: %"SC_FORMAT_LEN_SIZE_T"u", file->size);
472
3.43k
        break;
473
474
1.85k
      case 0x82:
475
1.85k
        if (length > 0) {
476
1.60k
          unsigned char byte = p[0];
477
1.60k
          const char *type;
478
479
1.60k
          file->shareable = byte & 0x40 ? 1 : 0;
480
1.60k
          sc_log(ctx, "  shareable: %s", (byte & 0x40) ? "yes" : "no");
481
1.60k
          file->ef_structure = byte & 0x07;
482
1.60k
          switch ((byte >> 3) & 7) {
483
862
            case 0:
484
862
              type = "working EF";
485
862
              file->type = SC_FILE_TYPE_WORKING_EF;
486
862
              break;
487
268
            case 1:
488
268
              type = "internal EF";
489
268
              file->type = SC_FILE_TYPE_INTERNAL_EF;
490
268
              break;
491
220
            case 7:
492
220
              type = "DF";
493
220
              file->type = SC_FILE_TYPE_DF;
494
220
              break;
495
252
            default:
496
252
              file->type = SC_FILE_TYPE_UNKNOWN;
497
252
              type = "unknown";
498
252
              break;
499
1.60k
          }
500
1.60k
          sc_log(ctx, "  type: %s", type);
501
1.60k
          sc_log(ctx, "  EF structure: %d", byte & 0x07);
502
1.60k
          sc_log(ctx, "  tag 0x82: 0x%02x", byte);
503
504
          /* if possible, get additional information for non-DFs */
505
1.60k
          if (file->type != SC_FILE_TYPE_DF) {
506
            /* max. record length for fixed- & variable-sized records */
507
1.38k
            if (length > 2 && byte & 0x06) {
508
509
              file->record_length = (length > 3)
509
509
                ? bebytes2ushort(p+2)
510
509
                : p[2];
511
509
              sc_log(ctx, "  record length: %"SC_FORMAT_LEN_SIZE_T"u",
512
509
                file->record_length);
513
509
            }
514
515
            /* number of records */
516
1.38k
            if (length > 4) {
517
267
              file->record_count = (length > 5)
518
267
                ? bebytes2ushort(p+4)
519
267
                : p[4];
520
267
              sc_log(ctx, "  records: %"SC_FORMAT_LEN_SIZE_T"u",
521
267
                file->record_count);
522
267
            }
523
1.38k
          }
524
525
1.60k
          if (SC_SUCCESS != sc_file_set_type_attr(file, p, length))
526
0
            sc_log(ctx, "Warning: Could not set file attributes");
527
1.60k
        }
528
1.85k
        break;
529
530
1.85k
      case 0x83:
531
1.01k
        if (length == 2) {
532
804
          file->id = (p[0] << 8) | p[1];
533
804
          sc_log(ctx, "  file identifier: 0x%02X%02X", p[0], p[1]);
534
804
        }
535
1.01k
        break;
536
537
360
      case 0x84:
538
360
        if (length > 0 && length <= 16) {
539
274
          memcpy(file->name, p, length);
540
274
          file->namelen = length;
541
542
274
          sc_log_hex(ctx, "  File name:", file->name, file->namelen);
543
274
          if (!file->type)
544
135
            file->type = SC_FILE_TYPE_DF;
545
274
        }
546
360
        break;
547
548
931
      case 0x85:
549
1.16k
      case 0xA5:
550
1.16k
        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.16k
        break;
554
555
1.21k
      case 0x86:
556
1.21k
        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.21k
        break;
560
561
577
      case 0x88:
562
577
        if (length == 1) {
563
93
          file->sid = *p;
564
93
          sc_log(ctx, "  short file identifier: 0x%02X", *p);
565
93
        }
566
577
        break;
567
568
1.37k
      case 0x8A:
569
1.37k
        if (length == 1) {
570
1.25k
          switch (p[0]) {
571
68
            case 0:
572
68
              file->status =SC_FILE_STATUS_NO_INFO;
573
68
              break;
574
69
            case 1:
575
69
              file->status = SC_FILE_STATUS_CREATION;
576
69
              break;
577
71
            case 3:
578
71
              file->status = SC_FILE_STATUS_INITIALISATION;
579
71
              break;
580
72
            case 4:
581
138
            case 6:
582
138
              file->status = SC_FILE_STATUS_INVALIDATED;
583
138
              break;
584
154
            case 5:
585
220
            case 7:
586
220
              file->status = SC_FILE_STATUS_ACTIVATED;
587
220
              break;
588
66
            case 12:
589
139
            case 13:
590
216
            case 14:
591
284
            case 15:
592
284
              file->status = SC_FILE_STATUS_TERMINATION;
593
284
              break;
594
66
            case 2:
595
66
              file->status = SC_FILE_STATUS_RFU_2;
596
66
              break;
597
66
            case 8:
598
66
              file->status = SC_FILE_STATUS_RFU_8;
599
66
              break;
600
66
            case 9:
601
66
              file->status = SC_FILE_STATUS_RFU_9;
602
66
              break;
603
66
            case 10:
604
66
              file->status = SC_FILE_STATUS_RFU_10;
605
66
              break;
606
67
            case 11:
607
67
              file->status = SC_FILE_STATUS_RFU_11;
608
67
              break;
609
70
            default:
610
70
              file->status = SC_FILE_STATUS_PROPRIETARY;
611
1.25k
          }
612
1.25k
        }
613
1.37k
        break;
614
615
1.37k
      case 0x62:
616
980
      case 0x64:
617
1.29k
      case 0x6F:
618
        /* allow nested FCP/FMD/FCI templates */
619
1.29k
        iso7816_process_fci(card, file, p, length);
620
16.1k
    }
621
16.1k
  }
622
623
8.75k
  file->magic = SC_FILE_MAGIC;
624
625
8.75k
  return SC_SUCCESS;
626
8.75k
}
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
49.8k
{
632
49.8k
  struct sc_context *ctx;
633
49.8k
  struct sc_apdu apdu;
634
49.8k
  unsigned char buf[SC_MAX_APDU_BUFFER_SIZE];
635
49.8k
  unsigned char pathbuf[SC_MAX_PATH_SIZE], *path = pathbuf;
636
49.8k
  int r, pathtype;
637
49.8k
  size_t pathlen;
638
49.8k
  int select_mf = 0;
639
49.8k
  struct sc_file *file = NULL;
640
49.8k
  const u8 *buffer;
641
49.8k
  size_t buffer_len;
642
49.8k
  unsigned int cla, tag;
643
644
49.8k
  if (card == NULL || in_path == NULL) {
645
0
    return SC_ERROR_INVALID_ARGUMENTS;
646
0
  }
647
49.8k
  ctx = card->ctx;
648
49.8k
  memcpy(path, in_path->value, in_path->len);
649
49.8k
  pathlen = in_path->len;
650
49.8k
  pathtype = in_path->type;
651
652
49.8k
  if (in_path->aid.len) {
653
1.81k
    if (!pathlen) {
654
1.30k
      memcpy(path, in_path->aid.value, in_path->aid.len);
655
1.30k
      pathlen = in_path->aid.len;
656
1.30k
      pathtype = SC_PATH_TYPE_DF_NAME;
657
1.30k
    } else {
658
      /* First, select the application */
659
517
      sc_format_apdu(card, &apdu, SC_APDU_CASE_3_SHORT, 0xA4, 4, 0);
660
517
      apdu.data = in_path->aid.value;
661
517
      apdu.datalen = in_path->aid.len;
662
517
      apdu.lc = in_path->aid.len;
663
664
517
      r = sc_transmit_apdu(card, &apdu);
665
517
      LOG_TEST_RET(ctx, r, "APDU transmit failed");
666
514
      r = sc_check_sw(card, apdu.sw1, apdu.sw2);
667
514
      if (r)
668
514
        LOG_FUNC_RETURN(ctx, r);
669
670
152
      if (pathtype == SC_PATH_TYPE_PATH
671
0
          || pathtype == SC_PATH_TYPE_DF_NAME)
672
152
        pathtype = SC_PATH_TYPE_FROM_CURRENT;
673
152
    }
674
1.81k
  }
675
676
49.4k
  sc_format_apdu(card, &apdu, SC_APDU_CASE_4_SHORT, 0xA4, 0, 0);
677
678
49.4k
  switch (pathtype) {
679
10.3k
  case SC_PATH_TYPE_FILE_ID:
680
10.3k
    apdu.p1 = 0;
681
10.3k
    if (pathlen != 2)
682
0
      return SC_ERROR_INVALID_ARGUMENTS;
683
10.3k
    break;
684
20.9k
  case SC_PATH_TYPE_DF_NAME:
685
20.9k
    apdu.p1 = 4;
686
20.9k
    break;
687
17.8k
  case SC_PATH_TYPE_PATH:
688
17.8k
    apdu.p1 = 8;
689
17.8k
    if (pathlen >= 2 && memcmp(path, "\x3F\x00", 2) == 0) {
690
12.4k
      if (pathlen == 2) { /* only 3F00 supplied */
691
3.55k
        select_mf = 1;
692
3.55k
        apdu.p1 = 0;
693
3.55k
        break;
694
3.55k
      }
695
8.93k
      path += 2;
696
8.93k
      pathlen -= 2;
697
8.93k
    }
698
14.2k
    break;
699
14.2k
  case SC_PATH_TYPE_FROM_CURRENT:
700
152
    apdu.p1 = 9;
701
152
    break;
702
114
  case SC_PATH_TYPE_PARENT:
703
114
    apdu.p1 = 3;
704
114
    pathlen = 0;
705
114
    apdu.cse = SC_APDU_CASE_2_SHORT;
706
114
    break;
707
0
  default:
708
0
    LOG_FUNC_RETURN(ctx, SC_ERROR_INVALID_ARGUMENTS);
709
49.4k
  }
710
49.4k
  apdu.lc = pathlen;
711
49.4k
  apdu.data = path;
712
49.4k
  apdu.datalen = pathlen;
713
714
49.4k
  if (file_out != NULL) {
715
32.1k
    apdu.p2 = 0;    /* first record, return FCI */
716
32.1k
    apdu.resp = buf;
717
32.1k
    apdu.resplen = sizeof(buf);
718
32.1k
    apdu.le = sc_get_max_recv_size(card) < 256 ? sc_get_max_recv_size(card) : 256;
719
32.1k
  }
720
17.3k
  else {
721
17.3k
    apdu.p2 = 0x0C;   /* first record, return nothing */
722
17.3k
    apdu.cse = (apdu.lc == 0) ? SC_APDU_CASE_1 : SC_APDU_CASE_3_SHORT;
723
17.3k
  }
724
725
49.4k
  r = sc_transmit_apdu(card, &apdu);
726
49.4k
  LOG_TEST_RET(ctx, r, "APDU transmit failed");
727
49.0k
  if (file_out == NULL) {
728
    /* For some cards 'SELECT' can be only with request to return FCI/FCP. */
729
17.3k
    r = sc_check_sw(card, apdu.sw1, apdu.sw2);
730
17.3k
    if (apdu.sw1 == 0x6A && apdu.sw2 == 0x86)   {
731
20
      apdu.p2 = 0x00;
732
20
      if (sc_transmit_apdu(card, &apdu) == SC_SUCCESS)
733
10
        r = sc_check_sw(card, apdu.sw1, apdu.sw2);
734
20
    }
735
17.3k
    if (apdu.sw1 == 0x61)
736
17.3k
      LOG_FUNC_RETURN(ctx, SC_SUCCESS);
737
17.3k
    LOG_FUNC_RETURN(ctx, r);
738
17.3k
  }
739
740
31.7k
  r = sc_check_sw(card, apdu.sw1, apdu.sw2);
741
31.7k
  if (r)
742
31.7k
    LOG_FUNC_RETURN(ctx, r);
743
744
14.0k
  if (file_out && (apdu.resplen == 0))   {
745
    /* For some cards 'SELECT' MF or DF_NAME do not return FCI. */
746
2.66k
    if (select_mf || pathtype == SC_PATH_TYPE_DF_NAME)   {
747
1.66k
      file = sc_file_new();
748
1.66k
      if (file == NULL)
749
1.66k
        LOG_FUNC_RETURN(ctx, SC_ERROR_OUT_OF_MEMORY);
750
1.66k
      file->path = *in_path;
751
752
1.66k
      *file_out = file;
753
1.66k
      LOG_FUNC_RETURN(ctx, SC_SUCCESS);
754
1.66k
    }
755
2.66k
  }
756
757
12.3k
  if (apdu.resplen < 2)
758
12.3k
    LOG_FUNC_RETURN(ctx, SC_ERROR_UNKNOWN_DATA_RECEIVED);
759
11.2k
  switch (apdu.resp[0]) {
760
10.1k
  case ISO7816_TAG_FCI:
761
10.9k
  case ISO7816_TAG_FCP:
762
10.9k
    file = sc_file_new();
763
10.9k
    if (file == NULL)
764
10.9k
      LOG_FUNC_RETURN(ctx, SC_ERROR_OUT_OF_MEMORY);
765
10.9k
    file->path = *in_path;
766
10.9k
    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.9k
    buffer = apdu.resp;
771
10.9k
    r = sc_asn1_read_tag(&buffer, apdu.resplen, &cla, &tag, &buffer_len);
772
10.9k
    if (r == SC_SUCCESS)
773
10.1k
      card->ops->process_fci(card, file, buffer, buffer_len);
774
10.9k
    *file_out = file;
775
10.9k
    break;
776
107
  case 0x00: /* proprietary coding */
777
107
    LOG_FUNC_RETURN(ctx, SC_ERROR_UNKNOWN_DATA_RECEIVED);
778
218
  default:
779
218
    LOG_FUNC_RETURN(ctx, SC_ERROR_UNKNOWN_DATA_RECEIVED);
780
11.2k
  }
781
782
10.9k
  return SC_SUCCESS;
783
11.2k
}
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
65.2k
{
904
65.2k
  struct sc_apdu apdu = {0};
905
65.2k
  int r;
906
65.2k
  size_t rlen;
907
908
  /* request at most max_recv_size bytes */
909
65.2k
  if (*count > sc_get_max_recv_size(card))
910
17.2k
    rlen = sc_get_max_recv_size(card);
911
47.9k
  else
912
47.9k
    rlen = *count;
913
914
65.2k
  sc_format_apdu(card, &apdu, SC_APDU_CASE_2, 0xC0, 0x00, 0x00);
915
65.2k
  apdu.le      = rlen;
916
65.2k
  apdu.resplen = rlen;
917
65.2k
  apdu.resp    = buf;
918
  /* don't call GET RESPONSE recursively */
919
65.2k
  apdu.flags  |= SC_APDU_FLAGS_NO_GET_RESP;
920
921
65.2k
  r = sc_transmit_apdu(card, &apdu);
922
65.2k
  LOG_TEST_RET(card->ctx, r, "APDU transmit failed");
923
924
64.7k
  *count = apdu.resplen;
925
926
64.7k
  if (apdu.resplen == 0) {
927
8.28k
    LOG_FUNC_RETURN(card->ctx, sc_check_sw(card, apdu.sw1, apdu.sw2));
928
8.28k
  }
929
56.5k
  if (apdu.sw1 == 0x90 && apdu.sw2 == 0x00)
930
17.4k
    r = 0;          /* no more data to read */
931
39.0k
  else if (apdu.sw1 == 0x61)
932
35.6k
    r = apdu.sw2 == 0 ? 256 : apdu.sw2;  /* more data to read    */
933
3.41k
  else if (apdu.sw1 == 0x62 && apdu.sw2 == 0x82)
934
196
    r = 0; /* Le not reached but file/record ended */
935
3.21k
  else
936
3.21k
    r = sc_check_sw(card, apdu.sw1, apdu.sw2);
937
938
56.5k
  return r;
939
64.7k
}
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.47k
{
981
1.47k
  struct sc_apdu apdu;
982
1.47k
  u8 sbuf[SC_MAX_APDU_BUFFER_SIZE];
983
1.47k
  u8 *p;
984
1.47k
  int r, locked = 0;
985
986
1.47k
  if (card == NULL || env == NULL) {
987
0
    return SC_ERROR_INVALID_ARGUMENTS;
988
0
  }
989
1.47k
  sc_format_apdu(card, &apdu, SC_APDU_CASE_3_SHORT, 0x22, 0x41, 0);
990
1.47k
  switch (env->operation) {
991
387
  case SC_SEC_OPERATION_DECIPHER:
992
387
  case SC_SEC_OPERATION_DERIVE:
993
387
    apdu.p2 = 0xB8;
994
387
    break;
995
1.08k
  case SC_SEC_OPERATION_SIGN:
996
1.08k
    apdu.p2 = 0xB6;
997
1.08k
    break;
998
0
  default:
999
0
    return SC_ERROR_INVALID_ARGUMENTS;
1000
1.47k
  }
1001
1.47k
  p = sbuf;
1002
1.47k
  if (env->flags & SC_SEC_ENV_ALG_REF_PRESENT) {
1003
1.00k
    *p++ = 0x80;  /* algorithm reference */
1004
1.00k
    *p++ = 0x01;
1005
1.00k
    *p++ = env->algorithm_ref & 0xFF;
1006
1.00k
  }
1007
1.47k
  if (env->flags & SC_SEC_ENV_FILE_REF_PRESENT) {
1008
0
    if (env->file_ref.len > SC_MAX_PATH_SIZE)
1009
0
      return SC_ERROR_INVALID_ARGUMENTS;
1010
0
    if (sizeof(sbuf) - (p - sbuf) < env->file_ref.len + 2)
1011
0
      return SC_ERROR_OFFSET_TOO_LARGE;
1012
1013
0
    *p++ = 0x81;
1014
0
    *p++ = (u8) env->file_ref.len;
1015
0
    memcpy(p, env->file_ref.value, env->file_ref.len);
1016
0
    p += env->file_ref.len;
1017
0
  }
1018
1.47k
  if (env->flags & SC_SEC_ENV_KEY_REF_PRESENT) {
1019
1.47k
    if (sizeof(sbuf) - (p - sbuf) < env->key_ref_len + 2)
1020
0
      return SC_ERROR_OFFSET_TOO_LARGE;
1021
1022
1.47k
    if (env->flags & SC_SEC_ENV_KEY_REF_SYMMETRIC)
1023
0
      *p++ = 0x83;
1024
1.47k
    else
1025
1.47k
      *p++ = 0x84;
1026
1.47k
    if (env->key_ref_len > SC_MAX_KEYREF_SIZE)
1027
0
      return SC_ERROR_INVALID_ARGUMENTS;
1028
1.47k
    *p++ = env->key_ref_len & 0xFF;
1029
1.47k
    memcpy(p, env->key_ref, env->key_ref_len);
1030
1.47k
    p += env->key_ref_len;
1031
1.47k
  }
1032
1.47k
  r = (int)(p - sbuf);
1033
1.47k
  apdu.lc = r;
1034
1.47k
  apdu.datalen = r;
1035
1.47k
  apdu.data = sbuf;
1036
1.47k
  if (se_num > 0) {
1037
0
    r = sc_lock(card);
1038
0
    LOG_TEST_RET(card->ctx, r, "sc_lock() failed");
1039
0
    locked = 1;
1040
0
  }
1041
1.47k
  if (apdu.datalen != 0) {
1042
1.47k
    r = sc_transmit_apdu(card, &apdu);
1043
1.47k
    if (r) {
1044
18
      sc_log(card->ctx, "%s: APDU transmit failed", sc_strerror(r));
1045
18
      goto err;
1046
18
    }
1047
1.45k
    r = sc_check_sw(card, apdu.sw1, apdu.sw2);
1048
1.45k
    if (r) {
1049
1.19k
      sc_log(card->ctx, "%s: Card returned error", sc_strerror(r));
1050
1.19k
      goto err;
1051
1.19k
    }
1052
1.45k
  }
1053
263
  if (se_num <= 0) {
1054
263
    r = SC_SUCCESS;
1055
263
    goto err;
1056
263
  }
1057
0
  sc_format_apdu(card, &apdu, SC_APDU_CASE_3_SHORT, 0x22, 0xF2, se_num);
1058
0
  r = sc_transmit_apdu(card, &apdu);
1059
0
  sc_unlock(card);
1060
0
  LOG_TEST_RET(card->ctx, r, "APDU transmit failed");
1061
1062
0
  return sc_check_sw(card, apdu.sw1, apdu.sw2);
1063
1.47k
err:
1064
1.47k
  if (locked)
1065
0
    sc_unlock(card);
1066
1.47k
  return r;
1067
0
}
1068
1069
1070
static int
1071
iso7816_restore_security_env(struct sc_card *card, int se_num)
1072
63
{
1073
63
  struct sc_apdu apdu;
1074
63
  int r;
1075
1076
63
  if (card == NULL) {
1077
0
    return SC_ERROR_INVALID_ARGUMENTS;
1078
0
  }
1079
1080
63
  sc_format_apdu(card, &apdu, SC_APDU_CASE_1, 0x22, 0xF3, se_num);
1081
1082
63
  r = sc_transmit_apdu(card, &apdu);
1083
63
  LOG_TEST_RET(card->ctx, r, "APDU transmit failed");
1084
59
  r = sc_check_sw(card, apdu.sw1, apdu.sw2);
1085
59
  LOG_TEST_RET(card->ctx, r, "Card returned error");
1086
1087
45
  return r;
1088
59
}
1089
1090
1091
static int
1092
iso7816_compute_signature(struct sc_card *card,
1093
    const u8 * data, size_t datalen,
1094
    u8 * out, size_t outlen)
1095
143
{
1096
143
  int r;
1097
143
  struct sc_apdu apdu;
1098
1099
143
  if (card == NULL || data == NULL || out == NULL) {
1100
0
    return SC_ERROR_INVALID_ARGUMENTS;
1101
0
  }
1102
143
  LOG_FUNC_CALLED(card->ctx);
1103
143
  sc_log(card->ctx,
1104
143
         "ISO7816 compute signature: in-len %"SC_FORMAT_LEN_SIZE_T"u, out-len %"SC_FORMAT_LEN_SIZE_T"u",
1105
143
         datalen, outlen);
1106
1107
  /* INS: 0x2A  PERFORM SECURITY OPERATION
1108
   * P1:  0x9E  Resp: Digital Signature
1109
   * P2:  0x9A  Cmd: Input for Digital Signature */
1110
143
  sc_format_apdu(card, &apdu, SC_APDU_CASE_4, 0x2A, 0x9E, 0x9A);
1111
143
  apdu.resp = out;
1112
143
  apdu.resplen = outlen;
1113
143
  apdu.le = outlen;
1114
1115
143
  apdu.data = data;
1116
143
  apdu.lc = datalen;
1117
143
  apdu.datalen = datalen;
1118
1119
143
  iso7816_fixup_transceive_length(card, &apdu);
1120
143
  r = sc_transmit_apdu(card, &apdu);
1121
143
  LOG_TEST_RET(card->ctx, r, "APDU transmit failed");
1122
105
  if (apdu.sw1 == 0x90 && apdu.sw2 == 0x00)
1123
105
    LOG_FUNC_RETURN(card->ctx, (int)apdu.resplen);
1124
1125
35
  r = sc_check_sw(card, apdu.sw1, apdu.sw2);
1126
35
  LOG_TEST_RET(card->ctx, r, "Card returned error");
1127
1128
0
  LOG_FUNC_RETURN(card->ctx, r);
1129
0
}
1130
1131
1132
static int
1133
iso7816_decipher(struct sc_card *card,
1134
    const u8 * crgram, size_t crgram_len,
1135
    u8 * out, size_t outlen)
1136
39
{
1137
39
  int r;
1138
39
  struct sc_apdu apdu;
1139
39
  u8 *sbuf = NULL;
1140
1141
39
  if (card == NULL || crgram == NULL || out == NULL) {
1142
0
    return SC_ERROR_INVALID_ARGUMENTS;
1143
0
  }
1144
39
  LOG_FUNC_CALLED(card->ctx);
1145
39
  sc_log(card->ctx,
1146
39
         "ISO7816 decipher: in-len %"SC_FORMAT_LEN_SIZE_T"u, out-len %"SC_FORMAT_LEN_SIZE_T"u",
1147
39
         crgram_len, outlen);
1148
1149
39
  sbuf = malloc(crgram_len + 1);
1150
39
  if (sbuf == NULL)
1151
0
    return SC_ERROR_OUT_OF_MEMORY;
1152
1153
  /* INS: 0x2A  PERFORM SECURITY OPERATION
1154
   * P1:  0x80  Resp: Plain value
1155
   * P2:  0x86  Cmd: Padding indicator byte followed by cryptogram */
1156
39
  sc_format_apdu(card, &apdu, SC_APDU_CASE_4, 0x2A, 0x80, 0x86);
1157
39
  apdu.resp    = out;
1158
39
  apdu.resplen = outlen;
1159
39
  apdu.le      = outlen;
1160
1161
39
  sbuf[0] = 0; /* padding indicator byte, 0x00 = No further indication */
1162
39
  memcpy(sbuf + 1, crgram, crgram_len);
1163
39
  apdu.data = sbuf;
1164
39
  apdu.lc = crgram_len + 1;
1165
39
  apdu.datalen = crgram_len + 1;
1166
1167
39
  iso7816_fixup_transceive_length(card, &apdu);
1168
39
  r = sc_transmit_apdu(card, &apdu);
1169
39
  sc_mem_clear(sbuf, crgram_len + 1);
1170
39
  free(sbuf);
1171
39
  LOG_TEST_RET(card->ctx, r, "APDU transmit failed");
1172
1173
34
  if (apdu.sw1 == 0x90 && apdu.sw2 == 0x00)
1174
34
    LOG_FUNC_RETURN(card->ctx, (int)apdu.resplen);
1175
7
  else
1176
34
    LOG_FUNC_RETURN(card->ctx, sc_check_sw(card, apdu.sw1, apdu.sw2));
1177
34
}
1178
1179
1180
int
1181
iso7816_build_pin_apdu(struct sc_card *card, struct sc_apdu *apdu,
1182
    struct sc_pin_cmd_data *data, u8 *buf, size_t buf_len)
1183
6.71k
{
1184
6.71k
  int r, len = 0, pad = 0, use_pin_pad = 0, ins, p1 = 0;
1185
6.71k
  int cse = SC_APDU_CASE_3_SHORT;
1186
1187
6.71k
  switch (data->pin_type) {
1188
6.71k
  case SC_AC_CHV:
1189
    /* fall through */
1190
6.71k
  case SC_AC_SESSION:
1191
6.71k
  case SC_AC_CONTEXT_SPECIFIC:
1192
6.71k
    break;
1193
0
  default:
1194
0
    return SC_ERROR_INVALID_ARGUMENTS;
1195
6.71k
  }
1196
1197
6.71k
  if (data->flags & SC_PIN_CMD_NEED_PADDING)
1198
1.21k
    pad = 1;
1199
6.71k
  if (data->flags & SC_PIN_CMD_USE_PINPAD)
1200
0
    use_pin_pad = 1;
1201
1202
6.71k
  data->pin1.offset = 5;
1203
1204
6.71k
  switch (data->cmd) {
1205
657
  case SC_PIN_CMD_VERIFY:
1206
657
    ins = 0x20;
1207
    /* detect overloaded APDU with SC_PIN_CMD_GET_INFO */
1208
657
    if (data->pin1.len == 0 && !use_pin_pad)
1209
0
      return SC_ERROR_INVALID_PIN_LENGTH;
1210
657
    if ((r = sc_build_pin(buf, buf_len, &data->pin1, pad)) < 0)
1211
26
      return r;
1212
631
    len = r;
1213
631
    break;
1214
133
  case SC_PIN_CMD_CHANGE:
1215
133
    ins = 0x24;
1216
133
    if (data->pin1.len != 0 || (use_pin_pad && !( data->flags & SC_PIN_CMD_IMPLICIT_CHANGE))) {
1217
132
      if ((r = sc_build_pin(buf, buf_len, &data->pin1, pad)) < 0)
1218
11
        return r;
1219
121
      len += r;
1220
121
    }
1221
1
    else {
1222
      /* implicit test */
1223
1
      p1 = 1;
1224
1
    }
1225
1226
122
    data->pin2.offset = data->pin1.offset + len;
1227
122
    if ((r = sc_build_pin(buf+len, buf_len-len, &data->pin2, pad)) < 0)
1228
2
      return r;
1229
    /* Special case - where provided the old PIN on the command line
1230
     * but expect the new one to be entered on the keypad.
1231
     */
1232
120
    if (data->pin1.len && data->pin2.len == 0) {
1233
0
      sc_log(card->ctx, "Special case - initial pin provided - but new pin asked on keypad");
1234
0
      data->flags |= SC_PIN_CMD_IMPLICIT_CHANGE;
1235
0
    };
1236
120
    len += r;
1237
120
    break;
1238
192
  case SC_PIN_CMD_UNBLOCK:
1239
192
    ins = 0x2C;
1240
192
    if (data->pin1.len != 0 || (use_pin_pad && !( data->flags & SC_PIN_CMD_IMPLICIT_CHANGE))) {
1241
192
      if ((r = sc_build_pin(buf, buf_len, &data->pin1, pad)) < 0)
1242
5
        return r;
1243
187
      len += r;
1244
187
    } else {
1245
0
      p1 |= 0x02;
1246
0
    }
1247
1248
187
    if (data->pin2.len != 0 || use_pin_pad) {
1249
187
      data->pin2.offset = data->pin1.offset + len;
1250
187
      if ((r = sc_build_pin(buf+len, buf_len-len, &data->pin2, pad)) < 0)
1251
2
        return r;
1252
185
      len += r;
1253
185
    } else {
1254
0
      p1 |= 0x01;
1255
0
    }
1256
185
    if (p1 == 0x03) {
1257
      /* No data to send or to receive */
1258
0
      cse = SC_APDU_CASE_1;
1259
0
    }
1260
185
    break;
1261
5.73k
  case SC_PIN_CMD_GET_INFO:
1262
5.73k
    ins = 0x20;
1263
    /* No data to send or to receive */
1264
5.73k
    cse = SC_APDU_CASE_1;
1265
5.73k
    break;
1266
0
  default:
1267
0
    return SC_ERROR_NOT_SUPPORTED;
1268
6.71k
  }
1269
1270
6.66k
  sc_format_apdu(card, apdu, cse, ins, p1, data->pin_reference);
1271
6.66k
  apdu->lc = len;
1272
6.66k
  apdu->datalen = len;
1273
6.66k
  apdu->data = buf;
1274
6.66k
  apdu->resplen = 0;
1275
1276
6.66k
  return 0;
1277
6.71k
}
1278
1279
1280
static int
1281
iso7816_pin_cmd(struct sc_card *card, struct sc_pin_cmd_data *data, int *tries_left)
1282
6.88k
{
1283
6.88k
  struct sc_apdu local_apdu, *apdu;
1284
6.88k
  int r;
1285
6.88k
  u8  sbuf[SC_MAX_APDU_BUFFER_SIZE];
1286
1287
6.88k
  data->pin1.tries_left = -1;
1288
6.88k
  if (tries_left != NULL) {
1289
982
    *tries_left = data->pin1.tries_left;
1290
982
  }
1291
1292
  /* Many cards do support PIN status queries, but some cards don't and
1293
   * mistakenly count the command as a failed PIN attempt, so for now we
1294
   * allow cards with this flag.  In future this may be reduced to a
1295
   * blocklist, subject to testing more cards. */
1296
6.88k
  if (data->cmd == SC_PIN_CMD_GET_INFO &&
1297
5.89k
      !(card->caps & SC_CARD_CAP_ISO7816_PIN_INFO)) {
1298
165
    sc_log(card->ctx, "Card does not support PIN status queries");
1299
165
    return SC_ERROR_NOT_SUPPORTED;
1300
165
  }
1301
1302
  /* See if we've been called from another card driver, which is
1303
   * passing an APDU to us (this allows to write card drivers
1304
   * whose PIN functions behave "mostly like ISO" except in some
1305
   * special circumstances.
1306
   */
1307
6.71k
  if (data->apdu == NULL) {
1308
6.71k
    r = iso7816_build_pin_apdu(card, &local_apdu, data, sbuf, sizeof(sbuf));
1309
6.71k
    if (r < 0)
1310
46
      return r;
1311
6.66k
    data->apdu = &local_apdu;
1312
6.66k
  }
1313
6.66k
  apdu = data->apdu;
1314
1315
6.66k
  if (!(data->flags & SC_PIN_CMD_USE_PINPAD) || data->cmd == SC_PIN_CMD_GET_INFO) {
1316
    /* Transmit the APDU to the card */
1317
6.66k
    r = sc_transmit_apdu(card, apdu);
1318
1319
    /* Clear the buffer - it may contain pins */
1320
6.66k
    sc_mem_clear(sbuf, sizeof(sbuf));
1321
6.66k
  }
1322
0
  else {
1323
    /* Call the reader driver to collect
1324
     * the PIN and pass on the APDU to the card */
1325
0
    if (data->pin1.offset == 0) {
1326
0
      sc_log(card->ctx, "Card driver didn't set PIN offset");
1327
0
      return SC_ERROR_INVALID_ARGUMENTS;
1328
0
    }
1329
0
    if (card->reader && card->reader->ops && card->reader->ops->perform_verify) {
1330
0
      r = card->reader->ops->perform_verify(card->reader, data);
1331
      /* sw1/sw2 filled in by reader driver */
1332
0
    }
1333
0
    else {
1334
0
      sc_log(card->ctx, "Card reader driver does not support "
1335
0
          "PIN entry through reader key pad");
1336
0
      r = SC_ERROR_NOT_SUPPORTED;
1337
0
    }
1338
0
  }
1339
1340
  /* Don't pass references to local variables up to the caller. */
1341
6.66k
  if (data->apdu == &local_apdu)
1342
6.66k
    data->apdu = NULL;
1343
1344
6.66k
  LOG_TEST_RET(card->ctx, r, "APDU transmit failed");
1345
6.64k
  r = sc_check_sw(card, apdu->sw1, apdu->sw2);
1346
1347
6.64k
  if (r == SC_SUCCESS) {
1348
1.69k
    data->pin1.logged_in = SC_PIN_STATE_LOGGED_IN;
1349
4.95k
  } else if (r == SC_ERROR_PIN_CODE_INCORRECT) {
1350
32
    data->pin1.tries_left = apdu->sw2 & 0xF;
1351
32
    data->pin1.logged_in = SC_PIN_STATE_LOGGED_OUT;
1352
32
    if (data->cmd == SC_PIN_CMD_GET_INFO)
1353
18
      r = SC_SUCCESS;
1354
4.91k
  } else if (r == SC_ERROR_AUTH_METHOD_BLOCKED) {
1355
6
    data->pin1.tries_left = 0;
1356
6
    data->pin1.logged_in = SC_PIN_STATE_LOGGED_OUT;
1357
6
    if (data->cmd == SC_PIN_CMD_GET_INFO)
1358
3
      r = SC_SUCCESS;
1359
6
  }
1360
6.64k
  if (tries_left != NULL) {
1361
925
    *tries_left = data->pin1.tries_left;
1362
925
  }
1363
1364
6.64k
  return r;
1365
6.66k
}
1366
1367
1368
static int iso7816_get_data(struct sc_card *card, unsigned int tag,  u8 *buf, size_t len)
1369
207
{
1370
207
  int                             r, cse;
1371
207
  struct sc_apdu                  apdu;
1372
1373
207
  SC_FUNC_CALLED(card->ctx, SC_LOG_DEBUG_VERBOSE);
1374
1375
207
  if (buf && len)
1376
207
    cse = SC_APDU_CASE_2;
1377
0
  else
1378
0
    cse = SC_APDU_CASE_1;
1379
1380
207
  sc_format_apdu(card, &apdu, cse, 0xCA, (tag >> 8) & 0xff, tag & 0xff);
1381
207
  apdu.le = len;
1382
207
  apdu.resp = buf;
1383
207
  apdu.resplen = len;
1384
207
  r = sc_transmit_apdu(card, &apdu);
1385
207
  LOG_TEST_RET(card->ctx, r, "APDU transmit failed");
1386
1387
203
  r = sc_check_sw(card, apdu.sw1, apdu.sw2);
1388
203
  LOG_TEST_RET(card->ctx, r, "GET_DATA returned error");
1389
1390
156
  if (apdu.resplen > len)
1391
0
    r = SC_ERROR_WRONG_LENGTH;
1392
156
  else
1393
156
    r = (int)apdu.resplen;
1394
1395
156
  LOG_FUNC_RETURN(card->ctx, r);
1396
156
}
1397
1398
int
1399
iso7816_select_aid(struct sc_card *card, const u8 *req,
1400
    size_t reqlen, u8 *resp, size_t *resplen)
1401
18.6k
{
1402
18.6k
  struct sc_context *ctx = card->ctx;
1403
18.6k
  struct sc_apdu apdu;
1404
18.6k
  int rv;
1405
1406
18.6k
  SC_FUNC_CALLED(ctx, SC_LOG_DEBUG_VERBOSE);
1407
1408
18.6k
  sc_format_apdu(card, &apdu, resp == NULL ? SC_APDU_CASE_3_SHORT : SC_APDU_CASE_4_SHORT, 0xA4, 0x04, resp == NULL ? 0x0C : 0x00);
1409
18.6k
  apdu.lc = reqlen;
1410
18.6k
  apdu.data = req;
1411
18.6k
  apdu.datalen = reqlen;
1412
18.6k
  apdu.resp = resp;
1413
18.6k
  apdu.resplen = resp == NULL ? 0 : *resplen;
1414
18.6k
  apdu.le = resp == NULL ? 0 : 256;
1415
1416
18.6k
  rv = sc_transmit_apdu(card, &apdu);
1417
18.6k
  if (resplen)
1418
12.2k
    *resplen = apdu.resplen;
1419
18.6k
  LOG_TEST_RET(card->ctx, rv, "APDU transmit failed");
1420
1421
18.4k
  rv = sc_check_sw(card, apdu.sw1, apdu.sw2);
1422
18.4k
  LOG_FUNC_RETURN(ctx, rv);
1423
18.4k
}
1424
1425
static int
1426
iso7816_init(struct sc_card *card)
1427
0
{
1428
0
#if ENABLE_SM
1429
0
  memset(&card->sm_ctx, 0, sizeof card->sm_ctx);
1430
0
#endif
1431
0
  return SC_SUCCESS;
1432
0
}
1433
1434
1435
static int
1436
no_match(struct sc_card *card)
1437
0
{
1438
0
  return 0;
1439
0
}
1440
1441
static struct sc_card_operations iso_ops = {
1442
  no_match,
1443
  iso7816_init, /* init   */
1444
  NULL,     /* finish */
1445
  iso7816_read_binary,
1446
  iso7816_write_binary,
1447
  iso7816_update_binary,
1448
  NULL,     /* erase_binary */
1449
  iso7816_read_record,
1450
  iso7816_write_record,
1451
  iso7816_append_record,
1452
  iso7816_update_record,
1453
  iso7816_select_file,
1454
  iso7816_get_response,
1455
  iso7816_get_challenge,
1456
  NULL,     /* verify */
1457
  NULL,     /* logout */
1458
  iso7816_restore_security_env,
1459
  iso7816_set_security_env,
1460
  iso7816_decipher,
1461
  iso7816_compute_signature,
1462
  NULL,     /* change_reference_data */
1463
  NULL,     /* reset_retry_counter   */
1464
  iso7816_create_file,
1465
  iso7816_delete_file,
1466
  NULL,     /* list_files */
1467
  iso7816_check_sw,
1468
  NULL,     /* card_ctl */
1469
  iso7816_process_fci,
1470
  iso7816_construct_fci,
1471
  iso7816_pin_cmd,
1472
  iso7816_get_data,
1473
  NULL,     /* put_data */
1474
  NULL,     /* delete_record */
1475
  NULL,     /* read_public_key */
1476
  NULL,     /* card_reader_lock_obtained */
1477
  NULL,     /* wrap */
1478
  NULL,     /* unwrap */
1479
  NULL,     /* encrypt_sym */
1480
  NULL      /* decrypt_sym */
1481
};
1482
1483
static struct sc_card_driver iso_driver = {
1484
  "ISO 7816 reference driver",
1485
  "iso7816",
1486
  &iso_ops,
1487
  NULL, 0, NULL
1488
};
1489
1490
struct sc_card_driver * sc_get_iso7816_driver(void)
1491
511k
{
1492
511k
  return &iso_driver;
1493
511k
}
1494
1495
0
#define ISO_READ_BINARY  0xB0
1496
0
#define ISO_P1_FLAG_SFID 0x80
1497
int iso7816_read_binary_sfid(sc_card_t *card, unsigned char sfid,
1498
    u8 **ef, size_t *ef_len)
1499
0
{
1500
0
  int r;
1501
0
  size_t read;
1502
0
  sc_apdu_t apdu;
1503
0
  u8 *p;
1504
1505
0
  if (!card || !ef || !ef_len) {
1506
0
    r = SC_ERROR_INVALID_ARGUMENTS;
1507
0
    goto err;
1508
0
  }
1509
0
  *ef_len = 0;
1510
1511
0
  read = card->max_recv_size;
1512
0
  sc_format_apdu(card, &apdu, SC_APDU_CASE_2,
1513
0
      ISO_READ_BINARY, ISO_P1_FLAG_SFID|sfid, 0);
1514
0
  p = realloc(*ef, read);
1515
0
  if (!p) {
1516
0
    r = SC_ERROR_OUT_OF_MEMORY;
1517
0
    goto err;
1518
0
  }
1519
0
  *ef = p;
1520
0
  apdu.resp = *ef;
1521
0
  apdu.resplen = read;
1522
0
  apdu.le = read;
1523
1524
0
  r = sc_transmit_apdu(card, &apdu);
1525
0
  if (r < 0)
1526
0
    goto err;
1527
0
  r = sc_check_sw(card, apdu.sw1, apdu.sw2);
1528
0
  if (r < 0 && r != SC_ERROR_FILE_END_REACHED)
1529
0
    goto err;
1530
  /* emulate the behaviour of iso7816_read_binary */
1531
0
  r = (int)apdu.resplen;
1532
1533
0
  while(1) {
1534
0
    if (r >= 0 && ((size_t) r) != read) {
1535
0
      *ef_len += r;
1536
0
      break;
1537
0
    }
1538
0
    if (r <= 0) {
1539
0
      if (*ef_len > 0)
1540
0
        break;
1541
0
      else {
1542
0
        sc_debug(card->ctx, SC_LOG_DEBUG_VERBOSE, "Could not read EF.");
1543
0
        goto err;
1544
0
      }
1545
0
    }
1546
0
    *ef_len += r;
1547
1548
0
    p = realloc(*ef, *ef_len + read);
1549
0
    if (!p) {
1550
0
      r = SC_ERROR_OUT_OF_MEMORY;
1551
0
      goto err;
1552
0
    }
1553
0
    *ef = p;
1554
1555
0
    r = iso7816_read_binary(card, (unsigned)*ef_len, *ef + *ef_len, read, 0);
1556
0
  }
1557
1558
0
  r = (int)*ef_len;
1559
1560
0
err:
1561
0
  return r;
1562
0
}
1563
1564
0
#define ISO_WRITE_BINARY  0xD0
1565
int iso7816_write_binary_sfid(sc_card_t *card, unsigned char sfid,
1566
    u8 *ef, size_t ef_len)
1567
0
{
1568
0
  int r;
1569
0
  size_t write, wrote = 0;
1570
0
  sc_apdu_t apdu;
1571
1572
0
  if (!card) {
1573
0
    r = SC_ERROR_INVALID_ARGUMENTS;
1574
0
    goto err;
1575
0
  }
1576
1577
0
  write = card->max_send_size;
1578
1579
0
  sc_format_apdu(card, &apdu, SC_APDU_CASE_3,
1580
0
      ISO_WRITE_BINARY, ISO_P1_FLAG_SFID|sfid, 0);
1581
1582
0
  if (write > ef_len) {
1583
0
    apdu.datalen = ef_len;
1584
0
    apdu.lc = ef_len;
1585
0
  } else {
1586
0
    apdu.datalen = write;
1587
0
    apdu.lc = write;
1588
0
  }
1589
0
  apdu.data = ef;
1590
1591
1592
0
  r = sc_transmit_apdu(card, &apdu);
1593
  /* emulate the behaviour of sc_write_binary */
1594
0
  if (r >= 0)
1595
0
    r = (int)apdu.datalen;
1596
1597
0
  while (1) {
1598
0
    if (r < 0 || ((size_t) r) > ef_len) {
1599
0
      sc_debug(card->ctx, SC_LOG_DEBUG_VERBOSE, "Could not write EF.");
1600
0
      goto err;
1601
0
    }
1602
0
    if (r == 0 || r == SC_ERROR_FILE_END_REACHED)
1603
0
      break;
1604
0
    wrote += r;
1605
0
    apdu.data += r;
1606
0
    if (wrote >= ef_len)
1607
0
      break;
1608
1609
0
    r = sc_write_binary(card, (unsigned)wrote, ef, write, 0);
1610
0
  }
1611
1612
0
  r = (int)wrote;
1613
1614
0
err:
1615
0
  return r;
1616
0
}
1617
1618
0
#define ISO_UPDATE_BINARY  0xD6
1619
int iso7816_update_binary_sfid(sc_card_t *card, unsigned char sfid,
1620
    u8 *ef, size_t ef_len)
1621
0
{
1622
0
  int r;
1623
0
  size_t write = MAX_SM_APDU_DATA_SIZE, wrote = 0;
1624
0
  sc_apdu_t apdu;
1625
0
#ifdef ENABLE_SM
1626
0
  struct iso_sm_ctx *iso_sm_ctx;
1627
0
#endif
1628
1629
0
  if (!card) {
1630
0
    r = SC_ERROR_INVALID_ARGUMENTS;
1631
0
    goto err;
1632
0
  }
1633
1634
0
#ifdef ENABLE_SM
1635
0
  iso_sm_ctx = card->sm_ctx.info.cmd_data;
1636
0
  if (write > SC_MAX_APDU_BUFFER_SIZE-2
1637
0
      || (card->sm_ctx.sm_mode == SM_MODE_TRANSMIT
1638
0
        && write > (((SC_MAX_APDU_BUFFER_SIZE-2
1639
          /* for encrypted APDUs we usually get authenticated status
1640
           * bytes (4B), a MAC (11B) and a cryptogram with padding
1641
           * indicator (3B without data).  The cryptogram is always
1642
           * padded to the block size. */
1643
0
          -18) / iso_sm_ctx->block_length)
1644
0
          * iso_sm_ctx->block_length - 1)))
1645
0
    sc_format_apdu(card, &apdu, SC_APDU_CASE_3_EXT,
1646
0
        ISO_UPDATE_BINARY, ISO_P1_FLAG_SFID|sfid, 0);
1647
0
  else
1648
0
#endif
1649
0
    sc_format_apdu(card, &apdu, SC_APDU_CASE_3_SHORT,
1650
0
        ISO_UPDATE_BINARY, ISO_P1_FLAG_SFID|sfid, 0);
1651
1652
0
  if (write > ef_len) {
1653
0
    apdu.datalen = ef_len;
1654
0
    apdu.lc = ef_len;
1655
0
  } else {
1656
0
    apdu.datalen = write;
1657
0
    apdu.lc = write;
1658
0
  }
1659
0
  apdu.data = ef;
1660
1661
1662
0
  r = sc_transmit_apdu(card, &apdu);
1663
  /* emulate the behaviour of sc_write_binary */
1664
0
  if (r >= 0)
1665
0
    r = (int)apdu.datalen;
1666
1667
0
  while (1) {
1668
0
    if (r < 0 || ((size_t) r) > ef_len) {
1669
0
      sc_debug(card->ctx, SC_LOG_DEBUG_VERBOSE, "Could not update EF.");
1670
0
      goto err;
1671
0
    }
1672
0
    if (r == 0 || r == SC_ERROR_FILE_END_REACHED)
1673
0
      break;
1674
0
    wrote += r;
1675
0
    apdu.data += r;
1676
0
    if (wrote >= ef_len)
1677
0
      break;
1678
1679
0
    r = sc_update_binary(card, (unsigned)wrote, ef, write, 0);
1680
0
  }
1681
1682
0
  r = (int)wrote;
1683
1684
0
err:
1685
0
  return r;
1686
0
}
1687
1688
int iso7816_logout(sc_card_t *card, unsigned char pin_reference)
1689
0
{
1690
0
  int r;
1691
0
  sc_apdu_t apdu;
1692
1693
0
  sc_format_apdu(card, &apdu, SC_APDU_CASE_1, 0x20, 0xFF, pin_reference);
1694
1695
0
  r = sc_transmit_apdu(card, &apdu);
1696
0
  if (r < 0)
1697
0
    return r;
1698
1699
0
  r = sc_check_sw(card, apdu.sw1, apdu.sw2);
1700
1701
0
  return r;
1702
0
}