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