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