Branch data Line data Source code
1 : : /*
2 : : * Shared test functions for libCACard
3 : : *
4 : : * Copyright 2018 - 2022 Red Hat, Inc.
5 : : *
6 : : * Author: Jakub Jelen <jjelen@redhat.com>
7 : : *
8 : : * This code is licensed under the GNU LGPL, version 2.1 or later.
9 : : * See the COPYING file in the top-level directory.
10 : : */
11 : : #include <glib.h>
12 : : #include <string.h>
13 : :
14 : : #include "common.h"
15 : : #include "simpletlv.h"
16 : :
17 : : int key_bits = 0;
18 : : int hw_tests = 0;
19 : :
20 : :
21 : 5 : static void select_coid(VReader *reader, unsigned char *coid,
22 : : int expect_success)
23 : : {
24 : : VReaderStatus status;
25 : 5 : int dwRecvLength = APDUBufSize;
26 : : uint8_t pbRecvBuffer[APDUBufSize];
27 : 5 : uint8_t selfile[] = {
28 : : 0x00, 0xa4, 0x02, 0x00, 0x02, 0x00, 0x00
29 : : };
30 : : size_t selfile_len = sizeof(selfile);
31 : :
32 : 5 : memcpy(&selfile[5], coid, 2);
33 : :
34 : 5 : g_debug("%s: Select OID 0x%02x 0x%02x", __func__, coid[0], coid[1]);
35 [ - + - + ]: 5 : g_assert_nonnull(reader);
36 : 5 : status = vreader_xfr_bytes(reader,
37 : : selfile, selfile_len,
38 : : pbRecvBuffer, &dwRecvLength);
39 [ - + ]: 5 : g_assert_cmpint(status, ==, VREADER_OK);
40 [ + + ]: 5 : if (expect_success) {
41 [ - + ]: 3 : g_assert_cmphex(pbRecvBuffer[dwRecvLength-2], ==, VCARD7816_SW1_SUCCESS);
42 [ - + ]: 3 : g_assert_cmphex(pbRecvBuffer[dwRecvLength-1], ==, 0x00);
43 : : } else {
44 [ - + ]: 2 : g_assert_cmphex(pbRecvBuffer[dwRecvLength-2], ==, VCARD7816_SW1_P1_P2_ERROR);
45 [ - + ]: 2 : g_assert_cmphex(pbRecvBuffer[dwRecvLength-1], ==, 0x82);
46 : : }
47 : 5 : }
48 : :
49 : 3 : void select_coid_good(VReader *reader, unsigned char *coid)
50 : : {
51 : 3 : select_coid(reader, coid, 1);
52 : 3 : }
53 : :
54 : 2 : void select_coid_bad(VReader *reader, unsigned char *coid)
55 : : {
56 : 2 : select_coid(reader, coid, 0);
57 : 2 : }
58 : :
59 : :
60 : 95 : int select_aid_response(VReader *reader, unsigned char *aid,
61 : : unsigned int aid_len, int response_len)
62 : : {
63 : : VReaderStatus status;
64 : 95 : int dwRecvLength = APDUBufSize;
65 : : uint8_t pbRecvBuffer[APDUBufSize];
66 : 95 : uint8_t selfile[] = {
67 : : 0x00, 0xa4, 0x04, 0x00, 0x00, /* Data Len to be overwritten */
68 : : 0xa0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* Data */
69 : : 0xa0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
70 : : };
71 : : size_t selfile_len = 0;
72 : :
73 : 95 : selfile_len = 5 + aid_len;
74 [ - + ]: 95 : g_assert_cmpint(selfile_len, <=, sizeof(selfile));
75 : 95 : memcpy(&selfile[5], aid, aid_len);
76 : 95 : selfile[4] = aid_len;
77 : :
78 [ - + - + ]: 95 : g_assert_nonnull(reader);
79 : 95 : status = vreader_xfr_bytes(reader,
80 : : selfile, selfile_len,
81 : : pbRecvBuffer, &dwRecvLength);
82 [ - + ]: 95 : g_assert_cmpint(status, ==, VREADER_OK);
83 [ + + ]: 95 : if (response_len > 0) {
84 : : /* we expect specific amount of response bytes */
85 [ - + ]: 9 : g_assert_cmphex(pbRecvBuffer[dwRecvLength-2], ==, VCARD7816_SW1_RESPONSE_BYTES);
86 [ - + ]: 9 : g_assert_cmphex(pbRecvBuffer[dwRecvLength-1], ==, response_len);
87 : : } else {
88 : : /* the default response length is 13 (FCI stub) */
89 [ - + ]: 86 : g_assert_cmphex(pbRecvBuffer[dwRecvLength-2], ==, VCARD7816_SW1_RESPONSE_BYTES);
90 [ - + ]: 86 : g_assert_cmphex(pbRecvBuffer[dwRecvLength-1], ==, 0x0d);
91 : : }
92 : 95 : return pbRecvBuffer[dwRecvLength-2];
93 : : }
94 : :
95 : 5 : void select_aid(VReader *reader, unsigned char *aid, unsigned int aid_len)
96 : : {
97 : 86 : (void) select_aid_response(reader, aid, aid_len, 0);
98 : 5 : }
99 : :
100 : 46 : void get_properties_coid(VReader *reader, const unsigned char coid[2],
101 : : enum TestObjectType object_type)
102 : : {
103 : 46 : int dwRecvLength = APDUBufSize;
104 : : VReaderStatus status;
105 : : uint8_t pbRecvBuffer[APDUBufSize], *p, *p_end, *p2, *p2_end;
106 : 46 : uint8_t get_properties[] = {
107 : : /* Get properties [Le] */
108 : : 0x80, 0x56, 0x01, 0x00, 0x00
109 : : };
110 : 46 : uint8_t get_properties_tag[] = {
111 : : /* Get properties [tag list] [Le] */
112 : : 0x80, 0x56, 0x02, 0x00, 0x02, 0x01, 0x01, 0x00
113 : : };
114 : : int verified_pki_properties = 0;
115 : : int num_objects = 0, num_objects_expected = -1;
116 : : int have_applet_information = 0;
117 : :
118 : 46 : status = vreader_xfr_bytes(reader,
119 : : get_properties, sizeof(get_properties),
120 : : pbRecvBuffer, &dwRecvLength);
121 [ - + ]: 46 : g_assert_cmpint(status, ==, VREADER_OK);
122 [ - + ]: 46 : g_assert_cmpint(dwRecvLength, ==, 2);
123 : : /* for too long Le, the cards return LE_ERROR with correct length to ask */
124 [ - + ]: 46 : g_assert_cmpint(pbRecvBuffer[dwRecvLength-2], ==, VCARD7816_SW1_LE_ERROR);
125 [ - + ]: 46 : g_assert_cmpint(pbRecvBuffer[dwRecvLength-1], >, 0);
126 : :
127 : : /* Update the APDU to match Le field from response and resend */
128 : 46 : get_properties[4] = pbRecvBuffer[1];
129 : 46 : dwRecvLength = APDUBufSize;
130 : 46 : status = vreader_xfr_bytes(reader,
131 : : get_properties, sizeof(get_properties),
132 : : pbRecvBuffer, &dwRecvLength);
133 [ - + ]: 46 : g_assert_cmpint(status, ==, VREADER_OK);
134 [ - + ]: 46 : g_assert_cmpint(dwRecvLength, >, 2);
135 [ - + ]: 46 : g_assert_cmpint(pbRecvBuffer[dwRecvLength-2], ==, VCARD7816_SW1_SUCCESS);
136 [ - + ]: 46 : g_assert_cmpint(pbRecvBuffer[dwRecvLength-1], ==, 0x00);
137 : :
138 : : /* try to parse the response, if it makes sense */
139 : 46 : p = pbRecvBuffer;
140 : 46 : p_end = p + dwRecvLength - 2;
141 [ + + ]: 173 : while (p < p_end) {
142 : : uint8_t tag;
143 : : size_t vlen;
144 [ - + ]: 127 : if (simpletlv_read_tag(&p, p_end - p, &tag, &vlen) < 0) {
145 : 0 : g_debug("The generated SimpleTLV can not be parsed");
146 : 0 : g_assert_not_reached();
147 : : }
148 : 127 : g_debug("Tag: 0x%02x, Len: %" G_GSIZE_FORMAT, tag, vlen);
149 [ - + ]: 127 : g_assert_cmpint(vlen, <=, p_end - p);
150 : :
151 [ + + + - : 127 : switch (tag) {
- - ]
152 : 46 : case 0x01: /* Applet Information */
153 [ - + ]: 46 : g_assert_cmpint(vlen, ==, 5);
154 [ - + ]: 46 : g_assert_cmphex(*p, ==, 0x10); /* Applet family */
155 : : have_applet_information = 1;
156 : : break;
157 : :
158 : 45 : case 0x40: /* Number of objects */
159 [ - + ]: 45 : g_assert_cmpint(vlen, ==, 1);
160 [ - + ]: 45 : if (num_objects_expected != -1) {
161 : 0 : g_debug("Received multiple number-of-objects tags");
162 : 0 : g_assert_not_reached();
163 : : }
164 : 45 : num_objects_expected = *p;
165 : 45 : break;
166 : :
167 : 36 : case 0x50: /* TV Object */
168 : : case 0x51: /* PKI Object */
169 : : /* recursive SimpleTLV structure */
170 : 36 : p2 = p;
171 : 36 : p2_end = p + vlen;
172 [ + + ]: 162 : while (p2 < p2_end) {
173 : : uint8_t tag2;
174 : : size_t vlen2;
175 [ - + ]: 126 : if (simpletlv_read_tag(&p2, p2_end - p2, &tag2, &vlen2) < 0) {
176 : 0 : g_debug("The generated SimpleTLV can not be parsed");
177 : 0 : g_assert_not_reached();
178 : : }
179 [ - + ]: 126 : g_assert_cmpint(vlen2, <=, p2_end - p2);
180 : 126 : g_debug(" Tag: 0x%02x, Len: %" G_GSIZE_FORMAT, tag2, vlen2);
181 : :
182 [ + + + + : 126 : switch (tag2) {
- ]
183 : 36 : case 0x41: /* Object ID */
184 [ - + - + : 36 : g_assert_cmpmem(p2, vlen2, coid, 2);
- + - + ]
185 : : break;
186 : :
187 : 36 : case 0x42: /* Buffer properties */
188 [ - + ]: 36 : g_assert_cmpint(vlen2, ==, 5);
189 [ + + ]: 36 : if (object_type != TEST_EMPTY_BUFFER)
190 [ - + ]: 27 : g_assert_cmpint(p2[0], ==, 0x00);
191 : : break;
192 : :
193 : 20 : case 0x43: /* PKI properties */
194 [ - + ]: 20 : g_assert_cmphex(p2[0], ==, 0x06);
195 [ + + + + ]: 20 : if (hw_tests && object_type == TEST_PKI) {
196 : : /* Assuming CAC card with 1024 b RSA keys */
197 : 10 : key_bits = 1024;
198 : : } else {
199 : : /* Assuming 2048 b RSA keys */
200 : 10 : key_bits = 2048;
201 : : }
202 [ - + ]: 20 : g_assert_cmphex(p2[1], ==, (key_bits / 8 / 8));
203 [ - + ]: 20 : g_assert_cmphex(p2[2], ==, 0x01);
204 [ - + ]: 20 : g_assert_cmphex(p2[3], ==, 0x01);
205 : : verified_pki_properties = 1;
206 : : break;
207 : :
208 : 34 : case 0x26:
209 [ - + ]: 34 : g_assert_cmpint(vlen2, ==, 1);
210 [ - + ]: 34 : g_assert_cmphex(p2[0], ==, 0x01);
211 : : break;
212 : :
213 : 0 : default:
214 : 0 : g_debug("Unknown tag in object: 0x%02x", tag2);
215 : 0 : g_assert_not_reached();
216 : : }
217 : 126 : p2 += vlen2;
218 : : }
219 : : /* one more object processed */
220 : 36 : num_objects++;
221 : 36 : break;
222 : :
223 : 0 : case 0x39:
224 [ # # ]: 0 : g_assert_cmpint(vlen, ==, 1);
225 [ # # ]: 0 : g_assert_cmphex(p[0], ==, 0x00);
226 : : break;
227 : :
228 : 0 : case 0x3A:
229 [ # # ]: 0 : g_assert_cmpint(vlen, ==, 7);
230 : : break;
231 : :
232 : 0 : default:
233 : 0 : g_debug("Unknown tag in properties buffer: 0x%02x", tag);
234 : 0 : g_assert_not_reached();
235 : : }
236 : 127 : p += vlen;
237 : : }
238 : :
239 [ + + ]: 46 : if (num_objects_expected != -1) {
240 [ - + ]: 45 : g_assert_cmpint(num_objects, ==, num_objects_expected);
241 : : }
242 : :
243 [ + + ]: 46 : if (object_type == TEST_EMPTY_BUFFER) {
244 [ - + ]: 9 : g_assert_cmpint(num_objects_expected, ==, 1);
245 : : }
246 : :
247 [ + + ]: 46 : if (object_type == TEST_EMPTY) {
248 [ - + ]: 9 : g_assert_cmpint(num_objects_expected, ==, 0);
249 : : }
250 : :
251 [ + + ]: 46 : if (object_type == TEST_PKI || object_type == TEST_PKI_2) {
252 [ - + ]: 20 : g_assert_cmpint(verified_pki_properties, ==, 1);
253 : : }
254 : :
255 [ - + ]: 46 : g_assert_cmpint(have_applet_information, ==, 1);
256 : :
257 : : /* Try to list only some properties */
258 : 46 : dwRecvLength = APDUBufSize;
259 : 46 : status = vreader_xfr_bytes(reader,
260 : : get_properties_tag, sizeof(get_properties_tag),
261 : : pbRecvBuffer, &dwRecvLength);
262 [ - + ]: 46 : g_assert_cmpint(status, ==, VREADER_OK);
263 [ - + ]: 46 : g_assert_cmpint(dwRecvLength, ==, 2);
264 [ - + ]: 46 : g_assert_cmpint(pbRecvBuffer[0], ==, VCARD7816_SW1_LE_ERROR);
265 [ - + ]: 46 : g_assert_cmpint(pbRecvBuffer[1], ==, 0x0e); /* Two applet information buffers */
266 : :
267 : : /* Update the APDU to match Le field from response and resend */
268 : 46 : get_properties_tag[7] = pbRecvBuffer[1];
269 : 46 : dwRecvLength = APDUBufSize;
270 : 46 : status = vreader_xfr_bytes(reader,
271 : : get_properties_tag, sizeof(get_properties_tag),
272 : : pbRecvBuffer, &dwRecvLength);
273 [ - + ]: 46 : g_assert_cmpint(status, ==, VREADER_OK);
274 [ - + ]: 46 : g_assert_cmpint(dwRecvLength, ==, 16); /* Two applet information buffers + status */
275 [ - + ]: 46 : g_assert_cmpint(pbRecvBuffer[dwRecvLength-2], ==, VCARD7816_SW1_SUCCESS);
276 [ - + ]: 46 : g_assert_cmpint(pbRecvBuffer[dwRecvLength-1], ==, 0x00);
277 : :
278 : :
279 : : /* Test the undocumented P1 = 0x40 */
280 : 46 : dwRecvLength = APDUBufSize;
281 : 46 : get_properties[2] = 0x40;
282 : 46 : get_properties[4] = 0x00;
283 : 46 : status = vreader_xfr_bytes(reader,
284 : : get_properties, sizeof(get_properties),
285 : : pbRecvBuffer, &dwRecvLength);
286 [ - + ]: 46 : g_assert_cmpint(status, ==, VREADER_OK);
287 : : /* for too long Le, the cards return LE_ERROR with correct length to ask */
288 [ - + ]: 46 : g_assert_cmpint(dwRecvLength, ==, 2);
289 [ - + ]: 46 : g_assert_cmpint(pbRecvBuffer[0], ==, VCARD7816_SW1_LE_ERROR);
290 [ - + ]: 46 : g_assert_cmpint(pbRecvBuffer[1], !=, 0x00);
291 : :
292 : : /* Update the APDU to match Le field from response and resend */
293 : 46 : get_properties[4] = pbRecvBuffer[1];
294 : 46 : dwRecvLength = APDUBufSize;
295 : 46 : status = vreader_xfr_bytes(reader,
296 : : get_properties, sizeof(get_properties),
297 : : pbRecvBuffer, &dwRecvLength);
298 [ - + ]: 46 : g_assert_cmpint(status, ==, VREADER_OK);
299 [ - + ]: 46 : g_assert_cmpint(dwRecvLength, >, 2);
300 [ - + ]: 46 : g_assert_cmpint(pbRecvBuffer[dwRecvLength-2], ==, VCARD7816_SW1_SUCCESS);
301 [ - + ]: 46 : g_assert_cmpint(pbRecvBuffer[dwRecvLength-1], ==, 0x00);
302 : :
303 : 46 : }
304 : :
305 : 23 : void get_properties(VReader *reader, enum TestObjectType object_type)
306 : : {
307 : : unsigned char coid[2];
308 [ + + + + : 23 : switch (object_type) {
- ]
309 : 11 : case TEST_PKI:
310 : 11 : coid[0] = 0x01;
311 : 11 : coid[1] = 0x00;
312 : 11 : get_properties_coid(reader, coid, object_type);
313 : 11 : break;
314 : :
315 : 9 : case TEST_PKI_2:
316 : 9 : coid[0] = 0x01;
317 : 9 : coid[1] = 0x01;
318 : 9 : get_properties_coid(reader, coid, object_type);
319 : 9 : break;
320 : :
321 : 2 : case TEST_CCC:
322 : 2 : coid[0] = 0xDB;
323 : 2 : coid[1] = 0x00;
324 : 2 : get_properties_coid(reader, coid, object_type);
325 : 2 : break;
326 : :
327 : 1 : case TEST_ACA:
328 : 1 : coid[0] = 0x03;
329 : 1 : coid[1] = 0x00;
330 : 1 : get_properties_coid(reader, coid, object_type);
331 : 1 : break;
332 : :
333 : 0 : case TEST_GENERIC:
334 : : case TEST_EMPTY_BUFFER:
335 : : case TEST_EMPTY:
336 : : case TEST_PASSTHROUGH:
337 : : default:
338 : 0 : g_debug("Got unknown object type");
339 : 0 : g_assert_not_reached();
340 : : }
341 : 23 : }
342 : :
343 : 34 : void read_buffer(VReader *reader, uint8_t type, enum TestObjectType object_type)
344 : : {
345 : : int dwRecvLength = APDUBufSize, dwLength, dwReadLength, offset, left;
346 : : VReaderStatus status;
347 : : uint8_t pbRecvBuffer[APDUBufSize];
348 : : uint8_t *data;
349 : 34 : uint8_t read_buffer[] = {
350 : : /*Read Buffer OFFSET TYPE LENGTH a_Le */
351 : : 0x80, 0x52, 0x00, 0x00, 0x02, 0x01, 0x02, 0x02
352 : : };
353 : : int card_urls = 0;
354 : :
355 : 34 : dwRecvLength = 4;
356 : 34 : read_buffer[5] = type;
357 : 34 : status = vreader_xfr_bytes(reader,
358 : : read_buffer, sizeof(read_buffer),
359 : : pbRecvBuffer, &dwRecvLength);
360 [ - + ]: 34 : g_assert_cmpint(status, ==, VREADER_OK);
361 [ - + ]: 34 : g_assert_cmpint(dwRecvLength, ==, 4);
362 [ - + ]: 34 : g_assert_cmphex(pbRecvBuffer[dwRecvLength-2], ==, VCARD7816_SW1_SUCCESS);
363 [ - + ]: 34 : g_assert_cmphex(pbRecvBuffer[dwRecvLength-1], ==, 0x00);
364 : :
365 : 34 : dwLength = (pbRecvBuffer[0] & 0xff) | ((pbRecvBuffer[1] << 8) & 0xff);
366 [ + + ]: 34 : if (dwLength == 0)
367 : 28 : return;
368 : :
369 : 6 : data = g_malloc(dwLength);
370 : : offset = 0x02;
371 : : left = dwLength;
372 : : do {
373 : 6 : dwReadLength = MIN(255, left);
374 : 6 : dwRecvLength = dwReadLength+2;
375 : 6 : read_buffer[2] = (unsigned char) ((offset >> 8) & 0xff);
376 : 6 : read_buffer[3] = (unsigned char) (offset & 0xff);
377 : 6 : read_buffer[6] = (unsigned char) (dwReadLength);
378 : 6 : read_buffer[7] = (unsigned char) (dwReadLength);
379 : 6 : status = vreader_xfr_bytes(reader,
380 : : read_buffer, sizeof(read_buffer),
381 : : pbRecvBuffer, &dwRecvLength);
382 [ - + ]: 6 : g_assert_cmpint(status, ==, VREADER_OK);
383 [ - + ]: 6 : g_assert_cmpint(dwRecvLength, ==, dwReadLength + 2);
384 [ - + ]: 6 : g_assert_cmphex(pbRecvBuffer[dwRecvLength-2], ==, VCARD7816_SW1_SUCCESS);
385 [ - + ]: 6 : g_assert_cmphex(pbRecvBuffer[dwRecvLength-1], ==, 0x00);
386 : :
387 : 6 : memcpy(data + offset - 2, pbRecvBuffer, dwReadLength);
388 : 6 : offset += dwReadLength;
389 : 6 : left -= dwReadLength;
390 [ - + ]: 6 : } while (left != 0);
391 : :
392 : : /* Try to parse the TAG buffer, if it makes sense */
393 [ + + ]: 6 : if (type == CAC_FILE_TAG) {
394 : 3 : uint8_t *p = data;
395 : 3 : uint8_t *p_end = p + offset - 2;
396 [ + + ]: 37 : while (p < p_end) {
397 : : uint8_t tag;
398 : : size_t vlen;
399 [ - + ]: 34 : if (simpletlv_read_tag(&p, p_end - p, &tag, &vlen) < 0) {
400 : 0 : g_debug("The generated SimpleTLV can not be parsed");
401 : 0 : g_assert_not_reached();
402 : : }
403 : 34 : g_debug("Tag: 0x%02x, Len: %" G_GSIZE_FORMAT, tag, vlen);
404 : :
405 [ + + ]: 34 : switch (tag) {
406 : 14 : case 0xF3: /* CardURL from CCC */
407 [ + - ]: 14 : if (object_type == TEST_CCC) {
408 : 14 : card_urls++;
409 : : } else {
410 : 0 : g_debug("CardURLs found outside of CCC buffer");
411 : 0 : g_assert_not_reached();
412 : : }
413 : 14 : break;
414 : : default:
415 : : break;
416 : : }
417 : : }
418 [ + + ]: 3 : if (object_type == TEST_CCC)
419 [ - + ]: 1 : g_assert_cmpint(card_urls, ==, 11 + 3);
420 : : }
421 : 6 : g_free(data);
422 : : }
423 : :
424 : 63 : void select_applet(VReader *reader, enum TestObjectType type)
425 : : {
426 : 63 : uint8_t selfile_ccc[] = {
427 : : /* Select CCC Applet */
428 : : 0xa0, 0x00, 0x00, 0x01, 0x16, 0xDB, 0x00
429 : : };
430 : 63 : uint8_t selfile_aca[] = {
431 : : /* Select ACA Applet */
432 : : 0xa0, 0x00, 0x00, 0x00, 0x79, 0x03, 0x00
433 : : };
434 : 63 : uint8_t selfile_pki[] = {
435 : : /* Select first PKI Applet */
436 : : 0xa0, 0x00, 0x00, 0x00, 0x79, 0x01, 0x00
437 : : };
438 : 63 : uint8_t selfile_pki_2[] = {
439 : : /* Select second PKI Applet */
440 : : 0xa0, 0x00, 0x00, 0x00, 0x79, 0x01, 0x01
441 : : };
442 : 63 : uint8_t selfile_passthrough[] = {
443 : : /* Select Person Instance (passthrough) */
444 : : 0xa0, 0x00, 0x00, 0x00, 0x79, 0x02, 0x00
445 : : };
446 : 63 : uint8_t selfile_empty[] = {
447 : : 0xA0, 0x00, 0x00, 0x00, 0x79, 0x02, 0xF0
448 : : };
449 : : uint8_t *aid = NULL;
450 : : size_t aid_len = 0;
451 : :
452 [ - + + + : 63 : switch (type) {
+ + + ]
453 : : case TEST_PKI:
454 : : aid = selfile_pki;
455 : : aid_len = sizeof(selfile_pki);
456 : : break;
457 : :
458 : : case TEST_PKI_2:
459 : : aid = selfile_pki_2;
460 : : aid_len = sizeof(selfile_pki_2);
461 : : break;
462 : :
463 : : case TEST_CCC:
464 : : aid = selfile_ccc;
465 : : aid_len = sizeof(selfile_ccc);
466 : : break;
467 : :
468 : : case TEST_ACA:
469 : : aid = selfile_aca;
470 : : aid_len = sizeof(selfile_aca);
471 : : break;
472 : :
473 : : case TEST_PASSTHROUGH:
474 : : aid = selfile_passthrough;
475 : : aid_len = sizeof(selfile_passthrough);
476 : : break;
477 : :
478 : : case TEST_EMPTY:
479 : : aid = selfile_empty;
480 : : aid_len = sizeof(selfile_empty);
481 : : break;
482 : :
483 : 0 : case TEST_GENERIC:
484 : : case TEST_EMPTY_BUFFER:
485 : : default:
486 : 0 : g_assert_not_reached();
487 : : }
488 : : g_assert_nonnull(aid);
489 : :
490 : : select_aid(reader, aid, aid_len);
491 : 63 : }
492 : :
493 : 28 : void do_sign(VReader *reader, int parts)
494 : : {
495 : : VReaderStatus status;
496 : 28 : int dwRecvLength = APDUBufSize;
497 : : uint8_t pbRecvBuffer[APDUBufSize];
498 : 28 : uint8_t sign[] = {
499 : : /* SIGN [p1,p2=0 ] [Lc ] [2048b keys: 256 bytes of PKCS#1.5 padded data] */
500 : : 0x80, 0x42, 0x00, 0x00, 0x00, 0x01, 0x00,
501 : : 0x00, 0x01, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
502 : : 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
503 : : 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
504 : : 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
505 : : 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
506 : : 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
507 : : 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
508 : : 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
509 : : 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
510 : : 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
511 : : 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
512 : : 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
513 : : 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
514 : : 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
515 : : 0xff, 0xff, 0x00, 0x64, 0x61, 0x74, 0x61, 0x20, 0x74, 0x6f, 0x20, 0x73, 0x69, 0x67, 0x6e, 0x20,
516 : : 0x28, 0x6d, 0x61, 0x78, 0x20, 0x31, 0x30, 0x30, 0x20, 0x62, 0x79, 0x74, 0x65, 0x73, 0x29, 0x0a
517 : : };
518 : : int sign_len = sizeof(sign);
519 : 28 : uint8_t getresp[] = {
520 : : /* Get Response (max we can get) */
521 : : 0x00, 0xc0, 0x00, 0x00, 0x00
522 : : };
523 [ - + - + ]: 28 : g_assert_nonnull(reader);
524 : :
525 : : /* Adjust the buffers to match the key lengths, if already retrieved */
526 [ + + ]: 28 : if (key_bits && key_bits < 2048) {
527 : 12 : sign[4] = key_bits/8; /* less than 2048b will fit the length into one byte */
528 : 12 : sign[5] = 0x00;
529 : 12 : sign[6] = 0x01;
530 : 12 : memcpy(&sign[7], &sign[sign_len-key_bits/8+2], key_bits/8-2);
531 : 12 : sign_len = 5 + key_bits/8;
532 : : }
533 : :
534 : : /* The driver supports signatures while data are passed in more separate APDUs */
535 [ + + ]: 28 : if (parts) {
536 : : int split = 0x47;
537 : : /* we have not sent the whole buffer */
538 : 14 : sign[2] = 0x80;
539 : 14 : sign[4] = split;
540 : 14 : sign[5] = 0x00;
541 : 14 : sign[6] = 0x01;
542 : 14 : sign[7] = 0xFF;
543 : 14 : sign[8] = 0xFF;
544 : : sign_len = 5 + split;
545 : :
546 : 14 : status = vreader_xfr_bytes(reader,
547 : : sign, sign_len,
548 : : pbRecvBuffer, &dwRecvLength);
549 [ - + ]: 14 : g_assert_cmpint(status, ==, VREADER_OK);
550 [ - + ]: 14 : g_assert_cmpint(dwRecvLength, ==, 2);
551 [ - + ]: 14 : g_assert_cmphex(pbRecvBuffer[dwRecvLength-2], ==, VCARD7816_SW1_SUCCESS);
552 [ - + ]: 14 : g_assert_cmphex(pbRecvBuffer[dwRecvLength-1], ==, 0x00);
553 : :
554 : : /* the next message will send the rest of the buffer */
555 : 14 : sign[2] = 0x00;
556 [ + - ]: 14 : if (key_bits)
557 : 14 : sign[4] = key_bits/8 - split;
558 : : else
559 : 0 : sign[4] = 256 - split;
560 : 14 : memmove(&sign[5], &sign[5+2+split], sign[4]);
561 : 14 : sign_len = 5 + sign[4];
562 : : }
563 : :
564 : 28 : dwRecvLength = APDUBufSize;
565 : 28 : status = vreader_xfr_bytes(reader,
566 : : sign, sign_len,
567 : : pbRecvBuffer, &dwRecvLength);
568 [ - + ]: 28 : g_assert_cmpint(status, ==, VREADER_OK);
569 [ - + ]: 28 : g_assert_cmphex(pbRecvBuffer[dwRecvLength-2], ==, VCARD7816_SW1_RESPONSE_BYTES);
570 [ - + ]: 28 : g_assert_cmphex(pbRecvBuffer[dwRecvLength-1], ==, (unsigned char) (key_bits/8));
571 : :
572 : :
573 : : /* fetch the actual response */
574 : 28 : dwRecvLength = APDUBufSize;
575 : 28 : status = vreader_xfr_bytes(reader,
576 : : getresp, sizeof(getresp),
577 : : pbRecvBuffer, &dwRecvLength);
578 [ - + ]: 28 : g_assert_cmpint(status, ==, VREADER_OK);
579 [ - + ]: 28 : g_assert_cmpint(dwRecvLength, ==, key_bits/8+2);
580 [ - + ]: 28 : g_assert_cmphex(pbRecvBuffer[dwRecvLength-2], ==, VCARD7816_SW1_SUCCESS);
581 [ - + ]: 28 : g_assert_cmphex(pbRecvBuffer[dwRecvLength-1], ==, 0x00);
582 : :
583 : 28 : }
584 : :
585 : 6 : void do_decipher(VReader *reader, enum TestObjectType type)
586 : : {
587 : : VReaderStatus status;
588 : 6 : int dwRecvLength = APDUBufSize;
589 : : uint8_t pbRecvBuffer[APDUBufSize];
590 : 6 : uint8_t apdu[7 + 256] = {
591 : : /* DECRYPT [p1,p2=0 ] [Lc ] */
592 : : 0x80, 0x42, 0x00, 0x00, 0x00, 0x01, 0x00,
593 : : /* [2048b keys: 256 bytes of encrypted data to be filled by the following code ] */
594 : : };
595 : : int apdu_len = sizeof(apdu);
596 : 6 : uint8_t getresp[] = {
597 : : /* Get Response (max we can get) */
598 : : 0x00, 0xc0, 0x00, 0x00, 0x00
599 : : };
600 : 6 : uint8_t cleartext[] = "1234567890\n";
601 : : int cleartext_len = sizeof(cleartext) - 1;
602 : : gchar *filename = NULL;
603 : 6 : gchar *ciphertext = NULL;
604 : 6 : gsize ciphertext_len = 0;
605 [ - + - + ]: 6 : g_assert_nonnull(reader);
606 : :
607 : : /* To decipher, we need some sensible data encrypted using public key
608 : : * (done in setup-softhsm.sh) */
609 : :
610 : : /* Read the encrypted file */
611 [ + + ]: 6 : if (hw_tests) {
612 : : const char *name;
613 [ + + ]: 4 : if (type == TEST_PKI) {
614 : : name = "01.crypt";
615 [ - + ]: 2 : } else if (type == TEST_PKI_2) {
616 : : name = "02.crypt";
617 : : } else {
618 : 0 : g_assert_not_reached();
619 : : }
620 : 4 : filename = g_test_build_filename(G_TEST_BUILT, name, NULL);
621 : : } else {
622 : : /* Generated from existing db using:
623 : : * echo "1234567890" > data
624 : : * certutil -L -d sql:$PWD/tests/db/ -n cert1 -r > tests/db.cert
625 : : * openssl rsautl -encrypt -inkey "tests/db.cert" -keyform DER -certin -in data -out "tests/db.crypt"
626 : : */
627 : : const char *name;
628 [ + + ]: 2 : if (type == TEST_PKI) {
629 : : name = "db.crypt";
630 [ - + ]: 1 : } else if (type == TEST_PKI_2) {
631 : : name = "db2.crypt";
632 : : } else {
633 : 0 : g_assert_not_reached();
634 : : }
635 : 2 : filename = g_test_build_filename(G_TEST_DIST, name, NULL);
636 : : }
637 [ - + ]: 6 : if (!g_file_get_contents(filename, &ciphertext, &ciphertext_len, NULL)) {
638 : 0 : g_test_skip("The encrypted file not found");
639 : 0 : g_free(filename);
640 : 0 : return;
641 : : }
642 : 6 : g_free(filename);
643 : :
644 : : /* Adjust the place where to store the read ciphertext */
645 [ + + ]: 6 : if (key_bits && key_bits < 2048) {
646 : 2 : apdu[4] = key_bits/8; /* less than 2048b will fit the length into one byte */
647 : 2 : apdu_len = 5 + key_bits/8;
648 : 2 : memcpy(&apdu[5], ciphertext, ciphertext_len);
649 : : } else {
650 : : /* This might be an issue for even larger keys than 2k */
651 [ - + ]: 4 : assert(ciphertext_len < (size_t) apdu_len + 7);
652 : 4 : memcpy(&apdu[7], ciphertext, ciphertext_len);
653 : : }
654 : 6 : g_free(ciphertext);
655 : :
656 : 6 : dwRecvLength = APDUBufSize;
657 : 6 : status = vreader_xfr_bytes(reader,
658 : : apdu, apdu_len,
659 : : pbRecvBuffer, &dwRecvLength);
660 [ - + ]: 6 : g_assert_cmpint(status, ==, VREADER_OK);
661 [ - + ]: 6 : g_assert_cmphex(pbRecvBuffer[dwRecvLength-2], ==, VCARD7816_SW1_RESPONSE_BYTES);
662 [ - + ]: 6 : g_assert_cmphex(pbRecvBuffer[dwRecvLength-1], ==, (unsigned char) (key_bits/8));
663 : :
664 : : /* fetch the actual response */
665 : 6 : dwRecvLength = APDUBufSize;
666 : 6 : status = vreader_xfr_bytes(reader,
667 : : getresp, sizeof(getresp),
668 : : pbRecvBuffer, &dwRecvLength);
669 [ - + ]: 6 : g_assert_cmpint(status, ==, VREADER_OK);
670 [ - + ]: 6 : g_assert_cmpint(dwRecvLength, ==, key_bits/8+2);
671 [ - + ]: 6 : g_assert_cmphex(pbRecvBuffer[dwRecvLength-2], ==, VCARD7816_SW1_SUCCESS);
672 [ - + ]: 6 : g_assert_cmphex(pbRecvBuffer[dwRecvLength-1], ==, 0x00);
673 : : /* Compare the actual deciphered data */
674 [ - + ]: 6 : g_assert_cmphex(pbRecvBuffer[0], ==, 0x00); /* Padding bytes */
675 [ - + ]: 6 : g_assert_cmphex(pbRecvBuffer[1], ==, 0x02);
676 [ - + ]: 6 : g_assert_cmphex(pbRecvBuffer[dwRecvLength - 2 - cleartext_len - 1], ==, 0x00);
677 [ - + ]: 6 : g_assert_cmpmem(&pbRecvBuffer[dwRecvLength - 2 - cleartext_len], cleartext_len,
678 : : cleartext, cleartext_len);
679 : :
680 : : }
681 : :
682 : 3 : void test_empty_applets(void)
683 : : {
684 : 3 : uint8_t applet_02fb[] = {
685 : : 0xA0, 0x00, 0x00, 0x00, 0x79, 0x02, 0xFB
686 : : };
687 : 3 : uint8_t applet_1201[] = {
688 : : 0xA0, 0x00, 0x00, 0x00, 0x79, 0x12, 0x01
689 : : };
690 : 3 : uint8_t applet_1202[] = {
691 : : 0xA0, 0x00, 0x00, 0x00, 0x79, 0x12, 0x02
692 : : };
693 : 3 : uint8_t applet_02f0[] = {
694 : : 0xA0, 0x00, 0x00, 0x00, 0x79, 0x02, 0xF0
695 : : };
696 : 3 : uint8_t applet_02f1[] = {
697 : : 0xA0, 0x00, 0x00, 0x00, 0x79, 0x02, 0xF1
698 : : };
699 : 3 : uint8_t applet_02f2[] = {
700 : : 0xA0, 0x00, 0x00, 0x00, 0x79, 0x02, 0xF2
701 : : };
702 : 3 : uint8_t coid[2] = {0x02, 0xFB};
703 : :
704 : 3 : VReader *reader = vreader_get_reader_by_id(0);
705 : :
706 : : /* Skip the HW tests without physical card */
707 [ - + ]: 2 : if (isHWTests() && vreader_card_is_present(reader) != VREADER_OK) {
708 : 0 : vreader_free(reader);
709 : 0 : g_test_skip("No physical card found");
710 : 0 : return;
711 : : }
712 : :
713 : : /* select the empty applet A00000007902FB, which should be empty buffer */
714 : : select_aid(reader, applet_02fb, sizeof(applet_02fb));
715 : :
716 : : /* get properties */
717 : 3 : get_properties_coid(reader, coid, TEST_EMPTY_BUFFER);
718 : :
719 : : /* get the TAG buffer length */
720 : 3 : read_buffer(reader, CAC_FILE_TAG, TEST_EMPTY_BUFFER);
721 : :
722 : : /* get the VALUE buffer length */
723 : 3 : read_buffer(reader, CAC_FILE_VALUE, TEST_EMPTY_BUFFER);
724 : :
725 : :
726 : : /* select the empty applet A0000000791201, which should be empty buffer */
727 : : select_aid(reader, applet_1201, sizeof(applet_1201));
728 : 3 : coid[0] = 0x12;
729 : 3 : coid[1] = 0x01;
730 : :
731 : : /* get properties */
732 : 3 : get_properties_coid(reader, coid, TEST_EMPTY_BUFFER);
733 : :
734 : : /* get the TAG buffer length */
735 : 3 : read_buffer(reader, CAC_FILE_TAG, TEST_EMPTY_BUFFER);
736 : :
737 : : /* get the VALUE buffer length */
738 : 3 : read_buffer(reader, CAC_FILE_VALUE, TEST_EMPTY_BUFFER);
739 : :
740 : :
741 : : /* select the empty applet A0000000791202, which should be empty buffer */
742 : : select_aid(reader, applet_1202, sizeof(applet_1202));
743 : : coid[0] = 0x12;
744 : 3 : coid[1] = 0x02;
745 : :
746 : : /* get properties */
747 : 3 : get_properties_coid(reader, coid, TEST_EMPTY_BUFFER);
748 : :
749 : : /* get the TAG buffer length */
750 : 3 : read_buffer(reader, CAC_FILE_TAG, TEST_EMPTY_BUFFER);
751 : :
752 : : /* get the VALUE buffer length */
753 : 3 : read_buffer(reader, CAC_FILE_VALUE, TEST_EMPTY_BUFFER);
754 : :
755 : :
756 : : /* select the empty applet A00000007902F0, which should be empty */
757 : : select_aid(reader, applet_02f0, sizeof(applet_02f0));
758 : :
759 : : /* get properties */
760 : 3 : get_properties_coid(reader, NULL, TEST_EMPTY);
761 : :
762 : :
763 : : /* select the empty applet A00000007902F1, which should be empty */
764 : : select_aid(reader, applet_02f1, sizeof(applet_02f1));
765 : :
766 : : /* get properties */
767 : 3 : get_properties_coid(reader, NULL, TEST_EMPTY);
768 : :
769 : :
770 : : /* select the empty applet A00000007902F2, which should be empty */
771 : : select_aid(reader, applet_02f2, sizeof(applet_02f2));
772 : :
773 : : /* get properties */
774 : 3 : get_properties_coid(reader, NULL, TEST_EMPTY);
775 : :
776 : :
777 : 3 : vreader_free(reader); /* get by id ref */
778 : : }
779 : :
780 : : /*
781 : : * Check that access method without provided buffer returns valid
782 : : * SW and allow us to get the response with the following APDU
783 : : *
784 : : * opensc-tool -s 00A4040007A000000116DB00 -s 80520000020102 -s 00C0000002 \
785 : : * -s 00520002020134 -s 00C0000034
786 : : */
787 : 3 : void test_get_response(void)
788 : : {
789 : 3 : VReader *reader = vreader_get_reader_by_id(0);
790 : 3 : int dwRecvLength = APDUBufSize, dwLength;
791 : : VReaderStatus status;
792 : : uint8_t pbRecvBuffer[APDUBufSize];
793 : 3 : uint8_t getresp[] = {
794 : : /* Get Response (max we can get) */
795 : : 0x00, 0xc0, 0x00, 0x00, 0x00
796 : : };
797 : 3 : uint8_t read_buffer[] = {
798 : : /*Read Buffer OFFSET TYPE LENGTH */
799 : : 0x00, 0x52, 0x00, 0x00, 0x02, 0x01, 0x02 /* no L_e */
800 : : };
801 : :
802 : : /* Skip the HW tests without physical card */
803 [ - + ]: 2 : if (isHWTests() && vreader_card_is_present(reader) != VREADER_OK) {
804 : 0 : vreader_free(reader);
805 : 0 : g_test_skip("No physical card found");
806 : 0 : return;
807 : : }
808 : :
809 : : /* select CCC */
810 : 3 : select_applet(reader, TEST_CCC);
811 : :
812 : : /* read buffer without response buffer. Ignore the response. */
813 : 3 : dwRecvLength = 2;
814 : 3 : status = vreader_xfr_bytes(reader,
815 : : read_buffer, sizeof(read_buffer),
816 : : pbRecvBuffer, &dwRecvLength);
817 [ - + ]: 3 : g_assert_cmpint(status, ==, VREADER_OK);
818 [ - + ]: 3 : g_assert_cmpint(dwRecvLength, ==, 2);
819 [ - + ]: 3 : g_assert_cmpint(pbRecvBuffer[0], ==, VCARD7816_SW1_RESPONSE_BYTES);
820 [ - + ]: 3 : g_assert_cmpint(pbRecvBuffer[1], ==, 0x02);
821 : :
822 : : /* read buffer without response buffer */
823 : 3 : dwRecvLength = 2;
824 : 3 : status = vreader_xfr_bytes(reader,
825 : : read_buffer, sizeof(read_buffer),
826 : : pbRecvBuffer, &dwRecvLength);
827 [ - + ]: 3 : g_assert_cmpint(status, ==, VREADER_OK);
828 [ - + ]: 3 : g_assert_cmpint(dwRecvLength, ==, 2);
829 [ - + ]: 3 : g_assert_cmpint(pbRecvBuffer[0], ==, VCARD7816_SW1_RESPONSE_BYTES);
830 [ - + ]: 3 : g_assert_cmpint(pbRecvBuffer[1], ==, 0x02);
831 : :
832 : : /* fetch the actual response */
833 : 3 : dwRecvLength = 4;
834 : 3 : getresp[4] = 0x02;
835 : 3 : status = vreader_xfr_bytes(reader,
836 : : getresp, sizeof(getresp),
837 : : pbRecvBuffer, &dwRecvLength);
838 [ - + ]: 3 : g_assert_cmpint(status, ==, VREADER_OK);
839 [ - + ]: 3 : g_assert_cmpint(dwRecvLength, ==, 4);
840 [ - + ]: 3 : g_assert_cmphex(pbRecvBuffer[2], ==, VCARD7816_SW1_SUCCESS);
841 [ - + ]: 3 : g_assert_cmphex(pbRecvBuffer[3], ==, 0x00);
842 : :
843 : : /* the same with offset */
844 : 3 : dwLength = (pbRecvBuffer[0] & 0xff) | ((pbRecvBuffer[1] << 8) & 0xff);
845 : 3 : dwRecvLength = dwLength + 2;
846 : 3 : read_buffer[3] = 0x02; // offset
847 : 3 : read_buffer[6] = dwLength;
848 : 3 : status = vreader_xfr_bytes(reader,
849 : : read_buffer, sizeof(read_buffer),
850 : : pbRecvBuffer, &dwRecvLength);
851 [ - + ]: 3 : g_assert_cmpint(status, ==, VREADER_OK);
852 [ - + ]: 3 : g_assert_cmpint(dwRecvLength, ==, 2);
853 [ - + ]: 3 : g_assert_cmpint(pbRecvBuffer[0], ==, VCARD7816_SW1_RESPONSE_BYTES);
854 [ - + ]: 3 : g_assert_cmpint(pbRecvBuffer[1], ==, dwLength);
855 : :
856 : : /* fetch the actual response */
857 : 3 : dwRecvLength = dwLength + 2;
858 : 3 : getresp[4] = dwLength;
859 : 3 : status = vreader_xfr_bytes(reader,
860 : : getresp, sizeof(getresp),
861 : : pbRecvBuffer, &dwRecvLength);
862 [ - + ]: 3 : g_assert_cmpint(status, ==, VREADER_OK);
863 [ - + ]: 3 : g_assert_cmpint(dwRecvLength, ==, dwLength + 2);
864 [ - + ]: 3 : g_assert_cmphex(pbRecvBuffer[dwRecvLength-2], ==, VCARD7816_SW1_SUCCESS);
865 [ - + ]: 3 : g_assert_cmphex(pbRecvBuffer[dwRecvLength-1], ==, 0x00);
866 : :
867 : : /* If we ask again, when there is no pending response */
868 : 3 : dwRecvLength = dwLength + 2;
869 : 3 : getresp[4] = dwLength;
870 : 3 : status = vreader_xfr_bytes(reader,
871 : : getresp, sizeof(getresp),
872 : : pbRecvBuffer, &dwRecvLength);
873 [ - + ]: 3 : g_assert_cmpint(status, ==, VREADER_OK);
874 [ - + ]: 3 : g_assert_cmpint(dwRecvLength, ==, 2);
875 [ - + ]: 3 : g_assert_cmphex(pbRecvBuffer[dwRecvLength-2], ==, VCARD7816_SW1_P1_P2_ERROR);
876 [ - + ]: 3 : g_assert_cmphex(pbRecvBuffer[dwRecvLength-1], ==, 0x88);
877 : :
878 : 3 : vreader_free(reader); /* get by id ref */
879 : : }
880 : :
881 : 3 : void check_login_count(void)
882 : : {
883 : 3 : VReader *reader = vreader_get_reader_by_id(0);
884 : : VReaderStatus status;
885 : 3 : int dwRecvLength = APDUBufSize;
886 : : uint8_t pbRecvBuffer[APDUBufSize];
887 : 3 : uint8_t login[] = {
888 : : /* VERIFY [p1,p2=0 ] [Lc] */
889 : : 0x00, 0x20, 0x00, 0x00, 0x00
890 : : };
891 [ - + - + ]: 3 : g_assert_nonnull(reader);
892 : :
893 : : /* Make sure we reset the login state here */
894 : 3 : vreader_power_off(reader);
895 : 3 : vreader_power_on(reader, NULL, NULL);
896 : :
897 : : /* Skip the HW tests without physical card */
898 [ - + ]: 2 : if (isHWTests() && vreader_card_is_present(reader) != VREADER_OK) {
899 : 0 : vreader_free(reader);
900 : 0 : g_test_skip("No physical card found");
901 : 0 : return;
902 : : }
903 : :
904 : : /* Get login count */
905 : 3 : status = vreader_xfr_bytes(reader,
906 : : login, sizeof(login),
907 : : pbRecvBuffer, &dwRecvLength);
908 [ - + ]: 3 : g_assert_cmpint(status, ==, VREADER_OK);
909 : : /* NSS does not know how to do this yet */
910 : 3 : if (isHWTests()) { /* HW tests have PIN */
911 [ - + ]: 2 : g_assert_cmphex(pbRecvBuffer[0], ==, VCARD7816_SW1_P1_P2_ERROR);
912 [ - + ]: 2 : g_assert_cmphex(pbRecvBuffer[1], ==, 0x88);
913 : : } else { /* NSS softoken does not have passphrase so it is unlocked automatically */
914 [ - + ]: 1 : g_assert_cmphex(pbRecvBuffer[0], ==, VCARD7816_SW1_SUCCESS);
915 [ - + ]: 1 : g_assert_cmphex(pbRecvBuffer[1], ==, 0x00);
916 : : }
917 : :
918 : : /* P1 = 0x01 is invalid */
919 : 3 : login[2] = 0x01;
920 : 3 : status = vreader_xfr_bytes(reader,
921 : : login, sizeof(login),
922 : : pbRecvBuffer, &dwRecvLength);
923 [ - + ]: 3 : g_assert_cmpint(status, ==, VREADER_OK);
924 [ - + ]: 3 : g_assert_cmphex(pbRecvBuffer[0], ==, VCARD7816_SW1_P1_P2_ERROR);
925 [ - + ]: 3 : g_assert_cmphex(pbRecvBuffer[1], ==, 0x00);
926 : :
927 : 3 : vreader_free(reader);
928 : : }
929 : :
930 : 3 : void test_msft_applet(void)
931 : : {
932 : 3 : int dwRecvLength = APDUBufSize;
933 : : VReaderStatus status;
934 : : uint8_t pbRecvBuffer[APDUBufSize];
935 : 3 : uint8_t msft_aid[] = {
936 : : 0xA0, 0x00, 0x00, 0x03, 0x97, 0x43, 0x49, 0x44, 0x5F, 0x01, 0x00
937 : : };
938 : 3 : uint8_t getresp[] = {
939 : : /* Get Response (max we can get) */
940 : : 0x00, 0xc0, 0x00, 0x00, 0x00
941 : : };
942 : 3 : uint8_t getdata[] = {
943 : : /* Get Data (max we can get) */
944 : : 0x00, 0xca, 0x7f, 0x68, 0x00
945 : : };
946 : 3 : uint8_t login[] = {
947 : : /* VERIFY [p1,p2=0 ] [Lc] */
948 : : 0x00, 0x20, 0x00, 0x00, 0x00
949 : : };
950 : 3 : VReader *reader = vreader_get_reader_by_id(0);
951 : :
952 [ - + - + ]: 3 : g_assert_nonnull(reader);
953 : :
954 : : /* Make sure we reset the login state here */
955 : 3 : vreader_power_off(reader);
956 : 3 : vreader_power_on(reader, NULL, NULL);
957 : :
958 : : /* Skip the HW tests without physical card */
959 [ - + ]: 2 : if (isHWTests() && vreader_card_is_present(reader) != VREADER_OK) {
960 : 0 : vreader_free(reader);
961 : 0 : g_test_skip("No physical card found");
962 : 0 : return;
963 : : }
964 : :
965 : :
966 : : /* select Microsoft PnP applet and wait for the response bytes */
967 : 3 : select_aid_response(reader, msft_aid, sizeof(msft_aid), 0x11);
968 : :
969 : : /* read the response from the card */
970 : 3 : dwRecvLength = APDUBufSize;
971 : 3 : status = vreader_xfr_bytes(reader,
972 : : getresp, sizeof(getresp),
973 : : pbRecvBuffer, &dwRecvLength);
974 [ - + ]: 3 : g_assert_cmpint(status, ==, VREADER_OK);
975 [ - + ]: 3 : g_assert_cmpint(dwRecvLength, >, 2);
976 [ - + ]: 3 : g_assert_cmphex(pbRecvBuffer[dwRecvLength-2], ==, VCARD7816_SW1_SUCCESS);
977 [ - + ]: 3 : g_assert_cmphex(pbRecvBuffer[dwRecvLength-1], ==, 0x00);
978 : :
979 : : /* We made sure the selection of other applets does not return anything
980 : : * in select_aid()
981 : : */
982 : :
983 : : /* ask the applet for unknown data */
984 : 3 : getdata[2] = 0xff;
985 : 3 : getdata[3] = 0xff;
986 : 3 : dwRecvLength = APDUBufSize;
987 : 3 : status = vreader_xfr_bytes(reader,
988 : : getdata, sizeof(getdata),
989 : : pbRecvBuffer, &dwRecvLength);
990 [ - + ]: 3 : g_assert_cmpint(status, ==, VREADER_OK);
991 [ - + ]: 3 : g_assert_cmpint(dwRecvLength, ==, 2);
992 [ - + ]: 3 : g_assert_cmpint(pbRecvBuffer[dwRecvLength-2], ==, 0x6a);
993 [ - + ]: 3 : g_assert_cmpint(pbRecvBuffer[dwRecvLength-1], ==, 0x88);
994 : :
995 : : /* ask the applet for our data */
996 : 3 : getdata[2] = 0x7f;
997 : 3 : getdata[3] = 0x68;
998 : 3 : dwRecvLength = APDUBufSize;
999 : 3 : status = vreader_xfr_bytes(reader,
1000 : : getdata, sizeof(getdata),
1001 : : pbRecvBuffer, &dwRecvLength);
1002 [ - + ]: 3 : g_assert_cmpint(status, ==, VREADER_OK);
1003 [ - + ]: 3 : g_assert_cmpint(dwRecvLength, ==, 0x21);
1004 [ - + ]: 3 : g_assert_cmpint(pbRecvBuffer[dwRecvLength-2], ==, VCARD7816_SW1_SUCCESS);
1005 [ - + ]: 3 : g_assert_cmpint(pbRecvBuffer[dwRecvLength-1], ==, 0x00);
1006 : :
1007 : : /* The above should have triggered the compat bits to return remaining 3 PIN attempts */
1008 : : /* Get login count */
1009 : 3 : status = vreader_xfr_bytes(reader,
1010 : : login, sizeof(login),
1011 : : pbRecvBuffer, &dwRecvLength);
1012 [ - + ]: 3 : g_assert_cmpint(status, ==, VREADER_OK);
1013 : 3 : if (isHWTests()) { /* HW tests have PIN and we assume there are still three attempts */
1014 [ - + ]: 2 : g_assert_cmphex(pbRecvBuffer[0], ==, VCARD7816_SW1_WARNING_CHANGE);
1015 [ - + ]: 2 : g_assert_cmphex(pbRecvBuffer[1], ==, 0xc3);
1016 : : } else { /* NSS softoken does not have passphrase so it is unlocked automatically */
1017 [ - + ]: 1 : g_assert_cmphex(pbRecvBuffer[0], ==, VCARD7816_SW1_SUCCESS);
1018 [ - + ]: 1 : g_assert_cmphex(pbRecvBuffer[1], ==, 0x00);
1019 : : }
1020 : :
1021 : :
1022 : :
1023 : 3 : vreader_free(reader); /* get by id ref */
1024 : : }
1025 : :
1026 : 6 : void select_gp(VReader *reader)
1027 : : {
1028 : 6 : int dwRecvLength = APDUBufSize;
1029 : : VReaderStatus status;
1030 : : uint8_t pbRecvBuffer[APDUBufSize];
1031 : 6 : uint8_t getresp[] = {
1032 : : /* Get Response (max we can get) */
1033 : : 0x00, 0xc0, 0x00, 0x00, 0x00
1034 : : };
1035 : 6 : uint8_t gp_aid[] = {
1036 : : 0xA0, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00
1037 : : };
1038 : :
1039 : : /* select GP and wait for the response bytes */
1040 : 6 : select_aid_response(reader, gp_aid, sizeof(gp_aid), 0x1b);
1041 : :
1042 : : /* read the response from the card */
1043 : 6 : dwRecvLength = APDUBufSize;
1044 : 6 : status = vreader_xfr_bytes(reader,
1045 : : getresp, sizeof(getresp),
1046 : : pbRecvBuffer, &dwRecvLength);
1047 [ - + ]: 6 : g_assert_cmpint(status, ==, VREADER_OK);
1048 [ - + ]: 6 : g_assert_cmpint(dwRecvLength, >, 2);
1049 [ - + ]: 6 : g_assert_cmphex(pbRecvBuffer[dwRecvLength-2], ==, VCARD7816_SW1_SUCCESS);
1050 [ - + ]: 6 : g_assert_cmphex(pbRecvBuffer[dwRecvLength-1], ==, 0x00);
1051 : 6 : }
1052 : :
1053 : 3 : void test_gp_applet(void)
1054 : : {
1055 : 3 : int dwRecvLength = APDUBufSize;
1056 : : VReaderStatus status;
1057 : : uint8_t pbRecvBuffer[APDUBufSize];
1058 : 3 : uint8_t getdata[] = {
1059 : : /* Get Data (max we can get) */
1060 : : 0x00, 0xca, 0x9f, 0x7f, 0x00
1061 : : };
1062 : 3 : VReader *reader = vreader_get_reader_by_id(0);
1063 : : unsigned int equal_bytes = 0, n;
1064 : :
1065 : 3 : select_gp(reader);
1066 : :
1067 : : /* We made sure the selection of other applets does not return anything
1068 : : * in select_aid()
1069 : : */
1070 : :
1071 : : /* ask the applet for some data */
1072 : 3 : dwRecvLength = APDUBufSize;
1073 : 3 : status = vreader_xfr_bytes(reader,
1074 : : getdata, sizeof(getdata),
1075 : : pbRecvBuffer, &dwRecvLength);
1076 [ - + ]: 3 : g_assert_cmpint(status, ==, VREADER_OK);
1077 [ - + ]: 3 : g_assert_cmpint(dwRecvLength, ==, 0x2F);
1078 [ - + ]: 3 : g_assert_cmpint(pbRecvBuffer[dwRecvLength-2], ==, VCARD7816_SW1_SUCCESS);
1079 [ - + ]: 3 : g_assert_cmpint(pbRecvBuffer[dwRecvLength-1], ==, 0x00);
1080 : : /* This part should be generate from certificate hash, which should
1081 : : * overwrite default values in template */
1082 [ + + ]: 21 : for (n = 15; n <= 20; ++n) {
1083 : 18 : equal_bytes += (pbRecvBuffer[n] == 0x00);
1084 : : }
1085 [ - + ]: 3 : g_assert_cmpint(equal_bytes, <, 6);
1086 : :
1087 : : /* 0x0066 tag should return card registration data */
1088 : 3 : dwRecvLength = APDUBufSize;
1089 : 3 : getdata[2] = 0x00;
1090 : 3 : getdata[3] = 0x66;
1091 : 3 : status = vreader_xfr_bytes(reader,
1092 : : getdata, sizeof(getdata),
1093 : : pbRecvBuffer, &dwRecvLength);
1094 [ - + ]: 3 : g_assert_cmpint(status, ==, VREADER_OK);
1095 [ - + ]: 3 : g_assert_cmpint(dwRecvLength, ==, 53);
1096 [ - + ]: 3 : g_assert_cmpint(pbRecvBuffer[dwRecvLength-2], ==, VCARD7816_SW1_SUCCESS);
1097 [ - + ]: 3 : g_assert_cmpint(pbRecvBuffer[dwRecvLength-1], ==, 0x00);
1098 : :
1099 : : /* anything else should fail */
1100 : 3 : dwRecvLength = APDUBufSize;
1101 : 3 : getdata[2] = 0xff;
1102 : 3 : getdata[3] = 0xff;
1103 : 3 : status = vreader_xfr_bytes(reader,
1104 : : getdata, sizeof(getdata),
1105 : : pbRecvBuffer, &dwRecvLength);
1106 [ - + ]: 3 : g_assert_cmpint(status, ==, VREADER_OK);
1107 [ - + ]: 3 : g_assert_cmpint(dwRecvLength, ==, 2);
1108 [ - + ]: 3 : g_assert_cmpint(pbRecvBuffer[dwRecvLength-2], ==, 0x6a);
1109 [ - + ]: 3 : g_assert_cmpint(pbRecvBuffer[dwRecvLength-1], ==, 0x88);
1110 : 3 : vreader_free(reader); /* get by id ref */
1111 : 3 : }
1112 : :
1113 : : int
1114 : 0 : isHWTests(void)
1115 : : {
1116 [ + + + + : 18 : return hw_tests;
+ + + + +
+ + + ]
1117 : : }
1118 : :
1119 : : void
1120 : 2 : setHWTests(int new_value)
1121 : : {
1122 : 2 : hw_tests = new_value;
1123 : 2 : }
1124 : :
1125 : : int
1126 : 2 : getBits(void)
1127 : : {
1128 : 2 : return key_bits;
1129 : : }
1130 : :
1131 : :
1132 : : /* vim: set ts=4 sw=4 tw=0 noet expandtab: */
|