Annotation of embedaddon/strongswan/src/tpm_extendpcr/tpm_extendpcr.c, revision 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>