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
p11_attrs_terminator(const CK_ATTRIBUTE * attrs)58 p11_attrs_terminator (const CK_ATTRIBUTE *attrs)
59 {
60 	return (attrs == NULL || attrs->type == CKA_INVALID);
61 }
62 
63 CK_ULONG
p11_attrs_count(const CK_ATTRIBUTE * attrs)64 p11_attrs_count (const CK_ATTRIBUTE *attrs)
65 {
66 	CK_ULONG count;
67 
68 	if (attrs == NULL)
69 		return 0UL;
70 
71 	for (count = 0; !p11_attrs_terminator (attrs); count++, attrs++);
72 
73 	return count;
74 }
75 
76 void
p11_attrs_free(void * attrs)77 p11_attrs_free (void *attrs)
78 {
79 	CK_ATTRIBUTE *ats = attrs;
80 	int i;
81 
82 	if (!attrs)
83 		return;
84 
85 	for (i = 0; !p11_attrs_terminator (ats + i); i++)
86 		free (ats[i].pValue);
87 	free (ats);
88 }
89 
90 static CK_ATTRIBUTE *
attrs_build(CK_ATTRIBUTE * attrs,CK_ULONG count_to_add,bool take_values,bool override,CK_ATTRIBUTE * (* generator)(void *),void * state)91 attrs_build (CK_ATTRIBUTE *attrs,
92              CK_ULONG count_to_add,
93              bool take_values,
94              bool override,
95              CK_ATTRIBUTE * (*generator) (void *),
96              void *state)
97 {
98 	CK_ATTRIBUTE *attr;
99 	CK_ATTRIBUTE *add;
100 	CK_ULONG current;
101 	CK_ULONG at;
102 	CK_ULONG j;
103 	CK_ULONG i;
104 	size_t length;
105 	void *new_memory;
106 
107 	/* How many attributes we already have */
108 	current = p11_attrs_count (attrs);
109 
110 	/* Reallocate for how many we need */
111 	length = current + count_to_add;
112 	return_val_if_fail (current <= length && length < SIZE_MAX, NULL);
113 	new_memory = reallocarray (attrs, length + 1, sizeof (CK_ATTRIBUTE));
114 	return_val_if_fail (new_memory != NULL, NULL);
115 	attrs = new_memory;
116 
117 	at = current;
118 	for (i = 0; i < count_to_add; i++) {
119 		add = (generator) (state);
120 
121 		/* Skip with invalid type */
122 		if (!add || add->type == CKA_INVALID)
123 			continue;
124 
125 		attr = NULL;
126 
127 		/* Do we have this attribute? */
128 		for (j = 0; attr == NULL && j < current; j++) {
129 			if (attrs[j].type == add->type) {
130 				attr = attrs + j;
131 				break;
132 			}
133 		}
134 
135 		/* The attribute doesn't exist */
136 		if (attr == NULL) {
137 			attr = attrs + at;
138 			at++;
139 
140 		/* The attribute exists and we're not overriding */
141 		} else if (!override) {
142 			if (take_values)
143 				free (add->pValue);
144 			continue;
145 
146 		/* The attribute exitss, and we're overriding */
147 		} else {
148 			free (attr->pValue);
149 		}
150 
151 		memcpy (attr, add, sizeof (CK_ATTRIBUTE));
152 		if (!take_values && attr->pValue != NULL) {
153 			if (attr->ulValueLen == 0)
154 				attr->pValue = malloc (1);
155 			else
156 				attr->pValue = memdup (attr->pValue, attr->ulValueLen);
157 			return_val_if_fail (attr->pValue != NULL, NULL);
158 		}
159 	}
160 
161 	/* Mark this as the end */
162 	(attrs + at)->type = CKA_INVALID;
163 	assert (p11_attrs_terminator (attrs + at));
164 	return attrs;
165 }
166 
167 static CK_ATTRIBUTE *
vararg_generator(void * state)168 vararg_generator (void *state)
169 {
170 	va_list *va = state;
171 	return va_arg (*va, CK_ATTRIBUTE *);
172 }
173 
174 CK_ATTRIBUTE *
p11_attrs_build(CK_ATTRIBUTE * attrs,...)175 p11_attrs_build (CK_ATTRIBUTE *attrs,
176                  ...)
177 {
178 	CK_ULONG count;
179 	va_list va;
180 
181 	count = 0UL;
182 	va_start (va, attrs);
183 	while (va_arg (va, CK_ATTRIBUTE *))
184 		count++;
185 	va_end (va);
186 
187 	va_start (va, attrs);
188 	attrs = attrs_build (attrs, count, false, true,
189 	                     vararg_generator, &va);
190 	va_end (va);
191 
192 	return attrs;
193 }
194 
195 static CK_ATTRIBUTE *
template_generator(void * state)196 template_generator (void *state)
197 {
198 	CK_ATTRIBUTE **template = state;
199 	return (*template)++;
200 }
201 
202 CK_ATTRIBUTE *
p11_attrs_buildn(CK_ATTRIBUTE * attrs,const CK_ATTRIBUTE * add,CK_ULONG count)203 p11_attrs_buildn (CK_ATTRIBUTE *attrs,
204                   const CK_ATTRIBUTE *add,
205                   CK_ULONG count)
206 {
207 	return attrs_build (attrs, count, false, true,
208 	                    template_generator, &add);
209 }
210 
211 CK_ATTRIBUTE *
p11_attrs_take(CK_ATTRIBUTE * attrs,CK_ATTRIBUTE_TYPE type,CK_VOID_PTR value,CK_ULONG length)212 p11_attrs_take (CK_ATTRIBUTE *attrs,
213                 CK_ATTRIBUTE_TYPE type,
214                 CK_VOID_PTR value,
215                 CK_ULONG length)
216 {
217 	CK_ATTRIBUTE attr = { type, value, length };
218 	CK_ATTRIBUTE *add = &attr;
219 	return attrs_build (attrs, 1, true, true,
220 	                    template_generator, &add);
221 }
222 
223 CK_ATTRIBUTE *
p11_attrs_merge(CK_ATTRIBUTE * attrs,CK_ATTRIBUTE * merge,bool replace)224 p11_attrs_merge (CK_ATTRIBUTE *attrs,
225                  CK_ATTRIBUTE *merge,
226                  bool replace)
227 {
228 	CK_ATTRIBUTE *ptr;
229 	CK_ULONG count;
230 
231 	if (attrs == NULL)
232 		return merge;
233 
234 	ptr = merge;
235 	count = p11_attrs_count (merge);
236 
237 	attrs = attrs_build (attrs, count, true, replace,
238 	                     template_generator, &ptr);
239 
240 	/*
241 	 * Since we're supposed to own the merge attributes,
242 	 * free the container array.
243 	 */
244 	free (merge);
245 
246 	return attrs;
247 }
248 
249 CK_ATTRIBUTE *
p11_attrs_dup(const CK_ATTRIBUTE * attrs)250 p11_attrs_dup (const CK_ATTRIBUTE *attrs)
251 {
252 	CK_ULONG count;
253 
254 	count = p11_attrs_count (attrs);
255 	return p11_attrs_buildn (NULL, attrs, count);
256 }
257 
258 CK_ATTRIBUTE *
p11_attrs_find(CK_ATTRIBUTE * attrs,CK_ATTRIBUTE_TYPE type)259 p11_attrs_find (CK_ATTRIBUTE *attrs,
260                 CK_ATTRIBUTE_TYPE type)
261 {
262 	CK_ULONG i;
263 
264 	for (i = 0; !p11_attrs_terminator (attrs + i); i++) {
265 		if (attrs[i].type == type)
266 			return attrs + i;
267 	}
268 
269 	return NULL;
270 }
271 
272 CK_ATTRIBUTE *
p11_attrs_findn(CK_ATTRIBUTE * attrs,CK_ULONG count,CK_ATTRIBUTE_TYPE type)273 p11_attrs_findn (CK_ATTRIBUTE *attrs,
274                  CK_ULONG count,
275                  CK_ATTRIBUTE_TYPE type)
276 {
277 	CK_ULONG i;
278 
279 	for (i = 0; i < count; i++) {
280 		if (attrs[i].type == type)
281 			return attrs + i;
282 	}
283 
284 	return NULL;
285 }
286 
287 bool
p11_attrs_find_bool(const CK_ATTRIBUTE * attrs,CK_ATTRIBUTE_TYPE type,CK_BBOOL * value)288 p11_attrs_find_bool (const CK_ATTRIBUTE *attrs,
289                      CK_ATTRIBUTE_TYPE type,
290                      CK_BBOOL *value)
291 {
292 	CK_ULONG i;
293 
294 	for (i = 0; !p11_attrs_terminator (attrs + i); i++) {
295 		if (attrs[i].type == type &&
296 		    attrs[i].ulValueLen == sizeof (CK_BBOOL) &&
297 		    attrs[i].pValue != NULL) {
298 			*value = *((CK_BBOOL *)attrs[i].pValue);
299 			return true;
300 		}
301 	}
302 
303 	return false;
304 }
305 
306 bool
p11_attrs_findn_bool(const CK_ATTRIBUTE * attrs,CK_ULONG count,CK_ATTRIBUTE_TYPE type,CK_BBOOL * value)307 p11_attrs_findn_bool (const CK_ATTRIBUTE *attrs,
308                       CK_ULONG count,
309                       CK_ATTRIBUTE_TYPE type,
310                       CK_BBOOL *value)
311 {
312 	CK_ULONG i;
313 
314 	for (i = 0; i < count; i++) {
315 		if (attrs[i].type == type &&
316 		    attrs[i].ulValueLen == sizeof (CK_BBOOL) &&
317 		    attrs[i].pValue != NULL) {
318 			*value = *((CK_BBOOL *)attrs[i].pValue);
319 			return true;
320 		}
321 	}
322 
323 	return false;
324 }
325 
326 bool
p11_attrs_find_ulong(const CK_ATTRIBUTE * attrs,CK_ATTRIBUTE_TYPE type,CK_ULONG * value)327 p11_attrs_find_ulong (const CK_ATTRIBUTE *attrs,
328                       CK_ATTRIBUTE_TYPE type,
329                       CK_ULONG *value)
330 {
331 	CK_ULONG i;
332 
333 	for (i = 0; !p11_attrs_terminator (attrs + i); i++) {
334 		if (attrs[i].type == type &&
335 		    attrs[i].ulValueLen == sizeof (CK_ULONG) &&
336 		    attrs[i].pValue != NULL) {
337 			*value = *((CK_ULONG *)attrs[i].pValue);
338 			return true;
339 		}
340 	}
341 
342 	return false;
343 }
344 
345 bool
p11_attrs_findn_ulong(const CK_ATTRIBUTE * attrs,CK_ULONG count,CK_ATTRIBUTE_TYPE type,CK_ULONG * value)346 p11_attrs_findn_ulong (const CK_ATTRIBUTE *attrs,
347                        CK_ULONG count,
348                        CK_ATTRIBUTE_TYPE type,
349                        CK_ULONG *value)
350 {
351 	CK_ULONG i;
352 
353 	for (i = 0; i < count; i++) {
354 		if (attrs[i].type == type &&
355 		    attrs[i].ulValueLen == sizeof (CK_ULONG) &&
356 		    attrs[i].pValue != NULL) {
357 			*value = *((CK_ULONG *)attrs[i].pValue);
358 			return true;
359 		}
360 	}
361 
362 	return false;
363 }
364 
365 void *
p11_attrs_find_value(CK_ATTRIBUTE * attrs,CK_ATTRIBUTE_TYPE type,size_t * length)366 p11_attrs_find_value (CK_ATTRIBUTE *attrs,
367                       CK_ATTRIBUTE_TYPE type,
368                       size_t *length)
369 {
370 	CK_ULONG i;
371 
372 	for (i = 0; !p11_attrs_terminator (attrs + i); i++) {
373 		if (attrs[i].type == type &&
374 		    attrs[i].ulValueLen != 0 &&
375 		    attrs[i].ulValueLen != (CK_ULONG)-1 &&
376 		    attrs[i].pValue != NULL) {
377 			if (length)
378 				*length = attrs[i].ulValueLen;
379 			return attrs[i].pValue;
380 		}
381 	}
382 
383 	return NULL;
384 }
385 
386 CK_ATTRIBUTE *
p11_attrs_find_valid(CK_ATTRIBUTE * attrs,CK_ATTRIBUTE_TYPE type)387 p11_attrs_find_valid (CK_ATTRIBUTE *attrs,
388                       CK_ATTRIBUTE_TYPE type)
389 {
390 	CK_ULONG i;
391 
392 	for (i = 0; !p11_attrs_terminator (attrs + i); i++) {
393 		if (attrs[i].type == type &&
394 		    attrs[i].pValue != NULL &&
395 		    attrs[i].ulValueLen != 0 &&
396 		    attrs[i].ulValueLen != (CK_ULONG)-1)
397 			return attrs + i;
398 	}
399 
400 	return NULL;
401 }
402 
403 bool
p11_attrs_remove(CK_ATTRIBUTE * attrs,CK_ATTRIBUTE_TYPE type)404 p11_attrs_remove (CK_ATTRIBUTE *attrs,
405                   CK_ATTRIBUTE_TYPE type)
406 {
407 	CK_ULONG count;
408 	CK_ULONG i;
409 
410 	count = p11_attrs_count (attrs);
411 	for (i = 0; i < count; i++) {
412 		if (attrs[i].type == type)
413 			break;
414 	}
415 
416 	if (i == count)
417 		return false;
418 
419 	if (attrs[i].pValue)
420 		free (attrs[i].pValue);
421 
422 	memmove (attrs + i, attrs + i + 1, (count - (i + 1)) * sizeof (CK_ATTRIBUTE));
423 	attrs[count - 1].type = CKA_INVALID;
424 	return true;
425 }
426 
427 void
p11_attrs_purge(CK_ATTRIBUTE * attrs)428 p11_attrs_purge (CK_ATTRIBUTE *attrs)
429 {
430 	int in, out;
431 
432 	for (in = 0, out = 0; !p11_attrs_terminator (attrs + in); in++) {
433 		if (attrs[in].ulValueLen == (CK_ULONG)-1) {
434 			free (attrs[in].pValue);
435 			attrs[in].pValue = NULL;
436 			attrs[in].ulValueLen = 0;
437 		} else {
438 			if (in != out)
439 				memcpy (attrs + out, attrs + in, sizeof (CK_ATTRIBUTE));
440 			out++;
441 		}
442 	}
443 
444 	attrs[out].type = CKA_INVALID;
445 	assert (p11_attrs_terminator (attrs + out));
446 
447 }
448 
449 bool
p11_attrs_match(const CK_ATTRIBUTE * attrs,const CK_ATTRIBUTE * match)450 p11_attrs_match (const CK_ATTRIBUTE *attrs,
451                  const CK_ATTRIBUTE *match)
452 {
453 	CK_ATTRIBUTE *attr;
454 
455 	for (; !p11_attrs_terminator (match); match++) {
456 		attr = p11_attrs_find ((CK_ATTRIBUTE *)attrs, match->type);
457 		if (!attr)
458 			return false;
459 		if (!p11_attr_equal (attr, match))
460 			return false;
461 	}
462 
463 	return true;
464 }
465 
466 bool
p11_attrs_matchn(const CK_ATTRIBUTE * attrs,const CK_ATTRIBUTE * match,CK_ULONG count)467 p11_attrs_matchn (const CK_ATTRIBUTE *attrs,
468                   const CK_ATTRIBUTE *match,
469                   CK_ULONG count)
470 {
471 	CK_ATTRIBUTE *attr;
472 	CK_ULONG i;
473 
474 	for (i = 0; i < count; i++) {
475 		attr = p11_attrs_find ((CK_ATTRIBUTE *)attrs, match[i].type);
476 		if (!attr)
477 			return false;
478 		if (!p11_attr_equal (attr, match + i))
479 			return false;
480 	}
481 
482 	return true;
483 
484 }
485 
486 
487 bool
p11_attr_match_value(const CK_ATTRIBUTE * attr,const void * value,ssize_t length)488 p11_attr_match_value (const CK_ATTRIBUTE *attr,
489                       const void *value,
490                       ssize_t length)
491 {
492 	if (length < 0)
493 		length = strlen (value);
494 	return (attr != NULL &&
495 	        attr->ulValueLen == length &&
496 	        (attr->pValue == value ||
497 	         (attr->pValue && value &&
498 	          memcmp (attr->pValue, value, attr->ulValueLen) == 0)));
499 }
500 
501 bool
p11_attr_equal(const void * v1,const void * v2)502 p11_attr_equal (const void *v1,
503                 const void *v2)
504 {
505 	const CK_ATTRIBUTE *one = v1;
506 	const CK_ATTRIBUTE *two = v2;
507 
508 	return (one == two ||
509 		(one && two && one->type == two->type &&
510 		 p11_attr_match_value (one, two->pValue, two->ulValueLen)));
511 }
512 
513 unsigned int
p11_attr_hash(const void * data)514 p11_attr_hash (const void *data)
515 {
516 	const CK_ATTRIBUTE *attr = data;
517 	uint32_t hash = 0;
518 
519 	if (attr != NULL) {
520 		p11_hash_murmur3 (&hash,
521 		                  &attr->type, sizeof (attr->type),
522 		                  attr->pValue, (size_t)attr->ulValueLen,
523 		                  NULL);
524 	}
525 
526 	return hash;
527 }
528 
529 static void
530 buffer_append_printf (p11_buffer *buffer,
531                       const char *format,
532                       ...) GNUC_PRINTF(2, 3);
533 
534 static void
buffer_append_printf(p11_buffer * buffer,const char * format,...)535 buffer_append_printf (p11_buffer *buffer,
536                       const char *format,
537                       ...)
538 {
539 	char *string;
540 	va_list va;
541 
542 	va_start (va, format);
543 	if (vasprintf (&string, format, va) < 0) {
544 		va_end (va);
545 		return_if_reached ();
546 	}
547 	va_end (va);
548 
549 	p11_buffer_add (buffer, string, -1);
550 	free (string);
551 }
552 
553 static bool
attribute_is_ulong_of_type(const CK_ATTRIBUTE * attr,CK_ULONG type)554 attribute_is_ulong_of_type (const CK_ATTRIBUTE *attr,
555                             CK_ULONG type)
556 {
557 	if (attr->type != type)
558 		return false;
559 	if (attr->ulValueLen != sizeof (CK_ULONG))
560 		return false;
561 	if (!attr->pValue)
562 		return false;
563 	return true;
564 }
565 
566 static bool
attribute_is_trust_value(const CK_ATTRIBUTE * attr)567 attribute_is_trust_value (const CK_ATTRIBUTE *attr)
568 {
569 	switch (attr->type) {
570 	case CKA_TRUST_DIGITAL_SIGNATURE:
571 	case CKA_TRUST_NON_REPUDIATION:
572 	case CKA_TRUST_KEY_ENCIPHERMENT:
573 	case CKA_TRUST_DATA_ENCIPHERMENT:
574 	case CKA_TRUST_KEY_AGREEMENT:
575 	case CKA_TRUST_KEY_CERT_SIGN:
576 	case CKA_TRUST_CRL_SIGN:
577 	case CKA_TRUST_SERVER_AUTH:
578 	case CKA_TRUST_CLIENT_AUTH:
579 	case CKA_TRUST_CODE_SIGNING:
580 	case CKA_TRUST_EMAIL_PROTECTION:
581 	case CKA_TRUST_IPSEC_END_SYSTEM:
582 	case CKA_TRUST_IPSEC_TUNNEL:
583 	case CKA_TRUST_IPSEC_USER:
584 	case CKA_TRUST_TIME_STAMPING:
585 		break;
586 	default:
587 		return false;
588 	}
589 
590 	return attribute_is_ulong_of_type (attr, attr->type);
591 }
592 
593 static bool
attribute_is_sensitive(const CK_ATTRIBUTE * attr,CK_OBJECT_CLASS klass)594 attribute_is_sensitive (const CK_ATTRIBUTE *attr,
595                         CK_OBJECT_CLASS klass)
596 {
597 	/*
598 	 * Don't print any just attribute, since they may contain
599 	 * sensitive data
600 	 */
601 
602 	switch (attr->type) {
603 	#define X(x) case x: return false;
604 	X (CKA_CLASS)
605 	X (CKA_TOKEN)
606 	X (CKA_PRIVATE)
607 	X (CKA_LABEL)
608 	X (CKA_APPLICATION)
609 	X (CKA_OBJECT_ID)
610 	X (CKA_CERTIFICATE_TYPE)
611 	X (CKA_ISSUER)
612 	X (CKA_SERIAL_NUMBER)
613 	X (CKA_AC_ISSUER)
614 	X (CKA_OWNER)
615 	X (CKA_ATTR_TYPES)
616 	X (CKA_TRUSTED)
617 	X (CKA_CERTIFICATE_CATEGORY)
618 	X (CKA_JAVA_MIDP_SECURITY_DOMAIN)
619 	X (CKA_URL)
620 	X (CKA_HASH_OF_SUBJECT_PUBLIC_KEY)
621 	X (CKA_HASH_OF_ISSUER_PUBLIC_KEY)
622 	X (CKA_CHECK_VALUE)
623 	X (CKA_KEY_TYPE)
624 	X (CKA_SUBJECT)
625 	X (CKA_ID)
626 	X (CKA_SENSITIVE)
627 	X (CKA_ENCRYPT)
628 	X (CKA_DECRYPT)
629 	X (CKA_WRAP)
630 	X (CKA_UNWRAP)
631 	X (CKA_SIGN)
632 	X (CKA_SIGN_RECOVER)
633 	X (CKA_VERIFY)
634 	X (CKA_VERIFY_RECOVER)
635 	X (CKA_DERIVE)
636 	X (CKA_START_DATE)
637 	X (CKA_END_DATE)
638 	X (CKA_MODULUS_BITS)
639 	X (CKA_PRIME_BITS)
640 	/* X (CKA_SUBPRIME_BITS) */
641 	/* X (CKA_SUB_PRIME_BITS) */
642 	X (CKA_VALUE_BITS)
643 	X (CKA_VALUE_LEN)
644 	X (CKA_EXTRACTABLE)
645 	X (CKA_LOCAL)
646 	X (CKA_NEVER_EXTRACTABLE)
647 	X (CKA_ALWAYS_SENSITIVE)
648 	X (CKA_KEY_GEN_MECHANISM)
649 	X (CKA_MODIFIABLE)
650 	X (CKA_SECONDARY_AUTH)
651 	X (CKA_AUTH_PIN_FLAGS)
652 	X (CKA_ALWAYS_AUTHENTICATE)
653 	X (CKA_WRAP_WITH_TRUSTED)
654 	X (CKA_WRAP_TEMPLATE)
655 	X (CKA_UNWRAP_TEMPLATE)
656 	X (CKA_HW_FEATURE_TYPE)
657 	X (CKA_RESET_ON_INIT)
658 	X (CKA_HAS_RESET)
659 	X (CKA_PIXEL_X)
660 	X (CKA_PIXEL_Y)
661 	X (CKA_RESOLUTION)
662 	X (CKA_CHAR_ROWS)
663 	X (CKA_CHAR_COLUMNS)
664 	X (CKA_COLOR)
665 	X (CKA_BITS_PER_PIXEL)
666 	X (CKA_CHAR_SETS)
667 	X (CKA_ENCODING_METHODS)
668 	X (CKA_MIME_TYPES)
669 	X (CKA_MECHANISM_TYPE)
670 	X (CKA_REQUIRED_CMS_ATTRIBUTES)
671 	X (CKA_DEFAULT_CMS_ATTRIBUTES)
672 	X (CKA_SUPPORTED_CMS_ATTRIBUTES)
673 	X (CKA_ALLOWED_MECHANISMS)
674 	X (CKA_X_ASSERTION_TYPE)
675 	X (CKA_X_CERTIFICATE_VALUE)
676 	X (CKA_X_PURPOSE)
677 	X (CKA_X_PEER)
678 	X (CKA_X_DISTRUSTED)
679 	X (CKA_X_CRITICAL)
680 	X (CKA_PUBLIC_KEY_INFO)
681 	X (CKA_NSS_URL)
682 	X (CKA_NSS_EMAIL)
683 	X (CKA_NSS_SMIME_INFO)
684 	X (CKA_NSS_SMIME_TIMESTAMP)
685 	X (CKA_NSS_PKCS8_SALT)
686 	X (CKA_NSS_PASSWORD_CHECK)
687 	X (CKA_NSS_EXPIRES)
688 	X (CKA_NSS_KRL)
689 	X (CKA_NSS_PQG_COUNTER)
690 	X (CKA_NSS_PQG_SEED)
691 	X (CKA_NSS_PQG_H)
692 	X (CKA_NSS_PQG_SEED_BITS)
693 	X (CKA_NSS_MODULE_SPEC)
694 	X (CKA_TRUST_DIGITAL_SIGNATURE)
695 	X (CKA_TRUST_NON_REPUDIATION)
696 	X (CKA_TRUST_KEY_ENCIPHERMENT)
697 	X (CKA_TRUST_DATA_ENCIPHERMENT)
698 	X (CKA_TRUST_KEY_AGREEMENT)
699 	X (CKA_TRUST_KEY_CERT_SIGN)
700 	X (CKA_TRUST_CRL_SIGN)
701 	X (CKA_TRUST_SERVER_AUTH)
702 	X (CKA_TRUST_CLIENT_AUTH)
703 	X (CKA_TRUST_CODE_SIGNING)
704 	X (CKA_TRUST_EMAIL_PROTECTION)
705 	X (CKA_TRUST_IPSEC_END_SYSTEM)
706 	X (CKA_TRUST_IPSEC_TUNNEL)
707 	X (CKA_TRUST_IPSEC_USER)
708 	X (CKA_TRUST_TIME_STAMPING)
709 	X (CKA_TRUST_STEP_UP_APPROVED)
710 	X (CKA_CERT_SHA1_HASH)
711 	X (CKA_CERT_MD5_HASH)
712 	case CKA_VALUE:
713 		return (klass != CKO_CERTIFICATE &&
714 			klass != CKO_X_CERTIFICATE_EXTENSION);
715 	#undef X
716 	}
717 
718 	return true;
719 }
720 
721 static void
format_class(p11_buffer * buffer,CK_OBJECT_CLASS klass)722 format_class (p11_buffer *buffer,
723               CK_OBJECT_CLASS klass)
724 {
725 	const char *string = p11_constant_name (p11_constant_classes, klass);
726 	if (string != NULL)
727 		p11_buffer_add (buffer, string, -1);
728 	else
729 		buffer_append_printf (buffer, "0x%08lX", klass);
730 }
731 
732 static void
format_assertion_type(p11_buffer * buffer,CK_X_ASSERTION_TYPE type)733 format_assertion_type (p11_buffer *buffer,
734                        CK_X_ASSERTION_TYPE type)
735 {
736 	const char *string = p11_constant_name (p11_constant_asserts, type);
737 	if (string != NULL)
738 		p11_buffer_add (buffer, string, -1);
739 	else
740 		buffer_append_printf (buffer, "0x%08lX", type);
741 }
742 
743 static void
format_key_type(p11_buffer * buffer,CK_KEY_TYPE type)744 format_key_type (p11_buffer *buffer,
745                  CK_KEY_TYPE type)
746 {
747 	const char *string = p11_constant_name (p11_constant_keys, type);
748 	if (string != NULL)
749 		p11_buffer_add (buffer, string, -1);
750 	else
751 		buffer_append_printf (buffer, "0x%08lX", type);
752 }
753 
754 static void
format_certificate_type(p11_buffer * buffer,CK_CERTIFICATE_TYPE type)755 format_certificate_type (p11_buffer *buffer,
756                          CK_CERTIFICATE_TYPE type)
757 {
758 	const char *string = p11_constant_name (p11_constant_certs, type);
759 	if (string != NULL)
760 		p11_buffer_add (buffer, string, -1);
761 	else
762 		buffer_append_printf (buffer, "0x%08lX", type);
763 }
764 
765 static void
format_trust_value(p11_buffer * buffer,CK_TRUST trust)766 format_trust_value (p11_buffer *buffer,
767                     CK_TRUST trust)
768 {
769 	const char *string = p11_constant_name (p11_constant_trusts, trust);
770 	if (string != NULL)
771 		p11_buffer_add (buffer, string, -1);
772 	else
773 		buffer_append_printf (buffer, "0x%08lX", trust);
774 }
775 
776 static void
format_certificate_category(p11_buffer * buffer,CK_ULONG category)777 format_certificate_category (p11_buffer *buffer,
778                              CK_ULONG category)
779 {
780 	const char *string = p11_constant_name (p11_constant_categories, category);
781 	if (string != NULL)
782 		buffer_append_printf (buffer, "%lu (%s)", category, string);
783 	else
784 		buffer_append_printf (buffer, "%lu", category);
785 }
786 
787 static void
format_attribute_type(p11_buffer * buffer,CK_ULONG type)788 format_attribute_type (p11_buffer *buffer,
789                        CK_ULONG type)
790 {
791 	const char *string = p11_constant_name (p11_constant_types, type);
792 	if (string != NULL)
793 		p11_buffer_add (buffer, string, -1);
794 	else
795 		buffer_append_printf (buffer, "CKA_0x%08lX", type);
796 }
797 
798 static void
format_some_bytes(p11_buffer * buffer,void * bytes,CK_ULONG length)799 format_some_bytes (p11_buffer *buffer,
800                    void *bytes,
801                    CK_ULONG length)
802 {
803 	unsigned char ch;
804 	const unsigned char *data = bytes;
805 	CK_ULONG i;
806 
807 	if (bytes == NULL) {
808 		p11_buffer_add (buffer, "NULL", -1);
809 		return;
810 	}
811 
812 	p11_buffer_add (buffer, "\"", 1);
813 	for (i = 0; i < length && i < 128; i++) {
814 		ch = data[i];
815 		if (ch == '\t')
816 			p11_buffer_add (buffer, "\\t", -1);
817 		else if (ch == '\n')
818 			p11_buffer_add (buffer, "\\n", -1);
819 		else if (ch == '\r')
820 			p11_buffer_add (buffer, "\\r", -1);
821 		else if (ch >= 32 && ch < 127)
822 			p11_buffer_add (buffer, &ch, 1);
823 		else
824 			buffer_append_printf (buffer, "\\x%02x", ch);
825 	}
826 
827 	if (i < length)
828 		buffer_append_printf (buffer, "...");
829 	p11_buffer_add (buffer, "\"", 1);
830 }
831 
832 void
p11_attr_format(p11_buffer * buffer,const CK_ATTRIBUTE * attr,CK_OBJECT_CLASS klass)833 p11_attr_format (p11_buffer *buffer,
834                  const CK_ATTRIBUTE *attr,
835                  CK_OBJECT_CLASS klass)
836 {
837 	p11_buffer_add (buffer, "{ ", -1);
838 	format_attribute_type (buffer, attr->type);
839 	p11_buffer_add (buffer, " = ", -1);
840 	if (attr->ulValueLen == CKA_INVALID) {
841 		buffer_append_printf (buffer, "(-1) INVALID");
842 	} else if (attribute_is_ulong_of_type (attr, CKA_CLASS)) {
843 		format_class (buffer, *((CK_OBJECT_CLASS *)attr->pValue));
844 	} else if (attribute_is_ulong_of_type (attr, CKA_X_ASSERTION_TYPE)) {
845 		format_assertion_type (buffer, *((CK_X_ASSERTION_TYPE *)attr->pValue));
846 	} else if (attribute_is_ulong_of_type (attr, CKA_CERTIFICATE_TYPE)) {
847 		format_certificate_type (buffer, *((CK_CERTIFICATE_TYPE *)attr->pValue));
848 	} else if (attribute_is_ulong_of_type (attr, CKA_CERTIFICATE_CATEGORY)) {
849 		format_certificate_category (buffer, *((CK_ULONG *)attr->pValue));
850 	} else if (attribute_is_ulong_of_type (attr, CKA_KEY_TYPE)) {
851 		format_key_type (buffer, *((CK_KEY_TYPE *)attr->pValue));
852 	} else if (attribute_is_trust_value (attr)) {
853 		format_trust_value (buffer, *((CK_TRUST *)attr->pValue));
854 	} else if (attribute_is_sensitive (attr, klass)) {
855 		buffer_append_printf (buffer, "(%lu) NOT-PRINTED", attr->ulValueLen);
856 	} else {
857 		buffer_append_printf (buffer, "(%lu) ", attr->ulValueLen);
858 		format_some_bytes (buffer, attr->pValue, attr->ulValueLen);
859 	}
860 	p11_buffer_add (buffer, " }", -1);
861 }
862 
863 void
p11_attrs_format(p11_buffer * buffer,const CK_ATTRIBUTE * attrs,int count)864 p11_attrs_format (p11_buffer *buffer,
865                   const CK_ATTRIBUTE *attrs,
866                   int count)
867 {
868 	CK_BBOOL first = CK_TRUE;
869 	CK_OBJECT_CLASS klass;
870 	int i;
871 
872 	if (count < 0)
873 		count = p11_attrs_count (attrs);
874 
875 	if (!p11_attrs_findn_ulong (attrs, CKA_CLASS, count, &klass))
876 		klass = CKA_INVALID;
877 
878 	buffer_append_printf (buffer, "(%d) [", count);
879 	for (i = 0; i < count; i++) {
880 		if (first)
881 			p11_buffer_add (buffer, " ", 1);
882 		else
883 			p11_buffer_add (buffer, ", ", 2);
884 		first = CK_FALSE;
885 		p11_attr_format (buffer, attrs + i, klass);
886 	}
887 	p11_buffer_add (buffer, " ]", -1);
888 }
889 
890 char *
p11_attrs_to_string(const CK_ATTRIBUTE * attrs,int count)891 p11_attrs_to_string (const CK_ATTRIBUTE *attrs,
892                      int count)
893 {
894 	p11_buffer buffer;
895 	if (!p11_buffer_init_null (&buffer, 128))
896 		return_val_if_reached (NULL);
897 	p11_attrs_format (&buffer, attrs, count);
898 	return p11_buffer_steal (&buffer, NULL);
899 }
900 
901 char *
p11_attr_to_string(const CK_ATTRIBUTE * attr,CK_OBJECT_CLASS klass)902 p11_attr_to_string (const CK_ATTRIBUTE *attr,
903                     CK_OBJECT_CLASS klass)
904 {
905 	p11_buffer buffer;
906 	if (!p11_buffer_init_null (&buffer, 32))
907 		return_val_if_reached (NULL);
908 	p11_attr_format (&buffer, attr, klass);
909 	return p11_buffer_steal (&buffer, NULL);
910 }
911