[Spice-devel] [PATCH libcacard 13/45] tests: Test previously introduced applets
Jakub Jelen
jjelen at redhat.com
Tue Jul 31 14:50:07 UTC 2018
* Make sure the GET PROPERTIES APDU returns something on every applet
* Make sure the GET ACR APDU returns something reasonable on ACA applet
with valid and invalid parameters
* Make sure the READ BUFFER APDU retunrs valid buffers
Signed-off-by: Jakub Jelen <jjelen at redhat.com>
Reviewed-by: Robert Relyea <rrelyea at redhat.com>
---
tests/libcacard.c | 341 +++++++++++++++++++++++++++++++++++++++++-----
1 file changed, 308 insertions(+), 33 deletions(-)
diff --git a/tests/libcacard.c b/tests/libcacard.c
index a6ff49b..fb2a8ca 100644
--- a/tests/libcacard.c
+++ b/tests/libcacard.c
@@ -128,6 +128,7 @@ static void test_xfer(void)
int dwRecvLength = APDUBufSize;
uint8_t pbRecvBuffer[APDUBufSize];
uint8_t pbSendBuffer[] = {
+ /* Select Applet that is not there */
0x00, 0xa4, 0x04, 0x00, 0x07, 0x62, 0x76, 0x01, 0xff, 0x00, 0x00, 0x00,
};
@@ -139,59 +140,329 @@ static void test_xfer(void)
vreader_free(reader); /* get by id ref */
}
-static void test_cac(void)
+static void get_properties(VReader *reader)
{
- VReader *reader = vreader_get_reader_by_id(0);
+ int dwRecvLength = APDUBufSize;
VReaderStatus status;
- int dwRecvLength = APDUBufSize, len;
uint8_t pbRecvBuffer[APDUBufSize];
- uint8_t selfile0[] = {
- 0x00, 0xa4, 0x04, 0x00, 0x07, 0xa0, 0x00, 0x00, 0x00, 0x79, 0x01, 0x00
+ uint8_t get_properties[] = {
+ /* Get properties */
+ 0x80, 0x56, 0x01, 0x00, 0x00
};
- uint8_t getresp[] = {
- 0x00, 0xc0, 0x00, 0x00, 0x07
+
+ status = vreader_xfr_bytes(reader,
+ get_properties, sizeof(get_properties),
+ pbRecvBuffer, &dwRecvLength);
+ g_assert_cmpint(status, ==, VREADER_OK);
+ g_assert_cmpint(dwRecvLength, >, 2);
+ g_assert_cmpint(pbRecvBuffer[dwRecvLength-2], ==, VCARD7816_SW1_SUCCESS);
+ g_assert_cmpint(pbRecvBuffer[dwRecvLength-1], ==, 0x00);
+
+}
+
+static void get_acr(VReader *reader)
+{
+ int dwRecvLength = APDUBufSize;
+ VReaderStatus status;
+ uint8_t pbRecvBuffer[APDUBufSize];
+ uint8_t get_acr[] = {
+ /* Get ACR [TYPE] [ 0 ] [Le] */
+ 0x80, 0x4c, 0x00, 0x00, 0x00
};
- uint8_t getcert[] = {
- 0x00, 0x36, 0x00, 0x00, 0x00
+ uint8_t get_acr_arg[] = {
+ /* Get ACR [TYPE] [ 0 ] [Lc] [data] [Le] */
+ 0x80, 0x4c, 0x01, 0x00, 0x01, 0x0A, 0x00
+ };
+ uint8_t get_acr_coid[] = {
+ /* Get ACR [TYPE] [ 0 ] [Lc] [ data ] [Le] */
+ 0x80, 0x4c, 0x12, 0x00, 0x02, 0xDB, 0x00, 0x00
+ };
+ uint8_t get_acr_aid[] = {
+ /* Get ACR [TYPE] [ 0 ] [Lc] [ data ] [Le]*/
+ 0x80, 0x4c, 0x11, 0x00, 0x07, 0xA0, 0x00, 0x00, 0x00, 0x79, 0x12, 0x02, 0x00
+ };
+ uint8_t getresp[] = {
+ /* Get Response (max we can get) */
+ 0x00, 0xc0, 0x00, 0x00, 0x00
};
- g_assert_nonnull(reader);
+ /* P1=0x00: ACR table */
+ dwRecvLength = APDUBufSize;
status = vreader_xfr_bytes(reader,
- selfile0, sizeof(selfile0),
+ get_acr, sizeof(get_acr),
+ pbRecvBuffer, &dwRecvLength);
+ g_assert_cmpint(status, ==, VREADER_OK);
+ g_assert_cmpint(dwRecvLength, >, 2);
+ g_assert_cmphex(pbRecvBuffer[dwRecvLength-2], ==, VCARD7816_SW1_SUCCESS);
+ g_assert_cmphex(pbRecvBuffer[dwRecvLength-1], ==, 0x00);
+
+ /* TODO parse the response */
+
+
+ /* P1=0x01: ACR table by ACRID=0x0A */
+ dwRecvLength = APDUBufSize;
+ status = vreader_xfr_bytes(reader,
+ get_acr_arg, sizeof(get_acr_arg),
+ pbRecvBuffer, &dwRecvLength);
+ g_assert_cmpint(status, ==, VREADER_OK);
+ g_assert_cmpint(dwRecvLength, >, 2);
+ g_assert_cmphex(pbRecvBuffer[dwRecvLength-2], ==, VCARD7816_SW1_SUCCESS);
+ g_assert_cmphex(pbRecvBuffer[dwRecvLength-1], ==, 0x00);
+
+ /* P1=0x01: ACR table by ACRID=0x0F (non-existing) */
+ get_acr_arg[5] = 0x0F;
+ dwRecvLength = APDUBufSize;
+ status = vreader_xfr_bytes(reader,
+ get_acr_arg, sizeof(get_acr_arg),
+ pbRecvBuffer, &dwRecvLength);
+ g_assert_cmpint(status, ==, VREADER_OK);
+ g_assert_cmpint(dwRecvLength, ==, 2);
+ g_assert_cmphex(pbRecvBuffer[dwRecvLength-2], ==, 0x6a);
+ g_assert_cmphex(pbRecvBuffer[dwRecvLength-1], ==, 0x88);
+
+
+ /* P1=0x10: Applet/Object ACR table */
+ get_acr[2] = 0x10;
+ dwRecvLength = APDUBufSize;
+ status = vreader_xfr_bytes(reader,
+ get_acr, sizeof(get_acr),
pbRecvBuffer, &dwRecvLength);
g_assert_cmpint(status, ==, VREADER_OK);
- g_assert_cmphex(pbRecvBuffer[0], ==, VCARD7816_SW1_RESPONSE_BYTES);
- g_assert_cmphex(pbRecvBuffer[1], ==, 0x7);
+ /* This one is big, so we will get SW1 = 0x61 without the actual response */
+ g_assert_cmpint(dwRecvLength, ==, 2);
+ g_assert_cmphex(pbRecvBuffer[dwRecvLength-2], ==, VCARD7816_SW1_RESPONSE_BYTES);
+ g_assert_cmphex(pbRecvBuffer[dwRecvLength-1], ==, 0x00);
+ /* fetch the actual response */
dwRecvLength = APDUBufSize;
status = vreader_xfr_bytes(reader,
getresp, sizeof(getresp),
pbRecvBuffer, &dwRecvLength);
g_assert_cmpint(status, ==, VREADER_OK);
- g_assert_cmpint(dwRecvLength, ==, 9);
- g_assert_cmphex(pbRecvBuffer[7], ==, VCARD7816_SW1_SUCCESS);
- g_assert_cmphex(pbRecvBuffer[8], ==, 0x0);
+ g_assert_cmpint(dwRecvLength, >, 2);
+ g_assert_cmphex(pbRecvBuffer[dwRecvLength-2], ==, VCARD7816_SW1_RESPONSE_BYTES);
+ g_assert_cmphex(pbRecvBuffer[dwRecvLength-1], >, 0x00);
- len = 0xff;
+ /* ignore the rest for now */
+
+
+ /* P1=0x11: Applet/Object ACR table by AID */
+ dwRecvLength = APDUBufSize;
+ status = vreader_xfr_bytes(reader,
+ get_acr_aid, sizeof(get_acr_aid),
+ pbRecvBuffer, &dwRecvLength);
+ g_assert_cmpint(status, ==, VREADER_OK);
+ g_assert_cmpint(dwRecvLength, >, 2);
+ g_assert_cmphex(pbRecvBuffer[dwRecvLength-2], ==, VCARD7816_SW1_SUCCESS);
+ g_assert_cmphex(pbRecvBuffer[dwRecvLength-1], ==, 0x00);
+
+ /* P1=0x11: unknown AID should fail */
+ get_acr_aid[11] = 0x11;
+ dwRecvLength = APDUBufSize;
+ status = vreader_xfr_bytes(reader,
+ get_acr_aid, sizeof(get_acr_aid),
+ pbRecvBuffer, &dwRecvLength);
+ g_assert_cmpint(status, ==, VREADER_OK);
+ g_assert_cmpint(dwRecvLength, ==, 2);
+ g_assert_cmphex(pbRecvBuffer[dwRecvLength-2], ==, VCARD7816_SW1_P1_P2_ERROR);
+ g_assert_cmphex(pbRecvBuffer[dwRecvLength-1], ==, 0x88);
+
+
+ /* P1=0x12: Applet/Object ACR table by OID */
+ dwRecvLength = APDUBufSize;
+ status = vreader_xfr_bytes(reader,
+ get_acr_coid, sizeof(get_acr_coid),
+ pbRecvBuffer, &dwRecvLength);
+ g_assert_cmpint(status, ==, VREADER_OK);
+ g_assert_cmpint(dwRecvLength, >, 2);
+ g_assert_cmphex(pbRecvBuffer[dwRecvLength-2], ==, VCARD7816_SW1_SUCCESS);
+ g_assert_cmphex(pbRecvBuffer[dwRecvLength-1], ==, 0x00);
+
+ /* P1=0x12: unknown OID should fail */
+ get_acr_coid[6] = 0xDB;
+ dwRecvLength = APDUBufSize;
+ status = vreader_xfr_bytes(reader,
+ get_acr_coid, sizeof(get_acr_coid),
+ pbRecvBuffer, &dwRecvLength);
+ g_assert_cmpint(status, ==, VREADER_OK);
+ g_assert_cmpint(dwRecvLength, ==, 2);
+ g_assert_cmphex(pbRecvBuffer[dwRecvLength-2], ==, VCARD7816_SW1_P1_P2_ERROR);
+ g_assert_cmphex(pbRecvBuffer[dwRecvLength-1], ==, 0x80);
+
+
+ /* P1=0x20: Access Method Provider table */
+ get_acr[2] = 0x20;
+ dwRecvLength = APDUBufSize;
+ status = vreader_xfr_bytes(reader,
+ get_acr, sizeof(get_acr),
+ pbRecvBuffer, &dwRecvLength);
+ g_assert_cmpint(status, ==, VREADER_OK);
+ g_assert_cmpint(dwRecvLength, >, 2);
+ g_assert_cmphex(pbRecvBuffer[dwRecvLength-2], ==, VCARD7816_SW1_SUCCESS);
+ g_assert_cmphex(pbRecvBuffer[dwRecvLength-1], ==, 0x00);
+
+ /* P1=0x21: Service Applet Table */
+ get_acr[2] = 0x21;
+ dwRecvLength = APDUBufSize;
+ status = vreader_xfr_bytes(reader,
+ get_acr, sizeof(get_acr),
+ pbRecvBuffer, &dwRecvLength);
+ g_assert_cmpint(status, ==, VREADER_OK);
+ g_assert_cmpint(dwRecvLength, >, 2);
+ g_assert_cmphex(pbRecvBuffer[dwRecvLength-2], ==, VCARD7816_SW1_SUCCESS);
+ g_assert_cmphex(pbRecvBuffer[dwRecvLength-1], ==, 0x00);
+
+}
+
+static void read_buffer(VReader *reader, uint8_t type)
+{
+ int dwRecvLength = APDUBufSize, dwLength, dwTagLength, offset;
+ VReaderStatus status;
+ uint8_t pbRecvBuffer[APDUBufSize];
+ uint8_t getresp[] = {
+ /* Get Response (max we can get) */
+ 0x00, 0xc0, 0x00, 0x00, 0xFF
+ };
+ uint8_t read_buffer[] = {
+ /*Read Buffer OFFSET TYPE LENGTH */
+ 0x80, 0x52, 0x00, 0x00, 0x02, 0x01, 0x02
+ };
+
+ dwRecvLength = 2;
+ read_buffer[5] = type;
+ status = vreader_xfr_bytes(reader,
+ read_buffer, sizeof(read_buffer),
+ pbRecvBuffer, &dwRecvLength);
+ g_assert_cmpint(status, ==, VREADER_OK);
+ g_assert_cmpint(dwRecvLength, ==, 2);
+ g_assert_cmpint(pbRecvBuffer[0], ==, VCARD7816_SW1_RESPONSE_BYTES);
+ g_assert_cmpint(pbRecvBuffer[1], ==, 0x02);
+
+ dwRecvLength = 4;
+ status = vreader_xfr_bytes(reader,
+ getresp, sizeof(getresp),
+ pbRecvBuffer, &dwRecvLength);
+ g_assert_cmpint(status, ==, VREADER_OK);
+ g_assert_cmpint(dwRecvLength, ==, 4);
+ g_assert_cmphex(pbRecvBuffer[2], ==, VCARD7816_SW1_SUCCESS);
+ g_assert_cmphex(pbRecvBuffer[3], ==, 0x00);
+
+ dwLength = (pbRecvBuffer[0] & 0xff) | ((pbRecvBuffer[1] << 8) & 0xff);
+ offset = 0x02;
do {
- dwRecvLength = APDUBufSize;
- getcert[4] = len;
+ /* This returns only success -- get response is needed to get the actual data */
+ dwRecvLength = 2;
+ dwTagLength = MIN(255, dwLength);
+ read_buffer[2] = (unsigned char) ((offset >> 8) & 0xff);
+ read_buffer[3] = (unsigned char) (offset & 0xff);
+ read_buffer[6] = (unsigned char) (dwTagLength);
status = vreader_xfr_bytes(reader,
- getcert, sizeof(getcert),
+ read_buffer, sizeof(read_buffer),
pbRecvBuffer, &dwRecvLength);
g_assert_cmpint(status, ==, VREADER_OK);
- g_assert_cmpint(dwRecvLength, ==, len + 2);
- switch (pbRecvBuffer[len]) {
- case VCARD7816_SW1_WARNING_CHANGE:
- len = pbRecvBuffer[len+1];
- break;
- case VCARD7816_SW1_SUCCESS:
- len = 0;
- break;
- default:
- g_assert_not_reached();
- }
- } while (len != 0);
+ g_assert_cmpint(dwRecvLength, ==, 2);
+ g_assert_cmpint(pbRecvBuffer[0], ==, VCARD7816_SW1_RESPONSE_BYTES);
+ g_assert_cmpint(pbRecvBuffer[1], ==, dwLength);
+
+ dwRecvLength = dwTagLength + 2;
+ status = vreader_xfr_bytes(reader,
+ getresp, sizeof(getresp),
+ pbRecvBuffer, &dwRecvLength);
+ g_assert_cmpint(status, ==, VREADER_OK);
+ g_assert_cmpint(dwRecvLength, ==, dwLength + 2);
+ g_assert_cmphex(pbRecvBuffer[dwLength], ==, VCARD7816_SW1_SUCCESS);
+ g_assert_cmphex(pbRecvBuffer[dwLength+1], ==, 0x00);
+
+ dwLength -= dwTagLength;
+ } while (dwLength != 0);
+}
+
+static void test_cac_pki(void)
+{
+ VReader *reader = vreader_get_reader_by_id(0);
+ VReaderStatus status;
+ int dwRecvLength = APDUBufSize;
+ uint8_t pbRecvBuffer[APDUBufSize];
+ uint8_t selfile0[] = {
+ /* Select first PKI Applet */
+ 0x00, 0xa4, 0x04, 0x00, 0x07, 0xa0, 0x00, 0x00, 0x00, 0x79, 0x01, 0x00
+ };
+
+ g_assert_nonnull(reader);
+ status = vreader_xfr_bytes(reader,
+ selfile0, sizeof(selfile0),
+ pbRecvBuffer, &dwRecvLength);
+ g_assert_cmpint(status, ==, VREADER_OK);
+ g_assert_cmphex(pbRecvBuffer[0], ==, VCARD7816_SW1_SUCCESS);
+ g_assert_cmphex(pbRecvBuffer[1], ==, 0x00);
+
+ /* get properties */
+ get_properties(reader);
+
+ /* get the TAG buffer length */
+ read_buffer(reader, CAC_FILE_TAG);
+
+ /* get the VALUE buffer length */
+ read_buffer(reader, CAC_FILE_VALUE);
+
+ vreader_free(reader); /* get by id ref */
+}
+
+static void test_cac_ccc(void)
+{
+ VReader *reader = vreader_get_reader_by_id(0);
+ VReaderStatus status;
+ int dwRecvLength = APDUBufSize;
+ uint8_t pbRecvBuffer[APDUBufSize];
+ uint8_t selfile0[] = {
+ /* Select first PKI Applet */
+ 0x00, 0xa4, 0x04, 0x00, 0x07, 0xa0, 0x00, 0x00, 0x01, 0x16, 0xDB, 0x00
+ };
+
+ g_assert_nonnull(reader);
+ status = vreader_xfr_bytes(reader,
+ selfile0, sizeof(selfile0),
+ pbRecvBuffer, &dwRecvLength);
+ g_assert_cmpint(status, ==, VREADER_OK);
+ g_assert_cmphex(pbRecvBuffer[0], ==, VCARD7816_SW1_SUCCESS);
+ g_assert_cmphex(pbRecvBuffer[1], ==, 0x00);
+
+ /* get properties */
+ get_properties(reader);
+
+ /* get the TAG buffer length */
+ read_buffer(reader, CAC_FILE_TAG);
+
+ /* get the VALUE buffer length */
+ read_buffer(reader, CAC_FILE_VALUE);
+
+ vreader_free(reader); /* get by id ref */
+}
+
+static void test_cac_aca(void)
+{
+ VReader *reader = vreader_get_reader_by_id(0);
+ VReaderStatus status;
+ int dwRecvLength = APDUBufSize;
+ uint8_t pbRecvBuffer[APDUBufSize];
+ uint8_t selfile0[] = {
+ /* Select first PKI Applet */
+ 0x00, 0xa4, 0x04, 0x00, 0x07, 0xa0, 0x00, 0x00, 0x00, 0x79, 0x03, 0x00
+ };
+
+ g_assert_nonnull(reader);
+ status = vreader_xfr_bytes(reader,
+ selfile0, sizeof(selfile0),
+ pbRecvBuffer, &dwRecvLength);
+ g_assert_cmpint(status, ==, VREADER_OK);
+ g_assert_cmphex(pbRecvBuffer[0], ==, VCARD7816_SW1_SUCCESS);
+ g_assert_cmphex(pbRecvBuffer[1], ==, 0x00);
+
+ /* get properties */
+ get_properties(reader);
+
+ /* get ACR */
+ get_acr(reader);
vreader_free(reader); /* get by id ref */
}
@@ -225,7 +496,9 @@ int main(int argc, char *argv[])
g_test_add_func("/libcacard/list", test_list);
g_test_add_func("/libcacard/card-remove-insert", test_card_remove_insert);
g_test_add_func("/libcacard/xfer", test_xfer);
- g_test_add_func("/libcacard/cac", test_cac);
+ g_test_add_func("/libcacard/cac-pki", test_cac_pki);
+ g_test_add_func("/libcacard/cac-ccc", test_cac_ccc);
+ g_test_add_func("/libcacard/cac-aca", test_cac_aca);
g_test_add_func("/libcacard/remove", test_remove);
ret = g_test_run();
@@ -237,3 +510,5 @@ int main(int argc, char *argv[])
return ret;
}
+
+/* vim: set ts=4 sw=4 tw=0 noet expandtab: */
--
2.17.1
More information about the Spice-devel
mailing list