Make MAC handle freeing correct.
diff --git a/README.md b/README.md
index e47b422..b133c58 100644
--- a/README.md
+++ b/README.md
@@ -1,5 +1,5 @@
 
-# COSE-C Implementation [![Build Status](https://travis-ci.org/cose-wg/COSE-C.svg?branch=master)](https://travis-ci.org/cose-wg/COSE-C)[![Coverage Status](https://coveralls.io/repos/cose-wg/COSE-C/badge.svg?branch=master&service=github)](https://coveralls.io/github/cose-wg/COSE-C?branch=master)
+# COSE-C Implementation [![Build Status](https://travis-ci.org/cose-wg/COSE-C.svg?branch=master)](https://travis-ci.org/cose-wg/COSE-C) [![Coverage Status](https://coveralls.io/repos/cose-wg/COSE-C/badge.svg?branch=master&service=github)](https://coveralls.io/github/cose-wg/COSE-C?branch=master)
 
 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.
diff --git a/src/MacMessage.c b/src/MacMessage.c
index e5bfad1..6f49454 100644
--- a/src/MacMessage.c
+++ b/src/MacMessage.c
@@ -79,9 +79,15 @@
 #ifdef USE_CBOR_CONTEXT
 	cn_cbor_context context;
 #endif
+	COSE_MacMessage * p = (COSE_MacMessage *)h;
 
 	if (!IsValidMacHandle(h)) return false;
 
+	if (p->m_message.m_refCount > 1) {
+		p->m_message.m_refCount--;
+		return true;
+	}
+
 #ifdef USE_CBOR_CONTEXT
 	context = ((COSE_MacMessage *)h)->m_message.m_allocContext;
 #endif
@@ -93,11 +99,21 @@
 	return true;
 }
 
-void _COSE_Mac_Release(COSE_MacMessage * p)
+bool _COSE_Mac_Release(COSE_MacMessage * p)
 {
+	COSE_RecipientInfo * pRecipient;
+	COSE_RecipientInfo * pRecipient2;
+
 	if (p->pbKey != NULL) COSE_FREE(p->pbKey, &p->m_message.m_allocContext);
 
+	for (pRecipient = p->m_recipientFirst; pRecipient != NULL; pRecipient = pRecipient2) {
+		pRecipient2 = pRecipient->m_recipientNext;
+		_COSE_Recipient_Free(pRecipient);
+	}
+
 	_COSE_Release(&p->m_message);
+
+	return true;
 }
 
 
@@ -423,12 +439,11 @@
 	cn_cbor_errback cbor_error;
 	byte * pbAuthData = NULL;
 	int cbitKey = 0;
-	byte * pbKeyIn = NULL;
 
 	int alg;
 	const cn_cbor * cn = NULL;
 
-	byte * pbKey = pbKeyIn;
+	byte * pbKey = NULL;
 #ifdef USE_CBOR_CONTEXT
 	cn_cbor_context * context = NULL;
 #endif
@@ -485,8 +500,6 @@
 	if (pbKey == NULL) {
 		pbKey = COSE_CALLOC(cbitKey / 8, 1, context);
 		CHECK_CONDITION(pbKey != NULL, COSE_ERR_OUT_OF_MEMORY);
-		pcose->pbKey = pbKey;
-		pcose->cbKey = cbitKey / 8;
 	}
 
 	//  If there is a recipient - ask it for the key
