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