* options.h, import.c (parse_import_options, delete_inv_parts):
[gnupg.git] / scd / atr.c
1 /* atr.c - ISO 7816 ATR fucntions
2  *      Copyright (C) 2003 Free Software Foundation, Inc.
3  *
4  * This file is part of GnuPG.
5  *
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.
10  *
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.
15  *
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
19  */
20
21 #include <config.h>
22 #include <errno.h>
23 #include <stdio.h>
24 #include <stdlib.h>
25 #include <string.h>
26 #include <dlfcn.h>
27 #include <assert.h>
28
29 #include "scdaemon.h"
30 #include "apdu.h"
31 #include "atr.h"
32
33 static int const fi_table[16] = { 0, 372, 558, 744, 1116,1488, 1860, -1,
34                                   -1, 512, 768, 1024, 1536, 2048, -1, -1 };
35 static int const di_table[16] = { -1, 1, 2, 4, 8, 16, -1, -1,
36                                   0, -1, -2, -4, -8, -16, -32, -64};
37                                   
38
39 /* Dump the ATR of the card at SLOT in a human readable format to
40    stream FP.  */
41 int
42 atr_dump (int slot, FILE *fp)
43 {
44   unsigned char *atrbuffer, *atr;
45   size_t atrlen;
46   int have_ta, have_tb, have_tc, have_td;
47   int n_historical;
48   int idx, val;
49   unsigned char chksum;
50
51   atr = atrbuffer = apdu_get_atr (slot, &atrlen);
52   if (!atr)
53     return gpg_error (GPG_ERR_GENERAL);
54   
55   fprintf (fp, "Info on ATR of length %u at slot %d\n",
56            (unsigned int)atrlen, slot);
57   if (!atrlen)
58     {
59       fprintf (fp, "error: empty ATR\n");
60       goto bailout;
61     }
62
63   
64   if (*atr == 0x3b)
65     fputs ("direct convention\n", fp);
66   else if (*atr == 0x3f)
67     fputs ("inverse convention\n", fp);
68   else
69     fprintf (fp,"error: invalid TS character 0x%02x\n", *atr);
70   if (!--atrlen)
71     goto bailout;
72   atr++;
73
74   chksum = *atr;
75   for (idx=1; idx < atrlen-1; idx++)
76     chksum ^= atr[idx];
77
78   have_ta = !!(*atr & 0x10);
79   have_tb = !!(*atr & 0x20);
80   have_tc = !!(*atr & 0x40);
81   have_td = !!(*atr & 0x80);
82   n_historical = (*atr & 0x0f);
83   fprintf (fp, "%d historical characters indicated\n", n_historical);
84
85   if (have_ta + have_tb + have_tc + have_td + n_historical > atrlen)
86     fputs ("error: ATR shorter than indicated by format character\n", fp);
87   if (!--atrlen)
88     goto bailout;
89   atr++;
90
91   if (have_ta)
92     {
93       fputs ("TA1: F=", fp);
94       val = fi_table[(*atr >> 4) & 0x0f];
95       if (!val)
96         fputs ("internal clock", fp);
97       else if (val == -1)
98         fputs ("RFU", fp);
99       else
100         fprintf (fp, "%d", val);
101       fputs (" D=", fp);
102       val = di_table[*atr & 0x0f]; 
103       if (!val)
104         fputs ("[impossible value]\n", fp);
105       else if (val == -1)
106         fputs ("RFU\n", fp);
107       else if (val < 0 )
108         fprintf (fp, "1/%d\n", val);
109       else 
110         fprintf (fp, "%d\n", val);
111       
112       if (!--atrlen)
113         goto bailout;
114       atr++;
115     }
116      
117   if (have_tb)
118     {
119       fprintf (fp, "TB1: II=%d PI1=%d%s\n", (*atr >> 5) & 3, *atr & 0x1f,
120                (*atr & 0x80)? " [high bit not cleared]":"");
121       if (!--atrlen)
122         goto bailout;
123       atr++;
124     }
125
126   if (have_tc)
127     {
128       if (*atr == 255)
129         fputs ("TC1: guard time shortened to 1 etu\n", fp);
130       else
131         fprintf (fp, "TC1: (extra guard time) N=%d\n", *atr);
132
133       if (!--atrlen)
134         goto bailout;
135       atr++;
136     }
137
138   if (have_td)
139     {
140       have_ta = !!(*atr & 0x10);
141       have_tb = !!(*atr & 0x20);
142       have_tc = !!(*atr & 0x40);
143       have_td = !!(*atr & 0x80);
144       fprintf (fp, "TD1: protocol T%d supported\n", *atr & 0x0f);
145
146       if (have_ta + have_tb + have_tc + have_td + n_historical > atrlen)
147         fputs ("error: ATR shorter than indicated by format character\n", fp);
148
149       if (!--atrlen)
150         goto bailout;
151       atr++;
152     }
153   else
154     have_ta = have_tb = have_tc = have_td = 0;
155
156   if (have_ta)
157     {
158       fprintf (fp, "TA2: (PTS) %stoggle, %splicit, T=%02X\n",
159                (*atr & 0x80)? "no-":"",
160                (*atr & 0x10)? "im": "ex",
161                (*atr & 0x0f));
162       if ((*atr & 0x60))
163         fprintf (fp, "note: reserved bits are set (TA2=0x%02X)\n", *atr);
164       if (!--atrlen)
165         goto bailout;
166       atr++;
167     }
168
169   if (have_tb)
170     {
171       fprintf (fp, "TB2: PI2=%d\n", *atr);
172       if (!--atrlen)
173         goto bailout;
174       atr++;
175     }
176
177   if (have_tc)
178     {
179       fprintf (fp, "TC2: PWI=%d\n", *atr);
180       if (!--atrlen)
181         goto bailout;
182       atr++;
183     }
184
185   if (have_td)
186     {
187       have_ta = !!(*atr & 0x10);
188       have_tb = !!(*atr & 0x20);
189       have_tc = !!(*atr & 0x40);
190       have_td = !!(*atr & 0x80);
191       fprintf (fp, "TD2: protocol T%d supported\n", *atr & 0x0f);
192
193       if (have_ta + have_tb + have_tc + have_td + n_historical > atrlen)
194         fputs ("error: ATR shorter than indicated by format character\n", fp);
195
196       if (!--atrlen)
197         goto bailout;
198       atr++;
199     }
200   else
201     have_ta = have_tb = have_tc = have_td = 0;
202
203   for (idx = 3; have_ta || have_tb || have_tc || have_td; idx++)
204     {
205       if (have_ta)
206         {
207           fprintf (fp, "TA%d: IFSC=%d\n", idx, *atr);
208           if (!--atrlen)
209             goto bailout;
210           atr++;
211         }
212
213       if (have_tb)
214         {
215           fprintf (fp, "TB%d: BWI=%d CWI=%d\n",
216                    idx, (*atr >> 4) & 0x0f, *atr & 0x0f);
217           if (!--atrlen)
218             goto bailout;
219           atr++;
220         }
221
222       if (have_tc)
223         {
224           fprintf (fp, "TC%d: 0x%02X\n", idx, *atr);
225           if (!--atrlen)
226             goto bailout;
227           atr++;
228         }
229
230       if (have_td)
231         {
232           have_ta = !!(*atr & 0x10);
233           have_tb = !!(*atr & 0x20);
234           have_tc = !!(*atr & 0x40);
235           have_td = !!(*atr & 0x80);
236           fprintf (fp, "TD%d: protocol T%d supported\n", idx, *atr & 0x0f);
237
238           if (have_ta + have_tb + have_tc + have_td + n_historical > atrlen)
239             fputs ("error: ATR shorter than indicated by format character\n",
240                    fp);
241
242           if (!--atrlen)
243             goto bailout;
244           atr++;
245         }
246       else
247         have_ta = have_tb = have_tc = have_td = 0;
248     }
249
250   if (n_historical + 1 > atrlen)
251     fputs ("error: ATR shorter than required for historical bytes "
252            "and checksum\n", fp);
253   
254   if (n_historical)
255     {
256       fputs ("Historical:", fp);
257       for (; n_historical && atrlen ; n_historical--, atrlen--, atr++)
258         fprintf (fp, " %02X", *atr);
259       putchar ('\n');
260     }
261
262   if (!atrlen)
263     fputs ("error: checksum missing\n", fp);
264   else if (*atr == chksum)
265     fprintf (fp, "TCK: %02X (good)\n", *atr);
266   else
267     fprintf (fp, "TCK: %02X (bad; calculated %02X)\n", *atr, chksum);
268
269   atrlen--;
270   if (atrlen)
271     fprintf (fp, "error: %u bytes garbage at end of ATR\n",
272              (unsigned int)atrlen );
273
274  bailout:
275   xfree (atrbuffer);
276
277   return 0;
278 }
279
280
281
282
283
284
285
286
287