t_cose
Loading...
Searching...
No Matches
t_cose_sign1_verify.h File Reference

Verify a COSE_Sign1 Message. More...

#include <stdint.h>
#include <stdbool.h>
#include "t_cose/q_useful_buf.h"
#include "t_cose/t_cose_common.h"
#include "qcbor/qcbor_common.h"

Go to the source code of this file.

Data Structures

struct  t_cose_parameters
 
struct  t_cose_sign1_verify_ctx
 

Macros

#define T_COSE_UNSET_ALGORITHM_ID   0
 
#define T_COSE_OPT_ALLOW_SHORT_CIRCUIT   0x00000001
 
#define T_COSE_OPT_REQUIRE_KID   0x00000002
 
#define T_COSE_OPT_TAG_REQUIRED   0x00000004
 
#define T_COSE_OPT_TAG_PROHIBITED   0x00000010
 
#define T_COSE_OPT_DECODE_ONLY   0x00000008
 
#define T_COSE_OPT_UNKNOWN_CRIT_ALLOWED   0x00000020
 
#define T_COSE_MAX_TAGS_TO_RETURN   4
 

Functions

static void t_cose_sign1_verify_init (struct t_cose_sign1_verify_ctx *context, uint32_t option_flags)
 Initialize for COSE_Sign1 message verification.
 
static void t_cose_sign1_set_verification_key (struct t_cose_sign1_verify_ctx *context, struct t_cose_key verification_key)
 Set key for COSE_Sign1 message verification.
 
static void t_cose_sign1_verify_set_auxiliary_buffer (struct t_cose_sign1_verify_ctx *context, struct q_useful_buf auxiliary_buffer)
 Configure a buffer used to serialize the Sig_Structure.
 
static size_t t_cose_sign1_verify_auxiliary_buffer_size (struct t_cose_sign1_verify_ctx *context)
 Get the required auxiliary buffer size for the most recent verification operation.
 
static enum t_cose_err_t t_cose_sign1_verify (struct t_cose_sign1_verify_ctx *context, struct q_useful_buf_c sign1, struct q_useful_buf_c *payload, struct t_cose_parameters *parameters)
 Verify a COSE_Sign1.
 
static enum t_cose_err_t t_cose_sign1_verify_aad (struct t_cose_sign1_verify_ctx *context, struct q_useful_buf_c sign1, struct q_useful_buf_c aad, struct q_useful_buf_c *payload, struct t_cose_parameters *parameters)
 Verify a COSE_Sign1 with Additional Authenticated Data.
 
static enum t_cose_err_t t_cose_sign1_verify_detached (struct t_cose_sign1_verify_ctx *context, struct q_useful_buf_c cose_sign1, struct q_useful_buf_c aad, struct q_useful_buf_c detached_payload, struct t_cose_parameters *parameters)
 Verify a COSE_Sign1 with detached payload.
 
static uint64_t t_cose_sign1_get_nth_tag (const struct t_cose_sign1_verify_ctx *context, size_t n)
 Return unprocessed tags from most recent signature verify.
 
enum t_cose_err_t t_cose_sign1_verify_internal (struct t_cose_sign1_verify_ctx *me, struct q_useful_buf_c sign1, struct q_useful_buf_c aad, struct q_useful_buf_c *payload, struct t_cose_parameters *parameters, bool is_detached)
 Semi-private function to verify a COSE_Sign1.
 

Detailed Description

Verify a COSE_Sign1 Message.

