xref: /illumos-gate/usr/src/lib/pkcs11/libpkcs11/common/pkcs11SUNWExtensions.c (revision 7c478bd95313f5f23a4c958a745db2134aa03244)
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 2004 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 /*
30  * Solaris specific functions to reduce the initialization
31  * overhead of using PKCS #11
32  */
33 
34 #include <stdlib.h>
35 #include <sys/types.h>
36 #include <security/cryptoki.h>
37 #include <assert.h>
38 #include <cryptoutil.h>
39 
40 static CK_OBJECT_CLASS objclass = CKO_SECRET_KEY;
41 static CK_BBOOL falsevalue = FALSE;
42 static CK_BBOOL truevalue = TRUE;
43 
44 #define	NUM_SECRETKEY_ATTRS	8
45 
46 typedef struct _ATTRTYPE_MECHINFO_MAPPING {
47 	CK_ATTRIBUTE_TYPE attr;
48 	CK_FLAGS	flag;
49 } ATTRTYPE_MECHINFO_MAPPING;
50 
51 /* possible attribute types for creating key */
52 ATTRTYPE_MECHINFO_MAPPING mapping[] = {
53 	{CKA_ENCRYPT, CKF_ENCRYPT},
54 	{CKA_DECRYPT, CKF_DECRYPT},
55 	{CKA_SIGN, CKF_SIGN},
56 	{CKA_VERIFY, CKF_VERIFY}
57 };
58 
59 
60 /*
61  * List of mechanisms that only supports asymmetric key operations
62  * in PKCS #11 V2.11
63  */
64 CK_MECHANISM_TYPE asymmetric_mechs[] = {
65 	CKM_RSA_PKCS_KEY_PAIR_GEN, CKM_RSA_PKCS, CKM_RSA_9796, CKM_RSA_X_509,
66 	CKM_RSA_PKCS_OAEP, CKM_RSA_X9_31_KEY_PAIR_GEN, CKM_RSA_X9_31,
67 	CKM_RSA_PKCS_PSS, CKM_DSA_KEY_PAIR_GEN, CKM_DSA, CKM_DSA_SHA1,
68 	CKM_DSA_PARAMETER_GEN, CKM_ECDSA_KEY_PAIR_GEN, CKM_EC_KEY_PAIR_GEN,
69 	CKM_ECDSA, CKM_ECDSA_SHA1, CKM_ECDH1_DERIVE,
70 	CKM_ECDH1_COFACTOR_DERIVE, CKM_ECMQV_DERIVE
71 };
72 
73 
74 /*
75  * SUNW_C_GetMechSession will initialize the framework and do all
76  * of the neccessary work of calling C_GetSlotList(), C_GetMechanismInfo()
77  * C_OpenSession() to provide a session capable of providing the requested
78  * mechanism.
79  *
80  * If the function is called multiple times, it will return a new session
81  * without reinitializing the framework.
82  */
83 CK_RV
84 SUNW_C_GetMechSession(CK_MECHANISM_TYPE mech, CK_SESSION_HANDLE_PTR hSession)
85 {
86 	CK_RV rv;
87 	CK_ULONG slotcount;
88 	CK_SLOT_ID_PTR slot_list;
89 	CK_SLOT_ID slot_id;
90 	CK_MECHANISM_INFO mech_info;
91 	CK_ULONG i;
92 
93 	if (hSession == NULL) {
94 		return (CKR_ARGUMENTS_BAD);
95 	}
96 
97 	/* initialize PKCS #11 */
98 	rv = C_Initialize(NULL);
99 	if ((rv != CKR_OK) && (rv != CKR_CRYPTOKI_ALREADY_INITIALIZED)) {
100 		return (rv);
101 	}
102 
103 	/* get slot count */
104 	rv = C_GetSlotList(0, NULL, &slotcount);
105 	if (rv != CKR_OK) {
106 		return (rv);
107 	}
108 
109 	if (slotcount == 0) {
110 		return (CKR_FUNCTION_FAILED);
111 	}
112 
113 
114 	/* allocate memory for slot list */
115 	slot_list = malloc(slotcount * sizeof (CK_SLOT_ID));
116 	if (slot_list == NULL) {
117 		return (CKR_HOST_MEMORY);
118 	}
119 
120 	if ((rv = C_GetSlotList(0, slot_list, &slotcount)) != CKR_OK) {
121 		free(slot_list);
122 		return (rv);
123 	}
124 
125 	/* find slot with matching mechanism */
126 	for (i = 0; i < slotcount; i++) {
127 		slot_id = slot_list[i];
128 		if (C_GetMechanismInfo(slot_id, mech, &mech_info) == CKR_OK) {
129 			/* found mechanism */
130 			break;
131 		}
132 	}
133 
134 	if (i == slotcount) {
135 		/* no matching mechanism found */
136 		free(slot_list);
137 		return (CKR_MECHANISM_INVALID);
138 	}
139 
140 	rv = C_OpenSession(slot_id, CKF_SERIAL_SESSION, NULL,
141 	    NULL, hSession);
142 
143 	free(slot_list);
144 	return (rv);
145 }
146 
147 /*
148  * SUNW_C_KeyToObject creates a secret key object for the given
149  * mechanism from the rawkey data.
150  */
151 CK_RV
152 SUNW_C_KeyToObject(CK_SESSION_HANDLE hSession, CK_MECHANISM_TYPE mech,
153     const void *rawkey, size_t rawkey_len, CK_OBJECT_HANDLE_PTR obj)
154 {
155 
156 	CK_RV rv;
157 	CK_SESSION_INFO session_info;
158 	CK_SLOT_ID slot_id;
159 	CK_MECHANISM_INFO mech_info;
160 	CK_ULONG i, j;
161 	CK_KEY_TYPE keytype;
162 	CK_ULONG num_asym_mechs, num_mapping;
163 
164 	/* template for creating generic secret key object */
165 	CK_ATTRIBUTE template[NUM_SECRETKEY_ATTRS];
166 
167 	if ((hSession == NULL) || (obj == NULL) ||
168 	    (rawkey == NULL) || (rawkey_len == 0)) {
169 		return (CKR_ARGUMENTS_BAD);
170 	}
171 
172 	/*
173 	 * Check to make sure mechanism type is not for asymmetric key
174 	 * only operations.  This function is only applicable to
175 	 * generating secret key.
176 	 */
177 	num_asym_mechs = sizeof (asymmetric_mechs) / sizeof (CK_MECHANISM_TYPE);
178 	for (i = 0; i < num_asym_mechs; i++) {
179 		if (mech == asymmetric_mechs[i]) {
180 			return (CKR_MECHANISM_INVALID);
181 		}
182 	}
183 
184 	/* set the attribute type flag on object based on mechanism */
185 	rv = C_GetSessionInfo(hSession, &session_info);
186 	if (rv != CKR_OK) {
187 		goto cleanup;
188 	}
189 
190 	slot_id = session_info.slotID;
191 
192 	/* create a generic object first */
193 	i = 0;
194 	template[i].type = CKA_CLASS;
195 	template[i].pValue = &objclass;
196 	template[i].ulValueLen = sizeof (objclass);
197 	i++;
198 
199 	/* get the key type for this mechanism */
200 	if ((rv = pkcs11_mech2keytype(mech, &keytype)) != CKR_OK) {
201 		return (rv);
202 	}
203 
204 	assert(i < NUM_SECRETKEY_ATTRS);
205 	template[i].type = CKA_KEY_TYPE;
206 	template[i].pValue = &keytype;
207 	template[i].ulValueLen = sizeof (keytype);
208 	i++;
209 
210 	rv = C_GetMechanismInfo(slot_id, mech, &mech_info);
211 	if (rv != CKR_OK) {
212 		goto cleanup;
213 	}
214 
215 	num_mapping = sizeof (mapping) / sizeof (ATTRTYPE_MECHINFO_MAPPING);
216 	for (j = 0; j < num_mapping; j++) {
217 		assert(i < NUM_SECRETKEY_ATTRS);
218 		template[i].type = mapping[j].attr;
219 		template[i].ulValueLen = sizeof (falsevalue);
220 		if (mech_info.flags & ((mapping[j]).flag)) {
221 			template[i].pValue = &truevalue;
222 		} else {
223 			template[i].pValue = &falsevalue;
224 		}
225 		i++;
226 	}
227 
228 	assert(i < NUM_SECRETKEY_ATTRS);
229 	template[i].type = CKA_TOKEN;
230 	template[i].pValue = &falsevalue;
231 	template[i].ulValueLen = sizeof (falsevalue);
232 	i++;
233 
234 	assert(i < NUM_SECRETKEY_ATTRS);
235 	template[i].type = CKA_VALUE;
236 	template[i].pValue = (CK_VOID_PTR)rawkey;
237 	template[i].ulValueLen = (CK_ULONG)rawkey_len;
238 	i++;
239 
240 	rv = C_CreateObject(hSession, template, i, obj);
241 	if (rv != CKR_OK) {
242 		return (rv);
243 	}
244 
245 	return (rv);
246 
247 cleanup:
248 	/* This cleanup is only for failure cases */
249 	(void) C_DestroyObject(hSession, *obj);
250 	return (rv);
251 }
252