Branch data Line data Source code
1 : : /*
2 : : * implement the ACA applet for the CAC card.
3 : : *
4 : : * Adaptation to GSC-IS 2.1:
5 : : * https://nvlpubs.nist.gov/nistpubs/Legacy/IR/nistir6887e2003.pdf
6 : : *
7 : : * Copyright 2018 Red Hat, Inc.
8 : : *
9 : : * Author: Jakub Jelen <jjelen@redhat.com>
10 : : *
11 : : * This code is licensed under the GNU LGPL, version 2.1 or later.
12 : : * See the COPYING file in the top-level directory.
13 : : */
14 : :
15 : : #include <glib.h>
16 : :
17 : : #include "card_7816t.h"
18 : : #include "card_7816.h"
19 : : #include "common.h"
20 : : #include "cac-aca.h"
21 : : #include "simpletlv.h"
22 : :
23 : : #include <string.h>
24 : :
25 : : #define MAX_ACCESS_METHODS 2
26 : :
27 : : /* From Table 3-2 */
28 : : enum ACRType {
29 : : ACR_ALWAYS = 0x00,
30 : : ACR_NEVER = 0x01,
31 : : ACR_XAUTH = 0x02,
32 : : ACR_XAUTH_OR_PIN = 0x03,
33 : : ACR_SECURE_CHANNEL_GP = 0x04,
34 : : ACR_ACR_PIN_ALWAYS = 0x05,
35 : : ACR_PIN = 0x06,
36 : : ACR_XAUTH_THEN_PIN = 0x07,
37 : : ACR_UPDATE_ONCE = 0x08,
38 : : ACR_PIN_THEN_XAUTH = 0x09,
39 : : /* RFU = 0x0A,*/
40 : : ACR_SECURE_CHANNEL_ISO = 0x0B,
41 : : ACR_XAUTH_AND_PIN = 0x0C
42 : : };
43 : :
44 : : /*
45 : : * ACR table:
46 : : * This table maps the Access Control Rule Type (ACRType) and Access Method
47 : : * information to the Access Control Rule Identifier (ACRID) for each
48 : : * Access Control Rule.
49 : : * (from 5.3.3.5 Get ACR APDU, Table 5-15)
50 : : */
51 : : struct acr_access_method {
52 : : unsigned char provider_id;
53 : : unsigned char keyIDOrReference;
54 : : };
55 : : struct acr_entry {
56 : : unsigned char acrid;
57 : : unsigned char acrtype;
58 : : /* No idea what does this mean, but it is used in the extended properties */
59 : : unsigned char applet_id;
60 : : unsigned int num_access_methods;
61 : : struct acr_access_method access_methods[MAX_ACCESS_METHODS];
62 : : };
63 : : struct acr_table {
64 : : unsigned char num_entries;
65 : : struct acr_entry entries[];
66 : : };
67 : :
68 : : /*
69 : : * Example:
70 : : * 01 05 TL: Applet family + Applet Version
71 : : * 10 02 06 02 02 (1B) (4B)
72 : : * A1 01 TL: Number of ACR entries (unique ACRID)
73 : : * 0B V: 11
74 : : * A0 03 TL: First ACR entry
75 : : * 00 V: ACRID of ACR entry
76 : : * 00 V: ACRType: BSI_ACR_ALWAYS
77 : : * 00 V: Number of AccessMethods in this ACR
78 : : * A0 03
79 : : * 01 V: ACRID of ACR entry
80 : : * 01 V: ACRType: BSI_ACR_NEVER
81 : : * 00 V: Number of AccessMethods in this ACR
82 : : * A0 03
83 : : * 02 V: ACRID of ACR entry
84 : : * 00 V: ACRType: BSI_ACR_ALWAYS
85 : : * 00 V: Number of AccessMethods in this ACR
86 : : * A0 05 TL: Next ACR entry
87 : : * 06 V: ACRID of ACR entry
88 : : * 06 V: ACRType: BSI_ACR_PIN
89 : : * 01 V: Number of AccessMethods in this ACR
90 : : * 1E V: First AccessMethodProviderID -- PIN ???
91 : : * 00 V: First keyIDOrReference -- id 00 ?
92 : : * A0 05
93 : : * 04 V: ACRID of ACR entry
94 : : * 04 V: ACRType: BSI_SECURE_CHANNEL_GP
95 : : * 01 V: Number of AccessMethods in this ACR
96 : : * 1F V: First AccessMethodProviderID -- SC ???
97 : : * 21 V: First keyIDOrReference -- ref 21 ??
98 : : * A0 07
99 : : * 08 V: ACRID of ACR entry
100 : : * 03 V: ACRType: BSI_ACR_XAUTH_OR_PIN
101 : : * 02 V: Number of AccessMethods in this ACR
102 : : * 1D V: First AccessMethodProviderID -- XAUTH ???
103 : : * 01 V: First keyIDOrReference -- ref 01 ??
104 : : * 1E V: Last AccessMethodProviderID -- PIN ???
105 : : * 01 V: Last keyIDOrReference -- id 01 ?
106 : : * A0 05
107 : : * 09 V: ACRID of ACR entry
108 : : * 02 V: ACRType: BSI_ACR_XAUTH
109 : : * 01 V: Number of AccessMethods in this ACR
110 : : * 1D V: First AccessMethodProviderID -- XAUTH ???
111 : : * 02 V: First keyIDOrReference -- ref 02 ??
112 : : * A0 07
113 : : * 0A V: ACRID of ACR entry
114 : : * 03 V: ACRType: BSI_ACR_XAUTH_OR_PIN
115 : : * 02 V: Number of AccessMethods in this ACR
116 : : * 1D V: First AccessMethodProviderID -- XAUTH ???
117 : : * 03 V: First keyIDOrReference -- ref 03 ??
118 : : * 1E V: Last AccessMethodProviderID -- PIN ???
119 : : * 01 V: Last keyIDOrReference -- id 01 ?
120 : : * A0 05
121 : : * 0B V: ACRID of ACR entry
122 : : * 02 V: ACRType: BSI_ACR_XAUTH
123 : : * 01 V: Number of AccessMethods in this ACR
124 : : * 1D V: First AccessMethodProviderID -- XAUTH ???
125 : : * 04 V: First keyIDOrReference -- ref 04 ??
126 : : * A0 03
127 : : * 10 V: ACRID of ACR entry
128 : : * 00 V: ACRType: BSI_ACR_ALWAYS
129 : : * 00 V: Number of AccessMethods in this ACR
130 : : * A0 03
131 : : * 11 V: ACRID of ACR entry
132 : : * 00 V: ACRType: BSI_ACR_ALWAYS
133 : : * 00 V: Number of AccessMethods in this ACR
134 : : */
135 : : static const struct acr_table acr_table = {
136 : : 11, {
137 : : {0x00, ACR_ALWAYS, 0x00, 0, {}},
138 : : {0x01, ACR_NEVER, 0x00, 0, {}},
139 : : {0x02, ACR_ALWAYS, 0x1F, 0, {}},
140 : : {0x06, ACR_PIN, 0x00, 1, {
141 : : {0x1E, 0x00}
142 : : }},
143 : : {0x04, ACR_SECURE_CHANNEL_GP, 0x1F, 1, {
144 : : {0x1F, 0x21}
145 : : }},
146 : : {0x08, ACR_XAUTH_OR_PIN, 0x00, 2, {
147 : : {0x1D, 0x01},
148 : : {0x1E, 0x01}
149 : : }},
150 : : {0x09, ACR_XAUTH, 0x00, 1, {
151 : : {0x1D, 0x01}
152 : : }},
153 : : {0x0A, ACR_XAUTH_OR_PIN, 0x00, 2, {
154 : : {0x1D, 0x03},
155 : : {0x1E, 0x01}
156 : : }},
157 : : {0x0B, ACR_XAUTH, 0x00, 1, {
158 : : {0x1D, 0x0}
159 : : }},
160 : : {0x10, ACR_ALWAYS, 0x1E, 0, {}},
161 : : {0x11, ACR_ALWAYS, 0x1D, 0, {}},
162 : : }
163 : : };
164 : :
165 : : static struct simpletlv_member *
166 : 3 : cac_aca_get_acr(size_t *acr_len, unsigned char *acrid)
167 : : {
168 : : struct simpletlv_member *r;
169 : : size_t i;
170 : : int j = 0;
171 : :
172 [ - + - + ]: 3 : g_return_val_if_fail(acr_len != NULL, NULL);
173 : :
174 [ + + ]: 3 : if (acrid != NULL) {
175 : 2 : r = g_malloc(sizeof(struct simpletlv_member));
176 : : } else {
177 : 1 : r = g_malloc_n(acr_table.num_entries + 1, sizeof(struct simpletlv_member));
178 : :
179 : 1 : r[j].tag = CAC_ACR_NUM_ENTRIES;
180 : 1 : r[j].length = 1;
181 : 1 : r[j].value.value = (unsigned char *) &acr_table.num_entries;
182 : 1 : r[j].type = SIMPLETLV_TYPE_LEAF;
183 : : j++;
184 : : }
185 [ + + ]: 36 : for (i = 0; i < acr_table.num_entries; i++) {
186 [ + + + + ]: 33 : if (acrid != NULL && *acrid != acr_table.entries[i].acrid)
187 : 21 : continue;
188 : :
189 : 12 : r[j].tag = CAC_ACR_ENTRY;
190 : 12 : r[j].length = 2*acr_table.entries[i].num_access_methods+3;
191 : 12 : r[j].value.value = (unsigned char *) &acr_table.entries[i];
192 : 12 : r[j].type = SIMPLETLV_TYPE_LEAF;
193 : 12 : j++;
194 : : }
195 [ + + ]: 3 : if (j <= 0) {
196 : : /* we did not find the requested ACRID */
197 : 1 : g_free(r);
198 : : r = NULL;
199 : : }
200 : 3 : *acr_len = j;
201 : 3 : return r;
202 : : }
203 : :
204 : : /*
205 : : * Service Applet Table:
206 : : * This table maps the Service Applet ID to the full AID for each
207 : : * Service Applet.
208 : : * (from 5.3.3.5 Get ACR APDU, Table 5-21)
209 : : */
210 : :
211 : : #define MAX_AID_LEN 7
212 : :
213 : : struct applet_entry {
214 : : unsigned char applet_id;
215 : : unsigned int applet_aid_len;
216 : : unsigned char applet_aid[MAX_AID_LEN];
217 : : };
218 : : struct service_applet_table {
219 : : unsigned num_entries;
220 : : unsigned num_static_entries;
221 : : struct applet_entry entries[];
222 : : };
223 : :
224 : : /* Example:
225 : : * 01 05 TL: Applet Information
226 : : * 10 02 06 02 02
227 : : * 94 01 TL: Number of Applet Entries
228 : : * 0F
229 : : * 93 0A TL: Applet entry
230 : : * 40 Applet ID
231 : : * 92 07 TL: Applet AID
232 : : * A0 00 00 01 16 30 00
233 : : * 93 0A
234 : : * 4F
235 : : * 92 07
236 : : * A0 00 00 01 16 DB 00
237 : : * 93 0A
238 : : * 4B
239 : : * 92 07
240 : : * A0 00 00 00 79 02 FB
241 : : * 93 0A
242 : : * 41
243 : : * 92 07
244 : : * A0 00 00 00 79 02 00
245 : : * 93 0A
246 : : * 42
247 : : * 92 07
248 : : * A0 00 00 00 79 02 01
249 : : * 93 0A
250 : : * 4E
251 : : * 92 07
252 : : * A0 00 00 00 79 02 FE
253 : : * 93 0A
254 : : * 4D
255 : : * 92 07
256 : : * A0 00 00 00 79 02 FD
257 : : * 93 0A
258 : : * 50
259 : : * 92 07
260 : : * A0 00 00 00 79 02 F2
261 : : * 93 0A
262 : : * 63
263 : : * 92 07
264 : : * A0 00 00 00 79 01 02
265 : : * 93 0A
266 : : * 51
267 : : * 92 07
268 : : * A0 00 00 00 79 02 F0
269 : : * 93 0A
270 : : * 61
271 : : * 92 07
272 : : * A0 00 00 00 79 01 00
273 : : * 93 0A
274 : : * 52
275 : : * 92 07
276 : : * A0 00 00 00 79 02 F1
277 : : * 93 0A
278 : : * 62
279 : : * 92 07
280 : : * A0 00 00 00 79 01 01
281 : : * 93 0A
282 : : * 44
283 : : * 92 07
284 : : * A0 00 00 00 79 12 01
285 : : * 93 0A
286 : : * 45
287 : : * 92 07
288 : : * A0 00 00 00 79 12 02
289 : : */
290 : :
291 : : static const struct service_applet_table service_table = {
292 : : 22, 12, {
293 : : /* Variable PKI applets entries */
294 : : {0x61, 7, "\xA0\x00\x00\x00\x79\x01\x00"},
295 : : {0x62, 7, "\xA0\x00\x00\x00\x79\x01\x01"},
296 : : {0x63, 7, "\xA0\x00\x00\x00\x79\x01\x02"},
297 : : {0x64, 7, "\xA0\x00\x00\x00\x79\x01\x03"},
298 : : {0x65, 7, "\xA0\x00\x00\x00\x79\x01\x04"},
299 : : {0x66, 7, "\xA0\x00\x00\x00\x79\x01\x05"},
300 : : {0x67, 7, "\xA0\x00\x00\x00\x79\x01\x06"},
301 : : {0x68, 7, "\xA0\x00\x00\x00\x79\x01\x07"},
302 : : {0x69, 7, "\xA0\x00\x00\x00\x79\x01\x08"},
303 : : {0x6a, 7, "\xA0\x00\x00\x00\x79\x01\x09"},
304 : : /* static applet entries */
305 : : {0x40, 7, "\xA0\x00\x00\x01\x16\x30\x00"},
306 : : {0x4F, 7, "\xA0\x00\x00\x01\x16\xDB\x00"},
307 : : {0x4B, 7, "\xA0\x00\x00\x00\x79\x02\xFB"},
308 : : {0x41, 7, "\xA0\x00\x00\x00\x79\x02\x00"},
309 : : {0x42, 7, "\xA0\x00\x00\x00\x79\x02\x01"},
310 : : {0x4E, 7, "\xA0\x00\x00\x00\x79\x02\xFE"},
311 : : {0x4D, 7, "\xA0\x00\x00\x00\x79\x02\xFD"},
312 : : {0x50, 7, "\xA0\x00\x00\x00\x79\x02\xF2"},
313 : : {0x51, 7, "\xA0\x00\x00\x00\x79\x02\xF0"},
314 : : {0x52, 7, "\xA0\x00\x00\x00\x79\x02\xF1"},
315 : : {0x44, 7, "\xA0\x00\x00\x00\x79\x12\x01"},
316 : : {0x45, 7, "\xA0\x00\x00\x00\x79\x12\x02"},
317 : : }
318 : : };
319 : :
320 : : static struct simpletlv_member *
321 : 87 : cac_aca_get_service_table(size_t *r_len, unsigned int pki_applets)
322 : : {
323 : : struct simpletlv_member *r = NULL;
324 : : unsigned char *num_entries_byte = NULL;
325 : : unsigned char *entry = NULL;
326 : : size_t i, j = 0;
327 : : unsigned int num_entries;
328 : :
329 [ - + - + ]: 87 : g_return_val_if_fail(r_len != NULL, NULL);
330 : :
331 : 87 : num_entries = service_table.num_static_entries + pki_applets;
332 : 87 : r = g_malloc_n(num_entries + 1, sizeof(struct simpletlv_member));
333 : :
334 : 87 : num_entries_byte = g_malloc(1);
335 : 87 : *num_entries_byte = num_entries;
336 : :
337 : 87 : r[0].type = SIMPLETLV_TYPE_LEAF;
338 : 87 : r[0].tag = CAC_ACR_SERVICE_NUM_ENTRIES;
339 : 87 : r[0].length = 1;
340 : 87 : r[0].value.value = num_entries_byte;
341 : : j = 1;
342 [ + + ]: 2001 : for (i = 0; i < service_table.num_entries; i++) {
343 : : /* Skip unused PKI applets */
344 [ + + + + ]: 1914 : if (i >= pki_applets && i < 10)
345 : 609 : continue;
346 : :
347 : 1305 : r[j].type = SIMPLETLV_TYPE_LEAF;
348 : 1305 : r[j].tag = CAC_ACR_SERVICE_ENTRY;
349 : 1305 : r[j].length = service_table.entries[i].applet_aid_len + 3;
350 : 1305 : entry = g_malloc(r[j].length);
351 : 1305 : entry[0] = service_table.entries[i].applet_id;
352 : 1305 : entry[1] = CAC_ACR_AID;
353 : 1305 : entry[2] = service_table.entries[i].applet_aid_len;
354 : 1305 : memcpy(&entry[3], (unsigned char *) &service_table.entries[i],
355 : : service_table.entries[i].applet_aid_len);
356 : 1305 : r[j].value.value = entry;
357 : 1305 : j++;
358 : : }
359 [ - + ]: 87 : g_assert_cmpint(j, ==, num_entries + 1);
360 : :
361 : 87 : *r_len = j;
362 : 87 : return r;
363 : : }
364 : :
365 : : /*
366 : : * Object/Applet ACR Table:
367 : : * This table maps the service (INS code/P1 byte/P2 byte/1 st data byte)
368 : : * to the ACRID for each container.
369 : : * (from 5.3.3.5 Get ACR APDU, Table 5-16)
370 : : *
371 : : * Can be pulled from existing card using the OpenSC:
372 : : * $ opensc-tool -s 00A4040007A0000000790300 -s 804C100000
373 : : */
374 : :
375 : : enum {
376 : : ACR_INS_CONFIG_NONE = 0x00,
377 : : ACR_INS_CONFIG_P1 = 0x01,
378 : : ACR_INS_CONFIG_P2 = 0x02,
379 : : ACR_INS_CONFIG_DATA1 = 0x04,
380 : : };
381 : :
382 : : #define ACR_MAX_INSTRUCTIONS 5
383 : : #define ACR_MAX_APPLET_OBJECTS 5
384 : :
385 : : struct cac_ins {
386 : : unsigned char code;
387 : : unsigned char acrid;
388 : : unsigned char config;
389 : : unsigned char p1;
390 : : unsigned char p2;
391 : : unsigned char data1;
392 : : };
393 : : struct acr_object {
394 : : unsigned char id[2];
395 : : unsigned int num_ins;
396 : : struct cac_ins ins[ACR_MAX_INSTRUCTIONS];
397 : : };
398 : : struct acr_applet {
399 : : unsigned char id;
400 : : unsigned int num_objects;
401 : : struct acr_object objects[ACR_MAX_APPLET_OBJECTS];
402 : : };
403 : : struct acr_applets {
404 : : unsigned int num_applets;
405 : : unsigned int num_static_applets;
406 : : struct acr_applet applets[];
407 : : };
408 : :
409 : : /* Example:
410 : : * 01 05 TL: Applet Information
411 : : * 10 02 06 02 02
412 : : * 81 01 TL: Number of applets managed by this ACA
413 : : * 10
414 : : * 80 09 TL: Card Applet ACR
415 : : * 1F Applet ID
416 : : * 01 Number of objects managed by this applet
417 : : * 82 05 TL: Card Object ACR
418 : : * FF FF Card Object ID
419 : : * 20 INS1 code
420 : : * 00 INS1 configuration definition
421 : : * 00 ACRID
422 : : * 80 1A TL: Card Applet ACR
423 : : * 4F Applet ID
424 : : * 02 Number of objects managed by this applet
425 : : * 82 08 TL: Card Object ACR
426 : : * DB 00 Card Object ID: CCC
427 : : * 58 INS1: Update Buffer
428 : : * 00 config: none
429 : : * 04 ACRID: (ID from ACR Table)
430 : : * 52 INS2: Read Buffer
431 : : * 00 config: none
432 : : * 00 ACRID: (ID from ACR Table)
433 : : * 82 0C TL: Card Object ACR
434 : : * FF FF Card Object ID
435 : : * 82 INS1 code
436 : : * 01 config
437 : : * 00 P1 Value
438 : : * 11 ACRID
439 : : * 84 INS2 code
440 : : * 00 INS2 config
441 : : * 11 ACRID
442 : : * 20 INS3 code
443 : : * 00 INS3 config
444 : : * 10 ACRID
445 : : * [...]
446 : : */
447 : :
448 : : static const struct acr_applets applets_table = {
449 : : 23, 13, {
450 : : /* Dynamic PKI applets */
451 : : {0x61, 2, {
452 : : {"\x01\x00", 3, {
453 : : {CAC_UPDATE_BUFFER, 0x04, .config = ACR_INS_CONFIG_NONE},
454 : : {CAC_READ_BUFFER, 0x00, .config = ACR_INS_CONFIG_NONE},
455 : : {CAC_SIGN_DECRYPT, 0x06, .config = ACR_INS_CONFIG_NONE}
456 : : }},
457 : : {"\xFF\xFF", 1, {
458 : : {VCARD7816_INS_VERIFY, 0x10, .config = ACR_INS_CONFIG_NONE},
459 : : }}
460 : : }},
461 : : {0x62, 2, {
462 : : {"\x01\x01", 3, {
463 : : {CAC_UPDATE_BUFFER, 0x04, .config = ACR_INS_CONFIG_NONE},
464 : : {CAC_READ_BUFFER, 0x00, .config = ACR_INS_CONFIG_NONE},
465 : : {CAC_SIGN_DECRYPT, 0x06, .config = ACR_INS_CONFIG_NONE}
466 : : }},
467 : : {"\xFF\xFF", 1, {
468 : : {VCARD7816_INS_VERIFY, 0x10, .config = ACR_INS_CONFIG_NONE},
469 : : }}
470 : : }},
471 : : {0x63, 2, {
472 : : {"\x01\x02", 3, {
473 : : {CAC_UPDATE_BUFFER, 0x04, .config = ACR_INS_CONFIG_NONE},
474 : : {CAC_READ_BUFFER, 0x00, .config = ACR_INS_CONFIG_NONE},
475 : : {CAC_SIGN_DECRYPT, 0x06, .config = ACR_INS_CONFIG_NONE}
476 : : }},
477 : : {"\xFF\xFF", 1, {
478 : : {VCARD7816_INS_VERIFY, 0x10, .config = ACR_INS_CONFIG_NONE},
479 : : }}
480 : : }},
481 : : {0x64, 2, {
482 : : {"\x01\x03", 3, {
483 : : {CAC_UPDATE_BUFFER, 0x04, .config = ACR_INS_CONFIG_NONE},
484 : : {CAC_READ_BUFFER, 0x00, .config = ACR_INS_CONFIG_NONE},
485 : : {CAC_SIGN_DECRYPT, 0x06, .config = ACR_INS_CONFIG_NONE}
486 : : }},
487 : : {"\xFF\xFF", 1, {
488 : : {VCARD7816_INS_VERIFY, 0x10, .config = ACR_INS_CONFIG_NONE},
489 : : }}
490 : : }},
491 : : {0x65, 2, {
492 : : {"\x01\x04", 3, {
493 : : {CAC_UPDATE_BUFFER, 0x04, .config = ACR_INS_CONFIG_NONE},
494 : : {CAC_READ_BUFFER, 0x00, .config = ACR_INS_CONFIG_NONE},
495 : : {CAC_SIGN_DECRYPT, 0x06, .config = ACR_INS_CONFIG_NONE}
496 : : }},
497 : : {"\xFF\xFF", 1, {
498 : : {VCARD7816_INS_VERIFY, 0x10, .config = ACR_INS_CONFIG_NONE},
499 : : }}
500 : : }},
501 : : {0x66, 2, {
502 : : {"\x01\x05", 3, {
503 : : {CAC_UPDATE_BUFFER, 0x04, .config = ACR_INS_CONFIG_NONE},
504 : : {CAC_READ_BUFFER, 0x00, .config = ACR_INS_CONFIG_NONE},
505 : : {CAC_SIGN_DECRYPT, 0x06, .config = ACR_INS_CONFIG_NONE}
506 : : }},
507 : : {"\xFF\xFF", 1, {
508 : : {VCARD7816_INS_VERIFY, 0x10, .config = ACR_INS_CONFIG_NONE},
509 : : }}
510 : : }},
511 : : {0x67, 2, {
512 : : {"\x01\x06", 3, {
513 : : {CAC_UPDATE_BUFFER, 0x04, .config = ACR_INS_CONFIG_NONE},
514 : : {CAC_READ_BUFFER, 0x00, .config = ACR_INS_CONFIG_NONE},
515 : : {CAC_SIGN_DECRYPT, 0x06, .config = ACR_INS_CONFIG_NONE}
516 : : }},
517 : : {"\xFF\xFF", 1, {
518 : : {VCARD7816_INS_VERIFY, 0x10, .config = ACR_INS_CONFIG_NONE},
519 : : }}
520 : : }},
521 : : {0x68, 2, {
522 : : {"\x01\x07", 3, {
523 : : {CAC_UPDATE_BUFFER, 0x04, .config = ACR_INS_CONFIG_NONE},
524 : : {CAC_READ_BUFFER, 0x00, .config = ACR_INS_CONFIG_NONE},
525 : : {CAC_SIGN_DECRYPT, 0x06, .config = ACR_INS_CONFIG_NONE}
526 : : }},
527 : : {"\xFF\xFF", 1, {
528 : : {VCARD7816_INS_VERIFY, 0x10, .config = ACR_INS_CONFIG_NONE},
529 : : }}
530 : : }},
531 : : {0x69, 2, {
532 : : {"\x01\x08", 3, {
533 : : {CAC_UPDATE_BUFFER, 0x04, .config = ACR_INS_CONFIG_NONE},
534 : : {CAC_READ_BUFFER, 0x00, .config = ACR_INS_CONFIG_NONE},
535 : : {CAC_SIGN_DECRYPT, 0x06, .config = ACR_INS_CONFIG_NONE}
536 : : }},
537 : : {"\xFF\xFF", 1, {
538 : : {VCARD7816_INS_VERIFY, 0x10, .config = ACR_INS_CONFIG_NONE},
539 : : }}
540 : : }},
541 : : {0x6a, 2, {
542 : : {"\x01\x09", 3, {
543 : : {CAC_UPDATE_BUFFER, 0x04, .config = ACR_INS_CONFIG_NONE},
544 : : {CAC_READ_BUFFER, 0x00, .config = ACR_INS_CONFIG_NONE},
545 : : {CAC_SIGN_DECRYPT, 0x06, .config = ACR_INS_CONFIG_NONE}
546 : : }},
547 : : {"\xFF\xFF", 1, {
548 : : {VCARD7816_INS_VERIFY, 0x10, .config = ACR_INS_CONFIG_NONE},
549 : : }}
550 : : }},
551 : : /* Static applets */
552 : : {0x1F, 1, {
553 : : {"\xFF\xFF", 1, {
554 : : {VCARD7816_INS_VERIFY, 0x00, .config = ACR_INS_CONFIG_NONE}
555 : : }}
556 : : }},
557 : : {0xF4, 2, {
558 : : {"\xDB\x00", 2, {
559 : : {CAC_UPDATE_BUFFER, 0x04, .config = ACR_INS_CONFIG_NONE},
560 : : {CAC_READ_BUFFER, 0x00, .config = ACR_INS_CONFIG_NONE}
561 : : }},
562 : : {"\xFF\xFF", 3, {
563 : : {VCARD7816_INS_EXTERNAL_AUTHENTICATE, 0x11, .config = ACR_INS_CONFIG_P1, .p1 = 0x00},
564 : : {VCARD7816_INS_GET_CHALLENGE, 0x11, .config = ACR_INS_CONFIG_NONE},
565 : : {VCARD7816_INS_VERIFY, 0x10, .config = ACR_INS_CONFIG_NONE},
566 : : }}
567 : : }},
568 : : {0x4B, 2, {
569 : : {"\x02\xFB", 2, {
570 : : {CAC_UPDATE_BUFFER, 0x06, .config = ACR_INS_CONFIG_NONE},
571 : : {CAC_READ_BUFFER, 0x00, .config = ACR_INS_CONFIG_NONE}
572 : : }},
573 : : {"\xFF\xFF", 3, {
574 : : {VCARD7816_INS_EXTERNAL_AUTHENTICATE, 0x11, .config = ACR_INS_CONFIG_P1, .p1 = 0x00},
575 : : {VCARD7816_INS_GET_CHALLENGE, 0x11, .config = ACR_INS_CONFIG_NONE},
576 : : {VCARD7816_INS_VERIFY, 0x10, .config = ACR_INS_CONFIG_NONE},
577 : : }}
578 : : }},
579 : : {0x41, 2, {
580 : : {"\x02\x00", 3, {
581 : : {CAC_UPDATE_BUFFER, 0x09, .config = ACR_INS_CONFIG_NONE},
582 : : {CAC_READ_BUFFER, 0x00, .config = ACR_INS_CONFIG_DATA1, .data1 = 0x01},
583 : : {CAC_READ_BUFFER, 0x08, .config = ACR_INS_CONFIG_NONE}
584 : : }},
585 : : {"\xFF\xFF", 3, {
586 : : {VCARD7816_INS_EXTERNAL_AUTHENTICATE, 0x11, .config = ACR_INS_CONFIG_P1, .p1 = 0x00},
587 : : {VCARD7816_INS_GET_CHALLENGE, 0x11, .config = ACR_INS_CONFIG_NONE},
588 : : {VCARD7816_INS_VERIFY, 0x10, .config = ACR_INS_CONFIG_NONE},
589 : : }}
590 : : }},
591 : : {0x42, 2, {
592 : : {"\x02\x01", 3, {
593 : : {CAC_UPDATE_BUFFER, 0x0B, .config = ACR_INS_CONFIG_NONE},
594 : : {CAC_READ_BUFFER, 0x00, .config = ACR_INS_CONFIG_DATA1, .data1=0x01},
595 : : {CAC_READ_BUFFER, 0x0A, .config = ACR_INS_CONFIG_NONE}
596 : : }},
597 : : {"\xFF\xFF", 3, {
598 : : {VCARD7816_INS_EXTERNAL_AUTHENTICATE, 0x11, .config = ACR_INS_CONFIG_P1, .p1 = 0x00},
599 : : {VCARD7816_INS_GET_CHALLENGE, 0x11, .config = ACR_INS_CONFIG_NONE},
600 : : {VCARD7816_INS_VERIFY, 0x10, .config = ACR_INS_CONFIG_NONE},
601 : : }}
602 : : }},
603 : : {0x40, 5, {
604 : : {"\x30\x00", 3, {
605 : : {CAC_UPDATE_BUFFER, 0x04, .config = ACR_INS_CONFIG_NONE},
606 : : {CAC_READ_BUFFER, 0x00, .config = ACR_INS_CONFIG_NONE},
607 : : {VCARD7816_INS_READ_BINARY, 0x00, .config = ACR_INS_CONFIG_NONE}
608 : : }},
609 : : {"\x60\x10", 3, {
610 : : {CAC_UPDATE_BUFFER, 0x04, .config = ACR_INS_CONFIG_NONE},
611 : : {CAC_READ_BUFFER, 0x00, .config = ACR_INS_CONFIG_DATA1, .data1 = 0x01},
612 : : {CAC_READ_BUFFER, 0x06, .config = ACR_INS_CONFIG_NONE}
613 : : }},
614 : : {"\x60\x30", 3, {
615 : : {CAC_UPDATE_BUFFER, 0x04, .config = ACR_INS_CONFIG_NONE},
616 : : {CAC_READ_BUFFER, 0x00, .config = ACR_INS_CONFIG_DATA1, .data1 = 0x01},
617 : : {CAC_READ_BUFFER, 0x06, .config = ACR_INS_CONFIG_NONE}
618 : : }},
619 : : {"\x90\x00", 2, {
620 : : {CAC_UPDATE_BUFFER, 0x04, .config = ACR_INS_CONFIG_NONE},
621 : : {CAC_READ_BUFFER, 0x00, .config = ACR_INS_CONFIG_NONE}
622 : : }},
623 : : {"\xFF\xFF", 3, {
624 : : {VCARD7816_INS_EXTERNAL_AUTHENTICATE, 0x11, .config = ACR_INS_CONFIG_P1, .p1 = 0x00},
625 : : {VCARD7816_INS_GET_CHALLENGE, 0x11, .config = ACR_INS_CONFIG_NONE},
626 : : {VCARD7816_INS_VERIFY, 0x10, .config = ACR_INS_CONFIG_NONE},
627 : : }}
628 : : }},
629 : : {0x4e, 2, {
630 : : {"\x02\xFE", 2, {
631 : : {CAC_UPDATE_BUFFER, 0x04, .config = ACR_INS_CONFIG_NONE},
632 : : {CAC_READ_BUFFER, 0x00, .config = ACR_INS_CONFIG_NONE}
633 : : }},
634 : : {"\xFF\xFF", 3, {
635 : : {VCARD7816_INS_EXTERNAL_AUTHENTICATE, 0x11, .config = ACR_INS_CONFIG_P1, .p1 = 0x00},
636 : : {VCARD7816_INS_GET_CHALLENGE, 0x11, .config = ACR_INS_CONFIG_NONE},
637 : : {VCARD7816_INS_VERIFY, 0x10, .config = ACR_INS_CONFIG_NONE},
638 : : }}
639 : : }},
640 : : {0x4d, 2, {
641 : : {"\x02\xFD", 3, {
642 : : {CAC_UPDATE_BUFFER, 0x06, .config = ACR_INS_CONFIG_NONE},
643 : : {CAC_READ_BUFFER, 0x00, .config = ACR_INS_CONFIG_DATA1, .data1 = 0x01},
644 : : {CAC_READ_BUFFER, 0x06, .config = ACR_INS_CONFIG_NONE}
645 : : }},
646 : : {"\xFF\xFF", 3, {
647 : : {VCARD7816_INS_EXTERNAL_AUTHENTICATE, 0x11, .config = ACR_INS_CONFIG_P1, .p1 = 0x00},
648 : : {VCARD7816_INS_GET_CHALLENGE, 0x11, .config = ACR_INS_CONFIG_NONE},
649 : : {VCARD7816_INS_VERIFY, 0x10, .config = ACR_INS_CONFIG_NONE},
650 : : }}
651 : : }},
652 : : {0x50, 1, {
653 : : {"\xFF\xFF", 5, {
654 : : {CAC_UPDATE_BUFFER, 0x04, .config = ACR_INS_CONFIG_NONE},
655 : : {CAC_READ_BUFFER, 0x00, .config = ACR_INS_CONFIG_NONE},
656 : : {VCARD7816_INS_EXTERNAL_AUTHENTICATE, 0x11, .config = ACR_INS_CONFIG_P1, .p1 = 0x00},
657 : : {VCARD7816_INS_GET_CHALLENGE, 0x11, .config = ACR_INS_CONFIG_NONE},
658 : : {VCARD7816_INS_VERIFY, 0x10, .config = ACR_INS_CONFIG_NONE},
659 : : }}
660 : : }},
661 : : {0x51, 1, {
662 : : {"\xFF\xFF", 5, {
663 : : {CAC_UPDATE_BUFFER, 0x04, .config = ACR_INS_CONFIG_NONE},
664 : : {CAC_READ_BUFFER, 0x00, .config = ACR_INS_CONFIG_NONE},
665 : : {VCARD7816_INS_EXTERNAL_AUTHENTICATE, 0x11, .config = ACR_INS_CONFIG_P1, .p1 = 0x00},
666 : : {VCARD7816_INS_GET_CHALLENGE, 0x11, .config = ACR_INS_CONFIG_NONE},
667 : : {VCARD7816_INS_VERIFY, 0x10, .config = ACR_INS_CONFIG_NONE},
668 : : }}
669 : : }},
670 : : {0x52, 1, {
671 : : {"\xFF\xFF", 5, {
672 : : {CAC_UPDATE_BUFFER, 0x04, .config = ACR_INS_CONFIG_NONE},
673 : : {CAC_READ_BUFFER, 0x00, .config = ACR_INS_CONFIG_NONE},
674 : : {VCARD7816_INS_EXTERNAL_AUTHENTICATE, 0x11, .config = ACR_INS_CONFIG_P1, .p1 = 0x00},
675 : : {VCARD7816_INS_GET_CHALLENGE, 0x11, .config = ACR_INS_CONFIG_NONE},
676 : : {VCARD7816_INS_VERIFY, 0x10, .config = ACR_INS_CONFIG_NONE},
677 : : }}
678 : : }},
679 : : {0x44, 2, {
680 : : {"\x12\x01", 3, {
681 : : {CAC_UPDATE_BUFFER, 0x06, .config = ACR_INS_CONFIG_NONE},
682 : : {CAC_READ_BUFFER, 0x00, .config = ACR_INS_CONFIG_DATA1, .data1 = 0x01},
683 : : {CAC_READ_BUFFER, 0x06, .config = ACR_INS_CONFIG_NONE}
684 : : }},
685 : : {"\xFF\xFF", 3, {
686 : : {VCARD7816_INS_EXTERNAL_AUTHENTICATE, 0x11, .config = ACR_INS_CONFIG_P1, .p1 = 0x00},
687 : : {VCARD7816_INS_GET_CHALLENGE, 0x11, .config = ACR_INS_CONFIG_NONE},
688 : : {VCARD7816_INS_VERIFY, 0x10, .config = ACR_INS_CONFIG_NONE},
689 : : }}
690 : : }},
691 : : {0x45, 2, {
692 : : {"\x12\x02", 3, {
693 : : {CAC_UPDATE_BUFFER, 0x06, .config = ACR_INS_CONFIG_NONE},
694 : : {CAC_READ_BUFFER, 0x00, .config = ACR_INS_CONFIG_DATA1, .data1 = 0x01},
695 : : {CAC_READ_BUFFER, 0x06, .config = ACR_INS_CONFIG_NONE}
696 : : }},
697 : : {"\xFF\xFF", 3, {
698 : : {VCARD7816_INS_EXTERNAL_AUTHENTICATE, 0x11, .config = ACR_INS_CONFIG_P1, .p1 = 0x00},
699 : : {VCARD7816_INS_GET_CHALLENGE, 0x11, .config = ACR_INS_CONFIG_NONE},
700 : : {VCARD7816_INS_VERIFY, 0x10, .config = ACR_INS_CONFIG_NONE},
701 : : }}
702 : : }},
703 : : }
704 : : };
705 : :
706 : : static unsigned char *
707 : 70 : acr_applet_object_encode(const struct acr_object *object, unsigned char *out,
708 : : unsigned int outlen, unsigned int *lenp)
709 : : {
710 : : unsigned int j;
711 : : unsigned char *p = NULL;
712 : :
713 : : p = out;
714 [ + + ]: 70 : if (outlen < 2)
715 : : return NULL;
716 : 69 : *p++ = object->id[0];
717 : 69 : *p++ = object->id[1];
718 : 69 : outlen -= 2;
719 [ + + ]: 253 : for (j = 0; j < object->num_ins; j++) {
720 [ + + ]: 186 : if (outlen < 2)
721 : : return NULL;
722 : 185 : *p++ = object->ins[j].code;
723 : 185 : *p++ = object->ins[j].config;
724 : 185 : outlen -= 2;
725 [ + + ]: 185 : if (object->ins[j].config & ACR_INS_CONFIG_P1) {
726 [ - + ]: 25 : if (outlen < 1)
727 : : return NULL;
728 : 25 : *p++ = object->ins[j].p1;
729 : 25 : outlen--;
730 : : }
731 [ + + ]: 185 : if (object->ins[j].config & ACR_INS_CONFIG_P2) {
732 [ + + ]: 3 : if (outlen < 1)
733 : : return NULL;
734 : 2 : *p++ = object->ins[j].p2;
735 : 2 : outlen--;
736 : : }
737 [ + + ]: 184 : if (object->ins[j].config & ACR_INS_CONFIG_DATA1) {
738 [ - + ]: 15 : if (outlen < 1)
739 : : return NULL;
740 : 15 : *p++ = object->ins[j].data1;
741 : 15 : outlen--;
742 : : }
743 : :
744 [ - + ]: 184 : if (outlen < 1)
745 : : return NULL;
746 : 184 : *p++ = object->ins[j].acrid;
747 : 184 : outlen--;
748 : : }
749 : 67 : *lenp = (p - out);
750 : 67 : return p;
751 : : }
752 : :
753 : : static unsigned char *
754 : 18 : acr_applet_encode(const struct acr_applet *applet, unsigned int *outlen)
755 : : {
756 : : unsigned char *buffer = NULL, *p, *lenp;
757 : : unsigned int i, j, plen, objlen, buffer_len;
758 : :
759 [ - + ]: 18 : if (outlen == NULL)
760 : : return NULL;
761 : :
762 : : plen = 2;
763 [ + + ]: 52 : for (i = 0; i < applet->num_objects; i++) {
764 : 34 : plen += 4;
765 [ + + ]: 128 : for (j = 0; j < applet->objects[i].num_ins; j++) {
766 : 94 : plen += 3;
767 [ + + ]: 94 : if (applet->objects[i].ins[j].config & ACR_INS_CONFIG_P1)
768 : 13 : plen++;
769 [ + + ]: 94 : if (applet->objects[i].ins[j].config & ACR_INS_CONFIG_P2)
770 : 1 : plen++;
771 [ + + ]: 94 : if (applet->objects[i].ins[j].config & ACR_INS_CONFIG_DATA1)
772 : 8 : plen++;
773 : : }
774 : : }
775 : : buffer_len = plen;
776 : 18 : buffer = g_malloc(plen);
777 : :
778 : : p = buffer;
779 : 18 : *p++ = applet->id;
780 : 18 : *p++ = applet->num_objects;
781 : 18 : plen -= 2;
782 [ + + ]: 52 : for (i = 0; i < applet->num_objects; i++) {
783 : 34 : *p++ = CAC_ACR_OBJECT_ACR;
784 : 34 : lenp = p++;
785 : 34 : plen -= 2;
786 : 34 : p = acr_applet_object_encode(&applet->objects[i], p, plen, &objlen);
787 [ - + ]: 34 : if (!p)
788 : 0 : goto failure;
789 : 34 : *lenp = objlen & 0xff;
790 : 34 : plen -= objlen;
791 : : }
792 : :
793 [ - + ]: 18 : g_assert_cmpint(p - buffer, ==, buffer_len);
794 : 18 : *outlen = buffer_len;
795 : 18 : return buffer;
796 : :
797 : : failure:
798 : 0 : g_free(buffer);
799 : 0 : return NULL;
800 : : }
801 : :
802 : : static struct simpletlv_member *
803 : 2 : cac_aca_get_applet_acr_coid(unsigned int pki_applets, unsigned char *coid)
804 : : {
805 : : struct simpletlv_member *r = NULL;
806 : : size_t i, j;
807 : :
808 : 2 : r = g_malloc(sizeof(struct simpletlv_member));
809 : :
810 [ + + ]: 36 : for (i = 0; i < applets_table.num_applets; i++) {
811 : : /* Skip unused PKI applets */
812 [ + + + + ]: 35 : if (i >= pki_applets && i < 10)
813 : 14 : continue;
814 : :
815 [ + + ]: 59 : for (j = 0; j < applets_table.applets[i].num_objects; j++) {
816 [ + + ]: 39 : if (memcmp(&applets_table.applets[i].objects[j].id, coid, 2) == 0) {
817 : : unsigned int buffer_len = ACR_MAX_INSTRUCTIONS * 6 + 2;
818 : : unsigned char *p = NULL;
819 : :
820 : 1 : r->type = SIMPLETLV_TYPE_LEAF;
821 : 1 : r->tag = CAC_ACR_OBJECT_ACR;
822 : 1 : r->value.value = g_malloc_n(buffer_len, sizeof(unsigned char));
823 : 1 : p = acr_applet_object_encode(
824 : : &applets_table.applets[i].objects[j],
825 : : r->value.value, buffer_len, &r->length);
826 : : /* return the record on success */
827 [ - + ]: 1 : if (p)
828 : : return r;
829 : :
830 : : /* clean up on failure */
831 : 0 : g_free(r->value.value);
832 : : }
833 : : }
834 : : }
835 : : /* Failure */
836 : 1 : g_free(r);
837 : 1 : return NULL;
838 : : }
839 : :
840 : : static unsigned char
841 : 2 : aid_to_applet_id(unsigned int pki_applets, unsigned char *aid, unsigned int aid_len)
842 : : {
843 : : unsigned int i;
844 [ + + ]: 45 : for (i = 0; i < service_table.num_entries; i++) {
845 [ + + ]: 44 : if ((i < pki_applets || i >= 10)
846 [ + - ]: 30 : && aid_len == service_table.entries[i].applet_aid_len
847 [ + + ]: 30 : && memcmp(aid, service_table.entries[i].applet_aid, aid_len) == 0)
848 : 1 : return service_table.entries[i].applet_id;
849 : : }
850 : : return 0x00;
851 : : }
852 : :
853 : : static struct simpletlv_member *
854 : 3 : cac_aca_get_applet_acr(unsigned int pki_applets, size_t *acr_len, unsigned char *aid,
855 : : unsigned int aid_len)
856 : : {
857 : : struct simpletlv_member *r = NULL;
858 : : unsigned char *num_applets_byte = NULL;
859 : : size_t i, j = 0;
860 : : unsigned char applet_id = 0;
861 : 3 : unsigned int num_applets = applets_table.num_static_applets + pki_applets;
862 : :
863 [ - + - + ]: 3 : g_return_val_if_fail(acr_len != NULL, NULL);
864 : :
865 [ + + ]: 3 : if (aid != NULL && aid_len != 0) {
866 : : /* We are selecting only one applet*/
867 : 2 : applet_id = aid_to_applet_id(pki_applets, aid, aid_len);
868 [ + + ]: 2 : if (applet_id == 0)
869 : : return NULL;
870 : :
871 : 1 : r = g_malloc(sizeof(struct simpletlv_member));
872 : : } else {
873 : 1 : r = g_malloc_n(num_applets + 1, sizeof(struct simpletlv_member));
874 : : }
875 : :
876 : : if (!applet_id) {
877 : 1 : num_applets_byte = g_malloc(1);
878 : 1 : *num_applets_byte = num_applets;
879 : :
880 : 1 : r[j].tag = CAC_ACR_NUM_APPLETS;
881 : 1 : r[j].length = 1;
882 : 1 : r[j].value.value = num_applets_byte;
883 : 1 : r[j].type = SIMPLETLV_TYPE_LEAF;
884 : : j++;
885 : : }
886 [ + + ]: 48 : for (i = 0; i < applets_table.num_applets; i++) {
887 : : /* Skip unused PKI applets */
888 [ + + + + ]: 46 : if (i >= pki_applets && i < 10)
889 : 14 : continue;
890 : :
891 [ + + + + ]: 32 : if (applet_id && applet_id != applets_table.applets[i].id)
892 : 15 : continue;
893 : :
894 : 17 : r[j].type = SIMPLETLV_TYPE_LEAF;
895 : 17 : r[j].tag = CAC_ACR_APPLET_ACR;
896 : 17 : r[j].value.value = acr_applet_encode(&applets_table.applets[i], &r[j].length);
897 [ - + ]: 17 : if (r[j].value.value == NULL)
898 : 0 : goto failure;
899 : 17 : j++;
900 : : }
901 : :
902 : 2 : *acr_len = j;
903 : 2 : return r;
904 : :
905 : : failure:
906 : 0 : simpletlv_free(r, j);
907 : 0 : g_free(num_applets_byte);
908 : 0 : return NULL;
909 : : }
910 : :
911 : : /*
912 : : * Access Method Provider (AMP) table:
913 : : * This table maps the Access Method Provider ID to the full AID
914 : : * for each Access Method Provider.
915 : : * (from 5.3.3.5 Get ACR APDU, Table 5-20)
916 : : */
917 : :
918 : : struct amp_entry {
919 : : unsigned char amp_id;
920 : : unsigned int amp_aid_len;
921 : : unsigned char amp_aid[7];
922 : : };
923 : : struct amp_table {
924 : : unsigned int num_entries;
925 : : struct amp_entry entries[5];
926 : : };
927 : :
928 : : /* Example:
929 : : * 01 05 TL: Applet information
930 : : * 10 02 06 02 02
931 : : * 91 01 TL: Number of AMP entries
932 : : * 03
933 : : * 90 0A AMP Entry
934 : : * 1F Access Method Provider ID
935 : : * 92 07 TL: Access Method Provider AID
936 : : * A0 00 00 00 79 03 00
937 : : * 90 0A AMP Entry
938 : : * 1E Access Method Provider ID
939 : : * 92 07 TL: Access Method Provider AID
940 : : * A0 00 00 00 79 03 00
941 : : * 90 0A AMP Entry
942 : : * 1D Access Method Provider ID
943 : : * 92 07 TL: Access Method Provider AID
944 : : * A0 00 00 00 79 03 00
945 : : */
946 : :
947 : : static const struct amp_table amp_table = {
948 : : 3, {
949 : : {0x1F, 7, "\xA0\x00\x00\x00\x79\x03\x00"},
950 : : {0x1E, 7, "\xA0\x00\x00\x00\x79\x03\x00"},
951 : : {0x1D, 7, "\xA0\x00\x00\x00\x79\x03\x00"},
952 : : }
953 : : };
954 : :
955 : : static const unsigned char amp_table_extended[] = {
956 : : 0x1F, 0x00, 0x07, 0xA0, 0x00, 0x00, 0x00, 0x79, 0x03, 0x00,
957 : : 0x12, 0x00, 0x00, 0x00,
958 : : /* Sometimes it can be 1E 00 07 A0 00 00 00 79 03 00 10 00 00 00 */
959 : : 0x1E, 0x00, 0x07, 0xA0, 0x00, 0x00, 0x00, 0x79, 0x03, 0x00,
960 : : 0x10, 0x01, 0x00, 0x00,
961 : : 0x1D, 0x00, 0x07, 0xA0, 0x00, 0x00, 0x00, 0x79, 0x03, 0x00,
962 : : 0x01, 0x00, 0x00, 0x00,
963 : : };
964 : :
965 : : static struct simpletlv_member *
966 : 1 : cac_aca_get_amp(size_t *amp_len)
967 : : {
968 : : struct simpletlv_member *r = NULL;
969 : : unsigned char *num_entries = NULL;
970 : : unsigned char *entry = NULL;
971 : : size_t i = 0;
972 : :
973 [ - + - + ]: 1 : g_return_val_if_fail(amp_len != NULL, NULL);
974 : :
975 : 1 : r = g_malloc_n(amp_table.num_entries + 1, sizeof(struct simpletlv_member));
976 : :
977 : 1 : num_entries = g_malloc(1);
978 : 1 : *num_entries = amp_table.num_entries;
979 : :
980 : 1 : r[0].tag = CAC_ACR_AMP_NUM_ENTRIES;
981 : 1 : r[0].length = 1;
982 : 1 : r[0].value.value = num_entries;
983 : 1 : r[0].type = SIMPLETLV_TYPE_LEAF;
984 [ + + ]: 4 : for (i = 1; i <= amp_table.num_entries; i++) {
985 : 3 : r[i].type = SIMPLETLV_TYPE_LEAF;
986 : 3 : r[i].tag = CAC_ACR_AMP_ENTRY;
987 : 3 : r[i].length = amp_table.entries[i].amp_aid_len + 3;
988 : 3 : entry = g_malloc(r[i].length);
989 : 3 : entry[0] = amp_table.entries[i].amp_id;
990 : 3 : entry[1] = CAC_ACR_AID;
991 : 3 : entry[2] = amp_table.entries[i].amp_aid_len;
992 : 3 : memcpy(&entry[3], (unsigned char *) &_table.entries[i],
993 : : amp_table.entries[i].amp_aid_len);
994 : 3 : r[i].value.value = entry;
995 : : }
996 : 1 : *amp_len = amp_table.num_entries + 1;
997 : 1 : return r;
998 : : }
999 : :
1000 : : /* ACA Applet Information
1001 : : * The following entry is always returned and precedes any ACR table,
1002 : : * Applet/Object ACR table or Authentication Method Provider table.
1003 : : *
1004 : : * 01 Tag: Applet Information
1005 : : * 05 Length
1006 : : * 10 Applet family
1007 : : * 02 06 02 02 Applet version
1008 : : */
1009 : : static unsigned char applet_information[] = "\x10\x02\x06\x02\x02";
1010 : : static struct simpletlv_member aca_properties[1] = {
1011 : : {CAC_PROPERTIES_APPLET_INFORMATION, 5, {/*.value = applet_information*/},
1012 : : SIMPLETLV_TYPE_LEAF},
1013 : : };
1014 : :
1015 : : static struct simpletlv_member *
1016 : : cac_aca_get_properties(size_t *properties_len)
1017 : : {
1018 : : g_assert_nonnull(properties_len);
1019 : :
1020 : : /* Inject Applet Version into Applet information */
1021 : 96 : aca_properties[0].value.value = applet_information;
1022 : :
1023 : : *properties_len = 1;
1024 : :
1025 : : return aca_properties;
1026 : : }
1027 : :
1028 : : /*
1029 : : * This is ACR table in undocumented compressed form
1030 : : *
1031 : : * |ACRID ACRType AMPid:keyID
1032 : : * 06 00 00 00 00 00 00 | 00 00
1033 : : * 06 01 01 00 01 00 00 | 01 01
1034 : : * 06 02 00 1F 00 00 00 | 02 00
1035 : : * 06 06 06 00 1E 00 00 | 06 06 1E:00
1036 : : * 06 04 04 1F 1F 21 00 | 04 04 1F:21
1037 : : * 08 08 03 00 9D 01 1E 01 00 | 08 03 9D:01 1E:01
1038 : : * 06 09 02 00 1D 02 00 | 09 02 1D:02
1039 : : * 08 0A 03 00 9D 03 1E 01 00 | 0A 03 9D:03 1E:01
1040 : : * 06 0B 02 00 1D 04 00 | 0B 02 1D:04
1041 : : * 06 10 00 1E 00 00 00 | 10 00
1042 : : * 06 11 00 1D 00 00 00 | 11 00
1043 : : * len | | ? | |
1044 : : * ACRID | ? | |
1045 : : * ACRType | |
1046 : : * AMPid |
1047 : : * KeyIdOrReference
1048 : : */
1049 : : static VCardResponse *
1050 : 1 : cac_aca_get_acr_response_extended(VCard *card, int Le)
1051 : : {
1052 : : size_t buffer_len;
1053 : : unsigned char *buffer = NULL, *p;
1054 : : VCardResponse *r = NULL;
1055 : : size_t i, j;
1056 : :
1057 : : buffer_len = acr_table.num_entries * (7 + 2 * (MAX_ACCESS_METHODS - 1));
1058 : 1 : buffer = g_malloc_n(buffer_len, sizeof(unsigned char));
1059 : : p = buffer;
1060 : :
1061 [ + + ]: 12 : for (i = 0; i < acr_table.num_entries; i++) {
1062 : : const struct acr_entry *a = &acr_table.entries[i];
1063 [ - + ]: 11 : g_assert_cmpint(a->num_access_methods, <=, MAX_ACCESS_METHODS);
1064 [ + + ]: 11 : *p++ = a->num_access_methods == 2 ? 0x08 : 0x06;
1065 : 11 : *p++ = a->acrid;
1066 : 11 : *p++ = a->acrtype;
1067 : 11 : *p++ = a->applet_id;
1068 : :
1069 [ + + ]: 19 : for (j = 0; j < a->num_access_methods; j++) {
1070 : 8 : *p++ = a->access_methods[j].provider_id;
1071 : 8 : *p++ = a->access_methods[j].keyIDOrReference;
1072 : : }
1073 [ + + ]: 11 : if (a->num_access_methods == 0) {
1074 : 5 : *p++ = 0x00;
1075 : 5 : *p++ = 0x00;
1076 : : }
1077 : 11 : *p++ = 0x00;
1078 : : }
1079 [ - + - + ]: 1 : g_assert((unsigned long)(p - buffer) <= buffer_len);
1080 : : buffer_len = (p - buffer);
1081 : :
1082 : 1 : r = vcard_response_new(card, buffer, buffer_len, Le,
1083 : : VCARD7816_STATUS_SUCCESS);
1084 : 1 : g_debug("%s: response bytes: %s", __func__,
1085 : : hex_dump(buffer, buffer_len));
1086 : 1 : g_free(buffer);
1087 : 1 : return r;
1088 : : }
1089 : :
1090 : :
1091 : :
1092 : : static VCardResponse *
1093 : 3 : cac_aca_get_acr_response_simpletlv(VCard *card, int Le, unsigned char *acrid)
1094 : : {
1095 : : size_t acr_buffer_len;
1096 : 3 : unsigned char *acr_buffer = NULL;
1097 : : size_t properties_len;
1098 : : const struct simpletlv_member *properties;
1099 : : size_t acr_len;
1100 : : struct simpletlv_member *acr = NULL;
1101 : : size_t list_len;
1102 : : struct simpletlv_member *list = NULL;
1103 : : VCardResponse *r = NULL;
1104 : :
1105 : : /* Prepare the SimpleTLV structures */
1106 : : properties = cac_aca_get_properties(&properties_len);
1107 : 3 : acr = cac_aca_get_acr(&acr_len, acrid);
1108 [ + + ]: 3 : if (acr == NULL) {
1109 : : /* The requested ACR was not found */
1110 : 1 : r = vcard_make_response(VCARD7816_STATUS_ERROR_DATA_NOT_FOUND);
1111 : 1 : return r;
1112 : : }
1113 : :
1114 : : /* Merge them together */
1115 : 2 : list_len = properties_len + acr_len;
1116 : 2 : list = simpletlv_merge(properties, properties_len, acr, acr_len);
1117 [ - + ]: 2 : if (list == NULL)
1118 : 0 : goto failure;
1119 : :
1120 : : /* encode the data */
1121 : 2 : acr_buffer_len = simpletlv_encode(list, list_len, &acr_buffer, 0, NULL);
1122 [ - + ]: 2 : if (acr_buffer == NULL)
1123 : 0 : goto failure;
1124 : :
1125 : 2 : r = vcard_response_new(card, acr_buffer, acr_buffer_len, Le,
1126 : : VCARD7816_STATUS_SUCCESS);
1127 : :
1128 : 2 : failure:
1129 : 2 : g_free(list);
1130 : 2 : g_free(acr);
1131 : 2 : g_free(acr_buffer);
1132 [ - + ]: 2 : if (r == NULL)
1133 : 0 : r = vcard_make_response(VCARD7816_STATUS_ERROR_GENERAL);
1134 : : return r;
1135 : : }
1136 : :
1137 : : VCardResponse *
1138 : 4 : cac_aca_get_acr_response(VCard *card, int Le, unsigned char *acrid, int format)
1139 : : {
1140 [ + + ]: 4 : if (format == CAC_FORMAT_SIMPLETLV) {
1141 : 3 : return cac_aca_get_acr_response_simpletlv(card, Le, acrid);
1142 : : } else {
1143 : 1 : return cac_aca_get_acr_response_extended(card, Le);
1144 : : }
1145 : : }
1146 : :
1147 : : static VCardResponse *
1148 : 5 : cac_aca_get_applet_acr_response_simpletlv(VCard *card, int Le,
1149 : : unsigned int pki_applets,
1150 : : unsigned char *aid,
1151 : : unsigned int aid_len,
1152 : : unsigned char *coid)
1153 : : {
1154 : : size_t acr_buffer_len;
1155 : 5 : unsigned char *acr_buffer = NULL;
1156 : : size_t properties_len;
1157 : : const struct simpletlv_member *properties;
1158 : 5 : size_t acr_len = 0;
1159 : : struct simpletlv_member *acr = NULL;
1160 : : size_t list_len;
1161 : : struct simpletlv_member *list = NULL;
1162 : : VCardResponse *r = NULL;
1163 : :
1164 : : /* Prepare the SimpleTLV structures */
1165 : : properties = cac_aca_get_properties(&properties_len);
1166 [ + + ]: 5 : if (coid != NULL) {
1167 : 2 : g_debug("%s: Called. COID = %s", __func__, hex_dump(coid, 2));
1168 : :
1169 : : /* getting the table for Card Object ID (2B) */
1170 : 2 : acr_len = 1; // returns exactly one element if found
1171 : 2 : acr = cac_aca_get_applet_acr_coid(pki_applets, coid);
1172 [ + + ]: 2 : if (!acr) {
1173 : : /* did not find the COID */
1174 : 1 : r = vcard_make_response(VCARD7816_STATUS_ERROR_WRONG_PARAMETERS_IN_DATA);
1175 : 1 : return r;
1176 : : }
1177 : : } else {
1178 : : /* getting the table for AID or the whole */
1179 : 3 : acr = cac_aca_get_applet_acr(pki_applets, &acr_len, aid, aid_len);
1180 [ + + ]: 3 : if (!acr && aid_len > 0) {
1181 : : /* did not find the AID */
1182 : 1 : r = vcard_make_response(VCARD7816_STATUS_ERROR_DATA_NOT_FOUND);
1183 : 1 : return r;
1184 : : }
1185 [ - + ]: 2 : if (acr == NULL)
1186 : 0 : goto failure;
1187 : : }
1188 : :
1189 : : /* Merge them together */
1190 : 3 : list_len = properties_len + acr_len;
1191 : 3 : list = simpletlv_merge(properties, properties_len, acr, acr_len);
1192 [ - + ]: 3 : if (list == NULL)
1193 : 0 : goto failure;
1194 : :
1195 : : /* encode the data */
1196 : 3 : acr_buffer_len = simpletlv_encode(list, list_len, &acr_buffer, 0, NULL);
1197 [ - + ]: 3 : if (acr_buffer == NULL)
1198 : 0 : goto failure;
1199 : :
1200 : 3 : r = vcard_response_new(card, acr_buffer, acr_buffer_len, Le,
1201 : : VCARD7816_STATUS_SUCCESS);
1202 : 3 : g_debug("%s: response bytes: %s", __func__,
1203 : : hex_dump(acr_buffer, acr_buffer_len));
1204 : :
1205 : 3 : failure:
1206 : 3 : g_free(list);
1207 : 3 : simpletlv_free(acr, acr_len);
1208 : 3 : g_free(acr_buffer);
1209 [ - + ]: 3 : if (r == NULL)
1210 : 0 : r = vcard_make_response(VCARD7816_STATUS_ERROR_GENERAL);
1211 : : return r;
1212 : : }
1213 : :
1214 : : /*
1215 : : * This is Applet/Object ACR Table in undocumented compressed format.
1216 : : *
1217 : : * Len
1218 : : * | Applet Id
1219 : : * | | Num Objects
1220 : : * | | | Len [OID] INS+Config+ACRID
1221 : : * 1C 1F 01
1222 : : * 19 FF FF
1223 : : * 26 80 00
1224 : : * 2C 80 04
1225 : : * 24 81 80 04
1226 : : * 24 81 01 00
1227 : : * 24 80 06
1228 : : * 20 00 00
1229 : : * D8 80 04
1230 : : * 24 4F 02
1231 : : * 08 DB 00
1232 : : * 58 00 04
1233 : : * 52 00 00
1234 : : * 18 FF FF
1235 : : * 82 01 00 11
1236 : : * 50 80 02
1237 : : * 82 80 02
1238 : : * F0 80 04
1239 : : * 34 80 04
1240 : : * 84 00 11
1241 : : * 20 00 10
1242 : : * [...]
1243 : : */
1244 : : static VCardResponse *
1245 : 1 : cac_aca_get_applet_acr_response_extended(VCard *card, int Le,
1246 : : unsigned int pki_applets)
1247 : : {
1248 : : size_t buffer_len, i, j, plen;
1249 : : unsigned char *buffer = NULL, *p;
1250 : : VCardResponse *r = NULL;
1251 : 1 : unsigned int num_applets = applets_table.num_static_applets + pki_applets;
1252 : :
1253 : 1 : buffer_len = num_applets * (3 + ACR_MAX_APPLET_OBJECTS
1254 : : * ( 3 + ACR_MAX_INSTRUCTIONS * 6));
1255 : 1 : buffer = g_malloc_n(buffer_len, sizeof(unsigned char));
1256 : : p = buffer;
1257 : : plen = buffer_len;
1258 : :
1259 [ + + ]: 24 : for (i = 0; i < applets_table.num_applets; i++) {
1260 : : const struct acr_applet *a;
1261 : : unsigned char *len;
1262 : : /* Skip unused PKI applets */
1263 [ + + + + ]: 23 : if (i >= pki_applets && i < 10)
1264 : 7 : continue;
1265 : :
1266 : : a = &applets_table.applets[i];
1267 [ - + ]: 16 : if (plen < 3)
1268 : 0 : goto failure;
1269 : : len = p++; /* here we will store the length later */
1270 : 16 : *p++ = a->id;
1271 : 16 : *p++ = a->num_objects;
1272 : 16 : plen -= 3;
1273 [ + + ]: 47 : for (j = 0; j < a->num_objects; j++) {
1274 : 31 : const struct acr_object *o = &a->objects[j];
1275 : : unsigned char *len2;
1276 : : unsigned int olen;
1277 : :
1278 : 31 : len2 = p++; /* here we will store the length later */
1279 : : /* the encoding from here on is the same as in specification */
1280 : 31 : p = acr_applet_object_encode(o, p, plen, &olen);
1281 [ - + ]: 31 : if (!p)
1282 : 0 : goto failure;
1283 : 31 : plen -= olen;
1284 : 31 : *len2 = olen;
1285 : : }
1286 : 16 : *len = (p - len - 1);
1287 : : }
1288 [ - + - + ]: 1 : g_assert((unsigned long)(p - buffer) <= buffer_len);
1289 : : buffer_len = (p - buffer);
1290 : :
1291 : 1 : r = vcard_response_new(card, buffer, buffer_len, Le,
1292 : : VCARD7816_STATUS_SUCCESS);
1293 : 1 : g_debug("%s: response bytes: %s", __func__,
1294 : : hex_dump(buffer, buffer_len));
1295 : 1 : failure:
1296 : 1 : g_free(buffer);
1297 : 1 : return r;
1298 : : }
1299 : :
1300 : : VCardResponse *
1301 : 6 : cac_aca_get_applet_acr_response(VCard *card, int Le, unsigned int pki_applets,
1302 : : unsigned char *aid, unsigned int aid_len,
1303 : : unsigned char *coid, int format)
1304 : : {
1305 [ + + ]: 6 : if (format == CAC_FORMAT_SIMPLETLV) {
1306 : 5 : return cac_aca_get_applet_acr_response_simpletlv(card, Le,
1307 : : pki_applets, aid, aid_len, coid);
1308 : : } else {
1309 : 1 : return cac_aca_get_applet_acr_response_extended(card, Le,
1310 : : pki_applets);
1311 : : }
1312 : : }
1313 : :
1314 : :
1315 : : static VCardResponse *
1316 : 1 : cac_aca_get_amp_response_simpletlv(VCard *card, int Le)
1317 : : {
1318 : : size_t amp_buffer_len;
1319 : 1 : unsigned char *amp_buffer = NULL;
1320 : : size_t properties_len;
1321 : : const struct simpletlv_member *properties;
1322 : 1 : size_t amp_len = 0;
1323 : : struct simpletlv_member *amp = NULL;
1324 : : size_t list_len;
1325 : : struct simpletlv_member *list = NULL;
1326 : : VCardResponse *r = NULL;
1327 : :
1328 : : /* Prepare the SimpleTLV structures */
1329 : : properties = cac_aca_get_properties(&properties_len);
1330 : 1 : amp = cac_aca_get_amp(&_len);
1331 [ - + ]: 1 : if (amp == NULL)
1332 : 0 : goto failure;
1333 : :
1334 : : /* Merge them together */
1335 : 1 : list_len = properties_len + amp_len;
1336 : 1 : list = simpletlv_merge(properties, properties_len, amp, amp_len);
1337 [ - + ]: 1 : if (list == NULL)
1338 : 0 : goto failure;
1339 : :
1340 : : /* encode the data */
1341 : 1 : amp_buffer_len = simpletlv_encode(list, list_len, &_buffer, 0, NULL);
1342 [ - + ]: 1 : if (amp_buffer == NULL)
1343 : 0 : goto failure;
1344 : :
1345 : 1 : r = vcard_response_new(card, amp_buffer, amp_buffer_len, Le,
1346 : : VCARD7816_STATUS_SUCCESS);
1347 : :
1348 : 1 : failure:
1349 : 1 : g_free(list);
1350 : 1 : simpletlv_free(amp, amp_len);
1351 : 1 : g_free(amp_buffer);
1352 [ - + ]: 1 : if (r == NULL)
1353 : 0 : r = vcard_make_response(VCARD7816_STATUS_ERROR_GENERAL);
1354 : 1 : return r;
1355 : : }
1356 : :
1357 : : VCardResponse *
1358 : 2 : cac_aca_get_amp_response(VCard *card, int Le, int format)
1359 : : {
1360 [ + + ]: 2 : if (format == CAC_FORMAT_SIMPLETLV) {
1361 : 1 : return cac_aca_get_amp_response_simpletlv(card, Le);
1362 : : } else {
1363 : : /* 1F 00 07 A0 00 00 00 79 03 00 12 00 00 00
1364 : : * 1E 00 07 A0 00 00 00 79 03 00 10 01 00 00
1365 : : * 1D 00 07 A0 00 00 00 79 03 00 01 00 00 00
1366 : : * LEN [ AID ] [OID]
1367 : : */
1368 : 1 : return vcard_response_new(card, amp_table_extended,
1369 : : sizeof(amp_table_extended), Le, VCARD7816_STATUS_SUCCESS);
1370 : : }
1371 : : }
1372 : :
1373 : : /*
1374 : : * This is Service Applet table in undocumented compressed format
1375 : : *
1376 : : * Applet ID
1377 : : * | Len [ AID ]
1378 : : * 40 00 07 A0 00 00 01 16 30 00
1379 : : * 4F 00 07 A0 00 00 01 16 DB 00
1380 : : * 4B 00 07 A0 00 00 00 79 02 FB
1381 : : * 41 00 07 A0 00 00 00 79 02 00
1382 : : * 42 00 07 A0 00 00 00 79 02 01
1383 : : * 4E 00 07 A0 00 00 00 79 02 FE
1384 : : * 4D 00 07 A0 00 00 00 79 02 FD
1385 : : * 50 00 07 A0 00 00 00 79 02 F2
1386 : : * 63 00 07 A0 00 00 00 79 01 02
1387 : : * 51 00 07 A0 00 00 00 79 02 F0
1388 : : * 61 00 07 A0 00 00 00 79 01 00
1389 : : * 52 00 07 A0 00 00 00 79 02 F1
1390 : : * 62 00 07 A0 00 00 00 79 01 01
1391 : : * 44 00 07 A0 00 00 00 79 12 01
1392 : : * 45 00 07 A0 00 00 00 79 12 02
1393 : : */
1394 : : static VCardResponse *
1395 : 1 : cac_aca_get_service_response_extended(VCard *card, int Le,
1396 : : unsigned int pki_applets)
1397 : : {
1398 : : size_t buffer_len;
1399 : : unsigned char *buffer = NULL, *p;
1400 : : VCardResponse *r = NULL;
1401 : : size_t num_entries, i;
1402 : :
1403 : 1 : num_entries = service_table.num_static_entries + pki_applets;
1404 : :
1405 : 1 : buffer_len = num_entries * (3 + MAX_AID_LEN);
1406 : 1 : buffer = g_malloc(buffer_len);
1407 : : p = buffer;
1408 : :
1409 [ + + ]: 23 : for (i = 0; i < service_table.num_entries; i++) {
1410 : : const struct applet_entry *e;
1411 : : /* Skip unused PKI applets */
1412 [ + + + + ]: 22 : if (i >= pki_applets && i < 10)
1413 : 7 : continue;
1414 : :
1415 : : e = &service_table.entries[i];
1416 : 15 : *p++ = e->applet_id;
1417 : 15 : *p++ = 0;
1418 : 15 : *p++ = e->applet_aid_len;
1419 : 15 : memcpy(p, e->applet_aid, e->applet_aid_len);
1420 : 15 : p += e->applet_aid_len;
1421 : : }
1422 [ - + - + ]: 1 : g_assert((unsigned long)(p - buffer) <= buffer_len);
1423 : : buffer_len = (p - buffer);
1424 : :
1425 : 1 : r = vcard_response_new(card, buffer, buffer_len, Le,
1426 : : VCARD7816_STATUS_SUCCESS);
1427 : 1 : g_debug("%s: response bytes: %s", __func__,
1428 : : hex_dump(buffer, buffer_len));
1429 : 1 : g_free(buffer);
1430 : 1 : return r;
1431 : : }
1432 : :
1433 : : static VCardResponse *
1434 : 87 : cac_aca_get_service_response_simpletlv(VCard *card, int Le,
1435 : : unsigned int pki_applets)
1436 : : {
1437 : : size_t service_buffer_len;
1438 : 87 : unsigned char *service_buffer = NULL;
1439 : : size_t properties_len;
1440 : : const struct simpletlv_member *properties;
1441 : 87 : size_t service_len = 0;
1442 : : struct simpletlv_member *service = NULL;
1443 : : size_t list_len;
1444 : : struct simpletlv_member *list = NULL;
1445 : : VCardResponse *r = NULL;
1446 : :
1447 : : /* Prepare the SimpleTLV structures */
1448 : : properties = cac_aca_get_properties(&properties_len);
1449 : 87 : service = cac_aca_get_service_table(&service_len, pki_applets);
1450 [ - + ]: 87 : if (service == NULL)
1451 : 0 : goto failure;
1452 : :
1453 : : /* Merge them together */
1454 : 87 : list_len = properties_len + service_len;
1455 : 87 : list = simpletlv_merge(properties, properties_len, service, service_len);
1456 [ - + ]: 87 : if (list == NULL)
1457 : 0 : goto failure;
1458 : :
1459 : : /* encode the data */
1460 : 87 : service_buffer_len = simpletlv_encode(list, list_len, &service_buffer, 0, NULL);
1461 [ - + ]: 87 : if (service_buffer == NULL)
1462 : 0 : goto failure;
1463 : :
1464 : 87 : r = vcard_response_new(card, service_buffer, service_buffer_len, Le,
1465 : : VCARD7816_STATUS_SUCCESS);
1466 : :
1467 : 87 : failure:
1468 : 87 : g_free(list);
1469 : 87 : simpletlv_free(service, service_len);
1470 : 87 : g_free(service_buffer);
1471 [ - + ]: 87 : if (r == NULL)
1472 : 0 : r = vcard_make_response(VCARD7816_STATUS_ERROR_GENERAL);
1473 : 87 : return r;
1474 : : }
1475 : :
1476 : : VCardResponse *
1477 : 88 : cac_aca_get_service_response(VCard *card, int Le,
1478 : : unsigned int pki_applets, int format)
1479 : : {
1480 [ + + ]: 88 : if (format == CAC_FORMAT_SIMPLETLV) {
1481 : 87 : return cac_aca_get_service_response_simpletlv(card, Le, pki_applets);
1482 : : } else {
1483 : 1 : return cac_aca_get_service_response_extended(card, Le, pki_applets);
1484 : : }
1485 : : }
1486 : :
1487 : : /* vim: set ts=4 sw=4 tw=0 noet expandtab: */
|