Start getting HKDF - HMAC-SHA256 running
diff --git a/src/Encrypt.c b/src/Encrypt.c
index 2440e14..a7d47e0 100644
--- a/src/Encrypt.c
+++ b/src/Encrypt.c
@@ -286,7 +286,7 @@
 	//  If there is a recipient - ask it for the key
 
 	for (pRecip = pcose->m_recipientFirst; pRecip != NULL; pRecip = pRecip->m_recipientNext) {
-		if (_COSE_Recipient_decrypt(pRecip, cbitKey, pbKey, perr)) break;
+		if (_COSE_Recipient_decrypt(pRecip, alg, cbitKey, pbKey, perr)) break;
 	}
 
 	//  Build protected headers
@@ -414,7 +414,7 @@
 		for (pri = pcose->m_recipientFirst; pri != NULL; pri = pri->m_recipientNext) {
 			if (pri->m_encrypt.m_message.m_flags & 1) {
 				t |= 1;
-				pcose->pbKey = _COSE_RecipientInfo_generateKey(pri, cbitKey, perr);
+				pcose->pbKey = _COSE_RecipientInfo_generateKey(pri, alg, cbitKey, perr);
 				if (pcose->pbKey == NULL) goto errorReturn;
 				pcose->cbKey = cbitKey / 8;
 			}
@@ -632,4 +632,4 @@
 	if (ptmp != NULL) CN_CBOR_FREE(ptmp, NULL);
 	if (pAuthData != NULL) CN_CBOR_FREE(pAuthData, context);
 	return false;
-}
\ No newline at end of file
+}
diff --git a/src/MacMessage.c b/src/MacMessage.c
index 2b5c401..a6318a2 100644
--- a/src/MacMessage.c
+++ b/src/MacMessage.c
@@ -310,7 +310,7 @@
 		for (pri = pcose->m_recipientFirst; pri != NULL; pri = pri->m_recipientNext) {
 			if (pri->m_encrypt.m_message.m_flags & 1) {
 				t |= 1;
-				pcose->pbKey = _COSE_RecipientInfo_generateKey(pri, cbitKey, perr);
+				pcose->pbKey = _COSE_RecipientInfo_generateKey(pri, alg, cbitKey, perr);
 				if (pcose->pbKey == NULL) goto errorReturn;
 
 				pcose->cbKey = cbitKey / 8;
@@ -499,7 +499,7 @@
 	//  If there is a recipient - ask it for the key
 
 	for (pRecip = pcose->m_recipientFirst; pRecip != NULL; pRecip = pRecip->m_recipientNext) {
-		if (_COSE_Recipient_decrypt(pRecip, cbitKey, pbKey, perr)) break;
+		if (_COSE_Recipient_decrypt(pRecip, alg, cbitKey, pbKey, perr)) break;
 	}
 	CHECK_CONDITION(pRecip != NULL, COSE_ERR_NO_RECIPIENT_FOUND);
 
diff --git a/src/Recipient.c b/src/Recipient.c
index cb1dc80..11fc583 100644
--- a/src/Recipient.c
+++ b/src/Recipient.c
@@ -6,6 +6,9 @@
 #include "configure.h"
 #include "crypto.h"
 
+extern bool BuildContextBytes(COSE * pcose, int algID, size_t cbitKey, byte ** ppbContext, size_t * pcbContext, CBOR_CONTEXT_COMMA cose_errback * perr);
+
+
 COSE* RecipientRoot = NULL;
 
 bool IsValidRecipientHandle(HCOSE_RECIPIENT h)
@@ -111,7 +114,7 @@
 	return;
 }
 
-bool _COSE_Recipient_decrypt(COSE_RecipientInfo * pRecip, int cbitKey, byte * pbKeyIn, cose_errback * perr)
+bool _COSE_Recipient_decrypt(COSE_RecipientInfo * pRecip, int algIn, int cbitKey, byte * pbKeyIn, cose_errback * perr)
 {
 	int alg;
 	const cn_cbor * cn = NULL;
@@ -125,6 +128,10 @@
 	byte * pbProtected = NULL;
 	COSE_Enveloped * pcose = &pRecip->m_encrypt;
 	cn_cbor * cnBody = NULL;
+	byte * pbContext = NULL;
+	size_t cbContext;
+	byte rgbDigest[512 / 8];
+	size_t cbDigest;
 
 #ifdef USE_CBOR_CONTEXT
 	context = &pcose->m_message.m_allocContext;
@@ -133,6 +140,7 @@
 	cn = _COSE_map_get_int(&pRecip->m_encrypt.m_message, COSE_Header_Algorithm, COSE_BOTH, perr);
 	if (cn == NULL) {
 	errorReturn:
+		if (pbContext != NULL) COSE_FREE(pbContext, context);
 		if (pbProtected != NULL) COSE_FREE(pbProtected, context);
 		if (pbAuthData != NULL) COSE_FREE(pbAuthData, context);
 		if (pAuthData != NULL) cn_cbor_free(pAuthData CBOR_CONTEXT_PARAM);
@@ -167,6 +175,12 @@
 	case COSE_Algorithm_AES_KW_256:
 		break;
 
+	case COSE_Algorithm_Direct_HKDF_AES_128:
+	case COSE_Algorithm_Direct_HKDF_AES_256:
+	case COSE_Algorithm_Direct_HKDF_HMAC_SHA_256:
+	case COSE_Algorithm_Direct_HKDF_HMAC_SHA_512:
+		break;
+
 	default:
 		FAIL_CONDITION(COSE_ERR_UNKNOWN_ALGORITHM);
 		break;
@@ -182,7 +196,7 @@
 	//  If there is a recipient - ask it for the key
 
 	for (pRecip2 = pcose->m_recipientFirst; pRecip2 != NULL; pRecip2 = pRecip->m_recipientNext) {
-		if (_COSE_Recipient_decrypt(pRecip2, cbitKey, pbKey, perr)) break;
+		if (_COSE_Recipient_decrypt(pRecip2, alg, cbitKey, pbKey, perr)) break;
 	}
 
 	cnBody = _COSE_arrayget_int(&pcose->m_message, INDEX_BODY);
@@ -204,6 +218,16 @@
 			memcpy(pbKey, pcose->pbKey, pcose->cbKey);
 		}
 
+	case COSE_Algorithm_Direct_HKDF_HMAC_SHA_256:
+		if (!BuildContextBytes(&pcose->m_message, algIn, cbitKey, &pbContext, &cbContext, CBOR_CONTEXT_PARAM_COMMA perr)) goto errorReturn;
+
+		cn = cn_cbor_mapget_int(pRecip->m_pkey, -1);
+		CHECK_CONDITION((cn != NULL) && (cn->type == CN_CBOR_BYTES), COSE_ERR_INVALID_PARAMETER);
+
+		if (!HKDF_Extract(&pcose->m_message, cn->v.bytes, cn->length, 256, rgbDigest, &cbDigest, CBOR_CONTEXT_PARAM_COMMA perr)) goto errorReturn;
+
+		if (!HKDF_Expand(&pcose->m_message, 256, rgbDigest, cbDigest, pbContext, cbContext, pbKey, cbitKey / 8, perr)) goto errorReturn;
+
 		break;
 
 	default:
@@ -243,6 +267,8 @@
 
 	switch (alg) {
 	case COSE_Algorithm_Direct:
+	case COSE_Algorithm_Direct_HKDF_HMAC_SHA_256:
+	case COSE_Algorithm_Direct_HKDF_HMAC_SHA_512:
 		//  This is a NOOP
 		cbitKey = 0;
 		CHECK_CONDITION(pRecipient->m_encrypt.m_recipientFirst == NULL, COSE_ERR_INVALID_PARAMETER);
@@ -271,7 +297,7 @@
 		for (pri = pRecipient->m_encrypt.m_recipientFirst; pri != NULL; pri = pri->m_recipientNext) {
 			if (pri->m_encrypt.m_message.m_flags & 1) {
 				t |= 1;
-				pRecipient->m_encrypt.pbKey = _COSE_RecipientInfo_generateKey(pri, cbitKey, perr);
+				pRecipient->m_encrypt.pbKey = _COSE_RecipientInfo_generateKey(pri, alg, cbitKey, perr);
 				if (pRecipient->m_encrypt.pbKey == NULL) goto errorReturn;
 				pRecipient->m_encrypt.cbKey = cbitKey / 8;
 			}
@@ -304,11 +330,14 @@
 	switch (alg) {
 
 	case COSE_Algorithm_Direct:
+	case COSE_Algorithm_Direct_HKDF_HMAC_SHA_256:
+	case COSE_Algorithm_Direct_HKDF_HMAC_SHA_512:
 		ptmp = cn_cbor_data_create(NULL, 0, CBOR_CONTEXT_PARAM_COMMA &cbor_error);
 		CHECK_CONDITION_CBOR(ptmp != NULL, cbor_error);
 		CHECK_CONDITION_CBOR(_COSE_array_replace(&pRecipient->m_encrypt.m_message, ptmp, INDEX_BODY, CBOR_CONTEXT_PARAM_COMMA &cbor_error), cbor_error);
 		break;
 
+
 	case COSE_Algorithm_AES_KW_256:
 		if (pRecipient->m_pkey != NULL) {
 			cn_cbor * pK = cn_cbor_mapget_int(pRecipient->m_pkey, -1);
@@ -342,24 +371,33 @@
 	return false;
 }
 
-byte * _COSE_RecipientInfo_generateKey(COSE_RecipientInfo * pRecipient, size_t cbitKeySize, cose_errback * perr)
+byte * _COSE_RecipientInfo_generateKey(COSE_RecipientInfo * pRecipient, int algIn, size_t cbitKeySize, cose_errback * perr)
 {
 	int alg;
 	const cn_cbor * cn_Alg = _COSE_map_get_int(&pRecipient->m_encrypt.m_message, COSE_Header_Algorithm, COSE_BOTH, perr);
+	byte * pbContext = NULL;
+	size_t cbContext;
+	byte * pb = NULL;
+#ifdef USE_CBOR_CONTEXT
+	cn_cbor_context * context = &pRecipient->m_encrypt.m_message.m_allocContext;
+#endif
+	const cn_cbor * pK;
+	byte rgbDigest[512 / 8];
+	size_t cbDigest;
 
 	CHECK_CONDITION(cn_Alg != NULL, COSE_ERR_INVALID_PARAMETER);
 	CHECK_CONDITION((cn_Alg->type == CN_CBOR_UINT) || (cn_Alg->type == CN_CBOR_INT), COSE_ERR_INVALID_PARAMETER);
 	alg = (int)cn_Alg->v.uint;
 
+	_COSE_encode_protected(&pRecipient->m_encrypt.m_message, perr);
+
 	switch (alg) {
 	case COSE_Algorithm_Direct:
-	{
-		byte * pb;
 		if (pRecipient->m_pkey != NULL) {
-			const cn_cbor * pK = cn_cbor_mapget_int(pRecipient->m_pkey, -1);
+			pK = cn_cbor_mapget_int(pRecipient->m_pkey, -1);
 			CHECK_CONDITION((pK != NULL) && (pK->type == CN_CBOR_BYTES), COSE_ERR_INVALID_PARAMETER);
 			CHECK_CONDITION(pK->length == cbitKeySize / 8, COSE_ERR_INVALID_PARAMETER);
-			pb = COSE_CALLOC(cbitKeySize / 8, 1, &pRecipient->m_encrypt.m_message.m_allocContext);
+			pb = COSE_CALLOC(cbitKeySize / 8, 1, context);
 			CHECK_CONDITION(pb != NULL, COSE_ERR_OUT_OF_MEMORY);
 			memcpy(pb, pK->v.bytes, cbitKeySize / 8);
 		}
@@ -369,10 +407,23 @@
 			if (pb == NULL) return NULL;
 			memcpy(pb, pRecipient->m_encrypt.pbKey, cbitKeySize / 8);
 		}
-		return pb;
-	}
 	break;
 
+	case COSE_Algorithm_Direct_HKDF_HMAC_SHA_256:
+		if (!BuildContextBytes(&pRecipient->m_encrypt.m_message, algIn, cbitKeySize, &pbContext, &cbContext, CBOR_CONTEXT_PARAM_COMMA perr)) goto errorReturn;
+
+		pK = cn_cbor_mapget_int(pRecipient->m_pkey, -1);
+		CHECK_CONDITION((pK != NULL) && (pK->type == CN_CBOR_BYTES), COSE_ERR_INVALID_PARAMETER);
+
+		if (!HKDF_Extract(&pRecipient->m_encrypt.m_message, pK->v.bytes, pK->length, 256, rgbDigest, &cbDigest, CBOR_CONTEXT_PARAM_COMMA perr)) goto errorReturn;
+
+		pb = COSE_CALLOC(cbitKeySize / 8, 1, context);
+		CHECK_CONDITION(pb != NULL, COSE_ERR_OUT_OF_MEMORY);
+
+		if (!HKDF_Expand(&pRecipient->m_encrypt.m_message, 256, rgbDigest, cbDigest, pbContext, cbContext, pb, cbitKeySize / 8, perr)) goto errorReturn;
+
+		break;
+
 	case COSE_Algorithm_ECDH_SS_HKDF_256: {
 		//  Need to have a key and it needs to be the correct type of key.
 		if ((pRecipient->m_pkey == NULL) || (cn_cbor_mapget_int(pRecipient->m_pkey, 1)->v.uint != 2)) return NULL;
@@ -383,7 +434,13 @@
 		return NULL;
 	}
 
+	if (pbContext != NULL) COSE_FREE(pbContext, context);
+	return pb;
+
 errorReturn:
+
+	if (pbContext != NULL) COSE_FREE(pbContext, context);
+	if (pb != NULL) COSE_FREE(pb, context);
 	return NULL;
 }
 
@@ -440,6 +497,10 @@
 		if (value->type == CN_CBOR_INT) {
 			switch (value->v.uint) {
 			case COSE_Algorithm_Direct:
+			case COSE_Algorithm_Direct_HKDF_AES_128:
+			case COSE_Algorithm_Direct_HKDF_AES_256:
+			case COSE_Algorithm_Direct_HKDF_HMAC_SHA_256:
+			case COSE_Algorithm_Direct_HKDF_HMAC_SHA_512:
 			case COSE_Algorithm_ECDH_ES_HKDF_256:
 			case COSE_Algorithm_ECDH_ES_HKDF_512:
 				((COSE_RecipientInfo *)h)->m_encrypt.m_message.m_flags |= 1;
@@ -458,3 +519,153 @@
 	return true;
 }
 
+
+byte RgbDontUse4[8 * 1024];
+
+bool BuildContextBytes(COSE * pcose, int algID, size_t cbitKey, byte ** ppbContext, size_t * pcbContext, CBOR_CONTEXT_COMMA cose_errback * perr)
+{
+	cn_cbor * pArray;
+	cn_cbor_errback cbor_error;
+	bool fReturn = false;
+	cn_cbor * cnT = NULL;
+	cn_cbor * cnArrayT = NULL;
+	cn_cbor * cnParam;
+	byte * pbContext = NULL;
+	size_t cbContext;
+
+	pArray = cn_cbor_array_create(CBOR_CONTEXT_PARAM_COMMA &cbor_error);
+	CHECK_CONDITION_CBOR(pArray != NULL, cbor_error);
+
+	cnT = cn_cbor_int_create(algID, CBOR_CONTEXT_PARAM_COMMA &cbor_error);
+	CHECK_CONDITION_CBOR(cnT != NULL, cbor_error);
+	CHECK_CONDITION_CBOR(cn_cbor_array_append(pArray, cnT, &cbor_error), cbor_error);
+	cnT = NULL;
+
+	cnArrayT = cn_cbor_array_create(CBOR_CONTEXT_PARAM_COMMA &cbor_error);
+	CHECK_CONDITION_CBOR(cnArrayT != NULL, cbor_error);
+
+	cnParam = _COSE_map_get_int(pcose, COSE_Header_KDF_U_nonce, COSE_BOTH, perr);
+	if (cnParam != NULL) {
+		cnT = cn_cbor_clone(cnParam, CBOR_CONTEXT_PARAM_COMMA &cbor_error);
+		CHECK_CONDITION_CBOR(cnT != NULL, cbor_error);
+		CHECK_CONDITION_CBOR(cn_cbor_array_append(cnArrayT, cnParam, &cbor_error), cbor_error);
+		cnT = NULL;
+		cnParam = NULL;
+	}
+
+	cnParam = _COSE_map_get_int(pcose, COSE_Header_KDF_U_name, COSE_BOTH, perr);
+	if (cnParam != NULL) {
+		cnT = cn_cbor_clone(cnParam, CBOR_CONTEXT_PARAM_COMMA &cbor_error);
+		CHECK_CONDITION_CBOR(cnT != NULL, cbor_error);
+		CHECK_CONDITION_CBOR(cn_cbor_array_append(cnArrayT, cnParam, &cbor_error), cbor_error);
+		cnT = NULL;
+		cnParam = NULL;
+	}
+
+	cnParam = _COSE_map_get_int(pcose, COSE_Header_KDF_U_other, COSE_BOTH, perr);
+	if (cnParam != NULL) {
+		cnT = cn_cbor_clone(cnParam, CBOR_CONTEXT_PARAM_COMMA &cbor_error);
+		CHECK_CONDITION_CBOR(cnT != NULL, cbor_error);
+		CHECK_CONDITION_CBOR(cn_cbor_array_append(cnArrayT, cnParam, &cbor_error), cbor_error);
+		cnT = NULL;
+		cnParam = NULL;
+	}
+
+	CHECK_CONDITION_CBOR(cn_cbor_array_append(pArray, cnArrayT, &cbor_error), cbor_error);
+	cnArrayT = NULL;
+
+	cnArrayT = cn_cbor_array_create(CBOR_CONTEXT_PARAM_COMMA &cbor_error);
+	CHECK_CONDITION_CBOR(cnArrayT != NULL, cbor_error);
+
+	cnParam = _COSE_map_get_int(pcose, COSE_Header_KDF_V_nonce, COSE_BOTH, perr);
+	if (cnParam != NULL) {
+		cnT = cn_cbor_clone(cnParam, CBOR_CONTEXT_PARAM_COMMA &cbor_error);
+		CHECK_CONDITION_CBOR(cnT != NULL, cbor_error);
+		CHECK_CONDITION_CBOR(cn_cbor_array_append(cnArrayT, cnParam, &cbor_error), cbor_error);
+		cnT = NULL;
+		cnParam = NULL;
+	}
+
+	cnParam = _COSE_map_get_int(pcose, COSE_Header_KDF_V_name, COSE_BOTH, perr);
+	if (cnParam != NULL) {
+		cnT = cn_cbor_clone(cnParam, CBOR_CONTEXT_PARAM_COMMA &cbor_error);
+		CHECK_CONDITION_CBOR(cnT != NULL, cbor_error);
+		CHECK_CONDITION_CBOR(cn_cbor_array_append(cnArrayT, cnParam, &cbor_error), cbor_error);
+		cnT = NULL;
+		cnParam = NULL;
+	}
+
+	cnParam = _COSE_map_get_int(pcose, COSE_Header_KDF_V_other, COSE_BOTH, perr);
+	if (cnParam != NULL) {
+		cnT = cn_cbor_clone(cnParam, CBOR_CONTEXT_PARAM_COMMA &cbor_error);
+		CHECK_CONDITION_CBOR(cnT != NULL, cbor_error);
+		CHECK_CONDITION_CBOR(cn_cbor_array_append(cnArrayT, cnParam, &cbor_error), cbor_error);
+		cnT = NULL;
+		cnParam = NULL;
+	}
+
+	CHECK_CONDITION_CBOR(cn_cbor_array_append(pArray, cnArrayT, &cbor_error), cbor_error);
+	cnArrayT = NULL;
+
+	cnArrayT = cn_cbor_array_create(CBOR_CONTEXT_PARAM_COMMA &cbor_error);
+	CHECK_CONDITION_CBOR(cnArrayT != NULL, cbor_error);
+
+	cnT = cn_cbor_int_create(cbitKey, CBOR_CONTEXT_PARAM_COMMA &cbor_error);
+	CHECK_CONDITION_CBOR(cnT != NULL, cbor_error);
+	CHECK_CONDITION_CBOR(cn_cbor_array_append(cnArrayT, cnT, &cbor_error), cbor_error);
+	cnT = NULL;
+
+	cnParam = _COSE_arrayget_int(pcose, INDEX_PROTECTED);
+	if (cnParam != NULL) {
+		cnT = cn_cbor_clone(cnParam, CBOR_CONTEXT_PARAM_COMMA &cbor_error);
+		CHECK_CONDITION_CBOR(cnT != NULL, cbor_error);
+		CHECK_CONDITION_CBOR(cn_cbor_array_append(cnArrayT, cnT, &cbor_error), cbor_error);
+		cnT = NULL;
+		cnParam = NULL;
+	}
+
+	cnParam = _COSE_map_get_int(pcose, COSE_Header_KDF_PUB_other, COSE_BOTH, perr);
+	if (cnParam != NULL) {
+		cnT = cn_cbor_clone(cnParam, CBOR_CONTEXT_PARAM_COMMA &cbor_error);
+		CHECK_CONDITION_CBOR(cnT != NULL, cbor_error);
+		CHECK_CONDITION_CBOR(cn_cbor_array_append(cnArrayT, cnParam, &cbor_error), cbor_error);
+		cnT = NULL;
+		cnParam = NULL;
+	}
+
+	CHECK_CONDITION_CBOR(cn_cbor_array_append(pArray, cnArrayT, &cbor_error), cbor_error);
+	cnArrayT = NULL;
+
+
+	cnParam = _COSE_map_get_int(pcose, COSE_Header_KDF_PRIV, COSE_BOTH, perr);
+	if (cnParam != NULL) {
+		cnT = cn_cbor_clone(cnParam, CBOR_CONTEXT_PARAM_COMMA &cbor_error);
+		CHECK_CONDITION_CBOR(cnT != NULL, cbor_error);
+		CHECK_CONDITION_CBOR(cn_cbor_array_append(cnArrayT, cnParam, &cbor_error), cbor_error);
+		cnT = NULL;
+		cnParam = NULL;
+	}
+
+	cbContext = cn_cbor_encoder_write(RgbDontUse4, 0, sizeof(RgbDontUse4), pArray);
+	CHECK_CONDITION(cbContext > 0, COSE_ERR_CBOR);
+	pbContext = (byte *)COSE_CALLOC(cbContext, 1, context);
+	CHECK_CONDITION(pbContext != NULL, COSE_ERR_OUT_OF_MEMORY);
+	CHECK_CONDITION(cn_cbor_encoder_write(pbContext, 0, cbContext, pArray), COSE_ERR_CBOR);
+
+	*ppbContext = pbContext;
+	*pcbContext = cbContext;
+	pbContext = NULL;
+	fReturn = true;
+
+returnHere:
+	if (pbContext != NULL) COSE_FREE(pbContext, context);
+	if (pArray != NULL) CN_CBOR_FREE(pArray, context);
+	if (cnArrayT != NULL) CN_CBOR_FREE(cnArrayT, context);
+	if (cnT != NULL) CN_CBOR_FREE(cnT, context);
+	return fReturn;
+
+errorReturn:
+	fReturn = false;
+	goto returnHere;
+}
+
diff --git a/src/Sign.c b/src/Sign.c
index 89f1d2c..5ec32ba 100644
--- a/src/Sign.c
+++ b/src/Sign.c
@@ -3,11 +3,14 @@
 #include "cose.h"
 #include "cose_int.h"
 
+COSE * SignRoot = NULL;
+
 bool IsValidSignHandle(HCOSE_SIGN h)
 {
 	COSE_SignMessage * p = (COSE_SignMessage *)h;
+
 	if (p == NULL) return false;
-	return true;
+	return _COSE_IsInList(SignRoot, &p->m_message);
 }
 
 
@@ -24,6 +27,8 @@
 		return NULL;
 	}
 
+	_COSE_InsertInList(&SignRoot, &pobj->m_message);
+
 	return (HCOSE_SIGN)pobj;
 }
 
@@ -57,6 +62,8 @@
 		pSigners = pSigners->next;
 	} while (pSigners != NULL);
 
+	if (pIn == NULL) _COSE_InsertInList(&SignRoot, &pobj->m_message);
+
 	return(HCOSE_SIGN)pobj;
 
 errorReturn:
@@ -79,6 +86,8 @@
 		return true;
 	}
 
+	_COSE_RemoveFromList(&SignRoot, &pMessage->m_message);
+
 #ifdef USE_CBOR_CONTEXT
 	context = pMessage->m_message.m_allocContext;
 #endif
diff --git a/src/Sign0.c b/src/Sign0.c
index 5b7201a..e404a53 100644
--- a/src/Sign0.c
+++ b/src/Sign0.c
@@ -8,13 +8,14 @@
 bool _COSE_Signer0_validate(COSE_Sign0Message * pSign, const cn_cbor * pKey, cose_errback * perr);
 void _COSE_Sign0_Release(COSE_Sign0Message * p);
 
-
+COSE * Sign0Root = NULL;
 
 bool IsValidSign0Handle(HCOSE_SIGN0 h)
 {
 	COSE_Sign0Message * p = (COSE_Sign0Message *)h;
+
 	if (p == NULL) return false;
-	return true;
+	return _COSE_IsInList(Sign0Root, &p->m_message);
 }
 
 
@@ -31,15 +32,16 @@
 		return NULL;
 	}
 
+	_COSE_InsertInList(&Sign0Root, &pobj->m_message);
+
 	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);
