First pass Sign0 and Mac0 implement
diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt
index 1f5166d..44c09fe 100644
--- a/src/CMakeLists.txt
+++ b/src/CMakeLists.txt
@@ -5,8 +5,10 @@
 set ( cose_sources 
 	Cose.c
 	MacMessage.c
+        MacMessage0.c
 	openssl.c
 	Sign.c
+        Sign0.c
 	cbor.c
 	Encrypt.c
         Encrypt0.c
diff --git a/src/Cose.c b/src/Cose.c
index 23b40e3..a26d139 100644
--- a/src/Cose.c
+++ b/src/Cose.c
@@ -183,6 +183,13 @@
 		}
 		break;
 
+	case COSE_sign0_object:
+		h = (HCOSE)_COSE_Sign0_Init_From_Object(cborRoot, NULL, CBOR_CONTEXT_PARAM_COMMA perr);
+		if (h == NULL) {
+			goto errorReturn;
+		}
+		break;
+
 	case COSE_mac_object:
 		h = (HCOSE)_COSE_Mac_Init_From_Object(cbor, NULL, CBOR_CONTEXT_PARAM_COMMA perr);
 		if (h == NULL) {
@@ -190,6 +197,13 @@
 		}
 		break;
 
+	case COSE_mac0_object:
+		h = (HCOSE)_COSE_Mac0_Init_From_Object(cbor, NULL, CBOR_CONTEXT_PARAM_COMMA perr);
+		if (h == NULL) {
+			goto errorReturn;
+		}
+		break;
+
 	case COSE_encrypt_object:
 		h = (HCOSE)_COSE_Encrypt_Init_From_Object(cbor, NULL, CBOR_CONTEXT_PARAM_COMMA perr);
 		if (h == NULL) {
diff --git a/src/Encrypt.c b/src/Encrypt.c
index 26b0223..2440e14 100644
--- a/src/Encrypt.c
+++ b/src/Encrypt.c
@@ -15,7 +15,7 @@
 bool IsValidEnvelopedHandle(HCOSE_ENVELOPED h)
 {
 	COSE_Enveloped * p = (COSE_Enveloped *)h;
-	return _COSE_IsInList(EnvelopedRoot, p);
+	return _COSE_IsInList(EnvelopedRoot, &p->m_message);
 }
 
 
@@ -38,7 +38,7 @@
 		return NULL;
 	}
 
-	_COSE_InsertInList(&EnvelopedRoot, pobj);
+	_COSE_InsertInList(&EnvelopedRoot, &pobj->m_message);
 
 	return (HCOSE_ENVELOPED) pobj;
 }
@@ -77,7 +77,7 @@
 		}
 	}
 
-	if (pIn == NULL) _COSE_InsertInList(&EnvelopedRoot, pobj);
+	if (pIn == NULL) _COSE_InsertInList(&EnvelopedRoot, &pobj->m_message);
 
 	return(HCOSE_ENVELOPED) pobj;
 }
@@ -87,6 +87,7 @@
 #ifdef USE_CBOR_CONTEXT
 	cn_cbor_context context;
 #endif
+	COSE_Enveloped * p = (COSE_Enveloped *)h;
 
 	if (!IsValidEnvelopedHandle(h)) return false;
 
@@ -94,7 +95,7 @@
 	context = ((COSE_Enveloped *)h)->m_message.m_allocContext;
 #endif
 
-	_COSE_RemoveFromList(&EnvelopedRoot, (COSE_Enveloped *)h);
+	_COSE_RemoveFromList(&EnvelopedRoot, &p->m_message);
 
 	_COSE_Enveloped_Release((COSE_Enveloped *)h);
 
diff --git a/src/MacMessage.c b/src/MacMessage.c
index c1c3da2..ed287d9 100644
--- a/src/MacMessage.c
+++ b/src/MacMessage.c
@@ -237,7 +237,7 @@
 }
 
 
