From ce7c160cdd174c4a14b6e9f1aed7bd5aee17b288 Mon Sep 17 00:00:00 2001 From: William Roberts Date: Wed, 8 Nov 2017 16:36:40 -0800 Subject: [PATCH] tpm2_rsaencrypt: support -I as an argument Make -I an argument and default to stdin. Update tpm2_create to use a common helper since both these tools have similair stdin logic. Drop unused routines from files.h Fixes: #508 Signed-off-by: William Roberts --- lib/files.c | 51 ++++++++++++++++++++++++----- lib/files.h | 33 ++++--------------- man/tpm2_rsaencrypt.1.md | 9 ++--- test/system/test_tpm2_rsadecrypt.sh | 2 +- test/system/test_tpm2_rsaencrypt.sh | 6 ++-- tools/tpm2_create.c | 41 ++--------------------- tools/tpm2_rsaencrypt.c | 37 +++++++++++---------- 7 files changed, 78 insertions(+), 101 deletions(-) diff --git a/lib/files.c b/lib/files.c index 6e96b2ad3..f77d81e9a 100644 --- a/lib/files.c +++ b/lib/files.c @@ -125,14 +125,6 @@ bool files_load_bytes_from_path(const char *path, UINT8 *buf, UINT16 *size) { return result; } -bool files_load_bytes_from_file(FILE *file, UINT8 *buf, UINT16 *size, const char *path) { - if (!buf || !size) { - return false; - } - - return read_bytes_from_file(file, buf, size, path); -} - bool files_save_bytes_to_file(const char *path, UINT8 *buf, UINT16 size) { if (!path || !buf) { @@ -533,3 +525,46 @@ bool files_read_header(FILE *out, uint32_t *version) { return files_read_32(out, version); } + +bool files_load_bytes_from_file_or_stdin(const char *path, UINT16 *size, BYTE *buf) { + + FILE *file = path ? fopen(path, "rb") : stdin; + path = file != stdin ? path : ""; + if (!file) { + LOG_ERR("Could not open file: \"%s\", error: %s", path, + strerror(errno)); + return false; + } + + /* + * Attempt to accurately read the file based on the file size. + * This may fail on stdin when it's a pipe. + */ + if (file == stdin) { + path = NULL; + } + + UINT16 original_size = *size; + bool res = files_load_bytes_from_path(path, buf, + size); + if (!res) { + res = true; + *size = fread(buf, 1, + *size, file); + if (!feof(file)) { + LOG_ERR("Data to be sealed larger than expected. Got %u expected %u", + original_size, res); + res = false; + } + else if (ferror(file)) { + LOG_ERR("Error reading sealed data from \"\""); + res = false; + } + } + + if (file != stdin) { + fclose(file); + } + + return res; +} diff --git a/lib/files.h b/lib/files.h index 096be42bb..82ff5c97f 100644 --- a/lib/files.h +++ b/lib/files.h @@ -54,36 +54,17 @@ bool files_load_bytes_from_path(const char *path, UINT8 *buf, UINT16 *size); /** - * Reads a series of bytes from a stdio FILE object. - * @param file - * The file to read from. - * @param buf - * The buffer to read into. - * @param size - * The size of the buffer to read into. + * Loads data from a file path or stdin enforcing an upper bound on size. * @param path - * An optional path for error reporting. A NULL path disables error logging. - * @return - * True on success, False otherwise. - */ -bool files_load_bytes_from_file(FILE *file, UINT8 *buf, UINT16 *size, const char *path); - -/** - * Reads a series of bytes from the standard input as a byte array. This is similar to - * files_read_bytes(), but it calculates the size to read for the caller. Size is both - * an input and output value where the size value is the max buffer size on call and - * the returned size is how much was read. - * - * @param buf - * The buffer to read the data into + * The path to load data from, NULL means stdin. * @param size - * The max size of the buffer on call, and the size of the data read on return. + * The maximum size. + * @param buf + * The buffer to write the data into. * @return - * True on success, false otherwise. + * True on success or false otherwise. */ -static inline bool files_load_bytes_from_stdin(UINT8 *buf, UINT16 *size) { - return files_load_bytes_from_file(stdin, buf, size, ""); -} +bool files_load_bytes_from_file_or_stdin(const char *path, UINT16 *size, BYTE *buf); /** * Similar to files_write_bytes(), in that it writes an array of bytes to disk, diff --git a/man/tpm2_rsaencrypt.1.md b/man/tpm2_rsaencrypt.1.md index 134fb96f8..e213180ab 100644 --- a/man/tpm2_rsaencrypt.1.md +++ b/man/tpm2_rsaencrypt.1.md @@ -8,11 +8,12 @@ # SYNOPSIS -**tpm2_rsaencrypt** [*OPTIONS*] +**tpm2_rsaencrypt** [*OPTIONS*] _FILE_ # DESCRIPTION -**tpm2_rsaencrypt**(1) performs RSA encryption using the indicated padding scheme according to +**tpm2_rsaencrypt**(1) performs RSA encryption on the contents of _FILE_ +(defaulting to stdin) using the indicated padding scheme according to IETF RFC 3447 (PKCS#1). The scheme of keyHandle should not be **TPM_ALG_NULL**. The key referenced by keyHandle is **required** to be: @@ -35,10 +36,6 @@ The key referenced by keyHandle is **required** to be: specifies the password of _KEY\_HANDLE_. Passwords should follow the password formatting standards, see section "Password Formatting". - * **-I**, **--in-file**=_INPUT\FILE_: - - Input file path, containing the data to be encrypted. - * **-o**, **--out-file**=_OUTPUT\_FILE_: Output file path, record the decrypted data. The default is to print an diff --git a/test/system/test_tpm2_rsadecrypt.sh b/test/system/test_tpm2_rsadecrypt.sh index 2a32c89be..b9643195f 100755 --- a/test/system/test_tpm2_rsadecrypt.sh +++ b/test/system/test_tpm2_rsadecrypt.sh @@ -71,7 +71,7 @@ tpm2_create -Q -g $alg_hash -G $alg_rsaencrypt_key -u $file_rsaencrypt_key_pub - tpm2_loadexternal -Q -H n -u $file_rsaencrypt_key_pub -C $file_rsaencrypt_key_ctx -tpm2_rsaencrypt -Q -c $file_rsaencrypt_key_ctx -I $file_input_data -o $file_rsa_en_output_data +tpm2_rsaencrypt -Q -c $file_rsaencrypt_key_ctx -o $file_rsa_en_output_data < $file_input_data tpm2_load -Q -c $file_primary_key_ctx -u $file_rsaencrypt_key_pub -r $file_rsaencrypt_key_priv -n $file_rsaencrypt_key_name -C $file_rsadecrypt_key_ctx diff --git a/test/system/test_tpm2_rsaencrypt.sh b/test/system/test_tpm2_rsaencrypt.sh index eea0042f0..b984a4d89 100755 --- a/test/system/test_tpm2_rsaencrypt.sh +++ b/test/system/test_tpm2_rsaencrypt.sh @@ -69,9 +69,9 @@ tpm2_create -Q -g $alg_hash -G $alg_rsaencrypt_key -u $file_rsaencrypt_key_pub - tpm2_loadexternal -Q -H n -u $file_rsaencrypt_key_pub -C $file_rsaencrypt_key_ctx #./tpm2_rsaencrypt -c context_loadexternal_out6.out -I secret.data -o rsa_en.out -tpm2_rsaencrypt -Q -c $file_rsaencrypt_key_ctx -I $file_input_data -o $file_rsa_en_output_data +tpm2_rsaencrypt -Q -c $file_rsaencrypt_key_ctx -o $file_rsa_en_output_data $file_input_data -# Test stdout for -o and ensure that output is xxd format -tpm2_rsaencrypt -c $file_rsaencrypt_key_ctx -I $file_input_data | xxd -r > /dev/null +# Test stdout for -o and ensure that output is xxd format, test that stdin pipe works as well. +cat $file_input_data | tpm2_rsaencrypt -c $file_rsaencrypt_key_ctx | xxd -r > /dev/null exit 0 diff --git a/tools/tpm2_create.c b/tools/tpm2_create.c index 9037bff0b..17148aa67 100644 --- a/tools/tpm2_create.c +++ b/tools/tpm2_create.c @@ -356,46 +356,9 @@ bool tpm2_tool_onstart(tpm2_options **opts) { static bool load_sensitive(void) { - bool is_stdin = !strcmp(ctx.input, "-"); - FILE *file = !is_stdin ? fopen(ctx.input, "rb") : stdin; - char *path = !is_stdin ? ctx.input : ""; - if (!file) { - LOG_ERR("Could not open file: \"%s\", error: %s", path, strerror(errno)); - return false; - } - - /* - * Attempt to accurately read the file based on the file size. - * This may fail on stdin when it's a pipe. - */ - if (is_stdin) { - path = NULL; - } - ctx.in_sensitive.t.sensitive.data.t.size = BUFFER_SIZE(typeof(ctx.in_sensitive.t.sensitive.data), buffer); - bool res = files_load_bytes_from_file(file, ctx.in_sensitive.t.sensitive.data.t.buffer, - &ctx.in_sensitive.t.sensitive.data.t.size, path); - - if (!res) { - res = true; - ctx.in_sensitive.t.sensitive.data.t.size = fread(ctx.in_sensitive.t.sensitive.data.t.buffer, 1, - ctx.in_sensitive.t.sensitive.data.t.size, file); - if (!feof(file)) { - LOG_ERR("Data to be sealed larger than expected. Got %u expected %u", - ctx.in_sensitive.t.sensitive.data.t.size, res); - res = false; - } - else if (ferror(file)) { - LOG_ERR("Error reading sealed data from \"\""); - res = false; - } - } - - if (!is_stdin) { - fclose(file); - } - - return res; + return files_load_bytes_from_file_or_stdin(ctx.input, + &ctx.in_sensitive.t.sensitive.data.t.size, ctx.in_sensitive.t.sensitive.data.t.buffer); } int tpm2_tool_onrun(TSS2_SYS_CONTEXT *sapi_context, tpm2_option_flags flags) { diff --git a/tools/tpm2_rsaencrypt.c b/tools/tpm2_rsaencrypt.c index 708d5b219..7f015bd24 100644 --- a/tools/tpm2_rsaencrypt.c +++ b/tools/tpm2_rsaencrypt.c @@ -46,14 +46,13 @@ typedef struct tpm_rsaencrypt_ctx tpm_rsaencrypt_ctx; struct tpm_rsaencrypt_ctx { struct { UINT8 k : 1; - UINT8 I : 1; UINT8 c : 1; - UINT8 unused : 5; } flags; char *context_key_file; TPMI_DH_OBJECT key_handle; TPM2B_PUBLIC_KEY_RSA message; char *output_path; + char *input_path; }; static tpm_rsaencrypt_ctx ctx; @@ -107,16 +106,6 @@ static bool on_option(char key, char *value) { ctx.flags.k = 1; } break; - case 'I': { - ctx.message.t.size = BUFFER_SIZE(TPM2B_PUBLIC_KEY_RSA, buffer); - bool result = files_load_bytes_from_path(value, ctx.message.t.buffer, - &ctx.message.t.size); - if (!result) { - return false; - } - ctx.flags.I = 1; - } - break; case 'o': { ctx.output_path = value; } @@ -131,25 +120,36 @@ static bool on_option(char key, char *value) { return true; } +static bool on_args(int argc, char **argv) { + + if (argc > 1) { + LOG_ERR("Only supports one hash input file, got: %d", argc); + return false; + } + + ctx.input_path = argv[1]; + + return true; +} + bool tpm2_tool_onstart(tpm2_options **opts) { static const struct option topts[] = { {"key-handle", required_argument, NULL, 'k'}, - {"in-file", required_argument, NULL, 'I'}, {"out-file", required_argument, NULL, 'o'}, {"key-context", required_argument, NULL, 'c'}, }; - *opts = tpm2_options_new("k:I:o:c:", ARRAY_LEN(topts), topts, - on_option, NULL); + *opts = tpm2_options_new("k:o:c:", ARRAY_LEN(topts), topts, + on_option, on_args); return *opts != NULL; } static bool init(TSS2_SYS_CONTEXT *sapi_context) { - if (!((ctx.flags.k || ctx.flags.c) && ctx.flags.I)) { - LOG_ERR("Expected options I and (k or c)"); + if (!(ctx.flags.k || ctx.flags.c)) { + LOG_ERR("Expected options k or c"); return false; } @@ -161,7 +161,8 @@ static bool init(TSS2_SYS_CONTEXT *sapi_context) { } } - return true; + ctx.message.t.size = BUFFER_SIZE(TPM2B_PUBLIC_KEY_RSA, buffer); + return files_load_bytes_from_file_or_stdin(ctx.input_path, &ctx.message.t.size, ctx.message.t.buffer); } int tpm2_tool_onrun(TSS2_SYS_CONTEXT *sapi_context, tpm2_option_flags flags) {