4 * The contents of this file are subject to the terms of the
5 * Common Development and Distribution License (the "License").
6 * You may not use this file except in compliance with the License.
8 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9 * or http://www.opensolaris.org/os/licensing.
10 * See the License for the specific language governing permissions
11 * and limitations under the License.
13 * When distributing Covered Code, include this CDDL HEADER in each
14 * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15 * If applicable, add the following below this CDDL HEADER, with the
16 * fields enclosed by brackets "[]" replaced with your own identifying
17 * information: Portions Copyright [yyyy] [name of copyright owner]
22 * Copyright 2007 Sun Microsystems, Inc. All rights reserved.
23 * Use is subject to license terms.
24 * Copyright 2012 Milan Jurik. All rights reserved.
25 * Copyright (c) 2018, Joyent, Inc.
31 #include "metaGlobal.h"
32 #include "metaAttrMasters.h"
35 find_attribute(CK_ATTRIBUTE_TYPE attrtype
, generic_attr_t
*attributes
,
36 size_t num_attributes
, generic_attr_t
**found_attribute
);
39 * get_master_attributes_by_object
41 * Returns an (statically allocated) set of object attributes, as determined by
42 * class and keytype of the supplied object. The attributes are only
43 * initialized to default values.
46 get_master_attributes_by_object(slot_session_t
*session
,
47 slot_object_t
*slot_object
, generic_attr_t
**attributes
,
48 size_t *num_attributes
)
52 CK_OBJECT_CLASS
class;
53 CK_ULONG subtype
= CK_UNAVAILABLE_INFORMATION
;
55 /* first get the class */
56 attr
.type
= CKA_CLASS
;
58 attr
.ulValueLen
= sizeof (class);
59 rv
= FUNCLIST(session
->fw_st_id
)->C_GetAttributeValue(
60 session
->hSession
, slot_object
->hObject
, &attr
, 1);
65 attr
.pValue
= &subtype
;
66 attr
.ulValueLen
= sizeof (subtype
);
69 attr
.type
= CKA_CERTIFICATE_TYPE
;
72 attr
.type
= CKA_HW_FEATURE_TYPE
;
77 case CKO_DOMAIN_PARAMETERS
:
78 attr
.type
= CKA_KEY_TYPE
;
83 /* should never be here */
84 return (CKR_ATTRIBUTE_VALUE_INVALID
);
86 rv
= FUNCLIST(session
->fw_st_id
)->C_GetAttributeValue(
87 session
->hSession
, slot_object
->hObject
, &attr
, 1);
93 rv
= get_master_attributes_by_type(class, subtype
,
94 attributes
, num_attributes
);
100 * get_master_attributes_by_template
102 * Returns an (statically allocated) set of object attributes, as determined by
103 * the supplied object template. The template is only used to determine the
104 * class/subclass of the object. The attributes are only initialized to
108 get_master_attributes_by_template(
109 CK_ATTRIBUTE
*template, CK_ULONG template_size
,
110 generic_attr_t
**attributes
, size_t *num_attributes
)
112 CK_OBJECT_CLASS
class;
113 CK_ULONG subtype
= CK_UNAVAILABLE_INFORMATION
;
116 found
= get_template_ulong(CKA_CLASS
, template, template_size
, &class);
118 return (CKR_TEMPLATE_INCOMPLETE
);
122 case CKO_CERTIFICATE
:
123 found
= get_template_ulong(CKA_CERTIFICATE_TYPE
,
124 template, template_size
, &subtype
);
127 found
= get_template_ulong(CKA_HW_FEATURE_TYPE
,
128 template, template_size
, &subtype
);
131 case CKO_PRIVATE_KEY
:
133 case CKO_DOMAIN_PARAMETERS
:
134 found
= get_template_ulong(CKA_KEY_TYPE
,
135 template, template_size
, &subtype
);
138 /* CKO_DATA has no subtype, just pretend it is found */
142 /* unknown object class */
143 return (CKR_ATTRIBUTE_VALUE_INVALID
);
147 return (CKR_TEMPLATE_INCOMPLETE
);
150 return (get_master_attributes_by_type(class, subtype
,
151 attributes
, num_attributes
));
155 * get_master_template_by_type
157 * Returns an (statically allocated) set of object attributes, as determined
158 * by the specified class and subtype. The attributes are initialized to default
162 get_master_template_by_type(CK_OBJECT_CLASS
class, CK_ULONG subtype
,
163 generic_attr_t
**attributes
, size_t *num_attributes
)
165 generic_attr_t
*master_template
= NULL
;
166 size_t master_template_size
= 0;
172 master_template
= (generic_attr_t
*)OBJ_HW_CLOCK
;
173 master_template_size
= sizeof (OBJ_HW_CLOCK
);
176 case CKH_MONOTONIC_COUNTER
:
177 master_template
= (generic_attr_t
*)OBJ_HW_MONOTONIC
;
178 master_template_size
= sizeof (OBJ_HW_MONOTONIC
);
188 /* Objects of this class have no subtype. */
189 master_template
= (generic_attr_t
*)OBJ_DATA
;
190 master_template_size
= sizeof (OBJ_DATA
);
193 case CKO_CERTIFICATE
:
196 master_template
= (generic_attr_t
*)OBJ_CERT_X509
;
197 master_template_size
= sizeof (OBJ_CERT_X509
);
200 case CKC_X_509_ATTR_CERT
:
201 master_template
= (generic_attr_t
*)OBJ_CERT_X509ATTR
;
202 master_template_size
= sizeof (OBJ_CERT_X509ATTR
);
214 master_template
= (generic_attr_t
*)OBJ_PUBKEY_RSA
;
215 master_template_size
= sizeof (OBJ_PUBKEY_RSA
);
219 master_template
= (generic_attr_t
*)OBJ_PUBKEY_DSA
;
220 master_template_size
= sizeof (OBJ_PUBKEY_DSA
);
224 master_template
= (generic_attr_t
*)OBJ_PUBKEY_EC
;
225 master_template_size
= sizeof (OBJ_PUBKEY_EC
);
229 master_template
= (generic_attr_t
*)OBJ_PUBKEY_DH
;
230 master_template_size
= sizeof (OBJ_PUBKEY_DH
);
234 master_template
= (generic_attr_t
*)OBJ_PUBKEY_X942DH
;
235 master_template_size
= sizeof (OBJ_PUBKEY_X942DH
);
239 master_template
= (generic_attr_t
*)OBJ_PUBKEY_KEA
;
240 master_template_size
= sizeof (OBJ_PUBKEY_KEA
);
249 case CKO_PRIVATE_KEY
:
252 master_template
= (generic_attr_t
*)OBJ_PRIVKEY_RSA
;
253 master_template_size
= sizeof (OBJ_PRIVKEY_RSA
);
257 master_template
= (generic_attr_t
*)OBJ_PRIVKEY_DSA
;
258 master_template_size
= sizeof (OBJ_PRIVKEY_DSA
);
262 master_template
= (generic_attr_t
*)OBJ_PRIVKEY_EC
;
263 master_template_size
= sizeof (OBJ_PRIVKEY_EC
);
267 master_template
= (generic_attr_t
*)OBJ_PRIVKEY_DH
;
268 master_template_size
= sizeof (OBJ_PRIVKEY_DH
);
272 master_template
= (generic_attr_t
*)OBJ_PRIVKEY_X942DH
;
273 master_template_size
= sizeof (OBJ_PRIVKEY_X942DH
);
277 master_template
= (generic_attr_t
*)OBJ_PRIVKEY_KEA
;
278 master_template_size
= sizeof (OBJ_PRIVKEY_KEA
);
289 * The only difference between secret keys is that some
290 * are valiable length (eg CKK_AES), while others are not
291 * (eg CKK_DES) -- and do not have a CKA_VALUE_LEN attribute.
293 * FUTURE(?): Consider using obj_seckey_withlen for unknown
294 * keytypes. This is the most likely choice, as new algorithms
295 * seem to support variable length keys. That's not the default
296 * now, because if people have implemented new key types with
297 * different attribute sets (like the mess of public/private
298 * key types), then incorrect behaviour would result. It's
299 * easier to relax this restriction than to tighten it (which
300 * would introduce a regression to anyone relying on this
301 * working for unknown key types).
313 master_template
= (generic_attr_t
*)OBJ_SECKEY
;
314 master_template_size
= sizeof (OBJ_SECKEY
);
317 case CKK_GENERIC_SECRET
:
326 master_template
= (generic_attr_t
*)OBJ_SECKEY_WITHLEN
;
327 master_template_size
= sizeof (OBJ_SECKEY_WITHLEN
);
336 case CKO_DOMAIN_PARAMETERS
:
339 master_template
= (generic_attr_t
*)OBJ_DOM_DSA
;
340 master_template_size
= sizeof (OBJ_DOM_DSA
);
344 master_template
= (generic_attr_t
*)OBJ_DOM_DH
;
345 master_template_size
= sizeof (OBJ_DOM_DH
);
349 master_template
= (generic_attr_t
*)OBJ_DOM_X942DH
;
350 master_template_size
= sizeof (OBJ_DOM_X942DH
);
364 /* Requested object is unknown or invalid. */
365 if (master_template
== NULL
)
366 return (CKR_ATTRIBUTE_VALUE_INVALID
);
368 *attributes
= master_template
;
369 *num_attributes
= master_template_size
;
376 * get_master_attributes_by_type
378 * Returns an (statically allocated) set of object attributes, as determined by
379 * the specified class and subtype. The attributes are initialized to default
383 get_master_attributes_by_type(CK_OBJECT_CLASS
class, CK_ULONG subtype
,
384 generic_attr_t
**attributes
, size_t *num_attributes
)
387 generic_attr_t
*master_template
= NULL
;
388 generic_attr_t
*new_attributes
;
389 size_t i
, num_new_attributes
, master_template_size
= 0;
391 /* Determine the appropriate master template needed. */
392 rv
= get_master_template_by_type(class, subtype
,
393 &master_template
, &master_template_size
);
397 /* Duplicate the master template. */
398 new_attributes
= malloc(master_template_size
);
399 if (new_attributes
== NULL
)
400 return (CKR_HOST_MEMORY
);
402 (void) memcpy(new_attributes
, master_template
, master_template_size
);
403 num_new_attributes
= master_template_size
/ sizeof (generic_attr_t
);
405 /* Set the pointer in the appropriate storage area. */
406 for (i
= 0; i
< num_new_attributes
; i
++) {
407 generic_attr_t
*attr
;
409 attr
= new_attributes
+ i
;
411 switch (attr
->attribute
.ulValueLen
) {
412 case (sizeof (CK_ULONG
)):
413 attr
->attribute
.pValue
= &attr
->generic_ulong
;
415 case (sizeof (CK_BBOOL
)):
416 attr
->attribute
.pValue
= &attr
->generic_bbool
;
419 attr
->attribute
.pValue
= attr
->generic_data
;
425 /* Secret keys share a common template, so set the key type here. */
426 if (class == CKO_SECRET_KEY
) {
427 /* Keytype / subtype is always the second attribute. */
428 new_attributes
[1].generic_ulong
= subtype
;
431 *attributes
= new_attributes
;
432 *num_attributes
= num_new_attributes
;
439 * get_master_attributes_by_duplication
441 * Returns an (statically allocated) set of object attributes, as copied from an
442 * existing set of attributes. The new attributes inherit the values from
443 * the old attributes.
446 get_master_attributes_by_duplication(
447 generic_attr_t
*src_attrs
, size_t num_src_attrs
,
448 generic_attr_t
**dst_attrs
, size_t *num_dst_attrs
)
451 generic_attr_t
*new_attrs
, *src
, *dst
;
454 new_attrs
= malloc(sizeof (generic_attr_t
) * num_src_attrs
);
455 if (new_attrs
== NULL
)
456 return (CKR_HOST_MEMORY
);
458 for (i
= 0; i
< num_src_attrs
; i
++) {
464 /* Adjust pointers in dst so that they don't point to src. */
466 if (src
->isMalloced
) {
467 dst
->attribute
.pValue
=
468 malloc(src
->attribute
.ulValueLen
);
470 if (dst
->attribute
.pValue
== NULL
) {
472 * Continue on error, so that the cleanup
473 * routine doesn't see pointers to src_attrs.
475 dst
->attribute
.ulValueLen
= 0;
476 rv
= CKR_HOST_MEMORY
;
479 } else if (src
->attribute
.pValue
== &src
->generic_bbool
) {
480 dst
->attribute
.pValue
= &dst
->generic_bbool
;
481 } else if (src
->attribute
.pValue
== &src
->generic_ulong
) {
482 dst
->attribute
.pValue
= &dst
->generic_ulong
;
483 } else if (src
->attribute
.pValue
== &src
->generic_data
) {
484 dst
->attribute
.pValue
= &dst
->generic_data
;
486 /* This shouldn't happen. */
487 dst
->attribute
.pValue
= NULL
;
488 dst
->attribute
.ulValueLen
= 0;
489 rv
= CKR_GENERAL_ERROR
;
490 num_src_attrs
= i
+ 1;
494 (void) memcpy(dst
->attribute
.pValue
, src
->attribute
.pValue
,
495 src
->attribute
.ulValueLen
);
499 dealloc_attributes(new_attrs
, num_src_attrs
);
501 *dst_attrs
= new_attrs
;
502 *num_dst_attrs
= num_src_attrs
;
512 * Deallocates the storage used for a set of attributes. The attribute
513 * values are zeroed out before being free'd.
516 dealloc_attributes(generic_attr_t
*attributes
, size_t num_attributes
)
519 generic_attr_t
*attr
;
521 for (i
= 0; i
< num_attributes
; i
++) {
522 attr
= attributes
+ i
;
525 * Zero-out any attribute values. We could do this just for
526 * attributes with isSensitive == True, but it's not much
527 * extra work to just do them all. [Most attributes are just
530 explicit_bzero(attr
->attribute
.pValue
,
531 attr
->attribute
.ulValueLen
);
533 if (attr
->isMalloced
)
534 free(attr
->attribute
.pValue
);
542 * attribute_set_value
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.
548 attribute_set_value(CK_ATTRIBUTE
*new_attr
,
549 generic_attr_t
*attributes
, size_t num_attributes
)
551 generic_attr_t
*attr
= NULL
;
553 if (new_attr
== NULL
)
554 return (CKR_TEMPLATE_INCOMPLETE
);
555 else if (new_attr
->pValue
== NULL
) {
556 return (CKR_ATTRIBUTE_VALUE_INVALID
);
559 find_attribute(new_attr
->type
, attributes
, num_attributes
, &attr
);
561 return (CKR_ATTRIBUTE_TYPE_INVALID
);
564 /* Store the new value. */
565 if (attr
->attribute
.ulValueLen
>= new_attr
->ulValueLen
) {
566 /* Existing storage is sufficient to store new value. */
568 /* bzero() out any data that won't be overwritten. */
569 explicit_bzero((char *)attr
->attribute
.pValue
+
570 new_attr
->ulValueLen
,
571 attr
->attribute
.ulValueLen
- new_attr
->ulValueLen
);
573 } else if (new_attr
->ulValueLen
<= sizeof (attr
->generic_data
)) {
574 /* Use generic storage to avoid a malloc. */
576 explicit_bzero(attr
->attribute
.pValue
,
577 attr
->attribute
.ulValueLen
);
578 if (attr
->isMalloced
) {
580 * If app sets a large value (triggering a malloc),
581 * then sets a tiny value, and finally again sets
582 * a large value (phew!) we could end up here.
584 * FUTURE?: Store the original malloc size, so that
585 * we can regrow the value up to the original size.
586 * This might avoid some heap churn for pathalogic
589 free(attr
->attribute
.pValue
);
590 attr
->isMalloced
= B_FALSE
;
593 attr
->attribute
.pValue
= attr
->generic_data
;
596 /* Need to allocate storage for the new value. */
599 newStorage
= malloc(new_attr
->ulValueLen
);
600 if (newStorage
== NULL
)
601 return (CKR_HOST_MEMORY
);
602 bzero(attr
->attribute
.pValue
, attr
->attribute
.ulValueLen
);
603 attr
->attribute
.pValue
= newStorage
;
604 attr
->isMalloced
= B_TRUE
;
607 (void) memcpy(attr
->attribute
.pValue
, new_attr
->pValue
,
608 new_attr
->ulValueLen
);
609 attr
->attribute
.ulValueLen
= new_attr
->ulValueLen
;
610 attr
->hasValueForClone
= B_TRUE
;
619 * Passes a pointer to the requested attribute, or NULL if not found.
622 find_attribute(CK_ATTRIBUTE_TYPE attrtype
, generic_attr_t
*attributes
,
623 size_t num_attributes
, generic_attr_t
**found_attribute
)
625 generic_attr_t
*attr
;
626 boolean_t found
= B_FALSE
;
629 /* Find the requested attribute. */
630 for (i
= 0, attr
= attributes
; i
< num_attributes
; i
++, attr
++) {
631 if (attr
->attribute
.type
== attrtype
) {
637 *found_attribute
= found
? attr
: NULL
;
644 * Look for the specified ulong-size attribute, and retrieve its value. The
645 * return value specifies if the attribute was found (or not).
648 get_template_ulong(CK_ATTRIBUTE_TYPE type
, CK_ATTRIBUTE
*attributes
,
649 CK_ULONG num_attributes
, CK_ULONG
*result
)
651 boolean_t found
= B_FALSE
;
654 for (i
= 0; i
< num_attributes
; i
++) {
655 if (attributes
[i
].type
== type
) {
656 CK_ULONG
*value
= attributes
[i
].pValue
;
669 * get_template_boolean
671 * Look for the specified boolean attribute, and retrieve its value. The
672 * return value specifies if the attribute was found (or not).
675 get_template_boolean(CK_ATTRIBUTE_TYPE type
, CK_ATTRIBUTE
*attributes
,
676 CK_ULONG num_attributes
, boolean_t
*result
)
678 boolean_t found
= B_FALSE
;
681 for (i
= 0; i
< num_attributes
; i
++) {
682 if (attributes
[i
].type
== type
) {
683 CK_BBOOL
*value
= attributes
[i
].pValue
;
685 if (*value
== CK_FALSE
)
699 * set_template_boolean
701 * Look for the specified boolean attribute, and set its value.
703 * if 'local' is true, it sets the pointer to the value in the template a new
704 * location. There should be no memory leak created by this because we are
705 * only doing this to booleans which should not be malloc'ed.
707 * if 'local' is false, it sets its value.
709 * The return value specifies if the attribute was found (or not).
712 set_template_boolean(CK_ATTRIBUTE_TYPE type
, CK_ATTRIBUTE
*attributes
,
713 CK_ULONG num_attributes
, boolean_t local
, CK_BBOOL
*value
)
717 for (i
= 0; i
< num_attributes
; i
++) {
718 if (attributes
[i
].type
== type
) {
720 attributes
[i
].pValue
= value
;
722 *((CK_BBOOL
*)attributes
[i
].pValue
) = *value
;