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