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 * Copyright 2018 OmniOS Community Edition (OmniOSce) Association.
26 */
27
28
29 #include <stdlib.h>
30 #include <stdio.h>
31 #include <unistd.h>
32 #include <strings.h>
33 #include <libintl.h>
34 #include <locale.h>
35
36 #include <tss/tspi.h>
37 #include <trousers/trousers.h>
38 #include "tpmadm.h"
39
40 extern cmdtable_t commands[];
41
42 static void
print_usage(char * progname,cmdtable_t cmds[])43 print_usage(char *progname, cmdtable_t cmds[])
44 {
45 cmdtable_t *p;
46
47 (void) fprintf(stderr,
48 gettext("usage: %s command args ...\n"), progname);
49 (void) fprintf(stderr,
50 gettext("where 'command' is one of the following:\n"));
51 for (p = &cmds[0]; p->name != NULL; p++) {
52 (void) fprintf(stderr, "\t%s %s\n", p->name, p->args);
53 }
54 }
55
56 int
main(int argc,char * argv[])57 main(int argc, char *argv[])
58 {
59 char *progname;
60 cmdtable_t *p;
61 cmdfunc_t fptr = NULL;
62 int ret;
63 TSS_HCONTEXT hContext;
64 TSS_HOBJECT hTPM;
65
66 /* Set up for i18n/l10n. */
67 #if !defined(TEXT_DOMAIN) /* Should be defined by cc -D. */
68 #define TEXT_DOMAIN "SYS_TEST" /* Use this only if it isn't. */
69 #endif
70 (void) setlocale(LC_ALL, "");
71 (void) textdomain(TEXT_DOMAIN);
72
73 progname = argv[0];
74 argc--;
75 argv++;
76
77 if (argc <= 0) {
78 print_usage(progname, commands);
79 return (ERR_USAGE);
80 }
81
82 for (p = &commands[0]; p->name != NULL; p++) {
83 if (0 == strcmp(p->name, argv[0])) {
84 fptr = p->func;
85 break;
86 }
87 }
88 if (fptr == NULL) {
89 print_usage(progname, commands);
90 return (ERR_USAGE);
91 }
92
93 if (tpm_preamble(&hContext, &hTPM))
94 return (ERR_FAIL);
95 ret = fptr(hContext, hTPM, argc, argv);
96 (void) tpm_postamble(hContext);
97
98 return (ret);
99 }
100
101
102 /*
103 * Utility functions
104 */
105
106 void
print_bytes(BYTE * bytes,size_t len,int formatted)107 print_bytes(BYTE *bytes, size_t len, int formatted)
108 {
109 int i;
110 for (i = 0; i < len; i++) {
111 (void) printf("%02X ", bytes[i]);
112 if (formatted && i % 16 == 7)
113 (void) printf(" ");
114 if (formatted && i % 16 == 15)
115 (void) printf("\n");
116 }
117 (void) printf("\n");
118 }
119
120
121 /*
122 * TSS convenience functions
123 */
124
125 void
print_error(TSS_RESULT ret,char * msg)126 print_error(TSS_RESULT ret, char *msg)
127 {
128 char *err_string;
129
130 /* Print the standard error string and error code. */
131 err_string = Trspi_Error_String(ret);
132 (void) fprintf(stderr, "%s: %s (0x%0x)\n", msg, err_string, ret);
133
134 /* For a few special cases, add a more verbose error message. */
135 switch (ret) {
136 case TPM_E_DEACTIVATED:
137 case TPM_E_DISABLED:
138 (void) fprintf(stderr,
139 gettext("Enable the TPM and reboot.\n"));
140 break;
141 case TSP_ERROR(TSS_E_COMM_FAILURE):
142 (void) fprintf(stderr,
143 gettext("Make sure the tcsd service "
144 "(svc:/application/security/tcsd) is running.\n"));
145 break;
146 }
147 }
148
149 int
get_tpm_capability(TSS_HCONTEXT hContext,TSS_HOBJECT hTPM,UINT32 cap,UINT32 subcap,void * buf,size_t bufsize)150 get_tpm_capability(TSS_HCONTEXT hContext, TSS_HOBJECT hTPM, UINT32 cap,
151 UINT32 subcap, void *buf, size_t bufsize)
152 {
153 TSS_RESULT ret;
154 UINT32 datalen;
155 BYTE *data;
156
157 ret = Tspi_TPM_GetCapability(hTPM, cap, sizeof (subcap),
158 (BYTE *)&subcap, &datalen, &data);
159 if (ret) {
160 print_error(ret, gettext("Get TPM capability"));
161 return (ERR_FAIL);
162 }
163
164 if (datalen > bufsize) {
165 (void) fprintf(stderr,
166 gettext("Capability 0x%x returned %u bytes "
167 "(expected %u)\n"), cap, datalen, bufsize);
168 return (ERR_FAIL);
169 }
170 bcopy(data, buf, datalen);
171
172 ret = Tspi_Context_FreeMemory(hContext, data);
173 if (ret) {
174 print_error(ret, gettext("Free capability buffer"));
175 return (ERR_FAIL);
176 }
177
178 return (0);
179 }
180
181 int
set_policy_options(TSS_HPOLICY hPolicy,TSS_FLAG mode,char * prompt,UINT32 secret_len,BYTE * secret)182 set_policy_options(TSS_HPOLICY hPolicy, TSS_FLAG mode, char *prompt,
183 UINT32 secret_len, BYTE *secret)
184 {
185 TSS_RESULT ret;
186 BYTE *unicode_prompt;
187 UINT32 len;
188
189 ret = Tspi_Policy_SetSecret(hPolicy, mode, secret_len, secret);
190 if (ret) {
191 print_error(ret, gettext("Set policy secret"));
192 return (ERR_FAIL);
193 }
194 if (prompt != NULL) {
195 unicode_prompt = Trspi_Native_To_UNICODE((BYTE *)prompt, &len);
196 ret = Tspi_SetAttribData(hPolicy,
197 TSS_TSPATTRIB_POLICY_POPUPSTRING,
198 0, len, unicode_prompt);
199 if (ret) {
200 print_error(ret, gettext("Set policy prompt"));
201 return (ERR_FAIL);
202 }
203 }
204
205 return (0);
206 }
207
208 int
set_object_policy(TSS_HOBJECT handle,TSS_FLAG mode,char * prompt,UINT32 secret_len,BYTE * secret)209 set_object_policy(TSS_HOBJECT handle, TSS_FLAG mode, char *prompt,
210 UINT32 secret_len, BYTE *secret)
211 {
212 TSS_HPOLICY hPolicy;
213 TSS_RESULT ret;
214
215 ret = Tspi_GetPolicyObject(handle, TSS_POLICY_USAGE, &hPolicy);
216 if (ret) {
217 print_error(ret, gettext("Get object policy"));
218 return (ERR_FAIL);
219 }
220
221 return (set_policy_options(hPolicy, mode, prompt, secret_len, secret));
222 }
223
224 int
tpm_preamble(TSS_HCONTEXT * hContext,TSS_HOBJECT * hTPM)225 tpm_preamble(TSS_HCONTEXT *hContext, TSS_HOBJECT *hTPM)
226 {
227 TSS_RESULT ret;
228
229 ret = Tspi_Context_Create(hContext);
230 if (ret) {
231 print_error(ret, gettext("Create context"));
232 return (ERR_FAIL);
233 }
234
235 ret = Tspi_Context_Connect(*hContext, NULL);
236 if (ret) {
237 print_error(ret, gettext("Connect context"));
238 (void) Tspi_Context_Close(*hContext);
239 return (ERR_FAIL);
240 }
241
242 ret = Tspi_Context_GetTpmObject(*hContext, hTPM);
243 if (ret) {
244 print_error(ret, gettext("Get TPM object"));
245 (void) Tspi_Context_Close(*hContext);
246 return (ERR_FAIL);
247 }
248 return (0);
249 }
250
251 int
tpm_postamble(TSS_HCONTEXT hContext)252 tpm_postamble(TSS_HCONTEXT hContext)
253 {
254 TSS_RESULT ret;
255
256 ret = Tspi_Context_Close(hContext);
257 if (ret) {
258 print_error(ret, gettext("Close context"));
259 return (ERR_FAIL);
260 }
261 return (0);
262 }
263