Annotation of embedaddon/strongswan/src/tpm_extendpcr/tpm_extendpcr.c, revision 1.1.1.1
1.1 misho 1: /*
2: * Copyright (C) 2017 Andreas Steffen
3: * HSR Hochschule fuer Technik Rapperswil
4: *
5: * This program is free software; you can redistribute it and/or modify it
6: * under the terms of the GNU General Public License as published by the
7: * Free Software Foundation; either version 2 of the License, or (at your
8: * option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>.
9: *
10: * This program is distributed in the hope that it will be useful, but
11: * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
12: * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
13: * for more details.
14: */
15:
16: #include <tpm_tss.h>
17:
18: #include <library.h>
19: #include <crypto/hashers/hasher.h>
20: #include <utils/debug.h>
21:
22: #include <syslog.h>
23: #include <getopt.h>
24: #include <errno.h>
25:
26:
27: /* logging */
28: static bool log_to_stderr = TRUE;
29: static bool log_to_syslog = TRUE;
30: static level_t default_loglevel = 1;
31:
32: /* global variables */
33: tpm_tss_t *tpm;
34: chunk_t digest;
35: chunk_t pcr_value;
36:
37: /**
38: * logging function for tpm_extendpcr
39: */
40: static void tpm_extendpcr_dbg(debug_t group, level_t level, char *fmt, ...)
41: {
42: char buffer[8192];
43: char *current = buffer, *next;
44: va_list args;
45:
46: if (level <= default_loglevel)
47: {
48: if (log_to_stderr)
49: {
50: va_start(args, fmt);
51: vfprintf(stderr, fmt, args);
52: va_end(args);
53: fprintf(stderr, "\n");
54: }
55: if (log_to_syslog)
56: {
57: /* write in memory buffer first */
58: va_start(args, fmt);
59: vsnprintf(buffer, sizeof(buffer), fmt, args);
60: va_end(args);
61:
62: /* do a syslog with every line */
63: while (current)
64: {
65: next = strchr(current, '\n');
66: if (next)
67: {
68: *(next++) = '\0';
69: }
70: syslog(LOG_INFO, "%s\n", current);
71: current = next;
72: }
73: }
74: }
75: }
76:
77: /**
78: * Initialize logging to stderr/syslog
79: */
80: static void init_log(const char *program)
81: {
82: dbg = tpm_extendpcr_dbg;
83:
84: if (log_to_stderr)
85: {
86: setbuf(stderr, NULL);
87: }
88: if (log_to_syslog)
89: {
90: openlog(program, LOG_CONS | LOG_NDELAY | LOG_PID, LOG_AUTHPRIV);
91: }
92: }
93:
94: /**
95: * @brief exit tpm_extendpcr
96: *
97: * @param status 0 = OK, -1 = general discomfort
98: */
99: static void exit_tpm_extendpcr(err_t message, ...)
100: {
101: int status = 0;
102:
103: DESTROY_IF(tpm);
104: chunk_free(&digest);
105: chunk_free(&pcr_value);
106:
107: /* print any error message to stderr */
108: if (message != NULL && *message != '\0')
109: {
110: va_list args;
111: char m[8192];
112:
113: va_start(args, message);
114: vsnprintf(m, sizeof(m), message, args);
115: va_end(args);
116:
117: fprintf(stderr, "tpm_extendpcr error: %s\n", m);
118: status = -1;
119: }
120: library_deinit();
121: exit(status);
122: }
123:
124: /**
125: * @brief prints the usage of the program to the stderr output
126: *
127: * If message is set, program is exited with 1 (error)
128: * @param message message in case of an error
129: */
130: static void usage(const char *message)
131: {
132: fprintf(stderr,
133: "Usage: tpm_extendpcr [--alg <name>] --pcr <nr> --digest <hex>|--in"
134: " <file>\n"
135: " [--hash] [--out <file>] [--quiet]"
136: " [--debug <level>]\n"
137: " tpm_extendpcr --help\n"
138: "\n"
139: "Options:\n"
140: " --alg (-a) hash algorithm (sha1|sha256)\n"
141: " --pcr (-p) platform configuration register (0..23)\n"
142: " --digest (-d) digest in hex format to be extended\n"
143: " --in (-i) binary input file with digest to be extended\n"
144: " --hash (-x) prehash the input file to create digest\n"
145: " --out (-o) binary output file with updated PCR value\n"
146: " --help (-h) show usage and exit\n"
147: "\n"
148: "Debugging output:\n"
149: " --debug (-l) changes the log level (-1..4, default: 1)\n"
150: " --quiet (-q) do not write log output to stderr\n"
151: );
152: exit_tpm_extendpcr(message);
153: }
154:
155: /**
156: * @brief main of tpm_extendpcr which extends digest into a PCR
157: *
158: * @param argc number of arguments
159: * @param argv pointer to the argument values
160: */
161: int main(int argc, char *argv[])
162: {
163: hash_algorithm_t alg = HASH_SHA1;
164: hasher_t *hasher = NULL;
165: char *infile = NULL, *outfile = NULL;
166: uint32_t pcr = 16;
167: bool hash = FALSE;
168:
169: atexit(library_deinit);
170: if (!library_init(NULL, "tpm_extendpcr"))
171: {
172: exit(SS_RC_LIBSTRONGSWAN_INTEGRITY);
173: }
174: if (lib->integrity &&
175: !lib->integrity->check_file(lib->integrity, "tpm_extendpcr", argv[0]))
176: {
177: fprintf(stderr, "integrity check of tpm_extendpcr failed\n");
178: exit(SS_RC_DAEMON_INTEGRITY);
179: }
180:
181: for (;;)
182: {
183: static const struct option long_opts[] = {
184: /* name, has_arg, flag, val */
185: { "help", no_argument, NULL, 'h' },
186: { "alg", required_argument, NULL, 'a' },
187: { "pcr", required_argument, NULL, 'p' },
188: { "digest", required_argument, NULL, 'd' },
189: { "in", required_argument, NULL, 'i' },
190: { "hash", no_argument, NULL, 'x' },
191: { "out", required_argument, NULL, 'o' },
192: { "quiet", no_argument, NULL, 'q' },
193: { "debug", required_argument, NULL, 'l' },
194: { 0,0,0,0 }
195: };
196:
197: /* parse next option */
198: int c = getopt_long(argc, argv, "ha:p:d:i:xo:ql:", long_opts, NULL);
199:
200: switch (c)
201: {
202: case EOF: /* end of flags */
203: break;
204:
205: case 'h': /* --help */
206: usage(NULL);
207:
208: case 'a': /* --alg <name> */
209: if (!enum_from_name(hash_algorithm_short_names, optarg, &alg))
210: {
211: usage("unsupported hash algorithm");
212: }
213: continue;
214: case 'p': /* --pcr <nr> */
215: pcr = atoi(optarg);
216: continue;
217:
218: case 'd': /* --digest <hex> */
219: digest = chunk_from_hex(chunk_from_str(optarg), NULL);
220: continue;
221:
222: case 'i': /* --in <file> */
223: infile = optarg;
224: continue;
225:
226: case 'x': /* --hash */
227: hash = TRUE;
228: continue;
229:
230: case 'o': /* --out <file> */
231: outfile = optarg;
232: continue;
233:
234: case 'q': /* --quiet */
235: log_to_stderr = FALSE;
236: continue;
237:
238: case 'l': /* --debug <level> */
239: default_loglevel = atoi(optarg);
240: continue;
241:
242: default:
243: usage("unknown option");
244: }
245: /* break from loop */
246: break;
247: }
248:
249: init_log("tpm_extendpcr");
250:
251: if (!lib->plugins->load(lib->plugins,
252: lib->settings->get_str(lib->settings, "tpm_extendpcr.load",
253: "tpm sha1 sha2")))
254: {
255: exit_tpm_extendpcr("plugin loading failed");
256: }
257:
258: /* try to find a TPM */
259: tpm = tpm_tss_probe(TPM_VERSION_ANY);
260: if (!tpm)
261: {
262: exit_tpm_extendpcr("no TPM found");
263: }
264:
265: /* read digest from file */
266: if (digest.len == 0)
267: {
268: chunk_t *chunk;
269:
270: if (!infile)
271: {
272: exit_tpm_extendpcr("--digest or --in option required");
273: }
274: chunk = chunk_map(infile, FALSE);
275: if (!chunk)
276: {
277: exit_tpm_extendpcr("reading input file failed");
278: }
279: if (hash)
280: {
281: hasher = lib->crypto->create_hasher(lib->crypto, alg);
282: if (!hasher || !hasher->allocate_hash(hasher, *chunk, &digest))
283: {
284: DESTROY_IF(hasher);
285: chunk_unmap(chunk);
286: exit_tpm_extendpcr("prehashing infile failed");
287: }
288: hasher->destroy(hasher);
289: }
290: else
291: {
292: digest = chunk_clone(*chunk);
293: }
294: chunk_unmap(chunk);
295: }
296: DBG1(DBG_PTS, "Digest: %#B", &digest);
297:
298: /* extend digest into PCR */
299: if (!tpm->extend_pcr(tpm, pcr, &pcr_value, digest, alg))
300: {
301: exit_tpm_extendpcr("extending PCR failed");
302: }
303: DBG1(DBG_PTS, "PCR %02u: %#B", pcr, &pcr_value);
304:
305: /* write PCR value to file */
306: if (outfile)
307: {
308: if (!chunk_write(pcr_value, outfile, 022, TRUE))
309: {
310: DBG1(DBG_PTS, "writing '%s' failed", outfile);
311: }
312: }
313: chunk_free(&pcr_value);
314:
315: exit_tpm_extendpcr(NULL);
316: return -1; /* should never be reached */
317: }
FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>