@@ -532,35 +545,29 @@
 
 	switch (alg) {
 	case COSE_Algorithm_HMAC_256_256:
-		if (!HMAC_Validate(pcose, 256, 256, pbAuthData, cbAuthData, perr)) goto errorReturn;
+		if (!HMAC_Validate(pcose, 256, 256, pbKey, cbitKey, pbAuthData, cbAuthData, perr)) goto errorReturn;
 		break;
 
 	case COSE_Algorithm_HMAC_256_64:
-		if (!HMAC_Validate(pcose, 256, 64, pbAuthData, cbAuthData, perr)) goto errorReturn;
+		if (!HMAC_Validate(pcose, 256, 64, pbKey, cbitKey, pbAuthData, cbAuthData, perr)) goto errorReturn;
 		break;
 
 	case COSE_Algorithm_HMAC_384_384:
-		if (!HMAC_Validate(pcose, 384, 384, pbAuthData, cbAuthData, perr)) goto errorReturn;
+		if (!HMAC_Validate(pcose, 384, 384, pbKey, cbitKey, pbAuthData, cbAuthData, perr)) goto errorReturn;
 		break;
 
 	case COSE_Algorithm_HMAC_512_512:
-		if (!HMAC_Validate(pcose, 512, 512, pbAuthData, cbAuthData, perr)) goto errorReturn;
+		if (!HMAC_Validate(pcose, 512, 512, pbKey, cbitKey, pbAuthData, cbAuthData, perr)) goto errorReturn;
 		break;
 
 	case COSE_Algorithm_CBC_MAC_128_64:
-		if (!AES_CBC_MAC_Validate(pcose, 128, 64, pbAuthData, cbAuthData, perr)) goto errorReturn;
+	case COSE_Algorithm_CBC_MAC_256_64:
+		if (!AES_CBC_MAC_Validate(pcose, 64, pbKey, cbitKey, pbAuthData, cbAuthData, perr)) goto errorReturn;
 		break;
 
 	case COSE_Algorithm_CBC_MAC_128_128:
-		if (!AES_CBC_MAC_Validate(pcose, 128, 128, pbAuthData, cbAuthData, perr)) goto errorReturn;
-		break;
-
-	case COSE_Algorithm_CBC_MAC_256_64:
-		if (!AES_CBC_MAC_Validate(pcose, 256, 64, pbAuthData, cbAuthData, perr)) goto errorReturn;
-		break;
-
 	case COSE_Algorithm_CBC_MAC_256_128:
-		if (!AES_CBC_MAC_Validate(pcose, 256, 128, pbAuthData, cbAuthData, perr)) goto errorReturn;
+		if (!AES_CBC_MAC_Validate(pcose, 128, pbKey, cbitKey, pbAuthData, cbAuthData, perr)) goto errorReturn;
 		break;
 
 	default:
@@ -570,7 +577,7 @@
 
 	if (pbAuthData != NULL) COSE_FREE(pbAuthData, context);
 	if (pAuthData != NULL) cn_cbor_free(pAuthData CBOR_CONTEXT_PARAM);
-	if ((pbKey != NULL) && (pbKeyIn == NULL)) {
+	if ((pbKey != NULL)) {
 		memset(pbKey, 0xff, cbitKey / 8);
 		COSE_FREE(pbKey, context);
 	}
@@ -580,7 +587,7 @@
 errorReturn:
 	if (pbAuthData != NULL) COSE_FREE(pbAuthData, context);
 	if (pAuthData != NULL) cn_cbor_free(pAuthData CBOR_CONTEXT_PARAM);
-	if ((pbKey != NULL) && (pbKeyIn == NULL)) {
+	if ((pbKey != NULL)) {
 		memset(pbKey, 0xff, cbitKey / 8);
 		COSE_FREE(pbKey, context);
 	}
@@ -623,7 +630,7 @@
 	}
 
 	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;
 
@@ -645,6 +652,7 @@
 		CHECK_CONDITION(p != NULL, COSE_ERR_NO_RECIPIENT_FOUND);
 		p = p->m_recipientNext;
 	}
+	p->m_encrypt.m_message.m_refCount++;
 	return (HCOSE_RECIPIENT)p;
 
 errorReturn:
diff --git a/src/Recipient.c b/src/Recipient.c
index 573d870..4cee65a 100644
--- a/src/Recipient.c
+++ b/src/Recipient.c
@@ -91,6 +91,11 @@
 
 void _COSE_Recipient_Free(COSE_RecipientInfo * pRecipient)
 {
+	if (pRecipient->m_encrypt.m_message.m_refCount > 1) {
+		pRecipient->m_encrypt.m_message.m_refCount--;
+		return;
+	}
+
 	COSE_FREE(pRecipient, &pRecipient->m_encrypt.m_message.m_allocContext);
 
 	return;
diff --git a/src/SignerInfo.c b/src/SignerInfo.c
index 8bbf317..a2ed0b6 100644
--- a/src/SignerInfo.c
+++ b/src/SignerInfo.c
@@ -211,13 +211,8 @@
 {
 	cn_cbor_errback cbor_error;
 	byte * pbAuthData = NULL;
-	int cbitKey = 0;
-	byte * pbKeyIn = NULL;
-
 	int alg;
 	const cn_cbor * cn = NULL;
-
-	byte * pbKey = pbKeyIn;
 #ifdef USE_CBOR_CONTEXT
 	cn_cbor_context * context = NULL;
 #endif
@@ -299,20 +294,12 @@
 
 	if (pbAuthData != NULL) COSE_FREE(pbAuthData, context);
 	if (pAuthData != NULL) cn_cbor_free(pAuthData CBOR_CONTEXT_PARAM);
-	if ((pbKey != NULL) && (pbKeyIn == NULL)) {
-		memset(pbKey, 0xff, cbitKey / 8);
-		COSE_FREE(pbKey, context);
-	}
 
 	return true;
 
 errorReturn:
 	if (pbAuthData != NULL) COSE_FREE(pbAuthData, context);
 	if (pAuthData != NULL) cn_cbor_free(pAuthData CBOR_CONTEXT_PARAM);
-	if ((pbKey != NULL) && (pbKeyIn == NULL)) {
-		memset(pbKey, 0xff, cbitKey / 8);
-		COSE_FREE(pbKey, context);
-	}
 
 	return false;
 }
diff --git a/src/cose_int.h b/src/cose_int.h
index d6906f0..4f6ad8b 100644
--- a/src/cose_int.h
+++ b/src/cose_int.h
@@ -152,7 +152,7 @@
 
 //  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);
+extern bool _COSE_Mac_Release(COSE_MacMessage * p);
 
 
 #define CHECK_CONDITION(condition, error) { if (!(condition)) { assert(false); perr->err = error; goto errorReturn;}}
diff --git a/src/crypto.h b/src/crypto.h
index 5eb16d9..d788f27 100644
--- a/src/crypto.h
+++ b/src/crypto.h
@@ -27,10 +27,10 @@
 bool AES_KW_Encrypt(COSE_RecipientInfo * pcose, const byte * pbKeyIn, int cbitKey, const byte *  pbContent, int  cbContent, cose_errback * perr);
 
 
-extern bool AES_CMAC_Validate(COSE_MacMessage * pcose, int KeySize, int TagSize, const byte * pbAuthData, int cbAuthData, cose_errback * perr);
+extern bool AES_CMAC_Validate(COSE_MacMessage * pcose, int KeySize, int TagSize, const byte * pbKey, int cbitKey, const byte * pbAuthData, int cbAuthData, cose_errback * perr);
 
 extern bool AES_CBC_MAC_Create(COSE_MacMessage * pcose, int KeySize, int TagSize, const byte * pbAuthData, int cbAuthData, cose_errback * perr);
-extern bool AES_CBC_MAC_Validate(COSE_MacMessage * pcose, int KeySize, int TagSize, const byte * pbAuthData, int cbAuthData, cose_errback * perr);
+extern bool AES_CBC_MAC_Validate(COSE_MacMessage * pcose, int TagSize, const byte * pbKey, int cbitKey, const byte * pbAuthData, int cbAuthData, cose_errback * perr);
 
 /**
 * Perform an HMAC Creation operation
@@ -44,7 +44,7 @@
 * @return						Did the function succeed?
 */
 bool HMAC_Create(COSE_MacMessage * pcose, int HSize, int TSize, const byte * pbAuthData, int cbAuthData, cose_errback * perr);
-bool HMAC_Validate(COSE_MacMessage * pcose, int HSize, int TSize, const byte * pbAuthData, int cbAuthData, cose_errback * perr);
+bool HMAC_Validate(COSE_MacMessage * pcose, int HSize, int TSize, const byte * pbKey, int cbitKey, const byte * pbAuthData, int cbAuthData, cose_errback * perr);
 
 /**
 * Perform a signature operation
diff --git a/src/openssl.c b/src/openssl.c
index 7de84f1..c3c08a4 100644
--- a/src/openssl.c
+++ b/src/openssl.c
@@ -436,7 +436,7 @@
 	return false;
 }
 
-bool AES_CBC_MAC_Validate(COSE_MacMessage * pcose, int KeySize, int TSize, const byte * pbAuthData, int cbAuthData, cose_errback * perr)
+bool AES_CBC_MAC_Validate(COSE_MacMessage * pcose, int TSize, const byte * pbKey, int cbitKey, const byte * pbAuthData, int cbAuthData, cose_errback * perr)
 {
 	const EVP_CIPHER * pcipher = NULL;
 	EVP_CIPHER_CTX ctx;
@@ -446,7 +446,7 @@
 	bool f = false;
 	unsigned int i;
 
-	switch (KeySize) {
+	switch (cbitKey) {
 	case 128:
 		pcipher = EVP_aes_128_cbc();
 		break;
@@ -462,7 +462,7 @@
 	//  Setup and run the OpenSSL code
 
 	EVP_CIPHER_CTX_init(&ctx);
-	CHECK_CONDITION(EVP_EncryptInit_ex(&ctx, pcipher, NULL, pcose->pbKey, rgbIV), COSE_ERR_CRYPTO_FAIL);
+	CHECK_CONDITION(EVP_EncryptInit_ex(&ctx, pcipher, NULL, pbKey, rgbIV), COSE_ERR_CRYPTO_FAIL);
 
 	TSize /= 8;
 
@@ -575,7 +575,7 @@
 	return true;
 }
 
-bool HMAC_Validate(COSE_MacMessage * pcose, int HSize, int TSize, const byte * pbAuthData, int cbAuthData, cose_errback * perr)
+bool HMAC_Validate(COSE_MacMessage * pcose, int HSize, int TSize, const byte * pbKey, int cbitKey, const byte * pbAuthData, int cbAuthData, cose_errback * perr)
 {
 	HMAC_CTX ctx;
 	const EVP_MD * pmd = NULL;
@@ -599,7 +599,7 @@
 	rgbOut = COSE_CALLOC(EVP_MAX_MD_SIZE, 1, context);
 	CHECK_CONDITION(rgbOut != NULL, COSE_ERR_OUT_OF_MEMORY);
 
-	CHECK_CONDITION(HMAC_Init(&ctx, pcose->pbKey, (int) pcose->cbKey, pmd), COSE_ERR_CRYPTO_FAIL);
+	CHECK_CONDITION(HMAC_Init(&ctx, pbKey, cbitKey/8, pmd), COSE_ERR_CRYPTO_FAIL);
 	CHECK_CONDITION(HMAC_Update(&ctx, pbAuthData, cbAuthData), COSE_ERR_CRYPTO_FAIL);
 	CHECK_CONDITION(HMAC_Final(&ctx, rgbOut, &cbOut), COSE_ERR_CRYPTO_FAIL);
 
@@ -616,7 +616,6 @@
 	COSE_FREE(rgbOut, context);
 	HMAC_cleanup(&ctx);
 	return false;
-
 }
 
 
diff --git a/test/CMakeLists.txt b/test/CMakeLists.txt
index 83f5c4d..99a8ec5 100644
--- a/test/CMakeLists.txt
+++ b/test/CMakeLists.txt
@@ -8,7 +8,7 @@
 
 set (CMAKE_RUNTIME_OUTPUT_DIRECTORY ${dist_dir}/test )
 
-add_executable ( cose_test test.c json.c encrypt.c sign.c context.c )
+add_executable ( cose_test test.c json.c encrypt.c sign.c context.c mac_test.c)
 
 target_link_libraries (cose_test PRIVATE cose-c )
 
diff --git a/test/mac_test.c b/test/mac_test.c
new file mode 100644
index 0000000..edec5f6
--- /dev/null
+++ b/test/mac_test.c
@@ -0,0 +1,220 @@
+#define _CRT_SECURE_NO_WARNINGS
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <cose.h>
+#include <cn-cbor/cn-cbor.h>
+
+#include "json.h"
+#include "test.h"
+#include "context.h"
+
+int _ValidateMAC(const cn_cbor * pControl, const byte * pbEncoded, size_t cbEncoded)
+{
+	const cn_cbor * pInput = cn_cbor_mapget_string(pControl, "input");
+	const cn_cbor * pFail;
+	const cn_cbor * pMac;
+	const cn_cbor * pRecipients;
+	HCOSE_MAC hMAC;
+	int type;
+	int iRecipient;
+	bool fFail = false;
+	bool fFailBody = false;
+
+	pFail = cn_cbor_mapget_string(pControl, "fail");
+	if ((pFail != NULL) && (pFail->type == CN_CBOR_TRUE)) {
+		fFailBody = true;
+	}
+
+	hMAC = (HCOSE_MAC) COSE_Decode(pbEncoded, cbEncoded, &type, COSE_mac_object, NULL, NULL);
+	if (hMAC == NULL) exit(1);
+
+	if ((pInput == NULL) || (pInput->type != CN_CBOR_MAP)) exit(1);
+	pMac = cn_cbor_mapget_string(pInput, "mac");
+	if ((pMac == NULL) || (pMac->type != CN_CBOR_MAP)) exit(1);
+
+	pRecipients = cn_cbor_mapget_string(pMac, "recipients");
+	if ((pRecipients == NULL) || (pRecipients->type != CN_CBOR_ARRAY)) exit(1);
+
+	iRecipient = (int) pRecipients->length - 1;
+	pRecipients = pRecipients->first_child;
+	for (; pRecipients != NULL; iRecipient--, pRecipients=pRecipients->next) {
+		cn_cbor * pkey = BuildKey(cn_cbor_mapget_string(pRecipients, "key"));
+		if (pkey == NULL) {
+			fFail = true;
+			continue;
+		}
+
+		HCOSE_RECIPIENT hRecip = COSE_Mac_GetRecipient(hMAC, iRecipient, NULL);
+		if (hRecip == NULL) {
+			fFail = true;
+			continue;
+		}
+
+		if (!COSE_Recipient_SetKey(hRecip, pkey, NULL)) {
+			fFail = true;
+			continue;
+		}
+
+		pFail = cn_cbor_mapget_string(pRecipients, "fail");
+		if (COSE_Mac_validate(hMAC, hRecip, NULL)) {
+			if ((pFail != NULL) && (pFail->type != CN_CBOR_TRUE)) fFail = true;
+		}
+		else {
+			if ((pFail == NULL) || (pFail->type == CN_CBOR_FALSE)) fFail = true;
+		}
+
+		COSE_Recipient_Free(hRecip);
+	}
+
+	COSE_Mac_Free(hMAC);
+
+	if (fFailBody) {
+		if (!fFail) fFail = true;
+		else fFail = false;
+	}
+
+	if (fFail) CFails += 1;
+	return 0;
+}
+
+int ValidateMAC(const cn_cbor * pControl)
+{
+	int cbEncoded;
+	byte * pbEncoded = GetCBOREncoding(pControl, &cbEncoded);
+
+	return _ValidateMAC(pControl, pbEncoded, cbEncoded);
+}
+
+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 * pAlg = COSE_Mac_map_get_int(hMacObj, 1, COSE_BOTH, NULL);
+
+	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_Recipient_Free(hRecip);
+	}
+
+	if (!COSE_Mac_encrypt(hMacObj, NULL)) exit(1);
+
+	size_t cb = COSE_Encode((HCOSE)hMacObj, NULL, 0, 0) + 1;
+	byte * rgb = (byte *)malloc(cb);
+	cb = COSE_Encode((HCOSE)hMacObj, rgb, 0, cb);
+
+	COSE_Mac_Free(hMacObj);
+
+	int f = _ValidateMAC(pControl, rgb, cb);
+
+	free(rgb);
+	return f;
+
+returnError:
+	CFails += 1;
+	return 1;
+}
+
+int MacMessage()
+{
+	HCOSE_MAC hEncObj = COSE_Mac_Init(CBOR_CONTEXT_PARAM_COMMA NULL);
+	char * sz = "This is the content to be used";
+	byte rgbSecret[256 / 8] = { 'a', 'b', 'c' };
+	byte  rgbKid[6] = { 'a', 'b', 'c', 'd', 'e', 'f' };
+	int cbKid = 6;
+	size_t cb;
+	byte * rgb;
+
+	COSE_Mac_map_put(hEncObj, COSE_Header_Algorithm, cn_cbor_int_create(COSE_Algorithm_HMAC_256_256, CBOR_CONTEXT_PARAM_COMMA NULL), COSE_PROTECT_ONLY, NULL);
+	COSE_Mac_SetContent(hEncObj, (byte *) sz, strlen(sz), NULL);
+
+	COSE_Mac_add_shared_secret(hEncObj, COSE_Algorithm_Direct, rgbSecret, sizeof(rgbSecret), rgbKid, cbKid, NULL);
+
+	COSE_Mac_encrypt(hEncObj, NULL);
+
+	cb = COSE_Encode((HCOSE)hEncObj, NULL, 0, 0) + 1;
+	rgb = (byte *)malloc(cb);
+	cb = COSE_Encode((HCOSE)hEncObj, rgb, 0, cb);
+
+	COSE_Mac_Free(hEncObj);
+
+	FILE * fp = fopen("test.mac.cbor", "wb");
+	fwrite(rgb, cb, 1, fp);
+	fclose(fp);
+
+#if 0
+	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, "%s", szX);
+	fprintf(stdout, "\r\n");
+#endif
+
+	COSE_Mac_Free(hEncObj);
+
+	/* */
+
+	int typ;
+	hEncObj = (HCOSE_MAC) COSE_Decode(rgb,  (int) cb, &typ, COSE_mac_object, NULL, NULL);
+
+	int iRecipient = 0;
+	do {
+		HCOSE_RECIPIENT hRecip;
+
+		hRecip = COSE_Mac_GetRecipient(hEncObj, iRecipient, NULL);
+		if (hRecip == NULL) break;
+
+		COSE_Recipient_SetKey_secret(hRecip, rgbSecret, sizeof(rgbSecret), NULL);
+
+		COSE_Mac_validate(hEncObj, hRecip, NULL);
+
+		iRecipient += 1;
+
+		COSE_Recipient_Free(hRecip);
+
+	} while (true);
+
+	COSE_Mac_Free(hEncObj);
+
+	return 1;
+}
diff --git a/test/test.c b/test/test.c
index 2d56925..e37146e 100644
--- a/test/test.c
+++ b/test/test.c
@@ -15,8 +15,6 @@
 
 #include "test.h"
 
-
-extern int EncryptMessage();
 int CFails = 0;
 
 
@@ -300,201 +298,6 @@
 	return pKeyOut;
 }
 
