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 /*
30  * Slot and Token Management functions
31  * (as defined in PKCS#11 spec section 11.5)
32  */
33 
34 #include <stdio.h>
35 #include <stdlib.h>
36 #include <string.h>
37 #include "metaGlobal.h"
38 
39 extern CK_ULONG num_meta_sessions;
40 extern CK_ULONG num_rw_meta_sessions;
41 
42 /*
43  * meta_GetSlotList
44  *
45  * For the metaslot, this is a trivial function. The metaslot module,
46  * by defination, provides exactly one slot. The token is always present.
47  *
48  * This function is actually not called.
49  */
50 /* ARGSUSED */
51 CK_RV
52 meta_GetSlotList(CK_BBOOL tokenPresent, CK_SLOT_ID_PTR pSlotList,
53     CK_ULONG_PTR pulCount)
54 {
55 	CK_RV rv;
56 
57 	if (pulCount == NULL)
58 		return (CKR_ARGUMENTS_BAD);
59 
60 	if (pSlotList == NULL) {
61 		*pulCount = 1;
62 		return (CKR_OK);
63 	}
64 
65 	if (*pulCount < 1) {
66 		rv = CKR_BUFFER_TOO_SMALL;
67 	} else {
68 		pSlotList[0] = METASLOT_SLOTID;
69 		rv = CKR_OK;
70 	}
71 	*pulCount = 1;
72 
73 	return (rv);
74 }
75 
76 
77 /*
78  * meta_GetSlotInfo
79  *
80  * Returns basic information about the metaslot.
81  *
82  * The slotID argument is ignored.
83  */
84 /*ARGSUSED*/
85 CK_RV
86 meta_GetSlotInfo(CK_SLOT_ID slotID, CK_SLOT_INFO_PTR pInfo)
87 {
88 	CK_SLOT_INFO slotinfo;
89 	CK_SLOT_ID true_id;
90 	CK_RV rv;
91 
92 	if (!metaslot_enabled) {
93 		return (CKR_SLOT_ID_INVALID);
94 	}
95 
96 	if (pInfo == NULL) {
97 		return (CKR_ARGUMENTS_BAD);
98 	}
99 
100 	/* Provide information about the slot in the provided buffer */
101 	(void) memcpy(pInfo->slotDescription, METASLOT_SLOT_DESCRIPTION, 64);
102 	(void) memcpy(pInfo->manufacturerID, METASLOT_MANUFACTURER_ID, 32);
103 	pInfo->hardwareVersion.major = METASLOT_HARDWARE_VERSION_MAJOR;
104 	pInfo->hardwareVersion.minor = METASLOT_HARDWARE_VERSION_MINOR;
105 	pInfo->firmwareVersion.major = METASLOT_FIRMWARE_VERSION_MAJOR;
106 	pInfo->firmwareVersion.minor = METASLOT_FIRMWARE_VERSION_MINOR;
107 
108 	/* Find out token is present in the underlying keystore */
109 	true_id = TRUEID(metaslot_keystore_slotid);
110 
111 	rv = FUNCLIST(metaslot_keystore_slotid)->C_GetSlotInfo(true_id,
112 	    &slotinfo);
113 	if ((rv == CKR_OK) && (slotinfo.flags & CKF_TOKEN_PRESENT)) {
114 		/*
115 		 * store the token present flag if it is successfully
116 		 * received from the keystore slot.
117 		 * If not, this flag will not be set.
118 		 */
119 		pInfo->flags = CKF_TOKEN_PRESENT;
120 	}
121 
122 	return (CKR_OK);
123 }
124 
125 
126 /*
127  * meta_GetTokenInfo
128  *
129  * Returns basic information about the metaslot "token."
130  *
131  * The slotID argument is ignored.
132  *
133  */
134 /*ARGSUSED*/
135 CK_RV
136 meta_GetTokenInfo(CK_SLOT_ID slotID, CK_TOKEN_INFO_PTR pInfo)
137 {
138 	CK_RV rv;
139 	CK_TOKEN_INFO metainfo;
140 	CK_SLOT_ID true_id;
141 
142 	if (!metaslot_enabled) {
143 		return (CKR_SLOT_ID_INVALID);
144 	}
145 
146 	if (pInfo == NULL)
147 		return (CKR_ARGUMENTS_BAD);
148 
149 	true_id = TRUEID(metaslot_keystore_slotid);
150 
151 	rv = FUNCLIST(metaslot_keystore_slotid)->C_GetTokenInfo(true_id,
152 	    &metainfo);
153 
154 	/*
155 	 * If we could not get information about the object token, use
156 	 * default values. This allows metaslot to be used even if there
157 	 * are problems with the object token (eg, it's not present).
158 	 */
159 	if (rv != CKR_OK) {
160 		metainfo.ulTotalPublicMemory	= CK_UNAVAILABLE_INFORMATION;
161 		metainfo.ulFreePublicMemory	= CK_UNAVAILABLE_INFORMATION;
162 		metainfo.ulTotalPrivateMemory	= CK_UNAVAILABLE_INFORMATION;
163 		metainfo.ulFreePrivateMemory	= CK_UNAVAILABLE_INFORMATION;
164 
165 		metainfo.flags = CKF_WRITE_PROTECTED;
166 
167 		metainfo.ulMaxPinLen = 0;
168 		metainfo.ulMinPinLen = 0;
169 		metainfo.hardwareVersion.major =
170 		    METASLOT_HARDWARE_VERSION_MAJOR;
171 		metainfo.hardwareVersion.minor =
172 		    METASLOT_HARDWARE_VERSION_MINOR;
173 		metainfo.firmwareVersion.major =
174 		    METASLOT_FIRMWARE_VERSION_MAJOR;
175 		metainfo.firmwareVersion.minor =
176 		    METASLOT_FIRMWARE_VERSION_MINOR;
177 	}
178 
179 	/*
180 	 * Override some values that the object token may have set. They
181 	 * can be inappropriate/misleading when used in the context of
182 	 * metaslot.
183 	 */
184 	(void) memcpy(metainfo.label, METASLOT_TOKEN_LABEL, 32);
185 	(void) memcpy(metainfo.manufacturerID,
186 	    METASLOT_MANUFACTURER_ID, 32);
187 	(void) memcpy(metainfo.model, METASLOT_TOKEN_MODEL, 16);
188 	(void) memset(metainfo.serialNumber, ' ', 16);
189 
190 	metainfo.ulMaxSessionCount	= CK_EFFECTIVELY_INFINITE;
191 	metainfo.ulSessionCount		= num_meta_sessions;
192 	metainfo.ulMaxRwSessionCount	= CK_EFFECTIVELY_INFINITE;
193 	metainfo.ulRwSessionCount	= num_rw_meta_sessions;
194 
195 	metainfo.flags |= CKF_RNG;
196 	metainfo.flags &= ~CKF_RESTORE_KEY_NOT_NEEDED;
197 	metainfo.flags |= CKF_TOKEN_INITIALIZED;
198 	metainfo.flags &= ~CKF_SECONDARY_AUTHENTICATION;
199 
200 	/* Clear the time field if the token does not have a clock. */
201 	if (!(metainfo.flags & CKF_CLOCK_ON_TOKEN))
202 		(void) memset(metainfo.utcTime, ' ', 16);
203 
204 	*pInfo = metainfo;
205 
206 	return (CKR_OK);
207 }
208 
209 
210 /*
211  * meta_WaitForSlotEvent
212  *
213  * The metaslot never generates events, so this function doesn't do anything
214  * useful. We do not pass on provider events because we want to hide details
215  * of the providers.
216  *
217  * If CKF_DONT_BLOCK flag is turned on, CKR_NO_EVENT will be return.
218  * Otherwise, return CKR_FUNCTION_FAILED.
219  *
220  */
221 /* ARGSUSED */
222 CK_RV
223 meta_WaitForSlotEvent(CK_FLAGS flags, CK_SLOT_ID_PTR pSlot,
224     CK_VOID_PTR pReserved)
225 {
226 	if (flags & CKF_DONT_BLOCK) {
227 		return (CKR_NO_EVENT);
228 	} else {
229 		return (CKR_FUNCTION_FAILED);
230 	}
231 }
232 
233 
234 /*
235  * meta_GetMechanismList
236  *
237  * The slotID argument is not used.
238  *
239  */
240 /*ARGSUSED*/
241 CK_RV
242 meta_GetMechanismList(CK_SLOT_ID slotID, CK_MECHANISM_TYPE_PTR pMechanismList,
243     CK_ULONG_PTR pulCount)
244 {
245 	CK_RV rv;
246 
247 	if (!metaslot_enabled) {
248 		return (CKR_SLOT_ID_INVALID);
249 	}
250 
251 	if (pulCount == NULL)
252 		return (CKR_ARGUMENTS_BAD);
253 
254 	rv = meta_mechManager_get_mechs(pMechanismList, pulCount);
255 
256 	if ((rv == CKR_BUFFER_TOO_SMALL) && (pMechanismList == NULL)) {
257 		/*
258 		 * if pMechanismList is not provided, just need to
259 		 * return count
260 		 */
261 		rv = CKR_OK;
262 	}
263 	return (rv);
264 }
265 
266 
267 /*
268  * meta_GetMechanismInfo
269  *
270  * The slotID argument is not used.
271  */
272 /*ARGSUSED*/
273 CK_RV
274 meta_GetMechanismInfo(CK_SLOT_ID slotID, CK_MECHANISM_TYPE type,
275     CK_MECHANISM_INFO_PTR pInfo)
276 {
277 	CK_RV rv;
278 	mechinfo_t **slots = NULL;
279 	unsigned long i, slotCount = 0;
280 	mech_support_info_t  mech_support_info;
281 
282 	if (!metaslot_enabled) {
283 		return (CKR_SLOT_ID_INVALID);
284 	}
285 
286 	if (pInfo == NULL) {
287 		return (CKR_ARGUMENTS_BAD);
288 	}
289 
290 	mech_support_info.supporting_slots =
291 	    malloc(meta_slotManager_get_slotcount() * sizeof (mechinfo_t *));
292 	if (mech_support_info.supporting_slots == NULL) {
293 		return (CKR_HOST_MEMORY);
294 	}
295 
296 	mech_support_info.mech = type;
297 
298 	rv = meta_mechManager_get_slots(&mech_support_info, TRUE);
299 	if (rv != CKR_OK) {
300 		free(mech_support_info.supporting_slots);
301 		return (rv);
302 	}
303 
304 	slotCount = mech_support_info.num_supporting_slots;
305 	slots = mech_support_info.supporting_slots;
306 
307 	/* Merge mechanism info from all slots. */
308 	(void) memcpy(pInfo, &(slots[0]->mechanism_info),
309 	    sizeof (CK_MECHANISM_INFO));
310 
311 	/* no need to look at index 0, since that's what we started with */
312 	for (i = 1; i < slotCount; i++) {
313 		CK_ULONG thisValue;
314 
315 		/* MinKeySize should be smallest of all slots. */
316 		thisValue = slots[i]->mechanism_info.ulMinKeySize;
317 		if (thisValue < pInfo->ulMinKeySize) {
318 			pInfo->ulMinKeySize = thisValue;
319 		}
320 
321 		/* MaxKeySize should be largest of all slots. */
322 		thisValue = slots[i]->mechanism_info.ulMaxKeySize;
323 		if (thisValue > pInfo->ulMaxKeySize) {
324 			pInfo->ulMaxKeySize = thisValue;
325 		}
326 
327 		pInfo->flags |= slots[i]->mechanism_info.flags;
328 	}
329 
330 	/* Clear the CKF_HW flag. We might select a software provider later. */
331 	pInfo->flags &= ~CKF_HW;
332 
333 	/* Clear the extenstion flag. Spec says is should never even be set. */
334 	pInfo->flags &= ~CKF_EXTENSION;
335 
336 	free(mech_support_info.supporting_slots);
337 
338 	return (CKR_OK);
339 }
340 
341 
342 /*
343  * meta_InitToken
344  *
345  * Not supported. The metaslot "token" is always initialized. The token object
346  * token must already be initialized. Other vendors don't seem to support
347  * this anyway.
348  */
349 /* ARGSUSED */
350 CK_RV
351 meta_InitToken(CK_SLOT_ID slotID, CK_UTF8CHAR_PTR pPin, CK_ULONG ulPinLen,
352     CK_UTF8CHAR_PTR pLabel)
353 {
354 	return (CKR_FUNCTION_NOT_SUPPORTED);
355 }
356 
357 
358 /*
359  * meta_InitPIN
360  *
361  * Not supported. Same reason as C_InitToken.
362  */
363 /* ARGSUSED */
364 CK_RV
365 meta_InitPIN(CK_SESSION_HANDLE hSession,
366     CK_UTF8CHAR_PTR pPin, CK_ULONG ulPinLen)
367 {
368 	return (CKR_FUNCTION_NOT_SUPPORTED);
369 }
370 
371 
372 /*
373  * meta_SetPIN
374  *
375  * This is basically just a pass-thru to the object token. No need to
376  * even check the arguments, since we don't use them.
377  */
378 CK_RV
379 meta_SetPIN(CK_SESSION_HANDLE hSession, CK_UTF8CHAR_PTR pOldPin,
380     CK_ULONG ulOldPinLen, CK_UTF8CHAR_PTR pNewPin, CK_ULONG ulNewPinLen)
381 {
382 	CK_RV rv;
383 	meta_session_t *session;
384 	slot_session_t *slot_session;
385 
386 	rv = meta_handle2session(hSession, &session);
387 	if (rv != CKR_OK)
388 		return (rv);
389 
390 	if (IS_READ_ONLY_SESSION(session->session_flags)) {
391 		REFRELEASE(session);
392 		return (CKR_SESSION_READ_ONLY);
393 	}
394 
395 	rv = meta_get_slot_session(get_keystore_slotnum(), &slot_session,
396 	    session->session_flags);
397 	if (rv != CKR_OK) {
398 		REFRELEASE(session);
399 		return (rv);
400 	}
401 
402 	rv = FUNCLIST(slot_session->fw_st_id)->C_SetPIN(slot_session->hSession,
403 	    pOldPin, ulOldPinLen, pNewPin, ulNewPinLen);
404 
405 	meta_release_slot_session(slot_session);
406 
407 	REFRELEASE(session);
408 	return (rv);
409 }
410