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