1 //******************************************************************
3 // Copyright 2015 Samsung Electronics All Rights Reserved.
5 //-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
7 // Licensed under the Apache License, Version 2.0 (the "License");
8 // you may not use this file except in compliance with the License.
9 // You may obtain a copy of the License at
11 // http://www.apache.org/licenses/LICENSE-2.0
13 // Unless required by applicable law or agreed to in writing, software
14 // distributed under the License is distributed on an "AS IS" BASIS,
15 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16 // See the License for the specific language governing permissions and
17 // limitations under the License.
19 //-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
22 #include "payload_logging.h"
23 #include "psinterface.h"
24 #include "resourcemanager.h"
25 #include "srmresourcestrings.h"
26 #include "srmutility.h"
27 #include "doxmresource.h"
28 #include "ocpayload.h"
29 #include "oic_malloc.h"
30 #include "oic_string.h"
31 #include "crlresource.h"
32 #include "ocpayloadcbor.h"
39 #define SEPARATOR_LEN (1)
40 #define CBOR_CRL_NAME "\"CRL\""
41 #define CBOR_CRL_NAME_LEN (5)
42 #define OIC_CBOR_CRL_NAME "crl"
43 #define OIC_CBOR_CRL_ID "CRLId"
44 #define OIC_CBOR_CRL_THIS_UPDATE "ThisUpdate"
45 #define OIC_CBOR_CRL_DATA "CRLData"
46 #define CRL_DEFAULT_CRL_ID (1)
47 #define CRL_DEFAULT_THIS_UPDATE "150101000000Z"
48 #define CRL_DEFAULT_LAST_UPDATE "20150701000000"
49 #define CRL_DEFAULT_CRL_DATA "-"
50 #define CRL_MAP_SIZE (3)
52 static OCResourceHandle gCrlHandle = NULL;
53 static OicSecCrl_t *gCrl = NULL;
55 /** Default cbor payload size. This value is increased in case of CborErrorOutOfMemory.
56 * The value of payload size is increased until reaching below max cbor size. */
57 static const uint16_t CBOR_SIZE = 1024;
59 // Max cbor size payload.
60 static const uint16_t CBOR_MAX_SIZE = 4400;
62 void DeleteCrl(OicSecCrl_t *crl)
67 OICFree(crl->ThisUpdate.data);
70 OICFree(crl->CrlData.data);
77 void printCrl(OicSecCrl_t *crl)
81 OIC_LOG(INFO, TAG, "Received NULL CRL");
85 OIC_LOG(INFO, TAG, "Crl object contain:");
86 OIC_LOG_V(INFO, TAG, "id = %d", crl->CrlId);
87 OIC_LOG_V(INFO, TAG, "this update = %s", crl->ThisUpdate.data);
89 OIC_LOG(INFO, TAG, "crl:");
90 OIC_LOG_V(INFO, TAG, "encoding = %d", crl->CrlData.encoding);
91 OIC_LOG_V(INFO, TAG, "data (length = %zu):", crl->CrlData.len);
92 OIC_LOG_BUFFER(INFO, TAG, crl->CrlData.data, crl->CrlData.len);
95 static bool copyByteArray(const uint8_t *in, size_t in_len, uint8_t **out, size_t *out_len)
98 uint8_t *tmp = OICMalloc(in_len);
103 memcpy(tmp, in, in_len);
109 static bool copyCrl(const OicSecCrl_t *in, OicSecCrl_t *out)
115 OIC_LOG(ERROR, TAG, "in or out crl is NULL");
119 out->CrlId = in->CrlId;
121 result = copyByteArray(in->ThisUpdate.data, in->ThisUpdate.len, &out->ThisUpdate.data, &out->ThisUpdate.len);
124 OIC_LOG(ERROR, TAG, "Can't allocate memory for ThisUpdate");
128 result = copyByteArray(in->CrlData.data, in->CrlData.len, &out->CrlData.data, &out->CrlData.len);
131 OIC_LOG(ERROR, TAG, "Can't allocate memory for CrlData");
138 static CborError setPubDataType(CborEncoder *out, const char *name, const OicSecKey_t *value)
140 if (!out || !name || !value)
142 OIC_LOG_V(ERROR, TAG, "%s: null input params", __func__);
143 return CborErrorInternalError;
148 const char *encoding = NULL;
149 bool binary_field = false;
154 switch(value->encoding)
156 case OIC_ENCODING_RAW:
158 encoding = OIC_SEC_ENCODING_RAW;
160 case OIC_ENCODING_BASE64:
161 encoding = OIC_SEC_ENCODING_BASE64;
163 case OIC_ENCODING_DER:
165 encoding = OIC_SEC_ENCODING_DER;
167 case OIC_ENCODING_PEM:
168 encoding = OIC_SEC_ENCODING_PEM;
171 OIC_LOG(ERROR, TAG, "Received UNKNOWN encoding, exit!");
172 return CborErrorInternalError;
180 CborError result = CborNoError;
181 result = cbor_encode_text_string(out, name, strlen(name));
182 VERIFY_CBOR_SUCCESS(TAG, result, "Failed Adding name Tag.");
184 result = cbor_encoder_create_map(out, &map, mapSize);
185 VERIFY_CBOR_SUCCESS(TAG, result, "Failed creating name map");
189 result = cbor_encode_text_string(&map, OIC_JSON_ENCODING_NAME,
190 strlen(OIC_JSON_ENCODING_NAME));
191 VERIFY_CBOR_SUCCESS(TAG, result, "Failed to add encoding tag.")
192 result = cbor_encode_text_string(&map, encoding, strlen(encoding));
193 VERIFY_CBOR_SUCCESS(TAG, result, "Failed to add encoding value.");
198 result = cbor_encode_text_string(&map, OIC_JSON_DATA_NAME, strlen(OIC_JSON_DATA_NAME));
199 VERIFY_CBOR_SUCCESS(TAG, result, "Failed to add data tag.");
202 result = cbor_encode_byte_string(&map, value->data, value->len);
206 result = cbor_encode_text_string(&map, (const char *)value->data, value->len);
208 VERIFY_CBOR_SUCCESS(TAG, result, "Failed to add data value.");
211 result = cbor_encoder_close_container(out, &map);
212 VERIFY_CBOR_SUCCESS(TAG, result, "Failed Closing PrivateData Map.");
218 static CborError getPubDataType(CborValue *in, const char *name, OicSecKey_t *value)
220 if (!in || !name || !value)
222 OIC_LOG_V(ERROR, TAG, "%s: null input params", __func__);
223 return CborErrorInternalError;
226 CborError result = CborNoError;
227 char *encoding = NULL;
229 CborValue crlNode = { .parser = NULL };
230 result = cbor_value_map_find_value(in, name, &crlNode);
231 if (CborNoError == result && cbor_value_is_map(&crlNode))
233 CborValue crlMap = { .parser = NULL };
234 result = cbor_value_enter_container(&crlNode, &crlMap);
236 while(cbor_value_is_valid(&crlMap) && cbor_value_is_text_string(&crlMap))
238 char *property = NULL;
240 result = cbor_value_dup_text_string(&crlMap, &property, &length, NULL);
241 VERIFY_CBOR_SUCCESS(TAG, result, "Failed Get first crl ojbject tag.");
242 result = cbor_value_advance(&crlMap);
243 VERIFY_CBOR_SUCCESS(TAG, result, "Failed to advance crlMap");
245 if (0 == strcmp(OIC_JSON_DATA_NAME, property))
247 if (cbor_value_is_byte_string(&crlMap))
249 result = cbor_value_dup_byte_string(&crlMap, &value->data, &value->len, NULL);
251 else if(cbor_value_is_text_string(&crlMap))
254 result = cbor_value_dup_text_string(&crlMap, &buffer, &value->len, NULL);
255 value->data = (uint8_t *)buffer;
259 result = CborErrorUnknownType;
260 OIC_LOG(ERROR, TAG, "Unknown type for crl->data.");
262 VERIFY_CBOR_SUCCESS(TAG, result, "Failed to read crl->data");
264 else if (0 == strcmp(OIC_JSON_ENCODING_NAME, property))
266 size_t encoding_len = 0;
267 result = cbor_value_dup_text_string(&crlMap, &encoding, &encoding_len, NULL);
268 VERIFY_CBOR_SUCCESS(TAG, result, "Failed to read crl->encdoing");
273 VERIFY_CBOR_SUCCESS(TAG, result, "Failed to find root node");
277 OicEncodingType_t type = OIC_ENCODING_UNKNOW;
278 if (0 == strcmp(encoding, OIC_SEC_ENCODING_BASE64)) type = OIC_ENCODING_BASE64;
279 else if (0 == strcmp(encoding, OIC_SEC_ENCODING_DER)) type = OIC_ENCODING_DER;
280 else if (0 == strcmp(encoding, OIC_SEC_ENCODING_PEM)) type = OIC_ENCODING_PEM;
281 else if (0 == strcmp(encoding, OIC_SEC_ENCODING_RAW)) type = OIC_ENCODING_RAW;
283 value->encoding = type;
289 OCStackResult CrlToCBORPayload(const OicSecCrl_t *crl, uint8_t **payload, size_t *size, char *lastUpdate)
291 if (NULL == crl || NULL == payload || NULL != *payload || NULL == size)
293 return OC_STACK_INVALID_PARAM;
296 size_t cborLen = *size;
305 size_t mapSize = CRL_MAP_SIZE;
313 OCStackResult ret = OC_STACK_ERROR;
318 CborError cborEncoderResult = CborNoError;
320 uint8_t *outPayload = (uint8_t *)OICCalloc(1, cborLen);
321 VERIFY_NON_NULL(TAG, outPayload, ERROR);
322 cbor_encoder_init(&encoder, outPayload, cborLen, 0);
324 cborEncoderResult = cbor_encoder_create_map(&encoder, &crlMap, mapSize);
325 VERIFY_CBOR_SUCCESS(TAG, cborEncoderResult, "Failed to create CRL Map");
328 cborEncoderResult = cbor_encode_text_string(&crlMap, OC_RSRVD_CRL_ID,
329 strlen(OC_RSRVD_CRL_ID));
330 VERIFY_CBOR_SUCCESS(TAG, cborEncoderResult, "Failed to add CRL ID");
331 cborEncoderResult = cbor_encode_int(&crlMap, crl->CrlId);
332 VERIFY_CBOR_SUCCESS(TAG, cborEncoderResult, "Failed to add CRL Id value");
334 //ThisUpdate -- Mandatory
335 cborEncoderResult = cbor_encode_text_string(&crlMap, OC_RSRVD_THIS_UPDATE,
336 strlen(OC_RSRVD_THIS_UPDATE));
337 VERIFY_CBOR_SUCCESS(TAG, cborEncoderResult, "Failed to add Crl update");
338 cborEncoderResult = cbor_encode_text_string(&crlMap, (const char *)crl->ThisUpdate.data,
339 crl->ThisUpdate.len);
340 VERIFY_CBOR_SUCCESS(TAG, cborEncoderResult, "Failed to add Crl Update value");
342 //CRLData -- Mandatory
343 cborEncoderResult = setPubDataType(&crlMap, OC_RSRVD_CRL, &crl->CrlData);
344 VERIFY_CBOR_SUCCESS(TAG, cborEncoderResult, "Failed to add CRLData object");
346 //lastUpdate - internal field
349 cborEncoderResult = cbor_encode_text_string(&crlMap, OC_RSRVD_LAST_UPDATE,
350 strlen(OC_RSRVD_LAST_UPDATE));
351 VERIFY_CBOR_SUCCESS(TAG, cborEncoderResult, "Failed to add last Update tag");
352 cborEncoderResult = cbor_encode_text_string(&crlMap, lastUpdate, strlen(lastUpdate));
353 VERIFY_CBOR_SUCCESS(TAG, cborEncoderResult, "Failed to add last Update value");
356 cborEncoderResult = cbor_encoder_close_container(&encoder, &crlMap);
357 VERIFY_CBOR_SUCCESS(TAG, cborEncoderResult, "Failed to add close Crl map");
359 *size = encoder.ptr - outPayload;
360 *payload = outPayload;
364 if ((CborErrorOutOfMemory == cborEncoderResult) && (cborLen < CBOR_MAX_SIZE))
366 // reallocate and try again!
368 // Since the allocated initial memory failed, double the memory.
369 cborLen += encoder.ptr - encoder.end;
370 cborEncoderResult = CborNoError;
371 ret = CrlToCBORPayload(crl, payload, &cborLen, lastUpdate);
374 if ((CborNoError != cborEncoderResult) || (OC_STACK_OK != ret))
380 ret = OC_STACK_ERROR;
386 OCStackResult CBORPayloadToCrl(const uint8_t *cborPayload, const size_t size,
387 OicSecCrl_t **secCrl)
389 if (NULL == cborPayload || NULL == secCrl || NULL != *secCrl || 0 == size)
391 return OC_STACK_INVALID_PARAM;
394 OCStackResult ret = OC_STACK_ERROR;
395 OicSecCrl_t *crl = NULL;
397 CborValue crlCbor = {.parser = NULL};
398 CborParser parser = {.end = NULL};
399 CborError cborFindResult = CborNoError;
401 cbor_parser_init(cborPayload, size, 0, &parser, &crlCbor);
402 CborValue crlMap = { .parser = NULL};
403 cborFindResult = cbor_value_enter_container(&crlCbor, &crlMap);
404 VERIFY_CBOR_SUCCESS(TAG, cborFindResult, "Failed to enter Crl map");
406 crl = (OicSecCrl_t *)OICCalloc(1, sizeof(OicSecCrl_t));
407 VERIFY_NON_NULL(TAG, crl, ERROR);
409 cborFindResult = cbor_value_map_find_value(&crlCbor, OC_RSRVD_CRL_ID, &crlMap);
410 if (CborNoError == cborFindResult && cbor_value_is_integer(&crlMap))
414 cborFindResult = cbor_value_get_int(&crlMap, &CrlId);
415 VERIFY_CBOR_SUCCESS(TAG, cborFindResult, "Failed Finding CrlId.");
416 crl->CrlId = (uint16_t)CrlId;
419 cborFindResult = cbor_value_map_find_value(&crlCbor, OC_RSRVD_THIS_UPDATE, &crlMap);
420 if (CborNoError == cborFindResult && cbor_value_is_text_string(&crlMap))
422 cborFindResult = cbor_value_dup_text_string(&crlMap,
423 (char **)&crl->ThisUpdate.data, &crl->ThisUpdate.len, NULL);
424 VERIFY_CBOR_SUCCESS(TAG, cborFindResult, "Failed Advancing Byte Array.");
427 cborFindResult = getPubDataType(&crlCbor, OC_RSRVD_CRL, &crl->CrlData);
428 VERIFY_CBOR_SUCCESS(TAG, cborFindResult, "Failed to read CRL.");
435 if (CborNoError != cborFindResult)
437 // PUT/POST CBOR may not have mandatory values set default values.
438 OIC_LOG (DEBUG, TAG, "Set default values");
440 if (copyCrl(gCrl, crl))
449 ret = OC_STACK_ERROR;
450 OIC_LOG (ERROR, TAG, "Can't set default crl");
456 static void getCurrentUTCTime(char *out, size_t len)
458 //TODO: how to implement it in cross-platform way?
460 struct tm * timeinfo = NULL;
463 timeinfo = localtime ( &rawtime );
465 if (NULL == timeinfo)
470 snprintf(out, len, "%04d%02d%02d%02d%02d%02d",
471 timeinfo->tm_year + 1900, timeinfo->tm_mon + 1, timeinfo->tm_mday,
472 timeinfo->tm_hour, timeinfo->tm_min, timeinfo->tm_sec);
475 OCStackResult UpdateCRLResource(OicSecCrl_t *crl)
477 static uint16_t crlid = 0;
478 uint8_t *payload = NULL;
481 crl->CrlId = crlid++;
483 if (!copyCrl(crl, gCrl))
485 OIC_LOG(ERROR, TAG, "Can't update global crl");
486 return OC_STACK_ERROR;
489 char currentTime[32] = {0};
490 getCurrentUTCTime(currentTime, sizeof(currentTime));
492 OCStackResult res = CrlToCBORPayload((const OicSecCrl_t *) crl, &payload, &size, currentTime);
493 if (OC_STACK_OK != res)
498 return UpdateSecureResourceInPS(OIC_CBOR_CRL_NAME, payload, size);
501 static OCEntityHandlerResult HandleCRLPostRequest(const OCEntityHandlerRequest *ehRequest)
503 OCEntityHandlerResult ehRet = OC_EH_ERROR;
504 OicSecCrl_t *crl = NULL;
505 uint8_t *payload = ((OCSecurityPayload *)ehRequest->payload)->securityData;
506 size_t size = ((OCSecurityPayload *) ehRequest->payload)->payloadSize;
510 OIC_LOG(INFO, TAG, "Update SVR DB...");
511 CBORPayloadToCrl(payload, size, &crl);
512 VERIFY_NON_NULL(TAG, crl, ERROR);
514 if (OC_STACK_OK == UpdateCRLResource(crl))
516 ehRet = OC_EH_RESOURCE_CREATED;
523 // Send payload to request originator
524 if (OC_STACK_OK != SendSRMResponse(ehRequest, ehRet, NULL, 0))
527 OIC_LOG(ERROR, TAG, "SendSRMResponse failed in HandleCRLPostRequest");
530 OIC_LOG_V(INFO, TAG, "%s RetVal %d", __func__, ehRet);
536 * This internal method is the entity handler for CRL resource and
537 * will handle REST request (GET/PUT/POST/DEL) for them.
539 static OCEntityHandlerResult CRLEntityHandler(OCEntityHandlerFlag flag,
540 OCEntityHandlerRequest *ehRequest,
541 void *callbackParameter)
543 OCEntityHandlerResult ehRet = OC_EH_ERROR;
544 (void)callbackParameter;
551 OIC_LOG(INFO, TAG, "Handle CRL resource");
553 if (flag & OC_REQUEST_FLAG)
555 // TODO : Handle PUT and DEL methods
556 OIC_LOG (INFO, TAG, "Flag includes OC_REQUEST_FLAG");
557 switch (ehRequest->method)
560 OIC_LOG (INFO, TAG, "Not implemented request method.");
561 //ehRet = HandleCRLGetRequest(ehRequest);
565 ehRet = HandleCRLPostRequest(ehRequest);
570 SendSRMResponse(ehRequest, ehRet, NULL, 0);
578 * This internal method is used to create '/oic/sec/crl' resource.
580 static OCStackResult CreateCRLResource()
582 OCStackResult ret = OCCreateResource(&gCrlHandle,
583 OIC_RSRC_TYPE_SEC_CRL,
584 OC_RSRVD_INTERFACE_DEFAULT,
590 if (OC_STACK_OK != ret)
592 OIC_LOG(FATAL, TAG, "Unable to instantiate CRL resource");
599 * Get the default value.
600 * @return defaultCrl for now.
602 static OicSecCrl_t *GetCrlDefault()
604 OicSecCrl_t *defaultCrl = (OicSecCrl_t *)OICCalloc(1, sizeof(OicSecCrl_t));
605 if (NULL == defaultCrl)
610 defaultCrl->CrlId = CRL_DEFAULT_CRL_ID;
611 defaultCrl->CrlData.encoding = OIC_ENCODING_DER;
613 bool result1 = copyByteArray((const uint8_t *)CRL_DEFAULT_CRL_DATA,
614 strlen(CRL_DEFAULT_CRL_DATA),
615 &defaultCrl->CrlData.data,
616 &defaultCrl->CrlData.len);
618 bool result2 = copyByteArray((const uint8_t *)CRL_DEFAULT_THIS_UPDATE,
619 strlen(CRL_DEFAULT_THIS_UPDATE),
620 &defaultCrl->ThisUpdate.data,
621 &defaultCrl->ThisUpdate.len);
623 if (!result1 || !result2)
625 DeleteCrl(defaultCrl);
633 * Initialize CRL resource by loading data from persistent storage.
636 * OC_STACK_OK - no errors
637 * OC_STACK_ERROR - stack process error
639 OCStackResult InitCRLResource()
641 OCStackResult ret = OC_STACK_ERROR;
642 // Read Crl resource from PS
643 uint8_t *data = NULL;
645 ret = GetSecureVirtualDatabaseFromPS(OIC_CBOR_CRL_NAME, &data, &size);
646 // If database read failed
647 if (OC_STACK_OK != ret)
649 OIC_LOG (DEBUG, TAG, "ReadSVDataFromPS failed");
653 // Read ACL resource from PS
654 ret = CBORPayloadToCrl(data, size, &gCrl);
658 * If SVR database in persistent storage got corrupted or
659 * is not available for some reason, a default CrlResource is created
660 * which allows user to initiate CrlResource provisioning again.
662 if ((OC_STACK_OK != ret) || !data || !gCrl)
664 gCrl = GetCrlDefault();
667 ret = CreateCRLResource();
673 * Perform cleanup for ACL resources.
675 OCStackResult DeInitCRLResource()
677 OCStackResult result = OCDeleteResource(gCrlHandle);
684 OicSecCrl_t *GetCRLResource()
686 OicSecCrl_t *crl = NULL;
688 //Read CRL resource from PS
689 uint8_t *data = NULL;
691 OCStackResult ret = GetSecureVirtualDatabaseFromPS(OIC_CBOR_CRL_NAME, &data, &size);
694 //Convert CBOR CRL into binary format
695 ret = CBORPayloadToCrl(data, size, &crl);
698 * If SVR database in persistent storage got corrupted or
699 * is not available for some reason, a default CrlResource is created
700 * which allows user to initiate CrlResource provisioning again.
702 if ((OC_STACK_OK != ret) || !data || !crl)
704 crl = GetCrlDefault();
711 OCStackResult getLastUpdateFromDB(char **lastUpdate)
713 OCStackResult result = OC_STACK_OK;
715 OCPayload *payload = NULL;
716 uint8_t *data = NULL;
721 return OC_STACK_INVALID_PARAM;
724 result = GetSecureVirtualDatabaseFromPS(OIC_CBOR_CRL_NAME, &data, &size);
725 if (result != OC_STACK_OK)
727 OIC_LOG(ERROR, TAG, "Can't get crl data from database");
731 result = OCParsePayload(&payload, PAYLOAD_TYPE_REPRESENTATION, data, size);
732 if (result != OC_STACK_OK)
734 OIC_LOG(ERROR, TAG, "Can't parse cbor data from DB");
738 if (!OCRepPayloadGetPropString((const OCRepPayload*)payload, OC_RSRVD_LAST_UPDATE, lastUpdate))
740 OIC_LOG_V(ERROR, TAG, "Can't get: %s", OC_RSRVD_LAST_UPDATE);
741 result = OC_STACK_ERROR;
745 if (result != OC_STACK_OK)
747 OIC_LOG(DEBUG, TAG, "Assume you are first time get Crl, and it can be absent in database");
748 OIC_LOG_V(DEBUG, TAG, "Return default last update time %s", CRL_DEFAULT_LAST_UPDATE);
750 *lastUpdate = OICStrdup(CRL_DEFAULT_LAST_UPDATE);
751 result = OC_STACK_OK;
753 OCPayloadDestroy((OCPayload *)payload);
760 uint8_t *data = NULL;
762 OicSecCrl_t *crl = NULL;
763 if (OC_STACK_OK == GetSecureVirtualDatabaseFromPS(OIC_CBOR_CRL_NAME, &data, &size) && data &&
764 OC_STACK_OK == CBORPayloadToCrl(data, size, &crl))
766 return crl->CrlData.data;
771 void GetDerCrl(ByteArray_t* out)
778 OicSecCrl_t *crlRes = GetCRLResource();
785 OicSecKey_t *crl = &crlRes->CrlData;
787 if (OIC_ENCODING_BASE64 == crl->encoding)
789 size_t outSize = B64DECODE_OUT_SAFESIZE((crl->len + 1));
790 uint8_t *out = OICCalloc(1, outSize);
793 OIC_LOG(ERROR, TAG, "Can't allocate memory for base64 str");
798 if(B64_OK == b64Decode((char*)crl->data, crl->len, out, outSize, &len))
800 memcpy(crl->data, out, len);
801 crl->len = (size_t)len;
803 OIC_LOG (ERROR, TAG, "Crl successfully decoded to base64.");
807 OIC_LOG (ERROR, TAG, "Base64 decoding failed.");
813 char *str = "Can't allocate memory for out->data";
814 out->data = OICMalloc(crl->len);
817 memcpy(out->data, crl->data, crl->len);
822 OIC_LOG_V(ERROR, TAG, "%s", str);