Skip to content

Commit

Permalink
man/tpm2_verifysignature: clarify the scheme option
Browse files Browse the repository at this point in the history
The -f/scheme option was confusing. One only needs to specify
the --scheme when the non *tss* format is used. The TSS format
contains the metadata identifying the type of signature it is.
It's only the *plain* formats that come from openssl or similair
tools that require the scheme.

Also, that clause said it only supports RSASSA, which is incorrect.

Signed-off-by: William Roberts <[email protected]>
  • Loading branch information
William Roberts committed Jun 2, 2020
1 parent f3341d3 commit e275ba5
Show file tree
Hide file tree
Showing 8 changed files with 156 additions and 41 deletions.
2 changes: 2 additions & 0 deletions lib/files.c
Original file line number Diff line number Diff line change
Expand Up @@ -730,10 +730,12 @@ tool_rc files_save_ESYS_TR(ESYS_CONTEXT *ectx, ESYS_TR handle, const char *path)
SAVE_TYPE(TPM2B_PUBLIC, public)
LOAD_TYPE(TPM2B_PUBLIC, public)
LOAD_TYPE_FILE(TPM2B_PUBLIC, public)
LOAD_TYPE_SILENT(TPM2B_PUBLIC, public)

SAVE_TYPE(TPMT_PUBLIC, template)
LOAD_TYPE(TPMT_PUBLIC, template)
LOAD_TYPE_FILE(TPMT_PUBLIC, template)
LOAD_TYPE_SILENT(TPMT_PUBLIC, template)

SAVE_TYPE(TPMT_SIGNATURE, signature)
LOAD_TYPE(TPMT_SIGNATURE, signature)
Expand Down
21 changes: 21 additions & 0 deletions lib/files.h
Original file line number Diff line number Diff line change
Expand Up @@ -168,6 +168,17 @@ bool files_save_public(TPM2B_PUBLIC *public, const char *path);
*/
bool files_save_template(TPMT_PUBLIC *template, const char *path);

/**
* Like files_load_template(), but doesn't report errors.
* @param path
* The path containing the TPMT_PUBLIC to load from.
* @param public
* The destination for the TPMT_PUBLIC.
* @return
* true on success, false otherwise.
*/
bool files_load_template_silent(const char *path, TPMT_PUBLIC *public);

/**
* Loads a TPM2B_PUBLIC from disk that was saved with files_save_pubkey()
* @param path
Expand All @@ -185,6 +196,16 @@ bool files_load_template(const char *path, TPMT_PUBLIC *public);

bool files_load_template_file(FILE *f, const char *path, TPMT_PUBLIC *public);

/**
* Like files_load_public(), but doesn't report errors.
* @param path
* The path containing the TP2B_PUBLIC to load from.
* @param public
* The destination for the TP2B_PUBLIC.
* @return
* true on success, false otherwise.
*/
bool files_load_public_silent(const char *path, TPM2B_PUBLIC *public);

