Make the triple wrap example work
diff --git a/src/Recipient.c b/src/Recipient.c
index c8e524a..da0543e 100644
--- a/src/Recipient.c
+++ b/src/Recipient.c
@@ -220,12 +220,11 @@
return fRet;
}
-bool _COSE_Recipient_decrypt(COSE_RecipientInfo * pRecip, int algIn, int cbitKey, byte * pbKeyIn, cose_errback * perr)
+bool _COSE_Recipient_decrypt(COSE_RecipientInfo * pRecip, int algIn, int cbitKeyOut, byte * pbKeyOut, cose_errback * perr)
{
int alg;
const cn_cbor * cn = NULL;
COSE_RecipientInfo * pRecip2;
- byte * pbKey = pbKeyIn;
#ifdef USE_CBOR_CONTEXT
cn_cbor_context * context;
#endif
@@ -237,6 +236,8 @@
byte rgbKey[256 / 8];
byte * pbSecret = NULL;
int cbKey2;
+ byte * pbKeyX = NULL;
+ int cbitKeyX = 0;
#ifdef USE_CBOR_CONTEXT
context = &pcose->m_message.m_allocContext;
@@ -251,24 +252,32 @@
if (pbSecret != NULL) COSE_FREE(pbSecret, context);
return false;
}
+ CHECK_CONDITION(cn->type != CN_CBOR_TEXT, COSE_ERR_UNKNOWN_ALGORITHM);
CHECK_CONDITION((cn->type == CN_CBOR_UINT) || (cn->type == CN_CBOR_INT), COSE_ERR_INVALID_PARAMETER);
alg = (int)cn->v.uint;
- CHECK_CONDITION(pbKey != NULL, COSE_ERR_INVALID_PARAMETER);
+ CHECK_CONDITION(pbKeyOut != NULL, COSE_ERR_INVALID_PARAMETER);
switch (alg) {
case COSE_Algorithm_Direct:
CHECK_CONDITION(pRecip->m_pkey != NULL, COSE_ERR_INVALID_PARAMETER);
cn = cn_cbor_mapget_int(pRecip->m_pkey, -1);
CHECK_CONDITION((cn != NULL) && (cn->type == CN_CBOR_BYTES), COSE_ERR_INVALID_PARAMETER);
- CHECK_CONDITION((cn->length == (unsigned int)cbitKey / 8), COSE_ERR_INVALID_PARAMETER);
- memcpy(pbKey, cn->v.bytes, cn->length);
+ CHECK_CONDITION((cn->length == (unsigned int)cbitKeyOut / 8), COSE_ERR_INVALID_PARAMETER);
+ memcpy(pbKeyOut, cn->v.bytes, cn->length);
return true;
case COSE_Algorithm_AES_KW_128:
+ cbitKeyX = 128;
+ break;
+
case COSE_Algorithm_AES_KW_192:
+ cbitKeyX = 192;
+ break;
+
case COSE_Algorithm_AES_KW_256:
+ cbitKeyX = 192;
break;
case COSE_Algorithm_Direct_HKDF_AES_128:
@@ -298,10 +307,15 @@
break;
}
- // If there is a recipient - ask it for the key
+ if (pcose->m_recipientFirst != NULL) {
+ // If there is a recipient - ask it for the key
+ CHECK_CONDITION(cbitKeyX != 0, COSE_ERR_INVALID_PARAMETER);
+ pbKeyX = COSE_CALLOC(cbitKeyX / 8, 1, context);
+ CHECK_CONDITION(pbKeyX != NULL, COSE_ERR_OUT_OF_MEMORY);
- for (pRecip2 = pcose->m_recipientFirst; pRecip2 != NULL; pRecip2 = pRecip->m_recipientNext) {
- if (_COSE_Recipient_decrypt(pRecip2, alg, cbitKey, pbKey, perr)) break;
+ for (pRecip2 = pcose->m_recipientFirst; pRecip2 != NULL; pRecip2 = pRecip->m_recipientNext) {
+ if (_COSE_Recipient_decrypt(pRecip2, alg, cbitKeyX, pbKeyX, perr)) break;
+ }
}
cnBody = _COSE_arrayget_int(&pcose->m_message, INDEX_BODY);
@@ -311,85 +325,91 @@
case COSE_Algorithm_AES_KW_128:
case COSE_Algorithm_AES_KW_192:
case COSE_Algorithm_AES_KW_256:
- CHECK_CONDITION(pRecip->m_pkey != NULL, COSE_ERR_INVALID_PARAMETER);
- int x = cbitKey / 8;
- cn = cn_cbor_mapget_int(pRecip->m_pkey, -1);
- CHECK_CONDITION((cn != NULL) && (cn->type == CN_CBOR_BYTES), COSE_ERR_INVALID_PARAMETER);
+ if (pbKeyX != NULL) {
+ int x = cbitKeyOut / 8;
+ if (!AES_KW_Decrypt((COSE_Enveloped *)pcose, pbKeyX, cbitKeyX, cnBody->v.bytes, cnBody->length, pbKeyOut, &x, perr)) goto errorReturn;
+ }
+ else {
+ CHECK_CONDITION(pRecip->m_pkey != NULL, COSE_ERR_INVALID_PARAMETER);
+ int x = cbitKeyOut / 8;
+ cn = cn_cbor_mapget_int(pRecip->m_pkey, -1);
+ CHECK_CONDITION((cn != NULL) && (cn->type == CN_CBOR_BYTES), COSE_ERR_INVALID_PARAMETER);
- if (!AES_KW_Decrypt((COSE_Enveloped *)pcose, cn->v.bytes, cn->length * 8, cnBody->v.bytes, cnBody->length, pbKey, &x, perr)) goto errorReturn;
+ if (!AES_KW_Decrypt((COSE_Enveloped *)pcose, cn->v.bytes, cn->length * 8, cnBody->v.bytes, cnBody->length, pbKeyOut, &x, perr)) goto errorReturn;
+ }
break;
case COSE_Algorithm_Direct_HKDF_HMAC_SHA_256:
- if (!HKDF_X(&pcose->m_message, true, false, false, false, algIn, pRecip->m_pkey, NULL, pbKey, cbitKey, 256, CBOR_CONTEXT_PARAM_COMMA perr)) goto errorReturn;
+ if (!HKDF_X(&pcose->m_message, true, false, false, false, algIn, pRecip->m_pkey, NULL, pbKeyOut, cbitKeyOut, 256, CBOR_CONTEXT_PARAM_COMMA perr)) goto errorReturn;
break;
case COSE_Algorithm_Direct_HKDF_HMAC_SHA_512:
- if (!HKDF_X(&pcose->m_message, true, false, false, false, algIn, pRecip->m_pkey, NULL, pbKey, cbitKey, 512, CBOR_CONTEXT_PARAM_COMMA perr)) goto errorReturn;
+ if (!HKDF_X(&pcose->m_message, true, false, false, false, algIn, pRecip->m_pkey, NULL, pbKeyOut, cbitKeyOut, 512, CBOR_CONTEXT_PARAM_COMMA perr)) goto errorReturn;
break;
case COSE_Algorithm_Direct_HKDF_AES_128:
- if (!HKDF_X(&pcose->m_message, false, false, false, false, algIn, pRecip->m_pkey, NULL, pbKey, cbitKey, 128, CBOR_CONTEXT_PARAM_COMMA perr)) goto errorReturn;
+ if (!HKDF_X(&pcose->m_message, false, false, false, false, algIn, pRecip->m_pkey, NULL, pbKeyOut, cbitKeyOut, 128, CBOR_CONTEXT_PARAM_COMMA perr)) goto errorReturn;
break;
case COSE_Algorithm_Direct_HKDF_AES_256:
- if (!HKDF_X(&pcose->m_message, false, false, false, false, algIn, pRecip->m_pkey, NULL, pbKey, cbitKey, 256, CBOR_CONTEXT_PARAM_COMMA perr)) goto errorReturn;
+ if (!HKDF_X(&pcose->m_message, false, false, false, false, algIn, pRecip->m_pkey, NULL, pbKeyOut, cbitKeyOut, 256, CBOR_CONTEXT_PARAM_COMMA perr)) goto errorReturn;
break;
case COSE_Algorithm_ECDH_ES_HKDF_256:
- if (!HKDF_X(&pcose->m_message, true, true, false, false, algIn, pRecip->m_pkey, NULL, pbKey, cbitKey, 256, CBOR_CONTEXT_PARAM_COMMA perr)) goto errorReturn;
+ if (!HKDF_X(&pcose->m_message, true, true, false, false, algIn, pRecip->m_pkey, NULL, pbKeyOut, cbitKeyOut, 256, CBOR_CONTEXT_PARAM_COMMA perr)) goto errorReturn;
break;
case COSE_Algorithm_ECDH_ES_HKDF_512:
- if (!HKDF_X(&pcose->m_message, true, true, false, false, algIn, pRecip->m_pkey, NULL, pbKey, cbitKey, 512, CBOR_CONTEXT_PARAM_COMMA perr)) goto errorReturn;
+ if (!HKDF_X(&pcose->m_message, true, true, false, false, algIn, pRecip->m_pkey, NULL, pbKeyOut, cbitKeyOut, 512, CBOR_CONTEXT_PARAM_COMMA perr)) goto errorReturn;
break;
case COSE_Algorithm_ECDH_SS_HKDF_256:
- if (!HKDF_X(&pcose->m_message, true, true, true, false, algIn, pRecip->m_pkey, NULL, pbKey, cbitKey, 256, CBOR_CONTEXT_PARAM_COMMA perr)) goto errorReturn;
+ if (!HKDF_X(&pcose->m_message, true, true, true, false, algIn, pRecip->m_pkey, NULL, pbKeyOut, cbitKeyOut, 256, CBOR_CONTEXT_PARAM_COMMA perr)) goto errorReturn;
break;
case COSE_Algorithm_ECDH_SS_HKDF_512:
- if (!HKDF_X(&pcose->m_message, true, true, true, false, algIn, pRecip->m_pkey, NULL, pbKey, cbitKey, 512, CBOR_CONTEXT_PARAM_COMMA perr)) goto errorReturn;
+ if (!HKDF_X(&pcose->m_message, true, true, true, false, algIn, pRecip->m_pkey, NULL, pbKeyOut, cbitKeyOut, 512, CBOR_CONTEXT_PARAM_COMMA perr)) goto errorReturn;
break;
case COSE_Algorithm_ECDH_ES_A128KW:
if (!HKDF_X(&pcose->m_message, true, true, false, false, COSE_Algorithm_AES_KW_128, pRecip->m_pkey, NULL, rgbKey, 128, 256, CBOR_CONTEXT_PARAM_COMMA perr)) goto errorReturn;
- if (!AES_KW_Decrypt((COSE_Enveloped *)pcose, rgbKey, 128, cnBody->v.bytes, cnBody->length, pbKey, &cbKey2, perr)) goto errorReturn;
+ if (!AES_KW_Decrypt((COSE_Enveloped *)pcose, rgbKey, 128, cnBody->v.bytes, cnBody->length, pbKeyOut, &cbKey2, perr)) goto errorReturn;
break;
case COSE_Algorithm_ECDH_ES_A192KW:
if (!HKDF_X(&pcose->m_message, true, true, false, false, COSE_Algorithm_AES_KW_192, pRecip->m_pkey, NULL, rgbKey, 192, 256, CBOR_CONTEXT_PARAM_COMMA perr)) goto errorReturn;
- if (!AES_KW_Decrypt((COSE_Enveloped *)pcose, rgbKey, 192, cnBody->v.bytes, cnBody->length, pbKey, &cbKey2, perr)) goto errorReturn;
+ if (!AES_KW_Decrypt((COSE_Enveloped *)pcose, rgbKey, 192, cnBody->v.bytes, cnBody->length, pbKeyOut, &cbKey2, perr)) goto errorReturn;
break;
case COSE_Algorithm_ECDH_ES_A256KW:
if (!HKDF_X(&pcose->m_message, true, true, false, false, COSE_Algorithm_AES_KW_256, pRecip->m_pkey, NULL, rgbKey, 256, 256, CBOR_CONTEXT_PARAM_COMMA perr)) goto errorReturn;
- if (!AES_KW_Decrypt((COSE_Enveloped *)pcose, rgbKey, 256, cnBody->v.bytes, cnBody->length, pbKey, &cbKey2, perr)) goto errorReturn;
+ if (!AES_KW_Decrypt((COSE_Enveloped *)pcose, rgbKey, 256, cnBody->v.bytes, cnBody->length, pbKeyOut, &cbKey2, perr)) goto errorReturn;
break;
case COSE_Algorithm_ECDH_SS_A128KW:
if (!HKDF_X(&pcose->m_message, true, true, true, false, COSE_Algorithm_AES_KW_128, pRecip->m_pkey, NULL, rgbKey, 128, 256, CBOR_CONTEXT_PARAM_COMMA perr)) goto errorReturn;
- if (!AES_KW_Decrypt((COSE_Enveloped *)pcose, rgbKey, 128, cnBody->v.bytes, cnBody->length, pbKey, &cbKey2, perr)) goto errorReturn;
+ if (!AES_KW_Decrypt((COSE_Enveloped *)pcose, rgbKey, 128, cnBody->v.bytes, cnBody->length, pbKeyOut, &cbKey2, perr)) goto errorReturn;
break;
case COSE_Algorithm_ECDH_SS_A192KW:
if (!HKDF_X(&pcose->m_message, true, true, true, false, COSE_Algorithm_AES_KW_192, pRecip->m_pkey, NULL, rgbKey, 192, 256, CBOR_CONTEXT_PARAM_COMMA perr)) goto errorReturn;
- if (!AES_KW_Decrypt((COSE_Enveloped *)pcose, rgbKey, 192, cnBody->v.bytes, cnBody->length, pbKey, &cbKey2, perr)) goto errorReturn;
+ if (!AES_KW_Decrypt((COSE_Enveloped *)pcose, rgbKey, 192, cnBody->v.bytes, cnBody->length, pbKeyOut, &cbKey2, perr)) goto errorReturn;
break;
case COSE_Algorithm_ECDH_SS_A256KW:
if (!HKDF_X(&pcose->m_message, true, true, true, false, COSE_Algorithm_AES_KW_256, pRecip->m_pkey, NULL, rgbKey, 256, 256, CBOR_CONTEXT_PARAM_COMMA perr)) goto errorReturn;
- if (!AES_KW_Decrypt((COSE_Enveloped *)pcose, rgbKey, 256, cnBody->v.bytes, cnBody->length, pbKey, &cbKey2, perr)) goto errorReturn;
+ if (!AES_KW_Decrypt((COSE_Enveloped *)pcose, rgbKey, 256, cnBody->v.bytes, cnBody->length, pbKeyOut, &cbKey2, perr)) goto errorReturn;
break;
@@ -404,7 +424,7 @@
bool _COSE_Recipient_encrypt(COSE_RecipientInfo * pRecipient, const byte * pbContent, size_t cbContent, cose_errback * perr)
{
int alg;
- int t;
+ int t = 0;
COSE_RecipientInfo * pri;
const cn_cbor * cn_Alg = NULL;
byte * pbAuthData = NULL;
@@ -486,16 +506,16 @@
}
}
CHECK_CONDITION(t != 3, COSE_ERR_INVALID_PARAMETER);
- }
- // Do we need to generate a random key at this point -
- // This is only true if we both haven't done it and and we have a recipient to encrypt it.
-
- if ((pRecipient->m_pkey!= NULL)) {
- pbKey = (byte *)COSE_CALLOC(cbitKey / 8, 1, context);
- CHECK_CONDITION(pbKey != NULL, COSE_ERR_OUT_OF_MEMORY);
- cbKey = cbitKey / 8;
- rand_bytes(pbKey, cbKey);
+ // Do we need to generate a random key at this point -
+ // This is only true if we both haven't done it and and we have a recipient to encrypt it.
+
+ if (t == 2) {
+ pbKey = (byte *)COSE_CALLOC(cbitKey / 8, 1, context);
+ CHECK_CONDITION(pbKey != NULL, COSE_ERR_OUT_OF_MEMORY);
+ cbKey = cbitKey / 8;
+ rand_bytes(pbKey, cbKey);
+ }
}
// Build protected headers
@@ -534,7 +554,7 @@
if (!AES_KW_Encrypt(pRecipient, pK->v.bytes, (int) pK->length*8, pbContent, (int) cbContent, perr)) goto errorReturn;
}
else {
- if (!AES_KW_Encrypt(pRecipient, NULL, 0, pbContent, (int) cbContent, perr)) goto errorReturn;
+ if (!AES_KW_Encrypt(pRecipient, pbKey, (int) cbKey*8, pbContent, (int) cbContent, perr)) goto errorReturn;
}
break;
@@ -1089,3 +1109,67 @@
return _COSE_map_get_int(&((COSE_RecipientInfo *)h)->m_encrypt.m_message, key, flags, perror);
}
+
+HCOSE_RECIPIENT COSE_Recipient_GetRecipient(HCOSE_RECIPIENT cose, int iRecipient, cose_errback * perr)
+{
+ int i;
+ COSE_RecipientInfo * p = NULL;
+
+ CHECK_CONDITION(IsValidRecipientHandle(cose), COSE_ERR_INVALID_HANDLE);
+ CHECK_CONDITION(iRecipient >= 0, COSE_ERR_INVALID_PARAMETER);
+
+ p = ((COSE_RecipientInfo *)cose)->m_encrypt.m_recipientFirst;
+ for (i = 0; i < iRecipient; i++) {
+ CHECK_CONDITION(p != NULL, COSE_ERR_INVALID_PARAMETER);
+ p = p->m_recipientNext;
+ }
+ if (p != NULL) p->m_encrypt.m_message.m_refCount++;
+
+errorReturn:
+ return (HCOSE_RECIPIENT)p;
+}
+
+bool COSE_Recipient_AddRecipient(HCOSE_RECIPIENT hEnc, HCOSE_RECIPIENT hRecip, cose_errback * perr)
+{
+ COSE_RecipientInfo * pRecip;
+ COSE_Enveloped * pEncrypt;
+ cn_cbor * pRecipients = NULL;
+#ifdef USE_CBOR_CONTEXT
+ cn_cbor_context * context;
+#endif
+ cn_cbor_errback cbor_error;
+
+ CHECK_CONDITION(IsValidRecipientHandle(hEnc), COSE_ERR_INVALID_HANDLE);
+ CHECK_CONDITION(IsValidRecipientHandle(hRecip), COSE_ERR_INVALID_HANDLE);
+
+ pEncrypt = &((COSE_RecipientInfo *)hEnc)->m_encrypt;
+ pRecip = (COSE_RecipientInfo *)hRecip;
+
+#ifdef USE_CBOR_CONTEXT
+ context = &pEncrypt->m_message.m_allocContext;
+#endif // USE_CBOR_CONTEXT
+
+ pRecip->m_recipientNext = pEncrypt->m_recipientFirst;
+ pEncrypt->m_recipientFirst = pRecip;
+
+ pRecipients = _COSE_arrayget_int(&pEncrypt->m_message, INDEX_RECIPIENTS);
+ if (pRecipients == NULL) {
+ pRecipients = cn_cbor_array_create(CBOR_CONTEXT_PARAM_COMMA &cbor_error);
+ CHECK_CONDITION_CBOR(pRecipients != NULL, cbor_error);
+
+ if (!_COSE_array_replace(&pEncrypt->m_message, pRecipients, INDEX_RECIPIENTS, CBOR_CONTEXT_PARAM_COMMA &cbor_error)) {
+ CN_CBOR_FREE(pRecipients, context);
+ if (perr != NULL) perr->err = _MapFromCBOR(cbor_error);
+ goto errorReturn;
+ }
+ }
+
+ CHECK_CONDITION_CBOR(cn_cbor_array_append(pRecipients, pRecip->m_encrypt.m_message.m_cbor, &cbor_error), cbor_error);
+
+ pRecip->m_encrypt.m_message.m_refCount++;
+
+ return true;
+
+errorReturn:
+ return false;
+}
diff --git a/src/cose.h b/src/cose.h
index dceed1c..7c13e36 100644
--- a/src/cose.h
+++ b/src/cose.h
@@ -211,6 +211,9 @@
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);
+extern bool COSE_Recipient_AddRecipient(HCOSE_RECIPIENT hMac, HCOSE_RECIPIENT hRecip, cose_errback * perr);
+HCOSE_RECIPIENT COSE_Recipient_GetRecipient(HCOSE_RECIPIENT cose, int iRecipient, cose_errback * perr);
+
/*
* Encrypt message API
diff --git a/test/encrypt.c b/test/encrypt.c
index a7072ba..ea5b23a 100644
--- a/test/encrypt.c
+++ b/test/encrypt.c
@@ -16,6 +16,85 @@
#pragma warning (disable: 4127)
#endif
+bool DecryptMessage(const byte * pbEncoded, size_t cbEncoded, bool fFailBody, const cn_cbor * pEnveloped, const cn_cbor * pRecipient1, int iRecipient1, const cn_cbor * pRecipient2, int iRecipient2)
+{
+ HCOSE_ENVELOPED hEnc = NULL;
+ HCOSE_RECIPIENT hRecip = NULL;
+ HCOSE_RECIPIENT hRecip2 = NULL;
+ bool fRet = false;
+ int type;
+ cose_errback cose_err;
+ cn_cbor * pkey;
+
+ hEnc = (HCOSE_ENVELOPED)COSE_Decode(pbEncoded, cbEncoded, &type, COSE_enveloped_object, CBOR_CONTEXT_PARAM_COMMA &cose_err);
+ if (hEnc == NULL) {
+ if (fFailBody && (cose_err.err == COSE_ERR_INVALID_PARAMETER)) return true;
+ goto errorReturn;
+ }
+
+ if (!SetReceivingAttributes((HCOSE)hEnc, pEnveloped, Attributes_Enveloped_protected)) goto errorReturn;
+
+ hRecip = COSE_Enveloped_GetRecipient(hEnc, iRecipient1, NULL);
+ if (hRecip == NULL) goto errorReturn;
+ if (!SetReceivingAttributes((HCOSE)hRecip, pRecipient1, Attributes_Recipient_protected)) goto errorReturn;
+
+ if (pRecipient2 != NULL) {
+ pkey = BuildKey(cn_cbor_mapget_string(pRecipient2, "key"), false);
+ if (pkey == NULL) goto errorReturn;
+
+ hRecip2 = COSE_Recipient_GetRecipient(hRecip, iRecipient2, NULL);
+ if (hRecip2 == NULL) goto errorReturn;
+
+ if (!SetReceivingAttributes((HCOSE)hRecip2, pRecipient2, Attributes_Recipient_protected)) goto errorReturn;
+ if (!COSE_Recipient_SetKey(hRecip2, pkey, NULL)) goto errorReturn;
+ }
+ else {
+ pkey = BuildKey(cn_cbor_mapget_string(pRecipient1, "key"), false);
+ if (pkey == NULL) goto errorReturn;
+ if (!COSE_Recipient_SetKey(hRecip, pkey, NULL)) goto errorReturn;
+ }
+
+
+ cn_cbor * cnStatic = cn_cbor_mapget_string(pRecipient1, "sender_key");
+ if (cnStatic != NULL) {
+ if (COSE_Recipient_map_get_int(hRecip, COSE_Header_ECDH_SPK, COSE_BOTH, NULL) == 0) {
+ COSE_Recipient_map_put_int(hRecip, COSE_Header_ECDH_SPK, BuildKey(cnStatic, true), COSE_DONT_SEND, NULL);
+ }
+ }
+
+ if (pRecipient2 != NULL) {
+ cnStatic = cn_cbor_mapget_string(pRecipient2, "sender_key");
+ if (cnStatic != NULL) {
+ if (COSE_Recipient_map_get_int(hRecip2, COSE_Header_ECDH_SPK, COSE_BOTH, NULL) == 0) {
+ COSE_Recipient_map_put_int(hRecip2, COSE_Header_ECDH_SPK, BuildKey(cnStatic, true), COSE_DONT_SEND, NULL);
+ }
+ }
+ }
+
+ if (!fFailBody) {
+ cn_cbor * cn = cn_cbor_mapget_string(pRecipient1, "fail");
+ if (cn != NULL && (cn->type == CN_CBOR_TRUE)) fFailBody = true;
+ if (fFailBody && (pRecipient2 != NULL)) {
+ cn = cn_cbor_mapget_string(pRecipient2, "fail");
+ if (cn != NULL && (cn->type == CN_CBOR_TRUE)) fFailBody = true;
+ }
+ }
+
+ if (COSE_Enveloped_decrypt(hEnc, hRecip, NULL)) {
+ fRet = !fFailBody;
+ }
+ else {
+ fRet = fFailBody;
+ }
+
+errorReturn:
+ if (hEnc != NULL) COSE_Enveloped_Free(hEnc);
+ if (hRecip != NULL) COSE_Recipient_Free(hRecip);
+ if (hRecip2 != NULL) COSE_Recipient_Free(hRecip2);
+
+
+ return fRet;
+}
int _ValidateEnveloped(const cn_cbor * pControl, const byte * pbEncoded, size_t cbEncoded)
{
@@ -23,10 +102,7 @@
const cn_cbor * pFail;
const cn_cbor * pEnveloped;
const cn_cbor * pRecipients;
- HCOSE_ENVELOPED hEnc;
- int type;
int iRecipient;
- bool fFail = false;
bool fFailBody = false;
pFail = cn_cbor_mapget_string(pControl, "fail");
@@ -44,56 +120,18 @@
iRecipient = (int) pRecipients->length - 1;
pRecipients = pRecipients->first_child;
for (; pRecipients != NULL; iRecipient--, pRecipients = pRecipients->next) {
-
- hEnc = (HCOSE_ENVELOPED)COSE_Decode(pbEncoded, cbEncoded, &type, COSE_enveloped_object, CBOR_CONTEXT_PARAM_COMMA NULL);
- if (hEnc == NULL) { if (fFailBody) return 0; else goto errorReturn; }
-
- if (!SetReceivingAttributes((HCOSE)hEnc, pEnveloped, Attributes_Enveloped_protected)) goto errorReturn;
-
- cn_cbor * pkey = BuildKey(cn_cbor_mapget_string(pRecipients, "key"), false);
- if (pkey == NULL) {
- fFail = true;
- continue;
- }
-
- HCOSE_RECIPIENT hRecip = COSE_Enveloped_GetRecipient(hEnc, iRecipient, NULL);
- if (hRecip == NULL) {
- fFail = true;
- continue;
- }
-
- if (!COSE_Recipient_SetKey(hRecip, pkey, NULL)) {
- fFail = true;
- continue;
- }
-
- if (!SetReceivingAttributes((HCOSE) hRecip, pRecipients, Attributes_Recipient_protected)) goto errorReturn;
-
- cn_cbor * cnStatic = cn_cbor_mapget_string(pRecipients, "sender_key");
- if (cnStatic != NULL) {
- if (COSE_Recipient_map_get_int(hRecip, COSE_Header_ECDH_SPK, COSE_BOTH, NULL) == 0) {
- COSE_Recipient_map_put_int(hRecip, COSE_Header_ECDH_SPK, BuildKey(cnStatic, true), COSE_DONT_SEND, NULL);
- }
- }
-
- pFail = cn_cbor_mapget_string(pRecipients, "fail");
- if (COSE_Enveloped_decrypt(hEnc, hRecip, NULL)) {
- if ((pFail != NULL) && (pFail->type != CN_CBOR_TRUE)) fFail = true;
+ cn_cbor * pRecip2 = cn_cbor_mapget_string(pRecipients, "recipients");
+ if (pRecip2 == NULL) {
+ if (!DecryptMessage(pbEncoded, cbEncoded, fFailBody, pEnveloped, pRecipients, iRecipient, NULL, 0)) CFails++;
}
else {
- if ((pFail == NULL) || (pFail->type == CN_CBOR_FALSE)) fFail = true;
+ int iRecipient2 = (int)(pRecip2->length - 1);
+ pRecip2 = pRecip2->first_child;
+ for (; pRecip2 != NULL; pRecip2 = pRecip2->next, iRecipient2--) {
+ if (!DecryptMessage(pbEncoded, cbEncoded, fFailBody, pEnveloped, pRecipients, iRecipient, pRecip2, iRecipient2)) CFails++;
+ }
}
-
- COSE_Enveloped_Free(hEnc);
- COSE_Recipient_Free(hRecip);
}
-
- if (fFailBody) {
- if (!fFail) fFail = true;
- else fFail = false;
- }
-
- if (fFail) CFails += 1;
return 0;
errorReturn:
@@ -109,6 +147,45 @@
return _ValidateEnveloped(pControl, pbEncoded, cbEncoded);
}
+HCOSE_RECIPIENT BuildRecipient(const cn_cbor * pRecipient)
+{
+ HCOSE_RECIPIENT hRecip = COSE_Recipient_Init(0, CBOR_CONTEXT_PARAM_COMMA NULL);
+ if (hRecip == NULL) goto returnError;
+
+ if (!SetSendingAttributes((HCOSE)hRecip, pRecipient, Attributes_Recipient_protected)) goto returnError;
+
+ cn_cbor * cnKey = cn_cbor_mapget_string(pRecipient, "key");
+ if (cnKey != NULL) {
+ cn_cbor * pkey = BuildKey(cnKey, true);
+ if (pkey == NULL) goto returnError;
+
+ if (!COSE_Recipient_SetKey(hRecip, pkey, NULL)) goto returnError;
+ }
+
+ cnKey = cn_cbor_mapget_string(pRecipient, "recipients");
+ if (cnKey != NULL) {
+ for (cnKey = cnKey->first_child; cnKey != NULL; cnKey = cnKey->next) {
+ HCOSE_RECIPIENT hRecip2 = BuildRecipient(cnKey);
+ if (hRecip2 == NULL) goto returnError;
+ if (!COSE_Recipient_AddRecipient(hRecip, hRecip2, NULL)) goto returnError;
+ COSE_Recipient_Free(hRecip2);
+ }
+ }
+
+
+ cn_cbor * pSenderKey = cn_cbor_mapget_string(pRecipient, "sender_key");
+ if (pSenderKey != NULL) {
+ cn_cbor * pSendKey = BuildKey(pSenderKey, false);
+ if (!COSE_Recipient_SetSenderKey(hRecip, pSendKey, 2, NULL)) goto returnError;
+ }
+
+ return hRecip;
+
+returnError:
+ COSE_Recipient_Free(hRecip);
+ return NULL;
+}
+
int BuildEnvelopedMessage(const cn_cbor * pControl)
{
int iRecipient;
@@ -140,24 +217,11 @@
pRecipients = pRecipients->first_child;
for (iRecipient = 0; pRecipients != NULL; iRecipient++, pRecipients = pRecipients->next) {
- cn_cbor * pkey = BuildKey(cn_cbor_mapget_string(pRecipients, "key"), true);
- if (pkey == NULL) goto returnError;
-
- HCOSE_RECIPIENT hRecip = COSE_Recipient_Init(0, CBOR_CONTEXT_PARAM_COMMA NULL);
+ HCOSE_RECIPIENT hRecip = BuildRecipient(pRecipients);
if (hRecip == NULL) goto returnError;
- if (!SetSendingAttributes((HCOSE)hRecip, pRecipients, Attributes_Recipient_protected)) goto returnError;
-
- if (!COSE_Recipient_SetKey(hRecip, pkey, NULL)) goto returnError;
-
if (!COSE_Enveloped_AddRecipient(hEncObj, hRecip, NULL)) goto returnError;
- cn_cbor * pSenderKey = cn_cbor_mapget_string(pRecipients, "sender_key");
- if (pSenderKey != NULL) {
- cn_cbor * pSendKey = BuildKey(pSenderKey, false);
- if (!COSE_Recipient_SetSenderKey(hRecip, pSendKey, 2, NULL)) goto returnError;
- }
-
COSE_Recipient_Free(hRecip);
}
diff --git a/test/test.c b/test/test.c
index d288a5c..7be7116 100644
--- a/test/test.c
+++ b/test/test.c
@@ -725,7 +725,6 @@
while ((dp = readdir(dirp)) != NULL) {
int cch = strlen(dp->d_name);
if (cch < 4) continue;
- if (strcmp(dp->d_name, "Triple-01.json") == 0) continue;
rgchFullName[ich] = 0;
if (ich + strlen(dp->d_name) >= sizeof(rgchFullName) - 2) {
fprintf(stderr, "Buffer overflow problem\n");