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