-bool COSE_Mac_map_put(HCOSE_MAC h, int key, cn_cbor * value, int flags, cose_errback * perror)
+bool COSE_Mac_map_put_int(HCOSE_MAC h, int key, cn_cbor * value, int flags, cose_errback * perror)
 {
 	if (!IsValidMacHandle(h) || (value == NULL)) {
 		if (perror != NULL) perror->err = COSE_ERR_INVALID_PARAMETER;
@@ -377,35 +377,29 @@
 
 	switch (alg) {
 	case COSE_Algorithm_CBC_MAC_128_64:
-		if (!AES_CBC_MAC_Create(pcose, 128, 64, pbAuthData, cbAuthData, perr)) goto errorReturn;
+	case COSE_Algorithm_CBC_MAC_256_64:
+		if (!AES_CBC_MAC_Create(pcose, 64, pcose->pbKey, pcose->cbKey, pbAuthData, cbAuthData, perr)) goto errorReturn;
 		break;
 
 	case COSE_Algorithm_CBC_MAC_128_128:
-		if (!AES_CBC_MAC_Create(pcose, 128, 128, pbAuthData, cbAuthData, perr)) goto errorReturn;
-		break;
-
-	case COSE_Algorithm_CBC_MAC_256_64:
-		if (!AES_CBC_MAC_Create(pcose, 256, 64, pbAuthData, cbAuthData, perr)) goto errorReturn;
-		break;
-
 	case COSE_Algorithm_CBC_MAC_256_128:
-		if (!AES_CBC_MAC_Create(pcose, 256, 128, pbAuthData, cbAuthData, perr)) goto errorReturn;
+		if (!AES_CBC_MAC_Create(pcose, 128, pcose->pbKey, pcose->cbKey, pbAuthData, cbAuthData, perr)) goto errorReturn;
 		break;
 
 	case COSE_Algorithm_HMAC_256_64:
-		if (!HMAC_Create(pcose, 256, 64, pbAuthData, cbAuthData, perr)) goto errorReturn;
+		if (!HMAC_Create(pcose, 256, 64, pcose->pbKey, pcose->cbKey, pbAuthData, cbAuthData, perr)) goto errorReturn;
 		break;
 
 	case COSE_Algorithm_HMAC_256_256:
-		if (!HMAC_Create(pcose, 256, 256, pbAuthData, cbAuthData, perr)) goto errorReturn;
+		if (!HMAC_Create(pcose, 256, 256, pcose->pbKey, pcose->cbKey, pbAuthData, cbAuthData, perr)) goto errorReturn;
 		break;
 
 	case COSE_Algorithm_HMAC_384_384:
-		if (!HMAC_Create(pcose, 384, 384, pbAuthData, cbAuthData, perr)) goto errorReturn;
+		if (!HMAC_Create(pcose, 384, 384, pcose->pbKey, pcose->cbKey, pbAuthData, cbAuthData, perr)) goto errorReturn;
 		break;
 
 	case COSE_Algorithm_HMAC_512_512:
-		if (!HMAC_Create(pcose, 512, 512, pbAuthData, cbAuthData, perr)) goto errorReturn;
+		if (!HMAC_Create(pcose, 512, 512, pcose->pbKey, pcose->cbKey, pbAuthData, cbAuthData, perr)) goto errorReturn;
 		break;
 
 	default:
diff --git a/src/MacMessage0.c b/src/MacMessage0.c
new file mode 100644
index 0000000..78f804a
--- /dev/null
+++ b/src/MacMessage0.c
@@ -0,0 +1,426 @@
+#include <stdlib.h>
+#include <memory.h>
+#include <stdio.h>
+#include <assert.h>
+#include <string.h>
+
+#include "cose.h"
+#include "cose_int.h"
+#include "configure.h"
+#include "crypto.h"
+
+byte RgbDontUse2[8 * 1024];   //  Remove this array when we can compute the size of a cbor serialization without this hack.
+
+
+bool IsValidMac0Handle(HCOSE_MAC0 h)
+{
+	COSE_Mac0Message * p = (COSE_Mac0Message *)h;
+	if (p == NULL) return false;
+	return true;
+}
+
+
+HCOSE_MAC0 COSE_Mac0_Init(CBOR_CONTEXT_COMMA cose_errback * perr)
+{
+	COSE_Mac0Message * pobj = (COSE_Mac0Message *)COSE_CALLOC(1, sizeof(COSE_Mac0Message), context);
+	CHECK_CONDITION(pobj != NULL, COSE_ERR_OUT_OF_MEMORY);
+
+	if (!_COSE_Init(&pobj->m_message, COSE_mac0_object, CBOR_CONTEXT_PARAM_COMMA perr)) {
+		goto errorReturn;
+	}
+
+	return (HCOSE_MAC0)pobj;
+
+errorReturn:
+	if (pobj != NULL) COSE_Mac0_Free((HCOSE_MAC0)pobj);
+	return NULL;
+}
+
+HCOSE_MAC0 _COSE_Mac0_Init_From_Object(cn_cbor * cbor, COSE_Mac0Message * pIn, CBOR_CONTEXT_COMMA cose_errback * perr)
+{
+	COSE_Mac0Message * pobj = pIn;
+	cn_cbor * pRecipients = NULL;
+	// cn_cbor * tmp;
+	cose_errback error = { COSE_ERR_NONE };
+	if (perr == NULL) perr = &error;
+
+	if (pobj == NULL) pobj = (COSE_Mac0Message *)COSE_CALLOC(1, sizeof(COSE_Mac0Message), context);
+	if (pobj == NULL) {
+		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 perr)) {
+		goto errorReturn;
+	}
+
+	pRecipients = _COSE_arrayget_int(&pobj->m_message, INDEX_MAC_RECIPIENTS);
+	CHECK_CONDITION(pRecipients == NULL, COSE_ERR_INVALID_PARAMETER);
+
+	return(HCOSE_MAC0)pobj;
+}
+
+bool COSE_Mac0_Free(HCOSE_MAC0 h)
+{
+#ifdef USE_CBOR_CONTEXT
+	cn_cbor_context context;
+#endif
+	COSE_Mac0Message * p = (COSE_Mac0Message *)h;
+
+	if (!IsValidMac0Handle(h)) return false;
+
+	if (p->m_message.m_refCount > 1) {
+		p->m_message.m_refCount--;
+		return true;
+	}
+
+#ifdef USE_CBOR_CONTEXT
+	context = ((COSE_Mac0Message *)h)->m_message.m_allocContext;
+#endif
+
+	_COSE_Mac0_Release((COSE_Mac0Message *)h);
+
+	COSE_FREE((COSE_Mac0Message *)h, &context);
+
+	return true;
+}
+
+bool _COSE_Mac0_Release(COSE_Mac0Message * p)
+{
+	_COSE_Release(&p->m_message);
+
+	return true;
+}
+
+bool COSE_Mac0_SetContent(HCOSE_MAC0 cose, const byte * rgbContent, size_t cbContent, cose_errback * perr)
+{
+	COSE_Mac0Message * p = (COSE_Mac0Message *)cose;
+#ifdef USE_CBOR_CONTEXT        
+	cn_cbor_context * context = &p->m_message.m_allocContext;
+#endif
+	cn_cbor * ptmp = NULL;
+	cn_cbor_errback cbor_error;
+
+	CHECK_CONDITION(IsValidMac0Handle(cose), COSE_ERR_INVALID_PARAMETER);
+
+	ptmp = cn_cbor_data_create(rgbContent, (int) cbContent, CBOR_CONTEXT_PARAM_COMMA &cbor_error);
+	CHECK_CONDITION_CBOR(ptmp != NULL, cbor_error);
+
+	CHECK_CONDITION_CBOR(_COSE_array_replace(&p->m_message, ptmp, INDEX_BODY, CBOR_CONTEXT_PARAM_COMMA &cbor_error),  cbor_error);
+	ptmp = NULL;
+
+	return true;
+
+errorReturn:
+	if (ptmp != NULL) CN_CBOR_FREE(ptmp, context);
+	return false;
+}
+
+
+cn_cbor * COSE_Mac0_map_get_int(HCOSE_MAC0 h, int key, int flags, cose_errback * perror)
+{
+	if (!IsValidMac0Handle(h)) {
+		if (perror != NULL) perror->err = COSE_ERR_INVALID_PARAMETER;
+		return NULL;
+	}
+
+	return _COSE_map_get_int(&((COSE_Mac0Message *)h)->m_message, key, flags, perror);
+}
+
+
+bool COSE_Mac0_map_put_int(HCOSE_MAC0 h, int key, cn_cbor * value, int flags, cose_errback * perror)
+{
+	if (!IsValidMac0Handle(h) || (value == NULL)) {
+		if (perror != NULL) perror->err = COSE_ERR_INVALID_PARAMETER;
+		return false;
+	}
+
+	return _COSE_map_put(&((COSE_Mac0Message *)h)->m_message, key, value, flags, perror);
+}
+
+
+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;
+	cn_cbor * pAuthData = NULL;
+	cn_cbor * ptmp = NULL;
+	size_t cbitKey;
+#ifdef USE_CBOR_CONTEXT
+	cn_cbor_context * context = NULL;
+#endif
+	COSE_Mac0Message * pcose = (COSE_Mac0Message *)h;
+	cn_cbor_errback cbor_error;
+
+	CHECK_CONDITION(IsValidMac0Handle(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_UINT || cn_Alg->type == CN_CBOR_INT)), COSE_ERR_INVALID_PARAMETER);
+
+	alg = (int) cn_Alg->v.uint;
+
+	//  Get the key size
+
+	switch (alg) {
+	case COSE_Algorithm_CBC_MAC_128_64:
+	case COSE_Algorithm_CBC_MAC_128_128:
+		cbitKey = 128;
+		break;
+
+	case COSE_Algorithm_CBC_MAC_256_64:
+	case COSE_Algorithm_CBC_MAC_256_128:
+	case COSE_Algorithm_HMAC_256_64:
+	case COSE_Algorithm_HMAC_256_256:
+		cbitKey = 256;
+		break;
+
+	case COSE_Algorithm_HMAC_384_384:
+		cbitKey = 384;
+		break;
+
+	case COSE_Algorithm_HMAC_512_512:
+		cbitKey = 512;
+		break;
+
+	default:
+		FAIL_CONDITION(COSE_ERR_INVALID_PARAMETER);
+	}
+
+	//  Build protected headers
+
+	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
+
+	size_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("MAC0", 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);
+
+	switch (alg) {
+	case COSE_Algorithm_CBC_MAC_128_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;
+
+	case COSE_Algorithm_CBC_MAC_128_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;
+
+	case COSE_Algorithm_HMAC_256_64:
+		if (!HMAC_Create((COSE_MacMessage *)pcose, 256, 64, pbKey, cbKey, pbAuthData, cbAuthData, perr)) goto errorReturn;
+		break;
+
+	case COSE_Algorithm_HMAC_256_256:
+		if (!HMAC_Create((COSE_MacMessage *)pcose, 256, 256, pbKey, cbKey, pbAuthData, cbAuthData, perr)) goto errorReturn;
+		break;
+
+	case COSE_Algorithm_HMAC_384_384:
+		if (!HMAC_Create((COSE_MacMessage *)pcose, 384, 384, pbKey, cbKey, pbAuthData, cbAuthData, perr)) goto errorReturn;
+		break;
+
+	case COSE_Algorithm_HMAC_512_512:
+		if (!HMAC_Create((COSE_MacMessage *)pcose, 512, 512, pbKey, cbKey, pbAuthData, cbAuthData, perr)) goto errorReturn;
+		break;
+
+	default:
+		FAIL_CONDITION(COSE_ERR_INVALID_PARAMETER);
+	}
+
+	//  Figure out the clean up
+
+	if (pbAuthData != NULL) COSE_FREE(pbAuthData, context);
+	if (pAuthData != NULL) cn_cbor_free(pAuthData CBOR_CONTEXT_PARAM);
+	if (ptmp != NULL) cn_cbor_free(ptmp CBOR_CONTEXT_PARAM);
+	return true;
+
+errorReturn:
+	if (pbAuthData != NULL) COSE_FREE(pbAuthData, context);
+	if (pAuthData != NULL) cn_cbor_free(pAuthData CBOR_CONTEXT_PARAM);
+	if (ptmp != NULL) cn_cbor_free(ptmp CBOR_CONTEXT_PARAM);
+	return false;
+}
+
+byte RgbDontUseMac[1024];
+
+bool COSE_Mac0_validate(HCOSE_MAC0 h, const byte * pbKey, size_t cbKey, cose_errback * perr)
+{
+	COSE_Mac0Message * pcose = (COSE_Mac0Message *)h;
+	cn_cbor_errback cbor_error;
+	byte * pbAuthData = NULL;
+	int cbitKey = 0;
+
+	int alg;
+	const cn_cbor * cn = NULL;
+
+#ifdef USE_CBOR_CONTEXT
+	cn_cbor_context * context = NULL;
+#endif
+	ssize_t cbAuthData;
+	cn_cbor * pAuthData = NULL;
+	cn_cbor * ptmp = NULL;
+
+	CHECK_CONDITION(IsValidMac0Handle(h), COSE_ERR_INVALID_PARAMETER);
+
+#ifdef USE_CBOR_CONTEXT
+	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;
+
+	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);
+
+		alg = (int)cn->v.uint;
+
+		switch (alg) {
+		case COSE_Algorithm_CBC_MAC_128_64:
+		case COSE_Algorithm_CBC_MAC_128_128:
+			cbitKey = 128;
+			break;
+
+		case COSE_Algorithm_CBC_MAC_256_64:
+		case COSE_Algorithm_CBC_MAC_256_128:
+		case COSE_Algorithm_HMAC_256_64:
+		case COSE_Algorithm_HMAC_256_256:
+			cbitKey = 256;
+			break;
+
+		case COSE_Algorithm_HMAC_384_384:
+			cbitKey = 384;
+			break;
+
+		case COSE_Algorithm_HMAC_512_512:
+			cbitKey = 512;
+			break;
+
+		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);
+
+	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("MAC0", 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
+
+	switch (alg) {
+	case COSE_Algorithm_HMAC_256_256:
+		if (!HMAC_Validate((COSE_MacMessage *)pcose, 256, 256, pbKey, cbKey, pbAuthData, cbAuthData, perr)) goto errorReturn;
+		break;
+
+	case COSE_Algorithm_HMAC_256_64:
+		if (!HMAC_Validate((COSE_MacMessage *)pcose, 256, 64, pbKey, cbKey, pbAuthData, cbAuthData, perr)) goto errorReturn;
+		break;
+
+	case COSE_Algorithm_HMAC_384_384:
+		if (!HMAC_Validate((COSE_MacMessage *)pcose, 384, 384, pbKey, cbKey, pbAuthData, cbAuthData, perr)) goto errorReturn;
+		break;
+
+	case COSE_Algorithm_HMAC_512_512:
+		if (!HMAC_Validate((COSE_MacMessage *)pcose, 512, 512, pbKey, cbKey, pbAuthData, cbAuthData, perr)) goto errorReturn;
+		break;
+
+	case COSE_Algorithm_CBC_MAC_128_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;
+
+	case COSE_Algorithm_CBC_MAC_128_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;
+
+	default:
+		FAIL_CONDITION(COSE_ERR_UNKNOWN_ALGORITHM);
+		break;
+	}
+
+	if (pbAuthData != NULL) COSE_FREE(pbAuthData, context);
+	if (pAuthData != NULL) cn_cbor_free(pAuthData CBOR_CONTEXT_PARAM);
+
+	return true;
+
+errorReturn:
+	if (pbAuthData != NULL) COSE_FREE(pbAuthData, context);
+	if (pAuthData != NULL) cn_cbor_free(pAuthData CBOR_CONTEXT_PARAM);
+
+	return false;
+}
diff --git a/src/Recipient.c b/src/Recipient.c
index 93cf834..cb1dc80 100644
--- a/src/Recipient.c
+++ b/src/Recipient.c
@@ -6,10 +6,14 @@
 #include "configure.h"
 #include "crypto.h"
 
