1 //******************************************************************
3 // Copyright 2015 Intel Mobile Communications GmbH All Rights Reserved.
5 //-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
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
11 // http://www.apache.org/licenses/LICENSE-2.0
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.
19 //-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
24 #include "ocpayload.h"
25 #include "oic_malloc.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"
34 #include "security_internals.h"
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 uint16_t CBOR_SIZE = 512;
42 /** Max cbor size payload. */
43 static const uint16_t CBOR_MAX_SIZE = 4400;
45 /** SVC Map size - Number of mandatory items. */
46 static const uint8_t SVC_MAP_SIZE = 3;
48 static OicSecSvc_t *gSvc = NULL;
49 static OCResourceHandle gSvcHandle = NULL;
51 void DeleteSVCList(OicSecSvc_t* svc)
55 OicSecSvc_t *svcTmp1 = NULL, *svcTmp2 = NULL;
56 LL_FOREACH_SAFE(svc, svcTmp1, svcTmp2)
58 LL_DELETE(svc, svcTmp1);
61 OICFree(svcTmp1->owners);
63 // Clean SVC node itself
69 static size_t svcElementsCount(const OicSecSvc_t *secSvc)
72 for (const OicSecSvc_t *svc = secSvc; svc; svc = svc->next)
79 OCStackResult SVCToCBORPayload(const OicSecSvc_t *svc, uint8_t **cborPayload,
82 if (NULL == svc || NULL == cborPayload || NULL != *cborPayload || NULL == cborSize)
84 return OC_STACK_INVALID_PARAM;
87 size_t cborLen = *cborSize;
95 int64_t cborEncoderResult = CborNoError;
96 OCStackResult ret = OC_STACK_ERROR;
100 uint8_t *outPayload = (uint8_t *)OICCalloc(1, cborLen);
101 VERIFY_NON_NULL(TAG, outPayload, ERROR);
103 cbor_encoder_init(&encoder, outPayload, cborLen, 0);
106 cborEncoderResult = cbor_encoder_create_array(&encoder, &svcArray, svcElementsCount(svc));
107 VERIFY_CBOR_SUCCESS(TAG, cborEncoderResult, "Failed to Create SVC Array.");
114 cborEncoderResult = cbor_encoder_create_map(&svcArray, &svcMap, SVC_MAP_SIZE);
115 VERIFY_CBOR_SUCCESS(TAG, cborEncoderResult, "Failed to Create SVC Map.");
117 // Service Device Identity
118 cborEncoderResult = cbor_encode_text_string(&svcMap, OIC_JSON_SERVICE_DEVICE_ID,
119 strlen(OIC_JSON_SERVICE_DEVICE_ID));
120 VERIFY_CBOR_SUCCESS(TAG, cborEncoderResult, "Failed to Add SVC Device Id.");
121 cborEncoderResult = cbor_encode_byte_string(&svcMap, (uint8_t *)svc->svcdid.id,
122 sizeof(svc->svcdid.id));
123 VERIFY_CBOR_SUCCESS(TAG, cborEncoderResult, "Failed to ");
126 cborEncoderResult = cbor_encode_text_string(&svcMap, OIC_JSON_SERVICE_TYPE,
127 strlen(OIC_JSON_SERVICE_TYPE));
128 VERIFY_CBOR_SUCCESS(TAG, cborEncoderResult, "Failed to Add SVC Serv Type Tag.");
129 cborEncoderResult = cbor_encode_int(&svcMap, svc->svct);
130 VERIFY_CBOR_SUCCESS(TAG, cborEncoderResult, "Failed to Add SVC Serv Type Value.");
133 // TODO: Need to modification to single ROwner, (Currently SINGLE_SERVICE_CLIENT_DRIVEN only)
134 cborEncoderResult = cbor_encode_text_string(&svcMap, OIC_JSON_OWNERS_NAME,
135 strlen(OIC_JSON_OWNERS_NAME));
136 VERIFY_CBOR_SUCCESS(TAG, cborEncoderResult, "Failed to Add SVC Owners Tag.");
137 cborEncoderResult = cbor_encoder_create_array(&svcMap, &owners, svc->ownersLen);
138 VERIFY_CBOR_SUCCESS(TAG, cborEncoderResult, "Failed to Add SVC Array.");
139 for (size_t i = 0; i < svc->ownersLen; i++)
141 cborEncoderResult = cbor_encode_byte_string(&owners, (uint8_t *)svc->owners[i].id,
142 sizeof(svc->owners[i].id));
143 VERIFY_CBOR_SUCCESS(TAG, cborEncoderResult, "Failed to Add SVC Owners Value.");
145 cborEncoderResult = cbor_encoder_close_container(&svcMap, &owners);
146 VERIFY_CBOR_SUCCESS(TAG, cborEncoderResult, "Failed to Close SVC Array.");
148 cborEncoderResult = cbor_encoder_close_container(&svcArray, &svcMap);
149 VERIFY_CBOR_SUCCESS(TAG, cborEncoderResult, "Failed to Close SVC Map.");
154 cborEncoderResult = cbor_encoder_close_container(&encoder, &svcArray);
155 VERIFY_CBOR_SUCCESS(TAG, cborEncoderResult, "Failed to Close SVC Array.");
157 if (CborNoError == cborEncoderResult)
159 *cborPayload = outPayload;
160 *cborSize = encoder.ptr - outPayload;
165 if ((CborErrorOutOfMemory == cborEncoderResult) && (cborLen < CBOR_MAX_SIZE))
167 // reallocate and try again!
170 // Since the allocated initial memory failed, double the memory.
171 cborLen += encoder.ptr - encoder.end;
172 cborEncoderResult = CborNoError;
173 ret = SVCToCBORPayload(svc, cborPayload, &cborLen);
177 if (CborNoError != cborEncoderResult)
183 ret = OC_STACK_ERROR;
189 OCStackResult CBORPayloadToSVC(const uint8_t *cborPayload, size_t size,
190 OicSecSvc_t **secSvc)
192 if (NULL == cborPayload || NULL == secSvc || NULL != *secSvc || 0 == size)
194 return OC_STACK_INVALID_PARAM;
199 OCStackResult ret = OC_STACK_ERROR;
201 CborValue svcCbor = { .parser = NULL };
202 CborParser parser = { .end = NULL };
203 CborError cborFindResult = CborNoError;
205 cbor_parser_init(cborPayload, size, 0, &parser, &svcCbor);
206 OicSecSvc_t *headSvc = NULL;
208 CborValue svcArray = { .parser = NULL };
209 cborFindResult = cbor_value_enter_container(&svcCbor, &svcArray);
210 VERIFY_CBOR_SUCCESS(TAG, cborFindResult, "Failed to Enter SVC Array.");
212 while (cbor_value_is_valid(&svcArray))
214 CborValue svcMap = { .parser = NULL };
215 OicSecSvc_t *svc = (OicSecSvc_t *) OICCalloc(1, sizeof(OicSecSvc_t));
216 VERIFY_NON_NULL(TAG, svc, ERROR);
217 cborFindResult = cbor_value_enter_container(&svcArray, &svcMap);
218 VERIFY_CBOR_SUCCESS(TAG, cborFindResult, "Failed to Enter SVC Map.");
220 while (cbor_value_is_valid(&svcMap))
224 CborType type = CborInvalidType;
226 cborFindResult = cbor_value_dup_text_string(&svcMap, &name, &len, NULL);
227 VERIFY_CBOR_SUCCESS(TAG, cborFindResult, "Failed to Find Name.");
228 cborFindResult = cbor_value_advance(&svcMap);
229 VERIFY_CBOR_SUCCESS(TAG, cborFindResult, "Failed to Advance.");
231 type = cbor_value_get_type(&svcMap);
232 // Service Device Identity
233 if (0 == strcmp(OIC_JSON_SERVICE_DEVICE_ID, name))
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);
242 if (0 == strcmp(OIC_JSON_SERVICE_TYPE, name))
244 cborFindResult = cbor_value_get_int(&svcMap, (int *) &svc->svct);
245 VERIFY_CBOR_SUCCESS(TAG, cborFindResult, "Failed to Find SVCT.");
248 // Owners -- Mandatory
249 if (0 == strcmp(OIC_JSON_OWNERS_NAME, name))
252 CborValue owners = { .parser = NULL };
254 cborFindResult = cbor_value_get_array_length(&svcMap, &svc->ownersLen);
255 VERIFY_CBOR_SUCCESS(TAG, cborFindResult, "Failed to Find Owner Len.");
256 cborFindResult = cbor_value_enter_container(&svcMap, &owners);
257 VERIFY_CBOR_SUCCESS(TAG, cborFindResult, "Failed to Enter Owner Array.");
258 svc->owners = (OicUuid_t *)OICCalloc(svc->ownersLen, sizeof(*svc->owners));
259 VERIFY_NON_NULL(TAG, svc->owners, ERROR);
261 while (cbor_value_is_valid(&owners))
263 uint8_t *owner = NULL;
264 cborFindResult = cbor_value_dup_byte_string(&owners, &owner, &len, NULL);
265 VERIFY_CBOR_SUCCESS(TAG, cborFindResult, "Failed to Find Owner Array Value.");
266 cborFindResult = cbor_value_advance(&owners);
267 VERIFY_CBOR_SUCCESS(TAG, cborFindResult, "Failed to Advance Owner Array.");
268 memcpy(svc->owners[i++].id, owner, len);
272 if (CborMapType != type && cbor_value_is_valid(&svcMap))
274 cborFindResult = cbor_value_advance(&svcMap);
275 VERIFY_CBOR_SUCCESS(TAG, cborFindResult, "Failed to Advance SVC.");
287 OicSecSvc_t *temp = headSvc;
294 if (cbor_value_is_valid(&svcArray))
296 cborFindResult = cbor_value_advance(&svcArray);
297 VERIFY_CBOR_SUCCESS(TAG, cborFindResult, "Failed to Find Name.");
304 if (CborNoError != cborFindResult)
306 DeleteSVCList(headSvc);
309 ret = OC_STACK_ERROR;
314 static OCEntityHandlerResult HandleSVCGetRequest(const OCEntityHandlerRequest * ehRequest)
316 // Convert SVC data into JSON for transmission
318 uint8_t *cborSvc = NULL;
319 OCStackResult res = SVCToCBORPayload(gSvc, &cborSvc, &size);
320 OCEntityHandlerResult ehRet = (res == OC_STACK_OK) ? OC_EH_OK : OC_EH_ERROR;
322 // Send response payload to request originator
323 if (OC_STACK_OK != SendSRMResponse(ehRequest, ehRet, cborSvc, size))
326 OIC_LOG(ERROR, TAG, "SendSRMResponse failed in HandleSVCGetRequest");
330 OIC_LOG_V (DEBUG, TAG, "%s RetVal %d", __func__ , ehRet);
334 static OCEntityHandlerResult HandleSVCPostRequest(const OCEntityHandlerRequest * ehRequest)
336 OCEntityHandlerResult ehRet = OC_EH_ERROR;
337 uint8_t *payload = ((OCSecurityPayload *) ehRequest->payload)->securityData;
338 size_t size = ((OCSecurityPayload *) ehRequest->payload)->payloadSize;
341 // Convert CBOR SVC data into SVC. This will also validate the SVC data received.
342 OicSecSvc_t *newSvc = NULL;
343 OCStackResult res = CBORPayloadToSVC(payload, size, &newSvc);
344 if (newSvc && res == OC_STACK_OK)
346 // Append the new SVC to existing SVC
347 LL_APPEND(gSvc, newSvc);
349 // Convert SVC data into JSON for update to persistent storage
351 uint8_t *cborPayload = NULL;
352 res = SVCToCBORPayload(gSvc, &cborPayload, &size);
353 if (cborPayload && OC_STACK_OK == res &&
354 UpdateSecureResourceInPS(OIC_JSON_SVC_NAME, cborPayload, size) == OC_STACK_OK)
356 ehRet = OC_EH_RESOURCE_CREATED;
358 OICFree(cborPayload);
362 // Send payload to request originator
363 if (OC_STACK_OK != SendSRMResponse(ehRequest, ehRet, NULL, 0))
366 OIC_LOG(ERROR, TAG, "SendSRMResponse failed in HandleSVCPostRequest");
369 OIC_LOG_V (DEBUG, TAG, "%s RetVal %d", __func__ , ehRet);
374 * This internal method is the entity handler for SVC resources and
375 * will handle REST request (GET/PUT/POST/DEL) for them.
377 static OCEntityHandlerResult SVCEntityHandler(OCEntityHandlerFlag flag,
378 OCEntityHandlerRequest * ehRequest,
379 void* callbackParameter)
381 (void) callbackParameter;
382 OCEntityHandlerResult ehRet = OC_EH_ERROR;
389 if (flag & OC_REQUEST_FLAG)
391 switch (ehRequest->method)
394 ehRet = HandleSVCGetRequest(ehRequest);
398 ehRet = HandleSVCPostRequest(ehRequest);
403 SendSRMResponse(ehRequest, ehRet, NULL, 0);
411 * This internal method is used to create '/oic/sec/svc' resource.
413 static OCStackResult CreateSVCResource()
415 OCStackResult ret = OCCreateResource(&gSvcHandle,
416 OIC_RSRC_TYPE_SEC_SVC,
423 if (OC_STACK_OK != ret)
425 OIC_LOG(FATAL, TAG, "Unable to instantiate SVC resource");
431 OCStackResult InitSVCResource()
433 OCStackResult ret = OC_STACK_ERROR;
435 OIC_LOG_V(DEBUG, TAG, "Begin %s ", __func__ );
437 uint8_t *data = NULL;
439 ret = GetSecureVirtualDatabaseFromPS(OIC_JSON_SVC_NAME, &data, &size);
440 // If database read failed
441 if (ret != OC_STACK_OK)
443 OIC_LOG (DEBUG, TAG, "ReadSVDataFromPS failed");
448 // Convert CBOR SVC into binary format
449 ret = CBORPayloadToSVC(data, size, &gSvc);
450 if (ret != OC_STACK_OK)
452 OIC_LOG (DEBUG, TAG, " ConvertCBOR SVC into binary format failed");
457 // Instantiate 'oic.sec.svc'
458 ret = CreateSVCResource();
460 if (OC_STACK_OK != ret)
465 OIC_LOG_V(DEBUG, TAG, "%s RetVal %d", __func__ , ret);
469 void DeInitSVCResource()
471 OCDeleteResource(gSvcHandle);