@@ -49,6 +51,8 @@
 		goto errorReturn;
 	}
 
+	if (pIn == NULL) _COSE_InsertInList(&Sign0Root, &pobj->m_message);
+
 	return(HCOSE_SIGN0)pobj;
 
 errorReturn:
@@ -71,6 +75,8 @@
 		return true;
 	}
 
+	_COSE_RemoveFromList(&Sign0Root, &pMessage->m_message);
+
 #ifdef USE_CBOR_CONTEXT
 	context = pMessage->m_message.m_allocContext;
 #endif
diff --git a/src/cbor.c b/src/cbor.c
index dc4c6bf..90e8256 100644
--- a/src/cbor.c
+++ b/src/cbor.c
@@ -1,5 +1,6 @@
 #include "cn-cbor/cn-cbor.h"
 #include <stdlib.h>
+#include <memory.h>
 
 #define INIT_CB(v) \
   if (errp) {errp->err = CN_CBOR_NO_ERROR;} \
@@ -14,10 +15,14 @@
     calloc(1, sizeof(cn_cbor));
 
 #define CN_CALLOC_CONTEXT() CN_CALLOC(context)
+#define CN_CBOR_CALLOC(c, i, ctx) ((ctx) && (ctx)->calloc_func) ? \
+    (ctx)->calloc_func(c, i, (ctx)->context) : \
+	calloc(c, i)
 #else
 #define CBOR_CONTEXT_PARAM
 #define CN_CALLOC(ctx) calloc(1, sizeof(cn_cbor));
 #define CN_CALLOC_CONTEXT() CN_CALLOC(context)
