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/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;
+}