Get free to work for signing
diff --git a/README.md b/README.md
index 13d0576..e47b422 100644
--- a/README.md
+++ b/README.md
@@ -1,6 +1,5 @@
-# COSE-C Implementation [![Build Status](https://travis-ci.org/cose-wg/COSE-C.svg?branch=master)](https://travis-ci.org/cose-wg/COSE-C)
-[![Coverage Status](https://coveralls.io/repos/cose-wg/COSE-C/badge.svg?branch=master&service=github)](https://coveralls.io/github/cose-wg/COSE-C?branch=master)
+# COSE-C Implementation [![Build Status](https://travis-ci.org/cose-wg/COSE-C.svg?branch=master)](https://travis-ci.org/cose-wg/COSE-C)[![Coverage Status](https://coveralls.io/repos/cose-wg/COSE-C/badge.svg?branch=master&service=github)](https://coveralls.io/github/cose-wg/COSE-C?branch=master)
This project is a C implementation of the IETF CBOR Encoded Mesage Syntax (COSE).
There are currently two versions of the COSE document that can be read.
diff --git a/src/Cose.c b/src/Cose.c
index ff33f3b..5a0ca32 100644
--- a/src/Cose.c
+++ b/src/Cose.c
@@ -48,6 +48,8 @@
CHECK_CONDITION_CBOR(_COSE_array_replace(pobj, pobj->m_unprotectMap, INDEX_UNPROTECTED, CBOR_CONTEXT_PARAM_COMMA &errState), errState);
pobj->m_ownUnprotectedMap = false;
+ pobj->m_refCount = 1;
+
return true;
errorReturn:
@@ -66,6 +68,7 @@
#ifdef USE_CBOR_CONTEXT
if (context != NULL) pobj->m_allocContext = *context;
#endif
+ pobj->m_cborRoot = pcbor;
pobj->m_cbor = pcbor;
#ifdef TAG_IN_ARRAY
@@ -75,6 +78,11 @@
if (cbor->type == CN_CBOR_UINT) {
pobj->m_msgType = (int) cbor->v.uint;
}
+#else
+ // Check if we have a tag
+ if (pcbor->type == CN_CBOR_TAG) {
+ pcbor = pobj->m_cbor = pcbor->first_child;
+ }
#endif
pmap = _COSE_arrayget_int(pobj, INDEX_PROTECTED);
@@ -98,6 +106,7 @@
pobj->m_ownUnprotectedMap = false;
pobj->m_ownMsg = true;
+ pobj->m_refCount = 1;
return true;
@@ -115,13 +124,14 @@
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_dontSendMap != NULL) CN_CBOR_FREE(pobj->m_dontSendMap, context);
- if (pobj->m_ownMsg && (pobj->m_cbor != NULL)) CN_CBOR_FREE(pobj->m_cbor, context);
+ if (pobj->m_ownMsg && (pobj->m_cborRoot != NULL) && (pobj->m_cborRoot->parent == NULL)) CN_CBOR_FREE(pobj->m_cborRoot, context);
}
HCOSE COSE_Decode(const byte * rgbData, size_t cbData, int * ptype, COSE_object_type struct_type, CBOR_CONTEXT_COMMA cose_errback * perr)
{
cn_cbor * cbor = NULL;
+ cn_cbor * cborRoot = NULL;
#ifdef TAG_IN_ARRAY
const cn_cbor * pType = NULL;
#endif
@@ -130,7 +140,7 @@
CHECK_CONDITION((rgbData != NULL) && (ptype != NULL), COSE_ERR_INVALID_PARAMETER);
- cbor = cn_cbor_decode(rgbData, cbData, CBOR_CONTEXT_PARAM_COMMA &cbor_err);
+ cbor = cborRoot = cn_cbor_decode(rgbData, cbData, CBOR_CONTEXT_PARAM_COMMA &cbor_err);
CHECK_CONDITION_CBOR(cbor != NULL, cbor_err);
#ifdef TAG_IN_ARRAY
@@ -167,7 +177,7 @@
break;
case COSE_sign_object:
- h = (HCOSE)_COSE_Sign_Init_From_Object(cbor, NULL, CBOR_CONTEXT_PARAM_COMMA perr);
+ h = (HCOSE)_COSE_Sign_Init_From_Object(cborRoot, NULL, CBOR_CONTEXT_PARAM_COMMA perr);
if (h == NULL) {
goto errorReturn;
}
diff --git a/src/Sign.c b/src/Sign.c
index 806b30a..89f1d2c 100644
--- a/src/Sign.c
+++ b/src/Sign.c
@@ -36,12 +36,7 @@
if (perr == NULL) perr = &error;
if (pobj == NULL) pobj = (COSE_SignMessage *)COSE_CALLOC(1, sizeof(COSE_SignMessage), context);
- if (pobj == NULL) {
- perr->err = COSE_ERR_OUT_OF_MEMORY;
- errorReturn:
- if ((pIn == NULL) && (pobj != NULL)) COSE_FREE(pobj, context);
- return NULL;
- }
+ CHECK_CONDITION(pobj != NULL, COSE_ERR_OUT_OF_MEMORY);
if (!_COSE_Init_From_Object(&pobj->m_message, cbor, CBOR_CONTEXT_PARAM_COMMA perr)) {
goto errorReturn;
@@ -50,12 +45,11 @@
pSigners = _COSE_arrayget_int(&pobj->m_message, INDEX_SIGNERS);
CHECK_CONDITION(pSigners != NULL, COSE_ERR_INVALID_PARAMETER);
CHECK_CONDITION(pSigners->type == CN_CBOR_ARRAY, COSE_ERR_INVALID_PARAMETER);
+ CHECK_CONDITION(pSigners->length > 0, COSE_ERR_INVALID_PARAMETER); // Must be at least one signer
pSigners = pSigners->first_child;
- CHECK_CONDITION(pSigners != NULL, COSE_ERR_INVALID_PARAMETER); // Must be at least one signer
-
do {
- COSE_SignerInfo * pInfo = _COSE_SignerInfo_Init_From_Object(pSigners, CBOR_CONTEXT_PARAM_COMMA perr);
+ COSE_SignerInfo * pInfo = _COSE_SignerInfo_Init_From_Object(pSigners, NULL, CBOR_CONTEXT_PARAM_COMMA perr);
if (pInfo == NULL) goto errorReturn;
pInfo->m_signerNext = pobj->m_signerFirst;
@@ -64,6 +58,10 @@
} while (pSigners != NULL);
return(HCOSE_SIGN)pobj;
+
+errorReturn:
+ if ((pIn == NULL) && (pobj != NULL)) COSE_FREE(pobj, context);
+ return NULL;
}
bool COSE_Sign_Free(HCOSE_SIGN h)
@@ -71,25 +69,37 @@
#ifdef USE_CBOR_CONTEXT
cn_cbor_context context;
#endif
+ COSE_SignMessage * pMessage = (COSE_SignMessage *)h;
if (!IsValidSignHandle(h)) return false;
+ // Check reference counting
+ if (pMessage->m_message.m_refCount > 1) {
+ pMessage->m_message.m_refCount--;
+ return true;
+ }
+
#ifdef USE_CBOR_CONTEXT
- context = ((COSE_SignMessage *)h)->m_message.m_allocContext;
+ context = pMessage->m_message.m_allocContext;
#endif
- _COSE_Sign_Release((COSE_SignMessage *)h);
+ _COSE_Sign_Release(pMessage);
- COSE_FREE((COSE_SignMessage *)h, &context);
+ COSE_FREE(pMessage, &context);
return true;
}
void _COSE_Sign_Release(COSE_SignMessage * 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_SignerInfo * pSigner;
+ COSE_SignerInfo * pSigner2;
+
+ for (pSigner = p->m_signerFirst; pSigner != NULL; pSigner = pSigner2)
+ {
+ pSigner2 = pSigner->m_signerNext;
+ _COSE_SignerInfo_Free(pSigner);
+ }
_COSE_Release(&p->m_message);
}
@@ -127,7 +137,6 @@
cn_cbor_context * context = NULL;
#endif
COSE_SignMessage * pMessage = (COSE_SignMessage *)hSign;
- COSE_SignerInfo * pSigner = NULL;
const cn_cbor * cbor;
cn_cbor * cbor2 = NULL;
HCOSE_SIGNER hSigner = NULL;
@@ -266,7 +275,7 @@
}
CHECK_CONDITION_CBOR(cn_cbor_array_append(pSigners, pSigner->m_message.m_cbor, &cbor_error), cbor_error);
-
+ pSigner->m_message.m_refCount++;
return true;
@@ -295,3 +304,27 @@
return _COSE_map_put(&((COSE_SignMessage *)h)->m_message, key, value, flags, perror);
}
+HCOSE_SIGNER COSE_Sign_GetSigner(HCOSE_SIGN cose, int iSigner, cose_errback * perr)
+{
+ int i;
+ COSE_SignerInfo * p;
+
+ if (!IsValidSignHandle(cose)) {
+ if (perr != NULL) perr->err = COSE_ERR_INVALID_PARAMETER;
+ return NULL;
+ }
+
+ p = ((COSE_SignMessage *)cose)->m_signerFirst;
+ for (i = 0; i < iSigner; i++) {
+ if (p == NULL) {
+ if (perr != NULL) perr->err = COSE_ERR_INVALID_PARAMETER;
+ return NULL;
+ }
+ p = p->m_signerNext;
+ }
+ p->m_message.m_refCount++;
+
+ return (HCOSE_SIGNER)p;
+}
+
+
diff --git a/src/SignerInfo.c b/src/SignerInfo.c
index 5c763ea..8bbf317 100644
--- a/src/SignerInfo.c
+++ b/src/SignerInfo.c
@@ -31,57 +31,51 @@
return (HCOSE_SIGNER)pobj;
}
-bool COSE_Signer_Free(HCOSE_SIGNER hSigner)
-{
- if (IsValidSignerHandle(hSigner)) {
- _COSE_Signer_Free((COSE_SignerInfo *)hSigner);
+bool _COSE_SignerInfo_Free(COSE_SignerInfo * pSigner)
+{
+#ifdef USE_CBOR_CONTEXT
+ cn_cbor_context context;
+#endif
+
+ // Check ref counting
+ if (pSigner->m_message.m_refCount > 1) {
+ pSigner->m_message.m_refCount--;
return true;
}
- return false;
+#ifdef USE_CBOR_CONTEXT
+ context = pSigner->m_message.m_allocContext;
+#endif
+
+ _COSE_Release(&pSigner->m_message);
+
+ COSE_FREE(pSigner, &context);
+ return true;
}
-void _COSE_Signer_Free(COSE_SignerInfo * pSigner)
+bool COSE_Signer_Free(HCOSE_SIGNER hSigner)
{
- COSE_FREE(pSigner, &pSigner->m_message.m_allocContext);
+ COSE_SignerInfo * pSigner = (COSE_SignerInfo *)hSigner;
- return;
+ if (!IsValidSignerHandle(hSigner)) return false;
+
+ return _COSE_SignerInfo_Free(pSigner);
}
-
-HCOSE_SIGNER COSE_Sign_GetSigner(HCOSE_SIGN cose, int iSigner, cose_errback * perr)
+COSE_SignerInfo * _COSE_SignerInfo_Init_From_Object(cn_cbor * cbor, COSE_SignerInfo * pIn, CBOR_CONTEXT_COMMA cose_errback * perr)
{
- int i;
- COSE_SignerInfo * p;
+ COSE_SignerInfo * pSigner = pIn;
- if (!IsValidSignHandle(cose)) {
- if (perr != NULL) perr->err = COSE_ERR_INVALID_PARAMETER;
- return NULL;
+ if (pSigner == NULL) {
+ pSigner = (COSE_SignerInfo *)COSE_CALLOC(1, sizeof(COSE_SignerInfo), context);
+ CHECK_CONDITION(pSigner != NULL, COSE_ERR_OUT_OF_MEMORY);
}
- p = ((COSE_SignMessage *)cose)->m_signerFirst;
- for (i = 0; i < iSigner; i++) {
- if (p == NULL) {
- if (perr != NULL) perr->err = COSE_ERR_INVALID_PARAMETER;
- return NULL;
- }
- p = p->m_signerNext;
- }
- return (HCOSE_SIGNER)p;
-}
-
-COSE_SignerInfo * _COSE_SignerInfo_Init_From_Object(cn_cbor * cbor, CBOR_CONTEXT_COMMA cose_errback * perr)
-{
- COSE_SignerInfo * pSigner = NULL;
-
- pSigner = (COSE_SignerInfo *)COSE_CALLOC(1, sizeof(COSE_SignerInfo), context);
- CHECK_CONDITION(pSigner != NULL, COSE_ERR_OUT_OF_MEMORY);
-
CHECK_CONDITION(cbor->type == CN_CBOR_ARRAY, COSE_ERR_INVALID_PARAMETER);
if (!_COSE_Init_From_Object(&pSigner->m_message, cbor, CBOR_CONTEXT_PARAM_COMMA perr)) {
- _COSE_Signer_Free(pSigner);
+ _COSE_SignerInfo_Free(pSigner);
return NULL;
}
diff --git a/src/cose_int.h b/src/cose_int.h
index b993449..d6906f0 100644
--- a/src/cose_int.h
+++ b/src/cose_int.h
@@ -8,7 +8,9 @@
int m_ownMsg; // Do I own the pointer @ m_cbor?
int m_ownUnprotectedMap; // Do I own the pointer @ m_unportectedMap?
int m_msgType; // What message type is this?
+ int m_refCount; // Allocator Reference Counting.
cn_cbor * m_cbor;
+ cn_cbor * m_cborRoot;
cn_cbor * m_protectedMap;
cn_cbor * m_unprotectMap;
cn_cbor * m_dontSendMap;
@@ -144,8 +146,8 @@
extern void _COSE_Sign_Release(COSE_SignMessage * p);
extern bool _COSE_Signer_sign(COSE_SignerInfo * pSigner, const cn_cbor * pcborBody, const cn_cbor * pcborProtected, cose_errback * perr);
-extern COSE_SignerInfo * _COSE_SignerInfo_Init_From_Object(cn_cbor * cbor, CBOR_CONTEXT_COMMA cose_errback * perr);
-extern void _COSE_Signer_Free(COSE_SignerInfo * pSigner);
+extern COSE_SignerInfo * _COSE_SignerInfo_Init_From_Object(cn_cbor * cbor, COSE_SignerInfo * pIn, CBOR_CONTEXT_COMMA cose_errback * perr);
+extern bool _COSE_SignerInfo_Free(COSE_SignerInfo * pSigner);
extern bool _COSE_Signer_validate(COSE_SignMessage * pSign, COSE_SignerInfo * pSigner, const byte * pbContent, size_t cbContent, const byte * pbProtected, size_t cbProtected, cose_errback * perr);
// Mac-ed items
diff --git a/test/sign.c b/test/sign.c
index cb12920..136cf47 100644
--- a/test/sign.c
+++ b/test/sign.c
@@ -73,7 +73,8 @@
if ((pFail == NULL) || (pFail->type == CN_CBOR_FALSE)) fFail = true;
}
- // COSE_Encrypt_Free(hSig);
+ COSE_Sign_Free(hSig);
+ COSE_Signer_Free(hSigner);
}
if (fFailBody) {
@@ -143,6 +144,8 @@
if (!COSE_Signer_SetKey(hSigner, pkey, NULL)) exit(1);
if (!COSE_Sign_AddSigner(hSignObj, hSigner, NULL)) exit(1);
+
+ COSE_Signer_Free(hSigner);
}
if (!COSE_Sign_Sign(hSignObj, NULL)) exit(1);
@@ -151,6 +154,8 @@
byte * rgb = (byte *)malloc(cb);
cb = COSE_Encode((HCOSE)hSignObj, rgb, 0, cb);
+ COSE_Sign_Free(hSignObj);
+
int f = _ValidateSigned(pControl, rgb, cb);
free(rgb);
@@ -183,7 +188,7 @@
cn_cbor_mapput_int(pkey, -4, cn_cbor_data_create(rgbD, sizeof(rgbD), CBOR_CONTEXT_PARAM_COMMA NULL), CBOR_CONTEXT_PARAM_COMMA NULL);
COSE_Sign_SetContent(hEncObj, (byte *) sz, strlen(sz), NULL);
- COSE_Sign_add_signer(hEncObj, pkey, COSE_Algorithm_ECDSA_SHA_256, NULL);
+ COSE_Signer_Free(COSE_Sign_add_signer(hEncObj, pkey, COSE_Algorithm_ECDSA_SHA_256, NULL));
COSE_Sign_Sign(hEncObj, NULL);
@@ -191,6 +196,7 @@
rgb = (byte *)malloc(cb);
cb = COSE_Encode((HCOSE)hEncObj, rgb, 0, cb);
+ COSE_Sign_Free(hEncObj);
FILE * fp = fopen("test.mac.cbor", "wb");
fwrite(rgb, cb, 1, fp);
@@ -207,8 +213,6 @@
fprintf(stdout, "\r\n");
#endif
- COSE_Sign_Free(hEncObj);
-
/* */
int typ;