+COSE* RecipientRoot = NULL;
+
 bool IsValidRecipientHandle(HCOSE_RECIPIENT h)
 {
-	if (h == NULL) return false;
-	return true;
+	COSE_RecipientInfo * p = (COSE_RecipientInfo *)h;
+
+	if (p == NULL) return false;
+	return _COSE_IsInList(RecipientRoot, &p->m_encrypt.m_message);
 }
 
 HCOSE_RECIPIENT COSE_Recipient_Init(CBOR_CONTEXT_COMMA cose_errback * perror)
@@ -25,17 +29,21 @@
 		return NULL;
 	}
 
+	_COSE_InsertInList(&RecipientRoot, &pobj->m_encrypt.m_message);
 	return (HCOSE_RECIPIENT)pobj;
 }
 
 bool COSE_Recipient_Free(HCOSE_RECIPIENT hRecipient)
 {
 	if (IsValidRecipientHandle(hRecipient)) {
+		COSE_RecipientInfo * p = (COSE_RecipientInfo *)hRecipient;
+		_COSE_RemoveFromList(&RecipientRoot, &p->m_encrypt.m_message);
 
-		_COSE_Recipient_Free((COSE_RecipientInfo *)hRecipient);
+		_COSE_Recipient_Free(p);
 		return true;
 	}
 
+
 	return false;
 }
 
@@ -82,6 +90,8 @@
 		goto errorReturn;
 	}
 
+	_COSE_InsertInList(&RecipientRoot, &pRecipient->m_encrypt.m_message);
+
 	return pRecipient;
 
 errorReturn:
@@ -204,8 +214,6 @@
 	return true;
 }
 
