/src/opensc/src/pkcs15init/pkcs15-oberthur.c
Line | Count | Source (jump to first uncovered line) |
1 | | /* |
2 | | * Oberthur specific operation for PKCS #15 initialization |
3 | | * |
4 | | * Copyright (C) 2002 Juha Yrjölä <juha.yrjola@iki.fi> |
5 | | * Copyright (C) 2009 Viktor Tarasov <viktor.tarasov@opentrust.com>, |
6 | | * OpenTrust <www.opentrust.com> |
7 | | * |
8 | | * This library is free software; you can redistribute it and/or |
9 | | * modify it under the terms of the GNU Lesser General Public |
10 | | * License as published by the Free Software Foundation; either |
11 | | * version 2.1 of the License, or (at your option) any later version. |
12 | | * |
13 | | * This library is distributed in the hope that it will be useful, |
14 | | * but WITHOUT ANY WARRANTY; without even the implied warranty of |
15 | | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU |
16 | | * Lesser General Public License for more details. |
17 | | * |
18 | | * You should have received a copy of the GNU Lesser General Public |
19 | | * License along with this library; if not, write to the Free Software |
20 | | * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA |
21 | | */ |
22 | | |
23 | | #include "pkcs15-oberthur.h" |
24 | | #include <sys/types.h> |
25 | | #include <ctype.h> |
26 | | |
27 | | #include "libopensc/opensc.h" |
28 | | #include "libopensc/cardctl.h" |
29 | | #include "libopensc/log.h" |
30 | | #include "profile.h" |
31 | | #include "pkcs15-init.h" |
32 | | |
33 | 1.13k | #define COSM_TITLE "OberthurAWP" |
34 | | |
35 | | #define TLV_TYPE_V 0 |
36 | | #define TLV_TYPE_LV 1 |
37 | | #define TLV_TYPE_TLV 2 |
38 | | |
39 | | /* Should be greater then SC_PKCS15_TYPE_CLASS_MASK */ |
40 | 220 | #define SC_DEVICE_SPECIFIC_TYPE 0x1000 |
41 | | |
42 | 220 | #define COSM_TYPE_PRKEY_RSA (SC_DEVICE_SPECIFIC_TYPE | SC_PKCS15_TYPE_PRKEY_RSA) |
43 | 0 | #define COSM_TYPE_PUBKEY_RSA (SC_DEVICE_SPECIFIC_TYPE | SC_PKCS15_TYPE_PUBKEY_RSA) |
44 | | |
45 | 0 | #define COSM_TOKEN_FLAG_PRN_GENERATION 0x01 |
46 | 0 | #define COSM_TOKEN_FLAG_LOGIN_REQUIRED 0x04 |
47 | 0 | #define COSM_TOKEN_FLAG_USER_PIN_INITIALIZED 0x08 |
48 | 0 | #define COSM_TOKEN_FLAG_TOKEN_INITIALIZED 0x0400 |
49 | | |
50 | | static int cosm_create_reference_data(struct sc_profile *, struct sc_pkcs15_card *, |
51 | | struct sc_pkcs15_auth_info *, const unsigned char *, size_t, |
52 | | const unsigned char *, size_t); |
53 | | static int cosm_update_pin(struct sc_profile *, struct sc_pkcs15_card *, |
54 | | struct sc_pkcs15_auth_info *, const unsigned char *, size_t, |
55 | | const unsigned char *, size_t); |
56 | | |
57 | | static int |
58 | | cosm_write_tokeninfo (struct sc_pkcs15_card *p15card, struct sc_profile *profile, |
59 | | char *label, unsigned flags) |
60 | 0 | { |
61 | 0 | struct sc_context *ctx; |
62 | 0 | struct sc_file *file = NULL; |
63 | 0 | int rv; |
64 | 0 | size_t sz; |
65 | 0 | char *buffer = NULL; |
66 | |
|
67 | 0 | if (!p15card || !p15card->card || !profile) |
68 | 0 | return SC_ERROR_INVALID_ARGUMENTS; |
69 | | |
70 | 0 | ctx = p15card->card->ctx; |
71 | |
|
72 | 0 | SC_FUNC_CALLED(ctx, SC_LOG_DEBUG_VERBOSE); |
73 | 0 | if (sc_profile_get_file(profile, COSM_TITLE"-token-info", &file)) { |
74 | 0 | rv = SC_ERROR_INCONSISTENT_PROFILE; |
75 | 0 | SC_TEST_GOTO_ERR(ctx, SC_LOG_DEBUG_VERBOSE, rv, "Cannot find "COSM_TITLE"-token-info"); |
76 | 0 | } |
77 | | |
78 | 0 | if (file->size < 16) { |
79 | 0 | rv = SC_ERROR_INCONSISTENT_PROFILE; |
80 | 0 | SC_TEST_GOTO_ERR(ctx, SC_LOG_DEBUG_VERBOSE, rv, "Insufficient size of the "COSM_TITLE"-token-info file"); |
81 | 0 | } |
82 | | |
83 | 0 | buffer = calloc(1, file->size); |
84 | 0 | if (!buffer) { |
85 | 0 | rv = SC_ERROR_OUT_OF_MEMORY; |
86 | 0 | SC_TEST_GOTO_ERR(ctx, SC_LOG_DEBUG_VERBOSE, rv, "Allocation error in cosm_write_tokeninfo()"); |
87 | 0 | } |
88 | | |
89 | 0 | if (label) |
90 | 0 | strncpy(buffer, label, file->size - 4); |
91 | 0 | else if (p15card->tokeninfo->label) |
92 | 0 | snprintf(buffer, file->size - 4, "%s", p15card->tokeninfo->label); |
93 | 0 | else if (profile->p15_spec && profile->p15_spec->tokeninfo->label) |
94 | 0 | snprintf(buffer, file->size - 4, "%s", profile->p15_spec->tokeninfo->label); |
95 | 0 | else |
96 | 0 | snprintf(buffer, file->size - 4, "OpenSC-Token"); |
97 | |
|
98 | 0 | sz = strlen(buffer); |
99 | 0 | if (sz < file->size - 4) |
100 | 0 | memset(buffer + sz, ' ', file->size - sz); |
101 | |
|
102 | 0 | sc_log(ctx, "cosm_write_tokeninfo() token label '%s'; oberthur flags 0x%X", buffer, flags); |
103 | |
|
104 | 0 | memset(buffer + file->size - 4, 0, 4); |
105 | 0 | *(buffer + file->size - 1) = flags & 0xFF; |
106 | 0 | *(buffer + file->size - 2) = (flags >> 8) & 0xFF; |
107 | |
|
108 | 0 | rv = sc_pkcs15init_update_file(profile, p15card, file, buffer, file->size); |
109 | 0 | if (rv > 0) |
110 | 0 | rv = 0; |
111 | |
|
112 | 0 | err: |
113 | 0 | sc_file_free(file); |
114 | 0 | free(buffer); |
115 | 0 | LOG_FUNC_RETURN(ctx, rv); |
116 | 0 | } |
117 | | |
118 | | |
119 | | int |
120 | | cosm_delete_file(struct sc_pkcs15_card *p15card, struct sc_profile *profile, |
121 | | struct sc_file *df) |
122 | 545 | { |
123 | 545 | struct sc_context *ctx = p15card->card->ctx; |
124 | 545 | struct sc_path path; |
125 | 545 | struct sc_file *parent; |
126 | 545 | int rv = 0; |
127 | | |
128 | 545 | SC_FUNC_CALLED(ctx, SC_LOG_DEBUG_VERBOSE); |
129 | 545 | sc_log(ctx, "id %04X", df->id); |
130 | 545 | if (df->type==SC_FILE_TYPE_DF) { |
131 | 477 | rv = sc_pkcs15init_authenticate(profile, p15card, df, SC_AC_OP_DELETE); |
132 | 477 | LOG_TEST_RET(ctx, rv, "Cannot authenticate SC_AC_OP_DELETE"); |
133 | 477 | } |
134 | | |
135 | | /* Select the parent DF */ |
136 | 166 | path = df->path; |
137 | 166 | if (path.len < 2) { |
138 | 6 | LOG_FUNC_RETURN(ctx, SC_ERROR_INVALID_ARGUMENTS); |
139 | 6 | } |
140 | 160 | path.len -= 2; |
141 | | |
142 | 160 | rv = sc_select_file(p15card->card, &path, &parent); |
143 | 160 | LOG_TEST_RET(ctx, rv, "Cannot select parent"); |
144 | | |
145 | 70 | rv = sc_pkcs15init_authenticate(profile, p15card, parent, SC_AC_OP_DELETE); |
146 | 70 | sc_file_free(parent); |
147 | 70 | LOG_TEST_RET(ctx, rv, "Cannot authenticate SC_AC_OP_DELETE"); |
148 | | |
149 | 69 | memset(&path, 0, sizeof(path)); |
150 | 69 | path.type = SC_PATH_TYPE_FILE_ID; |
151 | 69 | path.value[0] = df->id >> 8; |
152 | 69 | path.value[1] = df->id & 0xFF; |
153 | 69 | path.len = 2; |
154 | | |
155 | 69 | rv = sc_delete_file(p15card->card, &path); |
156 | | |
157 | 69 | LOG_FUNC_RETURN(ctx, rv); |
158 | 69 | } |
159 | | |
160 | | |
161 | | /* |
162 | | * Erase the card |
163 | | */ |
164 | | static int |
165 | | cosm_erase_card(struct sc_profile *profile, struct sc_pkcs15_card *p15card) |
166 | 483 | { |
167 | 483 | struct sc_context *ctx = p15card->card->ctx; |
168 | 483 | struct sc_file *df = profile->df_info->file, *dir; |
169 | 483 | int rv; |
170 | | |
171 | 483 | SC_FUNC_CALLED(ctx, SC_LOG_DEBUG_VERBOSE); |
172 | | /* Delete EF(DIR). This may not be very nice |
173 | | * against other applications that use this file, but |
174 | | * extremely useful for testing :) |
175 | | * Note we need to delete if before the DF because we create |
176 | | * it *after* the DF. |
177 | | * */ |
178 | 483 | if (sc_profile_get_file(profile, "DIR", &dir) >= 0) { |
179 | 15 | sc_log(ctx, "erase file dir %04X",dir->id); |
180 | 15 | rv = cosm_delete_file(p15card, profile, dir); |
181 | 15 | sc_file_free(dir); |
182 | 15 | if (rv < 0 && rv != SC_ERROR_FILE_NOT_FOUND) |
183 | 7 | goto done; |
184 | 15 | } |
185 | | |
186 | 476 | sc_log(ctx, "erase file ddf %04X",df->id); |
187 | 476 | rv = cosm_delete_file(p15card, profile, df); |
188 | 476 | if (rv < 0 && rv != SC_ERROR_FILE_NOT_FOUND) |
189 | 466 | goto done; |
190 | | |
191 | 10 | if (sc_profile_get_file(profile, "private-DF", &dir) >= 0) { |
192 | 4 | sc_log(ctx, "erase file dir %04X",dir->id); |
193 | 4 | rv = cosm_delete_file(p15card, profile, dir); |
194 | 4 | sc_file_free(dir); |
195 | 4 | if (rv < 0 && rv != SC_ERROR_FILE_NOT_FOUND) |
196 | 2 | goto done; |
197 | 4 | } |
198 | | |
199 | 8 | if (sc_profile_get_file(profile, "public-DF", &dir) >= 0) { |
200 | 0 | sc_log(ctx, "erase file dir %04X",dir->id); |
201 | 0 | rv = cosm_delete_file(p15card, profile, dir); |
202 | 0 | sc_file_free(dir); |
203 | 0 | if (rv < 0 && rv != SC_ERROR_FILE_NOT_FOUND) |
204 | 0 | goto done; |
205 | 0 | } |
206 | | |
207 | 8 | rv = sc_profile_get_file(profile, COSM_TITLE"-AppDF", &dir); |
208 | 8 | if (!rv) { |
209 | 1 | sc_log(ctx, "delete %s; r %i", COSM_TITLE"-AppDF", rv); |
210 | 1 | rv = cosm_delete_file(p15card, profile, dir); |
211 | 1 | sc_file_free(dir); |
212 | 1 | } |
213 | | |
214 | 8 | sc_free_apps(p15card->card); |
215 | 483 | done: |
216 | 483 | if (rv == SC_ERROR_FILE_NOT_FOUND) |
217 | 7 | rv = 0; |
218 | | |
219 | 483 | LOG_FUNC_RETURN(ctx, rv); |
220 | 483 | } |
221 | | |
222 | | |
223 | | static int |
224 | | cosm_create_dir(struct sc_profile *profile, struct sc_pkcs15_card *p15card, |
225 | | struct sc_file *df) |
226 | 17 | { |
227 | 17 | struct sc_context *ctx = p15card->card->ctx; |
228 | 17 | struct sc_file *file = NULL; |
229 | 17 | size_t ii; |
230 | 17 | int rv; |
231 | 17 | static const char *create_dfs[] = { |
232 | 17 | COSM_TITLE"-AppDF", |
233 | 17 | "private-DF", |
234 | 17 | "public-DF", |
235 | 17 | COSM_TITLE"-token-info", |
236 | 17 | COSM_TITLE"-puk-file", |
237 | 17 | COSM_TITLE"-container-list", |
238 | 17 | COSM_TITLE"-public-list", |
239 | 17 | COSM_TITLE"-private-list", |
240 | 17 | NULL |
241 | 17 | }; |
242 | | |
243 | 17 | SC_FUNC_CALLED(ctx, SC_LOG_DEBUG_VERBOSE); |
244 | | |
245 | | /* Oberthur AWP file system is expected.*/ |
246 | | /* Create private objects DF */ |
247 | 19 | for (ii = 0; create_dfs[ii]; ii++) { |
248 | 19 | if (sc_profile_get_file(profile, create_dfs[ii], &file)) { |
249 | 2 | sc_log(ctx, "Inconsistent profile: cannot find %s", create_dfs[ii]); |
250 | 2 | LOG_TEST_RET(ctx, SC_ERROR_INCONSISTENT_PROFILE, "Profile do not contains Oberthur AWP file"); |
251 | 2 | } |
252 | | |
253 | 17 | rv = sc_pkcs15init_create_file(profile, p15card, file); |
254 | 17 | sc_file_free(file); |
255 | 17 | if (rv != SC_ERROR_FILE_ALREADY_EXISTS) |
256 | 17 | LOG_TEST_RET(ctx, rv, "Failed to create Oberthur AWP file"); |
257 | 17 | } |
258 | | |
259 | 0 | rv = cosm_write_tokeninfo(p15card, profile, NULL, |
260 | 0 | COSM_TOKEN_FLAG_TOKEN_INITIALIZED | COSM_TOKEN_FLAG_PRN_GENERATION); |
261 | |
|
262 | 0 | LOG_FUNC_RETURN(ctx, rv); |
263 | 0 | } |
264 | | |
265 | | |
266 | | static int |
267 | | cosm_create_reference_data(struct sc_profile *profile, struct sc_pkcs15_card *p15card, |
268 | | struct sc_pkcs15_auth_info *ainfo, |
269 | | const unsigned char *pin, size_t pin_len, |
270 | | const unsigned char *puk, size_t puk_len ) |
271 | 7 | { |
272 | 7 | struct sc_context *ctx = p15card->card->ctx; |
273 | 7 | struct sc_card *card = p15card->card; |
274 | 7 | struct sc_pkcs15_auth_info profile_auth_pin = {0}, profile_auth_puk = {0}; |
275 | 7 | struct sc_cardctl_oberthur_createpin_info args; |
276 | 7 | int rv; |
277 | 7 | unsigned char oberthur_puk[16] = { |
278 | 7 | 0x6F, 0x47, 0xD9, 0x88, 0x4B, 0x6F, 0x9D, 0xC5, |
279 | 7 | 0x78, 0x33, 0x79, 0x8F, 0x5B, 0x7D, 0xE1, 0xA5 |
280 | 7 | }; |
281 | | |
282 | 7 | SC_FUNC_CALLED(ctx, SC_LOG_DEBUG_VERBOSE); |
283 | 7 | sc_log(ctx, |
284 | 7 | "pin lens %"SC_FORMAT_LEN_SIZE_T"u/%"SC_FORMAT_LEN_SIZE_T"u", |
285 | 7 | pin_len, puk_len); |
286 | 7 | if (!pin || pin_len>0x40) |
287 | 0 | return SC_ERROR_INVALID_ARGUMENTS; |
288 | 7 | if (puk && !puk_len) |
289 | 0 | return SC_ERROR_INVALID_ARGUMENTS; |
290 | 7 | if (ainfo->auth_type != SC_PKCS15_PIN_AUTH_TYPE_PIN) |
291 | 0 | return SC_ERROR_OBJECT_NOT_VALID; |
292 | | |
293 | 7 | rv = sc_select_file(card, &ainfo->path, NULL); |
294 | 7 | LOG_TEST_RET(ctx, rv, "Cannot select file"); |
295 | | |
296 | 4 | sc_profile_get_pin_info(profile, SC_PKCS15INIT_USER_PIN, &profile_auth_pin); |
297 | 4 | sc_profile_get_pin_info(profile, SC_PKCS15INIT_USER_PUK, &profile_auth_puk); |
298 | | |
299 | 4 | memset(&args, 0, sizeof(args)); |
300 | 4 | args.type = SC_AC_CHV; |
301 | 4 | args.ref = ainfo->attrs.pin.reference; |
302 | 4 | args.pin = pin; |
303 | 4 | args.pin_len = pin_len; |
304 | | |
305 | 4 | if (!(ainfo->attrs.pin.flags & SC_PKCS15_PIN_FLAG_UNBLOCKING_PIN)) { |
306 | 4 | args.pin_tries = profile_auth_pin.tries_left; |
307 | 4 | if (profile_auth_puk.tries_left > 0) { |
308 | 4 | args.puk = oberthur_puk; |
309 | 4 | args.puk_len = sizeof(oberthur_puk); |
310 | 4 | args.puk_tries = 5; |
311 | 4 | } |
312 | 4 | } |
313 | 0 | else { |
314 | 0 | args.pin_tries = profile_auth_puk.tries_left; |
315 | 0 | } |
316 | | |
317 | 4 | rv = sc_card_ctl(card, SC_CARDCTL_OBERTHUR_CREATE_PIN, &args); |
318 | 4 | LOG_TEST_RET(ctx, rv, "'CREATE_PIN' card specific command failed"); |
319 | | |
320 | 1 | if (!(ainfo->attrs.pin.flags & SC_PKCS15_PIN_FLAG_UNBLOCKING_PIN) |
321 | 1 | && (profile_auth_puk.tries_left > 0)) { |
322 | 1 | struct sc_file *file = NULL; |
323 | | |
324 | 1 | if (sc_profile_get_file(profile, COSM_TITLE"-puk-file", &file)) |
325 | 1 | LOG_TEST_RET(ctx, SC_ERROR_INCONSISTENT_PROFILE, "Cannot find PUKFILE"); |
326 | | |
327 | 0 | rv = sc_pkcs15init_update_file(profile, p15card, file, oberthur_puk, sizeof(oberthur_puk)); |
328 | 0 | LOG_TEST_RET(ctx, rv, "Failed to update pukfile"); |
329 | | |
330 | 0 | sc_file_free(file); |
331 | 0 | } |
332 | | |
333 | 0 | LOG_FUNC_RETURN(ctx, rv); |
334 | 0 | } |
335 | | |
336 | | |
337 | | /* |
338 | | * Update PIN |
339 | | */ |
340 | | static int |
341 | | cosm_update_pin(struct sc_profile *profile, struct sc_pkcs15_card *p15card, |
342 | | struct sc_pkcs15_auth_info *ainfo, const unsigned char *pin, size_t pin_len, |
343 | | const unsigned char *puk, size_t puk_len ) |
344 | 8 | { |
345 | 8 | struct sc_context *ctx = p15card->card->ctx; |
346 | 8 | int rv; |
347 | | |
348 | 8 | SC_FUNC_CALLED(ctx, SC_LOG_DEBUG_VERBOSE); |
349 | 8 | if (ainfo->auth_type != SC_PKCS15_PIN_AUTH_TYPE_PIN) |
350 | 0 | return SC_ERROR_OBJECT_NOT_VALID; |
351 | | |
352 | 8 | sc_log(ctx, "ref %i; flags 0x%X", ainfo->attrs.pin.reference, ainfo->attrs.pin.flags); |
353 | | |
354 | 8 | if (ainfo->attrs.pin.flags & SC_PKCS15_PIN_FLAG_SO_PIN) { |
355 | 1 | if (ainfo->attrs.pin.reference != 4) |
356 | 1 | LOG_TEST_RET(ctx, SC_ERROR_INVALID_PIN_REFERENCE, "cosm_update_pin() invalid SOPIN reference"); |
357 | 1 | sc_log(ctx, "Update SOPIN ignored"); |
358 | 1 | rv = SC_SUCCESS; |
359 | 1 | } |
360 | 7 | else { |
361 | 7 | rv = cosm_create_reference_data(profile, p15card, ainfo, pin, pin_len, puk, puk_len); |
362 | 7 | LOG_TEST_RET(ctx, rv, "cosm_update_pin() failed to change PIN"); |
363 | | |
364 | 0 | rv = cosm_write_tokeninfo(p15card, profile, NULL, |
365 | 0 | COSM_TOKEN_FLAG_TOKEN_INITIALIZED |
366 | 0 | | COSM_TOKEN_FLAG_PRN_GENERATION |
367 | 0 | | COSM_TOKEN_FLAG_LOGIN_REQUIRED |
368 | 0 | | COSM_TOKEN_FLAG_USER_PIN_INITIALIZED); |
369 | 0 | LOG_TEST_RET(ctx, rv, "cosm_update_pin() failed to update tokeninfo"); |
370 | 0 | } |
371 | | |
372 | 1 | LOG_FUNC_RETURN(ctx, rv); |
373 | 1 | } |
374 | | |
375 | | |
376 | | static int |
377 | | cosm_select_pin_reference(struct sc_profile *profile, struct sc_pkcs15_card *p15card, |
378 | | struct sc_pkcs15_auth_info *auth_info) |
379 | 525 | { |
380 | 525 | struct sc_context *ctx = p15card->card->ctx; |
381 | 525 | struct sc_pkcs15_pin_attributes *pin_attrs; |
382 | 525 | struct sc_file *pinfile; |
383 | | |
384 | 525 | SC_FUNC_CALLED(ctx, SC_LOG_DEBUG_VERBOSE); |
385 | 525 | if (auth_info->auth_type != SC_PKCS15_PIN_AUTH_TYPE_PIN) |
386 | 0 | return SC_ERROR_OBJECT_NOT_VALID; |
387 | | |
388 | 525 | pin_attrs = &auth_info->attrs.pin; |
389 | | |
390 | 525 | sc_log(ctx, "ref %i; flags %X", pin_attrs->reference, pin_attrs->flags); |
391 | 525 | if (sc_profile_get_file(profile, COSM_TITLE "-AppDF", &pinfile) < 0) { |
392 | 478 | sc_log(ctx, "Profile doesn't define \"%s\"", COSM_TITLE "-AppDF"); |
393 | 478 | return SC_ERROR_INCONSISTENT_PROFILE; |
394 | 478 | } |
395 | | |
396 | 47 | if (pin_attrs->flags & SC_PKCS15_PIN_FLAG_LOCAL) |
397 | 35 | auth_info->path = pinfile->path; |
398 | | |
399 | 47 | sc_file_free(pinfile); |
400 | | |
401 | 47 | if (pin_attrs->reference <= 0) { |
402 | 36 | if (pin_attrs->flags & SC_PKCS15_PIN_FLAG_SO_PIN) |
403 | 4 | pin_attrs->reference = 4; |
404 | 32 | else if (pin_attrs->flags & SC_PKCS15_PIN_FLAG_UNBLOCKING_PIN) |
405 | 6 | pin_attrs->reference = 4; |
406 | 26 | else |
407 | 26 | pin_attrs->reference = 1; |
408 | | |
409 | 36 | if (pin_attrs->flags & SC_PKCS15_PIN_FLAG_LOCAL) |
410 | 25 | pin_attrs->reference |= 0x80; |
411 | 36 | } |
412 | | |
413 | 47 | LOG_FUNC_RETURN(ctx, SC_SUCCESS); |
414 | 47 | } |
415 | | |
416 | | |
417 | | /* |
418 | | * Store a PIN |
419 | | */ |
420 | | static int |
421 | | cosm_create_pin(struct sc_profile *profile, struct sc_pkcs15_card *p15card, |
422 | | struct sc_file *df, struct sc_pkcs15_object *pin_obj, |
423 | | const unsigned char *pin, size_t pin_len, |
424 | | const unsigned char *puk, size_t puk_len) |
425 | 17 | { |
426 | 17 | struct sc_context *ctx = p15card->card->ctx; |
427 | 17 | struct sc_pkcs15_auth_info *auth_info = (struct sc_pkcs15_auth_info *) pin_obj->data; |
428 | 17 | struct sc_pkcs15_pin_attributes *pin_attrs; |
429 | 17 | struct sc_file *pin_file; |
430 | 17 | int rv = 0; |
431 | | |
432 | 17 | SC_FUNC_CALLED(ctx, SC_LOG_DEBUG_VERBOSE); |
433 | 17 | if (auth_info->auth_type != SC_PKCS15_PIN_AUTH_TYPE_PIN) |
434 | 0 | return SC_ERROR_OBJECT_NOT_VALID; |
435 | | |
436 | 17 | pin_attrs = &auth_info->attrs.pin; |
437 | | |
438 | 17 | sc_log(ctx, "create '%.*s'; ref 0x%X; flags %X", (int) sizeof pin_obj->label, pin_obj->label, pin_attrs->reference, pin_attrs->flags); |
439 | 17 | if (sc_profile_get_file(profile, COSM_TITLE "-AppDF", &pin_file) < 0) |
440 | 17 | LOG_TEST_RET(ctx, SC_ERROR_INCONSISTENT_PROFILE, "\""COSM_TITLE"-AppDF\" not defined"); |
441 | | |
442 | 17 | if (pin_attrs->flags & SC_PKCS15_PIN_FLAG_LOCAL) |
443 | 10 | auth_info->path = pin_file->path; |
444 | | |
445 | 17 | sc_file_free(pin_file); |
446 | | |
447 | 17 | if (pin_attrs->flags & SC_PKCS15_PIN_FLAG_SO_PIN) { |
448 | 3 | if (pin_attrs->flags & SC_PKCS15_PIN_FLAG_UNBLOCKING_PIN) { |
449 | 1 | LOG_TEST_RET(ctx, SC_ERROR_NOT_SUPPORTED, "SOPIN unblocking is not supported"); |
450 | 1 | } |
451 | 2 | else { |
452 | 2 | if (pin_attrs->reference != 4) |
453 | 2 | LOG_TEST_RET(ctx, SC_ERROR_INVALID_PIN_REFERENCE, "Invalid SOPIN reference"); |
454 | 2 | } |
455 | 3 | } |
456 | 14 | else { |
457 | 14 | if (pin_attrs->flags & SC_PKCS15_PIN_FLAG_UNBLOCKING_PIN) { |
458 | 4 | if (pin_attrs->reference != 0x84) |
459 | 4 | LOG_TEST_RET(ctx, SC_ERROR_INVALID_PIN_REFERENCE, "Invalid User PUK reference"); |
460 | 4 | } |
461 | 10 | else { |
462 | 10 | if (pin_attrs->reference != 0x81) |
463 | 10 | LOG_TEST_RET(ctx, SC_ERROR_INVALID_PIN_REFERENCE, "Invalid User PIN reference"); |
464 | 10 | } |
465 | 14 | } |
466 | | |
467 | 8 | if (pin && pin_len) { |
468 | 8 | rv = cosm_update_pin(profile, p15card, auth_info, pin, pin_len, puk, puk_len); |
469 | 8 | LOG_TEST_RET(ctx, rv, "Update PIN failed"); |
470 | 8 | } |
471 | | |
472 | 1 | LOG_FUNC_RETURN(ctx, rv); |
473 | 1 | } |
474 | | |
475 | | |
476 | | /* |
477 | | * Allocate a file |
478 | | */ |
479 | | static int |
480 | | cosm_new_file(struct sc_profile *profile, struct sc_card *card, |
481 | | unsigned int type, unsigned int num, struct sc_file **out) |
482 | 220 | { |
483 | 220 | struct sc_file *file; |
484 | 220 | const char *_template = NULL, *desc = NULL; |
485 | 220 | unsigned int structure = 0xFFFFFFFF; |
486 | | |
487 | 220 | SC_FUNC_CALLED(card->ctx, SC_LOG_DEBUG_VERBOSE); |
488 | 220 | sc_log(card->ctx, "cosm_new_file() type %X; num %i",type, num); |
489 | 220 | while (1) { |
490 | 220 | switch (type) { |
491 | 220 | case SC_PKCS15_TYPE_PRKEY_RSA: |
492 | 220 | case COSM_TYPE_PRKEY_RSA: |
493 | 220 | desc = "RSA private key"; |
494 | 220 | _template = "template-private-key"; |
495 | 220 | structure = SC_CARDCTL_OBERTHUR_KEY_RSA_CRT; |
496 | 220 | break; |
497 | 0 | case SC_PKCS15_TYPE_PUBKEY_RSA: |
498 | 0 | case COSM_TYPE_PUBKEY_RSA: |
499 | 0 | desc = "RSA public key"; |
500 | 0 | _template = "template-public-key"; |
501 | 0 | structure = SC_CARDCTL_OBERTHUR_KEY_RSA_PUBLIC; |
502 | 0 | break; |
503 | 0 | case SC_PKCS15_TYPE_CERT: |
504 | 0 | desc = "certificate"; |
505 | 0 | _template = "template-certificate"; |
506 | 0 | break; |
507 | 0 | case SC_PKCS15_TYPE_DATA_OBJECT: |
508 | 0 | desc = "data object"; |
509 | 0 | _template = "template-public-data"; |
510 | 0 | break; |
511 | 220 | } |
512 | 220 | if (_template) |
513 | 220 | break; |
514 | | /* If this is a specific type such as |
515 | | * SC_PKCS15_TYPE_CERT_FOOBAR, fall back to |
516 | | * the generic class (SC_PKCS15_TYPE_CERT) |
517 | | */ |
518 | 0 | if (!(type & ~SC_PKCS15_TYPE_CLASS_MASK)) { |
519 | 0 | sc_log(card->ctx, "File type %X not supported by card driver", |
520 | 0 | type); |
521 | 0 | return SC_ERROR_INVALID_ARGUMENTS; |
522 | 0 | } |
523 | 0 | type &= SC_PKCS15_TYPE_CLASS_MASK; |
524 | 0 | } |
525 | | |
526 | 220 | sc_log(card->ctx, "cosm_new_file() template %s; num %i",_template, num); |
527 | 220 | if (sc_profile_get_file(profile, _template, &file) < 0) { |
528 | 127 | sc_log(card->ctx, "Profile doesn't define %s template '%s'", |
529 | 127 | desc, _template); |
530 | 127 | LOG_FUNC_RETURN(card->ctx, SC_ERROR_NOT_SUPPORTED); |
531 | 127 | } |
532 | | |
533 | 93 | file->id |= (num & 0xFF); |
534 | 93 | if (file->path.len) { |
535 | 92 | file->path.value[file->path.len - 1] |= (num & 0xFF); |
536 | 92 | } |
537 | 93 | if (file->type == SC_FILE_TYPE_INTERNAL_EF) { |
538 | 7 | file->ef_structure = structure; |
539 | 7 | } |
540 | | |
541 | 93 | sc_log(card->ctx, |
542 | 93 | "cosm_new_file() file size %"SC_FORMAT_LEN_SIZE_T"u; ef type %i/%i; id %04X", |
543 | 93 | file->size, file->type, file->ef_structure, file->id); |
544 | 93 | *out = file; |
545 | | |
546 | 93 | LOG_FUNC_RETURN(card->ctx, SC_SUCCESS); |
547 | 93 | } |
548 | | |
549 | | |
550 | | static int |
551 | | cosm_get_temporary_public_key_file(struct sc_card *card, |
552 | | struct sc_file *prvkey_file, struct sc_file **pubkey_file) |
553 | 25 | { |
554 | 25 | struct sc_context *ctx = card->ctx; |
555 | 25 | const struct sc_acl_entry *entry = NULL; |
556 | 25 | struct sc_file *file = NULL; |
557 | 25 | int rv; |
558 | | |
559 | 25 | SC_FUNC_CALLED(card->ctx, SC_LOG_DEBUG_VERBOSE); |
560 | 25 | if (!pubkey_file || !prvkey_file) |
561 | 25 | LOG_FUNC_RETURN(card->ctx, SC_ERROR_INVALID_ARGUMENTS); |
562 | | |
563 | 25 | file = sc_file_new(); |
564 | 25 | if (!file) |
565 | 25 | LOG_FUNC_RETURN(card->ctx, SC_ERROR_OUT_OF_MEMORY); |
566 | | |
567 | 25 | file->status = SC_FILE_STATUS_ACTIVATED; |
568 | 25 | file->type = SC_FILE_TYPE_INTERNAL_EF; |
569 | 25 | file->ef_structure = SC_CARDCTL_OBERTHUR_KEY_RSA_PUBLIC; |
570 | 25 | file->id = 0x1012; |
571 | 25 | memcpy(&file->path, &prvkey_file->path, sizeof(file->path)); |
572 | 25 | file->path.value[file->path.len - 2] = 0x10; |
573 | 25 | file->path.value[file->path.len - 1] = 0x12; |
574 | 25 | file->size = prvkey_file->size; |
575 | | |
576 | 25 | entry = sc_file_get_acl_entry(prvkey_file, SC_AC_OP_UPDATE); |
577 | 25 | if (!entry) { |
578 | 2 | sc_file_free(file); |
579 | 2 | LOG_TEST_RET(ctx, SC_ERROR_OBJECT_NOT_FOUND, "Failed to find ACL entry"); |
580 | 2 | } |
581 | 23 | rv = sc_file_add_acl_entry(file, SC_AC_OP_UPDATE, entry->method, entry->key_ref); |
582 | 23 | if (!rv) |
583 | 23 | rv = sc_file_add_acl_entry(file, SC_AC_OP_PSO_ENCRYPT, SC_AC_NONE, 0); |
584 | 23 | if (!rv) |
585 | 23 | rv = sc_file_add_acl_entry(file, SC_AC_OP_PSO_VERIFY_SIGNATURE, SC_AC_NONE, 0); |
586 | 23 | if (!rv) |
587 | 23 | rv = sc_file_add_acl_entry(file, SC_AC_OP_EXTERNAL_AUTHENTICATE, SC_AC_NONE, 0); |
588 | 23 | if (rv < 0) |
589 | 0 | sc_file_free(file); |
590 | 23 | LOG_TEST_RET(ctx, rv, "Failed to add ACL entry to the temporary public key file"); |
591 | | |
592 | 23 | *pubkey_file = file; |
593 | | |
594 | 23 | LOG_FUNC_RETURN(card->ctx, rv); |
595 | 23 | } |
596 | | |
597 | | |
598 | | static int |
599 | | cosm_generate_key(struct sc_profile *profile, struct sc_pkcs15_card *p15card, |
600 | | struct sc_pkcs15_object *object, |
601 | | struct sc_pkcs15_pubkey *pubkey) |
602 | 35 | { |
603 | 35 | struct sc_context *ctx = p15card->card->ctx; |
604 | 35 | struct sc_pkcs15_prkey_info *key_info = (struct sc_pkcs15_prkey_info *)object->data; |
605 | 35 | struct sc_cardctl_oberthur_genkey_info args; |
606 | 35 | struct sc_file *prkf = NULL, *tmpf = NULL; |
607 | 35 | struct sc_path path; |
608 | 35 | int rv = 0; |
609 | | |
610 | 35 | SC_FUNC_CALLED(ctx, SC_LOG_DEBUG_VERBOSE); |
611 | | |
612 | 35 | if (object->type != SC_PKCS15_TYPE_PRKEY_RSA) |
613 | 35 | LOG_TEST_RET(ctx, SC_ERROR_NOT_SUPPORTED, "Generate key failed: RSA only supported"); |
614 | | |
615 | 35 | path = key_info->path; |
616 | 35 | path.len -= 2; |
617 | | |
618 | 35 | rv = sc_select_file(p15card->card, &path, &tmpf); |
619 | 35 | LOG_TEST_RET(ctx, rv, "Cannot generate key: failed to select private object DF"); |
620 | | |
621 | 34 | rv = sc_pkcs15init_authenticate(profile, p15card, tmpf, SC_AC_OP_CRYPTO); |
622 | 34 | if (rv != SC_SUCCESS) { |
623 | 1 | sc_file_free(tmpf); |
624 | 1 | LOG_TEST_RET(ctx, rv, "Cannot generate key: 'CRYPTO' authentication failed"); |
625 | 1 | } |
626 | | |
627 | 33 | rv = sc_pkcs15init_authenticate(profile, p15card, tmpf, SC_AC_OP_CREATE); |
628 | 33 | sc_file_free(tmpf); |
629 | 33 | tmpf = NULL; |
630 | 33 | LOG_TEST_RET(ctx, rv, "Cannot generate key: 'CREATE' authentication failed"); |
631 | | |
632 | 32 | rv = sc_select_file(p15card->card, &key_info->path, &prkf); |
633 | 32 | LOG_TEST_RET(ctx, rv, "Failed to generate key: cannot select private key file"); |
634 | | |
635 | | /* In the private key DF create the temporary public RSA file. */ |
636 | 25 | rv = cosm_get_temporary_public_key_file(p15card->card, prkf, &tmpf); |
637 | 25 | if (rv != SC_SUCCESS) { |
638 | 2 | sc_file_free(prkf); |
639 | 2 | LOG_TEST_RET(ctx, rv, "Error while getting temporary public key file"); |
640 | 2 | } |
641 | | |
642 | 23 | rv = sc_pkcs15init_create_file(profile, p15card, tmpf); |
643 | 23 | if (rv != SC_SUCCESS) { |
644 | 18 | sc_file_free(prkf); |
645 | 18 | sc_file_free(tmpf); |
646 | 18 | LOG_TEST_RET(ctx, rv, "cosm_generate_key() failed to create temporary public key EF"); |
647 | 18 | } |
648 | | |
649 | 5 | memset(&args, 0, sizeof(args)); |
650 | 5 | args.id_prv = prkf->id; |
651 | 5 | args.id_pub = tmpf->id; |
652 | 5 | args.exponent = 0x10001; |
653 | 5 | args.key_bits = key_info->modulus_length; |
654 | 5 | args.pubkey_len = key_info->modulus_length / 8; |
655 | 5 | args.pubkey = malloc(key_info->modulus_length / 8); |
656 | 5 | if (!args.pubkey) { |
657 | 0 | sc_file_free(prkf); |
658 | 0 | sc_file_free(tmpf); |
659 | 0 | LOG_TEST_RET(ctx, SC_ERROR_OUT_OF_MEMORY, "cosm_generate_key() cannot allocate pubkey"); |
660 | 0 | } |
661 | | |
662 | 5 | rv = sc_card_ctl(p15card->card, SC_CARDCTL_OBERTHUR_GENERATE_KEY, &args); |
663 | 5 | if (rv != SC_SUCCESS) { |
664 | 4 | sc_file_free(prkf); |
665 | 4 | sc_file_free(tmpf); |
666 | 4 | free(args.pubkey); |
667 | 4 | } |
668 | 5 | LOG_TEST_RET(ctx, rv, "cosm_generate_key() CARDCTL_OBERTHUR_GENERATE_KEY failed"); |
669 | | |
670 | | /* extract public key */ |
671 | 1 | pubkey->algorithm = SC_ALGORITHM_RSA; |
672 | 1 | pubkey->u.rsa.modulus.len = key_info->modulus_length / 8; |
673 | 1 | pubkey->u.rsa.modulus.data = malloc(key_info->modulus_length / 8); |
674 | 1 | if (!pubkey->u.rsa.modulus.data) { |
675 | 0 | sc_file_free(prkf); |
676 | 0 | sc_file_free(tmpf); |
677 | 0 | free(args.pubkey); |
678 | 0 | LOG_TEST_RET(ctx, SC_ERROR_OUT_OF_MEMORY, "cosm_generate_key() cannot allocate modulus buf"); |
679 | 0 | } |
680 | | |
681 | | /* FIXME and if the exponent length is not 3? */ |
682 | 1 | pubkey->u.rsa.exponent.len = 3; |
683 | 1 | pubkey->u.rsa.exponent.data = malloc(3); |
684 | 1 | if (!pubkey->u.rsa.exponent.data) { |
685 | 0 | sc_file_free(prkf); |
686 | 0 | sc_file_free(tmpf); |
687 | 0 | free(args.pubkey); |
688 | 0 | free(pubkey->u.rsa.modulus.data); |
689 | 0 | LOG_TEST_RET(ctx, SC_ERROR_OUT_OF_MEMORY, "cosm_generate_key() cannot allocate exponent buf"); |
690 | 0 | } |
691 | 1 | memcpy(pubkey->u.rsa.exponent.data, "\x01\x00\x01", 3); |
692 | 1 | memcpy(pubkey->u.rsa.modulus.data, args.pubkey, args.pubkey_len); |
693 | | |
694 | 1 | key_info->key_reference = prkf->path.value[prkf->path.len - 1] & 0xFF; |
695 | 1 | key_info->path = prkf->path; |
696 | | |
697 | 1 | sc_log(ctx, "cosm_generate_key() now delete temporary public key"); |
698 | 1 | rv = cosm_delete_file(p15card, profile, tmpf); |
699 | | |
700 | 1 | sc_file_free(tmpf); |
701 | 1 | sc_file_free(prkf); |
702 | 1 | free(args.pubkey); |
703 | | |
704 | 1 | LOG_FUNC_RETURN(ctx, rv); |
705 | 1 | } |
706 | | |
707 | | |
708 | | /* |
709 | | * Create private key file |
710 | | */ |
711 | | static int |
712 | | cosm_create_key(struct sc_profile *profile, struct sc_pkcs15_card *p15card, |
713 | | struct sc_pkcs15_object *object) |
714 | 1.92k | { |
715 | 1.92k | struct sc_context *ctx = p15card->card->ctx; |
716 | 1.92k | struct sc_pkcs15_prkey_info *key_info = (struct sc_pkcs15_prkey_info *)object->data; |
717 | 1.92k | struct sc_file *file = NULL; |
718 | 1.92k | int rv = 0; |
719 | | |
720 | 1.92k | SC_FUNC_CALLED(ctx, SC_LOG_DEBUG_VERBOSE); |
721 | 1.92k | if (object->type != SC_PKCS15_TYPE_PRKEY_RSA) |
722 | 1.92k | LOG_TEST_RET(ctx, SC_ERROR_NOT_SUPPORTED, "Create key failed: RSA only supported"); |
723 | | |
724 | 481 | if (key_info->path.len < 2) |
725 | 481 | LOG_TEST_RET(ctx, SC_ERROR_OBJECT_NOT_VALID, "The path needs to be at least to bytes long"); |
726 | | |
727 | 220 | sc_log(ctx, "create private key ID:%s", sc_pkcs15_print_id(&key_info->id)); |
728 | | /* Here, the path of private key file should be defined. |
729 | | * Nevertheless, we need to instantiate private key to get the ACLs. */ |
730 | 220 | rv = cosm_new_file(profile, p15card->card, SC_PKCS15_TYPE_PRKEY_RSA, key_info->key_reference, &file); |
731 | 220 | LOG_TEST_RET(ctx, rv, "Cannot create key: failed to allocate new key object"); |
732 | | |
733 | 93 | file->size = key_info->modulus_length; |
734 | 93 | memcpy(&file->path, &key_info->path, sizeof(file->path)); |
735 | 93 | file->id = file->path.value[file->path.len - 2] * 0x100 |
736 | 93 | + file->path.value[file->path.len - 1]; |
737 | | |
738 | 93 | sc_log(ctx, "Path of private key file to create %s", sc_print_path(&file->path)); |
739 | | |
740 | 93 | rv = sc_select_file(p15card->card, &file->path, NULL); |
741 | 93 | if (rv == 0) { |
742 | 48 | rv = cosm_delete_file(p15card, profile, file); |
743 | 48 | SC_TEST_GOTO_ERR(ctx, SC_LOG_DEBUG_VERBOSE, rv, "Failed to delete private key file"); |
744 | 48 | } |
745 | 45 | else if (rv != SC_ERROR_FILE_NOT_FOUND) { |
746 | 9 | SC_TEST_GOTO_ERR(ctx, SC_LOG_DEBUG_VERBOSE, rv, "Select private key file error"); |
747 | 9 | } |
748 | | |
749 | 50 | rv = sc_pkcs15init_create_file(profile, p15card, file); |
750 | 50 | SC_TEST_GOTO_ERR(ctx, SC_LOG_DEBUG_VERBOSE, rv, "Failed to create private key file"); |
751 | | |
752 | 35 | key_info->key_reference = file->path.value[file->path.len - 1]; |
753 | | |
754 | 93 | err: |
755 | 93 | sc_file_free(file); |
756 | | |
757 | 93 | LOG_FUNC_RETURN(ctx, rv); |
758 | 93 | } |
759 | | |
760 | | |
761 | | /* |
762 | | * Store a private key |
763 | | */ |
764 | | static int |
765 | | cosm_store_key(struct sc_profile *profile, struct sc_pkcs15_card *p15card, |
766 | | struct sc_pkcs15_object *object, |
767 | | struct sc_pkcs15_prkey *prkey) |
768 | 0 | { |
769 | 0 | struct sc_context *ctx = p15card->card->ctx; |
770 | 0 | struct sc_pkcs15_prkey_info *key_info = (struct sc_pkcs15_prkey_info *)object->data; |
771 | 0 | struct sc_file *file = NULL; |
772 | 0 | struct sc_cardctl_oberthur_updatekey_info update_info; |
773 | 0 | int rv = 0; |
774 | |
|
775 | 0 | SC_FUNC_CALLED(ctx, SC_LOG_DEBUG_VERBOSE); |
776 | 0 | if (object->type != SC_PKCS15_TYPE_PRKEY_RSA || prkey->algorithm != SC_ALGORITHM_RSA) |
777 | 0 | LOG_TEST_RET(ctx, SC_ERROR_NOT_SUPPORTED, "Store key failed: RSA only supported"); |
778 | | |
779 | 0 | sc_log(ctx, "store key with ID:%s and path:%s", sc_pkcs15_print_id(&key_info->id), |
780 | 0 | sc_print_path(&key_info->path)); |
781 | |
|
782 | 0 | rv = sc_select_file(p15card->card, &key_info->path, &file); |
783 | 0 | LOG_TEST_RET(ctx, rv, "Cannot store key: select key file failed"); |
784 | | |
785 | 0 | rv = sc_pkcs15init_authenticate(profile, p15card, file, SC_AC_OP_UPDATE); |
786 | 0 | LOG_TEST_RET(ctx, rv, "No authorisation to store private key"); |
787 | | |
788 | 0 | if (key_info->id.len > sizeof(update_info.id)) |
789 | 0 | LOG_FUNC_RETURN(ctx, SC_ERROR_INVALID_ARGUMENTS); |
790 | | |
791 | 0 | memset(&update_info, 0, sizeof(update_info)); |
792 | 0 | update_info.type = SC_CARDCTL_OBERTHUR_KEY_RSA_CRT; |
793 | 0 | update_info.data = (void *)&prkey->u.rsa; |
794 | 0 | update_info.data_len = sizeof(void *); |
795 | 0 | update_info.id_len = key_info->id.len; |
796 | 0 | memcpy(update_info.id, key_info->id.value, update_info.id_len); |
797 | |
|
798 | 0 | rv = sc_card_ctl(p15card->card, SC_CARDCTL_OBERTHUR_UPDATE_KEY, &update_info); |
799 | 0 | LOG_TEST_RET(ctx, rv, "Cannot update private key"); |
800 | | |
801 | 0 | sc_file_free(file); |
802 | |
|
803 | 0 | LOG_FUNC_RETURN(ctx, rv); |
804 | 0 | } |
805 | | |
806 | | |
807 | | #ifdef ENABLE_OPENSSL |
808 | | static int |
809 | | cosm_emu_update_dir (struct sc_profile *profile, struct sc_pkcs15_card *p15card, |
810 | | struct sc_app_info *info) |
811 | 0 | { |
812 | 0 | SC_FUNC_CALLED(p15card->card->ctx, 1); |
813 | | /* No DIR file in the native Oberthur card */ |
814 | 0 | SC_FUNC_RETURN(p15card->card->ctx, 1, SC_SUCCESS); |
815 | 0 | } |
816 | | |
817 | | |
818 | | static int |
819 | | cosm_emu_update_any_df(struct sc_profile *profile, struct sc_pkcs15_card *p15card, |
820 | | unsigned op, struct sc_pkcs15_object *object) |
821 | 0 | { |
822 | 0 | struct sc_context *ctx = p15card->card->ctx; |
823 | 0 | int rv = SC_ERROR_NOT_SUPPORTED; |
824 | |
|
825 | 0 | SC_FUNC_CALLED(ctx, 1); |
826 | 0 | switch(op) { |
827 | 0 | case SC_AC_OP_ERASE: |
828 | 0 | sc_log(ctx, "Update DF; erase object('%.*s',type:%X)", (int) sizeof object->label, object->label, object->type); |
829 | 0 | rv = awp_update_df_delete(p15card, profile, object); |
830 | 0 | break; |
831 | 0 | case SC_AC_OP_CREATE: |
832 | 0 | sc_log(ctx, "Update DF; create object('%.*s',type:%X)", (int) sizeof object->label, object->label, object->type); |
833 | 0 | rv = awp_update_df_create(p15card, profile, object); |
834 | 0 | break; |
835 | 0 | } |
836 | 0 | SC_FUNC_RETURN(ctx, 1, rv); |
837 | 0 | } |
838 | | |
839 | | |
840 | | static int |
841 | | cosm_emu_update_tokeninfo(struct sc_profile *profile, struct sc_pkcs15_card *p15card, |
842 | | struct sc_pkcs15_tokeninfo *tinfo) |
843 | 0 | { |
844 | 0 | struct sc_context *ctx = p15card->card->ctx; |
845 | 0 | struct sc_file *file = NULL; |
846 | 0 | int rv, flags = 0; |
847 | 0 | size_t label_len; |
848 | 0 | unsigned char *buf = NULL; |
849 | |
|
850 | 0 | SC_FUNC_CALLED(ctx, 1); |
851 | |
|
852 | 0 | if (sc_profile_get_file(profile, COSM_TITLE"-token-info", &file)) |
853 | 0 | LOG_TEST_RET(ctx, SC_ERROR_INCONSISTENT_PROFILE, "cannot find "COSM_TITLE"-token-info"); |
854 | | |
855 | 0 | buf = calloc(1, file->size); |
856 | 0 | if (!buf) { |
857 | 0 | sc_file_free(file); |
858 | 0 | SC_FUNC_RETURN(ctx, 1, SC_ERROR_OUT_OF_MEMORY); |
859 | 0 | } |
860 | | |
861 | 0 | label_len = strlen(tinfo->label) > (file->size - 4) ? (file->size - 4) : strlen(tinfo->label); |
862 | 0 | memcpy(buf, tinfo->label, label_len); |
863 | 0 | memset(buf + label_len, ' ', file->size - 4 - label_len); |
864 | | |
865 | | /* current PKCS#11 flags should be read from the token, |
866 | | * but for simplicity assume that user-pin is already initialised -- Andre 2010-10-05 |
867 | | */ |
868 | 0 | flags = COSM_TOKEN_FLAG_TOKEN_INITIALIZED |
869 | 0 | | COSM_TOKEN_FLAG_USER_PIN_INITIALIZED |
870 | 0 | | COSM_TOKEN_FLAG_LOGIN_REQUIRED |
871 | 0 | | COSM_TOKEN_FLAG_PRN_GENERATION; |
872 | |
|
873 | 0 | memset(buf + file->size - 4, 0, 4); |
874 | 0 | *(buf + file->size - 1) = flags % 0x100; |
875 | 0 | *(buf + file->size - 2) = (flags % 0x10000) / 0x100; |
876 | |
|
877 | 0 | sc_log(ctx, "Update token info (label:'%s',flags:%X,p15card->flags:%X)", buf, flags, p15card->flags); |
878 | 0 | rv = sc_pkcs15init_update_file(profile, p15card, file, buf, file->size); |
879 | 0 | free(buf); |
880 | 0 | sc_file_free(file); |
881 | |
|
882 | 0 | if (rv > 0) |
883 | 0 | rv = 0; |
884 | |
|
885 | 0 | SC_FUNC_RETURN(ctx, 1, rv); |
886 | 0 | } |
887 | | |
888 | | |
889 | | static int |
890 | | cosm_emu_write_info(struct sc_profile *profile, struct sc_pkcs15_card *p15card, |
891 | | struct sc_pkcs15_object *pin_obj) |
892 | 0 | { |
893 | 0 | SC_FUNC_CALLED(p15card->card->ctx, 1); |
894 | | /* No OpenSC Info file in the native Oberthur card */ |
895 | 0 | SC_FUNC_RETURN(p15card->card->ctx, 1, SC_SUCCESS); |
896 | 0 | } |
897 | | #endif |
898 | | |
899 | | |
900 | | static struct sc_pkcs15init_operations |
901 | | sc_pkcs15init_oberthur_operations = { |
902 | | cosm_erase_card, |
903 | | NULL, /* init_card */ |
904 | | cosm_create_dir, /* create_dir */ |
905 | | NULL, /* create_domain */ |
906 | | cosm_select_pin_reference, |
907 | | cosm_create_pin, |
908 | | NULL, /* select_key_reference */ |
909 | | cosm_create_key, /* create_key */ |
910 | | cosm_store_key, /* store_key */ |
911 | | cosm_generate_key, /* generate_key */ |
912 | | NULL, |
913 | | NULL, /* encode private/public key */ |
914 | | NULL, /* finalize_card */ |
915 | | NULL, /* delete_object */ |
916 | | #ifdef ENABLE_OPENSSL |
917 | | cosm_emu_update_dir, |
918 | | cosm_emu_update_any_df, |
919 | | cosm_emu_update_tokeninfo, |
920 | | cosm_emu_write_info, |
921 | | NULL, |
922 | | NULL |
923 | | #else |
924 | | NULL, NULL, NULL, NULL, NULL, |
925 | | NULL |
926 | | #endif |
927 | | }; |
928 | | |
929 | | struct sc_pkcs15init_operations * |
930 | | sc_pkcs15init_get_oberthur_ops(void) |
931 | 945 | { |
932 | 945 | return &sc_pkcs15init_oberthur_operations; |
933 | 945 | } |