[Spice-devel] [PATCH libcacard 39/45] tests: Negative test cases to increase coverage
Jakub Jelen
jjelen at redhat.com
Tue Jul 31 14:50:33 UTC 2018
* mostly negative test cases that were missed during initial implementation
* passthrough and empty applets
* multi-part signatures
* check login count
* invalid GET PROPERTIES APDU queries
* invalid SELECT APDU queries
* invalid instructions
* invalid READ BUFFER APDU queries
* invalid GET ACR APDU queries
* properly clean up the memory when the test is finished
Signed-off-by: Jakub Jelen <jjelen at redhat.com>
Reviewed-by: Robert Relyea <rrelyea at redhat.com>
---
tests/common.c | 108 ++++++++++-
tests/common.h | 5 +-
tests/hwtests.c | 44 ++++-
tests/libcacard.c | 468 +++++++++++++++++++++++++++++++++++++++++++++-
4 files changed, 605 insertions(+), 20 deletions(-)
diff --git a/tests/common.c b/tests/common.c
index a70ec89..ee10af8 100644
--- a/tests/common.c
+++ b/tests/common.c
@@ -351,8 +351,6 @@ void read_buffer(VReader *reader, uint8_t type, int object_type)
g_assert_cmphex(pbRecvBuffer[dwRecvLength-1], ==, 0x00);
dwLength = (pbRecvBuffer[0] & 0xff) | ((pbRecvBuffer[1] << 8) & 0xff);
- if (object_type != TEST_EMPTY_BUFFER)
- g_assert_cmpint(dwLength, !=, 0);
if (dwLength == 0)
return;
@@ -424,6 +422,13 @@ void select_applet(VReader *reader, int type)
/* Select first PKI Applet */
0xa0, 0x00, 0x00, 0x00, 0x79, 0x01, 0x00
};
+ uint8_t selfile_passthrough[] = {
+ /* Select Person Instance (passthrough) */
+ 0xa0, 0x00, 0x00, 0x00, 0x79, 0x02, 0x00
+ };
+ uint8_t selfile_empty[] = {
+ 0xA0, 0x00, 0x00, 0x00, 0x79, 0x02, 0xF0
+ };
uint8_t *aid = NULL;
size_t aid_len = 0;
@@ -443,6 +448,16 @@ void select_applet(VReader *reader, int type)
aid_len = sizeof(selfile_aca);
break;
+ case TEST_PASSTHROUGH:
+ aid = selfile_passthrough;
+ aid_len = sizeof(selfile_passthrough);
+ break;
+
+ case TEST_EMPTY:
+ aid = selfile_empty;
+ aid_len = sizeof(selfile_empty);
+ break;
+
default:
g_assert_not_reached();
}
@@ -451,7 +466,7 @@ void select_applet(VReader *reader, int type)
select_aid(reader, aid, aid_len);
}
-void do_sign(VReader *reader)
+void do_sign(VReader *reader, int parts)
{
VReaderStatus status;
int dwRecvLength = APDUBufSize;
@@ -492,6 +507,37 @@ void do_sign(VReader *reader)
sign_len = 5 + key_bits/8;
}
+ /* The driver supports signatures while data are passed in more separate APDUs */
+ if (parts) {
+ int split = 0x47;
+ /* we have not sent the whole buffer */
+ sign[2] = 0x80;
+ sign[4] = split;
+ sign[5] = 0x00;
+ sign[6] = 0x01;
+ sign[7] = 0xFF;
+ sign[8] = 0xFF;
+ sign_len = 5 + split;
+
+ status = vreader_xfr_bytes(reader,
+ sign, sign_len,
+ 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);
+
+ /* the next message will send the rest of the buffer */
+ sign[2] = 0x00;
+ if (key_bits)
+ sign[4] = key_bits/8 - split;
+ else
+ sign[4] = 256 - split;
+ memmove(&sign[5], &sign[5+2+split], sign[4]);
+ sign_len = 5 + sign[4];
+ }
+
+ dwRecvLength = APDUBufSize;
status = vreader_xfr_bytes(reader,
sign, sign_len,
pbRecvBuffer, &dwRecvLength);
@@ -629,6 +675,16 @@ void test_get_response(void)
/* select CCC */
select_applet(reader, TEST_CCC);
+ /* read buffer without response buffer. Ignore the response. */
+ dwRecvLength = 2;
+ 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);
+
/* read buffer without response buffer */
dwRecvLength = 2;
status = vreader_xfr_bytes(reader,
@@ -674,10 +730,54 @@ void test_get_response(void)
g_assert_cmphex(pbRecvBuffer[dwRecvLength-2], ==, VCARD7816_SW1_SUCCESS);
g_assert_cmphex(pbRecvBuffer[dwRecvLength-1], ==, 0x00);
- g_assert_cmpint(dwLength, ==, 0x34);
+ /* If we ask again, when there is no pending response */
+ dwRecvLength = dwLength + 2;
+ getresp[4] = dwLength;
+ status = vreader_xfr_bytes(reader,
+ getresp, sizeof(getresp),
+ 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);
+
vreader_free(reader); /* get by id ref */
}
+void check_login_count(void)
+{
+ VReader *reader = vreader_get_reader_by_id(0);
+ VReaderStatus status;
+ int dwRecvLength = APDUBufSize;
+ uint8_t pbRecvBuffer[APDUBufSize];
+ uint8_t login[] = {
+ /* VERIFY [p1,p2=0 ] [Lc] */
+ 0x00, 0x20, 0x00, 0x00, 0x00
+ };
+ g_assert_nonnull(reader);
+
+ /* Get login count */
+ status = vreader_xfr_bytes(reader,
+ login, sizeof(login),
+ pbRecvBuffer, &dwRecvLength);
+ g_assert_cmpint(status, ==, VREADER_OK);
+ /* NSS does not know how to do this yet */
+ g_assert_cmphex(pbRecvBuffer[0], ==, VCARD7816_SW1_P1_P2_ERROR);
+ g_assert_cmphex(pbRecvBuffer[1], ==, 0x88);
+
+ /* P1 = 0x01 is invalid */
+ login[2] = 0x01;
+ status = vreader_xfr_bytes(reader,
+ login, sizeof(login),
+ pbRecvBuffer, &dwRecvLength);
+ g_assert_cmpint(status, ==, VREADER_OK);
+ g_assert_cmphex(pbRecvBuffer[0], ==, VCARD7816_SW1_P1_P2_ERROR);
+ g_assert_cmphex(pbRecvBuffer[1], ==, 0x00);
+
+ vreader_free(reader);
+}
+
+
int
isHWTests(void)
{
diff --git a/tests/common.h b/tests/common.h
index c02ea6b..611bc3f 100644
--- a/tests/common.h
+++ b/tests/common.h
@@ -22,6 +22,7 @@ enum {
TEST_GENERIC = 4,
TEST_EMPTY_BUFFER = 5,
TEST_EMPTY = 6,
+ TEST_PASSTHROUGH = 7,
};
void select_coid_good(VReader *reader, unsigned char *coid);
@@ -37,12 +38,14 @@ void get_properties(VReader *reader, int object_type);
void read_buffer(VReader *reader, uint8_t type, int object_type);
-void do_sign(VReader *reader);
+void do_sign(VReader *reader, int parts);
void test_empty_applets(void);
void test_get_response(void);
+void check_login_count(void);
+
int isHWTests(void);
void setHWTests(int);
diff --git a/tests/hwtests.c b/tests/hwtests.c
index 1e35a9b..e357ea2 100644
--- a/tests/hwtests.c
+++ b/tests/hwtests.c
@@ -32,7 +32,8 @@ events_thread(gpointer arg)
while (1) {
event = vevent_wait_next_vevent();
- if (event == NULL) {
+ if (event == NULL || event->type == VEVENT_LAST) {
+ vevent_delete(event);
break;
}
reader_id = vreader_get_id(event->reader);
@@ -106,6 +107,7 @@ static void test_list(void)
vreader_free(r);
}
if (cards == 0) {
+ vreader_list_delete(list);
g_test_skip("No physical card found");
return;
}
@@ -122,11 +124,21 @@ static void do_login(VReader *reader)
uint8_t login[] = {
/* VERIFY [p1,p2=0 ] [Lc] [pin 77777777 ] */
0x00, 0x20, 0x00, 0x00, 0x08,
- 0x37, 0x37, 0x37, 0x37, 0x37, 0x37, 0x37, 0x37
+ //0x37, 0x37, 0x37, 0x37, 0x37, 0x37, 0x37, 0x37
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
};
+ int login_len, pin_len;
+
g_assert_nonnull(reader);
+
+ /* Set the pin from constant */
+ pin_len = strlen(LOGIN_PIN);
+ login[4] = pin_len;
+ memcpy(&login[5], LOGIN_PIN, pin_len);
+ login_len = 5 + pin_len;
+
status = vreader_xfr_bytes(reader,
- login, sizeof(login),
+ login, login_len,
pbRecvBuffer, &dwRecvLength);
g_assert_cmpint(status, ==, VREADER_OK);
g_assert_cmphex(pbRecvBuffer[0], ==, VCARD7816_SW1_SUCCESS);
@@ -227,7 +239,10 @@ static void test_sign(void)
/* get properties to figure out the key length */
get_properties(reader, TEST_PKI);
- do_sign(reader);
+ do_sign(reader, 0);
+
+ /* test also multipart signatures */
+ do_sign(reader, 1);
vreader_free(reader); /* get by id ref */
}
@@ -345,6 +360,21 @@ static void test_sign_bad_data_x509(void)
vreader_free(reader); /* get by id ref */
}
+static void libcacard_finalize(void)
+{
+ VReader *reader = vreader_get_reader_by_id(0);
+
+ /* This probably supposed to be a event that terminates the loop */
+ vevent_queue_vevent(vevent_new(VEVENT_LAST, reader, NULL));
+
+ /* join */
+ g_thread_join(thread);
+
+ /* Clean up */
+ vreader_free(reader);
+ vreader_free(reader);
+}
+
int main(int argc, char *argv[])
{
int ret;
@@ -358,6 +388,7 @@ int main(int argc, char *argv[])
g_test_add_func("/hw-tests/list", test_list);
g_test_add_func("/hw-tests/passthrough-applet", test_passthrough_applets);
g_test_add_func("/hw-tests/login", test_login);
+ g_test_add_func("/hw-tests/check-login-count", check_login_count);
g_test_add_func("/hw-tests/sign", test_sign);
g_test_add_func("/hw-tests/sign-bad-data", test_sign_bad_data_x509);
g_test_add_func("/hw-tests/empty-applets", test_empty_applets_hw);
@@ -365,10 +396,7 @@ int main(int argc, char *argv[])
ret = g_test_run();
- g_main_loop_unref(loop);
-
- /* FIXME: no wait to queue a NULL event */
- /* g_thread_join(thread); */
+ libcacard_finalize();
return ret;
}
diff --git a/tests/libcacard.c b/tests/libcacard.c
index cd08a54..eb3ad49 100644
--- a/tests/libcacard.c
+++ b/tests/libcacard.c
@@ -4,8 +4,8 @@
* Copyright 2018 Red Hat, Inc.
*
* Authors:
- * Jakub Jelen <jjelen at redhat.com>
* Marc-André Lureau <marcandre.lureau at redhat.com>
+ * Jakub Jelen <jjelen at redhat.com>
*
* This code is licensed under the GNU LGPL, version 2.1 or later.
* See the COPYING file in the top-level directory.
@@ -32,7 +32,8 @@ events_thread(gpointer arg)
while (1) {
event = vevent_wait_next_vevent();
- if (event == NULL) {
+ if (event == NULL || event->type == VEVENT_LAST) {
+ vevent_delete(event);
break;
}
reader_id = vreader_get_id(event->reader);
@@ -103,6 +104,7 @@ static void test_list(void)
if (vreader_card_is_present(r) == VREADER_OK) {
cards++;
}
+ vreader_free(r);
}
g_assert_cmpint(cards, ==, 1);
vreader_list_delete(list);
@@ -540,7 +542,10 @@ static void test_sign(void)
/* select the PKI */
select_applet(reader, TEST_PKI);
- do_sign(reader);
+ do_sign(reader, 0);
+
+ /* test also multipart signatures */
+ do_sign(reader, 1);
vreader_free(reader); /* get by id ref */
}
@@ -555,7 +560,7 @@ static void test_remove(void)
status = vreader_remove_reader(reader);
g_assert_cmpint(status, ==, VREADER_OK);
vreader_free(reader); /* get by id ref */
- vreader_free(reader);
+ //vreader_free(reader);
reader = vreader_get_reader_by_id(0);
g_assert_null(reader);
@@ -613,6 +618,10 @@ static void test_gp_applet(void)
/* Get Response (max we can get) */
0x00, 0xc0, 0x00, 0x00, 0x00
};
+ uint8_t getdata[] = {
+ /* Get Response (max we can get) */
+ 0x00, 0xca, 0x9f, 0x7f, 0x00
+ };
VReader *reader = vreader_get_reader_by_id(0);
/* select GP and wait for the response bytes */
@@ -632,8 +641,447 @@ static void test_gp_applet(void)
* in select_aid()
*/
+ /* ask the applet for some data */
+ dwRecvLength = APDUBufSize;
+ status = vreader_xfr_bytes(reader,
+ getdata, sizeof(getdata),
+ pbRecvBuffer, &dwRecvLength);
+ g_assert_cmpint(status, ==, VREADER_OK);
+ g_assert_cmpint(dwRecvLength, ==, 0x2F);
+ g_assert_cmpint(pbRecvBuffer[dwRecvLength-2], ==, VCARD7816_SW1_SUCCESS);
+ g_assert_cmpint(pbRecvBuffer[dwRecvLength-1], ==, 0x00);
+
+ vreader_free(reader); /* get by id ref */
+}
+
+static void test_invalid_properties(void)
+{
+ VReader *reader = vreader_get_reader_by_id(0);
+ VReaderStatus status;
+ int dwRecvLength = APDUBufSize;
+ uint8_t pbRecvBuffer[APDUBufSize];
+ uint8_t get_properties[] = {
+ /* Get properties [Le] [RFU] */
+ 0x80, 0x56, 0x01, 0x00, 0x00, 0x00, 0x00
+ };
+ size_t get_properties_len = 5;
+
+ g_assert_nonnull(reader);
+
+ select_applet(reader, TEST_CCC);
+
+ /* P1 = 0x00 is not supported */
+ get_properties[2] = 0x00;
+ dwRecvLength = APDUBufSize;
+ status = vreader_xfr_bytes(reader,
+ get_properties, get_properties_len,
+ pbRecvBuffer, &dwRecvLength);
+ g_assert_cmpint(status, ==, VREADER_OK);
+ g_assert_cmpint(dwRecvLength, ==, 2);
+ g_assert_cmpint(pbRecvBuffer[0], ==, VCARD7816_SW1_P1_P2_ERROR);
+ g_assert_cmpint(pbRecvBuffer[1], ==, 0x86);
+ get_properties[2] = 0x01;
+
+ /* P1 = 0x01 fails with additional data provided */
+ get_properties[2] = 0x01;
+ get_properties[4] = 0x02;
+ dwRecvLength = APDUBufSize;
+ 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[0], ==, VCARD7816_SW1_COMMAND_ERROR);
+ g_assert_cmpint(pbRecvBuffer[1], ==, 0x84);
+ get_properties[2] = 0x01;
+
+ /* P2 needs to be zero */
+ get_properties[3] = 0x01;
+ get_properties[4] = 0x00;
+ dwRecvLength = APDUBufSize;
+ status = vreader_xfr_bytes(reader,
+ get_properties, get_properties_len,
+ pbRecvBuffer, &dwRecvLength);
+ g_assert_cmpint(status, ==, VREADER_OK);
+ g_assert_cmpint(dwRecvLength, ==, 2);
+ g_assert_cmpint(pbRecvBuffer[0], ==, VCARD7816_SW1_P1_P2_ERROR);
+ g_assert_cmpint(pbRecvBuffer[1], ==, 0x86);
+ get_properties[3] = 0x00;
+
+ /* P1 = 0x02 requires some data (empty is invalid) */
+ get_properties[2] = 0x02;
+ dwRecvLength = APDUBufSize;
+ status = vreader_xfr_bytes(reader,
+ get_properties, get_properties_len,
+ pbRecvBuffer, &dwRecvLength);
+ g_assert_cmpint(status, ==, VREADER_OK);
+ g_assert_cmpint(dwRecvLength, ==, 2);
+ g_assert_cmpint(pbRecvBuffer[0], ==, VCARD7816_SW1_COMMAND_ERROR);
+ g_assert_cmpint(pbRecvBuffer[1], ==, 0x84);
+
+ /* P1 = 0x02 with invalid data fails */
+ get_properties[4] = 0x02;
+ get_properties[6] = 0xFF;
+ dwRecvLength = APDUBufSize;
+ 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[0], ==, VCARD7816_SW1_P1_P2_ERROR);
+ g_assert_cmpint(pbRecvBuffer[1], ==, 0x88);
+
+ /* P1 = 0x88 is invalid */
+ get_properties[2] = 0x88;
+ dwRecvLength = APDUBufSize;
+ status = vreader_xfr_bytes(reader,
+ get_properties, get_properties_len,
+ pbRecvBuffer, &dwRecvLength);
+ g_assert_cmpint(status, ==, VREADER_OK);
+ g_assert_cmpint(dwRecvLength, ==, 2);
+ g_assert_cmpint(pbRecvBuffer[0], ==, VCARD7816_SW1_P1_P2_ERROR);
+ g_assert_cmpint(pbRecvBuffer[1], ==, 0x86);
+
+ vreader_free(reader); /* get by id ref */
+}
+
+static void test_invalid_select(void)
+{
+ VReader *reader = vreader_get_reader_by_id(0);
+ VReaderStatus status;
+ int dwRecvLength = APDUBufSize;
+ uint8_t pbRecvBuffer[APDUBufSize];
+ uint8_t selfile[] = {
+ 0x00, 0xa4, 0x02, 0x00, 0x07, 0xa0, 0x00, 0x00, 0x00, 0x79, 0x01, 0x00
+ };
+
+ g_assert_nonnull(reader);
+
+ select_applet(reader, TEST_CCC);
+
+ /* CAC applets handle only the P1 = 0x02: Empty OID is not valid */
+ selfile[4] = 0x00;
+ dwRecvLength = APDUBufSize;
+ status = vreader_xfr_bytes(reader,
+ selfile, 5,
+ pbRecvBuffer, &dwRecvLength);
+ g_assert_cmpint(status, ==, VREADER_OK);
+ g_assert_cmpint(dwRecvLength, ==, 2);
+ g_assert_cmpint(pbRecvBuffer[0], ==, VCARD7816_SW1_COMMAND_ERROR);
+ g_assert_cmpint(pbRecvBuffer[1], ==, 0x84);
+
+ /* CAC applets handle only the P1 = 0x02: 7B OID is not valid */
+ selfile[4] = 0x07;
+ dwRecvLength = APDUBufSize;
+ status = vreader_xfr_bytes(reader,
+ selfile, sizeof(selfile),
+ pbRecvBuffer, &dwRecvLength);
+ g_assert_cmpint(status, ==, VREADER_OK);
+ g_assert_cmpint(dwRecvLength, ==, 2);
+ g_assert_cmpint(pbRecvBuffer[0], ==, VCARD7816_SW1_COMMAND_ERROR);
+ g_assert_cmpint(pbRecvBuffer[1], ==, 0x84);
+
+ /* TODO check the iso7816 code handling the remaining SELECT APDUs */
+
+ vreader_free(reader); /* get by id ref */
+}
+
+static void test_invalid_instruction(void)
+{
+ VReader *reader = vreader_get_reader_by_id(0);
+ VReaderStatus status;
+ int dwRecvLength = APDUBufSize;
+ uint8_t pbRecvBuffer[APDUBufSize];
+ uint8_t apdu[] = {
+ 0x00, 0xff, 0x00, 0x00, 0x00
+ };
+
+ g_assert_nonnull(reader);
+
+ /* Card Capability Container */
+ select_applet(reader, TEST_CCC);
+
+ /* 0xFF is invalid instruction everywhere, but fails in apdu_ins_to_string() */
+ /*dwRecvLength = APDUBufSize;
+ status = vreader_xfr_bytes(reader,
+ apdu, sizeof(apdu),
+ pbRecvBuffer, &dwRecvLength);
+ g_assert_cmpint(status, ==, VREADER_OK);
+ g_assert_cmpint(dwRecvLength, ==, 2);
+ g_assert_cmpint(pbRecvBuffer[0], ==, VCARD7816_SW1_INS_ERROR);
+ g_assert_cmpint(pbRecvBuffer[1], ==, 0x00);*/
+
+ /* CCC Applet does not know GET ACR instruction */
+ apdu[1] = 0x4c;
+ dwRecvLength = APDUBufSize;
+ status = vreader_xfr_bytes(reader,
+ apdu, sizeof(apdu),
+ pbRecvBuffer, &dwRecvLength);
+ g_assert_cmpint(status, ==, VREADER_OK);
+ g_assert_cmpint(dwRecvLength, ==, 2);
+ g_assert_cmpint(pbRecvBuffer[0], ==, VCARD7816_SW1_INS_ERROR);
+ g_assert_cmpint(pbRecvBuffer[1], ==, 0x00);
+
+ /* TODO check the iso7816 code handling the remaining SELECT APDUs */
+
+
+ /* PKI Applet */
+ select_applet(reader, TEST_PKI);
+
+ /* Update Buffer is not supported */
+ apdu[1] = 0x58;
+ dwRecvLength = APDUBufSize;
+ status = vreader_xfr_bytes(reader,
+ apdu, sizeof(apdu),
+ pbRecvBuffer, &dwRecvLength);
+ g_assert_cmpint(status, ==, VREADER_OK);
+ g_assert_cmpint(dwRecvLength, ==, 2);
+ g_assert_cmpint(pbRecvBuffer[0], ==, VCARD7816_SW1_COMMAND_ERROR);
+ g_assert_cmpint(pbRecvBuffer[1], ==, 0x85);
+
+ vreader_free(reader); /* get by id ref */
+}
+
+static void test_invalid_read_buffer_applet(VReader *reader, int object_type)
+{
+
+ VReaderStatus status;
+ int dwRecvLength = APDUBufSize;
+ uint8_t pbRecvBuffer[APDUBufSize];
+ uint8_t apdu[] = {
+ 0x00, 0x52, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00
+ };
+ int apdu_len;
+
+ select_applet(reader, object_type);
+
+ /* Empty body is not accepted */
+ apdu[4] = 0x00;
+ apdu_len = 5;
+ dwRecvLength = APDUBufSize;
+ status = vreader_xfr_bytes(reader,
+ apdu, apdu_len,
+ pbRecvBuffer, &dwRecvLength);
+ g_assert_cmpint(status, ==, VREADER_OK);
+ g_assert_cmpint(dwRecvLength, ==, 2);
+ g_assert_cmpint(pbRecvBuffer[0], ==, VCARD7816_SW1_COMMAND_ERROR);
+ g_assert_cmpint(pbRecvBuffer[1], ==, 0x84);
+
+ /* 4B is too much */
+ apdu[4] = 0x04;
+ apdu_len = 9;
+ dwRecvLength = APDUBufSize;
+ status = vreader_xfr_bytes(reader,
+ apdu, apdu_len,
+ pbRecvBuffer, &dwRecvLength);
+ g_assert_cmpint(status, ==, VREADER_OK);
+ g_assert_cmpint(dwRecvLength, ==, 2);
+ g_assert_cmpint(pbRecvBuffer[0], ==, VCARD7816_SW1_COMMAND_ERROR);
+ g_assert_cmpint(pbRecvBuffer[1], ==, 0x84);
+
+ /* The first byte is invalid (nor tag, nor value) */
+ apdu[4] = 0x02;
+ apdu[5] = 0x06;
+ apdu_len = 7;
+ dwRecvLength = APDUBufSize;
+ status = vreader_xfr_bytes(reader,
+ apdu, apdu_len,
+ pbRecvBuffer, &dwRecvLength);
+ g_assert_cmpint(status, ==, VREADER_OK);
+ g_assert_cmpint(dwRecvLength, ==, 2);
+ g_assert_cmpint(pbRecvBuffer[0], ==, VCARD7816_SW1_COMMAND_ERROR);
+ g_assert_cmpint(pbRecvBuffer[1], ==, 0x84);
+
+ /* Read tag: P1 and P2 defines offset -- overunning the buffer should fail */
+ apdu[2] = 0x08;
+ apdu[3] = 0x08; /* <- Large enough */
+ apdu[5] = 0x01;
+ dwRecvLength = APDUBufSize;
+ status = vreader_xfr_bytes(reader,
+ apdu, apdu_len,
+ pbRecvBuffer, &dwRecvLength);
+ g_assert_cmpint(status, ==, VREADER_OK);
+ g_assert_cmpint(dwRecvLength, ==, 2);
+ g_assert_cmpint(pbRecvBuffer[0], ==, VCARD7816_SW1_P1_P2_ERROR);
+ g_assert_cmpint(pbRecvBuffer[1], ==, 0x86);
+
+ /* Read value: P1 and P2 defines offset -- overunning the buffer should fail */
+ apdu[5] = 0x02;
+ dwRecvLength = APDUBufSize;
+ status = vreader_xfr_bytes(reader,
+ apdu, apdu_len,
+ pbRecvBuffer, &dwRecvLength);
+ g_assert_cmpint(status, ==, VREADER_OK);
+ g_assert_cmpint(dwRecvLength, ==, 2);
+ g_assert_cmpint(pbRecvBuffer[0], ==, VCARD7816_SW1_P1_P2_ERROR);
+ g_assert_cmpint(pbRecvBuffer[1], ==, 0x86);
+}
+
+static void test_invalid_read_buffer(void)
+{
+ VReader *reader = vreader_get_reader_by_id(0);
+
+ g_assert_nonnull(reader);
+
+ test_invalid_read_buffer_applet(reader, TEST_CCC);
+ test_invalid_read_buffer_applet(reader, TEST_PKI);
+ test_invalid_read_buffer_applet(reader, TEST_PASSTHROUGH);
+ test_invalid_read_buffer_applet(reader, TEST_EMPTY);
+
vreader_free(reader); /* get by id ref */
}
+
+static void test_invalid_acr(void)
+{
+ VReader *reader = vreader_get_reader_by_id(0);
+ VReaderStatus status;
+ int dwRecvLength = APDUBufSize;
+ uint8_t pbRecvBuffer[APDUBufSize];
+ uint8_t apdu[] = {
+ 0x00, 0x4c, 0x00, 0x00, 0x00, 0x00, 0x00
+ };
+ size_t apdu_len = 5;
+
+ g_assert_nonnull(reader);
+
+ select_applet(reader, TEST_ACA);
+
+ /* P2 needs to be zero */
+ apdu[3] = 0xff;
+ dwRecvLength = APDUBufSize;
+ status = vreader_xfr_bytes(reader,
+ apdu, apdu_len,
+ pbRecvBuffer, &dwRecvLength);
+ g_assert_cmpint(status, ==, VREADER_OK);
+ g_assert_cmpint(dwRecvLength, ==, 2);
+ g_assert_cmpint(pbRecvBuffer[0], ==, VCARD7816_SW1_P1_P2_ERROR);
+ g_assert_cmpint(pbRecvBuffer[1], ==, 0x86);
+ apdu[3] = 0x00;
+
+ /* For P1 = 0x00 we can not send any data */
+ apdu[4] = 0x02;
+ dwRecvLength = APDUBufSize;
+ status = vreader_xfr_bytes(reader,
+ apdu, sizeof(apdu),
+ pbRecvBuffer, &dwRecvLength);
+ g_assert_cmpint(status, ==, VREADER_OK);
+ g_assert_cmpint(dwRecvLength, ==, 2);
+ g_assert_cmpint(pbRecvBuffer[0], ==, VCARD7816_SW1_COMMAND_ERROR);
+ g_assert_cmpint(pbRecvBuffer[1], ==, 0x84);
+
+ /* For P1 = 0x01 we need to send exactly one byte */
+ apdu[2] = 0x01;
+ dwRecvLength = APDUBufSize;
+ status = vreader_xfr_bytes(reader,
+ apdu, sizeof(apdu),
+ pbRecvBuffer, &dwRecvLength);
+ g_assert_cmpint(status, ==, VREADER_OK);
+ g_assert_cmpint(dwRecvLength, ==, 2);
+ g_assert_cmpint(pbRecvBuffer[0], ==, VCARD7816_SW1_COMMAND_ERROR);
+ g_assert_cmpint(pbRecvBuffer[1], ==, 0x84);
+
+ /* For P1 = 0x10 we can not send any data */
+ apdu[2] = 0x10;
+ apdu[4] = 0x02;
+ dwRecvLength = APDUBufSize;
+ status = vreader_xfr_bytes(reader,
+ apdu, sizeof(apdu),
+ pbRecvBuffer, &dwRecvLength);
+ g_assert_cmpint(status, ==, VREADER_OK);
+ g_assert_cmpint(dwRecvLength, ==, 2);
+ g_assert_cmpint(pbRecvBuffer[0], ==, VCARD7816_SW1_COMMAND_ERROR);
+ g_assert_cmpint(pbRecvBuffer[1], ==, 0x84);
+
+ /* For P1 = 0x11 we need to send exactly 7B (2 are not enough) */
+ apdu[2] = 0x11;
+ dwRecvLength = APDUBufSize;
+ status = vreader_xfr_bytes(reader,
+ apdu, sizeof(apdu),
+ pbRecvBuffer, &dwRecvLength);
+ g_assert_cmpint(status, ==, VREADER_OK);
+ g_assert_cmpint(dwRecvLength, ==, 2);
+ g_assert_cmpint(pbRecvBuffer[0], ==, VCARD7816_SW1_COMMAND_ERROR);
+ g_assert_cmpint(pbRecvBuffer[1], ==, 0x84);
+
+ /* For P1 = 0x12 we need to send exactly 2B (1 is not enough) */
+ apdu[2] = 0x12;
+ apdu[4] = 0x01;
+ dwRecvLength = APDUBufSize;
+ status = vreader_xfr_bytes(reader,
+ apdu, 6,
+ pbRecvBuffer, &dwRecvLength);
+ g_assert_cmpint(status, ==, VREADER_OK);
+ g_assert_cmpint(dwRecvLength, ==, 2);
+ g_assert_cmpint(pbRecvBuffer[0], ==, VCARD7816_SW1_COMMAND_ERROR);
+ g_assert_cmpint(pbRecvBuffer[1], ==, 0x84);
+
+ /* For P1 = 0x20 we can not send any data */
+ apdu[2] = 0x20;
+ dwRecvLength = APDUBufSize;
+ status = vreader_xfr_bytes(reader,
+ apdu, 6,
+ pbRecvBuffer, &dwRecvLength);
+ g_assert_cmpint(status, ==, VREADER_OK);
+ g_assert_cmpint(dwRecvLength, ==, 2);
+ g_assert_cmpint(pbRecvBuffer[0], ==, VCARD7816_SW1_COMMAND_ERROR);
+ g_assert_cmpint(pbRecvBuffer[1], ==, 0x84);
+
+ /* For P1 = 0x21 we can not send any data */
+ apdu[2] = 0x21;
+ dwRecvLength = APDUBufSize;
+ status = vreader_xfr_bytes(reader,
+ apdu, 6,
+ pbRecvBuffer, &dwRecvLength);
+ g_assert_cmpint(status, ==, VREADER_OK);
+ g_assert_cmpint(dwRecvLength, ==, 2);
+ g_assert_cmpint(pbRecvBuffer[0], ==, VCARD7816_SW1_COMMAND_ERROR);
+ g_assert_cmpint(pbRecvBuffer[1], ==, 0x84);
+
+
+ vreader_free(reader); /* get by id ref */
+}
+
+static void test_passthrough_applet(void)
+{
+ uint8_t person_coid[2] = {0x02, 0x00};
+
+ VReader *reader = vreader_get_reader_by_id(0);
+
+ /* select the passthrough applet */
+ select_applet(reader, TEST_PASSTHROUGH);
+
+ /* get properties */
+ get_properties_coid(reader, person_coid, TEST_GENERIC);
+
+ /* These objects requires a PIN to read the value buffer */
+ do_login(reader);
+
+ /* get the TAG buffer length */
+ read_buffer(reader, CAC_FILE_TAG, TEST_EMPTY_BUFFER);
+
+ /* get the VALUE buffer length */
+ read_buffer(reader, CAC_FILE_VALUE, TEST_EMPTY_BUFFER);
+
+ /* the buffers are empty without physical card */
+
+ vreader_free(reader); /* get by id ref */
+}
+
+static void libcacard_finalize(void)
+{
+ VReader *reader = vreader_get_reader_by_id(0);
+
+ /* This probably supposed to be a event that terminates the loop */
+ vevent_queue_vevent(vevent_new(VEVENT_LAST, reader, NULL));
+
+ /* join */
+ g_thread_join(thread);
+
+ /* Clean up */
+ vreader_free(reader);
+ vreader_free(reader);
+}
+
int main(int argc, char *argv[])
{
int ret;
@@ -652,19 +1100,25 @@ int main(int argc, char *argv[])
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/get-response", test_get_response);
+ g_test_add_func("/libcacard/check-login-count", check_login_count);
g_test_add_func("/libcacard/login", test_login);
g_test_add_func("/libcacard/sign", test_sign);
g_test_add_func("/libcacard/empty-applets", test_empty_applets);
g_test_add_func("/libcacard/gp-applet", test_gp_applet);
+ g_test_add_func("/libcacard/invalid-properties-apdu", test_invalid_properties);
+ g_test_add_func("/libcacard/invalid-select-apdu", test_invalid_select);
+ g_test_add_func("/libcacard/invalid-instruction", test_invalid_instruction);
+ g_test_add_func("/libcacard/invalid-read-buffer", test_invalid_read_buffer);
+ g_test_add_func("/libcacard/invalid-acr", test_invalid_acr);
+ /* Even without the card, the passthrough applets are present */
+ g_test_add_func("/libcacard/passthrough-applet", test_passthrough_applet);
g_test_add_func("/libcacard/remove", test_remove);
ret = g_test_run();
g_main_loop_unref(loop);
- /* FIXME: no wait to queue a NULL event */
- /* g_thread_join(thread); */
-
+ libcacard_finalize();
return ret;
}
--
2.17.1
More information about the Spice-devel
mailing list