-byte RgbDontUse9[8 * 1024];
-
 bool _COSE_Recipient_encrypt(COSE_RecipientInfo * pRecipient, const byte * pbContent, size_t cbContent, cose_errback * perr)
 {
 	int alg;
@@ -290,25 +298,8 @@
 	if (cbProtected == NULL) goto errorReturn;
 
 	//  Build authenticated data
-	ssize_t cbAuthData = 0;
-	pbAuthData = NULL;
-	pAuthData = cn_cbor_array_create(CBOR_CONTEXT_PARAM_COMMA &cbor_error);
-	CHECK_CONDITION_CBOR(pAuthData != NULL, cbor_error);
-
-	ptmp = cn_cbor_data_create(cbProtected->v.bytes, (int)cbProtected->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;
-
-	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;
-
-	cbAuthData = cn_cbor_encoder_write(RgbDontUse9, 0, sizeof(RgbDontUse9), 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, pAuthData) == cbAuthData, COSE_ERR_CBOR);
+	size_t cbAuthData = 0;
+	if (!_COSE_Encrypt_Build_AAD(&pRecipient->m_encrypt.m_message, &pbAuthData, &cbAuthData, "Recipient", perr)) goto errorReturn;
 
 	switch (alg) {
 
diff --git a/src/Sign0.c b/src/Sign0.c
new file mode 100644
index 0000000..5b7201a
--- /dev/null
+++ b/src/Sign0.c
@@ -0,0 +1,378 @@
+#include <stdlib.h>
+
+#include "cose.h"
+#include "cose_int.h"
+#include "crypto.h"
+
+bool _COSE_Signer0_sign(COSE_Sign0Message * pSigner, const cn_cbor * pKey, cose_errback * perr);
+bool _COSE_Signer0_validate(COSE_Sign0Message * pSign, const cn_cbor * pKey, cose_errback * perr);
+void _COSE_Sign0_Release(COSE_Sign0Message * p);
+
+
+
+bool IsValidSign0Handle(HCOSE_SIGN0 h)
+{
+	COSE_Sign0Message * p = (COSE_Sign0Message *)h;
+	if (p == NULL) return false;
+	return true;
+}
+
+
+HCOSE_SIGN0 COSE_Sign0_Init(CBOR_CONTEXT_COMMA cose_errback * perror)
+{
+	COSE_Sign0Message * pobj = (COSE_Sign0Message *)COSE_CALLOC(1, sizeof(COSE_Sign0Message), context);
+	if (pobj == NULL) {
+		if (perror != NULL) perror->err = COSE_ERR_OUT_OF_MEMORY;
+		return NULL;
+	}
+
+	if (!_COSE_Init(&pobj->m_message, COSE_sign_object, CBOR_CONTEXT_PARAM_COMMA perror)) {
+		COSE_Sign0_Free((HCOSE_SIGN0)pobj);
+		return NULL;
+	}
+
+	return (HCOSE_SIGN0)pobj;
+}
+
+HCOSE_SIGN0 _COSE_Sign0_Init_From_Object(cn_cbor * cbor, COSE_Sign0Message * pIn, CBOR_CONTEXT_COMMA cose_errback * perr)
+{
+	COSE_Sign0Message * pobj = pIn;
+	cn_cbor * pSigners = NULL;
+	// cn_cbor * tmp;
+	cose_errback error = { 0 };
+	if (perr == NULL) perr = &error;
+
+	if (pobj == NULL) pobj = (COSE_Sign0Message *)COSE_CALLOC(1, sizeof(COSE_Sign0Message), context);
+	CHECK_CONDITION(pobj != NULL, COSE_ERR_OUT_OF_MEMORY);
+
+	if (!_COSE_Init_From_Object(&pobj->m_message, cbor, CBOR_CONTEXT_PARAM_COMMA perr)) {
+		goto errorReturn;
+	}
+
+	return(HCOSE_SIGN0)pobj;
+
+errorReturn:
+	if ((pIn == NULL) && (pobj != NULL)) COSE_FREE(pobj, context);
+	return NULL;
+}
+
+bool COSE_Sign0_Free(HCOSE_SIGN0 h)
+{
+#ifdef USE_CBOR_CONTEXT
+	cn_cbor_context context;
+#endif
+	COSE_Sign0Message * pMessage = (COSE_Sign0Message *)h;
+
+	if (!IsValidSign0Handle(h)) return false;
+
+	//  Check reference counting
+	if (pMessage->m_message.m_refCount > 1) {
+		pMessage->m_message.m_refCount--;
+		return true;
+	}
+
+#ifdef USE_CBOR_CONTEXT
+	context = pMessage->m_message.m_allocContext;
+#endif
+
+	_COSE_Sign0_Release(pMessage);
+
+	COSE_FREE(pMessage, &context);
+
+	return true;
+}
+
+void _COSE_Sign0_Release(COSE_Sign0Message * p)
+{
+	_COSE_Release(&p->m_message);
+}
+
+bool COSE_Sign0_SetContent(HCOSE_SIGN0 h, const byte * rgb, size_t cb, cose_errback * perr)
+{
+#ifdef USE_CBOR_CONTEXT
+	cn_cbor_context * context = NULL;
+#endif
+	cn_cbor * p = NULL;
+	COSE_Sign0Message * pMessage = (COSE_Sign0Message *)h;
+
+	if (!IsValidSign0Handle(h) || (rgb == NULL)) {
+		if (perr != NULL) perr->err = COSE_ERR_INVALID_PARAMETER;
+	errorReturn:
+		if (p != NULL) CN_CBOR_FREE(p, context);
+		return false;
+	}
+
+#ifdef USE_CBOR_CONTEXT
+	context = &pMessage->m_message.m_allocContext;
+#endif
+
+	p = cn_cbor_data_create(rgb, (int) cb, CBOR_CONTEXT_PARAM_COMMA NULL);
+	CHECK_CONDITION(p != NULL, COSE_ERR_OUT_OF_MEMORY);
+
+	CHECK_CONDITION(_COSE_array_replace(&pMessage->m_message, p, INDEX_BODY, CBOR_CONTEXT_PARAM_COMMA NULL), COSE_ERR_OUT_OF_MEMORY);
+
+	return true;
+}
+
+bool COSE_Sign0_Sign(HCOSE_SIGN0 h, const cn_cbor * pKey, cose_errback * perr)
+{
+#ifdef USE_CBOR_CONTEXT
+	// cn_cbor_context * context = NULL;
+#endif
+	COSE_Sign0Message * pMessage = (COSE_Sign0Message *)h;
+	const cn_cbor * pcborProtected;
+
+	if (!IsValidSign0Handle(h)) {
+		CHECK_CONDITION(false, COSE_ERR_INVALID_PARAMETER);
+	errorReturn:
+		return false;
+	}
+#ifdef USE_CBOR_CONTEXT
+	//	context = &pMessage->m_message.m_allocContext;
+#endif
+
+	pcborProtected = _COSE_encode_protected(&pMessage->m_message, perr);
+	if (pcborProtected == NULL) goto errorReturn;
+
+	if (!_COSE_Signer0_sign(pMessage, pKey, perr)) goto errorReturn;
+
+	return true;
+}
+
+bool COSE_Sign0_validate(HCOSE_SIGN0 hSign, const cn_cbor * pKey, cose_errback * perr)
+{
+	bool f;
+	COSE_Sign0Message * pSign;
+	const cn_cbor * cnContent;
+	const cn_cbor * cnProtected;
+
+	CHECK_CONDITION(IsValidSign0Handle(hSign), COSE_ERR_INVALID_PARAMETER);
+
+	pSign = (COSE_Sign0Message *)hSign;
+
+	cnContent = _COSE_arrayget_int(&pSign->m_message, INDEX_BODY);
+	CHECK_CONDITION(cnContent != NULL && cnContent->type == CN_CBOR_BYTES, COSE_ERR_INVALID_PARAMETER);
+
+	cnProtected = _COSE_arrayget_int(&pSign->m_message, INDEX_PROTECTED);
+	CHECK_CONDITION(cnProtected != NULL && cnContent->type == CN_CBOR_BYTES, COSE_ERR_INVALID_PARAMETER);
+
+	f = _COSE_Signer0_validate(pSign, pKey,  perr);
+
+	return f;
+
+errorReturn:
+	return false;
+}
+
+
+cn_cbor * COSE_Sign0_map_get_int(HCOSE_SIGN0 h, int key, int flags, cose_errback * perror)
+{
+	if (!IsValidSign0Handle(h)) {
+		if (perror != NULL) perror->err = COSE_ERR_INVALID_PARAMETER;
+		return NULL;
+	}
+
+	return _COSE_map_get_int(&((COSE_Sign0Message *)h)->m_message, key, flags, perror);
+}
+
+bool COSE_Sign0_map_put_int(HCOSE_SIGN0 h, int key, cn_cbor * value, int flags, cose_errback * perror)
+{
+	if (!IsValidSign0Handle(h) || (value == NULL)) {
+		if (perror != NULL) perror->err = COSE_ERR_INVALID_PARAMETER;
+		return false;
+	}
+
+	return _COSE_map_put(&((COSE_Sign0Message *)h)->m_message, key, value, flags, perror);
+}
+
+
+byte RgbDontUse4[8 * 1024];
+byte RgbDontUseSign[8 * 1024];
+
+static bool CreateSign0AAD(COSE_Sign0Message * pMessage, byte ** ppbToSign, size_t * pcbToSign, char * szContext, cose_errback * perr)
+{
+	cn_cbor * pArray = NULL;
+#ifdef USE_CBOR_CONTEXT
+	cn_cbor_context * context = &pMessage->m_message.m_allocContext;
+#endif
+	cn_cbor_errback cbor_error;
+	cn_cbor * cn = NULL;
+	cn_cbor * cn2;
+	size_t cbToSign;
+	byte * pbToSign = NULL;
+
+	pArray = cn_cbor_array_create(CBOR_CONTEXT_PARAM_COMMA &cbor_error);
+	CHECK_CONDITION_CBOR(pArray != NULL, cbor_error);
+
+	cn = cn_cbor_string_create(szContext, CBOR_CONTEXT_PARAM_COMMA &cbor_error);
+	CHECK_CONDITION_CBOR(cn != NULL, cbor_error);
+	CHECK_CONDITION_CBOR(cn_cbor_array_append(pArray, cn, &cbor_error), cbor_error);
+	cn = NULL;
+
+	cn2 = _COSE_arrayget_int(&pMessage->m_message, INDEX_PROTECTED);
+
+	cn = cn_cbor_data_create(cn2->v.bytes, (int)cn2->length, CBOR_CONTEXT_PARAM_COMMA &cbor_error);
+	CHECK_CONDITION_CBOR(cn != NULL, cbor_error);
+	CHECK_CONDITION_CBOR(cn_cbor_array_append(pArray, cn, &cbor_error), cbor_error);
+	cn = NULL;
+
+	cn = cn_cbor_data_create(NULL, 0, CBOR_CONTEXT_PARAM_COMMA &cbor_error);
+	CHECK_CONDITION_CBOR(cn != NULL, cbor_error);
+	CHECK_CONDITION_CBOR(cn_cbor_array_append(pArray, cn, &cbor_error), cbor_error);
+	cn = NULL;
+
+	cn2 = _COSE_arrayget_int(&pMessage->m_message, INDEX_BODY);
+	cn = cn_cbor_data_create(cn2->v.bytes, (int)cn2->length, CBOR_CONTEXT_PARAM_COMMA &cbor_error);
+	CHECK_CONDITION_CBOR(cn != NULL, cbor_error);
+	CHECK_CONDITION_CBOR(cn_cbor_array_append(pArray, cn, &cbor_error), cbor_error);
+	cn = NULL;
+
+
+	cbToSign = cn_cbor_encoder_write(RgbDontUse4, 0, sizeof(RgbDontUse4), pArray);
+	CHECK_CONDITION(cbToSign > 0, COSE_ERR_CBOR);
+	pbToSign = (byte *)COSE_CALLOC(cbToSign, 1, context);
+	CHECK_CONDITION(pbToSign != NULL, COSE_ERR_OUT_OF_MEMORY);
+	CHECK_CONDITION(cn_cbor_encoder_write(pbToSign, 0, cbToSign, pArray), COSE_ERR_CBOR);
+
+	*ppbToSign = pbToSign;
+	*pcbToSign = cbToSign;
+	pbToSign = NULL;
+
+	if (cn != NULL) CN_CBOR_FREE(cn, context);
+	if (pArray != NULL) COSE_FREE(pArray, context);
+	return true;
+
+errorReturn:
+	if (pbToSign != NULL) COSE_FREE(pbToSign, context);
+	if (cn != NULL) CN_CBOR_FREE(cn, context);
+	if (pArray != NULL) COSE_FREE(pArray, context);
+	return false;
+}
+
+bool _COSE_Signer0_sign(COSE_Sign0Message * pSigner, const cn_cbor * pKey, cose_errback * perr)
+{
+#ifdef USE_CBOR_CONTEXT
+	cn_cbor_context * context = &pSigner->m_message.m_allocContext;
+#endif
+	cn_cbor * pcborBody2 = NULL;
+	cn_cbor * pcborProtected2 = NULL;
+	cn_cbor * pArray = NULL;
+	cn_cbor * cn = NULL;
+	size_t cbToSign;
+	byte * pbToSign = NULL;
+	bool f;
+	int alg;
+
+	pArray = cn_cbor_array_create(CBOR_CONTEXT_PARAM_COMMA NULL);
+	if (pArray == NULL) {
+		if (perr != NULL) perr->err = COSE_ERR_OUT_OF_MEMORY;
+	errorReturn:
+		if (cn != NULL) CN_CBOR_FREE(cn, context);
+		if (pcborBody2 != NULL) CN_CBOR_FREE(pcborBody2, context);
+		if (pcborProtected2 != NULL) CN_CBOR_FREE(pcborProtected2, context);
+		if (pArray != NULL) COSE_FREE(pArray, context);
+		if (pbToSign != NULL) COSE_FREE(pbToSign, context);
+		return false;
+	}
+
+	cn = _COSE_map_get_int(&pSigner->m_message, COSE_Header_Algorithm, COSE_BOTH, perr);
+	if (cn == NULL) goto errorReturn;
+
+	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);
+
+		alg = (int)cn->v.uint;
+	}
+
+
+	if (!CreateSign0AAD(pSigner, &pbToSign, &cbToSign, "Signature1", perr)) goto errorReturn;
+
+	switch (alg) {
+	case COSE_Algorithm_ECDSA_SHA_256:
+		f = ECDSA_Sign(&pSigner->m_message, INDEX_SIGNATURE+1, pKey, 256, pbToSign, cbToSign, perr);
+		break;
+
+	case COSE_Algorithm_ECDSA_SHA_384:
+		f = ECDSA_Sign(&pSigner->m_message, INDEX_SIGNATURE+1, pKey, 384, pbToSign, cbToSign, perr);
+		break;
+
+	case COSE_Algorithm_ECDSA_SHA_512:
+		f = ECDSA_Sign(&pSigner->m_message, INDEX_SIGNATURE+1, pKey, 512, pbToSign, cbToSign, perr);
+		break;
+
+	default:
+		FAIL_CONDITION(COSE_ERR_INVALID_PARAMETER);
+	}
+
+	COSE_FREE(pbToSign, context);
+	CN_CBOR_FREE(pArray, context);
+
+	return f;
+}
+
+bool _COSE_Signer0_validate(COSE_Sign0Message * pSign, const cn_cbor * pKey, cose_errback * perr)
+{
+	byte * pbToSign = NULL;
+	int alg;
+	const cn_cbor * cn = NULL;
+#ifdef USE_CBOR_CONTEXT
+	cn_cbor_context * context = NULL;
+#endif
+	size_t cbToSign;
+	cn_cbor * pAuthData = NULL;
+	cn_cbor * cnSignature = NULL;
+
+#ifdef USE_CBOR_CONTEXT
+	context = &pSign->m_message.m_allocContext;
+#endif
+
+	cn = _COSE_map_get_int(&pSign->m_message, COSE_Header_Algorithm, COSE_BOTH, perr);
+	if (cn == NULL) goto errorReturn;
+
+	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);
+
+		alg = (int)cn->v.uint;
+	}
+
+	//  Build protected headers
+
+	if (!CreateSign0AAD(pSign, &pbToSign, &cbToSign, "Signature1", perr)) goto errorReturn;
+
+	cnSignature = _COSE_arrayget_int(&pSign->m_message, INDEX_SIGNATURE);
+
+	switch (alg) {
+	case COSE_Algorithm_ECDSA_SHA_256:
+		if (!ECDSA_Verify(&pSign->m_message, INDEX_SIGNATURE+1, pKey, 256, pbToSign, cbToSign, perr)) goto errorReturn;
+		break;
+
+	case COSE_Algorithm_ECDSA_SHA_384:
+		if (!ECDSA_Verify(&pSign->m_message, INDEX_SIGNATURE+1, pKey, 384, pbToSign, cbToSign, perr)) goto errorReturn;
+		break;
+
+	case COSE_Algorithm_ECDSA_SHA_512:
+		if (!ECDSA_Verify(&pSign->m_message, INDEX_SIGNATURE+1, pKey, 512, pbToSign, cbToSign, perr)) goto errorReturn;
+		break;
+
+	default:
+		FAIL_CONDITION(COSE_ERR_UNKNOWN_ALGORITHM);
+		break;
+	}
+
+	if (pbToSign != NULL) COSE_FREE(pbToSign, context);
+	if (pAuthData != NULL) cn_cbor_free(pAuthData CBOR_CONTEXT_PARAM);
+
+	return true;
+
+errorReturn:
+	if (pbToSign != NULL) COSE_FREE(pbToSign, context);
+	if (pAuthData != NULL) cn_cbor_free(pAuthData CBOR_CONTEXT_PARAM);
+
+	return false;
+}
diff --git a/src/SignerInfo.c b/src/SignerInfo.c
index a2ed0b6..8165bbd 100644
--- a/src/SignerInfo.c
+++ b/src/SignerInfo.c
@@ -169,15 +169,15 @@
 
 	switch (alg) {
 	case COSE_Algorithm_ECDSA_SHA_256:
-		f = ECDSA_Sign(pSigner, 256, pbToSign, cbToSign, perr);
+		f = ECDSA_Sign(&pSigner->m_message, INDEX_SIGNATURE, pSigner->m_pkey, 256, pbToSign, cbToSign, perr);
 		break;
 
 	case COSE_Algorithm_ECDSA_SHA_384:
-		f = ECDSA_Sign(pSigner, 384, pbToSign, cbToSign, perr);
+		f = ECDSA_Sign(&pSigner->m_message, INDEX_SIGNATURE, pSigner->m_pkey, 384, pbToSign, cbToSign, perr);
 		break;
 
 	case COSE_Algorithm_ECDSA_SHA_512:
-		f = ECDSA_Sign(pSigner, 512, pbToSign, cbToSign, perr);
+		f = ECDSA_Sign(&pSigner->m_message, INDEX_SIGNATURE, pSigner->m_pkey, 512, pbToSign, cbToSign, perr);
 		break;
 
 	default:
@@ -276,15 +276,15 @@
 
 	switch (alg) {
 	case COSE_Algorithm_ECDSA_SHA_256:
-		if (!ECDSA_Verify(pSigner, 256, pbAuthData, cbAuthData, cnSignature->v.bytes, cnSignature->length, perr)) goto errorReturn;
+		if (!ECDSA_Verify(&pSigner->m_message, INDEX_SIGNATURE, pSigner->m_pkey, 256, pbAuthData, cbAuthData, perr)) goto errorReturn;
 		break;
 
 	case COSE_Algorithm_ECDSA_SHA_384:
-		if (!ECDSA_Verify(pSigner, 384, pbAuthData, cbAuthData, cnSignature->v.bytes, cnSignature->length, perr)) goto errorReturn;
+		if (!ECDSA_Verify(&pSigner->m_message, INDEX_SIGNATURE, pSigner->m_pkey, 384, pbAuthData, cbAuthData, perr)) goto errorReturn;
 		break;
 
 	case COSE_Algorithm_ECDSA_SHA_512:
-		if (!ECDSA_Verify(pSigner, 512, pbAuthData, cbAuthData, cnSignature->v.bytes, cnSignature->length, perr)) goto errorReturn;
+		if (!ECDSA_Verify(&pSigner->m_message, INDEX_SIGNATURE, pSigner->m_pkey, 512, pbAuthData, cbAuthData, perr)) goto errorReturn;
 		break;
 
 	default:
diff --git a/src/cose.h b/src/cose.h
index 99e47ae..7f7c0a0 100644
--- a/src/cose.h
+++ b/src/cose.h
@@ -5,10 +5,12 @@
 typedef struct _cose * HCOSE;
 typedef struct _cose_sign * HCOSE_SIGN;
 typedef struct _cose_signer * HCOSE_SIGNER;
+typedef struct _cose_sign0 * HCOSE_SIGN0;
 typedef struct _cose_encrypt * HCOSE_ENCRYPT;
 typedef struct _cose_enveloped * HCOSE_ENVELOPED;
 typedef struct _cose_recipient * HCOSE_RECIPIENT;
 typedef struct _cose_mac * HCOSE_MAC;
+typedef struct _cose_mac0 * HCOSE_MAC0;
 
 /**
 * All of the different kinds of errors
@@ -43,7 +45,7 @@
 typedef enum {
 	COSE_unknown_object = 0,
 	COSE_sign_object = 991,
-	COSE_sign1_object = 997,
+	COSE_sign0_object = 997,
 	COSE_enveloped_object = 992,
 	COSE_encrypt_object = 993,
 	COSE_mac_object = 994,
@@ -206,7 +208,7 @@
 bool COSE_Mac_SetContent(HCOSE_MAC cose, const byte * rgbContent, size_t cbContent, cose_errback * errp);
 
 cn_cbor * COSE_Mac_map_get_int(HCOSE_MAC h, int key, int flags, cose_errback * perror);
-bool COSE_Mac_map_put(HCOSE_MAC cose, int key, cn_cbor * value, int flags, cose_errback * errp);
+bool COSE_Mac_map_put_int(HCOSE_MAC cose, int key, cn_cbor * value, int flags, cose_errback * errp);
 
 bool COSE_Mac_encrypt(HCOSE_MAC cose, cose_errback * perror);
 bool COSE_Mac_validate(HCOSE_MAC, HCOSE_RECIPIENT, cose_errback * perr);
@@ -216,6 +218,19 @@
 extern bool COSE_Mac_AddRecipient(HCOSE_MAC hMac, HCOSE_RECIPIENT hRecip, cose_errback * perr);
 HCOSE_RECIPIENT COSE_Mac_GetRecipient(HCOSE_MAC cose, int iRecipient, cose_errback * perr);
 
+//  MAC0 calls
+
+HCOSE_MAC0 COSE_Mac0_Init(CBOR_CONTEXT_COMMA cose_errback * perr);
+bool COSE_Mac0_Free(HCOSE_MAC0 cose);
+
+bool COSE_Mac0_SetContent(HCOSE_MAC0 cose, const byte * rgbContent, size_t cbContent, cose_errback * errp);
+
+cn_cbor * COSE_Mac0_map_get_int(HCOSE_MAC0 h, int key, int flags, cose_errback * perror);
+bool COSE_Mac0_map_put_int(HCOSE_MAC0 cose, int key, cn_cbor * value, int flags, cose_errback * errp);
+
+bool COSE_Mac0_encrypt(HCOSE_MAC0 cose, const byte * pbKey, size_t cbKey, cose_errback * perror);
+bool COSE_Mac0_validate(HCOSE_MAC0, const byte * pbKey, size_t cbKey, cose_errback * perr);
+
 //
 //
 
@@ -233,3 +248,15 @@
 bool COSE_Signer_Free(HCOSE_SIGNER cose);
 bool COSE_Signer_SetKey(HCOSE_SIGNER hSigner, const cn_cbor * pkey, cose_errback * perr);
 bool COSE_Signer_map_put(HCOSE_SIGNER cose, int key, cn_cbor * value, int flags, cose_errback * errp);
+
+/*
+ *  Sign routines
+ */
+
+HCOSE_SIGN0 COSE_Sign0_Init(CBOR_CONTEXT_COMMA cose_errback * perr);
+bool COSE_Sign0_Free(HCOSE_SIGN0 cose);
+bool COSE_Sign0_SetContent(HCOSE_SIGN0 cose, const byte * rgbContent, size_t cbContent, cose_errback * errp);
+bool COSE_Sign0_Sign(HCOSE_SIGN0 h, const cn_cbor * pkey, cose_errback * perr);
+bool COSE_Sign0_validate(HCOSE_SIGN0 hSign, const cn_cbor * pkey, cose_errback * perr);
+cn_cbor * COSE_Sign0_map_get_int(HCOSE_SIGN0 h, int key, int flags, cose_errback * perror);
+bool COSE_Sign0_map_put_int(HCOSE_SIGN0 cose, int key, cn_cbor * value, int flags, cose_errback * errp);
diff --git a/src/cose_int.h b/src/cose_int.h
index 5640946..65317f4 100644
--- a/src/cose_int.h
+++ b/src/cose_int.h
@@ -28,6 +28,10 @@
 	COSE_SignerInfo * m_signerFirst;
 } COSE_SignMessage;
 
+typedef struct {
+	COSE m_message;	    // The message object
+} COSE_Sign0Message;
+
 struct _SignerInfo {
 	COSE m_message;
 	byte * pbKey;
@@ -64,11 +68,15 @@
 
 typedef struct {
 	COSE m_message;			// The message object
-	COSE_RecipientInfo * m_recipientFirst;
 	byte * pbKey;
 	size_t cbKey;
+	COSE_RecipientInfo * m_recipientFirst;
 } COSE_MacMessage;
 
+typedef struct {
+	COSE m_message;			// The message object
+} COSE_Mac0Message;
+
 #ifdef USE_CBOR_CONTEXT
 /**
 * Allocate enough space for 1 `cn_cbor` structure.
@@ -179,8 +187,14 @@
 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);
 
+//  MAC0 Items
+extern HCOSE_MAC0 _COSE_Mac0_Init_From_Object(cn_cbor *, COSE_Mac0Message * pIn, CBOR_CONTEXT_COMMA cose_errback * errp);
+extern bool _COSE_Mac0_Release(COSE_Mac0Message * p);
 
-#define CHECK_CONDITION(condition, error) { if (!(condition)) { /*assert(false);*/ perr->err = error; goto errorReturn;}}
+//
+//  Debugging Items
+
+#define CHECK_CONDITION(condition, error) { if (!(condition)) { assert(false); perr->err = error; goto errorReturn;}}
 #define FAIL_CONDITION(error) { assert(false); perr->err = error; goto errorReturn;}
 #define CHECK_CONDITION_CBOR(condition, error) { if (!(condition)) { assert(false); perr->err = _MapFromCBOR(error); goto errorReturn;}}
 
