blob: e415843e63c5f5a92e55d1bce71c78d5ce74e27d [file] [log] [blame]
Harald Welted54c2ee2012-01-17 18:25:50 +01001#ifndef _OSMOCOM_SIM_H
2#define _OSMOCOM_SIM_H
3
4#include <osmocom/core/msgb.h>
5#include <osmocom/core/linuxlist.h>
6
7#define APDU_HDR_LEN 5
8
Kevin Redon6956ee12012-09-11 11:42:29 +02009/* command-response pairs cases, as specified in ISO/IEC 7816-3:2006(E) §12.1 */
Harald Welted54c2ee2012-01-17 18:25:50 +010010enum osim_apdu_case {
Kevin Redon6956ee12012-09-11 11:42:29 +020011 APDU_CASE_1, /* command header, no command data field, no response data field */
Kevin Redone07967f2012-09-11 11:44:18 +020012 APDU_CASE_2S, /* command header, no command data field, response data field (short) */
13 APDU_CASE_2E, /* command header, no command data field, response data field (extended) */
14 APDU_CASE_3S, /* command header, command data field (short), no response data field */
15 APDU_CASE_3E, /* command header, command data field (extended), no response data field */
16 APDU_CASE_4S, /* command header, command data field (short), response data field (short) */
17 APDU_CASE_4E /* command header, command data field (extended), response data field (extended) */
Harald Welted54c2ee2012-01-17 18:25:50 +010018};
19
Kevin Redon17073062012-09-11 11:54:52 +020020/* command header, as specified in ISO/IEC 7816-3:2006(E) §12.2 */
Harald Welted54c2ee2012-01-17 18:25:50 +010021struct osim_apdu_cmd_hdr {
Kevin Redon17073062012-09-11 11:54:52 +020022 uint8_t cla; /* CLASS byte */
23 uint8_t ins; /* INSTRUCTION byte */
24 uint8_t p1; /* Parameter 1 byte */
25 uint8_t p2; /* Parameter 2 byte */
26 uint8_t p3; /* Parameter 3 byte, used for TPDU */
Harald Welted54c2ee2012-01-17 18:25:50 +010027} __attribute__ ((packed));
28
29#define msgb_apdu_dr(__x)
30
Kevin Redondede8312012-09-11 11:59:21 +020031/* command body, as specified in ISO/IEC 7816-3:2006(E) §12.1 */
Harald Welted54c2ee2012-01-17 18:25:50 +010032struct osim_msgb_cb {
Kevin Redondede8312012-09-11 11:59:21 +020033 enum osim_apdu_case apduc; /* command-response pairs case, defining the encoding of Lc and Le */
34 uint16_t lc; /* number of bytes in the command data field Nc, which will encoded in 0, 1 or 3 bytes into Lc */
35 uint16_t le; /* maximum number of bytes expected in the response data field, which will encoded in 0, 1, 2 or 3 bytes into Le */
36 uint16_t sw; /* status word, composed of SW1 and SW2 bytes */
Harald Welted54c2ee2012-01-17 18:25:50 +010037};
38#define OSIM_MSGB_CB(__msgb) ((struct osim_msgb_cb *)&((__msgb)->cb[0]))
39/*! \brief status word from msgb->cb */
40#define msgb_apdu_case(__x) OSIM_MSGB_CB(__x)->apduc
41#define msgb_apdu_lc(__x) OSIM_MSGB_CB(__x)->lc
42#define msgb_apdu_le(__x) OSIM_MSGB_CB(__x)->le
43#define msgb_apdu_sw(__x) OSIM_MSGB_CB(__x)->sw
44/*! \brief pointer to the command header of the APDU */
45#define msgb_apdu_h(__x) ((struct osim_apdu_cmd_hdr *)(__x)->l2h)
46
47#define msgb_apdu_dc(__x) ((__x)->l2h + sizeof(struct osim_apdu_cmd_hdr))
48#define msgb_apdu_de(__x) ((__x)->l2h + sizeof(struct osim_apdu_cmd_hdr) + msgb_apdu_lc(__x))
49
50struct osim_file;
51struct osim_file_desc;
52struct osim_decoded_data;
53
54struct osim_file_ops {
55 int (*parse)(struct osim_decoded_data *dd,
56 const struct osim_file_desc *desc,
57 int len, uint8_t *data);
58 struct msgb * (*encode)(const struct osim_file *file,
59 const struct osim_decoded_data *decoded);
60};
61
62enum osim_element_type {
63 ELEM_T_NONE,
64 ELEM_T_BOOL, /*!< a boolean flag */
65 ELEM_T_UINT8, /*!< unsigned integer */
66 ELEM_T_UINT16, /*!< unsigned integer */
67 ELEM_T_UINT32, /*!< unsigned integer */
68 ELEM_T_STRING, /*!< generic string */
69 ELEM_T_BCD, /*!< BCD encoded digits */
70 ELEM_T_BYTES, /*!< BCD encoded digits */
71 ELEM_T_GROUP, /*!< group container, has siblings */
72};
73
74enum osim_element_repr {
75 ELEM_REPR_NONE,
76 ELEM_REPR_DEC,
77 ELEM_REPR_HEX,
78};
79
80struct osim_decoded_element {
81 struct llist_head list;
82
83 enum osim_element_type type;
84 enum osim_element_repr representation;
85 const char *name;
86
87 unsigned int length;
88 union {
89 uint8_t u8;
90 uint16_t u16;
91 uint32_t u32;
92 uint8_t *buf;
93 struct llist_head siblings;
94 } u;
95};
96
97struct osim_decoded_data {
98 /*! file to which we belong */
99 const struct osim_file *file;
100 /*! list of 'struct decoded_element' */
101 struct llist_head decoded_elements;
102};
103
104
105enum osim_file_type {
106 TYPE_NONE,
107 TYPE_DF,
108 TYPE_ADF,
109 TYPE_EF,
110 TYPE_EF_INT,
111};
112
113enum osim_ef_type {
114 EF_TYPE_TRANSP,
115 EF_TYPE_RECORD_FIXED,
116 EF_TYPE_RECORD_CYCLIC,
117};
118
119#define F_OPTIONAL 0x0001
120
121struct osim_file_desc {
122 struct llist_head list; /*!< local element in list */
123 struct llist_head child_list; /*!< list of children EF in DF */
124 struct osim_file_desc *parent; /*!< parent DF */
125
126 enum osim_file_type type;
127 enum osim_ef_type ef_type;
128
129 uint16_t fid; /*!< File Identifier */
130 uint8_t sfid; /*!< Short File IDentifier */
131 const char *df_name;
132 uint8_t df_name_len;
133
134 const char *short_name; /*!< Short Name (like EF.ICCID) */
135 const char *long_name; /*!< Long / description */
136 unsigned int flags;
137
138 struct osim_file_ops ops;
139};
140
141struct osim_file {
142 const struct osim_file_desc *desc;
143
144 struct msgb *encoded_data;
145 struct osim_decoded_data *decoded_data;
146};
147
148#define EF(pfid, pns, pflags, pnl, ptype, pdec, penc) \
149 { \
150 .fid = pfid, \
151 .type = TYPE_EF, \
152 .ef_type = ptype, \
153 .short_name = pns, \
154 .long_name = pnl, \
155 .flags = pflags, \
156 .ops = { .encode = penc, .parse = pdec }, \
157 }
158
159
160#define EF_TRANSP(fid, ns, flags, nl, dec, enc) \
161 EF(fid, ns, flags, nl, EF_TYPE_TRANSP, dec, enc)
162#define EF_TRANSP_N(fid, ns, flags, nl) \
163 EF_TRANSP(fid, ns, flags, nl, &default_decode, NULL)
164
165#define EF_CYCLIC(fid, ns, flags, nl, dec, enc) \
166 EF(fid, ns, flags, nl, EF_TYPE_RECORD_CYCLIC, dec, enc)
167#define EF_CYCLIC_N(fid, ns, flags, nl) \
168 EF_CYCLIC(fid, ns, flags, nl, &default_decode, NULL)
169
170#define EF_LIN_FIX(fid, ns, flags, nl, dec, enc) \
171 EF(fid, ns, flags, nl, EF_TYPE_RECORD_FIXED, dec, enc)
172#define EF_LIN_FIX_N(fid, ns, flags, nl) \
173 EF_LIN_FIX(fid, ns, flags, nl, &default_decode, NULL)
174
175struct osim_file_desc *
176osim_file_find_name(struct osim_file_desc *parent, const char *name);
177
178enum osim_card_sw_type {
179 SW_TYPE_NONE,
180 SW_TYPE_STR,
181};
182
183enum osim_card_sw_class {
184 SW_CLS_NONE,
185 SW_CLS_OK,
186 SW_CLS_POSTP,
187 SW_CLS_WARN,
188 SW_CLS_ERROR,
189};
190
191struct osim_card_sw {
192 uint16_t code;
193 uint16_t mask;
194 enum osim_card_sw_type type;
195 enum osim_card_sw_class class;
196 union {
197 const char *str;
198 } u;
199};
200
201#define OSIM_CARD_SW_LAST { \
202 .code = 0, .mask = 0, .type = SW_TYPE_NONE, \
203 .class = SW_CLS_NONE, .u.str = NULL \
204}
205
206struct osim_card_profile {
207 const char *name;
208 struct osim_file_desc *mf;
209 struct osim_card_sw **sws;
210};
211
212extern const struct tlv_definition ts102221_fcp_tlv_def;
213const struct value_string ts102221_fcp_vals[14];
214
215/* 11.1.1.3 */
216enum ts102221_fcp_tag {
217 UICC_FCP_T_FCP = 0x62,
218 UICC_FCP_T_FILE_SIZE = 0x80,
219 UICC_FCP_T_TOT_F_SIZE = 0x81,
220 UICC_FCP_T_FILE_DESC = 0x82,
221 UICC_FCP_T_FILE_ID = 0x83,
222 UICC_FCP_T_DF_NAME = 0x84,
223 UICC_FCP_T_SFID = 0x88,
224 UICC_FCP_T_LIFEC_STS = 0x8A,
225 UICC_FCP_T_SEC_ATTR_REFEXP= 0x8B,
226 UICC_FCP_T_SEC_ATTR_COMP= 0x8C,
227 UICC_FCP_T_PROPRIETARY = 0xA5,
228 UICC_FCP_T_SEC_ATTR_EXP = 0xAB,
229 UICC_FCP_T_PIN_STS_DO = 0xC6,
230};
231
232struct msgb *osim_new_apdumsg(uint8_t cla, uint8_t ins, uint8_t p1,
233 uint8_t p2, uint16_t lc, uint16_t le);
234
235struct osim_reader_ops;
236
237struct osim_reader_hdl {
238 /*! \brief member in global list of readers */
239 struct llist_head list;
240 struct osim_reader_ops *ops;
241 void *priv;
242 /*! \brief current card, if any */
243 struct osim_card_hdl *card;
244};
245
246struct osim_card_hdl {
247 /*! \brief member in global list of cards */
248 struct llist_head list;
249 /*! \brief reader through which card is accessed */
250 struct osim_reader_hdl *reader;
251 /*! \brief card profile */
252 struct osim_card_profile *prof;
253
254 /*! \brief list of channels for this card */
255 struct llist_head channels;
256};
257
258struct osim_chan_hdl {
259 /*! \brief linked to card->channels */
260 struct llist_head list;
261 /*! \brief card to which this channel belongs */
262 struct osim_card_hdl *card;
263 const struct osim_file_desc *cwd;
264};
265
266/* reader.c */
267int osim_transceive_apdu(struct osim_chan_hdl *st, struct msgb *amsg);
268struct osim_reader_hdl *osim_reader_open(int idx, const char *name);
269struct osim_card_hdl *osim_card_open(struct osim_reader_hdl *rh);
270#endif /* _OSMOCOM_SIM_H */