/src/opensc/src/libopensc/pkcs15-actalis.c
Line | Count | Source |
1 | | /* |
2 | | * PKCS15 emulation layer for Actalis card. |
3 | | * To see how this works, run p15dump on your Actalis Card. |
4 | | * |
5 | | * Copyright (C) 2005, Andrea Frigido <andrea@frisoft.it> |
6 | | * Copyright (C) 2005, Sirio Capizzi <graaf@virgilio.it> |
7 | | * Copyright (C) 2004, Antonino Iacono <ant_iacono@tin.it> |
8 | | * Copyright (C) 2003, Olaf Kirch <okir@suse.de> |
9 | | * |
10 | | * This library is free software; you can redistribute it and/or |
11 | | * modify it under the terms of the GNU Lesser General Public |
12 | | * License as published by the Free Software Foundation; either |
13 | | * version 2.1 of the License, or (at your option) any later version. |
14 | | * |
15 | | * This library is distributed in the hope that it will be useful, |
16 | | * but WITHOUT ANY WARRANTY; without even the implied warranty of |
17 | | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU |
18 | | * Lesser General Public License for more details. |
19 | | * |
20 | | * You should have received a copy of the GNU Lesser General Public |
21 | | * License along with this library; if not, write to the Free Software |
22 | | * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA |
23 | | */ |
24 | | |
25 | | #ifdef HAVE_CONFIG_H |
26 | | #include "config.h" |
27 | | #endif |
28 | | |
29 | | #include <stdlib.h> |
30 | | #include <string.h> |
31 | | #include <stdio.h> |
32 | | #ifdef ENABLE_ZLIB |
33 | | #include <zlib.h> |
34 | | #endif |
35 | | |
36 | | #include "common/compat_strlcpy.h" |
37 | | #include "libopensc/pkcs15.h" |
38 | | #include "libopensc/log.h" |
39 | | #include "libopensc/internal.h" |
40 | | |
41 | | static int (*set_security_env) (sc_card_t *, const sc_security_env_t *, int); |
42 | | |
43 | | static int set_sec_env(sc_card_t * card, const sc_security_env_t *env, |
44 | | int se_num) |
45 | 0 | { |
46 | 0 | int r; |
47 | 0 | sc_security_env_t tenv = *env; |
48 | 0 | if (tenv.operation == SC_SEC_OPERATION_SIGN) |
49 | 0 | tenv.operation = SC_SEC_OPERATION_DECIPHER; |
50 | |
|
51 | 0 | if ((r = |
52 | 0 | card->ops->restore_security_env(card, 0x40)) == SC_SUCCESS) |
53 | 0 | return set_security_env(card, &tenv, se_num); |
54 | 0 | else |
55 | 0 | return r; |
56 | 0 | } |
57 | | |
58 | | static int do_sign(sc_card_t * card, const u8 * in, size_t inlen, u8 * out, |
59 | | size_t outlen) |
60 | 0 | { |
61 | 0 | return card->ops->decipher(card, in, inlen, out, outlen); |
62 | 0 | } |
63 | | |
64 | | #if 1 |
65 | | /* XXX: temporary copy of the old pkcs15emu functions, |
66 | | * to be removed */ |
67 | | static int sc_pkcs15emu_add_pin(sc_pkcs15_card_t *p15card, |
68 | | const sc_pkcs15_id_t *id, const char *label, |
69 | | const sc_path_t *path, int ref, int type, |
70 | | unsigned int min_length, |
71 | | unsigned int max_length, |
72 | | int flags, int tries_left, const char pad_char, int obj_flags) |
73 | 0 | { |
74 | 0 | sc_pkcs15_auth_info_t info; |
75 | 0 | sc_pkcs15_object_t obj; |
76 | |
|
77 | 0 | memset(&info, 0, sizeof(info)); |
78 | 0 | memset(&obj, 0, sizeof(obj)); |
79 | |
|
80 | 0 | info.auth_id = *id; |
81 | 0 | info.auth_type = SC_PKCS15_PIN_AUTH_TYPE_PIN; |
82 | 0 | info.attrs.pin.min_length = min_length; |
83 | 0 | info.attrs.pin.max_length = max_length; |
84 | 0 | info.attrs.pin.stored_length = max_length; |
85 | 0 | info.attrs.pin.type = type; |
86 | 0 | info.attrs.pin.reference = ref; |
87 | 0 | info.attrs.pin.flags = flags; |
88 | 0 | info.attrs.pin.pad_char = pad_char; |
89 | 0 | info.tries_left = tries_left; |
90 | 0 | info.logged_in = SC_PIN_STATE_UNKNOWN; |
91 | |
|
92 | 0 | if (path) |
93 | 0 | info.path = *path; |
94 | 0 | if (type == SC_PKCS15_PIN_TYPE_BCD) |
95 | 0 | info.attrs.pin.stored_length /= 2; |
96 | |
|
97 | 0 | strlcpy(obj.label, label, sizeof(obj.label)); |
98 | 0 | obj.flags = obj_flags; |
99 | |
|
100 | 0 | return sc_pkcs15emu_add_pin_obj(p15card, &obj, &info); |
101 | 0 | } |
102 | | |
103 | | static int sc_pkcs15emu_add_prkey(sc_pkcs15_card_t *p15card, |
104 | | const sc_pkcs15_id_t *id, |
105 | | const char *label, |
106 | | int type, unsigned int modulus_length, int usage, |
107 | | const sc_path_t *path, int ref, |
108 | | const sc_pkcs15_id_t *auth_id, int obj_flags) |
109 | 0 | { |
110 | 0 | sc_pkcs15_prkey_info_t info; |
111 | 0 | sc_pkcs15_object_t obj; |
112 | |
|
113 | 0 | memset(&info, 0, sizeof(info)); |
114 | 0 | memset(&obj, 0, sizeof(obj)); |
115 | |
|
116 | 0 | info.id = *id; |
117 | 0 | info.modulus_length = modulus_length; |
118 | 0 | info.usage = usage; |
119 | 0 | info.native = 1; |
120 | 0 | info.key_reference = ref; |
121 | |
|
122 | 0 | if (path) |
123 | 0 | info.path = *path; |
124 | |
|
125 | 0 | obj.flags = obj_flags; |
126 | 0 | strlcpy(obj.label, label, sizeof(obj.label)); |
127 | 0 | if (auth_id != NULL) |
128 | 0 | obj.auth_id = *auth_id; |
129 | |
|
130 | 0 | return sc_pkcs15emu_add_rsa_prkey(p15card, &obj, &info); |
131 | 0 | } |
132 | | #endif |
133 | | |
134 | | static int sc_pkcs15emu_actalis_init(sc_pkcs15_card_t * p15card) |
135 | 0 | { |
136 | 0 | sc_card_t *card = p15card->card; |
137 | 0 | sc_path_t path; |
138 | 0 | sc_pkcs15_id_t id, auth_id; |
139 | 0 | unsigned char serial_buf[13], *serial; |
140 | 0 | int flags; |
141 | 0 | int r; |
142 | |
|
143 | 0 | #ifdef ENABLE_ZLIB |
144 | 0 | int use_file_cache_backup = p15card->opts.use_file_cache; |
145 | |
|
146 | 0 | int i = 0, j = 0; |
147 | 0 | const char *certLabel[] = { |
148 | 0 | "User Non-repudiation Certificate", /* "User Non-repudiation Certificate" */ |
149 | 0 | "TSA Certificate", |
150 | 0 | "CA Certificate" |
151 | 0 | }; |
152 | 0 | const char *certPath[] = |
153 | 0 | { "3F00300060006002", "3F00300060006003", "3F00300060006004" }; |
154 | 0 | #endif |
155 | |
|
156 | 0 | const char *keyPath = "3F00300040000008"; |
157 | 0 | const char *pinDfName = "05040200"; |
158 | | |
159 | | /* const int prkey_usage = SC_PKCS15_PRKEY_USAGE_NONREPUDIATION; */ |
160 | 0 | const int authprkey_usage = SC_PKCS15_PRKEY_USAGE_SIGN |
161 | 0 | | SC_PKCS15_PRKEY_USAGE_SIGNRECOVER |
162 | 0 | | SC_PKCS15_PRKEY_USAGE_ENCRYPT |
163 | 0 | | SC_PKCS15_PRKEY_USAGE_DECRYPT; |
164 | |
|
165 | 0 | const char *authPIN = "Authentication PIN"; |
166 | | /* const char *nonrepPIN = "Non-repudiation PIN"; */ |
167 | |
|
168 | 0 | const char *authPRKEY = "Authentication Key"; |
169 | | /* const char *nonrepPRKEY = "Non repudiation Key"; */ |
170 | |
|
171 | 0 | p15card->opts.use_file_cache = SC_PKCS15_OPTS_CACHE_ALL_FILES; |
172 | | |
173 | | /* Get Serial number */ |
174 | 0 | sc_format_path("3F0030000001", &path); |
175 | 0 | r = sc_select_file(card, &path, NULL); |
176 | 0 | if (r != SC_SUCCESS) |
177 | 0 | return SC_ERROR_WRONG_CARD; |
178 | | |
179 | 0 | r = sc_read_binary(card, 0xC3, serial_buf, 12, 0); |
180 | 0 | if (r != SC_SUCCESS) |
181 | 0 | return SC_ERROR_WRONG_CARD; |
182 | 0 | serial = serial_buf; |
183 | | |
184 | | /* |
185 | | * The serial number is 8 characters long. Later versions of the |
186 | | * card have the serial number at a different offset, after 4 more |
187 | | * bytes. |
188 | | */ |
189 | 0 | if (serial[0] != 'H') { |
190 | 0 | if (serial[4] == 'H') |
191 | 0 | serial = &serial_buf[4]; |
192 | 0 | else |
193 | 0 | return SC_ERROR_WRONG_CARD; |
194 | 0 | } |
195 | 0 | serial[8] = '\0'; |
196 | | |
197 | | /* Controllo che il serial number inizi per "H" */ |
198 | 0 | if( serial[0] != 'H' ) |
199 | 0 | return SC_ERROR_WRONG_CARD; |
200 | | |
201 | 0 | set_string(&p15card->tokeninfo->label, "Actalis"); |
202 | 0 | set_string(&p15card->tokeninfo->manufacturer_id, "Actalis"); |
203 | 0 | set_string(&p15card->tokeninfo->serial_number, (char *)serial); |
204 | |
|
205 | 0 | #ifdef ENABLE_ZLIB |
206 | 0 | for (i = 0; i < 3; i++) { |
207 | 0 | sc_path_t cpath; |
208 | 0 | sc_format_path(certPath[i], &cpath); |
209 | |
|
210 | 0 | if (sc_select_file(card, &cpath, NULL) == SC_SUCCESS) { |
211 | 0 | unsigned char *compCert = NULL, *cert = NULL, size[2]; |
212 | 0 | unsigned long compLen, len; |
213 | |
|
214 | 0 | sc_pkcs15_cert_info_t cert_info; |
215 | 0 | sc_pkcs15_object_t cert_obj; |
216 | 0 | memset(&cert_info, 0, sizeof(cert_info)); |
217 | 0 | memset(&cert_obj, 0, sizeof(cert_obj)); |
218 | |
|
219 | 0 | if (SC_SUCCESS != sc_read_binary(card, 2, size, 2, 0)) |
220 | 0 | continue; |
221 | 0 | compLen = (size[0] << 8) + size[1]; |
222 | 0 | compCert = malloc(compLen * sizeof(unsigned char)); |
223 | 0 | len = 3 * compLen; /*Approximation of the uncompressed size */ |
224 | 0 | cert = malloc(len * sizeof(unsigned char)); |
225 | 0 | if (!cert || !compCert) { |
226 | 0 | free(cert); |
227 | 0 | free(compCert); |
228 | 0 | sc_pkcs15_card_clear(p15card); |
229 | 0 | p15card->opts.use_file_cache = use_file_cache_backup; |
230 | 0 | return SC_ERROR_OUT_OF_MEMORY; |
231 | 0 | } |
232 | | |
233 | 0 | if (sc_read_binary(card, 4, compCert, compLen, 0) != SC_SUCCESS |
234 | 0 | || uncompress(cert, &len, compCert, compLen) != Z_OK) { |
235 | 0 | free(cert); |
236 | 0 | free(compCert); |
237 | 0 | continue; |
238 | 0 | } |
239 | 0 | cpath.index = 0; |
240 | 0 | cpath.count = (int)len; |
241 | |
|
242 | 0 | sc_pkcs15_cache_file(p15card, &cpath, cert, len); |
243 | 0 | id.value[0] = j + 1; |
244 | 0 | id.len = 1; |
245 | 0 | cert_info.id = id; |
246 | 0 | cert_info.path = cpath; |
247 | 0 | cert_info.authority = (j>0); |
248 | |
|
249 | 0 | strlcpy(cert_obj.label, certLabel[j], sizeof(cert_obj.label)); |
250 | |
|
251 | 0 | j++; |
252 | 0 | cert_obj.flags = SC_PKCS15_CO_FLAG_MODIFIABLE; |
253 | 0 | r = sc_pkcs15emu_add_x509_cert(p15card, &cert_obj, &cert_info); |
254 | 0 | if (r < 0) { |
255 | 0 | sc_log(card->ctx, "Failed to add cert obj r=%d", r); |
256 | 0 | free(cert); |
257 | 0 | free(compCert); |
258 | 0 | continue; |
259 | 0 | } |
260 | | |
261 | 0 | free(cert); |
262 | 0 | free(compCert); |
263 | 0 | } |
264 | 0 | } |
265 | 0 | #endif |
266 | | |
267 | | /* adding PINs & private keys */ |
268 | 0 | flags = SC_PKCS15_PIN_FLAG_CASE_SENSITIVE | |
269 | 0 | SC_PKCS15_PIN_FLAG_INITIALIZED | |
270 | 0 | SC_PKCS15_PIN_FLAG_NEEDS_PADDING; |
271 | |
|
272 | 0 | sc_format_path(pinDfName, &path); |
273 | 0 | path.type = SC_PATH_TYPE_DF_NAME; |
274 | |
|
275 | 0 | id.value[0] = 1; |
276 | 0 | id.len = 1; |
277 | 0 | sc_pkcs15emu_add_pin(p15card, &id, |
278 | 0 | authPIN, &path, 0x81, |
279 | 0 | SC_PKCS15_PIN_TYPE_ASCII_NUMERIC, |
280 | 0 | 5, 8, flags, 3, 0, |
281 | 0 | SC_PKCS15_CO_FLAG_MODIFIABLE | |
282 | 0 | SC_PKCS15_CO_FLAG_PRIVATE); |
283 | |
|
284 | 0 | sc_format_path(keyPath, &path); |
285 | 0 | id.value[0] = 1; |
286 | 0 | id.len = 1; |
287 | 0 | auth_id.value[0] = 1; |
288 | 0 | auth_id.len = 1; |
289 | 0 | sc_pkcs15emu_add_prkey(p15card, &id, |
290 | 0 | authPRKEY, |
291 | 0 | SC_PKCS15_TYPE_PRKEY_RSA, |
292 | 0 | 1024, authprkey_usage, |
293 | 0 | &path, 0x08, |
294 | 0 | &auth_id, |
295 | 0 | SC_PKCS15_CO_FLAG_PRIVATE); |
296 | | |
297 | | /* return to MF */ |
298 | 0 | sc_format_path("3F00", &path); |
299 | 0 | sc_select_file(card, &path, NULL); |
300 | 0 | { |
301 | | /* save old signature funcs */ |
302 | 0 | set_security_env = card->ops->set_security_env; |
303 | | /* set new one */ |
304 | 0 | card->ops->set_security_env = set_sec_env; |
305 | 0 | card->ops->compute_signature = do_sign; |
306 | 0 | } |
307 | |
|
308 | 0 | return SC_SUCCESS; |
309 | |
|
310 | 0 | } |
311 | | |
312 | | static int actalis_detect_card(sc_pkcs15_card_t * p15card) |
313 | 0 | { |
314 | 0 | sc_card_t *card = p15card->card; |
315 | | |
316 | | /* check if we have the correct card OS */ |
317 | 0 | if (strcmp(card->name, "CardOS M4")) |
318 | 0 | return SC_ERROR_WRONG_CARD; |
319 | | |
320 | 0 | return SC_SUCCESS; |
321 | 0 | } |
322 | | |
323 | | int sc_pkcs15emu_actalis_init_ex(sc_pkcs15_card_t * p15card, |
324 | | struct sc_aid *aid) |
325 | 0 | { |
326 | 0 | if (actalis_detect_card(p15card)) |
327 | 0 | return SC_ERROR_WRONG_CARD; |
328 | 0 | return sc_pkcs15emu_actalis_init(p15card); |
329 | 0 | } |