diff options
-rw-r--r-- | lib/t_cose/CMakeLists.txt | 65 | ||||
-rw-r--r-- | lib/t_cose/README.md | 95 | ||||
-rw-r--r-- | lib/t_cose/inc/t_cose_common.h | 154 | ||||
-rw-r--r-- | lib/t_cose/inc/t_cose_sign1_sign.h | 189 | ||||
-rw-r--r-- | lib/t_cose/inc/t_cose_sign1_verify.h | 115 | ||||
-rw-r--r-- | lib/t_cose/src/t_cose_crypto.h | 470 | ||||
-rw-r--r-- | lib/t_cose/src/t_cose_defines.h | 291 | ||||
-rw-r--r-- | lib/t_cose/src/t_cose_psa_crypto_hash.c | 180 | ||||
-rw-r--r-- | lib/t_cose/src/t_cose_psa_crypto_sign.c | 147 | ||||
-rw-r--r-- | lib/t_cose/src/t_cose_psa_crypto_verify.c | 51 | ||||
-rw-r--r-- | lib/t_cose/src/t_cose_sign1_sign.c | 526 | ||||
-rw-r--r-- | lib/t_cose/src/t_cose_sign1_verify.c | 280 | ||||
-rw-r--r-- | lib/t_cose/src/t_cose_util.c | 235 | ||||
-rw-r--r-- | lib/t_cose/src/t_cose_util.h | 156 |
14 files changed, 0 insertions, 2954 deletions
diff --git a/lib/t_cose/CMakeLists.txt b/lib/t_cose/CMakeLists.txt deleted file mode 100644 index 92317cb8d1..0000000000 --- a/lib/t_cose/CMakeLists.txt +++ /dev/null @@ -1,65 +0,0 @@ -#------------------------------------------------------------------------------- -# Copyright (c) 2019, Arm Limited. All rights reserved. -# -# SPDX-License-Identifier: BSD-3-Clause -# -#------------------------------------------------------------------------------- - -cmake_minimum_required(VERSION 3.7) - -#Tell cmake where our modules can be found -list(APPEND CMAKE_MODULE_PATH ${CMAKE_CURRENT_LIST_DIR}/../../../cmake) - -#Some project global settings -set(T_COSE_DIR "${CMAKE_CURRENT_LIST_DIR}") -get_filename_component(TFM_ROOT_DIR "${T_COSE_DIR}/../.." ABSOLUTE) - -#Include common stuff to control cmake. -include("Common/BuildSys") - -#Start an embedded project. -embedded_project_start(CONFIG "${TFM_ROOT_DIR}/configs/ConfigDefault.cmake") -project(tfm_t_cose LANGUAGES C) -embedded_project_fixup() - -if (NOT DEFINED ATTEST_INCLUDE_TEST_CODE_AND_KEY_ID) - message(FATAL_ERROR "Incomplete build configuration: ATTEST_INCLUDE_TEST_CODE_AND_KEY_ID is undefined. ") -endif() - -#Append all our source files to global lists. -list(APPEND ALL_SRC_C_SIGN - "${T_COSE_DIR}/src/t_cose_sign1_sign.c" - "${T_COSE_DIR}/src/t_cose_util.c" - "${T_COSE_DIR}/src/t_cose_psa_crypto_hash.c" - "${T_COSE_DIR}/src/t_cose_psa_crypto_sign.c" - ) - -list(APPEND ALL_SRC_C_VERIFY - "${T_COSE_DIR}/src/t_cose_sign1_verify.c" - "${T_COSE_DIR}/src/t_cose_util.c" - "${T_COSE_DIR}/src/t_cose_psa_crypto_hash.c" - "${T_COSE_DIR}/src/t_cose_psa_crypto_verify.c" - ) - -#Setting include directories -embedded_include_directories(PATH ${T_COSE_DIR}/inc ABSOLUTE) -embedded_include_directories(PATH ${TFM_ROOT_DIR}/secure_fw/services/initial_attestation ABSOLUTE) -embedded_target_include_directories(TARGET tfm_t_cose_verify PATH ${TFM_ROOT_DIR}/lib/ext/qcbor/util ABSOLUTE APPEND) -embedded_target_include_directories(TARGET tfm_t_cose_verify PATH ${TFM_ROOT_DIR}/test/suites/attestation ABSOLUTE APPEND) -embedded_target_include_directories(TARGET tfm_t_cose_sign PATH ${TFM_ROOT_DIR}/platform/include ABSOLUTE APPEND) - -#Specify what we build (t_cose_sign and t_cose_verify build as an object library) -add_library(tfm_t_cose_sign OBJECT ${ALL_SRC_C_SIGN}) -add_library(tfm_t_cose_verify OBJECT ${ALL_SRC_C_VERIFY}) - -if (ATTEST_INCLUDE_TEST_CODE_AND_KEY_ID) - embedded_set_target_compile_defines(TARGET tfm_t_cose_sign LANGUAGE C DEFINES INCLUDE_TEST_CODE_AND_KEY_ID APPEND) - embedded_set_target_compile_defines(TARGET tfm_t_cose_verify LANGUAGE C DEFINES INCLUDE_TEST_CODE_AND_KEY_ID APPEND) -endif() - -#Set common compiler flags -config_setting_shared_compiler_flags(tfm_t_cose_sign) -config_setting_shared_compiler_flags(tfm_t_cose_verify) - -embedded_project_end(tfm_t_cose_sign) -embedded_project_end(tfm_t_cose_verify) diff --git a/lib/t_cose/README.md b/lib/t_cose/README.md deleted file mode 100644 index 950180654f..0000000000 --- a/lib/t_cose/README.md +++ /dev/null @@ -1,95 +0,0 @@ -# t_cose - -## Introduction - -t_cose is a partial implementation of the COSE standard (RFC 8152). -COSE is quite a large standard so a full implementation of all of it -is a large undertaking. This implementation is starting out as just -enough for attestation and maybe CWT (Cbor Web Token) which is very -similar. - -As it may grow to support more of COSE over time, it is structured -with that in mind. - -It is also trying to be portable, the most interesting part of which -is interfacing with the libraries for performing cryptography and -access cryptographic keys. - -## Source files -The following files are more or less the public interface. -* t_cose_common.h -* t_cose_sign1.h -* t_cose_sign1_verify.h - -The rest of the files are internal source files that callers should -not depend on. - -t_cose_defines.h contains contants from RFC 8152 that are -part of the COSE standard. It should never have anything else -in it. - -t_cose_util is some utilities and code common to -signing and verification. Both signing and verifcation -depend on it. - -t_cose_crypto is the crypto porting layer. Generally -the .h file should not need to change for a new -platform. The .c file will be changed lots for -each new platform. - -## Dependency and Portability -t_cose is attempting to be very portable and -have a minmum number of #ifdefs. It is -designed to run 64-bit and 32-bit machines. - -It uses a minimum number of standard C -libraries, mostly just <stdint.h>, <string.h> and <stddef.h>. - -It uses QCBOR for CBOR encoding and decoding. -QCBOR is very portable. - -### Cryptography and Keys -There is a cryptographic adaption layer that -provides the following: -* Impedence match of parameters passed to/from the crypto -* Management of algorithm identifiers -* Management of error codes -* Management of key identifiers - -It is framed for the needs of t_cose, and is -not trying to be any kind of general crypto API. - -#### Question -Q: How many crypto APIs does it take to screw in a light bulb? -A: One more than it takes to screw in a light bulb. - -## Copyright and License - -### BSD-3-Clause license - -* Redistributions of source code must retain the above copyright -notice, this list of conditions and the following disclaimer. - -* Redistributions in binary form must reproduce the above copyright -notice, this list of conditions and the following disclaimer in the -documentation and/or other materials provided with the distribution. - -* Neither the name of the copyright holder nor the names of its -contributors may be used to endorse or promote products derived from -this software without specific prior written permission. - -THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR -A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT -HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, -SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT -LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, -DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY -THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - -### Copyright for this README - -Copyright (c) 2018-2019, Laurence Lundblade. All rights reserved. diff --git a/lib/t_cose/inc/t_cose_common.h b/lib/t_cose/inc/t_cose_common.h deleted file mode 100644 index 6e585d49a2..0000000000 --- a/lib/t_cose/inc/t_cose_common.h +++ /dev/null @@ -1,154 +0,0 @@ -/* - * t_cose_common.h - * - * Copyright 2019, Laurence Lundblade - * - * SPDX-License-Identifier: BSD-3-Clause - * - * See BSD-3-Clause license in README.md. - */ - - -#ifndef __T_COSE_COMMON_H__ -#define __T_COSE_COMMON_H__ - -#ifdef __cplusplus -extern "C" { -#endif - -/** - * \file t_cose_common.h - * - * \brief Defines common to all public t_cose interfaces. - * - */ - - -/* Private value. Intentionally not documented for Doxygen. - * This is the size allocated for the encoded protected headers. It - * needs to be big enough for make_protected_header() to succeed. It - * currently sized for one header with an algorithm ID up to 32 bits - * long -- one byte for the wrapping map, one byte for the label, 5 - * bytes for the ID. If this is made accidentially too small, QCBOR will - * only return an error, and not overrun any buffers. - * - * 9 extra bytes are added, rounding it up to 16 total, in case some - * other protected header is to be added. - */ -#define T_COSE_SIGN1_MAX_PROT_HEADER (1+1+5+9) - - -/** - * Error codes return by t_cose. - * - * Do not reorder these. It is OK to add - * new ones at the end. - */ -enum t_cose_err_t { - /** - * Operation completed successfully - */ - T_COSE_SUCCESS = 0, - /** - * The requested signing algorithm is not supported. - */ - T_COSE_ERR_UNSUPPORTED_SIGNING_ALG, - /** - * Error constructing the protected headers. - */ - T_COSE_ERR_PROTECTED_HEADERS, - /** - * The hash algorithm needed is not supported. Note that the - * signing algorithm identifier usually identifies the hash - * algorithm. - */ - T_COSE_ERR_UNSUPPORTED_HASH, - /** - * Some system failure when running the hash algorithm. - */ - T_COSE_ERR_HASH_GENERAL_FAIL, - /** - * The buffer to receive a hash result is too small. - */ - T_COSE_ERR_HASH_BUFFER_SIZE, - /** - * The buffer to receive result of a signing operation is too - * small. - */ - T_COSE_ERR_SIG_BUFFER_SIZE, - /** - * The buffer to receive to receive a key is too small. - */ - T_COSE_ERR_KEY_BUFFER_SIZE, - /** - * When verifying a \c COSE_Sign1, something is wrong with the - * format of the CBOR. For example, it is missing something like - * the payload. - */ - T_COSE_ERR_SIGN1_FORMAT, - /** - * When decoding some CBOR like a \c COSE_Sign1, the CBOR was not - * well-formed. Most likely what was supposed to be CBOR was is - * either not or it has been corrupted. - */ - T_COSE_ERR_CBOR_NOT_WELL_FORMED, - /** - * No algorithm ID was found when one is needed. For example, when - * verifying a \c COSE_Sign1. - */ - T_COSE_ERR_NO_ALG_ID, - /** - * No key ID was found when one is needed. For example, when - * verifying a \c COSE_Sign1. - */ - T_COSE_ERR_NO_KID, - /** - * Signature verification failed. For example, the cryptographic - * operations completed successfully but hash wasn't as expected. - */ - T_COSE_ERR_SIG_VERIFY, - /** - * Verification of a short-circuit signature failed. - */ - T_COSE_ERR_BAD_SHORT_CIRCUIT_KID, - /** - * Some (unspecified) argument was not valid. - */ - T_COSE_ERR_INVALID_ARGUMENT, - /** - * Out of heap memory. - */ - T_COSE_ERR_INSUFFICIENT_MEMORY, - /** - * General unspecific failure. - */ - T_COSE_ERR_FAIL, - /** - * Equivalent to \c PSA_ERROR_TAMPERING_DETECTED. - */ - T_COSE_ERR_TAMPERING_DETECTED, - /** - * The key identified by a key slot of a key ID was not found. - */ - T_COSE_ERR_UNKNOWN_KEY, - /** - * The key was found, but it was the wrong type for the operation. - */ - T_COSE_ERR_WRONG_TYPE_OF_KEY, - /** - * Error constructing the \c Sig_structure when signing or verify. - */ - T_COSE_ERR_SIG_STRUCT, - /** - * Signature was short-circuit. THe option to allow verification - * of short-circuit signatures was not set - */ - T_COSE_ERR_SHORT_CIRCUIT_SIG -}; - -#ifdef __cplusplus -} -#endif - - -#endif /* __T_COSE_COMMON_H__ */ diff --git a/lib/t_cose/inc/t_cose_sign1_sign.h b/lib/t_cose/inc/t_cose_sign1_sign.h deleted file mode 100644 index dbe8896b43..0000000000 --- a/lib/t_cose/inc/t_cose_sign1_sign.h +++ /dev/null @@ -1,189 +0,0 @@ -/* - * t_cose_sign1_sign.h - * - * Copyright (c) 2018-2019, Laurence Lundblade. All rights reserved. - * - * SPDX-License-Identifier: BSD-3-Clause - * - * See BSD-3-Clause license in README.md - */ - -#ifndef __T_COSE_SIGN1_H__ -#define __T_COSE_SIGN1_H__ - -#include <stdint.h> -#include <stdbool.h> -#include "qcbor.h" -#include "t_cose_common.h" - -#ifdef __cplusplus -extern "C" { -#endif - - -/** - * \file t_cose_sign1_sign.h - * - * \brief Create a \c COSE_Sign1, usually for EAT or CWT Token. - * - * This creates a \c COSE_Sign1 in compliance with [COSE (RFC 8152)] - * (https://tools.ietf.org/html/rfc8152). A \c COSE_Sign1 is a CBOR - * encoded binary blob that contains headers, a payload and a - * signature. Usually the signature is made with an EC signing - * algorithm like ECDSA. - * - * This implementation is intended to be small and portable to - * different OS's and platforms. Its dependencies are: - * - QCBOR - * - <stdint.h>, <string.h>, <stddef.h> - * - Hash functions like SHA-256 - * - Signing functions like ECDSA - * - * There is a cryptographic adaptation layer defined in - * t_cose_crypto.h. An implementation can be made of the functions in - * it for different platforms or OS's. This means that different - * platforms and OS's may support only signing with a particular set - * of algorithms. - * - * This \c COSE_Sign1 implementations is optimized for creating EAT - * tokens. - * - * It should work for CWT and others use cases too. The main point of - * the optimization is that only one output buffer is needed. There is - * no need for one buffer to hold the payload and another to hold the - * end result \c COSE_Sign1. The payload is encoded right into its final - * place in the end result \c COSE_Sign1. - */ - - -/** - * This is the context for creating a \c COSE_Sign1 structure. The caller - * should allocate it and pass it to the functions here. This is - * about 32 bytes so it fits easily on the stack. - */ -struct t_cose_sign1_ctx { - /* Private data structure */ - uint8_t buffer_for_protected_headers[ - T_COSE_SIGN1_MAX_PROT_HEADER]; - struct q_useful_buf_c protected_headers; - int32_t cose_algorithm_id; - int32_t key_select; - bool short_circuit_sign; - QCBOREncodeContext *cbor_encode_ctx; -}; - - -/** - * \brief Initialize to start creating a \c COSE_Sign1. - * - * \param[in] me The t_cose signing context. - * \param[in] short_circuit_sign \c true to select special test mode. - * \param[in] cose_algorithm_id The algorithm to sign with. The IDs are - * defined in [COSE (RFC 8152)] - * (https://tools.ietf.org/html/rfc8152) or - * in the [IANA COSE Registry] - * (https://www.iana.org/assignments/cose/cose.xhtml). - * \param[in] key_select Which signing key to use. - * \param[in] cbor_encode_ctx The CBOR encoder context to output to. - * - * \return This returns one of the error codes defined by \ref t_cose_err_t. - * - * It is possible to use this to compute the exact size of the - * resulting token so the exact sized buffer can be allocated. To do - * this initialize the \c cbor_encode_ctx with \c UsefulBufC that has - * a \c NULL pointer and large length like \c UINT32_MAX. Then run the - * normal token creation. The result will have a NULL pointer and the - * length of the token that would have been created. When this is run - * like this, the cryptographic functions will not actually run, but - * the size of their output will be taken into account. - * - * The key selection depends on the platform / OS. - * - * Which signing algorithms are supported depends on the platform/OS. - * The header file t_cose_defines.h contains defined constants for - * some of them. A typical example is \ref COSE_ALGORITHM_ES256 which - * indicates ECDSA with the NIST P-256 curve and SHA-256. - * - * To use this, create a \c QCBOREncodeContext and initialize it with - * an output buffer big enough to hold the payload and the COSE Sign 1 - * overhead. This overhead is about 30 bytes plus the size of the - * signature and the size of the key ID. - * - * After the \c QCBOREncodeContext is initialized, call - * t_cose_sign1_init() on it. - * - * Next call \c QCBOREncode_BstrWrap() to indicate the start of the - * payload. - * - * Next call various \c QCBOREncode_Addxxxx() methods to create the - * payload. - * - * Next call \c QCBOREncode_CloseBstrWrap() to indicate the end of the - * payload. This will also return a pointer and length of the payload - * that gets hashed. - * - * Next call t_cose_sign1_finish() with the pointer and length of the - * payload. This will do all the cryptography and complete the COSE - * Sign1. - * - * Finally, call \c QCBOREncode_Finish() to get the pointer and length - * of the complete token. - * - * This implements a special signing test mode called _short_ - * _circuit_ _signing_. This mode is useful when there is no signing - * key available, perhaps because it has not been provisioned or - * configured for the particular device. It may also be because the - * public key cryptographic functions have not been connected up in - * the cryptographic adaptation layer. - * - * It has no value for security at all. Data signed this way should - * not be trusted as anyone can sign like this. - * - * In this mode the signature is the hash of that would normally be - * signed by the public key algorithm. To make the signature the - * correct size for the particular algorithm instances of the hash are - * concatenated to pad it out. - * - * This mode is very useful for testing because all the code except - * the actual signing algorithm is run exactly as it would if a proper - * signing algorithm was run. - * - * The kid (Key ID) put in the unprotected headers is created as - * follows. The EC public key is CBOR encoded as a \c COSE_Key as - * defined in the COSE standard. That encoded CBOR is then - * hashed with SHA-256. This is similar to key IDs defined in IETF - * PKIX, but is based on COSE and CBOR rather than ASN.1. - */ -enum t_cose_err_t t_cose_sign1_init(struct t_cose_sign1_ctx *me, - bool short_circuit_sign, - int32_t cose_algorithm_id, - int32_t key_select, - QCBOREncodeContext *cbor_encode_ctx); - - -/** - * \brief Finish creation of the \c COSE_Sign1. - * - * \param[in] me The t_cose signing context. - * \param[in] payload The pointer and length of the payload. - * - * \return This returns one of the error codes defined by \ref t_cose_err_t. - * - * Call this to complete creation of a signed token started with - * t_cose_sign1_init(). - * - * This is when the signature algorithm is run. - * - * The payload parameter is used only to compute the hash for - * signing. The completed \c COSE_Sign1 is retrieved from the \c - * cbor_encode_ctx by calling \c QCBOREncode_Finish() - */ -enum t_cose_err_t t_cose_sign1_finish(struct t_cose_sign1_ctx *me, - struct q_useful_buf_c payload); - - -#ifdef __cplusplus -} -#endif - -#endif /* __T_COSE_SIGN1_H__ */ diff --git a/lib/t_cose/inc/t_cose_sign1_verify.h b/lib/t_cose/inc/t_cose_sign1_verify.h deleted file mode 100644 index 3406afcc6e..0000000000 --- a/lib/t_cose/inc/t_cose_sign1_verify.h +++ /dev/null @@ -1,115 +0,0 @@ -/* - * t_cose_sign1_verify.h - * - * Copyright 2019, Laurence Lundblade - * - * SPDX-License-Identifier: BSD-3-Clause - * - * See BSD-3-Clause license in README.md. - */ - - -#ifndef __T_COSE_SIGN1_VERIFY_H__ -#define __T_COSE_SIGN1_VERIFY_H__ - -#include <stdint.h> -#include "q_useful_buf.h" -#include "t_cose_common.h" - -#ifdef __cplusplus -extern "C" { -#endif - -/** - * \file t_cose_sign1_verify.h - * - * \brief Verify a COSE_Sign1 - * - * This creates a \c COSE_Sign1 in compliance with [COSE (RFC 8152)] - * (https://tools.ietf.org/html/rfc8152). A \c COSE_Sign1 is a CBOR - * encoded binary blob that contains headers, a payload and a - * signature. Usually the signature is made with an EC signing - * algorithm like ECDSA. - * - * This implementation is intended to be small and portable to - * different OS's and platforms. Its dependencies are: - * - QCBOR - * - <stdint.h>, <string.h>, <stddef.h> - * - Hash functions like SHA-256 - * - Signature verifications functions like ECDSA - * - * There is a cryptographic adaptation layer defined in - * t_cose_crypto.h. An implementation can be made of the functions in - * it for different platforms or OS's. This means that different - * platforms and OS's may support only signing with a particular set - * of algorithms. - * - * This should not yet be considered a real commercial - * implementation of COSE signature verification. It is - * close, but not there yet. It's purpose is to test - * COSE signing. The main thing this needs to become - * a real commercial implementation is code that - * tests this. It is a parser / decoder, so a - * proper test involves a lot of hostile input. - */ - - -/** - Pass this as \c option_flags to allow verification of - short-circuit signatures. This should only be used as - a test mode as short-circuit signatures are not secure. - */ -#define T_COSE_OPT_ALLOW_SHORT_CIRCUIT 0x00000001 - - -/** - * \brief Verify a COSE_Sign1 - * - * \param[in] option_flags Options controlling the verification. - * \param[in] key_select A key selection that may be used to either - * override the lookup by the kid in the COSE - * headers, or instead of the kid. How - * this works is platform / OS dependent. It - * may depend on \c option_flags too. - * \param[in] sign1 Pointer and length of CBOR encoded \c COSE_Sign1 - * that is to be verified. - * \param[out] payload Pointer and length of the still CBOR encoded - * payload - * - * \return This returns one of the error codes defined by \ref t_cose_err_t. - * - * Verification involves the following steps. - * - * The CBOR structure is parsed and verified. It makes sure \c sign1 - * is valid CBOR and that it is tagged as a \c COSE_Sign1. - * - * The signing algorithm is pulled out of the protected headers. - * - * The kid (key ID) is parsed out of the unprotected headers. - * - * The payload is identified. It doesn't have to be parsed in detail - * because it is wrapped in a bstr. - * - * The expected hash, the "to-be-signed" bytes are computed. The hash - * algorithm to use comes from the signing algorithm in the protected - * headers. If the algorithm is not known or not supported this will - * error out. - * - * The verification key is obtained. This may be by kid in the - * protected headers or by the key_select. - * - * Finally, the signature verification is performed. - * - * If it is successful, the pointer of the CBOR-encoded payload is - * returned. - * - * This will recognize the special kid for short-circuit signing - * and verify it if the \ref T_COSE_OPT_ALLOW_SHORT_CIRCUIT is set. - */ -enum t_cose_err_t t_cose_sign1_verify(int32_t option_flags, - int32_t key_select, - struct q_useful_buf_c sign1, - struct q_useful_buf_c *payload); - - -#endif /* __T_COSE_SIGN1_VERIFY_H__ */ diff --git a/lib/t_cose/src/t_cose_crypto.h b/lib/t_cose/src/t_cose_crypto.h deleted file mode 100644 index 83d9f33d30..0000000000 --- a/lib/t_cose/src/t_cose_crypto.h +++ /dev/null @@ -1,470 +0,0 @@ -/* - * t_cose_crypto.h - * - * Copyright 2019, Laurence Lundblade - * - * SPDX-License-Identifier: BSD-3-Clause - * - * See BSD-3-Clause license in README.md. - */ - - -#ifndef __T_COSE_CRYPTO_H__ -#define __T_COSE_CRYPTO_H__ - -#include "t_cose_common.h" -#include "q_useful_buf.h" -#include <stdint.h> -#include "t_cose_defines.h" - -#ifdef __cplusplus -extern "C" { -#endif - -/** - * \file t_cose_crypto.h - * - * \brief This is the adaptation layer for cryptographic functions used by - * t_cose. - * - * This is small wrapper around the cryptographic functions to: - * - Map COSE algorithm IDs to TF-M algorithm IDs - * - Map crypto errors to \ref t_cose_err_t errors - * - Have inputs and outputs be \c struct \c q_useful_buf_c and - * \c struct \c q_useful_buf - * - Handle key selection - * - * The idea is that implementations can be made of these functions - * that adapt to various cryptographic libraries that are used on - * various platforms and OSs. - * - * This runs entirely off of COSE-style algorithm identifiers. They - * are simple integers and thus work nice as function parameters. An - * initial set is defined by [COSE (RFC 8152)] - * (https://tools.ietf.org/html/rfc8152). New ones can be registered - * in the [IANA COSE Registry] - * (https://www.iana.org/assignments/cose/cose.xhtml). Local use new - * ones can also be defined (\c \#define) if what is needed is not in - * the IANA registry. - * - * Binary data is returned to the caller using a \c struct \c - * q_useful_buf to pass the buffer to receive the data and its length in - * and a \c q_useful_buf_c to return the pointer and length of the - * returned data. The point of this is coding hygiene. The buffer - * passed in is not const as it is to be modified. The \c - * q_useful_buf_c returned is const. - * - * The pointer in the \c q_useful_buf_c will always point to the buffer - * passed in via the \c q_useful_buf so the lifetime of the data is - * under control of the caller. - * - * This is not intended as any sort of general cryptographic API. It - * is just the functions needed by t_cose in the form that is most - * useful for t_cose. - */ - - -/** - * Size of the signature output for the NIST P-256 Curve. - */ -#define T_COSE_EC_P256_SIG_SIZE 64 - -/** - * Size of the largest signature of any of the algorithm types - * supported. - * - * This will have to be adjusted if support for other algorithms - * larger is added. - * - * This is a compile time constant so it can be used to define stack - * variable sizes. - */ -#define T_COSE_MAX_EC_SIG_SIZE T_COSE_EC_P256_SIG_SIZE - - -/** - * \brief Get the size in bytes of a particular signature type. - * - * \param[in] cose_sig_alg_id The COSE algorithm ID. - * - * \return The size in bytes of the signature for a public-key signing - * algorithm. - */ -static inline size_t t_cose_signature_size(int32_t cose_sig_alg_id); - - -/** - * \brief Perform public key signing. Part of the t_cose crypto - * adaptation layer. - * - * \param[in] cose_alg_id The algorithm to sign with. The IDs are - * defined in [COSE (RFC 8152)] - * (https://tools.ietf.org/html/rfc8152) or - * in the [IANA COSE Registry] - * (https://www.iana.org/assignments/cose/cose.xhtml). - * A proprietary ID can also be defined - * locally (\c \#define) if the needed - * one hasn't been registered. - * \param[in] key_select Indicates which key to use to sign. - * \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. - * - * \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 - * The requested signing algorithm, \c cose_alg_id, is 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_TAMPERING_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 key selection depends on the platform / OS. - * - * 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. - * - * 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_pub_key_sign(int32_t cose_alg_id, - int32_t key_select, - struct q_useful_buf_c hash_to_sign, - struct q_useful_buf signature_buffer, - struct q_useful_buf_c *signature); - - -/** - * \brief perform public key signature verification. Part of the - * t_cose crypto adaptation layer. - * - * \param[in] cose_alg_id The algorithm to use for verification. - * The IDs are defined in [COSE (RFC 8152)] - * (https://tools.ietf.org/html/rfc8152) - * or in the [IANA COSE Registry] - * (https://www.iana.org/assignments/cose/cose.xhtml). - * A proprietary ID can also be defined - * locally (\c \#define) if the needed one - * hasn't been registered. - * \param[in] key_select Verification key selection. - * \param[in] key_id A 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] signature The signature. - * - * This verifies that the \c signature passed in was over the \c - * hash_to_verify passed in. - * - * The public key used to verify the signature is selected by the \c - * key_id if it is not \c NULL_Q_USEFUL_BUF_C or the \c key_select if it - * is. - * - * The key selected must be, or include, a public key of the correct - * type for \c cose_alg_id. - * - * \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 - * The requested signing algorithm is 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_TAMPERING_DETECTED. - */ -enum t_cose_err_t -t_cose_crypto_pub_key_verify(int32_t cose_alg_id, - int32_t key_select, - struct q_useful_buf_c key_id, - struct q_useful_buf_c hash_to_verify, - struct q_useful_buf_c signature); - - -/** - * The size of X and Y coordinate in 2 parameter style EC public - * key. Format is as defined in [COSE (RFC 8152)] - * (https://tools.ietf.org/html/rfc8152) and [SEC 1: Elliptic Curve - * Cryptography](http://www.secg.org/sec1-v2.pdf). - * - * This size is well-known and documented in public standards. - */ -#define T_COSE_CRYPTO_EC_P256_COORD_SIZE 32 - - -/** - * \brief Get an elliptic curve public key. Part of the t_cose crypto - * adaptation layer. - * - * \param[in] key_select Used to look up the public - * key to return when \c kid is - * \c NULL_Q_USEFUL_BUF_C. - * \param[in] kid A key ID to look up against. May be - * \c NULL_Q_USEFUL_BUF_C. This is typically - * the kid from the COSE unprotected header. - * \param[out] cose_curve_id The curve ID of the key returned as - * defined by [COSE (RFC 8152)] - * (https://tools.ietf.org/html/rfc8152) - * or the IANA COSE registry. - * \param[in] buf_to_hold_x_coord Pointer and length into which the - * X coordinate is put. - * \param[in] buf_to_hold_y_coord Pointer and length into which the - * Y coordinate is put. - * \param[out] x_coord Pointer and length of the returned X - * coordinate. - * \param[out] y_coord Pointer and length of the returned Y - * coordinate. - * - * \retval T_COSE_SUCCESS - * The key was found and is returned. - * \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_FAIL - * General unspecific failure. - * \retval T_COSE_ERR_KEY_BUFFER_SIZE - * Buffer to hold the output was too small. - * - * This finds and returns a public key. Where it looks for the key is - * dependent on the OS / platform. - * - * \ref T_COSE_CRYPTO_EC_P256_COORD_SIZE is the size of the X or Y - * coordinate for the NIST P-256 curve. - * - * 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 X and Y coordinates. - */ -enum t_cose_err_t -t_cose_crypto_get_ec_pub_key(int32_t key_select, - struct q_useful_buf_c kid, - int32_t *cose_curve_id, - struct q_useful_buf buf_to_hold_x_coord, - struct q_useful_buf buf_to_hold_y_coord, - struct q_useful_buf_c *x_coord, - struct q_useful_buf_c *y_coord); - - -/* - * No function to get private key because there is no need for it. - * The private signing key only needs to exist behind - * t_cose_crypto_pub_key_sign(). - */ - - - - -#ifdef T_COSE_USE_B_CON_SHA256 -/* This is code for use with Brad Conte's crypto. See - * https://github.com/B-Con/crypto-algorithms and see the description - * of t_cose_crypto_hash - */ -#include "sha256.h" -#endif - - -/** - * The context for use with the hash adaptation layer here. - * - * Hash implementations for this porting layer are put into two - * different categories. - * - * The first can be supported generically without any dependency on - * the actual hash implementation in this header. These only need a - * pointer or handle for the hash context. Usually these are - * implemented by a service, system API or crypto HW that runs in a - * separate context or process. They probably allocate memory - * internally. These can use context.ptr or context.handle to hold the - * pointer or handle to the hash context. - * - * The second sort of hash implementations need more than just a - * pointer or handle. Typically these are libraries that are linked - * with this code and run in the same process / context / thread as - * this code. These can be efficient requiring no context switches or - * memory allocations. These type require this header be modified for - * the #include which defines the hash context and so this struct - * includes that context as a member. This context is allocated on the - * stack, so any members added here should be small enough to go on - * the stack. USE_B_CON_SHA256 is an example of this type. - * - * The actual implementation of the hash is in a separate .c file - * that will be specific to the particular platform, library, - * service or such used. - */ -struct t_cose_crypto_hash { - -#ifdef T_COSE_USE_B_CON_SHA256 - /* Specific context for Brad Conte's sha256.c */ - SHA256_CTX context; -#else - /* - * Generic pointer / handle that can work for many - * hash implementations. - */ - union { - void *ptr; - uint64_t handle; - } context; - int64_t status; -#endif - -}; - - -/** - * The size of the output of SHA-256 in bytes. - * - * (It is safe to define this independently here as its size is - * well-known and fixed. There is no need to reference - * platform-specific headers and incur messy dependence.) - */ -#define T_COSE_CRYPTO_SHA256_SIZE 32 - - -/** - * \brief Start cryptographic hash. Part of the t_cose crypto - * adaptation layer. - * - * \param[in,out] hash_ctx Pointer to the hash context that - * will be initialized. - * \param[in] cose_hash_alg_id Algorithm ID that identifies the - * hash to use. This is from the - * [IANA COSE Registry] - * (https://www.iana.org/assignments/cose/cose.xhtml). - * As of the creation of this interface - * no identifiers of only a hash - * functions have been registered. - * Signature algorithms that include - * specification of the hash have been - * registered, but they are not to be - * used here. Until hash functions only - * have been officially registered, some - * IDs are defined in the proprietary - * space in t_cose_common.h. - * - * \retval T_COSE_ERR_UNSUPPORTED_HASH - * The requested algorithm is unknown or unsupported. - * - * \retval T_COSE_ERR_HASH_GENERAL_FAIL - * Some general failure of the hash function - * - * This initializes the hash context for the particular algorithm. It - * must be called first. A \c hash_ctx can be reused if it is - * reinitialized. - */ -enum t_cose_err_t -t_cose_crypto_hash_start(struct t_cose_crypto_hash *hash_ctx, - int32_t cose_hash_alg_id); - - -/** - * \brief Feed data into a cryptographic hash. Part of the t_cose - * crypto adaptation layer. - * - * \param[in,out] hash_ctx Pointer to the hash context in which - * accumulate the hash. - * \param[in] data_to_hash Pointer and length of data to feed into - * hash. The pointer may by \c NULL in which - * case no hashing is performed. - * - * There is no return value. If an error occurs it is remembered in \c - * hash_ctx and returned when t_cose_crypto_hash_finish() is called. - * Once in the error state, this function may be called, but it will - * not do anything. - * - * This function can be called with \c data_to_hash.ptr NULL and it - * will pretend to hash. This allows the same code that is used to - * produce the real hash to be used to return a length of the would be - * hash for encoded data structure size calculations. - */ -void t_cose_crypto_hash_update(struct t_cose_crypto_hash *hash_ctx, - struct q_useful_buf_c data_to_hash); - - -/** - * \brief Finish a cryptographic hash. Part of the t_cose crypto - * adaptation layer. - * - * \param[in,out] hash_ctx Pointer to the hash context. - * \param[in] buffer_to_hold_result Pointer and length into which - * the resulting hash is put. - * \param[out] hash_result Pointer and length of the - * resulting hash. - * - * \retval T_COSE_ERR_HASH_GENERAL_FAIL - * Some general failure of the hash function. - * \retval T_COSE_ERR_HASH_BUFFER_SIZE - * The size of the buffer to hold the hash result was - * too small. - * - * Call this to complete the hashing operation. If the everything - * completed correctly, the resulting hash is returned. Note that any - * errors that occurred during t_cose_crypto_hash_update() are - * returned here. - * - * 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 hash. - */ -enum t_cose_err_t -t_cose_crypto_hash_finish(struct t_cose_crypto_hash *hash_ctx, - struct q_useful_buf buffer_to_hold_result, - struct q_useful_buf_c *hash_result); - - - -/* - * Public inline function. See documentation above. - */ -static inline size_t t_cose_signature_size(int32_t cose_sig_alg_id) -{ - switch(cose_sig_alg_id) { - case COSE_ALGORITHM_ES256: - return T_COSE_EC_P256_SIG_SIZE; - default: - return T_COSE_EC_P256_SIG_SIZE; - } -} - - -#ifdef __cplusplus -} -#endif - -#endif /* __T_COSE_CRYPTO_H__ */ diff --git a/lib/t_cose/src/t_cose_defines.h b/lib/t_cose/src/t_cose_defines.h deleted file mode 100644 index e2cc970eae..0000000000 --- a/lib/t_cose/src/t_cose_defines.h +++ /dev/null @@ -1,291 +0,0 @@ -/* - * t_cose_defines.h - * - * Copyright (c) 2018-2019, Laurence Lundblade. All rights reserved. - * - * SPDX-License-Identifier: BSD-3-Clause - * - * See BSD-3-Clause license in README.md - */ - -#ifndef __T_COSE_DEFINES_H__ -#define __T_COSE_DEFINES_H__ - -/** - * \file t_cose_defines.h - * - * \brief Constants from COSE standard and IANA registry. - * - * This file contains constants identifiers defined in [COSE (RFC - * 8152)] (https://tools.ietf.org/html/rfc8152) and [IANA COSE - * Registry] (https://www.iana.org/assignments/cose/cose.xhtml). They - * include algorithm IDs and other constants. - * - * Many constants in the IANA registry are not included here yet as - * they are not needed by t_cose. They can be added if they become - * needed. - */ - - - - -/* --------------- COSE Header parameters ----------- - * https://www.iana.org/assignments/cose/cose.xhtml#header-parameters - */ - -/** - * \def COSE_HEADER_PARAM_ALG - * - * \brief Label of COSE header that indicates an algorithm. - */ -#define COSE_HEADER_PARAM_ALG 1 - -/** - * \def COSE_HEADER_PARAM_KID - * - * \brief Label of COSE header that contains a key ID. - */ -#define COSE_HEADER_PARAM_KID 4 - - - - -/* ------------ COSE Header Algorithm Parameters -------------- - * https://www.iana.org/assignments/cose/cose.xhtml#header-algorithm-parameters - * - * None of these are defined here yet, as they are not needed by t_cose yet. - */ - - - - -/* ------------- COSE Algorithms ---------------------------- - * https://www.iana.org/assignments/cose/cose.xhtml#algorithms - */ - -/** - * \def COSE_ALGORITHM_ES256 - * - * \brief Indicates ECDSA with SHA-256. - * - * Value for \ref COSE_HEADER_PARAM_ALG to indicate ECDSA. w/SHA-256 - */ -#define COSE_ALGORITHM_ES256 -7 - -/** - * \def COSE_ALGORITHM_ES384 - * - * \brief Indicates ECDSA with SHA-384. - * - * Value for \ref COSE_HEADER_PARAM_ALG to indicate ECDSA. w/SHA-384 - */ -#define COSE_ALGORITHM_ES384 -35 - -/** - * \def COSE_ALGORITHM_ES512 - * - * \brief Indicates ECDSA with SHA-384. - * - * Value for \ref COSE_HEADER_PARAM_ALG to indicate ECDSA. w/SHA-512 - */ -#define COSE_ALGORITHM_ES512 -36 - - -/** - * \def COSE_ALG_SHA256_PROPRIETARY - * - * \brief COSE-style algorithm ID for SHA256. The official COSE - * algorithm registry doesn't yet define an ID for a pure hash - * function. One is needed for internal use, so this is defined. - * - * This is only used internally in the implementation and doesn't - * appear in any protocol messages so there are no interoperability - * issues. When this gets defined in the IANA registry, that value can - * be substituted here and all will work fine. - */ -#define COSE_ALG_SHA256_PROPRIETARY -72000 - - - - -/* ---------- COSE Key Common Parameters -------------- - * https://www.iana.org/assignments/cose/cose.xhtml#key-common-parameters - */ - -/** - * \def COSE_KEY_COMMON_KTY - * - * \brief Label for data item containing the key type. - * - * In a \c COSE_Key, label that indicates the data item containing the - * key type. - */ -#define COSE_KEY_COMMON_KTY 1 - -/** - * \def COSE_KEY_COMMON_KID - * - * \brief Label for data item containing the key's kid. - * - * In a \c COSE_Key, label that indicates the data item containing the - * kid of this key. - */ -#define COSE_KEY_COMMON_KID 2 - - - - -/* ---------- COSE Key Type Parameters -------------------- - * https://www.iana.org/assignments/cose/cose.xhtml#key-type-parameters - */ - -/** - * \def COSE_KEY_PARAM_CRV - * - * \brief Label for data item indicating EC curve. - * - * In a \c COSE_Key that holds an EC key of either type \ref - * COSE_KEY_TYPE_EC2 or \ref COSE_KEY_TYPE_OKP this labels the data - * item with the EC curve for the key. - */ -#define COSE_KEY_PARAM_CRV -1 - -/** - * \def COSE_KEY_PARAM_X_COORDINATE - * - * \brief Label for data item that is an X coordinate of an EC key. - * - * In a \c COSE_Key that holds an EC key, this is label that indicates - * the data item containing the X coordinate. - * - * This is used for both key types \ref COSE_KEY_TYPE_EC2 and \ref - * COSE_KEY_TYPE_OKP. - */ -#define COSE_KEY_PARAM_X_COORDINATE -2 - -/** - * \def COSE_KEY_PARAM_Y_COORDINATE - * - * \brief Label for data item that is a y coordinate of an EC key. - * - * In a COSE_Key that holds an EC key, this is label that indicates - * the data item containing the Y coordinate. - * - * This is used only for key type \ref COSE_KEY_TYPE_EC2. - */ -#define COSE_KEY_PARAM_Y_COORDINATE -3 - -/** - * \def COSE_KEY_PARAM_PRIVATE_D - * - * \brief Label for data item that is d, the private part of EC key. - * - * In a \c COSE_Key that holds an EC key, this is label that indicates - * the data item containing the Y coordinate. - * - * This is used for both key types \ref COSE_KEY_TYPE_EC2 and \ref - * COSE_KEY_TYPE_OKP. - */ -#define COSE_KEY_PARAM_PRIVATE_D -4 - - - - -/* ---------- COSE Key Types -------------------------------- - * https://www.iana.org/assignments/cose/cose.xhtml#key-type - */ - -/** - * \def COSE_KEY_TYPE_OKP - * - * \brief Key type is Octet Key Pair - * - * In a \c COSE_Key, this is a value of the data item labeled \ref - * COSE_KEY_COMMON_KTY that indicates the \c COSE_Key is some sort of - * key pair represented by some octets. It may or may not be an EC - * key. - */ -#define COSE_KEY_TYPE_OKP 1 - -/** - * \def COSE_KEY_TYPE_EC2 - * - * \brief Key is a 2-parameter EC key. - * - * In a \c COSE_Key, this is a value of the data item labeled \ref - * COSE_KEY_COMMON_KTY that indicates the \c COSE_Key is an EC key - * specified with two coordinates, X and Y. - */ -#define COSE_KEY_TYPE_EC2 2 - -/** - * \def COSE_KEY_TYPE_SYMMETRIC - * - * \brief Key is a symmetric key. - * - * In a \c COSE_Key, this is a value of the data item labeled \ref - * COSE_KEY_COMMON_KTY that indicates the \c COSE_Key is a symmetric - * key. - */ -#define COSE_KEY_TYPE_SYMMETRIC 4 - - - - -/* ----------- COSE Elliptic Curves --------------------- - * https://www.iana.org/assignments/cose/cose.xhtml#elliptic-curves - */ - -/** - * \def COSE_ELLIPTIC_CURVE_P_256 - * - * \brief Key type for NIST P-256 key - * - * In a \c COSE_Key, this is a value of the data item labeled \ref - * COSE_KEY_PARAM_CRV to indicate the NIST P-256 curve, also known as - * secp256r1. - * - * This key type is always \ref COSE_KEY_TYPE_EC2. - */ -#define COSE_ELLIPTIC_CURVE_P_256 1 - -/** - * \def COSE_ELLIPTIC_CURVE_P_384 - * - * \brief Key type for NIST P-384 key - * - * In a \c COSE_Key, this is a value of the data item labeled \ref - * COSE_KEY_PARAM_CRV to indicate the NIST P-384 curve, also known as - * secp384r1. - * - * This key type is always \ref COSE_KEY_TYPE_EC2. - */ -#define COSE_ELLIPTIC_CURVE_P_384 2 - -/** - * \def COSE_ELLIPTIC_CURVE_P_521 - * - * \brief Key type for NIST P-521 key - * - * In a \c COSE_Key, this is a value of the data item labeled \ref - * COSE_KEY_PARAM_CRV to indicate the NIST P-521 curve, also known as - * secp521r1. - */ -#define COSE_ELLIPTIC_CURVE_P_521 3 - - - - -/* ------- Constants from RFC 8152 --------- - */ - -/** - * \def COSE_SIG_CONTEXT_STRING_SIGNATURE1 - * - * \brief This is a string constant used by COSE to label \c COSE_Sign1 - * structures. See RFC 8152, section 4.4. - */ -#define COSE_SIG_CONTEXT_STRING_SIGNATURE1 "Signature1" - - -#endif /* __T_COSE_DEFINES_H__ */ diff --git a/lib/t_cose/src/t_cose_psa_crypto_hash.c b/lib/t_cose/src/t_cose_psa_crypto_hash.c deleted file mode 100644 index 3ba3e2fdbb..0000000000 --- a/lib/t_cose/src/t_cose_psa_crypto_hash.c +++ /dev/null @@ -1,180 +0,0 @@ -/* - * t_cose_psa_crypto_hash.c - * - * Copyright 2019, Laurence Lundblade - * - * Copyright (c) 2019, Arm Limited. - * - * SPDX-License-Identifier: BSD-3-Clause - * - * See BSD-3-Clause license in README.md - */ - -#include "t_cose_crypto.h" -#include "psa/crypto.h" - -/** - * \brief Convert COSE algorithm ID to a PSA algorithm ID - * - * \param[in] cose_hash_alg_id The COSE-based ID for the - * - * \return PSA-based hash algorithm ID, or MD4 in the case of error. - * - */ -static inline psa_algorithm_t cose_hash_alg_id_to_psa(int32_t cose_hash_alg_id) -{ - psa_algorithm_t return_value; - - switch (cose_hash_alg_id) { - - case COSE_ALG_SHA256_PROPRIETARY: - return_value = PSA_ALG_SHA_256; - break; - - default: - return_value = PSA_ALG_MD4; - break; - } - - return return_value; -} - - -/** - * \brief Map a PSA error into a t_cose error. - * - * \param[in] status The PSA status. - * - * \return The t_cose error. - */ -static inline enum t_cose_err_t psa_status_to_t_cose_error(psa_status_t status) -{ - switch (status) { - - case PSA_SUCCESS: - return T_COSE_SUCCESS; - - case PSA_ERROR_NOT_SUPPORTED: - return T_COSE_ERR_UNSUPPORTED_HASH; - - case PSA_ERROR_BUFFER_TOO_SMALL: - return T_COSE_ERR_HASH_BUFFER_SIZE; - - default: - return T_COSE_ERR_HASH_GENERAL_FAIL; - } -} - - -/* - * See documentation in t_cose_crypto.h - */ -enum t_cose_err_t t_cose_crypto_hash_start(struct t_cose_crypto_hash *hash_ctx, - int32_t cose_hash_alg_id) -{ - /* Here's how t_cose_crypto_hash is used with PSA hashes. - * - * If you look inside psa_hash.handle is just a uint32_t that is - * used as a handle. To avoid modifying t_cose_crypto.h in a - * PSA-specific way, this implementation just copies the PSA - * handle from the generic t_cose_crypto_hash on entry to a hash - * function, and back on exit. - * - * This could have been implemented by modifying t_cose_crypto.h - * so that psa_hash_operation_t is a member of t_cose_crypto_hash. - * It's nice to not have to modify t_cose_crypto.h. - * - * This would have been cleaner if psa_hash_operation_t didn't - * exist and the PSA crypto just used a plain pointer or integer - * handle. If psa_hash_operation_t is changed to be different - * than just the single uint32_t, then this code has to change. - * - * The status member of t_cose_crypto_hash is used to hold a - * psa_status_t error code. - */ - psa_hash_operation_t psa_hash = PSA_HASH_OPERATION_INIT; - psa_algorithm_t psa_alg; - - /* Map the algorithm ID */ - psa_alg = cose_hash_alg_id_to_psa(cose_hash_alg_id); - - /* Actually do the hash set up */ - hash_ctx->status = psa_hash_setup(&psa_hash, psa_alg); - - /* Copy the PSA handle back into the context */ - hash_ctx->context.handle = psa_hash.handle; - - /* Map errors and return */ - return psa_status_to_t_cose_error((psa_status_t)hash_ctx->status); -} - -/* - * See documentation in t_cose_crypto.h - */ -void t_cose_crypto_hash_update(struct t_cose_crypto_hash *hash_ctx, - struct q_useful_buf_c data_to_hash) -{ - /* See t_cose_crypto_hash_start() for context handling details */ - psa_hash_operation_t psa_hash; - - /* Copy the PSA handle out of the generic context */ - psa_hash.handle = (uint32_t)hash_ctx->context.handle; - - if(hash_ctx->status != PSA_SUCCESS) { - /* In error state. Nothing to do. */ - return; - } - - if(data_to_hash.ptr == NULL) { - /* No data was passed in to be hashed indicating the mode of use is - * the computation of the size of hash. This mode is hashing is used - * by t_cose when it is requested to compute the size of the signed - * data it might compute, which is in turn used to compute the - * size of a would be token. When computing the size, the size - * like this, there is nothing to do in update() - */ - return; - } - - /* Actually hash the data */ - hash_ctx->status = psa_hash_update(&psa_hash, - data_to_hash.ptr, - data_to_hash.len); - - /* Copy the PSA handle back into the context. */ - hash_ctx->context.handle = psa_hash.handle; -} - -/* - * See documentation in t_cose_crypto.h - */ -enum t_cose_err_t -t_cose_crypto_hash_finish(struct t_cose_crypto_hash *hash_ctx, - struct q_useful_buf buffer_to_hold_result, - struct q_useful_buf_c *hash_result) -{ - /* See t_cose_crypto_hash_start() for context handling details */ - psa_hash_operation_t psa_hash; - - /* Copy the PSA handle out of the generic context */ - psa_hash.handle = (uint32_t)hash_ctx->context.handle; - - if(hash_ctx->status != PSA_SUCCESS) { - /* Error state. Nothing to do */ - goto Done; - } - - /* Actually finish up the hash */ - hash_ctx->status = psa_hash_finish(&psa_hash, - buffer_to_hold_result.ptr, - buffer_to_hold_result.len, - &(hash_result->len)); - - hash_result->ptr = buffer_to_hold_result.ptr; - - /* Copy the PSA handle back into the context. */ - hash_ctx->context.handle = psa_hash.handle; - -Done: - return psa_status_to_t_cose_error((psa_status_t)hash_ctx->status); -} diff --git a/lib/t_cose/src/t_cose_psa_crypto_sign.c b/lib/t_cose/src/t_cose_psa_crypto_sign.c deleted file mode 100644 index 85800f54f7..0000000000 --- a/lib/t_cose/src/t_cose_psa_crypto_sign.c +++ /dev/null @@ -1,147 +0,0 @@ -/* - * Copyright (c) 2019, Arm Limited. All rights reserved. - * - * SPDX-License-Identifier: BSD-3-Clause - * - */ - -#include "t_cose_crypto.h" -#include "attestation_key.h" -#include "tfm_plat_crypto_keys.h" -#include "tfm_memory_utils.h" -#include "psa/crypto.h" - -/* Avoid compiler warning due to unused argument */ -#define ARG_UNUSED(arg) (void)(arg) - -enum t_cose_err_t -t_cose_crypto_pub_key_sign(int32_t cose_alg_id, - int32_t key_select, - struct q_useful_buf_c hash_to_sign, - struct q_useful_buf signature_buffer, - struct q_useful_buf_c *signature) -{ - enum t_cose_err_t cose_ret = T_COSE_SUCCESS; - enum psa_attest_err_t attest_ret; - psa_status_t psa_ret; - const size_t sig_size = t_cose_signature_size(cose_alg_id); - psa_key_handle_t private_key; - - ARG_UNUSED(key_select); - - if (sig_size > signature_buffer.len) { - return T_COSE_ERR_SIG_BUFFER_SIZE; - } - - /* FixMe: Registration of key(s) should not be done by attestation service. - * Later Crypto service is going to get the attestation key from - * platform layer. - */ - attest_ret = - attest_get_initial_attestation_private_key_handle(&private_key); - if (attest_ret != PSA_ATTEST_ERR_SUCCESS) { - return T_COSE_ERR_FAIL; - } - - psa_ret = psa_asymmetric_sign(private_key, - PSA_ALG_ECDSA(PSA_ALG_SHA_256), - hash_to_sign.ptr, - hash_to_sign.len, - signature_buffer.ptr, /* Sig buf */ - signature_buffer.len, /* Sig buf size */ - &(signature->len)); /* Sig length */ - - if (psa_ret != PSA_SUCCESS) { - cose_ret = T_COSE_ERR_FAIL; - } else { - signature->ptr = signature_buffer.ptr; - } - - return cose_ret; -} - -#ifdef INCLUDE_TEST_CODE_AND_KEY_ID /* Remove them from release build */ - -/** - * \brief Map PSA curve types to the curve type definition by RFC8152 - * (COSE). - * - * \param[in] psa_curve PSA curve type definition \ref psa_ecc_curve_t. - * - * \return Return COSE curve type according to \ref cose_ecc_curve_t. If - * mapping is not possible then return with -1. - */ -static inline enum cose_ecc_curve_t -cose_map_psa_elliptic_curve_type(psa_ecc_curve_t psa_curve) -{ - enum cose_ecc_curve_t cose_curve; - - /* FixMe: Mapping is not complete, missing ones: ED25519, ED448 */ - switch (psa_curve) { - case PSA_ECC_CURVE_SECP256R1: - cose_curve = P_256; - break; - case PSA_ECC_CURVE_SECP384R1: - cose_curve = P_384; - break; - case PSA_ECC_CURVE_SECP521R1: - cose_curve = P_521; - break; - case PSA_ECC_CURVE_CURVE25519: - cose_curve = X25519; - break; - case PSA_ECC_CURVE_CURVE448: - cose_curve = X448; - break; - default: - cose_curve = -1; - } - - return cose_curve; -} - -enum t_cose_err_t -t_cose_crypto_get_ec_pub_key(int32_t key_select, - struct q_useful_buf_c kid, - int32_t *cose_curve_id, - struct q_useful_buf buf_to_hold_x_coord, - struct q_useful_buf buf_to_hold_y_coord, - struct q_useful_buf_c *x_coord, - struct q_useful_buf_c *y_coord) -{ - enum psa_attest_err_t attest_res; - uint8_t *public_key; - size_t key_len; - uint32_t key_coord_len; - psa_ecc_curve_t psa_curve; - - attest_res = - attest_get_initial_attestation_public_key(&public_key, &key_len, - &psa_curve); - if (attest_res != PSA_ATTEST_ERR_SUCCESS) { - return T_COSE_ERR_FAIL; - } - - *cose_curve_id = cose_map_psa_elliptic_curve_type(psa_curve); - - /* Key is made up of a 0x4 byte and two coordinates */ - key_coord_len = (key_len - 1) / 2; - - /* Place they key parts into the x and y buffers. Stars at index 1 to skip - * the 0x4 byte. - */ - *x_coord = q_useful_buf_copy_ptr(buf_to_hold_x_coord, - &public_key[1], - key_coord_len); - - *y_coord = q_useful_buf_copy_ptr(buf_to_hold_y_coord, - &public_key[1 + key_coord_len], - key_coord_len); - - if(q_useful_buf_c_is_null(*x_coord) || q_useful_buf_c_is_null(*y_coord)) { - return T_COSE_ERR_KEY_BUFFER_SIZE; - } - - return T_COSE_SUCCESS; -} -#endif /* INCLUDE_TEST_CODE_AND_KEY_ID */ diff --git a/lib/t_cose/src/t_cose_psa_crypto_verify.c b/lib/t_cose/src/t_cose_psa_crypto_verify.c deleted file mode 100644 index 5e25edf099..0000000000 --- a/lib/t_cose/src/t_cose_psa_crypto_verify.c +++ /dev/null @@ -1,51 +0,0 @@ -/* - * Copyright (c) 2019, Arm Limited. All rights reserved. - * - * SPDX-License-Identifier: BSD-3-Clause - * - */ - -#include "t_cose_crypto.h" -#include "psa/crypto.h" -#include "attest_public_key.h" - -/* Avoid compiler warning due to unused argument */ -#define ARG_UNUSED(arg) (void)(arg) - -enum t_cose_err_t -t_cose_crypto_pub_key_verify(int32_t cose_alg_id, - int32_t key_select, - struct q_useful_buf_c key_id, - struct q_useful_buf_c hash_to_verify, - struct q_useful_buf_c signature) -{ - enum t_cose_err_t cose_ret = T_COSE_SUCCESS; - enum psa_attest_err_t attest_ret; - psa_status_t psa_ret; - psa_key_handle_t public_key; - - ARG_UNUSED(cose_alg_id); - ARG_UNUSED(key_select); - - attest_ret = attest_register_initial_attestation_public_key(&public_key); - if (attest_ret != PSA_ATTEST_ERR_SUCCESS) { - return T_COSE_ERR_FAIL; - } - - psa_ret = psa_asymmetric_verify(public_key, - PSA_ALG_ECDSA(PSA_ALG_SHA_256), - hash_to_verify.ptr, - hash_to_verify.len, - signature.ptr, - signature.len); - if (psa_ret != PSA_SUCCESS) { - cose_ret = T_COSE_ERR_SIG_VERIFY; - } - - attest_ret = attest_unregister_initial_attestation_public_key(public_key); - if (attest_ret != PSA_ATTEST_ERR_SUCCESS) { - cose_ret = T_COSE_ERR_FAIL; - } - - return cose_ret; -} diff --git a/lib/t_cose/src/t_cose_sign1_sign.c b/lib/t_cose/src/t_cose_sign1_sign.c deleted file mode 100644 index 1e6e606a8a..0000000000 --- a/lib/t_cose/src/t_cose_sign1_sign.c +++ /dev/null @@ -1,526 +0,0 @@ -/* - * t_cose_sign1_sign.c - * - * Copyright (c) 2018-2019, Laurence Lundblade. All rights reserved. - * - * SPDX-License-Identifier: BSD-3-Clause - * - * See BSD-3-Clause license in README.md - */ - -#include "t_cose_sign1_sign.h" -#include "qcbor.h" -#include "t_cose_defines.h" -#include "t_cose_crypto.h" -#include "t_cose_util.h" - - -/** - * \file t_cose_sign1_sign.c - * - * \brief This implements t_cose signing - */ - -#ifdef INCLUDE_TEST_CODE_AND_KEY_ID /* Remove them from release build */ -/** - * \brief Create a short-circuit signature - * - * \param[in] cose_alg_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_alg_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 - */ - enum t_cose_err_t return_value; - size_t array_indx; - size_t amount_to_copy; - size_t sig_size; - - sig_size = t_cose_signature_size(cose_alg_id); - - 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 /* INCLUDE_TEST_CODE_AND_KEY_ID */ - - - -/** - * The maximum size of a CBOR Encoded \c COSE_Key that this - * implementation can handle. \c COSE_Key is the serialization format - * for public and other types of keys defined by [COSE (RFC 8152)] - * (https://tools.ietf.org/html/rfc8152). - * - * This can be increased to handle larger keys, but stack usage will - * go up with this increase. - */ -#define MAX_ENCODED_COSE_KEY_SIZE \ - 1 + /* 1 byte to encode map */ \ - 2 + /* 2 bytes to encode key type */ \ - 2 + /* 2 bytes to encode curve */ \ - 2 * /* the X and Y coordinates at 32 bytes each */ \ - (T_COSE_CRYPTO_EC_P256_COORD_SIZE + 1 + 2) - - -#ifdef INCLUDE_TEST_CODE_AND_KEY_ID /* Remove them from release build */ -/** - * \brief CBOR encode a public key as a \c COSE_Key - * - * \param[in] key_select Identifies the public key to encode. - * - * \param[in] buffer_for_cose_key Pointer and length of buffer into which - * the encoded \c COSE_Key is put. - * \param[in] cose_key Pointer and length of the encoded \c COSE_Key. - * - * \return This returns one of the error codes defined by \ref t_cose_err_t. - * - * \c COSE_Key is the COSE-defined format for serializing a key for - * transmission in a protocol. This function encodes an EC public key - * expressed as an X and Y coordinate. - */ -static enum t_cose_err_t -t_cose_encode_cose_key(int32_t key_select, - struct q_useful_buf buffer_for_cose_key, - struct q_useful_buf_c *cose_key) -{ - /* approximate stack use on 32-bit machine: - * local use: 328 - * with calls: 370 - */ - enum t_cose_err_t return_value; - QCBORError qcbor_result; - QCBOREncodeContext cbor_encode_ctx; - Q_USEFUL_BUF_MAKE_STACK_UB( buffer_for_x_coord, - T_COSE_CRYPTO_EC_P256_COORD_SIZE); - Q_USEFUL_BUF_MAKE_STACK_UB( buffer_for_y_coord, - T_COSE_CRYPTO_EC_P256_COORD_SIZE); - struct q_useful_buf_c x_coord; - struct q_useful_buf_c y_coord; - int32_t cose_curve_id; - struct q_useful_buf_c encoded_key_id; - - /* Get the public key x and y */ - return_value = t_cose_crypto_get_ec_pub_key(key_select, - NULL_Q_USEFUL_BUF_C, - &cose_curve_id, - buffer_for_x_coord, - buffer_for_y_coord, - &x_coord, - &y_coord); - if(return_value != T_COSE_SUCCESS) { - goto Done; - } - - /* Encode it into a COSE_Key structure */ - QCBOREncode_Init(&cbor_encode_ctx, buffer_for_cose_key); - QCBOREncode_OpenMap(&cbor_encode_ctx); - QCBOREncode_AddInt64ToMapN(&cbor_encode_ctx, - COSE_KEY_COMMON_KTY, - COSE_KEY_TYPE_EC2); - QCBOREncode_AddInt64ToMapN(&cbor_encode_ctx, - COSE_KEY_PARAM_CRV, - cose_curve_id); - QCBOREncode_AddBytesToMapN(&cbor_encode_ctx, - COSE_KEY_PARAM_X_COORDINATE, - x_coord); - QCBOREncode_AddBytesToMapN(&cbor_encode_ctx, - COSE_KEY_PARAM_Y_COORDINATE, - y_coord); - QCBOREncode_CloseMap(&cbor_encode_ctx); - - qcbor_result = QCBOREncode_Finish(&cbor_encode_ctx, &encoded_key_id); - if(qcbor_result != QCBOR_SUCCESS) { - /* Mainly means that the COSE_Key was too big for buffer_for_cose_key */ - return_value = T_COSE_ERR_PROTECTED_HEADERS; - goto Done; - } - - /* Finish up and return */ - *cose_key = encoded_key_id; - return_value = T_COSE_SUCCESS; - -Done: - return return_value; -} - - -/** - * \brief SHA-256 hash a buffer in one quick function - * - * \param[in] bytes_to_hash The bytes to be hashed. - * - * \param[in] buffer_for_hash Pointer and length into which - * the resulting hash is put. - * \param[out] hash Pointer and length of the - * resulting hash. - * \return This returns one of the error codes defined by \ref t_cose_err_t. - * - * Simple wrapper for start, update and finish interface to a hash. - * - * Having this as a separate function helps keep stack usage down and - * is convenient. - */ -static enum t_cose_err_t quick_sha256(struct q_useful_buf_c bytes_to_hash, - struct q_useful_buf buffer_for_hash, - struct q_useful_buf_c *hash) -{ - /* approximate stack use on 32-bit machine: - local use: 132 - */ - enum t_cose_err_t return_value = 0; - struct t_cose_crypto_hash hash_ctx; - - return_value = t_cose_crypto_hash_start(&hash_ctx, - COSE_ALG_SHA256_PROPRIETARY); - if(return_value) { - goto Done; - } - t_cose_crypto_hash_update(&hash_ctx, bytes_to_hash); - return_value = t_cose_crypto_hash_finish(&hash_ctx, - buffer_for_hash, - hash); - -Done: - return return_value; -} - - -/** - * \brief Make a key ID based on the public key to go in the kid - * unprotected header. - * - * \param[in] key_select Identifies the public key. - * \param[in] buffer_for_key_id Pointer and length into which - * the resulting key ID is put. - * \param[out] key_id Pointer and length of the - * resulting key ID. - * - * \return This returns one of the error codes defined by \ref t_cose_err_t. - * - * - * See t_cose_sign1_init() for documentation of the key ID format - * created here. - */ -static inline enum t_cose_err_t get_keyid(int32_t key_select, - struct q_useful_buf buffer_for_key_id, - struct q_useful_buf_c *key_id) -{ - /* approximate stack use on 32-bit machine: - * local use: 100 - * with calls inlined: 560 - * with calls not inlined: 428 - */ - enum t_cose_err_t return_value; - Q_USEFUL_BUF_MAKE_STACK_UB( buffer_for_cose_key, - MAX_ENCODED_COSE_KEY_SIZE); - struct q_useful_buf_c cose_key; - - /* Doing the COSE encoding and the hashing in separate functions - * called from here reduces the stack usage in this function by a - * lot - */ - - /* Get the key and encode it as a COSE_Key */ - return_value = t_cose_encode_cose_key(key_select, - buffer_for_cose_key, - &cose_key); - if(return_value != T_COSE_SUCCESS) { - goto Done; - } - - /* SHA256 hash of it is all we care about in the end */ - return_value = quick_sha256(cose_key, buffer_for_key_id, key_id); - -Done: - return return_value; -} -#endif /* INCLUDE_TEST_CODE_AND_KEY_ID */ - - -/** - * \brief Makes the protected headers for COSE. - * - * \param[in] cose_alg_id The COSE algorithm ID to put in the headers. - * - * \param[in] buffer_for_header Pointer and length into which - * the resulting encoded protected - * headers is put. - * - * \return The pointer and length of the protected headers is - * returned, or \c NULL_Q_USEFUL_BUF_C if this fails. - * - * The protected headers are returned in fully encoded CBOR format as - * they are added to the \c COSE_Sign1 as a binary string. This is - * different from the unprotected headers which are not handled this - * way. - * - * This returns \c NULL_Q_USEFUL_BUF_C if buffer_for_header was too - * small. See also definition of \ref T_COSE_SIGN1_MAX_PROT_HEADER - */ -static inline struct q_useful_buf_c -make_protected_header(int32_t cose_alg_id, - struct q_useful_buf buffer_for_header) -{ - /* approximate stack use on 32-bit machine: - * local use: 170 - * with calls: 210 - */ - struct q_useful_buf_c protected_headers; - QCBORError qcbor_result; - QCBOREncodeContext cbor_encode_ctx; - struct q_useful_buf_c return_value; - - QCBOREncode_Init(&cbor_encode_ctx, buffer_for_header); - QCBOREncode_OpenMap(&cbor_encode_ctx); - QCBOREncode_AddInt64ToMapN(&cbor_encode_ctx, - COSE_HEADER_PARAM_ALG, - cose_alg_id); - QCBOREncode_CloseMap(&cbor_encode_ctx); - qcbor_result = QCBOREncode_Finish(&cbor_encode_ctx, &protected_headers); - - if(qcbor_result == QCBOR_SUCCESS) { - return_value = protected_headers; - } else { - return_value = NULL_Q_USEFUL_BUF_C; - } - - return return_value; -} - - -/** - * \brief Add the unprotected headers to a CBOR encoding context - * - * \param[in] cbor_encode_ctx CBOR encoding context to output to - * \param[in] kid The key ID to go into the kid header. - * - * No error is returned. If an error occurred it will be returned when - * \c QCBOR_Finish() is called on \c cbor_encode_ctx. - * - * The unprotected headers added by this are just the key ID - */ -static inline void add_unprotected_headers(QCBOREncodeContext *cbor_encode_ctx, - struct q_useful_buf_c kid) -{ - QCBOREncode_OpenMap(cbor_encode_ctx); - if(!q_useful_buf_c_is_null_or_empty(kid)) { - QCBOREncode_AddBytesToMapN(cbor_encode_ctx, COSE_HEADER_PARAM_KID, kid); - } - QCBOREncode_CloseMap(cbor_encode_ctx); -} - -/* - * Public function. See t_cose_sign1_sign.h - */ -enum t_cose_err_t t_cose_sign1_init(struct t_cose_sign1_ctx *me, - bool short_circuit_sign, - int32_t cose_alg_id, - int32_t key_select, - QCBOREncodeContext *cbor_encode_ctx) -{ - /* approximate stack use on 32-bit machine: - * local use: 66 - * with calls inlined: 900 - * with calls not inlined: 500 - */ - - int32_t hash_alg; - enum t_cose_err_t return_value; - struct q_useful_buf buffer_for_protected_header; - -#ifdef INCLUDE_TEST_CODE_AND_KEY_ID /* Remove them from release build */ - Q_USEFUL_BUF_MAKE_STACK_UB( buffer_for_kid, T_COSE_CRYPTO_SHA256_SIZE); -#endif - struct q_useful_buf_c kid = NULLUsefulBufC; - - - /* Check the cose_alg_id now by getting the hash alg as an early - error check even though it is not used until later. */ - hash_alg = hash_alg_id_from_sig_alg_id(cose_alg_id); - if(hash_alg == INT32_MAX) { - return T_COSE_ERR_UNSUPPORTED_SIGNING_ALG; - } - - /* Remember all the parameters in the context */ - me->cose_algorithm_id = cose_alg_id; - me->key_select = key_select; - me->short_circuit_sign = short_circuit_sign; - me->cbor_encode_ctx = cbor_encode_ctx; - - /* Get the key id because it goes into the headers that are about - to be made. */ -#ifdef INCLUDE_TEST_CODE_AND_KEY_ID /* Remove them from release build */ - if(short_circuit_sign) { - return_value = get_short_circuit_kid(buffer_for_kid, &kid); - } else { - return_value = get_keyid(key_select, buffer_for_kid, &kid); - } - if(return_value) { - goto Done; - } -#endif - - /* Get started with the tagged array that holds the four parts of - a cose single signed message */ - QCBOREncode_AddTag(cbor_encode_ctx, CBOR_TAG_COSE_SIGN1); - QCBOREncode_OpenArray(cbor_encode_ctx); - - /* The protected headers, which are added as a wrapped bstr */ - buffer_for_protected_header = - Q_USEFUL_BUF_FROM_BYTE_ARRAY(me->buffer_for_protected_headers); - me->protected_headers = make_protected_header(cose_alg_id, - buffer_for_protected_header); - if(q_useful_buf_c_is_null(me->protected_headers)) { - /* The sizing of storage for protected headers is - off (should never happen in tested, released code) */ - return_value = T_COSE_SUCCESS; - goto Done; - } - QCBOREncode_AddBytes(cbor_encode_ctx, me->protected_headers); - - /* The Unprotected headers */ - add_unprotected_headers(cbor_encode_ctx, kid); - - /* Any failures in CBOR encoding will be caught in finish - when the CBOR encoding is closed off. No need to track - here as the CBOR encoder tracks it internally. */ - - return_value = T_COSE_SUCCESS; - -Done: - return return_value; -} - - -/* - * Public function. See t_cose_sign1_sign.h - */ -enum t_cose_err_t t_cose_sign1_finish(struct t_cose_sign1_ctx *me, - struct q_useful_buf_c signed_payload) -{ - /* approximate stack use on 32-bit machine: - * local use: 116 - * with calls inline: 500 - * with calls not inlined; 450 - */ - enum t_cose_err_t return_value; - /* 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_EC_SIG_SIZE); - /* Buffer for the tbs hash. Only big enough for SHA256 */ - Q_USEFUL_BUF_MAKE_STACK_UB( buffer_for_tbs_hash, - T_COSE_CRYPTO_SHA256_SIZE); - - if (QCBOREncode_IsBufferNULL(me->cbor_encode_ctx)) { - /* Just calculating sizes. All that is needed is the - * signature size. - */ - return_value = T_COSE_SUCCESS; - - signature.ptr = NULL; - signature.len = t_cose_signature_size(me->cose_algorithm_id); - - } else { - - /* Create the hash of the to-be-signed bytes. Inputs to the hash - * are the protected headers, the payload that 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, - buffer_for_tbs_hash, - &tbs_hash, - me->protected_headers, - T_COSE_TBS_PAYLOAD_IS_BSTR_WRAPPED, - signed_payload); - if (return_value) { - goto Done; - } - - /* 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 - * which to place the signature is passed in and the signature is - * returned. - * - * Short-circuit signing is invoked if requested. It does no - * public key operation and requires no key. It is just a test - * mode that always works. - */ -#ifdef INCLUDE_TEST_CODE_AND_KEY_ID /* Remove them from release build */ - if (me->short_circuit_sign) { - return_value = short_circuit_sign(me->cose_algorithm_id, - tbs_hash, - buffer_for_signature, - &signature); - } else { -#endif - return_value = t_cose_crypto_pub_key_sign(me->cose_algorithm_id, - me->key_select, - tbs_hash, - buffer_for_signature, - &signature); -#ifdef INCLUDE_TEST_CODE_AND_KEY_ID /* Remove them from release build */ - } -#endif - if (return_value) { - goto Done; - } - } - - /* Add signature to CBOR and close out the array */ - QCBOREncode_AddBytes(me->cbor_encode_ctx, signature); - QCBOREncode_CloseArray(me->cbor_encode_ctx); - - /* CBOR encoding errors are tracked in the CBOR encoding context - and handled in the layer above this */ - -Done: - return return_value; -} diff --git a/lib/t_cose/src/t_cose_sign1_verify.c b/lib/t_cose/src/t_cose_sign1_verify.c deleted file mode 100644 index f8dc74832d..0000000000 --- a/lib/t_cose/src/t_cose_sign1_verify.c +++ /dev/null @@ -1,280 +0,0 @@ -/* - * t_cose_sign1_verify.c - * - * Copyright 2019, Laurence Lundblade - * - * SPDX-License-Identifier: BSD-3-Clause - * - * See BSD-3-Clause license in README.md. - */ - - -#include "t_cose_sign1_verify.h" -#include "qcbor.h" -#include "t_cose_crypto.h" -#include "t_cose_defines.h" -#include "q_useful_buf.h" -#include "t_cose_util.h" -#include <stdbool.h> -#include "qcbor_util.h" - - -/** - * \file t_cose_sign1_verify.c - * - * \brief \c COSE_Sign1 verification implementation. - */ - -#ifdef INCLUDE_TEST_CODE_AND_KEY_ID /* Remove them from release build */ -/** - * \brief Verify a short-circuit signature - * - * \param[in] cose_alg_id The COSE signature algorithm to use. - * \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_init() for description of the short-circuit - * signature. - */ -static inline enum t_cose_err_t -t_cose_crypto_short_circuit_verify(int32_t cose_alg_id, - struct q_useful_buf_c hash_to_verify, - struct q_useful_buf_c signature) -{ - struct q_useful_buf_c hash_from_sig; - enum t_cose_err_t return_value; - - (void)cose_alg_id; /* unused variable */ - - 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 /* INCLUDE_TEST_CODE_AND_KEY_ID */ - - - -/** - * \brief Parse the unprotected headers. - * - * \param[in] protected_headers Pointer and length of CBOR-encoded - * protected headers to parse. - * \param[out] cose_alg_id Place to return the COSE algorithm ID - * - * \returns 0 on success, non-zero on failure. - * - * This parses the contents of the protected headers after the bstr - * wrapping is removed. It only looks for the COSE algorithm ID and - * ignores any other headers. - * - * This will error out if the CBOR is not well-formed, the protected - * headers are not a map the algorithm ID is not found, or the - * algorithm ID is larger than \c INT32_MAX or smaller than \c - * INT32_MIN. - */ -static int parse_protected_headers(struct q_useful_buf_c protected_headers, - int32_t *cose_alg_id) -{ - QCBORDecodeContext decode_context; - QCBORItem item; - - QCBORDecode_Init(&decode_context, protected_headers, QCBOR_DECODE_MODE_NORMAL); - - if(qcbor_util_get_item_in_map(&decode_context, - COSE_HEADER_PARAM_ALG, - &item)) { - return 1; - } - - if(QCBORDecode_Finish(&decode_context)) { - return 1; - } - - if(item.uDataType != QCBOR_TYPE_INT64 || item.val.int64 > INT32_MAX) { - return 1; - } - - *cose_alg_id = (int32_t)item.val.int64; - - return 0; -} - - -/** - * \brief Parse the unprotected COSE header to find the kid - * - * \param[in,out] decode_context The CBOR decoding context to read the - * unprotected headers from. - * \param[out] kid Pointer and length of the kid found. - * The storage for the kid is whatever was - * passed to the decoder. - * - * \retval -1 - * CBOR was not well-formed - * \retval 0 - * Success - * - * This will consume the entire map containing the unprotected - * headers. Any headers except the kid will be ignored. - * - * If no kid exists, NULL_Q_USEFUL_BUF_C will be returned in \c kid. - */ -int parse_unprotected_headers(QCBORDecodeContext *decode_context, - struct q_useful_buf_c *kid) -{ - struct qcbor_util_items_to_get_t items[2]; - int return_value; - - items[0].label = COSE_HEADER_PARAM_KID; /* kid */ - items[1].label = 0; /* terminate list */ - - return_value = qcbor_util_get_items_in_map(decode_context, items); - if(return_value) { - goto Done; - } - - *kid = items[0].item.val.string; - -Done: - return return_value; -} - - -/* - * Public function. See t_cose_sign1_verify.h - */ -enum t_cose_err_t t_cose_sign1_verify(int32_t option_flags, - int32_t key_select, - struct q_useful_buf_c cose_sign1, - struct q_useful_buf_c *payload) -{ - QCBORDecodeContext decode_context; - QCBORItem item; - struct q_useful_buf_c protected_headers; - int32_t cose_algorithm_id; - struct q_useful_buf_c kid = NULL_Q_USEFUL_BUF_C; - enum t_cose_err_t return_value; - int result; - /* Buffer for the tbs hash. Only big enough for SHA256 */ - Q_USEFUL_BUF_MAKE_STACK_UB( buffer_for_tbs_hash, - T_COSE_CRYPTO_SHA256_SIZE); - struct q_useful_buf_c tbs_hash; - struct q_useful_buf_c signature; -#ifdef INCLUDE_TEST_CODE_AND_KEY_ID /* Remove them from release build */ - Q_USEFUL_BUF_MAKE_STACK_UB (buf_for_short_circuit_kid, - T_COSE_SHORT_CIRCUIT_KID_SIZE); - struct q_useful_buf_c short_circuit_kid; -#endif - - *payload = NULL_Q_USEFUL_BUF_C; - - QCBORDecode_Init(&decode_context, cose_sign1, QCBOR_DECODE_MODE_NORMAL); - - /* -- The array of four -- */ - QCBORDecode_GetNext(&decode_context, &item); - if(item.uDataType != QCBOR_TYPE_ARRAY || item.val.uCount != 4 || - !QCBORDecode_IsTagged(&decode_context, &item, CBOR_TAG_COSE_SIGN1)) { - return_value = T_COSE_ERR_SIGN1_FORMAT; - goto Done; - } - - - /* -- Get the protected headers -- */ - QCBORDecode_GetNext(&decode_context, &item); - if(item.uDataType != QCBOR_TYPE_BYTE_STRING) { - return_value = T_COSE_ERR_SIGN1_FORMAT; - goto Done; - } - - protected_headers = item.val.string; - - result = parse_protected_headers(protected_headers, &cose_algorithm_id); - if(result == -1) { - return_value = T_COSE_ERR_CBOR_NOT_WELL_FORMED; - goto Done; - } else if (result == 1) { - return_value = T_COSE_ERR_NO_ALG_ID; - goto Done; - } - - /* -- Get the unprotected headers -- */ - result = parse_unprotected_headers(&decode_context, &kid); - if(result == -1) { - return_value = T_COSE_ERR_CBOR_NOT_WELL_FORMED; - goto Done; - } else if (result == 1) { - return_value = T_COSE_ERR_NO_KID; - goto Done; - } - - /* -- Get the payload -- */ - QCBORDecode_GetNext(&decode_context, &item); - if(item.uDataType != QCBOR_TYPE_BYTE_STRING) { - return_value = T_COSE_ERR_SIGN1_FORMAT; - goto Done; - } - *payload = item.val.string; - - - /* -- Get the signature -- */ - QCBORDecode_GetNext(&decode_context, &item); - if(item.uDataType != QCBOR_TYPE_BYTE_STRING) { - return_value = T_COSE_ERR_SIGN1_FORMAT; - goto Done; - } - signature = item.val.string; - - - /* -- Compute the TBS bytes -- */ - return_value = create_tbs_hash(cose_algorithm_id, - buffer_for_tbs_hash, - &tbs_hash, - protected_headers, - T_COSE_TBS_BARE_PAYLOAD, - *payload); - if(return_value) { - goto Done; - } - -#ifdef INCLUDE_TEST_CODE_AND_KEY_ID /* Remove them from release build */ - /* -- Check for short-circuit signature and verify if it exists -- */ - return_value = get_short_circuit_kid(buf_for_short_circuit_kid, - &short_circuit_kid); - if(!return_value && !q_useful_buf_compare(kid, short_circuit_kid)) { - if(!(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(cose_algorithm_id, - tbs_hash, - signature); - goto Done; - } -#endif - - - /* -- Verify the signature -- */ - return_value = t_cose_crypto_pub_key_verify(cose_algorithm_id, - key_select, - kid, - tbs_hash, - signature); - -Done: - return return_value; -} diff --git a/lib/t_cose/src/t_cose_util.c b/lib/t_cose/src/t_cose_util.c deleted file mode 100644 index 6cf1b03d13..0000000000 --- a/lib/t_cose/src/t_cose_util.c +++ /dev/null @@ -1,235 +0,0 @@ -/* - * t_cose_util.c - * - * Copyright 2019, Laurence Lundblade - * - * SPDX-License-Identifier: BSD-3-Clause - * - * See BSD-3-Clause license in README.md. - */ - -#include "t_cose_util.h" -#include "qcbor.h" -#include "t_cose_defines.h" -#include "t_cose_common.h" -#include "t_cose_crypto.h" - - -/** - * \file t_cose_util.c - * - * \brief Implementation of t_cose utility functions. - * - * These are some functions common to signing and - * verification. - */ - - -/* - * Public function. See t_cose_util.h - */ -int32_t hash_alg_id_from_sig_alg_id(int32_t cose_sig_alg_id) -{ - /* If other hashes, particularly those that output bigger hashes - * are added here, various other parts of this code have to be - * changed to have larger buffers. - */ - switch(cose_sig_alg_id) { - case COSE_ALGORITHM_ES256: - return COSE_ALG_SHA256_PROPRIETARY; - - default: - return INT32_MAX; - } -} - - -/* - * Format of to-be-signed bytes used by create_tbs_hash(). - * This is defined in COSE (RFC 8152). It is the input - * to the hash. - * - * Sig_structure = [ - * context : "Signature" / "Signature1" / "CounterSignature", - * body_protected : empty_or_serialized_map, - * ? sign_protected : empty_or_serialized_map, - * external_aad : bstr, - * payload : bstr - * ] - * - * body_protected refers to the protected headers from the - * main COSE_Sign1 structure. This is a little hard to - * to understand in the spec. - * - * sign_protected is not used with COSE_Sign1 since - * there is no signer chunk. - * - * external_aad allows external data to be covered - * by the hash, but is not supported by this implementation. - */ - - -/** - * This is the size of the first part of the CBOR encoded TBS - * bytes. It is around 30 bytes. See create_tbs_hash(). - */ -#define T_COSE_SIZE_OF_TBS \ - 1 + /* For opening the array */ \ - sizeof(COSE_SIG_CONTEXT_STRING_SIGNATURE1) + /* "Signature1" */ \ - 2 + /* Overhead for encoding string */ \ - T_COSE_SIGN1_MAX_PROT_HEADER + /* entire protected headers */ \ - 1 + /* Empty bstr for absent external_aad */ \ - 9 /* The max CBOR length encoding for start of payload */ - - -/* - * Public function. See t_cose_util.h - */ -enum t_cose_err_t create_tbs_hash(int32_t cose_alg_id, - struct q_useful_buf buffer_for_hash, - struct q_useful_buf_c *hash, - struct q_useful_buf_c protected_headers, - enum t_cose_tbs_hash_mode_t payload_mode, - struct q_useful_buf_c payload) -{ - /* approximate stack use on 32-bit machine: - * local use: 210 - * total with calls: 250 - * Can be another 128 bytes or so depending on - * t_cose_crypto_hash implementation. It sometimes - * includes the full hashing context. - */ - enum t_cose_err_t return_value; - QCBOREncodeContext cbor_encode_ctx; - UsefulBuf_MAKE_STACK_UB( buffer_for_TBS_first_part, T_COSE_SIZE_OF_TBS); - struct q_useful_buf_c tbs_first_part; - QCBORError qcbor_result; - struct t_cose_crypto_hash hash_ctx; - int32_t hash_alg_id; - size_t bytes_to_omit; - - /* This builds the CBOR-format to-be-signed bytes */ - QCBOREncode_Init(&cbor_encode_ctx, buffer_for_TBS_first_part); - QCBOREncode_OpenArray(&cbor_encode_ctx); - /* context */ - QCBOREncode_AddSZString(&cbor_encode_ctx, - COSE_SIG_CONTEXT_STRING_SIGNATURE1); - /* body_protected */ - QCBOREncode_AddBytes(&cbor_encode_ctx, - protected_headers); - /* sign_protected is not used for Sign1 */ - - /* external_aad. There is none so an empty bstr */ - QCBOREncode_AddBytes(&cbor_encode_ctx, NULL_Q_USEFUL_BUF_C); - - /* The short fake payload. */ - if(payload_mode == T_COSE_TBS_PAYLOAD_IS_BSTR_WRAPPED) { - /* Fake payload is just an empty bstr. It is here only - * to make the array count right. It must be ommitted - * in the actual hashing below - */ - bytes_to_omit = 1; - QCBOREncode_AddBytes(&cbor_encode_ctx, NULL_Q_USEFUL_BUF_C); - } else { - /* Fake payload is the type and length of the wrapping - * bstr. It gets hashed with the first part, so no - * bytes to omit. - */ - bytes_to_omit = 0; - QCBOREncode_AddBytesLenOnly(&cbor_encode_ctx, payload); - } - /* Cleverness only works because the payload is last in the array */ - - /* Close of the array */ - QCBOREncode_CloseArray(&cbor_encode_ctx); - - /* get the encoded results, except for payload */ - qcbor_result = QCBOREncode_Finish(&cbor_encode_ctx, &tbs_first_part); - if(qcbor_result) { - /* Mainly means that the protected_headers were too big - * (which should never happen) */ - return_value = T_COSE_ERR_SIG_STRUCT; - goto Done; - } - - /* Start the hashing */ - hash_alg_id = hash_alg_id_from_sig_alg_id(cose_alg_id); - /* Don't check hash_alg_id for failure. t_cose_crypto_hash_start() - * will handle it properly. - */ - return_value = t_cose_crypto_hash_start(&hash_ctx, hash_alg_id); - if(return_value) { - goto Done; - } - - /* This structure is hashed in two parts. The first part is - * the CBOR-formatted array with protected headers and such. - * The last part is the actual bytes of the payload. Doing it - * this way avoids having to allocate a big buffer to hold - * these two parts together. It avoids having two copies of - * the payload in the implementaiton as the payload as formatted - * in the output buffer can be what is hashed. They payload - * is the largest memory use, so this saves a lot. - * - * This is further complicated because the the payload - * does have to be wrapped in a bstr. It is done one way - * when signing and another when verifying. - */ - - /* This is hashing of the first part, all the CBOR - * except the payload. - */ - t_cose_crypto_hash_update(&hash_ctx, - q_useful_buf_head(tbs_first_part, - tbs_first_part.len - bytes_to_omit)); - - /* Hash the payload, the second part. This may or may not - * have the bstr wrapping. If not, it was hashed above. - */ - t_cose_crypto_hash_update(&hash_ctx, payload); - - /* Finish the hash and set up to return it */ - return_value = t_cose_crypto_hash_finish(&hash_ctx, - buffer_for_hash, - hash); -Done: - return return_value; -} - - -#ifdef INCLUDE_TEST_CODE_AND_KEY_ID /* Remove them from release build */ -/* - * Public function. See t_cose_util.h - */ -enum t_cose_err_t -get_short_circuit_kid(struct q_useful_buf buffer_for_kid, - struct q_useful_buf_c *kid) -{ - /* This is a random hard coded key ID that is used to indicate - * short-circuit signing. It is OK to hard code this as the - * probability of collision with this ID is very low and the same - * as for collision between any two key IDs of any sort. - */ - uint8_t defined_short_circuit_kid[] = { - 0xef, 0x95, 0x4b, 0x4b, 0xd9, 0xbd, 0xf6, 0x70, - 0xd0, 0x33, 0x60, 0x82, 0xf5, 0xef, 0x15, 0x2a, - 0xf8, 0xf3, 0x5b, 0x6a, 0x6c, 0x00, 0xef, 0xa6, - 0xa9, 0xa7, 0x1f, 0x49, 0x51, 0x7e, 0x18, 0xc6}; - - /* Prevent a dumb error where the size constant in the header is - * wrong.This check will be evaluated at compile time and optimize - * out when all is correct. - */ - if(sizeof(defined_short_circuit_kid) != T_COSE_SHORT_CIRCUIT_KID_SIZE) { - return T_COSE_ERR_BAD_SHORT_CIRCUIT_KID; - } - - *kid = q_useful_buf_copy(buffer_for_kid, - Q_USEFUL_BUF_FROM_BYTE_ARRAY_LITERAL( - defined_short_circuit_kid)); - - return q_useful_buf_c_is_null(*kid) ? - T_COSE_ERR_KEY_BUFFER_SIZE : - T_COSE_SUCCESS; -} -#endif /* INCLUDE_TEST_CODE_AND_KEY_ID */ diff --git a/lib/t_cose/src/t_cose_util.h b/lib/t_cose/src/t_cose_util.h deleted file mode 100644 index 90be5bda3e..0000000000 --- a/lib/t_cose/src/t_cose_util.h +++ /dev/null @@ -1,156 +0,0 @@ -/* - * t_cose_util.h - * - * Copyright 2019, Laurence Lundblade - * - * SPDX-License-Identifier: BSD-3-Clause - * - * See BSD-3-Clause license in README.md. - */ - - -#ifndef __T_COSE_UTIL_H__ -#define __T_COSE_UTIL_H__ - -#include <stdint.h> -#include "q_useful_buf.h" -#include "t_cose_common.h" - -#ifdef __cplusplus -extern "C" { -#endif - -/** - * \file t_cose_util.h - * - * \brief Utility functions used internally by the t_cose implementation. - * - */ - - -/** - * The modes in which the payload is passed to create_tbs_hash(). This - * exists so the TBS bytes can be hashed in two separate chunks and - * avoids needing a second buffer the size of the payload in the - * t_cose implementation. - */ -enum t_cose_tbs_hash_mode_t { - /** The bytes passed for the payload include a wrapping bstr so - * one does not need to be added. - */ - T_COSE_TBS_PAYLOAD_IS_BSTR_WRAPPED, - /** The bytes passed for the payload do NOT have a wrapping bstr - * so one must be added. - */ - T_COSE_TBS_BARE_PAYLOAD -}; - - -/** - * \brief Return hash algorithm ID from a signature algorithm ID - * - * \param[in] cose_sig_alg_id A COSE signature algorithm identifier. - * - * \return \c INT32_MAX when the signature algorithm ID is not known. - * - * This works off of algorithm identifiers defined in the [IANA COSE - * Registry] (https://www.iana.org/assignments/cose/cose.xhtml). - * Corresponding local integer constants are defined in - * t_cose_defines.h. - * - * COSE signing algorithms are the combination of public key - * algorithm, curve, key size, hash algorithm and hash size. They are - * simple integers making them convenient for direct use in code. - * - * This function returns an identifier for only the hash algorithm - * from the combined identifier. - * - * If the needed algorithm identifiers are not in the IANA registry, - * they can be added to it. This will take some time and work. It is - * also fine to use algorithms in the proprietary space. - */ -int32_t hash_alg_id_from_sig_alg_id(int32_t cose_sig_alg_id); - - -/** - * \brief Create the hash of the to-be-signed (TBS) bytes for COSE. - * - * \param[in] cose_alg_id The COSE signing algorithm ID. Used to - * determine which hash function to use. - * \param[in] buffer_for_hash Pointer and length of buffer into which - * the resulting hash is put. - * \param[out] hash Pointer and length of the - * resulting hash. - * \param[in] protected_headers The CBOR encoded protected headers. - * \param[in] payload_mode See \ref t_cose_tbs_hash_mode_t. - * \param[in] payload The CBOR encoded payload. It may or may - * not have a wrapping bstr per - * \c payload_mode. - * - * \return This returns one of the error codes defined by \ref t_cose_err_t. - * - * \retval T_COSE_ERR_SIG_STRUCT - * Most likely this is because the protected_headers passed in - * is larger than \ref T_COSE_SIGN1_MAX_PROT_HEADER. - * \retval T_COSE_ERR_UNSUPPORTED_HASH - * If the hash algorithm is not known. - * \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 headers - * 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. - */ -enum t_cose_err_t create_tbs_hash(int32_t cose_alg_id, - struct q_useful_buf buffer_for_hash, - struct q_useful_buf_c *hash, - struct q_useful_buf_c protected_headers, - enum t_cose_tbs_hash_mode_t payload_mode, - struct q_useful_buf_c payload); - - -/** - * Size of the key returned by get_short_circuit_kid(). It is always - * this size. - */ -#define T_COSE_SHORT_CIRCUIT_KID_SIZE 32 - - -/** - * \brief Get the special kid for short-circuit signing. - * - * \param[in] buffer_for_kid Pointer and length of buffer into which - * the resulting hash is put. It should - * always be at least \ref - * T_COSE_SHORT_CIRCUIT_KID_SIZE. - * \param[out] kid Pointer and length of the returned kid. - * - * \retval T_COSE_SUCCESS - * The kid was returned. - * \retval T_COSE_ERR_KEY_BUFFER_SIZE - * \c buffer_for_kid is too small - * - * This always returns the same key ID. It always indicates - * short-circuit signing. It is OK to hard code this as the - * probability of collision with this ID is extremely low and the same - * as for collision between any two key IDs (kids) of any sort. - * - * This is the value of the kid. - * - * 0xef, 0x95, 0x4b, 0x4b, 0xd9, 0xbd, 0xf6, 0x70, - * 0xd0, 0x33, 0x60, 0x82, 0xf5, 0xef, 0x15, 0x2a, - * 0xf8, 0xf3, 0x5b, 0x6a, 0x6c, 0x00, 0xef, 0xa6, - * 0xa9, 0xa7, 0x1f, 0x49, 0x51, 0x7e, 0x18, 0xc6 - * - */ -enum t_cose_err_t -get_short_circuit_kid(struct q_useful_buf buffer_for_kid, - struct q_useful_buf_c *kid); - -#ifdef __cplusplus -} -#endif - -#endif /* __T_COSE_UTIL_H__ */ |