Skip to content

Commit

Permalink
Remove limit on MAC protected headers; MAC code size smaller (#276)
Browse files Browse the repository at this point in the history
* Rework of crypto adaptor layer for MAC

* A little more tidying up

* Improve comments; re order

* More code formatting and comments

* More code formatting and comments

* More code formatting and comments

---------

Co-authored-by: Laurence Lundblade <lgl@securitytheory.com>
  • Loading branch information
laurencelundblade and Laurence Lundblade authored Nov 16, 2023
1 parent 00992ed commit 1eeef3b
Show file tree
Hide file tree
Showing 11 changed files with 188 additions and 369 deletions.
68 changes: 18 additions & 50 deletions crypto_adapters/t_cose_openssl_crypto.c
Original file line number Diff line number Diff line change
Expand Up @@ -1052,7 +1052,7 @@ t_cose_crypto_hash_finish(struct t_cose_crypto_hash *hash_ctx,
* See documentation in t_cose_crypto.h
*/
enum t_cose_err_t
t_cose_crypto_hmac_compute_setup(struct t_cose_crypto_hmac *hmac_ctx,
t_cose_crypto_hmac_setup(struct t_cose_crypto_hmac *hmac_ctx,
struct t_cose_key signing_key,
const int32_t cose_alg_id)
{
Expand Down Expand Up @@ -1104,46 +1104,51 @@ t_cose_crypto_hmac_compute_setup(struct t_cose_crypto_hmac *hmac_ctx,
return T_COSE_ERR_HMAC_GENERAL_FAIL;
}

hmac_ctx->update_error = 1; /* 1 is success in OpenSSL */

return T_COSE_SUCCESS;
}


/*
* See documentation in t_cose_crypto.h
*/
enum t_cose_err_t
void
t_cose_crypto_hmac_update(struct t_cose_crypto_hmac *hmac_ctx,
struct q_useful_buf_c payload)
{
int ossl_result;

ossl_result = EVP_DigestSignUpdate(hmac_ctx->evp_ctx, payload.ptr, payload.len);
if(ossl_result != 1) {
return T_COSE_ERR_HMAC_GENERAL_FAIL;
if(hmac_ctx->update_error) { /* 1 is no error, 0 means error for OpenSSL */
if(payload.ptr) {
hmac_ctx->update_error = EVP_DigestSignUpdate(hmac_ctx->evp_ctx,
payload.ptr,
payload.len);
}
}

return T_COSE_SUCCESS;
}



/*
* See documentation in t_cose_crypto.h
*/
enum t_cose_err_t
t_cose_crypto_hmac_compute_finish(struct t_cose_crypto_hmac *hmac_ctx,
t_cose_crypto_hmac_finish(struct t_cose_crypto_hmac *hmac_ctx,
struct q_useful_buf tag_buf,
struct q_useful_buf_c *tag)
{
int ossl_result;
size_t in_out_len;

in_out_len = tag_buf.len;
ossl_result = EVP_DigestSignFinal(hmac_ctx->evp_ctx, tag_buf.ptr, &in_out_len);
if(hmac_ctx->update_error) {
hmac_ctx->update_error = EVP_DigestSignFinal(hmac_ctx->evp_ctx,
tag_buf.ptr,
&in_out_len);
}

EVP_MD_CTX_free(hmac_ctx->evp_ctx);
EVP_PKEY_free(hmac_ctx->evp_pkey);

if(ossl_result != 1) {
if(hmac_ctx->update_error != 1) {
return T_COSE_ERR_HMAC_GENERAL_FAIL;
}

Expand All @@ -1154,43 +1159,6 @@ t_cose_crypto_hmac_compute_finish(struct t_cose_crypto_hmac *hmac_ctx,
}


/*
* See documentation in t_cose_crypto.h
*/
// TODO: argument order alignment with t_cose_crypto_hmac_compute_setup
enum t_cose_err_t
t_cose_crypto_hmac_validate_setup(struct t_cose_crypto_hmac *hmac_ctx,
const int32_t cose_alg_id,
struct t_cose_key validation_key)
{
return t_cose_crypto_hmac_compute_setup(hmac_ctx, validation_key, cose_alg_id);
}


/*
* See documentation in t_cose_crypto.h
*/
enum t_cose_err_t
t_cose_crypto_hmac_validate_finish(struct t_cose_crypto_hmac *hmac_ctx,
struct q_useful_buf_c input_tag)
{
Q_USEFUL_BUF_MAKE_STACK_UB( tag_buf, T_COSE_CRYPTO_HMAC_TAG_MAX_SIZE);
struct q_useful_buf_c computed_tag;
enum t_cose_err_t result;

result = t_cose_crypto_hmac_compute_finish(hmac_ctx, tag_buf, &computed_tag);
if(result != T_COSE_SUCCESS) {
return result;
}

if(q_useful_buf_compare(computed_tag, input_tag)) {
return T_COSE_ERR_HMAC_VERIFY;
}

return T_COSE_SUCCESS;
}


/*
* See documentation in t_cose_crypto.h
*/
Expand Down
110 changes: 34 additions & 76 deletions crypto_adapters/t_cose_psa_crypto.c
Original file line number Diff line number Diff line change
Expand Up @@ -552,12 +552,12 @@ psa_status_to_t_cose_error_hmac(psa_status_t status)
* See documentation in t_cose_crypto.h
*/
enum t_cose_err_t
t_cose_crypto_hmac_compute_setup(struct t_cose_crypto_hmac *hmac_ctx,
struct t_cose_key signing_key,
const int32_t cose_alg_id)
t_cose_crypto_hmac_setup(struct t_cose_crypto_hmac *hmac_ctx,
struct t_cose_key signing_key,
const int32_t cose_alg_id)
{
psa_algorithm_t psa_alg;
psa_status_t psa_ret;
psa_status_t psa_ret;

/* Map the algorithm ID */
psa_alg = cose_hmac_alg_id_to_psa(cose_alg_id);
Expand All @@ -582,103 +582,61 @@ t_cose_crypto_hmac_compute_setup(struct t_cose_crypto_hmac *hmac_ctx,
(psa_key_id_t)signing_key.key.handle,
psa_alg);

hmac_ctx->status = PSA_SUCCESS;

return psa_status_to_t_cose_error_hmac(psa_ret);
}


/*
* See documentation in t_cose_crypto.h
*/
enum t_cose_err_t
void
t_cose_crypto_hmac_update(struct t_cose_crypto_hmac *hmac_ctx,
struct q_useful_buf_c payload)
{
psa_status_t psa_ret;

psa_ret = psa_mac_update(&hmac_ctx->op_ctx,
payload.ptr, payload.len);

return psa_status_to_t_cose_error_hmac(psa_ret);
}

/*
* See documentation in t_cose_crypto.h
*/
enum t_cose_err_t
t_cose_crypto_hmac_compute_finish(struct t_cose_crypto_hmac *hmac_ctx,
struct q_useful_buf tag_buf,
struct q_useful_buf_c *tag)
{
psa_status_t psa_ret;

psa_ret = psa_mac_sign_finish(&hmac_ctx->op_ctx,
tag_buf.ptr, tag_buf.len,
&(tag->len));
if(psa_ret == PSA_SUCCESS) {
tag->ptr = tag_buf.ptr;
if(hmac_ctx->status != PSA_SUCCESS) {
/* In error state. Nothing to do. */
return;
}

return psa_status_to_t_cose_error_hmac(psa_ret);
hmac_ctx->status = psa_mac_update(&hmac_ctx->op_ctx,
payload.ptr,
payload.len);
}


/*
* See documentation in t_cose_crypto.h
*/
enum t_cose_err_t
t_cose_crypto_hmac_validate_setup(struct t_cose_crypto_hmac *hmac_ctx,
const int32_t cose_alg_id,
struct t_cose_key validation_key)
t_cose_crypto_hmac_finish(struct t_cose_crypto_hmac *hmac_ctx,
struct q_useful_buf tag_buf,
struct q_useful_buf_c *tag)
{
psa_algorithm_t psa_alg;
psa_status_t psa_ret;

if(!hmac_ctx) {
return T_COSE_ERR_INVALID_ARGUMENT;
}

/* Map the algorithm ID */
psa_alg = cose_hmac_alg_id_to_psa(cose_alg_id);
if(!PSA_ALG_IS_MAC(psa_alg)) {
return T_COSE_ERR_UNSUPPORTED_HMAC_ALG;
}

/*
* Verify if HMAC algorithm is valid.
* According to COSE (RFC 9053), only SHA-256, SHA-384 and SHA-512 are
* supported in HMAC.
*/
if((psa_alg != PSA_ALG_HMAC(PSA_ALG_SHA_256)) &&
(psa_alg != PSA_ALG_HMAC(PSA_ALG_SHA_384)) &&
(psa_alg != PSA_ALG_HMAC(PSA_ALG_SHA_512))) {
return T_COSE_ERR_UNSUPPORTED_HMAC_ALG;
if(hmac_ctx->status != PSA_SUCCESS) {
/* Error state. Nothing to do */
goto done;
}

hmac_ctx->op_ctx = psa_mac_operation_init();
hmac_ctx->status = psa_mac_sign_finish(&hmac_ctx->op_ctx,
tag_buf.ptr,
tag_buf.len,
&(tag->len));
tag->ptr = tag_buf.ptr;

psa_ret = psa_mac_verify_setup(&hmac_ctx->op_ctx,
(psa_key_id_t)validation_key.key.handle,
psa_alg);

return psa_status_to_t_cose_error_hmac(psa_ret);
done:
return psa_status_to_t_cose_error_hmac(hmac_ctx->status);
}


/*
* See documentation in t_cose_crypto.h
/* The PSA API for MAC validation is not used because it results
* in larger code size overall and because OSSL doesn't have that
* API. There is no issue with a crypto service API that isolates
* the MAC key in an HSM or such by making this choice. It is still
* possible to to do. The MAC tag is a public value so it doesn't
* need to in the HSM.
*/
enum t_cose_err_t
t_cose_crypto_hmac_validate_finish(struct t_cose_crypto_hmac *hmac_ctx,
struct q_useful_buf_c tag)
{
psa_status_t psa_ret;

if(!hmac_ctx) {
return T_COSE_ERR_INVALID_ARGUMENT;
}

psa_ret = psa_mac_verify_finish(&hmac_ctx->op_ctx, tag.ptr, tag.len);

return psa_status_to_t_cose_error_hmac(psa_ret);
}


enum t_cose_err_t
Expand Down
36 changes: 7 additions & 29 deletions crypto_adapters/t_cose_test_crypto.c
Original file line number Diff line number Diff line change
Expand Up @@ -301,57 +301,35 @@ t_cose_crypto_hash_finish(struct t_cose_crypto_hash *hash_ctx,


enum t_cose_err_t
t_cose_crypto_hmac_compute_setup(struct t_cose_crypto_hmac *hmac_ctx,
struct t_cose_key signing_key,
const int32_t cose_alg_id)
t_cose_crypto_hmac_setup(struct t_cose_crypto_hmac *hmac_ctx,
struct t_cose_key signing_key,
const int32_t cose_alg_id)
{
(void)hmac_ctx;
(void)signing_key;
(void)cose_alg_id;
return T_COSE_ERR_UNSUPPORTED_SIGNING_ALG;
}

enum t_cose_err_t
void
t_cose_crypto_hmac_update(struct t_cose_crypto_hmac *hmac_ctx,
struct q_useful_buf_c payload)
{
(void)hmac_ctx;
(void)payload;
return T_COSE_ERR_UNSUPPORTED_SIGNING_ALG;
}

enum t_cose_err_t
t_cose_crypto_hmac_compute_finish(struct t_cose_crypto_hmac *hmac_ctx,
struct q_useful_buf tag_buf,
struct q_useful_buf_c *tag)
t_cose_crypto_hmac_finish(struct t_cose_crypto_hmac *hmac_ctx,
struct q_useful_buf tag_buf,
struct q_useful_buf_c *tag)
{
(void)hmac_ctx;
(void)tag_buf;
(void)tag;
return T_COSE_ERR_UNSUPPORTED_SIGNING_ALG;
}

enum t_cose_err_t
t_cose_crypto_hmac_validate_setup(struct t_cose_crypto_hmac *hmac_ctx,
const int32_t cose_alg_id,
struct t_cose_key validation_key)
{
(void)hmac_ctx;
(void)cose_alg_id;
(void)validation_key;
return T_COSE_ERR_UNSUPPORTED_SIGNING_ALG;
}

enum t_cose_err_t
t_cose_crypto_hmac_validate_finish(struct t_cose_crypto_hmac *hmac_ctx,
struct q_useful_buf_c tag)
{
(void)hmac_ctx;
(void)tag;
return T_COSE_ERR_UNSUPPORTED_SIGNING_ALG;
}



/*
* See documentation in t_cose_crypto.h
Expand Down
14 changes: 0 additions & 14 deletions inc/t_cose/t_cose_common.h
Original file line number Diff line number Diff line change
Expand Up @@ -250,20 +250,6 @@ enum t_cose_key_usage_flags {
};



/* Private value. Intentionally not documented for Doxygen.
* This is the size allocated for the encoded protected headers. It
* needs to be big enough for make_protected_header() to succeed. It
* currently sized for one header with an algorithm ID up to 32 bits
* long -- one byte for the wrapping map, one byte for the label, 5
* bytes for the ID. If this is made accidentially too small, QCBOR will
* only return an error, and not overrun any buffers.
*
* 9 extra bytes are added, rounding it up to 16 total, in case some
* other protected header is to be added.
*/
#define T_COSE_MAC0_MAX_SIZE_PROTECTED_PARAMETERS (1 + 1 + 5 + 9)

/* Six: an alg id, a kid, an iv, a content type, one custom, crit list
* or: 2 alg IDs, an IV, a kid, a supp_pub_info, one custom. If
* this is not enough use t_cose_encrypt_add_param_storage() or
Expand Down
4 changes: 1 addition & 3 deletions inc/t_cose/t_cose_mac_compute.h
Original file line number Diff line number Diff line change
Expand Up @@ -23,12 +23,10 @@ extern "C" {
/**
* This is the context for creating a \c COSE_Mac 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.
* about 72 bytes so it fits easily on the stack.
*/
struct t_cose_mac_calculate_ctx {
/* Private data structure */
uint8_t protected_parameters_buffer[
T_COSE_MAC0_MAX_SIZE_PROTECTED_PARAMETERS];
struct q_useful_buf_c protected_parameters; /* The encoded protected parameters */
int32_t cose_algorithm_id;
struct t_cose_key mac_key;
Expand Down
2 changes: 2 additions & 0 deletions inc/t_cose/t_cose_standard_constants.h
Original file line number Diff line number Diff line change
Expand Up @@ -742,4 +742,6 @@
*/
#define COSE_MAC_CONTEXT_STRING_MAC0 "MAC0"

#define COSE_MAC_CONTEXT_STRING_MAC "MAC"

#endif /* __T_COSE_STANDARD_CONSTANTS_H__ */
Loading

0 comments on commit 1eeef3b

Please sign in to comment.