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
58extern void stlogit(char *fmt, ...);
59
60CK_RV token_rng(TSS_HCONTEXT, CK_BYTE *,  CK_ULONG);
61int tok_slot2local(CK_SLOT_ID);
62CK_RV token_specific_session(CK_SLOT_ID);
63CK_RV token_specific_final(TSS_HCONTEXT);
64
65CK_RV
66token_specific_rsa_decrypt(
67	TSS_HCONTEXT,
68	CK_BYTE *,
69	CK_ULONG,
70	CK_BYTE *,
71	CK_ULONG *,
72	OBJECT *);
73
74CK_RV
75token_specific_rsa_encrypt(
76	TSS_HCONTEXT,
77	CK_BYTE *,
78	CK_ULONG,
79	CK_BYTE *,
80	CK_ULONG *,
81	OBJECT *);
82
83CK_RV
84token_specific_rsa_sign(
85	TSS_HCONTEXT,
86	CK_BYTE *,
87	CK_ULONG,
88	CK_BYTE *,
89	CK_ULONG *,
90	OBJECT *);
91
92CK_RV
93token_specific_rsa_verify(TSS_HCONTEXT, CK_BYTE *,
94    CK_ULONG, CK_BYTE *, CK_ULONG, OBJECT *);
95
96CK_RV
97token_specific_rsa_generate_keypair(TSS_HCONTEXT,
98	TEMPLATE *,
99	TEMPLATE *);
100
101CK_RV
102token_specific_sha_init(DIGEST_CONTEXT *);
103
104CK_RV
105token_specific_sha_update(DIGEST_CONTEXT *,
106	CK_BYTE *,
107	CK_ULONG);
108
109CK_RV
110token_specific_sha_final(DIGEST_CONTEXT *,
111	CK_BYTE *,
112	CK_ULONG *);
113
114CK_RV token_specific_login(TSS_HCONTEXT, CK_USER_TYPE, CK_CHAR_PTR, CK_ULONG);
115CK_RV token_specific_logout(TSS_HCONTEXT);
116CK_RV token_specific_init_pin(TSS_HCONTEXT, CK_CHAR_PTR, CK_ULONG);
117CK_RV token_specific_set_pin(ST_SESSION_HANDLE, CK_CHAR_PTR,
118	CK_ULONG, CK_CHAR_PTR, CK_ULONG);
119CK_RV token_specific_verify_so_pin(TSS_HCONTEXT, CK_CHAR_PTR, CK_ULONG);
120
121static CK_RV
122token_specific_init(char *, CK_SLOT_ID, TSS_HCONTEXT *);
123
124struct 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 */
149TSS_HKEY hPublicRootKey = NULL_HKEY;
150TSS_HKEY hPublicLeafKey = NULL_HKEY;
151TSS_HKEY hPrivateRootKey = NULL_HKEY;
152TSS_HKEY hPrivateLeafKey = NULL_HKEY;
153
154TSS_UUID publicRootKeyUUID;
155TSS_UUID publicLeafKeyUUID;
156TSS_UUID privateRootKeyUUID;
157TSS_UUID privateLeafKeyUUID;
158
159/* TSP policy handles */
160TSS_HPOLICY hDefaultPolicy = NULL_HPOLICY;
161
162/* PKCS#11 key handles */
163int not_initialized = 0;
164
165CK_BYTE current_user_pin_sha[SHA1_DIGEST_LENGTH];
166CK_BYTE current_so_pin_sha[SHA1_DIGEST_LENGTH];
167
168static TPM_CAP_VERSION_INFO tpmvinfo;
169
170static CK_RV
171verify_user_pin(TSS_HCONTEXT, CK_BYTE *);
172
173static TSS_RESULT
174tss_assign_secret_key_policy(TSS_HCONTEXT, TSS_FLAG, TSS_HKEY, CK_CHAR *);
175
176static TSS_RESULT
177set_legacy_key_params(TSS_HKEY);
178
179static void
180local_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 */
189static void
190tss_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 */
223static void
224tss_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
253static void
254local_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
266static void
267local_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
276static int
277local_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
299static int
300remove_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
346static int
347find_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
397static int
398local_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
409static int
410add_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
442static UINT32
443util_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 */
460static CK_ULONG
461util_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
491TSS_RESULT
492set_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 */
545CK_RV
546token_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*/
597CK_RV
598token_specific_session(CK_SLOT_ID  slotid)
599{
600	return (CKR_OK);
601}
602
603CK_RV
604token_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
628TSS_RESULT
629open_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*/
650static CK_RV
651token_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 */
681static CK_RV
682token_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 */
766static CK_RV
767token_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
929static TSS_RESULT
930tss_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	}
959done:
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 */
969static CK_RV
970token_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 */
1008static TSS_RESULT
1009token_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
1043done:
1044	return (result);
1045}
1046
1047static TSS_RESULT
1048tss_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
1082static TSS_RESULT
1083token_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
1104static TSS_RESULT
1105set_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
1130static TSS_RESULT
1131tss_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
1205static TSS_RESULT
1206tss_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
1254static CK_RV
1255token_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
1312done:
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 */
1321static CK_RV
1322token_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
1370done:
1371	if (rgbUnboundData != NULL)
1372		Tspi_Context_FreeMemory(hContext, rgbUnboundData);
1373	Tspi_Context_CloseObject(hContext, hEncData);
1374	return (rc);
1375}
1376
1377static CK_RV
1378token_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
1468static CK_RV
1469token_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
1555CK_RV
1556token_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
1667CK_RV
1668token_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*/
1692CK_RV
1693token_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
1705static CK_RV
1706check_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 */
1738static CK_RV
1739verify_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
1789CK_RV
1790token_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 */
1919CK_RV
1920token_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
1992CK_RV
1993token_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 */
2018static CK_RV
2019token_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
2078static CK_RV
2079token_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
2119CK_RV
2120token_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
2254static CK_RV
2255token_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
2404CK_RV
2405tpm_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
2481CK_RV
2482token_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
2503CK_RV
2504token_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
2554CK_RV
2555token_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
2609CK_RV
2610tpm_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
2720CK_RV
2721token_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 */
2749CK_RV
2750token_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
2799end:
2800	Tspi_Context_FreeMemory(hContext, modulus);
2801	return (rc);
2802}
2803