/src/p11-kit/common/attrs.c
Line | Count | Source |
1 | | /* |
2 | | * Copyright (C) 2012, Redhat Inc. |
3 | | * Copyright (c) 2011, Collabora Ltd. |
4 | | * |
5 | | * Redistribution and use in source and binary forms, with or without |
6 | | * modification, are permitted provided that the following conditions |
7 | | * are met: |
8 | | * |
9 | | * * Redistributions of source code must retain the above |
10 | | * copyright notice, this list of conditions and the |
11 | | * following disclaimer. |
12 | | * * Redistributions in binary form must reproduce the |
13 | | * above copyright notice, this list of conditions and |
14 | | * the following disclaimer in the documentation and/or |
15 | | * other materials provided with the distribution. |
16 | | * * The names of contributors to this software may not be |
17 | | * used to endorse or promote products derived from this |
18 | | * software without specific prior written permission. |
19 | | * |
20 | | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS |
21 | | * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT |
22 | | * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS |
23 | | * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE |
24 | | * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, |
25 | | * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, |
26 | | * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS |
27 | | * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED |
28 | | * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, |
29 | | * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF |
30 | | * THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH |
31 | | * DAMAGE. |
32 | | * |
33 | | * Author: Stef Walter <stefw@collabora.co.uk> |
34 | | */ |
35 | | |
36 | | #include "config.h" |
37 | | |
38 | | #include "attrs.h" |
39 | | #include "buffer.h" |
40 | | #include "compat.h" |
41 | | #include "constants.h" |
42 | | #include "debug.h" |
43 | | #include "hash.h" |
44 | | #include "pkcs11.h" |
45 | | #include "pkcs11i.h" |
46 | | #include "pkcs11x.h" |
47 | | |
48 | | #include <assert.h> |
49 | | #include <stdarg.h> |
50 | | #include <stdio.h> |
51 | | #include <stdint.h> |
52 | | #include <stdlib.h> |
53 | | #include <string.h> |
54 | | |
55 | | #define ELEMS(x) (sizeof (x) / sizeof (x[0])) |
56 | | |
57 | | bool |
58 | | p11_attrs_terminator (const CK_ATTRIBUTE *attrs) |
59 | 13.5k | { |
60 | 13.5k | return (attrs == NULL || attrs->type == CKA_INVALID); |
61 | 13.5k | } |
62 | | |
63 | | CK_ULONG |
64 | | p11_attrs_count (const CK_ATTRIBUTE *attrs) |
65 | 1.72k | { |
66 | 1.72k | CK_ULONG count; |
67 | | |
68 | 1.72k | if (attrs == NULL) |
69 | 860 | return 0; |
70 | | |
71 | 6.36k | for (count = 0; !p11_attrs_terminator (attrs); count++, attrs++); |
72 | | |
73 | 860 | return count; |
74 | 1.72k | } |
75 | | |
76 | | void |
77 | | p11_attrs_free (void *attrs) |
78 | 855 | { |
79 | 855 | CK_ATTRIBUTE *ats = attrs; |
80 | 855 | int i; |
81 | | |
82 | 855 | if (attrs == NULL) |
83 | 0 | return; |
84 | | |
85 | 6.32k | for (i = 0; !p11_attrs_terminator (ats + i); i++) |
86 | 5.47k | p11_attr_clear (&ats[i]); |
87 | 855 | free (ats); |
88 | 855 | } |
89 | | |
90 | | /* Call to this function always invalidates pointer to `attrs` |
91 | | */ |
92 | | static CK_ATTRIBUTE * |
93 | | attrs_build (CK_ATTRIBUTE *attrs, |
94 | | CK_ULONG count_to_add, |
95 | | bool take_values, |
96 | | bool override, |
97 | | CK_ATTRIBUTE * (*generator) (void *), |
98 | | void *state) |
99 | 860 | { |
100 | 860 | CK_ATTRIBUTE *attr; |
101 | 860 | CK_ATTRIBUTE *add; |
102 | 860 | CK_ULONG current; |
103 | 860 | CK_ULONG at; |
104 | 860 | CK_ULONG j; |
105 | 860 | CK_ULONG i; |
106 | 860 | size_t length; |
107 | 860 | void *new_memory; |
108 | | |
109 | | /* How many attributes we already have */ |
110 | 860 | current = p11_attrs_count (attrs); |
111 | | |
112 | | /* Reallocate for how many we need */ |
113 | 860 | length = current + count_to_add; |
114 | 860 | if (current > length || length >= SIZE_MAX) { |
115 | 0 | p11_attrs_free (attrs); |
116 | 0 | return_val_if_reached (NULL); |
117 | 0 | } |
118 | 860 | new_memory = reallocarray (attrs, length + 1, sizeof (CK_ATTRIBUTE)); |
119 | 860 | if (new_memory == NULL) { |
120 | 0 | p11_attrs_free (attrs); |
121 | 0 | return_val_if_reached (NULL); |
122 | 0 | } |
123 | 860 | attrs = new_memory; |
124 | | |
125 | 860 | at = current; |
126 | 6.36k | for (i = 0; i < count_to_add; i++) { |
127 | 5.50k | add = (generator) (state); |
128 | | |
129 | | /* Skip with invalid type */ |
130 | 5.50k | if (!add || add->type == CKA_INVALID) |
131 | 0 | continue; |
132 | | |
133 | 5.50k | attr = NULL; |
134 | | |
135 | | /* Do we have this attribute? */ |
136 | 5.50k | for (j = 0; attr == NULL && j < current; j++) { |
137 | 0 | if (attrs[j].type == add->type) { |
138 | 0 | attr = attrs + j; |
139 | 0 | break; |
140 | 0 | } |
141 | 0 | } |
142 | | |
143 | | /* The attribute doesn't exist */ |
144 | 5.50k | if (attr == NULL) { |
145 | 5.50k | attr = attrs + at; |
146 | 5.50k | at++; |
147 | | |
148 | | /* The attribute exists and we're not overriding */ |
149 | 5.50k | } else if (!override) { |
150 | 0 | if (take_values) |
151 | 0 | p11_attr_clear (add); |
152 | 0 | continue; |
153 | | |
154 | | /* The attribute exists but we're overriding */ |
155 | 0 | } else { |
156 | 0 | p11_attr_clear (attr); |
157 | 0 | } |
158 | | |
159 | 5.50k | if (take_values) { |
160 | 0 | memcpy (attr, add, sizeof (CK_ATTRIBUTE)); |
161 | 5.50k | } else if (!p11_attr_copy (attr, add)) { |
162 | 0 | attrs[at].type = CKA_INVALID; |
163 | 0 | p11_attrs_free (attrs); |
164 | 0 | return_val_if_reached (NULL); |
165 | 0 | } |
166 | 5.50k | } |
167 | | |
168 | | /* Mark this as the end */ |
169 | 860 | attrs[at].type = CKA_INVALID; |
170 | 860 | assert (p11_attrs_terminator (attrs + at)); |
171 | 860 | return attrs; |
172 | 860 | } |
173 | | |
174 | | static CK_ATTRIBUTE * |
175 | | vararg_generator (void *state) |
176 | 0 | { |
177 | 0 | va_list *va = state; |
178 | 0 | return va_arg (*va, CK_ATTRIBUTE *); |
179 | 0 | } |
180 | | |
181 | | CK_ATTRIBUTE * |
182 | | p11_attrs_build (CK_ATTRIBUTE *attrs, |
183 | | ...) |
184 | 0 | { |
185 | 0 | CK_ULONG count; |
186 | 0 | va_list va; |
187 | |
|
188 | 0 | count = 0UL; |
189 | 0 | va_start (va, attrs); |
190 | 0 | while (va_arg (va, CK_ATTRIBUTE *)) |
191 | 0 | count++; |
192 | 0 | va_end (va); |
193 | |
|
194 | 0 | va_start (va, attrs); |
195 | 0 | attrs = attrs_build (attrs, count, false, true, |
196 | 0 | vararg_generator, &va); |
197 | 0 | va_end (va); |
198 | |
|
199 | 0 | return attrs; |
200 | 0 | } |
201 | | |
202 | | static CK_ATTRIBUTE * |
203 | | template_generator (void *state) |
204 | 5.50k | { |
205 | 5.50k | CK_ATTRIBUTE **template = state; |
206 | 5.50k | return (*template)++; |
207 | 5.50k | } |
208 | | |
209 | | CK_ATTRIBUTE * |
210 | | p11_attrs_buildn (CK_ATTRIBUTE *attrs, |
211 | | const CK_ATTRIBUTE *add, |
212 | | CK_ULONG count) |
213 | 860 | { |
214 | 860 | return attrs_build (attrs, count, false, true, |
215 | 860 | template_generator, &add); |
216 | 860 | } |
217 | | |
218 | | CK_ATTRIBUTE * |
219 | | p11_attrs_take (CK_ATTRIBUTE *attrs, |
220 | | CK_ATTRIBUTE_TYPE type, |
221 | | CK_VOID_PTR value, |
222 | | CK_ULONG length) |
223 | 0 | { |
224 | 0 | CK_ATTRIBUTE attr = { type, value, length }; |
225 | 0 | CK_ATTRIBUTE *add = &attr; |
226 | 0 | return attrs_build (attrs, 1, true, true, |
227 | 0 | template_generator, &add); |
228 | 0 | } |
229 | | |
230 | | CK_ATTRIBUTE * |
231 | | p11_attrs_merge (CK_ATTRIBUTE *attrs, |
232 | | CK_ATTRIBUTE *merge, |
233 | | bool replace) |
234 | 0 | { |
235 | 0 | CK_ATTRIBUTE *ptr; |
236 | 0 | CK_ULONG count; |
237 | |
|
238 | 0 | if (attrs == NULL || attrs == merge) |
239 | 0 | return merge; |
240 | | |
241 | 0 | ptr = merge; |
242 | 0 | count = p11_attrs_count (merge); |
243 | |
|
244 | 0 | attrs = attrs_build (attrs, count, true, replace, |
245 | 0 | template_generator, &ptr); |
246 | 0 | if (attrs == NULL) { |
247 | 0 | p11_attrs_free (merge); |
248 | 0 | return_val_if_reached (NULL); |
249 | 0 | } |
250 | | |
251 | | /* |
252 | | * Since we're supposed to own the merge attributes, |
253 | | * free the container array. |
254 | | */ |
255 | 0 | free (merge); |
256 | 0 | return attrs; |
257 | 0 | } |
258 | | |
259 | | CK_ATTRIBUTE * |
260 | | p11_attrs_dup (const CK_ATTRIBUTE *attrs) |
261 | 860 | { |
262 | 860 | CK_ULONG count; |
263 | | |
264 | 860 | count = p11_attrs_count (attrs); |
265 | 860 | return p11_attrs_buildn (NULL, attrs, count); |
266 | 860 | } |
267 | | |
268 | | CK_ATTRIBUTE * |
269 | | p11_attrs_find (CK_ATTRIBUTE *attrs, |
270 | | CK_ATTRIBUTE_TYPE type) |
271 | 0 | { |
272 | 0 | CK_ULONG i; |
273 | |
|
274 | 0 | for (i = 0; !p11_attrs_terminator (attrs + i); i++) { |
275 | 0 | if (attrs[i].type == type) |
276 | 0 | return attrs + i; |
277 | 0 | } |
278 | | |
279 | 0 | return NULL; |
280 | 0 | } |
281 | | |
282 | | CK_ATTRIBUTE * |
283 | | p11_attrs_findn (CK_ATTRIBUTE *attrs, |
284 | | CK_ULONG count, |
285 | | CK_ATTRIBUTE_TYPE type) |
286 | 0 | { |
287 | 0 | CK_ULONG i; |
288 | |
|
289 | 0 | for (i = 0; i < count; i++) { |
290 | 0 | if (attrs[i].type == type) |
291 | 0 | return attrs + i; |
292 | 0 | } |
293 | | |
294 | 0 | return NULL; |
295 | 0 | } |
296 | | |
297 | | bool |
298 | | p11_attrs_find_bool (const CK_ATTRIBUTE *attrs, |
299 | | CK_ATTRIBUTE_TYPE type, |
300 | | CK_BBOOL *value) |
301 | 0 | { |
302 | 0 | CK_ULONG i; |
303 | |
|
304 | 0 | for (i = 0; !p11_attrs_terminator (attrs + i); i++) { |
305 | 0 | if (attrs[i].type == type && |
306 | 0 | attrs[i].ulValueLen == sizeof (CK_BBOOL) && |
307 | 0 | attrs[i].pValue != NULL) { |
308 | 0 | *value = *((CK_BBOOL *)attrs[i].pValue); |
309 | 0 | return true; |
310 | 0 | } |
311 | 0 | } |
312 | | |
313 | 0 | return false; |
314 | 0 | } |
315 | | |
316 | | bool |
317 | | p11_attrs_findn_bool (const CK_ATTRIBUTE *attrs, |
318 | | CK_ULONG count, |
319 | | CK_ATTRIBUTE_TYPE type, |
320 | | CK_BBOOL *value) |
321 | 0 | { |
322 | 0 | CK_ULONG i; |
323 | |
|
324 | 0 | for (i = 0; i < count; i++) { |
325 | 0 | if (attrs[i].type == type && |
326 | 0 | attrs[i].ulValueLen == sizeof (CK_BBOOL) && |
327 | 0 | attrs[i].pValue != NULL) { |
328 | 0 | *value = *((CK_BBOOL *)attrs[i].pValue); |
329 | 0 | return true; |
330 | 0 | } |
331 | 0 | } |
332 | | |
333 | 0 | return false; |
334 | 0 | } |
335 | | |
336 | | bool |
337 | | p11_attrs_find_ulong (const CK_ATTRIBUTE *attrs, |
338 | | CK_ATTRIBUTE_TYPE type, |
339 | | CK_ULONG *value) |
340 | 0 | { |
341 | 0 | CK_ULONG i; |
342 | |
|
343 | 0 | for (i = 0; !p11_attrs_terminator (attrs + i); i++) { |
344 | 0 | if (attrs[i].type == type && |
345 | 0 | attrs[i].ulValueLen == sizeof (CK_ULONG) && |
346 | 0 | attrs[i].pValue != NULL) { |
347 | 0 | *value = *((CK_ULONG *)attrs[i].pValue); |
348 | 0 | return true; |
349 | 0 | } |
350 | 0 | } |
351 | | |
352 | 0 | return false; |
353 | 0 | } |
354 | | |
355 | | bool |
356 | | p11_attrs_findn_ulong (const CK_ATTRIBUTE *attrs, |
357 | | CK_ULONG count, |
358 | | CK_ATTRIBUTE_TYPE type, |
359 | | CK_ULONG *value) |
360 | 0 | { |
361 | 0 | CK_ULONG i; |
362 | |
|
363 | 0 | for (i = 0; i < count; i++) { |
364 | 0 | if (attrs[i].type == type && |
365 | 0 | attrs[i].ulValueLen == sizeof (CK_ULONG) && |
366 | 0 | attrs[i].pValue != NULL) { |
367 | 0 | *value = *((CK_ULONG *)attrs[i].pValue); |
368 | 0 | return true; |
369 | 0 | } |
370 | 0 | } |
371 | | |
372 | 0 | return false; |
373 | 0 | } |
374 | | |
375 | | void * |
376 | | p11_attrs_find_value (CK_ATTRIBUTE *attrs, |
377 | | CK_ATTRIBUTE_TYPE type, |
378 | | size_t *length) |
379 | 0 | { |
380 | 0 | CK_ULONG i; |
381 | |
|
382 | 0 | for (i = 0; !p11_attrs_terminator (attrs + i); i++) { |
383 | 0 | if (attrs[i].type == type && |
384 | 0 | attrs[i].ulValueLen != 0 && |
385 | 0 | attrs[i].ulValueLen != (CK_ULONG)-1 && |
386 | 0 | attrs[i].pValue != NULL) { |
387 | 0 | if (length) |
388 | 0 | *length = attrs[i].ulValueLen; |
389 | 0 | return attrs[i].pValue; |
390 | 0 | } |
391 | 0 | } |
392 | | |
393 | 0 | return NULL; |
394 | 0 | } |
395 | | |
396 | | CK_ATTRIBUTE * |
397 | | p11_attrs_find_valid (CK_ATTRIBUTE *attrs, |
398 | | CK_ATTRIBUTE_TYPE type) |
399 | 0 | { |
400 | 0 | CK_ULONG i; |
401 | |
|
402 | 0 | for (i = 0; !p11_attrs_terminator (attrs + i); i++) { |
403 | 0 | if (attrs[i].type == type && |
404 | 0 | attrs[i].pValue != NULL && |
405 | 0 | attrs[i].ulValueLen != 0 && |
406 | 0 | attrs[i].ulValueLen != (CK_ULONG)-1) |
407 | 0 | return attrs + i; |
408 | 0 | } |
409 | | |
410 | 0 | return NULL; |
411 | 0 | } |
412 | | |
413 | | bool |
414 | | p11_attrs_remove (CK_ATTRIBUTE *attrs, |
415 | | CK_ATTRIBUTE_TYPE type) |
416 | 0 | { |
417 | 0 | CK_ULONG count; |
418 | 0 | CK_ULONG i; |
419 | |
|
420 | 0 | count = p11_attrs_count (attrs); |
421 | 0 | for (i = 0; i < count; i++) { |
422 | 0 | if (attrs[i].type == type) |
423 | 0 | break; |
424 | 0 | } |
425 | |
|
426 | 0 | if (i == count) |
427 | 0 | return false; |
428 | | |
429 | 0 | if (attrs[i].pValue) |
430 | 0 | p11_attr_clear (&attrs[i]); |
431 | |
|
432 | 0 | memmove (attrs + i, attrs + i + 1, (count - (i + 1)) * sizeof (CK_ATTRIBUTE)); |
433 | 0 | attrs[count - 1].type = CKA_INVALID; |
434 | 0 | return true; |
435 | 0 | } |
436 | | |
437 | | void |
438 | | p11_attrs_purge (CK_ATTRIBUTE *attrs) |
439 | 0 | { |
440 | 0 | int in, out; |
441 | |
|
442 | 0 | for (in = 0, out = 0; !p11_attrs_terminator (attrs + in); in++) { |
443 | 0 | if (attrs[in].ulValueLen == (CK_ULONG)-1) { |
444 | 0 | free (attrs[in].pValue); |
445 | 0 | attrs[in].pValue = NULL; |
446 | 0 | attrs[in].ulValueLen = 0; |
447 | 0 | } else { |
448 | 0 | if (in != out) |
449 | 0 | memcpy (attrs + out, attrs + in, sizeof (CK_ATTRIBUTE)); |
450 | 0 | out++; |
451 | 0 | } |
452 | 0 | } |
453 | |
|
454 | 0 | attrs[out].type = CKA_INVALID; |
455 | 0 | assert (p11_attrs_terminator (attrs + out)); |
456 | |
|
457 | 0 | } |
458 | | |
459 | | bool |
460 | | p11_attrs_match (const CK_ATTRIBUTE *attrs, |
461 | | const CK_ATTRIBUTE *match) |
462 | 0 | { |
463 | 0 | CK_ATTRIBUTE *attr; |
464 | |
|
465 | 0 | for (; !p11_attrs_terminator (match); match++) { |
466 | 0 | attr = p11_attrs_find ((CK_ATTRIBUTE *)attrs, match->type); |
467 | 0 | if (!attr) |
468 | 0 | return false; |
469 | 0 | if (!p11_attr_equal (attr, match)) |
470 | 0 | return false; |
471 | 0 | } |
472 | | |
473 | 0 | return true; |
474 | 0 | } |
475 | | |
476 | | bool |
477 | | p11_attrs_matchn (const CK_ATTRIBUTE *attrs, |
478 | | const CK_ATTRIBUTE *match, |
479 | | CK_ULONG count) |
480 | 0 | { |
481 | 0 | CK_ATTRIBUTE *attr; |
482 | 0 | CK_ULONG i; |
483 | |
|
484 | 0 | for (i = 0; i < count; i++) { |
485 | 0 | attr = p11_attrs_find ((CK_ATTRIBUTE *)attrs, match[i].type); |
486 | 0 | if (!attr) |
487 | 0 | return false; |
488 | 0 | if (!p11_attr_equal (attr, match + i)) |
489 | 0 | return false; |
490 | 0 | } |
491 | | |
492 | 0 | return true; |
493 | |
|
494 | 0 | } |
495 | | |
496 | | |
497 | | bool |
498 | | p11_attr_match_value (const CK_ATTRIBUTE *attr, |
499 | | const void *value, |
500 | | ssize_t length) |
501 | 0 | { |
502 | 0 | if (length < 0) |
503 | 0 | length = strlen (value); |
504 | 0 | return (attr != NULL && |
505 | 0 | attr->ulValueLen == length && |
506 | 0 | (attr->pValue == value || |
507 | 0 | (attr->pValue && value && |
508 | 0 | memcmp (attr->pValue, value, attr->ulValueLen) == 0))); |
509 | 0 | } |
510 | | |
511 | | bool |
512 | | p11_attr_equal (const void *v1, |
513 | | const void *v2) |
514 | 0 | { |
515 | 0 | const CK_ATTRIBUTE *one = v1; |
516 | 0 | const CK_ATTRIBUTE *two = v2; |
517 | |
|
518 | 0 | return (one == two || |
519 | 0 | (one && two && one->type == two->type && |
520 | 0 | p11_attr_match_value (one, two->pValue, two->ulValueLen))); |
521 | 0 | } |
522 | | |
523 | | unsigned int |
524 | | p11_attr_hash (const void *data) |
525 | 0 | { |
526 | 0 | const CK_ATTRIBUTE *attr = data; |
527 | 0 | uint32_t hash = 0; |
528 | |
|
529 | 0 | if (attr != NULL) { |
530 | 0 | p11_hash_murmur3 (&hash, |
531 | 0 | &attr->type, sizeof (attr->type), |
532 | 0 | attr->pValue, (size_t)attr->ulValueLen, |
533 | 0 | NULL); |
534 | 0 | } |
535 | |
|
536 | 0 | return hash; |
537 | 0 | } |
538 | | |
539 | | bool |
540 | | p11_attr_copy (CK_ATTRIBUTE *dst, const CK_ATTRIBUTE *src) |
541 | 6.02k | { |
542 | 6.02k | return_val_if_fail (dst != NULL, false); |
543 | 6.02k | return_val_if_fail (src != NULL, false); |
544 | | |
545 | 6.02k | memcpy (dst, src, sizeof (CK_ATTRIBUTE)); |
546 | | |
547 | 6.02k | if (src->pValue == NULL) |
548 | 0 | return true; |
549 | | |
550 | 6.02k | dst->pValue = malloc (src->ulValueLen == 0 ? 1 : src->ulValueLen); |
551 | 6.02k | return_val_if_fail (dst->pValue != NULL, false); |
552 | | |
553 | 6.02k | assert (dst->ulValueLen >= src->ulValueLen); |
554 | | |
555 | 6.02k | if (IS_ATTRIBUTE_ARRAY (src)) { |
556 | 172 | CK_ATTRIBUTE *child_dst; |
557 | 172 | const CK_ATTRIBUTE *child_src; |
558 | 172 | size_t i; |
559 | | |
560 | 172 | for (i = 0, child_dst = dst->pValue, child_src = src->pValue; |
561 | 688 | i < src->ulValueLen / sizeof (CK_ATTRIBUTE); |
562 | 516 | i++, child_dst++, child_src++) { |
563 | 516 | if (!p11_attr_copy (child_dst, child_src)) { |
564 | | /* Free the copied children */ |
565 | 0 | for (size_t j = 0; j < i; j++) |
566 | 0 | p11_attr_clear (child_dst + j); |
567 | 0 | free (dst->pValue); |
568 | 0 | dst->pValue = NULL; |
569 | 0 | return false; |
570 | 0 | } |
571 | 516 | } |
572 | 5.84k | } else { |
573 | 5.84k | memcpy (dst->pValue, src->pValue, src->ulValueLen); |
574 | 5.84k | } |
575 | | |
576 | 6.02k | return true; |
577 | 6.02k | } |
578 | | |
579 | | void |
580 | | p11_attr_clear (CK_ATTRIBUTE *attr) |
581 | 5.98k | { |
582 | 5.98k | if (attr == NULL || attr->pValue == NULL) |
583 | 0 | return; |
584 | | |
585 | 5.98k | if (IS_ATTRIBUTE_ARRAY (attr)) { |
586 | 171 | CK_ATTRIBUTE *child; |
587 | 171 | size_t i; |
588 | | |
589 | 171 | for (i = 0, child = attr->pValue; |
590 | 684 | i < attr->ulValueLen / sizeof (CK_ATTRIBUTE); |
591 | 513 | i++, child++) |
592 | 513 | p11_attr_clear (child); |
593 | 171 | } |
594 | 5.98k | free (attr->pValue); |
595 | 5.98k | attr->pValue = NULL; |
596 | 5.98k | } |
597 | | |
598 | | static void |
599 | | buffer_append_printf (p11_buffer *buffer, |
600 | | const char *format, |
601 | | ...) GNUC_PRINTF(2, 3); |
602 | | |
603 | | static void |
604 | | buffer_append_printf (p11_buffer *buffer, |
605 | | const char *format, |
606 | | ...) |
607 | 0 | { |
608 | 0 | char *string; |
609 | 0 | va_list va; |
610 | |
|
611 | 0 | va_start (va, format); |
612 | 0 | if (vasprintf (&string, format, va) < 0) { |
613 | 0 | va_end (va); |
614 | 0 | return_if_reached (); |
615 | 0 | } |
616 | 0 | va_end (va); |
617 | |
|
618 | 0 | p11_buffer_add (buffer, string, -1); |
619 | 0 | free (string); |
620 | 0 | } |
621 | | |
622 | | static bool |
623 | | attribute_is_ulong_of_type (const CK_ATTRIBUTE *attr, |
624 | | CK_ULONG type) |
625 | 0 | { |
626 | 0 | if (attr->type != type) |
627 | 0 | return false; |
628 | 0 | if (attr->ulValueLen != sizeof (CK_ULONG)) |
629 | 0 | return false; |
630 | 0 | if (!attr->pValue) |
631 | 0 | return false; |
632 | 0 | return true; |
633 | 0 | } |
634 | | |
635 | | static bool |
636 | | attribute_is_trust_value (const CK_ATTRIBUTE *attr) |
637 | 0 | { |
638 | 0 | switch (attr->type) { |
639 | 0 | case CKA_NSS_TRUST_DIGITAL_SIGNATURE: |
640 | 0 | case CKA_NSS_TRUST_NON_REPUDIATION: |
641 | 0 | case CKA_NSS_TRUST_KEY_ENCIPHERMENT: |
642 | 0 | case CKA_NSS_TRUST_DATA_ENCIPHERMENT: |
643 | 0 | case CKA_NSS_TRUST_KEY_AGREEMENT: |
644 | 0 | case CKA_NSS_TRUST_KEY_CERT_SIGN: |
645 | 0 | case CKA_NSS_TRUST_CRL_SIGN: |
646 | 0 | case CKA_NSS_TRUST_SERVER_AUTH: |
647 | 0 | case CKA_NSS_TRUST_CLIENT_AUTH: |
648 | 0 | case CKA_NSS_TRUST_CODE_SIGNING: |
649 | 0 | case CKA_NSS_TRUST_EMAIL_PROTECTION: |
650 | 0 | case CKA_NSS_TRUST_IPSEC_END_SYSTEM: |
651 | 0 | case CKA_NSS_TRUST_IPSEC_TUNNEL: |
652 | 0 | case CKA_NSS_TRUST_IPSEC_USER: |
653 | 0 | case CKA_NSS_TRUST_TIME_STAMPING: |
654 | 0 | case CKA_TRUST_SERVER_AUTH: |
655 | 0 | case CKA_TRUST_CLIENT_AUTH: |
656 | 0 | case CKA_TRUST_CODE_SIGNING: |
657 | 0 | case CKA_TRUST_EMAIL_PROTECTION: |
658 | 0 | case CKA_TRUST_IPSEC_IKE: |
659 | 0 | case CKA_TRUST_TIME_STAMPING: |
660 | 0 | case CKA_TRUST_OCSP_SIGNING: |
661 | 0 | break; |
662 | 0 | default: |
663 | 0 | return false; |
664 | 0 | } |
665 | | |
666 | 0 | return attribute_is_ulong_of_type (attr, attr->type); |
667 | 0 | } |
668 | | |
669 | | static bool |
670 | | attribute_is_sensitive (const CK_ATTRIBUTE *attr, |
671 | | CK_OBJECT_CLASS klass) |
672 | 0 | { |
673 | | /* |
674 | | * Don't print any just attribute, since they may contain |
675 | | * sensitive data |
676 | | */ |
677 | |
|
678 | 0 | switch (attr->type) { |
679 | 0 | #define X(x) case x: return false; |
680 | 0 | X (CKA_CLASS) |
681 | 0 | X (CKA_TOKEN) |
682 | 0 | X (CKA_PRIVATE) |
683 | 0 | X (CKA_LABEL) |
684 | 0 | X (CKA_APPLICATION) |
685 | 0 | X (CKA_OBJECT_ID) |
686 | 0 | X (CKA_CERTIFICATE_TYPE) |
687 | 0 | X (CKA_ISSUER) |
688 | 0 | X (CKA_SERIAL_NUMBER) |
689 | 0 | X (CKA_AC_ISSUER) |
690 | 0 | X (CKA_OWNER) |
691 | 0 | X (CKA_ATTR_TYPES) |
692 | 0 | X (CKA_TRUSTED) |
693 | 0 | X (CKA_CERTIFICATE_CATEGORY) |
694 | 0 | X (CKA_JAVA_MIDP_SECURITY_DOMAIN) |
695 | 0 | X (CKA_URL) |
696 | 0 | X (CKA_HASH_OF_SUBJECT_PUBLIC_KEY) |
697 | 0 | X (CKA_HASH_OF_ISSUER_PUBLIC_KEY) |
698 | 0 | X (CKA_CHECK_VALUE) |
699 | 0 | X (CKA_KEY_TYPE) |
700 | 0 | X (CKA_SUBJECT) |
701 | 0 | X (CKA_ID) |
702 | 0 | X (CKA_SENSITIVE) |
703 | 0 | X (CKA_ENCRYPT) |
704 | 0 | X (CKA_DECRYPT) |
705 | 0 | X (CKA_WRAP) |
706 | 0 | X (CKA_UNWRAP) |
707 | 0 | X (CKA_SIGN) |
708 | 0 | X (CKA_SIGN_RECOVER) |
709 | 0 | X (CKA_VERIFY) |
710 | 0 | X (CKA_VERIFY_RECOVER) |
711 | 0 | X (CKA_DERIVE) |
712 | 0 | X (CKA_START_DATE) |
713 | 0 | X (CKA_END_DATE) |
714 | 0 | X (CKA_MODULUS_BITS) |
715 | 0 | X (CKA_PRIME_BITS) |
716 | | /* X (CKA_SUBPRIME_BITS) */ |
717 | | /* X (CKA_SUB_PRIME_BITS) */ |
718 | 0 | X (CKA_VALUE_BITS) |
719 | 0 | X (CKA_VALUE_LEN) |
720 | 0 | X (CKA_EXTRACTABLE) |
721 | 0 | X (CKA_LOCAL) |
722 | 0 | X (CKA_NEVER_EXTRACTABLE) |
723 | 0 | X (CKA_ALWAYS_SENSITIVE) |
724 | 0 | X (CKA_KEY_GEN_MECHANISM) |
725 | 0 | X (CKA_MODIFIABLE) |
726 | 0 | X (CKA_SECONDARY_AUTH) |
727 | 0 | X (CKA_AUTH_PIN_FLAGS) |
728 | 0 | X (CKA_ALWAYS_AUTHENTICATE) |
729 | 0 | X (CKA_WRAP_WITH_TRUSTED) |
730 | 0 | X (CKA_WRAP_TEMPLATE) |
731 | 0 | X (CKA_UNWRAP_TEMPLATE) |
732 | 0 | X (CKA_HW_FEATURE_TYPE) |
733 | 0 | X (CKA_RESET_ON_INIT) |
734 | 0 | X (CKA_HAS_RESET) |
735 | 0 | X (CKA_PIXEL_X) |
736 | 0 | X (CKA_PIXEL_Y) |
737 | 0 | X (CKA_RESOLUTION) |
738 | 0 | X (CKA_CHAR_ROWS) |
739 | 0 | X (CKA_CHAR_COLUMNS) |
740 | 0 | X (CKA_COLOR) |
741 | 0 | X (CKA_BITS_PER_PIXEL) |
742 | 0 | X (CKA_CHAR_SETS) |
743 | 0 | X (CKA_ENCODING_METHODS) |
744 | 0 | X (CKA_MIME_TYPES) |
745 | 0 | X (CKA_MECHANISM_TYPE) |
746 | 0 | X (CKA_REQUIRED_CMS_ATTRIBUTES) |
747 | 0 | X (CKA_DEFAULT_CMS_ATTRIBUTES) |
748 | 0 | X (CKA_SUPPORTED_CMS_ATTRIBUTES) |
749 | 0 | X (CKA_ALLOWED_MECHANISMS) |
750 | 0 | X (CKA_TRUST_SERVER_AUTH) |
751 | 0 | X (CKA_TRUST_CLIENT_AUTH) |
752 | 0 | X (CKA_TRUST_CODE_SIGNING) |
753 | 0 | X (CKA_TRUST_EMAIL_PROTECTION) |
754 | 0 | X (CKA_TRUST_IPSEC_IKE) |
755 | 0 | X (CKA_TRUST_TIME_STAMPING) |
756 | 0 | X (CKA_TRUST_OCSP_SIGNING) |
757 | 0 | X (CKA_X_ASSERTION_TYPE) |
758 | 0 | X (CKA_X_CERTIFICATE_VALUE) |
759 | 0 | X (CKA_X_PURPOSE) |
760 | 0 | X (CKA_X_PEER) |
761 | 0 | X (CKA_X_DISTRUSTED) |
762 | 0 | X (CKA_X_CRITICAL) |
763 | 0 | X (CKA_PUBLIC_KEY_INFO) |
764 | 0 | X (CKA_NSS_URL) |
765 | 0 | X (CKA_NSS_EMAIL) |
766 | 0 | X (CKA_NSS_SMIME_INFO) |
767 | 0 | X (CKA_NSS_SMIME_TIMESTAMP) |
768 | 0 | X (CKA_NSS_PKCS8_SALT) |
769 | 0 | X (CKA_NSS_PASSWORD_CHECK) |
770 | 0 | X (CKA_NSS_EXPIRES) |
771 | 0 | X (CKA_NSS_KRL) |
772 | 0 | X (CKA_NSS_PQG_COUNTER) |
773 | 0 | X (CKA_NSS_PQG_SEED) |
774 | 0 | X (CKA_NSS_PQG_H) |
775 | 0 | X (CKA_NSS_PQG_SEED_BITS) |
776 | 0 | X (CKA_NSS_MODULE_SPEC) |
777 | 0 | X (CKA_NSS_TRUST_DIGITAL_SIGNATURE) |
778 | 0 | X (CKA_NSS_TRUST_NON_REPUDIATION) |
779 | 0 | X (CKA_NSS_TRUST_KEY_ENCIPHERMENT) |
780 | 0 | X (CKA_NSS_TRUST_DATA_ENCIPHERMENT) |
781 | 0 | X (CKA_NSS_TRUST_KEY_AGREEMENT) |
782 | 0 | X (CKA_NSS_TRUST_KEY_CERT_SIGN) |
783 | 0 | X (CKA_NSS_TRUST_CRL_SIGN) |
784 | 0 | X (CKA_NSS_TRUST_SERVER_AUTH) |
785 | 0 | X (CKA_NSS_TRUST_CLIENT_AUTH) |
786 | 0 | X (CKA_NSS_TRUST_CODE_SIGNING) |
787 | 0 | X (CKA_NSS_TRUST_EMAIL_PROTECTION) |
788 | 0 | X (CKA_NSS_TRUST_IPSEC_END_SYSTEM) |
789 | 0 | X (CKA_NSS_TRUST_IPSEC_TUNNEL) |
790 | 0 | X (CKA_NSS_TRUST_IPSEC_USER) |
791 | 0 | X (CKA_NSS_TRUST_TIME_STAMPING) |
792 | 0 | X (CKA_NSS_TRUST_STEP_UP_APPROVED) |
793 | 0 | X (CKA_NSS_CERT_SHA1_HASH) |
794 | 0 | X (CKA_NSS_CERT_MD5_HASH) |
795 | 0 | X (CKA_IBM_OPAQUE) |
796 | 0 | X (CKA_IBM_RESTRICTABLE) |
797 | 0 | X (CKA_IBM_NEVER_MODIFIABLE) |
798 | 0 | X (CKA_IBM_RETAINKEY) |
799 | 0 | X (CKA_IBM_ATTRBOUND) |
800 | 0 | X (CKA_IBM_KEYTYPE) |
801 | 0 | X (CKA_IBM_CV) |
802 | 0 | X (CKA_IBM_MACKEY) |
803 | 0 | X (CKA_IBM_USE_AS_DATA) |
804 | 0 | X (CKA_IBM_STRUCT_PARAMS) |
805 | 0 | X (CKA_IBM_STD_COMPLIANCE1) |
806 | 0 | X (CKA_IBM_PROTKEY_EXTRACTABLE) |
807 | 0 | X (CKA_IBM_PROTKEY_NEVER_EXTRACTABLE) |
808 | 0 | X (CKA_IBM_OPAQUE_PKEY) |
809 | 0 | X (CKA_IBM_DILITHIUM_MODE) |
810 | 0 | X (CKA_IBM_DILITHIUM_KEYFORM) |
811 | 0 | X (CKA_IBM_DILITHIUM_RHO) |
812 | 0 | X (CKA_IBM_DILITHIUM_T1) |
813 | 0 | X (CKA_IBM_KYBER_MODE) |
814 | 0 | X (CKA_IBM_KYBER_PK) |
815 | 0 | X (CKA_IBM_KYBER_KEYFORM) |
816 | 0 | case CKA_VALUE: |
817 | 0 | return (klass != CKO_CERTIFICATE && |
818 | 0 | klass != CKO_X_CERTIFICATE_EXTENSION); |
819 | 0 | #undef X |
820 | 0 | } |
821 | | |
822 | 0 | return true; |
823 | 0 | } |
824 | | |
825 | | static void |
826 | | format_class (p11_buffer *buffer, |
827 | | CK_OBJECT_CLASS klass) |
828 | 0 | { |
829 | 0 | const char *string = p11_constant_name (p11_constant_classes, klass); |
830 | 0 | if (string != NULL) |
831 | 0 | p11_buffer_add (buffer, string, -1); |
832 | 0 | else |
833 | 0 | buffer_append_printf (buffer, "0x%08lX", klass); |
834 | 0 | } |
835 | | |
836 | | static void |
837 | | format_assertion_type (p11_buffer *buffer, |
838 | | CK_X_ASSERTION_TYPE type) |
839 | 0 | { |
840 | 0 | const char *string = p11_constant_name (p11_constant_asserts, type); |
841 | 0 | if (string != NULL) |
842 | 0 | p11_buffer_add (buffer, string, -1); |
843 | 0 | else |
844 | 0 | buffer_append_printf (buffer, "0x%08lX", type); |
845 | 0 | } |
846 | | |
847 | | static void |
848 | | format_key_type (p11_buffer *buffer, |
849 | | CK_KEY_TYPE type) |
850 | 0 | { |
851 | 0 | const char *string = p11_constant_name (p11_constant_keys, type); |
852 | 0 | if (string != NULL) |
853 | 0 | p11_buffer_add (buffer, string, -1); |
854 | 0 | else |
855 | 0 | buffer_append_printf (buffer, "0x%08lX", type); |
856 | 0 | } |
857 | | |
858 | | static void |
859 | | format_certificate_type (p11_buffer *buffer, |
860 | | CK_CERTIFICATE_TYPE type) |
861 | 0 | { |
862 | 0 | const char *string = p11_constant_name (p11_constant_certs, type); |
863 | 0 | if (string != NULL) |
864 | 0 | p11_buffer_add (buffer, string, -1); |
865 | 0 | else |
866 | 0 | buffer_append_printf (buffer, "0x%08lX", type); |
867 | 0 | } |
868 | | |
869 | | static void |
870 | | format_trust_value (p11_buffer *buffer, |
871 | | CK_TRUST trust) |
872 | 0 | { |
873 | 0 | const char *string = p11_constant_name (p11_constant_trusts, trust); |
874 | 0 | if (string != NULL) |
875 | 0 | p11_buffer_add (buffer, string, -1); |
876 | 0 | else |
877 | 0 | buffer_append_printf (buffer, "0x%08lX", trust); |
878 | 0 | } |
879 | | |
880 | | static void |
881 | | format_certificate_category (p11_buffer *buffer, |
882 | | CK_ULONG category) |
883 | 0 | { |
884 | 0 | const char *string = p11_constant_name (p11_constant_categories, category); |
885 | 0 | if (string != NULL) |
886 | 0 | buffer_append_printf (buffer, "%lu (%s)", category, string); |
887 | 0 | else |
888 | 0 | buffer_append_printf (buffer, "%lu", category); |
889 | 0 | } |
890 | | |
891 | | static void |
892 | | format_attribute_type (p11_buffer *buffer, |
893 | | CK_ULONG type) |
894 | 0 | { |
895 | 0 | const char *string = p11_constant_name (p11_constant_types, type); |
896 | 0 | if (string != NULL) |
897 | 0 | p11_buffer_add (buffer, string, -1); |
898 | 0 | else |
899 | 0 | buffer_append_printf (buffer, "CKA_0x%08lX", type); |
900 | 0 | } |
901 | | |
902 | | static void |
903 | | format_some_bytes (p11_buffer *buffer, |
904 | | void *bytes, |
905 | | CK_ULONG length) |
906 | 0 | { |
907 | 0 | unsigned char ch; |
908 | 0 | const unsigned char *data = bytes; |
909 | 0 | CK_ULONG i; |
910 | |
|
911 | 0 | if (bytes == NULL) { |
912 | 0 | p11_buffer_add (buffer, "NULL", -1); |
913 | 0 | return; |
914 | 0 | } |
915 | | |
916 | 0 | p11_buffer_add (buffer, "\"", 1); |
917 | 0 | for (i = 0; i < length && i < 128; i++) { |
918 | 0 | ch = data[i]; |
919 | 0 | if (ch == '\t') |
920 | 0 | p11_buffer_add (buffer, "\\t", -1); |
921 | 0 | else if (ch == '\n') |
922 | 0 | p11_buffer_add (buffer, "\\n", -1); |
923 | 0 | else if (ch == '\r') |
924 | 0 | p11_buffer_add (buffer, "\\r", -1); |
925 | 0 | else if (ch >= 32 && ch < 127) |
926 | 0 | p11_buffer_add (buffer, &ch, 1); |
927 | 0 | else |
928 | 0 | buffer_append_printf (buffer, "\\x%02x", ch); |
929 | 0 | } |
930 | |
|
931 | 0 | if (i < length) |
932 | 0 | buffer_append_printf (buffer, "..."); |
933 | 0 | p11_buffer_add (buffer, "\"", 1); |
934 | 0 | } |
935 | | |
936 | | void |
937 | | p11_attr_format (p11_buffer *buffer, |
938 | | const CK_ATTRIBUTE *attr, |
939 | | CK_OBJECT_CLASS klass) |
940 | 0 | { |
941 | 0 | p11_buffer_add (buffer, "{ ", -1); |
942 | 0 | format_attribute_type (buffer, attr->type); |
943 | 0 | p11_buffer_add (buffer, " = ", -1); |
944 | 0 | if (attr->ulValueLen == CKA_INVALID) { |
945 | 0 | buffer_append_printf (buffer, "(-1) INVALID"); |
946 | 0 | } else if (attribute_is_ulong_of_type (attr, CKA_CLASS)) { |
947 | 0 | format_class (buffer, *((CK_OBJECT_CLASS *)attr->pValue)); |
948 | 0 | } else if (attribute_is_ulong_of_type (attr, CKA_X_ASSERTION_TYPE)) { |
949 | 0 | format_assertion_type (buffer, *((CK_X_ASSERTION_TYPE *)attr->pValue)); |
950 | 0 | } else if (attribute_is_ulong_of_type (attr, CKA_CERTIFICATE_TYPE)) { |
951 | 0 | format_certificate_type (buffer, *((CK_CERTIFICATE_TYPE *)attr->pValue)); |
952 | 0 | } else if (attribute_is_ulong_of_type (attr, CKA_CERTIFICATE_CATEGORY)) { |
953 | 0 | format_certificate_category (buffer, *((CK_ULONG *)attr->pValue)); |
954 | 0 | } else if (attribute_is_ulong_of_type (attr, CKA_KEY_TYPE)) { |
955 | 0 | format_key_type (buffer, *((CK_KEY_TYPE *)attr->pValue)); |
956 | 0 | } else if (attribute_is_trust_value (attr)) { |
957 | 0 | format_trust_value (buffer, *((CK_TRUST *)attr->pValue)); |
958 | 0 | } else if (attribute_is_sensitive (attr, klass)) { |
959 | 0 | buffer_append_printf (buffer, "(%lu) NOT-PRINTED", attr->ulValueLen); |
960 | 0 | } else { |
961 | 0 | buffer_append_printf (buffer, "(%lu) ", attr->ulValueLen); |
962 | 0 | format_some_bytes (buffer, attr->pValue, attr->ulValueLen); |
963 | 0 | } |
964 | 0 | p11_buffer_add (buffer, " }", -1); |
965 | 0 | } |
966 | | |
967 | | void |
968 | | p11_attrs_format (p11_buffer *buffer, |
969 | | const CK_ATTRIBUTE *attrs, |
970 | | int count) |
971 | 0 | { |
972 | 0 | CK_BBOOL first = CK_TRUE; |
973 | 0 | CK_OBJECT_CLASS klass; |
974 | 0 | int i; |
975 | |
|
976 | 0 | if (count < 0) |
977 | 0 | count = p11_attrs_count (attrs); |
978 | |
|
979 | 0 | if (!p11_attrs_findn_ulong (attrs, CKA_CLASS, count, &klass)) |
980 | 0 | klass = CKA_INVALID; |
981 | |
|
982 | 0 | buffer_append_printf (buffer, "(%d) [", count); |
983 | 0 | for (i = 0; i < count; i++) { |
984 | 0 | if (first) |
985 | 0 | p11_buffer_add (buffer, " ", 1); |
986 | 0 | else |
987 | 0 | p11_buffer_add (buffer, ", ", 2); |
988 | 0 | first = CK_FALSE; |
989 | 0 | p11_attr_format (buffer, attrs + i, klass); |
990 | 0 | } |
991 | 0 | p11_buffer_add (buffer, " ]", -1); |
992 | 0 | } |
993 | | |
994 | | char * |
995 | | p11_attrs_to_string (const CK_ATTRIBUTE *attrs, |
996 | | int count) |
997 | 0 | { |
998 | 0 | p11_buffer buffer; |
999 | 0 | if (!p11_buffer_init_null (&buffer, 128)) |
1000 | 0 | return_val_if_reached (NULL); |
1001 | 0 | p11_attrs_format (&buffer, attrs, count); |
1002 | 0 | return p11_buffer_steal (&buffer, NULL); |
1003 | 0 | } |
1004 | | |
1005 | | char * |
1006 | | p11_attr_to_string (const CK_ATTRIBUTE *attr, |
1007 | | CK_OBJECT_CLASS klass) |
1008 | 0 | { |
1009 | 0 | p11_buffer buffer; |
1010 | 0 | if (!p11_buffer_init_null (&buffer, 32)) |
1011 | 0 | return_val_if_reached (NULL); |
1012 | 0 | p11_attr_format (&buffer, attr, klass); |
1013 | | return p11_buffer_steal (&buffer, NULL); |
1014 | 0 | } |