147e946e7SWyllys Ingersoll /* 247e946e7SWyllys Ingersoll * CDDL HEADER START 347e946e7SWyllys Ingersoll * 447e946e7SWyllys Ingersoll * The contents of this file are subject to the terms of the 547e946e7SWyllys Ingersoll * Common Development and Distribution License (the "License"). 647e946e7SWyllys Ingersoll * You may not use this file except in compliance with the License. 747e946e7SWyllys Ingersoll * 847e946e7SWyllys Ingersoll * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 947e946e7SWyllys Ingersoll * or http://www.opensolaris.org/os/licensing. 1047e946e7SWyllys Ingersoll * See the License for the specific language governing permissions 1147e946e7SWyllys Ingersoll * and limitations under the License. 1247e946e7SWyllys Ingersoll * 1347e946e7SWyllys Ingersoll * When distributing Covered Code, include this CDDL HEADER in each 1447e946e7SWyllys Ingersoll * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 1547e946e7SWyllys Ingersoll * If applicable, add the following below this CDDL HEADER, with the 1647e946e7SWyllys Ingersoll * fields enclosed by brackets "[]" replaced with your own identifying 1747e946e7SWyllys Ingersoll * information: Portions Copyright [yyyy] [name of copyright owner] 1847e946e7SWyllys Ingersoll * 1947e946e7SWyllys Ingersoll * CDDL HEADER END 2047e946e7SWyllys Ingersoll */ 2147e946e7SWyllys Ingersoll 2247e946e7SWyllys Ingersoll /* 2347e946e7SWyllys Ingersoll * Copyright 2009 Sun Microsystems, Inc. All rights reserved. 2447e946e7SWyllys Ingersoll * Use is subject to license terms. 2547e946e7SWyllys Ingersoll */ 2647e946e7SWyllys Ingersoll 2747e946e7SWyllys Ingersoll 2847e946e7SWyllys Ingersoll #include <stdlib.h> 2947e946e7SWyllys Ingersoll #include <stdio.h> 3047e946e7SWyllys Ingersoll #include <unistd.h> 3147e946e7SWyllys Ingersoll #include <strings.h> 3247e946e7SWyllys Ingersoll #include <libintl.h> 3347e946e7SWyllys Ingersoll #include <locale.h> 3447e946e7SWyllys Ingersoll 3547e946e7SWyllys Ingersoll #include <tss/tspi.h> 36*304d8f90SScott Rotondo #include <trousers/trousers.h> 3747e946e7SWyllys Ingersoll #include "tpmadm.h" 3847e946e7SWyllys Ingersoll 3947e946e7SWyllys Ingersoll extern cmdtable_t commands[]; 4047e946e7SWyllys Ingersoll 4147e946e7SWyllys Ingersoll static void 4247e946e7SWyllys Ingersoll print_usage(char *progname, cmdtable_t cmds[]) 4347e946e7SWyllys Ingersoll { 4447e946e7SWyllys Ingersoll cmdtable_t *p; 4547e946e7SWyllys Ingersoll 4647e946e7SWyllys Ingersoll (void) fprintf(stderr, 4747e946e7SWyllys Ingersoll gettext("usage: %s command args ...\n"), progname); 4847e946e7SWyllys Ingersoll (void) fprintf(stderr, 4947e946e7SWyllys Ingersoll gettext("where 'command' is one of the following:\n")); 5047e946e7SWyllys Ingersoll for (p = &cmds[0]; p->name != NULL; p++) { 5147e946e7SWyllys Ingersoll (void) fprintf(stderr, "\t%s %s\n", p->name, p->args); 5247e946e7SWyllys Ingersoll } 5347e946e7SWyllys Ingersoll } 5447e946e7SWyllys Ingersoll 5547e946e7SWyllys Ingersoll int 5647e946e7SWyllys Ingersoll main(int argc, char *argv[]) 5747e946e7SWyllys Ingersoll { 5847e946e7SWyllys Ingersoll char *progname; 5947e946e7SWyllys Ingersoll cmdtable_t *p; 6047e946e7SWyllys Ingersoll cmdfunc_t fptr = NULL; 6147e946e7SWyllys Ingersoll int ret; 6247e946e7SWyllys Ingersoll TSS_HCONTEXT hContext; 6347e946e7SWyllys Ingersoll TSS_HOBJECT hTPM; 6447e946e7SWyllys Ingersoll 6547e946e7SWyllys Ingersoll /* Set up for i18n/l10n. */ 6647e946e7SWyllys Ingersoll #if !defined(TEXT_DOMAIN) /* Should be defined by cc -D. */ 6747e946e7SWyllys Ingersoll #define TEXT_DOMAIN "SYS_TEST" /* Use this only if it isn't. */ 6847e946e7SWyllys Ingersoll #endif 6947e946e7SWyllys Ingersoll (void) setlocale(LC_ALL, ""); 7047e946e7SWyllys Ingersoll (void) textdomain(TEXT_DOMAIN); 7147e946e7SWyllys Ingersoll 7247e946e7SWyllys Ingersoll progname = argv[0]; 7347e946e7SWyllys Ingersoll argc--; 7447e946e7SWyllys Ingersoll argv++; 7547e946e7SWyllys Ingersoll 7647e946e7SWyllys Ingersoll if (argc <= 0) { 7747e946e7SWyllys Ingersoll print_usage(progname, commands); 7847e946e7SWyllys Ingersoll return (ERR_USAGE); 7947e946e7SWyllys Ingersoll } 8047e946e7SWyllys Ingersoll 8147e946e7SWyllys Ingersoll for (p = &commands[0]; p->name != NULL; p++) { 8247e946e7SWyllys Ingersoll if (0 == strcmp(p->name, argv[0])) { 8347e946e7SWyllys Ingersoll fptr = p->func; 8447e946e7SWyllys Ingersoll break; 8547e946e7SWyllys Ingersoll } 8647e946e7SWyllys Ingersoll } 8747e946e7SWyllys Ingersoll if (fptr == NULL) { 8847e946e7SWyllys Ingersoll print_usage(progname, commands); 8947e946e7SWyllys Ingersoll return (ERR_USAGE); 9047e946e7SWyllys Ingersoll } 9147e946e7SWyllys Ingersoll 9247e946e7SWyllys Ingersoll if (tpm_preamble(&hContext, &hTPM)) 9347e946e7SWyllys Ingersoll return (ERR_FAIL); 9447e946e7SWyllys Ingersoll ret = fptr(hContext, hTPM, argc, argv); 9547e946e7SWyllys Ingersoll (void) tpm_postamble(hContext); 9647e946e7SWyllys Ingersoll 9747e946e7SWyllys Ingersoll return (ret); 9847e946e7SWyllys Ingersoll } 9947e946e7SWyllys Ingersoll 10047e946e7SWyllys Ingersoll 10147e946e7SWyllys Ingersoll /* 10247e946e7SWyllys Ingersoll * Utility functions 10347e946e7SWyllys Ingersoll */ 10447e946e7SWyllys Ingersoll 10547e946e7SWyllys Ingersoll void 10647e946e7SWyllys Ingersoll print_bytes(BYTE *bytes, size_t len, int formatted) 10747e946e7SWyllys Ingersoll { 10847e946e7SWyllys Ingersoll int i; 10947e946e7SWyllys Ingersoll for (i = 0; i < len; i++) { 11047e946e7SWyllys Ingersoll (void) printf("%02X ", bytes[i]); 11147e946e7SWyllys Ingersoll if (formatted && i % 16 == 7) 11247e946e7SWyllys Ingersoll (void) printf(" "); 11347e946e7SWyllys Ingersoll if (formatted && i % 16 == 15) 11447e946e7SWyllys Ingersoll (void) printf("\n"); 11547e946e7SWyllys Ingersoll } 11647e946e7SWyllys Ingersoll (void) printf("\n"); 11747e946e7SWyllys Ingersoll } 11847e946e7SWyllys Ingersoll 11947e946e7SWyllys Ingersoll 12047e946e7SWyllys Ingersoll /* 12147e946e7SWyllys Ingersoll * TSS convenience functions 12247e946e7SWyllys Ingersoll */ 12347e946e7SWyllys Ingersoll 12447e946e7SWyllys Ingersoll void 12547e946e7SWyllys Ingersoll print_error(TSS_RESULT ret, char *msg) 12647e946e7SWyllys Ingersoll { 12747e946e7SWyllys Ingersoll char *err_string; 12847e946e7SWyllys Ingersoll 12935494a3dSScott Rotondo /* Print the standard error string and error code. */ 13047e946e7SWyllys Ingersoll err_string = Trspi_Error_String(ret); 13147e946e7SWyllys Ingersoll (void) fprintf(stderr, "%s: %s (0x%0x)\n", msg, err_string, ret); 13235494a3dSScott Rotondo 13335494a3dSScott Rotondo /* For a few special cases, add a more verbose error message. */ 13435494a3dSScott Rotondo switch (ret) { 13535494a3dSScott Rotondo case TPM_E_DEACTIVATED: 13635494a3dSScott Rotondo case TPM_E_DISABLED: 13735494a3dSScott Rotondo (void) fprintf(stderr, 13835494a3dSScott Rotondo gettext("Enable the TPM and restart Solaris.\n")); 13935494a3dSScott Rotondo break; 14035494a3dSScott Rotondo case TSP_ERROR(TSS_E_COMM_FAILURE): 14135494a3dSScott Rotondo (void) fprintf(stderr, 14235494a3dSScott Rotondo gettext("Make sure the tcsd service " 14335494a3dSScott Rotondo "(svc:/application/security/tcsd) is running.\n")); 14435494a3dSScott Rotondo break; 14535494a3dSScott Rotondo } 14647e946e7SWyllys Ingersoll } 14747e946e7SWyllys Ingersoll 14847e946e7SWyllys Ingersoll int 14947e946e7SWyllys Ingersoll get_tpm_capability(TSS_HCONTEXT hContext, TSS_HOBJECT hTPM, UINT32 cap, 15047e946e7SWyllys Ingersoll UINT32 subcap, void *buf, size_t bufsize) 15147e946e7SWyllys Ingersoll { 15247e946e7SWyllys Ingersoll TSS_RESULT ret; 15347e946e7SWyllys Ingersoll UINT32 datalen; 15447e946e7SWyllys Ingersoll BYTE *data; 15547e946e7SWyllys Ingersoll 15647e946e7SWyllys Ingersoll ret = Tspi_TPM_GetCapability(hTPM, cap, sizeof (subcap), 15747e946e7SWyllys Ingersoll (BYTE *)&subcap, &datalen, &data); 15847e946e7SWyllys Ingersoll if (ret) { 15947e946e7SWyllys Ingersoll print_error(ret, gettext("Get TPM capability")); 16047e946e7SWyllys Ingersoll return (ERR_FAIL); 16147e946e7SWyllys Ingersoll } 16247e946e7SWyllys Ingersoll 16347e946e7SWyllys Ingersoll if (datalen > bufsize) { 16447e946e7SWyllys Ingersoll (void) fprintf(stderr, 16547e946e7SWyllys Ingersoll gettext("Capability 0x%x returned %u bytes " 16647e946e7SWyllys Ingersoll "(expected %u)\n"), cap, datalen, bufsize); 16747e946e7SWyllys Ingersoll return (ERR_FAIL); 16847e946e7SWyllys Ingersoll } 16947e946e7SWyllys Ingersoll bcopy(data, buf, datalen); 17047e946e7SWyllys Ingersoll 17147e946e7SWyllys Ingersoll ret = Tspi_Context_FreeMemory(hContext, data); 17247e946e7SWyllys Ingersoll if (ret) { 17347e946e7SWyllys Ingersoll print_error(ret, gettext("Free capability buffer")); 17447e946e7SWyllys Ingersoll return (ERR_FAIL); 17547e946e7SWyllys Ingersoll } 17647e946e7SWyllys Ingersoll 17747e946e7SWyllys Ingersoll return (0); 17847e946e7SWyllys Ingersoll } 17947e946e7SWyllys Ingersoll 18047e946e7SWyllys Ingersoll int 181*304d8f90SScott Rotondo set_policy_options(TSS_HPOLICY hPolicy, TSS_FLAG mode, char *prompt, 182*304d8f90SScott Rotondo UINT32 secret_len, BYTE *secret) 183*304d8f90SScott Rotondo { 184*304d8f90SScott Rotondo TSS_RESULT ret; 185*304d8f90SScott Rotondo BYTE *unicode_prompt; 186*304d8f90SScott Rotondo UINT32 len; 187*304d8f90SScott Rotondo 188*304d8f90SScott Rotondo ret = Tspi_Policy_SetSecret(hPolicy, mode, secret_len, secret); 189*304d8f90SScott Rotondo if (ret) { 190*304d8f90SScott Rotondo print_error(ret, gettext("Set policy secret")); 191*304d8f90SScott Rotondo return (ERR_FAIL); 192*304d8f90SScott Rotondo } 193*304d8f90SScott Rotondo if (prompt != NULL) { 194*304d8f90SScott Rotondo unicode_prompt = Trspi_Native_To_UNICODE((BYTE *)prompt, &len); 195*304d8f90SScott Rotondo ret = Tspi_SetAttribData(hPolicy, 196*304d8f90SScott Rotondo TSS_TSPATTRIB_POLICY_POPUPSTRING, 197*304d8f90SScott Rotondo NULL, len, unicode_prompt); 198*304d8f90SScott Rotondo if (ret) { 199*304d8f90SScott Rotondo print_error(ret, gettext("Set policy prompt")); 200*304d8f90SScott Rotondo return (ERR_FAIL); 201*304d8f90SScott Rotondo } 202*304d8f90SScott Rotondo } 203*304d8f90SScott Rotondo 204*304d8f90SScott Rotondo return (0); 205*304d8f90SScott Rotondo } 206*304d8f90SScott Rotondo 207*304d8f90SScott Rotondo int 208*304d8f90SScott Rotondo set_object_policy(TSS_HOBJECT handle, TSS_FLAG mode, char *prompt, 209*304d8f90SScott Rotondo UINT32 secret_len, BYTE *secret) 21047e946e7SWyllys Ingersoll { 21147e946e7SWyllys Ingersoll TSS_HPOLICY hPolicy; 21247e946e7SWyllys Ingersoll TSS_RESULT ret; 21347e946e7SWyllys Ingersoll 21447e946e7SWyllys Ingersoll ret = Tspi_GetPolicyObject(handle, TSS_POLICY_USAGE, &hPolicy); 21547e946e7SWyllys Ingersoll if (ret) { 21647e946e7SWyllys Ingersoll print_error(ret, gettext("Get object policy")); 21747e946e7SWyllys Ingersoll return (ERR_FAIL); 21847e946e7SWyllys Ingersoll } 21947e946e7SWyllys Ingersoll 220*304d8f90SScott Rotondo return (set_policy_options(hPolicy, mode, prompt, secret_len, secret)); 22147e946e7SWyllys Ingersoll } 22247e946e7SWyllys Ingersoll 22347e946e7SWyllys Ingersoll int 22447e946e7SWyllys Ingersoll tpm_preamble(TSS_HCONTEXT *hContext, TSS_HOBJECT *hTPM) 22547e946e7SWyllys Ingersoll { 22647e946e7SWyllys Ingersoll TSS_RESULT ret; 22747e946e7SWyllys Ingersoll 22847e946e7SWyllys Ingersoll ret = Tspi_Context_Create(hContext); 22947e946e7SWyllys Ingersoll if (ret) { 23047e946e7SWyllys Ingersoll print_error(ret, gettext("Create context")); 23147e946e7SWyllys Ingersoll return (ERR_FAIL); 23247e946e7SWyllys Ingersoll } 23347e946e7SWyllys Ingersoll 23447e946e7SWyllys Ingersoll ret = Tspi_Context_Connect(*hContext, NULL); 23547e946e7SWyllys Ingersoll if (ret) { 23647e946e7SWyllys Ingersoll print_error(ret, gettext("Connect context")); 23747e946e7SWyllys Ingersoll (void) Tspi_Context_Close(*hContext); 23847e946e7SWyllys Ingersoll return (ERR_FAIL); 23947e946e7SWyllys Ingersoll } 24047e946e7SWyllys Ingersoll 24147e946e7SWyllys Ingersoll ret = Tspi_Context_GetTpmObject(*hContext, hTPM); 24247e946e7SWyllys Ingersoll if (ret) { 24347e946e7SWyllys Ingersoll print_error(ret, gettext("Get TPM object")); 24447e946e7SWyllys Ingersoll (void) Tspi_Context_Close(*hContext); 24547e946e7SWyllys Ingersoll return (ERR_FAIL); 24647e946e7SWyllys Ingersoll } 24747e946e7SWyllys Ingersoll return (0); 24847e946e7SWyllys Ingersoll } 24947e946e7SWyllys Ingersoll 25047e946e7SWyllys Ingersoll int 25147e946e7SWyllys Ingersoll tpm_postamble(TSS_HCONTEXT hContext) 25247e946e7SWyllys Ingersoll { 25347e946e7SWyllys Ingersoll TSS_RESULT ret; 25447e946e7SWyllys Ingersoll 25547e946e7SWyllys Ingersoll ret = Tspi_Context_Close(hContext); 25647e946e7SWyllys Ingersoll if (ret) { 25747e946e7SWyllys Ingersoll print_error(ret, gettext("Close context")); 25847e946e7SWyllys Ingersoll return (ERR_FAIL); 25947e946e7SWyllys Ingersoll } 26047e946e7SWyllys Ingersoll return (0); 26147e946e7SWyllys Ingersoll } 262