Coverage Report

Created: 2026-06-10 06:48

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
16.8k
{
37
16.8k
  if (card == NULL || apdu == NULL) {
38
0
    return;
39
0
  }
40
41
16.8k
  if (apdu->lc > sc_get_max_send_size(card)) {
42
    /* The lower layers will automatically do chaining */
43
126
    apdu->flags |= SC_APDU_FLAGS_CHAINING;
44
126
  }
45
46
16.8k
  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
692
    apdu->le = sc_get_max_recv_size(card);
50
692
  }
51
16.8k
}
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
1.08M
{
112
1.08M
  const int err_count = sizeof(iso7816_errors)/sizeof(iso7816_errors[0]);
113
1.08M
  int i;
114
115
  /* Handle special cases here */
116
1.08M
  if (sw1 == 0x6C) {
117
745
    sc_log(card->ctx, "Wrong length; correct length is %d", sw2);
118
745
    return SC_ERROR_WRONG_LENGTH;
119
745
  }
120
1.08M
  if (sw1 == 0x90 && sw2 == 0x00)
121
222k
    return SC_SUCCESS;
122
863k
  if (sw1 == 0x63U && (sw2 & ~0x0fU) == 0xc0U) {
123
80
    sc_log(card->ctx, "PIN not verified (remaining tries: %d)", (sw2 & 0x0f));
124
80
    return SC_ERROR_PIN_CODE_INCORRECT;
125
80
  }
126
35.6M
  for (i = 0; i < err_count; i++)   {
127
35.5M
    if (iso7816_errors[i].SWs == ((sw1 << 8) | sw2)) {
128
755k
      sc_log(card->ctx, "%s", iso7816_errors[i].errorstr);
129
755k
      return iso7816_errors[i].errorno;
130
755k
    }
131
35.5M
  }
132
133
107k
  sc_log(card->ctx, "Unknown SWs; SW1=%02X, SW2=%02X", sw1, sw2);
134
107k
  return SC_ERROR_CARD_CMD_FAILED;
135
863k
}
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
3.36k
{
141
3.36k
  struct sc_context *ctx = card->ctx;
142
3.36k
  struct sc_apdu apdu;
143
3.36k
  int r;
144
145
3.36k
  if (idx > 0x7FFF) {
146
1
    sc_log(ctx, "invalid EF offset: 0x%X > 0x7FFF", idx);
147
1
    return SC_ERROR_OFFSET_TOO_LARGE;
148
1
  }
149
150
3.36k
  sc_format_apdu(card, &apdu, SC_APDU_CASE_2, 0xB0, (idx >> 8) & 0x7F, idx & 0xFF);
151
3.36k
  apdu.le = count;
152
3.36k
  apdu.resplen = count;
153
3.36k
  apdu.resp = buf;
154
155
3.36k
  iso7816_fixup_transceive_length(card, &apdu);
156
3.36k
  r = sc_transmit_apdu(card, &apdu);
157
3.36k
  LOG_TEST_RET(ctx, r, "APDU transmit failed");
158
159
3.35k
  r = sc_check_sw(card, apdu.sw1, apdu.sw2);
160
3.35k
  if (r == SC_ERROR_FILE_END_REACHED || r == SC_ERROR_INCORRECT_PARAMETERS)
161
3.35k
    LOG_FUNC_RETURN(ctx, (int)apdu.resplen);
162
3.14k
  LOG_TEST_RET(ctx, r, "Check SW error");
163
164
2.77k
  LOG_FUNC_RETURN(ctx, (int)apdu.resplen);
165
2.77k
}
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
4.39k
{
178
4.39k
  unsigned char offset_buffer[2];
179
4.39k
  size_t offset_buffer_len = sizeof offset_buffer;
180
4.39k
  struct sc_asn1_entry asn1_do_data[sizeof c_asn1_do_data / sizeof *c_asn1_do_data];
181
4.39k
  sc_copy_asn1_entry(c_asn1_do_data, asn1_do_data);
182
183
4.39k
  if (idx > 0xFFFF)
184
4.39k
    LOG_TEST_RET(ctx, SC_ERROR_INTERNAL, "Offset beyond 0xFFFF not supported");
185
4.39k
  offset_buffer[0] = (u8) (idx >> 8);
186
4.39k
  offset_buffer[1] = (u8) (idx & 0x00FF);
187
4.39k
  sc_format_asn1_entry(asn1_do_data + 0, offset_buffer, &offset_buffer_len, 1);
188
189
4.39k
  if (data && data_len) {
190
0
    sc_format_asn1_entry(asn1_do_data + 1, (void *) &data, &data_len, 1);
191
4.39k
  } else {
192
4.39k
    sc_format_asn1_entry(asn1_do_data + 1, NULL, NULL, 0);
193
4.39k
  }
194
195
4.39k
  LOG_TEST_RET(ctx,
196
4.39k
      sc_asn1_encode(ctx, asn1_do_data, out, outlen),
197
4.39k
      "sc_asn1_encode() failed");
198
199
4.39k
  return SC_SUCCESS;
200
4.39k
}
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
2.67k
{
206
2.67k
  struct sc_asn1_entry asn1_do_data[sizeof c_asn1_do_data / sizeof *c_asn1_do_data];
207
2.67k
  sc_copy_asn1_entry(c_asn1_do_data, asn1_do_data);
208
209
2.67k
  sc_format_asn1_entry(asn1_do_data + 0, NULL, NULL, 0);
210
2.67k
  sc_format_asn1_entry(asn1_do_data + 1, out, outlen, 0);
211
212
2.67k
  LOG_TEST_RET(ctx,
213
2.45k
      sc_asn1_decode(ctx, asn1_do_data, encoded_data, encoded_data_len, NULL, NULL),
214
2.45k
      "sc_asn1_decode() failed");
215
216
2.45k
  if (!(asn1_do_data[1].flags & SC_ASN1_PRESENT))
217
1.06k
    return SC_ERROR_INVALID_ASN1_OBJECT;
218
219
1.38k
  return SC_SUCCESS;
220
2.45k
}
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
7.93k
{
226
7.93k
  struct sc_apdu apdu;
227
7.93k
  int r;
228
  /* XXX maybe use some bigger buffer */
229
7.93k
  unsigned char resp[SC_MAX_APDU_RESP_SIZE];
230
7.93k
  unsigned char *encoded_data = NULL, *decoded_data = NULL;
231
7.93k
  size_t encoded_data_len = 0, decoded_data_len = 0;
232
233
7.93k
  if (rec_nr > 0xFF)
234
7.93k
    LOG_FUNC_RETURN(card->ctx, SC_ERROR_INVALID_ARGUMENTS);
235
236
7.92k
  if (idx == 0) {
237
3.53k
    sc_format_apdu(card, &apdu, SC_APDU_CASE_2, 0xB2, rec_nr, 0);
238
3.53k
    apdu.le = count;
239
3.53k
    apdu.resplen = count;
240
3.53k
    apdu.resp = buf;
241
4.39k
  } else {
242
4.39k
    r = encode_do_data(card->ctx, idx, NULL, 0, &encoded_data, &encoded_data_len);
243
4.39k
    LOG_TEST_GOTO_ERR(card->ctx, r, "Could not encode data objects");
244
245
4.39k
    sc_format_apdu(card, &apdu, SC_APDU_CASE_4, 0xB3, rec_nr, 0);
246
4.39k
    apdu.lc = encoded_data_len;
247
4.39k
    apdu.datalen = encoded_data_len;
248
4.39k
    apdu.data = encoded_data;
249
4.39k
    apdu.le = sizeof resp;
250
4.39k
    apdu.resplen = sizeof resp;
251
4.39k
    apdu.resp = resp;
252
4.39k
  }
253
7.92k
  apdu.p2 = (flags & SC_RECORD_EF_ID_MASK) << 3;
254
7.92k
  if (flags & SC_RECORD_BY_REC_NR)
255
7.92k
    apdu.p2 |= 0x04;
256
257
7.92k
  iso7816_fixup_transceive_length(card, &apdu);
258
7.92k
  r = sc_transmit_apdu(card, &apdu);
259
7.92k
  LOG_TEST_GOTO_ERR(card->ctx, r, "APDU transmit failed");
260
7.61k
  r = sc_check_sw(card, apdu.sw1, apdu.sw2);
261
7.61k
  LOG_TEST_GOTO_ERR(card->ctx, r, "Card returned error");
262
263
6.04k
  if (idx == 0) {
264
3.37k
    r = (int)apdu.resplen;
265
3.37k
  } else {
266
2.67k
    r = decode_do_data(card->ctx, apdu.resp, apdu.resplen,
267
2.67k
        &decoded_data, &decoded_data_len);
268
2.67k
    LOG_TEST_GOTO_ERR(card->ctx, r, "Could not decode data objects");
269
1.38k
    if (decoded_data_len <= count) {
270
1.34k
      count = decoded_data_len;
271
1.34k
    }
272
1.38k
    memcpy(buf, decoded_data, count);
273
1.38k
    r = (int)count;
274
1.38k
  }
275
276
7.92k
err:
277
7.92k
  free(encoded_data);
278
7.92k
  free(decoded_data);
279
7.92k
  LOG_FUNC_RETURN(card->ctx, r);
280
7.92k
}
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
4.16k
{
312
4.16k
  struct sc_apdu apdu;
313
4.16k
  int r;
314
315
4.16k
  sc_format_apdu(card, &apdu, SC_APDU_CASE_3, 0xE2, 0, 0);
316
4.16k
  apdu.lc = count;
317
4.16k
  apdu.datalen = count;
318
4.16k
  apdu.data = buf;
319
4.16k
  apdu.p2 = (flags & SC_RECORD_EF_ID_MASK) << 3;
320
321
4.16k
  iso7816_fixup_transceive_length(card, &apdu);
322
4.16k
  r = sc_transmit_apdu(card, &apdu);
323
4.16k
  LOG_TEST_RET(card->ctx, r, "APDU transmit failed");
324
537
  r = sc_check_sw(card, apdu.sw1, apdu.sw2);
325
537
  LOG_TEST_RET(card->ctx, r, "Card returned error");
326
327
56
  LOG_FUNC_RETURN(card->ctx, (int)count);
328
56
}
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
1.37k
{
377
1.37k
  struct sc_apdu apdu;
378
1.37k
  int r;
379
380
1.37k
  if (idx > 0x7fff) {
381
1
    sc_log(card->ctx, "invalid EF offset: 0x%X > 0x7FFF", idx);
382
1
    return SC_ERROR_OFFSET_TOO_LARGE;
383
1
  }
384
385
1.37k
  sc_format_apdu(card, &apdu, SC_APDU_CASE_3, 0xD0,
386
1.37k
           (idx >> 8) & 0x7F, idx & 0xFF);
387
1.37k
  apdu.lc = count;
388
1.37k
  apdu.datalen = count;
389
1.37k
  apdu.data = buf;
390
391
1.37k
  iso7816_fixup_transceive_length(card, &apdu);
392
1.37k
  r = sc_transmit_apdu(card, &apdu);
393
1.37k
  LOG_TEST_RET(card->ctx, r, "APDU transmit failed");
394
1.37k
  r = sc_check_sw(card, apdu.sw1, apdu.sw2);
395
1.37k
  LOG_TEST_RET(card->ctx, r, "Card returned error");
396
397
1.12k
  LOG_FUNC_RETURN(card->ctx, (int)count);
398
1.12k
}
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
2.33k
{
432
2.33k
  struct sc_context *ctx = card->ctx;
433
2.33k
  const unsigned char *p, *end;
434
2.33k
  unsigned int cla = 0, tag = 0;
435
2.33k
  size_t length;
436
437
2.33k
  file->status = SC_FILE_STATUS_UNKNOWN;
438
439
2.33k
  for (p = buf, length = buflen, end = buf + buflen;
440
7.48k
      p < end;
441
6.74k
      p += length, length = end - p) {
442
443
6.74k
    if (SC_SUCCESS != sc_asn1_read_tag(&p, length, &cla, &tag, &length)
444
5.80k
        || p == NULL) {
445
1.58k
      break;
446
1.58k
    }
447
5.15k
    switch (cla | tag) {
448
415
      case 0x81:
449
415
        if (file->size != 0) {
450
          /* don't overwrite existing file size excluding structural information */
451
85
          break;
452
85
        }
453
        /* fall through */
454
1.59k
      case 0x80:
455
        /* determine the file size */
456
1.59k
        file->size = 0;
457
1.59k
        if (p && length <= sizeof(size_t)) {
458
1.56k
          size_t size = 0, i;
459
4.88k
          for (i = 0; i < length; i++) {
460
3.31k
            size <<= 8;
461
3.31k
            size |= p[i];
462
3.31k
          }
463
1.56k
          if (size > MAX_FILE_SIZE) {
464
388
            file->size = MAX_FILE_SIZE;
465
388
            sc_log(ctx, "  file size truncated, encoded length: %"SC_FORMAT_LEN_SIZE_T"u", size);
466
1.18k
          } else {
467
1.18k
            file->size = size;
468
1.18k
          }
469
1.56k
        }
470
471
1.59k
        sc_log(ctx, "  bytes in file: %"SC_FORMAT_LEN_SIZE_T"u", file->size);
472
1.59k
        break;
473
474
335
      case 0x82:
475
335
        if (length > 0) {
476
286
          unsigned char byte = p[0];
477
286
          const char *type;
478
479
286
          file->shareable = byte & 0x40 ? 1 : 0;
480
286
          sc_log(ctx, "  shareable: %s", (byte & 0x40) ? "yes" : "no");
481
286
          file->ef_structure = byte & 0x07;
482
286
          switch ((byte >> 3) & 7) {
483
109
            case 0:
484
109
              type = "working EF";
485
109
              file->type = SC_FILE_TYPE_WORKING_EF;
486
109
              break;
487
48
            case 1:
488
48
              type = "internal EF";
489
48
              file->type = SC_FILE_TYPE_INTERNAL_EF;
490
48
              break;
491
40
            case 7:
492
40
              type = "DF";
493
40
              file->type = SC_FILE_TYPE_DF;
494
40
              break;
495
89
            default:
496
89
              file->type = SC_FILE_TYPE_UNKNOWN;
497
89
              type = "unknown";
498
89
              break;
499
286
          }
500
286
          sc_log(ctx, "  type: %s", type);
501
286
          sc_log(ctx, "  EF structure: %d", byte & 0x07);
502
286
          sc_log(ctx, "  tag 0x82: 0x%02x", byte);
503
504
          /* if possible, get additional information for non-DFs */
505
286
          if (file->type != SC_FILE_TYPE_DF) {
506
            /* max. record length for fixed- & variable-sized records */
507
246
            if (length > 2 && byte & 0x06) {
508
46
              file->record_length = (length > 3)
509
46
                ? bebytes2ushort(p+2)
510
46
                : p[2];
511
46
              sc_log(ctx, "  record length: %"SC_FORMAT_LEN_SIZE_T"u",
512
46
                file->record_length);
513
46
            }
514
515
            /* number of records */
516
246
            if (length > 4) {
517
41
              file->record_count = (length > 5)
518
41
                ? bebytes2ushort(p+4)
519
41
                : p[4];
520
41
              sc_log(ctx, "  records: %"SC_FORMAT_LEN_SIZE_T"u",
521
41
                file->record_count);
522
41
            }
523
246
          }
524
525
286
          if (SC_SUCCESS != sc_file_set_type_attr(file, p, length))
526
0
            sc_log(ctx, "Warning: Could not set file attributes");
527
286
        }
528
335
        break;
529
530
335
      case 0x83:
531
75
        if (length == 2) {
532
21
          file->id = (p[0] << 8) | p[1];
533
21
          sc_log(ctx, "  file identifier: 0x%02X%02X", p[0], p[1]);
534
21
        }
535
75
        break;
536
537
214
      case 0x84:
538
214
        if (length > 0 && length <= 16) {
539
88
          memcpy(file->name, p, length);
540
88
          file->namelen = length;
541
542
88
          sc_log_hex(ctx, "  File name:", file->name, file->namelen);
543
88
          if (!file->type)
544
37
            file->type = SC_FILE_TYPE_DF;
545
88
        }
546
214
        break;
547
548
214
      case 0x85:
549
285
      case 0xA5:
550
285
        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
285
        break;
554
555
257
      case 0x86:
556
257
        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
257
        break;
560
561
163
      case 0x88:
562
163
        if (length == 1) {
563
44
          file->sid = *p;
564
44
          sc_log(ctx, "  short file identifier: 0x%02X", *p);
565
44
        }
566
163
        break;
567
568
742
      case 0x8A:
569
742
        if (length == 1) {
570
658
          switch (p[0]) {
571
83
            case 0:
572
83
              file->status =SC_FILE_STATUS_NO_INFO;
573
83
              break;
574
44
            case 1:
575
44
              file->status = SC_FILE_STATUS_CREATION;
576
44
              break;
577
16
            case 3:
578
16
              file->status = SC_FILE_STATUS_INITIALISATION;
579
16
              break;
580
34
            case 4:
581
74
            case 6:
582
74
              file->status = SC_FILE_STATUS_INVALIDATED;
583
74
              break;
584
44
            case 5:
585
63
            case 7:
586
63
              file->status = SC_FILE_STATUS_ACTIVATED;
587
63
              break;
588
20
            case 12:
589
42
            case 13:
590
63
            case 14:
591
99
            case 15:
592
99
              file->status = SC_FILE_STATUS_TERMINATION;
593
99
              break;
594
12
            case 2:
595
12
              file->status = SC_FILE_STATUS_RFU_2;
596
12
              break;
597
38
            case 8:
598
38
              file->status = SC_FILE_STATUS_RFU_8;
599
38
              break;
600
21
            case 9:
601
21
              file->status = SC_FILE_STATUS_RFU_9;
602
21
              break;
603
51
            case 10:
604
51
              file->status = SC_FILE_STATUS_RFU_10;
605
51
              break;
606
75
            case 11:
607
75
              file->status = SC_FILE_STATUS_RFU_11;
608
75
              break;
609
82
            default:
610
82
              file->status = SC_FILE_STATUS_PROPRIETARY;
611
658
          }
612
658
        }
613
742
        break;
614
615
742
      case 0x62:
616
276
      case 0x64:
617
470
      case 0x6F:
618
        /* allow nested FCP/FMD/FCI templates */
619
470
        iso7816_process_fci(card, file, p, length);
620
5.15k
    }
621
5.15k
  }
622
623
2.33k
  file->magic = SC_FILE_MAGIC;
624
625
2.33k
  return SC_SUCCESS;
626
2.33k
}
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
15.2k
{
632
15.2k
  struct sc_context *ctx;
633
15.2k
  struct sc_apdu apdu;
634
15.2k
  unsigned char buf[SC_MAX_APDU_BUFFER_SIZE];
635
15.2k
  unsigned char pathbuf[SC_MAX_PATH_SIZE], *path = pathbuf;
636
15.2k
  int r, pathtype;
637
15.2k
  size_t pathlen;
638
15.2k
  int select_mf = 0;
639
15.2k
  struct sc_file *file = NULL;
640
15.2k
  const u8 *buffer;
641
15.2k
  size_t buffer_len;
642
15.2k
  unsigned int cla, tag;
643
644
15.2k
  if (card == NULL || in_path == NULL) {
645
0
    return SC_ERROR_INVALID_ARGUMENTS;
646
0
  }
647
15.2k
  ctx = card->ctx;
648
15.2k
  memcpy(path, in_path->value, in_path->len);
649
15.2k
  pathlen = in_path->len;
650
15.2k
  pathtype = in_path->type;
651
652
15.2k
  if (in_path->aid.len) {
653
1.36k
    if (!pathlen) {
654
1.33k
      memcpy(path, in_path->aid.value, in_path->aid.len);
655
1.33k
      pathlen = in_path->aid.len;
656
1.33k
      pathtype = SC_PATH_TYPE_DF_NAME;
657
1.33k
    } else {
658
      /* First, select the application */
659
27
      sc_format_apdu(card, &apdu, SC_APDU_CASE_3_SHORT, 0xA4, 4, 0);
660
27
      apdu.data = in_path->aid.value;
661
27
      apdu.datalen = in_path->aid.len;
662
27
      apdu.lc = in_path->aid.len;
663
664
27
      r = sc_transmit_apdu(card, &apdu);
665
27
      LOG_TEST_RET(ctx, r, "APDU transmit failed");
666
26
      r = sc_check_sw(card, apdu.sw1, apdu.sw2);
667
26
      if (r)
668
26
        LOG_FUNC_RETURN(ctx, r);
669
670
20
      if (pathtype == SC_PATH_TYPE_PATH
671
0
          || pathtype == SC_PATH_TYPE_DF_NAME)
672
20
        pathtype = SC_PATH_TYPE_FROM_CURRENT;
673
20
    }
674
1.36k
  }
675
676
15.2k
  sc_format_apdu(card, &apdu, SC_APDU_CASE_4_SHORT, 0xA4, 0, 0);
677
678
15.2k
  switch (pathtype) {
679
0
  case SC_PATH_TYPE_FILE_ID:
680
0
    apdu.p1 = 0;
681
0
    if (pathlen != 2)
682
0
      return SC_ERROR_INVALID_ARGUMENTS;
683
0
    break;
684
11.1k
  case SC_PATH_TYPE_DF_NAME:
685
11.1k
    apdu.p1 = 4;
686
11.1k
    break;
687
4.01k
  case SC_PATH_TYPE_PATH:
688
4.01k
    apdu.p1 = 8;
689
4.01k
    if (pathlen >= 2 && memcmp(path, "\x3F\x00", 2) == 0) {
690
2.87k
      if (pathlen == 2) { /* only 3F00 supplied */
691
2.87k
        select_mf = 1;
692
2.87k
        apdu.p1 = 0;
693
2.87k
        break;
694
2.87k
      }
695
0
      path += 2;
696
0
      pathlen -= 2;
697
0
    }
698
1.14k
    break;
699
1.14k
  case SC_PATH_TYPE_FROM_CURRENT:
700
20
    apdu.p1 = 9;
701
20
    break;
702
0
  case SC_PATH_TYPE_PARENT:
703
0
    apdu.p1 = 3;
704
0
    pathlen = 0;
705
0
    apdu.cse = SC_APDU_CASE_2_SHORT;
706
0
    break;
707
0
  default:
708
0
    LOG_FUNC_RETURN(ctx, SC_ERROR_INVALID_ARGUMENTS);
709
15.2k
  }
710
15.2k
  apdu.lc = pathlen;
711
15.2k
  apdu.data = path;
712
15.2k
  apdu.datalen = pathlen;
713
714
15.2k
  if (file_out != NULL) {
715
10.9k
    apdu.p2 = 0;    /* first record, return FCI */
716
10.9k
    apdu.resp = buf;
717
10.9k
    apdu.resplen = sizeof(buf);
718
10.9k
    apdu.le = sc_get_max_recv_size(card) < 256 ? sc_get_max_recv_size(card) : 256;
719
10.9k
  }
720
4.29k
  else {
721
4.29k
    apdu.p2 = 0x0C;   /* first record, return nothing */
722
4.29k
    apdu.cse = (apdu.lc == 0) ? SC_APDU_CASE_1 : SC_APDU_CASE_3_SHORT;
723
4.29k
  }
724
725
15.2k
  r = sc_transmit_apdu(card, &apdu);
726
15.2k
  LOG_TEST_RET(ctx, r, "APDU transmit failed");
727
14.9k
  if (file_out == NULL) {
728
    /* For some cards 'SELECT' can be only with request to return FCI/FCP. */
729
4.29k
    r = sc_check_sw(card, apdu.sw1, apdu.sw2);
730
4.29k
    if (apdu.sw1 == 0x6A && apdu.sw2 == 0x86)   {
731
7
      apdu.p2 = 0x00;
732
7
      if (sc_transmit_apdu(card, &apdu) == SC_SUCCESS)
733
4
        r = sc_check_sw(card, apdu.sw1, apdu.sw2);
734
7
    }
735
4.29k
    if (apdu.sw1 == 0x61)
736
4.29k
      LOG_FUNC_RETURN(ctx, SC_SUCCESS);
737
4.29k
    LOG_FUNC_RETURN(ctx, r);
738
4.29k
  }
739
740
10.6k
  r = sc_check_sw(card, apdu.sw1, apdu.sw2);
741
10.6k
  if (r)
742
10.6k
    LOG_FUNC_RETURN(ctx, r);
743
744
3.69k
  if (file_out && (apdu.resplen == 0))   {
745
    /* For some cards 'SELECT' MF or DF_NAME do not return FCI. */
746
2.03k
    if (select_mf || pathtype == SC_PATH_TYPE_DF_NAME)   {
747
2.03k
      file = sc_file_new();
748
2.03k
      if (file == NULL)
749
2.03k
        LOG_FUNC_RETURN(ctx, SC_ERROR_OUT_OF_MEMORY);
750
2.03k
      file->path = *in_path;
751
752
2.03k
      *file_out = file;
753
2.03k
      LOG_FUNC_RETURN(ctx, SC_SUCCESS);
754
2.03k
    }
755
2.03k
  }
756
757
1.66k
  if (apdu.resplen < 2)
758
1.66k
    LOG_FUNC_RETURN(ctx, SC_ERROR_UNKNOWN_DATA_RECEIVED);
759
1.64k
  switch (apdu.resp[0]) {
760
389
  case ISO7816_TAG_FCI:
761
1.62k
  case ISO7816_TAG_FCP:
762
1.62k
    file = sc_file_new();
763
1.62k
    if (file == NULL)
764
1.62k
      LOG_FUNC_RETURN(ctx, SC_ERROR_OUT_OF_MEMORY);
765
1.62k
    file->path = *in_path;
766
1.62k
    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
1.62k
    buffer = apdu.resp;
771
1.62k
    r = sc_asn1_read_tag(&buffer, apdu.resplen, &cla, &tag, &buffer_len);
772
1.62k
    if (r == SC_SUCCESS)
773
1.59k
      card->ops->process_fci(card, file, buffer, buffer_len);
774
1.62k
    *file_out = file;
775
1.62k
    break;
776
8
  case 0x00: /* proprietary coding */
777
8
    LOG_FUNC_RETURN(ctx, SC_ERROR_UNKNOWN_DATA_RECEIVED);
778
10
  default:
779
10
    LOG_FUNC_RETURN(ctx, SC_ERROR_UNKNOWN_DATA_RECEIVED);
780
1.64k
  }
781
782
1.62k
  return SC_SUCCESS;
783
1.64k
}
784
785
786
static int
787
iso7816_get_challenge(struct sc_card *card, u8 *rnd, size_t len)
788
5.84k
{
789
5.84k
  int r;
790
5.84k
  struct sc_apdu apdu;
791
792
5.84k
  sc_format_apdu(card, &apdu, SC_APDU_CASE_2, 0x84, 0x00, 0x00);
793
5.84k
  apdu.le = len;
794
5.84k
  apdu.resp = rnd;
795
5.84k
  apdu.resplen = len;
796
797
5.84k
  r = sc_transmit_apdu(card, &apdu);
798
5.84k
  LOG_TEST_RET(card->ctx, r, "APDU transmit failed");
799
800
5.81k
  r = sc_check_sw(card, apdu.sw1, apdu.sw2);
801
5.81k
  LOG_TEST_RET(card->ctx, r, "GET CHALLENGE failed");
802
803
4.19k
  if (len < apdu.resplen) {
804
0
    return (int) len;
805
0
  }
806
807
4.19k
  return (int) apdu.resplen;
808
4.19k
}
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
    if (sizeof(buf) < file->type_attr_len)