/**
* Serializes a TPMT_SIGNATURE to the file path provided.
Expand Down
116 changes: 96 additions & 20 deletions lib/tpm2_convert.c
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,8 @@
#include <string.h>
#include <strings.h>

#include <openssl/bio.h>
#include <openssl/err.h>
#include <openssl/pem.h>

#include "files.h"
Expand Down Expand Up @@ -69,7 +71,7 @@ bool tpm2_convert_pubkey_save(TPM2B_PUBLIC *public,
}

static bool convert_pubkey_RSA(TPMT_PUBLIC *public,
tpm2_convert_pubkey_fmt format, FILE *fp) {
tpm2_convert_pubkey_fmt format, BIO *bio) {

bool ret = false;
RSA *ssl_rsa_key = NULL;
Expand Down Expand Up @@ -109,10 +111,10 @@ static bool convert_pubkey_RSA(TPMT_PUBLIC *public,

switch (format) {
case pubkey_format_pem:
ssl_res = PEM_write_RSA_PUBKEY(fp, ssl_rsa_key);
ssl_res = PEM_write_bio_RSA_PUBKEY(bio, ssl_rsa_key);
break;
case pubkey_format_der:
ssl_res = i2d_RSA_PUBKEY_fp(fp, ssl_rsa_key);
ssl_res = i2d_RSA_PUBKEY_bio(bio, ssl_rsa_key);
break;
default:
LOG_ERR("Invalid OpenSSL target format %d encountered", format);
Expand Down Expand Up @@ -140,7 +142,7 @@ static bool convert_pubkey_RSA(TPMT_PUBLIC *public,
}

static bool convert_pubkey_ECC(TPMT_PUBLIC *public,
tpm2_convert_pubkey_fmt format, FILE *fp) {
tpm2_convert_pubkey_fmt format, BIO *bio) {

BIGNUM *x = NULL;
BIGNUM *y = NULL;
Expand Down Expand Up @@ -209,10 +211,10 @@ static bool convert_pubkey_ECC(TPMT_PUBLIC *public,

switch (format) {
case pubkey_format_pem:
ssl_res = PEM_write_EC_PUBKEY(fp, key);
ssl_res = PEM_write_bio_EC_PUBKEY(bio, key);
break;
case pubkey_format_der:
ssl_res = i2d_EC_PUBKEY_fp(fp, key);
ssl_res = i2d_EC_PUBKEY_bio(bio, key);
break;
default:
LOG_ERR("Invalid OpenSSL target format %d encountered", format);
Expand Down Expand Up @@ -243,37 +245,42 @@ static bool convert_pubkey_ECC(TPMT_PUBLIC *public,
return result;
}

static bool tpm2_convert_pubkey_ssl(TPMT_PUBLIC *public,
tpm2_convert_pubkey_fmt format, const char *path) {
static bool tpm2_convert_pubkey_bio(TPMT_PUBLIC *public,
tpm2_convert_pubkey_fmt format, BIO *bio) {

bool result = false;

FILE *fp = fopen(path, "wb");
if (!fp) {
LOG_ERR("Failed to open public key output file '%s': %s", path,
strerror(errno));
goto out;
}

switch (public->type) {
case TPM2_ALG_RSA:
result = convert_pubkey_RSA(public, format, fp);
result = convert_pubkey_RSA(public, format, bio);
break;
case TPM2_ALG_ECC:
result = convert_pubkey_ECC(public, format, fp);
result = convert_pubkey_ECC(public, format, bio);
break;
default:
LOG_ERR(
"Unsupported key type for requested output format. Only RSA is supported.");
}

fclose(fp);

out:
ERR_free_strings();
return result;
}

static bool tpm2_convert_pubkey_ssl(TPMT_PUBLIC *public,
tpm2_convert_pubkey_fmt format, const char *path) {

BIO *bio = BIO_new_file(path, "wb");
if (!bio) {
LOG_ERR("Failed to open public key output file '%s': %s", path,
ERR_error_string(ERR_get_error(), NULL));
return false;
}

bool result = tpm2_convert_pubkey_bio(public, format, bio);
BIO_free(bio);
return result;
}

bool tpm2_convert_sig_save(TPMT_SIGNATURE *signature,
tpm2_convert_sig_fmt format, const char *path) {

Expand Down Expand Up @@ -560,3 +567,72 @@ UINT8 *tpm2_convert_sig(UINT16 *size, TPMT_SIGNATURE *signature) {
LOG_ERR("%s: couldn't allocate memory", __func__);
return NULL;
}

bool tpm2_public_load_pkey(const char *path, EVP_PKEY **pkey) {

bool result = false;

BIO *bio = NULL;
EVP_PKEY *p = NULL;

/*
* Order Matters. You must check for the smallest TSS size first, which
* it the TPMT_PUBLIC as it's embedded in the TPM2B_PUBLIC. It's possible
* to have valid TPMT's and have them parse as valid TPM2B_PUBLIC's (apparantly).
*
* If none of them convert, we try it as a plain signature.
*/
TPM2B_PUBLIC public = { 0 };
bool ret = files_load_template_silent(path, &public.publicArea);
if (ret) {
goto convert_to_pem;
}

ret = files_load_public_silent(path, &public);
if (ret) {
goto convert_to_pem;
}

/* not a tss format, just treat it as a pem file */
bio = BIO_new_file(path, "rb");
if (!bio) {
LOG_ERR("Failed to open public key output file '%s': %s", path,
ERR_error_string(ERR_get_error(), NULL));
return false;
}

/* not a tpm data structure, must be pem */
goto try_pem;

convert_to_pem:
bio = BIO_new(BIO_s_mem());
if (!bio) {
LOG_ERR("Failed to allocate memory bio: %s",
ERR_error_string(ERR_get_error(), NULL));
return false;
}

ret = tpm2_convert_pubkey_bio(&public.publicArea, pubkey_format_pem, bio);
if (!ret) {
goto out;
}

try_pem:
p = PEM_read_bio_PUBKEY(bio, NULL, NULL, NULL);
if (!p) {
LOG_ERR("Failed to convert public key from file '%s': %s", path,
ERR_error_string(ERR_get_error(), NULL));
goto out;
}

*pkey = p;

result = true;

out:
if (bio) {
BIO_free(bio);
}

return result;
}
4 changes: 4 additions & 0 deletions lib/tpm2_convert.h
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,8 @@

#include <stdbool.h>

#include <openssl/evp.h>

#include <tss2/tss2_sys.h>

