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
31.3k
{
37
31.3k
  if (card == NULL || apdu == NULL) {
38
0
    return;
39
0
  }
40
41
31.3k
  if (apdu->lc > sc_get_max_send_size(card)) {
42
    /* The lower layers will automatically do chaining */
43
568
    apdu->flags |= SC_APDU_FLAGS_CHAINING;
44
568
  }
45
46
31.3k
  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.62k
    apdu->le = sc_get_max_recv_size(card);
50
2.62k
  }
51
31.3k
}
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
345k
{
112
345k
  const int err_count = sizeof(iso7816_errors)/sizeof(iso7816_errors[0]);
113
345k
  int i;
114
115
  /* Handle special cases here */
116
345k
  if (sw1 == 0x6C) {
117
179
    sc_log(card->ctx, "Wrong length; correct length is %d", sw2);
118
179
    return SC_ERROR_WRONG_LENGTH;
119
179
  }
120
345k
  if (sw1 == 0x90 && sw2 == 0x00)
121
135k
    return SC_SUCCESS;
122
209k
  if (sw1 == 0x63U && (sw2 & ~0x0fU) == 0xc0U) {
123
81
    sc_log(card->ctx, "PIN not verified (remaining tries: %d)", (sw2 & 0x0f));
124
81
    return SC_ERROR_PIN_CODE_INCORRECT;
125
81
  }
126
8.47M
  for (i = 0; i < err_count; i++)   {
127
8.46M
    if (iso7816_errors[i].SWs == ((sw1 << 8) | sw2)) {
128
196k
      sc_log(card->ctx, "%s", iso7816_errors[i].errorstr);
129
196k
      return iso7816_errors[i].errorno;
130
196k
    }
131
8.46M
  }
132
133
12.7k
  sc_log(card->ctx, "Unknown SWs; SW1=%02X, SW2=%02X", sw1, sw2);
134
12.7k
  return SC_ERROR_CARD_CMD_FAILED;
135
209k
}
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
19.8k
{
141
19.8k
  struct sc_context *ctx = card->ctx;
142
19.8k
  struct sc_apdu apdu;
143
19.8k
  int r;
144
145
19.8k
  if (idx > 0x7FFF) {
146
2
    sc_log(ctx, "invalid EF offset: 0x%X > 0x7FFF", idx);
147
2
    return SC_ERROR_OFFSET_TOO_LARGE;
148
2
  }
149
150
19.8k
  sc_format_apdu(card, &apdu, SC_APDU_CASE_2, 0xB0, (idx >> 8) & 0x7F, idx & 0xFF);
151
19.8k
  apdu.le = count;
152
19.8k
  apdu.resplen = count;
153
19.8k
  apdu.resp = buf;
154
155
19.8k
  iso7816_fixup_transceive_length(card, &apdu);
156
19.8k
  r = sc_transmit_apdu(card, &apdu);
157
19.8k
  LOG_TEST_RET(ctx, r, "APDU transmit failed");
158
159
19.2k
  r = sc_check_sw(card, apdu.sw1, apdu.sw2);
160
19.2k
  if (r == SC_ERROR_FILE_END_REACHED)
161
19.2k
    LOG_FUNC_RETURN(ctx, (int)apdu.resplen);
162
18.1k
  LOG_TEST_RET(ctx, r, "Check SW error");
163
164
14.9k
  LOG_FUNC_RETURN(ctx, (int)apdu.resplen);
165
14.9k
}
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
6.02k
{
178
6.02k
  unsigned char offset_buffer[2];
179
6.02k
  size_t offset_buffer_len = sizeof offset_buffer;
180
6.02k
  struct sc_asn1_entry asn1_do_data[sizeof c_asn1_do_data / sizeof *c_asn1_do_data];
181
6.02k
  sc_copy_asn1_entry(c_asn1_do_data, asn1_do_data);
182
183
6.02k
  if (idx > 0xFFFF)
184
6.02k
    LOG_TEST_RET(ctx, SC_ERROR_INTERNAL, "Offset beyond 0xFFFF not supported");
185
6.02k
  offset_buffer[0] = (u8) (idx >> 8);
186
6.02k
  offset_buffer[1] = (u8) (idx & 0x00FF);
187
6.02k
  sc_format_asn1_entry(asn1_do_data + 0, offset_buffer, &offset_buffer_len, 1);
188
189
6.02k
  if (data && data_len) {
190
0
    sc_format_asn1_entry(asn1_do_data + 1, (void *) &data, &data_len, 1);
191
6.02k
  } else {
192
6.02k
    sc_format_asn1_entry(asn1_do_data + 1, NULL, NULL, 0);
193
6.02k
  }
194
195
6.02k
  LOG_TEST_RET(ctx,
196
6.02k
      sc_asn1_encode(ctx, asn1_do_data, out, outlen),
197
6.02k
      "sc_asn1_encode() failed");
198
199
6.02k
  return SC_SUCCESS;
200
6.02k
}
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
4.04k
{
206
4.04k
  struct sc_asn1_entry asn1_do_data[sizeof c_asn1_do_data / sizeof *c_asn1_do_data];
207
4.04k
  sc_copy_asn1_entry(c_asn1_do_data, asn1_do_data);
208
209
4.04k
  sc_format_asn1_entry(asn1_do_data + 0, NULL, NULL, 0);
210
4.04k
  sc_format_asn1_entry(asn1_do_data + 1, out, outlen, 0);
211
212
4.04k
  LOG_TEST_RET(ctx,
213
3.90k
      sc_asn1_decode(ctx, asn1_do_data, encoded_data, encoded_data_len, NULL, NULL),
214
3.90k
      "sc_asn1_decode() failed");
215
216
3.90k
  if (!(asn1_do_data[1].flags & SC_ASN1_PRESENT))
217
2.21k
    return SC_ERROR_INVALID_ASN1_OBJECT;
218
219
1.69k
  return SC_SUCCESS;
220
3.90k
}
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
11.4k
{
226
11.4k
  struct sc_apdu apdu;
227
11.4k
  int r;
228
  /* XXX maybe use some bigger buffer */
229
11.4k
  unsigned char resp[SC_MAX_APDU_RESP_SIZE];
230
11.4k
  unsigned char *encoded_data = NULL, *decoded_data = NULL;
231
11.4k
  size_t encoded_data_len = 0, decoded_data_len = 0;
232
233
11.4k
  if (rec_nr > 0xFF)
234
11.4k
    LOG_FUNC_RETURN(card->ctx, SC_ERROR_INVALID_ARGUMENTS);
235
236
11.4k
  if (idx == 0) {
237
5.45k
    sc_format_apdu(card, &apdu, SC_APDU_CASE_2, 0xB2, rec_nr, 0);
238
5.45k
    apdu.le = count;
239
5.45k
    apdu.resplen = count;
240
5.45k
    apdu.resp = buf;
241
6.02k
  } else {
242
6.02k
    r = encode_do_data(card->ctx, idx, NULL, 0, &encoded_data, &encoded_data_len);
243
6.02k
    LOG_TEST_GOTO_ERR(card->ctx, r, "Could not encode data objects");
244
245
6.02k
    sc_format_apdu(card, &apdu, SC_APDU_CASE_4, 0xB3, rec_nr, 0);
246
6.02k
    apdu.lc = encoded_data_len;
247
6.02k
    apdu.datalen = encoded_data_len;
248
6.02k
    apdu.data = encoded_data;
249
6.02k
    apdu.le = sizeof resp;
250
6.02k
    apdu.resplen = sizeof resp;
251
6.02k
    apdu.resp = resp;
252
6.02k
  }
253
11.4k
  apdu.p2 = (flags & SC_RECORD_EF_ID_MASK) << 3;
254
11.4k
  if (flags & SC_RECORD_BY_REC_NR)
255
11.4k
    apdu.p2 |= 0x04;
256
257
11.4k
  iso7816_fixup_transceive_length(card, &apdu);
258
11.4k
  r = sc_transmit_apdu(card, &apdu);
259
11.4k
  LOG_TEST_GOTO_ERR(card->ctx, r, "APDU transmit failed");
260
10.3k
  r = sc_check_sw(card, apdu.sw1, apdu.sw2);
261
10.3k
  LOG_TEST_GOTO_ERR(card->ctx, r, "Card returned error");
262
263
8.87k
  if (idx == 0) {
264
4.83k
    r = (int)apdu.resplen;
265
4.83k
  } else {
266
4.04k
    r = decode_do_data(card->ctx, apdu.resp, apdu.resplen,
267
4.04k
        &decoded_data, &decoded_data_len);
268
4.04k
    LOG_TEST_GOTO_ERR(card->ctx, r, "Could not decode data objects");
269
1.69k
    if (decoded_data_len <= count) {
270
1.28k
      count = decoded_data_len;
271
1.28k
    }
272
1.69k
    memcpy(buf, decoded_data, count);
273
1.69k
    r = (int)count;
274
1.69k
  }
275
276
11.4k
err:
277
11.4k
  free(encoded_data);
278
11.4k
  free(decoded_data);
279
11.4k
  LOG_FUNC_RETURN(card->ctx, r);
280
11.4k
}
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
9.37k
{
432
9.37k
  struct sc_context *ctx = card->ctx;
433
9.37k
  const unsigned char *p, *end;
434
9.37k
  unsigned int cla = 0, tag = 0;
435
9.37k
  size_t length;
436
437
9.37k
  file->status = SC_FILE_STATUS_UNKNOWN;
438
439
9.37k
  for (p = buf, length = buflen, end = buf + buflen;
440
32.7k
      p < end;
441
29.4k
      p += length, length = end - p) {
442
443
29.4k
    if (SC_SUCCESS != sc_asn1_read_tag(&p, length, &cla, &tag, &length)
444
25.4k
        || p == NULL) {
445
6.05k
      break;
446
6.05k
    }
447
23.3k
    switch (cla | tag) {
448
2.57k
      case 0x81:
449
2.57k
        if (file->size != 0) {
450
          /* don't overwrite existing file size excluding structural information */
451
95
          break;
452
95
        }
453
        /* fall through */
454
5.13k
      case 0x80:
455
        /* determine the file size */
456
5.13k
        file->size = 0;
457
5.13k
        if (p && length <= sizeof(size_t)) {
458
5.09k
          size_t size = 0, i;
459
15.8k
          for (i = 0; i < length; i++) {
460
10.7k
            size <<= 8;
461
10.7k
            size |= p[i];
462
10.7k
          }
463
5.09k
          if (size > MAX_FILE_SIZE) {
464
659
            file->size = MAX_FILE_SIZE;
465
659
            sc_log(ctx, "  file size truncated, encoded length: %"SC_FORMAT_LEN_SIZE_T"u", size);
466
4.43k
          } else {
467
4.43k
            file->size = size;
468
4.43k
          }
469
5.09k
        }
470
471
5.13k
        sc_log(ctx, "  bytes in file: %"SC_FORMAT_LEN_SIZE_T"u", file->size);
472
5.13k
        break;
473
474
3.46k
      case 0x82:
475
3.46k
        if (length > 0) {
476
3.36k
          unsigned char byte = p[0];
477
3.36k
          const char *type;
478
479
3.36k
          file->shareable = byte & 0x40 ? 1 : 0;
480
3.36k
          sc_log(ctx, "  shareable: %s", (byte & 0x40) ? "yes" : "no");
481
3.36k
          file->ef_structure = byte & 0x07;
482
3.36k
          switch ((byte >> 3) & 7) {
483
2.33k
            case 0:
484
2.33k
              type = "working EF";
485
2.33k
              file->type = SC_FILE_TYPE_WORKING_EF;
486
2.33k
              break;
487
85
            case 1:
488
85
              type = "internal EF";
489
85
              file->type = SC_FILE_TYPE_INTERNAL_EF;
490
85
              break;
491
213
            case 7:
492
213
              type = "DF";
493
213
              file->type = SC_FILE_TYPE_DF;
494
213
              break;
495
733
            default:
496
733
              file->type = SC_FILE_TYPE_UNKNOWN;
497
733
              type = "unknown";
498
733
              break;
499
3.36k
          }
500
3.36k
          sc_log(ctx, "  type: %s", type);
501
3.36k
          sc_log(ctx, "  EF structure: %d", byte & 0x07);
502
3.36k
          sc_log(ctx, "  tag 0x82: 0x%02x", byte);
503
504
          /* if possible, get additional information for non-DFs */
505
3.36k
          if (file->type != SC_FILE_TYPE_DF) {
506
            /* max. record length for fixed- & variable-sized records */
507
3.14k
            if (length > 2 && byte & 0x06) {
508
392
              file->record_length = (length > 3)
509
392
                ? bebytes2ushort(p+2)
510
392
                : p[2];
511
392
              sc_log(ctx, "  record length: %"SC_FORMAT_LEN_SIZE_T"u",
512
392
                file->record_length);
513
392
            }
514
515
            /* number of records */
516
3.14k
            if (length > 4) {
517
269
              file->record_count = (length > 5)
518
269
                ? bebytes2ushort(p+4)
519
269
                : p[4];
520
269
              sc_log(ctx, "  records: %"SC_FORMAT_LEN_SIZE_T"u",
521
269
                file->record_count);
522
269
            }
523
3.14k
          }
524
525
3.36k
          if (SC_SUCCESS != sc_file_set_type_attr(file, p, length))
526
0
            sc_log(ctx, "Warning: Could not set file attributes");
527
3.36k
        }
528
3.46k
        break;
529
530
3.46k
      case 0x83:
531
2.64k
        if (length == 2) {
532
2.23k
          file->id = (p[0] << 8) | p[1];
533
2.23k
          sc_log(ctx, "  file identifier: 0x%02X%02X", p[0], p[1]);
534
2.23k
        }
535
2.64k
        break;
536
537
357
      case 0x84:
538
357
        if (length > 0 && length <= 16) {
539
263
          memcpy(file->name, p, length);
540
263
          file->namelen = length;
541
542
263
          sc_log_hex(ctx, "  File name:", file->name, file->namelen);
543
263
          if (!file->type)
544
106
            file->type = SC_FILE_TYPE_DF;
545
263
        }
546
357
        break;
547
548
503
      case 0x85:
549
1.21k
      case 0xA5:
550
1.21k
        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.21k
        break;
554
555
970
      case 0x86:
556
970
        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
970
        break;
560
561
526
      case 0x88:
562
526
        if (length == 1) {
563
71
          file->sid = *p;
564
71
          sc_log(ctx, "  short file identifier: 0x%02X", *p);
565
71
        }
566
526
        break;
567
568
2.20k
      case 0x8A:
569
2.20k
        if (length == 1) {
570
2.04k
          switch (p[0]) {
571
68
            case 0:
572
68
              file->status =SC_FILE_STATUS_NO_INFO;
573
68
              break;
574
106
            case 1:
575
106
              file->status = SC_FILE_STATUS_CREATION;
576
106
              break;
577
67
            case 3:
578
67
              file->status = SC_FILE_STATUS_INITIALISATION;
579
67
              break;
580
152
            case 4:
581
223
            case 6:
582
223
              file->status = SC_FILE_STATUS_INVALIDATED;
583
223
              break;
584
699
            case 5:
585
767
            case 7:
586
767
              file->status = SC_FILE_STATUS_ACTIVATED;
587
767
              break;
588
67
            case 12:
589
134
            case 13:
590
202
            case 14:
591
269
            case 15:
592
269
              file->status = SC_FILE_STATUS_TERMINATION;
593
269
              break;
594
69
            case 2:
595
69
              file->status = SC_FILE_STATUS_RFU_2;
596
69
              break;
597
66
            case 8:
598
66
              file->status = SC_FILE_STATUS_RFU_8;
599
66
              break;
600
79
            case 9:
601
79
              file->status = SC_FILE_STATUS_RFU_9;
602
79
              break;
603
67
            case 10:
604
67
              file->status = SC_FILE_STATUS_RFU_10;
605
67
              break;
606
75
            case 11:
607
75
              file->status = SC_FILE_STATUS_RFU_11;
608
75
              break;
609
186
            default:
610
186
              file->status = SC_FILE_STATUS_PROPRIETARY;
611
2.04k
          }
612
2.04k
        }
613
2.20k
        break;
614
615
2.20k
      case 0x62:
616
809
      case 0x64:
617
1.24k
      case 0x6F:
618
        /* allow nested FCP/FMD/FCI templates */
619
1.24k
        iso7816_process_fci(card, file, p, length);
620
23.3k
    }
621
23.3k
  }
622
623
9.37k
  file->magic = SC_FILE_MAGIC;
624
625
9.37k
  return SC_SUCCESS;
626
9.37k
}
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
46.4k
{
632
46.4k
  struct sc_context *ctx;
633
46.4k
  struct sc_apdu apdu;
634
46.4k
  unsigned char buf[SC_MAX_APDU_BUFFER_SIZE];
635
46.4k
  unsigned char pathbuf[SC_MAX_PATH_SIZE], *path = pathbuf;
636
46.4k
  int r, pathtype;
637
46.4k
  size_t pathlen;
638
46.4k
  int select_mf = 0;
639
46.4k
  struct sc_file *file = NULL;
640
46.4k
  const u8 *buffer;
641
46.4k
  size_t buffer_len;
642
46.4k
  unsigned int cla, tag;
643
644
46.4k
  if (card == NULL || in_path == NULL) {
645
0
    return SC_ERROR_INVALID_ARGUMENTS;
646
0
  }
647
46.4k
  ctx = card->ctx;
648
46.4k
  memcpy(path, in_path->value, in_path->len);
649
46.4k
  pathlen = in_path->len;
650
46.4k
  pathtype = in_path->type;
651
652
46.4k
  if (in_path->aid.len) {
653
1.75k
    if (!pathlen) {
654
1.43k
      memcpy(path, in_path->aid.value, in_path->aid.len);
655
1.43k
      pathlen = in_path->aid.len;
656
1.43k
      pathtype = SC_PATH_TYPE_DF_NAME;
657
1.43k
    } else {
658
      /* First, select the application */
659
322
      sc_format_apdu(card, &apdu, SC_APDU_CASE_3_SHORT, 0xA4, 4, 0);
660
322
      apdu.data = in_path->aid.value;
661
322
      apdu.datalen = in_path->aid.len;
662
322
      apdu.lc = in_path->aid.len;
663
664
322
      r = sc_transmit_apdu(card, &apdu);
665
322
      LOG_TEST_RET(ctx, r, "APDU transmit failed");
666
319
      r = sc_check_sw(card, apdu.sw1, apdu.sw2);
667
319
      if (r)
668
319
        LOG_FUNC_RETURN(ctx, r);
669
670
92
      if (pathtype == SC_PATH_TYPE_PATH
671
0
          || pathtype == SC_PATH_TYPE_DF_NAME)
672
92
        pathtype = SC_PATH_TYPE_FROM_CURRENT;
673
92
    }
674
1.75k
  }
675
676
46.2k
  sc_format_apdu(card, &apdu, SC_APDU_CASE_4_SHORT, 0xA4, 0, 0);
677
678
46.2k
  switch (pathtype) {
679
7.55k
  case SC_PATH_TYPE_FILE_ID:
680
7.55k
    apdu.p1 = 0;
681
7.55k
    if (pathlen != 2)
682
0
      return SC_ERROR_INVALID_ARGUMENTS;
683
7.55k
    break;
684
20.6k
  case SC_PATH_TYPE_DF_NAME:
685
20.6k
    apdu.p1 = 4;
686
20.6k
    break;
687
17.9k
  case SC_PATH_TYPE_PATH:
688
17.9k
    apdu.p1 = 8;
689
17.9k
    if (pathlen >= 2 && memcmp(path, "\x3F\x00", 2) == 0) {
690
12.6k
      if (pathlen == 2) { /* only 3F00 supplied */
691
3.21k
        select_mf = 1;
692
3.21k
        apdu.p1 = 0;
693
3.21k
        break;
694
3.21k
      }
695
9.45k
      path += 2;
696
9.45k
      pathlen -= 2;
697
9.45k
    }
698
14.6k
    break;
699
14.6k
  case SC_PATH_TYPE_FROM_CURRENT:
700
92
    apdu.p1 = 9;
701
92
    break;
702
79
  case SC_PATH_TYPE_PARENT:
703
79
    apdu.p1 = 3;
704
79
    pathlen = 0;
705
79
    apdu.cse = SC_APDU_CASE_2_SHORT;
706
79
    break;
707
0
  default:
708
0
    LOG_FUNC_RETURN(ctx, SC_ERROR_INVALID_ARGUMENTS);
709
46.2k
  }
710
46.2k
  apdu.lc = pathlen;
711
46.2k
  apdu.data = path;
712
46.2k
  apdu.datalen = pathlen;
713
714
46.2k
  if (file_out != NULL) {
715
29.0k
    apdu.p2 = 0;    /* first record, return FCI */
716
29.0k
    apdu.resp = buf;
717
29.0k
    apdu.resplen = sizeof(buf);
718
29.0k
    apdu.le = sc_get_max_recv_size(card) < 256 ? sc_get_max_recv_size(card) : 256;
719
29.0k
  }
720
17.2k
  else {
721
17.2k
    apdu.p2 = 0x0C;   /* first record, return nothing */
722
17.2k
    apdu.cse = (apdu.lc == 0) ? SC_APDU_CASE_1 : SC_APDU_CASE_3_SHORT;
723
17.2k
  }
724
725
46.2k
  r = sc_transmit_apdu(card, &apdu);
726
46.2k
  LOG_TEST_RET(ctx, r, "APDU transmit failed");
727
45.7k
  if (file_out == NULL) {
728
    /* For some cards 'SELECT' can be only with request to return FCI/FCP. */
729
17.2k
    r = sc_check_sw(card, apdu.sw1, apdu.sw2);
730
17.2k
    if (apdu.sw1 == 0x6A && apdu.sw2 == 0x86)   {
731
16
      apdu.p2 = 0x00;
732
16
      if (sc_transmit_apdu(card, &apdu) == SC_SUCCESS)
733
13
        r = sc_check_sw(card, apdu.sw1, apdu.sw2);
734
16
    }
735
17.2k
    if (apdu.sw1 == 0x61)
736
17.2k
      LOG_FUNC_RETURN(ctx, SC_SUCCESS);
737
17.2k
    LOG_FUNC_RETURN(ctx, r);
738
17.2k
  }
739
740
28.5k
  r = sc_check_sw(card, apdu.sw1, apdu.sw2);
741
28.5k
  if (r)
742
28.5k
    LOG_FUNC_RETURN(ctx, r);
743
744
12.0k
  if (file_out && (apdu.resplen == 0))   {
745
    /* For some cards 'SELECT' MF or DF_NAME do not return FCI. */
746
2.42k
    if (select_mf || pathtype == SC_PATH_TYPE_DF_NAME)   {
747
1.97k
      file = sc_file_new();
748
1.97k
      if (file == NULL)
749
1.97k
        LOG_FUNC_RETURN(ctx, SC_ERROR_OUT_OF_MEMORY);
750
1.97k
      file->path = *in_path;
751
752
1.97k
      *file_out = file;
753
1.97k
      LOG_FUNC_RETURN(ctx, SC_SUCCESS);
754
1.97k
    }
755
2.42k
  }
756
757
10.1k
  if (apdu.resplen < 2)
758
10.1k
    LOG_FUNC_RETURN(ctx, SC_ERROR_UNKNOWN_DATA_RECEIVED);
759
9.65k
  switch (apdu.resp[0]) {
760
8.75k
  case ISO7816_TAG_FCI:
761
9.24k
  case ISO7816_TAG_FCP:
762
9.24k
    file = sc_file_new();
763
9.24k
    if (file == NULL)
764
9.24k
      LOG_FUNC_RETURN(ctx, SC_ERROR_OUT_OF_MEMORY);
765
9.24k
    file->path = *in_path;
766
9.24k
    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
9.24k
    buffer = apdu.resp;
771
9.24k
    r = sc_asn1_read_tag(&buffer, apdu.resplen, &cla, &tag, &buffer_len);
772
9.24k
    if (r == SC_SUCCESS)
773
8.32k
      card->ops->process_fci(card, file, buffer, buffer_len);
774
9.24k
    *file_out = file;
775
9.24k
    break;
776
98
  case 0x00: /* proprietary coding */
777
98
    LOG_FUNC_RETURN(ctx, SC_ERROR_UNKNOWN_DATA_RECEIVED);
778
303
  default:
779
303
    LOG_FUNC_RETURN(ctx, SC_ERROR_UNKNOWN_DATA_RECEIVED);
780
9.65k
  }
781
782
9.24k
  return SC_SUCCESS;
783
9.65k
}
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
24.5k
{
904
24.5k
  struct sc_apdu apdu = {0};
905
24.5k
  int r;
906
24.5k
  size_t rlen;
907
908
  /* request at most max_recv_size bytes */
909
24.5k
  if (*count > sc_get_max_recv_size(card))
910
1.02k
    rlen = sc_get_max_recv_size(card);
911
23.5k
  else
912
23.5k
    rlen = *count;
913
914
24.5k
  sc_format_apdu(card, &apdu, SC_APDU_CASE_2, 0xC0, 0x00, 0x00);
915
24.5k
  apdu.le      = rlen;
916
24.5k
  apdu.resplen = rlen;
917
24.5k
  apdu.resp    = buf;
918
  /* don't call GET RESPONSE recursively */
919
24.5k
  apdu.flags  |= SC_APDU_FLAGS_NO_GET_RESP;
920
921
24.5k
  r = sc_transmit_apdu(card, &apdu);
922
24.5k
  LOG_TEST_RET(card->ctx, r, "APDU transmit failed");
923
924
24.1k
  *count = apdu.resplen;
925
926
24.1k
  if (apdu.resplen == 0) {
927
5.84k
    LOG_FUNC_RETURN(card->ctx, sc_check_sw(card, apdu.sw1, apdu.sw2));
928
5.84k
  }
929
18.3k
  if (apdu.sw1 == 0x90 && apdu.sw2 == 0x00)
930
7.22k
    r = 0;          /* no more data to read */
931
11.0k
  else if (apdu.sw1 == 0x61)
932
6.21k
    r = apdu.sw2 == 0 ? 256 : apdu.sw2;  /* more data to read    */
933
4.86k
  else if (apdu.sw1 == 0x62 && apdu.sw2 == 0x82)
934
2.80k
    r = 0; /* Le not reached but file/record ended */
935
2.06k
  else
936
2.06k
    r = sc_check_sw(card, apdu.sw1, apdu.sw2);
937
938
18.3k
  return r;
939
24.1k
}
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
170
{
981
170
  struct sc_apdu apdu;
982
170
  u8 sbuf[SC_MAX_APDU_BUFFER_SIZE];
983
170
  u8 *p;
984
170
  int r, locked = 0;
985
986
170
  if (card == NULL || env == NULL) {
987
0
    return SC_ERROR_INVALID_ARGUMENTS;
988
0
  }
989
170
  sc_format_apdu(card, &apdu, SC_APDU_CASE_3_SHORT, 0x22, 0x41, 0);
990
170
  switch (env->operation) {
991
100
  case SC_SEC_OPERATION_DECIPHER:
992
100
  case SC_SEC_OPERATION_DERIVE:
993
100
    apdu.p2 = 0xB8;
994
100
    break;
995
70
  case SC_SEC_OPERATION_SIGN:
996
70
    apdu.p2 = 0xB6;
997
70
    break;
998
0
  default:
999
0
    return SC_ERROR_INVALID_ARGUMENTS;
1000
170
  }
1001
170
  p = sbuf;
1002
170
  if (env->flags & SC_SEC_ENV_ALG_REF_PRESENT) {
1003
149
    *p++ = 0x80;  /* algorithm reference */
1004
149
    *p++ = 0x01;
1005
149
    *p++ = env->algorithm_ref & 0xFF;
1006
149
  }
1007
170
  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
170
  if (env->flags & SC_SEC_ENV_KEY_REF_PRESENT) {
1019
170
    if (sizeof(sbuf) - (p - sbuf) < env->key_ref_len + 2)
1020
0
      return SC_ERROR_OFFSET_TOO_LARGE;
1021
1022
170
    if (env->flags & SC_SEC_ENV_KEY_REF_SYMMETRIC)
1023
0
      *p++ = 0x83;
1024
170
    else
1025
170
      *p++ = 0x84;
1026
170
    if (env->key_ref_len > SC_MAX_KEYREF_SIZE)
1027
0
      return SC_ERROR_INVALID_ARGUMENTS;
1028
170
    *p++ = env->key_ref_len & 0xFF;
1029
170
    memcpy(p, env->key_ref, env->key_ref_len);
1030
170
    p += env->key_ref_len;
1031
170
  }
1032
170
  r = (int)(p - sbuf);
1033
170
  apdu.lc = r;
1034
170
  apdu.datalen = r;
1035
170
  apdu.data = sbuf;
1036
170
  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
170
  if (apdu.datalen != 0) {
1042
170
    r = sc_transmit_apdu(card, &apdu);
1043
170
    if (r) {
1044
0
      sc_log(card->ctx, "%s: APDU transmit failed", sc_strerror(r));
1045
0
      goto err;
1046
0
    }
1047
170
    r = sc_check_sw(card, apdu.sw1, apdu.sw2);
1048
170
    if (r) {
1049
58
      sc_log(card->ctx, "%s: Card returned error", sc_strerror(r));
1050
58
      goto err;
1051
58
    }
1052
170
  }
1053
112
  if (se_num <= 0) {
1054
112
    r = SC_SUCCESS;
1055
112
    goto err;
1056
112
  }
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
170
err:
1064
170
  if (locked)
1065
0
    sc_unlock(card);
1066
170
  return r;
1067
0
}
1068
1069
1070
static int
1071
iso7816_restore_security_env(struct sc_card *card, int se_num)
1072
0
{
1073
0
  struct sc_apdu apdu;
1074
0
  int r;
1075
1076
0
  if (card == NULL) {
1077
0
    return SC_ERROR_INVALID_ARGUMENTS;
1078
0
  }
1079
1080
0
  sc_format_apdu(card, &apdu, SC_APDU_CASE_1, 0x22, 0xF3, se_num);
1081
1082
0
  r = sc_transmit_apdu(card, &apdu);
1083
0
  LOG_TEST_RET(card->ctx, r, "APDU transmit failed");
1084
0
  r = sc_check_sw(card, apdu.sw1, apdu.sw2);
1085
0
  LOG_TEST_RET(card->ctx, r, "Card returned error");
1086
1087
0
  return r;
1088
0
}
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
8
{
1096
8
  int r;
1097
8
  struct sc_apdu apdu;
1098
1099
8
  if (card == NULL || data == NULL || out == NULL) {
1100
0
    return SC_ERROR_INVALID_ARGUMENTS;
1101
0
  }
1102
8
  LOG_FUNC_CALLED(card->ctx);
1103
8
  sc_log(card->ctx,
1104
8
         "ISO7816 compute signature: in-len %"SC_FORMAT_LEN_SIZE_T"u, out-len %"SC_FORMAT_LEN_SIZE_T"u",
1105
8
         datalen, outlen);
1106
1107
  /* INS: 0x2A  PERFORM SECURITY OPERATION
1108
   * P1:  0x9E  Resp: Digital Signature
1109
   * P2:  0x9A  Cmd: Input for Digital Signature */
1110
8
  sc_format_apdu(card, &apdu, SC_APDU_CASE_4, 0x2A, 0x9E, 0x9A);
1111
8
  apdu.resp = out;
1112
8
  apdu.resplen = outlen;
1113
8
  apdu.le = outlen;
1114
1115
8
  apdu.data = data;
1116
8
  apdu.lc = datalen;
1117
8
  apdu.datalen = datalen;
1118
1119
8
  iso7816_fixup_transceive_length(card, &apdu);
1120
8
  r = sc_transmit_apdu(card, &apdu);
1121
8
  LOG_TEST_RET(card->ctx, r, "APDU transmit failed");
1122
6
  if (apdu.sw1 == 0x90 && apdu.sw2 == 0x00)
1123
6
    LOG_FUNC_RETURN(card->ctx, (int)apdu.resplen);
1124
1125
4
  r = sc_check_sw(card, apdu.sw1, apdu.sw2);
1126
4
  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
38
{
1137
38
  int r;
1138
38
  struct sc_apdu apdu;
1139
38
  u8 *sbuf = NULL;
1140
1141
38
  if (card == NULL || crgram == NULL || out == NULL) {
1142
0
    return SC_ERROR_INVALID_ARGUMENTS;
1143
0
  }
1144
38
  LOG_FUNC_CALLED(card->ctx);
1145
38
  sc_log(card->ctx,
1146
38
         "ISO7816 decipher: in-len %"SC_FORMAT_LEN_SIZE_T"u, out-len %"SC_FORMAT_LEN_SIZE_T"u",
1147
38
         crgram_len, outlen);
1148
1149
38
  sbuf = malloc(crgram_len + 1);
1150
38
  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
38
  sc_format_apdu(card, &apdu, SC_APDU_CASE_4, 0x2A, 0x80, 0x86);
1157
38
  apdu.resp    = out;
1158
38
  apdu.resplen = outlen;
1159
38
  apdu.le      = outlen;
1160
1161
38
  sbuf[0] = 0; /* padding indicator byte, 0x00 = No further indication */
1162
38
  memcpy(sbuf + 1, crgram, crgram_len);
1163
38
  apdu.data = sbuf;
1164
38
  apdu.lc = crgram_len + 1;
1165
38
  apdu.datalen = crgram_len + 1;
1166
1167
38
  iso7816_fixup_transceive_length(card, &apdu);
1168
38
  r = sc_transmit_apdu(card, &apdu);
1169
38
  sc_mem_clear(sbuf, crgram_len + 1);
1170
38
  free(sbuf);
1171
38
  LOG_TEST_RET(card->ctx, r, "APDU transmit failed");
1172
1173
37
  if (apdu.sw1 == 0x90 && apdu.sw2 == 0x00)
1174
37
    LOG_FUNC_RETURN(card->ctx, (int)apdu.resplen);
1175
12
  else
1176
37
    LOG_FUNC_RETURN(card->ctx, sc_check_sw(card, apdu.sw1, apdu.sw2));
1177
37
}
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
929
{
1184
929
  int r, len = 0, pad = 0, use_pin_pad = 0, ins, p1 = 0;
1185
929
  int cse = SC_APDU_CASE_3_SHORT;
1186
1187
929
  switch (data->pin_type) {
1188
877
  case SC_AC_CHV:
1189
    /* fall through */
1190
879
  case SC_AC_SESSION:
1191
907
  case SC_AC_CONTEXT_SPECIFIC:
1192
907
    break;
1193
22
  default:
1194
22
    return SC_ERROR_INVALID_ARGUMENTS;
1195
929
  }
1196
1197
907
  if (data->flags & SC_PIN_CMD_NEED_PADDING)
1198
203
    pad = 1;
1199
907
  if (data->flags & SC_PIN_CMD_USE_PINPAD)
1200
0
    use_pin_pad = 1;
1201
1202
907
  data->pin1.offset = 5;
1203
1204
907
  switch (data->cmd) {
1205
201
  case SC_PIN_CMD_VERIFY:
1206
201
    ins = 0x20;
1207
    /* detect overloaded APDU with SC_PIN_CMD_GET_INFO */
1208
201
    if (data->pin1.len == 0 && !use_pin_pad)
1209
0
      return SC_ERROR_INVALID_PIN_LENGTH;
1210
201
    if ((r = sc_build_pin(buf, buf_len, &data->pin1, pad)) < 0)
1211
10
      return r;
1212
191
    len = r;
1213
191
    break;
1214
0
  case SC_PIN_CMD_CHANGE:
1215
0
    ins = 0x24;
1216
0
    if (data->pin1.len != 0 || (use_pin_pad && !( data->flags & SC_PIN_CMD_IMPLICIT_CHANGE))) {
1217
0
      if ((r = sc_build_pin(buf, buf_len, &data->pin1, pad)) < 0)
1218
0
        return r;
1219
0
      len += r;
1220
0
    }
1221
0
    else {
1222
      /* implicit test */
1223
0
      p1 = 1;
1224
0
    }
1225
1226
0
    data->pin2.offset = data->pin1.offset + len;
1227
0
    if ((r = sc_build_pin(buf+len, buf_len-len, &data->pin2, pad)) < 0)
1228
0
      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
0
    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
0
    len += r;
1237
0
    break;
1238
0
  case SC_PIN_CMD_UNBLOCK:
1239
0
    ins = 0x2C;
1240
0
    if (data->pin1.len != 0 || (use_pin_pad && !( data->flags & SC_PIN_CMD_IMPLICIT_CHANGE))) {
1241
0
      if ((r = sc_build_pin(buf, buf_len, &data->pin1, pad)) < 0)
1242
0
        return r;
1243
0
      len += r;
1244
0
    } else {
1245
0
      p1 |= 0x02;
1246
0
    }
1247
1248
0
    if (data->pin2.len != 0 || use_pin_pad) {
1249
0
      data->pin2.offset = data->pin1.offset + len;
1250
0
      if ((r = sc_build_pin(buf+len, buf_len-len, &data->pin2, pad)) < 0)
1251
0
        return r;
1252
0
      len += r;
1253
0
    } else {
1254
0
      p1 |= 0x01;
1255
0
    }
1256
0
    if (p1 == 0x03) {
1257
      /* No data to send or to receive */
1258
0
      cse = SC_APDU_CASE_1;
1259
0
    }
1260
0
    break;
1261
706
  case SC_PIN_CMD_GET_INFO:
1262
706
    ins = 0x20;
1263
    /* No data to send or to receive */
1264
706
    cse = SC_APDU_CASE_1;
1265
706
    break;
1266
0
  default:
1267
0
    return SC_ERROR_NOT_SUPPORTED;
1268
907
  }
1269
1270
897
  sc_format_apdu(card, apdu, cse, ins, p1, data->pin_reference);
1271
897
  apdu->lc = len;
1272
897
  apdu->datalen = len;
1273
897
  apdu->data = buf;
1274
897
  apdu->resplen = 0;
1275
1276
897
  return 0;
1277
907
}
1278
1279
1280
static int
1281
iso7816_pin_cmd(struct sc_card *card, struct sc_pin_cmd_data *data, int *tries_left)
1282
1.06k
{
1283
1.06k
  struct sc_apdu local_apdu, *apdu;
1284
1.06k
  int r;
1285
1.06k
  u8  sbuf[SC_MAX_APDU_BUFFER_SIZE];
1286
1287
1.06k
  data->pin1.tries_left = -1;
1288
1.06k
  if (tries_left != NULL) {
1289
201
    *tries_left = data->pin1.tries_left;
1290
201
  }
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
1.06k
  if (data->cmd == SC_PIN_CMD_GET_INFO &&
1297
866
      !(card->caps & SC_CARD_CAP_ISO7816_PIN_INFO)) {
1298
138
    sc_log(card->ctx, "Card does not support PIN status queries");
1299
138
    return SC_ERROR_NOT_SUPPORTED;
1300
138
  }
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
929
  if (data->apdu == NULL) {
1308
929
    r = iso7816_build_pin_apdu(card, &local_apdu, data, sbuf, sizeof(sbuf));
1309
929
    if (r < 0)
1310
32
      return r;
1311
897
    data->apdu = &local_apdu;
1312
897
  }
1313
897
  apdu = data->apdu;
1314
1315
897
  if (!(data->flags & SC_PIN_CMD_USE_PINPAD) || data->cmd == SC_PIN_CMD_GET_INFO) {
1316
    /* Transmit the APDU to the card */
1317
897
    r = sc_transmit_apdu(card, apdu);
1318
1319
    /* Clear the buffer - it may contain pins */
1320
897
    sc_mem_clear(sbuf, sizeof(sbuf));
1321
897
  }
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
897
  if (data->apdu == &local_apdu)
1342
897
    data->apdu = NULL;
1343
1344
897
  LOG_TEST_RET(card->ctx, r, "APDU transmit failed");
1345
896
  r = sc_check_sw(card, apdu->sw1, apdu->sw2);
1346
1347
896
  if (r == SC_SUCCESS) {
1348
767
    data->pin1.logged_in = SC_PIN_STATE_LOGGED_IN;
1349
767
  } else if (r == SC_ERROR_PIN_CODE_INCORRECT) {
1350
2
    data->pin1.tries_left = apdu->sw2 & 0xF;
1351
2
    data->pin1.logged_in = SC_PIN_STATE_LOGGED_OUT;
1352
2
    if (data->cmd == SC_PIN_CMD_GET_INFO)
1353
1
      r = SC_SUCCESS;
1354
127
  } else if (r == SC_ERROR_AUTH_METHOD_BLOCKED) {
1355
1
    data->pin1.tries_left = 0;
1356
1
    data->pin1.logged_in = SC_PIN_STATE_LOGGED_OUT;
1357
1
    if (data->cmd == SC_PIN_CMD_GET_INFO)
1358
1
      r = SC_SUCCESS;
1359
1
  }
1360
896
  if (tries_left != NULL) {
1361
191
    *tries_left = data->pin1.tries_left;
1362
191
  }
1363
1364
896
  return r;
1365
897
}
1366
1367
1368
static int iso7816_get_data(struct sc_card *card, unsigned int tag,  u8 *buf, size_t len)
1369
239
{
1370
239
  int                             r, cse;
1371
239
  struct sc_apdu                  apdu;
1372
1373
239
  SC_FUNC_CALLED(card->ctx, SC_LOG_DEBUG_VERBOSE);
1374
1375
239
  if (buf && len)
1376
239
    cse = SC_APDU_CASE_2;
1377
0
  else
1378
0
    cse = SC_APDU_CASE_1;
1379
1380
239
  sc_format_apdu(card, &apdu, cse, 0xCA, (tag >> 8) & 0xff, tag & 0xff);
1381
239
  apdu.le = len;
1382
239
  apdu.resp = buf;
1383
239
  apdu.resplen = len;
1384
239
  r = sc_transmit_apdu(card, &apdu);
1385
239
  LOG_TEST_RET(card->ctx, r, "APDU transmit failed");
1386
1387
229
  r = sc_check_sw(card, apdu.sw1, apdu.sw2);
1388
229
  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
12.6k
{
1402
12.6k
  struct sc_context *ctx = card->ctx;
1403
12.6k
  struct sc_apdu apdu;
1404
12.6k
  int rv;
1405
1406
12.6k
  SC_FUNC_CALLED(ctx, SC_LOG_DEBUG_VERBOSE);
1407
1408
12.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
12.6k
  apdu.lc = reqlen;
1410
12.6k
  apdu.data = req;
1411
12.6k
  apdu.datalen = reqlen;
1412
12.6k
  apdu.resp = resp;
1413
12.6k
  apdu.resplen = resp == NULL ? 0 : *resplen;
1414
12.6k
  apdu.le = resp == NULL ? 0 : 256;
1415
1416
12.6k
  rv = sc_transmit_apdu(card, &apdu);
1417
12.6k
  if (resplen)
1418
6.36k
    *resplen = apdu.resplen;
1419
12.6k
  LOG_TEST_RET(card->ctx, rv, "APDU transmit failed");
1420
1421
12.5k
  rv = sc_check_sw(card, apdu.sw1, apdu.sw2);
1422
12.5k
  LOG_FUNC_RETURN(ctx, rv);
1423
12.5k
}
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
444k
{
1492
444k
  return &iso_driver;
1493
444k
}
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
}