First pass of MAC working

Get one mac example to work.
diff --git a/src/Encrypt.c b/src/Encrypt.c
index 9f98d2c..561b4d8 100644
--- a/src/Encrypt.c
+++ b/src/Encrypt.c
@@ -1,6 +1,7 @@
 #include <stdlib.h>
 #include <memory.h>
 #include <stdio.h>
+#include <assert.h>
 
 #include "cose.h"
 #include "cose_int.h"
@@ -20,8 +21,8 @@
 
 size_t COSE_Encode(HCOSE msg, byte * rgb, int ib, size_t cb)
 {
-	if (rgb == NULL) return cbor_encoder_write(RgbDontUse, 0, sizeof(RgbDontUse), ((COSE *)msg)->m_cbor) + ib;
-	return cbor_encoder_write(rgb, ib, cb, ((COSE*)msg)->m_cbor);
+	if (rgb == NULL) return cn_cbor_encoder_write(RgbDontUse, 0, sizeof(RgbDontUse), ((COSE *)msg)->m_cbor) + ib;
+	return cn_cbor_encoder_write(rgb, ib, cb, ((COSE*)msg)->m_cbor);
 }
 
 HCOSE_ENCRYPT COSE_Encrypt_Init(CBOR_CONTEXT_COMMA cose_errback * perror)
@@ -46,32 +47,46 @@
 	return (HCOSE_ENCRYPT) pobj;
 }
 
