Branch data Line data Source code
1 : : /*
2 : : * Test general functionality of software emulated smart card
3 : : *
4 : : * Copyright 2018 Red Hat, Inc.
5 : : *
6 : : * Authors:
7 : : * Marc-André Lureau <marcandre.lureau@redhat.com>
8 : : * Jakub Jelen <jjelen@redhat.com>
9 : : *
10 : : * This code is licensed under the GNU LGPL, version 2.1 or later.
11 : : * See the COPYING file in the top-level directory.
12 : : */
13 : : #include <glib.h>
14 : : #include <string.h>
15 : : #include "libcacard.h"
16 : : #include "simpletlv.h"
17 : : #include "common.h"
18 : : #include "src/common.h"
19 : :
20 : : #define ARGS "db=\"sql:%s\" use_hw=no soft=(,Test,CAC,,cert1,cert2,cert3)"
21 : :
22 : : static GMainLoop *loop;
23 : : static GThread *thread;
24 : : static guint nreaders;
25 : : static GMutex mutex;
26 : : static GCond cond;
27 : :
28 : : static gpointer
29 : 1 : events_thread(G_GNUC_UNUSED gpointer arg)
30 : : {
31 : : unsigned int reader_id;
32 : : VEvent *event;
33 : :
34 : : while (1) {
35 : 6 : event = vevent_wait_next_vevent();
36 [ + + ]: 6 : if (event->type == VEVENT_LAST) {
37 : 1 : vevent_delete(event);
38 : : break;
39 : : }
40 : 5 : reader_id = vreader_get_id(event->reader);
41 [ + + ]: 5 : if (reader_id == VSCARD_UNDEFINED_READER_ID) {
42 : 1 : g_mutex_lock(&mutex);
43 : 1 : vreader_set_id(event->reader, nreaders++);
44 : 1 : g_cond_signal(&cond);
45 : 1 : g_mutex_unlock(&mutex);
46 : 1 : reader_id = vreader_get_id(event->reader);
47 : : }
48 [ - + ]: 5 : switch (event->type) {
49 : : case VEVENT_READER_INSERT:
50 : : case VEVENT_READER_REMOVE:
51 : : case VEVENT_CARD_INSERT:
52 : : case VEVENT_CARD_REMOVE:
53 : : break;
54 : 0 : case VEVENT_LAST:
55 : : default:
56 : 0 : g_warn_if_reached();
57 : 0 : break;
58 : : }
59 : 5 : vevent_delete(event);
60 : : }
61 : :
62 : 1 : return NULL;
63 : : }
64 : :
65 : 1 : static void libcacard_init(void)
66 : : {
67 : : VCardEmulOptions *command_line_options = NULL;
68 : 1 : gchar *dbdir = g_test_build_filename(G_TEST_DIST, "db", NULL);
69 : 1 : gchar *args = g_strdup_printf(ARGS, dbdir);
70 : : VReader *r;
71 : : VCardEmulError ret;
72 : :
73 : 1 : thread = g_thread_new("test/events", events_thread, NULL);
74 : :
75 : 1 : command_line_options = vcard_emul_options(args);
76 : 1 : ret = vcard_emul_init(command_line_options);
77 [ - + ]: 1 : g_assert_cmpint(ret, ==, VCARD_EMUL_OK);
78 : :
79 : 1 : r = vreader_get_reader_by_name("Test");
80 [ - + - + ]: 1 : g_assert_nonnull(r);
81 : 1 : vreader_free(r); /* get by name ref */
82 : :
83 : 1 : g_mutex_lock(&mutex);
84 [ - + ]: 1 : while (nreaders == 0)
85 : 0 : g_cond_wait(&cond, &mutex);
86 : 1 : g_mutex_unlock(&mutex);
87 : :
88 : 1 : g_free(args);
89 : 1 : g_free(dbdir);
90 : 1 : }
91 : :
92 : 1 : static void test_hex_dump(void)
93 : : {
94 : : unsigned char binary_data[4000];
95 : : unsigned int i;
96 : 1 : const char expected_data[] = "0x00 0x01 0x02 0x03 0x04 0x05 0x06 0x07*";
97 : :
98 [ + + ]: 4001 : for (i = 0; i < G_N_ELEMENTS(binary_data); i++) {
99 : 4000 : binary_data[i] = i & 0xff;
100 : : }
101 : :
102 : 1 : g_test_expect_message(G_LOG_DOMAIN, G_LOG_LEVEL_DEBUG, expected_data);
103 : 1 : g_debug("%s", hex_dump(binary_data, G_N_ELEMENTS(binary_data)));
104 : 1 : g_test_assert_expected_messages();
105 : :
106 : 1 : g_test_expect_message(G_LOG_DOMAIN, G_LOG_LEVEL_DEBUG, expected_data);
107 : 1 : g_debug("%s", hex_dump(binary_data, 8));
108 : 1 : g_test_assert_expected_messages();
109 : 1 : }
110 : :
111 : 1 : static void test_list(void)
112 : : {
113 : 1 : VReaderList *list = vreader_get_reader_list();
114 : : VReaderListEntry *reader_entry;
115 : : int cards = 0;
116 : :
117 [ + + ]: 2 : for (reader_entry = vreader_list_get_first(list); reader_entry;
118 : 1 : reader_entry = vreader_list_get_next(reader_entry)) {
119 : 1 : VReader *r = vreader_list_get_reader(reader_entry);
120 : : vreader_id_t id;
121 : 1 : id = vreader_get_id(r);
122 [ - + ]: 1 : g_assert_cmpstr(vreader_get_name(r), ==, "Test");
123 [ - + ]: 1 : g_assert_cmpint(id, !=, VSCARD_UNDEFINED_READER_ID);
124 [ + - ]: 1 : if (vreader_card_is_present(r) == VREADER_OK) {
125 : 1 : cards++;
126 : : }
127 : 1 : vreader_free(r);
128 : : }
129 [ - + ]: 1 : g_assert_cmpint(cards, ==, 1);
130 : 1 : vreader_list_delete(list);
131 : 1 : }
132 : :
133 : 1 : static void test_card_remove_insert(void)
134 : : {
135 : 1 : VReader *reader = vreader_get_reader_by_id(0);
136 : : VCardEmulError error;
137 : :
138 [ - + - + ]: 1 : g_assert_nonnull(reader);
139 : :
140 : 1 : error = vcard_emul_force_card_remove(reader);
141 [ - + ]: 1 : g_assert_cmpint(error, ==, VCARD_EMUL_OK);
142 [ - + ]: 1 : g_assert_cmpint(vreader_card_is_present(reader), ==, VREADER_NO_CARD);
143 : :
144 : 1 : error = vcard_emul_force_card_remove(reader);
145 [ - + ]: 1 : g_assert_cmpint(error, ==, VCARD_EMUL_FAIL);
146 [ - + ]: 1 : g_assert_cmpint(vreader_card_is_present(reader), ==, VREADER_NO_CARD);
147 : :
148 : 1 : error = vcard_emul_force_card_insert(reader);
149 [ - + ]: 1 : g_assert_cmpint(error, ==, VCARD_EMUL_OK);
150 [ - + ]: 1 : g_assert_cmpint(vreader_card_is_present(reader), ==, VREADER_OK);
151 : :
152 : 1 : error = vcard_emul_force_card_insert(reader);
153 [ - + ]: 1 : g_assert_cmpint(error, ==, VCARD_EMUL_FAIL);
154 [ - + ]: 1 : g_assert_cmpint(vreader_card_is_present(reader), ==, VREADER_OK);
155 : :
156 : 1 : vreader_free(reader); /* get by id ref */
157 : 1 : }
158 : :
159 : 1 : static void test_xfer(void)
160 : : {
161 : 1 : VReader *reader = vreader_get_reader_by_id(0);
162 : : VReaderStatus status;
163 : 1 : int dwRecvLength = APDUBufSize;
164 : : uint8_t pbRecvBuffer[APDUBufSize];
165 : 1 : uint8_t pbSendBuffer[] = {
166 : : /* Select Applet that is not there */
167 : : 0x00, 0xa4, 0x04, 0x00, 0x07, 0x62, 0x76, 0x01, 0xff, 0x00, 0x00, 0x00,
168 : : };
169 : :
170 [ - + - + ]: 1 : g_assert_nonnull(reader);
171 : 1 : status = vreader_xfr_bytes(reader,
172 : : pbSendBuffer, sizeof(pbSendBuffer),
173 : : pbRecvBuffer, &dwRecvLength);
174 [ - + ]: 1 : g_assert_cmpint(status, ==, VREADER_OK);
175 : 1 : vreader_free(reader); /* get by id ref */
176 : 1 : }
177 : :
178 : 6 : static void parse_acr(uint8_t *buf, int buflen)
179 : : {
180 : : uint8_t *p, *p_end;
181 : : int have_applet_information = 0;
182 : : int num_entries = 0, num_entries_expected = -1;
183 : :
184 : 6 : p = buf;
185 : 6 : p_end = p + buflen - 2;
186 [ + + ]: 47 : while (p < p_end) {
187 : : uint8_t tag;
188 : : size_t vlen;
189 [ - + ]: 41 : if (simpletlv_read_tag(&p, p_end - p, &tag, &vlen) < 0) {
190 : 0 : g_debug("The generated SimpleTLV can not be parsed");
191 : 0 : g_assert_not_reached();
192 : : }
193 [ - + ]: 41 : g_assert_cmpint(vlen, <=, p_end - p);
194 : 41 : g_debug("Tag: 0x%02x, Len: %" G_GSIZE_FORMAT, tag, vlen);
195 [ + + + - : 41 : switch (tag) {
+ ]
196 : 6 : case 0x01: /* Applet Information */
197 [ - + ]: 6 : g_assert_cmpint(vlen, ==, 5);
198 [ - + ]: 6 : g_assert_cmphex(*p, ==, 0x10); /* Applet family */
199 [ - + ]: 6 : g_assert_cmpint(have_applet_information, ==, 0);
200 : : have_applet_information = 1;
201 : : break;
202 : :
203 : 3 : case 0xA1: /* Num ACR Entries */
204 : : case 0x81: /* Num Applet/Objects */
205 : : case 0x91: /* Num AMP Entries */
206 : : case 0x94: /* Num Service Applet Entries */
207 [ - + ]: 3 : g_assert_cmpint(num_entries_expected, ==, -1);
208 [ - + ]: 3 : g_assert_cmpint(num_entries, ==, 0);
209 : 3 : num_entries_expected = *p;
210 : 3 : break;
211 : :
212 : 31 : case 0xA0: /* ACR Entry */
213 : : case 0x80: /* Aplet Entry */
214 : : case 0x90: /* AMP Entry */
215 : : case 0x93: /* Service Entry */
216 : 31 : num_entries++;
217 : 31 : break;
218 : :
219 : : case 0x82: /* Object ACR Entry */
220 : : /* this is only single entry without preceeding tags */
221 : : break;
222 : :
223 : 0 : default:
224 : 0 : g_debug("Unknown tag in object: 0x%02x", tag);
225 : 0 : g_assert_not_reached();
226 : : }
227 : 41 : p += vlen;
228 : : }
229 : :
230 : : /* Every response needs to have exactly one applet information tag */
231 [ - + ]: 6 : g_assert_cmpint(have_applet_information, ==, 1);
232 : : /* The number of entries in the second tag matches the number of entries later */
233 [ + + ]: 6 : if (num_entries_expected != -1) {
234 [ - + ]: 3 : g_assert_cmpint(num_entries, ==, num_entries_expected);
235 : : }
236 : : /* nothing left to read */
237 [ - + - + ]: 6 : g_assert_true(p == p_end);
238 : 6 : }
239 : :
240 : 1 : static void get_acr(VReader *reader)
241 : : {
242 : 1 : int dwRecvLength = APDUBufSize;
243 : : VReaderStatus status;
244 : : uint8_t pbRecvBuffer[APDUBufSize];
245 : 1 : uint8_t get_acr[] = {
246 : : /* Get ACR [TYPE] [ 0 ] [Le] */
247 : : 0x80, 0x4c, 0x00, 0x00, 0x00
248 : : };
249 : 1 : uint8_t get_acr_arg[] = {
250 : : /* Get ACR [TYPE] [ 0 ] [Lc] [data] [Le] */
251 : : 0x80, 0x4c, 0x01, 0x00, 0x01, 0x0A, 0x00
252 : : };
253 : 1 : uint8_t get_acr_coid[] = {
254 : : /* Get ACR [TYPE] [ 0 ] [Lc] [ data ] [Le] */
255 : : 0x80, 0x4c, 0x12, 0x00, 0x02, 0xDB, 0x00, 0x00
256 : : };
257 : 1 : uint8_t get_acr_aid[] = {
258 : : /* Get ACR [TYPE] [ 0 ] [Lc] [ data ] [Le]*/
259 : : 0x80, 0x4c, 0x11, 0x00, 0x07, 0xA0, 0x00, 0x00, 0x00, 0x79, 0x12, 0x02, 0x00
260 : : };
261 : 1 : uint8_t getresp[] = {
262 : : /* Get Response (max we can get) */
263 : : 0x00, 0xc0, 0x00, 0x00, 0x00
264 : : };
265 : :
266 : : /* P1=0x00: ACR table */
267 : : dwRecvLength = APDUBufSize;
268 : 1 : status = vreader_xfr_bytes(reader,
269 : : get_acr, sizeof(get_acr),
270 : : pbRecvBuffer, &dwRecvLength);
271 [ - + ]: 1 : g_assert_cmpint(status, ==, VREADER_OK);
272 [ - + ]: 1 : g_assert_cmpint(dwRecvLength, >, 2);
273 [ - + ]: 1 : g_assert_cmphex(pbRecvBuffer[dwRecvLength-2], ==, VCARD7816_SW1_SUCCESS);
274 [ - + ]: 1 : g_assert_cmphex(pbRecvBuffer[dwRecvLength-1], ==, 0x00);
275 : :
276 : : /* parse the response */
277 : 1 : parse_acr(pbRecvBuffer, dwRecvLength);
278 : :
279 : :
280 : : /* P1=0x01: ACR table by ACRID=0x0A */
281 : 1 : dwRecvLength = APDUBufSize;
282 : 1 : status = vreader_xfr_bytes(reader,
283 : : get_acr_arg, sizeof(get_acr_arg),
284 : : pbRecvBuffer, &dwRecvLength);
285 [ - + ]: 1 : g_assert_cmpint(status, ==, VREADER_OK);
286 [ - + ]: 1 : g_assert_cmpint(dwRecvLength, >, 2);
287 [ - + ]: 1 : g_assert_cmphex(pbRecvBuffer[dwRecvLength-2], ==, VCARD7816_SW1_SUCCESS);
288 [ - + ]: 1 : g_assert_cmphex(pbRecvBuffer[dwRecvLength-1], ==, 0x00);
289 : :
290 : : /* parse the response */
291 : 1 : parse_acr(pbRecvBuffer, dwRecvLength);
292 : :
293 : :
294 : : /* P1=0x01: ACR table by ACRID=0x0F (non-existing) */
295 : 1 : get_acr_arg[5] = 0x0F;
296 : 1 : dwRecvLength = APDUBufSize;
297 : 1 : status = vreader_xfr_bytes(reader,
298 : : get_acr_arg, sizeof(get_acr_arg),
299 : : pbRecvBuffer, &dwRecvLength);
300 [ - + ]: 1 : g_assert_cmpint(status, ==, VREADER_OK);
301 [ - + ]: 1 : g_assert_cmpint(dwRecvLength, ==, 2);
302 [ - + ]: 1 : g_assert_cmphex(pbRecvBuffer[dwRecvLength-2], ==, 0x6a);
303 [ - + ]: 1 : g_assert_cmphex(pbRecvBuffer[dwRecvLength-1], ==, 0x88);
304 : :
305 : :
306 : : /* P1=0x10: Applet/Object ACR table */
307 : 1 : get_acr[2] = 0x10;
308 : 1 : dwRecvLength = APDUBufSize;
309 : 1 : status = vreader_xfr_bytes(reader,
310 : : get_acr, sizeof(get_acr),
311 : : pbRecvBuffer, &dwRecvLength);
312 [ - + ]: 1 : g_assert_cmpint(status, ==, VREADER_OK);
313 : : /* This one is big, so we will get SW1 = 0x61 without the actual response */
314 [ - + ]: 1 : g_assert_cmpint(dwRecvLength, ==, 2);
315 [ - + ]: 1 : g_assert_cmphex(pbRecvBuffer[dwRecvLength-2], ==, VCARD7816_SW1_RESPONSE_BYTES);
316 [ - + ]: 1 : g_assert_cmphex(pbRecvBuffer[dwRecvLength-1], ==, 0x00);
317 : :
318 : : /* fetch the actual response */
319 : 1 : dwRecvLength = APDUBufSize;
320 : 1 : status = vreader_xfr_bytes(reader,
321 : : getresp, sizeof(getresp),
322 : : pbRecvBuffer, &dwRecvLength);
323 [ - + ]: 1 : g_assert_cmpint(status, ==, VREADER_OK);
324 [ - + ]: 1 : g_assert_cmpint(dwRecvLength, >, 2);
325 [ - + ]: 1 : g_assert_cmphex(pbRecvBuffer[dwRecvLength-2], ==, VCARD7816_SW1_RESPONSE_BYTES);
326 [ - + ]: 1 : g_assert_cmphex(pbRecvBuffer[dwRecvLength-1], >, 0x00);
327 : :
328 : : /* ignore the rest for now */
329 : :
330 : :
331 : : /* P1=0x11: Applet/Object ACR table by AID */
332 : 1 : dwRecvLength = APDUBufSize;
333 : 1 : status = vreader_xfr_bytes(reader,
334 : : get_acr_aid, sizeof(get_acr_aid),
335 : : pbRecvBuffer, &dwRecvLength);
336 [ - + ]: 1 : g_assert_cmpint(status, ==, VREADER_OK);
337 [ - + ]: 1 : g_assert_cmpint(dwRecvLength, >, 2);
338 [ - + ]: 1 : g_assert_cmphex(pbRecvBuffer[dwRecvLength-2], ==, VCARD7816_SW1_SUCCESS);
339 [ - + ]: 1 : g_assert_cmphex(pbRecvBuffer[dwRecvLength-1], ==, 0x00);
340 : :
341 : : /* parse the response */
342 : 1 : parse_acr(pbRecvBuffer, dwRecvLength);
343 : :
344 : :
345 : : /* P1=0x11: unknown AID should fail */
346 : 1 : get_acr_aid[11] = 0x11;
347 : 1 : dwRecvLength = APDUBufSize;
348 : 1 : status = vreader_xfr_bytes(reader,
349 : : get_acr_aid, sizeof(get_acr_aid),
350 : : pbRecvBuffer, &dwRecvLength);
351 [ - + ]: 1 : g_assert_cmpint(status, ==, VREADER_OK);
352 [ - + ]: 1 : g_assert_cmpint(dwRecvLength, ==, 2);
353 [ - + ]: 1 : g_assert_cmphex(pbRecvBuffer[dwRecvLength-2], ==, VCARD7816_SW1_P1_P2_ERROR);
354 [ - + ]: 1 : g_assert_cmphex(pbRecvBuffer[dwRecvLength-1], ==, 0x88);
355 : :
356 : :
357 : : /* P1=0x12: Applet/Object ACR table by OID */
358 : 1 : dwRecvLength = APDUBufSize;
359 : 1 : status = vreader_xfr_bytes(reader,
360 : : get_acr_coid, sizeof(get_acr_coid),
361 : : pbRecvBuffer, &dwRecvLength);
362 [ - + ]: 1 : g_assert_cmpint(status, ==, VREADER_OK);
363 [ - + ]: 1 : g_assert_cmpint(dwRecvLength, >, 2);
364 [ - + ]: 1 : g_assert_cmphex(pbRecvBuffer[dwRecvLength-2], ==, VCARD7816_SW1_SUCCESS);
365 [ - + ]: 1 : g_assert_cmphex(pbRecvBuffer[dwRecvLength-1], ==, 0x00);
366 : :
367 : : /* parse the response */
368 : 1 : parse_acr(pbRecvBuffer, dwRecvLength);
369 : :
370 : :
371 : : /* P1=0x12: unknown OID should fail */
372 : 1 : get_acr_coid[6] = 0xDB;
373 : 1 : dwRecvLength = APDUBufSize;
374 : 1 : status = vreader_xfr_bytes(reader,
375 : : get_acr_coid, sizeof(get_acr_coid),
376 : : pbRecvBuffer, &dwRecvLength);
377 [ - + ]: 1 : g_assert_cmpint(status, ==, VREADER_OK);
378 [ - + ]: 1 : g_assert_cmpint(dwRecvLength, ==, 2);
379 [ - + ]: 1 : g_assert_cmphex(pbRecvBuffer[dwRecvLength-2], ==, VCARD7816_SW1_P1_P2_ERROR);
380 [ - + ]: 1 : g_assert_cmphex(pbRecvBuffer[dwRecvLength-1], ==, 0x80);
381 : :
382 : :
383 : : /* P1=0x20: Access Method Provider table */
384 : 1 : get_acr[2] = 0x20;
385 : 1 : dwRecvLength = APDUBufSize;
386 : 1 : status = vreader_xfr_bytes(reader,
387 : : get_acr, sizeof(get_acr),
388 : : pbRecvBuffer, &dwRecvLength);
389 [ - + ]: 1 : g_assert_cmpint(status, ==, VREADER_OK);
390 [ - + ]: 1 : g_assert_cmpint(dwRecvLength, >, 2);
391 [ - + ]: 1 : g_assert_cmphex(pbRecvBuffer[dwRecvLength-2], ==, VCARD7816_SW1_SUCCESS);
392 [ - + ]: 1 : g_assert_cmphex(pbRecvBuffer[dwRecvLength-1], ==, 0x00);
393 : :
394 : : /* parse the response */
395 : 1 : parse_acr(pbRecvBuffer, dwRecvLength);
396 : :
397 : :
398 : : /* P1=0x21: Service Applet Table */
399 : 1 : get_acr[2] = 0x21;
400 : 1 : dwRecvLength = APDUBufSize;
401 : 1 : status = vreader_xfr_bytes(reader,
402 : : get_acr, sizeof(get_acr),
403 : : pbRecvBuffer, &dwRecvLength);
404 [ - + ]: 1 : g_assert_cmpint(status, ==, VREADER_OK);
405 [ - + ]: 1 : g_assert_cmpint(dwRecvLength, >, 2);
406 [ - + ]: 1 : g_assert_cmphex(pbRecvBuffer[dwRecvLength-2], ==, VCARD7816_SW1_SUCCESS);
407 [ - + ]: 1 : g_assert_cmphex(pbRecvBuffer[dwRecvLength-1], ==, 0x00);
408 : :
409 : : /* parse the response */
410 : 1 : parse_acr(pbRecvBuffer, dwRecvLength);
411 : :
412 : : /* Undocumented 0x40 returns ACR in different encoding */
413 : 1 : get_acr[2] = 0x40;
414 : 1 : dwRecvLength = APDUBufSize;
415 : 1 : status = vreader_xfr_bytes(reader,
416 : : get_acr, sizeof(get_acr),
417 : : pbRecvBuffer, &dwRecvLength);
418 [ - + ]: 1 : g_assert_cmpint(status, ==, VREADER_OK);
419 [ - + ]: 1 : g_assert_cmpint(dwRecvLength, >, 2);
420 [ - + ]: 1 : g_assert_cmphex(pbRecvBuffer[dwRecvLength-2], ==, VCARD7816_SW1_SUCCESS);
421 [ - + ]: 1 : g_assert_cmphex(pbRecvBuffer[dwRecvLength-1], ==, 0x00);
422 : :
423 : : /* parse the response */
424 : : //parse_acr(pbRecvBuffer, dwRecvLength);
425 : :
426 : : /* Undocumented 0x50 returns Applet/Object ACR in different encoding */
427 : 1 : get_acr[2] = 0x50;
428 : 1 : dwRecvLength = APDUBufSize;
429 : 1 : status = vreader_xfr_bytes(reader,
430 : : get_acr, sizeof(get_acr),
431 : : pbRecvBuffer, &dwRecvLength);
432 [ - + ]: 1 : g_assert_cmpint(status, ==, VREADER_OK);
433 [ - + ]: 1 : g_assert_cmpint(dwRecvLength, ==, 2);
434 [ - + ]: 1 : g_assert_cmphex(pbRecvBuffer[dwRecvLength-2], ==, VCARD7816_SW1_RESPONSE_BYTES);
435 [ - + ]: 1 : g_assert_cmphex(pbRecvBuffer[dwRecvLength-1], ==, 0x00);
436 : :
437 : : /* parse the response */
438 : : //parse_acr(pbRecvBuffer, dwRecvLength);
439 : :
440 : : /* Undocumented 0x60 returns AMP in different encoding */
441 : 1 : get_acr[2] = 0x60;
442 : 1 : dwRecvLength = APDUBufSize;
443 : 1 : status = vreader_xfr_bytes(reader,
444 : : get_acr, sizeof(get_acr),
445 : : pbRecvBuffer, &dwRecvLength);
446 [ - + ]: 1 : g_assert_cmpint(status, ==, VREADER_OK);
447 [ - + ]: 1 : g_assert_cmpint(dwRecvLength, >, 2);
448 [ - + ]: 1 : g_assert_cmphex(pbRecvBuffer[dwRecvLength-2], ==, VCARD7816_SW1_SUCCESS);
449 [ - + ]: 1 : g_assert_cmphex(pbRecvBuffer[dwRecvLength-1], ==, 0x00);
450 : :
451 : : /* parse the response */
452 : : //parse_acr(pbRecvBuffer, dwRecvLength);
453 : :
454 : : /* Undocumented 0x61 returns Service Applet in different encoding */
455 : 1 : get_acr[2] = 0x61;
456 : 1 : dwRecvLength = APDUBufSize;
457 : 1 : status = vreader_xfr_bytes(reader,
458 : : get_acr, sizeof(get_acr),
459 : : pbRecvBuffer, &dwRecvLength);
460 [ - + ]: 1 : g_assert_cmpint(status, ==, VREADER_OK);
461 [ - + ]: 1 : g_assert_cmpint(dwRecvLength, >, 2);
462 [ - + ]: 1 : g_assert_cmphex(pbRecvBuffer[dwRecvLength-2], ==, VCARD7816_SW1_SUCCESS);
463 [ - + ]: 1 : g_assert_cmphex(pbRecvBuffer[dwRecvLength-1], ==, 0x00);
464 : :
465 : : /* parse the response */
466 : : //parse_acr(pbRecvBuffer, dwRecvLength);
467 : 1 : }
468 : :
469 : 4 : static void do_login(VReader *reader)
470 : : {
471 : : VReaderStatus status;
472 : 4 : int dwRecvLength = APDUBufSize;
473 : : uint8_t pbRecvBuffer[APDUBufSize];
474 : 4 : uint8_t login[] = {
475 : : /* VERIFY [p1,p2=0 ] [Lc] [empty pin padded to 6 chars ] */
476 : : 0x00, 0x20, 0x00, 0x00, 0x06, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff
477 : : };
478 : 4 : uint8_t login_check[] = {
479 : : /* VERIFY [p1,p2=0 ] [Lc] */
480 : : 0x00, 0x20, 0x00, 0x00, 0x00
481 : : };
482 [ - + - + ]: 4 : g_assert_nonnull(reader);
483 : 4 : status = vreader_xfr_bytes(reader,
484 : : login, sizeof(login),
485 : : pbRecvBuffer, &dwRecvLength);
486 [ - + ]: 4 : g_assert_cmpint(status, ==, VREADER_OK);
487 [ - + ]: 4 : g_assert_cmphex(pbRecvBuffer[0], ==, VCARD7816_SW1_SUCCESS);
488 [ - + ]: 4 : g_assert_cmphex(pbRecvBuffer[1], ==, 0x00);
489 : :
490 : : /* Check the login status now */
491 : 4 : status = vreader_xfr_bytes(reader,
492 : : login_check, sizeof(login_check),
493 : : pbRecvBuffer, &dwRecvLength);
494 [ - + ]: 4 : g_assert_cmpint(status, ==, VREADER_OK);
495 [ - + ]: 4 : g_assert_cmphex(pbRecvBuffer[0], ==, VCARD7816_SW1_SUCCESS);
496 [ - + ]: 4 : g_assert_cmphex(pbRecvBuffer[1], ==, 0x00);
497 : 4 : }
498 : :
499 : 1 : static void test_cac_pki(void)
500 : : {
501 : 1 : VReader *reader = vreader_get_reader_by_id(0);
502 : :
503 : : /* select the first PKI applet */
504 : 1 : select_applet(reader, TEST_PKI);
505 : :
506 : : /* get properties */
507 : 1 : get_properties(reader, TEST_PKI);
508 : :
509 : : /* get the TAG buffer length */
510 : 1 : read_buffer(reader, CAC_FILE_TAG, TEST_PKI);
511 : :
512 : : /* get the VALUE buffer length */
513 : 1 : read_buffer(reader, CAC_FILE_VALUE, TEST_PKI);
514 : :
515 : 1 : vreader_free(reader); /* get by id ref */
516 : 1 : }
517 : :
518 : 1 : static void test_cac_ccc(void)
519 : : {
520 : 1 : VReader *reader = vreader_get_reader_by_id(0);
521 : :
522 : : /* select the CCC */
523 : 1 : select_applet(reader, TEST_CCC);
524 : :
525 : : /* get properties */
526 : 1 : get_properties(reader, TEST_CCC);
527 : :
528 : : /* get the TAG buffer length */
529 : 1 : read_buffer(reader, CAC_FILE_TAG, TEST_CCC);
530 : :
531 : : /* get the VALUE buffer length */
532 : 1 : read_buffer(reader, CAC_FILE_VALUE, TEST_CCC);
533 : :
534 : 1 : vreader_free(reader); /* get by id ref */
535 : 1 : }
536 : :
537 : 1 : static void test_cac_aca(void)
538 : : {
539 : 1 : VReader *reader = vreader_get_reader_by_id(0);
540 : :
541 : : /* select the ACA */
542 : 1 : select_applet(reader, TEST_ACA);
543 : :
544 : : /* get properties */
545 : 1 : get_properties(reader, TEST_ACA);
546 : :
547 : : /* get ACR */
548 : 1 : get_acr(reader);
549 : :
550 : 1 : vreader_free(reader); /* get by id ref */
551 : 1 : }
552 : :
553 : 1 : static void test_login(void)
554 : : {
555 : 1 : VReader *reader = vreader_get_reader_by_id(0);
556 : :
557 : : /* select the ACA */
558 : 1 : select_applet(reader, TEST_ACA);
559 : :
560 : 1 : do_login(reader);
561 : :
562 : 1 : vreader_free(reader); /* get by id ref */
563 : 1 : }
564 : :
565 : 1 : static void test_sign(void)
566 : : {
567 : 1 : VReader *reader = vreader_get_reader_by_id(0);
568 : :
569 : : /* select the ACA */
570 : 1 : select_applet(reader, TEST_ACA);
571 : :
572 : 1 : do_login(reader);
573 : :
574 : : /* select the PKI */
575 : 1 : select_applet(reader, TEST_PKI);
576 : :
577 : 1 : do_sign(reader, 0);
578 : :
579 : : /* test also multipart signatures */
580 : 1 : do_sign(reader, 1);
581 : :
582 : 1 : vreader_free(reader); /* get by id ref */
583 : 1 : }
584 : :
585 : 1 : static void test_decipher(void)
586 : : {
587 : 1 : VReader *reader = vreader_get_reader_by_id(0);
588 : :
589 : : /* select the ACA */
590 : 1 : select_applet(reader, TEST_ACA);
591 : :
592 : 1 : do_login(reader);
593 : :
594 : : /* select the PKI */
595 : 1 : select_applet(reader, TEST_PKI);
596 : :
597 : 1 : do_decipher(reader);
598 : :
599 : 1 : vreader_free(reader); /* get by id ref */
600 : 1 : }
601 : :
602 : 1 : static void test_remove(void)
603 : : {
604 : 1 : VReader *reader = vreader_get_reader_by_id(0);
605 : : VReaderStatus status;
606 : :
607 [ - + - + ]: 1 : g_assert_nonnull(reader);
608 : :
609 : 1 : status = vreader_remove_reader(reader);
610 [ - + ]: 1 : g_assert_cmpint(status, ==, VREADER_OK);
611 : 1 : vreader_free(reader); /* get by id ref */
612 : :
613 : 1 : reader = vreader_get_reader_by_id(0);
614 [ - + - + ]: 1 : g_assert_null(reader);
615 : 1 : }
616 : :
617 : 1 : static void test_select_coid(void)
618 : : {
619 : 1 : VReader *reader = vreader_get_reader_by_id(0);
620 : 1 : unsigned char coid[] = "\xDB\x00";
621 : 1 : uint8_t acf_aid[] = {
622 : : 0xA0, 0x00, 0x00, 0x01, 0x16, 0x30, 0x00
623 : : };
624 : :
625 : : /* select the CCC */
626 : 1 : select_applet(reader, TEST_CCC);
627 : :
628 : : /* get properties */
629 : 1 : get_properties(reader, TEST_CCC);
630 : :
631 : : /* select existing OID */
632 : 1 : select_coid_good(reader, coid);
633 : :
634 : : /* select non-existing OID */
635 : 1 : coid[1] = 0xDB;
636 : 1 : select_coid_bad(reader, coid);
637 : :
638 : : /* select the ACF */
639 : 1 : select_aid(reader, acf_aid, sizeof(acf_aid));
640 : :
641 : : /* select existing default OID */
642 : 1 : coid[0] = 0x30;
643 : 1 : coid[1] = 0x00;
644 : 1 : select_coid_good(reader, coid);
645 : :
646 : : /* select existing non-default OID */
647 : 1 : coid[0] = 0x90;
648 : 1 : select_coid_good(reader, coid);
649 : :
650 : : /* select non-existing OID */
651 : 1 : coid[1] = 0x90;
652 : 1 : select_coid_bad(reader, coid);
653 : :
654 : 1 : vreader_free(reader); /* get by id ref */
655 : 1 : }
656 : :
657 : 1 : static void test_invalid_properties(void)
658 : : {
659 : 1 : VReader *reader = vreader_get_reader_by_id(0);
660 : : VReaderStatus status;
661 : 1 : int dwRecvLength = APDUBufSize;
662 : : uint8_t pbRecvBuffer[APDUBufSize];
663 : 1 : uint8_t get_properties[] = {
664 : : /* Get properties [Le] [RFU] */
665 : : 0x80, 0x56, 0x01, 0x00, 0x00, 0x00, 0x00
666 : : };
667 : : size_t get_properties_len = 5;
668 : :
669 [ - + - + ]: 1 : g_assert_nonnull(reader);
670 : :
671 : 1 : select_applet(reader, TEST_CCC);
672 : :
673 : : /* P1 = 0x00 is not supported */
674 : 1 : get_properties[2] = 0x00;
675 : 1 : dwRecvLength = APDUBufSize;
676 : 1 : status = vreader_xfr_bytes(reader,
677 : : get_properties, get_properties_len,
678 : : pbRecvBuffer, &dwRecvLength);
679 [ - + ]: 1 : g_assert_cmpint(status, ==, VREADER_OK);
680 [ - + ]: 1 : g_assert_cmpint(dwRecvLength, ==, 2);
681 [ - + ]: 1 : g_assert_cmpint(pbRecvBuffer[0], ==, VCARD7816_SW1_P1_P2_ERROR);
682 [ - + ]: 1 : g_assert_cmpint(pbRecvBuffer[1], ==, 0x86);
683 : 1 : get_properties[2] = 0x01;
684 : :
685 : : /* P1 = 0x01 fails with additional data provided */
686 : : get_properties[2] = 0x01;
687 : 1 : get_properties[4] = 0x02;
688 : 1 : dwRecvLength = APDUBufSize;
689 : 1 : status = vreader_xfr_bytes(reader,
690 : : get_properties, sizeof(get_properties),
691 : : pbRecvBuffer, &dwRecvLength);
692 [ - + ]: 1 : g_assert_cmpint(status, ==, VREADER_OK);
693 [ - + ]: 1 : g_assert_cmpint(dwRecvLength, ==, 2);
694 [ - + ]: 1 : g_assert_cmpint(pbRecvBuffer[0], ==, VCARD7816_SW1_COMMAND_ERROR);
695 [ - + ]: 1 : g_assert_cmpint(pbRecvBuffer[1], ==, 0x84);
696 : 1 : get_properties[2] = 0x01;
697 : :
698 : : /* P2 needs to be zero */
699 : 1 : get_properties[3] = 0x01;
700 : 1 : get_properties[4] = 0x00;
701 : 1 : dwRecvLength = APDUBufSize;
702 : 1 : status = vreader_xfr_bytes(reader,
703 : : get_properties, get_properties_len,
704 : : pbRecvBuffer, &dwRecvLength);
705 [ - + ]: 1 : g_assert_cmpint(status, ==, VREADER_OK);
706 [ - + ]: 1 : g_assert_cmpint(dwRecvLength, ==, 2);
707 [ - + ]: 1 : g_assert_cmpint(pbRecvBuffer[0], ==, VCARD7816_SW1_P1_P2_ERROR);
708 [ - + ]: 1 : g_assert_cmpint(pbRecvBuffer[1], ==, 0x86);
709 : 1 : get_properties[3] = 0x00;
710 : :
711 : : /* P1 = 0x02 requires some data (empty is invalid) */
712 : 1 : get_properties[2] = 0x02;
713 : 1 : dwRecvLength = APDUBufSize;
714 : 1 : status = vreader_xfr_bytes(reader,
715 : : get_properties, get_properties_len,
716 : : pbRecvBuffer, &dwRecvLength);
717 [ - + ]: 1 : g_assert_cmpint(status, ==, VREADER_OK);
718 [ - + ]: 1 : g_assert_cmpint(dwRecvLength, ==, 2);
719 [ - + ]: 1 : g_assert_cmpint(pbRecvBuffer[0], ==, VCARD7816_SW1_COMMAND_ERROR);
720 [ - + ]: 1 : g_assert_cmpint(pbRecvBuffer[1], ==, 0x84);
721 : :
722 : : /* P1 = 0x02 with invalid data fails */
723 : 1 : get_properties[4] = 0x02;
724 : 1 : get_properties[6] = 0xFF;
725 : 1 : dwRecvLength = APDUBufSize;
726 : 1 : status = vreader_xfr_bytes(reader,
727 : : get_properties, sizeof(get_properties),
728 : : pbRecvBuffer, &dwRecvLength);
729 [ - + ]: 1 : g_assert_cmpint(status, ==, VREADER_OK);
730 [ - + ]: 1 : g_assert_cmpint(dwRecvLength, ==, 2);
731 [ - + ]: 1 : g_assert_cmpint(pbRecvBuffer[0], ==, VCARD7816_SW1_P1_P2_ERROR);
732 [ - + ]: 1 : g_assert_cmpint(pbRecvBuffer[1], ==, 0x88);
733 : :
734 : : /* P1 = 0x88 is invalid */
735 : 1 : get_properties[2] = 0x88;
736 : 1 : dwRecvLength = APDUBufSize;
737 : 1 : status = vreader_xfr_bytes(reader,
738 : : get_properties, get_properties_len,
739 : : pbRecvBuffer, &dwRecvLength);
740 [ - + ]: 1 : g_assert_cmpint(status, ==, VREADER_OK);
741 [ - + ]: 1 : g_assert_cmpint(dwRecvLength, ==, 2);
742 [ - + ]: 1 : g_assert_cmpint(pbRecvBuffer[0], ==, VCARD7816_SW1_P1_P2_ERROR);
743 [ - + ]: 1 : g_assert_cmpint(pbRecvBuffer[1], ==, 0x86);
744 : :
745 : 1 : vreader_free(reader); /* get by id ref */
746 : 1 : }
747 : :
748 : 1 : static void test_invalid_select(void)
749 : : {
750 : 1 : VReader *reader = vreader_get_reader_by_id(0);
751 : : VReaderStatus status;
752 : 1 : int dwRecvLength = APDUBufSize;
753 : : uint8_t pbRecvBuffer[APDUBufSize];
754 : 1 : uint8_t selfile[] = {
755 : : 0x00, 0xa4, 0x02, 0x00, 0x07, 0xa0, 0x00, 0x00, 0x00, 0x79, 0x01, 0x00
756 : : };
757 : :
758 [ - + - + ]: 1 : g_assert_nonnull(reader);
759 : :
760 : 1 : select_applet(reader, TEST_CCC);
761 : :
762 : : /* CAC applets handle only the P1 = 0x02: Empty OID is not valid */
763 : 1 : selfile[4] = 0x00;
764 : 1 : dwRecvLength = APDUBufSize;
765 : 1 : status = vreader_xfr_bytes(reader,
766 : : selfile, 5,
767 : : pbRecvBuffer, &dwRecvLength);
768 [ - + ]: 1 : g_assert_cmpint(status, ==, VREADER_OK);
769 [ - + ]: 1 : g_assert_cmpint(dwRecvLength, ==, 2);
770 [ - + ]: 1 : g_assert_cmpint(pbRecvBuffer[0], ==, VCARD7816_SW1_COMMAND_ERROR);
771 [ - + ]: 1 : g_assert_cmpint(pbRecvBuffer[1], ==, 0x84);
772 : :
773 : : /* CAC applets handle only the P1 = 0x02: 7B OID is not valid */
774 : 1 : selfile[4] = 0x07;
775 : 1 : dwRecvLength = APDUBufSize;
776 : 1 : status = vreader_xfr_bytes(reader,
777 : : selfile, sizeof(selfile),
778 : : pbRecvBuffer, &dwRecvLength);
779 [ - + ]: 1 : g_assert_cmpint(status, ==, VREADER_OK);
780 [ - + ]: 1 : g_assert_cmpint(dwRecvLength, ==, 2);
781 [ - + ]: 1 : g_assert_cmpint(pbRecvBuffer[0], ==, VCARD7816_SW1_COMMAND_ERROR);
782 [ - + ]: 1 : g_assert_cmpint(pbRecvBuffer[1], ==, 0x84);
783 : :
784 : : /* TODO check the iso7816 code handling the remaining SELECT APDUs */
785 : :
786 : 1 : vreader_free(reader); /* get by id ref */
787 : 1 : }
788 : :
789 : 1 : static void test_invalid_instruction(void)
790 : : {
791 : 1 : VReader *reader = vreader_get_reader_by_id(0);
792 : : VReaderStatus status;
793 : 1 : int dwRecvLength = APDUBufSize;
794 : : uint8_t pbRecvBuffer[APDUBufSize];
795 : 1 : uint8_t apdu[] = {
796 : : 0x00, 0xff, 0x00, 0x00, 0x00
797 : : };
798 : :
799 [ - + - + ]: 1 : g_assert_nonnull(reader);
800 : :
801 : : /* Card Capability Container */
802 : 1 : select_applet(reader, TEST_CCC);
803 : :
804 : : /* 0xFF is invalid instruction everywhere, but fails in apdu_ins_to_string() */
805 : : /*dwRecvLength = APDUBufSize;
806 : : status = vreader_xfr_bytes(reader,
807 : : apdu, sizeof(apdu),
808 : : pbRecvBuffer, &dwRecvLength);
809 : : g_assert_cmpint(status, ==, VREADER_OK);
810 : : g_assert_cmpint(dwRecvLength, ==, 2);
811 : : g_assert_cmpint(pbRecvBuffer[0], ==, VCARD7816_SW1_INS_ERROR);
812 : : g_assert_cmpint(pbRecvBuffer[1], ==, 0x00);*/
813 : :
814 : : /* CCC Applet does not know GET ACR instruction */
815 : 1 : apdu[1] = 0x4c;
816 : 1 : dwRecvLength = APDUBufSize;
817 : 1 : status = vreader_xfr_bytes(reader,
818 : : apdu, sizeof(apdu),
819 : : pbRecvBuffer, &dwRecvLength);
820 [ - + ]: 1 : g_assert_cmpint(status, ==, VREADER_OK);
821 [ - + ]: 1 : g_assert_cmpint(dwRecvLength, ==, 2);
822 [ - + ]: 1 : g_assert_cmpint(pbRecvBuffer[0], ==, VCARD7816_SW1_INS_ERROR);
823 [ - + ]: 1 : g_assert_cmpint(pbRecvBuffer[1], ==, 0x00);
824 : :
825 : : /* TODO check the iso7816 code handling the remaining SELECT APDUs */
826 : :
827 : :
828 : : /* PKI Applet */
829 : 1 : select_applet(reader, TEST_PKI);
830 : :
831 : : /* Update Buffer is not supported */
832 : 1 : apdu[1] = 0x58;
833 : 1 : dwRecvLength = APDUBufSize;
834 : 1 : status = vreader_xfr_bytes(reader,
835 : : apdu, sizeof(apdu),
836 : : pbRecvBuffer, &dwRecvLength);
837 [ - + ]: 1 : g_assert_cmpint(status, ==, VREADER_OK);
838 [ - + ]: 1 : g_assert_cmpint(dwRecvLength, ==, 2);
839 [ - + ]: 1 : g_assert_cmpint(pbRecvBuffer[0], ==, VCARD7816_SW1_COMMAND_ERROR);
840 [ - + ]: 1 : g_assert_cmpint(pbRecvBuffer[1], ==, 0x85);
841 : :
842 : 1 : vreader_free(reader); /* get by id ref */
843 : 1 : }
844 : :
845 : 4 : static void test_invalid_read_buffer_applet(VReader *reader, int object_type)
846 : : {
847 : :
848 : : VReaderStatus status;
849 : 4 : int dwRecvLength = APDUBufSize;
850 : : uint8_t pbRecvBuffer[APDUBufSize];
851 : 4 : uint8_t apdu[] = {
852 : : 0x00, 0x52, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00
853 : : };
854 : : int apdu_len;
855 : :
856 : 4 : select_applet(reader, object_type);
857 : :
858 : : /* Empty body is not accepted */
859 : 4 : apdu[4] = 0x00;
860 : : apdu_len = 5;
861 : 4 : dwRecvLength = APDUBufSize;
862 : 4 : status = vreader_xfr_bytes(reader,
863 : : apdu, apdu_len,
864 : : pbRecvBuffer, &dwRecvLength);
865 [ - + ]: 4 : g_assert_cmpint(status, ==, VREADER_OK);
866 [ - + ]: 4 : g_assert_cmpint(dwRecvLength, ==, 2);
867 [ - + ]: 4 : g_assert_cmpint(pbRecvBuffer[0], ==, VCARD7816_SW1_COMMAND_ERROR);
868 [ - + ]: 4 : g_assert_cmpint(pbRecvBuffer[1], ==, 0x84);
869 : :
870 : : /* 4B is too much */
871 : 4 : apdu[4] = 0x04;
872 : : apdu_len = 9;
873 : 4 : dwRecvLength = APDUBufSize;
874 : 4 : status = vreader_xfr_bytes(reader,
875 : : apdu, apdu_len,
876 : : pbRecvBuffer, &dwRecvLength);
877 [ - + ]: 4 : g_assert_cmpint(status, ==, VREADER_OK);
878 [ - + ]: 4 : g_assert_cmpint(dwRecvLength, ==, 2);
879 [ - + ]: 4 : g_assert_cmpint(pbRecvBuffer[0], ==, VCARD7816_SW1_COMMAND_ERROR);
880 [ - + ]: 4 : g_assert_cmpint(pbRecvBuffer[1], ==, 0x84);
881 : :
882 : : /* The first byte is invalid (nor tag, nor value) */
883 : 4 : apdu[4] = 0x02;
884 : 4 : apdu[5] = 0x06;
885 : : apdu_len = 7;
886 : 4 : dwRecvLength = APDUBufSize;
887 : 4 : status = vreader_xfr_bytes(reader,
888 : : apdu, apdu_len,
889 : : pbRecvBuffer, &dwRecvLength);
890 [ - + ]: 4 : g_assert_cmpint(status, ==, VREADER_OK);
891 [ - + ]: 4 : g_assert_cmpint(dwRecvLength, ==, 2);
892 [ - + ]: 4 : g_assert_cmpint(pbRecvBuffer[0], ==, VCARD7816_SW1_COMMAND_ERROR);
893 [ - + ]: 4 : g_assert_cmpint(pbRecvBuffer[1], ==, 0x84);
894 : :
895 : : /* Read tag: P1 and P2 defines offset -- overunning the buffer should fail */
896 : 4 : apdu[2] = 0x08;
897 : 4 : apdu[3] = 0x08; /* <- Large enough */
898 : 4 : apdu[5] = 0x01;
899 : 4 : dwRecvLength = APDUBufSize;
900 : 4 : status = vreader_xfr_bytes(reader,
901 : : apdu, apdu_len,
902 : : pbRecvBuffer, &dwRecvLength);
903 [ - + ]: 4 : g_assert_cmpint(status, ==, VREADER_OK);
904 [ - + ]: 4 : g_assert_cmpint(dwRecvLength, ==, 2);
905 [ - + ]: 4 : g_assert_cmpint(pbRecvBuffer[0], ==, VCARD7816_SW1_P1_P2_ERROR);
906 [ - + ]: 4 : g_assert_cmpint(pbRecvBuffer[1], ==, 0x86);
907 : :
908 : : /* Read value: P1 and P2 defines offset -- overunning the buffer should fail */
909 : 4 : apdu[5] = 0x02;
910 : 4 : dwRecvLength = APDUBufSize;
911 : 4 : status = vreader_xfr_bytes(reader,
912 : : apdu, apdu_len,
913 : : pbRecvBuffer, &dwRecvLength);
914 [ - + ]: 4 : g_assert_cmpint(status, ==, VREADER_OK);
915 [ - + ]: 4 : g_assert_cmpint(dwRecvLength, ==, 2);
916 [ - + ]: 4 : g_assert_cmpint(pbRecvBuffer[0], ==, VCARD7816_SW1_P1_P2_ERROR);
917 [ - + ]: 4 : g_assert_cmpint(pbRecvBuffer[1], ==, 0x86);
918 : 4 : }
919 : :
920 : 1 : static void test_invalid_read_buffer(void)
921 : : {
922 : 1 : VReader *reader = vreader_get_reader_by_id(0);
923 : :
924 [ - + - + ]: 1 : g_assert_nonnull(reader);
925 : :
926 : 1 : test_invalid_read_buffer_applet(reader, TEST_CCC);
927 : 1 : test_invalid_read_buffer_applet(reader, TEST_PKI);
928 : 1 : test_invalid_read_buffer_applet(reader, TEST_PASSTHROUGH);
929 : 1 : test_invalid_read_buffer_applet(reader, TEST_EMPTY);
930 : :
931 : 1 : vreader_free(reader); /* get by id ref */
932 : 1 : }
933 : :
934 : 1 : static void test_invalid_acr(void)
935 : : {
936 : 1 : VReader *reader = vreader_get_reader_by_id(0);
937 : : VReaderStatus status;
938 : 1 : int dwRecvLength = APDUBufSize;
939 : : uint8_t pbRecvBuffer[APDUBufSize];
940 : 1 : uint8_t apdu[] = {
941 : : 0x00, 0x4c, 0x00, 0x00, 0x00, 0x00, 0x00
942 : : };
943 : : size_t apdu_len = 5;
944 : :
945 [ - + - + ]: 1 : g_assert_nonnull(reader);
946 : :
947 : 1 : select_applet(reader, TEST_ACA);
948 : :
949 : : /* P2 needs to be zero */
950 : 1 : apdu[3] = 0xff;
951 : 1 : dwRecvLength = APDUBufSize;
952 : 1 : status = vreader_xfr_bytes(reader,
953 : : apdu, apdu_len,
954 : : pbRecvBuffer, &dwRecvLength);
955 [ - + ]: 1 : g_assert_cmpint(status, ==, VREADER_OK);
956 [ - + ]: 1 : g_assert_cmpint(dwRecvLength, ==, 2);
957 [ - + ]: 1 : g_assert_cmpint(pbRecvBuffer[0], ==, VCARD7816_SW1_P1_P2_ERROR);
958 [ - + ]: 1 : g_assert_cmpint(pbRecvBuffer[1], ==, 0x86);
959 : 1 : apdu[3] = 0x00;
960 : :
961 : : /* For P1 = 0x00 we can not send any data */
962 : 1 : apdu[4] = 0x02;
963 : 1 : dwRecvLength = APDUBufSize;
964 : 1 : status = vreader_xfr_bytes(reader,
965 : : apdu, sizeof(apdu),
966 : : pbRecvBuffer, &dwRecvLength);
967 [ - + ]: 1 : g_assert_cmpint(status, ==, VREADER_OK);
968 [ - + ]: 1 : g_assert_cmpint(dwRecvLength, ==, 2);
969 [ - + ]: 1 : g_assert_cmpint(pbRecvBuffer[0], ==, VCARD7816_SW1_COMMAND_ERROR);
970 [ - + ]: 1 : g_assert_cmpint(pbRecvBuffer[1], ==, 0x84);
971 : :
972 : : /* For P1 = 0x01 we need to send exactly one byte */
973 : 1 : apdu[2] = 0x01;
974 : 1 : dwRecvLength = APDUBufSize;
975 : 1 : status = vreader_xfr_bytes(reader,
976 : : apdu, sizeof(apdu),
977 : : pbRecvBuffer, &dwRecvLength);
978 [ - + ]: 1 : g_assert_cmpint(status, ==, VREADER_OK);
979 [ - + ]: 1 : g_assert_cmpint(dwRecvLength, ==, 2);
980 [ - + ]: 1 : g_assert_cmpint(pbRecvBuffer[0], ==, VCARD7816_SW1_COMMAND_ERROR);
981 [ - + ]: 1 : g_assert_cmpint(pbRecvBuffer[1], ==, 0x84);
982 : :
983 : : /* For P1 = 0x10 we can not send any data */
984 : 1 : apdu[2] = 0x10;
985 : 1 : apdu[4] = 0x02;
986 : 1 : dwRecvLength = APDUBufSize;
987 : 1 : status = vreader_xfr_bytes(reader,
988 : : apdu, sizeof(apdu),
989 : : pbRecvBuffer, &dwRecvLength);
990 [ - + ]: 1 : g_assert_cmpint(status, ==, VREADER_OK);
991 [ - + ]: 1 : g_assert_cmpint(dwRecvLength, ==, 2);
992 [ - + ]: 1 : g_assert_cmpint(pbRecvBuffer[0], ==, VCARD7816_SW1_COMMAND_ERROR);
993 [ - + ]: 1 : g_assert_cmpint(pbRecvBuffer[1], ==, 0x84);
994 : :
995 : : /* For P1 = 0x11 we need to send exactly 7B (2 are not enough) */
996 : 1 : apdu[2] = 0x11;
997 : 1 : dwRecvLength = APDUBufSize;
998 : 1 : status = vreader_xfr_bytes(reader,
999 : : apdu, sizeof(apdu),
1000 : : pbRecvBuffer, &dwRecvLength);
1001 [ - + ]: 1 : g_assert_cmpint(status, ==, VREADER_OK);
1002 [ - + ]: 1 : g_assert_cmpint(dwRecvLength, ==, 2);
1003 [ - + ]: 1 : g_assert_cmpint(pbRecvBuffer[0], ==, VCARD7816_SW1_COMMAND_ERROR);
1004 [ - + ]: 1 : g_assert_cmpint(pbRecvBuffer[1], ==, 0x84);
1005 : :
1006 : : /* For P1 = 0x12 we need to send exactly 2B (1 is not enough) */
1007 : 1 : apdu[2] = 0x12;
1008 : 1 : apdu[4] = 0x01;
1009 : 1 : dwRecvLength = APDUBufSize;
1010 : 1 : status = vreader_xfr_bytes(reader,
1011 : : apdu, 6,
1012 : : pbRecvBuffer, &dwRecvLength);
1013 [ - + ]: 1 : g_assert_cmpint(status, ==, VREADER_OK);
1014 [ - + ]: 1 : g_assert_cmpint(dwRecvLength, ==, 2);
1015 [ - + ]: 1 : g_assert_cmpint(pbRecvBuffer[0], ==, VCARD7816_SW1_COMMAND_ERROR);
1016 [ - + ]: 1 : g_assert_cmpint(pbRecvBuffer[1], ==, 0x84);
1017 : :
1018 : : /* For P1 = 0x20 we can not send any data */
1019 : 1 : apdu[2] = 0x20;
1020 : 1 : dwRecvLength = APDUBufSize;
1021 : 1 : status = vreader_xfr_bytes(reader,
1022 : : apdu, 6,
1023 : : pbRecvBuffer, &dwRecvLength);
1024 [ - + ]: 1 : g_assert_cmpint(status, ==, VREADER_OK);
1025 [ - + ]: 1 : g_assert_cmpint(dwRecvLength, ==, 2);
1026 [ - + ]: 1 : g_assert_cmpint(pbRecvBuffer[0], ==, VCARD7816_SW1_COMMAND_ERROR);
1027 [ - + ]: 1 : g_assert_cmpint(pbRecvBuffer[1], ==, 0x84);
1028 : :
1029 : : /* For P1 = 0x21 we can not send any data */
1030 : 1 : apdu[2] = 0x21;
1031 : 1 : dwRecvLength = APDUBufSize;
1032 : 1 : status = vreader_xfr_bytes(reader,
1033 : : apdu, 6,
1034 : : pbRecvBuffer, &dwRecvLength);
1035 [ - + ]: 1 : g_assert_cmpint(status, ==, VREADER_OK);
1036 [ - + ]: 1 : g_assert_cmpint(dwRecvLength, ==, 2);
1037 [ - + ]: 1 : g_assert_cmpint(pbRecvBuffer[0], ==, VCARD7816_SW1_COMMAND_ERROR);
1038 [ - + ]: 1 : g_assert_cmpint(pbRecvBuffer[1], ==, 0x84);
1039 : :
1040 : :
1041 : 1 : vreader_free(reader); /* get by id ref */
1042 : 1 : }
1043 : :
1044 : 1 : static void test_passthrough_applet(void)
1045 : : {
1046 : 1 : uint8_t person_coid[2] = {0x02, 0x00};
1047 : :
1048 : 1 : VReader *reader = vreader_get_reader_by_id(0);
1049 : :
1050 : : /* select the passthrough applet */
1051 : 1 : select_applet(reader, TEST_PASSTHROUGH);
1052 : :
1053 : : /* get properties */
1054 : 1 : get_properties_coid(reader, person_coid, TEST_GENERIC);
1055 : :
1056 : : /* These objects requires a PIN to read the value buffer */
1057 : 1 : do_login(reader);
1058 : :
1059 : : /* get the TAG buffer length */
1060 : 1 : read_buffer(reader, CAC_FILE_TAG, TEST_EMPTY_BUFFER);
1061 : :
1062 : : /* get the VALUE buffer length */
1063 : 1 : read_buffer(reader, CAC_FILE_VALUE, TEST_EMPTY_BUFFER);
1064 : :
1065 : : /* the buffers are empty without physical card */
1066 : :
1067 : 1 : vreader_free(reader); /* get by id ref */
1068 : 1 : }
1069 : :
1070 : : #define MAX_ATR_LEN 100
1071 : : #define CAC_ATR "\x3B\x7A\x18\x00\x00\x73\x66\x74\x65\x20\x63\x64\x31\x34\x34"
1072 : : #define CAC_ATR_LEN (sizeof(CAC_ATR) - 1)
1073 : 1 : static void test_atr(void)
1074 : : {
1075 : 1 : VReader *reader = vreader_get_reader_by_id(0);
1076 : 1 : unsigned char *atr = g_malloc0(MAX_ATR_LEN);
1077 : 1 : int atr_len = MAX_ATR_LEN;
1078 : :
1079 : : /* Cycle off and on to get the ATR from the card */
1080 : 1 : vreader_power_off(reader);
1081 : 1 : vreader_power_on(reader, atr, &atr_len);
1082 : :
1083 [ - + - + : 1 : g_assert_cmpmem(atr, atr_len, CAC_ATR, CAC_ATR_LEN);
- + ]
1084 : :
1085 : 1 : vreader_free(reader); /* get by id ref */
1086 : 1 : g_free(atr);
1087 : 1 : }
1088 : :
1089 : 1 : static void libcacard_finalize(void)
1090 : : {
1091 : 1 : VReader *reader = vreader_get_reader_by_id(0);
1092 : :
1093 : : /* This actually still generates events */
1094 [ - + ]: 1 : if (reader) /*if /remove didn't run */
1095 : 0 : vreader_remove_reader(reader);
1096 : :
1097 : : /* This probably supposed to be a event that terminates the loop */
1098 : 1 : vevent_queue_vevent(vevent_new(VEVENT_LAST, reader, NULL));
1099 : :
1100 : : /* join */
1101 : 1 : g_thread_join(thread);
1102 : :
1103 : : /* Clean up */
1104 : 1 : vreader_free(reader);
1105 : :
1106 : 1 : vcard_emul_finalize();
1107 : 1 : }
1108 : :
1109 : 1 : int main(int argc, char *argv[])
1110 : : {
1111 : : int ret;
1112 : :
1113 : 1 : g_test_init(&argc, &argv, NULL);
1114 : :
1115 : 1 : loop = g_main_loop_new(NULL, TRUE);
1116 : :
1117 : 1 : libcacard_init();
1118 : :
1119 : 1 : g_test_add_func("/libcacard/hexdump", test_hex_dump);
1120 : 1 : g_test_add_func("/libcacard/list", test_list);
1121 : 1 : g_test_add_func("/libcacard/card-remove-insert", test_card_remove_insert);
1122 : 1 : g_test_add_func("/libcacard/xfer", test_xfer);
1123 : 1 : g_test_add_func("/libcacard/select-coid", test_select_coid);
1124 : 1 : g_test_add_func("/libcacard/cac-pki", test_cac_pki);
1125 : 1 : g_test_add_func("/libcacard/cac-ccc", test_cac_ccc);
1126 : 1 : g_test_add_func("/libcacard/cac-aca", test_cac_aca);
1127 : 1 : g_test_add_func("/libcacard/get-response", test_get_response);
1128 : 1 : g_test_add_func("/libcacard/check-login-count", check_login_count);
1129 : 1 : g_test_add_func("/libcacard/login", test_login);
1130 : 1 : g_test_add_func("/libcacard/sign", test_sign);
1131 : 1 : g_test_add_func("/libcacard/decipher", test_decipher);
1132 : 1 : g_test_add_func("/libcacard/empty-applets", test_empty_applets);
1133 : 1 : g_test_add_func("/libcacard/gp-applet", test_gp_applet);
1134 : 1 : g_test_add_func("/libcacard/msft-applet", test_msft_applet);
1135 : 1 : g_test_add_func("/libcacard/invalid-properties-apdu", test_invalid_properties);
1136 : 1 : g_test_add_func("/libcacard/invalid-select-apdu", test_invalid_select);
1137 : 1 : g_test_add_func("/libcacard/invalid-instruction", test_invalid_instruction);
1138 : 1 : g_test_add_func("/libcacard/invalid-read-buffer", test_invalid_read_buffer);
1139 : 1 : g_test_add_func("/libcacard/invalid-acr", test_invalid_acr);
1140 : 1 : g_test_add_func("/libcacard/get-atr", test_atr);
1141 : : /* Even without the card, the passthrough applets are present */
1142 : 1 : g_test_add_func("/libcacard/passthrough-applet", test_passthrough_applet);
1143 : : /* TODO: Card/reader resets */
1144 : 1 : g_test_add_func("/libcacard/remove", test_remove);
1145 : :
1146 : 1 : ret = g_test_run();
1147 : :
1148 : 1 : g_main_loop_unref(loop);
1149 : :
1150 : 1 : libcacard_finalize();
1151 : : return ret;
1152 : : }
1153 : :
1154 : : /* vim: set ts=4 sw=4 tw=0 noet expandtab: */
|