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>