147e946e7SWyllys Ingersoll /*
247e946e7SWyllys Ingersoll  * The Initial Developer of the Original Code is International
347e946e7SWyllys Ingersoll  * Business Machines Corporation. Portions created by IBM
447e946e7SWyllys Ingersoll  * Corporation are Copyright (C) 2005 International Business
547e946e7SWyllys Ingersoll  * Machines Corporation. All Rights Reserved.
647e946e7SWyllys Ingersoll  *
747e946e7SWyllys Ingersoll  * This program is free software; you can redistribute it and/or modify
847e946e7SWyllys Ingersoll  * it under the terms of the Common Public License as published by
947e946e7SWyllys Ingersoll  * IBM Corporation; either version 1 of the License, or (at your option)
1047e946e7SWyllys Ingersoll  * any later version.
1147e946e7SWyllys Ingersoll  *
1247e946e7SWyllys Ingersoll  * This program is distributed in the hope that it will be useful,
1347e946e7SWyllys Ingersoll  * but WITHOUT ANY WARRANTY; without even the implied warranty of
1447e946e7SWyllys Ingersoll  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
1547e946e7SWyllys Ingersoll  * Common Public License for more details.
1647e946e7SWyllys Ingersoll  *
1747e946e7SWyllys Ingersoll  * You should have received a copy of the Common Public License
1847e946e7SWyllys Ingersoll  * along with this program; if not, a copy can be viewed at
1947e946e7SWyllys Ingersoll  * http://www.opensource.org/licenses/cpl1.0.php.
2047e946e7SWyllys Ingersoll  */
2147e946e7SWyllys Ingersoll /*
228932b28eSWyllys Ingersoll  * Copyright 2010 Sun Microsystems, Inc.  All rights reserved.
2347e946e7SWyllys Ingersoll  * Use is subject to license terms.
2433f5ff17SMilan Jurik  * Copyright 2012 Milan Jurik. All rights reserved.
2548bbca81SDaniel Hoffman  * Copyright (c) 2016 by Delphix. All rights reserved.
2691419a03SJason King  * Copyright 2018 Jason King
2747e946e7SWyllys Ingersoll  */
2847e946e7SWyllys Ingersoll 
2947e946e7SWyllys Ingersoll #include <pthread.h>
3047e946e7SWyllys Ingersoll #include <string.h>
3147e946e7SWyllys Ingersoll 
3247e946e7SWyllys Ingersoll #include <sys/types.h>
3347e946e7SWyllys Ingersoll #include <sys/stat.h>
3447e946e7SWyllys Ingersoll #include <uuid/uuid.h>
3547e946e7SWyllys Ingersoll #include <fcntl.h>
3647e946e7SWyllys Ingersoll #include <errno.h>
3747e946e7SWyllys Ingersoll #include <pwd.h>
3847e946e7SWyllys Ingersoll #include <syslog.h>
3947e946e7SWyllys Ingersoll 
4091419a03SJason King #include <sys/crypto/common.h>	/* For CRYPTO_BYTES2BITS */
4191419a03SJason King #include <rsa_impl.h>
4291419a03SJason King #include <padding.h>
43ab8176c2SWyllys Ingersoll 
4447e946e7SWyllys Ingersoll #include <tss/platform.h>
4547e946e7SWyllys Ingersoll #include <tss/tss_defines.h>
4647e946e7SWyllys Ingersoll #include <tss/tss_typedef.h>
4747e946e7SWyllys Ingersoll #include <tss/tss_structs.h>
4847e946e7SWyllys Ingersoll #include <tss/tss_error.h>
4947e946e7SWyllys Ingersoll #include <tss/tcs_error.h>
5047e946e7SWyllys Ingersoll #include <tss/tspi.h>
5147e946e7SWyllys Ingersoll #include <trousers/trousers.h>
5247e946e7SWyllys Ingersoll 
5347e946e7SWyllys Ingersoll #include "tpmtok_int.h"
5447e946e7SWyllys Ingersoll #include "tpmtok_defs.h"
5547e946e7SWyllys Ingersoll 
56ab8176c2SWyllys Ingersoll #define	MAX_RSA_KEYLENGTH 512
57ab8176c2SWyllys Ingersoll 
5847e946e7SWyllys Ingersoll extern void stlogit(char *fmt, ...);
5947e946e7SWyllys Ingersoll 
6047e946e7SWyllys Ingersoll CK_RV token_rng(TSS_HCONTEXT, CK_BYTE *,  CK_ULONG);
6147e946e7SWyllys Ingersoll int tok_slot2local(CK_SLOT_ID);
6247e946e7SWyllys Ingersoll CK_RV token_specific_session(CK_SLOT_ID);
63ab8176c2SWyllys Ingersoll CK_RV token_specific_final(TSS_HCONTEXT);
6447e946e7SWyllys Ingersoll 
6547e946e7SWyllys Ingersoll CK_RV
6647e946e7SWyllys Ingersoll token_specific_rsa_decrypt(
6747e946e7SWyllys Ingersoll 	TSS_HCONTEXT,
6847e946e7SWyllys Ingersoll 	CK_BYTE *,
6947e946e7SWyllys Ingersoll 	CK_ULONG,
7047e946e7SWyllys Ingersoll 	CK_BYTE *,
7147e946e7SWyllys Ingersoll 	CK_ULONG *,
7247e946e7SWyllys Ingersoll 	OBJECT *);
7347e946e7SWyllys Ingersoll 
7447e946e7SWyllys Ingersoll CK_RV
7547e946e7SWyllys Ingersoll token_specific_rsa_encrypt(
7647e946e7SWyllys Ingersoll 	TSS_HCONTEXT,
7747e946e7SWyllys Ingersoll 	CK_BYTE *,
7847e946e7SWyllys Ingersoll 	CK_ULONG,
7947e946e7SWyllys Ingersoll 	CK_BYTE *,
8047e946e7SWyllys Ingersoll 	CK_ULONG *,
8147e946e7SWyllys Ingersoll 	OBJECT *);
8247e946e7SWyllys Ingersoll 
8347e946e7SWyllys Ingersoll CK_RV
8447e946e7SWyllys Ingersoll token_specific_rsa_sign(
8547e946e7SWyllys Ingersoll 	TSS_HCONTEXT,
8647e946e7SWyllys Ingersoll 	CK_BYTE *,
8747e946e7SWyllys Ingersoll 	CK_ULONG,
8847e946e7SWyllys Ingersoll 	CK_BYTE *,
8947e946e7SWyllys Ingersoll 	CK_ULONG *,
9047e946e7SWyllys Ingersoll 	OBJECT *);
9147e946e7SWyllys Ingersoll 
9247e946e7SWyllys Ingersoll CK_RV
9347e946e7SWyllys Ingersoll token_specific_rsa_verify(TSS_HCONTEXT, CK_BYTE *,
9447e946e7SWyllys Ingersoll     CK_ULONG, CK_BYTE *, CK_ULONG, OBJECT *);
9547e946e7SWyllys Ingersoll 
9647e946e7SWyllys Ingersoll CK_RV
9747e946e7SWyllys Ingersoll token_specific_rsa_generate_keypair(TSS_HCONTEXT,
9847e946e7SWyllys Ingersoll 	TEMPLATE *,
9947e946e7SWyllys Ingersoll 	TEMPLATE *);
10047e946e7SWyllys Ingersoll 
10147e946e7SWyllys Ingersoll CK_RV
10247e946e7SWyllys Ingersoll token_specific_sha_init(DIGEST_CONTEXT *);
10347e946e7SWyllys Ingersoll 
10447e946e7SWyllys Ingersoll CK_RV
10547e946e7SWyllys Ingersoll token_specific_sha_update(DIGEST_CONTEXT *,
10647e946e7SWyllys Ingersoll 	CK_BYTE *,
10747e946e7SWyllys Ingersoll 	CK_ULONG);
10847e946e7SWyllys Ingersoll 
10947e946e7SWyllys Ingersoll CK_RV
11047e946e7SWyllys Ingersoll token_specific_sha_final(DIGEST_CONTEXT *,
11147e946e7SWyllys Ingersoll 	CK_BYTE *,
11247e946e7SWyllys Ingersoll 	CK_ULONG *);
11347e946e7SWyllys Ingersoll 
11447e946e7SWyllys Ingersoll CK_RV token_specific_login(TSS_HCONTEXT, CK_USER_TYPE, CK_CHAR_PTR, CK_ULONG);
11547e946e7SWyllys Ingersoll CK_RV token_specific_logout(TSS_HCONTEXT);
11647e946e7SWyllys Ingersoll CK_RV token_specific_init_pin(TSS_HCONTEXT, CK_CHAR_PTR, CK_ULONG);
11747e946e7SWyllys Ingersoll CK_RV token_specific_set_pin(ST_SESSION_HANDLE, CK_CHAR_PTR,
11847e946e7SWyllys Ingersoll 	CK_ULONG, CK_CHAR_PTR, CK_ULONG);
11947e946e7SWyllys Ingersoll CK_RV token_specific_verify_so_pin(TSS_HCONTEXT, CK_CHAR_PTR, CK_ULONG);
12047e946e7SWyllys Ingersoll 
12147e946e7SWyllys Ingersoll static CK_RV
12247e946e7SWyllys Ingersoll token_specific_init(char *, CK_SLOT_ID, TSS_HCONTEXT *);
12347e946e7SWyllys Ingersoll 
12447e946e7SWyllys Ingersoll struct token_specific_struct token_specific = {
12547e946e7SWyllys Ingersoll 	"TPM_Debug",
12647e946e7SWyllys Ingersoll 	&token_specific_init,
12747e946e7SWyllys Ingersoll 	NULL,
12847e946e7SWyllys Ingersoll 	&token_rng,
12947e946e7SWyllys Ingersoll 	&token_specific_session,
13047e946e7SWyllys Ingersoll 	&token_specific_final,
13147e946e7SWyllys Ingersoll 	&token_specific_rsa_decrypt,
13247e946e7SWyllys Ingersoll 	&token_specific_rsa_encrypt,
13347e946e7SWyllys Ingersoll 	&token_specific_rsa_sign,
13447e946e7SWyllys Ingersoll 	&token_specific_rsa_verify,
13547e946e7SWyllys Ingersoll 	&token_specific_rsa_generate_keypair,
13647e946e7SWyllys Ingersoll 	NULL,
13747e946e7SWyllys Ingersoll 	NULL,
13847e946e7SWyllys Ingersoll 	NULL,
13947e946e7SWyllys Ingersoll 	&token_specific_login,
14047e946e7SWyllys Ingersoll 	&token_specific_logout,
14147e946e7SWyllys Ingersoll 	&token_specific_init_pin,
14247e946e7SWyllys Ingersoll 	&token_specific_set_pin,
14347e946e7SWyllys Ingersoll 	&token_specific_verify_so_pin
14447e946e7SWyllys Ingersoll };
14547e946e7SWyllys Ingersoll 
14647e946e7SWyllys Ingersoll /* The context we'll use globally to connect to the TSP */
14747e946e7SWyllys Ingersoll 
14847e946e7SWyllys Ingersoll /* TSP key handles */
14947e946e7SWyllys Ingersoll TSS_HKEY hPublicRootKey = NULL_HKEY;
15047e946e7SWyllys Ingersoll TSS_HKEY hPublicLeafKey = NULL_HKEY;
15147e946e7SWyllys Ingersoll TSS_HKEY hPrivateRootKey = NULL_HKEY;
15247e946e7SWyllys Ingersoll TSS_HKEY hPrivateLeafKey = NULL_HKEY;
15347e946e7SWyllys Ingersoll 
15447e946e7SWyllys Ingersoll TSS_UUID publicRootKeyUUID;
15547e946e7SWyllys Ingersoll TSS_UUID publicLeafKeyUUID;
15647e946e7SWyllys Ingersoll TSS_UUID privateRootKeyUUID;
15747e946e7SWyllys Ingersoll TSS_UUID privateLeafKeyUUID;
15847e946e7SWyllys Ingersoll 
15947e946e7SWyllys Ingersoll /* TSP policy handles */
16047e946e7SWyllys Ingersoll TSS_HPOLICY hDefaultPolicy = NULL_HPOLICY;
16147e946e7SWyllys Ingersoll 
16247e946e7SWyllys Ingersoll /* PKCS#11 key handles */
16347e946e7SWyllys Ingersoll int not_initialized = 0;
16447e946e7SWyllys Ingersoll 
16547e946e7SWyllys Ingersoll CK_BYTE current_user_pin_sha[SHA1_DIGEST_LENGTH];
16647e946e7SWyllys Ingersoll CK_BYTE current_so_pin_sha[SHA1_DIGEST_LENGTH];
16747e946e7SWyllys Ingersoll 
16847e946e7SWyllys Ingersoll static TPM_CAP_VERSION_INFO tpmvinfo;
16947e946e7SWyllys Ingersoll 
17047e946e7SWyllys Ingersoll static CK_RV
17147e946e7SWyllys Ingersoll verify_user_pin(TSS_HCONTEXT, CK_BYTE *);
17247e946e7SWyllys Ingersoll 
173ab8176c2SWyllys Ingersoll static TSS_RESULT
174ab8176c2SWyllys Ingersoll tss_assign_secret_key_policy(TSS_HCONTEXT, TSS_FLAG, TSS_HKEY, CK_CHAR *);
175ab8176c2SWyllys Ingersoll 
176ab8176c2SWyllys Ingersoll static TSS_RESULT
177ab8176c2SWyllys Ingersoll set_legacy_key_params(TSS_HKEY);
178ab8176c2SWyllys Ingersoll 
17947e946e7SWyllys Ingersoll static void
local_uuid_clear(TSS_UUID * uuid)18047e946e7SWyllys Ingersoll local_uuid_clear(TSS_UUID *uuid)
18147e946e7SWyllys Ingersoll {
18247e946e7SWyllys Ingersoll 	if (uuid == NULL)
18347e946e7SWyllys Ingersoll 		return;
18447e946e7SWyllys Ingersoll 	(void) memset(uuid, 0, sizeof (TSS_UUID));
18547e946e7SWyllys Ingersoll }
18647e946e7SWyllys Ingersoll 
18747e946e7SWyllys Ingersoll 
18847e946e7SWyllys Ingersoll /* convert from TSS_UUID to uuid_t */
18947e946e7SWyllys Ingersoll static void
tss_uuid_convert_from(TSS_UUID * uu,uuid_t ptr)19047e946e7SWyllys Ingersoll tss_uuid_convert_from(TSS_UUID *uu, uuid_t ptr)
19147e946e7SWyllys Ingersoll {
19247e946e7SWyllys Ingersoll 	uint_t		tmp;
19347e946e7SWyllys Ingersoll 	uchar_t		*out = ptr;
19447e946e7SWyllys Ingersoll 
19547e946e7SWyllys Ingersoll 	tmp = ntohl(uu->ulTimeLow);
19647e946e7SWyllys Ingersoll 	out[3] = (uchar_t)tmp;
19747e946e7SWyllys Ingersoll 	tmp >>= 8;
19847e946e7SWyllys Ingersoll 	out[2] = (uchar_t)tmp;
19947e946e7SWyllys Ingersoll 	tmp >>= 8;
20047e946e7SWyllys Ingersoll 	out[1] = (uchar_t)tmp;
20147e946e7SWyllys Ingersoll 	tmp >>= 8;
20247e946e7SWyllys Ingersoll 	out[0] = (uchar_t)tmp;
20347e946e7SWyllys Ingersoll 
20447e946e7SWyllys Ingersoll 	tmp = ntohs(uu->usTimeMid);
20547e946e7SWyllys Ingersoll 	out[5] = (uchar_t)tmp;
20647e946e7SWyllys Ingersoll 	tmp >>= 8;
20747e946e7SWyllys Ingersoll 	out[4] = (uchar_t)tmp;
20847e946e7SWyllys Ingersoll 
20947e946e7SWyllys Ingersoll 	tmp = ntohs(uu->usTimeHigh);
21047e946e7SWyllys Ingersoll 	out[7] = (uchar_t)tmp;
21147e946e7SWyllys Ingersoll 	tmp >>= 8;
21247e946e7SWyllys Ingersoll 	out[6] = (uchar_t)tmp;
21347e946e7SWyllys Ingersoll 
21447e946e7SWyllys Ingersoll 	tmp = uu->bClockSeqHigh;
21547e946e7SWyllys Ingersoll 	out[8] = (uchar_t)tmp;
21647e946e7SWyllys Ingersoll 	tmp = uu->bClockSeqLow;
21747e946e7SWyllys Ingersoll 	out[9] = (uchar_t)tmp;
21847e946e7SWyllys Ingersoll 
21947e946e7SWyllys Ingersoll 	(void) memcpy(out+10, uu->rgbNode, 6);
22047e946e7SWyllys Ingersoll }
22147e946e7SWyllys Ingersoll 
22247e946e7SWyllys Ingersoll /* convert from uuid_t to TSS_UUID */
22347e946e7SWyllys Ingersoll static void
tss_uuid_convert_to(TSS_UUID * uuid,uuid_t in)22447e946e7SWyllys Ingersoll tss_uuid_convert_to(TSS_UUID *uuid, uuid_t in)
22547e946e7SWyllys Ingersoll {
22647e946e7SWyllys Ingersoll 	uchar_t		*ptr;
22747e946e7SWyllys Ingersoll 	uint32_t	ltmp;
22847e946e7SWyllys Ingersoll 	uint16_t	stmp;
22947e946e7SWyllys Ingersoll 
23047e946e7SWyllys Ingersoll 	ptr = in;
23147e946e7SWyllys Ingersoll 
23247e946e7SWyllys Ingersoll 	ltmp = *ptr++;
23347e946e7SWyllys Ingersoll 	ltmp = (ltmp << 8) | *ptr++;
23447e946e7SWyllys Ingersoll 	ltmp = (ltmp << 8) | *ptr++;
23547e946e7SWyllys Ingersoll 	ltmp = (ltmp << 8) | *ptr++;
23647e946e7SWyllys Ingersoll 	uuid->ulTimeLow = ntohl(ltmp);
23747e946e7SWyllys Ingersoll 
23847e946e7SWyllys Ingersoll 	stmp = *ptr++;
23947e946e7SWyllys Ingersoll 	stmp = (stmp << 8) | *ptr++;
24047e946e7SWyllys Ingersoll 	uuid->usTimeMid = ntohs(stmp);
24147e946e7SWyllys Ingersoll 
24247e946e7SWyllys Ingersoll 	stmp = *ptr++;
24347e946e7SWyllys Ingersoll 	stmp = (stmp << 8) | *ptr++;
24447e946e7SWyllys Ingersoll 	uuid->usTimeHigh = ntohs(stmp);
24547e946e7SWyllys Ingersoll 
24647e946e7SWyllys Ingersoll 	uuid->bClockSeqHigh = *ptr++;
24747e946e7SWyllys Ingersoll 
24847e946e7SWyllys Ingersoll 	uuid->bClockSeqLow = *ptr++;
24947e946e7SWyllys Ingersoll 
25047e946e7SWyllys Ingersoll 	(void) memcpy(uuid->rgbNode, ptr, 6);
25147e946e7SWyllys Ingersoll }
25247e946e7SWyllys Ingersoll 
25347e946e7SWyllys Ingersoll static void
local_uuid_copy(TSS_UUID * dst,TSS_UUID * src)25447e946e7SWyllys Ingersoll local_uuid_copy(TSS_UUID *dst, TSS_UUID *src)
25547e946e7SWyllys Ingersoll {
25647e946e7SWyllys Ingersoll 	uuid_t udst, usrc;
25747e946e7SWyllys Ingersoll 
25847e946e7SWyllys Ingersoll 	tss_uuid_convert_from(dst, udst);
25947e946e7SWyllys Ingersoll 	tss_uuid_convert_from(src, usrc);
26047e946e7SWyllys Ingersoll 
26147e946e7SWyllys Ingersoll 	uuid_copy(udst, usrc);
26247e946e7SWyllys Ingersoll 
26347e946e7SWyllys Ingersoll 	tss_uuid_convert_to(dst, udst);
26447e946e7SWyllys Ingersoll }
26547e946e7SWyllys Ingersoll 
26647e946e7SWyllys Ingersoll static void
local_uuid_generate(TSS_UUID * uu)26747e946e7SWyllys Ingersoll local_uuid_generate(TSS_UUID *uu)
26847e946e7SWyllys Ingersoll {
26947e946e7SWyllys Ingersoll 	uuid_t newuuid;
27047e946e7SWyllys Ingersoll 
27147e946e7SWyllys Ingersoll 	uuid_generate(newuuid);
27247e946e7SWyllys Ingersoll 
27347e946e7SWyllys Ingersoll 	tss_uuid_convert_to(uu, newuuid);
27447e946e7SWyllys Ingersoll }
27547e946e7SWyllys Ingersoll 
27647e946e7SWyllys Ingersoll static int
local_copy_file(char * dst,char * src)27747e946e7SWyllys Ingersoll local_copy_file(char *dst, char *src)
27847e946e7SWyllys Ingersoll {
27947e946e7SWyllys Ingersoll 	FILE *fdest, *fsrc;
28047e946e7SWyllys Ingersoll 	char line[BUFSIZ];
28147e946e7SWyllys Ingersoll 
28247e946e7SWyllys Ingersoll 	fdest = fopen(dst, "w");
28347e946e7SWyllys Ingersoll 	if (fdest == NULL)
28447e946e7SWyllys Ingersoll 		return (-1);
28547e946e7SWyllys Ingersoll 
28647e946e7SWyllys Ingersoll 	fsrc = fopen(src, "r");
28747e946e7SWyllys Ingersoll 	if (fsrc == NULL) {
28847e946e7SWyllys Ingersoll 		(void) fclose(fdest);
28947e946e7SWyllys Ingersoll 		return (-1);
29047e946e7SWyllys Ingersoll 	}
29147e946e7SWyllys Ingersoll 
29247e946e7SWyllys Ingersoll 	while (fread(line, sizeof (line), 1, fsrc))
29347e946e7SWyllys Ingersoll 		(void) fprintf(fdest, "%s\n", line);
29447e946e7SWyllys Ingersoll 	(void) fclose(fsrc);
29547e946e7SWyllys Ingersoll 	(void) fclose(fdest);
29647e946e7SWyllys Ingersoll 	return (0);
29747e946e7SWyllys Ingersoll }
29847e946e7SWyllys Ingersoll 
29947e946e7SWyllys Ingersoll static int
remove_uuid(char * keyname)30047e946e7SWyllys Ingersoll remove_uuid(char *keyname)
30147e946e7SWyllys Ingersoll {
30247e946e7SWyllys Ingersoll 	int ret = 0;
30347e946e7SWyllys Ingersoll 	FILE *fp, *newfp;
30447e946e7SWyllys Ingersoll 	char fname[MAXPATHLEN];
30547e946e7SWyllys Ingersoll 	char line[BUFSIZ], key[BUFSIZ], idstr[BUFSIZ];
30647e946e7SWyllys Ingersoll 	char *tmpfname;
30747e946e7SWyllys Ingersoll 	char *p = get_tpm_keystore_path();
30847e946e7SWyllys Ingersoll 
30947e946e7SWyllys Ingersoll 	if (p == NULL)
31047e946e7SWyllys Ingersoll 		return (-1);
31147e946e7SWyllys Ingersoll 
31247e946e7SWyllys Ingersoll 	(void) snprintf(fname, sizeof (fname),
31347e946e7SWyllys Ingersoll 	    "%s/%s", p, TPMTOK_UUID_INDEX_FILENAME);
31447e946e7SWyllys Ingersoll 
31547e946e7SWyllys Ingersoll 	fp = fopen(fname, "r");
31647e946e7SWyllys Ingersoll 	if (fp == NULL) {
31747e946e7SWyllys Ingersoll 		return (-1);
31847e946e7SWyllys Ingersoll 	}
31947e946e7SWyllys Ingersoll 
32047e946e7SWyllys Ingersoll 	tmpfname = tempnam("/tmp", "tpmtok");
32147e946e7SWyllys Ingersoll 	newfp = fopen(tmpfname, "w+");
32247e946e7SWyllys Ingersoll 	if (newfp == NULL) {
32347e946e7SWyllys Ingersoll 		free(tmpfname);
32447e946e7SWyllys Ingersoll 		(void) fclose(fp);
32547e946e7SWyllys Ingersoll 		return (-1);
32647e946e7SWyllys Ingersoll 	}
32747e946e7SWyllys Ingersoll 
32847e946e7SWyllys Ingersoll 	while (!feof(fp)) {
32947e946e7SWyllys Ingersoll 		(void) fgets(line, sizeof (line), fp);
33047e946e7SWyllys Ingersoll 		if (sscanf(line, "%1024s %1024s", key, idstr) == 2) {
33147e946e7SWyllys Ingersoll 			if (strcmp(key, keyname))
33247e946e7SWyllys Ingersoll 				(void) fprintf(newfp, "%s\n", line);
33347e946e7SWyllys Ingersoll 		}
33447e946e7SWyllys Ingersoll 	}
33547e946e7SWyllys Ingersoll 
33647e946e7SWyllys Ingersoll 	(void) fclose(fp);
33747e946e7SWyllys Ingersoll 	(void) fclose(newfp);
33847e946e7SWyllys Ingersoll 	if (local_copy_file(fname, tmpfname) == 0)
33947e946e7SWyllys Ingersoll 		(void) unlink(tmpfname);
34047e946e7SWyllys Ingersoll 
34147e946e7SWyllys Ingersoll 	free(tmpfname);
34247e946e7SWyllys Ingersoll 
34347e946e7SWyllys Ingersoll 	return (ret);
34447e946e7SWyllys Ingersoll }
34547e946e7SWyllys Ingersoll 
34647e946e7SWyllys Ingersoll static int
find_uuid(char * keyname,TSS_UUID * uu)34747e946e7SWyllys Ingersoll find_uuid(char *keyname, TSS_UUID *uu)
34847e946e7SWyllys Ingersoll {
34947e946e7SWyllys Ingersoll 	int ret = 0, found = 0;
35047e946e7SWyllys Ingersoll 	FILE *fp = NULL;
35147e946e7SWyllys Ingersoll 	char fname[MAXPATHLEN];
35247e946e7SWyllys Ingersoll 	char line[BUFSIZ], key[BUFSIZ], idstr[BUFSIZ];
35347e946e7SWyllys Ingersoll 	uuid_t uuid;
35447e946e7SWyllys Ingersoll 	char *p = get_tpm_keystore_path();
35547e946e7SWyllys Ingersoll 
35647e946e7SWyllys Ingersoll 	if (p == NULL)
35747e946e7SWyllys Ingersoll 		return (-1);
35847e946e7SWyllys Ingersoll 
35947e946e7SWyllys Ingersoll 	tss_uuid_convert_from(uu, uuid);
36047e946e7SWyllys Ingersoll 
36147e946e7SWyllys Ingersoll 	(void) snprintf(fname, sizeof (fname),
36247e946e7SWyllys Ingersoll 	    "%s/%s", p, TPMTOK_UUID_INDEX_FILENAME);
36347e946e7SWyllys Ingersoll 
36447e946e7SWyllys Ingersoll 	/* Open UUID Index file */
36547e946e7SWyllys Ingersoll 	fp = fopen(fname, "r");
36647e946e7SWyllys Ingersoll 	if (fp == NULL) {
36747e946e7SWyllys Ingersoll 		if (errno == ENOENT) {
36847e946e7SWyllys Ingersoll 			/* initialize the file */
36947e946e7SWyllys Ingersoll 			fp = fopen(fname, "w");
37047e946e7SWyllys Ingersoll 			if (fp != NULL)
37147e946e7SWyllys Ingersoll 				(void) fclose(fp);
37247e946e7SWyllys Ingersoll 		}
37347e946e7SWyllys Ingersoll 		return (-1);
37447e946e7SWyllys Ingersoll 	}
37547e946e7SWyllys Ingersoll 
37647e946e7SWyllys Ingersoll 	while (!feof(fp)) {
37747e946e7SWyllys Ingersoll 		(void) fgets(line, sizeof (line), fp);
37847e946e7SWyllys Ingersoll 		if (sscanf(line, "%1024s %1024s", key, idstr) == 2) {
37947e946e7SWyllys Ingersoll 			if (strcmp(key, keyname) == 0) {
38047e946e7SWyllys Ingersoll 				ret = uuid_parse(idstr, uuid);
38147e946e7SWyllys Ingersoll 				if (ret == 0) {
38247e946e7SWyllys Ingersoll 					found = 1;
38347e946e7SWyllys Ingersoll 					tss_uuid_convert_to(uu,
38447e946e7SWyllys Ingersoll 					    uuid);
38547e946e7SWyllys Ingersoll 				}
38647e946e7SWyllys Ingersoll 				break;
38747e946e7SWyllys Ingersoll 			}
38847e946e7SWyllys Ingersoll 		}
38947e946e7SWyllys Ingersoll 	}
39047e946e7SWyllys Ingersoll 	(void) fclose(fp);
39147e946e7SWyllys Ingersoll 
39247e946e7SWyllys Ingersoll 	if (!found)
39347e946e7SWyllys Ingersoll 		ret = -1;
39447e946e7SWyllys Ingersoll 	return (ret);
39547e946e7SWyllys Ingersoll }
39647e946e7SWyllys Ingersoll 
39747e946e7SWyllys Ingersoll static int
local_uuid_is_null(TSS_UUID * uu)39847e946e7SWyllys Ingersoll local_uuid_is_null(TSS_UUID *uu)
39947e946e7SWyllys Ingersoll {
40047e946e7SWyllys Ingersoll 	uuid_t uuid;
40147e946e7SWyllys Ingersoll 	int nulluuid;
40247e946e7SWyllys Ingersoll 
40347e946e7SWyllys Ingersoll 	tss_uuid_convert_from(uu, uuid);
40447e946e7SWyllys Ingersoll 
40547e946e7SWyllys Ingersoll 	nulluuid = uuid_is_null(uuid);
40647e946e7SWyllys Ingersoll 	return (nulluuid);
40747e946e7SWyllys Ingersoll }
40847e946e7SWyllys Ingersoll 
40947e946e7SWyllys Ingersoll static int
add_uuid(char * keyname,TSS_UUID * uu)41047e946e7SWyllys Ingersoll add_uuid(char *keyname, TSS_UUID *uu)
41147e946e7SWyllys Ingersoll {
41247e946e7SWyllys Ingersoll 	FILE *fp = NULL;
41347e946e7SWyllys Ingersoll 	char fname[MAXPATHLEN];
41447e946e7SWyllys Ingersoll 	char idstr[BUFSIZ];
41547e946e7SWyllys Ingersoll 	uuid_t uuid;
41647e946e7SWyllys Ingersoll 	char *p = get_tpm_keystore_path();
41747e946e7SWyllys Ingersoll 
41847e946e7SWyllys Ingersoll 	if (p == NULL)
41947e946e7SWyllys Ingersoll 		return (-1);
42047e946e7SWyllys Ingersoll 
42147e946e7SWyllys Ingersoll 	tss_uuid_convert_from(uu, uuid);
42247e946e7SWyllys Ingersoll 
42347e946e7SWyllys Ingersoll 	if (uuid_is_null(uuid))
42447e946e7SWyllys Ingersoll 		return (-1);
42547e946e7SWyllys Ingersoll 
42647e946e7SWyllys Ingersoll 	uuid_unparse(uuid, idstr);
42747e946e7SWyllys Ingersoll 
42847e946e7SWyllys Ingersoll 	(void) snprintf(fname, sizeof (fname),
42947e946e7SWyllys Ingersoll 	    "%s/%s", p, TPMTOK_UUID_INDEX_FILENAME);
43047e946e7SWyllys Ingersoll 
43147e946e7SWyllys Ingersoll 	fp = fopen(fname, "a");
43247e946e7SWyllys Ingersoll 	if (fp == NULL)
43347e946e7SWyllys Ingersoll 		return (-1);
43447e946e7SWyllys Ingersoll 
43547e946e7SWyllys Ingersoll 	(void) fprintf(fp, "%s %s\n", keyname, idstr);
43647e946e7SWyllys Ingersoll 	(void) fclose(fp);
43747e946e7SWyllys Ingersoll 
43847e946e7SWyllys Ingersoll 	return (0);
43947e946e7SWyllys Ingersoll }
44047e946e7SWyllys Ingersoll 
44147e946e7SWyllys Ingersoll 
44247e946e7SWyllys Ingersoll static UINT32
util_get_keysize_flag(CK_ULONG size)44347e946e7SWyllys Ingersoll util_get_keysize_flag(CK_ULONG size)
44447e946e7SWyllys Ingersoll {
44547e946e7SWyllys Ingersoll 	switch (size) {
44647e946e7SWyllys Ingersoll 		case 512:
44747e946e7SWyllys Ingersoll 			return (TSS_KEY_SIZE_512);
44847e946e7SWyllys Ingersoll 		case 1024:
44947e946e7SWyllys Ingersoll 			return (TSS_KEY_SIZE_1024);
45047e946e7SWyllys Ingersoll 		case 2048:
45147e946e7SWyllys Ingersoll 			return (TSS_KEY_SIZE_2048);
45247e946e7SWyllys Ingersoll 		default:
45347e946e7SWyllys Ingersoll 			break;
45447e946e7SWyllys Ingersoll 	}
45547e946e7SWyllys Ingersoll 
45647e946e7SWyllys Ingersoll 	return (0);
45747e946e7SWyllys Ingersoll }
45847e946e7SWyllys Ingersoll 
45947e946e7SWyllys Ingersoll /* make sure the public exponent attribute is 65537 */
46047e946e7SWyllys Ingersoll static CK_ULONG
util_check_public_exponent(TEMPLATE * tmpl)46147e946e7SWyllys Ingersoll util_check_public_exponent(TEMPLATE *tmpl)
46247e946e7SWyllys Ingersoll {
46347e946e7SWyllys Ingersoll 	CK_BBOOL flag;
46447e946e7SWyllys Ingersoll 	CK_ATTRIBUTE *publ_exp_attr;
46547e946e7SWyllys Ingersoll 	CK_BYTE pubexp_bytes[] = { 1, 0, 1 };
46647e946e7SWyllys Ingersoll 	CK_ULONG publ_exp, rc = 1;
46747e946e7SWyllys Ingersoll 
46847e946e7SWyllys Ingersoll 	flag = template_attribute_find(tmpl, CKA_PUBLIC_EXPONENT,
46947e946e7SWyllys Ingersoll 	    &publ_exp_attr);
47047e946e7SWyllys Ingersoll 	if (!flag) {
47147e946e7SWyllys Ingersoll 		LogError1("Couldn't find public exponent attribute");
47247e946e7SWyllys Ingersoll 		return (CKR_TEMPLATE_INCOMPLETE);
47347e946e7SWyllys Ingersoll 	}
47447e946e7SWyllys Ingersoll 
47547e946e7SWyllys Ingersoll 	switch (publ_exp_attr->ulValueLen) {
47647e946e7SWyllys Ingersoll 		case 3:
47747e946e7SWyllys Ingersoll 			rc = memcmp(pubexp_bytes, publ_exp_attr->pValue, 3);
47847e946e7SWyllys Ingersoll 			break;
47947e946e7SWyllys Ingersoll 		case sizeof (CK_ULONG):
48047e946e7SWyllys Ingersoll 			publ_exp = *((CK_ULONG *)publ_exp_attr->pValue);
48147e946e7SWyllys Ingersoll 			if (publ_exp == 65537)
48247e946e7SWyllys Ingersoll 				rc = 0;
48347e946e7SWyllys Ingersoll 			break;
48447e946e7SWyllys Ingersoll 		default:
48547e946e7SWyllys Ingersoll 			break;
48647e946e7SWyllys Ingersoll 	}
48747e946e7SWyllys Ingersoll 
48847e946e7SWyllys Ingersoll 	return (rc);
48947e946e7SWyllys Ingersoll }
49047e946e7SWyllys Ingersoll 
49147e946e7SWyllys Ingersoll TSS_RESULT
set_public_modulus(TSS_HCONTEXT hContext,TSS_HKEY hKey,unsigned long size_n,unsigned char * n)49247e946e7SWyllys Ingersoll set_public_modulus(TSS_HCONTEXT hContext, TSS_HKEY hKey,
49347e946e7SWyllys Ingersoll 	unsigned long size_n, unsigned char *n)
49447e946e7SWyllys Ingersoll {
49547e946e7SWyllys Ingersoll 	UINT64 offset;
49647e946e7SWyllys Ingersoll 	UINT32 blob_size;
49747e946e7SWyllys Ingersoll 	BYTE *blob, pub_blob[1024];
49847e946e7SWyllys Ingersoll 	TCPA_PUBKEY pub_key;
49947e946e7SWyllys Ingersoll 	TSS_RESULT result;
50047e946e7SWyllys Ingersoll 
50147e946e7SWyllys Ingersoll 	/* Get the TCPA_PUBKEY blob from the key object. */
50247e946e7SWyllys Ingersoll 	result = Tspi_GetAttribData(hKey, TSS_TSPATTRIB_KEY_BLOB,
50347e946e7SWyllys Ingersoll 	    TSS_TSPATTRIB_KEYBLOB_PUBLIC_KEY, &blob_size, &blob);
50447e946e7SWyllys Ingersoll 	if (result != TSS_SUCCESS) {
50547e946e7SWyllys Ingersoll 		stlogit("Tspi_GetAttribData failed: rc=0x%0x - %s\n",
50647e946e7SWyllys Ingersoll 		    result, Trspi_Error_String(result));
50747e946e7SWyllys Ingersoll 		return (result);
50847e946e7SWyllys Ingersoll 	}
50947e946e7SWyllys Ingersoll 
51047e946e7SWyllys Ingersoll 	offset = 0;
51147e946e7SWyllys Ingersoll 	result = Trspi_UnloadBlob_PUBKEY(&offset, blob, &pub_key);
51247e946e7SWyllys Ingersoll 	if (result != TSS_SUCCESS) {
51347e946e7SWyllys Ingersoll 		stlogit("Trspi_UnloadBlob_PUBKEY failed: rc=0x%0x - %s\n",
51447e946e7SWyllys Ingersoll 		    result, Trspi_Error_String(result));
51547e946e7SWyllys Ingersoll 		return (result);
51647e946e7SWyllys Ingersoll 	}
51747e946e7SWyllys Ingersoll 
51847e946e7SWyllys Ingersoll 	Tspi_Context_FreeMemory(hContext, blob);
51947e946e7SWyllys Ingersoll 	/* Free the first dangling reference, putting 'n' in its place */
52047e946e7SWyllys Ingersoll 	free(pub_key.pubKey.key);
52147e946e7SWyllys Ingersoll 	pub_key.pubKey.keyLength = size_n;
52247e946e7SWyllys Ingersoll 	pub_key.pubKey.key = n;
52347e946e7SWyllys Ingersoll 
52447e946e7SWyllys Ingersoll 	offset = 0;
52547e946e7SWyllys Ingersoll 	Trspi_LoadBlob_PUBKEY(&offset, pub_blob, &pub_key);
52647e946e7SWyllys Ingersoll 
52747e946e7SWyllys Ingersoll 	/* Free the second dangling reference */
52847e946e7SWyllys Ingersoll 	free(pub_key.algorithmParms.parms);
52947e946e7SWyllys Ingersoll 
53047e946e7SWyllys Ingersoll 	/* set the public key data in the TSS object */
53147e946e7SWyllys Ingersoll 	result = Tspi_SetAttribData(hKey, TSS_TSPATTRIB_KEY_BLOB,
53247e946e7SWyllys Ingersoll 	    TSS_TSPATTRIB_KEYBLOB_PUBLIC_KEY, (UINT32)offset, pub_blob);
53347e946e7SWyllys Ingersoll 	if (result != TSS_SUCCESS) {
53447e946e7SWyllys Ingersoll 		stlogit("Tspi_SetAttribData failed: rc=0x%0x - %s\n",
53547e946e7SWyllys Ingersoll 		    result, Trspi_Error_String(result));
53647e946e7SWyllys Ingersoll 		return (result);
53747e946e7SWyllys Ingersoll 	}
53847e946e7SWyllys Ingersoll 
53947e946e7SWyllys Ingersoll 	return (result);
54047e946e7SWyllys Ingersoll }
54147e946e7SWyllys Ingersoll 
54247e946e7SWyllys Ingersoll /*
54347e946e7SWyllys Ingersoll  * Get details about the TPM to put into the token_info structure.
54447e946e7SWyllys Ingersoll  */
54547e946e7SWyllys Ingersoll CK_RV
token_get_tpm_info(TSS_HCONTEXT hContext,TOKEN_DATA * td)54647e946e7SWyllys Ingersoll token_get_tpm_info(TSS_HCONTEXT hContext, TOKEN_DATA *td)
54747e946e7SWyllys Ingersoll {
54847e946e7SWyllys Ingersoll 	TSS_RESULT result;
54947e946e7SWyllys Ingersoll 	TPM_CAPABILITY_AREA capArea = TSS_TPMCAP_VERSION_VAL;
55047e946e7SWyllys Ingersoll 	UINT32 datalen;
55147e946e7SWyllys Ingersoll 	BYTE *data;
55247e946e7SWyllys Ingersoll 	TSS_HTPM hTPM;
55347e946e7SWyllys Ingersoll 
55447e946e7SWyllys Ingersoll 	if ((result = Tspi_Context_GetTpmObject(hContext, &hTPM))) {
55547e946e7SWyllys Ingersoll 		stlogit("Tspi_Context_GetTpmObject: 0x%0x - %s",
55647e946e7SWyllys Ingersoll 		    result, Trspi_Error_String(result));
55747e946e7SWyllys Ingersoll 		return (CKR_FUNCTION_FAILED);
55847e946e7SWyllys Ingersoll 	}
55947e946e7SWyllys Ingersoll 	if ((result = Tspi_TPM_GetCapability(hTPM,
56047e946e7SWyllys Ingersoll 	    capArea, 0, NULL, &datalen, &data)) != 0 || datalen == 0 ||
56147e946e7SWyllys Ingersoll 	    data == NULL) {
56247e946e7SWyllys Ingersoll 		stlogit("Tspi_Context_GetCapability: 0x%0x - %s",
56347e946e7SWyllys Ingersoll 		    result, Trspi_Error_String(result));
56447e946e7SWyllys Ingersoll 		return (CKR_FUNCTION_FAILED);
56547e946e7SWyllys Ingersoll 	}
56647e946e7SWyllys Ingersoll 	if (datalen > sizeof (tpmvinfo)) {
56747e946e7SWyllys Ingersoll 		Tspi_Context_FreeMemory(hContext, data);
56847e946e7SWyllys Ingersoll 		return (CKR_FUNCTION_FAILED);
56947e946e7SWyllys Ingersoll 	}
57047e946e7SWyllys Ingersoll 
5711dc1cb45SWyllys Ingersoll 	(void) memcpy(&tpmvinfo, (void *)data, datalen);
57247e946e7SWyllys Ingersoll 
57347e946e7SWyllys Ingersoll 	bzero(td->token_info.manufacturerID,
57447e946e7SWyllys Ingersoll 	    sizeof (td->token_info.manufacturerID));
57547e946e7SWyllys Ingersoll 
57647e946e7SWyllys Ingersoll 	(void) memset(td->token_info.manufacturerID,  ' ',
57747e946e7SWyllys Ingersoll 	    sizeof (td->token_info.manufacturerID) - 1);
5781dc1cb45SWyllys Ingersoll 
57947e946e7SWyllys Ingersoll 	(void) memcpy(td->token_info.manufacturerID,
58047e946e7SWyllys Ingersoll 	    tpmvinfo.tpmVendorID, sizeof (tpmvinfo.tpmVendorID));
58147e946e7SWyllys Ingersoll 
58247e946e7SWyllys Ingersoll 	(void) memset(td->token_info.label, ' ',
58347e946e7SWyllys Ingersoll 	    sizeof (td->token_info.label) - 1);
5841dc1cb45SWyllys Ingersoll 
5851dc1cb45SWyllys Ingersoll 	(void) memcpy(td->token_info.label, "TPM", 3);
58647e946e7SWyllys Ingersoll 
58747e946e7SWyllys Ingersoll 	td->token_info.hardwareVersion.major = tpmvinfo.version.major;
58847e946e7SWyllys Ingersoll 	td->token_info.hardwareVersion.minor = tpmvinfo.version.minor;
58947e946e7SWyllys Ingersoll 	td->token_info.firmwareVersion.major = tpmvinfo.version.revMajor;
59047e946e7SWyllys Ingersoll 	td->token_info.firmwareVersion.minor = tpmvinfo.version.revMinor;
59147e946e7SWyllys Ingersoll 
59247e946e7SWyllys Ingersoll 	Tspi_Context_FreeMemory(hContext, data);
59347e946e7SWyllys Ingersoll 	return (CKR_OK);
59447e946e7SWyllys Ingersoll }
59547e946e7SWyllys Ingersoll 
59647e946e7SWyllys Ingersoll /*ARGSUSED*/
59747e946e7SWyllys Ingersoll CK_RV
token_specific_session(CK_SLOT_ID slotid)59847e946e7SWyllys Ingersoll token_specific_session(CK_SLOT_ID  slotid)
59947e946e7SWyllys Ingersoll {
60047e946e7SWyllys Ingersoll 	return (CKR_OK);
60147e946e7SWyllys Ingersoll }
60247e946e7SWyllys Ingersoll 
60347e946e7SWyllys Ingersoll CK_RV
token_rng(TSS_HCONTEXT hContext,CK_BYTE * output,CK_ULONG bytes)60447e946e7SWyllys Ingersoll token_rng(TSS_HCONTEXT hContext, CK_BYTE *output, CK_ULONG bytes)
60547e946e7SWyllys Ingersoll {
60647e946e7SWyllys Ingersoll 	TSS_RESULT rc;
60747e946e7SWyllys Ingersoll 	TSS_HTPM hTPM;
60847e946e7SWyllys Ingersoll 	BYTE *random_bytes = NULL;
60947e946e7SWyllys Ingersoll 
61047e946e7SWyllys Ingersoll 	if ((rc = Tspi_Context_GetTpmObject(hContext, &hTPM))) {
61147e946e7SWyllys Ingersoll 		stlogit("Tspi_Context_GetTpmObject: 0x%0x - %s",
61247e946e7SWyllys Ingersoll 		    rc, Trspi_Error_String(rc));
61347e946e7SWyllys Ingersoll 		return (CKR_FUNCTION_FAILED);
61447e946e7SWyllys Ingersoll 	}
61547e946e7SWyllys Ingersoll 
61647e946e7SWyllys Ingersoll 	if ((rc = Tspi_TPM_GetRandom(hTPM, bytes, &random_bytes))) {
61747e946e7SWyllys Ingersoll 		stlogit("Tspi_TPM_GetRandom: 0x%0x - %s",
61847e946e7SWyllys Ingersoll 		    rc, Trspi_Error_String(rc));
61947e946e7SWyllys Ingersoll 		return (CKR_FUNCTION_FAILED);
62047e946e7SWyllys Ingersoll 	}
62147e946e7SWyllys Ingersoll 
62247e946e7SWyllys Ingersoll 	(void) memcpy(output, random_bytes, bytes);
62347e946e7SWyllys Ingersoll 	Tspi_Context_FreeMemory(hContext, random_bytes);
62447e946e7SWyllys Ingersoll 
62547e946e7SWyllys Ingersoll 	return (CKR_OK);
62647e946e7SWyllys Ingersoll }
62747e946e7SWyllys Ingersoll 
62847e946e7SWyllys Ingersoll TSS_RESULT
open_tss_context(TSS_HCONTEXT * pContext)62947e946e7SWyllys Ingersoll open_tss_context(TSS_HCONTEXT *pContext)
63047e946e7SWyllys Ingersoll {
63147e946e7SWyllys Ingersoll 	TSS_RESULT result;
63247e946e7SWyllys Ingersoll 
63347e946e7SWyllys Ingersoll 	if ((result = Tspi_Context_Create(pContext))) {
63447e946e7SWyllys Ingersoll 		stlogit("Tspi_Context_Create: 0x%0x - %s",
63547e946e7SWyllys Ingersoll 		    result, Trspi_Error_String(result));
63647e946e7SWyllys Ingersoll 		return (CKR_FUNCTION_FAILED);
63747e946e7SWyllys Ingersoll 	}
63847e946e7SWyllys Ingersoll 
63947e946e7SWyllys Ingersoll 	if ((result = Tspi_Context_Connect(*pContext, NULL))) {
64047e946e7SWyllys Ingersoll 		stlogit("Tspi_Context_Connect: 0x%0x - %s",
64147e946e7SWyllys Ingersoll 		    result, Trspi_Error_String(result));
6428932b28eSWyllys Ingersoll 		Tspi_Context_Close(*pContext);
6438932b28eSWyllys Ingersoll 		*pContext = 0;
64447e946e7SWyllys Ingersoll 		return (CKR_FUNCTION_FAILED);
64547e946e7SWyllys Ingersoll 	}
64647e946e7SWyllys Ingersoll 	return (result);
64747e946e7SWyllys Ingersoll }
64847e946e7SWyllys Ingersoll 
64947e946e7SWyllys Ingersoll /*ARGSUSED*/
65047e946e7SWyllys Ingersoll static CK_RV
token_specific_init(char * Correlator,CK_SLOT_ID SlotNumber,TSS_HCONTEXT * hContext)65147e946e7SWyllys Ingersoll token_specific_init(char *Correlator, CK_SLOT_ID SlotNumber,
65247e946e7SWyllys Ingersoll     TSS_HCONTEXT *hContext)
65347e946e7SWyllys Ingersoll {
65447e946e7SWyllys Ingersoll 	TSS_RESULT result;
65547e946e7SWyllys Ingersoll 
65647e946e7SWyllys Ingersoll 	result = open_tss_context(hContext);
65747e946e7SWyllys Ingersoll 	if (result)
65847e946e7SWyllys Ingersoll 		return (CKR_FUNCTION_FAILED);
65947e946e7SWyllys Ingersoll 
66047e946e7SWyllys Ingersoll 	if ((result = Tspi_Context_GetDefaultPolicy(*hContext,
66147e946e7SWyllys Ingersoll 	    &hDefaultPolicy))) {
66247e946e7SWyllys Ingersoll 		stlogit("Tspi_Context_GetDefaultPolicy: 0x%0x - %s",
66347e946e7SWyllys Ingersoll 		    result, Trspi_Error_String(result));
66447e946e7SWyllys Ingersoll 		return (CKR_FUNCTION_FAILED);
66547e946e7SWyllys Ingersoll 	}
66647e946e7SWyllys Ingersoll 
66747e946e7SWyllys Ingersoll 	local_uuid_clear(&publicRootKeyUUID);
66847e946e7SWyllys Ingersoll 	local_uuid_clear(&privateRootKeyUUID);
66947e946e7SWyllys Ingersoll 	local_uuid_clear(&publicLeafKeyUUID);
67047e946e7SWyllys Ingersoll 	local_uuid_clear(&privateLeafKeyUUID);
67147e946e7SWyllys Ingersoll 
67247e946e7SWyllys Ingersoll 	result = token_get_tpm_info(*hContext, nv_token_data);
67347e946e7SWyllys Ingersoll 	return (result);
67447e946e7SWyllys Ingersoll }
67547e946e7SWyllys Ingersoll 
67647e946e7SWyllys Ingersoll /*
67747e946e7SWyllys Ingersoll  * Given a modulus and prime from an RSA key, create a TSS_HKEY object by
67847e946e7SWyllys Ingersoll  * wrapping the RSA key with a key from the TPM (SRK or other previously stored
67947e946e7SWyllys Ingersoll  * key).
68047e946e7SWyllys Ingersoll  */
68147e946e7SWyllys Ingersoll static CK_RV
token_wrap_sw_key(TSS_HCONTEXT hContext,int size_n,unsigned char * n,int size_p,unsigned char * p,TSS_HKEY hParentKey,TSS_FLAG initFlags,TSS_HKEY * phKey)68247e946e7SWyllys Ingersoll token_wrap_sw_key(
68347e946e7SWyllys Ingersoll 	TSS_HCONTEXT hContext,
68447e946e7SWyllys Ingersoll 	int size_n,
68547e946e7SWyllys Ingersoll 	unsigned char *n,
68647e946e7SWyllys Ingersoll 	int size_p,
68747e946e7SWyllys Ingersoll 	unsigned char *p,
68847e946e7SWyllys Ingersoll 	TSS_HKEY hParentKey,
68947e946e7SWyllys Ingersoll 	TSS_FLAG initFlags,
69047e946e7SWyllys Ingersoll 	TSS_HKEY *phKey)
69147e946e7SWyllys Ingersoll {
69247e946e7SWyllys Ingersoll 	TSS_RESULT result;
69347e946e7SWyllys Ingersoll 	UINT32 key_size;
69447e946e7SWyllys Ingersoll 
69547e946e7SWyllys Ingersoll 	key_size = util_get_keysize_flag(size_n * 8);
69647e946e7SWyllys Ingersoll 	if (initFlags == 0) {
69747e946e7SWyllys Ingersoll 		return (CKR_FUNCTION_FAILED);
69847e946e7SWyllys Ingersoll 	}
69947e946e7SWyllys Ingersoll 
70047e946e7SWyllys Ingersoll 	/* create the TSS key object */
70147e946e7SWyllys Ingersoll 	result = Tspi_Context_CreateObject(hContext, TSS_OBJECT_TYPE_RSAKEY,
70247e946e7SWyllys Ingersoll 	    TSS_KEY_MIGRATABLE | initFlags | key_size, phKey);
70347e946e7SWyllys Ingersoll 	if (result != TSS_SUCCESS) {
70447e946e7SWyllys Ingersoll 		stlogit("Tspi_Context_CreateObject: 0x%0x - %s",
70547e946e7SWyllys Ingersoll 		    result, Trspi_Error_String(result));
70647e946e7SWyllys Ingersoll 		return (CKR_FUNCTION_FAILED);
70747e946e7SWyllys Ingersoll 	}
70847e946e7SWyllys Ingersoll 
70947e946e7SWyllys Ingersoll 	result = set_public_modulus(hContext, *phKey, size_n, n);
71047e946e7SWyllys Ingersoll 	if (result != TSS_SUCCESS) {
71147e946e7SWyllys Ingersoll 		Tspi_Context_CloseObject(hContext, *phKey);
71247e946e7SWyllys Ingersoll 		*phKey = NULL_HKEY;
71347e946e7SWyllys Ingersoll 		return (CKR_FUNCTION_FAILED);
71447e946e7SWyllys Ingersoll 	}
71547e946e7SWyllys Ingersoll 
71647e946e7SWyllys Ingersoll 	/* set the private key data in the TSS object */
71747e946e7SWyllys Ingersoll 	result = Tspi_SetAttribData(*phKey, TSS_TSPATTRIB_KEY_BLOB,
71847e946e7SWyllys Ingersoll 	    TSS_TSPATTRIB_KEYBLOB_PRIVATE_KEY, size_p, p);
71947e946e7SWyllys Ingersoll 	if (result != TSS_SUCCESS) {
72047e946e7SWyllys Ingersoll 		stlogit("Tspi_SetAttribData: 0x%x - %s",
72147e946e7SWyllys Ingersoll 		    result, Trspi_Error_String(result));
72247e946e7SWyllys Ingersoll 		Tspi_Context_CloseObject(hContext, *phKey);
72347e946e7SWyllys Ingersoll 		*phKey = NULL_HKEY;
72447e946e7SWyllys Ingersoll 		return (CKR_FUNCTION_FAILED);
72547e946e7SWyllys Ingersoll 	}
72647e946e7SWyllys Ingersoll 
727ab8176c2SWyllys Ingersoll 	result = tss_assign_secret_key_policy(hContext, TSS_POLICY_MIGRATION,
728ab8176c2SWyllys Ingersoll 	    *phKey, NULL);
72947e946e7SWyllys Ingersoll 
73047e946e7SWyllys Ingersoll 	if (TPMTOK_TSS_KEY_TYPE(initFlags) == TSS_KEY_TYPE_LEGACY) {
73147e946e7SWyllys Ingersoll 		if ((result = Tspi_SetAttribUint32(*phKey,
73247e946e7SWyllys Ingersoll 		    TSS_TSPATTRIB_KEY_INFO, TSS_TSPATTRIB_KEYINFO_ENCSCHEME,
73347e946e7SWyllys Ingersoll 		    TSS_ES_RSAESPKCSV15))) {
73447e946e7SWyllys Ingersoll 			stlogit("Tspi_SetAttribUint32: 0x%0x - %s\n",
73547e946e7SWyllys Ingersoll 			    result, Trspi_Error_String(result));
73647e946e7SWyllys Ingersoll 			Tspi_Context_CloseObject(hContext, *phKey);
73747e946e7SWyllys Ingersoll 			return (CKR_FUNCTION_FAILED);
73847e946e7SWyllys Ingersoll 		}
73947e946e7SWyllys Ingersoll 
74047e946e7SWyllys Ingersoll 		if ((result = Tspi_SetAttribUint32(*phKey,
74147e946e7SWyllys Ingersoll 		    TSS_TSPATTRIB_KEY_INFO, TSS_TSPATTRIB_KEYINFO_SIGSCHEME,
74247e946e7SWyllys Ingersoll 		    TSS_SS_RSASSAPKCS1V15_DER))) {
74347e946e7SWyllys Ingersoll 			stlogit("Tspi_SetAttribUint32: 0x%0x - %s\n",
74447e946e7SWyllys Ingersoll 			    result, Trspi_Error_String(result));
74547e946e7SWyllys Ingersoll 			Tspi_Context_CloseObject(hContext, *phKey);
74647e946e7SWyllys Ingersoll 			return (CKR_FUNCTION_FAILED);
74747e946e7SWyllys Ingersoll 		}
74847e946e7SWyllys Ingersoll 	}
74947e946e7SWyllys Ingersoll 
75047e946e7SWyllys Ingersoll 	result = Tspi_Key_WrapKey(*phKey, hParentKey, NULL_HPCRS);
75147e946e7SWyllys Ingersoll 	if (result != TSS_SUCCESS) {
75247e946e7SWyllys Ingersoll 		stlogit("Tspi_Key_WrapKey: 0x%0x - %s",
75347e946e7SWyllys Ingersoll 		    result, Trspi_Error_String(result));
75447e946e7SWyllys Ingersoll 		Tspi_Context_CloseObject(hContext, *phKey);
75547e946e7SWyllys Ingersoll 		*phKey = NULL_HKEY;
75647e946e7SWyllys Ingersoll 		return (CKR_FUNCTION_FAILED);
75747e946e7SWyllys Ingersoll 	}
75847e946e7SWyllys Ingersoll 
75947e946e7SWyllys Ingersoll 	return (CKR_OK);
76047e946e7SWyllys Ingersoll }
76147e946e7SWyllys Ingersoll 
76247e946e7SWyllys Ingersoll /*
76347e946e7SWyllys Ingersoll  * Create a TPM key blob for an imported key. This function is only called when
76447e946e7SWyllys Ingersoll  * a key is in active use, so any failure should trickle through.
76547e946e7SWyllys Ingersoll  */
76647e946e7SWyllys Ingersoll static CK_RV
token_wrap_key_object(TSS_HCONTEXT hContext,CK_OBJECT_HANDLE ckObject,TSS_HKEY hParentKey,TSS_HKEY * phKey)76747e946e7SWyllys Ingersoll token_wrap_key_object(TSS_HCONTEXT hContext,
76847e946e7SWyllys Ingersoll 	CK_OBJECT_HANDLE ckObject,
76947e946e7SWyllys Ingersoll 	TSS_HKEY hParentKey, TSS_HKEY *phKey)
77047e946e7SWyllys Ingersoll {
77147e946e7SWyllys Ingersoll 	CK_RV		rc = CKR_OK;
77247e946e7SWyllys Ingersoll 	CK_ATTRIBUTE	*attr = NULL, *new_attr, *prime_attr;
77347e946e7SWyllys Ingersoll 	CK_ULONG	class, key_type;
77447e946e7SWyllys Ingersoll 	OBJECT		*obj;
77547e946e7SWyllys Ingersoll 
77647e946e7SWyllys Ingersoll 	TSS_RESULT	result;
77747e946e7SWyllys Ingersoll 	TSS_FLAG	initFlags = 0;
77847e946e7SWyllys Ingersoll 	BYTE		*rgbBlob;
77947e946e7SWyllys Ingersoll 	UINT32		ulBlobLen;
78047e946e7SWyllys Ingersoll 
78147e946e7SWyllys Ingersoll 	if ((rc = object_mgr_find_in_map1(hContext, ckObject, &obj))) {
78247e946e7SWyllys Ingersoll 		return (rc);
78347e946e7SWyllys Ingersoll 	}
78447e946e7SWyllys Ingersoll 
78547e946e7SWyllys Ingersoll 	/* if the object isn't a key, fail */
78647e946e7SWyllys Ingersoll 	if (template_attribute_find(obj->template, CKA_KEY_TYPE,
78747e946e7SWyllys Ingersoll 	    &attr) == FALSE) {
78847e946e7SWyllys Ingersoll 		return (CKR_TEMPLATE_INCOMPLETE);
78947e946e7SWyllys Ingersoll 	}
79047e946e7SWyllys Ingersoll 
79147e946e7SWyllys Ingersoll 	key_type = *((CK_ULONG *)attr->pValue);
79247e946e7SWyllys Ingersoll 
79347e946e7SWyllys Ingersoll 	if (key_type != CKK_RSA) {
79447e946e7SWyllys Ingersoll 		return (CKR_TEMPLATE_INCONSISTENT);
79547e946e7SWyllys Ingersoll 	}
79647e946e7SWyllys Ingersoll 
79747e946e7SWyllys Ingersoll 	if (template_attribute_find(obj->template, CKA_CLASS,
79847e946e7SWyllys Ingersoll 	    &attr) == FALSE) {
79947e946e7SWyllys Ingersoll 		return (CKR_TEMPLATE_INCOMPLETE);
80047e946e7SWyllys Ingersoll 	}
80147e946e7SWyllys Ingersoll 
80247e946e7SWyllys Ingersoll 	class = *((CK_ULONG *)attr->pValue);
80347e946e7SWyllys Ingersoll 
80447e946e7SWyllys Ingersoll 	if (class == CKO_PRIVATE_KEY) {
80547e946e7SWyllys Ingersoll 		/*
80647e946e7SWyllys Ingersoll 		 * In order to create a full TSS key blob using a PKCS#11
80747e946e7SWyllys Ingersoll 		 * private key object, we need one of the two primes, the
80847e946e7SWyllys Ingersoll 		 * modulus and the private exponent and we need the public
80947e946e7SWyllys Ingersoll 		 * exponent to be correct.
81047e946e7SWyllys Ingersoll 		 */
81147e946e7SWyllys Ingersoll 
81247e946e7SWyllys Ingersoll 		/*
81347e946e7SWyllys Ingersoll 		 * Check the least likely attribute to exist first, the
81447e946e7SWyllys Ingersoll 		 * primes.
81547e946e7SWyllys Ingersoll 		 */
81647e946e7SWyllys Ingersoll 		if (template_attribute_find(obj->template, CKA_PRIME_1,
81747e946e7SWyllys Ingersoll 		    &prime_attr) == FALSE) {
81847e946e7SWyllys Ingersoll 			if (template_attribute_find(obj->template,
81947e946e7SWyllys Ingersoll 			    CKA_PRIME_2, &prime_attr) == FALSE) {
82047e946e7SWyllys Ingersoll 				return (CKR_TEMPLATE_INCOMPLETE);
82147e946e7SWyllys Ingersoll 			}
82247e946e7SWyllys Ingersoll 		}
82347e946e7SWyllys Ingersoll 
82447e946e7SWyllys Ingersoll 		/* Make sure the public exponent is usable */
82547e946e7SWyllys Ingersoll 		if ((rc = util_check_public_exponent(obj->template))) {
82647e946e7SWyllys Ingersoll 			return (CKR_TEMPLATE_INCONSISTENT);
82747e946e7SWyllys Ingersoll 		}
82847e946e7SWyllys Ingersoll 
82947e946e7SWyllys Ingersoll 		/* get the modulus */
83047e946e7SWyllys Ingersoll 		if (template_attribute_find(obj->template, CKA_MODULUS,
83147e946e7SWyllys Ingersoll 		    &attr) == FALSE) {
83247e946e7SWyllys Ingersoll 			return (CKR_TEMPLATE_INCOMPLETE);
83347e946e7SWyllys Ingersoll 		}
83447e946e7SWyllys Ingersoll 
83547e946e7SWyllys Ingersoll 		/* make sure the key size is usable */
83647e946e7SWyllys Ingersoll 		initFlags = util_get_keysize_flag(attr->ulValueLen * 8);
83747e946e7SWyllys Ingersoll 		if (initFlags == 0) {
83847e946e7SWyllys Ingersoll 			return (CKR_TEMPLATE_INCONSISTENT);
83947e946e7SWyllys Ingersoll 		}
84047e946e7SWyllys Ingersoll 
84147e946e7SWyllys Ingersoll 		/* generate the software based key */
84247e946e7SWyllys Ingersoll 		if ((rc = token_wrap_sw_key(hContext,
84347e946e7SWyllys Ingersoll 		    (int)attr->ulValueLen, attr->pValue,
84447e946e7SWyllys Ingersoll 		    (int)prime_attr->ulValueLen, prime_attr->pValue,
84547e946e7SWyllys Ingersoll 		    hParentKey, TSS_KEY_TYPE_LEGACY | TSS_KEY_NO_AUTHORIZATION,
84647e946e7SWyllys Ingersoll 		    phKey))) {
84747e946e7SWyllys Ingersoll 			return (rc);
84847e946e7SWyllys Ingersoll 		}
84947e946e7SWyllys Ingersoll 	} else if (class == CKO_PUBLIC_KEY) {
85047e946e7SWyllys Ingersoll 		/* Make sure the public exponent is usable */
85147e946e7SWyllys Ingersoll 		if ((util_check_public_exponent(obj->template))) {
85247e946e7SWyllys Ingersoll 			return (CKR_TEMPLATE_INCONSISTENT);
85347e946e7SWyllys Ingersoll 		}
85447e946e7SWyllys Ingersoll 
85547e946e7SWyllys Ingersoll 		/* grab the modulus to put into the TSS key object */
85647e946e7SWyllys Ingersoll 		if (template_attribute_find(obj->template,
85747e946e7SWyllys Ingersoll 		    CKA_MODULUS, &attr) == FALSE) {
85847e946e7SWyllys Ingersoll 			return (CKR_TEMPLATE_INCONSISTENT);
85947e946e7SWyllys Ingersoll 		}
86047e946e7SWyllys Ingersoll 
86147e946e7SWyllys Ingersoll 		/* make sure the key size is usable */
86247e946e7SWyllys Ingersoll 		initFlags = util_get_keysize_flag(attr->ulValueLen * 8);
86347e946e7SWyllys Ingersoll 		if (initFlags == 0) {
86447e946e7SWyllys Ingersoll 			return (CKR_TEMPLATE_INCONSISTENT);
86547e946e7SWyllys Ingersoll 		}
86647e946e7SWyllys Ingersoll 
867ab8176c2SWyllys Ingersoll 		initFlags |= TSS_KEY_MIGRATABLE | TSS_KEY_NO_AUTHORIZATION |
868ab8176c2SWyllys Ingersoll 		    TSS_KEY_TYPE_LEGACY;
86947e946e7SWyllys Ingersoll 
87047e946e7SWyllys Ingersoll 		if ((result = Tspi_Context_CreateObject(hContext,
87147e946e7SWyllys Ingersoll 		    TSS_OBJECT_TYPE_RSAKEY, initFlags, phKey))) {
87247e946e7SWyllys Ingersoll 			stlogit("Tspi_Context_CreateObject: 0x%0x - %s",
87347e946e7SWyllys Ingersoll 			    result, Trspi_Error_String(result));
87447e946e7SWyllys Ingersoll 			return (result);
87547e946e7SWyllys Ingersoll 		}
87647e946e7SWyllys Ingersoll 
87747e946e7SWyllys Ingersoll 		if ((result = set_public_modulus(hContext, *phKey,
87847e946e7SWyllys Ingersoll 		    attr->ulValueLen, attr->pValue))) {
87947e946e7SWyllys Ingersoll 			Tspi_Context_CloseObject(hContext, *phKey);
88047e946e7SWyllys Ingersoll 			*phKey = NULL_HKEY;
88147e946e7SWyllys Ingersoll 			return (CKR_FUNCTION_FAILED);
88247e946e7SWyllys Ingersoll 		}
883ab8176c2SWyllys Ingersoll 		result = tss_assign_secret_key_policy(hContext,
884ab8176c2SWyllys Ingersoll 		    TSS_POLICY_MIGRATION, *phKey, NULL);
885ab8176c2SWyllys Ingersoll 		if (result) {
886ab8176c2SWyllys Ingersoll 			Tspi_Context_CloseObject(hContext, *phKey);
887ab8176c2SWyllys Ingersoll 			*phKey = NULL_HKEY;
888ab8176c2SWyllys Ingersoll 			return (CKR_FUNCTION_FAILED);
889ab8176c2SWyllys Ingersoll 		}
890ab8176c2SWyllys Ingersoll 
891ab8176c2SWyllys Ingersoll 		result = set_legacy_key_params(*phKey);
892ab8176c2SWyllys Ingersoll 		if (result) {
893ab8176c2SWyllys Ingersoll 			Tspi_Context_CloseObject(hContext, *phKey);
894ab8176c2SWyllys Ingersoll 			*phKey = NULL_HKEY;
895ab8176c2SWyllys Ingersoll 			return (CKR_FUNCTION_FAILED);
896ab8176c2SWyllys Ingersoll 		}
89747e946e7SWyllys Ingersoll 	} else {
89847e946e7SWyllys Ingersoll 		return (CKR_FUNCTION_FAILED);
89947e946e7SWyllys Ingersoll 	}
90047e946e7SWyllys Ingersoll 
90147e946e7SWyllys Ingersoll 	/* grab the entire key blob to put into the PKCS#11 object */
90247e946e7SWyllys Ingersoll 	if ((result = Tspi_GetAttribData(*phKey, TSS_TSPATTRIB_KEY_BLOB,
90347e946e7SWyllys Ingersoll 	    TSS_TSPATTRIB_KEYBLOB_BLOB, &ulBlobLen, &rgbBlob))) {
90447e946e7SWyllys Ingersoll 		stlogit("Tspi_GetAttribData: 0x%0x - %s",
90547e946e7SWyllys Ingersoll 		    result, Trspi_Error_String(result));
90647e946e7SWyllys Ingersoll 		return (CKR_FUNCTION_FAILED);
90747e946e7SWyllys Ingersoll 	}
90847e946e7SWyllys Ingersoll 
90947e946e7SWyllys Ingersoll 	/* insert the key blob into the object */
91047e946e7SWyllys Ingersoll 	if ((rc = build_attribute(CKA_IBM_OPAQUE, rgbBlob, ulBlobLen,
91147e946e7SWyllys Ingersoll 	    &new_attr))) {
91247e946e7SWyllys Ingersoll 		Tspi_Context_FreeMemory(hContext, rgbBlob);
91347e946e7SWyllys Ingersoll 		return (rc);
91447e946e7SWyllys Ingersoll 	}
91547e946e7SWyllys Ingersoll 	(void) template_update_attribute(obj->template, new_attr);
91647e946e7SWyllys Ingersoll 	Tspi_Context_FreeMemory(hContext, rgbBlob);
91747e946e7SWyllys Ingersoll 
91847e946e7SWyllys Ingersoll 	/*
91947e946e7SWyllys Ingersoll 	 * If this is a token object, save it with the new attribute
92047e946e7SWyllys Ingersoll 	 * so that we don't have to go down this path again.
92147e946e7SWyllys Ingersoll 	 */
92247e946e7SWyllys Ingersoll 	if (!object_is_session_object(obj)) {
92347e946e7SWyllys Ingersoll 		rc = save_token_object(hContext, obj);
92447e946e7SWyllys Ingersoll 	}
92547e946e7SWyllys Ingersoll 
92647e946e7SWyllys Ingersoll 	return (rc);
92747e946e7SWyllys Ingersoll }
92847e946e7SWyllys Ingersoll 
92947e946e7SWyllys Ingersoll static TSS_RESULT
tss_assign_secret_key_policy(TSS_HCONTEXT hContext,TSS_FLAG policyType,TSS_HKEY hKey,CK_CHAR * passHash)930ab8176c2SWyllys Ingersoll tss_assign_secret_key_policy(TSS_HCONTEXT hContext, TSS_FLAG policyType,
931ab8176c2SWyllys Ingersoll     TSS_HKEY hKey, CK_CHAR *passHash)
93247e946e7SWyllys Ingersoll {
93347e946e7SWyllys Ingersoll 	TSS_RESULT result;
93447e946e7SWyllys Ingersoll 	TSS_HPOLICY hPolicy;
93547e946e7SWyllys Ingersoll 
93647e946e7SWyllys Ingersoll 	if ((result = Tspi_Context_CreateObject(hContext,
937ab8176c2SWyllys Ingersoll 	    TSS_OBJECT_TYPE_POLICY, policyType, &hPolicy))) {
93847e946e7SWyllys Ingersoll 		stlogit("Tspi_Context_CreateObject: 0x%0x - %s",
93947e946e7SWyllys Ingersoll 		    result, Trspi_Error_String(result));
94047e946e7SWyllys Ingersoll 		return (result);
94147e946e7SWyllys Ingersoll 	}
94247e946e7SWyllys Ingersoll 	if ((result = Tspi_Policy_AssignToObject(hPolicy, hKey))) {
94347e946e7SWyllys Ingersoll 		stlogit("Tspi_Policy_AssignToObject: 0x%0x - %s",
94447e946e7SWyllys Ingersoll 		    result, Trspi_Error_String(result));
94547e946e7SWyllys Ingersoll 		goto done;
94647e946e7SWyllys Ingersoll 	}
94747e946e7SWyllys Ingersoll 	if (passHash == NULL) {
94847e946e7SWyllys Ingersoll 		result = Tspi_Policy_SetSecret(hPolicy, TSS_SECRET_MODE_NONE,
94947e946e7SWyllys Ingersoll 		    0, NULL);
95047e946e7SWyllys Ingersoll 	} else {
95147e946e7SWyllys Ingersoll 		result = Tspi_Policy_SetSecret(hPolicy, TSS_SECRET_MODE_SHA1,
95247e946e7SWyllys Ingersoll 		    SHA1_DIGEST_LENGTH, passHash);
95347e946e7SWyllys Ingersoll 	}
95447e946e7SWyllys Ingersoll 	if (result != TSS_SUCCESS) {
95547e946e7SWyllys Ingersoll 		stlogit("Tspi_Policy_SetSecret: 0x%0x - %s",
95647e946e7SWyllys Ingersoll 		    result, Trspi_Error_String(result));
95747e946e7SWyllys Ingersoll 		goto done;
95847e946e7SWyllys Ingersoll 	}
95947e946e7SWyllys Ingersoll done:
96047e946e7SWyllys Ingersoll 	if (result != TSS_SUCCESS)
96147e946e7SWyllys Ingersoll 		Tspi_Context_CloseObject(hContext, hPolicy);
96247e946e7SWyllys Ingersoll 	return (result);
96347e946e7SWyllys Ingersoll }
96447e946e7SWyllys Ingersoll 
96547e946e7SWyllys Ingersoll /*
96647e946e7SWyllys Ingersoll  * Take a key from the TSS store (on-disk) and load it into the TPM, wrapped
96747e946e7SWyllys Ingersoll  * by an already TPM-resident key and protected with a PIN (optional).
96847e946e7SWyllys Ingersoll  */
96947e946e7SWyllys Ingersoll static CK_RV
token_load_key(TSS_HCONTEXT hContext,CK_OBJECT_HANDLE ckKey,TSS_HKEY hParentKey,CK_CHAR_PTR passHash,TSS_HKEY * phKey)97047e946e7SWyllys Ingersoll token_load_key(
97147e946e7SWyllys Ingersoll 	TSS_HCONTEXT hContext,
97247e946e7SWyllys Ingersoll 	CK_OBJECT_HANDLE ckKey,
97347e946e7SWyllys Ingersoll 	TSS_HKEY hParentKey,
97447e946e7SWyllys Ingersoll 	CK_CHAR_PTR passHash,
97547e946e7SWyllys Ingersoll 	TSS_HKEY *phKey)
97647e946e7SWyllys Ingersoll {
97747e946e7SWyllys Ingersoll 	TSS_RESULT result;
97847e946e7SWyllys Ingersoll 	CK_RV rc;
97947e946e7SWyllys Ingersoll 
980ab8176c2SWyllys Ingersoll 	/*
981ab8176c2SWyllys Ingersoll 	 * The key blob wasn't found, load the parts of the key
982ab8176c2SWyllys Ingersoll 	 * from the object DB and create a new key object that
983ab8176c2SWyllys Ingersoll 	 * gets loaded into the TPM, wrapped with the parent key.
984ab8176c2SWyllys Ingersoll 	 */
985ab8176c2SWyllys Ingersoll 	if ((rc = token_wrap_key_object(hContext, ckKey,
986ab8176c2SWyllys Ingersoll 	    hParentKey, phKey))) {
987ab8176c2SWyllys Ingersoll 		return (rc);
98847e946e7SWyllys Ingersoll 	}
98947e946e7SWyllys Ingersoll 
99047e946e7SWyllys Ingersoll 	/*
99147e946e7SWyllys Ingersoll 	 * Assign the PIN hash (optional) to the newly loaded key object,
99247e946e7SWyllys Ingersoll 	 * if this PIN is incorrect, the TPM will not be able to decrypt
99347e946e7SWyllys Ingersoll 	 * the private key and use it.
99447e946e7SWyllys Ingersoll 	 */
995ab8176c2SWyllys Ingersoll 	result = tss_assign_secret_key_policy(hContext, TSS_POLICY_USAGE,
996ab8176c2SWyllys Ingersoll 	    *phKey, passHash);
997ab8176c2SWyllys Ingersoll 
99847e946e7SWyllys Ingersoll 	return (result);
99947e946e7SWyllys Ingersoll }
100047e946e7SWyllys Ingersoll 
100147e946e7SWyllys Ingersoll /*
100247e946e7SWyllys Ingersoll  * Load the SRK into the TPM by referencing its well-known UUID and using the
100347e946e7SWyllys Ingersoll  * default SRK PIN (20 bytes of 0x00).
100447e946e7SWyllys Ingersoll  *
100547e946e7SWyllys Ingersoll  * NOTE - if the SRK PIN is changed by an administrative tool, this code will
100647e946e7SWyllys Ingersoll  * fail because it assumes that the well-known PIN is still being used.
100747e946e7SWyllys Ingersoll  */
100847e946e7SWyllys Ingersoll static TSS_RESULT
token_load_srk(TSS_HCONTEXT hContext,TSS_HKEY * hSRK)100947e946e7SWyllys Ingersoll token_load_srk(TSS_HCONTEXT hContext, TSS_HKEY *hSRK)
101047e946e7SWyllys Ingersoll {
101147e946e7SWyllys Ingersoll 	TSS_HPOLICY hPolicy;
101247e946e7SWyllys Ingersoll 	TSS_RESULT result;
101347e946e7SWyllys Ingersoll 	TSS_UUID SRK_UUID = TSS_UUID_SRK;
101447e946e7SWyllys Ingersoll 	BYTE wellKnown[] = TSS_WELL_KNOWN_SECRET;
101547e946e7SWyllys Ingersoll 	TSS_HTPM hTPM;
101647e946e7SWyllys Ingersoll 
101747e946e7SWyllys Ingersoll 	if ((result = Tspi_Context_GetTpmObject(hContext, &hTPM))) {
101847e946e7SWyllys Ingersoll 		stlogit("Tspi_Context_GetTpmObject: 0x%0x - %s",
101947e946e7SWyllys Ingersoll 		    result, Trspi_Error_String(result));
102047e946e7SWyllys Ingersoll 		return (CKR_FUNCTION_FAILED);
102147e946e7SWyllys Ingersoll 	}
102247e946e7SWyllys Ingersoll 
102347e946e7SWyllys Ingersoll 	/* load the SRK */
102447e946e7SWyllys Ingersoll 	if ((result = Tspi_Context_LoadKeyByUUID(hContext,
102547e946e7SWyllys Ingersoll 	    TSS_PS_TYPE_SYSTEM, SRK_UUID, hSRK))) {
102647e946e7SWyllys Ingersoll 		stlogit("Tspi_Context_LoadKeyByUUID: 0x%0x - %s",
102747e946e7SWyllys Ingersoll 		    result, Trspi_Error_String(result));
102847e946e7SWyllys Ingersoll 		goto done;
102947e946e7SWyllys Ingersoll 	}
103047e946e7SWyllys Ingersoll 	if ((result = Tspi_GetPolicyObject(*hSRK, TSS_POLICY_USAGE,
103147e946e7SWyllys Ingersoll 	    &hPolicy))) {
103247e946e7SWyllys Ingersoll 		stlogit("Tspi_GetPolicyObject: 0x%0x - %s",
103347e946e7SWyllys Ingersoll 		    result, Trspi_Error_String(result));
103447e946e7SWyllys Ingersoll 		goto done;
103547e946e7SWyllys Ingersoll 	}
103647e946e7SWyllys Ingersoll 	if ((result = Tspi_Policy_SetSecret(hPolicy, TSS_SECRET_MODE_SHA1,
103747e946e7SWyllys Ingersoll 	    sizeof (wellKnown), wellKnown))) {
103847e946e7SWyllys Ingersoll 		stlogit("Tspi_Policy_SetSecret: 0x%0x - %s",
103947e946e7SWyllys Ingersoll 		    result, Trspi_Error_String(result));
104047e946e7SWyllys Ingersoll 		goto done;
104147e946e7SWyllys Ingersoll 	}
104247e946e7SWyllys Ingersoll 
104347e946e7SWyllys Ingersoll done:
104447e946e7SWyllys Ingersoll 	return (result);
104547e946e7SWyllys Ingersoll }
104647e946e7SWyllys Ingersoll 
104747e946e7SWyllys Ingersoll static TSS_RESULT
tss_find_and_load_key(TSS_HCONTEXT hContext,char * keyid,TSS_UUID * uuid,TSS_HKEY hParent,BYTE * hash,TSS_HKEY * hKey)104847e946e7SWyllys Ingersoll tss_find_and_load_key(TSS_HCONTEXT hContext,
104947e946e7SWyllys Ingersoll 	char *keyid, TSS_UUID *uuid, TSS_HKEY hParent,
105047e946e7SWyllys Ingersoll 	BYTE *hash, TSS_HKEY *hKey)
105147e946e7SWyllys Ingersoll {
105247e946e7SWyllys Ingersoll 	TSS_RESULT result;
105347e946e7SWyllys Ingersoll 
105447e946e7SWyllys Ingersoll 	if (local_uuid_is_null(uuid) &&
105547e946e7SWyllys Ingersoll 	    find_uuid(keyid, uuid)) {
105647e946e7SWyllys Ingersoll 		/* The UUID was not created or saved yet */
105747e946e7SWyllys Ingersoll 		return (1);
105847e946e7SWyllys Ingersoll 	}
105947e946e7SWyllys Ingersoll 	result = Tspi_Context_GetKeyByUUID(hContext,
106047e946e7SWyllys Ingersoll 	    TSS_PS_TYPE_USER, *uuid, hKey);
106147e946e7SWyllys Ingersoll 	if (result) {
106247e946e7SWyllys Ingersoll 		stlogit("Tspi_Context_GetKeyByUUID: 0x%0x - %s",
106347e946e7SWyllys Ingersoll 		    result, Trspi_Error_String(result));
106447e946e7SWyllys Ingersoll 		return (result);
106547e946e7SWyllys Ingersoll 	}
106647e946e7SWyllys Ingersoll 
106747e946e7SWyllys Ingersoll 	if (hash != NULL) {
1068ab8176c2SWyllys Ingersoll 		result = tss_assign_secret_key_policy(hContext,
1069ab8176c2SWyllys Ingersoll 		    TSS_POLICY_USAGE, *hKey, (CK_BYTE *)hash);
107047e946e7SWyllys Ingersoll 		if (result)
107147e946e7SWyllys Ingersoll 			return (result);
107247e946e7SWyllys Ingersoll 	}
107347e946e7SWyllys Ingersoll 
107447e946e7SWyllys Ingersoll 	result = Tspi_Key_LoadKey(*hKey, hParent);
107547e946e7SWyllys Ingersoll 	if (result)
107647e946e7SWyllys Ingersoll 		stlogit("Tspi_Key_LoadKey: 0x%0x - %s",
107747e946e7SWyllys Ingersoll 		    result, Trspi_Error_String(result));
107847e946e7SWyllys Ingersoll 
107947e946e7SWyllys Ingersoll 	return (result);
108047e946e7SWyllys Ingersoll }
108147e946e7SWyllys Ingersoll 
108247e946e7SWyllys Ingersoll static TSS_RESULT
token_load_public_root_key(TSS_HCONTEXT hContext)108347e946e7SWyllys Ingersoll token_load_public_root_key(TSS_HCONTEXT hContext)
108447e946e7SWyllys Ingersoll {
108547e946e7SWyllys Ingersoll 	TSS_RESULT result;
108647e946e7SWyllys Ingersoll 	TSS_HKEY hSRK;
108747e946e7SWyllys Ingersoll 
108847e946e7SWyllys Ingersoll 	if (hPublicRootKey != NULL_HKEY)
108947e946e7SWyllys Ingersoll 		return (TSS_SUCCESS);
109047e946e7SWyllys Ingersoll 
109147e946e7SWyllys Ingersoll 	if ((result = token_load_srk(hContext, &hSRK))) {
109247e946e7SWyllys Ingersoll 		return (result);
109347e946e7SWyllys Ingersoll 	}
109447e946e7SWyllys Ingersoll 
109547e946e7SWyllys Ingersoll 	result = tss_find_and_load_key(hContext,
109647e946e7SWyllys Ingersoll 	    TPMTOK_PUBLIC_ROOT_KEY_ID,
109747e946e7SWyllys Ingersoll 	    &publicRootKeyUUID, hSRK, NULL, &hPublicRootKey);
109847e946e7SWyllys Ingersoll 	if (result)
109947e946e7SWyllys Ingersoll 		return (result);
110047e946e7SWyllys Ingersoll 
110147e946e7SWyllys Ingersoll 	return (result);
110247e946e7SWyllys Ingersoll }
110347e946e7SWyllys Ingersoll 
1104ab8176c2SWyllys Ingersoll static TSS_RESULT
set_legacy_key_params(TSS_HKEY hKey)1105ab8176c2SWyllys Ingersoll set_legacy_key_params(TSS_HKEY hKey)
1106ab8176c2SWyllys Ingersoll {
1107ab8176c2SWyllys Ingersoll 	TSS_RESULT result;
1108ab8176c2SWyllys Ingersoll 
1109ab8176c2SWyllys Ingersoll 	if ((result = Tspi_SetAttribUint32(hKey,
1110ab8176c2SWyllys Ingersoll 	    TSS_TSPATTRIB_KEY_INFO,
1111ab8176c2SWyllys Ingersoll 	    TSS_TSPATTRIB_KEYINFO_ENCSCHEME,
1112ab8176c2SWyllys Ingersoll 	    TSS_ES_RSAESPKCSV15))) {
1113ab8176c2SWyllys Ingersoll 		stlogit("Tspi_SetAttribUint32: 0x%0x - %s",
1114ab8176c2SWyllys Ingersoll 		    result, Trspi_Error_String(result));
1115ab8176c2SWyllys Ingersoll 		return (result);
1116ab8176c2SWyllys Ingersoll 	}
1117ab8176c2SWyllys Ingersoll 
1118ab8176c2SWyllys Ingersoll 	if ((result = Tspi_SetAttribUint32(hKey,
1119ab8176c2SWyllys Ingersoll 	    TSS_TSPATTRIB_KEY_INFO,
1120ab8176c2SWyllys Ingersoll 	    TSS_TSPATTRIB_KEYINFO_SIGSCHEME,
1121ab8176c2SWyllys Ingersoll 	    TSS_SS_RSASSAPKCS1V15_DER))) {
1122ab8176c2SWyllys Ingersoll 		stlogit("Tspi_SetAttribUint32: 0x%0x - %s",
1123ab8176c2SWyllys Ingersoll 		    result, Trspi_Error_String(result));
1124ab8176c2SWyllys Ingersoll 		return (result);
1125ab8176c2SWyllys Ingersoll 	}
1126ab8176c2SWyllys Ingersoll 
1127ab8176c2SWyllys Ingersoll 	return (result);
1128ab8176c2SWyllys Ingersoll }
1129ab8176c2SWyllys Ingersoll 
113047e946e7SWyllys Ingersoll static TSS_RESULT
tss_generate_key(TSS_HCONTEXT hContext,TSS_FLAG initFlags,BYTE * passHash,TSS_HKEY hParentKey,TSS_HKEY * phKey)113147e946e7SWyllys Ingersoll tss_generate_key(TSS_HCONTEXT hContext, TSS_FLAG initFlags, BYTE *passHash,
113247e946e7SWyllys Ingersoll 	TSS_HKEY hParentKey, TSS_HKEY *phKey)
113347e946e7SWyllys Ingersoll {
113447e946e7SWyllys Ingersoll 	TSS_RESULT	result;
113547e946e7SWyllys Ingersoll 	TSS_HPOLICY	hMigPolicy;
113647e946e7SWyllys Ingersoll 
113747e946e7SWyllys Ingersoll 	if ((result = Tspi_Context_CreateObject(hContext,
113847e946e7SWyllys Ingersoll 	    TSS_OBJECT_TYPE_RSAKEY, initFlags, phKey))) {
113947e946e7SWyllys Ingersoll 		stlogit("Tspi_Context_CreateObject: 0x%0x - %s",
114047e946e7SWyllys Ingersoll 		    result, Trspi_Error_String(result));
114147e946e7SWyllys Ingersoll 		return (result);
114247e946e7SWyllys Ingersoll 	}
1143ab8176c2SWyllys Ingersoll 	result = tss_assign_secret_key_policy(hContext, TSS_POLICY_USAGE,
1144ab8176c2SWyllys Ingersoll 	    *phKey, passHash);
114547e946e7SWyllys Ingersoll 
114647e946e7SWyllys Ingersoll 	if (result) {
114747e946e7SWyllys Ingersoll 		Tspi_Context_CloseObject(hContext, *phKey);
114847e946e7SWyllys Ingersoll 		return (result);
114947e946e7SWyllys Ingersoll 	}
115047e946e7SWyllys Ingersoll 
115147e946e7SWyllys Ingersoll 	if (TPMTOK_TSS_KEY_MIG_TYPE(initFlags) == TSS_KEY_MIGRATABLE) {
115247e946e7SWyllys Ingersoll 		if ((result = Tspi_Context_CreateObject(hContext,
115347e946e7SWyllys Ingersoll 		    TSS_OBJECT_TYPE_POLICY, TSS_POLICY_MIGRATION,
115447e946e7SWyllys Ingersoll 		    &hMigPolicy))) {
115547e946e7SWyllys Ingersoll 			stlogit("Tspi_Context_CreateObject: 0x%0x - %s",
115647e946e7SWyllys Ingersoll 			    result, Trspi_Error_String(result));
115747e946e7SWyllys Ingersoll 			Tspi_Context_CloseObject(hContext, *phKey);
115847e946e7SWyllys Ingersoll 			return (result);
115947e946e7SWyllys Ingersoll 		}
116047e946e7SWyllys Ingersoll 
116147e946e7SWyllys Ingersoll 		if (passHash == NULL) {
116247e946e7SWyllys Ingersoll 			result = Tspi_Policy_SetSecret(hMigPolicy,
116347e946e7SWyllys Ingersoll 			    TSS_SECRET_MODE_NONE, 0, NULL);
116447e946e7SWyllys Ingersoll 		} else {
116547e946e7SWyllys Ingersoll 			result = Tspi_Policy_SetSecret(hMigPolicy,
116647e946e7SWyllys Ingersoll 			    TSS_SECRET_MODE_SHA1, 20, passHash);
116747e946e7SWyllys Ingersoll 		}
116847e946e7SWyllys Ingersoll 
116947e946e7SWyllys Ingersoll 		if (result != TSS_SUCCESS) {
117047e946e7SWyllys Ingersoll 			stlogit("Tspi_Policy_SetSecret: 0x%0x - %s",
117147e946e7SWyllys Ingersoll 			    result, Trspi_Error_String(result));
117247e946e7SWyllys Ingersoll 			Tspi_Context_CloseObject(hContext, *phKey);
117347e946e7SWyllys Ingersoll 			Tspi_Context_CloseObject(hContext, hMigPolicy);
117447e946e7SWyllys Ingersoll 			return (result);
117547e946e7SWyllys Ingersoll 		}
117647e946e7SWyllys Ingersoll 
117747e946e7SWyllys Ingersoll 		if ((result = Tspi_Policy_AssignToObject(hMigPolicy, *phKey))) {
117847e946e7SWyllys Ingersoll 			stlogit("Tspi_Policy_AssignToObject: 0x%0x - %s",
117947e946e7SWyllys Ingersoll 			    result, Trspi_Error_String(result));
118047e946e7SWyllys Ingersoll 			Tspi_Context_CloseObject(hContext, *phKey);
118147e946e7SWyllys Ingersoll 			Tspi_Context_CloseObject(hContext, hMigPolicy);
118247e946e7SWyllys Ingersoll 			return (result);
118347e946e7SWyllys Ingersoll 		}
118447e946e7SWyllys Ingersoll 	}
118547e946e7SWyllys Ingersoll 
118647e946e7SWyllys Ingersoll 	if (TPMTOK_TSS_KEY_TYPE(initFlags) == TSS_KEY_TYPE_LEGACY) {
1187ab8176c2SWyllys Ingersoll 		result = set_legacy_key_params(*phKey);
1188ab8176c2SWyllys Ingersoll 		if (result) {
118947e946e7SWyllys Ingersoll 			Tspi_Context_CloseObject(hContext, *phKey);
119047e946e7SWyllys Ingersoll 			Tspi_Context_CloseObject(hContext, hMigPolicy);
119147e946e7SWyllys Ingersoll 			return (result);
119247e946e7SWyllys Ingersoll 		}
119347e946e7SWyllys Ingersoll 	}
119447e946e7SWyllys Ingersoll 
119547e946e7SWyllys Ingersoll 	if ((result = Tspi_Key_CreateKey(*phKey, hParentKey, 0))) {
119647e946e7SWyllys Ingersoll 		stlogit("Tspi_Key_CreateKey: 0x%0x - %s",
119747e946e7SWyllys Ingersoll 		    result, Trspi_Error_String(result));
119847e946e7SWyllys Ingersoll 		Tspi_Context_CloseObject(hContext, *phKey);
119947e946e7SWyllys Ingersoll 		Tspi_Context_CloseObject(hContext, hMigPolicy);
120047e946e7SWyllys Ingersoll 	}
120147e946e7SWyllys Ingersoll 
120247e946e7SWyllys Ingersoll 	return (result);
120347e946e7SWyllys Ingersoll }
120447e946e7SWyllys Ingersoll 
120547e946e7SWyllys Ingersoll static TSS_RESULT
tss_change_auth(TSS_HCONTEXT hContext,TSS_HKEY hObjectToChange,TSS_HKEY hParentObject,TSS_UUID objUUID,TSS_UUID parentUUID,CK_CHAR * passHash)120647e946e7SWyllys Ingersoll tss_change_auth(
120747e946e7SWyllys Ingersoll 	TSS_HCONTEXT hContext,
120847e946e7SWyllys Ingersoll 	TSS_HKEY hObjectToChange, TSS_HKEY hParentObject,
120947e946e7SWyllys Ingersoll 	TSS_UUID objUUID, TSS_UUID parentUUID,
121047e946e7SWyllys Ingersoll 	CK_CHAR *passHash)
121147e946e7SWyllys Ingersoll {
121247e946e7SWyllys Ingersoll 	TSS_RESULT result;
121347e946e7SWyllys Ingersoll 	TSS_HPOLICY hPolicy;
121447e946e7SWyllys Ingersoll 	TSS_HKEY oldkey;
121547e946e7SWyllys Ingersoll 
121647e946e7SWyllys Ingersoll 	if ((result = Tspi_Context_CreateObject(hContext,
121747e946e7SWyllys Ingersoll 	    TSS_OBJECT_TYPE_POLICY, TSS_POLICY_USAGE, &hPolicy))) {
121847e946e7SWyllys Ingersoll 		stlogit("Tspi_Context_CreateObject: 0x%0x - %s",
121947e946e7SWyllys Ingersoll 		    result, Trspi_Error_String(result));
122047e946e7SWyllys Ingersoll 		return (result);
122147e946e7SWyllys Ingersoll 	}
122247e946e7SWyllys Ingersoll 
122347e946e7SWyllys Ingersoll 	if ((result = Tspi_Policy_SetSecret(hPolicy, TSS_SECRET_MODE_SHA1,
122447e946e7SWyllys Ingersoll 	    SHA1_DIGEST_LENGTH, passHash))) {
122547e946e7SWyllys Ingersoll 		stlogit("Tspi_Policy_SetSecret: 0x%0x - %s",
122647e946e7SWyllys Ingersoll 		    result, Trspi_Error_String(result));
122747e946e7SWyllys Ingersoll 		return (result);
122847e946e7SWyllys Ingersoll 	}
122947e946e7SWyllys Ingersoll 
123047e946e7SWyllys Ingersoll 	if ((result = Tspi_ChangeAuth(hObjectToChange, hParentObject,
123147e946e7SWyllys Ingersoll 	    hPolicy))) {
123247e946e7SWyllys Ingersoll 		stlogit("Tspi_ChangeAuth: 0x%0x - %s",
123347e946e7SWyllys Ingersoll 		    result, Trspi_Error_String(result));
123447e946e7SWyllys Ingersoll 	}
123547e946e7SWyllys Ingersoll 	/*
123647e946e7SWyllys Ingersoll 	 * Update the PS key by unregistering the key UUID and then
123747e946e7SWyllys Ingersoll 	 * re-registering with the same UUID.  This forces the updated
123847e946e7SWyllys Ingersoll 	 * auth data associated with the key to be stored in PS so
123947e946e7SWyllys Ingersoll 	 * the new PIN can be used next time.
124047e946e7SWyllys Ingersoll 	 */
124147e946e7SWyllys Ingersoll 	if ((result = Tspi_Context_UnregisterKey(hContext,
124247e946e7SWyllys Ingersoll 	    TSS_PS_TYPE_USER, objUUID, &oldkey)))
124347e946e7SWyllys Ingersoll 		stlogit("Tspi_Context_UnregisterKey: 0x%0x - %s",
124447e946e7SWyllys Ingersoll 		    result, Trspi_Error_String(result));
124547e946e7SWyllys Ingersoll 
124647e946e7SWyllys Ingersoll 	if ((result = Tspi_Context_RegisterKey(hContext, hObjectToChange,
124747e946e7SWyllys Ingersoll 	    TSS_PS_TYPE_USER, objUUID, TSS_PS_TYPE_USER, parentUUID)))
124847e946e7SWyllys Ingersoll 		stlogit("Tspi_Context_RegisterKey: 0x%0x - %s",
124947e946e7SWyllys Ingersoll 		    result, Trspi_Error_String(result));
125047e946e7SWyllys Ingersoll 
125147e946e7SWyllys Ingersoll 	return (result);
125247e946e7SWyllys Ingersoll }
125347e946e7SWyllys Ingersoll 
125447e946e7SWyllys Ingersoll static CK_RV
token_generate_leaf_key(TSS_HCONTEXT hContext,int key_type,CK_CHAR_PTR passHash,TSS_HKEY * phKey)125547e946e7SWyllys Ingersoll token_generate_leaf_key(TSS_HCONTEXT hContext,
125647e946e7SWyllys Ingersoll 	int key_type, CK_CHAR_PTR passHash, TSS_HKEY *phKey)
125747e946e7SWyllys Ingersoll {
125847e946e7SWyllys Ingersoll 	CK_RV		rc = CKR_FUNCTION_FAILED;
125947e946e7SWyllys Ingersoll 	TSS_RESULT	result;
126047e946e7SWyllys Ingersoll 	TSS_HKEY	hParentKey;
126147e946e7SWyllys Ingersoll 	TSS_UUID	newuuid, parentUUID;
126247e946e7SWyllys Ingersoll 	char		*keyid;
126347e946e7SWyllys Ingersoll 	TSS_FLAG	initFlags = TSS_KEY_MIGRATABLE |
126447e946e7SWyllys Ingersoll 	    TSS_KEY_TYPE_BIND | TSS_KEY_SIZE_2048  | TSS_KEY_AUTHORIZATION;
126547e946e7SWyllys Ingersoll 
126647e946e7SWyllys Ingersoll 	switch (key_type) {
126747e946e7SWyllys Ingersoll 		case TPMTOK_PUBLIC_LEAF_KEY:
126847e946e7SWyllys Ingersoll 			hParentKey = hPublicRootKey;
126947e946e7SWyllys Ingersoll 			keyid = TPMTOK_PUBLIC_LEAF_KEY_ID;
127047e946e7SWyllys Ingersoll 			local_uuid_copy(&parentUUID, &publicRootKeyUUID);
127147e946e7SWyllys Ingersoll 			break;
127247e946e7SWyllys Ingersoll 		case TPMTOK_PRIVATE_LEAF_KEY:
127347e946e7SWyllys Ingersoll 			hParentKey = hPrivateRootKey;
127447e946e7SWyllys Ingersoll 			keyid = TPMTOK_PRIVATE_LEAF_KEY_ID;
127547e946e7SWyllys Ingersoll 			local_uuid_copy(&parentUUID, &privateRootKeyUUID);
127647e946e7SWyllys Ingersoll 			break;
127747e946e7SWyllys Ingersoll 		default:
127847e946e7SWyllys Ingersoll 			stlogit("Unknown key type 0x%0x", key_type);
127947e946e7SWyllys Ingersoll 			goto done;
128047e946e7SWyllys Ingersoll 	}
128147e946e7SWyllys Ingersoll 
128247e946e7SWyllys Ingersoll 	if (result = tss_generate_key(hContext, initFlags, passHash,
128347e946e7SWyllys Ingersoll 	    hParentKey, phKey)) {
128447e946e7SWyllys Ingersoll 		return (rc);
128547e946e7SWyllys Ingersoll 	}
128647e946e7SWyllys Ingersoll 
128747e946e7SWyllys Ingersoll 	/*
128847e946e7SWyllys Ingersoll 	 * - generate newUUID
128947e946e7SWyllys Ingersoll 	 * - Tspi_Context_RegisterKey(hContext, hPrivateRootKey,
129047e946e7SWyllys Ingersoll 	 *   USER, newUUID, USER, parentUUID);
129147e946e7SWyllys Ingersoll 	 * - store newUUID
129247e946e7SWyllys Ingersoll 	 */
129347e946e7SWyllys Ingersoll 	(void) local_uuid_generate(&newuuid);
129447e946e7SWyllys Ingersoll 
129547e946e7SWyllys Ingersoll 	result = Tspi_Context_RegisterKey(hContext, *phKey,
129647e946e7SWyllys Ingersoll 	    TSS_PS_TYPE_USER, newuuid,
129747e946e7SWyllys Ingersoll 	    TSS_PS_TYPE_USER, parentUUID);
129847e946e7SWyllys Ingersoll 	if (result == TSS_SUCCESS) {
129947e946e7SWyllys Ingersoll 		int ret;
130047e946e7SWyllys Ingersoll 		/*
130147e946e7SWyllys Ingersoll 		 * Add the UUID to the token UUID index.
130247e946e7SWyllys Ingersoll 		 */
130347e946e7SWyllys Ingersoll 		ret = add_uuid(keyid, &newuuid);
130447e946e7SWyllys Ingersoll 
130547e946e7SWyllys Ingersoll 		if (ret)
130647e946e7SWyllys Ingersoll 			result = Tspi_Context_UnregisterKey(hContext,
130747e946e7SWyllys Ingersoll 			    TSS_PS_TYPE_USER, newuuid, phKey);
130847e946e7SWyllys Ingersoll 		else
130947e946e7SWyllys Ingersoll 			rc = CKR_OK;
131047e946e7SWyllys Ingersoll 	}
131147e946e7SWyllys Ingersoll 
131247e946e7SWyllys Ingersoll done:
131347e946e7SWyllys Ingersoll 	return (rc);
131447e946e7SWyllys Ingersoll }
131547e946e7SWyllys Ingersoll 
131647e946e7SWyllys Ingersoll /*
131747e946e7SWyllys Ingersoll  * PINs are verified by attempting to bind/unbind random data using a
131847e946e7SWyllys Ingersoll  * TPM resident key that has the PIN being tested assigned as its "secret".
131947e946e7SWyllys Ingersoll  * If the PIN is incorrect, the unbind operation will fail.
132047e946e7SWyllys Ingersoll  */
132147e946e7SWyllys Ingersoll static CK_RV
token_verify_pin(TSS_HCONTEXT hContext,TSS_HKEY hKey)132247e946e7SWyllys Ingersoll token_verify_pin(TSS_HCONTEXT hContext, TSS_HKEY hKey)
132347e946e7SWyllys Ingersoll {
132447e946e7SWyllys Ingersoll 	TSS_HENCDATA hEncData;
132547e946e7SWyllys Ingersoll 	UINT32 ulUnboundDataLen;
132647e946e7SWyllys Ingersoll 	BYTE *rgbUnboundData = NULL;
132747e946e7SWyllys Ingersoll 	BYTE rgbData[16];
132847e946e7SWyllys Ingersoll 	TSS_RESULT result;
132947e946e7SWyllys Ingersoll 	CK_RV rc = CKR_FUNCTION_FAILED;
133047e946e7SWyllys Ingersoll 
133147e946e7SWyllys Ingersoll 	if ((result = Tspi_Context_CreateObject(hContext,
133247e946e7SWyllys Ingersoll 	    TSS_OBJECT_TYPE_ENCDATA, TSS_ENCDATA_BIND, &hEncData))) {
133347e946e7SWyllys Ingersoll 		stlogit("Tspi_Context_CreateObject: 0x%0x - %s",
133447e946e7SWyllys Ingersoll 		    result, Trspi_Error_String(result));
133547e946e7SWyllys Ingersoll 		goto done;
133647e946e7SWyllys Ingersoll 	}
133747e946e7SWyllys Ingersoll 
133847e946e7SWyllys Ingersoll 	/* Use some random data */
133947e946e7SWyllys Ingersoll 	rc = token_rng(hContext, rgbData, sizeof (rgbData));
134047e946e7SWyllys Ingersoll 	if (rc)
134147e946e7SWyllys Ingersoll 		goto done;
134247e946e7SWyllys Ingersoll 
134347e946e7SWyllys Ingersoll 	if ((result = Tspi_Data_Bind(hEncData, hKey,
134447e946e7SWyllys Ingersoll 	    sizeof (rgbData), rgbData))) {
134547e946e7SWyllys Ingersoll 		stlogit("Tspi_Data_Bind: 0x%0x - %s",
134647e946e7SWyllys Ingersoll 		    result, Trspi_Error_String(result));
134747e946e7SWyllys Ingersoll 		goto done;
134847e946e7SWyllys Ingersoll 	}
134947e946e7SWyllys Ingersoll 
135047e946e7SWyllys Ingersoll 	/* unbind the junk data to test the key's auth data */
135147e946e7SWyllys Ingersoll 	result = Tspi_Data_Unbind(hEncData, hKey, &ulUnboundDataLen,
135247e946e7SWyllys Ingersoll 	    &rgbUnboundData);
1353ab8176c2SWyllys Ingersoll 	if (result == TPM_E_AUTHFAIL) {
135447e946e7SWyllys Ingersoll 		rc = CKR_PIN_INCORRECT;
135547e946e7SWyllys Ingersoll 		stlogit("Tspi_Data_Unbind: 0x%0x - %s",
135647e946e7SWyllys Ingersoll 		    result, Trspi_Error_String(result));
135747e946e7SWyllys Ingersoll 		goto done;
135847e946e7SWyllys Ingersoll 	} else if (result != TSS_SUCCESS) {
135947e946e7SWyllys Ingersoll 		stlogit("Tspi_Data_Unbind: 0x%0x - %s",
136047e946e7SWyllys Ingersoll 		    result, Trspi_Error_String(result));
136147e946e7SWyllys Ingersoll 		rc = CKR_FUNCTION_FAILED;
136247e946e7SWyllys Ingersoll 		goto done;
136347e946e7SWyllys Ingersoll 	}
136447e946e7SWyllys Ingersoll 
136547e946e7SWyllys Ingersoll 	if (memcmp(rgbUnboundData, rgbData, ulUnboundDataLen))
136647e946e7SWyllys Ingersoll 		rc = CKR_PIN_INCORRECT;
136747e946e7SWyllys Ingersoll 	else
136847e946e7SWyllys Ingersoll 		rc = CKR_OK;
136947e946e7SWyllys Ingersoll 
137047e946e7SWyllys Ingersoll done:
137147e946e7SWyllys Ingersoll 	if (rgbUnboundData != NULL)
137247e946e7SWyllys Ingersoll 		Tspi_Context_FreeMemory(hContext, rgbUnboundData);
137347e946e7SWyllys Ingersoll 	Tspi_Context_CloseObject(hContext, hEncData);
137447e946e7SWyllys Ingersoll 	return (rc);
137547e946e7SWyllys Ingersoll }
137647e946e7SWyllys Ingersoll 
137747e946e7SWyllys Ingersoll static CK_RV
token_create_private_tree(TSS_HCONTEXT hContext,CK_BYTE * pinHash)137847e946e7SWyllys Ingersoll token_create_private_tree(TSS_HCONTEXT hContext, CK_BYTE *pinHash)
137947e946e7SWyllys Ingersoll {
138047e946e7SWyllys Ingersoll 	CK_RV		rc;
138147e946e7SWyllys Ingersoll 	TSS_RESULT	result;
138247e946e7SWyllys Ingersoll 	int		ret;
138347e946e7SWyllys Ingersoll 	TSS_FLAG initFlags = TSS_KEY_SIZE_2048 |
138447e946e7SWyllys Ingersoll 	    TSS_KEY_NO_AUTHORIZATION | TSS_KEY_TYPE_STORAGE;
138547e946e7SWyllys Ingersoll 	TSS_UUID SRK_UUID = TSS_UUID_SRK;
138647e946e7SWyllys Ingersoll 	TSS_HKEY hSRK;
138747e946e7SWyllys Ingersoll 
138847e946e7SWyllys Ingersoll 	if (token_load_srk(hContext, &hSRK))
138947e946e7SWyllys Ingersoll 		return (CKR_FUNCTION_FAILED);
139047e946e7SWyllys Ingersoll 
139147e946e7SWyllys Ingersoll 	/*
139247e946e7SWyllys Ingersoll 	 * - create UUID privateRootKeyUUID
139347e946e7SWyllys Ingersoll 	 * - Tspi_Context_RegisterKey(hContext, hPrivateRootKey,
139447e946e7SWyllys Ingersoll 	 *   USER, privateRootKeyUUID, system, UUID_SRK);
139547e946e7SWyllys Ingersoll 	 * - store privateRootKeyUUID in users private token space.
139647e946e7SWyllys Ingersoll 	 */
139747e946e7SWyllys Ingersoll 	if ((result = tss_generate_key(hContext, initFlags, NULL, hSRK,
139847e946e7SWyllys Ingersoll 	    &hPrivateRootKey))) {
139947e946e7SWyllys Ingersoll 		return (result);
140047e946e7SWyllys Ingersoll 	}
140147e946e7SWyllys Ingersoll 	if (local_uuid_is_null(&privateRootKeyUUID))
140247e946e7SWyllys Ingersoll 		local_uuid_generate(&privateRootKeyUUID);
140347e946e7SWyllys Ingersoll 
140447e946e7SWyllys Ingersoll 	result = Tspi_Context_RegisterKey(hContext, hPrivateRootKey,
140547e946e7SWyllys Ingersoll 	    TSS_PS_TYPE_USER, privateRootKeyUUID,
140647e946e7SWyllys Ingersoll 	    TSS_PS_TYPE_SYSTEM, SRK_UUID);
140747e946e7SWyllys Ingersoll 
140847e946e7SWyllys Ingersoll 	if (result) {
140947e946e7SWyllys Ingersoll 		local_uuid_clear(&privateRootKeyUUID);
141047e946e7SWyllys Ingersoll 		return (result);
141147e946e7SWyllys Ingersoll 	}
141247e946e7SWyllys Ingersoll 
141347e946e7SWyllys Ingersoll 	ret = add_uuid(TPMTOK_PRIVATE_ROOT_KEY_ID, &privateRootKeyUUID);
141447e946e7SWyllys Ingersoll 	if (ret) {
141547e946e7SWyllys Ingersoll 		result = Tspi_Context_UnregisterKey(hContext,
141647e946e7SWyllys Ingersoll 		    TSS_PS_TYPE_USER, privateRootKeyUUID,
141747e946e7SWyllys Ingersoll 		    &hPrivateRootKey);
141847e946e7SWyllys Ingersoll 		return (CKR_FUNCTION_FAILED);
141947e946e7SWyllys Ingersoll 	}
142047e946e7SWyllys Ingersoll 
142147e946e7SWyllys Ingersoll 	if ((result = Tspi_Key_LoadKey(hPrivateRootKey, hSRK))) {
142247e946e7SWyllys Ingersoll 		stlogit("Tspi_Key_LoadKey: 0x%0x - %s",
142347e946e7SWyllys Ingersoll 		    result, Trspi_Error_String(result));
142447e946e7SWyllys Ingersoll 		Tspi_Context_CloseObject(hContext, hPrivateRootKey);
142547e946e7SWyllys Ingersoll 
142647e946e7SWyllys Ingersoll 		(void) remove_uuid(TPMTOK_PRIVATE_ROOT_KEY_ID);
142747e946e7SWyllys Ingersoll 		local_uuid_clear(&privateRootKeyUUID);
142847e946e7SWyllys Ingersoll 
142947e946e7SWyllys Ingersoll 		hPrivateRootKey = NULL_HKEY;
143047e946e7SWyllys Ingersoll 		return (CKR_FUNCTION_FAILED);
143147e946e7SWyllys Ingersoll 	}
143247e946e7SWyllys Ingersoll 
143347e946e7SWyllys Ingersoll 
143447e946e7SWyllys Ingersoll 	/* generate the private leaf key */
143547e946e7SWyllys Ingersoll 	if ((rc = token_generate_leaf_key(hContext,
143647e946e7SWyllys Ingersoll 	    TPMTOK_PRIVATE_LEAF_KEY,
143747e946e7SWyllys Ingersoll 	    pinHash, &hPrivateLeafKey))) {
143847e946e7SWyllys Ingersoll 		return (rc);
143947e946e7SWyllys Ingersoll 	}
144047e946e7SWyllys Ingersoll 
144147e946e7SWyllys Ingersoll 	if ((result = Tspi_Key_LoadKey(hPrivateLeafKey, hPrivateRootKey))) {
144247e946e7SWyllys Ingersoll 		stlogit("Tspi_Key_LoadKey: 0x%0x - %s",
144347e946e7SWyllys Ingersoll 		    result, Trspi_Error_String(result));
144447e946e7SWyllys Ingersoll 
144547e946e7SWyllys Ingersoll 		(void) Tspi_Context_UnregisterKey(hContext,
144647e946e7SWyllys Ingersoll 		    TSS_PS_TYPE_USER, privateLeafKeyUUID,
144747e946e7SWyllys Ingersoll 		    &hPrivateLeafKey);
144847e946e7SWyllys Ingersoll 		(void) remove_uuid(TPMTOK_PRIVATE_LEAF_KEY_ID);
144947e946e7SWyllys Ingersoll 		local_uuid_clear(&privateLeafKeyUUID);
145047e946e7SWyllys Ingersoll 
145147e946e7SWyllys Ingersoll 		(void) Tspi_Context_UnregisterKey(hContext,
145247e946e7SWyllys Ingersoll 		    TSS_PS_TYPE_USER, privateRootKeyUUID,
145347e946e7SWyllys Ingersoll 		    &hPrivateRootKey);
145447e946e7SWyllys Ingersoll 		(void) remove_uuid(TPMTOK_PRIVATE_ROOT_KEY_ID);
145547e946e7SWyllys Ingersoll 		local_uuid_clear(&privateRootKeyUUID);
145647e946e7SWyllys Ingersoll 
145747e946e7SWyllys Ingersoll 		Tspi_Context_CloseObject(hContext, hPrivateRootKey);
145847e946e7SWyllys Ingersoll 		hPrivateRootKey = NULL_HKEY;
145947e946e7SWyllys Ingersoll 
146047e946e7SWyllys Ingersoll 		Tspi_Context_CloseObject(hContext, hPrivateLeafKey);
146147e946e7SWyllys Ingersoll 		hPrivateRootKey = NULL_HKEY;
146247e946e7SWyllys Ingersoll 
146347e946e7SWyllys Ingersoll 		return (CKR_FUNCTION_FAILED);
146447e946e7SWyllys Ingersoll 	}
146547e946e7SWyllys Ingersoll 	return (rc);
146647e946e7SWyllys Ingersoll }
146747e946e7SWyllys Ingersoll 
146847e946e7SWyllys Ingersoll static CK_RV
token_create_public_tree(TSS_HCONTEXT hContext,CK_BYTE * pinHash)146947e946e7SWyllys Ingersoll token_create_public_tree(TSS_HCONTEXT hContext, CK_BYTE *pinHash)
147047e946e7SWyllys Ingersoll {
147147e946e7SWyllys Ingersoll 	CK_RV		rc;
147247e946e7SWyllys Ingersoll 	TSS_RESULT	result;
147347e946e7SWyllys Ingersoll 	int		ret;
147447e946e7SWyllys Ingersoll 	TSS_FLAG initFlags = TSS_KEY_SIZE_2048 |
147547e946e7SWyllys Ingersoll 	    TSS_KEY_NO_AUTHORIZATION | TSS_KEY_TYPE_STORAGE;
147647e946e7SWyllys Ingersoll 	TSS_UUID srk_uuid = TSS_UUID_SRK;
147747e946e7SWyllys Ingersoll 	TSS_HKEY hSRK;
147847e946e7SWyllys Ingersoll 
147947e946e7SWyllys Ingersoll 	if (token_load_srk(hContext, &hSRK))
148047e946e7SWyllys Ingersoll 		return (CKR_FUNCTION_FAILED);
148147e946e7SWyllys Ingersoll 
148247e946e7SWyllys Ingersoll 	/*
148347e946e7SWyllys Ingersoll 	 * - create publicRootKeyUUID
148447e946e7SWyllys Ingersoll 	 * - Tspi_Context_RegisterKey(hContext, hPublicRootKey,
148547e946e7SWyllys Ingersoll 	 *   USER, publicRootKeyUUID, system, UUID_SRK);
148647e946e7SWyllys Ingersoll 	 * - store publicRootKeyUUID in users private token space.
148747e946e7SWyllys Ingersoll 	 */
148847e946e7SWyllys Ingersoll 	if ((result = tss_generate_key(hContext, initFlags, NULL, hSRK,
148947e946e7SWyllys Ingersoll 	    &hPublicRootKey))) {
149047e946e7SWyllys Ingersoll 		return (CKR_FUNCTION_FAILED);
149147e946e7SWyllys Ingersoll 	}
149247e946e7SWyllys Ingersoll 	if (local_uuid_is_null(&publicRootKeyUUID))
149347e946e7SWyllys Ingersoll 		local_uuid_generate(&publicRootKeyUUID);
149447e946e7SWyllys Ingersoll 
149547e946e7SWyllys Ingersoll 	result = Tspi_Context_RegisterKey(hContext, hPublicRootKey,
149647e946e7SWyllys Ingersoll 	    TSS_PS_TYPE_USER, publicRootKeyUUID,
149747e946e7SWyllys Ingersoll 	    TSS_PS_TYPE_SYSTEM, srk_uuid);
149847e946e7SWyllys Ingersoll 
149947e946e7SWyllys Ingersoll 	if (result) {
150047e946e7SWyllys Ingersoll 		local_uuid_clear(&publicRootKeyUUID);
150147e946e7SWyllys Ingersoll 		return (CKR_FUNCTION_FAILED);
150247e946e7SWyllys Ingersoll 	}
150347e946e7SWyllys Ingersoll 
150447e946e7SWyllys Ingersoll 	ret = add_uuid(TPMTOK_PUBLIC_ROOT_KEY_ID, &publicRootKeyUUID);
150547e946e7SWyllys Ingersoll 	if (ret) {
150647e946e7SWyllys Ingersoll 		result = Tspi_Context_UnregisterKey(hContext,
150747e946e7SWyllys Ingersoll 		    TSS_PS_TYPE_USER, publicRootKeyUUID,
150847e946e7SWyllys Ingersoll 		    &hPublicRootKey);
150947e946e7SWyllys Ingersoll 		/* does result matter here? */
151047e946e7SWyllys Ingersoll 		return (CKR_FUNCTION_FAILED);
151147e946e7SWyllys Ingersoll 	}
151247e946e7SWyllys Ingersoll 
151347e946e7SWyllys Ingersoll 	/* Load the newly created publicRootKey into the TPM using the SRK */
151447e946e7SWyllys Ingersoll 	if ((result = Tspi_Key_LoadKey(hPublicRootKey, hSRK))) {
151547e946e7SWyllys Ingersoll 		stlogit("Tspi_Key_LoadKey: 0x%x - %s", result,
151647e946e7SWyllys Ingersoll 		    Trspi_Error_String(result));
151747e946e7SWyllys Ingersoll 		Tspi_Context_CloseObject(hContext, hPublicRootKey);
151847e946e7SWyllys Ingersoll 		hPublicRootKey = NULL_HKEY;
151947e946e7SWyllys Ingersoll 		return (CKR_FUNCTION_FAILED);
152047e946e7SWyllys Ingersoll 	}
152147e946e7SWyllys Ingersoll 
152247e946e7SWyllys Ingersoll 	/* create the SO's leaf key */
152347e946e7SWyllys Ingersoll 	if ((rc = token_generate_leaf_key(hContext, TPMTOK_PUBLIC_LEAF_KEY,
152447e946e7SWyllys Ingersoll 	    pinHash, &hPublicLeafKey))) {
152547e946e7SWyllys Ingersoll 		return (rc);
152647e946e7SWyllys Ingersoll 	}
152747e946e7SWyllys Ingersoll 
152847e946e7SWyllys Ingersoll 	if ((result = Tspi_Key_LoadKey(hPublicLeafKey, hPublicRootKey))) {
152947e946e7SWyllys Ingersoll 		stlogit("Tspi_Key_LoadKey: 0x%0x - %s",
153047e946e7SWyllys Ingersoll 		    result, Trspi_Error_String(result));
153147e946e7SWyllys Ingersoll 
153247e946e7SWyllys Ingersoll 		/* Unregister keys and clear UUIDs */
153347e946e7SWyllys Ingersoll 		(void) Tspi_Context_UnregisterKey(hContext,
153447e946e7SWyllys Ingersoll 		    TSS_PS_TYPE_USER, publicLeafKeyUUID,
153547e946e7SWyllys Ingersoll 		    &hPublicLeafKey);
153647e946e7SWyllys Ingersoll 		(void) remove_uuid(TPMTOK_PUBLIC_LEAF_KEY_ID);
153747e946e7SWyllys Ingersoll 
153847e946e7SWyllys Ingersoll 		(void) Tspi_Context_UnregisterKey(hContext,
153947e946e7SWyllys Ingersoll 		    TSS_PS_TYPE_USER, publicRootKeyUUID,
154047e946e7SWyllys Ingersoll 		    &hPublicRootKey);
154147e946e7SWyllys Ingersoll 		(void) remove_uuid(TPMTOK_PUBLIC_ROOT_KEY_ID);
154247e946e7SWyllys Ingersoll 
154347e946e7SWyllys Ingersoll 		Tspi_Context_CloseObject(hContext, hPublicRootKey);
154447e946e7SWyllys Ingersoll 		hPublicRootKey = NULL_HKEY;
154547e946e7SWyllys Ingersoll 
154647e946e7SWyllys Ingersoll 		Tspi_Context_CloseObject(hContext, hPublicLeafKey);
154747e946e7SWyllys Ingersoll 		hPublicLeafKey = NULL_HKEY;
154847e946e7SWyllys Ingersoll 
154947e946e7SWyllys Ingersoll 		return (CKR_FUNCTION_FAILED);
155047e946e7SWyllys Ingersoll 	}
155147e946e7SWyllys Ingersoll 
155247e946e7SWyllys Ingersoll 	return (rc);
155347e946e7SWyllys Ingersoll }
155447e946e7SWyllys Ingersoll 
155547e946e7SWyllys Ingersoll CK_RV
token_specific_login(TSS_HCONTEXT hContext,CK_USER_TYPE userType,CK_CHAR_PTR pPin,CK_ULONG ulPinLen)155647e946e7SWyllys Ingersoll token_specific_login(
155747e946e7SWyllys Ingersoll 	TSS_HCONTEXT hContext,
155847e946e7SWyllys Ingersoll 	CK_USER_TYPE userType,
155947e946e7SWyllys Ingersoll 	CK_CHAR_PTR pPin,
156047e946e7SWyllys Ingersoll 	CK_ULONG ulPinLen)
156147e946e7SWyllys Ingersoll {
156247e946e7SWyllys Ingersoll 	CK_RV rc;
156347e946e7SWyllys Ingersoll 	CK_BYTE hash_sha[SHA1_DIGEST_LENGTH];
156447e946e7SWyllys Ingersoll 	TSS_RESULT result;
156547e946e7SWyllys Ingersoll 	TSS_HKEY hSRK;
156647e946e7SWyllys Ingersoll 
156747e946e7SWyllys Ingersoll 	/* Make sure the SRK is loaded into the TPM */
156847e946e7SWyllys Ingersoll 	if ((result = token_load_srk(hContext, &hSRK))) {
156947e946e7SWyllys Ingersoll 		return (CKR_FUNCTION_FAILED);
157047e946e7SWyllys Ingersoll 	}
157147e946e7SWyllys Ingersoll 
157247e946e7SWyllys Ingersoll 	if ((rc = compute_sha(pPin, ulPinLen, hash_sha))) {
157347e946e7SWyllys Ingersoll 		return (CKR_FUNCTION_FAILED);
157447e946e7SWyllys Ingersoll 	}
157547e946e7SWyllys Ingersoll 
157647e946e7SWyllys Ingersoll 	if (userType == CKU_USER) {
157747e946e7SWyllys Ingersoll 		/*
157847e946e7SWyllys Ingersoll 		 * If the public root key doesn't exist yet,
157947e946e7SWyllys Ingersoll 		 * the SO hasn't init'd the token.
158047e946e7SWyllys Ingersoll 		 */
158147e946e7SWyllys Ingersoll 		if ((result = token_load_public_root_key(hContext))) {
158247e946e7SWyllys Ingersoll 			if (result == TPM_E_DECRYPT_ERROR) {
158347e946e7SWyllys Ingersoll 				return (CKR_USER_PIN_NOT_INITIALIZED);
158447e946e7SWyllys Ingersoll 			}
158547e946e7SWyllys Ingersoll 		}
158647e946e7SWyllys Ingersoll 
158747e946e7SWyllys Ingersoll 		/*
158847e946e7SWyllys Ingersoll 		 * - find privateRootKeyUUID
158947e946e7SWyllys Ingersoll 		 * - load by UUID (SRK parent)
159047e946e7SWyllys Ingersoll 		 */
159147e946e7SWyllys Ingersoll 		if (local_uuid_is_null(&privateRootKeyUUID) &&
159247e946e7SWyllys Ingersoll 		    find_uuid(TPMTOK_PRIVATE_ROOT_KEY_ID,
159347e946e7SWyllys Ingersoll 		    &privateRootKeyUUID)) {
159447e946e7SWyllys Ingersoll 				if (memcmp(hash_sha,
159547e946e7SWyllys Ingersoll 				    default_user_pin_sha,
159647e946e7SWyllys Ingersoll 				    SHA1_DIGEST_LENGTH))
159747e946e7SWyllys Ingersoll 					return (CKR_PIN_INCORRECT);
159847e946e7SWyllys Ingersoll 
159947e946e7SWyllys Ingersoll 				not_initialized = 1;
160047e946e7SWyllys Ingersoll 				return (CKR_OK);
160147e946e7SWyllys Ingersoll 		}
160247e946e7SWyllys Ingersoll 
160347e946e7SWyllys Ingersoll 		if ((rc = verify_user_pin(hContext, hash_sha))) {
160447e946e7SWyllys Ingersoll 			return (rc);
160547e946e7SWyllys Ingersoll 		}
160647e946e7SWyllys Ingersoll 
160747e946e7SWyllys Ingersoll 		(void) memcpy(current_user_pin_sha, hash_sha,
160847e946e7SWyllys Ingersoll 		    SHA1_DIGEST_LENGTH);
160947e946e7SWyllys Ingersoll 
161047e946e7SWyllys Ingersoll 		rc = load_private_token_objects(hContext);
161147e946e7SWyllys Ingersoll 		if (rc == CKR_OK) {
161247e946e7SWyllys Ingersoll 			(void) XProcLock(xproclock);
161347e946e7SWyllys Ingersoll 			global_shm->priv_loaded = TRUE;
161447e946e7SWyllys Ingersoll 			(void) XProcUnLock(xproclock);
161547e946e7SWyllys Ingersoll 		}
161647e946e7SWyllys Ingersoll 	} else {
161747e946e7SWyllys Ingersoll 		/*
161847e946e7SWyllys Ingersoll 		 * SO login logic:
161947e946e7SWyllys Ingersoll 		 *
162047e946e7SWyllys Ingersoll 		 * - find publicRootKey UUID
162147e946e7SWyllys Ingersoll 		 * - load by UUID wrap with hSRK from above
162247e946e7SWyllys Ingersoll 		 */
162347e946e7SWyllys Ingersoll 		if (local_uuid_is_null(&publicRootKeyUUID) &&
162447e946e7SWyllys Ingersoll 		    find_uuid(TPMTOK_PUBLIC_ROOT_KEY_ID,
162547e946e7SWyllys Ingersoll 		    &publicRootKeyUUID)) {
162647e946e7SWyllys Ingersoll 				if (memcmp(hash_sha,
162747e946e7SWyllys Ingersoll 				    default_so_pin_sha,
162847e946e7SWyllys Ingersoll 				    SHA1_DIGEST_LENGTH))
162947e946e7SWyllys Ingersoll 					return (CKR_PIN_INCORRECT);
163047e946e7SWyllys Ingersoll 
163147e946e7SWyllys Ingersoll 				not_initialized = 1;
163247e946e7SWyllys Ingersoll 				return (CKR_OK);
163347e946e7SWyllys Ingersoll 
163447e946e7SWyllys Ingersoll 		}
163547e946e7SWyllys Ingersoll 		if (hPublicRootKey == NULL_HKEY) {
163647e946e7SWyllys Ingersoll 			result = tss_find_and_load_key(
163747e946e7SWyllys Ingersoll 			    hContext,
163847e946e7SWyllys Ingersoll 			    TPMTOK_PUBLIC_ROOT_KEY_ID,
163947e946e7SWyllys Ingersoll 			    &publicRootKeyUUID, hSRK, NULL,
164047e946e7SWyllys Ingersoll 			    &hPublicRootKey);
164147e946e7SWyllys Ingersoll 
164247e946e7SWyllys Ingersoll 			if (result)
164347e946e7SWyllys Ingersoll 				return (CKR_FUNCTION_FAILED);
164447e946e7SWyllys Ingersoll 		}
164547e946e7SWyllys Ingersoll 
164647e946e7SWyllys Ingersoll 		/* find, load the public leaf key */
164747e946e7SWyllys Ingersoll 		if (hPublicLeafKey == NULL_HKEY) {
164847e946e7SWyllys Ingersoll 			result = tss_find_and_load_key(
164947e946e7SWyllys Ingersoll 			    hContext,
165047e946e7SWyllys Ingersoll 			    TPMTOK_PUBLIC_LEAF_KEY_ID,
165147e946e7SWyllys Ingersoll 			    &publicLeafKeyUUID, hPublicRootKey, hash_sha,
165247e946e7SWyllys Ingersoll 			    &hPublicLeafKey);
165347e946e7SWyllys Ingersoll 			if (result)
165447e946e7SWyllys Ingersoll 				return (CKR_FUNCTION_FAILED);
165547e946e7SWyllys Ingersoll 		}
165647e946e7SWyllys Ingersoll 
165747e946e7SWyllys Ingersoll 		if ((rc = token_verify_pin(hContext, hPublicLeafKey))) {
165847e946e7SWyllys Ingersoll 			return (rc);
165947e946e7SWyllys Ingersoll 		}
166047e946e7SWyllys Ingersoll 
166147e946e7SWyllys Ingersoll 		(void) memcpy(current_so_pin_sha, hash_sha, SHA1_DIGEST_LENGTH);
166247e946e7SWyllys Ingersoll 	}
166347e946e7SWyllys Ingersoll 
166447e946e7SWyllys Ingersoll 	return (rc);
166547e946e7SWyllys Ingersoll }
166647e946e7SWyllys Ingersoll 
166747e946e7SWyllys Ingersoll CK_RV
token_specific_logout(TSS_HCONTEXT hContext)166847e946e7SWyllys Ingersoll token_specific_logout(TSS_HCONTEXT hContext)
166947e946e7SWyllys Ingersoll {
167047e946e7SWyllys Ingersoll 	if (hPrivateLeafKey != NULL_HKEY) {
167147e946e7SWyllys Ingersoll 		Tspi_Key_UnloadKey(hPrivateLeafKey);
167247e946e7SWyllys Ingersoll 		hPrivateLeafKey = NULL_HKEY;
167347e946e7SWyllys Ingersoll 	} else if (hPublicLeafKey != NULL_HKEY) {
167447e946e7SWyllys Ingersoll 		Tspi_Key_UnloadKey(hPublicLeafKey);
167547e946e7SWyllys Ingersoll 		hPublicLeafKey = NULL_HKEY;
167647e946e7SWyllys Ingersoll 	}
167747e946e7SWyllys Ingersoll 
167847e946e7SWyllys Ingersoll 	local_uuid_clear(&publicRootKeyUUID);
167947e946e7SWyllys Ingersoll 	local_uuid_clear(&publicLeafKeyUUID);
168047e946e7SWyllys Ingersoll 	local_uuid_clear(&privateRootKeyUUID);
168147e946e7SWyllys Ingersoll 	local_uuid_clear(&privateLeafKeyUUID);
168247e946e7SWyllys Ingersoll 
168347e946e7SWyllys Ingersoll 	(void) memset(current_so_pin_sha, 0, SHA1_DIGEST_LENGTH);
168447e946e7SWyllys Ingersoll 	(void) memset(current_user_pin_sha, 0, SHA1_DIGEST_LENGTH);
168547e946e7SWyllys Ingersoll 
168647e946e7SWyllys Ingersoll 	(void) object_mgr_purge_private_token_objects(hContext);
168747e946e7SWyllys Ingersoll 
168847e946e7SWyllys Ingersoll 	return (CKR_OK);
168947e946e7SWyllys Ingersoll }
169047e946e7SWyllys Ingersoll 
169147e946e7SWyllys Ingersoll /*ARGSUSED*/
169247e946e7SWyllys Ingersoll CK_RV
token_specific_init_pin(TSS_HCONTEXT hContext,CK_CHAR_PTR pPin,CK_ULONG ulPinLen)169347e946e7SWyllys Ingersoll token_specific_init_pin(TSS_HCONTEXT hContext,
169447e946e7SWyllys Ingersoll 	CK_CHAR_PTR pPin, CK_ULONG ulPinLen)
169547e946e7SWyllys Ingersoll {
169647e946e7SWyllys Ingersoll 	/*
169747e946e7SWyllys Ingersoll 	 * Since the SO must log in before calling C_InitPIN, we will
169847e946e7SWyllys Ingersoll 	 * be able to return (CKR_OK) automatically here.
169947e946e7SWyllys Ingersoll 	 * This is because the USER key structure is created at the
170048bbca81SDaniel Hoffman 	 * time of their first login, not at C_InitPIN time.
170147e946e7SWyllys Ingersoll 	 */
170247e946e7SWyllys Ingersoll 	return (CKR_OK);
170347e946e7SWyllys Ingersoll }
170447e946e7SWyllys Ingersoll 
170547e946e7SWyllys Ingersoll static CK_RV
check_pin_properties(CK_USER_TYPE userType,CK_BYTE * pinHash,CK_ULONG ulPinLen)170647e946e7SWyllys Ingersoll check_pin_properties(CK_USER_TYPE userType, CK_BYTE *pinHash,
170747e946e7SWyllys Ingersoll 	CK_ULONG ulPinLen)
170847e946e7SWyllys Ingersoll {
170947e946e7SWyllys Ingersoll 	/* make sure the new PIN is different */
171047e946e7SWyllys Ingersoll 	if (userType == CKU_USER) {
171147e946e7SWyllys Ingersoll 		if (!memcmp(pinHash, default_user_pin_sha,
171247e946e7SWyllys Ingersoll 		    SHA1_DIGEST_LENGTH)) {
171347e946e7SWyllys Ingersoll 			LogError1("new PIN must not be the default");
171447e946e7SWyllys Ingersoll 			return (CKR_PIN_INVALID);
171547e946e7SWyllys Ingersoll 		}
171647e946e7SWyllys Ingersoll 	} else {
171747e946e7SWyllys Ingersoll 		if (!memcmp(pinHash, default_so_pin_sha,
171847e946e7SWyllys Ingersoll 		    SHA1_DIGEST_LENGTH)) {
171947e946e7SWyllys Ingersoll 			LogError1("new PIN must not be the default");
172047e946e7SWyllys Ingersoll 			return (CKR_PIN_INVALID);
172147e946e7SWyllys Ingersoll 		}
172247e946e7SWyllys Ingersoll 	}
172347e946e7SWyllys Ingersoll 
172447e946e7SWyllys Ingersoll 	if (ulPinLen > MAX_PIN_LEN || ulPinLen < MIN_PIN_LEN) {
172547e946e7SWyllys Ingersoll 		LogError1("New PIN is out of size range");
172647e946e7SWyllys Ingersoll 		return (CKR_PIN_LEN_RANGE);
172747e946e7SWyllys Ingersoll 	}
172847e946e7SWyllys Ingersoll 
172947e946e7SWyllys Ingersoll 	return (CKR_OK);
173047e946e7SWyllys Ingersoll }
173147e946e7SWyllys Ingersoll 
173247e946e7SWyllys Ingersoll /*
173347e946e7SWyllys Ingersoll  * This function is called from set_pin only, where a non-logged-in public
173447e946e7SWyllys Ingersoll  * session can provide the user pin which must be verified. This function
173547e946e7SWyllys Ingersoll  * assumes that the pin has already been set once, so there's no migration
173647e946e7SWyllys Ingersoll  * path option or checking of the default user pin.
173747e946e7SWyllys Ingersoll  */
173847e946e7SWyllys Ingersoll static CK_RV
verify_user_pin(TSS_HCONTEXT hContext,CK_BYTE * hash_sha)173947e946e7SWyllys Ingersoll verify_user_pin(TSS_HCONTEXT hContext, CK_BYTE *hash_sha)
174047e946e7SWyllys Ingersoll {
174147e946e7SWyllys Ingersoll 	CK_RV rc;
174247e946e7SWyllys Ingersoll 	TSS_RESULT result;
174347e946e7SWyllys Ingersoll 	TSS_HKEY hSRK;
174447e946e7SWyllys Ingersoll 
174547e946e7SWyllys Ingersoll 	if (token_load_srk(hContext, &hSRK))
174647e946e7SWyllys Ingersoll 		return (CKR_FUNCTION_FAILED);
174747e946e7SWyllys Ingersoll 
174847e946e7SWyllys Ingersoll 	/*
174947e946e7SWyllys Ingersoll 	 * Verify the user by loading the privateLeafKey
175047e946e7SWyllys Ingersoll 	 * into the TPM (if it's not already) and then
175147e946e7SWyllys Ingersoll 	 * call the verify_pin operation.
175247e946e7SWyllys Ingersoll 	 *
175347e946e7SWyllys Ingersoll 	 * The hashed PIN is assigned to the private leaf key.
175447e946e7SWyllys Ingersoll 	 * If it is incorrect (not the same as the one originally
175547e946e7SWyllys Ingersoll 	 * used when the key was created), the verify operation
175647e946e7SWyllys Ingersoll 	 * will fail.
175747e946e7SWyllys Ingersoll 	 */
175847e946e7SWyllys Ingersoll 	if (hPrivateRootKey == NULL_HKEY) {
175947e946e7SWyllys Ingersoll 		result = tss_find_and_load_key(
176047e946e7SWyllys Ingersoll 		    hContext,
176147e946e7SWyllys Ingersoll 		    TPMTOK_PRIVATE_ROOT_KEY_ID,
176247e946e7SWyllys Ingersoll 		    &privateRootKeyUUID, hSRK, NULL, &hPrivateRootKey);
176347e946e7SWyllys Ingersoll 		if (result)
176447e946e7SWyllys Ingersoll 			return (CKR_FUNCTION_FAILED);
176547e946e7SWyllys Ingersoll 	}
176647e946e7SWyllys Ingersoll 
176747e946e7SWyllys Ingersoll 	if (hPrivateLeafKey == NULL_HKEY) {
176847e946e7SWyllys Ingersoll 		result = tss_find_and_load_key(
176947e946e7SWyllys Ingersoll 		    hContext,
177047e946e7SWyllys Ingersoll 		    TPMTOK_PRIVATE_LEAF_KEY_ID,
177147e946e7SWyllys Ingersoll 		    &privateLeafKeyUUID, hPrivateRootKey, hash_sha,
177247e946e7SWyllys Ingersoll 		    &hPrivateLeafKey);
177347e946e7SWyllys Ingersoll 
177447e946e7SWyllys Ingersoll 		if (result)
177547e946e7SWyllys Ingersoll 			return (CKR_FUNCTION_FAILED);
177647e946e7SWyllys Ingersoll 	}
177747e946e7SWyllys Ingersoll 
177847e946e7SWyllys Ingersoll 	/*
177947e946e7SWyllys Ingersoll 	 * Verify that the PIN is correct by attempting to wrap/unwrap some
178047e946e7SWyllys Ingersoll 	 * random data.
178147e946e7SWyllys Ingersoll 	 */
178247e946e7SWyllys Ingersoll 	if ((rc = token_verify_pin(hContext, hPrivateLeafKey))) {
178347e946e7SWyllys Ingersoll 		return (rc);
178447e946e7SWyllys Ingersoll 	}
178547e946e7SWyllys Ingersoll 
178647e946e7SWyllys Ingersoll 	return (CKR_OK);
178747e946e7SWyllys Ingersoll }
178847e946e7SWyllys Ingersoll 
178947e946e7SWyllys Ingersoll CK_RV
token_specific_set_pin(ST_SESSION_HANDLE session,CK_CHAR_PTR pOldPin,CK_ULONG ulOldPinLen,CK_CHAR_PTR pNewPin,CK_ULONG ulNewPinLen)179047e946e7SWyllys Ingersoll token_specific_set_pin(ST_SESSION_HANDLE session,
179147e946e7SWyllys Ingersoll 	CK_CHAR_PTR pOldPin, CK_ULONG ulOldPinLen,
179247e946e7SWyllys Ingersoll 	CK_CHAR_PTR pNewPin, CK_ULONG ulNewPinLen)
179347e946e7SWyllys Ingersoll {
179447e946e7SWyllys Ingersoll 	SESSION		*sess = session_mgr_find(session.sessionh);
179547e946e7SWyllys Ingersoll 	CK_BYTE		oldpin_hash[SHA1_DIGEST_LENGTH];
179647e946e7SWyllys Ingersoll 	CK_BYTE		newpin_hash[SHA1_DIGEST_LENGTH];
179747e946e7SWyllys Ingersoll 	CK_RV		rc;
179847e946e7SWyllys Ingersoll 	TSS_HKEY	hSRK;
179947e946e7SWyllys Ingersoll 
180047e946e7SWyllys Ingersoll 	if (!sess) {
180147e946e7SWyllys Ingersoll 		return (CKR_SESSION_HANDLE_INVALID);
180247e946e7SWyllys Ingersoll 	}
180347e946e7SWyllys Ingersoll 
180447e946e7SWyllys Ingersoll 	if ((rc = compute_sha(pOldPin, ulOldPinLen, oldpin_hash))) {
180547e946e7SWyllys Ingersoll 		return (CKR_FUNCTION_FAILED);
180647e946e7SWyllys Ingersoll 	}
180747e946e7SWyllys Ingersoll 	if ((rc = compute_sha(pNewPin, ulNewPinLen, newpin_hash))) {
180847e946e7SWyllys Ingersoll 		return (CKR_FUNCTION_FAILED);
180947e946e7SWyllys Ingersoll 	}
181047e946e7SWyllys Ingersoll 
181147e946e7SWyllys Ingersoll 	if (token_load_srk(sess->hContext, &hSRK)) {
181247e946e7SWyllys Ingersoll 		return (CKR_FUNCTION_FAILED);
181347e946e7SWyllys Ingersoll 	}
181447e946e7SWyllys Ingersoll 
181547e946e7SWyllys Ingersoll 	/*
181647e946e7SWyllys Ingersoll 	 * From the PKCS#11 2.20 spec: "C_SetPIN modifies the PIN of
181747e946e7SWyllys Ingersoll 	 * the user that is currently logged in, or the CKU_USER PIN
181847e946e7SWyllys Ingersoll 	 * if the session is not logged in."
181947e946e7SWyllys Ingersoll 	 * A non R/W session fails with CKR_SESSION_READ_ONLY.
182047e946e7SWyllys Ingersoll 	 */
182147e946e7SWyllys Ingersoll 	if (sess->session_info.state == CKS_RW_USER_FUNCTIONS ||
182247e946e7SWyllys Ingersoll 	    sess->session_info.state == CKS_RW_PUBLIC_SESSION) {
182347e946e7SWyllys Ingersoll 		if (not_initialized) {
182447e946e7SWyllys Ingersoll 			if (memcmp(oldpin_hash, default_user_pin_sha,
182547e946e7SWyllys Ingersoll 			    SHA1_DIGEST_LENGTH)) {
182647e946e7SWyllys Ingersoll 				return (CKR_PIN_INCORRECT);
182747e946e7SWyllys Ingersoll 			}
182847e946e7SWyllys Ingersoll 
182947e946e7SWyllys Ingersoll 			if ((rc = check_pin_properties(CKU_USER, newpin_hash,
183047e946e7SWyllys Ingersoll 			    ulNewPinLen))) {
183147e946e7SWyllys Ingersoll 				return (rc);
183247e946e7SWyllys Ingersoll 			}
183347e946e7SWyllys Ingersoll 
183447e946e7SWyllys Ingersoll 			if ((rc = token_create_private_tree(sess->hContext,
183547e946e7SWyllys Ingersoll 			    newpin_hash))) {
183647e946e7SWyllys Ingersoll 				return (CKR_FUNCTION_FAILED);
183747e946e7SWyllys Ingersoll 			}
183847e946e7SWyllys Ingersoll 
183947e946e7SWyllys Ingersoll 			nv_token_data->token_info.flags &=
184047e946e7SWyllys Ingersoll 			    ~(CKF_USER_PIN_TO_BE_CHANGED);
184147e946e7SWyllys Ingersoll 			nv_token_data->token_info.flags |=
184247e946e7SWyllys Ingersoll 			    CKF_USER_PIN_INITIALIZED;
184347e946e7SWyllys Ingersoll 
184447e946e7SWyllys Ingersoll 			nv_token_data->token_info.flags &=
184547e946e7SWyllys Ingersoll 			    ~(CKF_USER_PIN_TO_BE_CHANGED);
184647e946e7SWyllys Ingersoll 			nv_token_data->token_info.flags |=
184747e946e7SWyllys Ingersoll 			    CKF_USER_PIN_INITIALIZED;
184847e946e7SWyllys Ingersoll 
184947e946e7SWyllys Ingersoll 			return (save_token_data(nv_token_data));
185047e946e7SWyllys Ingersoll 		}
185147e946e7SWyllys Ingersoll 
185247e946e7SWyllys Ingersoll 		if (sess->session_info.state == CKS_RW_USER_FUNCTIONS) {
185347e946e7SWyllys Ingersoll 			/* if we're already logged in, just verify the hash */
185447e946e7SWyllys Ingersoll 			if (memcmp(current_user_pin_sha, oldpin_hash,
185547e946e7SWyllys Ingersoll 			    SHA1_DIGEST_LENGTH)) {
185647e946e7SWyllys Ingersoll 				return (CKR_PIN_INCORRECT);
185747e946e7SWyllys Ingersoll 			}
185847e946e7SWyllys Ingersoll 		} else {
185947e946e7SWyllys Ingersoll 			if ((rc = verify_user_pin(sess->hContext,
186047e946e7SWyllys Ingersoll 			    oldpin_hash))) {
186147e946e7SWyllys Ingersoll 				return (rc);
186247e946e7SWyllys Ingersoll 			}
186347e946e7SWyllys Ingersoll 		}
186447e946e7SWyllys Ingersoll 
186547e946e7SWyllys Ingersoll 		if ((rc = check_pin_properties(CKU_USER, newpin_hash,
186647e946e7SWyllys Ingersoll 		    ulNewPinLen)))
186747e946e7SWyllys Ingersoll 			return (rc);
186847e946e7SWyllys Ingersoll 
186947e946e7SWyllys Ingersoll 		/* change the auth on the TSS object */
187047e946e7SWyllys Ingersoll 		if (tss_change_auth(sess->hContext,
187147e946e7SWyllys Ingersoll 		    hPrivateLeafKey, hPrivateRootKey,
187247e946e7SWyllys Ingersoll 		    privateLeafKeyUUID, privateRootKeyUUID,
187347e946e7SWyllys Ingersoll 		    newpin_hash))
187447e946e7SWyllys Ingersoll 			return (CKR_FUNCTION_FAILED);
187547e946e7SWyllys Ingersoll 
187647e946e7SWyllys Ingersoll 	} else if (sess->session_info.state == CKS_RW_SO_FUNCTIONS) {
187747e946e7SWyllys Ingersoll 		if (not_initialized) {
187847e946e7SWyllys Ingersoll 			if (memcmp(default_so_pin_sha, oldpin_hash,
187947e946e7SWyllys Ingersoll 			    SHA1_DIGEST_LENGTH))
188047e946e7SWyllys Ingersoll 				return (CKR_PIN_INCORRECT);
188147e946e7SWyllys Ingersoll 
188247e946e7SWyllys Ingersoll 			if ((rc = check_pin_properties(CKU_SO,
188347e946e7SWyllys Ingersoll 			    newpin_hash, ulNewPinLen)))
188447e946e7SWyllys Ingersoll 				return (rc);
188547e946e7SWyllys Ingersoll 
188647e946e7SWyllys Ingersoll 			if ((rc = token_create_public_tree(sess->hContext,
188747e946e7SWyllys Ingersoll 			    newpin_hash)))
188847e946e7SWyllys Ingersoll 				return (CKR_FUNCTION_FAILED);
188947e946e7SWyllys Ingersoll 
189047e946e7SWyllys Ingersoll 			nv_token_data->token_info.flags &=
189147e946e7SWyllys Ingersoll 			    ~(CKF_SO_PIN_TO_BE_CHANGED);
189247e946e7SWyllys Ingersoll 
189347e946e7SWyllys Ingersoll 			return (save_token_data(nv_token_data));
189447e946e7SWyllys Ingersoll 		}
189547e946e7SWyllys Ingersoll 
189647e946e7SWyllys Ingersoll 		if (memcmp(current_so_pin_sha, oldpin_hash,
189747e946e7SWyllys Ingersoll 		    SHA1_DIGEST_LENGTH))
189847e946e7SWyllys Ingersoll 			return (CKR_PIN_INCORRECT);
189947e946e7SWyllys Ingersoll 
190047e946e7SWyllys Ingersoll 		if ((rc = check_pin_properties(CKU_SO, newpin_hash,
190147e946e7SWyllys Ingersoll 		    ulNewPinLen)))
190247e946e7SWyllys Ingersoll 			return (rc);
190347e946e7SWyllys Ingersoll 
190447e946e7SWyllys Ingersoll 		/* change auth on the SO's leaf key */
190547e946e7SWyllys Ingersoll 		if (tss_change_auth(sess->hContext,
190647e946e7SWyllys Ingersoll 		    hPublicLeafKey, hPublicRootKey,
190747e946e7SWyllys Ingersoll 		    publicLeafKeyUUID, publicRootKeyUUID,
190847e946e7SWyllys Ingersoll 		    newpin_hash))
190947e946e7SWyllys Ingersoll 			return (CKR_FUNCTION_FAILED);
191047e946e7SWyllys Ingersoll 
191147e946e7SWyllys Ingersoll 	} else {
191247e946e7SWyllys Ingersoll 		rc = CKR_SESSION_READ_ONLY;
191347e946e7SWyllys Ingersoll 	}
191447e946e7SWyllys Ingersoll 
191547e946e7SWyllys Ingersoll 	return (rc);
191647e946e7SWyllys Ingersoll }
191747e946e7SWyllys Ingersoll 
191847e946e7SWyllys Ingersoll /* only called at token init time */
191947e946e7SWyllys Ingersoll CK_RV
token_specific_verify_so_pin(TSS_HCONTEXT hContext,CK_CHAR_PTR pPin,CK_ULONG ulPinLen)192047e946e7SWyllys Ingersoll token_specific_verify_so_pin(TSS_HCONTEXT hContext, CK_CHAR_PTR pPin,
192147e946e7SWyllys Ingersoll     CK_ULONG ulPinLen)
192247e946e7SWyllys Ingersoll {
192347e946e7SWyllys Ingersoll 	CK_BYTE hash_sha[SHA1_DIGEST_LENGTH];
192447e946e7SWyllys Ingersoll 	CK_RV rc;
192547e946e7SWyllys Ingersoll 	TSS_RESULT result;
192647e946e7SWyllys Ingersoll 	TSS_HKEY hSRK;
192747e946e7SWyllys Ingersoll 
192847e946e7SWyllys Ingersoll 	if ((rc = compute_sha(pPin, ulPinLen, hash_sha))) {
192947e946e7SWyllys Ingersoll 		return (CKR_FUNCTION_FAILED);
193047e946e7SWyllys Ingersoll 	}
193147e946e7SWyllys Ingersoll 	if ((rc = token_load_srk(hContext, &hSRK))) {
193247e946e7SWyllys Ingersoll 		return (CKR_FUNCTION_FAILED);
193347e946e7SWyllys Ingersoll 	}
193447e946e7SWyllys Ingersoll 
193547e946e7SWyllys Ingersoll 	/*
193647e946e7SWyllys Ingersoll 	 * TRYME INSTEAD:
193747e946e7SWyllys Ingersoll 	 * - find publicRootKeyUUID
193847e946e7SWyllys Ingersoll 	 * - Load publicRootKey by UUID (SRK parent)
193947e946e7SWyllys Ingersoll 	 * - find publicLeafKeyUUID
194047e946e7SWyllys Ingersoll 	 * - Load publicLeafKey by UUID (publicRootKey parent)
194147e946e7SWyllys Ingersoll 	 * - set password policy on publicLeafKey
194247e946e7SWyllys Ingersoll 	 */
194347e946e7SWyllys Ingersoll 	if (local_uuid_is_null(&publicRootKeyUUID) &&
194447e946e7SWyllys Ingersoll 	    find_uuid(TPMTOK_PUBLIC_ROOT_KEY_ID, &publicRootKeyUUID)) {
194547e946e7SWyllys Ingersoll 		/*
194648bbca81SDaniel Hoffman 		 * The SO hasn't set their PIN yet, compare the
194747e946e7SWyllys Ingersoll 		 * login pin with the hard-coded value.
194847e946e7SWyllys Ingersoll 		 */
194947e946e7SWyllys Ingersoll 		if (memcmp(default_so_pin_sha, hash_sha,
195047e946e7SWyllys Ingersoll 		    SHA1_DIGEST_LENGTH)) {
195147e946e7SWyllys Ingersoll 			return (CKR_PIN_INCORRECT);
195247e946e7SWyllys Ingersoll 		}
195347e946e7SWyllys Ingersoll 		return (CKR_OK);
195447e946e7SWyllys Ingersoll 	}
195547e946e7SWyllys Ingersoll 
195647e946e7SWyllys Ingersoll 	result = Tspi_Context_GetKeyByUUID(hContext,
195747e946e7SWyllys Ingersoll 	    TSS_PS_TYPE_USER, publicRootKeyUUID, &hPublicRootKey);
195847e946e7SWyllys Ingersoll 
195947e946e7SWyllys Ingersoll 	if (result)
196047e946e7SWyllys Ingersoll 		return (CKR_FUNCTION_FAILED);
196147e946e7SWyllys Ingersoll 
196247e946e7SWyllys Ingersoll 	result = Tspi_Key_LoadKey(hPublicRootKey, hSRK);
196347e946e7SWyllys Ingersoll 	if (result)
196447e946e7SWyllys Ingersoll 		return (CKR_FUNCTION_FAILED);
196547e946e7SWyllys Ingersoll 
196647e946e7SWyllys Ingersoll 	if (local_uuid_is_null(&publicLeafKeyUUID) &&
196747e946e7SWyllys Ingersoll 	    find_uuid(TPMTOK_PUBLIC_LEAF_KEY_ID, &publicLeafKeyUUID))
196847e946e7SWyllys Ingersoll 		return (CKR_FUNCTION_FAILED);
196947e946e7SWyllys Ingersoll 
197047e946e7SWyllys Ingersoll 	result = Tspi_Context_GetKeyByUUID(hContext,
197147e946e7SWyllys Ingersoll 	    TSS_PS_TYPE_USER, publicLeafKeyUUID, &hPublicLeafKey);
197247e946e7SWyllys Ingersoll 	if (result)
197347e946e7SWyllys Ingersoll 		return (CKR_FUNCTION_FAILED);
197447e946e7SWyllys Ingersoll 
1975ab8176c2SWyllys Ingersoll 	result = tss_assign_secret_key_policy(hContext, TSS_POLICY_USAGE,
1976ab8176c2SWyllys Ingersoll 	    hPublicLeafKey, hash_sha);
197747e946e7SWyllys Ingersoll 	if (result)
197847e946e7SWyllys Ingersoll 		return (CKR_FUNCTION_FAILED);
197947e946e7SWyllys Ingersoll 
198047e946e7SWyllys Ingersoll 	result = Tspi_Key_LoadKey(hPublicLeafKey, hPublicRootKey);
198147e946e7SWyllys Ingersoll 	if (result)
198247e946e7SWyllys Ingersoll 		return (CKR_FUNCTION_FAILED);
198347e946e7SWyllys Ingersoll 
198447e946e7SWyllys Ingersoll 	/* If the hash given is wrong, the verify will fail */
198547e946e7SWyllys Ingersoll 	if ((rc = token_verify_pin(hContext, hPublicLeafKey))) {
198647e946e7SWyllys Ingersoll 		return (rc);
198747e946e7SWyllys Ingersoll 	}
198847e946e7SWyllys Ingersoll 
198947e946e7SWyllys Ingersoll 	return (CKR_OK);
199047e946e7SWyllys Ingersoll }
199147e946e7SWyllys Ingersoll 
199247e946e7SWyllys Ingersoll CK_RV
token_specific_final(TSS_HCONTEXT hContext)1993ab8176c2SWyllys Ingersoll token_specific_final(TSS_HCONTEXT hContext)
199447e946e7SWyllys Ingersoll {
1995ab8176c2SWyllys Ingersoll 	if (hPublicRootKey != NULL_HKEY) {
1996ab8176c2SWyllys Ingersoll 		Tspi_Context_CloseObject(hContext, hPublicRootKey);
1997ab8176c2SWyllys Ingersoll 		hPublicRootKey = NULL_HKEY;
1998ab8176c2SWyllys Ingersoll 	}
1999ab8176c2SWyllys Ingersoll 	if (hPublicLeafKey != NULL_HKEY) {
2000ab8176c2SWyllys Ingersoll 		Tspi_Context_CloseObject(hContext, hPublicLeafKey);
2001ab8176c2SWyllys Ingersoll 		hPublicLeafKey = NULL_HKEY;
2002ab8176c2SWyllys Ingersoll 	}
2003ab8176c2SWyllys Ingersoll 	if (hPrivateRootKey != NULL_HKEY) {
2004ab8176c2SWyllys Ingersoll 		Tspi_Context_CloseObject(hContext, hPrivateRootKey);
2005ab8176c2SWyllys Ingersoll 		hPrivateRootKey = NULL_HKEY;
2006ab8176c2SWyllys Ingersoll 	}
2007ab8176c2SWyllys Ingersoll 	if (hPrivateLeafKey != NULL_HKEY) {
2008ab8176c2SWyllys Ingersoll 		Tspi_Context_CloseObject(hContext, hPrivateLeafKey);
2009ab8176c2SWyllys Ingersoll 		hPrivateLeafKey = NULL_HKEY;
2010ab8176c2SWyllys Ingersoll 	}
201147e946e7SWyllys Ingersoll 	return (CKR_OK);
201247e946e7SWyllys Ingersoll }
201347e946e7SWyllys Ingersoll 
201447e946e7SWyllys Ingersoll /*
201547e946e7SWyllys Ingersoll  * Wrap the 20 bytes of auth data and store in an attribute of the two
201647e946e7SWyllys Ingersoll  * keys.
201747e946e7SWyllys Ingersoll  */
201847e946e7SWyllys Ingersoll static CK_RV
token_wrap_auth_data(TSS_HCONTEXT hContext,CK_BYTE * authData,TEMPLATE * publ_tmpl,TEMPLATE * priv_tmpl)201947e946e7SWyllys Ingersoll token_wrap_auth_data(TSS_HCONTEXT hContext,
202047e946e7SWyllys Ingersoll 	CK_BYTE *authData, TEMPLATE *publ_tmpl,
202147e946e7SWyllys Ingersoll 	TEMPLATE *priv_tmpl)
202247e946e7SWyllys Ingersoll {
202347e946e7SWyllys Ingersoll 	CK_RV		rc;
202447e946e7SWyllys Ingersoll 	CK_ATTRIBUTE	*new_attr;
202547e946e7SWyllys Ingersoll 
202647e946e7SWyllys Ingersoll 	TSS_RESULT	ret;
202747e946e7SWyllys Ingersoll 	TSS_HKEY	hParentKey;
202847e946e7SWyllys Ingersoll 	TSS_HENCDATA	hEncData;
202947e946e7SWyllys Ingersoll 	BYTE		*blob;
203047e946e7SWyllys Ingersoll 	UINT32		blob_size;
203147e946e7SWyllys Ingersoll 
203247e946e7SWyllys Ingersoll 	if ((hPrivateLeafKey == NULL_HKEY) && (hPublicLeafKey == NULL_HKEY)) {
203347e946e7SWyllys Ingersoll 		return (CKR_FUNCTION_FAILED);
203447e946e7SWyllys Ingersoll 	} else if (hPublicLeafKey != NULL_HKEY) {
203547e946e7SWyllys Ingersoll 		hParentKey = hPublicLeafKey;
203647e946e7SWyllys Ingersoll 	} else {
203747e946e7SWyllys Ingersoll 		hParentKey = hPrivateLeafKey;
203847e946e7SWyllys Ingersoll 	}
203947e946e7SWyllys Ingersoll 
204047e946e7SWyllys Ingersoll 	/* create the encrypted data object */
204147e946e7SWyllys Ingersoll 	if ((ret = Tspi_Context_CreateObject(hContext,
204247e946e7SWyllys Ingersoll 	    TSS_OBJECT_TYPE_ENCDATA, TSS_ENCDATA_BIND, &hEncData))) {
204347e946e7SWyllys Ingersoll 		stlogit("Tspi_Context_CreateObject: 0x%0x - %s",
204447e946e7SWyllys Ingersoll 		    ret, Trspi_Error_String(ret));
204547e946e7SWyllys Ingersoll 		return (CKR_FUNCTION_FAILED);
204647e946e7SWyllys Ingersoll 	}
204747e946e7SWyllys Ingersoll 
204847e946e7SWyllys Ingersoll 	if ((ret = Tspi_Data_Bind(hEncData, hParentKey, SHA1_DIGEST_LENGTH,
204947e946e7SWyllys Ingersoll 	    authData))) {
205047e946e7SWyllys Ingersoll 		stlogit("Tspi_Data_Bind: 0x%0x - %s",
205147e946e7SWyllys Ingersoll 		    ret, Trspi_Error_String(ret));
205247e946e7SWyllys Ingersoll 		return (CKR_FUNCTION_FAILED);
205347e946e7SWyllys Ingersoll 	}
205447e946e7SWyllys Ingersoll 
205547e946e7SWyllys Ingersoll 	/* pull the encrypted data out of the encrypted data object */
205647e946e7SWyllys Ingersoll 	if ((ret = Tspi_GetAttribData(hEncData, TSS_TSPATTRIB_ENCDATA_BLOB,
205747e946e7SWyllys Ingersoll 	    TSS_TSPATTRIB_ENCDATABLOB_BLOB, &blob_size, &blob))) {
205847e946e7SWyllys Ingersoll 		stlogit("Tspi_SetAttribData: 0x%0x - %s",
205947e946e7SWyllys Ingersoll 		    ret, Trspi_Error_String(ret));
206047e946e7SWyllys Ingersoll 		return (CKR_FUNCTION_FAILED);
206147e946e7SWyllys Ingersoll 	}
206247e946e7SWyllys Ingersoll 
206347e946e7SWyllys Ingersoll 	if ((rc = build_attribute(CKA_ENC_AUTHDATA, blob, blob_size,
206447e946e7SWyllys Ingersoll 	    &new_attr))) {
206547e946e7SWyllys Ingersoll 		return (rc);
206647e946e7SWyllys Ingersoll 	}
206747e946e7SWyllys Ingersoll 	(void) template_update_attribute(publ_tmpl, new_attr);
206847e946e7SWyllys Ingersoll 
206947e946e7SWyllys Ingersoll 	if ((rc = build_attribute(CKA_ENC_AUTHDATA, blob,
207047e946e7SWyllys Ingersoll 	    blob_size, &new_attr))) {
207147e946e7SWyllys Ingersoll 		return (rc);
207247e946e7SWyllys Ingersoll 	}
207347e946e7SWyllys Ingersoll 	(void) template_update_attribute(priv_tmpl, new_attr);
207447e946e7SWyllys Ingersoll 
207547e946e7SWyllys Ingersoll 	return (rc);
207647e946e7SWyllys Ingersoll }
207747e946e7SWyllys Ingersoll 
207847e946e7SWyllys Ingersoll static CK_RV
token_unwrap_auth_data(TSS_HCONTEXT hContext,CK_BYTE * encAuthData,CK_ULONG encAuthDataLen,TSS_HKEY hKey,BYTE ** authData)207947e946e7SWyllys Ingersoll token_unwrap_auth_data(TSS_HCONTEXT hContext, CK_BYTE *encAuthData,
208047e946e7SWyllys Ingersoll 	CK_ULONG encAuthDataLen, TSS_HKEY hKey,
208147e946e7SWyllys Ingersoll 	BYTE **authData)
208247e946e7SWyllys Ingersoll {
208347e946e7SWyllys Ingersoll 	TSS_RESULT	result;
208447e946e7SWyllys Ingersoll 	TSS_HENCDATA	hEncData;
208547e946e7SWyllys Ingersoll 	BYTE		*buf;
208647e946e7SWyllys Ingersoll 	UINT32		buf_size;
208747e946e7SWyllys Ingersoll 
208847e946e7SWyllys Ingersoll 	if ((result = Tspi_Context_CreateObject(hContext,
208947e946e7SWyllys Ingersoll 	    TSS_OBJECT_TYPE_ENCDATA, TSS_ENCDATA_BIND, &hEncData))) {
209047e946e7SWyllys Ingersoll 		stlogit("Tspi_Context_CreateObject: 0x%0x - %s",
209147e946e7SWyllys Ingersoll 		    result, Trspi_Error_String(result));
209247e946e7SWyllys Ingersoll 		return (CKR_FUNCTION_FAILED);
209347e946e7SWyllys Ingersoll 	}
209447e946e7SWyllys Ingersoll 
209547e946e7SWyllys Ingersoll 	if ((result = Tspi_SetAttribData(hEncData,
209647e946e7SWyllys Ingersoll 	    TSS_TSPATTRIB_ENCDATA_BLOB, TSS_TSPATTRIB_ENCDATABLOB_BLOB,
209747e946e7SWyllys Ingersoll 	    encAuthDataLen, encAuthData))) {
209847e946e7SWyllys Ingersoll 		stlogit("Tspi_SetAttribData: 0x%0x - %s",
209947e946e7SWyllys Ingersoll 		    result, Trspi_Error_String(result));
210047e946e7SWyllys Ingersoll 		return (CKR_FUNCTION_FAILED);
210147e946e7SWyllys Ingersoll 	}
210247e946e7SWyllys Ingersoll 
210347e946e7SWyllys Ingersoll 	/* unbind the data, receiving the plaintext back */
210447e946e7SWyllys Ingersoll 	if ((result = Tspi_Data_Unbind(hEncData, hKey, &buf_size, &buf))) {
210547e946e7SWyllys Ingersoll 		stlogit("Tspi_Data_Unbind: 0x%0x - %s",
210647e946e7SWyllys Ingersoll 		    result, Trspi_Error_String(result));
210747e946e7SWyllys Ingersoll 		return (CKR_FUNCTION_FAILED);
210847e946e7SWyllys Ingersoll 	}
210947e946e7SWyllys Ingersoll 
211047e946e7SWyllys Ingersoll 	if (buf_size != SHA1_DIGEST_LENGTH) {
211147e946e7SWyllys Ingersoll 		return (CKR_FUNCTION_FAILED);
211247e946e7SWyllys Ingersoll 	}
211347e946e7SWyllys Ingersoll 
211447e946e7SWyllys Ingersoll 	*authData = buf;
211547e946e7SWyllys Ingersoll 
211647e946e7SWyllys Ingersoll 	return (CKR_OK);
211747e946e7SWyllys Ingersoll }
211847e946e7SWyllys Ingersoll 
211947e946e7SWyllys Ingersoll CK_RV
token_specific_rsa_generate_keypair(TSS_HCONTEXT hContext,TEMPLATE * publ_tmpl,TEMPLATE * priv_tmpl)212047e946e7SWyllys Ingersoll token_specific_rsa_generate_keypair(
212147e946e7SWyllys Ingersoll 	TSS_HCONTEXT hContext,
212247e946e7SWyllys Ingersoll 	TEMPLATE  *publ_tmpl,
212347e946e7SWyllys Ingersoll 	TEMPLATE  *priv_tmpl)
212447e946e7SWyllys Ingersoll {
212547e946e7SWyllys Ingersoll 	CK_ATTRIBUTE	*attr = NULL;
212647e946e7SWyllys Ingersoll 	CK_ULONG	mod_bits = 0;
212747e946e7SWyllys Ingersoll 	CK_BBOOL	flag;
212847e946e7SWyllys Ingersoll 	CK_RV		rc;
212947e946e7SWyllys Ingersoll 
213047e946e7SWyllys Ingersoll 	TSS_FLAG	initFlags = 0;
213147e946e7SWyllys Ingersoll 	BYTE		authHash[SHA1_DIGEST_LENGTH];
213247e946e7SWyllys Ingersoll 	BYTE		*authData = NULL;
213347e946e7SWyllys Ingersoll 	TSS_HKEY	hKey = NULL_HKEY;
213447e946e7SWyllys Ingersoll 	TSS_HKEY	hParentKey = NULL_HKEY;
213547e946e7SWyllys Ingersoll 	TSS_RESULT	result;
213647e946e7SWyllys Ingersoll 	UINT32		ulBlobLen;
213747e946e7SWyllys Ingersoll 	BYTE		*rgbBlob;
213847e946e7SWyllys Ingersoll 
213947e946e7SWyllys Ingersoll 	/* Make sure the public exponent is usable */
214047e946e7SWyllys Ingersoll 	if ((util_check_public_exponent(publ_tmpl))) {
214147e946e7SWyllys Ingersoll 		return (CKR_TEMPLATE_INCONSISTENT);
214247e946e7SWyllys Ingersoll 	}
214347e946e7SWyllys Ingersoll 
214447e946e7SWyllys Ingersoll 	flag = template_attribute_find(publ_tmpl, CKA_MODULUS_BITS, &attr);
214547e946e7SWyllys Ingersoll 	if (!flag) {
214647e946e7SWyllys Ingersoll 		return (CKR_TEMPLATE_INCOMPLETE);
214747e946e7SWyllys Ingersoll 	}
214847e946e7SWyllys Ingersoll 	mod_bits = *(CK_ULONG *)attr->pValue;
214947e946e7SWyllys Ingersoll 
215047e946e7SWyllys Ingersoll 	if ((initFlags = util_get_keysize_flag(mod_bits)) == 0) {
215147e946e7SWyllys Ingersoll 		return (CKR_KEY_SIZE_RANGE);
215247e946e7SWyllys Ingersoll 	}
215347e946e7SWyllys Ingersoll 
215447e946e7SWyllys Ingersoll 	/*
215547e946e7SWyllys Ingersoll 	 * If we're not logged in, hPrivateLeafKey and hPublicLeafKey
215647e946e7SWyllys Ingersoll 	 * should be NULL.
215747e946e7SWyllys Ingersoll 	 */
215847e946e7SWyllys Ingersoll 	if ((hPrivateLeafKey == NULL_HKEY) &&
215947e946e7SWyllys Ingersoll 	    (hPublicLeafKey == NULL_HKEY)) {
216047e946e7SWyllys Ingersoll 		/* public session, wrap key with the PRK */
216147e946e7SWyllys Ingersoll 		initFlags |= TSS_KEY_TYPE_LEGACY |
216247e946e7SWyllys Ingersoll 		    TSS_KEY_NO_AUTHORIZATION | TSS_KEY_MIGRATABLE;
216347e946e7SWyllys Ingersoll 
216447e946e7SWyllys Ingersoll 		if ((result = token_load_public_root_key(hContext))) {
216547e946e7SWyllys Ingersoll 			return (CKR_FUNCTION_FAILED);
216647e946e7SWyllys Ingersoll 		}
216747e946e7SWyllys Ingersoll 
216847e946e7SWyllys Ingersoll 		hParentKey = hPublicRootKey;
216947e946e7SWyllys Ingersoll 	} else if (hPrivateLeafKey != NULL_HKEY) {
217047e946e7SWyllys Ingersoll 		/* logged in USER session */
217147e946e7SWyllys Ingersoll 		initFlags |= TSS_KEY_TYPE_LEGACY |
217247e946e7SWyllys Ingersoll 		    TSS_KEY_AUTHORIZATION | TSS_KEY_MIGRATABLE;
217347e946e7SWyllys Ingersoll 
217447e946e7SWyllys Ingersoll 		/* get a random SHA1 hash for the auth data */
217547e946e7SWyllys Ingersoll 		if ((rc = token_rng(hContext, authHash, SHA1_DIGEST_LENGTH))) {
217647e946e7SWyllys Ingersoll 			return (CKR_FUNCTION_FAILED);
217747e946e7SWyllys Ingersoll 		}
217847e946e7SWyllys Ingersoll 
217947e946e7SWyllys Ingersoll 		authData = authHash;
218047e946e7SWyllys Ingersoll 		hParentKey = hPrivateRootKey;
218147e946e7SWyllys Ingersoll 	} else {
218247e946e7SWyllys Ingersoll 		/* logged in SO session */
218347e946e7SWyllys Ingersoll 		initFlags |= TSS_KEY_TYPE_LEGACY |
218447e946e7SWyllys Ingersoll 		    TSS_KEY_AUTHORIZATION | TSS_KEY_MIGRATABLE;
218547e946e7SWyllys Ingersoll 
218647e946e7SWyllys Ingersoll 		/* get a random SHA1 hash for the auth data */
218747e946e7SWyllys Ingersoll 		if ((rc = token_rng(hContext, authHash, SHA1_DIGEST_LENGTH))) {
218847e946e7SWyllys Ingersoll 			return (CKR_FUNCTION_FAILED);
218947e946e7SWyllys Ingersoll 		}
219047e946e7SWyllys Ingersoll 
219147e946e7SWyllys Ingersoll 		authData = authHash;
219247e946e7SWyllys Ingersoll 		hParentKey = hPublicRootKey;
219347e946e7SWyllys Ingersoll 	}
219447e946e7SWyllys Ingersoll 
219547e946e7SWyllys Ingersoll 	if ((result = tss_generate_key(hContext, initFlags, authData,
219647e946e7SWyllys Ingersoll 	    hParentKey, &hKey))) {
219747e946e7SWyllys Ingersoll 		return (result);
219847e946e7SWyllys Ingersoll 	}
219947e946e7SWyllys Ingersoll 
220047e946e7SWyllys Ingersoll 	if ((result = Tspi_GetAttribData(hKey, TSS_TSPATTRIB_KEY_BLOB,
220147e946e7SWyllys Ingersoll 	    TSS_TSPATTRIB_KEYBLOB_BLOB, &ulBlobLen, &rgbBlob))) {
220247e946e7SWyllys Ingersoll 		stlogit("Tspi_GetAttribData: 0x%0x - %s",
220347e946e7SWyllys Ingersoll 		    result, Trspi_Error_String(result));
220447e946e7SWyllys Ingersoll 		return (CKR_FUNCTION_FAILED);
220547e946e7SWyllys Ingersoll 	}
220647e946e7SWyllys Ingersoll 
220747e946e7SWyllys Ingersoll 	if ((rc = build_attribute(CKA_IBM_OPAQUE, rgbBlob,
220847e946e7SWyllys Ingersoll 	    ulBlobLen, &attr))) {
220947e946e7SWyllys Ingersoll 		Tspi_Context_FreeMemory(hContext, rgbBlob);
221047e946e7SWyllys Ingersoll 		return (rc);
221147e946e7SWyllys Ingersoll 	}
221247e946e7SWyllys Ingersoll 	(void) template_update_attribute(priv_tmpl, attr);
221347e946e7SWyllys Ingersoll 	if ((rc = build_attribute(CKA_IBM_OPAQUE, rgbBlob,
221447e946e7SWyllys Ingersoll 	    ulBlobLen, &attr))) {
221547e946e7SWyllys Ingersoll 		Tspi_Context_FreeMemory(hContext, rgbBlob);
221647e946e7SWyllys Ingersoll 		return (rc);
221747e946e7SWyllys Ingersoll 	}
221847e946e7SWyllys Ingersoll 	(void) template_update_attribute(publ_tmpl, attr);
221947e946e7SWyllys Ingersoll 
222047e946e7SWyllys Ingersoll 	Tspi_Context_FreeMemory(hContext, rgbBlob);
222147e946e7SWyllys Ingersoll 
222247e946e7SWyllys Ingersoll 	/* grab the public key to put into the public key object */
222347e946e7SWyllys Ingersoll 	if ((result = Tspi_GetAttribData(hKey, TSS_TSPATTRIB_RSAKEY_INFO,
222447e946e7SWyllys Ingersoll 	    TSS_TSPATTRIB_KEYINFO_RSA_MODULUS, &ulBlobLen, &rgbBlob))) {
222547e946e7SWyllys Ingersoll 		stlogit("Tspi_GetAttribData: 0x%0x - %s",
222647e946e7SWyllys Ingersoll 		    result, Trspi_Error_String(result));
222747e946e7SWyllys Ingersoll 		return (result);
222847e946e7SWyllys Ingersoll 	}
222947e946e7SWyllys Ingersoll 
223047e946e7SWyllys Ingersoll 	/* add the public key blob to the object template */
223147e946e7SWyllys Ingersoll 	if ((rc = build_attribute(CKA_MODULUS, rgbBlob, ulBlobLen, &attr))) {
223247e946e7SWyllys Ingersoll 		Tspi_Context_FreeMemory(hContext, rgbBlob);
223347e946e7SWyllys Ingersoll 		return (rc);
223447e946e7SWyllys Ingersoll 	}
223547e946e7SWyllys Ingersoll 	(void) template_update_attribute(publ_tmpl, attr);
223647e946e7SWyllys Ingersoll 
223747e946e7SWyllys Ingersoll 	/* add the public key blob to the object template */
223847e946e7SWyllys Ingersoll 	if ((rc = build_attribute(CKA_MODULUS, rgbBlob, ulBlobLen, &attr))) {
223947e946e7SWyllys Ingersoll 		Tspi_Context_FreeMemory(hContext, rgbBlob);
224047e946e7SWyllys Ingersoll 		return (rc);
224147e946e7SWyllys Ingersoll 	}
224247e946e7SWyllys Ingersoll 	(void) template_update_attribute(priv_tmpl, attr);
224347e946e7SWyllys Ingersoll 	Tspi_Context_FreeMemory(hContext, rgbBlob);
224447e946e7SWyllys Ingersoll 
224547e946e7SWyllys Ingersoll 	/* wrap the authdata and put it into an object */
224647e946e7SWyllys Ingersoll 	if (authData != NULL) {
224747e946e7SWyllys Ingersoll 		rc = token_wrap_auth_data(hContext, authData, publ_tmpl,
224847e946e7SWyllys Ingersoll 		    priv_tmpl);
224947e946e7SWyllys Ingersoll 	}
225047e946e7SWyllys Ingersoll 
225147e946e7SWyllys Ingersoll 	return (rc);
225247e946e7SWyllys Ingersoll }
225347e946e7SWyllys Ingersoll 
225447e946e7SWyllys Ingersoll static CK_RV
token_rsa_load_key(TSS_HCONTEXT hContext,OBJECT * key_obj,TSS_HKEY * phKey)225547e946e7SWyllys Ingersoll token_rsa_load_key(
225647e946e7SWyllys Ingersoll 	TSS_HCONTEXT hContext,
225747e946e7SWyllys Ingersoll 	OBJECT *key_obj,
225847e946e7SWyllys Ingersoll 	TSS_HKEY *phKey)
225947e946e7SWyllys Ingersoll {
226047e946e7SWyllys Ingersoll 	TSS_RESULT result;
226147e946e7SWyllys Ingersoll 	TSS_HPOLICY hPolicy = NULL_HPOLICY;
226247e946e7SWyllys Ingersoll 	TSS_HKEY	hParentKey;
226347e946e7SWyllys Ingersoll 	BYTE		*authData = NULL;
226447e946e7SWyllys Ingersoll 	CK_ATTRIBUTE	*attr;
226547e946e7SWyllys Ingersoll 	CK_RV		rc;
226647e946e7SWyllys Ingersoll 	CK_OBJECT_HANDLE handle;
2267ab8176c2SWyllys Ingersoll 	CK_ULONG	class;
226847e946e7SWyllys Ingersoll 
226947e946e7SWyllys Ingersoll 	if (hPrivateLeafKey != NULL_HKEY) {
227047e946e7SWyllys Ingersoll 		hParentKey = hPrivateRootKey;
227147e946e7SWyllys Ingersoll 	} else {
227247e946e7SWyllys Ingersoll 		if ((result = token_load_public_root_key(hContext)))
227347e946e7SWyllys Ingersoll 			return (CKR_FUNCTION_FAILED);
227447e946e7SWyllys Ingersoll 
227547e946e7SWyllys Ingersoll 		hParentKey = hPublicRootKey;
227647e946e7SWyllys Ingersoll 	}
227747e946e7SWyllys Ingersoll 
2278*e2e372a4SToomas Soome 	*phKey = 0;
2279ab8176c2SWyllys Ingersoll 	if (template_attribute_find(key_obj->template, CKA_CLASS,
2280ab8176c2SWyllys Ingersoll 	    &attr) == FALSE) {
2281ab8176c2SWyllys Ingersoll 		return (CKR_TEMPLATE_INCOMPLETE);
2282ab8176c2SWyllys Ingersoll 	}
2283ab8176c2SWyllys Ingersoll 	class = *((CK_ULONG *)attr->pValue);
2284ab8176c2SWyllys Ingersoll 
2285ab8176c2SWyllys Ingersoll 	rc = template_attribute_find(key_obj->template,
2286ab8176c2SWyllys Ingersoll 	    CKA_IBM_OPAQUE, &attr);
2287ab8176c2SWyllys Ingersoll 	/*
2288ab8176c2SWyllys Ingersoll 	 * A public key cannot use the OPAQUE data attribute so they
2289ab8176c2SWyllys Ingersoll 	 * must be created in software.  A private key may not yet
2290ab8176c2SWyllys Ingersoll 	 * have its "opaque" data defined and needs to be created
2291ab8176c2SWyllys Ingersoll 	 * and loaded so it can be used inside the TPM.
2292ab8176c2SWyllys Ingersoll 	 */
2293ab8176c2SWyllys Ingersoll 	if (class == CKO_PUBLIC_KEY || rc == FALSE) {
229447e946e7SWyllys Ingersoll 		rc = object_mgr_find_in_map2(hContext, key_obj, &handle);
229547e946e7SWyllys Ingersoll 		if (rc != CKR_OK)
229647e946e7SWyllys Ingersoll 			return (CKR_FUNCTION_FAILED);
229747e946e7SWyllys Ingersoll 
229847e946e7SWyllys Ingersoll 		if ((rc = token_load_key(hContext,
229947e946e7SWyllys Ingersoll 		    handle, hParentKey, NULL, phKey))) {
230047e946e7SWyllys Ingersoll 			return (rc);
230147e946e7SWyllys Ingersoll 		}
230247e946e7SWyllys Ingersoll 	}
2303ab8176c2SWyllys Ingersoll 	/*
2304ab8176c2SWyllys Ingersoll 	 * If this is a private key, get the blob and load it in the TPM.
2305ab8176c2SWyllys Ingersoll 	 * If it is public, the key is already loaded in software.
2306ab8176c2SWyllys Ingersoll 	 */
2307ab8176c2SWyllys Ingersoll 	if (class == CKO_PRIVATE_KEY) {
2308ab8176c2SWyllys Ingersoll 		/* If we already have a handle, just load it */
2309*e2e372a4SToomas Soome 		if (*phKey != 0) {
2310ab8176c2SWyllys Ingersoll 			result = Tspi_Key_LoadKey(*phKey, hParentKey);
2311ab8176c2SWyllys Ingersoll 			if (result) {
2312ab8176c2SWyllys Ingersoll 				stlogit("Tspi_Context_LoadKeyByBlob: "
2313ab8176c2SWyllys Ingersoll 				    "0x%0x - %s",
2314ab8176c2SWyllys Ingersoll 				    result, Trspi_Error_String(result));
2315ab8176c2SWyllys Ingersoll 				return (CKR_FUNCTION_FAILED);
2316ab8176c2SWyllys Ingersoll 			}
2317ab8176c2SWyllys Ingersoll 		} else {
2318ab8176c2SWyllys Ingersoll 			/* try again to get the CKA_IBM_OPAQUE attr */
2319ab8176c2SWyllys Ingersoll 			if ((rc = template_attribute_find(key_obj->template,
2320ab8176c2SWyllys Ingersoll 			    CKA_IBM_OPAQUE, &attr)) == FALSE) {
2321ab8176c2SWyllys Ingersoll 				return (rc);
2322ab8176c2SWyllys Ingersoll 			}
2323ab8176c2SWyllys Ingersoll 			if ((result = Tspi_Context_LoadKeyByBlob(hContext,
2324ab8176c2SWyllys Ingersoll 			    hParentKey, attr->ulValueLen, attr->pValue,
2325ab8176c2SWyllys Ingersoll 			    phKey))) {
2326ab8176c2SWyllys Ingersoll 				stlogit("Tspi_Context_LoadKeyByBlob: "
2327ab8176c2SWyllys Ingersoll 				    "0x%0x - %s",
2328ab8176c2SWyllys Ingersoll 				    result, Trspi_Error_String(result));
2329ab8176c2SWyllys Ingersoll 				return (CKR_FUNCTION_FAILED);
2330ab8176c2SWyllys Ingersoll 			}
2331ab8176c2SWyllys Ingersoll 		}
233247e946e7SWyllys Ingersoll 	}
233347e946e7SWyllys Ingersoll 
233447e946e7SWyllys Ingersoll 	/* auth data may be required */
233547e946e7SWyllys Ingersoll 	if (template_attribute_find(key_obj->template, CKA_ENC_AUTHDATA,
233647e946e7SWyllys Ingersoll 	    &attr) == TRUE && attr) {
233747e946e7SWyllys Ingersoll 		if ((hPrivateLeafKey == NULL_HKEY) &&
233847e946e7SWyllys Ingersoll 		    (hPublicLeafKey == NULL_HKEY)) {
233947e946e7SWyllys Ingersoll 			return (CKR_FUNCTION_FAILED);
234047e946e7SWyllys Ingersoll 		} else if (hPublicLeafKey != NULL_HKEY) {
234147e946e7SWyllys Ingersoll 			hParentKey = hPublicLeafKey;
234247e946e7SWyllys Ingersoll 		} else {
234347e946e7SWyllys Ingersoll 			hParentKey = hPrivateLeafKey;
234447e946e7SWyllys Ingersoll 		}
234547e946e7SWyllys Ingersoll 
234647e946e7SWyllys Ingersoll 		if ((result = token_unwrap_auth_data(hContext,
2347ab8176c2SWyllys Ingersoll 		    attr->pValue, attr->ulValueLen,
2348ab8176c2SWyllys Ingersoll 		    hParentKey, &authData))) {
234947e946e7SWyllys Ingersoll 			return (CKR_FUNCTION_FAILED);
235047e946e7SWyllys Ingersoll 		}
235147e946e7SWyllys Ingersoll 
235247e946e7SWyllys Ingersoll 		if ((result = Tspi_GetPolicyObject(*phKey,
235347e946e7SWyllys Ingersoll 		    TSS_POLICY_USAGE, &hPolicy))) {
235447e946e7SWyllys Ingersoll 			stlogit("Tspi_GetPolicyObject: 0x%0x - %s",
235547e946e7SWyllys Ingersoll 			    result, Trspi_Error_String(result));
235647e946e7SWyllys Ingersoll 			return (CKR_FUNCTION_FAILED);
235747e946e7SWyllys Ingersoll 		}
235847e946e7SWyllys Ingersoll 
235947e946e7SWyllys Ingersoll 		/*
236047e946e7SWyllys Ingersoll 		 * If the policy handle returned is the same as the
236147e946e7SWyllys Ingersoll 		 * context's default policy, then a new policy must
236247e946e7SWyllys Ingersoll 		 * be created and assigned to the key. Otherwise, just set the
236347e946e7SWyllys Ingersoll 		 * secret in the policy.
236447e946e7SWyllys Ingersoll 		 */
236547e946e7SWyllys Ingersoll 		if (hPolicy == hDefaultPolicy) {
236647e946e7SWyllys Ingersoll 			if ((result = Tspi_Context_CreateObject(hContext,
236747e946e7SWyllys Ingersoll 			    TSS_OBJECT_TYPE_POLICY, TSS_POLICY_USAGE,
236847e946e7SWyllys Ingersoll 			    &hPolicy))) {
236947e946e7SWyllys Ingersoll 				stlogit("Tspi_Context_CreateObject: "
237047e946e7SWyllys Ingersoll 				    "0x%0x - %s",
237147e946e7SWyllys Ingersoll 				    result, Trspi_Error_String(result));
237247e946e7SWyllys Ingersoll 				return (CKR_FUNCTION_FAILED);
237347e946e7SWyllys Ingersoll 			}
237447e946e7SWyllys Ingersoll 
237547e946e7SWyllys Ingersoll 			if ((result = Tspi_Policy_SetSecret(hPolicy,
237647e946e7SWyllys Ingersoll 			    TSS_SECRET_MODE_SHA1,
237747e946e7SWyllys Ingersoll 			    SHA1_DIGEST_LENGTH, authData))) {
237847e946e7SWyllys Ingersoll 				stlogit("Tspi_Policy_SetSecret: "
237947e946e7SWyllys Ingersoll 				    "0x%0x - %s",
238047e946e7SWyllys Ingersoll 				    result, Trspi_Error_String(result));
238147e946e7SWyllys Ingersoll 				return (CKR_FUNCTION_FAILED);
238247e946e7SWyllys Ingersoll 			}
238347e946e7SWyllys Ingersoll 
238447e946e7SWyllys Ingersoll 			if ((result = Tspi_Policy_AssignToObject(hPolicy,
238547e946e7SWyllys Ingersoll 			    *phKey))) {
238647e946e7SWyllys Ingersoll 				stlogit("Tspi_Policy_AssignToObject: "
238747e946e7SWyllys Ingersoll 				    "0x%0x - %s",
238847e946e7SWyllys Ingersoll 				    result, Trspi_Error_String(result));
238947e946e7SWyllys Ingersoll 				return (CKR_FUNCTION_FAILED);
239047e946e7SWyllys Ingersoll 			}
239147e946e7SWyllys Ingersoll 		} else if ((result = Tspi_Policy_SetSecret(hPolicy,
239247e946e7SWyllys Ingersoll 		    TSS_SECRET_MODE_SHA1, SHA1_DIGEST_LENGTH, authData))) {
239347e946e7SWyllys Ingersoll 			stlogit("Tspi_Policy_SetSecret: 0x%0x - %s",
239447e946e7SWyllys Ingersoll 			    result, Trspi_Error_String(result));
239547e946e7SWyllys Ingersoll 			return (CKR_FUNCTION_FAILED);
239647e946e7SWyllys Ingersoll 		}
239747e946e7SWyllys Ingersoll 
239847e946e7SWyllys Ingersoll 		Tspi_Context_FreeMemory(hContext, authData);
239947e946e7SWyllys Ingersoll 	}
240047e946e7SWyllys Ingersoll 
240147e946e7SWyllys Ingersoll 	return (CKR_OK);
240247e946e7SWyllys Ingersoll }
240347e946e7SWyllys Ingersoll 
240447e946e7SWyllys Ingersoll CK_RV
tpm_decrypt_data(TSS_HCONTEXT hContext,TSS_HKEY hKey,CK_BYTE * in_data,CK_ULONG in_data_len,CK_BYTE * out_data,CK_ULONG * out_data_len)240547e946e7SWyllys Ingersoll tpm_decrypt_data(
240647e946e7SWyllys Ingersoll 	TSS_HCONTEXT hContext,
240747e946e7SWyllys Ingersoll 	TSS_HKEY    hKey,
240847e946e7SWyllys Ingersoll 	CK_BYTE   * in_data,
240947e946e7SWyllys Ingersoll 	CK_ULONG    in_data_len,
241047e946e7SWyllys Ingersoll 	CK_BYTE   * out_data,
241147e946e7SWyllys Ingersoll 	CK_ULONG  * out_data_len)
241247e946e7SWyllys Ingersoll {
241347e946e7SWyllys Ingersoll 	TSS_RESULT result;
241447e946e7SWyllys Ingersoll 	TSS_HENCDATA	hEncData = NULL_HENCDATA;
241547e946e7SWyllys Ingersoll 	UINT32		buf_size = 0, modLen;
241647e946e7SWyllys Ingersoll 	BYTE		*buf = NULL, *modulus = NULL;
241747e946e7SWyllys Ingersoll 	CK_ULONG	chunklen, remain, outlen;
241847e946e7SWyllys Ingersoll 
241947e946e7SWyllys Ingersoll 	/* push the data into the encrypted data object */
242047e946e7SWyllys Ingersoll 	if ((result = Tspi_Context_CreateObject(hContext,
242147e946e7SWyllys Ingersoll 	    TSS_OBJECT_TYPE_ENCDATA, TSS_ENCDATA_BIND, &hEncData))) {
242247e946e7SWyllys Ingersoll 		stlogit("Tspi_Context_CreateObject: 0x%0x - %s",
242347e946e7SWyllys Ingersoll 		    result, Trspi_Error_String(result));
242447e946e7SWyllys Ingersoll 		return (CKR_FUNCTION_FAILED);
242547e946e7SWyllys Ingersoll 	}
242647e946e7SWyllys Ingersoll 
242747e946e7SWyllys Ingersoll 	/*
242847e946e7SWyllys Ingersoll 	 * Figure out the modulus size so we can break the data
242947e946e7SWyllys Ingersoll 	 * into smaller chunks if necessary.
243047e946e7SWyllys Ingersoll 	 */
243147e946e7SWyllys Ingersoll 	if ((result = Tspi_GetAttribData(hKey, TSS_TSPATTRIB_RSAKEY_INFO,
243247e946e7SWyllys Ingersoll 	    TSS_TSPATTRIB_KEYINFO_RSA_MODULUS, &modLen, &modulus))) {
243347e946e7SWyllys Ingersoll 		stlogit("Tspi_GetAttribData: 0x%0x - %s",
243447e946e7SWyllys Ingersoll 		    result, Trspi_Error_String(result));
243547e946e7SWyllys Ingersoll 		return (result);
243647e946e7SWyllys Ingersoll 	}
243747e946e7SWyllys Ingersoll 	/* we don't need the actual modulus */
243847e946e7SWyllys Ingersoll 	Tspi_Context_FreeMemory(hContext, modulus);
243947e946e7SWyllys Ingersoll 
244047e946e7SWyllys Ingersoll 	chunklen = (in_data_len > modLen ? modLen : in_data_len);
244147e946e7SWyllys Ingersoll 	remain = in_data_len;
244247e946e7SWyllys Ingersoll 	outlen = 0;
244347e946e7SWyllys Ingersoll 
244447e946e7SWyllys Ingersoll 	while (remain > 0) {
244547e946e7SWyllys Ingersoll 		if ((result = Tspi_SetAttribData(hEncData,
244647e946e7SWyllys Ingersoll 		    TSS_TSPATTRIB_ENCDATA_BLOB,
244747e946e7SWyllys Ingersoll 		    TSS_TSPATTRIB_ENCDATABLOB_BLOB,
244847e946e7SWyllys Ingersoll 		    chunklen, in_data))) {
244947e946e7SWyllys Ingersoll 			stlogit("Tspi_SetAttribData: 0x%0x - %s",
245047e946e7SWyllys Ingersoll 			    result, Trspi_Error_String(result));
245147e946e7SWyllys Ingersoll 			return (CKR_FUNCTION_FAILED);
245247e946e7SWyllys Ingersoll 		}
245347e946e7SWyllys Ingersoll 
245447e946e7SWyllys Ingersoll 		/* unbind the data, receiving the plaintext back */
245547e946e7SWyllys Ingersoll 		if ((result = Tspi_Data_Unbind(hEncData, hKey,
245647e946e7SWyllys Ingersoll 		    &buf_size, &buf))) {
245747e946e7SWyllys Ingersoll 			stlogit("Tspi_Data_Unbind: 0x%0x - %s",
245847e946e7SWyllys Ingersoll 			    result, Trspi_Error_String(result));
245947e946e7SWyllys Ingersoll 			return (CKR_FUNCTION_FAILED);
246047e946e7SWyllys Ingersoll 		}
246147e946e7SWyllys Ingersoll 
246247e946e7SWyllys Ingersoll 		if (*out_data_len < buf_size + outlen) {
246347e946e7SWyllys Ingersoll 			Tspi_Context_FreeMemory(hContext, buf);
246447e946e7SWyllys Ingersoll 			return (CKR_BUFFER_TOO_SMALL);
246547e946e7SWyllys Ingersoll 		}
246647e946e7SWyllys Ingersoll 
246747e946e7SWyllys Ingersoll 		(void) memcpy(out_data + outlen, buf, buf_size);
246847e946e7SWyllys Ingersoll 
246947e946e7SWyllys Ingersoll 		outlen += buf_size;
247047e946e7SWyllys Ingersoll 		in_data += chunklen;
247147e946e7SWyllys Ingersoll 		remain -= chunklen;
247247e946e7SWyllys Ingersoll 
247347e946e7SWyllys Ingersoll 		Tspi_Context_FreeMemory(hContext, buf);
247447e946e7SWyllys Ingersoll 		if (chunklen > remain)
247547e946e7SWyllys Ingersoll 			chunklen = remain;
247647e946e7SWyllys Ingersoll 	}
247747e946e7SWyllys Ingersoll 	*out_data_len = outlen;
247847e946e7SWyllys Ingersoll 	return (CKR_OK);
247947e946e7SWyllys Ingersoll }
248047e946e7SWyllys Ingersoll 
248147e946e7SWyllys Ingersoll CK_RV
token_specific_rsa_decrypt(TSS_HCONTEXT hContext,CK_BYTE * in_data,CK_ULONG in_data_len,CK_BYTE * out_data,CK_ULONG * out_data_len,OBJECT * key_obj)248247e946e7SWyllys Ingersoll token_specific_rsa_decrypt(
248347e946e7SWyllys Ingersoll 	TSS_HCONTEXT hContext,
248447e946e7SWyllys Ingersoll 	CK_BYTE   * in_data,
248547e946e7SWyllys Ingersoll 	CK_ULONG    in_data_len,
248647e946e7SWyllys Ingersoll 	CK_BYTE   * out_data,
248747e946e7SWyllys Ingersoll 	CK_ULONG  * out_data_len,
248847e946e7SWyllys Ingersoll 	OBJECT	  * key_obj)
248947e946e7SWyllys Ingersoll {
249047e946e7SWyllys Ingersoll 	CK_RV		rc;
249147e946e7SWyllys Ingersoll 	TSS_HKEY	hKey;
249247e946e7SWyllys Ingersoll 
249347e946e7SWyllys Ingersoll 	if ((rc = token_rsa_load_key(hContext, key_obj, &hKey))) {
249447e946e7SWyllys Ingersoll 		return (rc);
249547e946e7SWyllys Ingersoll 	}
249647e946e7SWyllys Ingersoll 
249747e946e7SWyllys Ingersoll 	rc = tpm_decrypt_data(hContext, hKey, in_data, in_data_len,
249847e946e7SWyllys Ingersoll 	    out_data, out_data_len);
249947e946e7SWyllys Ingersoll 
250047e946e7SWyllys Ingersoll 	return (rc);
250147e946e7SWyllys Ingersoll }
250247e946e7SWyllys Ingersoll 
250347e946e7SWyllys Ingersoll CK_RV
token_specific_rsa_verify(TSS_HCONTEXT hContext,CK_BYTE * in_data,CK_ULONG in_data_len,CK_BYTE * sig,CK_ULONG sig_len,OBJECT * key_obj)250447e946e7SWyllys Ingersoll token_specific_rsa_verify(
250547e946e7SWyllys Ingersoll 	TSS_HCONTEXT hContext,
250647e946e7SWyllys Ingersoll 	CK_BYTE   * in_data,
250747e946e7SWyllys Ingersoll 	CK_ULONG    in_data_len,
250847e946e7SWyllys Ingersoll 	CK_BYTE   * sig,
250947e946e7SWyllys Ingersoll 	CK_ULONG    sig_len,
251047e946e7SWyllys Ingersoll 	OBJECT	  * key_obj)
251147e946e7SWyllys Ingersoll {
251247e946e7SWyllys Ingersoll 	TSS_RESULT	result;
251347e946e7SWyllys Ingersoll 	TSS_HHASH	hHash;
251447e946e7SWyllys Ingersoll 	TSS_HKEY	hKey;
251547e946e7SWyllys Ingersoll 	CK_RV		rc;
251647e946e7SWyllys Ingersoll 
251747e946e7SWyllys Ingersoll 	if ((rc = token_rsa_load_key(hContext, key_obj, &hKey))) {
251847e946e7SWyllys Ingersoll 		return (rc);
251947e946e7SWyllys Ingersoll 	}
252047e946e7SWyllys Ingersoll 
252147e946e7SWyllys Ingersoll 	/* Create the hash object we'll use to sign */
252247e946e7SWyllys Ingersoll 	if ((result = Tspi_Context_CreateObject(hContext,
252347e946e7SWyllys Ingersoll 	    TSS_OBJECT_TYPE_HASH, TSS_HASH_OTHER, &hHash))) {
252447e946e7SWyllys Ingersoll 		stlogit("Tspi_Context_CreateObject: 0x%0x - %s",
252547e946e7SWyllys Ingersoll 		    result, Trspi_Error_String(result));
252647e946e7SWyllys Ingersoll 		return (CKR_FUNCTION_FAILED);
252747e946e7SWyllys Ingersoll 	}
252847e946e7SWyllys Ingersoll 
252947e946e7SWyllys Ingersoll 	/* Insert the data into the hash object */
253047e946e7SWyllys Ingersoll 	if ((result = Tspi_Hash_SetHashValue(hHash, in_data_len,
253147e946e7SWyllys Ingersoll 	    in_data))) {
253247e946e7SWyllys Ingersoll 		stlogit("Tspi_Hash_SetHashValue: 0x%0x - %s",
253347e946e7SWyllys Ingersoll 		    result, Trspi_Error_String(result));
253447e946e7SWyllys Ingersoll 		return (CKR_FUNCTION_FAILED);
253547e946e7SWyllys Ingersoll 	}
253647e946e7SWyllys Ingersoll 
253747e946e7SWyllys Ingersoll 	/* Verify */
253847e946e7SWyllys Ingersoll 	result = Tspi_Hash_VerifySignature(hHash, hKey, sig_len, sig);
253947e946e7SWyllys Ingersoll 	if (result != TSS_SUCCESS &&
254047e946e7SWyllys Ingersoll 	    TPMTOK_TSS_ERROR_CODE(result) != TSS_E_FAIL) {
254147e946e7SWyllys Ingersoll 		stlogit("Tspi_Hash_VerifySignature: 0x%0x - %s",
254247e946e7SWyllys Ingersoll 		    result, Trspi_Error_String(result));
254347e946e7SWyllys Ingersoll 	}
254447e946e7SWyllys Ingersoll 
254547e946e7SWyllys Ingersoll 	if (TPMTOK_TSS_ERROR_CODE(result) == TSS_E_FAIL) {
254647e946e7SWyllys Ingersoll 		rc = CKR_SIGNATURE_INVALID;
254747e946e7SWyllys Ingersoll 	} else {
254847e946e7SWyllys Ingersoll 		rc = CKR_OK;
254947e946e7SWyllys Ingersoll 	}
255047e946e7SWyllys Ingersoll 
255147e946e7SWyllys Ingersoll 	return (rc);
255247e946e7SWyllys Ingersoll }
255347e946e7SWyllys Ingersoll 
255447e946e7SWyllys Ingersoll CK_RV
token_specific_rsa_sign(TSS_HCONTEXT hContext,CK_BYTE * in_data,CK_ULONG in_data_len,CK_BYTE * out_data,CK_ULONG * out_data_len,OBJECT * key_obj)255547e946e7SWyllys Ingersoll token_specific_rsa_sign(
255647e946e7SWyllys Ingersoll 	TSS_HCONTEXT hContext,
255747e946e7SWyllys Ingersoll 	CK_BYTE   * in_data,
255847e946e7SWyllys Ingersoll 	CK_ULONG    in_data_len,
255947e946e7SWyllys Ingersoll 	CK_BYTE   * out_data,
256047e946e7SWyllys Ingersoll 	CK_ULONG  * out_data_len,
256147e946e7SWyllys Ingersoll 	OBJECT	  * key_obj)
256247e946e7SWyllys Ingersoll {
256347e946e7SWyllys Ingersoll 	TSS_RESULT	result;
256447e946e7SWyllys Ingersoll 	TSS_HHASH	hHash;
256547e946e7SWyllys Ingersoll 	BYTE		*sig;
256647e946e7SWyllys Ingersoll 	UINT32		sig_len;
256747e946e7SWyllys Ingersoll 	TSS_HKEY	hKey;
256847e946e7SWyllys Ingersoll 	CK_RV		rc;
256947e946e7SWyllys Ingersoll 
257047e946e7SWyllys Ingersoll 	if ((rc = token_rsa_load_key(hContext, key_obj, &hKey))) {
257147e946e7SWyllys Ingersoll 		return (rc);
257247e946e7SWyllys Ingersoll 	}
257347e946e7SWyllys Ingersoll 
257447e946e7SWyllys Ingersoll 	/* Create the hash object we'll use to sign */
257547e946e7SWyllys Ingersoll 	if ((result = Tspi_Context_CreateObject(hContext,
257647e946e7SWyllys Ingersoll 	    TSS_OBJECT_TYPE_HASH, TSS_HASH_OTHER, &hHash))) {
257747e946e7SWyllys Ingersoll 		stlogit("Tspi_Context_CreateObject: 0x%0x - %s",
257847e946e7SWyllys Ingersoll 		    result, Trspi_Error_String(result));
257947e946e7SWyllys Ingersoll 		return (CKR_FUNCTION_FAILED);
258047e946e7SWyllys Ingersoll 	}
258147e946e7SWyllys Ingersoll 
258247e946e7SWyllys Ingersoll 	/* Insert the data into the hash object */
258347e946e7SWyllys Ingersoll 	if ((result = Tspi_Hash_SetHashValue(hHash, in_data_len,
258447e946e7SWyllys Ingersoll 	    in_data))) {
258547e946e7SWyllys Ingersoll 		stlogit("Tspi_Hash_SetHashValue: 0x%0x - %s",
258647e946e7SWyllys Ingersoll 		    result, Trspi_Error_String(result));
258747e946e7SWyllys Ingersoll 		return (CKR_FUNCTION_FAILED);
258847e946e7SWyllys Ingersoll 	}
258947e946e7SWyllys Ingersoll 
259047e946e7SWyllys Ingersoll 	/* Sign */
259147e946e7SWyllys Ingersoll 	if ((result = Tspi_Hash_Sign(hHash, hKey, &sig_len, &sig))) {
259247e946e7SWyllys Ingersoll 		stlogit("Tspi_Hash_Sign: 0x%0x - %s",
259347e946e7SWyllys Ingersoll 		    result, Trspi_Error_String(result));
2594ab8176c2SWyllys Ingersoll 		return (CKR_DATA_LEN_RANGE);
259547e946e7SWyllys Ingersoll 	}
259647e946e7SWyllys Ingersoll 
259747e946e7SWyllys Ingersoll 	if (sig_len > *out_data_len) {
259847e946e7SWyllys Ingersoll 		Tspi_Context_FreeMemory(hContext, sig);
259947e946e7SWyllys Ingersoll 		return (CKR_BUFFER_TOO_SMALL);
260047e946e7SWyllys Ingersoll 	}
260147e946e7SWyllys Ingersoll 
260247e946e7SWyllys Ingersoll 	(void) memcpy(out_data, sig, sig_len);
260347e946e7SWyllys Ingersoll 	*out_data_len = sig_len;
260447e946e7SWyllys Ingersoll 	Tspi_Context_FreeMemory(hContext, sig);
260547e946e7SWyllys Ingersoll 
260647e946e7SWyllys Ingersoll 	return (CKR_OK);
260747e946e7SWyllys Ingersoll }
260847e946e7SWyllys Ingersoll 
260947e946e7SWyllys Ingersoll CK_RV
tpm_encrypt_data(TSS_HCONTEXT hContext,TSS_HKEY hKey,CK_BYTE * in_data,CK_ULONG in_data_len,CK_BYTE * out_data,CK_ULONG * out_data_len)261047e946e7SWyllys Ingersoll tpm_encrypt_data(
261147e946e7SWyllys Ingersoll 	TSS_HCONTEXT hContext,
261247e946e7SWyllys Ingersoll 	TSS_HKEY hKey,
261347e946e7SWyllys Ingersoll 	CK_BYTE *in_data,
261447e946e7SWyllys Ingersoll 	CK_ULONG in_data_len,
261547e946e7SWyllys Ingersoll 	CK_BYTE *out_data,
261647e946e7SWyllys Ingersoll 	CK_ULONG *out_data_len)
261747e946e7SWyllys Ingersoll {
261847e946e7SWyllys Ingersoll 	TSS_RESULT	result;
261947e946e7SWyllys Ingersoll 	TSS_HENCDATA	hEncData;
262047e946e7SWyllys Ingersoll 	BYTE		*dataBlob, *modulus;
262147e946e7SWyllys Ingersoll 	UINT32		dataBlobSize, modLen;
262247e946e7SWyllys Ingersoll 	CK_ULONG	chunklen, remain;
262347e946e7SWyllys Ingersoll 	CK_ULONG	outlen;
2624ab8176c2SWyllys Ingersoll 	UINT32		keyusage, scheme, maxsize;
262547e946e7SWyllys Ingersoll 
262647e946e7SWyllys Ingersoll 	if ((result = Tspi_Context_CreateObject(hContext,
262747e946e7SWyllys Ingersoll 	    TSS_OBJECT_TYPE_ENCDATA, TSS_ENCDATA_BIND, &hEncData))) {
262847e946e7SWyllys Ingersoll 		stlogit("Tspi_Context_CreateObject: 0x%0x - %s",
262947e946e7SWyllys Ingersoll 		    result, Trspi_Error_String(result));
263047e946e7SWyllys Ingersoll 		return (CKR_FUNCTION_FAILED);
263147e946e7SWyllys Ingersoll 	}
263247e946e7SWyllys Ingersoll 	/*
263347e946e7SWyllys Ingersoll 	 * Figure out the modulus size so we can break the data
263447e946e7SWyllys Ingersoll 	 * into smaller chunks if necessary.
263547e946e7SWyllys Ingersoll 	 */
263647e946e7SWyllys Ingersoll 	if ((result = Tspi_GetAttribData(hKey, TSS_TSPATTRIB_RSAKEY_INFO,
263747e946e7SWyllys Ingersoll 	    TSS_TSPATTRIB_KEYINFO_RSA_MODULUS, &modLen, &modulus))) {
263847e946e7SWyllys Ingersoll 		stlogit("Tspi_GetAttribData: 0x%0x - %s",
263947e946e7SWyllys Ingersoll 		    result, Trspi_Error_String(result));
264047e946e7SWyllys Ingersoll 		return (result);
264147e946e7SWyllys Ingersoll 	}
264247e946e7SWyllys Ingersoll 	/* we don't need the actual modulus */
264347e946e7SWyllys Ingersoll 	Tspi_Context_FreeMemory(hContext, modulus);
264447e946e7SWyllys Ingersoll 
264547e946e7SWyllys Ingersoll 	/*
264647e946e7SWyllys Ingersoll 	 * According to TSS spec for Tspi_Data_Bind (4.3.4.21.5),
2647ab8176c2SWyllys Ingersoll 	 * Max input data size varies depending on the key type and
2648ab8176c2SWyllys Ingersoll 	 * encryption scheme.
264947e946e7SWyllys Ingersoll 	 */
2650ab8176c2SWyllys Ingersoll 	if ((result = Tspi_GetAttribUint32(hKey, TSS_TSPATTRIB_KEY_INFO,
2651ab8176c2SWyllys Ingersoll 	    TSS_TSPATTRIB_KEYINFO_USAGE, &keyusage))) {
2652ab8176c2SWyllys Ingersoll 		stlogit("Cannot find USAGE: %s\n",
2653ab8176c2SWyllys Ingersoll 		    Trspi_Error_String(result));
2654ab8176c2SWyllys Ingersoll 		return (result);
2655ab8176c2SWyllys Ingersoll 	}
2656ab8176c2SWyllys Ingersoll 	if ((result = Tspi_GetAttribUint32(hKey, TSS_TSPATTRIB_KEY_INFO,
2657ab8176c2SWyllys Ingersoll 	    TSS_TSPATTRIB_KEYINFO_ENCSCHEME, &scheme))) {
2658ab8176c2SWyllys Ingersoll 		stlogit("Cannot find ENCSCHEME: %s\n",
2659ab8176c2SWyllys Ingersoll 		    Trspi_Error_String(result));
2660ab8176c2SWyllys Ingersoll 		return (result);
2661ab8176c2SWyllys Ingersoll 	}
2662ab8176c2SWyllys Ingersoll 	switch (scheme) {
2663ab8176c2SWyllys Ingersoll 		case TSS_ES_RSAESPKCSV15:
2664ab8176c2SWyllys Ingersoll 			if (keyusage == TSS_KEYUSAGE_BIND)
2665ab8176c2SWyllys Ingersoll 				maxsize = 16;
2666ab8176c2SWyllys Ingersoll 			else /* legacy */
2667ab8176c2SWyllys Ingersoll 				maxsize = 11;
2668ab8176c2SWyllys Ingersoll 			break;
2669ab8176c2SWyllys Ingersoll 		case TSS_ES_RSAESOAEP_SHA1_MGF1:
2670ab8176c2SWyllys Ingersoll 			maxsize = 47;
2671ab8176c2SWyllys Ingersoll 			break;
2672ab8176c2SWyllys Ingersoll 		default:
2673ab8176c2SWyllys Ingersoll 			maxsize = 0;
2674ab8176c2SWyllys Ingersoll 	}
2675ab8176c2SWyllys Ingersoll 
2676ab8176c2SWyllys Ingersoll 	modLen -= maxsize;
267747e946e7SWyllys Ingersoll 
267847e946e7SWyllys Ingersoll 	chunklen = (in_data_len > modLen ? modLen : in_data_len);
267947e946e7SWyllys Ingersoll 	remain = in_data_len;
268047e946e7SWyllys Ingersoll 	outlen = 0;
268147e946e7SWyllys Ingersoll 	while (remain > 0) {
268247e946e7SWyllys Ingersoll 		if ((result = Tspi_Data_Bind(hEncData, hKey,
268347e946e7SWyllys Ingersoll 		    chunklen, in_data))) {
268447e946e7SWyllys Ingersoll 			stlogit("Tspi_Data_Bind: 0x%0x - %s",
268547e946e7SWyllys Ingersoll 			    result, Trspi_Error_String(result));
268647e946e7SWyllys Ingersoll 			return (CKR_FUNCTION_FAILED);
268747e946e7SWyllys Ingersoll 		}
268847e946e7SWyllys Ingersoll 
268947e946e7SWyllys Ingersoll 		if ((result = Tspi_GetAttribData(hEncData,
269047e946e7SWyllys Ingersoll 		    TSS_TSPATTRIB_ENCDATA_BLOB,
269147e946e7SWyllys Ingersoll 		    TSS_TSPATTRIB_ENCDATABLOB_BLOB,
269247e946e7SWyllys Ingersoll 		    &dataBlobSize, &dataBlob))) {
269347e946e7SWyllys Ingersoll 			stlogit("Tspi_GetAttribData: 0x%0x - %s",
269447e946e7SWyllys Ingersoll 			    result, Trspi_Error_String(result));
269547e946e7SWyllys Ingersoll 			return (CKR_FUNCTION_FAILED);
269647e946e7SWyllys Ingersoll 		}
269747e946e7SWyllys Ingersoll 
269847e946e7SWyllys Ingersoll 		if (outlen + dataBlobSize > *out_data_len) {
269947e946e7SWyllys Ingersoll 			Tspi_Context_FreeMemory(hContext, dataBlob);
270047e946e7SWyllys Ingersoll 			return (CKR_DATA_LEN_RANGE);
270147e946e7SWyllys Ingersoll 		}
270247e946e7SWyllys Ingersoll 
270347e946e7SWyllys Ingersoll 		(void) memcpy(out_data + outlen,
270447e946e7SWyllys Ingersoll 		    dataBlob, dataBlobSize);
270547e946e7SWyllys Ingersoll 
270647e946e7SWyllys Ingersoll 		outlen += dataBlobSize;
270747e946e7SWyllys Ingersoll 		in_data += chunklen;
270847e946e7SWyllys Ingersoll 		remain -= chunklen;
270947e946e7SWyllys Ingersoll 
271047e946e7SWyllys Ingersoll 		if (chunklen > remain)
271147e946e7SWyllys Ingersoll 			chunklen = remain;
271247e946e7SWyllys Ingersoll 
271347e946e7SWyllys Ingersoll 		Tspi_Context_FreeMemory(hContext, dataBlob);
271447e946e7SWyllys Ingersoll 	}
271547e946e7SWyllys Ingersoll 	*out_data_len = outlen;
271647e946e7SWyllys Ingersoll 
271747e946e7SWyllys Ingersoll 	return (CKR_OK);
271847e946e7SWyllys Ingersoll }
271947e946e7SWyllys Ingersoll 
272047e946e7SWyllys Ingersoll CK_RV
token_specific_rsa_encrypt(TSS_HCONTEXT hContext,CK_BYTE * in_data,CK_ULONG in_data_len,CK_BYTE * out_data,CK_ULONG * out_data_len,OBJECT * key_obj)272147e946e7SWyllys Ingersoll token_specific_rsa_encrypt(
272247e946e7SWyllys Ingersoll 	TSS_HCONTEXT hContext,
272347e946e7SWyllys Ingersoll 	CK_BYTE   * in_data,
272447e946e7SWyllys Ingersoll 	CK_ULONG    in_data_len,
272547e946e7SWyllys Ingersoll 	CK_BYTE   * out_data,
272647e946e7SWyllys Ingersoll 	CK_ULONG  * out_data_len,
272747e946e7SWyllys Ingersoll 	OBJECT	  * key_obj)
272847e946e7SWyllys Ingersoll {
272947e946e7SWyllys Ingersoll 	TSS_HKEY	hKey;
273047e946e7SWyllys Ingersoll 	CK_RV		rc;
273147e946e7SWyllys Ingersoll 
273247e946e7SWyllys Ingersoll 	if ((rc = token_rsa_load_key(hContext, key_obj, &hKey))) {
273347e946e7SWyllys Ingersoll 		return (rc);
273447e946e7SWyllys Ingersoll 	}
273547e946e7SWyllys Ingersoll 
273647e946e7SWyllys Ingersoll 	rc  = tpm_encrypt_data(hContext, hKey, in_data, in_data_len,
273747e946e7SWyllys Ingersoll 	    out_data, out_data_len);
273847e946e7SWyllys Ingersoll 
273947e946e7SWyllys Ingersoll 	return (rc);
274047e946e7SWyllys Ingersoll }
2741ab8176c2SWyllys Ingersoll 
2742ab8176c2SWyllys Ingersoll /*
2743ab8176c2SWyllys Ingersoll  * RSA Verify Recover
2744ab8176c2SWyllys Ingersoll  *
2745ab8176c2SWyllys Ingersoll  * Public key crypto is done in software, not by the TPM.
274691419a03SJason King  * We use libsoftcrypto and perform the RSA operations ourselves similar
274791419a03SJason King  * to how pkcs11_softtoken performs the operation.
2748ab8176c2SWyllys Ingersoll  */
2749ab8176c2SWyllys Ingersoll CK_RV
token_specific_rsa_verify_recover(TSS_HCONTEXT hContext,CK_BYTE_PTR pSignature,CK_ULONG ulSignatureLen,CK_BYTE_PTR pData,CK_ULONG_PTR pulDataLen,OBJECT * key_obj)2750ab8176c2SWyllys Ingersoll token_specific_rsa_verify_recover(
2751ab8176c2SWyllys Ingersoll 	TSS_HCONTEXT	hContext,
275291419a03SJason King 	CK_BYTE_PTR	pSignature,
275391419a03SJason King 	CK_ULONG	ulSignatureLen,
275491419a03SJason King 	CK_BYTE_PTR	pData,
275591419a03SJason King 	CK_ULONG_PTR	pulDataLen,
2756ab8176c2SWyllys Ingersoll 	OBJECT		*key_obj)
2757ab8176c2SWyllys Ingersoll {
2758ab8176c2SWyllys Ingersoll 	TSS_HKEY	hKey;
2759ab8176c2SWyllys Ingersoll 	TSS_RESULT	result;
2760ab8176c2SWyllys Ingersoll 	CK_RV		rc;
2761ab8176c2SWyllys Ingersoll 	BYTE		*modulus;
2762ab8176c2SWyllys Ingersoll 	UINT32		modLen;
276391419a03SJason King 	RSAbytekey	rsa = { 0 };
2764ab8176c2SWyllys Ingersoll 	uchar_t		exp[] = { 0x01, 0x00, 0x01 };
276591419a03SJason King 	CK_BYTE		plain_data[MAX_RSA_KEYLENGTH];
276691419a03SJason King 	size_t		data_len;
2767ab8176c2SWyllys Ingersoll 
2768ab8176c2SWyllys Ingersoll 	if ((rc = token_rsa_load_key(hContext, key_obj, &hKey))) {
2769ab8176c2SWyllys Ingersoll 		return (rc);
2770ab8176c2SWyllys Ingersoll 	}
2771ab8176c2SWyllys Ingersoll 
2772ab8176c2SWyllys Ingersoll 	if ((result = Tspi_GetAttribData(hKey, TSS_TSPATTRIB_RSAKEY_INFO,
2773ab8176c2SWyllys Ingersoll 	    TSS_TSPATTRIB_KEYINFO_RSA_MODULUS, &modLen, &modulus))) {
2774ab8176c2SWyllys Ingersoll 		stlogit("Tspi_GetAttribData: 0x%0x - %s",
2775ab8176c2SWyllys Ingersoll 		    result, Trspi_Error_String(result));
2776ab8176c2SWyllys Ingersoll 		return (CKR_FUNCTION_FAILED);
2777ab8176c2SWyllys Ingersoll 	}
2778ab8176c2SWyllys Ingersoll 
277991419a03SJason King 	if (ulSignatureLen != modLen) {
2780ab8176c2SWyllys Ingersoll 		rc = CKR_SIGNATURE_LEN_RANGE;
2781ab8176c2SWyllys Ingersoll 		goto end;
2782ab8176c2SWyllys Ingersoll 	}
2783ab8176c2SWyllys Ingersoll 
278491419a03SJason King 	rsa.modulus = modulus;
278591419a03SJason King 	rsa.modulus_bits = CRYPTO_BYTES2BITS(modLen);
278691419a03SJason King 	rsa.pubexpo = exp;
278791419a03SJason King 	rsa.pubexpo_bytes = sizeof (exp);
2788ab8176c2SWyllys Ingersoll 
278991419a03SJason King 	if ((rc = rsa_encrypt(&rsa, pSignature, modLen, plain_data)) != CKR_OK)
2790ab8176c2SWyllys Ingersoll 		goto end;
2791ab8176c2SWyllys Ingersoll 
279291419a03SJason King 	data_len = modLen;
279391419a03SJason King 	if ((rc = pkcs1_decode(PKCS1_VERIFY, plain_data, &data_len)) != CKR_OK)
2794ab8176c2SWyllys Ingersoll 		goto end;
2795ab8176c2SWyllys Ingersoll 
279691419a03SJason King 	(void) memcpy(pData, &plain_data[modLen - data_len], data_len);
279791419a03SJason King 	*pulDataLen = data_len;
2798ab8176c2SWyllys Ingersoll 
2799ab8176c2SWyllys Ingersoll end:
2800ab8176c2SWyllys Ingersoll 	Tspi_Context_FreeMemory(hContext, modulus);
2801ab8176c2SWyllys Ingersoll 	return (rc);
2802ab8176c2SWyllys Ingersoll }
2803