[Spice-devel] [PATCH libcacard v2 03/35] Adjust PKI Applet to CAC 2
Jakub Jelen
jjelen at redhat.com
Thu Aug 2 09:43:35 UTC 2018
* This involves creation of properties structures in the applet,
that are used to discover pki buffers in the applet and its
properties.
* This also removes the old way of accessing certificates using
GET CERTIFICATE APDU also with the test
* This uses the new function vcard_emul_rsa_bits() to expose the
real key size in properties buffer
Signed-off-by: Jakub Jelen <jjelen at redhat.com>
Reviewed-by: Robert Relyea <rrelyea at redhat.com>
---
src/cac.c | 474 ++++++++++++++++++++++++++++++++++++++++------
src/cac.h | 30 ++-
tests/libcacard.c | 26 +--
3 files changed, 439 insertions(+), 91 deletions(-)
diff --git a/src/cac.c b/src/cac.c
index 8adb7f3..06a5d1b 100644
--- a/src/cac.c
+++ b/src/cac.c
@@ -17,13 +17,11 @@
#include "vcard.h"
#include "vcard_emul.h"
#include "card_7816.h"
+#include "simpletlv.h"
+#include "common.h"
/* private data for PKI applets */
typedef struct CACPKIAppletDataStruct {
- unsigned char *cert;
- int cert_len;
- unsigned char *cert_buffer;
- int cert_buffer_len;
unsigned char *sign_buffer;
int sign_buffer_len;
VCardKey *key;
@@ -33,12 +31,146 @@ typedef struct CACPKIAppletDataStruct {
* CAC applet private data
*/
struct VCardAppletPrivateStruct {
+ /* common attributes */
+ unsigned char *tag_buffer;
+ int tag_buffer_len;
+ unsigned char *val_buffer;
+ int val_buffer_len;
+ struct simpletlv_member *properties;
+ unsigned int properties_len;
+ /* applet-specific */
union {
CACPKIAppletData pki_data;
void *reserved;
} u;
};
+/*
+ * Encode SimpleTLV structures to file expected to be returned by the card.
+ * This means, data in SimpleTLV prefixed with 2B encoding the length of
+ * the whole buffer.
+ */
+static int
+cac_create_file(struct simpletlv_member *tlv, size_t tlv_len,
+ unsigned char **out, int type)
+{
+ int len, length;
+ unsigned char *buffer = NULL, *start;
+
+ len = simpletlv_get_length(tlv, tlv_len, type);
+ if (len < 0)
+ goto failure;
+
+ buffer = g_malloc(2 /*2B length*/ + len);
+
+ start = buffer + 2;
+ if (type == SIMPLETLV_TL)
+ length = simpletlv_encode_tl(tlv, tlv_len, &start, len, NULL);
+ else if (type == SIMPLETLV_VALUE)
+ length = simpletlv_encode_val(tlv, tlv_len, &start, len, NULL);
+ else
+ goto failure;
+
+ if (length <= 0)
+ goto failure;
+
+ ushort2lebytes(buffer, length);
+
+ *out = buffer;
+ return len + 2;
+
+failure:
+ *out = NULL;
+ g_free(buffer);
+ return 0;
+}
+
+static inline int
+cac_create_tl_file(struct simpletlv_member *tlv, size_t tlv_len,
+ unsigned char **out)
+{
+ return cac_create_file(tlv, tlv_len, out, SIMPLETLV_TL);
+}
+
+static inline int
+cac_create_val_file(struct simpletlv_member *tlv, size_t tlv_len,
+ unsigned char **out)
+{
+ return cac_create_file(tlv, tlv_len, out, SIMPLETLV_VALUE);
+}
+
+/*
+ * This function returns properties of an applet encoded as SimpleTLV.
+ * If the tags argument is provided, only the tags in the passed list
+ * with respective values are returned.
+ * Otherwise, all the tags are returned.
+ */
+static VCardResponse *
+get_properties(VCard *card,
+ struct simpletlv_member *properties, unsigned int properties_len,
+ unsigned char *tags, unsigned int tags_len,
+ unsigned int a_Le)
+{
+ VCardResponse *r = NULL;
+ struct simpletlv_member *cp = NULL;
+ unsigned int cp_len = 0;
+ unsigned char *properties_buffer = NULL;
+ unsigned int properties_buffer_len = 0;
+
+ if (tags_len > 0 && tags) {
+ unsigned int i, j, k = 0;
+
+ cp = g_malloc_n(tags_len, sizeof(struct simpletlv_member));
+
+ /* show only matching */
+ for (j = 0; j < tags_len; j++) {
+ int match = 0;
+ for (i = 0; i < properties_len; i++) {
+ if (properties[i].tag == tags[j]) {
+ memcpy(&cp[k], &properties[i],
+ sizeof(struct simpletlv_member));
+ match++;
+ k++;
+ break; // XXX do not allow more tags of the same ID
+ }
+ }
+ /* if this tag was not found, return */
+ if (!match) {
+ r = vcard_make_response(VCARD7816_STATUS_ERROR_DATA_NOT_FOUND);
+ goto cleanup;
+ }
+ }
+ cp_len = tags_len;
+ } else {
+ cp = properties;
+ cp_len = properties_len;
+ }
+
+ /* Encode the SimpleTLV structure */
+ properties_buffer_len = simpletlv_encode(cp, cp_len,
+ &properties_buffer, 0, NULL);
+ if (properties_buffer_len <= 0) {
+ g_debug("%s: Failed to encode properties buffer", __func__);
+ goto cleanup;
+ }
+
+ if (a_Le > properties_buffer_len) {
+ r = vcard_response_new_status_bytes(
+ VCARD7816_SW1_LE_ERROR, properties_buffer_len);
+ goto cleanup;
+ }
+ r = vcard_response_new(card, properties_buffer, properties_buffer_len,
+ a_Le, VCARD7816_STATUS_SUCCESS);
+
+cleanup:
+ g_free(properties_buffer);
+ if (tags_len > 0 && tags)
+ g_free(cp);
+ if (r == NULL)
+ r = vcard_make_response(VCARD7816_STATUS_ERROR_GENERAL);
+ return r;
+}
+
/*
* handle all the APDU's that are common to all CAC applets
*/
@@ -46,9 +178,61 @@ static VCardStatus
cac_common_process_apdu(VCard *card, VCardAPDU *apdu, VCardResponse **response)
{
int ef;
+ VCardAppletPrivate *applet_private;
VCardStatus ret = VCARD_FAIL;
+ applet_private = vcard_get_current_applet_private(card, apdu->a_channel);
+
switch (apdu->a_ins) {
+ case CAC_GET_PROPERTIES:
+ /* 5.3.3.4: Get Properties APDU */
+ assert(applet_private);
+
+ if (apdu->a_p2 != 0x00) {
+ /* P2 needs to be 0x00 */
+ *response = vcard_make_response(
+ VCARD7816_STATUS_ERROR_P1_P2_INCORRECT);
+ ret = VCARD_DONE;
+ break;
+ }
+ switch (apdu->a_p1) {
+ case 0x00:
+ /* Get a GSC-IS v2.0 compatible properties response message. */
+ /* If P1 = 0x00 cannot be supported by the smart card, SW1 = 0x6A and SW2 = 86. */
+ *response = vcard_make_response(
+ VCARD7816_STATUS_ERROR_P1_P2_INCORRECT);
+ break;
+ case 0x01:
+ /* Get all the properties. */
+ if (apdu->a_Lc != 0) {
+ *response = vcard_make_response(
+ VCARD7816_STATUS_ERROR_DATA_INVALID);
+ ret = VCARD_DONE;
+ break;
+ }
+ *response = get_properties(card, applet_private->properties,
+ applet_private->properties_len, NULL, 0, apdu->a_Le);
+ break;
+ case 0x02:
+ /* Get the properties of the tags provided in list of tags in
+ * the command data field. */
+ if (apdu->a_Lc == 0) {
+ *response = vcard_make_response(
+ VCARD7816_STATUS_ERROR_DATA_INVALID);
+ ret = VCARD_DONE;
+ break;
+ }
+ *response = get_properties(card, applet_private->properties,
+ applet_private->properties_len, apdu->a_body, apdu->a_Lc, apdu->a_Le);
+ break;
+ default:
+ /* unknown params returns (SW1=0x6A, SW2=0x86) */
+ *response = vcard_make_response(
+ VCARD7816_STATUS_ERROR_P1_P2_INCORRECT);
+ break;
+ }
+ ret = VCARD_DONE;
+ break;
case VCARD7816_INS_SELECT_FILE:
if (apdu->a_p1 != 0x02) {
/* let the 7816 code handle applet switches */
@@ -78,12 +262,6 @@ cac_common_process_apdu(VCard *card, VCardAPDU *apdu, VCardResponse **response)
/* let the 7816 code handle these */
ret = VCARD_NEXT;
break;
- case CAC_GET_PROPERTIES:
- case CAC_GET_ACR:
- /* skip these for now, this will probably be needed */
- *response = vcard_make_response(VCARD7816_STATUS_ERROR_P1_P2_INCORRECT);
- ret = VCARD_DONE;
- break;
default:
*response = vcard_make_response(
VCARD7816_STATUS_ERROR_COMMAND_NOT_SUPPORTED);
@@ -93,6 +271,87 @@ cac_common_process_apdu(VCard *card, VCardAPDU *apdu, VCardResponse **response)
return ret;
}
+/*
+ * Handle READ BUFFER APDU and other common APDUs for CAC applets
+ */
+static VCardStatus
+cac_common_process_apdu_read(VCard *card, VCardAPDU *apdu,
+ VCardResponse **response)
+{
+ VCardAppletPrivate *applet_private;
+ VCardStatus ret = VCARD_FAIL;
+ int size, offset;
+
+ applet_private = vcard_get_current_applet_private(card, apdu->a_channel);
+
+ switch (apdu->a_ins) {
+ case CAC_READ_BUFFER:
+ /* Body contains exactly two bytes */
+ if (!apdu->a_body || apdu->a_Lc != 2) {
+ *response = vcard_make_response(
+ VCARD7816_STATUS_ERROR_DATA_INVALID);
+ ret = VCARD_DONE;
+ break;
+ }
+
+ /* Second byte defines how many bytes should be read */
+ size = apdu->a_body[1];
+
+ /* P1 | P2 defines offset to read from */
+ offset = (apdu->a_p1 << 8) | apdu->a_p2;
+ g_debug("%s: Reqested offset: %d bytes", __func__, offset);
+
+ /* First byte selects TAG+LEN or VALUE buffer */
+ switch (apdu->a_body[0]) {
+ case CAC_FILE_VALUE:
+ size = MIN(size, applet_private->val_buffer_len - offset);
+ if (size < 0) { /* Overrun returns (SW1=0x6A, SW2=0x86) */
+ *response = vcard_make_response(
+ VCARD7816_STATUS_ERROR_P1_P2_INCORRECT);
+ break;
+ }
+ *response = vcard_response_new_bytes(
+ card, applet_private->val_buffer + offset, size,
+ apdu->a_Le, VCARD7816_SW1_SUCCESS, 0);
+ break;
+ case CAC_FILE_TAG:
+ g_debug("%s: Reqested: %d bytes", __func__, size);
+ size = MIN(size, applet_private->tag_buffer_len - offset);
+ if (size < 0) { /* Overrun returns (SW1=0x6A, SW2=0x86) */
+ *response = vcard_make_response(
+ VCARD7816_STATUS_ERROR_P1_P2_INCORRECT);
+ break;
+ }
+ g_debug("%s: Returning: %d bytes (have %d)", __func__, size,
+ applet_private->tag_buffer_len);
+ *response = vcard_response_new_bytes(
+ card, applet_private->tag_buffer + offset, size,
+ apdu->a_Le, VCARD7816_SW1_SUCCESS, 0);
+ break;
+ default:
+ *response = vcard_make_response(
+ VCARD7816_STATUS_ERROR_DATA_INVALID);
+ break;
+ }
+ if (*response == NULL) {
+ *response = vcard_make_response(
+ VCARD7816_STATUS_EXC_ERROR_MEMORY_FAILURE);
+ }
+ ret = VCARD_DONE;
+ break;
+ case CAC_UPDATE_BUFFER:
+ *response = vcard_make_response(
+ VCARD7816_STATUS_ERROR_COMMAND_NOT_SUPPORTED);
+ ret = VCARD_DONE;
+ break;
+ default:
+ ret = cac_common_process_apdu(card, apdu, response);
+ break;
+ }
+ return ret;
+}
+
+
/*
* reset the inter call state between applet selects
*/
@@ -105,10 +364,8 @@ cac_applet_pki_reset(VCard *card, int channel)
assert(applet_private);
pki_applet = &(applet_private->u.pki_data);
- pki_applet->cert_buffer = NULL;
g_free(pki_applet->sign_buffer);
pki_applet->sign_buffer = NULL;
- pki_applet->cert_buffer_len = 0;
pki_applet->sign_buffer_len = 0;
return VCARD_DONE;
}
@@ -119,7 +376,7 @@ cac_applet_pki_process_apdu(VCard *card, VCardAPDU *apdu,
{
CACPKIAppletData *pki_applet;
VCardAppletPrivate *applet_private;
- int size, next;
+ int size;
unsigned char *sign_buffer;
bool retain_sign_buffer = FALSE;
vcard_7816_status_t status;
@@ -135,37 +392,6 @@ cac_applet_pki_process_apdu(VCard *card, VCardAPDU *apdu,
VCARD7816_STATUS_ERROR_CONDITION_NOT_SATISFIED);
ret = VCARD_DONE;
break;
- case CAC_GET_CERTIFICATE:
- if ((apdu->a_p2 != 0) || (apdu->a_p1 != 0)) {
- *response = vcard_make_response(
- VCARD7816_STATUS_ERROR_P1_P2_INCORRECT);
- break;
- }
- assert(pki_applet->cert != NULL);
- size = apdu->a_Le;
- if (pki_applet->cert_buffer == NULL) {
- pki_applet->cert_buffer = pki_applet->cert;
- pki_applet->cert_buffer_len = pki_applet->cert_len;
- }
- size = MIN(size, pki_applet->cert_buffer_len);
- next = MIN(255, pki_applet->cert_buffer_len - size);
- *response = vcard_response_new_bytes(
- card, pki_applet->cert_buffer, size,
- apdu->a_Le, next ?
- VCARD7816_SW1_WARNING_CHANGE :
- VCARD7816_SW1_SUCCESS,
- next);
- pki_applet->cert_buffer += size;
- pki_applet->cert_buffer_len -= size;
- if ((*response == NULL) || (next == 0)) {
- pki_applet->cert_buffer = NULL;
- }
- if (*response == NULL) {
- *response = vcard_make_response(
- VCARD7816_STATUS_EXC_ERROR_MEMORY_FAILURE);
- }
- ret = VCARD_DONE;
- break;
case CAC_SIGN_DECRYPT:
if (apdu->a_p2 != 0) {
*response = vcard_make_response(
@@ -215,21 +441,13 @@ cac_applet_pki_process_apdu(VCard *card, VCardAPDU *apdu,
}
ret = VCARD_DONE;
break;
- case CAC_READ_BUFFER:
- /* new CAC call, go ahead and use the old version for now */
- /* TODO: implement */
- *response = vcard_make_response(
- VCARD7816_STATUS_ERROR_COMMAND_NOT_SUPPORTED);
- ret = VCARD_DONE;
- break;
default:
- ret = cac_common_process_apdu(card, apdu, response);
+ ret = cac_common_process_apdu_read(card, apdu, response);
break;
}
return ret;
}
-
static VCardStatus
cac_applet_id_process_apdu(VCard *card, VCardAPDU *apdu,
VCardResponse **response)
@@ -293,8 +511,11 @@ cac_delete_pki_applet_private(VCardAppletPrivate *applet_private)
return;
}
pki_applet_data = &(applet_private->u.pki_data);
- g_free(pki_applet_data->cert);
g_free(pki_applet_data->sign_buffer);
+ 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);
if (pki_applet_data->key != NULL) {
vcard_emul_delete_key(pki_applet_data->key);
}
@@ -302,25 +523,156 @@ cac_delete_pki_applet_private(VCardAppletPrivate *applet_private)
}
static VCardAppletPrivate *
-cac_new_pki_applet_private(const unsigned char *cert,
+cac_new_pki_applet_private(int i, const unsigned char *cert,
int cert_len, VCardKey *key)
{
CACPKIAppletData *pki_applet_data;
VCardAppletPrivate *applet_private;
+ int bits;
+
+ /* PKI applet Properies ex.:
+ * 01 Tag: Applet Information
+ * 05 Length
+ * 10 Applet family
+ * 02 06 02 03 Applet version
+ * 40 Tag: Number of objects managed by this instance
+ * 01 Length
+ * 01 One
+ * 51 Tag: First PKI object
+ * 11 Length
+ * 41 Tag: ObjectID
+ * 02 Length
+ * 01 01
+ * 42 Buffer properties
+ * 05 Length
+ * 00 Type of tag supported
+ * 1E 00 T-Buffer length (LSB, MSB)
+ * 54 05 V-Buffer length (LSB, MSB)
+ * 43 Tag: PKI properties
+ * 04 Length
+ * 06 Algorithm ID Table 5-6 in GSC-IS 2.1
+ * 10 Key length bytes /8
+ * 01 Private key initialized
+ * 01 Public key initialized
+ */
+ unsigned char object_id[] = "\x01\x00";
+ unsigned char buffer_properties[] = "\x00\x00\x00\x00\x00";
+ unsigned char pki_properties[] = "\x06\x10\x01\x01";
+ static struct simpletlv_member pki_object[3] = {
+ {CAC_PROPERTIES_OBJECT_ID, 2, {/*.value = object_id*/},
+ SIMPLETLV_TYPE_LEAF},
+ {CAC_PROPERTIES_BUFFER_PROPERTIES, 5, {/*.value = buffer_properties*/},
+ SIMPLETLV_TYPE_LEAF},
+ {CAC_PROPERTIES_PKI_PROPERTIES, 4, {/*.value = pki_properties*/},
+ SIMPLETLV_TYPE_LEAF},
+ };
+ unsigned char applet_information[] = "\x10\x02\x06\x02\x03";
+ unsigned char number_objects[] = "\x01";
+ static struct simpletlv_member properties[] = {
+ {CAC_PROPERTIES_APPLET_INFORMATION, 5, {/*.value = applet_information*/},
+ SIMPLETLV_TYPE_LEAF},
+ {CAC_PROPERTIES_NUMBER_OBJECTS, 1, {/*.value = number_objects */},
+ SIMPLETLV_TYPE_LEAF},
+ {CAC_PROPERTIES_PKI_OBJECT, 3, {/*.child = pki_object*/},
+ SIMPLETLV_TYPE_COMPOUND},
+ };
+ size_t properties_len = sizeof(properties)/sizeof(struct simpletlv_member);
+ /* if this would be 1, the certificate would be compressed */
+ unsigned char certinfo[] = "\x00";
+ struct simpletlv_member buffer[] = {
+ {CAC_PKI_TAG_CERTINFO, 1, {/*.value = certinfo*/}, SIMPLETLV_TYPE_LEAF},
+ {CAC_PKI_TAG_CERTIFICATE, cert_len, {/*.value = cert*/}, SIMPLETLV_TYPE_LEAF},
+ };
+ size_t buffer_len = sizeof(buffer)/sizeof(struct simpletlv_member);
applet_private = g_new0(VCardAppletPrivate, 1);
pki_applet_data = &(applet_private->u.pki_data);
- pki_applet_data->cert = (unsigned char *)g_malloc(cert_len+1);
/*
* if we want to support compression, then we simply change the 0 to a 1
- * and compress the cert data with libz
+ * in certinfo and compress the cert data with libz
*/
- pki_applet_data->cert[0] = 0; /* not compressed */
- memcpy(&pki_applet_data->cert[1], cert, cert_len);
- pki_applet_data->cert_len = cert_len+1;
+ /* prepare the buffers to when READ_BUFFER will be called.
+ * Assuming VM card with (LSB first if > 255)
+ * separate Tag+Length, Value buffers as described in 8.4:
+ * 2 B 1 B 1-3 B 1 B 1-3 B
+ * [ T-Len ] [ Tag1 ] [ Len1 ] [ Tag2] [ Len2 ] [...]
+ *
+ * 2 B Len1 B Len2 B
+ * [ V-Len ] [ Value 1 ] [ Value 2 ] [...]
+ * */
+
+ /* Tag+Len buffer */
+ buffer[0].value.value = certinfo;
+ buffer[1].value.value = (unsigned char *)cert;
+ /* Ex:
+ * 0A 00 Length of whole buffer
+ * 71 Tag: CertInfo
+ * 01 Length: 1B
+ * 70 Tag: Certificate
+ * FF B2 03 Length: (\x03 << 8) || \xB2
+ * 72 Tag: MSCUID
+ * 26 Length
+ */
+ applet_private->tag_buffer_len = cac_create_tl_file(buffer, buffer_len,
+ &applet_private->tag_buffer);
+ if (applet_private->tag_buffer_len == 0) {
+ goto failure;
+ }
+ g_debug("%s: applet_private->tag_buffer = %s", __func__,
+ hex_dump(applet_private->tag_buffer, applet_private->tag_buffer_len, NULL, 0));
+
+ /* Value buffer */
+ /* Ex:
+ * DA 03 Length of complete buffer
+ * 01 Value of CertInfo
+ * 78 [..] 6C Cert Value
+ * 7B 63 37 35 62 62 61 64 61 2D 35 32 39 38 2D 31
+ * 37 35 62 2D 39 32 64 63 2D 39 38 35 30 36 62 65
+ * 30 30 30 30 30 7D MSCUID Value
+ */
+ applet_private->val_buffer_len = cac_create_val_file(buffer, buffer_len,
+ &applet_private->val_buffer);
+ if (applet_private->val_buffer_len == 0) {
+ goto failure;
+ }
+ g_debug("%s: applet_private->val_buffer = %s", __func__,
+ hex_dump(applet_private->val_buffer, applet_private->val_buffer_len, NULL, 0));
+
+ /* Inject Object ID */
+ object_id[1] = i;
+ pki_object[0].value.value = object_id;
+
+ /* 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);
+ pki_object[1].value.value = buffer_properties;
+
+ /* PKI properties needs adjustments based on the key sizes */
+ bits = vcard_emul_rsa_bits(key);
+ g_debug("RSA bits = %d", bits);
+ if (bits > 0)
+ pki_properties[1] = 0xff & (bits / 8 / 8);
+ pki_object[2].value.value = pki_properties;
+
+ /* Inject Applet Version */
+ properties[0].value.value = applet_information;
+ properties[1].value.value = number_objects;
+ properties[2].value.child = pki_object;
+
+ /* Clone the properties */
+ applet_private->properties_len = properties_len;
+ applet_private->properties = simpletlv_clone(properties, properties_len);
+ if (applet_private->properties == NULL) {
+ goto failure;
+ }
pki_applet_data->key = key;
return applet_private;
+
+failure:
+ if (applet_private)
+ cac_delete_pki_applet_private(applet_private);
+ return NULL;
}
@@ -338,7 +690,7 @@ cac_new_pki_applet(int i, const unsigned char *cert,
pki_aid[pki_aid_len-1] = i;
- applet_private = cac_new_pki_applet_private(cert, cert_len, key);
+ applet_private = cac_new_pki_applet_private(i, cert, cert_len, key);
if (applet_private == NULL) {
goto failure;
}
diff --git a/src/cac.h b/src/cac.h
index af7f4cd..7c5e9a3 100644
--- a/src/cac.h
+++ b/src/cac.h
@@ -11,12 +11,30 @@
#include "vcard.h"
#include "vreader.h"
-#define CAC_GET_PROPERTIES 0x56
-#define CAC_GET_ACR 0x4c
-#define CAC_READ_BUFFER 0x52
-#define CAC_UPDATE_BUFFER 0x58
-#define CAC_SIGN_DECRYPT 0x42
-#define CAC_GET_CERTIFICATE 0x36
+#define CAC_GET_PROPERTIES 0x56
+#define CAC_GET_ACR 0x4c
+#define CAC_READ_BUFFER 0x52 /* CACv2 */
+#define CAC_UPDATE_BUFFER 0x58
+#define CAC_SIGN_DECRYPT 0x42
+#define CAC_GET_CERTIFICATE 0x36 /* CACv1 */
+
+/* read file TAGs for CACv2 */
+#define CAC_FILE_TAG 0x01
+#define CAC_FILE_VALUE 0x02
+
+/* PKI applet tags */
+#define CAC_PKI_TAG_CERTIFICATE 0x70
+#define CAC_PKI_TAG_CERTINFO 0x71
+
+/* Applet properties tags */
+#define CAC_PROPERTIES_APPLET_INFORMATION 0x01
+#define CAC_PROPERTIES_NUMBER_OBJECTS 0x40
+#define CAC_PROPERTIES_OBJECT_ID 0x41
+#define CAC_PROPERTIES_BUFFER_PROPERTIES 0x42
+#define CAC_PROPERTIES_PKI_PROPERTIES 0x43
+#define CAC_PROPERTIES_TV_OBJECT 0x50
+#define CAC_PROPERTIES_PKI_OBJECT 0x51
+
/*
* Initialize the cac card. This is the only public function in this file. All
diff --git a/tests/libcacard.c b/tests/libcacard.c
index 2b769be..9dfe974 100644
--- a/tests/libcacard.c
+++ b/tests/libcacard.c
@@ -145,7 +145,7 @@ static void test_cac(void)
{
VReader *reader = vreader_get_reader_by_id(0);
VReaderStatus status;
- int dwRecvLength = APDUBufSize, len;
+ int dwRecvLength = APDUBufSize;
uint8_t pbRecvBuffer[APDUBufSize];
uint8_t selfile0[] = {
0x00, 0xa4, 0x04, 0x00, 0x07, 0xa0, 0x00, 0x00, 0x00, 0x79, 0x01, 0x00
@@ -153,9 +153,6 @@ static void test_cac(void)
uint8_t getresp[] = {
0x00, 0xc0, 0x00, 0x00, 0x07
};
- uint8_t getcert[] = {
- 0x00, 0x36, 0x00, 0x00, 0x00
- };
g_assert_nonnull(reader);
status = vreader_xfr_bytes(reader,
@@ -174,26 +171,7 @@ static void test_cac(void)
g_assert_cmphex(pbRecvBuffer[7], ==, VCARD7816_SW1_SUCCESS);
g_assert_cmphex(pbRecvBuffer[8], ==, 0x0);
- len = 0xff;
- do {
- dwRecvLength = APDUBufSize;
- getcert[4] = len;
- status = vreader_xfr_bytes(reader,
- getcert, sizeof(getcert),
- 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);
+ /* The old way of reading certificate does not work anymore */
vreader_free(reader); /* get by id ref */
}
--
2.17.1
More information about the Spice-devel
mailing list