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