aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDavid Hu <david.hu@arm.com>2020-03-26 14:02:35 +0800
committerDavid Hu <david.hu@arm.com>2020-06-22 02:33:00 +0000
commit0414fa1f0cacabd3331a44237c8dbda9baaf4a83 (patch)
tree6527c9072061fa2644dbbd59423fab632fe8817b
parent3b49ce71f346dceb3e09eb07435aeab56aebb7b7 (diff)
downloadtrusted-firmware-m-0414fa1f0cacabd3331a44237c8dbda9baaf4a83.tar.gz
COSE: Implement Short Circuit option in COSE_Mac0
Add a flag T_COSE_OPT_SHORT_CIRCUIT_TAG to control the Short Circuit tagging in COSE_Mac0. Implement Short Circuit tag generation and verification. Skip kid parameter in COSE_Mac0 if Short Circuit is enabled. Add decoding routine for Short Circuit option in COSE_Mac0. Change-Id: I6fe0d797ea7646848c00d8a3fec9de97925ff4dc Signed-off-by: David Hu <david.hu@arm.com>
-rw-r--r--lib/ext/t_cose/crypto_adapters/t_cose_psa_crypto.c5
-rw-r--r--lib/ext/t_cose/inc/t_cose_common.h10
-rw-r--r--lib/ext/t_cose/inc/t_cose_mac0_sign.h28
-rw-r--r--lib/ext/t_cose/inc/t_cose_sign1_verify.h11
-rw-r--r--lib/ext/t_cose/src/t_cose_crypto.h17
-rw-r--r--lib/ext/t_cose/src/t_cose_mac0_sign.c115
-rw-r--r--lib/ext/t_cose/src/t_cose_mac0_verify.c77
7 files changed, 246 insertions, 17 deletions
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 f6036f9cf..22203dd5e 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
@@ -290,10 +290,13 @@ enum t_cose_err_t t_cose_crypto_sig_size(int32_t cose_algorithm_id,
Done:
return return_value;
}
+#endif /* !T_COSE_DISABLE_SIGN1 */
+#if !defined(T_COSE_DISABLE_SHORT_CIRCUIT_SIGN) || \
+ !defined(T_COSE_DISABLE_SIGN1)
/**
* \brief Convert COSE hash algorithm ID to a PSA hash algorithm ID
*
@@ -408,7 +411,7 @@ t_cose_crypto_hash_finish(struct t_cose_crypto_hash *hash_ctx,
Done:
return psa_status_to_t_cose_error_hash(hash_ctx->status);
}
-#endif /* !T_COSE_DISABLE_SIGN1 */
+#endif /* !T_COSE_DISABLE_SHORT_CIRCUIT_SIGN || !T_COSE_DISABLE_SIGN1 */
#ifndef T_COSE_DISABLE_MAC0
/**
diff --git a/lib/ext/t_cose/inc/t_cose_common.h b/lib/ext/t_cose/inc/t_cose_common.h
index c6f2ec6b2..9b1a3dc5e 100644
--- a/lib/ext/t_cose/inc/t_cose_common.h
+++ b/lib/ext/t_cose/inc/t_cose_common.h
@@ -452,6 +452,16 @@ struct t_cose_parameters {
/**
+ * Pass this as \c option_flags to allow verification of short-circuit
+ * signatures. This should only be used as a test mode as
+ * short-circuit signatures are not secure.
+ *
+ * See also \ref T_COSE_OPT_SHORT_CIRCUIT_SIG.
+ */
+#define T_COSE_OPT_ALLOW_SHORT_CIRCUIT 0x00000001
+
+
+/**
* The error \ref T_COSE_ERR_NO_KID is returned if the kid parameter
* is missing. Note that the kid parameter is primarily passed on to
* the crypto layer so the crypto layer can look up the key. If the
diff --git a/lib/ext/t_cose/inc/t_cose_mac0_sign.h b/lib/ext/t_cose/inc/t_cose_mac0_sign.h
index c3839f5f0..fa9821081 100644
--- a/lib/ext/t_cose/inc/t_cose_mac0_sign.h
+++ b/lib/ext/t_cose/inc/t_cose_mac0_sign.h
@@ -18,6 +18,27 @@ extern "C" {
/**
+ * This selects a test mode called _short_ _circuit_ _tagging_.
+ * This mode is useful when the symmetric key is unavailable
+ * or unable to be accessed, perhaps because it has not been provisioned or
+ * configured for the particular device.
+ *
+ * It has no value for security at all. Data signed this way MUST NOT
+ * be trusted as anyone can sign like this.
+ *
+ * In this mode, the tag is the hash of that which would normally be MACed by
+ * a symmetric key.
+ *
+ * This mode is very useful for testing because all the code except
+ * the actual MAC algorithm is run exactly as it would if a proper
+ * MAC algorithm was run. This can be used for end-end system
+ * testing all the way to a server or relying party, not just for
+ * testing device code as t_cose_mac0_verify() supports it too.
+ */
+#define T_COSE_OPT_SHORT_CIRCUIT_TAG 0x00000004
+
+
+/**
* This is the context for creating a \c COSE_Mac0 structure. The caller
* should allocate it and pass it to the functions here. This is
* about 32 bytes so it fits easily on the stack.
@@ -49,7 +70,8 @@ struct t_cose_mac0_sign_ctx {
*
* Initialize the \ref t_cose_mac0_sign_ctx context. Typically, no
* \c option_flags are needed and 0 is passed. A \c cose_algorithm_id
- * must always be given.
+ * must always be given. See \ref T_COSE_OPT_SHORT_CIRCUIT_TAG and
+ * related for possible option flags.
*
* The algorithm ID space is from
* [COSE (RFC8152)](https://tools.ietf.org/html/rfc8152) and the
@@ -74,6 +96,10 @@ t_cose_mac0_sign_init(struct t_cose_mac0_sign_ctx *me,
*
* This needs to be called to set the signing key to use. The \c kid
* may be omitted by giving \c NULL_Q_USEFUL_BUF_C.
+ *
+ * If short-circuit signing is used,
+ * \ref T_COSE_OPT_SHORT_CIRCUIT_TAG, then this does not need to be
+ * called.
*/
static void
t_cose_mac0_set_signing_key(struct t_cose_mac0_sign_ctx *context,
diff --git a/lib/ext/t_cose/inc/t_cose_sign1_verify.h b/lib/ext/t_cose/inc/t_cose_sign1_verify.h
index 48ac7c919..198a21a35 100644
--- a/lib/ext/t_cose/inc/t_cose_sign1_verify.h
+++ b/lib/ext/t_cose/inc/t_cose_sign1_verify.h
@@ -52,17 +52,6 @@ extern "C" {
/**
- * Pass this as \c option_flags to allow verification of short-circuit
- * signatures. This should only be used as a test mode as
- * short-circuit signatures are not secure.
- *
- * See also \ref T_COSE_OPT_SHORT_CIRCUIT_SIG.
- */
-#define T_COSE_OPT_ALLOW_SHORT_CIRCUIT 0x00000001
-
-
-
-/**
* Context for signature verification. It is about 24 bytes on a
* 64-bit machine and 12 bytes on a 32-bit machine.
*/
diff --git a/lib/ext/t_cose/src/t_cose_crypto.h b/lib/ext/t_cose/src/t_cose_crypto.h
index 8c98c4896..019f909f3 100644
--- a/lib/ext/t_cose/src/t_cose_crypto.h
+++ b/lib/ext/t_cose/src/t_cose_crypto.h
@@ -724,6 +724,23 @@ static inline size_t t_cose_tag_size(int32_t cose_alg_id)
}
}
+#ifndef T_COSE_DISABLE_SHORT_CIRCUIT_SIGN
+/*
+ * Get the COSE Hash algorithm ID from the corresponding
+ * COSE HMAC algorithm ID
+ */
+static inline int32_t t_cose_hmac_to_hash_alg_id(int32_t cose_hamc_alg_id)
+{
+ switch(cose_hamc_alg_id) {
+ case T_COSE_ALGORITHM_HMAC256:
+ return COSE_ALGORITHM_SHA_256;
+
+ default:
+ return INT32_MAX;
+ }
+}
+#endif
+
#ifdef __cplusplus
}
#endif
diff --git a/lib/ext/t_cose/src/t_cose_mac0_sign.c b/lib/ext/t_cose/src/t_cose_mac0_sign.c
index 7a5740976..4cd30e9cd 100644
--- a/lib/ext/t_cose/src/t_cose_mac0_sign.c
+++ b/lib/ext/t_cose/src/t_cose_mac0_sign.c
@@ -126,6 +126,81 @@ add_unprotected_parameters(const struct t_cose_mac0_sign_ctx *me,
return T_COSE_SUCCESS;
}
+#ifndef T_COSE_DISABLE_SHORT_CIRCUIT_SIGN
+/**
+ * \brief Create a short-circuit tag
+ *
+ * \param[in] cose_alg_id Algorithm ID. This is used only to make
+ * the short-circuit tag the same size as the
+ * real tag would be for the particular algorithm.
+ * \param[in] header The Header of COSE_Mac0.
+ * \param[in] payload The payload of COSE_Mac0
+ * \param[in] tag_buffer Pointer and length of buffer into which
+ * the resulting tag is put.
+ * \param[out] tag Pointer and length of the tag returned.
+ *
+ * \return This returns one of the error codes defined by \ref t_cose_err_t.
+ *
+ * This creates the short-circuit tag that is actually a hash of input bytes.
+ * This is a test mode only has it has no security value. This is retained in
+ * commercial production code as a useful test or demo that can run
+ * even if key material is not set up or accessible.
+ */
+static inline enum t_cose_err_t
+short_circuit_tag(int32_t cose_alg_id,
+ struct q_useful_buf_c header,
+ struct q_useful_buf_c payload,
+ struct q_useful_buf tag_buffer,
+ struct q_useful_buf_c *tag)
+{
+ /* approximate stack use on 32-bit machine: local use: 16 bytes */
+ enum t_cose_err_t return_value;
+ struct t_cose_crypto_hash hash_ctx;
+ size_t tag_size;
+ int32_t hash_alg_id;
+
+ /*
+ * The length of Hash result equals that of HMAC result
+ * with the same Hash algorithm.
+ */
+ tag_size = t_cose_tag_size(cose_alg_id);
+
+ /* Check the tag length against buffer size */
+ if(tag_size == INT32_MAX) {
+ return_value = T_COSE_ERR_UNSUPPORTED_SIGNING_ALG;
+ goto Done;
+ }
+
+ if(tag_size > tag_buffer.len) {
+ /* Buffer too small for this tag */
+ return_value = T_COSE_ERR_SIG_BUFFER_SIZE;
+ goto Done;
+ }
+
+ hash_alg_id = t_cose_hmac_to_hash_alg_id(cose_alg_id);
+ if(hash_alg_id == INT32_MAX) {
+ return_value = T_COSE_ERR_UNSUPPORTED_SIGNING_ALG;
+ goto Done;
+ }
+
+ return_value = t_cose_crypto_hash_start(&hash_ctx, hash_alg_id);
+ if(return_value != T_COSE_SUCCESS) {
+ goto Done;
+ }
+
+ /* Hash the Header */
+ t_cose_crypto_hash_update(&hash_ctx, q_useful_buf_head(header, header.len));
+
+ /* Hash the payload */
+ t_cose_crypto_hash_update(&hash_ctx, payload);
+
+ return_value = t_cose_crypto_hash_finish(&hash_ctx, tag_buffer, tag);
+
+Done:
+ return return_value;
+}
+#endif /* T_COSE_DISABLE_SHORT_CIRCUIT_SIGN */
+
/*
* Public function. See t_cose_mac0.h
*/
@@ -175,10 +250,19 @@ t_cose_mac0_encode_parameters(struct t_cose_mac0_sign_ctx *me,
QCBOREncode_AddBytes(cbor_encode_ctx, me->protected_parameters);
/* The Unprotected parameters */
- /* Get the kid because it goes into the parameters that are about
- * to be made.
- */
- kid = me->kid;
+ if(me->option_flags & T_COSE_OPT_SHORT_CIRCUIT_TAG) {
+#ifndef T_COSE_DISABLE_SHORT_CIRCUIT_SIGN
+ kid = NULL_Q_USEFUL_BUF_C;
+#else
+ return_value = T_COSE_ERR_SHORT_CIRCUIT_SIG_DISABLED;
+ goto Done;
+#endif
+ } else {
+ /* Get the kid because it goes into the parameters that are about
+ * to be made.
+ */
+ kid = me->kid;
+ }
return_value = add_unprotected_parameters(me, kid, cbor_encode_ctx);
if(return_value != T_COSE_SUCCESS) {
@@ -261,7 +345,30 @@ t_cose_mac0_encode_tag(struct t_cose_mac0_sign_ctx *me,
* Start the HMAC.
* Calculate the tag of the first part of ToBeMaced and the wrapped
* payload, to save a bigger buffer containing the entire ToBeMaced.
+ *
+ * Short-circuit tagging is invoked if requested. It does no HMAC operation
+ * and requires no key. It is just a test mode that works without accessing
+ * any device asset.
*/
+ if(me->option_flags & T_COSE_OPT_SHORT_CIRCUIT_TAG) {
+#ifndef T_COSE_DISABLE_SHORT_CIRCUIT_SIGN
+ /* Short-circuit tag. Hash is used to generated tag instead of HMAC */
+ return_value = short_circuit_tag(me->cose_algorithm_id,
+ tbm_first_part,
+ maced_payload,
+ tag_buf,
+ &tag);
+ if(return_value) {
+ goto Done;
+ }
+
+ goto CloseArray;
+#else
+ return_value = T_COSE_ERR_SHORT_CIRCUIT_SIG_DISABLED;
+ goto Done;
+#endif
+ }
+
return_value = t_cose_crypto_hmac_sign_setup(&hmac_ctx,
me->signing_key,
me->cose_algorithm_id);
diff --git a/lib/ext/t_cose/src/t_cose_mac0_verify.c b/lib/ext/t_cose/src/t_cose_mac0_verify.c
index ce47bb60c..b75cbda0b 100644
--- a/lib/ext/t_cose/src/t_cose_mac0_verify.c
+++ b/lib/ext/t_cose/src/t_cose_mac0_verify.c
@@ -13,6 +13,69 @@
#include "t_cose_parameters.h"
#include "t_cose_util.h"
+#ifndef T_COSE_DISABLE_SHORT_CIRCUIT_SIGN
+/**
+ * \brief Verify a short-circuit tag
+ *
+ * \param[in] cose_alg_id Algorithm ID. This is used only to make
+ * the short-circuit signature the same size as the
+ * real tag would be for the particular algorithm.
+ * \param[in] header The Header of COSE_Mac0.
+ * \param[in] payload The payload of COSE_Mac0
+ * \param[in] tag Pointer and length of tag to be verified
+ *
+ * \return This returns one of the error codes defined by \ref
+ * t_cose_err_t.
+ *
+ * See short_circuit_tag() in t_cose_mac0_sign.c for description of
+ * the short-circuit tag.
+ */
+static inline enum t_cose_err_t
+short_circuit_verify(int32_t cose_alg_id,
+ struct q_useful_buf_c header,
+ struct q_useful_buf_c payload,
+ struct q_useful_buf_c tag_to_verify)
+{
+ /* approximate stack use on 32-bit machine: local use: 16 bytes */
+ enum t_cose_err_t return_value;
+ struct t_cose_crypto_hash hash_ctx;
+ Q_USEFUL_BUF_MAKE_STACK_UB(tag_buffer, T_COSE_CRYPTO_HMAC_TAG_MAX_SIZE);
+ struct q_useful_buf_c tag;
+ int32_t hash_alg_id;
+
+ hash_alg_id = t_cose_hmac_to_hash_alg_id(cose_alg_id);
+ if (hash_alg_id == INT32_MAX) {
+ return_value = T_COSE_ERR_UNSUPPORTED_SIGNING_ALG;
+ goto Done;
+ }
+
+ return_value = t_cose_crypto_hash_start(&hash_ctx, hash_alg_id);
+ if (return_value != T_COSE_SUCCESS) {
+ goto Done;
+ }
+
+ /* Hash the Header */
+ t_cose_crypto_hash_update(&hash_ctx, q_useful_buf_head(header, header.len));
+
+ /* Hash the payload */
+ t_cose_crypto_hash_update(&hash_ctx, payload);
+
+ return_value = t_cose_crypto_hash_finish(&hash_ctx, tag_buffer, &tag);
+ if (return_value != T_COSE_SUCCESS) {
+ goto Done;
+ }
+
+ if (q_useful_buf_compare(tag_to_verify, tag)) {
+ return_value = T_COSE_ERR_SIG_VERIFY;
+ } else {
+ return_value = T_COSE_SUCCESS;
+ }
+
+Done:
+ return return_value;
+}
+#endif /* T_COSE_DISABLE_SHORT_CIRCUIT_SIGN */
+
/**
* \file t_cose_mac0_verify.c
*
@@ -153,6 +216,20 @@ enum t_cose_err_t t_cose_mac0_verify(struct t_cose_mac0_verify_ctx *context,
goto Done;
}
+ if (context->option_flags & T_COSE_OPT_ALLOW_SHORT_CIRCUIT) {
+#ifndef T_COSE_DISABLE_SHORT_CIRCUIT_SIGN
+ /* Short-circuit tag. Hash is used to generated tag instead of HMAC */
+ return_value = short_circuit_verify(
+ parsed_protected_parameters.cose_algorithm_id,
+ tbm_first_part,
+ *payload,
+ tag);
+#else
+ return_value = T_COSE_ERR_SHORT_CIRCUIT_SIG_DISABLED;
+#endif
+ goto Done;
+
+ }
/*
* Start the HMAC verification.
* Calculate the tag of the first part of ToBeMaced and the wrapped