829
0
      return SC_ERROR_INTERNAL;
830
0
    memcpy(buf, file->type_attr, file->type_attr_len);
831
0
    sc_asn1_put_tag(0x82, buf, file->type_attr_len,
832
0
        p, *outlen - (p - out), &p);
833
0
  } else {
834
0
    buf[0] = file->shareable ? 0x40 : 0;
835
0
    switch (file->type) {
836
0
    case SC_FILE_TYPE_INTERNAL_EF:
837
0
      buf[0] |= 0x08;
838
      /* fall through */
839
0
    case SC_FILE_TYPE_WORKING_EF:
840
0
      buf[0] |= file->ef_structure & 7;
841
0
      break;
842
0
    case SC_FILE_TYPE_DF:
843
0
      buf[0] |= 0x38;
844
0
      break;
845
0
    default:
846
0
      return SC_ERROR_NOT_SUPPORTED;
847
0
    }
848
0
    sc_asn1_put_tag(0x82, buf, 1, p, *outlen - (p - out), &p);
849
0
  }
850
0
  buf[0] = (file->id >> 8) & 0xFF;
851
0
  buf[1] = file->id & 0xFF;
852
0
  sc_asn1_put_tag(0x83, buf, 2, p, *outlen - (p - out), &p);
853
  /* 0x84 = DF name */
