147e946e7SWyllys Ingersoll /*
247e946e7SWyllys Ingersoll  * CDDL HEADER START
347e946e7SWyllys Ingersoll  *
447e946e7SWyllys Ingersoll  * The contents of this file are subject to the terms of the
547e946e7SWyllys Ingersoll  * Common Development and Distribution License (the "License").
647e946e7SWyllys Ingersoll  * You may not use this file except in compliance with the License.
747e946e7SWyllys Ingersoll  *
847e946e7SWyllys Ingersoll  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
947e946e7SWyllys Ingersoll  * or http://www.opensolaris.org/os/licensing.
1047e946e7SWyllys Ingersoll  * See the License for the specific language governing permissions
1147e946e7SWyllys Ingersoll  * and limitations under the License.
1247e946e7SWyllys Ingersoll  *
1347e946e7SWyllys Ingersoll  * When distributing Covered Code, include this CDDL HEADER in each
1447e946e7SWyllys Ingersoll  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
1547e946e7SWyllys Ingersoll  * If applicable, add the following below this CDDL HEADER, with the
1647e946e7SWyllys Ingersoll  * fields enclosed by brackets "[]" replaced with your own identifying
1747e946e7SWyllys Ingersoll  * information: Portions Copyright [yyyy] [name of copyright owner]
1847e946e7SWyllys Ingersoll  *
1947e946e7SWyllys Ingersoll  * CDDL HEADER END
2047e946e7SWyllys Ingersoll  */
2147e946e7SWyllys Ingersoll 
2247e946e7SWyllys Ingersoll /*
2347e946e7SWyllys Ingersoll  * Copyright 2009 Sun Microsystems, Inc.  All rights reserved.
2447e946e7SWyllys Ingersoll  * Use is subject to license terms.
2579f1e617SAndy Fiddaman  * Copyright 2018 OmniOS Community Edition (OmniOSce) Association.
2647e946e7SWyllys Ingersoll  */
2747e946e7SWyllys Ingersoll 
2847e946e7SWyllys Ingersoll 
2947e946e7SWyllys Ingersoll #include <stdlib.h>
3047e946e7SWyllys Ingersoll #include <stdio.h>
3147e946e7SWyllys Ingersoll #include <unistd.h>
3247e946e7SWyllys Ingersoll #include <strings.h>
3347e946e7SWyllys Ingersoll #include <libintl.h>
3447e946e7SWyllys Ingersoll #include <locale.h>
3547e946e7SWyllys Ingersoll 
3647e946e7SWyllys Ingersoll #include <tss/tspi.h>
37304d8f90SScott Rotondo #include <trousers/trousers.h>
3847e946e7SWyllys Ingersoll #include "tpmadm.h"
3947e946e7SWyllys Ingersoll 
4047e946e7SWyllys Ingersoll extern cmdtable_t commands[];
4147e946e7SWyllys Ingersoll 
4247e946e7SWyllys Ingersoll static void
print_usage(char * progname,cmdtable_t cmds[])4347e946e7SWyllys Ingersoll print_usage(char *progname, cmdtable_t cmds[])
4447e946e7SWyllys Ingersoll {
4547e946e7SWyllys Ingersoll 	cmdtable_t *p;
4647e946e7SWyllys Ingersoll 
4747e946e7SWyllys Ingersoll 	(void) fprintf(stderr,
4847e946e7SWyllys Ingersoll 	    gettext("usage: %s command args ...\n"), progname);
4947e946e7SWyllys Ingersoll 	(void) fprintf(stderr,
5047e946e7SWyllys Ingersoll 	    gettext("where 'command' is one of the following:\n"));
5147e946e7SWyllys Ingersoll 	for (p = &cmds[0]; p->name != NULL; p++) {
5247e946e7SWyllys Ingersoll 		(void) fprintf(stderr, "\t%s %s\n", p->name, p->args);
5347e946e7SWyllys Ingersoll 	}
5447e946e7SWyllys Ingersoll }
5547e946e7SWyllys Ingersoll 
5647e946e7SWyllys Ingersoll int
main(int argc,char * argv[])5747e946e7SWyllys Ingersoll main(int argc, char *argv[])
5847e946e7SWyllys Ingersoll {
5947e946e7SWyllys Ingersoll 	char *progname;
6047e946e7SWyllys Ingersoll 	cmdtable_t *p;
6147e946e7SWyllys Ingersoll 	cmdfunc_t fptr = NULL;
6247e946e7SWyllys Ingersoll 	int ret;
6347e946e7SWyllys Ingersoll 	TSS_HCONTEXT hContext;
6447e946e7SWyllys Ingersoll 	TSS_HOBJECT hTPM;
6547e946e7SWyllys Ingersoll 
6647e946e7SWyllys Ingersoll 	/* Set up for i18n/l10n. */
6747e946e7SWyllys Ingersoll #if !defined(TEXT_DOMAIN)		/* Should be defined by cc -D. */
6847e946e7SWyllys Ingersoll #define	TEXT_DOMAIN	"SYS_TEST"	/* Use this only if it isn't. */
6947e946e7SWyllys Ingersoll #endif
7047e946e7SWyllys Ingersoll 	(void) setlocale(LC_ALL, "");
7147e946e7SWyllys Ingersoll 	(void) textdomain(TEXT_DOMAIN);
7247e946e7SWyllys Ingersoll 
7347e946e7SWyllys Ingersoll 	progname = argv[0];
7447e946e7SWyllys Ingersoll 	argc--;
7547e946e7SWyllys Ingersoll 	argv++;
7647e946e7SWyllys Ingersoll 
7747e946e7SWyllys Ingersoll 	if (argc <= 0) {
7847e946e7SWyllys Ingersoll 		print_usage(progname, commands);
7947e946e7SWyllys Ingersoll 		return (ERR_USAGE);
8047e946e7SWyllys Ingersoll 	}
8147e946e7SWyllys Ingersoll 
8247e946e7SWyllys Ingersoll 	for (p = &commands[0]; p->name != NULL; p++) {
8347e946e7SWyllys Ingersoll 		if (0 == strcmp(p->name, argv[0])) {
8447e946e7SWyllys Ingersoll 			fptr = p->func;
8547e946e7SWyllys Ingersoll 			break;
8647e946e7SWyllys Ingersoll 		}
8747e946e7SWyllys Ingersoll 	}
8847e946e7SWyllys Ingersoll 	if (fptr == NULL) {
8947e946e7SWyllys Ingersoll 		print_usage(progname, commands);
9047e946e7SWyllys Ingersoll 		return (ERR_USAGE);
9147e946e7SWyllys Ingersoll 	}
9247e946e7SWyllys Ingersoll 
9347e946e7SWyllys Ingersoll 	if (tpm_preamble(&hContext, &hTPM))
9447e946e7SWyllys Ingersoll 		return (ERR_FAIL);
9547e946e7SWyllys Ingersoll 	ret = fptr(hContext, hTPM, argc, argv);
9647e946e7SWyllys Ingersoll 	(void) tpm_postamble(hContext);
9747e946e7SWyllys Ingersoll 
9847e946e7SWyllys Ingersoll 	return (ret);
9947e946e7SWyllys Ingersoll }
10047e946e7SWyllys Ingersoll 
10147e946e7SWyllys Ingersoll 
10247e946e7SWyllys Ingersoll /*
10347e946e7SWyllys Ingersoll  * Utility functions
10447e946e7SWyllys Ingersoll  */
10547e946e7SWyllys Ingersoll 
10647e946e7SWyllys Ingersoll void
print_bytes(BYTE * bytes,size_t len,int formatted)10747e946e7SWyllys Ingersoll print_bytes(BYTE *bytes, size_t len, int formatted)
10847e946e7SWyllys Ingersoll {
10947e946e7SWyllys Ingersoll 	int i;
11047e946e7SWyllys Ingersoll 	for (i = 0; i < len; i++) {
11147e946e7SWyllys Ingersoll 		(void) printf("%02X ", bytes[i]);
11247e946e7SWyllys Ingersoll 		if (formatted && i % 16 == 7)
11347e946e7SWyllys Ingersoll 			(void) printf("  ");
11447e946e7SWyllys Ingersoll 		if (formatted && i % 16 == 15)
11547e946e7SWyllys Ingersoll 			(void) printf("\n");
11647e946e7SWyllys Ingersoll 	}
11747e946e7SWyllys Ingersoll 	(void) printf("\n");
11847e946e7SWyllys Ingersoll }
11947e946e7SWyllys Ingersoll 
12047e946e7SWyllys Ingersoll 
12147e946e7SWyllys Ingersoll /*
12247e946e7SWyllys Ingersoll  * TSS convenience functions
12347e946e7SWyllys Ingersoll  */
12447e946e7SWyllys Ingersoll 
12547e946e7SWyllys Ingersoll void
print_error(TSS_RESULT ret,char * msg)12647e946e7SWyllys Ingersoll print_error(TSS_RESULT ret, char *msg)
12747e946e7SWyllys Ingersoll {
12847e946e7SWyllys Ingersoll 	char *err_string;
12947e946e7SWyllys Ingersoll 
13035494a3dSScott Rotondo 	/* Print the standard error string and error code. */
13147e946e7SWyllys Ingersoll 	err_string = Trspi_Error_String(ret);
13247e946e7SWyllys Ingersoll 	(void) fprintf(stderr, "%s: %s (0x%0x)\n", msg, err_string, ret);
13335494a3dSScott Rotondo 
13435494a3dSScott Rotondo 	/* For a few special cases, add a more verbose error message. */
13535494a3dSScott Rotondo 	switch (ret) {
136304d8f90SScott Rotondo 	case TPM_E_DEACTIVATED:
137304d8f90SScott Rotondo 	case TPM_E_DISABLED:
13835494a3dSScott Rotondo 		(void) fprintf(stderr,
13979f1e617SAndy Fiddaman 		    gettext("Enable the TPM and reboot.\n"));
14035494a3dSScott Rotondo 		break;
141304d8f90SScott Rotondo 	case TSP_ERROR(TSS_E_COMM_FAILURE):
14235494a3dSScott Rotondo 		(void) fprintf(stderr,
14335494a3dSScott Rotondo 		    gettext("Make sure the tcsd service "
14435494a3dSScott Rotondo 		    "(svc:/application/security/tcsd) is running.\n"));
14535494a3dSScott Rotondo 		break;
14635494a3dSScott Rotondo 	}
14747e946e7SWyllys Ingersoll }
14847e946e7SWyllys Ingersoll 
14947e946e7SWyllys Ingersoll int
get_tpm_capability(TSS_HCONTEXT hContext,TSS_HOBJECT hTPM,UINT32 cap,UINT32 subcap,void * buf,size_t bufsize)15047e946e7SWyllys Ingersoll get_tpm_capability(TSS_HCONTEXT hContext, TSS_HOBJECT hTPM, UINT32 cap,
15179f1e617SAndy Fiddaman     UINT32 subcap, void *buf, size_t bufsize)
15247e946e7SWyllys Ingersoll {
15347e946e7SWyllys Ingersoll 	TSS_RESULT ret;
15447e946e7SWyllys Ingersoll 	UINT32 datalen;
15547e946e7SWyllys Ingersoll 	BYTE *data;
15647e946e7SWyllys Ingersoll 
15747e946e7SWyllys Ingersoll 	ret = Tspi_TPM_GetCapability(hTPM, cap, sizeof (subcap),
15847e946e7SWyllys Ingersoll 	    (BYTE *)&subcap, &datalen, &data);
15947e946e7SWyllys Ingersoll 	if (ret) {
16047e946e7SWyllys Ingersoll 		print_error(ret, gettext("Get TPM capability"));
16147e946e7SWyllys Ingersoll 		return (ERR_FAIL);
16247e946e7SWyllys Ingersoll 	}
16347e946e7SWyllys Ingersoll 
16447e946e7SWyllys Ingersoll 	if (datalen > bufsize) {
16547e946e7SWyllys Ingersoll 		(void) fprintf(stderr,
16647e946e7SWyllys Ingersoll 		    gettext("Capability 0x%x returned %u bytes "
16747e946e7SWyllys Ingersoll 		    "(expected %u)\n"), cap, datalen, bufsize);
16847e946e7SWyllys Ingersoll 		return (ERR_FAIL);
16947e946e7SWyllys Ingersoll 	}
17047e946e7SWyllys Ingersoll 	bcopy(data, buf, datalen);
17147e946e7SWyllys Ingersoll 
17247e946e7SWyllys Ingersoll 	ret = Tspi_Context_FreeMemory(hContext, data);
17347e946e7SWyllys Ingersoll 	if (ret) {
17447e946e7SWyllys Ingersoll 		print_error(ret, gettext("Free capability buffer"));
17547e946e7SWyllys Ingersoll 		return (ERR_FAIL);
17647e946e7SWyllys Ingersoll 	}
17747e946e7SWyllys Ingersoll 
17847e946e7SWyllys Ingersoll 	return (0);
17947e946e7SWyllys Ingersoll }
18047e946e7SWyllys Ingersoll 
18147e946e7SWyllys Ingersoll int
set_policy_options(TSS_HPOLICY hPolicy,TSS_FLAG mode,char * prompt,UINT32 secret_len,BYTE * secret)182304d8f90SScott Rotondo set_policy_options(TSS_HPOLICY hPolicy, TSS_FLAG mode, char *prompt,
18379f1e617SAndy Fiddaman     UINT32 secret_len, BYTE *secret)
18447e946e7SWyllys Ingersoll {
18547e946e7SWyllys Ingersoll 	TSS_RESULT ret;
186304d8f90SScott Rotondo 	BYTE *unicode_prompt;
187304d8f90SScott Rotondo 	UINT32 len;
18847e946e7SWyllys Ingersoll 
189304d8f90SScott Rotondo 	ret = Tspi_Policy_SetSecret(hPolicy, mode, secret_len, secret);
19047e946e7SWyllys Ingersoll 	if (ret) {
191304d8f90SScott Rotondo 		print_error(ret, gettext("Set policy secret"));
19247e946e7SWyllys Ingersoll 		return (ERR_FAIL);
19347e946e7SWyllys Ingersoll 	}
194304d8f90SScott Rotondo 	if (prompt != NULL) {
195304d8f90SScott Rotondo 		unicode_prompt = Trspi_Native_To_UNICODE((BYTE *)prompt, &len);
196304d8f90SScott Rotondo 		ret = Tspi_SetAttribData(hPolicy,
197304d8f90SScott Rotondo 		    TSS_TSPATTRIB_POLICY_POPUPSTRING,
198*6f2b04a2SToomas Soome 		    0, len, unicode_prompt);
199304d8f90SScott Rotondo 		if (ret) {
200304d8f90SScott Rotondo 			print_error(ret, gettext("Set policy prompt"));
201304d8f90SScott Rotondo 			return (ERR_FAIL);
202304d8f90SScott Rotondo 		}
203304d8f90SScott Rotondo 	}
204304d8f90SScott Rotondo 
205304d8f90SScott Rotondo 	return (0);
206304d8f90SScott Rotondo }
20747e946e7SWyllys Ingersoll 
208304d8f90SScott Rotondo int
set_object_policy(TSS_HOBJECT handle,TSS_FLAG mode,char * prompt,UINT32 secret_len,BYTE * secret)209304d8f90SScott Rotondo set_object_policy(TSS_HOBJECT handle, TSS_FLAG mode, char *prompt,
21079f1e617SAndy Fiddaman     UINT32 secret_len, BYTE *secret)
211304d8f90SScott Rotondo {
212304d8f90SScott Rotondo 	TSS_HPOLICY hPolicy;
213304d8f90SScott Rotondo 	TSS_RESULT ret;
214304d8f90SScott Rotondo 
215304d8f90SScott Rotondo 	ret = Tspi_GetPolicyObject(handle, TSS_POLICY_USAGE, &hPolicy);
21647e946e7SWyllys Ingersoll 	if (ret) {
217304d8f90SScott Rotondo 		print_error(ret, gettext("Get object policy"));
21847e946e7SWyllys Ingersoll 		return (ERR_FAIL);
21947e946e7SWyllys Ingersoll 	}
22047e946e7SWyllys Ingersoll 
221304d8f90SScott Rotondo 	return (set_policy_options(hPolicy, mode, prompt, secret_len, secret));
22247e946e7SWyllys Ingersoll }
22347e946e7SWyllys Ingersoll 
22447e946e7SWyllys Ingersoll int
tpm_preamble(TSS_HCONTEXT * hContext,TSS_HOBJECT * hTPM)22547e946e7SWyllys Ingersoll tpm_preamble(TSS_HCONTEXT *hContext, TSS_HOBJECT *hTPM)
22647e946e7SWyllys Ingersoll {
22747e946e7SWyllys Ingersoll 	TSS_RESULT ret;
22847e946e7SWyllys Ingersoll 
22947e946e7SWyllys Ingersoll 	ret = Tspi_Context_Create(hContext);
23047e946e7SWyllys Ingersoll 	if (ret) {
23147e946e7SWyllys Ingersoll 		print_error(ret, gettext("Create context"));
23247e946e7SWyllys Ingersoll 		return (ERR_FAIL);
23347e946e7SWyllys Ingersoll 	}
23447e946e7SWyllys Ingersoll 
23547e946e7SWyllys Ingersoll 	ret = Tspi_Context_Connect(*hContext, NULL);
23647e946e7SWyllys Ingersoll 	if (ret) {
23747e946e7SWyllys Ingersoll 		print_error(ret, gettext("Connect context"));
23847e946e7SWyllys Ingersoll 		(void) Tspi_Context_Close(*hContext);
23947e946e7SWyllys Ingersoll 		return (ERR_FAIL);
24047e946e7SWyllys Ingersoll 	}
24147e946e7SWyllys Ingersoll 
24247e946e7SWyllys Ingersoll 	ret = Tspi_Context_GetTpmObject(*hContext, hTPM);
24347e946e7SWyllys Ingersoll 	if (ret) {
24447e946e7SWyllys Ingersoll 		print_error(ret, gettext("Get TPM object"));
24547e946e7SWyllys Ingersoll 		(void) Tspi_Context_Close(*hContext);
24647e946e7SWyllys Ingersoll 		return (ERR_FAIL);
24747e946e7SWyllys Ingersoll 	}
24847e946e7SWyllys Ingersoll 	return (0);
24947e946e7SWyllys Ingersoll }
25047e946e7SWyllys Ingersoll 
25147e946e7SWyllys Ingersoll int
tpm_postamble(TSS_HCONTEXT hContext)25247e946e7SWyllys Ingersoll tpm_postamble(TSS_HCONTEXT hContext)
25347e946e7SWyllys Ingersoll {
25447e946e7SWyllys Ingersoll 	TSS_RESULT ret;
25547e946e7SWyllys Ingersoll 
25647e946e7SWyllys Ingersoll 	ret = Tspi_Context_Close(hContext);
25747e946e7SWyllys Ingersoll 	if (ret) {
25847e946e7SWyllys Ingersoll 		print_error(ret, gettext("Close context"));
25947e946e7SWyllys Ingersoll 		return (ERR_FAIL);
26047e946e7SWyllys Ingersoll 	}
26147e946e7SWyllys Ingersoll 	return (0);
26247e946e7SWyllys Ingersoll }
263