Blame src/cac-aca.c

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 *) &amp_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(&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, &amp_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: */