854
0
  if (file->prop_attr_len) {
855
0
    if (sizeof(buf) < file->prop_attr_len)
856
0
      return SC_ERROR_INTERNAL;
857
0
    memcpy(buf, file->prop_attr, file->prop_attr_len);
858
0
    sc_asn1_put_tag(0x85, buf, file->prop_attr_len,
859
0
        p, *outlen - (p - out), &p);
860
0
  }
861
0
  if (file->sec_attr_len) {
862
0
    if (sizeof(buf) < file->sec_attr_len)
863
0
      return SC_ERROR_INTERNAL;
864
0
    memcpy(buf, file->sec_attr, file->sec_attr_len);
865
0
    sc_asn1_put_tag(0x86, buf, file->sec_attr_len,
866
0
        p, *outlen - (p - out), &p);
867
0
  }
868
0
  out[1] = p - out - 2;
869
870
0
  *outlen = p - out;
871
0
  return 0;
872
0
}
873
874
875
static int
876
iso7816_create_file(struct sc_card *card, sc_file_t *file)
877
0
{
878
0
  int r;
879
0
  size_t len;
880
0
  u8 sbuf[SC_MAX_APDU_BUFFER_SIZE];
881
0
  struct sc_apdu apdu;
882
883
0
  len = SC_MAX_APDU_BUFFER_SIZE;
884
885
0
  if (card->ops->construct_fci == NULL)
886
0
    LOG_FUNC_RETURN(card->ctx, SC_ERROR_NOT_SUPPORTED);
887
0
  r = card->ops->construct_fci(card, file, sbuf, &len);
888
0
  LOG_TEST_RET(card->ctx, r, "construct_fci() failed");
889
890
0
  sc_format_apdu(card, &apdu, SC_APDU_CASE_3_SHORT, 0xE0, 0x00, 0x00);
891
0
  apdu.lc = len;
892
0
  apdu.datalen = len;
893
0
  apdu.data = sbuf;
894
895
0
  r = sc_transmit_apdu(card, &apdu);
896
0
  LOG_TEST_RET(card->ctx, r, "APDU transmit failed");
897
0
  r = sc_check_sw(card, apdu.sw1, apdu.sw2);
898
0
  LOG_TEST_RET(card->ctx, r, "Card returned error");
899
900
0
  return r;
901
0
}
902
903
904
static int
905
iso7816_get_response(struct sc_card *card, size_t *count, u8 *buf)
906
41.5k
{
907
41.5k
  struct sc_apdu apdu = {0};
908
41.5k
  int r;
909
41.5k
  size_t rlen;
910
911
  /* request at most max_recv_size bytes */
912
41.5k
  if (*count > sc_get_max_recv_size(card))
913
314
    rlen = sc_get_max_recv_size(card);
914
41.2k
  else
915
41.2k
    rlen = *count;
916
917
41.5k
  sc_format_apdu(card, &apdu, SC_APDU_CASE_2, 0xC0, 0x00, 0x00);
918
41.5k
  apdu.le      = rlen;
919
41.5k
  apdu.resplen = rlen;
920
41.5k
  apdu.resp    = buf;
921
  /* don't call GET RESPONSE recursively */
922
41.5k
  apdu.flags  |= SC_APDU_FLAGS_NO_GET_RESP;
923
924
41.5k
  r = sc_transmit_apdu(card, &apdu);
925
41.5k
  LOG_TEST_RET(card->ctx, r, "APDU transmit failed");
926
927
41.0k
  *count = apdu.resplen;
928
929
41.0k
  if (apdu.resplen == 0) {
930
3.72k
    LOG_FUNC_RETURN(card->ctx, sc_check_sw(card, apdu.sw1, apdu.sw2));
931
3.72k
  }
932
37.3k
  if (apdu.sw1 == 0x90 && apdu.sw2 == 0x00)
933
1.82k
    r = 0;          /* no more data to read */
934
35.5k
  else if (apdu.sw1 == 0x61)
935
1.68k
    r = apdu.sw2 == 0 ? 256 : apdu.sw2;  /* more data to read    */
936
33.8k
  else if (apdu.sw1 == 0x62 && apdu.sw2 == 0x82)
937
335
    r = 0; /* Le not reached but file/record ended */
938
33.4k
  else
939
33.4k
    r = sc_check_sw(card, apdu.sw1, apdu.sw2);
940
941
37.3k
  return r;
942
41.0k
}
943
944
945
static int
946
iso7816_delete_file(struct sc_card *card, const sc_path_t *path)
947
0
{
948
0
  int r;
949
0
  u8 sbuf[2];
950
0
  struct sc_apdu apdu;
951
952
0
  SC_FUNC_CALLED(card->ctx, SC_LOG_DEBUG_VERBOSE);
953
0
  if (path->type != SC_PATH_TYPE_FILE_ID || (path->len != 0 && path->len != 2)) {
954
0
    sc_log(card->ctx, "File type has to be SC_PATH_TYPE_FILE_ID");
955
0
    LOG_FUNC_RETURN(card->ctx, SC_ERROR_INVALID_ARGUMENTS);
956
0
  }
957
958
0
  if (path->len == 2) {
959
0
    sbuf[0] = path->value[0];
960
0
    sbuf[1] = path->value[1];
961
0
    sc_format_apdu(card, &apdu, SC_APDU_CASE_3_SHORT, 0xE4, 0x00, 0x00);
962
0
    apdu.lc = 2;
963
0
    apdu.datalen = 2;
964
0
    apdu.data = sbuf;
965
0
  }
966
0
  else   {
967
    /* No file ID given: means currently selected file */
968
0
    sc_format_apdu(card, &apdu, SC_APDU_CASE_1, 0xE4, 0x00, 0x00);
969
0
  }
970
971
0
  r = sc_transmit_apdu(card, &apdu);
972
0
  LOG_TEST_RET(card->ctx, r, "APDU transmit failed");
973
0
  r = sc_check_sw(card, apdu.sw1, apdu.sw2);
974
0
  LOG_TEST_RET(card->ctx, r, "Card returned error");
975
976
0
  return r;
977
0
}
978
979
980
static int
981
iso7816_set_security_env(struct sc_card *card,
982
    const struct sc_security_env *env, int se_num)
