xref: /titanic_50/usr/src/lib/pkcs11/libpkcs11/common/metaAttrManager.c (revision 03831d35f7499c87d51205817c93e9a8d42c4bae)
1 /*
2  * CDDL HEADER START
3  *
4  * The contents of this file are subject to the terms of the
5  * Common Development and Distribution License, Version 1.0 only
6  * (the "License").  You may not use this file except in compliance
7  * with the License.
8  *
9  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
10  * or http://www.opensolaris.org/os/licensing.
11  * See the License for the specific language governing permissions
12  * and limitations under the License.
13  *
14  * When distributing Covered Code, include this CDDL HEADER in each
15  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
16  * If applicable, add the following below this CDDL HEADER, with the
17  * fields enclosed by brackets "[]" replaced with your own identifying
18  * information: Portions Copyright [yyyy] [name of copyright owner]
19  *
20  * CDDL HEADER END
21  */
22 /*
23  * Copyright 2005 Sun Microsystems, Inc.  All rights reserved.
24  * Use is subject to license terms.
25  */
26 
27 #pragma ident	"%Z%%M%	%I%	%E% SMI"
28 
29 #include <string.h>
30 #include <stdlib.h>
31 #include <strings.h>
32 #include "metaGlobal.h"
33 #include "metaAttrMasters.h"
34 
35 static void
36 find_attribute(CK_ATTRIBUTE_TYPE attrtype, generic_attr_t *attributes,
37 	size_t num_attributes, generic_attr_t **found_attribute);
38 
39 /*
40  * get_master_attributes_by_object
41  *
42  * Returns an (statically allocated) set of object attributes, as determined by
43  * class and keytype of the supplied object.  The attributes are only
44  * initialized to default values.
45  */
46 CK_RV
47 get_master_attributes_by_object(slot_session_t *session,
48     slot_object_t *slot_object, generic_attr_t **attributes,
49     size_t *num_attributes)
50 {
51 	CK_RV rv;
52 	CK_ATTRIBUTE attr;
53 	CK_OBJECT_CLASS class;
54 	CK_ULONG subtype = CK_UNAVAILABLE_INFORMATION;
55 
56 	/* first get the class */
57 	attr.type = CKA_CLASS;
58 	attr.pValue = &class;
59 	attr.ulValueLen = sizeof (class);
60 	rv = FUNCLIST(session->fw_st_id)->C_GetAttributeValue(
61 	    session->hSession, slot_object->hObject, &attr, 1);
62 	if (rv != CKR_OK) {
63 		return (rv);
64 	}
65 
66 	attr.pValue = &subtype;
67 	attr.ulValueLen = sizeof (subtype);
68 	switch (class) {
69 		case CKO_CERTIFICATE:
70 			attr.type = CKA_CERTIFICATE_TYPE;
71 			break;
72 		case CKO_HW_FEATURE:
73 			attr.type = CKA_HW_FEATURE_TYPE;
74 			break;
75 		case CKO_PUBLIC_KEY:
76 		case CKO_PRIVATE_KEY:
77 		case CKO_SECRET_KEY:
78 		case CKO_DOMAIN_PARAMETERS:
79 			attr.type = CKA_KEY_TYPE;
80 			break;
81 		case CKO_DATA:
82 			goto get_attr;
83 			break;
84 		default:
85 			/* should never be here */
86 			return (CKR_ATTRIBUTE_VALUE_INVALID);
87 	}
88 	rv = FUNCLIST(session->fw_st_id)->C_GetAttributeValue(
89 	    session->hSession, slot_object->hObject, &attr, 1);
90 	if (rv != CKR_OK) {
91 		return (rv);
92 	}
93 
94 get_attr:
95 	rv = get_master_attributes_by_type(class, subtype,
96 	    attributes, num_attributes);
97 
98 	return (rv);
99 }
100 
101 /*
102  * get_master_attributes_by_template
103  *
104  * Returns an (statically allocated) set of object attributes, as determined by
105  * the supplied object template. The template is only used to determine the
106  * class/subclass of the object. The attributes are only initialized to
107  * default values.
108  */
109 CK_RV
110 get_master_attributes_by_template(
111 	CK_ATTRIBUTE *template, CK_ULONG template_size,
112 	generic_attr_t **attributes, size_t *num_attributes)
113 {
114 	CK_OBJECT_CLASS class;
115 	CK_ULONG subtype = CK_UNAVAILABLE_INFORMATION;
116 	boolean_t found;
117 
118 	found = get_template_ulong(CKA_CLASS, template, template_size, &class);
119 	if (!found) {
120 		return (CKR_TEMPLATE_INCOMPLETE);
121 	}
122 
123 	switch (class) {
124 		case CKO_CERTIFICATE:
125 			found = get_template_ulong(CKA_CERTIFICATE_TYPE,
126 			    template, template_size, &subtype);
127 			break;
128 		case CKO_HW_FEATURE:
129 			found = get_template_ulong(CKA_HW_FEATURE_TYPE,
130 			    template, template_size, &subtype);
131 			break;
132 		case CKO_PUBLIC_KEY:
133 		case CKO_PRIVATE_KEY:
134 		case CKO_SECRET_KEY:
135 		case CKO_DOMAIN_PARAMETERS:
136 			found = get_template_ulong(CKA_KEY_TYPE,
137 			    template, template_size, &subtype);
138 			break;
139 		case CKO_DATA:
140 			/* CKO_DATA has no subtype, just pretend it is found  */
141 			found = B_TRUE;
142 		default:
143 			/* unknown object class */
144 			return (CKR_ATTRIBUTE_VALUE_INVALID);
145 	}
146 
147 	if (!found) {
148 		return (CKR_TEMPLATE_INCOMPLETE);
149 	}
150 
151 	return (get_master_attributes_by_type(class, subtype,
152 		attributes, num_attributes));
153 }
154 
155 /*
156  * get_master_template_by_type
157  *
158  * Returns an (statically allocated) set of object attributes, as determined
159  * by the specified class and subtype. The attributes are initialized to default
160  * values.
161  */
162 CK_RV
163 get_master_template_by_type(CK_OBJECT_CLASS class, CK_ULONG subtype,
164     generic_attr_t **attributes, size_t *num_attributes)
165 {
166 	generic_attr_t *master_template = NULL;
167 	size_t master_template_size = 0;
168 
169 	switch (class) {
170 	    case CKO_HW_FEATURE:
171 		switch (subtype) {
172 		    case CKO_HW_FEATURE:
173 			master_template = (generic_attr_t *)OBJ_HW_CLOCK;
174 			master_template_size = sizeof (OBJ_HW_CLOCK);
175 			break;
176 
177 		    case CKH_MONOTONIC_COUNTER:
178 			master_template = (generic_attr_t *)OBJ_HW_MONOTONIC;
179 			master_template_size = sizeof (OBJ_HW_MONOTONIC);
180 			break;
181 
182 		    default:
183 			/* Unsupported. */
184 			break;
185 		}
186 		break;
187 
188 	    case CKO_DATA:
189 		/* Objects of this class have no subtype. */
190 		master_template = (generic_attr_t *)OBJ_DATA;
191 		master_template_size = sizeof (OBJ_DATA);
192 		break;
193 
194 	    case CKO_CERTIFICATE:
195 		switch (subtype) {
196 		    case CKC_X_509:
197 			master_template = (generic_attr_t *)OBJ_CERT_X509;
198 			master_template_size = sizeof (OBJ_CERT_X509);
199 			break;
200 
201 		    case CKC_X_509_ATTR_CERT:
202 			master_template = (generic_attr_t *)OBJ_CERT_X509ATTR;
203 			master_template_size = sizeof (OBJ_CERT_X509ATTR);
204 			break;
205 
206 		    default:
207 			/* Unsupported. */
208 			break;
209 		}
210 		break;
211 
212 	    case CKO_PUBLIC_KEY:
213 		switch (subtype) {
214 		    case CKK_RSA:
215 			master_template = (generic_attr_t *)OBJ_PUBKEY_RSA;
216 			master_template_size = sizeof (OBJ_PUBKEY_RSA);
217 			break;
218 
219 		    case CKK_DSA:
220 			master_template = (generic_attr_t *)OBJ_PUBKEY_DSA;
221 			master_template_size = sizeof (OBJ_PUBKEY_DSA);
222 			break;
223 
224 		    case CKK_EC:
225 			master_template = (generic_attr_t *)OBJ_PUBKEY_EC;
226 			master_template_size = sizeof (OBJ_PUBKEY_EC);
227 			break;
228 
229 		    case CKK_DH:
230 			master_template = (generic_attr_t *)OBJ_PUBKEY_DH;
231 			master_template_size = sizeof (OBJ_PUBKEY_DH);
232 			break;
233 
234 		    case CKK_X9_42_DH:
235 			master_template = (generic_attr_t *)OBJ_PUBKEY_X942DH;
236 			master_template_size = sizeof (OBJ_PUBKEY_X942DH);
237 			break;
238 
239 		    case CKK_KEA:
240 			master_template = (generic_attr_t *)OBJ_PUBKEY_KEA;
241 			master_template_size = sizeof (OBJ_PUBKEY_KEA);
242 			break;
243 
244 		    default:
245 			/* Unsupported. */
246 			break;
247 		}
248 		break;
249 
250 	    case CKO_PRIVATE_KEY:
251 		switch (subtype) {
252 		    case CKK_RSA:
253 			master_template = (generic_attr_t *)OBJ_PRIVKEY_RSA;
254 			master_template_size = sizeof (OBJ_PRIVKEY_RSA);
255 			break;
256 
257 		    case CKK_DSA:
258 			master_template = (generic_attr_t *)OBJ_PRIVKEY_DSA;
259 			master_template_size = sizeof (OBJ_PRIVKEY_DSA);
260 			break;
261 
262 		    case CKK_EC:
263 			master_template = (generic_attr_t *)OBJ_PRIVKEY_EC;
264 			master_template_size = sizeof (OBJ_PRIVKEY_EC);
265 			break;
266 
267 		    case CKK_DH:
268 			master_template = (generic_attr_t *)OBJ_PRIVKEY_DH;
269 			master_template_size = sizeof (OBJ_PRIVKEY_DH);
270 			break;
271 
272 		    case CKK_X9_42_DH:
273 			master_template = (generic_attr_t *)OBJ_PRIVKEY_X942DH;
274 			master_template_size = sizeof (OBJ_PRIVKEY_X942DH);
275 			break;
276 
277 		    case CKK_KEA:
278 			master_template = (generic_attr_t *)OBJ_PRIVKEY_KEA;
279 			master_template_size = sizeof (OBJ_PRIVKEY_KEA);
280 			break;
281 
282 		    default:
283 			/* Unsupported. */
284 			break;
285 		}
286 		break;
287 
288 	    case CKO_SECRET_KEY:
289 		/*
290 		 * The only difference between secret keys is that some
291 		 * are valiable length (eg CKK_AES), while others are not
292 		 * (eg CKK_DES) -- and do not have a CKA_VALUE_LEN attribute.
293 		 *
294 		 * FUTURE(?): Consider using obj_seckey_withlen for unknown
295 		 * keytypes. This is the most likely choice, as new algorithms
296 		 * seem to support variable length keys. That's not the default
297 		 * now, because if people have implemented new key types with
298 		 * different attribute sets (like the mess of public/private
299 		 * key types), then incorrect behaviour would result. It's
300 		 * easier to relax this restriction than to tighten it (which
301 		 * would introduce a regression to anyone relying on this
302 		 * working for unknown key types).
303 		 *
304 		 */
305 		switch (subtype) {
306 		    case CKK_DES:
307 		    case CKK_DES2:
308 		    case CKK_DES3:
309 		    case CKK_IDEA:
310 		    case CKK_CDMF:
311 		    case CKK_SKIPJACK:
312 		    case CKK_BATON:
313 		    case CKK_JUNIPER:
314 			master_template = (generic_attr_t *)OBJ_SECKEY;
315 			master_template_size = sizeof (OBJ_SECKEY);
316 			break;
317 
318 		    case CKK_GENERIC_SECRET:
319 		    case CKK_RC2:
320 		    case CKK_RC4:
321 		    case CKK_RC5:
322 		    case CKK_AES:
323 		    case CKK_BLOWFISH:
324 		    case CKK_CAST:
325 		    case CKK_CAST3:
326 		    case CKK_CAST128:
327 			master_template = (generic_attr_t *)OBJ_SECKEY_WITHLEN;
328 			master_template_size = sizeof (OBJ_SECKEY_WITHLEN);
329 			break;
330 
331 		    default:
332 			/* Unsupported. */
333 			break;
334 		}
335 		break;
336 
337 	    case CKO_DOMAIN_PARAMETERS:
338 		switch (subtype) {
339 		    case CKK_DSA:
340 			master_template = (generic_attr_t *)OBJ_DOM_DSA;
341 			master_template_size = sizeof (OBJ_DOM_DSA);
342 			break;
343 
344 		    case CKK_DH:
345 			master_template = (generic_attr_t *)OBJ_DOM_DH;
346 			master_template_size = sizeof (OBJ_DOM_DH);
347 			break;
348 
349 		    case CKK_X9_42_DH:
350 			master_template = (generic_attr_t *)OBJ_DOM_X942DH;
351 			master_template_size = sizeof (OBJ_DOM_X942DH);
352 			break;
353 
354 		    default:
355 			/* Unsupported. */
356 			break;
357 		}
358 		break;
359 
360 	    default:
361 		/* Unsupported. */
362 		break;
363 	}
364 
365 	/* Requested object is unknown or invalid. */
366 	if (master_template == NULL)
367 		return (CKR_ATTRIBUTE_VALUE_INVALID);
368 	else {
369 		*attributes = master_template;
370 		*num_attributes = master_template_size;
371 		return (CKR_OK);
372 	}
373 }
374 
375 
376 /*
377  * get_master_attributes_by_type
378  *
379  * Returns an (statically allocated) set of object attributes, as determined by
380  * the specified class and subtype. The attributes are initialized to default
381  * values.
382  */
383 CK_RV
384 get_master_attributes_by_type(CK_OBJECT_CLASS class, CK_ULONG subtype,
385 	generic_attr_t **attributes, size_t *num_attributes)
386 {
387 	CK_RV rv;
388 	generic_attr_t *master_template = NULL;
389 	generic_attr_t *new_attributes;
390 	size_t i, num_new_attributes, master_template_size = 0;
391 
392 	/* Determine the appropriate master template needed. */
393 	rv = get_master_template_by_type(class, subtype,
394 		&master_template, &master_template_size);
395 	if (rv != CKR_OK)
396 		return (rv);
397 
398 	/* Duplicate the master template. */
399 	new_attributes = malloc(master_template_size);
400 	if (new_attributes == NULL)
401 		return (CKR_HOST_MEMORY);
402 
403 	(void) memcpy(new_attributes, master_template, master_template_size);
404 	num_new_attributes = master_template_size / sizeof (generic_attr_t);
405 
406 	/* Set the pointer in the appropriate storage area. */
407 	for (i = 0; i < num_new_attributes; i++) {
408 		generic_attr_t *attr;
409 
410 		attr = new_attributes + i;
411 
412 		switch (attr->attribute.ulValueLen) {
413 			case (sizeof (CK_ULONG)):
414 				attr->attribute.pValue = &attr->generic_ulong;
415 				break;
416 			case (sizeof (CK_BBOOL)):
417 				attr->attribute.pValue = &attr->generic_bbool;
418 				break;
419 			default:
420 				attr->attribute.pValue = attr->generic_data;
421 				break;
422 		}
423 
424 	}
425 
426 	/* Secret keys share a common template, so set the key type here. */
427 	if (class == CKO_SECRET_KEY) {
428 		/* Keytype / subtype is always the second attribute. */
429 		new_attributes[1].generic_ulong = subtype;
430 	}
431 
432 	*attributes = new_attributes;
433 	*num_attributes = num_new_attributes;
434 
435 	return (CKR_OK);
436 }
437 
438 
439 /*
440  * get_master_attributes_by_duplication
441  *
442  * Returns an (statically allocated) set of object attributes, as copied from an
443  * existing set of attributes. The new attributes inherit the values from
444  * the old attributes.
445  */
446 CK_RV
447 get_master_attributes_by_duplication(
448 	generic_attr_t *src_attrs, size_t num_src_attrs,
449 	generic_attr_t **dst_attrs, size_t *num_dst_attrs)
450 {
451 	CK_RV rv = CKR_OK;
452 	generic_attr_t *new_attrs, *src, *dst;
453 	size_t i;
454 
455 	new_attrs = malloc(sizeof (generic_attr_t) * num_src_attrs);
456 	if (new_attrs == NULL)
457 		return (CKR_HOST_MEMORY);
458 
459 	for (i = 0; i < num_src_attrs; i++) {
460 		src = src_attrs + i;
461 		dst = new_attrs + i;
462 
463 		*dst = *src;
464 
465 		/* Adjust pointers in dst so that they don't point to src. */
466 
467 		if (src->isMalloced) {
468 			dst->attribute.pValue =
469 				malloc(src->attribute.ulValueLen);
470 
471 			if (dst->attribute.pValue == NULL) {
472 				/*
473 				 * Continue on error, so that the cleanup
474 				 * routine doesn't see pointers to src_attrs.
475 				 */
476 				dst->attribute.ulValueLen = 0;
477 				rv = CKR_HOST_MEMORY;
478 				continue;
479 			}
480 		} else if (src->attribute.pValue == &src->generic_bbool) {
481 			dst->attribute.pValue = &dst->generic_bbool;
482 		} else if (src->attribute.pValue == &src->generic_ulong) {
483 			dst->attribute.pValue = &dst->generic_ulong;
484 		} else if (src->attribute.pValue == &src->generic_data) {
485 			dst->attribute.pValue = &dst->generic_data;
486 		} else {
487 			/* This shouldn't happen. */
488 			dst->attribute.pValue = NULL;
489 			dst->attribute.ulValueLen = 0;
490 			rv = CKR_GENERAL_ERROR;
491 			num_src_attrs = i + 1;
492 			break;
493 		}
494 
495 		(void) memcpy(dst->attribute.pValue, src->attribute.pValue,
496 			src->attribute.ulValueLen);
497 	}
498 
499 	if (rv != CKR_OK) {
500 		dealloc_attributes(new_attrs, num_src_attrs);
501 	} else {
502 		*dst_attrs = new_attrs;
503 		*num_dst_attrs = num_src_attrs;
504 	}
505 
506 	return (rv);
507 }
508 
509 
510 /*
511  * dealloc_attributes
512  *
513  * Deallocates the storage used for a set of attributes. The attribute
514  * values are zeroed out before being free'd.
515  */
516 void
517 dealloc_attributes(generic_attr_t *attributes, size_t num_attributes)
518 {
519 	size_t i;
520 	generic_attr_t *attr;
521 
522 	for (i = 0; i < num_attributes; i++) {
523 		attr = attributes + i;
524 
525 		/*
526 		 * Zero-out any attribute values. We could do this just for
527 		 * attributes with isSensitive == True, but it's not much
528 		 * extra work to just do them all. [Most attributes are just
529 		 * 1 or 4 bytes]
530 		 */
531 		bzero(attr->attribute.pValue, attr->attribute.ulValueLen);
532 
533 		if (attr->isMalloced)
534 			free(attr->attribute.pValue);
535 	}
536 
537 	free(attributes);
538 }
539 
540 
541 /*
542  * attribute_set_value
543  *
544  * Sets the value of the specified attribute. Any portion of the old value
545  * which will not be overwritten by the new value is zeroed out.
546  */
547 CK_RV
548 attribute_set_value(CK_ATTRIBUTE *new_attr,
549 	generic_attr_t *attributes, size_t num_attributes)
550 {
551 	generic_attr_t *attr = NULL;
552 
553 	if (new_attr == NULL)
554 		return (CKR_TEMPLATE_INCOMPLETE);
555 	else if (new_attr->pValue == NULL) {
556 		return (CKR_ATTRIBUTE_VALUE_INVALID);
557 	}
558 
559 	find_attribute(new_attr->type, attributes, num_attributes, &attr);
560 	if (attr == NULL) {
561 		return (CKR_ATTRIBUTE_TYPE_INVALID);
562 	}
563 
564 	/* Store the new value. */
565 	if (attr->attribute.ulValueLen >= new_attr->ulValueLen) {
566 		/* Existing storage is sufficient to store new value. */
567 
568 		/* bzero() out any data that won't be overwritten. */
569 		bzero((char *)attr->attribute.pValue + new_attr->ulValueLen,
570 			attr->attribute.ulValueLen - new_attr->ulValueLen);
571 
572 	} else if (new_attr->ulValueLen <= sizeof (attr->generic_data)) {
573 		/* Use generic storage to avoid a malloc. */
574 
575 		bzero(attr->attribute.pValue, attr->attribute.ulValueLen);
576 		if (attr->isMalloced) {
577 			/*
578 			 * If app sets a large value (triggering a malloc),
579 			 * then sets a tiny value, and finally again sets
580 			 * a large value (phew!) we could end up here.
581 			 *
582 			 * FUTURE?: Store the original malloc size, so that
583 			 * we can regrow the value up to the original size.
584 			 * This might avoid some heap churn for pathalogic
585 			 * applications.
586 			 */
587 			free(attr->attribute.pValue);
588 			attr->isMalloced = B_FALSE;
589 		}
590 
591 		attr->attribute.pValue = attr->generic_data;
592 
593 	} else {
594 		/* Need to allocate storage for the new value. */
595 		void *newStorage;
596 
597 		newStorage = malloc(new_attr->ulValueLen);
598 		if (newStorage == NULL)
599 			return (CKR_HOST_MEMORY);
600 		bzero(attr->attribute.pValue, attr->attribute.ulValueLen);
601 		attr->attribute.pValue = newStorage;
602 		attr->isMalloced = B_TRUE;
603 	}
604 
605 	(void) memcpy(attr->attribute.pValue, new_attr->pValue,
606 		new_attr->ulValueLen);
607 	attr->attribute.ulValueLen = new_attr->ulValueLen;
608 	attr->hasValueForClone = B_TRUE;
609 
610 	return (CKR_OK);
611 }
612 
613 
614 /*
615  * find_attribute
616  *
617  * Passes a pointer to the requested attribute, or NULL if not found.
618  */
619 static void
620 find_attribute(CK_ATTRIBUTE_TYPE attrtype, generic_attr_t *attributes,
621 	size_t num_attributes, generic_attr_t **found_attribute)
622 {
623 	generic_attr_t *attr;
624 	boolean_t found = B_FALSE;
625 	size_t i;
626 
627 	/* Find the requested attribute. */
628 	for (i = 0, attr = attributes; i < num_attributes; i++, attr++) {
629 		if (attr->attribute.type == attrtype) {
630 			found = B_TRUE;
631 			break;
632 		}
633 	}
634 
635 	*found_attribute = found ? attr : NULL;
636 }
637 
638 
639 /*
640  * get_template_ulong
641  *
642  * Look for the specified ulong-size attribute, and retrieve its value. The
643  * return value specifies if the attribute was found (or not).
644  */
645 boolean_t
646 get_template_ulong(CK_ATTRIBUTE_TYPE type, CK_ATTRIBUTE *attributes,
647 	CK_ULONG num_attributes, CK_ULONG *result)
648 {
649 	boolean_t found = B_FALSE;
650 	CK_ULONG i;
651 
652 	for (i = 0; i < num_attributes; i++) {
653 		if (attributes[i].type == type) {
654 			CK_ULONG *value = attributes[i].pValue;
655 
656 			*result = *value;
657 			found = B_TRUE;
658 			break;
659 		}
660 	}
661 
662 	return (found);
663 }
664 
665 
666 /*
667  * get_template_boolean
668  *
669  * Look for the specified boolean attribute, and retrieve its value. The
670  * return value specifies if the attribute was found (or not).
671  */
672 boolean_t
673 get_template_boolean(CK_ATTRIBUTE_TYPE type, CK_ATTRIBUTE *attributes,
674 	CK_ULONG num_attributes, boolean_t *result)
675 {
676 	boolean_t found = B_FALSE;
677 	CK_ULONG i;
678 
679 	for (i = 0; i < num_attributes; i++) {
680 		if (attributes[i].type == type) {
681 			CK_BBOOL *value = attributes[i].pValue;
682 
683 			if (*value == CK_FALSE)
684 				*result = B_FALSE;
685 			else
686 				*result = B_TRUE;
687 
688 			found = B_TRUE;
689 			break;
690 		}
691 	}
692 
693 	return (found);
694 }
695