Merge pull request #31 from jimsch/master

Coverity Cleanup
diff --git a/Doxyfile.in b/Doxyfile.in
new file mode 100644
index 0000000..63d95b4
--- /dev/null
+++ b/Doxyfile.in
@@ -0,0 +1,10 @@
+PROJECT_NAME           = "@CMAKE_PROJECT_NAME@"
+PROJECT_NUMBER         = @CN_VERSION@
+STRIP_FROM_PATH        = @PROJECT_SOURCE_DIR@ \
+                         @PROJECT_BINARY_DIR@
+INPUT                  = @PROJECT_SOURCE_DIR@/README.md \
+                         @PROJECT_SOURCE_DIR@/include \
+                         src
+FILE_PATTERNS          = *.c
+RECURSIVE              = YES
+USE_MDFILE_AS_MAINPAGE = README.md
diff --git a/src/Cose.c b/src/Cose.c
index 33ac49d..7524ec0 100644
--- a/src/Cose.c
+++ b/src/Cose.c
@@ -14,7 +14,7 @@
 }
 
 
-bool _COSE_Init(COSE* pobj, int msgType, CBOR_CONTEXT_COMMA cose_errback * perr)
+bool _COSE_Init(COSE_INIT_FLAGS flags, COSE* pobj, int msgType, CBOR_CONTEXT_COMMA cose_errback * perr)
 {
 		    cn_cbor_errback errState;;
 
@@ -22,14 +22,19 @@
 	if (context != NULL) pobj->m_allocContext = *context;
 #endif
 
+	CHECK_CONDITION((flags & ~(COSE_INIT_FLAGS_DETACHED_CONTENT | COSE_INIT_FLAGS_NO_CBOR_TAG)) == 0, COSE_ERR_INVALID_PARAMETER);
+
+	pobj->m_flags = flags;
+
 	pobj->m_protectedMap = cn_cbor_map_create(CBOR_CONTEXT_PARAM_COMMA &errState);
 	CHECK_CONDITION_CBOR(pobj->m_protectedMap != NULL, errState);
 
 	pobj->m_dontSendMap = cn_cbor_map_create(CBOR_CONTEXT_PARAM_COMMA &errState);
 	CHECK_CONDITION_CBOR(pobj->m_dontSendMap != NULL, errState);
 
-	pobj->m_cbor = cn_cbor_array_create(CBOR_CONTEXT_PARAM_COMMA &errState);
+	pobj->m_cborRoot = pobj->m_cbor = cn_cbor_array_create(CBOR_CONTEXT_PARAM_COMMA &errState);
 	CHECK_CONDITION_CBOR(pobj->m_cbor != NULL, errState);
+	pobj->m_cborRoot = NULL;
 	pobj->m_ownMsg = 1;
 
 #ifdef TAG_IN_ARRAY
@@ -48,6 +53,14 @@
 	CHECK_CONDITION_CBOR(_COSE_array_replace(pobj, pobj->m_unprotectMap, INDEX_UNPROTECTED, CBOR_CONTEXT_PARAM_COMMA &errState), errState);
 	pobj->m_ownUnprotectedMap = false;
 
+	/*
+	if (!(flags & COSE_INIT_FLAGS_NO_CBOR_TAG)) {
+		cn_cbor_errback cbor_error;
+		cn_cbor * cn = cn_cbor_tag_create(msgType, pobj->m_cborRoot, CBOR_CONTEXT_PARAM_COMMA &cbor_error);
+		CHECK_CONDITION_CBOR(cn != NULL, cbor_error);
+		pobj->m_cborRoot = cn;
+	}*/
+
 	pobj->m_refCount = 1;
 
 	return true;
@@ -220,6 +233,15 @@
 	return NULL;
 }
 