983
0
{
984
0
  struct sc_apdu apdu;
985
0
  u8 sbuf[SC_MAX_APDU_BUFFER_SIZE];
986
0
  u8 *p;
987
0
  int r, locked = 0;
988
989
0
  if (card == NULL || env == NULL) {
990
0
    return SC_ERROR_INVALID_ARGUMENTS;
991
0
  }
992
0
  sc_format_apdu(card, &apdu, SC_APDU_CASE_3_SHORT, 0x22, 0x41, 0);
993
0
  switch (env->operation) {
994
0
  case SC_SEC_OPERATION_AUTHENTICATE:
995
0
    apdu.p2 = 0xA4;
996
0
    break;
997
0
  case SC_SEC_OPERATION_DECIPHER:
998
0
  case SC_SEC_OPERATION_DERIVE:
999
0
    apdu.p2 = 0xB8;
1000
0
    break;
1001
0
  case SC_SEC_OPERATION_SIGN:
1002
0
    apdu.p2 = 0xB6;
1003
0
    break;
1004
0
  default:
1005
0
    return SC_ERROR_INVALID_ARGUMENTS;
1006
0
  }
1007
0
  p = sbuf;
1008
0
  if (env->flags & SC_SEC_ENV_ALG_REF_PRESENT) {
1009
0
    *p++ = 0x80;  /* algorithm reference */
1010
0
    *p++ = 0x01;
1011
0
    *p++ = env->algorithm_ref & 0xFF;
1012
0
  }
1013
0
  if (env->flags & SC_SEC_ENV_FILE_REF_PRESENT) {
1014
0
    if (env->file_ref.len > SC_MAX_PATH_SIZE)
1015
0
      return SC_ERROR_INVALID_ARGUMENTS;
1016
0
    if (sizeof(sbuf) - (p - sbuf) < env->file_ref.len + 2)
1017
0
      return SC_ERROR_OFFSET_TOO_LARGE;
1018
1019
0
    *p++ = 0x81;
1020
0
    *p++ = (u8) env->file_ref.len;
1021
0
    memcpy(p, env->file_ref.value, env->file_ref.len);
1022
0
    p += env->file_ref.len;
1023
0
  }
1024
0
  if (env->flags & SC_SEC_ENV_KEY_REF_PRESENT) {
1025
0
    if (sizeof(sbuf) - (p - sbuf) < env->key_ref_len + 2)
1026
0
      return SC_ERROR_OFFSET_TOO_LARGE;
1027
1028
0
    if (env->flags & SC_SEC_ENV_KEY_REF_SYMMETRIC)
1029
0
      *p++ = 0x83;
1030
0
    else
1031
0
      *p++ = 0x84;
1032
0
    if (env->key_ref_len > SC_MAX_KEYREF_SIZE)
1033
0
      return SC_ERROR_INVALID_ARGUMENTS;
1034
0
    *p++ = env->key_ref_len & 0xFF;
1035
0
    memcpy(p, env->key_ref, env->key_ref_len);
1036
0
    p += env->key_ref_len;
1037
0
  }
1038
0
  r = (int)(p - sbuf);
1039
0
  apdu.lc = r;
1040
0
  apdu.datalen = r;
1041
0
  apdu.data = sbuf;
1042
0
  if (se_num > 0) {
1043
0
    r = sc_lock(card);
1044
0
    LOG_TEST_RET(card->ctx, r, "sc_lock() failed");
1045
0
    locked = 1;
1046
0
  }
1047
0
  if (apdu.datalen != 0) {
1048
0
    r = sc_transmit_apdu(card, &apdu);
1049
0
    if (r) {
1050
0
      sc_log(card->ctx, "%s: APDU transmit failed", sc_strerror(r));
1051
0
      goto err;
1052
0
    }
1053
0
    r = sc_check_sw(card, apdu.sw1, apdu.sw2);
1054
0
    if (r) {
1055
0
      sc_log(card->ctx, "%s: Card returned error", sc_strerror(r));
1056
0
      goto err;
1057
0
    }
1058
0
  }
1059
0
  if (se_num <= 0) {
1060
0
    r = SC_SUCCESS;
1061
0
    goto err;
1062
0
  }
1063
0
  sc_format_apdu(card, &apdu, SC_APDU_CASE_3_SHORT, 0x22, 0xF2, se_num);
1064
0
  r = sc_transmit_apdu(card, &apdu);
1065
0
  sc_unlock(card);
1066
0
  LOG_TEST_RET(card->ctx, r, "APDU transmit failed");
1067
1068
0
  return sc_check_sw(card, apdu.sw1, apdu.sw2);
1069
0
err:
1070
0
  if (locked)
1071
0
    sc_unlock(card);
1072
0
  return r;
1073
0
}
1074
1075
1076
static int
1077
iso7816_restore_security_env(struct sc_card *card, int se_num)
1078
0
{
1079
0
  struct sc_apdu apdu;
1080
0
  int r;
1081
1082
0
  if (card == NULL) {
1083
0
    return SC_ERROR_INVALID_ARGUMENTS;
1084
0
  }
1085
1086
0
  sc_format_apdu(card, &apdu, SC_APDU_CASE_1, 0x22, 0xF3, se_num);
1087
1088
0
  r = sc_transmit_apdu(card, &apdu);
1089
0
  LOG_TEST_RET(card->ctx, r, "APDU transmit failed");
1090
0
  r = sc_check_sw(card, apdu.sw1, apdu.sw2);
1091
0
  LOG_TEST_RET(card->ctx, r, "Card returned error");
1092
1093
0
  return r;
1094
0
}
1095
1096
1097
static int
1098
iso7816_compute_signature(struct sc_card *card,
1099
    const u8 * data, size_t datalen,
1100
    u8 * out, size_t outlen)
