File: | lib/pkcs11.c |
Location: | line 955, column 11 |
Description: | Value stored to 'ret' is never read |
1 | /* |
2 | * GnuTLS PKCS#11 support |
3 | * Copyright (C) 2010, 2011 Free Software Foundation |
4 | * Copyright (C) 2008, Joe Orton <joe@manyfish.co.uk> |
5 | * |
6 | * Authors: Nikos Mavrogiannopoulos, Stef Walter |
7 | * |
8 | * Inspired and some parts (pkcs11_login) based on neon PKCS #11 support |
9 | * by Joe Orton. More ideas came from the pkcs11-helper library by |
10 | * Alon Bar-Lev. |
11 | * |
12 | * The GnuTLS is free software; you can redistribute it and/or |
13 | * modify it under the terms of the GNU Lesser General Public License |
14 | * as published by the Free Software Foundation; either version 3 of |
15 | * the License, or (at your option) any later version. |
16 | * |
17 | * This library is distributed in the hope that it will be useful, but |
18 | * WITHOUT ANY WARRANTY; without even the implied warranty of |
19 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU |
20 | * Lesser General Public License for more details. |
21 | * |
22 | * You should have received a copy of the GNU Lesser General Public License |
23 | * along with this program. If not, see <http://www.gnu.org/licenses/> |
24 | */ |
25 | |
26 | #include <gnutls_int.h> |
27 | #include <gnutls/pkcs11.h> |
28 | #include <stdio.h> |
29 | #include <string.h> |
30 | #include <gnutls_errors.h> |
31 | #include <gnutls_datumgnutls_datum_t.h> |
32 | |
33 | |
34 | #include <pkcs11_int.h> |
35 | #include <p11-kit/p11-kit.h> |
36 | #include <p11-kit/pin.h> |
37 | |
38 | #define MAX_PROVIDERS16 16 |
39 | |
40 | /* XXX: try to eliminate this */ |
41 | #define MAX_CERT_SIZE8*1024 8*1024 |
42 | |
43 | struct gnutls_pkcs11_provider_s |
44 | { |
45 | struct ck_function_list *module; |
46 | unsigned long nslots; |
47 | ck_slot_id_t *slots; |
48 | struct ck_info info; |
49 | int initialized; |
50 | }; |
51 | |
52 | struct flags_find_data_st |
53 | { |
54 | struct p11_kit_uri *info; |
55 | unsigned int slot_flags; |
56 | }; |
57 | |
58 | struct url_find_data_st |
59 | { |
60 | gnutls_pkcs11_obj_t crt; |
61 | }; |
62 | |
63 | struct crt_find_data_st |
64 | { |
65 | gnutls_pkcs11_obj_t *p_list; |
66 | unsigned int *n_list; |
67 | unsigned int current; |
68 | gnutls_pkcs11_obj_attr_t flags; |
69 | struct p11_kit_uri *info; |
70 | }; |
71 | |
72 | |
73 | static struct gnutls_pkcs11_provider_s providers[MAX_PROVIDERS16]; |
74 | static int active_providers = 0; |
75 | static int initialized_registered = 0; |
76 | |
77 | static gnutls_pkcs11_pin_callback_t pin_func; |
78 | static void *pin_data; |
79 | |
80 | gnutls_pkcs11_token_callback_t token_func; |
81 | void *token_data; |
82 | |
83 | int |
84 | pkcs11_rv_to_err (ck_rv_t rv) |
85 | { |
86 | switch (rv) |
87 | { |
88 | case CKR_OK(0UL): |
89 | return 0; |
90 | case CKR_HOST_MEMORY(2UL): |
91 | return GNUTLS_E_MEMORY_ERROR-25; |
92 | case CKR_SLOT_ID_INVALID(3UL): |
93 | return GNUTLS_E_PKCS11_SLOT_ERROR-305; |
94 | case CKR_ARGUMENTS_BAD(7UL): |
95 | case CKR_MECHANISM_PARAM_INVALID(0x71UL): |
96 | return GNUTLS_E_INVALID_REQUEST-50; |
97 | case CKR_NEED_TO_CREATE_THREADS(9UL): |
98 | case CKR_CANT_LOCK(0xaUL): |
99 | case CKR_FUNCTION_NOT_PARALLEL(0x51UL): |
100 | case CKR_MUTEX_BAD(0x1a0UL): |
101 | case CKR_MUTEX_NOT_LOCKED(0x1a1UL): |
102 | return GNUTLS_E_LOCKING_ERROR-306; |
103 | case CKR_ATTRIBUTE_READ_ONLY(0x10UL): |
104 | case CKR_ATTRIBUTE_SENSITIVE(0x11UL): |
105 | case CKR_ATTRIBUTE_TYPE_INVALID(0x12UL): |
106 | case CKR_ATTRIBUTE_VALUE_INVALID(0x13UL): |
107 | return GNUTLS_E_PKCS11_ATTRIBUTE_ERROR-307; |
108 | case CKR_DEVICE_ERROR(0x30UL): |
109 | case CKR_DEVICE_MEMORY(0x31UL): |
110 | case CKR_DEVICE_REMOVED(0x32UL): |
111 | return GNUTLS_E_PKCS11_DEVICE_ERROR-308; |
112 | case CKR_DATA_INVALID(0x20UL): |
113 | case CKR_DATA_LEN_RANGE(0x21UL): |
114 | case CKR_ENCRYPTED_DATA_INVALID(0x40UL): |
115 | case CKR_ENCRYPTED_DATA_LEN_RANGE(0x41UL): |
116 | case CKR_OBJECT_HANDLE_INVALID(0x82UL): |
117 | return GNUTLS_E_PKCS11_DATA_ERROR-309; |
118 | case CKR_FUNCTION_NOT_SUPPORTED(0x54UL): |
119 | case CKR_MECHANISM_INVALID(0x70UL): |
120 | return GNUTLS_E_PKCS11_UNSUPPORTED_FEATURE_ERROR-310; |
121 | case CKR_KEY_HANDLE_INVALID(0x60UL): |
122 | case CKR_KEY_SIZE_RANGE(0x62UL): |
123 | case CKR_KEY_TYPE_INCONSISTENT(0x63UL): |
124 | case CKR_KEY_NOT_NEEDED(0x64UL): |
125 | case CKR_KEY_CHANGED(0x65UL): |
126 | case CKR_KEY_NEEDED(0x66UL): |
127 | case CKR_KEY_INDIGESTIBLE(0x67UL): |
128 | case CKR_KEY_FUNCTION_NOT_PERMITTED(0x68UL): |
129 | case CKR_KEY_NOT_WRAPPABLE(0x69UL): |
130 | case CKR_KEY_UNEXTRACTABLE(0x6aUL): |
131 | return GNUTLS_E_PKCS11_KEY_ERROR-311; |
132 | case CKR_PIN_INCORRECT(0xa0UL): |
133 | case CKR_PIN_INVALID(0xa1UL): |
134 | case CKR_PIN_LEN_RANGE(0xa2UL): |
135 | return GNUTLS_E_PKCS11_PIN_ERROR-303; |
136 | case CKR_PIN_EXPIRED(0xa3UL): |
137 | return GNUTLS_E_PKCS11_PIN_EXPIRED-312; |
138 | case CKR_PIN_LOCKED(0xa4UL): |
139 | return GNUTLS_E_PKCS11_PIN_LOCKED-313; |
140 | case CKR_SESSION_CLOSED(0xb0UL): |
141 | case CKR_SESSION_COUNT(0xb1UL): |
142 | case CKR_SESSION_HANDLE_INVALID(0xb3UL): |
143 | case CKR_SESSION_PARALLEL_NOT_SUPPORTED(0xb4UL): |
144 | case CKR_SESSION_READ_ONLY(0xb5UL): |
145 | case CKR_SESSION_EXISTS(0xb6UL): |
146 | case CKR_SESSION_READ_ONLY_EXISTS(0xb7UL): |
147 | case CKR_SESSION_READ_WRITE_SO_EXISTS(0xb8UL): |
148 | return GNUTLS_E_PKCS11_SESSION_ERROR-314; |
149 | case CKR_SIGNATURE_INVALID(0xc0UL): |
150 | case CKR_SIGNATURE_LEN_RANGE(0xc1UL): |
151 | return GNUTLS_E_PKCS11_SIGNATURE_ERROR-315; |
152 | case CKR_TOKEN_NOT_PRESENT(0xe0UL): |
153 | case CKR_TOKEN_NOT_RECOGNIZED(0xe1UL): |
154 | case CKR_TOKEN_WRITE_PROTECTED(0xe2UL): |
155 | return GNUTLS_E_PKCS11_TOKEN_ERROR-316; |
156 | case CKR_USER_ALREADY_LOGGED_IN(0x100UL): |
157 | case CKR_USER_NOT_LOGGED_IN(0x101UL): |
158 | case CKR_USER_PIN_NOT_INITIALIZED(0x102UL): |
159 | case CKR_USER_TYPE_INVALID(0x103UL): |
160 | case CKR_USER_ANOTHER_ALREADY_LOGGED_IN(0x104UL): |
161 | case CKR_USER_TOO_MANY_TYPES(0x105UL): |
162 | return GNUTLS_E_PKCS11_USER_ERROR-317; |
163 | case CKR_BUFFER_TOO_SMALL(0x150UL): |
164 | return GNUTLS_E_SHORT_MEMORY_BUFFER-51; |
165 | default: |
166 | return GNUTLS_E_PKCS11_ERROR-300; |
167 | } |
168 | } |
169 | |
170 | /* Fake scan */ |
171 | void |
172 | pkcs11_rescan_slots (void) |
173 | { |
174 | unsigned long slots; |
175 | |
176 | pkcs11_get_slot_list (providers[active_providers - 1].module, 0, |
177 | NULL((void*)0), &slots); |
178 | } |
179 | |
180 | static int |
181 | pkcs11_add_module (const char *name, struct ck_function_list *module) |
182 | { |
183 | struct ck_info info; |
184 | int i; |
185 | |
186 | if (active_providers >= MAX_PROVIDERS16) |
187 | { |
188 | gnutls_assert ()do { if (__builtin_expect((_gnutls_log_level >= 2), 0)) _gnutls_log ( 2, "ASSERT: %s:%d\n", "pkcs11.c",188); } while(0);; |
189 | return GNUTLS_E_CONSTRAINT_ERROR-101; |
190 | } |
191 | |
192 | /* initially check if this module is a duplicate */ |
193 | memset(&info, 0, sizeof(info)); |
194 | pkcs11_get_module_info (module, &info); |
195 | for (i=0;i<active_providers;i++) |
196 | { |
197 | /* already loaded, skip the rest */ |
198 | if (memcmp(&info, &providers[i].info, sizeof(info)) == 0) |
199 | { |
200 | _gnutls_debug_log("%s is already loaded.\n", name)do { if (__builtin_expect((_gnutls_log_level >= 2), 0)) _gnutls_log ( 2, "%s is already loaded.\n", name); } while(0); |
201 | return GNUTLS_E_INT_RET_0-1251; |
202 | } |
203 | } |
204 | |
205 | active_providers++; |
206 | providers[active_providers - 1].module = module; |
207 | |
208 | /* cache the number of slots in this module */ |
209 | if (pkcs11_get_slot_list |
210 | (providers[active_providers - 1].module, 0, NULL((void*)0), |
211 | &providers[active_providers - 1].nslots) != CKR_OK(0UL)) |
212 | { |
213 | gnutls_assert ()do { if (__builtin_expect((_gnutls_log_level >= 2), 0)) _gnutls_log ( 2, "ASSERT: %s:%d\n", "pkcs11.c",213); } while(0);; |
214 | goto fail; |
215 | } |
216 | |
217 | providers[active_providers - 1].slots = |
218 | gnutls_malloc (sizeof (*providers[active_providers - 1].slots) * |
219 | providers[active_providers - 1].nslots); |
220 | if (providers[active_providers - 1].slots == NULL((void*)0)) |
221 | { |
222 | gnutls_assert ()do { if (__builtin_expect((_gnutls_log_level >= 2), 0)) _gnutls_log ( 2, "ASSERT: %s:%d\n", "pkcs11.c",222); } while(0);; |
223 | goto fail; |
224 | } |
225 | |
226 | if (pkcs11_get_slot_list |
227 | (providers[active_providers - 1].module, 0, |
228 | providers[active_providers - 1].slots, |
229 | &providers[active_providers - 1].nslots) != CKR_OK(0UL)) |
230 | { |
231 | gnutls_assert ()do { if (__builtin_expect((_gnutls_log_level >= 2), 0)) _gnutls_log ( 2, "ASSERT: %s:%d\n", "pkcs11.c",231); } while(0);; |
232 | gnutls_free (providers[active_providers - 1].slots); |
233 | goto fail; |
234 | } |
235 | |
236 | memcpy (&providers[active_providers - 1].info, &info, sizeof(info)); |
237 | |
238 | _gnutls_debug_log ("p11: loaded provider '%s' with %d slots\n",do { if (__builtin_expect((_gnutls_log_level >= 2), 0)) _gnutls_log ( 2, "p11: loaded provider '%s' with %d slots\n", name, (int) providers[active_providers - 1].nslots); } while(0) |
239 | name, (int) providers[active_providers - 1].nslots)do { if (__builtin_expect((_gnutls_log_level >= 2), 0)) _gnutls_log ( 2, "p11: loaded provider '%s' with %d slots\n", name, (int) providers[active_providers - 1].nslots); } while(0); |
240 | |
241 | return 0; |
242 | |
243 | fail: |
244 | active_providers--; |
245 | return GNUTLS_E_PKCS11_LOAD_ERROR-301; |
246 | } |
247 | |
248 | |
249 | /** |
250 | * gnutls_pkcs11_add_provider: |
251 | * @name: The filename of the module |
252 | * @params: should be NULL |
253 | * |
254 | * This function will load and add a PKCS 11 module to the module |
255 | * list used in gnutls. After this function is called the module will |
256 | * be used for PKCS 11 operations. |
257 | * |
258 | * Returns: On success, %GNUTLS_E_SUCCESS (0) is returned, otherwise a |
259 | * negative error value. |
260 | * |
261 | * Since: 2.12.0 |
262 | **/ |
263 | int |
264 | gnutls_pkcs11_add_provider (const char *name, const char *params) |
265 | { |
266 | struct ck_function_list *module; |
267 | int ret; |
268 | |
269 | active_providers++; |
270 | if (p11_kit_load_initialize_module (name, &module) != CKR_OK(0UL)) |
271 | { |
272 | gnutls_assert ()do { if (__builtin_expect((_gnutls_log_level >= 2), 0)) _gnutls_log ( 2, "ASSERT: %s:%d\n", "pkcs11.c",272); } while(0);; |
273 | _gnutls_debug_log ("p11: Cannot load provider %s\n", name)do { if (__builtin_expect((_gnutls_log_level >= 2), 0)) _gnutls_log ( 2, "p11: Cannot load provider %s\n", name); } while(0); |
274 | active_providers--; |
275 | return GNUTLS_E_PKCS11_LOAD_ERROR-301; |
276 | } |
277 | |
278 | ret = pkcs11_add_module (name, module); |
279 | if (ret == 0) |
280 | { |
281 | /* Mark this one as having been separately initialized */ |
282 | providers[active_providers - 1].initialized = 1; |
283 | } |
284 | else |
285 | { |
286 | if (ret == GNUTLS_E_INT_RET_0-1251) ret = 0; |
287 | p11_kit_finalize_module (module); |
288 | gnutls_assert ()do { if (__builtin_expect((_gnutls_log_level >= 2), 0)) _gnutls_log ( 2, "ASSERT: %s:%d\n", "pkcs11.c",288); } while(0);; |
289 | } |
290 | |
291 | return ret; |
292 | } |
293 | |
294 | |
295 | /** |
296 | * gnutls_pkcs11_obj_get_info: |
297 | * @crt: should contain a #gnutls_pkcs11_obj_t structure |
298 | * @itype: Denotes the type of information requested |
299 | * @output: where output will be stored |
300 | * @output_size: contains the maximum size of the output and will be overwritten with actual |
301 | * |
302 | * This function will return information about the PKCS11 certificate |
303 | * such as the label, id as well as token information where the key is |
304 | * stored. When output is text it returns null terminated string |
305 | * although @output_size contains the size of the actual data only. |
306 | * |
307 | * Returns: %GNUTLS_E_SUCCESS (0) on success or a negative error code on error. |
308 | * |
309 | * Since: 2.12.0 |
310 | **/ |
311 | int |
312 | gnutls_pkcs11_obj_get_info (gnutls_pkcs11_obj_t crt, |
313 | gnutls_pkcs11_obj_info_t itype, |
314 | void *output, size_t * output_size) |
315 | { |
316 | return pkcs11_get_info (crt->info, itype, output, output_size); |
317 | } |
318 | |
319 | int |
320 | pkcs11_get_info (struct p11_kit_uri *info, |
321 | gnutls_pkcs11_obj_info_t itype, void *output, |
322 | size_t * output_size) |
323 | { |
324 | struct ck_attribute *attr = NULL((void*)0); |
325 | struct ck_version *version = NULL((void*)0); |
326 | const char *str = NULL((void*)0); |
327 | size_t str_max = 0; |
328 | int terminate = 0; |
329 | int hexify = 0; |
330 | size_t length = 0; |
331 | const char *data = NULL((void*)0); |
332 | char buf[32]; |
333 | |
334 | /* |
335 | * Either attr, str or version is valid by the time switch |
336 | * finishes |
337 | */ |
338 | |
339 | switch (itype) |
340 | { |
341 | case GNUTLS_PKCS11_OBJ_ID: |
342 | attr = p11_kit_uri_get_attribute (info, CKA_ID(0x102UL)); |
343 | break; |
344 | case GNUTLS_PKCS11_OBJ_ID_HEX: |
345 | attr = p11_kit_uri_get_attribute (info, CKA_ID(0x102UL)); |
346 | hexify = 1; |
347 | terminate = 1; |
348 | break; |
349 | case GNUTLS_PKCS11_OBJ_LABEL: |
350 | attr = p11_kit_uri_get_attribute (info, CKA_LABEL(3UL)); |
351 | terminate = 1; |
352 | break; |
353 | case GNUTLS_PKCS11_OBJ_TOKEN_LABEL: |
354 | str = p11_kit_uri_get_token_info (info)->label; |
355 | str_max = 32; |
356 | break; |
357 | case GNUTLS_PKCS11_OBJ_TOKEN_SERIAL: |
358 | str = p11_kit_uri_get_token_info (info)->serial_number; |
359 | str_max = 16; |
360 | break; |
361 | case GNUTLS_PKCS11_OBJ_TOKEN_MANUFACTURER: |
362 | str = p11_kit_uri_get_token_info (info)->manufacturer_id; |
363 | str_max = 32; |
364 | break; |
365 | case GNUTLS_PKCS11_OBJ_TOKEN_MODEL: |
366 | str = p11_kit_uri_get_token_info (info)->model; |
367 | str_max = 16; |
368 | break; |
369 | case GNUTLS_PKCS11_OBJ_LIBRARY_DESCRIPTION: |
370 | str = p11_kit_uri_get_module_info (info)->library_description; |
371 | str_max = 32; |
372 | break; |
373 | case GNUTLS_PKCS11_OBJ_LIBRARY_VERSION: |
374 | version = &p11_kit_uri_get_module_info (info)->library_version; |
375 | break; |
376 | case GNUTLS_PKCS11_OBJ_LIBRARY_MANUFACTURER: |
377 | str = p11_kit_uri_get_module_info (info)->manufacturer_id; |
378 | str_max = 32; |
379 | break; |
380 | default: |
381 | gnutls_assert ()do { if (__builtin_expect((_gnutls_log_level >= 2), 0)) _gnutls_log ( 2, "ASSERT: %s:%d\n", "pkcs11.c",381); } while(0);; |
382 | return GNUTLS_E_INVALID_REQUEST-50; |
383 | } |
384 | |
385 | if (attr != NULL((void*)0)) |
386 | { |
387 | data = attr->value; |
388 | length = attr->value_len; |
389 | } |
390 | else if (str != NULL((void*)0)) |
391 | { |
392 | data = str; |
393 | length = p11_kit_space_strlen (str, str_max); |
394 | terminate = 1; |
395 | } |
396 | else if (version != NULL((void*)0)) |
397 | { |
398 | data = buf; |
399 | length = snprintf (buf, sizeof (buf), "%d.%d", (int)version->major, |
400 | (int)version->minor); |
401 | terminate = 1; |
402 | } |
403 | |
404 | if (hexify) |
405 | { |
406 | /* terminate is assumed with hexify */ |
407 | if (*output_size < length * 3) |
408 | { |
409 | *output_size = length * 3; |
410 | return GNUTLS_E_SHORT_MEMORY_BUFFER-51; |
411 | } |
412 | if (output) |
413 | _gnutls_bin2hex (data, length, output, *output_size, ":"); |
414 | *output_size = length * 3; |
415 | return 0; |
416 | } |
417 | else |
418 | { |
419 | if (*output_size < length + terminate) |
420 | { |
421 | *output_size = length + terminate; |
422 | return GNUTLS_E_SHORT_MEMORY_BUFFER-51; |
423 | } |
424 | if (output) |
425 | { |
426 | memcpy (output, data, length); |
427 | if (terminate) |
428 | ((unsigned char*)output)[length] = '\0'; |
429 | } |
430 | *output_size = length + terminate; |
431 | } |
432 | |
433 | return 0; |
434 | } |
435 | |
436 | static int init = 0; |
437 | |
438 | /* tries to load modules from /etc/gnutls/pkcs11.conf if it exists |
439 | */ |
440 | static void _pkcs11_compat_init(const char* configfile) |
441 | { |
442 | FILE *fp; |
443 | int ret; |
444 | char line[512]; |
445 | const char *library; |
446 | |
447 | if (configfile == NULL((void*)0)) |
448 | configfile = "/etc/gnutls/pkcs11.conf"; |
449 | |
450 | fp = fopen (configfile, "r"); |
451 | if (fp == NULL((void*)0)) |
452 | { |
453 | gnutls_assert ()do { if (__builtin_expect((_gnutls_log_level >= 2), 0)) _gnutls_log ( 2, "ASSERT: %s:%d\n", "pkcs11.c",453); } while(0);; |
454 | return; |
455 | } |
456 | |
457 | _gnutls_debug_log ("Loading PKCS #11 libraries from %s\n", configfile)do { if (__builtin_expect((_gnutls_log_level >= 2), 0)) _gnutls_log ( 2, "Loading PKCS #11 libraries from %s\n", configfile); } while (0); |
458 | while (fgets (line, sizeof (line), fp) != NULL((void*)0)) |
459 | { |
460 | if (strncmp (line, "load", sizeof ("load") - 1) == 0) |
461 | { |
462 | char *p; |
463 | p = strchr (line, '='); |
464 | if (p == NULL((void*)0)) |
465 | continue; |
466 | |
467 | library = ++p; |
468 | p = strchr (line, '\n'); |
469 | if (p != NULL((void*)0)) |
470 | *p = 0; |
471 | |
472 | ret = gnutls_pkcs11_add_provider (library, NULL((void*)0)); |
473 | if (ret < 0) |
474 | { |
475 | gnutls_assert ()do { if (__builtin_expect((_gnutls_log_level >= 2), 0)) _gnutls_log ( 2, "ASSERT: %s:%d\n", "pkcs11.c",475); } while(0);; |
476 | _gnutls_debug_log ("Cannot load provider: %s\n", library)do { if (__builtin_expect((_gnutls_log_level >= 2), 0)) _gnutls_log ( 2, "Cannot load provider: %s\n", library); } while(0); |
477 | continue; |
478 | } |
479 | } |
480 | } |
481 | fclose(fp); |
482 | |
483 | return; |
484 | } |
485 | |
486 | static int |
487 | initialize_automatic_p11_kit (void) |
488 | { |
489 | struct ck_function_list **modules; |
490 | const char *name; |
491 | ck_rv_t rv; |
492 | int i, ret; |
493 | |
494 | rv = p11_kit_initialize_registered (); |
495 | if (rv != CKR_OK(0UL)) |
496 | { |
497 | gnutls_assert ()do { if (__builtin_expect((_gnutls_log_level >= 2), 0)) _gnutls_log ( 2, "ASSERT: %s:%d\n", "pkcs11.c",497); } while(0);; |
498 | _gnutls_debug_log ("Cannot initialize registered module: %s\n",do { if (__builtin_expect((_gnutls_log_level >= 2), 0)) _gnutls_log ( 2, "Cannot initialize registered module: %s\n", p11_kit_strerror (rv)); } while(0) |
499 | p11_kit_strerror (rv))do { if (__builtin_expect((_gnutls_log_level >= 2), 0)) _gnutls_log ( 2, "Cannot initialize registered module: %s\n", p11_kit_strerror (rv)); } while(0); |
500 | return GNUTLS_E_INTERNAL_ERROR-59; |
501 | } |
502 | |
503 | initialized_registered = 1; |
504 | |
505 | modules = p11_kit_registered_modules (); |
506 | for (i = 0; modules[i] != NULL((void*)0); i++) |
507 | { |
508 | name = p11_kit_registered_module_to_name (modules[i]); |
509 | ret = pkcs11_add_module (name, modules[i]); |
510 | if (ret != 0 && ret != GNUTLS_E_INT_RET_0-1251) |
511 | { |
512 | gnutls_assert ()do { if (__builtin_expect((_gnutls_log_level >= 2), 0)) _gnutls_log ( 2, "ASSERT: %s:%d\n", "pkcs11.c",512); } while(0);; |
513 | _gnutls_debug_log ("Cannot add registered module: %s\n", name)do { if (__builtin_expect((_gnutls_log_level >= 2), 0)) _gnutls_log ( 2, "Cannot add registered module: %s\n", name); } while(0); |
514 | } |
515 | } |
516 | |
517 | free (modules); |
518 | return 0; |
519 | } |
520 | |
521 | /** |
522 | * gnutls_pkcs11_init: |
523 | * @flags: %GNUTLS_PKCS11_FLAG_MANUAL or %GNUTLS_PKCS11_FLAG_AUTO |
524 | * @deprecated_config_file: either NULL or the location of a deprecated |
525 | * configuration file |
526 | * |
527 | * This function will initialize the PKCS 11 subsystem in gnutls. It will |
528 | * read configuration files if %GNUTLS_PKCS11_FLAG_AUTO is used or allow |
529 | * you to independently load PKCS 11 modules using gnutls_pkcs11_add_provider() |
530 | * if %GNUTLS_PKCS11_FLAG_MANUAL is specified. |
531 | * |
532 | * Normally you don't need to call this function since it is being called |
533 | * by gnutls_global_init() using the %GNUTLS_PKCS11_FLAG_AUTO. If other option |
534 | * is required then it must be called before it. |
535 | * |
536 | * Returns: On success, %GNUTLS_E_SUCCESS (0) is returned, otherwise a |
537 | * negative error value. |
538 | * |
539 | * Since: 2.12.0 |
540 | **/ |
541 | int |
542 | gnutls_pkcs11_init (unsigned int flags, const char *deprecated_config_file) |
543 | { |
544 | int ret = 0; |
545 | |
546 | if (init != 0) |
547 | { |
548 | init++; |
549 | return 0; |
550 | } |
551 | init++; |
552 | |
553 | if (flags == GNUTLS_PKCS11_FLAG_MANUAL0) |
554 | return 0; |
555 | else if (flags == GNUTLS_PKCS11_FLAG_AUTO1) |
556 | { |
557 | if (deprecated_config_file == NULL((void*)0)) |
558 | ret = initialize_automatic_p11_kit (); |
559 | |
560 | _pkcs11_compat_init(deprecated_config_file); |
561 | |
562 | return ret; |
563 | } |
564 | |
565 | return 0; |
566 | } |
567 | |
568 | /** |
569 | * gnutls_pkcs11_deinit: |
570 | * |
571 | * This function will deinitialize the PKCS 11 subsystem in gnutls. |
572 | * |
573 | * Since: 2.12.0 |
574 | **/ |
575 | void |
576 | gnutls_pkcs11_deinit (void) |
577 | { |
578 | int i; |
579 | |
580 | init--; |
581 | if (init > 0) |
582 | return; |
583 | if (init < 0) |
584 | { |
585 | init = 0; |
586 | return; |
587 | } |
588 | |
589 | for (i = 0; i < active_providers; i++) |
590 | { |
591 | if (providers[i].initialized) |
592 | p11_kit_finalize_module (providers[i].module); |
593 | } |
594 | active_providers = 0; |
595 | |
596 | if (initialized_registered != 0) |
597 | p11_kit_finalize_registered (); |
598 | initialized_registered = 0; |
599 | } |
600 | |
601 | /** |
602 | * gnutls_pkcs11_set_pin_function: |
603 | * @fn: The PIN callback, a gnutls_pkcs11_pin_callback_t() function. |
604 | * @userdata: data to be supplied to callback |
605 | * |
606 | * This function will set a callback function to be used when a PIN is |
607 | * required for PKCS 11 operations. See |
608 | * gnutls_pkcs11_pin_callback_t() on how the callback should behave. |
609 | * |
610 | * Since: 2.12.0 |
611 | **/ |
612 | void |
613 | gnutls_pkcs11_set_pin_function (gnutls_pkcs11_pin_callback_t fn, |
614 | void *userdata) |
615 | { |
616 | pin_func = fn; |
617 | pin_data = userdata; |
618 | } |
619 | |
620 | /** |
621 | * gnutls_pkcs11_set_token_function: |
622 | * @fn: The token callback |
623 | * @userdata: data to be supplied to callback |
624 | * |
625 | * This function will set a callback function to be used when a token |
626 | * needs to be inserted to continue PKCS 11 operations. |
627 | * |
628 | * Since: 2.12.0 |
629 | **/ |
630 | void |
631 | gnutls_pkcs11_set_token_function (gnutls_pkcs11_token_callback_t fn, |
632 | void *userdata) |
633 | { |
634 | token_func = fn; |
635 | token_data = userdata; |
636 | } |
637 | |
638 | int |
639 | pkcs11_url_to_info (const char *url, struct p11_kit_uri **info) |
640 | { |
641 | int allocated = 0; |
642 | int ret; |
643 | |
644 | if (*info == NULL((void*)0)) |
645 | { |
646 | *info = p11_kit_uri_new (); |
647 | if (*info == NULL((void*)0)) |
648 | { |
649 | gnutls_assert ()do { if (__builtin_expect((_gnutls_log_level >= 2), 0)) _gnutls_log ( 2, "ASSERT: %s:%d\n", "pkcs11.c",649); } while(0);; |
650 | return GNUTLS_E_MEMORY_ERROR-25; |
651 | } |
652 | allocated = 1; |
653 | } |
654 | |
655 | ret = p11_kit_uri_parse (url, P11_KIT_URI_FOR_ANY, *info); |
656 | if (ret < 0) |
657 | { |
658 | if (allocated) |
659 | { |
660 | p11_kit_uri_free (*info); |
661 | *info = NULL((void*)0); |
662 | } |
663 | gnutls_assert ()do { if (__builtin_expect((_gnutls_log_level >= 2), 0)) _gnutls_log ( 2, "ASSERT: %s:%d\n", "pkcs11.c",663); } while(0);; |
664 | return ret == P11_KIT_URI_NO_MEMORY ? |
665 | GNUTLS_E_MEMORY_ERROR-25 : GNUTLS_E_PARSING_ERROR-302; |
666 | } |
667 | |
668 | return 0; |
669 | } |
670 | |
671 | int |
672 | pkcs11_info_to_url (struct p11_kit_uri *info, |
673 | gnutls_pkcs11_url_type_t detailed, char **url) |
674 | { |
675 | p11_kit_uri_type_t type = 0; |
676 | int ret; |
677 | |
678 | switch (detailed) |
679 | { |
680 | case GNUTLS_PKCS11_URL_GENERIC: |
681 | type = P11_KIT_URI_FOR_OBJECT_ON_TOKEN; |
682 | break; |
683 | case GNUTLS_PKCS11_URL_LIB: |
684 | type = P11_KIT_URI_FOR_OBJECT_ON_TOKEN_AND_MODULE; |
685 | break; |
686 | case GNUTLS_PKCS11_URL_LIB_VERSION: |
687 | type = P11_KIT_URI_FOR_OBJECT_ON_TOKEN_AND_MODULE | P11_KIT_URI_FOR_MODULE_WITH_VERSION; |
688 | break; |
689 | } |
690 | |
691 | ret = p11_kit_uri_format (info, type, url); |
692 | if (ret < 0) |
693 | { |
694 | gnutls_assert ()do { if (__builtin_expect((_gnutls_log_level >= 2), 0)) _gnutls_log ( 2, "ASSERT: %s:%d\n", "pkcs11.c",694); } while(0);; |
695 | return ret == P11_KIT_URI_NO_MEMORY ? |
696 | GNUTLS_E_MEMORY_ERROR-25 : GNUTLS_E_INTERNAL_ERROR-59; |
697 | } |
698 | |
699 | return 0; |
700 | } |
701 | |
702 | /** |
703 | * gnutls_pkcs11_obj_init: |
704 | * @obj: The structure to be initialized |
705 | * |
706 | * This function will initialize a pkcs11 certificate structure. |
707 | * |
708 | * Returns: On success, %GNUTLS_E_SUCCESS (0) is returned, otherwise a |
709 | * negative error value. |
710 | * |
711 | * Since: 2.12.0 |
712 | **/ |
713 | int |
714 | gnutls_pkcs11_obj_init (gnutls_pkcs11_obj_t * obj) |
715 | { |
716 | *obj = gnutls_calloc (1, sizeof (struct gnutls_pkcs11_obj_st)); |
717 | if (*obj == NULL((void*)0)) |
718 | { |
719 | gnutls_assert ()do { if (__builtin_expect((_gnutls_log_level >= 2), 0)) _gnutls_log ( 2, "ASSERT: %s:%d\n", "pkcs11.c",719); } while(0);; |
720 | return GNUTLS_E_MEMORY_ERROR-25; |
721 | } |
722 | |
723 | (*obj)->info = p11_kit_uri_new (); |
724 | if ((*obj)->info == NULL((void*)0)) |
725 | { |
726 | free (*obj); |
727 | gnutls_assert ()do { if (__builtin_expect((_gnutls_log_level >= 2), 0)) _gnutls_log ( 2, "ASSERT: %s:%d\n", "pkcs11.c",727); } while(0);; |
728 | return GNUTLS_E_MEMORY_ERROR-25; |
729 | } |
730 | |
731 | return 0; |
732 | } |
733 | |
734 | /** |
735 | * gnutls_pkcs11_obj_deinit: |
736 | * @obj: The structure to be initialized |
737 | * |
738 | * This function will deinitialize a certificate structure. |
739 | * |
740 | * Since: 2.12.0 |
741 | **/ |
742 | void |
743 | gnutls_pkcs11_obj_deinit (gnutls_pkcs11_obj_t obj) |
744 | { |
745 | _gnutls_free_datum (&obj->raw)_gnutls_free_datum_m(&obj->raw, gnutls_free); |
746 | p11_kit_uri_free (obj->info); |
747 | free (obj); |
748 | } |
749 | |
750 | /** |
751 | * gnutls_pkcs11_obj_export: |
752 | * @obj: Holds the object |
753 | * @output_data: will contain a certificate PEM or DER encoded |
754 | * @output_data_size: holds the size of output_data (and will be |
755 | * replaced by the actual size of parameters) |
756 | * |
757 | * This function will export the PKCS11 object data. It is normal for |
758 | * data to be inaccesible and in that case %GNUTLS_E_INVALID_REQUEST |
759 | * will be returned. |
760 | * |
761 | * If the buffer provided is not long enough to hold the output, then |
762 | * *output_data_size is updated and GNUTLS_E_SHORT_MEMORY_BUFFER will |
763 | * be returned. |
764 | * |
765 | * If the structure is PEM encoded, it will have a header |
766 | * of "BEGIN CERTIFICATE". |
767 | * |
768 | * Returns: In case of failure a negative error code will be |
769 | * returned, and %GNUTLS_E_SUCCESS (0) on success. |
770 | * |
771 | * Since: 2.12.0 |
772 | **/ |
773 | int |
774 | gnutls_pkcs11_obj_export (gnutls_pkcs11_obj_t obj, |
775 | void *output_data, size_t * output_data_size) |
776 | { |
777 | if (obj == NULL((void*)0) || obj->raw.data == NULL((void*)0)) |
778 | { |
779 | gnutls_assert ()do { if (__builtin_expect((_gnutls_log_level >= 2), 0)) _gnutls_log ( 2, "ASSERT: %s:%d\n", "pkcs11.c",779); } while(0);; |
780 | return GNUTLS_E_INVALID_REQUEST-50; |
781 | } |
782 | |
783 | if (output_data == NULL((void*)0) || *output_data_size < obj->raw.size) |
784 | { |
785 | *output_data_size = obj->raw.size; |
786 | gnutls_assert ()do { if (__builtin_expect((_gnutls_log_level >= 2), 0)) _gnutls_log ( 2, "ASSERT: %s:%d\n", "pkcs11.c",786); } while(0);; |
787 | return GNUTLS_E_SHORT_MEMORY_BUFFER-51; |
788 | } |
789 | *output_data_size = obj->raw.size; |
790 | |
791 | memcpy (output_data, obj->raw.data, obj->raw.size); |
792 | return 0; |
793 | } |
794 | |
795 | int |
796 | pkcs11_find_object (struct ck_function_list ** _module, |
797 | ck_session_handle_t * _pks, |
798 | ck_object_handle_t * _obj, |
799 | struct p11_kit_uri *info, unsigned int flags) |
800 | { |
801 | int ret; |
802 | struct ck_function_list *module; |
803 | ck_session_handle_t pks; |
804 | ck_object_handle_t obj; |
805 | struct ck_attribute *attrs; |
806 | unsigned long attr_count; |
807 | unsigned long count; |
808 | ck_rv_t rv; |
809 | |
810 | ret = pkcs11_open_session (&module, &pks, info, flags & SESSION_LOGIN(1<<1)); |
811 | if (ret < 0) |
812 | { |
813 | gnutls_assert ()do { if (__builtin_expect((_gnutls_log_level >= 2), 0)) _gnutls_log ( 2, "ASSERT: %s:%d\n", "pkcs11.c",813); } while(0);; |
814 | return ret; |
815 | } |
816 | |
817 | attrs = p11_kit_uri_get_attributes (info, &attr_count); |
818 | rv = pkcs11_find_objects_init (module, pks, attrs, attr_count); |
819 | if (rv != CKR_OK(0UL)) |
820 | { |
821 | gnutls_assert ()do { if (__builtin_expect((_gnutls_log_level >= 2), 0)) _gnutls_log ( 2, "ASSERT: %s:%d\n", "pkcs11.c",821); } while(0);; |
822 | _gnutls_debug_log ("pk11: FindObjectsInit failed.\n")do { if (__builtin_expect((_gnutls_log_level >= 2), 0)) _gnutls_log ( 2, "pk11: FindObjectsInit failed.\n"); } while(0); |
823 | ret = pkcs11_rv_to_err (rv); |
824 | goto fail; |
825 | } |
826 | |
827 | if (pkcs11_find_objects (module, pks, &obj, 1, &count) == CKR_OK(0UL) && count == 1) |
828 | { |
829 | *_obj = obj; |
830 | *_pks = pks; |
831 | *_module = module; |
832 | pkcs11_find_objects_final (module, pks); |
833 | return 0; |
834 | } |
835 | |
836 | ret = GNUTLS_E_REQUESTED_DATA_NOT_AVAILABLE-56; |
837 | pkcs11_find_objects_final (module, pks); |
838 | fail: |
839 | pkcs11_close_session (module, pks); |
840 | |
841 | return ret; |
842 | } |
843 | |
844 | int |
845 | pkcs11_find_slot (struct ck_function_list ** module, ck_slot_id_t * slot, |
846 | struct p11_kit_uri *info, struct token_info *_tinfo) |
847 | { |
848 | int x, z; |
849 | |
850 | for (x = 0; x < active_providers; x++) |
851 | { |
852 | for (z = 0; z < providers[x].nslots; z++) |
853 | { |
854 | struct token_info tinfo; |
855 | |
856 | if (pkcs11_get_token_info |
857 | (providers[x].module, providers[x].slots[z], |
858 | &tinfo.tinfo) != CKR_OK(0UL)) |
859 | { |
860 | continue; |
861 | } |
862 | tinfo.sid = providers[x].slots[z]; |
863 | tinfo.prov = &providers[x]; |
864 | |
865 | if (pkcs11_get_slot_info |
866 | (providers[x].module, providers[x].slots[z], |
867 | &tinfo.sinfo) != CKR_OK(0UL)) |
868 | { |
869 | continue; |
870 | } |
871 | |
872 | if (!p11_kit_uri_match_token_info (info, &tinfo.tinfo) || |
873 | !p11_kit_uri_match_module_info (info, &providers[x].info)) |
874 | { |
875 | continue; |
876 | } |
877 | |
878 | /* ok found */ |
879 | *module = providers[x].module; |
880 | *slot = providers[x].slots[z]; |
881 | |
882 | if (_tinfo != NULL((void*)0)) |
883 | memcpy (_tinfo, &tinfo, sizeof (tinfo)); |
884 | |
885 | return 0; |
886 | } |
887 | } |
888 | |
889 | gnutls_assert ()do { if (__builtin_expect((_gnutls_log_level >= 2), 0)) _gnutls_log ( 2, "ASSERT: %s:%d\n", "pkcs11.c",889); } while(0);; |
890 | return GNUTLS_E_PKCS11_REQUESTED_OBJECT_NOT_AVAILBLE-323; |
891 | } |
892 | |
893 | int |
894 | pkcs11_open_session (struct ck_function_list ** _module, ck_session_handle_t * _pks, |
895 | struct p11_kit_uri *info, unsigned int flags) |
896 | { |
897 | ck_rv_t rv; |
898 | int ret; |
899 | ck_session_handle_t pks = 0; |
900 | struct ck_function_list *module; |
901 | ck_slot_id_t slot; |
902 | struct token_info tinfo; |
903 | |
904 | ret = pkcs11_find_slot (&module, &slot, info, &tinfo); |
905 | if (ret < 0) |
906 | { |
907 | gnutls_assert ()do { if (__builtin_expect((_gnutls_log_level >= 2), 0)) _gnutls_log ( 2, "ASSERT: %s:%d\n", "pkcs11.c",907); } while(0);; |
908 | return ret; |
909 | } |
910 | |
911 | rv = (module)->C_OpenSession (slot, |
912 | ((flags & SESSION_WRITE(1<<0)) |
913 | ? CKF_RW_SESSION(1UL << 1) : 0) | |
914 | CKF_SERIAL_SESSION(1UL << 2), NULL((void*)0), NULL((void*)0), &pks); |
915 | if (rv != CKR_OK(0UL)) |
916 | { |
917 | gnutls_assert ()do { if (__builtin_expect((_gnutls_log_level >= 2), 0)) _gnutls_log ( 2, "ASSERT: %s:%d\n", "pkcs11.c",917); } while(0);; |
918 | return pkcs11_rv_to_err (rv); |
919 | } |
920 | |
921 | if (flags & SESSION_LOGIN(1<<1)) |
922 | { |
923 | ret = pkcs11_login (module, pks, &tinfo, info, (flags & SESSION_SO(1<<2)) ? 1 : 0); |
924 | if (ret < 0) |
925 | { |
926 | gnutls_assert ()do { if (__builtin_expect((_gnutls_log_level >= 2), 0)) _gnutls_log ( 2, "ASSERT: %s:%d\n", "pkcs11.c",926); } while(0);; |
927 | pkcs11_close_session (module, pks); |
928 | return ret; |
929 | } |
930 | } |
931 | |
932 | /* ok found */ |
933 | *_pks = pks; |
934 | *_module = module; |
935 | return 0; |
936 | } |
937 | |
938 | |
939 | int |
940 | _pkcs11_traverse_tokens (find_func_t find_func, void *input, |
941 | struct p11_kit_uri *info, unsigned int flags) |
942 | { |
943 | ck_rv_t rv; |
944 | int found = 0, x, z, ret; |
945 | ck_session_handle_t pks = 0; |
946 | struct ck_function_list *module = NULL((void*)0); |
947 | |
948 | for (x = 0; x < active_providers; x++) |
949 | { |
950 | module = providers[x].module; |
951 | for (z = 0; z < providers[x].nslots; z++) |
952 | { |
953 | struct token_info tinfo; |
954 | |
955 | ret = GNUTLS_E_PKCS11_ERROR-300; |
Value stored to 'ret' is never read | |
956 | |
957 | if (pkcs11_get_token_info (module, providers[x].slots[z], |
958 | &tinfo.tinfo) != CKR_OK(0UL)) |
959 | { |
960 | continue; |
961 | } |
962 | tinfo.sid = providers[x].slots[z]; |
963 | tinfo.prov = &providers[x]; |
964 | |
965 | if (pkcs11_get_slot_info (module, providers[x].slots[z], |
966 | &tinfo.sinfo) != CKR_OK(0UL)) |
967 | { |
968 | continue; |
969 | } |
970 | |
971 | rv = (module)->C_OpenSession (providers[x].slots[z], |
972 | ((flags & SESSION_WRITE(1<<0)) |
973 | ? CKF_RW_SESSION(1UL << 1) : 0) | |
974 | CKF_SERIAL_SESSION(1UL << 2), NULL((void*)0), NULL((void*)0), &pks); |
975 | if (rv != CKR_OK(0UL)) |
976 | { |
977 | continue; |
978 | } |
979 | |
980 | if (flags & SESSION_LOGIN(1<<1)) |
981 | { |
982 | ret = pkcs11_login (module, pks, &tinfo, info, (flags & SESSION_SO(1<<2)) ? 1 : 0); |
983 | if (ret < 0) |
984 | { |
985 | gnutls_assert ()do { if (__builtin_expect((_gnutls_log_level >= 2), 0)) _gnutls_log ( 2, "ASSERT: %s:%d\n", "pkcs11.c",985); } while(0);; |
986 | return ret; |
987 | } |
988 | } |
989 | |
990 | ret = find_func (module, pks, &tinfo, &providers[x].info, input); |
991 | |
992 | if (ret == 0) |
993 | { |
994 | found = 1; |
995 | goto finish; |
996 | } |
997 | else |
998 | { |
999 | pkcs11_close_session (module, pks); |
1000 | pks = 0; |
1001 | } |
1002 | } |
1003 | } |
1004 | |
1005 | finish: |
1006 | /* final call */ |
1007 | |
1008 | if (found == 0) |
1009 | { |
1010 | if (module) |
1011 | ret = find_func (module, pks, NULL((void*)0), NULL((void*)0), input); |
1012 | else |
1013 | ret = gnutls_assert_val(GNUTLS_E_REQUESTED_DATA_NOT_AVAILABLE)gnutls_assert_val_int(-56, "pkcs11.c", 1013); |
1014 | } |
1015 | else |
1016 | { |
1017 | ret = 0; |
1018 | } |
1019 | |
1020 | if (pks != 0 && module != NULL((void*)0)) |
1021 | { |
1022 | pkcs11_close_session (module, pks); |
1023 | } |
1024 | |
1025 | return ret; |
1026 | } |
1027 | |
1028 | /* imports a raw certificate from a token to a pkcs11_obj_t structure. |
1029 | */ |
1030 | static int |
1031 | pkcs11_obj_import (ck_object_class_t class, gnutls_pkcs11_obj_t obj, |
1032 | const gnutls_datum_t * data, |
1033 | const gnutls_datum_t * id, |
1034 | const gnutls_datum_t * label, |
1035 | struct ck_token_info *tinfo, struct ck_info *lib_info) |
1036 | { |
1037 | struct ck_attribute attr; |
1038 | int ret; |
1039 | |
1040 | switch (class) |
1041 | { |
1042 | case CKO_CERTIFICATE(1UL): |
1043 | obj->type = GNUTLS_PKCS11_OBJ_X509_CRT; |
1044 | break; |
1045 | case CKO_PUBLIC_KEY(2UL): |
1046 | obj->type = GNUTLS_PKCS11_OBJ_PUBKEY; |
1047 | break; |
1048 | case CKO_PRIVATE_KEY(3UL): |
1049 | obj->type = GNUTLS_PKCS11_OBJ_PRIVKEY; |
1050 | break; |
1051 | case CKO_SECRET_KEY(4UL): |
1052 | obj->type = GNUTLS_PKCS11_OBJ_SECRET_KEY; |
1053 | break; |
1054 | case CKO_DATA(0UL): |
1055 | obj->type = GNUTLS_PKCS11_OBJ_DATA; |
1056 | break; |
1057 | default: |
1058 | obj->type = GNUTLS_PKCS11_OBJ_UNKNOWN; |
1059 | } |
1060 | |
1061 | attr.type = CKA_CLASS(0UL); |
1062 | attr.value = &class; |
1063 | attr.value_len = sizeof (class); |
1064 | ret = p11_kit_uri_set_attribute (obj->info, &attr); |
1065 | if (ret < 0) |
1066 | { |
1067 | gnutls_assert ()do { if (__builtin_expect((_gnutls_log_level >= 2), 0)) _gnutls_log ( 2, "ASSERT: %s:%d\n", "pkcs11.c",1067); } while(0);; |
1068 | return GNUTLS_E_MEMORY_ERROR-25; |
1069 | } |
1070 | |
1071 | if (data && data->data) |
1072 | { |
1073 | ret = _gnutls_set_datum (&obj->raw, data->data, data->size)_gnutls_set_datum_m(&obj->raw,data->data,data->size , gnutls_malloc); |
1074 | if (ret < 0) |
1075 | { |
1076 | gnutls_assert ()do { if (__builtin_expect((_gnutls_log_level >= 2), 0)) _gnutls_log ( 2, "ASSERT: %s:%d\n", "pkcs11.c",1076); } while(0);; |
1077 | return ret; |
1078 | } |
1079 | } |
1080 | |
1081 | /* copy the token and library info into the uri */ |
1082 | memcpy (p11_kit_uri_get_token_info (obj->info), tinfo, sizeof (struct ck_token_info)); |
1083 | memcpy (p11_kit_uri_get_module_info (obj->info), lib_info, sizeof (struct ck_info)); |
1084 | |
1085 | if (label && label->data) |
1086 | { |
1087 | attr.type = CKA_LABEL(3UL); |
1088 | attr.value = label->data; |
1089 | attr.value_len = label->size; |
1090 | ret = p11_kit_uri_set_attribute (obj->info, &attr); |
1091 | if (ret < 0) |
1092 | { |
1093 | gnutls_assert ()do { if (__builtin_expect((_gnutls_log_level >= 2), 0)) _gnutls_log ( 2, "ASSERT: %s:%d\n", "pkcs11.c",1093); } while(0);; |
1094 | return GNUTLS_E_MEMORY_ERROR-25; |
1095 | } |
1096 | } |
1097 | |
1098 | if (id && id->data) |
1099 | { |
1100 | attr.type = CKA_ID(0x102UL); |
1101 | attr.value = id->data; |
1102 | attr.value_len = id->size; |
1103 | ret = p11_kit_uri_set_attribute (obj->info, &attr); |
1104 | if (ret < 0) |
1105 | { |
1106 | gnutls_assert ()do { if (__builtin_expect((_gnutls_log_level >= 2), 0)) _gnutls_log ( 2, "ASSERT: %s:%d\n", "pkcs11.c",1106); } while(0);; |
1107 | return GNUTLS_E_MEMORY_ERROR-25; |
1108 | } |
1109 | } |
1110 | |
1111 | return 0; |
1112 | } |
1113 | |
1114 | static int read_pkcs11_pubkey(struct ck_function_list *module, |
1115 | ck_session_handle_t pks, ck_object_handle_t obj, |
1116 | ck_key_type_t key_type, gnutls_datum_t * pubkey) |
1117 | { |
1118 | struct ck_attribute a[4]; |
1119 | opaque tmp1[2048]; |
1120 | opaque tmp2[2048]; |
1121 | int ret; |
1122 | |
1123 | switch (key_type) |
1124 | { |
1125 | case CKK_RSA(0UL): |
1126 | a[0].type = CKA_MODULUS(0x120UL); |
1127 | a[0].value = tmp1; |
1128 | a[0].value_len = sizeof (tmp1); |
1129 | a[1].type = CKA_PUBLIC_EXPONENT(0x122UL); |
1130 | a[1].value = tmp2; |
1131 | a[1].value_len = sizeof (tmp2); |
1132 | |
1133 | if (pkcs11_get_attribute_value (module, pks, obj, a, 2) == CKR_OK(0UL)) |
1134 | { |
1135 | |
1136 | ret = |
1137 | _gnutls_set_datum (&pubkey[0],_gnutls_set_datum_m(&pubkey[0],a[0].value,a[0].value_len, gnutls_malloc) |
1138 | a[0].value, a[0].value_len)_gnutls_set_datum_m(&pubkey[0],a[0].value,a[0].value_len, gnutls_malloc); |
1139 | |
1140 | if (ret >= 0) |
1141 | ret = |
1142 | _gnutls_set_datum (&pubkey_gnutls_set_datum_m(&pubkey [1],a[1].value,a[1].value_len , gnutls_malloc) |
1143 | [1], a[1].value, a[1].value_len)_gnutls_set_datum_m(&pubkey [1],a[1].value,a[1].value_len , gnutls_malloc); |
1144 | |
1145 | if (ret < 0) |
1146 | { |
1147 | gnutls_assert ()do { if (__builtin_expect((_gnutls_log_level >= 2), 0)) _gnutls_log ( 2, "ASSERT: %s:%d\n", "pkcs11.c",1147); } while(0);; |
1148 | _gnutls_free_datum (&pubkey[1])_gnutls_free_datum_m(&pubkey[1], gnutls_free); |
1149 | _gnutls_free_datum (&pubkey[0])_gnutls_free_datum_m(&pubkey[0], gnutls_free); |
1150 | return GNUTLS_E_MEMORY_ERROR-25; |
1151 | } |
1152 | } |
1153 | else |
1154 | { |
1155 | gnutls_assert ()do { if (__builtin_expect((_gnutls_log_level >= 2), 0)) _gnutls_log ( 2, "ASSERT: %s:%d\n", "pkcs11.c",1155); } while(0);; |
1156 | return GNUTLS_E_PKCS11_ERROR-300; |
1157 | } |
1158 | break; |
1159 | case CKK_DSA(1UL): |
1160 | a[0].type = CKA_PRIME(0x130UL); |
1161 | a[0].value = tmp1; |
1162 | a[0].value_len = sizeof (tmp1); |
1163 | a[1].type = CKA_SUBPRIME(0x131UL); |
1164 | a[1].value = tmp2; |
1165 | a[1].value_len = sizeof (tmp2); |
1166 | |
1167 | if (pkcs11_get_attribute_value (module, pks, obj, a, 2) == CKR_OK(0UL)) |
1168 | { |
1169 | ret = |
1170 | _gnutls_set_datum (&pubkey[0],_gnutls_set_datum_m(&pubkey[0],a[0].value,a[0].value_len, gnutls_malloc) |
1171 | a[0].value, a[0].value_len)_gnutls_set_datum_m(&pubkey[0],a[0].value,a[0].value_len, gnutls_malloc); |
1172 | |
1173 | if (ret >= 0) |
1174 | ret = |
1175 | _gnutls_set_datum (&pubkey_gnutls_set_datum_m(&pubkey [1],a[1].value,a[1].value_len , gnutls_malloc) |
1176 | [1], a[1].value, a[1].value_len)_gnutls_set_datum_m(&pubkey [1],a[1].value,a[1].value_len , gnutls_malloc); |
1177 | |
1178 | if (ret < 0) |
1179 | { |
1180 | gnutls_assert ()do { if (__builtin_expect((_gnutls_log_level >= 2), 0)) _gnutls_log ( 2, "ASSERT: %s:%d\n", "pkcs11.c",1180); } while(0);; |
1181 | _gnutls_free_datum (&pubkey[1])_gnutls_free_datum_m(&pubkey[1], gnutls_free); |
1182 | _gnutls_free_datum (&pubkey[0])_gnutls_free_datum_m(&pubkey[0], gnutls_free); |
1183 | return GNUTLS_E_MEMORY_ERROR-25; |
1184 | } |
1185 | } |
1186 | else |
1187 | { |
1188 | gnutls_assert ()do { if (__builtin_expect((_gnutls_log_level >= 2), 0)) _gnutls_log ( 2, "ASSERT: %s:%d\n", "pkcs11.c",1188); } while(0);; |
1189 | return GNUTLS_E_PKCS11_ERROR-300; |
1190 | } |
1191 | |
1192 | a[0].type = CKA_BASE(0x132UL); |
1193 | a[0].value = tmp1; |
1194 | a[0].value_len = sizeof (tmp1); |
1195 | a[1].type = CKA_VALUE(0x11UL); |
1196 | a[1].value = tmp2; |
1197 | a[1].value_len = sizeof (tmp2); |
1198 | |
1199 | if (pkcs11_get_attribute_value (module, pks, obj, a, 2) == CKR_OK(0UL)) |
1200 | { |
1201 | ret = |
1202 | _gnutls_set_datum (&pubkey[2],_gnutls_set_datum_m(&pubkey[2],a[0].value,a[0].value_len, gnutls_malloc) |
1203 | a[0].value, a[0].value_len)_gnutls_set_datum_m(&pubkey[2],a[0].value,a[0].value_len, gnutls_malloc); |
1204 | |
1205 | if (ret >= 0) |
1206 | ret = |
1207 | _gnutls_set_datum (&pubkey_gnutls_set_datum_m(&pubkey [3],a[1].value,a[1].value_len , gnutls_malloc) |
1208 | [3], a[1].value, a[1].value_len)_gnutls_set_datum_m(&pubkey [3],a[1].value,a[1].value_len , gnutls_malloc); |
1209 | |
1210 | if (ret < 0) |
1211 | { |
1212 | gnutls_assert ()do { if (__builtin_expect((_gnutls_log_level >= 2), 0)) _gnutls_log ( 2, "ASSERT: %s:%d\n", "pkcs11.c",1212); } while(0);; |
1213 | _gnutls_free_datum (&pubkey[0])_gnutls_free_datum_m(&pubkey[0], gnutls_free); |
1214 | _gnutls_free_datum (&pubkey[1])_gnutls_free_datum_m(&pubkey[1], gnutls_free); |
1215 | _gnutls_free_datum (&pubkey[2])_gnutls_free_datum_m(&pubkey[2], gnutls_free); |
1216 | _gnutls_free_datum (&pubkey[3])_gnutls_free_datum_m(&pubkey[3], gnutls_free); |
1217 | return GNUTLS_E_MEMORY_ERROR-25; |
1218 | } |
1219 | } |
1220 | else |
1221 | { |
1222 | gnutls_assert ()do { if (__builtin_expect((_gnutls_log_level >= 2), 0)) _gnutls_log ( 2, "ASSERT: %s:%d\n", "pkcs11.c",1222); } while(0);; |
1223 | return GNUTLS_E_PKCS11_ERROR-300; |
1224 | } |
1225 | break; |
1226 | case CKK_ECDSA(3UL): |
1227 | a[0].type = CKA_EC_PARAMS(0x180UL); |
1228 | a[0].value = tmp1; |
1229 | a[0].value_len = sizeof (tmp1); |
1230 | a[1].type = CKA_EC_POINT(0x181UL); |
1231 | a[1].value = tmp2; |
1232 | a[1].value_len = sizeof (tmp2); |
1233 | |
1234 | if (pkcs11_get_attribute_value (module, pks, obj, a, 2) == CKR_OK(0UL)) |
1235 | { |
1236 | ret = |
1237 | _gnutls_set_datum (&pubkey[0],_gnutls_set_datum_m(&pubkey[0],a[0].value,a[0].value_len, gnutls_malloc) |
1238 | a[0].value, a[0].value_len)_gnutls_set_datum_m(&pubkey[0],a[0].value,a[0].value_len, gnutls_malloc); |
1239 | |
1240 | if (ret >= 0) |
1241 | ret = |
1242 | _gnutls_set_datum (&pubkey_gnutls_set_datum_m(&pubkey [1],a[1].value,a[1].value_len , gnutls_malloc) |
1243 | [1], a[1].value, a[1].value_len)_gnutls_set_datum_m(&pubkey [1],a[1].value,a[1].value_len , gnutls_malloc); |
1244 | |
1245 | if (ret < 0) |
1246 | { |
1247 | gnutls_assert ()do { if (__builtin_expect((_gnutls_log_level >= 2), 0)) _gnutls_log ( 2, "ASSERT: %s:%d\n", "pkcs11.c",1247); } while(0);; |
1248 | _gnutls_free_datum (&pubkey[1])_gnutls_free_datum_m(&pubkey[1], gnutls_free); |
1249 | _gnutls_free_datum (&pubkey[0])_gnutls_free_datum_m(&pubkey[0], gnutls_free); |
1250 | return GNUTLS_E_MEMORY_ERROR-25; |
1251 | } |
1252 | } |
1253 | else |
1254 | { |
1255 | gnutls_assert ()do { if (__builtin_expect((_gnutls_log_level >= 2), 0)) _gnutls_log ( 2, "ASSERT: %s:%d\n", "pkcs11.c",1255); } while(0);; |
1256 | return GNUTLS_E_PKCS11_ERROR-300; |
1257 | } |
1258 | |
1259 | break; |
1260 | default: |
1261 | return gnutls_assert_val(GNUTLS_E_UNIMPLEMENTED_FEATURE)gnutls_assert_val_int(-1250, "pkcs11.c", 1261); |
1262 | } |
1263 | |
1264 | return 0; |
1265 | } |
1266 | |
1267 | static int |
1268 | pkcs11_obj_import_pubkey (struct ck_function_list *module, |
1269 | ck_session_handle_t pks, |
1270 | ck_object_handle_t obj, |
1271 | gnutls_pkcs11_obj_t crt, |
1272 | const gnutls_datum_t * id, |
1273 | const gnutls_datum_t * label, |
1274 | struct ck_token_info *tinfo, |
1275 | struct ck_info *lib_info) |
1276 | { |
1277 | struct ck_attribute a[4]; |
1278 | ck_key_type_t key_type; |
1279 | int ret; |
1280 | ck_bool_t tval; |
1281 | |
1282 | a[0].type = CKA_KEY_TYPE(0x100UL); |
1283 | a[0].value = &key_type; |
1284 | a[0].value_len = sizeof (key_type); |
1285 | |
1286 | if (pkcs11_get_attribute_value (module, pks, obj, a, 1) == CKR_OK(0UL)) |
1287 | { |
1288 | crt->pk_algorithm = mech_to_pk(key_type); |
1289 | |
1290 | ret = read_pkcs11_pubkey(module, pks, obj, key_type, crt->pubkey); |
1291 | if (ret < 0) |
1292 | return gnutls_assert_val(ret)gnutls_assert_val_int(ret, "pkcs11.c", 1292); |
1293 | } |
1294 | |
1295 | /* read key usage flags */ |
1296 | a[0].type = CKA_ENCRYPT(0x104UL); |
1297 | a[0].value = &tval; |
1298 | a[0].value_len = sizeof (tval); |
1299 | |
1300 | if (pkcs11_get_attribute_value (module, pks, obj, a, 1) == CKR_OK(0UL)) |
1301 | { |
1302 | if (tval != 0) |
1303 | { |
1304 | crt->key_usage |= GNUTLS_KEY_DATA_ENCIPHERMENT16; |
1305 | } |
1306 | } |
1307 | |
1308 | a[0].type = CKA_VERIFY(0x10aUL); |
1309 | a[0].value = &tval; |
1310 | a[0].value_len = sizeof (tval); |
1311 | |
1312 | if (pkcs11_get_attribute_value (module, pks, obj, a, 1) == CKR_OK(0UL)) |
1313 | { |
1314 | if (tval != 0) |
1315 | { |
1316 | crt->key_usage |= GNUTLS_KEY_DIGITAL_SIGNATURE128 | |
1317 | GNUTLS_KEY_KEY_CERT_SIGN4 | GNUTLS_KEY_CRL_SIGN2 |
1318 | | GNUTLS_KEY_NON_REPUDIATION64; |
1319 | } |
1320 | } |
1321 | |
1322 | a[0].type = CKA_VERIFY_RECOVER(0x10bUL); |
1323 | a[0].value = &tval; |
1324 | a[0].value_len = sizeof (tval); |
1325 | |
1326 | if (pkcs11_get_attribute_value (module, pks, obj, a, 1) == CKR_OK(0UL)) |
1327 | { |
1328 | if (tval != 0) |
1329 | { |
1330 | crt->key_usage |= GNUTLS_KEY_DIGITAL_SIGNATURE128 | |
1331 | GNUTLS_KEY_KEY_CERT_SIGN4 | GNUTLS_KEY_CRL_SIGN2 |
1332 | | GNUTLS_KEY_NON_REPUDIATION64; |
1333 | } |
1334 | } |
1335 | |
1336 | a[0].type = CKA_DERIVE(0x10cUL); |
1337 | a[0].value = &tval; |
1338 | a[0].value_len = sizeof (tval); |
1339 | |
1340 | if (pkcs11_get_attribute_value (module, pks, obj, a, 1) == CKR_OK(0UL)) |
1341 | { |
1342 | if (tval != 0) |
1343 | { |
1344 | crt->key_usage |= GNUTLS_KEY_KEY_AGREEMENT8; |
1345 | } |
1346 | } |
1347 | |
1348 | a[0].type = CKA_WRAP(0x106UL); |
1349 | a[0].value = &tval; |
1350 | a[0].value_len = sizeof (tval); |
1351 | |
1352 | if (pkcs11_get_attribute_value (module, pks, obj, a, 1) == CKR_OK(0UL)) |
1353 | { |
1354 | if (tval != 0) |
1355 | { |
1356 | crt->key_usage |= GNUTLS_KEY_KEY_ENCIPHERMENT32; |
1357 | } |
1358 | } |
1359 | |
1360 | return pkcs11_obj_import (CKO_PUBLIC_KEY(2UL), crt, NULL((void*)0), id, label, |
1361 | tinfo, lib_info); |
1362 | } |
1363 | |
1364 | static int |
1365 | find_obj_url (struct ck_function_list *module, ck_session_handle_t pks, |
1366 | struct token_info *info, struct ck_info *lib_info, void *input) |
1367 | { |
1368 | struct url_find_data_st *find_data = input; |
1369 | struct ck_attribute a[4]; |
1370 | struct ck_attribute *attr; |
1371 | ck_object_class_t class = -1; |
1372 | ck_certificate_type_t type = -1; |
1373 | ck_rv_t rv; |
1374 | ck_object_handle_t obj; |
1375 | unsigned long count, a_vals; |
1376 | int found = 0, ret; |
1377 | opaque *cert_data = NULL((void*)0); |
1378 | char label_tmp[PKCS11_LABEL_SIZE128]; |
1379 | |
1380 | if (info == NULL((void*)0)) |
1381 | { /* we don't support multiple calls */ |
1382 | gnutls_assert ()do { if (__builtin_expect((_gnutls_log_level >= 2), 0)) _gnutls_log ( 2, "ASSERT: %s:%d\n", "pkcs11.c",1382); } while(0);; |
1383 | return GNUTLS_E_REQUESTED_DATA_NOT_AVAILABLE-56; |
1384 | } |
1385 | |
1386 | /* do not bother reading the token if basic fields do not match |
1387 | */ |
1388 | if (!p11_kit_uri_match_token_info (find_data->crt->info, &info->tinfo) || |
1389 | !p11_kit_uri_match_module_info (find_data->crt->info, lib_info)) |
1390 | { |
1391 | gnutls_assert ()do { if (__builtin_expect((_gnutls_log_level >= 2), 0)) _gnutls_log ( 2, "ASSERT: %s:%d\n", "pkcs11.c",1391); } while(0);; |
1392 | return GNUTLS_E_REQUESTED_DATA_NOT_AVAILABLE-56; |
1393 | } |
1394 | |
1395 | attr = p11_kit_uri_get_attribute (find_data->crt->info, CKA_ID(0x102UL)); |
1396 | if (attr == NULL((void*)0)) |
1397 | { |
1398 | gnutls_assert ()do { if (__builtin_expect((_gnutls_log_level >= 2), 0)) _gnutls_log ( 2, "ASSERT: %s:%d\n", "pkcs11.c",1398); } while(0);; |
1399 | return GNUTLS_E_INVALID_REQUEST-50; |
1400 | } |
1401 | |
1402 | /* search the token for the id */ |
1403 | |
1404 | cert_data = gnutls_malloc (MAX_CERT_SIZE8*1024); |
1405 | if (cert_data == NULL((void*)0)) |
1406 | { |
1407 | gnutls_assert ()do { if (__builtin_expect((_gnutls_log_level >= 2), 0)) _gnutls_log ( 2, "ASSERT: %s:%d\n", "pkcs11.c",1407); } while(0);; |
1408 | return GNUTLS_E_MEMORY_ERROR-25; |
1409 | } |
1410 | |
1411 | /* Find objects with given class and type */ |
1412 | memcpy (a, attr, sizeof (struct ck_attribute)); |
1413 | a_vals = 1; |
1414 | |
1415 | attr = p11_kit_uri_get_attribute (find_data->crt->info, CKA_CLASS(0UL)); |
1416 | if (attr) |
1417 | { |
1418 | if(attr->value && attr->value_len == sizeof (ck_object_class_t)) |
1419 | class = *((ck_object_class_t*)attr->value); |
1420 | if (class == CKO_CERTIFICATE(1UL)) |
1421 | type = CKC_X_509(0UL); |
1422 | memcpy (a + a_vals, attr, sizeof (struct ck_attribute)); |
1423 | a_vals++; |
1424 | } |
1425 | |
1426 | if (type != -1) |
1427 | { |
1428 | a[a_vals].type = CKA_CERTIFICATE_TYPE(0x80UL); |
1429 | a[a_vals].value = &type; |
1430 | a[a_vals].value_len = sizeof type; |
1431 | a_vals++; |
1432 | } |
1433 | |
1434 | rv = pkcs11_find_objects_init (module, pks, a, a_vals); |
1435 | if (rv != CKR_OK(0UL)) |
1436 | { |
1437 | gnutls_assert ()do { if (__builtin_expect((_gnutls_log_level >= 2), 0)) _gnutls_log ( 2, "ASSERT: %s:%d\n", "pkcs11.c",1437); } while(0);; |
1438 | _gnutls_debug_log ("pk11: FindObjectsInit failed.\n")do { if (__builtin_expect((_gnutls_log_level >= 2), 0)) _gnutls_log ( 2, "pk11: FindObjectsInit failed.\n"); } while(0); |
1439 | ret = pkcs11_rv_to_err (rv); |
1440 | goto cleanup; |
1441 | } |
1442 | |
1443 | while (pkcs11_find_objects (module, pks, &obj, 1, &count) == CKR_OK(0UL) && count == 1) |
1444 | { |
1445 | |
1446 | a[0].type = CKA_VALUE(0x11UL); |
1447 | a[0].value = cert_data; |
1448 | a[0].value_len = MAX_CERT_SIZE8*1024; |
1449 | a[1].type = CKA_LABEL(3UL); |
1450 | a[1].value = label_tmp; |
1451 | a[1].value_len = sizeof (label_tmp); |
1452 | |
1453 | if (pkcs11_get_attribute_value (module, pks, obj, a, 2) == CKR_OK(0UL)) |
1454 | { |
1455 | gnutls_datum_t id; |
1456 | gnutls_datum_t data = { a[0].value, a[0].value_len }; |
1457 | gnutls_datum_t label = { a[1].value, a[1].value_len }; |
1458 | |
1459 | attr = p11_kit_uri_get_attribute (find_data->crt->info, CKA_ID(0x102UL)); |
1460 | id.data = attr->value; |
1461 | id.size = attr->value_len; |
1462 | |
1463 | if (class == CKO_PUBLIC_KEY(2UL)) |
1464 | { |
1465 | ret = |
1466 | pkcs11_obj_import_pubkey (module, pks, obj, |
1467 | find_data->crt, |
1468 | &id, &label, |
1469 | &info->tinfo, lib_info); |
1470 | } |
1471 | else |
1472 | { |
1473 | ret = |
1474 | pkcs11_obj_import (class, |
1475 | find_data->crt, |
1476 | &data, &id, &label, |
1477 | &info->tinfo, lib_info); |
1478 | } |
1479 | if (ret < 0) |
1480 | { |
1481 | gnutls_assert ()do { if (__builtin_expect((_gnutls_log_level >= 2), 0)) _gnutls_log ( 2, "ASSERT: %s:%d\n", "pkcs11.c",1481); } while(0);; |
1482 | goto cleanup; |
1483 | } |
1484 | |
1485 | found = 1; |
1486 | break; |
1487 | } |
1488 | else |
1489 | { |
1490 | _gnutls_debug_log ("pk11: Skipped cert, missing attrs.\n")do { if (__builtin_expect((_gnutls_log_level >= 2), 0)) _gnutls_log ( 2, "pk11: Skipped cert, missing attrs.\n"); } while(0); |
1491 | } |
1492 | } |
1493 | |
1494 | if (found == 0) |
1495 | { |
1496 | gnutls_assert ()do { if (__builtin_expect((_gnutls_log_level >= 2), 0)) _gnutls_log ( 2, "ASSERT: %s:%d\n", "pkcs11.c",1496); } while(0);; |
1497 | ret = GNUTLS_E_REQUESTED_DATA_NOT_AVAILABLE-56; |
1498 | } |
1499 | else |
1500 | { |
1501 | ret = 0; |
1502 | } |
1503 | |
1504 | cleanup: |
1505 | gnutls_free (cert_data); |
1506 | pkcs11_find_objects_final (module, pks); |
1507 | |
1508 | return ret; |
1509 | } |
1510 | |
1511 | unsigned int |
1512 | pkcs11_obj_flags_to_int (unsigned int flags) |
1513 | { |
1514 | unsigned int ret_flags = 0; |
1515 | |
1516 | if (flags & GNUTLS_PKCS11_OBJ_FLAG_LOGIN(1<<0)) |
1517 | ret_flags |= SESSION_LOGIN(1<<1); |
1518 | if (flags & GNUTLS_PKCS11_OBJ_FLAG_LOGIN_SO(1<<3)) |
1519 | ret_flags |= SESSION_LOGIN(1<<1)|SESSION_SO(1<<2); |
1520 | |
1521 | return ret_flags; |
1522 | } |
1523 | |
1524 | /** |
1525 | * gnutls_pkcs11_obj_import_url: |
1526 | * @cert: The structure to store the parsed certificate |
1527 | * @url: a PKCS 11 url identifying the key |
1528 | * @flags: One of GNUTLS_PKCS11_OBJ_* flags |
1529 | * |
1530 | * This function will "import" a PKCS 11 URL identifying a certificate |
1531 | * key to the #gnutls_pkcs11_obj_t structure. This does not involve any |
1532 | * parsing (such as X.509 or OpenPGP) since the #gnutls_pkcs11_obj_t is |
1533 | * format agnostic. Only data are transferred. |
1534 | * |
1535 | * Returns: On success, %GNUTLS_E_SUCCESS (0) is returned, otherwise a |
1536 | * negative error value. |
1537 | * |
1538 | * Since: 2.12.0 |
1539 | **/ |
1540 | int |
1541 | gnutls_pkcs11_obj_import_url (gnutls_pkcs11_obj_t cert, const char *url, |
1542 | unsigned int flags) |
1543 | { |
1544 | int ret; |
1545 | struct url_find_data_st find_data; |
1546 | |
1547 | /* fill in the find data structure */ |
1548 | find_data.crt = cert; |
1549 | |
1550 | ret = pkcs11_url_to_info (url, &cert->info); |
1551 | if (ret < 0) |
1552 | { |
1553 | gnutls_assert ()do { if (__builtin_expect((_gnutls_log_level >= 2), 0)) _gnutls_log ( 2, "ASSERT: %s:%d\n", "pkcs11.c",1553); } while(0);; |
1554 | return ret; |
1555 | } |
1556 | |
1557 | ret = |
1558 | _pkcs11_traverse_tokens (find_obj_url, &find_data, cert->info, |
1559 | pkcs11_obj_flags_to_int (flags)); |
1560 | |
1561 | if (ret < 0) |
1562 | { |
1563 | gnutls_assert ()do { if (__builtin_expect((_gnutls_log_level >= 2), 0)) _gnutls_log ( 2, "ASSERT: %s:%d\n", "pkcs11.c",1563); } while(0);; |
1564 | return ret; |
1565 | } |
1566 | |
1567 | return 0; |
1568 | } |
1569 | |
1570 | struct token_num |
1571 | { |
1572 | struct p11_kit_uri *info; |
1573 | unsigned int seq; /* which one we are looking for */ |
1574 | unsigned int current; /* which one are we now */ |
1575 | }; |
1576 | |
1577 | static int |
1578 | find_token_num (struct ck_function_list *module, |
1579 | ck_session_handle_t pks, |
1580 | struct token_info *tinfo, |
1581 | struct ck_info *lib_info, void *input) |
1582 | { |
1583 | struct token_num *find_data = input; |
1584 | |
1585 | if (tinfo == NULL((void*)0)) |
1586 | { /* we don't support multiple calls */ |
1587 | gnutls_assert ()do { if (__builtin_expect((_gnutls_log_level >= 2), 0)) _gnutls_log ( 2, "ASSERT: %s:%d\n", "pkcs11.c",1587); } while(0);; |
1588 | return GNUTLS_E_REQUESTED_DATA_NOT_AVAILABLE-56; |
1589 | } |
1590 | |
1591 | if (find_data->current == find_data->seq) |
1592 | { |
1593 | memcpy (p11_kit_uri_get_token_info (find_data->info), &tinfo->tinfo, sizeof (struct ck_token_info)); |
1594 | memcpy (p11_kit_uri_get_module_info (find_data->info), lib_info, sizeof (struct ck_info)); |
1595 | return 0; |
1596 | } |
1597 | |
1598 | find_data->current++; |
1599 | /* search the token for the id */ |
1600 | |
1601 | |
1602 | return GNUTLS_E_REQUESTED_DATA_NOT_AVAILABLE-56; /* non zero is enough */ |
1603 | } |
1604 | |
1605 | /** |
1606 | * gnutls_pkcs11_token_get_url: |
1607 | * @seq: sequence number starting from 0 |
1608 | * @detailed: non zero if a detailed URL is required |
1609 | * @url: will contain an allocated url |
1610 | * |
1611 | * This function will return the URL for each token available |
1612 | * in system. The url has to be released using gnutls_free() |
1613 | * |
1614 | * Returns: On success, %GNUTLS_E_SUCCESS (0) is returned, |
1615 | * %GNUTLS_E_REQUESTED_DATA_NOT_AVAILABLE if the sequence number |
1616 | * exceeds the available tokens, otherwise a negative error value. |
1617 | * |
1618 | * Since: 2.12.0 |
1619 | **/ |
1620 | int |
1621 | gnutls_pkcs11_token_get_url (unsigned int seq, |
1622 | gnutls_pkcs11_url_type_t detailed, char **url) |
1623 | { |
1624 | int ret; |
1625 | struct token_num tn; |
1626 | |
1627 | memset (&tn, 0, sizeof (tn)); |
1628 | tn.seq = seq; |
1629 | tn.info = p11_kit_uri_new (); |
1630 | |
1631 | ret = _pkcs11_traverse_tokens (find_token_num, &tn, NULL((void*)0), 0); |
1632 | if (ret < 0) |
1633 | { |
1634 | p11_kit_uri_free (tn.info); |
1635 | gnutls_assert ()do { if (__builtin_expect((_gnutls_log_level >= 2), 0)) _gnutls_log ( 2, "ASSERT: %s:%d\n", "pkcs11.c",1635); } while(0);; |
1636 | return ret; |
1637 | } |
1638 | |
1639 | ret = pkcs11_info_to_url (tn.info, detailed, url); |
1640 | p11_kit_uri_free (tn.info); |
1641 | |
1642 | if (ret < 0) |
1643 | { |
1644 | gnutls_assert ()do { if (__builtin_expect((_gnutls_log_level >= 2), 0)) _gnutls_log ( 2, "ASSERT: %s:%d\n", "pkcs11.c",1644); } while(0);; |
1645 | return ret; |
1646 | } |
1647 | |
1648 | return 0; |
1649 | |
1650 | } |
1651 | |
1652 | /** |
1653 | * gnutls_pkcs11_token_get_info: |
1654 | * @url: should contain a PKCS 11 URL |
1655 | * @ttype: Denotes the type of information requested |
1656 | * @output: where output will be stored |
1657 | * @output_size: contains the maximum size of the output and will be overwritten with actual |
1658 | * |
1659 | * This function will return information about the PKCS 11 token such |
1660 | * as the label, id, etc. |
1661 | * |
1662 | * Returns: %GNUTLS_E_SUCCESS (0) on success or a negative error code |
1663 | * on error. |
1664 | * |
1665 | * Since: 2.12.0 |
1666 | **/ |
1667 | int |
1668 | gnutls_pkcs11_token_get_info (const char *url, |
1669 | gnutls_pkcs11_token_info_t ttype, |
1670 | void *output, size_t * output_size) |
1671 | { |
1672 | struct p11_kit_uri *info = NULL((void*)0); |
1673 | const char *str; |
1674 | size_t str_max; |
1675 | size_t len; |
1676 | int ret; |
1677 | |
1678 | ret = pkcs11_url_to_info (url, &info); |
1679 | if (ret < 0) |
1680 | { |
1681 | gnutls_assert ()do { if (__builtin_expect((_gnutls_log_level >= 2), 0)) _gnutls_log ( 2, "ASSERT: %s:%d\n", "pkcs11.c",1681); } while(0);; |
1682 | return ret; |
1683 | } |
1684 | |
1685 | switch (ttype) |
1686 | { |
1687 | case GNUTLS_PKCS11_TOKEN_LABEL: |
1688 | str = p11_kit_uri_get_token_info (info)->label; |
1689 | str_max = 32; |
1690 | break; |
1691 | case GNUTLS_PKCS11_TOKEN_SERIAL: |
1692 | str = p11_kit_uri_get_token_info (info)->serial_number; |
1693 | str_max = 16; |
1694 | break; |
1695 | case GNUTLS_PKCS11_TOKEN_MANUFACTURER: |
1696 | str = p11_kit_uri_get_token_info (info)->manufacturer_id; |
1697 | str_max = 32; |
1698 | break; |
1699 | case GNUTLS_PKCS11_TOKEN_MODEL: |
1700 | str = p11_kit_uri_get_token_info (info)->model; |
1701 | str_max = 16; |
1702 | break; |
1703 | default: |
1704 | p11_kit_uri_free (info); |
1705 | gnutls_assert ()do { if (__builtin_expect((_gnutls_log_level >= 2), 0)) _gnutls_log ( 2, "ASSERT: %s:%d\n", "pkcs11.c",1705); } while(0);; |
1706 | return GNUTLS_E_INVALID_REQUEST-50; |
1707 | } |
1708 | |
1709 | len = p11_kit_space_strlen (str, str_max); |
1710 | |
1711 | if (len + 1 > *output_size) |
1712 | { |
1713 | *output_size = len + 1; |
1714 | return GNUTLS_E_SHORT_MEMORY_BUFFER-51; |
1715 | } |
1716 | |
1717 | memcpy (output, str, len); |
1718 | ((char*)output)[len] = '\0'; |
1719 | |
1720 | *output_size = len; |
1721 | |
1722 | p11_kit_uri_free (info); |
1723 | return 0; |
1724 | } |
1725 | |
1726 | /** |
1727 | * gnutls_pkcs11_obj_export_url: |
1728 | * @obj: Holds the PKCS 11 certificate |
1729 | * @detailed: non zero if a detailed URL is required |
1730 | * @url: will contain an allocated url |
1731 | * |
1732 | * This function will export a URL identifying the given certificate. |
1733 | * |
1734 | * Returns: On success, %GNUTLS_E_SUCCESS (0) is returned, otherwise a |
1735 | * negative error value. |
1736 | * |
1737 | * Since: 2.12.0 |
1738 | **/ |
1739 | int |
1740 | gnutls_pkcs11_obj_export_url (gnutls_pkcs11_obj_t obj, |
1741 | gnutls_pkcs11_url_type_t detailed, char **url) |
1742 | { |
1743 | int ret; |
1744 | |
1745 | ret = pkcs11_info_to_url (obj->info, detailed, url); |
1746 | if (ret < 0) |
1747 | { |
1748 | gnutls_assert ()do { if (__builtin_expect((_gnutls_log_level >= 2), 0)) _gnutls_log ( 2, "ASSERT: %s:%d\n", "pkcs11.c",1748); } while(0);; |
1749 | return ret; |
1750 | } |
1751 | |
1752 | return 0; |
1753 | } |
1754 | |
1755 | /** |
1756 | * gnutls_pkcs11_obj_get_type: |
1757 | * @obj: Holds the PKCS 11 object |
1758 | * |
1759 | * This function will return the type of the certificate being |
1760 | * stored in the structure. |
1761 | * |
1762 | * Returns: The type of the certificate. |
1763 | * |
1764 | * Since: 2.12.0 |
1765 | **/ |
1766 | gnutls_pkcs11_obj_type_t |
1767 | gnutls_pkcs11_obj_get_type (gnutls_pkcs11_obj_t obj) |
1768 | { |
1769 | return obj->type; |
1770 | } |
1771 | |
1772 | struct pkey_list |
1773 | { |
1774 | gnutls_buffer_st *key_ids; |
1775 | size_t key_ids_size; |
1776 | }; |
1777 | |
1778 | |
1779 | static int |
1780 | retrieve_pin_for_pinfile (const char *pinfile, struct ck_token_info *token_info, |
1781 | int attempts, ck_user_type_t user_type, struct p11_kit_pin **pin) |
1782 | { |
1783 | unsigned int flags = 0; |
1784 | struct p11_kit_uri *token_uri; |
1785 | struct p11_kit_pin *result; |
1786 | char *label; |
1787 | |
1788 | label = p11_kit_space_strdup (token_info->label, sizeof (token_info->label)); |
1789 | if (label == NULL((void*)0)) |
1790 | { |
1791 | gnutls_assert ()do { if (__builtin_expect((_gnutls_log_level >= 2), 0)) _gnutls_log ( 2, "ASSERT: %s:%d\n", "pkcs11.c",1791); } while(0);; |
1792 | return GNUTLS_E_MEMORY_ERROR-25; |
1793 | } |
1794 | |
1795 | token_uri = p11_kit_uri_new (); |
1796 | if (token_uri == NULL((void*)0)) |
1797 | { |
1798 | free (label); |
1799 | gnutls_assert ()do { if (__builtin_expect((_gnutls_log_level >= 2), 0)) _gnutls_log ( 2, "ASSERT: %s:%d\n", "pkcs11.c",1799); } while(0);; |
1800 | return GNUTLS_E_MEMORY_ERROR-25; |
1801 | } |
1802 | |
1803 | memcpy (p11_kit_uri_get_token_info (token_uri), token_info, |
1804 | sizeof (struct ck_token_info)); |
1805 | |
1806 | if (attempts) |
1807 | flags |= P11_KIT_PIN_FLAGS_RETRY; |
1808 | if (user_type == CKU_USER(1UL)) |
1809 | { |
1810 | flags |= P11_KIT_PIN_FLAGS_USER_LOGIN; |
1811 | if (token_info->flags & CKF_USER_PIN_COUNT_LOW(1UL << 16)) |
1812 | flags |= P11_KIT_PIN_FLAGS_MANY_TRIES; |
1813 | if (token_info->flags & CKF_USER_PIN_FINAL_TRY(1UL << 17)) |
1814 | flags |= P11_KIT_PIN_FLAGS_FINAL_TRY; |
1815 | } |
1816 | else if (user_type == CKU_SO(0UL)) |
1817 | { |
1818 | flags |= P11_KIT_PIN_FLAGS_SO_LOGIN; |
1819 | if (token_info->flags & CKF_SO_PIN_COUNT_LOW(1UL << 20)) |
1820 | flags |= P11_KIT_PIN_FLAGS_MANY_TRIES; |
1821 | if (token_info->flags & CKF_SO_PIN_FINAL_TRY(1UL << 21)) |
1822 | flags |= P11_KIT_PIN_FLAGS_FINAL_TRY; |
1823 | } |
1824 | else if (user_type == CKU_CONTEXT_SPECIFIC(2UL)) |
1825 | { |
1826 | flags |= P11_KIT_PIN_FLAGS_CONTEXT_LOGIN; |
1827 | } |
1828 | |
1829 | result = p11_kit_pin_request (pinfile, token_uri, label, flags); |
1830 | p11_kit_uri_free (token_uri); |
1831 | free (label); |
1832 | |
1833 | if (result == NULL((void*)0)) |
1834 | { |
1835 | gnutls_assert ()do { if (__builtin_expect((_gnutls_log_level >= 2), 0)) _gnutls_log ( 2, "ASSERT: %s:%d\n", "pkcs11.c",1835); } while(0);; |
1836 | return GNUTLS_E_PKCS11_PIN_ERROR-303; |
1837 | } |
1838 | |
1839 | *pin = result; |
1840 | return 0; |
1841 | } |
1842 | |
1843 | static int |
1844 | retrieve_pin_for_callback (struct ck_token_info *token_info, int attempts, |
1845 | ck_user_type_t user_type, struct p11_kit_pin **pin) |
1846 | { |
1847 | char pin_value[GNUTLS_PKCS11_MAX_PIN_LEN32]; |
1848 | unsigned int flags = 0; |
1849 | char *token_str; |
1850 | char *label; |
1851 | struct p11_kit_uri *token_uri; |
1852 | int ret = 0; |
1853 | |
1854 | label = p11_kit_space_strdup (token_info->label, sizeof (token_info->label)); |
1855 | if (label == NULL((void*)0)) |
1856 | { |
1857 | gnutls_assert ()do { if (__builtin_expect((_gnutls_log_level >= 2), 0)) _gnutls_log ( 2, "ASSERT: %s:%d\n", "pkcs11.c",1857); } while(0);; |
1858 | return GNUTLS_E_MEMORY_ERROR-25; |
1859 | } |
1860 | |
1861 | token_uri = p11_kit_uri_new (); |
1862 | if (token_uri == NULL((void*)0)) |
1863 | { |
1864 | free (label); |
1865 | gnutls_assert ()do { if (__builtin_expect((_gnutls_log_level >= 2), 0)) _gnutls_log ( 2, "ASSERT: %s:%d\n", "pkcs11.c",1865); } while(0);; |
1866 | return GNUTLS_E_MEMORY_ERROR-25; |
1867 | } |
1868 | |
1869 | memcpy (p11_kit_uri_get_token_info (token_uri), token_info, |
1870 | sizeof (struct ck_token_info)); |
1871 | ret = pkcs11_info_to_url (token_uri, 1, &token_str); |
1872 | p11_kit_uri_free (token_uri); |
1873 | |
1874 | if (ret < 0) |
1875 | { |
1876 | free (label); |
1877 | gnutls_assert ()do { if (__builtin_expect((_gnutls_log_level >= 2), 0)) _gnutls_log ( 2, "ASSERT: %s:%d\n", "pkcs11.c",1877); } while(0);; |
1878 | return GNUTLS_E_MEMORY_ERROR-25; |
1879 | } |
1880 | |
1881 | if (user_type == CKU_USER(1UL)) |
1882 | { |
1883 | flags |= GNUTLS_PKCS11_PIN_USER; |
1884 | if (token_info->flags & CKF_USER_PIN_COUNT_LOW(1UL << 16)) |
1885 | flags |= GNUTLS_PKCS11_PIN_COUNT_LOW; |
1886 | if (token_info->flags & CKF_USER_PIN_FINAL_TRY(1UL << 17)) |
1887 | flags |= GNUTLS_PKCS11_PIN_FINAL_TRY; |
1888 | } |
1889 | else if (user_type == CKU_SO(0UL)) |
1890 | { |
1891 | flags |= GNUTLS_PKCS11_PIN_SO; |
1892 | if (token_info->flags & CKF_SO_PIN_COUNT_LOW(1UL << 20)) |
1893 | flags |= GNUTLS_PKCS11_PIN_COUNT_LOW; |
1894 | if (token_info->flags & CKF_SO_PIN_FINAL_TRY(1UL << 21)) |
1895 | flags |= GNUTLS_PKCS11_PIN_FINAL_TRY; |
1896 | } |
1897 | |
1898 | if (attempts > 0) |
1899 | flags |= GNUTLS_PKCS11_PIN_WRONG; |
1900 | |
1901 | ret = pin_func (pin_data, attempts, (char*)token_str, label, |
1902 | flags, pin_value, GNUTLS_PKCS11_MAX_PIN_LEN32); |
1903 | free (token_str); |
1904 | free (label); |
1905 | |
1906 | if (ret < 0) |
1907 | return gnutls_assert_val(GNUTLS_E_PKCS11_PIN_ERROR)gnutls_assert_val_int(-303, "pkcs11.c", 1907); |
1908 | |
1909 | *pin = p11_kit_pin_new_for_string (pin_value); |
1910 | |
1911 | if (*pin == NULL((void*)0)) |
1912 | return gnutls_assert_val(GNUTLS_E_INTERNAL_ERROR)gnutls_assert_val_int(-59, "pkcs11.c", 1912); |
1913 | |
1914 | return 0; |
1915 | } |
1916 | |
1917 | static int |
1918 | retrieve_pin (struct p11_kit_uri *info, struct ck_token_info *token_info, |
1919 | int attempts, ck_user_type_t user_type, struct p11_kit_pin **pin) |
1920 | { |
1921 | const char *pinfile; |
1922 | |
1923 | *pin = NULL((void*)0); |
1924 | |
1925 | /* Check if a pinfile is specified, and use that if possible */ |
1926 | pinfile = p11_kit_uri_get_pinfile (info); |
1927 | if (pinfile != NULL((void*)0)) |
1928 | { |
1929 | _gnutls_debug_log("pk11: Using pinfile to retrieve PIN\n")do { if (__builtin_expect((_gnutls_log_level >= 2), 0)) _gnutls_log ( 2, "pk11: Using pinfile to retrieve PIN\n"); } while(0); |
1930 | return retrieve_pin_for_pinfile (pinfile, token_info, attempts, user_type, pin); |
1931 | } |
1932 | |
1933 | /* The global gnutls pin callback */ |
1934 | else if (pin_func) |
1935 | return retrieve_pin_for_callback (token_info, attempts, user_type, pin); |
1936 | |
1937 | /* Otherwise, PIN entry is necessary for login, so fail if there's |
1938 | * no callback. */ |
1939 | else |
1940 | { |
1941 | gnutls_assert ()do { if (__builtin_expect((_gnutls_log_level >= 2), 0)) _gnutls_log ( 2, "ASSERT: %s:%d\n", "pkcs11.c",1941); } while(0);; |
1942 | _gnutls_debug_log ("pk11: No pin callback but login required.\n")do { if (__builtin_expect((_gnutls_log_level >= 2), 0)) _gnutls_log ( 2, "pk11: No pin callback but login required.\n"); } while( 0); |
1943 | return GNUTLS_E_PKCS11_ERROR-300; |
1944 | } |
1945 | } |
1946 | |
1947 | int |
1948 | pkcs11_login (struct ck_function_list * module, ck_session_handle_t pks, |
1949 | const struct token_info *tokinfo, struct p11_kit_uri *info, int so) |
1950 | { |
1951 | struct ck_session_info session_info; |
1952 | int attempt = 0, ret; |
1953 | ck_user_type_t user_type; |
1954 | ck_rv_t rv; |
1955 | |
1956 | user_type = (so == 0) ? CKU_USER(1UL) : CKU_SO(0UL); |
1957 | if (so == 0 && (tokinfo->tinfo.flags & CKF_LOGIN_REQUIRED(1UL << 2)) == 0) |
1958 | { |
1959 | gnutls_assert ()do { if (__builtin_expect((_gnutls_log_level >= 2), 0)) _gnutls_log ( 2, "ASSERT: %s:%d\n", "pkcs11.c",1959); } while(0);; |
1960 | _gnutls_debug_log ("pk11: No login required.\n")do { if (__builtin_expect((_gnutls_log_level >= 2), 0)) _gnutls_log ( 2, "pk11: No login required.\n"); } while(0); |
1961 | return 0; |
1962 | } |
1963 | |
1964 | /* For a token with a "protected" (out-of-band) authentication |
1965 | * path, calling login with a NULL username is all that is |
1966 | * required. */ |
1967 | if (tokinfo->tinfo.flags & CKF_PROTECTED_AUTHENTICATION_PATH(1UL << 8)) |
1968 | { |
1969 | rv = (module)->C_Login (pks, (so == 0) ? CKU_USER(1UL) : CKU_SO(0UL), NULL((void*)0), 0); |
1970 | if (rv == CKR_OK(0UL) || rv == CKR_USER_ALREADY_LOGGED_IN(0x100UL)) |
1971 | { |
1972 | return 0; |
1973 | } |
1974 | else |
1975 | { |
1976 | gnutls_assert ()do { if (__builtin_expect((_gnutls_log_level >= 2), 0)) _gnutls_log ( 2, "ASSERT: %s:%d\n", "pkcs11.c",1976); } while(0);; |
1977 | _gnutls_debug_log ("pk11: Protected login failed.\n")do { if (__builtin_expect((_gnutls_log_level >= 2), 0)) _gnutls_log ( 2, "pk11: Protected login failed.\n"); } while(0); |
1978 | ret = GNUTLS_E_PKCS11_ERROR-300; |
1979 | goto cleanup; |
1980 | } |
1981 | } |
1982 | |
1983 | do |
1984 | { |
1985 | struct p11_kit_pin *pin; |
1986 | struct ck_token_info tinfo; |
1987 | |
1988 | memcpy (&tinfo, &tokinfo->tinfo, sizeof(tinfo)); |
1989 | |
1990 | /* Check whether the session is already logged in, and if so, just skip */ |
1991 | rv = (module)->C_GetSessionInfo (pks, &session_info); |
1992 | if (rv == CKR_OK(0UL) && (session_info.state == CKS_RO_USER_FUNCTIONS(1UL) || |
1993 | session_info.state == CKS_RW_USER_FUNCTIONS(3UL))) |
1994 | { |
1995 | ret = 0; |
1996 | goto cleanup; |
1997 | } |
1998 | |
1999 | /* If login has been attempted once already, check the token |
2000 | * status again, the flags might change. */ |
2001 | if (attempt) |
2002 | { |
2003 | if (pkcs11_get_token_info |
2004 | (tokinfo->prov->module, tokinfo->sid, &tinfo) != CKR_OK(0UL)) |
2005 | { |
2006 | gnutls_assert ()do { if (__builtin_expect((_gnutls_log_level >= 2), 0)) _gnutls_log ( 2, "ASSERT: %s:%d\n", "pkcs11.c",2006); } while(0);; |
2007 | _gnutls_debug_log ("pk11: GetTokenInfo failed\n")do { if (__builtin_expect((_gnutls_log_level >= 2), 0)) _gnutls_log ( 2, "pk11: GetTokenInfo failed\n"); } while(0); |
2008 | ret = GNUTLS_E_PKCS11_ERROR-300; |
2009 | goto cleanup; |
2010 | } |
2011 | } |
2012 | |
2013 | ret = retrieve_pin (info, &tinfo, attempt++, user_type, &pin); |
2014 | if (ret < 0) |
2015 | { |
2016 | gnutls_assert ()do { if (__builtin_expect((_gnutls_log_level >= 2), 0)) _gnutls_log ( 2, "ASSERT: %s:%d\n", "pkcs11.c",2016); } while(0);; |
2017 | goto cleanup; |
2018 | } |
2019 | |
2020 | rv = (module)->C_Login (pks, user_type, |
2021 | (unsigned char *)p11_kit_pin_get_value (pin, NULL((void*)0)), |
2022 | p11_kit_pin_get_length (pin)); |
2023 | |
2024 | p11_kit_pin_unref (pin); |
2025 | } |
2026 | while (rv == CKR_PIN_INCORRECT(0xa0UL)); |
2027 | |
2028 | _gnutls_debug_log ("pk11: Login result = %lu\n", rv)do { if (__builtin_expect((_gnutls_log_level >= 2), 0)) _gnutls_log ( 2, "pk11: Login result = %lu\n", rv); } while(0); |
2029 | |
2030 | |
2031 | ret = (rv == CKR_OK(0UL) |
2032 | || rv == CKR_USER_ALREADY_LOGGED_IN(0x100UL)) ? 0 : pkcs11_rv_to_err (rv); |
2033 | |
2034 | cleanup: |
2035 | return ret; |
2036 | } |
2037 | |
2038 | int |
2039 | pkcs11_call_token_func (struct p11_kit_uri *info, const unsigned retry) |
2040 | { |
2041 | struct ck_token_info *tinfo; |
2042 | char *label; |
2043 | int ret = 0; |
2044 | |
2045 | tinfo = p11_kit_uri_get_token_info (info); |
2046 | label = p11_kit_space_strdup (tinfo->label, sizeof (tinfo->label)); |
2047 | ret = (token_func) (token_data, label, retry); |
2048 | free (label); |
2049 | |
2050 | return ret; |
2051 | } |
2052 | |
2053 | |
2054 | static int |
2055 | find_privkeys (struct ck_function_list *module, ck_session_handle_t pks, |
2056 | struct token_info *info, struct pkey_list *list) |
2057 | { |
2058 | struct ck_attribute a[3]; |
2059 | ck_object_class_t class; |
2060 | ck_rv_t rv; |
2061 | ck_object_handle_t obj; |
2062 | unsigned long count, current; |
2063 | char certid_tmp[PKCS11_ID_SIZE128]; |
2064 | |
2065 | class = CKO_PRIVATE_KEY(3UL); |
2066 | |
2067 | /* Find an object with private key class and a certificate ID |
2068 | * which matches the certificate. */ |
2069 | /* FIXME: also match the cert subject. */ |
2070 | a[0].type = CKA_CLASS(0UL); |
2071 | a[0].value = &class; |
2072 | a[0].value_len = sizeof class; |
2073 | |
2074 | rv = pkcs11_find_objects_init (module, pks, a, 1); |
2075 | if (rv != CKR_OK(0UL)) |
2076 | { |
2077 | gnutls_assert ()do { if (__builtin_expect((_gnutls_log_level >= 2), 0)) _gnutls_log ( 2, "ASSERT: %s:%d\n", "pkcs11.c",2077); } while(0);; |
2078 | return pkcs11_rv_to_err (rv); |
2079 | } |
2080 | |
2081 | list->key_ids_size = 0; |
2082 | while (pkcs11_find_objects (module, pks, &obj, 1, &count) == CKR_OK(0UL) && count == 1) |
2083 | { |
2084 | list->key_ids_size++; |
2085 | } |
2086 | |
2087 | pkcs11_find_objects_final (module, pks); |
2088 | |
2089 | if (list->key_ids_size == 0) |
2090 | { |
2091 | gnutls_assert ()do { if (__builtin_expect((_gnutls_log_level >= 2), 0)) _gnutls_log ( 2, "ASSERT: %s:%d\n", "pkcs11.c",2091); } while(0);; |
2092 | return GNUTLS_E_REQUESTED_DATA_NOT_AVAILABLE-56; |
2093 | } |
2094 | |
2095 | list->key_ids = |
2096 | gnutls_malloc (sizeof (gnutls_buffer_st) * list->key_ids_size); |
2097 | if (list->key_ids == NULL((void*)0)) |
2098 | { |
2099 | gnutls_assert ()do { if (__builtin_expect((_gnutls_log_level >= 2), 0)) _gnutls_log ( 2, "ASSERT: %s:%d\n", "pkcs11.c",2099); } while(0);; |
2100 | return GNUTLS_E_MEMORY_ERROR-25; |
2101 | } |
2102 | |
2103 | /* actual search */ |
2104 | a[0].type = CKA_CLASS(0UL); |
2105 | a[0].value = &class; |
2106 | a[0].value_len = sizeof class; |
2107 | |
2108 | rv = pkcs11_find_objects_init (module, pks, a, 1); |
2109 | if (rv != CKR_OK(0UL)) |
2110 | { |
2111 | gnutls_assert ()do { if (__builtin_expect((_gnutls_log_level >= 2), 0)) _gnutls_log ( 2, "ASSERT: %s:%d\n", "pkcs11.c",2111); } while(0);; |
2112 | return pkcs11_rv_to_err (rv); |
2113 | } |
2114 | |
2115 | current = 0; |
2116 | while (pkcs11_find_objects (module, pks, &obj, 1, &count) == CKR_OK(0UL) && count == 1) |
2117 | { |
2118 | |
2119 | a[0].type = CKA_ID(0x102UL); |
2120 | a[0].value = certid_tmp; |
2121 | a[0].value_len = sizeof (certid_tmp); |
2122 | |
2123 | _gnutls_buffer_init (&list->key_ids[current]); |
2124 | |
2125 | if (pkcs11_get_attribute_value (module, pks, obj, a, 1) == CKR_OK(0UL)) |
2126 | { |
2127 | _gnutls_buffer_append_data (&list->key_ids[current], |
2128 | a[0].value, a[0].value_len); |
2129 | current++; |
2130 | } |
2131 | |
2132 | if (current > list->key_ids_size) |
2133 | break; |
2134 | } |
2135 | |
2136 | pkcs11_find_objects_final (module, pks); |
2137 | |
2138 | list->key_ids_size = current - 1; |
2139 | |
2140 | return 0; |
2141 | } |
2142 | |
2143 | /* Recover certificate list from tokens */ |
2144 | |
2145 | |
2146 | static int |
2147 | find_objs (struct ck_function_list * module, ck_session_handle_t pks, |
2148 | struct token_info *info, struct ck_info *lib_info, void *input) |
2149 | { |
2150 | struct crt_find_data_st *find_data = input; |
2151 | struct ck_attribute a[4]; |
2152 | struct ck_attribute *attr; |
2153 | ck_object_class_t class = -1; |
2154 | ck_certificate_type_t type = -1; |
2155 | unsigned int trusted; |
2156 | ck_rv_t rv; |
2157 | ck_object_handle_t obj; |
2158 | unsigned long count; |
2159 | opaque *cert_data; |
2160 | char certid_tmp[PKCS11_ID_SIZE128]; |
2161 | char label_tmp[PKCS11_LABEL_SIZE128]; |
2162 | int ret, i; |
2163 | struct pkey_list plist; /* private key holder */ |
2164 | int tot_values = 0; |
2165 | |
2166 | if (info == NULL((void*)0)) |
2167 | { /* final call */ |
2168 | if (find_data->current <= *find_data->n_list) |
2169 | ret = 0; |
2170 | else |
2171 | ret = GNUTLS_E_SHORT_MEMORY_BUFFER-51; |
2172 | |
2173 | *find_data->n_list = find_data->current; |
2174 | |
2175 | return ret; |
2176 | } |
2177 | |
2178 | /* do not bother reading the token if basic fields do not match |
2179 | */ |
2180 | if (!p11_kit_uri_match_token_info (find_data->info, &info->tinfo) || |
2181 | !p11_kit_uri_match_module_info (find_data->info, lib_info)) |
2182 | { |
2183 | gnutls_assert ()do { if (__builtin_expect((_gnutls_log_level >= 2), 0)) _gnutls_log ( 2, "ASSERT: %s:%d\n", "pkcs11.c",2183); } while(0);; |
2184 | return GNUTLS_E_REQUESTED_DATA_NOT_AVAILABLE-56; |
2185 | } |
2186 | |
2187 | memset (&plist, 0, sizeof (plist)); |
2188 | |
2189 | if (find_data->flags == GNUTLS_PKCS11_OBJ_ATTR_CRT_WITH_PRIVKEY) |
2190 | { |
2191 | ret = find_privkeys (module, pks, info, &plist); |
2192 | if (ret < 0) |
2193 | { |
2194 | gnutls_assert ()do { if (__builtin_expect((_gnutls_log_level >= 2), 0)) _gnutls_log ( 2, "ASSERT: %s:%d\n", "pkcs11.c",2194); } while(0);; |
2195 | return ret; |
2196 | } |
2197 | |
2198 | if (plist.key_ids_size == 0) |
2199 | { |
2200 | gnutls_assert ()do { if (__builtin_expect((_gnutls_log_level >= 2), 0)) _gnutls_log ( 2, "ASSERT: %s:%d\n", "pkcs11.c",2200); } while(0);; |
2201 | return GNUTLS_E_REQUESTED_DATA_NOT_AVAILABLE-56; |
2202 | } |
2203 | } |
2204 | |
2205 | cert_data = gnutls_malloc (MAX_CERT_SIZE8*1024); |
2206 | if (cert_data == NULL((void*)0)) |
2207 | { |
2208 | gnutls_assert ()do { if (__builtin_expect((_gnutls_log_level >= 2), 0)) _gnutls_log ( 2, "ASSERT: %s:%d\n", "pkcs11.c",2208); } while(0);; |
2209 | return GNUTLS_E_MEMORY_ERROR-25; |
2210 | } |
2211 | |
2212 | /* Find objects with cert class and X.509 cert type. */ |
2213 | |
2214 | tot_values = 0; |
2215 | |
2216 | if (find_data->flags == GNUTLS_PKCS11_OBJ_ATTR_CRT_ALL |
2217 | || find_data->flags == GNUTLS_PKCS11_OBJ_ATTR_CRT_WITH_PRIVKEY) |
2218 | { |
2219 | class = CKO_CERTIFICATE(1UL); |
2220 | type = CKC_X_509(0UL); |
2221 | trusted = 1; |
2222 | |
2223 | a[tot_values].type = CKA_CLASS(0UL); |
2224 | a[tot_values].value = &class; |
2225 | a[tot_values].value_len = sizeof class; |
2226 | tot_values++; |
2227 | |
2228 | a[tot_values].type = CKA_CERTIFICATE_TYPE(0x80UL); |
2229 | a[tot_values].value = &type; |
2230 | a[tot_values].value_len = sizeof type; |
2231 | tot_values++; |
2232 | |
2233 | } |
2234 | else if (find_data->flags == GNUTLS_PKCS11_OBJ_ATTR_CRT_TRUSTED) |
2235 | { |
2236 | class = CKO_CERTIFICATE(1UL); |
2237 | type = CKC_X_509(0UL); |
2238 | trusted = 1; |
2239 | |
2240 | a[tot_values].type = CKA_CLASS(0UL); |
2241 | a[tot_values].value = &class; |
2242 | a[tot_values].value_len = sizeof class; |
2243 | tot_values++; |
2244 | |
2245 | a[tot_values].type = CKA_TRUSTED(0x86UL); |
2246 | a[tot_values].value = &trusted; |
2247 | a[tot_values].value_len = sizeof trusted; |
2248 | tot_values++; |
2249 | |
2250 | } |
2251 | else if (find_data->flags == GNUTLS_PKCS11_OBJ_ATTR_PUBKEY) |
2252 | { |
2253 | class = CKO_PUBLIC_KEY(2UL); |
2254 | |
2255 | a[tot_values].type = CKA_CLASS(0UL); |
2256 | a[tot_values].value = &class; |
2257 | a[tot_values].value_len = sizeof class; |
2258 | tot_values++; |
2259 | } |
2260 | else if (find_data->flags == GNUTLS_PKCS11_OBJ_ATTR_PRIVKEY) |
2261 | { |
2262 | class = CKO_PRIVATE_KEY(3UL); |
2263 | |
2264 | a[tot_values].type = CKA_CLASS(0UL); |
2265 | a[tot_values].value = &class; |
2266 | a[tot_values].value_len = sizeof class; |
2267 | tot_values++; |
2268 | } |
2269 | else if (find_data->flags == GNUTLS_PKCS11_OBJ_ATTR_ALL) |
2270 | { |
2271 | if (class != -1) |
2272 | { |
2273 | a[tot_values].type = CKA_CLASS(0UL); |
2274 | a[tot_values].value = &class; |
2275 | a[tot_values].value_len = sizeof class; |
2276 | tot_values++; |
2277 | } |
2278 | if (type != -1) |
2279 | { |
2280 | a[tot_values].type = CKA_CERTIFICATE_TYPE(0x80UL); |
2281 | a[tot_values].value = &type; |
2282 | a[tot_values].value_len = sizeof type; |
2283 | tot_values++; |
2284 | } |
2285 | } |
2286 | else |
2287 | { |
2288 | gnutls_assert ()do { if (__builtin_expect((_gnutls_log_level >= 2), 0)) _gnutls_log ( 2, "ASSERT: %s:%d\n", "pkcs11.c",2288); } while(0);; |
2289 | ret = GNUTLS_E_INVALID_REQUEST-50; |
2290 | goto fail; |
2291 | } |
2292 | |
2293 | attr = p11_kit_uri_get_attribute (find_data->info, CKA_ID(0x102UL)); |
2294 | if (attr != NULL((void*)0)) |
2295 | { |
2296 | memcpy (a + tot_values, attr, sizeof (struct ck_attribute)); |
2297 | tot_values++; |
2298 | } |
2299 | |
2300 | rv = pkcs11_find_objects_init (module, pks, a, tot_values); |
2301 | if (rv != CKR_OK(0UL)) |
2302 | { |
2303 | gnutls_assert ()do { if (__builtin_expect((_gnutls_log_level >= 2), 0)) _gnutls_log ( 2, "ASSERT: %s:%d\n", "pkcs11.c",2303); } while(0);; |
2304 | _gnutls_debug_log ("pk11: FindObjectsInit failed.\n")do { if (__builtin_expect((_gnutls_log_level >= 2), 0)) _gnutls_log ( 2, "pk11: FindObjectsInit failed.\n"); } while(0); |
2305 | return pkcs11_rv_to_err (rv); |
2306 | } |
2307 | |
2308 | while (pkcs11_find_objects (module, pks, &obj, 1, &count) == CKR_OK(0UL) && count == 1) |
2309 | { |
2310 | gnutls_datum_t label, id, value; |
2311 | |
2312 | a[0].type = CKA_LABEL(3UL); |
2313 | a[0].value = label_tmp; |
2314 | a[0].value_len = sizeof label_tmp; |
2315 | |
2316 | if (pkcs11_get_attribute_value (module, pks, obj, a, 1) == CKR_OK(0UL)) |
2317 | { |
2318 | label.data = a[0].value; |
2319 | label.size = a[0].value_len; |
2320 | } |
2321 | else |
2322 | { |
2323 | label.data = NULL((void*)0); |
2324 | label.size = 0; |
2325 | } |
2326 | |
2327 | a[0].type = CKA_ID(0x102UL); |
2328 | a[0].value = certid_tmp; |
2329 | a[0].value_len = sizeof certid_tmp; |
2330 | |
2331 | if (pkcs11_get_attribute_value (module, pks, obj, a, 1) == CKR_OK(0UL)) |
2332 | { |
2333 | id.data = a[0].value; |
2334 | id.size = a[0].value_len; |
2335 | } |
2336 | else |
2337 | { |
2338 | id.data = NULL((void*)0); |
2339 | id.size = 0; |
2340 | } |
2341 | |
2342 | a[0].type = CKA_VALUE(0x11UL); |
2343 | a[0].value = cert_data; |
2344 | a[0].value_len = MAX_CERT_SIZE8*1024; |
2345 | if (pkcs11_get_attribute_value (module, pks, obj, a, 1) == CKR_OK(0UL)) |
2346 | { |
2347 | value.data = a[0].value; |
2348 | value.size = a[0].value_len; |
2349 | } |
2350 | else |
2351 | { |
2352 | value.data = NULL((void*)0); |
2353 | value.size = 0; |
2354 | } |
2355 | |
2356 | if (find_data->flags == GNUTLS_PKCS11_OBJ_ATTR_ALL) |
2357 | { |
2358 | a[0].type = CKA_CLASS(0UL); |
2359 | a[0].value = &class; |
2360 | a[0].value_len = sizeof class; |
2361 | |
2362 | pkcs11_get_attribute_value (module, pks, obj, a, 1); |
2363 | } |
2364 | |
2365 | if (find_data->flags == GNUTLS_PKCS11_OBJ_ATTR_CRT_WITH_PRIVKEY) |
2366 | { |
2367 | for (i = 0; i < plist.key_ids_size; i++) |
2368 | { |
2369 | if (plist.key_ids[i].length != |
2370 | a[1].value_len |
2371 | || memcmp (plist.key_ids[i].data, |
2372 | a[1].value, a[1].value_len) != 0) |
2373 | { |
2374 | /* not found */ |
2375 | continue; |
2376 | } |
2377 | } |
2378 | } |
2379 | |
2380 | if (find_data->current < *find_data->n_list) |
2381 | { |
2382 | ret = |
2383 | gnutls_pkcs11_obj_init (&find_data->p_list[find_data->current]); |
2384 | if (ret < 0) |
2385 | { |
2386 | gnutls_assert ()do { if (__builtin_expect((_gnutls_log_level >= 2), 0)) _gnutls_log ( 2, "ASSERT: %s:%d\n", "pkcs11.c",2386); } while(0);; |
2387 | goto fail; |
2388 | } |
2389 | |
2390 | if (class == CKO_PUBLIC_KEY(2UL)) |
2391 | { |
2392 | ret = |
2393 | pkcs11_obj_import_pubkey (module, pks, obj, |
2394 | find_data->p_list |
2395 | [find_data->current], |
2396 | &id, &label, |
2397 | &info->tinfo, lib_info); |
2398 | } |
2399 | else |
2400 | { |
2401 | ret = |
2402 | pkcs11_obj_import (class, |
2403 | find_data->p_list |
2404 | [find_data->current], |
2405 | &value, &id, &label, |
2406 | &info->tinfo, lib_info); |
2407 | } |
2408 | if (ret < 0) |
2409 | { |
2410 | gnutls_assert ()do { if (__builtin_expect((_gnutls_log_level >= 2), 0)) _gnutls_log ( 2, "ASSERT: %s:%d\n", "pkcs11.c",2410); } while(0);; |
2411 | goto fail; |
2412 | } |
2413 | } |
2414 | |
2415 | find_data->current++; |
2416 | |
2417 | } |
2418 | |
2419 | gnutls_free (cert_data); |
2420 | pkcs11_find_objects_final (module, pks); |
2421 | |
2422 | return GNUTLS_E_REQUESTED_DATA_NOT_AVAILABLE-56; /* continue until all tokens have been checked */ |
2423 | |
2424 | fail: |
2425 | gnutls_free (cert_data); |
2426 | pkcs11_find_objects_final (module, pks); |
2427 | if (plist.key_ids != NULL((void*)0)) |
2428 | { |
2429 | for (i = 0; i < plist.key_ids_size; i++) |
2430 | { |
2431 | _gnutls_buffer_clear (&plist.key_ids[i]); |
2432 | } |
2433 | gnutls_free (plist.key_ids); |
2434 | } |
2435 | for (i = 0; i < find_data->current; i++) |
2436 | { |
2437 | gnutls_pkcs11_obj_deinit (find_data->p_list[i]); |
2438 | } |
2439 | find_data->current = 0; |
2440 | |
2441 | return ret; |
2442 | } |
2443 | |
2444 | /** |
2445 | * gnutls_pkcs11_obj_list_import_url: |
2446 | * @p_list: An uninitialized object list (may be NULL) |
2447 | * @n_list: initially should hold the maximum size of the list. Will contain the actual size. |
2448 | * @url: A PKCS 11 url identifying a set of objects |
2449 | * @attrs: Attributes of type #gnutls_pkcs11_obj_attr_t that can be used to limit output |
2450 | * @flags: One of GNUTLS_PKCS11_OBJ_* flags |
2451 | * |
2452 | * This function will initialize and set values to an object list |
2453 | * by using all objects identified by a PKCS 11 URL. |
2454 | * |
2455 | * Returns: On success, %GNUTLS_E_SUCCESS (0) is returned, otherwise a |
2456 | * negative error value. |
2457 | * |
2458 | * Since: 2.12.0 |
2459 | **/ |
2460 | int |
2461 | gnutls_pkcs11_obj_list_import_url (gnutls_pkcs11_obj_t * p_list, |
2462 | unsigned int *n_list, |
2463 | const char *url, |
2464 | gnutls_pkcs11_obj_attr_t attrs, |
2465 | unsigned int flags) |
2466 | { |
2467 | int ret; |
2468 | struct crt_find_data_st find_data; |
2469 | |
2470 | memset (&find_data, 0, sizeof (find_data)); |
2471 | |
2472 | /* fill in the find data structure */ |
2473 | find_data.p_list = p_list; |
2474 | find_data.n_list = n_list; |
2475 | find_data.flags = attrs; |
2476 | find_data.current = 0; |
2477 | |
2478 | if (url == NULL((void*)0) || url[0] == 0) |
2479 | { |
2480 | url = "pkcs11:"; |
2481 | } |
2482 | |
2483 | ret = pkcs11_url_to_info (url, &find_data.info); |
2484 | if (ret < 0) |
2485 | { |
2486 | gnutls_assert ()do { if (__builtin_expect((_gnutls_log_level >= 2), 0)) _gnutls_log ( 2, "ASSERT: %s:%d\n", "pkcs11.c",2486); } while(0);; |
2487 | return ret; |
2488 | } |
2489 | |
2490 | ret = |
2491 | _pkcs11_traverse_tokens (find_objs, &find_data, find_data.info, |
2492 | pkcs11_obj_flags_to_int (flags)); |
2493 | p11_kit_uri_free (find_data.info); |
2494 | |
2495 | if (ret < 0) |
2496 | { |
2497 | gnutls_assert ()do { if (__builtin_expect((_gnutls_log_level >= 2), 0)) _gnutls_log ( 2, "ASSERT: %s:%d\n", "pkcs11.c",2497); } while(0);; |
2498 | return ret; |
2499 | } |
2500 | |
2501 | return 0; |
2502 | } |
2503 | |
2504 | /** |
2505 | * gnutls_x509_crt_import_pkcs11_url: |
2506 | * @crt: A certificate of type #gnutls_x509_crt_t |
2507 | * @url: A PKCS 11 url |
2508 | * @flags: One of GNUTLS_PKCS11_OBJ_* flags |
2509 | * |
2510 | * This function will import a PKCS 11 certificate directly from a token |
2511 | * without involving the #gnutls_pkcs11_obj_t structure. This function will |
2512 | * fail if the certificate stored is not of X.509 type. |
2513 | * |
2514 | * Returns: On success, %GNUTLS_E_SUCCESS (0) is returned, otherwise a |
2515 | * negative error value. |
2516 | * |
2517 | * Since: 2.12.0 |
2518 | **/ |
2519 | int |
2520 | gnutls_x509_crt_import_pkcs11_url (gnutls_x509_crt_t crt, |
2521 | const char *url, unsigned int flags) |
2522 | { |
2523 | gnutls_pkcs11_obj_t pcrt; |
2524 | int ret; |
2525 | |
2526 | ret = gnutls_pkcs11_obj_init (&pcrt); |
2527 | if (ret < 0) |
2528 | { |
2529 | gnutls_assert ()do { if (__builtin_expect((_gnutls_log_level >= 2), 0)) _gnutls_log ( 2, "ASSERT: %s:%d\n", "pkcs11.c",2529); } while(0);; |
2530 | return ret; |
2531 | } |
2532 | |
2533 | ret = gnutls_pkcs11_obj_import_url (pcrt, url, flags); |
2534 | if (ret < 0) |
2535 | { |
2536 | gnutls_assert ()do { if (__builtin_expect((_gnutls_log_level >= 2), 0)) _gnutls_log ( 2, "ASSERT: %s:%d\n", "pkcs11.c",2536); } while(0);; |
2537 | goto cleanup; |
2538 | } |
2539 | |
2540 | ret = gnutls_x509_crt_import (crt, &pcrt->raw, GNUTLS_X509_FMT_DER); |
2541 | if (ret < 0) |
2542 | { |
2543 | gnutls_assert ()do { if (__builtin_expect((_gnutls_log_level >= 2), 0)) _gnutls_log ( 2, "ASSERT: %s:%d\n", "pkcs11.c",2543); } while(0);; |
2544 | goto cleanup; |
2545 | } |
2546 | |
2547 | ret = 0; |
2548 | cleanup: |
2549 | |
2550 | gnutls_pkcs11_obj_deinit (pcrt); |
2551 | |
2552 | return ret; |
2553 | } |
2554 | |
2555 | |
2556 | /** |
2557 | * gnutls_x509_crt_import_pkcs11: |
2558 | * @crt: A certificate of type #gnutls_x509_crt_t |
2559 | * @pkcs11_crt: A PKCS 11 object that contains a certificate |
2560 | * |
2561 | * This function will import a PKCS 11 certificate to a #gnutls_x509_crt_t |
2562 | * structure. |
2563 | * |
2564 | * Returns: On success, %GNUTLS_E_SUCCESS (0) is returned, otherwise a |
2565 | * negative error value. |
2566 | * |
2567 | * Since: 2.12.0 |
2568 | **/ |
2569 | int |
2570 | gnutls_x509_crt_import_pkcs11 (gnutls_x509_crt_t crt, |
2571 | gnutls_pkcs11_obj_t pkcs11_crt) |
2572 | { |
2573 | return gnutls_x509_crt_import (crt, &pkcs11_crt->raw, GNUTLS_X509_FMT_DER); |
2574 | } |
2575 | |
2576 | /** |
2577 | * gnutls_x509_crt_list_import_pkcs11: |
2578 | * @certs: A list of certificates of type #gnutls_x509_crt_t |
2579 | * @cert_max: The maximum size of the list |
2580 | * @objs: A list of PKCS 11 objects |
2581 | * @flags: 0 for now |
2582 | * |
2583 | * This function will import a PKCS 11 certificate list to a list of |
2584 | * #gnutls_x509_crt_t structure. These must not be initialized. |
2585 | * |
2586 | * Returns: On success, %GNUTLS_E_SUCCESS (0) is returned, otherwise a |
2587 | * negative error value. |
2588 | * |
2589 | * Since: 2.12.0 |
2590 | **/ |
2591 | int |
2592 | gnutls_x509_crt_list_import_pkcs11 (gnutls_x509_crt_t * certs, |
2593 | unsigned int cert_max, |
2594 | gnutls_pkcs11_obj_t * const objs, |
2595 | unsigned int flags) |
2596 | { |
2597 | int i, j; |
2598 | int ret; |
2599 | |
2600 | for (i = 0; i < cert_max; i++) |
2601 | { |
2602 | ret = gnutls_x509_crt_init (&certs[i]); |
2603 | if (ret < 0) |
2604 | { |
2605 | gnutls_assert ()do { if (__builtin_expect((_gnutls_log_level >= 2), 0)) _gnutls_log ( 2, "ASSERT: %s:%d\n", "pkcs11.c",2605); } while(0);; |
2606 | goto cleanup; |
2607 | } |
2608 | |
2609 | ret = gnutls_x509_crt_import_pkcs11 (certs[i], objs[i]); |
2610 | if (ret < 0) |
2611 | { |
2612 | gnutls_assert ()do { if (__builtin_expect((_gnutls_log_level >= 2), 0)) _gnutls_log ( 2, "ASSERT: %s:%d\n", "pkcs11.c",2612); } while(0);; |
2613 | goto cleanup; |
2614 | } |
2615 | } |
2616 | |
2617 | return 0; |
2618 | |
2619 | cleanup: |
2620 | for (j = 0; j < i; j++) |
2621 | { |
2622 | gnutls_x509_crt_deinit (certs[j]); |
2623 | } |
2624 | |
2625 | return ret; |
2626 | } |
2627 | |
2628 | static int |
2629 | find_flags (struct ck_function_list * module, ck_session_handle_t pks, |
2630 | struct token_info *info, struct ck_info *lib_info, void *input) |
2631 | { |
2632 | struct flags_find_data_st *find_data = input; |
2633 | |
2634 | if (info == NULL((void*)0)) |
2635 | { /* we don't support multiple calls */ |
2636 | gnutls_assert ()do { if (__builtin_expect((_gnutls_log_level >= 2), 0)) _gnutls_log ( 2, "ASSERT: %s:%d\n", "pkcs11.c",2636); } while(0);; |
2637 | return GNUTLS_E_REQUESTED_DATA_NOT_AVAILABLE-56; |
2638 | } |
2639 | |
2640 | /* do not bother reading the token if basic fields do not match |
2641 | */ |
2642 | if (!p11_kit_uri_match_token_info (find_data->info, &info->tinfo) || |
2643 | !p11_kit_uri_match_module_info (find_data->info, lib_info)) |
2644 | { |
2645 | gnutls_assert ()do { if (__builtin_expect((_gnutls_log_level >= 2), 0)) _gnutls_log ( 2, "ASSERT: %s:%d\n", "pkcs11.c",2645); } while(0);; |
2646 | return GNUTLS_E_REQUESTED_DATA_NOT_AVAILABLE-56; |
2647 | } |
2648 | |
2649 | /* found token! */ |
2650 | |
2651 | find_data->slot_flags = info->sinfo.flags; |
2652 | |
2653 | return 0; |
2654 | } |
2655 | |
2656 | /** |
2657 | * gnutls_pkcs11_token_get_flags: |
2658 | * @url: should contain a PKCS 11 URL |
2659 | * @flags: The output flags (GNUTLS_PKCS11_TOKEN_*) |
2660 | * |
2661 | * This function will return information about the PKCS 11 token flags. |
2662 | * The flags from the %gnutls_pkcs11_token_info_t enumeration. |
2663 | * |
2664 | * Returns: %GNUTLS_E_SUCCESS (0) on success or a negative error code on error. |
2665 | * |
2666 | * Since: 2.12.0 |
2667 | **/ |
2668 | int |
2669 | gnutls_pkcs11_token_get_flags (const char *url, unsigned int *flags) |
2670 | { |
2671 | struct flags_find_data_st find_data; |
2672 | int ret; |
2673 | |
2674 | memset (&find_data, 0, sizeof (find_data)); |
2675 | ret = pkcs11_url_to_info (url, &find_data.info); |
2676 | if (ret < 0) |
2677 | { |
2678 | gnutls_assert ()do { if (__builtin_expect((_gnutls_log_level >= 2), 0)) _gnutls_log ( 2, "ASSERT: %s:%d\n", "pkcs11.c",2678); } while(0);; |
2679 | return ret; |
2680 | } |
2681 | |
2682 | ret = _pkcs11_traverse_tokens (find_flags, &find_data, find_data.info, 0); |
2683 | p11_kit_uri_free (find_data.info); |
2684 | |
2685 | if (ret < 0) |
2686 | { |
2687 | gnutls_assert ()do { if (__builtin_expect((_gnutls_log_level >= 2), 0)) _gnutls_log ( 2, "ASSERT: %s:%d\n", "pkcs11.c",2687); } while(0);; |
2688 | return ret; |
2689 | } |
2690 | |
2691 | *flags = 0; |
2692 | if (find_data.slot_flags & CKF_HW_SLOT(1UL << 2)) |
2693 | *flags |= GNUTLS_PKCS11_TOKEN_HW1; |
2694 | |
2695 | return 0; |
2696 | |
2697 | } |
2698 | |
2699 | /** |
2700 | * gnutls_pkcs11_token_get_mechanism: |
2701 | * @url: should contain a PKCS 11 URL |
2702 | * @idx: The index of the mechanism |
2703 | * @mechanism: The PKCS #11 mechanism ID |
2704 | * |
2705 | * This function will return the names of the supported mechanisms |
2706 | * by the token. It should be called with an increasing index until |
2707 | * it return GNUTLS_E_REQUESTED_DATA_NOT_AVAILABLE. |
2708 | * |
2709 | * Returns: %GNUTLS_E_SUCCESS (0) on success or a negative error code on error. |
2710 | * |
2711 | * Since: 2.12.0 |
2712 | **/ |
2713 | int |
2714 | gnutls_pkcs11_token_get_mechanism (const char *url, int idx, |
2715 | unsigned long *mechanism) |
2716 | { |
2717 | int ret; |
2718 | ck_rv_t rv; |
2719 | struct ck_function_list *module; |
2720 | ck_slot_id_t slot; |
2721 | struct token_info tinfo; |
2722 | struct p11_kit_uri *info = NULL((void*)0); |
2723 | unsigned long count; |
2724 | ck_mechanism_type_t mlist[400]; |
2725 | |
2726 | ret = pkcs11_url_to_info (url, &info); |
2727 | if (ret < 0) |
2728 | { |
2729 | gnutls_assert ()do { if (__builtin_expect((_gnutls_log_level >= 2), 0)) _gnutls_log ( 2, "ASSERT: %s:%d\n", "pkcs11.c",2729); } while(0);; |
2730 | return ret; |
2731 | } |
2732 | |
2733 | |
2734 | ret = pkcs11_find_slot (&module, &slot, info, &tinfo); |
2735 | p11_kit_uri_free (info); |
2736 | |
2737 | if (ret < 0) |
2738 | { |
2739 | gnutls_assert ()do { if (__builtin_expect((_gnutls_log_level >= 2), 0)) _gnutls_log ( 2, "ASSERT: %s:%d\n", "pkcs11.c",2739); } while(0);; |
2740 | return ret; |
2741 | } |
2742 | |
2743 | count = sizeof (mlist) / sizeof (mlist[0]); |
2744 | rv = pkcs11_get_mechanism_list (module, slot, mlist, &count); |
2745 | if (rv != CKR_OK(0UL)) |
2746 | { |
2747 | gnutls_assert ()do { if (__builtin_expect((_gnutls_log_level >= 2), 0)) _gnutls_log ( 2, "ASSERT: %s:%d\n", "pkcs11.c",2747); } while(0);; |
2748 | return pkcs11_rv_to_err (rv); |
2749 | } |
2750 | |
2751 | if (idx >= count) |
2752 | { |
2753 | gnutls_assert ()do { if (__builtin_expect((_gnutls_log_level >= 2), 0)) _gnutls_log ( 2, "ASSERT: %s:%d\n", "pkcs11.c",2753); } while(0);; |
2754 | return GNUTLS_E_REQUESTED_DATA_NOT_AVAILABLE-56; |
2755 | } |
2756 | |
2757 | *mechanism = mlist[idx]; |
2758 | |
2759 | return 0; |
2760 | |
2761 | } |
2762 | |
2763 | /** |
2764 | * gnutls_pkcs11_type_get_name: |
2765 | * @type: Holds the PKCS 11 object type, a #gnutls_pkcs11_obj_type_t. |
2766 | * |
2767 | * This function will return a human readable description of the |
2768 | * PKCS11 object type @obj. It will return "Unknown" for unknown |
2769 | * types. |
2770 | * |
2771 | * Returns: human readable string labeling the PKCS11 object type |
2772 | * @type. |
2773 | * |
2774 | * Since: 2.12.0 |
2775 | **/ |
2776 | const char * |
2777 | gnutls_pkcs11_type_get_name (gnutls_pkcs11_obj_type_t type) |
2778 | { |
2779 | switch (type) |
2780 | { |
2781 | case GNUTLS_PKCS11_OBJ_X509_CRT: |
2782 | return "X.509 Certificate"; |
2783 | case GNUTLS_PKCS11_OBJ_PUBKEY: |
2784 | return "Public key"; |
2785 | case GNUTLS_PKCS11_OBJ_PRIVKEY: |
2786 | return "Private key"; |
2787 | case GNUTLS_PKCS11_OBJ_SECRET_KEY: |
2788 | return "Secret key"; |
2789 | case GNUTLS_PKCS11_OBJ_DATA: |
2790 | return "Data"; |
2791 | case GNUTLS_PKCS11_OBJ_UNKNOWN: |
2792 | default: |
2793 | return "Unknown"; |
2794 | } |
2795 | } |
2796 | |
2797 | ck_rv_t |
2798 | pkcs11_get_slot_list (struct ck_function_list * module, unsigned char token_present, |
2799 | ck_slot_id_t *slot_list, unsigned long *count) |
2800 | { |
2801 | return (module)->C_GetSlotList (token_present, slot_list, count); |
2802 | } |
2803 | |
2804 | ck_rv_t |
2805 | pkcs11_get_module_info (struct ck_function_list * module, |
2806 | struct ck_info * info) |
2807 | { |
2808 | return (module)->C_GetInfo (info); |
2809 | } |
2810 | |
2811 | ck_rv_t |
2812 | pkcs11_get_slot_info(struct ck_function_list * module, |
2813 | ck_slot_id_t slot_id, |
2814 | struct ck_slot_info *info) |
2815 | { |
2816 | return (module)->C_GetSlotInfo (slot_id, info); |
2817 | } |
2818 | |
2819 | ck_rv_t |
2820 | pkcs11_get_token_info (struct ck_function_list * module, |
2821 | ck_slot_id_t slot_id, |
2822 | struct ck_token_info *info) |
2823 | { |
2824 | return (module)->C_GetTokenInfo (slot_id, info); |
2825 | } |
2826 | |
2827 | ck_rv_t |
2828 | pkcs11_find_objects_init (struct ck_function_list *module, |
2829 | ck_session_handle_t sess, |
2830 | struct ck_attribute *templ, |
2831 | unsigned long count) |
2832 | { |
2833 | return (module)->C_FindObjectsInit (sess, templ, count); |
2834 | } |
2835 | |
2836 | ck_rv_t |
2837 | pkcs11_find_objects (struct ck_function_list *module, |
2838 | ck_session_handle_t sess, |
2839 | ck_object_handle_t *objects, |
2840 | unsigned long max_object_count, |
2841 | unsigned long *object_count) |
2842 | { |
2843 | return (module)->C_FindObjects (sess, objects, max_object_count, object_count); |
2844 | } |
2845 | |
2846 | ck_rv_t |
2847 | pkcs11_find_objects_final (struct ck_function_list *module, |
2848 | ck_session_handle_t sess) |
2849 | { |
2850 | return (module)->C_FindObjectsFinal (sess); |
2851 | } |
2852 | |
2853 | ck_rv_t |
2854 | pkcs11_close_session (struct ck_function_list *module, |
2855 | ck_session_handle_t sess) |
2856 | { |
2857 | return (module)->C_CloseSession (sess); |
2858 | } |
2859 | |
2860 | ck_rv_t |
2861 | pkcs11_get_attribute_value(struct ck_function_list *module, |
2862 | ck_session_handle_t sess, |
2863 | ck_object_handle_t object, |
2864 | struct ck_attribute *templ, |
2865 | unsigned long count) |
2866 | { |
2867 | return (module)->C_GetAttributeValue (sess, object, templ, count); |
2868 | } |
2869 | |
2870 | ck_rv_t |
2871 | pkcs11_get_mechanism_list (struct ck_function_list *module, |
2872 | ck_slot_id_t slot_id, |
2873 | ck_mechanism_type_t *mechanism_list, |
2874 | unsigned long *count) |
2875 | { |
2876 | return (module)->C_GetMechanismList (slot_id, mechanism_list, count); |
2877 | } |
2878 | |
2879 | ck_rv_t |
2880 | pkcs11_sign_init (struct ck_function_list *module, |
2881 | ck_session_handle_t sess, |
2882 | struct ck_mechanism *mechanism, |
2883 | ck_object_handle_t key) |
2884 | { |
2885 | return (module)->C_SignInit (sess, mechanism, key); |
2886 | } |
2887 | |
2888 | ck_rv_t |
2889 | pkcs11_sign (struct ck_function_list *module, |
2890 | ck_session_handle_t sess, |
2891 | unsigned char *data, |
2892 | unsigned long data_len, |
2893 | unsigned char *signature, |
2894 | unsigned long *signature_len) |
2895 | { |
2896 | return (module)->C_Sign (sess, data, data_len, signature, signature_len); |
2897 | } |
2898 | |
2899 | ck_rv_t |
2900 | pkcs11_generate_key_pair (struct ck_function_list *module, |
2901 | ck_session_handle_t sess, |
2902 | struct ck_mechanism *mechanism, |
2903 | struct ck_attribute *pub_templ, |
2904 | unsigned long pub_templ_count, |
2905 | struct ck_attribute *priv_templ, |
2906 | unsigned long priv_templ_count, |
2907 | ck_object_handle_t *pub, |
2908 | ck_object_handle_t *priv) |
2909 | { |
2910 | return (module)->C_GenerateKeyPair (sess, mechanism, pub_templ, pub_templ_count, |
2911 | priv_templ, priv_templ_count, pub, priv); |
2912 | } |
2913 | |
2914 | ck_rv_t |
2915 | pkcs11_decrypt_init (struct ck_function_list *module, |
2916 | ck_session_handle_t sess, |
2917 | struct ck_mechanism *mechanism, |
2918 | ck_object_handle_t key) |
2919 | { |
2920 | return (module)->C_DecryptInit (sess, mechanism, key); |
2921 | } |
2922 | |
2923 | ck_rv_t |
2924 | pkcs11_decrypt (struct ck_function_list *module, |
2925 | ck_session_handle_t sess, |
2926 | unsigned char *encrypted_data, |
2927 | unsigned long encrypted_data_len, |
2928 | unsigned char *data, unsigned long *data_len) |
2929 | { |
2930 | return (module)->C_Decrypt (sess, encrypted_data, encrypted_data_len, |
2931 | data, data_len); |
2932 | } |
2933 | |
2934 | ck_rv_t |
2935 | pkcs11_create_object (struct ck_function_list *module, |
2936 | ck_session_handle_t sess, |
2937 | struct ck_attribute *templ, |
2938 | unsigned long count, |
2939 | ck_object_handle_t *object) |
2940 | { |
2941 | return (module)->C_CreateObject (sess, templ, count, object); |
2942 | } |
2943 | |
2944 | ck_rv_t |
2945 | pkcs11_destroy_object (struct ck_function_list *module, |
2946 | ck_session_handle_t sess, |
2947 | ck_object_handle_t object) |
2948 | { |
2949 | return (module)->C_DestroyObject (sess, object); |
2950 | } |
2951 | |
2952 | ck_rv_t |
2953 | pkcs11_init_token (struct ck_function_list *module, |
2954 | ck_slot_id_t slot_id, unsigned char *pin, |
2955 | unsigned long pin_len, unsigned char *label) |
2956 | { |
2957 | return (module)->C_InitToken (slot_id, pin, pin_len, label); |
2958 | } |
2959 | |
2960 | ck_rv_t |
2961 | pkcs11_init_pin (struct ck_function_list *module, |
2962 | ck_session_handle_t sess, |
2963 | unsigned char *pin, |
2964 | unsigned long pin_len) |
2965 | { |
2966 | return (module)->C_InitPIN (sess, pin, pin_len); |
2967 | } |
2968 | |
2969 | ck_rv_t |
2970 | pkcs11_set_pin (struct ck_function_list *module, |
2971 | ck_session_handle_t sess, |
2972 | unsigned char *old_pin, |
2973 | unsigned long old_len, |
2974 | unsigned char *new_pin, |
2975 | unsigned long new_len) |
2976 | { |
2977 | return (module)->C_SetPIN (sess, old_pin, old_len, new_pin, new_len); |
2978 | } |
2979 | |
2980 | const char * |
2981 | pkcs11_strerror (ck_rv_t rv) |
2982 | { |
2983 | return p11_kit_strerror (rv); |
2984 | } |