-HCOSE_ENCRYPT _COSE_Encrypt_Init_From_Object(cn_cbor * cbor, COSE_Encrypt * pIn, CBOR_CONTEXT_COMMA cose_errback * errp)
+HCOSE_ENCRYPT _COSE_Encrypt_Init_From_Object(cn_cbor * cbor, COSE_Encrypt * pIn, CBOR_CONTEXT_COMMA cose_errback * perr)
 {
 	COSE_Encrypt * pobj = pIn;
 	cn_cbor * pRecipients = NULL;
+	cn_cbor * tmp;
+	cose_errback error = { 0 };
+	if (perr == NULL) perr = &error;
 
 	if (pobj == NULL) pobj = (COSE_Encrypt *)COSE_CALLOC(1, sizeof(COSE_Encrypt), context);
 	if (pobj == NULL) {
-		if (errp != NULL) errp->err = COSE_ERR_OUT_OF_MEMORY;
+		perr->err = COSE_ERR_OUT_OF_MEMORY;
+	errorReturn:
+		if ((pIn == NULL) && (pobj != NULL)) COSE_FREE(pobj, context);
 		return NULL;
 	}
 
-	if (!_COSE_Init_From_Object(&pobj->m_message, cbor, CBOR_CONTEXT_PARAM_COMMA errp)) {
-		return NULL;
+	if (!_COSE_Init_From_Object(&pobj->m_message, cbor, CBOR_CONTEXT_PARAM_COMMA perr)) {
+		goto errorReturn;
+	}
+
+	tmp = cn_cbor_mapget_int(cbor, COSE_Header_Ciphertext);
+	if (tmp != NULL) {
+		CHECK_CONDITION(tmp->type == CN_CBOR_BYTES, COSE_ERR_INVALID_PARAMETER);
+		pobj->cbContent = tmp->length;
+		pobj->pbContent = tmp->v.str;
 	}
 
 	pRecipients = (cn_cbor *) cn_cbor_mapget_int(cbor, COSE_Header_Recipients);
-	while (pRecipients != NULL) {
-		COSE_RecipientInfo * pInfo = _COSE_Recipient_Init_From_Object(pRecipients, CBOR_CONTEXT_PARAM_COMMA errp);
-		if (pInfo == NULL) {
-			if (pIn == NULL) COSE_Encrypt_Free((HCOSE_ENCRYPT) pobj);
-			return NULL;
-		}
+	if (pRecipients != NULL) {
+		CHECK_CONDITION(pRecipients->type == CN_CBOR_ARRAY, COSE_ERR_INVALID_PARAMETER);
 
-		pInfo->m_recipientNext = pobj->m_recipientFirst;
-		pobj->m_recipientFirst = pInfo;
-		pRecipients = pRecipients->next;
+		pRecipients = pRecipients->first_child;
+		while (pRecipients != NULL) {
+			COSE_RecipientInfo * pInfo = _COSE_Recipient_Init_From_Object(pRecipients, CBOR_CONTEXT_PARAM_COMMA perr);
+			CHECK_CONDITION(pInfo != NULL, COSE_ERR_OUT_OF_MEMORY);
+
+			pInfo->m_recipientNext = pobj->m_recipientFirst;
+			pobj->m_recipientFirst = pInfo;
+			pRecipients = pRecipients->next;
+		}
 	}
 
 	return(HCOSE_ENCRYPT) pobj;
@@ -186,23 +201,25 @@
 {
 	COSE_Encrypt * pcose = (COSE_Encrypt *)h;
 	COSE_RecipientInfo * pRecip = (COSE_RecipientInfo *)hRecip;
+	cose_errback error = { 0 };
+	bool f;
 
 	if (!IsValidEncryptHandle(h) || (!IsValidRecipientHandle(hRecip))) {
 		if (perr != NULL) perr->err = COSE_ERR_INVALID_PARAMETER;
 		return false;
 	}
 
-	return _COSE_Encrypt_decrypt(pcose, pRecip, perr);
+	f = _COSE_Encrypt_decrypt(pcose, pRecip, 0, NULL, &error);
+	if (perr != NULL) *perr = error;
+	return f;
 }
 
-bool _COSE_Encrypt_decrypt(COSE_Encrypt * pcose, COSE_RecipientInfo * pRecip, cose_errback * perr)
+bool _COSE_Encrypt_decrypt(COSE_Encrypt * pcose, COSE_RecipientInfo * pRecip, int cbitKey, byte *pbKeyIn, cose_errback * perr)
 {
 	int alg;
-	int cbitKey;
 	const cn_cbor * cn = NULL;
-	cose_errback error = { 0 };
 
-	byte * pbKey = NULL;
+	byte * pbKey = pbKeyIn;
 	cn_cbor_context * context;
 	byte * pbAuthData = NULL;
 	ssize_t cbAuthData;
@@ -211,52 +228,65 @@
 	ssize_t cbProtected;
 	cn_cbor * ptmp = NULL;
 
+	assert(perr != NULL);
+
 #ifdef USE_CBOR_CONTEXT
 	context = &pcose->m_message.m_allocContext;
 #endif
 
-	cn = _COSE_map_get_int(&pcose->m_message, COSE_Header_Algorithm, COSE_BOTH, &error);
-
+	cn = _COSE_map_get_int(&pcose->m_message, COSE_Header_Algorithm, COSE_BOTH, perr);
 	if (cn == NULL) {
 	error:
+	errorReturn:
 		if (pbProtected != NULL) COSE_FREE(pbProtected, context);
 		if (pbAuthData != NULL) COSE_FREE(pbAuthData, context);
 		if (pAuthData != NULL) cn_cbor_free(pAuthData CBOR_CONTEXT_PARAM);
-		if (pbKey != NULL) COSE_FREE(pbKey, context);
-		if (perr != NULL) *perr = error;
+		if ((pbKey != NULL) && (pbKeyIn == NULL)) {
+			memset(pbKey, 0xff, cbitKey / 8);
+			COSE_FREE(pbKey, context);
+		}
 		return false;
 	}
-	if (cn->type != CN_CBOR_UINT) goto error;
+	CHECK_CONDITION(cn->type == CN_CBOR_UINT, CN_CBOR_ERR_INVALID_PARAMETER);
 	alg = cn->v.uint;
 
 	switch (alg) {
-	case COSE_Algorithm_AES_CCM_64:
+	case COSE_Algorithm_AES_CCM_16_64_128:
+	case COSE_Algorithm_AES_CCM_16_128_128:
+	case COSE_Algorithm_AES_CCM_64_64_128:
+	case COSE_Algorithm_AES_CCM_64_128_128:
 		cbitKey = 128;
 		break;
 
+	case COSE_Algorithm_Direct:
+		CHECK_CONDITION(pcose->cbKey == cbitKey / 8, COSE_ERR_INVALID_PARAMETER);
+		break;
+
 	default:
-		error.err = COSE_ERR_UNKNOWN_ALGORITHM;
-		goto error;
+		CHECK_CONDITION(false, COSE_ERR_UNKNOWN_ALGORITHM);
+		break;
 	}
 
-	pbKey = COSE_CALLOC(cbitKey / 8, 1, context);
+	//  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 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, cbitKey, pbKey, &error)) break;
-	}
-
-	if (pRecip == NULL) {
-		error.err = COSE_ERR_NO_RECIPIENT_FOUND;
-		goto error;
+		if (_COSE_Recipient_decrypt(pRecip, cbitKey, pbKey, perr)) break;
 	}
 
 	//  Build protected headers
 
-	if (pcose->m_message.m_protectedMap->first_child != NULL) {
-		cbProtected = cbor_encoder_write(RgbDontUse, 0, sizeof(RgbDontUse), pcose->m_message.m_protectedMap);
+	if ((pcose->m_message.m_protectedMap != NULL) && (pcose->m_message.m_protectedMap->first_child != NULL)) {
+		cbProtected = cn_cbor_encoder_write(RgbDontUse, 0, sizeof(RgbDontUse), pcose->m_message.m_protectedMap);
 		pbProtected = (byte *)COSE_CALLOC(cbProtected, 1, context);
 		if (pbProtected == NULL) goto error;
-		if (cbor_encoder_write(pbProtected, 0, cbProtected, pcose->m_message.m_protectedMap) != cbProtected) goto error;
+		if (cn_cbor_encoder_write(pbProtected, 0, cbProtected, pcose->m_message.m_protectedMap) != cbProtected) goto error;
 		if (!cn_cbor_mapput_int(pcose->m_message.m_cbor, COSE_Header_Protected, cn_cbor_data_create(pbProtected, cbProtected, CBOR_CONTEXT_PARAM_COMMA NULL), CBOR_CONTEXT_PARAM_COMMA NULL)) goto error;
 	}
 	else {
@@ -269,32 +299,43 @@
 	pAuthData = cn_cbor_array_create(CBOR_CONTEXT_PARAM_COMMA NULL);
 
 	ptmp = cn_cbor_data_create(pbProtected, cbProtected, CBOR_CONTEXT_PARAM_COMMA NULL);
-	if (ptmp == NULL) goto error;
+	CHECK_CONDITION(ptmp != NULL, COSE_ERR_CBOR);
 	cn_cbor_array_append(pAuthData, ptmp, NULL);
 	pbProtected = NULL;
 
 	ptmp = cn_cbor_data_create(NULL, 0, CBOR_CONTEXT_PARAM_COMMA NULL);
-	if (ptmp == NULL) goto error;
+	CHECK_CONDITION(ptmp != NULL, COSE_ERR_CBOR);
 	cn_cbor_array_append(pAuthData, ptmp, NULL);
 
-	cbAuthData = cbor_encoder_write(RgbDontUse, 0, sizeof(RgbDontUse), pAuthData);
+	cbAuthData = cn_cbor_encoder_write(RgbDontUse, 0, sizeof(RgbDontUse), pAuthData);
 	pbAuthData = (byte *)COSE_CALLOC(cbAuthData, 1, context);
-	if (pbAuthData == NULL) goto error;
-	if (cbor_encoder_write(pbAuthData, 0, cbAuthData, pAuthData) != cbAuthData) goto error;
+	CHECK_CONDITION(pbAuthData != NULL, COSE_ERR_OUT_OF_MEMORY);
+	CHECK_CONDITION((cn_cbor_encoder_write(pbAuthData, 0, cbAuthData, pAuthData) == cbAuthData), COSE_ERR_CBOR);
 
 	switch (alg) {
-	case COSE_Algorithm_AES_CCM_64:
-		if (!AES_CCM_Decrypt(pcose, 8, 8, pbAuthData, cbAuthData)) {
-			error.err = COSE_ERR_DECRYPT_FAILED;
+	case COSE_Algorithm_AES_CCM_64_64_128:
+	case COSE_Algorithm_AES_CCM_64_64_256:
+		if (!AES_CCM_Decrypt(pcose, 8, 8, pbKey, cbitKey/8, pbAuthData, cbAuthData, perr)) {
 			goto error;
 		}
 		break;
 
+	case COSE_Algorithm_Direct:
+		CHECK_CONDITION((pcose->cbKey == cbitKey / 8),  COSE_ERR_INVALID_PARAMETER);
+		memcpy(pbKey, pcose->pbKey, pcose->cbKey);
+		break;
+
 	default:
-		error.err = COSE_ERR_UNKNOWN_ALGORITHM;
-		goto error;
+		CHECK_CONDITION(false, COSE_ERR_UNKNOWN_ALGORITHM);
+		break;
 	}
 
+	if (pbProtected != NULL) COSE_FREE(pbProtected, context);
+	if (pbAuthData != NULL) COSE_FREE(pbAuthData, context);
+	if (pAuthData != NULL) cn_cbor_free(pAuthData CBOR_CONTEXT_PARAM);
+	if ((pbKey != NULL) && (pbKeyIn == NULL)) COSE_FREE(pbKey, context);
+	perr->err = COSE_ERR_NONE;
+
 	return true;
 }
 
@@ -333,13 +374,16 @@
 		if (perror != NULL) *perror = error;
 		return false;
 	}
-	if (cn_Alg->type != CN_CBOR_UINT) goto error;
+	if ((cn_Alg->type != CN_CBOR_UINT) && (cn_Alg->type != CN_CBOR_INT)) goto error;
 	alg = cn_Alg->v.uint;
 
 	//  Get the key size
 
 	switch (alg) {
-	case COSE_Algorithm_AES_CCM_64:
+	case COSE_Algorithm_AES_CCM_64_64_128:
+	case COSE_Algorithm_AES_CCM_16_128_128:
+	case COSE_Algorithm_AES_CCM_64_128_128:
+	case COSE_Algorithm_AES_CCM_16_64_128:
 		cbitKey = 128;
 		break;
 
@@ -382,10 +426,10 @@
 	//  Build protected headers
 
 	if (pcose->m_message.m_protectedMap->first_child != NULL) {
-		cbProtected = cbor_encoder_write(RgbDontUse, 0, sizeof(RgbDontUse), pcose->m_message.m_protectedMap);
+		cbProtected = cn_cbor_encoder_write(RgbDontUse, 0, sizeof(RgbDontUse), pcose->m_message.m_protectedMap);
 		pbProtected = (byte *) COSE_CALLOC(cbProtected, 1, context);
 		if (pbProtected == NULL) goto error;
-		if (cbor_encoder_write(pbProtected, 0, cbProtected, pcose->m_message.m_protectedMap) != cbProtected) goto error;
+		if (cn_cbor_encoder_write(pbProtected, 0, cbProtected, pcose->m_message.m_protectedMap) != cbProtected) goto error;
 		if (!cn_cbor_mapput_int(pcose->m_message.m_cbor, COSE_Header_Protected, cn_cbor_data_create(pbProtected, cbProtected, CBOR_CONTEXT_PARAM_COMMA NULL), CBOR_CONTEXT_PARAM_COMMA NULL)) goto error;
 	}
 	else {
@@ -415,15 +459,15 @@
 	cn_cbor_array_append(pAuthData, ptmp, NULL);
 	ptmp = NULL;
 
-	cbAuthData = cbor_encoder_write(RgbDontUse, 0, sizeof(RgbDontUse), pAuthData);
+	cbAuthData = cn_cbor_encoder_write(RgbDontUse, 0, sizeof(RgbDontUse), pAuthData);
 	pbAuthData = (byte *) COSE_CALLOC(cbAuthData, 1, context);
 	if (pbAuthData == NULL) goto error;
-	if (cbor_encoder_write(pbAuthData, 0, cbAuthData, pAuthData) != cbAuthData) goto error;
+	if (cn_cbor_encoder_write(pbAuthData, 0, cbAuthData, pAuthData) != cbAuthData) goto error;
 
 	switch (alg) {
 #ifdef INCLUDE_AES_CCM_64
-	case COSE_Algorithm_AES_CCM_64:
-		if (!AES_CCM_Encrypt(pcose, 64, 8, pbAuthData, cbAuthData)) goto error;
+	case COSE_Algorithm_AES_CCM_64_128_128:
+		if (!AES_CCM_Encrypt(pcose, 64, 8, pbAuthData, cbAuthData, perror)) goto error;
 		break;
 #endif