Merge Mac compute and validate routines w/ Mac0
diff --git a/src/MacMessage.c b/src/MacMessage.c
index d67f63f..df62f1e 100644
--- a/src/MacMessage.c
+++ b/src/MacMessage.c
@@ -299,6 +299,19 @@
 
 bool COSE_Mac_encrypt(HCOSE_MAC h, cose_errback * perr)
 {
+	COSE_MacMessage * pcose = (COSE_MacMessage *)h;
+
+	CHECK_CONDITION(IsValidMacHandle(h), COSE_ERR_INVALID_HANDLE);
+	CHECK_CONDITION(pcose->m_recipientFirst != NULL, COSE_ERR_INVALID_PARAMETER);
+
+		return _COSE_Mac_compute(pcose, NULL, 0, "MAC", perr);
+
+	errorReturn:
+		return false;
+}
+
+bool _COSE_Mac_compute(COSE_MacMessage * pcose, const byte * pbKeyIn, size_t cbKeyIn, const char * szContext, cose_errback * perr)
+{
 	int alg;
 	int t;
 	COSE_RecipientInfo * pri;
@@ -306,24 +319,17 @@
 	byte * pbAuthData = NULL;
 	size_t cbitKey;
 #ifdef USE_CBOR_CONTEXT
-	cn_cbor_context * context = NULL;
+	cn_cbor_context * context = &pcose->m_message.m_allocContext;
 #endif
-	COSE_MacMessage * pcose = (COSE_MacMessage *)h;
 	bool fRet = false;
 	size_t cbAuthData = 0;
 	byte * pbKey = NULL;
 	size_t cbKey = 0;
 
-	CHECK_CONDITION(IsValidMacHandle(h), COSE_ERR_INVALID_PARAMETER);
-
-#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, perr);
 	if (cn_Alg == NULL) goto errorReturn;
 	CHECK_CONDITION(cn_Alg->type != CN_CBOR_TEXT, COSE_ERR_UNKNOWN_ALGORITHM);
-	CHECK_CONDITION(((cn_Alg->type == CN_CBOR_UINT || cn_Alg->type == CN_CBOR_INT)), COSE_ERR_UNKNOWN_ALGORITHM);
+	CHECK_CONDITION(((cn_Alg->type == CN_CBOR_UINT || cn_Alg->type == CN_CBOR_INT)), COSE_ERR_INVALID_PARAMETER);
 
 	alg = (int) cn_Alg->v.uint;
 
@@ -384,28 +390,35 @@
 
 	//  If we are doing direct encryption - then recipient generates the key
 
-	if (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;
-				pbKey = _COSE_RecipientInfo_generateKey(pri, alg, cbitKey, perr);
-				cbKey = cbitKey / 8;
-				if (pbKey == NULL) goto errorReturn;
-			}
-			else {
-				t |= 2;
-			}
-		}
-		CHECK_CONDITION(t != 3, COSE_ERR_INVALID_PARAMETER);
+	if (pbKeyIn != NULL) {
+		CHECK_CONDITION(cbKeyIn == cbitKey / 8, COSE_ERR_INVALID_PARAMETER);
+		pbKey = pbKeyIn;
+		cbKey = cbKeyIn;
 	}
