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