diff --git a/src/crypto.h b/src/crypto.h
index c8728ca..8f7c8df 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 * pbKey, int cbitKey, 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, size_t 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 TagSize, const byte * pbKey, int cbitKey, const byte * pbAuthData, int cbAuthData, cose_errback * perr);
+extern bool AES_CBC_MAC_Create(COSE_MacMessage * pcose, int TagSize, const byte * pbKey, size_t cbKey, const byte * pbAuthData, size_t cbAuthData, cose_errback * perr);
+extern bool AES_CBC_MAC_Validate(COSE_MacMessage * pcose, int TagSize, const byte * pbKey, size_t cbitKey, const byte * pbAuthData, size_t cbAuthData, cose_errback * perr);
 
 /**
 * Perform an HMAC Creation operation
@@ -43,8 +43,8 @@
 * @param[in]	cose_errback *	Error return location
 * @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 * pbKey, int cbitKey, const byte * pbAuthData, int cbAuthData, cose_errback * perr);
+bool HMAC_Create(COSE_MacMessage * pcose, int HSize, int TSize, const byte * pbKey, size_t cbKey, const byte * pbAuthData, size_t cbAuthData, cose_errback * perr);
+bool HMAC_Validate(COSE_MacMessage * pcose, int HSize, int TSize, const byte * pbKey, size_t cbitKey, const byte * pbAuthData, size_t cbAuthData, cose_errback * perr);
 
 /**
 * Perform a signature operation
@@ -55,8 +55,8 @@
 * @param[in]	cose_errback *	Error return location
 * @return						Did the function succeed?
 */