+#deifne CN_CBOR_CALLOC(c, i, ctx) calloc(c, i);
 #endif
 
 
@@ -106,3 +111,34 @@
 
 	return true;
 }
+
+cn_cbor * cn_cbor_clone(const cn_cbor * pIn, CBOR_CONTEXT_COMMA cn_cbor_errback * pcn_cbor_error)
+{
+	cn_cbor * pOut = NULL;
+	char * sz;
+	unsigned char * pb;
+
+	switch (pIn->type) {
+	case CN_CBOR_TEXT:
+		sz = CN_CBOR_CALLOC(pIn->length + 1, 1, context);
+		memcpy(sz, pIn->v.str, pIn->length);
+		sz[pIn->length] = 0;
+		pOut = cn_cbor_string_create(sz CBOR_CONTEXT_PARAM, pcn_cbor_error);
+		break;
+
+	case CN_CBOR_UINT:
+		pOut = cn_cbor_int_create(pIn->v.sint CBOR_CONTEXT_PARAM, pcn_cbor_error);
+		break;
+
+	case CN_CBOR_BYTES:
+		pb = CN_CBOR_CALLOC((int) pIn->length, 1, context);
+		memcpy(pb, pIn->v.bytes, pIn->length);
+		pOut = cn_cbor_data_create(pb, (int) pIn->length CBOR_CONTEXT_PARAM, pcn_cbor_error);
+		break;
+
+	default:
+		break;
+	}
+
+	return pOut;
+}
diff --git a/src/cose.h b/src/cose.h
index 7f7c0a0..d3aa969 100644
--- a/src/cose.h
+++ b/src/cose.h
@@ -136,6 +136,17 @@
 	COSE_Header_Content_Type = 3,
 	COSE_Header_KID = 4,
 	COSE_Header_IV = 5,
