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