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