1101
0
{
1102
0
  int r;
1103
0
  struct sc_apdu apdu;
1104
1105
0
  if (card == NULL || data == NULL || out == NULL) {
1106
0
    return SC_ERROR_INVALID_ARGUMENTS;
1107
0
  }
1108
0
  LOG_FUNC_CALLED(card->ctx);
1109
0
  sc_log(card->ctx,
1110
0
         "ISO7816 compute signature: in-len %"SC_FORMAT_LEN_SIZE_T"u, out-len %"SC_FORMAT_LEN_SIZE_T"u",
1111
0
         datalen, outlen);
1112
1113
  /* INS: 0x2A  PERFORM SECURITY OPERATION
1114
   * P1:  0x9E  Resp: Digital Signature
1115
   * P2:  0x9A  Cmd: Input for Digital Signature */
1116
0
  sc_format_apdu(card, &apdu, SC_APDU_CASE_4, 0x2A, 0x9E, 0x9A);
1117
0
  apdu.resp = out;
1118
0
  apdu.resplen = outlen;
1119
0
  apdu.le = outlen;
1120
1121
0
  apdu.data = data;
1122
0
  apdu.lc = datalen;
1123
0
  apdu.datalen = datalen;
1124
1125
0
  iso7816_fixup_transceive_length(card, &apdu);
1126
0
  r = sc_transmit_apdu(card, &apdu);
1127
0
  LOG_TEST_RET(card->ctx, r, "APDU transmit failed");
1128
0
  if (apdu.sw1 == 0x90 && apdu.sw2 == 0x00)
1129
0
    LOG_FUNC_RETURN(card->ctx, (int)apdu.resplen);
1130
1131
0
  r = sc_check_sw(card, apdu.sw1, apdu.sw2);
1132
0
  LOG_TEST_RET(card->ctx, r, "Card returned error");
1133
1134
0
  LOG_FUNC_RETURN(card->ctx, r);
1135
0
}
1136
1137
1138
static int
1139
iso7816_decipher(struct sc_card *card,
1140
    const u8 * crgram, size_t crgram_len,
1141
    u8 * out, size_t outlen)
