зеркало из https://github.com/microsoft/CCF.git
This commit is contained in:
Родитель
2253a8d89f
Коммит
9afb0209b8
|
@ -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)
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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 -----
|
||||
|
|
|
@ -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,
|
|
@ -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
|
||||
|
|
|
@ -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 */
|
||||
|
|
@ -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, ¶meters, 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, ¶meters, 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, ¶meters, 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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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 */,
|
||||
|
|
|
@ -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);
|
||||
|
||||
|
||||
/**
|
||||
|
|
|
@ -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 */
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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)
|
||||
|
|
Загрузка…
Ссылка в новой задаче