+
+	COSE_Header_HKDF_salt = -20,
+	COSE_Header_KDF_U_nonce = -21,
+	COSE_Header_KDF_U_name = -22,
+	COSE_Header_KDF_U_other = -23,
+	COSE_Header_KDF_V_nonce = -24,
+	COSE_Header_KDF_V_name = -25,
+	COSE_Header_KDF_V_other = -26,
+
+	COSE_Header_KDF_PUB_other = -999,
+	COSE_Header_KDF_PRIV = -998,
 } COSE_Header;
 
 typedef enum {
@@ -260,3 +271,10 @@
 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);
+
+
+/*
+*/
+
+extern cn_cbor * cn_cbor_clone(const cn_cbor * pIn, CBOR_CONTEXT_COMMA cn_cbor_errback * perr);
+
diff --git a/src/cose_int.h b/src/cose_int.h
index 65317f4..51609aa 100644
--- a/src/cose_int.h
+++ b/src/cose_int.h
@@ -169,9 +169,9 @@
 
 extern COSE_RecipientInfo * _COSE_Recipient_Init_From_Object(cn_cbor *, CBOR_CONTEXT_COMMA cose_errback * errp);
 extern void _COSE_Recipient_Free(COSE_RecipientInfo *);
-extern bool _COSE_Recipient_decrypt(COSE_RecipientInfo * pRecip, int cbitKey, byte * pbKey, cose_errback * errp);
+extern bool _COSE_Recipient_decrypt(COSE_RecipientInfo * pRecip, int algIn, int cbitKey, byte * pbKey, cose_errback * errp);
 extern bool _COSE_Recipient_encrypt(COSE_RecipientInfo * pRecipient, const byte * pbContent, size_t cbContent, cose_errback * perr);
