mirror of https://gerrit.osmocom.org/libosmocore
sim: add class_tables / card profiles
The tables permit code to determine the APDU class of an APDU based on it APDU/TPDU header (CLA/INS/P1/P2/P3).
This commit is contained in:
parent
2c34ab4a80
commit
4acaa13433
|
@ -92,6 +92,7 @@ nobase_include_HEADERS = \
|
|||
osmocom/gsm/rxlev_stat.h \
|
||||
osmocom/gsm/sysinfo.h \
|
||||
osmocom/gsm/tlv.h \
|
||||
osmocom/sim/class_tables.h \
|
||||
osmocom/sim/sim.h
|
||||
|
||||
if ENABLE_PLUGIN
|
||||
|
|
|
@ -0,0 +1,42 @@
|
|||
#pragma once
|
||||
|
||||
/* simtrace - tables determining APDU case for card emulation
|
||||
*
|
||||
* (C) 2016 by Harald Welte <laforge@gnumonks.org>
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License version 2, or
|
||||
* any later version as published by the Free Software Foundation.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*/
|
||||
|
||||
#include <stdint.h>
|
||||
|
||||
struct osim_cla_ins_case {
|
||||
uint8_t cla;
|
||||
uint8_t cla_mask;
|
||||
int (*helper)(const struct osim_cla_ins_case *cic, const uint8_t *hdr);
|
||||
const uint8_t *ins_tbl;
|
||||
};
|
||||
|
||||
struct osim_cla_ins_card_profile {
|
||||
const char *name;
|
||||
const char *description;
|
||||
const struct osim_cla_ins_case *cic_arr;
|
||||
unsigned int cic_arr_size;
|
||||
};
|
||||
|
||||
extern const struct osim_cla_ins_card_profile osim_iso7816_cic_profile;
|
||||
extern const struct osim_cla_ins_card_profile osim_uicc_cic_profile;
|
||||
extern const struct osim_cla_ins_card_profile osim_uicc_sim_cic_profile;
|
||||
|
||||
int osim_determine_apdu_case(const struct osim_cla_ins_card_profile *prof,
|
||||
const uint8_t *hdr);
|
|
@ -13,8 +13,9 @@ noinst_HEADERS = sim_int.h gsm_int.h
|
|||
|
||||
lib_LTLIBRARIES = libosmosim.la
|
||||
|
||||
libosmosim_la_SOURCES = core.c reader.c reader_pcsc.c \
|
||||
card_fs_sim.c card_fs_usim.c card_fs_uicc.c card_fs_isim.c card_fs_tetra.c
|
||||
libosmosim_la_SOURCES = core.c reader.c reader_pcsc.c class_tables.c \
|
||||
card_fs_sim.c card_fs_usim.c card_fs_uicc.c \
|
||||
card_fs_isim.c card_fs_tetra.c
|
||||
libosmosim_la_LDFLAGS = -version-info $(LIBVERSION)
|
||||
libosmosim_la_LIBADD = \
|
||||
$(top_builddir)/src/libosmocore.la \
|
||||
|
|
|
@ -0,0 +1,313 @@
|
|||
/* simtrace - tables determining APDU case for card emulation
|
||||
*
|
||||
* (C) 2016 by Harald Welte <laforge@gnumonks.org>
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License version 2, or
|
||||
* any later version as published by the Free Software Foundation.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*/
|
||||
|
||||
#include <stdint.h>
|
||||
#include <osmocom/core/utils.h>
|
||||
#include <osmocom/sim/class_tables.h>
|
||||
|
||||
static const uint8_t iso7816_ins_tbl[] = {
|
||||
[0xB0] = 2, /* READ BIN */
|
||||
[0xD0] = 3, /* WRITE BIN */
|
||||
[0xD6] = 3, /* UPDATE BIN */
|
||||
[0x0E] = 3, /* ERASE BIN */
|
||||
[0xB2] = 2, /* READ REC */
|
||||
[0xD2] = 3, /* WRITE REC */
|
||||
[0xE2] = 3, /* APPEND REC */
|
||||
[0xDC] = 3, /* UPDATE REC */
|
||||
[0xCA] = 2, /* GET DATA */
|
||||
[0xDA] = 3, /* PUT DATA */
|
||||
[0xA4] = 4, /* SELECT FILE */
|
||||
[0x20] = 3, /* VERIFY */
|
||||
[0x88] = 4, /* INT AUTH */
|
||||
[0x82] = 3, /* EXT AUTH */
|
||||
[0x84] = 2, /* GET CHALLENGE */
|
||||
[0x70] = 2, /* MANAGE CHANNEL */
|
||||
};
|
||||
|
||||
static const struct osim_cla_ins_case iso7816_4_ins_case[] = {
|
||||
{
|
||||
.cla = 0x00,
|
||||
.cla_mask = 0xF0,
|
||||
.ins_tbl = iso7816_ins_tbl,
|
||||
}, {
|
||||
.cla = 0x80, /* 0x80/0x90 */
|
||||
.cla_mask = 0xE0,
|
||||
.ins_tbl = iso7816_ins_tbl,
|
||||
}, {
|
||||
.cla = 0xB0,
|
||||
.cla_mask = 0xF0,
|
||||
.ins_tbl = iso7816_ins_tbl,
|
||||
}, {
|
||||
.cla = 0xC0,
|
||||
.cla_mask = 0xF0,
|
||||
.ins_tbl = iso7816_ins_tbl,
|
||||
},
|
||||
};
|
||||
|
||||
const struct osim_cla_ins_card_profile osim_iso7816_cic_profile = {
|
||||
.name = "ISO 7816-4",
|
||||
.description = "ISO 7816-4",
|
||||
.cic_arr = iso7816_4_ins_case,
|
||||
.cic_arr_size = ARRAY_SIZE(iso7816_4_ins_case),
|
||||
};
|
||||
|
||||
static const uint8_t gsm1111_ins_tbl[256] = {
|
||||
[0xA4] = 4, /* SELECT FILE */
|
||||
[0xF2] = 2, /* STATUS */
|
||||
[0xB0] = 2, /* READ BINARY */
|
||||
[0xD6] = 3, /* UPDATE BINARY */
|
||||
[0xB2] = 2, /* READ RECORD */
|
||||
[0xDC] = 3, /* UPDATE RECORD */
|
||||
[0xA2] = 4, /* SEEK */
|
||||
[0x32] = 4, /* INCREASE */
|
||||
[0x20] = 3, /* VERIFY CHV */
|
||||
[0x24] = 3, /* CHANGE CHV */
|
||||
[0x26] = 3, /* DISABLE CHV */
|
||||
[0x28] = 3, /* ENABLE CHV */
|
||||
[0x2C] = 3, /* UNBLOCK CHV */
|
||||
[0x04] = 1, /* INVALIDATE */
|
||||
[0x44] = 1, /* REHABILITATE */
|
||||
[0x88] = 4, /* RUN GSM ALGO */
|
||||
[0xFA] = 1, /* SLEEP */
|
||||
[0xC0] = 2, /* GET RESPONSE */
|
||||
[0x10] = 3, /* TERMINAL PROFILE */
|
||||
[0xC2] = 4, /* ENVELOPE */
|
||||
[0x12] = 2, /* FETCH */
|
||||
[0x14] = 3, /* TERMINAL RESPONSE */
|
||||
};
|
||||
|
||||
/* According to Table 9 / Section 9.2 of TS 11.11 */
|
||||
static const struct osim_cla_ins_case gsm1111_ins_case[] = {
|
||||
{
|
||||
.cla = 0xA0,
|
||||
.cla_mask = 0xFF,
|
||||
.ins_tbl = gsm1111_ins_tbl,
|
||||
},
|
||||
};
|
||||
|
||||
const struct osim_cla_ins_card_profile osim_gsm1111_cic_profile = {
|
||||
.name = "GSM SIM",
|
||||
.description = "GSM/3GPP TS 11.11",
|
||||
.cic_arr = gsm1111_ins_case,
|
||||
.cic_arr_size = ARRAY_SIZE(gsm1111_ins_case),
|
||||
};
|
||||
|
||||
/* ETSI TS 102 221, Table 10.5, CLA = 0x0x, 0x4x or 0x6x */
|
||||
static const uint8_t uicc_ins_tbl_046[256] = {
|
||||
[0xA4] = 4, /* SELET FILE */
|
||||
[0xB0] = 2, /* READ BINARY */
|
||||
[0xD6] = 3, /* UPDATE BINARY */
|
||||
[0xB2] = 2, /* READ RECORD */
|
||||
[0xDC] = 3, /* UPDATE RECORD */
|
||||
[0xA2] = 4, /* SEEK */
|
||||
[0x20] = 3, /* VERIFY PIN */
|
||||
[0x24] = 3, /* CHANGE PIN */
|
||||
[0x26] = 3, /* DISABLE PIN */
|
||||
[0x28] = 3, /* ENABLE PIN */
|
||||
[0x2C] = 3, /* UNBLOCK PIN */
|
||||
[0x04] = 1, /* DEACTIVATE FILE */
|
||||
[0x44] = 1, /* ACTIVATE FILE */
|
||||
[0x88] = 4, /* AUTHENTICATE */
|
||||
[0x89] = 4, /* AUTHENTICATE */
|
||||
[0x84] = 2, /* GET CHALLENGE */
|
||||
[0x70] = 2, /* MANAGE CHANNEL */
|
||||
[0x73] = 0x80, /* MANAGE SECURE CHANNEL */
|
||||
[0x75] = 0x80, /* TRANSACT DATA */
|
||||
[0xC0] = 2, /* GET RESPONSE */
|
||||
};
|
||||
|
||||
static int uicc046_cla_ins_helper(const struct osim_cla_ins_case *cic,
|
||||
const uint8_t *hdr)
|
||||
{
|
||||
uint8_t ins = hdr[1];
|
||||
uint8_t p1 = hdr[2];
|
||||
uint8_t p2 = hdr[3];
|
||||
uint8_t p2_cmd;
|
||||
|
||||
switch (ins) {
|
||||
case 0x73: /* MANAGE SECURE CHANNEL */
|
||||
if (p1 == 0x00) /* Retrieve UICC Endpoints */
|
||||
return 2;
|
||||
switch (p1 & 0x07) {
|
||||
case 1: /* Establish SA - Master SA */
|
||||
case 2: /* Establish SA - Conn. SA */
|
||||
case 3: /* Start secure channel SA */
|
||||
p2_cmd = p2 >> 5;
|
||||
if (p2 == 0x80 || p2_cmd == 0) {
|
||||
/* command data */
|
||||
return 3;
|
||||
}
|
||||
if (p2_cmd == 5 || p2_cmd == 1) {
|
||||
/* response data */
|
||||
return 2;
|
||||
}
|
||||
return 0;
|
||||
break;
|
||||
case 4: /* Terminate secure chan SA */
|
||||
return 3;
|
||||
break;
|
||||
}
|
||||
break;
|
||||
case 0x75: /* TRANSACT DATA */
|
||||
if (p1 & 0x04)
|
||||
return 3;
|
||||
else
|
||||
return 2;
|
||||
break;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* ETSI TS 102 221, Table 10.5, CLA = 0x8x, 0xCx or 0xEx */
|
||||
static const uint8_t uicc_ins_tbl_8ce[256] = {
|
||||
[0xF2] = 2, /* STATUS */
|
||||
[0x32] = 4, /* INCREASE */
|
||||
[0xCB] = 4, /* RETRIEVE DATA */
|
||||
[0xDB] = 3, /* SET DATA */
|
||||
[0xAA] = 3, /* TERMINAL CAPABILITY */
|
||||
};
|
||||
|
||||
/* ETSI TS 102 221, Table 10.5, CLA = 0x80 */
|
||||
static const uint8_t uicc_ins_tbl_80[256] = {
|
||||
[0x10] = 3, /* TERMINAL PROFILE */
|
||||
[0xC2] = 4, /* ENVELOPE */
|
||||
[0x12] = 2, /* FETCH */
|
||||
[0x14] = 3, /* TERMINAL RESPONSE */
|
||||
};
|
||||
|
||||
static const struct osim_cla_ins_case uicc_ins_case[] = {
|
||||
{
|
||||
.cla = 0x80,
|
||||
.cla_mask = 0xFF,
|
||||
.ins_tbl = uicc_ins_tbl_80,
|
||||
}, {
|
||||
.cla = 0x00,
|
||||
.cla_mask = 0xF0,
|
||||
.helper = uicc046_cla_ins_helper,
|
||||
.ins_tbl = uicc_ins_tbl_046,
|
||||
}, {
|
||||
.cla = 0x40,
|
||||
.cla_mask = 0xF0,
|
||||
.helper = uicc046_cla_ins_helper,
|
||||
.ins_tbl = uicc_ins_tbl_046,
|
||||
}, {
|
||||
.cla = 0x60,
|
||||
.cla_mask = 0xF0,
|
||||
.helper = uicc046_cla_ins_helper,
|
||||
.ins_tbl = uicc_ins_tbl_046,
|
||||
}, {
|
||||
.cla = 0x80,
|
||||
.cla_mask = 0xF0,
|
||||
.ins_tbl = uicc_ins_tbl_8ce,
|
||||
}, {
|
||||
.cla = 0xC0,
|
||||
.cla_mask = 0xF0,
|
||||
.ins_tbl = uicc_ins_tbl_8ce,
|
||||
}, {
|
||||
.cla = 0xE0,
|
||||
.cla_mask = 0xF0,
|
||||
.ins_tbl = uicc_ins_tbl_8ce,
|
||||
},
|
||||
};
|
||||
|
||||
const struct osim_cla_ins_card_profile osim_uicc_cic_profile = {
|
||||
.name = "UICC",
|
||||
.description = "TS 102 221 / 3GPP TS 31.102",
|
||||
.cic_arr = uicc_ins_case,
|
||||
.cic_arr_size = ARRAY_SIZE(uicc_ins_case),
|
||||
};
|
||||
|
||||
|
||||
static const struct osim_cla_ins_case uicc_sim_ins_case[] = {
|
||||
{
|
||||
.cla = 0xA0,
|
||||
.cla_mask = 0xFF,
|
||||
.ins_tbl = gsm1111_ins_tbl,
|
||||
}, {
|
||||
.cla = 0x80,
|
||||
.cla_mask = 0xFF,
|
||||
.ins_tbl = uicc_ins_tbl_80,
|
||||
}, {
|
||||
.cla = 0x00,
|
||||
.cla_mask = 0xF0,
|
||||
.helper = uicc046_cla_ins_helper,
|
||||
.ins_tbl = uicc_ins_tbl_046,
|
||||
}, {
|
||||
.cla = 0x40,
|
||||
.cla_mask = 0xF0,
|
||||
.helper = uicc046_cla_ins_helper,
|
||||
.ins_tbl = uicc_ins_tbl_046,
|
||||
}, {
|
||||
.cla = 0x60,
|
||||
.cla_mask = 0xF0,
|
||||
.helper = uicc046_cla_ins_helper,
|
||||
.ins_tbl = uicc_ins_tbl_046,
|
||||
}, {
|
||||
.cla = 0x80,
|
||||
.cla_mask = 0xF0,
|
||||
.ins_tbl = uicc_ins_tbl_8ce,
|
||||
}, {
|
||||
.cla = 0xC0,
|
||||
.cla_mask = 0xF0,
|
||||
.ins_tbl = uicc_ins_tbl_8ce,
|
||||
}, {
|
||||
.cla = 0xE0,
|
||||
.cla_mask = 0xF0,
|
||||
.ins_tbl = uicc_ins_tbl_8ce,
|
||||
},
|
||||
};
|
||||
|
||||
const struct osim_cla_ins_card_profile osim_uicc_sim_cic_profile = {
|
||||
.name = "UICC+SIM",
|
||||
.description = "TS 102 221 / 3GPP TS 31.102 + GSM TS 11.11",
|
||||
.cic_arr = uicc_sim_ins_case,
|
||||
.cic_arr_size = ARRAY_SIZE(uicc_sim_ins_case),
|
||||
};
|
||||
|
||||
/* 3GPP TS 31.102 */
|
||||
const uint8_t usim_ins_case[256] = {
|
||||
[0x88] = 4, /* AUTHENTICATE */
|
||||
};
|
||||
|
||||
int osim_determine_apdu_case(const struct osim_cla_ins_card_profile *prof,
|
||||
const uint8_t *hdr)
|
||||
{
|
||||
uint8_t cla = hdr[0];
|
||||
uint8_t ins = hdr[1];
|
||||
int i;
|
||||
int rc;
|
||||
|
||||
for (i = 0; i < prof->cic_arr_size; i++) {
|
||||
const struct osim_cla_ins_case *cic = &prof->cic_arr[i];
|
||||
if ((cla & cic->cla_mask) != cic->cla)
|
||||
continue;
|
||||
rc = cic->ins_tbl[ins];
|
||||
switch (rc) {
|
||||
case 0x80:
|
||||
return cic->helper(cic, hdr);
|
||||
case 0x00:
|
||||
/* continue with fruther cic, rather than abort
|
||||
* now */
|
||||
continue;
|
||||
default:
|
||||
return rc;
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
Loading…
Reference in New Issue