Coverage

* Make a single AAD routine for MAC messages
* Add some additional corner cases to test
diff --git a/src/MacMessage.c b/src/MacMessage.c
index efd6b17..a5a0f91 100644
--- a/src/MacMessage.c
+++ b/src/MacMessage.c
@@ -178,6 +178,75 @@
 }
 
 
+static bool Mac_Build_AAD(COSE * pCose, byte ** ppbAuthData, size_t * pcbAuthData, CBOR_CONTEXT_COMMA cose_errback * perr)
+{
+	cn_cbor * pAuthData = NULL;
+	bool fRet = false;
+	cn_cbor_errback cbor_error;
+	cn_cbor * ptmp = NULL;
+	cn_cbor * pcn;
+	size_t cbAuthData;
+	byte * pbAuthData = NULL;
+
+	//  Build authenticated data
+	//  Protected headers
+	//  external data
+	//  body
+
+	pAuthData = cn_cbor_array_create(CBOR_CONTEXT_PARAM_COMMA NULL);
+	CHECK_CONDITION(pAuthData != NULL, COSE_ERR_OUT_OF_MEMORY);
+
+	//  Add the context string
+
+	ptmp = cn_cbor_string_create("MAC", CBOR_CONTEXT_PARAM_COMMA &cbor_error);
+	CHECK_CONDITION_CBOR(ptmp != NULL, cbor_error);
+	CHECK_CONDITION_CBOR(cn_cbor_array_append(pAuthData, ptmp, &cbor_error), cbor_error);
+	ptmp = NULL;
+
+	// Add the protected attributes
+
+	pcn = _COSE_arrayget_int(pCose, INDEX_PROTECTED);
+	CHECK_CONDITION((pcn != NULL) && (pcn->type == CN_CBOR_BYTES), COSE_ERR_INVALID_PARAMETER);
+
+	ptmp = cn_cbor_data_create(pcn->v.bytes, (int)pcn->length, CBOR_CONTEXT_PARAM_COMMA NULL);
+	CHECK_CONDITION(ptmp != NULL, COSE_ERR_CBOR);
+
+	CHECK_CONDITION(cn_cbor_array_append(pAuthData, ptmp, NULL), COSE_ERR_CBOR);
+	ptmp = NULL;
+
+	//  Add the external bytes
+
+	ptmp = cn_cbor_data_create(pCose->m_pbExternal, (int) pCose->m_cbExternal, CBOR_CONTEXT_PARAM_COMMA &cbor_error);
+	CHECK_CONDITION_CBOR(ptmp != NULL, cbor_error);
+	CHECK_CONDITION_CBOR(cn_cbor_array_append(pAuthData, ptmp, &cbor_error), cbor_error);
+	ptmp = NULL;
+
+	//  Add the content
+	pcn = _COSE_arrayget_int(pCose, INDEX_BODY);
+	ptmp = cn_cbor_data_create(pcn->v.bytes, (int)pcn->length, CBOR_CONTEXT_PARAM_COMMA &cbor_error);
+	CHECK_CONDITION_CBOR(ptmp != NULL, cbor_error);
+	CHECK_CONDITION_CBOR(cn_cbor_array_append(pAuthData, ptmp, &cbor_error), cbor_error);
+	ptmp = NULL;
+
+	//  Turn it into bytes
+	cbAuthData = cn_cbor_encoder_write(RgbDontUse2, 0, sizeof(RgbDontUse2), pAuthData);
+	CHECK_CONDITION(cbAuthData > 0, COSE_ERR_CBOR);
+	pbAuthData = (byte *)COSE_CALLOC(cbAuthData, 1, context);
+	CHECK_CONDITION(pbAuthData != NULL, COSE_ERR_OUT_OF_MEMORY);
+	CHECK_CONDITION(cn_cbor_encoder_write(pbAuthData, 0, cbAuthData, pAuthData) == cbAuthData, COSE_ERR_CBOR);
+
+	*ppbAuthData = pbAuthData;
+	*pcbAuthData = cbAuthData;
+	pbAuthData = NULL;
+	fRet = true;
+
+errorReturn:
+	if (pbAuthData != NULL) COSE_FREE(pbAuthData, context);
+	if (pAuthData != NULL) CN_CBOR_FREE(pAuthData, context);
+	if (ptmp != NULL) CN_CBOR_FREE(ptmp, context);
+	return fRet;
+}
+
 bool COSE_Mac_encrypt(HCOSE_MAC h, cose_errback * perr)
 {
 	int alg;
@@ -192,8 +261,8 @@
 	cn_cbor_context * context = NULL;
 #endif
 	COSE_MacMessage * pcose = (COSE_MacMessage *)h;
-	cn_cbor_errback cbor_error;
 	bool fRet = false;
+	size_t cbAuthData = 0;
 
 	CHECK_CONDITION(IsValidMacHandle(h), COSE_ERR_INVALID_PARAMETER);
 
@@ -266,45 +335,9 @@
 	const cn_cbor * cbProtected = _COSE_encode_protected(&pcose->m_message, perr);
 	if (cbProtected == NULL) goto errorReturn;
 
-	//  Get the body
-	const cn_cbor * cbBody = _COSE_arrayget_int(&pcose->m_message, INDEX_BODY);
-	CHECK_CONDITION(cbBody != NULL, COSE_ERR_INVALID_PARAMETER);
-
 	//  Build authenticated data
-	//  Protected headers
-	//  external data
-	//  body
 
-	ssize_t cbAuthData = 0;
-	pAuthData = cn_cbor_array_create(CBOR_CONTEXT_PARAM_COMMA NULL);
-	CHECK_CONDITION(pAuthData != NULL, COSE_ERR_OUT_OF_MEMORY);
-
-	ptmp = cn_cbor_string_create("MAC", CBOR_CONTEXT_PARAM_COMMA &cbor_error);
-	CHECK_CONDITION_CBOR(ptmp != NULL, cbor_error);
-	CHECK_CONDITION_CBOR(cn_cbor_array_append(pAuthData, ptmp, &cbor_error), cbor_error);
-	ptmp = NULL;
-
-	ptmp = cn_cbor_data_create(cbProtected->v.bytes, (int) cbProtected->length, CBOR_CONTEXT_PARAM_COMMA NULL);
-	CHECK_CONDITION(ptmp != NULL, COSE_ERR_CBOR);
-
-	CHECK_CONDITION(cn_cbor_array_append(pAuthData, ptmp, NULL), COSE_ERR_CBOR);
-	ptmp = NULL;
-
-	ptmp = cn_cbor_data_create(NULL, 0, CBOR_CONTEXT_PARAM_COMMA &cbor_error);
-	CHECK_CONDITION_CBOR(ptmp != NULL, cbor_error);
-	CHECK_CONDITION_CBOR(cn_cbor_array_append(pAuthData, ptmp, &cbor_error), cbor_error);
-	ptmp = NULL;
-
-	ptmp = cn_cbor_data_create(cbBody->v.bytes, (int) cbBody->length, CBOR_CONTEXT_PARAM_COMMA &cbor_error);
-	CHECK_CONDITION_CBOR(ptmp != NULL, cbor_error);
-	CHECK_CONDITION_CBOR(cn_cbor_array_append(pAuthData, ptmp, &cbor_error), cbor_error);
-	ptmp = NULL;
-
-	cbAuthData = cn_cbor_encoder_write(RgbDontUse2, 0, sizeof(RgbDontUse2), pAuthData);
-	CHECK_CONDITION(cbAuthData > 0, COSE_ERR_CBOR);
-	pbAuthData = (byte *)COSE_CALLOC(cbAuthData, 1, context);
-	CHECK_CONDITION(pbAuthData != NULL, COSE_ERR_OUT_OF_MEMORY);
-	CHECK_CONDITION(cn_cbor_encoder_write(pbAuthData, 0, cbAuthData, pAuthData) == cbAuthData, COSE_ERR_CBOR);
+	if (!Mac_Build_AAD(&pcose->m_message, &pbAuthData, &cbAuthData, CBOR_CONTEXT_PARAM_COMMA perr)) goto errorReturn;
 
 	switch (alg) {
 	case COSE_Algorithm_CBC_MAC_128_64:
@@ -358,7 +391,6 @@
 {
 	COSE_MacMessage * pcose = (COSE_MacMessage *)h;
 	COSE_RecipientInfo * pRecip = (COSE_RecipientInfo *)hRecip;
-	cn_cbor_errback cbor_error;
 	byte * pbAuthData = NULL;
 	int cbitKey = 0;
 
@@ -369,9 +401,8 @@
 #ifdef USE_CBOR_CONTEXT
 	cn_cbor_context * context = NULL;
 #endif
-	ssize_t cbAuthData;
+	size_t cbAuthData;
 	cn_cbor * pAuthData = NULL;
-	cn_cbor * ptmp = NULL;
 
 	CHECK_CONDITION(IsValidMacHandle(h) && IsValidRecipientHandle(hRecip), COSE_ERR_INVALID_PARAMETER);
 
@@ -436,34 +467,9 @@
 	cn_cbor * cnProtected = _COSE_arrayget_int(&pcose->m_message, INDEX_PROTECTED);
 	CHECK_CONDITION((cnProtected != NULL) && (cnProtected->type == CN_CBOR_BYTES), COSE_ERR_INVALID_PARAMETER);
 
-	cn_cbor * cnContent = _COSE_arrayget_int(&pcose->m_message, INDEX_BODY);
-	CHECK_CONDITION((cnContent != NULL) && (cnContent->type == CN_CBOR_BYTES), COSE_ERR_INVALID_PARAMETER);
-
 	//  Build authenticated data
-	pbAuthData = NULL;
-	pAuthData = cn_cbor_array_create(CBOR_CONTEXT_PARAM_COMMA &cbor_error);
-	CHECK_CONDITION_CBOR(pAuthData != NULL, cbor_error);
 
-	ptmp = cn_cbor_string_create("MAC", CBOR_CONTEXT_PARAM_COMMA &cbor_error);
-	CHECK_CONDITION_CBOR(ptmp != NULL, cbor_error);
-	CHECK_CONDITION_CBOR(cn_cbor_array_append(pAuthData, ptmp, &cbor_error), cbor_error);
-
-	ptmp = cn_cbor_data_create(cnProtected->v.bytes, (int) cnProtected->length, CBOR_CONTEXT_PARAM_COMMA &cbor_error);
-	CHECK_CONDITION_CBOR(ptmp != NULL, cbor_error);
-	CHECK_CONDITION_CBOR(cn_cbor_array_append(pAuthData, ptmp, &cbor_error), cbor_error);
-
-	ptmp = cn_cbor_data_create(NULL, 0, CBOR_CONTEXT_PARAM_COMMA &cbor_error);
-	CHECK_CONDITION_CBOR(ptmp != NULL, cbor_error);
-	CHECK_CONDITION_CBOR(cn_cbor_array_append(pAuthData, ptmp, &cbor_error), cbor_error);
-
-	ptmp = cn_cbor_data_create(cnContent->v.bytes, (int) cnContent->length, CBOR_CONTEXT_PARAM_COMMA &cbor_error);
-	CHECK_CONDITION_CBOR(ptmp != NULL, cbor_error);
-	CHECK_CONDITION_CBOR(cn_cbor_array_append(pAuthData, ptmp, &cbor_error), cbor_error);
-
-	cbAuthData = cn_cbor_encoder_write(RgbDontUseMac, 0, sizeof(RgbDontUseMac), pAuthData);
-	pbAuthData = (byte *)COSE_CALLOC(cbAuthData, 1, context);
-	CHECK_CONDITION(pbAuthData != NULL, COSE_ERR_OUT_OF_MEMORY);
-	CHECK_CONDITION((cn_cbor_encoder_write(pbAuthData, 0, cbAuthData+1, pAuthData) == cbAuthData), COSE_ERR_CBOR); // M00HACK
+	if (!Mac_Build_AAD(&pcose->m_message, &pbAuthData, &cbAuthData, CBOR_CONTEXT_PARAM_COMMA perr)) goto errorReturn;
 
 	switch (alg) {
 	case COSE_Algorithm_HMAC_256_256:
diff --git a/test/mac_test.c b/test/mac_test.c
index b94c692..7ef91c0 100644
--- a/test/mac_test.c
+++ b/test/mac_test.c
@@ -348,6 +348,7 @@
 {
     HCOSE_MAC hMAC;
     HCOSE_ENCRYPT hEncrypt = NULL;
+	HCOSE_RECIPIENT hRecipient = NULL;
     byte rgb[10];
 	cn_cbor * cn = cn_cbor_int_create(5, CBOR_CONTEXT_PARAM_COMMA NULL);
 
@@ -380,6 +381,19 @@
     COSE_Mac_GetRecipient((HCOSE_MAC)hEncrypt, 0, NULL);
 
     //
+	//  Unsupported algorithm
+
+	hMAC = COSE_Mac_Init(CBOR_CONTEXT_PARAM_COMMA NULL);
+	if (hMAC == NULL) CFails++;
+	if (!COSE_Mac_SetContent(hMAC, (byte *) "Message", 7, NULL)) CFails++;
+	if (!COSE_Mac_map_put_int(hMAC, COSE_Header_Algorithm, cn_cbor_int_create(-99, CBOR_CONTEXT_PARAM_COMMA NULL), COSE_PROTECT_ONLY, NULL)) CFails++;
+	hRecipient = COSE_Recipient_from_shared_secret(rgb, sizeof(rgb), rgb, sizeof(rgb), CBOR_CONTEXT_PARAM_COMMA NULL);
+	if (hRecipient == NULL) CFails++;
+	if (!COSE_Mac_AddRecipient(hMAC, hRecipient, NULL)) CFails++;
+	if (COSE_Mac_encrypt(hMAC, NULL)) CFails++;
+
+	if (!COSE_Mac_map_put_int(hMAC, COSE_Header_Algorithm, cn_cbor_string_create("hmac", CBOR_CONTEXT_PARAM_COMMA NULL), COSE_PROTECT_ONLY, NULL)) CFails++;
+	if (COSE_Mac_encrypt(hMAC, NULL)) CFails++;
 
     return;
 }
@@ -390,11 +404,12 @@
 	byte rgb[10];
 	cn_cbor * cn = cn_cbor_int_create(5, CBOR_CONTEXT_PARAM_COMMA NULL);
 
+	hEncrypt = COSE_Encrypt_Init(CBOR_CONTEXT_PARAM_COMMA NULL);
+
 	//  Missing case - addref then release on item
 
 	//  Invalid Handle checks
 
-	COSE_Mac0_Free((HCOSE_MAC0)hEncrypt);
 	COSE_Mac0_SetContent((HCOSE_MAC0)hEncrypt, rgb, 10, NULL);
 	COSE_Mac0_map_get_int((HCOSE_MAC0)hEncrypt, 1, COSE_BOTH, NULL);
 	COSE_Mac0_map_put_int((HCOSE_MAC0)hEncrypt, 1, cn, COSE_PROTECT_ONLY, NULL);
@@ -410,7 +425,9 @@
 	COSE_Mac0_encrypt((HCOSE_MAC0)hEncrypt, rgb, 10, NULL);
 	COSE_Mac0_validate((HCOSE_MAC0)hEncrypt, rgb, 10, NULL);
 
-	//
+	COSE_Mac0_Free((HCOSE_MAC0)hEncrypt);
+
+
 
 	return;
 }