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