Add the create function to the test pass
diff --git a/dumper/dumper.c b/dumper/dumper.c
index 13a26c2..3770939 100644
--- a/dumper/dumper.c
+++ b/dumper/dumper.c
@@ -343,7 +343,7 @@
group = 0;
for (i = 0; i < cbor->length; i+=2, cbor2 = cbor2->next->next) {
if ((cbor2->type == CN_CBOR_UINT) && (cbor2->v.uint == 1)) {
- group = cbor2->next->v.uint;
+ group = (int) cbor2->next->v.uint;
break;
}
}
diff --git a/src/MacMessage.c b/src/MacMessage.c
index 83e6a0e..7683c1d 100644
--- a/src/MacMessage.c
+++ b/src/MacMessage.c
@@ -564,6 +564,24 @@
return false;
}
+bool COSE_Mac_AddRecipient(HCOSE_MAC hMac, HCOSE_RECIPIENT hRecip, cose_errback * perr)
+{
+ COSE_RecipientInfo * pRecip;
+ COSE_MacMessage * pMac;
+
+ CHECK_CONDITION(IsValidMacHandle(hMac), COSE_ERR_INVALID_PARAMETER);
+ CHECK_CONDITION(IsValidRecipientHandle(hRecip), COSE_ERR_INVALID_PARAMETER);
+
+ pMac = (COSE_MacMessage *)hMac;
+ pRecip = (COSE_RecipientInfo *)hRecip;
+
+ pRecip->m_recipientNext = pMac->m_recipientFirst;
+ pMac->m_recipientFirst = pRecip;
+ return true;
+
+errorReturn:
+ return false;
+}
HCOSE_RECIPIENT COSE_Mac_GetRecipient(HCOSE_MAC cose, int iRecipient, cose_errback * perr)
diff --git a/src/Recipient.c b/src/Recipient.c
index 41a965c..2d3d4db 100644
--- a/src/Recipient.c
+++ b/src/Recipient.c
@@ -12,6 +12,34 @@
return true;
}
+HCOSE_RECIPIENT COSE_Recipient_Init(CBOR_CONTEXT_COMMA cose_errback * perror)
+{
+ COSE_RecipientInfo * pobj = (COSE_RecipientInfo *)COSE_CALLOC(1, sizeof(COSE_RecipientInfo), context);
+ if (pobj == NULL) {
+ if (perror != NULL) perror->err = COSE_ERR_OUT_OF_MEMORY;
+ return NULL;
+ }
+
+ if (!_COSE_Init(&pobj->m_encrypt.m_message, COSE_recipient_object, CBOR_CONTEXT_PARAM_COMMA perror)) {
+ COSE_Recipient_Free((HCOSE_RECIPIENT)pobj);
+ return NULL;
+ }
+
+ return (HCOSE_RECIPIENT)pobj;
+}
+
+bool COSE_Recipient_Free(HCOSE_RECIPIENT hRecipient)
+{
+ if (IsValidRecipientHandle(hRecipient)) {
+
+ _COSE_Recipient_Free((COSE_RecipientInfo *)hRecipient);
+ return true;
+ }
+
+ return false;
+}
+
+
HCOSE_RECIPIENT COSE_Encrypt_GetRecipient(HCOSE_ENCRYPT cose, int iRecipient, cose_errback * perr)
{
int i;
@@ -161,17 +189,28 @@
int alg;
const cn_cbor * cn_Alg = _COSE_map_get_int(&pRecipient->m_encrypt.m_message, COSE_Header_Algorithm, COSE_BOTH, perr);
- if (cn_Alg == NULL) return false;
- if ((cn_Alg->type != CN_CBOR_UINT) && (cn_Alg->type != CN_CBOR_INT)) return false;
+ CHECK_CONDITION(cn_Alg != NULL, COSE_ERR_INVALID_PARAMETER);
+ CHECK_CONDITION((cn_Alg->type == CN_CBOR_UINT) || (cn_Alg->type == CN_CBOR_INT), COSE_ERR_INVALID_PARAMETER);
alg = (int)cn_Alg->v.uint;
switch (alg) {
case COSE_Algorithm_Direct:
{
- if (pRecipient->m_encrypt.cbKey != cbitKeySize / 8) return NULL;
- byte * pb = (byte *)malloc(cbitKeySize / 8);
- if (pb == NULL) return NULL;
- memcpy(pb, pRecipient->m_encrypt.pbKey, cbitKeySize / 8);
+ byte * pb;
+ if (pRecipient->m_pkey != NULL) {
+ const cn_cbor * pK = cn_cbor_mapget_int(pRecipient->m_pkey, -1);
+ CHECK_CONDITION((pK != NULL) && (pK->type == CN_CBOR_BYTES), COSE_ERR_INVALID_PARAMETER);
+ CHECK_CONDITION(pK->length == cbitKeySize / 8, COSE_ERR_INVALID_PARAMETER);
+ pb = COSE_CALLOC(cbitKeySize / 8, 1, &pRecipient->m_encrypt.m_message.m_allocContext);
+ CHECK_CONDITION(pb != NULL, COSE_ERR_OUT_OF_MEMORY);
+ memcpy(pb, pK->v.bytes, cbitKeySize / 8);
+ }
+ else {
+ if (pRecipient->m_encrypt.cbKey != cbitKeySize / 8) return NULL;
+ pb = (byte *)malloc(cbitKeySize / 8);
+ if (pb == NULL) return NULL;
+ memcpy(pb, pRecipient->m_encrypt.pbKey, cbitKeySize / 8);
+ }
return pb;
}
break;
@@ -185,6 +224,9 @@
default:
return NULL;
}
+
+errorReturn:
+ return NULL;
}
bool COSE_Recipient_SetKey_secret(HCOSE_RECIPIENT h, const byte * pbKey, int cbKey, cose_errback * perror)
@@ -219,8 +261,42 @@
return false;
}
+
+
p = (COSE_RecipientInfo *)h;
p->m_pkey = pKey;
return true;
}
+
+bool COSE_Recipient_map_put(HCOSE_RECIPIENT h, int key, cn_cbor * value, int flags, cose_errback * perror)
+{
+ if (!IsValidRecipientHandle(h) || (value == NULL)) {
+ if (perror != NULL) perror->err = COSE_ERR_INVALID_PARAMETER;
+ return false;
+ }
+
+ if (!_COSE_map_put(&((COSE_RecipientInfo *)h)->m_encrypt.m_message, key, value, flags, perror)) return false;
+
+ if (key == COSE_Header_Algorithm) {
+ if (value->type == CN_CBOR_INT) {
+ switch (value->v.uint) {
+ case COSE_Algorithm_Direct:
+ case COSE_Algorithm_ECDH_ES_HKDF_256:
+ case COSE_Algorithm_ECDH_ES_HKDF_512:
+ ((COSE_RecipientInfo *)h)->m_encrypt.m_message.m_flags |= 1;
+ break;
+
+ default:
+ ((COSE_RecipientInfo *)h)->m_encrypt.m_message.m_flags &= ~1;
+ break;
+ }
+ }
+ else {
+ ((COSE_RecipientInfo *)h)->m_encrypt.m_message.m_flags &= ~1;
+ }
+ }
+
+ return true;
+}
+
diff --git a/src/cose.h b/src/cose.h
index 3259957..969e40c 100644
--- a/src/cose.h
+++ b/src/cose.h
@@ -46,7 +46,8 @@
COSE_enveloped_object = 992,
COSE_encrypted_object = 993,
COSE_mac_object = 994,
- COSE_mac0_object = 996
+ COSE_mac0_object = 996,
+ COSE_recipient_object = -1
} COSE_object_type;
// Generic functions for the COSE library
@@ -135,9 +136,17 @@
HCOSE_RECIPIENT COSE_Encrypt_add_shared_secret(HCOSE_ENCRYPT cose, COSE_Algorithms algId, byte * rgbKey, int cbKey, byte * rgbKid, int cbKid, cose_errback * perr);
HCOSE_RECIPIENT COSE_Encrypt_GetRecipient(HCOSE_ENCRYPT cose, int iRecipient, cose_errback * perr);
+
+HCOSE_RECIPIENT COSE_Recipient_Init(CBOR_CONTEXT_COMMA cose_errback * perror);
+bool COSE_Recipient_Free(HCOSE_RECIPIENT cose);
bool COSE_Recipient_SetKey_secret(HCOSE_RECIPIENT h, const byte * rgb, int cb, cose_errback * perr);
bool COSE_Recipient_SetKey(HCOSE_RECIPIENT h, const cn_cbor * pKey, cose_errback * perror);
+bool COSE_Recipient_map_put(HCOSE_RECIPIENT h, int key, cn_cbor * value, int flags, cose_errback * perror);
+cn_cbor * COSE_Recipient_map_get_string(HCOSE_RECIPIENT cose, const char * key, int flags, cose_errback * errp);
+cn_cbor * COSE_Recipient_map_get_int(HCOSE_RECIPIENT cose, int key, int flags, cose_errback * errp);
+
+
//
//
@@ -153,6 +162,7 @@
HCOSE_RECIPIENT COSE_Mac_add_shared_secret(HCOSE_MAC cose, COSE_Algorithms algId, byte * rgbKey, int cbKey, byte * rgbKid, int cbKid, cose_errback * perr);
+extern bool COSE_Mac_AddRecipient(HCOSE_MAC hMac, HCOSE_RECIPIENT hRecip, cose_errback * perr);
HCOSE_RECIPIENT COSE_Mac_GetRecipient(HCOSE_MAC cose, int iRecipient, cose_errback * perr);
//
diff --git a/test/json.c b/test/json.c
index bf44aff..c5e3a9f 100644
--- a/test/json.c
+++ b/test/json.c
@@ -56,7 +56,7 @@
for (ib2 = ib + 1; ib2 < cch; ib2++) if (rgch[ib2] == '"') break;
rgch[ib2] = 0;
node = cn_cbor_string_create(&rgch[ib+1], CBOR_CONTEXT_PARAM_COMMA NULL);
- rgch[ib2] = '"';
+ // rgch[ib2] = '"';
ib = ib2;
break;
@@ -219,7 +219,7 @@
decoding_table = malloc(256);
for (int i = 0; i < 64; i++)
- decoding_table[(unsigned char)encoding_table[i]] = i;
+ decoding_table[encoding_table[i]] = (char) i;
}
diff --git a/test/test.c b/test/test.c
index c6175b0..4af9a6b 100644
--- a/test/test.c
+++ b/test/test.c
@@ -24,6 +24,28 @@
#define CBOR_CONTEXT_PARAM_COMMA
#endif
+struct {
+ char * sz;
+ int i;
+} RgAlgorithmNames[5] = {
+ {"HS256", COSE_Algorithm_HMAC_256_256},
+ {"HS256/64", COSE_Algorithm_HMAC_256_64},
+ {"HS384", COSE_Algorithm_HMAC_384_384},
+ {"HS512", COSE_Algorithm_HMAC_512_512},
+ {"direct", COSE_Algorithm_Direct}
+};
+
+int MapAlgorithmName(const cn_cbor * p)
+{
+ int i;
+
+ for (i = 0; i < _countof(RgAlgorithmNames); i++) {
+ if (strcmp(RgAlgorithmNames[i].sz, p->v.str) == 0) return RgAlgorithmNames[i].i;
+ }
+
+ return 0;
+}
+
cn_cbor * cn_cbor_clone(const cn_cbor * pIn)
{
cn_cbor * pOut = NULL;
@@ -101,6 +123,58 @@
{ "k", 4, OPERATION_BASE64, -1}
};
+enum {
+ Attributes_MAC_protected=1,
+ Attributes_MAC_unprotected,
+ Attributes_Recipient_protected,
+ Attributes_Recipient_unprotected,
+} whichSet;
+
+bool SetAttributes(HCOSE hHandle, const cn_cbor * pAttributes, int which)
+{
+ const cn_cbor * pKey;
+ const cn_cbor * pValue;
+ int keyNew;
+ cn_cbor * pValueNew;
+
+ if (pAttributes == NULL) return true;
+ if (pAttributes->type != CN_CBOR_MAP) return false;
+
+ for (pKey = pAttributes->first_child; pKey != NULL; pKey = pKey->next->next) {
+ pValue = pKey->next;
+
+ if (pKey->type != CN_CBOR_TEXT) return false;
+
+ if (strcmp(pKey->v.str, "alg") == 0) {
+ keyNew = COSE_Header_Algorithm;
+ pValueNew = cn_cbor_int_create(MapAlgorithmName(pValue), CBOR_CONTEXT_PARAM_COMMA NULL);
+ }
+ else {
+ continue;
+ }
+
+ switch (which) {
+ case Attributes_MAC_protected:
+ COSE_Mac_map_put((HCOSE_MAC)hHandle, keyNew, pValueNew, COSE_PROTECT_ONLY, NULL);
+ break;
+
+ case Attributes_MAC_unprotected:
+ COSE_Mac_map_put((HCOSE_MAC)hHandle, keyNew, pValueNew, COSE_UNPROTECT_ONLY, NULL);
+ break;
+
+ case Attributes_Recipient_protected:
+ COSE_Recipient_map_put((HCOSE_RECIPIENT)hHandle, keyNew, pValueNew, COSE_PROTECT_ONLY, NULL);
+ break;
+
+ case Attributes_Recipient_unprotected:
+ COSE_Recipient_map_put((HCOSE_RECIPIENT)hHandle, keyNew, pValueNew, COSE_UNPROTECT_ONLY, NULL);
+ break;
+ }
+ }
+
+ return true;
+}
+
cn_cbor * BuildKey(const cn_cbor * pKeyIn)
{
cn_cbor * pKeyOut = cn_cbor_map_create(CBOR_CONTEXT_PARAM_COMMA NULL);
@@ -221,6 +295,63 @@
return 0;
}
+
+int BuildMacMessage(const cn_cbor * pControl)
+{
+ int iRecipient;
+
+ //
+ // We don't run this for all control sequences - skip those marked fail.
+ //
+
+ const cn_cbor * pFail = cn_cbor_mapget_string(pControl, "fail");
+ if ((pFail != NULL) && (pFail->type == CN_CBOR_TRUE)) return 0;
+
+ HCOSE_MAC hMacObj = COSE_Mac_Init(CBOR_CONTEXT_PARAM_COMMA NULL);
+
+ const cn_cbor * pInputs = cn_cbor_mapget_string(pControl, "input");
+ if (pInputs == NULL) exit(1);
+ const cn_cbor * pMac = cn_cbor_mapget_string(pInputs, "mac");
+ if (pMac == NULL) exit(1);
+
+ const cn_cbor * pContent = cn_cbor_mapget_string(pInputs, "plaintext");
+ if (!COSE_Mac_SetContent(hMacObj, pContent->v.bytes, pContent->length, NULL)) goto returnError;
+
+ if (!SetAttributes((HCOSE) hMacObj, cn_cbor_mapget_string(pMac, "protected"), Attributes_MAC_protected)) goto returnError;
+ if (!SetAttributes((HCOSE) hMacObj, cn_cbor_mapget_string(pMac, "unprotected"), Attributes_MAC_unprotected)) goto returnError;
+
+ const cn_cbor * pRecipients = cn_cbor_mapget_string(pMac, "recipients");
+ if ((pRecipients == NULL) || (pRecipients->type != CN_CBOR_ARRAY)) exit(1);
+
+ pRecipients = pRecipients->first_child;
+ for (iRecipient = 0; pRecipients != NULL; iRecipient++, pRecipients = pRecipients->next) {
+ cn_cbor * pkey = BuildKey(cn_cbor_mapget_string(pRecipients, "key"));
+ if (pkey == NULL) exit(1);
+
+ HCOSE_RECIPIENT hRecip = COSE_Recipient_Init(CBOR_CONTEXT_PARAM_COMMA NULL);
+ if (hRecip == NULL) exit(1);
+
+ if (!SetAttributes((HCOSE) hRecip, cn_cbor_mapget_string(pRecipients, "protected"), Attributes_Recipient_protected)) goto returnError;
+ if (!SetAttributes((HCOSE) hRecip, cn_cbor_mapget_string(pRecipients, "unprotected"), Attributes_Recipient_unprotected)) goto returnError;
+
+ if (!COSE_Recipient_SetKey(hRecip, pkey, NULL)) exit(1);
+
+ if (!COSE_Mac_AddRecipient(hMacObj, hRecip, NULL)) exit(1);
+ }
+
+ COSE_Mac_encrypt(hMacObj, NULL);
+
+ size_t cb = COSE_Encode((HCOSE)hMacObj, NULL, 0, 0) + 1;
+ byte * rgb = (byte *)malloc(cb);
+ cb = COSE_Encode((HCOSE)hMacObj, rgb, 0, cb);
+
+ return 0;
+
+returnError:
+ CFails += 1;
+ return 1;
+}
+
int MacMessage()
{
HCOSE_MAC hEncObj = COSE_Mac_Init(CBOR_CONTEXT_PARAM_COMMA NULL);
@@ -453,6 +584,7 @@
if (cn_cbor_mapget_string(pInput, "mac") != NULL) {
ValidateMAC(pControl);
+ BuildMacMessage(pControl);
}
}
else {