72c86e7fd4e076d40992767ca518725bfda3cbbc
[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 ((CborErrorOutOfMemory == cborEncoderResult) && (cborLen < CBOR_MAX_SIZE))
366     {
367         // reallocate and try again!
368         OICFree(outPayload);
369         // Since the allocated initial memory failed, double the memory.
370         cborLen += cbor_encoder_get_buffer_size(&encoder, encoder.end);
371         cborEncoderResult = CborNoError;
372         ret = CrlToCBORPayload(crl, payload, &cborLen, lastUpdate);
373     }
374
375     if ((CborNoError != cborEncoderResult) || (OC_STACK_OK != ret))
376     {
377         OICFree(outPayload);
378         outPayload = NULL;
379         *payload = NULL;
380         *size = 0;
381         ret = OC_STACK_ERROR;
382     }
383
384     return ret;
385 }
386
387 OCStackResult CBORPayloadToCrl(const uint8_t *cborPayload, const size_t size,
388                                OicSecCrl_t **secCrl)
389 {
390     if (NULL == cborPayload || NULL == secCrl || NULL != *secCrl || 0 == size)
391     {
392         return OC_STACK_INVALID_PARAM;
393     }
394
395     OCStackResult ret = OC_STACK_ERROR;
396     OicSecCrl_t *crl = NULL;
397
398     CborValue crlCbor = {.parser = NULL};
399     CborParser parser = {.end = NULL};
400     CborError cborFindResult = CborNoError;
401
402     cbor_parser_init(cborPayload, size, 0, &parser, &crlCbor);
403     CborValue crlMap = { .parser = NULL};
404     cborFindResult = cbor_value_enter_container(&crlCbor, &crlMap);
405     VERIFY_CBOR_SUCCESS(TAG, cborFindResult, "Failed to enter Crl map");
406
407     crl = (OicSecCrl_t *)OICCalloc(1, sizeof(OicSecCrl_t));
408     VERIFY_NON_NULL(TAG, crl, ERROR);
409
410     cborFindResult = cbor_value_map_find_value(&crlCbor, OC_RSRVD_CRL_ID, &crlMap);
411     if (CborNoError == cborFindResult && cbor_value_is_integer(&crlMap))
412     {
413         int CrlId;
414
415         cborFindResult = cbor_value_get_int(&crlMap, &CrlId);
416         VERIFY_CBOR_SUCCESS(TAG, cborFindResult, "Failed Finding CrlId.");
417         crl->CrlId = (uint16_t)CrlId;
418     }
419
420     cborFindResult = cbor_value_map_find_value(&crlCbor, OC_RSRVD_THIS_UPDATE, &crlMap);
421     if (CborNoError == cborFindResult && cbor_value_is_text_string(&crlMap))
422     {
423         cborFindResult = cbor_value_dup_text_string(&crlMap,
424                 (char **)&crl->ThisUpdate.data, &crl->ThisUpdate.len, NULL);
425         VERIFY_CBOR_SUCCESS(TAG, cborFindResult, "Failed Advancing Byte Array.");
426     }
427
428     cborFindResult = getPubDataType(&crlCbor, OC_RSRVD_CRL, &crl->CrlData);
429     VERIFY_CBOR_SUCCESS(TAG, cborFindResult, "Failed to read CRL.");
430
431     printCrl(crl);
432
433     *secCrl = crl;
434     ret = OC_STACK_OK;
435 exit:
436     if (CborNoError != cborFindResult)
437     {
438         // PUT/POST CBOR may not have mandatory values set default values.
439         OIC_LOG (DEBUG, TAG, "Set default values");
440
441         if (copyCrl(gCrl, crl))
442         {
443             *secCrl = crl;
444             ret = OC_STACK_OK;
445         }
446         else
447         {
448             DeleteCrl(crl);
449             crl = NULL;
450             ret = OC_STACK_ERROR;
451             OIC_LOG (ERROR, TAG, "Can't set default crl");
452         }
453     }
454     return ret;
455 }
456
457 static void getCurrentUTCTime(char *out, size_t len)
458 {
459     //TODO: how to implement it in cross-platform way?
460     time_t rawtime;
461     struct tm * timeinfo = NULL;
462
463     time ( &rawtime );
464     timeinfo = localtime ( &rawtime );
465
466     if (NULL == timeinfo)
467     {
468         return;
469     }
470
471     snprintf(out, len, "%04d%02d%02d%02d%02d%02d",
472             timeinfo->tm_year + 1900, timeinfo->tm_mon + 1, timeinfo->tm_mday,
473             timeinfo->tm_hour, timeinfo->tm_min, timeinfo->tm_sec);
474 }
475
476 OCStackResult UpdateCRLResource(OicSecCrl_t *crl)
477 {
478     static uint16_t crlid = 0;
479     uint8_t *payload = NULL;
480     size_t size = 0;
481
482     crl->CrlId = crlid++;
483
484     if (!copyCrl(crl, gCrl))
485     {
486         OIC_LOG(ERROR, TAG, "Can't update global crl");
487         return OC_STACK_ERROR;
488     }
489
490     char currentTime[32] = {0};
491     getCurrentUTCTime(currentTime, sizeof(currentTime));
492
493     OCStackResult res = CrlToCBORPayload((const OicSecCrl_t *) crl, &payload, &size, currentTime);
494     if (OC_STACK_OK != res)
495     {
496         return res;
497     }
498
499     return UpdateSecureResourceInPS(OIC_CBOR_CRL_NAME, payload, size);
500 }
501
502 static OCEntityHandlerResult HandleCRLPostRequest(const OCEntityHandlerRequest *ehRequest)
503 {
504     OCEntityHandlerResult ehRet = OC_EH_ERROR;
505     OicSecCrl_t *crl = NULL;
506     uint8_t *payload = ((OCSecurityPayload *)ehRequest->payload)->securityData;
507     size_t size = ((OCSecurityPayload *) ehRequest->payload)->payloadSize;
508
509     if (payload)
510     {
511         OIC_LOG(INFO, TAG, "Update SVR DB...");
512         CBORPayloadToCrl(payload, size, &crl);
513         VERIFY_NON_NULL(TAG, crl, ERROR);
514
515         if (OC_STACK_OK == UpdateCRLResource(crl))
516         {
517             ehRet = OC_EH_RESOURCE_CREATED;
518         }
519
520         DeleteCrl(crl);
521     }
522
523 exit:
524     // Send payload to request originator
525     if (OC_STACK_OK != SendSRMResponse(ehRequest, ehRet, NULL, 0))
526     {
527         ehRet = OC_EH_ERROR;
528         OIC_LOG(ERROR, TAG, "SendSRMResponse failed in HandleCRLPostRequest");
529     }
530
531     OIC_LOG_V(INFO, TAG, "%s RetVal %d", __func__, ehRet);
532     return ehRet;
533 }
534
535
536 /**
537  * This internal method is the entity handler for CRL resource and
538  * will handle REST request (GET/PUT/POST/DEL) for them.
539  */
540 static OCEntityHandlerResult CRLEntityHandler(OCEntityHandlerFlag flag,
541                                               OCEntityHandlerRequest *ehRequest,
542                                               void *callbackParameter)
543 {
544     OCEntityHandlerResult ehRet = OC_EH_ERROR;
545     (void)callbackParameter;
546
547     if (!ehRequest)
548     {
549         return ehRet;
550     }
551
552     OIC_LOG(INFO, TAG, "Handle CRL resource");
553
554     if (flag & OC_REQUEST_FLAG)
555     {
556         // TODO :  Handle PUT and DEL methods
557         OIC_LOG (INFO, TAG, "Flag includes OC_REQUEST_FLAG");
558         switch (ehRequest->method)
559         {
560             case OC_REST_GET:
561                 OIC_LOG (INFO, TAG, "Not implemented request method.");
562                 //ehRet = HandleCRLGetRequest(ehRequest);
563                 break;
564
565             case OC_REST_POST:
566                 ehRet = HandleCRLPostRequest(ehRequest);
567                 break;
568
569             default:
570                 ehRet = OC_EH_ERROR;
571                 SendSRMResponse(ehRequest, ehRet, NULL, 0);
572         }
573     }
574
575     return ehRet;
576 }
577
578 /**
579  * This internal method is used to create '/oic/sec/crl' resource.
580  */
581 static OCStackResult CreateCRLResource()
582 {
583     OCStackResult ret = OCCreateResource(&gCrlHandle,
584                                          OIC_RSRC_TYPE_SEC_CRL,
585                                          OC_RSRVD_INTERFACE_DEFAULT,
586                                          OIC_RSRC_CRL_URI,
587                                          CRLEntityHandler,
588                                          NULL,
589                                          OC_OBSERVABLE);
590
591     if (OC_STACK_OK != ret)
592     {
593         OIC_LOG(FATAL, TAG, "Unable to instantiate CRL resource");
594         DeInitCRLResource();
595     }
596     return ret;
597 }
598
599 /**
600  * Get the default value.
601  * @return defaultCrl for now.
602  */
603 static OicSecCrl_t *GetCrlDefault()
604 {
605     OicSecCrl_t *defaultCrl = (OicSecCrl_t *)OICCalloc(1, sizeof(OicSecCrl_t));
606     if (NULL == defaultCrl)
607     {
608         return NULL;
609     }
610
611     defaultCrl->CrlId = CRL_DEFAULT_CRL_ID;
612     defaultCrl->CrlData.encoding = OIC_ENCODING_DER;
613
614     bool result1 = copyByteArray((const uint8_t *)CRL_DEFAULT_CRL_DATA,
615                                  strlen(CRL_DEFAULT_CRL_DATA),
616                                  &defaultCrl->CrlData.data,
617                                  &defaultCrl->CrlData.len);
618
619     bool result2 = copyByteArray((const uint8_t *)CRL_DEFAULT_THIS_UPDATE,
620                                  strlen(CRL_DEFAULT_THIS_UPDATE),
621                                  &defaultCrl->ThisUpdate.data,
622                                  &defaultCrl->ThisUpdate.len);
623
624     if (!result1 || !result2)
625     {
626         DeleteCrl(defaultCrl);
627         return NULL;
628     }
629
630     return defaultCrl;
631 }
632
633 /**
634  * Initialize CRL resource by loading data from persistent storage.
635  *
636  * @retval
637  *     OC_STACK_OK    - no errors
638  *     OC_STACK_ERROR - stack process error
639  */
640 OCStackResult InitCRLResource()
641 {
642     OCStackResult ret = OC_STACK_ERROR;
643     // Read Crl resource from PS
644     uint8_t *data = NULL;
645     size_t size = 0;
646     ret = GetSecureVirtualDatabaseFromPS(OIC_CBOR_CRL_NAME, &data, &size);
647     // If database read failed
648     if (OC_STACK_OK != ret)
649     {
650         OIC_LOG (DEBUG, TAG, "ReadSVDataFromPS failed");
651     }
652     if (data)
653     {
654         // Read ACL resource from PS
655         ret = CBORPayloadToCrl(data, size, &gCrl);
656     }
657
658     /*
659      * If SVR database in persistent storage got corrupted or
660      * is not available for some reason, a default CrlResource is created
661      * which allows user to initiate CrlResource provisioning again.
662      */
663     if ((OC_STACK_OK != ret) || !data || !gCrl)
664     {
665         gCrl = GetCrlDefault();
666     }
667
668     ret = CreateCRLResource();
669     OICFree(data);
670     return ret;
671 }
672
673 /**
674  * Perform cleanup for ACL resources.
675  */
676 OCStackResult DeInitCRLResource()
677 {
678     OCStackResult result = OCDeleteResource(gCrlHandle);
679     gCrlHandle = NULL;
680     DeleteCrl(gCrl);
681     gCrl = NULL;
682     return result;
683 }
684
685 OicSecCrl_t *GetCRLResource()
686 {
687     OicSecCrl_t *crl =  NULL;
688
689     //Read CRL resource from PS
690     uint8_t *data = NULL;
691     size_t size = 0;
692     OCStackResult ret = GetSecureVirtualDatabaseFromPS(OIC_CBOR_CRL_NAME, &data, &size);
693     if (data)
694     {
695         //Convert CBOR CRL into binary format
696         ret = CBORPayloadToCrl(data, size, &crl);
697     }
698     /*
699      * If SVR database in persistent storage got corrupted or
700      * is not available for some reason, a default CrlResource is created
701      * which allows user to initiate CrlResource provisioning again.
702      */
703     if ((OC_STACK_OK != ret) || !data || !crl)
704     {
705         crl = GetCrlDefault();
706     }
707     OICFree(data);
708
709     return crl;
710 }
711
712 OCStackResult getLastUpdateFromDB(char **lastUpdate)
713 {
714     OCStackResult result = OC_STACK_OK;
715
716     OCPayload *payload = NULL;
717     uint8_t *data = NULL;
718     size_t size = 0;
719
720     if (!lastUpdate)
721     {
722         return OC_STACK_INVALID_PARAM;
723     }
724
725     result = GetSecureVirtualDatabaseFromPS(OIC_CBOR_CRL_NAME, &data, &size);
726     if (result != OC_STACK_OK)
727     {
728         OIC_LOG(ERROR, TAG, "Can't get crl data from database");
729         goto exit;
730     }
731
732     result = OCParsePayload(&payload, PAYLOAD_TYPE_REPRESENTATION, data, size);
733     if (result != OC_STACK_OK)
734     {
735         OIC_LOG(ERROR, TAG, "Can't parse cbor data from DB");
736         goto exit;
737     }
738
739     if (!OCRepPayloadGetPropString((const OCRepPayload*)payload, OC_RSRVD_LAST_UPDATE, lastUpdate))
740     {
741         OIC_LOG_V(ERROR, TAG, "Can't get: %s", OC_RSRVD_LAST_UPDATE);
742         result = OC_STACK_ERROR;
743     }
744
745 exit:
746     if (result != OC_STACK_OK)
747     {
748         OIC_LOG(DEBUG, TAG, "Assume you are first time get Crl, and it can be absent in database");
749         OIC_LOG_V(DEBUG, TAG, "Return default last update time %s", CRL_DEFAULT_LAST_UPDATE);
750
751         *lastUpdate = OICStrdup(CRL_DEFAULT_LAST_UPDATE);
752         result = OC_STACK_OK;
753     }
754     OCPayloadDestroy((OCPayload *)payload);
755
756     return result;
757 }
758
759 uint8_t *GetCrl()
760 {
761     uint8_t *data = NULL;
762     size_t size = 0;
763     OicSecCrl_t *crl = NULL;
764     if (OC_STACK_OK == GetSecureVirtualDatabaseFromPS(OIC_CBOR_CRL_NAME, &data, &size) && data &&
765         OC_STACK_OK == CBORPayloadToCrl(data, size, &crl))
766     {
767         return crl->CrlData.data;
768     }
769     return NULL;
770 }
771
772 void GetDerCrl(ByteArray_t* out)
773 {
774     if(NULL == out)
775     {
776         return;
777     }
778
779     OicSecCrl_t *crlRes = GetCRLResource();
780
781     if(NULL == crlRes)
782     {
783         return;
784     }
785
786     OicSecKey_t *crl = &crlRes->CrlData;
787
788     if (OIC_ENCODING_BASE64 == crl->encoding)
789     {
790         size_t outSize = B64DECODE_OUT_SAFESIZE((crl->len + 1));
791         uint8_t *out = OICCalloc(1, outSize);
792         if (!out)
793         {
794             OIC_LOG(ERROR, TAG, "Can't allocate memory for base64 str");
795             return;
796         }
797         uint32_t len = 0;
798
799         if(B64_OK == b64Decode((char*)crl->data, crl->len, out, outSize, &len))
800         {
801             memcpy(crl->data, out, len);
802             crl->len = (size_t)len;
803
804             OIC_LOG (ERROR, TAG, "Crl successfully decoded to base64.");
805         }
806         else
807         {
808             OIC_LOG (ERROR, TAG, "Base64 decoding failed.");
809         }
810     }
811
812     out->len = 0;
813
814     out->data = OICMalloc(crl->len);
815     if (out->data)
816     {
817         memcpy(out->data, crl->data, crl->len);
818         out->len = crl->len;
819     }
820     else
821     {
822         OIC_LOG(ERROR, TAG, "Can't allocate memory for out->data");
823     }
824     DeleteCrl(crlRes);
825 }