blob: 6ec9d320c87c4a6900893e289e8814a169dea94f [file] [log] [blame]
Gaurav Shahbf6c4a72010-03-05 10:58:48 -08001// Copyright (c) 2009,2010 The Chromium OS Authors. All rights reserved.
2// Use of this source code is governed by a BSD-style license that can be
3// found in the LICENSE file.
4
5#include "bitstring.h"
6#include "commands.h"
7#include "tpm_nv.h"
8
9#include <stdio.h>
10#include <stdlib.h>
11#include <fcntl.h>
12#include <string.h>
13#include <unistd.h>
14#include <sys/types.h>
15#include <sys/stat.h>
16#include <stdint.h>
17#include <getopt.h>
18#include <errno.h>
19#include <limits.h>
20
21#define PROGNAME "tpm-nvtool"
22
23static struct option
24long_options[] = {
25 { "define", no_argument, 0, 'D' },
26 { "file", required_argument, 0, 'f' },
27 { "help", no_argument, 0, 'h' },
28 { "hexdump", no_argument, 0, 'x' },
29 { "index", required_argument, 0, 'I' },
30 { "index_password", required_argument, 0, 'i' },
31 { "list", no_argument, 0, 'l' },
32 { "offset", required_argument, 0, 'O' },
33 { "owner_password", required_argument, 0, 'o' },
34 { "password", required_argument, 0, '0' },
35 { "pcr", required_argument, 0, 'p' },
36 { "permissions", required_argument, 0, 'P' },
37 { "read", no_argument, 0, 'r' },
38 { "release", no_argument, 0, 'R' },
39 { "size", required_argument, 0, 's' },
40 { "string", required_argument, 0, 'd' },
41 { "write", no_argument, 0, 'w' },
42 { "writezero", no_argument, 0, 'z' },
43 { NULL, 0, 0, 0 },
44};
45
46static const char* options = "0:DI:O:P:Rd:f:hi:lo:p:rs:wxz";
47
48static void
49help_brief(void)
50{
51 TNV_stderr("Try %s --help for more information.\n", PROGNAME);
52}
53
54static void
55help_long(void)
56{
57 const char* help_message =
58#include "help/help.h"
59 ;
60 TNV_stderr("%s", help_message);
61}
62
63int
64main(int argc, char** argv)
65{
66 tnv_args_t tnv_args;
67 tnv_context_t* t = NULL;
68 char* tss_server = NULL;
69 uint64_t cmdmap = 0ULL;
70 int c, option_index = 0, ret = 0;
71 int data_fd = -1;
72
73 if (argc <= 1) {
74 help_brief();
75 exit(1);
76 }
77
78 memset(&tnv_args, 0, sizeof(tnv_args));
79 tnv_args.data_fd = -1;
80
81 while ((c = getopt_long(argc, argv, options, long_options, &option_index))
82 != -1) {
83 switch (c) {
84 case '0':
85 tnv_args.password = optarg;
86 tnv_args.flags |= TNV_FLAG_RWAUTH;
87 break;
88 case 'D':
89 cmdmap |= CMD_BITMAP(CMDBIT_TNV_DEFINE);
90 break;
91 case 'I': {
92 errno = 0;
93 char* end;
94 uint64_t tmp_index = strtoull(optarg, &end, 0);
95 if (errno || (end != optarg + strlen(optarg)) ||
96 (tmp_index > UINT_MAX) || (tmp_index == 0)) {
97 TNV_stderr("Invalid index %s.\n", optarg);
98 exit(1);
99 }
100 tnv_args.index = (uint32_t)tmp_index;
101 cmdmap |= CMD_BITMAP(CMDBIT_TNV_INDEX);
102 break;
103 }
104 case 'O':
105 errno = 0;
106 char* end;
107 uint64_t tmp_offset = strtoull(optarg, &end, 0);
108 if (errno || (end != optarg + strlen(optarg)) ||
109 (tmp_offset > UINT_MAX)) {
110 TNV_stderr("Invalid offset %s.\n", optarg);
111 exit(1);
112 }
113 tnv_args.offset = (uint32_t)tmp_offset;
114 break;
115 case 'P': {
116 int i;
117 char* aperm = strtok((char*)optarg, ",");
118 while (aperm) {
119 for (i = 0; TPM_NV_PER_table[i].permission_name; i++) {
120 if (strcasecmp(TPM_NV_PER_table[i].permission_name,
121 aperm) == 0) {
122 if (TPM_NV_PER_table[i].allowed == TRUE) {
123 tnv_args.permissions |=
124 TPM_NV_PER_table[i].permission_value;
125 }
126 }
127 }
128 aperm = strtok(NULL, ",");
129 }
130 break;
131 }
132 case 'R':
133 cmdmap |= CMD_BITMAP(CMDBIT_TNV_RELEASE);
134 break;
135 case 'd':
136 cmdmap |= CMD_BITMAP(CMDBIT_TNV_DATA);
137 if (*optarg == '\0') {
138 TNV_stderr("Attempt to write an empty string.\n");
139 exit(1);
140 }
141 tnv_args.data = optarg;
142 break;
143 case 'f':
144 tnv_args.data = optarg;
145 tnv_args.flags |= TNV_FLAG_FILEDATA;
146 cmdmap |= CMD_BITMAP(CMDBIT_TNV_FILE);
147 break;
148 case 'h':
149 help_long();
150 exit(0);
151 case 'i':
152 tnv_args.index_password = optarg;
153 break;
154 case 'l':
155 cmdmap |= CMD_BITMAP(CMDBIT_TNV_LIST);
156 break;
157 case 'o':
158 tnv_args.owner_password = optarg;
159 break;
160 case 'p': {
161 errno = 0;
162 char* end;
163 uint64_t tmp_pcr = strtoull(optarg, &end, 0);
164 if (errno || (end != optarg + strlen(optarg)) ||
165 (tmp_pcr >= TNV_MAX_PCRS)) {
166 TNV_stderr("Invalid PCR index %s.\n", optarg);
167 exit(1);
168 }
169 bit_set(tnv_args.pcrs_selected.bitmap, tmp_pcr);
170 if ((uint32_t)tmp_pcr > tnv_args.pcrs_selected.highest) {
171 tnv_args.pcrs_selected.highest = (uint32_t)tmp_pcr;
172 }
173 tnv_args.pcrs_selected.count++;
174 break;
175 }
176 case 'r':
177 cmdmap |= CMD_BITMAP(CMDBIT_TNV_READ);
178 break;
179 case 's': {
180 errno = 0;
181 char* end;
182 uint64_t tmp_size = strtoull(optarg, &end, 0);
183 if (errno || (end != optarg + strlen(optarg)) ||
184 (tmp_size > UINT_MAX)) {
185 TNV_stderr("Invalid size %s.\n", optarg);
186 exit(1);
187 }
188 tnv_args.size = (uint32_t)tmp_size;
189 break;
190 }
191 case 'w':
192 cmdmap |= CMD_BITMAP(CMDBIT_TNV_WRITE);
193 break;
194 case 'x':
195 tnv_args.flags |= TNV_FLAG_HEXDUMP;
196 break;
197 case 'z':
198 cmdmap |= CMD_BITMAP(CMDBIT_TNV_WRITEZERO);
199 break;
200 default:
201 help_brief();
202 exit(1);
203 }
204 }
205
206 if (optind != argc) {
207 help_brief();
208 exit(1);
209 }
210
211 switch (cmdmap) {
212 case CMD_TNV_DEFINE:
213 tnv_args.flags |= (TNV_FLAG_CREATE | TNV_FLAG_NEEDOWNER);
214 break;
215 case CMD_TNV_RELEASE:
216 tnv_args.flags |= (TNV_FLAG_DESTROY | TNV_FLAG_NEEDOWNER);
217 break;
218 case CMD_TNV_LIST:
219 tnv_args.flags |= TNV_FLAG_NONSPECIFIC;
220 break;
221 case CMD_TNV_LIST_INDEX:
222 case CMD_TNV_READ:
223 break;
224 case CMD_TNV_WRITE: {
225 size_t dataLength = strlen(tnv_args.data);
226 if ((tnv_args.size == 0) || (tnv_args.size > dataLength)) {
227 tnv_args.size = dataLength;
228 }
229 break;
230 }
231 case CMD_TNV_WRITE_FILE: {
232 struct stat stbuf;
233 char fileBuffer[TNV_MAX_NV_SIZE];
234 int fd = open(tnv_args.data, O_RDONLY);
235 ret = -1;
236 if (fd < 0) {
237 TNV_stderr("Failed to open %s for reading (%s).\n",
238 tnv_args.data, strerror(errno));
239 goto out;
240 }
241 if (fstat(fd, &stbuf) < 0) {
242 TNV_stderr("Failed to stat %s (%s).\n", tnv_args.data,
243 strerror(errno));
244 goto out;
245 }
246 if (stbuf.st_size > TNV_MAX_NV_SIZE) {
247 TNV_stderr("Will not read files larger than %u bytes.\n",
248 TNV_MAX_NV_SIZE);
249 goto out;
250 }
251 if (stbuf.st_size == 0) {
252 TNV_stderr("Zero length file %s.\n", tnv_args.data);
253 goto out;
254 }
255 if (!S_ISREG(stbuf.st_mode)) {
256 TNV_stderr("Will not read from a non-regular file.\n");
257 goto out;
258 }
259 if (read(fd, fileBuffer, stbuf.st_size) != stbuf.st_size) {
260 TNV_stderr("Failed to read file content (%s).\n",
261 strerror(errno));
262 goto out;
263 }
264 tnv_args.data = &fileBuffer[0];
265 if ((tnv_args.size == 0) || (tnv_args.size > stbuf.st_size)) {
266 tnv_args.size = stbuf.st_size;
267 }
268 break;
269 }
270 case CMD_TNV_WRITEZERO:
271 tnv_args.offset = 0;
272 tnv_args.size = 0;
273 break;
274 default:
275 help_brief();
276 exit(1);
277 }
278
279 tnv_args.tss_version = TSS_TSPATTRIB_CONTEXT_VERSION_V1_1;
280
281 t = tnv_open_context(tss_server, &tnv_args);
282 if (t == NULL) {
283 exit(1);
284 }
285
286 switch (cmdmap) {
287 case CMD_TNV_DEFINE:
288 ret = tnv_define(t, &tnv_args);
289 break;
290 case CMD_TNV_LIST:
291 ret = tnv_list(t, &tnv_args);
292 break;
293 case CMD_TNV_LIST_INDEX:
294 ret = tnv_list(t, &tnv_args);
295 break;
296 case CMD_TNV_READ:
297 ret = tnv_read(t, &tnv_args);
298 break;
299 case CMD_TNV_RELEASE:
300 ret = tnv_release(t, &tnv_args);
301 break;
302 case CMD_TNV_WRITE:
303 ret = tnv_write(t, &tnv_args);
304 break;
305 case CMD_TNV_WRITEZERO:
306 ret = tnv_write(t, &tnv_args);
307 break;
308 }
309
310out:
311
312 if (data_fd >= 0) {
313 close(data_fd);
314 }
315
316 tnv_close_context(&t);
317
318 exit(ret);
319}