1142
0
{
1143
0
  int r;
1144
0
  struct sc_apdu apdu;
1145
0
  u8 *sbuf = NULL;
1146
1147
0
  if (card == NULL || crgram == NULL || out == NULL) {
1148
0
    return SC_ERROR_INVALID_ARGUMENTS;
1149
0
  }
1150
0
  LOG_FUNC_CALLED(card->ctx);
1151
0
  sc_log(card->ctx,
1152
0
         "ISO7816 decipher: in-len %"SC_FORMAT_LEN_SIZE_T"u, out-len %"SC_FORMAT_LEN_SIZE_T"u",
1153
0
         crgram_len, outlen);
1154
1155
0
  sbuf = malloc(crgram_len + 1);
1156
0
  if (sbuf == NULL)
1157
0
    return SC_ERROR_OUT_OF_MEMORY;
1158
1159
  /* INS: 0x2A  PERFORM SECURITY OPERATION
1160
   * P1:  0x80  Resp: Plain value
1161
   * P2:  0x86  Cmd: Padding indicator byte followed by cryptogram */
1162
0
  sc_format_apdu(card, &apdu, SC_APDU_CASE_4, 0x2A, 0x80, 0x86);
1163
0
  apdu.resp    = out;
1164
0
  apdu.resplen = outlen;
1165
0
  apdu.le      = outlen;
1166
1167
0
  sbuf[0] = 0; /* padding indicator byte, 0x00 = No further indication */
1168
0
  memcpy(sbuf + 1, crgram, crgram_len);
1169
0
  apdu.data = sbuf;
1170
0
  apdu.lc = crgram_len + 1;
1171
0
  apdu.datalen = crgram_len + 1;
1172
1173
0
  iso7816_fixup_transceive_length(card, &apdu);
1174
0
  r = sc_transmit_apdu(card, &apdu);
1175
0
  sc_mem_clear(sbuf, crgram_len + 1);
1176
0
  free(sbuf);
1177
0
  LOG_TEST_RET(card->ctx, r, "APDU transmit failed");
1178
1179
0
  if (apdu.sw1 == 0x90 && apdu.sw2 == 0x00)
1180
0
    LOG_FUNC_RETURN(card->ctx, (int)apdu.resplen);
1181
0
  else
1182
0
    LOG_FUNC_RETURN(card->ctx, sc_check_sw(card, apdu.sw1, apdu.sw2));
1183
0
}
1184
1185
1186
int
1187
iso7816_build_pin_apdu(struct sc_card *card, struct sc_apdu *apdu,
1188
    struct sc_pin_cmd_data *data, u8 *buf, size_t buf_len)
