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>