+	else {
+			t = 0;
+			for (pri = pcose->m_recipientFirst; pri != NULL; pri = pri->m_recipientNext) {
+				if (pri->m_encrypt.m_message.m_flags & 1) {
+					CHECK_CONDITION(pbKey == NULL, COSE_ERR_INVALID_PARAMETER);
 
-	if (pbKey == NULL) {
-		pbKey = (byte *)COSE_CALLOC(cbitKey / 8, 1, context);
-		CHECK_CONDITION(pbKey != NULL, COSE_ERR_OUT_OF_MEMORY);
+					t |= 1;
+					pbKey = _COSE_RecipientInfo_generateKey(pri, alg, cbitKey, perr);
+					cbKey = cbitKey / 8;
+					CHECK_CONDITION(pbKey != NULL, COSE_ERR_OUT_OF_MEMORY);
+				}
+				else {
+					t |= 2;
+				}
+			}
+			CHECK_CONDITION(t != 3, COSE_ERR_INVALID_PARAMETER);
 
-		cbKey = cbitKey / 8;
-		rand_bytes(pbKey, cbKey);
+		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
@@ -415,7 +428,7 @@
 
 	//  Build authenticated data
 
-	if (!_COSE_Mac_Build_AAD(&pcose->m_message, "MAC", &pbAuthData, &cbAuthData, CBOR_CONTEXT_PARAM_COMMA perr)) goto errorReturn;
+	if (!_COSE_Mac_Build_AAD(&pcose->m_message, szContext, &pbAuthData, &cbAuthData, CBOR_CONTEXT_PARAM_COMMA perr)) goto errorReturn;
 
 	switch (alg) {
 #ifdef USE_AES_CBC_MAC_128_64
@@ -479,7 +492,7 @@
 	fRet = true;
 
 errorReturn:
-	if (pbKey != NULL) {
+	if ((pbKey != NULL) && (pbKeyIn != pbKey)) {
 		memset(pbKey, 0, cbKey);
 		COSE_FREE(pbKey, context);
 	}
@@ -491,6 +504,17 @@
 {
 	COSE_MacMessage * pcose = (COSE_MacMessage *)h;
 	COSE_RecipientInfo * pRecip = (COSE_RecipientInfo *)hRecip;
+
+	CHECK_CONDITION(IsValidMacHandle(h) && IsValidRecipientHandle(hRecip), COSE_ERR_INVALID_PARAMETER);
+
+	return _COSE_Mac_validate(pcose, pRecip, NULL, 0, "MAC", perr);
+
+errorReturn:
+	return false;
+}
+
+bool _COSE_Mac_validate(COSE_MacMessage * pcose, COSE_RecipientInfo * pRecip, const byte * pbKeyIn, size_t cbKeyIn, const char * szContext, cose_errback * perr)
+{
 	byte * pbAuthData = NULL;
 	int cbitKey = 0;
 	bool fRet = false;
@@ -500,15 +524,11 @@
 
 	byte * pbKey = NULL;
 #ifdef USE_CBOR_CONTEXT
-	cn_cbor_context * context = NULL;
+	cn_cbor_context * context = &pcose->m_message.m_allocContext;
 #endif
 	size_t cbAuthData;
 
-	CHECK_CONDITION(IsValidMacHandle(h) && IsValidRecipientHandle(hRecip), COSE_ERR_INVALID_PARAMETER);
-
-#ifdef USE_CBOR_CONTEXT
-	context = &pcose->m_message.m_allocContext;
-#endif
+	CHECK_CONDITION(!((pRecip != NULL) && (pbKeyIn != NULL)), COSE_ERR_INTERNAL);
 
 	cn = _COSE_map_get_int(&pcose->m_message, COSE_Header_Algorithm, COSE_BOTH, perr);
 	if (cn == NULL) goto errorReturn;
@@ -577,26 +597,43 @@
 
 	//  Allocate the key if we have not already done so
 
-	if (pbKey == NULL) {
-		pbKey = COSE_CALLOC(cbitKey / 8, 1, context);
-		CHECK_CONDITION(pbKey != NULL, COSE_ERR_OUT_OF_MEMORY);
+	if (pbKeyIn != NULL) {
+		CHECK_CONDITION(cbitKey / 8 == cbKeyIn, COSE_ERR_INVALID_PARAMETER);
+		pbKey = pbKeyIn;
 	}
+	else {
+		if (pbKey == NULL) {
+			pbKey = COSE_CALLOC(cbitKey / 8, 1, context);
+			CHECK_CONDITION(pbKey != NULL, COSE_ERR_OUT_OF_MEMORY);
+		}
 
-	//  If there is a recipient - ask it for the key
+		//  If there is a recipient - ask it for the key
 
-	for (pRecip = pcose->m_recipientFirst; pRecip != NULL; pRecip = pRecip->m_recipientNext) {
-		if (_COSE_Recipient_decrypt(pRecip, NULL, alg, cbitKey, pbKey, perr)) break;
+		if (pRecip != NULL) {
+			COSE_RecipientInfo * pRecipX;
+
+			for (pRecipX = pcose->m_recipientFirst; pRecipX != NULL; pRecipX = pRecipX->m_recipientNext) {
+				if (pRecip == pRecipX) {
+					if (!_COSE_Recipient_decrypt(pRecipX, pRecip, alg, cbitKey, pbKey, perr)) goto errorReturn;
+					break;
+				}
+				else if (pRecipX->m_recipientNext != NULL) {
+					if (_COSE_Recipient_decrypt(pRecipX, pRecip, alg, cbitKey, pbKey, perr)) break;
+				}
+			}
+			CHECK_CONDITION(pRecipX != NULL, COSE_ERR_NO_RECIPIENT_FOUND);
+		}
+		else {
+			for (pRecip = pcose->m_recipientFirst; pRecip != NULL; pRecip = pRecip->m_recipientNext) {
+				if (_COSE_Recipient_decrypt(pRecip, NULL, alg, cbitKey, pbKey, perr)) break;
+			}
+			CHECK_CONDITION(pRecip != NULL, COSE_ERR_NO_RECIPIENT_FOUND);
+		}
 	}
-	CHECK_CONDITION(pRecip != NULL, COSE_ERR_NO_RECIPIENT_FOUND);
-
-	//  Build protected headers
-
-	cn_cbor * cnProtected = _COSE_arrayget_int(&pcose->m_message, INDEX_PROTECTED);
-	CHECK_CONDITION((cnProtected != NULL) && (cnProtected->type == CN_CBOR_BYTES), COSE_ERR_INVALID_PARAMETER);
 
 	//  Build authenticated data
 
-	if (!_COSE_Mac_Build_AAD(&pcose->m_message, "MAC", &pbAuthData, &cbAuthData, CBOR_CONTEXT_PARAM_COMMA perr)) goto errorReturn;
+	if (!_COSE_Mac_Build_AAD(&pcose->m_message, szContext, &pbAuthData, &cbAuthData, CBOR_CONTEXT_PARAM_COMMA perr)) goto errorReturn;
 
 	switch (alg) {
 #ifdef USE_HMAC_256_256
@@ -655,7 +692,7 @@
 	fRet = true;
 
 errorReturn:
-	if ((pbKey != NULL)) {
+	if ((pbKey != NULL) && (pbKey != pbKeyIn)) {
 		memset(pbKey, 0xff, cbitKey / 8);
 		COSE_FREE(pbKey, context);
 	}
diff --git a/src/MacMessage0.c b/src/MacMessage0.c
index 11a6542..43df47b 100644
--- a/src/MacMessage0.c
+++ b/src/MacMessage0.c
@@ -200,232 +200,169 @@
 
 bool COSE_Mac0_encrypt(HCOSE_MAC0 h, const byte * pbKey, size_t cbKey, cose_errback * perr)
 {
-	int alg;
-	const cn_cbor * cn_Alg = NULL;
-	byte * pbAuthData = NULL;
-	size_t cbitKey;
-#ifdef USE_CBOR_CONTEXT
-	cn_cbor_context * context = NULL;
-#endif
 	COSE_Mac0Message * pcose = (COSE_Mac0Message *)h;
-	bool fRet = false;
-	size_t cbAuthData;
 
-	CHECK_CONDITION(IsValidMac0Handle(h), COSE_ERR_INVALID_PARAMETER);
+	CHECK_CONDITION(IsValidMac0Handle(h), COSE_ERR_INVALID_HANDLE);
+	CHECK_CONDITION(pbKey != NULL, COSE_ERR_INVALID_PARAMETER);
 
-#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, perr);
-	if (cn_Alg == NULL) goto errorReturn;
-	CHECK_CONDITION(cn_Alg->type != CN_CBOR_TEXT, COSE_ERR_UNKNOWN_ALGORITHM);
-	CHECK_CONDITION(((cn_Alg->type == CN_CBOR_UINT || cn_Alg->type == CN_CBOR_INT)), COSE_ERR_INVALID_PARAMETER);
-
-	alg = (int) cn_Alg->v.uint;
-
-	//  Get the key size
-
-	switch (alg) {
-#ifdef USE_AES_CBC_MAC_128_64
-	case COSE_Algorithm_CBC_MAC_128_64:
-		cbitKey = 128;
-		break;
-#endif
-
-#ifdef USE_AES_CBC_MAC_128_128
-	case COSE_Algorithm_CBC_MAC_128_128:
-		cbitKey = 128;
-		break;
-#endif
-
-#ifdef USE_AES_CBC_MAC_256_64
-	case COSE_Algorithm_CBC_MAC_256_64: 
-		cbitKey = 256; 
-		break;
-#endif
-
-#ifdef USE_AES_CBC_MAC_256_128
-	case COSE_Algorithm_CBC_MAC_256_128: 
-		cbitKey = 256; 
-		break;
-#endif
-
-#ifdef USE_HMAC_256_64
-	case COSE_Algorithm_HMAC_256_64: 
-		cbitKey = 256; 
-		break;
-#endif
-
-#ifdef USE_HMAC_256_256
-	case COSE_Algorithm_HMAC_256_256: 
-		cbitKey = 256; 
-		break;
-#endif
-
-#ifdef USE_HMAC_384_384
-	case COSE_Algorithm_HMAC_384_384: 
-		cbitKey = 384; 
-		break;
-#endif
-
-#ifdef USE_HMAC_512_512
-	case COSE_Algorithm_HMAC_512_512: 
-		cbitKey = 512; 
-		break;
-#endif
-
-	default:
-		FAIL_CONDITION(COSE_ERR_UNKNOWN_ALGORITHM);
-	}
-
-	//  Build protected headers
-
-	const cn_cbor * cbProtected = _COSE_encode_protected(&pcose->m_message, perr);
-	if (cbProtected == NULL) goto errorReturn;
-
-	//  Build authenticated data
-	if (!_COSE_Mac_Build_AAD(&pcose->m_message, "MAC0", &pbAuthData, &cbAuthData, CBOR_CONTEXT_PARAM_COMMA perr)) goto errorReturn;
-
-	switch (alg) {
-#ifdef USE_AES_CBC_MAC_128_64
-	case COSE_Algorithm_CBC_MAC_128_64:
-		if (!AES_CBC_MAC_Create((COSE_MacMessage *)pcose, 64, pbKey, cbKey, pbAuthData, cbAuthData, perr)) goto errorReturn;
-		break;
-#endif
-
-#ifdef USE_AES_CBC_MAC_256_64
-	case COSE_Algorithm_CBC_MAC_256_64:
-		if (!AES_CBC_MAC_Create((COSE_MacMessage *)pcose, 64, pbKey, cbKey, pbAuthData, cbAuthData, perr)) goto errorReturn;
-		break;
-#endif
-
-#ifdef USE_AES_CBC_MAC_128_128
-	case COSE_Algorithm_CBC_MAC_128_128:
-		if (!AES_CBC_MAC_Create((COSE_MacMessage *)pcose, 128, pbKey, cbKey, pbAuthData, cbAuthData, perr)) goto errorReturn;
-		break;
-#endif
-
-#ifdef USE_AES_CBC_MAC_256_128
-	case COSE_Algorithm_CBC_MAC_256_128:
-		if (!AES_CBC_MAC_Create((COSE_MacMessage *)pcose, 128, pbKey, cbKey, pbAuthData, cbAuthData, perr)) goto errorReturn;
-		break;
-#endif
-
-#ifdef USE_HMAC_256_64
-	case COSE_Algorithm_HMAC_256_64:
-		if (!HMAC_Create((COSE_MacMessage *)pcose, 256, 64, pbKey, cbKey, pbAuthData, cbAuthData, perr)) goto errorReturn;
-		break;
-#endif
-
-#ifdef USE_HMAC_256_256
-	case COSE_Algorithm_HMAC_256_256:
-		if (!HMAC_Create((COSE_MacMessage *)pcose, 256, 256, pbKey, cbKey, pbAuthData, cbAuthData, perr)) goto errorReturn;
-		break;
-#endif
-
-#ifdef USE_HMAC_384_384
-	case COSE_Algorithm_HMAC_384_384:
-		if (!HMAC_Create((COSE_MacMessage *)pcose, 384, 384, pbKey, cbKey, pbAuthData, cbAuthData, perr)) goto errorReturn;
-		break;
-#endif
-
-#ifdef USE_HMAC_512_512
-	case COSE_Algorithm_HMAC_512_512:
-		if (!HMAC_Create((COSE_MacMessage *)pcose, 512, 512, pbKey, cbKey, pbAuthData, cbAuthData, perr)) goto errorReturn;
-		break;
-#endif
-
-	default:
-		FAIL_CONDITION(COSE_ERR_INVALID_PARAMETER);
-	}
-
-	//  Figure out the clean up
-
-	fRet = true;
+	return _COSE_Mac_compute(pcose, pbKey, cbKey, "MAC0", perr);
 
 errorReturn:
-	if (pbAuthData != NULL) COSE_FREE(pbAuthData, context);
-	return fRet;
+	return false;
 }
 
 bool COSE_Mac0_validate(HCOSE_MAC0 h, const byte * pbKey, size_t cbKey, cose_errback * perr)
 {
 	COSE_Mac0Message * pcose = (COSE_Mac0Message *)h;
-	byte * pbAuthData = NULL;
-	int cbitKey = 0;
-	bool fRet = false;
-	int alg;
-	const cn_cbor * cn = NULL;
+	CHECK_CONDITION(IsValidMac0Handle(h), COSE_ERR_INVALID_HANDLE);
+	CHECK_CONDITION(pbKey != NULL, COSE_ERR_INVALID_PARAMETER);
+
+	return _COSE_Mac_validate(pcose, NULL, pbKey, cbKey, "MAC0", perr);
+
+errorReturn:
+	return false;
+}
+
+#if 0
+	int foo() {
+		COSE_Mac0Message * pcose = (COSE_Mac0Message *)h;
+		byte * pbAuthData = NULL;
+		int cbitKey = 0;
+		bool fRet = false;
+		int alg;
+		const cn_cbor * cn = NULL;
 
 #ifdef USE_CBOR_CONTEXT
-	cn_cbor_context * context = NULL;
+		cn_cbor_context * context = NULL;
 #endif
-	size_t cbAuthData;
+		size_t cbAuthData;
 
-	CHECK_CONDITION(IsValidMac0Handle(h), COSE_ERR_INVALID_PARAMETER);
+		CHECK_CONDITION(IsValidMac0Handle(h), COSE_ERR_INVALID_PARAMETER);
 
 #ifdef USE_CBOR_CONTEXT
-	context = &pcose->m_message.m_allocContext;
+		context = &pcose->m_message.m_allocContext;
 #endif
 
-	cn = _COSE_map_get_int(&pcose->m_message, COSE_Header_Algorithm, COSE_BOTH, perr);
-	if (cn == NULL) goto errorReturn;
+		cn = _COSE_map_get_int(&pcose->m_message, COSE_Header_Algorithm, COSE_BOTH, perr);
+		if (cn == NULL) goto errorReturn;
 
-	if (cn->type == CN_CBOR_TEXT) {
+		if (cn->type == CN_CBOR_TEXT) {
 			FAIL_CONDITION(COSE_ERR_UNKNOWN_ALGORITHM);
-	}
-	else {
-		CHECK_CONDITION((cn->type == CN_CBOR_UINT || cn->type == CN_CBOR_INT), COSE_ERR_INVALID_PARAMETER);
+		}
+		else {
+			CHECK_CONDITION((cn->type == CN_CBOR_UINT || cn->type == CN_CBOR_INT), COSE_ERR_INVALID_PARAMETER);
 
-		alg = (int)cn->v.uint;
+			alg = (int)cn->v.uint;
+
+			switch (alg) {
+#ifdef USE_AES_CBC_MAC_128_64
+			case COSE_Algorithm_CBC_MAC_128_64:
+				cbitKey = 128;
+				break;
+#endif
+
+#ifdef USE_AES_CBC_MAC_128_128
+			case COSE_Algorithm_CBC_MAC_128_128:
+				cbitKey = 128;
+				break;
+#endif
+
+#ifdef USE_AES_CBC_MAC_256_64
+			case COSE_Algorithm_CBC_MAC_256_64:
+				cbitKey = 256;
+				break;
+#endif
+
+#ifdef USE_AES_CBC_MAC_256_128
+			case COSE_Algorithm_CBC_MAC_256_128:
+				cbitKey = 256;
+				break;
+#endif
+
+#ifdef USE_HMAC_256_64
+			case COSE_Algorithm_HMAC_256_64:
+				cbitKey = 256;
+				break;
+#endif
+
+#ifdef USE_HMAC_256_256
+			case COSE_Algorithm_HMAC_256_256:
+				cbitKey = 256;
+				break;
+#endif
+
+#ifdef USE_HMAC_384_384
+			case COSE_Algorithm_HMAC_384_384:
+				cbitKey = 384;
+				break;
+#endif
+
+#ifdef USE_HMAC_512_512
+			case COSE_Algorithm_HMAC_512_512:
+				cbitKey = 512;
+				break;
+#endif
+
+			default:
+				FAIL_CONDITION(COSE_ERR_UNKNOWN_ALGORITHM);
+				break;
+			}
+		}
+
+		//  Build protected headers
+
+		cn_cbor * cnProtected = _COSE_arrayget_int(&pcose->m_message, INDEX_PROTECTED);
+		CHECK_CONDITION((cnProtected != NULL) && (cnProtected->type == CN_CBOR_BYTES), COSE_ERR_INVALID_PARAMETER);
+
+		//  Build authenticated data
+		if (!_COSE_Mac_Build_AAD(&pcose->m_message, "MAC0", &pbAuthData, &cbAuthData, CBOR_CONTEXT_PARAM_COMMA perr)) goto errorReturn;
 
 		switch (alg) {
+#ifdef USE_HMAC_256_256
+		case COSE_Algorithm_HMAC_256_256:
+			if (!HMAC_Validate((COSE_MacMessage *)pcose, 256, 256, pbKey, cbKey, pbAuthData, cbAuthData, perr)) goto errorReturn;
+			break;
+#endif
+
+#ifdef USE_HMAC_256_64
+		case COSE_Algorithm_HMAC_256_64:
+			if (!HMAC_Validate((COSE_MacMessage *)pcose, 256, 64, pbKey, cbKey, pbAuthData, cbAuthData, perr)) goto errorReturn;
+			break;
+#endif
+
+#ifdef USE_HMAC_384_384
+		case COSE_Algorithm_HMAC_384_384:
+			if (!HMAC_Validate((COSE_MacMessage *)pcose, 384, 384, pbKey, cbKey, pbAuthData, cbAuthData, perr)) goto errorReturn;
+			break;
+#endif
+
+#ifdef USE_HMAC_512_512
+		case COSE_Algorithm_HMAC_512_512:
+			if (!HMAC_Validate((COSE_MacMessage *)pcose, 512, 512, pbKey, cbKey, pbAuthData, cbAuthData, perr)) goto errorReturn;
+			break;
+#endif
+
 #ifdef USE_AES_CBC_MAC_128_64
 		case COSE_Algorithm_CBC_MAC_128_64:
-			cbitKey = 128;
+			if (!AES_CBC_MAC_Validate((COSE_MacMessage *)pcose, 64, pbKey, cbKey, pbAuthData, cbAuthData, perr)) goto errorReturn;
+			break;
+#endif
+
+#ifdef USE_AES_CBC_MAC_256_64
+		case COSE_Algorithm_CBC_MAC_256_64:
+			if (!AES_CBC_MAC_Validate((COSE_MacMessage *)pcose, 64, pbKey, cbKey, pbAuthData, cbAuthData, perr)) goto errorReturn;
 			break;
 #endif
 
 #ifdef USE_AES_CBC_MAC_128_128
 		case COSE_Algorithm_CBC_MAC_128_128:
-			cbitKey = 128;
-			break;
-#endif
-
-#ifdef USE_AES_CBC_MAC_256_64
-		case COSE_Algorithm_CBC_MAC_256_64: 
-			cbitKey = 256; 
+			if (!AES_CBC_MAC_Validate((COSE_MacMessage *)pcose, 128, pbKey, cbKey, pbAuthData, cbAuthData, perr)) goto errorReturn;
 			break;
 #endif
 
 #ifdef USE_AES_CBC_MAC_256_128
-		case COSE_Algorithm_CBC_MAC_256_128: 
-			cbitKey = 256; 
-			break;
-#endif
-
-#ifdef USE_HMAC_256_64
-		case COSE_Algorithm_HMAC_256_64: 
-			cbitKey = 256; 
-			break;
-#endif
-
-#ifdef USE_HMAC_256_256
-		case COSE_Algorithm_HMAC_256_256: 
-			cbitKey = 256; 
-			break;
-#endif
-
-#ifdef USE_HMAC_384_384
-		case COSE_Algorithm_HMAC_384_384: 
-			cbitKey = 384; 
-			break;
-#endif
-
-#ifdef USE_HMAC_512_512
-		case COSE_Algorithm_HMAC_512_512: 
-			cbitKey = 512; 
+		case COSE_Algorithm_CBC_MAC_256_128:
+			if (!AES_CBC_MAC_Validate((COSE_MacMessage *)pcose, 128, pbKey, cbKey, pbAuthData, cbAuthData, perr)) goto errorReturn;
 			break;
 #endif
 
@@ -433,74 +370,13 @@
 			FAIL_CONDITION(COSE_ERR_UNKNOWN_ALGORITHM);
 			break;
 		}
+
+		fRet = true;
+
+	errorReturn:
+		if (pbAuthData != NULL) COSE_FREE(pbAuthData, context);
+
+		return fRet;
 	}
 
-	//  Build protected headers
-
-	cn_cbor * cnProtected = _COSE_arrayget_int(&pcose->m_message, INDEX_PROTECTED);
-	CHECK_CONDITION((cnProtected != NULL) && (cnProtected->type == CN_CBOR_BYTES), COSE_ERR_INVALID_PARAMETER);
-
-	//  Build authenticated data
-	if (!_COSE_Mac_Build_AAD(&pcose->m_message, "MAC0", &pbAuthData, &cbAuthData, CBOR_CONTEXT_PARAM_COMMA perr)) goto errorReturn;
-
-	switch (alg) {
-#ifdef USE_HMAC_256_256
-	case COSE_Algorithm_HMAC_256_256:
-		if (!HMAC_Validate((COSE_MacMessage *)pcose, 256, 256, pbKey, cbKey, pbAuthData, cbAuthData, perr)) goto errorReturn;
-		break;
-#endif
-
-#ifdef USE_HMAC_256_64
-	case COSE_Algorithm_HMAC_256_64:
-		if (!HMAC_Validate((COSE_MacMessage *)pcose, 256, 64, pbKey, cbKey, pbAuthData, cbAuthData, perr)) goto errorReturn;
-		break;
-#endif
-
-#ifdef USE_HMAC_384_384
-	case COSE_Algorithm_HMAC_384_384:
-		if (!HMAC_Validate((COSE_MacMessage *)pcose, 384, 384, pbKey, cbKey, pbAuthData, cbAuthData, perr)) goto errorReturn;
-		break;
-#endif
-
-#ifdef USE_HMAC_512_512
-	case COSE_Algorithm_HMAC_512_512:
-		if (!HMAC_Validate((COSE_MacMessage *)pcose, 512, 512, pbKey, cbKey, pbAuthData, cbAuthData, perr)) goto errorReturn;
-		break;
-#endif
-
-#ifdef USE_AES_CBC_MAC_128_64
-	case COSE_Algorithm_CBC_MAC_128_64:
-		if (!AES_CBC_MAC_Validate((COSE_MacMessage *)pcose, 64, pbKey, cbKey, pbAuthData, cbAuthData, perr)) goto errorReturn;
-		break;
-#endif
-
-#ifdef USE_AES_CBC_MAC_256_64
-	case COSE_Algorithm_CBC_MAC_256_64:
-		if (!AES_CBC_MAC_Validate((COSE_MacMessage *)pcose, 64, pbKey, cbKey, pbAuthData, cbAuthData, perr)) goto errorReturn;
-		break;
-#endif
-
-#ifdef USE_AES_CBC_MAC_128_128
-	case COSE_Algorithm_CBC_MAC_128_128:
-		if (!AES_CBC_MAC_Validate((COSE_MacMessage *)pcose, 128, pbKey, cbKey, pbAuthData, cbAuthData, perr)) goto errorReturn;
-		break;
-#endif
-
-#ifdef USE_AES_CBC_MAC_256_128
-	case COSE_Algorithm_CBC_MAC_256_128:
-		if (!AES_CBC_MAC_Validate((COSE_MacMessage *)pcose, 128, pbKey, cbKey, pbAuthData, cbAuthData, perr)) goto errorReturn;
-		break;
-#endif
-
-	default:
-		FAIL_CONDITION(COSE_ERR_UNKNOWN_ALGORITHM);
-		break;
-	}
-
-	fRet = true;
-
-errorReturn:
-	if (pbAuthData != NULL) COSE_FREE(pbAuthData, context);
-
-	return fRet;
-}
+#endif
\ No newline at end of file
diff --git a/src/cose_int.h b/src/cose_int.h
index 367c7c8..4fc9254 100644
--- a/src/cose_int.h
+++ b/src/cose_int.h
@@ -72,9 +72,12 @@
 	COSE_RecipientInfo * m_recipientFirst;
 } COSE_MacMessage;
 
+#if 0
 typedef struct {
 	COSE m_message;			// The message object
 } COSE_Mac0Message;
+#endif
+typedef COSE_MacMessage COSE_Mac0Message;
 
 #ifdef USE_CBOR_CONTEXT
 /**
@@ -194,6 +197,8 @@
 extern HCOSE_MAC _COSE_Mac_Init_From_Object(cn_cbor *, COSE_MacMessage * pIn, CBOR_CONTEXT_COMMA cose_errback * errp);
 extern bool _COSE_Mac_Release(COSE_MacMessage * p);
 extern bool _COSE_Mac_Build_AAD(COSE * pCose, char * szContext, byte ** ppbAuthData, size_t * pcbAuthData, CBOR_CONTEXT_COMMA cose_errback * perr);
+extern bool _COSE_Mac_compute(COSE_MacMessage * pcose, const byte * pbKeyIn, size_t cbKeyIn, const char * szContext, cose_errback * perr);
+extern bool _COSE_Mac_validate(COSE_MacMessage * pcose, COSE_RecipientInfo * pRecip, const byte * pbKeyIn, size_t cbKeyIn, const char * szContext, cose_errback * perr);
 
 //  MAC0 Items
 extern HCOSE_MAC0 _COSE_Mac0_Init_From_Object(cn_cbor *, COSE_Mac0Message * pIn, CBOR_CONTEXT_COMMA cose_errback * errp);