This verifies a COSE_Sign1 message in compliance with [COSE (RFC 8152)] (https://tools.ietf.org/html/rfc8152). A COSE_Sign1 message is a CBOR encoded binary blob that contains header parameters, a payload and a signature. Usually the signature is made with an EC signing algorithm like ECDSA.

This implementation is intended to be small and portable to different OS's and platforms. Its dependencies are:

  • QCBOR
  • <stdint.h>, <string.h>, <stddef.h>
  • Hash functions like SHA-256
  • Signing functions like ECDSA

There is a cryptographic adaptation layer defined in t_cose_crypto.h. An implementation can be made of the functions in it for different cryptographic libraries. This means that different integrations with different cryptographic libraries may support only signing with a particular set of algorithms. Integration with OpenSSL is supported. Key ID look up also varies by different cryptographic library integrations.

See t_cose_common.h for preprocessor defines to reduce object code and stack use by disabling features.

Macro Definition Documentation

◆ T_COSE_MAX_TAGS_TO_RETURN

#define T_COSE_MAX_TAGS_TO_RETURN   4

The maximum number of unprocessed tags that can be returned by t_cose_sign1_get_nth_tag(). The CWT tag is an example of the tags that might returned. The COSE tags that are processed, don't count here.

◆ T_COSE_OPT_ALLOW_SHORT_CIRCUIT

#define T_COSE_OPT_ALLOW_SHORT_CIRCUIT   0x00000001

Pass this as 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 T_COSE_OPT_SHORT_CIRCUIT_SIG.

◆ T_COSE_OPT_DECODE_ONLY

#define T_COSE_OPT_DECODE_ONLY   0x00000008

See t_cose_sign1_set_verification_key().

This option disables cryptographic signature verification. With this option the verification_key is not needed. This is useful to decode the COSE_Sign1 message to get the kid (key ID). The verification key can be looked up or otherwise obtained by the caller. Once the key in in hand, t_cose_sign1_verify() can be called again to perform the full verification.

The payload will always be returned whether this is option is given or not, but it should not be considered secure when this option is given.

◆ T_COSE_OPT_REQUIRE_KID

#define T_COSE_OPT_REQUIRE_KID   0x00000002

The error 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 verification key is determined by other than the kid, then it is fine if there is no kid.

◆ T_COSE_OPT_TAG_PROHIBITED

#define T_COSE_OPT_TAG_PROHIBITED   0x00000010

Normally this will decode the CBOR presented as a COSE_Sign1 message whether it is tagged using QCBOR tagging as such or not. If this option is set, then T_COSE_ERR_INCORRECTLY_TAGGED is returned if a CBOR_TAG_COSE_SIGN1 tag. When this option is set the caller knows for certain that a COSE signed message is expected.

See discussion on T_COSE_OPT_TAG_REQUIRED.

◆ T_COSE_OPT_TAG_REQUIRED

#define T_COSE_OPT_TAG_REQUIRED   0x00000004

Normally this will decode the CBOR presented as a COSE_Sign1 message whether it is tagged using QCBOR tagging as such or not. If this option is set, then T_COSE_ERR_INCORRECTLY_TAGGED is returned if it is not a CBOR_TAG_COSE_SIGN1 tag.

See also T_COSE_OPT_TAG_PROHIBITED. If neither this or T_COSE_OPT_TAG_PROHIBITED is set then the content can either be COSE message (COSE_Sign1 CDDL from RFC 8152) or a COSESign1 tagg (COSE_Sign1_Tagged from RFC 8152).

See t_cose_sign1_get_nth_tag() to get further tags that enclose the COSE message.

◆ T_COSE_OPT_UNKNOWN_CRIT_ALLOWED

#define T_COSE_OPT_UNKNOWN_CRIT_ALLOWED   0x00000020

This option disables verification that critical header parameters are known.

Without this flag set, an error is raised during verification if there is an unknown header parameter in the critical header parameters list. However, if this flag is set then that part of verification is skipped.

◆ T_COSE_UNSET_ALGORITHM_ID

#define T_COSE_UNSET_ALGORITHM_ID   0

A special COSE algorithm ID that indicates no COSE algorithm ID or an unset COSE algorithm ID.

Function Documentation

◆ t_cose_sign1_get_nth_tag()

static uint64_t t_cose_sign1_get_nth_tag ( const struct t_cose_sign1_verify_ctx * context,
size_t n )
inlinestatic

Return unprocessed tags from most recent signature verify.

Parameters
[in]contextThe t_cose signature verification context.
[in]nIndex of the tag to return.
Returns
The tag value or CBOR_TAG_INVALID64 if there is no tag at the index or the index is too large.

The 0th tag is the one for which the COSE message is the content. Loop from 0 up until CBOR_TAG_INVALID64 is returned. The maximum is T_COSE_MAX_TAGS_TO_RETURN.

It will be necessary to call this for a general implementation of a CWT since sometimes the CWT tag is required. This is also needed for recursive processing of nested COSE signing and/or encryption.

◆ t_cose_sign1_set_verification_key()

static void t_cose_sign1_set_verification_key ( struct t_cose_sign1_verify_ctx * context,
struct t_cose_key verification_key )
inlinestatic

Set key for COSE_Sign1 message verification.

Parameters
[in,out]contextThe t_cose signature verification context.
[in]verification_keyThe verification key to use.

There are four ways that the verification key is found and supplied to t_cose so that t_cose_sign1_verify() succeeds.

  1. Look up by kid parameter and set by t_cose_sign1_set_verification_key()
  2. Look up by other and set by t_cose_sign1_set_verification_key()
  3. Determination by kid that short circuit signing is used (test only)
  4. Look up by kid parameter in cryptographic adaptation layer

Note that there is no means where certificates, like X.509 certificates, are provided in the COSE parameters. Perhaps there will be in the future but that is not in common use or supported by this implementation.

To use 1, it is necessary to call t_cose_sign1_verify_init() and t_cose_sign1_verify() twice. The first time t_cose_sign1_verify_init() is called, give the T_COSE_OPT_DECODE_ONLY option. Then call t_cose_sign1_verify() and the kid will be returned in parameters. The caller finds the kid on their own. Then call this to set the key. Last call t_cose_sign1_verify(), again without the T_COSE_OPT_DECODE_ONLY option.

To use 2, the key is somehow determined without the kid and t_cose_sign1_set_verification_key() is called with it. Then t_cose_sign1_verify() is called. Note that this implementation cannot return non-standard header parameters, at least not yet.

To use 3, initialize with T_COSE_OPT_ALLOW_SHORT_CIRCUIT. No call to t_cose_sign1_set_verification_key() is necessary. If you do call t_cose_sign1_set_verification_key(), the kid for short circuit signing will be recognized and the set key will be ignored.

To use 4, first be sure that the cryptographic adapter supports look up by kid. There's no API to determine this, so it is probably determined by other system documentation (aka source code). In this mode, all that is necessary is to call t_cose_sign1_verify().

3 always works no matter what is done in the cryptographic adaptation layer because it never calls out to it. The OpenSSL adaptor supports 1 and 2.

◆ t_cose_sign1_verify()

static enum t_cose_err_t t_cose_sign1_verify ( struct t_cose_sign1_verify_ctx * context,
struct q_useful_buf_c sign1,
struct q_useful_buf_c * payload,
struct t_cose_parameters * parameters )
inlinestatic

Verify a COSE_Sign1.

Parameters
[in,out]contextThe t_cose signature verification context.
[in]sign1Pointer and length of CBOR encoded COSE_Sign1 message that is to be verified.
[out]payloadPointer and length of the payload.
[out]parametersPlace to return parsed parameters. May be NULL.
Returns
This returns one of the error codes defined by t_cose_err_t.

See t_cose_sign1_set_verification_key() for discussion on where the verification key comes from.

Verification involves the following steps.

  • The CBOR-format COSE_Sign1 structure is parsed. This makes sure COSE_Sign1 is valid CBOR and follows the required structure for COSE_Sign1.
  • The protected header parameters are decoded, particular the algorithm id.
  • The unprotected headers parameters are decoded, particularly the kid.
  • The payload is identified. The internals of the payload are not decoded.
  • The expected hash, the "to-be-signed" bytes are computed. The hash algorithm used comes from the signing algorithm. If the algorithm is unknown or not supported this will error out.
  • Finally, the signature verification is performed.

If verification is successful, the pointer to the CBOR-encoded payload is returned. The parameters are returned if requested. All pointers returned are to memory in the sign1 passed in.

Note that this only handles standard COSE header parameters. There are no facilities for custom header parameters, even though they are allowed by the COSE standard.

This will recognize the special key ID for short-circuit signing and verify it if the T_COSE_OPT_ALLOW_SHORT_CIRCUIT is set.

Indefinite length CBOR strings are not supported by this implementation. T_COSE_ERR_SIGN1_FORMAT will be returned if they are in the input COSE_Sign1 messages. For example, if the payload is an indefinite-length byte string, this error will be returned.

◆ t_cose_sign1_verify_aad()

static enum t_cose_err_t t_cose_sign1_verify_aad ( struct t_cose_sign1_verify_ctx * context,
struct q_useful_buf_c sign1,
struct q_useful_buf_c aad,
struct q_useful_buf_c * payload,
struct t_cose_parameters * parameters )
inlinestatic

Verify a COSE_Sign1 with Additional Authenticated Data.

Parameters
[in,out]contextThe t_cose signature verification context.
[in]sign1Pointer and length of CBOR encoded COSE_Sign1 message that is to be verified.
[in]aadThe Additional Authenticated Data or NULL_Q_USEFUL_BUF_C.
[out]payloadPointer and length of the payload.
[out]parametersPlace to return parsed parameters. May be NULL.
Returns
This returns one of the error codes defined by t_cose_err_t.

This is just like t_cose_sign1_verify(), but allows passing AAD (Additional Authenticated Data) for verification.

AAD is some additional bytes that are covered by the signature in addition to the payload. They may be any bytes, but are often some options or commands that are sent along with the COSE_Sign1. If a COSE_Sign1 was created with AAD, that AAD must be passed in here to successfully verify the signature. If it is not, a T_COSE_ERR_SIG_VERIFY will occur. There is no indication in the COSE_Sign1 to know whether there was AAD input when it was created. It has to be known by context.

Calling this with aad as NULL_Q_USEFUL_BUF_C is the same as calling t_cose_sign1_verify().

◆ t_cose_sign1_verify_auxiliary_buffer_size()

static size_t t_cose_sign1_verify_auxiliary_buffer_size ( struct t_cose_sign1_verify_ctx * context)
inlinestatic

Get the required auxiliary buffer size for the most recent verification operation.

Parameters
[in,out]contextThe t_cose signature verification context.
Returns
The number of bytes of auxiliary buffer used by the most recent verification operation.

This function can be called after t_cose_sign1_verify (or equivalent) was called. If the context was initialized with the DECODE_ONLY flag, it returns the number of bytes that would have been used by the signing operation. This allows the caller to allocate an appropriately sized buffer before performing the actual verification.

This function returns zero if the signature algorithm used does not need an auxiliary buffer.

◆ t_cose_sign1_verify_detached()

static enum t_cose_err_t t_cose_sign1_verify_detached ( struct t_cose_sign1_verify_ctx * context,
struct q_useful_buf_c cose_sign1,
struct q_useful_buf_c aad,
struct q_useful_buf_c detached_payload,
struct t_cose_parameters * parameters )
inlinestatic

Verify a COSE_Sign1 with detached payload.

Parameters
[in,out]contextThe t_cose signature verification context.
[in]cose_sign1Pointer and length of CBOR encoded COSE_Sign1 message that is to be verified.
[in]aadThe Additional Authenticated Data or NULL_Q_USEFUL_BUF_C.
[in]detached_payloadPointer and length of the payload.
[out]parametersPlace to return parsed parameters. May be NULL.
Returns
This returns one of the error codes defined by t_cose_err_t.

A detached payload is one that is not inside the COSE_Sign1, but is conveyed separately. It is still covered by the signature exactly as if it was the payload inside the COSE_Sign1.

This function is the same as t_cose_sign1_verify_aad(), but for use with a detached payload. Instead of the payload being returned, it must be passed in as it must have arrived separately from the COSE_Sign1. The signature covers it so it must be passed in to complete the verification.

aad may be NULL_Q_USEFUL_BUF_C if there is no AAD.

◆ t_cose_sign1_verify_init()

static void t_cose_sign1_verify_init ( struct t_cose_sign1_verify_ctx * context,
uint32_t option_flags )
inlinestatic

Initialize for COSE_Sign1 message verification.

Parameters
[in,out]contextThe context to initialize.
[in]option_flagsOptions controlling the verification.

This must be called before using the verification context.

◆ t_cose_sign1_verify_internal()

enum t_cose_err_t t_cose_sign1_verify_internal ( struct t_cose_sign1_verify_ctx * me,
struct q_useful_buf_c sign1,
struct q_useful_buf_c aad,
struct q_useful_buf_c * payload,
struct t_cose_parameters * parameters,
bool is_detached )

Semi-private function to verify a COSE_Sign1.

Parameters
[in,out]meThe t_cose signature verification context.
[in]sign1Pointer and length of CBOR encoded COSE_Sign1 message that is to be verified.
[in]aadThe Additional Authenticated Data or NULL_Q_USEFUL_BUF_C.
[in,out]payloadPointer and length of the payload.
[out]parametersPlace to return parsed parameters. May be NULL.
[in]is_detachedIndicates the payload is detached.
Returns
This returns one of the error codes defined by t_cose_err_t.

This does the work for t_cose_sign1_verify(), t_cose_sign1_verify_aad() and t_cose_sign1_verify_detached(). It is a semi-private function which means its interface isn't guaranteed so it should not to call it directly.

◆ t_cose_sign1_verify_set_auxiliary_buffer()

static void t_cose_sign1_verify_set_auxiliary_buffer ( struct t_cose_sign1_verify_ctx * context,
struct q_useful_buf auxiliary_buffer )
inlinestatic

Configure a buffer used to serialize the Sig_Structure.

Parameters
[in,out]contextThe t_cose signature verification context.
[in]auxiliary_bufferThe auxiliary buffer to be used.

Some signature algorithms (namely EdDSA), require two passes over their input. In order to achieve this, the library needs to serialize a temporary to-be-signed structure into an auxiliary buffer. This function allows the user to configure such a buffer.

The buffer must be big enough to accomodate the Sig_Structure type, which is roughly the sum of sizes of the encoded protected parameters, aad and payload, along with a few dozen bytes of overhead.

To compute the exact size needed, initialize the context with the T_COSE_OPT_DECODE_ONLY option, and call the t_cose_sign1_verify (or similar). After the message decoding, the necessary auxiliary buffer size is available by calling t_cose_sign1_verify_auxiliary_buffer_size.