1189
0
{
1190
0
  int r, len = 0, pad = 0, use_pin_pad = 0, ins, p1 = 0;
1191
0
  int cse = SC_APDU_CASE_3_SHORT;
1192
1193
0
  switch (data->pin_type) {
1194
0
  case SC_AC_CHV:
1195
    /* fall through */
1196
0
  case SC_AC_SESSION:
1197
0
  case SC_AC_CONTEXT_SPECIFIC:
1198
0
    break;
1199
0
  default:
1200
0
    return SC_ERROR_INVALID_ARGUMENTS;
1201
0
  }
1202
1203
0
  if (data->flags & SC_PIN_CMD_NEED_PADDING)
1204
0
    pad = 1;
1205
0
  if (data->flags & SC_PIN_CMD_USE_PINPAD)
1206
0
    use_pin_pad = 1;
1207
1208
0
  data->pin1.offset = 5;
1209
1210
0
  switch (data->cmd) {
1211
0
  case SC_PIN_CMD_VERIFY:
1212
0
    ins = 0x20;
1213
    /* detect overloaded APDU with SC_PIN_CMD_GET_INFO */
1214
0
    if (data->pin1.len == 0 && !use_pin_pad)
1215
0
      return SC_ERROR_INVALID_PIN_LENGTH;
1216
0
    if ((r = sc_build_pin(buf, buf_len, &data->pin1, pad)) < 0)
1217
0
      return r;
1218
0
    len = r;
1219
0
    break;
1220
0
  case SC_PIN_CMD_CHANGE:
1221
0
    ins = 0x24;
1222
0
    if (data->pin1.len != 0 || (use_pin_pad && !( data->flags & SC_PIN_CMD_IMPLICIT_CHANGE))) {
1223
0
      if ((r = sc_build_pin(buf, buf_len, &data->pin1, pad)) < 0)
1224
0
        return r;
1225
0
      len += r;
1226
0
    }
1227
0
    else {
1228
      /* implicit test */
1229
0
      p1 = 1;
1230
0
    }
1231
1232
0
    data->pin2.offset = data->pin1.offset + len;
1233
0
    if ((r = sc_build_pin(buf+len, buf_len-len, &data->pin2, pad)) < 0)
1234
0
      return r;
1235
    /* Special case - where provided the old PIN on the command line
1236
     * but expect the new one to be entered on the keypad.
1237
     */
1238
0
    if (data->pin1.len && data->pin2.len == 0) {
1239
0
      sc_log(card->ctx, "Special case - initial pin provided - but new pin asked on keypad");
1240
0
      data->flags |= SC_PIN_CMD_IMPLICIT_CHANGE;
1241
0
    };
1242
0
    len += r;
1243
0
    break;
1244
0
  case SC_PIN_CMD_UNBLOCK:
1245
0
    ins = 0x2C;
1246
0
    if (data->pin1.len != 0 || (use_pin_pad && !( data->flags & SC_PIN_CMD_IMPLICIT_CHANGE))) {
1247
0
      if ((r = sc_build_pin(buf, buf_len, &data->pin1, pad)) < 0)
1248
0
        return r;
1249
0
      len += r;
1250
0
    } else {
1251
0
      p1 |= 0x02;
1252
0
    }
1253
1254
0
    if (data->pin2.len != 0 || use_pin_pad) {
1255
0
      data->pin2.offset = data->pin1.offset + len;
1256
0
      if ((r = sc_build_pin(buf+len, buf_len-len, &data->pin2, pad)) < 0)
1257
0
        return r;
1258
0
      len += r;
1259
0
    } else {
1260
0
      p1 |= 0x01;
1261
0
    }
1262
0
    if (p1 == 0x03) {
1263
      /* No data to send or to receive */
1264
0
      cse = SC_APDU_CASE_1;
1265
0
    }
1266
0
    break;
1267
0
  case SC_PIN_CMD_GET_INFO:
1268
0
    ins = 0x20;
1269
    /* No data to send or to receive */
1270
0
    cse = SC_APDU_CASE_1;
1271
0
    break;
1272
0
  default:
1273
0
    return SC_ERROR_NOT_SUPPORTED;
1274
0
  }
1275
1276
0
  sc_format_apdu(card, apdu, cse, ins, p1, data->pin_reference);
1277
0
  apdu->lc = len;
1278
0
  apdu->datalen = len;
1279
0
  apdu->data = buf;
1280
0
  apdu->resplen = 0;
1281
1282
0
  return 0;
1283
0
}
1284
1285
1286
static int
1287
iso7816_pin_cmd(struct sc_card *card, struct sc_pin_cmd_data *data)
1288
0
{
1289
0
  struct sc_apdu local_apdu, *apdu;
1290
0
  int r;
1291
0
  u8  sbuf[SC_MAX_APDU_BUFFER_SIZE];
1292
1293
0
  data->pin1.tries_left = -1;
1294
1295
  /* Many cards do support PIN status queries, but some cards don't and
1296
   * mistakenly count the command as a failed PIN attempt, so for now we
1297
   * allow cards with this flag.  In future this may be reduced to a
1298
   * blocklist, subject to testing more cards. */
1299
0
  if (data->cmd == SC_PIN_CMD_GET_INFO &&
1300
0
      !(card->caps & SC_CARD_CAP_ISO7816_PIN_INFO)) {
1301
0
    sc_log(card->ctx, "Card does not support PIN status queries");
1302
0
    return SC_ERROR_NOT_SUPPORTED;
1303
0
  }
1304
1305
  /* See if we've been called from another card driver, which is
1306
   * passing an APDU to us (this allows to write card drivers
1307
   * whose PIN functions behave "mostly like ISO" except in some
1308
   * special circumstances.
1309
   */
1310
0
  if (data->apdu == NULL) {
1311
0
    r = iso7816_build_pin_apdu(card, &local_apdu, data, sbuf, sizeof(sbuf));
1312
0
    if (r < 0)
1313
0
      return r;
1314
0
    data->apdu = &local_apdu;
1315
0
  }
1316
0
  apdu = data->apdu;
1317
1318
0
  if (!(data->flags & SC_PIN_CMD_USE_PINPAD) || data->cmd == SC_PIN_CMD_GET_INFO) {
1319
    /* Transmit the APDU to the card */
1320
0
    r = sc_transmit_apdu(card, apdu);
1321
1322
    /* Clear the buffer - it may contain pins */
1323
0
    sc_mem_clear(sbuf, sizeof(sbuf));
1324
0
  }
1325
0
  else {
1326
    /* Call the reader driver to collect
1327
     * the PIN and pass on the APDU to the card */
1328
0
    if (data->pin1.offset == 0) {
1329
0
      sc_log(card->ctx, "Card driver didn't set PIN offset");
1330
0
      return SC_ERROR_INVALID_ARGUMENTS;
1331
0
    }
1332
0
    if (card->reader && card->reader->ops && card->reader->ops->perform_verify) {
1333
0
      r = card->reader->ops->perform_verify(card->reader, data);
1334
      /* sw1/sw2 filled in by reader driver */
1335
0
    }
1336
0
    else {
1337
0
      sc_log(card->ctx, "Card reader driver does not support "
1338
0
          "PIN entry through reader key pad");
1339
0
      r = SC_ERROR_NOT_SUPPORTED;
1340
0
    }
1341
0
  }
1342
1343
  /* Don't pass references to local variables up to the caller. */
1344
0
  if (data->apdu == &local_apdu)
1345
0
    data->apdu = NULL;
1346
1347
0
  LOG_TEST_RET(card->ctx, r, "APDU transmit failed");
1348
0
  r = sc_check_sw(card, apdu->sw1, apdu->sw2);
1349
1350
0
  if (r == SC_SUCCESS) {
1351
0
    data->pin1.logged_in = SC_PIN_STATE_LOGGED_IN;
1352
0
  } else if (r == SC_ERROR_PIN_CODE_INCORRECT) {
1353
0
    data->pin1.tries_left = apdu->sw2 & 0xF;
1354
0
    data->pin1.logged_in = SC_PIN_STATE_LOGGED_OUT;
1355
0
    if (data->cmd == SC_PIN_CMD_GET_INFO)
1356
0
      r = SC_SUCCESS;
1357
0
  } else if (r == SC_ERROR_AUTH_METHOD_BLOCKED) {
1358
0
    data->pin1.tries_left = 0;
1359
0
    data->pin1.logged_in = SC_PIN_STATE_LOGGED_OUT;
1360
0
    if (data->cmd == SC_PIN_CMD_GET_INFO)
1361
0
      r = SC_SUCCESS;
1362
0
  }
1363
1364
0
  return r;
1365
0
}
1366
1367
1368
static int iso7816_get_data(struct sc_card *card, unsigned int tag,  u8 *buf, size_t len)
1369
256
{
1370
256
  int                             r, cse;
1371
256
  struct sc_apdu                  apdu;
1372
1373
256
  SC_FUNC_CALLED(card->ctx, SC_LOG_DEBUG_VERBOSE);
1374
1375
256
  if (buf && len)
1376
256
    cse = SC_APDU_CASE_2;
1377
0
  else
1378
0
    cse = SC_APDU_CASE_1;
1379
1380
256
  sc_format_apdu(card, &apdu, cse, 0xCA, (tag >> 8) & 0xff, tag & 0xff);
1381
256
  apdu.le = len;
1382
256
  apdu.resp = buf;
1383
256
  apdu.resplen = len;
1384
256
  r = sc_transmit_apdu(card, &apdu);
1385
256
  LOG_TEST_RET(card->ctx, r, "APDU transmit failed");
1386
1387
249
  r = sc_check_sw(card, apdu.sw1, apdu.sw2);
1388
249
  LOG_TEST_RET(card->ctx, r, "GET_DATA returned error");
1389
1390
189
  if (apdu.resplen > len)
1391
0
    r = SC_ERROR_WRONG_LENGTH;
1392
189
  else
1393
189
    r = (int)apdu.resplen;
1394
1395
189
  LOG_FUNC_RETURN(card->ctx, r);
1396
189
}
1397
1398
int
1399
iso7816_select_aid(struct sc_card *card, const u8 *req,
1400
    size_t reqlen, u8 *resp, size_t *resplen)