-int _ValidateMAC(const cn_cbor * pControl, const byte * pbEncoded, size_t cbEncoded)
-{
-	const cn_cbor * pInput = cn_cbor_mapget_string(pControl, "input");
-	const cn_cbor * pFail;
-	const cn_cbor * pMac;
-	const cn_cbor * pRecipients;
-	HCOSE_MAC hMAC;
-	int type;
-	int iRecipient;
-	bool fFail = false;
-	bool fFailBody = false;
-
-	pFail = cn_cbor_mapget_string(pControl, "fail");
-	if ((pFail != NULL) && (pFail->type == CN_CBOR_TRUE)) {
-		fFailBody = true;
-	}
-
-	hMAC = (HCOSE_MAC) COSE_Decode(pbEncoded, cbEncoded, &type, COSE_mac_object, NULL, NULL);
-	if (hMAC == NULL) exit(1);
-
-	if ((pInput == NULL) || (pInput->type != CN_CBOR_MAP)) exit(1);
-	pMac = cn_cbor_mapget_string(pInput, "mac");
-	if ((pMac == NULL) || (pMac->type != CN_CBOR_MAP)) exit(1);
-
-	pRecipients = cn_cbor_mapget_string(pMac, "recipients");
-	if ((pRecipients == NULL) || (pRecipients->type != CN_CBOR_ARRAY)) exit(1);
-
-	iRecipient = (int) pRecipients->length - 1;
-	pRecipients = pRecipients->first_child;
-	for (; pRecipients != NULL; iRecipient--, pRecipients=pRecipients->next) {
-		cn_cbor * pkey = BuildKey(cn_cbor_mapget_string(pRecipients, "key"));
-		if (pkey == NULL) {
-			fFail = true;
-			continue;
-		}
-
-		HCOSE_RECIPIENT hRecip = COSE_Mac_GetRecipient(hMAC, iRecipient, NULL);
-		if (hRecip == NULL) {
-			fFail = true;
-			continue;
-		}
-
-		if (!COSE_Recipient_SetKey(hRecip, pkey, NULL)) {
-			fFail = true;
-			continue;
-		}
-
-		pFail = cn_cbor_mapget_string(pRecipients, "fail");
-		if (COSE_Mac_validate(hMAC, hRecip, NULL)) {
-			if ((pFail != NULL) && (pFail->type != CN_CBOR_TRUE)) fFail = true;
-		}
-		else {
-			if ((pFail == NULL) || (pFail->type == CN_CBOR_FALSE)) fFail = true;
-		}
-	}
-
-	if (fFailBody) {
-		if (!fFail) fFail = true;
-		else fFail = false;
-	}
-
-	if (fFail) CFails += 1;
-	return 0;
-}
-
-int ValidateMAC(const cn_cbor * pControl)
-{
-	int cbEncoded;
-	byte * pbEncoded = GetCBOREncoding(pControl, &cbEncoded);
-
-	return _ValidateMAC(pControl, pbEncoded, cbEncoded);
-}
-
-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 * pAlg = COSE_Mac_map_get_int(hMacObj, 1, COSE_BOTH, NULL);
-
-	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);
-	}
-
-	if (!COSE_Mac_encrypt(hMacObj, NULL)) exit(1);
-
-	size_t cb = COSE_Encode((HCOSE)hMacObj, NULL, 0, 0) + 1;
-	byte * rgb = (byte *)malloc(cb);
-	cb = COSE_Encode((HCOSE)hMacObj, rgb, 0, cb);
-
-	int f = _ValidateMAC(pControl, rgb, cb);
-
-	free(rgb);
-	return f;
-
-returnError:
-	CFails += 1;
-	return 1;
-}
-
-int MacMessage()
-{
-	HCOSE_MAC hEncObj = COSE_Mac_Init(CBOR_CONTEXT_PARAM_COMMA NULL);
-	char * sz = "This is the content to be used";
-	byte rgbSecret[256 / 8] = { 'a', 'b', 'c' };
-	byte  rgbKid[6] = { 'a', 'b', 'c', 'd', 'e', 'f' };
-	int cbKid = 6;
-	size_t cb;
-	byte * rgb;
-
-	COSE_Mac_map_put(hEncObj, COSE_Header_Algorithm, cn_cbor_int_create(COSE_Algorithm_HMAC_256_256, CBOR_CONTEXT_PARAM_COMMA NULL), COSE_PROTECT_ONLY, NULL);
-	COSE_Mac_SetContent(hEncObj, (byte *) sz, strlen(sz), NULL);
-
-	COSE_Mac_add_shared_secret(hEncObj, COSE_Algorithm_Direct, rgbSecret, sizeof(rgbSecret), rgbKid, cbKid, NULL);
-
-	COSE_Mac_encrypt(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);
-
-#if 0
-	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, "%s", szX);
-	fprintf(stdout, "\r\n");
-#endif
-
-	COSE_Mac_Free(hEncObj);
-
-	/* */
-
-	int typ;
-	hEncObj = (HCOSE_MAC) COSE_Decode(rgb,  (int) cb, &typ, COSE_mac_object, NULL, NULL);
-
-	int iRecipient = 0;
-	do {
-		HCOSE_RECIPIENT hRecip;
-
-		hRecip = COSE_Mac_GetRecipient(hEncObj, iRecipient, NULL);
-		if (hRecip == NULL) break;
-
-		COSE_Recipient_SetKey_secret(hRecip, rgbSecret, sizeof(rgbSecret), NULL);
-
-		COSE_Mac_validate(hEncObj, hRecip, NULL);
-
-		iRecipient += 1;
-
-	} while (true);
-
-	return 1;
-}
 
 
 bool cn_cbor_array_replace(cn_cbor * cb_array, cn_cbor * cb_value, int index, CBOR_CONTEXT_COMMA cn_cbor_errback *errp);
diff --git a/test/test.h b/test/test.h
index 0a4ecd4..d5ab6b4 100644
--- a/test/test.h
+++ b/test/test.h
@@ -23,6 +23,11 @@
 int SignMessage();
 int BuildSignedMessage(const cn_cbor * pControl);
 
+// mac_testc
+
+int ValidateMac(const cn_cbor * pControl);
+int MacMessage();
+int BuildMacMessage(const cn_cbor * pControl);
 
 //  test.c
 enum {