xref: /illumos-gate/usr/src/cmd/cmd-crypto/tpmadm/main.c (revision 56f33205c9ed776c3c909e07d52e94610a675740)
1 /*
2  * CDDL HEADER START
3  *
4  * The contents of this file are subject to the terms of the
5  * Common Development and Distribution License (the "License").
6  * You may not use this file except in compliance with the License.
7  *
8  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9  * or http://www.opensolaris.org/os/licensing.
10  * See the License for the specific language governing permissions
11  * and limitations under the License.
12  *
13  * When distributing Covered Code, include this CDDL HEADER in each
14  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15  * If applicable, add the following below this CDDL HEADER, with the
16  * fields enclosed by brackets "[]" replaced with your own identifying
17  * information: Portions Copyright [yyyy] [name of copyright owner]
18  *
19  * CDDL HEADER END
20  */
21 
22 /*
23  * Copyright 2009 Sun Microsystems, Inc.  All rights reserved.
24  * Use is subject to license terms.
25  */
26 
27 
28 #include <stdlib.h>
29 #include <stdio.h>
30 #include <unistd.h>
31 #include <strings.h>
32 #include <libintl.h>
33 #include <locale.h>
34 
35 #include <tss/tspi.h>
36 #include <trousers/trousers.h>
37 #include "tpmadm.h"
38 
39 extern cmdtable_t commands[];
40 
41 static void
42 print_usage(char *progname, cmdtable_t cmds[])
43 {
44 	cmdtable_t *p;
45 
46 	(void) fprintf(stderr,
47 	    gettext("usage: %s command args ...\n"), progname);
48 	(void) fprintf(stderr,
49 	    gettext("where 'command' is one of the following:\n"));
50 	for (p = &cmds[0]; p->name != NULL; p++) {
51 		(void) fprintf(stderr, "\t%s %s\n", p->name, p->args);
52 	}
53 }
54 
55 int
56 main(int argc, char *argv[])
57 {
58 	char *progname;
59 	cmdtable_t *p;
60 	cmdfunc_t fptr = NULL;
61 	int ret;
62 	TSS_HCONTEXT hContext;
63 	TSS_HOBJECT hTPM;
64 
65 	/* Set up for i18n/l10n. */
66 #if !defined(TEXT_DOMAIN)		/* Should be defined by cc -D. */
67 #define	TEXT_DOMAIN	"SYS_TEST"	/* Use this only if it isn't. */
68 #endif
69 	(void) setlocale(LC_ALL, "");
70 	(void) textdomain(TEXT_DOMAIN);
71 
72 	progname = argv[0];
73 	argc--;
74 	argv++;
75 
76 	if (argc <= 0) {
77 		print_usage(progname, commands);
78 		return (ERR_USAGE);
79 	}
80 
81 	for (p = &commands[0]; p->name != NULL; p++) {
82 		if (0 == strcmp(p->name, argv[0])) {
83 			fptr = p->func;
84 			break;
85 		}
86 	}
87 	if (fptr == NULL) {
88 		print_usage(progname, commands);
89 		return (ERR_USAGE);
90 	}
91 
92 	if (tpm_preamble(&hContext, &hTPM))
93 		return (ERR_FAIL);
94 	ret = fptr(hContext, hTPM, argc, argv);
95 	(void) tpm_postamble(hContext);
96 
97 	return (ret);
98 }
99 
100 
101 /*
102  * Utility functions
103  */
104 
105 void
106 print_bytes(BYTE *bytes, size_t len, int formatted)
107 {
108 	int i;
109 	for (i = 0; i < len; i++) {
110 		(void) printf("%02X ", bytes[i]);
111 		if (formatted && i % 16 == 7)
112 			(void) printf("  ");
113 		if (formatted && i % 16 == 15)
114 			(void) printf("\n");
115 	}
116 	(void) printf("\n");
117 }
118 
119 
120 /*
121  * TSS convenience functions
122  */
123 
124 void
125 print_error(TSS_RESULT ret, char *msg)
126 {
127 	char *err_string;
128 
129 	/* Print the standard error string and error code. */
130 	err_string = Trspi_Error_String(ret);
131 	(void) fprintf(stderr, "%s: %s (0x%0x)\n", msg, err_string, ret);
132 
133 	/* For a few special cases, add a more verbose error message. */
134 	switch (ret) {
135 	case TPM_E_DEACTIVATED:
136 	case TPM_E_DISABLED:
137 		(void) fprintf(stderr,
138 		    gettext("Enable the TPM and restart Solaris.\n"));
139 		break;
140 	case TSP_ERROR(TSS_E_COMM_FAILURE):
141 		(void) fprintf(stderr,
142 		    gettext("Make sure the tcsd service "
143 		    "(svc:/application/security/tcsd) is running.\n"));
144 		break;
145 	}
146 }
147 
148 int
149 get_tpm_capability(TSS_HCONTEXT hContext, TSS_HOBJECT hTPM, UINT32 cap,
150 UINT32 subcap, void *buf, size_t bufsize)
151 {
152 	TSS_RESULT ret;
153 	UINT32 datalen;
154 	BYTE *data;
155 
156 	ret = Tspi_TPM_GetCapability(hTPM, cap, sizeof (subcap),
157 	    (BYTE *)&subcap, &datalen, &data);
158 	if (ret) {
159 		print_error(ret, gettext("Get TPM capability"));
160 		return (ERR_FAIL);
161 	}
162 
163 	if (datalen > bufsize) {
164 		(void) fprintf(stderr,
165 		    gettext("Capability 0x%x returned %u bytes "
166 		    "(expected %u)\n"), cap, datalen, bufsize);
167 		return (ERR_FAIL);
168 	}
169 	bcopy(data, buf, datalen);
170 
171 	ret = Tspi_Context_FreeMemory(hContext, data);
172 	if (ret) {
173 		print_error(ret, gettext("Free capability buffer"));
174 		return (ERR_FAIL);
175 	}
176 
177 	return (0);
178 }
179 
180 int
181 set_policy_options(TSS_HPOLICY hPolicy, TSS_FLAG mode, char *prompt,
182 UINT32 secret_len, BYTE *secret)
183 {
184 	TSS_RESULT ret;
185 	BYTE *unicode_prompt;
186 	UINT32 len;
187 
188 	ret = Tspi_Policy_SetSecret(hPolicy, mode, secret_len, secret);
189 	if (ret) {
190 		print_error(ret, gettext("Set policy secret"));
191 		return (ERR_FAIL);
192 	}
193 	if (prompt != NULL) {
194 		unicode_prompt = Trspi_Native_To_UNICODE((BYTE *)prompt, &len);
195 		ret = Tspi_SetAttribData(hPolicy,
196 		    TSS_TSPATTRIB_POLICY_POPUPSTRING,
197 		    NULL, len, unicode_prompt);
198 		if (ret) {
199 			print_error(ret, gettext("Set policy prompt"));
200 			return (ERR_FAIL);
201 		}
202 	}
203 
204 	return (0);
205 }
206 
207 int
208 set_object_policy(TSS_HOBJECT handle, TSS_FLAG mode, char *prompt,
209 UINT32 secret_len, BYTE *secret)
210 {
211 	TSS_HPOLICY hPolicy;
212 	TSS_RESULT ret;
213 
214 	ret = Tspi_GetPolicyObject(handle, TSS_POLICY_USAGE, &hPolicy);
215 	if (ret) {
216 		print_error(ret, gettext("Get object policy"));
217 		return (ERR_FAIL);
218 	}
219 
220 	return (set_policy_options(hPolicy, mode, prompt, secret_len, secret));
221 }
222 
223 int
224 tpm_preamble(TSS_HCONTEXT *hContext, TSS_HOBJECT *hTPM)
225 {
226 	TSS_RESULT ret;
227 
228 	ret = Tspi_Context_Create(hContext);
229 	if (ret) {
230 		print_error(ret, gettext("Create context"));
231 		return (ERR_FAIL);
232 	}
233 
234 	ret = Tspi_Context_Connect(*hContext, NULL);
235 	if (ret) {
236 		print_error(ret, gettext("Connect context"));
237 		(void) Tspi_Context_Close(*hContext);
238 		return (ERR_FAIL);
239 	}
240 
241 	ret = Tspi_Context_GetTpmObject(*hContext, hTPM);
242 	if (ret) {
243 		print_error(ret, gettext("Get TPM object"));
244 		(void) Tspi_Context_Close(*hContext);
245 		return (ERR_FAIL);
246 	}
247 	return (0);
248 }
249 
250 int
251 tpm_postamble(TSS_HCONTEXT hContext)
252 {
253 	TSS_RESULT ret;
254 
255 	ret = Tspi_Context_Close(hContext);
256 	if (ret) {
257 		print_error(ret, gettext("Close context"));
258 		return (ERR_FAIL);
259 	}
260 	return (0);
261 }
262