+byte RgbDontUse[8 * 1024];   //  Remove this array when we can compute the size of a cbor serialization without this hack.
+
+size_t COSE_Encode(HCOSE msg, byte * rgb, size_t ib, size_t cb)
+{
+	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);
+}
+
+
 cn_cbor * COSE_get_cbor(HCOSE h)
 {
 	COSE * msg = (COSE *)h;
diff --git a/src/Encrypt.c b/src/Encrypt.c
index dd253c7..cd1ba35 100644
--- a/src/Encrypt.c
+++ b/src/Encrypt.c
@@ -18,6 +18,20 @@
 
 COSE * EnvelopedRoot = NULL;
 
+/*! \private
+* @brief Test if a HCOSE_ENVELOPED handle is valid
+*
+*  Internal function to test if a enveloped message handle is valid.
+*  This will start returning invalid results and cause the code to
+*  crash if handles are not released before the memory that underlies them
+*  is deallocated.  This is an issue of a block allocator is used since
+*  in that case it is common to allocate memory but never to de-allocate it
+*  and just do that in a single big block.
+*
+*  @param h handle to be validated
+*  @returns result of check
+*/
+
 bool IsValidEnvelopedHandle(HCOSE_ENVELOPED h)
 {
 	COSE_Enveloped * p = (COSE_Enveloped *)h;
@@ -25,21 +39,29 @@
 }
 
 
-size_t COSE_Encode(HCOSE msg, byte * rgb, size_t ib, size_t cb)
-{
-	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_ENVELOPED COSE_Enveloped_Init(CBOR_CONTEXT_COMMA cose_errback * perror)
+/*!
+* @brief Allocate and initialize an object for creation of an Enveloped message object
+*
+* Allocate and initialize the object used to create a COSE Enveloped message object.
+* Supported flags are:
+*  COSE_INIT_FLAG_DETACHED_CONTENT - content is not part of the message
+*  COSE_INIT_NO_CBOR_FLAG - Do not emit the leading CBOR tag on the message.
+* 
+*  See the notes on the memory model for the use of the context variable.
+*  Applications need to free the returned handle before deallocating the 
+*  memory block that it was wrapped in for correct handle checking.
+*
+* @param flags Set of initialization flags from the COSE_INIT_FLAGS enum
+* @param context CN_CBOR context allocator struture
+* @param perr Location to return error specific information
+* @returns handle to the newly allocated object
+*/
+HCOSE_ENVELOPED COSE_Enveloped_Init(COSE_INIT_FLAGS flags, CBOR_CONTEXT_COMMA cose_errback * perr)
 {
 	COSE_Enveloped * pobj = (COSE_Enveloped *)COSE_CALLOC(1, sizeof(COSE_Enveloped), context);
-	if (pobj == NULL) {
-		if (perror != NULL) perror->err = COSE_ERR_OUT_OF_MEMORY;
-		return NULL;
-	}
+	CHECK_CONDITION(pobj != NULL, COSE_ERR_OUT_OF_MEMORY);
 
-	if (!_COSE_Init(&pobj->m_message, COSE_enveloped_object, CBOR_CONTEXT_PARAM_COMMA perror)) {
+	if (!_COSE_Init(flags,&pobj->m_message, COSE_enveloped_object, CBOR_CONTEXT_PARAM_COMMA perr)) {
 		_COSE_Enveloped_Release(pobj);
 		COSE_FREE(pobj, context);
 		return NULL;
@@ -48,6 +70,9 @@
 	_COSE_InsertInList(&EnvelopedRoot, &pobj->m_message);
 
 	return (HCOSE_ENVELOPED) pobj;
+
+errorReturn:
+	return NULL;
 }
 
 HCOSE_ENVELOPED _COSE_Enveloped_Init_From_Object(cn_cbor * cbor, COSE_Enveloped * pIn, CBOR_CONTEXT_COMMA cose_errback * perr)
@@ -140,15 +165,15 @@
 	COSE_Enveloped * pcose = (COSE_Enveloped *)h;
 	COSE_RecipientInfo * pRecip = (COSE_RecipientInfo *)hRecip;
 	cose_errback error = { 0 };
-	bool f;
+	bool f = false;
 
-	if (!IsValidEnvelopedHandle(h) || (!IsValidRecipientHandle(hRecip))) {
-		if (perr != NULL) perr->err = COSE_ERR_INVALID_PARAMETER;
-		return false;
-	}
+	CHECK_CONDITION(IsValidEnvelopedHandle(h), COSE_ERR_INVALID_HANDLE);
+	CHECK_CONDITION(IsValidRecipientHandle(hRecip), COSE_ERR_INVALID_HANDLE);
 
 	f = _COSE_Enveloped_decrypt(pcose, pRecip, 0, NULL, &error);
 	if (perr != NULL) *perr = error;
+
+	errorReturn:
 	return f;
 }
 
@@ -311,7 +336,7 @@
 	byte * pbKey = NULL;
 	size_t cbKey = 0;
 
-	CHECK_CONDITION(IsValidEnvelopedHandle(h), COSE_ERR_INVALID_PARAMETER);
+	CHECK_CONDITION(IsValidEnvelopedHandle(h), COSE_ERR_INVALID_HANDLE);
 
 #ifdef USE_CBOR_CONTEXT
 	context = &pcose->m_message.m_allocContext;
@@ -347,7 +372,7 @@
 	case COSE_Algorithm_AES_GCM_256: cbitKey = 256; break;
 
 	default:
-		FAIL_CONDITION(COSE_ERR_INVALID_PARAMETER);
+		FAIL_CONDITION(COSE_ERR_UNKNOWN_ALGORITHM);
 	}
 
 	//  If we are doing direct encryption - then recipient generates the key
@@ -415,7 +440,7 @@
 		break;
 
 	default:
-		FAIL_CONDITION(COSE_ERR_INVALID_PARAMETER);
+		FAIL_CONDITION(COSE_ERR_UNKNOWN_ALGORITHM);
 	}
 
 	for (pri = pcose->m_recipientFirst; pri != NULL; pri = pri->m_recipientNext) {
@@ -435,14 +460,15 @@
 	return fRet;
 }
 
-bool COSE_Enveloped_SetContent(HCOSE_ENVELOPED h, const byte * rgb, size_t cb, cose_errback * perror)
+bool COSE_Enveloped_SetContent(HCOSE_ENVELOPED h, const byte * rgb, size_t cb, cose_errback * perr)
 {
-	if (!IsValidEnvelopedHandle(h) || (rgb == NULL)) {
-		if (perror != NULL) perror->err = COSE_ERR_INVALID_PARAMETER;
-		return false;
-	}
+	CHECK_CONDITION(IsValidEnvelopedHandle(h), COSE_ERR_INVALID_HANDLE);
+	CHECK_CONDITION(rgb != NULL, COSE_ERR_INVALID_PARAMETER);
 
-	return _COSE_Enveloped_SetContent((COSE_Enveloped *)h, rgb, cb, perror);
+	return _COSE_Enveloped_SetContent((COSE_Enveloped *)h, rgb, cb, perr);
+
+errorReturn:
+	return false;
 }
 
 /*!
@@ -462,12 +488,13 @@
 
 bool COSE_Enveloped_SetExternal(HCOSE_ENVELOPED hcose, const byte * pbExternalData, size_t cbExternalData, cose_errback * perr)
 {
-	if (!IsValidEnvelopedHandle(hcose)) {
-		if (perr != NULL) perr->err = COSE_ERR_INVALID_PARAMETER;
-		return false;
-	}
+	CHECK_CONDITION(IsValidEnvelopedHandle(hcose), COSE_ERR_INVALID_HANDLE)
+	CHECK_CONDITION((pbExternalData != NULL) || (cbExternalData == 0), COSE_ERR_INVALID_PARAMETER);
 
 	return _COSE_SetExternal(&((COSE_Enveloped *)hcose)->m_message, pbExternalData, cbExternalData, perr);
+
+errorReturn:
+	return false;
 }
 
 
@@ -488,7 +515,7 @@
 cn_cbor * COSE_Enveloped_map_get_int(HCOSE_ENVELOPED h, int key, int flags, cose_errback * perror)
 {
 	if (!IsValidEnvelopedHandle(h)) {
-		if (perror != NULL) perror->err = COSE_ERR_INVALID_PARAMETER;
+		if (perror != NULL) perror->err = COSE_ERR_INVALID_HANDLE;
 		return NULL;
 	}
 
@@ -496,14 +523,15 @@
 }
 
 
-bool COSE_Enveloped_map_put_int(HCOSE_ENVELOPED h, int key, cn_cbor * value, int flags, cose_errback * perror)
+bool COSE_Enveloped_map_put_int(HCOSE_ENVELOPED h, int key, cn_cbor * value, int flags, cose_errback * perr)
 {
-	if (!IsValidEnvelopedHandle(h) || (value == NULL)) {
-		if (perror != NULL) perror->err = COSE_ERR_INVALID_PARAMETER;
-		return false;
-	}
+	CHECK_CONDITION(IsValidEnvelopedHandle(h), COSE_ERR_INVALID_HANDLE);
+	CHECK_CONDITION(value != NULL, COSE_ERR_INVALID_PARAMETER);
 
-	return _COSE_map_put(&((COSE_Enveloped *)h)->m_message, key, value, flags, perror);
+	return _COSE_map_put(&((COSE_Enveloped *)h)->m_message, key, value, flags, perr);
+
+errorReturn:
+	return false;
 }
 
 bool COSE_Enveloped_AddRecipient(HCOSE_ENVELOPED hEnc, HCOSE_RECIPIENT hRecip, cose_errback * perr)
@@ -516,8 +544,8 @@
 #endif
 	cn_cbor_errback cbor_error;
 
-	CHECK_CONDITION(IsValidEnvelopedHandle(hEnc), COSE_ERR_INVALID_PARAMETER);
-	CHECK_CONDITION(IsValidRecipientHandle(hRecip), COSE_ERR_INVALID_PARAMETER);
+	CHECK_CONDITION(IsValidEnvelopedHandle(hEnc), COSE_ERR_INVALID_HANDLE);
+	CHECK_CONDITION(IsValidRecipientHandle(hRecip), COSE_ERR_INVALID_HANDLE);
 
 	pEncrypt = (COSE_Enveloped *)hEnc;
 	pRecip = (COSE_RecipientInfo *)hRecip;
@@ -612,7 +640,8 @@
 	int i;
 	COSE_RecipientInfo * p = NULL;
 
-	CHECK_CONDITION(IsValidEnvelopedHandle(cose), COSE_ERR_INVALID_PARAMETER);
+	CHECK_CONDITION(IsValidEnvelopedHandle(cose), COSE_ERR_INVALID_HANDLE);
+	CHECK_CONDITION(iRecipient >= 0, COSE_ERR_INVALID_PARAMETER);
 
 	p = ((COSE_Enveloped *)cose)->m_recipientFirst;
 	for (i = 0; i < iRecipient; i++) {
diff --git a/src/Encrypt0.c b/src/Encrypt0.c
index 6585bcf..9135959 100644
--- a/src/Encrypt0.c
+++ b/src/Encrypt0.c
@@ -18,6 +18,19 @@
 
 COSE * EncryptRoot = NULL;
 
+/*! \private
+* @brief Test if a HCOSE_ENCRYPT handle is valid
+*
+*  Internal function to test if an encrypt message handle is valid.
+*  This will start returning invalid results and cause the code to
+*  crash if handles are not released before the memory that underlies them
+*  is deallocated.  This is an issue of a block allocator is used since
+*  in that case it is common to allocate memory but never to de-allocate it
+*  and just do that in a single big block.
+*
+*  @param h handle to be validated
+*  @returns result of check
+*/
 
 bool IsValidEncryptHandle(HCOSE_ENCRYPT h)
 {
@@ -26,15 +39,13 @@
 }
 
 
-HCOSE_ENCRYPT COSE_Encrypt_Init(CBOR_CONTEXT_COMMA cose_errback * perror)
+HCOSE_ENCRYPT COSE_Encrypt_Init(COSE_INIT_FLAGS flags, CBOR_CONTEXT_COMMA cose_errback * perr)
 {
+	CHECK_CONDITION(flags == COSE_INIT_FLAGS_NONE, COSE_ERR_INVALID_PARAMETER);
 	COSE_Encrypt * pobj = (COSE_Encrypt *)COSE_CALLOC(1, sizeof(COSE_Encrypt), context);
-	if (pobj == NULL) {
-		if (perror != NULL) perror->err = COSE_ERR_OUT_OF_MEMORY;
-		return NULL;
-	}
+	CHECK_CONDITION(pobj != NULL, COSE_ERR_OUT_OF_MEMORY);
 
-	if (!_COSE_Init(&pobj->m_message, COSE_enveloped_object, CBOR_CONTEXT_PARAM_COMMA perror)) {
+	if (!_COSE_Init(flags, &pobj->m_message, COSE_enveloped_object, CBOR_CONTEXT_PARAM_COMMA perr)) {
 		_COSE_Encrypt_Release(pobj);
 		COSE_FREE(pobj, context);
 		return NULL;
@@ -43,6 +54,9 @@
 	_COSE_InsertInList(&EncryptRoot, &pobj->m_message);
 
 	return (HCOSE_ENCRYPT) pobj;
+
+errorReturn:
+	return NULL;
 }
 
 HCOSE_ENCRYPT _COSE_Encrypt_Init_From_Object(cn_cbor * cbor, COSE_Encrypt * pIn, CBOR_CONTEXT_COMMA cose_errback * perr)
diff --git a/src/MacMessage.c b/src/MacMessage.c
index 8244707..78bdcfc 100644
--- a/src/MacMessage.c
+++ b/src/MacMessage.c
@@ -38,12 +38,16 @@
 }
 
 
-HCOSE_MAC COSE_Mac_Init(CBOR_CONTEXT_COMMA cose_errback * perr)
+HCOSE_MAC COSE_Mac_Init(COSE_INIT_FLAGS flags, CBOR_CONTEXT_COMMA cose_errback * perr)
 {
-	COSE_MacMessage * pobj = (COSE_MacMessage *)COSE_CALLOC(1, sizeof(COSE_MacMessage), context);
+	COSE_MacMessage * pobj = NULL;
+
+	CHECK_CONDITION(flags == COSE_INIT_FLAGS_NONE, COSE_ERR_INVALID_PARAMETER);
+
+	pobj = (COSE_MacMessage *)COSE_CALLOC(1, sizeof(COSE_MacMessage), context);
 	CHECK_CONDITION(pobj != NULL, COSE_ERR_OUT_OF_MEMORY);
 
-	if (!_COSE_Init(&pobj->m_message, COSE_mac_object, CBOR_CONTEXT_PARAM_COMMA perr)) {
+	if (!_COSE_Init(flags, &pobj->m_message, COSE_mac_object, CBOR_CONTEXT_PARAM_COMMA perr)) {
 		goto errorReturn;
 	}
 
diff --git a/src/MacMessage0.c b/src/MacMessage0.c
index 81c8c4b..1a61ffa 100644
--- a/src/MacMessage0.c
+++ b/src/MacMessage0.c
@@ -15,18 +15,36 @@
 
 COSE * Mac0Root = NULL;
 
+/*! \private
+* @brief Test if a HCOSE_MAC0 handle is valid
+*
+*  Internal function to test if a MAC0 message handle is valid.
+*  This will start returning invalid results and cause the code to
+*  crash if handles are not released before the memory that underlies them
+*  is deallocated.  This is an issue of a block allocator is used since
+*  in that case it is common to allocate memory but never to de-allocate it
+*  and just do that in a single big block.
+*
+*  @param h handle to be validated
+*  @returns result of check
+*/
+
 bool IsValidMac0Handle(HCOSE_MAC0 h)
 {
 	COSE_Mac0Message * p = (COSE_Mac0Message *)h;
 	return _COSE_IsInList(Mac0Root, (COSE *) p);
 }
 
-HCOSE_MAC0 COSE_Mac0_Init(CBOR_CONTEXT_COMMA cose_errback * perr)
+HCOSE_MAC0 COSE_Mac0_Init(COSE_INIT_FLAGS flags, CBOR_CONTEXT_COMMA cose_errback * perr)
 {
-	COSE_Mac0Message * pobj = (COSE_Mac0Message *)COSE_CALLOC(1, sizeof(COSE_Mac0Message), context);
+	COSE_Mac0Message * pobj = NULL;
+
+	CHECK_CONDITION(flags == COSE_INIT_FLAGS_NONE, COSE_ERR_INVALID_PARAMETER);
+
+	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)) {
+	if (!_COSE_Init(flags, &pobj->m_message, COSE_mac0_object, CBOR_CONTEXT_PARAM_COMMA perr)) {
 		goto errorReturn;
 	}
 
diff --git a/src/Message.c b/src/Message.c
index e62fc28..4b9ea25 100644
--- a/src/Message.c
+++ b/src/Message.c
@@ -5,9 +5,5 @@
 #include "configure.h"
 #include "crypto.h"
 
-bool _COSE_Free(COSE * p)
-{
-	COSE_FREE(p, &p->m_allocContext);
-	return true;
-}
+
 
diff --git a/src/Recipient.c b/src/Recipient.c
index 71baa81..3f8ea04 100644
--- a/src/Recipient.c
+++ b/src/Recipient.c
@@ -11,6 +11,19 @@
 
 COSE* RecipientRoot = NULL;
 
+/*! \private
+* @brief Test if a HCOSE_RECIPIENT handle is valid
+*
+*  Internal function to test if a recipient handle is valid.
+*  This will start returning invalid results and cause the code to
+*  crash if handles are not released before the memory that underlies them
+*  is deallocated.  This is an issue of a block allocator is used since
+*  in that case it is common to allocate memory but never to de-allocate it
+*  and just do that in a single big block.
+*
+*  @param h handle to be validated
+*  @returns result of check
+*/
 bool IsValidRecipientHandle(HCOSE_RECIPIENT h)
 {
 	COSE_RecipientInfo * p = (COSE_RecipientInfo *)h;
@@ -19,21 +32,22 @@
 	return _COSE_IsInList(RecipientRoot, &p->m_encrypt.m_message);
 }
 
-HCOSE_RECIPIENT COSE_Recipient_Init(CBOR_CONTEXT_COMMA cose_errback * perror)
+HCOSE_RECIPIENT COSE_Recipient_Init(COSE_INIT_FLAGS flags, CBOR_CONTEXT_COMMA cose_errback * perr)
 {
+	CHECK_CONDITION(flags == COSE_INIT_FLAGS_NONE, COSE_ERR_INVALID_PARAMETER);
 	COSE_RecipientInfo * pobj = (COSE_RecipientInfo *)COSE_CALLOC(1, sizeof(COSE_RecipientInfo), context);
-	if (pobj == NULL) {
-		if (perror != NULL) perror->err = COSE_ERR_OUT_OF_MEMORY;
-		return NULL;
-	}
+	CHECK_CONDITION(pobj != NULL, COSE_ERR_OUT_OF_MEMORY);
 
-	if (!_COSE_Init(&pobj->m_encrypt.m_message, COSE_recipient_object, CBOR_CONTEXT_PARAM_COMMA perror)) {
+	if (!_COSE_Init(flags, &pobj->m_encrypt.m_message, COSE_recipient_object, CBOR_CONTEXT_PARAM_COMMA perr)) {
 		_COSE_Recipient_Free(pobj);
 		return NULL;
 	}
 
 	_COSE_InsertInList(&RecipientRoot, &pobj->m_encrypt.m_message);
 	return (HCOSE_RECIPIENT)pobj;
+
+errorReturn:
+	return NULL;
 }
 
 bool COSE_Recipient_Free(HCOSE_RECIPIENT hRecipient)
@@ -53,7 +67,7 @@
 {
 	HCOSE_RECIPIENT hRecipient = NULL;
 
-	hRecipient = COSE_Recipient_Init(CBOR_CONTEXT_PARAM_COMMA perr);
+	hRecipient = COSE_Recipient_Init(0, CBOR_CONTEXT_PARAM_COMMA perr);
 	if (hRecipient == NULL) goto errorReturn;
 
 	if (!COSE_Recipient_SetKey_secret(hRecipient, rgbKey, cbKey, rgbKid, cbKid, perr)) goto errorReturn;
@@ -383,8 +397,8 @@
 	byte * pbContext = NULL;
 	byte rgbKey[256 / 8];
 	byte * pbSecret = NULL;
-	byte * pbKey;
-	size_t cbKey;
+	byte * pbKey = NULL;
+	size_t cbKey = 0;
 
 #ifdef USE_CBOR_CONTEXT
 	context = &pRecipient->m_encrypt.m_message.m_allocContext;
diff --git a/src/Sign.c b/src/Sign.c
index c07448c..76420cd 100644
--- a/src/Sign.c
+++ b/src/Sign.c
@@ -39,15 +39,17 @@
 * @param perr is a cose_errback return variable
 * @return HCOSE_SIGN a handle for the newly allocated object
 */
-HCOSE_SIGN COSE_Sign_Init(CBOR_CONTEXT_COMMA cose_errback * perr)
+HCOSE_SIGN COSE_Sign_Init(COSE_INIT_FLAGS flags, CBOR_CONTEXT_COMMA cose_errback * perr)
 {
+	CHECK_CONDITION(flags == COSE_INIT_FLAGS_NONE, COSE_ERR_INVALID_PARAMETER);
 	COSE_SignMessage * pobj = (COSE_SignMessage *)COSE_CALLOC(1, sizeof(COSE_SignMessage), context);
+	CHECK_CONDITION(pobj != NULL, COSE_ERR_OUT_OF_MEMORY);
 	if (pobj == NULL) {
 		if (perr != NULL) perr->err = COSE_ERR_OUT_OF_MEMORY;
 		return NULL;
 	}
 
-	if (!_COSE_Init(&pobj->m_message, COSE_sign_object, CBOR_CONTEXT_PARAM_COMMA perr)) {
+	if (!_COSE_Init(flags, &pobj->m_message, COSE_sign_object, CBOR_CONTEXT_PARAM_COMMA perr)) {
 		_COSE_Sign_Release(pobj);
 		COSE_FREE(pobj, context);
 		return NULL;
@@ -56,6 +58,9 @@
 	_COSE_InsertInList(&SignRoot, &pobj->m_message);
 
 	return (HCOSE_SIGN)pobj;
+
+errorReturn:
+	return NULL;
 }
 
 HCOSE_SIGN _COSE_Sign_Init_From_Object(cn_cbor * cbor, COSE_SignMessage * pIn, CBOR_CONTEXT_COMMA cose_errback * perr)
diff --git a/src/Sign0.c b/src/Sign0.c
index c8a9376..93c2184 100644
--- a/src/Sign0.c
+++ b/src/Sign0.c
@@ -15,9 +15,9 @@
 COSE * Sign0Root = NULL;
 
 /*! \private
-* @brief Test if a HCOSE_SIGN handle is valid
+* @brief Test if a HCOSE_SIGN0 handle is valid
 *
-*  Internal function to test if a sign handle is valid.
+*  Internal function to test if a sign0 message handle is valid.
 *  This will start returning invalid results and cause the code to
 *  crash if handles are not released before the memory that underlies them
 *  is deallocated.  This is an issue of a block allocator is used since
@@ -37,15 +37,16 @@
 }
 
 
-HCOSE_SIGN0 COSE_Sign0_Init(CBOR_CONTEXT_COMMA cose_errback * perror)
+HCOSE_SIGN0 COSE_Sign0_Init(COSE_INIT_FLAGS flags, CBOR_CONTEXT_COMMA cose_errback * perr)
 {
+	CHECK_CONDITION(flags == COSE_INIT_FLAGS_NONE, COSE_ERR_INVALID_PARAMETER);
 	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;
+		if (perr != NULL) perr->err = COSE_ERR_OUT_OF_MEMORY;
 		return NULL;
 	}
 
-	if (!_COSE_Init(&pobj->m_message, COSE_sign_object, CBOR_CONTEXT_PARAM_COMMA perror)) {
+	if (!_COSE_Init(flags,&pobj->m_message, COSE_sign_object, CBOR_CONTEXT_PARAM_COMMA perr)) {
 		_COSE_Sign0_Release(pobj);
 		COSE_FREE(pobj, context);
 		return NULL;
@@ -54,6 +55,9 @@
 	_COSE_InsertInList(&Sign0Root, &pobj->m_message);
 
 	return (HCOSE_SIGN0)pobj;
+
+errorReturn:
+	return NULL;
 }
 
 HCOSE_SIGN0 _COSE_Sign0_Init_From_Object(cn_cbor * cbor, COSE_Sign0Message * pIn, CBOR_CONTEXT_COMMA cose_errback * perr)
diff --git a/src/SignerInfo.c b/src/SignerInfo.c
index 1285ec9..5169887 100644
--- a/src/SignerInfo.c
+++ b/src/SignerInfo.c
@@ -67,7 +67,7 @@
 		return NULL;
 	}
 
-	if (!_COSE_Init(&pobj->m_message, COSE_recipient_object, CBOR_CONTEXT_PARAM_COMMA perror)) {
+	if (!_COSE_Init(0, &pobj->m_message, COSE_recipient_object, CBOR_CONTEXT_PARAM_COMMA perror)) {
 		_COSE_SignerInfo_Free(pobj);
 		COSE_FREE(pobj, context);
 		return NULL;
diff --git a/src/cbor.c b/src/cbor.c
index cfe1baf..31b6ddf 100644
--- a/src/cbor.c
+++ b/src/cbor.c
@@ -144,3 +144,19 @@
 
 	return pOut;
 }
+
+cn_cbor * cn_cbor_tag_create(int tag, cn_cbor * child, CBOR_CONTEXT_COMMA cn_cbor_errback * perr)
+{
+	cn_cbor * pcnTag = CN_CALLOC(context);
+	if (pcnTag == NULL) {
+		if (perr != NULL) perr->err = CN_CBOR_ERR_OUT_OF_MEMORY;
+		return NULL;
+	}
+
+	pcnTag->type = CN_CBOR_TAG;
+	pcnTag->v.sint = tag;
+	pcnTag->first_child = child;
+	child->parent = pcnTag;
+
+	return pcnTag;
+}
diff --git a/src/cose.h b/src/cose.h
index bbb7c08..200d163 100644
--- a/src/cose.h
+++ b/src/cose.h
@@ -20,6 +20,7 @@
 	COSE_ERR_NONE,
 	/** An invalid parameter was passed to a function */
 	COSE_ERR_INVALID_PARAMETER,
+	COSE_ERR_INVALID_HANDLE,
 	/** Allocation failed */
 	COSE_ERR_OUT_OF_MEMORY,
 	/** Error in processing CBOR */
@@ -34,6 +35,12 @@
 	COSE_ERR_CRYPTO_FAIL
 } cose_error;
 
+typedef enum cose_init_flags {
+	COSE_INIT_FLAGS_NONE=0,
+	COSE_INIT_FLAGS_DETACHED_CONTENT=1,
+	COSE_INIT_FLAGS_NO_CBOR_TAG=2,
+	COSE_INIT_FLAGS_ZERO_FORM=4
+} COSE_INIT_FLAGS;
 /**
 * Errors
 */
@@ -62,11 +69,7 @@
 
 //  Functions for the signing object
 
-HCOSE_SIGN COSE_Sign_Init(CBOR_CONTEXT_COMMA cose_errback * perr);
-bool COSE_Sign_Free(HCOSE_SIGN cose);
 
-HCOSE_MAC COSE_Mac_Init(CBOR_CONTEXT_COMMA cose_errback * perr);
-bool COSE_Mac_Free(HCOSE_MAC cose);
 
 typedef enum {
 	COSE_PROTECT_ONLY = 1,
@@ -165,7 +168,7 @@
  *  messages dealing with the Enveloped message type
  */
 
-HCOSE_ENVELOPED  COSE_Enveloped_Init(CBOR_CONTEXT_COMMA cose_errback * perr);
+HCOSE_ENVELOPED  COSE_Enveloped_Init(COSE_INIT_FLAGS flags, CBOR_CONTEXT_COMMA cose_errback * perr);
 bool COSE_Enveloped_Free(HCOSE_ENVELOPED cose);
 
 cn_cbor * COSE_Enveloped_map_get_int(HCOSE_ENVELOPED cose, int key, int flags, cose_errback * errp);
@@ -187,7 +190,7 @@
 /*
  */
 
-HCOSE_RECIPIENT COSE_Recipient_Init(CBOR_CONTEXT_COMMA cose_errback * perror);
+HCOSE_RECIPIENT COSE_Recipient_Init(COSE_INIT_FLAGS flags, CBOR_CONTEXT_COMMA cose_errback * perror);
 bool COSE_Recipient_Free(HCOSE_RECIPIENT cose);
 HCOSE_RECIPIENT COSE_Recipient_from_shared_secret(byte * rgbKey, int cbKey, byte * rgbKid, int cbKid, CBOR_CONTEXT_COMMA cose_errback * perr);
 
@@ -204,7 +207,7 @@
  *  Encrypt message API
  */
 
-HCOSE_ENCRYPT  COSE_Encrypt_Init(CBOR_CONTEXT_COMMA cose_errback * perr);
+HCOSE_ENCRYPT  COSE_Encrypt_Init(COSE_INIT_FLAGS flags, CBOR_CONTEXT_COMMA cose_errback * perr);
 bool COSE_Encrypt_Free(HCOSE_ENCRYPT cose);
 
 cn_cbor * COSE_Encrypt_map_get_int(HCOSE_ENCRYPT cose, int key, int flags, cose_errback * errp);
@@ -224,6 +227,9 @@
 //
 //
 
+HCOSE_MAC COSE_Mac_Init(COSE_INIT_FLAGS flags, CBOR_CONTEXT_COMMA cose_errback * perr);
+bool COSE_Mac_Free(HCOSE_MAC cose);
+
 bool COSE_Mac_SetContent(HCOSE_MAC cose, const byte * rgbContent, size_t cbContent, cose_errback * errp);
 bool COSE_Mac_SetExternal(HCOSE_MAC hcose, const byte * pbExternalData, size_t cbExternalData, cose_errback * perr);
 
@@ -238,7 +244,7 @@
 
 //  MAC0 calls
 
-HCOSE_MAC0 COSE_Mac0_Init(CBOR_CONTEXT_COMMA cose_errback * perr);
+HCOSE_MAC0 COSE_Mac0_Init(COSE_INIT_FLAGS flags, 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);
@@ -253,7 +259,11 @@
 //
 //
 
+HCOSE_SIGN COSE_Sign_Init(COSE_INIT_FLAGS flags, CBOR_CONTEXT_COMMA cose_errback * perr);
+bool COSE_Sign_Free(HCOSE_SIGN cose);
+
 bool COSE_Sign_SetContent(HCOSE_SIGN cose, const byte * rgbContent, size_t cbContent, cose_errback * errp);
+
 HCOSE_SIGNER COSE_Sign_add_signer(HCOSE_SIGN cose, const cn_cbor * pkey, int algId, cose_errback * perr);
 extern bool COSE_Sign_AddSigner(HCOSE_SIGN hSign, HCOSE_SIGNER hSigner, cose_errback * perr);
 bool COSE_Sign_Sign(HCOSE_SIGN h, cose_errback * perr);
@@ -275,7 +285,7 @@
  *  Sign routines
  */
 
-HCOSE_SIGN0 COSE_Sign0_Init(CBOR_CONTEXT_COMMA cose_errback * perr);
+HCOSE_SIGN0 COSE_Sign0_Init(COSE_INIT_FLAGS flags, 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);
@@ -291,4 +301,5 @@
 */
 
 extern cn_cbor * cn_cbor_clone(const cn_cbor * pIn, CBOR_CONTEXT_COMMA cn_cbor_errback * perr);
+extern cn_cbor * cn_cbor_tag_create(int tag, cn_cbor * child, CBOR_CONTEXT_COMMA cn_cbor_errback * perr);
 
diff --git a/src/cose_int.h b/src/cose_int.h
index aad4776..fb82337 100644
--- a/src/cose_int.h
+++ b/src/cose_int.h
@@ -4,7 +4,7 @@
 // interface, and they were quite confusing in cn-cbor.h
 
 typedef struct _COSE {
-	int m_flags;		//  Not sure what goes here yet
+	COSE_INIT_FLAGS m_flags;		//  Not sure what goes here yet
 	int m_ownMsg;		//  Do I own the pointer @ m_cbor?
 	int m_ownUnprotectedMap; //  Do I own the pointer @ m_unportectedMap?
 	int m_msgType;		//  What message type is this?
@@ -141,7 +141,7 @@
 extern bool IsValidRecipientHandle(HCOSE_RECIPIENT h);
 extern bool IsValidSignerHandle(HCOSE_SIGNER h);
 
-extern bool _COSE_Init(COSE * pcose, int msgType, CBOR_CONTEXT_COMMA cose_errback * errp);
+extern bool _COSE_Init(COSE_INIT_FLAGS flags, COSE * pcose, int msgType, CBOR_CONTEXT_COMMA cose_errback * errp);
 extern bool _COSE_Init_From_Object(COSE* pobj, cn_cbor * pcbor, CBOR_CONTEXT_COMMA cose_errback * perror);
 extern void _COSE_Release(COSE * pcose);
 
diff --git a/test/encrypt.c b/test/encrypt.c
index c691b4e..68ca8bf 100644
--- a/test/encrypt.c
+++ b/test/encrypt.c
@@ -109,7 +109,7 @@
 	const cn_cbor * pFail = cn_cbor_mapget_string(pControl, "fail");
 	if ((pFail != NULL) && (pFail->type == CN_CBOR_TRUE)) return 0;
 
-	HCOSE_ENVELOPED hEncObj = COSE_Enveloped_Init(CBOR_CONTEXT_PARAM_COMMA NULL);
+	HCOSE_ENVELOPED hEncObj = COSE_Enveloped_Init(0, CBOR_CONTEXT_PARAM_COMMA NULL);
 
 	const cn_cbor * pInputs = cn_cbor_mapget_string(pControl, "input");
 	if (pInputs == NULL) goto returnError;
@@ -132,7 +132,7 @@
 		cn_cbor * pkey = BuildKey(cn_cbor_mapget_string(pRecipients, "key"), true);
 		if (pkey == NULL) goto returnError;
 
-		HCOSE_RECIPIENT hRecip = COSE_Recipient_Init(CBOR_CONTEXT_PARAM_COMMA NULL);
+		HCOSE_RECIPIENT hRecip = COSE_Recipient_Init(0, CBOR_CONTEXT_PARAM_COMMA NULL);
 		if (hRecip == NULL) goto returnError;
 
 		if (!SetSendingAttributes((HCOSE)hRecip, pRecipients, Attributes_Recipient_protected)) goto returnError;
@@ -163,7 +163,7 @@
 
 int EncryptMessage()
 {
-	HCOSE_ENVELOPED hEncObj = COSE_Enveloped_Init(CBOR_CONTEXT_PARAM_COMMA NULL);
+	HCOSE_ENVELOPED hEncObj = COSE_Enveloped_Init(0, CBOR_CONTEXT_PARAM_COMMA NULL);
 	byte rgbSecret[128 / 8] = { 'a', 'b', 'c' };
 	int cbSecret = 128/8;
 	byte  rgbKid[15] = { 'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'l', 'm', 'n', 'o', 'p' };
@@ -171,7 +171,7 @@
 	size_t cb;
 	byte * rgb;
 	char * sz = "This is the content to be used";
-	HCOSE_RECIPIENT hRecip;
+	HCOSE_RECIPIENT hRecip = NULL;
 
 	if (hEncObj == NULL) goto errorReturn;
 	if (!COSE_Enveloped_map_put_int(hEncObj, COSE_Header_Algorithm, cn_cbor_int_create(COSE_Algorithm_AES_CCM_16_64_128, CBOR_CONTEXT_PARAM_COMMA NULL), COSE_PROTECT_ONLY, NULL)) goto errorReturn;
@@ -329,7 +329,7 @@
 	const cn_cbor * pFail = cn_cbor_mapget_string(pControl, "fail");
 	if ((pFail != NULL) && (pFail->type == CN_CBOR_TRUE)) return 0;
 
-	HCOSE_ENCRYPT hEncObj = COSE_Encrypt_Init(CBOR_CONTEXT_PARAM_COMMA NULL);
+	HCOSE_ENCRYPT hEncObj = COSE_Encrypt_Init(0, CBOR_CONTEXT_PARAM_COMMA NULL);
 
 	const cn_cbor * pInputs = cn_cbor_mapget_string(pControl, "input");
 	if (pInputs == NULL) goto returnError;
@@ -373,59 +373,91 @@
 
 void Enveloped_Corners()
 {
-	HCOSE_MAC hMAC = NULL;
+	HCOSE_ENVELOPED hEncryptNULL = NULL;
 	HCOSE_ENVELOPED hEncrypt = NULL;
+	HCOSE_ENVELOPED hEncryptBad = NULL;
+	HCOSE_RECIPIENT hRecipientNULL = NULL;
 	HCOSE_RECIPIENT hRecipient = NULL;
+	HCOSE_RECIPIENT hRecipientBad = NULL;
 	byte rgb[10];
 	cn_cbor * cn = cn_cbor_int_create(5, CBOR_CONTEXT_PARAM_COMMA NULL);
+	cose_errback cose_error;
+
+        hEncrypt = COSE_Enveloped_Init(0, CBOR_CONTEXT_PARAM_COMMA NULL);
+        hEncryptBad = (HCOSE_ENVELOPED) COSE_Mac_Init(0, CBOR_CONTEXT_PARAM_COMMA NULL);
+        hRecipient = COSE_Recipient_Init(0, CBOR_CONTEXT_PARAM_COMMA NULL);
+        hRecipientBad = (HCOSE_RECIPIENT) COSE_Mac_Init(0, CBOR_CONTEXT_PARAM_COMMA NULL);
 
 	//  Missing case - addref then release on item
 
-	//  Incorrect algorithm
 
-	hMAC = (HCOSE_MAC)COSE_Enveloped_Init(CBOR_CONTEXT_PARAM_COMMA NULL);
+        //
+        //  Do parameter checks
+        //      - NULL handle
+        //      - Incorrect handle
+        //      - NULL pointer
+        //
 
-	// NULL Handle checks
+        CHECK_FAILURE(COSE_Enveloped_SetContent(hEncryptNULL, rgb, 10, &cose_error), COSE_ERR_INVALID_HANDLE, CFails++);
+        CHECK_FAILURE(COSE_Enveloped_SetContent(hEncryptBad, rgb, 10, &cose_error), COSE_ERR_INVALID_HANDLE, CFails++);
+        CHECK_FAILURE(COSE_Enveloped_SetContent(hEncrypt, NULL, 10, &cose_error), COSE_ERR_INVALID_PARAMETER, CFails++);
 
-	if (COSE_Enveloped_SetContent(hEncrypt, rgb, 10, NULL)) CFails++;
-	if (COSE_Enveloped_map_get_int(hEncrypt, 1, COSE_BOTH, NULL)) CFails++;
-	if (COSE_Enveloped_map_put_int(hEncrypt, 1, cn, COSE_PROTECT_ONLY, NULL)) CFails++;
-	if (COSE_Enveloped_encrypt(hEncrypt, NULL)) CFails++;
-	if (COSE_Enveloped_decrypt(hEncrypt, (HCOSE_RECIPIENT)hMAC, NULL)) CFails++;
-	if (COSE_Enveloped_AddRecipient(hEncrypt, (HCOSE_RECIPIENT)hMAC, NULL)) CFails++;
-	if (COSE_Enveloped_GetRecipient(hEncrypt, 0, NULL)) CFails++;
-	if (COSE_Enveloped_SetExternal(hEncrypt, rgb, 10, NULL)) CFails++;
-	if (COSE_Enveloped_Free(hEncrypt)) CFails++;
 
-	//  Incorrect handle checks
+	CHECK_FAILURE(COSE_Enveloped_map_put_int(hEncryptNULL, 1, cn, COSE_PROTECT_ONLY, &cose_error), COSE_ERR_INVALID_HANDLE, CFails++);
+	CHECK_FAILURE(COSE_Enveloped_map_put_int(hEncryptBad, 1, cn, COSE_PROTECT_ONLY, &cose_error), COSE_ERR_INVALID_HANDLE, CFails++);
+	CHECK_FAILURE(COSE_Enveloped_map_put_int(hEncrypt, 1, cn, COSE_PROTECT_ONLY | COSE_UNPROTECT_ONLY, &cose_error), COSE_ERR_INVALID_PARAMETER, CFails++);
+	CHECK_FAILURE(COSE_Enveloped_map_put_int(hEncrypt, 1, NULL, COSE_PROTECT_ONLY, &cose_error), COSE_ERR_INVALID_PARAMETER, CFails++);
+        
 
-	hEncrypt = (HCOSE_ENVELOPED)COSE_Mac_Init(CBOR_CONTEXT_PARAM_COMMA NULL);
+        CHECK_FAILURE(COSE_Enveloped_map_get_int(hEncryptNULL, 1, COSE_BOTH, &cose_error), COSE_ERR_INVALID_HANDLE, CFails++);
+        CHECK_FAILURE(COSE_Enveloped_map_get_int(hEncryptBad, 1, COSE_BOTH, &cose_error), COSE_ERR_INVALID_HANDLE, CFails++);
 
-	if (COSE_Enveloped_SetContent(hEncrypt, rgb, 10, NULL)) CFails++;
-	if (COSE_Enveloped_map_get_int(hEncrypt, 1, COSE_BOTH, NULL)) CFails++;
-	if (COSE_Enveloped_map_put_int(hEncrypt, 1, cn, COSE_PROTECT_ONLY, NULL)) CFails++;
-	if (COSE_Enveloped_encrypt(hEncrypt, NULL)) CFails++;
-	if (COSE_Enveloped_decrypt(hEncrypt, (HCOSE_RECIPIENT)hMAC, NULL)) CFails++;
-	if (COSE_Enveloped_AddRecipient(hEncrypt, (HCOSE_RECIPIENT)hMAC, NULL)) CFails++;
-	if (COSE_Enveloped_GetRecipient(hEncrypt, 0, NULL)) CFails++;
-	if (COSE_Enveloped_SetExternal(hEncrypt, rgb, 10, NULL)) CFails++;
-	if (COSE_Enveloped_Free(hEncrypt)) CFails++;
+
+        CHECK_FAILURE(COSE_Enveloped_encrypt(hEncryptNULL, &cose_error), COSE_ERR_INVALID_HANDLE, CFails++);
+        CHECK_FAILURE(COSE_Enveloped_encrypt(hEncryptBad, &cose_error), COSE_ERR_INVALID_HANDLE, CFails++);
+
+        CHECK_FAILURE(COSE_Enveloped_decrypt(hEncryptNULL, hRecipient, &cose_error), COSE_ERR_INVALID_HANDLE, CFails++);
+        CHECK_FAILURE(COSE_Enveloped_decrypt(hEncryptBad, hRecipient, &cose_error), COSE_ERR_INVALID_HANDLE, CFails++);
+        CHECK_FAILURE(COSE_Enveloped_decrypt(hEncrypt, hRecipientNULL, &cose_error), COSE_ERR_INVALID_HANDLE, CFails++);
+        CHECK_FAILURE(COSE_Enveloped_decrypt(hEncrypt, hRecipientBad, &cose_error), COSE_ERR_INVALID_HANDLE, CFails++);
+
+
+	CHECK_FAILURE(COSE_Enveloped_AddRecipient(hEncryptNULL, hRecipient, &cose_error), COSE_ERR_INVALID_HANDLE, CFails++);
+	CHECK_FAILURE(COSE_Enveloped_AddRecipient(hEncryptBad, hRecipient, &cose_error), COSE_ERR_INVALID_HANDLE, CFails++);
+	CHECK_FAILURE(COSE_Enveloped_AddRecipient(hEncrypt, hRecipientNULL, &cose_error), COSE_ERR_INVALID_HANDLE, CFails++);
+	CHECK_FAILURE(COSE_Enveloped_AddRecipient(hEncrypt, hRecipientBad, &cose_error), COSE_ERR_INVALID_HANDLE, CFails++);
+        
+	CHECK_FAILURE_PTR(COSE_Enveloped_GetRecipient(hEncryptNULL, 0, &cose_error), COSE_ERR_INVALID_HANDLE, CFails++);
+	CHECK_FAILURE_PTR(COSE_Enveloped_GetRecipient(hEncryptBad, 0, &cose_error), COSE_ERR_INVALID_HANDLE, CFails++);
+            
+	CHECK_FAILURE(COSE_Enveloped_SetExternal(hEncryptNULL, rgb, 10, &cose_error), COSE_ERR_INVALID_HANDLE, CFails++);
+	CHECK_FAILURE(COSE_Enveloped_SetExternal(hEncryptBad, rgb, 10, &cose_error), COSE_ERR_INVALID_HANDLE, CFails++);
+	CHECK_FAILURE(COSE_Enveloped_SetExternal(hEncrypt, NULL, 10, &cose_error), COSE_ERR_INVALID_PARAMETER, CFails++);
+            
+	if (!COSE_Enveloped_Free(hEncrypt)) CFails++;
+	if (!COSE_Recipient_Free(hRecipient)) CFails++;
+
 
 	//
 	//  Unsupported algorithm
 
-	hEncrypt = COSE_Enveloped_Init(CBOR_CONTEXT_PARAM_COMMA NULL);
+	hEncrypt = COSE_Enveloped_Init(0, CBOR_CONTEXT_PARAM_COMMA NULL);
 	if (hEncrypt == NULL) CFails++;
-	if (!COSE_Enveloped_SetContent(hEncrypt, (byte *) "Message", 7, NULL)) CFails++;
-	if (!COSE_Enveloped_map_put_int(hEncrypt, COSE_Header_Algorithm, cn_cbor_int_create(-99, CBOR_CONTEXT_PARAM_COMMA NULL), COSE_PROTECT_ONLY, NULL)) CFails++;
+	CHECK_RETURN(COSE_Enveloped_SetContent(hEncrypt, (byte *) "Message", 7, &cose_error), COSE_ERR_NONE, CFails++);
+	CHECK_RETURN(COSE_Enveloped_map_put_int(hEncrypt, COSE_Header_Algorithm, cn_cbor_int_create(-99, CBOR_CONTEXT_PARAM_COMMA NULL), COSE_PROTECT_ONLY, &cose_error), COSE_ERR_NONE, CFails++);
 	hRecipient = COSE_Recipient_from_shared_secret(rgb, sizeof(rgb), rgb, sizeof(rgb), CBOR_CONTEXT_PARAM_COMMA NULL);
 	if (hRecipient == NULL) CFails++;
-	if (!COSE_Enveloped_AddRecipient(hEncrypt, hRecipient, NULL)) CFails++;
-	if (COSE_Enveloped_encrypt(hEncrypt, NULL)) CFails++;
-	if (COSE_Enveloped_GetRecipient(hEncrypt, 9, NULL)) CFails++;
+	CHECK_RETURN(COSE_Enveloped_AddRecipient(hEncrypt, hRecipient, &cose_error), COSE_ERR_NONE, CFails++);
+	CHECK_FAILURE(COSE_Enveloped_encrypt(hEncrypt, &cose_error), COSE_ERR_UNKNOWN_ALGORITHM, CFails++);
 
-	if (!COSE_Enveloped_map_put_int(hEncrypt, COSE_Header_Algorithm, cn_cbor_string_create("hmac", CBOR_CONTEXT_PARAM_COMMA NULL), COSE_PROTECT_ONLY, NULL)) CFails++;
-	if (COSE_Enveloped_encrypt(hEncrypt, NULL)) CFails++;
+	CHECK_RETURN(COSE_Enveloped_map_put_int(hEncrypt, COSE_Header_Algorithm, cn_cbor_string_create("hmac", CBOR_CONTEXT_PARAM_COMMA NULL), COSE_PROTECT_ONLY, &cose_error), COE_ERR_NONE, CFails++);
+	CHECK_FAILURE(COSE_Enveloped_encrypt(hEncrypt, &cose_error), COSE_ERR_UNKNOWN_ALGORITHM, CFails++);
+
+        //
+        //  Over shoot the recipients
+        
+        CHECK_FAILURE_PTR(COSE_Enveloped_GetRecipient(hEncrypt, -1, &cose_error), COSE_ERR_INVALID_PARAMETER, CFails++);
+        CHECK_FAILURE_PTR(COSE_Enveloped_GetRecipient(hEncrypt, 9, &cose_error), COSE_ERR_INVALID_PARAMETER, CFails++);
 
 	return;
 }
@@ -450,7 +482,7 @@
 
 	//  Wrong type of handle checks
 
-	hEncrypt = (HCOSE_ENCRYPT) COSE_Mac_Init(CBOR_CONTEXT_PARAM_COMMA NULL);
+	hEncrypt = (HCOSE_ENCRYPT) COSE_Mac_Init(0, CBOR_CONTEXT_PARAM_COMMA NULL);
 
 	if (COSE_Encrypt_SetContent(hEncrypt, rgb, 10, NULL)) CFails++;
 	if (COSE_Encrypt_map_get_int(hEncrypt, 1, COSE_BOTH, NULL)) CFails++;
@@ -463,7 +495,7 @@
 	//
 	//  Unsupported algorithm
 
-	hEncrypt = COSE_Encrypt_Init(CBOR_CONTEXT_PARAM_COMMA NULL);
+	hEncrypt = COSE_Encrypt_Init(0, CBOR_CONTEXT_PARAM_COMMA NULL);
 	if (hEncrypt == NULL) CFails++;
 	if (!COSE_Encrypt_SetContent(hEncrypt, (byte *) "Message", 7, NULL)) CFails++;
 	if (!COSE_Encrypt_map_put_int(hEncrypt, COSE_Header_Algorithm, cn_cbor_int_create(-99, CBOR_CONTEXT_PARAM_COMMA NULL), COSE_PROTECT_ONLY, NULL)) CFails++;
diff --git a/test/mac_test.c b/test/mac_test.c
index 630698e..92610d5 100644
--- a/test/mac_test.c
+++ b/test/mac_test.c
@@ -106,7 +106,7 @@
 	const cn_cbor * pFail = cn_cbor_mapget_string(pControl, "fail");
 	if ((pFail != NULL) && (pFail->type == CN_CBOR_TRUE)) return 0;
 
-	HCOSE_MAC hMacObj = COSE_Mac_Init(CBOR_CONTEXT_PARAM_COMMA NULL);
+	HCOSE_MAC hMacObj = COSE_Mac_Init(0, CBOR_CONTEXT_PARAM_COMMA NULL);
 
 	const cn_cbor * pInputs = cn_cbor_mapget_string(pControl, "input");
 	if (pInputs == NULL) goto returnError;
@@ -128,7 +128,7 @@
 		cn_cbor * pkey = BuildKey(cn_cbor_mapget_string(pRecipients, "key"), true);
 		if (pkey == NULL) goto returnError;
 
-		HCOSE_RECIPIENT hRecip = COSE_Recipient_Init(CBOR_CONTEXT_PARAM_COMMA NULL);
+		HCOSE_RECIPIENT hRecip = COSE_Recipient_Init(0, CBOR_CONTEXT_PARAM_COMMA NULL);
 		if (hRecip == NULL) goto returnError;
 
 		if (!SetSendingAttributes((HCOSE) hRecip, pRecipients, Attributes_Recipient_protected)) goto returnError;
@@ -160,7 +160,7 @@
 
 int MacMessage()
 {
-	HCOSE_MAC hEncObj = COSE_Mac_Init(CBOR_CONTEXT_PARAM_COMMA NULL);
+	HCOSE_MAC hEncObj = COSE_Mac_Init(0, CBOR_CONTEXT_PARAM_COMMA NULL);
 	char * sz = "This is the content to be used";
 	byte rgbSecret[256 / 8] = { 'a', 'b', 'c' };
 	byte  rgbKid[6] = { 'a', 'b', 'c', 'd', 'e', 'f' };
@@ -317,7 +317,7 @@
 	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);
+	HCOSE_MAC0 hMacObj = COSE_Mac0_Init(0, CBOR_CONTEXT_PARAM_COMMA NULL);
 
 	const cn_cbor * pInputs = cn_cbor_mapget_string(pControl, "input");
 	if (pInputs == NULL) goto returnError;
@@ -372,7 +372,7 @@
 
     //  Incorrect algorithm
     
-    hMAC = (HCOSE_MAC) COSE_Mac_Init(CBOR_CONTEXT_PARAM_COMMA NULL);
+    hMAC = (HCOSE_MAC) COSE_Mac_Init(0, CBOR_CONTEXT_PARAM_COMMA NULL);
 
     //  Invalid Handle checks
 
@@ -386,7 +386,7 @@
 	if (COSE_Mac_SetExternal((HCOSE_MAC)hEncrypt, rgb, 0, NULL)) CFails++;
 	if (COSE_Mac_Free((HCOSE_MAC)hEncrypt)) CFails++;
 
-    hEncrypt = COSE_Encrypt_Init(CBOR_CONTEXT_PARAM_COMMA NULL);
+    hEncrypt = COSE_Encrypt_Init(0, CBOR_CONTEXT_PARAM_COMMA NULL);
 
 	if (COSE_Mac_SetContent((HCOSE_MAC)hEncrypt, rgb, 10, NULL)) CFails++;
 	if (COSE_Mac_map_get_int((HCOSE_MAC)hEncrypt, 1, COSE_BOTH, NULL)) CFails++;
@@ -401,7 +401,7 @@
     //
 	//  Unsupported algorithm
 
-	hMAC = COSE_Mac_Init(CBOR_CONTEXT_PARAM_COMMA NULL);
+	hMAC = COSE_Mac_Init(0, CBOR_CONTEXT_PARAM_COMMA NULL);
 	if (hMAC == NULL) CFails++;
 	if (!COSE_Mac_SetContent(hMAC, (byte *) "Message", 7, NULL)) CFails++;
 	if (!COSE_Mac_map_put_int(hMAC, COSE_Header_Algorithm, cn_cbor_int_create(-99, CBOR_CONTEXT_PARAM_COMMA NULL), COSE_PROTECT_ONLY, NULL)) CFails++;
@@ -424,7 +424,7 @@
 	byte rgb[10];
 	cn_cbor * cn = cn_cbor_int_create(5, CBOR_CONTEXT_PARAM_COMMA NULL);
 
-	hEncrypt = COSE_Encrypt_Init(CBOR_CONTEXT_PARAM_COMMA NULL);
+	hEncrypt = COSE_Encrypt_Init(0, CBOR_CONTEXT_PARAM_COMMA NULL);
 
 	//  Missing case - addref then release on item
 
@@ -438,7 +438,7 @@
 	if (COSE_Mac0_SetExternal((HCOSE_MAC0)hEncrypt, rgb, 0, NULL)) CFails++;
 	if (COSE_Mac0_Free((HCOSE_MAC0)hEncrypt)) CFails++;
 
-	hEncrypt = COSE_Encrypt_Init(CBOR_CONTEXT_PARAM_COMMA NULL);
+	hEncrypt = COSE_Encrypt_Init(0, CBOR_CONTEXT_PARAM_COMMA NULL);
 
 	if (COSE_Mac0_SetContent((HCOSE_MAC0)hEncrypt, rgb, 10, NULL)) CFails++;
 	if (COSE_Mac0_map_get_int((HCOSE_MAC0)hEncrypt, 1, COSE_BOTH, NULL)) CFails++;
@@ -452,7 +452,7 @@
 	//
 	//  Unsupported algorithm
 
-	hMAC = COSE_Mac0_Init(CBOR_CONTEXT_PARAM_COMMA NULL);
+	hMAC = COSE_Mac0_Init(0, CBOR_CONTEXT_PARAM_COMMA NULL);
 	if (hMAC == NULL) CFails++;
 	if (!COSE_Mac0_SetContent(hMAC, (byte *) "Message", 7, NULL)) CFails++;
 	if (!COSE_Mac0_map_put_int(hMAC, COSE_Header_Algorithm, cn_cbor_int_create(-99, CBOR_CONTEXT_PARAM_COMMA NULL), COSE_PROTECT_ONLY, NULL)) CFails++;
diff --git a/test/sign.c b/test/sign.c
index 3cc0ab0..05d62d8 100644
--- a/test/sign.c
+++ b/test/sign.c
@@ -108,7 +108,7 @@
 	const cn_cbor * pFail = cn_cbor_mapget_string(pControl, "fail");
 	if ((pFail != NULL) && (pFail->type == CN_CBOR_TRUE)) return 0;
 
-	HCOSE_SIGN hSignObj = COSE_Sign_Init(CBOR_CONTEXT_PARAM_COMMA NULL);
+	HCOSE_SIGN hSignObj = COSE_Sign_Init(0, CBOR_CONTEXT_PARAM_COMMA NULL);
 
 	const cn_cbor * pInputs = cn_cbor_mapget_string(pControl, "input");
 	if (pInputs == NULL) goto returnError;
@@ -163,7 +163,7 @@
 
 int SignMessage()
 {
-	HCOSE_SIGN hEncObj = COSE_Sign_Init(CBOR_CONTEXT_PARAM_COMMA NULL);
+	HCOSE_SIGN hEncObj = COSE_Sign_Init(0, CBOR_CONTEXT_PARAM_COMMA NULL);
 	char * sz = "This is the content to be used";
 	size_t cb;
 	byte * rgb;
@@ -310,7 +310,7 @@
 	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);
+	HCOSE_SIGN0 hSignObj = COSE_Sign0_Init(0, CBOR_CONTEXT_PARAM_COMMA NULL);
 
 	const cn_cbor * pInputs = cn_cbor_mapget_string(pControl, "input");
 	if (pInputs == NULL) goto returnError;
@@ -355,7 +355,7 @@
 	byte rgb[10];
 	cn_cbor * cn = cn_cbor_int_create(5, CBOR_CONTEXT_PARAM_COMMA NULL);
 
-	hSign2 = COSE_Sign_Init(CBOR_CONTEXT_PARAM_COMMA  NULL);
+	hSign2 = COSE_Sign_Init(0, CBOR_CONTEXT_PARAM_COMMA  NULL);
 	hSigner2 = COSE_Signer_Init(CBOR_CONTEXT_PARAM_COMMA  NULL);
 
 	//  Missing case - addref then release on item
@@ -382,8 +382,8 @@
 	if (COSE_Signer_SetExternal(hSigner, rgb, sizeof(rgb), NULL)) CFails++;
 
 
-	hSign = (HCOSE_SIGN) COSE_Encrypt_Init(CBOR_CONTEXT_PARAM_COMMA NULL);
-	hSigner = (HCOSE_SIGNER) COSE_Recipient_Init(CBOR_CONTEXT_PARAM_COMMA NULL);
+	hSign = (HCOSE_SIGN) COSE_Encrypt_Init(0, CBOR_CONTEXT_PARAM_COMMA NULL);
+	hSigner = (HCOSE_SIGNER) COSE_Recipient_Init(0, CBOR_CONTEXT_PARAM_COMMA NULL);
 
 	if (COSE_Sign_SetContent(hSign, rgb, 10, NULL)) CFails++;
 	if (COSE_Sign_map_get_int(hSign, 1, COSE_BOTH, NULL)) CFails++;
@@ -405,7 +405,7 @@
 	//
 	//  Unsupported algorithm
 
-	hSign = COSE_Sign_Init(CBOR_CONTEXT_PARAM_COMMA NULL);
+	hSign = COSE_Sign_Init(0, CBOR_CONTEXT_PARAM_COMMA NULL);
 	if (hSign == NULL) CFails++;
 	hSigner = COSE_Signer_Init(CBOR_CONTEXT_PARAM_COMMA NULL);
 	if (hSigner == NULL) CFails++;
@@ -429,7 +429,7 @@
 	byte rgb[10];
 	cn_cbor * cn = cn_cbor_int_create(5, CBOR_CONTEXT_PARAM_COMMA NULL);
 
-	hSign2 = COSE_Sign0_Init(CBOR_CONTEXT_PARAM_COMMA NULL);
+	hSign2 = COSE_Sign0_Init(0, CBOR_CONTEXT_PARAM_COMMA NULL);
 	//  Missing case - addref then release on item
 
 	//  Incorrect algorithm
@@ -445,7 +445,7 @@
 	if (COSE_Sign0_validate(hSign2, NULL, NULL)) CFails++;
 	if (COSE_Sign0_SetExternal(hSign, rgb, sizeof(rgb), NULL)) CFails++;
 
-	hSign = (HCOSE_SIGN0)COSE_Encrypt_Init(CBOR_CONTEXT_PARAM_COMMA NULL);
+	hSign = (HCOSE_SIGN0)COSE_Encrypt_Init(0, CBOR_CONTEXT_PARAM_COMMA NULL);
 
 	if (COSE_Sign0_SetContent(hSign, rgb, 10, NULL)) CFails++;
 	if (COSE_Sign0_map_get_int(hSign, 1, COSE_BOTH, NULL)) CFails++;
@@ -457,7 +457,7 @@
 	//
 	//  Unsupported algorithm
 
-	hSign = COSE_Sign0_Init(CBOR_CONTEXT_PARAM_COMMA NULL);
+	hSign = COSE_Sign0_Init(0, CBOR_CONTEXT_PARAM_COMMA NULL);
 	if (hSign == NULL) CFails++;
 
 	if (!COSE_Sign0_SetContent(hSign, (byte *) "Message", 7, NULL)) CFails++;
diff --git a/test/test.h b/test/test.h
index 967bd48..34d832b 100644
--- a/test/test.h
+++ b/test/test.h
@@ -1,4 +1,5 @@
 #ifndef _countof
+
 #define _countof(x) (sizeof(x)/sizeof(x[0]))
 #endif
 
@@ -71,3 +72,28 @@
 byte * FromHex(const char * rgch, int cch);
 bool SetSendingAttributes(HCOSE hMsg, const cn_cbor * pIn, int base);
 bool SetReceivingAttributes(HCOSE hMsg, const cn_cbor * pIn, int base);
+
+//
+//  Internal macros to make testing easier
+//
+
+#define CHECK_RETURN(functionCall, errorReturn, onFailure) \
+{	\
+	if (!functionCall) onFailure; \
+}
+
+#define CHECK_FAILURE(functionCall, errorReturn, onFailure)       \
+    { \
+        bool bReturn = functionCall;  \
+        if (!bReturn) { \
+            if (cose_error.err != errorReturn) onFailure; \
+        } else if (errorReturn != COSE_ERR_NONE) onFailure; \
+    }
+
+#define CHECK_FAILURE_PTR(functionCall, errorReturn, onFailure)       \
+    { \
+        void * bReturn = functionCall;  \
+        if (bReturn == NULL) { \
+            if (cose_error.err != errorReturn) onFailure; \
+        } else if (errorReturn != COSE_ERR_NONE) onFailure; \
+    }