293 changes: 137 additions & 156 deletions tools/tpm2_verifysignature.c
Expand Up @@ -29,39 +29,34 @@
// THE POSSIBILITY OF SUCH DAMAGE.
//**********************************************************************;

#include <stdarg.h>

#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <limits.h>
#include <ctype.h>
#include <getopt.h>

#include <sapi/tpm20.h>

#include "tpm2_options.h"
#include "files.h"
#include "log.h"
#include "tpm2_util.h"
#include "tpm_hash.h"
#include "tpm2_alg_util.h"
#include "tpm_hash.h"
#include "tpm2_options.h"
#include "tpm2_tool.h"
#include "tpm2_util.h"

typedef struct tpm2_verifysig_ctx tpm2_verifysig_ctx;
struct tpm2_verifysig_ctx {
union {
struct {
uint8_t key_handle :1;
uint8_t digest :1;
uint8_t halg :1;
uint8_t msg :1;
uint8_t raw :1;
uint8_t sig :1;
uint8_t ticket :1;
uint8_t key_context :1;
UINT8 key_handle :1;
UINT8 digest :1;
UINT8 halg :1;
UINT8 msg :1;
UINT8 raw :1;
UINT8 sig :1;
UINT8 ticket :1;
UINT8 key_context :1;
};
uint8_t all;
UINT8 all;
} flags;
TPMI_ALG_HASH halg;
TPM2B_DIGEST msgHash;
Expand All @@ -71,10 +66,15 @@ struct tpm2_verifysig_ctx {
char *sig_file_path;
char *out_file_path;
char *context_key_file_path;
TSS2_SYS_CONTEXT *sapi_context;
};

static bool verify_signature(tpm2_verifysig_ctx *ctx) {
tpm2_verifysig_ctx ctx = {
.halg = TPM_ALG_SHA1,
.msgHash = TPM2B_TYPE_INIT(TPM2B_DIGEST, buffer),
};

static bool verify_signature(TSS2_SYS_CONTEXT *sapi_context) {


UINT32 rval;
TPMT_TK_VERIFIED validation;
Expand All @@ -88,19 +88,20 @@ static bool verify_signature(tpm2_verifysig_ctx *ctx) {
sessionsDataOut.rspAuthsCount = 1;

UINT16 i;
for (i = 0; i < ctx->msgHash.t.size; i++)
printf("%02x ", ctx->msgHash.t.buffer[i]);
printf("\n");
for (i = 0; i < ctx.msgHash.t.size; i++) {
tpm2_tool_output("%02x ", ctx.msgHash.t.buffer[i]);
}
tpm2_tool_output("\n");

rval = Tss2_Sys_VerifySignature(ctx->sapi_context, ctx->keyHandle, NULL,
&ctx->msgHash, &ctx->signature, &validation, &sessionsDataOut);
rval = Tss2_Sys_VerifySignature(sapi_context, ctx.keyHandle, NULL,
&ctx.msgHash, &ctx.signature, &validation, &sessionsDataOut);
if (rval != TPM_RC_SUCCESS) {
LOG_ERR("Tss2_Sys_VerifySignature failed, error code: 0x%x", rval);
return false;
}

/* TODO fix serialization */
return files_save_bytes_to_file(ctx->out_file_path, (UINT8 *) &validation,
return files_save_bytes_to_file(ctx.out_file_path, (UINT8 *) &validation,
sizeof(validation));
}

Expand Down Expand Up @@ -132,72 +133,86 @@ static TPM2B *message_from_file(const char *msg_file_path) {
return msg;
}

static bool generate_signature(tpm2_verifysig_ctx *ctx) {
static bool generate_signature(void) {

UINT16 size;
UINT8 *buffer;

if (ctx->flags.raw) {
ctx->signature.sigAlg = TPM_ALG_RSASSA;
ctx->signature.signature.rsassa.hash = ctx->halg;
ctx->signature.signature.rsassa.sig.t.size =
sizeof(ctx->signature.signature.rsassa.sig) - 2;
if (ctx.flags.raw) {
ctx.signature.sigAlg = TPM_ALG_RSASSA;
ctx.signature.signature.rsassa.hash = ctx.halg;
ctx.signature.signature.rsassa.sig.t.size =
sizeof(ctx.signature.signature.rsassa.sig) - 2;

buffer = ctx->signature.signature.rsassa.sig.t.buffer;
size = ctx->signature.signature.rsassa.sig.t.size;
buffer = ctx.signature.signature.rsassa.sig.t.buffer;
size = ctx.signature.signature.rsassa.sig.t.size;
} else {
size = sizeof(ctx->signature);
buffer = (UINT8 *) &ctx->signature;
size = sizeof(ctx.signature);
buffer = (UINT8 *) &ctx.signature;
}

bool result = files_load_bytes_from_path(ctx->sig_file_path, buffer, &size);
bool result = files_load_bytes_from_path(ctx.sig_file_path, buffer, &size);
if (!result) {
LOG_ERR("Could not create %s signature from file: \"%s\"",
ctx->flags.raw ? "raw" : "\0", ctx->sig_file_path);
ctx.flags.raw ? "raw" : "\0", ctx.sig_file_path);
}
return result;
}

static bool init(tpm2_verifysig_ctx *ctx) {
static bool init(TSS2_SYS_CONTEXT *sapi_context) {

/* check flags for mismatches */
if (ctx.flags.digest && (ctx.flags.msg || ctx.flags.halg)) {
LOG_ERR(
"Cannot specify --digest (-D) and ( --msg (-m) or --halg (-g) )");
return false;
}

if (!((ctx.flags.key_handle || ctx.flags.key_context) && ctx.flags.sig
&& ctx.flags.ticket)) {
LOG_ERR(
"--keyHandle (-k) or --keyContext (-c) and --sig (-s) and --ticket (-t) must be specified");
return false;
}

TPM2B *msg = NULL;
bool return_value = false;

if (ctx->flags.msg) {
msg = message_from_file(ctx->msg_file_path);
if (ctx.flags.msg) {
msg = message_from_file(ctx.msg_file_path);
if (!msg) {
/* message_from_file() logs specific error no need to here */
return false;
}
}

if (ctx->flags.sig) {
bool res = generate_signature(ctx);
if (ctx.flags.sig) {
bool res = generate_signature();
if (!res) {
goto err;
}
}

if (ctx->flags.key_context) {
bool result = files_load_tpm_context_from_file(ctx->sapi_context, &ctx->keyHandle,
ctx->context_key_file_path);
if (ctx.flags.key_context) {
bool result = files_load_tpm_context_from_file(sapi_context, &ctx.keyHandle,
ctx.context_key_file_path);
if (!result) {
goto err;
}
}

/* If no digest is specified, compute it */
if (!ctx->flags.digest) {
if (!ctx->flags.msg) {
if (!ctx.flags.digest) {
if (!ctx.flags.msg) {
/*
* This is a redundant check since main() checks this case, but we'll add it here to silence any
* complainers.
*/
LOG_ERR("No digest set and no message file to compute from, cannot compute message hash!");
goto err;
}
int rc = tpm_hash_compute_data(ctx->sapi_context, ctx->halg,
TPM_RH_NULL, msg->buffer, msg->size, &ctx->msgHash, NULL);
int rc = tpm_hash_compute_data(sapi_context, ctx.halg,
TPM_RH_NULL, msg->buffer, msg->size, &ctx.msgHash, NULL);
if (rc) {
LOG_ERR("Compute message hash failed!");
goto err;
Expand All @@ -208,12 +223,72 @@ static bool init(tpm2_verifysig_ctx *ctx) {
err:
free(msg);
return return_value;

}

static bool on_option(char key, char *value) {

switch (key) {
case 'k': {
bool res = tpm2_util_string_to_uint32(value, &ctx.keyHandle);
if (!res) {
LOG_ERR("Unable to convert key handle, got: \"%s\"", value);
return false;
}
ctx.flags.key_handle = 1;
}
break;
case 'g': {
ctx.halg = tpm2_alg_util_from_optarg(value);
if (ctx.halg == TPM_ALG_ERROR) {
LOG_ERR("Unable to convert algorithm, got: \"%s\"", value);
return false;
}
ctx.flags.halg = 1;
}
break;
case 'm': {
ctx.msg_file_path = value;
ctx.flags.msg = 1;
}
break;
case 'D': {
UINT16 size = sizeof(ctx.msgHash);
if (!files_load_bytes_from_path(value, (UINT8 *) &ctx.msgHash, &size)) {
LOG_ERR("Could not load digest from file!");
return false;
}
ctx.flags.digest = 1;
}
break;
case 'r':
ctx.flags.raw = 1;
break;
case 's':
ctx.sig_file_path = value;
ctx.flags.sig = 1;
break;
case 't':
ctx.out_file_path = value;

if (files_does_file_exist(ctx.out_file_path)) {
return false;
}
ctx.flags.ticket = 1;
break;
case 'c':
ctx.context_key_file_path = value;
ctx.flags.key_context = 1;
break;
/* no default */
}

return true;
}

static bool handle_options_and_init(int argc, char *argv[], tpm2_verifysig_ctx *ctx) {
bool tpm2_tool_onstart(tpm2_options **opts) {

const char *optstring = "k:g:m:D:rs:t:c:";
const struct option long_options[] = {
const struct option topts[] = {
{ "keyHandle", 1, NULL, 'k' },
{ "digest", 1, NULL, 'D' },
{ "halg", 1, NULL, 'g' },
Expand All @@ -225,121 +300,27 @@ static bool handle_options_and_init(int argc, char *argv[], tpm2_verifysig_ctx *
{ NULL, 0, NULL, '\0' }
};

if (argc == 1) {
LOG_ERR("Invalid usage. Try --help for help.");
return false;
}

int opt;
while ((opt = getopt_long(argc, argv, optstring, long_options, NULL)) != -1) {
switch (opt) {
case 'k': {
bool res = tpm2_util_string_to_uint32(optarg, &ctx->keyHandle);
if (!res) {
LOG_ERR("Unable to convert key handle, got: \"%s\"", optarg);
return false;
}
ctx->flags.key_handle = 1;
}
break;
case 'g': {
ctx->halg = tpm2_alg_util_from_optarg(optarg);
if (ctx->halg == TPM_ALG_ERROR) {
LOG_ERR("Unable to convert algorithm, got: \"%s\"", optarg);
return false;
}
ctx->flags.halg = 1;
}
break;
case 'm': {
ctx->msg_file_path = optarg;
ctx->flags.msg = 1;
}
break;
case 'D': {
UINT16 size = sizeof(ctx->msgHash);
if (!files_load_bytes_from_path(optarg, (UINT8 *) &ctx->msgHash, &size)) {
LOG_ERR("Could not load digest from file!");
return false;
}
ctx->flags.digest = 1;
}
break;
case 'r':
ctx->flags.raw = 1;
break;
case 's':
ctx->sig_file_path = optarg;
ctx->flags.sig = 1;
break;
case 't':
ctx->out_file_path = optarg;

if (files_does_file_exist(ctx->out_file_path)) {
return false;
}
ctx->flags.ticket = 1;
break;
case 'c':
ctx->context_key_file_path = optarg;
ctx->flags.key_context = 1;
break;
case ':':
LOG_ERR("Argument %c needs a value!", optopt);
break;
case '?':
LOG_ERR("Unknown Argument: %c", optopt);
break;
/* no default */
}
};

/* check flags for mismatches */
if (ctx->flags.digest && (ctx->flags.msg || ctx->flags.halg)) {
LOG_ERR(
"Cannot specify --digest (-D) and ( --msg (-m) or --halg (-g) )");
return false;
}

if (!((ctx->flags.key_handle || ctx->flags.key_context) && ctx->flags.sig
&& ctx->flags.ticket)) {
LOG_ERR(
"--keyHandle (-k) or --keyContext (-c) and --sig (-s) and --ticket (-t) must be specified");
return false;
}
*opts = tpm2_options_new("k:g:m:D:rs:t:c:", ARRAY_LEN(topts), topts,
on_option, NULL);

/* initialize and process */
return init(ctx);
return *opts != NULL;
}

int execute_tool(int argc, char *argv[], char *envp[], common_opts_t *opts,
TSS2_SYS_CONTEXT *sapi_context) {

(void) opts;
(void) envp;
int tpm2_tool_onrun(TSS2_SYS_CONTEXT *sapi_context, tpm2_option_flags flags) {

int normalized_return_code = 1;
UNUSED(flags);

tpm2_verifysig_ctx ctx = {
.flags = { .all = 0 },
.halg = TPM_ALG_SHA1,
.msgHash = TPM2B_TYPE_INIT(TPM2B_DIGEST, buffer),
.sig_file_path = NULL,
.msg_file_path = NULL,
.out_file_path = NULL,
.context_key_file_path = NULL,
.sapi_context = sapi_context
};

bool res = handle_options_and_init(argc, argv, &ctx);
/* initialize and process */
bool res = init(sapi_context);
if (!res) {
return normalized_return_code;
return 1;
}

res = verify_signature(&ctx);
res = verify_signature(sapi_context);
if (!res) {
LOG_ERR("Verify signature failed!");
return normalized_return_code;
return 1;
}

return 0;
Expand Down