-extern byte * _COSE_RecipientInfo_generateKey(COSE_RecipientInfo * pRecipient, size_t cbitKeySize, cose_errback * perr);
+extern byte * _COSE_RecipientInfo_generateKey(COSE_RecipientInfo * pRecipient, int algIn, size_t cbitKeySize, cose_errback * perr);
 
 
 //  Signed items
@@ -183,6 +183,11 @@
 extern bool _COSE_SignerInfo_Free(COSE_SignerInfo * pSigner);
 extern bool _COSE_Signer_validate(COSE_SignMessage * pSign, COSE_SignerInfo * pSigner, const byte * pbContent, size_t cbContent, const byte * pbProtected, size_t cbProtected, cose_errback * perr);
 
+
+// Sign0 items
+extern HCOSE_SIGN0 _COSE_Sign0_Init_From_Object(cn_cbor * cbor, COSE_Sign0Message * pIn, CBOR_CONTEXT_COMMA cose_errback * perr);
+extern void _COSE_Sign0_Release(COSE_Sign0Message * p);
+
 //  Mac-ed items
 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);
diff --git a/src/crypto.h b/src/crypto.h
index 8f7c8df..043c4f9 100644
--- a/src/crypto.h
+++ b/src/crypto.h
@@ -46,6 +46,9 @@
 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);
 
