/src/opensc/src/pkcs15init/pkcs15-oberthur-awp.c
Line | Count | Source (jump to first uncovered line) |
1 | | /* |
2 | | * Oberthur AWP extension for PKCS #15 initialization |
3 | | * |
4 | | * Copyright (C) 2010 Viktor Tarasov <viktor.tarasov@opentrust.com> |
5 | | * Copyright (C) 2002 Juha Yrjola <juha.yrjola@iki.fi> |
6 | | * |
7 | | * This library is free software; you can redistribute it and/or |
8 | | * modify it under the terms of the GNU Lesser General Public |
9 | | * License as published by the Free Software Foundation; either |
10 | | * version 2.1 of the License, or (at your option) any later version. |
11 | | * |
12 | | * This library is distributed in the hope that it will be useful, |
13 | | * but WITHOUT ANY WARRANTY; without even the implied warranty of |
14 | | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU |
15 | | * Lesser General Public License for more details. |
16 | | * |
17 | | * You should have received a copy of the GNU Lesser General Public |
18 | | * License along with this library; if not, write to the Free Software |
19 | | * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA |
20 | | * |
21 | | * best view with tabstop=4 |
22 | | * |
23 | | */ |
24 | | |
25 | | #include <stdlib.h> |
26 | | #include <string.h> |
27 | | #include <sys/types.h> |
28 | | |
29 | | #include "config.h" |
30 | | #include "pkcs15-oberthur.h" |
31 | | |
32 | | #include "libopensc/opensc.h" |
33 | | #include "libopensc/cardctl.h" |
34 | | #include "libopensc/log.h" |
35 | | #include "profile.h" |
36 | | #include "pkcs15-init.h" |
37 | | #include "libopensc/asn1.h" |
38 | | |
39 | | #ifdef ENABLE_OPENSSL |
40 | | #include "libopensc/sc-ossl-compat.h" |
41 | | |
42 | | struct awp_lv zero_lv = { 0, NULL }; |
43 | | struct awp_lv x30_lv = { 0x10, (unsigned char *)"0000000000000000" }; |
44 | | |
45 | | static unsigned char * |
46 | | awp_get_commonName(X509 *x) |
47 | 0 | { |
48 | 0 | unsigned char *ret = NULL; |
49 | 0 | int r; |
50 | |
|
51 | 0 | r = X509_NAME_get_index_by_NID(X509_get_subject_name(x), |
52 | 0 | NID_commonName, -1); |
53 | 0 | if (r >= 0) { |
54 | 0 | X509_NAME_ENTRY *ne; |
55 | 0 | ASN1_STRING *a_str; |
56 | |
|
57 | 0 | if (!(ne = X509_NAME_get_entry(X509_get_subject_name(x), r))) |
58 | 0 | ; |
59 | 0 | else if (!(a_str = X509_NAME_ENTRY_get_data(ne))) |
60 | 0 | ; |
61 | 0 | else if (a_str->type == 0x0C) { |
62 | 0 | ret = malloc(a_str->length + 1); |
63 | 0 | if (ret) { |
64 | 0 | memcpy(ret, a_str->data, a_str->length); |
65 | 0 | *(ret + a_str->length) = '\0'; |
66 | 0 | } |
67 | 0 | } |
68 | 0 | else { |
69 | 0 | unsigned char *tmp = NULL; |
70 | |
|
71 | 0 | r = ASN1_STRING_to_UTF8(&tmp, a_str); |
72 | 0 | if (r > 0) { |
73 | 0 | ret = malloc(r + 1); |
74 | 0 | if (ret) { |
75 | 0 | memcpy(ret, tmp, r); |
76 | 0 | *(ret + r) = '\0'; |
77 | 0 | } |
78 | |
|
79 | 0 | OPENSSL_free(tmp); |
80 | 0 | } |
81 | 0 | } |
82 | 0 | } |
83 | |
|
84 | 0 | return ret; |
85 | 0 | } |
86 | | |
87 | | |
88 | | static int |
89 | | awp_new_file(struct sc_pkcs15_card *p15card, struct sc_profile *profile, |
90 | | unsigned int type, unsigned int num, |
91 | | struct sc_file **info_out, struct sc_file **obj_out) |
92 | 0 | { |
93 | 0 | struct sc_context *ctx = p15card->card->ctx; |
94 | 0 | struct sc_file *ifile=NULL, *ofile=NULL; |
95 | 0 | char name[NAME_MAX_LEN]; |
96 | 0 | const char *itag=NULL, *otag=NULL; |
97 | |
|
98 | 0 | LOG_FUNC_CALLED(ctx); |
99 | 0 | sc_log(ctx, "type 0x%X; num %i; info %p; obj %p", type, num, info_out, obj_out); |
100 | 0 | switch (type) { |
101 | 0 | case SC_PKCS15_TYPE_CERT_X509: |
102 | 0 | itag = "certificate-info"; |
103 | 0 | otag = "template-certificate"; |
104 | 0 | break; |
105 | 0 | case SC_PKCS15_TYPE_PRKEY_RSA: |
106 | 0 | case COSM_TYPE_PRKEY_RSA: |
107 | 0 | itag = "private-key-info"; |
108 | 0 | otag = "template-private-key"; |
109 | 0 | break; |
110 | 0 | case SC_PKCS15_TYPE_PUBKEY_RSA: |
111 | 0 | case COSM_TYPE_PUBKEY_RSA: |
112 | 0 | itag = "public-key-info"; |
113 | 0 | otag = "template-public-key"; |
114 | 0 | break; |
115 | 0 | case SC_PKCS15_TYPE_DATA_OBJECT: |
116 | 0 | itag = "data-info"; |
117 | 0 | otag = "template-data"; |
118 | 0 | break; |
119 | 0 | case COSM_TYPE_PRIVDATA_OBJECT: |
120 | 0 | itag = "privdata-info"; |
121 | 0 | otag = "template-privdata"; |
122 | 0 | break; |
123 | 0 | case SC_PKCS15_TYPE_AUTH_PIN: |
124 | 0 | case COSM_TOKENINFO : |
125 | 0 | itag = "token-info"; |
126 | 0 | num = 0; |
127 | 0 | break; |
128 | 0 | case COSM_PUBLIC_LIST: |
129 | 0 | itag = "public-list"; |
130 | 0 | num = 0; |
131 | 0 | break; |
132 | 0 | case COSM_PRIVATE_LIST: |
133 | 0 | itag = "private-list"; |
134 | 0 | num = 0; |
135 | 0 | break; |
136 | 0 | case COSM_CONTAINER_LIST: |
137 | 0 | itag = "container-list"; |
138 | 0 | num = 0; |
139 | 0 | break; |
140 | 0 | default: |
141 | 0 | return SC_ERROR_INVALID_ARGUMENTS; |
142 | 0 | } |
143 | | |
144 | 0 | if (itag) { |
145 | 0 | snprintf(name, sizeof(name),"%s-%s", COSM_TITLE, itag); |
146 | 0 | sc_log(ctx, "info template %s",name); |
147 | 0 | if (sc_profile_get_file(profile, name, &ifile) < 0) { |
148 | 0 | sc_log(ctx, "profile does not defines template '%s'", name); |
149 | 0 | return SC_ERROR_INCONSISTENT_PROFILE; |
150 | 0 | } |
151 | 0 | } |
152 | | |
153 | 0 | if (otag) { |
154 | 0 | sc_log(ctx, "obj template %s",otag); |
155 | 0 | if (sc_profile_get_file(profile, otag, &ofile) < 0) { |
156 | 0 | sc_file_free(ifile); |
157 | 0 | sc_log(ctx, "profile does not defines template '%s'", name); |
158 | 0 | return SC_ERROR_INCONSISTENT_PROFILE; |
159 | 0 | } |
160 | | |
161 | 0 | ofile->id |= (num & 0xFF); |
162 | 0 | ofile->path.value[ofile->path.len-1] |= (num & 0xFF); |
163 | 0 | } |
164 | | |
165 | 0 | if (ifile) { |
166 | 0 | if(info_out) { |
167 | 0 | if (ofile) { |
168 | 0 | ifile->id = ofile->id | 0x100; |
169 | |
|
170 | 0 | ifile->path = ofile->path; |
171 | 0 | ifile->path.value[ifile->path.len-2] |= 0x01; |
172 | 0 | } |
173 | |
|
174 | 0 | sc_log(ctx, |
175 | 0 | "info_file(id:%04X,size:%"SC_FORMAT_LEN_SIZE_T"u,rlen:%"SC_FORMAT_LEN_SIZE_T"u)", |
176 | 0 | ifile->id, ifile->size, ifile->record_length); |
177 | 0 | *info_out = ifile; |
178 | 0 | } |
179 | 0 | else { |
180 | 0 | sc_file_free(ifile); |
181 | 0 | } |
182 | 0 | } |
183 | |
|
184 | 0 | if (ofile) { |
185 | 0 | sc_log(ctx, |
186 | 0 | "obj file %04X; size %"SC_FORMAT_LEN_SIZE_T"u; ", |
187 | 0 | ofile->id, ofile->size); |
188 | 0 | if (obj_out) |
189 | 0 | *obj_out = ofile; |
190 | 0 | else |
191 | 0 | sc_file_free(ofile); |
192 | 0 | } |
193 | |
|
194 | 0 | LOG_FUNC_RETURN(ctx, SC_SUCCESS); |
195 | 0 | } |
196 | | |
197 | | |
198 | | static int |
199 | | awp_update_blob(struct sc_context *ctx, |
200 | | unsigned char **blob, int *blob_size, |
201 | | struct awp_lv *lv, int type) |
202 | 0 | { |
203 | 0 | unsigned char *pp; |
204 | |
|
205 | 0 | LOG_FUNC_CALLED(ctx); |
206 | 0 | switch (type) { |
207 | 0 | case TLV_TYPE_LLV : |
208 | 0 | if (!(pp = realloc(*blob, *blob_size + 2 + lv->len))) |
209 | 0 | return SC_ERROR_OUT_OF_MEMORY; |
210 | 0 | *(pp + *blob_size) = (lv->len >> 8) & 0xFF; |
211 | 0 | *(pp + *blob_size + 1) = lv->len & 0xFF; |
212 | 0 | memcpy(pp + *blob_size + 2, lv->value, (lv->len & 0xFF)); |
213 | 0 | *blob_size += 2 + lv->len; |
214 | 0 | break; |
215 | 0 | case TLV_TYPE_LV : |
216 | 0 | if (!(pp = realloc(*blob, *blob_size + 1 + lv->len))) |
217 | 0 | return SC_ERROR_OUT_OF_MEMORY; |
218 | 0 | *(pp + *blob_size) = lv->len & 0xFF; |
219 | 0 | memcpy(pp + *blob_size + 1, lv->value, (lv->len & 0xFF)); |
220 | 0 | *blob_size += 1 + lv->len; |
221 | 0 | break; |
222 | 0 | case TLV_TYPE_V : |
223 | 0 | if (0 == *blob_size + lv->len) |
224 | 0 | return SC_ERROR_INVALID_DATA; |
225 | 0 | if (!(pp = realloc(*blob, *blob_size + lv->len))) |
226 | 0 | return SC_ERROR_OUT_OF_MEMORY; |
227 | 0 | memcpy(pp + *blob_size, lv->value, lv->len); |
228 | 0 | *blob_size += lv->len; |
229 | 0 | break; |
230 | 0 | default: |
231 | 0 | sc_log(ctx, "Invalid tlv type %i",type); |
232 | 0 | return SC_ERROR_INCORRECT_PARAMETERS; |
233 | 0 | } |
234 | | |
235 | 0 | *blob = pp; |
236 | |
|
237 | 0 | LOG_FUNC_RETURN(ctx, SC_SUCCESS); |
238 | 0 | } |
239 | | |
240 | | |
241 | | static int |
242 | | awp_new_container_entry(struct sc_pkcs15_card *p15card, unsigned char *buff, size_t len) |
243 | 0 | { |
244 | 0 | struct sc_context *ctx = p15card->card->ctx; |
245 | 0 | int mm, rv = 0; |
246 | 0 | unsigned ii, marks[5] = {4,6,8,10,0}; |
247 | 0 | unsigned char rand_buf[0x10]; |
248 | |
|
249 | 0 | LOG_FUNC_CALLED(ctx); |
250 | 0 | if (len<0x34) |
251 | 0 | LOG_TEST_RET(ctx, SC_ERROR_INCORRECT_PARAMETERS, "Invalid container update size"); |
252 | | |
253 | 0 | rv = sc_get_challenge(p15card->card, rand_buf, sizeof(rand_buf)); |
254 | 0 | LOG_TEST_RET(ctx, rv, "Cannot get challenge"); |
255 | | |
256 | 0 | *(buff + 12) = 0x26; |
257 | 0 | *(buff + 13) = '{'; |
258 | 0 | for (ii=0, mm = 0; ii<sizeof(rand_buf); ii++) { |
259 | 0 | if (ii==marks[mm]) { |
260 | 0 | *(buff + 14 + ii*2 + mm) = '-'; |
261 | 0 | mm++; |
262 | 0 | } |
263 | 0 | sprintf((char *)(buff + 14 + ii*2 + mm),"%02X", rand_buf[ii]); |
264 | 0 | } |
265 | 0 | *(buff + 14 + ii*2 + mm) = (unsigned char)'}'; |
266 | |
|
267 | 0 | LOG_FUNC_RETURN(ctx, rv); |
268 | 0 | } |
269 | | |
270 | | |
271 | | static int |
272 | | awp_create_container_record (struct sc_pkcs15_card *p15card, struct sc_profile *profile, |
273 | | struct sc_file *list_file, struct awp_crypto_container *acc) |
274 | 0 | { |
275 | 0 | struct sc_context *ctx = p15card->card->ctx; |
276 | 0 | int rv; |
277 | 0 | unsigned char *buff = NULL; |
278 | |
|
279 | 0 | LOG_FUNC_CALLED(ctx); |
280 | 0 | sc_log(ctx, "container file(file-id:%X,rlen:%"SC_FORMAT_LEN_SIZE_T"u,rcount:%"SC_FORMAT_LEN_SIZE_T"u)", |
281 | 0 | list_file->id, list_file->record_length, list_file->record_count); |
282 | |
|
283 | 0 | buff = malloc(list_file->record_length); |
284 | 0 | if (!buff) |
285 | 0 | LOG_FUNC_RETURN(ctx, SC_ERROR_OUT_OF_MEMORY); |
286 | | |
287 | 0 | memset(buff, 0, list_file->record_length); |
288 | |
|
289 | 0 | rv = awp_new_container_entry(p15card, buff, list_file->record_length); |
290 | 0 | if (rv < 0) { |
291 | 0 | free(buff); |
292 | 0 | sc_log(ctx, "Cannot create container"); |
293 | 0 | LOG_FUNC_RETURN(ctx, rv); |
294 | 0 | } |
295 | | |
296 | 0 | *(buff + 0) = (acc->pubkey_id >> 8) & 0xFF; |
297 | 0 | *(buff + 1) = acc->pubkey_id & 0xFF; |
298 | 0 | *(buff + 2) = (acc->prkey_id >> 8) & 0xFF; |
299 | 0 | *(buff + 3) = acc->prkey_id & 0xFF; |
300 | 0 | *(buff + 4) = (acc->cert_id >> 8) & 0xFF; |
301 | 0 | *(buff + 5) = acc->cert_id & 0xFF; |
302 | |
|
303 | 0 | rv = sc_select_file(p15card->card, &list_file->path, NULL); |
304 | 0 | if (rv == SC_ERROR_FILE_NOT_FOUND) |
305 | 0 | rv = sc_pkcs15init_create_file(profile, p15card, list_file); |
306 | |
|
307 | 0 | if (!rv) |
308 | 0 | rv = sc_append_record(p15card->card, buff, list_file->record_length, SC_RECORD_BY_REC_NR); |
309 | |
|
310 | 0 | free(buff); |
311 | 0 | LOG_FUNC_RETURN(ctx, rv); |
312 | 0 | } |
313 | | |
314 | | |
315 | | static int |
316 | | awp_create_container(struct sc_pkcs15_card *p15card, struct sc_profile *profile, int type, |
317 | | struct awp_lv *key_id, struct awp_crypto_container *acc) |
318 | 0 | { |
319 | 0 | struct sc_context *ctx = p15card->card->ctx; |
320 | 0 | struct sc_file *clist = NULL, *file = NULL; |
321 | 0 | int rv = 0; |
322 | |
|
323 | 0 | LOG_FUNC_CALLED(ctx); |
324 | 0 | sc_log(ctx, "create container(%X:%X:%X)", acc->prkey_id, acc->cert_id, acc->pubkey_id); |
325 | |
|
326 | 0 | rv = awp_new_file(p15card, profile, COSM_CONTAINER_LIST, 0, &clist, NULL); |
327 | 0 | LOG_TEST_RET(ctx, rv, "Create container failed"); |
328 | 0 | sc_log(ctx, "container cfile(rcount:%"SC_FORMAT_LEN_SIZE_T"u,rlength:%"SC_FORMAT_LEN_SIZE_T"u)", clist->record_count, clist->record_length); |
329 | |
|
330 | 0 | rv = sc_select_file(p15card->card, &clist->path, &file); |
331 | 0 | LOG_TEST_RET(ctx, rv, "Create container failed: cannot select container's list"); |
332 | 0 | file->record_length = clist->record_length; |
333 | |
|
334 | 0 | sc_log(ctx, "container file(rcount:%"SC_FORMAT_LEN_SIZE_T"u,rlength:%"SC_FORMAT_LEN_SIZE_T"u)", file->record_count, file->record_length); |
335 | 0 | sc_log(ctx, "Append new record %"SC_FORMAT_LEN_SIZE_T"u for private key", file->record_count + 1); |
336 | |
|
337 | 0 | rv = awp_create_container_record(p15card, profile, file, acc); |
338 | |
|
339 | 0 | sc_file_free(file); |
340 | 0 | sc_file_free(clist); |
341 | |
|
342 | 0 | LOG_FUNC_RETURN(ctx, rv); |
343 | 0 | } |
344 | | |
345 | | |
346 | | static int |
347 | | awp_update_container_entry (struct sc_pkcs15_card *p15card, struct sc_profile *profile, |
348 | | struct sc_file *list_file, int type, int file_id, |
349 | | size_t rec, int offs) |
350 | 0 | { |
351 | 0 | struct sc_context *ctx = p15card->card->ctx; |
352 | 0 | int rv; |
353 | 0 | unsigned char *buff = NULL; |
354 | |
|
355 | 0 | LOG_FUNC_CALLED(ctx); |
356 | 0 | sc_log(ctx, |
357 | 0 | "update container entry(type:%X,id %i,rec %"SC_FORMAT_LEN_SIZE_T"u,offs %i", |
358 | 0 | type, file_id, rec, offs); |
359 | 0 | sc_log(ctx, "container file(file-id:%X,rlen:%"SC_FORMAT_LEN_SIZE_T"u,rcount:%"SC_FORMAT_LEN_SIZE_T"u)", |
360 | 0 | list_file->id, list_file->record_length, list_file->record_count); |
361 | |
|
362 | 0 | buff = malloc(list_file->record_length); |
363 | 0 | if (!buff) |
364 | 0 | LOG_FUNC_RETURN(ctx, SC_ERROR_OUT_OF_MEMORY); |
365 | | |
366 | 0 | memset(buff, 0, list_file->record_length); |
367 | |
|
368 | 0 | if (rec > list_file->record_count) { |
369 | 0 | rv = awp_new_container_entry(p15card, buff, list_file->record_length); |
370 | 0 | } |
371 | 0 | else { |
372 | 0 | rv = sc_select_file(p15card->card, &list_file->path, NULL); |
373 | 0 | if (!rv) |
374 | 0 | rv = sc_read_record(p15card->card, (unsigned int)rec, 0, buff, list_file->record_length, SC_RECORD_BY_REC_NR); |
375 | 0 | } |
376 | 0 | if (rv < 0) { |
377 | 0 | free(buff); |
378 | 0 | LOG_FUNC_RETURN(ctx, rv); |
379 | 0 | } |
380 | | |
381 | 0 | switch (type) { |
382 | 0 | case SC_PKCS15_TYPE_PUBKEY_RSA: |
383 | 0 | case COSM_TYPE_PUBKEY_RSA: |
384 | 0 | if (*(buff + offs + 4)) |
385 | 0 | sc_log(ctx, "Insert public key to container that contains certificate %02X%02X", |
386 | 0 | *(buff + offs + 4), *(buff + offs + 5)); |
387 | 0 | *(buff + offs + 0) = (file_id >> 8) & 0xFF; |
388 | 0 | *(buff + offs + 1) = file_id & 0xFF; |
389 | 0 | break; |
390 | 0 | case SC_PKCS15_TYPE_PRKEY_RSA: |
391 | 0 | case COSM_TYPE_PRKEY_RSA: |
392 | 0 | if (*(buff + offs + 2)) { |
393 | 0 | free(buff); |
394 | 0 | LOG_TEST_RET(ctx, SC_ERROR_INVALID_CARD, "private key exists already"); |
395 | 0 | } |
396 | | |
397 | 0 | *(buff + offs + 2) = (file_id >> 8) & 0xFF; |
398 | 0 | *(buff + offs + 3) = file_id & 0xFF; |
399 | 0 | break; |
400 | 0 | case SC_PKCS15_TYPE_CERT_X509 : |
401 | 0 | *(buff + offs + 4) = (file_id >> 8) & 0xFF; |
402 | 0 | *(buff + offs + 5) = file_id & 0xFF; |
403 | 0 | break; |
404 | 0 | default: |
405 | 0 | free(buff); |
406 | 0 | LOG_FUNC_RETURN(ctx, SC_ERROR_INCORRECT_PARAMETERS); |
407 | 0 | } |
408 | | |
409 | 0 | if (rec > list_file->record_count) { |
410 | 0 | rv = sc_select_file(p15card->card, &list_file->path, NULL); |
411 | 0 | if (rv == SC_ERROR_FILE_NOT_FOUND) |
412 | 0 | rv = sc_pkcs15init_create_file(profile, p15card, list_file); |
413 | |
|
414 | 0 | if (!rv) |
415 | 0 | rv = sc_append_record(p15card->card, buff, list_file->record_length, SC_RECORD_BY_REC_NR); |
416 | 0 | } |
417 | 0 | else { |
418 | 0 | rv = sc_update_record(p15card->card, (unsigned int)rec, 0, buff, list_file->record_length, SC_RECORD_BY_REC_NR); |
419 | 0 | } |
420 | |
|
421 | 0 | free(buff); |
422 | 0 | LOG_FUNC_RETURN(ctx, rv); |
423 | 0 | } |
424 | | |
425 | | |
426 | | static int |
427 | | awp_update_container(struct sc_pkcs15_card *p15card, struct sc_profile *profile, int type, |
428 | | struct awp_lv *key_id, unsigned obj_id, unsigned int *prkey_id) |
429 | 0 | { |
430 | 0 | struct sc_context *ctx = p15card->card->ctx; |
431 | 0 | struct sc_file *clist = NULL, *file = NULL; |
432 | 0 | struct sc_path private_path; |
433 | 0 | int rv = 0; |
434 | 0 | size_t rec; |
435 | 0 | int rec_offs; |
436 | 0 | unsigned char *list = NULL; |
437 | |
|
438 | 0 | LOG_FUNC_CALLED(ctx); |
439 | 0 | sc_log(ctx, "update container(type:%X,obj_id:%X)", type, obj_id); |
440 | |
|
441 | 0 | if (prkey_id) |
442 | 0 | *prkey_id = 0; |
443 | | |
444 | | /* |
445 | | * Get path of the DF that contains private objects. |
446 | | */ |
447 | 0 | rv = awp_new_file(p15card, profile, SC_PKCS15_TYPE_PRKEY_RSA, 1, NULL, &file); |
448 | 0 | if (rv) |
449 | 0 | goto done; |
450 | 0 | private_path = file->path; |
451 | 0 | sc_file_free(file), file=NULL; |
452 | |
|
453 | 0 | rv = awp_new_file(p15card, profile, COSM_CONTAINER_LIST, 0, &clist, NULL); |
454 | 0 | if (rv) |
455 | 0 | goto done; |
456 | | |
457 | 0 | rv = sc_select_file(p15card->card, &clist->path, &file); |
458 | 0 | if (rv) |
459 | 0 | goto done; |
460 | 0 | file->record_length = clist->record_length; |
461 | |
|
462 | 0 | if (type == SC_PKCS15_TYPE_PRKEY_RSA || type == COSM_TYPE_PRKEY_RSA) { |
463 | 0 | rec_offs = 0; |
464 | 0 | rv = awp_update_container_entry(p15card, profile, file, type, obj_id, file->record_count + 1, rec_offs); |
465 | 0 | goto done; |
466 | 0 | } |
467 | | |
468 | 0 | list = malloc(AWP_CONTAINER_RECORD_LEN * file->record_count); |
469 | 0 | if (!list) { |
470 | 0 | rv = SC_ERROR_OUT_OF_MEMORY; |
471 | 0 | goto done; |
472 | 0 | } |
473 | | |
474 | 0 | rv = sc_pkcs15init_authenticate(profile, p15card, file, SC_AC_OP_READ); |
475 | 0 | if (rv) |
476 | 0 | goto done; |
477 | | |
478 | 0 | for (rec=0; rec < file->record_count; rec++) { |
479 | 0 | unsigned char tmp[256]; |
480 | |
|
481 | 0 | rv = sc_read_record(p15card->card, (unsigned int)rec + 1, 0, tmp, sizeof(tmp), SC_RECORD_BY_REC_NR); |
482 | 0 | if (rv >= AWP_CONTAINER_RECORD_LEN) |
483 | 0 | memcpy(list + rec*AWP_CONTAINER_RECORD_LEN, tmp, AWP_CONTAINER_RECORD_LEN); |
484 | 0 | else |
485 | 0 | goto done; |
486 | 0 | } |
487 | | |
488 | 0 | for (rec=0, rv=0; !rv && rec < file->record_count; rec++) { |
489 | 0 | for (rec_offs=0; !rv && rec_offs<12; rec_offs+=6) { |
490 | 0 | int offs; |
491 | |
|
492 | 0 | sc_log(ctx, "rec %zu; rec_offs %d", rec, rec_offs); |
493 | 0 | offs = (int)rec*AWP_CONTAINER_RECORD_LEN + rec_offs; |
494 | 0 | if (*(list + offs + 2)) { |
495 | 0 | unsigned char *buff = NULL; |
496 | 0 | int id_offs; |
497 | 0 | struct sc_path path = private_path; |
498 | 0 | struct sc_file *ff = NULL; |
499 | |
|
500 | 0 | path.value[path.len - 2] = *(list + offs + 2) | 0x01; |
501 | 0 | path.value[path.len - 1] = *(list + offs + 3); |
502 | 0 | rv = sc_select_file(p15card->card, &path, &ff); |
503 | 0 | if (rv) |
504 | 0 | continue; |
505 | | |
506 | 0 | rv = sc_pkcs15init_authenticate(profile, p15card, ff, SC_AC_OP_READ); |
507 | 0 | if (rv) { |
508 | 0 | sc_file_free(ff); |
509 | 0 | break; |
510 | 0 | } |
511 | | |
512 | 0 | buff = malloc(ff->size); |
513 | 0 | if (!buff) |
514 | 0 | rv = SC_ERROR_OUT_OF_MEMORY; |
515 | |
|
516 | 0 | if (!rv) { |
517 | 0 | rv = sc_read_binary(p15card->card, 0, buff, ff->size, 0); |
518 | 0 | if ((unsigned)rv == ff->size) { |
519 | 0 | rv = 0; |
520 | 0 | id_offs = 5 + *(buff+3); |
521 | |
|
522 | 0 | if (key_id->len == *(buff + id_offs) && |
523 | 0 | !memcmp(key_id->value, buff + id_offs + 1, key_id->len)) { |
524 | 0 | sc_log(ctx, "found key file friend"); |
525 | 0 | if (!rv) |
526 | 0 | rv = awp_update_container_entry(p15card, profile, file, type, obj_id, rec + 1, rec_offs); |
527 | |
|
528 | 0 | if (rv >= 0 && prkey_id) |
529 | 0 | *prkey_id = *(list + offs + 2) * 0x100 + *(list + offs + 3); |
530 | 0 | } |
531 | 0 | } |
532 | 0 | } |
533 | |
|
534 | 0 | free(buff); |
535 | 0 | sc_file_free(ff); |
536 | |
|
537 | 0 | if (rv) |
538 | 0 | break; |
539 | 0 | } |
540 | 0 | } |
541 | 0 | } |
542 | |
|
543 | 0 | done: |
544 | 0 | sc_file_free(clist); |
545 | 0 | sc_file_free(file); |
546 | 0 | if (list) free(list); |
547 | |
|
548 | 0 | LOG_FUNC_RETURN(ctx, rv); |
549 | 0 | } |
550 | | |
551 | | |
552 | | static int |
553 | | awp_update_df_create_pin(struct sc_pkcs15_card *p15card, struct sc_profile *profile, |
554 | | struct sc_pkcs15_object *pinobj) |
555 | 0 | { |
556 | 0 | SC_FUNC_CALLED(p15card->card->ctx, 1); |
557 | | /* No update DF when creating PIN objects */ |
558 | 0 | SC_FUNC_RETURN(p15card->card->ctx, 1, SC_SUCCESS); |
559 | 0 | } |
560 | | |
561 | | |
562 | | static int |
563 | | awp_set_certificate_info (struct sc_pkcs15_card *p15card, |
564 | | struct sc_profile *profile, |
565 | | struct sc_file *file, |
566 | | struct awp_cert_info *ci) |
567 | 0 | { |
568 | 0 | struct sc_context *ctx = p15card->card->ctx; |
569 | 0 | int r = 0, blob_size; |
570 | 0 | unsigned char *blob; |
571 | 0 | const char *default_cert_label = "Certificate"; |
572 | |
|
573 | 0 | LOG_FUNC_CALLED(ctx); |
574 | 0 | blob_size = 2; |
575 | 0 | if (!(blob = malloc(blob_size))) { |
576 | 0 | r = SC_ERROR_OUT_OF_MEMORY; |
577 | 0 | goto done; |
578 | 0 | } |
579 | | |
580 | | /* TODO: cert flags */ |
581 | 0 | *blob = (COSM_TAG_CERT >> 8) & 0xFF; |
582 | 0 | *(blob + 1) = COSM_TAG_CERT & 0xFF; |
583 | |
|
584 | 0 | if (ci->label.len && ci->label.len != strlen(default_cert_label) |
585 | 0 | && memcmp(ci->label.value, default_cert_label, strlen(default_cert_label))) |
586 | 0 | r = awp_update_blob(ctx, &blob, &blob_size, &ci->label, TLV_TYPE_LLV); |
587 | 0 | else |
588 | 0 | r = awp_update_blob(ctx, &blob, &blob_size, &ci->cn, TLV_TYPE_LLV); |
589 | 0 | if (r) |
590 | 0 | goto done; |
591 | | |
592 | 0 | r = awp_update_blob(ctx, &blob, &blob_size, &ci->id, TLV_TYPE_LLV); |
593 | 0 | if (r) |
594 | 0 | goto done; |
595 | | |
596 | 0 | r = awp_update_blob(ctx, &blob, &blob_size, &ci->subject, TLV_TYPE_LLV); |
597 | 0 | if (r) |
598 | 0 | goto done; |
599 | | |
600 | 0 | if (ci->issuer.len != ci->subject.len || |
601 | 0 | memcmp(ci->issuer.value, ci->subject.value, ci->subject.len)) { |
602 | 0 | r = awp_update_blob(ctx, &blob, &blob_size, &ci->issuer, TLV_TYPE_LLV); |
603 | 0 | if (r) |
604 | 0 | goto done; |
605 | 0 | r = awp_update_blob(ctx, &blob, &blob_size, &ci->serial, TLV_TYPE_LLV); |
606 | 0 | if (r) |
607 | 0 | goto done; |
608 | 0 | } |
609 | 0 | else { |
610 | 0 | r = awp_update_blob(ctx, &blob, &blob_size, &zero_lv, TLV_TYPE_LLV); |
611 | 0 | if (r) |
612 | 0 | goto done; |
613 | 0 | r = awp_update_blob(ctx, &blob, &blob_size, &zero_lv, TLV_TYPE_LLV); |
614 | 0 | if (r) |
615 | 0 | goto done; |
616 | 0 | } |
617 | | |
618 | 0 | file->size = blob_size; |
619 | 0 | r = sc_pkcs15init_create_file(profile, p15card, file); |
620 | 0 | if (r) |
621 | 0 | goto done; |
622 | | |
623 | 0 | r = sc_pkcs15init_update_file(profile, p15card, file, blob, blob_size); |
624 | 0 | if (r < 0) |
625 | 0 | goto done; |
626 | | |
627 | 0 | r = 0; |
628 | 0 | done: |
629 | 0 | if (blob) |
630 | 0 | free(blob); |
631 | |
|
632 | 0 | LOG_FUNC_RETURN(ctx, r); |
633 | 0 | } |
634 | | |
635 | | |
636 | | static int |
637 | | awp_update_object_list(struct sc_pkcs15_card *p15card, struct sc_profile *profile, |
638 | | unsigned int type, int num) |
639 | 0 | { |
640 | 0 | struct sc_context *ctx = p15card->card->ctx; |
641 | 0 | struct sc_file *obj_file = NULL, *lst_file = NULL; |
642 | 0 | struct sc_file *file = NULL; |
643 | 0 | char obj_name[NAME_MAX_LEN], lst_name[NAME_MAX_LEN]; |
644 | 0 | unsigned char *buff = NULL; |
645 | 0 | int rv; |
646 | 0 | unsigned ii; |
647 | 0 | unsigned long flags; |
648 | |
|
649 | 0 | LOG_FUNC_CALLED(ctx); |
650 | 0 | sc_log(ctx, "type %i, num %i", type, num); |
651 | 0 | switch (type) { |
652 | 0 | case SC_PKCS15_TYPE_CERT_X509: |
653 | 0 | snprintf(obj_name, NAME_MAX_LEN, "template-certificate"); |
654 | 0 | snprintf(lst_name, NAME_MAX_LEN,"%s-public-list", COSM_TITLE); |
655 | 0 | break; |
656 | 0 | case SC_PKCS15_TYPE_PUBKEY_RSA: |
657 | 0 | case COSM_TYPE_PUBKEY_RSA: |
658 | 0 | snprintf(obj_name, NAME_MAX_LEN, "template-public-key"); |
659 | 0 | snprintf(lst_name, NAME_MAX_LEN,"%s-public-list", COSM_TITLE); |
660 | 0 | break; |
661 | 0 | case SC_PKCS15_TYPE_DATA_OBJECT: |
662 | 0 | snprintf(obj_name, NAME_MAX_LEN, "template-data"); |
663 | 0 | snprintf(lst_name, NAME_MAX_LEN,"%s-public-list", COSM_TITLE); |
664 | 0 | break; |
665 | 0 | case COSM_TYPE_PRIVDATA_OBJECT: |
666 | 0 | snprintf(obj_name, NAME_MAX_LEN, "template-privdata"); |
667 | 0 | snprintf(lst_name, NAME_MAX_LEN,"%s-private-list", COSM_TITLE); |
668 | 0 | break; |
669 | 0 | case SC_PKCS15_TYPE_PRKEY_RSA: |
670 | 0 | case COSM_TYPE_PRKEY_RSA: |
671 | 0 | snprintf(obj_name, NAME_MAX_LEN,"template-private-key"); |
672 | 0 | snprintf(lst_name, NAME_MAX_LEN,"%s-private-list", COSM_TITLE); |
673 | 0 | break; |
674 | 0 | default: |
675 | 0 | sc_log(ctx, "Not supported file type %X", type); |
676 | 0 | return SC_ERROR_INVALID_ARGUMENTS; |
677 | 0 | } |
678 | | |
679 | 0 | sc_log(ctx, "obj_name %s; num 0x%X",obj_name, num); |
680 | 0 | sc_log(ctx, "lst_name %s",lst_name); |
681 | 0 | if (sc_profile_get_file(profile, obj_name, &obj_file) < 0) { |
682 | 0 | sc_log(ctx, "No profile template '%s'", obj_name); |
683 | 0 | rv = SC_ERROR_NOT_SUPPORTED; |
684 | 0 | goto done; |
685 | 0 | } |
686 | 0 | else if (sc_profile_get_file(profile, lst_name, &lst_file) < 0) { |
687 | 0 | sc_log(ctx, "No profile template '%s'", lst_name); |
688 | 0 | rv = SC_ERROR_NOT_SUPPORTED; |
689 | 0 | goto done; |
690 | 0 | } |
691 | | |
692 | 0 | obj_file->id |= (num & 0xFF); |
693 | 0 | obj_file->path.value[obj_file->path.len-1] |= (num & 0xFF); |
694 | |
|
695 | 0 | rv = sc_select_file(p15card->card, &obj_file->path, &file); |
696 | 0 | if (rv) |
697 | 0 | goto done; |
698 | | |
699 | 0 | if (type == SC_PKCS15_TYPE_PUBKEY_RSA || type == COSM_TYPE_PUBKEY_RSA) { |
700 | 0 | if (file->size==PUBKEY_512_ASN1_SIZE) |
701 | 0 | file->size = 512; |
702 | 0 | else if (file->size==PUBKEY_1024_ASN1_SIZE) |
703 | 0 | file->size = 1024; |
704 | 0 | else if (file->size==PUBKEY_2048_ASN1_SIZE) |
705 | 0 | file->size = 2048; |
706 | 0 | } |
707 | |
|
708 | 0 | buff = malloc(lst_file->size); |
709 | 0 | if (!buff) { |
710 | 0 | rv = SC_ERROR_OUT_OF_MEMORY; |
711 | 0 | goto done; |
712 | 0 | } |
713 | | |
714 | 0 | rv = sc_pkcs15init_authenticate(profile, p15card, lst_file, SC_AC_OP_READ); |
715 | 0 | if (rv) |
716 | 0 | goto done; |
717 | 0 | rv = sc_pkcs15init_authenticate(profile, p15card, lst_file, SC_AC_OP_UPDATE); |
718 | 0 | if (rv) |
719 | 0 | goto done; |
720 | | |
721 | 0 | rv = sc_select_file(p15card->card, &lst_file->path, NULL); |
722 | 0 | if (rv == SC_ERROR_FILE_NOT_FOUND) |
723 | 0 | rv = sc_pkcs15init_create_file(profile, p15card, lst_file); |
724 | 0 | if (rv < 0) |
725 | 0 | goto done; |
726 | | |
727 | 0 | flags = lst_file->ef_structure; |
728 | 0 | rv = sc_read_binary(p15card->card, 0, buff, lst_file->size, &flags); |
729 | 0 | if (rv < 0) |
730 | 0 | goto done; |
731 | | |
732 | 0 | for (ii=0; ii < lst_file->size; ii+=5) |
733 | 0 | if (*(buff + ii) != COSM_LIST_TAG) |
734 | 0 | break; |
735 | 0 | if (ii>=lst_file->size) { |
736 | 0 | rv = SC_ERROR_UNKNOWN_DATA_RECEIVED; |
737 | 0 | goto done; |
738 | 0 | } |
739 | | |
740 | 0 | sc_log(ctx, |
741 | 0 | "ii %i, rv %i; %X; %"SC_FORMAT_LEN_SIZE_T"u", |
742 | 0 | ii, rv, file->id, file->size); |
743 | 0 | *(buff + ii) = COSM_LIST_TAG; |
744 | 0 | *(buff + ii + 1) = (file->id >> 8) & 0xFF; |
745 | 0 | *(buff + ii + 2) = file->id & 0xFF; |
746 | 0 | *(buff + ii + 3) = (file->size >> 8) & 0xFF; |
747 | 0 | *(buff + ii + 4) = file->size & 0xFF; |
748 | |
|
749 | 0 | rv = sc_update_binary(p15card->card, ii, buff + ii, 5, 0); |
750 | 0 | sc_log(ctx, "rv %i",rv); |
751 | 0 | if (rv < 0) |
752 | 0 | goto done; |
753 | | |
754 | 0 | rv = 0; |
755 | 0 | done: |
756 | 0 | if (buff) |
757 | 0 | free(buff); |
758 | 0 | sc_file_free(lst_file); |
759 | 0 | sc_file_free(obj_file); |
760 | 0 | sc_file_free(file); |
761 | |
|
762 | 0 | LOG_FUNC_RETURN(ctx, rv); |
763 | 0 | } |
764 | | |
765 | | |
766 | | static int |
767 | | awp_encode_key_info(struct sc_pkcs15_card *p15card, struct sc_pkcs15_object *obj, |
768 | | struct sc_pkcs15_pubkey_rsa *pubkey, struct awp_key_info *ki) |
769 | 0 | { |
770 | 0 | struct sc_context *ctx = p15card->card->ctx; |
771 | 0 | struct sc_pkcs15_prkey_info *key_info; |
772 | 0 | int r = 0; |
773 | |
|
774 | 0 | LOG_FUNC_CALLED(ctx); |
775 | |
|
776 | 0 | key_info = (struct sc_pkcs15_prkey_info *)obj->data; |
777 | |
|
778 | 0 | sc_log(ctx, "object(%s,type:%X)", obj->label, obj->type); |
779 | 0 | if (obj->type == SC_PKCS15_TYPE_PUBKEY_RSA || obj->type == COSM_TYPE_PUBKEY_RSA ) |
780 | 0 | ki->flags = COSM_TAG_PUBKEY_RSA; |
781 | 0 | else if (obj->type == SC_PKCS15_TYPE_PRKEY_RSA || obj->type == COSM_TYPE_PRKEY_RSA) |
782 | 0 | ki->flags = COSM_TAG_PRVKEY_RSA; |
783 | 0 | else |
784 | 0 | return SC_ERROR_INCORRECT_PARAMETERS; |
785 | | |
786 | 0 | if (obj->type == COSM_TYPE_PUBKEY_RSA || obj->type == COSM_TYPE_PRKEY_RSA) |
787 | 0 | ki->flags |= COSM_GENERATED; |
788 | |
|
789 | 0 | ki->label.value = (unsigned char *)strdup(obj->label); |
790 | 0 | ki->label.len = strlen(obj->label); |
791 | 0 | sc_log(ctx, |
792 | 0 | "cosm_encode_key_info() label(%zu):%s", |
793 | 0 | ki->label.len, ki->label.value); |
794 | | |
795 | | /* |
796 | | * Oberthur saves modulus value without tag and length. |
797 | | */ |
798 | 0 | sc_log(ctx, |
799 | 0 | "pubkey->modulus.len %"SC_FORMAT_LEN_SIZE_T"u", |
800 | 0 | pubkey->modulus.len); |
801 | 0 | ki->modulus.value = malloc(pubkey->modulus.len); |
802 | 0 | if (!ki->modulus.value) { |
803 | 0 | r = SC_ERROR_OUT_OF_MEMORY; |
804 | 0 | goto done; |
805 | 0 | } |
806 | 0 | memcpy(ki->modulus.value, pubkey->modulus.data, pubkey->modulus.len); |
807 | 0 | ki->modulus.len = pubkey->modulus.len; |
808 | | |
809 | | /* |
810 | | * Oberthur saves exponents as length and value, without tag. |
811 | | */ |
812 | 0 | ki->exponent.value = malloc(pubkey->exponent.len); |
813 | 0 | if (!ki->exponent.value) { |
814 | 0 | r = SC_ERROR_OUT_OF_MEMORY; |
815 | 0 | goto done; |
816 | 0 | } |
817 | 0 | memcpy(ki->exponent.value, pubkey->exponent.data, pubkey->exponent.len); |
818 | 0 | ki->exponent.len = pubkey->exponent.len; |
819 | | |
820 | | /* |
821 | | * ID |
822 | | */ |
823 | 0 | ki->id.value = calloc(1, key_info->id.len); |
824 | 0 | if (!ki->id.value) |
825 | 0 | LOG_TEST_RET(ctx, SC_ERROR_OUT_OF_MEMORY, "AWP encode cert failed: ID allocation error"); |
826 | 0 | memcpy(ki->id.value, key_info->id.value, key_info->id.len); |
827 | 0 | ki->id.len = key_info->id.len; |
828 | |
|
829 | 0 | sc_log(ctx, "cosm_encode_key_info() label:%s",ki->label.value); |
830 | 0 | done: |
831 | 0 | LOG_FUNC_RETURN(ctx, r); |
832 | 0 | } |
833 | | |
834 | | |
835 | | static void |
836 | | awp_free_key_info(struct awp_key_info *ki) |
837 | 0 | { |
838 | 0 | free(ki->modulus.value); |
839 | 0 | free(ki->exponent.value); |
840 | 0 | free(ki->id.value); |
841 | 0 | } |
842 | | |
843 | | |
844 | | static int |
845 | | awp_set_key_info (struct sc_pkcs15_card *p15card, struct sc_profile *profile, struct sc_file *file, |
846 | | struct awp_key_info *ki, struct awp_cert_info *ci) |
847 | 0 | { |
848 | 0 | struct sc_context *ctx = p15card->card->ctx; |
849 | 0 | int r = 0, blob_size; |
850 | 0 | unsigned char *blob; |
851 | |
|
852 | 0 | LOG_FUNC_CALLED(ctx); |
853 | 0 | sc_log(ctx, "file:%p, kinfo:%p, cinfo:%p", file, ki, ci); |
854 | 0 | blob_size = 2; |
855 | 0 | blob = malloc(blob_size); |
856 | 0 | if (!blob) |
857 | 0 | LOG_TEST_RET(ctx, SC_ERROR_OUT_OF_MEMORY, "AWP set key info failed: blob allocation error"); |
858 | | |
859 | 0 | sc_log(ctx, "label:%s",ki->label.value); |
860 | |
|
861 | 0 | *blob = (ki->flags >> 8) & 0xFF; |
862 | 0 | *(blob + 1) = ki->flags & 0xFF; |
863 | 0 | if (ci && ci->label.len) |
864 | 0 | r = awp_update_blob(ctx, &blob, &blob_size, &ci->label, TLV_TYPE_LLV); |
865 | 0 | else if (ci && !ci->label.len) |
866 | 0 | r = awp_update_blob(ctx, &blob, &blob_size, &ci->cn, TLV_TYPE_LLV); |
867 | 0 | else |
868 | 0 | r = awp_update_blob(ctx, &blob, &blob_size, &ki->label, TLV_TYPE_LLV); |
869 | 0 | if (r) |
870 | 0 | goto done; |
871 | | |
872 | 0 | r = awp_update_blob(ctx, &blob, &blob_size, &ki->id, TLV_TYPE_LLV); |
873 | 0 | if (r) |
874 | 0 | goto done; |
875 | | |
876 | 0 | r = awp_update_blob(ctx, &blob, &blob_size, &x30_lv, TLV_TYPE_V); |
877 | 0 | if (r) |
878 | 0 | goto done; |
879 | | |
880 | 0 | if (ci) |
881 | 0 | r = awp_update_blob(ctx, &blob, &blob_size, &(ci->subject), TLV_TYPE_LLV); |
882 | 0 | else |
883 | 0 | r = awp_update_blob(ctx, &blob, &blob_size, &zero_lv, TLV_TYPE_LLV); |
884 | 0 | if (r) |
885 | 0 | goto done; |
886 | | |
887 | 0 | if ((ki->flags & ~COSM_GENERATED) != COSM_TAG_PUBKEY_RSA) { |
888 | 0 | r = awp_update_blob(ctx, &blob, &blob_size, &ki->modulus, TLV_TYPE_V); |
889 | 0 | if (r) |
890 | 0 | goto done; |
891 | | |
892 | 0 | r = awp_update_blob(ctx, &blob, &blob_size, &ki->exponent, TLV_TYPE_LV); |
893 | 0 | if (r) |
894 | 0 | goto done; |
895 | 0 | } |
896 | | |
897 | 0 | file->size = blob_size; |
898 | 0 | r = sc_pkcs15init_create_file(profile, p15card, file); |
899 | 0 | if (r == SC_ERROR_FILE_ALREADY_EXISTS) { |
900 | 0 | r = cosm_delete_file(p15card, profile, file); |
901 | 0 | if (!r) |
902 | 0 | r = sc_pkcs15init_create_file(profile, p15card, file); |
903 | 0 | } |
904 | |
|
905 | 0 | if (r<0) |
906 | 0 | goto done; |
907 | | |
908 | 0 | r = sc_pkcs15init_update_file(profile, p15card, file, blob, blob_size); |
909 | 0 | if (r < 0) |
910 | 0 | goto done; |
911 | | |
912 | 0 | r = 0; |
913 | 0 | done: |
914 | 0 | if (blob) |
915 | 0 | free(blob); |
916 | |
|
917 | 0 | LOG_FUNC_RETURN(ctx, r); |
918 | 0 | } |
919 | | |
920 | | |
921 | | static int |
922 | | awp_encode_cert_info(struct sc_pkcs15_card *p15card, struct sc_pkcs15_object *obj, |
923 | | struct awp_cert_info *ci) |
924 | 0 | { |
925 | 0 | struct sc_context *ctx = p15card->card->ctx; |
926 | 0 | struct sc_pkcs15_cert_info *cert_info; |
927 | 0 | struct sc_pkcs15_pubkey_rsa pubkey; |
928 | 0 | int r = 0; |
929 | 0 | unsigned char *buff = NULL, *ptr; |
930 | 0 | BIO *mem = NULL; |
931 | 0 | X509 *x = NULL; |
932 | |
|
933 | 0 | LOG_FUNC_CALLED(ctx); |
934 | |
|
935 | 0 | if (!obj || !ci) |
936 | 0 | LOG_TEST_RET(ctx, SC_ERROR_INVALID_ARGUMENTS, "AWP encode cert failed: invalid parameters"); |
937 | | |
938 | 0 | cert_info = (struct sc_pkcs15_cert_info *)obj->data; |
939 | |
|
940 | 0 | sc_log(ctx, |
941 | 0 | "Encode cert(%s,id:%s,der(%p,%"SC_FORMAT_LEN_SIZE_T"u))", |
942 | 0 | obj->label, sc_pkcs15_print_id(&cert_info->id), |
943 | 0 | obj->content.value, obj->content.len); |
944 | 0 | memset(&pubkey, 0, sizeof(pubkey)); |
945 | |
|
946 | 0 | ci->label.value = (unsigned char *)strdup(obj->label); |
947 | 0 | ci->label.len = strlen(obj->label); |
948 | |
|
949 | 0 | mem = BIO_new_mem_buf(obj->content.value, (int)obj->content.len); |
950 | 0 | if (!mem) { |
951 | 0 | sc_log_openssl(ctx); |
952 | 0 | LOG_TEST_RET(ctx, SC_ERROR_INVALID_DATA, "AWP encode cert failed: invalid data"); |
953 | 0 | } |
954 | | |
955 | 0 | x = d2i_X509_bio(mem, NULL); |
956 | 0 | if (!x) { |
957 | 0 | sc_log_openssl(ctx); |
958 | 0 | LOG_TEST_RET(ctx, SC_ERROR_INVALID_DATA, "AWP encode cert failed: x509 parse error"); |
959 | 0 | } |
960 | | |
961 | 0 | buff = OPENSSL_malloc(i2d_X509(x,NULL) + EVP_MAX_MD_SIZE); |
962 | 0 | if (!buff) |
963 | 0 | LOG_TEST_RET(ctx, SC_ERROR_OUT_OF_MEMORY, "AWP encode cert failed: memory allocation error"); |
964 | | |
965 | | /* |
966 | | * subject commonName. |
967 | | */ |
968 | 0 | ptr = awp_get_commonName(x); |
969 | 0 | if (!ptr) { |
970 | 0 | r = SC_ERROR_INTERNAL; |
971 | 0 | LOG_TEST_GOTO_ERR(ctx, r, "AWP encode cert failed: cannot get CommonName"); |
972 | 0 | } |
973 | 0 | ci->cn.value = ptr; |
974 | 0 | ci->cn.len = strlen((char *)ptr); |
975 | | |
976 | | /* |
977 | | * subject DN |
978 | | */ |
979 | 0 | ptr = buff; |
980 | 0 | r = i2d_X509_NAME(X509_get_subject_name(x),&ptr); |
981 | 0 | if (r<=0) { |
982 | 0 | sc_log_openssl(ctx); |
983 | 0 | r = SC_ERROR_INTERNAL; |
984 | 0 | LOG_TEST_GOTO_ERR(ctx, r, "AWP encode cert failed: cannot get SubjectName"); |
985 | 0 | } |
986 | | |
987 | 0 | ci->subject.value = malloc(r); |
988 | 0 | if (!ci->subject.value) { |
989 | 0 | r = SC_ERROR_OUT_OF_MEMORY; |
990 | 0 | LOG_TEST_GOTO_ERR(ctx, r, "AWP encode cert failed: subject allocation error"); |
991 | 0 | } |
992 | 0 | memcpy(ci->subject.value, buff, r); |
993 | 0 | ci->subject.len = r; |
994 | | |
995 | | /* |
996 | | * issuer DN |
997 | | */ |
998 | 0 | ptr = buff; |
999 | 0 | r = i2d_X509_NAME(X509_get_issuer_name(x),&ptr); |
1000 | 0 | if (r <= 0) { |
1001 | 0 | sc_log_openssl(ctx); |
1002 | 0 | r = SC_ERROR_INTERNAL; |
1003 | 0 | LOG_TEST_GOTO_ERR(ctx, r, "AWP encode cert failed: cannot get IssuerName"); |
1004 | 0 | } |
1005 | | |
1006 | 0 | ci->issuer.value = malloc(r); |
1007 | 0 | if (!ci->issuer.value) { |
1008 | 0 | r = SC_ERROR_OUT_OF_MEMORY; |
1009 | 0 | LOG_TEST_GOTO_ERR(ctx, r, "AWP encode cert failed: issuer allocation error"); |
1010 | 0 | } |
1011 | 0 | memcpy(ci->issuer.value, buff, r); |
1012 | 0 | ci->issuer.len = r; |
1013 | | |
1014 | | /* |
1015 | | * ID |
1016 | | */ |
1017 | 0 | ci->id.value = calloc(1, cert_info->id.len); |
1018 | 0 | if (!ci->id.value) { |
1019 | 0 | r = SC_ERROR_OUT_OF_MEMORY; |
1020 | 0 | LOG_TEST_GOTO_ERR(ctx, r, "AWP encode cert failed: ID allocation error"); |
1021 | 0 | } |
1022 | 0 | memcpy(ci->id.value, cert_info->id.value, cert_info->id.len); |
1023 | 0 | ci->id.len = cert_info->id.len; |
1024 | | |
1025 | | /* |
1026 | | * serial number |
1027 | | */ |
1028 | 0 | #if OPENSSL_VERSION_NUMBER >= 0x10100000L |
1029 | | |
1030 | | /* TODO the der encoding of a ANS1_INTEGER is a TLV, the original code only as using the |
1031 | | * i2c_ASN1_INTEGER which is not in OpenSSL 1.1 |
1032 | | * It was adding the tag V_ASN1_INTEGER and the one byte length back in in effect creating |
1033 | | * a DER encoded ASN1_INTEGER |
1034 | | * So we can simplify the code and make compatible with OpenSSL 1.1. This needs to be tested |
1035 | | */ |
1036 | 0 | ci->serial.len = 0; |
1037 | 0 | ci->serial.value = NULL; |
1038 | | /* get length */ |
1039 | 0 | ci->serial.len = i2d_ASN1_INTEGER(X509_get_serialNumber(x), NULL); |
1040 | 0 | if (ci->serial.len > 0) { |
1041 | 0 | if (!(ci->serial.value = malloc(ci->serial.len))) { |
1042 | 0 | ci->serial.len = 0; |
1043 | 0 | r = SC_ERROR_OUT_OF_MEMORY; |
1044 | 0 | goto err; |
1045 | 0 | } |
1046 | 0 | ci->serial.len = i2d_ASN1_INTEGER(X509_get_serialNumber(x), &ci->serial.value); |
1047 | 0 | } |
1048 | | /* if len == 0, and value == NULL, then the cert did not have a serial number.*/ |
1049 | 0 | sc_log(ctx, "cert. serial encoded length %zu", ci->serial.len); |
1050 | |
|
1051 | | #else |
1052 | | do { |
1053 | | int encoded_len; |
1054 | | unsigned char encoded[0x40], *encoded_ptr; |
1055 | | |
1056 | | encoded_ptr = encoded; |
1057 | | encoded_len = i2c_ASN1_INTEGER(X509_get_serialNumber(x), &encoded_ptr); |
1058 | | |
1059 | | if (!(ci->serial.value = malloc(encoded_len + 3))) { |
1060 | | r = SC_ERROR_OUT_OF_MEMORY; |
1061 | | goto err; |
1062 | | } |
1063 | | |
1064 | | memcpy(ci->serial.value + 2, encoded, encoded_len); |
1065 | | *(ci->serial.value + 0) = V_ASN1_INTEGER; |
1066 | | *(ci->serial.value + 1) = encoded_len; |
1067 | | ci->serial.len = encoded_len + 2; |
1068 | | |
1069 | | sc_log(ctx, "cert. serial encoded length %i", encoded_len); |
1070 | | } while (0); |
1071 | | #endif |
1072 | |
|
1073 | 0 | ci->x509 = X509_dup(x); |
1074 | 0 | err: |
1075 | 0 | ERR_print_errors_fp(stderr); |
1076 | 0 | ERR_clear_error(); |
1077 | 0 | if (pubkey.exponent.data) free(pubkey.exponent.data); |
1078 | 0 | if (pubkey.modulus.data) free(pubkey.modulus.data); |
1079 | 0 | if (x) X509_free(x); |
1080 | 0 | if (mem) BIO_free(mem); |
1081 | 0 | if (buff) OPENSSL_free(buff); |
1082 | |
|
1083 | 0 | LOG_FUNC_RETURN(ctx, r); |
1084 | 0 | } |
1085 | | |
1086 | | |
1087 | | static void |
1088 | | awp_free_cert_info(struct awp_cert_info *ci) |
1089 | 0 | { |
1090 | 0 | if (ci) { |
1091 | 0 | if (ci->cn.len && ci->cn.value) |
1092 | 0 | free(ci->cn.value); |
1093 | |
|
1094 | 0 | if (ci->id.len && ci->id.value) |
1095 | 0 | free(ci->id.value); |
1096 | |
|
1097 | 0 | if (ci->subject.len && ci->subject.value) |
1098 | 0 | free(ci->subject.value); |
1099 | |
|
1100 | 0 | if (ci->issuer.len && ci->issuer.value) |
1101 | 0 | free(ci->issuer.value); |
1102 | |
|
1103 | 0 | if (ci->x509) |
1104 | 0 | X509_free(ci->x509); |
1105 | |
|
1106 | 0 | memset(ci,0,sizeof(struct awp_cert_info)); |
1107 | 0 | } |
1108 | 0 | } |
1109 | | |
1110 | | |
1111 | | static int |
1112 | | awp_encode_data_info(struct sc_pkcs15_card *p15card, struct sc_pkcs15_object *obj, |
1113 | | struct awp_data_info *di) |
1114 | 0 | { |
1115 | 0 | struct sc_context *ctx = p15card->card->ctx; |
1116 | 0 | struct sc_pkcs15_data_info *data_info; |
1117 | 0 | int r = 0; |
1118 | 0 | unsigned char *buf = NULL; |
1119 | 0 | size_t buflen; |
1120 | |
|
1121 | 0 | LOG_FUNC_CALLED(ctx); |
1122 | |
|
1123 | 0 | if (!obj || !di) |
1124 | 0 | LOG_TEST_RET(ctx, SC_ERROR_INVALID_ARGUMENTS, "AWP encode data failed: invalid parameters"); |
1125 | | |
1126 | 0 | data_info = (struct sc_pkcs15_data_info *)obj->data; |
1127 | |
|
1128 | 0 | sc_log(ctx, |
1129 | 0 | "Encode data(%s,id:%s,der(%p,%"SC_FORMAT_LEN_SIZE_T"u))", |
1130 | 0 | obj->label, sc_pkcs15_print_id(&data_info->id), |
1131 | 0 | obj->content.value, obj->content.len); |
1132 | |
|
1133 | 0 | di->flags = 0x0000; |
1134 | |
|
1135 | 0 | di->label.value = (unsigned char *)strdup(obj->label); |
1136 | 0 | di->label.len = strlen(obj->label); |
1137 | |
|
1138 | 0 | di->app.len = strlen(data_info->app_label); |
1139 | 0 | if (di->app.len) { |
1140 | 0 | di->app.value = (unsigned char *)strdup(data_info->app_label); |
1141 | 0 | if (!di->app.value) |
1142 | 0 | LOG_FUNC_RETURN(ctx, SC_ERROR_OUT_OF_MEMORY); |
1143 | 0 | } |
1144 | | |
1145 | 0 | r = sc_asn1_encode_object_id(&buf, &buflen, &data_info->app_oid); |
1146 | 0 | LOG_TEST_RET(ctx, r, "AWP encode data failed: cannot encode OID"); |
1147 | | |
1148 | 0 | di->oid.len = buflen + 2; |
1149 | 0 | di->oid.value = malloc(di->oid.len); |
1150 | 0 | if (!di->oid.value) { |
1151 | 0 | free(buf); |
1152 | 0 | LOG_TEST_RET(ctx, SC_ERROR_OUT_OF_MEMORY, "AWP encode data failed: cannot allocate OID"); |
1153 | 0 | } |
1154 | | |
1155 | 0 | *(di->oid.value + 0) = 0x06; |
1156 | 0 | *(di->oid.value + 1) = buflen; |
1157 | 0 | memcpy(di->oid.value + 2, buf, buflen); |
1158 | |
|
1159 | 0 | free(buf); |
1160 | 0 | LOG_FUNC_RETURN(ctx, r); |
1161 | 0 | } |
1162 | | |
1163 | | |
1164 | | static void |
1165 | | awp_free_data_info(struct awp_data_info *di) |
1166 | 0 | { |
1167 | 0 | if (di->label.len && di->label.value) |
1168 | 0 | free(di->label.value); |
1169 | |
|
1170 | 0 | if (di->app.len && di->app.value) |
1171 | 0 | free(di->app.value); |
1172 | |
|
1173 | 0 | if (di->oid.len && di->oid.value) |
1174 | 0 | free(di->oid.value); |
1175 | |
|
1176 | 0 | memset(di, 0, sizeof(struct awp_data_info)); |
1177 | 0 | } |
1178 | | |
1179 | | |
1180 | | static int |
1181 | | awp_set_data_info (struct sc_pkcs15_card *p15card, struct sc_profile *profile, |
1182 | | struct sc_file *file, struct awp_data_info *di) |
1183 | 0 | { |
1184 | 0 | struct sc_context *ctx = p15card->card->ctx; |
1185 | 0 | int r = 0, blob_size; |
1186 | 0 | unsigned char *blob; |
1187 | |
|
1188 | 0 | LOG_FUNC_CALLED(ctx); |
1189 | 0 | sc_log(ctx, "Set 'DATA' info %p", di); |
1190 | 0 | blob_size = 2; |
1191 | 0 | if (!(blob = malloc(blob_size))) { |
1192 | 0 | r = SC_ERROR_OUT_OF_MEMORY; |
1193 | 0 | goto done; |
1194 | 0 | } |
1195 | 0 | *blob = (di->flags >> 8) & 0xFF; |
1196 | 0 | *(blob + 1) = di->flags & 0xFF; |
1197 | |
|
1198 | 0 | r = awp_update_blob(ctx, &blob, &blob_size, &di->label, TLV_TYPE_LLV); |
1199 | 0 | if (r) |
1200 | 0 | goto done; |
1201 | | |
1202 | 0 | r = awp_update_blob(ctx, &blob, &blob_size, &di->app, TLV_TYPE_LLV); |
1203 | 0 | if (r) |
1204 | 0 | goto done; |
1205 | | |
1206 | 0 | r = awp_update_blob(ctx, &blob, &blob_size, &di->oid, TLV_TYPE_LLV); |
1207 | 0 | if (r) |
1208 | 0 | goto done; |
1209 | | |
1210 | 0 | file->size = blob_size; |
1211 | 0 | r = sc_pkcs15init_create_file(profile, p15card, file); |
1212 | 0 | if (r) |
1213 | 0 | goto done; |
1214 | | |
1215 | 0 | r = sc_pkcs15init_update_file(profile, p15card, file, blob, blob_size); |
1216 | 0 | if (r < 0) |
1217 | 0 | goto done; |
1218 | | |
1219 | 0 | r = 0; |
1220 | 0 | done: |
1221 | 0 | if (blob) |
1222 | 0 | free(blob); |
1223 | |
|
1224 | 0 | LOG_FUNC_RETURN(ctx, r); |
1225 | 0 | } |
1226 | | |
1227 | | |
1228 | | static int |
1229 | | awp_get_lv(struct sc_context *ctx, unsigned char *buf, size_t buf_len, |
1230 | | size_t offs, int len_len, |
1231 | | struct awp_lv *out) |
1232 | 0 | { |
1233 | 0 | int len = 0, ii; |
1234 | |
|
1235 | 0 | if (buf_len - offs < 2) |
1236 | 0 | return 0; |
1237 | | |
1238 | 0 | if (len_len > 2) { |
1239 | 0 | len = len_len; |
1240 | 0 | len_len = 0; |
1241 | 0 | } |
1242 | 0 | else { |
1243 | 0 | for (len=0, ii=0; ii<len_len; ii++) |
1244 | 0 | len = len * 0x100 + *(buf + offs + ii); |
1245 | 0 | } |
1246 | |
|
1247 | 0 | if (len && out) { |
1248 | 0 | if (out->value) |
1249 | 0 | free(out->value); |
1250 | |
|
1251 | 0 | out->value = malloc(len); |
1252 | 0 | if (!out->value) |
1253 | 0 | return SC_ERROR_OUT_OF_MEMORY; |
1254 | 0 | memcpy(out->value, buf + offs + len_len, len); |
1255 | 0 | out->len = len; |
1256 | 0 | } |
1257 | | |
1258 | 0 | return len_len + len; |
1259 | 0 | } |
1260 | | |
1261 | | |
1262 | | static int |
1263 | | awp_parse_key_info(struct sc_context *ctx, unsigned char *buf, size_t buf_len, |
1264 | | struct awp_key_info *ikey) |
1265 | 0 | { |
1266 | 0 | size_t offs; |
1267 | 0 | int len; |
1268 | |
|
1269 | 0 | LOG_FUNC_CALLED(ctx); |
1270 | 0 | offs = 0; |
1271 | | |
1272 | | /* Flags */ |
1273 | 0 | if (buf_len - offs < 2) |
1274 | 0 | LOG_FUNC_RETURN(ctx, SC_SUCCESS); |
1275 | 0 | ikey->flags = *(buf + offs) * 0x100 + *(buf + offs + 1); |
1276 | 0 | offs += 2; |
1277 | | |
1278 | | /* Label */ |
1279 | 0 | len = awp_get_lv(ctx, buf, buf_len, offs, 2, &ikey->label); |
1280 | 0 | LOG_TEST_RET(ctx, len, "AWP parse key info failed: label"); |
1281 | 0 | if (!len) |
1282 | 0 | LOG_FUNC_RETURN(ctx, SC_SUCCESS); |
1283 | 0 | offs += len; |
1284 | | |
1285 | | /* Ignore Key ID */ |
1286 | 0 | len = awp_get_lv(ctx, buf, buf_len, offs, 2, &ikey->id); |
1287 | 0 | LOG_TEST_RET(ctx, len, "AWP parse key info failed: ID"); |
1288 | 0 | if (!len) |
1289 | 0 | LOG_FUNC_RETURN(ctx, SC_SUCCESS); |
1290 | 0 | offs += len; |
1291 | |
|
1292 | 0 | while (*(buf + offs) == '0') |
1293 | 0 | offs++; |
1294 | | |
1295 | | /* Subject */ |
1296 | 0 | len = awp_get_lv(ctx, buf, buf_len, offs, 2, &ikey->subject); |
1297 | 0 | LOG_TEST_RET(ctx, len, "AWP parse key info failed: subject"); |
1298 | 0 | if (!len) |
1299 | 0 | LOG_FUNC_RETURN(ctx, SC_SUCCESS); |
1300 | 0 | offs += len; |
1301 | | |
1302 | | /* Modulus */ |
1303 | 0 | if (buf_len - offs > 64 && buf_len - offs < 128) |
1304 | 0 | len = awp_get_lv(ctx, buf, buf_len, offs, 64, &ikey->modulus); |
1305 | 0 | else if (buf_len - offs > 128 && buf_len - offs < 256) |
1306 | 0 | len = awp_get_lv(ctx, buf, buf_len, offs, 128, &ikey->modulus); |
1307 | 0 | else |
1308 | 0 | len = awp_get_lv(ctx, buf, buf_len, offs, 256, &ikey->modulus); |
1309 | 0 | LOG_TEST_RET(ctx, len, "AWP parse key info failed: modulus"); |
1310 | 0 | if (!len) |
1311 | 0 | LOG_FUNC_RETURN(ctx, SC_SUCCESS); |
1312 | 0 | offs += len; |
1313 | | |
1314 | | /* Exponent */ |
1315 | 0 | len = awp_get_lv(ctx, buf, buf_len, offs, 1, &ikey->exponent); |
1316 | 0 | LOG_TEST_RET(ctx, len, "AWP parse key info failed: exponent"); |
1317 | 0 | if (!len) |
1318 | 0 | LOG_FUNC_RETURN(ctx, SC_SUCCESS); |
1319 | | |
1320 | 0 | LOG_FUNC_RETURN(ctx, SC_SUCCESS); |
1321 | 0 | } |
1322 | | |
1323 | | |
1324 | | static int |
1325 | | awp_update_key_info(struct sc_pkcs15_card *p15card, struct sc_profile *profile, |
1326 | | unsigned prvkey_id, struct awp_cert_info *ci) |
1327 | 0 | { |
1328 | 0 | struct sc_context *ctx = p15card->card->ctx; |
1329 | 0 | struct sc_file *key_file=NULL, *info_file=NULL, *file=NULL; |
1330 | 0 | struct awp_key_info ikey; |
1331 | 0 | int rv = 0; |
1332 | 0 | unsigned char *buf; |
1333 | 0 | size_t buf_len; |
1334 | |
|
1335 | 0 | LOG_FUNC_CALLED(ctx); |
1336 | |
|
1337 | 0 | rv = awp_new_file(p15card, profile, SC_PKCS15_TYPE_PRKEY_RSA, prvkey_id & 0xFF, &info_file, &key_file); |
1338 | 0 | LOG_TEST_RET(ctx, rv, "AWP update key info failed: instantiation error"); |
1339 | 0 | sc_log(ctx, "key id %X; info id%X", key_file->id, info_file->id); |
1340 | |
|
1341 | 0 | rv = sc_pkcs15init_authenticate(profile, p15card, info_file, SC_AC_OP_READ); |
1342 | 0 | if (rv) { |
1343 | 0 | sc_log(ctx, "AWP update key info failed: 'READ' authentication error"); |
1344 | 0 | goto done; |
1345 | 0 | } |
1346 | | |
1347 | 0 | rv = sc_select_file(p15card->card, &info_file->path, &file); |
1348 | 0 | if (rv) { |
1349 | 0 | sc_log(ctx, "AWP update key info failed: cannot select info file"); |
1350 | 0 | goto done; |
1351 | 0 | } |
1352 | | |
1353 | 0 | buf = calloc(1,file->size); |
1354 | 0 | if (!buf) |
1355 | 0 | LOG_TEST_RET(ctx, SC_ERROR_OUT_OF_MEMORY, "AWP update key info failed: allocation error"); |
1356 | | |
1357 | 0 | rv = sc_read_binary(p15card->card, 0, buf, file->size, 0); |
1358 | 0 | if (rv < 0) { |
1359 | 0 | sc_log(ctx, "AWP update key info failed: read info file error"); |
1360 | 0 | goto done; |
1361 | 0 | } |
1362 | 0 | buf_len = rv; |
1363 | |
|
1364 | 0 | memset(&ikey, 0, sizeof(ikey)); |
1365 | 0 | rv = awp_parse_key_info(ctx, buf, buf_len, &ikey); |
1366 | 0 | if (rv < 0) { |
1367 | 0 | sc_log(ctx, "AWP update key info failed: parse key info error"); |
1368 | 0 | goto done; |
1369 | 0 | } |
1370 | 0 | free(buf); |
1371 | |
|
1372 | 0 | rv = awp_set_key_info(p15card, profile, info_file, &ikey, ci); |
1373 | 0 | LOG_TEST_RET(ctx, rv, "AWP update key info failed: set key info error"); |
1374 | 0 | done: |
1375 | 0 | sc_file_free(file); |
1376 | 0 | sc_file_free(key_file); |
1377 | 0 | sc_file_free(info_file); |
1378 | |
|
1379 | 0 | LOG_FUNC_RETURN(ctx, rv); |
1380 | 0 | } |
1381 | | |
1382 | | |
1383 | | static int |
1384 | | awp_update_df_create_cert(struct sc_pkcs15_card *p15card, struct sc_profile *profile, |
1385 | | struct sc_pkcs15_object *obj) |
1386 | 0 | { |
1387 | 0 | struct sc_context *ctx = p15card->card->ctx; |
1388 | 0 | struct sc_file *info_file=NULL, *obj_file=NULL; |
1389 | 0 | struct awp_cert_info icert; |
1390 | 0 | struct sc_pkcs15_der der; |
1391 | 0 | struct sc_path path; |
1392 | 0 | unsigned prvkey_id, obj_id; |
1393 | 0 | int rv; |
1394 | |
|
1395 | 0 | LOG_FUNC_CALLED(ctx); |
1396 | |
|
1397 | 0 | der = obj->content; |
1398 | 0 | path = ((struct sc_pkcs15_cert_info *)obj->data)->path; |
1399 | 0 | obj_id = (path.value[path.len-1] & 0xFF) + (path.value[path.len-2] & 0xFF) * 0x100; |
1400 | |
|
1401 | 0 | rv = awp_new_file(p15card, profile, SC_PKCS15_TYPE_CERT_X509, obj_id & 0xFF, &info_file, &obj_file); |
1402 | 0 | LOG_TEST_RET(ctx, rv, "COSM new file error"); |
1403 | | |
1404 | 0 | memset(&icert, 0, sizeof(icert)); |
1405 | 0 | sc_log(ctx, |
1406 | 0 | "Cert Der(%p,%"SC_FORMAT_LEN_SIZE_T"u)", der.value, der.len); |
1407 | 0 | rv = awp_encode_cert_info(p15card, obj, &icert); |
1408 | 0 | SC_TEST_GOTO_ERR(ctx, SC_LOG_DEBUG_VERBOSE, rv, "'Create Cert' update DF failed: cannot encode info"); |
1409 | | |
1410 | 0 | rv = awp_set_certificate_info(p15card, profile, info_file, &icert); |
1411 | 0 | SC_TEST_GOTO_ERR(ctx, SC_LOG_DEBUG_VERBOSE, rv, "'Create Cert' update DF failed: cannot set info"); |
1412 | | |
1413 | 0 | rv = awp_update_object_list(p15card, profile, SC_PKCS15_TYPE_CERT_X509, obj_id & 0xFF); |
1414 | 0 | SC_TEST_GOTO_ERR(ctx, SC_LOG_DEBUG_VERBOSE, rv, "'Create Cert' update DF failed: cannot update list"); |
1415 | | |
1416 | 0 | rv = awp_update_container(p15card, profile, SC_PKCS15_TYPE_CERT_X509, &icert.id, obj_id, &prvkey_id); |
1417 | 0 | SC_TEST_GOTO_ERR(ctx, SC_LOG_DEBUG_VERBOSE, rv, "'Create Cert' update DF failed: cannot update container"); |
1418 | | |
1419 | 0 | sc_log(ctx, "PrvKeyID:%04X", prvkey_id); |
1420 | |
|
1421 | 0 | if (prvkey_id) |
1422 | 0 | rv = awp_update_key_info(p15card, profile, prvkey_id, &icert); |
1423 | 0 | SC_TEST_GOTO_ERR(ctx, SC_LOG_DEBUG_VERBOSE, rv, "'Create Cert' update DF failed: cannot update key info"); |
1424 | | |
1425 | 0 | awp_free_cert_info(&icert); |
1426 | |
|
1427 | 0 | err: |
1428 | 0 | sc_file_free(info_file); |
1429 | 0 | sc_file_free(obj_file); |
1430 | |
|
1431 | 0 | LOG_FUNC_RETURN(ctx, rv); |
1432 | 0 | } |
1433 | | |
1434 | | |
1435 | | static int |
1436 | | awp_update_df_create_prvkey(struct sc_pkcs15_card *p15card, struct sc_profile *profile, |
1437 | | struct sc_pkcs15_object *key_obj) |
1438 | 0 | { |
1439 | 0 | struct sc_context *ctx = p15card->card->ctx; |
1440 | 0 | struct sc_pkcs15_pubkey pubkey; |
1441 | 0 | struct sc_pkcs15_der der; |
1442 | 0 | struct awp_key_info ikey; |
1443 | 0 | struct awp_cert_info icert; |
1444 | 0 | struct sc_file *info_file=NULL; |
1445 | 0 | struct sc_pkcs15_prkey_info *key_info; |
1446 | 0 | struct sc_pkcs15_object *cert_obj = NULL, *pubkey_obj = NULL; |
1447 | 0 | struct sc_path path; |
1448 | 0 | struct awp_crypto_container cc; |
1449 | 0 | struct sc_pkcs15_cert *p15cert = NULL; |
1450 | 0 | int rv; |
1451 | |
|
1452 | 0 | LOG_FUNC_CALLED(ctx); |
1453 | |
|
1454 | 0 | memset(&ikey, 0, sizeof(ikey)); |
1455 | 0 | memset(&icert, 0, sizeof(icert)); |
1456 | |
|
1457 | 0 | key_info = (struct sc_pkcs15_prkey_info *)key_obj->data; |
1458 | 0 | der = key_obj->content; |
1459 | |
|
1460 | 0 | memset(&cc, 0, sizeof(cc)); |
1461 | 0 | path = key_info->path; |
1462 | 0 | cc.prkey_id = (path.value[path.len-1] & 0xFF) + (path.value[path.len-2] & 0xFF) * 0x100; |
1463 | |
|
1464 | 0 | rv = sc_pkcs15_find_cert_by_id(p15card, &key_info->id, &cert_obj); |
1465 | 0 | if (!rv) { |
1466 | 0 | struct sc_pkcs15_cert_info *cert_info = (struct sc_pkcs15_cert_info *) cert_obj->data; |
1467 | 0 | int private_obj = cert_obj->flags & SC_PKCS15_CO_FLAG_PRIVATE; |
1468 | |
|
1469 | 0 | path = cert_info->path; |
1470 | 0 | cc.cert_id = (path.value[path.len-1] & 0xFF) + (path.value[path.len-2] & 0xFF) * 0x100; |
1471 | |
|
1472 | 0 | rv = sc_pkcs15_read_certificate(p15card, cert_info, private_obj, &p15cert); |
1473 | 0 | SC_TEST_GOTO_ERR(ctx, SC_LOG_DEBUG_VERBOSE, rv, "AWP 'update private key' DF failed: cannot get certificate"); |
1474 | | |
1475 | 0 | rv = sc_pkcs15_allocate_object_content(ctx, cert_obj, p15cert->data.value, p15cert->data.len); |
1476 | 0 | SC_TEST_GOTO_ERR(ctx, SC_LOG_DEBUG_VERBOSE, rv, "AWP 'update private key' DF failed: cannot allocate content"); |
1477 | | |
1478 | 0 | rv = awp_encode_cert_info(p15card, cert_obj, &icert); |
1479 | 0 | SC_TEST_GOTO_ERR(ctx, SC_LOG_DEBUG_VERBOSE, rv, "AWP 'update private key' DF failed: cannot encode cert info"); |
1480 | | |
1481 | 0 | sc_pkcs15_free_certificate(p15cert); |
1482 | 0 | p15cert = NULL; |
1483 | 0 | } |
1484 | | |
1485 | 0 | rv = sc_pkcs15_find_pubkey_by_id(p15card, &key_info->id, &pubkey_obj); |
1486 | 0 | if (!rv) { |
1487 | 0 | path = ((struct sc_pkcs15_cert_info *)pubkey_obj->data)->path; |
1488 | 0 | cc.pubkey_id = (path.value[path.len-1] & 0xFF) + (path.value[path.len-2] & 0xFF) * 0x100; |
1489 | 0 | } |
1490 | |
|
1491 | 0 | rv = awp_new_file(p15card, profile, key_obj->type, cc.prkey_id & 0xFF, &info_file, NULL); |
1492 | 0 | SC_TEST_GOTO_ERR(ctx, SC_LOG_DEBUG_VERBOSE, rv, "New private key info file error"); |
1493 | | |
1494 | 0 | pubkey.algorithm = SC_ALGORITHM_RSA; |
1495 | 0 | sc_log(ctx, |
1496 | 0 | "PrKey Der(%p,%"SC_FORMAT_LEN_SIZE_T"u)", der.value, der.len); |
1497 | 0 | rv = sc_pkcs15_decode_pubkey(ctx, &pubkey, der.value, der.len); |
1498 | 0 | SC_TEST_GOTO_ERR(ctx, SC_LOG_DEBUG_VERBOSE, rv, "AWP 'update private key' DF failed: decode public key error"); |
1499 | | |
1500 | 0 | rv = awp_encode_key_info(p15card, key_obj, &pubkey.u.rsa, &ikey); |
1501 | 0 | SC_TEST_GOTO_ERR(ctx, SC_LOG_DEBUG_VERBOSE, rv, "AWP 'update private key' DF failed: encode info error"); |
1502 | | |
1503 | 0 | rv = awp_set_key_info(p15card, profile, info_file, &ikey, cert_obj ? &icert : NULL); |
1504 | 0 | SC_TEST_GOTO_ERR(ctx, SC_LOG_DEBUG_VERBOSE, rv, "AWP 'update private key' DF failed: set info error"); |
1505 | | |
1506 | 0 | rv = awp_update_object_list(p15card, profile, key_obj->type, cc.prkey_id & 0xFF); |
1507 | 0 | SC_TEST_GOTO_ERR(ctx, SC_LOG_DEBUG_VERBOSE, rv, "AWP 'update private key' DF failed: update object list error"); |
1508 | | |
1509 | 0 | rv = awp_create_container(p15card, profile, key_obj->type, &ikey.id, &cc); |
1510 | 0 | SC_TEST_GOTO_ERR(ctx, SC_LOG_DEBUG_VERBOSE, rv, "AWP 'update private key' DF failed: update container error"); |
1511 | | |
1512 | 0 | err: |
1513 | 0 | if (p15cert) |
1514 | 0 | sc_pkcs15_free_certificate(p15cert); |
1515 | 0 | sc_file_free(info_file); |
1516 | 0 | if (cert_obj) |
1517 | 0 | awp_free_cert_info(&icert); |
1518 | 0 | awp_free_key_info(&ikey); |
1519 | |
|
1520 | 0 | LOG_FUNC_RETURN(ctx, rv); |
1521 | 0 | } |
1522 | | |
1523 | | |
1524 | | static int |
1525 | | awp_update_df_create_pubkey(struct sc_pkcs15_card *p15card, struct sc_profile *profile, |
1526 | | struct sc_pkcs15_object *obj) |
1527 | 0 | { |
1528 | 0 | struct sc_context *ctx = p15card->card->ctx; |
1529 | 0 | struct sc_pkcs15_pubkey pubkey; |
1530 | 0 | struct sc_pkcs15_der der; |
1531 | 0 | struct awp_key_info ikey; |
1532 | 0 | struct sc_file *info_file=NULL; |
1533 | 0 | struct sc_path path; |
1534 | 0 | unsigned obj_id; |
1535 | 0 | int index, rv; |
1536 | |
|
1537 | 0 | LOG_FUNC_CALLED(ctx); |
1538 | |
|
1539 | 0 | path = ((struct sc_pkcs15_pubkey_info *)obj->data)->path; |
1540 | 0 | der = obj->content; |
1541 | 0 | index = path.value[path.len-1] & 0xFF; |
1542 | 0 | obj_id = (path.value[path.len-1] & 0xFF) + (path.value[path.len-2] & 0xFF) * 0x100; |
1543 | |
|
1544 | 0 | memset(&ikey, 0, sizeof(ikey)); |
1545 | |
|
1546 | 0 | rv = awp_new_file(p15card, profile, obj->type, index, &info_file, NULL); |
1547 | 0 | SC_TEST_GOTO_ERR(ctx, SC_LOG_DEBUG_VERBOSE, rv, "New public key info file error"); |
1548 | | |
1549 | 0 | pubkey.algorithm = SC_ALGORITHM_RSA; |
1550 | 0 | sc_log(ctx, |
1551 | 0 | "PrKey Der(%p,%"SC_FORMAT_LEN_SIZE_T"u)", der.value, der.len); |
1552 | 0 | rv = sc_pkcs15_decode_pubkey(ctx, &pubkey, der.value, der.len); |
1553 | 0 | SC_TEST_GOTO_ERR(ctx, SC_LOG_DEBUG_VERBOSE, rv, "AWP 'update public key' DF failed: decode public key error"); |
1554 | | |
1555 | 0 | rv = awp_encode_key_info(p15card, obj, &pubkey.u.rsa, &ikey); |
1556 | 0 | SC_TEST_GOTO_ERR(ctx, SC_LOG_DEBUG_VERBOSE, rv, "AWP 'update public key' DF failed: encode info error"); |
1557 | | |
1558 | 0 | rv = awp_set_key_info(p15card, profile, info_file, &ikey, NULL); |
1559 | 0 | SC_TEST_GOTO_ERR(ctx, SC_LOG_DEBUG_VERBOSE, rv, "AWP 'update public key' DF failed: set info error"); |
1560 | | |
1561 | 0 | rv = awp_update_object_list(p15card, profile, obj->type, index); |
1562 | 0 | SC_TEST_GOTO_ERR(ctx, SC_LOG_DEBUG_VERBOSE, rv, "AWP 'update public key' DF failed: update object list error"); |
1563 | | |
1564 | 0 | rv = awp_update_container(p15card, profile, obj->type, &ikey.id, obj_id, NULL); |
1565 | 0 | SC_TEST_GOTO_ERR(ctx, SC_LOG_DEBUG_VERBOSE, rv, "AWP 'update public key' DF failed: update container error"); |
1566 | | |
1567 | 0 | err: |
1568 | 0 | awp_free_key_info(&ikey); |
1569 | 0 | sc_file_free(info_file); |
1570 | 0 | LOG_FUNC_RETURN(ctx, rv); |
1571 | 0 | } |
1572 | | |
1573 | | |
1574 | | static int |
1575 | | awp_update_df_create_data(struct sc_pkcs15_card *p15card, struct sc_profile *profile, |
1576 | | struct sc_pkcs15_object *obj) |
1577 | 0 | { |
1578 | 0 | struct sc_context *ctx = p15card->card->ctx; |
1579 | 0 | struct sc_file *info_file=NULL, *obj_file=NULL; |
1580 | 0 | struct awp_data_info idata; |
1581 | 0 | struct sc_path path; |
1582 | 0 | unsigned obj_id, obj_type = obj->auth_id.len ? COSM_TYPE_PRIVDATA_OBJECT : SC_PKCS15_TYPE_DATA_OBJECT; |
1583 | 0 | int rv; |
1584 | |
|
1585 | 0 | LOG_FUNC_CALLED(ctx); |
1586 | 0 | memset(&idata, 0, sizeof(idata)); |
1587 | |
|
1588 | 0 | path = ((struct sc_pkcs15_data_info *)obj->data)->path; |
1589 | 0 | obj_id = (path.value[path.len-1] & 0xFF) + (path.value[path.len-2] & 0xFF) * 0x100; |
1590 | |
|
1591 | 0 | rv = awp_new_file(p15card, profile, obj_type, obj_id & 0xFF, &info_file, &obj_file); |
1592 | 0 | LOG_TEST_GOTO_ERR(ctx, rv, "COSM new file error"); |
1593 | | |
1594 | 0 | rv = awp_encode_data_info(p15card, obj, &idata); |
1595 | 0 | LOG_TEST_GOTO_ERR(ctx, rv, "'Create Data' update DF failed: cannot encode info"); |
1596 | | |
1597 | 0 | rv = awp_set_data_info(p15card, profile, info_file, &idata); |
1598 | 0 | LOG_TEST_GOTO_ERR(ctx, rv, "'Create Data' update DF failed: cannot set info"); |
1599 | | |
1600 | 0 | rv = awp_update_object_list(p15card, profile, obj_type, obj_id & 0xFF); |
1601 | 0 | LOG_TEST_GOTO_ERR(ctx, rv, "'Create Data' update DF failed: cannot update list"); |
1602 | | |
1603 | 0 | err: |
1604 | 0 | awp_free_data_info(&idata); |
1605 | 0 | sc_file_free(info_file); |
1606 | 0 | sc_file_free(obj_file); |
1607 | |
|
1608 | 0 | LOG_FUNC_RETURN(ctx, rv); |
1609 | 0 | } |
1610 | | |
1611 | | |
1612 | | int |
1613 | | awp_update_df_create(struct sc_pkcs15_card *p15card, struct sc_profile *profile, |
1614 | | struct sc_pkcs15_object *object) |
1615 | 0 | { |
1616 | 0 | struct sc_context *ctx = p15card->card->ctx; |
1617 | 0 | int rv = SC_ERROR_INTERNAL; |
1618 | |
|
1619 | 0 | LOG_FUNC_CALLED(ctx); |
1620 | 0 | if (!object) |
1621 | 0 | LOG_FUNC_RETURN(ctx, SC_SUCCESS); |
1622 | | |
1623 | 0 | switch (object->type) { |
1624 | 0 | case SC_PKCS15_TYPE_AUTH_PIN: |
1625 | 0 | rv = awp_update_df_create_pin(p15card, profile, object); |
1626 | 0 | break; |
1627 | 0 | case SC_PKCS15_TYPE_CERT_X509: |
1628 | 0 | rv = awp_update_df_create_cert(p15card, profile, object); |
1629 | 0 | break; |
1630 | 0 | case SC_PKCS15_TYPE_PRKEY_RSA: |
1631 | 0 | rv = awp_update_df_create_prvkey(p15card, profile, object); |
1632 | 0 | break; |
1633 | 0 | case SC_PKCS15_TYPE_PUBKEY_RSA: |
1634 | 0 | rv = awp_update_df_create_pubkey(p15card, profile, object); |
1635 | 0 | break; |
1636 | 0 | case SC_PKCS15_TYPE_DATA_OBJECT: |
1637 | 0 | rv = awp_update_df_create_data(p15card, profile, object); |
1638 | 0 | break; |
1639 | 0 | default: |
1640 | 0 | LOG_TEST_RET(ctx, SC_ERROR_INVALID_ARGUMENTS, "'Create' update DF failed: unsupported object type"); |
1641 | 0 | } |
1642 | | |
1643 | 0 | LOG_FUNC_RETURN(ctx, rv); |
1644 | 0 | } |
1645 | | |
1646 | | |
1647 | | static int |
1648 | | awp_delete_from_container(struct sc_pkcs15_card *p15card, |
1649 | | struct sc_profile *profile, int type, int file_id) |
1650 | 0 | { |
1651 | 0 | struct sc_context *ctx = p15card->card->ctx; |
1652 | 0 | struct sc_file *clist=NULL, *file=NULL; |
1653 | 0 | unsigned rec, rec_len; |
1654 | 0 | int rv = 0, ii; |
1655 | 0 | unsigned char *buff=NULL; |
1656 | |
|
1657 | 0 | LOG_FUNC_CALLED(ctx); |
1658 | 0 | sc_log(ctx, "update container entry (type:%X,file-id:%X)", type, file_id); |
1659 | |
|
1660 | 0 | rv = awp_new_file(p15card, profile, COSM_CONTAINER_LIST, 0, &clist, NULL); |
1661 | 0 | LOG_TEST_RET(ctx, rv, "AWP update container entry: cannot get allocate AWP file"); |
1662 | | |
1663 | 0 | rv = sc_select_file(p15card->card, &clist->path, &file); |
1664 | 0 | LOG_TEST_RET(ctx, rv, "AWP update container entry: cannot select container list file"); |
1665 | | |
1666 | 0 | buff = malloc(file->record_length); |
1667 | 0 | if (!buff) |
1668 | 0 | LOG_TEST_RET(ctx, SC_ERROR_OUT_OF_MEMORY, "AWP update container entry: allocation error"); |
1669 | | |
1670 | 0 | for (rec = 1; rec <= (unsigned)file->record_count; rec++) { |
1671 | 0 | rv = sc_read_record(p15card->card, rec, 0, buff, file->record_length, SC_RECORD_BY_REC_NR); |
1672 | 0 | if (rv < 0) { |
1673 | 0 | sc_log(ctx, "AWP update container entry: read record error %i", rv); |
1674 | 0 | break; |
1675 | 0 | } |
1676 | 0 | rec_len = rv; |
1677 | |
|
1678 | 0 | for (ii=0; ii<12; ii+=2) |
1679 | 0 | if (file_id == (*(buff+ii) * 0x100 + *(buff+ii+1))) |
1680 | 0 | break; |
1681 | 0 | if (ii==12) |
1682 | 0 | continue; |
1683 | | |
1684 | 0 | if (type == SC_PKCS15_TYPE_PRKEY_RSA || type == COSM_TYPE_PRKEY_RSA) |
1685 | 0 | memset(buff + ii/6*6, 0, 6); |
1686 | 0 | else |
1687 | 0 | memset(buff + ii, 0, 2); |
1688 | |
|
1689 | 0 | if (!memcmp(buff,"\0\0\0\0\0\0\0\0\0\0\0\0",12)) { |
1690 | 0 | rv = sc_pkcs15init_authenticate(profile, p15card, file, SC_AC_OP_ERASE); |
1691 | 0 | if (rv < 0) { |
1692 | 0 | sc_log(ctx, "AWP update container entry: 'erase' authentication error %i", rv); |
1693 | 0 | break; |
1694 | 0 | } |
1695 | | |
1696 | 0 | rv = sc_delete_record(p15card->card, rec); |
1697 | 0 | if (rv < 0) { |
1698 | 0 | sc_log(ctx, "AWP update container entry: delete record error %i", rv); |
1699 | 0 | break; |
1700 | 0 | } |
1701 | 0 | } |
1702 | 0 | else { |
1703 | 0 | rv = sc_pkcs15init_authenticate(profile, p15card, file, SC_AC_OP_UPDATE); |
1704 | 0 | if (rv < 0) { |
1705 | 0 | sc_log(ctx, "AWP update container entry: 'update' authentication error %i", rv); |
1706 | 0 | break; |
1707 | 0 | } |
1708 | | |
1709 | 0 | rv = sc_update_record(p15card->card, rec, 0, buff, rec_len, SC_RECORD_BY_REC_NR); |
1710 | 0 | if (rv < 0) { |
1711 | 0 | sc_log(ctx, "AWP update container entry: update record error %i", rv); |
1712 | 0 | break; |
1713 | 0 | } |
1714 | 0 | } |
1715 | 0 | } |
1716 | |
|
1717 | 0 | if (rv > 0) |
1718 | 0 | rv = 0; |
1719 | |
|
1720 | 0 | free(buff); |
1721 | 0 | sc_file_free(clist); |
1722 | 0 | sc_file_free(file); |
1723 | |
|
1724 | 0 | LOG_FUNC_RETURN(ctx, rv); |
1725 | 0 | } |
1726 | | |
1727 | | |
1728 | | static int |
1729 | | awp_remove_from_object_list( struct sc_pkcs15_card *p15card, struct sc_profile *profile, |
1730 | | int type, unsigned int obj_id) |
1731 | 0 | { |
1732 | 0 | struct sc_context *ctx = p15card->card->ctx; |
1733 | 0 | struct sc_file *lst_file=NULL, *lst=NULL; |
1734 | 0 | int rv = 0; |
1735 | 0 | unsigned ii; |
1736 | 0 | char lst_name[NAME_MAX_LEN]; |
1737 | 0 | unsigned char *buff=NULL; |
1738 | 0 | unsigned char id[2]; |
1739 | |
|
1740 | 0 | LOG_FUNC_CALLED(ctx); |
1741 | 0 | sc_log(ctx, "type %X; obj_id %X",type, obj_id); |
1742 | |
|
1743 | 0 | switch (type) { |
1744 | 0 | case SC_PKCS15_TYPE_PRKEY_RSA: |
1745 | 0 | case COSM_TYPE_PRKEY_RSA: |
1746 | 0 | snprintf(lst_name, NAME_MAX_LEN,"%s-private-list", COSM_TITLE); |
1747 | 0 | break; |
1748 | 0 | case SC_PKCS15_TYPE_PUBKEY_RSA: |
1749 | 0 | case SC_PKCS15_TYPE_CERT_X509: |
1750 | 0 | case SC_PKCS15_TYPE_DATA_OBJECT: |
1751 | 0 | case COSM_TYPE_PUBKEY_RSA: |
1752 | 0 | snprintf(lst_name, NAME_MAX_LEN,"%s-public-list", COSM_TITLE); |
1753 | 0 | break; |
1754 | 0 | default: |
1755 | 0 | LOG_TEST_RET(ctx, SC_ERROR_INCORRECT_PARAMETERS, "AWP update object list: invalid type"); |
1756 | 0 | } |
1757 | | |
1758 | 0 | sc_log(ctx, "AWP update object list: select '%s' file", lst_name); |
1759 | 0 | rv = sc_profile_get_file(profile, lst_name, &lst_file); |
1760 | 0 | LOG_TEST_RET(ctx, rv, "AWP update object list: cannot instantiate list file"); |
1761 | | |
1762 | 0 | rv = sc_select_file(p15card->card, &lst_file->path, &lst); |
1763 | 0 | LOG_TEST_RET(ctx, rv, "AWP update object list: cannot select list file"); |
1764 | | |
1765 | 0 | rv = sc_pkcs15init_authenticate(profile, p15card, lst, SC_AC_OP_READ); |
1766 | 0 | LOG_TEST_RET(ctx, rv, "AWP update object list: 'read' authentication failed"); |
1767 | | |
1768 | 0 | buff = malloc(lst->size); |
1769 | 0 | if (!buff) |
1770 | 0 | LOG_TEST_RET(ctx, SC_ERROR_OUT_OF_MEMORY, "AWP update object list: allocation error"); |
1771 | | |
1772 | 0 | rv = sc_read_binary(p15card->card, 0, buff, lst->size, 0); |
1773 | 0 | if (rv != (int)lst->size) |
1774 | 0 | goto done; |
1775 | | |
1776 | 0 | id[0] = (obj_id >> 8) & 0xFF; |
1777 | 0 | id[1] = obj_id & 0xFF; |
1778 | 0 | for (ii=0; ii<lst->size; ii+=5) { |
1779 | 0 | if (*(buff+ii)==0xFF && *(buff+ii+1)==id[0] && *(buff+ii+2)==id[1]) { |
1780 | 0 | rv = sc_pkcs15init_authenticate(profile, p15card, lst, SC_AC_OP_UPDATE); |
1781 | 0 | if (rv) |
1782 | 0 | goto done; |
1783 | | |
1784 | 0 | rv = sc_update_binary(p15card->card, ii, (unsigned char *)"\0", 1, 0); |
1785 | 0 | if (rv && rv!=1) |
1786 | 0 | rv = SC_ERROR_INVALID_CARD; |
1787 | 0 | break; |
1788 | 0 | } |
1789 | 0 | } |
1790 | | |
1791 | 0 | if (rv > 0) |
1792 | 0 | rv = 0; |
1793 | 0 | done: |
1794 | 0 | if (buff) |
1795 | 0 | free(buff); |
1796 | 0 | sc_file_free(lst); |
1797 | 0 | sc_file_free(lst_file); |
1798 | |
|
1799 | 0 | LOG_FUNC_RETURN(ctx, rv); |
1800 | 0 | } |
1801 | | |
1802 | | |
1803 | | static int |
1804 | | awp_update_df_delete_cert(struct sc_pkcs15_card *p15card, struct sc_profile *profile, |
1805 | | struct sc_pkcs15_object *obj) |
1806 | 0 | { |
1807 | 0 | struct sc_context *ctx = p15card->card->ctx; |
1808 | 0 | struct sc_file *info_file = NULL; |
1809 | 0 | struct sc_path path; |
1810 | 0 | int rv = SC_ERROR_NOT_SUPPORTED; |
1811 | 0 | unsigned file_id; |
1812 | |
|
1813 | 0 | LOG_FUNC_CALLED(ctx); |
1814 | |
|
1815 | 0 | path = ((struct sc_pkcs15_cert_info *) obj->data)->path; |
1816 | 0 | file_id = path.value[path.len-2] * 0x100 + path.value[path.len-1]; |
1817 | 0 | sc_log(ctx, "file-id:%X", file_id); |
1818 | |
|
1819 | 0 | rv = awp_new_file(p15card, profile, obj->type, file_id & 0xFF, &info_file, NULL); |
1820 | 0 | LOG_TEST_RET(ctx, rv, "AWP 'delete cert' update DF failed: cannot get allocate new AWP file"); |
1821 | 0 | sc_log(ctx, "info file-id:%X", info_file->id); |
1822 | |
|
1823 | 0 | rv = cosm_delete_file(p15card, profile, info_file); |
1824 | 0 | if (rv != SC_ERROR_FILE_NOT_FOUND) |
1825 | 0 | LOG_TEST_RET(ctx, rv, "AWP 'delete cert' update DF failed: delete info file error"); |
1826 | | |
1827 | 0 | rv = awp_delete_from_container(p15card, profile, obj->type, file_id); |
1828 | 0 | LOG_TEST_RET(ctx, rv, "AWP 'delete cert' update DF failed: cannot update container"); |
1829 | | |
1830 | 0 | rv = awp_remove_from_object_list(p15card, profile, obj->type, file_id); |
1831 | 0 | LOG_TEST_RET(ctx, rv, "AWP 'delete cert' update DF failed: cannot remove object"); |
1832 | | |
1833 | 0 | LOG_FUNC_RETURN(ctx, rv); |
1834 | 0 | } |
1835 | | |
1836 | | |
1837 | | static int |
1838 | | awp_update_df_delete_prvkey(struct sc_pkcs15_card *p15card, struct sc_profile *profile, |
1839 | | struct sc_pkcs15_object *obj) |
1840 | 0 | { |
1841 | 0 | struct sc_context *ctx = p15card->card->ctx; |
1842 | 0 | struct sc_file *info_file = NULL; |
1843 | 0 | struct sc_path path; |
1844 | 0 | int rv = SC_ERROR_NOT_SUPPORTED; |
1845 | 0 | unsigned file_id; |
1846 | |
|
1847 | 0 | LOG_FUNC_CALLED(ctx); |
1848 | |
|
1849 | 0 | path = ((struct sc_pkcs15_prkey_info *) obj->data)->path; |
1850 | 0 | file_id = path.value[path.len-2] * 0x100 + path.value[path.len-1]; |
1851 | 0 | sc_log(ctx, "file-id:%X", file_id); |
1852 | |
|
1853 | 0 | rv = awp_new_file(p15card, profile, obj->type, file_id & 0xFF, &info_file, NULL); |
1854 | 0 | LOG_TEST_RET(ctx, rv, "AWP 'delete prkey' update DF failed: cannot get allocate new AWP file"); |
1855 | 0 | sc_log(ctx, "info file-id:%X", info_file->id); |
1856 | |
|
1857 | 0 | rv = cosm_delete_file(p15card, profile, info_file); |
1858 | 0 | if (rv != SC_ERROR_FILE_NOT_FOUND) |
1859 | 0 | LOG_TEST_RET(ctx, rv, "AWP 'delete prkey' update DF failed: delete info file error"); |
1860 | | |
1861 | 0 | rv = awp_delete_from_container(p15card, profile, obj->type, file_id); |
1862 | 0 | LOG_TEST_RET(ctx, rv, "AWP 'delete prkey' update DF failed: cannot update container"); |
1863 | | |
1864 | 0 | rv = awp_remove_from_object_list(p15card, profile, obj->type, file_id); |
1865 | 0 | LOG_TEST_RET(ctx, rv, "AWP 'delete prkey' update DF failed: cannot remove object"); |
1866 | | |
1867 | 0 | LOG_FUNC_RETURN(ctx, rv); |
1868 | 0 | } |
1869 | | |
1870 | | |
1871 | | static int |
1872 | | awp_update_df_delete_pubkey(struct sc_pkcs15_card *p15card, struct sc_profile *profile, |
1873 | | struct sc_pkcs15_object *obj) |
1874 | 0 | { |
1875 | 0 | struct sc_context *ctx = p15card->card->ctx; |
1876 | 0 | struct sc_file *info_file = NULL; |
1877 | 0 | struct sc_path path; |
1878 | 0 | int rv = SC_ERROR_NOT_SUPPORTED; |
1879 | 0 | unsigned file_id; |
1880 | |
|
1881 | 0 | LOG_FUNC_CALLED(ctx); |
1882 | |
|
1883 | 0 | path = ((struct sc_pkcs15_pubkey_info *) obj->data)->path; |
1884 | 0 | file_id = path.value[path.len-2] * 0x100 + path.value[path.len-1]; |
1885 | 0 | sc_log(ctx, "file-id:%X", file_id); |
1886 | |
|
1887 | 0 | rv = awp_new_file(p15card, profile, obj->type, file_id & 0xFF, &info_file, NULL); |
1888 | 0 | LOG_TEST_RET(ctx, rv, "AWP 'delete pubkey' update DF failed: cannot get allocate new AWP file"); |
1889 | 0 | sc_log(ctx, "info file-id:%X", info_file->id); |
1890 | |
|
1891 | 0 | rv = cosm_delete_file(p15card, profile, info_file); |
1892 | 0 | if (rv != SC_ERROR_FILE_NOT_FOUND) |
1893 | 0 | LOG_TEST_RET(ctx, rv, "AWP 'delete pubkey' update DF failed: delete info file error"); |
1894 | | |
1895 | 0 | rv = awp_delete_from_container(p15card, profile, obj->type, file_id); |
1896 | 0 | LOG_TEST_RET(ctx, rv, "AWP 'delete pubkey' update DF failed: cannot update container"); |
1897 | | |
1898 | 0 | rv = awp_remove_from_object_list(p15card, profile, obj->type, file_id); |
1899 | 0 | LOG_TEST_RET(ctx, rv, "AWP 'delete pubkey' update DF failed: cannot remove object"); |
1900 | | |
1901 | 0 | LOG_FUNC_RETURN(ctx, rv); |
1902 | 0 | } |
1903 | | |
1904 | | |
1905 | | static int |
1906 | | awp_update_df_delete_data(struct sc_pkcs15_card *p15card, struct sc_profile *profile, |
1907 | | struct sc_pkcs15_object *obj) |
1908 | 0 | { |
1909 | 0 | struct sc_context *ctx = p15card->card->ctx; |
1910 | 0 | struct sc_file *info_file = NULL; |
1911 | 0 | struct sc_path path; |
1912 | 0 | int rv = SC_ERROR_NOT_SUPPORTED; |
1913 | 0 | unsigned file_id; |
1914 | |
|
1915 | 0 | LOG_FUNC_CALLED(ctx); |
1916 | |
|
1917 | 0 | path = ((struct sc_pkcs15_data_info *) obj->data)->path; |
1918 | 0 | file_id = path.value[path.len-2] * 0x100 + path.value[path.len-1]; |
1919 | 0 | sc_log(ctx, "file-id:%X", file_id); |
1920 | |
|
1921 | 0 | rv = awp_new_file(p15card, profile, obj->type, file_id & 0xFF, &info_file, NULL); |
1922 | 0 | LOG_TEST_RET(ctx, rv, "AWP 'delete DATA' update DF failed: cannot get allocate new AWP file"); |
1923 | 0 | sc_log(ctx, "info file-id:%X", info_file->id); |
1924 | |
|
1925 | 0 | rv = cosm_delete_file(p15card, profile, info_file); |
1926 | 0 | if (rv != SC_ERROR_FILE_NOT_FOUND) |
1927 | 0 | LOG_TEST_RET(ctx, rv, "AWP 'delete DATA' update DF failed: delete info file error"); |
1928 | | |
1929 | 0 | rv = awp_remove_from_object_list(p15card, profile, obj->type, file_id); |
1930 | 0 | LOG_TEST_RET(ctx, rv, "AWP 'delete DATA' update DF failed: cannot remove object"); |
1931 | | |
1932 | 0 | LOG_FUNC_RETURN(ctx, rv); |
1933 | 0 | } |
1934 | | |
1935 | | |
1936 | | int |
1937 | | awp_update_df_delete(struct sc_pkcs15_card *p15card, struct sc_profile *profile, |
1938 | | struct sc_pkcs15_object *object) |
1939 | 0 | { |
1940 | 0 | struct sc_context *ctx = p15card->card->ctx; |
1941 | 0 | int rv = SC_ERROR_INTERNAL; |
1942 | |
|
1943 | 0 | LOG_FUNC_CALLED(ctx); |
1944 | 0 | if (!object) |
1945 | 0 | LOG_FUNC_RETURN(ctx, SC_SUCCESS); |
1946 | | |
1947 | 0 | switch (object->type) { |
1948 | 0 | case SC_PKCS15_TYPE_CERT_X509: |
1949 | 0 | rv = awp_update_df_delete_cert(p15card, profile, object); |
1950 | 0 | break; |
1951 | 0 | case SC_PKCS15_TYPE_PRKEY_RSA: |
1952 | 0 | rv = awp_update_df_delete_prvkey(p15card, profile, object); |
1953 | 0 | break; |
1954 | 0 | case SC_PKCS15_TYPE_PUBKEY_RSA: |
1955 | 0 | rv = awp_update_df_delete_pubkey(p15card, profile, object); |
1956 | 0 | break; |
1957 | 0 | case SC_PKCS15_TYPE_DATA_OBJECT: |
1958 | 0 | rv = awp_update_df_delete_data(p15card, profile, object); |
1959 | 0 | break; |
1960 | 0 | default: |
1961 | 0 | LOG_TEST_RET(ctx, SC_ERROR_INVALID_ARGUMENTS, "'Create' update DF failed: unsupported object type"); |
1962 | 0 | } |
1963 | | |
1964 | 0 | SC_FUNC_RETURN(ctx, 1, rv); |
1965 | 0 | } |
1966 | | |
1967 | | #endif /* #ifdef ENABLE_OPENSSL */ |