Coverage Report

Created: 2025-08-29 06:26

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