[IOT-2610] CRL empty query fix
[iotivity.git] / resource / csdk / security / src / crlresource.c
1 //******************************************************************
2 //
3 // Copyright 2015 Samsung Electronics All Rights Reserved.
4 //
5 //-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
6 //
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
10 //
11 //      http://www.apache.org/licenses/LICENSE-2.0
12 //
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.
18 //
19 //-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
20
21 #include "utlist.h"
22 #include "crl_logging.h"
23 #include "payload_logging.h"
24 #include "psinterface.h"
25 #include "resourcemanager.h"
26 #include "srmresourcestrings.h"
27 #include "srmutility.h"
28 #include "doxmresource.h"
29 #include "ocpayload.h"
30 #include "ocpayloadcbor.h"
31 #include "oic_malloc.h"
32 #include "oic_string.h"
33 #include "crlresource.h"
34 #include "ocpayloadcbor.h"
35 #include "base64.h"
36 #include <time.h>
37
38 #define TAG  "OIC_SRM_CRL"
39
40 #define SEPARATOR                   ":"
41 #define SEPARATOR_LEN               (1)
42 #define CBOR_CRL_NAME               "\"CRL\""
43 #define CBOR_CRL_NAME_LEN           (5)
44 #define OIC_CBOR_CRL_NAME           "crl"
45 #define OIC_CBOR_CRL_ID             "CRLId"
46 #define OIC_CBOR_CRL_THIS_UPDATE    "ThisUpdate"
47 #define OIC_CBOR_CRL_DATA           "CRLData"
48 #define CRL_DEFAULT_CRL_ID          (1)
49 #define CRL_DEFAULT_THIS_UPDATE     "150101000000Z"
50 #define CRL_DEFAULT_LAST_UPDATE     "20150701000000"
51 #define CRL_DEFAULT_CRL_DATA        "-"
52 #define CRL_MAP_SIZE                (5)
53
54 static OCResourceHandle     gCrlHandle  = NULL;
55 static OicSecCrl_t         *gCrl        = NULL;
56
57 /** Default cbor payload size. This value is increased in case of CborErrorOutOfMemory.
58  * The value of payload size is increased until reaching below max cbor size. */
59 static const uint16_t CBOR_SIZE = 1024;
60
61 // Max cbor size payload.
62 static const uint16_t CBOR_MAX_SIZE = 4400;
63
64 void DeleteCrl(OicSecCrl_t *crl)
65 {
66     if (crl)
67     {
68         //Clean ThisUpdate
69         OICFree(crl->ThisUpdate.data);
70
71         //clean CrlData
72         OICFree(crl->CrlData.data);
73
74         //Clean crl itself
75         OICFree(crl);
76     }
77 }
78
79 static bool copyByteArray(const uint8_t *in, size_t in_len, uint8_t **out, size_t *out_len)
80 {
81     OICFree(*out);
82     uint8_t *tmp = OICMalloc(in_len);
83     if (!tmp)
84     {
85         return false;
86     }
87     memcpy(tmp, in, in_len);
88     *out = tmp;
89     *out_len = in_len;
90     return true;
91 }
92
93 static bool copyCrl(const OicSecCrl_t *in, OicSecCrl_t *out)
94 {
95     bool result = true;
96
97     if (!in || !out)
98     {
99         OIC_LOG(ERROR, TAG, "in or out crl is NULL");
100         return false;
101     }
102
103     out->CrlId = in->CrlId;
104
105     if (NULL != in->ThisUpdate.data)
106     {
107         result = copyByteArray(in->ThisUpdate.data, in->ThisUpdate.len, &out->ThisUpdate.data, &out->ThisUpdate.len);
108         VERIFY_SUCCESS(TAG, result, ERROR);
109     }
110
111     if (NULL != in->CrlData.data)
112     {
113         result = copyByteArray(in->CrlData.data, in->CrlData.len, &out->CrlData.data, &out->CrlData.len);
114         VERIFY_SUCCESS(TAG, result, ERROR);
115     }
116
117 exit:
118     return result;
119 }
120
121 static CborError setCrlData(CborEncoder *out, const char *name, const OicSecKey_t *value)
122 {
123     if (!out || !name || !value)
124     {
125         OIC_LOG_V(ERROR, TAG, "%s: null input params", __func__);
126         return CborErrorInternalError;
127     }
128
129     CborError result = CborErrorInternalError;
130
131     size_t len = 0;
132     size_t encodeBufferSize = B64ENCODE_OUT_SAFESIZE((value->len + 1));
133     char *encodeBuffer = OICCalloc(1, encodeBufferSize);
134
135     VERIFY_NOT_NULL(TAG, encodeBuffer, ERROR);
136
137     B64Result b64result = b64Encode(value->data, value->len, encodeBuffer, encodeBufferSize, &len);
138     VERIFY_SUCCESS(TAG, (B64_OK == b64result), ERROR);
139
140     result = cbor_encode_text_string(out, name, strlen(name));
141     VERIFY_CBOR_SUCCESS(TAG, result, "Failed Adding name Tag.");
142
143     result = cbor_encode_text_string(out, (const char *)encodeBuffer, len);
144     VERIFY_CBOR_SUCCESS(TAG, result, "Failed Adding data Tag.");
145
146 exit:
147     OICFree(encodeBuffer);
148
149     return result;
150 }
151
152 static CborError getCrlData(CborValue *in, const char *name, OicSecKey_t *value)
153 {
154     if (!in || !name || !value)
155     {
156         OIC_LOG_V(ERROR, TAG, "%s: null input params", __func__);
157         return CborErrorInternalError;
158     }
159
160     CborError result = CborNoError;
161     CborValue crlNode = { .parser = NULL };
162     char *decodeBuffer = NULL;
163     size_t decodeBufferSize;
164
165     result = cbor_value_map_find_value(in, name, &crlNode);
166     if (CborNoError == result && cbor_value_is_text_string(&crlNode))
167     {
168         result = cbor_value_dup_text_string(&crlNode,
169                 (char **)&decodeBuffer, &decodeBufferSize, NULL);
170         VERIFY_CBOR_SUCCESS(TAG, result, "Failed Advancing Byte Array.");
171
172         value->len = B64DECODE_OUT_SAFESIZE(decodeBufferSize + 1);
173         value->data = OICCalloc(1, value->len);
174         VERIFY_NOT_NULL(TAG, value->data, ERROR);
175
176         B64Result b64result = b64Decode(decodeBuffer, decodeBufferSize, value->data, value->len, &value->len);
177         if (B64_OK != b64result)
178         {
179             OIC_LOG_V(ERROR, TAG, "CRL b64Decode error");
180             result = CborErrorInternalError;
181         }
182
183     }
184
185 exit:
186     OICFree(decodeBuffer);
187     return result;
188 }
189
190 OCStackResult CrlToCBORPayload(const OicSecCrl_t *crl, uint8_t **payload, size_t *size, char *lastUpdate)
191 {
192     if (NULL == crl || NULL == payload || NULL != *payload || NULL == size)
193     {
194         return OC_STACK_INVALID_PARAM;
195     }
196
197     size_t cborLen = *size;
198     if (0 == cborLen)
199     {
200         cborLen = CBOR_SIZE;
201     }
202
203     *payload = NULL;
204     *size = 0;
205
206     size_t mapSize = CRL_MAP_SIZE;
207     if (lastUpdate)
208     {
209         mapSize++;
210     }
211
212     OIC_LOG_CRL(INFO, crl);
213
214     OCStackResult ret = OC_STACK_ERROR;
215
216     CborEncoder encoder;
217     CborEncoder crlMap;
218
219     CborError cborEncoderResult = CborNoError;
220
221     uint8_t *outPayload = (uint8_t *)OICCalloc(1, cborLen);
222     VERIFY_NOT_NULL_RETURN(TAG, outPayload, ERROR, OC_STACK_ERROR);
223
224     cbor_encoder_init(&encoder, outPayload, cborLen, 0);
225
226     cborEncoderResult = cbor_encoder_create_map(&encoder, &crlMap, mapSize);
227     VERIFY_CBOR_SUCCESS(TAG, cborEncoderResult, "Failed to create CRL Map");
228
229     //CRLId -- Mandatory
230     cborEncoderResult = cbor_encode_text_string(&crlMap, OC_RSRVD_CRL_ID,
231         strlen(OC_RSRVD_CRL_ID));
232     VERIFY_CBOR_SUCCESS(TAG, cborEncoderResult, "Failed to add CRL ID");
233     cborEncoderResult = cbor_encode_int(&crlMap, crl->CrlId);
234     VERIFY_CBOR_SUCCESS(TAG, cborEncoderResult, "Failed to add CRL Id value");
235
236     //ThisUpdate -- Mandatory
237     cborEncoderResult = cbor_encode_text_string(&crlMap, OC_RSRVD_THIS_UPDATE,
238         strlen(OC_RSRVD_THIS_UPDATE));
239     VERIFY_CBOR_SUCCESS(TAG, cborEncoderResult, "Failed to add Crl update");
240     cborEncoderResult = cbor_encode_text_string(&crlMap, (const char *)crl->ThisUpdate.data,
241                                                 crl->ThisUpdate.len);
242     VERIFY_CBOR_SUCCESS(TAG, cborEncoderResult, "Failed to add Crl Update value");
243
244     //CRLData -- Mandatory
245     cborEncoderResult = setCrlData(&crlMap, OC_RSRVD_CRL, &crl->CrlData);
246     VERIFY_CBOR_SUCCESS(TAG, cborEncoderResult, "Failed to add CRLData object");
247
248     //lastUpdate - internal field
249     if (lastUpdate)
250     {
251         cborEncoderResult = cbor_encode_text_string(&crlMap, OC_RSRVD_LAST_UPDATE,
252             strlen(OC_RSRVD_LAST_UPDATE));
253         VERIFY_CBOR_SUCCESS(TAG, cborEncoderResult, "Failed to add last Update tag");
254         cborEncoderResult = cbor_encode_text_string(&crlMap, lastUpdate, strlen(lastUpdate));
255         VERIFY_CBOR_SUCCESS(TAG, cborEncoderResult, "Failed to add last Update value");
256     }
257
258     //RT -- Mandatory
259     CborEncoder rtArray;
260     cborEncoderResult = cbor_encode_text_string(&crlMap, OIC_JSON_RT_NAME,
261             strlen(OIC_JSON_RT_NAME));
262     VERIFY_CBOR_SUCCESS(TAG, cborEncoderResult, "Failed Addding RT Name Tag.");
263     cborEncoderResult = cbor_encoder_create_array(&crlMap, &rtArray, 1);
264     VERIFY_CBOR_SUCCESS(TAG, cborEncoderResult, "Failed Addding RT Value.");
265     cborEncoderResult = cbor_encode_text_string(&rtArray, OIC_RSRC_TYPE_SEC_CRL,
266             strlen(OIC_RSRC_TYPE_SEC_CRL));
267     VERIFY_CBOR_SUCCESS(TAG, cborEncoderResult, "Failed Adding RT Value.");
268     cborEncoderResult = cbor_encoder_close_container(&crlMap, &rtArray);
269     VERIFY_CBOR_SUCCESS(TAG, cborEncoderResult, "Failed Closing RT.");
270
271     //IF-- Mandatory
272     CborEncoder ifArray;
273     cborEncoderResult = cbor_encode_text_string(&crlMap, OIC_JSON_IF_NAME,
274        strlen(OIC_JSON_IF_NAME));
275     VERIFY_CBOR_SUCCESS(TAG, cborEncoderResult, "Failed Addding IF Name Tag.");
276     cborEncoderResult = cbor_encoder_create_array(&crlMap, &ifArray, 1);
277     VERIFY_CBOR_SUCCESS(TAG, cborEncoderResult, "Failed Addding IF Value.");
278     cborEncoderResult = cbor_encode_text_string(&ifArray, OC_RSRVD_INTERFACE_DEFAULT,
279             strlen(OC_RSRVD_INTERFACE_DEFAULT));
280     VERIFY_CBOR_SUCCESS(TAG, cborEncoderResult, "Failed Adding IF Value.");
281     cborEncoderResult = cbor_encoder_close_container(&crlMap, &ifArray);
282     VERIFY_CBOR_SUCCESS(TAG, cborEncoderResult, "Failed Closing IF.");
283
284     cborEncoderResult = cbor_encoder_close_container(&encoder, &crlMap);
285     VERIFY_CBOR_SUCCESS(TAG, cborEncoderResult, "Failed to add close Crl map");
286
287     *size = cbor_encoder_get_buffer_size(&encoder, outPayload);
288     *payload = outPayload;
289     ret = OC_STACK_OK;
290
291 exit:
292     if ((CborNoError != cborEncoderResult) || (OC_STACK_OK != ret))
293     {
294         OICFree(outPayload);
295         if ((CborErrorOutOfMemory == cborEncoderResult) && (cborLen < CBOR_MAX_SIZE))
296         {
297             // Since the allocated initial memory failed, double the memory.
298             cborLen += cbor_encoder_get_buffer_size(&encoder, encoder.end);
299             cborEncoderResult = CborNoError;
300             ret = CrlToCBORPayload(crl, payload, &cborLen, lastUpdate);
301             if (OC_STACK_OK != ret)
302             {
303                 outPayload = NULL;
304                 *payload = NULL;
305                 *size = 0;
306                 ret = OC_STACK_ERROR;
307             }
308         }
309         else
310         {
311             outPayload = NULL;
312             *payload = NULL;
313             *size = 0;
314             ret = OC_STACK_ERROR;
315         }
316     }
317
318     return ret;
319 }
320
321 OCStackResult CBORPayloadToCrl(const uint8_t *cborPayload, const size_t size,
322                                OicSecCrl_t **secCrl)
323 {
324     if (NULL == cborPayload || NULL == secCrl || NULL != *secCrl || 0 == size)
325     {
326         return OC_STACK_INVALID_PARAM;
327     }
328
329     OCStackResult ret = OC_STACK_ERROR;
330     OicSecCrl_t *crl = NULL;
331
332     CborValue crlCbor = {.parser = NULL};
333     CborParser parser = {.end = NULL};
334     CborError cborFindResult = CborNoError;
335
336     cbor_parser_init(cborPayload, size, 0, &parser, &crlCbor);
337     CborValue crlMap = { .parser = NULL};
338     cborFindResult = cbor_value_enter_container(&crlCbor, &crlMap);
339     VERIFY_CBOR_SUCCESS(TAG, cborFindResult, "Failed to enter Crl map");
340
341     crl = (OicSecCrl_t *)OICCalloc(1, sizeof(OicSecCrl_t));
342     VERIFY_NOT_NULL(TAG, crl, ERROR);
343
344     cborFindResult = cbor_value_map_find_value(&crlCbor, OC_RSRVD_CRL_ID, &crlMap);
345     if (CborNoError == cborFindResult && cbor_value_is_integer(&crlMap))
346     {
347         int CrlId;
348
349         cborFindResult = cbor_value_get_int(&crlMap, &CrlId);
350         VERIFY_CBOR_SUCCESS(TAG, cborFindResult, "Failed Finding CrlId.");
351         crl->CrlId = (uint16_t)CrlId;
352     }
353
354     cborFindResult = cbor_value_map_find_value(&crlCbor, OC_RSRVD_THIS_UPDATE, &crlMap);
355     if (CborNoError == cborFindResult && cbor_value_is_text_string(&crlMap))
356     {
357         cborFindResult = cbor_value_dup_text_string(&crlMap,
358                 (char **)&crl->ThisUpdate.data, &crl->ThisUpdate.len, NULL);
359         VERIFY_CBOR_SUCCESS(TAG, cborFindResult, "Failed Advancing Byte Array.");
360     }
361
362     cborFindResult = getCrlData(&crlCbor, OC_RSRVD_CRL, &crl->CrlData);
363     VERIFY_CBOR_SUCCESS(TAG, cborFindResult, "Failed to read CRL.");
364
365     OIC_LOG_CRL(INFO, crl);
366
367     *secCrl = crl;
368     ret = OC_STACK_OK;
369 exit:
370     if (CborNoError != cborFindResult)
371     {
372         // PUT/POST CBOR may not have mandatory values set default values.
373         OIC_LOG (DEBUG, TAG, "Set default values");
374
375         if (copyCrl(gCrl, crl))
376         {
377             *secCrl = crl;
378             ret = OC_STACK_OK;
379         }
380         else
381         {
382             DeleteCrl(crl);
383             crl = NULL;
384             ret = OC_STACK_ERROR;
385             OIC_LOG (ERROR, TAG, "Can't set default crl");
386         }
387     }
388     return ret;
389 }
390
391 static void getCurrentUTCTime(char *out, size_t len)
392 {
393     //TODO: how to implement it in cross-platform way?
394     time_t rawtime;
395     struct tm * timeinfo = NULL;
396
397     time ( &rawtime );
398     timeinfo = localtime ( &rawtime );
399
400     if (NULL == timeinfo)
401     {
402         return;
403     }
404
405     snprintf(out, len, "%04d%02d%02d%02d%02d%02d",
406             timeinfo->tm_year + 1900, timeinfo->tm_mon + 1, timeinfo->tm_mday,
407             timeinfo->tm_hour, timeinfo->tm_min, timeinfo->tm_sec);
408 }
409
410 OCStackResult UpdateCRLResource(OicSecCrl_t *crl)
411 {
412     static uint16_t crlid = 0;
413     uint8_t *payload = NULL;
414     size_t size = 0;
415
416     if ( NULL == gCrl )
417     {
418         OIC_LOG(ERROR, TAG, "Crl resourse isn't initialized");
419         return OC_STACK_ERROR;
420     }
421
422     if ( 0 == crl->CrlId)
423     {
424         crl->CrlId = ++crlid;
425     }
426     else
427     {
428         if (crl->CrlId > crlid)
429         {
430             crlid = crl->CrlId;
431         }
432     }
433
434     if (!copyCrl(crl, gCrl))
435     {
436         OIC_LOG(ERROR, TAG, "Can't update global crl");
437         return OC_STACK_ERROR;
438     }
439
440     char currentTime[32] = {0};
441     getCurrentUTCTime(currentTime, sizeof(currentTime));
442
443     OCStackResult res = CrlToCBORPayload((const OicSecCrl_t *) gCrl, &payload, &size, currentTime);
444     if (OC_STACK_OK != res)
445     {
446         return res;
447     }
448
449     return UpdateSecureResourceInPS(OIC_CBOR_CRL_NAME, payload, size);
450 }
451
452 static bool ValidateQuery(const char * query)
453 {
454     OIC_LOG (DEBUG, TAG, "In ValidateQuery");
455
456     bool bInterfaceQry = false;      // does querystring contains 'if' query ?
457     bool bInterfaceMatch = false;    // does 'if' query matches with oic.if.baseline ?
458
459     OicParseQueryIter_t parseIter = {.attrPos = NULL};
460
461     ParseQueryIterInit((unsigned char*)query, &parseIter);
462
463     while (GetNextQuery(&parseIter))
464     {
465         if (strncasecmp((char *)parseIter.attrPos, OC_RSRVD_INTERFACE, parseIter.attrLen) == 0)
466         {
467             bInterfaceQry = true;
468             if ((strncasecmp((char *)parseIter.valPos, OC_RSRVD_INTERFACE_DEFAULT, parseIter.valLen) == 0))
469             {
470                 bInterfaceMatch = true;
471             }
472             return (bInterfaceQry ? bInterfaceMatch: false);
473         }
474     }
475
476     return true;
477 }
478
479 static OCEntityHandlerResult HandleCRLGetRequest(const OCEntityHandlerRequest *ehRequest)
480 {
481     OCEntityHandlerResult ehRet = OC_EH_OK;
482     uint8_t* payload = NULL;
483     size_t size = 0;
484
485     if (ehRequest->query)
486     {
487         OIC_LOG_V(DEBUG,TAG,"query:%s",ehRequest->query);
488         OIC_LOG(DEBUG, TAG, "HandleCRLGetRequest processing query");
489         if (!ValidateQuery(ehRequest->query))
490         {
491             ehRet = OC_EH_ERROR;
492         }
493     }
494
495     if ( NULL == gCrl )
496     {
497         OIC_LOG(ERROR, TAG, "Crl resourse isn't initialized");
498         ehRet = OC_EH_ERROR;
499     }
500
501     if (OC_EH_OK == ehRet && OC_STACK_OK != CrlToCBORPayload(gCrl, &payload, &size, NULL))
502     {
503         OIC_LOG(ERROR, TAG, " HandleCRLGetRequest error");
504         ehRet = OC_EH_ERROR;
505     }
506
507     ehRet = (payload ? OC_EH_OK : OC_EH_ERROR);
508     OIC_LOG(DEBUG, TAG, "CRL payload with GET response");
509     OIC_LOG_BUFFER(DEBUG, TAG, payload, size);
510
511     // Send payload to request originator
512     if (OC_STACK_OK != SendSRMResponse(ehRequest, ehRet, payload, size))
513     {
514         ehRet = OC_EH_ERROR;
515         OIC_LOG(ERROR, TAG, "SendSRMResponse failed in HandleCRLGetRequest");
516     }
517
518     OICFree(payload);
519
520     OIC_LOG_V(INFO, TAG, "%s RetVal %d", __func__, ehRet);
521     return ehRet;
522 }
523
524 static OCEntityHandlerResult HandleCRLPostRequest(const OCEntityHandlerRequest *ehRequest)
525 {
526     OCEntityHandlerResult ehRet = OC_EH_ERROR;
527     OicSecCrl_t *crl = NULL;
528     uint8_t *payload = ((OCSecurityPayload *)ehRequest->payload)->securityData;
529     size_t size = ((OCSecurityPayload *) ehRequest->payload)->payloadSize;
530     bool create = (NULL == gCrl);
531
532     if (payload)
533     {
534         OIC_LOG(INFO, TAG, "Update SVR DB...");
535         CBORPayloadToCrl(payload, size, &crl);
536         VERIFY_NOT_NULL(TAG, crl, ERROR);
537
538         if (OC_STACK_OK == UpdateCRLResource(crl))
539         {
540             ehRet = create ? OC_EH_RESOURCE_CREATED : OC_EH_CHANGED;
541         }
542
543         DeleteCrl(crl);
544     }
545
546 exit:
547     // Send payload to request originator
548     if (OC_STACK_OK != SendSRMResponse(ehRequest, ehRet, NULL, 0))
549     {
550         ehRet = OC_EH_ERROR;
551         OIC_LOG(ERROR, TAG, "SendSRMResponse failed in HandleCRLPostRequest");
552     }
553
554     OIC_LOG_V(INFO, TAG, "%s RetVal %d", __func__, ehRet);
555     return ehRet;
556 }
557
558
559 /**
560  * This internal method is the entity handler for CRL resource and
561  * will handle REST request (GET/PUT/POST/DEL) for them.
562  */
563 static OCEntityHandlerResult CRLEntityHandler(OCEntityHandlerFlag flag,
564                                               OCEntityHandlerRequest *ehRequest,
565                                               void *callbackParameter)
566 {
567     OCEntityHandlerResult ehRet = OC_EH_ERROR;
568     (void)callbackParameter;
569
570     if (!ehRequest)
571     {
572         return ehRet;
573     }
574
575     OIC_LOG(INFO, TAG, "Handle CRL resource");
576
577     if (flag & OC_REQUEST_FLAG)
578     {
579         // TODO :  Handle PUT and DEL methods
580         OIC_LOG (INFO, TAG, "Flag includes OC_REQUEST_FLAG");
581         switch (ehRequest->method)
582         {
583             case OC_REST_GET:
584                 ehRet = HandleCRLGetRequest(ehRequest);
585                 break;
586
587             case OC_REST_POST:
588                 ehRet = HandleCRLPostRequest(ehRequest);
589                 break;
590
591             default:
592                 ehRet = OC_EH_ERROR;
593                 SendSRMResponse(ehRequest, ehRet, NULL, 0);
594         }
595     }
596
597     return ehRet;
598 }
599
600 /**
601  * This internal method is used to create '/oic/sec/crl' resource.
602  */
603 static OCStackResult CreateCRLResource()
604 {
605     OCStackResult ret = OCCreateResource(&gCrlHandle,
606                                          OIC_RSRC_TYPE_SEC_CRL,
607                                          OC_RSRVD_INTERFACE_DEFAULT,
608                                          OIC_RSRC_CRL_URI,
609                                          CRLEntityHandler,
610                                          NULL,
611                                          OC_SECURE |
612                                          OC_DISCOVERABLE);
613
614     if (OC_STACK_OK != ret)
615     {
616         OIC_LOG(FATAL, TAG, "Unable to instantiate CRL resource");
617         DeInitCRLResource();
618     }
619     return ret;
620 }
621
622 /**
623  * Get the default value.
624  * @return defaultCrl for now.
625  */
626 static OicSecCrl_t *GetCrlDefault()
627 {
628     OicSecCrl_t *defaultCrl = (OicSecCrl_t *)OICCalloc(1, sizeof(OicSecCrl_t));
629     if (NULL == defaultCrl)
630     {
631         return NULL;
632     }
633
634     defaultCrl->CrlId = CRL_DEFAULT_CRL_ID;
635     defaultCrl->CrlData.encoding = OIC_ENCODING_DER;
636
637     bool result1 = copyByteArray((const uint8_t *)CRL_DEFAULT_CRL_DATA,
638                                  sizeof(CRL_DEFAULT_CRL_DATA),
639                                  &defaultCrl->CrlData.data,
640                                  &defaultCrl->CrlData.len);
641
642     bool result2 = copyByteArray((const uint8_t *)CRL_DEFAULT_THIS_UPDATE,
643                                  sizeof(CRL_DEFAULT_THIS_UPDATE),
644                                  &defaultCrl->ThisUpdate.data,
645                                  &defaultCrl->ThisUpdate.len);
646
647     if (!result1 || !result2)
648     {
649         DeleteCrl(defaultCrl);
650         return NULL;
651     }
652
653     return defaultCrl;
654 }
655
656 /**
657  * Initialize CRL resource by loading data from persistent storage.
658  *
659  * @retval
660  *     OC_STACK_OK    - no errors
661  *     OC_STACK_ERROR - stack process error
662  */
663 OCStackResult InitCRLResource()
664 {
665     OCStackResult ret = OC_STACK_ERROR;
666     // Read Crl resource from PS
667     uint8_t *data = NULL;
668     size_t size = 0;
669     ret = GetSecureVirtualDatabaseFromPS(OIC_CBOR_CRL_NAME, &data, &size);
670     // If database read failed
671     if (OC_STACK_OK != ret)
672     {
673         OIC_LOG (DEBUG, TAG, "ReadSVDataFromPS failed");
674     }
675     if (data)
676     {
677         // Read CRL resource from PS
678         ret = CBORPayloadToCrl(data, size, &gCrl);
679     }
680
681     /*
682      * If SVR database in persistent storage got corrupted or
683      * is not available for some reason, a default CrlResource is created
684      * which allows user to initiate CrlResource provisioning again.
685      */
686     if ((OC_STACK_OK != ret) || !data || !gCrl)
687     {
688         gCrl = GetCrlDefault();
689     }
690
691     ret = CreateCRLResource();
692     OICFree(data);
693     return ret;
694 }
695
696 /**
697  * Perform cleanup for CRL resources.
698  */
699 OCStackResult DeInitCRLResource()
700 {
701     OCStackResult result = OCDeleteResource(gCrlHandle);
702     gCrlHandle = NULL;
703     DeleteCrl(gCrl);
704     gCrl = NULL;
705     return result;
706 }
707
708 OicSecCrl_t *GetCRLResource()
709 {
710     OicSecCrl_t *crl =  NULL;
711
712     //Read CRL resource from PS
713     uint8_t *data = NULL;
714     size_t size = 0;
715     OCStackResult ret = GetSecureVirtualDatabaseFromPS(OIC_CBOR_CRL_NAME, &data, &size);
716     if (data)
717     {
718         //Convert CBOR CRL into binary format
719         ret = CBORPayloadToCrl(data, size, &crl);
720     }
721     /*
722      * If SVR database in persistent storage got corrupted or
723      * is not available for some reason, a default CrlResource is created
724      * which allows user to initiate CrlResource provisioning again.
725      */
726     if ((OC_STACK_OK != ret) || !data || !crl)
727     {
728         crl = GetCrlDefault();
729     }
730     OICFree(data);
731
732     return crl;
733 }
734
735 OCStackResult getLastUpdateFromDB(char **lastUpdate)
736 {
737     OCStackResult result = OC_STACK_OK;
738
739     OCPayload *payload = NULL;
740     uint8_t *data = NULL;
741     size_t size = 0;
742
743     if (!lastUpdate)
744     {
745         return OC_STACK_INVALID_PARAM;
746     }
747
748     result = GetSecureVirtualDatabaseFromPS(OIC_CBOR_CRL_NAME, &data, &size);
749     if (result != OC_STACK_OK)
750     {
751         OIC_LOG(ERROR, TAG, "Can't get crl data from database");
752         goto exit;
753     }
754
755     result = OCParsePayload(&payload, OC_FORMAT_CBOR, PAYLOAD_TYPE_REPRESENTATION, data, size);
756     if (result != OC_STACK_OK)
757     {
758         OIC_LOG(ERROR, TAG, "Can't parse cbor data from DB");
759         goto exit;
760     }
761
762     if (!OCRepPayloadGetPropString((const OCRepPayload*)payload, OC_RSRVD_LAST_UPDATE, lastUpdate))
763     {
764         OIC_LOG_V(ERROR, TAG, "Can't get: %s", OC_RSRVD_LAST_UPDATE);
765         result = OC_STACK_ERROR;
766     }
767
768 exit:
769     if (result != OC_STACK_OK)
770     {
771         OIC_LOG(DEBUG, TAG, "Assume you are first time get Crl, and it can be absent in database");
772         OIC_LOG_V(DEBUG, TAG, "Return default last update time %s", CRL_DEFAULT_LAST_UPDATE);
773
774         *lastUpdate = OICStrdup(CRL_DEFAULT_LAST_UPDATE);
775         result = OC_STACK_OK;
776     }
777     OCPayloadDestroy((OCPayload *)payload);
778
779     return result;
780 }
781
782 uint8_t *GetCrl()
783 {
784     uint8_t *data = NULL;
785     size_t size = 0;
786     OicSecCrl_t *crl = NULL;
787     if (OC_STACK_OK == GetSecureVirtualDatabaseFromPS(OIC_CBOR_CRL_NAME, &data, &size) && data &&
788         OC_STACK_OK == CBORPayloadToCrl(data, size, &crl))
789     {
790         return crl->CrlData.data;
791     }
792     return NULL;
793 }
794
795 void GetDerCrl(ByteArray_t* out)
796 {
797     if(NULL == out)
798     {
799         return;
800     }
801
802     OicSecCrl_t *crlRes = GetCRLResource();
803
804     if(NULL == crlRes)
805     {
806         return;
807     }
808
809     OicSecKey_t *crl = &crlRes->CrlData;
810
811     if (OIC_ENCODING_BASE64 == crl->encoding)
812     {
813         size_t decodeBufferSize = B64DECODE_OUT_SAFESIZE((crl->len + 1));
814         uint8_t *decodeBuffer = OICCalloc(1, decodeBufferSize);
815         if (!decodeBuffer)
816         {
817             OIC_LOG(ERROR, TAG, "Can't allocate memory for base64 str");
818             return;
819         }
820         size_t len = 0;
821
822         if(B64_OK == b64Decode((char*)crl->data, crl->len, decodeBuffer, decodeBufferSize, &len))
823         {
824             memcpy(crl->data, decodeBuffer, len);
825             crl->len = (size_t)len;
826
827             OIC_LOG (ERROR, TAG, "Crl successfully decoded to base64.");
828         }
829         else
830         {
831             OIC_LOG (ERROR, TAG, "Base64 decoding failed.");
832         }
833
834         OICFree(decodeBuffer);
835     }
836
837     out->len = 0;
838
839     uint8_t *tmp = OICRealloc(out->data, crl->len);
840     if (tmp)
841     {
842         out->data = tmp;
843         memcpy(out->data, crl->data, crl->len);
844         out->len = crl->len;
845     }
846     else
847     {
848         OICFree(out->data);
849         out->data = NULL;
850         OIC_LOG(ERROR, TAG, "Can't allocate memory for out->data");
851     }
852     DeleteCrl(crlRes);
853 }