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) && cbor_value_is_byte_string(&svcMap))
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) && cbor_value_is_integer(&svcMap))
246 cborFindResult = cbor_value_get_int(&svcMap, &svct);
247 VERIFY_CBOR_SUCCESS(TAG, cborFindResult, "Failed to Find SVCT.");
248 svc->svct = (OicSecSvcType_t)svct;
251 // Owners -- Mandatory
252 if (0 == strcmp(OIC_JSON_OWNERS_NAME, name) && cbor_value_is_array(&svcMap))
255 CborValue owners = { .parser = NULL };
257 cborFindResult = cbor_value_get_array_length(&svcMap, &svc->ownersLen);
258 VERIFY_CBOR_SUCCESS(TAG, cborFindResult, "Failed to Find Owner Len.");
259 cborFindResult = cbor_value_enter_container(&svcMap, &owners);
260 VERIFY_CBOR_SUCCESS(TAG, cborFindResult, "Failed to Enter Owner Array.");
261 svc->owners = (OicUuid_t *)OICCalloc(svc->ownersLen, sizeof(*svc->owners));
262 VERIFY_NON_NULL(TAG, svc->owners, ERROR);
264 while (cbor_value_is_valid(&owners) && cbor_value_is_byte_string(&owners))
266 uint8_t *owner = NULL;
267 cborFindResult = cbor_value_dup_byte_string(&owners, &owner, &len, NULL);
268 VERIFY_CBOR_SUCCESS(TAG, cborFindResult, "Failed to Find Owner Array Value.");
269 cborFindResult = cbor_value_advance(&owners);
270 VERIFY_CBOR_SUCCESS(TAG, cborFindResult, "Failed to Advance Owner Array.");
271 memcpy(svc->owners[i++].id, owner, len);
275 if (CborMapType != type && cbor_value_is_valid(&svcMap))
277 cborFindResult = cbor_value_advance(&svcMap);
278 VERIFY_CBOR_SUCCESS(TAG, cborFindResult, "Failed to Advance SVC.");
290 OicSecSvc_t *temp = headSvc;
297 if (cbor_value_is_valid(&svcArray))
299 cborFindResult = cbor_value_advance(&svcArray);
300 VERIFY_CBOR_SUCCESS(TAG, cborFindResult, "Failed to Find Name.");
307 if (CborNoError != cborFindResult)
309 DeleteSVCList(headSvc);
312 ret = OC_STACK_ERROR;
317 static OCEntityHandlerResult HandleSVCGetRequest(const OCEntityHandlerRequest * ehRequest)
319 // Convert SVC data into JSON for transmission
321 uint8_t *cborSvc = NULL;
322 OCStackResult res = SVCToCBORPayload(gSvc, &cborSvc, &size);
323 OCEntityHandlerResult ehRet = (res == OC_STACK_OK) ? OC_EH_OK : OC_EH_ERROR;
325 // Send response payload to request originator
326 if (OC_STACK_OK != SendSRMResponse(ehRequest, ehRet, cborSvc, size))
329 OIC_LOG(ERROR, TAG, "SendSRMResponse failed in HandleSVCGetRequest");
333 OIC_LOG_V (DEBUG, TAG, "%s RetVal %d", __func__ , ehRet);
337 static OCEntityHandlerResult HandleSVCPostRequest(const OCEntityHandlerRequest * ehRequest)
339 OCEntityHandlerResult ehRet = OC_EH_ERROR;
340 uint8_t *payload = ((OCSecurityPayload *) ehRequest->payload)->securityData;
341 size_t size = ((OCSecurityPayload *) ehRequest->payload)->payloadSize;
344 // Convert CBOR SVC data into SVC. This will also validate the SVC data received.
345 OicSecSvc_t *newSvc = NULL;
346 OCStackResult res = CBORPayloadToSVC(payload, size, &newSvc);
347 if (newSvc && res == OC_STACK_OK)
349 // Append the new SVC to existing SVC
350 LL_APPEND(gSvc, newSvc);
352 // Convert SVC data into JSON for update to persistent storage
354 uint8_t *cborPayload = NULL;
355 res = SVCToCBORPayload(gSvc, &cborPayload, &size);
356 if (cborPayload && OC_STACK_OK == res &&
357 UpdateSecureResourceInPS(OIC_JSON_SVC_NAME, cborPayload, size) == OC_STACK_OK)
359 ehRet = OC_EH_CHANGED;
361 OICFree(cborPayload);
365 // Send payload to request originator
366 if (OC_STACK_OK != SendSRMResponse(ehRequest, ehRet, NULL, 0))
369 OIC_LOG(ERROR, TAG, "SendSRMResponse failed in HandleSVCPostRequest");
372 OIC_LOG_V (DEBUG, TAG, "%s RetVal %d", __func__ , ehRet);
377 * This internal method is the entity handler for SVC resources and
378 * will handle REST request (GET/PUT/POST/DEL) for them.
380 static OCEntityHandlerResult SVCEntityHandler(OCEntityHandlerFlag flag,
381 OCEntityHandlerRequest * ehRequest,
382 void* callbackParameter)
384 (void) callbackParameter;
385 OCEntityHandlerResult ehRet = OC_EH_ERROR;
392 if (flag & OC_REQUEST_FLAG)
394 switch (ehRequest->method)
397 ehRet = HandleSVCGetRequest(ehRequest);
401 ehRet = HandleSVCPostRequest(ehRequest);
406 SendSRMResponse(ehRequest, ehRet, NULL, 0);
414 * This internal method is used to create '/oic/sec/svc' resource.
416 static OCStackResult CreateSVCResource()
418 OCStackResult ret = OCCreateResource(&gSvcHandle,
419 OIC_RSRC_TYPE_SEC_SVC,
420 OC_RSRVD_INTERFACE_DEFAULT,
426 if (OC_STACK_OK != ret)
428 OIC_LOG(FATAL, TAG, "Unable to instantiate SVC resource");
434 OCStackResult InitSVCResource()
436 OCStackResult ret = OC_STACK_ERROR;
438 OIC_LOG_V(DEBUG, TAG, "Begin %s ", __func__ );
440 uint8_t *data = NULL;
442 ret = GetSecureVirtualDatabaseFromPS(OIC_JSON_SVC_NAME, &data, &size);
443 // If database read failed
444 if (ret != OC_STACK_OK)
446 OIC_LOG (DEBUG, TAG, "ReadSVDataFromPS failed");
451 // Convert CBOR SVC into binary format
452 ret = CBORPayloadToSVC(data, size, &gSvc);
453 if (ret != OC_STACK_OK)
455 OIC_LOG (DEBUG, TAG, " ConvertCBOR SVC into binary format failed");
460 // Instantiate 'oic.sec.svc'
461 ret = CreateSVCResource();
463 if (OC_STACK_OK != ret)
468 OIC_LOG_V(DEBUG, TAG, "%s RetVal %d", __func__ , ret);
472 void DeInitSVCResource()
474 OCDeleteResource(gSvcHandle);