-bool ECDSA_Sign(COSE_SignerInfo * pSigner, int cbitsDigest, const byte * rgbToSign, size_t cbToSign, cose_errback * perr);
-bool ECDSA_Verify(COSE_SignerInfo * pSigner, int cbitsDigest, const byte * rgbToSign, size_t cbToSign, const byte * rgbSig, size_t cbSig, cose_errback * perr);
+bool ECDSA_Sign(COSE * pSigner, int index, const cn_cbor * pKey, int cbitsDigest, const byte * rgbToSign, size_t cbToSign, cose_errback * perr);
+bool ECDSA_Verify(COSE * pSigner, int index, const cn_cbor * pKey, int cbitsDigest, const byte * rgbToSign, size_t cbToSign, cose_errback * perr);
 
 /**
 *  Generate random bytes in a buffer
diff --git a/src/openssl.c b/src/openssl.c
index 90d8db3..4ddfe97 100644
--- a/src/openssl.c
+++ b/src/openssl.c
@@ -376,7 +376,7 @@
 }
 
 
-bool AES_CBC_MAC_Create(COSE_MacMessage * pcose, int KeySize, int TSize, const byte * pbAuthData, int cbAuthData, cose_errback * perr)
+bool AES_CBC_MAC_Create(COSE_MacMessage * pcose, int TSize, const byte * pbKey, size_t cbKey, const byte * pbAuthData, size_t cbAuthData, cose_errback * perr)
 {
 	const EVP_CIPHER * pcipher = NULL;
 	EVP_CIPHER_CTX ctx;
@@ -393,7 +393,7 @@
 	rgbOut = COSE_CALLOC(16, 1, context);
 	CHECK_CONDITION(rgbOut != NULL, COSE_ERR_OUT_OF_MEMORY);
 
-	switch (KeySize) {
+	switch (cbKey*8) {
 	case 128:
 		pcipher = EVP_aes_128_cbc();
 		break;
@@ -409,7 +409,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);
 
 	for (i = 0; i < (unsigned int)cbAuthData / 16; i++) {
 		CHECK_CONDITION(EVP_EncryptUpdate(&ctx, rgbOut, &cbOut, pbAuthData + (i * 16), 16), COSE_ERR_CRYPTO_FAIL);
@@ -436,7 +436,7 @@
 	return false;
 }
 
-bool AES_CBC_MAC_Validate(COSE_MacMessage * pcose, int TSize, const byte * pbKey, int cbitKey, const byte * pbAuthData, int cbAuthData, cose_errback * perr)
+bool AES_CBC_MAC_Validate(COSE_MacMessage * pcose, int TSize, const byte * pbKey, size_t cbKey, const byte * pbAuthData, size_t cbAuthData, cose_errback * perr)
 {
 	const EVP_CIPHER * pcipher = NULL;
 	EVP_CIPHER_CTX ctx;
@@ -446,7 +446,7 @@
 	bool f = false;
 	unsigned int i;
 
-	switch (cbitKey) {
+	switch (cbKey*8) {
 	case 128:
 		pcipher = EVP_aes_128_cbc();
 		break;
@@ -536,7 +536,7 @@
 }
 #endif
 
-bool HMAC_Create(COSE_MacMessage * pcose, int HSize, int TSize, const byte * pbAuthData, int cbAuthData, cose_errback * perr)
+bool HMAC_Create(COSE_MacMessage * pcose, int HSize, int TSize, const byte * pbKey, size_t cbKey, const byte * pbAuthData, size_t cbAuthData, cose_errback * perr)
 {
 	HMAC_CTX ctx;
 	const EVP_MD * pmd = NULL;
@@ -565,7 +565,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, (int) cbKey, 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);
 
@@ -575,7 +575,7 @@
 	return true;
 }
 
-bool HMAC_Validate(COSE_MacMessage * pcose, int HSize, int TSize, const byte * pbKey, int cbitKey, const byte * pbAuthData, int cbAuthData, cose_errback * perr)
+bool HMAC_Validate(COSE_MacMessage * pcose, int HSize, int TSize, const byte * pbKey, size_t cbKey, const byte * pbAuthData, size_t 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, pbKey, cbitKey/8, pmd), COSE_ERR_CRYPTO_FAIL);
+	CHECK_CONDITION(HMAC_Init(&ctx, pbKey, (int) cbKey, 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);
 
@@ -702,7 +702,7 @@
 }
 */
 
