xref: /illumos-gate/usr/src/lib/pkcs11/pkcs11_tpm/common/tpm_specific.c (revision 7a088f03b431bdffa96c3b2175964d4d38420caa)
1 /*
2  * The Initial Developer of the Original Code is International
3  * Business Machines Corporation. Portions created by IBM
4  * Corporation are Copyright (C) 2005 International Business
5  * Machines Corporation. All Rights Reserved.
6  *
7  * This program is free software; you can redistribute it and/or modify
8  * it under the terms of the Common Public License as published by
9  * IBM Corporation; either version 1 of the License, or (at your option)
10  * any later version.
11  *
12  * This program is distributed in the hope that it will be useful,
13  * but WITHOUT ANY WARRANTY; without even the implied warranty of
14  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15  * Common Public License for more details.
16  *
17  * You should have received a copy of the Common Public License
18  * along with this program; if not, a copy can be viewed at
19  * http://www.opensource.org/licenses/cpl1.0.php.
20  */
21 /*
22  * Copyright 2009 Sun Microsystems, Inc.  All rights reserved.
23  * Use is subject to license terms.
24  */
25 
26 #include <pthread.h>
27 #include <string.h>
28 
29 #include <sys/types.h>
30 #include <sys/stat.h>
31 #include <uuid/uuid.h>
32 #include <fcntl.h>
33 #include <errno.h>
34 #include <pwd.h>
35 #include <syslog.h>
36 
37 #include <tss/platform.h>
38 #include <tss/tss_defines.h>
39 #include <tss/tss_typedef.h>
40 #include <tss/tss_structs.h>
41 #include <tss/tss_error.h>
42 #include <tss/tcs_error.h>
43 #include <tss/tspi.h>
44 #include <trousers/trousers.h>
45 
46 #include "tpmtok_int.h"
47 #include "tpmtok_defs.h"
48 
49 extern void stlogit(char *fmt, ...);
50 
51 CK_RV token_rng(TSS_HCONTEXT, CK_BYTE *,  CK_ULONG);
52 int tok_slot2local(CK_SLOT_ID);
53 CK_RV token_specific_session(CK_SLOT_ID);
54 CK_RV token_specific_final(void);
55 
56 CK_RV
57 token_specific_rsa_decrypt(
58 	TSS_HCONTEXT,
59 	CK_BYTE *,
60 	CK_ULONG,
61 	CK_BYTE *,
62 	CK_ULONG *,
63 	OBJECT *);
64 
65 CK_RV
66 token_specific_rsa_encrypt(
67 	TSS_HCONTEXT,
68 	CK_BYTE *,
69 	CK_ULONG,
70 	CK_BYTE *,
71 	CK_ULONG *,
72 	OBJECT *);
73 
74 CK_RV
75 token_specific_rsa_sign(
76 	TSS_HCONTEXT,
77 	CK_BYTE *,
78 	CK_ULONG,
79 	CK_BYTE *,
80 	CK_ULONG *,
81 	OBJECT *);
82 
83 CK_RV
84 token_specific_rsa_verify(TSS_HCONTEXT, CK_BYTE *,
85     CK_ULONG, CK_BYTE *, CK_ULONG, OBJECT *);
86 
87 CK_RV
88 token_specific_rsa_generate_keypair(TSS_HCONTEXT,
89 	TEMPLATE *,
90 	TEMPLATE *);
91 
92 CK_RV
93 token_specific_sha_init(DIGEST_CONTEXT *);
94 
95 CK_RV
96 token_specific_sha_update(DIGEST_CONTEXT *,
97 	CK_BYTE *,
98 	CK_ULONG);
99 
100 CK_RV
101 token_specific_sha_final(DIGEST_CONTEXT *,
102 	CK_BYTE *,
103 	CK_ULONG *);
104 
105 CK_RV token_specific_login(TSS_HCONTEXT, CK_USER_TYPE, CK_CHAR_PTR, CK_ULONG);
106 CK_RV token_specific_logout(TSS_HCONTEXT);
107 CK_RV token_specific_init_pin(TSS_HCONTEXT, CK_CHAR_PTR, CK_ULONG);
108 CK_RV token_specific_set_pin(ST_SESSION_HANDLE, CK_CHAR_PTR,
109 	CK_ULONG, CK_CHAR_PTR, CK_ULONG);
110 CK_RV token_specific_verify_so_pin(TSS_HCONTEXT, CK_CHAR_PTR, CK_ULONG);
111 
112 static CK_RV
113 token_specific_init(char *, CK_SLOT_ID, TSS_HCONTEXT *);
114 
115 struct token_specific_struct token_specific = {
116 	"TPM_Debug",
117 	&token_specific_init,
118 	NULL,
119 	&token_rng,
120 	&token_specific_session,
121 	&token_specific_final,
122 	&token_specific_rsa_decrypt,
123 	&token_specific_rsa_encrypt,
124 	&token_specific_rsa_sign,
125 	&token_specific_rsa_verify,
126 	&token_specific_rsa_generate_keypair,
127 	NULL,
128 	NULL,
129 	NULL,
130 	&token_specific_login,
131 	&token_specific_logout,
132 	&token_specific_init_pin,
133 	&token_specific_set_pin,
134 	&token_specific_verify_so_pin
135 };
136 
137 /* The context we'll use globally to connect to the TSP */
138 
139 /* TSP key handles */
140 TSS_HKEY hPublicRootKey = NULL_HKEY;
141 TSS_HKEY hPublicLeafKey = NULL_HKEY;
142 TSS_HKEY hPrivateRootKey = NULL_HKEY;
143 TSS_HKEY hPrivateLeafKey = NULL_HKEY;
144 
145 TSS_UUID publicRootKeyUUID;
146 TSS_UUID publicLeafKeyUUID;
147 TSS_UUID privateRootKeyUUID;
148 TSS_UUID privateLeafKeyUUID;
149 
150 /* TSP policy handles */
151 TSS_HPOLICY hDefaultPolicy = NULL_HPOLICY;
152 
153 /* PKCS#11 key handles */
154 CK_OBJECT_HANDLE ckPublicRootKey = 0;
155 CK_OBJECT_HANDLE ckPublicLeafKey = 0;
156 CK_OBJECT_HANDLE ckPrivateRootKey = 0;
157 CK_OBJECT_HANDLE ckPrivateLeafKey = 0;
158 
159 int not_initialized = 0;
160 
161 CK_BYTE current_user_pin_sha[SHA1_DIGEST_LENGTH];
162 CK_BYTE current_so_pin_sha[SHA1_DIGEST_LENGTH];
163 
164 static TPM_CAP_VERSION_INFO tpmvinfo;
165 
166 static CK_RV
167 verify_user_pin(TSS_HCONTEXT, CK_BYTE *);
168 
169 static void
170 local_uuid_clear(TSS_UUID *uuid)
171 {
172 	if (uuid == NULL)
173 		return;
174 	(void) memset(uuid, 0, sizeof (TSS_UUID));
175 }
176 
177 
178 /* convert from TSS_UUID to uuid_t */
179 static void
180 tss_uuid_convert_from(TSS_UUID *uu, uuid_t ptr)
181 {
182 	uint_t		tmp;
183 	uchar_t		*out = ptr;
184 
185 	tmp = ntohl(uu->ulTimeLow);
186 	out[3] = (uchar_t)tmp;
187 	tmp >>= 8;
188 	out[2] = (uchar_t)tmp;
189 	tmp >>= 8;
190 	out[1] = (uchar_t)tmp;
191 	tmp >>= 8;
192 	out[0] = (uchar_t)tmp;
193 
194 	tmp = ntohs(uu->usTimeMid);
195 	out[5] = (uchar_t)tmp;
196 	tmp >>= 8;
197 	out[4] = (uchar_t)tmp;
198 
199 	tmp = ntohs(uu->usTimeHigh);
200 	out[7] = (uchar_t)tmp;
201 	tmp >>= 8;
202 	out[6] = (uchar_t)tmp;
203 
204 	tmp = uu->bClockSeqHigh;
205 	out[8] = (uchar_t)tmp;
206 	tmp = uu->bClockSeqLow;
207 	out[9] = (uchar_t)tmp;
208 
209 	(void) memcpy(out+10, uu->rgbNode, 6);
210 }
211 
212 /* convert from uuid_t to TSS_UUID */
213 static void
214 tss_uuid_convert_to(TSS_UUID *uuid, uuid_t in)
215 {
216 	uchar_t		*ptr;
217 	uint32_t	ltmp;
218 	uint16_t	stmp;
219 
220 	ptr = in;
221 
222 	ltmp = *ptr++;
223 	ltmp = (ltmp << 8) | *ptr++;
224 	ltmp = (ltmp << 8) | *ptr++;
225 	ltmp = (ltmp << 8) | *ptr++;
226 	uuid->ulTimeLow = ntohl(ltmp);
227 
228 	stmp = *ptr++;
229 	stmp = (stmp << 8) | *ptr++;
230 	uuid->usTimeMid = ntohs(stmp);
231 
232 	stmp = *ptr++;
233 	stmp = (stmp << 8) | *ptr++;
234 	uuid->usTimeHigh = ntohs(stmp);
235 
236 	uuid->bClockSeqHigh = *ptr++;
237 
238 	uuid->bClockSeqLow = *ptr++;
239 
240 	(void) memcpy(uuid->rgbNode, ptr, 6);
241 }
242 
243 static void
244 local_uuid_copy(TSS_UUID *dst, TSS_UUID *src)
245 {
246 	uuid_t udst, usrc;
247 
248 	tss_uuid_convert_from(dst, udst);
249 	tss_uuid_convert_from(src, usrc);
250 
251 	uuid_copy(udst, usrc);
252 
253 	tss_uuid_convert_to(dst, udst);
254 }
255 
256 static void
257 local_uuid_generate(TSS_UUID *uu)
258 {
259 	uuid_t newuuid;
260 
261 	uuid_generate(newuuid);
262 
263 	tss_uuid_convert_to(uu, newuuid);
264 }
265 
266 static int
267 local_copy_file(char *dst, char *src)
268 {
269 	FILE *fdest, *fsrc;
270 	char line[BUFSIZ];
271 
272 	fdest = fopen(dst, "w");
273 	if (fdest == NULL)
274 		return (-1);
275 
276 	fsrc = fopen(src, "r");
277 	if (fsrc == NULL) {
278 		(void) fclose(fdest);
279 		return (-1);
280 	}
281 
282 	while (fread(line, sizeof (line), 1, fsrc))
283 		(void) fprintf(fdest, "%s\n", line);
284 	(void) fclose(fsrc);
285 	(void) fclose(fdest);
286 	return (0);
287 }
288 
289 static int
290 remove_uuid(char *keyname)
291 {
292 	int ret = 0;
293 	FILE *fp, *newfp;
294 	char fname[MAXPATHLEN];
295 	char line[BUFSIZ], key[BUFSIZ], idstr[BUFSIZ];
296 	char *tmpfname;
297 	char *p = get_tpm_keystore_path();
298 
299 	if (p == NULL)
300 		return (-1);
301 
302 	(void) snprintf(fname, sizeof (fname),
303 	    "%s/%s", p, TPMTOK_UUID_INDEX_FILENAME);
304 
305 	fp = fopen(fname, "r");
306 	if (fp == NULL) {
307 		return (-1);
308 	}
309 
310 	tmpfname = tempnam("/tmp", "tpmtok");
311 	newfp = fopen(tmpfname, "w+");
312 	if (newfp == NULL) {
313 		free(tmpfname);
314 		(void) fclose(fp);
315 		return (-1);
316 	}
317 
318 	while (!feof(fp)) {
319 		(void) fgets(line, sizeof (line), fp);
320 		if (sscanf(line, "%1024s %1024s", key, idstr) == 2) {
321 			if (strcmp(key, keyname))
322 				(void) fprintf(newfp, "%s\n", line);
323 		}
324 	}
325 
326 	(void) fclose(fp);
327 	(void) fclose(newfp);
328 	if (local_copy_file(fname, tmpfname) == 0)
329 		(void) unlink(tmpfname);
330 
331 	free(tmpfname);
332 
333 	return (ret);
334 }
335 
336 static int
337 find_uuid(char *keyname, TSS_UUID *uu)
338 {
339 	int ret = 0, found = 0;
340 	FILE *fp = NULL;
341 	char fname[MAXPATHLEN];
342 	char line[BUFSIZ], key[BUFSIZ], idstr[BUFSIZ];
343 	uuid_t uuid;
344 	char *p = get_tpm_keystore_path();
345 
346 	if (p == NULL)
347 		return (-1);
348 
349 	tss_uuid_convert_from(uu, uuid);
350 
351 	(void) snprintf(fname, sizeof (fname),
352 	    "%s/%s", p, TPMTOK_UUID_INDEX_FILENAME);
353 
354 	/* Open UUID Index file */
355 	fp = fopen(fname, "r");
356 	if (fp == NULL) {
357 		if (errno == ENOENT) {
358 			/* initialize the file */
359 			fp = fopen(fname, "w");
360 			if (fp != NULL)
361 				(void) fclose(fp);
362 		}
363 		return (-1);
364 	}
365 
366 	while (!feof(fp)) {
367 		(void) fgets(line, sizeof (line), fp);
368 		if (sscanf(line, "%1024s %1024s", key, idstr) == 2) {
369 			if (strcmp(key, keyname) == 0) {
370 				ret = uuid_parse(idstr, uuid);
371 				if (ret == 0) {
372 					found = 1;
373 					tss_uuid_convert_to(uu,
374 					    uuid);
375 				}
376 				break;
377 			}
378 		}
379 	}
380 	(void) fclose(fp);
381 
382 	if (!found)
383 		ret = -1;
384 	return (ret);
385 }
386 
387 static int
388 local_uuid_is_null(TSS_UUID *uu)
389 {
390 	uuid_t uuid;
391 	int nulluuid;
392 
393 	tss_uuid_convert_from(uu, uuid);
394 
395 	nulluuid = uuid_is_null(uuid);
396 	return (nulluuid);
397 }
398 
399 static int
400 add_uuid(char *keyname, TSS_UUID *uu)
401 {
402 	FILE *fp = NULL;
403 	char fname[MAXPATHLEN];
404 	char idstr[BUFSIZ];
405 	uuid_t uuid;
406 	char *p = get_tpm_keystore_path();
407 
408 	if (p == NULL)
409 		return (-1);
410 
411 	tss_uuid_convert_from(uu, uuid);
412 
413 	if (uuid_is_null(uuid))
414 		return (-1);
415 
416 	uuid_unparse(uuid, idstr);
417 
418 	(void) snprintf(fname, sizeof (fname),
419 	    "%s/%s", p, TPMTOK_UUID_INDEX_FILENAME);
420 
421 	fp = fopen(fname, "a");
422 	if (fp == NULL)
423 		return (-1);
424 
425 	(void) fprintf(fp, "%s %s\n", keyname, idstr);
426 	(void) fclose(fp);
427 
428 	return (0);
429 }
430 
431 
432 static UINT32
433 util_get_keysize_flag(CK_ULONG size)
434 {
435 	switch (size) {
436 		case 512:
437 			return (TSS_KEY_SIZE_512);
438 			break;
439 		case 1024:
440 			return (TSS_KEY_SIZE_1024);
441 			break;
442 		case 2048:
443 			return (TSS_KEY_SIZE_2048);
444 			break;
445 		default:
446 			break;
447 	}
448 
449 	return (0);
450 }
451 
452 /* make sure the public exponent attribute is 65537 */
453 static CK_ULONG
454 util_check_public_exponent(TEMPLATE *tmpl)
455 {
456 	CK_BBOOL flag;
457 	CK_ATTRIBUTE *publ_exp_attr;
458 	CK_BYTE pubexp_bytes[] = { 1, 0, 1 };
459 	CK_ULONG publ_exp, rc = 1;
460 
461 	flag = template_attribute_find(tmpl, CKA_PUBLIC_EXPONENT,
462 	    &publ_exp_attr);
463 	if (!flag) {
464 		LogError1("Couldn't find public exponent attribute");
465 		return (CKR_TEMPLATE_INCOMPLETE);
466 	}
467 
468 	switch (publ_exp_attr->ulValueLen) {
469 		case 3:
470 			rc = memcmp(pubexp_bytes, publ_exp_attr->pValue, 3);
471 			break;
472 		case sizeof (CK_ULONG):
473 			publ_exp = *((CK_ULONG *)publ_exp_attr->pValue);
474 			if (publ_exp == 65537)
475 				rc = 0;
476 			break;
477 		default:
478 			break;
479 	}
480 
481 	return (rc);
482 }
483 
484 TSS_RESULT
485 set_public_modulus(TSS_HCONTEXT hContext, TSS_HKEY hKey,
486 	unsigned long size_n, unsigned char *n)
487 {
488 	UINT64 offset;
489 	UINT32 blob_size;
490 	BYTE *blob, pub_blob[1024];
491 	TCPA_PUBKEY pub_key;
492 	TSS_RESULT result;
493 
494 	/* Get the TCPA_PUBKEY blob from the key object. */
495 	result = Tspi_GetAttribData(hKey, TSS_TSPATTRIB_KEY_BLOB,
496 	    TSS_TSPATTRIB_KEYBLOB_PUBLIC_KEY, &blob_size, &blob);
497 	if (result != TSS_SUCCESS) {
498 		stlogit("Tspi_GetAttribData failed: rc=0x%0x - %s\n",
499 		    result, Trspi_Error_String(result));
500 		return (result);
501 	}
502 
503 	offset = 0;
504 	result = Trspi_UnloadBlob_PUBKEY(&offset, blob, &pub_key);
505 	if (result != TSS_SUCCESS) {
506 		stlogit("Trspi_UnloadBlob_PUBKEY failed: rc=0x%0x - %s\n",
507 		    result, Trspi_Error_String(result));
508 		return (result);
509 	}
510 
511 	Tspi_Context_FreeMemory(hContext, blob);
512 	/* Free the first dangling reference, putting 'n' in its place */
513 	free(pub_key.pubKey.key);
514 	pub_key.pubKey.keyLength = size_n;
515 	pub_key.pubKey.key = n;
516 
517 	offset = 0;
518 	Trspi_LoadBlob_PUBKEY(&offset, pub_blob, &pub_key);
519 
520 	/* Free the second dangling reference */
521 	free(pub_key.algorithmParms.parms);
522 
523 	/* set the public key data in the TSS object */
524 	result = Tspi_SetAttribData(hKey, TSS_TSPATTRIB_KEY_BLOB,
525 	    TSS_TSPATTRIB_KEYBLOB_PUBLIC_KEY, (UINT32)offset, pub_blob);
526 	if (result != TSS_SUCCESS) {
527 		stlogit("Tspi_SetAttribData failed: rc=0x%0x - %s\n",
528 		    result, Trspi_Error_String(result));
529 		return (result);
530 	}
531 
532 	return (result);
533 }
534 
535 /*
536  * Get details about the TPM to put into the token_info structure.
537  */
538 CK_RV
539 token_get_tpm_info(TSS_HCONTEXT hContext, TOKEN_DATA *td)
540 {
541 	TSS_RESULT result;
542 	TPM_CAPABILITY_AREA capArea = TSS_TPMCAP_VERSION_VAL;
543 	UINT32 datalen;
544 	BYTE *data;
545 	TSS_HTPM hTPM;
546 
547 	if ((result = Tspi_Context_GetTpmObject(hContext, &hTPM))) {
548 		stlogit("Tspi_Context_GetTpmObject: 0x%0x - %s",
549 		    result, Trspi_Error_String(result));
550 		return (CKR_FUNCTION_FAILED);
551 	}
552 	if ((result = Tspi_TPM_GetCapability(hTPM,
553 	    capArea, 0, NULL, &datalen, &data)) != 0 || datalen == 0 ||
554 	    data == NULL) {
555 		stlogit("Tspi_Context_GetCapability: 0x%0x - %s",
556 		    result, Trspi_Error_String(result));
557 		return (CKR_FUNCTION_FAILED);
558 	}
559 	if (datalen > sizeof (tpmvinfo)) {
560 		Tspi_Context_FreeMemory(hContext, data);
561 		return (CKR_FUNCTION_FAILED);
562 	}
563 
564 	(void) memcpy(&tpmvinfo, (void *)data, sizeof (tpmvinfo));
565 
566 	bzero(td->token_info.manufacturerID,
567 	    sizeof (td->token_info.manufacturerID));
568 
569 	(void) memset(td->token_info.manufacturerID,  ' ',
570 	    sizeof (td->token_info.manufacturerID) - 1);
571 	(void) memcpy(td->token_info.manufacturerID,
572 	    tpmvinfo.tpmVendorID, sizeof (tpmvinfo.tpmVendorID));
573 
574 	(void) memset(td->token_info.label, ' ',
575 	    sizeof (td->token_info.label) - 1);
576 	(void) memcpy(td->token_info.label, "TPM", 6);
577 
578 	td->token_info.hardwareVersion.major = tpmvinfo.version.major;
579 	td->token_info.hardwareVersion.minor = tpmvinfo.version.minor;
580 	td->token_info.firmwareVersion.major = tpmvinfo.version.revMajor;
581 	td->token_info.firmwareVersion.minor = tpmvinfo.version.revMinor;
582 
583 	Tspi_Context_FreeMemory(hContext, data);
584 	return (CKR_OK);
585 }
586 
587 /*ARGSUSED*/
588 CK_RV
589 token_specific_session(CK_SLOT_ID  slotid)
590 {
591 	return (CKR_OK);
592 }
593 
594 CK_RV
595 token_rng(TSS_HCONTEXT hContext, CK_BYTE *output, CK_ULONG bytes)
596 {
597 	TSS_RESULT rc;
598 	TSS_HTPM hTPM;
599 	BYTE *random_bytes = NULL;
600 
601 	if ((rc = Tspi_Context_GetTpmObject(hContext, &hTPM))) {
602 		stlogit("Tspi_Context_GetTpmObject: 0x%0x - %s",
603 		    rc, Trspi_Error_String(rc));
604 		return (CKR_FUNCTION_FAILED);
605 	}
606 
607 	if ((rc = Tspi_TPM_GetRandom(hTPM, bytes, &random_bytes))) {
608 		stlogit("Tspi_TPM_GetRandom: 0x%0x - %s",
609 		    rc, Trspi_Error_String(rc));
610 		return (CKR_FUNCTION_FAILED);
611 	}
612 
613 	(void) memcpy(output, random_bytes, bytes);
614 	Tspi_Context_FreeMemory(hContext, random_bytes);
615 
616 	return (CKR_OK);
617 }
618 
619 TSS_RESULT
620 open_tss_context(TSS_HCONTEXT *pContext)
621 {
622 	TSS_RESULT result;
623 
624 	if ((result = Tspi_Context_Create(pContext))) {
625 		stlogit("Tspi_Context_Create: 0x%0x - %s",
626 		    result, Trspi_Error_String(result));
627 		return (CKR_FUNCTION_FAILED);
628 	}
629 
630 	if ((result = Tspi_Context_Connect(*pContext, NULL))) {
631 		stlogit("Tspi_Context_Connect: 0x%0x - %s",
632 		    result, Trspi_Error_String(result));
633 		return (CKR_FUNCTION_FAILED);
634 	}
635 	return (result);
636 }
637 
638 /*ARGSUSED*/
639 static CK_RV
640 token_specific_init(char *Correlator, CK_SLOT_ID SlotNumber,
641     TSS_HCONTEXT *hContext)
642 {
643 	TSS_RESULT result;
644 
645 	result = open_tss_context(hContext);
646 	if (result)
647 		return (CKR_FUNCTION_FAILED);
648 
649 	if ((result = Tspi_Context_GetDefaultPolicy(*hContext,
650 	    &hDefaultPolicy))) {
651 		stlogit("Tspi_Context_GetDefaultPolicy: 0x%0x - %s",
652 		    result, Trspi_Error_String(result));
653 		return (CKR_FUNCTION_FAILED);
654 	}
655 
656 	local_uuid_clear(&publicRootKeyUUID);
657 	local_uuid_clear(&privateRootKeyUUID);
658 	local_uuid_clear(&publicLeafKeyUUID);
659 	local_uuid_clear(&privateLeafKeyUUID);
660 
661 	result = token_get_tpm_info(*hContext, nv_token_data);
662 	return (result);
663 }
664 
665 /*
666  * Try to find the opaque key blob data for a token object.
667  */
668 static CK_RV
669 token_get_key_blob(CK_OBJECT_HANDLE ckKey, CK_ULONG *blob_size,
670 	CK_BYTE **ret_blob)
671 {
672 	CK_RV rc = CKR_OK;
673 	CK_BYTE_PTR blob = NULL;
674 	CK_ATTRIBUTE tmpl[] = {
675 		{CKA_IBM_OPAQUE, NULL_PTR, 0}
676 	};
677 	SESSION dummy_sess;
678 
679 	/* set up dummy session */
680 	(void) memset(&dummy_sess, 0, sizeof (SESSION));
681 	dummy_sess.session_info.state = CKS_RO_USER_FUNCTIONS;
682 
683 	/* find object the first time to return the size of the buffer needed */
684 	if ((rc = object_mgr_get_attribute_values(&dummy_sess, ckKey,
685 	    tmpl, 1))) {
686 		return (rc);
687 	}
688 
689 	blob = malloc(tmpl[0].ulValueLen);
690 	if (blob == NULL) {
691 		rc = CKR_HOST_MEMORY;
692 		return (rc);
693 	}
694 
695 	tmpl[0].pValue = blob;
696 	/* find object the 2nd time to fill the buffer with data */
697 	if ((rc = object_mgr_get_attribute_values(&dummy_sess, ckKey,
698 	    tmpl, 1))) {
699 		return (rc);
700 	}
701 
702 	*ret_blob = blob;
703 	*blob_size = tmpl[0].ulValueLen;
704 done:
705 	return (rc);
706 }
707 
708 /*
709  * Given a modulus and prime from an RSA key, create a TSS_HKEY object by
710  * wrapping the RSA key with a key from the TPM (SRK or other previously stored
711  * key).
712  */
713 static CK_RV
714 token_wrap_sw_key(
715 	TSS_HCONTEXT hContext,
716 	int size_n,
717 	unsigned char *n,
718 	int size_p,
719 	unsigned char *p,
720 	TSS_HKEY hParentKey,
721 	TSS_FLAG initFlags,
722 	TSS_HKEY *phKey)
723 {
724 	TSS_RESULT result;
725 	TSS_HPOLICY hPolicy;
726 	UINT32 key_size;
727 
728 	key_size = util_get_keysize_flag(size_n * 8);
729 	if (initFlags == 0) {
730 		return (CKR_FUNCTION_FAILED);
731 	}
732 
733 	/* create the TSS key object */
734 	result = Tspi_Context_CreateObject(hContext, TSS_OBJECT_TYPE_RSAKEY,
735 	    TSS_KEY_MIGRATABLE | initFlags | key_size, phKey);
736 	if (result != TSS_SUCCESS) {
737 		stlogit("Tspi_Context_CreateObject: 0x%0x - %s",
738 		    result, Trspi_Error_String(result));
739 		return (CKR_FUNCTION_FAILED);
740 	}
741 
742 	result = set_public_modulus(hContext, *phKey, size_n, n);
743 	if (result != TSS_SUCCESS) {
744 		Tspi_Context_CloseObject(hContext, *phKey);
745 		*phKey = NULL_HKEY;
746 		return (CKR_FUNCTION_FAILED);
747 	}
748 
749 	/* set the private key data in the TSS object */
750 	result = Tspi_SetAttribData(*phKey, TSS_TSPATTRIB_KEY_BLOB,
751 	    TSS_TSPATTRIB_KEYBLOB_PRIVATE_KEY, size_p, p);
752 	if (result != TSS_SUCCESS) {
753 		stlogit("Tspi_SetAttribData: 0x%x - %s",
754 		    result, Trspi_Error_String(result));
755 		Tspi_Context_CloseObject(hContext, *phKey);
756 		*phKey = NULL_HKEY;
757 		return (CKR_FUNCTION_FAILED);
758 	}
759 
760 	result = Tspi_Context_CreateObject(hContext,
761 	    TSS_OBJECT_TYPE_POLICY, TSS_POLICY_MIGRATION, &hPolicy);
762 	if (result != TSS_SUCCESS) {
763 		stlogit("Tspi_Context_CreateObject: 0x%0x - %s",
764 		    result, Trspi_Error_String(result));
765 		Tspi_Context_CloseObject(hContext, *phKey);
766 		*phKey = NULL_HKEY;
767 		return (CKR_FUNCTION_FAILED);
768 	}
769 
770 	result = Tspi_Policy_AssignToObject(hPolicy, *phKey);
771 	if (result != TSS_SUCCESS) {
772 		stlogit("Tspi_Policy_AssignToObject: 0x%0x - %s\n",
773 		    result, Trspi_Error_String(result));
774 		Tspi_Context_CloseObject(hContext, *phKey);
775 		Tspi_Context_CloseObject(hContext, hPolicy);
776 		*phKey = NULL_HKEY;
777 		return (CKR_FUNCTION_FAILED);
778 	}
779 
780 	result = Tspi_Policy_SetSecret(hPolicy, TSS_SECRET_MODE_NONE, 0, NULL);
781 	if (result != TSS_SUCCESS) {
782 		stlogit("Tspi_Policy_SetSecret: 0x%0x - %s\n",
783 		    result, Trspi_Error_String(result));
784 		Tspi_Context_CloseObject(hContext, *phKey);
785 		Tspi_Context_CloseObject(hContext, hPolicy);
786 		*phKey = NULL_HKEY;
787 		return (CKR_FUNCTION_FAILED);
788 	}
789 
790 	if (TPMTOK_TSS_KEY_TYPE(initFlags) == TSS_KEY_TYPE_LEGACY) {
791 		if ((result = Tspi_SetAttribUint32(*phKey,
792 		    TSS_TSPATTRIB_KEY_INFO, TSS_TSPATTRIB_KEYINFO_ENCSCHEME,
793 		    TSS_ES_RSAESPKCSV15))) {
794 			stlogit("Tspi_SetAttribUint32: 0x%0x - %s\n",
795 			    result, Trspi_Error_String(result));
796 			Tspi_Context_CloseObject(hContext, *phKey);
797 			Tspi_Context_CloseObject(hContext, hPolicy);
798 			return (CKR_FUNCTION_FAILED);
799 		}
800 
801 		if ((result = Tspi_SetAttribUint32(*phKey,
802 		    TSS_TSPATTRIB_KEY_INFO, TSS_TSPATTRIB_KEYINFO_SIGSCHEME,
803 		    TSS_SS_RSASSAPKCS1V15_DER))) {
804 			stlogit("Tspi_SetAttribUint32: 0x%0x - %s\n",
805 			    result, Trspi_Error_String(result));
806 			Tspi_Context_CloseObject(hContext, *phKey);
807 			Tspi_Context_CloseObject(hContext, hPolicy);
808 			return (CKR_FUNCTION_FAILED);
809 		}
810 	}
811 
812 	result = Tspi_Key_WrapKey(*phKey, hParentKey, NULL_HPCRS);
813 	if (result != TSS_SUCCESS) {
814 		stlogit("Tspi_Key_WrapKey: 0x%0x - %s",
815 		    result, Trspi_Error_String(result));
816 		Tspi_Context_CloseObject(hContext, *phKey);
817 		*phKey = NULL_HKEY;
818 		return (CKR_FUNCTION_FAILED);
819 	}
820 
821 	return (CKR_OK);
822 }
823 
824 /*
825  * Create a TPM key blob for an imported key. This function is only called when
826  * a key is in active use, so any failure should trickle through.
827  */
828 static CK_RV
829 token_wrap_key_object(TSS_HCONTEXT hContext,
830 	CK_OBJECT_HANDLE ckObject,
831 	TSS_HKEY hParentKey, TSS_HKEY *phKey)
832 {
833 	CK_RV		rc = CKR_OK;
834 	CK_ATTRIBUTE	*attr = NULL, *new_attr, *prime_attr;
835 	CK_ULONG	class, key_type;
836 	OBJECT		*obj;
837 
838 	TSS_RESULT	result;
839 	TSS_FLAG	initFlags = 0;
840 	BYTE		*rgbBlob;
841 	UINT32		ulBlobLen;
842 
843 	if ((rc = object_mgr_find_in_map1(hContext, ckObject, &obj))) {
844 		return (rc);
845 	}
846 
847 	/* if the object isn't a key, fail */
848 	if (template_attribute_find(obj->template, CKA_KEY_TYPE,
849 	    &attr) == FALSE) {
850 		return (CKR_TEMPLATE_INCOMPLETE);
851 	}
852 
853 	key_type = *((CK_ULONG *)attr->pValue);
854 
855 	if (key_type != CKK_RSA) {
856 		return (CKR_TEMPLATE_INCONSISTENT);
857 	}
858 
859 	if (template_attribute_find(obj->template, CKA_CLASS,
860 	    &attr) == FALSE) {
861 		return (CKR_TEMPLATE_INCOMPLETE);
862 	}
863 
864 	class = *((CK_ULONG *)attr->pValue);
865 
866 	if (class == CKO_PRIVATE_KEY) {
867 		/*
868 		 * In order to create a full TSS key blob using a PKCS#11
869 		 * private key object, we need one of the two primes, the
870 		 * modulus and the private exponent and we need the public
871 		 * exponent to be correct.
872 		 */
873 
874 		/*
875 		 * Check the least likely attribute to exist first, the
876 		 * primes.
877 		 */
878 		if (template_attribute_find(obj->template, CKA_PRIME_1,
879 		    &prime_attr) == FALSE) {
880 			if (template_attribute_find(obj->template,
881 			    CKA_PRIME_2, &prime_attr) == FALSE) {
882 				return (CKR_TEMPLATE_INCOMPLETE);
883 			}
884 		}
885 
886 		/* Make sure the public exponent is usable */
887 		if ((rc = util_check_public_exponent(obj->template))) {
888 			return (CKR_TEMPLATE_INCONSISTENT);
889 		}
890 
891 		/* get the modulus */
892 		if (template_attribute_find(obj->template, CKA_MODULUS,
893 		    &attr) == FALSE) {
894 			return (CKR_TEMPLATE_INCOMPLETE);
895 		}
896 
897 		/* make sure the key size is usable */
898 		initFlags = util_get_keysize_flag(attr->ulValueLen * 8);
899 		if (initFlags == 0) {
900 			return (CKR_TEMPLATE_INCONSISTENT);
901 		}
902 
903 		/* generate the software based key */
904 		if ((rc = token_wrap_sw_key(hContext,
905 		    (int)attr->ulValueLen, attr->pValue,
906 		    (int)prime_attr->ulValueLen, prime_attr->pValue,
907 		    hParentKey, TSS_KEY_TYPE_LEGACY | TSS_KEY_NO_AUTHORIZATION,
908 		    phKey))) {
909 			return (rc);
910 		}
911 	} else if (class == CKO_PUBLIC_KEY) {
912 		/* Make sure the public exponent is usable */
913 		if ((util_check_public_exponent(obj->template))) {
914 			return (CKR_TEMPLATE_INCONSISTENT);
915 		}
916 
917 		/* grab the modulus to put into the TSS key object */
918 		if (template_attribute_find(obj->template,
919 		    CKA_MODULUS, &attr) == FALSE) {
920 			return (CKR_TEMPLATE_INCONSISTENT);
921 		}
922 
923 		/* make sure the key size is usable */
924 		initFlags = util_get_keysize_flag(attr->ulValueLen * 8);
925 		if (initFlags == 0) {
926 			return (CKR_TEMPLATE_INCONSISTENT);
927 		}
928 
929 		initFlags |= TSS_KEY_TYPE_LEGACY | TSS_KEY_MIGRATABLE |
930 		    TSS_KEY_NO_AUTHORIZATION;
931 
932 		if ((result = Tspi_Context_CreateObject(hContext,
933 		    TSS_OBJECT_TYPE_RSAKEY, initFlags, phKey))) {
934 			stlogit("Tspi_Context_CreateObject: 0x%0x - %s",
935 			    result, Trspi_Error_String(result));
936 			return (result);
937 		}
938 
939 		if ((result = set_public_modulus(hContext, *phKey,
940 		    attr->ulValueLen, attr->pValue))) {
941 			Tspi_Context_CloseObject(hContext, *phKey);
942 			*phKey = NULL_HKEY;
943 			return (CKR_FUNCTION_FAILED);
944 		}
945 	} else {
946 		return (CKR_FUNCTION_FAILED);
947 	}
948 
949 	/* grab the entire key blob to put into the PKCS#11 object */
950 	if ((result = Tspi_GetAttribData(*phKey, TSS_TSPATTRIB_KEY_BLOB,
951 	    TSS_TSPATTRIB_KEYBLOB_BLOB, &ulBlobLen, &rgbBlob))) {
952 		stlogit("Tspi_GetAttribData: 0x%0x - %s",
953 		    result, Trspi_Error_String(result));
954 		return (CKR_FUNCTION_FAILED);
955 	}
956 
957 	/* insert the key blob into the object */
958 	if ((rc = build_attribute(CKA_IBM_OPAQUE, rgbBlob, ulBlobLen,
959 	    &new_attr))) {
960 		Tspi_Context_FreeMemory(hContext, rgbBlob);
961 		return (rc);
962 	}
963 	(void) template_update_attribute(obj->template, new_attr);
964 	Tspi_Context_FreeMemory(hContext, rgbBlob);
965 
966 	/*
967 	 * If this is a token object, save it with the new attribute
968 	 * so that we don't have to go down this path again.
969 	 */
970 	if (!object_is_session_object(obj)) {
971 		rc = save_token_object(hContext, obj);
972 	}
973 
974 	return (rc);
975 }
976 
977 static TSS_RESULT
978 tss_assign_secret_key_policy(TSS_HCONTEXT hContext, TSS_HKEY hKey,
979     CK_CHAR *passHash)
980 {
981 	TSS_RESULT result;
982 	TSS_HPOLICY hPolicy;
983 
984 	if ((result = Tspi_Context_CreateObject(hContext,
985 	    TSS_OBJECT_TYPE_POLICY, TSS_POLICY_USAGE, &hPolicy))) {
986 		stlogit("Tspi_Context_CreateObject: 0x%0x - %s",
987 		    result, Trspi_Error_String(result));
988 		return (result);
989 	}
990 	if ((result = Tspi_Policy_AssignToObject(hPolicy, hKey))) {
991 		stlogit("Tspi_Policy_AssignToObject: 0x%0x - %s",
992 		    result, Trspi_Error_String(result));
993 		goto done;
994 	}
995 	if (passHash == NULL) {
996 		result = Tspi_Policy_SetSecret(hPolicy, TSS_SECRET_MODE_NONE,
997 		    0, NULL);
998 	} else {
999 		result = Tspi_Policy_SetSecret(hPolicy, TSS_SECRET_MODE_SHA1,
1000 		    SHA1_DIGEST_LENGTH, passHash);
1001 	}
1002 	if (result != TSS_SUCCESS) {
1003 		stlogit("Tspi_Policy_SetSecret: 0x%0x - %s",
1004 		    result, Trspi_Error_String(result));
1005 		goto done;
1006 	}
1007 done:
1008 	if (result != TSS_SUCCESS)
1009 		Tspi_Context_CloseObject(hContext, hPolicy);
1010 	return (result);
1011 }
1012 
1013 /*
1014  * Take a key from the TSS store (on-disk) and load it into the TPM, wrapped
1015  * by an already TPM-resident key and protected with a PIN (optional).
1016  */
1017 static CK_RV
1018 token_load_key(
1019 	TSS_HCONTEXT hContext,
1020 	CK_OBJECT_HANDLE ckKey,
1021 	TSS_HKEY hParentKey,
1022 	CK_CHAR_PTR passHash,
1023 	TSS_HKEY *phKey)
1024 {
1025 	TSS_RESULT result;
1026 	CK_BYTE *blob = NULL;
1027 	CK_ULONG ulBlobSize = 0;
1028 	CK_RV rc;
1029 
1030 	if ((rc = token_get_key_blob(ckKey, &ulBlobSize, &blob))) {
1031 		if (rc != CKR_ATTRIBUTE_TYPE_INVALID) {
1032 			return (rc);
1033 		}
1034 		/*
1035 		 * The key blob wasn't found, load the parts of the key
1036 		 * from the object DB and create a new key object that
1037 		 * gets loaded into the TPM, wrapped with the parent key.
1038 		 */
1039 		if ((rc = token_wrap_key_object(hContext, ckKey,
1040 		    hParentKey, phKey))) {
1041 			return (rc);
1042 		}
1043 	}
1044 
1045 	if (blob != NULL) {
1046 		/* load the key into the TPM, wrapped with parent key */
1047 		if ((result = Tspi_Context_LoadKeyByBlob(hContext,
1048 		    hParentKey, ulBlobSize, blob, phKey))) {
1049 			stlogit("Tspi_Context_LoadKeyByBlob: 0x%x - %s",
1050 			    result, Trspi_Error_String(result));
1051 			goto done;
1052 		}
1053 	}
1054 	/*
1055 	 * Assign the PIN hash (optional) to the newly loaded key object,
1056 	 * if this PIN is incorrect, the TPM will not be able to decrypt
1057 	 * the private key and use it.
1058 	 */
1059 	result = tss_assign_secret_key_policy(hContext, *phKey, passHash);
1060 done:
1061 	free(blob);
1062 	return (result);
1063 }
1064 
1065 /*
1066  * Load the SRK into the TPM by referencing its well-known UUID and using the
1067  * default SRK PIN (20 bytes of 0x00).
1068  *
1069  * NOTE - if the SRK PIN is changed by an administrative tool, this code will
1070  * fail because it assumes that the well-known PIN is still being used.
1071  */
1072 static TSS_RESULT
1073 token_load_srk(TSS_HCONTEXT hContext, TSS_HKEY *hSRK)
1074 {
1075 	TSS_HPOLICY hPolicy;
1076 	TSS_RESULT result;
1077 	TSS_UUID SRK_UUID = TSS_UUID_SRK;
1078 	BYTE wellKnown[] = TSS_WELL_KNOWN_SECRET;
1079 	TSS_HTPM hTPM;
1080 
1081 	if ((result = Tspi_Context_GetTpmObject(hContext, &hTPM))) {
1082 		stlogit("Tspi_Context_GetTpmObject: 0x%0x - %s",
1083 		    result, Trspi_Error_String(result));
1084 		return (CKR_FUNCTION_FAILED);
1085 	}
1086 
1087 	/* load the SRK */
1088 	if ((result = Tspi_Context_LoadKeyByUUID(hContext,
1089 	    TSS_PS_TYPE_SYSTEM, SRK_UUID, hSRK))) {
1090 		stlogit("Tspi_Context_LoadKeyByUUID: 0x%0x - %s",
1091 		    result, Trspi_Error_String(result));
1092 		goto done;
1093 	}
1094 	if ((result = Tspi_GetPolicyObject(*hSRK, TSS_POLICY_USAGE,
1095 	    &hPolicy))) {
1096 		stlogit("Tspi_GetPolicyObject: 0x%0x - %s",
1097 		    result, Trspi_Error_String(result));
1098 		goto done;
1099 	}
1100 	if ((result = Tspi_Policy_SetSecret(hPolicy, TSS_SECRET_MODE_SHA1,
1101 	    sizeof (wellKnown), wellKnown))) {
1102 		stlogit("Tspi_Policy_SetSecret: 0x%0x - %s",
1103 		    result, Trspi_Error_String(result));
1104 		goto done;
1105 	}
1106 
1107 done:
1108 	return (result);
1109 }
1110 
1111 static TSS_RESULT
1112 tss_find_and_load_key(TSS_HCONTEXT hContext,
1113 	char *keyid, TSS_UUID *uuid, TSS_HKEY hParent,
1114 	BYTE *hash, TSS_HKEY *hKey)
1115 {
1116 	TSS_RESULT result;
1117 
1118 	if (local_uuid_is_null(uuid) &&
1119 	    find_uuid(keyid, uuid)) {
1120 		/* The UUID was not created or saved yet */
1121 		return (1);
1122 	}
1123 	result = Tspi_Context_GetKeyByUUID(hContext,
1124 	    TSS_PS_TYPE_USER, *uuid, hKey);
1125 	if (result) {
1126 		stlogit("Tspi_Context_GetKeyByUUID: 0x%0x - %s",
1127 		    result, Trspi_Error_String(result));
1128 		return (result);
1129 	}
1130 
1131 	if (hash != NULL) {
1132 		result = tss_assign_secret_key_policy(hContext, *hKey,
1133 		    (CK_BYTE *)hash);
1134 		if (result)
1135 			return (result);
1136 	}
1137 
1138 	result = Tspi_Key_LoadKey(*hKey, hParent);
1139 	if (result)
1140 		stlogit("Tspi_Key_LoadKey: 0x%0x - %s",
1141 		    result, Trspi_Error_String(result));
1142 
1143 	return (result);
1144 }
1145 
1146 static TSS_RESULT
1147 token_load_public_root_key(TSS_HCONTEXT hContext)
1148 {
1149 	TSS_RESULT result;
1150 	TSS_HKEY hSRK;
1151 
1152 	if (hPublicRootKey != NULL_HKEY)
1153 		return (TSS_SUCCESS);
1154 
1155 	if ((result = token_load_srk(hContext, &hSRK))) {
1156 		return (result);
1157 	}
1158 
1159 	result = tss_find_and_load_key(hContext,
1160 	    TPMTOK_PUBLIC_ROOT_KEY_ID,
1161 	    &publicRootKeyUUID, hSRK, NULL, &hPublicRootKey);
1162 	if (result)
1163 		return (result);
1164 
1165 	return (result);
1166 }
1167 
1168 static TSS_RESULT
1169 tss_generate_key(TSS_HCONTEXT hContext, TSS_FLAG initFlags, BYTE *passHash,
1170 	TSS_HKEY hParentKey, TSS_HKEY *phKey)
1171 {
1172 	TSS_RESULT	result;
1173 	TSS_HPOLICY	hMigPolicy;
1174 
1175 	if ((result = Tspi_Context_CreateObject(hContext,
1176 	    TSS_OBJECT_TYPE_RSAKEY, initFlags, phKey))) {
1177 		stlogit("Tspi_Context_CreateObject: 0x%0x - %s",
1178 		    result, Trspi_Error_String(result));
1179 		return (result);
1180 	}
1181 	result = tss_assign_secret_key_policy(hContext, *phKey, passHash);
1182 
1183 	if (result) {
1184 		Tspi_Context_CloseObject(hContext, *phKey);
1185 		return (result);
1186 	}
1187 
1188 	if (TPMTOK_TSS_KEY_MIG_TYPE(initFlags) == TSS_KEY_MIGRATABLE) {
1189 		if ((result = Tspi_Context_CreateObject(hContext,
1190 		    TSS_OBJECT_TYPE_POLICY, TSS_POLICY_MIGRATION,
1191 		    &hMigPolicy))) {
1192 			stlogit("Tspi_Context_CreateObject: 0x%0x - %s",
1193 			    result, Trspi_Error_String(result));
1194 			Tspi_Context_CloseObject(hContext, *phKey);
1195 			return (result);
1196 		}
1197 
1198 		if (passHash == NULL) {
1199 			result = Tspi_Policy_SetSecret(hMigPolicy,
1200 			    TSS_SECRET_MODE_NONE, 0, NULL);
1201 		} else {
1202 			result = Tspi_Policy_SetSecret(hMigPolicy,
1203 			    TSS_SECRET_MODE_SHA1, 20, passHash);
1204 		}
1205 
1206 		if (result != TSS_SUCCESS) {
1207 			stlogit("Tspi_Policy_SetSecret: 0x%0x - %s",
1208 			    result, Trspi_Error_String(result));
1209 			Tspi_Context_CloseObject(hContext, *phKey);
1210 			Tspi_Context_CloseObject(hContext, hMigPolicy);
1211 			return (result);
1212 		}
1213 
1214 		if ((result = Tspi_Policy_AssignToObject(hMigPolicy, *phKey))) {
1215 			stlogit("Tspi_Policy_AssignToObject: 0x%0x - %s",
1216 			    result, Trspi_Error_String(result));
1217 			Tspi_Context_CloseObject(hContext, *phKey);
1218 			Tspi_Context_CloseObject(hContext, hMigPolicy);
1219 			return (result);
1220 		}
1221 	}
1222 
1223 	if (TPMTOK_TSS_KEY_TYPE(initFlags) == TSS_KEY_TYPE_LEGACY) {
1224 		if ((result = Tspi_SetAttribUint32(*phKey,
1225 		    TSS_TSPATTRIB_KEY_INFO,
1226 		    TSS_TSPATTRIB_KEYINFO_ENCSCHEME,
1227 		    TSS_ES_RSAESPKCSV15))) {
1228 			stlogit("Tspi_SetAttribUint32: 0x%0x - %s",
1229 			    result, Trspi_Error_String(result));
1230 			Tspi_Context_CloseObject(hContext, *phKey);
1231 			Tspi_Context_CloseObject(hContext, hMigPolicy);
1232 			return (result);
1233 		}
1234 
1235 		if ((result = Tspi_SetAttribUint32(*phKey,
1236 		    TSS_TSPATTRIB_KEY_INFO,
1237 		    TSS_TSPATTRIB_KEYINFO_SIGSCHEME,
1238 		    TSS_SS_RSASSAPKCS1V15_DER))) {
1239 			stlogit("Tspi_SetAttribUint32: 0x%0x - %s",
1240 			    result, Trspi_Error_String(result));
1241 			Tspi_Context_CloseObject(hContext, *phKey);
1242 			Tspi_Context_CloseObject(hContext, hMigPolicy);
1243 			return (result);
1244 		}
1245 	}
1246 
1247 	if ((result = Tspi_Key_CreateKey(*phKey, hParentKey, 0))) {
1248 		stlogit("Tspi_Key_CreateKey: 0x%0x - %s",
1249 		    result, Trspi_Error_String(result));
1250 		Tspi_Context_CloseObject(hContext, *phKey);
1251 		Tspi_Context_CloseObject(hContext, hMigPolicy);
1252 	}
1253 
1254 	return (result);
1255 }
1256 
1257 static TSS_RESULT
1258 tss_change_auth(
1259 	TSS_HCONTEXT hContext,
1260 	TSS_HKEY hObjectToChange, TSS_HKEY hParentObject,
1261 	TSS_UUID objUUID, TSS_UUID parentUUID,
1262 	CK_CHAR *passHash)
1263 {
1264 	TSS_RESULT result;
1265 	TSS_HPOLICY hPolicy;
1266 	TSS_HKEY oldkey;
1267 
1268 	if ((result = Tspi_Context_CreateObject(hContext,
1269 	    TSS_OBJECT_TYPE_POLICY, TSS_POLICY_USAGE, &hPolicy))) {
1270 		stlogit("Tspi_Context_CreateObject: 0x%0x - %s",
1271 		    result, Trspi_Error_String(result));
1272 		return (result);
1273 	}
1274 
1275 	if ((result = Tspi_Policy_SetSecret(hPolicy, TSS_SECRET_MODE_SHA1,
1276 	    SHA1_DIGEST_LENGTH, passHash))) {
1277 		stlogit("Tspi_Policy_SetSecret: 0x%0x - %s",
1278 		    result, Trspi_Error_String(result));
1279 		return (result);
1280 	}
1281 
1282 	if ((result = Tspi_ChangeAuth(hObjectToChange, hParentObject,
1283 	    hPolicy))) {
1284 		stlogit("Tspi_ChangeAuth: 0x%0x - %s",
1285 		    result, Trspi_Error_String(result));
1286 	}
1287 	/*
1288 	 * Update the PS key by unregistering the key UUID and then
1289 	 * re-registering with the same UUID.  This forces the updated
1290 	 * auth data associated with the key to be stored in PS so
1291 	 * the new PIN can be used next time.
1292 	 */
1293 	if ((result = Tspi_Context_UnregisterKey(hContext,
1294 	    TSS_PS_TYPE_USER, objUUID, &oldkey)))
1295 		stlogit("Tspi_Context_UnregisterKey: 0x%0x - %s",
1296 		    result, Trspi_Error_String(result));
1297 
1298 	if ((result = Tspi_Context_RegisterKey(hContext, hObjectToChange,
1299 	    TSS_PS_TYPE_USER, objUUID, TSS_PS_TYPE_USER, parentUUID)))
1300 		stlogit("Tspi_Context_RegisterKey: 0x%0x - %s",
1301 		    result, Trspi_Error_String(result));
1302 
1303 	return (result);
1304 }
1305 
1306 static CK_RV
1307 token_generate_leaf_key(TSS_HCONTEXT hContext,
1308 	int key_type, CK_CHAR_PTR passHash, TSS_HKEY *phKey)
1309 {
1310 	CK_RV		rc = CKR_FUNCTION_FAILED;
1311 	TSS_RESULT	result;
1312 	TSS_HKEY	hParentKey;
1313 	TSS_UUID	newuuid, parentUUID;
1314 	char		*keyid;
1315 	TSS_FLAG	initFlags = TSS_KEY_MIGRATABLE |
1316 	    TSS_KEY_TYPE_BIND | TSS_KEY_SIZE_2048  | TSS_KEY_AUTHORIZATION;
1317 
1318 	switch (key_type) {
1319 		case TPMTOK_PUBLIC_LEAF_KEY:
1320 			hParentKey = hPublicRootKey;
1321 			keyid = TPMTOK_PUBLIC_LEAF_KEY_ID;
1322 			local_uuid_copy(&parentUUID, &publicRootKeyUUID);
1323 			break;
1324 		case TPMTOK_PRIVATE_LEAF_KEY:
1325 			hParentKey = hPrivateRootKey;
1326 			keyid = TPMTOK_PRIVATE_LEAF_KEY_ID;
1327 			local_uuid_copy(&parentUUID, &privateRootKeyUUID);
1328 			break;
1329 		default:
1330 			stlogit("Unknown key type 0x%0x", key_type);
1331 			goto done;
1332 			break;
1333 	}
1334 
1335 	if (result = tss_generate_key(hContext, initFlags, passHash,
1336 	    hParentKey, phKey)) {
1337 		return (rc);
1338 	}
1339 
1340 	/*
1341 	 * - generate newUUID
1342 	 * - Tspi_Context_RegisterKey(hContext, hPrivateRootKey,
1343 	 *   USER, newUUID, USER, parentUUID);
1344 	 * - store newUUID
1345 	 */
1346 	(void) local_uuid_generate(&newuuid);
1347 
1348 	result = Tspi_Context_RegisterKey(hContext, *phKey,
1349 	    TSS_PS_TYPE_USER, newuuid,
1350 	    TSS_PS_TYPE_USER, parentUUID);
1351 	if (result == TSS_SUCCESS) {
1352 		int ret;
1353 		/*
1354 		 * Add the UUID to the token UUID index.
1355 		 */
1356 		ret = add_uuid(keyid, &newuuid);
1357 
1358 		if (ret)
1359 			result = Tspi_Context_UnregisterKey(hContext,
1360 			    TSS_PS_TYPE_USER, newuuid, phKey);
1361 		else
1362 			rc = CKR_OK;
1363 	}
1364 
1365 done:
1366 	return (rc);
1367 }
1368 
1369 /*
1370  * PINs are verified by attempting to bind/unbind random data using a
1371  * TPM resident key that has the PIN being tested assigned as its "secret".
1372  * If the PIN is incorrect, the unbind operation will fail.
1373  */
1374 static CK_RV
1375 token_verify_pin(TSS_HCONTEXT hContext, TSS_HKEY hKey)
1376 {
1377 	TSS_HENCDATA hEncData;
1378 	UINT32 ulUnboundDataLen;
1379 	BYTE *rgbUnboundData = NULL;
1380 	BYTE rgbData[16];
1381 	TSS_RESULT result;
1382 	CK_RV rc = CKR_FUNCTION_FAILED;
1383 
1384 	if ((result = Tspi_Context_CreateObject(hContext,
1385 	    TSS_OBJECT_TYPE_ENCDATA, TSS_ENCDATA_BIND, &hEncData))) {
1386 		stlogit("Tspi_Context_CreateObject: 0x%0x - %s",
1387 		    result, Trspi_Error_String(result));
1388 		goto done;
1389 	}
1390 
1391 	/* Use some random data */
1392 	rc = token_rng(hContext, rgbData, sizeof (rgbData));
1393 	if (rc)
1394 		goto done;
1395 
1396 	if ((result = Tspi_Data_Bind(hEncData, hKey,
1397 	    sizeof (rgbData), rgbData))) {
1398 		stlogit("Tspi_Data_Bind: 0x%0x - %s",
1399 		    result, Trspi_Error_String(result));
1400 		goto done;
1401 	}
1402 
1403 	/* unbind the junk data to test the key's auth data */
1404 	result = Tspi_Data_Unbind(hEncData, hKey, &ulUnboundDataLen,
1405 	    &rgbUnboundData);
1406 	if (result == TSS_E_TSP_AUTHFAIL) {
1407 		rc = CKR_PIN_INCORRECT;
1408 		stlogit("Tspi_Data_Unbind: 0x%0x - %s",
1409 		    result, Trspi_Error_String(result));
1410 		goto done;
1411 	} else if (result != TSS_SUCCESS) {
1412 		stlogit("Tspi_Data_Unbind: 0x%0x - %s",
1413 		    result, Trspi_Error_String(result));
1414 		rc = CKR_FUNCTION_FAILED;
1415 		goto done;
1416 	}
1417 
1418 	if (memcmp(rgbUnboundData, rgbData, ulUnboundDataLen))
1419 		rc = CKR_PIN_INCORRECT;
1420 	else
1421 		rc = CKR_OK;
1422 
1423 done:
1424 	if (rgbUnboundData != NULL)
1425 		Tspi_Context_FreeMemory(hContext, rgbUnboundData);
1426 	Tspi_Context_CloseObject(hContext, hEncData);
1427 	return (rc);
1428 }
1429 
1430 static CK_RV
1431 token_create_private_tree(TSS_HCONTEXT hContext, CK_BYTE *pinHash)
1432 {
1433 	CK_RV		rc;
1434 	TSS_RESULT	result;
1435 	int		ret;
1436 	TSS_FLAG initFlags = TSS_KEY_SIZE_2048 |
1437 	    TSS_KEY_NO_AUTHORIZATION | TSS_KEY_TYPE_STORAGE;
1438 	TSS_UUID SRK_UUID = TSS_UUID_SRK;
1439 	TSS_HKEY hSRK;
1440 
1441 	if (token_load_srk(hContext, &hSRK))
1442 		return (CKR_FUNCTION_FAILED);
1443 
1444 	/*
1445 	 * - create UUID privateRootKeyUUID
1446 	 * - Tspi_Context_RegisterKey(hContext, hPrivateRootKey,
1447 	 *   USER, privateRootKeyUUID, system, UUID_SRK);
1448 	 * - store privateRootKeyUUID in users private token space.
1449 	 */
1450 	if ((result = tss_generate_key(hContext, initFlags, NULL, hSRK,
1451 	    &hPrivateRootKey))) {
1452 		return (result);
1453 	}
1454 	if (local_uuid_is_null(&privateRootKeyUUID))
1455 		local_uuid_generate(&privateRootKeyUUID);
1456 
1457 	result = Tspi_Context_RegisterKey(hContext, hPrivateRootKey,
1458 	    TSS_PS_TYPE_USER, privateRootKeyUUID,
1459 	    TSS_PS_TYPE_SYSTEM, SRK_UUID);
1460 
1461 	if (result) {
1462 		local_uuid_clear(&privateRootKeyUUID);
1463 		return (result);
1464 	}
1465 
1466 	ret = add_uuid(TPMTOK_PRIVATE_ROOT_KEY_ID, &privateRootKeyUUID);
1467 	if (ret) {
1468 		result = Tspi_Context_UnregisterKey(hContext,
1469 		    TSS_PS_TYPE_USER, privateRootKeyUUID,
1470 		    &hPrivateRootKey);
1471 		return (CKR_FUNCTION_FAILED);
1472 	}
1473 
1474 	if ((result = Tspi_Key_LoadKey(hPrivateRootKey, hSRK))) {
1475 		stlogit("Tspi_Key_LoadKey: 0x%0x - %s",
1476 		    result, Trspi_Error_String(result));
1477 		Tspi_Context_CloseObject(hContext, hPrivateRootKey);
1478 
1479 		(void) remove_uuid(TPMTOK_PRIVATE_ROOT_KEY_ID);
1480 		local_uuid_clear(&privateRootKeyUUID);
1481 
1482 		hPrivateRootKey = NULL_HKEY;
1483 		return (CKR_FUNCTION_FAILED);
1484 	}
1485 
1486 
1487 	/* generate the private leaf key */
1488 	if ((rc = token_generate_leaf_key(hContext,
1489 	    TPMTOK_PRIVATE_LEAF_KEY,
1490 	    pinHash, &hPrivateLeafKey))) {
1491 		return (rc);
1492 	}
1493 
1494 	if ((result = Tspi_Key_LoadKey(hPrivateLeafKey, hPrivateRootKey))) {
1495 		stlogit("Tspi_Key_LoadKey: 0x%0x - %s",
1496 		    result, Trspi_Error_String(result));
1497 
1498 		(void) Tspi_Context_UnregisterKey(hContext,
1499 		    TSS_PS_TYPE_USER, privateLeafKeyUUID,
1500 		    &hPrivateLeafKey);
1501 		(void) remove_uuid(TPMTOK_PRIVATE_LEAF_KEY_ID);
1502 		local_uuid_clear(&privateLeafKeyUUID);
1503 
1504 		(void) Tspi_Context_UnregisterKey(hContext,
1505 		    TSS_PS_TYPE_USER, privateRootKeyUUID,
1506 		    &hPrivateRootKey);
1507 		(void) remove_uuid(TPMTOK_PRIVATE_ROOT_KEY_ID);
1508 		local_uuid_clear(&privateRootKeyUUID);
1509 
1510 		Tspi_Context_CloseObject(hContext, hPrivateRootKey);
1511 		hPrivateRootKey = NULL_HKEY;
1512 
1513 		Tspi_Context_CloseObject(hContext, hPrivateLeafKey);
1514 		hPrivateRootKey = NULL_HKEY;
1515 
1516 		return (CKR_FUNCTION_FAILED);
1517 	}
1518 	return (rc);
1519 }
1520 
1521 static CK_RV
1522 token_create_public_tree(TSS_HCONTEXT hContext, CK_BYTE *pinHash)
1523 {
1524 	CK_RV		rc;
1525 	TSS_RESULT	result;
1526 	int		ret;
1527 	TSS_FLAG initFlags = TSS_KEY_SIZE_2048 |
1528 	    TSS_KEY_NO_AUTHORIZATION | TSS_KEY_TYPE_STORAGE;
1529 	TSS_UUID srk_uuid = TSS_UUID_SRK;
1530 	TSS_HKEY hSRK;
1531 
1532 	if (token_load_srk(hContext, &hSRK))
1533 		return (CKR_FUNCTION_FAILED);
1534 
1535 	/*
1536 	 * - create publicRootKeyUUID
1537 	 * - Tspi_Context_RegisterKey(hContext, hPublicRootKey,
1538 	 *   USER, publicRootKeyUUID, system, UUID_SRK);
1539 	 * - store publicRootKeyUUID in users private token space.
1540 	 */
1541 	if ((result = tss_generate_key(hContext, initFlags, NULL, hSRK,
1542 	    &hPublicRootKey))) {
1543 		return (CKR_FUNCTION_FAILED);
1544 	}
1545 	if (local_uuid_is_null(&publicRootKeyUUID))
1546 		local_uuid_generate(&publicRootKeyUUID);
1547 
1548 	result = Tspi_Context_RegisterKey(hContext, hPublicRootKey,
1549 	    TSS_PS_TYPE_USER, publicRootKeyUUID,
1550 	    TSS_PS_TYPE_SYSTEM, srk_uuid);
1551 
1552 	if (result) {
1553 		local_uuid_clear(&publicRootKeyUUID);
1554 		return (CKR_FUNCTION_FAILED);
1555 	}
1556 
1557 	ret = add_uuid(TPMTOK_PUBLIC_ROOT_KEY_ID, &publicRootKeyUUID);
1558 	if (ret) {
1559 		result = Tspi_Context_UnregisterKey(hContext,
1560 		    TSS_PS_TYPE_USER, publicRootKeyUUID,
1561 		    &hPublicRootKey);
1562 		/* does result matter here? */
1563 		return (CKR_FUNCTION_FAILED);
1564 	}
1565 
1566 	/* Load the newly created publicRootKey into the TPM using the SRK */
1567 	if ((result = Tspi_Key_LoadKey(hPublicRootKey, hSRK))) {
1568 		stlogit("Tspi_Key_LoadKey: 0x%x - %s", result,
1569 		    Trspi_Error_String(result));
1570 		Tspi_Context_CloseObject(hContext, hPublicRootKey);
1571 		hPublicRootKey = NULL_HKEY;
1572 		return (CKR_FUNCTION_FAILED);
1573 	}
1574 
1575 	/* create the SO's leaf key */
1576 	if ((rc = token_generate_leaf_key(hContext, TPMTOK_PUBLIC_LEAF_KEY,
1577 	    pinHash, &hPublicLeafKey))) {
1578 		return (rc);
1579 	}
1580 
1581 	if ((result = Tspi_Key_LoadKey(hPublicLeafKey, hPublicRootKey))) {
1582 		stlogit("Tspi_Key_LoadKey: 0x%0x - %s",
1583 		    result, Trspi_Error_String(result));
1584 
1585 		/* Unregister keys and clear UUIDs */
1586 		(void) Tspi_Context_UnregisterKey(hContext,
1587 		    TSS_PS_TYPE_USER, publicLeafKeyUUID,
1588 		    &hPublicLeafKey);
1589 		(void) remove_uuid(TPMTOK_PUBLIC_LEAF_KEY_ID);
1590 
1591 		(void) Tspi_Context_UnregisterKey(hContext,
1592 		    TSS_PS_TYPE_USER, publicRootKeyUUID,
1593 		    &hPublicRootKey);
1594 		(void) remove_uuid(TPMTOK_PUBLIC_ROOT_KEY_ID);
1595 
1596 		Tspi_Context_CloseObject(hContext, hPublicRootKey);
1597 		hPublicRootKey = NULL_HKEY;
1598 
1599 		Tspi_Context_CloseObject(hContext, hPublicLeafKey);
1600 		hPublicLeafKey = NULL_HKEY;
1601 
1602 		return (CKR_FUNCTION_FAILED);
1603 	}
1604 
1605 	return (rc);
1606 }
1607 
1608 CK_RV
1609 token_specific_login(
1610 	TSS_HCONTEXT hContext,
1611 	CK_USER_TYPE userType,
1612 	CK_CHAR_PTR pPin,
1613 	CK_ULONG ulPinLen)
1614 {
1615 	CK_RV rc;
1616 	CK_BYTE hash_sha[SHA1_DIGEST_LENGTH];
1617 	TSS_RESULT result;
1618 	TSS_HKEY hSRK;
1619 
1620 	/* Make sure the SRK is loaded into the TPM */
1621 	if ((result = token_load_srk(hContext, &hSRK))) {
1622 		return (CKR_FUNCTION_FAILED);
1623 	}
1624 
1625 	if ((rc = compute_sha(pPin, ulPinLen, hash_sha))) {
1626 		return (CKR_FUNCTION_FAILED);
1627 	}
1628 
1629 	if (userType == CKU_USER) {
1630 		/*
1631 		 * If the public root key doesn't exist yet,
1632 		 * the SO hasn't init'd the token.
1633 		 */
1634 		if ((result = token_load_public_root_key(hContext))) {
1635 			if (result == TPM_E_DECRYPT_ERROR) {
1636 				return (CKR_USER_PIN_NOT_INITIALIZED);
1637 			}
1638 		}
1639 
1640 		/*
1641 		 * - find privateRootKeyUUID
1642 		 * - load by UUID (SRK parent)
1643 		 */
1644 		if (local_uuid_is_null(&privateRootKeyUUID) &&
1645 		    find_uuid(TPMTOK_PRIVATE_ROOT_KEY_ID,
1646 		    &privateRootKeyUUID)) {
1647 				if (memcmp(hash_sha,
1648 				    default_user_pin_sha,
1649 				    SHA1_DIGEST_LENGTH))
1650 					return (CKR_PIN_INCORRECT);
1651 
1652 				not_initialized = 1;
1653 				return (CKR_OK);
1654 		}
1655 
1656 		if ((rc = verify_user_pin(hContext, hash_sha))) {
1657 			return (rc);
1658 		}
1659 
1660 		(void) memcpy(current_user_pin_sha, hash_sha,
1661 		    SHA1_DIGEST_LENGTH);
1662 
1663 		rc = load_private_token_objects(hContext);
1664 		if (rc == CKR_OK) {
1665 			(void) XProcLock(xproclock);
1666 			global_shm->priv_loaded = TRUE;
1667 			(void) XProcUnLock(xproclock);
1668 		}
1669 	} else {
1670 		/*
1671 		 * SO login logic:
1672 		 *
1673 		 * - find publicRootKey UUID
1674 		 * - load by UUID wrap with hSRK from above
1675 		 */
1676 		if (local_uuid_is_null(&publicRootKeyUUID) &&
1677 		    find_uuid(TPMTOK_PUBLIC_ROOT_KEY_ID,
1678 		    &publicRootKeyUUID)) {
1679 				if (memcmp(hash_sha,
1680 				    default_so_pin_sha,
1681 				    SHA1_DIGEST_LENGTH))
1682 					return (CKR_PIN_INCORRECT);
1683 
1684 				not_initialized = 1;
1685 				return (CKR_OK);
1686 
1687 		}
1688 		if (hPublicRootKey == NULL_HKEY) {
1689 			result = tss_find_and_load_key(
1690 			    hContext,
1691 			    TPMTOK_PUBLIC_ROOT_KEY_ID,
1692 			    &publicRootKeyUUID, hSRK, NULL,
1693 			    &hPublicRootKey);
1694 
1695 			if (result)
1696 				return (CKR_FUNCTION_FAILED);
1697 		}
1698 
1699 		/* find, load the public leaf key */
1700 		if (hPublicLeafKey == NULL_HKEY) {
1701 			result = tss_find_and_load_key(
1702 			    hContext,
1703 			    TPMTOK_PUBLIC_LEAF_KEY_ID,
1704 			    &publicLeafKeyUUID, hPublicRootKey, hash_sha,
1705 			    &hPublicLeafKey);
1706 			if (result)
1707 				return (CKR_FUNCTION_FAILED);
1708 		}
1709 
1710 		if ((rc = token_verify_pin(hContext, hPublicLeafKey))) {
1711 			return (rc);
1712 		}
1713 
1714 		(void) memcpy(current_so_pin_sha, hash_sha, SHA1_DIGEST_LENGTH);
1715 	}
1716 
1717 	return (rc);
1718 }
1719 
1720 CK_RV
1721 token_specific_logout(TSS_HCONTEXT hContext)
1722 {
1723 	if (hPrivateLeafKey != NULL_HKEY) {
1724 		Tspi_Key_UnloadKey(hPrivateLeafKey);
1725 		hPrivateLeafKey = NULL_HKEY;
1726 	} else if (hPublicLeafKey != NULL_HKEY) {
1727 		Tspi_Key_UnloadKey(hPublicLeafKey);
1728 		hPublicLeafKey = NULL_HKEY;
1729 	}
1730 
1731 	local_uuid_clear(&publicRootKeyUUID);
1732 	local_uuid_clear(&publicLeafKeyUUID);
1733 	local_uuid_clear(&privateRootKeyUUID);
1734 	local_uuid_clear(&privateLeafKeyUUID);
1735 
1736 	(void) memset(current_so_pin_sha, 0, SHA1_DIGEST_LENGTH);
1737 	(void) memset(current_user_pin_sha, 0, SHA1_DIGEST_LENGTH);
1738 
1739 	(void) object_mgr_purge_private_token_objects(hContext);
1740 
1741 	return (CKR_OK);
1742 }
1743 
1744 /*ARGSUSED*/
1745 CK_RV
1746 token_specific_init_pin(TSS_HCONTEXT hContext,
1747 	CK_CHAR_PTR pPin, CK_ULONG ulPinLen)
1748 {
1749 	/*
1750 	 * Since the SO must log in before calling C_InitPIN, we will
1751 	 * be able to return (CKR_OK) automatically here.
1752 	 * This is because the USER key structure is created at the
1753 	 * time of her first login, not at C_InitPIN time.
1754 	 */
1755 	return (CKR_OK);
1756 }
1757 
1758 static CK_RV
1759 check_pin_properties(CK_USER_TYPE userType, CK_BYTE *pinHash,
1760 	CK_ULONG ulPinLen)
1761 {
1762 	/* make sure the new PIN is different */
1763 	if (userType == CKU_USER) {
1764 		if (!memcmp(pinHash, default_user_pin_sha,
1765 		    SHA1_DIGEST_LENGTH)) {
1766 			LogError1("new PIN must not be the default");
1767 			return (CKR_PIN_INVALID);
1768 		}
1769 	} else {
1770 		if (!memcmp(pinHash, default_so_pin_sha,
1771 		    SHA1_DIGEST_LENGTH)) {
1772 			LogError1("new PIN must not be the default");
1773 			return (CKR_PIN_INVALID);
1774 		}
1775 	}
1776 
1777 	if (ulPinLen > MAX_PIN_LEN || ulPinLen < MIN_PIN_LEN) {
1778 		LogError1("New PIN is out of size range");
1779 		return (CKR_PIN_LEN_RANGE);
1780 	}
1781 
1782 	return (CKR_OK);
1783 }
1784 
1785 /*
1786  * This function is called from set_pin only, where a non-logged-in public
1787  * session can provide the user pin which must be verified. This function
1788  * assumes that the pin has already been set once, so there's no migration
1789  * path option or checking of the default user pin.
1790  */
1791 static CK_RV
1792 verify_user_pin(TSS_HCONTEXT hContext, CK_BYTE *hash_sha)
1793 {
1794 	CK_RV rc;
1795 	TSS_RESULT result;
1796 	TSS_HKEY hSRK;
1797 
1798 	if (token_load_srk(hContext, &hSRK))
1799 		return (CKR_FUNCTION_FAILED);
1800 
1801 	/*
1802 	 * Verify the user by loading the privateLeafKey
1803 	 * into the TPM (if it's not already) and then
1804 	 * call the verify_pin operation.
1805 	 *
1806 	 * The hashed PIN is assigned to the private leaf key.
1807 	 * If it is incorrect (not the same as the one originally
1808 	 * used when the key was created), the verify operation
1809 	 * will fail.
1810 	 */
1811 	if (hPrivateRootKey == NULL_HKEY) {
1812 		result = tss_find_and_load_key(
1813 		    hContext,
1814 		    TPMTOK_PRIVATE_ROOT_KEY_ID,
1815 		    &privateRootKeyUUID, hSRK, NULL, &hPrivateRootKey);
1816 		if (result)
1817 			return (CKR_FUNCTION_FAILED);
1818 	}
1819 
1820 	if (hPrivateLeafKey == NULL_HKEY) {
1821 		result = tss_find_and_load_key(
1822 		    hContext,
1823 		    TPMTOK_PRIVATE_LEAF_KEY_ID,
1824 		    &privateLeafKeyUUID, hPrivateRootKey, hash_sha,
1825 		    &hPrivateLeafKey);
1826 
1827 		if (result)
1828 			return (CKR_FUNCTION_FAILED);
1829 	}
1830 
1831 	/*
1832 	 * Verify that the PIN is correct by attempting to wrap/unwrap some
1833 	 * random data.
1834 	 */
1835 	if ((rc = token_verify_pin(hContext, hPrivateLeafKey))) {
1836 		return (rc);
1837 	}
1838 
1839 	return (CKR_OK);
1840 }
1841 
1842 CK_RV
1843 token_specific_set_pin(ST_SESSION_HANDLE session,
1844 	CK_CHAR_PTR pOldPin, CK_ULONG ulOldPinLen,
1845 	CK_CHAR_PTR pNewPin, CK_ULONG ulNewPinLen)
1846 {
1847 	SESSION		*sess = session_mgr_find(session.sessionh);
1848 	CK_BYTE		oldpin_hash[SHA1_DIGEST_LENGTH];
1849 	CK_BYTE		newpin_hash[SHA1_DIGEST_LENGTH];
1850 	CK_RV		rc;
1851 	TSS_HKEY	hSRK;
1852 
1853 	if (!sess) {
1854 		return (CKR_SESSION_HANDLE_INVALID);
1855 	}
1856 
1857 	if ((rc = compute_sha(pOldPin, ulOldPinLen, oldpin_hash))) {
1858 		return (CKR_FUNCTION_FAILED);
1859 	}
1860 	if ((rc = compute_sha(pNewPin, ulNewPinLen, newpin_hash))) {
1861 		return (CKR_FUNCTION_FAILED);
1862 	}
1863 
1864 	if (token_load_srk(sess->hContext, &hSRK)) {
1865 		return (CKR_FUNCTION_FAILED);
1866 	}
1867 
1868 	/*
1869 	 * From the PKCS#11 2.20 spec: "C_SetPIN modifies the PIN of
1870 	 * the user that is currently logged in, or the CKU_USER PIN
1871 	 * if the session is not logged in."
1872 	 * A non R/W session fails with CKR_SESSION_READ_ONLY.
1873 	 */
1874 	if (sess->session_info.state == CKS_RW_USER_FUNCTIONS ||
1875 	    sess->session_info.state == CKS_RW_PUBLIC_SESSION) {
1876 		if (not_initialized) {
1877 			if (memcmp(oldpin_hash, default_user_pin_sha,
1878 			    SHA1_DIGEST_LENGTH)) {
1879 				return (CKR_PIN_INCORRECT);
1880 			}
1881 
1882 			if ((rc = check_pin_properties(CKU_USER, newpin_hash,
1883 			    ulNewPinLen))) {
1884 				return (rc);
1885 			}
1886 
1887 			if ((rc = token_create_private_tree(sess->hContext,
1888 			    newpin_hash))) {
1889 				return (CKR_FUNCTION_FAILED);
1890 			}
1891 
1892 			nv_token_data->token_info.flags &=
1893 			    ~(CKF_USER_PIN_TO_BE_CHANGED);
1894 			nv_token_data->token_info.flags |=
1895 			    CKF_USER_PIN_INITIALIZED;
1896 
1897 			nv_token_data->token_info.flags &=
1898 			    ~(CKF_USER_PIN_TO_BE_CHANGED);
1899 			nv_token_data->token_info.flags |=
1900 			    CKF_USER_PIN_INITIALIZED;
1901 
1902 			return (save_token_data(nv_token_data));
1903 		}
1904 
1905 		if (sess->session_info.state == CKS_RW_USER_FUNCTIONS) {
1906 			/* if we're already logged in, just verify the hash */
1907 			if (memcmp(current_user_pin_sha, oldpin_hash,
1908 			    SHA1_DIGEST_LENGTH)) {
1909 				return (CKR_PIN_INCORRECT);
1910 			}
1911 		} else {
1912 			if ((rc = verify_user_pin(sess->hContext,
1913 			    oldpin_hash))) {
1914 				return (rc);
1915 			}
1916 		}
1917 
1918 		if ((rc = check_pin_properties(CKU_USER, newpin_hash,
1919 		    ulNewPinLen)))
1920 			return (rc);
1921 
1922 		/* change the auth on the TSS object */
1923 		if (tss_change_auth(sess->hContext,
1924 		    hPrivateLeafKey, hPrivateRootKey,
1925 		    privateLeafKeyUUID, privateRootKeyUUID,
1926 		    newpin_hash))
1927 			return (CKR_FUNCTION_FAILED);
1928 
1929 	} else if (sess->session_info.state == CKS_RW_SO_FUNCTIONS) {
1930 		if (not_initialized) {
1931 			if (memcmp(default_so_pin_sha, oldpin_hash,
1932 			    SHA1_DIGEST_LENGTH))
1933 				return (CKR_PIN_INCORRECT);
1934 
1935 			if ((rc = check_pin_properties(CKU_SO,
1936 			    newpin_hash, ulNewPinLen)))
1937 				return (rc);
1938 
1939 			if ((rc = token_create_public_tree(sess->hContext,
1940 			    newpin_hash)))
1941 				return (CKR_FUNCTION_FAILED);
1942 
1943 			nv_token_data->token_info.flags &=
1944 			    ~(CKF_SO_PIN_TO_BE_CHANGED);
1945 
1946 			return (save_token_data(nv_token_data));
1947 		}
1948 
1949 		if (memcmp(current_so_pin_sha, oldpin_hash,
1950 		    SHA1_DIGEST_LENGTH))
1951 			return (CKR_PIN_INCORRECT);
1952 
1953 		if ((rc = check_pin_properties(CKU_SO, newpin_hash,
1954 		    ulNewPinLen)))
1955 			return (rc);
1956 
1957 		/* change auth on the SO's leaf key */
1958 		if (tss_change_auth(sess->hContext,
1959 		    hPublicLeafKey, hPublicRootKey,
1960 		    publicLeafKeyUUID, publicRootKeyUUID,
1961 		    newpin_hash))
1962 			return (CKR_FUNCTION_FAILED);
1963 
1964 	} else {
1965 		rc = CKR_SESSION_READ_ONLY;
1966 	}
1967 
1968 	return (rc);
1969 }
1970 
1971 /* only called at token init time */
1972 CK_RV
1973 token_specific_verify_so_pin(TSS_HCONTEXT hContext, CK_CHAR_PTR pPin,
1974     CK_ULONG ulPinLen)
1975 {
1976 	CK_BYTE hash_sha[SHA1_DIGEST_LENGTH];
1977 	CK_RV rc;
1978 	TSS_RESULT result;
1979 	TSS_HKEY hSRK;
1980 
1981 	if ((rc = compute_sha(pPin, ulPinLen, hash_sha))) {
1982 		return (CKR_FUNCTION_FAILED);
1983 	}
1984 	if ((rc = token_load_srk(hContext, &hSRK))) {
1985 		return (CKR_FUNCTION_FAILED);
1986 	}
1987 
1988 	/*
1989 	 * TRYME INSTEAD:
1990 	 * - find publicRootKeyUUID
1991 	 * - Load publicRootKey by UUID (SRK parent)
1992 	 * - find publicLeafKeyUUID
1993 	 * - Load publicLeafKey by UUID (publicRootKey parent)
1994 	 * - set password policy on publicLeafKey
1995 	 */
1996 	if (local_uuid_is_null(&publicRootKeyUUID) &&
1997 	    find_uuid(TPMTOK_PUBLIC_ROOT_KEY_ID, &publicRootKeyUUID)) {
1998 		/*
1999 		 * The SO hasn't set her PIN yet, compare the
2000 		 * login pin with the hard-coded value.
2001 		 */
2002 		if (memcmp(default_so_pin_sha, hash_sha,
2003 		    SHA1_DIGEST_LENGTH)) {
2004 			return (CKR_PIN_INCORRECT);
2005 		}
2006 		return (CKR_OK);
2007 	}
2008 
2009 	result = Tspi_Context_GetKeyByUUID(hContext,
2010 	    TSS_PS_TYPE_USER, publicRootKeyUUID, &hPublicRootKey);
2011 
2012 	if (result)
2013 		return (CKR_FUNCTION_FAILED);
2014 
2015 	result = Tspi_Key_LoadKey(hPublicRootKey, hSRK);
2016 	if (result)
2017 		return (CKR_FUNCTION_FAILED);
2018 
2019 	if (local_uuid_is_null(&publicLeafKeyUUID) &&
2020 	    find_uuid(TPMTOK_PUBLIC_LEAF_KEY_ID, &publicLeafKeyUUID))
2021 		return (CKR_FUNCTION_FAILED);
2022 
2023 	result = Tspi_Context_GetKeyByUUID(hContext,
2024 	    TSS_PS_TYPE_USER, publicLeafKeyUUID, &hPublicLeafKey);
2025 	if (result)
2026 		return (CKR_FUNCTION_FAILED);
2027 
2028 	result = tss_assign_secret_key_policy(hContext, hPublicLeafKey,
2029 	    hash_sha);
2030 	if (result)
2031 		return (CKR_FUNCTION_FAILED);
2032 
2033 	result = Tspi_Key_LoadKey(hPublicLeafKey, hPublicRootKey);
2034 	if (result)
2035 		return (CKR_FUNCTION_FAILED);
2036 
2037 	/* If the hash given is wrong, the verify will fail */
2038 	if ((rc = token_verify_pin(hContext, hPublicLeafKey))) {
2039 		return (rc);
2040 	}
2041 
2042 	return (CKR_OK);
2043 }
2044 
2045 CK_RV
2046 token_specific_final()
2047 {
2048 	return (CKR_OK);
2049 }
2050 
2051 /*
2052  * Wrap the 20 bytes of auth data and store in an attribute of the two
2053  * keys.
2054  */
2055 static CK_RV
2056 token_wrap_auth_data(TSS_HCONTEXT hContext,
2057 	CK_BYTE *authData, TEMPLATE *publ_tmpl,
2058 	TEMPLATE *priv_tmpl)
2059 {
2060 	CK_RV		rc;
2061 	CK_ATTRIBUTE	*new_attr;
2062 
2063 	TSS_RESULT	ret;
2064 	TSS_HKEY	hParentKey;
2065 	TSS_HENCDATA	hEncData;
2066 	BYTE		*blob;
2067 	UINT32		blob_size;
2068 
2069 	if ((hPrivateLeafKey == NULL_HKEY) && (hPublicLeafKey == NULL_HKEY)) {
2070 		return (CKR_FUNCTION_FAILED);
2071 	} else if (hPublicLeafKey != NULL_HKEY) {
2072 		hParentKey = hPublicLeafKey;
2073 	} else {
2074 		hParentKey = hPrivateLeafKey;
2075 	}
2076 
2077 	/* create the encrypted data object */
2078 	if ((ret = Tspi_Context_CreateObject(hContext,
2079 	    TSS_OBJECT_TYPE_ENCDATA, TSS_ENCDATA_BIND, &hEncData))) {
2080 		stlogit("Tspi_Context_CreateObject: 0x%0x - %s",
2081 		    ret, Trspi_Error_String(ret));
2082 		return (CKR_FUNCTION_FAILED);
2083 	}
2084 
2085 	if ((ret = Tspi_Data_Bind(hEncData, hParentKey, SHA1_DIGEST_LENGTH,
2086 	    authData))) {
2087 		stlogit("Tspi_Data_Bind: 0x%0x - %s",
2088 		    ret, Trspi_Error_String(ret));
2089 		return (CKR_FUNCTION_FAILED);
2090 	}
2091 
2092 	/* pull the encrypted data out of the encrypted data object */
2093 	if ((ret = Tspi_GetAttribData(hEncData, TSS_TSPATTRIB_ENCDATA_BLOB,
2094 	    TSS_TSPATTRIB_ENCDATABLOB_BLOB, &blob_size, &blob))) {
2095 		stlogit("Tspi_SetAttribData: 0x%0x - %s",
2096 		    ret, Trspi_Error_String(ret));
2097 		return (CKR_FUNCTION_FAILED);
2098 	}
2099 
2100 	if ((rc = build_attribute(CKA_ENC_AUTHDATA, blob, blob_size,
2101 	    &new_attr))) {
2102 		return (rc);
2103 	}
2104 	(void) template_update_attribute(publ_tmpl, new_attr);
2105 
2106 	if ((rc = build_attribute(CKA_ENC_AUTHDATA, blob,
2107 	    blob_size, &new_attr))) {
2108 		return (rc);
2109 	}
2110 	(void) template_update_attribute(priv_tmpl, new_attr);
2111 
2112 	return (rc);
2113 }
2114 
2115 static CK_RV
2116 token_unwrap_auth_data(TSS_HCONTEXT hContext, CK_BYTE *encAuthData,
2117 	CK_ULONG encAuthDataLen, TSS_HKEY hKey,
2118 	BYTE **authData)
2119 {
2120 	TSS_RESULT	result;
2121 	TSS_HENCDATA	hEncData;
2122 	BYTE		*buf;
2123 	UINT32		buf_size;
2124 
2125 	if ((result = Tspi_Context_CreateObject(hContext,
2126 	    TSS_OBJECT_TYPE_ENCDATA, TSS_ENCDATA_BIND, &hEncData))) {
2127 		stlogit("Tspi_Context_CreateObject: 0x%0x - %s",
2128 		    result, Trspi_Error_String(result));
2129 		return (CKR_FUNCTION_FAILED);
2130 	}
2131 
2132 	if ((result = Tspi_SetAttribData(hEncData,
2133 	    TSS_TSPATTRIB_ENCDATA_BLOB, TSS_TSPATTRIB_ENCDATABLOB_BLOB,
2134 	    encAuthDataLen, encAuthData))) {
2135 		stlogit("Tspi_SetAttribData: 0x%0x - %s",
2136 		    result, Trspi_Error_String(result));
2137 		return (CKR_FUNCTION_FAILED);
2138 	}
2139 
2140 	/* unbind the data, receiving the plaintext back */
2141 	if ((result = Tspi_Data_Unbind(hEncData, hKey, &buf_size, &buf))) {
2142 		stlogit("Tspi_Data_Unbind: 0x%0x - %s",
2143 		    result, Trspi_Error_String(result));
2144 		return (CKR_FUNCTION_FAILED);
2145 	}
2146 
2147 	if (buf_size != SHA1_DIGEST_LENGTH) {
2148 		return (CKR_FUNCTION_FAILED);
2149 	}
2150 
2151 	*authData = buf;
2152 
2153 	return (CKR_OK);
2154 }
2155 
2156 CK_RV
2157 token_specific_rsa_generate_keypair(
2158 	TSS_HCONTEXT hContext,
2159 	TEMPLATE  *publ_tmpl,
2160 	TEMPLATE  *priv_tmpl)
2161 {
2162 	CK_ATTRIBUTE	*attr = NULL;
2163 	CK_ULONG	mod_bits = 0;
2164 	CK_BBOOL	flag;
2165 	CK_RV		rc;
2166 
2167 	TSS_FLAG	initFlags = 0;
2168 	BYTE		authHash[SHA1_DIGEST_LENGTH];
2169 	BYTE		*authData = NULL;
2170 	TSS_HKEY	hKey = NULL_HKEY;
2171 	TSS_HKEY	hParentKey = NULL_HKEY;
2172 	TSS_RESULT	result;
2173 	UINT32		ulBlobLen;
2174 	BYTE		*rgbBlob;
2175 
2176 	/* Make sure the public exponent is usable */
2177 	if ((util_check_public_exponent(publ_tmpl))) {
2178 		return (CKR_TEMPLATE_INCONSISTENT);
2179 	}
2180 
2181 	flag = template_attribute_find(publ_tmpl, CKA_MODULUS_BITS, &attr);
2182 	if (!flag) {
2183 		return (CKR_TEMPLATE_INCOMPLETE);
2184 	}
2185 	mod_bits = *(CK_ULONG *)attr->pValue;
2186 
2187 	if ((initFlags = util_get_keysize_flag(mod_bits)) == 0) {
2188 		return (CKR_KEY_SIZE_RANGE);
2189 	}
2190 
2191 	/*
2192 	 * If we're not logged in, hPrivateLeafKey and hPublicLeafKey
2193 	 * should be NULL.
2194 	 */
2195 	if ((hPrivateLeafKey == NULL_HKEY) &&
2196 	    (hPublicLeafKey == NULL_HKEY)) {
2197 		/* public session, wrap key with the PRK */
2198 		initFlags |= TSS_KEY_TYPE_LEGACY |
2199 		    TSS_KEY_NO_AUTHORIZATION | TSS_KEY_MIGRATABLE;
2200 
2201 		if ((result = token_load_public_root_key(hContext))) {
2202 			return (CKR_FUNCTION_FAILED);
2203 		}
2204 
2205 		hParentKey = hPublicRootKey;
2206 	} else if (hPrivateLeafKey != NULL_HKEY) {
2207 		/* logged in USER session */
2208 		initFlags |= TSS_KEY_TYPE_LEGACY |
2209 		    TSS_KEY_AUTHORIZATION | TSS_KEY_MIGRATABLE;
2210 
2211 		/* get a random SHA1 hash for the auth data */
2212 		if ((rc = token_rng(hContext, authHash, SHA1_DIGEST_LENGTH))) {
2213 			return (CKR_FUNCTION_FAILED);
2214 		}
2215 
2216 		authData = authHash;
2217 		hParentKey = hPrivateRootKey;
2218 	} else {
2219 		/* logged in SO session */
2220 		initFlags |= TSS_KEY_TYPE_LEGACY |
2221 		    TSS_KEY_AUTHORIZATION | TSS_KEY_MIGRATABLE;
2222 
2223 		/* get a random SHA1 hash for the auth data */
2224 		if ((rc = token_rng(hContext, authHash, SHA1_DIGEST_LENGTH))) {
2225 			return (CKR_FUNCTION_FAILED);
2226 		}
2227 
2228 		authData = authHash;
2229 		hParentKey = hPublicRootKey;
2230 	}
2231 
2232 	if ((result = tss_generate_key(hContext, initFlags, authData,
2233 	    hParentKey, &hKey))) {
2234 		return (result);
2235 	}
2236 
2237 	if ((result = Tspi_GetAttribData(hKey, TSS_TSPATTRIB_KEY_BLOB,
2238 	    TSS_TSPATTRIB_KEYBLOB_BLOB, &ulBlobLen, &rgbBlob))) {
2239 		stlogit("Tspi_GetAttribData: 0x%0x - %s",
2240 		    result, Trspi_Error_String(result));
2241 		return (CKR_FUNCTION_FAILED);
2242 	}
2243 
2244 	if ((rc = build_attribute(CKA_IBM_OPAQUE, rgbBlob,
2245 	    ulBlobLen, &attr))) {
2246 		Tspi_Context_FreeMemory(hContext, rgbBlob);
2247 		return (rc);
2248 	}
2249 	(void) template_update_attribute(priv_tmpl, attr);
2250 	if ((rc = build_attribute(CKA_IBM_OPAQUE, rgbBlob,
2251 	    ulBlobLen, &attr))) {
2252 		Tspi_Context_FreeMemory(hContext, rgbBlob);
2253 		return (rc);
2254 	}
2255 	(void) template_update_attribute(publ_tmpl, attr);
2256 
2257 	Tspi_Context_FreeMemory(hContext, rgbBlob);
2258 
2259 	/* grab the public key to put into the public key object */
2260 	if ((result = Tspi_GetAttribData(hKey, TSS_TSPATTRIB_RSAKEY_INFO,
2261 	    TSS_TSPATTRIB_KEYINFO_RSA_MODULUS, &ulBlobLen, &rgbBlob))) {
2262 		stlogit("Tspi_GetAttribData: 0x%0x - %s",
2263 		    result, Trspi_Error_String(result));
2264 		return (result);
2265 	}
2266 
2267 	/* add the public key blob to the object template */
2268 	if ((rc = build_attribute(CKA_MODULUS, rgbBlob, ulBlobLen, &attr))) {
2269 		Tspi_Context_FreeMemory(hContext, rgbBlob);
2270 		return (rc);
2271 	}
2272 	(void) template_update_attribute(publ_tmpl, attr);
2273 
2274 	/* add the public key blob to the object template */
2275 	if ((rc = build_attribute(CKA_MODULUS, rgbBlob, ulBlobLen, &attr))) {
2276 		Tspi_Context_FreeMemory(hContext, rgbBlob);
2277 		return (rc);
2278 	}
2279 	(void) template_update_attribute(priv_tmpl, attr);
2280 	Tspi_Context_FreeMemory(hContext, rgbBlob);
2281 
2282 	/* wrap the authdata and put it into an object */
2283 	if (authData != NULL) {
2284 		rc = token_wrap_auth_data(hContext, authData, publ_tmpl,
2285 		    priv_tmpl);
2286 	}
2287 
2288 	return (rc);
2289 }
2290 
2291 static CK_RV
2292 token_rsa_load_key(
2293 	TSS_HCONTEXT hContext,
2294 	OBJECT *key_obj,
2295 	TSS_HKEY *phKey)
2296 {
2297 	TSS_RESULT result;
2298 	TSS_HPOLICY hPolicy = NULL_HPOLICY;
2299 	TSS_HKEY	hParentKey;
2300 	BYTE		*authData = NULL;
2301 	CK_ATTRIBUTE	*attr;
2302 	CK_RV		rc;
2303 	CK_OBJECT_HANDLE handle;
2304 
2305 	if (hPrivateLeafKey != NULL_HKEY) {
2306 		hParentKey = hPrivateRootKey;
2307 	} else {
2308 		if ((result = token_load_public_root_key(hContext)))
2309 			return (CKR_FUNCTION_FAILED);
2310 
2311 		hParentKey = hPublicRootKey;
2312 	}
2313 
2314 	if ((rc = template_attribute_find(key_obj->template,
2315 	    CKA_IBM_OPAQUE, &attr)) == FALSE) {
2316 		/* if the key blob wasn't found, then try to wrap the key */
2317 		rc = object_mgr_find_in_map2(hContext, key_obj, &handle);
2318 		if (rc != CKR_OK)
2319 			return (CKR_FUNCTION_FAILED);
2320 
2321 		if ((rc = token_load_key(hContext,
2322 		    handle, hParentKey, NULL, phKey))) {
2323 			return (rc);
2324 		}
2325 		/* try again to get the CKA_IBM_OPAQUE attr */
2326 		if ((rc = template_attribute_find(key_obj->template,
2327 		    CKA_IBM_OPAQUE, &attr)) == FALSE) {
2328 			return (rc);
2329 		}
2330 	}
2331 
2332 	if ((result = Tspi_Context_LoadKeyByBlob(hContext,
2333 	    hParentKey, attr->ulValueLen,
2334 	    attr->pValue, phKey))) {
2335 		stlogit("Tspi_Context_LoadKeyByBlob: 0x%0x - %s",
2336 		    result, Trspi_Error_String(result));
2337 		return (CKR_FUNCTION_FAILED);
2338 	}
2339 
2340 	/* auth data may be required */
2341 	if (template_attribute_find(key_obj->template, CKA_ENC_AUTHDATA,
2342 	    &attr) == TRUE && attr) {
2343 		if ((hPrivateLeafKey == NULL_HKEY) &&
2344 		    (hPublicLeafKey == NULL_HKEY)) {
2345 			return (CKR_FUNCTION_FAILED);
2346 		} else if (hPublicLeafKey != NULL_HKEY) {
2347 			hParentKey = hPublicLeafKey;
2348 		} else {
2349 			hParentKey = hPrivateLeafKey;
2350 		}
2351 
2352 		if ((result = token_unwrap_auth_data(hContext,
2353 		    attr->pValue,
2354 		    attr->ulValueLen, hParentKey, &authData))) {
2355 			return (CKR_FUNCTION_FAILED);
2356 		}
2357 
2358 		if ((result = Tspi_GetPolicyObject(*phKey,
2359 		    TSS_POLICY_USAGE, &hPolicy))) {
2360 			stlogit("Tspi_GetPolicyObject: 0x%0x - %s",
2361 			    result, Trspi_Error_String(result));
2362 			return (CKR_FUNCTION_FAILED);
2363 		}
2364 
2365 		/*
2366 		 * If the policy handle returned is the same as the
2367 		 * context's default policy, then a new policy must
2368 		 * be created and assigned to the key. Otherwise, just set the
2369 		 * secret in the policy.
2370 		 */
2371 		if (hPolicy == hDefaultPolicy) {
2372 			if ((result = Tspi_Context_CreateObject(hContext,
2373 			    TSS_OBJECT_TYPE_POLICY, TSS_POLICY_USAGE,
2374 			    &hPolicy))) {
2375 				stlogit("Tspi_Context_CreateObject: "
2376 				    "0x%0x - %s",
2377 				    result, Trspi_Error_String(result));
2378 				return (CKR_FUNCTION_FAILED);
2379 			}
2380 
2381 			if ((result = Tspi_Policy_SetSecret(hPolicy,
2382 			    TSS_SECRET_MODE_SHA1,
2383 			    SHA1_DIGEST_LENGTH, authData))) {
2384 				stlogit("Tspi_Policy_SetSecret: "
2385 				    "0x%0x - %s",
2386 				    result, Trspi_Error_String(result));
2387 				return (CKR_FUNCTION_FAILED);
2388 			}
2389 
2390 			if ((result = Tspi_Policy_AssignToObject(hPolicy,
2391 			    *phKey))) {
2392 				stlogit("Tspi_Policy_AssignToObject: "
2393 				    "0x%0x - %s",
2394 				    result, Trspi_Error_String(result));
2395 				return (CKR_FUNCTION_FAILED);
2396 			}
2397 		} else if ((result = Tspi_Policy_SetSecret(hPolicy,
2398 		    TSS_SECRET_MODE_SHA1, SHA1_DIGEST_LENGTH, authData))) {
2399 			stlogit("Tspi_Policy_SetSecret: 0x%0x - %s",
2400 			    result, Trspi_Error_String(result));
2401 			return (CKR_FUNCTION_FAILED);
2402 		}
2403 
2404 		Tspi_Context_FreeMemory(hContext, authData);
2405 	}
2406 
2407 	return (CKR_OK);
2408 }
2409 
2410 CK_RV
2411 tpm_decrypt_data(
2412 	TSS_HCONTEXT hContext,
2413 	TSS_HKEY    hKey,
2414 	CK_BYTE   * in_data,
2415 	CK_ULONG    in_data_len,
2416 	CK_BYTE   * out_data,
2417 	CK_ULONG  * out_data_len)
2418 {
2419 	TSS_RESULT result;
2420 	TSS_HENCDATA	hEncData = NULL_HENCDATA;
2421 	UINT32		buf_size = 0, modLen;
2422 	BYTE		*buf = NULL, *modulus = NULL;
2423 	CK_ULONG	chunklen, remain, outlen;
2424 
2425 	/* push the data into the encrypted data object */
2426 	if ((result = Tspi_Context_CreateObject(hContext,
2427 	    TSS_OBJECT_TYPE_ENCDATA, TSS_ENCDATA_BIND, &hEncData))) {
2428 		stlogit("Tspi_Context_CreateObject: 0x%0x - %s",
2429 		    result, Trspi_Error_String(result));
2430 		return (CKR_FUNCTION_FAILED);
2431 	}
2432 
2433 	/*
2434 	 * Figure out the modulus size so we can break the data
2435 	 * into smaller chunks if necessary.
2436 	 */
2437 	if ((result = Tspi_GetAttribData(hKey, TSS_TSPATTRIB_RSAKEY_INFO,
2438 	    TSS_TSPATTRIB_KEYINFO_RSA_MODULUS, &modLen, &modulus))) {
2439 		stlogit("Tspi_GetAttribData: 0x%0x - %s",
2440 		    result, Trspi_Error_String(result));
2441 		return (result);
2442 	}
2443 	/* we don't need the actual modulus */
2444 	Tspi_Context_FreeMemory(hContext, modulus);
2445 
2446 	chunklen = (in_data_len > modLen ? modLen : in_data_len);
2447 	remain = in_data_len;
2448 	outlen = 0;
2449 
2450 	while (remain > 0) {
2451 		if ((result = Tspi_SetAttribData(hEncData,
2452 		    TSS_TSPATTRIB_ENCDATA_BLOB,
2453 		    TSS_TSPATTRIB_ENCDATABLOB_BLOB,
2454 		    chunklen, in_data))) {
2455 			stlogit("Tspi_SetAttribData: 0x%0x - %s",
2456 			    result, Trspi_Error_String(result));
2457 			return (CKR_FUNCTION_FAILED);
2458 		}
2459 
2460 		/* unbind the data, receiving the plaintext back */
2461 		if ((result = Tspi_Data_Unbind(hEncData, hKey,
2462 		    &buf_size, &buf))) {
2463 			stlogit("Tspi_Data_Unbind: 0x%0x - %s",
2464 			    result, Trspi_Error_String(result));
2465 			return (CKR_FUNCTION_FAILED);
2466 		}
2467 
2468 		if (*out_data_len < buf_size + outlen) {
2469 			Tspi_Context_FreeMemory(hContext, buf);
2470 			return (CKR_BUFFER_TOO_SMALL);
2471 		}
2472 
2473 		(void) memcpy(out_data + outlen, buf, buf_size);
2474 
2475 		outlen += buf_size;
2476 		in_data += chunklen;
2477 		remain -= chunklen;
2478 
2479 		Tspi_Context_FreeMemory(hContext, buf);
2480 		if (chunklen > remain)
2481 			chunklen = remain;
2482 	}
2483 	*out_data_len = outlen;
2484 	return (CKR_OK);
2485 }
2486 
2487 CK_RV
2488 token_specific_rsa_decrypt(
2489 	TSS_HCONTEXT hContext,
2490 	CK_BYTE   * in_data,
2491 	CK_ULONG    in_data_len,
2492 	CK_BYTE   * out_data,
2493 	CK_ULONG  * out_data_len,
2494 	OBJECT	  * key_obj)
2495 {
2496 	CK_RV		rc;
2497 	TSS_HKEY	hKey;
2498 
2499 	if ((rc = token_rsa_load_key(hContext, key_obj, &hKey))) {
2500 		return (rc);
2501 	}
2502 
2503 	rc = tpm_decrypt_data(hContext, hKey, in_data, in_data_len,
2504 	    out_data, out_data_len);
2505 
2506 	return (rc);
2507 }
2508 
2509 CK_RV
2510 token_specific_rsa_verify(
2511 	TSS_HCONTEXT hContext,
2512 	CK_BYTE   * in_data,
2513 	CK_ULONG    in_data_len,
2514 	CK_BYTE   * sig,
2515 	CK_ULONG    sig_len,
2516 	OBJECT	  * key_obj)
2517 {
2518 	TSS_RESULT	result;
2519 	TSS_HHASH	hHash;
2520 	TSS_HKEY	hKey;
2521 	CK_RV		rc;
2522 
2523 	if ((rc = token_rsa_load_key(hContext, key_obj, &hKey))) {
2524 		return (rc);
2525 	}
2526 
2527 	/* Create the hash object we'll use to sign */
2528 	if ((result = Tspi_Context_CreateObject(hContext,
2529 	    TSS_OBJECT_TYPE_HASH, TSS_HASH_OTHER, &hHash))) {
2530 		stlogit("Tspi_Context_CreateObject: 0x%0x - %s",
2531 		    result, Trspi_Error_String(result));
2532 		return (CKR_FUNCTION_FAILED);
2533 	}
2534 
2535 	/* Insert the data into the hash object */
2536 	if ((result = Tspi_Hash_SetHashValue(hHash, in_data_len,
2537 	    in_data))) {
2538 		stlogit("Tspi_Hash_SetHashValue: 0x%0x - %s",
2539 		    result, Trspi_Error_String(result));
2540 		return (CKR_FUNCTION_FAILED);
2541 	}
2542 
2543 	/* Verify */
2544 	result = Tspi_Hash_VerifySignature(hHash, hKey, sig_len, sig);
2545 	if (result != TSS_SUCCESS &&
2546 	    TPMTOK_TSS_ERROR_CODE(result) != TSS_E_FAIL) {
2547 		stlogit("Tspi_Hash_VerifySignature: 0x%0x - %s",
2548 		    result, Trspi_Error_String(result));
2549 	}
2550 
2551 	if (TPMTOK_TSS_ERROR_CODE(result) == TSS_E_FAIL) {
2552 		rc = CKR_SIGNATURE_INVALID;
2553 	} else {
2554 		rc = CKR_OK;
2555 	}
2556 
2557 	return (rc);
2558 }
2559 
2560 CK_RV
2561 token_specific_rsa_sign(
2562 	TSS_HCONTEXT hContext,
2563 	CK_BYTE   * in_data,
2564 	CK_ULONG    in_data_len,
2565 	CK_BYTE   * out_data,
2566 	CK_ULONG  * out_data_len,
2567 	OBJECT	  * key_obj)
2568 {
2569 	TSS_RESULT	result;
2570 	TSS_HHASH	hHash;
2571 	BYTE		*sig;
2572 	UINT32		sig_len;
2573 	TSS_HKEY	hKey;
2574 	CK_RV		rc;
2575 
2576 	if ((rc = token_rsa_load_key(hContext, key_obj, &hKey))) {
2577 		return (rc);
2578 	}
2579 
2580 	/* Create the hash object we'll use to sign */
2581 	if ((result = Tspi_Context_CreateObject(hContext,
2582 	    TSS_OBJECT_TYPE_HASH, TSS_HASH_OTHER, &hHash))) {
2583 		stlogit("Tspi_Context_CreateObject: 0x%0x - %s",
2584 		    result, Trspi_Error_String(result));
2585 		return (CKR_FUNCTION_FAILED);
2586 	}
2587 
2588 	/* Insert the data into the hash object */
2589 	if ((result = Tspi_Hash_SetHashValue(hHash, in_data_len,
2590 	    in_data))) {
2591 		stlogit("Tspi_Hash_SetHashValue: 0x%0x - %s",
2592 		    result, Trspi_Error_String(result));
2593 		return (CKR_FUNCTION_FAILED);
2594 	}
2595 
2596 	/* Sign */
2597 	if ((result = Tspi_Hash_Sign(hHash, hKey, &sig_len, &sig))) {
2598 		stlogit("Tspi_Hash_Sign: 0x%0x - %s",
2599 		    result, Trspi_Error_String(result));
2600 		return (CKR_FUNCTION_FAILED);
2601 	}
2602 
2603 	if (sig_len > *out_data_len) {
2604 		Tspi_Context_FreeMemory(hContext, sig);
2605 		return (CKR_BUFFER_TOO_SMALL);
2606 	}
2607 
2608 	(void) memcpy(out_data, sig, sig_len);
2609 	*out_data_len = sig_len;
2610 	Tspi_Context_FreeMemory(hContext, sig);
2611 
2612 	return (CKR_OK);
2613 }
2614 
2615 CK_RV
2616 tpm_encrypt_data(
2617 	TSS_HCONTEXT hContext,
2618 	TSS_HKEY hKey,
2619 	CK_BYTE *in_data,
2620 	CK_ULONG in_data_len,
2621 	CK_BYTE *out_data,
2622 	CK_ULONG *out_data_len)
2623 {
2624 	TSS_RESULT	result;
2625 	TSS_HENCDATA	hEncData;
2626 	BYTE		*dataBlob, *modulus;
2627 	UINT32		dataBlobSize, modLen;
2628 	CK_ULONG	chunklen, remain;
2629 	CK_ULONG	outlen;
2630 
2631 	if ((result = Tspi_Context_CreateObject(hContext,
2632 	    TSS_OBJECT_TYPE_ENCDATA, TSS_ENCDATA_BIND, &hEncData))) {
2633 		stlogit("Tspi_Context_CreateObject: 0x%0x - %s",
2634 		    result, Trspi_Error_String(result));
2635 		return (CKR_FUNCTION_FAILED);
2636 	}
2637 	/*
2638 	 * Figure out the modulus size so we can break the data
2639 	 * into smaller chunks if necessary.
2640 	 */
2641 	if ((result = Tspi_GetAttribData(hKey, TSS_TSPATTRIB_RSAKEY_INFO,
2642 	    TSS_TSPATTRIB_KEYINFO_RSA_MODULUS, &modLen, &modulus))) {
2643 		stlogit("Tspi_GetAttribData: 0x%0x - %s",
2644 		    result, Trspi_Error_String(result));
2645 		return (result);
2646 	}
2647 	/* we don't need the actual modulus */
2648 	Tspi_Context_FreeMemory(hContext, modulus);
2649 
2650 	/*
2651 	 * According to TSS spec for Tspi_Data_Bind (4.3.4.21.5),
2652 	 * Max input data size is: modLen - (40 - 2 - 4 - 1)
2653 	 * (for RSA OAEP SHA1 operations).
2654 	 */
2655 	modLen -= 47;
2656 
2657 	chunklen = (in_data_len > modLen ? modLen : in_data_len);
2658 	remain = in_data_len;
2659 	outlen = 0;
2660 	while (remain > 0) {
2661 		if ((result = Tspi_Data_Bind(hEncData, hKey,
2662 		    chunklen, in_data))) {
2663 			stlogit("Tspi_Data_Bind: 0x%0x - %s",
2664 			    result, Trspi_Error_String(result));
2665 			return (CKR_FUNCTION_FAILED);
2666 		}
2667 
2668 		if ((result = Tspi_GetAttribData(hEncData,
2669 		    TSS_TSPATTRIB_ENCDATA_BLOB,
2670 		    TSS_TSPATTRIB_ENCDATABLOB_BLOB,
2671 		    &dataBlobSize, &dataBlob))) {
2672 			stlogit("Tspi_GetAttribData: 0x%0x - %s",
2673 			    result, Trspi_Error_String(result));
2674 			return (CKR_FUNCTION_FAILED);
2675 		}
2676 
2677 		if (outlen + dataBlobSize > *out_data_len) {
2678 			Tspi_Context_FreeMemory(hContext, dataBlob);
2679 			return (CKR_DATA_LEN_RANGE);
2680 		}
2681 
2682 		(void) memcpy(out_data + outlen,
2683 		    dataBlob, dataBlobSize);
2684 
2685 		outlen += dataBlobSize;
2686 		in_data += chunklen;
2687 		remain -= chunklen;
2688 
2689 		if (chunklen > remain)
2690 			chunklen = remain;
2691 
2692 		Tspi_Context_FreeMemory(hContext, dataBlob);
2693 	}
2694 	*out_data_len = outlen;
2695 
2696 	return (CKR_OK);
2697 }
2698 
2699 CK_RV
2700 token_specific_rsa_encrypt(
2701 	TSS_HCONTEXT hContext,
2702 	CK_BYTE   * in_data,
2703 	CK_ULONG    in_data_len,
2704 	CK_BYTE   * out_data,
2705 	CK_ULONG  * out_data_len,
2706 	OBJECT	  * key_obj)
2707 {
2708 	TSS_HKEY	hKey;
2709 	CK_RV		rc;
2710 
2711 	if ((rc = token_rsa_load_key(hContext, key_obj, &hKey))) {
2712 		return (rc);
2713 	}
2714 
2715 	rc  = tpm_encrypt_data(hContext, hKey, in_data, in_data_len,
2716 	    out_data, out_data_len);
2717 
2718 	return (rc);
2719 }
2720