And part three

Error doing the commit from the tool means a breakdown
diff --git a/src/Recipient.c b/src/Recipient.c
index 0f6cb1f..7ea8005 100644
--- a/src/Recipient.c
+++ b/src/Recipient.c
@@ -28,6 +28,7 @@
 			if (perr != NULL) perr->err = COSE_ERR_INVALID_PARAMETER;
 			return NULL;
 		}
+		p = p->m_recipientNext;
 	}
 	return (HCOSE_RECIPIENT)p;
 }
@@ -42,6 +43,11 @@
 		return NULL;
 	}
 
+	if (cbor->type != CN_CBOR_MAP) {
+		if (errp != NULL) errp->err = COSE_ERR_INVALID_PARAMETER;
+		COSE_FREE(pRecipient, context);
+		return NULL;
+	}
 	if (_COSE_Encrypt_Init_From_Object(cbor, &pRecipient->m_encrypt, CBOR_CONTEXT_PARAM_COMMA errp) == NULL) {
 		_COSE_Recipient_Free(pRecipient);
 		return NULL;
@@ -59,7 +65,7 @@
 
 bool _COSE_Recipient_decrypt(COSE_RecipientInfo * pRecip, int cbitKey, byte * pbKey, cose_errback * perr)
 {
-	return _COSE_Encrypt_decrypt(&pRecip->m_encrypt, NULL, perr);
+	return _COSE_Encrypt_decrypt(&pRecip->m_encrypt, NULL, cbitKey, pbKey, perr);
 }
 
 
@@ -69,7 +75,7 @@
 	const cn_cbor * cn_Alg = _COSE_map_get_int(&pRecipient->m_encrypt.m_message, COSE_Header_Algorithm, COSE_BOTH, NULL);
 
 	if (cn_Alg == NULL) return false;
-	if (cn_Alg->type != CN_CBOR_UINT) return false;
+	if ((cn_Alg->type != CN_CBOR_UINT) && (cn_Alg->type != CN_CBOR_INT)) return false;
 	alg = cn_Alg->v.uint;
 
 	switch (alg) {
diff --git a/src/Sign.c b/src/Sign.c
index b648437..b0e5d82 100644
--- a/src/Sign.c
+++ b/src/Sign.c
@@ -3,64 +3,98 @@
 #include "cose.h"
 #include "cose_int.h"
 
-
-HCOSE COSE_Decode(const byte * rgbData, int cbData, int * ptype, CBOR_CONTEXT_COMMA cose_errback * errp)
+bool IsValidSignHandle(HCOSE_SIGN h)
 {
-	cn_cbor * cbor;
-	const cn_cbor * pType = NULL;
-	HCOSE h;
-
-	if ((rgbData == NULL) || (ptype == NULL)) {
-		if (errp != NULL) errp->err = COSE_ERR_INVALID_PARAMETER;
-		return NULL;
-	}
-
-	cbor = (cn_cbor *) cn_cbor_decode(rgbData, cbData, CBOR_CONTEXT_PARAM_COMMA NULL);
-	if (cbor == NULL) {
-		if (errp != NULL) errp->err = COSE_ERR_CBOR;
-		return NULL;
-	}
-
-	if (cbor->type != CN_CBOR_MAP) {
-	error:
-		COSE_FREE(cbor, context);
-		if (errp != NULL) errp->err = COSE_ERR_INVALID_PARAMETER;
-		return NULL;
-	}
-
-	pType = cn_cbor_mapget_int(cbor, COSE_Header_Type);
-	if ((pType == NULL) || (pType->type != CN_CBOR_UINT)) goto error;
-
-	switch (pType->v.sint) {
-	case 1:
-		h = (HCOSE) _COSE_Encrypt_Init_From_Object(cbor, NULL, CBOR_CONTEXT_PARAM_COMMA errp);
-		if (h == NULL) {
-			COSE_FREE(cbor, context);
-			return NULL;
-		}
-		return h;
-
-//	case 2:
-//		return (COSE *)COSE_Sign_Init(cbor CBOR_CONTEXT_PARAM);
-	}
-
-	goto error;
+	COSE_SignMessage * p = (COSE_SignMessage *)h;
+	if (p == NULL) return false;
+	return true;
 }
 
-#if 0
-COSE_SignMessage * COSE_Sign_Init(const cn_cbor * CBOR_CONTEXT)
+
+HCOSE_SIGN COSE_Sign_Init(CBOR_CONTEXT_COMMA cose_errback * perror)
 {
-	COSE_SignMessage * msg;
+	COSE_SignMessage * pobj = (COSE_SignMessage *)COSE_CALLOC(1, sizeof(COSE_SignMessage), context);
+	if (pobj == NULL) {
+		if (perror != NULL) perror->err = COSE_ERR_OUT_OF_MEMORY;
+		return NULL;
+	}
+
+	if (!_COSE_Init(&pobj->m_message, CBOR_CONTEXT_PARAM_COMMA perror)) {
+	error_setup:
+		COSE_Sign_Free((HCOSE_SIGN)pobj);
+		return NULL;
+	}
+
+	if (!cn_cbor_mapput_int(pobj->m_message.m_cbor, COSE_Header_Type, cn_cbor_int_create(2, CBOR_CONTEXT_PARAM_COMMA NULL), CBOR_CONTEXT_PARAM_COMMA NULL)) {
+		if (perror != NULL) perror->err = COSE_ERR_OUT_OF_MEMORY;
+		goto error_setup;
+	}
+
+	return (HCOSE_SIGN)pobj;
+}
+
+HCOSE_SIGN _COSE_Sign_Init_From_Object(cn_cbor * cbor, COSE_SignMessage * pIn, CBOR_CONTEXT_COMMA cose_errback * perr)
+{
+	COSE_SignMessage * pobj = pIn;
+	cn_cbor * pSigners = NULL;
+	// cn_cbor * tmp;
+	cose_errback error = { 0 };
+	if (perr == NULL) perr = &error;
+
+	if (pobj == NULL) pobj = (COSE_SignMessage *)COSE_CALLOC(1, sizeof(COSE_SignMessage), 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;
+	}
+
+	pSigners = (cn_cbor *)cn_cbor_mapget_int(cbor, COSE_Header_Recipients);
+	if (pSigners != NULL) {
+		CHECK_CONDITION(pSigners->type == CN_CBOR_ARRAY, COSE_ERR_INVALID_PARAMETER);
+
+		pSigners = pSigners->first_child;
+		while (pSigners != NULL) {
+			COSE_SignerInfo * pInfo = _COSE_SignerInfo_Init_From_Object(pSigners, CBOR_CONTEXT_PARAM_COMMA perr);
+			CHECK_CONDITION(pInfo != NULL, COSE_ERR_OUT_OF_MEMORY);
+
+			pInfo->m_signerNext = pobj->m_signerFirst;
+			pobj->m_signerFirst = pInfo;
+			pSigners = pSigners->next;
+		}
+	}
+
+	return(HCOSE_SIGN)pobj;
+}
+
+bool COSE_Sign_Free(HCOSE_SIGN h)
+{
+#ifdef USE_CBOR_CONTEXT
+	cn_cbor_context context;
+#endif
+
+	if (!IsValidSignHandle(h)) return false;
 
 #ifdef USE_CBOR_CONTEXT
-	msg = (COSE_SignMessage *) context->calloc_func(1, sizeof(COSE_SignMessage), context->context);
-#else
-	msg = (COSE_SignMessage *) calloc(1, sizeof(COSE_SignMessage));
+	context = ((COSE_SignMessage *)h)->m_message.m_allocContext;
 #endif
 
-	msg->m_message.m_flags = 1;
-	msg->m_message.m_cbor = (cn_cbor *) msg;
+	_COSE_Sign_Release((COSE_SignMessage *)h);
 
-	return msg;
+	COSE_FREE((COSE_SignMessage *)h, &context);
+
+	return true;
 }
-#endif
+
+void _COSE_Sign_Release(COSE_SignMessage * p)
+{
+	// if (p->pbContent != NULL) COSE_FREE(p->pbContent, &p->m_message.m_allocContext);
+	//	if (p->pbIV != NULL) COSE_FREE(p->pbIV, &p->m_message.m_allocContext);
+	// if (p->pbKey != NULL) COSE_FREE(p->pbKey, &p->m_message.m_allocContext);
+
+	_COSE_Release(&p->m_message);
+}
diff --git a/src/SignerInfo.c b/src/SignerInfo.c
new file mode 100644
index 0000000..bc32412
--- /dev/null
+++ b/src/SignerInfo.c
@@ -0,0 +1,67 @@
+#include <stdlib.h>
+#include <memory.h>
+
+#include "cose.h"
+#include "cose_int.h"
+#include "configure.h"
+#include "crypto.h"
+
+extern bool IsValidSignHandle(HCOSE_SIGN h);
+
+bool IsValidSignerHandle(HCOSE_SIGNER h)
+{
+	if (h == NULL) return false;
+	return true;
+}
+
+void _COSE_Signer_Free(COSE_SignerInfo * pSigner)
+{
+	COSE_FREE(pSigner, &pSigner->m_message.m_allocContext);
+
+	return;
+}
+
+
+HCOSE_SIGNER COSE_Sign_GetSigner(HCOSE_SIGN cose, int iSigner, cose_errback * perr)
+{
+	int i;
+	COSE_SignerInfo * p;
+
+	if (!IsValidSignHandle(cose)) {
+		if (perr != NULL) perr->err = COSE_ERR_INVALID_PARAMETER;
+		return NULL;
+	}
+
+	p = ((COSE_SignMessage *)cose)->m_signerFirst;
+	for (i = 0; i < iSigner; i++) {
+		if (p == NULL) {
+			if (perr != NULL) perr->err = COSE_ERR_INVALID_PARAMETER;
+			return NULL;
+		}
+		p = p->m_signerNext;
+	}
+	return (HCOSE_SIGNER)p;
+}
+
+COSE_SignerInfo * _COSE_SignerInfo_Init_From_Object(cn_cbor * cbor, CBOR_CONTEXT_COMMA cose_errback * perr)
+{
+	COSE_SignerInfo * pSigner = NULL;
+
+	pSigner = (COSE_SignerInfo *)COSE_CALLOC(1, sizeof(COSE_SignerInfo), context);
+	if (pSigner == NULL) {
+		if (perr != NULL) perr->err = COSE_ERR_OUT_OF_MEMORY;
+		return NULL;
+	}
+
+	if (cbor->type != CN_CBOR_MAP) {
+		if (perr != NULL) perr->err = COSE_ERR_INVALID_PARAMETER;
+		COSE_FREE(pSigner, context);
+		return NULL;
+	}
+	if (!_COSE_Init_From_Object(&pSigner->m_message, cbor, CBOR_CONTEXT_PARAM_COMMA perr)) {
+		_COSE_Signer_Free(pSigner);
+		return NULL;
+	}
+
+	return pSigner;
+}
diff --git a/src/openssl.c b/src/openssl.c
index ac3fab5..a43f285 100644
--- a/src/openssl.c
+++ b/src/openssl.c
@@ -3,73 +3,100 @@
 #include "cose_int.h"
 #include "crypto.h"
 
+#include <assert.h>
+
 #ifdef USE_OPEN_SSL
 
-#include <openssl\evp.h>
-#include <openssl\rand.h>
+#include <openssl/evp.h>
+#include <openssl/hmac.h>
+#include <openssl/rand.h>
 
 
-bool AES_CCM_Decrypt(COSE_Encrypt * pcose, int TSize, int LSize, const byte * pbAuthData, int cbAuthData)
+bool AES_CCM_Decrypt(COSE_Encrypt * pcose, int TSize, int LSize, const byte * pbKey, int cbKey, const byte * pbAuthData, int cbAuthData, cose_errback * perr)
 {
 	EVP_CIPHER_CTX ctx;
 	int cbOut;
 	byte * rgbOut = NULL;
-	ssize_t NSize = 15 - LSize;
+	int NSize = 15 - LSize;
 	int outl = 0;
 	byte rgbIV[15] = { 0 };
 	const cn_cbor * pIV = NULL;
+	const EVP_CIPHER * cipher;
 #ifdef USE_CBOR_CONTEXT
 	cn_cbor_context * context = &pcose->m_message.m_allocContext;
 #endif
 
+	assert(perr != NULL);
+	EVP_CIPHER_CTX_init(&ctx);
+
 	//  Setup the IV/Nonce and put it into the message
 
 	pIV = _COSE_map_get_int(&pcose->m_message, COSE_Header_IV, COSE_BOTH, NULL);
 	if ((pIV == NULL) || (pIV->type!= CN_CBOR_BYTES)) {
-	error:
+		perr->err = COSE_ERR_INVALID_PARAMETER;
+
+	errorReturn:
 		if (rgbOut != NULL) COSE_FREE(rgbOut, context);
+		EVP_CIPHER_CTX_cleanup(&ctx);
 		return false;
 	}
 
-	if (pIV->length > NSize) goto error;
+	CHECK_CONDITION(pIV->length <= NSize, COSE_ERR_INVALID_PARAMETER);
 	memcpy(&rgbIV[NSize - pIV->length], pIV->v.str, pIV->length);
 
 	//  Setup and run the OpenSSL code
 
-	EVP_CIPHER_CTX_init(&ctx);
-	EVP_EncryptInit_ex(&ctx, EVP_aes_128_ccm(), NULL, NULL, NULL);
+	switch (cbKey) {
+	case 128/8:
+		cipher = EVP_aes_128_ccm();
+		break;
 
-	EVP_CIPHER_CTX_ctrl(&ctx, EVP_CTRL_CCM_SET_L, LSize, 0);
-	EVP_CIPHER_CTX_ctrl(&ctx, EVP_CTRL_CCM_SET_IVLEN, NSize, 0);
-	EVP_CIPHER_CTX_ctrl(&ctx, EVP_CTRL_CCM_SET_TAG, TSize, NULL);	// Say we are doing an 8 byte tag
+	case 192/8:
+		cipher = EVP_aes_192_ccm();
+		break;
 
-	EVP_EncryptInit(&ctx, 0, pcose->pbKey, rgbIV);
+	case 256/8:
+		cipher = EVP_aes_256_ccm();
+		break;
 
-	EVP_EncryptUpdate(&ctx, 0, &cbOut, 0, pcose->cbContent);
+	default:
+		CHECK_CONDITION(false, COSE_ERR_INVALID_PARAMETER);
+		break;
+	}
+	CHECK_CONDITION(EVP_DecryptInit_ex(&ctx, cipher, NULL, NULL, NULL), COSE_ERR_DECRYPT_FAILED);
 
-	EVP_EncryptUpdate(&ctx, NULL, &outl, pbAuthData, cbAuthData);
+	CHECK_CONDITION(EVP_CIPHER_CTX_ctrl(&ctx, EVP_CTRL_CCM_SET_L, LSize, 0), COSE_ERR_DECRYPT_FAILED);
+	CHECK_CONDITION(EVP_CIPHER_CTX_ctrl(&ctx, EVP_CTRL_CCM_SET_IVLEN, NSize, 0), COSE_ERR_DECRYPT_FAILED);
+	CHECK_CONDITION(EVP_CIPHER_CTX_ctrl(&ctx, EVP_CTRL_CCM_SET_TAG, TSize, &pcose->pbContent[pcose->cbContent - TSize]), COSE_ERR_DECRYPT_FAILED);
 
-	rgbOut = (byte *)COSE_CALLOC(cbOut + TSize, 1, context);
-	if (rgbOut == NULL) goto error;
+	CHECK_CONDITION(EVP_DecryptInit(&ctx, 0, pbKey, rgbIV), COSE_ERR_DECRYPT_FAILED);
 
-	EVP_EncryptUpdate(&ctx, rgbOut, &cbOut, pcose->pbContent, pcose->cbContent);
 
-	EVP_EncryptFinal_ex(&ctx, &rgbOut[cbOut], &cbOut);
+	CHECK_CONDITION(EVP_DecryptUpdate(&ctx, NULL, &cbOut, NULL, pcose->cbContent-TSize), COSE_ERR_DECRYPT_FAILED);
 
-	EVP_CIPHER_CTX_ctrl(&ctx, EVP_CTRL_CCM_GET_TAG, TSize, &rgbOut[pcose->cbContent]);
+	cbOut = pcose->cbContent - TSize;
+	rgbOut = (byte *)COSE_CALLOC(cbOut, 1, context);
+	CHECK_CONDITION(rgbOut != NULL, CN_CBOR_ERR_OUT_OF_MEMORY);
 
-	cn_cbor_mapput_int(pcose->m_message.m_cbor, COSE_Header_Ciphertext, cn_cbor_data_create(rgbOut, pcose->cbContent + TSize, CBOR_CONTEXT_PARAM_COMMA NULL), CBOR_CONTEXT_PARAM_COMMA NULL);
+	CHECK_CONDITION(EVP_DecryptUpdate(&ctx, NULL, &outl, pbAuthData, cbAuthData), COSE_ERR_DECRYPT_FAILED);
+
+	CHECK_CONDITION(EVP_DecryptUpdate(&ctx, rgbOut, &cbOut, pcose->pbContent, pcose->cbContent-TSize), COSE_ERR_DECRYPT_FAILED);
+
+	EVP_CIPHER_CTX_cleanup(&ctx);
+
+	pcose->pbContent = rgbOut;
+	pcose->cbContent = cbOut;
 
 	return true;
 }
 
 
-bool AES_CCM_Encrypt(COSE_Encrypt * pcose, int TSize, int LSize, const byte * pbAuthData, int cbAuthData)
+bool AES_CCM_Encrypt(COSE_Encrypt * pcose, int TSize, int LSize, const byte * pbAuthData, int cbAuthData, cose_errback * perr)
 {
 	EVP_CIPHER_CTX ctx;
 	int cbOut;
 	byte * rgbOut = NULL;
-	ssize_t NSize = 15 - LSize;
+	int NSize = 15 - LSize;
 	int outl = 0;
 	byte rgbIV[15] = { 0 };
 	const cn_cbor * cbor_iv = NULL;
@@ -81,47 +108,81 @@
 
 	cbor_iv = _COSE_map_get_int(&pcose->m_message, COSE_Header_IV, COSE_BOTH, NULL);
 	if ((cbor_iv == NULL) || (cbor_iv->type != CN_CBOR_BYTES)) {
-		error:
+		perr->err = COSE_ERR_INVALID_PARAMETER;
+		errorReturn:
 		if (rgbOut != NULL) COSE_FREE(rgbOut, context);
+		EVP_CIPHER_CTX_cleanup(&ctx);
 		return false;
 	}
 
-	if (cbor_iv->length > NSize) goto error;
+	CHECK_CONDITION(cbor_iv->length <= NSize, COSE_ERR_INVALID_PARAMETER);
 	memcpy(&rgbIV[NSize-cbor_iv->length], cbor_iv->v.str, cbor_iv->length);
 
-#if 0
-	if (!cn_cbor_mapput_int(pcose->m_message.m_cbor, COSE_Header_IV, cn_cbor_data_create(rgbIV, NSize, CBOR_CONTEXT_PARAM_COMMA NULL), CBOR_CONTEXT_PARAM_COMMA NULL)) {
-		goto error;
-	}
-#endif
-
 	//  Setup and run the OpenSSL code
 
 	EVP_CIPHER_CTX_init(&ctx);
-	EVP_EncryptInit_ex(&ctx, EVP_aes_128_ccm(), NULL, NULL, NULL);
+	CHECK_CONDITION(EVP_EncryptInit_ex(&ctx, EVP_aes_128_ccm(), NULL, NULL, NULL), COSE_ERR_CRYPTO_FAIL);
 
 	TSize /= 8; // Comes in in bits not bytes.
-	EVP_CIPHER_CTX_ctrl(&ctx, EVP_CTRL_CCM_SET_L, LSize, 0);
-	EVP_CIPHER_CTX_ctrl(&ctx, EVP_CTRL_CCM_SET_IVLEN, NSize, 0);
-	EVP_CIPHER_CTX_ctrl(&ctx, EVP_CTRL_CCM_SET_TAG, TSize, NULL);	// Say we are doing an 8 byte tag
+	CHECK_CONDITION(EVP_CIPHER_CTX_ctrl(&ctx, EVP_CTRL_CCM_SET_L, LSize, 0), COSE_ERR_CRYPTO_FAIL);
+	CHECK_CONDITION(EVP_CIPHER_CTX_ctrl(&ctx, EVP_CTRL_CCM_SET_IVLEN, NSize, 0), COSE_ERR_CRYPTO_FAIL);
+	CHECK_CONDITION(EVP_CIPHER_CTX_ctrl(&ctx, EVP_CTRL_CCM_SET_TAG, TSize, NULL), COSE_ERR_CRYPTO_FAIL);	// Say we are doing an 8 byte tag
 
-	EVP_EncryptInit(&ctx, 0, pcose->pbKey, rgbIV);
+	CHECK_CONDITION(EVP_EncryptInit(&ctx, 0, pcose->pbKey, rgbIV), COSE_ERR_CRYPTO_FAIL);
 
-	EVP_EncryptUpdate(&ctx, 0, &cbOut, 0, pcose->cbContent);
+	CHECK_CONDITION(EVP_EncryptUpdate(&ctx, 0, &cbOut, 0, pcose->cbContent), COSE_ERR_CRYPTO_FAIL);
 
-	EVP_EncryptUpdate(&ctx, NULL, &outl, pbAuthData, cbAuthData);
+	CHECK_CONDITION(EVP_EncryptUpdate(&ctx, NULL, &outl, pbAuthData, cbAuthData), COSE_ERR_CRYPTO_FAIL);
 
 	rgbOut = (byte *)COSE_CALLOC(cbOut + TSize, 1, context);
-	if (rgbOut == NULL) goto error;
+	CHECK_CONDITION(rgbOut != NULL, COSE_ERR_OUT_OF_MEMORY);
 
-	EVP_EncryptUpdate(&ctx, rgbOut, &cbOut, pcose->pbContent, pcose->cbContent);
+	CHECK_CONDITION(EVP_EncryptUpdate(&ctx, rgbOut, &cbOut, pcose->pbContent, pcose->cbContent), COSE_ERR_CRYPTO_FAIL);
 
-	EVP_EncryptFinal_ex(&ctx, &rgbOut[cbOut], &cbOut);
+	CHECK_CONDITION(EVP_EncryptFinal_ex(&ctx, &rgbOut[cbOut], &cbOut), COSE_ERR_CRYPTO_FAIL);
 
-	EVP_CIPHER_CTX_ctrl(&ctx, EVP_CTRL_CCM_GET_TAG, TSize, &rgbOut[pcose->cbContent]);
+	CHECK_CONDITION(EVP_CIPHER_CTX_ctrl(&ctx, EVP_CTRL_CCM_GET_TAG, TSize, &rgbOut[pcose->cbContent]), COSE_ERR_CRYPTO_FAIL);
 
-	cn_cbor_mapput_int(pcose->m_message.m_cbor, COSE_Header_Ciphertext, cn_cbor_data_create(rgbOut,  pcose->cbContent + TSize, CBOR_CONTEXT_PARAM_COMMA NULL), CBOR_CONTEXT_PARAM_COMMA NULL);
+	CHECK_CONDITION(cn_cbor_mapput_int(pcose->m_message.m_cbor, COSE_Header_Ciphertext, cn_cbor_data_create(rgbOut,  pcose->cbContent + TSize, CBOR_CONTEXT_PARAM_COMMA NULL), CBOR_CONTEXT_PARAM_COMMA NULL), COSE_ERR_CBOR);
 
+	EVP_CIPHER_CTX_cleanup(&ctx);
+	return true;
+}
+
+bool HMAC_Create(COSE_Encrypt * pcose, int HSize, int TSize, const byte * pbAuthData, int cbAuthData, cose_errback * perr)
+{
+	HMAC_CTX ctx;
+	EVP_MD * pmd = NULL;
+	byte * rgbOut = NULL;
+	unsigned int cbOut;
+#ifdef USE_CBOR_CONTEXT
+	cn_cbor_context * context = &pcose->m_message.m_allocContext;
+#endif
+
+	HMAC_CTX_init(&ctx);
+
+	if (0) {
+	errorReturn:
+		COSE_FREE(rgbOut, context);
+		HMAC_cleanup(&ctx);
+		return false;
+	}
+
+	switch (HSize) {
+	case 256: pmd = EVP_sha256(); break;
+	default: CHECK_CONDITION(false, COSE_ERR_INVALID_PARAMETER); break;
+	}
+
+	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, pcose->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);
+
+	CHECK_CONDITION(cn_cbor_mapput_int(pcose->m_message.m_cbor, COSE_Header_Tag, cn_cbor_data_create(rgbOut, TSize/8, CBOR_CONTEXT_PARAM_COMMA NULL), CBOR_CONTEXT_PARAM_COMMA NULL), COSE_ERR_CBOR);
+
+	HMAC_cleanup(&ctx);
 	return true;
 }
 
diff --git a/test/test.c b/test/test.c
index 9563941..793788a 100644
--- a/test/test.c
+++ b/test/test.c
@@ -13,10 +13,58 @@
 
 int main(int argc, char * argv[])
 {
+	MacMessage();
+	SignMessage();
 	EncryptMessage();
 	return 0;
 }
 
+int MacMessage()
+{
+	HCOSE_MAC hEncObj = COSE_Mac_Init(NULL, NULL);
+	char * sz = "This is the content to be used";
+	byte rgbSecret[256 / 8] = { 'a', 'b', 'c' };
+	byte  rgbKid[6] = { 'a', 'b', 'c', 'd', 'e', 'f' };
+	int cbKid = 6;
+	ssize_t cb;
+	byte * rgb;
+
+	COSE_Mac_map_put(hEncObj, COSE_Header_Algorithm, cn_cbor_int_create(COSE_Algorithm_HMAC_256_256, NULL, NULL), COSE_PROTECT_ONLY, NULL);
+	COSE_Mac_SetContent(hEncObj, sz, strlen(sz), NULL);
+
+	COSE_Mac_add_shared_secret(hEncObj, COSE_Algorithm_Direct, rgbSecret, sizeof(rgbSecret), rgbKid, cbKid, NULL);
+
+	COSE_Mac_encrypt(hEncObj, NULL);
+
+	cb = COSE_Encode((HCOSE)hEncObj, NULL, 0, 0) + 1;
+	rgb = (byte *)malloc(cb);
+	cb = COSE_Encode((HCOSE)hEncObj, rgb, 0, cb);
+
+
+	FILE * fp = fopen("test.mac.cbor", "wb");
+	fwrite(rgb, cb, 1, fp);
+	fclose(fp);
+
+	char * szX;
+	int cbPrint = 0;
+	cn_cbor * cbor = COSE_get_cbor((HCOSE)hEncObj);
+	cbPrint = cn_cbor_printer_write(NULL, 0, cbor, "  ", "\r\n");
+	szX = malloc(cbPrint);
+	cn_cbor_printer_write(szX, cbPrint, cbor, "  ", "\r\n");
+	fprintf(stdout, szX);
+	fprintf(stdout, "\r\n");
+
+	COSE_Mac_Free(hEncObj);
+
+}
+
+int SignMessage()
+{
+	HCOSE_SIGN hEncObj = COSE_Sign_Init(NULL, NULL);
+
+
+}
+
 int EncryptMessage()
 {
 	HCOSE_ENCRYPT hEncObj = COSE_Encrypt_Init(NULL, NULL);
@@ -24,12 +72,12 @@
 	int cbSecret = 128/8;
 	byte  rgbKid[6] = { 'a', 'b', 'c', 'd', 'e', 'f' };
 	int cbKid = 6;
-	int cb;
+	ssize_t cb;
 	byte * rgb;
 	char * sz = "This is the content to be used";
 
 
-	COSE_Encrypt_map_put(hEncObj, COSE_Header_Algorithm, cn_cbor_int_create(COSE_Algorithm_AES_CCM_64, NULL, NULL), COSE_PROTECT_ONLY, NULL);
+	COSE_Encrypt_map_put(hEncObj, COSE_Header_Algorithm, cn_cbor_int_create(COSE_Algorithm_AES_CCM_16_64_128, NULL, NULL), COSE_PROTECT_ONLY, NULL);
 	COSE_Encrypt_SetContent(hEncObj, sz, strlen(sz), NULL);
 	COSE_Encrypt_map_put(hEncObj, COSE_Header_IV, cn_cbor_data_create(rgbKid, cbKid, NULL, NULL), COSE_UNPROTECT_ONLY, NULL);
 
@@ -47,11 +95,11 @@
 	fclose(fp);
 
 	char * szX;
-	int cbPrint;
+	int cbPrint = 0;
 	cn_cbor * cbor = COSE_get_cbor((HCOSE) hEncObj);
-	cbPrint = cn_cbor_printer_write(NULL, 0, cbor, "  ", "\r\n");
+	//cbPrint = cn_cbor_printer_write(NULL, 0, cbor, "  ", "\r\n");
 	szX = malloc(cbPrint);
-	cn_cbor_printer_write(szX, cbPrint, cbor, "  ", "\r\n");
+	//cn_cbor_printer_write(szX, cbPrint, cbor, "  ", "\r\n");
 	fprintf(stdout, szX);
 	fprintf(stdout, "\r\n");
 
@@ -73,6 +121,8 @@
 
 		COSE_Encrypt_decrypt(hEncObj, hRecip, NULL);
 
+		iRecipient += 1;
+
 	} while (true);
 
 	return 1;