Put in first cut as signing
First cut as doing a signature - still has known problems
diff --git a/README.md b/README.md
new file mode 100644
index 0000000..9bf464a
--- /dev/null
+++ b/README.md
@@ -0,0 +1,23 @@
+# COSE-C Implementation
+
+This project is a C implementation of the IETF CBOR Encoded Mesage Syntax (COSE).
+There are currently two versions of the COSE document that can be read.
+The most current work in progress draft can be found on github in the [cose-wg/cose-spec](https://cose-wg.github.io/cose-spec/) project.
+The IETF also keeps a copy of the spec in the [COSE WG](https://tools.ietf.org/html/draft-ietf-cose-msg).
+
+The project is using the [CN-CBOR](https://github.com/cabo/cn-cbor) project to provide an implemenetation of the Concise Binary Object Representation or [CBOR](https://datatracker.ietf.org/doc/rfc7049/).
+
+The project is using OpenSSL for the cryptographic primatives.
+
+## Contributing
+
+## Building
+
+The project currently is using Visual Studio for it's build environment.
+The intention is to move to cmake in the future.
+
+## Memory Model
+
+The memory model used in this library is a mess. This is in large part because the memory model of cn-cbor is still poorly understood.
+
+This needs to get figured out in the near future.
diff --git a/src/Cose.c b/src/Cose.c
index 369b7e1..320ac92 100644
--- a/src/Cose.c
+++ b/src/Cose.c
@@ -228,3 +228,36 @@
return f;
}
+
+byte RgbDontUse3[1024];
+
+const cn_cbor * _COSE_encode_protected(COSE * pMessage, cose_errback * perr)
+{
+ const cn_cbor * pProtected;
+ int cbProtected;
+ byte * pbProtected = NULL;
+#ifdef USE_CBOR_CONTEXT
+ cn_cbor_context * context = &pMessage->m_allocContext;
+#endif // USE_CBOR_CONTEXT
+
+ pProtected = cn_cbor_mapget_int(pMessage->m_cbor, COSE_Header_Protected);
+ if (pProtected != NULL) {
+ errorReturn:
+ if (pbProtected != NULL) COSE_FREE(pbProtected, context);
+ return pProtected;
+ }
+
+ cbProtected = cn_cbor_encoder_write(RgbDontUse3, 0, sizeof(RgbDontUse3), pMessage->m_protectedMap);
+ pbProtected = (byte *)COSE_CALLOC(cbProtected, 1, context);
+ CHECK_CONDITION(pbProtected != NULL, COSE_ERR_OUT_OF_MEMORY);
+
+ CHECK_CONDITION(cn_cbor_encoder_write(pbProtected, 0, cbProtected, pMessage->m_protectedMap) == cbProtected, COSE_ERR_CBOR);
+
+ pProtected = cn_cbor_data_create(pbProtected, cbProtected, CBOR_CONTEXT_PARAM_COMMA NULL);
+ CHECK_CONDITION(pProtected != NULL, COSE_ERR_OUT_OF_MEMORY);
+ pbProtected = NULL;
+
+ CHECK_CONDITION(cn_cbor_mapput_int(pMessage->m_cbor, COSE_Header_Protected, pProtected, CBOR_CONTEXT_PARAM_COMMA NULL), COSE_ERR_CBOR);
+
+ return pProtected;
+}
diff --git a/src/Sign.c b/src/Sign.c
index b0e5d82..aefb765 100644
--- a/src/Sign.c
+++ b/src/Sign.c
@@ -98,3 +98,129 @@
_COSE_Release(&p->m_message);
}
+
+bool COSE_Sign_SetContent(HCOSE_SIGN h, const byte * rgb, size_t cb, cose_errback * perr)
+{
+#ifdef USE_CBOR_CONTEXT
+ cn_cbor_context * context;
+#endif
+ cn_cbor * p;
+ COSE_SignMessage * pMessage = (COSE_SignMessage *)h;
+
+ if (!IsValidSignHandle(h) || (rgb == NULL)) {
+ if (perr != NULL) perr->err = COSE_ERR_INVALID_PARAMETER;
+ errorReturn:
+ return false;
+ }
+
+#ifdef USE_CBOR_CONTEXT
+ context = &((COSE_SignMessage *)h)->m_message.m_allocContext;
+#endif
+
+ p = cn_cbor_data_create(rgb, cb, CBOR_CONTEXT_PARAM_COMMA NULL);
+ CHECK_CONDITION(p != NULL, CN_CBOR_ERR_OUT_OF_DATA);
+
+ CHECK_CONDITION(cn_cbor_mapput_int(pMessage->m_message.m_cbor, COSE_Header_Ciphertext, p, CBOR_CONTEXT_PARAM_COMMA NULL), COSE_ERR_OUT_OF_MEMORY);
+
+ return true;
+}
+
+HCOSE_SIGNER COSE_Sign_add_signer(HCOSE_SIGN hSign, const cn_cbor * pkey, int algId, cose_errback * perr)
+{
+#ifdef USE_CBOR_CONTEXT
+ cn_cbor_context * context = NULL;
+#endif
+ COSE_SignMessage * pMessage = (COSE_SignMessage *)hSign;
+ COSE_SignerInfo * pSigner = NULL;
+ const cn_cbor * cbor;
+ const cn_cbor * cbor2 = NULL;
+
+ if (!IsValidSignHandle(hSign) || (pkey == NULL)) {
+ if (perr != NULL) perr->err = COSE_ERR_INVALID_PARAMETER;
+ errorReturn:
+ if (cbor2 != NULL) CN_CBOR_FREE(cbor2, context);
+ if (pSigner != NULL) _COSE_Signer_Free(pSigner);
+ return NULL;
+ }
+
+ switch (algId) {
+ case COSE_Algorithm_ECDSA_SHA_256:
+ cbor = cn_cbor_mapget_int(pkey, COSE_Key_Type);
+ CHECK_CONDITION(cbor != NULL, COSE_ERR_INVALID_PARAMETER);
+ CHECK_CONDITION((cbor->type == CN_CBOR_UINT) && (cbor->v.uint == COSE_Key_Type_EC2), CN_CBOR_ERR_INVALID_PARAMETER);
+ break;
+
+ default:
+ CHECK_CONDITION(false, COSE_ERR_INVALID_PARAMETER);
+ }
+
+#ifdef USE_CBOR_CONTEXT
+ context = &pMessage->m_message.m_allocContext;
+#endif
+
+ pSigner = (COSE_SignerInfo *)COSE_CALLOC(1, sizeof(COSE_SignerInfo), context);
+ CHECK_CONDITION(pSigner != NULL, COSE_ERR_OUT_OF_MEMORY);
+
+ if (!_COSE_Init(&pSigner->m_message, CBOR_CONTEXT_PARAM_COMMA perr)) goto errorReturn;
+
+ cbor = cn_cbor_mapget_int(pkey, COSE_Key_ID);
+ if (cbor != NULL) {
+ CHECK_CONDITION(cbor->type == CN_CBOR_BYTES, CN_CBOR_ERR_INVALID_PARAMETER);
+ cbor2 = cn_cbor_data_create(cbor->v.str, cbor->length, CBOR_CONTEXT_PARAM_COMMA NULL);
+ CHECK_CONDITION(cbor2 != NULL, COSE_ERR_CBOR);
+ CHECK_CONDITION(cn_cbor_mapput_int(pSigner->m_message.m_unprotectMap, COSE_Parameter_KID, cbor2, CBOR_CONTEXT_PARAM_COMMA NULL), COSE_ERR_CBOR);
+ cbor2 = NULL;
+ }
+
+ pSigner->m_pkey = pkey;
+
+ pSigner->m_signerNext = pMessage->m_signerFirst;
+ pMessage->m_signerFirst = pSigner;
+
+ cn_cbor * pSigners = (cn_cbor *)cn_cbor_mapget_int(pMessage->m_message.m_cbor, COSE_Header_Signers);
+ if (pSigners == NULL) {
+ pSigners = cn_cbor_array_create(CBOR_CONTEXT_PARAM_COMMA NULL);
+ CHECK_CONDITION(pSigners != NULL, COSE_ERR_OUT_OF_MEMORY);
+ if (!cn_cbor_mapput_int(pMessage->m_message.m_cbor, COSE_Header_Signers, pSigners, CBOR_CONTEXT_PARAM_COMMA NULL)) {
+ cn_cbor_free(pSigners, context);
+ CHECK_CONDITION(false, COSE_ERR_CBOR);
+ }
+ }
+
+ CHECK_CONDITION(cn_cbor_array_append(pSigners, pSigner->m_message.m_cbor, CBOR_CONTEXT_PARAM_COMMA NULL), COSE_ERR_CBOR);
+
+ return (HCOSE_SIGNER)pSigner;
+}
+
+bool COSE_Sign_Sign(HCOSE_SIGN h, cose_errback * perr)
+{
+#ifdef USE_CBOR_CONTEXT
+ cn_cbor_context * context = NULL;
+#endif
+ COSE_SignMessage * pMessage = (COSE_SignMessage *)h;
+ COSE_SignerInfo * pSigner;
+ const cn_cbor * pcborBody;
+ const cn_cbor * pcborProtected;
+
+ if (!IsValidSignHandle(h)) {
+ CHECK_CONDITION(false, COSE_ERR_INVALID_PARAMETER);
+ errorReturn:
+ return false;
+ }
+#ifdef USE_CBOR_CONTEXT
+ context = &pMessage->m_message.m_allocContext;
+#endif
+
+ // From this layer we use the protected fields and the body
+ pcborBody = cn_cbor_mapget_int(pMessage->m_message.m_cbor, COSE_Header_Ciphertext);
+ CHECK_CONDITION(pcborBody != NULL, COSE_ERR_INVALID_PARAMETER);
+
+ pcborProtected = _COSE_encode_protected(&pMessage->m_message, perr);
+ if (pcborProtected == NULL) goto errorReturn;
+
+ for (pSigner = pMessage->m_signerFirst; pSigner != NULL; pSigner = pSigner->m_signerNext) {
+ if (!_COSE_Signer_sign(pSigner, pcborBody, pcborProtected, perr)) goto errorReturn;
+ }
+
+ return true;
+}
\ No newline at end of file
diff --git a/src/SignerInfo.c b/src/SignerInfo.c
index bc32412..bffe1ef 100644
--- a/src/SignerInfo.c
+++ b/src/SignerInfo.c
@@ -65,3 +65,61 @@
return pSigner;
}
+
+byte RgbDontUse4[1024];
+
+bool _COSE_Signer_sign(COSE_SignerInfo * pSigner, const cn_cbor * pcborBody, const cn_cbor * pcborProtected, cose_errback * perr)
+{
+#ifdef USE_CBOR_CONTEXT
+ cn_cbor_context * context = &pSigner->m_message.m_allocContext;
+#endif
+ cn_cbor * pcborBody2 = NULL;
+ cn_cbor * pcborProtected2 = NULL;
+ cn_cbor * pcborProtectedSign = NULL;
+ cn_cbor * pcborProtectedSign2 = NULL;
+ cn_cbor * pArray = NULL;
+ size_t cbToSign;
+ byte * pbToSign = NULL;
+ bool f;
+
+ pArray = cn_cbor_array_create(context, NULL);
+ if (pArray == NULL) {
+ if (perr != NULL) perr->err = COSE_ERR_OUT_OF_MEMORY;
+ errorReturn:
+ if (pcborBody2 != NULL) CN_CBOR_FREE(pcborBody2, context);
+ if (pcborProtected2 != NULL) CN_CBOR_FREE(pcborProtected2, context);
+ if (pArray != NULL) COSE_FREE(pArray, context);
+ if (pbToSign != NULL) COSE_FREE(pbToSign, context);
+ return false;
+ }
+
+ pcborProtectedSign = _COSE_encode_protected(&pSigner->m_message, perr);
+ if (pcborProtectedSign == NULL) goto errorReturn;
+
+ pcborBody2 = cn_cbor_data_create(pcborBody->v.str, pcborBody->length, CBOR_CONTEXT_PARAM_COMMA NULL);
+ CHECK_CONDITION(pcborBody2 != NULL, COSE_ERR_OUT_OF_MEMORY);
+
+ pcborProtected2 = cn_cbor_data_create(pcborProtected->v.str, pcborProtected->length, CBOR_CONTEXT_PARAM_COMMA NULL);
+ CHECK_CONDITION(pcborProtected2 != NULL, COSE_ERR_OUT_OF_MEMORY);
+
+ pcborProtectedSign2 = cn_cbor_data_create(pcborProtectedSign->v.str, pcborProtectedSign->length, CBOR_CONTEXT_PARAM_COMMA NULL);
+ CHECK_CONDITION(pcborProtectedSign2 != NULL, COSE_ERR_OUT_OF_MEMORY);
+
+ CHECK_CONDITION(cn_cbor_array_append(pArray, pcborProtected2, NULL), COSE_ERR_CBOR);
+ CHECK_CONDITION(cn_cbor_array_append(pArray, pcborProtectedSign2, NULL), COSE_ERR_CBOR);
+ CHECK_CONDITION(cn_cbor_array_append(pArray, cn_cbor_data_create(NULL, 0, CBOR_CONTEXT_PARAM_COMMA NULL), NULL), COSE_ERR_CBOR);
+ CHECK_CONDITION(cn_cbor_array_append(pArray, pcborBody2, NULL), COSE_ERR_CBOR);
+
+ cbToSign = cn_cbor_encoder_write(RgbDontUse4, 0, sizeof(RgbDontUse4), pArray);
+ CHECK_CONDITION(cbToSign > 0, COSE_ERR_CBOR);
+ pbToSign = (byte *)COSE_CALLOC(cbToSign, 1, context);
+ CHECK_CONDITION(pbToSign != NULL, COSE_ERR_OUT_OF_MEMORY);
+ CHECK_CONDITION(cn_cbor_encoder_write(pbToSign, 0, cbToSign, pArray), COSE_ERR_CBOR);
+
+ f = ECDSA_Sign(pSigner, pbToSign, cbToSign, perr);
+
+ COSE_FREE(pbToSign, context);
+ CN_CBOR_FREE(pArray, context);
+
+ return f;
+}
diff --git a/src/cose.h b/src/cose.h
index 28b0560..bff6d23 100644
--- a/src/cose.h
+++ b/src/cose.h
@@ -70,7 +70,7 @@
COSE_Algorithm_HMAC_256_256 = 4,
COSE_Algorithm_AES_CCM_16_64_128 = 10,
- COSE_Algoirthm_AES_CCM_16_64_256 = 11,
+ COSE_Algorithm_AES_CCM_16_64_256 = 11,
COSE_Algorithm_AES_CCM_64_64_128 = 30,
COSE_Algorithm_AES_CCM_64_64_256 = 31,
COSE_Algorithm_AES_CCM_16_128_128 = 12,
@@ -83,6 +83,7 @@
COSE_Algorithm_PS256 = -26,
COSE_Algorithm_PS384 = -27,
COSE_Algorithm_PS512 = -28,
+ COSE_Algorithm_ECDSA_SHA_256 = -7,
} COSE_Algorithms;
typedef enum {
@@ -95,9 +96,17 @@
COSE_Header_Recipients,
COSE_Header_Type,
COSE_Header_PlainText,
- COSE_Header_Tag
+ COSE_Header_Tag,
+ COSE_Header_Signers,
+ COSE_Header_Signature,
} COSE_Header;
+typedef enum {
+ COSE_Key_Type_EC2 = 2,
+ COSE_Key_Type = 1,
+ COSE_Key_ID = 2,
+ COSE_Parameter_KID = 4,
+} COSE_Constants;
void COSE_Encrypt_SetContent(HCOSE_ENCRYPT cose, const byte * rgbContent, size_t cbContent, cose_errback * errp);
void COSE_Encrypt_SetNonce(HCOSE_ENCRYPT cose, byte * rgbIV, size_t cbIV);
@@ -131,3 +140,7 @@
HCOSE_RECIPIENT COSE_Mac_GetRecipient(HCOSE_MAC cose, int iRecipient, cose_errback * perr);
+//
+//
+
+HCOSE_SIGNER COSE_Sign_add_signer(HCOSE_SIGN cose, const cn_cbor * pkey, int algId, cose_errback * perr);
diff --git a/src/cose_int.h b/src/cose_int.h
index 750c6a2..83babcd 100644
--- a/src/cose_int.h
+++ b/src/cose_int.h
@@ -27,6 +27,7 @@
COSE m_message;
byte * pbKey;
size_t cbKey;
+ const cn_cbor * m_pkey;
COSE_SignerInfo * m_signerNext;
} COSE_SignerInfo;
@@ -108,6 +109,9 @@
#define UNUSED_PARAM(p) ((void)&(p))
#endif
+extern const cn_cbor * _COSE_encode_protected(COSE * pMessage, cose_errback * perr);
+
+
extern bool IsValidEncryptHandle(HCOSE_ENCRYPT h);
extern bool IsValidRecipientHandle(HCOSE_RECIPIENT h);
@@ -133,6 +137,7 @@
// Signed items
extern HCOSE_SIGN _COSE_Sign_Init_From_Object(cn_cbor *, COSE_SignMessage * pIn, CBOR_CONTEXT_COMMA cose_errback * errp);
extern void _COSE_Sign_Release(COSE_SignMessage * p);
+extern bool _COSE_Signer_sign(COSE_SignMessage * pSigner, const cn_cbor * pcborBody, const cn_cbor * pcborProtected, cose_errback * perr);
// Mac-ed items
extern HCOSE_MAC _COSE_Mac_Init_From_Object(cn_cbor *, COSE_MacMessage * pIn, CBOR_CONTEXT_COMMA cose_errback * errp);
diff --git a/src/crypto.h b/src/crypto.h
index 1f382dc..014f261 100644
--- a/src/crypto.h
+++ b/src/crypto.h
@@ -37,6 +37,17 @@
bool HMAC_Create(COSE_Encrypt * pcose, int HSize, int TSize, const byte * pbAuthData, int cbAuthData, cose_errback * perr);
/**
+* Perform a signature operation
+*
+* @param[in] COSE_SignerInfo Pointer to COSE SignerInfo context object
+* @param[in] byte * Pointer to text to be signed
+* @param[in] size_t size of text to be signed
+* @param[in] cose_errback * Error return location
+* @return Did the function succeed?
+*/
+bool ECDSA_Sign(COSE_SignerInfo * pSigner, const byte * rgbToSign, size_t cbToSign, cose_errback * perr);
+
+/**
* Generate random bytes in a buffer
*
* @param[in] byte * Pointer to buffer to be filled
diff --git a/src/openssl.c b/src/openssl.c
index a43f285..99b53ae 100644
--- a/src/openssl.c
+++ b/src/openssl.c
@@ -9,6 +9,7 @@
#include <openssl/evp.h>
#include <openssl/hmac.h>
+#include <openssl/ecdsa.h>
#include <openssl/rand.h>
@@ -186,6 +187,119 @@
return true;
}
+#define COSE_Key_EC_Curve -1
+#define COSE_Key_EC_X -2
+#define COSE_Key_EC_Y -3
+#define COSE_Key_EC_d -4
+
+EC_KEY * ECKey_From(const cn_cbor * pKey, cose_errback * perr)
+{
+ EC_KEY * pNewKey = EC_KEY_new();
+ byte rgbKey[512+1];
+ const cn_cbor * p;
+ int nidGroup = -1;
+ EC_POINT * pPoint = NULL;
+
+ p = cn_cbor_mapget_int(pKey, COSE_Key_EC_Curve);
+ if (p == NULL) return NULL;
+ switch (p->v.sint) {
+ case 1: // P-256
+ nidGroup = NID_X9_62_prime256v1;
+ break;
+
+ case 2: // P-384
+ nidGroup = NID_secp384r1;
+ break;
+
+ case 3: // P-521
+ nidGroup = NID_secp521r1;
+ break;
+
+ default:
+ return NULL;
+ }
+
+ EC_GROUP * ecgroup = EC_GROUP_new_by_curve_name(nidGroup);
+ EC_KEY_set_group(pNewKey, ecgroup);
+
+ rgbKey[0] = POINT_CONVERSION_UNCOMPRESSED;
+ p = cn_cbor_mapget_int(pKey, COSE_Key_EC_X);
+ if (p == NULL) return NULL;
+ if (p->type != CN_CBOR_BYTES) return NULL;
+ memcpy(rgbKey+1, p->v.str, p->length);
+
+ p = cn_cbor_mapget_int(pKey, COSE_Key_EC_Y);
+ if (p == NULL) return NULL;
+ if (p->type != CN_CBOR_BYTES) return NULL;
+ memcpy(rgbKey + p->length+1, p->v.str, p->length);
+
+ pPoint = EC_POINT_new(ecgroup);
+ EC_POINT_oct2point(ecgroup, pPoint, rgbKey, p->length * 2 + 1, NULL);
+ EC_KEY_set_public_key(pNewKey, pPoint);
+
+ p = cn_cbor_mapget_int(pKey, COSE_Key_EC_d);
+ if (p != NULL) {
+ BIGNUM * pbn;
+
+ pbn = BN_bin2bn(p->v.str, p->length, NULL);
+ EC_KEY_set_private_key(pNewKey, pbn);
+ }
+
+ return pNewKey;
+}
+
+/*
+bool ECDSA_Sign(const cn_cbor * pKey)
+{
+ byte * digest = NULL;
+ int digestLen = 0;
+ ECDSA_SIG * sig;
+
+ EC_KEY * eckey = ECKey_From(pKey);
+
+ sig = ECDSA_do_sign(digest, digestLen, eckey);
+
+ return true;
+}
+*/
+
+bool ECDSA_Sign(COSE_SignerInfo * pSigner, const byte * rgbToSign, size_t cbToSign, cose_errback * perr)
+{
+ EC_KEY * eckey = NULL;
+ byte rgbDigest[EVP_MAX_MD_SIZE];
+ size_t cbDigest = sizeof(rgbDigest);
+ ECDSA_SIG * sig;
+ byte * pbSig = NULL;
+ size_t cbSig;
+#ifdef USE_CBOR_CONTEXT
+ cn_cbor_context * context = &pSigner->m_message.m_allocContext;
+#endif
+ cn_cbor * p = NULL;
+
+ eckey = ECKey_From(pSigner->m_pkey, perr);
+ if (eckey == NULL) {
+ errorReturn:
+ if (p != NULL) CN_CBOR_FREE(p, context);
+ if (eckey != NULL) EC_KEY_free(eckey);
+ return false;
+ }
+
+ EVP_Digest(rgbToSign, cbToSign, rgbDigest, &cbDigest, EVP_sha256(), NULL);
+
+ cbSig = ECDSA_size(eckey);
+ pbSig = COSE_CALLOC(cbSig, 1, context);
+ CHECK_CONDITION(pbSig != NULL, COSE_ERR_OUT_OF_MEMORY);
+
+ CHECK_CONDITION(ECDSA_sign(0, rgbDigest, cbDigest, pbSig, &cbSig, eckey), COSE_ERR_CRYPTO_FAIL);
+
+ p = cn_cbor_data_create(pbSig, cbSig, CBOR_CONTEXT_PARAM_COMMA NULL);
+ CHECK_CONDITION(p != NULL, COSE_ERR_OUT_OF_MEMORY);
+
+ CHECK_CONDITION(cn_cbor_mapput_int(pSigner->m_message.m_cbor, COSE_Header_Signature, p, CBOR_CONTEXT_PARAM_COMMA NULL), COSE_ERR_CBOR);
+
+ return true;
+}
+
void rand_bytes(byte * pb, size_t cb)
{
diff --git a/test/test.c b/test/test.c
index 793788a..8fe0354 100644
--- a/test/test.c
+++ b/test/test.c
@@ -61,7 +61,47 @@
int SignMessage()
{
HCOSE_SIGN hEncObj = COSE_Sign_Init(NULL, NULL);
+ char * sz = "This is the content to be used";
+ ssize_t cb;
+ byte * rgb;
+ byte rgbX[] = { 0x65, 0xed, 0xa5, 0xa1, 0x25, 0x77, 0xc2, 0xba, 0xe8, 0x29, 0x43, 0x7f, 0xe3, 0x38, 0x70, 0x1a, 0x10, 0xaa, 0xa3, 0x75, 0xe1, 0xbb, 0x5b, 0x5d, 0xe1, 0x08, 0xde, 0x43, 0x9c, 0x08, 0x55, 0x1d };
+ byte rgbY[] = { 0x1e, 0x52, 0xed, 0x75, 0x70, 0x11, 0x63, 0xf7, 0xf9, 0xe4, 0x0d, 0xdf, 0x9f, 0x34, 0x1b, 0x3d, 0xc9, 0xba, 0x86, 0x0a, 0xf7, 0xe0, 0xca, 0x7c, 0xa7, 0xe9, 0xee, 0xcd, 0x00, 0x84, 0xd1, 0x9c };
+ byte kid[] = { 0x6d, 0x65, 0x72, 0x69, 0x61, 0x64, 0x6f, 0x63, 0x2e, 0x62, 0x72, 0x61, 0x6e, 0x64, 0x79, 0x62, 0x75, 0x63, 0x6, 0xb4, 0x06, 0x27, 0x56, 0x36, 0xb6, 0xc6, 0x16, 0xe6, 0x42, 0xe6, 0x57, 0x86, 0x16, 0xd7, 0x06, 0xc65};
+ byte rgbD[] = {0xaf, 0xf9, 0x07, 0xc9, 0x9f, 0x9a, 0xd3, 0xaa, 0xe6, 0xc4, 0xcd, 0xf2, 0x11, 0x22, 0xbc, 0xe2, 0xbd, 0x68, 0xb5, 0x28, 0x3e, 0x69, 0x07, 0x15, 0x4a, 0xd9, 0x11, 0x84, 0x0f, 0xa2, 0x08, 0xcf};
+
+ cn_cbor * pkey = cn_cbor_map_create(NULL, NULL);
+ cn_cbor_mapput_int(pkey, COSE_Key_Type, cn_cbor_int_create(COSE_Key_Type_EC2, NULL, NULL), NULL, NULL);
+ cn_cbor_mapput_int(pkey, -1, cn_cbor_int_create(1, NULL, NULL), NULL, NULL);
+ cn_cbor_mapput_int(pkey, -2, cn_cbor_data_create(rgbX, sizeof(rgbX), NULL, NULL), NULL, NULL);
+ cn_cbor_mapput_int(pkey, -3, cn_cbor_data_create(rgbY, sizeof(rgbY), NULL, NULL), NULL, NULL);
+ cn_cbor_mapput_int(pkey, COSE_Key_ID, cn_cbor_data_create(kid, sizeof(kid), NULL, NULL), NULL, NULL);
+ cn_cbor_mapput_int(pkey, -4, cn_cbor_data_create(rgbD, sizeof(rgbD), NULL, NULL), NULL, NULL);
+
+ COSE_Sign_SetContent(hEncObj, sz, strlen(sz), NULL);
+ COSE_Sign_add_signer(hEncObj, pkey, COSE_Algorithm_ECDSA_SHA_256, NULL);
+
+ COSE_Sign_Sign(hEncObj, NULL);
+
+ cb = COSE_Encode((HCOSE)hEncObj, NULL, 0, 0) + 1;
+ rgb = (byte *)malloc(cb);
+ cb = COSE_Encode((HCOSE)hEncObj, rgb, 0, cb);
+
+
+ FILE * fp = fopen("test.mac.cbor", "wb");
+ fwrite(rgb, cb, 1, fp);
+ fclose(fp);
+
+ char * szX;
+ int cbPrint = 0;
+ cn_cbor * cbor = COSE_get_cbor((HCOSE)hEncObj);
+ cbPrint = cn_cbor_printer_write(NULL, 0, cbor, " ", "\r\n");
+ szX = malloc(cbPrint);
+ cn_cbor_printer_write(szX, cbPrint, cbor, " ", "\r\n");
+ fprintf(stdout, szX);
+ fprintf(stdout, "\r\n");
+
+ COSE_Sign_Free(hEncObj);
}