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 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 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 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 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 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 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 NULL, 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 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 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 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