typedef enum tpm2_convert_pubkey_fmt tpm2_convert_pubkey_fmt;
Expand Down Expand Up @@ -113,4 +115,6 @@ bool tpm2_convert_sig_load(const char *path, tpm2_convert_sig_fmt format,
bool tpm2_convert_sig_load_plain(const char *path,
TPM2B_MAX_BUFFER *signature, TPMI_ALG_HASH *halg);

bool tpm2_public_load_pkey(const char *path, EVP_PKEY **pkey);

#endif /* CONVERSION_H */
17 changes: 12 additions & 5 deletions man/tpm2_verifysignature.1.md
Original file line number Diff line number Diff line change
Expand Up @@ -46,12 +46,19 @@ symmetric key, both the public and private portions need to be loaded.

The input signature file of the signature to be validated.

* **-f**, **\--format**=_FORMAT_:
* **-f**, **\--scheme**=_SCHEME_:

Set the input signature file to a specified format. The default is the
tpm2.0 TPMT_SIGNATURE data format, however different schemes can be selected
if the data came from an external source like OpenSSL. The tool currently
only supports rsassa.
The signing scheme that was used to sign the message. This option should only
be specified if the signature comes in from a non *tss* standard, like openssl.
See "Signature format specifiers" for more details. The *tss* format contains
the signature metadata required to understand it's signature scheme.

Signing schemes should follow the "formatting standards", see section
"Algorithm Specifiers".

* **\--format**=_SCHEME_:

Deprecated. Same as **\--scheme**.

* **-t**, **\--ticket**=_FILE_:

Expand Down
14 changes: 12 additions & 2 deletions test/integration/tests/checkquote.sh
Original file line number Diff line number Diff line change
Expand Up @@ -65,12 +65,22 @@ tpm2_createek -G ecc -c ecc.ek

tpm2_createak -C ecc.ek -c ecc.ak -G ecc -g sha256 -s ecdsa

tpm2_readpublic -c ecc.ak -f pem -o ecc.ek.pem
tpm2_readpublic -c ecc.ak -f pem -o ecc.ak.pem

tpm2_getrandom -o nonce.bin 20

tpm2_quote -c ecc.ak -l sha256:15,16,22 -q nonce.bin -m quote.bin -s quote.sig -o quote.pcr -g sha256

tpm2_checkquote -u ecc.ek.pem -m quote.bin -s quote.sig -f quote.pcr -g sha256 -q nonce.bin
tpm2_checkquote -u ecc.ak.pem -m quote.bin -s quote.sig -f quote.pcr -g sha256 -q nonce.bin

# Verify that tss format works
tpm2_readpublic -c ecc.ak -f tss -o ecc.ak.tss

tpm2_checkquote -u ecc.ak.tss -m quote.bin -s quote.sig -f quote.pcr -g sha256 -q nonce.bin

# Verify the tpmt format works
tpm2_readpublic -c ecc.ak -f tpmt -o ecc.ak.tpmt

tpm2_checkquote -u ecc.ak.tpmt -m quote.bin -s quote.sig -f quote.pcr -g sha256 -q nonce.bin

exit 0
15 changes: 4 additions & 11 deletions tools/misc/tpm2_checkquote.c
Original file line number Diff line number Diff line change
Expand Up @@ -52,17 +52,13 @@ static bool verify(void) {

bool result = false;

// Read in the AKpub they provided as an RSA object
FILE *f = fopen(ctx.pubkey_file_path, "rb");
if (!f) {
LOG_ERR("Could not open RSA pubkey input file \"%s\" error: \"%s\"",
ctx.pubkey_file_path, strerror(errno));
/* read the public key */
EVP_PKEY *pkey = NULL;
bool ret = tpm2_public_load_pkey(ctx.pubkey_file_path, &pkey);
if (!ret) {
return false;
}

/* read the public key */
EVP_PKEY *pkey = PEM_read_PUBKEY(f, NULL, NULL, NULL);

EVP_PKEY_CTX *pkey_ctx = EVP_PKEY_CTX_new(pkey, NULL);
if (!pkey_ctx) {
LOG_ERR("EVP_PKEY_CTX_new failed: %s", ERR_error_string(ERR_get_error(), NULL));
Expand Down Expand Up @@ -125,9 +121,6 @@ static bool verify(void) {
result = true;

err:
if (f) {
fclose(f);
}

EVP_PKEY_free(pkey);
EVP_PKEY_CTX_free(pkey_ctx);
Expand Down
8 changes: 5 additions & 3 deletions tools/tpm2_verifysignature.c
Original file line number Diff line number Diff line change
Expand Up @@ -201,15 +201,16 @@ static bool on_option(char key, char *value) {
ctx.flags.digest = 1;
}
break;
case 'f': {
case 0:
/* Falls-Thru */
case 'f':
ctx.format = tpm2_alg_util_from_optarg(value, tpm2_alg_util_flags_sig);
if (ctx.format == TPM2_ALG_ERROR) {
LOG_ERR("Unknown signing scheme, got: \"%s\"", value);
return false;
}

ctx.flags.fmt = 1;
}
break;
case 's':
ctx.sig_file_path = value;
Expand All @@ -231,7 +232,8 @@ bool tpm2_tool_onstart(tpm2_options **opts) {
{ "digest", required_argument, NULL, 'd' },
{ "hash-algorithm", required_argument, NULL, 'g' },
{ "message", required_argument, NULL, 'm' },
{ "format", required_argument, NULL, 'f' },
{ "format", required_argument, NULL, '0' },
{ "scheme", required_argument, NULL, 'f' },
{ "signature", required_argument, NULL, 's' },
{ "ticket", required_argument, NULL, 't' },
{ "key-context", required_argument, NULL, 'c' },
Expand Down

0 comments on commit e275ba5

Please sign in to comment.