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..dfaf2ebd2 100644 --- a/lib/ext/t_cose/src/t_cose_sign1_sign.c +++ b/lib/ext/t_cose/src/t_cose_sign1_sign.c @@ -43,6 +43,18 @@ #error COSE algorithm identifier definitions are in error #endif +/** + * This is the size of the first part of the CBOR encoded TBS + * bytes. It is around 30 bytes. See create_tbs_hash(). + */ +#define T_COSE_SIZE_OF_TBS \ + 1 + /* For opening the array */ \ + sizeof(COSE_SIG_CONTEXT_STRING_SIGNATURE1) + /* "Signature1" */ \ + 2 + /* Overhead for encoding string */ \ + T_COSE_SIGN1_MAX_SIZE_PROTECTED_PARAMETERS + /* entire protected params */ \ + 1 + /* Empty bstr for absent external_aad */ \ + 220 /* The max CBOR length encoding for start of payload */ + #ifndef T_COSE_DISABLE_SHORT_CIRCUIT_SIGN /** @@ -323,14 +335,27 @@ 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; +#else + /* pointer and length of the completed tbs message */ + struct q_useful_buf_c tbs_message; + QCBOREncodeContext cbor_Sig_structure_ctx; + /* Pointer and length of the completed signature */ + QCBORError qcbor_result; + Q_USEFUL_BUF_MAKE_STACK_UB( buffer_for_tbs_message, T_COSE_SIZE_OF_TBS); +#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 +384,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 +400,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 +415,41 @@ 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 + QCBOREncode_Init(&cbor_Sig_structure_ctx, buffer_for_tbs_message); + QCBOREncode_OpenArray(&cbor_Sig_structure_ctx); + + /* context */ + QCBOREncode_AddSZString(&cbor_Sig_structure_ctx, COSE_SIG_CONTEXT_STRING_SIGNATURE1); + /* body_protected */ + QCBOREncode_AddBytes(&cbor_Sig_structure_ctx, me->protected_parameters); + + /* sign_protected is not used for COSE_Sign1 */ + + /* external_aad. There is none so an empty bstr */ + QCBOREncode_AddBytes(&cbor_Sig_structure_ctx, NULL_Q_USEFUL_BUF_C); + + /* payload */ + QCBOREncode_AddBytes(&cbor_Sig_structure_ctx, signed_payload); + + /* Close off the array */ + QCBOREncode_CloseArray(&cbor_Sig_structure_ctx); + + qcbor_result = QCBOREncode_Finish(&cbor_Sig_structure_ctx, &tbs_message); + if(qcbor_result) { + /* Mainly means that the protected_parameters were too big + * (which should never happen) */ + return_value = T_COSE_ERR_SIG_STRUCT; + goto Done; + } + + tbs = &tbs_message; + #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 {