代码拉取完成,页面将自动刷新
From 63cb698013ea79f324af4aec69574424274be716 Mon Sep 17 00:00:00 2001
From: mayuanchen <[email protected]>
Date: Tue, 9 May 2023 20:35:00 -0400
Subject: [PATCH 1/4] newfeature: tpm: add ecc encrypt/decrypt commands
support.
Change-Id: I5efa3311728bfc981206faffe2bd2a5eae7b456c
---
Makefile.am | 2 +
.../tpm2-tools/tpm2_completion.bash | 103 ++++-
lib/tpm2.c | 76 ++++
lib/tpm2.h | 11 +
lib/tpm2_alg_util.c | 42 +++
lib/tpm2_alg_util.h | 12 +
tools/tpm2_eccdecrypt.c | 354 ++++++++++++++++++
tools/tpm2_eccencrypt.c | 200 ++++++++++
8 files changed, 799 insertions(+), 1 deletion(-)
create mode 100644 tools/tpm2_eccdecrypt.c
create mode 100644 tools/tpm2_eccencrypt.c
diff --git a/Makefile.am b/Makefile.am
index 5e53f62..3c81ff3 100644
--- a/Makefile.am
+++ b/Makefile.am
@@ -126,6 +126,8 @@ tpm2_tools = \
tools/tpm2_duplicate.c \
tools/tpm2_getcap.c \
tools/tpm2_gettestresult.c \
+ tools/tpm2_eccdecrypt.c \
+ tools/tpm2_eccencrypt.c \
tools/tpm2_encryptdecrypt.c \
tools/tpm2_evictcontrol.c \
tools/tpm2_flushcontext.c \
diff --git a/dist/bash-completion/tpm2-tools/tpm2_completion.bash b/dist/bash-completion/tpm2-tools/tpm2_completion.bash
index 3bbe814..b87d98d 100644
--- a/dist/bash-completion/tpm2-tools/tpm2_completion.bash
+++ b/dist/bash-completion/tpm2-tools/tpm2_completion.bash
@@ -1100,6 +1100,107 @@ _tpm2_duplicate()
} &&
complete -F _tpm2_duplicate tpm2_duplicate
# ex: filetype=sh
+# bash completion for tpm2_eccdecrypt -*- shell-script -*-
+_tpm2_eccdecrypt()
+ {
+ local auth_methods=(str: hex: file: file:- session: pcr:)
+
+ local hash_methods=(sha1 sha256 sha384 sha512)
+
+ local format_methods=(tss plain)
+
+ local signing_scheme=(rsassa rsapss ecdsa ecdaa sm2 ecshnorr hmac)
+
+ local key_object=(rsa ecc aes camellia hmac xor keyedhash)
+
+ local key_attributes=(\| fixedtpm stclear fixedparent \
+ sensitivedataorigin userwithauth adminwithpolicy noda \
+ encrypteddupplication restricted decrypt sign)
+
+ local nv_attributes=(\| ppwrite ownerwrite authwrite policywrite \
+ policydelete writelocked writeall writedefine write_stclear \
+ globallock ppread ownerread authread policyread no_da orderly \
+ clear_stclear readlocked written platformcreate read_stclear)
+
+ local cur prev words cword split
+ _init_completion -s || return
+ case $prev in
+ -h | --help)
+ COMPREPLY=( $(compgen -W "man no-man" -- "$cur") )
+ return;;
+ -T | --tcti)
+ COMPREPLY=( $(compgen -W "tabrmd mssim device none" -- "$cur") )
+ return;;
+ -c | --key-context)
+ _filedir
+ return;;
+ -p | --auth)
+ COMPREPLY=($(compgen -W "${auth_methods[*]}" -- "$cur"))
+ return;;
+ -o | --output)
+ _filedir
+ return;;
+ -s | --scheme)
+ COMPREPLY=($(compgen -W "${signing_scheme[*]}" -- "$cur"))
+ return;;
+ esac
+
+ COMPREPLY=($(compgen -W "-h --help -v --version -V --verbose -Q --quiet \
+ -Z --enable-erata -T --tcti \
+ -c -p -o -s --key-context --auth --output --scheme --shared-data1 --shared-data2 --cphash " \
+ -- "$cur"))
+ } &&
+ complete -F _tpm2_eccdecrypt tpm2_eccdecrypt
+# ex: filetype=sh
+# bash completion for tpm2_eccencrypt -*- shell-script -*-
+_tpm2_eccencrypt()
+ {
+ local auth_methods=(str: hex: file: file:- session: pcr:)
+
+ local hash_methods=(sha1 sha256 sha384 sha512)
+
+ local format_methods=(tss plain)
+
+ local signing_scheme=(rsassa rsapss ecdsa ecdaa sm2 ecshnorr hmac)
+
+ local key_object=(rsa ecc aes camellia hmac xor keyedhash)
+
+ local key_attributes=(\| fixedtpm stclear fixedparent \
+ sensitivedataorigin userwithauth adminwithpolicy noda \
+ encrypteddupplication restricted decrypt sign)
+
+ local nv_attributes=(\| ppwrite ownerwrite authwrite policywrite \
+ policydelete writelocked writeall writedefine write_stclear \
+ globallock ppread ownerread authread policyread no_da orderly \
+ clear_stclear readlocked written platformcreate read_stclear)
+
+ local cur prev words cword split
+ _init_completion -s || return
+ case $prev in
+ -h | --help)
+ COMPREPLY=( $(compgen -W "man no-man" -- "$cur") )
+ return;;
+ -T | --tcti)
+ COMPREPLY=( $(compgen -W "tabrmd mssim device none" -- "$cur") )
+ return;;
+ -c | --key-context)
+ _filedir
+ return;;
+ -o | --output)
+ _filedir
+ return;;
+ -s | --scheme)
+ COMPREPLY=($(compgen -W "${signing_scheme[*]}" -- "$cur"))
+ return;;
+ esac
+
+ COMPREPLY=($(compgen -W "-h --help -v --version -V --verbose -Q --quiet \
+ -Z --enable-erata -T --tcti \
+ -c -o -s --key-context --output --scheme --shared-data1 --shared-data2" \
+ -- "$cur"))
+ } &&
+ complete -F _tpm2_eccencrypt tpm2_eccencrypt
+# ex: filetype=sh
# bash completion for tpm2_ecdhkeygen -*- shell-script -*-
_tpm2_ecdhkeygen()
{
@@ -5092,7 +5193,7 @@ _tpm2() {
_init_completion -s || return
if ((cword == 1)); then
- COMPREPLY=($(compgen -W "activatecredential certify certifyX509certutil certifycreation changeauth changeeps changepps checkquote clear clearcontrol clockrateadjust commit create createak createek createpolicy createprimary dictionarylockout duplicate ecdhkeygen ecdhzgen ecephemeral encryptdecrypt eventlog evictcontrol flushcontext getcap getcommandauditdigest geteccparameters getekcertificate getrandom getsessionauditdigest gettestresult gettime hash hierarchycontrol hmac import incrementalselftest load loadexternal makecredential nvcertify nvdefine nvextend nvincrement nvread nvreadlock nvreadpublic nvsetbits nvundefine nvwrite nvwritelock pcrallocate pcrevent pcrextend pcrread pcrreset policyauthorize policyauthorizenv policyauthvalue policycommandcode policycountertimer policycphash policyduplicationselect policylocality policynamehash policynv policynvwritten policyor policypassword policypcr policyrestart policysecret policysigned policytemplate policyticket print quote rc_decode readclock readpublic rsadecrypt rsaencrypt selftest send setclock setcommandauditstatus setprimarypolicy shutdown sign startauthsession startup stirrandom testparms unseal verifysignature zgen2phase " -- "$cur"))
+ COMPREPLY=($(compgen -W "activatecredential certify certifyX509certutil certifycreation changeauth changeeps changepps checkquote clear clearcontrol clockrateadjust commit create createak createek createpolicy createprimary dictionarylockout duplicate eccdecrypt eccencrypt ecdhkeygen ecdhzgen ecephemeral encryptdecrypt eventlog evictcontrol flushcontext getcap getcommandauditdigest geteccparameters getekcertificate getrandom getsessionauditdigest gettestresult gettime hash hierarchycontrol hmac import incrementalselftest load loadexternal makecredential nvcertify nvdefine nvextend nvincrement nvread nvreadlock nvreadpublic nvsetbits nvundefine nvwrite nvwritelock pcrallocate pcrevent pcrextend pcrread pcrreset policyauthorize policyauthorizenv policyauthvalue policycommandcode policycountertimer policycphash policyduplicationselect policylocality policynamehash policynv policynvwritten policyor policypassword policypcr policyrestart policysecret policysigned policytemplate policyticket print quote rc_decode readclock readpublic rsadecrypt rsaencrypt selftest send setclock setcommandauditstatus setprimarypolicy shutdown sign startauthsession startup stirrandom testparms unseal verifysignature zgen2phase " -- "$cur"))
else
tpmcommand=_tpm2_$prev
type $tpmcommand &>/dev/null && $tpmcommand
diff --git a/lib/tpm2.c b/lib/tpm2.c
index 93b2322..14de540 100644
--- a/lib/tpm2.c
+++ b/lib/tpm2.c
@@ -2484,6 +2484,82 @@ tool_rc tpm2_rsa_encrypt(ESYS_CONTEXT *ectx, tpm2_loaded_object *keyobj,
return tool_rc_success;
}
+tool_rc tpm2_ecc_decrypt(ESYS_CONTEXT *ectx, tpm2_loaded_object *keyobj,
+ const TPM2B_MAX_BUFFER *cipher_text, const TPMT_ECC_DECRYPT *in_scheme,
+ const TPM2B_DATA *shared_data1, const TPM2B_DATA *shared_data2,
+ TPM2B_MAX_BUFFER **message, TPM2B_DIGEST *cp_hash,
+ TPMI_ALG_HASH parameter_hash_algorithm) {
+
+ ESYS_TR keyobj_session_handle = ESYS_TR_NONE;
+ tool_rc rc = tpm2_auth_util_get_shandle(ectx, keyobj->tr_handle,
+ keyobj->session, &keyobj_session_handle);
+ if (rc != tool_rc_success) {
+ return rc;
+ }
+
+ if (cp_hash && cp_hash->size) {
+ /*
+ * Need sys_context to be able to calculate CpHash
+ */
+ TSS2_SYS_CONTEXT *sys_context = 0;
+ rc = tpm2_getsapicontext(ectx, &sys_context);
+ if(rc != tool_rc_success) {
+ LOG_ERR("Failed to acquire SAPI context.");
+ return rc;
+ }
+
+ TSS2_RC rval = Tss2_Sys_ECC_Decrypt_Prepare(sys_context, keyobj->handle,
+ in_scheme, cipher_text, shared_data1, shared_data2);
+ if (rval != TPM2_RC_SUCCESS) {
+ LOG_PERR(Tss2_Sys_ECC_Decrypt_Prepare, rval);
+ return tool_rc_general_error;
+ }
+
+ TPM2B_NAME *name1 = 0;
+ rc = tpm2_tr_get_name(ectx, keyobj->tr_handle, &name1);
+ if (rc != tool_rc_success) {
+ goto tpm2_eccdecrypt_free_name1;
+ }
+
+ rc = tpm2_sapi_getcphash(sys_context, name1, 0, 0,
+ parameter_hash_algorithm, cp_hash);
+
+ /*
+ * Exit here without making the ESYS call since we just need the cpHash
+ */
+tpm2_eccdecrypt_free_name1:
+ Esys_Free(name1);
+ goto tpm2_eccdecrypt_skip_esapi_call;
+ }
+
+ TSS2_RC rval = Esys_ECC_Decrypt(ectx, keyobj->tr_handle,
+ keyobj_session_handle, ESYS_TR_NONE, ESYS_TR_NONE, in_scheme,
+ cipher_text, shared_data1, shared_data2, message);
+ if (rval != TPM2_RC_SUCCESS) {
+ LOG_PERR(Esys_ECC_Decrypt, rval);
+ return tool_rc_from_tpm(rval);
+ }
+
+tpm2_eccdecrypt_skip_esapi_call:
+ return rc;
+}
+
+tool_rc tpm2_ecc_encrypt(ESYS_CONTEXT *ectx, tpm2_loaded_object *keyobj,
+ const TPM2B_MAX_BUFFER *message, const TPMT_ECC_DECRYPT *scheme,
+ const TPM2B_DATA *shared_data1, const TPM2B_DATA *shared_data2,
+ TPM2B_MAX_BUFFER **cipher_text) {
+
+ TSS2_RC rval = Esys_ECC_Encrypt(ectx, keyobj->tr_handle,
+ ESYS_TR_NONE, ESYS_TR_NONE, ESYS_TR_NONE, scheme, message,
+ shared_data1, shared_data2, cipher_text);
+ if (rval != TPM2_RC_SUCCESS) {
+ LOG_PERR(Esys_ECC_Encrypt, rval);
+ return tool_rc_from_tpm(rval);
+ }
+
+ return tool_rc_success;
+}
+
tool_rc tpm2_load(ESYS_CONTEXT *esys_context, tpm2_loaded_object *parentobj,
const TPM2B_PRIVATE *in_private, const TPM2B_PUBLIC *in_public,
ESYS_TR *object_handle, TPM2B_DIGEST *cp_hash,
diff --git a/lib/tpm2.h b/lib/tpm2.h
index 52a8956..9aed2a7 100644
--- a/lib/tpm2.h
+++ b/lib/tpm2.h
@@ -252,6 +252,17 @@ tool_rc tpm2_rsa_encrypt(ESYS_CONTEXT *ectx, tpm2_loaded_object *keyobj,
const TPM2B_PUBLIC_KEY_RSA *message, const TPMT_RSA_DECRYPT *scheme,
const TPM2B_DATA *label, TPM2B_PUBLIC_KEY_RSA **cipher_text);
+tool_rc tpm2_ecc_decrypt(ESYS_CONTEXT *ectx, tpm2_loaded_object *keyobj,
+ const TPM2B_MAX_BUFFER *cipher_text, const TPMT_ECC_DECRYPT *in_scheme,
+ const TPM2B_DATA *shared_data1, const TPM2B_DATA *shared_data2,
+ TPM2B_MAX_BUFFER **message, TPM2B_DIGEST *cp_hash,
+ TPMI_ALG_HASH parameter_hash_algorithm);
+
+tool_rc tpm2_ecc_encrypt(ESYS_CONTEXT *ectx, tpm2_loaded_object *keyobj,
+ const TPM2B_MAX_BUFFER *message, const TPMT_ECC_DECRYPT *scheme,
+ const TPM2B_DATA *shared_data1, const TPM2B_DATA *shared_data2,
+ TPM2B_MAX_BUFFER **cipher_text);
+
tool_rc tpm2_load(ESYS_CONTEXT *esys_context, tpm2_loaded_object *parentobj,
const TPM2B_PRIVATE *in_private, const TPM2B_PUBLIC *in_public,
ESYS_TR *object_handle, TPM2B_DIGEST *cp_hash,
diff --git a/lib/tpm2_alg_util.c b/lib/tpm2_alg_util.c
index 65739fc..19fdf25 100644
--- a/lib/tpm2_alg_util.c
+++ b/lib/tpm2_alg_util.c
@@ -660,6 +660,48 @@ tool_rc tpm2_alg_util_handle_rsa_ext_alg(const char *alg_spec,
return result ? tool_rc_success : tool_rc_general_error;
}
+tool_rc tpm2_alg_util_handle_ecc_ext_alg(const char *alg_spec,
+ TPM2B_PUBLIC *public) {
+
+ char *ext_alg_str = calloc(1, strlen(alg_spec) + strlen("ecc") +
+ strlen("_nist_p256:") + 1);
+ if (ext_alg_str == NULL) {
+ LOG_ERR("oom");
+ return tool_rc_general_error;
+ }
+
+ strcat(ext_alg_str, "ecc");
+ switch(public->publicArea.parameters.eccDetail.curveID) {
+ case TPM2_ECC_NIST_P192:
+ strcat(ext_alg_str, "_nist_p192:");
+ break;
+ case TPM2_ECC_NIST_P224:
+ strcat(ext_alg_str, "_nist_p224:");
+ break;
+ case TPM2_ECC_NIST_P256:
+ strcat(ext_alg_str, "_nist_p256:");
+ break;
+ case TPM2_ECC_NIST_P384:
+ strcat(ext_alg_str, "_nist_p384:");
+ break;
+ case TPM2_ECC_NIST_P521:
+ strcat(ext_alg_str, "_nist_p521:");
+ break;
+ case TPM2_ECC_SM2_P256:
+ strcat(ext_alg_str, "_sm2:");
+ break;
+ default:
+ strcat(ext_alg_str, "_nist_p256:");
+ break;
+ };
+ strcat(ext_alg_str, alg_spec);
+
+ bool result = tpm2_alg_util_handle_ext_alg(ext_alg_str, public);
+ free(ext_alg_str);
+
+ return result ? tool_rc_success : tool_rc_general_error;
+}
+
static alg_iter_res find_match(TPM2_ALG_ID id, const char *name,
tpm2_alg_util_flags flags, void *userdata) {
diff --git a/lib/tpm2_alg_util.h b/lib/tpm2_alg_util.h
index ae5e3fb..a9cff56 100644
--- a/lib/tpm2_alg_util.h
+++ b/lib/tpm2_alg_util.h
@@ -184,6 +184,18 @@ bool tpm2_alg_util_handle_ext_alg(const char *alg_spec, TPM2B_PUBLIC *public);
tool_rc tpm2_alg_util_handle_rsa_ext_alg(const char *alg_spec,
TPM2B_PUBLIC *public);
+/**
+ * Retrieves the scheme information for an ECC key to be used in
+ * TPM2_CC_ECC_Encrypt or TPM2_CC_ECC_Decrypt
+ * @param alg_spec
+ * Friendly specification of the ECC scheme (sm2-sm3_256)
+ * @param public
+ * Public structure which will contain relevant information about
+ * specified algorithm
+ */
+tool_rc tpm2_alg_util_handle_ecc_ext_alg(const char *alg_spec,
+ TPM2B_PUBLIC *public);
+
/**
*
* @param alg_details
diff --git a/tools/tpm2_eccdecrypt.c b/tools/tpm2_eccdecrypt.c
new file mode 100644
index 0000000..d6ee2d4
--- /dev/null
+++ b/tools/tpm2_eccdecrypt.c
@@ -0,0 +1,354 @@
+/* SPDX-License-Identifier: BSD-3-Clause */
+
+#include <stdlib.h>
+
+#include "files.h"
+#include "log.h"
+#include "tpm2.h"
+#include "tpm2_tool.h"
+#include "tpm2_alg_util.h"
+#include "tpm2_options.h"
+
+#define MAX_SESSIONS 3
+typedef struct tpm_eccdecrypt_ctx tpm_eccdecrypt_ctx;
+struct tpm_eccdecrypt_ctx {
+ /*
+ * Inputs
+ */
+ struct {
+ const char *ctx_path;
+ const char *auth_str;
+ tpm2_loaded_object object;
+ } key;
+
+ TPM2B_DATA shared_data1;
+ TPM2B_DATA shared_data2;
+ char *data1_path;
+ char *data2_path;
+ TPM2B_MAX_BUFFER cipher_text;
+ char *input_path;
+
+ TPMT_ECC_DECRYPT scheme;
+ const char *scheme_str;
+
+ /*
+ * Outputs
+ */
+ char *output_file_path;
+ TPM2B_MAX_BUFFER *message;
+ FILE *foutput;
+
+ /*
+ * Parameter hashes
+ */
+ const char *cp_hash_path;
+ TPM2B_DIGEST cp_hash;
+ bool is_command_dispatch;
+ TPMI_ALG_HASH parameter_hash_algorithm;
+};
+
+static tpm_eccdecrypt_ctx ctx = {
+ .scheme = {
+ .scheme = TPM2_ALG_SM2,
+ .details = {
+ .anySig = {.hashAlg = TPM2_ALG_SM3_256}
+ }
+ },
+ .parameter_hash_algorithm = TPM2_ALG_ERROR,
+};
+
+static tool_rc ecc_decrypt(ESYS_CONTEXT *ectx) {
+
+ return tpm2_ecc_decrypt(ectx, &ctx.key.object, &ctx.cipher_text,
+ &ctx.scheme, &ctx.shared_data1, &ctx.shared_data2, &ctx.message,
+ &ctx.cp_hash, ctx.parameter_hash_algorithm);
+}
+
+static tool_rc process_output(ESYS_CONTEXT *ectx) {
+
+ UNUSED(ectx);
+ /*
+ * 1. Outputs that do not require TPM2_CC_<command> dispatch
+ */
+ bool is_file_op_success = true;
+ if (ctx.cp_hash_path) {
+ is_file_op_success = files_save_digest(&ctx.cp_hash, ctx.cp_hash_path);
+
+ if (!is_file_op_success) {
+ return tool_rc_general_error;
+ }
+ }
+
+ tool_rc rc = tool_rc_success;
+ if (!ctx.is_command_dispatch) {
+ return rc;
+ }
+
+ /*
+ * 2. Outputs generated after TPM2_CC_<command> dispatch
+ */
+ is_file_op_success = files_write_bytes(ctx.foutput, ctx.message->buffer,
+ ctx.message->size);
+ if (ctx.foutput != stdout) {
+ fclose(ctx.foutput);
+ }
+
+ return is_file_op_success ? tool_rc_success : tool_rc_general_error;
+}
+
+static tool_rc process_inputs(ESYS_CONTEXT *ectx) {
+
+ UNUSED(ectx);
+ /*
+ * 1. Object and auth initializations
+ */
+
+ /*
+ * 1.a Add the new-auth values to be set for the object.
+ */
+
+ /*
+ * 1.b Add object names and their auth sessions
+ */
+ tool_rc rc = tpm2_util_object_load_auth(ectx, ctx.key.ctx_path,
+ ctx.key.auth_str, &ctx.key.object, false,
+ TPM2_HANDLES_FLAGS_TRANSIENT|TPM2_HANDLES_FLAGS_PERSISTENT);
+ if (rc != tool_rc_success) {
+ return rc;
+ }
+
+ /*
+ * 2. Restore auxiliary sessions
+ */
+
+ /*
+ * 3. Command specific initializations
+ */
+
+ ctx.foutput = ctx.output_file_path ?
+ fopen(ctx.output_file_path, "wb+") : stdout;
+ if (!ctx.foutput) {
+ return tool_rc_general_error;
+ }
+
+ TPM2B_PUBLIC *key_public_info = 0;
+ rc = tpm2_readpublic(ectx, ctx.key.object.tr_handle, &key_public_info,
+ 0, 0);
+ if (rc != tool_rc_success) {
+ goto out;
+ }
+
+ if (key_public_info->publicArea.type != TPM2_ALG_ECC) {
+ LOG_ERR("Unsupported key type for ECC decryption.");
+ rc = tool_rc_general_error;
+ goto out;
+ }
+
+ /*
+ * Get scheme information
+ */
+ if (ctx.scheme_str) {
+ rc = tpm2_alg_util_handle_ecc_ext_alg(ctx.scheme_str, key_public_info);
+ ctx.scheme.scheme =
+ key_public_info->publicArea.parameters.eccDetail.scheme.scheme;
+ ctx.scheme.details.anySig.hashAlg =
+ key_public_info->publicArea.parameters.eccDetail.scheme.details.anySig.hashAlg;
+
+ if (rc != tool_rc_success) {
+ goto out;
+ }
+ }
+
+ /*
+ * Get enc data blob
+ */
+ ctx.cipher_text.size = BUFFER_SIZE(TPM2B_MAX_BUFFER, buffer);
+ bool result = files_load_bytes_from_buffer_or_file_or_stdin(0,
+ ctx.input_path, &ctx.cipher_text.size, ctx.cipher_text.buffer);
+ if (!result) {
+ rc = tool_rc_general_error;
+ }
+
+ /*
+ * Get shared data blob
+ */
+ if (ctx.data1_path) {
+ ctx.shared_data1.size = BUFFER_SIZE(TPM2B_DATA, buffer);
+ bool ret = files_load_bytes_from_buffer_or_file_or_stdin(0,
+ ctx.data1_path, &ctx.shared_data1.size, ctx.shared_data1.buffer);
+ if (!ret) {
+ rc = tool_rc_general_error;
+ }
+ }
+
+ if (ctx.data2_path) {
+ ctx.shared_data2.size = BUFFER_SIZE(TPM2B_DATA, buffer);
+ bool ret = files_load_bytes_from_buffer_or_file_or_stdin(0,
+ ctx.data2_path, &ctx.shared_data2.size, ctx.shared_data2.buffer);
+ if (!ret) {
+ rc = tool_rc_general_error;
+ }
+ }
+
+ /*
+ * 4. Configuration for calculating the pHash
+ */
+
+ /*
+ * 4.a Determine pHash length and alg
+ */
+ tpm2_session *all_sessions[MAX_SESSIONS] = {
+ ctx.key.object.session,
+ 0,
+ 0
+ };
+
+ const char **cphash_path = ctx.cp_hash_path ? &ctx.cp_hash_path : 0;
+
+ ctx.parameter_hash_algorithm = tpm2_util_calculate_phash_algorithm(ectx,
+ cphash_path, &ctx.cp_hash, 0, 0, all_sessions);
+
+ /*
+ * 4.b Determine if TPM2_CC_<command> is to be dispatched
+ */
+ ctx.is_command_dispatch = ctx.cp_hash_path ? false : true;
+
+out:
+ Esys_Free(key_public_info);
+ return rc;
+}
+
+static tool_rc check_options(ESYS_CONTEXT *ectx) {
+
+ UNUSED(ectx);
+
+ if (!ctx.key.ctx_path) {
+ LOG_ERR("Expected argument -c.");
+ return tool_rc_option_error;
+ }
+
+ if (ctx.output_file_path && ctx.cp_hash_path) {
+ LOG_ERR("Cannout decrypt when calculating cphash");
+ return tool_rc_option_error;
+ }
+
+ return tool_rc_success;
+}
+
+static bool on_option(char key, char *value) {
+
+ switch (key) {
+ case 'c':
+ ctx.key.ctx_path = value;
+ break;
+ case 'p':
+ ctx.key.auth_str = value;
+ break;
+ case 'o': {
+ ctx.output_file_path = value;
+ break;
+ }
+ case 's':
+ ctx.scheme_str = value;
+ break;
+ case 0:
+ ctx.cp_hash_path = value;
+ break;
+ case 1:
+ ctx.data1_path = value;
+ break;
+ case 2:
+ ctx.data2_path = value;
+ break;
+ }
+ return true;
+}
+
+static bool on_args(int argc, char **argv) {
+
+ if (argc > 1) {
+ LOG_ERR("Only supports one input file, got: %d", argc);
+ return false;
+ }
+
+ ctx.input_path = argv[0];
+
+ return true;
+}
+
+static bool tpm2_tool_onstart(tpm2_options **opts) {
+
+ static struct option topts[] = {
+ { "auth", required_argument, 0, 'p' },
+ { "output", required_argument, 0, 'o' },
+ { "key-context", required_argument, 0, 'c' },
+ { "scheme", required_argument, 0, 's' },
+ { "cphash", required_argument, 0, 0 },
+ { "shared-data1",required_argument, 0, 1 },
+ { "shared-data2",required_argument, 0, 2 },
+ };
+
+ *opts = tpm2_options_new("p:o:c:s:", ARRAY_LEN(topts), topts, on_option,
+ on_args, 0);
+
+ return *opts != 0;
+}
+
+static tool_rc tpm2_tool_onrun(ESYS_CONTEXT *ectx, tpm2_option_flags flags) {
+
+ UNUSED(flags);
+
+ /*
+ * 1. Process options
+ */
+ tool_rc rc = check_options(ectx);
+ if (rc != tool_rc_success) {
+ return rc;
+ }
+
+ /*
+ * 2. Process inputs
+ */
+ rc = process_inputs(ectx);
+ if (rc != tool_rc_success) {
+ return rc;
+ }
+
+ /*
+ * 3. TPM2_CC_<command> call
+ */
+ rc = ecc_decrypt(ectx);
+ if (rc != tool_rc_success) {
+ return rc;
+ }
+
+ /*
+ * 4. Process outputs
+ */
+ return process_output(ectx);
+}
+
+static tool_rc tpm2_tool_onstop(ESYS_CONTEXT *ectx) {
+
+ UNUSED(ectx);
+
+ /*
+ * 1. Free objects
+ */
+ free(ctx.message);
+
+ /*
+ * 2. Close authorization sessions
+ */
+ tool_rc rc = tpm2_session_close(&ctx.key.object.session);
+
+ /*
+ * 3. Close auxiliary sessions
+ */
+
+ return rc;
+}
+
+// Register this tool with tpm2_tool.c
+TPM2_TOOL_REGISTER("eccdecrypt", tpm2_tool_onstart, tpm2_tool_onrun,
+ tpm2_tool_onstop, 0)
diff --git a/tools/tpm2_eccencrypt.c b/tools/tpm2_eccencrypt.c
new file mode 100644
index 0000000..d7fd022
--- /dev/null
+++ b/tools/tpm2_eccencrypt.c
@@ -0,0 +1,200 @@
+/* SPDX-License-Identifier: BSD-3-Clause */
+
+#include <stdbool.h>
+#include <stdlib.h>
+
+#include "files.h"
+#include "log.h"
+#include "object.h"
+#include "tpm2.h"
+#include "tpm2_tool.h"
+#include "tpm2_alg_util.h"
+#include "tpm2_options.h"
+
+typedef struct tpm_eccencrypt_ctx tpm_eccencrypt_ctx;
+struct tpm_eccencrypt_ctx {
+ const char *context_arg;
+ tpm2_loaded_object key_context;
+ TPM2B_MAX_BUFFER message;
+ char *output_path;
+ char *input_path;
+ TPMT_ECC_DECRYPT scheme;
+ const char *scheme_str;
+ TPM2B_DATA shared_data1;
+ TPM2B_DATA shared_data2;
+ char *data1_path;
+ char *data2_path;
+};
+
+static tpm_eccencrypt_ctx ctx = {
+ .context_arg = NULL,
+ .scheme = {
+ .scheme = TPM2_ALG_SM2,
+ .details = {
+ .anySig = {.hashAlg = TPM2_ALG_SM3_256}
+ }
+ }
+};
+
+static tool_rc ecc_encrypt_and_save(ESYS_CONTEXT *context) {
+
+ bool ret = false;
+ TPM2B_MAX_BUFFER *out_data = NULL;
+
+ tool_rc rc = tpm2_ecc_encrypt(context, &ctx.key_context,
+ &ctx.message, &ctx.scheme, &ctx.shared_data1,
+ &ctx.shared_data2, &out_data);
+ if (rc != tool_rc_success) {
+ return rc;
+ }
+
+ FILE *f = ctx.output_path ? fopen(ctx.output_path, "wb+") : stdout;
+ if (!f) {
+ goto out;
+ }
+
+ ret = files_write_bytes(f, out_data->buffer, out_data->size);
+ if (f != stdout) {
+ fclose(f);
+ }
+
+out:
+ free(out_data);
+ return ret ? tool_rc_success : tool_rc_general_error;
+}
+
+static bool on_option(char key, char *value) {
+
+ switch (key) {
+ case 'c':
+ ctx.context_arg = value;
+ break;
+ case 'o':
+ ctx.output_path = value;
+ break;
+ case 's':
+ ctx.scheme_str = value;
+ break;
+ case 1:
+ ctx.data1_path = value;
+ break;
+ case 2:
+ ctx.data2_path = value;
+ break;
+ }
+ return true;
+}
+
+static bool on_args(int argc, char **argv) {
+
+ if (argc > 1) {
+ LOG_ERR("Only supports one input file, got: %d", argc);
+ return false;
+ }
+
+ ctx.input_path = argv[0];
+
+ return true;
+}
+
+static bool tpm2_tool_onstart(tpm2_options **opts) {
+
+ static const struct option topts[] = {
+ {"output", required_argument, NULL, 'o'},
+ {"key-context", required_argument, NULL, 'c'},
+ {"scheme", required_argument, NULL, 's'},
+ {"shared-data1",required_argument, NULL, 1 },
+ {"shared-data2",required_argument, NULL, 2 },
+ };
+
+ *opts = tpm2_options_new("o:c:s:", ARRAY_LEN(topts), topts, on_option,
+ on_args, 0);
+
+ return *opts != NULL;
+}
+
+static tool_rc init(ESYS_CONTEXT *context) {
+
+ if (!ctx.context_arg) {
+ LOG_ERR("Expected option c");
+ return tool_rc_option_error;
+ }
+
+ ctx.message.size = BUFFER_SIZE(TPM2B_MAX_BUFFER, buffer);
+ bool result = files_load_bytes_from_buffer_or_file_or_stdin(NULL,
+ ctx.input_path, &ctx.message.size, ctx.message.buffer);
+ if (!result) {
+ return tool_rc_general_error;
+ }
+
+ if (ctx.data1_path) {
+ ctx.shared_data1.size = BUFFER_SIZE(TPM2B_DATA, buffer);
+ bool ret = files_load_bytes_from_buffer_or_file_or_stdin(NULL,
+ ctx.data1_path, &ctx.shared_data1.size, ctx.shared_data1.buffer);
+ if (!ret) {
+ return tool_rc_general_error;
+ }
+ }
+
+ if (ctx.data2_path) {
+ ctx.shared_data2.size = BUFFER_SIZE(TPM2B_DATA, buffer);
+ bool ret = files_load_bytes_from_buffer_or_file_or_stdin(NULL,
+ ctx.data2_path, &ctx.shared_data2.size, ctx.shared_data2.buffer);
+ if (!ret) {
+ return tool_rc_general_error;
+ }
+ }
+
+ /*
+ * Load the decryption key
+ */
+ tool_rc rc = tpm2_util_object_load(context, ctx.context_arg, &ctx.key_context,
+ TPM2_HANDLES_FLAGS_TRANSIENT|TPM2_HANDLES_FLAGS_PERSISTENT);
+ if (rc != tool_rc_success) {
+ return rc;
+ }
+
+ TPM2B_PUBLIC *key_public_info = 0;
+ rc = tpm2_readpublic(context, ctx.key_context.tr_handle, &key_public_info,
+ NULL, NULL);
+ if (rc != tool_rc_success) {
+ goto out;
+ }
+
+ if (key_public_info->publicArea.type != TPM2_ALG_ECC) {
+ LOG_ERR("Unsupported key type for ECC encryption.");
+ rc = tool_rc_general_error;
+ goto out;
+ }
+
+ /*
+ * Get scheme information
+ */
+ if (ctx.scheme_str) {
+ rc = tpm2_alg_util_handle_ecc_ext_alg(ctx.scheme_str, key_public_info);
+ ctx.scheme.scheme =
+ key_public_info->publicArea.parameters.eccDetail.scheme.scheme;
+ ctx.scheme.details.anySig.hashAlg =
+ key_public_info->publicArea.parameters.eccDetail.scheme.details.anySig.hashAlg;
+ }
+
+out:
+ Esys_Free(key_public_info);
+
+ return rc;
+}
+
+static tool_rc tpm2_tool_onrun(ESYS_CONTEXT *context, tpm2_option_flags flags) {
+
+ UNUSED(flags);
+
+ tool_rc rc = init(context);
+ if (rc != tool_rc_success) {
+ return rc;
+ }
+
+ return ecc_encrypt_and_save(context);
+}
+
+// Register this tool with tpm2_tool.c
+TPM2_TOOL_REGISTER("eccencrypt", tpm2_tool_onstart, tpm2_tool_onrun, NULL, NULL)
--
2.17.1
此处可能存在不合适展示的内容,页面不予展示。您可通过相关编辑功能自查并修改。
如您确认内容无涉及 不当用语 / 纯广告导流 / 暴力 / 低俗色情 / 侵权 / 盗版 / 虚假 / 无价值内容或违法国家有关法律法规的内容,可点击提交进行申诉,我们将尽快为您处理。