17c478bd9Sstevel@tonic-gate /*
27c478bd9Sstevel@tonic-gate  * CDDL HEADER START
37c478bd9Sstevel@tonic-gate  *
47c478bd9Sstevel@tonic-gate  * The contents of this file are subject to the terms of the
5034448feSmcpowers  * Common Development and Distribution License (the "License").
6034448feSmcpowers  * You may not use this file except in compliance with the License.
77c478bd9Sstevel@tonic-gate  *
87c478bd9Sstevel@tonic-gate  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
97c478bd9Sstevel@tonic-gate  * or http://www.opensolaris.org/os/licensing.
107c478bd9Sstevel@tonic-gate  * See the License for the specific language governing permissions
117c478bd9Sstevel@tonic-gate  * and limitations under the License.
127c478bd9Sstevel@tonic-gate  *
137c478bd9Sstevel@tonic-gate  * When distributing Covered Code, include this CDDL HEADER in each
147c478bd9Sstevel@tonic-gate  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
157c478bd9Sstevel@tonic-gate  * If applicable, add the following below this CDDL HEADER, with the
167c478bd9Sstevel@tonic-gate  * fields enclosed by brackets "[]" replaced with your own identifying
177c478bd9Sstevel@tonic-gate  * information: Portions Copyright [yyyy] [name of copyright owner]
187c478bd9Sstevel@tonic-gate  *
197c478bd9Sstevel@tonic-gate  * CDDL HEADER END
207c478bd9Sstevel@tonic-gate  */
217c478bd9Sstevel@tonic-gate /*
22034448feSmcpowers  * Copyright 2007 Sun Microsystems, Inc.  All rights reserved.
237c478bd9Sstevel@tonic-gate  * Use is subject to license terms.
2433f5ff17SMilan Jurik  * Copyright 2012 Milan Jurik. All rights reserved.
25*a8793c76SJason King  * Copyright (c) 2018, Joyent, Inc.
267c478bd9Sstevel@tonic-gate  */
277c478bd9Sstevel@tonic-gate 
287c478bd9Sstevel@tonic-gate #include <string.h>
297c478bd9Sstevel@tonic-gate #include <stdlib.h>
307c478bd9Sstevel@tonic-gate #include <strings.h>
317c478bd9Sstevel@tonic-gate #include "metaGlobal.h"
327c478bd9Sstevel@tonic-gate #include "metaAttrMasters.h"
337c478bd9Sstevel@tonic-gate 
347c478bd9Sstevel@tonic-gate static void
357c478bd9Sstevel@tonic-gate find_attribute(CK_ATTRIBUTE_TYPE attrtype, generic_attr_t *attributes,
36*a8793c76SJason King     size_t num_attributes, generic_attr_t **found_attribute);
377c478bd9Sstevel@tonic-gate 
387c478bd9Sstevel@tonic-gate /*
397c478bd9Sstevel@tonic-gate  * get_master_attributes_by_object
407c478bd9Sstevel@tonic-gate  *
417c478bd9Sstevel@tonic-gate  * Returns an (statically allocated) set of object attributes, as determined by
427c478bd9Sstevel@tonic-gate  * class and keytype of the supplied object.  The attributes are only
437c478bd9Sstevel@tonic-gate  * initialized to default values.
447c478bd9Sstevel@tonic-gate  */
457c478bd9Sstevel@tonic-gate CK_RV
get_master_attributes_by_object(slot_session_t * session,slot_object_t * slot_object,generic_attr_t ** attributes,size_t * num_attributes)467c478bd9Sstevel@tonic-gate get_master_attributes_by_object(slot_session_t *session,
477c478bd9Sstevel@tonic-gate     slot_object_t *slot_object, generic_attr_t **attributes,
487c478bd9Sstevel@tonic-gate     size_t *num_attributes)
497c478bd9Sstevel@tonic-gate {
507c478bd9Sstevel@tonic-gate 	CK_RV rv;
517c478bd9Sstevel@tonic-gate 	CK_ATTRIBUTE attr;
527c478bd9Sstevel@tonic-gate 	CK_OBJECT_CLASS class;
537c478bd9Sstevel@tonic-gate 	CK_ULONG subtype = CK_UNAVAILABLE_INFORMATION;
547c478bd9Sstevel@tonic-gate 
557c478bd9Sstevel@tonic-gate 	/* first get the class */
567c478bd9Sstevel@tonic-gate 	attr.type = CKA_CLASS;
577c478bd9Sstevel@tonic-gate 	attr.pValue = &class;
587c478bd9Sstevel@tonic-gate 	attr.ulValueLen = sizeof (class);
597c478bd9Sstevel@tonic-gate 	rv = FUNCLIST(session->fw_st_id)->C_GetAttributeValue(
607c478bd9Sstevel@tonic-gate 	    session->hSession, slot_object->hObject, &attr, 1);
617c478bd9Sstevel@tonic-gate 	if (rv != CKR_OK) {
627c478bd9Sstevel@tonic-gate 		return (rv);
637c478bd9Sstevel@tonic-gate 	}
647c478bd9Sstevel@tonic-gate 
657c478bd9Sstevel@tonic-gate 	attr.pValue = &subtype;
667c478bd9Sstevel@tonic-gate 	attr.ulValueLen = sizeof (subtype);
677c478bd9Sstevel@tonic-gate 	switch (class) {
687c478bd9Sstevel@tonic-gate 		case CKO_CERTIFICATE:
697c478bd9Sstevel@tonic-gate 			attr.type = CKA_CERTIFICATE_TYPE;
707c478bd9Sstevel@tonic-gate 			break;
717c478bd9Sstevel@tonic-gate 		case CKO_HW_FEATURE:
727c478bd9Sstevel@tonic-gate 			attr.type = CKA_HW_FEATURE_TYPE;
737c478bd9Sstevel@tonic-gate 			break;
747c478bd9Sstevel@tonic-gate 		case CKO_PUBLIC_KEY:
757c478bd9Sstevel@tonic-gate 		case CKO_PRIVATE_KEY:
767c478bd9Sstevel@tonic-gate 		case CKO_SECRET_KEY:
777c478bd9Sstevel@tonic-gate 		case CKO_DOMAIN_PARAMETERS:
787c478bd9Sstevel@tonic-gate 			attr.type = CKA_KEY_TYPE;
797c478bd9Sstevel@tonic-gate 			break;
807c478bd9Sstevel@tonic-gate 		case CKO_DATA:
817c478bd9Sstevel@tonic-gate 			goto get_attr;
827c478bd9Sstevel@tonic-gate 		default:
837c478bd9Sstevel@tonic-gate 			/* should never be here */
847c478bd9Sstevel@tonic-gate 			return (CKR_ATTRIBUTE_VALUE_INVALID);
857c478bd9Sstevel@tonic-gate 	}
867c478bd9Sstevel@tonic-gate 	rv = FUNCLIST(session->fw_st_id)->C_GetAttributeValue(
877c478bd9Sstevel@tonic-gate 	    session->hSession, slot_object->hObject, &attr, 1);
887c478bd9Sstevel@tonic-gate 	if (rv != CKR_OK) {
897c478bd9Sstevel@tonic-gate 		return (rv);
907c478bd9Sstevel@tonic-gate 	}
917c478bd9Sstevel@tonic-gate 
927c478bd9Sstevel@tonic-gate get_attr:
937c478bd9Sstevel@tonic-gate 	rv = get_master_attributes_by_type(class, subtype,
947c478bd9Sstevel@tonic-gate 	    attributes, num_attributes);
957c478bd9Sstevel@tonic-gate 
967c478bd9Sstevel@tonic-gate 	return (rv);
977c478bd9Sstevel@tonic-gate }
987c478bd9Sstevel@tonic-gate 
997c478bd9Sstevel@tonic-gate /*
1007c478bd9Sstevel@tonic-gate  * get_master_attributes_by_template
1017c478bd9Sstevel@tonic-gate  *
1027c478bd9Sstevel@tonic-gate  * Returns an (statically allocated) set of object attributes, as determined by
1037c478bd9Sstevel@tonic-gate  * the supplied object template. The template is only used to determine the
1047c478bd9Sstevel@tonic-gate  * class/subclass of the object. The attributes are only initialized to
1057c478bd9Sstevel@tonic-gate  * default values.
1067c478bd9Sstevel@tonic-gate  */
1077c478bd9Sstevel@tonic-gate CK_RV
get_master_attributes_by_template(CK_ATTRIBUTE * template,CK_ULONG template_size,generic_attr_t ** attributes,size_t * num_attributes)1087c478bd9Sstevel@tonic-gate get_master_attributes_by_template(
1097c478bd9Sstevel@tonic-gate 	CK_ATTRIBUTE *template, CK_ULONG template_size,
1107c478bd9Sstevel@tonic-gate 	generic_attr_t **attributes, size_t *num_attributes)
1117c478bd9Sstevel@tonic-gate {
1127c478bd9Sstevel@tonic-gate 	CK_OBJECT_CLASS class;
1137c478bd9Sstevel@tonic-gate 	CK_ULONG subtype = CK_UNAVAILABLE_INFORMATION;
1147c478bd9Sstevel@tonic-gate 	boolean_t found;
1157c478bd9Sstevel@tonic-gate 
1167c478bd9Sstevel@tonic-gate 	found = get_template_ulong(CKA_CLASS, template, template_size, &class);
1177c478bd9Sstevel@tonic-gate 	if (!found) {
1187c478bd9Sstevel@tonic-gate 		return (CKR_TEMPLATE_INCOMPLETE);
1197c478bd9Sstevel@tonic-gate 	}
1207c478bd9Sstevel@tonic-gate 
1217c478bd9Sstevel@tonic-gate 	switch (class) {
1227c478bd9Sstevel@tonic-gate 		case CKO_CERTIFICATE:
1237c478bd9Sstevel@tonic-gate 			found = get_template_ulong(CKA_CERTIFICATE_TYPE,
1247c478bd9Sstevel@tonic-gate 			    template, template_size, &subtype);
1257c478bd9Sstevel@tonic-gate 			break;
1267c478bd9Sstevel@tonic-gate 		case CKO_HW_FEATURE:
1277c478bd9Sstevel@tonic-gate 			found = get_template_ulong(CKA_HW_FEATURE_TYPE,
1287c478bd9Sstevel@tonic-gate 			    template, template_size, &subtype);
1297c478bd9Sstevel@tonic-gate 			break;
1307c478bd9Sstevel@tonic-gate 		case CKO_PUBLIC_KEY:
1317c478bd9Sstevel@tonic-gate 		case CKO_PRIVATE_KEY:
1327c478bd9Sstevel@tonic-gate 		case CKO_SECRET_KEY:
1337c478bd9Sstevel@tonic-gate 		case CKO_DOMAIN_PARAMETERS:
1347c478bd9Sstevel@tonic-gate 			found = get_template_ulong(CKA_KEY_TYPE,
1357c478bd9Sstevel@tonic-gate 			    template, template_size, &subtype);
1367c478bd9Sstevel@tonic-gate 			break;
1377c478bd9Sstevel@tonic-gate 		case CKO_DATA:
1387c478bd9Sstevel@tonic-gate 			/* CKO_DATA has no subtype, just pretend it is found  */
1397c478bd9Sstevel@tonic-gate 			found = B_TRUE;
14038a641c5SToomas Soome 			break;
1417c478bd9Sstevel@tonic-gate 		default:
1427c478bd9Sstevel@tonic-gate 			/* unknown object class */
1437c478bd9Sstevel@tonic-gate 			return (CKR_ATTRIBUTE_VALUE_INVALID);
1447c478bd9Sstevel@tonic-gate 	}
1457c478bd9Sstevel@tonic-gate 
1467c478bd9Sstevel@tonic-gate 	if (!found) {
1477c478bd9Sstevel@tonic-gate 		return (CKR_TEMPLATE_INCOMPLETE);
1487c478bd9Sstevel@tonic-gate 	}
1497c478bd9Sstevel@tonic-gate 
1507c478bd9Sstevel@tonic-gate 	return (get_master_attributes_by_type(class, subtype,
15133f5ff17SMilan Jurik 	    attributes, num_attributes));
1527c478bd9Sstevel@tonic-gate }
1537c478bd9Sstevel@tonic-gate 
1547c478bd9Sstevel@tonic-gate /*
1557c478bd9Sstevel@tonic-gate  * get_master_template_by_type
1567c478bd9Sstevel@tonic-gate  *
1577c478bd9Sstevel@tonic-gate  * Returns an (statically allocated) set of object attributes, as determined
1587c478bd9Sstevel@tonic-gate  * by the specified class and subtype. The attributes are initialized to default
1597c478bd9Sstevel@tonic-gate  * values.
1607c478bd9Sstevel@tonic-gate  */
1617c478bd9Sstevel@tonic-gate CK_RV
get_master_template_by_type(CK_OBJECT_CLASS class,CK_ULONG subtype,generic_attr_t ** attributes,size_t * num_attributes)1627c478bd9Sstevel@tonic-gate get_master_template_by_type(CK_OBJECT_CLASS class, CK_ULONG subtype,
1637c478bd9Sstevel@tonic-gate     generic_attr_t **attributes, size_t *num_attributes)
1647c478bd9Sstevel@tonic-gate {
1657c478bd9Sstevel@tonic-gate 	generic_attr_t *master_template = NULL;
1667c478bd9Sstevel@tonic-gate 	size_t master_template_size = 0;
1677c478bd9Sstevel@tonic-gate 
1687c478bd9Sstevel@tonic-gate 	switch (class) {
16933f5ff17SMilan Jurik 	case CKO_HW_FEATURE:
1707c478bd9Sstevel@tonic-gate 		switch (subtype) {
17133f5ff17SMilan Jurik 		case CKO_HW_FEATURE:
1727c478bd9Sstevel@tonic-gate 			master_template = (generic_attr_t *)OBJ_HW_CLOCK;
1737c478bd9Sstevel@tonic-gate 			master_template_size = sizeof (OBJ_HW_CLOCK);
1747c478bd9Sstevel@tonic-gate 			break;
1757c478bd9Sstevel@tonic-gate 
17633f5ff17SMilan Jurik 		case CKH_MONOTONIC_COUNTER:
1777c478bd9Sstevel@tonic-gate 			master_template = (generic_attr_t *)OBJ_HW_MONOTONIC;
1787c478bd9Sstevel@tonic-gate 			master_template_size = sizeof (OBJ_HW_MONOTONIC);
1797c478bd9Sstevel@tonic-gate 			break;
1807c478bd9Sstevel@tonic-gate 
18133f5ff17SMilan Jurik 		default:
1827c478bd9Sstevel@tonic-gate 			/* Unsupported. */
1837c478bd9Sstevel@tonic-gate 			break;
1847c478bd9Sstevel@tonic-gate 		}
1857c478bd9Sstevel@tonic-gate 		break;
1867c478bd9Sstevel@tonic-gate 
18733f5ff17SMilan Jurik 	case CKO_DATA:
1887c478bd9Sstevel@tonic-gate 		/* Objects of this class have no subtype. */
1897c478bd9Sstevel@tonic-gate 		master_template = (generic_attr_t *)OBJ_DATA;
1907c478bd9Sstevel@tonic-gate 		master_template_size = sizeof (OBJ_DATA);
1917c478bd9Sstevel@tonic-gate 		break;
1927c478bd9Sstevel@tonic-gate 
19333f5ff17SMilan Jurik 	case CKO_CERTIFICATE:
1947c478bd9Sstevel@tonic-gate 		switch (subtype) {
19533f5ff17SMilan Jurik 		case CKC_X_509:
1967c478bd9Sstevel@tonic-gate 			master_template = (generic_attr_t *)OBJ_CERT_X509;
1977c478bd9Sstevel@tonic-gate 			master_template_size = sizeof (OBJ_CERT_X509);
1987c478bd9Sstevel@tonic-gate 			break;
1997c478bd9Sstevel@tonic-gate 
20033f5ff17SMilan Jurik 		case CKC_X_509_ATTR_CERT:
2017c478bd9Sstevel@tonic-gate 			master_template = (generic_attr_t *)OBJ_CERT_X509ATTR;
2027c478bd9Sstevel@tonic-gate 			master_template_size = sizeof (OBJ_CERT_X509ATTR);
2037c478bd9Sstevel@tonic-gate 			break;
2047c478bd9Sstevel@tonic-gate 
20533f5ff17SMilan Jurik 		default:
2067c478bd9Sstevel@tonic-gate 			/* Unsupported. */
2077c478bd9Sstevel@tonic-gate 			break;
2087c478bd9Sstevel@tonic-gate 		}
2097c478bd9Sstevel@tonic-gate 		break;
2107c478bd9Sstevel@tonic-gate 
21133f5ff17SMilan Jurik 	case CKO_PUBLIC_KEY:
2127c478bd9Sstevel@tonic-gate 		switch (subtype) {
21333f5ff17SMilan Jurik 		case CKK_RSA:
2147c478bd9Sstevel@tonic-gate 			master_template = (generic_attr_t *)OBJ_PUBKEY_RSA;
2157c478bd9Sstevel@tonic-gate 			master_template_size = sizeof (OBJ_PUBKEY_RSA);
2167c478bd9Sstevel@tonic-gate 			break;
2177c478bd9Sstevel@tonic-gate 
21833f5ff17SMilan Jurik 		case CKK_DSA:
2197c478bd9Sstevel@tonic-gate 			master_template = (generic_attr_t *)OBJ_PUBKEY_DSA;
2207c478bd9Sstevel@tonic-gate 			master_template_size = sizeof (OBJ_PUBKEY_DSA);
2217c478bd9Sstevel@tonic-gate 			break;
2227c478bd9Sstevel@tonic-gate 
22333f5ff17SMilan Jurik 		case CKK_EC:
2247c478bd9Sstevel@tonic-gate 			master_template = (generic_attr_t *)OBJ_PUBKEY_EC;
2257c478bd9Sstevel@tonic-gate 			master_template_size = sizeof (OBJ_PUBKEY_EC);
2267c478bd9Sstevel@tonic-gate 			break;
2277c478bd9Sstevel@tonic-gate 
22833f5ff17SMilan Jurik 		case CKK_DH:
2297c478bd9Sstevel@tonic-gate 			master_template = (generic_attr_t *)OBJ_PUBKEY_DH;
2307c478bd9Sstevel@tonic-gate 			master_template_size = sizeof (OBJ_PUBKEY_DH);
2317c478bd9Sstevel@tonic-gate 			break;
2327c478bd9Sstevel@tonic-gate 
23333f5ff17SMilan Jurik 		case CKK_X9_42_DH:
2347c478bd9Sstevel@tonic-gate 			master_template = (generic_attr_t *)OBJ_PUBKEY_X942DH;
2357c478bd9Sstevel@tonic-gate 			master_template_size = sizeof (OBJ_PUBKEY_X942DH);
2367c478bd9Sstevel@tonic-gate 			break;
2377c478bd9Sstevel@tonic-gate 
23833f5ff17SMilan Jurik 		case CKK_KEA:
2397c478bd9Sstevel@tonic-gate 			master_template = (generic_attr_t *)OBJ_PUBKEY_KEA;
2407c478bd9Sstevel@tonic-gate 			master_template_size = sizeof (OBJ_PUBKEY_KEA);
2417c478bd9Sstevel@tonic-gate 			break;
2427c478bd9Sstevel@tonic-gate 
24333f5ff17SMilan Jurik 		default:
2447c478bd9Sstevel@tonic-gate 			/* Unsupported. */
2457c478bd9Sstevel@tonic-gate 			break;
2467c478bd9Sstevel@tonic-gate 		}
2477c478bd9Sstevel@tonic-gate 		break;
2487c478bd9Sstevel@tonic-gate 
24933f5ff17SMilan Jurik 	case CKO_PRIVATE_KEY:
2507c478bd9Sstevel@tonic-gate 		switch (subtype) {
25133f5ff17SMilan Jurik 		case CKK_RSA:
2527c478bd9Sstevel@tonic-gate 			master_template = (generic_attr_t *)OBJ_PRIVKEY_RSA;
2537c478bd9Sstevel@tonic-gate 			master_template_size = sizeof (OBJ_PRIVKEY_RSA);
2547c478bd9Sstevel@tonic-gate 			break;
2557c478bd9Sstevel@tonic-gate 
25633f5ff17SMilan Jurik 		case CKK_DSA:
2577c478bd9Sstevel@tonic-gate 			master_template = (generic_attr_t *)OBJ_PRIVKEY_DSA;
2587c478bd9Sstevel@tonic-gate 			master_template_size = sizeof (OBJ_PRIVKEY_DSA);
2597c478bd9Sstevel@tonic-gate 			break;
2607c478bd9Sstevel@tonic-gate 
26133f5ff17SMilan Jurik 		case CKK_EC:
2627c478bd9Sstevel@tonic-gate 			master_template = (generic_attr_t *)OBJ_PRIVKEY_EC;
2637c478bd9Sstevel@tonic-gate 			master_template_size = sizeof (OBJ_PRIVKEY_EC);
2647c478bd9Sstevel@tonic-gate 			break;
2657c478bd9Sstevel@tonic-gate 
26633f5ff17SMilan Jurik 		case CKK_DH:
2677c478bd9Sstevel@tonic-gate 			master_template = (generic_attr_t *)OBJ_PRIVKEY_DH;
2687c478bd9Sstevel@tonic-gate 			master_template_size = sizeof (OBJ_PRIVKEY_DH);
2697c478bd9Sstevel@tonic-gate 			break;
2707c478bd9Sstevel@tonic-gate 
27133f5ff17SMilan Jurik 		case CKK_X9_42_DH:
2727c478bd9Sstevel@tonic-gate 			master_template = (generic_attr_t *)OBJ_PRIVKEY_X942DH;
2737c478bd9Sstevel@tonic-gate 			master_template_size = sizeof (OBJ_PRIVKEY_X942DH);
2747c478bd9Sstevel@tonic-gate 			break;
2757c478bd9Sstevel@tonic-gate 
27633f5ff17SMilan Jurik 		case CKK_KEA:
2777c478bd9Sstevel@tonic-gate 			master_template = (generic_attr_t *)OBJ_PRIVKEY_KEA;
2787c478bd9Sstevel@tonic-gate 			master_template_size = sizeof (OBJ_PRIVKEY_KEA);
2797c478bd9Sstevel@tonic-gate 			break;
2807c478bd9Sstevel@tonic-gate 
28133f5ff17SMilan Jurik 		default:
2827c478bd9Sstevel@tonic-gate 			/* Unsupported. */
2837c478bd9Sstevel@tonic-gate 			break;
2847c478bd9Sstevel@tonic-gate 		}
2857c478bd9Sstevel@tonic-gate 		break;
2867c478bd9Sstevel@tonic-gate 
28733f5ff17SMilan Jurik 	case CKO_SECRET_KEY:
2887c478bd9Sstevel@tonic-gate 		/*
2897c478bd9Sstevel@tonic-gate 		 * The only difference between secret keys is that some
2907c478bd9Sstevel@tonic-gate 		 * are valiable length (eg CKK_AES), while others are not
2917c478bd9Sstevel@tonic-gate 		 * (eg CKK_DES) -- and do not have a CKA_VALUE_LEN attribute.
2927c478bd9Sstevel@tonic-gate 		 *
2937c478bd9Sstevel@tonic-gate 		 * FUTURE(?): Consider using obj_seckey_withlen for unknown
2947c478bd9Sstevel@tonic-gate 		 * keytypes. This is the most likely choice, as new algorithms
2957c478bd9Sstevel@tonic-gate 		 * seem to support variable length keys. That's not the default
2967c478bd9Sstevel@tonic-gate 		 * now, because if people have implemented new key types with
2977c478bd9Sstevel@tonic-gate 		 * different attribute sets (like the mess of public/private
2987c478bd9Sstevel@tonic-gate 		 * key types), then incorrect behaviour would result. It's
2997c478bd9Sstevel@tonic-gate 		 * easier to relax this restriction than to tighten it (which
3007c478bd9Sstevel@tonic-gate 		 * would introduce a regression to anyone relying on this
3017c478bd9Sstevel@tonic-gate 		 * working for unknown key types).
3027c478bd9Sstevel@tonic-gate 		 *
3037c478bd9Sstevel@tonic-gate 		 */
3047c478bd9Sstevel@tonic-gate 		switch (subtype) {
30533f5ff17SMilan Jurik 		case CKK_DES:
30633f5ff17SMilan Jurik 		case CKK_DES2:
30733f5ff17SMilan Jurik 		case CKK_DES3:
30833f5ff17SMilan Jurik 		case CKK_IDEA:
30933f5ff17SMilan Jurik 		case CKK_CDMF:
31033f5ff17SMilan Jurik 		case CKK_SKIPJACK:
31133f5ff17SMilan Jurik 		case CKK_BATON:
31233f5ff17SMilan Jurik 		case CKK_JUNIPER:
3137c478bd9Sstevel@tonic-gate 			master_template = (generic_attr_t *)OBJ_SECKEY;
3147c478bd9Sstevel@tonic-gate 			master_template_size = sizeof (OBJ_SECKEY);
3157c478bd9Sstevel@tonic-gate 			break;
3167c478bd9Sstevel@tonic-gate 
31733f5ff17SMilan Jurik 		case CKK_GENERIC_SECRET:
31833f5ff17SMilan Jurik 		case CKK_RC2:
31933f5ff17SMilan Jurik 		case CKK_RC4:
32033f5ff17SMilan Jurik 		case CKK_RC5:
32133f5ff17SMilan Jurik 		case CKK_AES:
32233f5ff17SMilan Jurik 		case CKK_BLOWFISH:
32333f5ff17SMilan Jurik 		case CKK_CAST:
32433f5ff17SMilan Jurik 		case CKK_CAST3:
32533f5ff17SMilan Jurik 		case CKK_CAST128:
3267c478bd9Sstevel@tonic-gate 			master_template = (generic_attr_t *)OBJ_SECKEY_WITHLEN;
3277c478bd9Sstevel@tonic-gate 			master_template_size = sizeof (OBJ_SECKEY_WITHLEN);
3287c478bd9Sstevel@tonic-gate 			break;
3297c478bd9Sstevel@tonic-gate 
33033f5ff17SMilan Jurik 		default:
3317c478bd9Sstevel@tonic-gate 			/* Unsupported. */
3327c478bd9Sstevel@tonic-gate 			break;
3337c478bd9Sstevel@tonic-gate 		}
3347c478bd9Sstevel@tonic-gate 		break;
3357c478bd9Sstevel@tonic-gate 
33633f5ff17SMilan Jurik 	case CKO_DOMAIN_PARAMETERS:
3377c478bd9Sstevel@tonic-gate 		switch (subtype) {
33833f5ff17SMilan Jurik 		case CKK_DSA:
3397c478bd9Sstevel@tonic-gate 			master_template = (generic_attr_t *)OBJ_DOM_DSA;
3407c478bd9Sstevel@tonic-gate 			master_template_size = sizeof (OBJ_DOM_DSA);
3417c478bd9Sstevel@tonic-gate 			break;
3427c478bd9Sstevel@tonic-gate 
34333f5ff17SMilan Jurik 		case CKK_DH:
3447c478bd9Sstevel@tonic-gate 			master_template = (generic_attr_t *)OBJ_DOM_DH;
3457c478bd9Sstevel@tonic-gate 			master_template_size = sizeof (OBJ_DOM_DH);
3467c478bd9Sstevel@tonic-gate 			break;
3477c478bd9Sstevel@tonic-gate 
34833f5ff17SMilan Jurik 		case CKK_X9_42_DH:
3497c478bd9Sstevel@tonic-gate 			master_template = (generic_attr_t *)OBJ_DOM_X942DH;
3507c478bd9Sstevel@tonic-gate 			master_template_size = sizeof (OBJ_DOM_X942DH);
3517c478bd9Sstevel@tonic-gate 			break;
3527c478bd9Sstevel@tonic-gate 
35333f5ff17SMilan Jurik 		default:
3547c478bd9Sstevel@tonic-gate 			/* Unsupported. */
3557c478bd9Sstevel@tonic-gate 			break;
3567c478bd9Sstevel@tonic-gate 		}
3577c478bd9Sstevel@tonic-gate 		break;
3587c478bd9Sstevel@tonic-gate 
35933f5ff17SMilan Jurik 	default:
3607c478bd9Sstevel@tonic-gate 		/* Unsupported. */
3617c478bd9Sstevel@tonic-gate 		break;
3627c478bd9Sstevel@tonic-gate 	}
3637c478bd9Sstevel@tonic-gate 
3647c478bd9Sstevel@tonic-gate 	/* Requested object is unknown or invalid. */
3657c478bd9Sstevel@tonic-gate 	if (master_template == NULL)
3667c478bd9Sstevel@tonic-gate 		return (CKR_ATTRIBUTE_VALUE_INVALID);
3677c478bd9Sstevel@tonic-gate 	else {
3687c478bd9Sstevel@tonic-gate 		*attributes = master_template;
3697c478bd9Sstevel@tonic-gate 		*num_attributes = master_template_size;
3707c478bd9Sstevel@tonic-gate 		return (CKR_OK);
3717c478bd9Sstevel@tonic-gate 	}
3727c478bd9Sstevel@tonic-gate }
3737c478bd9Sstevel@tonic-gate 
3747c478bd9Sstevel@tonic-gate 
3757c478bd9Sstevel@tonic-gate /*
3767c478bd9Sstevel@tonic-gate  * get_master_attributes_by_type
3777c478bd9Sstevel@tonic-gate  *
3787c478bd9Sstevel@tonic-gate  * Returns an (statically allocated) set of object attributes, as determined by
3797c478bd9Sstevel@tonic-gate  * the specified class and subtype. The attributes are initialized to default
3807c478bd9Sstevel@tonic-gate  * values.
3817c478bd9Sstevel@tonic-gate  */
3827c478bd9Sstevel@tonic-gate CK_RV
get_master_attributes_by_type(CK_OBJECT_CLASS class,CK_ULONG subtype,generic_attr_t ** attributes,size_t * num_attributes)3837c478bd9Sstevel@tonic-gate get_master_attributes_by_type(CK_OBJECT_CLASS class, CK_ULONG subtype,
384*a8793c76SJason King     generic_attr_t **attributes, size_t *num_attributes)
3857c478bd9Sstevel@tonic-gate {
3867c478bd9Sstevel@tonic-gate 	CK_RV rv;
3877c478bd9Sstevel@tonic-gate 	generic_attr_t *master_template = NULL;
3887c478bd9Sstevel@tonic-gate 	generic_attr_t *new_attributes;
3897c478bd9Sstevel@tonic-gate 	size_t i, num_new_attributes, master_template_size = 0;
3907c478bd9Sstevel@tonic-gate 
3917c478bd9Sstevel@tonic-gate 	/* Determine the appropriate master template needed. */
3927c478bd9Sstevel@tonic-gate 	rv = get_master_template_by_type(class, subtype,
39333f5ff17SMilan Jurik 	    &master_template, &master_template_size);
3947c478bd9Sstevel@tonic-gate 	if (rv != CKR_OK)
3957c478bd9Sstevel@tonic-gate 		return (rv);
3967c478bd9Sstevel@tonic-gate 
3977c478bd9Sstevel@tonic-gate 	/* Duplicate the master template. */
3987c478bd9Sstevel@tonic-gate 	new_attributes = malloc(master_template_size);
3997c478bd9Sstevel@tonic-gate 	if (new_attributes == NULL)
4007c478bd9Sstevel@tonic-gate 		return (CKR_HOST_MEMORY);
4017c478bd9Sstevel@tonic-gate 
4027c478bd9Sstevel@tonic-gate 	(void) memcpy(new_attributes, master_template, master_template_size);
4037c478bd9Sstevel@tonic-gate 	num_new_attributes = master_template_size / sizeof (generic_attr_t);
4047c478bd9Sstevel@tonic-gate 
4057c478bd9Sstevel@tonic-gate 	/* Set the pointer in the appropriate storage area. */
4067c478bd9Sstevel@tonic-gate 	for (i = 0; i < num_new_attributes; i++) {
4077c478bd9Sstevel@tonic-gate 		generic_attr_t *attr;
4087c478bd9Sstevel@tonic-gate 
4097c478bd9Sstevel@tonic-gate 		attr = new_attributes + i;
4107c478bd9Sstevel@tonic-gate 
4117c478bd9Sstevel@tonic-gate 		switch (attr->attribute.ulValueLen) {
4127c478bd9Sstevel@tonic-gate 			case (sizeof (CK_ULONG)):
4137c478bd9Sstevel@tonic-gate 				attr->attribute.pValue = &attr->generic_ulong;
4147c478bd9Sstevel@tonic-gate 				break;
4157c478bd9Sstevel@tonic-gate 			case (sizeof (CK_BBOOL)):
4167c478bd9Sstevel@tonic-gate 				attr->attribute.pValue = &attr->generic_bbool;
4177c478bd9Sstevel@tonic-gate 				break;
4187c478bd9Sstevel@tonic-gate 			default:
4197c478bd9Sstevel@tonic-gate 				attr->attribute.pValue = attr->generic_data;
4207c478bd9Sstevel@tonic-gate 				break;
4217c478bd9Sstevel@tonic-gate 		}
4227c478bd9Sstevel@tonic-gate 
4237c478bd9Sstevel@tonic-gate 	}
4247c478bd9Sstevel@tonic-gate 
4257c478bd9Sstevel@tonic-gate 	/* Secret keys share a common template, so set the key type here. */
4267c478bd9Sstevel@tonic-gate 	if (class == CKO_SECRET_KEY) {
4277c478bd9Sstevel@tonic-gate 		/* Keytype / subtype is always the second attribute. */
4287c478bd9Sstevel@tonic-gate 		new_attributes[1].generic_ulong = subtype;
4297c478bd9Sstevel@tonic-gate 	}
4307c478bd9Sstevel@tonic-gate 
4317c478bd9Sstevel@tonic-gate 	*attributes = new_attributes;
4327c478bd9Sstevel@tonic-gate 	*num_attributes = num_new_attributes;
4337c478bd9Sstevel@tonic-gate 
4347c478bd9Sstevel@tonic-gate 	return (CKR_OK);
4357c478bd9Sstevel@tonic-gate }
4367c478bd9Sstevel@tonic-gate 
4377c478bd9Sstevel@tonic-gate 
4387c478bd9Sstevel@tonic-gate /*
4397c478bd9Sstevel@tonic-gate  * get_master_attributes_by_duplication
4407c478bd9Sstevel@tonic-gate  *
4417c478bd9Sstevel@tonic-gate  * Returns an (statically allocated) set of object attributes, as copied from an
4427c478bd9Sstevel@tonic-gate  * existing set of attributes. The new attributes inherit the values from
4437c478bd9Sstevel@tonic-gate  * the old attributes.
4447c478bd9Sstevel@tonic-gate  */
4457c478bd9Sstevel@tonic-gate CK_RV
get_master_attributes_by_duplication(generic_attr_t * src_attrs,size_t num_src_attrs,generic_attr_t ** dst_attrs,size_t * num_dst_attrs)4467c478bd9Sstevel@tonic-gate get_master_attributes_by_duplication(
4477c478bd9Sstevel@tonic-gate 	generic_attr_t *src_attrs, size_t num_src_attrs,
4487c478bd9Sstevel@tonic-gate 	generic_attr_t **dst_attrs, size_t *num_dst_attrs)
4497c478bd9Sstevel@tonic-gate {
4507c478bd9Sstevel@tonic-gate 	CK_RV rv = CKR_OK;
4517c478bd9Sstevel@tonic-gate 	generic_attr_t *new_attrs, *src, *dst;
4527c478bd9Sstevel@tonic-gate 	size_t i;
4537c478bd9Sstevel@tonic-gate 
4547c478bd9Sstevel@tonic-gate 	new_attrs = malloc(sizeof (generic_attr_t) * num_src_attrs);
4557c478bd9Sstevel@tonic-gate 	if (new_attrs == NULL)
4567c478bd9Sstevel@tonic-gate 		return (CKR_HOST_MEMORY);
4577c478bd9Sstevel@tonic-gate 
4587c478bd9Sstevel@tonic-gate 	for (i = 0; i < num_src_attrs; i++) {
4597c478bd9Sstevel@tonic-gate 		src = src_attrs + i;
4607c478bd9Sstevel@tonic-gate 		dst = new_attrs + i;
4617c478bd9Sstevel@tonic-gate 
4627c478bd9Sstevel@tonic-gate 		*dst = *src;
4637c478bd9Sstevel@tonic-gate 
4647c478bd9Sstevel@tonic-gate 		/* Adjust pointers in dst so that they don't point to src. */
4657c478bd9Sstevel@tonic-gate 
4667c478bd9Sstevel@tonic-gate 		if (src->isMalloced) {
4677c478bd9Sstevel@tonic-gate 			dst->attribute.pValue =
46833f5ff17SMilan Jurik 			    malloc(src->attribute.ulValueLen);
4697c478bd9Sstevel@tonic-gate 
4707c478bd9Sstevel@tonic-gate 			if (dst->attribute.pValue == NULL) {
4717c478bd9Sstevel@tonic-gate 				/*
4727c478bd9Sstevel@tonic-gate 				 * Continue on error, so that the cleanup
4737c478bd9Sstevel@tonic-gate 				 * routine doesn't see pointers to src_attrs.
4747c478bd9Sstevel@tonic-gate 				 */
4757c478bd9Sstevel@tonic-gate 				dst->attribute.ulValueLen = 0;
4767c478bd9Sstevel@tonic-gate 				rv = CKR_HOST_MEMORY;
4777c478bd9Sstevel@tonic-gate 				continue;
4787c478bd9Sstevel@tonic-gate 			}
4797c478bd9Sstevel@tonic-gate 		} else if (src->attribute.pValue == &src->generic_bbool) {
4807c478bd9Sstevel@tonic-gate 			dst->attribute.pValue = &dst->generic_bbool;
4817c478bd9Sstevel@tonic-gate 		} else if (src->attribute.pValue == &src->generic_ulong) {
4827c478bd9Sstevel@tonic-gate 			dst->attribute.pValue = &dst->generic_ulong;
4837c478bd9Sstevel@tonic-gate 		} else if (src->attribute.pValue == &src->generic_data) {
4847c478bd9Sstevel@tonic-gate 			dst->attribute.pValue = &dst->generic_data;
4857c478bd9Sstevel@tonic-gate 		} else {
4867c478bd9Sstevel@tonic-gate 			/* This shouldn't happen. */
4877c478bd9Sstevel@tonic-gate 			dst->attribute.pValue = NULL;
4887c478bd9Sstevel@tonic-gate 			dst->attribute.ulValueLen = 0;
4897c478bd9Sstevel@tonic-gate 			rv = CKR_GENERAL_ERROR;
4907c478bd9Sstevel@tonic-gate 			num_src_attrs = i + 1;
4917c478bd9Sstevel@tonic-gate 			break;
4927c478bd9Sstevel@tonic-gate 		}
4937c478bd9Sstevel@tonic-gate 
4947c478bd9Sstevel@tonic-gate 		(void) memcpy(dst->attribute.pValue, src->attribute.pValue,
49533f5ff17SMilan Jurik 		    src->attribute.ulValueLen);
4967c478bd9Sstevel@tonic-gate 	}
4977c478bd9Sstevel@tonic-gate 
4987c478bd9Sstevel@tonic-gate 	if (rv != CKR_OK) {
4997c478bd9Sstevel@tonic-gate 		dealloc_attributes(new_attrs, num_src_attrs);
5007c478bd9Sstevel@tonic-gate 	} else {
5017c478bd9Sstevel@tonic-gate 		*dst_attrs = new_attrs;
5027c478bd9Sstevel@tonic-gate 		*num_dst_attrs = num_src_attrs;
5037c478bd9Sstevel@tonic-gate 	}
5047c478bd9Sstevel@tonic-gate 
5057c478bd9Sstevel@tonic-gate 	return (rv);
5067c478bd9Sstevel@tonic-gate }
5077c478bd9Sstevel@tonic-gate 
5087c478bd9Sstevel@tonic-gate 
5097c478bd9Sstevel@tonic-gate /*
5107c478bd9Sstevel@tonic-gate  * dealloc_attributes
5117c478bd9Sstevel@tonic-gate  *
5127c478bd9Sstevel@tonic-gate  * Deallocates the storage used for a set of attributes. The attribute
5137c478bd9Sstevel@tonic-gate  * values are zeroed out before being free'd.
5147c478bd9Sstevel@tonic-gate  */
5157c478bd9Sstevel@tonic-gate void
dealloc_attributes(generic_attr_t * attributes,size_t num_attributes)5167c478bd9Sstevel@tonic-gate dealloc_attributes(generic_attr_t *attributes, size_t num_attributes)
5177c478bd9Sstevel@tonic-gate {
5187c478bd9Sstevel@tonic-gate 	size_t i;
5197c478bd9Sstevel@tonic-gate 	generic_attr_t *attr;
5207c478bd9Sstevel@tonic-gate 
5217c478bd9Sstevel@tonic-gate 	for (i = 0; i < num_attributes; i++) {
5227c478bd9Sstevel@tonic-gate 		attr = attributes + i;
5237c478bd9Sstevel@tonic-gate 
5247c478bd9Sstevel@tonic-gate 		/*
5257c478bd9Sstevel@tonic-gate 		 * Zero-out any attribute values. We could do this just for
5267c478bd9Sstevel@tonic-gate 		 * attributes with isSensitive == True, but it's not much
5277c478bd9Sstevel@tonic-gate 		 * extra work to just do them all. [Most attributes are just
5287c478bd9Sstevel@tonic-gate 		 * 1 or 4 bytes]
5297c478bd9Sstevel@tonic-gate 		 */
530*a8793c76SJason King 		explicit_bzero(attr->attribute.pValue,
531*a8793c76SJason King 		    attr->attribute.ulValueLen);
5327c478bd9Sstevel@tonic-gate 
5337c478bd9Sstevel@tonic-gate 		if (attr->isMalloced)
5347c478bd9Sstevel@tonic-gate 			free(attr->attribute.pValue);
5357c478bd9Sstevel@tonic-gate 	}
5367c478bd9Sstevel@tonic-gate 
5377c478bd9Sstevel@tonic-gate 	free(attributes);
5387c478bd9Sstevel@tonic-gate }
5397c478bd9Sstevel@tonic-gate 
5407c478bd9Sstevel@tonic-gate 
5417c478bd9Sstevel@tonic-gate /*
5427c478bd9Sstevel@tonic-gate  * attribute_set_value
5437c478bd9Sstevel@tonic-gate  *
5447c478bd9Sstevel@tonic-gate  * Sets the value of the specified attribute. Any portion of the old value
5457c478bd9Sstevel@tonic-gate  * which will not be overwritten by the new value is zeroed out.
5467c478bd9Sstevel@tonic-gate  */
5477c478bd9Sstevel@tonic-gate CK_RV
attribute_set_value(CK_ATTRIBUTE * new_attr,generic_attr_t * attributes,size_t num_attributes)5487c478bd9Sstevel@tonic-gate attribute_set_value(CK_ATTRIBUTE *new_attr,
549*a8793c76SJason King     generic_attr_t *attributes, size_t num_attributes)
5507c478bd9Sstevel@tonic-gate {
5517c478bd9Sstevel@tonic-gate 	generic_attr_t *attr = NULL;
5527c478bd9Sstevel@tonic-gate 
5537c478bd9Sstevel@tonic-gate 	if (new_attr == NULL)
5547c478bd9Sstevel@tonic-gate 		return (CKR_TEMPLATE_INCOMPLETE);
5557c478bd9Sstevel@tonic-gate 	else if (new_attr->pValue == NULL) {
5567c478bd9Sstevel@tonic-gate 		return (CKR_ATTRIBUTE_VALUE_INVALID);
5577c478bd9Sstevel@tonic-gate 	}
5587c478bd9Sstevel@tonic-gate 
5597c478bd9Sstevel@tonic-gate 	find_attribute(new_attr->type, attributes, num_attributes, &attr);
5607c478bd9Sstevel@tonic-gate 	if (attr == NULL) {
5617c478bd9Sstevel@tonic-gate 		return (CKR_ATTRIBUTE_TYPE_INVALID);
5627c478bd9Sstevel@tonic-gate 	}
5637c478bd9Sstevel@tonic-gate 
5647c478bd9Sstevel@tonic-gate 	/* Store the new value. */
5657c478bd9Sstevel@tonic-gate 	if (attr->attribute.ulValueLen >= new_attr->ulValueLen) {
5667c478bd9Sstevel@tonic-gate 		/* Existing storage is sufficient to store new value. */
5677c478bd9Sstevel@tonic-gate 
5687c478bd9Sstevel@tonic-gate 		/* bzero() out any data that won't be overwritten. */
569*a8793c76SJason King 		explicit_bzero((char *)attr->attribute.pValue +
570*a8793c76SJason King 		    new_attr->ulValueLen,
57133f5ff17SMilan Jurik 		    attr->attribute.ulValueLen - new_attr->ulValueLen);
5727c478bd9Sstevel@tonic-gate 
5737c478bd9Sstevel@tonic-gate 	} else if (new_attr->ulValueLen <= sizeof (attr->generic_data)) {
5747c478bd9Sstevel@tonic-gate 		/* Use generic storage to avoid a malloc. */
5757c478bd9Sstevel@tonic-gate 
576*a8793c76SJason King 		explicit_bzero(attr->attribute.pValue,
577*a8793c76SJason King 		    attr->attribute.ulValueLen);
5787c478bd9Sstevel@tonic-gate 		if (attr->isMalloced) {
5797c478bd9Sstevel@tonic-gate 			/*
5807c478bd9Sstevel@tonic-gate 			 * If app sets a large value (triggering a malloc),
5817c478bd9Sstevel@tonic-gate 			 * then sets a tiny value, and finally again sets
5827c478bd9Sstevel@tonic-gate 			 * a large value (phew!) we could end up here.
5837c478bd9Sstevel@tonic-gate 			 *
5847c478bd9Sstevel@tonic-gate 			 * FUTURE?: Store the original malloc size, so that
5857c478bd9Sstevel@tonic-gate 			 * we can regrow the value up to the original size.
5867c478bd9Sstevel@tonic-gate 			 * This might avoid some heap churn for pathalogic
5877c478bd9Sstevel@tonic-gate 			 * applications.
5887c478bd9Sstevel@tonic-gate 			 */
5897c478bd9Sstevel@tonic-gate 			free(attr->attribute.pValue);
5907c478bd9Sstevel@tonic-gate 			attr->isMalloced = B_FALSE;
5917c478bd9Sstevel@tonic-gate 		}
5927c478bd9Sstevel@tonic-gate 
5937c478bd9Sstevel@tonic-gate 		attr->attribute.pValue = attr->generic_data;
5947c478bd9Sstevel@tonic-gate 
5957c478bd9Sstevel@tonic-gate 	} else {
5967c478bd9Sstevel@tonic-gate 		/* Need to allocate storage for the new value. */
5977c478bd9Sstevel@tonic-gate 		void *newStorage;
5987c478bd9Sstevel@tonic-gate 
5997c478bd9Sstevel@tonic-gate 		newStorage = malloc(new_attr->ulValueLen);
6007c478bd9Sstevel@tonic-gate 		if (newStorage == NULL)
6017c478bd9Sstevel@tonic-gate 			return (CKR_HOST_MEMORY);
6027c478bd9Sstevel@tonic-gate 		bzero(attr->attribute.pValue, attr->attribute.ulValueLen);
6037c478bd9Sstevel@tonic-gate 		attr->attribute.pValue = newStorage;
6047c478bd9Sstevel@tonic-gate 		attr->isMalloced = B_TRUE;
6057c478bd9Sstevel@tonic-gate 	}
6067c478bd9Sstevel@tonic-gate 
6077c478bd9Sstevel@tonic-gate 	(void) memcpy(attr->attribute.pValue, new_attr->pValue,
60833f5ff17SMilan Jurik 	    new_attr->ulValueLen);
6097c478bd9Sstevel@tonic-gate 	attr->attribute.ulValueLen = new_attr->ulValueLen;
6107c478bd9Sstevel@tonic-gate 	attr->hasValueForClone = B_TRUE;
6117c478bd9Sstevel@tonic-gate 
6127c478bd9Sstevel@tonic-gate 	return (CKR_OK);
6137c478bd9Sstevel@tonic-gate }
6147c478bd9Sstevel@tonic-gate 
6157c478bd9Sstevel@tonic-gate 
6167c478bd9Sstevel@tonic-gate /*
6177c478bd9Sstevel@tonic-gate  * find_attribute
6187c478bd9Sstevel@tonic-gate  *
6197c478bd9Sstevel@tonic-gate  * Passes a pointer to the requested attribute, or NULL if not found.
6207c478bd9Sstevel@tonic-gate  */
6217c478bd9Sstevel@tonic-gate static void
find_attribute(CK_ATTRIBUTE_TYPE attrtype,generic_attr_t * attributes,size_t num_attributes,generic_attr_t ** found_attribute)6227c478bd9Sstevel@tonic-gate find_attribute(CK_ATTRIBUTE_TYPE attrtype, generic_attr_t *attributes,
623*a8793c76SJason King     size_t num_attributes, generic_attr_t **found_attribute)
6247c478bd9Sstevel@tonic-gate {
6257c478bd9Sstevel@tonic-gate 	generic_attr_t *attr;
6267c478bd9Sstevel@tonic-gate 	boolean_t found = B_FALSE;
6277c478bd9Sstevel@tonic-gate 	size_t i;
6287c478bd9Sstevel@tonic-gate 
6297c478bd9Sstevel@tonic-gate 	/* Find the requested attribute. */
6307c478bd9Sstevel@tonic-gate 	for (i = 0, attr = attributes; i < num_attributes; i++, attr++) {
6317c478bd9Sstevel@tonic-gate 		if (attr->attribute.type == attrtype) {
6327c478bd9Sstevel@tonic-gate 			found = B_TRUE;
6337c478bd9Sstevel@tonic-gate 			break;
6347c478bd9Sstevel@tonic-gate 		}
6357c478bd9Sstevel@tonic-gate 	}
6367c478bd9Sstevel@tonic-gate 
6377c478bd9Sstevel@tonic-gate 	*found_attribute = found ? attr : NULL;
6387c478bd9Sstevel@tonic-gate }
6397c478bd9Sstevel@tonic-gate 
6407c478bd9Sstevel@tonic-gate 
6417c478bd9Sstevel@tonic-gate /*
6427c478bd9Sstevel@tonic-gate  * get_template_ulong
6437c478bd9Sstevel@tonic-gate  *
6447c478bd9Sstevel@tonic-gate  * Look for the specified ulong-size attribute, and retrieve its value. The
6457c478bd9Sstevel@tonic-gate  * return value specifies if the attribute was found (or not).
6467c478bd9Sstevel@tonic-gate  */
6477c478bd9Sstevel@tonic-gate boolean_t
get_template_ulong(CK_ATTRIBUTE_TYPE type,CK_ATTRIBUTE * attributes,CK_ULONG num_attributes,CK_ULONG * result)6487c478bd9Sstevel@tonic-gate get_template_ulong(CK_ATTRIBUTE_TYPE type, CK_ATTRIBUTE *attributes,
649*a8793c76SJason King     CK_ULONG num_attributes, CK_ULONG *result)
6507c478bd9Sstevel@tonic-gate {
6517c478bd9Sstevel@tonic-gate 	boolean_t found = B_FALSE;
6527c478bd9Sstevel@tonic-gate 	CK_ULONG i;
6537c478bd9Sstevel@tonic-gate 
6547c478bd9Sstevel@tonic-gate 	for (i = 0; i < num_attributes; i++) {
6557c478bd9Sstevel@tonic-gate 		if (attributes[i].type == type) {
6567c478bd9Sstevel@tonic-gate 			CK_ULONG *value = attributes[i].pValue;
6577c478bd9Sstevel@tonic-gate 
6587c478bd9Sstevel@tonic-gate 			*result = *value;
6597c478bd9Sstevel@tonic-gate 			found = B_TRUE;
6607c478bd9Sstevel@tonic-gate 			break;
6617c478bd9Sstevel@tonic-gate 		}
6627c478bd9Sstevel@tonic-gate 	}
6637c478bd9Sstevel@tonic-gate 
6647c478bd9Sstevel@tonic-gate 	return (found);
6657c478bd9Sstevel@tonic-gate }
6667c478bd9Sstevel@tonic-gate 
6677c478bd9Sstevel@tonic-gate 
6687c478bd9Sstevel@tonic-gate /*
6697c478bd9Sstevel@tonic-gate  * get_template_boolean
6707c478bd9Sstevel@tonic-gate  *
6717c478bd9Sstevel@tonic-gate  * Look for the specified boolean attribute, and retrieve its value. The
6727c478bd9Sstevel@tonic-gate  * return value specifies if the attribute was found (or not).
6737c478bd9Sstevel@tonic-gate  */
6747c478bd9Sstevel@tonic-gate boolean_t
get_template_boolean(CK_ATTRIBUTE_TYPE type,CK_ATTRIBUTE * attributes,CK_ULONG num_attributes,boolean_t * result)6757c478bd9Sstevel@tonic-gate get_template_boolean(CK_ATTRIBUTE_TYPE type, CK_ATTRIBUTE *attributes,
676*a8793c76SJason King     CK_ULONG num_attributes, boolean_t *result)
6777c478bd9Sstevel@tonic-gate {
6787c478bd9Sstevel@tonic-gate 	boolean_t found = B_FALSE;
6797c478bd9Sstevel@tonic-gate 	CK_ULONG i;
6807c478bd9Sstevel@tonic-gate 
6817c478bd9Sstevel@tonic-gate 	for (i = 0; i < num_attributes; i++) {
6827c478bd9Sstevel@tonic-gate 		if (attributes[i].type == type) {
6837c478bd9Sstevel@tonic-gate 			CK_BBOOL *value = attributes[i].pValue;
6847c478bd9Sstevel@tonic-gate 
6857c478bd9Sstevel@tonic-gate 			if (*value == CK_FALSE)
6867c478bd9Sstevel@tonic-gate 				*result = B_FALSE;
6877c478bd9Sstevel@tonic-gate 			else
6887c478bd9Sstevel@tonic-gate 				*result = B_TRUE;
6897c478bd9Sstevel@tonic-gate 
6907c478bd9Sstevel@tonic-gate 			found = B_TRUE;
6917c478bd9Sstevel@tonic-gate 			break;
6927c478bd9Sstevel@tonic-gate 		}
6937c478bd9Sstevel@tonic-gate 	}
6947c478bd9Sstevel@tonic-gate 
6957c478bd9Sstevel@tonic-gate 	return (found);
6967c478bd9Sstevel@tonic-gate }
697034448feSmcpowers 
698034448feSmcpowers /*
699034448feSmcpowers  * set_template_boolean
700034448feSmcpowers  *
701034448feSmcpowers  * Look for the specified boolean attribute, and set its value.
702034448feSmcpowers  *
703034448feSmcpowers  * if 'local' is true, it sets the pointer to the value in the template a new
704034448feSmcpowers  * location.  There should be no memory leak created by this because we are
705034448feSmcpowers  * only doing this to booleans which should not be malloc'ed.
706034448feSmcpowers  *
707034448feSmcpowers  * if 'local' is false, it sets its value.
708034448feSmcpowers  *
709034448feSmcpowers  * The return value specifies if the attribute was found (or not).
710034448feSmcpowers  */
711034448feSmcpowers int
set_template_boolean(CK_ATTRIBUTE_TYPE type,CK_ATTRIBUTE * attributes,CK_ULONG num_attributes,boolean_t local,CK_BBOOL * value)712034448feSmcpowers set_template_boolean(CK_ATTRIBUTE_TYPE type, CK_ATTRIBUTE *attributes,
713*a8793c76SJason King     CK_ULONG num_attributes, boolean_t local, CK_BBOOL *value)
714034448feSmcpowers {
715034448feSmcpowers 	int i;
716034448feSmcpowers 
717034448feSmcpowers 	for (i = 0; i < num_attributes; i++) {
718034448feSmcpowers 		if (attributes[i].type == type) {
719034448feSmcpowers 			if (local)
720034448feSmcpowers 				attributes[i].pValue = value;
721034448feSmcpowers 			else
722034448feSmcpowers 				*((CK_BBOOL *)attributes[i].pValue) = *value;
723034448feSmcpowers 
724034448feSmcpowers 			return (i);
725034448feSmcpowers 		}
726034448feSmcpowers 	}
727034448feSmcpowers 
728034448feSmcpowers 	return (-1);
729034448feSmcpowers }
730