1401
9.92k
{
1402
9.92k
  struct sc_context *ctx = card->ctx;
1403
9.92k
  struct sc_apdu apdu;
1404
9.92k
  int rv;
1405
1406
9.92k
  SC_FUNC_CALLED(ctx, SC_LOG_DEBUG_VERBOSE);
1407
1408
9.92k
  sc_format_apdu(card, &apdu, resp == NULL ? SC_APDU_CASE_3_SHORT : SC_APDU_CASE_4_SHORT, 0xA4, 0x04, resp == NULL ? 0x0C : 0x00);
1409
9.92k
  apdu.lc = reqlen;
1410
9.92k
  apdu.data = req;
1411
9.92k
  apdu.datalen = reqlen;
1412
9.92k
  apdu.resp = resp;
1413
9.92k
  apdu.resplen = resp == NULL ? 0 : *resplen;
1414
9.92k
  apdu.le = resp == NULL ? 0 : 256;
1415
1416
9.92k
  rv = sc_transmit_apdu(card, &apdu);
1417
9.92k
  if (resplen)
1418
5.30k
    *resplen = apdu.resplen;
1419
9.92k
  LOG_TEST_RET(card->ctx, rv, "APDU transmit failed");
1420
1421
9.80k
  rv = sc_check_sw(card, apdu.sw1, apdu.sw2);
1422
9.80k
  LOG_FUNC_RETURN(ctx, rv);
1423
9.80k
}
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
5.29k
{
1438
5.29k
  return 0;
1439
5.29k
}
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
258k
{
1492
258k
  return &iso_driver;
1493
258k
}
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) {
1535
0
      if (*ef_len > 0)
1536
0
        break;
1537
0
      else {
1538
0
        sc_debug(card->ctx, SC_LOG_DEBUG_VERBOSE, "Could not read EF.");
1539
0
        goto err;
1540
0
      }
1541
0
    }
1542
0
    *ef_len += r;
1543
1544
0
    p = realloc(*ef, *ef_len + read);
1545
0
    if (!p) {
1546
0
      r = SC_ERROR_OUT_OF_MEMORY;
1547
0
      goto err;
1548
0
    }
1549
0
    *ef = p;
1550
1551
0
    r = iso7816_read_binary(card, (unsigned)*ef_len, *ef + *ef_len, read, 0);
1552
0
  }
1553
1554
0
  r = (int)*ef_len;
1555
1556
0
err:
1557
0
  return r;
1558
0
}
1559
1560
0
#define ISO_WRITE_BINARY  0xD0
1561
int iso7816_write_binary_sfid(sc_card_t *card, unsigned char sfid,
1562
    u8 *ef, size_t ef_len)
1563
0
{
1564
0
  int r;
1565
0
  size_t write, wrote = 0;
1566
0
  sc_apdu_t apdu;
1567
1568
0
  if (!card) {
1569
0
    r = SC_ERROR_INVALID_ARGUMENTS;
1570
0
    goto err;
1571
0
  }
1572
1573
0
  write = card->max_send_size;
1574
1575
0
  sc_format_apdu(card, &apdu, SC_APDU_CASE_3,
1576
0
      ISO_WRITE_BINARY, ISO_P1_FLAG_SFID|sfid, 0);
1577
1578
0
  if (write > ef_len) {
1579
0
    apdu.datalen = ef_len;
1580
0
    apdu.lc = ef_len;
1581
0
  } else {
1582
0
    apdu.datalen = write;
1583
0
    apdu.lc = write;
1584
0
  }
1585
0
  apdu.data = ef;
1586
1587
1588
0
  r = sc_transmit_apdu(card, &apdu);
1589
  /* emulate the behaviour of sc_write_binary */
1590
0
  if (r >= 0)
1591
0
    r = (int)apdu.datalen;
1592
1593
0
  while (1) {
1594
0
    if (r < 0 || ((size_t) r) > ef_len) {
1595
0
      sc_debug(card->ctx, SC_LOG_DEBUG_VERBOSE, "Could not write EF.");
1596
0
      goto err;
1597
0
    }
1598
0
    if (r == 0 || r == SC_ERROR_FILE_END_REACHED)
1599
0
      break;
1600
0
    wrote += r;
1601
0
    apdu.data += r;
1602
0
    if (wrote >= ef_len)
1603
0
      break;
1604
1605
0
    r = sc_write_binary(card, (unsigned)wrote, ef, write, 0);
1606
0
  }
1607
1608
0
  r = (int)wrote;
1609
1610
0
err:
1611
0
  return r;
1612
0
}
1613
1614
0
#define ISO_UPDATE_BINARY  0xD6
1615
int iso7816_update_binary_sfid(sc_card_t *card, unsigned char sfid,
1616
    u8 *ef, size_t ef_len)
1617
0
{
1618
0
  int r;
1619
0
  size_t write = MAX_SM_APDU_DATA_SIZE, wrote = 0;
1620
0
  sc_apdu_t apdu;
1621
0
#ifdef ENABLE_SM
1622
0
  struct iso_sm_ctx *iso_sm_ctx;
1623
0
#endif
1624
1625
0
  if (!card) {
1626
0
    r = SC_ERROR_INVALID_ARGUMENTS;
1627
0
    goto err;
1628
0
  }
1629
1630
0
#ifdef ENABLE_SM
1631
0
  iso_sm_ctx = card->sm_ctx.info.cmd_data;
1632
0
  if (write > SC_MAX_APDU_BUFFER_SIZE-2
1633
0
      || (card->sm_ctx.sm_mode == SM_MODE_TRANSMIT
1634
0
        && write > (((SC_MAX_APDU_BUFFER_SIZE-2
1635
          /* for encrypted APDUs we usually get authenticated status
1636
           * bytes (4B), a MAC (11B) and a cryptogram with padding
1637
           * indicator (3B without data).  The cryptogram is always
1638
           * padded to the block size. */
1639
0
          -18) / iso_sm_ctx->block_length)
1640
0
          * iso_sm_ctx->block_length - 1)))
1641
0
    sc_format_apdu(card, &apdu, SC_APDU_CASE_3_EXT,
1642
0
        ISO_UPDATE_BINARY, ISO_P1_FLAG_SFID|sfid, 0);
1643
0
  else
1644
0
#endif
1645
0
    sc_format_apdu(card, &apdu, SC_APDU_CASE_3_SHORT,
1646
0
        ISO_UPDATE_BINARY, ISO_P1_FLAG_SFID|sfid, 0);
1647
1648
0
  if (write > ef_len) {
1649
0
    apdu.datalen = ef_len;
1650
0
    apdu.lc = ef_len;
1651
0
  } else {
1652
0
    apdu.datalen = write;
1653
0
    apdu.lc = write;
1654
0
  }
1655
0
  apdu.data = ef;
1656
1657
1658
0
  r = sc_transmit_apdu(card, &apdu);
1659
  /* emulate the behaviour of sc_write_binary */
1660
0
  if (r >= 0)
1661
0
    r = (int)apdu.datalen;
1662
1663
0
  while (1) {
1664
0
    if (r < 0 || ((size_t) r) > ef_len) {
1665
0
      sc_debug(card->ctx, SC_LOG_DEBUG_VERBOSE, "Could not update EF.");
1666
0
      goto err;
1667
0
    }
1668
0
    if (r == 0 || r == SC_ERROR_FILE_END_REACHED)
1669
0
      break;
1670
0
    wrote += r;
1671
0
    apdu.data += r;
1672
0
    if (wrote >= ef_len)
1673
0
      break;
1674
1675
0
    r = sc_update_binary(card, (unsigned)wrote, ef, write, 0);
1676
0
  }
1677
1678
0
  r = (int)wrote;
1679
1680
0
err:
1681
0
  return r;
1682
0
}
1683
1684
int iso7816_logout(sc_card_t *card, unsigned char pin_reference)
1685
0
{
1686
0
  int r;
1687
0
  sc_apdu_t apdu;
1688
1689
0
  sc_format_apdu(card, &apdu, SC_APDU_CASE_1, 0x20, 0xFF, pin_reference);
1690
1691
0
  r = sc_transmit_apdu(card, &apdu);
1692
0
  if (r < 0)
1693
0
    return r;
1694
1695
0
  r = sc_check_sw(card, apdu.sw1, apdu.sw2);
1696
1697
0
  return r;
1698
0
}