Checkpoint commit

Moved files from a different project to here
Got more things working.
diff --git a/.gitignore b/.gitignore
index bbf313b..6415927 100644
--- a/.gitignore
+++ b/.gitignore
@@ -30,3 +30,7 @@
 
 # Debug files
 *.dSYM/
+
+*~
+Debug
+Release
diff --git a/src/Cose.c b/src/Cose.c
new file mode 100644
index 0000000..9b671e1
--- /dev/null
+++ b/src/Cose.c
@@ -0,0 +1,152 @@
+#include <stdlib.h>
+#include <memory.h>
+
+#include "cose.h"
+#include "cose_int.h"
+#include "configure.h"
+#include "crypto.h"
+
+bool IsValidCOSEHandle(HCOSE h)
+{
+	COSE_Encrypt * p = (COSE_Encrypt *)h;
+	if (p == NULL) return false;
+	return true;
+}
+
+
+bool _COSE_Init(COSE* pobj, CBOR_CONTEXT_COMMA cose_errback * perror)
+{
+	cn_cbor_errback errState = { 0 };
+
+#ifdef USE_CBOR_CONTEXT
+	if (context != NULL) pobj->m_allocContext = *context;
+#endif
+
+	pobj->m_protectedMap = cn_cbor_map_create(CBOR_CONTEXT_PARAM_COMMA &errState);
+	if (pobj->m_protectedMap == NULL) {
+	error_setup:
+		_COSE_Release( pobj);
+		if (perror != NULL) perror->err = COSE_ERR_OUT_OF_MEMORY;
+		return false;
+	}
+
+	pobj->m_unprotectMap = cn_cbor_map_create(CBOR_CONTEXT_PARAM_COMMA &errState);
+	if (pobj->m_unprotectMap == NULL) goto error_setup;
+	pobj->m_ownUnprotectedMap = true;
+
+	pobj->m_cbor = cn_cbor_map_create(CBOR_CONTEXT_PARAM_COMMA &errState);
+	if (pobj->m_cbor == NULL) goto error_setup;
+	pobj->m_ownMsg = true;
+
+	return true;
+}
+
+bool _COSE_Init_From_Object(COSE* pobj, cn_cbor * pcbor, CBOR_CONTEXT_COMMA cose_errback * perror)
+{
+	const cn_cbor * pmap = NULL;
+	cn_cbor_errback errState = { 0 };
+
+#ifdef USE_CBOR_CONTEXT
+	if (context != NULL) pobj->m_allocContext = *context;
+#endif
+
+	pmap = cn_cbor_mapget_int(pcbor, COSE_Header_Protected);
+	if (pmap != NULL) {
+		if (pmap->type != CN_CBOR_BYTES) {
+			if (perror != NULL) perror->err = COSE_ERR_INVALID_PARAMETER;
+		setup_error:
+			_COSE_Release(pobj);
+			return false;
+		}
+		pobj->m_protectedMap = (cn_cbor *) cn_cbor_decode((const byte *) pmap->v.str, pmap->length, context, &errState);
+		if (pobj->m_protectedMap == NULL) {
+			if (perror != NULL) perror->err = COSE_ERR_INVALID_PARAMETER; // M00BUG - get error state from errState
+			goto setup_error;
+		}
+	}
+
+	pobj->m_unprotectMap = (cn_cbor *) cn_cbor_mapget_int(pcbor, COSE_Header_Unprotected);
+	pobj->m_ownUnprotectedMap = false;
+
+	pobj->m_cbor = pcbor;
+	pobj->m_ownMsg = true;
+
+	return true;
+}
+
+void _COSE_Release(COSE * pobj)
+{
+	cn_cbor_context * context = &pobj->m_allocContext;
+
+	if (pobj->m_protectedMap != NULL) CN_CBOR_FREE(pobj->m_protectedMap, context);
+	if (pobj->m_ownUnprotectedMap && (pobj->m_unprotectMap != NULL)) CN_CBOR_FREE(pobj->m_unprotectMap, context);
+	if (pobj->m_ownMsg && (pobj->m_cbor != NULL)) CN_CBOR_FREE(pobj->m_cbor, context);
+}
+
+cn_cbor * COSE_get_cbor(HCOSE h)
+{
+	COSE * msg = (COSE *)h;
+	if (!IsValidCOSEHandle(h)) return NULL;
+
+	return msg->m_cbor;
+}
+
+const cn_cbor * _COSE_map_get_int(COSE * pcose, int key, int flags, cose_errback * perror)
+{
+	const cn_cbor * p = NULL;
+
+	if (perror != NULL) perror->err = COSE_ERR_NONE;
+
+	if ((pcose->m_protectedMap != NULL) && ((flags & COSE_PROTECT_ONLY) != 0)) {
+		p = cn_cbor_mapget_int(pcose->m_protectedMap, key);
+		if (p != NULL) return p;
+	}
+
+	if ((pcose->m_unprotectMap != NULL) && ((flags & COSE_UNPROTECT_ONLY) != 0)) {
+		p = cn_cbor_mapget_int(pcose->m_unprotectMap, key);
+	}
+
+	return p;
+}
+
+const cn_cbor * _COSE_map_get_str(COSE * pcose, const char * key, int flags, cose_errback * perror)
+{
+	const cn_cbor * p = NULL;
+
+	if (perror != NULL) perror->err = COSE_ERR_NONE;
+
+	if ((pcose->m_protectedMap != NULL) && ((flags & COSE_PROTECT_ONLY) != 0)) {
+		p = cn_cbor_mapget_string(pcose->m_protectedMap, key);
+		if (p != NULL) return p;
+	}
+
+	if ((pcose->m_unprotectMap != NULL) && ((flags & COSE_UNPROTECT_ONLY) != 0)) {
+		p = cn_cbor_mapget_string(pcose->m_unprotectMap, key);
+	}
+
+	return p;
+}
+
+bool _COSE_map_put(COSE * pCose, int key, cn_cbor * value, int flags, cose_errback * perror)
+{
+	cn_cbor_context * context = &pCose->m_allocContext;
+	cn_cbor_errback error;
+	bool f;
+
+	if ((flags & COSE_BOTH) == COSE_BOTH) {
+		if (perror != NULL) perror->err = COSE_ERR_INVALID_PARAMETER;
+		return false;
+	}
+
+	if (perror != NULL) perror->err = COSE_ERR_NONE;
+	if (flags & COSE_PROTECT_ONLY) {
+		f = cn_cbor_mapput_int(pCose->m_protectedMap, key, value, CBOR_CONTEXT_PARAM_COMMA &error);
+	}
+	else {
+		f = cn_cbor_mapput_int(pCose->m_unprotectMap, key, value, CBOR_CONTEXT_PARAM_COMMA &error);
+	}
+	if (!f && perror != NULL) {
+		perror->err = error.err; // M00BUG
+	}
+	return f;
+}
diff --git a/src/Encrypt.c b/src/Encrypt.c
new file mode 100644
index 0000000..9f98d2c
--- /dev/null
+++ b/src/Encrypt.c
@@ -0,0 +1,494 @@
+#include <stdlib.h>
+#include <memory.h>
+#include <stdio.h>
+
+#include "cose.h"
+#include "cose_int.h"
+#include "configure.h"
+#include "crypto.h"
+
+byte RgbDontUse[8 * 1024];   //  Remove this array when we can compute the size of a cbor serialization without this hack.
+
+
+bool IsValidEncryptHandle(HCOSE_ENCRYPT h)
+{
+	COSE_Encrypt * p = (COSE_Encrypt *)h;
+	if (p == NULL) return false;
+	return true;
+}
+
+
+size_t COSE_Encode(HCOSE msg, byte * rgb, int ib, size_t cb)
+{
+	if (rgb == NULL) return cbor_encoder_write(RgbDontUse, 0, sizeof(RgbDontUse), ((COSE *)msg)->m_cbor) + ib;
+	return cbor_encoder_write(rgb, ib, cb, ((COSE*)msg)->m_cbor);
+}
+
+HCOSE_ENCRYPT COSE_Encrypt_Init(CBOR_CONTEXT_COMMA cose_errback * perror)
+{
+	COSE_Encrypt * pobj = (COSE_Encrypt *)COSE_CALLOC(1, sizeof(COSE_Encrypt), context);
+	if (pobj == NULL) {
+		if (perror != NULL) perror->err = COSE_ERR_OUT_OF_MEMORY;
+		return NULL;
+	}
+
+	if (!_COSE_Init(&pobj->m_message, CBOR_CONTEXT_PARAM_COMMA perror)) {
+	error_setup:
+		COSE_Encrypt_Free((HCOSE_ENCRYPT)pobj);
+		return NULL;
+	}
+
+	if (!cn_cbor_mapput_int(pobj->m_message.m_cbor, COSE_Header_Type, cn_cbor_int_create(1, CBOR_CONTEXT_PARAM_COMMA NULL), CBOR_CONTEXT_PARAM_COMMA NULL)) {
+		if (perror != NULL) perror->err = COSE_ERR_OUT_OF_MEMORY;
+		goto error_setup;
+	}
+
+	return (HCOSE_ENCRYPT) pobj;
+}
+
+HCOSE_ENCRYPT _COSE_Encrypt_Init_From_Object(cn_cbor * cbor, COSE_Encrypt * pIn, CBOR_CONTEXT_COMMA cose_errback * errp)
+{
+	COSE_Encrypt * pobj = pIn;
+	cn_cbor * pRecipients = NULL;
+
+	if (pobj == NULL) pobj = (COSE_Encrypt *)COSE_CALLOC(1, sizeof(COSE_Encrypt), context);
+	if (pobj == NULL) {
+		if (errp != NULL) errp->err = COSE_ERR_OUT_OF_MEMORY;
+		return NULL;
+	}
+
+	if (!_COSE_Init_From_Object(&pobj->m_message, cbor, CBOR_CONTEXT_PARAM_COMMA errp)) {
+		return NULL;
+	}
+
+	pRecipients = (cn_cbor *) cn_cbor_mapget_int(cbor, COSE_Header_Recipients);
+	while (pRecipients != NULL) {
+		COSE_RecipientInfo * pInfo = _COSE_Recipient_Init_From_Object(pRecipients, CBOR_CONTEXT_PARAM_COMMA errp);
+		if (pInfo == NULL) {
+			if (pIn == NULL) COSE_Encrypt_Free((HCOSE_ENCRYPT) pobj);
+			return NULL;
+		}
+
+		pInfo->m_recipientNext = pobj->m_recipientFirst;
+		pobj->m_recipientFirst = pInfo;
+		pRecipients = pRecipients->next;
+	}
+
+	return(HCOSE_ENCRYPT) pobj;
+}
+
+bool COSE_Encrypt_Free(HCOSE_ENCRYPT h)
+{
+#ifdef USE_CBOR_CONTEXT
+	cn_cbor_context context;
+#endif
+
+	if (!IsValidEncryptHandle(h)) return false;
+
+#ifdef USE_CBOR_CONTEXT
+	context = ((COSE_Encrypt *)h)->m_message.m_allocContext;
+#endif
+
+	_COSE_Encrypt_Release((COSE_Encrypt *)h);
+
+	COSE_FREE((COSE_Encrypt *)h, &context);
+
+	return true;
+}
+
+void _COSE_Encrypt_Release(COSE_Encrypt * p)
+{
+	if (p->pbContent != NULL) COSE_FREE(p->pbContent, &p->m_message.m_allocContext);
+	//	if (p->pbIV != NULL) COSE_FREE(p->pbIV, &p->m_message.m_allocContext);
+	if (p->pbKey != NULL) COSE_FREE(p ->pbKey, &p->m_message.m_allocContext);
+
+	_COSE_Release(&p->m_message);
+}
+
+HCOSE_RECIPIENT COSE_Encrypt_add_shared_secret(HCOSE_ENCRYPT hcose, COSE_Algorithms alg, byte * rgbKey, int cbKey, byte * rgbKid, int cbKid, cose_errback * perror)
+{
+#ifdef USE_CBOR_CONTEXT
+	cn_cbor_context * context;
+#endif // USE_CBOR_CONTEXT
+	COSE_RecipientInfo * pobj;
+	COSE_Encrypt * pcose = (COSE_Encrypt *)hcose;
+
+	if (!IsValidEncryptHandle(hcose) || (rgbKey == NULL)) {
+		if (perror != NULL) perror->err = COSE_ERR_INVALID_PARAMETER;
+		return NULL;
+	}
+
+	switch (alg) {
+	case COSE_Algorithm_Direct:
+		break;
+
+	default:
+		if (perror != NULL) perror->err = COSE_ERR_INVALID_PARAMETER;
+		return NULL;
+	}
+
+
+#ifdef USE_CBOR_CONTEXT
+	context = &pcose->m_message.m_allocContext;
+#endif // USE_CBOR_CONTEXT
+
+	pobj = (COSE_RecipientInfo *) COSE_CALLOC(1, sizeof(COSE_RecipientInfo) , context);
+	if (pobj == NULL) {
+		oom_error:
+		if (perror != NULL) perror->err = COSE_ERR_OUT_OF_MEMORY;
+	error:
+		// M00BUG COSE_Recipient_Free(pobj);
+		return NULL;
+	}
+
+	if (!_COSE_Init(&pobj->m_encrypt.m_message, CBOR_CONTEXT_PARAM_COMMA perror)) {
+		goto error;
+	}
+
+	if (!cn_cbor_mapput_int(pobj->m_encrypt.m_message.m_unprotectMap, COSE_Header_Algorithm, cn_cbor_int_create(alg, CBOR_CONTEXT_PARAM_COMMA NULL), CBOR_CONTEXT_PARAM_COMMA NULL)) goto error;
+
+	if (cbKid > 0) {
+		byte * pb = (byte *)COSE_CALLOC(cbKid, 1, context);
+		if (pb == NULL) goto oom_error;
+		memcpy(pb, rgbKid, cbKid);
+		if (!cn_cbor_mapput_int(pobj->m_encrypt.m_message.m_unprotectMap, COSE_Header_KID, cn_cbor_data_create(pb, cbKid, CBOR_CONTEXT_PARAM_COMMA NULL), CBOR_CONTEXT_PARAM_COMMA NULL)) {
+			COSE_FREE(pb, context);
+			goto oom_error; // M00BUG - get error from CBOR
+		}
+	}
+
+
+	pobj->m_encrypt.pbKey = (byte *) COSE_CALLOC(cbKey, 1, context);
+	if (pobj->m_encrypt.pbKey == NULL) goto error;
+	memcpy(pobj->m_encrypt.pbKey, rgbKey, cbKey);
+	pobj->m_encrypt.cbKey = cbKey;
+
+	pobj->m_recipientNext = pcose->m_recipientFirst;
+	pcose->m_recipientFirst = pobj;
+
+	cn_cbor * pRecipients = (cn_cbor *) cn_cbor_mapget_int(pcose->m_message.m_cbor, COSE_Header_Recipients);
+	if (pRecipients == NULL) {
+		pRecipients = cn_cbor_array_create(CBOR_CONTEXT_PARAM_COMMA NULL);
+		if (pRecipients == NULL) goto error;
+		if (!cn_cbor_mapput_int(pcose->m_message.m_cbor, COSE_Header_Recipients, pRecipients, CBOR_CONTEXT_PARAM_COMMA NULL)) {
+			cn_cbor_free(pRecipients, context);
+			goto error;
+		}
+	}
+
+	cn_cbor_array_append(pRecipients, pobj->m_encrypt.m_message.m_cbor, NULL);
+
+	pobj->m_encrypt.m_message.m_flags |= 1;
+	return (HCOSE_RECIPIENT) pobj;
+}
+
+bool COSE_Encrypt_decrypt(HCOSE_ENCRYPT h, HCOSE_RECIPIENT hRecip, cose_errback * perr)
+{
+	COSE_Encrypt * pcose = (COSE_Encrypt *)h;
+	COSE_RecipientInfo * pRecip = (COSE_RecipientInfo *)hRecip;
+
+	if (!IsValidEncryptHandle(h) || (!IsValidRecipientHandle(hRecip))) {
+		if (perr != NULL) perr->err = COSE_ERR_INVALID_PARAMETER;
+		return false;
+	}
+
+	return _COSE_Encrypt_decrypt(pcose, pRecip, perr);
+}
+
+bool _COSE_Encrypt_decrypt(COSE_Encrypt * pcose, COSE_RecipientInfo * pRecip, cose_errback * perr)
+{
+	int alg;
+	int cbitKey;
+	const cn_cbor * cn = NULL;
+	cose_errback error = { 0 };
+
+	byte * pbKey = NULL;
+	cn_cbor_context * context;
+	byte * pbAuthData = NULL;
+	ssize_t cbAuthData;
+	cn_cbor * pAuthData = NULL;
+	byte * pbProtected = NULL;
+	ssize_t cbProtected;
+	cn_cbor * ptmp = NULL;
+
+#ifdef USE_CBOR_CONTEXT
+	context = &pcose->m_message.m_allocContext;
+#endif
+
+	cn = _COSE_map_get_int(&pcose->m_message, COSE_Header_Algorithm, COSE_BOTH, &error);
+
+	if (cn == NULL) {
+	error:
+		if (pbProtected != NULL) COSE_FREE(pbProtected, context);
+		if (pbAuthData != NULL) COSE_FREE(pbAuthData, context);
+		if (pAuthData != NULL) cn_cbor_free(pAuthData CBOR_CONTEXT_PARAM);
+		if (pbKey != NULL) COSE_FREE(pbKey, context);
+		if (perr != NULL) *perr = error;
+		return false;
+	}
+	if (cn->type != CN_CBOR_UINT) goto error;
+	alg = cn->v.uint;
+
+	switch (alg) {
+	case COSE_Algorithm_AES_CCM_64:
+		cbitKey = 128;
+		break;
+
+	default:
+		error.err = COSE_ERR_UNKNOWN_ALGORITHM;
+		goto error;
+	}
+
+	pbKey = COSE_CALLOC(cbitKey / 8, 1, context);
+
+	for (pRecip = pcose->m_recipientFirst; pRecip != NULL; pRecip = pRecip->m_recipientNext) {
+		if (_COSE_Recipient_decrypt(pRecip, cbitKey, pbKey, &error)) break;
+	}
+
+	if (pRecip == NULL) {
+		error.err = COSE_ERR_NO_RECIPIENT_FOUND;
+		goto error;
+	}
+
+	//  Build protected headers
+
+	if (pcose->m_message.m_protectedMap->first_child != NULL) {
+		cbProtected = cbor_encoder_write(RgbDontUse, 0, sizeof(RgbDontUse), pcose->m_message.m_protectedMap);
+		pbProtected = (byte *)COSE_CALLOC(cbProtected, 1, context);
+		if (pbProtected == NULL) goto error;
+		if (cbor_encoder_write(pbProtected, 0, cbProtected, pcose->m_message.m_protectedMap) != cbProtected) goto error;
+		if (!cn_cbor_mapput_int(pcose->m_message.m_cbor, COSE_Header_Protected, cn_cbor_data_create(pbProtected, cbProtected, CBOR_CONTEXT_PARAM_COMMA NULL), CBOR_CONTEXT_PARAM_COMMA NULL)) goto error;
+	}
+	else {
+		pbProtected = NULL;
+		cbProtected = 0;
+	}
+
+	//  Build authenticated data
+	pbAuthData = NULL;
+	pAuthData = cn_cbor_array_create(CBOR_CONTEXT_PARAM_COMMA NULL);
+
+	ptmp = cn_cbor_data_create(pbProtected, cbProtected, CBOR_CONTEXT_PARAM_COMMA NULL);
+	if (ptmp == NULL) goto error;
+	cn_cbor_array_append(pAuthData, ptmp, NULL);
+	pbProtected = NULL;
+
+	ptmp = cn_cbor_data_create(NULL, 0, CBOR_CONTEXT_PARAM_COMMA NULL);
+	if (ptmp == NULL) goto error;
+	cn_cbor_array_append(pAuthData, ptmp, NULL);
+
+	cbAuthData = cbor_encoder_write(RgbDontUse, 0, sizeof(RgbDontUse), pAuthData);
+	pbAuthData = (byte *)COSE_CALLOC(cbAuthData, 1, context);
+	if (pbAuthData == NULL) goto error;
+	if (cbor_encoder_write(pbAuthData, 0, cbAuthData, pAuthData) != cbAuthData) goto error;
+
+	switch (alg) {
+	case COSE_Algorithm_AES_CCM_64:
+		if (!AES_CCM_Decrypt(pcose, 8, 8, pbAuthData, cbAuthData)) {
+			error.err = COSE_ERR_DECRYPT_FAILED;
+			goto error;
+		}
+		break;
+
+	default:
+		error.err = COSE_ERR_UNKNOWN_ALGORITHM;
+		goto error;
+	}
+
+	return true;
+}
+
+bool COSE_Encrypt_encrypt(HCOSE_ENCRYPT h, cose_errback * perror)
+{
+	int alg;
+	int t;
+	COSE_RecipientInfo * pri;
+	const cn_cbor * cn_Alg = NULL;
+	byte * pbAuthData = NULL;
+	cn_cbor * pAuthData = NULL;
+	cn_cbor * ptmp = NULL;
+	byte * pbProtected = NULL;
+	ssize_t cbProtected = 0;
+	size_t cbitKey;
+	cn_cbor_context * context;
+	COSE_Encrypt * pcose = (COSE_Encrypt *) h;
+	cose_errback error;
+
+	if (!IsValidEncryptHandle(h)) {
+		if (perror != NULL) perror->err = COSE_ERR_INVALID_PARAMETER;
+		return false;
+	}
+#ifdef USE_CBOR_CONTEXT
+	context = &pcose->m_message.m_allocContext;
+#endif // USE_CBOR_CONTEXT
+
+	cn_Alg = _COSE_map_get_int(&pcose->m_message, COSE_Header_Algorithm, COSE_BOTH, &error);
+
+	if (cn_Alg == NULL) {
+	error:
+		if (pbProtected != NULL) COSE_FREE(pbProtected, context);
+		if (pbAuthData != NULL) COSE_FREE(pbAuthData, context);
+		if (pAuthData != NULL) cn_cbor_free(pAuthData CBOR_CONTEXT_PARAM);
+		if (ptmp != NULL) cn_cbor_free(ptmp CBOR_CONTEXT_PARAM);
+		if (perror != NULL) *perror = error;
+		return false;
+	}
+	if (cn_Alg->type != CN_CBOR_UINT) goto error;
+	alg = cn_Alg->v.uint;
+
+	//  Get the key size
+
+	switch (alg) {
+	case COSE_Algorithm_AES_CCM_64:
+		cbitKey = 128;
+		break;
+
+	case COSE_Algorithm_Direct:
+		cbitKey = 0;
+		break;
+
+	default:
+		goto error;
+	}
+
+	//  If we are doing direct encryption - then recipient generates the key
+
+	if (pcose->pbKey == NULL) {
+		t = 0;
+		for (pri = pcose->m_recipientFirst; pri != NULL; pri = pri->m_recipientNext) {
+			if (pri->m_encrypt.m_message.m_flags & 1) {
+				t |= 1;
+				pcose->pbKey = _COSE_RecipientInfo_generateKey(pri, cbitKey);
+				if (pcose->pbKey == NULL) goto error;
+				pcose->cbKey = cbitKey / 8;
+			}
+			else {
+				t |= 2;
+			}
+		}
+		if (t == 3) {
+			error.err = CN_CBOR_ERR_INVALID_PARAMETER;
+			goto error;
+		}
+	}
+
+	if (pcose->pbKey == NULL) {
+		pcose->pbKey = (byte *) COSE_CALLOC(cbitKey/8, 1, context);
+		if (pcose->pbKey == NULL) goto error;
+		pcose->cbKey = cbitKey / 8;
+		rand_bytes(pcose->pbKey, pcose->cbKey);
+	}
+
+	//  Build protected headers
+
+	if (pcose->m_message.m_protectedMap->first_child != NULL) {
+		cbProtected = cbor_encoder_write(RgbDontUse, 0, sizeof(RgbDontUse), pcose->m_message.m_protectedMap);
+		pbProtected = (byte *) COSE_CALLOC(cbProtected, 1, context);
+		if (pbProtected == NULL) goto error;
+		if (cbor_encoder_write(pbProtected, 0, cbProtected, pcose->m_message.m_protectedMap) != cbProtected) goto error;
+		if (!cn_cbor_mapput_int(pcose->m_message.m_cbor, COSE_Header_Protected, cn_cbor_data_create(pbProtected, cbProtected, CBOR_CONTEXT_PARAM_COMMA NULL), CBOR_CONTEXT_PARAM_COMMA NULL)) goto error;
+	}
+	else {
+		pbProtected = NULL;
+		cbProtected = 0;
+	}
+
+	//  Add Unprotected headers
+	if (pcose->m_message.m_unprotectMap->first_child != NULL) {
+		if (!cn_cbor_mapput_int(pcose->m_message.m_cbor, COSE_Header_Unprotected, pcose->m_message.m_unprotectMap, CBOR_CONTEXT_PARAM_COMMA NULL)) goto error;
+		pcose->m_message.m_ownUnprotectedMap = false;
+	}
+
+	//  Build authenticated data
+	ssize_t cbAuthData = 0;
+	pbAuthData = NULL;
+	pAuthData = cn_cbor_array_create(CBOR_CONTEXT_PARAM_COMMA NULL);
+
+	ptmp = cn_cbor_data_create(pbProtected, cbProtected, CBOR_CONTEXT_PARAM_COMMA NULL);
+	if (ptmp == NULL) goto error;
+	cn_cbor_array_append(pAuthData, ptmp, NULL);
+	pbProtected = NULL;
+	ptmp = NULL;
+
+	ptmp = cn_cbor_data_create(NULL, 0, CBOR_CONTEXT_PARAM_COMMA NULL);
+	if (ptmp == NULL) goto error;
+	cn_cbor_array_append(pAuthData, ptmp, NULL);
+	ptmp = NULL;
+
+	cbAuthData = cbor_encoder_write(RgbDontUse, 0, sizeof(RgbDontUse), pAuthData);
+	pbAuthData = (byte *) COSE_CALLOC(cbAuthData, 1, context);
+	if (pbAuthData == NULL) goto error;
+	if (cbor_encoder_write(pbAuthData, 0, cbAuthData, pAuthData) != cbAuthData) goto error;
+
+	switch (alg) {
+#ifdef INCLUDE_AES_CCM_64
+	case COSE_Algorithm_AES_CCM_64:
+		if (!AES_CCM_Encrypt(pcose, 64, 8, pbAuthData, cbAuthData)) goto error;
+		break;
+#endif
+
+	case COSE_Algorithm_Direct:
+		break;
+
+	default:
+		return false;
+	}
+
+	for (pri = pcose->m_recipientFirst; pri != NULL; pri = pri->m_recipientNext) {
+		_COSE_Encrypt_SetContent(&pri->m_encrypt, pcose->pbKey, pcose->cbKey, &error);
+		if (error.err != COSE_ERR_NONE) goto error;
+
+		if (!COSE_Encrypt_encrypt((HCOSE_ENCRYPT) &pri->m_encrypt, &error)) goto error;
+	}
+
+	//  Figure out the clean up
+
+	if (pbAuthData != NULL) COSE_FREE(pbAuthData, context);
+	if (pAuthData != NULL) cn_cbor_free(pAuthData CBOR_CONTEXT_PARAM);
+
+	return true;
+}
+
+void COSE_Encrypt_SetContent(HCOSE_ENCRYPT h, const byte * rgb, size_t cb, cose_errback * perror)
+{
+	if (!IsValidEncryptHandle(h) || (rgb == NULL)) {
+		if (perror != NULL) perror->err = COSE_ERR_INVALID_PARAMETER;
+	}
+
+	_COSE_Encrypt_SetContent((COSE_Encrypt *)h, rgb, cb, perror);
+}
+
+void _COSE_Encrypt_SetContent(COSE_Encrypt * cose, const byte * rgb, size_t cb, cose_errback * perror)
+{
+	cose->pbContent = (byte *)COSE_CALLOC(cb, 1, &cose->m_message.m_allocContext);
+	if (cose->pbContent == NULL) {
+		if (perror != NULL) perror->err = COSE_ERR_INVALID_PARAMETER;
+		return;
+	}
+	memcpy(cose->pbContent, rgb, cb);
+	cose->cbContent = cb;
+
+	if (perror != NULL) perror->err = COSE_ERR_NONE;
+	return;
+}
+
+const cn_cbor * COSE_Encrypt_map_get_int(HCOSE_ENCRYPT h, int key, int flags, cose_errback * perror)
+{
+	if (!IsValidEncryptHandle(h)) {
+		if (perror != NULL) perror->err = COSE_ERR_INVALID_PARAMETER;
+		return NULL;
+	}
+
+	return _COSE_map_get_int(&((COSE_Encrypt *)h)->m_message, key, flags, perror);
+}
+
+
+bool COSE_Encrypt_map_put(HCOSE_ENCRYPT h, int key, cn_cbor * value, int flags, cose_errback * perror)
+{
+	if (!IsValidEncryptHandle(h) || (value == NULL)) {
+		if (perror != NULL) perror->err = COSE_ERR_INVALID_PARAMETER;
+		return false;
+	}
+
+	return _COSE_map_put(&((COSE_Encrypt *)h)->m_message, key, value, flags, perror);
+}
diff --git a/src/Message.c b/src/Message.c
new file mode 100644
index 0000000..e62fc28
--- /dev/null
+++ b/src/Message.c
@@ -0,0 +1,13 @@
+#include <stdlib.h>
+
+#include "cose.h"
+#include "cose_int.h"
+#include "configure.h"
+#include "crypto.h"
+
+bool _COSE_Free(COSE * p)
+{
+	COSE_FREE(p, &p->m_allocContext);
+	return true;
+}
+
diff --git a/src/ReadMe.txt b/src/ReadMe.txt
new file mode 100644
index 0000000..9645755
--- /dev/null
+++ b/src/ReadMe.txt
@@ -0,0 +1,29 @@
+========================================================================
+    STATIC LIBRARY : C Project Overview
+========================================================================
+
+AppWizard has created this C library project for you.
+
+No source files were created as part of your project.
+
+
+C.vcxproj
+    This is the main project file for VC++ projects generated using an Application Wizard.
+    It contains information about the version of Visual C++ that generated the file, and
+    information about the platforms, configurations, and project features selected with the
+    Application Wizard.
+
+C.vcxproj.filters
+    This is the filters file for VC++ projects generated using an Application Wizard. 
+    It contains information about the association between the files in your project 
+    and the filters. This association is used in the IDE to show grouping of files with
+    similar extensions under a specific node (for e.g. ".cpp" files are associated with the
+    "Source Files" filter).
+
+/////////////////////////////////////////////////////////////////////////////
+Other notes:
+
+AppWizard uses "TODO:" comments to indicate parts of the source code you
+should add to or customize.
+
+/////////////////////////////////////////////////////////////////////////////
diff --git a/src/Recipient.c b/src/Recipient.c
new file mode 100644
index 0000000..0f6cb1f
--- /dev/null
+++ b/src/Recipient.c
@@ -0,0 +1,112 @@
+#include <stdlib.h>
+#include <memory.h>
+
+#include "cose.h"
+#include "cose_int.h"
+#include "configure.h"
+#include "crypto.h"
+
+bool IsValidRecipientHandle(HCOSE_RECIPIENT h)
+{
+	if (h == NULL) return false;
+	return true;
+}
+
+HCOSE_RECIPIENT COSE_Encrypt_GetRecipient(HCOSE_ENCRYPT cose, int iRecipient, cose_errback * perr)
+{
+	int i;
+	COSE_RecipientInfo * p;
+
+	if (!IsValidEncryptHandle(cose)) {
+		if (perr != NULL) perr->err = COSE_ERR_INVALID_PARAMETER;
+		return NULL;
+	}
+
+	p = ((COSE_Encrypt *)cose)->m_recipientFirst;
+	for (i = 0; i < iRecipient; i++) {
+		if (p == NULL) {
+			if (perr != NULL) perr->err = COSE_ERR_INVALID_PARAMETER;
+			return NULL;
+		}
+	}
+	return (HCOSE_RECIPIENT)p;
+}
+
+COSE_RecipientInfo * _COSE_Recipient_Init_From_Object(cn_cbor * cbor, CBOR_CONTEXT_COMMA cose_errback * errp)
+{
+	COSE_RecipientInfo * pRecipient = NULL;
+
+	pRecipient = (COSE_RecipientInfo *)COSE_CALLOC(1, sizeof(COSE_RecipientInfo), context);
+	if (pRecipient == NULL) {
+		if (errp != NULL) errp->err = COSE_ERR_OUT_OF_MEMORY;
+		return NULL;
+	}
+
+	if (_COSE_Encrypt_Init_From_Object(cbor, &pRecipient->m_encrypt, CBOR_CONTEXT_PARAM_COMMA errp) == NULL) {
+		_COSE_Recipient_Free(pRecipient);
+		return NULL;
+	}
+
+	return pRecipient;
+}
+
+void _COSE_Recipient_Free(COSE_RecipientInfo * pRecipient)
+{
+	COSE_FREE(pRecipient, &pRecipient->m_encrypt.m_message.m_allocContext);
+
+	return;
+}
+
+bool _COSE_Recipient_decrypt(COSE_RecipientInfo * pRecip, int cbitKey, byte * pbKey, cose_errback * perr)
+{
+	return _COSE_Encrypt_decrypt(&pRecip->m_encrypt, NULL, perr);
+}
+
+
+byte * _COSE_RecipientInfo_generateKey(COSE_RecipientInfo * pRecipient, size_t cbitKeySize)
+{
+	int alg;
+	const cn_cbor * cn_Alg = _COSE_map_get_int(&pRecipient->m_encrypt.m_message, COSE_Header_Algorithm, COSE_BOTH, NULL);
+
+	if (cn_Alg == NULL) return false;
+	if (cn_Alg->type != CN_CBOR_UINT) return false;
+	alg = cn_Alg->v.uint;
+
+	switch (alg) {
+	case COSE_Algorithm_Direct:
+	{
+		if (pRecipient->m_encrypt.cbKey != cbitKeySize / 8) return NULL;
+		byte * pb = (byte *)malloc(cbitKeySize / 8);
+		if (pb == NULL) return NULL;
+		memcpy(pb, pRecipient->m_encrypt.pbKey, cbitKeySize / 8);
+		return pb;
+	}
+	break;
+
+	default:
+		return NULL;
+	}
+}
+
+bool COSE_Recipient_SetKey(HCOSE_RECIPIENT h, const byte * pbKey, int cbKey, cose_errback * perror)
+{
+	COSE_RecipientInfo * p;
+
+	if (!IsValidRecipientHandle(h) || (pbKey == NULL)) {
+		if (perror != NULL) perror->err = COSE_ERR_CBOR;
+		return false;
+	}
+
+	p = (COSE_RecipientInfo *)h;
+
+	p->m_encrypt.pbKey = (byte *)COSE_CALLOC(cbKey, 1, &p->m_encrypt.m_message.m_allocContext);
+	if (p->m_encrypt.pbKey == NULL) {
+		if (perror != NULL) perror->err = COSE_ERR_OUT_OF_MEMORY;
+		return false;
+	}
+
+	memcpy(p->m_encrypt.pbKey, pbKey, cbKey);
+	p->m_encrypt.cbKey = cbKey;
+
+	return true;
+}
\ No newline at end of file
diff --git a/src/Sign.c b/src/Sign.c
new file mode 100644
index 0000000..b648437
--- /dev/null
+++ b/src/Sign.c
@@ -0,0 +1,66 @@
+#include <stdlib.h>
+
+#include "cose.h"
+#include "cose_int.h"
+
+
+HCOSE COSE_Decode(const byte * rgbData, int cbData, int * ptype, CBOR_CONTEXT_COMMA cose_errback * errp)
+{
+	cn_cbor * cbor;
+	const cn_cbor * pType = NULL;
+	HCOSE h;
+
+	if ((rgbData == NULL) || (ptype == NULL)) {
+		if (errp != NULL) errp->err = COSE_ERR_INVALID_PARAMETER;
+		return NULL;
+	}
+
+	cbor = (cn_cbor *) cn_cbor_decode(rgbData, cbData, CBOR_CONTEXT_PARAM_COMMA NULL);
+	if (cbor == NULL) {
+		if (errp != NULL) errp->err = COSE_ERR_CBOR;
+		return NULL;
+	}
+
+	if (cbor->type != CN_CBOR_MAP) {
+	error:
+		COSE_FREE(cbor, context);
+		if (errp != NULL) errp->err = COSE_ERR_INVALID_PARAMETER;
+		return NULL;
+	}
+
+	pType = cn_cbor_mapget_int(cbor, COSE_Header_Type);
+	if ((pType == NULL) || (pType->type != CN_CBOR_UINT)) goto error;
+
+	switch (pType->v.sint) {
+	case 1:
+		h = (HCOSE) _COSE_Encrypt_Init_From_Object(cbor, NULL, CBOR_CONTEXT_PARAM_COMMA errp);
+		if (h == NULL) {
+			COSE_FREE(cbor, context);
+			return NULL;
+		}
+		return h;
+
+//	case 2:
+//		return (COSE *)COSE_Sign_Init(cbor CBOR_CONTEXT_PARAM);
+	}
+
+	goto error;
+}
+
+#if 0
+COSE_SignMessage * COSE_Sign_Init(const cn_cbor * CBOR_CONTEXT)
+{
+	COSE_SignMessage * msg;
+
+#ifdef USE_CBOR_CONTEXT
+	msg = (COSE_SignMessage *) context->calloc_func(1, sizeof(COSE_SignMessage), context->context);
+#else
+	msg = (COSE_SignMessage *) calloc(1, sizeof(COSE_SignMessage));
+#endif
+
+	msg->m_message.m_flags = 1;
+	msg->m_message.m_cbor = (cn_cbor *) msg;
+
+	return msg;
+}
+#endif
diff --git a/src/bcrypt.c b/src/bcrypt.c
new file mode 100644
index 0000000..04907e8
--- /dev/null
+++ b/src/bcrypt.c
@@ -0,0 +1,64 @@
+#include "cose.h"
+#include "configure.h"
+#include "cose_int.h"
+#include "crypto.h"
+
+#if USE_BCRYPT
+
+#include <Windows.h>
+
+bool AES_CCM_Encrypt(COSE_Encrypt * pcose, int TSize, int LSize, int KSize, byte * pbAuthData, int cbAuthData)
+{
+	NTSTATUS err;
+	BCRYPT_ALG_HANDLE hAlg = NULL;
+	BCRYPT_KEY_DATA_BLOB_HEADER * pHdr = NULL;
+	BCRYPT_KEY_HANDLE hKey = NULL;
+	BCRYPT_AUTHENTICATED_CIPHER_MODE_INFO authInfo = { 0 };
+	byte rgbTag[16];
+	int cbOut;
+	byte * pbOut = NULL;
+
+	err = BCryptOpenAlgorithmProvider(&hAlg, "AES_CCM", NULL, 0);
+	if (err != 0) {
+	error:
+		if (pbOut != NULL) free(pbOut);
+		if (pHdr != NULL) free(pHdr);
+		if (hKey != NULL) BCryptDestroyKey(hKey);
+		if (hAlg != NULL) BCryptCloseAlgorithmProvider(hAlg, 0);
+		return false;
+	}
+
+	pHdr = (BCRYPT_KEY_DATA_BLOB_HEADER *)malloc(sizeof(*pHdr) + KSize / 8);
+	if (pHdr == NULL) goto error;
+	pHdr->dwMagic = BCRYPT_KEY_DATA_BLOB_MAGIC;
+	pHdr->dwVersion = BCRYPT_KEY_DATA_BLOB_VERSION1;
+	pHdr->cbKeyData = KSize / 8;
+	memcpy(&pHdr[1], pcose->pbKey, pcose->cbKey);
+
+	err = BCryptImportKey(hAlg, NULL, BCRYPT_KEY_DATA_BLOB, &hKey, NULL, 0, pHdr, (sizeof(*pHdr) + KSize / 8), 0);
+	if (err != 0) goto error;
+
+	BCRYPT_INIT_AUTH_MODE_INFO(authInfo);
+	authInfo.pbNonce = pcose->pbIV;
+	authInfo.cbNonce = pcose->cbIV;
+	authInfo.pbAuthData = pbAuthData;
+	authInfo.cbAuthData = cbAuthData;
+	authInfo.pbTag = rgbTag;
+	authInfo.cbTag = TSize / 8;
+	authInfo.pbMacContext = NULL;
+
+	cbOut = pcose->cbContent + TSize / 8;
+	pbOut = (byte *)malloc(cbOut);
+	if (pbOut == NULL) goto error;
+
+	err = BCryptEncrypt(hKey, pcose->pbContent, pcose->cbContent, &authInfo, NULL, 0, pbOut, cbOut, 0, 0);
+	if (err != 0) goto error;
+
+	memcpy(&pbOut[pcose->cbContent], rgbTag, TSize / 8);
+
+	cn_cbor_mapput_int(pcose->m_message.m_cbor, COSE_Header_Ciphertext, cn_cbor_data_create(pbOut, cbOut, NULL), NULL);
+
+	return true;
+}
+
+#endif // USE_BCRYPT
\ No newline at end of file
diff --git a/src/configure.h b/src/configure.h
new file mode 100644
index 0000000..8b8ef23
--- /dev/null
+++ b/src/configure.h
@@ -0,0 +1,5 @@
+#define INCLUDE_AES_CCM_64 1
+
+
+#define USE_OPEN_SSL 1
+#define USE_BCRYPT 0
diff --git a/src/cose.h b/src/cose.h
new file mode 100644
index 0000000..10811c1
--- /dev/null
+++ b/src/cose.h
@@ -0,0 +1,95 @@
+#define USE_CBOR_CONTEXT 1
+
+#include <cn-cbor\cn-cbor.h>
+#include "configure.h"
+typedef unsigned char byte;
+
+typedef struct _cose * HCOSE;
+typedef struct _cose_sign * HCOSE_SIGN;
+typedef struct _cose_encrypt * HCOSE_ENCRYPT;
+typedef struct _cose_recipient * HCOSE_RECIPIENT;
+
+
+/**
+* All of the different kinds of errors
+*/
+typedef enum cose_error {
+	/** No error has occurred */
+	COSE_ERR_NONE,
+	/** An invalid parameter was passed to a function */
+	COSE_ERR_INVALID_PARAMETER,
+	/** Allocation failed */
+	COSE_ERR_OUT_OF_MEMORY,
+	/** Error in processing CBOR */
+	COSE_ERR_CBOR,
+	/** Unknown algorithm found */
+	COSE_ERR_UNKNOWN_ALGORITHM,
+	/** No usable recipient found */
+	COSE_ERR_NO_RECIPIENT_FOUND,
+	/** Decryption operation failed */
+	COSE_ERR_DECRYPT_FAILED
+} cose_error;
+
+/**
+* Errors
+*/
+typedef struct cose_errback {
+	/** The error, or CN_CBOR_NO_ERROR if none */
+	cose_error err;
+} cose_errback;
+
+//  Generic functions for the COSE library
+
+HCOSE COSE_Decode(const byte * rgbData, int cbData, int * type, CBOR_CONTEXT_COMMA cose_errback * perr);  //  Decode the object
+size_t COSE_Encode(HCOSE msg, byte * rgb, int ib, size_t cb);
+
+cn_cbor * COSE_get_cbor(HCOSE hmsg);
+
+//  Functions for the signing object
+
+HCOSE_SIGN * COSE_Sign_Init(CBOR_CONTEXT_COMMA cose_errback * perr);
+// COSE_SignMessage * COSE_Sign_Init(const cn_cbor * COMMA_CBOR_CONTEXT);
+
+
+HCOSE_ENCRYPT  COSE_Encrypt_Init(CBOR_CONTEXT_COMMA cose_errback * perr);
+bool COSE_Encrypt_Free(HCOSE_ENCRYPT cose);
+
+typedef enum {
+	COSE_PROTECT_ONLY = 1,
+	COSE_UNPROTECT_ONLY = 2,
+	COSE_BOTH = 3
+} cose_protect_state;
+
+typedef enum {
+	COSE_Algorithm_AES_CCM_64 = 1,
+	COSE_Algorithm_Direct,
+	COSE_Algorithm_ECDH_ES_Direct
+} COSE_Algorithms;
+
+typedef enum {
+	COSE_Header_Algorithm = 1,
+	COSE_Header_KID,
+	COSE_Header_Protected,
+	COSE_Header_Unprotected,
+	COSE_Header_IV,
+	COSE_Header_Ciphertext,
+	COSE_Header_Recipients,
+	COSE_Header_Type
+} COSE_Header;
+
+
+void COSE_Encrypt_SetContent(HCOSE_ENCRYPT cose, const byte * rgbContent, size_t cbContent, cose_errback * errp);
+void COSE_Encrypt_SetNonce(HCOSE_ENCRYPT cose, byte * rgbIV, size_t cbIV);
+
+const cn_cbor * COSE_Encrypt_map_get_string(HCOSE_ENCRYPT cose, const char * key, int flags, cose_errback * errp);
+const cn_cbor * COSE_Encrypt_map_get_int(HCOSE_ENCRYPT cose, int key, int flags, cose_errback * errp);
+
+bool COSE_Encrypt_map_put(HCOSE_ENCRYPT cose, int key, cn_cbor * value, int flags, cose_errback * errp);
+
+bool COSE_Encrypt_encrypt(HCOSE_ENCRYPT cose, cose_errback * perror);
+bool COSE_Encrypt_decrypt(HCOSE_ENCRYPT, HCOSE_RECIPIENT, cose_errback * perr);
+
+HCOSE_RECIPIENT COSE_Encrypt_add_shared_secret(HCOSE_ENCRYPT cose, COSE_Algorithms algId, byte * rgbKey, int cbKey, byte * rgbKid, int cbKid, cose_errback * perr);
+
+HCOSE_RECIPIENT COSE_Encrypt_GetRecipient(HCOSE_ENCRYPT cose, int iRecipient, cose_errback * perr);
+bool COSE_Recipient_SetKey(HCOSE_RECIPIENT h, const byte * rgb, int cb, cose_errback * perr);
diff --git a/src/cose_int.h b/src/cose_int.h
new file mode 100644
index 0000000..69afe6a
--- /dev/null
+++ b/src/cose_int.h
@@ -0,0 +1,113 @@
+// These definitions are here because they aren't required for the public
+// interface, and they were quite confusing in cn-cbor.h
+
+typedef struct {
+	int m_flags;        //  Not sure what goes here yet
+	int m_ownMsg : 1;	//  Do I own the pointer @ m_cbor?
+	int m_ownUnprotectedMap : 1; //  Do I own the pointer @ m_unportectedMap?
+	int m_msgType : 4;	//  What message type is this?
+	cn_cbor * m_cbor;
+	cn_cbor * m_protectedMap;
+	cn_cbor * m_unprotectMap;
+#ifdef USE_CBOR_CONTEXT
+	cn_cbor_context m_allocContext;
+#endif
+} COSE;
+
+typedef struct {
+	COSE m_message;	    // The message object
+} COSE_SignMessage;
+
+
+struct _RecipientInfo;
+typedef struct _RecipientInfo COSE_RecipientInfo;
+
+typedef struct {
+	COSE m_message;		// The message object
+	COSE_RecipientInfo * m_recipientFirst;
+	byte * pbContent;
+	size_t cbContent;
+	byte * pbKey;
+	size_t cbKey;
+//	byte * pbIV;
+//	size_t cbIV;
+} COSE_Encrypt;
+
+typedef struct _RecipientInfo {
+	COSE_Encrypt m_encrypt;
+	COSE_RecipientInfo * m_recipientNext;
+} COSE_RecipientInfo;
+
+
+#ifdef USE_CBOR_CONTEXT
+/**
+* Allocate enough space for 1 `cn_cbor` structure.
+*
+* @param[in]  ctx  The allocation context, or NULL for calloc.
+* @return          A pointer to a `cn_cbor` or NULL on failure
+*/
+#define CN_CALLOC(ctx) ((ctx) && (ctx)->calloc_func) ? \
+    (ctx)->calloc_func(1, sizeof(cn_cbor), (ctx)->context) : \
+    calloc(1, sizeof(cn_cbor));
+
+/**
+*  Allocate space required
+*
+* @param[in]	ctx  The allocation context, or NULL for normal calloc.
+* @param[in]	count	Number of items to allocate
+* @param[in]	size	Size of item to allocate
+* @return				A pointer to the object needed
+*/
+#define COSE_CALLOC(count, size, ctx) ((((ctx)) && ((ctx)->calloc_func)) ? \
+	((ctx)->calloc_func(count, size, (ctx)->context)) : \
+	calloc(count, size))
+
+/**
+* Free a
+* @param  free_func [description]
+* @return           [description]
+*/
+#define COSE_FREE(ptr, ctx) (((ctx) && (ctx)->free_func) ? \
+    ((ctx)->free_func((ptr), (ctx)->context)) : \
+    free((ptr)))
+
+#define CBOR_CONTEXT_PARAM , context
+#define CBOR_CONTEXT_PARAM_COMMA context ,
+//#define CN_CALLOC_CONTEXT() CN_CALLOC(context)
+#define CN_CBOR_FREE(p, context) cn_cbor_free(p, context)
+
+#else
+
+#define CBOR_CONTEXT_PARAM
+#define CN_CALLOC_CONTEXT() CN_CALLOC
+#define COSE_CALLOC(ctx, count, size) calloc(count, size)
+#define CN_CBOR_FREE(p, context) cn_cbor_free(p)
+
+#define COSE_FREE(ptr, ctx) free(ptr)
+
+#endif // USE_CBOR_CONTEXT
+
+#ifndef UNUSED_PARAM
+#define UNUSED_PARAM(p) ((void)&(p))
+#endif
+
+extern bool IsValidEncryptHandle(HCOSE_ENCRYPT h);
+extern bool IsValidRecipientHandle(HCOSE_RECIPIENT h);
+
+extern bool _COSE_Init(COSE * pcose, CBOR_CONTEXT_COMMA cose_errback * errp);
+extern bool _COSE_Init_From_Object(COSE* pobj, cn_cbor * pcbor, CBOR_CONTEXT_COMMA cose_errback * perror);
+extern void _COSE_Release(COSE * pcose);
+
+extern const cn_cbor * _COSE_map_get_string(COSE * cose, const char * key, int flags, cose_errback * errp);
+extern const cn_cbor * _COSE_map_get_int(COSE * cose, int key, int flags, cose_errback * errp);
+extern bool _COSE_map_put(COSE * cose, int key, cn_cbor * value, int flags, cose_errback * errp);
+
+extern HCOSE_ENCRYPT _COSE_Encrypt_Init_From_Object(cn_cbor *, COSE_Encrypt * pIn, CBOR_CONTEXT_COMMA cose_errback * errp);
+extern void _COSE_Encrypt_Release(COSE_Encrypt * p);
+extern bool _COSE_Encrypt_decrypt(COSE_Encrypt * pbody, COSE_RecipientInfo * pRecip, cose_errback * perr);
+extern void _COSE_Encrypt_SetContent(COSE_Encrypt * cose, const byte * rgbContent, size_t cbContent, cose_errback * errp);
+
+extern COSE_RecipientInfo * _COSE_Recipient_Init_From_Object(cn_cbor *, CBOR_CONTEXT_COMMA cose_errback * errp);
+extern void _COSE_Recipient_Free(COSE_RecipientInfo *);
+extern bool _COSE_Recipient_decrypt(COSE_RecipientInfo * pRecip, int cbitKey, byte * pbKey, cose_errback * errp);
+extern byte * _COSE_RecipientInfo_generateKey(COSE_RecipientInfo * pRecipient, size_t cbitKeySize);
diff --git a/src/crypto.h b/src/crypto.h
new file mode 100644
index 0000000..3a74fb8
--- /dev/null
+++ b/src/crypto.h
@@ -0,0 +1,32 @@
+/**
+* Perform an AES-CCM Decryption operation
+*
+* @param[in]   COSE_Encrypt Pointer to COSE Encryption context object
+* @param[in]   int          Size of the Tag value to be create
+* @param[in]   int          Size of the Message Length field
+* @param[in]   byte *       Pointer to authenticated data structure
+* @param[in]   int          Size of authenticated data structure
+* @return                   Did the function succeed?
+*/
+bool AES_CCM_Decrypt(COSE_Encrypt * pcose, int TSize, int LSize, const byte * pbAuthData, int cbAuthData);
+
+/**
+* Perform an AES-CCM Encryption operation
+*
+* @param[in]   COSE_Encrypt Pointer to COSE Encryption context object
+* @param[in]   int          Size of the Tag value to be create
+* @param[in]   int          Size of the Message Length field
+* @param[in]   byte *       Pointer to authenticated data structure
+* @param[in]   int          Size of authenticated data structure
+* @return                   Did the function succeed?
+*/
+bool AES_CCM_Encrypt(COSE_Encrypt * pcose, int TSize, int LSize, const byte * pbAuthData, int cbAuthData);
+
+/**
+*  Generate random bytes in a buffer
+*
+* @param[in]   byte *      Pointer to buffer to be filled
+* @param[in]   size_t      Size of buffer to be filled
+* @return                  none
+*/
+void rand_bytes(byte * pb, size_t cb);
diff --git a/src/openssl.c b/src/openssl.c
new file mode 100644
index 0000000..ac3fab5
--- /dev/null
+++ b/src/openssl.c
@@ -0,0 +1,134 @@
+#include "cose.h"
+#include "configure.h"
+#include "cose_int.h"
+#include "crypto.h"
+
+#ifdef USE_OPEN_SSL
+
+#include <openssl\evp.h>
+#include <openssl\rand.h>
+
+
+bool AES_CCM_Decrypt(COSE_Encrypt * pcose, int TSize, int LSize, const byte * pbAuthData, int cbAuthData)
+{
+	EVP_CIPHER_CTX ctx;
+	int cbOut;
+	byte * rgbOut = NULL;
+	ssize_t NSize = 15 - LSize;
+	int outl = 0;
+	byte rgbIV[15] = { 0 };
+	const cn_cbor * pIV = NULL;
+#ifdef USE_CBOR_CONTEXT
+	cn_cbor_context * context = &pcose->m_message.m_allocContext;
+#endif
+
+	//  Setup the IV/Nonce and put it into the message
+
+	pIV = _COSE_map_get_int(&pcose->m_message, COSE_Header_IV, COSE_BOTH, NULL);
+	if ((pIV == NULL) || (pIV->type!= CN_CBOR_BYTES)) {
+	error:
+		if (rgbOut != NULL) COSE_FREE(rgbOut, context);
+		return false;
+	}
+
+	if (pIV->length > NSize) goto error;
+	memcpy(&rgbIV[NSize - pIV->length], pIV->v.str, pIV->length);
+
+	//  Setup and run the OpenSSL code
+
+	EVP_CIPHER_CTX_init(&ctx);
+	EVP_EncryptInit_ex(&ctx, EVP_aes_128_ccm(), NULL, NULL, NULL);
+
+	EVP_CIPHER_CTX_ctrl(&ctx, EVP_CTRL_CCM_SET_L, LSize, 0);
+	EVP_CIPHER_CTX_ctrl(&ctx, EVP_CTRL_CCM_SET_IVLEN, NSize, 0);
+	EVP_CIPHER_CTX_ctrl(&ctx, EVP_CTRL_CCM_SET_TAG, TSize, NULL);	// Say we are doing an 8 byte tag
+
+	EVP_EncryptInit(&ctx, 0, pcose->pbKey, rgbIV);
+
+	EVP_EncryptUpdate(&ctx, 0, &cbOut, 0, pcose->cbContent);
+
+	EVP_EncryptUpdate(&ctx, NULL, &outl, pbAuthData, cbAuthData);
+
+	rgbOut = (byte *)COSE_CALLOC(cbOut + TSize, 1, context);
+	if (rgbOut == NULL) goto error;
+
+	EVP_EncryptUpdate(&ctx, rgbOut, &cbOut, pcose->pbContent, pcose->cbContent);
+
+	EVP_EncryptFinal_ex(&ctx, &rgbOut[cbOut], &cbOut);
+
+	EVP_CIPHER_CTX_ctrl(&ctx, EVP_CTRL_CCM_GET_TAG, TSize, &rgbOut[pcose->cbContent]);
+
+	cn_cbor_mapput_int(pcose->m_message.m_cbor, COSE_Header_Ciphertext, cn_cbor_data_create(rgbOut, pcose->cbContent + TSize, CBOR_CONTEXT_PARAM_COMMA NULL), CBOR_CONTEXT_PARAM_COMMA NULL);
+
+	return true;
+}
+
+
+bool AES_CCM_Encrypt(COSE_Encrypt * pcose, int TSize, int LSize, const byte * pbAuthData, int cbAuthData)
+{
+	EVP_CIPHER_CTX ctx;
+	int cbOut;
+	byte * rgbOut = NULL;
+	ssize_t NSize = 15 - LSize;
+	int outl = 0;
+	byte rgbIV[15] = { 0 };
+	const cn_cbor * cbor_iv = NULL;
+#ifdef USE_CBOR_CONTEXT
+	cn_cbor_context * context = &pcose->m_message.m_allocContext;
+#endif
+
+	//  Setup the IV/Nonce and put it into the message
+
+	cbor_iv = _COSE_map_get_int(&pcose->m_message, COSE_Header_IV, COSE_BOTH, NULL);
+	if ((cbor_iv == NULL) || (cbor_iv->type != CN_CBOR_BYTES)) {
+		error:
+		if (rgbOut != NULL) COSE_FREE(rgbOut, context);
+		return false;
+	}
+
+	if (cbor_iv->length > NSize) goto error;
+	memcpy(&rgbIV[NSize-cbor_iv->length], cbor_iv->v.str, cbor_iv->length);
+
+#if 0
+	if (!cn_cbor_mapput_int(pcose->m_message.m_cbor, COSE_Header_IV, cn_cbor_data_create(rgbIV, NSize, CBOR_CONTEXT_PARAM_COMMA NULL), CBOR_CONTEXT_PARAM_COMMA NULL)) {
+		goto error;
+	}
+#endif
+
+	//  Setup and run the OpenSSL code
+
+	EVP_CIPHER_CTX_init(&ctx);
+	EVP_EncryptInit_ex(&ctx, EVP_aes_128_ccm(), NULL, NULL, NULL);
+
+	TSize /= 8; // Comes in in bits not bytes.
+	EVP_CIPHER_CTX_ctrl(&ctx, EVP_CTRL_CCM_SET_L, LSize, 0);
+	EVP_CIPHER_CTX_ctrl(&ctx, EVP_CTRL_CCM_SET_IVLEN, NSize, 0);
+	EVP_CIPHER_CTX_ctrl(&ctx, EVP_CTRL_CCM_SET_TAG, TSize, NULL);	// Say we are doing an 8 byte tag
+
+	EVP_EncryptInit(&ctx, 0, pcose->pbKey, rgbIV);
+
+	EVP_EncryptUpdate(&ctx, 0, &cbOut, 0, pcose->cbContent);
+
+	EVP_EncryptUpdate(&ctx, NULL, &outl, pbAuthData, cbAuthData);
+
+	rgbOut = (byte *)COSE_CALLOC(cbOut + TSize, 1, context);
+	if (rgbOut == NULL) goto error;
+
+	EVP_EncryptUpdate(&ctx, rgbOut, &cbOut, pcose->pbContent, pcose->cbContent);
+
+	EVP_EncryptFinal_ex(&ctx, &rgbOut[cbOut], &cbOut);
+
+	EVP_CIPHER_CTX_ctrl(&ctx, EVP_CTRL_CCM_GET_TAG, TSize, &rgbOut[pcose->cbContent]);
+
+	cn_cbor_mapput_int(pcose->m_message.m_cbor, COSE_Header_Ciphertext, cn_cbor_data_create(rgbOut,  pcose->cbContent + TSize, CBOR_CONTEXT_PARAM_COMMA NULL), CBOR_CONTEXT_PARAM_COMMA NULL);
+
+	return true;
+}
+
+
+void rand_bytes(byte * pb, size_t cb)
+{
+	RAND_bytes(pb, cb);
+}
+
+#endif // USE_OPEN_SSL
diff --git a/test/ReadMe.txt b/test/ReadMe.txt
new file mode 100644
index 0000000..d657473
--- /dev/null
+++ b/test/ReadMe.txt
@@ -0,0 +1,40 @@
+========================================================================
+    CONSOLE APPLICATION : test Project Overview
+========================================================================
+
+AppWizard has created this test application for you.
+
+This file contains a summary of what you will find in each of the files that
+make up your test application.
+
+
+test.vcxproj
+    This is the main project file for VC++ projects generated using an Application Wizard.
+    It contains information about the version of Visual C++ that generated the file, and
+    information about the platforms, configurations, and project features selected with the
+    Application Wizard.
+
+test.vcxproj.filters
+    This is the filters file for VC++ projects generated using an Application Wizard. 
+    It contains information about the association between the files in your project 
+    and the filters. This association is used in the IDE to show grouping of files with
+    similar extensions under a specific node (for e.g. ".cpp" files are associated with the
+    "Source Files" filter).
+
+test.cpp
+    This is the main application source file.
+
+/////////////////////////////////////////////////////////////////////////////
+Other standard files:
+
+StdAfx.h, StdAfx.cpp
+    These files are used to build a precompiled header (PCH) file
+    named test.pch and a precompiled types file named StdAfx.obj.
+
+/////////////////////////////////////////////////////////////////////////////
+Other notes:
+
+AppWizard uses "TODO:" comments to indicate parts of the source code you
+should add to or customize.
+
+/////////////////////////////////////////////////////////////////////////////
diff --git a/test/stdafx.cpp b/test/stdafx.cpp
new file mode 100644
index 0000000..ab6cf71
--- /dev/null
+++ b/test/stdafx.cpp
@@ -0,0 +1,8 @@
+// stdafx.cpp : source file that includes just the standard includes
+// test.pch will be the pre-compiled header
+// stdafx.obj will contain the pre-compiled type information
+
+#include "stdafx.h"
+
+// TODO: reference any additional headers you need in STDAFX.H
+// and not in this file
diff --git a/test/stdafx.h b/test/stdafx.h
new file mode 100644
index 0000000..b005a83
--- /dev/null
+++ b/test/stdafx.h
@@ -0,0 +1,15 @@
+// stdafx.h : include file for standard system include files,
+// or project specific include files that are used frequently, but
+// are changed infrequently
+//
+
+#pragma once
+
+#include "targetver.h"
+
+#include <stdio.h>
+#include <tchar.h>
+
+
+
+// TODO: reference additional headers your program requires here
diff --git a/test/targetver.h b/test/targetver.h
new file mode 100644
index 0000000..87c0086
--- /dev/null
+++ b/test/targetver.h
@@ -0,0 +1,8 @@
+#pragma once
+
+// Including SDKDDKVer.h defines the highest available Windows platform.
+
+// If you wish to build your application for a previous Windows platform, include WinSDKVer.h and
+// set the _WIN32_WINNT macro to the platform you wish to support before including SDKDDKVer.h.
+
+#include <SDKDDKVer.h>
diff --git a/test/test.c b/test/test.c
new file mode 100644
index 0000000..9563941
--- /dev/null
+++ b/test/test.c
@@ -0,0 +1,79 @@
+// test.cpp : Defines the entry point for the console application.
+//
+
+#define _CRT_SECURE_NO_WARNINGS
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <cose.h>
+#include <cn-cbor\cn-cbor.h>
+
+extern int EncryptMessage();
+
+int main(int argc, char * argv[])
+{
+	EncryptMessage();
+	return 0;
+}
+
+int EncryptMessage()
+{
+	HCOSE_ENCRYPT hEncObj = COSE_Encrypt_Init(NULL, NULL);
+	byte rgbSecret[128 / 8] = { 'a', 'b', 'c' };
+	int cbSecret = 128/8;
+	byte  rgbKid[6] = { 'a', 'b', 'c', 'd', 'e', 'f' };
+	int cbKid = 6;
+	int cb;
+	byte * rgb;
+	char * sz = "This is the content to be used";
+
+
+	COSE_Encrypt_map_put(hEncObj, COSE_Header_Algorithm, cn_cbor_int_create(COSE_Algorithm_AES_CCM_64, NULL, NULL), COSE_PROTECT_ONLY, NULL);
+	COSE_Encrypt_SetContent(hEncObj, sz, strlen(sz), NULL);
+	COSE_Encrypt_map_put(hEncObj, COSE_Header_IV, cn_cbor_data_create(rgbKid, cbKid, NULL, NULL), COSE_UNPROTECT_ONLY, NULL);
+
+	COSE_Encrypt_add_shared_secret(hEncObj, COSE_Algorithm_Direct, rgbSecret, cbSecret, rgbKid, cbKid, NULL);
+
+	COSE_Encrypt_encrypt(hEncObj, NULL);
+
+	cb = COSE_Encode((HCOSE)hEncObj, NULL, 0, 0) +1;
+	rgb = (byte *)malloc(cb);
+	cb = COSE_Encode((HCOSE)hEncObj, rgb, 0, cb);
+
+
+	FILE * fp = fopen("test.cbor", "wb");
+	fwrite(rgb, cb, 1, fp);
+	fclose(fp);
+
+	char * szX;
+	int cbPrint;
+	cn_cbor * cbor = COSE_get_cbor((HCOSE) hEncObj);
+	cbPrint = cn_cbor_printer_write(NULL, 0, cbor, "  ", "\r\n");
+	szX = malloc(cbPrint);
+	cn_cbor_printer_write(szX, cbPrint, cbor, "  ", "\r\n");
+	fprintf(stdout, szX);
+	fprintf(stdout, "\r\n");
+
+	COSE_Encrypt_Free(hEncObj);
+
+	/* */
+
+	int typ;
+	hEncObj = (HCOSE_ENCRYPT) COSE_Decode(rgb, cb, &typ, NULL, NULL);
+	
+	int iRecipient = 0;
+	do {
+		HCOSE_RECIPIENT hRecip;
+
+		hRecip = COSE_Encrypt_GetRecipient(hEncObj, iRecipient, NULL);
+		if (hRecip == NULL) break;
+
+		COSE_Recipient_SetKey(hRecip, rgbSecret, cbSecret, NULL);
+
+		COSE_Encrypt_decrypt(hEncObj, hRecip, NULL);
+
+	} while (true);
+
+	return 1;
+}
diff --git a/test/test.cbor b/test/test.cbor
new file mode 100644
index 0000000..852efbc
--- /dev/null
+++ b/test/test.cbor
@@ -0,0 +1 @@
+¥¡¢FabcdefC¡¡FabcdefX&¾gN5{œŸÐl	;A#åE‰Îú¼×èb<ó¬ôØñºò
\ No newline at end of file
diff --git a/test/test.sdf b/test/test.sdf
new file mode 100644
index 0000000..b578cd2
--- /dev/null
+++ b/test/test.sdf
Binary files differ
diff --git a/test/test.sln b/test/test.sln
new file mode 100644
index 0000000..1514741
--- /dev/null
+++ b/test/test.sln
@@ -0,0 +1,58 @@
+
+Microsoft Visual Studio Solution File, Format Version 12.00
+# Visual Studio 2013
+VisualStudioVersion = 12.0.31101.0
+MinimumVisualStudioVersion = 10.0.40219.1
+Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "test", "test.vcxproj", "{754DE184-43E9-48D8-A348-267A0AE6914D}"
+	ProjectSection(ProjectDependencies) = postProject
+		{812F0EC4-27E4-4AC7-9201-DB099790004B} = {812F0EC4-27E4-4AC7-9201-DB099790004B}
+		{A45661E2-52CA-4531-9CC0-98EC8F88D50D} = {A45661E2-52CA-4531-9CC0-98EC8F88D50D}
+	EndProjectSection
+EndProject
+Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "C", "..\src\C.vcxproj", "{A45661E2-52CA-4531-9CC0-98EC8F88D50D}"
+EndProject
+Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "cn-cbor", "..\..\cn-cbor\implement\cn-cbor\cn-cbor.vcxproj", "{812F0EC4-27E4-4AC7-9201-DB099790004B}"
+EndProject
+Global
+	GlobalSection(SolutionConfigurationPlatforms) = preSolution
+		Debug|ARM = Debug|ARM
+		Debug|Win32 = Debug|Win32
+		Debug|x64 = Debug|x64
+		Release|ARM = Release|ARM
+		Release|Win32 = Release|Win32
+		Release|x64 = Release|x64
+	EndGlobalSection
+	GlobalSection(ProjectConfigurationPlatforms) = postSolution
+		{754DE184-43E9-48D8-A348-267A0AE6914D}.Debug|ARM.ActiveCfg = Debug|Win32
+		{754DE184-43E9-48D8-A348-267A0AE6914D}.Debug|Win32.ActiveCfg = Debug|Win32
+		{754DE184-43E9-48D8-A348-267A0AE6914D}.Debug|Win32.Build.0 = Debug|Win32
+		{754DE184-43E9-48D8-A348-267A0AE6914D}.Debug|x64.ActiveCfg = Debug|Win32
+		{754DE184-43E9-48D8-A348-267A0AE6914D}.Release|ARM.ActiveCfg = Release|Win32
+		{754DE184-43E9-48D8-A348-267A0AE6914D}.Release|Win32.ActiveCfg = Release|Win32
+		{754DE184-43E9-48D8-A348-267A0AE6914D}.Release|Win32.Build.0 = Release|Win32
+		{754DE184-43E9-48D8-A348-267A0AE6914D}.Release|x64.ActiveCfg = Release|Win32
+		{A45661E2-52CA-4531-9CC0-98EC8F88D50D}.Debug|ARM.ActiveCfg = Debug|Win32
+		{A45661E2-52CA-4531-9CC0-98EC8F88D50D}.Debug|Win32.ActiveCfg = Debug|Win32
+		{A45661E2-52CA-4531-9CC0-98EC8F88D50D}.Debug|Win32.Build.0 = Debug|Win32
+		{A45661E2-52CA-4531-9CC0-98EC8F88D50D}.Debug|x64.ActiveCfg = Debug|Win32
+		{A45661E2-52CA-4531-9CC0-98EC8F88D50D}.Release|ARM.ActiveCfg = Release|Win32
+		{A45661E2-52CA-4531-9CC0-98EC8F88D50D}.Release|Win32.ActiveCfg = Release|Win32
+		{A45661E2-52CA-4531-9CC0-98EC8F88D50D}.Release|Win32.Build.0 = Release|Win32
+		{A45661E2-52CA-4531-9CC0-98EC8F88D50D}.Release|x64.ActiveCfg = Release|Win32
+		{812F0EC4-27E4-4AC7-9201-DB099790004B}.Debug|ARM.ActiveCfg = Debug|ARM
+		{812F0EC4-27E4-4AC7-9201-DB099790004B}.Debug|ARM.Build.0 = Debug|ARM
+		{812F0EC4-27E4-4AC7-9201-DB099790004B}.Debug|Win32.ActiveCfg = Debug|Win32
+		{812F0EC4-27E4-4AC7-9201-DB099790004B}.Debug|Win32.Build.0 = Debug|Win32
+		{812F0EC4-27E4-4AC7-9201-DB099790004B}.Debug|x64.ActiveCfg = Debug|x64
+		{812F0EC4-27E4-4AC7-9201-DB099790004B}.Debug|x64.Build.0 = Debug|x64
+		{812F0EC4-27E4-4AC7-9201-DB099790004B}.Release|ARM.ActiveCfg = Release|ARM
+		{812F0EC4-27E4-4AC7-9201-DB099790004B}.Release|ARM.Build.0 = Release|ARM
+		{812F0EC4-27E4-4AC7-9201-DB099790004B}.Release|Win32.ActiveCfg = Release|Win32
+		{812F0EC4-27E4-4AC7-9201-DB099790004B}.Release|Win32.Build.0 = Release|Win32
+		{812F0EC4-27E4-4AC7-9201-DB099790004B}.Release|x64.ActiveCfg = Release|x64
+		{812F0EC4-27E4-4AC7-9201-DB099790004B}.Release|x64.Build.0 = Release|x64
+	EndGlobalSection
+	GlobalSection(SolutionProperties) = preSolution
+		HideSolutionNode = FALSE
+	EndGlobalSection
+EndGlobal
diff --git a/test/test.v12.suo b/test/test.v12.suo
new file mode 100644
index 0000000..7a13725
--- /dev/null
+++ b/test/test.v12.suo
Binary files differ
diff --git a/test/test.vcxproj b/test/test.vcxproj
new file mode 100644
index 0000000..267726c
--- /dev/null
+++ b/test/test.vcxproj
@@ -0,0 +1,105 @@
+<?xml version="1.0" encoding="utf-8"?>
+<Project DefaultTargets="Build" ToolsVersion="12.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
+  <ItemGroup Label="ProjectConfigurations">
+    <ProjectConfiguration Include="Debug|Win32">
+      <Configuration>Debug</Configuration>
+      <Platform>Win32</Platform>
+    </ProjectConfiguration>
+    <ProjectConfiguration Include="Release|Win32">
+      <Configuration>Release</Configuration>
+      <Platform>Win32</Platform>
+    </ProjectConfiguration>
+  </ItemGroup>
+  <PropertyGroup Label="Globals">
+    <ProjectGuid>{754DE184-43E9-48D8-A348-267A0AE6914D}</ProjectGuid>
+    <Keyword>Win32Proj</Keyword>
+    <RootNamespace>test</RootNamespace>
+  </PropertyGroup>
+  <Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
+  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="Configuration">
+    <ConfigurationType>Application</ConfigurationType>
+    <UseDebugLibraries>true</UseDebugLibraries>
+    <PlatformToolset>v120</PlatformToolset>
+    <CharacterSet>Unicode</CharacterSet>
+  </PropertyGroup>
+  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="Configuration">
+    <ConfigurationType>Application</ConfigurationType>
+    <UseDebugLibraries>false</UseDebugLibraries>
+    <PlatformToolset>v120</PlatformToolset>
+    <WholeProgramOptimization>true</WholeProgramOptimization>
+    <CharacterSet>Unicode</CharacterSet>
+  </PropertyGroup>
+  <Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />
+  <ImportGroup Label="ExtensionSettings">
+  </ImportGroup>
+  <ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
+    <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
+  </ImportGroup>
+  <ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
+    <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
+  </ImportGroup>
+  <PropertyGroup Label="UserMacros" />
+  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
+    <LinkIncremental>true</LinkIncremental>
+  </PropertyGroup>
+  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
+    <LinkIncremental>false</LinkIncremental>
+  </PropertyGroup>
+  <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
+    <ClCompile>
+      <PrecompiledHeader>
+      </PrecompiledHeader>
+      <WarningLevel>Level3</WarningLevel>
+      <Optimization>Disabled</Optimization>
+      <PreprocessorDefinitions>WIN32;_DEBUG;_CONSOLE;_LIB;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+      <SDLCheck>true</SDLCheck>
+      <AdditionalIncludeDirectories>C:\Projects\COSE\COSE-C\src;C:\Projects\COSE\cn-cbor\implement\cn-cbor\include;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
+      <CompileAs>Default</CompileAs>
+      <CallingConvention>Cdecl</CallingConvention>
+    </ClCompile>
+    <Link>
+      <SubSystem>Console</SubSystem>
+      <GenerateDebugInformation>true</GenerateDebugInformation>
+      <AdditionalDependencies>c:\projects\openssl\bin\lib\ssleay32.lib;c:\projects\openssl\bin\lib\libeay32.lib;Ws2_32.lib;%(AdditionalDependencies)</AdditionalDependencies>
+    </Link>
+  </ItemDefinitionGroup>
+  <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
+    <ClCompile>
+      <WarningLevel>Level3</WarningLevel>
+      <PrecompiledHeader>
+      </PrecompiledHeader>
+      <Optimization>MaxSpeed</Optimization>
+      <FunctionLevelLinking>true</FunctionLevelLinking>
+      <IntrinsicFunctions>true</IntrinsicFunctions>
+      <PreprocessorDefinitions>WIN32;NDEBUG;_CONSOLE;_LIB;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+      <SDLCheck>true</SDLCheck>
+    </ClCompile>
+    <Link>
+      <SubSystem>Console</SubSystem>
+      <GenerateDebugInformation>true</GenerateDebugInformation>
+      <EnableCOMDATFolding>true</EnableCOMDATFolding>
+      <OptimizeReferences>true</OptimizeReferences>
+    </Link>
+  </ItemDefinitionGroup>
+  <ItemGroup>
+    <Text Include="ReadMe.txt" />
+  </ItemGroup>
+  <ItemGroup>
+    <ClInclude Include="stdafx.h" />
+    <ClInclude Include="targetver.h" />
+  </ItemGroup>
+  <ItemGroup>
+    <ClCompile Include="test.c" />
+  </ItemGroup>
+  <ItemGroup>
+    <ProjectReference Include="..\..\cn-cbor\implement\cn-cbor\cn-cbor.vcxproj">
+      <Project>{812f0ec4-27e4-4ac7-9201-db099790004b}</Project>
+    </ProjectReference>
+    <ProjectReference Include="..\src\C.vcxproj">
+      <Project>{a45661e2-52ca-4531-9cc0-98ec8f88d50d}</Project>
+    </ProjectReference>
+  </ItemGroup>
+  <Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
+  <ImportGroup Label="ExtensionTargets">
+  </ImportGroup>
+</Project>
\ No newline at end of file
diff --git a/test/test.vcxproj.filters b/test/test.vcxproj.filters
new file mode 100644
index 0000000..1d6c70c
--- /dev/null
+++ b/test/test.vcxproj.filters
@@ -0,0 +1,33 @@
+<?xml version="1.0" encoding="utf-8"?>
+<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
+  <ItemGroup>
+    <Filter Include="Source Files">
+      <UniqueIdentifier>{4FC737F1-C7A5-4376-A066-2A32D752A2FF}</UniqueIdentifier>
+      <Extensions>cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx</Extensions>
+    </Filter>
+    <Filter Include="Header Files">
+      <UniqueIdentifier>{93995380-89BD-4b04-88EB-625FBE52EBFB}</UniqueIdentifier>
+      <Extensions>h;hh;hpp;hxx;hm;inl;inc;xsd</Extensions>
+    </Filter>
+    <Filter Include="Resource Files">
+      <UniqueIdentifier>{67DA6AB6-F800-4c08-8B7A-83BB121AAD01}</UniqueIdentifier>
+      <Extensions>rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav;mfcribbon-ms</Extensions>
+    </Filter>
+  </ItemGroup>
+  <ItemGroup>
+    <Text Include="ReadMe.txt" />
+  </ItemGroup>
+  <ItemGroup>
+    <ClInclude Include="stdafx.h">
+      <Filter>Header Files</Filter>
+    </ClInclude>
+    <ClInclude Include="targetver.h">
+      <Filter>Header Files</Filter>
+    </ClInclude>
+  </ItemGroup>
+  <ItemGroup>
+    <ClCompile Include="test.c">
+      <Filter>Source Files</Filter>
+    </ClCompile>
+  </ItemGroup>
+</Project>
\ No newline at end of file
diff --git a/test/test.vcxproj.user b/test/test.vcxproj.user
new file mode 100644
index 0000000..ef5ff2a
--- /dev/null
+++ b/test/test.vcxproj.user
@@ -0,0 +1,4 @@
+<?xml version="1.0" encoding="utf-8"?>
+<Project ToolsVersion="12.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
+  <PropertyGroup />
+</Project>
\ No newline at end of file