1
/* iso7816.c - ISO 7816 commands
2
* Copyright (C) 2003, 2004 Free Software Foundation, Inc.
4
* This file is part of GnuPG.
6
* GnuPG is free software; you can redistribute it and/or modify
7
* it under the terms of the GNU General Public License as published by
8
* the Free Software Foundation; either version 2 of the License, or
9
* (at your option) any later version.
11
* GnuPG 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
14
* GNU General Public License for more details.
16
* You should have received a copy of the GNU General Public License
17
* along with this program; if not, write to the Free Software
18
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
20
* $Id: iso7816.c,v 1.3.2.11 2004/10/20 08:54:45 wk Exp $
29
#if defined(GNUPG_SCD_MAIN_HEADER)
30
#include GNUPG_SCD_MAIN_HEADER
31
#elif GNUPG_MAJOR_VERSION == 1
32
/* This is used with GnuPG version < 1.9. The code has been source
33
copied from the current GnuPG >= 1.9 and is maintained over
40
#else /* GNUPG_MAJOR_VERSION != 1 */
42
#endif /* GNUPG_MAJOR_VERSION != 1 */
48
#define CMD_SELECT_FILE 0xA4
49
#define CMD_VERIFY 0x20
50
#define CMD_CHANGE_REFERENCE_DATA 0x24
51
#define CMD_RESET_RETRY_COUNTER 0x2C
52
#define CMD_GET_DATA 0xCA
53
#define CMD_PUT_DATA 0xDA
56
#define CMD_INTERNAL_AUTHENTICATE 0x88
57
#define CMD_GENERATE_KEYPAIR 0x47
58
#define CMD_GET_CHALLENGE 0x84
59
#define CMD_READ_BINARY 0xB0
60
#define CMD_READ_RECORD 0xB2
69
case SW_EEPROM_FAILURE: ec = GPG_ERR_HARDWARE; break;
70
case SW_WRONG_LENGTH: ec = GPG_ERR_INV_VALUE; break;
71
case SW_CHV_WRONG: ec = GPG_ERR_BAD_PIN; break;
72
case SW_CHV_BLOCKED: ec = GPG_ERR_PIN_BLOCKED; break;
73
case SW_USE_CONDITIONS: ec = GPG_ERR_USE_CONDITIONS; break;
74
case SW_NOT_SUPPORTED: ec = GPG_ERR_NOT_SUPPORTED; break;
75
case SW_BAD_PARAMETER: ec = GPG_ERR_INV_VALUE; break;
76
case SW_FILE_NOT_FOUND: ec = GPG_ERR_ENOENT; break;
77
case SW_RECORD_NOT_FOUND:ec= GPG_ERR_NOT_FOUND; break;
78
case SW_REF_NOT_FOUND: ec = GPG_ERR_NO_OBJ; break;
79
case SW_BAD_P0_P1: ec = GPG_ERR_INV_VALUE; break;
80
case SW_INS_NOT_SUP: ec = GPG_ERR_CARD; break;
81
case SW_CLA_NOT_SUP: ec = GPG_ERR_CARD; break;
82
case SW_SUCCESS: ec = 0; break;
84
case SW_HOST_OUT_OF_CORE: ec = GPG_ERR_ENOMEM; break;
85
case SW_HOST_INV_VALUE: ec = GPG_ERR_INV_VALUE; break;
86
case SW_HOST_INCOMPLETE_CARD_RESPONSE: ec = GPG_ERR_CARD; break;
87
case SW_HOST_NOT_SUPPORTED: ec = GPG_ERR_NOT_SUPPORTED; break;
88
case SW_HOST_LOCKING_FAILED: ec = GPG_ERR_BUG; break;
89
case SW_HOST_BUSY: ec = GPG_ERR_EBUSY; break;
90
case SW_HOST_NO_CARD: ec = GPG_ERR_CARD_NOT_PRESENT; break;
91
case SW_HOST_CARD_INACTIVE: ec = GPG_ERR_CARD_RESET; break;
92
case SW_HOST_CARD_IO_ERROR: ec = GPG_ERR_EIO; break;
93
case SW_HOST_GENERAL_ERROR: ec = GPG_ERR_GENERAL; break;
94
case SW_HOST_NO_READER: ec = GPG_ERR_ENODEV; break;
95
case SW_HOST_ABORTED: ec = GPG_ERR_CANCELED; break;
99
ec = GPG_ERR_GENERAL; /* Should not happen. */
100
else if ((sw & 0xff00) == SW_MORE_DATA)
101
ec = 0; /* This should actually never been seen here. */
105
return gpg_error (ec);
108
/* Map a status word from the APDU layer to a gpg-error code. */
110
iso7816_map_sw (int sw)
112
/* All APDU functions should return 0x9000 on success but for
113
historical reasons of the implementation some return 0 to
114
indicate success. We allow for that here. */
115
return sw? map_sw (sw) : 0;
119
/* This function is specialized version of the SELECT FILE command.
120
SLOT is the card and reader as created for example by
121
apdu_open_reader (), AID is a buffer of size AIDLEN holding the
122
requested application ID. The function can't be used to enumerate
123
AIDs and won't return the AID on success. The return value is 0
124
for okay or a GPG error code. Note that ISO error codes are
125
internally mapped. */
127
iso7816_select_application (int slot, const char *aid, size_t aidlen)
130
sw = apdu_send_simple (slot, 0x00, CMD_SELECT_FILE, 4, 0, aidlen, aid);
136
iso7816_select_file (int slot, int tag, int is_dir,
137
unsigned char **result, size_t *resultlen)
140
unsigned char tagbuf[2];
142
tagbuf[0] = (tag >> 8) & 0xff;
143
tagbuf[1] = tag & 0xff;
145
if (result || resultlen)
149
return gpg_error (GPG_ERR_NOT_IMPLEMENTED);
153
p0 = (tag == 0x3F00)? 0: is_dir? 1:2;
154
p1 = 0x0c; /* No FC return. */
155
sw = apdu_send_simple (slot, 0x00, CMD_SELECT_FILE,
164
/* This is a private command currently only working for TCOS cards. */
166
iso7816_list_directory (int slot, int list_dirs,
167
unsigned char **result, size_t *resultlen)
171
if (!result || !resultlen)
172
return gpg_error (GPG_ERR_INV_VALUE);
176
sw = apdu_send (slot, 0x80, 0xAA, list_dirs? 1:2, 0, -1, NULL,
178
if (sw != SW_SUCCESS)
180
/* Make sure that pending buffers are released. */
190
/* Perform a VERIFY command on SLOT using the card holder verification
191
vector CHVNO with a CHV of lenght CHVLEN. Returns 0 on success. */
193
iso7816_verify (int slot, int chvno, const char *chv, size_t chvlen)
197
sw = apdu_send_simple (slot, 0x00, CMD_VERIFY, 0, chvno, chvlen, chv);
201
/* Perform a CHANGE_REFERENCE_DATA command on SLOT for the card holder
202
verification vector CHVNO. If the OLDCHV is NULL (and OLDCHVLEN
203
0), a "change reference data" is done, otherwise an "exchange
204
reference data". The new reference data is expected in NEWCHV of
207
iso7816_change_reference_data (int slot, int chvno,
208
const char *oldchv, size_t oldchvlen,
209
const char *newchv, size_t newchvlen)
214
if ((!oldchv && oldchvlen)
215
|| (oldchv && !oldchvlen)
216
|| !newchv || !newchvlen )
217
return gpg_error (GPG_ERR_INV_VALUE);
219
buf = xtrymalloc (oldchvlen + newchvlen);
221
return gpg_error (gpg_err_code_from_errno (errno));
223
memcpy (buf, oldchv, oldchvlen);
224
memcpy (buf+oldchvlen, newchv, newchvlen);
226
sw = apdu_send_simple (slot, 0x00, CMD_CHANGE_REFERENCE_DATA,
227
oldchvlen? 0 : 1, chvno, oldchvlen+newchvlen, buf);
234
iso7816_reset_retry_counter (int slot, int chvno,
235
const char *newchv, size_t newchvlen)
239
if (!newchv || !newchvlen )
240
return gpg_error (GPG_ERR_INV_VALUE);
242
sw = apdu_send_simple (slot, 0x00, CMD_RESET_RETRY_COUNTER,
243
2, chvno, newchvlen, newchv);
248
/* Perform a GET DATA command requesting TAG and storing the result in
249
a newly allocated buffer at the address passed by RESULT. Return
250
the length of this data at the address of RESULTLEN. */
252
iso7816_get_data (int slot, int tag,
253
unsigned char **result, size_t *resultlen)
257
if (!result || !resultlen)
258
return gpg_error (GPG_ERR_INV_VALUE);
262
sw = apdu_send (slot, 0x00, CMD_GET_DATA,
263
((tag >> 8) & 0xff), (tag & 0xff), -1, NULL,
265
if (sw != SW_SUCCESS)
267
/* Make sure that pending buffers are released. */
278
/* Perform a PUT DATA command on card in SLOT. Write DATA of length
281
iso7816_put_data (int slot, int tag,
282
const unsigned char *data, size_t datalen)
286
sw = apdu_send_simple (slot, 0x00, CMD_PUT_DATA,
287
((tag >> 8) & 0xff), (tag & 0xff),
292
/* Manage Security Environment. This is a weird operation and there
293
is no easy abstraction for it. Furthermore, some card seem to have
294
a different interpreation of 7816-8 and thus we resort to let the
295
caller decide what to do. */
297
iso7816_manage_security_env (int slot, int p1, int p2,
298
const unsigned char *data, size_t datalen)
302
if (p1 < 0 || p1 > 255 || p2 < 0 || p2 > 255 || !data || !datalen)
303
return gpg_error (GPG_ERR_INV_VALUE);
305
sw = apdu_send_simple (slot, 0x00, CMD_MSE, p1, p2, datalen, data);
310
/* Perform the security operation COMPUTE DIGITAL SIGANTURE. On
311
success 0 is returned and the data is availavle in a newly
312
allocated buffer stored at RESULT with its length stored at
315
iso7816_compute_ds (int slot, const unsigned char *data, size_t datalen,
316
unsigned char **result, size_t *resultlen)
320
if (!data || !datalen || !result || !resultlen)
321
return gpg_error (GPG_ERR_INV_VALUE);
325
sw = apdu_send (slot, 0x00, CMD_PSO, 0x9E, 0x9A, datalen, data,
327
if (sw != SW_SUCCESS)
329
/* Make sure that pending buffers are released. */
340
/* Perform the security operation DECIPHER. PADIND is the padding
341
indicator to be used. It should be 0 if no padding is required, a
342
value of -1 suppresses the padding byte. On success 0 is returned
343
and the plaintext is available in a newly allocated buffer stored
344
at RESULT with its length stored at RESULTLEN. */
346
iso7816_decipher (int slot, const unsigned char *data, size_t datalen,
347
int padind, unsigned char **result, size_t *resultlen)
352
if (!data || !datalen || !result || !resultlen)
353
return gpg_error (GPG_ERR_INV_VALUE);
359
/* We need to prepend the padding indicator. */
360
buf = xtrymalloc (datalen + 1);
362
return gpg_error (gpg_err_code_from_errno (errno));
364
*buf = padind; /* Padding indicator. */
365
memcpy (buf+1, data, datalen);
366
sw = apdu_send (slot, 0x00, CMD_PSO, 0x80, 0x86, datalen+1, buf,
372
sw = apdu_send (slot, 0x00, CMD_PSO, 0x80, 0x86, datalen, data,
375
if (sw != SW_SUCCESS)
377
/* Make sure that pending buffers are released. */
389
iso7816_internal_authenticate (int slot,
390
const unsigned char *data, size_t datalen,
391
unsigned char **result, size_t *resultlen)
395
if (!data || !datalen || !result || !resultlen)
396
return gpg_error (GPG_ERR_INV_VALUE);
400
sw = apdu_send (slot, 0x00, CMD_INTERNAL_AUTHENTICATE, 0, 0,
401
datalen, data, result, resultlen);
402
if (sw != SW_SUCCESS)
404
/* Make sure that pending buffers are released. */
416
do_generate_keypair (int slot, int readonly,
417
const unsigned char *data, size_t datalen,
418
unsigned char **result, size_t *resultlen)
422
if (!data || !datalen || !result || !resultlen)
423
return gpg_error (GPG_ERR_INV_VALUE);
427
sw = apdu_send (slot, 0x00, CMD_GENERATE_KEYPAIR, readonly? 0x81:0x80, 0,
428
datalen, data, result, resultlen);
429
if (sw != SW_SUCCESS)
431
/* Make sure that pending buffers are released. */
443
iso7816_generate_keypair (int slot,
444
const unsigned char *data, size_t datalen,
445
unsigned char **result, size_t *resultlen)
447
return do_generate_keypair (slot, 0, data, datalen, result, resultlen);
452
iso7816_read_public_key (int slot,
453
const unsigned char *data, size_t datalen,
454
unsigned char **result, size_t *resultlen)
456
return do_generate_keypair (slot, 1, data, datalen, result, resultlen);
462
iso7816_get_challenge (int slot, int length, unsigned char *buffer)
465
unsigned char *result;
468
if (!buffer || length < 1)
469
return gpg_error (GPG_ERR_INV_VALUE);
474
n = length > 254? 254 : length;
475
sw = apdu_send_le (slot, 0x00, CMD_GET_CHALLENGE, 0, 0, -1, NULL,
477
&result, &resultlen);
478
if (sw != SW_SUCCESS)
480
/* Make sure that pending buffers are released. */
486
memcpy (buffer, result, resultlen);
496
/* Perform a READ BINARY command requesting a maximum of NMAX bytes
497
from OFFSET. With NMAX = 0 the entire file is read. The result is
498
stored in a newly allocated buffer at the address passed by RESULT.
499
Returns the length of this data at the address of RESULTLEN. */
501
iso7816_read_binary (int slot, size_t offset, size_t nmax,
502
unsigned char **result, size_t *resultlen)
505
unsigned char *buffer;
507
int read_all = !nmax;
510
if (!result || !resultlen)
511
return gpg_error (GPG_ERR_INV_VALUE);
515
/* We can only encode 15 bits in p0,p1 to indicate an offset. Thus
516
we check for this limit. */
518
return gpg_error (GPG_ERR_INV_VALUE);
524
/* Fixme: Either the ccid driver or the TCOS cards have problems
526
if (read_all || nmax > 254)
530
sw = apdu_send_le (slot, 0x00, CMD_READ_BINARY,
531
((offset>>8) & 0xff), (offset & 0xff) , -1, NULL,
532
n, &buffer, &bufferlen);
534
if (sw != SW_SUCCESS && sw != SW_EOF_REACHED)
536
/* Make sure that pending buffers are released. */
543
if (*result) /* Need to extend the buffer. */
545
unsigned char *p = xtryrealloc (*result, *resultlen + bufferlen);
548
gpg_error_t err = gpg_error_from_errno (errno);
556
memcpy (*result + *resultlen, buffer, bufferlen);
557
*resultlen += bufferlen;
561
else /* Transfer the buffer into our result. */
564
*resultlen = bufferlen;
568
break; /* We simply truncate the result for too large
570
if (nmax > bufferlen)
575
while ((read_all && sw != SW_EOF_REACHED) || (!read_all && nmax));
580
/* Perform a READ RECORD command. RECNO gives the record number to
581
read with 0 indicating the current record. RECCOUNT must be 1 (not
582
all cards support reading of more than one record). SHORT_EF
583
should be 0 to read the current EF or contain a short EF. The
584
result is stored in a newly allocated buffer at the address passed
585
by RESULT. Returns the length of this data at the address of
588
iso7816_read_record (int slot, int recno, int reccount, int short_ef,
589
unsigned char **result, size_t *resultlen)
592
unsigned char *buffer;
595
if (!result || !resultlen)
596
return gpg_error (GPG_ERR_INV_VALUE);
600
/* We can only encode 15 bits in p0,p1 to indicate an offset. Thus
601
we check for this limit. */
602
if (recno < 0 || recno > 255 || reccount != 1
603
|| short_ef < 0 || short_ef > 254 )
604
return gpg_error (GPG_ERR_INV_VALUE);
608
/* Fixme: Either the ccid driver of the TCOS cards have problems
610
sw = apdu_send_le (slot, 0x00, CMD_READ_RECORD,
612
short_ef? short_ef : 0x04,
614
254, &buffer, &bufferlen);
616
if (sw != SW_SUCCESS && sw != SW_EOF_REACHED)
618
/* Make sure that pending buffers are released. */
626
*resultlen = bufferlen;