Merge "Merge remote-tracking branch 'origin/master' into notification-service" into...
[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 "crlresource.h"
31 #include "crl.h"
32
33 #define TAG  "SRM-CRL"
34
35 #define SEPARATOR                   ":"
36 #define SEPARATOR_LEN               (1)
37 #define CBOR_CRL_NAME               "\"CRL\""
38 #define CBOR_CRL_NAME_LEN           (5)
39 #define OIC_CBOR_CRL_NAME           "crl"
40 #define OIC_CBOR_CRL_ID             "CRLId"
41 #define OIC_CBOR_CRL_THIS_UPDATE    "ThisUpdate"
42 #define OIC_CBOR_CRL_DATA           "CRLData"
43 #define CRL_DEFAULT_CRL_ID          (1)
44 #define CRL_DEFAULT_THIS_UPDATE     "150101000000Z"
45 #define CRL_DEFAULT_CRL_DATA        "-"
46
47 static OCResourceHandle     gCrlHandle  = NULL;
48 static OicSecCrl_t         *gCrl        = NULL;
49
50 /** Default cbor payload size. This value is increased in case of CborErrorOutOfMemory.
51  * The value of payload size is increased until reaching below max cbor size. */
52 static const uint16_t CBOR_SIZE = 1024;
53
54 // Max cbor size payload.
55 static const uint16_t CBOR_MAX_SIZE = 4400;
56
57 // PSTAT Map size - Number of mandatory items
58 static const uint8_t CRL_MAP_SIZE = 3;
59
60 void DeleteCrlBinData(OicSecCrl_t *crl)
61 {
62     if (crl)
63     {
64         //Clean ThisUpdate
65         OICFree(crl->ThisUpdate.data);
66
67         //clean CrlData
68         OICFree(crl->CrlData.data);
69
70         //Clean crl itself
71         OICFree(crl);
72     }
73 }
74
75 OCStackResult CrlToCBORPayload(const OicSecCrl_t *crl, uint8_t **payload, size_t *size)
76 {
77     if (NULL == crl || NULL == payload || NULL != *payload || NULL == size)
78     {
79         return OC_STACK_INVALID_PARAM;
80     }
81
82     size_t cborLen = *size;
83     if (0 == cborLen)
84     {
85         cborLen = CBOR_SIZE;
86     }
87
88     *payload = NULL;
89     *size = 0;
90
91     OCStackResult ret = OC_STACK_ERROR;
92
93     CborEncoder encoder;
94     CborEncoder crlMap;
95
96     CborError cborEncoderResult = CborNoError;
97
98     uint8_t *outPayload = (uint8_t *)OICCalloc(1, cborLen);
99     VERIFY_NON_NULL(TAG, outPayload, ERROR);
100     cbor_encoder_init(&encoder, outPayload, cborLen, 0);
101
102     cborEncoderResult = cbor_encoder_create_map(&encoder, &crlMap, CRL_MAP_SIZE);
103     VERIFY_CBOR_SUCCESS(TAG, cborEncoderResult, "Failed to create CRL Map");
104
105     //CRLId -- Mandatory
106     cborEncoderResult = cbor_encode_text_string(&crlMap, OIC_CBOR_CRL_ID,
107         strlen(OIC_CBOR_CRL_ID));
108     VERIFY_CBOR_SUCCESS(TAG, cborEncoderResult, "Failed to add CRL ID");
109     cborEncoderResult = cbor_encode_int(&crlMap, crl->CrlId);
110     VERIFY_CBOR_SUCCESS(TAG, cborEncoderResult, "Failed to add CRL Id value");
111
112     //ThisUpdate -- Mandatory
113     cborEncoderResult = cbor_encode_text_string(&crlMap, OIC_CBOR_CRL_THIS_UPDATE,
114         strlen(OIC_CBOR_CRL_THIS_UPDATE));
115     VERIFY_CBOR_SUCCESS(TAG, cborEncoderResult, "Failed to add Crl update");
116     cborEncoderResult = cbor_encode_byte_string(&crlMap, crl->ThisUpdate.data,
117                                                 crl->ThisUpdate.len);
118     VERIFY_CBOR_SUCCESS(TAG, cborEncoderResult, "Failed to add Crl Update value");
119
120     //CRLData -- Mandatory
121     cborEncoderResult = cbor_encode_text_string(&crlMap, OIC_CBOR_CRL_DATA,
122         strlen(OIC_CBOR_CRL_DATA));
123     VERIFY_CBOR_SUCCESS(TAG, cborEncoderResult, "Failed to add Crl data name");
124     cborEncoderResult = cbor_encode_byte_string(&crlMap, crl->CrlData.data,
125                                                 crl->CrlData.len);
126     VERIFY_CBOR_SUCCESS(TAG, cborEncoderResult, "Failed to add Crl data value");
127
128     cborEncoderResult = cbor_encoder_close_container(&encoder, &crlMap);
129     VERIFY_CBOR_SUCCESS(TAG, cborEncoderResult, "Failed to add close Crl map");
130
131     *size = encoder.ptr - outPayload;
132     *payload = outPayload;
133     ret = OC_STACK_OK;
134
135 exit:
136     if ((CborErrorOutOfMemory == cborEncoderResult) && (cborLen < CBOR_MAX_SIZE))
137     {
138         // reallocate and try again!
139         OICFree(outPayload);
140         // Since the allocated initial memory failed, double the memory.
141         cborLen += encoder.ptr - encoder.end;
142         cborEncoderResult = CborNoError;
143         ret = CrlToCBORPayload(crl, payload, &cborLen);
144     }
145
146     if ((CborNoError != cborEncoderResult) || (OC_STACK_OK != ret))
147     {
148         OICFree(outPayload);
149         outPayload = NULL;
150         *payload = NULL;
151         *size = 0;
152         ret = OC_STACK_ERROR;
153     }
154
155     return ret;
156 }
157
158 OCStackResult CBORPayloadToCrl(const uint8_t *cborPayload, const size_t size,
159                                OicSecCrl_t **secCrl)
160 {
161     if (NULL == cborPayload || NULL == secCrl || NULL != *secCrl || 0 == size)
162     {
163         return OC_STACK_INVALID_PARAM;
164     }
165
166     OCStackResult ret = OC_STACK_ERROR;
167     *secCrl = NULL;
168
169     CborValue crlCbor = {.parser = NULL};
170     CborParser parser = {.end = NULL};
171     CborError cborFindResult = CborNoError;
172
173     cbor_parser_init(cborPayload, size, 0, &parser, &crlCbor);
174     CborValue crlMap = { .parser = NULL};
175     OicSecCrl_t *crl = NULL;
176     size_t outLen = 0;
177     cborFindResult = cbor_value_enter_container(&crlCbor, &crlMap);
178     VERIFY_CBOR_SUCCESS(TAG, cborFindResult, "Failed to enter Crl map");
179
180     crl = (OicSecCrl_t *)OICCalloc(1, sizeof(OicSecCrl_t));
181     VERIFY_NON_NULL(TAG, crl, ERROR);
182
183     cborFindResult = cbor_value_map_find_value(&crlCbor, OIC_CBOR_CRL_ID, &crlMap);
184     if (CborNoError == cborFindResult && cbor_value_is_integer(&crlMap))
185     {
186         int CrlId;
187
188         cborFindResult = cbor_value_get_int(&crlMap, &CrlId);
189         VERIFY_CBOR_SUCCESS(TAG, cborFindResult, "Failed Finding CrlId.");
190         crl->CrlId = (uint16_t)CrlId;
191     }
192
193     cborFindResult = cbor_value_map_find_value(&crlCbor, OIC_CBOR_CRL_THIS_UPDATE, &crlMap);
194     if (CborNoError == cborFindResult && cbor_value_is_byte_string(&crlMap))
195     {
196         cborFindResult = cbor_value_dup_byte_string(&crlMap,
197             &crl->ThisUpdate.data, &crl->ThisUpdate.len, NULL);
198         VERIFY_CBOR_SUCCESS(TAG, cborFindResult, "Failed Advancing Byte Array.");
199     }
200     cborFindResult = cbor_value_map_find_value(&crlCbor, OIC_CBOR_CRL_DATA, &crlMap);
201     if (CborNoError == cborFindResult && cbor_value_is_byte_string(&crlMap))
202     {
203         cborFindResult = cbor_value_dup_byte_string(&crlMap,
204                          &crl->CrlData.data, &crl->CrlData.len, NULL);
205         VERIFY_CBOR_SUCCESS(TAG, cborFindResult, "Failed Advancing Byte Array.");
206     }
207
208     *secCrl = crl;
209     ret = OC_STACK_OK;
210 exit:
211     if (CborNoError != cborFindResult)
212     {
213         // PUT/POST CBOR may not have mandatory values set default values.
214         if (gCrl)
215         {
216             OIC_LOG (DEBUG, TAG, "Set default values");
217             crl->CrlId = gCrl->CrlId;
218             if (crl->ThisUpdate.data)
219             {
220                 OICFree(crl->ThisUpdate.data);
221             }
222             outLen = gCrl->ThisUpdate.len;
223             crl->ThisUpdate.data = (uint8_t*) OICMalloc(outLen);
224             if (crl->ThisUpdate.data)
225             {
226                 memcpy(crl->ThisUpdate.data, gCrl->ThisUpdate.data, outLen);
227                 crl->ThisUpdate.len = outLen;
228             }
229             else
230             {
231                 crl->ThisUpdate.len = 0;
232                 OIC_LOG(ERROR, TAG, "Set default failed");
233             }
234             if (crl->CrlData.data)
235             {
236                 OICFree(crl->CrlData.data);
237             }
238             outLen = gCrl->CrlData.len;
239             crl->CrlData.data = (uint8_t*) OICMalloc(outLen);
240             if (crl->CrlData.data && gCrl->CrlData.data)
241             {
242                 memcpy(crl->CrlData.data, gCrl->CrlData.data, outLen);
243                 crl->CrlData.len = outLen;
244             }
245             else
246             {
247                 crl->CrlData.len = 0;
248                 OIC_LOG (ERROR, TAG, "Set default failed");
249             }
250
251             *secCrl = crl;
252             ret = OC_STACK_OK;
253         }
254         else
255         {
256             OIC_LOG (ERROR, TAG, "CBORPayloadToCrl failed");
257             DeleteCrlBinData(crl);
258             crl = NULL;
259             ret = OC_STACK_ERROR;
260         }
261     }
262     return ret;
263 }
264
265 OCStackResult UpdateCRLResource(const OicSecCrl_t *crl)
266 {
267     uint8_t *payload = NULL;
268     size_t size = 0;
269
270     OCStackResult res = CrlToCBORPayload((OicSecCrl_t *) crl, &payload, &size);
271     if (OC_STACK_OK != res)
272     {
273         return res;
274     }
275
276     return UpdateSecureResourceInPS(OIC_CBOR_CRL_NAME, payload, size);
277 }
278
279 static OCEntityHandlerResult HandleCRLPostRequest(const OCEntityHandlerRequest *ehRequest)
280 {
281     OCEntityHandlerResult ehRet = OC_EH_ERROR;
282     OicSecCrl_t *crl = NULL;
283     uint8_t *payload = ((OCSecurityPayload *)ehRequest->payload)->securityData;
284     size_t size = ((OCSecurityPayload *) ehRequest->payload)->payloadSize;
285
286     if (payload)
287     {
288         OIC_LOG(INFO, TAG, "UpdateSVRDB...");
289         CBORPayloadToCrl(payload, size, &crl);
290         VERIFY_NON_NULL(TAG, crl, ERROR);
291
292         gCrl->CrlId = crl->CrlId;
293
294         OICFree(gCrl->ThisUpdate.data);
295         gCrl->ThisUpdate.data = NULL;
296         gCrl->ThisUpdate.data = OICMalloc(crl->ThisUpdate.len);
297         VERIFY_NON_NULL(TAG, gCrl->ThisUpdate.data, ERROR);
298         memcpy(gCrl->ThisUpdate.data, crl->ThisUpdate.data, crl->ThisUpdate.len);
299         gCrl->ThisUpdate.len = crl->ThisUpdate.len;
300
301         OICFree(gCrl->CrlData.data);
302         gCrl->CrlData.data = OICMalloc(crl->CrlData.len);
303         VERIFY_NON_NULL(TAG, gCrl->CrlData.data, ERROR);
304         memcpy(gCrl->CrlData.data, crl->CrlData.data, crl->CrlData.len);
305         gCrl->CrlData.len = crl->CrlData.len;
306
307         if (OC_STACK_OK == UpdateSecureResourceInPS(OIC_CBOR_CRL_NAME, payload, size))
308         {
309             ehRet = OC_EH_RESOURCE_CREATED;
310         }
311
312         DeleteCrlBinData(crl);
313     }
314
315 exit:
316     // Send payload to request originator
317     if (OC_STACK_OK != SendSRMResponse(ehRequest, ehRet, NULL, 0))
318     {
319         ehRet = OC_EH_ERROR;
320         OIC_LOG(ERROR, TAG, "SendSRMResponse failed in HandleCRLPostRequest");
321     }
322
323     OIC_LOG_V(INFO, TAG, "%s RetVal %d", __func__, ehRet);
324     return ehRet;
325 }
326
327
328 /**
329  * This internal method is the entity handler for CRL resource and
330  * will handle REST request (GET/PUT/POST/DEL) for them.
331  */
332 static OCEntityHandlerResult CRLEntityHandler(OCEntityHandlerFlag flag,
333                                               OCEntityHandlerRequest *ehRequest,
334                                               void *callbackParameter)
335 {
336     OCEntityHandlerResult ehRet = OC_EH_ERROR;
337     (void)callbackParameter;
338
339     if (!ehRequest)
340     {
341         return ehRet;
342     }
343
344     OIC_LOG(INFO, TAG, "Handle CRL resource");
345
346     if (flag & OC_REQUEST_FLAG)
347     {
348         // TODO :  Handle PUT and DEL methods
349         OIC_LOG (INFO, TAG, "Flag includes OC_REQUEST_FLAG");
350         switch (ehRequest->method)
351         {
352             case OC_REST_GET:
353                 OIC_LOG (INFO, TAG, "Not implemented request method.");
354                 //ehRet = HandleCRLGetRequest(ehRequest);
355                 break;
356
357             case OC_REST_POST:
358                 ehRet = HandleCRLPostRequest(ehRequest);
359                 break;
360
361             default:
362                 ehRet = OC_EH_ERROR;
363                 SendSRMResponse(ehRequest, ehRet, NULL, 0);
364         }
365     }
366
367     return ehRet;
368 }
369
370 /**
371  * This internal method is used to create '/oic/sec/crl' resource.
372  */
373 static OCStackResult CreateCRLResource()
374 {
375     OCStackResult ret = OCCreateResource(&gCrlHandle,
376                                          OIC_RSRC_TYPE_SEC_CRL,
377                                          OC_RSRVD_INTERFACE_DEFAULT,
378                                          OIC_RSRC_CRL_URI,
379                                          CRLEntityHandler,
380                                          NULL,
381                                          OC_OBSERVABLE);
382
383     if (OC_STACK_OK != ret)
384     {
385         OIC_LOG(FATAL, TAG, "Unable to instantiate CRL resource");
386         DeInitCRLResource();
387     }
388     return ret;
389 }
390
391 /**
392  * Get the default value.
393  * @return defaultCrl for now.
394  */
395 static OicSecCrl_t *GetCrlDefault()
396 {
397     OicSecCrl_t *defaultCrl = (OicSecCrl_t *)OICCalloc(1, sizeof(OicSecCrl_t));
398     if (NULL == defaultCrl)
399     {
400         return NULL;
401     }
402     defaultCrl->CrlId = CRL_DEFAULT_CRL_ID;
403
404     defaultCrl->CrlData.len = strlen(CRL_DEFAULT_CRL_DATA);
405     defaultCrl->CrlData.data = (uint8_t*) OICMalloc(defaultCrl->CrlData.len);
406     if (defaultCrl->CrlData.data)
407     {
408         memcpy(defaultCrl->CrlData.data, CRL_DEFAULT_CRL_DATA, defaultCrl->CrlData.len);
409     }
410     else
411     {
412         defaultCrl->CrlData.len = 0;
413     }
414
415     defaultCrl->ThisUpdate.len = strlen(CRL_DEFAULT_THIS_UPDATE);
416     defaultCrl->ThisUpdate.data = (uint8_t*) OICMalloc(defaultCrl->ThisUpdate.len);
417     if (defaultCrl->ThisUpdate.data)
418     {
419         memcpy(defaultCrl->ThisUpdate.data, CRL_DEFAULT_THIS_UPDATE, defaultCrl->ThisUpdate.len);
420     }
421     else
422     {
423         defaultCrl->ThisUpdate.len = 0;
424     }
425
426     return defaultCrl;
427 }
428
429 /**
430  * Initialize CRL resource by loading data from persistent storage.
431  *
432  * @retval
433  *     OC_STACK_OK    - no errors
434  *     OC_STACK_ERROR - stack process error
435  */
436 OCStackResult InitCRLResource()
437 {
438     OCStackResult ret = OC_STACK_ERROR;
439     // Read Crl resource from PS
440     uint8_t *data = NULL;
441     size_t size = 0;
442     ret = GetSecureVirtualDatabaseFromPS(OIC_CBOR_CRL_NAME, &data, &size);
443     // If database read failed
444     if (OC_STACK_OK != ret)
445     {
446         OIC_LOG (DEBUG, TAG, "ReadSVDataFromPS failed");
447     }
448     if (data)
449     {
450         // Read ACL resource from PS
451         ret = CBORPayloadToCrl(data, size, &gCrl);
452     }
453
454     /*
455      * If SVR database in persistent storage got corrupted or
456      * is not available for some reason, a default CrlResource is created
457      * which allows user to initiate CrlResource provisioning again.
458      */
459     if ((OC_STACK_OK != ret) || !data || !gCrl)
460     {
461         gCrl = GetCrlDefault();
462     }
463
464     ret = CreateCRLResource();
465     OICFree(data);
466     return ret;
467 }
468
469 /**
470  * Perform cleanup for ACL resources.
471  */
472 OCStackResult DeInitCRLResource()
473 {
474     OCStackResult result = OCDeleteResource(gCrlHandle);
475     gCrlHandle = NULL;
476     DeleteCrlBinData(gCrl);
477     gCrl = NULL;
478     return result;
479 }
480
481 OicSecCrl_t *GetCRLResource()
482 {
483     OicSecCrl_t *crl =  NULL;
484
485     //Read CRL resource from PS
486     uint8_t *data = NULL;
487     size_t size = 0;
488     OCStackResult ret = GetSecureVirtualDatabaseFromPS(OIC_CBOR_CRL_NAME, &data, &size);
489     if (data)
490     {
491         //Convert CBOR CRL into binary format
492         ret = CBORPayloadToCrl(data, size, &crl);
493     }
494     /*
495      * If SVR database in persistent storage got corrupted or
496      * is not available for some reason, a default CrlResource is created
497      * which allows user to initiate CrlResource provisioning again.
498      */
499     if ((OC_STACK_OK != ret) || !data || !crl)
500     {
501         crl = GetCrlDefault();
502     }
503     OICFree(data);
504
505     return crl;
506 }
507
508 uint8_t *GetCrl()
509 {
510     uint8_t *data = NULL;
511     size_t size = 0;
512     OicSecCrl_t *crl = NULL;
513     if (OC_STACK_OK == GetSecureVirtualDatabaseFromPS(OIC_CBOR_CRL_NAME, &data, &size) && data &&
514         OC_STACK_OK == CBORPayloadToCrl(data, size, &crl))
515     {
516         return crl->CrlData.data;
517     }
518     return NULL;
519 }
520
521 void  GetDerCrl(ByteArray* crlArray)
522 {
523     if(NULL == crlArray)
524     {
525         return;
526     }
527     OicSecCrl_t * crlRes = GetCRLResource();
528     if (NULL != crlArray->data && NULL != crlRes
529         && NULL !=crlRes->CrlData.data && crlRes->CrlData.len <= crlArray->len)
530     {
531         memcpy(crlArray->data, crlRes->CrlData.data, crlRes->CrlData.len);
532         crlArray->len = crlRes->CrlData.len;
533     }
534     else
535     {
536         crlArray->len = 0;
537     }
538     DeleteCrlBinData(crlRes);
539 }