First pass at getting COSE_KEY written (#112)

* First pass at getting COSE_KEY written

* Always set a context even if null

* Correct context parameters

* Fix a memoy leak, an object leak and an incorrect return code

* Fix compile error.

* Reduce test count

Windows only does one compiler

* Wrong level
diff --git a/.github/workflows/main.yml b/.github/workflows/main.yml
index 7827ebf..3387630 100644
--- a/.github/workflows/main.yml
+++ b/.github/workflows/main.yml
@@ -35,6 +35,10 @@
             "-DCOSE_C_INCLUDE_ENCRYPT=OFF -DCOSE_C_INCLUDE_ENCRYPT0=OFF -DCOSE_C_INCLUDE_MAC0=OFF -DCOSE_C_INCLUDE_MAC=OFF -DCOSE_C_INCLUDE_SIGN=OFF -DCOSE_C_INCLUDE_SIGN1=ON -DCOSE_C_INCLUDE_COUNTERSIGN=ON",

             "-DCOSE_C_OPTIMIZE=ON -DCOSE_C_INCLUDE_COUNTERSIGN=ON"

           ]

+        exclude:

+          # this really just does VS not gcc or clang

+          - os: windows-2019

+            COMPILER: gcc

 

     steps:

       - uses: actions/checkout@v1

diff --git a/include/cose/cose.h b/include/cose/cose.h
index 8c24fb5..03a5870 100644
--- a/include/cose/cose.h
+++ b/include/cose/cose.h
@@ -3,6 +3,9 @@
 #include <stdbool.h>
 #include <cn-cbor/cn-cbor.h>
 #include "cose/cose_configure.h"
