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