xref: /onnv-gate/usr/src/cmd/cmd-crypto/tpmadm/main.c (revision 11070:3ac202191cfa)
19126SWyllys.Ingersoll@Sun.COM /*
29126SWyllys.Ingersoll@Sun.COM  * CDDL HEADER START
39126SWyllys.Ingersoll@Sun.COM  *
49126SWyllys.Ingersoll@Sun.COM  * The contents of this file are subject to the terms of the
59126SWyllys.Ingersoll@Sun.COM  * Common Development and Distribution License (the "License").
69126SWyllys.Ingersoll@Sun.COM  * You may not use this file except in compliance with the License.
79126SWyllys.Ingersoll@Sun.COM  *
89126SWyllys.Ingersoll@Sun.COM  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
99126SWyllys.Ingersoll@Sun.COM  * or http://www.opensolaris.org/os/licensing.
109126SWyllys.Ingersoll@Sun.COM  * See the License for the specific language governing permissions
119126SWyllys.Ingersoll@Sun.COM  * and limitations under the License.
129126SWyllys.Ingersoll@Sun.COM  *
139126SWyllys.Ingersoll@Sun.COM  * When distributing Covered Code, include this CDDL HEADER in each
149126SWyllys.Ingersoll@Sun.COM  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
159126SWyllys.Ingersoll@Sun.COM  * If applicable, add the following below this CDDL HEADER, with the
169126SWyllys.Ingersoll@Sun.COM  * fields enclosed by brackets "[]" replaced with your own identifying
179126SWyllys.Ingersoll@Sun.COM  * information: Portions Copyright [yyyy] [name of copyright owner]
189126SWyllys.Ingersoll@Sun.COM  *
199126SWyllys.Ingersoll@Sun.COM  * CDDL HEADER END
209126SWyllys.Ingersoll@Sun.COM  */
219126SWyllys.Ingersoll@Sun.COM 
229126SWyllys.Ingersoll@Sun.COM /*
239126SWyllys.Ingersoll@Sun.COM  * Copyright 2009 Sun Microsystems, Inc.  All rights reserved.
249126SWyllys.Ingersoll@Sun.COM  * Use is subject to license terms.
259126SWyllys.Ingersoll@Sun.COM  */
269126SWyllys.Ingersoll@Sun.COM 
279126SWyllys.Ingersoll@Sun.COM 
289126SWyllys.Ingersoll@Sun.COM #include <stdlib.h>
299126SWyllys.Ingersoll@Sun.COM #include <stdio.h>
309126SWyllys.Ingersoll@Sun.COM #include <unistd.h>
319126SWyllys.Ingersoll@Sun.COM #include <strings.h>
329126SWyllys.Ingersoll@Sun.COM #include <libintl.h>
339126SWyllys.Ingersoll@Sun.COM #include <locale.h>
349126SWyllys.Ingersoll@Sun.COM 
359126SWyllys.Ingersoll@Sun.COM #include <tss/tspi.h>
36*11070SScott.Rotondo@Sun.COM #include <trousers/trousers.h>
379126SWyllys.Ingersoll@Sun.COM #include "tpmadm.h"
389126SWyllys.Ingersoll@Sun.COM 
399126SWyllys.Ingersoll@Sun.COM extern cmdtable_t commands[];
409126SWyllys.Ingersoll@Sun.COM 
419126SWyllys.Ingersoll@Sun.COM static void
print_usage(char * progname,cmdtable_t cmds[])429126SWyllys.Ingersoll@Sun.COM print_usage(char *progname, cmdtable_t cmds[])
439126SWyllys.Ingersoll@Sun.COM {
449126SWyllys.Ingersoll@Sun.COM 	cmdtable_t *p;
459126SWyllys.Ingersoll@Sun.COM 
469126SWyllys.Ingersoll@Sun.COM 	(void) fprintf(stderr,
479126SWyllys.Ingersoll@Sun.COM 	    gettext("usage: %s command args ...\n"), progname);
489126SWyllys.Ingersoll@Sun.COM 	(void) fprintf(stderr,
499126SWyllys.Ingersoll@Sun.COM 	    gettext("where 'command' is one of the following:\n"));
509126SWyllys.Ingersoll@Sun.COM 	for (p = &cmds[0]; p->name != NULL; p++) {
519126SWyllys.Ingersoll@Sun.COM 		(void) fprintf(stderr, "\t%s %s\n", p->name, p->args);
529126SWyllys.Ingersoll@Sun.COM 	}
539126SWyllys.Ingersoll@Sun.COM }
549126SWyllys.Ingersoll@Sun.COM 
559126SWyllys.Ingersoll@Sun.COM int
main(int argc,char * argv[])569126SWyllys.Ingersoll@Sun.COM main(int argc, char *argv[])
579126SWyllys.Ingersoll@Sun.COM {
589126SWyllys.Ingersoll@Sun.COM 	char *progname;
599126SWyllys.Ingersoll@Sun.COM 	cmdtable_t *p;
609126SWyllys.Ingersoll@Sun.COM 	cmdfunc_t fptr = NULL;
619126SWyllys.Ingersoll@Sun.COM 	int ret;
629126SWyllys.Ingersoll@Sun.COM 	TSS_HCONTEXT hContext;
639126SWyllys.Ingersoll@Sun.COM 	TSS_HOBJECT hTPM;
649126SWyllys.Ingersoll@Sun.COM 
659126SWyllys.Ingersoll@Sun.COM 	/* Set up for i18n/l10n. */
669126SWyllys.Ingersoll@Sun.COM #if !defined(TEXT_DOMAIN)		/* Should be defined by cc -D. */
679126SWyllys.Ingersoll@Sun.COM #define	TEXT_DOMAIN	"SYS_TEST"	/* Use this only if it isn't. */
689126SWyllys.Ingersoll@Sun.COM #endif
699126SWyllys.Ingersoll@Sun.COM 	(void) setlocale(LC_ALL, "");
709126SWyllys.Ingersoll@Sun.COM 	(void) textdomain(TEXT_DOMAIN);
719126SWyllys.Ingersoll@Sun.COM 
729126SWyllys.Ingersoll@Sun.COM 	progname = argv[0];
739126SWyllys.Ingersoll@Sun.COM 	argc--;
749126SWyllys.Ingersoll@Sun.COM 	argv++;
759126SWyllys.Ingersoll@Sun.COM 
769126SWyllys.Ingersoll@Sun.COM 	if (argc <= 0) {
779126SWyllys.Ingersoll@Sun.COM 		print_usage(progname, commands);
789126SWyllys.Ingersoll@Sun.COM 		return (ERR_USAGE);
799126SWyllys.Ingersoll@Sun.COM 	}
809126SWyllys.Ingersoll@Sun.COM 
819126SWyllys.Ingersoll@Sun.COM 	for (p = &commands[0]; p->name != NULL; p++) {
829126SWyllys.Ingersoll@Sun.COM 		if (0 == strcmp(p->name, argv[0])) {
839126SWyllys.Ingersoll@Sun.COM 			fptr = p->func;
849126SWyllys.Ingersoll@Sun.COM 			break;
859126SWyllys.Ingersoll@Sun.COM 		}
869126SWyllys.Ingersoll@Sun.COM 	}
879126SWyllys.Ingersoll@Sun.COM 	if (fptr == NULL) {
889126SWyllys.Ingersoll@Sun.COM 		print_usage(progname, commands);
899126SWyllys.Ingersoll@Sun.COM 		return (ERR_USAGE);
909126SWyllys.Ingersoll@Sun.COM 	}
919126SWyllys.Ingersoll@Sun.COM 
929126SWyllys.Ingersoll@Sun.COM 	if (tpm_preamble(&hContext, &hTPM))
939126SWyllys.Ingersoll@Sun.COM 		return (ERR_FAIL);
949126SWyllys.Ingersoll@Sun.COM 	ret = fptr(hContext, hTPM, argc, argv);
959126SWyllys.Ingersoll@Sun.COM 	(void) tpm_postamble(hContext);
969126SWyllys.Ingersoll@Sun.COM 
979126SWyllys.Ingersoll@Sun.COM 	return (ret);
989126SWyllys.Ingersoll@Sun.COM }
999126SWyllys.Ingersoll@Sun.COM 
1009126SWyllys.Ingersoll@Sun.COM 
1019126SWyllys.Ingersoll@Sun.COM /*
1029126SWyllys.Ingersoll@Sun.COM  * Utility functions
1039126SWyllys.Ingersoll@Sun.COM  */
1049126SWyllys.Ingersoll@Sun.COM 
1059126SWyllys.Ingersoll@Sun.COM void
print_bytes(BYTE * bytes,size_t len,int formatted)1069126SWyllys.Ingersoll@Sun.COM print_bytes(BYTE *bytes, size_t len, int formatted)
1079126SWyllys.Ingersoll@Sun.COM {
1089126SWyllys.Ingersoll@Sun.COM 	int i;
1099126SWyllys.Ingersoll@Sun.COM 	for (i = 0; i < len; i++) {
1109126SWyllys.Ingersoll@Sun.COM 		(void) printf("%02X ", bytes[i]);
1119126SWyllys.Ingersoll@Sun.COM 		if (formatted && i % 16 == 7)
1129126SWyllys.Ingersoll@Sun.COM 			(void) printf("  ");
1139126SWyllys.Ingersoll@Sun.COM 		if (formatted && i % 16 == 15)
1149126SWyllys.Ingersoll@Sun.COM 			(void) printf("\n");
1159126SWyllys.Ingersoll@Sun.COM 	}
1169126SWyllys.Ingersoll@Sun.COM 	(void) printf("\n");
1179126SWyllys.Ingersoll@Sun.COM }
1189126SWyllys.Ingersoll@Sun.COM 
1199126SWyllys.Ingersoll@Sun.COM 
1209126SWyllys.Ingersoll@Sun.COM /*
1219126SWyllys.Ingersoll@Sun.COM  * TSS convenience functions
1229126SWyllys.Ingersoll@Sun.COM  */
1239126SWyllys.Ingersoll@Sun.COM 
1249126SWyllys.Ingersoll@Sun.COM void
print_error(TSS_RESULT ret,char * msg)1259126SWyllys.Ingersoll@Sun.COM print_error(TSS_RESULT ret, char *msg)
1269126SWyllys.Ingersoll@Sun.COM {
1279126SWyllys.Ingersoll@Sun.COM 	char *err_string;
1289126SWyllys.Ingersoll@Sun.COM 
12910851SScott.Rotondo@Sun.COM 	/* Print the standard error string and error code. */
1309126SWyllys.Ingersoll@Sun.COM 	err_string = Trspi_Error_String(ret);
1319126SWyllys.Ingersoll@Sun.COM 	(void) fprintf(stderr, "%s: %s (0x%0x)\n", msg, err_string, ret);
13210851SScott.Rotondo@Sun.COM 
13310851SScott.Rotondo@Sun.COM 	/* For a few special cases, add a more verbose error message. */
13410851SScott.Rotondo@Sun.COM 	switch (ret) {
135*11070SScott.Rotondo@Sun.COM 	case TPM_E_DEACTIVATED:
136*11070SScott.Rotondo@Sun.COM 	case TPM_E_DISABLED:
13710851SScott.Rotondo@Sun.COM 		(void) fprintf(stderr,
13810851SScott.Rotondo@Sun.COM 		    gettext("Enable the TPM and restart Solaris.\n"));
13910851SScott.Rotondo@Sun.COM 		break;
140*11070SScott.Rotondo@Sun.COM 	case TSP_ERROR(TSS_E_COMM_FAILURE):
14110851SScott.Rotondo@Sun.COM 		(void) fprintf(stderr,
14210851SScott.Rotondo@Sun.COM 		    gettext("Make sure the tcsd service "
14310851SScott.Rotondo@Sun.COM 		    "(svc:/application/security/tcsd) is running.\n"));
14410851SScott.Rotondo@Sun.COM 		break;
14510851SScott.Rotondo@Sun.COM 	}
1469126SWyllys.Ingersoll@Sun.COM }
1479126SWyllys.Ingersoll@Sun.COM 
1489126SWyllys.Ingersoll@Sun.COM int
get_tpm_capability(TSS_HCONTEXT hContext,TSS_HOBJECT hTPM,UINT32 cap,UINT32 subcap,void * buf,size_t bufsize)1499126SWyllys.Ingersoll@Sun.COM get_tpm_capability(TSS_HCONTEXT hContext, TSS_HOBJECT hTPM, UINT32 cap,
1509126SWyllys.Ingersoll@Sun.COM UINT32 subcap, void *buf, size_t bufsize)
1519126SWyllys.Ingersoll@Sun.COM {
1529126SWyllys.Ingersoll@Sun.COM 	TSS_RESULT ret;
1539126SWyllys.Ingersoll@Sun.COM 	UINT32 datalen;
1549126SWyllys.Ingersoll@Sun.COM 	BYTE *data;
1559126SWyllys.Ingersoll@Sun.COM 
1569126SWyllys.Ingersoll@Sun.COM 	ret = Tspi_TPM_GetCapability(hTPM, cap, sizeof (subcap),
1579126SWyllys.Ingersoll@Sun.COM 	    (BYTE *)&subcap, &datalen, &data);
1589126SWyllys.Ingersoll@Sun.COM 	if (ret) {
1599126SWyllys.Ingersoll@Sun.COM 		print_error(ret, gettext("Get TPM capability"));
1609126SWyllys.Ingersoll@Sun.COM 		return (ERR_FAIL);
1619126SWyllys.Ingersoll@Sun.COM 	}
1629126SWyllys.Ingersoll@Sun.COM 
1639126SWyllys.Ingersoll@Sun.COM 	if (datalen > bufsize) {
1649126SWyllys.Ingersoll@Sun.COM 		(void) fprintf(stderr,
1659126SWyllys.Ingersoll@Sun.COM 		    gettext("Capability 0x%x returned %u bytes "
1669126SWyllys.Ingersoll@Sun.COM 		    "(expected %u)\n"), cap, datalen, bufsize);
1679126SWyllys.Ingersoll@Sun.COM 		return (ERR_FAIL);
1689126SWyllys.Ingersoll@Sun.COM 	}
1699126SWyllys.Ingersoll@Sun.COM 	bcopy(data, buf, datalen);
1709126SWyllys.Ingersoll@Sun.COM 
1719126SWyllys.Ingersoll@Sun.COM 	ret = Tspi_Context_FreeMemory(hContext, data);
1729126SWyllys.Ingersoll@Sun.COM 	if (ret) {
1739126SWyllys.Ingersoll@Sun.COM 		print_error(ret, gettext("Free capability buffer"));
1749126SWyllys.Ingersoll@Sun.COM 		return (ERR_FAIL);
1759126SWyllys.Ingersoll@Sun.COM 	}
1769126SWyllys.Ingersoll@Sun.COM 
1779126SWyllys.Ingersoll@Sun.COM 	return (0);
1789126SWyllys.Ingersoll@Sun.COM }
1799126SWyllys.Ingersoll@Sun.COM 
1809126SWyllys.Ingersoll@Sun.COM int
set_policy_options(TSS_HPOLICY hPolicy,TSS_FLAG mode,char * prompt,UINT32 secret_len,BYTE * secret)181*11070SScott.Rotondo@Sun.COM set_policy_options(TSS_HPOLICY hPolicy, TSS_FLAG mode, char *prompt,
182*11070SScott.Rotondo@Sun.COM UINT32 secret_len, BYTE *secret)
183*11070SScott.Rotondo@Sun.COM {
184*11070SScott.Rotondo@Sun.COM 	TSS_RESULT ret;
185*11070SScott.Rotondo@Sun.COM 	BYTE *unicode_prompt;
186*11070SScott.Rotondo@Sun.COM 	UINT32 len;
187*11070SScott.Rotondo@Sun.COM 
188*11070SScott.Rotondo@Sun.COM 	ret = Tspi_Policy_SetSecret(hPolicy, mode, secret_len, secret);
189*11070SScott.Rotondo@Sun.COM 	if (ret) {
190*11070SScott.Rotondo@Sun.COM 		print_error(ret, gettext("Set policy secret"));
191*11070SScott.Rotondo@Sun.COM 		return (ERR_FAIL);
192*11070SScott.Rotondo@Sun.COM 	}
193*11070SScott.Rotondo@Sun.COM 	if (prompt != NULL) {
194*11070SScott.Rotondo@Sun.COM 		unicode_prompt = Trspi_Native_To_UNICODE((BYTE *)prompt, &len);
195*11070SScott.Rotondo@Sun.COM 		ret = Tspi_SetAttribData(hPolicy,
196*11070SScott.Rotondo@Sun.COM 		    TSS_TSPATTRIB_POLICY_POPUPSTRING,
197*11070SScott.Rotondo@Sun.COM 		    NULL, len, unicode_prompt);
198*11070SScott.Rotondo@Sun.COM 		if (ret) {
199*11070SScott.Rotondo@Sun.COM 			print_error(ret, gettext("Set policy prompt"));
200*11070SScott.Rotondo@Sun.COM 			return (ERR_FAIL);
201*11070SScott.Rotondo@Sun.COM 		}
202*11070SScott.Rotondo@Sun.COM 	}
203*11070SScott.Rotondo@Sun.COM 
204*11070SScott.Rotondo@Sun.COM 	return (0);
205*11070SScott.Rotondo@Sun.COM }
206*11070SScott.Rotondo@Sun.COM 
207*11070SScott.Rotondo@Sun.COM int
set_object_policy(TSS_HOBJECT handle,TSS_FLAG mode,char * prompt,UINT32 secret_len,BYTE * secret)208*11070SScott.Rotondo@Sun.COM set_object_policy(TSS_HOBJECT handle, TSS_FLAG mode, char *prompt,
209*11070SScott.Rotondo@Sun.COM UINT32 secret_len, BYTE *secret)
2109126SWyllys.Ingersoll@Sun.COM {
2119126SWyllys.Ingersoll@Sun.COM 	TSS_HPOLICY hPolicy;
2129126SWyllys.Ingersoll@Sun.COM 	TSS_RESULT ret;
2139126SWyllys.Ingersoll@Sun.COM 
2149126SWyllys.Ingersoll@Sun.COM 	ret = Tspi_GetPolicyObject(handle, TSS_POLICY_USAGE, &hPolicy);
2159126SWyllys.Ingersoll@Sun.COM 	if (ret) {
2169126SWyllys.Ingersoll@Sun.COM 		print_error(ret, gettext("Get object policy"));
2179126SWyllys.Ingersoll@Sun.COM 		return (ERR_FAIL);
2189126SWyllys.Ingersoll@Sun.COM 	}
2199126SWyllys.Ingersoll@Sun.COM 
220*11070SScott.Rotondo@Sun.COM 	return (set_policy_options(hPolicy, mode, prompt, secret_len, secret));
2219126SWyllys.Ingersoll@Sun.COM }
2229126SWyllys.Ingersoll@Sun.COM 
2239126SWyllys.Ingersoll@Sun.COM int
tpm_preamble(TSS_HCONTEXT * hContext,TSS_HOBJECT * hTPM)2249126SWyllys.Ingersoll@Sun.COM tpm_preamble(TSS_HCONTEXT *hContext, TSS_HOBJECT *hTPM)
2259126SWyllys.Ingersoll@Sun.COM {
2269126SWyllys.Ingersoll@Sun.COM 	TSS_RESULT ret;
2279126SWyllys.Ingersoll@Sun.COM 
2289126SWyllys.Ingersoll@Sun.COM 	ret = Tspi_Context_Create(hContext);
2299126SWyllys.Ingersoll@Sun.COM 	if (ret) {
2309126SWyllys.Ingersoll@Sun.COM 		print_error(ret, gettext("Create context"));
2319126SWyllys.Ingersoll@Sun.COM 		return (ERR_FAIL);
2329126SWyllys.Ingersoll@Sun.COM 	}
2339126SWyllys.Ingersoll@Sun.COM 
2349126SWyllys.Ingersoll@Sun.COM 	ret = Tspi_Context_Connect(*hContext, NULL);
2359126SWyllys.Ingersoll@Sun.COM 	if (ret) {
2369126SWyllys.Ingersoll@Sun.COM 		print_error(ret, gettext("Connect context"));
2379126SWyllys.Ingersoll@Sun.COM 		(void) Tspi_Context_Close(*hContext);
2389126SWyllys.Ingersoll@Sun.COM 		return (ERR_FAIL);
2399126SWyllys.Ingersoll@Sun.COM 	}
2409126SWyllys.Ingersoll@Sun.COM 
2419126SWyllys.Ingersoll@Sun.COM 	ret = Tspi_Context_GetTpmObject(*hContext, hTPM);
2429126SWyllys.Ingersoll@Sun.COM 	if (ret) {
2439126SWyllys.Ingersoll@Sun.COM 		print_error(ret, gettext("Get TPM object"));
2449126SWyllys.Ingersoll@Sun.COM 		(void) Tspi_Context_Close(*hContext);
2459126SWyllys.Ingersoll@Sun.COM 		return (ERR_FAIL);
2469126SWyllys.Ingersoll@Sun.COM 	}
2479126SWyllys.Ingersoll@Sun.COM 	return (0);
2489126SWyllys.Ingersoll@Sun.COM }
2499126SWyllys.Ingersoll@Sun.COM 
2509126SWyllys.Ingersoll@Sun.COM int
tpm_postamble(TSS_HCONTEXT hContext)2519126SWyllys.Ingersoll@Sun.COM tpm_postamble(TSS_HCONTEXT hContext)
2529126SWyllys.Ingersoll@Sun.COM {
2539126SWyllys.Ingersoll@Sun.COM 	TSS_RESULT ret;
2549126SWyllys.Ingersoll@Sun.COM 
2559126SWyllys.Ingersoll@Sun.COM 	ret = Tspi_Context_Close(hContext);
2569126SWyllys.Ingersoll@Sun.COM 	if (ret) {
2579126SWyllys.Ingersoll@Sun.COM 		print_error(ret, gettext("Close context"));
2589126SWyllys.Ingersoll@Sun.COM 		return (ERR_FAIL);
2599126SWyllys.Ingersoll@Sun.COM 	}
2609126SWyllys.Ingersoll@Sun.COM 	return (0);
2619126SWyllys.Ingersoll@Sun.COM }
262