1 /*
2 * pkcs15.c: PKCS #15 general functions
3 *
4 * Copyright (C) 2001, 2002 Juha Yrjölä <juha.yrjola@iki.fi>
5 *
6 * This library is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU Lesser General Public
8 * License as published by the Free Software Foundation; either
9 * version 2.1 of the License, or (at your option) any later version.
10 *
11 * This library is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 * Lesser General Public License for more details.
15 *
16 * You should have received a copy of the GNU Lesser General Public
17 * License along with this library; if not, write to the Free Software
18 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
19 */
20
21 #ifdef HAVE_CONFIG_H
22 #include <config.h>
23 #endif
24
25 #include <stdlib.h>
26 #include <string.h>
27 #include <stdio.h>
28 #include <assert.h>
29 #include <ctype.h>
30
31 #include "cardctl.h"
32 #include "internal.h"
33 #include "pkcs15.h"
34 #include "asn1.h"
35 #include "common/libscdl.h"
36
37 #ifdef ENABLE_OPENSSL
38 #include <openssl/sha.h>
39 #endif
40
41 #ifdef HAVE_SYS_TIME_H
42 #include <sys/time.h>
43 #endif
44
45 static const struct sc_asn1_entry c_asn1_twlabel[] = {
46 { "twlabel", SC_ASN1_UTF8STRING, SC_ASN1_TAG_UTF8STRING, 0, NULL, NULL },
47 { NULL, 0, 0, 0, NULL, NULL }
48 };
49
50 static const struct sc_asn1_entry c_asn1_algorithm_info[7] = {
51 { "reference", SC_ASN1_INTEGER, SC_ASN1_TAG_INTEGER, 0, NULL, NULL },
52 { "algorithmPKCS#11", SC_ASN1_INTEGER, SC_ASN1_TAG_INTEGER, 0, NULL, NULL },
53 { "parameters", SC_ASN1_CHOICE, 0, 0, NULL, NULL },
54 { "supportedOperations",SC_ASN1_BIT_FIELD, SC_ASN1_TAG_BIT_STRING, 0, NULL, NULL },
55 { "objId", SC_ASN1_OBJECT, SC_ASN1_TAG_OBJECT, SC_ASN1_OPTIONAL, NULL, NULL },
56 { "algRef", SC_ASN1_INTEGER, SC_ASN1_TAG_INTEGER, SC_ASN1_OPTIONAL, NULL, NULL },
57 { NULL, 0, 0, 0, NULL, NULL }
58 };
59
60 static const struct sc_asn1_entry c_asn1_algorithm_info_parameters[3] = {
61 { "PKCS15RSAParameters",SC_ASN1_NULL, SC_ASN1_TAG_NULL, 0, NULL, NULL },
62 { "PKCS15ECParameters", SC_ASN1_OBJECT, SC_ASN1_TAG_OBJECT, 0, NULL, NULL },
63 { NULL, 0, 0, 0, NULL, NULL }
64 };
65
66 /*
67 * in src/libopensc/types.h SC_MAX_SUPPORTED_ALGORITHMS defined as 16
68 */
69 static const struct sc_asn1_entry c_asn1_supported_algorithms[SC_MAX_SUPPORTED_ALGORITHMS + 1] = {
70 { "algorithmInfo", SC_ASN1_STRUCT, SC_ASN1_TAG_SEQUENCE | SC_ASN1_CONS, SC_ASN1_OPTIONAL, NULL, NULL },
71 { "algorithmInfo", SC_ASN1_STRUCT, SC_ASN1_TAG_SEQUENCE | SC_ASN1_CONS, SC_ASN1_OPTIONAL, NULL, NULL },
72 { "algorithmInfo", SC_ASN1_STRUCT, SC_ASN1_TAG_SEQUENCE | SC_ASN1_CONS, SC_ASN1_OPTIONAL, NULL, NULL },
73 { "algorithmInfo", SC_ASN1_STRUCT, SC_ASN1_TAG_SEQUENCE | SC_ASN1_CONS, SC_ASN1_OPTIONAL, NULL, NULL },
74 { "algorithmInfo", SC_ASN1_STRUCT, SC_ASN1_TAG_SEQUENCE | SC_ASN1_CONS, SC_ASN1_OPTIONAL, NULL, NULL },
75 { "algorithmInfo", SC_ASN1_STRUCT, SC_ASN1_TAG_SEQUENCE | SC_ASN1_CONS, SC_ASN1_OPTIONAL, NULL, NULL },
76 { "algorithmInfo", SC_ASN1_STRUCT, SC_ASN1_TAG_SEQUENCE | SC_ASN1_CONS, SC_ASN1_OPTIONAL, NULL, NULL },
77 { "algorithmInfo", SC_ASN1_STRUCT, SC_ASN1_TAG_SEQUENCE | SC_ASN1_CONS, SC_ASN1_OPTIONAL, NULL, NULL },
78 { "algorithmInfo", SC_ASN1_STRUCT, SC_ASN1_TAG_SEQUENCE | SC_ASN1_CONS, SC_ASN1_OPTIONAL, NULL, NULL },
79 { "algorithmInfo", SC_ASN1_STRUCT, SC_ASN1_TAG_SEQUENCE | SC_ASN1_CONS, SC_ASN1_OPTIONAL, NULL, NULL },
80 { "algorithmInfo", SC_ASN1_STRUCT, SC_ASN1_TAG_SEQUENCE | SC_ASN1_CONS, SC_ASN1_OPTIONAL, NULL, NULL },
81 { "algorithmInfo", SC_ASN1_STRUCT, SC_ASN1_TAG_SEQUENCE | SC_ASN1_CONS, SC_ASN1_OPTIONAL, NULL, NULL },
82 { "algorithmInfo", SC_ASN1_STRUCT, SC_ASN1_TAG_SEQUENCE | SC_ASN1_CONS, SC_ASN1_OPTIONAL, NULL, NULL },
83 { "algorithmInfo", SC_ASN1_STRUCT, SC_ASN1_TAG_SEQUENCE | SC_ASN1_CONS, SC_ASN1_OPTIONAL, NULL, NULL },
84 { "algorithmInfo", SC_ASN1_STRUCT, SC_ASN1_TAG_SEQUENCE | SC_ASN1_CONS, SC_ASN1_OPTIONAL, NULL, NULL },
85 { "algorithmInfo", SC_ASN1_STRUCT, SC_ASN1_TAG_SEQUENCE | SC_ASN1_CONS, SC_ASN1_OPTIONAL, NULL, NULL },
86 { NULL, 0, 0, 0, NULL, NULL }
87 };
88
89 #define C_ASN1_LAST_UPDATE_SIZE 3
90 static const struct sc_asn1_entry c_asn1_last_update[C_ASN1_LAST_UPDATE_SIZE] = {
91 { "generalizedTime", SC_ASN1_GENERALIZEDTIME, SC_ASN1_TAG_GENERALIZEDTIME, SC_ASN1_OPTIONAL, NULL, NULL },
92 { "referencedTime", SC_ASN1_PATH, SC_ASN1_TAG_SEQUENCE | SC_ASN1_CONS, SC_ASN1_OPTIONAL, NULL, NULL },
93 { NULL, 0, 0, 0, NULL, NULL }
94 };
95
96 #define C_ASN1_PROFILE_INDICATION_SIZE 3
97 static const struct sc_asn1_entry c_asn1_profile_indication[C_ASN1_PROFILE_INDICATION_SIZE] = {
98 { "profileOID", SC_ASN1_OBJECT, SC_ASN1_TAG_OBJECT, SC_ASN1_OPTIONAL, NULL, NULL },
99 { "profileName", SC_ASN1_UTF8STRING, SC_ASN1_TAG_UTF8STRING, SC_ASN1_OPTIONAL, NULL, NULL },
100 { NULL, 0, 0, 0, NULL, NULL }
101 };
102
103 #define C_ASN1_TOKI_ATTRS_SIZE 15
104 static const struct sc_asn1_entry c_asn1_toki_attrs[C_ASN1_TOKI_ATTRS_SIZE] = {
105 { "version", SC_ASN1_INTEGER, SC_ASN1_TAG_INTEGER, 0, NULL, NULL },
106 { "serialNumber", SC_ASN1_OCTET_STRING, SC_ASN1_TAG_OCTET_STRING, SC_ASN1_OPTIONAL, NULL, NULL },
107 { "manufacturerID", SC_ASN1_UTF8STRING, SC_ASN1_TAG_UTF8STRING, SC_ASN1_OPTIONAL, NULL, NULL },
108 { "label", SC_ASN1_UTF8STRING, SC_ASN1_CTX | 0, SC_ASN1_OPTIONAL, NULL, NULL },
109 /* XXX the Taiwanese ID card erroneously uses explicit tagging */
110 { "label-tw", SC_ASN1_STRUCT, SC_ASN1_CTX | 0 | SC_ASN1_CONS, SC_ASN1_OPTIONAL, NULL, NULL },
111 { "tokenflags", SC_ASN1_BIT_FIELD, SC_ASN1_TAG_BIT_STRING, 0, NULL, NULL },
112 { "seInfo", SC_ASN1_SE_INFO, SC_ASN1_CONS | SC_ASN1_TAG_SEQUENCE, SC_ASN1_OPTIONAL, NULL, NULL },
113 { "recordInfo", SC_ASN1_STRUCT, SC_ASN1_CONS | SC_ASN1_CTX | 1, SC_ASN1_OPTIONAL, NULL, NULL },
114 { "supportedAlgorithms", SC_ASN1_STRUCT, SC_ASN1_CONS | SC_ASN1_CTX | 2, SC_ASN1_OPTIONAL, NULL, NULL },
115 { "issuerId", SC_ASN1_UTF8STRING, SC_ASN1_CTX | 3, SC_ASN1_OPTIONAL, NULL, NULL },
116 { "holderId", SC_ASN1_UTF8STRING, SC_ASN1_CTX | 4, SC_ASN1_OPTIONAL, NULL, NULL },
117 { "lastUpdate", SC_ASN1_STRUCT, SC_ASN1_CONS | SC_ASN1_CTX | 5, SC_ASN1_OPTIONAL, NULL, NULL },
118 { "preferredLanguage", SC_ASN1_PRINTABLESTRING, SC_ASN1_TAG_PRINTABLESTRING, SC_ASN1_OPTIONAL, NULL, NULL },
119 { "profileIndication", SC_ASN1_STRUCT, SC_ASN1_CONS | SC_ASN1_CTX | 6, SC_ASN1_OPTIONAL, NULL, NULL },
120 { NULL, 0, 0, 0, NULL, NULL }
121 };
122
123 static const struct sc_asn1_entry c_asn1_tokeninfo[] = {
124 { "TokenInfo", SC_ASN1_STRUCT, SC_ASN1_CONS | SC_ASN1_TAG_SEQUENCE, 0, NULL, NULL },
125 { NULL, 0, 0, 0, NULL, NULL }
126 };
127
128 static void sc_pkcs15_free_unusedspace(struct sc_pkcs15_card *);
129 static void sc_pkcs15_remove_dfs(struct sc_pkcs15_card *);
130 static void sc_pkcs15_remove_objects(struct sc_pkcs15_card *);
131 static int sc_pkcs15_aux_get_md_guid(struct sc_pkcs15_card *, const struct sc_pkcs15_object *,
132 unsigned, unsigned char *, size_t *);
133 static void sc_pkcs15_clear_tokeninfo(struct sc_pkcs15_tokeninfo *tokeninfo);
134
sc_pkcs15_parse_tokeninfo(sc_context_t * ctx,sc_pkcs15_tokeninfo_t * ti,const u8 * buf,size_t blen)135 int sc_pkcs15_parse_tokeninfo(sc_context_t *ctx,
136 sc_pkcs15_tokeninfo_t *ti, const u8 *buf, size_t blen)
137 {
138 int r;
139 size_t ii;
140 u8 serial[128];
141 size_t serial_len = sizeof(serial);
142 u8 mnfid[SC_PKCS15_MAX_LABEL_SIZE];
143 size_t mnfid_len = sizeof(mnfid) - 1;
144 u8 label[SC_PKCS15_MAX_LABEL_SIZE];
145 size_t label_len = sizeof(label) - 1;
146 u8 last_update[32], profile_indication[SC_PKCS15_MAX_LABEL_SIZE];
147 size_t lupdate_len = sizeof(last_update) - 1, pi_len = sizeof(profile_indication) - 1;
148 size_t flags_len = sizeof(ti->flags);
149 u8 preferred_language[3];
150 size_t lang_length = sizeof(preferred_language);
151 struct sc_asn1_entry asn1_supported_algorithms[SC_MAX_SUPPORTED_ALGORITHMS + 1],
152 asn1_algo_infos[SC_MAX_SUPPORTED_ALGORITHMS][7],
153 asn1_algo_infos_parameters[SC_MAX_SUPPORTED_ALGORITHMS][3];
154 size_t reference_len = sizeof(ti->supported_algos[0].reference);
155 size_t mechanism_len = sizeof(ti->supported_algos[0].mechanism);
156 size_t parameter_len = sizeof(ti->supported_algos[0].parameters);
157 size_t operations_len = sizeof(ti->supported_algos[0].operations);
158 size_t algo_ref_len = sizeof(ti->supported_algos[0].algo_ref);
159
160 struct sc_asn1_entry asn1_last_update[C_ASN1_LAST_UPDATE_SIZE];
161 struct sc_asn1_entry asn1_profile_indication[C_ASN1_PROFILE_INDICATION_SIZE];
162 struct sc_asn1_entry asn1_toki_attrs[C_ASN1_TOKI_ATTRS_SIZE], asn1_tokeninfo[3], asn1_twlabel[3];
163
164 memset(last_update, 0, sizeof(last_update));
165 memset(label, 0, sizeof(label));
166 memset(profile_indication, 0, sizeof(profile_indication));
167 memset(mnfid, 0, sizeof(mnfid));
168
169 sc_copy_asn1_entry(c_asn1_twlabel, asn1_twlabel);
170 sc_copy_asn1_entry(c_asn1_toki_attrs, asn1_toki_attrs);
171 sc_copy_asn1_entry(c_asn1_tokeninfo, asn1_tokeninfo);
172 sc_copy_asn1_entry(c_asn1_last_update, asn1_last_update);
173 sc_format_asn1_entry(asn1_twlabel, label, &label_len, 0);
174 sc_copy_asn1_entry(c_asn1_profile_indication, asn1_profile_indication);
175
176 for (ii=0; ii<SC_MAX_SUPPORTED_ALGORITHMS; ii++) {
177 sc_copy_asn1_entry(c_asn1_algorithm_info, asn1_algo_infos[ii]);
178 sc_copy_asn1_entry(c_asn1_algorithm_info_parameters,
179 asn1_algo_infos_parameters[ii]);
180 }
181 sc_copy_asn1_entry(c_asn1_supported_algorithms, asn1_supported_algorithms);
182
183 for (ii=0; ii<SC_MAX_SUPPORTED_ALGORITHMS; ii++) {
184 sc_format_asn1_entry(asn1_algo_infos[ii] + 0, &ti->supported_algos[ii].reference, &reference_len, 0);
185 sc_format_asn1_entry(asn1_algo_infos[ii] + 1, &ti->supported_algos[ii].mechanism, &mechanism_len, 0);
186 sc_format_asn1_entry(asn1_algo_infos[ii] + 2,
187 asn1_algo_infos_parameters[ii], NULL, 0);
188 sc_format_asn1_entry(asn1_algo_infos_parameters[ii] + 0,
189 NULL, NULL, 0);
190 sc_format_asn1_entry(asn1_algo_infos_parameters[ii] + 1,
191 &ti->supported_algos[ii].parameters, ¶meter_len, 0);
192 sc_format_asn1_entry(asn1_algo_infos[ii] + 3, &ti->supported_algos[ii].operations, &operations_len, 0);
193 sc_format_asn1_entry(asn1_algo_infos[ii] + 4, &ti->supported_algos[ii].algo_id, NULL, 1);
194 sc_format_asn1_entry(asn1_algo_infos[ii] + 5, &ti->supported_algos[ii].algo_ref, &algo_ref_len, 0);
195 sc_format_asn1_entry(asn1_supported_algorithms + ii, asn1_algo_infos[ii], NULL, 0);
196 }
197
198 sc_format_asn1_entry(asn1_last_update + 0, last_update, &lupdate_len, 0);
199 sc_format_asn1_entry(asn1_last_update + 1, &ti->last_update.path, NULL, 0);
200
201 sc_format_asn1_entry(asn1_profile_indication + 0, &ti->profile_indication.oid, NULL, 0);
202 sc_format_asn1_entry(asn1_profile_indication + 1, profile_indication, &pi_len, 0);
203
204 sc_format_asn1_entry(asn1_toki_attrs + 0, &ti->version, NULL, 0);
205 sc_format_asn1_entry(asn1_toki_attrs + 1, serial, &serial_len, 0);
206 sc_format_asn1_entry(asn1_toki_attrs + 2, mnfid, &mnfid_len, 0);
207 sc_format_asn1_entry(asn1_toki_attrs + 3, label, &label_len, 0);
208 sc_format_asn1_entry(asn1_toki_attrs + 4, asn1_twlabel, NULL, 0);
209 sc_format_asn1_entry(asn1_toki_attrs + 5, &ti->flags, &flags_len, 0);
210 sc_format_asn1_entry(asn1_toki_attrs + 6, &ti->seInfo, &ti->num_seInfo, 0);
211 sc_format_asn1_entry(asn1_toki_attrs + 7, NULL, NULL, 0);
212 sc_format_asn1_entry(asn1_toki_attrs + 8, asn1_supported_algorithms, NULL, 0);
213 sc_format_asn1_entry(asn1_toki_attrs + 9, NULL, NULL, 0);
214 sc_format_asn1_entry(asn1_toki_attrs + 10, NULL, NULL, 0);
215 sc_format_asn1_entry(asn1_toki_attrs + 11, asn1_last_update, NULL, 0);
216 sc_format_asn1_entry(asn1_toki_attrs + 12, preferred_language, &lang_length, 0);
217 sc_format_asn1_entry(asn1_toki_attrs + 13, asn1_profile_indication, NULL, 0);
218 sc_format_asn1_entry(asn1_tokeninfo, asn1_toki_attrs, NULL, 0);
219
220 r = sc_asn1_decode(ctx, asn1_tokeninfo, buf, blen, NULL, NULL);
221 if (r != SC_SUCCESS) {
222 /* The decoding could have allocated something we need to free */
223 sc_pkcs15_clear_tokeninfo(ti);
224 LOG_TEST_RET(ctx, r, "ASN.1 parsing of EF(TokenInfo) failed");
225 }
226
227 if (asn1_toki_attrs[1].flags & SC_ASN1_PRESENT && serial_len > 0) {
228 free(ti->serial_number);
229 ti->serial_number = malloc(serial_len * 2 + 1);
230 if (ti->serial_number == NULL)
231 return SC_ERROR_OUT_OF_MEMORY;
232 sc_bin_to_hex(serial, serial_len, ti->serial_number, serial_len * 2 + 1, 0);
233 sc_log(ctx, "TokenInfo.serialNunmber '%s'", ti->serial_number);
234 }
235
236 if (ti->manufacturer_id == NULL) {
237 if (asn1_toki_attrs[2].flags & SC_ASN1_PRESENT)
238 ti->manufacturer_id = strdup((char *) mnfid);
239 else
240 ti->manufacturer_id = strdup("(unknown)");
241 if (ti->manufacturer_id == NULL)
242 return SC_ERROR_OUT_OF_MEMORY;
243 }
244 if (ti->label == NULL) {
245 if (asn1_toki_attrs[3].flags & SC_ASN1_PRESENT ||
246 asn1_toki_attrs[4].flags & SC_ASN1_PRESENT)
247 ti->label = strdup((char *) label);
248 else
249 ti->label = strdup("(unknown)");
250 if (ti->label == NULL)
251 return SC_ERROR_OUT_OF_MEMORY;
252 }
253 if (asn1_toki_attrs[11].flags & SC_ASN1_PRESENT) {
254 if (asn1_last_update[0].flags & SC_ASN1_PRESENT) {
255 sc_log(ctx, "LastUpdate.generalizedTime present");
256 ti->last_update.gtime = strdup((char *)last_update);
257 if (ti->last_update.gtime == NULL)
258 return SC_ERROR_OUT_OF_MEMORY;
259 }
260 else if (asn1_last_update[1].flags & SC_ASN1_PRESENT) {
261 sc_log(ctx, "LastUpdate.referencedTime present");
262 }
263 }
264 if (asn1_toki_attrs[12].flags & SC_ASN1_PRESENT) {
265 preferred_language[2] = 0;
266 ti->preferred_language = strdup((char *)preferred_language);
267 if (ti->preferred_language == NULL)
268 return SC_ERROR_OUT_OF_MEMORY;
269 }
270
271 sc_init_oid(&ti->profile_indication.oid);
272 if (asn1_toki_attrs[13].flags & SC_ASN1_PRESENT) {
273 if (asn1_profile_indication[0].flags & SC_ASN1_PRESENT) {
274 sc_log(ctx, "ProfileIndication.oid present");
275 }
276 else if (asn1_profile_indication[1].flags & SC_ASN1_PRESENT) {
277 sc_log(ctx, "ProfileIndication.name present");
278 ti->profile_indication.name = strdup((char *)profile_indication);
279 if (ti->profile_indication.name == NULL)
280 return SC_ERROR_OUT_OF_MEMORY;
281 }
282 }
283
284 sc_log(ctx, "LastUpdate.path '%s'", sc_print_path(&ti->last_update.path));
285 sc_log(ctx, "ProfileIndication.name '%s'", ti->profile_indication.name);
286 return SC_SUCCESS;
287 }
288
289
290 int
sc_pkcs15_encode_tokeninfo(sc_context_t * ctx,sc_pkcs15_tokeninfo_t * ti,u8 ** buf,size_t * buflen)291 sc_pkcs15_encode_tokeninfo(sc_context_t *ctx, sc_pkcs15_tokeninfo_t *ti,
292 u8 **buf, size_t *buflen)
293 {
294 int r, ii;
295 size_t serial_len, mnfid_len, label_len, flags_len, last_upd_len, pi_len;
296
297 struct sc_asn1_entry asn1_toki_attrs[C_ASN1_TOKI_ATTRS_SIZE];
298 struct sc_asn1_entry asn1_tokeninfo[2];
299 struct sc_asn1_entry asn1_supported_algorithms[SC_MAX_SUPPORTED_ALGORITHMS + 1],
300 asn1_algo_infos[SC_MAX_SUPPORTED_ALGORITHMS][7],
301 asn1_algo_infos_parameters[SC_MAX_SUPPORTED_ALGORITHMS][3];
302 size_t reference_len = sizeof(ti->supported_algos[0].reference);
303 size_t mechanism_len = sizeof(ti->supported_algos[0].mechanism);
304 size_t parameter_len = sizeof(ti->supported_algos[0].parameters);
305 size_t operations_len = sizeof(ti->supported_algos[0].operations);
306 size_t algo_ref_len = sizeof(ti->supported_algos[0].algo_ref);
307 struct sc_asn1_entry asn1_last_update[C_ASN1_LAST_UPDATE_SIZE];
308 struct sc_asn1_entry asn1_profile_indication[C_ASN1_PROFILE_INDICATION_SIZE];
309
310 sc_copy_asn1_entry(c_asn1_toki_attrs, asn1_toki_attrs);
311 sc_copy_asn1_entry(c_asn1_tokeninfo, asn1_tokeninfo);
312 sc_copy_asn1_entry(c_asn1_last_update, asn1_last_update);
313 sc_copy_asn1_entry(c_asn1_profile_indication, asn1_profile_indication);
314
315 for (ii=0; ii<SC_MAX_SUPPORTED_ALGORITHMS && ti->supported_algos[ii].reference; ii++) {
316 sc_copy_asn1_entry(c_asn1_algorithm_info, asn1_algo_infos[ii]);
317 sc_copy_asn1_entry(c_asn1_algorithm_info_parameters,
318 asn1_algo_infos_parameters[ii]);
319 }
320 sc_copy_asn1_entry(c_asn1_supported_algorithms, asn1_supported_algorithms);
321
322 for (ii=0; ii<SC_MAX_SUPPORTED_ALGORITHMS && ti->supported_algos[ii].reference; ii++) {
323 sc_format_asn1_entry(asn1_algo_infos[ii] + 0, &ti->supported_algos[ii].reference, &reference_len, 1);
324 sc_format_asn1_entry(asn1_algo_infos[ii] + 1, &ti->supported_algos[ii].mechanism, &mechanism_len, 1);
325 sc_format_asn1_entry(asn1_algo_infos[ii] + 2,
326 asn1_algo_infos_parameters[ii], NULL, 1);
327 if (!sc_valid_oid(&ti->supported_algos[ii].parameters)) {
328 sc_format_asn1_entry(asn1_algo_infos_parameters[ii] + 0,
329 NULL, NULL, 1);
330 }
331 else {
332 sc_format_asn1_entry(asn1_algo_infos_parameters[ii] + 1,
333 &ti->supported_algos[ii].parameters, ¶meter_len, 0);
334 }
335 sc_format_asn1_entry(asn1_algo_infos[ii] + 3, &ti->supported_algos[ii].operations, &operations_len, 1);
336 sc_format_asn1_entry(asn1_algo_infos[ii] + 4, &ti->supported_algos[ii].algo_id, NULL, 1);
337 sc_format_asn1_entry(asn1_algo_infos[ii] + 5, &ti->supported_algos[ii].algo_ref, &algo_ref_len, 1);
338 sc_format_asn1_entry(asn1_supported_algorithms + ii, asn1_algo_infos[ii], NULL, 1);
339 }
340
341 sc_format_asn1_entry(asn1_toki_attrs + 0, &ti->version, NULL, 1);
342 if (ti->serial_number != NULL) {
343 u8 serial[128];
344 serial_len = 0;
345 if (strlen(ti->serial_number)/2 > sizeof(serial))
346 return SC_ERROR_BUFFER_TOO_SMALL;
347 serial_len = sizeof(serial);
348 if (sc_hex_to_bin(ti->serial_number, serial, &serial_len) < 0)
349 return SC_ERROR_INVALID_ARGUMENTS;
350 sc_format_asn1_entry(asn1_toki_attrs + 1, serial, &serial_len, 1);
351 }
352 else {
353 sc_format_asn1_entry(asn1_toki_attrs + 1, NULL, NULL, 0);
354 }
355
356 if (ti->manufacturer_id != NULL) {
357 mnfid_len = strlen(ti->manufacturer_id);
358 sc_format_asn1_entry(asn1_toki_attrs + 2, ti->manufacturer_id, &mnfid_len, 1);
359 }
360 else {
361 sc_format_asn1_entry(asn1_toki_attrs + 2, NULL, NULL, 0);
362 }
363
364 if (ti->label != NULL) {
365 label_len = strlen(ti->label);
366 sc_format_asn1_entry(asn1_toki_attrs + 3, ti->label, &label_len, 1);
367 }
368 else {
369 sc_format_asn1_entry(asn1_toki_attrs + 3, NULL, NULL, 0);
370 }
371
372 if (ti->flags) {
373 flags_len = sizeof(ti->flags);
374 sc_format_asn1_entry(asn1_toki_attrs + 5, &ti->flags, &flags_len, 1);
375 }
376 else {
377 sc_format_asn1_entry(asn1_toki_attrs + 5, NULL, NULL, 0);
378 }
379
380 if (ti->num_seInfo)
381 sc_format_asn1_entry(asn1_toki_attrs + 6, ti->seInfo, &ti->num_seInfo, 1);
382 else
383 sc_format_asn1_entry(asn1_toki_attrs + 6, NULL, NULL, 0);
384
385 sc_format_asn1_entry(asn1_toki_attrs + 7, NULL, NULL, 0);
386
387 if (ti->supported_algos[0].reference)
388 sc_format_asn1_entry(asn1_toki_attrs + 8, asn1_supported_algorithms, NULL, 1);
389 else
390 sc_format_asn1_entry(asn1_toki_attrs + 8, NULL, NULL, 0);
391
392 sc_format_asn1_entry(asn1_toki_attrs + 9, NULL, NULL, 0);
393 sc_format_asn1_entry(asn1_toki_attrs + 10, NULL, NULL, 0);
394
395 if (ti->last_update.path.len) {
396 sc_format_asn1_entry(asn1_last_update + 0, &ti->last_update.path, NULL, 1);
397 sc_format_asn1_entry(asn1_toki_attrs + 11, asn1_last_update, NULL, 1);
398 }
399 else if (ti->last_update.gtime != NULL) {
400 last_upd_len = strlen(ti->last_update.gtime);
401 sc_format_asn1_entry(asn1_last_update + 0, ti->last_update.gtime, &last_upd_len, 1);
402 sc_format_asn1_entry(asn1_toki_attrs + 11, asn1_last_update, NULL, 1);
403 }
404 else {
405 sc_format_asn1_entry(asn1_toki_attrs + 11, NULL, NULL, 0);
406 }
407 sc_format_asn1_entry(asn1_toki_attrs + 12, NULL, NULL, 0);
408
409 if (sc_valid_oid(&ti->profile_indication.oid)) {
410 sc_format_asn1_entry(asn1_profile_indication + 0, &ti->profile_indication.oid, NULL, 1);
411 sc_format_asn1_entry(asn1_toki_attrs + 13, asn1_profile_indication, NULL, 1);
412 }
413 else if (ti->profile_indication.name) {
414 pi_len = strlen(ti->profile_indication.name);
415 sc_format_asn1_entry(asn1_profile_indication + 1, ti->profile_indication.name, &pi_len, 1);
416 sc_format_asn1_entry(asn1_toki_attrs + 13, asn1_profile_indication, NULL, 1);
417 }
418 else {
419 sc_format_asn1_entry(asn1_toki_attrs + 13, NULL, NULL, 0);
420 }
421
422 sc_format_asn1_entry(asn1_tokeninfo, asn1_toki_attrs, NULL, 1);
423
424 r = sc_asn1_encode(ctx, asn1_tokeninfo, buf, buflen);
425 LOG_TEST_RET(ctx, r, "sc_asn1_encode() failed");
426
427 return SC_SUCCESS;
428 }
429
430 static const struct sc_asn1_entry c_asn1_ddo[] = {
431 { "oid", SC_ASN1_OBJECT, SC_ASN1_TAG_OBJECT, SC_ASN1_OPTIONAL, NULL, NULL },
432 { "odfPath", SC_ASN1_PATH, SC_ASN1_CONS | SC_ASN1_TAG_SEQUENCE, SC_ASN1_OPTIONAL, NULL, NULL },
433 { "tokenInfoPath", SC_ASN1_PATH, SC_ASN1_CONS | SC_ASN1_CTX | 0, SC_ASN1_OPTIONAL, NULL, NULL },
434 { "unusedPath", SC_ASN1_PATH, SC_ASN1_CONS | SC_ASN1_CTX | 1, SC_ASN1_OPTIONAL, NULL, NULL },
435 /* According to PKCS#15 v1.1 here is the place for the future extensions.
436 * The following data are used when ODF record points to the xDF files in a different application.
437 */
438 { "ddoIIN", SC_ASN1_OCTET_STRING, SC_ASN1_APP | 0x02, SC_ASN1_OPTIONAL, NULL, NULL },
439 { "ddoAID", SC_ASN1_OCTET_STRING, SC_ASN1_APP | 0x0F, SC_ASN1_OPTIONAL, NULL, NULL },
440 { NULL, 0, 0, 0, NULL, NULL }
441 };
442
443 static void
fix_authentic_ddo(struct sc_pkcs15_card * p15card)444 fix_authentic_ddo(struct sc_pkcs15_card *p15card)
445 {
446 /* AuthentIC v3.2 card has invalid ODF and tokenInfo paths encoded into DDO.
447 * Cleanup this attributes -- default values must be OK.
448 */
449 if (p15card->card->type == SC_CARD_TYPE_OBERTHUR_AUTHENTIC_3_2) {
450 sc_file_free(p15card->file_odf);
451 p15card->file_odf = NULL;
452 sc_file_free(p15card->file_tokeninfo);
453 p15card->file_tokeninfo = NULL;
454 }
455 }
456
457 static int
parse_ddo(struct sc_pkcs15_card * p15card,const u8 * buf,size_t buflen)458 parse_ddo(struct sc_pkcs15_card *p15card, const u8 * buf, size_t buflen)
459 {
460 struct sc_context *ctx = p15card->card->ctx;
461 struct sc_asn1_entry asn1_ddo[7];
462 sc_path_t odf_path, ti_path, us_path;
463 struct sc_iid iid;
464 struct sc_aid aid;
465 int r;
466
467 LOG_FUNC_CALLED(ctx);
468
469 iid.len = sizeof(iid.value);
470 aid.len = sizeof(aid.value);
471
472 sc_copy_asn1_entry(c_asn1_ddo, asn1_ddo);
473 sc_format_asn1_entry(asn1_ddo + 1, &odf_path, NULL, 0);
474 sc_format_asn1_entry(asn1_ddo + 2, &ti_path, NULL, 0);
475 sc_format_asn1_entry(asn1_ddo + 3, &us_path, NULL, 0);
476 sc_format_asn1_entry(asn1_ddo + 4, iid.value, &iid.len, 0);
477 sc_format_asn1_entry(asn1_ddo + 5, aid.value, &aid.len, 0);
478
479 r = sc_asn1_decode(ctx, asn1_ddo, buf, buflen, NULL, NULL);
480 LOG_TEST_RET(ctx, r, "DDO parsing failed");
481
482 if (asn1_ddo[1].flags & SC_ASN1_PRESENT) {
483 sc_file_free(p15card->file_odf);
484 p15card->file_odf = sc_file_new();
485 if (p15card->file_odf == NULL)
486 goto mem_err;
487 p15card->file_odf->path = odf_path;
488 }
489 if (asn1_ddo[2].flags & SC_ASN1_PRESENT) {
490 sc_file_free(p15card->file_tokeninfo);
491 p15card->file_tokeninfo = sc_file_new();
492 if (p15card->file_tokeninfo == NULL)
493 goto mem_err;
494 p15card->file_tokeninfo->path = ti_path;
495 }
496 if (asn1_ddo[3].flags & SC_ASN1_PRESENT) {
497 sc_file_free(p15card->file_unusedspace);
498 p15card->file_unusedspace = sc_file_new();
499 if (p15card->file_unusedspace == NULL)
500 goto mem_err;
501 p15card->file_unusedspace->path = us_path;
502 }
503 if (asn1_ddo[4].flags & SC_ASN1_PRESENT) {
504 sc_debug(ctx, SC_LOG_DEBUG_ASN1, "DDO.IID '%s'", sc_dump_hex(iid.value, iid.len));
505 memcpy(&p15card->app->ddo.iid, &iid, sizeof(struct sc_iid));
506 }
507 if (asn1_ddo[5].flags & SC_ASN1_PRESENT) {
508 sc_debug(ctx, SC_LOG_DEBUG_ASN1, "DDO.AID '%s'", sc_dump_hex(aid.value, aid.len));
509 memcpy(&p15card->app->ddo.aid, &aid, sizeof(struct sc_aid));
510 }
511
512 fix_authentic_ddo(p15card);
513 LOG_FUNC_RETURN(ctx, SC_SUCCESS);
514 mem_err:
515 sc_file_free(p15card->file_odf);
516 p15card->file_odf = NULL;
517 sc_file_free(p15card->file_tokeninfo);
518 p15card->file_tokeninfo = NULL;
519 sc_file_free(p15card->file_unusedspace);
520 p15card->file_unusedspace = NULL;
521 LOG_FUNC_RETURN(ctx, SC_ERROR_OUT_OF_MEMORY);
522 }
523
524
525 char *
sc_pkcs15_get_lastupdate(struct sc_pkcs15_card * p15card)526 sc_pkcs15_get_lastupdate(struct sc_pkcs15_card *p15card)
527 {
528 struct sc_context *ctx = p15card->card->ctx;
529 struct sc_file *file = NULL;
530 struct sc_asn1_entry asn1_last_update[C_ASN1_LAST_UPDATE_SIZE];
531 unsigned char *content, last_update[32];
532 size_t lupdate_len = sizeof(last_update) - 1;
533 int r, content_len;
534 size_t size;
535
536 if (p15card->tokeninfo->last_update.gtime)
537 goto done;
538
539 if (!p15card->tokeninfo->last_update.path.len)
540 return NULL;
541
542 r = sc_select_file(p15card->card, &p15card->tokeninfo->last_update.path, &file);
543 if (r < 0)
544 return NULL;
545
546 size = file->size ? file->size : 1024;
547
548 content = calloc(size, 1);
549 if (!content)
550 return NULL;
551
552 r = sc_read_binary(p15card->card, 0, content, size, 0);
553 if (r < 0)
554 return NULL;
555 content_len = r;
556
557 sc_file_free(file);
558
559 sc_copy_asn1_entry(c_asn1_last_update, asn1_last_update);
560 sc_format_asn1_entry(asn1_last_update + 0, last_update, &lupdate_len, 0);
561
562 r = sc_asn1_decode(ctx, asn1_last_update, content, content_len, NULL, NULL);
563 free(content);
564 if (r < 0)
565 return NULL;
566
567 p15card->tokeninfo->last_update.gtime = strdup((char *)last_update);
568 if (!p15card->tokeninfo->last_update.gtime)
569 return NULL;
570 done:
571 sc_log(ctx, "lastUpdate.gtime '%s'", p15card->tokeninfo->last_update.gtime);
572 return p15card->tokeninfo->last_update.gtime;
573 }
574
575
576 static const struct sc_asn1_entry c_asn1_odf[] = {
577 { "privateKeys", SC_ASN1_STRUCT, SC_ASN1_CTX | 0 | SC_ASN1_CONS, 0, NULL, NULL },
578 { "publicKeys", SC_ASN1_STRUCT, SC_ASN1_CTX | 1 | SC_ASN1_CONS, 0, NULL, NULL },
579 { "trustedPublicKeys", SC_ASN1_STRUCT, SC_ASN1_CTX | 2 | SC_ASN1_CONS, 0, NULL, NULL },
580 { "secretKeys", SC_ASN1_STRUCT, SC_ASN1_CTX | 3 | SC_ASN1_CONS, 0, NULL, NULL },
581 { "certificates", SC_ASN1_STRUCT, SC_ASN1_CTX | 4 | SC_ASN1_CONS, 0, NULL, NULL },
582 { "trustedCertificates", SC_ASN1_STRUCT, SC_ASN1_CTX | 5 | SC_ASN1_CONS, 0, NULL, NULL },
583 { "usefulCertificates", SC_ASN1_STRUCT, SC_ASN1_CTX | 6 | SC_ASN1_CONS, 0, NULL, NULL },
584 { "dataObjects", SC_ASN1_STRUCT, SC_ASN1_CTX | 7 | SC_ASN1_CONS, 0, NULL, NULL },
585 { "authObjects", SC_ASN1_STRUCT, SC_ASN1_CTX | 8 | SC_ASN1_CONS, 0, NULL, NULL },
586 { NULL, 0, 0, 0, NULL, NULL }
587 };
588
589 static const unsigned int odf_indexes[] = {
590 SC_PKCS15_PRKDF,
591 SC_PKCS15_PUKDF,
592 SC_PKCS15_PUKDF_TRUSTED,
593 SC_PKCS15_SKDF,
594 SC_PKCS15_CDF,
595 SC_PKCS15_CDF_TRUSTED,
596 SC_PKCS15_CDF_USEFUL,
597 SC_PKCS15_DODF,
598 SC_PKCS15_AODF,
599 };
600
601
602 static int
parse_odf(const unsigned char * buf,size_t buflen,struct sc_pkcs15_card * p15card)603 parse_odf(const unsigned char * buf, size_t buflen, struct sc_pkcs15_card *p15card)
604 {
605 const unsigned char *p = buf;
606 size_t left = buflen;
607 int r, i, type;
608 struct sc_path path;
609 struct sc_asn1_entry asn1_obj_or_path[] = {
610 { "path", SC_ASN1_PATH, SC_ASN1_CONS | SC_ASN1_SEQUENCE, 0, &path, NULL },
611 { NULL, 0, 0, 0, NULL, NULL }
612 };
613 struct sc_asn1_entry asn1_odf[10];
614
615 sc_copy_asn1_entry(c_asn1_odf, asn1_odf);
616 for (i = 0; asn1_odf[i].name != NULL; i++)
617 sc_format_asn1_entry(asn1_odf + i, asn1_obj_or_path, NULL, 0);
618 while (left > 0) {
619 r = sc_asn1_decode_choice(p15card->card->ctx, asn1_odf, p, left, &p, &left);
620 if (r == SC_ERROR_ASN1_END_OF_CONTENTS)
621 break;
622 if (r < 0)
623 return r;
624 type = r;
625 if (p15card->file_app) {
626 r = sc_pkcs15_make_absolute_path(&p15card->file_app->path, &path);
627 if (r < 0)
628 return r;
629 r = sc_pkcs15_add_df(p15card, odf_indexes[type], &path);
630 if (r)
631 return r;
632 }
633 }
634 return 0;
635 }
636
637
638 int
sc_pkcs15_encode_odf(struct sc_context * ctx,struct sc_pkcs15_card * p15card,unsigned char ** buf,size_t * buflen)639 sc_pkcs15_encode_odf(struct sc_context *ctx, struct sc_pkcs15_card *p15card,
640 unsigned char **buf, size_t *buflen)
641 {
642 struct sc_path path;
643 struct sc_asn1_entry asn1_obj_or_path[] = {
644 { "path", SC_ASN1_PATH, SC_ASN1_CONS | SC_ASN1_SEQUENCE, 0, &path, NULL },
645 { NULL, 0, 0, 0, NULL, NULL }
646 };
647 struct sc_asn1_entry *asn1_paths = NULL;
648 struct sc_asn1_entry *asn1_odf = NULL;
649 int df_count = 0, r, c = 0;
650 const int nr_indexes = sizeof(odf_indexes)/sizeof(odf_indexes[0]);
651 struct sc_pkcs15_df *df;
652
653 df = p15card->df_list;
654 while (df != NULL) {
655 df_count++;
656 df = df->next;
657 };
658 if (df_count == 0)
659 LOG_TEST_RET(ctx, SC_ERROR_OBJECT_NOT_FOUND, "No DF's found.");
660
661 asn1_odf = malloc(sizeof(struct sc_asn1_entry) * (df_count + 1));
662 if (asn1_odf == NULL) {
663 r = SC_ERROR_OUT_OF_MEMORY;
664 goto err;
665 }
666 asn1_paths = malloc(sizeof(struct sc_asn1_entry) * (df_count * 2));
667 if (asn1_paths == NULL) {
668 r = SC_ERROR_OUT_OF_MEMORY;
669 goto err;
670 }
671 for (df = p15card->df_list; df != NULL; df = df->next) {
672 int j, type = -1;
673
674 for (j = 0; j < nr_indexes; j++)
675 if (odf_indexes[j] == df->type) {
676 type = j;
677 break;
678 }
679 if (type == -1) {
680 sc_log(ctx, "Unsupported DF type.");
681 continue;
682 }
683 asn1_odf[c] = c_asn1_odf[type];
684 sc_format_asn1_entry(asn1_odf + c, asn1_paths + 2*c, NULL, 1);
685 sc_copy_asn1_entry(asn1_obj_or_path, asn1_paths + 2*c);
686 sc_format_asn1_entry(asn1_paths + 2*c, &df->path, NULL, 1);
687 c++;
688 }
689 asn1_odf[c].name = NULL;
690 r = sc_asn1_encode(ctx, asn1_odf, buf, buflen);
691 err:
692 if (asn1_paths != NULL)
693 free(asn1_paths);
694 if (asn1_odf != NULL)
695 free(asn1_odf);
696 return r;
697 }
698
699
700 struct sc_pkcs15_card *
sc_pkcs15_card_new(void)701 sc_pkcs15_card_new(void)
702 {
703 struct sc_pkcs15_card *p15card;
704
705 p15card = calloc(1, sizeof(struct sc_pkcs15_card));
706 if (p15card == NULL)
707 return NULL;
708
709 p15card->tokeninfo = calloc(1, sizeof(struct sc_pkcs15_tokeninfo));
710 if (p15card->tokeninfo == NULL) {
711 free(p15card);
712 return NULL;
713 }
714
715 p15card->magic = SC_PKCS15_CARD_MAGIC;
716 return p15card;
717 }
718
719
720 struct sc_pkcs15_tokeninfo *
sc_pkcs15_tokeninfo_new(void)721 sc_pkcs15_tokeninfo_new(void)
722 {
723 struct sc_pkcs15_tokeninfo *tokeninfo;
724
725 tokeninfo = calloc(1, sizeof(struct sc_pkcs15_tokeninfo));
726 if (tokeninfo == NULL) {
727 return NULL;
728 }
729
730 sc_init_oid(&tokeninfo->profile_indication.oid);
731
732 return tokeninfo;
733 }
734
735 static void
sc_pkcs15_clear_tokeninfo(struct sc_pkcs15_tokeninfo * tokeninfo)736 sc_pkcs15_clear_tokeninfo(struct sc_pkcs15_tokeninfo *tokeninfo)
737 {
738 if (!tokeninfo)
739 return;
740
741 free(tokeninfo->label);
742 tokeninfo->label = NULL;
743 free(tokeninfo->serial_number);
744 tokeninfo->serial_number = NULL;
745 free(tokeninfo->manufacturer_id);
746 tokeninfo->manufacturer_id = NULL;
747 free(tokeninfo->last_update.gtime);
748 tokeninfo->last_update.gtime = NULL;
749 free(tokeninfo->preferred_language);
750 tokeninfo->preferred_language = NULL;
751 free(tokeninfo->profile_indication.name);
752 tokeninfo->profile_indication.name = NULL;
753 if (tokeninfo->seInfo != NULL) {
754 unsigned i;
755 for (i = 0; i < tokeninfo->num_seInfo; i++)
756 free(tokeninfo->seInfo[i]);
757 free(tokeninfo->seInfo);
758 tokeninfo->seInfo = NULL;
759 }
760 }
761
762 void
sc_pkcs15_free_tokeninfo(struct sc_pkcs15_tokeninfo * tokeninfo)763 sc_pkcs15_free_tokeninfo(struct sc_pkcs15_tokeninfo *tokeninfo)
764 {
765 if (!tokeninfo)
766 return;
767
768 sc_pkcs15_clear_tokeninfo(tokeninfo);
769 free(tokeninfo);
770 }
771
772 void
sc_pkcs15_free_app(struct sc_pkcs15_card * p15card)773 sc_pkcs15_free_app(struct sc_pkcs15_card *p15card)
774 {
775 if (p15card && p15card->app) {
776 free(p15card->app->label);
777 free(p15card->app->ddo.value);
778 free(p15card->app);
779 p15card->app = NULL;
780 }
781 }
782
783
784 void
sc_pkcs15_card_free(struct sc_pkcs15_card * p15card)785 sc_pkcs15_card_free(struct sc_pkcs15_card *p15card)
786 {
787 if (p15card == NULL || p15card->magic != SC_PKCS15_CARD_MAGIC)
788 return;
789
790 if (p15card->ops.clear)
791 p15card->ops.clear(p15card);
792
793 /* For more complicated MD data a dedicated release procedure
794 * has to be implemented. */
795 if (p15card->md_data)
796 free(p15card->md_data);
797
798 sc_pkcs15_free_app(p15card);
799 sc_pkcs15_remove_objects(p15card);
800 sc_pkcs15_remove_dfs(p15card);
801 sc_pkcs15_free_unusedspace(p15card);
802 p15card->unusedspace_read = 0;
803
804 sc_file_free(p15card->file_app);
805 sc_file_free(p15card->file_tokeninfo);
806 sc_file_free(p15card->file_odf);
807 sc_file_free(p15card->file_unusedspace);
808
809 p15card->magic = 0;
810 sc_pkcs15_free_tokeninfo(p15card->tokeninfo);
811 sc_pkcs15_free_app(p15card);
812 free(p15card);
813 }
814
815
816 void
sc_pkcs15_card_clear(struct sc_pkcs15_card * p15card)817 sc_pkcs15_card_clear(struct sc_pkcs15_card *p15card)
818 {
819 if (p15card == NULL)
820 return;
821
822 if (p15card->ops.clear)
823 p15card->ops.clear(p15card);
824
825 p15card->flags = 0;
826 p15card->tokeninfo->version = 0;
827 p15card->tokeninfo->flags = 0;
828
829 sc_pkcs15_remove_objects(p15card);
830 sc_pkcs15_remove_dfs(p15card);
831
832 p15card->df_list = NULL;
833 sc_file_free(p15card->file_app);
834 p15card->file_app = NULL;
835 sc_file_free(p15card->file_tokeninfo);
836 p15card->file_tokeninfo = NULL;
837 sc_file_free(p15card->file_odf);
838 p15card->file_odf = NULL;
839 sc_file_free(p15card->file_unusedspace);
840 p15card->file_unusedspace = NULL;
841
842 free(p15card->tokeninfo->label);
843 p15card->tokeninfo->label = NULL;
844 free(p15card->tokeninfo->serial_number);
845 p15card->tokeninfo->serial_number = NULL;
846 free(p15card->tokeninfo->manufacturer_id);
847 p15card->tokeninfo->manufacturer_id = NULL;
848 free(p15card->tokeninfo->last_update.gtime);
849 p15card->tokeninfo->last_update.gtime = NULL;
850 free(p15card->tokeninfo->preferred_language);
851 p15card->tokeninfo->preferred_language = NULL;
852 free(p15card->tokeninfo->profile_indication.name);
853 p15card->tokeninfo->profile_indication.name = NULL;
854 if (p15card->tokeninfo->seInfo != NULL) {
855 size_t i;
856 for (i = 0; i < p15card->tokeninfo->num_seInfo; i++)
857 free(p15card->tokeninfo->seInfo[i]);
858 free(p15card->tokeninfo->seInfo);
859 p15card->tokeninfo->seInfo = NULL;
860 p15card->tokeninfo->num_seInfo = 0;
861 }
862 }
863
864
865 struct sc_app_info *
sc_find_app(struct sc_card * card,struct sc_aid * aid)866 sc_find_app(struct sc_card *card, struct sc_aid *aid)
867 {
868 int ii;
869
870 if (card->app_count <= 0)
871 return NULL;
872
873 if (!aid || !aid->len)
874 return card->app[0];
875
876 for (ii=0; ii < card->app_count; ii++) {
877 if (card->app[ii]->aid.len != aid->len)
878 continue;
879 if (memcmp(card->app[ii]->aid.value, aid->value, aid->len))
880 continue;
881 return card->app[ii];
882 }
883 return NULL;
884 }
885
886
887 static struct sc_app_info *
sc_dup_app_info(const struct sc_app_info * info)888 sc_dup_app_info(const struct sc_app_info *info)
889 {
890 struct sc_app_info *out = calloc(1, sizeof(struct sc_app_info));
891
892 if (!out)
893 return NULL;
894
895 memcpy(out, info, sizeof(struct sc_app_info));
896
897 if (info->label) {
898 out->label = strdup(info->label);
899 if (!out->label) {
900 free(out);
901 return NULL;
902 }
903 } else
904 out->label = NULL;
905
906 out->ddo.value = malloc(info->ddo.len);
907 if (!out->ddo.value) {
908 free(out->label);
909 free(out);
910 return NULL;
911 }
912 memcpy(out->ddo.value, info->ddo.value, info->ddo.len);
913
914 return out;
915 }
916
917
918 struct sc_app_info *
sc_pkcs15_get_application_by_type(struct sc_card * card,char * app_type)919 sc_pkcs15_get_application_by_type(struct sc_card * card, char *app_type)
920 {
921 struct sc_app_info *out = NULL;
922 scconf_block *conf_block = NULL;
923 int i, rv;
924
925 if (!card)
926 return NULL;
927
928 if (card->app_count < 0) {
929 rv = sc_enum_apps(card);
930 if (rv < 0 && rv != SC_ERROR_FILE_NOT_FOUND)
931 return NULL;
932 }
933
934 conf_block = sc_get_conf_block(card->ctx, "framework", "pkcs15", 1);
935 if (!conf_block)
936 return NULL;
937
938 for (i = 0; i < card->app_count; i++) {
939 struct sc_app_info *app_info = card->app[i];
940 scconf_block **blocks = NULL;
941 char str_path[SC_MAX_AID_STRING_SIZE];
942
943 sc_bin_to_hex(app_info->aid.value, app_info->aid.len, str_path, sizeof(str_path), 0);
944 blocks = scconf_find_blocks(card->ctx->conf, conf_block, "application", str_path);
945 if (blocks) {
946 if (blocks[0]) {
947 char *type = (char *)scconf_get_str(blocks[0], "type", app_type);
948 if (!strcmp(type, app_type)) {
949 out = app_info;
950 free(blocks);
951 break;
952 }
953 }
954 free(blocks);
955 }
956 }
957
958 return out;
959 }
960
961
962 int
sc_pkcs15_bind_internal(struct sc_pkcs15_card * p15card,struct sc_aid * aid)963 sc_pkcs15_bind_internal(struct sc_pkcs15_card *p15card, struct sc_aid *aid)
964 {
965 struct sc_path tmppath;
966 struct sc_card *card = p15card->card;
967 struct sc_context *ctx = card->ctx;
968 struct sc_pkcs15_tokeninfo tokeninfo;
969 struct sc_pkcs15_df *df;
970 const struct sc_app_info *info = NULL;
971 unsigned char *buf = NULL;
972 size_t len;
973 int err, ok = 0;
974
975 LOG_FUNC_CALLED(ctx);
976 /* Enumerate apps now */
977 if (card->app_count < 0) {
978 err = sc_enum_apps(card);
979 if (err != SC_SUCCESS)
980 sc_log(ctx, "unable to enumerate apps: %s", sc_strerror(err));
981 }
982 sc_file_free(p15card->file_app);
983 p15card->file_app = sc_file_new();
984 if (p15card->file_app == NULL) {
985 err = SC_ERROR_OUT_OF_MEMORY;
986 goto end;
987 }
988
989 sc_format_path("3F005015", &p15card->file_app->path);
990
991 info = sc_find_app(card, aid);
992 if (info) {
993 sc_log(ctx, "bind to application('%s',aid:'%s')", info->label, sc_dump_hex(info->aid.value, info->aid.len));
994 sc_pkcs15_free_app(p15card);
995 p15card->app = sc_dup_app_info(info);
996 if (!p15card->app) {
997 err = SC_ERROR_OUT_OF_MEMORY;
998 goto end;
999 }
1000
1001 if (info->path.len)
1002 p15card->file_app->path = info->path;
1003
1004 if (info->ddo.value && info->ddo.len)
1005 parse_ddo(p15card, info->ddo.value, info->ddo.len);
1006
1007 }
1008 else if (aid) {
1009 sc_log(ctx, "Application '%s' not found", sc_dump_hex(aid->value, aid->len));
1010 err = SC_ERROR_INVALID_ARGUMENTS;
1011 goto end;
1012 }
1013 sc_log(ctx, "application path '%s'", sc_print_path(&p15card->file_app->path));
1014
1015 /* Check if pkcs15 directory exists */
1016 err = sc_select_file(card, &p15card->file_app->path, NULL);
1017
1018 /* If the above test failed on cards without EF(DIR),
1019 * try to continue read ODF from 3F005031. -aet
1020 */
1021 if ((err != SC_SUCCESS) && (card->app_count < 1)) {
1022 sc_format_path("3F00", &p15card->file_app->path);
1023 err = SC_SUCCESS;
1024 }
1025
1026 if (err < 0) {
1027 sc_log (ctx, "Cannot select application path");
1028 goto end;
1029 }
1030
1031 if (p15card->file_odf == NULL) {
1032 /* check if an ODF is present; we don't know yet whether we have a pkcs15 card */
1033 sc_format_path("5031", &tmppath);
1034 err = sc_pkcs15_make_absolute_path(&p15card->file_app->path, &tmppath);
1035 if (err != SC_SUCCESS) {
1036 sc_log(ctx, "Cannot make absolute path to EF(ODF); error:%i", err);
1037 goto end;
1038 }
1039 sc_log(ctx, "absolute path to EF(ODF) %s", sc_print_path(&tmppath));
1040 err = sc_select_file(card, &tmppath, &p15card->file_odf);
1041 }
1042 else {
1043 tmppath = p15card->file_odf->path;
1044 sc_file_free(p15card->file_odf);
1045 p15card->file_odf = NULL;
1046 err = sc_select_file(card, &tmppath, &p15card->file_odf);
1047 }
1048
1049 if (err != SC_SUCCESS) {
1050 sc_log(ctx, "EF(ODF) not found in '%s'", sc_print_path(&tmppath));
1051 goto end;
1052 }
1053
1054 len = p15card->file_odf->size;
1055 if (!len) {
1056 sc_log(ctx, "EF(ODF) is empty");
1057 goto end;
1058 }
1059 if (len > MAX_FILE_SIZE) {
1060 sc_log(ctx, "EF(ODF) too large");
1061 goto end;
1062 }
1063 buf = malloc(len);
1064 if(buf == NULL) {
1065 err = SC_ERROR_OUT_OF_MEMORY;
1066 goto end;
1067 }
1068
1069 err = -1; /* file state: not in cache */
1070 if (p15card->opts.use_file_cache) {
1071 err = sc_pkcs15_read_cached_file(p15card, &tmppath, &buf, &len);
1072 if (err == SC_SUCCESS)
1073 err = len;
1074 }
1075 if (err < 0) {
1076 err = sc_read_binary(card, 0, buf, len, 0);
1077 if (err < 2) {
1078 if (err < 0) {
1079 sc_log(ctx, "read EF(ODF) file error: %s", sc_strerror(err));
1080 } else {
1081 err = SC_ERROR_PKCS15_APP_NOT_FOUND;
1082 sc_log(ctx, "Invalid content of EF(ODF): %s", sc_strerror(err));
1083 }
1084 goto end;
1085 }
1086 /* sc_read_binary may return less than requested */
1087 len = err;
1088
1089 if (p15card->opts.use_file_cache) {
1090 sc_pkcs15_cache_file(p15card, &tmppath, buf, len);
1091 }
1092 }
1093
1094 if (parse_odf(buf, len, p15card)) {
1095 err = SC_ERROR_PKCS15_APP_NOT_FOUND;
1096 sc_log(ctx, "Unable to parse ODF");
1097 goto end;
1098 }
1099 free(buf);
1100 buf = NULL;
1101
1102 sc_log(ctx, "The following DFs were found:");
1103 for (df = p15card->df_list; df; df = df->next)
1104 sc_log(ctx, " DF type %u, path %s, index %u, count %d", df->type,
1105 sc_print_path(&df->path), df->path.index, df->path.count);
1106
1107 if (p15card->file_tokeninfo == NULL) {
1108 sc_format_path("5032", &tmppath);
1109 err = sc_pkcs15_make_absolute_path(&p15card->file_app->path, &tmppath);
1110 if (err != SC_SUCCESS) {
1111 sc_log(ctx, "Cannot make absolute path to EF(TokenInfo); error:%i", err);
1112 goto end;
1113 }
1114 sc_log(ctx, "absolute path to EF(TokenInfo) %s", sc_print_path(&tmppath));
1115 }
1116 else {
1117 tmppath = p15card->file_tokeninfo->path;
1118 sc_file_free(p15card->file_tokeninfo);
1119 p15card->file_tokeninfo = NULL;
1120 }
1121
1122 err = sc_select_file(card, &tmppath, &p15card->file_tokeninfo);
1123 if (err) {
1124 sc_log(ctx, "cannot select EF(TokenInfo) file: %s", sc_strerror(err));
1125 goto end;
1126 }
1127
1128 len = p15card->file_tokeninfo->size;
1129 if (!len) {
1130 sc_log(ctx, "EF(TokenInfo) is empty");
1131 goto end;
1132 }
1133 if (len > MAX_FILE_SIZE) {
1134 sc_log(ctx, "EF(TokenInfo) too large");
1135 goto end;
1136 }
1137 buf = malloc(len);
1138 if(buf == NULL) {
1139 err = SC_ERROR_OUT_OF_MEMORY;
1140 goto end;
1141 }
1142
1143 err = -1; /* file state: not in cache */
1144 if (p15card->opts.use_file_cache) {
1145 err = sc_pkcs15_read_cached_file(p15card, &tmppath, &buf, &len);
1146 if (err == SC_SUCCESS)
1147 err = len;
1148 }
1149 if (err < 0) {
1150 err = sc_read_binary(card, 0, buf, len, 0);
1151 if (err <= 2) {
1152 if (err < 0) {
1153 sc_log(ctx, "read EF(TokenInfo) file error: %s", sc_strerror(err));
1154 } else {
1155 err = SC_ERROR_PKCS15_APP_NOT_FOUND;
1156 sc_log(ctx, "Invalid content of EF(TokenInfo): %s", sc_strerror(err));
1157 }
1158 goto end;
1159 }
1160 /* sc_read_binary may return less than requested */
1161 len = err;
1162
1163 if (p15card->opts.use_file_cache) {
1164 sc_pkcs15_cache_file(p15card, &tmppath, buf, len);
1165 }
1166 }
1167
1168 memset(&tokeninfo, 0, sizeof(tokeninfo));
1169 err = sc_pkcs15_parse_tokeninfo(ctx, &tokeninfo, buf, (size_t)err);
1170 if (err != SC_SUCCESS) {
1171 sc_log(ctx, "cannot parse TokenInfo content: %s", sc_strerror(err));
1172 goto end;
1173 }
1174
1175 sc_pkcs15_clear_tokeninfo(p15card->tokeninfo);
1176 *(p15card->tokeninfo) = tokeninfo;
1177
1178 if (!p15card->tokeninfo->serial_number && 0 == card->serialnr.len) {
1179 sc_card_ctl(p15card->card, SC_CARDCTL_GET_SERIALNR, &card->serialnr);
1180 }
1181
1182 if (!p15card->tokeninfo->serial_number && card->serialnr.len) {
1183 char *serial = calloc(1, card->serialnr.len*2 + 1);
1184 size_t ii;
1185 if (!serial) {
1186 err = SC_ERROR_OUT_OF_MEMORY;
1187 goto end;
1188 }
1189
1190 for(ii=0;ii<card->serialnr.len;ii++)
1191 sprintf(serial + ii*2, "%02X", *(card->serialnr.value + ii));
1192
1193 p15card->tokeninfo->serial_number = serial;
1194 sc_log(ctx, "p15card->tokeninfo->serial_number %s", p15card->tokeninfo->serial_number);
1195 }
1196
1197 ok = 1;
1198 end:
1199 if(buf != NULL)
1200 free(buf);
1201 if (!ok) {
1202 sc_pkcs15_card_clear(p15card);
1203 if (err == SC_ERROR_FILE_NOT_FOUND)
1204 err = SC_ERROR_WRONG_CARD;
1205 LOG_FUNC_RETURN(ctx, err);
1206 }
1207
1208 LOG_FUNC_RETURN(ctx, SC_SUCCESS);
1209 }
1210
1211
1212 int
sc_pkcs15_bind(struct sc_card * card,struct sc_aid * aid,struct sc_pkcs15_card ** p15card_out)1213 sc_pkcs15_bind(struct sc_card *card, struct sc_aid *aid,
1214 struct sc_pkcs15_card **p15card_out)
1215 {
1216 struct sc_pkcs15_card *p15card = NULL;
1217 struct sc_context *ctx;
1218 scconf_block *conf_block = NULL;
1219 int r, emu_first, enable_emu;
1220 const char *private_certificate;
1221
1222 if (card == NULL || p15card_out == NULL) {
1223 return SC_ERROR_INVALID_ARGUMENTS;
1224 }
1225 ctx = card->ctx;
1226
1227 LOG_FUNC_CALLED(ctx);
1228 sc_log(ctx, "application(aid:'%s')", aid ? sc_dump_hex(aid->value, aid->len) : "empty");
1229
1230 p15card = sc_pkcs15_card_new();
1231 if (p15card == NULL)
1232 LOG_FUNC_RETURN(ctx, SC_ERROR_OUT_OF_MEMORY);
1233
1234 p15card->card = card;
1235 p15card->opts.use_file_cache = 0;
1236 p15card->opts.use_pin_cache = 1;
1237 p15card->opts.pin_cache_counter = 10;
1238 p15card->opts.pin_cache_ignore_user_consent = 0;
1239 if(0 == strcmp(ctx->app_name, "tokend")) {
1240 private_certificate = "ignore";
1241 p15card->opts.private_certificate = SC_PKCS15_CARD_OPTS_PRIV_CERT_IGNORE;
1242 } else {
1243 private_certificate = "protect";
1244 p15card->opts.private_certificate = SC_PKCS15_CARD_OPTS_PRIV_CERT_PROTECT;
1245 }
1246
1247 conf_block = sc_get_conf_block(ctx, "framework", "pkcs15", 1);
1248 if (conf_block) {
1249 p15card->opts.use_file_cache = scconf_get_bool(conf_block, "use_file_caching", p15card->opts.use_file_cache);
1250 p15card->opts.use_pin_cache = scconf_get_bool(conf_block, "use_pin_caching", p15card->opts.use_pin_cache);
1251 p15card->opts.pin_cache_counter = scconf_get_int(conf_block, "pin_cache_counter", p15card->opts.pin_cache_counter);
1252 p15card->opts.pin_cache_ignore_user_consent = scconf_get_bool(conf_block, "pin_cache_ignore_user_consent",
1253 p15card->opts.pin_cache_ignore_user_consent);
1254 private_certificate = scconf_get_str(conf_block, "private_certificate", private_certificate);
1255 }
1256 if (0 == strcmp(private_certificate, "protect")) {
1257 p15card->opts.private_certificate = SC_PKCS15_CARD_OPTS_PRIV_CERT_PROTECT;
1258 } else if (0 == strcmp(private_certificate, "ignore")) {
1259 p15card->opts.private_certificate = SC_PKCS15_CARD_OPTS_PRIV_CERT_IGNORE;
1260 } else if (0 == strcmp(private_certificate, "declassify")) {
1261 p15card->opts.private_certificate = SC_PKCS15_CARD_OPTS_PRIV_CERT_DECLASSIFY;
1262 }
1263 sc_log(ctx, "PKCS#15 options: use_file_cache=%d use_pin_cache=%d pin_cache_counter=%d pin_cache_ignore_user_consent=%d private_certificate=%d",
1264 p15card->opts.use_file_cache, p15card->opts.use_pin_cache,p15card->opts.pin_cache_counter,
1265 p15card->opts.pin_cache_ignore_user_consent, p15card->opts.private_certificate);
1266
1267 r = sc_lock(card);
1268 if (r) {
1269 sc_log(ctx, "sc_lock() failed: %s", sc_strerror(r));
1270 sc_pkcs15_card_free(p15card);
1271 LOG_FUNC_RETURN(ctx, r);
1272 }
1273
1274 enable_emu = scconf_get_bool(conf_block, "enable_pkcs15_emulation", 1);
1275 if (enable_emu) {
1276 sc_log(ctx, "PKCS#15 emulation enabled");
1277 emu_first = scconf_get_bool(conf_block, "try_emulation_first", 0);
1278 if (emu_first || sc_pkcs15_is_emulation_only(card)) {
1279 r = sc_pkcs15_bind_synthetic(p15card, aid);
1280 if (r == SC_SUCCESS)
1281 goto done;
1282 r = sc_pkcs15_bind_internal(p15card, aid);
1283 if (r < 0)
1284 goto error;
1285 } else {
1286 r = sc_pkcs15_bind_internal(p15card, aid);
1287 if (r == SC_SUCCESS)
1288 goto done;
1289 r = sc_pkcs15_bind_synthetic(p15card, aid);
1290 if (r < 0)
1291 goto error;
1292 }
1293 }
1294 else {
1295 r = sc_pkcs15_bind_internal(p15card, aid);
1296 if (r < 0)
1297 goto error;
1298 }
1299 done:
1300 *p15card_out = p15card;
1301 sc_unlock(card);
1302 LOG_FUNC_RETURN(ctx, SC_SUCCESS);
1303 error:
1304 sc_unlock(card);
1305 sc_pkcs15_card_free(p15card);
1306 LOG_FUNC_RETURN(ctx, r);
1307 }
1308
1309
1310 int
sc_pkcs15_unbind(struct sc_pkcs15_card * p15card)1311 sc_pkcs15_unbind(struct sc_pkcs15_card *p15card)
1312 {
1313 if (p15card == NULL || p15card->magic != SC_PKCS15_CARD_MAGIC) {
1314 return SC_ERROR_INVALID_ARGUMENTS;
1315 }
1316
1317 LOG_FUNC_CALLED(p15card->card->ctx);
1318 if (p15card->dll_handle)
1319 sc_dlclose(p15card->dll_handle);
1320 sc_pkcs15_pincache_clear(p15card);
1321 sc_pkcs15_card_free(p15card);
1322 return 0;
1323 }
1324
1325
1326 static int
__sc_pkcs15_search_objects(struct sc_pkcs15_card * p15card,unsigned int class_mask,unsigned int type,int (* func)(sc_pkcs15_object_t *,void *),void * func_arg,sc_pkcs15_object_t ** ret,size_t ret_size)1327 __sc_pkcs15_search_objects(struct sc_pkcs15_card *p15card, unsigned int class_mask, unsigned int type,
1328 int (*func)(sc_pkcs15_object_t *, void *), void *func_arg,
1329 sc_pkcs15_object_t **ret, size_t ret_size)
1330 {
1331 struct sc_pkcs15_object *obj = NULL;
1332 struct sc_pkcs15_df *df = NULL;
1333 unsigned int df_mask = 0;
1334 size_t match_count = 0;
1335 int r;
1336
1337 if (type)
1338 class_mask |= SC_PKCS15_TYPE_TO_CLASS(type);
1339
1340 /* Make sure the class mask we have makes sense */
1341 if (class_mask == 0
1342 || (class_mask & ~(
1343 SC_PKCS15_SEARCH_CLASS_PRKEY |
1344 SC_PKCS15_SEARCH_CLASS_PUBKEY |
1345 SC_PKCS15_SEARCH_CLASS_SKEY |
1346 SC_PKCS15_SEARCH_CLASS_CERT |
1347 SC_PKCS15_SEARCH_CLASS_DATA |
1348 SC_PKCS15_SEARCH_CLASS_AUTH))) {
1349 LOG_FUNC_RETURN(p15card->card->ctx, SC_ERROR_INVALID_ARGUMENTS);
1350 }
1351
1352 if (class_mask & SC_PKCS15_SEARCH_CLASS_PRKEY)
1353 df_mask |= (1 << SC_PKCS15_PRKDF);
1354 if (class_mask & SC_PKCS15_SEARCH_CLASS_PUBKEY)
1355 df_mask |= (1 << SC_PKCS15_PUKDF) | (1 << SC_PKCS15_PUKDF_TRUSTED);
1356 if (class_mask & SC_PKCS15_SEARCH_CLASS_CERT)
1357 df_mask |= (1 << SC_PKCS15_CDF) | (1 << SC_PKCS15_CDF_TRUSTED) | (1 << SC_PKCS15_CDF_USEFUL);
1358 if (class_mask & SC_PKCS15_SEARCH_CLASS_DATA)
1359 df_mask |= (1 << SC_PKCS15_DODF);
1360 if (class_mask & SC_PKCS15_SEARCH_CLASS_AUTH)
1361 df_mask |= (1 << SC_PKCS15_AODF);
1362 if (class_mask & SC_PKCS15_SEARCH_CLASS_SKEY)
1363 df_mask |= (1 << SC_PKCS15_SKDF);
1364
1365 /* Make sure all the DFs we want to search have been
1366 * enumerated. */
1367 for (df = p15card->df_list; df != NULL; df = df->next) {
1368 if (!(df_mask & (1 << df->type))) {
1369 continue;
1370 }
1371 if (df->enumerated)
1372 continue;
1373 /* Enumerate the DF's, so p15card->obj_list is populated. */
1374 if (p15card->ops.parse_df)
1375 r = p15card->ops.parse_df(p15card, df);
1376 else
1377 r = sc_pkcs15_parse_df(p15card, df);
1378 if (r != SC_SUCCESS)
1379 continue;
1380 }
1381
1382 /* And now loop over all objects */
1383 for (obj = p15card->obj_list; obj != NULL; obj = obj->next) {
1384 /* Check object type */
1385 if (!(class_mask & SC_PKCS15_TYPE_TO_CLASS(obj->type)))
1386 continue;
1387 if (type != 0
1388 && obj->type != type
1389 && (obj->type & SC_PKCS15_TYPE_CLASS_MASK) != type)
1390 continue;
1391
1392 /* Potential candidate, apply search function */
1393 if (func != NULL && func(obj, func_arg) <= 0)
1394 continue;
1395 /* Okay, we have a match. */
1396 match_count++;
1397 if (!ret || ret_size <= 0)
1398 continue;
1399 ret[match_count-1] = obj;
1400 if (ret_size <= match_count)
1401 break;
1402 }
1403
1404 return match_count;
1405 }
1406
1407
1408 int
sc_pkcs15_get_objects(struct sc_pkcs15_card * p15card,unsigned int type,struct sc_pkcs15_object ** ret,size_t ret_size)1409 sc_pkcs15_get_objects(struct sc_pkcs15_card *p15card, unsigned int type,
1410 struct sc_pkcs15_object **ret, size_t ret_size)
1411 {
1412 return sc_pkcs15_get_objects_cond(p15card, type, NULL, NULL, ret, ret_size);
1413 }
1414
1415
1416 static int
compare_obj_id(struct sc_pkcs15_object * obj,const struct sc_pkcs15_id * id)1417 compare_obj_id(struct sc_pkcs15_object *obj, const struct sc_pkcs15_id *id)
1418 {
1419 void *data = obj->data;
1420
1421 switch (obj->type & SC_PKCS15_TYPE_CLASS_MASK) {
1422 case SC_PKCS15_TYPE_CERT:
1423 return sc_pkcs15_compare_id(&((struct sc_pkcs15_cert_info *) data)->id, id);
1424 case SC_PKCS15_TYPE_PRKEY:
1425 return sc_pkcs15_compare_id(&((struct sc_pkcs15_prkey_info *) data)->id, id);
1426 case SC_PKCS15_TYPE_PUBKEY:
1427 return sc_pkcs15_compare_id(&((struct sc_pkcs15_pubkey_info *) data)->id, id);
1428 case SC_PKCS15_TYPE_SKEY:
1429 return sc_pkcs15_compare_id(&((struct sc_pkcs15_skey_info *) data)->id, id);
1430 case SC_PKCS15_TYPE_AUTH:
1431 return sc_pkcs15_compare_id(&((struct sc_pkcs15_auth_info *) data)->auth_id, id);
1432 case SC_PKCS15_TYPE_DATA_OBJECT:
1433 return sc_pkcs15_compare_id(&((struct sc_pkcs15_data_info *) data)->id, id);
1434 }
1435 return 0;
1436 }
1437
1438
1439 static int
sc_obj_app_oid(struct sc_pkcs15_object * obj,const struct sc_object_id * app_oid)1440 sc_obj_app_oid(struct sc_pkcs15_object *obj, const struct sc_object_id *app_oid)
1441 {
1442 if ((obj->type & SC_PKCS15_TYPE_CLASS_MASK) == SC_PKCS15_TYPE_DATA_OBJECT)
1443 return sc_compare_oid(&((struct sc_pkcs15_data_info *) obj->data)->app_oid, app_oid);
1444 return 0;
1445 }
1446
1447
1448 static int
compare_obj_usage(struct sc_pkcs15_object * obj,unsigned int mask,unsigned int value)1449 compare_obj_usage(struct sc_pkcs15_object *obj, unsigned int mask, unsigned int value)
1450 {
1451 void *data = obj->data;
1452 unsigned int usage;
1453
1454 switch (obj->type & SC_PKCS15_TYPE_CLASS_MASK) {
1455 case SC_PKCS15_TYPE_PRKEY:
1456 usage = ((struct sc_pkcs15_prkey_info *) data)->usage;
1457 break;
1458 case SC_PKCS15_TYPE_PUBKEY:
1459 usage = ((struct sc_pkcs15_pubkey_info *) data)->usage;
1460 break;
1461 default:
1462 return 0;
1463 }
1464 return (usage & mask & value) != 0;
1465 }
1466
1467
1468 static int
compare_obj_flags(struct sc_pkcs15_object * obj,unsigned int mask,unsigned int value)1469 compare_obj_flags(struct sc_pkcs15_object *obj, unsigned int mask, unsigned int value)
1470 {
1471 struct sc_pkcs15_auth_info *auth_info;
1472 unsigned int flags;
1473
1474 switch (obj->type & SC_PKCS15_TYPE_CLASS_MASK) {
1475 case SC_PKCS15_TYPE_AUTH:
1476 auth_info = (struct sc_pkcs15_auth_info *) obj->data;
1477 if (auth_info->auth_type != SC_PKCS15_PIN_AUTH_TYPE_PIN)
1478 return 0;
1479 flags = auth_info->attrs.pin.flags;
1480 break;
1481 default:
1482 return 0;
1483 }
1484 return !((flags ^ value) & mask);
1485 }
1486
1487
1488 static int
compare_obj_reference(struct sc_pkcs15_object * obj,int value)1489 compare_obj_reference(struct sc_pkcs15_object *obj, int value)
1490 {
1491 struct sc_pkcs15_auth_info *auth_info;
1492 void *data = obj->data;
1493 int reference;
1494
1495 switch (obj->type & SC_PKCS15_TYPE_CLASS_MASK) {
1496 case SC_PKCS15_TYPE_AUTH:
1497 auth_info = (struct sc_pkcs15_auth_info *) obj->data;
1498 if (auth_info->auth_type != SC_PKCS15_PIN_AUTH_TYPE_PIN)
1499 return 0;
1500 reference = auth_info->attrs.pin.reference;
1501 break;
1502 case SC_PKCS15_TYPE_PRKEY:
1503 reference = ((struct sc_pkcs15_prkey_info *) data)->key_reference;
1504 break;
1505 default:
1506 return 0;
1507 }
1508 return reference == value;
1509 }
1510
1511
1512 static int
compare_obj_path(struct sc_pkcs15_object * obj,const struct sc_path * path)1513 compare_obj_path(struct sc_pkcs15_object *obj, const struct sc_path *path)
1514 {
1515 void *data = obj->data;
1516
1517 switch (obj->type & SC_PKCS15_TYPE_CLASS_MASK) {
1518 case SC_PKCS15_TYPE_PRKEY:
1519 return sc_compare_path(&((struct sc_pkcs15_prkey_info *) data)->path, path);
1520 case SC_PKCS15_TYPE_PUBKEY:
1521 return sc_compare_path(&((struct sc_pkcs15_pubkey_info *) data)->path, path);
1522 case SC_PKCS15_TYPE_SKEY:
1523 return sc_compare_path(&((struct sc_pkcs15_skey_info *) data)->path, path);
1524 case SC_PKCS15_TYPE_CERT:
1525 return sc_compare_path(&((struct sc_pkcs15_cert_info *) data)->path, path);
1526 case SC_PKCS15_TYPE_AUTH:
1527 return sc_compare_path(&((struct sc_pkcs15_auth_info *) data)->path, path);
1528 case SC_PKCS15_TYPE_DATA_OBJECT:
1529 return sc_compare_path(&((struct sc_pkcs15_data_info *) data)->path, path);
1530 }
1531 return 0;
1532 }
1533
1534
1535 static int
compare_obj_data_name(struct sc_pkcs15_object * obj,const char * app_label,const char * label)1536 compare_obj_data_name(struct sc_pkcs15_object *obj, const char *app_label, const char *label)
1537 {
1538 struct sc_pkcs15_data_info *cinfo = (struct sc_pkcs15_data_info *) obj->data;
1539
1540 if (obj->type != SC_PKCS15_TYPE_DATA_OBJECT)
1541 return 0;
1542
1543 return !strncmp(cinfo->app_label, app_label, sizeof cinfo->app_label) &&
1544 !strncmp(obj->label, label, sizeof obj->label);
1545 }
1546
1547
1548 static int
compare_obj_key(struct sc_pkcs15_object * obj,void * arg)1549 compare_obj_key(struct sc_pkcs15_object *obj, void *arg)
1550 {
1551 struct sc_pkcs15_search_key *sk = (struct sc_pkcs15_search_key *) arg;
1552
1553 if (sk->id && !compare_obj_id(obj, sk->id))
1554 return 0;
1555 if (sk->app_oid && !sc_obj_app_oid(obj, sk->app_oid))
1556 return 0;
1557 if (sk->usage_mask && !compare_obj_usage(obj, sk->usage_mask, sk->usage_value))
1558 return 0;
1559 if (sk->flags_mask && !compare_obj_flags(obj, sk->flags_mask, sk->flags_value))
1560 return 0;
1561 if (sk->match_reference && !compare_obj_reference(obj, sk->reference))
1562 return 0;
1563 if (sk->path && !compare_obj_path(obj, sk->path))
1564 return 0;
1565 if (
1566 sk->app_label && sk->label &&
1567 !compare_obj_data_name(obj, sk->app_label, sk->label)
1568 ) {
1569 return 0;
1570 }
1571
1572 return 1;
1573 }
1574
1575
1576 static int
find_by_key(struct sc_pkcs15_card * p15card,unsigned int type,struct sc_pkcs15_search_key * sk,struct sc_pkcs15_object ** out)1577 find_by_key(struct sc_pkcs15_card *p15card, unsigned int type, struct sc_pkcs15_search_key *sk,
1578 struct sc_pkcs15_object **out)
1579 {
1580 int r;
1581
1582 r = sc_pkcs15_get_objects_cond(p15card, type, compare_obj_key, sk, out, 1);
1583 if (r < 0)
1584 return r;
1585 if (r == 0)
1586 return SC_ERROR_OBJECT_NOT_FOUND;
1587 return 0;
1588 }
1589
1590
1591 int
sc_pkcs15_search_objects(struct sc_pkcs15_card * p15card,struct sc_pkcs15_search_key * sk,struct sc_pkcs15_object ** ret,size_t ret_size)1592 sc_pkcs15_search_objects(struct sc_pkcs15_card *p15card, struct sc_pkcs15_search_key *sk,
1593 struct sc_pkcs15_object **ret, size_t ret_size)
1594 {
1595 return __sc_pkcs15_search_objects(p15card,
1596 sk->class_mask, sk->type,
1597 compare_obj_key, sk,
1598 ret, ret_size);
1599 }
1600
1601
1602 int
sc_pkcs15_get_objects_cond(struct sc_pkcs15_card * p15card,unsigned int type,int (* func)(struct sc_pkcs15_object *,void *),void * func_arg,struct sc_pkcs15_object ** ret,size_t ret_size)1603 sc_pkcs15_get_objects_cond(struct sc_pkcs15_card *p15card, unsigned int type,
1604 int (* func)(struct sc_pkcs15_object *, void *),
1605 void *func_arg, struct sc_pkcs15_object **ret, size_t ret_size)
1606 {
1607 return __sc_pkcs15_search_objects(p15card, 0, type,
1608 func, func_arg, ret, ret_size);
1609 }
1610
1611
sc_pkcs15_find_object_by_id(struct sc_pkcs15_card * p15card,unsigned int type,const struct sc_pkcs15_id * id,struct sc_pkcs15_object ** out)1612 int sc_pkcs15_find_object_by_id(struct sc_pkcs15_card *p15card,
1613 unsigned int type, const struct sc_pkcs15_id *id,
1614 struct sc_pkcs15_object **out)
1615 {
1616 struct sc_pkcs15_search_key sk;
1617 int r;
1618
1619 memset(&sk, 0, sizeof(sk));
1620 sk.id = id;
1621
1622 r = __sc_pkcs15_search_objects(p15card, 0, type, compare_obj_key, &sk, out, 1);
1623 if (r < 0)
1624 return r;
1625 if (r == 0)
1626 return SC_ERROR_OBJECT_NOT_FOUND;
1627 return 0;
1628 }
1629
1630
1631 int
sc_pkcs15_find_cert_by_id(struct sc_pkcs15_card * p15card,const struct sc_pkcs15_id * id,struct sc_pkcs15_object ** out)1632 sc_pkcs15_find_cert_by_id(struct sc_pkcs15_card *p15card, const struct sc_pkcs15_id *id,
1633 struct sc_pkcs15_object **out)
1634 {
1635 return sc_pkcs15_find_object_by_id(p15card, SC_PKCS15_TYPE_CERT, id, out);
1636 }
1637
1638
1639 int
sc_pkcs15_find_prkey_by_id(struct sc_pkcs15_card * p15card,const struct sc_pkcs15_id * id,struct sc_pkcs15_object ** out)1640 sc_pkcs15_find_prkey_by_id(struct sc_pkcs15_card *p15card, const struct sc_pkcs15_id *id,
1641 struct sc_pkcs15_object **out)
1642 {
1643 return sc_pkcs15_find_object_by_id(p15card, SC_PKCS15_TYPE_PRKEY, id, out);
1644 }
1645
1646
1647 int
sc_pkcs15_find_pubkey_by_id(struct sc_pkcs15_card * p15card,const struct sc_pkcs15_id * id,struct sc_pkcs15_object ** out)1648 sc_pkcs15_find_pubkey_by_id(struct sc_pkcs15_card *p15card, const struct sc_pkcs15_id *id,
1649 struct sc_pkcs15_object **out)
1650 {
1651 return sc_pkcs15_find_object_by_id(p15card, SC_PKCS15_TYPE_PUBKEY, id, out);
1652 }
1653
1654
1655 int
sc_pkcs15_find_skey_by_id(struct sc_pkcs15_card * p15card,const struct sc_pkcs15_id * id,struct sc_pkcs15_object ** out)1656 sc_pkcs15_find_skey_by_id(struct sc_pkcs15_card *p15card, const struct sc_pkcs15_id *id,
1657 struct sc_pkcs15_object **out)
1658 {
1659 return sc_pkcs15_find_object_by_id(p15card, SC_PKCS15_TYPE_SKEY, id, out);
1660 }
1661
1662
1663 int
sc_pkcs15_find_pin_by_auth_id(struct sc_pkcs15_card * p15card,const struct sc_pkcs15_id * id,struct sc_pkcs15_object ** out)1664 sc_pkcs15_find_pin_by_auth_id(struct sc_pkcs15_card *p15card, const struct sc_pkcs15_id *id,
1665 struct sc_pkcs15_object **out)
1666 {
1667 return sc_pkcs15_find_object_by_id(p15card, SC_PKCS15_TYPE_AUTH, id, out);
1668 }
1669
1670
1671 int
sc_pkcs15_find_pin_by_reference(struct sc_pkcs15_card * p15card,const sc_path_t * path,int reference,struct sc_pkcs15_object ** out)1672 sc_pkcs15_find_pin_by_reference(struct sc_pkcs15_card *p15card, const sc_path_t *path, int reference,
1673 struct sc_pkcs15_object **out)
1674 {
1675 struct sc_pkcs15_search_key sk;
1676
1677 memset(&sk, 0, sizeof(sk));
1678 sk.match_reference = 1;
1679 sk.reference = reference;
1680 sk.path = path;
1681
1682 return find_by_key(p15card, SC_PKCS15_TYPE_AUTH_PIN, &sk, out);
1683 }
1684
1685
1686 int
sc_pkcs15_find_pin_by_type_and_reference(struct sc_pkcs15_card * p15card,const struct sc_path * path,unsigned auth_method,int reference,struct sc_pkcs15_object ** out)1687 sc_pkcs15_find_pin_by_type_and_reference(struct sc_pkcs15_card *p15card, const struct sc_path *path,
1688 unsigned auth_method, int reference,
1689 struct sc_pkcs15_object **out)
1690 {
1691 struct sc_context *ctx = p15card->card->ctx;
1692 struct sc_pkcs15_object *auth_objs[0x10];
1693 size_t nn_objs, ii;
1694 int r;
1695
1696 /* Get all existing pkcs15 AUTH objects */
1697 r = sc_pkcs15_get_objects(p15card, SC_PKCS15_TYPE_AUTH_PIN, auth_objs, 0x10);
1698 LOG_TEST_RET(ctx, r, "Get PKCS#15 AUTH objects error");
1699 nn_objs = r;
1700
1701 for (ii=0; ii<nn_objs; ii++) {
1702 struct sc_pkcs15_auth_info *auth_info = (struct sc_pkcs15_auth_info *)auth_objs[ii]->data;
1703
1704 if (auth_info->auth_method != auth_method)
1705 continue;
1706 if (auth_info->auth_type == SC_PKCS15_PIN_AUTH_TYPE_PIN)
1707 if (auth_info->attrs.pin.reference != reference)
1708 continue;
1709
1710 if (path && !sc_compare_path(&auth_info->path, path))
1711 continue;
1712
1713 if (out)
1714 *out = auth_objs[ii];
1715
1716 return SC_SUCCESS;
1717 }
1718
1719 return SC_ERROR_OBJECT_NOT_FOUND;
1720 }
1721
1722
1723 int
sc_pkcs15_find_so_pin(struct sc_pkcs15_card * p15card,struct sc_pkcs15_object ** out)1724 sc_pkcs15_find_so_pin(struct sc_pkcs15_card *p15card, struct sc_pkcs15_object **out)
1725 {
1726 struct sc_pkcs15_search_key sk;
1727
1728 memset(&sk, 0, sizeof(sk));
1729 sk.flags_mask = sk.flags_value = SC_PKCS15_PIN_FLAG_SO_PIN;
1730
1731 return find_by_key(p15card, SC_PKCS15_TYPE_AUTH_PIN, &sk, out);
1732 }
1733
1734
1735 int
sc_pkcs15_find_pin_by_flags(struct sc_pkcs15_card * p15card,unsigned flags,unsigned mask,int * index,struct sc_pkcs15_object ** out)1736 sc_pkcs15_find_pin_by_flags(struct sc_pkcs15_card *p15card,
1737 unsigned flags, unsigned mask, int *index,
1738 struct sc_pkcs15_object **out)
1739 {
1740 struct sc_context *ctx = p15card->card->ctx;
1741 struct sc_pkcs15_object *auths[SC_PKCS15_MAX_PINS];
1742 int r, i, num, idx = 0;
1743
1744 LOG_FUNC_CALLED(ctx);
1745 sc_log(ctx, "Find PIN flags:0x%X, mask:0x%X, index:%i", flags, mask, index ? *index : -1);
1746 if (index)
1747 idx = *index;
1748 /* Get authentication PKCS#15 objects that are present in the given application */
1749 r = sc_pkcs15_get_objects(p15card, SC_PKCS15_TYPE_AUTH_PIN, auths, SC_PKCS15_MAX_PINS);
1750 if (r < 0)
1751 return r;
1752 num = r;
1753
1754 for (i=idx; i<num; i++) {
1755 struct sc_pkcs15_auth_info *pin_info = (struct sc_pkcs15_auth_info *)(*(auths + i))->data;
1756
1757 if (!pin_info || pin_info->auth_type != SC_PKCS15_PIN_AUTH_TYPE_PIN)
1758 continue;
1759
1760 if ((pin_info->attrs.pin.flags & mask) != flags)
1761 continue;
1762
1763 if (out)
1764 *out = *(auths + i);
1765 if (index)
1766 *index = i;
1767
1768 LOG_FUNC_RETURN(ctx, SC_SUCCESS);
1769 }
1770
1771 LOG_FUNC_RETURN(ctx, SC_ERROR_OBJECT_NOT_FOUND);
1772 }
1773
1774
1775 int
sc_pkcs15_find_data_object_by_id(struct sc_pkcs15_card * p15card,const struct sc_pkcs15_id * id,struct sc_pkcs15_object ** out)1776 sc_pkcs15_find_data_object_by_id(struct sc_pkcs15_card *p15card, const struct sc_pkcs15_id *id,
1777 struct sc_pkcs15_object **out)
1778 {
1779 return sc_pkcs15_find_object_by_id(p15card, SC_PKCS15_TYPE_DATA_OBJECT, id, out);
1780 }
1781
1782
1783 int
sc_pkcs15_find_data_object_by_app_oid(struct sc_pkcs15_card * p15card,const struct sc_object_id * app_oid,struct sc_pkcs15_object ** out)1784 sc_pkcs15_find_data_object_by_app_oid(struct sc_pkcs15_card *p15card, const struct sc_object_id *app_oid,
1785 struct sc_pkcs15_object **out)
1786 {
1787 struct sc_pkcs15_search_key sk;
1788 int r;
1789
1790 memset(&sk, 0, sizeof(sk));
1791 sk.app_oid = app_oid;
1792
1793 r = __sc_pkcs15_search_objects(p15card, 0, SC_PKCS15_TYPE_DATA_OBJECT,
1794 compare_obj_key, &sk,
1795 out, 1);
1796 if (r < 0)
1797 return r;
1798 if (r == 0)
1799 return SC_ERROR_OBJECT_NOT_FOUND;
1800 return 0;
1801 }
1802
1803
1804 int
sc_pkcs15_find_data_object_by_name(struct sc_pkcs15_card * p15card,const char * app_label,const char * label,struct sc_pkcs15_object ** out)1805 sc_pkcs15_find_data_object_by_name(struct sc_pkcs15_card *p15card, const char *app_label, const char *label,
1806 struct sc_pkcs15_object **out)
1807 {
1808 struct sc_pkcs15_search_key sk;
1809 int r;
1810
1811 memset(&sk, 0, sizeof(sk));
1812 sk.app_label = app_label;
1813 sk.label = label;
1814
1815 r = __sc_pkcs15_search_objects(p15card, 0, SC_PKCS15_TYPE_DATA_OBJECT,
1816 compare_obj_key, &sk,
1817 out, 1);
1818 if (r < 0)
1819 return r;
1820 if (r == 0)
1821 return SC_ERROR_OBJECT_NOT_FOUND;
1822 return 0;
1823 }
1824
1825
1826 int
sc_pkcs15_find_prkey_by_id_usage(struct sc_pkcs15_card * p15card,const struct sc_pkcs15_id * id,unsigned int usage,struct sc_pkcs15_object ** out)1827 sc_pkcs15_find_prkey_by_id_usage(struct sc_pkcs15_card *p15card, const struct sc_pkcs15_id *id,
1828 unsigned int usage, struct sc_pkcs15_object **out)
1829 {
1830 struct sc_pkcs15_search_key sk;
1831
1832 memset(&sk, 0, sizeof(sk));
1833 sk.usage_mask = sk.usage_value = usage;
1834 sk.id = id;
1835
1836 return find_by_key(p15card, SC_PKCS15_TYPE_PRKEY, &sk, out);
1837 }
1838
1839
1840 int
sc_pkcs15_find_prkey_by_reference(struct sc_pkcs15_card * p15card,const struct sc_path * path,int reference,struct sc_pkcs15_object ** out)1841 sc_pkcs15_find_prkey_by_reference(struct sc_pkcs15_card *p15card, const struct sc_path *path,
1842 int reference,
1843 struct sc_pkcs15_object **out)
1844 {
1845 struct sc_pkcs15_search_key sk;
1846
1847 memset(&sk, 0, sizeof(sk));
1848 sk.match_reference = 1;
1849 sk.reference = reference;
1850 sk.path = path;
1851
1852 return find_by_key(p15card, SC_PKCS15_TYPE_PRKEY, &sk, out);
1853 }
1854
1855
1856 int
sc_pkcs15_add_object(struct sc_pkcs15_card * p15card,struct sc_pkcs15_object * obj)1857 sc_pkcs15_add_object(struct sc_pkcs15_card *p15card, struct sc_pkcs15_object *obj)
1858 {
1859 struct sc_pkcs15_object *p = p15card->obj_list;
1860
1861 if (!obj)
1862 return 0;
1863 obj->next = obj->prev = NULL;
1864 if (p15card->obj_list == NULL) {
1865 p15card->obj_list = obj;
1866 return 0;
1867 }
1868 while (p->next != NULL)
1869 p = p->next;
1870 p->next = obj;
1871 obj->prev = p;
1872
1873 return 0;
1874 }
1875
1876
1877 void
sc_pkcs15_remove_object(struct sc_pkcs15_card * p15card,struct sc_pkcs15_object * obj)1878 sc_pkcs15_remove_object(struct sc_pkcs15_card *p15card, struct sc_pkcs15_object *obj)
1879 {
1880 if (!obj)
1881 return;
1882 else if (obj->prev == NULL)
1883 p15card->obj_list = obj->next;
1884 else
1885 obj->prev->next = obj->next;
1886 if (obj->next != NULL)
1887 obj->next->prev = obj->prev;
1888 }
1889
1890
1891 static void
sc_pkcs15_remove_objects(struct sc_pkcs15_card * p15card)1892 sc_pkcs15_remove_objects(struct sc_pkcs15_card *p15card)
1893 {
1894 struct sc_pkcs15_object *cur = NULL, *next = NULL;
1895
1896 if (!p15card || !p15card->obj_list)
1897 return;
1898 for (cur = p15card->obj_list; cur; cur = next) {
1899 next = cur->next;
1900 sc_pkcs15_free_object(cur);
1901 }
1902
1903 p15card->obj_list = NULL;
1904 }
1905
1906
1907 void
sc_pkcs15_free_object(struct sc_pkcs15_object * obj)1908 sc_pkcs15_free_object(struct sc_pkcs15_object *obj)
1909 {
1910 if (!obj)
1911 return;
1912 switch (obj->type & SC_PKCS15_TYPE_CLASS_MASK) {
1913 case SC_PKCS15_TYPE_PRKEY:
1914 sc_pkcs15_free_prkey_info((sc_pkcs15_prkey_info_t *)obj->data);
1915 break;
1916 case SC_PKCS15_TYPE_PUBKEY:
1917 /* This is normally passed to framework-pkcs15,
1918 * but if something fails on the way, it would not get freed */
1919 if (obj->emulated) {
1920 sc_pkcs15_free_pubkey(obj->emulated);
1921 }
1922 sc_pkcs15_free_pubkey_info((sc_pkcs15_pubkey_info_t *)obj->data);
1923 break;
1924 case SC_PKCS15_TYPE_CERT:
1925 sc_pkcs15_free_cert_info((sc_pkcs15_cert_info_t *)obj->data);
1926 break;
1927 case SC_PKCS15_TYPE_DATA_OBJECT:
1928 sc_pkcs15_free_data_info((sc_pkcs15_data_info_t *)obj->data);
1929 break;
1930 case SC_PKCS15_TYPE_AUTH:
1931 sc_pkcs15_free_auth_info((sc_pkcs15_auth_info_t *)obj->data);
1932 break;
1933 default:
1934 free(obj->data);
1935 }
1936
1937 sc_pkcs15_free_object_content(obj);
1938
1939 free(obj);
1940 }
1941
1942
1943 int
sc_pkcs15_add_df(struct sc_pkcs15_card * p15card,unsigned int type,const sc_path_t * path)1944 sc_pkcs15_add_df(struct sc_pkcs15_card *p15card, unsigned int type, const sc_path_t *path)
1945 {
1946 struct sc_pkcs15_df *p, *newdf;
1947
1948 newdf = calloc(1, sizeof(struct sc_pkcs15_df));
1949 if (newdf == NULL)
1950 return SC_ERROR_OUT_OF_MEMORY;
1951 newdf->path = *path;
1952 newdf->type = type;
1953
1954 if (p15card->df_list == NULL) {
1955 p15card->df_list = newdf;
1956 return 0;
1957 }
1958
1959 p = p15card->df_list;
1960 while (p->next != NULL)
1961 p = p->next;
1962 p->next = newdf;
1963 newdf->prev = p;
1964
1965 return 0;
1966 }
1967
1968
1969 static void
sc_pkcs15_remove_dfs(struct sc_pkcs15_card * p15card)1970 sc_pkcs15_remove_dfs(struct sc_pkcs15_card *p15card)
1971 {
1972 struct sc_pkcs15_df *cur = NULL, *next = NULL;
1973
1974 if (!p15card || !p15card->df_list)
1975 return;
1976
1977 for (cur = p15card->df_list; cur; cur = next) {
1978 next = cur->next;
1979 free(cur);
1980 }
1981
1982 p15card->df_list = NULL;
1983 }
1984
1985
1986 int
sc_pkcs15_encode_df(struct sc_context * ctx,struct sc_pkcs15_card * p15card,struct sc_pkcs15_df * df,unsigned char ** buf_out,size_t * bufsize_out)1987 sc_pkcs15_encode_df(struct sc_context *ctx, struct sc_pkcs15_card *p15card, struct sc_pkcs15_df *df,
1988 unsigned char **buf_out, size_t *bufsize_out)
1989 {
1990 unsigned char *buf = NULL, *tmp = NULL, *p;
1991 size_t bufsize = 0, tmpsize;
1992 const struct sc_pkcs15_object *obj;
1993 int (* func)(struct sc_context *, const struct sc_pkcs15_object *nobj,
1994 unsigned char **nbuf, size_t *nbufsize) = NULL;
1995 int r;
1996
1997 if (p15card == NULL || p15card->magic != SC_PKCS15_CARD_MAGIC) {
1998 return SC_ERROR_INVALID_ARGUMENTS;
1999 }
2000 switch (df->type) {
2001 case SC_PKCS15_PRKDF:
2002 func = sc_pkcs15_encode_prkdf_entry;
2003 break;
2004 case SC_PKCS15_PUKDF:
2005 case SC_PKCS15_PUKDF_TRUSTED:
2006 func = sc_pkcs15_encode_pukdf_entry;
2007 break;
2008 case SC_PKCS15_SKDF:
2009 func = sc_pkcs15_encode_skdf_entry;
2010 break;
2011 case SC_PKCS15_CDF:
2012 case SC_PKCS15_CDF_TRUSTED:
2013 case SC_PKCS15_CDF_USEFUL:
2014 func = sc_pkcs15_encode_cdf_entry;
2015 break;
2016 case SC_PKCS15_DODF:
2017 func = sc_pkcs15_encode_dodf_entry;
2018 break;
2019 case SC_PKCS15_AODF:
2020 func = sc_pkcs15_encode_aodf_entry;
2021 break;
2022 }
2023 if (func == NULL) {
2024 sc_log(ctx, "unknown DF type: %d", df->type);
2025 *buf_out = NULL;
2026 *bufsize_out = 0;
2027 return 0;
2028 }
2029 for (obj = p15card->obj_list; obj != NULL; obj = obj->next) {
2030 if (obj->df != df)
2031 continue;
2032 r = func(ctx, obj, &tmp, &tmpsize);
2033 if (r) {
2034 free(tmp);
2035 free(buf);
2036 return r;
2037 }
2038 if (!tmpsize)
2039 continue;
2040 p = (u8 *) realloc(buf, bufsize + tmpsize);
2041 if (!p) {
2042 free(tmp);
2043 free(buf);
2044 return SC_ERROR_OUT_OF_MEMORY;
2045 }
2046 buf = p;
2047 memcpy(buf + bufsize, tmp, tmpsize);
2048 free(tmp);
2049 bufsize += tmpsize;
2050 }
2051 *buf_out = buf;
2052 *bufsize_out = bufsize;
2053
2054 return 0;
2055 }
2056
2057
2058 int
sc_pkcs15_parse_df(struct sc_pkcs15_card * p15card,struct sc_pkcs15_df * df)2059 sc_pkcs15_parse_df(struct sc_pkcs15_card *p15card, struct sc_pkcs15_df *df)
2060 {
2061 struct sc_context *ctx = p15card->card->ctx;
2062 unsigned char *buf;
2063 const unsigned char *p;
2064 size_t bufsize;
2065 int r;
2066 struct sc_pkcs15_object *obj = NULL;
2067 int (* func)(struct sc_pkcs15_card *, struct sc_pkcs15_object *,
2068 const u8 **nbuf, size_t *nbufsize) = NULL;
2069
2070 sc_log(ctx, "called; path=%s, type=%d, enum=%d", sc_print_path(&df->path), df->type, df->enumerated);
2071
2072 if (df->enumerated)
2073 LOG_FUNC_RETURN(ctx, SC_SUCCESS);
2074
2075 switch (df->type) {
2076 case SC_PKCS15_PRKDF:
2077 func = sc_pkcs15_decode_prkdf_entry;
2078 break;
2079 case SC_PKCS15_PUKDF:
2080 func = sc_pkcs15_decode_pukdf_entry;
2081 break;
2082 case SC_PKCS15_SKDF:
2083 func = sc_pkcs15_decode_skdf_entry;
2084 break;
2085 case SC_PKCS15_CDF:
2086 case SC_PKCS15_CDF_TRUSTED:
2087 case SC_PKCS15_CDF_USEFUL:
2088 func = sc_pkcs15_decode_cdf_entry;
2089 break;
2090 case SC_PKCS15_DODF:
2091 func = sc_pkcs15_decode_dodf_entry;
2092 break;
2093 case SC_PKCS15_AODF:
2094 func = sc_pkcs15_decode_aodf_entry;
2095 break;
2096 }
2097 if (func == NULL) {
2098 sc_log(ctx, "unknown DF type: %d", df->type);
2099 LOG_FUNC_RETURN(ctx, SC_ERROR_INVALID_ARGUMENTS);
2100 }
2101 r = sc_pkcs15_read_file(p15card, &df->path, &buf, &bufsize);
2102 LOG_TEST_RET(ctx, r, "pkcs15 read file failed");
2103
2104 p = buf;
2105 while (bufsize && *p != 0x00) {
2106
2107 obj = calloc(1, sizeof(struct sc_pkcs15_object));
2108 if (obj == NULL) {
2109 r = SC_ERROR_OUT_OF_MEMORY;
2110 goto ret;
2111 }
2112 r = func(p15card, obj, &p, &bufsize);
2113 if (r) {
2114 free(obj);
2115 if (r == SC_ERROR_ASN1_END_OF_CONTENTS) {
2116 r = 0;
2117 break;
2118 }
2119 sc_log(ctx, "%s: Error decoding DF entry", sc_strerror(r));
2120 goto ret;
2121 }
2122
2123 obj->df = df;
2124 r = sc_pkcs15_add_object(p15card, obj);
2125 if (r) {
2126 if (obj->data)
2127 free(obj->data);
2128 free(obj);
2129 sc_log(ctx, "%s: Error adding object", sc_strerror(r));
2130 goto ret;
2131 }
2132 };
2133
2134 if (r > 0)
2135 r = 0;
2136 ret:
2137 df->enumerated = 1;
2138 free(buf);
2139 LOG_FUNC_RETURN(ctx, r);
2140 }
2141
2142
2143 int
sc_pkcs15_add_unusedspace(struct sc_pkcs15_card * p15card,const struct sc_path * path,const struct sc_pkcs15_id * auth_id)2144 sc_pkcs15_add_unusedspace(struct sc_pkcs15_card *p15card, const struct sc_path *path,
2145 const struct sc_pkcs15_id *auth_id)
2146 {
2147 struct sc_context *ctx = p15card->card->ctx;
2148 struct sc_pkcs15_unusedspace *p = p15card->unusedspace_list, *new_unusedspace;
2149
2150 if (path->count == -1) {
2151 char pbuf[SC_MAX_PATH_STRING_SIZE];
2152
2153 int r = sc_path_print(pbuf, sizeof(pbuf), path);
2154 if (r != SC_SUCCESS)
2155 pbuf[0] = '\0';
2156
2157 sc_log(ctx, "No offset and length present in path %s", pbuf);
2158 return SC_ERROR_INVALID_ARGUMENTS;
2159 }
2160
2161 new_unusedspace = calloc(1, sizeof(sc_pkcs15_unusedspace_t));
2162 if (new_unusedspace == NULL)
2163 return SC_ERROR_OUT_OF_MEMORY;
2164 new_unusedspace->path = *path;
2165 if (auth_id != NULL)
2166 new_unusedspace->auth_id = *auth_id;
2167
2168 if (p15card->unusedspace_list == NULL) {
2169 p15card->unusedspace_list = new_unusedspace;
2170 return 0;
2171 }
2172 while (p->next != NULL)
2173 p = p->next;
2174 p->next = new_unusedspace;
2175 new_unusedspace->prev = p;
2176
2177 return 0;
2178 }
2179
2180
2181 void
sc_pkcs15_remove_unusedspace(struct sc_pkcs15_card * p15card,struct sc_pkcs15_unusedspace * unusedspace)2182 sc_pkcs15_remove_unusedspace(struct sc_pkcs15_card *p15card, struct sc_pkcs15_unusedspace *unusedspace)
2183 {
2184 if (!unusedspace)
2185 return;
2186
2187 if (!unusedspace->prev)
2188 p15card->unusedspace_list = unusedspace->next;
2189 else
2190 unusedspace->prev->next = unusedspace->next;
2191
2192 if (unusedspace->next)
2193 unusedspace->next->prev = unusedspace->prev;
2194
2195 free(unusedspace);
2196 }
2197
2198
2199 static void
sc_pkcs15_free_unusedspace(struct sc_pkcs15_card * p15card)2200 sc_pkcs15_free_unusedspace(struct sc_pkcs15_card *p15card)
2201 {
2202 struct sc_pkcs15_unusedspace *cur = NULL, *next = NULL;
2203
2204 if (!p15card || !p15card->unusedspace_list)
2205 return;
2206 for (cur = p15card->unusedspace_list; cur; cur = next) {
2207 next = cur->next;
2208 free(cur);
2209 }
2210
2211 p15card->unusedspace_list = NULL;
2212 }
2213
2214
2215 int
sc_pkcs15_encode_unusedspace(struct sc_context * ctx,struct sc_pkcs15_card * p15card,unsigned char ** buf,size_t * buflen)2216 sc_pkcs15_encode_unusedspace(struct sc_context *ctx, struct sc_pkcs15_card *p15card,
2217 unsigned char **buf, size_t *buflen)
2218 {
2219 struct sc_path dummy_path;
2220 static const struct sc_asn1_entry c_asn1_unusedspace[] = {
2221 { "UnusedSpace", SC_ASN1_STRUCT, SC_ASN1_TAG_SEQUENCE | SC_ASN1_CONS, 0, NULL, NULL },
2222 { NULL, 0, 0, 0, NULL, NULL }
2223 };
2224 static const struct sc_asn1_entry c_asn1_unusedspace_values[] = {
2225 { "path", SC_ASN1_PATH, SC_ASN1_TAG_SEQUENCE | SC_ASN1_CONS, 0, NULL, NULL },
2226 { "authId", SC_ASN1_PKCS15_ID, SC_ASN1_TAG_OCTET_STRING, SC_ASN1_OPTIONAL, NULL, NULL },
2227 { NULL, 0, 0, 0, NULL, NULL }
2228 };
2229 struct sc_asn1_entry *asn1_unusedspace = NULL;
2230 struct sc_asn1_entry *asn1_values = NULL;
2231 int unusedspace_count = 0, r, c = 0;
2232 struct sc_pkcs15_unusedspace *unusedspace = NULL;
2233
2234 sc_format_path("3F00", &dummy_path);
2235 dummy_path.index = dummy_path.count = 0;
2236
2237 unusedspace = p15card->unusedspace_list;
2238 for ( ; unusedspace != NULL; unusedspace = unusedspace->next)
2239 unusedspace_count++;
2240 if (unusedspace_count == 0) {
2241 /* The standard says there has to be at least 1 entry,
2242 * so we use a path with a length of 0 bytes */
2243 r = sc_pkcs15_add_unusedspace(p15card, &dummy_path, NULL);
2244 if (r)
2245 return r;
2246 unusedspace_count = 1;
2247 }
2248
2249 asn1_unusedspace = (struct sc_asn1_entry *)
2250 malloc(sizeof(struct sc_asn1_entry) * (unusedspace_count + 1));
2251 if (asn1_unusedspace == NULL) {
2252 r = SC_ERROR_OUT_OF_MEMORY;
2253 goto err;
2254 }
2255 asn1_values = (struct sc_asn1_entry *)
2256 malloc(sizeof(struct sc_asn1_entry) * (unusedspace_count * 3));
2257 if (asn1_values == NULL) {
2258 r = SC_ERROR_OUT_OF_MEMORY;
2259 goto err;
2260 }
2261
2262 for (unusedspace = p15card->unusedspace_list; unusedspace != NULL; unusedspace = unusedspace->next) {
2263 sc_copy_asn1_entry(c_asn1_unusedspace, asn1_unusedspace + c);
2264 sc_format_asn1_entry(asn1_unusedspace + c, asn1_values + 3*c, NULL, 1);
2265 sc_copy_asn1_entry(c_asn1_unusedspace_values, asn1_values + 3*c);
2266 sc_format_asn1_entry(asn1_values + 3*c, &unusedspace->path, NULL, 1);
2267 sc_format_asn1_entry(asn1_values + 3*c+1, &unusedspace->auth_id, NULL,
2268 unusedspace->auth_id.len > 0 ? 1 : 0);
2269 c++;
2270 }
2271 asn1_unusedspace[c].name = NULL;
2272
2273 r = sc_asn1_encode(ctx, asn1_unusedspace, buf, buflen);
2274
2275 err:
2276 if (asn1_values != NULL)
2277 free(asn1_values);
2278 if (asn1_unusedspace != NULL)
2279 free(asn1_unusedspace);
2280
2281 /* If we added the dummy entry, remove it now */
2282 if (unusedspace_count == 1 && sc_compare_path(&p15card->unusedspace_list->path, &dummy_path))
2283 sc_pkcs15_remove_unusedspace(p15card, p15card->unusedspace_list);
2284
2285 return r;
2286 }
2287
2288
2289 int
sc_pkcs15_parse_unusedspace(const unsigned char * buf,size_t buflen,struct sc_pkcs15_card * p15card)2290 sc_pkcs15_parse_unusedspace(const unsigned char *buf, size_t buflen, struct sc_pkcs15_card *p15card)
2291 {
2292 const unsigned char *p = buf;
2293 size_t left = buflen;
2294 int r;
2295 struct sc_path path;
2296 struct sc_pkcs15_id auth_id;
2297 struct sc_asn1_entry asn1_unusedspace[] = {
2298 { "UnusedSpace", SC_ASN1_STRUCT, SC_ASN1_TAG_SEQUENCE | SC_ASN1_CONS, 0, NULL, NULL },
2299 { NULL, 0, 0, 0, NULL, NULL }
2300 };
2301 struct sc_asn1_entry asn1_unusedspace_values[] = {
2302 { "path", SC_ASN1_PATH, SC_ASN1_TAG_SEQUENCE | SC_ASN1_CONS, 0, NULL, NULL },
2303 { "authId", SC_ASN1_PKCS15_ID, SC_ASN1_TAG_OCTET_STRING, SC_ASN1_OPTIONAL, NULL, NULL },
2304 { NULL, 0, 0, 0, NULL, NULL }
2305 };
2306
2307 /* Clean the list if already present */
2308 sc_pkcs15_free_unusedspace(p15card);
2309
2310 sc_format_asn1_entry(asn1_unusedspace, asn1_unusedspace_values, NULL, 1);
2311 sc_format_asn1_entry(asn1_unusedspace_values, &path, NULL, 1);
2312 sc_format_asn1_entry(asn1_unusedspace_values+1, &auth_id, NULL, 0);
2313
2314 while (left > 0) {
2315 memset(&auth_id, 0, sizeof(auth_id));
2316 r = sc_asn1_decode(p15card->card->ctx, asn1_unusedspace, p, left, &p, &left);
2317 if (r == SC_ERROR_ASN1_END_OF_CONTENTS)
2318 break;
2319 if (r < 0)
2320 return r;
2321 /* If the path length is 0, it's a dummy path then don't add it.
2322 * If the path length isn't included (-1) then it's against the standard
2323 * but we'll just ignore it instead of returning an error. */
2324 if (path.count > 0 && p15card->file_app) {
2325 r = sc_pkcs15_make_absolute_path(&p15card->file_app->path, &path);
2326 if (r < 0)
2327 return r;
2328 r = sc_pkcs15_add_unusedspace(p15card, &path, &auth_id);
2329 if (r)
2330 return r;
2331 }
2332 }
2333
2334 p15card->unusedspace_read = 1;
2335
2336 return 0;
2337 }
2338
2339
2340 int
sc_pkcs15_read_file(struct sc_pkcs15_card * p15card,const struct sc_path * in_path,unsigned char ** buf,size_t * buflen)2341 sc_pkcs15_read_file(struct sc_pkcs15_card *p15card, const struct sc_path *in_path,
2342 unsigned char **buf, size_t *buflen)
2343 {
2344 struct sc_context *ctx;
2345 struct sc_file *file = NULL;
2346 unsigned char *data = NULL;
2347 size_t len = 0, offset = 0;
2348 int r;
2349
2350 if (p15card == NULL || p15card->card == NULL || in_path == NULL || buf == NULL) {
2351 return SC_ERROR_INVALID_ARGUMENTS;
2352 }
2353 ctx = p15card->card->ctx;
2354
2355 LOG_FUNC_CALLED(ctx);
2356 sc_log(ctx, "path=%s, index=%u, count=%d", sc_print_path(in_path), in_path->index, in_path->count);
2357
2358 r = -1; /* file state: not in cache */
2359 if (p15card->opts.use_file_cache) {
2360 r = sc_pkcs15_read_cached_file(p15card, in_path, &data, &len);
2361
2362 if (!r && in_path->aid.len > 0 && in_path->len >= 2) {
2363 struct sc_path parent = *in_path;
2364
2365 parent.len -= 2;
2366 parent.type = SC_PATH_TYPE_PATH;
2367 r = sc_select_file(p15card->card, &parent, NULL);
2368 }
2369 }
2370
2371 if (r) {
2372 r = sc_lock(p15card->card);
2373 if (r)
2374 goto fail;
2375 r = sc_select_file(p15card->card, in_path, &file);
2376 if (r)
2377 goto fail_unlock;
2378
2379 /* Handle the case where the ASN.1 Path object specified
2380 * index and length values */
2381 if (in_path->count < 0) {
2382 if (file->size)
2383 len = file->size;
2384 else
2385 len = 1024;
2386 offset = 0;
2387 }
2388 else {
2389 offset = in_path->index;
2390 len = in_path->count;
2391 /* Make sure we're within proper bounds */
2392 if (offset >= file->size || offset + len > file->size) {
2393 r = SC_ERROR_INVALID_ASN1_OBJECT;
2394 goto fail_unlock;
2395 }
2396 }
2397 data = malloc(len);
2398 if (data == NULL) {
2399 r = SC_ERROR_OUT_OF_MEMORY;
2400 goto fail_unlock;
2401 }
2402
2403 if (file->ef_structure == SC_FILE_EF_LINEAR_VARIABLE_TLV) {
2404 unsigned int i;
2405 size_t l, record_len;
2406 unsigned char *head = data;
2407
2408 for (i=1; ; i++) {
2409 l = len - (head - data);
2410 if (l > 256) {
2411 l = 256;
2412 }
2413 r = sc_read_record(p15card->card, i, head, l, SC_RECORD_BY_REC_NR);
2414 if (r == SC_ERROR_RECORD_NOT_FOUND)
2415 break;
2416 if (r < 0) {
2417 goto fail_unlock;
2418 }
2419 if (r < 2)
2420 break;
2421 record_len = head[1];
2422 if (record_len != 0xff) {
2423 memmove(head, head+2, r-2);
2424 head += (r-2);
2425 }
2426 else {
2427 if (r < 4)
2428 break;
2429 memmove(head, head+4, r-4);
2430 head += (r-4);
2431 }
2432 }
2433 len = head-data;
2434 }
2435 else {
2436 r = sc_read_binary(p15card->card, offset, data, len, 0);
2437 if (r < 0) {
2438 goto fail_unlock;
2439 }
2440 /* sc_read_binary may return less than requested */
2441 len = r;
2442 }
2443 sc_unlock(p15card->card);
2444
2445 sc_file_free(file);
2446
2447 if (len && p15card->opts.use_file_cache) {
2448 sc_pkcs15_cache_file(p15card, in_path, data, len);
2449 }
2450 }
2451 *buf = data;
2452 *buflen = len;
2453 LOG_FUNC_RETURN(ctx, SC_SUCCESS);
2454
2455 fail_unlock:
2456 sc_unlock(p15card->card);
2457 fail:
2458 free(data);
2459 sc_file_free(file);
2460 LOG_FUNC_RETURN(ctx, r);
2461 }
2462
2463
2464 int
sc_pkcs15_compare_id(const struct sc_pkcs15_id * id1,const struct sc_pkcs15_id * id2)2465 sc_pkcs15_compare_id(const struct sc_pkcs15_id *id1, const struct sc_pkcs15_id *id2)
2466 {
2467 if (id1 == NULL || id2 == NULL)
2468 return 0;
2469 if (id1->len != id2->len)
2470 return 0;
2471 return memcmp(id1->value, id2->value, id1->len) == 0;
2472 }
2473
2474
2475 void
sc_pkcs15_format_id(const char * str,struct sc_pkcs15_id * id)2476 sc_pkcs15_format_id(const char *str, struct sc_pkcs15_id *id)
2477 {
2478 size_t len;
2479
2480 if (!id)
2481 return;
2482 len = sizeof(id->value);
2483
2484 if (sc_hex_to_bin(str, id->value, &len) != SC_SUCCESS)
2485 id->len = 0;
2486 else
2487 id->len = len;
2488 }
2489
2490
2491 const char *
sc_pkcs15_print_id(const struct sc_pkcs15_id * id)2492 sc_pkcs15_print_id(const struct sc_pkcs15_id *id)
2493 {
2494 static char buffer[256];
2495
2496 sc_bin_to_hex(id->value, id->len, buffer, sizeof(buffer), '\0');
2497 return buffer;
2498 }
2499
2500
2501 int
sc_pkcs15_hex_string_to_id(const char * in,struct sc_pkcs15_id * out)2502 sc_pkcs15_hex_string_to_id(const char *in, struct sc_pkcs15_id *out)
2503 {
2504 out->len = sizeof(out->value);
2505 return sc_hex_to_bin(in, out->value, &out->len);
2506 }
2507
2508
2509 int
sc_pkcs15_make_absolute_path(const struct sc_path * parent,struct sc_path * child)2510 sc_pkcs15_make_absolute_path(const struct sc_path *parent, struct sc_path *child)
2511 {
2512 /* nothing to do if child has valid 'aid' */
2513 if (child->aid.len)
2514 return SC_SUCCESS;
2515
2516 if (parent->aid.len) {
2517 sc_path_t ppath;
2518
2519 /* child inherits parent's 'aid' */
2520 child->aid = parent->aid;
2521 if (!parent->len)
2522 return SC_SUCCESS;
2523
2524 /* parent has valid 'path' -- concatenate it with the child's one */
2525 memcpy(&ppath, parent, sizeof(sc_path_t));
2526 ppath.aid.len = 0;
2527 ppath.type = SC_PATH_TYPE_FROM_CURRENT;
2528 return sc_concatenate_path(child, &ppath, child);
2529
2530 }
2531 else if (parent->type == SC_PATH_TYPE_DF_NAME) {
2532 /* child inherits parent's 'DF NAME' as 'aid' */
2533 if (parent->len > sizeof(child->aid.value))
2534 return SC_ERROR_WRONG_LENGTH;
2535
2536 memcpy(child->aid.value, parent->value, parent->len);
2537 child->aid.len = parent->len;
2538
2539 return SC_SUCCESS;
2540 }
2541
2542 /* a 0 length path stays a 0 length path */
2543 if (child->len == 0)
2544 return SC_SUCCESS;
2545
2546 if (sc_compare_path_prefix(sc_get_mf_path(), child))
2547 return SC_SUCCESS;
2548
2549 return sc_concatenate_path(child, parent, child);
2550 }
2551
2552
sc_pkcs15_free_object_content(struct sc_pkcs15_object * obj)2553 void sc_pkcs15_free_object_content(struct sc_pkcs15_object *obj)
2554 {
2555 if (obj->content.value && obj->content.len) {
2556 if (SC_PKCS15_TYPE_AUTH & obj->type
2557 || SC_PKCS15_TYPE_SKEY & obj->type
2558 || SC_PKCS15_TYPE_PRKEY & obj->type) {
2559 /* clean everything that potentially contains a secret */
2560 sc_mem_clear(obj->content.value, obj->content.len);
2561 sc_mem_secure_free(obj->content.value, obj->content.len);
2562 } else {
2563 free(obj->content.value);
2564 }
2565 }
2566 obj->content.value = NULL;
2567 obj->content.len = 0;
2568 }
2569
2570
2571 int
sc_pkcs15_allocate_object_content(struct sc_context * ctx,struct sc_pkcs15_object * obj,const unsigned char * value,size_t len)2572 sc_pkcs15_allocate_object_content(struct sc_context *ctx, struct sc_pkcs15_object *obj,
2573 const unsigned char *value, size_t len)
2574 {
2575 unsigned char *tmp_buf;
2576
2577 if (!obj)
2578 return SC_ERROR_INVALID_ARGUMENTS;
2579
2580 if (!value || !len) {
2581 sc_pkcs15_free_object_content(obj);
2582 return SC_SUCCESS;
2583 }
2584
2585 /* Need to pass by temporary variable,
2586 * because 'value' and 'content.value' pointers can be the sames.
2587 */
2588 if (SC_PKCS15_TYPE_AUTH & obj->type
2589 || SC_PKCS15_TYPE_SKEY & obj->type
2590 || SC_PKCS15_TYPE_PRKEY & obj->type) {
2591 tmp_buf = sc_mem_secure_alloc(len);
2592 } else {
2593 tmp_buf = malloc(len);
2594 }
2595 if (!tmp_buf)
2596 return SC_ERROR_OUT_OF_MEMORY;
2597
2598 memcpy(tmp_buf, value, len);
2599
2600 sc_pkcs15_free_object_content(obj);
2601
2602 obj->content.value = tmp_buf;
2603 obj->content.len = len;
2604
2605 return SC_SUCCESS;
2606 }
2607
2608
2609 struct sc_supported_algo_info *
sc_pkcs15_get_supported_algo(struct sc_pkcs15_card * p15card,unsigned operation,unsigned mechanism)2610 sc_pkcs15_get_supported_algo(struct sc_pkcs15_card *p15card, unsigned operation, unsigned mechanism)
2611 {
2612 struct sc_context *ctx = p15card->card->ctx;
2613 struct sc_supported_algo_info *info = NULL;
2614 int ii;
2615
2616 for (ii=0;ii<SC_MAX_SUPPORTED_ALGORITHMS && p15card->tokeninfo->supported_algos[ii].reference; ii++)
2617 if ((p15card->tokeninfo->supported_algos[ii].operations & operation)
2618 && (p15card->tokeninfo->supported_algos[ii].mechanism == mechanism))
2619 break;
2620
2621 if (ii < SC_MAX_SUPPORTED_ALGORITHMS && p15card->tokeninfo->supported_algos[ii].reference) {
2622 info = &p15card->tokeninfo->supported_algos[ii];
2623 sc_log(ctx, "found supported algorithm (ref:%X,mech:%X,ops:%X,algo_ref:%X)",
2624 info->reference, info->mechanism, info->operations, info->algo_ref);
2625 }
2626
2627 return info;
2628 }
2629
2630 struct sc_supported_algo_info *
sc_pkcs15_get_specific_supported_algo(struct sc_pkcs15_card * p15card,unsigned operation,unsigned mechanism,const struct sc_object_id * algo_oid)2631 sc_pkcs15_get_specific_supported_algo(struct sc_pkcs15_card *p15card, unsigned operation, unsigned mechanism, const struct sc_object_id *algo_oid)
2632 {
2633 struct sc_context *ctx = p15card->card->ctx;
2634 struct sc_supported_algo_info *info = NULL;
2635 int ii;
2636
2637 if (algo_oid == NULL)
2638 return NULL;
2639
2640 for (ii=0;ii<SC_MAX_SUPPORTED_ALGORITHMS && p15card->tokeninfo->supported_algos[ii].reference; ii++)
2641 if ((p15card->tokeninfo->supported_algos[ii].operations & operation)
2642 && (p15card->tokeninfo->supported_algos[ii].mechanism == mechanism)
2643 && sc_compare_oid(algo_oid, &p15card->tokeninfo->supported_algos[ii].algo_id) == 1)
2644 break;
2645
2646 if (ii < SC_MAX_SUPPORTED_ALGORITHMS && p15card->tokeninfo->supported_algos[ii].reference) {
2647 info = &p15card->tokeninfo->supported_algos[ii];
2648 sc_log(ctx, "found supported algorithm (ref:%X,mech:%X,ops:%X,algo_ref:%X)",
2649 info->reference, info->mechanism, info->operations, info->algo_ref);
2650 }
2651
2652 return info;
2653 }
2654
2655 int
sc_pkcs15_get_generalized_time(struct sc_context * ctx,char ** out)2656 sc_pkcs15_get_generalized_time(struct sc_context *ctx, char **out)
2657 {
2658 #ifdef HAVE_GETTIMEOFDAY
2659 struct timeval tv;
2660 #endif
2661 struct tm tm;
2662 time_t t;
2663
2664 if (!ctx || !out)
2665 return SC_ERROR_INVALID_ARGUMENTS;
2666 *out = NULL;
2667
2668 #ifdef HAVE_GETTIMEOFDAY
2669 gettimeofday(&tv, NULL);
2670 t = tv.tv_sec;
2671 #else
2672 t = time(NULL);
2673 #endif
2674
2675 #ifdef _WIN32
2676 if (0 != gmtime_s(&tm, &t))
2677 LOG_FUNC_RETURN(ctx, SC_ERROR_INTERNAL);
2678 #else
2679 if (NULL == gmtime_r(&t, &tm))
2680 LOG_FUNC_RETURN(ctx, SC_ERROR_INTERNAL);
2681 #endif
2682
2683 *out = calloc(1, 16);
2684 if (*out == NULL)
2685 LOG_TEST_RET(ctx, SC_ERROR_OUT_OF_MEMORY, "memory failure");
2686
2687 /* print time in generalized time format */
2688 if (!strftime(*out, 16, "%Y%m%d%H%M%SZ", &tm)) {
2689 free(*out);
2690 LOG_TEST_RET(ctx, SC_ERROR_INTERNAL, "strftime failed");
2691 }
2692
2693 return SC_SUCCESS;
2694 }
2695
2696
2697 int
sc_pkcs15_add_supported_algo_ref(struct sc_pkcs15_object * obj,struct sc_supported_algo_info * algo)2698 sc_pkcs15_add_supported_algo_ref(struct sc_pkcs15_object *obj, struct sc_supported_algo_info *algo)
2699 {
2700 unsigned int ii, *algo_refs = NULL;
2701
2702 if (!algo)
2703 return SC_SUCCESS;
2704
2705 switch (obj->type & SC_PKCS15_TYPE_CLASS_MASK) {
2706 case SC_PKCS15_TYPE_PRKEY:
2707 algo_refs = ((struct sc_pkcs15_prkey_info *)obj->data)->algo_refs;
2708 break;
2709 case SC_PKCS15_TYPE_PUBKEY:
2710 algo_refs = ((struct sc_pkcs15_pubkey_info *)obj->data)->algo_refs;
2711 break;
2712 case SC_PKCS15_TYPE_SKEY:
2713 algo_refs = ((struct sc_pkcs15_skey_info *)obj->data)->algo_refs;
2714 break;
2715 }
2716 if (!algo_refs)
2717 return SC_ERROR_NOT_SUPPORTED;
2718
2719 for (ii=0;ii<SC_MAX_SUPPORTED_ALGORITHMS && *(algo_refs + ii);ii++)
2720 if (*(algo_refs + ii) == algo->reference)
2721 return SC_SUCCESS;
2722
2723 for (ii=0;ii<SC_MAX_SUPPORTED_ALGORITHMS;ii++) {
2724 if (*(algo_refs + ii) == 0) {
2725 *(algo_refs + ii) = algo->reference;
2726 return SC_SUCCESS;
2727 }
2728 }
2729
2730 return SC_ERROR_TOO_MANY_OBJECTS;
2731 }
2732
2733
2734 int
sc_pkcs15_get_object_id(const struct sc_pkcs15_object * obj,struct sc_pkcs15_id * out)2735 sc_pkcs15_get_object_id(const struct sc_pkcs15_object *obj, struct sc_pkcs15_id *out)
2736 {
2737 if (!obj || !out)
2738 return SC_ERROR_INVALID_ARGUMENTS;
2739
2740 switch (obj->type & SC_PKCS15_TYPE_CLASS_MASK) {
2741 case SC_PKCS15_TYPE_CERT:
2742 *out = ((struct sc_pkcs15_cert_info *) obj->data)->id;
2743 break;
2744 case SC_PKCS15_TYPE_PRKEY:
2745 *out = ((struct sc_pkcs15_prkey_info *) obj->data)->id;
2746 break;
2747 case SC_PKCS15_TYPE_PUBKEY:
2748 *out = ((struct sc_pkcs15_pubkey_info *) obj->data)->id;
2749 break;
2750 case SC_PKCS15_TYPE_SKEY:
2751 *out = ((struct sc_pkcs15_skey_info *) obj->data)->id;
2752 break;
2753 case SC_PKCS15_TYPE_AUTH:
2754 *out = ((struct sc_pkcs15_auth_info *) obj->data)->auth_id;
2755 break;
2756 case SC_PKCS15_TYPE_DATA_OBJECT:
2757 *out = ((struct sc_pkcs15_data_info *) obj->data)->id;
2758 break;
2759 default:
2760 return SC_ERROR_NOT_SUPPORTED;
2761 }
2762
2763 return SC_SUCCESS;
2764 }
2765
2766 /*
2767 * Simplified GUID serializing.
2768 * Ex. {3F2504E0-4F89-11D3-9A0C-0305E82C3301}
2769 *
2770 * There is no variant, version number and other special meaning fields
2771 * that are described in RFC-4122 .
2772 */
2773 int
sc_pkcs15_serialize_guid(unsigned char * in,size_t in_size,unsigned flags,char * out,size_t out_size)2774 sc_pkcs15_serialize_guid(unsigned char *in, size_t in_size, unsigned flags,
2775 char *out, size_t out_size)
2776 {
2777 int ii, jj, offs = 0;
2778
2779 if (in_size < 16)
2780 return SC_ERROR_BUFFER_TOO_SMALL;
2781 if (out_size < 39)
2782 return SC_ERROR_BUFFER_TOO_SMALL;
2783
2784 *out = '\0';
2785 if (!flags)
2786 strcpy(out, "{");
2787 for (ii=0; ii<4; ii++)
2788 sprintf(out + strlen(out), "%02x", *(in + offs++));
2789 for (jj=0; jj<3; jj++) {
2790 strcat(out, "-");
2791 for (ii=0; ii<2; ii++)
2792 sprintf(out + strlen(out), "%02x", *(in + offs++));
2793 }
2794 strcat(out, "-");
2795 for (ii=0; ii<6; ii++)
2796 sprintf(out + strlen(out), "%02x", *(in + offs++));
2797 if (!flags)
2798 strcat(out, "}");
2799
2800 return SC_SUCCESS;
2801 }
2802
2803
2804 int
sc_pkcs15_get_object_guid(struct sc_pkcs15_card * p15card,const struct sc_pkcs15_object * obj,unsigned flags,unsigned char * out,size_t * out_size)2805 sc_pkcs15_get_object_guid(struct sc_pkcs15_card *p15card, const struct sc_pkcs15_object *obj,
2806 unsigned flags, unsigned char *out, size_t *out_size)
2807 {
2808 struct sc_context *ctx = p15card->card->ctx;
2809 struct sc_serial_number serialnr;
2810 struct sc_pkcs15_id id;
2811 unsigned char guid_bin[SC_PKCS15_MAX_ID_SIZE + SC_MAX_SERIALNR];
2812 int rv, guid_bin_size;
2813
2814 LOG_FUNC_CALLED(ctx);
2815 if(!out || !out_size)
2816 LOG_FUNC_RETURN(ctx, SC_ERROR_INVALID_ARGUMENTS);
2817
2818 if (p15card->ops.get_guid) {
2819 rv = p15card->ops.get_guid(p15card, obj, out, out_size);
2820 LOG_FUNC_RETURN(ctx, rv);
2821 }
2822
2823 rv = sc_pkcs15_aux_get_md_guid(p15card, obj, flags, out, out_size);
2824 if (rv == SC_SUCCESS)
2825 LOG_FUNC_RETURN(ctx, SC_SUCCESS);
2826 else if (rv != SC_ERROR_NOT_SUPPORTED)
2827 LOG_TEST_RET(ctx, rv, "Failed to get alternative object GUID");
2828
2829 memset(out, 0, *out_size);
2830
2831 rv = sc_pkcs15_get_object_id(obj, &id);
2832 LOG_TEST_RET(ctx, rv, "Cannot get object's ID");
2833
2834 if (p15card->tokeninfo && p15card->tokeninfo->serial_number) {
2835 /* The serial from EF(TokenInfo) is preferred because of the
2836 * "--serial" parameter of pkcs15-init. */
2837 serialnr.len = SC_MAX_SERIALNR;
2838 rv = sc_hex_to_bin(p15card->tokeninfo->serial_number, serialnr.value, &serialnr.len);
2839 if (rv) {
2840 /* Fallback in case hex_to_bin fails due to unexpected characters */
2841 serialnr.len = strlen(p15card->tokeninfo->serial_number);
2842 if (serialnr.len > SC_MAX_SERIALNR)
2843 serialnr.len = SC_MAX_SERIALNR;
2844
2845 memcpy(serialnr.value, p15card->tokeninfo->serial_number, serialnr.len);
2846 }
2847 } else if (p15card->card->serialnr.len) {
2848 serialnr = p15card->card->serialnr;
2849 } else {
2850 rv = sc_card_ctl(p15card->card, SC_CARDCTL_GET_SERIALNR, &serialnr);
2851 LOG_TEST_RET(ctx, rv, "'GET_SERIALNR' CTL failed and other serial numbers not present");
2852 }
2853
2854 memset(guid_bin, 0, sizeof(guid_bin));
2855 memcpy(guid_bin, id.value, id.len);
2856 memcpy(guid_bin + id.len, serialnr.value, serialnr.len);
2857 guid_bin_size = id.len + serialnr.len;
2858
2859 /*
2860 * If OpenSSL is available (SHA1), then rather use the hash of the data
2861 * - this also protects against data being too short
2862 */
2863 #ifdef ENABLE_OPENSSL
2864 SHA1(guid_bin, guid_bin_size, guid_bin);
2865 guid_bin_size = SHA_DIGEST_LENGTH;
2866 #else
2867 /* If guid_bin has a size larger than 16 bytes
2868 * force the remaining bytes up to 16 bytes to be zero
2869 * so sc_pkcs15_serialize_guid won't fail because the size is less than 16
2870 */
2871 if (guid_bin_size < 16)
2872 guid_bin_size = 16;
2873 #endif
2874
2875 rv = sc_pkcs15_serialize_guid(guid_bin, guid_bin_size, flags, (char *)out, *out_size);
2876 LOG_TEST_RET(ctx, rv, "Serialize GUID error");
2877
2878 *out_size = strlen((char *)out);
2879 LOG_FUNC_RETURN(ctx, rv);
2880 }
2881
2882
2883 static int
sc_pkcs15_aux_get_md_guid(struct sc_pkcs15_card * p15card,const struct sc_pkcs15_object * obj,unsigned flags,unsigned char * out,size_t * out_size)2884 sc_pkcs15_aux_get_md_guid(struct sc_pkcs15_card *p15card, const struct sc_pkcs15_object *obj,
2885 unsigned flags,
2886 unsigned char *out, size_t *out_size)
2887 {
2888 struct sc_context *ctx = p15card->card->ctx;
2889 struct sc_pkcs15_prkey_info *prkey_info = NULL;
2890 int rv;
2891
2892 LOG_FUNC_CALLED(ctx);
2893 if(!out || !out_size)
2894 LOG_FUNC_RETURN(ctx, SC_ERROR_INVALID_ARGUMENTS);
2895
2896 if ((obj->type & SC_PKCS15_TYPE_CLASS_MASK) != SC_PKCS15_TYPE_PRKEY)
2897 LOG_FUNC_RETURN(ctx, SC_ERROR_NOT_SUPPORTED);
2898
2899 prkey_info = (struct sc_pkcs15_prkey_info *)obj->data;
2900 if (!prkey_info->aux_data || prkey_info->aux_data->type != SC_AUX_DATA_TYPE_MD_CMAP_RECORD)
2901 LOG_FUNC_RETURN(ctx, SC_ERROR_NOT_SUPPORTED);
2902
2903 rv = sc_aux_data_get_md_guid(ctx, prkey_info->aux_data, flags, out, out_size);
2904 LOG_FUNC_RETURN(ctx, rv);
2905 }
2906
2907
2908 void
sc_pkcs15_free_key_params(struct sc_pkcs15_key_params * params)2909 sc_pkcs15_free_key_params(struct sc_pkcs15_key_params *params)
2910 {
2911 if (!params)
2912 return;
2913 if (params->data && params->free_params)
2914 params->free_params(params->data);
2915 else if (params->data)
2916 free(params->data);
2917
2918 params->data = NULL;
2919 }
2920
2921