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