* 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@xxxxxxxxxx> Reviewed-by: Robert Relyea <rrelyea@xxxxxxxxxx> --- 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 _______________________________________________ Spice-devel mailing list Spice-devel@xxxxxxxxxxxxxxxxxxxxx https://lists.freedesktop.org/mailman/listinfo/spice-devel