/src/opensc/src/pkcs15init/pkcs15-sc-hsm.c
Line | Count | Source (jump to first uncovered line) |
1 | | /* |
2 | | * pkcs15-sc-hsm.c : PKCS#15 emulation for write support |
3 | | * |
4 | | * Copyright (C) 2012 Andreas Schwier, CardContact, Minden, Germany |
5 | | * |
6 | | * This library is free software; you can redistribute it and/or |
7 | | * modify it under the terms of the GNU Lesser General Public |
8 | | * License as published by the Free Software Foundation; either |
9 | | * version 2.1 of the License, or (at your option) any later version. |
10 | | * |
11 | | * This library is distributed in the hope that it will be useful, |
12 | | * but WITHOUT ANY WARRANTY; without even the implied warranty of |
13 | | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU |
14 | | * Lesser General Public License for more details. |
15 | | * |
16 | | * You should have received a copy of the GNU Lesser General Public |
17 | | * License along with this library; if not, write to the Free Software |
18 | | * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA |
19 | | */ |
20 | | |
21 | | #ifdef HAVE_CONFIG_H |
22 | | #include <config.h> |
23 | | #endif |
24 | | |
25 | | #include <stdlib.h> |
26 | | #include <string.h> |
27 | | #include <sys/types.h> |
28 | | #include <ctype.h> |
29 | | #include <errno.h> |
30 | | #include <stdio.h> |
31 | | |
32 | | #include "../libopensc/opensc.h" |
33 | | #include "../libopensc/cardctl.h" |
34 | | #include "../libopensc/log.h" |
35 | | #include "../libopensc/pkcs15.h" |
36 | | #include "../libopensc/cards.h" |
37 | | #include "../libopensc/card-sc-hsm.h" |
38 | | #include "../libopensc/asn1.h" |
39 | | #include "../libopensc/pkcs15.h" |
40 | | |
41 | | #include "common/compat_strlcpy.h" |
42 | | #include "common/compat_strlcat.h" |
43 | | |
44 | | #include "pkcs15-init.h" |
45 | | #include "profile.h" |
46 | | |
47 | | |
48 | | |
49 | | static u8 pubexp[] = { 0x01, 0x00, 0x01 }; |
50 | | |
51 | | |
52 | | |
53 | | static int sc_hsm_delete_ef(sc_pkcs15_card_t *p15card, u8 prefix, u8 id) |
54 | 0 | { |
55 | 0 | sc_card_t *card = p15card->card; |
56 | 0 | sc_path_t path; |
57 | 0 | u8 fid[2]; |
58 | 0 | int r; |
59 | |
|
60 | 0 | fid[0] = prefix; |
61 | 0 | fid[1] = id; |
62 | |
|
63 | 0 | sc_path_set(&path, SC_PATH_TYPE_FILE_ID, fid, 2, 0, -1); |
64 | |
|
65 | 0 | r = sc_delete_file(card, &path); |
66 | 0 | LOG_TEST_RET(card->ctx, r, "Could not delete file"); |
67 | | |
68 | 0 | LOG_FUNC_RETURN(card->ctx, r); |
69 | 0 | } |
70 | | |
71 | | |
72 | | |
73 | | static int sc_hsm_update_ef(sc_pkcs15_card_t *p15card, u8 prefix, u8 id, int erase, u8 *buf, size_t buflen) |
74 | 422 | { |
75 | 422 | sc_card_t *card = p15card->card; |
76 | 422 | sc_file_t *file = NULL; |
77 | 422 | sc_path_t path; |
78 | 422 | u8 fid[2]; |
79 | 422 | int r; |
80 | | |
81 | 422 | fid[0] = prefix; |
82 | 422 | fid[1] = id; |
83 | | |
84 | 422 | sc_path_set(&path, SC_PATH_TYPE_FILE_ID, fid, 2, 0, -1); |
85 | | |
86 | 422 | r = sc_select_file(card, &path, NULL); |
87 | | |
88 | 422 | if ((r == SC_SUCCESS) && erase) { |
89 | 12 | r = sc_delete_file(card, &path); |
90 | 12 | LOG_TEST_RET(card->ctx, r, "Could not delete file"); |
91 | 5 | r = SC_ERROR_FILE_NOT_FOUND; |
92 | 5 | } |
93 | | |
94 | 415 | if (r == SC_ERROR_FILE_NOT_FOUND) { |
95 | 7 | file = sc_file_new(); |
96 | 7 | file->id = (path.value[0] << 8) | path.value[1]; |
97 | 7 | file->type = SC_FILE_TYPE_WORKING_EF; |
98 | 7 | file->ef_structure = SC_FILE_EF_TRANSPARENT; |
99 | 7 | file->size = (size_t) 0; |
100 | 7 | file->status = SC_FILE_STATUS_ACTIVATED; |
101 | 7 | r = sc_create_file(card, file); |
102 | 7 | sc_file_free(file); |
103 | 7 | LOG_TEST_RET(card->ctx, r, "Could not create file"); |
104 | 7 | } |
105 | | |
106 | 415 | r = sc_update_binary(card, 0, buf, buflen, 0); |
107 | 415 | LOG_FUNC_RETURN(card->ctx, r); |
108 | 415 | } |
109 | | |
110 | | |
111 | | |
112 | | static int sc_hsm_create_key(sc_profile_t *profile, sc_pkcs15_card_t *p15card, |
113 | | sc_pkcs15_object_t *obj) |
114 | 1.85k | { |
115 | | // Keys are automatically generated in GENERATE ASYMMETRIC KEY PAIR command |
116 | 1.85k | LOG_FUNC_CALLED(p15card->card->ctx); |
117 | 1.85k | LOG_FUNC_RETURN(p15card->card->ctx, SC_SUCCESS); |
118 | 1.85k | } |
119 | | |
120 | | |
121 | | |
122 | | static int sc_hsm_store_key(sc_profile_t *profile, sc_pkcs15_card_t *p15card, |
123 | | sc_pkcs15_object_t *obj, sc_pkcs15_prkey_t *key) |
124 | 1.11k | { |
125 | 1.11k | LOG_FUNC_CALLED(p15card->card->ctx); |
126 | 1.11k | LOG_FUNC_RETURN(p15card->card->ctx, SC_ERROR_NOT_SUPPORTED); |
127 | 1.11k | } |
128 | | |
129 | | |
130 | | |
131 | | static int sc_hsm_determine_free_id(struct sc_pkcs15_card *p15card, u8 range) |
132 | 1.12k | { |
133 | 1.12k | struct sc_card *card = p15card->card; |
134 | 1.12k | u8 filelist[MAX_EXT_APDU_LENGTH]; |
135 | 1.12k | int filelistlength, i, j; |
136 | | |
137 | 1.12k | LOG_FUNC_CALLED(p15card->card->ctx); |
138 | | |
139 | 1.12k | filelistlength = sc_list_files(card, filelist, sizeof(filelist)); |
140 | 1.12k | LOG_TEST_RET(card->ctx, filelistlength, "Could not enumerate file and key identifier"); |
141 | | |
142 | 17.2k | for (j = 0; j < 256; j++) { |
143 | 351k | for (i = 0; i + 1 < filelistlength; i += 2) { |
144 | 334k | if ((filelist[i] == range) && (filelist[i + 1] == j)) { |
145 | 116 | break; |
146 | 116 | } |
147 | 334k | } |
148 | 17.2k | if (i >= filelistlength) { |
149 | 1.05k | LOG_FUNC_RETURN(p15card->card->ctx, j); |
150 | 1.05k | } |
151 | 17.2k | } |
152 | 63 | LOG_FUNC_RETURN(p15card->card->ctx, SC_ERROR_NOT_ENOUGH_MEMORY); |
153 | 63 | } |
154 | | |
155 | | |
156 | | |
157 | 356 | static int sc_hsm_encode_gakp_rsa(struct sc_pkcs15_card *p15card, sc_cvc_t *cvc, size_t keysize) { |
158 | 356 | struct sc_object_id rsa15withSHA256 = { { 0,4,0,127,0,7,2,2,2,1,2,-1 } }; |
159 | | |
160 | 356 | LOG_FUNC_CALLED(p15card->card->ctx); |
161 | | |
162 | 356 | cvc->coefficientAorExponentlen = sizeof(pubexp); |
163 | 356 | cvc->coefficientAorExponent = malloc(sizeof(pubexp)); |
164 | 356 | if (!cvc->coefficientAorExponent) { |
165 | 0 | LOG_FUNC_RETURN(p15card->card->ctx, SC_ERROR_OUT_OF_MEMORY); |
166 | 0 | } |
167 | 356 | memcpy(cvc->coefficientAorExponent, pubexp, sizeof(pubexp)); |
168 | | |
169 | 356 | cvc->pukoid = rsa15withSHA256; |
170 | 356 | cvc->modulusSize = (int)keysize; |
171 | | |
172 | 356 | LOG_FUNC_RETURN(p15card->card->ctx, SC_SUCCESS); |
173 | 356 | } |
174 | | |
175 | | |
176 | | |
177 | 363 | static int sc_hsm_encode_gakp_ec(struct sc_pkcs15_card *p15card, sc_cvc_t *cvc, struct sc_pkcs15_prkey_info *key_info) { |
178 | 363 | struct sc_object_id ecdsaWithSHA256 = { { 0,4,0,127,0,7,2,2,2,2,3,-1 } }; |
179 | 363 | struct sc_ec_parameters *ecparams = (struct sc_ec_parameters *)key_info->params.data; |
180 | 363 | struct ec_curve *curve = NULL; |
181 | 363 | u8 *curveoid; |
182 | 363 | int curveoidlen,r; |
183 | | |
184 | 363 | LOG_FUNC_CALLED(p15card->card->ctx); |
185 | | |
186 | 363 | curveoid = ecparams->der.value; |
187 | 363 | if ((ecparams->der.len < 3) || (*curveoid++ != 0x06)) { |
188 | 0 | sc_log(p15card->card->ctx, "EC_PARAMS does not contain curve object identifier"); |
189 | 0 | LOG_FUNC_RETURN(p15card->card->ctx, SC_ERROR_INVALID_DATA); |
190 | 0 | } |
191 | | |
192 | 363 | curveoidlen = *curveoid++; |
193 | | |
194 | 363 | r = sc_pkcs15emu_sc_hsm_get_curve(&curve, curveoid, curveoidlen); |
195 | 363 | LOG_TEST_RET(p15card->card->ctx, r, "Unsupported named curve"); |
196 | | |
197 | 363 | cvc->primeOrModuluslen = curve->prime.len; |
198 | 363 | cvc->primeOrModulus = malloc(cvc->primeOrModuluslen); |
199 | 363 | if (!cvc->primeOrModulus) { |
200 | 0 | LOG_FUNC_RETURN(p15card->card->ctx, SC_ERROR_OUT_OF_MEMORY); |
201 | 0 | } |
202 | 363 | memcpy(cvc->primeOrModulus, curve->prime.value, cvc->primeOrModuluslen); |
203 | | |
204 | 363 | cvc->coefficientAorExponentlen = curve->coefficientA.len; |
205 | 363 | cvc->coefficientAorExponent = malloc(cvc->coefficientAorExponentlen); |
206 | 363 | if (!cvc->coefficientAorExponent) { |
207 | 0 | LOG_FUNC_RETURN(p15card->card->ctx, SC_ERROR_OUT_OF_MEMORY); |
208 | 0 | } |
209 | 363 | memcpy(cvc->coefficientAorExponent, curve->coefficientA.value, cvc->coefficientAorExponentlen); |
210 | | |
211 | 363 | cvc->coefficientBlen = curve->coefficientB.len; |
212 | 363 | cvc->coefficientB = malloc(cvc->coefficientBlen); |
213 | 363 | if (!cvc->coefficientB) { |
214 | 0 | LOG_FUNC_RETURN(p15card->card->ctx, SC_ERROR_OUT_OF_MEMORY); |
215 | 0 | } |
216 | 363 | memcpy(cvc->coefficientB, curve->coefficientB.value, cvc->coefficientBlen); |
217 | | |
218 | 363 | cvc->basePointGlen = curve->basePointG.len; |
219 | 363 | cvc->basePointG = malloc(cvc->basePointGlen); |
220 | 363 | if (!cvc->basePointG) { |
221 | 0 | LOG_FUNC_RETURN(p15card->card->ctx, SC_ERROR_OUT_OF_MEMORY); |
222 | 0 | } |
223 | 363 | memcpy(cvc->basePointG, curve->basePointG.value, cvc->basePointGlen); |
224 | | |
225 | 363 | cvc->orderlen = curve->order.len; |
226 | 363 | cvc->order = malloc(cvc->orderlen); |
227 | 363 | if (!cvc->order) { |
228 | 0 | LOG_FUNC_RETURN(p15card->card->ctx, SC_ERROR_OUT_OF_MEMORY); |
229 | 0 | } |
230 | 363 | memcpy(cvc->order, curve->order.value, cvc->orderlen); |
231 | | |
232 | 363 | cvc->cofactorlen = curve->coFactor.len; |
233 | 363 | cvc->cofactor = malloc(cvc->cofactorlen); |
234 | 363 | if (!cvc->cofactor) { |
235 | 0 | LOG_FUNC_RETURN(p15card->card->ctx, SC_ERROR_OUT_OF_MEMORY); |
236 | 0 | } |
237 | 363 | memcpy(cvc->cofactor, curve->coFactor.value, cvc->cofactorlen); |
238 | | |
239 | 363 | cvc->pukoid = ecdsaWithSHA256; |
240 | | |
241 | 363 | LOG_FUNC_RETURN(p15card->card->ctx, SC_SUCCESS); |
242 | 363 | } |
243 | | |
244 | | |
245 | | |
246 | | static int sc_hsm_generate_key(struct sc_profile *profile, struct sc_pkcs15_card *p15card, |
247 | | struct sc_pkcs15_object *object, |
248 | | struct sc_pkcs15_pubkey *pubkey) |
249 | 742 | { |
250 | 742 | struct sc_card *card = p15card->card; |
251 | 742 | sc_hsm_private_data_t *priv = (sc_hsm_private_data_t *) card->drv_data; |
252 | 742 | struct sc_pkcs15_prkey_info *key_info = (struct sc_pkcs15_prkey_info *)object->data; |
253 | 742 | sc_cardctl_sc_hsm_keygen_info_t sc_hsm_keyinfo; |
254 | 742 | sc_cvc_t cvc; |
255 | 742 | u8 *cvcbin, *cvcpo; |
256 | 742 | unsigned int cla,tag; |
257 | 742 | size_t taglen, cvclen; |
258 | 742 | int r; |
259 | | |
260 | 742 | LOG_FUNC_CALLED(p15card->card->ctx); |
261 | | |
262 | 742 | key_info->key_reference = sc_hsm_determine_free_id(p15card, KEY_PREFIX); |
263 | 742 | LOG_TEST_RET(card->ctx, key_info->key_reference, "Could not determine key reference"); |
264 | | |
265 | 719 | memset(&cvc, 0, sizeof(cvc)); |
266 | | |
267 | 719 | strlcpy(cvc.car, "UTCA00001", sizeof cvc.car); |
268 | 719 | cvc.carLen = strlen(cvc.car); |
269 | 719 | if (priv->serialno) |
270 | 0 | strlcpy(cvc.chr, priv->serialno, sizeof cvc.chr); |
271 | 719 | strlcat(cvc.chr, "00001", sizeof cvc.chr); |
272 | 719 | cvc.chrLen = strlen(cvc.chr); |
273 | | |
274 | 719 | switch(object->type) { |
275 | 356 | case SC_PKCS15_TYPE_PRKEY_RSA: |
276 | 356 | r = sc_hsm_encode_gakp_rsa(p15card, &cvc, key_info->modulus_length); |
277 | 356 | break; |
278 | 363 | case SC_PKCS15_TYPE_PRKEY_EC: |
279 | 363 | r = sc_hsm_encode_gakp_ec(p15card, &cvc, key_info); |
280 | 363 | break; |
281 | 0 | default: |
282 | 0 | r = SC_ERROR_NOT_IMPLEMENTED; |
283 | 0 | break; |
284 | 719 | } |
285 | 719 | if (r != SC_SUCCESS) { |
286 | 0 | sc_pkcs15emu_sc_hsm_free_cvc(&cvc); |
287 | 0 | LOG_TEST_RET(p15card->card->ctx, r, "Could not encode GAKP cdata"); |
288 | 0 | } |
289 | | |
290 | 719 | r = sc_pkcs15emu_sc_hsm_encode_cvc(p15card, &cvc, &cvcbin, &cvclen); |
291 | 719 | sc_pkcs15emu_sc_hsm_free_cvc(&cvc); |
292 | 719 | LOG_TEST_RET(p15card->card->ctx, r, "Could not encode GAKP cdata"); |
293 | | |
294 | | |
295 | 719 | cvcpo = cvcbin; |
296 | 719 | sc_asn1_read_tag((const u8 **)&cvcpo, cvclen, &cla, &tag, &taglen); |
297 | 719 | sc_asn1_read_tag((const u8 **)&cvcpo, cvclen, &cla, &tag, &taglen); |
298 | | |
299 | 719 | sc_hsm_keyinfo.key_id = key_info->key_reference; |
300 | 719 | sc_hsm_keyinfo.auth_key_id = 0; |
301 | 719 | sc_hsm_keyinfo.gakprequest = cvcpo; |
302 | 719 | sc_hsm_keyinfo.gakprequest_len = taglen; |
303 | 719 | sc_hsm_keyinfo.gakpresponse = NULL; |
304 | 719 | sc_hsm_keyinfo.gakpresponse_len = 0; |
305 | | |
306 | 719 | r = sc_card_ctl(card, SC_CARDCTL_SC_HSM_GENERATE_KEY, &sc_hsm_keyinfo); |
307 | 719 | if (r < 0) |
308 | 687 | goto out; |
309 | | |
310 | | |
311 | 32 | cvcpo = sc_hsm_keyinfo.gakpresponse; |
312 | 32 | cvclen = sc_hsm_keyinfo.gakpresponse_len; |
313 | | |
314 | 32 | r = sc_pkcs15emu_sc_hsm_decode_cvc(p15card, (const u8 **)&cvcpo, &cvclen, &cvc); |
315 | 32 | if (r < 0) { |
316 | 32 | sc_log(p15card->card->ctx, "Could not decode GAKP rdata"); |
317 | 32 | r = SC_ERROR_OBJECT_NOT_VALID; |
318 | 32 | goto out; |
319 | 32 | } |
320 | | |
321 | 0 | r = sc_hsm_update_ef(p15card, EE_CERTIFICATE_PREFIX, key_info->key_reference, 1, sc_hsm_keyinfo.gakpresponse, sc_hsm_keyinfo.gakpresponse_len); |
322 | 0 | if (r < 0) { |
323 | 0 | sc_log(p15card->card->ctx, "Could not save certificate signing request"); |
324 | 0 | goto out; |
325 | 0 | } |
326 | | |
327 | 0 | if (pubkey != NULL) { |
328 | 0 | r = sc_pkcs15emu_sc_hsm_get_public_key(p15card->card->ctx, &cvc, pubkey); |
329 | 0 | } |
330 | |
|
331 | 719 | out: |
332 | | |
333 | 719 | sc_pkcs15emu_sc_hsm_free_cvc(&cvc); |
334 | | |
335 | 719 | if (cvcbin) { |
336 | 719 | free(cvcbin); |
337 | 719 | } |
338 | 719 | if (sc_hsm_keyinfo.gakpresponse) { |
339 | 32 | free(sc_hsm_keyinfo.gakpresponse); |
340 | 32 | } |
341 | 719 | LOG_FUNC_RETURN(p15card->card->ctx, r); |
342 | 719 | } |
343 | | |
344 | | |
345 | | |
346 | | /* |
347 | | * Certificates with a related private key are stored in the fid range CE00 - CEFF. The |
348 | | * second byte in the fid matches the key id. |
349 | | * Certificates without a related private key (e.g. CA certificates) are stored in the fid range |
350 | | * CA00 - CAFF. The second byte is a free selected id. |
351 | | */ |
352 | | static int sc_hsm_emu_store_cert(struct sc_pkcs15_card *p15card, struct sc_profile *profile, |
353 | | struct sc_pkcs15_object *object, |
354 | | struct sc_pkcs15_der *data) |
355 | | |
356 | 0 | { |
357 | 0 | struct sc_pkcs15_cert_info *cert_info = (struct sc_pkcs15_cert_info *) object->data; |
358 | 0 | struct sc_pkcs15_object *prkey; |
359 | 0 | sc_path_t path; |
360 | 0 | u8 id[2]; |
361 | 0 | int r; |
362 | |
|
363 | 0 | r = sc_pkcs15_find_object_by_id(p15card, SC_PKCS15_TYPE_PRKEY, &cert_info->id , &prkey); |
364 | |
|
365 | 0 | if (r == SC_ERROR_OBJECT_NOT_FOUND) { |
366 | 0 | r = sc_hsm_determine_free_id(p15card, CA_CERTIFICATE_PREFIX); |
367 | 0 | LOG_TEST_RET(p15card->card->ctx, r, "Out of identifier to store certificate description"); |
368 | | |
369 | 0 | id[0] = CA_CERTIFICATE_PREFIX; |
370 | 0 | id[1] = r; |
371 | 0 | } else { |
372 | 0 | LOG_TEST_RET(p15card->card->ctx, r, "Error locating matching private key"); |
373 | | |
374 | 0 | id[0] = EE_CERTIFICATE_PREFIX; |
375 | 0 | id[1] = ((struct sc_pkcs15_prkey_info *)prkey->data)->key_reference; |
376 | 0 | } |
377 | | |
378 | 0 | sc_path_set(&path, SC_PATH_TYPE_FILE_ID, id, 2, 0, -1); |
379 | 0 | cert_info->path = path; |
380 | |
|
381 | 0 | r = sc_hsm_update_ef(p15card, id[0], id[1], 1, data->value, data->len); |
382 | 0 | return r; |
383 | 0 | } |
384 | | |
385 | | |
386 | | |
387 | | static int sc_hsm_emu_delete_cert(struct sc_pkcs15_card *p15card, struct sc_profile *profile, |
388 | | struct sc_pkcs15_object *object) |
389 | | |
390 | 0 | { |
391 | 0 | struct sc_pkcs15_cert_info *cert_info = (struct sc_pkcs15_cert_info *) object->data; |
392 | |
|
393 | 0 | return sc_hsm_delete_ef(p15card, cert_info->path.value[0], cert_info->path.value[1]); |
394 | 0 | } |
395 | | |
396 | | |
397 | | |
398 | | static int sc_hsm_emu_store_binary(struct sc_pkcs15_card *p15card, struct sc_profile *profile, |
399 | | struct sc_pkcs15_object *object, |
400 | | struct sc_pkcs15_der *data) |
401 | | |
402 | 382 | { |
403 | 382 | struct sc_pkcs15_data_info *data_info = (struct sc_pkcs15_data_info *) object->data; |
404 | 382 | sc_path_t path; |
405 | 382 | u8 id[2]; |
406 | 382 | int r; |
407 | | |
408 | 382 | r = sc_hsm_determine_free_id(p15card, DCOD_PREFIX); |
409 | 382 | LOG_TEST_RET(p15card->card->ctx, r, "Out of identifier to store data description"); |
410 | | |
411 | 336 | if (object->flags & SC_PKCS15_CO_FLAG_PRIVATE) { |
412 | 0 | id[0] = PROT_DATA_PREFIX; |
413 | 336 | } else { |
414 | 336 | id[0] = DATA_PREFIX; |
415 | 336 | } |
416 | 336 | id[1] = r; |
417 | | |
418 | 336 | sc_path_set(&path, SC_PATH_TYPE_FILE_ID, id, 2, 0, -1); |
419 | 336 | data_info->path = path; |
420 | | |
421 | 336 | r = sc_hsm_update_ef(p15card, id[0], id[1], 1, data->value, data->len); |
422 | 336 | return r; |
423 | 382 | } |
424 | | |
425 | | |
426 | | |
427 | | static int sc_hsm_emu_store_data(struct sc_pkcs15_card *p15card, struct sc_profile *profile, |
428 | | struct sc_pkcs15_object *object, |
429 | | struct sc_pkcs15_der *data, struct sc_path *path) |
430 | | |
431 | 382 | { |
432 | 382 | struct sc_context *ctx = p15card->card->ctx; |
433 | 382 | int r; |
434 | | |
435 | 382 | LOG_FUNC_CALLED(ctx); |
436 | | |
437 | 382 | switch (object->type & SC_PKCS15_TYPE_CLASS_MASK) { |
438 | 0 | case SC_PKCS15_TYPE_PRKEY: |
439 | 0 | case SC_PKCS15_TYPE_PUBKEY: |
440 | 0 | r = SC_SUCCESS; |
441 | 0 | break; |
442 | 0 | case SC_PKCS15_TYPE_CERT: |
443 | 0 | r = sc_hsm_emu_store_cert(p15card, profile, object, data); |
444 | 0 | break; |
445 | 382 | case SC_PKCS15_TYPE_DATA_OBJECT: |
446 | 382 | r = sc_hsm_emu_store_binary(p15card, profile, object, data); |
447 | 382 | break; |
448 | 0 | default: |
449 | 0 | r = SC_ERROR_NOT_IMPLEMENTED; |
450 | 0 | break; |
451 | 382 | } |
452 | | |
453 | 382 | LOG_FUNC_RETURN(ctx, r); |
454 | 382 | } |
455 | | |
456 | | |
457 | | |
458 | | static int sc_hsm_emu_delete_object(struct sc_profile *profile, struct sc_pkcs15_card *p15card, |
459 | | struct sc_pkcs15_object *object, const struct sc_path *path) |
460 | 0 | { |
461 | 0 | struct sc_context *ctx = p15card->card->ctx; |
462 | 0 | int r; |
463 | |
|
464 | 0 | LOG_FUNC_CALLED(ctx); |
465 | |
|
466 | 0 | switch (object->type & SC_PKCS15_TYPE_CLASS_MASK) { |
467 | 0 | case SC_PKCS15_TYPE_PRKEY: |
468 | 0 | r = sc_hsm_delete_ef(p15card, KEY_PREFIX, ((struct sc_pkcs15_prkey_info *)object->data)->key_reference); |
469 | 0 | break; |
470 | 0 | case SC_PKCS15_TYPE_CERT: |
471 | 0 | r = sc_hsm_emu_delete_cert(p15card, profile, object); |
472 | 0 | break; |
473 | 0 | case SC_PKCS15_TYPE_DATA_OBJECT: |
474 | 0 | r = sc_delete_file(p15card->card, path); |
475 | 0 | break; |
476 | 0 | case SC_PKCS15_TYPE_PUBKEY: |
477 | 0 | r = SC_SUCCESS; |
478 | 0 | break; |
479 | 0 | default: |
480 | 0 | r = SC_ERROR_NOT_IMPLEMENTED; |
481 | 0 | break; |
482 | 0 | } |
483 | | |
484 | 0 | LOG_FUNC_RETURN(ctx, r); |
485 | 0 | } |
486 | | |
487 | | |
488 | | |
489 | | static int sc_hsm_emu_update_prkd(struct sc_profile *profile, struct sc_pkcs15_card *p15card, |
490 | | struct sc_pkcs15_object *object) |
491 | 0 | { |
492 | 0 | struct sc_pkcs15_prkey_info *key_info = (struct sc_pkcs15_prkey_info *)object->data; |
493 | 0 | u8 *buf; |
494 | 0 | size_t buflen; |
495 | 0 | int r; |
496 | | |
497 | | // Don't save AID in PRKD |
498 | 0 | key_info->path.aid.len = 0; |
499 | |
|
500 | 0 | r = sc_pkcs15_encode_prkdf_entry(p15card->card->ctx, object, &buf, &buflen); |
501 | 0 | LOG_TEST_RET(p15card->card->ctx, r, "Error encoding PRKD entry"); |
502 | | |
503 | 0 | r = sc_hsm_update_ef(p15card, PRKD_PREFIX, key_info->key_reference, 0, buf, buflen); |
504 | 0 | free(buf); |
505 | 0 | return r; |
506 | 0 | } |
507 | | |
508 | | |
509 | | |
510 | | static int sc_hsm_emu_update_dcod(struct sc_profile *profile, struct sc_pkcs15_card *p15card, |
511 | | struct sc_pkcs15_object *object) |
512 | 121 | { |
513 | 121 | struct sc_pkcs15_data_info *data_info = (struct sc_pkcs15_data_info *) object->data; |
514 | 121 | u8 *buf; |
515 | 121 | size_t buflen; |
516 | 121 | int r; |
517 | | |
518 | 121 | r = sc_pkcs15_encode_dodf_entry(p15card->card->ctx, object, &buf, &buflen); |
519 | 121 | LOG_TEST_RET(p15card->card->ctx, r, "Error encoding DCOD entry"); |
520 | | |
521 | 86 | r = sc_hsm_update_ef(p15card, DCOD_PREFIX, data_info->path.value[data_info->path.len - 1], 0, buf, buflen); |
522 | 86 | free(buf); |
523 | 86 | return r; |
524 | 121 | } |
525 | | |
526 | | |
527 | | |
528 | | static int sc_hsm_emu_update_cd(struct sc_profile *profile, struct sc_pkcs15_card *p15card, |
529 | | struct sc_pkcs15_object *object) |
530 | 0 | { |
531 | 0 | struct sc_pkcs15_cert_info *cert_info = (struct sc_pkcs15_cert_info *) object->data; |
532 | 0 | u8 *buf; |
533 | 0 | size_t buflen; |
534 | 0 | int r; |
535 | |
|
536 | 0 | if ((cert_info->path.len < 2) || |
537 | 0 | ((cert_info->path.value[cert_info->path.len - 2]) != CA_CERTIFICATE_PREFIX)) { |
538 | | // Certificates associated with stored private keys don't get a separate CD entry |
539 | 0 | return SC_SUCCESS; |
540 | 0 | } |
541 | | |
542 | 0 | r = sc_pkcs15_encode_cdf_entry(p15card->card->ctx, object, &buf, &buflen); |
543 | 0 | LOG_TEST_RET(p15card->card->ctx, r, "Error encoding CD entry"); |
544 | | |
545 | 0 | r = sc_hsm_update_ef(p15card, CD_PREFIX, cert_info->path.value[cert_info->path.len - 1], 0, buf, buflen); |
546 | 0 | free(buf); |
547 | 0 | return r; |
548 | 0 | } |
549 | | |
550 | | |
551 | | |
552 | | static int sc_hsm_emu_delete_cd(struct sc_profile *profile, struct sc_pkcs15_card *p15card, |
553 | | struct sc_pkcs15_object *object) |
554 | 0 | { |
555 | 0 | struct sc_pkcs15_cert_info *cert_info = (struct sc_pkcs15_cert_info *) object->data; |
556 | |
|
557 | 0 | if ((cert_info->path.len < 2) || |
558 | 0 | ((cert_info->path.value[cert_info->path.len - 2]) != CA_CERTIFICATE_PREFIX)) { |
559 | | // Certificates associated with stored private keys don't get a separate CD entry |
560 | 0 | return SC_SUCCESS; |
561 | 0 | } |
562 | | |
563 | 0 | return sc_hsm_delete_ef(p15card, CD_PREFIX, cert_info->path.value[cert_info->path.len - 1]); |
564 | 0 | } |
565 | | |
566 | | |
567 | | |
568 | | static int sc_hsm_emu_update_any_df(struct sc_profile *profile, struct sc_pkcs15_card *p15card, |
569 | | unsigned op, struct sc_pkcs15_object *object) |
570 | 124 | { |
571 | 124 | struct sc_context *ctx = p15card->card->ctx; |
572 | 124 | int rv = SC_ERROR_NOT_SUPPORTED; |
573 | | |
574 | 124 | SC_FUNC_CALLED(ctx, 1); |
575 | 124 | switch(op) { |
576 | 0 | case SC_AC_OP_ERASE: |
577 | 0 | sc_log(ctx, "Update DF; erase object('%s',type:%X)", object->label, object->type); |
578 | 0 | switch(object->type & SC_PKCS15_TYPE_CLASS_MASK) { |
579 | 0 | case SC_PKCS15_TYPE_PRKEY: |
580 | 0 | rv = sc_hsm_delete_ef(p15card, PRKD_PREFIX, ((struct sc_pkcs15_prkey_info *)object->data)->key_reference); |
581 | 0 | break; |
582 | 0 | case SC_PKCS15_TYPE_PUBKEY: |
583 | 0 | rv = SC_SUCCESS; |
584 | 0 | break; |
585 | 0 | case SC_PKCS15_TYPE_CERT: |
586 | 0 | rv = sc_hsm_emu_delete_cd(profile, p15card, object); |
587 | 0 | break; |
588 | 0 | case SC_PKCS15_TYPE_DATA_OBJECT: |
589 | 0 | rv = sc_hsm_delete_ef(p15card, DCOD_PREFIX, ((struct sc_pkcs15_data_info *)object->data)->path.value[1]); |
590 | 0 | break; |
591 | 0 | } |
592 | 0 | break; |
593 | 0 | case SC_AC_OP_UPDATE: |
594 | 124 | case SC_AC_OP_CREATE: |
595 | 124 | sc_log(ctx, "Update DF; create object('%s',type:%X)", object->label, object->type); |
596 | 124 | switch(object->type & SC_PKCS15_TYPE_CLASS_MASK) { |
597 | 0 | case SC_PKCS15_TYPE_PUBKEY: |
598 | 0 | rv = SC_SUCCESS; |
599 | 0 | break; |
600 | 0 | case SC_PKCS15_TYPE_PRKEY: |
601 | 0 | rv = sc_hsm_emu_update_prkd(profile, p15card, object); |
602 | 0 | break; |
603 | 0 | case SC_PKCS15_TYPE_CERT: |
604 | 0 | rv = sc_hsm_emu_update_cd(profile, p15card, object); |
605 | 0 | break; |
606 | 121 | case SC_PKCS15_TYPE_DATA_OBJECT: |
607 | 121 | rv = sc_hsm_emu_update_dcod(profile, p15card, object); |
608 | 121 | break; |
609 | 124 | } |
610 | 124 | break; |
611 | 124 | } |
612 | 124 | SC_FUNC_RETURN(ctx, 1, rv); |
613 | 124 | } |
614 | | |
615 | | |
616 | | |
617 | | static struct sc_pkcs15init_operations |
618 | | sc_pkcs15init_sc_hsm_operations = { |
619 | | NULL, /* erase_card */ |
620 | | NULL, /* init_card */ |
621 | | NULL, /* create_dir */ |
622 | | NULL, /* create_domain */ |
623 | | NULL, /* select_pin_reference */ |
624 | | NULL, /* create_pin */ |
625 | | NULL, /* select key reference */ |
626 | | sc_hsm_create_key, |
627 | | sc_hsm_store_key, |
628 | | sc_hsm_generate_key, |
629 | | NULL, /* encode private key */ |
630 | | NULL, /* encode public key */ |
631 | | NULL, /* finalize_card */ |
632 | | sc_hsm_emu_delete_object, /* delete object */ |
633 | | NULL, /* pkcs15init emulation update_dir */ |
634 | | sc_hsm_emu_update_any_df, /* pkcs15init emulation update_any_df */ |
635 | | NULL, /* pkcs15init emulation update_tokeninfo */ |
636 | | NULL, /* pkcs15init emulation write_info */ |
637 | | sc_hsm_emu_store_data, |
638 | | NULL, /* sanity_check */ |
639 | | }; |
640 | | |
641 | | |
642 | | struct sc_pkcs15init_operations * |
643 | | sc_pkcs15init_get_sc_hsm_ops(void) |
644 | 701 | { |
645 | 701 | return &sc_pkcs15init_sc_hsm_operations; |
646 | 701 | } |
647 | | |