CRED payload conversion from JSON to CBOR
[platform/upstream/iotivity.git] / resource / csdk / security / src / svcresource.c
1 //******************************************************************
2 //
3 // Copyright 2015 Intel Mobile Communications GmbH 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 #include <stdlib.h>
21 #include <string.h>
22
23 #include "ocstack.h"
24 #include "ocpayload.h"
25 #include "oic_malloc.h"
26 #include "utlist.h"
27 #include "payload_logging.h"
28 #include "resourcemanager.h"
29 #include "psinterface.h"
30 #include "svcresource.h"
31 #include "srmresourcestrings.h"
32 #include "srmutility.h"
33
34 #include "security_internals.h"
35
36 #define TAG  "SRM-SVC"
37
38 /** Default cbor payload size. This value is increased in case of CborErrorOutOfMemory.
39  * The value of payload size is increased until reaching belox max cbor size. */
40 static const uint8_t CBOR_SIZE = 255;
41
42 /** Max cbor size payload. */
43 static const uint16_t CBOR_MAX_SIZE = 4400;
44
45 /** SVC Map size - Number of mandatory items. */
46 static const uint8_t SVC_MAP_SIZE = 3;
47
48 static OicSecSvc_t        *gSvc = NULL;
49 static OCResourceHandle    gSvcHandle = NULL;
50
51 void DeleteSVCList(OicSecSvc_t* svc)
52 {
53     if (svc)
54     {
55         OicSecSvc_t *svcTmp1 = NULL, *svcTmp2 = NULL;
56         LL_FOREACH_SAFE(svc, svcTmp1, svcTmp2)
57         {
58             LL_DELETE(svc, svcTmp1);
59
60             // Clean Owners
61             OICFree(svcTmp1->owners);
62
63             // Clean SVC node itself
64             OICFree(svcTmp1);
65         }
66     }
67 }
68
69 static size_t svcElementsCount(const OicSecSvc_t *secSvc)
70 {
71     size_t size = 0;
72     for (const OicSecSvc_t *svc = secSvc; svc; svc = svc->next)
73     {
74         size++;
75     }
76     return size;
77 }
78
79 OCStackResult SVCToCBORPayload(const OicSecSvc_t *svc, uint8_t **cborPayload,
80                                size_t *cborSize)
81 {
82     if (NULL == svc || NULL == cborPayload || NULL != *cborPayload || NULL == cborSize)
83     {
84        return OC_STACK_INVALID_PARAM;
85     }
86
87     size_t cborLen = *cborSize;
88     if (0 == cborLen)
89     {
90         cborLen = CBOR_SIZE;
91     }
92     *cborPayload = NULL;
93     *cborSize = 0;
94
95     CborError cborEncoderResult = CborNoError;
96     OCStackResult ret = OC_STACK_ERROR;
97     CborEncoder encoder = { {.ptr = NULL }, .end = 0 };
98     CborEncoder svcArray = { {.ptr = NULL }, .end = 0 };
99
100     uint8_t *outPayload = (uint8_t *)OICCalloc(1, cborLen);
101     VERIFY_NON_NULL(TAG, outPayload, ERROR);
102
103     cbor_encoder_init(&encoder, outPayload, cborLen, 0);
104
105     // Create SVC Array
106     cborEncoderResult = cbor_encoder_create_array(&encoder, &svcArray,
107                                                   svcElementsCount(svc));
108     VERIFY_CBOR_SUCCESS(TAG, cborEncoderResult, "Failed to Create SVC Array.");
109
110     while (svc)
111     {
112         CborEncoder svcMap = { {.ptr = NULL }, .end = 0};
113         cborEncoderResult = cbor_encoder_create_map(&svcArray, &svcMap, SVC_MAP_SIZE);
114         VERIFY_CBOR_SUCCESS(TAG, cborEncoderResult, "Failed to Create SVC Map.");
115
116         // Service Device Identity
117         cborEncoderResult = cbor_encode_text_string(&svcMap, OIC_JSON_SERVICE_DEVICE_ID,
118             strlen(OIC_JSON_SERVICE_DEVICE_ID));
119         VERIFY_CBOR_SUCCESS(TAG, cborEncoderResult, "Failed to Add SVC Device Id.");
120         cborEncoderResult = cbor_encode_byte_string(&svcMap, (uint8_t *)svc->svcdid.id,
121             sizeof(svc->svcdid.id));
122         VERIFY_CBOR_SUCCESS(TAG, cborEncoderResult, "Failed to ");
123
124         // Service Type
125         cborEncoderResult = cbor_encode_text_string(&svcMap, OIC_JSON_SERVICE_TYPE,
126             strlen(OIC_JSON_SERVICE_TYPE));
127         VERIFY_CBOR_SUCCESS(TAG, cborEncoderResult, "Failed to Add SVC Serv Type Tag.");
128         cborEncoderResult = cbor_encode_int(&svcMap, svc->svct);
129         VERIFY_CBOR_SUCCESS(TAG, cborEncoderResult, "Failed to Add SVC Serv Type Value.");
130
131         // Owners
132         cborEncoderResult = cbor_encode_text_string(&svcMap, OIC_JSON_OWNERS_NAME,
133             strlen(OIC_JSON_OWNERS_NAME));
134         VERIFY_CBOR_SUCCESS(TAG, cborEncoderResult, "Failed to Add SVC Owners Tag.");
135         CborEncoder owners = { {.ptr = NULL }, .end = 0 };
136         cborEncoderResult = cbor_encoder_create_array(&svcMap, &owners, svc->ownersLen);
137         VERIFY_CBOR_SUCCESS(TAG, cborEncoderResult, "Failed to Add SVC Array.");
138         for (size_t i = 0; i < svc->ownersLen; i++)
139         {
140             cborEncoderResult = cbor_encode_byte_string(&owners, (uint8_t *)svc->owners[i].id,
141                 sizeof(svc->owners[i].id));
142             VERIFY_CBOR_SUCCESS(TAG, cborEncoderResult, "Failed to Add SVC Owners Value.");
143         }
144         cborEncoderResult = cbor_encoder_close_container(&svcMap, &owners);
145         VERIFY_CBOR_SUCCESS(TAG, cborEncoderResult, "Failed to Close SVC Array.");
146
147         cborEncoderResult = cbor_encoder_close_container(&svcArray, &svcMap);
148         VERIFY_CBOR_SUCCESS(TAG, cborEncoderResult, "Failed to Close SVC Map.");
149
150         svc = svc->next;
151     }
152
153     cborEncoderResult = cbor_encoder_close_container(&encoder, &svcArray);
154     VERIFY_CBOR_SUCCESS(TAG, cborEncoderResult, "Failed to Close SVC Array.");
155
156     *cborPayload = outPayload;
157     *cborSize = encoder.ptr - outPayload;
158     ret = OC_STACK_OK;
159
160 exit:
161     if ((CborErrorOutOfMemory == cborEncoderResult) && (cborLen < CBOR_MAX_SIZE))
162     {
163         // reallocate and try again!
164         OICFree(outPayload);
165         outPayload = NULL;
166         // Since the allocated initial memory failed, double the memory.
167         cborLen += encoder.ptr - encoder.end;
168         cborEncoderResult = CborNoError;
169         ret = SVCToCBORPayload(svc, cborPayload, &cborLen);
170     }
171
172     if (CborNoError != cborEncoderResult)
173     {
174         OICFree(outPayload);
175         outPayload = NULL;
176         *cborSize = 0;
177         *cborPayload = NULL;
178         ret = OC_STACK_ERROR;
179     }
180
181     return ret;
182 }
183
184 OCStackResult CBORPayloadToSVC(const uint8_t *cborPayload, size_t size,
185                                OicSecSvc_t **secSvc)
186 {
187     if (NULL == cborPayload || NULL == secSvc || NULL != *secSvc)
188     {
189         return OC_STACK_INVALID_PARAM;
190     }
191
192     *secSvc = NULL;
193
194     OCStackResult ret = OC_STACK_ERROR;
195
196     CborValue svcCbor = { .parser = NULL };
197     CborParser parser = { .end = NULL };
198     CborError cborFindResult = CborNoError;
199     int cborLen = size;
200     if (0 == size)
201     {
202        cborLen = CBOR_SIZE;
203     }
204     cbor_parser_init(cborPayload, cborLen, 0, &parser, &svcCbor);
205
206     OicSecSvc_t *headSvc = NULL;
207
208     CborValue svcArray = { .parser = NULL };
209     cborFindResult = cbor_value_enter_container(&svcCbor, &svcArray);
210     VERIFY_CBOR_SUCCESS(TAG, cborFindResult, "Failed to Enter SVC Array.");
211
212     while (cbor_value_is_valid(&svcArray))
213     {
214         CborValue svcMap = { .parser = NULL };
215         cborFindResult = cbor_value_enter_container(&svcArray, &svcMap);
216         VERIFY_CBOR_SUCCESS(TAG, cborFindResult, "Failed to Enter SVC Map.");
217
218         OicSecSvc_t *svc = (OicSecSvc_t *) OICCalloc(1, sizeof(OicSecSvc_t));
219         VERIFY_NON_NULL(TAG, svc, ERROR);
220
221         while (cbor_value_is_valid(&svcMap))
222         {
223             char* name = NULL;
224             size_t len = 0;
225             cborFindResult = cbor_value_dup_text_string(&svcMap, &name, &len, NULL);
226             VERIFY_CBOR_SUCCESS(TAG, cborFindResult, "Failed to Find Name.");
227             cborFindResult = cbor_value_advance(&svcMap);
228             VERIFY_CBOR_SUCCESS(TAG, cborFindResult, "Failed to Advance.");
229
230             CborType type = cbor_value_get_type(&svcMap);
231
232             // Service Device Identity
233             if (0 == strcmp(OIC_JSON_SERVICE_DEVICE_ID, name))
234             {
235                 uint8_t *subjectId = NULL;
236                 cborFindResult = cbor_value_dup_byte_string(&svcMap, &subjectId, &len, NULL);
237                 VERIFY_CBOR_SUCCESS(TAG, cborFindResult, "Failed to Find SubjectId.");
238                 memcpy(svc->svcdid.id, subjectId, len);
239                 OICFree(subjectId);
240             }
241             // Service Type
242             if (0 == strcmp(OIC_JSON_SERVICE_TYPE, name))
243             {
244                 cborFindResult = cbor_value_get_int(&svcMap, (int *) &svc->svct);
245                 VERIFY_CBOR_SUCCESS(TAG, cborFindResult, "Failed to Find SVCT.");
246             }
247
248             // Owners -- Mandatory
249             if (0 == strcmp(OIC_JSON_OWNERS_NAME, name))
250             {
251                 CborValue owners = { .parser = NULL };
252                 cborFindResult = cbor_value_get_array_length(&svcMap, &svc->ownersLen);
253                 VERIFY_CBOR_SUCCESS(TAG, cborFindResult, "Failed to Find Owner Len.");
254                 cborFindResult = cbor_value_enter_container(&svcMap, &owners);
255                 VERIFY_CBOR_SUCCESS(TAG, cborFindResult, "Failed to Enter Owner Array.");
256                 int i = 0;
257                 svc->owners = (OicUuid_t *)OICCalloc(svc->ownersLen, sizeof(*svc->owners));
258                 VERIFY_NON_NULL(TAG, svc->owners, ERROR);
259                 while (cbor_value_is_valid(&owners))
260                 {
261                     uint8_t *owner = NULL;
262                     cborFindResult = cbor_value_dup_byte_string(&owners, &owner, &len, NULL);
263                     VERIFY_CBOR_SUCCESS(TAG, cborFindResult, "Failed to Find Owner Array Value.");
264                     cborFindResult = cbor_value_advance(&owners);
265                     VERIFY_CBOR_SUCCESS(TAG, cborFindResult, "Failed to Advance Owner Array.");
266                     memcpy(svc->owners[i].id, owner, len);
267                     OICFree(owner);
268                 }
269             }
270             if (CborMapType != type  && cbor_value_is_valid(&svcMap))
271             {
272                 cborFindResult = cbor_value_advance(&svcMap);
273                 VERIFY_CBOR_SUCCESS(TAG, cborFindResult, "Failed to Advance SVC.");
274             }
275             OICFree(name);
276         }
277
278         svc->next = NULL;
279         if (NULL == headSvc)
280         {
281             headSvc = svc;
282         }
283         else
284         {
285             OicSecSvc_t *temp = headSvc;
286             while (temp->next)
287             {
288                 temp = temp->next;
289             }
290             temp->next = svc;
291         }
292         if (cbor_value_is_valid(&svcArray))
293         {
294             cborFindResult = cbor_value_advance(&svcArray);
295             VERIFY_CBOR_SUCCESS(TAG, cborFindResult, "Failed to Find Name.");
296         }
297     }
298     *secSvc = headSvc;
299     ret = OC_STACK_OK;
300
301 exit:
302     if (CborNoError != cborFindResult)
303     {
304         DeleteSVCList(headSvc);
305         headSvc = NULL;
306         ret = OC_STACK_ERROR;
307     }
308     return ret;
309 }
310
311 static OCEntityHandlerResult HandleSVCGetRequest (const OCEntityHandlerRequest * ehRequest)
312 {
313     // Convert SVC data into JSON for transmission
314     size_t size = 0;
315     uint8_t *cborSvc = NULL;
316     OCStackResult res =  SVCToCBORPayload(gSvc, &cborSvc, &size);
317     OCEntityHandlerResult ehRet = (res == OC_STACK_OK) ? OC_EH_OK : OC_EH_ERROR;
318
319     // Send response payload to request originator
320     SendSRMCBORResponse(ehRequest, ehRet, cborSvc);
321
322     OICFree(cborSvc);
323
324     OIC_LOG_V (DEBUG, TAG, "%s RetVal %d", __func__ , ehRet);
325     return ehRet;
326 }
327
328 static OCEntityHandlerResult HandleSVCPostRequest (const OCEntityHandlerRequest * ehRequest)
329 {
330     OCEntityHandlerResult ehRet = OC_EH_ERROR;
331     uint8_t *payload = ((OCSecurityPayload *) ehRequest->payload)->securityData1;;
332     if (payload)
333     {
334         // Convert CBOR SVC data into SVC. This will also validate the SVC data received.
335         OicSecSvc_t *newSvc = NULL;
336         OCStackResult res =  CBORPayloadToSVC(payload, CBOR_SIZE, &newSvc);
337         if (newSvc && res == OC_STACK_OK)
338         {
339             // Append the new SVC to existing SVC
340             LL_APPEND(gSvc, newSvc);
341
342             // Convert SVC data into JSON for update to persistent storage
343             size_t size = 0;
344             uint8_t *cborPayload = NULL;
345             res = SVCToCBORPayload(gSvc, &cborPayload, &size);
346             if (cborPayload && OC_STACK_OK == res &&
347                 UpdateSecureResourceInPS(OIC_JSON_SVC_NAME, cborPayload, size) == OC_STACK_OK)
348             {
349                 ehRet = OC_EH_RESOURCE_CREATED;
350             }
351             OICFree(cborPayload);
352         }
353     }
354
355     // Send payload to request originator
356     SendSRMCBORResponse(ehRequest, ehRet, NULL);
357
358     OIC_LOG_V (DEBUG, TAG, "%s RetVal %d", __func__ , ehRet);
359     return ehRet;
360 }
361
362 /*
363  * This internal method is the entity handler for SVC resources and
364  * will handle REST request (GET/PUT/POST/DEL) for them.
365  */
366 OCEntityHandlerResult SVCEntityHandler (OCEntityHandlerFlag flag,
367                                         OCEntityHandlerRequest * ehRequest,
368                                         void* callbackParameter)
369 {
370     (void) callbackParameter;
371     OCEntityHandlerResult ehRet = OC_EH_ERROR;
372
373     if (!ehRequest)
374     {
375         return ehRet;
376     }
377
378     if (flag & OC_REQUEST_FLAG)
379     {
380         switch (ehRequest->method)
381         {
382             case OC_REST_GET:
383                 ehRet = HandleSVCGetRequest(ehRequest);
384                 break;
385
386             case OC_REST_POST:
387                 ehRet = HandleSVCPostRequest(ehRequest);
388                 break;
389
390             default:
391                 ehRet = OC_EH_ERROR;
392                 SendSRMCBORResponse(ehRequest, ehRet, NULL);
393         }
394     }
395
396     return ehRet;
397 }
398
399 /*
400  * This internal method is used to create '/oic/sec/svc' resource.
401  */
402 OCStackResult CreateSVCResource()
403 {
404     OCStackResult ret;
405
406     ret = OCCreateResource(&gSvcHandle,
407                            OIC_RSRC_TYPE_SEC_SVC,
408                            OIC_MI_DEF,
409                            OIC_RSRC_SVC_URI,
410                            SVCEntityHandler,
411                            NULL,
412                            OC_OBSERVABLE);
413
414     if (OC_STACK_OK != ret)
415     {
416         OIC_LOG(FATAL, TAG, "Unable to instantiate SVC resource");
417         DeInitSVCResource();
418     }
419     return ret;
420 }
421
422
423 OCStackResult InitSVCResource()
424 {
425     OIC_LOG_V (DEBUG, TAG, "Begin %s ", __func__ );
426     OCStackResult ret = OC_STACK_ERROR;
427
428     uint8_t *data = NULL;
429     size_t size = 0;
430     ret = GetSecureVirtualDatabaseFromPS(OIC_JSON_SVC_NAME, &data, &size);
431     // If database read failed
432     if (ret != OC_STACK_OK)
433     {
434         OIC_LOG (DEBUG, TAG, "ReadSVDataFromPS failed");
435     }
436
437     if (data)
438     {
439         // Convert JSON SVC into binary format
440         ret = CBORPayloadToSVC(data, size, &gSvc);
441         OICFree(data);
442     }
443
444     // Instantiate 'oic.sec.svc'
445     ret = CreateSVCResource();
446
447     if (OC_STACK_OK != ret)
448     {
449         DeInitSVCResource();
450     }
451
452     OIC_LOG_V (DEBUG, TAG, "%s RetVal %d", __func__ , ret);
453     return ret;
454 }
455
456 /**
457  * Perform cleanup for SVC resources.
458  *
459  * @retval  none
460  */
461 void DeInitSVCResource()
462 {
463     OCDeleteResource(gSvcHandle);
464     gSvcHandle = NULL;
465
466     DeleteSVCList(gSvc);
467     gSvc = NULL;
468 }