Continued
diff --git a/src/Cose.c b/src/Cose.c
index 9b671e1..369b7e1 100644
--- a/src/Cose.c
+++ b/src/Cose.c
@@ -27,13 +27,16 @@
error_setup:
_COSE_Release( pobj);
if (perror != NULL) perror->err = COSE_ERR_OUT_OF_MEMORY;
- return false;
+return false;
}
pobj->m_unprotectMap = cn_cbor_map_create(CBOR_CONTEXT_PARAM_COMMA &errState);
if (pobj->m_unprotectMap == NULL) goto error_setup;
pobj->m_ownUnprotectedMap = true;
+ pobj->m_dontSendMap = cn_cbor_map_create(CBOR_CONTEXT_PARAM_COMMA &errState);
+ if (pobj->m_dontSendMap == NULL) goto error_setup;
+
pobj->m_cbor = cn_cbor_map_create(CBOR_CONTEXT_PARAM_COMMA &errState);
if (pobj->m_cbor == NULL) goto error_setup;
pobj->m_ownMsg = true;
@@ -58,14 +61,14 @@
_COSE_Release(pobj);
return false;
}
- pobj->m_protectedMap = (cn_cbor *) cn_cbor_decode((const byte *) pmap->v.str, pmap->length, context, &errState);
+ pobj->m_protectedMap = (cn_cbor *)cn_cbor_decode((const byte *)pmap->v.str, pmap->length, context, &errState);
if (pobj->m_protectedMap == NULL) {
if (perror != NULL) perror->err = COSE_ERR_INVALID_PARAMETER; // M00BUG - get error state from errState
goto setup_error;
}
}
- pobj->m_unprotectMap = (cn_cbor *) cn_cbor_mapget_int(pcbor, COSE_Header_Unprotected);
+ pobj->m_unprotectMap = (cn_cbor *)cn_cbor_mapget_int(pcbor, COSE_Header_Unprotected);
pobj->m_ownUnprotectedMap = false;
pobj->m_cbor = pcbor;
@@ -80,9 +83,59 @@
if (pobj->m_protectedMap != NULL) CN_CBOR_FREE(pobj->m_protectedMap, context);
if (pobj->m_ownUnprotectedMap && (pobj->m_unprotectMap != NULL)) CN_CBOR_FREE(pobj->m_unprotectMap, context);
+ if (pobj->m_dontSendMap != NULL) CN_CBOR_FREE(pobj->m_dontSendMap, context);
if (pobj->m_ownMsg && (pobj->m_cbor != NULL)) CN_CBOR_FREE(pobj->m_cbor, context);
}
+
+HCOSE COSE_Decode(const byte * rgbData, int cbData, int * ptype, CBOR_CONTEXT_COMMA cose_errback * errp)
+{
+ cn_cbor * cbor;
+ const cn_cbor * pType = NULL;
+ HCOSE h;
+
+ if ((rgbData == NULL) || (ptype == NULL)) {
+ if (errp != NULL) errp->err = COSE_ERR_INVALID_PARAMETER;
+ return NULL;
+ }
+
+ cbor = (cn_cbor *)cn_cbor_decode(rgbData, cbData, CBOR_CONTEXT_PARAM_COMMA NULL);
+ if (cbor == NULL) {
+ if (errp != NULL) errp->err = COSE_ERR_CBOR;
+ return NULL;
+ }
+
+ if (cbor->type != CN_CBOR_MAP) {
+ error:
+ COSE_FREE(cbor, context);
+ if (errp != NULL) errp->err = COSE_ERR_INVALID_PARAMETER;
+ return NULL;
+ }
+
+ pType = cn_cbor_mapget_int(cbor, COSE_Header_Type);
+ if ((pType == NULL) || (pType->type != CN_CBOR_UINT)) goto error;
+
+ switch (pType->v.sint) {
+ case 1:
+ h = (HCOSE)_COSE_Encrypt_Init_From_Object(cbor, NULL, CBOR_CONTEXT_PARAM_COMMA errp);
+ if (h == NULL) {
+ COSE_FREE(cbor, context);
+ return NULL;
+ }
+ return h;
+
+ case 2:
+ h = (HCOSE)_COSE_Sign_Init_From_Object(cbor, NULL, CBOR_CONTEXT_PARAM_COMMA errp);
+ if (h == NULL) {
+ COSE_FREE(cbor, context);
+ return NULL;
+ }
+ return h;
+ }
+
+ goto error;
+}
+
cn_cbor * COSE_get_cbor(HCOSE h)
{
COSE * msg = (COSE *)h;
@@ -104,8 +157,12 @@
if ((pcose->m_unprotectMap != NULL) && ((flags & COSE_UNPROTECT_ONLY) != 0)) {
p = cn_cbor_mapget_int(pcose->m_unprotectMap, key);
+ if (p != NULL) return p;
}
+ if ((pcose->m_dontSendMap != NULL) && ((flags & COSE_DONT_SEND) != 0)) {
+ p = cn_cbor_mapget_int(pcose->m_dontSendMap, key);
+ }
return p;
}
@@ -124,29 +181,50 @@
p = cn_cbor_mapget_string(pcose->m_unprotectMap, key);
}
+ if ((pcose->m_dontSendMap != NULL) && ((flags & COSE_DONT_SEND) != 0)) {
+ p = cn_cbor_mapget_string(pcose->m_dontSendMap, key);
+ }
+
return p;
}
-bool _COSE_map_put(COSE * pCose, int key, cn_cbor * value, int flags, cose_errback * perror)
+bool _COSE_map_put(COSE * pCose, int key, cn_cbor * value, int flags, cose_errback * perr)
{
cn_cbor_context * context = &pCose->m_allocContext;
cn_cbor_errback error;
bool f;
if ((flags & COSE_BOTH) == COSE_BOTH) {
- if (perror != NULL) perror->err = COSE_ERR_INVALID_PARAMETER;
+ if (perr != NULL) perr->err = COSE_ERR_INVALID_PARAMETER;
+ errorReturn:
return false;
}
- if (perror != NULL) perror->err = COSE_ERR_NONE;
- if (flags & COSE_PROTECT_ONLY) {
+ if (perr != NULL) perr->err = COSE_ERR_NONE;
+
+ switch (flags) {
+ case COSE_PROTECT_ONLY:
f = cn_cbor_mapput_int(pCose->m_protectedMap, key, value, CBOR_CONTEXT_PARAM_COMMA &error);
- }
- else {
+ break;
+
+ case COSE_UNPROTECT_ONLY:
f = cn_cbor_mapput_int(pCose->m_unprotectMap, key, value, CBOR_CONTEXT_PARAM_COMMA &error);
+ break;
+
+ case COSE_DONT_SEND:
+ if (pCose->m_dontSendMap == NULL) {
+ pCose->m_dontSendMap = cn_cbor_map_create(CBOR_CONTEXT_PARAM_COMMA &error);
+ CHECK_CONDITION(pCose->m_dontSendMap != NULL, COSE_ERR_OUT_OF_MEMORY);
+ }
+ f = cn_cbor_mapput_int(pCose->m_dontSendMap, key, value, CBOR_CONTEXT_PARAM_COMMA &error);
+ break;
+
+ default:
+ CHECK_CONDITION(false, COSE_ERR_INVALID_PARAMETER);
+ break;
}
- if (!f && perror != NULL) {
- perror->err = error.err; // M00BUG
- }
+
+ CHECK_CONDITION(f, error.err);
+
return f;
}
diff --git a/src/MacMessage.c b/src/MacMessage.c
new file mode 100644
index 0000000..31c6bd3
--- /dev/null
+++ b/src/MacMessage.c
@@ -0,0 +1,381 @@
+#include <stdlib.h>
+#include <memory.h>
+#include <stdio.h>
+#include <assert.h>
+
+#include "cose.h"
+#include "cose_int.h"
+#include "configure.h"
+#include "crypto.h"
+
+byte RgbDontUse2[8 * 1024]; // Remove this array when we can compute the size of a cbor serialization without this hack.
+
+
+bool IsValidMacHandle(HCOSE_MAC h)
+{
+ COSE_MacMessage * p = (COSE_MacMessage *)h;
+ if (p == NULL) return false;
+ return true;
+}
+
+
+HCOSE_MAC COSE_Mac_Init(CBOR_CONTEXT_COMMA cose_errback * perror)
+{
+ COSE_MacMessage * pobj = (COSE_MacMessage *)COSE_CALLOC(1, sizeof(COSE_MacMessage), context);
+ if (pobj == NULL) {
+ if (perror != NULL) perror->err = COSE_ERR_OUT_OF_MEMORY;
+ return NULL;
+ }
+
+ if (!_COSE_Init(&pobj->m_message, CBOR_CONTEXT_PARAM_COMMA perror)) {
+ error_setup:
+ COSE_Mac_Free((HCOSE_MAC)pobj);
+ return NULL;
+ }
+
+ if (!cn_cbor_mapput_int(pobj->m_message.m_cbor, COSE_Header_Type, cn_cbor_int_create(2, CBOR_CONTEXT_PARAM_COMMA NULL), CBOR_CONTEXT_PARAM_COMMA NULL)) {
+ if (perror != NULL) perror->err = COSE_ERR_OUT_OF_MEMORY;
+ goto error_setup;
+ }
+
+ return (HCOSE_MAC)pobj;
+}
+
+HCOSE_MAC _COSE_Mac_Init_From_Object(cn_cbor * cbor, COSE_MacMessage * pIn, CBOR_CONTEXT_COMMA cose_errback * perr)
+{
+ COSE_MacMessage * pobj = pIn;
+ cn_cbor * pRecipients = NULL;
+ // cn_cbor * tmp;
+ cose_errback error = { COSE_ERR_NONE };
+ if (perr == NULL) perr = &error;
+
+ if (pobj == NULL) pobj = (COSE_MacMessage *)COSE_CALLOC(1, sizeof(COSE_MacMessage), context);
+ if (pobj == NULL) {
+ perr->err = COSE_ERR_OUT_OF_MEMORY;
+ errorReturn:
+ if ((pIn == NULL) && (pobj != NULL)) COSE_FREE(pobj, context);
+ return NULL;
+ }
+
+ if (!_COSE_Init_From_Object(&pobj->m_message, cbor, CBOR_CONTEXT_PARAM_COMMA perr)) {
+ goto errorReturn;
+ }
+
+ pRecipients = (cn_cbor *)cn_cbor_mapget_int(cbor, COSE_Header_Recipients);
+ if (pRecipients != NULL) {
+ CHECK_CONDITION(pRecipients->type == CN_CBOR_ARRAY, COSE_ERR_INVALID_PARAMETER);
+
+ pRecipients = pRecipients->first_child;
+ while (pRecipients != NULL) {
+ COSE_RecipientInfo * pInfo = _COSE_Recipient_Init_From_Object(pRecipients, CBOR_CONTEXT_PARAM_COMMA perr);
+ CHECK_CONDITION(pInfo != NULL, COSE_ERR_OUT_OF_MEMORY);
+
+ pInfo->m_recipientNext = pobj->m_recipientFirst;
+ pobj->m_recipientFirst = pInfo;
+ pRecipients = pRecipients->next;
+ }
+ }
+
+ return(HCOSE_MAC)pobj;
+}
+
+bool COSE_Mac_Free(HCOSE_MAC h)
+{
+#ifdef USE_CBOR_CONTEXT
+ cn_cbor_context context;
+#endif
+
+ if (!IsValidMacHandle(h)) return false;
+
+#ifdef USE_CBOR_CONTEXT
+ context = ((COSE_MacMessage *)h)->m_message.m_allocContext;
+#endif
+
+ _COSE_Mac_Release((COSE_MacMessage *)h);
+
+ COSE_FREE((COSE_MacMessage *)h, &context);
+
+ return true;
+}
+
+void _COSE_Mac_Release(COSE_MacMessage * p)
+{
+ // if (p->pbContent != NULL) COSE_FREE(p->pbContent, &p->m_message.m_allocContext);
+ // if (p->pbIV != NULL) COSE_FREE(p->pbIV, &p->m_message.m_allocContext);
+ if (p->pbKey != NULL) COSE_FREE(p->pbKey, &p->m_message.m_allocContext);
+
+ _COSE_Release(&p->m_message);
+}
+
+
+
+HCOSE_RECIPIENT COSE_Mac_add_shared_secret(HCOSE_MAC hcose, COSE_Algorithms alg, byte * rgbKey, int cbKey, byte * rgbKid, int cbKid, cose_errback * perror)
+{
+#ifdef USE_CBOR_CONTEXT
+ cn_cbor_context * context;
+#endif // USE_CBOR_CONTEXT
+ COSE_RecipientInfo * pobj;
+ COSE_MacMessage * pcose = (COSE_MacMessage *)hcose;
+
+ if (!IsValidMacHandle(hcose) || (rgbKey == NULL)) {
+ if (perror != NULL) perror->err = COSE_ERR_INVALID_PARAMETER;
+ return NULL;
+ }
+
+ switch (alg) {
+ case COSE_Algorithm_Direct:
+ break;
+
+ default:
+ if (perror != NULL) perror->err = COSE_ERR_INVALID_PARAMETER;
+ return NULL;
+ }
+
+
+#ifdef USE_CBOR_CONTEXT
+ context = &pcose->m_message.m_allocContext;
+#endif // USE_CBOR_CONTEXT
+
+ pobj = (COSE_RecipientInfo *)COSE_CALLOC(1, sizeof(COSE_RecipientInfo), context);
+ if (pobj == NULL) {
+ oom_error:
+ if (perror != NULL) perror->err = COSE_ERR_OUT_OF_MEMORY;
+ error:
+ // M00BUG COSE_Recipient_Free(pobj);
+ return NULL;
+ }
+
+ if (!_COSE_Init(&pobj->m_encrypt.m_message, CBOR_CONTEXT_PARAM_COMMA perror)) {
+ goto error;
+ }
+
+ if (!cn_cbor_mapput_int(pobj->m_encrypt.m_message.m_unprotectMap, COSE_Header_Algorithm, cn_cbor_int_create(alg, CBOR_CONTEXT_PARAM_COMMA NULL), CBOR_CONTEXT_PARAM_COMMA NULL)) goto error;
+
+ if (cbKid > 0) {
+ byte * pb = (byte *)COSE_CALLOC(cbKid, 1, context);
+ if (pb == NULL) goto oom_error;
+ memcpy(pb, rgbKid, cbKid);
+ if (!cn_cbor_mapput_int(pobj->m_encrypt.m_message.m_unprotectMap, COSE_Header_KID, cn_cbor_data_create(pb, cbKid, CBOR_CONTEXT_PARAM_COMMA NULL), CBOR_CONTEXT_PARAM_COMMA NULL)) {
+ COSE_FREE(pb, context);
+ goto oom_error; // M00BUG - get error from CBOR
+ }
+ }
+
+
+ pobj->m_encrypt.pbKey = (byte *)COSE_CALLOC(cbKey, 1, context);
+ if (pobj->m_encrypt.pbKey == NULL) goto error;
+ memcpy(pobj->m_encrypt.pbKey, rgbKey, cbKey);
+ pobj->m_encrypt.cbKey = cbKey;
+
+ pobj->m_recipientNext = pcose->m_recipientFirst;
+ pcose->m_recipientFirst = pobj;
+
+ cn_cbor * pRecipients = (cn_cbor *)cn_cbor_mapget_int(pcose->m_message.m_cbor, COSE_Header_Recipients);
+ if (pRecipients == NULL) {
+ pRecipients = cn_cbor_array_create(CBOR_CONTEXT_PARAM_COMMA NULL);
+ if (pRecipients == NULL) goto error;
+ if (!cn_cbor_mapput_int(pcose->m_message.m_cbor, COSE_Header_Recipients, pRecipients, CBOR_CONTEXT_PARAM_COMMA NULL)) {
+ cn_cbor_free(pRecipients, context);
+ goto error;
+ }
+ }
+
+ cn_cbor_array_append(pRecipients, pobj->m_encrypt.m_message.m_cbor, NULL);
+
+ pobj->m_encrypt.m_message.m_flags |= 1;
+ return (HCOSE_RECIPIENT)pobj;
+}
+
+void COSE_Mac_SetContent(HCOSE_MAC cose, const byte * rgbContent, size_t cbContent, cose_errback * errp)
+{
+ COSE_MacMessage * p = (COSE_MacMessage *)cose;
+ cn_cbor_context * context = &p->m_message.m_allocContext;
+
+ if (!IsValidMacHandle(cose)) {
+ if (errp != NULL) errp->err = COSE_ERR_INVALID_PARAMETER;
+ return;
+ }
+
+ p->pbContent = rgbContent;
+ p->cbContent = cbContent;
+
+ if (!cn_cbor_mapput_int(p->m_message.m_cbor, COSE_Header_PlainText, cn_cbor_data_create (rgbContent, cbContent, CBOR_CONTEXT_PARAM_COMMA NULL), CBOR_CONTEXT_PARAM_COMMA NULL)) {
+ if (errp != NULL) errp->err = COSE_ERR_CBOR;
+ return;
+ }
+}
+
+
+const cn_cbor * COSE_Mac_map_get_int(HCOSE_MAC h, int key, int flags, cose_errback * perror)
+{
+ if (!IsValidMacHandle(h)) {
+ if (perror != NULL) perror->err = COSE_ERR_INVALID_PARAMETER;
+ return NULL;
+ }
+
+ return _COSE_map_get_int(&((COSE_MacMessage *)h)->m_message, key, flags, perror);
+}
+
+
+bool COSE_Mac_map_put(HCOSE_MAC h, int key, cn_cbor * value, int flags, cose_errback * perror)
+{
+ if (!IsValidMacHandle(h) || (value == NULL)) {
+ if (perror != NULL) perror->err = COSE_ERR_INVALID_PARAMETER;
+ return false;
+ }
+
+ return _COSE_map_put(&((COSE_MacMessage *)h)->m_message, key, value, flags, perror);
+}
+
+
+bool COSE_Mac_encrypt(HCOSE_MAC h, cose_errback * perror)
+{
+ int alg;
+ int t;
+ COSE_RecipientInfo * pri;
+ const cn_cbor * cn_Alg = NULL;
+ byte * pbAuthData = NULL;
+ cn_cbor * pAuthData = NULL;
+ cn_cbor * ptmp = NULL;
+ byte * pbProtected = NULL;
+ ssize_t cbProtected = 0;
+ size_t cbitKey;
+ cn_cbor_context * context;
+ COSE_Encrypt * pcose = (COSE_Encrypt *)h;
+ cose_errback error;
+
+ if (!IsValidMacHandle(h)) {
+ if (perror != NULL) perror->err = COSE_ERR_INVALID_PARAMETER;
+ return false;
+ }
+#ifdef USE_CBOR_CONTEXT
+ context = &pcose->m_message.m_allocContext;
+#endif // USE_CBOR_CONTEXT
+
+ cn_Alg = _COSE_map_get_int(&pcose->m_message, COSE_Header_Algorithm, COSE_BOTH, &error);
+
+ if (cn_Alg == NULL) {
+ error:
+ if (pbProtected != NULL) COSE_FREE(pbProtected, context);
+ if (pbAuthData != NULL) COSE_FREE(pbAuthData, context);
+ if (pAuthData != NULL) cn_cbor_free(pAuthData CBOR_CONTEXT_PARAM);
+ if (ptmp != NULL) cn_cbor_free(ptmp CBOR_CONTEXT_PARAM);
+ if (perror != NULL) *perror = error;
+ return false;
+ }
+ if (cn_Alg->type != CN_CBOR_UINT) goto error;
+ alg = cn_Alg->v.uint;
+
+ // Get the key size
+
+ switch (alg) {
+ case COSE_Algorithm_HMAC_256_256:
+ cbitKey = 256;
+ break;
+
+ default:
+ goto error;
+ }
+
+ // If we are doing direct encryption - then recipient generates the key
+
+ if (pcose->pbKey == NULL) {
+ t = 0;
+ for (pri = pcose->m_recipientFirst; pri != NULL; pri = pri->m_recipientNext) {
+ if (pri->m_encrypt.m_message.m_flags & 1) {
+ t |= 1;
+ pcose->pbKey = _COSE_RecipientInfo_generateKey(pri, cbitKey);
+ if (pcose->pbKey == NULL) goto error;
+ pcose->cbKey = cbitKey / 8;
+ }
+ else {
+ t |= 2;
+ }
+ }
+ if (t == 3) {
+ error.err = CN_CBOR_ERR_INVALID_PARAMETER;
+ goto error;
+ }
+ }
+
+ if (pcose->pbKey == NULL) {
+ pcose->pbKey = (byte *)COSE_CALLOC(cbitKey / 8, 1, context);
+ if (pcose->pbKey == NULL) goto error;
+ pcose->cbKey = cbitKey / 8;
+ rand_bytes(pcose->pbKey, pcose->cbKey);
+ }
+
+ // Build protected headers
+
+ if (pcose->m_message.m_protectedMap->first_child != NULL) {
+ cbProtected = cn_cbor_encoder_write(RgbDontUse2, 0, sizeof(RgbDontUse2), pcose->m_message.m_protectedMap);
+ pbProtected = (byte *)COSE_CALLOC(cbProtected, 1, context);
+ if (pbProtected == NULL) goto error;
+ if (cn_cbor_encoder_write(pbProtected, 0, cbProtected, pcose->m_message.m_protectedMap) != cbProtected) goto error;
+ if (!cn_cbor_mapput_int(pcose->m_message.m_cbor, COSE_Header_Protected, cn_cbor_data_create(pbProtected, cbProtected, CBOR_CONTEXT_PARAM_COMMA NULL), CBOR_CONTEXT_PARAM_COMMA NULL)) goto error;
+ }
+ else {
+ pbProtected = NULL;
+ cbProtected = 0;
+ }
+
+ // Add Unprotected headers
+ if (pcose->m_message.m_unprotectMap->first_child != NULL) {
+ if (!cn_cbor_mapput_int(pcose->m_message.m_cbor, COSE_Header_Unprotected, pcose->m_message.m_unprotectMap, CBOR_CONTEXT_PARAM_COMMA NULL)) goto error;
+ pcose->m_message.m_ownUnprotectedMap = false;
+ }
+
+ // Build authenticated data
+ // Protected headers
+ // external data
+ // body
+
+ ssize_t cbAuthData = 0;
+ pbAuthData = NULL;
+ pAuthData = cn_cbor_array_create(CBOR_CONTEXT_PARAM_COMMA NULL);
+
+ ptmp = cn_cbor_data_create(pbProtected, cbProtected, CBOR_CONTEXT_PARAM_COMMA NULL);
+ if (ptmp == NULL) goto error;
+ cn_cbor_array_append(pAuthData, ptmp, NULL);
+ pbProtected = NULL;
+ ptmp = NULL;
+
+ ptmp = cn_cbor_data_create(NULL, 0, CBOR_CONTEXT_PARAM_COMMA NULL);
+ if (ptmp == NULL) goto error;
+ cn_cbor_array_append(pAuthData, ptmp, NULL);
+ ptmp = NULL;
+
+ ptmp = cn_cbor_data_create(pcose->pbContent, pcose->cbContent, CBOR_CONTEXT_PARAM_COMMA NULL);
+ if (ptmp == NULL) goto error;
+ cn_cbor_array_append(pAuthData, ptmp, NULL);
+ ptmp = NULL;
+
+ cbAuthData = cn_cbor_encoder_write(RgbDontUse2, 0, sizeof(RgbDontUse2), pAuthData);
+ pbAuthData = (byte *)COSE_CALLOC(cbAuthData, 1, context);
+ if (pbAuthData == NULL) goto error;
+ if (cn_cbor_encoder_write(pbAuthData, 0, cbAuthData, pAuthData) != cbAuthData) goto error;
+
+ switch (alg) {
+ case COSE_Algorithm_HMAC_256_256:
+ if (!HMAC_Create(pcose, 256, 256, pbAuthData, cbAuthData, perror)) goto error;
+ break;
+
+ default:
+ return false;
+ }
+
+ for (pri = pcose->m_recipientFirst; pri != NULL; pri = pri->m_recipientNext) {
+ _COSE_Encrypt_SetContent(&pri->m_encrypt, pcose->pbKey, pcose->cbKey, &error);
+ if (error.err != COSE_ERR_NONE) goto error;
+
+ if (!COSE_Encrypt_encrypt((HCOSE_ENCRYPT)&pri->m_encrypt, &error)) goto error;
+ }
+
+ // Figure out the clean up
+
+ if (pbAuthData != NULL) COSE_FREE(pbAuthData, context);
+ if (pAuthData != NULL) cn_cbor_free(pAuthData CBOR_CONTEXT_PARAM);
+
+ return true;
+}
+
diff --git a/src/cose.h b/src/cose.h
index 10811c1..28b0560 100644
--- a/src/cose.h
+++ b/src/cose.h
@@ -6,9 +6,10 @@
typedef struct _cose * HCOSE;
typedef struct _cose_sign * HCOSE_SIGN;
+typedef struct _cose_signer * HCOSE_SIGNER;
typedef struct _cose_encrypt * HCOSE_ENCRYPT;
typedef struct _cose_recipient * HCOSE_RECIPIENT;
-
+typedef struct _cose_mac * HCOSE_MAC;
/**
* All of the different kinds of errors
@@ -27,13 +28,15 @@
/** No usable recipient found */
COSE_ERR_NO_RECIPIENT_FOUND,
/** Decryption operation failed */
- COSE_ERR_DECRYPT_FAILED
+ COSE_ERR_DECRYPT_FAILED,
+ /** Cryptographic failure */
+ COSE_ERR_CRYPTO_FAIL
} cose_error;
/**
* Errors
*/
-typedef struct cose_errback {
+typedef struct _cose_errback {
/** The error, or CN_CBOR_NO_ERROR if none */
cose_error err;
} cose_errback;
@@ -47,23 +50,39 @@
// Functions for the signing object
-HCOSE_SIGN * COSE_Sign_Init(CBOR_CONTEXT_COMMA cose_errback * perr);
-// COSE_SignMessage * COSE_Sign_Init(const cn_cbor * COMMA_CBOR_CONTEXT);
-
+HCOSE_SIGN COSE_Sign_Init(CBOR_CONTEXT_COMMA cose_errback * perr);
+bool COSE_Sign_Free(HCOSE_SIGN cose);
HCOSE_ENCRYPT COSE_Encrypt_Init(CBOR_CONTEXT_COMMA cose_errback * perr);
bool COSE_Encrypt_Free(HCOSE_ENCRYPT cose);
+HCOSE_MAC COSE_Mac_Init(CBOR_CONTEXT_COMMA cose_errback * perr);
+bool COSE_Mac_Free(HCOSE_MAC cose);
+
typedef enum {
COSE_PROTECT_ONLY = 1,
COSE_UNPROTECT_ONLY = 2,
- COSE_BOTH = 3
+ COSE_DONT_SEND = 4,
+ COSE_BOTH = 7
} cose_protect_state;
typedef enum {
- COSE_Algorithm_AES_CCM_64 = 1,
- COSE_Algorithm_Direct,
- COSE_Algorithm_ECDH_ES_Direct
+ 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_64_64_128 = 30,
+ COSE_Algorithm_AES_CCM_64_64_256 = 31,
+ COSE_Algorithm_AES_CCM_16_128_128 = 12,
+ COSE_Algorithm_AES_CCM_16_128_256 = 13,
+ COSE_Algorithm_AES_CCM_64_128_128 = 32,
+ COSE_Algorithm_AES_CCM_64_128_256 = 33,
+
+ COSE_Algorithm_Direct = -6,
+ COSE_Algorithm_ECDH_ES_Direct,
+ COSE_Algorithm_PS256 = -26,
+ COSE_Algorithm_PS384 = -27,
+ COSE_Algorithm_PS512 = -28,
} COSE_Algorithms;
typedef enum {
@@ -74,7 +93,9 @@
COSE_Header_IV,
COSE_Header_Ciphertext,
COSE_Header_Recipients,
- COSE_Header_Type
+ COSE_Header_Type,
+ COSE_Header_PlainText,
+ COSE_Header_Tag
} COSE_Header;
@@ -93,3 +114,20 @@
HCOSE_RECIPIENT COSE_Encrypt_GetRecipient(HCOSE_ENCRYPT cose, int iRecipient, cose_errback * perr);
bool COSE_Recipient_SetKey(HCOSE_RECIPIENT h, const byte * rgb, int cb, cose_errback * perr);
+
+//
+//
+
+void COSE_Mac_SetContent(HCOSE_MAC cose, const byte * rgbContent, size_t cbContent, cose_errback * errp);
+
+const cn_cbor * COSE_Mac_map_get_int(HCOSE_MAC h, int key, int flags, cose_errback * perror);
+bool COSE_Mac_map_put(HCOSE_MAC cose, int key, cn_cbor * value, int flags, cose_errback * errp);
+
+bool COSE_Mac_encrypt(HCOSE_MAC cose, cose_errback * perror);
+
+void COSE_Encrypt_SetContent(HCOSE_ENCRYPT cose, const byte * rgbContent, size_t cbContent, cose_errback * errp);
+
+HCOSE_RECIPIENT COSE_Mac_add_shared_secret(HCOSE_MAC cose, COSE_Algorithms algId, byte * rgbKey, int cbKey, byte * rgbKid, int cbKid, cose_errback * perr);
+
+HCOSE_RECIPIENT COSE_Mac_GetRecipient(HCOSE_MAC cose, int iRecipient, cose_errback * perr);
+
diff --git a/src/cose_int.h b/src/cose_int.h
index 69afe6a..750c6a2 100644
--- a/src/cose_int.h
+++ b/src/cose_int.h
@@ -9,15 +9,26 @@
cn_cbor * m_cbor;
cn_cbor * m_protectedMap;
cn_cbor * m_unprotectMap;
+ cn_cbor * m_dontSendMap;
#ifdef USE_CBOR_CONTEXT
cn_cbor_context m_allocContext;
#endif
} COSE;
+struct _SignerInfo;
+typedef struct _SignerInfo COSE_SignerInfo;
+
typedef struct {
COSE m_message; // The message object
+ COSE_SignerInfo * m_signerFirst;
} COSE_SignMessage;
+typedef struct _SignerInfo {
+ COSE m_message;
+ byte * pbKey;
+ size_t cbKey;
+ COSE_SignerInfo * m_signerNext;
+} COSE_SignerInfo;
struct _RecipientInfo;
typedef struct _RecipientInfo COSE_RecipientInfo;
@@ -29,8 +40,6 @@
size_t cbContent;
byte * pbKey;
size_t cbKey;
-// byte * pbIV;
-// size_t cbIV;
} COSE_Encrypt;
typedef struct _RecipientInfo {
@@ -38,6 +47,14 @@
COSE_RecipientInfo * m_recipientNext;
} COSE_RecipientInfo;
+typedef struct {
+ COSE m_message; // The message object
+ COSE_RecipientInfo * m_recipientFirst;
+ byte * pbContent;
+ size_t cbContent;
+ byte * pbKey;
+ size_t cbKey;
+} COSE_MacMessage;
#ifdef USE_CBOR_CONTEXT
/**
@@ -104,10 +121,22 @@
extern HCOSE_ENCRYPT _COSE_Encrypt_Init_From_Object(cn_cbor *, COSE_Encrypt * pIn, CBOR_CONTEXT_COMMA cose_errback * errp);
extern void _COSE_Encrypt_Release(COSE_Encrypt * p);
-extern bool _COSE_Encrypt_decrypt(COSE_Encrypt * pbody, COSE_RecipientInfo * pRecip, cose_errback * perr);
+extern bool _COSE_Encrypt_decrypt(COSE_Encrypt * pcose, COSE_RecipientInfo * pRecip, int cbitKey, byte *pbKeyIn, cose_errback * perr);
extern void _COSE_Encrypt_SetContent(COSE_Encrypt * cose, const byte * rgbContent, size_t cbContent, cose_errback * errp);
extern COSE_RecipientInfo * _COSE_Recipient_Init_From_Object(cn_cbor *, CBOR_CONTEXT_COMMA cose_errback * errp);
extern void _COSE_Recipient_Free(COSE_RecipientInfo *);
extern bool _COSE_Recipient_decrypt(COSE_RecipientInfo * pRecip, int cbitKey, byte * pbKey, cose_errback * errp);
extern byte * _COSE_RecipientInfo_generateKey(COSE_RecipientInfo * pRecipient, size_t cbitKeySize);
+
+
+// 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);
+
+// Mac-ed items
+extern HCOSE_MAC _COSE_Mac_Init_From_Object(cn_cbor *, COSE_MacMessage * pIn, CBOR_CONTEXT_COMMA cose_errback * errp);
+extern void _COSE_Mac_Release(COSE_MacMessage * p);
+
+
+#define CHECK_CONDITION(condition, error) { if (!(condition)) { perr->err = error; goto errorReturn;}}
diff --git a/src/crypto.h b/src/crypto.h
index 3a74fb8..1f382dc 100644
--- a/src/crypto.h
+++ b/src/crypto.h
@@ -8,7 +8,7 @@
* @param[in] int Size of authenticated data structure
* @return Did the function succeed?
*/
-bool AES_CCM_Decrypt(COSE_Encrypt * pcose, int TSize, int LSize, const byte * pbAuthData, int cbAuthData);
+bool AES_CCM_Decrypt(COSE_Encrypt * pcose, int TSize, int LSize, const byte * pbKey, int cbKey, const byte * pbAuthData, int cbAuthData, cose_errback * perr);
/**
* Perform an AES-CCM Encryption operation
@@ -20,7 +20,21 @@
* @param[in] int Size of authenticated data structure
* @return Did the function succeed?
*/
-bool AES_CCM_Encrypt(COSE_Encrypt * pcose, int TSize, int LSize, const byte * pbAuthData, int cbAuthData);
+bool AES_CCM_Encrypt(COSE_Encrypt * pcose, int TSize, int LSize, const byte * pbAuthData, int cbAuthData, cose_errback * perr);
+
+
+/**
+* Perform an HMAC Creation operation
+*
+* @param[in] COSE_Encrypt Pointer to COSE Encryption context object
+* @param[in] int Hash function to be used
+* @param[in] int Size of Tag value to be created
+* @param[in] byte * Pointer to authenticated data structure
+* @param[in] int Size of authenticated data structure
+* @param[in] cose_errback * Error return location
+* @return Did the function succeed?
+*/
+bool HMAC_Create(COSE_Encrypt * pcose, int HSize, int TSize, const byte * pbAuthData, int cbAuthData, cose_errback * perr);
/**
* Generate random bytes in a buffer