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