From 64940d293a7de6141e387cb8d98510143a4ab5d3 Mon Sep 17 00:00:00 2001 From: Sigurd Hellesvik Date: Mon, 18 Nov 2024 13:21:32 +0100 Subject: [PATCH] [nrf noup] Attest+COSE: Draft to test upstream change https://review.trustedfirmware.org/c/TF-M/trusted-firmware-m/+/33713 Signed-off-by: Sigurd Hellesvik --- config/config_base.cmake | 1 + .../tfm_attestation_integration_guide.rst | 2 +- .../t_cose/crypto_adapters/t_cose_psa_crypto.c | 17 ++++++++++++++--- lib/ext/t_cose/src/t_cose_crypto.h | 11 +++++------ lib/ext/t_cose/src/t_cose_sign1_sign.c | 15 ++++++++++++++- lib/ext/t_cose/test/t_cose_make_test_messages.c | 17 +++++++++++++++-- lib/ext/t_cose/tfm_t_cose.cmake | 1 + .../partitions/initial_attestation/Kconfig | 8 ++++++++ .../initial_attestation/attest_token_encode.c | 1 - 9 files changed, 59 insertions(+), 14 deletions(-) diff --git a/config/config_base.cmake b/config/config_base.cmake index 56b52ca77..13f675a02 100644 --- a/config/config_base.cmake +++ b/config/config_base.cmake @@ -146,6 +146,7 @@ set(SYMMETRIC_INITIAL_ATTESTATION OFF CACHE BOOL "Use symmetr set(ATTEST_INCLUDE_TEST_CODE OFF CACHE BOOL "Include minimal development tests in the initial attestation regression test suite") set(ATTEST_KEY_BITS 256 CACHE STRING "The size of the initial attestation key in bits") set(PSA_INITIAL_ATTEST_MAX_TOKEN_SIZE 0x250 CACHE STRING "The maximum possible size of a token") +set(ATTEST_SIGN_MESSAGE OFF CACHE BOOL "Sign message instead of hash") set(TFM_PARTITION_PLATFORM OFF CACHE BOOL "Enable Platform partition") diff --git a/docs/integration_guide/services/tfm_attestation_integration_guide.rst b/docs/integration_guide/services/tfm_attestation_integration_guide.rst index 5e9a126fa..2af01b068 100644 --- a/docs/integration_guide/services/tfm_attestation_integration_guide.rst +++ b/docs/integration_guide/services/tfm_attestation_integration_guide.rst @@ -412,7 +412,7 @@ device. System integrators might need to re-implement the following functions if they want to use initial attestation service with a different cryptographic library than Crypto service: -- ``t_cose_crypto_pub_key_sign()``: Calculates the signature over a hash value. +- ``t_cose_crypto_pub_key_sign()``: Calculates the signature over a value. - ``t_cose_crypto_get_ec_pub_key()``: Get the public key to create the key identifier. - ``t_cose_crypto_hash_start()``: Start a multipart hash operation. diff --git a/lib/ext/t_cose/crypto_adapters/t_cose_psa_crypto.c b/lib/ext/t_cose/crypto_adapters/t_cose_psa_crypto.c index 20ab764e3..d42a438c3 100644 --- a/lib/ext/t_cose/crypto_adapters/t_cose_psa_crypto.c +++ b/lib/ext/t_cose/crypto_adapters/t_cose_psa_crypto.c @@ -164,7 +164,7 @@ t_cose_crypto_pub_key_verify(int32_t cose_algorithm_id, enum t_cose_err_t t_cose_crypto_pub_key_sign(int32_t cose_algorithm_id, struct t_cose_key signing_key, - struct q_useful_buf_c hash_to_sign, + struct q_useful_buf_c to_sign, struct q_useful_buf signature_buffer, struct q_useful_buf_c *signature) { @@ -196,13 +196,24 @@ t_cose_crypto_pub_key_sign(int32_t cose_algorithm_id, /* It is assumed that this call is checking the signature_buffer * length and won't write off the end of it. */ + +#ifdef T_COSE_SIGN_MESSAGE + psa_result = psa_sign_message(signing_key_psa, + psa_alg_id, + to_sign.ptr, + to_sign.len, + signature_buffer.ptr, /* Sig buf */ + signature_buffer.len, /* Sig buf size */ + &signature_len); /* Sig length */ +#else psa_result = psa_sign_hash(signing_key_psa, psa_alg_id, - hash_to_sign.ptr, - hash_to_sign.len, + to_sign.ptr, + to_sign.len, signature_buffer.ptr, /* Sig buf */ signature_buffer.len, /* Sig buf size */ &signature_len); /* Sig length */ +#endif return_value = psa_status_to_t_cose_error_signing(psa_result); diff --git a/lib/ext/t_cose/src/t_cose_crypto.h b/lib/ext/t_cose/src/t_cose_crypto.h index d068fc206..1466ce0a3 100644 --- a/lib/ext/t_cose/src/t_cose_crypto.h +++ b/lib/ext/t_cose/src/t_cose_crypto.h @@ -155,10 +155,10 @@ t_cose_crypto_sig_size(int32_t cose_algorithm_id, struct t_cose_key signing_key, size_t *sig_size); - /** - * \brief Perform public key signing. Part of the t_cose crypto - * adaptation layer. + * \brief Perform public key signing of a payload. Can sign either + * a message or message hash. Part of the t_cose crypto adaptation + * layer. * * \param[in] cose_algorithm_id The algorithm to sign with. The IDs are * defined in [COSE (RFC 8152)] @@ -169,8 +169,7 @@ t_cose_crypto_sig_size(int32_t cose_algorithm_id, * locally (\c \#define) if the needed * one hasn't been registered. * \param[in] signing_key Indicates or contains key to sign with. - * \param[in] hash_to_sign The bytes to sign. Typically, a hash of - * a payload. + * \param[in] to_sign The bytes to sign. * \param[in] signature_buffer Pointer and length of buffer into which * the resulting signature is put. * \param[in] signature Pointer and length of the signature @@ -215,7 +214,7 @@ t_cose_crypto_sig_size(int32_t cose_algorithm_id, enum t_cose_err_t t_cose_crypto_pub_key_sign(int32_t cose_algorithm_id, struct t_cose_key signing_key, - struct q_useful_buf_c hash_to_sign, + struct q_useful_buf_c to_sign, struct q_useful_buf signature_buffer, struct q_useful_buf_c *signature); diff --git a/lib/ext/t_cose/src/t_cose_sign1_sign.c b/lib/ext/t_cose/src/t_cose_sign1_sign.c index de11a9a34..ba8047633 100644 --- a/lib/ext/t_cose/src/t_cose_sign1_sign.c +++ b/lib/ext/t_cose/src/t_cose_sign1_sign.c @@ -323,14 +323,20 @@ t_cose_sign1_encode_signature(struct t_cose_sign1_sign_ctx *me, */ enum t_cose_err_t return_value; QCBORError cbor_err; + /* Pointer to useful_buf used for the signature*/ + struct q_useful_buf_c *tbs; +#ifndef T_COSE_SIGN_MESSAGE /* pointer and length of the completed tbs hash */ struct q_useful_buf_c tbs_hash; +#endif /* Pointer and length of the completed signature */ struct q_useful_buf_c signature; /* Buffer for the actual signature */ Q_USEFUL_BUF_MAKE_STACK_UB( buffer_for_signature, T_COSE_MAX_SIG_SIZE); +#ifndef T_COSE_SIGN_MESSAGE /* Buffer for the tbs hash. */ Q_USEFUL_BUF_MAKE_STACK_UB( buffer_for_tbs_hash, T_COSE_CRYPTO_MAX_HASH_SIZE); +#endif struct q_useful_buf_c signed_payload; QCBOREncode_CloseBstrWrap(cbor_encode_ctx, &signed_payload); @@ -359,6 +365,7 @@ t_cose_sign1_encode_signature(struct t_cose_sign1_sign_ctx *me, &signature.len); } else { + #ifndef T_COSE_SIGN_MESSAGE /* Create the hash of the to-be-signed bytes. Inputs to the * hash are the protected parameters, the payload that is * getting signed, the cose signature alg from which the hash @@ -374,6 +381,7 @@ t_cose_sign1_encode_signature(struct t_cose_sign1_sign_ctx *me, if(return_value) { goto Done; } + #endif /* Compute the signature using public key crypto. The key and * algorithm ID are passed in to know how and what to sign @@ -388,9 +396,14 @@ t_cose_sign1_encode_signature(struct t_cose_sign1_sign_ctx *me, */ if(!(me->option_flags & T_COSE_OPT_SHORT_CIRCUIT_SIG)) { /* Normal, non-short-circuit signing */ + #ifdef T_COSE_SIGN_MESSAGE + tbs = &(me->protected_parameters); + #else + tbs = &tbs_hash; + #endif return_value = t_cose_crypto_pub_key_sign(me->cose_algorithm_id, me->signing_key, - tbs_hash, + *tbs, buffer_for_signature, &signature); } else { diff --git a/lib/ext/t_cose/test/t_cose_make_test_messages.c b/lib/ext/t_cose/test/t_cose_make_test_messages.c index 89bb7847c..4a82597ab 100644 --- a/lib/ext/t_cose/test/t_cose_make_test_messages.c +++ b/lib/ext/t_cose/test/t_cose_make_test_messages.c @@ -475,14 +475,18 @@ t_cose_sign1_test_message_output_signature(struct t_cose_sign1_sign_ctx *me, */ enum t_cose_err_t return_value; QCBORError cbor_err; + /* Pointer to useful_buf used for the signature*/ + struct q_useful_buf_c *tbs; /* pointer and length of the completed tbs hash */ struct q_useful_buf_c tbs_hash; /* Pointer and length of the completed signature */ struct q_useful_buf_c signature; /* Buffer for the actual signature */ Q_USEFUL_BUF_MAKE_STACK_UB( buffer_for_signature, T_COSE_MAX_SIG_SIZE); +#ifndef T_COSE_SIGN_MESSAGE /* Buffer for the tbs hash. */ Q_USEFUL_BUF_MAKE_STACK_UB( buffer_for_tbs_hash, T_COSE_CRYPTO_MAX_HASH_SIZE); +#endif struct q_useful_buf_c signed_payload; QCBOREncode_CloseBstrWrap(cbor_encode_ctx, &signed_payload); @@ -501,6 +505,8 @@ t_cose_sign1_test_message_output_signature(struct t_cose_sign1_sign_ctx *me, goto Done; } + if(!(me->option_flags & T_COSE_OPT_SIGN_MESSAGE)) { +#ifndef T_COSE_SIGN_MESSAGE /* Create the hash of the to-be-signed bytes. Inputs to the hash * are the protected parameters, the payload that is getting signed, the * cose signature alg from which the hash alg is determined. The @@ -516,6 +522,7 @@ t_cose_sign1_test_message_output_signature(struct t_cose_sign1_sign_ctx *me, if(return_value != T_COSE_SUCCESS) { goto Done; } +#endif /* Compute the signature using public key crypto. The key selector * and algorithm ID are passed in to know how and what to sign @@ -529,11 +536,17 @@ t_cose_sign1_test_message_output_signature(struct t_cose_sign1_sign_ctx *me, */ if(!(me->option_flags & T_COSE_OPT_SHORT_CIRCUIT_SIG)) { /* Normal, non-short-circuit signing */ + if(!(me->option_flags & T_COSE_OPT_SIGN_MESSAGE)) { + tbs = &tbs_hash; + } else { + tbs = &(me->protected_parameters); + } return_value = t_cose_crypto_pub_key_sign(me->cose_algorithm_id, me->signing_key, - tbs_hash, + *tbs, buffer_for_signature, - &signature); + &signature, + me->option_flags); } else { #ifndef T_COSE_DISABLE_SHORT_CIRCUIT_SIGN return_value = short_circuit_sign(me->cose_algorithm_id, diff --git a/lib/ext/t_cose/tfm_t_cose.cmake b/lib/ext/t_cose/tfm_t_cose.cmake index 7c5e59e91..18db7593c 100644 --- a/lib/ext/t_cose/tfm_t_cose.cmake +++ b/lib/ext/t_cose/tfm_t_cose.cmake @@ -29,6 +29,7 @@ target_compile_definitions(tfm_t_cose_defs $<$:T_COSE_DISABLE_SIGN1> $<$>:T_COSE_DISABLE_MAC0> $<$>:T_COSE_DISABLE_SHORT_CIRCUIT_SIGN> + $<$:T_COSE_SIGN_MESSAGE> ) ############################### t_cose common ################################## diff --git a/secure_fw/partitions/initial_attestation/Kconfig b/secure_fw/partitions/initial_attestation/Kconfig index 6bf4ddb2f..92dc24870 100644 --- a/secure_fw/partitions/initial_attestation/Kconfig +++ b/secure_fw/partitions/initial_attestation/Kconfig @@ -32,6 +32,14 @@ config ATTEST_KEY_BITS help The size of the initial attestation key in bits +config ATTEST_SIGN_MESSAGE + bool "Sign message instead of hash" + default n + help + By default attestation calculates a hash of the payload and signs that. + Use this to instead sign the payload/message directly. + + config PSA_INITIAL_ATTEST_MAX_TOKEN_SIZE hex "The maximum possible size of a token" default 0x250 diff --git a/secure_fw/partitions/initial_attestation/attest_token_encode.c b/secure_fw/partitions/initial_attestation/attest_token_encode.c index f17d0a535..c950d1e7c 100644 --- a/secure_fw/partitions/initial_attestation/attest_token_encode.c +++ b/secure_fw/partitions/initial_attestation/attest_token_encode.c @@ -241,7 +241,6 @@ attest_token_encode_start(struct attest_token_encode_ctx *me, me->opt_flags = opt_flags; me->key_select = key_select; - if (opt_flags & TOKEN_OPT_SHORT_CIRCUIT_SIGN) { t_cose_options |= T_COSE_OPT_SHORT_CIRCUIT_SIG; } else {