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 "ocpayloadcbor.h"
26 #include "oic_malloc.h"
28 #include "payload_logging.h"
29 #include "resourcemanager.h"
30 #include "psinterface.h"
31 #include "svcresource.h"
32 #include "srmresourcestrings.h"
33 #include "srmutility.h"
35 #include "security_internals.h"
37 #define TAG "OIC_SRM_SVC"
39 /** Default cbor payload size. This value is increased in case of CborErrorOutOfMemory.
40 * The value of payload size is increased until reaching belox max cbor size. */
41 static const uint16_t CBOR_SIZE = 512;
43 /** Max cbor size payload. */
44 static const uint16_t CBOR_MAX_SIZE = 4400;
46 /** SVC Map size - Number of mandatory items. */
47 static const uint8_t SVC_MAP_SIZE = 3;
49 static OicSecSvc_t *gSvc = NULL;
50 static OCResourceHandle gSvcHandle = NULL;
52 void DeleteSVCList(OicSecSvc_t* svc)
56 OicSecSvc_t *svcTmp1 = NULL, *svcTmp2 = NULL;
57 LL_FOREACH_SAFE(svc, svcTmp1, svcTmp2)
59 LL_DELETE(svc, svcTmp1);
62 OICFree(svcTmp1->owners);
64 // Clean SVC node itself
70 static size_t svcElementsCount(const OicSecSvc_t *secSvc)
73 for (const OicSecSvc_t *svc = secSvc; svc; svc = svc->next)
80 OCStackResult SVCToCBORPayload(const OicSecSvc_t *svc, uint8_t **cborPayload,
83 if (NULL == svc || NULL == cborPayload || NULL != *cborPayload || NULL == cborSize)
85 return OC_STACK_INVALID_PARAM;
88 size_t cborLen = *cborSize;
96 int64_t cborEncoderResult = CborNoError;
97 OCStackResult ret = OC_STACK_ERROR;
101 uint8_t *outPayload = (uint8_t *)OICCalloc(1, cborLen);
102 VERIFY_NON_NULL(TAG, outPayload, ERROR);
104 cbor_encoder_init(&encoder, outPayload, cborLen, 0);
107 cborEncoderResult = cbor_encoder_create_array(&encoder, &svcArray, svcElementsCount(svc));
108 VERIFY_CBOR_SUCCESS(TAG, cborEncoderResult, "Failed to Create SVC Array.");
115 cborEncoderResult = cbor_encoder_create_map(&svcArray, &svcMap, SVC_MAP_SIZE);
116 VERIFY_CBOR_SUCCESS(TAG, cborEncoderResult, "Failed to Create SVC Map.");
118 // Service Device Identity
119 cborEncoderResult = cbor_encode_text_string(&svcMap, OIC_JSON_SERVICE_DEVICE_ID,
120 strlen(OIC_JSON_SERVICE_DEVICE_ID));
121 VERIFY_CBOR_SUCCESS(TAG, cborEncoderResult, "Failed to Add SVC Device Id.");
122 cborEncoderResult = cbor_encode_byte_string(&svcMap, (uint8_t *)svc->svcdid.id,
123 sizeof(svc->svcdid.id));
124 VERIFY_CBOR_SUCCESS(TAG, cborEncoderResult, "Failed to ");
127 cborEncoderResult = cbor_encode_text_string(&svcMap, OIC_JSON_SERVICE_TYPE,
128 strlen(OIC_JSON_SERVICE_TYPE));
129 VERIFY_CBOR_SUCCESS(TAG, cborEncoderResult, "Failed to Add SVC Serv Type Tag.");
130 cborEncoderResult = cbor_encode_int(&svcMap, svc->svct);
131 VERIFY_CBOR_SUCCESS(TAG, cborEncoderResult, "Failed to Add SVC Serv Type Value.");
134 // TODO: Need to modification to single ROwner, (Currently SINGLE_SERVICE_CLIENT_DRIVEN only)
135 cborEncoderResult = cbor_encode_text_string(&svcMap, OIC_JSON_OWNERS_NAME,
136 strlen(OIC_JSON_OWNERS_NAME));
137 VERIFY_CBOR_SUCCESS(TAG, cborEncoderResult, "Failed to Add SVC Owners Tag.");
138 cborEncoderResult = cbor_encoder_create_array(&svcMap, &owners, svc->ownersLen);
139 VERIFY_CBOR_SUCCESS(TAG, cborEncoderResult, "Failed to Add SVC Array.");
140 for (size_t i = 0; i < svc->ownersLen; i++)
142 cborEncoderResult = cbor_encode_byte_string(&owners, (uint8_t *)svc->owners[i].id,
143 sizeof(svc->owners[i].id));
144 VERIFY_CBOR_SUCCESS(TAG, cborEncoderResult, "Failed to Add SVC Owners Value.");
146 cborEncoderResult = cbor_encoder_close_container(&svcMap, &owners);
147 VERIFY_CBOR_SUCCESS(TAG, cborEncoderResult, "Failed to Close SVC Array.");
149 cborEncoderResult = cbor_encoder_close_container(&svcArray, &svcMap);
150 VERIFY_CBOR_SUCCESS(TAG, cborEncoderResult, "Failed to Close SVC Map.");
155 cborEncoderResult = cbor_encoder_close_container(&encoder, &svcArray);
156 VERIFY_CBOR_SUCCESS(TAG, cborEncoderResult, "Failed to Close SVC Array.");
158 if (CborNoError == cborEncoderResult)
160 *cborPayload = outPayload;
161 *cborSize = cbor_encoder_get_buffer_size(&encoder, outPayload);
166 if ((CborErrorOutOfMemory == cborEncoderResult) && (cborLen < CBOR_MAX_SIZE))
168 // reallocate and try again!
171 // Since the allocated initial memory failed, double the memory.
172 cborLen += cbor_encoder_get_buffer_size(&encoder, encoder.end);
173 cborEncoderResult = CborNoError;
174 ret = SVCToCBORPayload(svc, cborPayload, &cborLen);
178 if (CborNoError != cborEncoderResult)
184 ret = OC_STACK_ERROR;
190 OCStackResult CBORPayloadToSVC(const uint8_t *cborPayload, size_t size,
191 OicSecSvc_t **secSvc)
193 if (NULL == cborPayload || NULL == secSvc || NULL != *secSvc || 0 == size)
195 return OC_STACK_INVALID_PARAM;
200 OCStackResult ret = OC_STACK_ERROR;
202 CborValue svcCbor = { .parser = NULL };
203 CborParser parser = { .end = NULL };
204 CborError cborFindResult = CborNoError;
206 cbor_parser_init(cborPayload, size, 0, &parser, &svcCbor);
207 OicSecSvc_t *headSvc = NULL;
209 CborValue svcArray = { .parser = NULL };
210 cborFindResult = cbor_value_enter_container(&svcCbor, &svcArray);
211 VERIFY_CBOR_SUCCESS(TAG, cborFindResult, "Failed to Enter SVC Array.");
213 while (cbor_value_is_valid(&svcArray))
215 CborValue svcMap = { .parser = NULL };
216 OicSecSvc_t *svc = (OicSecSvc_t *) OICCalloc(1, sizeof(OicSecSvc_t));
217 VERIFY_NON_NULL(TAG, svc, ERROR);
218 cborFindResult = cbor_value_enter_container(&svcArray, &svcMap);
219 VERIFY_CBOR_SUCCESS(TAG, cborFindResult, "Failed to Enter SVC Map.");
221 while (cbor_value_is_valid(&svcMap))
225 CborType type = CborInvalidType;
227 cborFindResult = cbor_value_dup_text_string(&svcMap, &name, &len, NULL);
228 VERIFY_CBOR_SUCCESS(TAG, cborFindResult, "Failed to Find Name.");
229 cborFindResult = cbor_value_advance(&svcMap);
230 VERIFY_CBOR_SUCCESS(TAG, cborFindResult, "Failed to Advance.");
232 type = cbor_value_get_type(&svcMap);
233 // Service Device Identity
234 if (0 == strcmp(OIC_JSON_SERVICE_DEVICE_ID, name) && cbor_value_is_byte_string(&svcMap))
236 uint8_t *subjectId = NULL;
237 cborFindResult = cbor_value_dup_byte_string(&svcMap, &subjectId, &len, NULL);
238 VERIFY_CBOR_SUCCESS(TAG, cborFindResult, "Failed to Find SubjectId.");
239 memcpy(svc->svcdid.id, subjectId, len);
243 if (0 == strcmp(OIC_JSON_SERVICE_TYPE, name) && cbor_value_is_integer(&svcMap))
247 cborFindResult = cbor_value_get_int(&svcMap, &svct);
248 VERIFY_CBOR_SUCCESS(TAG, cborFindResult, "Failed to Find SVCT.");
249 svc->svct = (OicSecSvcType_t)svct;
252 // Owners -- Mandatory
253 if (0 == strcmp(OIC_JSON_OWNERS_NAME, name) && cbor_value_is_array(&svcMap))
256 CborValue owners = { .parser = NULL };
258 cborFindResult = cbor_value_get_array_length(&svcMap, &svc->ownersLen);
259 VERIFY_CBOR_SUCCESS(TAG, cborFindResult, "Failed to Find Owner Len.");
260 cborFindResult = cbor_value_enter_container(&svcMap, &owners);
261 VERIFY_CBOR_SUCCESS(TAG, cborFindResult, "Failed to Enter Owner Array.");
262 svc->owners = (OicUuid_t *)OICCalloc(svc->ownersLen, sizeof(*svc->owners));
263 VERIFY_NON_NULL(TAG, svc->owners, ERROR);
265 while (cbor_value_is_valid(&owners) && cbor_value_is_byte_string(&owners))
267 uint8_t *owner = NULL;
268 cborFindResult = cbor_value_dup_byte_string(&owners, &owner, &len, NULL);
269 VERIFY_CBOR_SUCCESS(TAG, cborFindResult, "Failed to Find Owner Array Value.");
270 cborFindResult = cbor_value_advance(&owners);
271 VERIFY_CBOR_SUCCESS(TAG, cborFindResult, "Failed to Advance Owner Array.");
272 memcpy(svc->owners[i++].id, owner, len);
276 if (CborMapType != type && cbor_value_is_valid(&svcMap))
278 cborFindResult = cbor_value_advance(&svcMap);
279 VERIFY_CBOR_SUCCESS(TAG, cborFindResult, "Failed to Advance SVC.");
291 OicSecSvc_t *temp = headSvc;
298 if (cbor_value_is_valid(&svcArray))
300 cborFindResult = cbor_value_advance(&svcArray);
301 VERIFY_CBOR_SUCCESS(TAG, cborFindResult, "Failed to Find Name.");
308 if (CborNoError != cborFindResult)
310 DeleteSVCList(headSvc);
313 ret = OC_STACK_ERROR;
318 static OCEntityHandlerResult HandleSVCGetRequest(const OCEntityHandlerRequest * ehRequest)
320 // Convert SVC data into JSON for transmission
322 uint8_t *cborSvc = NULL;
323 OCStackResult res = SVCToCBORPayload(gSvc, &cborSvc, &size);
324 OCEntityHandlerResult ehRet = (res == OC_STACK_OK) ? OC_EH_OK : OC_EH_ERROR;
326 // Send response payload to request originator
327 if (OC_STACK_OK != SendSRMResponse(ehRequest, ehRet, cborSvc, size))
330 OIC_LOG(ERROR, TAG, "SendSRMResponse failed in HandleSVCGetRequest");
334 OIC_LOG_V (DEBUG, TAG, "%s RetVal %d", __func__ , ehRet);
338 static OCEntityHandlerResult HandleSVCPostRequest(const OCEntityHandlerRequest * ehRequest)
340 OCEntityHandlerResult ehRet = OC_EH_ERROR;
341 uint8_t *payload = ((OCSecurityPayload *) ehRequest->payload)->securityData;
342 size_t size = ((OCSecurityPayload *) ehRequest->payload)->payloadSize;
345 // Convert CBOR SVC data into SVC. This will also validate the SVC data received.
346 OicSecSvc_t *newSvc = NULL;
347 OCStackResult res = CBORPayloadToSVC(payload, size, &newSvc);
348 if (newSvc && res == OC_STACK_OK)
350 // Append the new SVC to existing SVC
351 LL_APPEND(gSvc, newSvc);
353 // Convert SVC data into JSON for update to persistent storage
355 uint8_t *cborPayload = NULL;
356 res = SVCToCBORPayload(gSvc, &cborPayload, &size);
357 if (cborPayload && OC_STACK_OK == res &&
358 UpdateSecureResourceInPS(OIC_JSON_SVC_NAME, cborPayload, size) == OC_STACK_OK)
360 ehRet = OC_EH_CHANGED;
362 OICFree(cborPayload);
366 // Send payload to request originator
367 if (OC_STACK_OK != SendSRMResponse(ehRequest, ehRet, NULL, 0))
370 OIC_LOG(ERROR, TAG, "SendSRMResponse failed in HandleSVCPostRequest");
373 OIC_LOG_V (DEBUG, TAG, "%s RetVal %d", __func__ , ehRet);
378 * This internal method is the entity handler for SVC resources and
379 * will handle REST request (GET/PUT/POST/DEL) for them.
381 static OCEntityHandlerResult SVCEntityHandler(OCEntityHandlerFlag flag,
382 OCEntityHandlerRequest * ehRequest,
383 void* callbackParameter)
385 (void) callbackParameter;
386 OCEntityHandlerResult ehRet = OC_EH_ERROR;
393 if (flag & OC_REQUEST_FLAG)
395 switch (ehRequest->method)
398 ehRet = HandleSVCGetRequest(ehRequest);
402 ehRet = HandleSVCPostRequest(ehRequest);
407 SendSRMResponse(ehRequest, ehRet, NULL, 0);
415 * This internal method is used to create '/oic/sec/svc' resource.
417 static OCStackResult CreateSVCResource()
419 OCStackResult ret = OCCreateResource(&gSvcHandle,
420 OIC_RSRC_TYPE_SEC_SVC,
421 OC_RSRVD_INTERFACE_DEFAULT,
427 if (OC_STACK_OK != ret)
429 OIC_LOG(FATAL, TAG, "Unable to instantiate SVC resource");
435 OCStackResult InitSVCResource()
437 OCStackResult ret = OC_STACK_ERROR;
439 OIC_LOG_V(DEBUG, TAG, "Begin %s ", __func__ );
441 uint8_t *data = NULL;
443 ret = GetSecureVirtualDatabaseFromPS(OIC_JSON_SVC_NAME, &data, &size);
444 // If database read failed
445 if (ret != OC_STACK_OK)
447 OIC_LOG (DEBUG, TAG, "ReadSVDataFromPS failed");
452 // Convert CBOR SVC into binary format
453 ret = CBORPayloadToSVC(data, size, &gSvc);
454 if (ret != OC_STACK_OK)
456 OIC_LOG (DEBUG, TAG, " ConvertCBOR SVC into binary format failed");
461 // Instantiate 'oic.sec.svc'
462 ret = CreateSVCResource();
464 if (OC_STACK_OK != ret)
469 OIC_LOG_V(DEBUG, TAG, "%s RetVal %d", __func__ , ret);
473 void DeInitSVCResource()
475 OCDeleteResource(gSvcHandle);