|
Packit |
cfa437 |
/*
|
|
Packit |
cfa437 |
* implement the ACA applet for the CAC card.
|
|
Packit |
cfa437 |
*
|
|
Packit |
cfa437 |
* Adaptation to GSC-IS 2.1:
|
|
Packit |
cfa437 |
* https://nvlpubs.nist.gov/nistpubs/Legacy/IR/nistir6887e2003.pdf
|
|
Packit |
cfa437 |
*
|
|
Packit |
cfa437 |
* Copyright 2018 Red Hat, Inc.
|
|
Packit |
cfa437 |
*
|
|
Packit |
cfa437 |
* Author: Jakub Jelen <jjelen@redhat.com>
|
|
Packit |
cfa437 |
*
|
|
Packit |
cfa437 |
* This code is licensed under the GNU LGPL, version 2.1 or later.
|
|
Packit |
cfa437 |
* See the COPYING file in the top-level directory.
|
|
Packit |
cfa437 |
*/
|
|
Packit |
cfa437 |
|
|
Packit |
cfa437 |
#include "glib-compat.h"
|
|
Packit |
cfa437 |
#include "card_7816t.h"
|
|
Packit |
cfa437 |
#include "card_7816.h"
|
|
Packit |
cfa437 |
#include "common.h"
|
|
Packit |
cfa437 |
#include "cac-aca.h"
|
|
Packit |
cfa437 |
#include "simpletlv.h"
|
|
Packit |
cfa437 |
|
|
Packit |
cfa437 |
#include <string.h>
|
|
Packit |
cfa437 |
|
|
Packit |
cfa437 |
#define MAX_ACCESS_METHODS 2
|
|
Packit |
cfa437 |
|
|
Packit |
cfa437 |
/* From Table 3-2 */
|
|
Packit |
cfa437 |
enum ACRType {
|
|
Packit |
cfa437 |
ACR_ALWAYS = 0x00,
|
|
Packit |
cfa437 |
ACR_NEVER = 0x01,
|
|
Packit |
cfa437 |
ACR_XAUTH = 0x02,
|
|
Packit |
cfa437 |
ACR_XAUTH_OR_PIN = 0x03,
|
|
Packit |
cfa437 |
ACR_SECURE_CHANNEL_GP = 0x04,
|
|
Packit |
cfa437 |
ACR_ACR_PIN_ALWAYS = 0x05,
|
|
Packit |
cfa437 |
ACR_PIN = 0x06,
|
|
Packit |
cfa437 |
ACR_XAUTH_THEN_PIN = 0x07,
|
|
Packit |
cfa437 |
ACR_UPDATE_ONCE = 0x08,
|
|
Packit |
cfa437 |
ACR_PIN_THEN_XAUTH = 0x09,
|
|
Packit |
cfa437 |
/* RFU = 0x0A,*/
|
|
Packit |
cfa437 |
ACR_SECURE_CHANNEL_ISO = 0x0B,
|
|
Packit |
cfa437 |
ACR_XAUTH_AND_PIN = 0x0C
|
|
Packit |
cfa437 |
};
|
|
Packit |
cfa437 |
|
|
Packit |
cfa437 |
/*
|
|
Packit |
cfa437 |
* ACR table:
|
|
Packit |
cfa437 |
* This table maps the Access Control Rule Type (ACRType) and Access Method
|
|
Packit |
cfa437 |
* information to the Access Control Rule Identifier (ACRID) for each
|
|
Packit |
cfa437 |
* Access Control Rule.
|
|
Packit |
cfa437 |
* (from 5.3.3.5 Get ACR APDU, Table 5-15)
|
|
Packit |
cfa437 |
*/
|
|
Packit |
cfa437 |
struct acr_access_method {
|
|
Packit |
cfa437 |
unsigned char provider_id;
|
|
Packit |
cfa437 |
unsigned char keyIDOrReference;
|
|
Packit |
cfa437 |
};
|
|
Packit |
cfa437 |
struct acr_entry {
|
|
Packit |
cfa437 |
unsigned char acrid;
|
|
Packit |
cfa437 |
unsigned char acrtype;
|
|
Packit |
cfa437 |
/* No idea what does this mean, but it is used in the extended properties */
|
|
Packit |
cfa437 |
unsigned char applet_id;
|
|
Packit |
cfa437 |
unsigned int num_access_methods;
|
|
Packit |
cfa437 |
struct acr_access_method access_methods[MAX_ACCESS_METHODS];
|
|
Packit |
cfa437 |
};
|
|
Packit |
cfa437 |
struct acr_table {
|
|
Packit |
cfa437 |
unsigned int num_entries;
|
|
Packit |
cfa437 |
struct acr_entry entries[];
|
|
Packit |
cfa437 |
};
|
|
Packit |
cfa437 |
|
|
Packit |
cfa437 |
/*
|
|
Packit |
cfa437 |
* Example:
|
|
Packit |
cfa437 |
* 01 05 TL: Applet family + Applet Version
|
|
Packit |
cfa437 |
* 10 02 06 02 02 (1B) (4B)
|
|
Packit |
cfa437 |
* A1 01 TL: Number of ACR entries (unique ACRID)
|
|
Packit |
cfa437 |
* 0B V: 11
|
|
Packit |
cfa437 |
* A0 03 TL: First ACR entry
|
|
Packit |
cfa437 |
* 00 V: ACRID of ACR entry
|
|
Packit |
cfa437 |
* 00 V: ACRType: BSI_ACR_ALWAYS
|
|
Packit |
cfa437 |
* 00 V: Number of AccessMethods in this ACR
|
|
Packit |
cfa437 |
* A0 03
|
|
Packit |
cfa437 |
* 01 V: ACRID of ACR entry
|
|
Packit |
cfa437 |
* 01 V: ACRType: BSI_ACR_NEVER
|
|
Packit |
cfa437 |
* 00 V: Number of AccessMethods in this ACR
|
|
Packit |
cfa437 |
* A0 03
|
|
Packit |
cfa437 |
* 02 V: ACRID of ACR entry
|
|
Packit |
cfa437 |
* 00 V: ACRType: BSI_ACR_ALWAYS
|
|
Packit |
cfa437 |
* 00 V: Number of AccessMethods in this ACR
|
|
Packit |
cfa437 |
* A0 05 TL: Next ACR entry
|
|
Packit |
cfa437 |
* 06 V: ACRID of ACR entry
|
|
Packit |
cfa437 |
* 06 V: ACRType: BSI_ACR_PIN
|
|
Packit |
cfa437 |
* 01 V: Number of AccessMethods in this ACR
|
|
Packit |
cfa437 |
* 1E V: First AccessMethodProviderID -- PIN ???
|
|
Packit |
cfa437 |
* 00 V: First keyIDOrReference -- id 00 ?
|
|
Packit |
cfa437 |
* A0 05
|
|
Packit |
cfa437 |
* 04 V: ACRID of ACR entry
|
|
Packit |
cfa437 |
* 04 V: ACRType: BSI_SECURE_CHANNEL_GP
|
|
Packit |
cfa437 |
* 01 V: Number of AccessMethods in this ACR
|
|
Packit |
cfa437 |
* 1F V: First AccessMethodProviderID -- SC ???
|
|
Packit |
cfa437 |
* 21 V: First keyIDOrReference -- ref 21 ??
|
|
Packit |
cfa437 |
* A0 07
|
|
Packit |
cfa437 |
* 08 V: ACRID of ACR entry
|
|
Packit |
cfa437 |
* 03 V: ACRType: BSI_ACR_XAUTH_OR_PIN
|
|
Packit |
cfa437 |
* 02 V: Number of AccessMethods in this ACR
|
|
Packit |
cfa437 |
* 1D V: First AccessMethodProviderID -- XAUTH ???
|
|
Packit |
cfa437 |
* 01 V: First keyIDOrReference -- ref 01 ??
|
|
Packit |
cfa437 |
* 1E V: Last AccessMethodProviderID -- PIN ???
|
|
Packit |
cfa437 |
* 01 V: Last keyIDOrReference -- id 01 ?
|
|
Packit |
cfa437 |
* A0 05
|
|
Packit |
cfa437 |
* 09 V: ACRID of ACR entry
|
|
Packit |
cfa437 |
* 02 V: ACRType: BSI_ACR_XAUTH
|
|
Packit |
cfa437 |
* 01 V: Number of AccessMethods in this ACR
|
|
Packit |
cfa437 |
* 1D V: First AccessMethodProviderID -- XAUTH ???
|
|
Packit |
cfa437 |
* 02 V: First keyIDOrReference -- ref 02 ??
|
|
Packit |
cfa437 |
* A0 07
|
|
Packit |
cfa437 |
* 0A V: ACRID of ACR entry
|
|
Packit |
cfa437 |
* 03 V: ACRType: BSI_ACR_XAUTH_OR_PIN
|
|
Packit |
cfa437 |
* 02 V: Number of AccessMethods in this ACR
|
|
Packit |
cfa437 |
* 1D V: First AccessMethodProviderID -- XAUTH ???
|
|
Packit |
cfa437 |
* 03 V: First keyIDOrReference -- ref 03 ??
|
|
Packit |
cfa437 |
* 1E V: Last AccessMethodProviderID -- PIN ???
|
|
Packit |
cfa437 |
* 01 V: Last keyIDOrReference -- id 01 ?
|
|
Packit |
cfa437 |
* A0 05
|
|
Packit |
cfa437 |
* 0B V: ACRID of ACR entry
|
|
Packit |
cfa437 |
* 02 V: ACRType: BSI_ACR_XAUTH
|
|
Packit |
cfa437 |
* 01 V: Number of AccessMethods in this ACR
|
|
Packit |
cfa437 |
* 1D V: First AccessMethodProviderID -- XAUTH ???
|
|
Packit |
cfa437 |
* 04 V: First keyIDOrReference -- ref 04 ??
|
|
Packit |
cfa437 |
* A0 03
|
|
Packit |
cfa437 |
* 10 V: ACRID of ACR entry
|
|
Packit |
cfa437 |
* 00 V: ACRType: BSI_ACR_ALWAYS
|
|
Packit |
cfa437 |
* 00 V: Number of AccessMethods in this ACR
|
|
Packit |
cfa437 |
* A0 03
|
|
Packit |
cfa437 |
* 11 V: ACRID of ACR entry
|
|
Packit |
cfa437 |
* 00 V: ACRType: BSI_ACR_ALWAYS
|
|
Packit |
cfa437 |
* 00 V: Number of AccessMethods in this ACR
|
|
Packit |
cfa437 |
*/
|
|
Packit |
cfa437 |
struct acr_table acr_table = {
|
|
Packit |
cfa437 |
11, {
|
|
Packit |
cfa437 |
{0x00, ACR_ALWAYS, 0x00, 0},
|
|
Packit |
cfa437 |
{0x01, ACR_NEVER, 0x00, 0},
|
|
Packit |
cfa437 |
{0x02, ACR_ALWAYS, 0x1F, 0},
|
|
Packit |
cfa437 |
{0x06, ACR_PIN, 0x00, 1, {
|
|
Packit |
cfa437 |
{0x1E, 0x00}
|
|
Packit |
cfa437 |
}},
|
|
Packit |
cfa437 |
{0x04, ACR_SECURE_CHANNEL_GP, 0x1F, 1, {
|
|
Packit |
cfa437 |
{0x1F, 0x21}
|
|
Packit |
cfa437 |
}},
|
|
Packit |
cfa437 |
{0x08, ACR_XAUTH_OR_PIN, 0x00, 2, {
|
|
Packit |
cfa437 |
{0x1D, 0x01},
|
|
Packit |
cfa437 |
{0x1E, 0x01}
|
|
Packit |
cfa437 |
}},
|
|
Packit |
cfa437 |
{0x09, ACR_XAUTH, 0x00, 1, {
|
|
Packit |
cfa437 |
{0x1D, 0x01}
|
|
Packit |
cfa437 |
}},
|
|
Packit |
cfa437 |
{0x0A, ACR_XAUTH_OR_PIN, 0x00, 2, {
|
|
Packit |
cfa437 |
{0x1D, 0x03},
|
|
Packit |
cfa437 |
{0x1E, 0x01}
|
|
Packit |
cfa437 |
}},
|
|
Packit |
cfa437 |
{0x0B, ACR_XAUTH, 0x00, 1, {
|
|
Packit |
cfa437 |
{0x1D, 0x0}
|
|
Packit |
cfa437 |
}},
|
|
Packit |
cfa437 |
{0x10, ACR_ALWAYS, 0x1E, 0},
|
|
Packit |
cfa437 |
{0x11, ACR_ALWAYS, 0x1D, 0},
|
|
Packit |
cfa437 |
}
|
|
Packit |
cfa437 |
};
|
|
Packit |
cfa437 |
|
|
Packit |
cfa437 |
static struct simpletlv_member *
|
|
Packit |
cfa437 |
cac_aca_get_acr(size_t *acr_len, unsigned char *acrid)
|
|
Packit |
cfa437 |
{
|
|
Packit |
cfa437 |
struct simpletlv_member *r;
|
|
Packit |
cfa437 |
size_t i;
|
|
Packit |
cfa437 |
int j = 0;
|
|
Packit |
cfa437 |
|
|
Packit |
cfa437 |
g_assert_nonnull(acr_len);
|
|
Packit |
cfa437 |
|
|
Packit |
cfa437 |
if (acrid != NULL) {
|
|
Packit |
cfa437 |
r = g_malloc(sizeof(struct simpletlv_member));
|
|
Packit |
cfa437 |
} else {
|
|
Packit |
cfa437 |
r = g_malloc_n(acr_table.num_entries + 1, sizeof(struct simpletlv_member));
|
|
Packit |
cfa437 |
|
|
Packit |
cfa437 |
r[j].tag = CAC_ACR_NUM_ENTRIES;
|
|
Packit |
cfa437 |
r[j].length = 1;
|
|
Packit |
cfa437 |
r[j].value.value = (unsigned char *) &acr_table.num_entries;
|
|
Packit |
cfa437 |
r[j].type = SIMPLETLV_TYPE_LEAF;
|
|
Packit |
cfa437 |
j++;
|
|
Packit |
cfa437 |
}
|
|
Packit |
cfa437 |
for (i = 0; i < acr_table.num_entries; i++) {
|
|
Packit |
cfa437 |
if (acrid != NULL && *acrid != acr_table.entries[i].acrid)
|
|
Packit |
cfa437 |
continue;
|
|
Packit |
cfa437 |
|
|
Packit |
cfa437 |
r[j].tag = CAC_ACR_ENTRY;
|
|
Packit |
cfa437 |
r[j].length = 2*acr_table.entries[i].num_access_methods+3;
|
|
Packit |
cfa437 |
r[j].value.value = (unsigned char *) &acr_table.entries[i];
|
|
Packit |
cfa437 |
r[j].type = SIMPLETLV_TYPE_LEAF;
|
|
Packit |
cfa437 |
j++;
|
|
Packit |
cfa437 |
}
|
|
Packit |
cfa437 |
if (j <= 0) {
|
|
Packit |
cfa437 |
/* we did not find the requested ACRID */
|
|
Packit |
cfa437 |
g_free(r);
|
|
Packit |
cfa437 |
r = NULL;
|
|
Packit |
cfa437 |
}
|
|
Packit |
cfa437 |
*acr_len = j;
|
|
Packit |
cfa437 |
return r;
|
|
Packit |
cfa437 |
}
|
|
Packit |
cfa437 |
|
|
Packit |
cfa437 |
/*
|
|
Packit |
cfa437 |
* Service Applet Table:
|
|
Packit |
cfa437 |
* This table maps the Service Applet ID to the full AID for each
|
|
Packit |
cfa437 |
* Service Applet.
|
|
Packit |
cfa437 |
* (from 5.3.3.5 Get ACR APDU, Table 5-21)
|
|
Packit |
cfa437 |
*/
|
|
Packit |
cfa437 |
|
|
Packit |
cfa437 |
#define MAX_AID_LEN 7
|
|
Packit |
cfa437 |
|
|
Packit |
cfa437 |
struct applet_entry {
|
|
Packit |
cfa437 |
unsigned char applet_id;
|
|
Packit |
cfa437 |
unsigned int applet_aid_len;
|
|
Packit |
cfa437 |
unsigned char applet_aid[MAX_AID_LEN];
|
|
Packit |
cfa437 |
};
|
|
Packit |
cfa437 |
struct service_applet_table {
|
|
Packit |
cfa437 |
unsigned num_entries;
|
|
Packit |
cfa437 |
unsigned num_static_entries;
|
|
Packit |
cfa437 |
struct applet_entry entries[];
|
|
Packit |
cfa437 |
};
|
|
Packit |
cfa437 |
|
|
Packit |
cfa437 |
/* Example:
|
|
Packit |
cfa437 |
* 01 05 TL: Applet Information
|
|
Packit |
cfa437 |
* 10 02 06 02 02
|
|
Packit |
cfa437 |
* 94 01 TL: Number of Applet Entries
|
|
Packit |
cfa437 |
* 0F
|
|
Packit |
cfa437 |
* 93 0A TL: Applet entry
|
|
Packit |
cfa437 |
* 40 Applet ID
|
|
Packit |
cfa437 |
* 92 07 TL: Applet AID
|
|
Packit |
cfa437 |
* A0 00 00 01 16 30 00
|
|
Packit |
cfa437 |
* 93 0A
|
|
Packit |
cfa437 |
* 4F
|
|
Packit |
cfa437 |
* 92 07
|
|
Packit |
cfa437 |
* A0 00 00 01 16 DB 00
|
|
Packit |
cfa437 |
* 93 0A
|
|
Packit |
cfa437 |
* 4B
|
|
Packit |
cfa437 |
* 92 07
|
|
Packit |
cfa437 |
* A0 00 00 00 79 02 FB
|
|
Packit |
cfa437 |
* 93 0A
|
|
Packit |
cfa437 |
* 41
|
|
Packit |
cfa437 |
* 92 07
|
|
Packit |
cfa437 |
* A0 00 00 00 79 02 00
|
|
Packit |
cfa437 |
* 93 0A
|
|
Packit |
cfa437 |
* 42
|
|
Packit |
cfa437 |
* 92 07
|
|
Packit |
cfa437 |
* A0 00 00 00 79 02 01
|
|
Packit |
cfa437 |
* 93 0A
|
|
Packit |
cfa437 |
* 4E
|
|
Packit |
cfa437 |
* 92 07
|
|
Packit |
cfa437 |
* A0 00 00 00 79 02 FE
|
|
Packit |
cfa437 |
* 93 0A
|
|
Packit |
cfa437 |
* 4D
|
|
Packit |
cfa437 |
* 92 07
|
|
Packit |
cfa437 |
* A0 00 00 00 79 02 FD
|
|
Packit |
cfa437 |
* 93 0A
|
|
Packit |
cfa437 |
* 50
|
|
Packit |
cfa437 |
* 92 07
|
|
Packit |
cfa437 |
* A0 00 00 00 79 02 F2
|
|
Packit |
cfa437 |
* 93 0A
|
|
Packit |
cfa437 |
* 63
|
|
Packit |
cfa437 |
* 92 07
|
|
Packit |
cfa437 |
* A0 00 00 00 79 01 02
|
|
Packit |
cfa437 |
* 93 0A
|
|
Packit |
cfa437 |
* 51
|
|
Packit |
cfa437 |
* 92 07
|
|
Packit |
cfa437 |
* A0 00 00 00 79 02 F0
|
|
Packit |
cfa437 |
* 93 0A
|
|
Packit |
cfa437 |
* 61
|
|
Packit |
cfa437 |
* 92 07
|
|
Packit |
cfa437 |
* A0 00 00 00 79 01 00
|
|
Packit |
cfa437 |
* 93 0A
|
|
Packit |
cfa437 |
* 52
|
|
Packit |
cfa437 |
* 92 07
|
|
Packit |
cfa437 |
* A0 00 00 00 79 02 F1
|
|
Packit |
cfa437 |
* 93 0A
|
|
Packit |
cfa437 |
* 62
|
|
Packit |
cfa437 |
* 92 07
|
|
Packit |
cfa437 |
* A0 00 00 00 79 01 01
|
|
Packit |
cfa437 |
* 93 0A
|
|
Packit |
cfa437 |
* 44
|
|
Packit |
cfa437 |
* 92 07
|
|
Packit |
cfa437 |
* A0 00 00 00 79 12 01
|
|
Packit |
cfa437 |
* 93 0A
|
|
Packit |
cfa437 |
* 45
|
|
Packit |
cfa437 |
* 92 07
|
|
Packit |
cfa437 |
* A0 00 00 00 79 12 02
|
|
Packit |
cfa437 |
*/
|
|
Packit |
cfa437 |
|
|
Packit |
cfa437 |
struct service_applet_table service_table = {
|
|
Packit |
cfa437 |
22, 12, {
|
|
Packit |
cfa437 |
/* Variable PKI applets entries */
|
|
Packit |
cfa437 |
{0x61, 7, "\xA0\x00\x00\x00\x79\x01\x00"},
|
|
Packit |
cfa437 |
{0x62, 7, "\xA0\x00\x00\x00\x79\x01\x01"},
|
|
Packit |
cfa437 |
{0x63, 7, "\xA0\x00\x00\x00\x79\x01\x02"},
|
|
Packit |
cfa437 |
{0x64, 7, "\xA0\x00\x00\x00\x79\x01\x03"},
|
|
Packit |
cfa437 |
{0x65, 7, "\xA0\x00\x00\x00\x79\x01\x04"},
|
|
Packit |
cfa437 |
{0x66, 7, "\xA0\x00\x00\x00\x79\x01\x05"},
|
|
Packit |
cfa437 |
{0x67, 7, "\xA0\x00\x00\x00\x79\x01\x06"},
|
|
Packit |
cfa437 |
{0x68, 7, "\xA0\x00\x00\x00\x79\x01\x07"},
|
|
Packit |
cfa437 |
{0x69, 7, "\xA0\x00\x00\x00\x79\x01\x08"},
|
|
Packit |
cfa437 |
{0x6a, 7, "\xA0\x00\x00\x00\x79\x01\x09"},
|
|
Packit |
cfa437 |
/* static applet entries */
|
|
Packit |
cfa437 |
{0x40, 7, "\xA0\x00\x00\x01\x16\x30\x00"},
|
|
Packit |
cfa437 |
{0x4F, 7, "\xA0\x00\x00\x01\x16\xDB\x00"},
|
|
Packit |
cfa437 |
{0x4B, 7, "\xA0\x00\x00\x00\x79\x02\xFB"},
|
|
Packit |
cfa437 |
{0x41, 7, "\xA0\x00\x00\x00\x79\x02\x00"},
|
|
Packit |
cfa437 |
{0x42, 7, "\xA0\x00\x00\x00\x79\x02\x01"},
|
|
Packit |
cfa437 |
{0x4E, 7, "\xA0\x00\x00\x00\x79\x02\xFE"},
|
|
Packit |
cfa437 |
{0x4D, 7, "\xA0\x00\x00\x00\x79\x02\xFD"},
|
|
Packit |
cfa437 |
{0x50, 7, "\xA0\x00\x00\x00\x79\x02\xF2"},
|
|
Packit |
cfa437 |
{0x51, 7, "\xA0\x00\x00\x00\x79\x02\xF0"},
|
|
Packit |
cfa437 |
{0x52, 7, "\xA0\x00\x00\x00\x79\x02\xF1"},
|
|
Packit |
cfa437 |
{0x44, 7, "\xA0\x00\x00\x00\x79\x12\x01"},
|
|
Packit |
cfa437 |
{0x45, 7, "\xA0\x00\x00\x00\x79\x12\x02"},
|
|
Packit |
cfa437 |
}
|
|
Packit |
cfa437 |
};
|
|
Packit |
cfa437 |
|
|
Packit |
cfa437 |
static struct simpletlv_member *
|
|
Packit |
cfa437 |
cac_aca_get_service_table(size_t *r_len, unsigned int pki_applets)
|
|
Packit |
cfa437 |
{
|
|
Packit |
cfa437 |
struct simpletlv_member *r = NULL;
|
|
Packit |
cfa437 |
unsigned char *num_entries_byte = NULL;
|
|
Packit |
cfa437 |
unsigned char *entry = NULL;
|
|
Packit |
cfa437 |
size_t i, j = 0;
|
|
Packit |
cfa437 |
unsigned int num_entries;
|
|
Packit |
cfa437 |
|
|
Packit |
cfa437 |
g_assert_nonnull(r_len);
|
|
Packit |
cfa437 |
|
|
Packit |
cfa437 |
num_entries = service_table.num_static_entries + pki_applets;
|
|
Packit |
cfa437 |
r = g_malloc_n(num_entries + 1, sizeof(struct simpletlv_member));
|
|
Packit |
cfa437 |
|
|
Packit |
cfa437 |
num_entries_byte = g_malloc(1);
|
|
Packit |
cfa437 |
*num_entries_byte = num_entries;
|
|
Packit |
cfa437 |
|
|
Packit |
cfa437 |
r[0].type = SIMPLETLV_TYPE_LEAF;
|
|
Packit |
cfa437 |
r[0].tag = CAC_ACR_SERVICE_NUM_ENTRIES;
|
|
Packit |
cfa437 |
r[0].length = 1;
|
|
Packit |
cfa437 |
r[0].value.value = num_entries_byte;
|
|
Packit |
cfa437 |
j = 1;
|
|
Packit |
cfa437 |
for (i = 0; i < service_table.num_entries; i++) {
|
|
Packit |
cfa437 |
/* Skip unused PKI applets */
|
|
Packit |
cfa437 |
if (i >= pki_applets && i < 10)
|
|
Packit |
cfa437 |
continue;
|
|
Packit |
cfa437 |
|
|
Packit |
cfa437 |
r[j].type = SIMPLETLV_TYPE_LEAF;
|
|
Packit |
cfa437 |
r[j].tag = CAC_ACR_SERVICE_ENTRY;
|
|
Packit |
cfa437 |
r[j].length = service_table.entries[i].applet_aid_len + 3;
|
|
Packit |
cfa437 |
entry = g_malloc(r[j].length);
|
|
Packit |
cfa437 |
entry[0] = service_table.entries[i].applet_id;
|
|
Packit |
cfa437 |
entry[1] = CAC_ACR_AID;
|
|
Packit |
cfa437 |
entry[2] = service_table.entries[i].applet_aid_len;
|
|
Packit |
cfa437 |
memcpy(&entry[3], (unsigned char *) &service_table.entries[i],
|
|
Packit |
cfa437 |
service_table.entries[i].applet_aid_len);
|
|
Packit |
cfa437 |
r[j].value.value = entry;
|
|
Packit |
cfa437 |
j++;
|
|
Packit |
cfa437 |
}
|
|
Packit |
cfa437 |
g_assert_cmpint(j, ==, num_entries + 1);
|
|
Packit |
cfa437 |
|
|
Packit |
cfa437 |
*r_len = j;
|
|
Packit |
cfa437 |
return r;
|
|
Packit |
cfa437 |
}
|
|
Packit |
cfa437 |
|
|
Packit |
cfa437 |
/*
|
|
Packit |
cfa437 |
* Object/Applet ACR Table:
|
|
Packit |
cfa437 |
* This table maps the service (INS code/P1 byte/P2 byte/1 st data byte)
|
|
Packit |
cfa437 |
* to the ACRID for each container.
|
|
Packit |
cfa437 |
* (from 5.3.3.5 Get ACR APDU, Table 5-16)
|
|
Packit |
cfa437 |
*
|
|
Packit |
cfa437 |
* Can be pulled from existing card using the OpenSC:
|
|
Packit |
cfa437 |
* $ opensc-tool -s 00A4040007A0000000790300 -s 804C100000
|
|
Packit |
cfa437 |
*/
|
|
Packit |
cfa437 |
|
|
Packit |
cfa437 |
enum {
|
|
Packit |
cfa437 |
ACR_INS_CONFIG_NONE = 0x00,
|
|
Packit |
cfa437 |
ACR_INS_CONFIG_P1 = 0x01,
|
|
Packit |
cfa437 |
ACR_INS_CONFIG_P2 = 0x02,
|
|
Packit |
cfa437 |
ACR_INS_CONFIG_DATA1 = 0x04,
|
|
Packit |
cfa437 |
};
|
|
Packit |
cfa437 |
|
|
Packit |
cfa437 |
#define ACR_MAX_INSTRUCTIONS 5
|
|
Packit |
cfa437 |
#define ACR_MAX_APPLET_OBJECTS 5
|
|
Packit |
cfa437 |
|
|
Packit |
cfa437 |
struct cac_ins {
|
|
Packit |
cfa437 |
unsigned char code;
|
|
Packit |
cfa437 |
unsigned char acrid;
|
|
Packit |
cfa437 |
unsigned char config;
|
|
Packit |
cfa437 |
unsigned char p1;
|
|
Packit |
cfa437 |
unsigned char p2;
|
|
Packit |
cfa437 |
unsigned char data1;
|
|
Packit |
cfa437 |
};
|
|
Packit |
cfa437 |
struct acr_object {
|
|
Packit |
cfa437 |
unsigned char id[2];
|
|
Packit |
cfa437 |
unsigned int num_ins;
|
|
Packit |
cfa437 |
struct cac_ins ins[ACR_MAX_INSTRUCTIONS];
|
|
Packit |
cfa437 |
};
|
|
Packit |
cfa437 |
struct acr_applet {
|
|
Packit |
cfa437 |
unsigned char id;
|
|
Packit |
cfa437 |
unsigned int num_objects;
|
|
Packit |
cfa437 |
struct acr_object objects[ACR_MAX_APPLET_OBJECTS];
|
|
Packit |
cfa437 |
};
|
|
Packit |
cfa437 |
struct acr_applets {
|
|
Packit |
cfa437 |
unsigned int num_applets;
|
|
Packit |
cfa437 |
unsigned int num_static_applets;
|
|
Packit |
cfa437 |
struct acr_applet applets[];
|
|
Packit |
cfa437 |
};
|
|
Packit |
cfa437 |
|
|
Packit |
cfa437 |
/* Example:
|
|
Packit |
cfa437 |
* 01 05 TL: Applet Information
|
|
Packit |
cfa437 |
* 10 02 06 02 02
|
|
Packit |
cfa437 |
* 81 01 TL: Number of applets managed by this ACA
|
|
Packit |
cfa437 |
* 10
|
|
Packit |
cfa437 |
* 80 09 TL: Card Applet ACR
|
|
Packit |
cfa437 |
* 1F Applet ID
|
|
Packit |
cfa437 |
* 01 Number of objects managed by this applet
|
|
Packit |
cfa437 |
* 82 05 TL: Card Object ACR
|
|
Packit |
cfa437 |
* FF FF Card Object ID
|
|
Packit |
cfa437 |
* 20 INS1 code
|
|
Packit |
cfa437 |
* 00 INS1 configuration definition
|
|
Packit |
cfa437 |
* 00 ACRID
|
|
Packit |
cfa437 |
* 80 1A TL: Card Applet ACR
|
|
Packit |
cfa437 |
* 4F Applet ID
|
|
Packit |
cfa437 |
* 02 Number of objects managed by this applet
|
|
Packit |
cfa437 |
* 82 08 TL: Card Object ACR
|
|
Packit |
cfa437 |
* DB 00 Card Object ID: CCC
|
|
Packit |
cfa437 |
* 58 INS1: Update Buffer
|
|
Packit |
cfa437 |
* 00 config: none
|
|
Packit |
cfa437 |
* 04 ACRID: (ID from ACR Table)
|
|
Packit |
cfa437 |
* 52 INS2: Read Buffer
|
|
Packit |
cfa437 |
* 00 config: none
|
|
Packit |
cfa437 |
* 00 ACRID: (ID from ACR Table)
|
|
Packit |
cfa437 |
* 82 0C TL: Card Object ACR
|
|
Packit |
cfa437 |
* FF FF Card Object ID
|
|
Packit |
cfa437 |
* 82 INS1 code
|
|
Packit |
cfa437 |
* 01 config
|
|
Packit |
cfa437 |
* 00 P1 Value
|
|
Packit |
cfa437 |
* 11 ACRID
|
|
Packit |
cfa437 |
* 84 INS2 code
|
|
Packit |
cfa437 |
* 00 INS2 config
|
|
Packit |
cfa437 |
* 11 ACRID
|
|
Packit |
cfa437 |
* 20 INS3 code
|
|
Packit |
cfa437 |
* 00 INS3 config
|
|
Packit |
cfa437 |
* 10 ACRID
|
|
Packit |
cfa437 |
* [...]
|
|
Packit |
cfa437 |
*/
|
|
Packit |
cfa437 |
|
|
Packit |
cfa437 |
struct acr_applets applets_table = {
|
|
Packit |
cfa437 |
23, 13, {
|
|
Packit |
cfa437 |
/* Dynamic PKI applets */
|
|
Packit |
cfa437 |
{0x61, 2, {
|
|
Packit |
cfa437 |
{"\x01\x00", 3, {
|
|
Packit |
cfa437 |
{CAC_UPDATE_BUFFER, 0x04, ACR_INS_CONFIG_NONE},
|
|
Packit |
cfa437 |
{CAC_READ_BUFFER, 0x00, ACR_INS_CONFIG_NONE},
|
|
Packit |
cfa437 |
{CAC_SIGN_DECRYPT, 0x06, ACR_INS_CONFIG_NONE}
|
|
Packit |
cfa437 |
}},
|
|
Packit |
cfa437 |
{"\xFF\xFF", 1, {
|
|
Packit |
cfa437 |
{VCARD7816_INS_VERIFY, 0x10, ACR_INS_CONFIG_NONE},
|
|
Packit |
cfa437 |
}}
|
|
Packit |
cfa437 |
}},
|
|
Packit |
cfa437 |
{0x62, 2, {
|
|
Packit |
cfa437 |
{"\x01\x01", 3, {
|
|
Packit |
cfa437 |
{CAC_UPDATE_BUFFER, 0x04, ACR_INS_CONFIG_NONE},
|
|
Packit |
cfa437 |
{CAC_READ_BUFFER, 0x00, ACR_INS_CONFIG_NONE},
|
|
Packit |
cfa437 |
{CAC_SIGN_DECRYPT, 0x06, ACR_INS_CONFIG_NONE}
|
|
Packit |
cfa437 |
}},
|
|
Packit |
cfa437 |
{"\xFF\xFF", 1, {
|
|
Packit |
cfa437 |
{VCARD7816_INS_VERIFY, 0x10, ACR_INS_CONFIG_NONE},
|
|
Packit |
cfa437 |
}}
|
|
Packit |
cfa437 |
}},
|
|
Packit |
cfa437 |
{0x63, 2, {
|
|
Packit |
cfa437 |
{"\x01\x02", 3, {
|
|
Packit |
cfa437 |
{CAC_UPDATE_BUFFER, 0x04, ACR_INS_CONFIG_NONE},
|
|
Packit |
cfa437 |
{CAC_READ_BUFFER, 0x00, ACR_INS_CONFIG_NONE},
|
|
Packit |
cfa437 |
{CAC_SIGN_DECRYPT, 0x06, ACR_INS_CONFIG_NONE}
|
|
Packit |
cfa437 |
}},
|
|
Packit |
cfa437 |
{"\xFF\xFF", 1, {
|
|
Packit |
cfa437 |
{VCARD7816_INS_VERIFY, 0x10, ACR_INS_CONFIG_NONE},
|
|
Packit |
cfa437 |
}}
|
|
Packit |
cfa437 |
}},
|
|
Packit |
cfa437 |
{0x64, 2, {
|
|
Packit |
cfa437 |
{"\x01\x03", 3, {
|
|
Packit |
cfa437 |
{CAC_UPDATE_BUFFER, 0x04, ACR_INS_CONFIG_NONE},
|
|
Packit |
cfa437 |
{CAC_READ_BUFFER, 0x00, ACR_INS_CONFIG_NONE},
|
|
Packit |
cfa437 |
{CAC_SIGN_DECRYPT, 0x06, ACR_INS_CONFIG_NONE}
|
|
Packit |
cfa437 |
}},
|
|
Packit |
cfa437 |
{"\xFF\xFF", 1, {
|
|
Packit |
cfa437 |
{VCARD7816_INS_VERIFY, 0x10, ACR_INS_CONFIG_NONE},
|
|
Packit |
cfa437 |
}}
|
|
Packit |
cfa437 |
}},
|
|
Packit |
cfa437 |
{0x65, 2, {
|
|
Packit |
cfa437 |
{"\x01\x04", 3, {
|
|
Packit |
cfa437 |
{CAC_UPDATE_BUFFER, 0x04, ACR_INS_CONFIG_NONE},
|
|
Packit |
cfa437 |
{CAC_READ_BUFFER, 0x00, ACR_INS_CONFIG_NONE},
|
|
Packit |
cfa437 |
{CAC_SIGN_DECRYPT, 0x06, ACR_INS_CONFIG_NONE}
|
|
Packit |
cfa437 |
}},
|
|
Packit |
cfa437 |
{"\xFF\xFF", 1, {
|
|
Packit |
cfa437 |
{VCARD7816_INS_VERIFY, 0x10, ACR_INS_CONFIG_NONE},
|
|
Packit |
cfa437 |
}}
|
|
Packit |
cfa437 |
}},
|
|
Packit |
cfa437 |
{0x66, 2, {
|
|
Packit |
cfa437 |
{"\x01\x05", 3, {
|
|
Packit |
cfa437 |
{CAC_UPDATE_BUFFER, 0x04, ACR_INS_CONFIG_NONE},
|
|
Packit |
cfa437 |
{CAC_READ_BUFFER, 0x00, ACR_INS_CONFIG_NONE},
|
|
Packit |
cfa437 |
{CAC_SIGN_DECRYPT, 0x06, ACR_INS_CONFIG_NONE}
|
|
Packit |
cfa437 |
}},
|
|
Packit |
cfa437 |
{"\xFF\xFF", 1, {
|
|
Packit |
cfa437 |
{VCARD7816_INS_VERIFY, 0x10, ACR_INS_CONFIG_NONE},
|
|
Packit |
cfa437 |
}}
|
|
Packit |
cfa437 |
}},
|
|
Packit |
cfa437 |
{0x67, 2, {
|
|
Packit |
cfa437 |
{"\x01\x06", 3, {
|
|
Packit |
cfa437 |
{CAC_UPDATE_BUFFER, 0x04, ACR_INS_CONFIG_NONE},
|
|
Packit |
cfa437 |
{CAC_READ_BUFFER, 0x00, ACR_INS_CONFIG_NONE},
|
|
Packit |
cfa437 |
{CAC_SIGN_DECRYPT, 0x06, ACR_INS_CONFIG_NONE}
|
|
Packit |
cfa437 |
}},
|
|
Packit |
cfa437 |
{"\xFF\xFF", 1, {
|
|
Packit |
cfa437 |
{VCARD7816_INS_VERIFY, 0x10, ACR_INS_CONFIG_NONE},
|
|
Packit |
cfa437 |
}}
|
|
Packit |
cfa437 |
}},
|
|
Packit |
cfa437 |
{0x68, 2, {
|
|
Packit |
cfa437 |
{"\x01\x07", 3, {
|
|
Packit |
cfa437 |
{CAC_UPDATE_BUFFER, 0x04, ACR_INS_CONFIG_NONE},
|
|
Packit |
cfa437 |
{CAC_READ_BUFFER, 0x00, ACR_INS_CONFIG_NONE},
|
|
Packit |
cfa437 |
{CAC_SIGN_DECRYPT, 0x06, ACR_INS_CONFIG_NONE}
|
|
Packit |
cfa437 |
}},
|
|
Packit |
cfa437 |
{"\xFF\xFF", 1, {
|
|
Packit |
cfa437 |
{VCARD7816_INS_VERIFY, 0x10, ACR_INS_CONFIG_NONE},
|
|
Packit |
cfa437 |
}}
|
|
Packit |
cfa437 |
}},
|
|
Packit |
cfa437 |
{0x69, 2, {
|
|
Packit |
cfa437 |
{"\x01\x08", 3, {
|
|
Packit |
cfa437 |
{CAC_UPDATE_BUFFER, 0x04, ACR_INS_CONFIG_NONE},
|
|
Packit |
cfa437 |
{CAC_READ_BUFFER, 0x00, ACR_INS_CONFIG_NONE},
|
|
Packit |
cfa437 |
{CAC_SIGN_DECRYPT, 0x06, ACR_INS_CONFIG_NONE}
|
|
Packit |
cfa437 |
}},
|
|
Packit |
cfa437 |
{"\xFF\xFF", 1, {
|
|
Packit |
cfa437 |
{VCARD7816_INS_VERIFY, 0x10, ACR_INS_CONFIG_NONE},
|
|
Packit |
cfa437 |
}}
|
|
Packit |
cfa437 |
}},
|
|
Packit |
cfa437 |
{0x6a, 2, {
|
|
Packit |
cfa437 |
{"\x01\x09", 3, {
|
|
Packit |
cfa437 |
{CAC_UPDATE_BUFFER, 0x04, ACR_INS_CONFIG_NONE},
|
|
Packit |
cfa437 |
{CAC_READ_BUFFER, 0x00, ACR_INS_CONFIG_NONE},
|
|
Packit |
cfa437 |
{CAC_SIGN_DECRYPT, 0x06, ACR_INS_CONFIG_NONE}
|
|
Packit |
cfa437 |
}},
|
|
Packit |
cfa437 |
{"\xFF\xFF", 1, {
|
|
Packit |
cfa437 |
{VCARD7816_INS_VERIFY, 0x10, ACR_INS_CONFIG_NONE},
|
|
Packit |
cfa437 |
}}
|
|
Packit |
cfa437 |
}},
|
|
Packit |
cfa437 |
/* Static applets */
|
|
Packit |
cfa437 |
{0x1F, 1, {
|
|
Packit |
cfa437 |
{"\xFF\xFF", 1, {
|
|
Packit |
cfa437 |
{VCARD7816_INS_VERIFY, 0x00, ACR_INS_CONFIG_NONE}
|
|
Packit |
cfa437 |
}}
|
|
Packit |
cfa437 |
}},
|
|
Packit |
cfa437 |
{0xF4, 2, {
|
|
Packit |
cfa437 |
{"\xDB\x00", 2, {
|
|
Packit |
cfa437 |
{CAC_UPDATE_BUFFER, 0x04, ACR_INS_CONFIG_NONE},
|
|
Packit |
cfa437 |
{CAC_READ_BUFFER, 0x00, ACR_INS_CONFIG_NONE}
|
|
Packit |
cfa437 |
}},
|
|
Packit |
cfa437 |
{"\xFF\xFF", 3, {
|
|
Packit |
cfa437 |
{VCARD7816_INS_EXTERNAL_AUTHENTICATE, 0x11, ACR_INS_CONFIG_P1, .p1=0x00},
|
|
Packit |
cfa437 |
{VCARD7816_INS_GET_CHALLENGE, 0x11, ACR_INS_CONFIG_NONE},
|
|
Packit |
cfa437 |
{VCARD7816_INS_VERIFY, 0x10, ACR_INS_CONFIG_NONE},
|
|
Packit |
cfa437 |
}}
|
|
Packit |
cfa437 |
}},
|
|
Packit |
cfa437 |
{0x4B, 2, {
|
|
Packit |
cfa437 |
{"\x02\xFB", 2, {
|
|
Packit |
cfa437 |
{CAC_UPDATE_BUFFER, 0x06, ACR_INS_CONFIG_NONE},
|
|
Packit |
cfa437 |
{CAC_READ_BUFFER, 0x00, ACR_INS_CONFIG_NONE}
|
|
Packit |
cfa437 |
}},
|
|
Packit |
cfa437 |
{"\xFF\xFF", 3, {
|
|
Packit |
cfa437 |
{VCARD7816_INS_EXTERNAL_AUTHENTICATE, 0x11, ACR_INS_CONFIG_P1, .p1=0x00},
|
|
Packit |
cfa437 |
{VCARD7816_INS_GET_CHALLENGE, 0x11, ACR_INS_CONFIG_NONE},
|
|
Packit |
cfa437 |
{VCARD7816_INS_VERIFY, 0x10, ACR_INS_CONFIG_NONE},
|
|
Packit |
cfa437 |
}}
|
|
Packit |
cfa437 |
}},
|
|
Packit |
cfa437 |
{0x41, 2, {
|
|
Packit |
cfa437 |
{"\x02\x00", 3, {
|
|
Packit |
cfa437 |
{CAC_UPDATE_BUFFER, 0x09, ACR_INS_CONFIG_NONE},
|
|
Packit |
cfa437 |
{CAC_READ_BUFFER, 0x00, ACR_INS_CONFIG_DATA1, .data1=0x01},
|
|
Packit |
cfa437 |
{CAC_READ_BUFFER, 0x08, ACR_INS_CONFIG_NONE}
|
|
Packit |
cfa437 |
}},
|
|
Packit |
cfa437 |
{"\xFF\xFF", 3, {
|
|
Packit |
cfa437 |
{VCARD7816_INS_EXTERNAL_AUTHENTICATE, 0x11, ACR_INS_CONFIG_P1, .p1=0x00},
|
|
Packit |
cfa437 |
{VCARD7816_INS_GET_CHALLENGE, 0x11, ACR_INS_CONFIG_NONE},
|
|
Packit |
cfa437 |
{VCARD7816_INS_VERIFY, 0x10, ACR_INS_CONFIG_NONE},
|
|
Packit |
cfa437 |
}}
|
|
Packit |
cfa437 |
}},
|
|
Packit |
cfa437 |
{0x42, 2, {
|
|
Packit |
cfa437 |
{"\x02\x01", 3, {
|
|
Packit |
cfa437 |
{CAC_UPDATE_BUFFER, 0x0B, ACR_INS_CONFIG_NONE},
|
|
Packit |
cfa437 |
{CAC_READ_BUFFER, 0x00, ACR_INS_CONFIG_DATA1, .data1=0x01},
|
|
Packit |
cfa437 |
{CAC_READ_BUFFER, 0x0A, ACR_INS_CONFIG_NONE}
|
|
Packit |
cfa437 |
}},
|
|
Packit |
cfa437 |
{"\xFF\xFF", 3, {
|
|
Packit |
cfa437 |
{VCARD7816_INS_EXTERNAL_AUTHENTICATE, 0x11, ACR_INS_CONFIG_P1, .p1=0x00},
|
|
Packit |
cfa437 |
{VCARD7816_INS_GET_CHALLENGE, 0x11, ACR_INS_CONFIG_NONE},
|
|
Packit |
cfa437 |
{VCARD7816_INS_VERIFY, 0x10, ACR_INS_CONFIG_NONE},
|
|
Packit |
cfa437 |
}}
|
|
Packit |
cfa437 |
}},
|
|
Packit |
cfa437 |
{0x40, 5, {
|
|
Packit |
cfa437 |
{"\x30\x00", 3, {
|
|
Packit |
cfa437 |
{CAC_UPDATE_BUFFER, 0x04, ACR_INS_CONFIG_NONE},
|
|
Packit |
cfa437 |
{CAC_READ_BUFFER, 0x00, ACR_INS_CONFIG_NONE},
|
|
Packit |
cfa437 |
{VCARD7816_INS_READ_BINARY, 0x00, ACR_INS_CONFIG_NONE}
|
|
Packit |
cfa437 |
}},
|
|
Packit |
cfa437 |
{"\x60\x10", 3, {
|
|
Packit |
cfa437 |
{CAC_UPDATE_BUFFER, 0x04, ACR_INS_CONFIG_NONE},
|
|
Packit |
cfa437 |
{CAC_READ_BUFFER, 0x00, ACR_INS_CONFIG_DATA1, .data1=0x01},
|
|
Packit |
cfa437 |
{CAC_READ_BUFFER, 0x06, ACR_INS_CONFIG_NONE}
|
|
Packit |
cfa437 |
}},
|
|
Packit |
cfa437 |
{"\x60\x30", 3, {
|
|
Packit |
cfa437 |
{CAC_UPDATE_BUFFER, 0x04, ACR_INS_CONFIG_NONE},
|
|
Packit |
cfa437 |
{CAC_READ_BUFFER, 0x00, ACR_INS_CONFIG_DATA1, .data1=0x01},
|
|
Packit |
cfa437 |
{CAC_READ_BUFFER, 0x06, ACR_INS_CONFIG_NONE}
|
|
Packit |
cfa437 |
}},
|
|
Packit |
cfa437 |
{"\x90\x00", 2, {
|
|
Packit |
cfa437 |
{CAC_UPDATE_BUFFER, 0x04, ACR_INS_CONFIG_NONE},
|
|
Packit |
cfa437 |
{CAC_READ_BUFFER, 0x00, ACR_INS_CONFIG_NONE}
|
|
Packit |
cfa437 |
}},
|
|
Packit |
cfa437 |
{"\xFF\xFF", 3, {
|
|
Packit |
cfa437 |
{VCARD7816_INS_EXTERNAL_AUTHENTICATE, 0x11, ACR_INS_CONFIG_P1, .p1=0x00},
|
|
Packit |
cfa437 |
{VCARD7816_INS_GET_CHALLENGE, 0x11, ACR_INS_CONFIG_NONE},
|
|
Packit |
cfa437 |
{VCARD7816_INS_VERIFY, 0x10, ACR_INS_CONFIG_NONE},
|
|
Packit |
cfa437 |
}}
|
|
Packit |
cfa437 |
}},
|
|
Packit |
cfa437 |
{0x4e, 2, {
|
|
Packit |
cfa437 |
{"\x02\xFE", 2, {
|
|
Packit |
cfa437 |
{CAC_UPDATE_BUFFER, 0x04, ACR_INS_CONFIG_NONE},
|
|
Packit |
cfa437 |
{CAC_READ_BUFFER, 0x00, ACR_INS_CONFIG_NONE}
|
|
Packit |
cfa437 |
}},
|
|
Packit |
cfa437 |
{"\xFF\xFF", 3, {
|
|
Packit |
cfa437 |
{VCARD7816_INS_EXTERNAL_AUTHENTICATE, 0x11, ACR_INS_CONFIG_P1, .p1=0x00},
|
|
Packit |
cfa437 |
{VCARD7816_INS_GET_CHALLENGE, 0x11, ACR_INS_CONFIG_NONE},
|
|
Packit |
cfa437 |
{VCARD7816_INS_VERIFY, 0x10, ACR_INS_CONFIG_NONE},
|
|
Packit |
cfa437 |
}}
|
|
Packit |
cfa437 |
}},
|
|
Packit |
cfa437 |
{0x4d, 2, {
|
|
Packit |
cfa437 |
{"\x02\xFD", 3, {
|
|
Packit |
cfa437 |
{CAC_UPDATE_BUFFER, 0x06, ACR_INS_CONFIG_NONE},
|
|
Packit |
cfa437 |
{CAC_READ_BUFFER, 0x00, ACR_INS_CONFIG_DATA1, .data1=0x01},
|
|
Packit |
cfa437 |
{CAC_READ_BUFFER, 0x06, ACR_INS_CONFIG_NONE}
|
|
Packit |
cfa437 |
}},
|
|
Packit |
cfa437 |
{"\xFF\xFF", 3, {
|
|
Packit |
cfa437 |
{VCARD7816_INS_EXTERNAL_AUTHENTICATE, 0x11, ACR_INS_CONFIG_P1, .p1=0x00},
|
|
Packit |
cfa437 |
{VCARD7816_INS_GET_CHALLENGE, 0x11, ACR_INS_CONFIG_NONE},
|
|
Packit |
cfa437 |
{VCARD7816_INS_VERIFY, 0x10, ACR_INS_CONFIG_NONE},
|
|
Packit |
cfa437 |
}}
|
|
Packit |
cfa437 |
}},
|
|
Packit |
cfa437 |
{0x50, 1, {
|
|
Packit |
cfa437 |
{"\xFF\xFF", 5, {
|
|
Packit |
cfa437 |
{CAC_UPDATE_BUFFER, 0x04, ACR_INS_CONFIG_NONE},
|
|
Packit |
cfa437 |
{CAC_READ_BUFFER, 0x00, ACR_INS_CONFIG_NONE},
|
|
Packit |
cfa437 |
{VCARD7816_INS_EXTERNAL_AUTHENTICATE, 0x11, ACR_INS_CONFIG_P1, .p1=0x00},
|
|
Packit |
cfa437 |
{VCARD7816_INS_GET_CHALLENGE, 0x11, ACR_INS_CONFIG_NONE},
|
|
Packit |
cfa437 |
{VCARD7816_INS_VERIFY, 0x10, ACR_INS_CONFIG_NONE},
|
|
Packit |
cfa437 |
}}
|
|
Packit |
cfa437 |
}},
|
|
Packit |
cfa437 |
{0x51, 1, {
|
|
Packit |
cfa437 |
{"\xFF\xFF", 5, {
|
|
Packit |
cfa437 |
{CAC_UPDATE_BUFFER, 0x04, ACR_INS_CONFIG_NONE},
|
|
Packit |
cfa437 |
{CAC_READ_BUFFER, 0x00, ACR_INS_CONFIG_NONE},
|
|
Packit |
cfa437 |
{VCARD7816_INS_EXTERNAL_AUTHENTICATE, 0x11, ACR_INS_CONFIG_P1, .p1=0x00},
|
|
Packit |
cfa437 |
{VCARD7816_INS_GET_CHALLENGE, 0x11, ACR_INS_CONFIG_NONE},
|
|
Packit |
cfa437 |
{VCARD7816_INS_VERIFY, 0x10, ACR_INS_CONFIG_NONE},
|
|
Packit |
cfa437 |
}}
|
|
Packit |
cfa437 |
}},
|
|
Packit |
cfa437 |
{0x52, 1, {
|
|
Packit |
cfa437 |
{"\xFF\xFF", 5, {
|
|
Packit |
cfa437 |
{CAC_UPDATE_BUFFER, 0x04, ACR_INS_CONFIG_NONE},
|
|
Packit |
cfa437 |
{CAC_READ_BUFFER, 0x00, ACR_INS_CONFIG_NONE},
|
|
Packit |
cfa437 |
{VCARD7816_INS_EXTERNAL_AUTHENTICATE, 0x11, ACR_INS_CONFIG_P1, .p1=0x00},
|
|
Packit |
cfa437 |
{VCARD7816_INS_GET_CHALLENGE, 0x11, ACR_INS_CONFIG_NONE},
|
|
Packit |
cfa437 |
{VCARD7816_INS_VERIFY, 0x10, ACR_INS_CONFIG_NONE},
|
|
Packit |
cfa437 |
}}
|
|
Packit |
cfa437 |
}},
|
|
Packit |
cfa437 |
{0x44, 2, {
|
|
Packit |
cfa437 |
{"\x12\x01", 3, {
|
|
Packit |
cfa437 |
{CAC_UPDATE_BUFFER, 0x06, ACR_INS_CONFIG_NONE},
|
|
Packit |
cfa437 |
{CAC_READ_BUFFER, 0x00, ACR_INS_CONFIG_DATA1, .data1=0x01},
|
|
Packit |
cfa437 |
{CAC_READ_BUFFER, 0x06, ACR_INS_CONFIG_NONE}
|
|
Packit |
cfa437 |
}},
|
|
Packit |
cfa437 |
{"\xFF\xFF", 3, {
|
|
Packit |
cfa437 |
{VCARD7816_INS_EXTERNAL_AUTHENTICATE, 0x11, ACR_INS_CONFIG_P1, .p1=0x00},
|
|
Packit |
cfa437 |
{VCARD7816_INS_GET_CHALLENGE, 0x11, ACR_INS_CONFIG_NONE},
|
|
Packit |
cfa437 |
{VCARD7816_INS_VERIFY, 0x10, ACR_INS_CONFIG_NONE},
|
|
Packit |
cfa437 |
}}
|
|
Packit |
cfa437 |
}},
|
|
Packit |
cfa437 |
{0x45, 2, {
|
|
Packit |
cfa437 |
{"\x12\x02", 3, {
|
|
Packit |
cfa437 |
{CAC_UPDATE_BUFFER, 0x06, ACR_INS_CONFIG_NONE},
|
|
Packit |
cfa437 |
{CAC_READ_BUFFER, 0x00, ACR_INS_CONFIG_DATA1, .data1=0x01},
|
|
Packit |
cfa437 |
{CAC_READ_BUFFER, 0x06, ACR_INS_CONFIG_NONE}
|
|
Packit |
cfa437 |
}},
|
|
Packit |
cfa437 |
{"\xFF\xFF", 3, {
|
|
Packit |
cfa437 |
{VCARD7816_INS_EXTERNAL_AUTHENTICATE, 0x11, ACR_INS_CONFIG_P1, .p1=0x00},
|
|
Packit |
cfa437 |
{VCARD7816_INS_GET_CHALLENGE, 0x11, ACR_INS_CONFIG_NONE},
|
|
Packit |
cfa437 |
{VCARD7816_INS_VERIFY, 0x10, ACR_INS_CONFIG_NONE},
|
|
Packit |
cfa437 |
}}
|
|
Packit |
cfa437 |
}},
|
|
Packit |
cfa437 |
}
|
|
Packit |
cfa437 |
};
|
|
Packit |
cfa437 |
|
|
Packit |
cfa437 |
static unsigned char *
|
|
Packit |
cfa437 |
acr_applet_object_encode(struct acr_object *object, unsigned char *out,
|
|
Packit |
cfa437 |
unsigned int outlen, unsigned int *lenp)
|
|
Packit |
cfa437 |
{
|
|
Packit |
cfa437 |
unsigned int j;
|
|
Packit |
cfa437 |
unsigned char *p = NULL;
|
|
Packit |
cfa437 |
|
|
Packit |
cfa437 |
p = out;
|
|
Packit |
cfa437 |
if (outlen < 2)
|
|
Packit |
cfa437 |
return NULL;
|
|
Packit |
cfa437 |
*p++ = object->id[0];
|
|
Packit |
cfa437 |
*p++ = object->id[1];
|
|
Packit |
cfa437 |
outlen -= 2;
|
|
Packit |
cfa437 |
for (j = 0; j < object->num_ins; j++) {
|
|
Packit |
cfa437 |
if (outlen < 3)
|
|
Packit |
cfa437 |
return NULL;
|
|
Packit |
cfa437 |
*p++ = object->ins[j].code;
|
|
Packit |
cfa437 |
*p++ = object->ins[j].config;
|
|
Packit |
cfa437 |
outlen -= 2;
|
|
Packit |
cfa437 |
if (object->ins[j].config & ACR_INS_CONFIG_P1) {
|
|
Packit |
cfa437 |
if (outlen < 1)
|
|
Packit |
cfa437 |
return NULL;
|
|
Packit |
cfa437 |
*p++ = object->ins[j].p1;
|
|
Packit |
cfa437 |
outlen--;
|
|
Packit |
cfa437 |
}
|
|
Packit |
cfa437 |
if (object->ins[j].config & ACR_INS_CONFIG_P2) {
|
|
Packit |
cfa437 |
if (outlen < 1)
|
|
Packit |
cfa437 |
return NULL;
|
|
Packit |
cfa437 |
*p++ = object->ins[j].p2;
|
|
Packit |
cfa437 |
outlen--;
|
|
Packit |
cfa437 |
}
|
|
Packit |
cfa437 |
if (object->ins[j].config & ACR_INS_CONFIG_DATA1) {
|
|
Packit |
cfa437 |
if (outlen < 1)
|
|
Packit |
cfa437 |
return NULL;
|
|
Packit |
cfa437 |
*p++ = object->ins[j].data1;
|
|
Packit |
cfa437 |
outlen--;
|
|
Packit |
cfa437 |
}
|
|
Packit |
cfa437 |
|
|
Packit |
cfa437 |
if (outlen < 1)
|
|
Packit |
cfa437 |
return NULL;
|
|
Packit |
cfa437 |
*p++ = object->ins[j].acrid;
|
|
Packit |
cfa437 |
outlen--;
|
|
Packit |
cfa437 |
}
|
|
Packit |
cfa437 |
*lenp = (p - out);
|
|
Packit |
cfa437 |
return p;
|
|
Packit |
cfa437 |
}
|
|
Packit |
cfa437 |
|
|
Packit |
cfa437 |
static unsigned char *
|
|
Packit |
cfa437 |
acr_applet_encode(struct acr_applet *applet, unsigned int *outlen)
|
|
Packit |
cfa437 |
{
|
|
Packit |
cfa437 |
unsigned char *buffer = NULL, *p, *lenp;
|
|
Packit |
cfa437 |
unsigned int i, j, plen, objlen, buffer_len;
|
|
Packit |
cfa437 |
|
|
Packit |
cfa437 |
if (outlen == NULL)
|
|
Packit |
cfa437 |
return NULL;
|
|
Packit |
cfa437 |
|
|
Packit |
cfa437 |
plen = 2;
|
|
Packit |
cfa437 |
for (i = 0; i < applet->num_objects; i++) {
|
|
Packit |
cfa437 |
plen += 4;
|
|
Packit |
cfa437 |
for (j = 0; j < applet->objects[i].num_ins; j++) {
|
|
Packit |
cfa437 |
plen += 3;
|
|
Packit |
cfa437 |
if (applet->objects[i].ins[j].config & ACR_INS_CONFIG_P1)
|
|
Packit |
cfa437 |
plen++;
|
|
Packit |
cfa437 |
if (applet->objects[i].ins[j].config & ACR_INS_CONFIG_P2)
|
|
Packit |
cfa437 |
plen++;
|
|
Packit |
cfa437 |
if (applet->objects[i].ins[j].config & ACR_INS_CONFIG_DATA1)
|
|
Packit |
cfa437 |
plen++;
|
|
Packit |
cfa437 |
}
|
|
Packit |
cfa437 |
}
|
|
Packit |
cfa437 |
buffer_len = plen;
|
|
Packit |
cfa437 |
buffer = g_malloc(plen);
|
|
Packit |
cfa437 |
|
|
Packit |
cfa437 |
p = buffer;
|
|
Packit |
cfa437 |
*p++ = applet->id;
|
|
Packit |
cfa437 |
*p++ = applet->num_objects;
|
|
Packit |
cfa437 |
plen -= 2;
|
|
Packit |
cfa437 |
for (i = 0; i < applet->num_objects; i++) {
|
|
Packit |
cfa437 |
*p++ = CAC_ACR_OBJECT_ACR;
|
|
Packit |
cfa437 |
lenp = p++;
|
|
Packit |
cfa437 |
plen -= 2;
|
|
Packit |
cfa437 |
p = acr_applet_object_encode(&applet->objects[i], p, plen, &objlen);
|
|
Packit |
cfa437 |
if (!p)
|
|
Packit |
cfa437 |
goto failure;
|
|
Packit |
cfa437 |
*lenp = objlen & 0xff;
|
|
Packit |
cfa437 |
plen -= objlen;
|
|
Packit |
cfa437 |
}
|
|
Packit |
cfa437 |
|
|
Packit |
cfa437 |
g_assert_cmpint(p - buffer, ==, buffer_len);
|
|
Packit |
cfa437 |
*outlen = buffer_len;
|
|
Packit |
cfa437 |
return buffer;
|
|
Packit |
cfa437 |
|
|
Packit |
cfa437 |
failure:
|
|
Packit |
cfa437 |
g_free(buffer);
|
|
Packit |
cfa437 |
return NULL;
|
|
Packit |
cfa437 |
}
|
|
Packit |
cfa437 |
|
|
Packit |
cfa437 |
static struct simpletlv_member *
|
|
Packit |
cfa437 |
cac_aca_get_applet_acr_coid(unsigned int pki_applets, unsigned char *coid)
|
|
Packit |
cfa437 |
{
|
|
Packit |
cfa437 |
struct simpletlv_member *r = NULL;
|
|
Packit |
cfa437 |
size_t i, j;
|
|
Packit |
cfa437 |
|
|
Packit |
cfa437 |
r = g_malloc(sizeof(struct simpletlv_member));
|
|
Packit |
cfa437 |
|
|
Packit |
cfa437 |
for (i = 0; i <= applets_table.num_applets; i++) {
|
|
Packit |
cfa437 |
/* Skip unused PKI applets */
|
|
Packit |
cfa437 |
if (i >= pki_applets && i < 10)
|
|
Packit |
cfa437 |
continue;
|
|
Packit |
cfa437 |
|
|
Packit |
cfa437 |
for (j = 0; j < applets_table.applets[i].num_objects; j++) {
|
|
Packit |
cfa437 |
if (memcmp(&applets_table.applets[i].objects[j].id, coid, 2) == 0) {
|
|
Packit |
cfa437 |
unsigned int buffer_len = ACR_MAX_INSTRUCTIONS * 6 + 2;
|
|
Packit |
cfa437 |
unsigned char *p = NULL;
|
|
Packit |
cfa437 |
|
|
Packit |
cfa437 |
r->type = SIMPLETLV_TYPE_LEAF;
|
|
Packit |
cfa437 |
r->tag = CAC_ACR_OBJECT_ACR;
|
|
Packit |
cfa437 |
r->value.value = g_malloc_n(buffer_len, sizeof(unsigned char));
|
|
Packit |
cfa437 |
p = acr_applet_object_encode(
|
|
Packit |
cfa437 |
&applets_table.applets[i].objects[j],
|
|
Packit |
cfa437 |
r->value.value, buffer_len, &r->length);
|
|
Packit |
cfa437 |
/* return the record on success */
|
|
Packit |
cfa437 |
if (p)
|
|
Packit |
cfa437 |
return r;
|
|
Packit |
cfa437 |
|
|
Packit |
cfa437 |
/* clean up on failure */
|
|
Packit |
cfa437 |
g_free(r->value.value);
|
|
Packit |
cfa437 |
}
|
|
Packit |
cfa437 |
}
|
|
Packit |
cfa437 |
}
|
|
Packit |
cfa437 |
/* Failure */
|
|
Packit |
cfa437 |
g_free(r);
|
|
Packit |
cfa437 |
return NULL;
|
|
Packit |
cfa437 |
}
|
|
Packit |
cfa437 |
|
|
Packit |
cfa437 |
static unsigned char
|
|
Packit |
cfa437 |
aid_to_applet_id(unsigned int pki_applets, unsigned char *aid, unsigned int aid_len)
|
|
Packit |
cfa437 |
{
|
|
Packit |
cfa437 |
unsigned int i;
|
|
Packit |
cfa437 |
for (i = 0; i < service_table.num_entries; i++) {
|
|
Packit |
cfa437 |
if ((i < pki_applets || i >= 10)
|
|
Packit |
cfa437 |
&& aid_len == service_table.entries[i].applet_aid_len
|
|
Packit |
cfa437 |
&& memcmp(aid, service_table.entries[i].applet_aid, aid_len) == 0)
|
|
Packit |
cfa437 |
return service_table.entries[i].applet_id;
|
|
Packit |
cfa437 |
}
|
|
Packit |
cfa437 |
return 0x00;
|
|
Packit |
cfa437 |
}
|
|
Packit |
cfa437 |
|
|
Packit |
cfa437 |
static struct simpletlv_member *
|
|
Packit |
cfa437 |
cac_aca_get_applet_acr(unsigned int pki_applets, size_t *acr_len, unsigned char *aid,
|
|
Packit |
cfa437 |
unsigned int aid_len)
|
|
Packit |
cfa437 |
{
|
|
Packit |
cfa437 |
struct simpletlv_member *r = NULL;
|
|
Packit |
cfa437 |
unsigned char *num_applets_byte = NULL;
|
|
Packit |
cfa437 |
size_t i, j = 0;
|
|
Packit |
cfa437 |
unsigned char applet_id = 0;
|
|
Packit |
cfa437 |
unsigned int num_applets = applets_table.num_static_applets + pki_applets;
|
|
Packit |
cfa437 |
|
|
Packit |
cfa437 |
g_assert_nonnull(acr_len);
|
|
Packit |
cfa437 |
|
|
Packit |
cfa437 |
if (aid != NULL && aid_len != 0) {
|
|
Packit |
cfa437 |
/* We are selecting only one applet*/
|
|
Packit |
cfa437 |
applet_id = aid_to_applet_id(pki_applets, aid, aid_len);
|
|
Packit |
cfa437 |
if (applet_id == 0)
|
|
Packit |
cfa437 |
return NULL;
|
|
Packit |
cfa437 |
|
|
Packit |
cfa437 |
r = g_malloc(sizeof(struct simpletlv_member));
|
|
Packit |
cfa437 |
} else {
|
|
Packit |
cfa437 |
r = g_malloc_n(num_applets + 1, sizeof(struct simpletlv_member));
|
|
Packit |
cfa437 |
}
|
|
Packit |
cfa437 |
|
|
Packit |
cfa437 |
if (!applet_id) {
|
|
Packit |
cfa437 |
num_applets_byte = g_malloc(1);
|
|
Packit |
cfa437 |
*num_applets_byte = num_applets;
|
|
Packit |
cfa437 |
|
|
Packit |
cfa437 |
r[j].tag = CAC_ACR_NUM_APPLETS;
|
|
Packit |
cfa437 |
r[j].length = 1;
|
|
Packit |
cfa437 |
r[j].value.value = num_applets_byte;
|
|
Packit |
cfa437 |
r[j].type = SIMPLETLV_TYPE_LEAF;
|
|
Packit |
cfa437 |
j++;
|
|
Packit |
cfa437 |
}
|
|
Packit |
cfa437 |
for (i = 0; i < applets_table.num_applets; i++) {
|
|
Packit |
cfa437 |
/* Skip unused PKI applets */
|
|
Packit |
cfa437 |
if (i >= pki_applets && i < 10)
|
|
Packit |
cfa437 |
continue;
|
|
Packit |
cfa437 |
|
|
Packit |
cfa437 |
if (applet_id && applet_id != applets_table.applets[i].id)
|
|
Packit |
cfa437 |
continue;
|
|
Packit |
cfa437 |
|
|
Packit |
cfa437 |
r[j].type = SIMPLETLV_TYPE_LEAF;
|
|
Packit |
cfa437 |
r[j].tag = CAC_ACR_APPLET_ACR;
|
|
Packit |
cfa437 |
r[j].value.value = acr_applet_encode(&applets_table.applets[i], &r[j].length);
|
|
Packit |
cfa437 |
if (r[j].value.value == NULL)
|
|
Packit |
cfa437 |
goto failure;
|
|
Packit |
cfa437 |
j++;
|
|
Packit |
cfa437 |
}
|
|
Packit |
cfa437 |
|
|
Packit |
cfa437 |
*acr_len = j;
|
|
Packit |
cfa437 |
return r;
|
|
Packit |
cfa437 |
|
|
Packit |
cfa437 |
failure:
|
|
Packit |
cfa437 |
simpletlv_free(r, j);
|
|
Packit |
cfa437 |
g_free(num_applets_byte);
|
|
Packit |
cfa437 |
return NULL;
|
|
Packit |
cfa437 |
}
|
|
Packit |
cfa437 |
|
|
Packit |
cfa437 |
/*
|
|
Packit |
cfa437 |
* Access Method Provider (AMP) table:
|
|
Packit |
cfa437 |
* This table maps the Access Method Provider ID to the full AID
|
|
Packit |
cfa437 |
* for each Access Method Provider.
|
|
Packit |
cfa437 |
* (from 5.3.3.5 Get ACR APDU, Table 5-20)
|
|
Packit |
cfa437 |
*/
|
|
Packit |
cfa437 |
|
|
Packit |
cfa437 |
struct amp_entry {
|
|
Packit |
cfa437 |
unsigned char amp_id;
|
|
Packit |
cfa437 |
unsigned int amp_aid_len;
|
|
Packit |
cfa437 |
unsigned char amp_aid[7];
|
|
Packit |
cfa437 |
};
|
|
Packit |
cfa437 |
struct amp_table {
|
|
Packit |
cfa437 |
unsigned int num_entries;
|
|
Packit |
cfa437 |
struct amp_entry entries[5];
|
|
Packit |
cfa437 |
};
|
|
Packit |
cfa437 |
|
|
Packit |
cfa437 |
/* Example:
|
|
Packit |
cfa437 |
* 01 05 TL: Applet information
|
|
Packit |
cfa437 |
* 10 02 06 02 02
|
|
Packit |
cfa437 |
* 91 01 TL: Number of AMP entries
|
|
Packit |
cfa437 |
* 03
|
|
Packit |
cfa437 |
* 90 0A AMP Entry
|
|
Packit |
cfa437 |
* 1F Access Method Provider ID
|
|
Packit |
cfa437 |
* 92 07 TL: Access Method Provider AID
|
|
Packit |
cfa437 |
* A0 00 00 00 79 03 00
|
|
Packit |
cfa437 |
* 90 0A AMP Entry
|
|
Packit |
cfa437 |
* 1E Access Method Provider ID
|
|
Packit |
cfa437 |
* 92 07 TL: Access Method Provider AID
|
|
Packit |
cfa437 |
* A0 00 00 00 79 03 00
|
|
Packit |
cfa437 |
* 90 0A AMP Entry
|
|
Packit |
cfa437 |
* 1D Access Method Provider ID
|
|
Packit |
cfa437 |
* 92 07 TL: Access Method Provider AID
|
|
Packit |
cfa437 |
* A0 00 00 00 79 03 00
|
|
Packit |
cfa437 |
*/
|
|
Packit |
cfa437 |
|
|
Packit |
cfa437 |
struct amp_table amp_table = {
|
|
Packit |
cfa437 |
3, {
|
|
Packit |
cfa437 |
{0x1F, 7, "\xA0\x00\x00\x00\x79\x03\x00"},
|
|
Packit |
cfa437 |
{0x1E, 7, "\xA0\x00\x00\x00\x79\x03\x00"},
|
|
Packit |
cfa437 |
{0x1D, 7, "\xA0\x00\x00\x00\x79\x03\x00"},
|
|
Packit |
cfa437 |
}
|
|
Packit |
cfa437 |
};
|
|
Packit |
cfa437 |
|
|
Packit |
cfa437 |
static unsigned char amp_table_extended[] = {
|
|
Packit |
cfa437 |
0x1F, 0x00, 0x07, 0xA0, 0x00, 0x00, 0x00, 0x79, 0x03, 0x00,
|
|
Packit |
cfa437 |
0x12, 0x00, 0x00, 0x00,
|
|
Packit |
cfa437 |
/* Sometimes it can be 1E 00 07 A0 00 00 00 79 03 00 10 00 00 00 */
|
|
Packit |
cfa437 |
0x1E, 0x00, 0x07, 0xA0, 0x00, 0x00, 0x00, 0x79, 0x03, 0x00,
|
|
Packit |
cfa437 |
0x10, 0x01, 0x00, 0x00,
|
|
Packit |
cfa437 |
0x1D, 0x00, 0x07, 0xA0, 0x00, 0x00, 0x00, 0x79, 0x03, 0x00,
|
|
Packit |
cfa437 |
0x01, 0x00, 0x00, 0x00,
|
|
Packit |
cfa437 |
};
|
|
Packit |
cfa437 |
|
|
Packit |
cfa437 |
static struct simpletlv_member *
|
|
Packit |
cfa437 |
cac_aca_get_amp(size_t *amp_len)
|
|
Packit |
cfa437 |
{
|
|
Packit |
cfa437 |
struct simpletlv_member *r = NULL;
|
|
Packit |
cfa437 |
unsigned char *num_entries = NULL;
|
|
Packit |
cfa437 |
unsigned char *entry = NULL;
|
|
Packit |
cfa437 |
size_t i = 0;
|
|
Packit |
cfa437 |
|
|
Packit |
cfa437 |
g_assert_nonnull(amp_len);
|
|
Packit |
cfa437 |
|
|
Packit |
cfa437 |
r = g_malloc_n(amp_table.num_entries + 1, sizeof(struct simpletlv_member));
|
|
Packit |
cfa437 |
|
|
Packit |
cfa437 |
num_entries = g_malloc(1);
|
|
Packit |
cfa437 |
*num_entries = amp_table.num_entries;
|
|
Packit |
cfa437 |
|
|
Packit |
cfa437 |
r[0].tag = CAC_ACR_AMP_NUM_ENTRIES;
|
|
Packit |
cfa437 |
r[0].length = 1;
|
|
Packit |
cfa437 |
r[0].value.value = num_entries;
|
|
Packit |
cfa437 |
r[0].type = SIMPLETLV_TYPE_LEAF;
|
|
Packit |
cfa437 |
for (i = 1; i <= amp_table.num_entries; i++) {
|
|
Packit |
cfa437 |
r[i].type = SIMPLETLV_TYPE_LEAF;
|
|
Packit |
cfa437 |
r[i].tag = CAC_ACR_AMP_ENTRY;
|
|
Packit |
cfa437 |
r[i].length = amp_table.entries[i].amp_aid_len + 3;
|
|
Packit |
cfa437 |
entry = g_malloc(r[i].length);
|
|
Packit |
cfa437 |
entry[0] = amp_table.entries[i].amp_id;
|
|
Packit |
cfa437 |
entry[1] = CAC_ACR_AID;
|
|
Packit |
cfa437 |
entry[2] = amp_table.entries[i].amp_aid_len;
|
|
Packit |
cfa437 |
memcpy(&entry[3], (unsigned char *) &_table.entries[i],
|
|
Packit |
cfa437 |
amp_table.entries[i].amp_aid_len);
|
|
Packit |
cfa437 |
r[i].value.value = entry;
|
|
Packit |
cfa437 |
}
|
|
Packit |
cfa437 |
*amp_len = amp_table.num_entries + 1;
|
|
Packit |
cfa437 |
return r;
|
|
Packit |
cfa437 |
}
|
|
Packit |
cfa437 |
|
|
Packit |
cfa437 |
/* ACA Applet Information
|
|
Packit |
cfa437 |
* The following entry is always returned and precedes any ACR table,
|
|
Packit |
cfa437 |
* Applet/Object ACR table or Authentication Method Provider table.
|
|
Packit |
cfa437 |
*
|
|
Packit |
cfa437 |
* 01 Tag: Applet Information
|
|
Packit |
cfa437 |
* 05 Length
|
|
Packit |
cfa437 |
* 10 Applet family
|
|
Packit |
cfa437 |
* 02 06 02 02 Applet version
|
|
Packit |
cfa437 |
*/
|
|
Packit |
cfa437 |
unsigned char applet_information[] = "\x10\x02\x06\x02\x02";
|
|
Packit |
cfa437 |
static struct simpletlv_member aca_properties[1] = {
|
|
Packit |
cfa437 |
{CAC_PROPERTIES_APPLET_INFORMATION, 5, {/*.value = applet_information*/},
|
|
Packit |
cfa437 |
SIMPLETLV_TYPE_LEAF},
|
|
Packit |
cfa437 |
};
|
|
Packit |
cfa437 |
|
|
Packit |
cfa437 |
static struct simpletlv_member *
|
|
Packit |
cfa437 |
cac_aca_get_properties(size_t *properties_len)
|
|
Packit |
cfa437 |
{
|
|
Packit |
cfa437 |
g_assert_nonnull(properties_len);
|
|
Packit |
cfa437 |
|
|
Packit |
cfa437 |
/* Inject Applet Version into Applet information */
|
|
Packit |
cfa437 |
aca_properties[0].value.value = applet_information;
|
|
Packit |
cfa437 |
|
|
Packit |
cfa437 |
*properties_len = 1;
|
|
Packit |
cfa437 |
|
|
Packit |
cfa437 |
return aca_properties;
|
|
Packit |
cfa437 |
}
|
|
Packit |
cfa437 |
|
|
Packit |
cfa437 |
/*
|
|
Packit |
cfa437 |
* This is ACR table in undocumented compressed form
|
|
Packit |
cfa437 |
*
|
|
Packit |
cfa437 |
* |ACRID ACRType AMPid:keyID
|
|
Packit |
cfa437 |
* 06 00 00 00 00 00 00 | 00 00
|
|
Packit |
cfa437 |
* 06 01 01 00 01 00 00 | 01 01
|
|
Packit |
cfa437 |
* 06 02 00 1F 00 00 00 | 02 00
|
|
Packit |
cfa437 |
* 06 06 06 00 1E 00 00 | 06 06 1E:00
|
|
Packit |
cfa437 |
* 06 04 04 1F 1F 21 00 | 04 04 1F:21
|
|
Packit |
cfa437 |
* 08 08 03 00 9D 01 1E 01 00 | 08 03 9D:01 1E:01
|
|
Packit |
cfa437 |
* 06 09 02 00 1D 02 00 | 09 02 1D:02
|
|
Packit |
cfa437 |
* 08 0A 03 00 9D 03 1E 01 00 | 0A 03 9D:03 1E:01
|
|
Packit |
cfa437 |
* 06 0B 02 00 1D 04 00 | 0B 02 1D:04
|
|
Packit |
cfa437 |
* 06 10 00 1E 00 00 00 | 10 00
|
|
Packit |
cfa437 |
* 06 11 00 1D 00 00 00 | 11 00
|
|
Packit |
cfa437 |
* len | | ? | |
|
|
Packit |
cfa437 |
* ACRID | ? | |
|
|
Packit |
cfa437 |
* ACRType | |
|
|
Packit |
cfa437 |
* AMPid |
|
|
Packit |
cfa437 |
* KeyIdOrReference
|
|
Packit |
cfa437 |
*/
|
|
Packit |
cfa437 |
static VCardResponse *
|
|
Packit |
cfa437 |
cac_aca_get_acr_response_extended(VCard *card, int Le, unsigned char *acrid)
|
|
Packit |
cfa437 |
{
|
|
Packit |
cfa437 |
size_t buffer_len;
|
|
Packit |
cfa437 |
unsigned char *buffer = NULL, *p;
|
|
Packit |
cfa437 |
VCardResponse *r = NULL;
|
|
Packit |
cfa437 |
size_t i, j;
|
|
Packit |
cfa437 |
|
|
Packit |
cfa437 |
buffer_len = acr_table.num_entries * (7 + 2 * (MAX_ACCESS_METHODS - 1));
|
|
Packit |
cfa437 |
buffer = g_malloc_n(buffer_len, sizeof(unsigned char));
|
|
Packit |
cfa437 |
p = buffer;
|
|
Packit |
cfa437 |
|
|
Packit |
cfa437 |
for (i = 0; i < acr_table.num_entries; i++) {
|
|
Packit |
cfa437 |
struct acr_entry *a = &acr_table.entries[i];
|
|
Packit |
cfa437 |
g_assert_cmpint(a->num_access_methods, <=, MAX_ACCESS_METHODS);
|
|
Packit |
cfa437 |
*p++ = a->num_access_methods == 2 ? 0x08 : 0x06;
|
|
Packit |
cfa437 |
*p++ = a->acrid;
|
|
Packit |
cfa437 |
*p++ = a->acrtype;
|
|
Packit |
cfa437 |
*p++ = a->applet_id;
|
|
Packit |
cfa437 |
|
|
Packit |
cfa437 |
for (j = 0; j < a->num_access_methods; j++) {
|
|
Packit |
cfa437 |
*p++ = a->access_methods[j].provider_id;
|
|
Packit |
cfa437 |
*p++ = a->access_methods[j].keyIDOrReference;
|
|
Packit |
cfa437 |
}
|
|
Packit |
cfa437 |
if (a->num_access_methods == 0) {
|
|
Packit |
cfa437 |
*p++ = 0x00;
|
|
Packit |
cfa437 |
*p++ = 0x00;
|
|
Packit |
cfa437 |
}
|
|
Packit |
cfa437 |
*p++ = 0x00;
|
|
Packit |
cfa437 |
}
|
|
Packit |
cfa437 |
g_assert((unsigned long)(p - buffer) <= buffer_len);
|
|
Packit |
cfa437 |
buffer_len = (p - buffer);
|
|
Packit |
cfa437 |
|
|
Packit |
cfa437 |
r = vcard_response_new(card, buffer, buffer_len, Le,
|
|
Packit |
cfa437 |
VCARD7816_STATUS_SUCCESS);
|
|
Packit |
cfa437 |
g_debug("%s: response bytes: %s", __func__,
|
|
Packit |
cfa437 |
hex_dump(buffer, buffer_len, NULL, 0));
|
|
Packit |
cfa437 |
g_free(buffer);
|
|
Packit |
cfa437 |
return r;
|
|
Packit |
cfa437 |
}
|
|
Packit |
cfa437 |
|
|
Packit |
cfa437 |
|
|
Packit |
cfa437 |
|
|
Packit |
cfa437 |
static VCardResponse *
|
|
Packit |
cfa437 |
cac_aca_get_acr_response_simpletlv(VCard *card, int Le, unsigned char *acrid)
|
|
Packit |
cfa437 |
{
|
|
Packit |
cfa437 |
size_t acr_buffer_len;
|
|
Packit |
cfa437 |
unsigned char *acr_buffer = NULL;
|
|
Packit |
cfa437 |
size_t properties_len;
|
|
Packit |
cfa437 |
const struct simpletlv_member *properties;
|
|
Packit |
cfa437 |
size_t acr_len;
|
|
Packit |
cfa437 |
struct simpletlv_member *acr = NULL;
|
|
Packit |
cfa437 |
size_t list_len;
|
|
Packit |
cfa437 |
struct simpletlv_member *list = NULL;
|
|
Packit |
cfa437 |
VCardResponse *r = NULL;
|
|
Packit |
cfa437 |
|
|
Packit |
cfa437 |
/* Prepare the SimpleTLV structures */
|
|
Packit |
cfa437 |
properties = cac_aca_get_properties(&properties_len);
|
|
Packit |
cfa437 |
acr = cac_aca_get_acr(&acr_len, acrid);
|
|
Packit |
cfa437 |
if (acr == NULL) {
|
|
Packit |
cfa437 |
/* The requested ACR was not found */
|
|
Packit |
cfa437 |
r = vcard_make_response(VCARD7816_STATUS_ERROR_DATA_NOT_FOUND);
|
|
Packit |
cfa437 |
return r;
|
|
Packit |
cfa437 |
}
|
|
Packit |
cfa437 |
|
|
Packit |
cfa437 |
/* Merge them together */
|
|
Packit |
cfa437 |
list_len = properties_len + acr_len;
|
|
Packit |
cfa437 |
list = simpletlv_merge(properties, properties_len, acr, acr_len);
|
|
Packit |
cfa437 |
if (list == NULL)
|
|
Packit |
cfa437 |
goto failure;
|
|
Packit |
cfa437 |
|
|
Packit |
cfa437 |
/* encode the data */
|
|
Packit |
cfa437 |
acr_buffer_len = simpletlv_encode(list, list_len, &acr_buffer, 0, NULL);
|
|
Packit |
cfa437 |
if (acr_buffer == NULL)
|
|
Packit |
cfa437 |
goto failure;
|
|
Packit |
cfa437 |
|
|
Packit |
cfa437 |
r = vcard_response_new(card, acr_buffer, acr_buffer_len, Le,
|
|
Packit |
cfa437 |
VCARD7816_STATUS_SUCCESS);
|
|
Packit |
cfa437 |
|
|
Packit |
cfa437 |
failure:
|
|
Packit |
cfa437 |
g_free(list);
|
|
Packit |
cfa437 |
g_free(acr);
|
|
Packit |
cfa437 |
g_free(acr_buffer);
|
|
Packit |
cfa437 |
if (r == NULL)
|
|
Packit |
cfa437 |
r = vcard_make_response(VCARD7816_STATUS_ERROR_GENERAL);
|
|
Packit |
cfa437 |
return r;
|
|
Packit |
cfa437 |
}
|
|
Packit |
cfa437 |
|
|
Packit |
cfa437 |
VCardResponse *
|
|
Packit |
cfa437 |
cac_aca_get_acr_response(VCard *card, int Le, unsigned char *acrid, int format)
|
|
Packit |
cfa437 |
{
|
|
Packit |
cfa437 |
if (format == CAC_FORMAT_SIMPLETLV) {
|
|
Packit |
cfa437 |
return cac_aca_get_acr_response_simpletlv(card, Le, acrid);
|
|
Packit |
cfa437 |
} else {
|
|
Packit |
cfa437 |
return cac_aca_get_acr_response_extended(card, Le, acrid);
|
|
Packit |
cfa437 |
}
|
|
Packit |
cfa437 |
}
|
|
Packit |
cfa437 |
|
|
Packit |
cfa437 |
static VCardResponse *
|
|
Packit |
cfa437 |
cac_aca_get_applet_acr_response_simpletlv(VCard *card, int Le,
|
|
Packit |
cfa437 |
unsigned int pki_applets,
|
|
Packit |
cfa437 |
unsigned char *aid,
|
|
Packit |
cfa437 |
unsigned int aid_len,
|
|
Packit |
cfa437 |
unsigned char *coid)
|
|
Packit |
cfa437 |
{
|
|
Packit |
cfa437 |
size_t acr_buffer_len;
|
|
Packit |
cfa437 |
unsigned char *acr_buffer = NULL;
|
|
Packit |
cfa437 |
size_t properties_len;
|
|
Packit |
cfa437 |
const struct simpletlv_member *properties;
|
|
Packit |
cfa437 |
size_t acr_len = 0;
|
|
Packit |
cfa437 |
struct simpletlv_member *acr = NULL;
|
|
Packit |
cfa437 |
size_t list_len;
|
|
Packit |
cfa437 |
struct simpletlv_member *list = NULL;
|
|
Packit |
cfa437 |
VCardResponse *r = NULL;
|
|
Packit |
cfa437 |
|
|
Packit |
cfa437 |
/* Prepare the SimpleTLV structures */
|
|
Packit |
cfa437 |
properties = cac_aca_get_properties(&properties_len);
|
|
Packit |
cfa437 |
if (coid != NULL) {
|
|
Packit |
cfa437 |
g_debug("%s: Called. COID = %s", __func__, hex_dump(coid, 2, NULL, 0));
|
|
Packit |
cfa437 |
|
|
Packit |
cfa437 |
/* getting the table for Card Object ID (2B) */
|
|
Packit |
cfa437 |
acr_len = 1; // returns exactly one element if found
|
|
Packit |
cfa437 |
acr = cac_aca_get_applet_acr_coid(pki_applets, coid);
|
|
Packit |
cfa437 |
if (!acr) {
|
|
Packit |
cfa437 |
/* did not find the COID */
|
|
Packit |
cfa437 |
r = vcard_make_response(VCARD7816_STATUS_ERROR_WRONG_PARAMETERS_IN_DATA);
|
|
Packit |
cfa437 |
return r;
|
|
Packit |
cfa437 |
}
|
|
Packit |
cfa437 |
} else {
|
|
Packit |
cfa437 |
/* getting the table for AID or the whole */
|
|
Packit |
cfa437 |
acr = cac_aca_get_applet_acr(pki_applets, &acr_len, aid, aid_len);
|
|
Packit |
cfa437 |
if (!acr && aid_len > 0) {
|
|
Packit |
cfa437 |
/* did not find the AID */
|
|
Packit |
cfa437 |
r = vcard_make_response(VCARD7816_STATUS_ERROR_DATA_NOT_FOUND);
|
|
Packit |
cfa437 |
return r;
|
|
Packit |
cfa437 |
}
|
|
Packit |
cfa437 |
if (acr == NULL)
|
|
Packit |
cfa437 |
goto failure;
|
|
Packit |
cfa437 |
}
|
|
Packit |
cfa437 |
|
|
Packit |
cfa437 |
/* Merge them together */
|
|
Packit |
cfa437 |
list_len = properties_len + acr_len;
|
|
Packit |
cfa437 |
list = simpletlv_merge(properties, properties_len, acr, acr_len);
|
|
Packit |
cfa437 |
if (list == NULL)
|
|
Packit |
cfa437 |
goto failure;
|
|
Packit |
cfa437 |
|
|
Packit |
cfa437 |
/* encode the data */
|
|
Packit |
cfa437 |
acr_buffer_len = simpletlv_encode(list, list_len, &acr_buffer, 0, NULL);
|
|
Packit |
cfa437 |
if (acr_buffer == NULL)
|
|
Packit |
cfa437 |
goto failure;
|
|
Packit |
cfa437 |
|
|
Packit |
cfa437 |
r = vcard_response_new(card, acr_buffer, acr_buffer_len, Le,
|
|
Packit |
cfa437 |
VCARD7816_STATUS_SUCCESS);
|
|
Packit |
cfa437 |
g_debug("%s: response bytes: %s", __func__,
|
|
Packit |
cfa437 |
hex_dump(acr_buffer, acr_buffer_len, NULL, 0));
|
|
Packit |
cfa437 |
|
|
Packit |
cfa437 |
failure:
|
|
Packit |
cfa437 |
g_free(list);
|
|
Packit |
cfa437 |
simpletlv_free(acr, acr_len);
|
|
Packit |
cfa437 |
g_free(acr_buffer);
|
|
Packit |
cfa437 |
if (r == NULL)
|
|
Packit |
cfa437 |
r = vcard_make_response(VCARD7816_STATUS_ERROR_GENERAL);
|
|
Packit |
cfa437 |
return r;
|
|
Packit |
cfa437 |
}
|
|
Packit |
cfa437 |
|
|
Packit |
cfa437 |
/*
|
|
Packit |
cfa437 |
* This is Applet/Object ACR Table in undocumented compressed format.
|
|
Packit |
cfa437 |
*
|
|
Packit |
cfa437 |
* Len
|
|
Packit |
cfa437 |
* | Applet Id
|
|
Packit |
cfa437 |
* | | Num Objects
|
|
Packit |
cfa437 |
* | | | Len [OID] INS+Config+ACRID
|
|
Packit |
cfa437 |
* 1C 1F 01
|
|
Packit |
cfa437 |
* 19 FF FF
|
|
Packit |
cfa437 |
* 26 80 00
|
|
Packit |
cfa437 |
* 2C 80 04
|
|
Packit |
cfa437 |
* 24 81 80 04
|
|
Packit |
cfa437 |
* 24 81 01 00
|
|
Packit |
cfa437 |
* 24 80 06
|
|
Packit |
cfa437 |
* 20 00 00
|
|
Packit |
cfa437 |
* D8 80 04
|
|
Packit |
cfa437 |
* 24 4F 02
|
|
Packit |
cfa437 |
* 08 DB 00
|
|
Packit |
cfa437 |
* 58 00 04
|
|
Packit |
cfa437 |
* 52 00 00
|
|
Packit |
cfa437 |
* 18 FF FF
|
|
Packit |
cfa437 |
* 82 01 00 11
|
|
Packit |
cfa437 |
* 50 80 02
|
|
Packit |
cfa437 |
* 82 80 02
|
|
Packit |
cfa437 |
* F0 80 04
|
|
Packit |
cfa437 |
* 34 80 04
|
|
Packit |
cfa437 |
* 84 00 11
|
|
Packit |
cfa437 |
* 20 00 10
|
|
Packit |
cfa437 |
* [...]
|
|
Packit |
cfa437 |
*/
|
|
Packit |
cfa437 |
static VCardResponse *
|
|
Packit |
cfa437 |
cac_aca_get_applet_acr_response_extended(VCard *card, int Le,
|
|
Packit |
cfa437 |
unsigned int pki_applets,
|
|
Packit |
cfa437 |
unsigned char *aid,
|
|
Packit |
cfa437 |
unsigned int aid_len,
|
|
Packit |
cfa437 |
unsigned char *coid)
|
|
Packit |
cfa437 |
{
|
|
Packit |
cfa437 |
size_t buffer_len, i, j, plen;
|
|
Packit |
cfa437 |
unsigned char *buffer = NULL, *p;
|
|
Packit |
cfa437 |
VCardResponse *r = NULL;
|
|
Packit |
cfa437 |
unsigned int num_applets = applets_table.num_static_applets + pki_applets;
|
|
Packit |
cfa437 |
|
|
Packit |
cfa437 |
buffer_len = num_applets * (3 + ACR_MAX_APPLET_OBJECTS
|
|
Packit |
cfa437 |
* ( 3 + ACR_MAX_INSTRUCTIONS * 6));
|
|
Packit |
cfa437 |
buffer = g_malloc_n(buffer_len, sizeof(unsigned char));
|
|
Packit |
cfa437 |
p = buffer;
|
|
Packit |
cfa437 |
plen = buffer_len;
|
|
Packit |
cfa437 |
|
|
Packit |
cfa437 |
for (i = 0; i < applets_table.num_applets; i++) {
|
|
Packit |
cfa437 |
struct acr_applet *a;
|
|
Packit |
cfa437 |
unsigned char *len;
|
|
Packit |
cfa437 |
/* Skip unused PKI applets */
|
|
Packit |
cfa437 |
if (i >= pki_applets && i < 10)
|
|
Packit |
cfa437 |
continue;
|
|
Packit |
cfa437 |
|
|
Packit |
cfa437 |
a = &applets_table.applets[i];
|
|
Packit |
cfa437 |
if (plen < 3)
|
|
Packit |
cfa437 |
goto failure;
|
|
Packit |
cfa437 |
len = p++; /* here we will store the length later */
|
|
Packit |
cfa437 |
*p++ = a->id;
|
|
Packit |
cfa437 |
*p++ = a->num_objects;
|
|
Packit |
cfa437 |
plen -= 3;
|
|
Packit |
cfa437 |
for (j = 0; j < a->num_objects; j++) {
|
|
Packit |
cfa437 |
struct acr_object *o = &a->objects[j];
|
|
Packit |
cfa437 |
unsigned char *len2;
|
|
Packit |
cfa437 |
unsigned int olen;
|
|
Packit |
cfa437 |
|
|
Packit |
cfa437 |
len2 = p++; /* here we will store the length later */
|
|
Packit |
cfa437 |
/* the encoding from here on is the same as in specification */
|
|
Packit |
cfa437 |
p = acr_applet_object_encode(o, p, plen, &olen);
|
|
Packit |
cfa437 |
if (!p)
|
|
Packit |
cfa437 |
goto failure;
|
|
Packit |
cfa437 |
plen -= olen;
|
|
Packit |
cfa437 |
*len2 = olen;
|
|
Packit |
cfa437 |
}
|
|
Packit |
cfa437 |
*len = (p - len - 1);
|
|
Packit |
cfa437 |
}
|
|
Packit |
cfa437 |
g_assert((unsigned long)(p - buffer) <= buffer_len);
|
|
Packit |
cfa437 |
buffer_len = (p - buffer);
|
|
Packit |
cfa437 |
|
|
Packit |
cfa437 |
r = vcard_response_new(card, buffer, buffer_len, Le,
|
|
Packit |
cfa437 |
VCARD7816_STATUS_SUCCESS);
|
|
Packit |
cfa437 |
g_debug("%s: response bytes: %s", __func__,
|
|
Packit |
cfa437 |
hex_dump(buffer, buffer_len, NULL, 0));
|
|
Packit |
cfa437 |
failure:
|
|
Packit |
cfa437 |
g_free(buffer);
|
|
Packit |
cfa437 |
return r;
|
|
Packit |
cfa437 |
}
|
|
Packit |
cfa437 |
|
|
Packit |
cfa437 |
VCardResponse *
|
|
Packit |
cfa437 |
cac_aca_get_applet_acr_response(VCard *card, int Le, unsigned int pki_applets,
|
|
Packit |
cfa437 |
unsigned char *aid, unsigned int aid_len,
|
|
Packit |
cfa437 |
unsigned char *coid, int format)
|
|
Packit |
cfa437 |
{
|
|
Packit |
cfa437 |
if (format == CAC_FORMAT_SIMPLETLV) {
|
|
Packit |
cfa437 |
return cac_aca_get_applet_acr_response_simpletlv(card, Le,
|
|
Packit |
cfa437 |
pki_applets, aid, aid_len, coid);
|
|
Packit |
cfa437 |
} else {
|
|
Packit |
cfa437 |
return cac_aca_get_applet_acr_response_extended(card, Le,
|
|
Packit |
cfa437 |
pki_applets, aid, aid_len, coid);
|
|
Packit |
cfa437 |
}
|
|
Packit |
cfa437 |
}
|
|
Packit |
cfa437 |
|
|
Packit |
cfa437 |
|
|
Packit |
cfa437 |
static VCardResponse *
|
|
Packit |
cfa437 |
cac_aca_get_amp_response_simpletlv(VCard *card, int Le)
|
|
Packit |
cfa437 |
{
|
|
Packit |
cfa437 |
size_t amp_buffer_len;
|
|
Packit |
cfa437 |
unsigned char *amp_buffer = NULL;
|
|
Packit |
cfa437 |
size_t properties_len;
|
|
Packit |
cfa437 |
const struct simpletlv_member *properties;
|
|
Packit |
cfa437 |
size_t amp_len = 0;
|
|
Packit |
cfa437 |
struct simpletlv_member *amp = NULL;
|
|
Packit |
cfa437 |
size_t list_len;
|
|
Packit |
cfa437 |
struct simpletlv_member *list = NULL;
|
|
Packit |
cfa437 |
VCardResponse *r = NULL;
|
|
Packit |
cfa437 |
|
|
Packit |
cfa437 |
/* Prepare the SimpleTLV structures */
|
|
Packit |
cfa437 |
properties = cac_aca_get_properties(&properties_len);
|
|
Packit |
cfa437 |
amp = cac_aca_get_amp(&_len);
|
|
Packit |
cfa437 |
if (amp == NULL)
|
|
Packit |
cfa437 |
goto failure;
|
|
Packit |
cfa437 |
|
|
Packit |
cfa437 |
/* Merge them together */
|
|
Packit |
cfa437 |
list_len = properties_len + amp_len;
|
|
Packit |
cfa437 |
list = simpletlv_merge(properties, properties_len, amp, amp_len);
|
|
Packit |
cfa437 |
if (list == NULL)
|
|
Packit |
cfa437 |
goto failure;
|
|
Packit |
cfa437 |
|
|
Packit |
cfa437 |
/* encode the data */
|
|
Packit |
cfa437 |
amp_buffer_len = simpletlv_encode(list, list_len, &_buffer, 0, NULL);
|
|
Packit |
cfa437 |
if (amp_buffer == NULL)
|
|
Packit |
cfa437 |
goto failure;
|
|
Packit |
cfa437 |
|
|
Packit |
cfa437 |
r = vcard_response_new(card, amp_buffer, amp_buffer_len, Le,
|
|
Packit |
cfa437 |
VCARD7816_STATUS_SUCCESS);
|
|
Packit |
cfa437 |
|
|
Packit |
cfa437 |
failure:
|
|
Packit |
cfa437 |
g_free(list);
|
|
Packit |
cfa437 |
simpletlv_free(amp, amp_len);
|
|
Packit |
cfa437 |
g_free(amp_buffer);
|
|
Packit |
cfa437 |
if (r == NULL)
|
|
Packit |
cfa437 |
r = vcard_make_response(VCARD7816_STATUS_ERROR_GENERAL);
|
|
Packit |
cfa437 |
return r;
|
|
Packit |
cfa437 |
}
|
|
Packit |
cfa437 |
|
|
Packit |
cfa437 |
VCardResponse *
|
|
Packit |
cfa437 |
cac_aca_get_amp_response(VCard *card, int Le, int format)
|
|
Packit |
cfa437 |
{
|
|
Packit |
cfa437 |
if (format == CAC_FORMAT_SIMPLETLV) {
|
|
Packit |
cfa437 |
return cac_aca_get_amp_response_simpletlv(card, Le);
|
|
Packit |
cfa437 |
} else {
|
|
Packit |
cfa437 |
/* 1F 00 07 A0 00 00 00 79 03 00 12 00 00 00
|
|
Packit |
cfa437 |
* 1E 00 07 A0 00 00 00 79 03 00 10 01 00 00
|
|
Packit |
cfa437 |
* 1D 00 07 A0 00 00 00 79 03 00 01 00 00 00
|
|
Packit |
cfa437 |
* LEN [ AID ] [OID]
|
|
Packit |
cfa437 |
*/
|
|
Packit |
cfa437 |
return vcard_response_new(card, amp_table_extended,
|
|
Packit |
cfa437 |
sizeof(amp_table_extended), Le, VCARD7816_STATUS_SUCCESS);
|
|
Packit |
cfa437 |
}
|
|
Packit |
cfa437 |
}
|
|
Packit |
cfa437 |
|
|
Packit |
cfa437 |
/*
|
|
Packit |
cfa437 |
* This is Service Applet table in undocumented compressed format
|
|
Packit |
cfa437 |
*
|
|
Packit |
cfa437 |
* Applet ID
|
|
Packit |
cfa437 |
* | Len [ AID ]
|
|
Packit |
cfa437 |
* 40 00 07 A0 00 00 01 16 30 00
|
|
Packit |
cfa437 |
* 4F 00 07 A0 00 00 01 16 DB 00
|
|
Packit |
cfa437 |
* 4B 00 07 A0 00 00 00 79 02 FB
|
|
Packit |
cfa437 |
* 41 00 07 A0 00 00 00 79 02 00
|
|
Packit |
cfa437 |
* 42 00 07 A0 00 00 00 79 02 01
|
|
Packit |
cfa437 |
* 4E 00 07 A0 00 00 00 79 02 FE
|
|
Packit |
cfa437 |
* 4D 00 07 A0 00 00 00 79 02 FD
|
|
Packit |
cfa437 |
* 50 00 07 A0 00 00 00 79 02 F2
|
|
Packit |
cfa437 |
* 63 00 07 A0 00 00 00 79 01 02
|
|
Packit |
cfa437 |
* 51 00 07 A0 00 00 00 79 02 F0
|
|
Packit |
cfa437 |
* 61 00 07 A0 00 00 00 79 01 00
|
|
Packit |
cfa437 |
* 52 00 07 A0 00 00 00 79 02 F1
|
|
Packit |
cfa437 |
* 62 00 07 A0 00 00 00 79 01 01
|
|
Packit |
cfa437 |
* 44 00 07 A0 00 00 00 79 12 01
|
|
Packit |
cfa437 |
* 45 00 07 A0 00 00 00 79 12 02
|
|
Packit |
cfa437 |
*/
|
|
Packit |
cfa437 |
static VCardResponse *
|
|
Packit |
cfa437 |
cac_aca_get_service_response_extended(VCard *card, int Le,
|
|
Packit |
cfa437 |
unsigned int pki_applets)
|
|
Packit |
cfa437 |
{
|
|
Packit |
cfa437 |
size_t buffer_len;
|
|
Packit |
cfa437 |
unsigned char *buffer = NULL, *p;
|
|
Packit |
cfa437 |
VCardResponse *r = NULL;
|
|
Packit |
cfa437 |
size_t num_entries, i;
|
|
Packit |
cfa437 |
|
|
Packit |
cfa437 |
num_entries = service_table.num_static_entries + pki_applets;
|
|
Packit |
cfa437 |
|
|
Packit |
cfa437 |
buffer_len = num_entries * (3 + MAX_AID_LEN);
|
|
Packit |
cfa437 |
buffer = g_malloc(buffer_len);
|
|
Packit |
cfa437 |
p = buffer;
|
|
Packit |
cfa437 |
|
|
Packit |
cfa437 |
for (i = 0; i < service_table.num_entries; i++) {
|
|
Packit |
cfa437 |
struct applet_entry *e;
|
|
Packit |
cfa437 |
/* Skip unused PKI applets */
|
|
Packit |
cfa437 |
if (i >= pki_applets && i < 10)
|
|
Packit |
cfa437 |
continue;
|
|
Packit |
cfa437 |
|
|
Packit |
cfa437 |
e = &service_table.entries[i];
|
|
Packit |
cfa437 |
*p++ = e->applet_id;
|
|
Packit |
cfa437 |
*p++ = 0;
|
|
Packit |
cfa437 |
*p++ = e->applet_aid_len;
|
|
Packit |
cfa437 |
memcpy(p, e->applet_aid, e->applet_aid_len);
|
|
Packit |
cfa437 |
p += e->applet_aid_len;
|
|
Packit |
cfa437 |
}
|
|
Packit |
cfa437 |
g_assert((unsigned long)(p - buffer) <= buffer_len);
|
|
Packit |
cfa437 |
buffer_len = (p - buffer);
|
|
Packit |
cfa437 |
|
|
Packit |
cfa437 |
r = vcard_response_new(card, buffer, buffer_len, Le,
|
|
Packit |
cfa437 |
VCARD7816_STATUS_SUCCESS);
|
|
Packit |
cfa437 |
g_debug("%s: response bytes: %s", __func__,
|
|
Packit |
cfa437 |
hex_dump(buffer, buffer_len, NULL, 0));
|
|
Packit |
cfa437 |
g_free(buffer);
|
|
Packit |
cfa437 |
return r;
|
|
Packit |
cfa437 |
}
|
|
Packit |
cfa437 |
|
|
Packit |
cfa437 |
static VCardResponse *
|
|
Packit |
cfa437 |
cac_aca_get_service_response_simpletlv(VCard *card, int Le,
|
|
Packit |
cfa437 |
unsigned int pki_applets)
|
|
Packit |
cfa437 |
{
|
|
Packit |
cfa437 |
size_t service_buffer_len;
|
|
Packit |
cfa437 |
unsigned char *service_buffer = NULL;
|
|
Packit |
cfa437 |
size_t properties_len;
|
|
Packit |
cfa437 |
const struct simpletlv_member *properties;
|
|
Packit |
cfa437 |
size_t service_len = 0;
|
|
Packit |
cfa437 |
struct simpletlv_member *service = NULL;
|
|
Packit |
cfa437 |
size_t list_len;
|
|
Packit |
cfa437 |
struct simpletlv_member *list = NULL;
|
|
Packit |
cfa437 |
VCardResponse *r = NULL;
|
|
Packit |
cfa437 |
|
|
Packit |
cfa437 |
/* Prepare the SimpleTLV structures */
|
|
Packit |
cfa437 |
properties = cac_aca_get_properties(&properties_len);
|
|
Packit |
cfa437 |
service = cac_aca_get_service_table(&service_len, pki_applets);
|
|
Packit |
cfa437 |
if (service == NULL)
|
|
Packit |
cfa437 |
goto failure;
|
|
Packit |
cfa437 |
|
|
Packit |
cfa437 |
/* Merge them together */
|
|
Packit |
cfa437 |
list_len = properties_len + service_len;
|
|
Packit |
cfa437 |
list = simpletlv_merge(properties, properties_len, service, service_len);
|
|
Packit |
cfa437 |
if (list == NULL)
|
|
Packit |
cfa437 |
goto failure;
|
|
Packit |
cfa437 |
|
|
Packit |
cfa437 |
/* encode the data */
|
|
Packit |
cfa437 |
service_buffer_len = simpletlv_encode(list, list_len, &service_buffer, 0, NULL);
|
|
Packit |
cfa437 |
if (service_buffer == NULL)
|
|
Packit |
cfa437 |
goto failure;
|
|
Packit |
cfa437 |
|
|
Packit |
cfa437 |
r = vcard_response_new(card, service_buffer, service_buffer_len, Le,
|
|
Packit |
cfa437 |
VCARD7816_STATUS_SUCCESS);
|
|
Packit |
cfa437 |
|
|
Packit |
cfa437 |
failure:
|
|
Packit |
cfa437 |
g_free(list);
|
|
Packit |
cfa437 |
simpletlv_free(service, service_len);
|
|
Packit |
cfa437 |
g_free(service_buffer);
|
|
Packit |
cfa437 |
if (r == NULL)
|
|
Packit |
cfa437 |
r = vcard_make_response(VCARD7816_STATUS_ERROR_GENERAL);
|
|
Packit |
cfa437 |
return r;
|
|
Packit |
cfa437 |
}
|
|
Packit |
cfa437 |
|
|
Packit |
cfa437 |
VCardResponse *
|
|
Packit |
cfa437 |
cac_aca_get_service_response(VCard *card, int Le,
|
|
Packit |
cfa437 |
unsigned int pki_applets, int format)
|
|
Packit |
cfa437 |
{
|
|
Packit |
cfa437 |
if (format == CAC_FORMAT_SIMPLETLV) {
|
|
Packit |
cfa437 |
return cac_aca_get_service_response_simpletlv(card, Le, pki_applets);
|
|
Packit |
cfa437 |
} else {
|
|
Packit |
cfa437 |
return cac_aca_get_service_response_extended(card, Le, pki_applets);
|
|
Packit |
cfa437 |
}
|
|
Packit |
cfa437 |
}
|
|
Packit |
cfa437 |
|
|
Packit |
cfa437 |
/* vim: set ts=4 sw=4 tw=0 noet expandtab: */
|