X-Git-Url: http://review.tizen.org/git/?a=blobdiff_plain;f=resource%2Fcsdk%2Fsecurity%2Fsrc%2Fcrlresource.c;h=a59df3b9d81f6f3c311e17fc491d32facc0eeeb1;hb=refs%2Ftags%2Fsubmit%2Ftizen_4.0%2F20171010.021147;hp=8514e335a9179e7bc7f390bf86222538e666301a;hpb=b578b61090303a71ae07126107c40c18238a02cd;p=platform%2Fupstream%2Fiotivity.git diff --git a/resource/csdk/security/src/crlresource.c b/resource/csdk/security/src/crlresource.c index 8514e33..a59df3b 100644 --- a/resource/csdk/security/src/crlresource.c +++ b/resource/csdk/security/src/crlresource.c @@ -18,43 +18,49 @@ // //-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= -#include -#include -#include "ocstack.h" -#include "logger.h" -#include "oic_malloc.h" -#include "cJSON.h" -#include "base64.h" -#include "resourcemanager.h" -#include "psinterface.h" #include "utlist.h" +#include "payload_logging.h" +#include "psinterface.h" +#include "resourcemanager.h" #include "srmresourcestrings.h" -#include "doxmresource.h" #include "srmutility.h" -#ifdef __WITH_X509__ +#include "doxmresource.h" +#include "ocpayload.h" +#include "ocpayloadcbor.h" +#include "oic_malloc.h" +#include "oic_string.h" #include "crlresource.h" -#include "crl.h" -#endif /* __WITH_X509__ */ +#include "ocpayloadcbor.h" +#include "base64.h" +#include -#define TAG "SRM-CRL" +#define TAG "OIC_SRM_CRL" #define SEPARATOR ":" #define SEPARATOR_LEN (1) -#define JSON_CRL_NAME "\"CRL\"" -#define JSON_CRL_NAME_LEN (5) -#define OIC_JSON_CRL_NAME "crl" -#define OIC_JSON_CRL_ID "CRLId" -#define OIC_JSON_CRL_THIS_UPDATE "ThisUpdate" -#define OIC_JSON_CRL_DATA "CRLData" -#define CRL_DEFAULT_CRL_ID 1 +#define CBOR_CRL_NAME "\"CRL\"" +#define CBOR_CRL_NAME_LEN (5) +#define OIC_CBOR_CRL_NAME "crl" +#define OIC_CBOR_CRL_ID "CRLId" +#define OIC_CBOR_CRL_THIS_UPDATE "ThisUpdate" +#define OIC_CBOR_CRL_DATA "CRLData" +#define CRL_DEFAULT_CRL_ID (1) #define CRL_DEFAULT_THIS_UPDATE "150101000000Z" +#define CRL_DEFAULT_LAST_UPDATE "20150701000000" #define CRL_DEFAULT_CRL_DATA "-" +#define CRL_MAP_SIZE (3) static OCResourceHandle gCrlHandle = NULL; static OicSecCrl_t *gCrl = NULL; +/** Default cbor payload size. This value is increased in case of CborErrorOutOfMemory. + * The value of payload size is increased until reaching below max cbor size. */ +static const uint16_t CBOR_SIZE = 1024; -void DeleteCrlBinData(OicSecCrl_t *crl) +// Max cbor size payload. +static const uint16_t CBOR_MAX_SIZE = 4400; + +void DeleteCrl(OicSecCrl_t *crl) { if (crl) { @@ -69,277 +75,468 @@ void DeleteCrlBinData(OicSecCrl_t *crl) } } -char *BinToCrlJSON(const OicSecCrl_t *crl, const bool isIncResName) +void printCrl(const OicSecCrl_t *crl) { if (NULL == crl) { - return NULL; + OIC_LOG(INFO, TAG, "Received NULL CRL"); + return; } - char *base64Buff = NULL; - uint32_t outLen = 0; - uint32_t base64CRLLen = 0; - B64Result b64Ret = B64_OK; - char *jsonStr = NULL; + OIC_LOG(INFO, TAG, "Crl object contain:"); + OIC_LOG_V(INFO, TAG, "id = %d", crl->CrlId); + OIC_LOG_V(INFO, TAG, "this update = %s", crl->ThisUpdate.data); - cJSON *jsonRoot = cJSON_CreateObject(); - VERIFY_NON_NULL(TAG, jsonRoot, ERROR); + OIC_LOG(INFO, TAG, "crl:"); + OIC_LOG_V(INFO, TAG, "encoding = %d", crl->CrlData.encoding); + OIC_LOG_V(INFO, TAG, "data (length = %zu):", crl->CrlData.len); + OIC_LOG_BUFFER(INFO, TAG, crl->CrlData.data, crl->CrlData.len); +} - cJSON *jsonCrl = NULL; - if(isIncResName) - { - jsonCrl = cJSON_CreateObject(); - VERIFY_NON_NULL(TAG, jsonCrl, ERROR); - cJSON_AddItemToObject(jsonRoot, OIC_JSON_CRL_NAME, jsonCrl); - } - else +static bool copyByteArray(const uint8_t *in, size_t in_len, uint8_t **out, size_t *out_len) +{ + OICFree(*out); + uint8_t *tmp = OICMalloc(in_len); + if (!tmp) { - jsonCrl = jsonRoot; + return false; } + memcpy(tmp, in, in_len); + *out = tmp; + *out_len = in_len; + return true; +} - //CRLId -- Mandatory - cJSON_AddNumberToObject(jsonCrl, OIC_JSON_CRL_ID, (int)crl->CrlId); +static bool copyCrl(const OicSecCrl_t *in, OicSecCrl_t *out) +{ + bool result = false; - //ThisUpdate -- Mandatory - outLen = 0; - base64CRLLen = B64ENCODE_OUT_SAFESIZE(crl->ThisUpdate.len); - base64Buff = OICMalloc(base64CRLLen); - b64Ret = b64Encode(crl->ThisUpdate.data, crl->ThisUpdate.len, base64Buff, - base64CRLLen, &outLen); - VERIFY_SUCCESS(TAG, b64Ret == B64_OK, ERROR); - cJSON_AddStringToObject(jsonCrl, OIC_JSON_CRL_THIS_UPDATE, base64Buff); - OICFree(base64Buff); + if (!in || !out) + { + OIC_LOG(ERROR, TAG, "in or out crl is NULL"); + return false; + } - //CRLData -- Mandatory - outLen = 0; - base64CRLLen = B64ENCODE_OUT_SAFESIZE(crl->CrlData.len); - base64Buff = OICMalloc(base64CRLLen); - b64Ret = b64Encode(crl->CrlData.data, crl->CrlData.len, base64Buff, - base64CRLLen, &outLen); - VERIFY_SUCCESS(TAG, b64Ret == B64_OK, ERROR); - cJSON_AddStringToObject(jsonCrl, OIC_JSON_CRL_DATA, base64Buff); + out->CrlId = in->CrlId; - jsonStr = cJSON_PrintUnformatted(jsonRoot); + result = copyByteArray(in->ThisUpdate.data, in->ThisUpdate.len, &out->ThisUpdate.data, &out->ThisUpdate.len); + if (!result) + { + OIC_LOG(ERROR, TAG, "Can't allocate memory for ThisUpdate"); + return false; + } -exit: - OICFree(base64Buff); - if (jsonRoot) + result = copyByteArray(in->CrlData.data, in->CrlData.len, &out->CrlData.data, &out->CrlData.len); + if (!result) { - cJSON_Delete(jsonRoot); + OIC_LOG(ERROR, TAG, "Can't allocate memory for CrlData"); + return false; } - return jsonStr; + + return result; } -OicSecCrl_t *JSONToCrlBin(const char * jsonStr, const bool isIncResName) +static CborError setPubDataType(CborEncoder *out, const char *name, const OicSecKey_t *value) { - if (NULL == jsonStr) + if (!out || !name || !value) { - return NULL; + OIC_LOG_V(ERROR, TAG, "%s: null input params", __func__); + return CborErrorInternalError; } - OCStackResult ret = OC_STACK_ERROR; - OicSecCrl_t *crl = NULL; - cJSON *jsonCrl = NULL; - cJSON *jsonObj = NULL; + CborEncoder map; - unsigned char *base64Buff = NULL; - uint32_t base64CRLLen = 0; - uint32_t outLen = 0; - B64Result b64Ret = B64_OK; + const char *encoding = NULL; + bool binary_field = false; - cJSON *jsonRoot = cJSON_Parse(jsonStr); - VERIFY_NON_NULL(TAG, jsonRoot, ERROR); + size_t mapSize = 0; - if(isIncResName) + mapSize++; + switch(value->encoding) { - jsonCrl = cJSON_GetObjectItem(jsonRoot, OIC_JSON_CRL_NAME); + case OIC_ENCODING_RAW: + binary_field = true; + encoding = OIC_SEC_ENCODING_RAW; + break; + case OIC_ENCODING_BASE64: + encoding = OIC_SEC_ENCODING_BASE64; + break; + case OIC_ENCODING_DER: + binary_field = true; + encoding = OIC_SEC_ENCODING_DER; + break; + case OIC_ENCODING_PEM: + encoding = OIC_SEC_ENCODING_PEM; + break; + default: + OIC_LOG(ERROR, TAG, "Received UNKNOWN encoding, exit!"); + return CborErrorInternalError; } - else + + if (value->data) { - jsonCrl = jsonRoot; + mapSize++; } - VERIFY_NON_NULL(TAG, jsonCrl, ERROR); - crl = (OicSecCrl_t *)OICCalloc(1, sizeof(OicSecCrl_t)); - VERIFY_NON_NULL(TAG, crl, ERROR); + CborError result = CborNoError; + result = cbor_encode_text_string(out, name, strlen(name)); + VERIFY_CBOR_SUCCESS(TAG, result, "Failed Adding name Tag."); - //CRLId -- Mandatory - jsonObj = cJSON_GetObjectItem(jsonCrl, OIC_JSON_CRL_ID); - if(jsonObj) + result = cbor_encoder_create_map(out, &map, mapSize); + VERIFY_CBOR_SUCCESS(TAG, result, "Failed creating name map"); + + if (encoding) + { + result = cbor_encode_text_string(&map, OIC_JSON_ENCODING_NAME, + strlen(OIC_JSON_ENCODING_NAME)); + VERIFY_CBOR_SUCCESS(TAG, result, "Failed to add encoding tag.") + result = cbor_encode_text_string(&map, encoding, strlen(encoding)); + VERIFY_CBOR_SUCCESS(TAG, result, "Failed to add encoding value."); + }; + + if (value->data) { - VERIFY_SUCCESS(TAG, cJSON_Number == jsonObj->type, ERROR); - crl->CrlId = (uint16_t)jsonObj->valueint; + result = cbor_encode_text_string(&map, OIC_JSON_DATA_NAME, strlen(OIC_JSON_DATA_NAME)); + VERIFY_CBOR_SUCCESS(TAG, result, "Failed to add data tag."); + if (binary_field) + { + result = cbor_encode_byte_string(&map, value->data, value->len); + } + else + { + result = cbor_encode_text_string(&map, (const char *)value->data, value->len); + } + VERIFY_CBOR_SUCCESS(TAG, result, "Failed to add data value."); } - else // PUT/POST JSON may not have CRLId so set it to the gCRList->CRLId + + result = cbor_encoder_close_container(out, &map); + VERIFY_CBOR_SUCCESS(TAG, result, "Failed Closing PrivateData Map."); + +exit: + return result; +} + +static CborError getPubDataType(CborValue *in, const char *name, OicSecKey_t *value) +{ + if (!in || !name || !value) { - VERIFY_NON_NULL(TAG, gCrl, ERROR); - crl->CrlId = gCrl->CrlId; + OIC_LOG_V(ERROR, TAG, "%s: null input params", __func__); + return CborErrorInternalError; } - //ThisUpdate -- Mandatory - jsonObj = cJSON_GetObjectItem(jsonCrl, OIC_JSON_CRL_THIS_UPDATE); - if(jsonObj) + CborError result = CborNoError; + char *encoding = NULL; + + CborValue crlNode = { .parser = NULL }; + result = cbor_value_map_find_value(in, name, &crlNode); + if (CborNoError == result && cbor_value_is_map(&crlNode)) { - VERIFY_SUCCESS(TAG, cJSON_String == jsonObj->type, ERROR); - if(cJSON_String == jsonObj->type) + CborValue crlMap = { .parser = NULL }; + result = cbor_value_enter_container(&crlNode, &crlMap); + + while(cbor_value_is_valid(&crlMap) && cbor_value_is_text_string(&crlMap)) { - //Check for empty string, in case ThisUpdate field has not been set yet - if (jsonObj->valuestring[0]) + char *property = NULL; + size_t length = 0; + result = cbor_value_dup_text_string(&crlMap, &property, &length, NULL); + VERIFY_CBOR_SUCCESS(TAG, result, "Failed Get first crl ojbject tag."); + result = cbor_value_advance(&crlMap); + VERIFY_CBOR_SUCCESS(TAG, result, "Failed to advance crlMap"); + + if (0 == strcmp(OIC_JSON_DATA_NAME, property)) + { + if (cbor_value_is_byte_string(&crlMap)) + { + result = cbor_value_dup_byte_string(&crlMap, &value->data, &value->len, NULL); + } + else if(cbor_value_is_text_string(&crlMap)) + { + char *buffer = NULL; + result = cbor_value_dup_text_string(&crlMap, &buffer, &value->len, NULL); + value->data = (uint8_t *)buffer; + } + else + { + result = CborErrorUnknownType; + OIC_LOG(ERROR, TAG, "Unknown type for crl->data."); + } + VERIFY_CBOR_SUCCESS(TAG, result, "Failed to read crl->data"); + } + else if (0 == strcmp(OIC_JSON_ENCODING_NAME, property)) { - base64CRLLen = B64ENCODE_OUT_SAFESIZE(strlen(jsonObj->valuestring)); - base64Buff = OICMalloc(base64CRLLen); - b64Ret = b64Decode(jsonObj->valuestring, strlen(jsonObj->valuestring), base64Buff, - base64CRLLen, &outLen); - VERIFY_SUCCESS(TAG, (b64Ret == B64_OK && outLen <= base64CRLLen), - ERROR); - crl->ThisUpdate.data = OICMalloc(outLen + 1); - memcpy(crl->ThisUpdate.data, base64Buff, outLen); - crl->ThisUpdate.len = outLen; - OICFree(base64Buff); - base64Buff = NULL; + size_t encoding_len = 0; + result = cbor_value_dup_text_string(&crlMap, &encoding, &encoding_len, NULL); + VERIFY_CBOR_SUCCESS(TAG, result, "Failed to read crl->encdoing"); } + OICFree(property); } } - else // PUT/POST JSON will not have ThisUpdate so set it to the gCRList->ThisUpdate + VERIFY_CBOR_SUCCESS(TAG, result, "Failed to find root node"); + + if (encoding) { - VERIFY_NON_NULL(TAG, gCrl, ERROR); - outLen = gCrl->ThisUpdate.len; - crl->ThisUpdate.data = OICMalloc(outLen + 1); - memcpy(crl->ThisUpdate.data, gCrl->ThisUpdate.data, outLen); - crl->ThisUpdate.len = outLen; + OicEncodingType_t type = OIC_ENCODING_UNKNOW; + if (0 == strcmp(encoding, OIC_SEC_ENCODING_BASE64)) type = OIC_ENCODING_BASE64; + else if (0 == strcmp(encoding, OIC_SEC_ENCODING_DER)) type = OIC_ENCODING_DER; + else if (0 == strcmp(encoding, OIC_SEC_ENCODING_PEM)) type = OIC_ENCODING_PEM; + else if (0 == strcmp(encoding, OIC_SEC_ENCODING_RAW)) type = OIC_ENCODING_RAW; + + value->encoding = type; } +exit: + return result; +} + +OCStackResult CrlToCBORPayload(const OicSecCrl_t *crl, uint8_t **payload, size_t *size, char *lastUpdate) +{ + if (NULL == crl || NULL == payload || NULL != *payload || NULL == size) + { + return OC_STACK_INVALID_PARAM; + } + + size_t cborLen = *size; + if (0 == cborLen) + { + cborLen = CBOR_SIZE; + } + + *payload = NULL; + *size = 0; + + size_t mapSize = CRL_MAP_SIZE; + if (lastUpdate) + { + mapSize++; + } + + printCrl(crl); + + OCStackResult ret = OC_STACK_ERROR; + + CborEncoder encoder; + CborEncoder crlMap; + + CborError cborEncoderResult = CborNoError; + + uint8_t *outPayload = (uint8_t *)OICCalloc(1, cborLen); + VERIFY_NON_NULL(TAG, outPayload, ERROR); + cbor_encoder_init(&encoder, outPayload, cborLen, 0); + + cborEncoderResult = cbor_encoder_create_map(&encoder, &crlMap, mapSize); + VERIFY_CBOR_SUCCESS(TAG, cborEncoderResult, "Failed to create CRL Map"); + + //CRLId -- Mandatory + cborEncoderResult = cbor_encode_text_string(&crlMap, OC_RSRVD_CRL_ID, + strlen(OC_RSRVD_CRL_ID)); + VERIFY_CBOR_SUCCESS(TAG, cborEncoderResult, "Failed to add CRL ID"); + cborEncoderResult = cbor_encode_int(&crlMap, crl->CrlId); + VERIFY_CBOR_SUCCESS(TAG, cborEncoderResult, "Failed to add CRL Id value"); + + //ThisUpdate -- Mandatory + cborEncoderResult = cbor_encode_text_string(&crlMap, OC_RSRVD_THIS_UPDATE, + strlen(OC_RSRVD_THIS_UPDATE)); + VERIFY_CBOR_SUCCESS(TAG, cborEncoderResult, "Failed to add Crl update"); + cborEncoderResult = cbor_encode_text_string(&crlMap, (const char *)crl->ThisUpdate.data, + crl->ThisUpdate.len); + VERIFY_CBOR_SUCCESS(TAG, cborEncoderResult, "Failed to add Crl Update value"); //CRLData -- Mandatory - jsonObj = cJSON_GetObjectItem(jsonCrl, OIC_JSON_CRL_DATA); - if(jsonObj) + cborEncoderResult = setPubDataType(&crlMap, OC_RSRVD_CRL, &crl->CrlData); + VERIFY_CBOR_SUCCESS(TAG, cborEncoderResult, "Failed to add CRLData object"); + + //lastUpdate - internal field + if (lastUpdate) { - VERIFY_SUCCESS(TAG, cJSON_String == jsonObj->type, ERROR); - if(cJSON_String == jsonObj->type) + cborEncoderResult = cbor_encode_text_string(&crlMap, OC_RSRVD_LAST_UPDATE, + strlen(OC_RSRVD_LAST_UPDATE)); + VERIFY_CBOR_SUCCESS(TAG, cborEncoderResult, "Failed to add last Update tag"); + cborEncoderResult = cbor_encode_text_string(&crlMap, lastUpdate, strlen(lastUpdate)); + VERIFY_CBOR_SUCCESS(TAG, cborEncoderResult, "Failed to add last Update value"); + } + + cborEncoderResult = cbor_encoder_close_container(&encoder, &crlMap); + VERIFY_CBOR_SUCCESS(TAG, cborEncoderResult, "Failed to add close Crl map"); + + *size = cbor_encoder_get_buffer_size(&encoder, outPayload); + *payload = outPayload; + ret = OC_STACK_OK; + +exit: + if ((CborNoError != cborEncoderResult) || (OC_STACK_OK != ret)) + { + OICFree(outPayload); + outPayload = NULL; + *payload = NULL; + *size = 0; + ret = OC_STACK_ERROR; + if ((CborErrorOutOfMemory == cborEncoderResult) && (cborLen < CBOR_MAX_SIZE)) { - //Check for empty string, in case CRLData field has not been set yet - if (jsonObj->valuestring[0]) - { - outLen = 0; - base64CRLLen = B64ENCODE_OUT_SAFESIZE(strlen(jsonObj->valuestring)); - base64Buff = OICMalloc(base64CRLLen); - b64Ret = b64Decode(jsonObj->valuestring, strlen(jsonObj->valuestring), base64Buff, - base64CRLLen, &outLen); - VERIFY_SUCCESS(TAG, (b64Ret == B64_OK && outLen <= base64CRLLen), - ERROR); - crl->CrlData.data = OICMalloc(outLen + 1); - memcpy(crl->CrlData.data, base64Buff, outLen); - crl->CrlData.len = outLen; - OICFree(base64Buff); - base64Buff = NULL; - } + // Since the allocated initial memory failed, double the memory. + cborLen += cbor_encoder_get_buffer_size(&encoder, encoder.end); + cborEncoderResult = CborNoError; + ret = CrlToCBORPayload(crl, payload, &cborLen, lastUpdate); } } - else // PUT/POST JSON will not have CRLData so set it to the gCRList->CRLData + + return ret; +} + +OCStackResult CBORPayloadToCrl(const uint8_t *cborPayload, const size_t size, + OicSecCrl_t **secCrl) +{ + if (NULL == cborPayload || NULL == secCrl || NULL != *secCrl || 0 == size) { - VERIFY_NON_NULL(TAG, gCrl, ERROR); - outLen = gCrl->CrlData.len; - crl->CrlData.data = OICMalloc(outLen + 1); - memcpy(crl->CrlData.data, gCrl->CrlData.data, outLen); - crl->CrlData.len = outLen; + return OC_STACK_INVALID_PARAM; } + OCStackResult ret = OC_STACK_ERROR; + OicSecCrl_t *crl = NULL; + + CborValue crlCbor = {.parser = NULL}; + CborParser parser = {.end = NULL}; + CborError cborFindResult = CborNoError; + + cbor_parser_init(cborPayload, size, 0, &parser, &crlCbor); + CborValue crlMap = { .parser = NULL}; + cborFindResult = cbor_value_enter_container(&crlCbor, &crlMap); + VERIFY_CBOR_SUCCESS(TAG, cborFindResult, "Failed to enter Crl map"); + + crl = (OicSecCrl_t *)OICCalloc(1, sizeof(OicSecCrl_t)); + VERIFY_NON_NULL(TAG, crl, ERROR); + + cborFindResult = cbor_value_map_find_value(&crlCbor, OC_RSRVD_CRL_ID, &crlMap); + if (CborNoError == cborFindResult && cbor_value_is_integer(&crlMap)) + { + int CrlId; + + cborFindResult = cbor_value_get_int(&crlMap, &CrlId); + VERIFY_CBOR_SUCCESS(TAG, cborFindResult, "Failed Finding CrlId."); + crl->CrlId = (uint16_t)CrlId; + } + + cborFindResult = cbor_value_map_find_value(&crlCbor, OC_RSRVD_THIS_UPDATE, &crlMap); + if (CborNoError == cborFindResult && cbor_value_is_text_string(&crlMap)) + { + cborFindResult = cbor_value_dup_text_string(&crlMap, + (char **)&crl->ThisUpdate.data, &crl->ThisUpdate.len, NULL); + VERIFY_CBOR_SUCCESS(TAG, cborFindResult, "Failed Advancing Byte Array."); + } + + cborFindResult = getPubDataType(&crlCbor, OC_RSRVD_CRL, &crl->CrlData); + VERIFY_CBOR_SUCCESS(TAG, cborFindResult, "Failed to read CRL."); + + printCrl(crl); + + *secCrl = crl; ret = OC_STACK_OK; exit: - cJSON_Delete(jsonRoot); - OICFree(base64Buff); - base64Buff = NULL; - if (OC_STACK_OK != ret) + if (CborNoError != cborFindResult) { - DeleteCrlBinData(crl); - crl = NULL; + // PUT/POST CBOR may not have mandatory values set default values. + OIC_LOG (DEBUG, TAG, "Set default values"); + + if (copyCrl(gCrl, crl)) + { + *secCrl = crl; + ret = OC_STACK_OK; + } + else + { + DeleteCrl(crl); + crl = NULL; + ret = OC_STACK_ERROR; + OIC_LOG (ERROR, TAG, "Can't set default crl"); + } } - return crl; + return ret; } -OCStackResult UpdateCRLResource(const OicSecCrl_t *crl) +static void getCurrentUTCTime(char *out, size_t len) { - char *jsonStr = NULL; - OCStackResult res = OC_STACK_ERROR; + //TODO: how to implement it in cross-platform way? + time_t rawtime; + struct tm * timeinfo = NULL; + + time ( &rawtime ); + timeinfo = localtime ( &rawtime ); - jsonStr = BinToCrlJSON((OicSecCrl_t *) crl, true); - if (!jsonStr) + if (NULL == timeinfo) { - return OC_STACK_ERROR; + return; } - cJSON *jsonObj = cJSON_Parse(jsonStr); - OICFree(jsonStr); + snprintf(out, len, "%04d%02d%02d%02d%02d%02d", + timeinfo->tm_year + 1900, timeinfo->tm_mon + 1, timeinfo->tm_mday, + timeinfo->tm_hour, timeinfo->tm_min, timeinfo->tm_sec); +} + +OCStackResult UpdateCRLResource(OicSecCrl_t *crl) +{ + static uint16_t crlid = 0; + uint8_t *payload = NULL; + size_t size = 0; + + crl->CrlId = crlid++; - if (jsonObj == NULL) + if (!copyCrl(crl, gCrl)) { + OIC_LOG(ERROR, TAG, "Can't update global crl"); return OC_STACK_ERROR; } - res = UpdateSVRDatabase(OIC_JSON_CRL_NAME, jsonObj); - cJSON_Delete(jsonObj); + char currentTime[32] = {0}; + getCurrentUTCTime(currentTime, sizeof(currentTime)); + + OCStackResult res = CrlToCBORPayload((const OicSecCrl_t *) crl, &payload, &size, currentTime); + if (OC_STACK_OK != res) + { + return res; + } - return res; + return UpdateSecureResourceInPS(OIC_CBOR_CRL_NAME, payload, size); } static OCEntityHandlerResult HandleCRLPostRequest(const OCEntityHandlerRequest *ehRequest) { OCEntityHandlerResult ehRet = OC_EH_ERROR; + OicSecCrl_t *crl = NULL; + uint8_t *payload = ((OCSecurityPayload *)ehRequest->payload)->securityData; + size_t size = ((OCSecurityPayload *) ehRequest->payload)->payloadSize; - char *jsonCRL = (char *)(((OCSecurityPayload *)ehRequest->payload)->securityData); - - if (jsonCRL) + if (payload) { - OC_LOG(INFO, TAG, "UpdateSVRDB..."); - OC_LOG_V(INFO, TAG, "crl: \"%s\"", jsonCRL); + OIC_LOG(INFO, TAG, "Update SVR DB..."); + CBORPayloadToCrl(payload, size, &crl); + VERIFY_NON_NULL(TAG, crl, ERROR); - cJSON *jsonObj = cJSON_Parse(jsonCRL); - OicSecCrl_t *crl = NULL; - crl = JSONToCrlBin(jsonCRL, false); - if (!crl) + if (OC_STACK_OK == UpdateCRLResource(crl)) { - OC_LOG(ERROR, TAG, "Error JSONToCrlBin"); - } - - gCrl->CrlId = crl->CrlId; - - OICFree(gCrl->ThisUpdate.data); - gCrl->ThisUpdate.data = NULL; - gCrl->ThisUpdate.data = OICMalloc(crl->ThisUpdate.len); - memcpy(gCrl->ThisUpdate.data, crl->ThisUpdate.data, crl->ThisUpdate.len); - gCrl->ThisUpdate.len = crl->ThisUpdate.len; - - OICFree(gCrl->CrlData.data); - gCrl->CrlData.data = NULL; - gCrl->CrlData.data = OICMalloc(crl->CrlData.len); - memcpy(gCrl->CrlData.data, crl->CrlData.data, crl->CrlData.len); - gCrl->CrlData.len = crl->CrlData.len; - - if (OC_STACK_OK == UpdateSVRDatabase(OIC_JSON_CRL_NAME, jsonObj)) - { - OC_LOG(INFO, TAG, "UpdateSVRDB == OK"); ehRet = OC_EH_RESOURCE_CREATED; } - DeleteCrlBinData(crl); - cJSON_Delete(jsonObj); - + DeleteCrl(crl); } +exit: // Send payload to request originator - SendSRMResponse(ehRequest, ehRet, NULL); + if (OC_STACK_OK != SendSRMResponse(ehRequest, ehRet, NULL, 0)) + { + ehRet = OC_EH_ERROR; + OIC_LOG(ERROR, TAG, "SendSRMResponse failed in HandleCRLPostRequest"); + } - OC_LOG_V(INFO, TAG, "%s RetVal %d", __func__, ehRet); + OIC_LOG_V(INFO, TAG, "%s RetVal %d", __func__, ehRet); return ehRet; } -/* +/** * This internal method is the entity handler for CRL resource and * will handle REST request (GET/PUT/POST/DEL) for them. */ -OCEntityHandlerResult CRLEntityHandler(OCEntityHandlerFlag flag, - OCEntityHandlerRequest *ehRequest, - void *callbackParameter) +static OCEntityHandlerResult CRLEntityHandler(OCEntityHandlerFlag flag, + OCEntityHandlerRequest *ehRequest, + void *callbackParameter) { OCEntityHandlerResult ehRet = OC_EH_ERROR; (void)callbackParameter; @@ -349,16 +546,16 @@ OCEntityHandlerResult CRLEntityHandler(OCEntityHandlerFlag flag, return ehRet; } - OC_LOG(INFO, TAG, "Handle CRL resource"); + OIC_LOG(INFO, TAG, "Handle CRL resource"); if (flag & OC_REQUEST_FLAG) { // TODO : Handle PUT and DEL methods - OC_LOG (INFO, TAG, "Flag includes OC_REQUEST_FLAG"); + OIC_LOG (INFO, TAG, "Flag includes OC_REQUEST_FLAG"); switch (ehRequest->method) { case OC_REST_GET: - OC_LOG (INFO, TAG, "Not implemented request method."); + OIC_LOG (INFO, TAG, "Not implemented request method."); //ehRet = HandleCRLGetRequest(ehRequest); break; @@ -368,53 +565,64 @@ OCEntityHandlerResult CRLEntityHandler(OCEntityHandlerFlag flag, default: ehRet = OC_EH_ERROR; - SendSRMResponse(ehRequest, ehRet, NULL); + SendSRMResponse(ehRequest, ehRet, NULL, 0); } } return ehRet; } -/* +/** * This internal method is used to create '/oic/sec/crl' resource. */ -OCStackResult CreateCRLResource() +static OCStackResult CreateCRLResource() { - OCStackResult ret; - ret = OCCreateResource(&gCrlHandle, - OIC_RSRC_TYPE_SEC_CRL, - OIC_MI_DEF, - OIC_RSRC_CRL_URI, - CRLEntityHandler, - NULL, - OC_OBSERVABLE); + OCStackResult ret = OCCreateResource(&gCrlHandle, + OIC_RSRC_TYPE_SEC_CRL, + OC_RSRVD_INTERFACE_DEFAULT, + OIC_RSRC_CRL_URI, + CRLEntityHandler, + NULL, + OC_OBSERVABLE); if (OC_STACK_OK != ret) { - OC_LOG(FATAL, TAG, "Unable to instantiate CRL resource"); + OIC_LOG(FATAL, TAG, "Unable to instantiate CRL resource"); DeInitCRLResource(); } return ret; } /** - * Get the default value - * @retval NULL for now. Update it when we finalize the default info. + * Get the default value. + * @return defaultCrl for now. */ static OicSecCrl_t *GetCrlDefault() { - OicSecCrl_t *defaultCrl = NULL; - defaultCrl = (OicSecCrl_t *)OICCalloc(1, sizeof(OicSecCrl_t)); + OicSecCrl_t *defaultCrl = (OicSecCrl_t *)OICCalloc(1, sizeof(OicSecCrl_t)); + if (NULL == defaultCrl) + { + return NULL; + } defaultCrl->CrlId = CRL_DEFAULT_CRL_ID; + defaultCrl->CrlData.encoding = OIC_ENCODING_DER; + + bool result1 = copyByteArray((const uint8_t *)CRL_DEFAULT_CRL_DATA, + strlen(CRL_DEFAULT_CRL_DATA), + &defaultCrl->CrlData.data, + &defaultCrl->CrlData.len); - defaultCrl->CrlData.len = strlen(CRL_DEFAULT_CRL_DATA); - defaultCrl->CrlData.data = OICMalloc(defaultCrl->CrlData.len); - memcpy(defaultCrl->CrlData.data, CRL_DEFAULT_CRL_DATA, defaultCrl->CrlData.len); + bool result2 = copyByteArray((const uint8_t *)CRL_DEFAULT_THIS_UPDATE, + strlen(CRL_DEFAULT_THIS_UPDATE), + &defaultCrl->ThisUpdate.data, + &defaultCrl->ThisUpdate.len); - defaultCrl->ThisUpdate.len = strlen(CRL_DEFAULT_THIS_UPDATE); - defaultCrl->ThisUpdate.data = OICMalloc(defaultCrl->ThisUpdate.len); - memcpy(defaultCrl->ThisUpdate.data, CRL_DEFAULT_THIS_UPDATE, defaultCrl->ThisUpdate.len); + if (!result1 || !result2) + { + DeleteCrl(defaultCrl); + return NULL; + } return defaultCrl; } @@ -429,40 +637,46 @@ static OicSecCrl_t *GetCrlDefault() OCStackResult InitCRLResource() { OCStackResult ret = OC_STACK_ERROR; - char* jsonSVRDatabase; - - //Read CRL resource from PS - jsonSVRDatabase = GetSVRDatabase(); - - if (jsonSVRDatabase) + // Read Crl resource from PS + uint8_t *data = NULL; + size_t size = 0; + ret = GetSecureVirtualDatabaseFromPS(OIC_CBOR_CRL_NAME, &data, &size); + // If database read failed + if (OC_STACK_OK != ret) + { + OIC_LOG (DEBUG, TAG, "ReadSVDataFromPS failed"); + } + if (data) { - //Convert JSON CRL into binary format - gCrl = JSONToCrlBin(jsonSVRDatabase, true); + // Read ACL resource from PS + ret = CBORPayloadToCrl(data, size, &gCrl); } + /* * If SVR database in persistent storage got corrupted or * is not available for some reason, a default CrlResource is created * which allows user to initiate CrlResource provisioning again. */ - if (!jsonSVRDatabase || !gCrl) + if ((OC_STACK_OK != ret) || !data || !gCrl) { gCrl = GetCrlDefault(); } ret = CreateCRLResource(); - OICFree(jsonSVRDatabase); + OICFree(data); return ret; } /** * Perform cleanup for ACL resources. */ -void DeInitCRLResource() +OCStackResult DeInitCRLResource() { - OCDeleteResource(gCrlHandle); + OCStackResult result = OCDeleteResource(gCrlHandle); gCrlHandle = NULL; - DeleteCrlBinData(gCrl); + DeleteCrl(gCrl); gCrl = NULL; + return result; } OicSecCrl_t *GetCRLResource() @@ -470,71 +684,140 @@ OicSecCrl_t *GetCRLResource() OicSecCrl_t *crl = NULL; //Read CRL resource from PS - char* jsonSVRDatabase = GetSVRDatabase(); - - if (jsonSVRDatabase) + uint8_t *data = NULL; + size_t size = 0; + OCStackResult ret = GetSecureVirtualDatabaseFromPS(OIC_CBOR_CRL_NAME, &data, &size); + if (data) { - //Convert JSON CRL into binary format - crl = JSONToCrlBin(jsonSVRDatabase, true); + //Convert CBOR CRL into binary format + ret = CBORPayloadToCrl(data, size, &crl); } /* * If SVR database in persistent storage got corrupted or * is not available for some reason, a default CrlResource is created * which allows user to initiate CrlResource provisioning again. */ - if (!jsonSVRDatabase || !crl) + if ((OC_STACK_OK != ret) || !data || !crl) { crl = GetCrlDefault(); } - OICFree(jsonSVRDatabase); + OICFree(data); return crl; } -char *GetBase64CRL() +OCStackResult getLastUpdateFromDB(char **lastUpdate) { - cJSON *jsonCrl = NULL; - cJSON *jsonObj = NULL; - char *jsonSVRDatabase = GetSVRDatabase(); - char* ret = NULL; + OCStackResult result = OC_STACK_OK; - cJSON *jsonRoot = cJSON_Parse(jsonSVRDatabase); - VERIFY_NON_NULL(TAG, jsonRoot, ERROR); + OCPayload *payload = NULL; + uint8_t *data = NULL; + size_t size = 0; - jsonCrl = cJSON_GetObjectItem(jsonRoot, OIC_JSON_CRL_NAME); - VERIFY_NON_NULL(TAG, jsonCrl, ERROR); + if (!lastUpdate) + { + return OC_STACK_INVALID_PARAM; + } - //CRLData -- Mandatory - jsonObj = cJSON_GetObjectItem(jsonCrl, OIC_JSON_CRL_DATA); - if(jsonObj) + result = GetSecureVirtualDatabaseFromPS(OIC_CBOR_CRL_NAME, &data, &size); + if (result != OC_STACK_OK) { - VERIFY_SUCCESS(TAG, cJSON_String == jsonObj->type, ERROR); - if(cJSON_String == jsonObj->type) - { - //Check for empty string, in case CRLData field has not been set yet - if (jsonObj->valuestring[0]) - { - ret = jsonObj->valuestring; - } - } + OIC_LOG(ERROR, TAG, "Can't get crl data from database"); + goto exit; } + + result = OCParsePayload(&payload, PAYLOAD_TYPE_REPRESENTATION, data, size); + if (result != OC_STACK_OK) + { + OIC_LOG(ERROR, TAG, "Can't parse cbor data from DB"); + goto exit; + } + + if (!OCRepPayloadGetPropString((const OCRepPayload*)payload, OC_RSRVD_LAST_UPDATE, lastUpdate)) + { + OIC_LOG_V(ERROR, TAG, "Can't get: %s", OC_RSRVD_LAST_UPDATE); + result = OC_STACK_ERROR; + } + exit: - OICFree(jsonSVRDatabase); - cJSON_Delete(jsonRoot); - return ret; + if (result != OC_STACK_OK) + { + OIC_LOG(DEBUG, TAG, "Assume you are first time get Crl, and it can be absent in database"); + OIC_LOG_V(DEBUG, TAG, "Return default last update time %s", CRL_DEFAULT_LAST_UPDATE); + + *lastUpdate = OICStrdup(CRL_DEFAULT_LAST_UPDATE); + result = OC_STACK_OK; + } + OCPayloadDestroy((OCPayload *)payload); + + return result; } -void GetDerCrl(ByteArray crlArray) +uint8_t *GetCrl() { - OicSecCrl_t * crlRes = GetCRLResource(); - if (crlRes && crlRes->CrlData.len <= crlArray.len) + uint8_t *data = NULL; + size_t size = 0; + OicSecCrl_t *crl = NULL; + if (OC_STACK_OK == GetSecureVirtualDatabaseFromPS(OIC_CBOR_CRL_NAME, &data, &size) && data && + OC_STACK_OK == CBORPayloadToCrl(data, size, &crl)) + { + return crl->CrlData.data; + } + return NULL; +} + +void GetDerCrl(ByteArray_t* out) +{ + if(NULL == out) + { + return; + } + + OicSecCrl_t *crlRes = GetCRLResource(); + + if(NULL == crlRes) + { + return; + } + + OicSecKey_t *crl = &crlRes->CrlData; + + if (OIC_ENCODING_BASE64 == crl->encoding) + { + size_t outSize = B64DECODE_OUT_SAFESIZE((crl->len + 1)); + uint8_t *out = OICCalloc(1, outSize); + if (!out) + { + OIC_LOG(ERROR, TAG, "Can't allocate memory for base64 str"); + return; + } + uint32_t len = 0; + + if(B64_OK == b64Decode((char*)crl->data, crl->len, out, outSize, &len)) + { + memcpy(crl->data, out, len); + crl->len = (size_t)len; + + OIC_LOG (ERROR, TAG, "Crl successfully decoded to base64."); + } + else + { + OIC_LOG (ERROR, TAG, "Base64 decoding failed."); + } + OICFree(out); + } + + out->len = 0; + + out->data = OICRealloc(out->data, crl->len); + if (out->data) { - memcpy(crlArray.data, crlRes->CrlData.data, crlRes->CrlData.len); - crlArray.len = crlRes->CrlData.len; + memcpy(out->data, crl->data, crl->len); + out->len = crl->len; } else { - crlArray.len = 0; + OIC_LOG(ERROR, TAG, "Can't allocate memory for out->data"); } - DeleteCrlBinData(crlRes); + DeleteCrl(crlRes); }