-bool ECDSA_Sign(COSE_SignerInfo * pSigner, int cbitDigest, const byte * rgbToSign, size_t cbToSign, cose_errback * perr)
+bool ECDSA_Sign(COSE * pSigner, int index, const cn_cbor * pKey, int cbitDigest, const byte * rgbToSign, size_t cbToSign, cose_errback * perr)
 {
 	EC_KEY * eckey = NULL;
 	byte rgbDigest[EVP_MAX_MD_SIZE];
@@ -710,7 +710,7 @@
 	byte  * pbSig = NULL;
 	const EVP_MD * digest;
 #ifdef USE_CBOR_CONTEXT
-	cn_cbor_context * context = &pSigner->m_message.m_allocContext;
+	cn_cbor_context * context = &pSigner->m_allocContext;
 #endif
 	cn_cbor * p = NULL;
 	ECDSA_SIG * psig = NULL;
@@ -719,7 +719,7 @@
 	byte rgbSig[66];
 	int cb;
 	
-	eckey = ECKey_From(pSigner->m_pkey, &cbR, perr);
+	eckey = ECKey_From(pKey, &cbR, perr);
 	if (eckey == NULL) {
 	errorReturn:
 		if (p != NULL) CN_CBOR_FREE(p, context);
@@ -743,8 +743,6 @@
 	pbSig = COSE_CALLOC(cbR, 2, context);
 	CHECK_CONDITION(pbSig != NULL, COSE_ERR_OUT_OF_MEMORY);
 
-
-
 	cb = BN_bn2bin(psig->r, rgbSig);
 	CHECK_CONDITION(cb <= cbR, COSE_ERR_INVALID_PARAMETER);
 	memcpy(pbSig + cbR - cb, rgbSig, cb);
@@ -756,25 +754,27 @@
 	p = cn_cbor_data_create(pbSig, cbR*2, CBOR_CONTEXT_PARAM_COMMA &cbor_error);
 	CHECK_CONDITION_CBOR(p != NULL, cbor_error);
 
-	CHECK_CONDITION(_COSE_array_replace(&pSigner->m_message, p, INDEX_SIGNATURE, CBOR_CONTEXT_PARAM_COMMA NULL), COSE_ERR_CBOR);
+	CHECK_CONDITION(_COSE_array_replace(pSigner, p, index, CBOR_CONTEXT_PARAM_COMMA NULL), COSE_ERR_CBOR);
 	
 	return true;
 }
 
-bool ECDSA_Verify(COSE_SignerInfo * pSigner, int cbitDigest, const byte * rgbToSign, size_t cbToSign, const byte * rgbSignature, size_t cbSignature, cose_errback * perr)
+bool ECDSA_Verify(COSE * pSigner, int index, const cn_cbor * pKey, int cbitDigest, const byte * rgbToSign, size_t cbToSign, cose_errback * perr)
 {
 	EC_KEY * eckey = NULL;
 	byte rgbDigest[EVP_MAX_MD_SIZE];
 	unsigned int cbDigest = sizeof(rgbDigest);
 	const EVP_MD * digest;
 #ifdef USE_CBOR_CONTEXT
-	cn_cbor_context * context = &pSigner->m_message.m_allocContext;
+	cn_cbor_context * context = &pSigner->m_allocContext;
 #endif
 	cn_cbor * p = NULL;
 	ECDSA_SIG sig = { NULL, NULL };
 	int cbR;
+	cn_cbor * pSig;
+	size_t cbSignature;
 
-	eckey = ECKey_From(pSigner->m_pkey, &cbR, perr);
+	eckey = ECKey_From(pKey, &cbR, perr);
 	if (eckey == NULL) {
 	errorReturn:
 		if (sig.r != NULL) BN_free(sig.r);
@@ -793,14 +793,19 @@
 	}
 	EVP_Digest(rgbToSign, cbToSign, rgbDigest, &cbDigest, digest, NULL);
 
+	pSig = _COSE_arrayget_int(pSigner, index);
+	CHECK_CONDITION(pSig != NULL, CN_CBOR_ERR_INVALID_PARAMETER);
+	cbSignature = pSig->length;
+
 	CHECK_CONDITION(cbSignature / 2 == cbR, COSE_ERR_INVALID_PARAMETER);
-	sig.r = BN_bin2bn(rgbSignature,(int) cbSignature/2, NULL);
-	sig.s = BN_bin2bn(rgbSignature+cbSignature/2, (int) cbSignature/2, NULL);
+	sig.r = BN_bin2bn(pSig->v.bytes,(int) cbSignature/2, NULL);
+	sig.s = BN_bin2bn(pSig->v.bytes+cbSignature/2, (int) cbSignature/2, NULL);
 
 	CHECK_CONDITION(ECDSA_do_verify(rgbDigest, cbDigest, &sig, eckey) == 1, COSE_ERR_CRYPTO_FAIL);
 
 	BN_free(sig.r);
 	BN_free(sig.s);
+	if (eckey != NULL) EC_KEY_free(eckey);
 
 	return true;
 }
diff --git a/test/CMakeLists.txt b/test/CMakeLists.txt
index 65ba3c0..03690ae 100644
--- a/test/CMakeLists.txt
+++ b/test/CMakeLists.txt
@@ -51,6 +51,17 @@
 add_test ( NAME cbc-mac-03 WORKING_DIRECTORY ${CMAKE_SOURCE_DIR} COMMAND cose_test Examples/cbc-mac-examples/cbc-mac-03.json )
 add_test ( NAME cbc-mac-04 WORKING_DIRECTORY ${CMAKE_SOURCE_DIR} COMMAND cose_test Examples/cbc-mac-examples/cbc-mac-04.json )
 
+add_test ( NAME hmac-enc01 WORKING_DIRECTORY ${CMAKE_SOURCE_DIR} COMMAND cose_test Examples/hmac-examples/Hmac-Enc01.json )
+add_test ( NAME hmac-enc02 WORKING_DIRECTORY ${CMAKE_SOURCE_DIR} COMMAND cose_test Examples/hmac-examples/Hmac-Enc02.json )
+add_test ( NAME hmac-enc03 WORKING_DIRECTORY ${CMAKE_SOURCE_DIR} COMMAND cose_test Examples/hmac-examples/Hmac-Enc03.json )
+add_test ( NAME hmac-enc04 WORKING_DIRECTORY ${CMAKE_SOURCE_DIR} COMMAND cose_test Examples/hmac-examples/Hmac-Enc04.json )
+add_test ( NAME hmac-enc05 WORKING_DIRECTORY ${CMAKE_SOURCE_DIR} COMMAND cose_test Examples/hmac-examples/Hmac-Enc05.json )
+
+add_test ( NAME cbc-mac-enc-01 WORKING_DIRECTORY ${CMAKE_SOURCE_DIR} COMMAND cose_test Examples/cbc-mac-examples/cbc-mac-enc-01.json )
+add_test ( NAME cbc-mac-enc-02 WORKING_DIRECTORY ${CMAKE_SOURCE_DIR} COMMAND cose_test Examples/cbc-mac-examples/cbc-mac-enc-02.json )
+add_test ( NAME cbc-mac-enc-03 WORKING_DIRECTORY ${CMAKE_SOURCE_DIR} COMMAND cose_test Examples/cbc-mac-examples/cbc-mac-enc-03.json )
+add_test ( NAME cbc-mac-enc-04 WORKING_DIRECTORY ${CMAKE_SOURCE_DIR} COMMAND cose_test Examples/cbc-mac-examples/cbc-mac-enc-04.json )
+
 add_test ( NAME aes-gcm-01 WORKING_DIRECTORY ${CMAKE_SOURCE_DIR} COMMAND cose_test Examples/aes-gcm-examples/aes-gcm-01.json )
 add_test ( NAME aes-gcm-02 WORKING_DIRECTORY ${CMAKE_SOURCE_DIR} COMMAND cose_test Examples/aes-gcm-examples/aes-gcm-02.json )
 add_test ( NAME aes-gcm-03 WORKING_DIRECTORY ${CMAKE_SOURCE_DIR} COMMAND cose_test Examples/aes-gcm-examples/aes-gcm-03.json )
diff --git a/test/mac_test.c b/test/mac_test.c
index 725c389..113f254 100644
--- a/test/mac_test.c
+++ b/test/mac_test.c
@@ -162,7 +162,7 @@
 	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_map_put_int(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);
@@ -216,3 +216,121 @@
 
 	return 1;
 }
