[release/3.x] Cherry pick: Update t_cose to version 1.1. (#4564) (#4568)

This commit is contained in:
github-actions[bot] 2022-11-16 19:06:54 +00:00 коммит произвёл GitHub
Родитель 2253a8d89f
Коммит 9afb0209b8
Не найден ключ, соответствующий данной подписи
Идентификатор ключа GPG: 4AEE18F83AFDEB23
35 изменённых файлов: 2988 добавлений и 778 удалений

1
3rdparty/exported/t_cose/CMakeLists.txt поставляемый
Просмотреть файл

@ -66,6 +66,7 @@ set(T_COSE_SRC_COMMON
src/t_cose_parameters.c
src/t_cose_sign1_verify.c
src/t_cose_util.c
src/t_cose_short_circuit.c
)
find_package(QCBOR REQUIRED)

9
3rdparty/exported/t_cose/Makefile.ossl поставляемый
Просмотреть файл

@ -62,7 +62,7 @@ INC=-I inc -I test -I src
ALL_INC=$(INC) $(CRYPTO_INC) $(QCBOR_INC)
CFLAGS=$(CMD_LINE) $(ALL_INC) $(C_OPTS) $(TEST_CONFIG_OPTS) $(CRYPTO_CONFIG_OPTS)
SRC_OBJ=src/t_cose_sign1_verify.o src/t_cose_sign1_sign.o src/t_cose_util.o src/t_cose_parameters.o
SRC_OBJ=src/t_cose_sign1_verify.o src/t_cose_sign1_sign.o src/t_cose_util.o src/t_cose_parameters.o src/t_cose_short_circuit.o
.PHONY: all install install_headers install_so uninstall clean
@ -122,9 +122,10 @@ PUBLIC_INTERFACE=inc/t_cose/t_cose_common.h inc/t_cose/t_cose_sign1_sign.h inc/t
# ---- source dependecies -----
src/t_cose_util.o: src/t_cose_util.h src/t_cose_standard_constants.h inc/t_cose/t_cose_common.h src/t_cose_crypto.h
src/t_cose_sign1_verify.o: inc/t_cose/t_cose_sign1_verify.h src/t_cose_crypto.h src/t_cose_util.h src/t_cose_parameters.h inc/t_cose/t_cose_common.h src/t_cose_standard_constants.h
src/t_cose_sign1_verify.o: inc/t_cose/t_cose_sign1_verify.h src/t_cose_crypto.h src/t_cose_util.h src/t_cose_parameters.h inc/t_cose/t_cose_common.h src/t_cose_standard_constants.h src/t_cose_short_circuit.h
src/t_cose_parameters.o: src/t_cose_parameters.h src/t_cose_standard_constants.h inc/t_cose/t_cose_sign1_verify.h inc/t_cose/t_cose_common.h
src/t_cose_sign1_sign.o: inc/t_cose/t_cose_sign1_sign.h src/t_cose_standard_constants.h src/t_cose_crypto.h src/t_cose_util.h inc/t_cose/t_cose_common.h
src/t_cose_sign1_sign.o: inc/t_cose/t_cose_sign1_sign.h src/t_cose_standard_constants.h src/t_cose_crypto.h src/t_cose_util.h inc/t_cose/t_cose_common.h src/t_cose_short_circuit.h
src/t_cose_short_circuit.o: src/t_cose_short_circuit.h src/t_cose_standard_constants.h src/t_cose_crypto.h
# ---- test dependencies -----
@ -132,7 +133,7 @@ test/t_cose_test.o: test/t_cose_test.h test/t_cose_make_test_messages.h src/t_co
test/t_cose_sign_verify_test.o: test/t_cose_sign_verify_test.h test/t_cose_make_test_messages.h src/t_cose_crypto.h test/t_cose_make_test_pub_key.h $(PUBLIC_INTERFACE)
test/t_cose_make_test_messages.o: test/t_cose_make_test_messages.h inc/t_cose/t_cose_sign1_sign.h inc/t_cose/t_cose_common.h src/t_cose_standard_constants.h src/t_cose_crypto.h src/t_cose_util.h
test/run_test.o: test/run_test.h test/t_cose_test.h test/t_cose_hash_fail_test.h
test/t_cose_make_openssl_test_key.o: test/t_cose_make_test_pub_key.h src/t_cose_standard_constants.h inc/t_cose/t_cose_common.h
test/t_cose_make_openssl_test_key.o: test/t_cose_make_test_pub_key.h test/t_cose_rsa_test_key.h src/t_cose_standard_constants.h inc/t_cose/t_cose_common.h
# ---- crypto dependencies ----
crypto_adapters/t_cose_openssl_crypto.o: src/t_cose_crypto.h inc/t_cose/t_cose_common.h src/t_cose_standard_constants.h inc/t_cose/q_useful_buf.h

9
3rdparty/exported/t_cose/Makefile.psa поставляемый
Просмотреть файл

@ -64,7 +64,7 @@ INC=-I inc -I test -I src
ALL_INC=$(INC) $(CRYPTO_INC) $(QCBOR_INC)
CFLAGS=$(CMD_LINE) $(ALL_INC) $(C_OPTS) $(TEST_CONFIG_OPTS) $(CRYPTO_CONFIG_OPTS)
SRC_OBJ=src/t_cose_sign1_verify.o src/t_cose_sign1_sign.o src/t_cose_util.o src/t_cose_parameters.o
SRC_OBJ=src/t_cose_sign1_verify.o src/t_cose_sign1_sign.o src/t_cose_util.o src/t_cose_parameters.o src/t_cose_short_circuit.o
.PHONY: all install install_headers install_so uninstall clean
@ -124,9 +124,10 @@ PUBLIC_INTERFACE=inc/t_cose/t_cose_common.h inc/t_cose/t_cose_sign1_sign.h inc/t
# ---- source dependecies -----
src/t_cose_util.o: src/t_cose_util.h src/t_cose_standard_constants.h inc/t_cose/t_cose_common.h src/t_cose_crypto.h
src/t_cose_sign1_verify.o: inc/t_cose/t_cose_sign1_verify.h src/t_cose_crypto.h src/t_cose_util.h src/t_cose_parameters.h inc/t_cose/t_cose_common.h src/t_cose_standard_constants.h
src/t_cose_sign1_verify.o: inc/t_cose/t_cose_sign1_verify.h src/t_cose_crypto.h src/t_cose_util.h src/t_cose_parameters.h inc/t_cose/t_cose_common.h src/t_cose_standard_constants.h src/t_cose_short_circuit.h
src/t_cose_parameters.o: src/t_cose_parameters.h src/t_cose_standard_constants.h inc/t_cose/t_cose_sign1_verify.h inc/t_cose/t_cose_common.h
src/t_cose_sign1_sign.o: inc/t_cose/t_cose_sign1_sign.h src/t_cose_standard_constants.h src/t_cose_crypto.h src/t_cose_util.h inc/t_cose/t_cose_common.h
src/t_cose_sign1_sign.o: inc/t_cose/t_cose_sign1_sign.h src/t_cose_standard_constants.h src/t_cose_crypto.h src/t_cose_util.h inc/t_cose/t_cose_common.h src/t_cose_short_circuit.h
src/t_cose_short_circuit.o: src/t_cose_short_circuit.h src/t_cose_standard_constants.h src/t_cose_crypto.h
# ---- test dependencies -----
@ -134,7 +135,7 @@ test/t_cose_test.o: test/t_cose_test.h test/t_cose_make_test_messages.h src/t_co
test/t_cose_sign_verify_test.o: test/t_cose_sign_verify_test.h test/t_cose_make_test_messages.h src/t_cose_crypto.h test/t_cose_make_test_pub_key.h $(PUBLIC_INTERFACE)
test/t_cose_make_test_messages.o: test/t_cose_make_test_messages.h inc/t_cose/t_cose_sign1_sign.h inc/t_cose/t_cose_common.h src/t_cose_standard_constants.h src/t_cose_crypto.h src/t_cose_util.h
test/run_test.o: test/run_test.h test/t_cose_test.h test/t_cose_hash_fail_test.h
test/t_cose_make_psa_test_key.o: test/t_cose_make_test_pub_key.h src/t_cose_standard_constants.h inc/t_cose/t_cose_common.h
test/t_cose_make_psa_test_key.o: test/t_cose_make_test_pub_key.h test/t_cose_rsa_test_key.h src/t_cose_standard_constants.h inc/t_cose/t_cose_common.h
# ---- crypto dependencies ----
crypto_adapters/t_cose_psa_crypto.o: src/t_cose_crypto.h inc/t_cose/t_cose_common.h src/t_cose_standard_constants.h inc/t_cose/q_useful_buf.h

9
3rdparty/exported/t_cose/Makefile.test поставляемый
Просмотреть файл

@ -43,10 +43,10 @@ TEST_OBJ=test/t_cose_test.o test/run_tests.o test/t_cose_make_test_messages.o $(
# ---- the main body that is invariant ----
INC=-I inc -I test -I src
ALL_INC=$(CRYPTO_INC) $(QCBOR_INC) $(INC)
ALL_INC=$(INC) $(CRYPTO_INC) $(QCBOR_INC)
CFLAGS=$(CMD_LINE) $(ALL_INC) $(C_OPTS) $(TEST_CONFIG_OPTS) $(CRYPTO_CONFIG_OPTS)
SRC_OBJ=src/t_cose_sign1_verify.o src/t_cose_sign1_sign.o src/t_cose_util.o src/t_cose_parameters.o
SRC_OBJ=src/t_cose_sign1_verify.o src/t_cose_sign1_sign.o src/t_cose_util.o src/t_cose_parameters.o src/t_cose_short_circuit.o
.PHONY: all clean
@ -72,9 +72,10 @@ PUBLIC_INTERFACE=inc/t_cose/t_cose_common.h inc/t_cose/t_cose_sign1_sign.h inc/t
# ---- source dependecies -----
src/t_cose_util.o: src/t_cose_util.h src/t_cose_standard_constants.h inc/t_cose/t_cose_common.h src/t_cose_crypto.h
src/t_cose_sign1_verify.o: inc/t_cose/t_cose_sign1_verify.h src/t_cose_crypto.h src/t_cose_util.h src/t_cose_parameters.h inc/t_cose/t_cose_common.h src/t_cose_standard_constants.h
src/t_cose_sign1_verify.o: inc/t_cose/t_cose_sign1_verify.h src/t_cose_crypto.h src/t_cose_util.h src/t_cose_parameters.h inc/t_cose/t_cose_common.h src/t_cose_standard_constants.h src/t_cose_short_circuit.h
src/t_cose_parameters.o: src/t_cose_parameters.h src/t_cose_standard_constants.h inc/t_cose/t_cose_sign1_verify.h inc/t_cose/t_cose_common.h
src/t_cose_sign1_sign.o: inc/t_cose/t_cose_sign1_sign.h src/t_cose_standard_constants.h src/t_cose_crypto.h src/t_cose_util.h inc/t_cose/t_cose_common.h
src/t_cose_sign1_sign.o: inc/t_cose/t_cose_sign1_sign.h src/t_cose_standard_constants.h src/t_cose_crypto.h src/t_cose_util.h inc/t_cose/t_cose_common.h src/t_cose_short_circuit.h
src/t_cose_short_circuit.o: src/t_cose_short_circuit.h src/t_cose_standard_constants.h src/t_cose_crypto.h
# ---- test dependencies -----

17
3rdparty/exported/t_cose/README.md поставляемый
Просмотреть файл

@ -97,8 +97,9 @@ To build run:
#### OpenSSL Crypto -- Makefile.ossl
This OpenSSL integration supports SHA-256, SHA-384 and SHA-512 with
ECDSA to support the COSE algorithms ES256, ES384 and ES512. It is a
full and tested integration with OpenSSL crypto.
ECDSA, EdDSA, or RSAPSS to support the COSE algorithms ES256, ES384 and
ES512, PS256, PS384 and PS512. It is a full and tested integration
with OpenSSL crypto.
If OpenSSL is installed in /usr/local or as a standar library, you can
probably just run make:
@ -139,8 +140,9 @@ test coverage, but the code should handle them all correctly.
As of March 2022, t_cose works with the PSA 1.0 Crypto API as
implemented by Mbed TLS 2.x and 3.x.
This integration supports SHA-256, SHA-384 and SHA-512 with ECDSA to
support the COSE algorithms ES256, ES384 and ES512.
This integration supports SHA-256, SHA-384 and SHA-512 with
ECDSA, EdDSA or RSAPSS to support the COSE algorithms ES256, ES384 and
ES512, PS256, PS384 and PS512.
If Mbed TLS is installed in /usr/local, you can probably just run
make:
@ -273,10 +275,6 @@ In addition to the above memory usage, the crypto library will use
some stack and/or heap memory. This will vary quite a bit by crypto
library. Some may use malloc. Some may not.
So far no support for RSA is available, but since the keys and
signatures are much bigger, implementing it will increase stack and
memory usage substantially.
The OpenSSL library does use malloc, even with ECDSA. Another
implementation of ECDSA might not use malloc, as the keys are small
enough.
@ -299,14 +297,13 @@ just have different names.
been assigned by IANA.
* No way to add custom headers when creating signed messages or
process them during verification.
* Only ECDSA is supported so far (facilities are available to add
others).
* Does not handle CBOR indefinite length strings (indefinite length
maps and arrays are handled).
* Counter signatures are not supported.
## Credit
* Paul Liétar for RSA PSS (PS256..PS512) and EdDSA
* Maik Riechert for cmake, CI and other.
* Ken Takayama for the bulk of the detached content implementation.
* Tamas Ban for lots code review comments, design ideas and porting to ARM PSA.

Просмотреть файл

@ -14,10 +14,10 @@
#include "t_cose_crypto.h" /* The interface this code implements */
#include <openssl/ecdsa.h> /* Needed for signature format conversion */
#include <openssl/rsa.h>
#include <openssl/evp.h>
#include <openssl/err.h>
/**
* \file t_cose_openssl_crypto.c
*
@ -60,9 +60,66 @@
* a llittle.
*/
/*
* See documentation in t_cose_crypto.h
*
* This will typically not be referenced and thus not linked,
* for deployed code. This is mainly used for test.
*/
bool t_cose_crypto_is_algorithm_supported(int32_t cose_algorithm_id)
{
static const int32_t supported_algs[] = {
COSE_ALGORITHM_SHA_256,
COSE_ALGORITHM_SHA_384,
COSE_ALGORITHM_SHA_512,
COSE_ALGORITHM_ES256,
#ifndef T_COSE_DISABLE_ES384
COSE_ALGORITHM_ES384,
#endif
#ifndef T_COSE_DISABLE_ES512
COSE_ALGORITHM_ES512,
#endif
#ifndef T_COSE_DISABLE_PS256
COSE_ALGORITHM_PS256,
#endif
#ifndef T_COSE_DISABLE_PS384
COSE_ALGORITHM_PS384,
#endif
#ifndef T_COSE_DISABLE_PS512
COSE_ALGORITHM_PS512,
#endif
#ifndef T_COSE_DISABLE_EDDSA
COSE_ALGORITHM_EDDSA,
#endif
0 /* List terminator */
};
return t_cose_check_list(cose_algorithm_id, supported_algs);
}
/**
* \brief Convert DER-encoded signature to COSE-serialized signature
* \brief Get the rounded up size of an ECDSA key in bytes.
*/
static unsigned ecdsa_key_size(EVP_PKEY *key_evp)
{
int key_len_bits;
unsigned key_len_bytes;
key_len_bits = EVP_PKEY_bits(key_evp);
/* Calculation of size per RFC 8152 section 8.1 -- round up to
* number of bytes. */
key_len_bytes = (unsigned)key_len_bits / 8;
if(key_len_bits % 8) {
key_len_bytes++;
}
return key_len_bytes;
}
/**
* \brief Convert DER-encoded ECDSA signature to COSE-serialized signature
*
* \param[in] key_len Size of the key in bytes -- governs sig size.
* \param[in] der_signature DER-encoded signature.
@ -77,10 +134,11 @@
* concatenated.
*/
static inline struct q_useful_buf_c
signature_der_to_cose(unsigned key_len,
struct q_useful_buf_c der_signature,
struct q_useful_buf signature_buffer)
ecdsa_signature_der_to_cose(EVP_PKEY *key_evp,
struct q_useful_buf_c der_signature,
struct q_useful_buf signature_buffer)
{
unsigned key_len;
size_t r_len;
size_t s_len;
const BIGNUM *r_bn;
@ -91,6 +149,8 @@ signature_der_to_cose(unsigned key_len,
const unsigned char *temp_der_sig_pointer;
ECDSA_SIG *es;
key_len = ecdsa_key_size(key_evp);
/* Put DER-encode sig into an ECDSA_SIG so we can get the r and s out. */
temp_der_sig_pointer = der_signature.ptr;
es = d2i_ECDSA_SIG(NULL, &temp_der_sig_pointer, (long)der_signature.len);
@ -141,7 +201,7 @@ Done:
/**
* \brief Convert COSE-serialized signature to DER-encoded signature.
* \brief Convert COSE-serialized ECDSA signature to DER-encoded signature.
*
* \param[in] key_len Size of the key in bytes -- governs sig size.
* \param[in] cose_signature The COSE-serialized signature.
@ -161,11 +221,12 @@ Done:
* between the two.
*/
static enum t_cose_err_t
signature_cose_to_der(unsigned key_len,
struct q_useful_buf_c cose_signature,
struct q_useful_buf buffer,
struct q_useful_buf_c *der_signature)
ecdsa_signature_cose_to_der(EVP_PKEY *key_evp,
struct q_useful_buf_c cose_signature,
struct q_useful_buf buffer,
struct q_useful_buf_c *der_signature)
{
unsigned key_len;
enum t_cose_err_t return_value;
BIGNUM *signature_r_bn = NULL;
BIGNUM *signature_s_bn = NULL;
@ -174,6 +235,8 @@ signature_cose_to_der(unsigned key_len,
unsigned char *der_signature_ptr;
int der_signature_len;
key_len = ecdsa_key_size(key_evp);
/* Check the signature length against expected */
if(cose_signature.len != key_len * 2) {
return_value = T_COSE_ERR_SIG_VERIFY;
@ -257,29 +320,20 @@ Done:
return return_value;
}
/**
* \brief Common checks and conversions for signing and verification key.
*
* \param[in] t_cose_key The key to check and convert.
* \param[out] return_ossl_ec_key The OpenSSL key in memory.
* \param[out] return_key_size_in_bytes How big the key is.
*
* \return Error or \ref T_COSE_SUCCESS.
*
* It pulls the OpenSSL key out of \c t_cose_key and checks
* it and figures out the number of bytes in the key rounded up. This
* is also the size of r and s in the signature.
* It pulls the OpenSSL key out of \c t_cose_key and checks it.
*/
static enum t_cose_err_t
key_convert_and_size(struct t_cose_key t_cose_key,
EVP_PKEY **return_ossl_ec_key,
unsigned *return_key_size_in_bytes)
key_convert(struct t_cose_key t_cose_key, EVP_PKEY **return_ossl_ec_key)
{
enum t_cose_err_t return_value;
int key_len_bits; /* type unsigned is conscious choice */
unsigned key_len_bytes; /* type unsigned is conscious choice */
EVP_PKEY *ossl_ec_key;
/* Check the signing key and get it out of the union */
if(t_cose_key.crypto_lib != T_COSE_CRYPTO_LIB_OPENSSL) {
@ -290,19 +344,7 @@ key_convert_and_size(struct t_cose_key t_cose_key,
return_value = T_COSE_ERR_EMPTY_KEY;
goto Done;
}
ossl_ec_key = (EVP_PKEY *)t_cose_key.k.key_ptr;
key_len_bits = EVP_PKEY_bits(ossl_ec_key);
/* Calculation of size per RFC 8152 section 8.1 -- round up to
* number of bytes. */
key_len_bytes = (unsigned)key_len_bits / 8;
if(key_len_bits % 8) {
key_len_bytes++;
}
*return_key_size_in_bytes = key_len_bytes;
*return_ossl_ec_key = ossl_ec_key;
*return_ossl_ec_key = (EVP_PKEY *)t_cose_key.k.key_ptr;
return_value = T_COSE_SUCCESS;
@ -310,7 +352,6 @@ Done:
return return_value;
}
/*
* Public Interface. See documentation in t_cose_crypto.h
*/
@ -319,23 +360,124 @@ enum t_cose_err_t t_cose_crypto_sig_size(int32_t cose_algorithm_id,
size_t *sig_size)
{
enum t_cose_err_t return_value;
unsigned key_len_bytes;
EVP_PKEY *signing_key_evp; /* Unused */
EVP_PKEY *signing_key_evp;
if(!t_cose_algorithm_is_ecdsa(cose_algorithm_id)) {
return_value = T_COSE_ERR_UNSUPPORTED_SIGNING_ALG;
goto Done;
}
return_value = key_convert_and_size(signing_key, &signing_key_evp, &key_len_bytes);
return_value = key_convert(signing_key, &signing_key_evp);
if(return_value != T_COSE_SUCCESS) {
goto Done;
return return_value;
}
/* Double because signature is made of up r and s values */
*sig_size = key_len_bytes * 2;
if(t_cose_algorithm_is_ecdsa(cose_algorithm_id)) {
/* EVP_PKEY_size is not suitable because it returns the size
* of the DER-encoded signature, which is larger than the COSE
* signatures.
*
* We instead compute the size ourselves based on the COSE
* encoding of two r and s values, each the same size as the key.
*/
*sig_size = ecdsa_key_size(signing_key_evp) * 2;
return_value = T_COSE_SUCCESS;
goto Done;
} else if (t_cose_algorithm_is_rsassa_pss(cose_algorithm_id)
|| cose_algorithm_id == T_COSE_ALGORITHM_EDDSA) {
*sig_size = (size_t)EVP_PKEY_size(signing_key_evp);
return_value = T_COSE_SUCCESS;
goto Done;
} else {
return_value = T_COSE_ERR_UNSUPPORTED_SIGNING_ALG;
}
Done:
return return_value;
}
/**
* \brief Configure an EVP_PKEY_CTX for a given algorithm.
*
* \param[in] context The OpenSSL context to configure.
* \param[in] cose_algorithm_id The algorithm ID.
*
* \return Error or \ref T_COSE_SUCCESS.
*/
static enum t_cose_err_t
configure_pkey_context(EVP_PKEY_CTX* context, int32_t cose_algorithm_id)
{
enum t_cose_err_t return_value;
const EVP_MD *md;
int ossl_result;
if (t_cose_algorithm_is_ecdsa(cose_algorithm_id)) {
/* ECDSA doesn't need any further configuration of its context.
* The parameters are inferred from the key.
*/
return_value = T_COSE_SUCCESS;
} else if (t_cose_algorithm_is_rsassa_pss(cose_algorithm_id)) {
/**
* These parameters are specified in Section 2 of RFC8230.
* In a nutshell:
* - PSS padding
* - MGF1 mask generation, using the same hash function used to digest
* the message.
* - Salt length should match the size of the output of the hash
* function.
*/
switch (cose_algorithm_id) {
case T_COSE_ALGORITHM_PS256:
md = EVP_sha256();
break;
case T_COSE_ALGORITHM_PS384:
md = EVP_sha384();
break;
case T_COSE_ALGORITHM_PS512:
md = EVP_sha512();
break;
default:
return_value = T_COSE_ERR_UNSUPPORTED_SIGNING_ALG;
goto Done;
}
ossl_result = EVP_PKEY_CTX_set_rsa_padding(context, RSA_PKCS1_PSS_PADDING);
if(ossl_result != 1) {
return_value = T_COSE_ERR_SIG_FAIL;
goto Done;
}
/* EVP_PKEY_CTX_set_signature_md and EVP_PKEY_CTX_set_rsa_mgf1_md are
* macro wrappers around the EVP_PKEY_CTX_ctrl function, and cast
* the `const EVP_MD*` argument into a void*. This would cause a
* cast-qual warning, if not for the pragmas. Clang supports GCC
* pragmas, so it works on clang too.
*/
#pragma GCC diagnostic push
#pragma GCC diagnostic ignored "-Wcast-qual"
ossl_result = EVP_PKEY_CTX_set_signature_md(context, md);
if(ossl_result != 1) {
return_value = T_COSE_ERR_SIG_FAIL;
goto Done;
}
ossl_result = EVP_PKEY_CTX_set_rsa_mgf1_md(context, md);
if(ossl_result != 1) {
return_value = T_COSE_ERR_SIG_FAIL;
goto Done;
}
#pragma GCC diagnostic pop
ossl_result = EVP_PKEY_CTX_set_rsa_pss_saltlen(context, RSA_PSS_SALTLEN_DIGEST);
if(ossl_result != 1) {
return_value = T_COSE_ERR_SIG_FAIL;
goto Done;
}
return_value = T_COSE_SUCCESS;
} else {
return_value = T_COSE_ERR_UNSUPPORTED_SIGNING_ALG;
}
return_value = T_COSE_SUCCESS;
Done:
return return_value;
@ -364,8 +506,13 @@ t_cose_crypto_sign(const int32_t cose_algorithm_id,
EVP_PKEY_CTX *sign_context;
EVP_PKEY *signing_key_evp;
int ossl_result;
unsigned key_size_bytes;
MakeUsefulBufOnStack( der_format_signature, T_COSE_MAX_SIG_SIZE + DER_SIG_ENCODE_OVER_HEAD);
/* This buffer is passed to OpenSSL to write the ECDSA signature into, in
* DER format, before it can be converted to the expected COSE format. When
* RSA signing is selected, this buffer is unused since OpenSSL's output is
* suitable for use in COSE directly.
*/
MakeUsefulBufOnStack( der_format_signature, T_COSE_MAX_ECDSA_SIG_SIZE + DER_SIG_ENCODE_OVER_HEAD);
/* This implementation supports only ECDSA so far. The
* interface allows it to support other, but none are implemented.
@ -376,14 +523,15 @@ t_cose_crypto_sign(const int32_t cose_algorithm_id,
* check looks for ECDSA signing as indicated by COSE and rejects
* what is not since it only supports ECDSA.
*/
if(!t_cose_algorithm_is_ecdsa(cose_algorithm_id)) {
if(!t_cose_algorithm_is_ecdsa(cose_algorithm_id) &&
!t_cose_algorithm_is_rsassa_pss(cose_algorithm_id)) {
return_value = T_COSE_ERR_UNSUPPORTED_SIGNING_ALG;
goto Done2;
}
/* Pull the pointer to the OpenSSL-format EVP_PKEY out of the
* t_cose key structure and get the key size. */
return_value = key_convert_and_size(signing_key, &signing_key_evp, &key_size_bytes);
* t_cose key structure. */
return_value = key_convert(signing_key, &signing_key_evp);
if(return_value != T_COSE_SUCCESS) {
goto Done2;
}
@ -401,33 +549,60 @@ t_cose_crypto_sign(const int32_t cose_algorithm_id,
goto Done;
}
return_value = configure_pkey_context(sign_context, cose_algorithm_id);
if (return_value) {
goto Done;
}
/* Actually do the signature operation. */
ossl_result = EVP_PKEY_sign(sign_context,
der_format_signature.ptr, &der_format_signature.len,
hash_to_sign.ptr, hash_to_sign.len);
if(ossl_result != 1) {
return_value = T_COSE_ERR_SIG_FAIL;
goto Done;
if (t_cose_algorithm_is_ecdsa(cose_algorithm_id)) {
ossl_result = EVP_PKEY_sign(sign_context,
der_format_signature.ptr,
&der_format_signature.len,
hash_to_sign.ptr,
hash_to_sign.len);
if(ossl_result != 1) {
return_value = T_COSE_ERR_SIG_FAIL;
goto Done;
}
/* The signature produced by OpenSSL is DER-encoded. That encoding
* has to be removed and turned into the serialization format used
* by COSE. It is unfortunate that the OpenSSL APIs that create
* signatures that are not in DER-format are slated for
* deprecation.
*/
*signature = ecdsa_signature_der_to_cose(
signing_key_evp,
q_usefulbuf_const(der_format_signature),
signature_buffer);
if(q_useful_buf_c_is_null(*signature)) {
return_value = T_COSE_ERR_SIG_FAIL;
goto Done;
}
return_value = T_COSE_SUCCESS;
} else if (t_cose_algorithm_is_rsassa_pss(cose_algorithm_id)) {
/* signature->len gets adjusted to match just the signature size.
*/
*signature = q_usefulbuf_const(signature_buffer);
ossl_result = EVP_PKEY_sign(sign_context,
signature_buffer.ptr,
&signature->len,
hash_to_sign.ptr,
hash_to_sign.len);
if(ossl_result != 1) {
return_value = T_COSE_ERR_SIG_FAIL;
goto Done;
}
return_value = T_COSE_SUCCESS;
} else {
return_value = T_COSE_ERR_UNSUPPORTED_SIGNING_ALG;
}
/* The signature produced by OpenSSL is DER-encoded. That encoding
* has to be removed and turned into the serialization format used
* by COSE. It is unfortunate that the OpenSSL APIs that create
* signatures that are not in DER-format are slated for
* deprecation.
*/
*signature = signature_der_to_cose((unsigned)key_size_bytes,
q_usefulbuf_const(der_format_signature),
signature_buffer);
if(q_useful_buf_c_is_null(*signature)) {
return_value = T_COSE_ERR_SIG_FAIL;
goto Done;
}
/* Everything succeeded */
return_value = T_COSE_SUCCESS;
Done:
/* This checks for NULL before free, so it is not
* necessary to check for NULL here.
@ -454,43 +629,59 @@ t_cose_crypto_verify(const int32_t cose_algorithm_id,
enum t_cose_err_t return_value;
EVP_PKEY_CTX *verify_context = NULL;
EVP_PKEY *verification_key_evp;
unsigned key_size;
MakeUsefulBufOnStack( der_format_buffer, T_COSE_MAX_SIG_SIZE + DER_SIG_ENCODE_OVER_HEAD);
struct q_useful_buf_c der_format_signature;
/* This buffer is used to convert COSE ECDSA signature to DER format,
* before it can be consumed by OpenSSL. When RSA signatures are
* selected the buffer is unused.
*/
MakeUsefulBufOnStack( der_format_buffer, T_COSE_MAX_ECDSA_SIG_SIZE + DER_SIG_ENCODE_OVER_HEAD);
/* This is the signature that will be passed to OpenSSL. It will either
* point to `cose_signature`, or into `der_format_buffer`, depending on
* whether an RSA or ECDSA signature is used
*/
struct q_useful_buf_c openssl_signature;
/* This implementation doesn't use any key store with the ability
* to look up a key based on kid. */
(void)kid;
if(!t_cose_algorithm_is_ecdsa(cose_algorithm_id)) {
if(!t_cose_algorithm_is_ecdsa(cose_algorithm_id) &&
!t_cose_algorithm_is_rsassa_pss(cose_algorithm_id)) {
return_value = T_COSE_ERR_UNSUPPORTED_SIGNING_ALG;
goto Done;
}
/* Get the verification key in an EVP_PKEY structure which is what
* is needed for sig verification. This also gets the key size
* which is needed to convert the format of the signature. */
return_value = key_convert_and_size(verification_key,
&verification_key_evp,
&key_size);
* is needed for sig verification. */
return_value = key_convert(verification_key, &verification_key_evp);
if(return_value != T_COSE_SUCCESS) {
goto Done;
}
/* Unfortunately the officially supported OpenSSL API supports
* only DER-encoded signatures so the COSE format signatures must
* be converted to DER for verification. This requires a temporary
* buffer and a fair bit of work inside signature_cose_to_der().
*/
return_value = signature_cose_to_der(key_size,
cose_signature,
der_format_buffer,
&der_format_signature);
if(return_value) {
if (t_cose_algorithm_is_ecdsa(cose_algorithm_id)) {
/* Unfortunately the officially supported OpenSSL API supports
* only DER-encoded signatures so the COSE format ECDSA signatures must
* be converted to DER for verification. This requires a temporary
* buffer and a fair bit of work inside ecdsa_signature_cose_to_der().
*/
return_value = ecdsa_signature_cose_to_der(verification_key_evp,
cose_signature,
der_format_buffer,
&openssl_signature);
if(return_value) {
goto Done;
}
} else if (t_cose_algorithm_is_rsassa_pss(cose_algorithm_id)) {
/* COSE RSA signatures are already in the format OpenSSL
* expects, they can be used without any re-encoding.
*/
openssl_signature = cose_signature;
} else {
return_value = T_COSE_ERR_UNSUPPORTED_SIGNING_ALG;
goto Done;
}
/* Create the verification context and set it up with the
* necessary verification key.
*/
@ -506,10 +697,15 @@ t_cose_crypto_verify(const int32_t cose_algorithm_id,
goto Done;
}
return_value = configure_pkey_context(verify_context, cose_algorithm_id);
if (return_value) {
goto Done;
}
/* Actually do the signature verification */
ossl_result = EVP_PKEY_verify(verify_context,
der_format_signature.ptr,
der_format_signature.len,
openssl_signature.ptr,
openssl_signature.len,
hash_to_verify.ptr,
hash_to_verify.len);
@ -553,13 +749,13 @@ t_cose_crypto_hash_start(struct t_cose_crypto_hash *hash_ctx,
nid = NID_sha256;
break;
#ifndef T_COSE_DISABLE_ES384
#if !defined(T_COSE_DISABLE_ES384) || !defined(T_COSE_DISABLE_PS384)
case COSE_ALGORITHM_SHA_384:
nid = NID_sha384;
break;
#endif
#ifndef T_COSE_DISABLE_ES512
#if !defined(T_COSE_DISABLE_ES512) || !defined(T_COSE_DISABLE_PS512)
case COSE_ALGORITHM_SHA_512:
nid = NID_sha512;
break;
@ -621,6 +817,7 @@ t_cose_crypto_hash_finish(struct t_cose_crypto_hash *hash_ctx,
unsigned int hash_result_len;
if(!hash_ctx->update_error) {
EVP_MD_CTX_free(hash_ctx->evp_ctx);
return T_COSE_ERR_HASH_GENERAL_FAIL;
}
@ -637,3 +834,133 @@ t_cose_crypto_hash_finish(struct t_cose_crypto_hash *hash_ctx,
return ossl_result ? T_COSE_SUCCESS : T_COSE_ERR_HASH_GENERAL_FAIL;
}
#ifndef T_COSE_DISABLE_EDDSA
/*
* See documentation in t_cose_crypto.h
*/
enum t_cose_err_t
t_cose_crypto_sign_eddsa(struct t_cose_key signing_key,
struct q_useful_buf_c tbs,
struct q_useful_buf signature_buffer,
struct q_useful_buf_c *signature)
{
enum t_cose_err_t return_value;
int ossl_result;
EVP_MD_CTX *sign_context = NULL;
EVP_PKEY *signing_key_evp;
return_value = key_convert(signing_key, &signing_key_evp);
if(return_value != T_COSE_SUCCESS) {
goto Done;
}
sign_context = EVP_MD_CTX_new();
if(sign_context == NULL) {
return_value = T_COSE_ERR_INSUFFICIENT_MEMORY;
goto Done;
}
ossl_result = EVP_DigestSignInit(sign_context,
NULL,
NULL,
NULL,
signing_key_evp);
if(ossl_result != 1) {
return_value = T_COSE_ERR_SIG_FAIL;
goto Done;
}
*signature = q_usefulbuf_const(signature_buffer);
/** Must use EVP_DigestSign rather than EVP_PKEY_verify, since
* the tbs data is not hashed yet. Because of how EdDSA works, we
* cannot hash the data ourselves separately.
*/
ossl_result = EVP_DigestSign(sign_context,
signature_buffer.ptr,
&signature->len,
tbs.ptr,
tbs.len);
if (ossl_result != 1) {
/* Failed before even trying to verify the signature */
return_value = T_COSE_ERR_SIG_FAIL;
goto Done;
}
/* Everything succeeded */
return_value = T_COSE_SUCCESS;
Done:
EVP_MD_CTX_free(sign_context);
return return_value;
}
/*
* See documentation in t_cose_crypto.h
*/
enum t_cose_err_t
t_cose_crypto_verify_eddsa(struct t_cose_key verification_key,
struct q_useful_buf_c kid,
struct q_useful_buf_c tbs,
struct q_useful_buf_c signature)
{
enum t_cose_err_t return_value;
int ossl_result;
EVP_MD_CTX *verify_context = NULL;
EVP_PKEY *verification_key_evp;
/* This implementation doesn't use any key store with the ability
* to look up a key based on kid. */
(void)kid;
return_value = key_convert(verification_key, &verification_key_evp);
if(return_value != T_COSE_SUCCESS) {
goto Done;
}
verify_context = EVP_MD_CTX_new();
if(verify_context == NULL) {
return_value = T_COSE_ERR_INSUFFICIENT_MEMORY;
goto Done;
}
ossl_result = EVP_DigestVerifyInit(verify_context,
NULL,
NULL,
NULL,
verification_key_evp);
if(ossl_result != 1) {
return_value = T_COSE_ERR_SIG_FAIL;
goto Done;
}
/** Must use EVP_DigestVerify rather than EVP_PKEY_verify, since
* the tbs data is not hashed yet. Because of how EdDSA works, we
* cannot hash the data ourselves separately.
*/
ossl_result = EVP_DigestVerify(verify_context,
signature.ptr,
signature.len,
tbs.ptr,
tbs.len);
if(ossl_result == 0) {
/* The operation succeeded, but the signature doesn't match */
return_value = T_COSE_ERR_SIG_VERIFY;
goto Done;
} else if (ossl_result != 1) {
/* Failed before even trying to verify the signature */
return_value = T_COSE_ERR_SIG_FAIL;
goto Done;
}
/* Everything succeeded */
return_value = T_COSE_SUCCESS;
Done:
EVP_MD_CTX_free(verify_context);
return return_value;
}
#endif /* T_COSE_DISABLE_EDDSA */

Просмотреть файл

@ -12,10 +12,10 @@
/**
* \file t_cose_psa_crypto.c
*
* \brief Crypto Adaptation for t_cose to use ARM's PSA ECDSA and hashes.
* \brief Crypto Adaptation for t_cose to use ARM's PSA.
*
* This connects up the abstract interface in t_cose_crypto.h to the
* implementations of ECDSA signing and hashing in ARM's Mbed TLS crypto
* implementations of signing and hashing in ARM's Mbed TLS crypto
* library that implements the Arm PSA 1.0 crypto API.
*
* This adapter layer doesn't bloat the implementation as everything
@ -42,6 +42,43 @@
/* Avoid compiler warning due to unused argument */
#define ARG_UNUSED(arg) (void)(arg)
/*
* See documentation in t_cose_crypto.h
*
* This will typically not be referenced and thus not linked,
* for deployed code. This is mainly used for test.
*/
bool t_cose_crypto_is_algorithm_supported(int32_t cose_algorithm_id)
{
/* Notably, this list does not include EDDSA, regardless of how
* t_cose is configured, since PSA doesn't support it.
*/
static const int32_t supported_algs[] = {
COSE_ALGORITHM_SHA_256,
COSE_ALGORITHM_SHA_384,
COSE_ALGORITHM_SHA_512,
COSE_ALGORITHM_ES256,
#ifndef T_COSE_DISABLE_ES384
COSE_ALGORITHM_ES384,
#endif
#ifndef T_COSE_DISABLE_ES512
COSE_ALGORITHM_ES512,
#endif
#ifndef T_COSE_DISABLE_PS256
COSE_ALGORITHM_PS256,
#endif
#ifndef T_COSE_DISABLE_PS384
COSE_ALGORITHM_PS384,
#endif
#ifndef T_COSE_DISABLE_PS512
COSE_ALGORITHM_PS512,
#endif
0 /* List terminator */
};
return t_cose_check_list(cose_algorithm_id, supported_algs);
}
/**
* \brief Map a COSE signing algorithm ID to a PSA signing algorithm ID
@ -60,10 +97,19 @@ static psa_algorithm_t cose_alg_id_to_psa_alg_id(int32_t cose_alg_id)
#endif
#ifndef T_COSE_DISABLE_ES512
cose_alg_id == COSE_ALGORITHM_ES512 ? PSA_ALG_ECDSA(PSA_ALG_SHA_512) :
#endif
#ifndef T_COSE_DISABLE_PS256
cose_alg_id == COSE_ALGORITHM_PS256 ? PSA_ALG_RSA_PSS(PSA_ALG_SHA_256) :
#endif
#ifndef T_COSE_DISABLE_PS384
cose_alg_id == COSE_ALGORITHM_PS384 ? PSA_ALG_RSA_PSS(PSA_ALG_SHA_384) :
#endif
#ifndef T_COSE_DISABLE_PS512
cose_alg_id == COSE_ALGORITHM_PS512 ? PSA_ALG_RSA_PSS(PSA_ALG_SHA_512) :
#endif
0;
/* psa/crypto_values.h doesn't seem to define a "no alg" value,
* but zero seems OK for that use in the ECDSA context. */
* but zero seems OK for that use in the signing context. */
}
@ -107,18 +153,7 @@ t_cose_crypto_verify(int32_t cose_algorithm_id,
/* Convert to PSA algorithm ID scheme */
psa_alg_id = cose_alg_id_to_psa_alg_id(cose_algorithm_id);
/* This implementation supports ECDSA and only ECDSA. The
* interface allows it to support other, but none are implemented.
* This implementation works for different keys lengths and
* curves. That is the curve and key length as associated with the
* signing_key passed in, not the cose_algorithm_id This check
* looks for ECDSA signing as indicated by COSE and rejects what
* is not. (Perhaps this check can be removed to save object code
* if it is the case that psa_verify_hash() does the right
* checks).
*/
if(!PSA_ALG_IS_ECDSA(psa_alg_id)) {
if(!PSA_ALG_IS_ECDSA(psa_alg_id) && !PSA_ALG_IS_RSA_PSS(psa_alg_id)) {
return_value = T_COSE_ERR_UNSUPPORTED_SIGNING_ALG;
goto Done;
}
@ -156,18 +191,7 @@ t_cose_crypto_sign(int32_t cose_algorithm_id,
size_t signature_len;
psa_alg_id = cose_alg_id_to_psa_alg_id(cose_algorithm_id);
/* This implementation supports ECDSA and only ECDSA. The
* interface allows it to support other, but none are implemented.
* This implementation works for different keys lengths and
* curves. That is the curve and key length as associated with the
* signing_key passed in, not the cose_algorithm_id This check
* looks for ECDSA signing as indicated by COSE and rejects what
* is not. (Perhaps this check can be removed to save object code
* if it is the case that psa_verify_hash() does the right
* checks).
*/
if(!PSA_ALG_IS_ECDSA(psa_alg_id)) {
if(!PSA_ALG_IS_ECDSA(psa_alg_id) && !PSA_ALG_IS_RSA_PSS(psa_alg_id)) {
return_value = T_COSE_ERR_UNSUPPORTED_SIGNING_ALG;
goto Done;
}
@ -207,21 +231,15 @@ enum t_cose_err_t t_cose_crypto_sig_size(int32_t cose_algorithm_id,
size_t *sig_size)
{
enum t_cose_err_t return_value;
psa_algorithm_t psa_alg_id;
mbedtls_svc_key_id_t signing_key_psa;
size_t key_len_bits;
size_t key_len_bytes;
psa_key_attributes_t key_attributes;
psa_key_type_t key_type;
size_t key_len_bits;
psa_status_t status;
/* If desperate to save code, this can return the constant
* T_COSE_MAX_SIG_SIZE instead of doing an exact calculation. The
* buffer size calculation will return too large of a value and
* waste a little heap / stack, but everything will still work
* (except the tests that test for exact values will fail). This
* will save 100 bytes or so of object code.
*/
if(!t_cose_algorithm_is_ecdsa(cose_algorithm_id)) {
psa_alg_id = cose_alg_id_to_psa_alg_id(cose_algorithm_id);
if(!PSA_ALG_IS_ECDSA(psa_alg_id) && !PSA_ALG_IS_RSA_PSS(psa_alg_id)) {
return_value = T_COSE_ERR_UNSUPPORTED_SIGNING_ALG;
goto Done;
}
@ -229,22 +247,17 @@ enum t_cose_err_t t_cose_crypto_sig_size(int32_t cose_algorithm_id,
signing_key_psa = (mbedtls_svc_key_id_t)signing_key.k.key_handle;
key_attributes = psa_key_attributes_init();
status = psa_get_key_attributes(signing_key_psa, &key_attributes);
key_len_bits = psa_get_key_bits(&key_attributes);
return_value = psa_status_to_t_cose_error_signing(status);
if(return_value == T_COSE_SUCCESS) {
/* Calculation of size per RFC 8152 section 8.1 -- round up to
* number of bytes. */
key_len_bytes = key_len_bits / 8;
if(key_len_bits % 8) {
key_len_bytes++;
}
/* Double because signature is made of up r and s values */
*sig_size = key_len_bytes * 2;
if(return_value) {
goto Done;
}
key_type = psa_get_key_type(&key_attributes);
key_len_bits = psa_get_key_bits(&key_attributes);
*sig_size = (size_t)PSA_SIGN_OUTPUT_SIZE(key_type, (int)key_len_bits, psa_alg_id);
return_value = T_COSE_SUCCESS;
Done:
return return_value;
}
@ -264,10 +277,10 @@ static inline psa_algorithm_t
cose_hash_alg_id_to_psa(int32_t cose_hash_alg_id)
{
return cose_hash_alg_id == COSE_ALGORITHM_SHA_256 ? PSA_ALG_SHA_256 :
#ifndef T_COSE_DISABLE_ES384
#if !defined(T_COSE_DISABLE_ES384) || !defined(T_COSE_DISABLE_PS384)
cose_hash_alg_id == COSE_ALGORITHM_SHA_384 ? PSA_ALG_SHA_384 :
#endif
#ifndef T_COSE_DISABLE_ES512
#if !defined(T_COSE_DISABLE_ES512) || !defined(T_COSE_DISABLE_PS512)
cose_hash_alg_id == COSE_ALGORITHM_SHA_512 ? PSA_ALG_SHA_512 :
#endif
UINT16_MAX;
@ -367,3 +380,44 @@ t_cose_crypto_hash_finish(struct t_cose_crypto_hash *hash_ctx,
Done:
return psa_status_to_t_cose_error_hash(hash_ctx->status);
}
#ifndef T_COSE_DISABLE_EDDSA
/*
* See documentation in t_cose_crypto.h
*/
enum t_cose_err_t
t_cose_crypto_sign_eddsa(struct t_cose_key signing_key,
struct q_useful_buf_c tbs,
struct q_useful_buf signature_buffer,
struct q_useful_buf_c *signature)
{
(void)signing_key;
(void)tbs;
(void)signature_buffer;
(void)signature;
/* MbedTLS does not support EdDSA */
return T_COSE_ERR_UNSUPPORTED_SIGNING_ALG;
}
/*
* See documentation in t_cose_crypto.h
*/
enum t_cose_err_t
t_cose_crypto_verify_eddsa(struct t_cose_key verification_key,
struct q_useful_buf_c kid,
struct q_useful_buf_c tbs,
struct q_useful_buf_c signature)
{
(void)verification_key;
(void)kid;
(void)tbs;
(void)signature;
/* MbedTLS does not support EdDSA */
return T_COSE_ERR_UNSUPPORTED_SIGNING_ALG;
}
#endif /* T_COSE_DISABLE_EDDSA */

Просмотреть файл

@ -46,6 +46,23 @@
int hash_test_mode = 0;
#endif
/*
* See documentation in t_cose_crypto.h
*
* This will typically not be referenced and thus not linked,
* for deployed code. This is mainly used for test.
*/
bool
t_cose_crypto_is_algorithm_supported(int32_t cose_algorithm_id)
{
static const int32_t supported_algs[] = {
COSE_ALGORITHM_SHA_256,
0 /* List terminator */
};
return t_cose_check_list(cose_algorithm_id, supported_algs);
}
/*
* See documentation in t_cose_crypto.h
@ -57,7 +74,7 @@ enum t_cose_err_t t_cose_crypto_sig_size(int32_t cose_algorithm_id,
(void)cose_algorithm_id;
(void)signing_key;
*sig_size = T_COSE_MAX_SIG_SIZE;
*sig_size = T_COSE_MAX_ECDSA_SIG_SIZE;
return T_COSE_SUCCESS;
}
@ -104,7 +121,7 @@ t_cose_crypto_verify(int32_t cose_algorithm_id,
/*
* Public function, see t_cose_make_test_pub_key.h
*/
int check_for_key_pair_leaks()
int check_for_key_pair_leaks(void)
{
/* No check for leaks with this stubbed out crypto. With this test
crypto there is no file with code to make keys so there is no place
@ -168,3 +185,41 @@ t_cose_crypto_hash_finish(struct t_cose_crypto_hash *hash_ctx,
return 0;
}
#ifndef T_COSE_DISABLE_EDDSA
/*
* See documentation in t_cose_crypto.h
*/
enum t_cose_err_t
t_cose_crypto_sign_eddsa(struct t_cose_key signing_key,
struct q_useful_buf_c tbs,
struct q_useful_buf signature_buffer,
struct q_useful_buf_c *signature)
{
(void)signing_key;
(void)tbs;
(void)signature_buffer;
(void)signature;
return T_COSE_ERR_UNSUPPORTED_SIGNING_ALG;
}
/*
* See documentation in t_cose_crypto.h
*/
enum t_cose_err_t
t_cose_crypto_verify_eddsa(struct t_cose_key verification_key,
struct q_useful_buf_c kid,
struct q_useful_buf_c tbs,
struct q_useful_buf_c signature)
{
(void)verification_key;
(void)kid;
(void)tbs;
(void)signature;
return T_COSE_ERR_UNSUPPORTED_SIGNING_ALG;
}
#endif /* T_COSE_DISABLE_EDDSA */

Просмотреть файл

@ -37,7 +37,7 @@
/**
* \brief Make an EC key pair in OpenSSL library form.
* \brief Make a key pair in OpenSSL library form.
*
* \param[in] cose_algorithm_id The algorithm to sign with, for example
* \ref T_COSE_ALGORITHM_ES256.
@ -45,33 +45,41 @@
*
* The key made here is fixed and just useful for testing.
*/
enum t_cose_err_t make_ossl_ecdsa_key_pair(int32_t cose_algorithm_id,
struct t_cose_key *key_pair)
enum t_cose_err_t make_ossl_key_pair(int32_t cose_algorithm_id,
struct t_cose_key *key_pair)
{
enum t_cose_err_t return_value;
int ossl_result;
int ossl_nid;
int ossl_key_type;
int ossl_curve_nid;
EVP_PKEY *pkey = NULL;
EVP_PKEY_CTX *ctx;
switch (cose_algorithm_id) {
case T_COSE_ALGORITHM_ES256:
ossl_nid = NID_X9_62_prime256v1;
ossl_key_type = EVP_PKEY_EC;
ossl_curve_nid = NID_X9_62_prime256v1;
break;
case T_COSE_ALGORITHM_ES384:
ossl_nid = NID_secp384r1;
ossl_key_type = EVP_PKEY_EC;
ossl_curve_nid = NID_secp384r1;
break;
case T_COSE_ALGORITHM_ES512:
ossl_nid = NID_secp521r1;
ossl_key_type = EVP_PKEY_EC;
ossl_curve_nid = NID_secp521r1;
break;
case T_COSE_ALGORITHM_EDDSA:
ossl_key_type = EVP_PKEY_ED25519;
break;
default:
return T_COSE_ERR_UNSUPPORTED_SIGNING_ALG;
}
ctx = EVP_PKEY_CTX_new_id(EVP_PKEY_EC, NULL);
ctx = EVP_PKEY_CTX_new_id(ossl_key_type, NULL);
if(ctx == NULL) {
return_value = T_COSE_ERR_INSUFFICIENT_MEMORY;
goto Done;
@ -82,10 +90,12 @@ enum t_cose_err_t make_ossl_ecdsa_key_pair(int32_t cose_algorithm_id,
goto Done;
}
ossl_result = EVP_PKEY_CTX_set_ec_paramgen_curve_nid(ctx, ossl_nid);
if(ossl_result != 1) {
return_value = T_COSE_ERR_FAIL;
goto Done;
if (ossl_key_type == EVP_PKEY_EC) {
ossl_result = EVP_PKEY_CTX_set_ec_paramgen_curve_nid(ctx, ossl_curve_nid);
if(ossl_result != 1) {
return_value = T_COSE_ERR_FAIL;
goto Done;
}
}
pkey = EVP_PKEY_new();
@ -107,11 +117,11 @@ Done:
/**
* \brief Free a PSA / MBed key.
* \brief Free an OpenSSL key.
*
* \param[in] key_pair The key pair to close / deallocate / free.
*/
void free_ossl_ecdsa_key_pair(struct t_cose_key key_pair)
void free_ossl_key_pair(struct t_cose_key key_pair)
{
EVP_PKEY_free(key_pair.k.key_ptr);
}
@ -156,7 +166,7 @@ static void print_useful_buf(const char *string_label, struct q_useful_buf_c buf
* is simpler to use. In the code below constructed_payload_buffer is
* the extra buffer that two-step signing avoids.
*/
int32_t one_step_sign_example()
int32_t one_step_sign_example(void)
{
struct t_cose_sign1_sign_ctx sign_ctx;
@ -215,7 +225,7 @@ int32_t one_step_sign_example()
* The making and destroying of the key pair is the only code
* dependent on the crypto library in this file.
*/
return_value = make_ossl_ecdsa_key_pair(T_COSE_ALGORITHM_ES256, &key_pair);
return_value = make_ossl_key_pair(T_COSE_ALGORITHM_ES256, &key_pair);
printf("Made EC key with curve prime256v1: %d (%s)\n", return_value, return_value ? "fail" : "success");
if(return_value) {
@ -325,7 +335,7 @@ int32_t one_step_sign_example()
* use. This call indicates that the key slot can be de allocated.
*/
printf("Freeing key pair\n\n\n");
free_ossl_ecdsa_key_pair(key_pair);
free_ossl_key_pair(key_pair);
Done:
return (int32_t)return_value;
@ -341,7 +351,7 @@ Done:
* constructed directly into the output buffer, uses less memory,
* but is more complicated to use.
*/
int two_step_sign_example()
int two_step_sign_example(void)
{
struct t_cose_sign1_sign_ctx sign_ctx;
enum t_cose_err_t return_value;
@ -366,7 +376,7 @@ int two_step_sign_example()
* The making and destroying of the key pair is the only code
* dependent on the crypto library in this file.
*/
return_value = make_ossl_ecdsa_key_pair(T_COSE_ALGORITHM_ES256, &key_pair);
return_value = make_ossl_key_pair(T_COSE_ALGORITHM_ES256, &key_pair);
printf("Made EC key with curve prime256v1: %d (%s)\n", return_value, return_value ? "fail" : "success");
if(return_value) {
@ -528,12 +538,190 @@ int two_step_sign_example()
* OpenSSL uses memory allocation for keys, so they must be freed.
*/
printf("Freeing key pair\n\n\n");
free_ossl_ecdsa_key_pair(key_pair);
free_ossl_key_pair(key_pair);
Done:
return (int)return_value;
}
/**
* \brief Sign and verify example with dynamically allocated buffers
*
* The signing operation of t_cose requires the caller to provide a
* buffer large enough to hold the result. If the provided buffer is
* too small, the operation will fail.
*
* When EDDSA is used, an additional auxiliary buffer is needed for
* both signing and verification.
*
* While memory-constrained applications may want to use stack or
* statically allocated buffers of a fixed size, others prefer the
* flexibility of dynamically allocating buffers of the right size on
* demand.
*
* This example shows how to call t_cose to determine the size of the
* output and auxiliary buffers, before dynamically allocating them
* using malloc and free. Any alternative allocator could also have
* been used.
*
*/
int32_t dynamic_buffer_example(void)
{
struct t_cose_sign1_sign_ctx sign_ctx;
enum t_cose_err_t return_value;
struct q_useful_buf signed_cose_buffer;
struct q_useful_buf_c signed_cose;
struct q_useful_buf auxiliary_buffer;
struct q_useful_buf_c constructed_payload;
struct q_useful_buf_c returned_payload;
struct t_cose_key key_pair;
struct t_cose_sign1_verify_ctx verify_ctx;
/* ------ Prepare the payload ------ */
constructed_payload = Q_USEFUL_BUF_FROM_SZ_LITERAL("payload");
printf("Encoded payload size = %ld\n", constructed_payload.len);
/* ------ Make an EDDSA key pair ------ */
return_value = make_ossl_key_pair(T_COSE_ALGORITHM_EDDSA, &key_pair);
printf("Made EC key with curve ed25519: %d (%s)\n", return_value, return_value ? "fail" : "success");
if(return_value) {
goto Done;
}
/* ------ Initialize for signing ------ */
t_cose_sign1_sign_init(&sign_ctx, 0, T_COSE_ALGORITHM_EDDSA);
t_cose_sign1_set_signing_key(&sign_ctx, key_pair, NULL_Q_USEFUL_BUF_C);
/* ------ Compute the size of the output and auxiliary buffers ------
*
* A large but NULL output buffer is given to the signing operation.
* The size of result, signed_cose, will reflect how big of a buffer
* needs to be provided for the real operation.
*
* Similarly, the necessary auxiliary buffer size is saved in the
* signing context and available by calling t_cose_sign1_sign_auxiliary_buffer_size.
*
* Both sizes are used later on to allocate the proper buffers.
*/
return_value = t_cose_sign1_sign(&sign_ctx,
constructed_payload,
(struct q_useful_buf){ NULL, SIZE_MAX },
&signed_cose);
printf("Computed signing size %d (%s)\n", return_value, return_value ? "fail" : "success");
if(return_value) {
goto Done;
}
printf("Output buffer size = %zu bytes\n", signed_cose.len);
printf("Auxiliary buffer size = %zu bytes\n", t_cose_sign1_sign_auxiliary_buffer_size(&sign_ctx));
/* ------ Allocate buffers of the right size ------ */
signed_cose_buffer.ptr = malloc(signed_cose.len);
signed_cose_buffer.len = signed_cose.len;
auxiliary_buffer.len = t_cose_sign1_sign_auxiliary_buffer_size(&sign_ctx);
auxiliary_buffer.ptr = malloc(auxiliary_buffer.len);
if (signed_cose_buffer.ptr == NULL || auxiliary_buffer.ptr == NULL) {
printf("Buffer allocation failed\n");
return_value = T_COSE_ERR_INSUFFICIENT_MEMORY;
goto Done;
}
/* ------ Sign ------
*
* Call the sign function again, this time providing it with the
* real buffers.
*/
t_cose_sign1_sign_set_auxiliary_buffer(&sign_ctx, auxiliary_buffer);
return_value = t_cose_sign1_sign(&sign_ctx,
constructed_payload,
signed_cose_buffer,
&signed_cose);
printf("Finished signing: %d (%s)\n", return_value, return_value ? "fail" : "success");
if(return_value) {
goto Done;
}
print_useful_buf("Completed COSE_Sign1 message:\n", signed_cose);
printf("\n");
/* ------ Free the auxiliary buffer ------
*
* We could have re-used the allocation for the verification step
* (since it would be the same size), but for demonstration purpose
* we deallocate it here and re-compute its size from the signed
* message.
*/
free(auxiliary_buffer.ptr);
/* ------ Compute the size of the auxiliary buffer ------
*
* We call the verify procedure with the DECODE_ONLY flag.
*
* This is only necessary because EDDSA is used as a signing
* algorithm. Other algorithms have no need for an auxiliary
* buffer.
*/
t_cose_sign1_verify_init(&verify_ctx, T_COSE_OPT_DECODE_ONLY);
printf("Initialized t_cose for decoding\n");
return_value = t_cose_sign1_verify(&verify_ctx, signed_cose, NULL, NULL);
printf("Decode-only complete: %d (%s)\n", return_value, return_value ? "fail" : "success");
if(return_value) {
goto Done;
}
printf("Auxiliary buffer size = %zu bytes\n", t_cose_sign1_verify_auxiliary_buffer_size(&verify_ctx));
/* ------ Allocate an auxiliary buffer of the right size ------ */
auxiliary_buffer.len = t_cose_sign1_verify_auxiliary_buffer_size(&verify_ctx);
auxiliary_buffer.ptr = malloc(auxiliary_buffer.len);
if (auxiliary_buffer.ptr == NULL) {
printf("Auxiliary buffer allocation failed\n");
return_value = T_COSE_ERR_INSUFFICIENT_MEMORY;
goto Done;
}
/* ------ Set up for verification ------
*
* We re-initialize the context, without any flags this time so it
* performs the actual verification.
*/
t_cose_sign1_verify_init(&verify_ctx, 0);
t_cose_sign1_set_verification_key(&verify_ctx, key_pair);
t_cose_sign1_verify_set_auxiliary_buffer(&verify_ctx, auxiliary_buffer);
printf("Initialized t_cose for verification and set verification key\n");
/* ------ Perform the verification ------ */
return_value = t_cose_sign1_verify(&verify_ctx,
signed_cose, /* COSE to verify */
&returned_payload, /* Payload from signed_cose */
NULL); /* Don't return parameters */
printf("Verification complete: %d (%s)\n", return_value, return_value ? "fail" : "success");
if(return_value) {
goto Done;
}
print_useful_buf("Signed payload:\n", returned_payload);
/* ------ Free the output and auxiliary buffers ------ */
free(signed_cose_buffer.ptr);
free(auxiliary_buffer.ptr);
/* ------ Free key pair ------ */
printf("Freeing key pair\n\n\n");
free_ossl_key_pair(key_pair);
Done:
return (int32_t)return_value;
}
int main(int argc, const char * argv[])
{
(void)argc; /* Avoid unused parameter error */
@ -541,4 +729,5 @@ int main(int argc, const char * argv[])
one_step_sign_example();
two_step_sign_example();
dynamic_buffer_example();
}

Просмотреть файл

@ -216,7 +216,7 @@ static void print_useful_buf(const char *string_label, struct q_useful_buf_c buf
* is simpler to use. In the code below constructed_payload_buffer is
* the extra buffer that two-step signing avoids.
*/
int32_t one_step_sign_example()
int32_t one_step_sign_example(void)
{
struct t_cose_sign1_sign_ctx sign_ctx;
@ -401,7 +401,7 @@ Done:
* constructed directly into the output buffer, uses less memory,
* but is more complicated to use.
*/
int two_step_sign_example()
int two_step_sign_example(void)
{
struct t_cose_sign1_sign_ctx sign_ctx;
enum t_cose_err_t return_value;

Просмотреть файл

Просмотреть файл

@ -13,6 +13,7 @@
#define __T_COSE_COMMON_H__
#include <stdint.h>
#include <stdbool.h>
#ifdef __cplusplus
extern "C" {
@ -44,6 +45,15 @@ extern "C" {
* of stack. No stack will be saved if \c T_COSE_DISABLE_ES512 is not
* also defined.
*
* \c T_COSE_DISABLE_PS256 -- Disables the COSE algorithm PS256
* algorithm.
*
* \c T_COSE_DISABLE_PS384 -- Disables the COSE algorithm PS384
* algorithm.
*
* \c T_COSE_DISABLE_PS512 -- Disables the COSE algorithm PS512
* algorithm.
*
* \c T_COSE_DISABLE_CONTENT_TYPE -- Disables the content type
* parameters for both signing and verifying.
*/
@ -64,6 +74,19 @@ extern "C" {
*/
#define T_COSE_ALGORITHM_ES256 -7
/**
* \def T_COSE_ALGORITHM_EDDSA
*
* \brief Indicates EDDSA, as described by RFC8032.
*
* This value comes from the
* [IANA COSE Registry](https://www.iana.org/assignments/cose/cose.xhtml).
*
* Keys using either the edwards25519 or edwards448 curves can be used
* with this algorithm.
*/
#define T_COSE_ALGORITHM_EDDSA -8
/**
* \def T_COSE_ALGORITHM_ES384
*
@ -90,6 +113,36 @@ extern "C" {
*/
#define T_COSE_ALGORITHM_ES512 -36
/**
* \def T_COSE_ALGORITHM_PS256
*
* \brief Indicates RSASSA-PSS with SHA-256.
*
* This value comes from the
* [IANA COSE Registry](https://www.iana.org/assignments/cose/cose.xhtml).
*/
#define T_COSE_ALGORITHM_PS256 -37
/**
* \def T_COSE_ALGORITHM_PS384
*
* \brief Indicates RSASSA-PSS with SHA-384.
*
* This value comes from the
* [IANA COSE Registry](https://www.iana.org/assignments/cose/cose.xhtml).
*/
#define T_COSE_ALGORITHM_PS384 -38
/**
* \def T_COSE_ALGORITHM_PS512
*
* \brief Indicates RSASSA-PSS with SHA-512.
*
* This value comes from the
* [IANA COSE Registry](https://www.iana.org/assignments/cose/cose.xhtml).
*/
#define T_COSE_ALGORITHM_PS512 -39
@ -165,7 +218,7 @@ struct t_cose_key {
* needs to be big enough for encode_protected_parameters() to
* succeed. It currently sized for one parameter 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
* the label, 5 bytes for the ID. If this is made accidentally too
* small, QCBOR will only return an error, and not overrun any
* buffers.
*
@ -307,10 +360,11 @@ enum t_cose_err_t {
* cryptographic library used by this integration of t_cose.
*/
T_COSE_ERR_INCORRECT_KEY_FOR_LIB = 29,
/** This implementation only handles integer COSE algorithm IDs with
* values less than \c INT32_MAX. */
T_COSE_ERR_NON_INTEGER_ALG_ID = 30,
/** The content type parameter contains a content type that is
* neither integer or text string or it is an integer not in the
* range of 0 to \c UINT16_MAX. */
@ -341,6 +395,14 @@ enum t_cose_err_t {
/** More than \ref T_COSE_MAX_TAGS_TO_RETURN unprocessed tags when
* verifying a signature. */
T_COSE_ERR_TOO_MANY_TAGS = 37,
/** The signature algorithm needs an extra buffer, but none was provided.
* See \ref t_cose_sign1_verify_set_auxiliary_buffer for more details.
*/
T_COSE_ERR_NEED_AUXILIARY_BUFFER = 38,
/** The auxiliary buffer is too small */
T_COSE_ERR_AUXILIARY_BUFFER_SIZE = 39,
};
@ -370,6 +432,23 @@ enum t_cose_err_t {
*/
#define T_COSE_EMPTY_UINT_CONTENT_TYPE UINT16_MAX+1
/**
* \brief Check whether an algorithm is supported.
*
* \param[in] cose_algorithm_id COSE Integer algorithm ID.
*
* \returns \c true if algorithm is supported, \c false if not.
*
* Algorithms identifiers are from COSE algorithm registry:
* https://www.iana.org/assignments/cose/cose.xhtml#algorithms
*
* A primary use for this is to determine whether or not to run a test case.
* It is often unneccessary for regular use, because all the APIs will return
* T_COSE_ERR_UNSUPPORTED_XXXX if the algorithm is not supported.
*/
bool
t_cose_is_algorithm_supported(int32_t cose_algorithm_id);
#ifdef __cplusplus
}

Просмотреть файл

@ -77,6 +77,21 @@ struct t_cose_sign1_sign_ctx {
uint32_t content_type_uint;
const char * content_type_tstr;
#endif
#ifndef T_COSE_DISABLE_EDDSA
/**
* A auxiliary buffer provided by the caller, used to serialize
* the Sig_Structure. This is only needed when using EdDSA, as
* otherwise the Sig_Structure is hashed incrementally.
*/
struct q_useful_buf auxiliary_buffer;
/* The size of the serialized Sig_Structure used in the last
* signing operation. This can be used by the user to determine
* a suitable auxiliary buffer size.
*/
size_t auxiliary_buffer_size;
#endif
};
@ -171,6 +186,53 @@ t_cose_sign1_set_signing_key(struct t_cose_sign1_sign_ctx *context,
struct t_cose_key signing_key,
struct q_useful_buf_c kid);
/**
* \brief Configure an auxiliary buffer used to serialize the Sig_Structure.
*
* \param[in] context The t_cose signing context.
* \param[in] auxiliary_buffer The buffer used to serialize the Sig_Structure.
*
* 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, an auxiliary buffer with a NULL
* pointer and a large size, such as \c UINT32_MAX, can be used. No
* actual signing will take place, but the auxiliary buffer will be shrunk
* to the to expected size.
*
*/
static void
t_cose_sign1_sign_set_auxiliary_buffer(struct t_cose_sign1_sign_ctx *context,
struct q_useful_buf auxiliary_buffer);
/**
* \brief Get the required auxiliary buffer size for the most recent
* signing operation.
*
* \param[in] context The t_cose signing context.
*
* \return The number of bytes of auxiliary buffer used by the most
* recent signing operation.
*
* This function can be called after \ref t_cose_sign1_sign (or
* equivalent) was called. If a NULL output buffer was passed to the
* signing function (to operate in size calculation mode), this 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 if the signature algorithm used does not need
* an auxiliary buffer.
*/
static size_t
t_cose_sign1_sign_auxiliary_buffer_size(struct t_cose_sign1_sign_ctx *context);
#ifndef T_COSE_DISABLE_CONTENT_TYPE
@ -426,12 +488,18 @@ t_cose_sign1_sign_init(struct t_cose_sign1_sign_ctx *me,
{
memset(me, 0, sizeof(*me));
#ifndef T_COSE_DISABLE_CONTENT_TYPE
/* Only member for which 0 is not the empty state */
me->content_type_uint = T_COSE_EMPTY_UINT_CONTENT_TYPE;
#endif
me->cose_algorithm_id = cose_algorithm_id;
me->option_flags = option_flags;
#ifndef T_COSE_DISABLE_EDDSA
/* Start with large (but NULL) auxiliary buffer. If EdDSA is used,
* the Sig_Structure data will be serialized here.
*/
me->auxiliary_buffer.len = SIZE_MAX;
#endif
}
@ -444,6 +512,30 @@ t_cose_sign1_set_signing_key(struct t_cose_sign1_sign_ctx *me,
me->signing_key = signing_key;
}
static inline void
t_cose_sign1_sign_set_auxiliary_buffer(struct t_cose_sign1_sign_ctx *me,
struct q_useful_buf auxiliary_buffer)
{
#ifndef T_COSE_DISABLE_EDDSA
me->auxiliary_buffer = auxiliary_buffer;
#else
(void)me;
(void)auxiliary_buffer;
#endif
}
static inline size_t
t_cose_sign1_sign_auxiliary_buffer_size(struct t_cose_sign1_sign_ctx *me)
{
#ifndef T_COSE_DISABLE_EDDSA
return me->auxiliary_buffer_size;
#else
/* If EdDSA is disabled we don't ever need an auxiliary buffer. */
(void)me;
return 0;
#endif
}
/**
* \brief Semi-private function that ouputs the COSE parameters, startng a

Просмотреть файл

@ -187,14 +187,30 @@ struct t_cose_parameters {
/**
* Context for signature verification. It is about 56 bytes on a
* 64-bit machine and 42 bytes on a 32-bit machine.
* Context for signature verification. It is about 80 bytes on a
* 64-bit machine and 54 bytes on a 32-bit machine, or less if
* certain features are disabled.
*/
struct t_cose_sign1_verify_ctx {
/* Private data structure */
struct t_cose_key verification_key;
uint32_t option_flags;
uint64_t auTags[T_COSE_MAX_TAGS_TO_RETURN];
#ifndef T_COSE_DISABLE_EDDSA
/**
* A auxiliary buffer provided by the caller, used to serialize
* the Sig_Structure. This is only needed when using EdDSA, as
* otherwise the Sig_Structure is hashed incrementally.
*/
struct q_useful_buf auxiliary_buffer;
/* The size of the serialized Sig_Structure used in the last
* verification. This can be used by the user to determine a
* suitable auxiliary buffer size.
*/
size_t auxiliary_buffer_size;
#endif
};
@ -264,6 +280,54 @@ t_cose_sign1_set_verification_key(struct t_cose_sign1_verify_ctx *context,
struct t_cose_key verification_key);
/**
* \brief Configure a buffer used to serialize the Sig_Structure.
*
* \param[in,out] context The t_cose signature verification context.
* \param[in] auxiliary_buffer The 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 \ref T_COSE_OPT_DECODE_ONLY option, and call the
* \ref t_cose_sign1_verify (or similar). After the message decoding,
* the necessary auxiliary buffer size is available by calling
* \ref t_cose_sign1_verify_auxiliary_buffer_size.
*
*/
static void
t_cose_sign1_verify_set_auxiliary_buffer(struct t_cose_sign1_verify_ctx *context,
struct q_useful_buf auxiliary_buffer);
/**
* \brief Get the required auxiliary buffer size for the most recent
* verification operation.
*
* \param[in,out] context The t_cose signature verification context.
*
* \return The number of bytes of auxiliary buffer used by the most
* recent verification operation.
*
* This function can be called after \ref 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.
*/
static size_t
t_cose_sign1_verify_auxiliary_buffer_size(struct t_cose_sign1_verify_ctx *context);
/**
* \brief Verify a \c COSE_Sign1.
*
@ -419,8 +483,15 @@ static inline void
t_cose_sign1_verify_init(struct t_cose_sign1_verify_ctx *me,
uint32_t option_flags)
{
memset(me, 0, sizeof(*me));
me->option_flags = option_flags;
me->verification_key = T_COSE_NULL_KEY;
#ifndef T_COSE_DISABLE_EDDSA
/* Start with large (but NULL) auxiliary buffer. If EdDSA is used,
* the Sig_Structure data will be serialized here.
*/
me->auxiliary_buffer.len = SIZE_MAX;
#endif
}
@ -431,6 +502,30 @@ t_cose_sign1_set_verification_key(struct t_cose_sign1_verify_ctx *me,
me->verification_key = verification_key;
}
static inline void
t_cose_sign1_verify_set_auxiliary_buffer(struct t_cose_sign1_verify_ctx *me,
struct q_useful_buf auxiliary_buffer)
{
#ifndef T_COSE_DISABLE_EDDSA
me->auxiliary_buffer = auxiliary_buffer;
#else
(void)me;
(void)auxiliary_buffer;
#endif
}
static inline size_t
t_cose_sign1_verify_auxiliary_buffer_size(struct t_cose_sign1_verify_ctx *me)
{
#ifndef T_COSE_DISABLE_EDDSA
return me->auxiliary_buffer_size;
#else
/* If EdDSA is disabled we don't ever need an auxiliary buffer. */
(void)me;
return 0;
#endif
}
static inline uint64_t
t_cose_sign1_get_nth_tag(const struct t_cose_sign1_verify_ctx *context,

170
3rdparty/exported/t_cose/src/t_cose_crypto.h поставляемый
Просмотреть файл

@ -83,8 +83,6 @@ extern "C" {
* - If not ECDSA add another function like t_cose_algorithm_is_ecdsa()
* - Support for a new COSE_ALGORITHM_XXX signature algorithm is added
* - See \ref T_COSE_CRYPTO_MAX_HASH_SIZE for additional hashes
* - Support larger key sizes (and thus signature sizes)
* - See \ref T_COSE_MAX_SIG_SIZE
* - Support another hash implementation that is not a service
* - See struct \ref t_cose_crypto_hash
*
@ -118,19 +116,32 @@ extern "C" {
* 8.1. It is the concatenation of r and s, each of which is the key
* size in bits rounded up to the nearest byte. That is twice the key
* size in bytes.
*
* RSA signatures are typically much larger than this, but do not need
* to be stored on the stack, since the COSE format is the same as the
* one OpenSSL understands natively. The stack variable therefore does
* not need to be made large enough to fit these signatures.
*/
#ifndef T_COSE_DISABLE_ES512
#define T_COSE_MAX_SIG_SIZE T_COSE_EC_P512_SIG_SIZE
#define T_COSE_MAX_ECDSA_SIG_SIZE T_COSE_EC_P512_SIG_SIZE
#else
#ifndef T_COSE_DISABLE_ES384
#define T_COSE_MAX_SIG_SIZE T_COSE_EC_P384_SIG_SIZE
#define T_COSE_MAX_ECDSA_SIG_SIZE T_COSE_EC_P384_SIG_SIZE
#else
#define T_COSE_MAX_SIG_SIZE T_COSE_EC_P256_SIG_SIZE
#define T_COSE_MAX_ECDSA_SIG_SIZE T_COSE_EC_P256_SIG_SIZE
#endif
#endif
/*
* Says where a particular algorithm is supported or not.
* Most useful for test code that wants to know if a
* test should be attempted or not.
*
* See t_cose_is_algorithm_supported()
*/
bool t_cose_crypto_is_algorithm_supported(int32_t cose_algorithm_id);
/**
* \brief Returns the size of a signature given the key and algorithm.
@ -206,10 +217,6 @@ t_cose_crypto_sig_size(int32_t cose_algorithm_id,
* for details on how \c q_useful_buf and \c q_useful_buf_c are used
* to return the signature.
*
* To find out the size of the signature buffer needed, call this with
* \c signature_buffer->ptr \c NULL and \c signature_buffer->len a
* very large number like \c UINT32_MAX. The size will be returned in
* \c signature->len.
*/
enum t_cose_err_t
t_cose_crypto_sign(int32_t cose_algorithm_id,
@ -233,7 +240,7 @@ t_cose_crypto_sign(int32_t cose_algorithm_id,
* hasn't been registered.
* \param[in] verification_key The verification key to use.
* \param[in] kid The COSE kid (key ID) or \c NULL_Q_USEFUL_BUF_C.
* \param[in] hash_to_verify The data or hash that is to be verified.
* \param[in] hash_to_verify The hash of the data that is to be verified.
* \param[in] signature The COSE-format signature.
*
* This verifies that the \c signature passed in was over the \c
@ -276,8 +283,107 @@ t_cose_crypto_verify(int32_t cose_algorithm_id,
struct q_useful_buf_c hash_to_verify,
struct q_useful_buf_c signature);
#ifndef T_COSE_DISABLE_EDDSA
/**
* \brief Perform public key signing for EdDSA.
*
* The EdDSA signing algorithm (or more precisely its PureEdDSA
* variant, used in COSE) requires two passes over the input data.
* This requires the whole to-be-signed structure to be held in
* memory and given as an argument to this function, rather than
* an incrementally computed hash.
*
* \param[in] signing_key Indicates or contains key to sign with.
* \param[in] tbs 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
* returned.
*
* \retval T_COSE_SUCCESS
* Successfully created the signature.
* \retval T_COSE_ERR_SIG_BUFFER_SIZE
* The \c signature_buffer too small.
* \retval T_COSE_ERR_UNSUPPORTED_SIGNING_ALG
* EdDSA signatures are not supported.
* \retval T_COSE_ERR_UNKNOWN_KEY
* The key identified by \c key_select was not found.
* \retval T_COSE_ERR_WRONG_TYPE_OF_KEY
* The key was found, but it was the wrong type.
* \retval T_COSE_ERR_INVALID_ARGUMENT
* Some (unspecified) argument was not valid.
* \retval T_COSE_ERR_INSUFFICIENT_MEMORY
* Insufficient heap memory.
* \retval T_COSE_ERR_FAIL
* General unspecific failure.
* \retval T_COSE_ERR_TAMPERING_DETECTED
* Equivalent to \c PSA_ERROR_CORRUPTION_DETECTED.
*
* This is called to do public key signing. The implementation will
* vary from one platform / OS to another but should conform to the
* description here.
*
* The contents of signing_key is usually the type that holds
* a key for the cryptographic library.
*
* See the note in the Detailed Description (the \\file comment block)
* for details on how \c q_useful_buf and \c q_useful_buf_c are used
* to return the signature.
*
*/
enum t_cose_err_t
t_cose_crypto_sign_eddsa(struct t_cose_key signing_key,
struct q_useful_buf_c tbs,
struct q_useful_buf signature_buffer,
struct q_useful_buf_c *signature);
/**
* \brief Perform public key signature verification for EdDSA.
*
* The EdDSA signing algorithm (or more precisely its PureEdDSA
* variant, used in COSE) requires two passes over the input data.
* This requires the whole to-be-signed structure to be held in
* memory and given as an argument to this function, rather than
* an incrementally computed hash.
*
* \param[in] verification_key The verification key to use.
* \param[in] kid The COSE kid (key ID) or \c NULL_Q_USEFUL_BUF_C.
* \param[in] tbs The data to be verified.
* \param[in] signature The COSE-format signature.
*
* The key selected must be of the correct type for EdDSA
* signatures.
*
* \retval T_COSE_SUCCESS
* The signature is valid
* \retval T_COSE_ERR_SIG_VERIFY
* Signature verification failed. For example, the
* cryptographic operations completed successfully but hash
* wasn't as expected.
* \retval T_COSE_ERR_UNKNOWN_KEY
* The key identified by \c key_select or a \c kid was
* not found.
* \retval T_COSE_ERR_WRONG_TYPE_OF_KEY
* The key was found, but it was the wrong type
* for the operation.
* \retval T_COSE_ERR_UNSUPPORTED_SIGNING_ALG
* EdDSA signatures are not supported.
* \retval T_COSE_ERR_INVALID_ARGUMENT
* Some (unspecified) argument was not valid.
* \retval T_COSE_ERR_INSUFFICIENT_MEMORY
* Out of heap memory.
* \retval T_COSE_ERR_FAIL
* General unspecific failure.
* \retval T_COSE_ERR_TAMPERING_DETECTED
* Equivalent to \c PSA_ERROR_CORRUPTION_DETECTED.
*/
enum t_cose_err_t
t_cose_crypto_verify_eddsa(struct t_cose_key verification_key,
struct q_useful_buf_c kid,
struct q_useful_buf_c tbs,
struct q_useful_buf_c signature);
#endif /* T_COSE_DISABLE_EDDSA */
#ifdef T_COSE_USE_PSA_CRYPTO
#include "psa/crypto.h"
@ -386,10 +492,10 @@ struct t_cose_crypto_hash {
* The maximum needed to hold a hash. It is smaller and less stack is needed
* if the larger hashes are disabled.
*/
#ifndef T_COSE_DISABLE_ES512
#if !defined(T_COSE_DISABLE_ES512) || !defined(T_COSE_DISABLE_PS512)
#define T_COSE_CRYPTO_MAX_HASH_SIZE T_COSE_CRYPTO_SHA512_SIZE
#else
#ifndef T_COSE_DISABLE_ES384
#if !defined(T_COSE_DISABLE_ES384) || !defined(T_COSE_DISABLE_PS384)
#define T_COSE_CRYPTO_MAX_HASH_SIZE T_COSE_CRYPTO_SHA384_SIZE
#else
#define T_COSE_CRYPTO_MAX_HASH_SIZE T_COSE_CRYPTO_SHA256_SIZE
@ -505,12 +611,26 @@ t_cose_crypto_hash_finish(struct t_cose_crypto_hash *hash_ctx,
* integer COSE algorithm ID uses the ECDSA signing algorithm
* or not.
*
* (As other types of signing algorithms are added, RSA for example,
* a similar function can be added for them.)
*/
static bool
t_cose_algorithm_is_ecdsa(int32_t cose_algorithm_id);
/**
* \brief Indicate whether a COSE algorithm is RSASSA-PSS or not.
*
* \param[in] cose_algorithm_id The algorithm ID to check.
*
* \returns This returns \c true if the algorithm is RSASSA-PSS
* and \c false if not.
*
* This is a convenience function to check whether a given
* integer COSE algorithm ID uses the RSASSA-PSS signing algorithm
* or not.
*
*/
static bool
t_cose_algorithm_is_rsassa_pss(int32_t cose_algorithm_id);
@ -558,11 +678,31 @@ t_cose_algorithm_is_ecdsa(int32_t cose_algorithm_id)
#ifndef T_COSE_DISABLE_ES512
COSE_ALGORITHM_ES512,
#endif
0}; /* 0 is a reserved COSE alg ID ans will never be used */
0}; /* 0 is a reserved COSE alg ID and will never be used */
return t_cose_check_list(cose_algorithm_id, ecdsa_list);
}
static inline bool
t_cose_algorithm_is_rsassa_pss(int32_t cose_algorithm_id)
{
/* The simple list of COSE alg IDs that use RSASSA-PSS */
static const int32_t rsa_list[] = {
#ifndef T_COSE_DISABLE_PS256
COSE_ALGORITHM_PS256,
#endif
#ifndef T_COSE_DISABLE_PS384
COSE_ALGORITHM_PS384,
#endif
#ifndef T_COSE_DISABLE_PS512
COSE_ALGORITHM_PS512,
#endif
0}; /* 0 is a reserved COSE alg ID and will never be used */
return t_cose_check_list(cose_algorithm_id, rsa_list);
}
#ifdef __cplusplus
}
#endif

130
3rdparty/exported/t_cose/src/t_cose_short_circuit.c поставляемый Normal file
Просмотреть файл

@ -0,0 +1,130 @@
/*
* t_cose_short_circuit.c
*
* Copyright 2019-2022, Laurence Lundblade
*
* SPDX-License-Identifier: BSD-3-Clause
*
* See BSD-3-Clause license in README.md
*/
#include "t_cose_short_circuit.h"
#include "t_cose_standard_constants.h"
#include "t_cose_crypto.h"
/**
* \file t_cose_short_circuit.h
*
* \brief Functions used to compute and verify short-circuit signatures.
*
* These signatures don't use any cryptographic algorithm and don't
* provide any security guarantees at all. They are provided for
* demonstration purposes, and will not be used unless explicitly
* enabled by users of the library.
*
*/
#ifndef T_COSE_DISABLE_SHORT_CIRCUIT_SIGN
/**
* See documentation in t_cose_short_circuit.h
*/
enum t_cose_err_t
short_circuit_sig_size(int32_t cose_algorithm_id, size_t *sig_size)
{
*sig_size = cose_algorithm_id == COSE_ALGORITHM_ES256 ? T_COSE_EC_P256_SIG_SIZE :
cose_algorithm_id == COSE_ALGORITHM_ES384 ? T_COSE_EC_P384_SIG_SIZE :
cose_algorithm_id == COSE_ALGORITHM_ES512 ? T_COSE_EC_P512_SIG_SIZE :
0;
return sig_size == 0 ? T_COSE_ERR_UNSUPPORTED_SIGNING_ALG : T_COSE_SUCCESS;
}
/**
* See documentation in t_cose_short_circuit.h
*/
enum t_cose_err_t
short_circuit_sign(int32_t cose_algorithm_id,
struct q_useful_buf_c hash_to_sign,
struct q_useful_buf signature_buffer,
struct q_useful_buf_c *signature)
{
/* approximate stack use on 32-bit machine: local use: 16 bytes
*/
enum t_cose_err_t return_value;
size_t array_indx;
size_t amount_to_copy;
size_t sig_size;
return_value = short_circuit_sig_size(cose_algorithm_id, &sig_size);
/* Check the signature length against buffer size */
if(return_value != T_COSE_SUCCESS) {
goto Done;
}
if(sig_size > signature_buffer.len) {
/* Buffer too small for this signature type */
return_value = T_COSE_ERR_SIG_BUFFER_SIZE;
goto Done;
}
/* Loop concatening copies of the hash to fill out to signature size */
for(array_indx = 0; array_indx < sig_size; array_indx += hash_to_sign.len) {
amount_to_copy = sig_size - array_indx;
if(amount_to_copy > hash_to_sign.len) {
amount_to_copy = hash_to_sign.len;
}
memcpy((uint8_t *)signature_buffer.ptr + array_indx,
hash_to_sign.ptr,
amount_to_copy);
}
signature->ptr = signature_buffer.ptr;
signature->len = sig_size;
return_value = T_COSE_SUCCESS;
Done:
return return_value;
}
/**
* See documentation in t_cose_short_circuit.h
*/
enum t_cose_err_t
t_cose_crypto_short_circuit_verify(struct q_useful_buf_c hash_to_verify,
struct q_useful_buf_c signature)
{
/* Aproximate stack usage
* 64-bit 32-bit
* local vars 24 12
* TOTAL 24 12
*/
struct q_useful_buf_c hash_from_sig;
enum t_cose_err_t return_value;
hash_from_sig = q_useful_buf_head(signature, hash_to_verify.len);
if(q_useful_buf_c_is_null(hash_from_sig)) {
return_value = T_COSE_ERR_SIG_VERIFY;
goto Done;
}
if(q_useful_buf_compare(hash_from_sig, hash_to_verify)) {
return_value = T_COSE_ERR_SIG_VERIFY;
} else {
return_value = T_COSE_SUCCESS;
}
Done:
return return_value;
}
#else /* T_COSE_DISABLE_SHORT_CIRCUIT_SIGN */
/* So some of the build checks don't get confused by an empty object file */
void t_cose_short_circuit_placeholder()
{}
#endif /* T_COSE_DISABLE_SHORT_CIRCUIT_SIGN */

100
3rdparty/exported/t_cose/src/t_cose_short_circuit.h поставляемый Normal file
Просмотреть файл

@ -0,0 +1,100 @@
/*
* t_cose_short_circuit.h
*
* Copyright 2019-2022, Laurence Lundblade
*
* SPDX-License-Identifier: BSD-3-Clause
*
* See BSD-3-Clause license in README.md
*/
#ifndef __T_COSE_SHORT_CIRCUIT_H__
#define __T_COSE_SHORT_CIRCUIT_H__
#include <stdint.h>
#include "t_cose/q_useful_buf.h"
#include "t_cose/t_cose_common.h"
#ifdef __cplusplus
extern "C" {
#endif
/**
* \file t_cose_short_circuit.h
*
* \brief Functions used to compute and verify short-circuit signatures.
*
* These signatures don't use any cryptographic algorithm and don't
* provide any security guarantees at all. They are provided for
* demonstration purposes, and will not be used unless explicitly
* enabled by users of the library.
*
*/
#ifndef T_COSE_DISABLE_SHORT_CIRCUIT_SIGN
/**
* \brief Compute the size of a short-circuit signature.
*
* \param[in] cose_algorithm_id Algorithm ID. This is used only to make
* the short-circuit signature the same size
* as the real signature would be for the
* particular algorithm.
* \param[out] sig_size The returned size in bytes.
*
* \return An error code or \ref T_COSE_SUCCESS.
*/
enum t_cose_err_t
short_circuit_sig_size(int32_t cose_algorithm_id, size_t *sig_size);
/**
* \brief Create a short-circuit signature
*
* \param[in] cose_algorithm_id Algorithm ID. This is used only to make
* the short-circuit signature the same size
* as the real signature would be for the
* particular algorithm.
* \param[in] hash_to_sign The bytes to sign. Typically, a hash of
* a payload.
* \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
* returned.
*
* \return This returns one of the error codes defined by \ref t_cose_err_t.
*
* This creates the short-circuit signature that is a concatenation of
* hashes up to the expected size of the signature. 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.
*/
enum t_cose_err_t
short_circuit_sign(int32_t cose_algorithm_id,
struct q_useful_buf_c hash_to_sign,
struct q_useful_buf signature_buffer,
struct q_useful_buf_c *signature);
/**
* \brief Verify a short-circuit signature
*
* \param[in] hash_to_verify Pointer and length of hash to verify.
* \param[in] signature Pointer and length of signature.
*
* \return This returns one of the error codes defined by \ref
* t_cose_err_t.
*
* See t_cose_sign1_sign_init() for description of the short-circuit
* signature.
*/
enum t_cose_err_t
t_cose_crypto_short_circuit_verify(struct q_useful_buf_c hash_to_verify,
struct q_useful_buf_c signature);
#endif
#ifdef __cplusplus
}
#endif
#endif

Просмотреть файл

@ -13,7 +13,12 @@
#include "t_cose_standard_constants.h"
#include "t_cose_crypto.h"
#include "t_cose_util.h"
#include "t_cose_short_circuit.h"
#ifndef QCBOR_1_1
// The OpenBytes API we use was only added in 1.1.
#error t_cose requires QCBOR 1.1 or greater
#endif
/**
* \file t_cose_sign1_sign.c
@ -43,90 +48,17 @@
#error COSE algorithm identifier definitions are in error
#endif
#if T_COSE_ALGORITHM_PS256 != COSE_ALGORITHM_PS256
#error COSE algorithm identifier definitions are in error
#endif
#ifndef T_COSE_DISABLE_SHORT_CIRCUIT_SIGN
static inline enum t_cose_err_t
short_circuit_sig_size(int32_t cose_algorithm_id,
size_t *sig_size)
{
*sig_size = cose_algorithm_id == COSE_ALGORITHM_ES256 ? T_COSE_EC_P256_SIG_SIZE :
cose_algorithm_id == COSE_ALGORITHM_ES384 ? T_COSE_EC_P384_SIG_SIZE :
cose_algorithm_id == COSE_ALGORITHM_ES512 ? T_COSE_EC_P512_SIG_SIZE :
0;
return sig_size == 0 ? T_COSE_ERR_UNSUPPORTED_SIGNING_ALG : T_COSE_SUCCESS;
}
/**
* \brief Create a short-circuit signature
*
* \param[in] cose_algorithm_id Algorithm ID. This is used only to make
* the short-circuit signature the same size
* as the real signature would be for the
* particular algorithm.
* \param[in] hash_to_sign The bytes to sign. Typically, a hash of
* a payload.
* \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
* returned.
*
* \return This returns one of the error codes defined by \ref t_cose_err_t.
*
* This creates the short-circuit signature that is a concatenation of
* hashes up to the expected size of the signature. 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_sign(int32_t cose_algorithm_id,
struct q_useful_buf_c hash_to_sign,
struct q_useful_buf signature_buffer,
struct q_useful_buf_c *signature)
{
/* approximate stack use on 32-bit machine: local use: 16 bytes
*/
enum t_cose_err_t return_value;
size_t array_indx;
size_t amount_to_copy;
size_t sig_size;
return_value = short_circuit_sig_size(cose_algorithm_id, &sig_size);
/* Check the signature length against buffer size */
if(return_value != T_COSE_SUCCESS) {
goto Done;
}
if(sig_size > signature_buffer.len) {
/* Buffer too small for this signature type */
return_value = T_COSE_ERR_SIG_BUFFER_SIZE;
goto Done;
}
/* Loop concatening copies of the hash to fill out to signature size */
for(array_indx = 0; array_indx < sig_size; array_indx += hash_to_sign.len) {
amount_to_copy = sig_size - array_indx;
if(amount_to_copy > hash_to_sign.len) {
amount_to_copy = hash_to_sign.len;
}
memcpy((uint8_t *)signature_buffer.ptr + array_indx,
hash_to_sign.ptr,
amount_to_copy);
}
signature->ptr = signature_buffer.ptr;
signature->len = sig_size;
return_value = T_COSE_SUCCESS;
Done:
return return_value;
}
#endif /* T_COSE_DISABLE_SHORT_CIRCUIT_SIGN */
#if T_COSE_ALGORITHM_PS384 != COSE_ALGORITHM_PS384
#error COSE algorithm identifier definitions are in error
#endif
#if T_COSE_ALGORITHM_PS512 != COSE_ALGORITHM_PS512
#error COSE algorithm identifier definitions are in error
#endif
/**
* \brief Makes the protected header parameters for COSE.
@ -243,13 +175,8 @@ t_cose_sign1_encode_parameters_internal(struct t_cose_sign1_sign_ctx *me,
{
enum t_cose_err_t return_value;
struct q_useful_buf_c kid;
int32_t hash_alg_id;
/* Check the cose_algorithm_id now by getting the hash alg as an
* early error check even though it is not used until later.
*/
hash_alg_id = hash_alg_id_from_sig_alg_id(me->cose_algorithm_id);
if(hash_alg_id == T_COSE_INVALID_ALGORITHM_ID) {
if (!signature_algorithm_id_is_supported(me->cose_algorithm_id)) {
return T_COSE_ERR_UNSUPPORTED_SIGNING_ALG;
}
@ -300,6 +227,218 @@ Done:
return return_value;
}
#ifndef T_COSE_DISABLE_SHORT_CIRCUIT_SIGN
/**
* \brief Compute the short-circuit signature for a COSE_Sign1 message.
*
* \param[in] me The t_cose signing context.
* \param[in] aad The Additional Authenticated Data or \c NULL_Q_USEFUL_BUF_C.
* \param[in] payload Pointer and length of payload to sign.
* \param[in] buffer_for_signature Pointer and length of buffer to output to.
* \param[out] signature Pointer and length of the resulting signature.
*
* \returns An error of type \ref t_cose_err_t.
*
* This function does not actually perform any kind of cryptographic
* signature, and should only be used as a test mode.
*
* If \c buffer_for_signature contains a \c NULL pointer, this function
* will compute the necessary size, and set \c signature accordingly.
*/
static inline enum t_cose_err_t
sign1_sign_short_circuit(struct t_cose_sign1_sign_ctx *me,
struct q_useful_buf_c aad,
struct q_useful_buf_c payload,
struct q_useful_buf buffer_for_signature,
struct q_useful_buf_c *signature)
{
enum t_cose_err_t return_value;
Q_USEFUL_BUF_MAKE_STACK_UB( buffer_for_tbs_hash, T_COSE_CRYPTO_MAX_HASH_SIZE);
struct q_useful_buf_c tbs_hash;
/* 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 cose_algorithm_id was checked in
* t_cose_sign1_init() so it doesn't need to be checked here.
*/
return_value = create_tbs_hash(me->cose_algorithm_id,
me->protected_parameters,
aad,
payload,
buffer_for_tbs_hash,
&tbs_hash);
if (return_value) {
goto Done;
}
if (buffer_for_signature.ptr == NULL) {
/* Output size calculation. Only need signature size. */
signature->ptr = NULL;
return_value = short_circuit_sig_size(me->cose_algorithm_id, &signature->len);
} else {
/* Perform the a short circuit signing */
return_value = short_circuit_sign(me->cose_algorithm_id,
tbs_hash,
buffer_for_signature,
signature);
}
Done:
return return_value;
}
#endif /* T_COSE_DISABLE_SHORT_CIRCUIT_SIGN */
#ifndef T_COSE_DISABLE_EDDSA
/**
* \brief Compute an EDDSA signature for a COSE_Sign1 message.
*
* \param[in] me The t_cose signing context.
* \param[in] aad The Additional Authenticated Data or \c NULL_Q_USEFUL_BUF_C.
* \param[in] payload Pointer and length of payload to sign.
* \param[in] buffer_for_signature Pointer and length of buffer to output to.
* \param[out] signature Pointer and length of the resulting signature.
*
* \returns An error of type \ref t_cose_err_t.
*
* Unlike other algorithms, EDDSA signing requires two passes over the
* to-be-signed data, and therefore cannot be performed incrementally.
* This function serializes the to-be-signed bytes and uses the crypto
* adapter to compute the signature over them. An auxiliary buffer,
* used to store the to-be-signed bytes, must have previously been
* configured by calling the \ref t_cose_sign1_sign_set_auxiliary_buffer
* function.
*
* If \c buffer_for_signature contains a \c NULL pointer, this function
* will compute the necessary size, and update \c signature accordingly.
*/
static inline enum t_cose_err_t
sign1_sign_eddsa(struct t_cose_sign1_sign_ctx *me,
struct q_useful_buf_c aad,
struct q_useful_buf_c payload,
struct q_useful_buf buffer_for_signature,
struct q_useful_buf_c *signature)
{
enum t_cose_err_t return_value;
struct q_useful_buf_c tbs;
/* Serialize the TBS data into the auxiliary buffer.
* If auxiliary_buffer.ptr is NULL this will succeed, computing
* the necessary size.
*/
return_value = create_tbs(me->protected_parameters,
aad,
payload,
me->auxiliary_buffer,
&tbs);
if (return_value == T_COSE_ERR_TOO_SMALL) {
/* Be a bit more specific about which buffer is too small */
return_value = T_COSE_ERR_AUXILIARY_BUFFER_SIZE;
}
if (return_value) {
goto Done;
}
/* Record how much buffer we actually used / would have used,
* allowing the caller to allocate an appropriately sized buffer.
* This is particularly useful when buffer_for_signature.ptr is
* NULL and no signing is actually taking place yet.
*/
me->auxiliary_buffer_size = tbs.len;
if (buffer_for_signature.ptr == NULL) {
/* Output size calculation. Only need signature size. */
signature->ptr = NULL;
return_value = t_cose_crypto_sig_size(me->cose_algorithm_id,
me->signing_key,
&signature->len);
} else if (me->auxiliary_buffer.ptr == NULL) {
/* Without a real auxiliary buffer, we have nothing to sign. */
return_value = T_COSE_ERR_NEED_AUXILIARY_BUFFER;
} else {
/* Perform the public key signing over the TBS bytes we just
* serialized.
*/
return_value = t_cose_crypto_sign_eddsa(me->signing_key,
tbs,
buffer_for_signature,
signature);
}
Done:
return return_value;
}
#endif /* T_COSE_DISABLE_EDDSA */
/**
* \brief Compute a signature for a COSE_Sign1 message, following the
* general procedure which works for most algorithms.
*
* \param[in] me The t_cose signing context.
* \param[in] aad The Additional Authenticated Data or \c NULL_Q_USEFUL_BUF_C.
* \param[in] payload Pointer and length of payload to sign.
* \param[in] buffer_for_signature Pointer and length of buffer to output to.
* \param[out] signature Pointer and length of the resulting signature.
*
* \returns An error of type \ref t_cose_err_t.
*
* The message's to-be-signed bytes are hashed incrementally using the
* chosen algorithm's digest function, and the result is signed by the
* crypto adapter.
*
* This function does not support short-circuit signing or EDDSA
* signatures, which require a special procedure. See
* \ref sign1_sign_short_circuit and \ref sign1_sign_eddsa.
*
* If \c buffer_for_signature contains a \c NULL pointer, this function
* will compute the necessary size, and update \c signature accordingly.
*/
static inline enum t_cose_err_t
sign1_sign_default(struct t_cose_sign1_sign_ctx *me,
struct q_useful_buf_c aad,
struct q_useful_buf_c payload,
struct q_useful_buf buffer_for_signature,
struct q_useful_buf_c *signature)
{
enum t_cose_err_t return_value;
Q_USEFUL_BUF_MAKE_STACK_UB( buffer_for_tbs_hash, T_COSE_CRYPTO_MAX_HASH_SIZE);
struct q_useful_buf_c tbs_hash;
/* 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 cose_algorithm_id was checked in
* t_cose_sign1_init() so it doesn't need to be checked here.
*/
return_value = create_tbs_hash(me->cose_algorithm_id,
me->protected_parameters,
aad,
payload,
buffer_for_tbs_hash,
&tbs_hash);
if (return_value) {
goto Done;
}
if (buffer_for_signature.ptr == NULL) {
/* Output size calculation. Only need signature size. */
signature->ptr = NULL;
return_value = t_cose_crypto_sig_size(me->cose_algorithm_id,
me->signing_key,
&signature->len);
} else {
/* Perform the public key signing */
return_value = t_cose_crypto_sign(me->cose_algorithm_id,
me->signing_key,
tbs_hash,
buffer_for_signature,
signature);
}
Done:
return return_value;
}
/*
* Semi-private function. See t_cose_sign1_sign.h
@ -312,17 +451,12 @@ t_cose_sign1_encode_signature_aad_internal(struct t_cose_sign1_sign_ctx *me,
{
enum t_cose_err_t return_value;
QCBORError cbor_err;
/* 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);
/* Buffer for the tbs hash. */
Q_USEFUL_BUF_MAKE_STACK_UB( buffer_for_tbs_hash, T_COSE_CRYPTO_MAX_HASH_SIZE);
/* Pointer and length of the buffer for the signature */
struct q_useful_buf buffer_for_signature;
struct q_useful_buf_c signed_payload;
if(q_useful_buf_c_is_null(detached_payload)) {
QCBOREncode_CloseBstrWrap2(cbor_encode_ctx, false, &signed_payload);
} else {
@ -343,72 +477,47 @@ t_cose_sign1_encode_signature_aad_internal(struct t_cose_sign1_sign_ctx *me,
goto Done;
}
/* 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 cose_algorithm_id was checked in
* t_cose_sign1_init() so it doesn't need to be checked here.
/* The signature gets written directly into the output buffer.
* The matching QCBOREncode_CloseBytes call further down still needs do a
* memmove to make space for the CBOR header, but at least we avoid the need
* to allocate an extra buffer.
*/
return_value = create_tbs_hash(me->cose_algorithm_id,
me->protected_parameters,
aad,
signed_payload,
buffer_for_tbs_hash,
&tbs_hash);
if(return_value) {
goto Done;
}
QCBOREncode_OpenBytes(cbor_encode_ctx, &buffer_for_signature);
/* Compute the signature using public key crypto. The key and
* algorithm ID are passed in to know how and what to sign
* with. The hash of the TBS bytes is what is signed. A buffer
* in which to place the signature is passed in and the
* signature is returned.
*
* That or just compute the length of the signature if this
* is only an output length computation.
/* Sign the message using the appropriate procedure, depending on
* the flags and algorithm.
*/
if(!(me->option_flags & T_COSE_OPT_SHORT_CIRCUIT_SIG)) {
if (QCBOREncode_IsBufferNULL(cbor_encode_ctx)) {
/* Output size calculation. Only need signature size. */
signature.ptr = NULL;
return_value = t_cose_crypto_sig_size(me->cose_algorithm_id,
me->signing_key,
&signature.len);
} else {
/* Perform the public key signing */
return_value = t_cose_crypto_sign(me->cose_algorithm_id,
me->signing_key,
tbs_hash,
buffer_for_signature,
&signature);
}
#ifndef T_COSE_DISABLE_SHORT_CIRCUIT_SIGN
} else {
if (QCBOREncode_IsBufferNULL(cbor_encode_ctx)) {
/* Output size calculation. Only need signature size. */
signature.ptr = NULL;
return_value = short_circuit_sig_size(me->cose_algorithm_id,
&signature.len);
} else {
/* Perform the a short circuit signing */
return_value = short_circuit_sign(me->cose_algorithm_id,
tbs_hash,
buffer_for_signature,
&signature);
}
#endif /* T_COSE_DISABLE_SHORT_CIRCUIT_SIGN */
if (me->option_flags & T_COSE_OPT_SHORT_CIRCUIT_SIG) {
return_value = sign1_sign_short_circuit(me,
aad,
signed_payload,
buffer_for_signature,
&signature);
} else
#endif
#ifndef T_COSE_DISABLE_EDDSA
if (me->cose_algorithm_id == COSE_ALGORITHM_EDDSA) {
return_value = sign1_sign_eddsa(me,
aad,
signed_payload,
buffer_for_signature,
&signature);
} else
#endif
{
return_value = sign1_sign_default(me,
aad,
signed_payload,
buffer_for_signature,
&signature);
}
if(return_value != T_COSE_SUCCESS) {
if (return_value)
goto Done;
}
/* Add signature to CBOR and close out the array */
QCBOREncode_AddBytes(cbor_encode_ctx, signature);
QCBOREncode_CloseBytes(cbor_encode_ctx, signature.len);
QCBOREncode_CloseArray(cbor_encode_ctx);
/* The layer above this must check for and handle CBOR encoding
@ -482,6 +591,15 @@ t_cose_sign1_sign_aad_internal(struct t_cose_sign1_sign_ctx *me,
goto Done;
}
QCBORError cbor_err = QCBOREncode_GetErrorState(&encode_context);
if(cbor_err == QCBOR_ERR_BUFFER_TOO_SMALL) {
return_value = T_COSE_ERR_TOO_SMALL;
goto Done;
} else if(cbor_err != QCBOR_SUCCESS) {
return_value = T_COSE_ERR_CBOR_FORMATTING;
goto Done;
}
/* -- Close off and get the resulting encoded CBOR -- */
if(QCBOREncode_Finish(&encode_context, result)) {
return_value = T_COSE_ERR_CBOR_NOT_WELL_FORMED;

Просмотреть файл

@ -1,7 +1,7 @@
/*
* t_cose_sign1_verify.c
*
* Copyright 2019-2021, Laurence Lundblade
* Copyright 2019-2022, Laurence Lundblade
*
* SPDX-License-Identifier: BSD-3-Clause
*
@ -19,6 +19,7 @@
#include "t_cose_crypto.h"
#include "t_cose_util.h"
#include "t_cose_parameters.h"
#include "t_cose_short_circuit.h"
@ -29,50 +30,6 @@
*/
#ifndef T_COSE_DISABLE_SHORT_CIRCUIT_SIGN
/**
* \brief Verify a short-circuit signature
*
* \param[in] hash_to_verify Pointer and length of hash to verify.
* \param[in] signature Pointer and length of signature.
*
* \return This returns one of the error codes defined by \ref
* t_cose_err_t.
*
* See t_cose_sign1_sign_init() for description of the short-circuit
* signature.
*/
static inline enum t_cose_err_t
t_cose_crypto_short_circuit_verify(struct q_useful_buf_c hash_to_verify,
struct q_useful_buf_c signature)
{
/* Aproximate stack usage
* 64-bit 32-bit
* local vars 24 12
* TOTAL 24 12
*/
struct q_useful_buf_c hash_from_sig;
enum t_cose_err_t return_value;
hash_from_sig = q_useful_buf_head(signature, hash_to_verify.len);
if(q_useful_buf_c_is_null(hash_from_sig)) {
return_value = T_COSE_ERR_SIG_VERIFY;
goto Done;
}
if(q_useful_buf_compare(hash_from_sig, hash_to_verify)) {
return_value = T_COSE_ERR_SIG_VERIFY;
} else {
return_value = T_COSE_SUCCESS;
}
Done:
return return_value;
}
#endif /* T_COSE_DISABLE_SHORT_CIRCUIT_SIGN */
/**
* \brief Check the tagging of the COSE about to be verified.
*
@ -187,6 +144,213 @@ qcbor_decode_error_to_t_cose_error(QCBORError qcbor_error)
}
#ifndef T_COSE_DISABLE_SHORT_CIRCUIT_SIGN
/**
* \brief Verify the short-circuit signature of a COSE_Sign1 message.
*
* \param[in] me The t_cose signature verification context.
* \param[in] parameters The previously decoded parameters from the message.
* \param[in] protected_parameters Full, CBOR encoded, protected parameters.
* \param[in] aad The Additional Authenticated Data or \c NULL_Q_USEFUL_BUF_C.
* \param[in] payload Pointer and length of the message's payload.
* \param[in] signature Pointer and length of the message's signature.
*
* \return This returns one of the error codes defined by \ref t_cose_err_t.
*
* This function always succeeds if the \ref T_COSE_OPT_DECODE_ONLY
* flag is set.
*
* No actual cryptographic algorithm is used, and a successful
* verification does not provide any security guarantees. To avoid
* accidental bypass of signature verification, the \ref T_COSE_OPT_ALLOW_SHORT_CIRCUIT
* flag must be set in the verification context.
*/
static inline enum t_cose_err_t
sign1_verify_short_circuit(struct t_cose_sign1_verify_ctx *me,
const struct t_cose_parameters *parameters,
struct q_useful_buf_c signature,
struct q_useful_buf_c protected_parameters,
struct q_useful_buf_c aad,
struct q_useful_buf_c payload)
{
enum t_cose_err_t return_value;
Q_USEFUL_BUF_MAKE_STACK_UB(buffer_for_tbs_hash, T_COSE_CRYPTO_MAX_HASH_SIZE);
struct q_useful_buf_c tbs_hash;
if(me->option_flags & T_COSE_OPT_DECODE_ONLY) {
return_value = T_COSE_SUCCESS;
goto Done;
}
if(!(me->option_flags & T_COSE_OPT_ALLOW_SHORT_CIRCUIT)) {
return_value = T_COSE_ERR_SHORT_CIRCUIT_SIG;
goto Done;
}
/* -- Compute the TBS hash -- */
return_value = create_tbs_hash(parameters->cose_algorithm_id,
protected_parameters,
aad,
payload,
buffer_for_tbs_hash,
&tbs_hash);
if(return_value) {
goto Done;
}
return_value = t_cose_crypto_short_circuit_verify(tbs_hash, signature);
Done:
return return_value;
}
#endif /* T_COSE_DISABLE_SHORT_CIRCUIT_SIGN */
#ifndef T_COSE_DISABLE_EDDSA
/**
* \brief Verify the EDDSA signature from a COSE_Sign1 message.
*
* \param[in] me The t_cose signature verification context.
* \param[in] parameters The previously decoded parameters from the message.
* \param[in] protected_parameters Full, CBOR encoded, protected parameters.
* \param[in] aad The Additional Authenticated Data or \c NULL_Q_USEFUL_BUF_C.
* \param[in] payload Pointer and length of the message's payload.
* \param[in] signature Pointer and length of the message's signature.
*
* \return This returns one of the error codes defined by \ref t_cose_err_t.
*
* Unlike other algorithms, EDDSA verification requires two passes over
* the to-be-signed data, and therefore cannot be performed incrementally.
* This function serializes the to-be-signed bytes and uses the crypto
* adapter to verify the signature. An auxiliary buffer, used to store
* the to-be-signed bytes, must have previously been configured by
* calling the \ref t_cose_sign1_verify_set_auxiliary_buffer function.
*
* Signature verification is skipped if the \ref T_COSE_OPT_DECODE_ONLY
* flag is set. This mode can however be used to determine the
* necessary size for the auxiliary buffer.
*/
static enum t_cose_err_t
sign1_verify_eddsa(struct t_cose_sign1_verify_ctx *me,
const struct t_cose_parameters *parameters,
struct q_useful_buf_c signature,
struct q_useful_buf_c protected_parameters,
struct q_useful_buf_c aad,
struct q_useful_buf_c payload)
{
enum t_cose_err_t return_value;
struct q_useful_buf_c tbs;
/* We need to serialize the Sig_structure (rather than hashing it
* incrementally) before signing. We do this before checking for
* the DECODE_ONLY option, as this allows the caller to discover
* the necessary buffer size (create_tbs supports a NULL
* auxiliary_buffer, and we record the size the structure would
* have occupied).
*/
return_value = create_tbs(protected_parameters,
aad,
payload,
me->auxiliary_buffer,
&tbs);
if (return_value == T_COSE_ERR_TOO_SMALL) {
/* Be a bit more specific about which buffer is too small */
return_value = T_COSE_ERR_AUXILIARY_BUFFER_SIZE;
}
if (return_value) {
goto Done;
}
/* Record how much buffer we actually used / would have used,
* allowing the caller to allocate an appropriately sized buffer.
* This is particularly useful in DECODE_ONLY mode.
*/
me->auxiliary_buffer_size = tbs.len;
if(me->option_flags & T_COSE_OPT_DECODE_ONLY) {
return_value = T_COSE_SUCCESS;
goto Done;
}
if (me->auxiliary_buffer.ptr == NULL) {
return_value = T_COSE_ERR_NEED_AUXILIARY_BUFFER;
goto Done;
}
return_value = t_cose_crypto_verify_eddsa(me->verification_key,
parameters->kid,
tbs,
signature);
Done:
return return_value;
}
#endif /* T_COSE_DISABLE_EDDSA */
/**
* \brief Verify the signature from a COSE_Sign1 message, following
* the general process which work for most algorithms.
*
* \param[in] me The t_cose signature verification context.
* \param[in] parameters The previously decoded parameters from the message.
* \param[in] protected_parameters Full, CBOR encoded, protected parameters.
* \param[in] aad The Additional Authenticated Data or \c NULL_Q_USEFUL_BUF_C.
* \param[in] payload Pointer and length of the message's payload.
* \param[in] signature Pointer and length of the message's signature.
*
* \return This returns one of the error codes defined by \ref t_cose_err_t.
*
* This function always succeeds if the \ref T_COSE_OPT_DECODE_ONLY
* flag is set.
*
* Short-circuit signing or EDDSA signatures, which require a special
* procedure, are not supported. See \ref sign1_sign_short_circuit and
* \ref sign1_sign_eddsa.
*/
static enum t_cose_err_t
sign1_verify_default(struct t_cose_sign1_verify_ctx *me,
const struct t_cose_parameters *parameters,
struct q_useful_buf_c signature,
struct q_useful_buf_c protected_parameters,
struct q_useful_buf_c aad,
struct q_useful_buf_c payload)
{
enum t_cose_err_t return_value;
Q_USEFUL_BUF_MAKE_STACK_UB(buffer_for_tbs_hash, T_COSE_CRYPTO_MAX_HASH_SIZE);
struct q_useful_buf_c tbs_hash;
if(me->option_flags & T_COSE_OPT_DECODE_ONLY) {
return_value = T_COSE_SUCCESS;
goto Done;
}
/* -- Compute the TBS hash -- */
return_value = create_tbs_hash(parameters->cose_algorithm_id,
protected_parameters,
aad,
payload,
buffer_for_tbs_hash,
&tbs_hash);
if(return_value) {
goto Done;
}
/* -- Call crypto adapter to verify the signature -- */
return_value = t_cose_crypto_verify(parameters->cose_algorithm_id,
me->verification_key,
parameters->kid,
tbs_hash,
signature);
Done:
return return_value;
}
/*
* Semi-private function. See t_cose_sign1_verify.h
*/
enum t_cose_err_t
t_cose_sign1_verify_internal(struct t_cose_sign1_verify_ctx *me,
struct q_useful_buf_c cose_sign1,
@ -211,12 +375,11 @@ t_cose_sign1_verify_internal(struct t_cose_sign1_verify_ctx *me,
QCBORDecodeContext decode_context;
struct q_useful_buf_c protected_parameters;
enum t_cose_err_t return_value;
Q_USEFUL_BUF_MAKE_STACK_UB( buffer_for_tbs_hash, T_COSE_CRYPTO_MAX_HASH_SIZE);
struct q_useful_buf_c tbs_hash;
struct q_useful_buf_c signature;
struct t_cose_label_list critical_parameter_labels;
struct t_cose_label_list unknown_parameter_labels;
struct t_cose_parameters parameters;
struct q_useful_buf_c signed_payload;
QCBORError qcbor_error;
#ifndef T_COSE_DISABLE_SHORT_CIRCUIT_SIGN
struct q_useful_buf_c short_circuit_kid;
@ -265,6 +428,7 @@ t_cose_sign1_verify_internal(struct t_cose_sign1_verify_ctx *me,
/* --- The payload --- */
if(is_dc) {
signed_payload = *payload;
QCBORItem tmp;
QCBORDecode_GetNext(&decode_context, &tmp);
if (tmp.uDataType != QCBOR_TYPE_NULL) {
@ -272,10 +436,10 @@ t_cose_sign1_verify_internal(struct t_cose_sign1_verify_ctx *me,
goto Done;
}
/* In detached content mode, the payload should be set by
* function caller, so there is no need to set tye payload.
* function caller, so there is no need to set the payload.
*/
} else {
QCBORDecode_GetByteString(&decode_context, payload);
QCBORDecode_GetByteString(&decode_context, &signed_payload);
}
/* --- The signature --- */
@ -308,54 +472,34 @@ t_cose_sign1_verify_internal(struct t_cose_sign1_verify_ctx *me,
goto Done;
}
/* -- Skip signature verification if requested --*/
if(me->option_flags & T_COSE_OPT_DECODE_ONLY) {
return_value = T_COSE_SUCCESS;
goto Done;
}
/* -- Compute the TBS bytes -- */
return_value = create_tbs_hash(parameters.cose_algorithm_id,
protected_parameters,
aad,
*payload,
buffer_for_tbs_hash,
&tbs_hash);
if(return_value) {
goto Done;
}
/* -- Check for short-circuit signature and verify if it exists -- */
#ifndef T_COSE_DISABLE_SHORT_CIRCUIT_SIGN
short_circuit_kid = get_short_circuit_kid();
if(!q_useful_buf_compare(parameters.kid, short_circuit_kid)) {
if(!(me->option_flags & T_COSE_OPT_ALLOW_SHORT_CIRCUIT)) {
return_value = T_COSE_ERR_SHORT_CIRCUIT_SIG;
goto Done;
}
return_value = t_cose_crypto_short_circuit_verify(tbs_hash, signature);
return_value = sign1_verify_short_circuit(me, &parameters, signature, protected_parameters, aad, signed_payload);
goto Done;
}
#endif /* T_COSE_DISABLE_SHORT_CIRCUIT_SIGN */
#ifndef T_COSE_DISABLE_EDDSA
if (parameters.cose_algorithm_id == COSE_ALGORITHM_EDDSA) {
return_value = sign1_verify_eddsa(me, &parameters, signature, protected_parameters, aad, signed_payload);
goto Done;
}
#endif
/* -- Verify the signature (if it wasn't short-circuit) -- */
return_value = t_cose_crypto_verify(parameters.cose_algorithm_id,
me->verification_key,
parameters.kid,
tbs_hash,
signature);
return_value = sign1_verify_default(me, &parameters, signature, protected_parameters, aad, signed_payload);
Done:
if(returned_parameters != NULL) {
*returned_parameters = parameters;
if (return_value == T_COSE_SUCCESS)
{
if(returned_parameters != NULL) {
*returned_parameters = parameters;
}
if(!is_dc && payload != NULL) {
*payload = signed_payload;
}
}
return return_value;
}

Просмотреть файл

@ -163,6 +163,20 @@
*/
#define COSE_ALGORITHM_ES256 -7
/**
* \def COSE_ALGORITHM_EDDSA
*
* \brief Indicates EDDSA.
*
* Value for \ref COSE_HEADER_PARAM_ALG to indicate EDDSA.
*
* Keys using either the edwards25519 or edwards448 curves can be used
* with this algorithm.
*
* See https://tools.ietf.org/search/rfc8032 and https://tools.ietf.org/html/rfc8152
*/
#define COSE_ALGORITHM_EDDSA -8
/**
* \def COSE_ALGORITHM_ES384
*
@ -189,6 +203,38 @@
*/
#define COSE_ALGORITHM_ES512 -36
/**
* \def COSE_ALGORITHM_PS256
*
* \brief Indicates RSASSA-PSS with SHA-256.
*
* Value for \ref COSE_HEADER_PARAM_ALG to indicate RSASSA-PSS with SHA-256.
*
* See https://tools.ietf.org/search/rfc8230 and https://tools.ietf.org/html/rfc8152
*/
#define COSE_ALGORITHM_PS256 -37
/**
* \def COSE_ALGORITHM_PS384
*
* \brief Indicates RSASSA-PSS with SHA-384.
*
* Value for \ref COSE_HEADER_PARAM_ALG to indicate RSASSA-PSS with SHA-384.
*
* See https://tools.ietf.org/search/rfc8230 and https://tools.ietf.org/html/rfc8152
*/
#define COSE_ALGORITHM_PS384 -38
/**
* \def COSE_ALGORITHM_PS512
*
* \brief Indicates RSASSA-PSS with SHA-512.
*
* Value for \ref COSE_HEADER_PARAM_ALG to indicate RSASSA-PSS with SHA-512.
*
* See https://tools.ietf.org/search/rfc8230 and https://tools.ietf.org/html/rfc8152
*/
#define COSE_ALGORITHM_PS512 -39
/**
* \def COSE_ALGORITHM_SHA_256

79
3rdparty/exported/t_cose/src/t_cose_util.c поставляемый
Просмотреть файл

@ -24,6 +24,43 @@
* primarily the to-be-signed bytes hashing.
*/
/*
* Public function. See t_cose_util.h
*/
bool signature_algorithm_id_is_supported(int32_t cose_algorithm_id)
{
return (cose_algorithm_id == COSE_ALGORITHM_ES256)
#ifndef T_COSE_DISABLE_ES384
|| (cose_algorithm_id == COSE_ALGORITHM_ES384)
#endif
#ifndef T_COSE_DISABLE_ES512
|| (cose_algorithm_id == COSE_ALGORITHM_ES512)
#endif
#ifndef T_COSE_DISABLE_PS256
|| (cose_algorithm_id == COSE_ALGORITHM_PS256)
#endif
#ifndef T_COSE_DISABLE_PS384
|| (cose_algorithm_id == COSE_ALGORITHM_PS384)
#endif
#ifndef T_COSE_DISABLE_PS512
|| (cose_algorithm_id == COSE_ALGORITHM_PS512)
#endif
#ifndef T_COSE_DISABLE_EDDSA
|| (cose_algorithm_id == COSE_ALGORITHM_EDDSA)
#endif
;
}
/*
* Public function.
*
* This is declared in t_cose_common.h, but there is no t_cose_common.c,
* so this little function is put here.*/
bool
t_cose_is_algorithm_supported(int32_t cose_algorithm_id)
{
return t_cose_crypto_is_algorithm_supported(cose_algorithm_id);
}
/*
* Public function. See t_cose_util.h
@ -44,12 +81,48 @@ int32_t hash_alg_id_from_sig_alg_id(int32_t cose_algorithm_id)
#endif
#ifndef T_COSE_DISABLE_ES512
cose_algorithm_id == COSE_ALGORITHM_ES512 ? COSE_ALGORITHM_SHA_512 :
#endif
#ifndef T_COSE_DISABLE_PS256
cose_algorithm_id == COSE_ALGORITHM_PS256 ? COSE_ALGORITHM_SHA_256 :
#endif
#ifndef T_COSE_DISABLE_PS384
cose_algorithm_id == COSE_ALGORITHM_PS384 ? COSE_ALGORITHM_SHA_384 :
#endif
#ifndef T_COSE_DISABLE_PS512
cose_algorithm_id == COSE_ALGORITHM_PS512 ? COSE_ALGORITHM_SHA_512 :
#endif
T_COSE_INVALID_ALGORITHM_ID;
}
/*
* Public function. See t_cose_util.h
*/
enum t_cose_err_t
create_tbs(struct q_useful_buf_c protected_parameters,
struct q_useful_buf_c aad,
struct q_useful_buf_c payload,
struct q_useful_buf buffer_for_tbs,
struct q_useful_buf_c *tbs)
{
QCBOREncodeContext cbor_context;
QCBOREncode_Init(&cbor_context, buffer_for_tbs);
QCBOREncode_OpenArray(&cbor_context);
QCBOREncode_AddSZString(&cbor_context, COSE_SIG_CONTEXT_STRING_SIGNATURE1);
QCBOREncode_AddBytes(&cbor_context, protected_parameters);
QCBOREncode_AddBytes(&cbor_context, aad);
QCBOREncode_AddBytes(&cbor_context, payload);
QCBOREncode_CloseArray(&cbor_context);
QCBORError cbor_err = QCBOREncode_Finish(&cbor_context, tbs);
if (cbor_err == QCBOR_ERR_BUFFER_TOO_SMALL) {
return T_COSE_ERR_TOO_SMALL;
} else if (cbor_err != QCBOR_SUCCESS) {
return T_COSE_ERR_CBOR_FORMATTING;
} else {
return T_COSE_SUCCESS;
}
}
/**
* \brief Hash an encoded bstr without actually encoding it in memory
@ -126,6 +199,11 @@ enum t_cose_err_t create_tbs_hash(int32_t cose_algorithm_id,
/* Start the hashing */
hash_alg_id = hash_alg_id_from_sig_alg_id(cose_algorithm_id);
if (hash_alg_id == T_COSE_INVALID_ALGORITHM_ID) {
return_value = T_COSE_ERR_UNSUPPORTED_SIGNING_ALG;
goto Done;
}
/* Don't check hash_alg_id for failure. t_cose_crypto_hash_start()
* will handle error properly. It was also checked earlier.
*/
@ -206,4 +284,5 @@ struct q_useful_buf_c get_short_circuit_kid(void)
return short_circuit_kid;
}
#endif

64
3rdparty/exported/t_cose/src/t_cose_util.h поставляемый
Просмотреть файл

@ -36,6 +36,22 @@ extern "C" {
*/
#define T_COSE_INVALID_ALGORITHM_ID COSE_ALGORITHM_RESERVED
/**
* \brief Check whether a signature algorithm is valid and supported
* by the library.
*
* \param[in] cose_algorithm_id A COSE signature algorithm identifier.
*
* \return \c true if the algorithm is supported.
*
* What algorithms are supported can change as more algorithms are
* added to the library, and depend on the build configuration. Even
* if a signature algorithm is supported by the t_cose library and
* this function returns true, using an algorithm can fail for other
* reasons, for example if the crypto adapter does not support it.
*
*/
bool signature_algorithm_id_is_supported(int32_t cose_algorithm_id);
/**
* \brief Return hash algorithm ID from a signature algorithm ID
@ -43,7 +59,8 @@ extern "C" {
* \param[in] cose_algorithm_id A COSE signature algorithm identifier.
*
* \return \c T_COSE_INVALID_ALGORITHM_ID when the signature algorithm ID
is not known.
is not known, or if the signature algorithm does not have
an associated hash algorithm (eg. EDDSA).
*
* This works off of algorithm identifiers defined in the
* [IANA COSE Registry](https://www.iana.org/assignments/cose/cose.xhtml).
@ -89,13 +106,17 @@ int32_t hash_alg_id_from_sig_alg_id(int32_t cose_algorithm_id);
* \retval T_COSE_ERR_HASH_GENERAL_FAIL
* In case of some general hash failure.
*
* The input to the public key signature algorithm in COSE is the hash
* of a CBOR encoded structure containing the protected parameters
* algorithm ID and a few other things. This formats that structure
* and computes the hash of it. These are known as the to-be-signed or
* "TBS" bytes. The exact specification is in [RFC 8152 section
* The input to the public key signature algorithm in COSE is a CBOR
* encoded structure containing the protected parameters algorithm ID
* and a few other things. These are known as the to-be-signed or "TBS"
* bytes. The exact specification is in [RFC 8152 section
* 4.4](https://tools.ietf.org/html/rfc8152#section-4.4).
*
* Most algorithms use a hash of these bytes, which this function
* computes incrementally. If the entire TBS structure is needed
* (for signing with EdDSA for example), the \ref create_tbs function
* can be used instead.
*
* \c aad can be \ref NULL_Q_USEFUL_BUF_C if not present.
*/
enum t_cose_err_t create_tbs_hash(int32_t cose_algorithm_id,
@ -105,6 +126,37 @@ enum t_cose_err_t create_tbs_hash(int32_t cose_algorithm_id,
struct q_useful_buf buffer_for_hash,
struct q_useful_buf_c *hash);
/**
* Serialize the to-be-signed (TBS) bytes for COSE.
*
* \param[in] protected_parameters Full, CBOR encoded, protected parameters.
* \param[in] aad Additional Authenitcated Data to be
* included in TBS.
* \param[in] payload The CBOR-encoded payload.
* \param[in] buffer_for_tbs Pointer and length of buffer into which
* the resulting TBS bytes is put.
* \param[out] tbs Pointer and length of the
* resulting TBS bytes.
*
* \return This returns one of the error codes defined by \ref t_cose_err_t.
* \retval T_COSE_ERR_TOO_SMALL
* The output buffer is too small.
* \retval T_COSE_ERR_CBOR_FORMATTING
* Something went wrong formatting the CBOR.
*
* The input to the public key signature algorithm in COSE is a CBOR
* encoded structure containing the protected parameters algorithm ID
* and a few other things. These are known as the to-be-signed or "TBS"
* bytes. The exact specification is in [RFC 8152 section
* 4.4](https://tools.ietf.org/html/rfc8152#section-4.4).
*
* \c aad can be \ref NULL_Q_USEFUL_BUF_C if not present.
*/
enum t_cose_err_t create_tbs(struct q_useful_buf_c protected_parameters,
struct q_useful_buf_c aad,
struct q_useful_buf_c payload,
struct q_useful_buf buffer_for_tbs,
struct q_useful_buf_c *tbs);

Просмотреть файл

@ -47,6 +47,9 @@
E73CDABE23A7316700D262E0 /* run_tests.c in Sources */ = {isa = PBXBuildFile; fileRef = E72FB01C231ADAA8000970FE /* run_tests.c */; };
E73CDABF23A7316700D262E0 /* t_cose_sign1_sign.c in Sources */ = {isa = PBXBuildFile; fileRef = E7E36E8E226CB9460040613B /* t_cose_sign1_sign.c */; };
E73CDAD423AD4F3900D262E0 /* t_cose_psa_crypto.c in Sources */ = {isa = PBXBuildFile; fileRef = E73CDAD223AD4E6D00D262E0 /* t_cose_psa_crypto.c */; };
E73FDFC528B6BB32002CF0CC /* t_cose_short_circuit.c in Sources */ = {isa = PBXBuildFile; fileRef = E73FDFC328B6BB32002CF0CC /* t_cose_short_circuit.c */; };
E73FDFC628B6BB62002CF0CC /* t_cose_short_circuit.c in Sources */ = {isa = PBXBuildFile; fileRef = E73FDFC328B6BB32002CF0CC /* t_cose_short_circuit.c */; };
E73FDFC728B6BB63002CF0CC /* t_cose_short_circuit.c in Sources */ = {isa = PBXBuildFile; fileRef = E73FDFC328B6BB32002CF0CC /* t_cose_short_circuit.c */; };
E74FFBBA263BAB38003B66FF /* libcrypto.a in Frameworks */ = {isa = PBXBuildFile; fileRef = E74FFBB8263BAB0D003B66FF /* libcrypto.a */; };
E772026F23CAEC84006E966E /* t_cose_sign1_verify.c in Sources */ = {isa = PBXBuildFile; fileRef = E7E36E8A226CB9460040613B /* t_cose_sign1_verify.c */; };
E772027123CAEC84006E966E /* t_cose_test.c in Sources */ = {isa = PBXBuildFile; fileRef = E7F70AC52270DFAE007CE07F /* t_cose_test.c */; };
@ -160,6 +163,8 @@
E73BF71C23B07ACF00DF5C36 /* t_cose_basic_example_openssl */ = {isa = PBXFileReference; explicitFileType = "compiled.mach-o.executable"; includeInIndex = 0; path = t_cose_basic_example_openssl; sourceTree = BUILT_PRODUCTS_DIR; };
E73CDAC623A7316700D262E0 /* t_cose_psa */ = {isa = PBXFileReference; explicitFileType = "compiled.mach-o.executable"; includeInIndex = 0; path = t_cose_psa; sourceTree = BUILT_PRODUCTS_DIR; };
E73CDAD223AD4E6D00D262E0 /* t_cose_psa_crypto.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = t_cose_psa_crypto.c; sourceTree = "<group>"; };
E73FDFC328B6BB32002CF0CC /* t_cose_short_circuit.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = t_cose_short_circuit.c; sourceTree = "<group>"; };
E73FDFC428B6BB32002CF0CC /* t_cose_short_circuit.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = t_cose_short_circuit.h; sourceTree = "<group>"; };
E7489C9F259F8B4B0004634C /* qcbor_encode.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = qcbor_encode.h; path = ../../../../../usr/local/include/qcbor/qcbor_encode.h; sourceTree = "<group>"; };
E7489CA0259F8B4B0004634C /* qcbor_common.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = qcbor_common.h; path = ../../../../../usr/local/include/qcbor/qcbor_common.h; sourceTree = "<group>"; };
E7489CA1259F8B4B0004634C /* qcbor_spiffy_decode.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = qcbor_spiffy_decode.h; path = ../../../../../usr/local/include/qcbor/qcbor_spiffy_decode.h; sourceTree = "<group>"; };
@ -347,6 +352,8 @@
E7E36E86226CB9460040613B /* src */ = {
isa = PBXGroup;
children = (
E73FDFC328B6BB32002CF0CC /* t_cose_short_circuit.c */,
E73FDFC428B6BB32002CF0CC /* t_cose_short_circuit.h */,
E71D9ECA23341D8200A21F7F /* t_cose_standard_constants.h */,
E7E36E89226CB9460040613B /* t_cose_util.c */,
E7E36E8A226CB9460040613B /* t_cose_sign1_verify.c */,
@ -556,6 +563,7 @@
files = (
E730E60B23612DAB00175CE0 /* t_cose_sign1_verify.c in Sources */,
E730E60C23612DAB00175CE0 /* run_tests.c in Sources */,
E73FDFC528B6BB32002CF0CC /* t_cose_short_circuit.c in Sources */,
E730E62123612E3900175CE0 /* t_cose_test_crypto.c in Sources */,
E730E61123612DAB00175CE0 /* t_cose_parameters.c in Sources */,
E730E61223612DAB00175CE0 /* t_cose_make_test_messages.c in Sources */,
@ -601,6 +609,7 @@
E73CDAAE23A7316700D262E0 /* t_cose_sign1_verify.c in Sources */,
E73CDAB023A7316700D262E0 /* t_cose_test.c in Sources */,
E73CDAD423AD4F3900D262E0 /* t_cose_psa_crypto.c in Sources */,
E73FDFC728B6BB63002CF0CC /* t_cose_short_circuit.c in Sources */,
E73CDAB223A7316700D262E0 /* t_cose_util.c in Sources */,
E73CDAB623A7316700D262E0 /* t_cose_parameters.c in Sources */,
E73CDAB823A7316700D262E0 /* t_cose_sign_verify_test.c in Sources */,
@ -641,6 +650,7 @@
E721CB9A2362ABA400C7FD56 /* t_cose_make_openssl_test_key.c in Sources */,
E7E36EA5226CBB570040613B /* t_cose_openssl_crypto.c in Sources */,
0F91057A2321878F00008572 /* t_cose_parameters.c in Sources */,
E73FDFC628B6BB62002CF0CC /* t_cose_short_circuit.c in Sources */,
0F8B2FEF2345A33A00A22349 /* t_cose_make_test_messages.c in Sources */,
E7E36E90226CB9460040613B /* t_cose_util.c in Sources */,
E721CB9B2362AC2A00C7FD56 /* t_cose_sign_verify_test.c in Sources */,

6
3rdparty/exported/t_cose/test/run_tests.c поставляемый
Просмотреть файл

@ -61,7 +61,9 @@ static test_entry s_tests[] = {
TEST_ENTRY(sign_verify_make_cwt_test),
TEST_ENTRY(sign_verify_sig_fail_test),
TEST_ENTRY(sign_verify_get_size_test),
TEST_ENTRY(known_good_test),
TEST_ENTRY(sign_verify_known_good_test),
TEST_ENTRY(sign_verify_unsupported_test),
TEST_ENTRY(sign_verify_bad_auxiliary_buffer),
#endif /* T_COSE_DISABLE_SIGN_VERIFY_TESTS */
#ifndef T_COSE_DISABLE_SHORT_CIRCUIT_SIGN
@ -231,7 +233,7 @@ int RunTestsTCose(const char *szTestNames[],
}
}
int nTestResult = (t->test_fun)();
int32_t nTestResult = (int32_t)(t->test_fun)();
nTestsRun++;
if(pfOutput) {
(*pfOutput)(t->szTestName, poutCtx, 0);

Просмотреть файл

@ -22,14 +22,7 @@
*
* They are made by:
*
* openssl ecparam -genkey -name prime256v1 -noout -out ec256-key-pair.pem
*
* Edit the PEM headers off so it is just b64
*
* base64 --decode to get the pure DER
*
* xxd -i to turn it into a C variable
*
* openssl ecparam -genkey -name prime256v1 | sed -e '1d' -e '$d' | base64 --decode | xxd -i
*
* See also:
* https://stackoverflow.com/
@ -91,37 +84,66 @@ static const unsigned char ec521_key_pair[] = {
0x43, 0xc0, 0xa8, 0x52, 0x1f, 0xf9, 0x53
};
static const unsigned char rsa2048_private_key[] = {
#include "t_cose_rsa_test_key.h"
};
static const unsigned char ed25519_private_key[] = {
0x30, 0x2e, 0x02, 0x01, 0x00, 0x30, 0x05, 0x06, 0x03, 0x2b, 0x65, 0x70,
0x04, 0x22, 0x04, 0x20, 0x5f, 0xe3, 0x9b, 0x74, 0x55, 0xa0, 0x73, 0xd1,
0x38, 0xc2, 0xe7, 0xd4, 0xe5, 0x06, 0x30, 0x52, 0x9f, 0xce, 0x7d, 0xdc,
0xe8, 0x22, 0x80, 0x2a, 0x68, 0x5d, 0xa8, 0x99, 0x16, 0x5d, 0x44, 0x58
};
/*
* Public function, see t_cose_make_test_pub_key.h
*/
/*
* The key object returned by this is malloced and has to be freed by
* by calling free_ecdsa_key_pair(). This heap use is a part of
* by calling free_key_pair(). This heap use is a part of
* OpenSSL and not t_cose which does not use the heap.
*/
enum t_cose_err_t make_ecdsa_key_pair(int32_t cose_algorithm_id,
enum t_cose_err_t make_key_pair(int32_t cose_algorithm_id,
struct t_cose_key *key_pair)
{
enum t_cose_err_t return_value;
EVP_PKEY *pkey;
const uint8_t *rfc5915_key;
long rfc5915_key_len;
int key_type;
const uint8_t *key_data;
long key_len;
switch (cose_algorithm_id) {
case T_COSE_ALGORITHM_ES256:
rfc5915_key = ec256_key_pair;
rfc5915_key_len = sizeof(ec256_key_pair);
key_type = EVP_PKEY_EC;
key_data = ec256_key_pair;
key_len = sizeof(ec256_key_pair);
break;
case T_COSE_ALGORITHM_ES384:
rfc5915_key = ec384_key_pair;
rfc5915_key_len = sizeof(ec384_key_pair);
key_type = EVP_PKEY_EC;
key_data = ec384_key_pair;
key_len = sizeof(ec384_key_pair);
break;
case T_COSE_ALGORITHM_ES512:
rfc5915_key = ec521_key_pair;
rfc5915_key_len = sizeof(ec521_key_pair);
key_type = EVP_PKEY_EC;
key_data = ec521_key_pair;
key_len = sizeof(ec521_key_pair);
break;
case T_COSE_ALGORITHM_PS256:
case T_COSE_ALGORITHM_PS384:
case T_COSE_ALGORITHM_PS512:
key_type = EVP_PKEY_RSA;
key_data = rsa2048_private_key;
key_len = sizeof(rsa2048_private_key);
break;
case T_COSE_ALGORITHM_EDDSA:
key_type = EVP_PKEY_ED25519;
key_data = ed25519_private_key;
key_len = sizeof(ed25519_private_key);
break;
default:
@ -129,7 +151,7 @@ enum t_cose_err_t make_ecdsa_key_pair(int32_t cose_algorithm_id,
}
/* This imports the public key too */
pkey = d2i_PrivateKey(EVP_PKEY_EC, NULL, &rfc5915_key, rfc5915_key_len);
pkey = d2i_PrivateKey(key_type, NULL, &key_data, key_len);
if(pkey == NULL) {
return_value = T_COSE_ERR_FAIL;
goto Done;
@ -147,7 +169,7 @@ Done:
/*
* Public function, see t_cose_make_test_pub_key.h
*/
void free_ecdsa_key_pair(struct t_cose_key key_pair)
void free_key_pair(struct t_cose_key key_pair)
{
EVP_PKEY_free(key_pair.k.key_ptr);
}

Просмотреть файл

@ -52,8 +52,8 @@
/*
* Public function, see t_cose_make_test_pub_key.h
*/
enum t_cose_err_t make_ecdsa_key_pair(int32_t cose_algorithm_id,
struct t_cose_key *key_pair)
enum t_cose_err_t make_key_pair(int32_t cose_algorithm_id,
struct t_cose_key *key_pair)
{
psa_key_type_t key_type;
psa_status_t crypto_result;
@ -64,9 +64,12 @@ enum t_cose_err_t make_ecdsa_key_pair(int32_t cose_algorithm_id,
psa_key_attributes_t key_attributes;
static const uint8_t private_key_256[] = {PRIVATE_KEY_prime256v1};
static const uint8_t private_key_384[] = {PRIVATE_KEY_secp384r1};
static const uint8_t private_key_521[] = {PRIVATE_KEY_secp521r1};
static const uint8_t private_key_256[] = {PRIVATE_KEY_prime256v1};
static const uint8_t private_key_384[] = {PRIVATE_KEY_secp384r1};
static const uint8_t private_key_521[] = {PRIVATE_KEY_secp521r1};
static const uint8_t private_key_rsa2048[] = {
#include "t_cose_rsa_test_key.h"
};
/* There is not a 1:1 mapping from COSE algorithm to key type, but
* there is usually an obvious curve for an algorithm. That
@ -95,6 +98,27 @@ enum t_cose_err_t make_ecdsa_key_pair(int32_t cose_algorithm_id,
key_alg = PSA_ALG_ECDSA(PSA_ALG_SHA_512);
break;
case COSE_ALGORITHM_PS256:
private_key = private_key_rsa2048;
private_key_len = sizeof(private_key_rsa2048);
key_type = PSA_KEY_TYPE_RSA_KEY_PAIR;
key_alg = PSA_ALG_RSA_PSS(PSA_ALG_SHA_256);
break;
case COSE_ALGORITHM_PS384:
private_key = private_key_rsa2048;
private_key_len = sizeof(private_key_rsa2048);
key_type = PSA_KEY_TYPE_RSA_KEY_PAIR;
key_alg = PSA_ALG_RSA_PSS(PSA_ALG_SHA_384);
break;
case COSE_ALGORITHM_PS512:
private_key = private_key_rsa2048;
private_key_len = sizeof(private_key_rsa2048);
key_type = PSA_KEY_TYPE_RSA_KEY_PAIR;
key_alg = PSA_ALG_RSA_PSS(PSA_ALG_SHA_512);
break;
default:
return T_COSE_ERR_UNSUPPORTED_SIGNING_ALG;
}
@ -162,7 +186,7 @@ enum t_cose_err_t make_ecdsa_key_pair(int32_t cose_algorithm_id,
/*
* Public function, see t_cose_make_test_pub_key.h
*/
void free_ecdsa_key_pair(struct t_cose_key key_pair)
void free_key_pair(struct t_cose_key key_pair)
{
psa_destroy_key((mbedtls_svc_key_id_t)key_pair.k.key_handle);
}
@ -171,7 +195,7 @@ void free_ecdsa_key_pair(struct t_cose_key key_pair)
/*
* Public function, see t_cose_make_test_pub_key.h
*/
int check_for_key_pair_leaks()
int check_for_key_pair_leaks(void)
{
/* The key allocation counters are private data structures, but
* they are the only way to do the valuable test for key

Просмотреть файл

@ -516,8 +516,8 @@ t_cose_sign1_test_message_output_signature(struct t_cose_sign1_sign_ctx *me,
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);
/* Pointer and length of the buffer for the signature */
struct q_useful_buf buffer_for_signature;
/* Buffer for the tbs hash. */
Q_USEFUL_BUF_MAKE_STACK_UB( buffer_for_tbs_hash, T_COSE_CRYPTO_MAX_HASH_SIZE);
struct q_useful_buf_c signed_payload;
@ -554,6 +554,13 @@ t_cose_sign1_test_message_output_signature(struct t_cose_sign1_sign_ctx *me,
goto Done;
}
/* The signature gets written directly into the output buffer.
* The matching QCBOREncode_CloseBytes call further down still needs do a
* memmove to make space for the CBOR header, but at least we avoid the need
* to allocate an extra buffer.
*/
QCBOREncode_OpenBytes(cbor_encode_ctx, &buffer_for_signature);
/* Compute the signature using public key crypto. The key selector
* and algorithm ID are passed in to know how and what to sign
* with. The hash of the TBS bytes are what is signed. A buffer in
@ -585,7 +592,7 @@ t_cose_sign1_test_message_output_signature(struct t_cose_sign1_sign_ctx *me,
}
/* Add signature to CBOR and close out the array */
QCBOREncode_AddBytes(cbor_encode_ctx, signature);
QCBOREncode_CloseBytes(cbor_encode_ctx, signature.len);
if(test_mess_options & T_COSE_TEST_INDEFINITE_MAPS_ARRAYS) {
QCBOREncode_CloseArrayIndefiniteLength(cbor_encode_ctx);

Просмотреть файл

@ -20,14 +20,14 @@
/**
* \brief make an ECDSA key pair for testing suited to algorim
* \brief make a key pair for testing suited to algorithm
*
*/
enum t_cose_err_t make_ecdsa_key_pair(int32_t cose_algorithm_id,
struct t_cose_key *key_pair);
enum t_cose_err_t make_key_pair(int32_t cose_algorithm_id,
struct t_cose_key *key_pair);
void free_ecdsa_key_pair(struct t_cose_key key_pair);
void free_key_pair(struct t_cose_key key_pair);
/**

123
3rdparty/exported/t_cose/test/t_cose_rsa_test_key.h поставляемый Normal file
Просмотреть файл

@ -0,0 +1,123 @@
/*
* t_cose_rsa_test_key.h
*
* Copyright 2019-2022, Laurence Lundblade
*
* SPDX-License-Identifier: BSD-3-Clause
*
* See BSD-3-Clause license in README.md
*/
/**
* An RSA private key in PKCS #1 (RFC 8017) format.
*
* This was generated by:
*
* openssl genrsa 2048 | sed -e '1d' -e '$d' | base64 --decode | xxd -i
*
* This file is used whether mbedtls or OpenSSL is used.
*
* On its own, the file is not itself valid C, and must be wrapped in a variable
* definition before being included.
*/
0x30, 0x82, 0x04, 0xa3, 0x02, 0x01, 0x00, 0x02, 0x82, 0x01, 0x01, 0x00,
0x9e, 0x4e, 0x3b, 0x05, 0xb4, 0x33, 0xe5, 0x49, 0x68, 0xdc, 0x64, 0xa0,
0x4e, 0x2c, 0x63, 0xd8, 0x11, 0x25, 0x7c, 0xe0, 0x63, 0xb6, 0x64, 0x89,
0x0b, 0xbd, 0xcd, 0x62, 0x30, 0xd4, 0x52, 0xa2, 0x52, 0xe0, 0x61, 0x84,
0xee, 0xf9, 0x6e, 0x14, 0x9f, 0x9e, 0x0e, 0xee, 0x67, 0x51, 0x09, 0xa9,
0x15, 0x05, 0x07, 0x17, 0x09, 0x93, 0x76, 0x87, 0x45, 0x2b, 0x89, 0xfd,
0x7c, 0xa7, 0xfa, 0xfc, 0x1b, 0x7b, 0x6e, 0xbb, 0x5f, 0xfc, 0x8a, 0xca,
0xc9, 0x14, 0xb4, 0xd0, 0xe8, 0x91, 0xb1, 0x60, 0xe8, 0x89, 0x54, 0xe0,
0x06, 0x0b, 0x59, 0xff, 0x90, 0x12, 0x34, 0x47, 0xd7, 0xbf, 0x82, 0xa8,
0x48, 0x77, 0x46, 0x56, 0x2c, 0xfb, 0x84, 0x00, 0x01, 0xdb, 0x6b, 0x14,
0xe2, 0x5a, 0xc7, 0x77, 0x3c, 0x8e, 0x48, 0x59, 0x21, 0xc6, 0x7a, 0x28,
0x17, 0x3f, 0xfa, 0xe1, 0xea, 0xc4, 0x6f, 0xa0, 0x0d, 0xf0, 0x04, 0x5a,
0x29, 0x97, 0x2e, 0x96, 0x35, 0x25, 0xba, 0x0a, 0x39, 0x51, 0x9e, 0x1d,
0x64, 0x95, 0xad, 0xc8, 0xc1, 0xa6, 0xfd, 0x61, 0xa1, 0x56, 0x40, 0x96,
0x85, 0x42, 0x83, 0x1e, 0x8f, 0xc8, 0xfa, 0x70, 0x2b, 0xea, 0xbd, 0xe6,
0x2d, 0x6f, 0x6a, 0x73, 0x00, 0x2a, 0x8f, 0x8e, 0x2c, 0x28, 0xdb, 0xc0,
0xa0, 0x23, 0x37, 0x6f, 0x67, 0xe3, 0x3d, 0x8f, 0xe6, 0x12, 0xbe, 0x8c,
0xdf, 0x67, 0xfb, 0xbf, 0xe2, 0x80, 0xd0, 0xdf, 0xe0, 0xf9, 0x68, 0xeb,
0x7f, 0x37, 0x4f, 0x17, 0xb8, 0x1e, 0x06, 0x46, 0x1a, 0x47, 0x6b, 0xd3,
0x40, 0x2c, 0x9a, 0xd1, 0xc5, 0x5c, 0xd2, 0x59, 0xad, 0x78, 0x82, 0x1b,
0x07, 0x49, 0x0e, 0x70, 0xa4, 0x69, 0x0c, 0xac, 0xf4, 0x78, 0x2e, 0x2d,
0x3e, 0x94, 0xc2, 0x3b, 0x80, 0xbc, 0x88, 0x91, 0xc9, 0xfe, 0x06, 0x1c,
0x19, 0xe3, 0x22, 0xbf, 0x02, 0x03, 0x01, 0x00, 0x01, 0x02, 0x82, 0x01,
0x00, 0x57, 0x8b, 0x07, 0x94, 0xc5, 0xec, 0x94, 0xf5, 0x9d, 0xa9, 0x93,
0x74, 0x1b, 0x06, 0xed, 0x48, 0x05, 0x63, 0x67, 0xc5, 0x67, 0x1e, 0xec,
0x45, 0xe5, 0x5a, 0x57, 0x03, 0xdf, 0xe0, 0xea, 0xb9, 0x9d, 0x7f, 0x3c,
0x2e, 0x99, 0x41, 0x12, 0xa1, 0x11, 0x0c, 0x05, 0x51, 0xcd, 0x8c, 0xc0,
0xfc, 0xe2, 0x04, 0xdf, 0xc0, 0xdb, 0xa8, 0xd2, 0xb9, 0x47, 0x85, 0x26,
0x50, 0x29, 0xe9, 0x73, 0x20, 0x8b, 0xca, 0x1c, 0x98, 0x3e, 0x22, 0x98,
0x56, 0x40, 0x10, 0xd5, 0x55, 0x59, 0xe7, 0x87, 0xe2, 0x01, 0x76, 0x40,
0x9b, 0x8a, 0x7c, 0x28, 0x8e, 0xed, 0x8b, 0x43, 0xa2, 0x1f, 0x2b, 0x67,
0x03, 0xcc, 0xdf, 0x38, 0xe4, 0x5b, 0x07, 0xd4, 0x1d, 0x74, 0xe9, 0x74,
0x34, 0x1e, 0x60, 0xf9, 0x41, 0x75, 0x19, 0x71, 0xe4, 0xe8, 0x8a, 0xab,
0xef, 0x13, 0xbc, 0x6b, 0xef, 0x17, 0x36, 0xfe, 0x4a, 0xf3, 0xe6, 0x17,
0x45, 0xd5, 0xfd, 0x7b, 0x82, 0xc6, 0x35, 0x72, 0x77, 0x91, 0x3d, 0x05,
0xd4, 0x00, 0xa3, 0x0d, 0xd5, 0x9a, 0x4e, 0x6b, 0xf4, 0x6f, 0xd5, 0xe9,
0x31, 0x58, 0x3e, 0x01, 0xfc, 0x7e, 0x7a, 0x80, 0x8f, 0x1e, 0x78, 0xbc,
0x31, 0x23, 0x03, 0x6a, 0x30, 0x31, 0x4e, 0xbb, 0x0e, 0x8f, 0xed, 0x26,
0x8d, 0x2d, 0x29, 0xc9, 0x83, 0xb8, 0x57, 0x39, 0x90, 0xd0, 0x43, 0x51,
0xb6, 0xf8, 0x5c, 0x20, 0xbe, 0x8e, 0x5d, 0xed, 0xde, 0x82, 0xe7, 0x0a,
0xf2, 0x7f, 0x76, 0x8c, 0x9d, 0x8a, 0x76, 0xa5, 0xb3, 0x63, 0x59, 0x4a,
0xcb, 0x90, 0x2b, 0x5f, 0xa4, 0xb9, 0x63, 0x10, 0x12, 0xaa, 0xa8, 0x87,
0xed, 0x60, 0x06, 0x2d, 0x1f, 0x0f, 0xad, 0x19, 0xde, 0xd0, 0xff, 0x6f,
0x2c, 0xc2, 0x4c, 0x9e, 0x1f, 0x89, 0xc8, 0x18, 0xa0, 0x42, 0xad, 0xa0,
0xa0, 0x37, 0x17, 0x68, 0x01, 0x02, 0x81, 0x81, 0x00, 0xcf, 0xcd, 0x4a,
0x0e, 0xcb, 0xe9, 0x19, 0x57, 0x2d, 0x42, 0x8a, 0xbf, 0xf9, 0x9b, 0xbc,
0xe1, 0x45, 0x87, 0x1c, 0xbe, 0xc4, 0x64, 0x9b, 0xbb, 0x40, 0x0c, 0xc5,
0x34, 0xbe, 0xbf, 0xcf, 0x6c, 0xc1, 0x4c, 0x5d, 0x72, 0x6b, 0x3f, 0xdf,
0x0c, 0x81, 0x7b, 0x2c, 0x30, 0xbf, 0x93, 0x49, 0x99, 0x28, 0xb1, 0x88,
0xf9, 0x76, 0x13, 0x6d, 0xe3, 0x1a, 0x85, 0xcf, 0x34, 0x77, 0x72, 0x76,
0x70, 0xe9, 0xe5, 0x5e, 0xc6, 0x1d, 0x7f, 0xec, 0x11, 0x6e, 0xf8, 0x50,
0x9d, 0xb3, 0x04, 0xd9, 0x0c, 0xc3, 0xf5, 0x40, 0x98, 0x8c, 0x77, 0x96,
0x89, 0x69, 0x10, 0xb3, 0xa8, 0x43, 0x99, 0x95, 0xc8, 0x6c, 0x21, 0x16,
0x36, 0x33, 0xf8, 0x6c, 0x4b, 0x99, 0x24, 0x64, 0x93, 0xbb, 0xbf, 0xa5,
0x3f, 0xed, 0xd4, 0x66, 0x9c, 0x3e, 0xd6, 0xf9, 0x62, 0x43, 0x41, 0xe5,
0xaf, 0xfe, 0x8e, 0x98, 0xbf, 0x02, 0x81, 0x81, 0x00, 0xc3, 0x05, 0xfc,
0x0e, 0xaa, 0x94, 0x58, 0xbe, 0x92, 0xdb, 0x0e, 0x89, 0x30, 0x18, 0x7e,
0xa2, 0x2c, 0x5f, 0x16, 0xad, 0x9f, 0xd2, 0x4b, 0x40, 0x8d, 0x60, 0x30,
0xfa, 0x9b, 0xaa, 0xcb, 0x20, 0xcd, 0x18, 0x63, 0x1d, 0x51, 0xda, 0xb3,
0x61, 0xb1, 0xcc, 0x82, 0x45, 0x2a, 0x84, 0x82, 0x7b, 0xb5, 0xc1, 0x0c,
0xd4, 0xe5, 0xe4, 0x0f, 0x03, 0xe7, 0x92, 0x48, 0x24, 0x85, 0x4c, 0xa6,
0x02, 0xd3, 0x7b, 0xe8, 0xb8, 0x9e, 0xf4, 0x92, 0xb9, 0x55, 0x71, 0x2e,
0x80, 0x45, 0x7c, 0x80, 0x62, 0x20, 0x1b, 0x9a, 0xbb, 0x18, 0x36, 0x36,
0x5d, 0x69, 0xf0, 0xea, 0x41, 0x5c, 0x4c, 0x75, 0x5c, 0x62, 0xc9, 0x4f,
0xae, 0xb0, 0xad, 0x98, 0xc5, 0x03, 0xf2, 0xf9, 0xde, 0x1f, 0x01, 0xe9,
0x1e, 0x3d, 0xe8, 0xf8, 0x84, 0xaf, 0x49, 0x61, 0x2f, 0x4e, 0x20, 0xb4,
0x18, 0x79, 0xb3, 0xf6, 0x01, 0x02, 0x81, 0x80, 0x72, 0xe2, 0x03, 0xf7,
0x7a, 0x34, 0x3c, 0x96, 0x3d, 0xa7, 0x74, 0x1d, 0xfe, 0x59, 0x63, 0x6b,
0x07, 0x8d, 0x53, 0x0f, 0x04, 0x74, 0xba, 0xc4, 0x22, 0xfc, 0xec, 0x69,
0xe4, 0xab, 0x16, 0x7a, 0x01, 0xc3, 0xbe, 0x45, 0xeb, 0x95, 0x3c, 0x33,
0x25, 0xc2, 0x7b, 0x03, 0xd8, 0x66, 0x0d, 0x62, 0x67, 0x64, 0xff, 0x5d,
0x2b, 0x32, 0x42, 0xa6, 0x33, 0x9b, 0x96, 0x9a, 0x63, 0x0f, 0x1c, 0xfb,
0xff, 0xd3, 0x97, 0x39, 0xe0, 0x45, 0x40, 0xb5, 0xc2, 0xab, 0xf5, 0xa5,
0xb9, 0xbb, 0x0c, 0x64, 0x4a, 0x51, 0xe4, 0x8c, 0x71, 0xdc, 0x0b, 0x95,
0x9c, 0x48, 0x67, 0x8a, 0xb7, 0x14, 0xca, 0x02, 0x2c, 0x05, 0x7e, 0xca,
0x28, 0xa1, 0x46, 0xfd, 0xe4, 0x84, 0x82, 0x36, 0x4a, 0xae, 0x01, 0x25,
0xfe, 0xce, 0x56, 0x8c, 0x3b, 0x11, 0x8e, 0x7e, 0x0c, 0xc0, 0xf9, 0xc2,
0xfa, 0xf0, 0xca, 0xf1, 0x02, 0x81, 0x80, 0x61, 0x53, 0x61, 0x40, 0xe8,
0x7b, 0xf3, 0xf5, 0xd7, 0x50, 0x1e, 0xe6, 0xf3, 0xeb, 0xa5, 0x76, 0xc5,
0x72, 0x06, 0xdd, 0x4a, 0xff, 0x25, 0xb2, 0xe7, 0x5a, 0xf3, 0xd6, 0x7d,
0x4d, 0x34, 0xe5, 0xff, 0xb4, 0x85, 0xf2, 0x21, 0xe1, 0x64, 0xd8, 0x02,
0x65, 0x2f, 0x35, 0xd9, 0x4c, 0x1b, 0xda, 0x25, 0x10, 0x5c, 0x98, 0xfa,
0xc9, 0x5f, 0x7c, 0xf1, 0x5a, 0x1d, 0x4a, 0xac, 0x83, 0x5d, 0xed, 0xd7,
0x20, 0xe5, 0x39, 0x0d, 0x8a, 0xbc, 0x96, 0x65, 0x3f, 0x80, 0x97, 0x5f,
0x16, 0x0c, 0xf3, 0xeb, 0x56, 0x1b, 0x57, 0xf7, 0x73, 0x46, 0x9a, 0x43,
0xbe, 0x89, 0x09, 0x69, 0x48, 0x76, 0xe1, 0x4e, 0x23, 0x6c, 0xf2, 0x9f,
0x15, 0x63, 0x42, 0x1f, 0x00, 0x69, 0x16, 0x22, 0x9f, 0x4f, 0x79, 0x5a,
0x28, 0x23, 0xae, 0x03, 0xd4, 0x38, 0xfd, 0xe4, 0x9d, 0x89, 0x83, 0x15,
0x69, 0x6c, 0x01, 0x02, 0x81, 0x81, 0x00, 0xc3, 0x8d, 0xfa, 0x78, 0xed,
0xb8, 0x99, 0xd3, 0xee, 0xd0, 0xbd, 0x74, 0xf3, 0x6e, 0xd1, 0xb4, 0x37,
0xc0, 0x89, 0x6c, 0xf0, 0x69, 0xbc, 0xbe, 0x5c, 0xd4, 0x6a, 0xa5, 0xba,
0x39, 0x3e, 0x68, 0x87, 0xeb, 0x35, 0x6d, 0x24, 0x3c, 0x3f, 0x11, 0xcd,
0x31, 0x60, 0x8b, 0xb6, 0x7f, 0x6c, 0x42, 0xe3, 0x8d, 0xc3, 0x90, 0x79,
0x9a, 0xba, 0x1c, 0xac, 0x72, 0x5d, 0x05, 0x8a, 0x50, 0x87, 0x34, 0x67,
0xba, 0x19, 0x2c, 0xd6, 0x9b, 0x3f, 0xd7, 0x32, 0x4f, 0x60, 0x9e, 0x19,
0x00, 0x1e, 0x29, 0xfd, 0x8f, 0xcd, 0xec, 0x75, 0xcd, 0x42, 0xcc, 0x5f,
0xad, 0x42, 0xa3, 0xf6, 0xc5, 0x5a, 0x14, 0xaa, 0x9f, 0x75, 0xe6, 0x13,
0x96, 0xdf, 0x73, 0xcd, 0xd8, 0x8b, 0x02, 0x9c, 0xeb, 0xa5, 0x2f, 0x06,
0x12, 0xc3, 0x0c, 0xf3, 0xbb, 0x9f, 0x16, 0xdb, 0xe6, 0xd2, 0x78, 0x58,
0x35, 0xb7, 0x4b

Разница между файлами не показана из-за своего большого размера Загрузить разницу

Просмотреть файл

@ -50,6 +50,18 @@ int_fast32_t sign_verify_get_size_test(void);
/*
* Test against known good messages.
*/
int_fast32_t known_good_test(void);
int_fast32_t sign_verify_known_good_test(void);
/*
* Test the return value when using an unsupported algorithm.
*/
int_fast32_t sign_verify_unsupported_test(void);
/*
* Test the return value when using a small or no auxiliary buffer.
*/
int_fast32_t sign_verify_bad_auxiliary_buffer(void);
#endif /* t_cose_sign_verify_test_h */

6
3rdparty/exported/t_cose/test/t_cose_test.c поставляемый
Просмотреть файл

@ -844,7 +844,7 @@ struct test_case {
static struct test_case bad_parameters_tests_table[] = {
{T_COSE_TEST_EMPTY_PROTECTED_PARAMETERS, T_COSE_ERR_UNSUPPORTED_HASH},
{T_COSE_TEST_EMPTY_PROTECTED_PARAMETERS, T_COSE_ERR_UNSUPPORTED_SIGNING_ALG},
{T_COSE_TEST_UNCLOSED_PROTECTED, T_COSE_ERR_PARAMETER_CBOR},
@ -1523,7 +1523,7 @@ int_fast32_t tags_test()
}
int32_t get_size_test()
int_fast32_t get_size_test()
{
struct t_cose_sign1_sign_ctx sign_ctx;
QCBOREncodeContext cbor_encode;
@ -1620,7 +1620,7 @@ int32_t get_size_test()
/*
* Public function, see t_cose_test.h
*/
int32_t indef_array_and_map_test()
int_fast32_t indef_array_and_map_test()
{
enum t_cose_err_t return_value;
uint32_t t_opts;

4
3rdparty/exported/t_cose/test/t_cose_test.h поставляемый
Просмотреть файл

@ -145,14 +145,14 @@ int_fast32_t short_circuit_hash_fail_test(void);
int_fast32_t tags_test(void);
int32_t get_size_test(void);
int_fast32_t get_size_test(void);
/*
* Test the decoding of COSE messages that use indefinite length
* maps and arrays instead of definite length.
*/
int32_t indef_array_and_map_test(void);
int_fast32_t indef_array_and_map_test(void);
#endif /* t_cose_test_h */

Просмотреть файл

@ -150,7 +150,7 @@
"type": "git",
"git": {
"repositoryUrl": "https://github.com/laurencelundblade/t_cose",
"commitHash": "d5ff4e282d8af34e5756627cf877ab399e7e51af"
"commitHash": "e7a40d257a24d9c97066f920d419c5b11484a342"
}
}
}

Просмотреть файл

@ -4,10 +4,9 @@
# Build t_cose
set(T_COSE_DIR "${CCF_3RD_PARTY_EXPORTED_DIR}/t_cose")
set(T_COSE_SRC "${T_COSE_DIR}/src")
set(T_COSE_INC "${T_COSE_DIR}/inc")
set(T_COSE_DEFS -DT_COSE_USE_OPENSSL_CRYPTO=1)
# https://github.com/laurencelundblade/t_cose/issues/50
# set(T_COSE_OPTS_INTERFACE -Wno-c99-extensions)
set(T_COSE_DEFS -DT_COSE_USE_OPENSSL_CRYPTO=1
-DT_COSE_DISABLE_SHORT_CIRCUIT_SIGN=1
)
set(T_COSE_SRCS
"${T_COSE_SRC}/t_cose_parameters.c" "${T_COSE_SRC}/t_cose_sign1_verify.c"
"${T_COSE_SRC}/t_cose_util.c"
@ -21,8 +20,8 @@ if(COMPILE_TARGET STREQUAL "sgx")
target_include_directories(t_cose.enclave PRIVATE "${T_COSE_SRC}")
target_include_directories(
t_cose.enclave
PUBLIC $<BUILD_INTERFACE:${CCF_3RD_PARTY_EXPORTED_DIR}/t_cose>
$<INSTALL_INTERFACE:include/3rdparty/t_cose>
PUBLIC $<BUILD_INTERFACE:${CCF_3RD_PARTY_EXPORTED_DIR}/t_cose/inc>
$<INSTALL_INTERFACE:include/3rdparty/t_cose/inc>
)
target_link_libraries(t_cose.enclave PUBLIC qcbor.enclave)
@ -44,8 +43,8 @@ target_compile_options(t_cose.host INTERFACE ${T_COSE_OPTS_INTERFACE})
target_include_directories(t_cose.host PRIVATE "${T_COSE_SRC}")
target_include_directories(
t_cose.host PUBLIC $<BUILD_INTERFACE:${CCF_3RD_PARTY_EXPORTED_DIR}/t_cose>
$<INSTALL_INTERFACE:include/3rdparty/t_cose>
t_cose.host PUBLIC $<BUILD_INTERFACE:${CCF_3RD_PARTY_EXPORTED_DIR}/t_cose/inc>
$<INSTALL_INTERFACE:include/3rdparty/t_cose/inc>
)
target_link_libraries(t_cose.host PUBLIC qcbor.host crypto)