Attest: Add attestation core, COSE library & tests

Adds core library for creating EAT (draft-mandyam-eat-01)
format attestations.  Adds t_cose an implementation of
COSE_Sign1 as defined in RFC 8152 section 4.2. Adds
basic test for creation of EAT format attestations.

Change-Id: I1ff8339edc55d50bd7639e42539844f2394280dc
Signed-off-by: Laurence Lundblade <lgl@securitytheory.com>
diff --git a/lib/t_cose/README.md b/lib/t_cose/README.md
new file mode 100644
index 0000000..9501806
--- /dev/null
+++ b/lib/t_cose/README.md
@@ -0,0 +1,95 @@
+#  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
new file mode 100644
index 0000000..d509a4b
--- /dev/null
+++ b/lib/t_cose/inc/t_cose_common.h
@@ -0,0 +1,148 @@
+/*
+ * t_cose_common.h
+ *
+ * Copyright 2019, Laurence Lundblade
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ *
+ * See BSD-3-Clause license in README.mdE.
+ */
+
+
+#ifndef __T_COSE_COMMON_H__
+#define __T_COSE_COMMON_H__
+
+
+/**
+ * \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
+};
+
+
+
+#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
new file mode 100644
index 0000000..35b26e5
--- /dev/null
+++ b/lib/t_cose/inc/t_cose_sign1_sign.h
@@ -0,0 +1,181 @@
+/*
+ * 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"
+
+
+/**
+ * \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 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 useful_buf_c payload);
+
+
+#endif /* __T_COSE_SIGN1_H__ */
diff --git a/lib/t_cose/src/t_cose_crypto.h b/lib/t_cose/src/t_cose_crypto.h
new file mode 100644
index 0000000..b77af32
--- /dev/null
+++ b/lib/t_cose/src/t_cose_crypto.h
@@ -0,0 +1,413 @@
+/*
+ * t_cose_crypto.h
+ *
+ * Copyright 2019, Laurence Lundblade
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ *
+ * See BSD-3-Clause license in README.mdE.
+ */
+
+
+#ifndef __T_COSE_CRYPTO_H__
+#define __T_COSE_CRYPTO_H__
+
+#include "t_cose_common.h"
+#include "useful_buf.h"
+#include <stdint.h>
+#include "t_cose_defines.h"
+
+
+/**
+ * \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 useful_buf_c and
+ *   \c struct \c 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
+ * useful_buf to pass the buffer to receive the data and its length in
+ * and a \c 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
+ * useful_buf_c returned is const.
+ *
+ * The pointer in the \c useful_buf_c will always point to the buffer
+ * passed in via the \c 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 useful_buf and \c 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 useful_buf_c hash_to_sign,
+                           struct useful_buf signature_buffer,
+                           struct 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_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_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 useful_buf_c key_id,
+                             struct useful_buf_c hash_to_verify,
+                             struct 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_USEFUL_BUF_C.
+ * \param[in] kid            A key ID to look up against. May be
+ *                           \c NULL_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 useful_buf and \c 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 useful_buf_c kid,
+                             int32_t *cose_curve_id,
+                             struct useful_buf buf_to_hold_x_coord,
+                             struct useful_buf buf_to_hold_y_coord,
+                             struct useful_buf_c  *x_coord,
+                             struct 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().
+ */
+
+
+
+
+/**
+ * The context for use with the hash adaptation layer here.
+ */
+struct t_cose_crypto_hash {
+    /* Can't put the actual size here without creating dependecy on
+     * actual hash implementation, so this is a fairly large and
+     * accommodating size.
+     */
+    uint8_t bytes[128];
+};
+
+
+/**
+ * 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.
+ */
+void t_cose_crypto_hash_update(struct t_cose_crypto_hash *hash_ctx,
+                               struct 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 useful_buf and \c 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 useful_buf buffer_to_hold_result,
+                          struct 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;
+    }
+}
+
+
+#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
new file mode 100644
index 0000000..e2cc970e
--- /dev/null
+++ b/lib/t_cose/src/t_cose_defines.h
@@ -0,0 +1,291 @@
+/*
+ * 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_sign1_sign.c b/lib/t_cose/src/t_cose_sign1_sign.c
new file mode 100644
index 0000000..8f55bc0
--- /dev/null
+++ b/lib/t_cose/src/t_cose_sign1_sign.c
@@ -0,0 +1,499 @@
+/*
+ * 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
+ */
+
+
+/**
+ * \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 useful_buf_c hash_to_sign,
+                   struct useful_buf signature_buffer,
+                   struct 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;
+}
+
+
+
+/**
+ * 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)
+
+
+/**
+ * \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 useful_buf buffer_for_cose_key,
+                       struct 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;
+    USEFUL_BUF_MAKE_STACK_UB( buffer_for_x_coord,
+                                  T_COSE_CRYPTO_EC_P256_COORD_SIZE);
+    USEFUL_BUF_MAKE_STACK_UB( buffer_for_y_coord,
+                                  T_COSE_CRYPTO_EC_P256_COORD_SIZE);
+    struct useful_buf_c       x_coord;
+    struct useful_buf_c       y_coord;
+    int32_t                   cose_curve_id;
+    struct 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_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 useful_buf_c bytes_to_hash,
+                                      struct useful_buf buffer_for_hash,
+                                      struct 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 useful_buf buffer_for_key_id,
+                                          struct 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;
+    USEFUL_BUF_MAKE_STACK_UB(   buffer_for_cose_key,
+                                    MAX_ENCODED_COSE_KEY_SIZE);
+    struct 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;
+}
+
+
+/**
+ * \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_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_USEFUL_BUF_C if buffer_for_header was too
+ * small. See also definition of \ref T_COSE_SIGN1_MAX_PROT_HEADER
+ */
+static inline struct useful_buf_c
+make_protected_header(int32_t cose_alg_id,
+                      struct useful_buf buffer_for_header)
+{
+    /* approximate stack use on 32-bit machine:
+     * local use: 170
+     * with calls: 210
+     */
+    struct useful_buf_c protected_headers;
+    QCBORError          qcbor_result;
+    QCBOREncodeContext  cbor_encode_ctx;
+    struct 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_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 useful_buf_c kid)
+{
+    QCBOREncode_OpenMap(cbor_encode_ctx);
+    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;
+    USEFUL_BUF_MAKE_STACK_UB(   buffer_for_kid, T_COSE_CRYPTO_SHA256_SIZE);
+    struct useful_buf_c         kid;
+    struct useful_buf           buffer_for_protected_header;
+
+    /* 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. */
+    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;
+    }
+
+    /* 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 =
+        USEFUL_BUF_FROM_BYTE_ARRAY(me->buffer_for_protected_headers);
+    me->protected_headers = make_protected_header(cose_alg_id,
+                                                  buffer_for_protected_header);
+    if(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 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 useful_buf_c        tbs_hash;
+    /* Pointer and length of the completed signature */
+    struct useful_buf_c        signature;
+    /* Buffer for the actual signature */
+    USEFUL_BUF_MAKE_STACK_UB(  buffer_for_signature,
+                                   T_COSE_MAX_EC_SIG_SIZE);
+    /* Buffer for the tbs hash. Only big enough for SHA256 */
+    USEFUL_BUF_MAKE_STACK_UB(  buffer_for_tbs_hash,
+                                   T_COSE_CRYPTO_SHA256_SIZE);
+
+    /* 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,
+                                   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.
+     */
+    if(me->short_circuit_sign) {
+        return_value = short_circuit_sign(me->cose_algorithm_id,
+                                          tbs_hash,
+                                          buffer_for_signature,
+                                          &signature);
+    } else {
+        return_value = t_cose_crypto_pub_key_sign(me->cose_algorithm_id,
+                                                  me->key_select,
+                                                  tbs_hash,
+                                                  buffer_for_signature,
+                                                  &signature);
+    }
+    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_util.c b/lib/t_cose/src/t_cose_util.c
new file mode 100644
index 0000000..ba4910e
--- /dev/null
+++ b/lib/t_cose/src/t_cose_util.c
@@ -0,0 +1,189 @@
+/*
+ *  t_cose_util.c
+ *
+ * Copyright 2019, Laurence Lundblade
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ *
+ * See BSD-3-Clause license in README.mdE.
+ */
+
+#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.
+ *
+ */
+
+
+/*
+ * 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
+ * ]
+ */
+
+
+/**
+ * This is the size of the first part of the CBOR encoded TBS
+ * bytes. It is around 20 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 */ \
+    3 * ( /* 3 NULL bstrs for fields not used */ \
+        1 /* size of a NULL bstr */  \
+    )
+
+
+/*
+ * Public function. See t_cose_util.h
+ */
+enum t_cose_err_t create_tbs_hash(int32_t cose_alg_id,
+                                  struct useful_buf buffer_for_hash,
+                                  struct useful_buf_c *hash,
+                                  struct useful_buf_c protected_headers,
+                                  struct useful_buf_c payload)
+{
+    /* approximate stack use on 32-bit machine:
+     * local use: 320
+     * with calls: 360
+     */
+    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 useful_buf_c         tbs_first_part;
+    QCBORError                  qcbor_result;
+    struct t_cose_crypto_hash   hash_ctx;
+    int32_t                     hash_alg_id;
+
+    /* 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 */
+    QCBOREncode_AddBytes(&cbor_encode_ctx, NULL_USEFUL_BUF_C);
+    /* external_aad */
+    QCBOREncode_AddBytes(&cbor_encode_ctx, NULL_USEFUL_BUF_C);
+    /* fake payload */
+    QCBOREncode_AddBytes(&cbor_encode_ctx, NULL_USEFUL_BUF_C);
+    QCBOREncode_CloseArray(&cbor_encode_ctx);
+
+    /* get the result and convert it to struct useful_buf_c representation */
+    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;
+    }
+
+    /* Hash the first part of the TBS. Take all but the last two
+     * bytes. The last two bytes are the fake payload from above. It
+     * is replaced by the real payload which is hashed next. The fake
+     * payload is needed so the array count is right. This is one of
+     * the main things that make it possible to implement with one
+     * buffer for the whole cose sign1.
+     */
+    t_cose_crypto_hash_update(&hash_ctx,
+                              useful_buf_head(tbs_first_part,
+                                              tbs_first_part.len - 2));
+
+    /* Hash the payload */
+    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;
+}
+
+
+/*
+ * Public function. See t_cose_util.h
+ */
+enum t_cose_err_t
+get_short_circuit_kid(struct useful_buf buffer_for_kid,
+                     struct 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 = useful_buf_copy(buffer_for_kid,
+                           USEFUL_BUF_FROM_BYTE_ARRAY_LITERAL(
+                               defined_short_circuit_kid));
+
+    return useful_buf_c_is_null(*kid) ?
+              T_COSE_ERR_KEY_BUFFER_SIZE :
+              T_COSE_SUCCESS;
+}
diff --git a/lib/t_cose/src/t_cose_util.h b/lib/t_cose/src/t_cose_util.h
new file mode 100644
index 0000000..7b39dc3
--- /dev/null
+++ b/lib/t_cose/src/t_cose_util.h
@@ -0,0 +1,126 @@
+/*
+ *  t_cose_util.h
+ *
+ * Copyright 2019, Laurence Lundblade
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ *
+ * See BSD-3-Clause license in README.mdE.
+ */
+
+
+#ifndef __T_COSE_UTIL_H__
+#define __T_COSE_UTIL_H__
+
+#include <stdint.h>
+#include "useful_buf.h"
+#include "t_cose_common.h"
+
+/**
+ * \file t_cose_util.h
+ *
+ * \brief Utility functions used internally by the t_cose implementation.
+ *
+ */
+
+
+/**
+ * \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           The CBOR encoded payload
+ *
+ * \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 useful_buf buffer_for_hash,
+                                  struct useful_buf_c *hash,
+                                  struct useful_buf_c protected_headers,
+                                  struct 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 useful_buf buffer_for_kid,
+                      struct useful_buf_c *kid);
+
+#endif /* __T_COSE_UTIL_H__ */