blob: 320ac921beb150ca1d86a643ba77b215f0e9a3e0 [file] [log] [blame]
#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_dontSendMap = cn_cbor_map_create(CBOR_CONTEXT_PARAM_COMMA &errState);
if (pobj->m_dontSendMap == NULL) goto error_setup;
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_dontSendMap != NULL) CN_CBOR_FREE(pobj->m_dontSendMap, context);
if (pobj->m_ownMsg && (pobj->m_cbor != NULL)) CN_CBOR_FREE(pobj->m_cbor, context);
}
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:
h = (HCOSE)_COSE_Sign_Init_From_Object(cbor, NULL, CBOR_CONTEXT_PARAM_COMMA errp);
if (h == NULL) {
COSE_FREE(cbor, context);
return NULL;
}
return h;
}
goto error;
}
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);
if (p != NULL) return p;
}
if ((pcose->m_dontSendMap != NULL) && ((flags & COSE_DONT_SEND) != 0)) {
p = cn_cbor_mapget_int(pcose->m_dontSendMap, 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);
}
if ((pcose->m_dontSendMap != NULL) && ((flags & COSE_DONT_SEND) != 0)) {
p = cn_cbor_mapget_string(pcose->m_dontSendMap, key);
}
return p;
}
bool _COSE_map_put(COSE * pCose, int key, cn_cbor * value, int flags, cose_errback * perr)
{
cn_cbor_context * context = &pCose->m_allocContext;
cn_cbor_errback error;
bool f;
if ((flags & COSE_BOTH) == COSE_BOTH) {
if (perr != NULL) perr->err = COSE_ERR_INVALID_PARAMETER;
errorReturn:
return false;
}
if (perr != NULL) perr->err = COSE_ERR_NONE;
switch (flags) {
case COSE_PROTECT_ONLY:
f = cn_cbor_mapput_int(pCose->m_protectedMap, key, value, CBOR_CONTEXT_PARAM_COMMA &error);
break;
case COSE_UNPROTECT_ONLY:
f = cn_cbor_mapput_int(pCose->m_unprotectMap, key, value, CBOR_CONTEXT_PARAM_COMMA &error);
break;
case COSE_DONT_SEND:
if (pCose->m_dontSendMap == NULL) {
pCose->m_dontSendMap = cn_cbor_map_create(CBOR_CONTEXT_PARAM_COMMA &error);
CHECK_CONDITION(pCose->m_dontSendMap != NULL, COSE_ERR_OUT_OF_MEMORY);
}
f = cn_cbor_mapput_int(pCose->m_dontSendMap, key, value, CBOR_CONTEXT_PARAM_COMMA &error);
break;
default:
CHECK_CONDITION(false, COSE_ERR_INVALID_PARAMETER);
break;
}
CHECK_CONDITION(f, error.err);
return f;
}
byte RgbDontUse3[1024];
const cn_cbor * _COSE_encode_protected(COSE * pMessage, cose_errback * perr)
{
const cn_cbor * pProtected;
int cbProtected;
byte * pbProtected = NULL;
#ifdef USE_CBOR_CONTEXT
cn_cbor_context * context = &pMessage->m_allocContext;
#endif // USE_CBOR_CONTEXT
pProtected = cn_cbor_mapget_int(pMessage->m_cbor, COSE_Header_Protected);
if (pProtected != NULL) {
errorReturn:
if (pbProtected != NULL) COSE_FREE(pbProtected, context);
return pProtected;
}
cbProtected = cn_cbor_encoder_write(RgbDontUse3, 0, sizeof(RgbDontUse3), pMessage->m_protectedMap);
pbProtected = (byte *)COSE_CALLOC(cbProtected, 1, context);
CHECK_CONDITION(pbProtected != NULL, COSE_ERR_OUT_OF_MEMORY);
CHECK_CONDITION(cn_cbor_encoder_write(pbProtected, 0, cbProtected, pMessage->m_protectedMap) == cbProtected, COSE_ERR_CBOR);
pProtected = cn_cbor_data_create(pbProtected, cbProtected, CBOR_CONTEXT_PARAM_COMMA NULL);
CHECK_CONDITION(pProtected != NULL, COSE_ERR_OUT_OF_MEMORY);
pbProtected = NULL;
CHECK_CONDITION(cn_cbor_mapput_int(pMessage->m_cbor, COSE_Header_Protected, pProtected, CBOR_CONTEXT_PARAM_COMMA NULL), COSE_ERR_CBOR);
return pProtected;
}