+
+
+int _ValidateMac0(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_MAC0 hMAC;
+	int type;
+	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_MAC0)COSE_Decode(pbEncoded, cbEncoded, &type, COSE_mac0_object, CBOR_CONTEXT_PARAM_COMMA NULL);
+	if (hMAC == NULL) exit(1);
+
+	if ((pInput == NULL) || (pInput->type != CN_CBOR_MAP)) exit(1);
+	pMac = cn_cbor_mapget_string(pInput, "mac0");
+	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);
+
+	pRecipients = pRecipients->first_child;
+
+	cn_cbor * pkey = BuildKey(cn_cbor_mapget_string(pRecipients, "key"));
+		if (pkey == NULL) {
+			fFail = true;
+			goto exitHere;
+		}
+
+		cn_cbor *k = cn_cbor_mapget_int(pkey, -1);
+
+		pFail = cn_cbor_mapget_string(pRecipients, "fail");
+		if (COSE_Mac0_validate(hMAC, k->v.bytes, k->length, NULL)) {
+			if ((pFail != NULL) && (pFail->type != CN_CBOR_TRUE)) fFail = true;
+		}
+		else {
+			if ((pFail == NULL) || (pFail->type == CN_CBOR_FALSE)) fFail = true;
+		}
+
+
+	COSE_Mac0_Free(hMAC);
+
+	if (fFailBody) {
+		if (!fFail) fFail = true;
+		else fFail = false;
+	}
+	exitHere:
+	if (fFail) CFails += 1;
+	return 0;
+}
+
+int ValidateMac0(const cn_cbor * pControl)
+{
+	int cbEncoded;
+	byte * pbEncoded = GetCBOREncoding(pControl, &cbEncoded);
+
+	return _ValidateMac0(pControl, pbEncoded, cbEncoded);
+}
+
+int BuildMac0Message(const cn_cbor * pControl)
+{
+
+	//
+	//  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_MAC0 hMacObj = COSE_Mac0_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, "mac0");
+	if (pMac == NULL) exit(1);
+
+	const cn_cbor * pContent = cn_cbor_mapget_string(pInputs, "plaintext");
+	if (!COSE_Mac0_SetContent(hMacObj, pContent->v.bytes, pContent->length, NULL)) goto returnError;
+
+	if (!SetAttributes((HCOSE)hMacObj, cn_cbor_mapget_string(pMac, "protected"), Attributes_MAC0_protected)) goto returnError;
+	if (!SetAttributes((HCOSE)hMacObj, cn_cbor_mapget_string(pMac, "unprotected"), Attributes_MAC0_unprotected)) goto returnError;
+
+	const cn_cbor * pAlg = COSE_Mac0_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;
+
+	cn_cbor * pkey = BuildKey(cn_cbor_mapget_string(pRecipients, "key"));
+		if (pkey == NULL) exit(1);
+
+		cn_cbor * k = cn_cbor_mapget_int(pkey, -1);
+
+	if (!COSE_Mac0_encrypt(hMacObj, k->v.bytes, k->length, 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_Mac0_Free(hMacObj);
+
+	int f = _ValidateMac0(pControl, rgb, cb);
+
+	free(rgb);
+	return f;
+
+returnError:
+	CFails += 1;
+	return 1;
+}
diff --git a/test/sign.c b/test/sign.c
index 136cf47..28734b2 100644
--- a/test/sign.c
+++ b/test/sign.c
@@ -239,3 +239,119 @@
 
 	return 1;
 }
+
+
+int _ValidateSign0(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 * pSign;
+	HCOSE_SIGN0	hSig;
+	int type;
+	bool fFail = false;
+	bool fFailBody = false;
+
+#ifdef USE_CBOR_CONTEXT
+	allocator = CreateContext();
+#endif 
+
+	pFail = cn_cbor_mapget_string(pControl, "fail");
+	if ((pFail != NULL) && (pFail->type == CN_CBOR_TRUE)) {
+		fFailBody = true;
+	}
+
+	if ((pInput == NULL) || (pInput->type != CN_CBOR_MAP)) exit(1);
+	pSign = cn_cbor_mapget_string(pInput, "sign0");
+	if ((pSign == NULL) || (pSign->type != CN_CBOR_MAP)) exit(1);
+
+	hSig = (HCOSE_SIGN0)COSE_Decode(pbEncoded, cbEncoded, &type, COSE_sign0_object, CBOR_CONTEXT_PARAM_COMMA NULL);
+	if (hSig == NULL) exit(1);
+
+
+	cn_cbor * pkey = BuildKey(cn_cbor_mapget_string(pSign, "key"));
+	if (pkey == NULL) {
+		fFail = true;
+		goto exitHere;
+	}
+
+
+	pFail = cn_cbor_mapget_string(pInput, "fail");
+	if (COSE_Sign0_validate(hSig, pkey, NULL)) {
+		if ((pFail != NULL) && (pFail->type != CN_CBOR_TRUE)) fFail = true;
+	}
+	else {
+		if ((pFail == NULL) || (pFail->type == CN_CBOR_FALSE)) fFail = true;
+	}
+
+	COSE_Sign0_Free(hSig);
+
+	if (fFailBody) {
+		if (!fFail) fFail = true;
+		else fFail = false;
+	}
+
+exitHere:
+#ifdef USE_CBOR_CONTEXT
+	FreeContext(allocator);
+	allocator = NULL;
+#endif
+
+	if (fFail) CFails += 1;
+	return 0;
+}
+
+int ValidateSign0(const cn_cbor * pControl)
+{
+	int cbEncoded;
+	byte * pbEncoded = GetCBOREncoding(pControl, &cbEncoded);
+
+	return _ValidateSign0(pControl, pbEncoded, cbEncoded);
+}
+
+int BuildSign0Message(const cn_cbor * pControl)
+{
+	//
+	//  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_SIGN0 hSignObj = COSE_Sign0_Init(CBOR_CONTEXT_PARAM_COMMA NULL);
+
+	const cn_cbor * pInputs = cn_cbor_mapget_string(pControl, "input");
+	if (pInputs == NULL) exit(1);
+	const cn_cbor * pSign = cn_cbor_mapget_string(pInputs, "sign0");
+	if (pSign == NULL) exit(1);
+
+	const cn_cbor * pContent = cn_cbor_mapget_string(pInputs, "plaintext");
+	if (!COSE_Sign0_SetContent(hSignObj, pContent->v.bytes, pContent->length, NULL)) goto returnError;
+
+	if (!SetAttributes((HCOSE)hSignObj, cn_cbor_mapget_string(pSign, "protected"), Attributes_Sign0_protected)) goto returnError;
+	if (!SetAttributes((HCOSE)hSignObj, cn_cbor_mapget_string(pSign, "unprotected"), Attributes_Sign0_unprotected)) goto returnError;
+	if (!SetAttributes((HCOSE)hSignObj, cn_cbor_mapget_string(pSign, "unsent"), Attributes_Sign0_unsent)) goto returnError;
+
+	const cn_cbor * pAlg = COSE_Sign0_map_get_int(hSignObj, 1, COSE_BOTH, NULL);
+
+	cn_cbor * pkey = BuildKey(cn_cbor_mapget_string(pSign, "key"));
+	if (pkey == NULL) exit(1);
+
+
+	if (!COSE_Sign0_Sign(hSignObj, pkey, NULL)) exit(1);
+
+	size_t cb = COSE_Encode((HCOSE)hSignObj, NULL, 0, 0) + 1;
+	byte * rgb = (byte *)malloc(cb);
+	cb = COSE_Encode((HCOSE)hSignObj, rgb, 0, cb);
+
+	COSE_Sign0_Free(hSignObj);
+
+	int f = _ValidateSign0(pControl, rgb, cb);
+
+	free(rgb);
+	return f;
+
+returnError:
+	CFails += 1;
+	return 1;
+}
+
diff --git a/test/test.c b/test/test.c
index 0774d6a..7098c6b 100644
--- a/test/test.c
+++ b/test/test.c
@@ -197,7 +197,7 @@
 		}
 		else if (strcmp(pKey->v.str, "IV_hex") == 0) {
 			keyNew = COSE_Header_IV;
-			pValueNew = cn_cbor_data_create(FromHex(pValue->v.str, pValue->length), (int) pValue->length / 2, CBOR_CONTEXT_PARAM_COMMA NULL);
+			pValueNew = cn_cbor_data_create(FromHex(pValue->v.str, (int) pValue->length), (int) pValue->length / 2, CBOR_CONTEXT_PARAM_COMMA NULL);
 		}
 		else {
 			continue;
@@ -205,11 +205,27 @@
 
 		switch (which) {
 		case Attributes_MAC_protected:
-			COSE_Mac_map_put((HCOSE_MAC)hHandle, keyNew, pValueNew, COSE_PROTECT_ONLY, NULL);
+			COSE_Mac_map_put_int((HCOSE_MAC)hHandle, keyNew, pValueNew, COSE_PROTECT_ONLY, NULL);
 			break;
 
 		case Attributes_MAC_unprotected:
-			COSE_Mac_map_put((HCOSE_MAC)hHandle, keyNew, pValueNew, COSE_UNPROTECT_ONLY, NULL);
+			COSE_Mac_map_put_int((HCOSE_MAC)hHandle, keyNew, pValueNew, COSE_UNPROTECT_ONLY, NULL);
+			break;
+
+		case Attributes_MAC_unsent:
+			COSE_Mac_map_put_int((HCOSE_MAC)hHandle, keyNew, pValueNew, COSE_DONT_SEND, NULL);
+			break;
+
+		case Attributes_MAC0_protected:
+			COSE_Mac0_map_put_int((HCOSE_MAC0)hHandle, keyNew, pValueNew, COSE_PROTECT_ONLY, NULL);
+			break;
+
+		case Attributes_MAC0_unprotected:
+			COSE_Mac0_map_put_int((HCOSE_MAC0)hHandle, keyNew, pValueNew, COSE_UNPROTECT_ONLY, NULL);
+			break;
+
+		case Attributes_MAC0_unsent:
+			COSE_Mac0_map_put_int((HCOSE_MAC0)hHandle, keyNew, pValueNew, COSE_DONT_SEND, NULL);
 			break;
 
 		case Attributes_Recipient_protected:
@@ -271,6 +287,19 @@
 		case Attributes_Signer_unsent:
 			COSE_Signer_map_put((HCOSE_SIGNER)hHandle, keyNew, pValueNew, COSE_DONT_SEND, NULL);
 			break;
+
+		case Attributes_Sign0_protected:
+			COSE_Sign0_map_put_int((HCOSE_SIGN0)hHandle, keyNew, pValueNew, COSE_PROTECT_ONLY, NULL);
+			break;
+
+		case Attributes_Sign0_unprotected:
+			COSE_Sign0_map_put_int((HCOSE_SIGN0)hHandle, keyNew, pValueNew, COSE_UNPROTECT_ONLY, NULL);
+			break;
+
+		case Attributes_Sign0_unsent:
+			COSE_Sign0_map_put_int((HCOSE_SIGN0)hHandle, keyNew, pValueNew, COSE_DONT_SEND, NULL);
+			break;
+
 		}
 	}
 
@@ -398,6 +427,10 @@
 			ValidateMAC(pControl);
 			BuildMacMessage(pControl);
 		}
+		else if (cn_cbor_mapget_string(pInput, "mac0") != NULL) {
+			ValidateMac0(pControl);
+			BuildMac0Message(pControl);
+		}
 		else if (cn_cbor_mapget_string(pInput, "enveloped") != NULL) {
 			ValidateEnveloped(pControl);
 			BuildEnvelopedMessage(pControl);
@@ -406,6 +439,10 @@
 			ValidateSigned(pControl);
 			BuildSignedMessage(pControl);
 		}
+		else if (cn_cbor_mapget_string(pInput, "sign0") != NULL) {
+			ValidateSign0(pControl);
+			BuildSign0Message(pControl);
+		}
 		else if (cn_cbor_mapget_string(pInput, "encrypted") != NULL) {
 			ValidateEncrypt(pControl);
 			BuildEncryptMessage(pControl);
diff --git a/test/test.h b/test/test.h
index e9f9178..b4629b1 100644
--- a/test/test.h
+++ b/test/test.h
@@ -24,17 +24,25 @@
 int ValidateSigned(const cn_cbor * pControl);
 int SignMessage();
 int BuildSignedMessage(const cn_cbor * pControl);
+int ValidateSign0(const cn_cbor * pControl);
+int BuildSign0Message(const cn_cbor * pControl);
 
 // mac_testc
 
 int ValidateMAC(const cn_cbor * pControl);
 int MacMessage();
 int BuildMacMessage(const cn_cbor * pControl);
+int ValidateMac0(const cn_cbor * pControl);
+int BuildMac0Message(const cn_cbor * pControl);
 
 //  test.c
 enum {
 	Attributes_MAC_protected=1,
 	Attributes_MAC_unprotected,
+	Attributes_MAC_unsent,
+	Attributes_MAC0_protected,
+	Attributes_MAC0_unprotected,
+	Attributes_MAC0_unsent,
 	Attributes_Recipient_protected,
 	Attributes_Recipient_unprotected,
 	Attributes_Recipient_unsent,
@@ -50,6 +58,9 @@
 	Attributes_Signer_protected,
 	Attributes_Signer_unprotected,
 	Attributes_Signer_unsent,
+	Attributes_Sign0_protected,
+	Attributes_Sign0_unprotected,
+	Attributes_Sign0_unsent,
 } whichSet;
 
 extern int CFails;