Merge pull request #40 from jimsch/master

Add build dependency on the Embed TLS crypto package

We get a first cut as using the mbed TLS system.  Don't know why the coverage dropped so much will need to look at that later.  The testing does not pass so it is not automatically running the suites this is the next step.
diff --git a/.gitignore b/.gitignore
index 89b9e01..94ef967 100644
--- a/.gitignore
+++ b/.gitignore
@@ -55,9 +55,12 @@
 *.vcxproj
 *.vcxproj.filters
 *.opensdf
+*.VC.db
+*.VC.opendb
 
 # CMake and CTest directories
 project_cn-cbor-prefix
+project_embedtls-prefix
 Testing
 dist
 test/test.cbor
diff --git a/.travis.yml b/.travis.yml
index dc9ecf0..f52dba4 100644
--- a/.travis.yml
+++ b/.travis.yml
@@ -9,10 +9,13 @@
 env:
   - USE_CONTEXT=ON
   - USE_CONTEXT=OFF
+#  - USE_CONTEXT=OFF USE_EMBEDTLS=ON
 matrix:
   exclude:
     - compiler: gcc
       env: USE_CONTEXT=OFF
+#    - compiler: gcc
+#      env: USE_CONTEXT=OFF USE_EMBEDTLS=ON
 addons:
   apt:
     sources:
@@ -24,7 +27,7 @@
 script:
   - git clone git://github.com/cose-wg/Examples Examples
   - mkdir build
-  - cd build && cmake -Duse_context=$USE_CONTEXT -Dcoveralls_send=ON .. && make all test
+  - cd build && cmake -Duse_context=$USE_CONTEXT -Dcoveralls_send=ON -Duse_embedtls=$USE_EMBEDTLS .. && make all test
   - make coveralls
 
 
diff --git a/CMakeLists.txt b/CMakeLists.txt
index 863bc27..bc1146d 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -25,6 +25,7 @@
 option ( coveralls_send "Send data to coveralls site" OFF )
 option (build_docs      "Create docs using Doxygen" ${DOXYGEN_FOUND} )
 option (build_shared_libs "Build Shared Libraries" ON)
+option (use_embedtls    "Use MBedTLS for the Crypto Package" OFF)
 
 set ( dist_dir          ${CMAKE_BINARY_DIR}/dist )
 set ( prefix            ${CMAKE_INSTALL_PREFIX} )
@@ -117,6 +118,23 @@
 set_property (TARGET cn-cbor PROPERTY IMPORTED_LOCATION "${install_dir}/lib/${CMAKE_SHARED_MODULE_PREFIX}cn-cbor${CMAKE_SHARED_LIBRARY_SUFFIX}")
 add_dependencies(cn-cbor project_cn-cbor)
 
+if (use_embedtls)
+   add_definitions( -DUSE_MBED_TLS )
+   ExternalProject_Add(
+     project_embedtls
+     GIT_REPOSITORY https://github.com/ARMmbed/mbedtls
+     CMAKE_ARGS -DENABLED_PROGRAMS=OFF -DCMAKE_INSTALL_PREFIX:PATH=<INSTALL_DIR> -Dcoveralls=OFF -DUSE_SHARED_MBEDTLS_LIBRARY=${build_shared_libs} -Dfatal_warnings=OFF -DENABLE_TESTING=OFF -DLIB_INSTALL_DIR=${install_dir}/lib
+     INTALL_DIR "${dist_dir}"
+     UPDATE_DISCONNECTED 1
+   )
+
+   ExternalProject_Get_Property(project_embedtls install_dir)
+   include_directories( "${install_dir}/include" )
+   add_library( embedtls STATIC IMPORTED)
+   set_property (TARGET embedtls PROPERTY IMPORTED_LOCATION "${dist_dir}/lib/${CMAKE_SHARED_MODULE_PREFIX}mbedcrypto${CMAKE_SHARED_LIBRARY_SUFFIX}")
+   add_dependencies(embedtls project_embedtls)
+endif ()
+
 
 ## include the parts
 add_subdirectory(src)
diff --git a/dumper/CMakeLists.txt b/dumper/CMakeLists.txt
index a4ad18f..7890ec5 100644
--- a/dumper/CMakeLists.txt
+++ b/dumper/CMakeLists.txt
@@ -25,6 +25,10 @@
 
 target_link_libraries( cose_dumper PRIVATE ws2_32 )
 endif ()
+if (use_embedtls)
+    target_include_directories ( cose_dumper PUBLIC ${CMAKE_SHARED_MODLE_PREFIX}embedtls${CMAKE_SHARED_LIBRARY_SUFFIX}/include )
+    target_link_libraries ( cose_dumper PRIVATE embedtls )
+endif()
 
 target_include_directories ( cose_dumper PRIVATE ../include )
 target_include_directories ( cose_dumper PRIVATE ../src )
diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt
index 44c09fe..4311f1b 100644
--- a/src/CMakeLists.txt
+++ b/src/CMakeLists.txt
@@ -6,6 +6,7 @@
 	Cose.c
 	MacMessage.c
         MacMessage0.c
+        mbedtls.c
 	openssl.c
 	Sign.c
         Sign0.c
@@ -29,6 +30,10 @@
 
 target_link_libraries ( cose-c PRIVATE ${OPENSSL_LIBRARIES} )
 target_link_libraries ( cose-c PRIVATE cn-cbor )
