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