+bool HKDF_Extract(COSE * pcose, const byte * pbKey, size_t cbKey, size_t cbitDigest, byte * rgbDigest, size_t * pcbDigest, CBOR_CONTEXT_COMMA cose_errback * perr);
+bool HKDF_Expand(COSE * pcose, int cbitDigest, const byte * pbPRK, size_t cbPRK, const byte * pbInfo, size_t cbInfo, byte * pbOutput, size_t cbOutput, cose_errback * perr);
+
 /**
 * Perform a signature operation
 *
diff --git a/src/openssl.c b/src/openssl.c
index 4ddfe97..e877bab 100644
--- a/src/openssl.c
+++ b/src/openssl.c
@@ -15,6 +15,7 @@
 #include <openssl/ecdsa.h>
 #include <openssl/rand.h>
 
+#define MIN(A, B) ((A) < (B) ? (A) : (B))
 
 bool AES_CCM_Decrypt(COSE_Enveloped * pcose, int TSize, int LSize, const byte * pbKey, int cbKey, const byte * pbCrypto, size_t cbCrypto, const byte * pbAuthData, size_t cbAuthData, cose_errback * perr)
 {
@@ -536,6 +537,85 @@
 }
 #endif
 
+
+bool HKDF_Extract(COSE * pcose, const byte * pbKey, size_t cbKey, size_t cbitDigest, byte * rgbDigest, size_t * pcbDigest, CBOR_CONTEXT_COMMA cose_errback * perr)
+{
+	byte rgbSalt[EVP_MAX_MD_SIZE] = { 0 };
+	int cbSalt;
+	cn_cbor * cnSalt;
+	HMAC_CTX ctx;
+	const EVP_MD * pmd = NULL;
+	unsigned int cbDigest;
+
+	if (0) {
+	errorReturn:
+		HMAC_cleanup(&ctx);
+		return false;
+	}
+
+	switch (cbitDigest) {
+	case 256: pmd = EVP_sha256(); cbSalt = 256 / 8;  break;
+	case 384: pmd = EVP_sha384(); cbSalt = 384 / 8; break;
+	case 512: pmd = EVP_sha512(); cbSalt = 512 / 8; break;
+	default: FAIL_CONDITION(COSE_ERR_INVALID_PARAMETER); break;
+	}
+
+	cnSalt = _COSE_map_get_int(pcose, COSE_Header_HKDF_salt, COSE_BOTH, perr);
+
+	HMAC_CTX_init(&ctx);
+	if (cnSalt != NULL) {
+		CHECK_CONDITION(HMAC_Init(&ctx, cnSalt->v.bytes, (int) cnSalt->length, pmd), COSE_ERR_CRYPTO_FAIL);
+	}
+	else {
+		CHECK_CONDITION(HMAC_Init(&ctx, rgbSalt, cbSalt, pmd), COSE_ERR_CRYPTO_FAIL);
+	}
+	CHECK_CONDITION(HMAC_Update(&ctx, pbKey, (int)cbKey), COSE_ERR_CRYPTO_FAIL);
+	CHECK_CONDITION(HMAC_Final(&ctx, rgbDigest, &cbDigest), COSE_ERR_CRYPTO_FAIL);
+	*pcbDigest = cbDigest;
+	HMAC_cleanup(&ctx);
+	return true;
+}
+
+bool HKDF_Expand(COSE * pcose, int cbitDigest, const byte * pbPRK, size_t cbPRK, const byte * pbInfo, size_t cbInfo, byte * pbOutput, size_t cbOutput, cose_errback * perr)
+{
+	HMAC_CTX ctx;
+	const EVP_MD * pmd = NULL;
+	size_t ib;
+	int cbSalt;
+	unsigned int cbDigest = 0;
+	byte rgbDigest[EVP_MAX_MD_SIZE];
+	byte bCount = 1;
+
+	if (0) {
+	errorReturn:
+		HMAC_cleanup(&ctx);
+		return false;
+	}
+
+	switch (cbitDigest) {
+	case 256: pmd = EVP_sha256(); cbSalt = 256 / 8;  break;
+	case 384: pmd = EVP_sha384(); cbSalt = 384 / 8; break;
+	case 512: pmd = EVP_sha512(); cbSalt = 512 / 8; break;
+	default: FAIL_CONDITION(COSE_ERR_INVALID_PARAMETER); break;
+	}
+
+	HMAC_CTX_init(&ctx);
+	CHECK_CONDITION(HMAC_Init(&ctx, pbPRK, (int)cbPRK, pmd), COSE_ERR_CRYPTO_FAIL);
+
+	for (ib = 0; ib < cbOutput; ib += cbDigest, bCount += 1) {
+		CHECK_CONDITION(HMAC_Update(&ctx, rgbDigest, cbDigest), COSE_ERR_CRYPTO_FAIL);
+		CHECK_CONDITION(HMAC_Update(&ctx, pbInfo, cbInfo), COSE_ERR_CRYPTO_FAIL);
+		CHECK_CONDITION(HMAC_Update(&ctx, &bCount, 1), COSE_ERR_CRYPTO_FAIL);
+		CHECK_CONDITION(HMAC_Final(&ctx, rgbDigest, &cbDigest), COSE_ERR_CRYPTO_FAIL);
+
+		memcpy(pbOutput + ib, rgbDigest, MIN(cbDigest, cbOutput - ib));
+	}
+
+	HMAC_cleanup(&ctx);
+	return true;
+
+}
+
 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;
diff --git a/test/CMakeLists.txt b/test/CMakeLists.txt
index b1fbb7c..b83ff94 100644
--- a/test/CMakeLists.txt
+++ b/test/CMakeLists.txt
@@ -29,6 +29,7 @@
 enable_testing()
 
 add_test ( NAME cose_test COMMAND cose_test )
+
 add_test ( NAME mac-02 WORKING_DIRECTORY ${CMAKE_SOURCE_DIR} COMMAND cose_test Examples/spec-examples/Mac-02.json )
 add_test ( NAME mac-04 WORKING_DIRECTORY ${CMAKE_SOURCE_DIR} COMMAND cose_test Examples/spec-examples/Mac-04.json )
 
@@ -37,47 +38,18 @@
 add_test ( NAME sig-03 WORKING_DIRECTORY ${CMAKE_SOURCE_DIR} COMMAND cose_test Examples/spec-examples/Sig-03.json )
 add_test ( NAME sig-04 WORKING_DIRECTORY ${CMAKE_SOURCE_DIR} COMMAND cose_test Examples/spec-examples/Sig-04.json )
 
+add_test ( NAME enc-02 WORKING_DIRECTORY ${CMAKE_SOURCE_DIR} COMMAND cose_test Examples/spec-examples/Enc-02.json )
 add_test ( NAME enc-04 WORKING_DIRECTORY ${CMAKE_SOURCE_DIR} COMMAND cose_test Examples/spec-examples/Enc-04.json )
 add_test ( NAME enc-05 WORKING_DIRECTORY ${CMAKE_SOURCE_DIR} COMMAND cose_test Examples/spec-examples/Enc-05.json )
 
-add_test ( NAME hmac-01 WORKING_DIRECTORY ${CMAKE_SOURCE_DIR} COMMAND cose_test --dir Examples/hmac-examples )
+add_test ( NAME aes-ccm WORKING_DIRECTORY ${CMAKE_SOURCE_DIR} COMMAND cose_test --dir Examples/aes-ccm-examples )
 
-add_test ( NAME cbc-mac-01 WORKING_DIRECTORY ${CMAKE_SOURCE_DIR} COMMAND cose_test Examples/cbc-mac-examples/cbc-mac-01.json )
-add_test ( NAME cbc-mac-02 WORKING_DIRECTORY ${CMAKE_SOURCE_DIR} COMMAND cose_test Examples/cbc-mac-examples/cbc-mac-02.json )
-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 aes-gcm WORKING_DIRECTORY ${CMAKE_SOURCE_DIR} COMMAND cose_test --dir Examples/aes-gcm-examples )
 
-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 )
-add_test ( NAME aes-gcm-04 WORKING_DIRECTORY ${CMAKE_SOURCE_DIR} COMMAND cose_test Examples/aes-gcm-examples/aes-gcm-04.json )
-
-add_test ( NAME aes-gcm-enc-01 WORKING_DIRECTORY ${CMAKE_SOURCE_DIR} COMMAND cose_test Examples/aes-gcm-examples/aes-gcm-enc-01.json )
-add_test ( NAME aes-gcm-enc-02 WORKING_DIRECTORY ${CMAKE_SOURCE_DIR} COMMAND cose_test Examples/aes-gcm-examples/aes-gcm-enc-02.json )
-add_test ( NAME aes-gcm-enc-03 WORKING_DIRECTORY ${CMAKE_SOURCE_DIR} COMMAND cose_test Examples/aes-gcm-examples/aes-gcm-enc-03.json )
-add_test ( NAME aes-gcm-enc-04 WORKING_DIRECTORY ${CMAKE_SOURCE_DIR} COMMAND cose_test Examples/aes-gcm-examples/aes-gcm-enc-04.json )
-
-add_test ( NAME aes-ccm-01 WORKING_DIRECTORY ${CMAKE_SOURCE_DIR} COMMAND cose_test Examples/aes-ccm-examples/aes-ccm-01.json )
-add_test ( NAME aes-ccm-02 WORKING_DIRECTORY ${CMAKE_SOURCE_DIR} COMMAND cose_test Examples/aes-ccm-examples/aes-ccm-02.json )
-add_test ( NAME aes-ccm-03 WORKING_DIRECTORY ${CMAKE_SOURCE_DIR} COMMAND cose_test Examples/aes-ccm-examples/aes-ccm-03.json )
-add_test ( NAME aes-ccm-04 WORKING_DIRECTORY ${CMAKE_SOURCE_DIR} COMMAND cose_test Examples/aes-ccm-examples/aes-ccm-04.json )
-add_test ( NAME aes-ccm-05 WORKING_DIRECTORY ${CMAKE_SOURCE_DIR} COMMAND cose_test Examples/aes-ccm-examples/aes-ccm-05.json )
-add_test ( NAME aes-ccm-06 WORKING_DIRECTORY ${CMAKE_SOURCE_DIR} COMMAND cose_test Examples/aes-ccm-examples/aes-ccm-06.json )
-add_test ( NAME aes-ccm-07 WORKING_DIRECTORY ${CMAKE_SOURCE_DIR} COMMAND cose_test Examples/aes-ccm-examples/aes-ccm-07.json )
-add_test ( NAME aes-ccm-08 WORKING_DIRECTORY ${CMAKE_SOURCE_DIR} COMMAND cose_test Examples/aes-ccm-examples/aes-ccm-08.json )
-
-add_test ( NAME aes-ccm-enc-01 WORKING_DIRECTORY ${CMAKE_SOURCE_DIR} COMMAND cose_test Examples/aes-ccm-examples/aes-ccm-enc-01.json )
-add_test ( NAME aes-ccm-enc-02 WORKING_DIRECTORY ${CMAKE_SOURCE_DIR} COMMAND cose_test Examples/aes-ccm-examples/aes-ccm-enc-02.json )
-add_test ( NAME aes-ccm-enc-03 WORKING_DIRECTORY ${CMAKE_SOURCE_DIR} COMMAND cose_test Examples/aes-ccm-examples/aes-ccm-enc-03.json )
-add_test ( NAME aes-ccm-enc-04 WORKING_DIRECTORY ${CMAKE_SOURCE_DIR} COMMAND cose_test Examples/aes-ccm-examples/aes-ccm-enc-04.json )
-add_test ( NAME aes-ccm-enc-05 WORKING_DIRECTORY ${CMAKE_SOURCE_DIR} COMMAND cose_test Examples/aes-ccm-examples/aes-ccm-enc-05.json )
-add_test ( NAME aes-ccm-enc-06 WORKING_DIRECTORY ${CMAKE_SOURCE_DIR} COMMAND cose_test Examples/aes-ccm-examples/aes-ccm-enc-06.json )
-add_test ( NAME aes-ccm-enc-07 WORKING_DIRECTORY ${CMAKE_SOURCE_DIR} COMMAND cose_test Examples/aes-ccm-examples/aes-ccm-enc-07.json )
-add_test ( NAME aes-ccm-enc-08 WORKING_DIRECTORY ${CMAKE_SOURCE_DIR} COMMAND cose_test Examples/aes-ccm-examples/aes-ccm-enc-08.json )
+add_test ( NAME cbc-mac WORKING_DIRECTORY ${CMAKE_SOURCE_DIR} COMMAND cose_test --dir Examples/cbc-mac-examples )
 
 add_test ( NAME ecdsa WORKING_DIRECTORY ${CMAKE_SOURCE_DIR} COMMAND cose_test --dir Examples/ecdsa-examples )
+
+add_test ( NAME hmac WORKING_DIRECTORY ${CMAKE_SOURCE_DIR} COMMAND cose_test --dir Examples/hmac-examples )
+
+add_test (NAME hkdf-hmac-sha WORKING_DIRECTORY ${CMAKE_SOURCE_DIR} COMMAND cose_test --dir Examples/hkdf-hmac-sha-examples )
diff --git a/test/test.c b/test/test.c
index 11acf5c..43af8e1 100644
--- a/test/test.c
+++ b/test/test.c
@@ -28,7 +28,7 @@
 	int    i;
 } NameMap;
 
-NameMap RgAlgorithmNames[26] = {
+NameMap RgAlgorithmNames[30] = {
 	{"HS256", COSE_Algorithm_HMAC_256_256},
 	{"HS256/64", COSE_Algorithm_HMAC_256_64},
 	{"HS384", COSE_Algorithm_HMAC_384_384},
@@ -55,6 +55,10 @@
 	{"ES256", COSE_Algorithm_ECDSA_SHA_256},
 	{"ES384", COSE_Algorithm_ECDSA_SHA_384},
 	{"ES512", COSE_Algorithm_ECDSA_SHA_512},
+	{"HKDF-HMAC-SHA-256", COSE_Algorithm_Direct_HKDF_HMAC_SHA_256},
+	{"HKDF-HMAC-SHA-512", COSE_Algorithm_Direct_HKDF_HMAC_SHA_512},
+	{"HKDF-AES-128", COSE_Algorithm_Direct_HKDF_AES_128},
+	{"HKDF-AES-256", COSE_Algorithm_Direct_HKDF_AES_256},
 };
 
 
@@ -82,29 +86,6 @@
 	return MapName(p, RgAlgorithmNames, _countof(RgAlgorithmNames));
 }
 
-cn_cbor * cn_cbor_clone(const cn_cbor * pIn)
-{
-	cn_cbor * pOut = NULL;
-	char * sz;
-
-	switch (pIn->type) {
-	case CN_CBOR_TEXT:
-		sz = malloc(pIn->length + 1);
-		memcpy(sz, pIn->v.str, pIn->length);
-		sz[pIn->length] = 0;
-		pOut = cn_cbor_string_create(sz, CBOR_CONTEXT_PARAM_COMMA NULL);
-		break;
-
-	case CN_CBOR_UINT:
-		pOut = cn_cbor_int_create(pIn->v.sint, CBOR_CONTEXT_PARAM_COMMA NULL);
-		break;
-
-	default:
-		break;
-	}
-
-	return pOut;
-}
 
 byte fromHex(char c)
 {
@@ -199,7 +180,8 @@
 		}
 		else if (strcmp(pKey->v.str, "ctyp") == 0) {
 			keyNew = COSE_Header_Content_Type;
-			pValueNew = cn_cbor_clone(pValue);;
+			pValueNew = cn_cbor_clone(pValue, CBOR_CONTEXT_PARAM_COMMA NULL);
+			if (pValueNew == NULL) return FALSE;
 		}
 		else if (strcmp(pKey->v.str, "IV_hex") == 0) {
 			keyNew = COSE_Header_IV;
@@ -349,7 +331,7 @@
 					((RgStringKeys[i].kty == 0) || (RgStringKeys[i].kty == kty))) {
 					switch (RgStringKeys[i].operation) {
 					case OPERATION_NONE:
-						cn_cbor_mapput_int(pKeyOut, RgStringKeys[i].keyNew, cn_cbor_clone(pValue), CBOR_CONTEXT_PARAM_COMMA NULL);
+						cn_cbor_mapput_int(pKeyOut, RgStringKeys[i].keyNew, cn_cbor_clone(pValue, CBOR_CONTEXT_PARAM_COMMA NULL), CBOR_CONTEXT_PARAM_COMMA NULL);
 						break;
 
 					case OPERATION_BASE64:
diff --git a/test/test.h b/test/test.h
index b4629b1..b64bc1d 100644
--- a/test/test.h
+++ b/test/test.h
@@ -66,7 +66,6 @@
 extern int CFails;
 
 int MapAlgorithmName(const cn_cbor * p);
-cn_cbor * cn_cbor_clone(const cn_cbor * pIn);
 byte * GetCBOREncoding(const cn_cbor * pControl, int * pcbEncoded);
 bool SetAttributes(HCOSE hHandle, const cn_cbor * pAttributes, int which);
 cn_cbor * BuildKey(const cn_cbor * pKeyIn);