+if (use_embedtls)
+    target_include_directories ( cose-c PUBLIC ${CMAKE_SHARED_MODLE_PREFIX}embedtls${CMAKE_SHARED_LIBRARY_SUFFIX}/include )
+    target_link_libraries ( cose-c PRIVATE embedtls )
+endif()
 
 install ( TARGETS cose-c
 	LIBRARY DESTINATION lib
diff --git a/src/Cose.c b/src/Cose.c
index 2de060e..dd2bb1a 100644
--- a/src/Cose.c
+++ b/src/Cose.c
@@ -406,14 +406,14 @@
 
 HCOSE_COUNTERSIGN _COSE_CounterSign_get(COSE * pMessage, int iSigner, cose_errback * perr)
 {
-	COSE_SignerInfo * pSigner = pMessage->m_counterSigners;
+	COSE_CounterSign * pSigner = pMessage->m_counterSigners;
 	int i;
 
-	for (i = 0; i < iSigner; i++, pSigner = pSigner->m_signerNext) {
+	for (i = 0; i < iSigner; i++, pSigner = pSigner->m_next) {
 		CHECK_CONDITION(pSigner != NULL, COSE_ERR_INVALID_PARAMETER);
 	}
 
-	return pSigner;
+	return (HCOSE_COUNTERSIGN) pSigner;
 
 errorReturn:
 	return false;
@@ -425,8 +425,8 @@
 	cn_cbor_errback cbor_err;
 	COSE_CounterSign * pSigner = NULL;
 	cn_cbor * pcnProtected = NULL;
-	cn_cbor * pcn;
-	cn_cbor * pcn2;
+	cn_cbor * pcn = NULL;
+	cn_cbor * pcn2 = NULL;
 
 	if (pMessage->m_counterSigners == NULL) return true;
 
@@ -439,14 +439,16 @@
 	pcnProtected = _COSE_arrayget_int(pMessage, INDEX_PROTECTED);
 	CHECK_CONDITION(pcnProtected != NULL, COSE_ERR_INTERNAL);
 
-	for (pSigner = pMessage->m_counterSigners; pSigner != NULL; pSigner = pSigner->m_signer.m_signerNext) {
+	for (pSigner = pMessage->m_counterSigners; pSigner != NULL; pSigner = pSigner->m_next) {
+		CHECK_CONDITION(pSigner->m_signer.m_signerNext == NULL, COSE_ERR_INTERNAL);
+
 		pcn = cn_cbor_data_create(pcnProtected->v.bytes, pcnProtected->v.count, CBOR_CONTEXT_PARAM_COMMA &cbor_err);
 		CHECK_CONDITION_CBOR(pcnProtected != NULL, cbor_err);
 
 		pcn2 = cn_cbor_clone(pcnBody, CBOR_CONTEXT_PARAM_COMMA &cbor_err);
 		CHECK_CONDITION_CBOR(pcnBody != NULL, cbor_err);
 
-		if (!_COSE_Signer_sign(pSigner, pcnBody, pcn2, perr)) goto errorReturn;
+		if (!_COSE_Signer_sign(&pSigner->m_signer, pcnBody, pcn2, perr)) goto errorReturn;
 		pcn = NULL;
 		pcn2 = NULL;
 
diff --git a/src/Recipient.c b/src/Recipient.c
index 618fef3..b970106 100644
--- a/src/Recipient.c
+++ b/src/Recipient.c
@@ -123,6 +123,7 @@
 	return;
 }
 
+#if defined(USE_HKDF_SHA2) || defined(USE_HKDF_AES)
 /**
 * Perform an AES-CCM Decryption operation
 *
@@ -153,6 +154,7 @@
 
 
 	if (fECDH) {
+#ifdef USE_ECDH
 		cn_cbor * pkeyMessage;
 
 		if (pKeyPrivate != NULL) {
@@ -185,6 +187,9 @@
 
 			if (!ECDH_ComputeSecret(pCose, (cn_cbor **)&pKeyPrivate, pkeyMessage, &pbSecret, &cbSecret, CBOR_CONTEXT_PARAM_COMMA perr)) goto errorReturn;
 		}
+#else
+                goto errorReturn;
+#endif
 	}
 	else {
 		CHECK_CONDITION(pKeyPrivate != NULL, COSE_ERR_INVALID_PARAMETER);
@@ -201,12 +206,20 @@
 	}
 
 	if (fHMAC) {
+#ifdef USE_HKDF_SHA2
 		if (!HKDF_Extract(pCose, pbSecret, cbSecret, cbitHash, rgbDigest, &cbDigest, CBOR_CONTEXT_PARAM_COMMA perr)) goto errorReturn;
 
 		if (!HKDF_Expand(pCose, cbitHash, rgbDigest, cbDigest, pbContext, cbContext, pbKey, cbitKey / 8, perr)) goto errorReturn;
+#else
+                goto errorReturn;
+#endif
 	}
 	else {
+#ifdef USE_HKDF_AES
 		if (!HKDF_AES_Expand(pCose, cbitHash, pbSecret, cbSecret, pbContext, cbContext, pbKey, cbitKey / 8, perr)) goto errorReturn;
+#else
+                goto errorReturn;
+#endif
 	}
 	fRet = true;
 
@@ -219,6 +232,7 @@
 	if (pbContext != NULL) COSE_FREE(pbContext, context);
 	return fRet;
 }
+#endif // defined(USE_HKDF_SHA2) || defined(USE_HKDF_AES)
 
 bool _COSE_Recipient_decrypt(COSE_RecipientInfo * pRecip, COSE_RecipientInfo * pRecipUse, int algIn, int cbitKeyOut, byte * pbKeyOut, cose_errback * perr)
 {
diff --git a/src/configure.h b/src/configure.h
index 183ca31..1be4d3f 100644
--- a/src/configure.h
+++ b/src/configure.h
@@ -1,7 +1,24 @@
 //
+//  Determine which cryptographic library we are goig to be usig
+//
+
+#if defined(USE_MBED_TLS)
+#if defined(USE_OPEN_SSL) || defined(USE_BCRYPT)
+#error Only Define One Crypto Package
+#endif
+#elif defined(USE_BCRYPT)
+#if defined(USE_OPENSSL)
+#error Only Define One Crypto Package
+#endif
+#elif !defined(USE_OPEN_SSL)
+#define USE_OPEN_SSL
+#endif
+
+//
 //  Define which AES GCM algorithms are being used
 //
 
+#if !defined(USE_MBED_TLS)
 #define USE_AES_GCM_128
 #define USE_AES_GCM_192
 #define USE_AES_GCM_256
@@ -9,6 +26,7 @@
 #if defined(USE_AES_GCM_128) || defined(USE_AES_GCM_192) || defined(USE_AES_GCM_256)
 #define USE_AES_GCM
 #endif
+#endif // !defined(USE_MBED_TLS)
 
 //
 //  Define which AES CCM algorithms are being used
@@ -41,55 +59,81 @@
 //  Define which AES CBC-MAC algorithms are to be used
 //
 
+#if !defined(USE_MBED_TLS)
+
 #define USE_AES_CBC_MAC_128_64
 #define USE_AES_CBC_MAC_128_128
 #define USE_AES_CBC_MAC_256_64
 #define USE_AES_CBC_MAC_256_128
 
+#endif // !defined(USE_MBED_TLS)
+
 //
 //  Define which ECDH algorithms are to be used
 //
 
+#if !defined(USE_MBED_TLS)
 #define USE_ECDH_ES_HKDF_256
 #define USE_ECDH_ES_HKDF_512
 #define USE_ECDH_SS_HKDF_256
 #define USE_ECDH_SS_HKDF_512
+#if defined(USE_ECDH_ES_HKDF_256) || defined(USE_ECDH_ES_HKDF_512) || defined(USE_ECDH_SS_HKDF_256) || defined(USE_ECDH_SS_HKDF_512)
+#define USE_ECDH 1
+#define USE_HKDF_SHA2 1
+#endif
+#endif // !defined(USE_MBED_TLS)
 
+#if !defined(USE_MBED_TLS)
 #define USE_ECDH_ES_A128KW
 #define USE_ECDH_ES_A192KW
 #define USE_ECDH_ES_A256KW
 #define USE_ECDH_SS_A128KW
 #define USE_ECDH_SS_A192KW
 #define USE_ECDH_SS_A256KW
+#if defined(USE_ECDH_ES_A128KW) || defined(USE_ECDH_ES_A192KW) || defined(USE_ECDH_ES_A256KW) || defined(USE_ECDH_SS_A128KW) || defined(USE_ECDH_SS_A192KW) || defined(USE_ECDH_SS_A256KW)
+#define USE_ECDH 1
+#define USE_HKDF_AES 1
+#endif
+#endif // !defined(USE_MBED_TLS)
 
 //
 //  Define which Key Wrap functions are to be used
 //
 
+#if !defined(USE_MBED_TLS)
 #define USE_AES_KW_128
 #define USE_AES_KW_192
 #define USE_AES_KW_256
+#endif // !defined(USE_MBED_TLS)
 
 //
 //  Define which of the DIRECT + KDF algorithms are to be used
 //
 
+#if !defined(USE_MBED_TLS)
 #define USE_Direct_HKDF_HMAC_SHA_256
 #define USE_Direct_HKDF_HMAC_SHA_512
 #define USE_Direct_HKDF_AES_128
 #define USE_Direct_HKDF_AES_256
+#if defined(USE_Direct_HKDF_HMAC_SHA_256) || defined(USE_Direct_HKDF_HMAC_SHA_512)
+#define USE_HKDF_SHA2 1
+#endif
+#if defined(USE_Direct_HKDF_AES_128) || defined(USE_Direct_KDF_AES_256)
+#define USE_HKDF_AES 1
+#endif
+#endif // !defined(USE_MBED_TLS)
 
 
 //
 //  Define which of the signature algorithms are to be used
 //
 
+#if !defined(USE_MBED_TLS)
 #define USE_ECDSA_SHA_256
 #define USE_ECDSA_SHA_384
 #define USE_ECDSA_SHA_512
+#endif // !defined(USE_MBED_TLS)
 
 
-#define USE_OPEN_SSL 1
-#define USE_BCRYPT 0
 
 //#define USE_COUNTER_SIGNATURES
diff --git a/src/cose_int.h b/src/cose_int.h
index 72a2bd5..8eeb483 100644
--- a/src/cose_int.h
+++ b/src/cose_int.h
@@ -5,7 +5,7 @@
 
 #ifdef USE_COUNTER_SIGNATURES
 struct _COSE_COUNTER_SIGN;
-typedef struct _COSE_COUNTER_SIGN COSE_Counter_Sign;
+typedef struct _COSE_COUNTER_SIGN COSE_CounterSign;
 #endif
 
 typedef struct _COSE {
@@ -26,7 +26,7 @@
 #endif
 	struct _COSE * m_handleList;
 #ifdef USE_COUNTER_SIGNATURES
-	COSE_Counter_Sign * m_counterSigners;
+	COSE_CounterSign * m_counterSigners;
 #endif
 } COSE;
 
@@ -90,6 +90,7 @@
 #ifdef USE_COUNTER_SIGNATURES
 typedef struct _COSE_COUNTER_SIGN {
 	COSE_SignerInfo m_signer;
+	COSE_CounterSign * m_next;
 } COSE_CounterSign;
 #endif
 
@@ -275,4 +276,4 @@
 };
 
 
-#define COSE_CounterSign_object 1000
\ No newline at end of file
+#define COSE_CounterSign_object 1000
diff --git a/src/mbedtls.c b/src/mbedtls.c
new file mode 100644
index 0000000..428ecb0
--- /dev/null
+++ b/src/mbedtls.c
@@ -0,0 +1,1237 @@
+#include "cose.h"
+#include "configure.h"
+#include "cose_int.h"
+#include "crypto.h"
+
+#include <assert.h>
+#include <memory.h>
+
+#ifdef USE_MBED_TLS
+
+#include "mbedtls/ccm.h"
+#include "mbedtls/md.h"
+#include "mbedtls/ctr_drbg.h"
+#include "mbedtls/entropy.h"
+
+bool FUseCompressed = true;
+
+#define MIN(A, B) ((A) < (B) ? (A) : (B))
+
+bool AES_CCM_Decrypt(COSE_Enveloped * pcose, int TSize, int LSize, const byte * pbKey, size_t cbKey, const byte * pbCrypto, size_t cbCrypto, const byte * pbAuthData, size_t cbAuthData, cose_errback * perr)
+{
+
+	mbedtls_ccm_context ctx;
+	int cbOut;
+	byte * rgbOut = NULL;
+	int NSize = 15 - (LSize/8);
+	byte rgbIV[15] = { 0 };
+	const cn_cbor * pIV = NULL;
+	mbedtls_cipher_id_t cipher;
+#ifdef USE_CBOR_CONTEXT
+	cn_cbor_context * context = &pcose->m_message.m_allocContext;
+#endif
+
+	mbedtls_ccm_init(&ctx);
+	
+        //  Setup the IV/Nonce and put it into the message
+	pIV = _COSE_map_get_int(&pcose->m_message, COSE_Header_IV, COSE_BOTH, NULL);
+	if ((pIV == NULL) || (pIV->type!= CN_CBOR_BYTES)) {
+		if (perr != NULL) perr->err = COSE_ERR_INVALID_PARAMETER;
+
+	errorReturn:
+		if (rgbOut != NULL) COSE_FREE(rgbOut, context);
+		mbedtls_ccm_free(&ctx);
+		return false;
+	}
+	CHECK_CONDITION(pIV->length == NSize, COSE_ERR_INVALID_PARAMETER);
+	memcpy(rgbIV, pIV->v.str, pIV->length);
+
+	//  Setup and run the mbedTLS code
+	cipher = MBEDTLS_CIPHER_ID_AES;
+	
+        CHECK_CONDITION(!mbedtls_ccm_setkey(&ctx, cipher, pbKey, cbKey*8), COSE_ERR_CRYPTO_FAIL);
+	TSize /= 8; // Comes in in bits not bytes.
+
+	cbOut = (int)  cbCrypto - TSize;
+	rgbOut = (byte *)COSE_CALLOC(cbOut, 1, context);
+	CHECK_CONDITION(rgbOut != NULL, COSE_ERR_OUT_OF_MEMORY);
+        
+		
+	CHECK_CONDITION(!mbedtls_ccm_auth_decrypt(&ctx, cbOut, rgbIV, NSize, pbAuthData, cbAuthData, pbCrypto, rgbOut, &pbCrypto[cbOut], TSize), COSE_ERR_CRYPTO_FAIL);
+        
+	mbedtls_ccm_free(&ctx);
+	pcose->pbContent = rgbOut;
+	pcose->cbContent = cbOut;
+
+	return true;
+}
+
+
+bool AES_CCM_Encrypt(COSE_Enveloped * pcose, int TSize, int LSize, const byte * pbKey, size_t cbKey, const byte * pbAuthData, size_t cbAuthData, cose_errback * perr)
+{
+	mbedtls_ccm_context ctx;
+	int cbOut;
+	byte * rgbOut = NULL;
+	int NSize = 15 - (LSize/8);
+	const cn_cbor * cbor_iv = NULL;
+	cn_cbor * cbor_iv_t = NULL;
+#ifdef USE_CBOR_CONTEXT
+	cn_cbor_context * context = &pcose->m_message.m_allocContext;
+#endif
+	cn_cbor * cnTmp = NULL;
+	mbedtls_cipher_id_t cipher;
+	byte rgbIV[16];
+	byte * pbIV = NULL;
+	cn_cbor_errback cbor_error;
+
+        mbedtls_ccm_init(&ctx);
+
+	cipher = MBEDTLS_CIPHER_ID_AES;			
+	
+	//  Setup the IV/Nonce and put it into the message
+	cbor_iv = _COSE_map_get_int(&pcose->m_message, COSE_Header_IV, COSE_BOTH, perr);
+	if (cbor_iv == NULL) {
+	
+                pbIV = COSE_CALLOC(NSize, 1, context);
+		CHECK_CONDITION(pbIV != NULL, COSE_ERR_OUT_OF_MEMORY);
+		rand_bytes(pbIV, NSize);
+		memcpy(rgbIV, pbIV, NSize);
+		cbor_iv_t = cn_cbor_data_create(pbIV, NSize, CBOR_CONTEXT_PARAM_COMMA &cbor_error);
+		CHECK_CONDITION_CBOR(cbor_iv_t != NULL, cbor_error);
+		pbIV = NULL;
+
+		if (!_COSE_map_put(&pcose->m_message, COSE_Header_IV, cbor_iv_t, COSE_UNPROTECT_ONLY, perr)) goto errorReturn;
+		cbor_iv_t = NULL;
+	}
+	else {
+		CHECK_CONDITION(cbor_iv->type == CN_CBOR_BYTES, COSE_ERR_INVALID_PARAMETER);
+		CHECK_CONDITION(cbor_iv->length == NSize, COSE_ERR_INVALID_PARAMETER);
+		memcpy(rgbIV, cbor_iv->v.str, cbor_iv->length);
+	}
+
+	//  Setup and run the mbedTLS code
+	
+	//cbKey comes in bytes not bits
+ 	CHECK_CONDITION(!mbedtls_ccm_setkey(&ctx, cipher, pbKey, cbKey*8), COSE_ERR_CRYPTO_FAIL);
+	
+	TSize /= 8; // Comes in in bits not bytes.
+
+	rgbOut = (byte *)COSE_CALLOC(cbOut+TSize, 1, context);
+	CHECK_CONDITION(rgbOut != NULL, COSE_ERR_OUT_OF_MEMORY);
+
+	CHECK_CONDITION(!mbedtls_ccm_encrypt_and_tag(&ctx, pcose->cbContent, rgbIV, NSize, pbAuthData, cbAuthData, pcose->pbContent, rgbOut, &rgbOut[pcose->cbContent], TSize), COSE_ERR_CRYPTO_FAIL);	
+
+	cnTmp = cn_cbor_data_create(rgbOut, (int)pcose->cbContent + TSize, CBOR_CONTEXT_PARAM_COMMA NULL);
+	CHECK_CONDITION(cnTmp != NULL, COSE_ERR_CBOR);
+	rgbOut = NULL;
+
+	CHECK_CONDITION(_COSE_array_replace(&pcose->m_message, cnTmp, INDEX_BODY, CBOR_CONTEXT_PARAM_COMMA NULL), COSE_ERR_CBOR);
+	cnTmp = NULL;
+
+	mbedtls_ccm_free(&ctx);
+	
+	return true;
+
+errorReturn:
+	if (pbIV != NULL) COSE_FREE(pbIV, context);
+	if (cbor_iv_t != NULL) COSE_FREE(cbor_iv_t, context);
+	if (rgbOut != NULL) COSE_FREE(rgbOut, context);
+	if (cnTmp != NULL) COSE_FREE(cnTmp, context);
+	printf("errorReturn from OPENSSL\n");
+	mbedtls_ccm_free(&ctx);
+	return false;
+}
+/*
+bool AES_GCM_Decrypt(COSE_Enveloped * pcose, const byte * pbKey, size_t cbKey, const byte * pbCrypto, size_t cbCrypto, const byte * pbAuthData, size_t cbAuthData, cose_errback * perr)
+{
+	EVP_CIPHER_CTX ctx;
+	int cbOut;
+	byte * rgbOut = NULL;
+	int outl = 0;
+	byte rgbIV[15] = { 0 };
+	const cn_cbor * pIV = NULL;
+	const EVP_CIPHER * cipher;
+#ifdef USE_CBOR_CONTEXT
+	cn_cbor_context * context = &pcose->m_message.m_allocContext;
+#endif
+	int TSize = 128 / 8;
+
+	EVP_CIPHER_CTX_init(&ctx);
+
+	//  Setup the IV/Nonce and put it into the message
+
+	pIV = _COSE_map_get_int(&pcose->m_message, COSE_Header_IV, COSE_BOTH, NULL);
+	if ((pIV == NULL) || (pIV->type != CN_CBOR_BYTES)) {
+		if (perr != NULL) perr->err = COSE_ERR_INVALID_PARAMETER;
+
+	errorReturn:
+		if (rgbOut != NULL) COSE_FREE(rgbOut, context);
+		EVP_CIPHER_CTX_cleanup(&ctx);
+		return false;
+	}
+
+	CHECK_CONDITION(pIV->length == 96/8, COSE_ERR_INVALID_PARAMETER);
+	memcpy(rgbIV, pIV->v.str, pIV->length);
+
+	//  Setup and run the OpenSSL code
+
+	switch (cbKey) {
+	case 128 / 8:
+		cipher = EVP_aes_128_gcm();
+		break;
+
+	case 192 / 8:
+		cipher = EVP_aes_192_gcm();
+		break;
+
+	case 256 / 8:
+		cipher = EVP_aes_256_gcm();
+		break;
+
+	default:
+		FAIL_CONDITION(COSE_ERR_INVALID_PARAMETER);
+		break;
+	}
+
+	//  Do the setup for OpenSSL
+
+	CHECK_CONDITION(EVP_DecryptInit_ex(&ctx, cipher, NULL, NULL, NULL), COSE_ERR_DECRYPT_FAILED);
+
+	CHECK_CONDITION(EVP_CIPHER_CTX_ctrl(&ctx, EVP_CTRL_CCM_SET_TAG, TSize, (void *)&pbCrypto[cbCrypto - TSize]), COSE_ERR_DECRYPT_FAILED);
+
+	CHECK_CONDITION(EVP_DecryptInit(&ctx, 0, pbKey, rgbIV), COSE_ERR_DECRYPT_FAILED);
+	
+	//  Pus in the AAD
+
+	CHECK_CONDITION(EVP_DecryptUpdate(&ctx, NULL, &outl, pbAuthData, (int) cbAuthData), COSE_ERR_DECRYPT_FAILED);
+
+	//  
+
+	cbOut = (int)cbCrypto - TSize;
+	rgbOut = (byte *)COSE_CALLOC(cbOut, 1, context);
+	CHECK_CONDITION(rgbOut != NULL, COSE_ERR_OUT_OF_MEMORY);
+
+	//  Process content
+
+	CHECK_CONDITION(EVP_DecryptUpdate(&ctx, rgbOut, &cbOut, pbCrypto, (int)cbCrypto - TSize), COSE_ERR_DECRYPT_FAILED);
+
+	//  Process Tag
+
+	CHECK_CONDITION(EVP_CIPHER_CTX_ctrl(&ctx, EVP_CTRL_GCM_SET_TAG, TSize, (byte *)pbCrypto + cbCrypto - TSize), COSE_ERR_DECRYPT_FAILED);
+
+	//  Check the result
+
+	CHECK_CONDITION(EVP_DecryptFinal(&ctx, rgbOut + cbOut, &cbOut), COSE_ERR_DECRYPT_FAILED);
+
+	EVP_CIPHER_CTX_cleanup(&ctx);
+
+	pcose->pbContent = rgbOut;
+	pcose->cbContent = cbOut;
+
+	return true;
+}
+
+bool AES_GCM_Encrypt(COSE_Enveloped * pcose, const byte * pbKey, size_t cbKey, const byte * pbAuthData, size_t cbAuthData, cose_errback * perr)
+{
+	EVP_CIPHER_CTX ctx;
+	int cbOut;
+	byte * rgbOut = NULL;
+	int outl = 0;
+	byte rgbIV[16] = { 0 };
+	byte * pbIV = NULL;
+	const cn_cbor * cbor_iv = NULL;
+	cn_cbor * cbor_iv_t = NULL;
+	const EVP_CIPHER * cipher;
+#ifdef USE_CBOR_CONTEXT
+	cn_cbor_context * context = &pcose->m_message.m_allocContext;
+#endif
+	cn_cbor_errback cbor_error;
+
+	// Make it first so we can clean it up
+	EVP_CIPHER_CTX_init(&ctx);
+
+	//  Setup the IV/Nonce and put it into the message
+
+	cbor_iv = _COSE_map_get_int(&pcose->m_message, COSE_Header_IV, COSE_BOTH, perr);
+	if (cbor_iv == NULL) {
+		pbIV = COSE_CALLOC(96, 1, context);
+		CHECK_CONDITION(pbIV != NULL, COSE_ERR_OUT_OF_MEMORY);
+		rand_bytes(pbIV, 96 / 8);
+		memcpy(rgbIV, pbIV, 96 / 8);
+		cbor_iv_t = cn_cbor_data_create(pbIV, 96 / 8, CBOR_CONTEXT_PARAM_COMMA &cbor_error);
+		CHECK_CONDITION_CBOR(cbor_iv_t != NULL, cbor_error);
+		pbIV = NULL;
+
+		if (!_COSE_map_put(&pcose->m_message, COSE_Header_IV, cbor_iv_t, COSE_UNPROTECT_ONLY, perr)) goto errorReturn;
+		cbor_iv_t = NULL;
+	}
+	else {
+		CHECK_CONDITION(cbor_iv->type == CN_CBOR_BYTES, COSE_ERR_INVALID_PARAMETER);
+		CHECK_CONDITION(cbor_iv->length == 96 / 8, COSE_ERR_INVALID_PARAMETER);
+		memcpy(rgbIV, cbor_iv->v.str, cbor_iv->length);
+	}
+
+
+	switch (cbKey*8) {
+	case 128:
+		cipher = EVP_aes_128_gcm();
+		break;
+
+	case 192:
+		cipher = EVP_aes_192_gcm();
+		break;
+
+	case 256:
+		cipher = EVP_aes_256_gcm();
+		break;
+
+	default:
+		FAIL_CONDITION(COSE_ERR_INVALID_PARAMETER);
+		break;
+	}
+
+	//  Setup and run the OpenSSL code
+
+	CHECK_CONDITION(EVP_EncryptInit_ex(&ctx, cipher, NULL, NULL, NULL), COSE_ERR_CRYPTO_FAIL);
+
+	CHECK_CONDITION(EVP_EncryptInit(&ctx, 0, pbKey, rgbIV), COSE_ERR_CRYPTO_FAIL);
+
+	CHECK_CONDITION(EVP_EncryptUpdate(&ctx, NULL, &outl, pbAuthData, (int) cbAuthData), COSE_ERR_CRYPTO_FAIL);
+
+	rgbOut = (byte *)COSE_CALLOC(pcose->cbContent + 128/8, 1, context);
+	CHECK_CONDITION(rgbOut != NULL, COSE_ERR_OUT_OF_MEMORY);
+
+	CHECK_CONDITION(EVP_EncryptUpdate(&ctx, rgbOut, &cbOut, pcose->pbContent, (int)pcose->cbContent), COSE_ERR_CRYPTO_FAIL);
+
+	CHECK_CONDITION(EVP_EncryptFinal_ex(&ctx, &rgbOut[cbOut], &cbOut), COSE_ERR_CRYPTO_FAIL);
+
+	CHECK_CONDITION(EVP_CIPHER_CTX_ctrl(&ctx, EVP_CTRL_GCM_GET_TAG, 128/8, &rgbOut[pcose->cbContent]), COSE_ERR_CRYPTO_FAIL);
+
+	cn_cbor * cnTmp = cn_cbor_data_create(rgbOut, (int)pcose->cbContent + 128/8, CBOR_CONTEXT_PARAM_COMMA NULL);
+	CHECK_CONDITION(cnTmp != NULL, COSE_ERR_CBOR);
+	rgbOut = NULL;
+	CHECK_CONDITION(_COSE_array_replace(&pcose->m_message, cnTmp, INDEX_BODY, CBOR_CONTEXT_PARAM_COMMA NULL), COSE_ERR_CBOR);
+
+	EVP_CIPHER_CTX_cleanup(&ctx);
+	return true;
+
+errorReturn:
+	if (pbIV != NULL) COSE_FREE(pbIV, context);
+	if (cbor_iv_t != NULL) COSE_FREE(cbor_iv_t, context);
+	if (rgbOut != NULL) COSE_FREE(rgbOut, context);
+	EVP_CIPHER_CTX_cleanup(&ctx);
+	return false;
+}
+
+
+bool AES_CBC_MAC_Create(COSE_MacMessage * pcose, int TSize, const byte * pbKey, size_t cbKey, const byte * pbAuthData, size_t cbAuthData, cose_errback * perr)
+{
+	const EVP_CIPHER * pcipher = NULL;
+	EVP_CIPHER_CTX ctx;
+	int cbOut;
+	byte rgbIV[16] = { 0 };
+	byte * rgbOut = NULL;
+	bool f = false;
+	unsigned int i;
+	cn_cbor * cn = NULL;
+#ifdef USE_CBOR_CONTEXT
+	cn_cbor_context * context = &pcose->m_message.m_allocContext;
+#endif
+
+	EVP_CIPHER_CTX_init(&ctx);
+
+	rgbOut = COSE_CALLOC(16, 1, context);
+	CHECK_CONDITION(rgbOut != NULL, COSE_ERR_OUT_OF_MEMORY);
+
+	switch (cbKey*8) {
+	case 128:
+		pcipher = EVP_aes_128_cbc();
+		break;
+
+	case 256:
+		pcipher = EVP_aes_256_cbc();
+		break;
+
+	default:
+		FAIL_CONDITION(COSE_ERR_INVALID_PARAMETER);
+	}
+
+	//  Setup and run the OpenSSL code
+
+	CHECK_CONDITION(EVP_EncryptInit_ex(&ctx, pcipher, NULL, pbKey, rgbIV), COSE_ERR_CRYPTO_FAIL);
+
+	for (i = 0; i < (unsigned int)cbAuthData / 16; i++) {
+		CHECK_CONDITION(EVP_EncryptUpdate(&ctx, rgbOut, &cbOut, pbAuthData + (i * 16), 16), COSE_ERR_CRYPTO_FAIL);
+	}
+	if (cbAuthData % 16 != 0) {
+		CHECK_CONDITION(EVP_EncryptUpdate(&ctx, rgbOut, &cbOut, pbAuthData + (i * 16), cbAuthData % 16), COSE_ERR_CRYPTO_FAIL);
+		CHECK_CONDITION(EVP_EncryptUpdate(&ctx, rgbOut, &cbOut, rgbIV, 16 - (cbAuthData % 16)), COSE_ERR_CRYPTO_FAIL);
+	}
+
+	cn = cn_cbor_data_create(rgbOut, TSize / 8, CBOR_CONTEXT_PARAM_COMMA NULL);
+	CHECK_CONDITION(cn != NULL, COSE_ERR_OUT_OF_MEMORY);
+	rgbOut = NULL;
+
+	CHECK_CONDITION(_COSE_array_replace(&pcose->m_message, cn, INDEX_MAC_TAG, CBOR_CONTEXT_PARAM_COMMA NULL), COSE_ERR_CBOR);
+	cn = NULL;
+
+	EVP_CIPHER_CTX_cleanup(&ctx);
+	return !f;
+
+errorReturn:
+	if (rgbOut != NULL) COSE_FREE(rgbOut, context);
+	if (cn != NULL) CN_CBOR_FREE(cn, context);
+	EVP_CIPHER_CTX_cleanup(&ctx);
+	return false;
+}
+
+bool AES_CBC_MAC_Validate(COSE_MacMessage * pcose, int TSize, const byte * pbKey, size_t cbKey, const byte * pbAuthData, size_t cbAuthData, cose_errback * perr)
+{
+	const EVP_CIPHER * pcipher = NULL;
+	EVP_CIPHER_CTX ctx;
+	int cbOut;
+	byte rgbIV[16] = { 0 };
+	byte rgbTag[16] = { 0 };
+	bool f = false;
+	unsigned int i;
+
+	switch (cbKey*8) {
+	case 128:
+		pcipher = EVP_aes_128_cbc();
+		break;
+
+	case 256:
+		pcipher = EVP_aes_256_cbc();
+		break;
+
+	default:
+		FAIL_CONDITION(COSE_ERR_INVALID_PARAMETER);
+	}
+
+	//  Setup and run the OpenSSL code
+
+	EVP_CIPHER_CTX_init(&ctx);
+	CHECK_CONDITION(EVP_EncryptInit_ex(&ctx, pcipher, NULL, pbKey, rgbIV), COSE_ERR_CRYPTO_FAIL);
+
+	TSize /= 8;
+
+	for (i = 0; i < (unsigned int) cbAuthData / 16; i++) {
+		CHECK_CONDITION(EVP_EncryptUpdate(&ctx, rgbTag, &cbOut, pbAuthData+(i*16), 16), COSE_ERR_CRYPTO_FAIL);
+	}
+	if (cbAuthData % 16 != 0) {
+		CHECK_CONDITION(EVP_EncryptUpdate(&ctx, rgbTag, &cbOut, pbAuthData + (i * 16), cbAuthData % 16), COSE_ERR_CRYPTO_FAIL);
+		CHECK_CONDITION(EVP_EncryptUpdate(&ctx, rgbTag, &cbOut, rgbIV, 16 - (cbAuthData % 16)), COSE_ERR_CRYPTO_FAIL);
+	}
+
+	cn_cbor * cn = _COSE_arrayget_int(&pcose->m_message, INDEX_MAC_TAG);
+	CHECK_CONDITION(cn != NULL, COSE_ERR_CBOR);
+
+	for (i = 0; i < (unsigned int)TSize; i++) f |= (cn->v.bytes[i] != rgbTag[i]);
+
+	EVP_CIPHER_CTX_cleanup(&ctx);
+	return !f;
+
+errorReturn:
+	EVP_CIPHER_CTX_cleanup(&ctx);
+	return false;
+}
+
+#if 0
+//  We are doing CBC-MAC not CMAC at this time
+bool AES_CMAC_Validate(COSE_MacMessage * pcose, int KeySize, int TagSize, const byte * pbAuthData, int cbAuthData, cose_errback * perr)
+{
+	CMAC_CTX * pctx = NULL;
+	const EVP_CIPHER * pcipher = NULL;
+	byte * rgbOut = NULL;
+	size_t cbOut;
+	bool f = false;
+	unsigned int i;
+#ifdef USE_CBOR_CONTEXT
+	cn_cbor_context * context = &pcose->m_message.m_allocContext;
+#endif
+
+	pctx = CMAC_CTX_new();
+
+
+	switch (KeySize) {
+	case 128: pcipher = EVP_aes_128_cbc(); break;
+	case 256: pcipher = EVP_aes_256_cbc(); break;
+	default: FAIL_CONDITION(COSE_ERR_INVALID_PARAMETER); break;
+	}
+
+	rgbOut = COSE_CALLOC(128/8, 1, context);
+	CHECK_CONDITION(rgbOut != NULL, COSE_ERR_OUT_OF_MEMORY);
+
+	CHECK_CONDITION(CMAC_Init(pctx, pcose->pbKey, pcose->cbKey, pcipher, NULL ) == 1, COSE_ERR_CRYPTO_FAIL);
+	CHECK_CONDITION(CMAC_Update(pctx, pbAuthData, cbAuthData), COSE_ERR_CRYPTO_FAIL);
+	CHECK_CONDITION(CMAC_Final(pctx, rgbOut, &cbOut), COSE_ERR_CRYPTO_FAIL);
+
+	cn_cbor * cn = _COSE_arrayget_int(&pcose->m_message, INDEX_MAC_TAG);
+	CHECK_CONDITION(cn != NULL, COSE_ERR_CBOR);
+
+	for (i = 0; i < (unsigned int)TagSize / 8; i++) f |= (cn->v.bytes[i] != rgbOut[i]);
+
+	COSE_FREE(rgbOut, context);
+	CMAC_CTX_cleanup(pctx);
+	CMAC_CTX_free(pctx);
+	return !f;
+
+errorReturn:
+	COSE_FREE(rgbOut, context);
+	CMAC_CTX_cleanup(pctx);
+	CMAC_CTX_free(pctx);
+	return false;
+
+}
+#endif
+
+bool HKDF_AES_Expand(COSE * pcose, size_t cbitKey, const byte * pbPRK, size_t cbPRK, const byte * pbInfo, size_t cbInfo, byte * pbOutput, size_t cbOutput, cose_errback * perr)
+{
+	const EVP_CIPHER * pcipher = NULL;
+	EVP_CIPHER_CTX ctx;
+	int cbOut;
+	byte rgbIV[16] = { 0 };
+	byte bCount = 1;
+	size_t ib;
+	byte rgbDigest[128 / 8];
+	int cbDigest = 0;
+	byte rgbOut[16];
+
+	EVP_CIPHER_CTX_init(&ctx);
+
+	switch (cbitKey) {
+	case 128:
+		pcipher = EVP_aes_128_cbc();
+		break;
+
+	case 256:
+		pcipher = EVP_aes_256_cbc();
+		break;
+
+	default:
+		FAIL_CONDITION(COSE_ERR_INVALID_PARAMETER);
+	}
+	CHECK_CONDITION(cbPRK == cbitKey / 8, COSE_ERR_INVALID_PARAMETER);
+
+	//  Setup and run the OpenSSL code
+
+
+	for (ib = 0; ib < cbOutput; ib += 16, bCount += 1) {
+		size_t ib2;
+
+		CHECK_CONDITION(EVP_EncryptInit_ex(&ctx, pcipher, NULL, pbPRK, rgbIV), COSE_ERR_CRYPTO_FAIL);
+
+		CHECK_CONDITION(EVP_EncryptUpdate(&ctx, rgbOut, &cbOut, rgbDigest, cbDigest), COSE_ERR_CRYPTO_FAIL);
+		for (ib2 = 0; ib2 < cbInfo; ib2+=16) {
+			CHECK_CONDITION(EVP_EncryptUpdate(&ctx, rgbOut, &cbOut, pbInfo+ib2, (int) MIN(16, cbInfo-ib2)), COSE_ERR_CRYPTO_FAIL);
+		}
+		CHECK_CONDITION(EVP_EncryptUpdate(&ctx, rgbOut, &cbOut, &bCount, 1), COSE_ERR_CRYPTO_FAIL);
+		if ((cbInfo + 1) % 16 != 0) {
+			CHECK_CONDITION(EVP_EncryptUpdate(&ctx, rgbOut, &cbOut, rgbIV, (int) 16-(cbInfo+1)%16), COSE_ERR_CRYPTO_FAIL);
+		}
+		memcpy(rgbDigest, rgbOut, cbOut);
+		cbDigest = cbOut;
+		memcpy(pbOutput + ib, rgbDigest, MIN(16, cbOutput - ib));
+	}
+
+	EVP_CIPHER_CTX_cleanup(&ctx);
+	return true;
+
+errorReturn:
+	EVP_CIPHER_CTX_cleanup(&ctx);
+	return false;
+}
+
+
+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;
+
+	HMAC_CTX_init(&ctx);
+
+	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);
+
+	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, size_t 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;
+
+	HMAC_CTX_init(&ctx);
+
+	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;
+	}
+
+
+	for (ib = 0; ib < cbOutput; ib += cbDigest, bCount += 1) {
+		CHECK_CONDITION(HMAC_Init_ex(&ctx, pbPRK, (int)cbPRK, pmd, NULL), COSE_ERR_CRYPTO_FAIL);
+		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;
+
+}
+
+void dump_output(byte* b, size_t s){
+	for(int i = 0; i < s; i++){
+		printf("%02x", *b);
+		b++;
+	}
+	printf("\n");
+}
+
+void diff(unsigned char* a, size_t a_l, unsigned char* b, size_t b_l){
+	size_t s;
+	s = (a_l < b_l) ? a_l : b_l;
+	unsigned char* tmp = a;
+	printf("size = %d\n",s );
+//	printf("%02x\n", *tmp);
+	int i;
+	for(i = 0; i < s; ++i){
+		printf("%02x", *tmp);
+		tmp++;
+	}
+	printf("\n");
+
+	tmp = b;
+	for(i = 0; i < s; ++i){
+		printf("%02x", *tmp);
+		tmp++;
+	}
+	printf("\n");
+
+	for(i = 0; i < s; ++i){
+
+		if(*a != *b){
+			printf("^^");
+
+		} else {
+			printf("__");
+
+		}
+
+		a++;
+		b++;
+	}
+	printf("\n");
+}
+*/
+
+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)
+{
+	byte * rgbOut = NULL;
+//	unsigned int cbOut;
+	mbedtls_md_context_t contx;
+	const char* md_name;
+	const struct mbedtls_md_info_t * info;
+
+#ifdef USE_CBOR_CONTEXT
+	cn_cbor_context * context = &pcose->m_message.m_allocContext;
+#endif
+
+	switch (HSize) {
+		case 256: md_name = "SHA256"; break;
+		case 384: md_name = "SHA384"; break;
+		case 512: md_name = "SHA512"; break;
+		default: FAIL_CONDITION(COSE_ERR_INVALID_PARAMETER); break;
+	}
+
+	if (0) {
+	errorReturn:
+		COSE_FREE(rgbOut, context);
+		mbedtls_md_free(&contx); 
+		return false;
+	}
+
+	mbedtls_md_init(&contx);
+	info = mbedtls_md_info_from_string (md_name);
+	mbedtls_md_setup( &contx, info, 1 );
+
+	rgbOut = COSE_CALLOC(mbedtls_md_get_size(info), 1, context);
+	CHECK_CONDITION(rgbOut != NULL, COSE_ERR_OUT_OF_MEMORY);
+
+	CHECK_CONDITION(!(mbedtls_md_hmac_starts (&contx, (char*)pbKey, cbKey)), COSE_ERR_CRYPTO_FAIL);
+	CHECK_CONDITION(!(mbedtls_md_hmac_update (&contx, pbAuthData, cbAuthData)), COSE_ERR_CRYPTO_FAIL);
+	CHECK_CONDITION(!(mbedtls_md_hmac_finish (&contx, rgbOut)), COSE_ERR_CRYPTO_FAIL);
+
+	CHECK_CONDITION(_COSE_array_replace(&pcose->m_message, cn_cbor_data_create(rgbOut, TSize / 8, CBOR_CONTEXT_PARAM_COMMA NULL), INDEX_MAC_TAG, CBOR_CONTEXT_PARAM_COMMA NULL), COSE_ERR_CBOR);
+
+	mbedtls_md_free(&contx); 
+	return true;
+}
+
+bool HMAC_Validate(COSE_MacMessage * pcose, int HSize, int TSize, const byte * pbKey, size_t cbKey, const byte * pbAuthData, size_t cbAuthData, cose_errback * perr)
+{
+	mbedtls_md_context_t contx;
+	const char* md_name;
+	const struct mbedtls_md_info_t * info;
+	byte * rgbOut = NULL;
+	unsigned int cbOut;
+	bool f = false;
+	unsigned int i;
+
+#ifdef USE_CBOR_CONTEXT
+	cn_cbor_context * context = &pcose->m_message.m_allocContext;
+#endif
+
+	switch (HSize) {
+		case 256: md_name = "SHA256"; break;
+		case 384: md_name = "SHA384"; break;
+		case 512: md_name = "SHA512"; break;
+		default: FAIL_CONDITION(COSE_ERR_INVALID_PARAMETER); break;
+	}
+
+	mbedtls_md_init(&contx);
+	info = mbedtls_md_info_from_string (md_name);
+	mbedtls_md_setup( &contx, info, 1 );
+	
+	cbOut = mbedtls_md_get_size(info);
+	rgbOut = COSE_CALLOC(cbOut, 1, context);
+	CHECK_CONDITION(rgbOut != NULL, COSE_ERR_OUT_OF_MEMORY);
+
+	CHECK_CONDITION(!(mbedtls_md_hmac_starts (&contx, (char*)pbKey, cbKey)), COSE_ERR_CRYPTO_FAIL);
+	CHECK_CONDITION(!(mbedtls_md_hmac_update (&contx, pbAuthData, cbAuthData)), COSE_ERR_CRYPTO_FAIL);
+	CHECK_CONDITION(!(mbedtls_md_hmac_finish (&contx, rgbOut)), COSE_ERR_CRYPTO_FAIL);
+
+	cn_cbor * cn = _COSE_arrayget_int(&pcose->m_message, INDEX_MAC_TAG);
+	CHECK_CONDITION(cn != NULL, COSE_ERR_CBOR);
+
+	if (cn->length > (int) cbOut) return false;
+	for (i = 0; i < (unsigned int) TSize/8; i++) f |= (cn->v.bytes[i] != rgbOut[i]);
+
+	mbedtls_md_free(&contx); 
+	return !f;
+
+errorReturn:
+	COSE_FREE(rgbOut, context);
+	mbedtls_md_free(&contx); 
+	return false;
+}
+/*
+
+#define COSE_Key_EC_Curve -1
+#define COSE_Key_EC_X -2
+#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 * pNewKey = EC_KEY_new();
+	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);
+	CHECK_CONDITION(p != NULL, COSE_ERR_INVALID_PARAMETER);
+
+	switch (p->v.sint) {
+	case 1: // P-256
+		nidGroup = NID_X9_62_prime256v1;
+		*cbGroup = 256 / 8;
+		break;
+
+	case 2: // P-384
+		nidGroup = NID_secp384r1;
+		*cbGroup = 384 / 8;
+		break;
+
+	case 3: // P-521
+		nidGroup = NID_secp521r1;
+		*cbGroup = (521 + 7) / 8;
+		break;
+
+	default:
+		FAIL_CONDITION(COSE_ERR_INVALID_PARAMETER);
+	}
+
+	EC_GROUP * ecgroup = EC_GROUP_new_by_curve_name(nidGroup);
+	CHECK_CONDITION(ecgroup != NULL, COSE_ERR_INVALID_PARAMETER);
+	CHECK_CONDITION(EC_KEY_set_group(pNewKey, ecgroup) == 1, COSE_ERR_CRYPTO_FAIL);
+
+	p = cn_cbor_mapget_int(pKey, 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);
+	CHECK_CONDITION((p != NULL), COSE_ERR_INVALID_PARAMETER);
+	if (p->type == CN_CBOR_BYTES) {
+		rgbKey[0] = POINT_CONVERSION_UNCOMPRESSED;
+		cbKey = (*cbGroup * 2) + 1;
+		CHECK_CONDITION(p->length == *cbGroup, COSE_ERR_INVALID_PARAMETER);
+		memcpy(rgbKey + p->length + 1, p->v.str, p->length);
+	}
+	else if (p->type == CN_CBOR_TRUE) {
+		cbKey = (*cbGroup) + 1;
+		rgbKey[0] = POINT_CONVERSION_COMPRESSED + 1;
+	}
+	else if (p->type == CN_CBOR_FALSE) {
+		cbKey = (*cbGroup) + 1;
+		rgbKey[0] = POINT_CONVERSION_COMPRESSED;
+	}
+	else FAIL_CONDITION(COSE_ERR_INVALID_PARAMETER);
+
+	pPoint = EC_POINT_new(ecgroup);
+	CHECK_CONDITION(pPoint != NULL, COSE_ERR_CRYPTO_FAIL);
+	CHECK_CONDITION(EC_POINT_oct2point(ecgroup, pPoint, rgbKey, cbKey, NULL) == 1, COSE_ERR_CRYPTO_FAIL);
+	CHECK_CONDITION(EC_KEY_set_public_key(pNewKey, pPoint) == 1, COSE_ERR_CRYPTO_FAIL);
+
+	p = cn_cbor_mapget_int(pKey, COSE_Key_EC_d);
+	if (p != NULL) {
+		BIGNUM * pbn;
+
+		pbn = BN_bin2bn(p->v.bytes, (int) p->length, NULL);
+		CHECK_CONDITION(pbn != NULL, COSE_ERR_CRYPTO_FAIL);
+		CHECK_CONDITION(EC_KEY_set_private_key(pNewKey, pbn) == 1, COSE_ERR_CRYPTO_FAIL);
+	}
+	
+	return pNewKey;
+
+errorReturn:
+	if (pNewKey != NULL) EC_KEY_free(pNewKey);
+	return NULL;
+}
+
+cn_cbor * EC_FromKey(const EC_KEY * pKey, CBOR_CONTEXT_COMMA cose_errback * perr)
+{
+	cn_cbor * pkey = NULL;
+	const EC_GROUP * pgroup;
+	int cose_group;
+	cn_cbor * p = NULL;
+	cn_cbor_errback cbor_error;
+	const EC_POINT * pPoint;
+	size_t cbSize;
+	byte * pbOut = NULL;
+
+	pgroup = EC_KEY_get0_group(pKey);
+	CHECK_CONDITION(pgroup != NULL, COSE_ERR_INVALID_PARAMETER);
+
+	switch (EC_GROUP_get_curve_name(pgroup)) {
+	case NID_X9_62_prime256v1:		cose_group = 1;		break;
+	case NID_secp384r1: cose_group = 2; break;
+	case NID_secp521r1: cose_group = 3; break;
+
+	default:
+		FAIL_CONDITION(COSE_ERR_INVALID_PARAMETER);
+	}
+
+	pkey = cn_cbor_map_create(CBOR_CONTEXT_PARAM_COMMA &cbor_error);
+	CHECK_CONDITION_CBOR(pkey != NULL, cbor_error);
+
+	p = cn_cbor_int_create(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 &cbor_error), cbor_error);
+	p = NULL;
+
+	pPoint = EC_KEY_get0_public_key(pKey);
+	CHECK_CONDITION(pPoint != NULL, COSE_ERR_INVALID_PARAMETER);
+
+	if (FUseCompressed) {
+		cbSize = EC_POINT_point2oct(pgroup, pPoint, POINT_CONVERSION_COMPRESSED, NULL, 0, NULL);
+		CHECK_CONDITION(cbSize > 0, COSE_ERR_CRYPTO_FAIL);
+		pbOut = COSE_CALLOC(cbSize, 1, context);
+		CHECK_CONDITION(pbOut != NULL, COSE_ERR_OUT_OF_MEMORY);
+		CHECK_CONDITION(EC_POINT_point2oct(pgroup, pPoint, POINT_CONVERSION_COMPRESSED, pbOut, cbSize, NULL) == cbSize, COSE_ERR_CRYPTO_FAIL);
+	}
+	else {
+		cbSize = EC_POINT_point2oct(pgroup, pPoint, POINT_CONVERSION_UNCOMPRESSED, NULL, 0, NULL);
+		CHECK_CONDITION(cbSize > 0, COSE_ERR_CRYPTO_FAIL);
+		pbOut = COSE_CALLOC(cbSize, 1, context);
+		CHECK_CONDITION(pbOut != NULL, COSE_ERR_OUT_OF_MEMORY);
+		CHECK_CONDITION(EC_POINT_point2oct(pgroup, pPoint, POINT_CONVERSION_UNCOMPRESSED, pbOut, cbSize, NULL) == cbSize, COSE_ERR_CRYPTO_FAIL);
+	}
+	p = cn_cbor_data_create(pbOut+1, (int) (cbSize / 2), CBOR_CONTEXT_PARAM_COMMA &cbor_error);
+	CHECK_CONDITION_CBOR(p != NULL, cbor_error);
+	CHECK_CONDITION_CBOR(cn_cbor_mapput_int(pkey, COSE_Key_EC_X, p, CBOR_CONTEXT_PARAM_COMMA &cbor_error), cbor_error);
+	p = NULL;
+
+	if (FUseCompressed) {
+		p = cn_cbor_bool_create(pbOut[0] & 1, CBOR_CONTEXT_PARAM_COMMA &cbor_error);
+		CHECK_CONDITION_CBOR(p != NULL, cbor_error);
+		CHECK_CONDITION_CBOR(cn_cbor_mapput_int(pkey, COSE_Key_EC_Y, p, CBOR_CONTEXT_PARAM_COMMA &cbor_error), cbor_error);
+		p = NULL;
+	}
+	else {
+		p = cn_cbor_data_create(pbOut + cbSize / 2 + 1, (int)(cbSize / 2), CBOR_CONTEXT_PARAM_COMMA &cbor_error);
+		pbOut = NULL;   // It is already part of the other one.
+		CHECK_CONDITION_CBOR(p != NULL, cbor_error);
+		CHECK_CONDITION_CBOR(cn_cbor_mapput_int(pkey, COSE_Key_EC_Y, p, CBOR_CONTEXT_PARAM_COMMA &cbor_error), cbor_error);
+		p = NULL;
+	}
+
+	p = cn_cbor_int_create(COSE_Key_Type_EC2, CBOR_CONTEXT_PARAM_COMMA &cbor_error);
+	CHECK_CONDITION_CBOR(p != NULL, cbor_error);
+	CHECK_CONDITION_CBOR(cn_cbor_mapput_int(pkey, COSE_Key_Type, p, CBOR_CONTEXT_PARAM_COMMA &cbor_error), cbor_error);
+	p = NULL;
+
+returnHere:
+	if (pbOut != NULL) COSE_FREE(pbOut, context);
+	if (p != NULL) CN_CBOR_FREE(p, context);
+	return pkey;
+
+errorReturn:
+	CN_CBOR_FREE(pkey, context);
+	pkey = NULL;
+	goto returnHere;
+}
+*/
+/*
+bool ECDSA_Sign(const cn_cbor * pKey)
+{
+	byte * digest = NULL;
+	int digestLen = 0;
+	ECDSA_SIG * sig;
+
+	EC_KEY * eckey = ECKey_From(pKey);
+
+	sig = ECDSA_do_sign(digest, digestLen, eckey);
+
+	return true;
+}
+*/
+/*
+bool ECDSA_Sign(COSE * pSigner, int index, const cn_cbor * pKey, int cbitDigest, const byte * rgbToSign, size_t cbToSign, cose_errback * perr)
+{
+	EC_KEY * eckey = NULL;
+	byte rgbDigest[EVP_MAX_MD_SIZE];
+	unsigned int cbDigest = sizeof(rgbDigest);
+	byte  * pbSig = NULL;
+	const EVP_MD * digest;
+#ifdef USE_CBOR_CONTEXT
+	cn_cbor_context * context = &pSigner->m_allocContext;
+#endif
+	cn_cbor * p = NULL;
+	ECDSA_SIG * psig = NULL;
+	cn_cbor_errback cbor_error;
+	int cbR;
+	byte rgbSig[66];
+	int cb;
+	
+	eckey = ECKey_From(pKey, &cbR, perr);
+	if (eckey == NULL) {
+	errorReturn:
+		if (pbSig != NULL) COSE_FREE(pbSig, context);
+		if (p != NULL) CN_CBOR_FREE(p, context);
+		if (eckey != NULL) EC_KEY_free(eckey);
+		return false;
+	}
+
+	switch (cbitDigest) {
+	case 256: digest = EVP_sha256(); break;
+	case 512: digest = EVP_sha512(); break;
+	case 384: digest = EVP_sha384(); break;
+	default:
+		FAIL_CONDITION(COSE_ERR_INVALID_PARAMETER);
+	}
+
+	EVP_Digest(rgbToSign, cbToSign, rgbDigest, &cbDigest, digest, NULL);
+
+	psig = ECDSA_do_sign(rgbDigest, cbDigest, eckey);
+	CHECK_CONDITION(psig != NULL, COSE_ERR_CRYPTO_FAIL);
+
+	pbSig = COSE_CALLOC(cbR, 2, context);
+	CHECK_CONDITION(pbSig != NULL, COSE_ERR_OUT_OF_MEMORY);
+
+	cb = BN_bn2bin(psig->r, rgbSig);
+	CHECK_CONDITION(cb <= cbR, COSE_ERR_INVALID_PARAMETER);
+	memcpy(pbSig + cbR - cb, rgbSig, cb);
+
+	cb = BN_bn2bin(psig->s, rgbSig);
+	CHECK_CONDITION(cb <= cbR, COSE_ERR_INVALID_PARAMETER);
+	memcpy(pbSig + 2*cbR - cb, rgbSig, cb);
+
+	p = cn_cbor_data_create(pbSig, cbR*2, CBOR_CONTEXT_PARAM_COMMA &cbor_error);
+	CHECK_CONDITION_CBOR(p != NULL, cbor_error);
+
+	CHECK_CONDITION(_COSE_array_replace(pSigner, p, index, CBOR_CONTEXT_PARAM_COMMA NULL), COSE_ERR_CBOR);
+	
+	pbSig = NULL;
+
+	if (eckey != NULL) EC_KEY_free(eckey);
+
+	return true;
+}
+
+bool ECDSA_Verify(COSE * pSigner, int index, const cn_cbor * pKey, int cbitDigest, const byte * rgbToSign, size_t cbToSign, cose_errback * perr)
+{
+	EC_KEY * eckey = NULL;
+	byte rgbDigest[EVP_MAX_MD_SIZE];
+	unsigned int cbDigest = sizeof(rgbDigest);
+	const EVP_MD * digest;
+#ifdef USE_CBOR_CONTEXT
+	cn_cbor_context * context = &pSigner->m_allocContext;
+#endif
+	cn_cbor * p = NULL;
+	ECDSA_SIG sig = { NULL, NULL };
+	int cbR;
+	cn_cbor * pSig;
+	size_t cbSignature;
+
+	eckey = ECKey_From(pKey, &cbR, perr);
+	if (eckey == NULL) {
+	errorReturn:
+		if (sig.r != NULL) BN_free(sig.r);
+		if (sig.s != NULL) BN_free(sig.s);
+		if (p != NULL) CN_CBOR_FREE(p, context);
+		if (eckey != NULL) EC_KEY_free(eckey);
+		return false;
+	}
+
+	switch (cbitDigest) {
+	case 256: digest = EVP_sha256(); break;
+	case 512: digest = EVP_sha512(); break;
+	case 384: digest = EVP_sha384(); break;
+	default:
+		FAIL_CONDITION(COSE_ERR_INVALID_PARAMETER);
+	}
+	EVP_Digest(rgbToSign, cbToSign, rgbDigest, &cbDigest, digest, NULL);
+
+	pSig = _COSE_arrayget_int(pSigner, index);
+	CHECK_CONDITION(pSig != NULL, COSE_ERR_INVALID_PARAMETER);
+	cbSignature = pSig->length;
+
+	CHECK_CONDITION(cbSignature / 2 == cbR, COSE_ERR_INVALID_PARAMETER);
+	sig.r = BN_bin2bn(pSig->v.bytes,(int) cbSignature/2, NULL);
+	sig.s = BN_bin2bn(pSig->v.bytes+cbSignature/2, (int) cbSignature/2, NULL);
+
+	CHECK_CONDITION(ECDSA_do_verify(rgbDigest, cbDigest, &sig, eckey) == 1, COSE_ERR_CRYPTO_FAIL);
+
+	BN_free(sig.r);
+	BN_free(sig.s);
+	if (eckey != NULL) EC_KEY_free(eckey);
+
+	return true;
+}
+
+bool AES_KW_Decrypt(COSE_Enveloped * pcose, const byte * pbKeyIn, size_t cbitKey, const byte * pbCipherText, size_t cbCipherText, byte * pbKeyOut, int * pcbKeyOut, cose_errback * perr)
+{
+	byte rgbOut[512 / 8];
+	AES_KEY key;
+
+	CHECK_CONDITION(AES_set_decrypt_key(pbKeyIn, (int)cbitKey, &key) == 0, COSE_ERR_CRYPTO_FAIL);
+
+	CHECK_CONDITION(AES_unwrap_key(&key, NULL, rgbOut, pbCipherText, (int) cbCipherText), COSE_ERR_CRYPTO_FAIL);
+
+	memcpy(pbKeyOut, rgbOut, cbCipherText - 8);
+	*pcbKeyOut = (int) (cbCipherText - 8);
+
+	return true;
+errorReturn:
+	return false;
+}
+
+bool AES_KW_Encrypt(COSE_RecipientInfo * pcose, const byte * pbKeyIn, int cbitKey, const byte *  pbContent, int  cbContent, cose_errback * perr)
+{
+	byte  *pbOut = NULL;
+	AES_KEY key;
+#ifdef USE_CBOR_CONTEXT
+	cn_cbor_context * context = &pcose->m_encrypt.m_message.m_allocContext;
+#endif
+	cn_cbor * cnTmp = NULL;
+
+	pbOut = COSE_CALLOC(cbContent + 8, 1, context);
+	CHECK_CONDITION(pbOut != NULL, COSE_ERR_OUT_OF_MEMORY);
+
+	CHECK_CONDITION(AES_set_encrypt_key(pbKeyIn, cbitKey, &key) == 0, COSE_ERR_CRYPTO_FAIL);
+
+	CHECK_CONDITION(AES_wrap_key(&key, NULL, pbOut, pbContent, cbContent), COSE_ERR_CRYPTO_FAIL);
+
+	cnTmp = cn_cbor_data_create(pbOut, (int)cbContent + 8, CBOR_CONTEXT_PARAM_COMMA NULL);
+	CHECK_CONDITION(cnTmp != NULL, COSE_ERR_CBOR);
+	pbOut = NULL;
+	CHECK_CONDITION(_COSE_array_replace(&pcose->m_encrypt.m_message, cnTmp, INDEX_BODY, CBOR_CONTEXT_PARAM_COMMA NULL), COSE_ERR_CBOR);
+	cnTmp = NULL;
+
+	return true;
+
+errorReturn:
+	COSE_FREE(cnTmp, context);
+	if (pbOut != NULL) COSE_FREE(pbOut, context);
+	return false;
+}
+
+*/
+/*
+//#include <stdio.h> //TODO
+void rand_bytes(byte * pb, size_t cb){
+//ctx->aes_ctx->rk e null... i callchainen längst in. prova istället:
+//kolla https://tls.mbed.org/kb/how-to/add-a-random-generator
+        //init random
+       mbedtls_ctr_drbg_context ctr_drbg;
+          char *personalization = "my_app_specific_string";
+
+        ret = mbedtls_ctr_drbg_init( &ctr_drbg, mbedtls_entropy_func, &entropy,
+                                         (const unsigned char *) personalization,
+                                                             strlen( personalization ) ); 
+        
+        if(ret != 0) {
+            //printf TODO
+        }    
+    
+        mbedtls_ctr_drbg_random(&ctx,pb, cb); 	
+
+	mbedtls_ctr_drbg_free(&ctx);	
+        printf("rand byute done\n");
+}*/
+//TODO HOW TO GENERATE GOOD RANDOM BYTES
+static const unsigned char entropy_source_pr[96] =
+   { 0xc1, 0x80, 0x81, 0xa6, 0x5d, 0x44, 0x02, 0x16,
+     0x19, 0xb3, 0xf1, 0x80, 0xb1, 0xc9, 0x20, 0x02,
+     0x6a, 0x54, 0x6f, 0x0c, 0x70, 0x81, 0x49, 0x8b,
+     0x6e, 0xa6, 0x62, 0x52, 0x6d, 0x51, 0xb1, 0xcb,
+     0x58, 0x3b, 0xfa, 0xd5, 0x37, 0x5f, 0xfb, 0xc9,
+     0xff, 0x46, 0xd2, 0x19, 0xc7, 0x22, 0x3e, 0x95,
+     0x45, 0x9d, 0x82, 0xe1, 0xe7, 0x22, 0x9f, 0x63,
+     0x31, 0x69, 0xd2, 0x6b, 0x57, 0x47, 0x4f, 0xa3,
+     0x37, 0xc9, 0x98, 0x1c, 0x0b, 0xfb, 0x91, 0x31,
+     0x4d, 0x55, 0xb9, 0xe9, 0x1c, 0x5a, 0x5e, 0xe4,
+     0x93, 0x92, 0xcf, 0xc5, 0x23, 0x12, 0xd5, 0x56,
+     0x2c, 0x4a, 0x6e, 0xff, 0xdc, 0x10, 0xd0, 0x68 };
+
+static const unsigned char nonce_pers_pr[16] =
+     { 0xd2, 0x54, 0xfc, 0xff, 0x02, 0x1e, 0x69, 0xd2,
+      0x29, 0xc9, 0xcf, 0xad, 0x85, 0xfa, 0x48, 0x6c };
+
+static size_t test_offset;
+static int ctr_drbg_self_test_entropy( void *data, unsigned char *buf, size_t len ) {
+    const unsigned char *p = data;
+    memcpy( buf, p + test_offset, len );
+    test_offset += len;
+    return( 0 );
+ }
+
+void rand_bytes(byte* pb, size_t cb){
+     
+     mbedtls_ctr_drbg_context ctx;
+    // unsigned char buf[16];
+     
+     mbedtls_ctr_drbg_init( &ctx );
+     
+     mbedtls_ctr_drbg_seed_entropy_len( &ctx, ctr_drbg_self_test_entropy, (void *) entropy_source_pr, nonce_pers_pr, 16, 32 );
+     
+     //mbedtls_ctr_drbg_set_prediction_resistance( &ctx, MBEDTLS_CTR_DRBG_PR_ON );
+    
+     mbedtls_ctr_drbg_random( &ctx, pb, cb );
+     //mbedtls_ctr_drbg_random( &ctx, buf, MBEDTLS_CTR_DRBG_BLOCKSIZE );
+     //memcmp( buf, result_pr, MBEDTLS_CTR_DRBG_BLOCKSIZE ) );
+     
+     mbedtls_ctr_drbg_free( &ctx );
+}
+//END OF TODO RANDOM BYTES
+
+/*!
+*
+* @param[in] pRecipent	Pointer to the message object
+* @param[in] ppKeyPrivate	Address of key with private portion
+* @param[in] pKeyPublic	Address of the key w/o a private portion
+* @param[in/out] ppbSecret	pointer to buffer to hold the computed secret
+* @param[in/out] pcbSecret	size of the computed secret
+* @param[in] context		cbor allocation context structure
+* @param[out] perr			location to return error information
+* @returns		success of the function
+*/
+/*
+bool ECDH_ComputeSecret(COSE * pRecipient, cn_cbor ** ppKeyPrivate, const cn_cbor * pKeyPublic, byte ** ppbSecret, size_t * pcbSecret, CBOR_CONTEXT_COMMA cose_errback *perr)
+{
+	EC_KEY * peckeyPrivate = NULL;
+	EC_KEY * peckeyPublic = NULL;
+	int cbGroup;
+	int cbsecret;
+	byte * pbsecret = NULL;
+	bool fRet = false;
+
+	peckeyPublic = ECKey_From(pKeyPublic, &cbGroup, perr);
+	if (peckeyPublic == NULL) goto errorReturn;
+
+	if (*ppKeyPrivate == NULL) {
+		{
+			cn_cbor * pCompress = _COSE_map_get_int(pRecipient, COSE_Header_UseCompressedECDH, COSE_BOTH, perr);
+			if (pCompress == NULL) FUseCompressed = false;
+			else FUseCompressed = (pCompress->type == CN_CBOR_TRUE);
+		}
+		peckeyPrivate = EC_KEY_new();
+		EC_KEY_set_group(peckeyPrivate, EC_KEY_get0_group(peckeyPublic));
+		CHECK_CONDITION(EC_KEY_generate_key(peckeyPrivate) == 1, COSE_ERR_CRYPTO_FAIL);
+		*ppKeyPrivate = EC_FromKey(peckeyPrivate, CBOR_CONTEXT_PARAM_COMMA perr);
+		if (*ppKeyPrivate == NULL) goto errorReturn;
+	}
+	else {
+		peckeyPrivate = ECKey_From(*ppKeyPrivate, &cbGroup, perr);
+		if (peckeyPrivate == NULL) goto errorReturn;
+	}
+
+	pbsecret = COSE_CALLOC(cbGroup, 1, context);
+	CHECK_CONDITION(pbsecret != NULL, COSE_ERR_OUT_OF_MEMORY);
+
+	cbsecret = ECDH_compute_key(pbsecret, cbGroup, EC_KEY_get0_public_key(peckeyPublic), peckeyPrivate, NULL);
+	CHECK_CONDITION(cbsecret > 0, COSE_ERR_CRYPTO_FAIL);
+
+	*ppbSecret = pbsecret;
+	*pcbSecret = cbsecret;
+	pbsecret = NULL;
+
+	fRet = true;
+
+errorReturn:
+	if (pbsecret != NULL) COSE_FREE(pbsecret, context);
+	if (peckeyPublic != NULL) EC_KEY_free(peckeyPublic);
+	if (peckeyPrivate != NULL) EC_KEY_free(peckeyPrivate);
+
+	return fRet;
+}
+*/
+#endif // USE_MBED_TLS
diff --git a/test/CMakeLists.txt b/test/CMakeLists.txt
index 2173f53..522f6d2 100644
--- a/test/CMakeLists.txt
+++ b/test/CMakeLists.txt
@@ -11,11 +11,15 @@
 add_executable ( cose_test test.c json.c encrypt.c sign.c context.c mac_test.c)
 
 target_link_libraries (cose_test PRIVATE cose-c )
+if (use_embedtls)
+    target_link_libraries ( cose_test PRIVATE embedtls )
+endif()
 
 ## OpenSSL
 
 target_include_directories(cose_test PRIVATE ${OPENSSL_INCLUDE_DIR})
 target_link_libraries( cose_test PRIVATE ${OPENSSL_LIBRARIES} )
+
 target_link_libraries( cose_test PRIVATE cn-cbor )
 if ( MSVC )
     target_link_libraries( cose_test PRIVATE ws2_32 )
diff --git a/test/encrypt.c b/test/encrypt.c
index 541fdec..24141d5 100644
--- a/test/encrypt.c
+++ b/test/encrypt.c
@@ -213,6 +213,15 @@
 
 	if (!SetSendingAttributes((HCOSE)hEncObj, pEnveloped, Attributes_Enveloped_protected)) goto returnError;
 
+#if 0
+	const cn_cbor * pCounterSign = cn_cbor_mapget_string(pEnveloped, "countersign");
+	if (pCounterSign != NULL) {
+		HCOSE_COUNTERSIGN hCSign = BuildCounterSign(pCounterSign);
+		if (hCSign == NULL) goto returnError;
+		if (!COSE_Enveloped_AddCounterSigner(hEncObj, hCSign, NULL)) goto returnError;
+	}
+#endif
+
 	const cn_cbor * pAlg = COSE_Enveloped_map_get_int(hEncObj, 1, COSE_BOTH, NULL);
 	if (pAlg == NULL) goto returnError;
 
diff --git a/test/mac_test.c b/test/mac_test.c
index 455a395..eb288af 100644
--- a/test/mac_test.c
+++ b/test/mac_test.c
@@ -130,8 +130,6 @@
 
 	if (!SetSendingAttributes((HCOSE)hMacObj, pMac, Attributes_MAC_protected)) goto returnError;
 
-	const cn_cbor * pAlg = COSE_Mac_map_get_int(hMacObj, 1, COSE_BOTH, NULL);
-
 	const cn_cbor * pRecipients = cn_cbor_mapget_string(pMac, "recipients");
 	if ((pRecipients == NULL) || (pRecipients->type != CN_CBOR_ARRAY)) goto returnError;
 
@@ -347,8 +345,6 @@
 
 	if (!SetSendingAttributes((HCOSE)hMacObj, pMac, Attributes_MAC0_protected)) goto returnError;
 
-	const cn_cbor * pAlg = COSE_Mac0_map_get_int(hMacObj, 1, COSE_BOTH, NULL);
-
 	const cn_cbor * pRecipients = cn_cbor_mapget_string(pMac, "recipients");
 	if ((pRecipients == NULL) || (pRecipients->type != CN_CBOR_ARRAY)) goto returnError;
 
diff --git a/test/sign.c b/test/sign.c
index 6bb1e6b..1ed188d 100644
--- a/test/sign.c
+++ b/test/sign.c
@@ -124,8 +124,6 @@
 
 	if (!SetSendingAttributes((HCOSE)hSignObj, pSign, Attributes_Sign_protected)) goto returnError;
 
-	const cn_cbor * pAlg = COSE_Sign_map_get_int(hSignObj, 1, COSE_BOTH, NULL);
-
 	const cn_cbor * pSigners = cn_cbor_mapget_string(pSign, "signers");
 	if ((pSigners == NULL) || (pSigners->type != CN_CBOR_ARRAY)) goto returnError;
 
@@ -326,8 +324,6 @@
 
 	if (!SetSendingAttributes((HCOSE)hSignObj, pSign, Attributes_Sign0_protected)) goto returnError;
 
-	const cn_cbor * pAlg = COSE_Sign0_map_get_int(hSignObj, 1, COSE_BOTH, NULL);
-
 	cn_cbor * pkey = BuildKey(cn_cbor_mapget_string(pSign, "key"), false);
 	if (pkey == NULL) goto returnError;