* These are probably not mandatory, but they are present in real card * There are two types od them, one of them presents buffers in properties, but they are empty. The other does not even present the buffers in properties. * They do not have any known purpose, but they are on existing cards * ACF applet has more valid Card Object IDs it answers to on SELECT OID APDU * This requires some internal changes of SELECT OID handling, but currently, we do not have any "useful" data in different OIDs so we just need to keep the protocol. * Actually, the data in ACF (Access Control File) are one of the mandatory parts of CAC, but they are not exposed in PKCS#11 and impossible to emulate (signatures of the internal structures), but ActivClient does not really need them. Signed-off-by: Jakub Jelen <jjelen@xxxxxxxxxx> Reviewed-by: Robert Relyea <rrelyea@xxxxxxxxxx> --- src/cac.c | 376 +++++++++++++++++++++++++++++++++++++++++++++- src/cac.h | 2 + tests/libcacard.c | 156 +++++++++++++------ 3 files changed, 482 insertions(+), 52 deletions(-) diff --git a/src/cac.c b/src/cac.c index 0bc0833..782de1e 100644 --- a/src/cac.c +++ b/src/cac.c @@ -25,6 +25,20 @@ static unsigned char cac_aca_aid[] = { 0xa0, 0x00, 0x00, 0x00, 0x79, 0x03, 0x00 }; static unsigned char cac_ccc_aid[] = { 0xa0, 0x00, 0x00, 0x01, 0x16, 0xDB, 0x00 }; +static unsigned char cac_02fb_aid[] = { + 0xa0, 0x00, 0x00, 0x00, 0x79, 0x02, 0xFB }; +static unsigned char cac_1201_aid[] = { + 0xa0, 0x00, 0x00, 0x00, 0x79, 0x12, 0x01 }; +static unsigned char cac_1202_aid[] = { + 0xa0, 0x00, 0x00, 0x00, 0x79, 0x12, 0x02 }; +static unsigned char cac_02f0_aid[] = { + 0xa0, 0x00, 0x00, 0x00, 0x79, 0x02, 0xF0 }; +static unsigned char cac_02f1_aid[] = { + 0xa0, 0x00, 0x00, 0x00, 0x79, 0x02, 0xF1 }; +static unsigned char cac_02f2_aid[] = { + 0xa0, 0x00, 0x00, 0x00, 0x79, 0x02, 0xF2 }; +static unsigned char cac_access_control_aid[] = { + 0xa0, 0x00, 0x00, 0x01, 0x16, 0x30, 0x00 }; /* private data for PKI applets */ @@ -44,6 +58,10 @@ typedef struct CACACAAppletDataStruct { /* At the moment mostly in cac-aca.c */ } CACACAAppletData; +struct coid { + unsigned char v[2]; +}; + /* * CAC applet private data */ @@ -55,6 +73,12 @@ struct VCardAppletPrivateStruct { int val_buffer_len; struct simpletlv_member *properties; unsigned int properties_len; + /* TODO we should also keep a state, which OID is selected, + * but it does not matter now, because we do not have anything different + * in either buffer + */ + struct coid *coids; + unsigned int coids_len; /* applet-specific */ union { CACPKIAppletData pki_data; @@ -196,9 +220,10 @@ cleanup: static VCardStatus cac_common_process_apdu(VCard *card, VCardAPDU *apdu, VCardResponse **response) { - int ef; VCardAppletPrivate *applet_private; VCardStatus ret = VCARD_FAIL; + int found = 0; + unsigned int i; applet_private = vcard_get_current_applet_private(card, apdu->a_channel); @@ -268,9 +293,15 @@ cac_common_process_apdu(VCard *card, VCardAPDU *apdu, VCardResponse **response) ret = VCARD_DONE; break; } - /* CAC 1.0 only supports ef = 0 */ - ef = apdu->a_body[0] | (apdu->a_body[1] << 8); - if (ef != 0) { + /* CAC 2 Card Object ID needs to match one of the COID defined + * in the applet + */ + for (i = 0; i < applet_private->coids_len; i++) { + if (memcmp(apdu->a_body, applet_private->coids[i].v, 2) == 0) { + found = 1; + } + } + if (!found) { *response = vcard_make_response( VCARD7816_STATUS_ERROR_FILE_NOT_FOUND); ret = VCARD_DONE; @@ -597,6 +628,7 @@ cac_delete_pki_applet_private(VCardAppletPrivate *applet_private) g_free(pki_applet_data->sign_buffer); g_free(applet_private->tag_buffer); g_free(applet_private->val_buffer); + g_free(applet_private->coids); /* this one is cloned so needs to be freed */ simpletlv_free(applet_private->properties, applet_private->properties_len); if (pki_applet_data->key != NULL) { @@ -613,6 +645,7 @@ cac_delete_ccc_applet_private(VCardAppletPrivate *applet_private) } g_free(applet_private->tag_buffer); g_free(applet_private->val_buffer); + g_free(applet_private->coids); g_free(applet_private); } @@ -622,6 +655,21 @@ cac_delete_aca_applet_private(VCardAppletPrivate *applet_private) if (applet_private == NULL) { return; } + g_free(applet_private->coids); + g_free(applet_private); +} + +static void +cac_delete_empty_applet_private(VCardAppletPrivate *applet_private) +{ + if (applet_private == NULL) { + return; + } + g_free(applet_private->coids); + g_free(applet_private->tag_buffer); + g_free(applet_private->val_buffer); + /* this one is cloned so needs to be freed */ + simpletlv_free(applet_private->properties, applet_private->properties_len); g_free(applet_private); } @@ -746,6 +794,11 @@ cac_new_pki_applet_private(int i, const unsigned char *cert, object_id[1] = i; pki_object[0].value.value = object_id; + /* Create Object ID list */ + applet_private->coids = g_malloc(sizeof(struct coid)); + memcpy(applet_private->coids[0].v, object_id, 2); + applet_private->coids_len = 1; + /* Inject T-Buffer and V-Buffer lengths in the properties buffer */ ushort2lebytes(&buffer_properties[1], applet_private->tag_buffer_len); ushort2lebytes(&buffer_properties[3], applet_private->val_buffer_len); @@ -1050,12 +1103,27 @@ failure: * 41 Personnel Category Code * 4D 57 Pay Plan Code * 30 30 Personnel Entitlement Condition Code - * TODO For real cards, we could try to proxy this from original card, - * OpenSC exposes this as a data object as SimpleLTV merged in one buffer + * + * pkcs11-tool --pin 77777777 --read-object --application-label 'Personnel' --type data + * OpenSC exposes this as a data object as SimpleLTV merged in one buffer: + * 19 00 + * 20 00 + * 35 00 + * 24 01 + * 4e + * 25 02 + * 30 31 + * 26 04 + * 57 4f 2d 31 + * 34 01 + * 41 + * 36 02 + * 4d 57 + * d3 02 + * 30 30 + * 00 00 fc bf <<< OpenSC bug (junk in the end instead of last encoded elements) * * - * A0000001166010: Not actually an applet - * A0000001166030: Not actually an applet * * * A0000000791201: Empty @@ -1091,6 +1159,94 @@ failure: * $ opensc-tool -s 00A4040007A0000000791202 -s 8052000002020202 * TAG, VALUE BUFFERS: * empty + * + * A00000007902F0: Empty (no buffers) + * $ opensc-tool -s 00A4040007A00000007902F0 -s 8056010000 + * PROPERTIES: + * 01 05 + * 10 02 06 02 03 + * 40 01 + * 00 + * + * A00000007902F1: Empty (no buffers) + * $ opensc-tool -s 00A4040007A00000007902F1 -s 8056010000 + * PROPERTIES: + * 01 05 + * 10 02 06 02 03 + * 40 01 + * 00 + * + * A00000007902F2: Empty (no buffers) + * $ opensc-tool -s 00A4040007A00000007902F2 -s 8056010000 + * PROPERTIES: + * 01 05 + * 10 02 06 02 03 + * 40 01 + * 00 + * + * + * Access Control File + * A0000001163000 + * PROPERTIES: shared among the OIDs + * 01 05 + * 10 02 06 02 03 + * 40 01 Number of objects + * 04 + * 50 0B TV Buffer + * 41 02 Object ID + * 30 00 + * 42 05 + * 00 <- These are SimpleTLV + * 1A 00 D2 07 + * 50 0B TV Buffer + * 41 02 Object ID + * 60 10 + * 42 05 + * 00 + * 0E 00 BA 0B + * 50 0B TV buffer + * 41 02 Object ID + * 60 30 + * 42 05 + * 00 + * 0A 00 EE 2C + * 50 0B TV Buffer + * 41 02 Object ID + * 90 00 + * 42 05 + * 00 + * 0E 00 4E 04 + * + * OID buffers: + * :3000 + * Tag buffer: + * 0C 00 + * 30 19 SEIWG data + * 34 10 ?? list of 0x30 + * 35 08 ?? 32 30 31 32 30 34 30 31 + * 3E FF 1A 06 ?? + * FE 00 Error detection code + * Value buffer: + * D4 F8 10 DA 08 26 6C 10 A2 04 E5 83 60 DA 01 0C + * 11 CE 66 62 84 38 10 93 E1 <-- SEIWG data + * + * :6010 + * Tag buffer: + * 06 00 + * BC FF CF 04 ?? + * FE 00 Error Detection Code + * + * :6030 + * Tag buffer: + * 06 00 + * BC FF A9 29 ?? + * FE 00 Error Detection Code + * + * :9000 + * 08 00 + * BB FF 38 02 Some PKCS#7 signed block + * BA 30 ??? + * FE 00 Error Detectionc Code */ @@ -1364,6 +1520,11 @@ cac_new_ccc_applet_private(int cert_count) /* Inject Object ID */ tv_object[0].value.value = object_id; + /* Create Object ID list */ + applet_private->coids = g_malloc(sizeof(struct coid)); + memcpy(applet_private->coids[0].v, object_id, 2); + applet_private->coids_len = 1; + /* Inject T-Buffer and V-Buffer lengths in the properties buffer */ ushort2lebytes(&buffer_properties[1], applet_private->tag_buffer_len); ushort2lebytes(&buffer_properties[3], applet_private->val_buffer_len); @@ -1446,6 +1607,12 @@ cac_new_aca_applet_private(int cert_count) if (applet_private == NULL) goto failure; + /* store the applet OID */ + applet_private->coids = g_malloc(sizeof(struct coid)); + applet_private->coids[0].v[0] = 0x03; + applet_private->coids[0].v[1] = 0x00; + applet_private->coids_len = 1; + /* Link the properties */ applet_private->properties = properties; applet_private->properties_len = 1; @@ -1461,6 +1628,107 @@ failure: return NULL; } +static VCardAppletPrivate * +cac_new_empty_applet_private(unsigned char objects[][2], unsigned int objects_len) +{ + VCardAppletPrivate *applet_private = NULL; + + unsigned char object_id[] = "\x00\x00"; + unsigned char buffer_properties[] = "\x00\x00\x00\x00\x00"; + static struct simpletlv_member tv_buffer[] = { + {CAC_PROPERTIES_OBJECT_ID, 2, {/*.value = object_id*/}, + SIMPLETLV_TYPE_LEAF}, + {CAC_PROPERTIES_BUFFER_PROPERTIES, 5, {/*.value = buffer_properties*/}, + SIMPLETLV_TYPE_LEAF}, + }; + unsigned char applet_information[] = "\x10\x02\x06\x02\x03"; + unsigned char number_objects = 0; + static struct simpletlv_member properties[7] = { + {CAC_PROPERTIES_APPLET_INFORMATION, 5, {/*.value = applet_information*/}, + SIMPLETLV_TYPE_LEAF}, + {CAC_PROPERTIES_NUMBER_OBJECTS, 1, {/*.value = number_objects*/}, + SIMPLETLV_TYPE_LEAF}, + {CAC_PROPERTIES_TV_OBJECT, 2, {.child = NULL}, + SIMPLETLV_TYPE_COMPOUND}, + {CAC_PROPERTIES_TV_OBJECT, 2, {.child = NULL}, + SIMPLETLV_TYPE_COMPOUND}, + {CAC_PROPERTIES_TV_OBJECT, 2, {.child = NULL}, + SIMPLETLV_TYPE_COMPOUND}, + {CAC_PROPERTIES_TV_OBJECT, 2, {.child = NULL}, + SIMPLETLV_TYPE_COMPOUND}, + {CAC_PROPERTIES_TV_OBJECT, 2, {.child = NULL}, + SIMPLETLV_TYPE_COMPOUND}, + }; + unsigned properties_len = 2; + unsigned int i; + + for (i = 0; i < objects_len; i++) { + /* Adjust Object ID based on the AID */ + object_id[0] = objects[i][0]; + object_id[1] = objects[i][1]; + + /* Create arbitrary sized buffers */ + buffer_properties[0] = 0x01; // not a SimpleTLV + buffer_properties[1] = 0x60; + buffer_properties[2] = 0x00; + buffer_properties[3] = 0x60; + buffer_properties[4] = 0x00; + + /* Inject Object ID */ + tv_buffer[0].value.value = object_id; + tv_buffer[1].value.value = buffer_properties; + + /* clone the object to the structure */ + properties[2+i].value.child = simpletlv_clone(tv_buffer, 2); + if (properties[2+i].value.child == NULL) + goto failure; + + properties_len++; + number_objects++; + } + + /* Inject Applet Version */ + properties[0].value.value = applet_information; + properties[1].value.value = &number_objects; + + /* Create the private data structure */ + applet_private = g_new0(VCardAppletPrivate, 1); + if (applet_private == NULL) + goto failure; + + /* Create Object ID list */ + applet_private->coids = g_malloc_n(objects_len, sizeof(struct coid)); + memcpy(applet_private->coids, objects, 2*objects_len); + applet_private->coids_len = objects_len; + + /* Clone the properties */ + applet_private->properties_len = properties_len; + applet_private->properties = simpletlv_clone(properties, properties_len); + if (applet_private->properties == NULL) + goto failure; + + /* clean up the allocated properties */ + for (i = 0; i < number_objects; i++) { + simpletlv_free(properties[2+i].value.child, 2); + } + + /* tag/value buffers */ + applet_private->tag_buffer = g_malloc0(2); + applet_private->tag_buffer_len = 2; + applet_private->val_buffer = g_malloc0(2); + applet_private->val_buffer_len = 2; + + return applet_private; + +failure: + for (i = 0; i < number_objects; i++) { + simpletlv_free(properties[2+i].value.child, 3); + } + if (applet_private != NULL) { + cac_delete_aca_applet_private(applet_private); + } + return NULL; +} /* * create a new ACA applet @@ -1530,6 +1798,36 @@ failure: return NULL; } +static VCardApplet * +cac_new_empty_applet(unsigned char *aid, unsigned int aid_len, + unsigned char coids[][2], unsigned int coids_len) +{ + VCardAppletPrivate *applet_private; + VCardApplet *applet; + + applet_private = cac_new_empty_applet_private(coids, coids_len); + if (applet_private == NULL) { + goto failure; + } + + applet = vcard_new_applet(cac_common_process_apdu_read, + NULL, aid, aid_len); + if (applet == NULL) { + goto failure; + } + + vcard_set_applet_private(applet, applet_private, + cac_delete_empty_applet_private); + applet_private = NULL; + + return applet; + +failure: + if (applet_private != NULL) { + cac_delete_empty_applet_private(applet_private); + } + return NULL; +} /* * Initialize the cac card. This is the only public function in this file. All @@ -1545,6 +1843,13 @@ cac_card_init(VReader *reader, VCard *card, { int i; VCardApplet *applet; + unsigned char coids[][2] = {{0x02, 0xfb}}; + unsigned char acf_coids[][2] = { + {0x30, 0x00}, + {0x60, 0x10}, + {0x60, 0x30}, + {0x90, 0x00}, + }; /* CAC Cards are VM Cards */ vcard_set_type(card, VCARD_VM); @@ -1579,6 +1884,61 @@ cac_card_init(VReader *reader, VCard *card, } vcard_add_applet(card, applet); + /* Three more empty applets without buffer */ + /* 02 F0 */ + applet = cac_new_empty_applet(cac_02f0_aid, sizeof(cac_02f0_aid), NULL, 0); + if (applet == NULL) { + goto failure; + } + vcard_add_applet(card, applet); + + /* 02 F1 */ + applet = cac_new_empty_applet(cac_02f1_aid, sizeof(cac_02f1_aid), NULL, 0); + if (applet == NULL) { + goto failure; + } + vcard_add_applet(card, applet); + + /* 02 F2 */ + applet = cac_new_empty_applet(cac_02f2_aid, sizeof(cac_02f2_aid), NULL, 0); + if (applet == NULL) { + goto failure; + } + vcard_add_applet(card, applet); + + /* Empty generic applet (0x02FB) */ + applet = cac_new_empty_applet(cac_02fb_aid, sizeof(cac_02fb_aid), + coids, 1); + if (applet == NULL) { + goto failure; + } + vcard_add_applet(card, applet); + + /* Empty generic applet (0x1201) */ + coids[0][0] = 0x12; + coids[0][1] = 0x01; + applet = cac_new_empty_applet(cac_1201_aid, sizeof(cac_1201_aid), coids, 1); + if (applet == NULL) { + goto failure; + } + vcard_add_applet(card, applet); + + /* Empty generic applet (0x1202) */ + coids[0][1] = 0x02; + applet = cac_new_empty_applet(cac_1202_aid, sizeof(cac_1202_aid), coids, 1); + if (applet == NULL) { + goto failure; + } + vcard_add_applet(card, applet); + + /* Access Control File */ + applet = cac_new_empty_applet(cac_access_control_aid, + sizeof(cac_access_control_aid), acf_coids, 4); + if (applet == NULL) { + goto failure; + } + vcard_add_applet(card, applet); + /* GP applet is created from vcard_emul_type() */ return VCARD_DONE; diff --git a/src/cac.h b/src/cac.h index f21b119..ff8fa0e 100644 --- a/src/cac.h +++ b/src/cac.h @@ -25,6 +25,8 @@ /* PKI applet tags */ #define CAC_PKI_TAG_CERTIFICATE 0x70 #define CAC_PKI_TAG_CERTINFO 0x71 +#define CAC_PKI_TAG_MSCUID 0x72 +#define CAC_PKI_TAG_ERROR_DETECTION_CODE 0xFE /* ACA applet tags */ #define CAC_ACR_NUM_ENTRIES 0xA1 diff --git a/tests/libcacard.c b/tests/libcacard.c index 5323a2c..b1c5604 100644 --- a/tests/libcacard.c +++ b/tests/libcacard.c @@ -12,9 +12,10 @@ static GMutex mutex; static GCond cond; enum { - TEST_PKI, - TEST_CCC, - TEST_ACA + TEST_PKI = 1, + TEST_CCC = 2, + TEST_ACA = 3, + TEST_GENERIC = 4 }; static gpointer @@ -150,7 +151,8 @@ static void test_xfer(void) vreader_free(reader); /* get by id ref */ } -static void get_properties(VReader *reader, int object_type) +static void get_properties_coid(VReader *reader, const unsigned char coid[2], + int object_type) { int dwRecvLength = APDUBufSize; VReaderStatus status; @@ -197,8 +199,8 @@ static void get_properties(VReader *reader, int object_type) g_debug("The generated SimpleTLV can not be parsed"); g_assert_not_reached(); } - g_assert_cmpint(vlen, <=, p_end - p); g_debug("Tag: 0x%02x, Len: %lu", tag, vlen); + g_assert_cmpint(vlen, <=, p_end - p); switch (tag) { case 0x01: /* Applet Information */ @@ -233,20 +235,13 @@ static void get_properties(VReader *reader, int object_type) switch (tag2) { case 0x41: /* Object ID */ - if (object_type == TEST_PKI) { - // XXX only the first PKI for now - g_assert_cmpmem(p2, vlen2, "\x01\x00", 2); - } else if (object_type == TEST_CCC) { - g_assert_cmpmem(p2, vlen2, "\xDB\x00", 2); - } else { - g_debug("Got unknown object type"); - g_assert_not_reached(); - } + g_assert_cmpmem(p2, vlen2, coid, 2); break; case 0x42: /* Buffer properties */ g_assert_cmpint(vlen2, ==, 5); - g_assert_cmpint(p2[0], ==, 0x00); + if (object_type != TEST_GENERIC) + g_assert_cmpint(p2[0], ==, 0x00); break; case 0x43: /* PKI properties */ @@ -284,6 +279,7 @@ static void get_properties(VReader *reader, int object_type) g_assert_cmpint(have_applet_information, ==, 1); + /* Try to list only some properties */ dwRecvLength = APDUBufSize; status = vreader_xfr_bytes(reader, get_properties_tag, sizeof(get_properties_tag), @@ -305,6 +301,35 @@ static void get_properties(VReader *reader, int object_type) g_assert_cmpint(pbRecvBuffer[dwRecvLength-1], ==, 0x00); } +static void get_properties(VReader *reader, int object_type) +{ + unsigned char coid[2]; + switch (object_type) { + case TEST_PKI: + // XXX only the first PKI for now + coid[0] = 0x01; + coid[1] = 0x00; + get_properties_coid(reader, coid, object_type); + break; + + case TEST_CCC: + coid[0] = 0xDB; + coid[1] = 0x00; + get_properties_coid(reader, coid, object_type); + break; + + case TEST_ACA: + coid[0] = 0x03; + coid[1] = 0x00; + get_properties_coid(reader, coid, object_type); + break; + + default: + g_debug("Got unknown object type"); + g_assert_not_reached(); + } +} + static void parse_acr(uint8_t *buf, int buflen) { uint8_t *p, *p_end; @@ -559,10 +584,13 @@ static void read_buffer(VReader *reader, uint8_t type, int object_type) 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); + g_assert_cmphex(pbRecvBuffer[dwRecvLength-2], ==, VCARD7816_SW1_SUCCESS); + g_assert_cmphex(pbRecvBuffer[dwRecvLength-1], ==, 0x00); dwLength = (pbRecvBuffer[0] & 0xff) | ((pbRecvBuffer[1] << 8) & 0xff); + if (dwLength == 0) + return; + data = g_malloc(dwLength); offset = 0x02; do { @@ -617,54 +645,69 @@ static void read_buffer(VReader *reader, uint8_t type, int object_type) g_free(data); } -static void select_aid(VReader *reader, int type) +static void select_aid(VReader *reader, unsigned char *aid, unsigned int aid_len) { VReaderStatus status; int dwRecvLength = APDUBufSize; uint8_t pbRecvBuffer[APDUBufSize]; + uint8_t selfile[] = { + 0x00, 0xa4, 0x04, 0x00, 0x07, 0xa0, 0x00, 0x00, 0x00, 0x79, 0x01, 0x00 + }; + size_t selfile_len = sizeof(selfile); + + g_assert_cmpint(aid_len, ==, 7); + memcpy(&selfile[5], aid, aid_len); + + g_debug("%s: Add applet with AID 0x%02x 0x%02x 0x%02x 0x%02x 0x%02x 0x%02x 0x%02x", + __func__, aid[0], aid[1], aid[2], aid[3], aid[4], aid[5], aid[6]); + g_assert_nonnull(reader); + status = vreader_xfr_bytes(reader, + selfile, selfile_len, + pbRecvBuffer, &dwRecvLength); + g_assert_cmpint(status, ==, VREADER_OK); + g_assert_cmphex(pbRecvBuffer[dwRecvLength-2], ==, VCARD7816_SW1_RESPONSE_BYTES); + g_assert_cmphex(pbRecvBuffer[dwRecvLength-1], >, 0); +} + +static void select_applet(VReader *reader, int type) +{ uint8_t selfile_ccc[] = { /* Select CCC Applet */ - 0x00, 0xa4, 0x04, 0x00, 0x07, 0xa0, 0x00, 0x00, 0x01, 0x16, 0xDB, 0x00 + 0xa0, 0x00, 0x00, 0x01, 0x16, 0xDB, 0x00 }; uint8_t selfile_aca[] = { /* Select ACA Applet */ - 0x00, 0xa4, 0x04, 0x00, 0x07, 0xa0, 0x00, 0x00, 0x00, 0x79, 0x03, 0x00 + 0xa0, 0x00, 0x00, 0x00, 0x79, 0x03, 0x00 }; uint8_t selfile_pki[] = { /* Select first PKI Applet */ - 0x00, 0xa4, 0x04, 0x00, 0x07, 0xa0, 0x00, 0x00, 0x00, 0x79, 0x01, 0x00 + 0xa0, 0x00, 0x00, 0x00, 0x79, 0x01, 0x00 }; - uint8_t *selfile = NULL; - size_t selfile_len = 0; + uint8_t *aid = NULL; + size_t aid_len = 0; switch (type) { case TEST_PKI: - selfile = selfile_pki; - selfile_len = sizeof(selfile_pki); + aid = selfile_pki; + aid_len = sizeof(selfile_pki); break; case TEST_CCC: - selfile = selfile_ccc; - selfile_len = sizeof(selfile_ccc); + aid = selfile_ccc; + aid_len = sizeof(selfile_ccc); break; case TEST_ACA: - selfile = selfile_aca; - selfile_len = sizeof(selfile_aca); + aid = selfile_aca; + aid_len = sizeof(selfile_aca); break; default: g_assert_not_reached(); } - g_assert_nonnull(selfile); + g_assert_nonnull(aid); - g_assert_nonnull(reader); - status = vreader_xfr_bytes(reader, - selfile, selfile_len, - pbRecvBuffer, &dwRecvLength); - g_assert_cmpint(status, ==, VREADER_OK); - g_assert_cmphex(pbRecvBuffer[dwRecvLength-2], ==, VCARD7816_SW1_RESPONSE_BYTES); - g_assert_cmphex(pbRecvBuffer[dwRecvLength-1], >, 0); + select_aid(reader, aid, aid_len); } static void do_login(VReader *reader) @@ -740,7 +783,7 @@ static void test_cac_pki(void) VReader *reader = vreader_get_reader_by_id(0); /* select the first PKI applet */ - select_aid(reader, TEST_PKI); + select_applet(reader, TEST_PKI); /* get properties */ get_properties(reader, TEST_PKI); @@ -759,7 +802,7 @@ static void test_cac_ccc(void) VReader *reader = vreader_get_reader_by_id(0); /* select the CCC */ - select_aid(reader, TEST_CCC); + select_applet(reader, TEST_CCC); /* get properties */ get_properties(reader, TEST_CCC); @@ -778,7 +821,7 @@ static void test_cac_aca(void) VReader *reader = vreader_get_reader_by_id(0); /* select the ACA */ - select_aid(reader, TEST_ACA); + select_applet(reader, TEST_ACA); /* get properties */ get_properties(reader, TEST_ACA); @@ -794,7 +837,7 @@ static void test_login(void) VReader *reader = vreader_get_reader_by_id(0); /* select the ACA */ - select_aid(reader, TEST_ACA); + select_applet(reader, TEST_ACA); do_login(reader); @@ -806,12 +849,12 @@ static void test_sign(void) VReader *reader = vreader_get_reader_by_id(0); /* select the ACA */ - select_aid(reader, TEST_ACA); + select_applet(reader, TEST_ACA); do_login(reader); /* select the PKI */ - select_aid(reader, TEST_PKI); + select_applet(reader, TEST_PKI); do_sign(reader); @@ -854,7 +897,7 @@ static void test_get_response(void) }; /* select CCC */ - select_aid(reader, TEST_CCC); + select_applet(reader, TEST_CCC); /* read buffer without response buffer */ dwRecvLength = 2; @@ -880,6 +923,30 @@ static void test_get_response(void) vreader_free(reader); /* get by id ref */ } +static void test_other_applets(void) +{ + uint8_t applet_02fb[] = { + /*Read Buffer OFFSET TYPE LENGTH */ + 0xA0, 0x00, 0x00, 0x00, 0x79, 0x02, 0xFB + }; + uint8_t coid[2] = {0x02, 0xFB}; + VReader *reader = vreader_get_reader_by_id(0); + + /* select the empty applet A00000007902FB, which should be empty*/ + select_aid(reader, applet_02fb, sizeof(applet_02fb)); + + /* get properties */ + get_properties_coid(reader, coid, TEST_GENERIC); + + /* get the TAG buffer length */ + read_buffer(reader, CAC_FILE_TAG, TEST_GENERIC); + + /* get the VALUE buffer length */ + read_buffer(reader, CAC_FILE_VALUE, TEST_GENERIC); + + vreader_free(reader); /* get by id ref */ +} + static void libcacard_finalize(void) { VReader *reader = vreader_get_reader_by_id(0); @@ -914,6 +981,7 @@ int main(int argc, char *argv[]) g_test_add_func("/libcacard/get-response", test_get_response); g_test_add_func("/libcacard/login", test_login); g_test_add_func("/libcacard/sign", test_sign); + g_test_add_func("/libcacard/other-applets", test_other_applets); g_test_add_func("/libcacard/remove", test_remove); ret = g_test_run(); -- 2.17.1 _______________________________________________ Spice-devel mailing list Spice-devel@xxxxxxxxxxxxxxxxxxxxx https://lists.freedesktop.org/mailman/listinfo/spice-devel