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
print_usage(char * progname,cmdtable_t cmds[])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
main(int argc,char * argv[])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
print_bytes(BYTE * bytes,size_t len,int formatted)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
print_error(TSS_RESULT ret,char * msg)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
get_tpm_capability(TSS_HCONTEXT hContext,TSS_HOBJECT hTPM,UINT32 cap,UINT32 subcap,void * buf,size_t bufsize)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
set_policy_options(TSS_HPOLICY hPolicy,TSS_FLAG mode,char * prompt,UINT32 secret_len,BYTE * secret)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
set_object_policy(TSS_HOBJECT handle,TSS_FLAG mode,char * prompt,UINT32 secret_len,BYTE * secret)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
tpm_preamble(TSS_HCONTEXT * hContext,TSS_HOBJECT * hTPM)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
tpm_postamble(TSS_HCONTEXT hContext)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