+#ifdef COSE_C_USE_OPENSSL
+#include <openssl/evp.h>
+#endif
 
 #ifdef __cplusplus
 extern "C" {
@@ -21,6 +24,7 @@
 typedef struct _cose_mac0* HCOSE_MAC0;
 typedef struct _cose_counterSignature* HCOSE_COUNTERSIGN;
 typedef struct _cose_counterSignature1* HCOSE_COUNTERSIGN1;
+typedef struct _cose_key* HCOSE_KEY;
 
 /**
  * All of the different kinds of errors
@@ -210,6 +214,19 @@
 } COSE_Curves;
 
 /*
+ * Functions dealing with keys
+ */
+
+HCOSE_KEY COSE_KEY_FromCbor(cn_cbor* pcborKey,
+	CBOR_CONTEXT_COMMA cose_errback* perror);
+bool COSE_KEY_Free(HCOSE_KEY h);
+#ifdef COSE_C_USE_OPENSSL
+HCOSE_KEY COSE_KEY_FromEVP(EVP_PKEY* opensslKey,
+	cn_cbor* pcborKey,
+	CBOR_CONTEXT_COMMA cose_errback* perror);
+#endif
+	
+/*
  *  messages dealing with the Enveloped message type
  */
 
@@ -288,11 +305,20 @@
 bool COSE_Recipient_SetKey(HCOSE_RECIPIENT h,
 	const cn_cbor* pKey,
 	cose_errback* perror);
+bool COSE_Recipient_SetKey2(HCOSE_RECIPIENT h,
+	HCOSE_KEY hKey,
+	cose_errback* perror);
+
 bool COSE_Recipient_SetSenderKey(HCOSE_RECIPIENT h,
 	const cn_cbor* pKey,
 	int destination,
 	cose_errback* perror);
-bool COSE_Recipient_SetExternal(HCOSE_RECIPIENT hcose,
+bool COSE_Recipient_SetSenderKey2(HCOSE_RECIPIENT h,
+	HCOSE_KEY hKey,
+	int destintion,
+	cose_errback* perror);
+
+	bool COSE_Recipient_SetExternal(HCOSE_RECIPIENT hcose,
 	const byte* pbExternalData,
 	size_t cbExternalData,
 	cose_errback* perr);
@@ -480,6 +506,9 @@
 bool COSE_Signer_SetKey(HCOSE_SIGNER hSigner,
 	const cn_cbor* pkey,
 	cose_errback* perr);
+bool COSE_Signer_SetKey2(HCOSE_SIGNER hSigner,
+	HCOSE_KEY pkey,
+	cose_errback* perr);
 cn_cbor* COSE_Signer_map_get_int(HCOSE_SIGNER h,
 	int key,
 	int flags,
@@ -525,9 +554,13 @@
 	cose_errback* perr);
 
 bool COSE_Sign1_Sign(HCOSE_SIGN1 h, const cn_cbor* pkey, cose_errback* perr);
+bool COSE_Sign1_Sign2(HCOSE_SIGN1 h, HCOSE_KEY pkey, cose_errback* perr);
 bool COSE_Sign1_validate(HCOSE_SIGN1 hSign,
 	const cn_cbor* pkey,
 	cose_errback* perr);
+bool COSE_Sign1_validate2(HCOSE_SIGN1 hSign,
+	HCOSE_KEY pkey,
+	cose_errback* perr);
 cn_cbor* COSE_Sign1_map_get_int(HCOSE_SIGN1 h,
 	int key,
 	int flags,
@@ -560,6 +593,9 @@
 bool COSE_CounterSign_SetKey(HCOSE_COUNTERSIGN,
 	const cn_cbor* pkey,
 	cose_errback* perr);
+bool COSE_CounterSign_SetKey2(HCOSE_COUNTERSIGN,
+	HCOSE_KEY pkey,
+	cose_errback* perr);
 
 	
 HCOSE_COUNTERSIGN COSE_Signer_add_countersignature(HCOSE_SIGNER hSigner, HCOSE_COUNTERSIGN hCountersignature, cose_errback* perr);
diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt
index c62cdfc..f5e9194 100644
--- a/src/CMakeLists.txt
+++ b/src/CMakeLists.txt
@@ -39,6 +39,7 @@
     cose_crypto.h
     cose_int.h
     Cose.c
+    CoseKey.c
     CounterSign.c
     CounterSign0.c
     MacMessage.c
diff --git a/src/Cose.c b/src/Cose.c
index 8c29e98..413a099 100644
--- a/src/Cose.c
+++ b/src/Cose.c
@@ -55,6 +55,7 @@
 	pcose->m_unprotectMap =
 		cn_cbor_map_create(CBOR_CONTEXT_PARAM_COMMA & errState);
 	CHECK_CONDITION_CBOR(pcose->m_unprotectMap != NULL, errState);
+	pcose->m_ownUnprotectedMap = true;
 	CHECK_CONDITION_CBOR(
 		_COSE_array_replace(pcose, pcose->m_unprotectMap, INDEX_UNPROTECTED,
 			CBOR_CONTEXT_PARAM_COMMA & errState),
diff --git a/src/CoseKey.c b/src/CoseKey.c
new file mode 100644
index 0000000..9a101b5
--- /dev/null
+++ b/src/CoseKey.c
@@ -0,0 +1,131 @@
+#include <stdlib.h>
+
+#include "cose/cose.h"
+#include "cose/cose_configure.h"
+#include "cose_int.h"
+#include "cose_crypto.h"
+
+COSE_KEY *KeysRoot = 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 IsValidKeyHandle(HCOSE_KEY h)
+{
+	COSE_KEY *p = (COSE_KEY*)h;
+	if (KeysRoot == NULL) {
+		return false;
+	}
+	if (p == NULL) {
+		return false;
+	}
+
+	for (const COSE_KEY *walk = KeysRoot; walk != NULL; walk = walk->m_nextKey) {
+		if (walk == p) {
+			return true;
+		}
+	}
+	return false;
+}
+
+HCOSE_KEY COSE_KEY_FromCbor(cn_cbor *pcborKey,
+	CBOR_CONTEXT_COMMA cose_errback *perror)
+{
+	COSE_KEY *pkey = NULL;
+
+	pkey = (COSE_KEY *)COSE_CALLOC(1, sizeof(COSE_KEY), context);
+
+	if (pkey == NULL) {
+		if (perror != NULL) {
+			perror->err = COSE_ERR_OUT_OF_MEMORY;
+		}
+		return NULL;
+	}
+
+#ifdef USE_CBOR_CONTEXT
+	if (context != NULL) {
+		pkey->m_allocContext = *context;
+	}
+#endif
+	
+	pkey->m_refCount = 1;
+	pkey->m_cborKey = pcborKey;
+
+	pkey->m_nextKey = KeysRoot;
+	KeysRoot = pkey;
+	
+	return (HCOSE_KEY)pkey;
+}
+
+bool COSE_KEY_Free(HCOSE_KEY h)
+{
+	COSE_KEY *p = (COSE_KEY *)h;
+	if (!IsValidKeyHandle(h)) {
+		return false;	
+	}
+
+	if (p->m_refCount > 1) {
+		p->m_refCount--;
+		return true;
+	}
+	
+	if (KeysRoot == p) {
+		KeysRoot = p->m_nextKey;
+		p->m_nextKey = NULL;;
+	}
+	else {
+		for (COSE_KEY *walk = KeysRoot; walk->m_nextKey != NULL;
+			 walk = walk->m_nextKey) {
+			if (walk->m_nextKey == p) {
+				walk->m_nextKey = p->m_nextKey;
+				p->m_nextKey = NULL;
+				break;
+			}
+		}
+	}
+	
+	COSE_FREE(p, &p->m_allocContext);
+
+	return true;
+}
+
+#if defined(COSE_C_USE_OPENSSL) && (OPENSSL_VERSION_NUMBER > 0x10100000L)
+HCOSE_KEY COSE_KEY_FromEVP(EVP_PKEY * opensslKey, cn_cbor * pcborKey, CBOR_CONTEXT_COMMA cose_errback* perror)
+{
+	COSE_KEY *pkey = NULL;
+
+	pkey = (COSE_KEY *)COSE_CALLOC(1, sizeof(COSE_KEY), context);
+
+	if (pkey == NULL) {
+		perror->err = COSE_ERR_OUT_OF_MEMORY;
+		return NULL;
+	}
+
+#ifdef USE_CBOR_CONTEXT
+	if (context != NULL) {
+		pkey->m_allocContext = *context;
+	}
+#endif
+
+	pkey->m_refCount = 1;
+	pkey->m_cborKey = pcborKey;
+	pkey->m_opensslKey = opensslKey;
+	EVP_PKEY_up_ref(opensslKey);
+
+	pkey->m_nextKey = KeysRoot;
+	KeysRoot = pkey;
+
+	return (HCOSE_KEY)pkey;
+}
+#endif
diff --git a/src/CounterSign.c b/src/CounterSign.c
index d7fee85..8d4b0e8 100644
--- a/src/CounterSign.c
+++ b/src/CounterSign.c
@@ -230,17 +230,44 @@
 	cose_errback* perr)
 {
 	bool fRet = false;
-	CHECK_CONDITION(IsValidCounterSignHandle(h), COSE_ERR_INVALID_HANDLE);
+	HCOSE_KEY coseKey = NULL;
+#ifdef USE_CBOR_CONTEXT
+	cn_cbor_context* context = NULL;
+#endif
+	
 	CHECK_CONDITION(pkey != NULL, COSE_ERR_INVALID_PARAMETER);
+	coseKey = COSE_KEY_FromCbor((cn_cbor*) pkey, CBOR_CONTEXT_PARAM_COMMA perr);
+	CHECK_CONDITION(coseKey != NULL, COSE_ERR_OUT_OF_MEMORY);
 
-	COSE_CounterSign* p = (COSE_CounterSign*)h;
-	if (p->m_signer.m_pkey != NULL) {
-		CN_CBOR_FREE(p->m_signer.m_pkey, &p->m_signer.m_message.m_allocContext);
-	}
-	p->m_signer.m_pkey = (cn_cbor *) pkey;
+	fRet = COSE_CounterSign_SetKey2(h, coseKey, perr);
 
-	fRet = true;
 errorReturn:
+	if (coseKey != NULL) {
+		COSE_KEY_Free(coseKey);
+	}
+	return fRet;
+}
+
+bool COSE_CounterSign_SetKey2(HCOSE_COUNTERSIGN hSigner, HCOSE_KEY hKey, cose_errback* perr)
+{
+	bool fRet = false;
+	COSE_CounterSign* pSigner = (COSE_CounterSign*)hSigner;
+
+	CHECK_CONDITION(IsValidCounterSignHandle(hSigner), COSE_ERR_INVALID_HANDLE);
+	CHECK_CONDITION(IsValidKeyHandle(hKey), COSE_ERR_INVALID_HANDLE);
+	
+	if (pSigner->m_signer.m_pkey != NULL) {
+		COSE_KEY_Free((HCOSE_KEY) pSigner->m_signer.m_pkey);
+	}
+	COSE_KEY* pKey = (COSE_KEY*)hKey;
+	
+	pSigner->m_signer.m_pkey = pKey;
+	if (hKey != NULL) {
+		pKey->m_refCount += 1;
+	}
+	fRet = true;
+
+	errorReturn:
 	return fRet;
 }
 
diff --git a/src/Recipient.c b/src/Recipient.c
index dd2c307..7b98788 100644
--- a/src/Recipient.c
+++ b/src/Recipient.c
@@ -147,12 +147,10 @@
 
 	_COSE_Enveloped_Release(&pRecipient->m_encrypt);
 	if (pRecipient->m_pkey != NULL) {
-		CN_CBOR_FREE((cn_cbor *)pRecipient->m_pkey,
-			&pRecipient->m_encrypt.m_message.m_allocContext);
+		COSE_KEY_Free((HCOSE_KEY) pRecipient->m_pkey);
 	}
 	if (pRecipient->m_pkeyStatic != NULL) {
-		CN_CBOR_FREE((cn_cbor *) pRecipient->m_pkeyStatic,
-			&pRecipient->m_encrypt.m_message.m_allocContext);
+		COSE_KEY_Free((HCOSE_KEY) pRecipient->m_pkeyStatic);
 	}
 
 	COSE_FREE(pRecipient, &pRecipient->m_encrypt.m_message.m_allocContext);
@@ -184,8 +182,8 @@
 	bool fStatic,
 	bool fSend,
 	int algResult,
-	const cn_cbor *pKeyPrivate,
-	const cn_cbor *pKeyPublic,
+	COSE_KEY *pKeyPrivate,
+	COSE_KEY *pKeyPublic,
 	byte *pbKey,
 	size_t cbitKey,
 	size_t cbitHash,
@@ -207,10 +205,10 @@
 
 	if (fECDH) {
 #ifdef USE_ECDH
-		cn_cbor *pkeyMessage;
+		COSE_KEY *pkeyMessage;
 
 		if (pKeyPrivate != NULL) {
-			cn = cn_cbor_mapget_int(pKeyPrivate, COSE_Key_Type);
+			cn = cn_cbor_mapget_int(pKeyPrivate->m_cborKey, COSE_Key_Type);
 			CHECK_CONDITION((cn != NULL) && (cn->type == CN_CBOR_UINT),
 				COSE_ERR_INVALID_PARAMETER);
 			CHECK_CONDITION(
@@ -218,7 +216,7 @@
 		}
 
 		if (pKeyPublic != NULL) {
-			cn = cn_cbor_mapget_int(pKeyPublic, COSE_Key_Type);
+			cn = cn_cbor_mapget_int(pKeyPublic->m_cborKey, COSE_Key_Type);
 			CHECK_CONDITION((cn != NULL) && (cn->type == CN_CBOR_UINT),
 				COSE_ERR_INVALID_PARAMETER);
 			CHECK_CONDITION(
@@ -227,28 +225,33 @@
 
 		if (fSend) {
 			CHECK_CONDITION(pKeyPublic != NULL, COSE_ERR_INVALID_PARAMETER);
-			pkeyMessage = (cn_cbor *)pKeyPrivate;
+			pkeyMessage = pKeyPrivate;
 
 			if (!ECDH_ComputeSecret(pCose, &pkeyMessage, pKeyPublic, &pbSecret,
 					&cbSecret, CBOR_CONTEXT_PARAM_COMMA perr)) {
 				goto errorReturn;
 			}
-			if (!fStatic && pkeyMessage->parent == NULL) {
+			if (!fStatic && pkeyMessage->m_cborKey->parent == NULL) {
 				if (!_COSE_map_put(pCose, COSE_Header_ECDH_EPHEMERAL,
-						pkeyMessage, COSE_UNPROTECT_ONLY, perr)) {
+						pkeyMessage->m_cborKey, COSE_UNPROTECT_ONLY, perr)) {
 					goto errorReturn;
 				}
 			}
 		}
 		else {
-			pkeyMessage = _COSE_map_get_int(pCose,
+			cn_cbor * cborKey = _COSE_map_get_int(pCose,
 				fStatic ? COSE_Header_ECDH_STATIC : COSE_Header_ECDH_EPHEMERAL,
 				COSE_BOTH, perr);
+			CHECK_CONDITION(cborKey != NULL, COSE_ERR_OUT_OF_MEMORY);
+			
+			pkeyMessage = (COSE_KEY *) COSE_KEY_FromCbor(cborKey, CBOR_CONTEXT_PARAM_COMMA perr);
+			if (pkeyMessage == NULL) {
+				goto errorReturn;
+			}
 
-			CHECK_CONDITION(pkeyMessage != NULL, COSE_ERR_INVALID_PARAMETER);
 			CHECK_CONDITION(pKeyPrivate != NULL, COSE_ERR_INVALID_PARAMETER);
 
-			if (!ECDH_ComputeSecret(pCose, (cn_cbor **)&pKeyPrivate,
+			if (!ECDH_ComputeSecret(pCose, &pKeyPrivate,
 					pkeyMessage, &pbSecret, &cbSecret,
 					CBOR_CONTEXT_PARAM_COMMA perr)) {
 				goto errorReturn;
@@ -260,7 +263,7 @@
 	}
 	else {
 		CHECK_CONDITION(pKeyPrivate != NULL, COSE_ERR_INVALID_PARAMETER);
-		cn = cn_cbor_mapget_int(pKeyPrivate, COSE_Key_Type);
+		cn = cn_cbor_mapget_int(pKeyPrivate->m_cborKey, COSE_Key_Type);
 		CHECK_CONDITION((cn != NULL) && (cn->type == CN_CBOR_UINT),
 			COSE_ERR_INVALID_PARAMETER);
 		CHECK_CONDITION(
@@ -268,7 +271,7 @@
 
 		CHECK_CONDITION(cn->v.sint == 4, COSE_ERR_INVALID_PARAMETER);
 
-		cn = cn_cbor_mapget_int(pKeyPrivate, -1);
+		cn = cn_cbor_mapget_int(pKeyPrivate->m_cborKey, -1);
 		CHECK_CONDITION((cn != NULL) && (cn->type == CN_CBOR_BYTES),
 			COSE_ERR_INVALID_PARAMETER);
 		pbSecret = (byte *)cn->v.bytes;
@@ -377,7 +380,7 @@
 	switch (alg) {
 		case COSE_Algorithm_Direct:
 			CHECK_CONDITION(pRecip->m_pkey != NULL, COSE_ERR_INVALID_PARAMETER);
-			cn = cn_cbor_mapget_int(pRecip->m_pkey, -1);
+			cn = cn_cbor_mapget_int(pRecip->m_pkey->m_cborKey, -1);
 			CHECK_CONDITION((cn != NULL) && (cn->type == CN_CBOR_BYTES),
 				COSE_ERR_INVALID_PARAMETER);
 			CHECK_CONDITION(((size_t)cn->length == cbitKeyOut / 8),
@@ -512,7 +515,7 @@
 #ifdef USE_AES_KW_128
 		case COSE_Algorithm_AES_KW_128:
 			if (pbKeyX != NULL) {
-				int x = cbitKeyOut / 8;
+				int x = (int) (cbitKeyOut / 8);
 				if (!AES_KW_Decrypt((COSE_Enveloped *)pcose, pbKeyX, cbitKeyX,
 						cnBody->v.bytes, cnBody->length, pbKeyOut, &x, perr)) {
 					goto errorReturn;
@@ -522,7 +525,7 @@
 				CHECK_CONDITION(
 					pRecip->m_pkey != NULL, COSE_ERR_INVALID_PARAMETER);
 				int x = cbitKeyOut / 8;
-				cn = cn_cbor_mapget_int(pRecip->m_pkey, -1);
+				cn = cn_cbor_mapget_int(pRecip->m_pkey->m_cborKey, -1);
 				CHECK_CONDITION((cn != NULL) && (cn->type == CN_CBOR_BYTES),
 					COSE_ERR_INVALID_PARAMETER);
 
@@ -548,7 +551,7 @@
 				CHECK_CONDITION(
 					pRecip->m_pkey != NULL, COSE_ERR_INVALID_PARAMETER);
 				int x = cbitKeyOut / 8;
-				cn = cn_cbor_mapget_int(pRecip->m_pkey, -1);
+				cn = cn_cbor_mapget_int(pRecip->m_pkey->m_cborKey, -1);
 				CHECK_CONDITION((cn != NULL) && (cn->type == CN_CBOR_BYTES),
 					COSE_ERR_INVALID_PARAMETER);
 
@@ -574,7 +577,7 @@
 				CHECK_CONDITION(
 					pRecip->m_pkey != NULL, COSE_ERR_INVALID_PARAMETER);
 				int x = cbitKeyOut / 8;
-				cn = cn_cbor_mapget_int(pRecip->m_pkey, -1);
+				cn = cn_cbor_mapget_int(pRecip->m_pkey->m_cborKey, -1);
 				CHECK_CONDITION((cn != NULL) && (cn->type == CN_CBOR_BYTES),
 					COSE_ERR_INVALID_PARAMETER);
 
@@ -995,7 +998,7 @@
 #ifdef USE_AES_KW_128
 		case COSE_Algorithm_AES_KW_128:
 			if (pRecipient->m_pkey != NULL) {
-				cn_cbor *pK = cn_cbor_mapget_int(pRecipient->m_pkey, -1);
+				cn_cbor *pK = cn_cbor_mapget_int(pRecipient->m_pkey->m_cborKey, -1);
 				CHECK_CONDITION(pK != NULL, COSE_ERR_INVALID_PARAMETER);
 				if (!AES_KW_Encrypt(pRecipient, pK->v.bytes,
 						(int)pK->length * 8, pbContent, (int)cbContent, perr)) {
@@ -1014,7 +1017,7 @@
 #ifdef USE_AES_KW_192
 		case COSE_Algorithm_AES_KW_192:
 			if (pRecipient->m_pkey != NULL) {
-				cn_cbor *pK = cn_cbor_mapget_int(pRecipient->m_pkey, -1);
+				cn_cbor *pK = cn_cbor_mapget_int(pRecipient->m_pkey->m_cborKey, -1);
 				CHECK_CONDITION(pK != NULL, COSE_ERR_INVALID_PARAMETER);
 				if (!AES_KW_Encrypt(pRecipient, pK->v.bytes,
 						(int)pK->length * 8, pbContent, (int)cbContent, perr)) {
@@ -1033,7 +1036,7 @@
 #ifdef USE_AES_KW_256
 		case COSE_Algorithm_AES_KW_256:
 			if (pRecipient->m_pkey != NULL) {
-				cn_cbor *pK = cn_cbor_mapget_int(pRecipient->m_pkey, -1);
+				cn_cbor *pK = cn_cbor_mapget_int(pRecipient->m_pkey->m_cborKey, -1);
 				CHECK_CONDITION(pK != NULL, COSE_ERR_INVALID_PARAMETER);
 				if (!AES_KW_Encrypt(pRecipient, pK->v.bytes,
 						(int)pK->length * 8, pbContent, (int)cbContent, perr)) {
@@ -1203,7 +1206,7 @@
 		case COSE_Algorithm_Direct:
 			CHECK_CONDITION(
 				pRecipient->m_pkey != NULL, COSE_ERR_INVALID_PARAMETER);
-			pK = cn_cbor_mapget_int(pRecipient->m_pkey, -1);
+			pK = cn_cbor_mapget_int(pRecipient->m_pkey->m_cborKey, -1);
 			CHECK_CONDITION((pK != NULL) && (pK->type == CN_CBOR_BYTES),
 				COSE_ERR_INVALID_PARAMETER);
 			CHECK_CONDITION((size_t)pK->length == cbitKeySize / 8,
@@ -1335,6 +1338,7 @@
 #ifdef USE_CBOR_CONTEXT
 	cn_cbor_context *context = NULL;
 #endif
+	HCOSE_KEY hKey = NULL;
 
 	CHECK_CONDITION(
 		IsValidRecipientHandle(hRecipient), COSE_ERR_INVALID_HANDLE);
@@ -1404,7 +1408,10 @@
 		cbor_error);
 	cnTemp = NULL;
 
-	if (!COSE_Recipient_SetKey(hRecipient, cn_Temp, perr)) {
+	hKey = COSE_KEY_FromCbor(cn_Temp, CBOR_CONTEXT_PARAM_COMMA perr);
+	CHECK_CONDITION(hKey != NULL, COSE_ERR_OUT_OF_MEMORY);
+
+	if (!COSE_Recipient_SetKey2(hRecipient, hKey, perr)) {
 		goto errorReturn;
 	}
 	cn_Temp = NULL;
@@ -1412,7 +1419,10 @@
 	return true;
 
 errorReturn:
-	if (cn_Temp != NULL) {
+	if (hKey != NULL) {
+		COSE_KEY_Free(hKey);
+	}
+	if (cn_Temp != NULL) {		
 		CN_CBOR_FREE(cn_Temp, context);
 	}
 	if (cnTemp != NULL) {
@@ -1431,17 +1441,47 @@
 	const cn_cbor *pKey,
 	cose_errback *perr)
 {
-	COSE_RecipientInfo *p;
-
+	HCOSE_KEY hkey = NULL;
 	CHECK_CONDITION(IsValidRecipientHandle(h), COSE_ERR_INVALID_HANDLE);
 	CHECK_CONDITION(pKey != NULL, COSE_ERR_INVALID_PARAMETER);
 
+	COSE_RecipientInfo *p = (COSE_RecipientInfo *)h;
+
+#ifdef USE_CBOR_CONTEXT
+	cn_cbor_context *context = &p->m_encrypt.m_message.m_allocContext;
+#endif
+
+	hkey = COSE_KEY_FromCbor(
+		(cn_cbor *)pKey, CBOR_CONTEXT_PARAM_COMMA perr);
+	CHECK_CONDITION(hkey != NULL, COSE_ERR_OUT_OF_MEMORY);
+	if (!COSE_Recipient_SetKey2(h, hkey, perr)) {
+		goto errorReturn;
+	}
+	COSE_KEY_Free(hkey);
+	return true;
+
+errorReturn:
+	if (hkey != NULL) {
+		COSE_KEY_Free(hkey);
+	}
+	return false;
+}
+
+bool COSE_Recipient_SetKey2(HCOSE_RECIPIENT h, HCOSE_KEY hKey, cose_errback * perr)
+{
+	COSE_RecipientInfo *p;
+
+	CHECK_CONDITION(IsValidRecipientHandle(h), COSE_ERR_INVALID_HANDLE);
+
 	p = (COSE_RecipientInfo *)h;
 	if (p->m_pkey != NULL) {
-		CN_CBOR_FREE((cn_cbor *) p->m_pkey, &p->m_encrypt.m_message.m_allocContext);
+		COSE_KEY_Free((HCOSE_KEY) p->m_pkey);
 	}
 	
-	p->m_pkey = pKey;
+	p->m_pkey = (COSE_KEY *)hKey;
+	if (p->m_pkey != NULL) {
+		p->m_pkey->m_refCount += 1;
+	}
 
 	return true;
 
@@ -1459,7 +1499,7 @@
  * released.
  *
  * @param h  Handle to the recipient object
- * @param pKey pointer to COSE key structure contiaing the private key
+ * @param pKey pointer to COSE key structure containing the private key
  * @param destination 0 - set nothing, 1 - set spk_kid, 2 - set spk
  * @param perr location for return of error code
  * @return true on success
@@ -1470,6 +1510,33 @@
 	int destination,
 	cose_errback *perr)
 {
+	bool fRet = false;
+	HCOSE_KEY coseKey = NULL;
+
+	CHECK_CONDITION(IsValidRecipientHandle(h), COSE_ERR_INVALID_HANDLE);
+	CHECK_CONDITION(pKey != NULL, COSE_ERR_INVALID_PARAMETER);
+
+	#ifdef USE_CBOR_CONTEXT
+	cn_cbor_context *context = NULL;
+#endif
+	
+	coseKey = COSE_KEY_FromCbor((cn_cbor *)pKey, CBOR_CONTEXT_PARAM_COMMA perr);
+	CHECK_CONDITION(coseKey != NULL, COSE_ERR_OUT_OF_MEMORY);
+
+	fRet = COSE_Recipient_SetSenderKey2(h, coseKey, destination, perr);
+
+errorReturn:
+	if (coseKey != NULL) {
+		COSE_KEY_Free(coseKey);
+	}
+	return fRet;
+}
+
+bool COSE_Recipient_SetSenderKey2(HCOSE_RECIPIENT h,
+	HCOSE_KEY hKey,
+	int destination,
+	cose_errback *perr)
+{
 	COSE_RecipientInfo *p;
 	bool f = false;
 	cn_cbor *cn;
@@ -1481,9 +1548,10 @@
 #endif
 
 	CHECK_CONDITION(IsValidRecipientHandle(h), COSE_ERR_INVALID_HANDLE);
-	CHECK_CONDITION(pKey != NULL, COSE_ERR_INVALID_PARAMETER);
+	CHECK_CONDITION(IsValidKeyHandle(hKey), COSE_ERR_INVALID_PARAMETER);
 
 	p = (COSE_RecipientInfo *)h;
+	COSE_KEY *pKey = (COSE_KEY *)hKey;	
 
 #ifdef USE_CBOR_CONTEXT
 	context = &p->m_encrypt.m_message.m_allocContext;
@@ -1494,7 +1562,7 @@
 			break;
 
 		case 1:
-			cn = cn_cbor_mapget_int(pKey, COSE_Key_ID);
+			cn = cn_cbor_mapget_int(pKey->m_cborKey, COSE_Key_ID);
 			CHECK_CONDITION(cn != NULL, COSE_ERR_INVALID_PARAMETER);
 			cn2 = cn_cbor_clone(cn, CBOR_CONTEXT_PARAM_COMMA & cbor_err);
 			CHECK_CONDITION_CBOR(cn2 != NULL, cbor_err);
@@ -1508,7 +1576,7 @@
 		case 2:
 			cn2 = cn_cbor_map_create(CBOR_CONTEXT_PARAM_COMMA & cbor_err);
 			CHECK_CONDITION_CBOR(cn2 != NULL, cbor_err);
-			cn = cn_cbor_mapget_int(pKey, COSE_Key_Type);
+			cn = cn_cbor_mapget_int(pKey->m_cborKey, COSE_Key_Type);
 			CHECK_CONDITION(cn != NULL, COSE_ERR_INVALID_PARAMETER);
 			cn3 = cn_cbor_clone(cn, CBOR_CONTEXT_PARAM_COMMA & cbor_err);
 			CHECK_CONDITION_CBOR(cn3 != NULL, cbor_err);
@@ -1516,21 +1584,21 @@
 									 CBOR_CONTEXT_PARAM_COMMA & cbor_err),
 				cbor_err);
 			cn3 = NULL;
-			cn = cn_cbor_mapget_int(pKey, COSE_Key_EC2_Curve);
+			cn = cn_cbor_mapget_int(pKey->m_cborKey, COSE_Key_EC2_Curve);
 			cn3 = cn_cbor_clone(cn, CBOR_CONTEXT_PARAM_COMMA & cbor_err);
 			CHECK_CONDITION_CBOR(cn3 != NULL, cbor_err);
 			CHECK_CONDITION_CBOR(cn_cbor_mapput_int(cn2, COSE_Key_EC2_Curve,
 									 cn3, CBOR_CONTEXT_PARAM_COMMA & cbor_err),
 				cbor_err);
 			cn3 = NULL;
-			cn = cn_cbor_mapget_int(pKey, COSE_Key_EC2_X);
+			cn = cn_cbor_mapget_int(pKey->m_cborKey, COSE_Key_EC2_X);
 			cn3 = cn_cbor_clone(cn, CBOR_CONTEXT_PARAM_COMMA & cbor_err);
 			CHECK_CONDITION_CBOR(cn3 != NULL, cbor_err);
 			CHECK_CONDITION_CBOR(cn_cbor_mapput_int(cn2, COSE_Key_EC2_X, cn3,
 									 CBOR_CONTEXT_PARAM_COMMA & cbor_err),
 				cbor_err);
 			cn3 = NULL;
-			cn = cn_cbor_mapget_int(pKey, COSE_Key_EC2_Y);
+			cn = cn_cbor_mapget_int(pKey->m_cborKey, COSE_Key_EC2_Y);
 			cn3 = cn_cbor_clone(cn, CBOR_CONTEXT_PARAM_COMMA & cbor_err);
 			CHECK_CONDITION_CBOR(cn3 != NULL, cbor_err);
 			CHECK_CONDITION_CBOR(cn_cbor_mapput_int(cn2, COSE_Key_EC2_Y, cn3,
@@ -1548,7 +1616,11 @@
 			FAIL_CONDITION(COSE_ERR_INVALID_PARAMETER);
 	}
 
+	if (p->m_pkeyStatic != NULL) {
+		COSE_KEY_Free((HCOSE_KEY)p->m_pkeyStatic);
+	}
 	p->m_pkeyStatic = pKey;
+	pKey->m_refCount += 1;
 
 	f = true;
 errorReturn:
diff --git a/src/Sign1.c b/src/Sign1.c
index a9dd02d..fd217c2 100644
--- a/src/Sign1.c
+++ b/src/Sign1.c
@@ -13,12 +13,11 @@
 #if INCLUDE_SIGN1
 
 bool _COSE_Signer1_sign(COSE_Sign1Message *pSigner,
-	const cn_cbor *pKey,
+	COSE_KEY *pKey,
 	cose_errback *perr);
 bool _COSE_Signer1_validate(COSE_Sign1Message *pSign,
-	const cn_cbor *pKey,
+	COSE_KEY *pKey,
 	cose_errback *perr);
-void _COSE_Sign1_Release(COSE_Sign1Message *p);
 
 COSE *Sign1Root = NULL;
 
@@ -217,6 +216,32 @@
 
 bool COSE_Sign1_Sign(HCOSE_SIGN1 h, const cn_cbor *pKey, cose_errback *perr)
 {
+	HCOSE_KEY cose = NULL;
+	bool fRet = false;
+
+	CHECK_CONDITION(pKey != NULL, COSE_ERR_INVALID_PARAMETER);
+
+#ifdef USE_CBOR_CONTEXT
+	cn_cbor_context *context = NULL;
+#endif
+	
+	cose = COSE_KEY_FromCbor((cn_cbor *)pKey, CBOR_CONTEXT_PARAM_COMMA perr);
+	if (cose == NULL) {
+		goto errorReturn;
+	}
+
+	fRet = COSE_Sign1_Sign2(h, cose, perr);
+
+errorReturn:
+	if (cose != NULL) {
+		COSE_KEY_Free(cose);
+	}
+	return fRet;
+}
+
+
+bool COSE_Sign1_Sign2(HCOSE_SIGN1 h, HCOSE_KEY hKey, cose_errback *perr)
+{
 #ifdef USE_CBOR_CONTEXT
 	cn_cbor_context *context = NULL;
 #endif
@@ -228,6 +253,8 @@
 	errorReturn:
 		return false;
 	}
+	CHECK_CONDITION(IsValidKeyHandle(hKey), COSE_ERR_INVALID_HANDLE);
+	
 #ifdef USE_CBOR_CONTEXT
 	context = &pMessage->m_message.m_allocContext;
 #endif
@@ -237,7 +264,7 @@
 		goto errorReturn;
 	}
 
-	if (!_COSE_Signer1_sign(pMessage, pKey, perr)) {
+	if (!_COSE_Signer1_sign(pMessage, (COSE_KEY*) hKey, perr)) {
 		goto errorReturn;
 	}
 
@@ -261,6 +288,7 @@
 	COSE_Sign1Message *pSign;
 	const cn_cbor *cnContent;
 	const cn_cbor *cnProtected;
+	COSE_KEY *pcose = NULL;
 
 	CHECK_CONDITION(IsValidSign1Handle(hSign), COSE_ERR_INVALID_HANDLE);
 
@@ -274,11 +302,22 @@
 	CHECK_CONDITION(cnProtected != NULL && cnProtected->type == CN_CBOR_BYTES,
 		COSE_ERR_INVALID_PARAMETER);
 
-	f = _COSE_Signer1_validate(pSign, pKey, perr);
+#ifdef USE_CBOR_CONTEXT
+	cn_cbor_context *context = &pSign->m_message.m_allocContext;
+#endif
 
+	pcose = (COSE_KEY*) COSE_KEY_FromCbor((cn_cbor *)pKey, CBOR_CONTEXT_PARAM_COMMA perr);
+	CHECK_CONDITION(pKey != NULL, COSE_ERR_OUT_OF_MEMORY);
+
+	f = _COSE_Signer1_validate(pSign, pcose, perr);
+
+	COSE_KEY_Free((HCOSE_KEY)pcose);
 	return f;
 
 errorReturn:
+	if (pcose != NULL) {
+		COSE_KEY_Free((HCOSE_KEY)pcose);
+	}
 	return false;
 }
 
@@ -406,7 +445,7 @@
 }
 
 bool _COSE_Signer1_sign(COSE_Sign1Message *pSigner,
-	const cn_cbor *pKey,
+	COSE_KEY *pKey,
 	cose_errback *perr)
 {
 #ifdef USE_CBOR_CONTEXT
@@ -502,7 +541,7 @@
 }
 
 bool _COSE_Signer1_validate(COSE_Sign1Message *pSign,
-	const cn_cbor *pKey,
+	COSE_KEY *pKey,
 	cose_errback *perr)
 {
 	byte *pbToSign = NULL;
diff --git a/src/SignerInfo.c b/src/SignerInfo.c
index 1513366..2ffc110 100644
--- a/src/SignerInfo.c
+++ b/src/SignerInfo.c
@@ -34,7 +34,9 @@
 	}
 
 	_COSE_Release(&pSigner->m_message);
-	CN_CBOR_FREE(pSigner->m_pkey, &pSigner->m_message.m_allocContext);
+	if (pSigner->m_pkey != NULL) {
+		COSE_KEY_Free((HCOSE_KEY)pSigner->m_pkey);
+	}
 
 	return true;
 }
@@ -339,22 +341,51 @@
 }
 
 #if INCLUDE_SIGN
-bool COSE_Signer_SetKey(HCOSE_SIGNER h, const cn_cbor *pKey, cose_errback *perr)
+bool COSE_Signer_SetKey2(HCOSE_SIGNER h, HCOSE_KEY pKey, cose_errback *perr)
 {
 	COSE_SignerInfo *p;
 	bool fRet = false;
 
 	CHECK_CONDITION(IsValidSignerHandle(h), COSE_ERR_INVALID_HANDLE);
-	CHECK_CONDITION(pKey != NULL, COSE_ERR_INVALID_PARAMETER);
+	CHECK_CONDITION(IsValidKeyHandle(pKey), COSE_ERR_INVALID_HANDLE);
 
 	p = (COSE_SignerInfo *)h;
-	p->m_pkey = pKey;
+	if (p->m_pkey != NULL) {
+		COSE_KEY_Free((HCOSE_KEY)p->m_pkey);
+	}
+	COSE_KEY *pcose = (COSE_KEY *)pKey;
+	p->m_pkey = pcose;
+	if (pcose != NULL) {
+		pcose->m_refCount += 1;
+	}
 
 	fRet = true;
 errorReturn:
 	return fRet;
 }
 
+bool COSE_Signer_SetKey(HCOSE_SIGNER h, const cn_cbor *pKey, cose_errback *perr)
+{
+	HCOSE_KEY cose = NULL;
+	bool fRet = false;
+#ifdef USE_CBOR_CONTEXT
+	cn_cbor_context *context = NULL;
+#endif
+
+	CHECK_CONDITION(pKey != NULL, COSE_ERR_INVALID_PARAMETER);
+	cose = COSE_KEY_FromCbor((cn_cbor*) pKey, CBOR_CONTEXT_PARAM_COMMA perr);
+	
+	CHECK_CONDITION(cose != NULL, COSE_ERR_OUT_OF_MEMORY);
+
+	fRet =COSE_Signer_SetKey2(h, cose, perr);
+
+errorReturn:
+	if (cose != NULL) {
+		COSE_KEY_Free(cose);
+	}
+	return fRet;
+}
+
 /*!
  * @brief Set the application external data for authentication
  *
diff --git a/src/cose_crypto.h b/src/cose_crypto.h
index 3f34ed5..27c0ff5 100644
--- a/src/cose_crypto.h
+++ b/src/cose_crypto.h
@@ -161,35 +161,35 @@
  */
 bool ECDSA_Sign(COSE* pSigner,
 	int index,
-	const cn_cbor* pKey,
+	COSE_KEY* pKey,
 	int cbitsDigest,
 	const byte* rgbToSign,
 	size_t cbToSign,
 	cose_errback* perr);
 bool ECDSA_Verify(COSE* pSigner,
 	int index,
-	const cn_cbor* pKey,
+	COSE_KEY* pKey,
 	int cbitsDigest,
 	const byte* rgbToSign,
 	size_t cbToSign,
 	cose_errback* perr);
 
 bool ECDH_ComputeSecret(COSE* pReciient,
-	cn_cbor** ppKeyMe,
-	const cn_cbor* pKeyYou,
+	COSE_KEY **ppKeyMe,
+	COSE_KEY *pKeyYou,
 	byte** ppbSecret,
 	size_t* pcbSecret,
 	CBOR_CONTEXT_COMMA cose_errback* perr);
 
 bool EdDSA_Sign(COSE* pSigner,
 	int index,
-	const cn_cbor* pKey,
+	COSE_KEY* pKey,
 	const byte* rgbToSign,
 	size_t cbToSign,
 	cose_errback* perr);
 bool EdDSA_Verify(COSE* pSigner,
 	int index,
-	const cn_cbor* pKey,
+	COSE_KEY* pKey,
 	const byte* rgbToSign,
 	size_t cbToSign,
 	cose_errback* perr);
diff --git a/src/cose_int.h b/src/cose_int.h
index 0c6dcd2..fce2352 100644
--- a/src/cose_int.h
+++ b/src/cose_int.h
@@ -4,6 +4,9 @@
 #include <cn-cbor/cn-cbor.h>
 #include <cose/cose.h>
 #include <stdbool.h>
+#ifdef COSE_C_USE_OPENSSL
+#include <openssl/evp.h>
+#endif
 
 // These definitions are here because they aren't required for the public
 // interface, and they were quite confusing in cn-cbor.h
@@ -19,6 +22,19 @@
 #define _countof(x) (sizeof(x) / sizeof(x[0]))
 #endif
 
+typedef struct _COSE_KEY {
+	int m_refCount;
+	cn_cbor *m_cborKey;
+	int flags;
+	struct _COSE_KEY *m_nextKey;
+#ifdef USE_CBOR_CONTEXT
+	cn_cbor_context m_allocContext;
+#endif
+#ifdef COSE_C_USE_OPENSSL
+	EVP_PKEY *m_opensslKey;
+#endif
+} COSE_KEY;
+
 typedef struct _COSE {
 	COSE_INIT_FLAGS m_flags;  //  Not sure what goes here yet
 	int m_ownMsg;			  //  Do I own the pointer @ m_cbor?
@@ -59,7 +75,7 @@
 
 struct _SignerInfo {
 	COSE m_message;
-	cn_cbor *m_pkey;
+	COSE_KEY *m_pkey;
 	COSE_SignerInfo *m_signerNext;
 };
 
@@ -86,8 +102,8 @@
 struct _RecipientInfo {
 	COSE_Enveloped m_encrypt;
 	COSE_RecipientInfo *m_recipientNext;
-	const cn_cbor *m_pkey;
-	const cn_cbor *m_pkeyStatic;
+	COSE_KEY *m_pkey;
+	COSE_KEY *m_pkeyStatic;
 };
 
 typedef struct {
@@ -177,6 +193,8 @@
 bool IsValidCounterSignHandle(HCOSE_COUNTERSIGN h);
 bool IsValidMacHandle(HCOSE_MAC h);
 bool IsValidMac0Handle(HCOSE_MAC0 h);
+bool IsValidKeyHandle(HCOSE_KEY h);
+
 
 bool _COSE_Init(COSE_INIT_FLAGS flags,
 	COSE *pcose,
diff --git a/src/mbedtls.c b/src/mbedtls.c
index 4732816..9bf0e54 100644
--- a/src/mbedtls.c
+++ b/src/mbedtls.c
@@ -404,11 +404,11 @@
 	size_t *pcbDigest,
 	CBOR_CONTEXT_COMMA cose_errback *perr)
 {
-	mbedtls_md_info_t *pmd;
+	const mbedtls_md_info_t *pmd = NULL;
 	mbedtls_md_type_t mdType;
 
-	int cbSalt;
-	cn_cbor *cnSalt;
+	int cbSalt = 0;
+	cn_cbor *cnSalt = NULL;
 	unsigned int cbDigest;
 
 	if (0) {
@@ -440,7 +440,7 @@
 	}
 
 	cbSalt = 0;
-	byte *pbSalt = NULL;
+	const byte *pbSalt = NULL;
 
 	cnSalt = _COSE_map_get_int(pcose, COSE_Header_HKDF_salt, COSE_BOTH, perr);
 
@@ -469,7 +469,7 @@
 {
 	UNUSED(pcose);
 	mbedtls_md_type_t mdType;
-	mbedtls_md_info_t *pmd;
+	const mbedtls_md_info_t *pmd = NULL;
 
 	unsigned int cbDigest = 0;
 
@@ -662,7 +662,7 @@
 #define COSE_Key_EC_Y -3
 #define COSE_Key_EC_d -4
 
-bool ECKey_From(const cn_cbor *pKey,
+bool ECKey_From(COSE_KEY *pKey,
 	mbedtls_ecp_keypair *keypair,
 	cose_errback *perr)
 {
@@ -672,7 +672,7 @@
 	const cn_cbor *p;
 	mbedtls_ecp_group_id groupId = 0;
 
-	p = cn_cbor_mapget_int(pKey, COSE_Key_Type);
+	p = cn_cbor_mapget_int(pKey->m_cborKey, COSE_Key_Type);
 	CHECK_CONDITION(p != NULL, COSE_ERR_INVALID_PARAMETER);
 	if (p->type == CN_CBOR_UINT) {
 		CHECK_CONDITION(
@@ -682,7 +682,7 @@
 		FAIL_CONDITION(COSE_ERR_INVALID_PARAMETER);
 	}
 
-	p = cn_cbor_mapget_int(pKey, COSE_Key_EC_Curve);
+	p = cn_cbor_mapget_int(pKey->m_cborKey, COSE_Key_EC_Curve);
 	CHECK_CONDITION(
 		(p != NULL) && (p->type == CN_CBOR_UINT), COSE_ERR_INVALID_PARAMETER);
 
@@ -706,13 +706,13 @@
 		COSE_ERR_INVALID_PARAMETER);
 	cbGroup = (int)(keypair->grp.nbits + 7) / 8;
 
-	p = cn_cbor_mapget_int(pKey, COSE_Key_EC_X);
+	p = cn_cbor_mapget_int(pKey->m_cborKey, COSE_Key_EC_X);
 	CHECK_CONDITION(
 		(p != NULL) && (p->type == CN_CBOR_BYTES), COSE_ERR_INVALID_PARAMETER);
 	CHECK_CONDITION(p->length == cbGroup, COSE_ERR_INVALID_PARAMETER);
 	memcpy(rgbKey + 1, p->v.str, p->length);
 
-	p = cn_cbor_mapget_int(pKey, COSE_Key_EC_Y);
+	p = cn_cbor_mapget_int(pKey->m_cborKey, COSE_Key_EC_Y);
 	CHECK_CONDITION((p != NULL), COSE_ERR_INVALID_PARAMETER);
 	if (p->type == CN_CBOR_BYTES) {
 		rgbKey[0] = 0x04;
@@ -744,7 +744,7 @@
 						&keypair->grp, &keypair->Q, rgbKey, cbKey) == 0,
 		COSE_ERR_INVALID_PARAMETER);
 
-	p = cn_cbor_mapget_int(pKey, COSE_Key_EC_d);
+	p = cn_cbor_mapget_int(pKey->m_cborKey, COSE_Key_EC_d);
 	if (p != NULL) {
 		CHECK_CONDITION(p->type == CN_CBOR_BYTES, COSE_ERR_INVALID_PARAMETER);
 		CHECK_CONDITION(
@@ -759,7 +759,7 @@
 
 bool ECDSA_Sign(COSE *pSigner,
 	int index,
-	const cn_cbor *pKey,
+	COSE_KEY *pKey,
 	int cbitDigest,
 	const byte *rgbToSign,
 	size_t cbToSign,
@@ -852,7 +852,7 @@
 
 bool ECDSA_Verify(COSE *pSigner,
 	int index,
-	const cn_cbor *pKey,
+	COSE_KEY *pKey,
 	int cbitDigest,
 	const byte *rgbToSign,
 	size_t cbToSign,
@@ -1105,8 +1105,8 @@
  */
 
 bool ECDH_ComputeSecret(COSE *pRecipient,
-	cn_cbor **ppKeyPrivate,
-	const cn_cbor *pKeyPublic,
+	COSE_KEY **ppKeyPrivate,
+	COSE_KEY *pKeyPublic,
 	byte **ppbSecret,
 	size_t *pcbSecret,
 	CBOR_CONTEXT_COMMA cose_errback *perr)
@@ -1131,7 +1131,7 @@
 	mbedtls_mpi_init(&d);
 	mbedtls_ecp_keypair_init(&keypair);
 
-	p = cn_cbor_mapget_int(pKeyPublic, COSE_Key_EC_Curve);
+	p = cn_cbor_mapget_int(pKeyPublic->m_cborKey, COSE_Key_EC_Curve);
 	CHECK_CONDITION(
 		(p != NULL) && (p->type == CN_CBOR_UINT), COSE_ERR_INVALID_PARAMETER);
 
@@ -1185,7 +1185,7 @@
 			COSE_ERR_CRYPTO_FAIL);
 
 		cn_cbor_errback cbor_error;
-		int cbSize = (olen - 1) / 2;
+		int cbSize = (int) (olen - 1) / 2;
 
 		pkey = cn_cbor_map_create(CBOR_CONTEXT_PARAM_COMMA & cbor_error);
 		CHECK_CONDITION_CBOR(pkey != NULL, cbor_error);
@@ -1194,7 +1194,7 @@
 			cose_group, CBOR_CONTEXT_PARAM_COMMA & cbor_error);
 		CHECK_CONDITION_CBOR(p != NULL, cbor_error);
 		CHECK_CONDITION_CBOR(cn_cbor_mapput_int(pkey, COSE_Key_EC_Curve, p,
-								 CBOR_CONTEXT_PARAM_COMMA perr),
+								 CBOR_CONTEXT_PARAM_COMMA &cbor_error),
 			cbor_error);
 		p = NULL;
 
@@ -1232,11 +1232,16 @@
 			cbor_error);
 		p = NULL;
 
-		*ppKeyPrivate = pkey;
+		COSE_KEY *coseKey = (COSE_KEY*) COSE_KEY_FromCbor(pkey, CBOR_CONTEXT_PARAM_COMMA perr);
+		if (coseKey == NULL) {
+			goto errorReturn;
+		}
+
+		*ppKeyPrivate = coseKey;
 		pkey = NULL;
 	}
 	else {
-		p = cn_cbor_mapget_int(*ppKeyPrivate, COSE_Key_EC_d);
+		p = cn_cbor_mapget_int((*ppKeyPrivate)->m_cborKey, COSE_Key_EC_d);
 		CHECK_CONDITION(p != NULL, COSE_ERR_INVALID_PARAMETER);
 
 		CHECK_CONDITION(p->type == CN_CBOR_BYTES, COSE_ERR_INVALID_PARAMETER);
diff --git a/src/openssl.c b/src/openssl.c
index a377f9c..55cf00a 100644
--- a/src/openssl.c
+++ b/src/openssl.c
@@ -1072,16 +1072,25 @@
 #define COSE_Key_EC_Y -3
 #define COSE_Key_EC_d -4
 
-EC_KEY *ECKey_From(const cn_cbor *pKey, int *cbGroup, cose_errback *perr)
+EC_KEY *ECKey_From(COSE_KEY *pKey, int *cbGroup, cose_errback *perr)
 {
-	EC_KEY *pNewKey = EC_KEY_new();
+	EC_KEY *pNewKey = NULL;
+	if (pKey->m_opensslKey != NULL) {
+		EC_KEY *pKeyNew = EVP_PKEY_get1_EC_KEY(pKey->m_opensslKey);
+		CHECK_CONDITION(pKeyNew != NULL, COSE_ERR_INVALID_PARAMETER);
+		return pKeyNew;
+	}
+	
 	byte rgbKey[512 + 1];
 	int cbKey;
 	const cn_cbor *p;
 	int nidGroup = -1;
 	EC_POINT *pPoint = NULL;
 
-	p = cn_cbor_mapget_int(pKey, COSE_Key_EC_Curve);
+	pNewKey = EC_KEY_new();
+	CHECK_CONDITION(pNewKey != NULL, COSE_ERR_OUT_OF_MEMORY);
+	
+	p = cn_cbor_mapget_int(pKey->m_cborKey, COSE_Key_EC_Curve);
 	CHECK_CONDITION(p != NULL, COSE_ERR_INVALID_PARAMETER);
 
 	switch (p->v.sint) {
@@ -1109,13 +1118,13 @@
 	CHECK_CONDITION(
 		EC_KEY_set_group(pNewKey, ecgroup) == 1, COSE_ERR_CRYPTO_FAIL);
 
-	p = cn_cbor_mapget_int(pKey, COSE_Key_EC_X);
+	p = cn_cbor_mapget_int(pKey->m_cborKey, COSE_Key_EC_X);
 	CHECK_CONDITION(
 		(p != NULL) && (p->type == CN_CBOR_BYTES), COSE_ERR_INVALID_PARAMETER);
 	CHECK_CONDITION(p->length == *cbGroup, COSE_ERR_INVALID_PARAMETER);
 	memcpy(rgbKey + 1, p->v.str, p->length);
 
-	p = cn_cbor_mapget_int(pKey, COSE_Key_EC_Y);
+	p = cn_cbor_mapget_int(pKey->m_cborKey, COSE_Key_EC_Y);
 	CHECK_CONDITION((p != NULL), COSE_ERR_INVALID_PARAMETER);
 	if (p->type == CN_CBOR_BYTES) {
 		rgbKey[0] = POINT_CONVERSION_UNCOMPRESSED;
@@ -1142,7 +1151,7 @@
 	CHECK_CONDITION(
 		EC_KEY_set_public_key(pNewKey, pPoint) == 1, COSE_ERR_CRYPTO_FAIL);
 
-	p = cn_cbor_mapget_int(pKey, COSE_Key_EC_d);
+	p = cn_cbor_mapget_int(pKey->m_cborKey, COSE_Key_EC_d);
 	if (p != NULL) {
 		BIGNUM *pbn;
 
@@ -1152,6 +1161,11 @@
 			EC_KEY_set_private_key(pNewKey, pbn) == 1, COSE_ERR_CRYPTO_FAIL);
 	}
 
+	pKey->m_opensslKey = EVP_PKEY_new();
+	CHECK_CONDITION(pKey->m_opensslKey != NULL, COSE_ERR_OUT_OF_MEMORY);
+	
+	CHECK_CONDITION(EVP_PKEY_set1_EC_KEY(pKey->m_opensslKey, pNewKey) == 1, COSE_ERR_CRYPTO_FAIL);
+
 	return pNewKey;
 
 errorReturn:
@@ -1161,7 +1175,7 @@
 	return NULL;
 }
 
-cn_cbor *EC_FromKey(const EC_KEY *pKey, CBOR_CONTEXT_COMMA cose_errback *perr)
+COSE_KEY *EC_FromKey(const EC_KEY *pKey, CBOR_CONTEXT_COMMA cose_errback *perr)
 {
 	cn_cbor *pkey = NULL;
 	const EC_GROUP *pgroup;
@@ -1172,6 +1186,7 @@
 	byte *pbPoint = NULL;
 	size_t cbSize;
 	byte *pbOut = NULL;
+	COSE_KEY *coseKey = NULL;
 
 	pgroup = EC_KEY_get0_group(pKey);
 	CHECK_CONDITION(pgroup != NULL, COSE_ERR_INVALID_PARAMETER);
@@ -1270,6 +1285,10 @@
 		cbor_error);
 	p = NULL;
 
+	coseKey = (COSE_KEY*) COSE_KEY_FromCbor(pkey, CBOR_CONTEXT_PARAM_COMMA perr);
+	CHECK_CONDITION(coseKey != NULL, COSE_ERR_OUT_OF_MEMORY);
+	pkey = NULL;
+
 returnHere:
 	if (pbPoint != NULL) {
 		COSE_FREE(pbPoint, context);
@@ -1280,7 +1299,7 @@
 	if (p != NULL) {
 		CN_CBOR_FREE(p, context);
 	}
-	return pkey;
+	return coseKey;
 
 errorReturn:
 	CN_CBOR_FREE(pkey, context);
@@ -1305,7 +1324,7 @@
 
 bool ECDSA_Sign(COSE *pSigner,
 	int index,
-	const cn_cbor *pKey,
+	COSE_KEY *pKey,
 	int cbitDigest,
 	const byte *rgbToSign,
 	size_t cbToSign,
@@ -1393,7 +1412,7 @@
 
 bool ECDSA_Verify(COSE *pSigner,
 	int index,
-	const cn_cbor *pKey,
+	COSE_KEY *pKey,
 	int cbitDigest,
 	const byte *rgbToSign,
 	size_t cbToSign,
@@ -1475,7 +1494,7 @@
 #ifdef USE_EDDSA
 bool EdDSA_Sign(COSE *pSigner,
 	int index,
-	const cn_cbor *pKeyIn,
+	COSE_KEY *pKeyIn,
 	const byte *rgbToSign,
 	size_t cbToSign,
 	cose_errback *perr)
@@ -1491,7 +1510,7 @@
 	byte *pbSig = NULL;
 	int cbSig;
 
-	p = cn_cbor_mapget_int(pKeyIn, COSE_Key_OPK_Curve);
+	p = cn_cbor_mapget_int(pKeyIn->m_cborKey, COSE_Key_OPK_Curve);
 	if (p == NULL) {
 	errorReturn:
 		if (mdCtx != NULL) {
@@ -1526,7 +1545,7 @@
 			FAIL_CONDITION(COSE_ERR_INVALID_PARAMETER);
 	}
 
-	p = cn_cbor_mapget_int(pKeyIn, COSE_Key_EC_d);
+	p = cn_cbor_mapget_int(pKeyIn->m_cborKey, COSE_Key_EC_d);
 	CHECK_CONDITION(p != NULL, COSE_ERR_INVALID_PARAMETER);
 
 	pkey = EVP_PKEY_new_raw_private_key(type, NULL, p->v.bytes, p->length);
@@ -1577,7 +1596,7 @@
 
 bool EdDSA_Verify(COSE *pSigner,
 	int index,
-	const cn_cbor *pKey,
+	COSE_KEY *pKey,
 	const byte *rgbToSign,
 	size_t cbToSign,
 	cose_errback *perr)
@@ -1585,7 +1604,7 @@
 	cn_cbor *pSig;
 	EVP_PKEY *pkey = NULL;
 
-	cn_cbor *p = cn_cbor_mapget_int(pKey, COSE_Key_OPK_Curve);
+	cn_cbor *p = cn_cbor_mapget_int(pKey->m_cborKey, COSE_Key_OPK_Curve);
 	if (p == NULL) {
 	errorReturn:
 		if (pkey != NULL) {
@@ -1609,7 +1628,7 @@
 			FAIL_CONDITION(COSE_ERR_INVALID_PARAMETER);
 	}
 
-	p = cn_cbor_mapget_int(pKey, COSE_Key_OPK_X);
+	p = cn_cbor_mapget_int(pKey->m_cborKey, COSE_Key_OPK_X);
 	CHECK_CONDITION(p != NULL, COSE_ERR_INVALID_PARAMETER);
 
 	pkey = EVP_PKEY_new_raw_public_key(type, NULL, p->v.bytes, p->length);
@@ -1729,8 +1748,8 @@
  */
 
 bool ECDH_ComputeSecret(COSE *pRecipient,
-	cn_cbor **ppKeyPrivate,
-	const cn_cbor *pKeyPublic,
+	COSE_KEY **ppKeyPrivate,
+	COSE_KEY *pKeyPublic,
 	byte **ppbSecret,
 	size_t *pcbSecret,
 	CBOR_CONTEXT_COMMA cose_errback *perr)
diff --git a/test/mac_test.c b/test/mac_test.c
index d7cf060..efaa0d9 100644
--- a/test/mac_test.c
+++ b/test/mac_test.c
@@ -84,11 +84,13 @@
 
 		if (!SetReceivingAttributes(
 				(HCOSE)hRecip, pRecipients, Attributes_Recipient_protected)) {
+			COSE_Recipient_Free(hRecip);
 			goto failTest;
 		}
 
 		if (!COSE_Recipient_SetKey(hRecip, pkey, NULL)) {
 			fFail = true;
+			COSE_Recipient_Free(hRecip);
 			continue;
 		}
 
@@ -147,6 +149,7 @@
 			cn_cbor *countersigners =
 				cn_cbor_mapget_string(countersignList, "signers");
 			if (countersigners == NULL) {
+				COSE_Recipient_Free(hRecip);
 				goto failTest;
 			}
 			int count = countersigners->length;
@@ -154,6 +157,7 @@
 
 			if (COSE_Recipient_map_get_int(hRecip, COSE_Header_CounterSign,
 					COSE_UNPROTECT_ONLY, 0) == NULL) {
+				COSE_Recipient_Free(hRecip);
 				goto failTest;
 			}
 
diff --git a/test/sign.c b/test/sign.c
index 603b80a..eedb4e6 100644
--- a/test/sign.c
+++ b/test/sign.c
@@ -130,7 +130,7 @@
 				fFail = true;
 				continue;
 			}
-			int count = countersigners->length;
+			size_t count = countersigners->length;
 			bool forward = true;
 
 			if (COSE_Signer_map_get_int(hSigner, COSE_Header_CounterSign,
@@ -138,7 +138,7 @@
 				goto returnError;
 			}
 
-			for (int counterNo = 0; counterNo < count; counterNo++) {
+			for (size_t counterNo = 0; counterNo < count; counterNo++) {
 				bool noSignAlg = false;
 
 				h = COSE_Signer_get_countersignature(hSigner, counterNo, 0);
@@ -666,7 +666,7 @@
 			fFail = true;
 			goto exitHere;
 		}
-		int count = countersigners->length;
+		size_t count = countersigners->length;
 		bool forward = true;
 
 		if (COSE_Sign1_map_get_int(hSig, COSE_Header_CounterSign,
@@ -674,7 +674,7 @@
 			goto returnError;
 		}
 
-		for (int counterNo = 0; counterNo < count; counterNo++) {
+		for (size_t counterNo = 0; counterNo < count; counterNo++) {
 			bool noSignAlg = false;
 
 			HCOSE_COUNTERSIGN h =