1 /* *****************************************************************
3 * Copyright 2016 Samsung Electronics All Rights Reserved.
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 * *****************************************************************/
25 #include "oic_malloc.h"
26 #include "oic_string.h"
29 #include "ocpayload.h"
30 #include "payload_logging.h"
31 #include "resourcemanager.h"
32 #include "pconfresource.h"
33 #include "psinterface.h"
35 #include "srmresourcestrings.h"
36 #include "doxmresource.h"
37 #include "srmutility.h"
38 #include "ocserverrequest.h"
40 #include "psinterface.h"
41 #include "security_internals.h"
48 #define TAG "SRM-PCONF"
50 static const uint16_t CBOR_SIZE = 1024;
51 static const uint64_t CBOR_MAX_SIZE = 4400;
52 static const uint8_t PCONF_MAP_SIZE = 4;
53 static const uint8_t PCONF_RESOURCE_MAP_SIZE = 4;
55 static OicSecPconf_t *gPconf = NULL;
56 static OCResourceHandle gPconfHandle = NULL;
57 static OicSecPconf_t gDefaultPconf =
60 NULL, /* OicSecPrm *prm */
61 0, /* size_t prmLen */
62 {.val = {0}}, /* OicDpPin_t pin */
63 NULL, /* OicSecPdAcl_t *pdacls */
64 NULL, /* OicUuid_t *pddevs */
65 0, /* size_t pddevLen */
66 {.id = {0}}, /* OicUuid_t deviceID */
67 {.id = {0}}, /* OicUuid_t rowner */
71 * This function frees OicSecPdAcl_t object's fields and object itself.
73 void FreePdAclList(OicSecPdAcl_t* pdacls)
80 OicSecPdAcl_t *aclTmp1 = NULL;
81 OicSecPdAcl_t *aclTmp2 = NULL;
82 LL_FOREACH_SAFE(pdacls, aclTmp1, aclTmp2)
84 LL_DELETE(pdacls, aclTmp1);
87 for (i = 0; i < aclTmp1->resourcesLen; i++)
89 OICFree(aclTmp1->resources[i]);
91 OICFree(aclTmp1->resources);
96 for(i = 0; i < aclTmp1->prdRecrLen; i++)
98 OICFree(aclTmp1->periods[i]);
100 OICFree(aclTmp1->periods);
104 if(aclTmp1->recurrences)
106 for(i = 0; i < aclTmp1->prdRecrLen; i++)
108 OICFree(aclTmp1->recurrences[i]);
110 OICFree(aclTmp1->recurrences);
119 void DeletePconfBinData(OicSecPconf_t* pconf)
129 FreePdAclList(pconf->pdacls);
133 OICFree(pconf->pddevs);
140 static size_t OicPdAclSize(const OicSecPdAcl_t *pdAcl)
147 OicSecPdAcl_t *tmp = (OicSecPdAcl_t *)pdAcl;
157 OCStackResult PconfToCBORPayload(const OicSecPconf_t *pconf,uint8_t **payload,size_t *size)
159 if (NULL == pconf || NULL == payload || NULL != *payload || NULL == size)
161 return OC_STACK_INVALID_PARAM;
163 size_t cborLen = *size;
170 OCStackResult ret = OC_STACK_ERROR;
172 CborEncoder pconfMap;
174 int64_t cborEncoderResult = CborNoError;
175 uint8_t mapSize = PCONF_MAP_SIZE;
177 if (pconf->prmLen > 0)
190 uint8_t *outPayload = (uint8_t *)OICCalloc(1, cborLen);
191 VERIFY_NON_NULL(TAG, outPayload, ERROR);
193 cbor_encoder_init(&encoder, outPayload, cborLen, 0);
194 cborEncoderResult = cbor_encoder_create_map(&encoder, &pconfMap, mapSize);
195 VERIFY_CBOR_SUCCESS(TAG, cborEncoderResult, "Failed Creating Pconf Map.");
198 cborEncoderResult = cbor_encode_text_string(&pconfMap, OIC_JSON_EDP_NAME,
199 strlen(OIC_JSON_EDP_NAME));
200 VERIFY_CBOR_SUCCESS(TAG, cborEncoderResult, "Failed Encode EDP String.");
201 cborEncoderResult = cbor_encode_boolean(&pconfMap, pconf->edp);
202 VERIFY_CBOR_SUCCESS(TAG, cborEncoderResult, "Failed Convert PconfEDP value");
204 //PRM type -- Not Mandatory
205 if(pconf->prmLen > 0)
208 cborEncoderResult = cbor_encode_text_string(&pconfMap, OIC_JSON_PRM_NAME,
209 strlen(OIC_JSON_PRM_NAME));
210 VERIFY_CBOR_SUCCESS(TAG, cborEncoderResult, "Failed Convert Pconf PRM NAME");
211 cborEncoderResult = cbor_encoder_create_array(&pconfMap, &prm, pconf->prmLen);
212 VERIFY_CBOR_SUCCESS(TAG, cborEncoderResult, "Failed Convert Pconf PRM value");
214 for (size_t i = 0; i < pconf->prmLen; i++)
216 cborEncoderResult = cbor_encode_int(&prm, pconf->prm[i]);
217 VERIFY_CBOR_SUCCESS(TAG, cborEncoderResult, "Failed Convert Pconf PRM Array");
219 cborEncoderResult = cbor_encoder_close_container(&pconfMap, &prm);
220 VERIFY_CBOR_SUCCESS(TAG, cborEncoderResult, "Failed to close encode array");
224 cborEncoderResult = cbor_encode_text_string(&pconfMap, OIC_JSON_PIN_NAME,
225 strlen(OIC_JSON_PIN_NAME));
226 VERIFY_CBOR_SUCCESS(TAG, cborEncoderResult, "Failed to create OIC_JSON_PIN_NAME");
227 cborEncoderResult = cbor_encode_byte_string(&pconfMap, pconf->pin.val, sizeof(pconf->pin.val));
228 VERIFY_CBOR_SUCCESS(TAG, cborEncoderResult, "Failed to convert pin value");
233 OicSecPdAcl_t *pdacl = pconf->pdacls;
234 CborEncoder pdAclArray;
235 cborEncoderResult = cbor_encode_text_string(&pconfMap, OIC_JSON_PDACL_NAME,
236 strlen(OIC_JSON_PDACL_NAME));
237 VERIFY_CBOR_SUCCESS(TAG, cborEncoderResult, "Failed to create OIC_JSON_PDACL_NAME");
238 cborEncoderResult = cbor_encoder_create_array(&pconfMap, &pdAclArray,
239 OicPdAclSize(pconf->pdacls));
240 VERIFY_CBOR_SUCCESS(TAG, cborEncoderResult, "Failed to creeate _pdacl array");
244 CborEncoder pdAclMap;
245 // PDACL Map size - Number of mandatory items
246 uint8_t aclMapSize = 2;
248 if (pdacl->prdRecrLen)
252 if (pdacl->recurrences)
257 cborEncoderResult = cbor_encoder_create_map(&pdAclArray, &pdAclMap, aclMapSize);
258 VERIFY_CBOR_SUCCESS(TAG, cborEncoderResult, "Failed to creeate _pdacl array");
260 // Resources -- Mandatory
261 cborEncoderResult = cbor_encode_text_string(&pdAclMap, OIC_JSON_RESOURCES_NAME,
262 strlen(OIC_JSON_RESOURCES_NAME));
263 VERIFY_CBOR_SUCCESS(TAG, cborEncoderResult, "Failed to encode resource result");
265 CborEncoder resources;
266 cborEncoderResult = cbor_encoder_create_array(&pdAclMap, &resources,
267 pdacl->resourcesLen);
268 VERIFY_CBOR_SUCCESS(TAG, cborEncoderResult, "Failed to create resource array");
270 for (size_t i = 0; i < pdacl->resourcesLen; i++)
273 cborEncoderResult = cbor_encoder_create_map(&resources, &rMap,
274 PCONF_RESOURCE_MAP_SIZE);
275 VERIFY_CBOR_SUCCESS(TAG, cborEncoderResult, "Failed Addding Resource Map.");
277 cborEncoderResult = cbor_encode_text_string(&rMap, OIC_JSON_HREF_NAME,
278 strlen(OIC_JSON_HREF_NAME));
279 VERIFY_CBOR_SUCCESS(TAG, cborEncoderResult, "Failed Addding HREF Name Tag.");
280 cborEncoderResult = cbor_encode_text_string(&rMap, pdacl->resources[i],
281 strlen(pdacl->resources[i]));
282 VERIFY_CBOR_SUCCESS(TAG, cborEncoderResult, "Failed Addding HREF Value in Map.");
284 cborEncoderResult = cbor_encode_text_string(&rMap, OIC_JSON_REL_NAME,
285 strlen(OIC_JSON_REL_NAME));
286 VERIFY_CBOR_SUCCESS(TAG, cborEncoderResult, "Failed Addding REL Name Tag.");
288 // TODO : Need to assign real value of REL
289 cborEncoderResult = cbor_encode_text_string(&rMap, OIC_JSON_EMPTY_STRING,
290 strlen(OIC_JSON_EMPTY_STRING));
291 VERIFY_CBOR_SUCCESS(TAG, cborEncoderResult, "Failed Addding REL Value.");
293 cborEncoderResult = cbor_encode_text_string(&rMap, OIC_JSON_RT_NAME,
294 strlen(OIC_JSON_RT_NAME));
295 VERIFY_CBOR_SUCCESS(TAG, cborEncoderResult, "Failed Addding RT Name Tag.");
297 // TODO : Need to assign real value of RT
298 cborEncoderResult = cbor_encode_text_string(&rMap, OIC_JSON_EMPTY_STRING,
299 strlen(OIC_JSON_EMPTY_STRING));
300 VERIFY_CBOR_SUCCESS(TAG, cborEncoderResult, "Failed Addding RT Value.");
302 cborEncoderResult = cbor_encode_text_string(&rMap, OIC_JSON_IF_NAME,
303 strlen(OIC_JSON_IF_NAME));
304 VERIFY_CBOR_SUCCESS(TAG, cborEncoderResult, "Failed Addding IF Name Tag.");
306 // TODO : Need to assign real value of IF
307 cborEncoderResult = cbor_encode_text_string(&rMap, OIC_JSON_EMPTY_STRING,
308 strlen(OIC_JSON_EMPTY_STRING));
309 VERIFY_CBOR_SUCCESS(TAG, cborEncoderResult, "Failed Addding IF Value.");
311 cborEncoderResult = cbor_encoder_close_container(&resources, &rMap);
312 VERIFY_CBOR_SUCCESS(TAG, cborEncoderResult, "Failed Closing Resource Map.");
315 cborEncoderResult = cbor_encoder_close_container(&pdAclMap, &resources);
316 VERIFY_CBOR_SUCCESS(TAG, cborEncoderResult, "Failed to close resource array");
318 // Permissions -- Mandatory
319 cborEncoderResult = cbor_encode_text_string(&pdAclMap, OIC_JSON_PERMISSION_NAME,
320 strlen(OIC_JSON_PERMISSION_NAME));
321 VERIFY_CBOR_SUCCESS(TAG, cborEncoderResult, "Failed to create permition string");
322 cborEncoderResult = cbor_encode_int(&pdAclMap, pdacl->permission);
323 VERIFY_CBOR_SUCCESS(TAG, cborEncoderResult, "Failed to encode permition calue");
325 // Period -- Not Mandatory
329 cborEncoderResult = cbor_encode_text_string(&pdAclMap, OIC_JSON_PERIODS_NAME,
330 strlen(OIC_JSON_PERIODS_NAME));
331 VERIFY_CBOR_SUCCESS(TAG, cborEncoderResult, "Failed to encode period value");
332 cborEncoderResult = cbor_encoder_create_array(&pdAclMap, &period,
334 VERIFY_CBOR_SUCCESS(TAG, cborEncoderResult, "Failed to create array");
336 for (size_t i = 0; i < pdacl->prdRecrLen; i++)
338 cborEncoderResult = cbor_encode_text_string(&period, pdacl->periods[i],
339 strlen(pdacl->periods[i]));
340 VERIFY_CBOR_SUCCESS(TAG, cborEncoderResult, "Failed to encode period");
342 cborEncoderResult = cbor_encoder_close_container(&pdAclMap, &period);
343 VERIFY_CBOR_SUCCESS(TAG, cborEncoderResult,"Failed to close period array");
346 // Period -- Not Mandatory
347 if(0 != pdacl->prdRecrLen && pdacl->recurrences)
349 CborEncoder recurrences;
350 cborEncoderResult = cbor_encode_text_string(&pdAclMap, OIC_JSON_RECURRENCES_NAME,
351 strlen(OIC_JSON_RECURRENCES_NAME));
352 VERIFY_CBOR_SUCCESS(TAG, cborEncoderResult,"Failed to encode recurrences");
353 cborEncoderResult = cbor_encoder_create_array(&pdAclMap, &recurrences,
355 VERIFY_CBOR_SUCCESS(TAG, cborEncoderResult, "Failed to create rec array");
357 for (size_t i = 0; i < pdacl->prdRecrLen; i++)
359 cborEncoderResult = cbor_encode_text_string(&recurrences,
360 pdacl->recurrences[i], strlen(pdacl->recurrences[i]));
361 VERIFY_CBOR_SUCCESS(TAG, cborEncoderResult, "Failed to encode recurrences");
363 cborEncoderResult = cbor_encoder_close_container(&pdAclMap, &recurrences);
364 VERIFY_CBOR_SUCCESS(TAG, cborEncoderResult, "Failed to close rec array");
366 cborEncoderResult = cbor_encoder_close_container(&pdAclArray, &pdAclMap);
367 VERIFY_CBOR_SUCCESS(TAG, cborEncoderResult, "Failed to close acl map");
372 cborEncoderResult = cbor_encoder_close_container(&pconfMap, &pdAclArray);
373 VERIFY_CBOR_SUCCESS(TAG, cborEncoderResult, "Failed to close acl array");
377 //There may not be paired devices if it did not pairing before
378 if (pconf->pddevs && 0 < pconf->pddevLen)
381 cborEncoderResult = cbor_encode_text_string(&pconfMap, OIC_JSON_PDDEV_LIST_NAME,
382 strlen(OIC_JSON_PDDEV_LIST_NAME));
383 VERIFY_CBOR_SUCCESS(TAG, cborEncoderResult, "Failed to encode pddev");
384 cborEncoderResult = cbor_encoder_create_array(&pconfMap, &pddev, pconf->pddevLen);
385 VERIFY_CBOR_SUCCESS(TAG, cborEncoderResult, "Failed to create array");
387 for (size_t i = 0; i < pconf->pddevLen; i++)
389 char *pddevId = NULL;
390 ret = ConvertUuidToStr(&pconf->pddevs[i], &pddevId);
391 VERIFY_SUCCESS(TAG, ret == OC_STACK_OK, ERROR);
392 cborEncoderResult = cbor_encode_text_string(&pddev, pddevId, strlen(pddevId));
393 VERIFY_CBOR_SUCCESS(TAG, cborEncoderResult, "Failed Addding pddev Id Value.");
396 cborEncoderResult = cbor_encoder_close_container(&pconfMap, &pddev);
397 VERIFY_CBOR_SUCCESS(TAG, cborEncoderResult, "Failed to close pddev array");
400 //DeviceId -- Mandatory
401 //There may not be devicd id if caller is provisoning tool
402 cborEncoderResult = cbor_encode_text_string(&pconfMap, OIC_JSON_DEVICE_ID_NAME,
403 strlen(OIC_JSON_DEVICE_ID_NAME));
404 VERIFY_CBOR_SUCCESS(TAG, cborEncoderResult, "Failed to encode device id");
406 char *deviceId = NULL;
407 ret = ConvertUuidToStr(&pconf->deviceID, &deviceId);
408 VERIFY_SUCCESS(TAG, ret == OC_STACK_OK, ERROR);
409 cborEncoderResult = cbor_encode_text_string(&pconfMap, deviceId, strlen(deviceId));
410 VERIFY_CBOR_SUCCESS(TAG, cborEncoderResult, "Failed to encode deviceID value");
414 //ROwner -- Mandatory
417 cborEncoderResult = cbor_encode_text_string(&pconfMap, OIC_JSON_ROWNERID_NAME,
418 strlen(OIC_JSON_ROWNERID_NAME));
419 VERIFY_CBOR_SUCCESS(TAG, cborEncoderResult, "Failed to encode rowner string");
420 ret = ConvertUuidToStr(&pconf->rownerID, &rowner);
421 VERIFY_SUCCESS(TAG, ret == OC_STACK_OK, ERROR);
422 cborEncoderResult = cbor_encode_text_string(&pconfMap, rowner, strlen(rowner));
423 VERIFY_CBOR_SUCCESS(TAG, cborEncoderResult, "Failed to encode rwoner value");
427 cborEncoderResult = cbor_encoder_close_container(&encoder, &pconfMap);
428 VERIFY_CBOR_SUCCESS(TAG, cborEncoderResult, "Failed to close pconfMap");
430 *size = encoder.ptr - outPayload;
431 *payload = outPayload;
434 if ((CborErrorOutOfMemory == cborEncoderResult) && (cborLen < CBOR_MAX_SIZE))
436 // reallocate and try again!
438 // Since the allocated initial memory failed, double the memory.
439 cborLen += encoder.ptr - encoder.end;
440 cborEncoderResult = CborNoError;
441 ret = PconfToCBORPayload(pconf, payload, &cborLen);
444 if ((CborNoError != cborEncoderResult) || (OC_STACK_OK != ret))
450 ret = OC_STACK_ERROR;
455 OCStackResult CBORPayloadToPconf(const uint8_t *cborPayload, size_t size, OicSecPconf_t **secPconf)
457 if (NULL == cborPayload || NULL == secPconf || NULL != *secPconf || 0 == size)
459 return OC_STACK_INVALID_PARAM;
461 OCStackResult ret = OC_STACK_ERROR;
463 CborValue pconfCbor = { .parser = NULL };
464 CborParser parser = { .end = NULL };
465 CborError cborFindResult = CborNoError;
467 cbor_parser_init(cborPayload, size, 0, &parser, &pconfCbor);
468 CborValue pconfMap = { .parser = NULL } ;
469 OicSecPconf_t *pconf = NULL;
470 cborFindResult = cbor_value_enter_container(&pconfCbor, &pconfMap);
471 VERIFY_CBOR_SUCCESS(TAG, cborFindResult, "Failed to enter map");
472 pconf = (OicSecPconf_t *)OICCalloc(1, sizeof(*pconf));
473 VERIFY_NON_NULL(TAG, pconf, ERROR);
474 while (cbor_value_is_valid(&pconfMap))
478 CborType type = cbor_value_get_type(&pconfMap);
479 if (type == CborTextStringType && cbor_value_is_text_string(&pconfMap))
481 cborFindResult = cbor_value_dup_text_string(&pconfMap, &name, &len, NULL);
482 VERIFY_CBOR_SUCCESS(TAG, cborFindResult, "Failed to get value");
483 cborFindResult = cbor_value_advance(&pconfMap);
484 VERIFY_CBOR_SUCCESS(TAG, cborFindResult, "Failed to advance value");
490 if(0 == strcmp(OIC_JSON_EDP_NAME, name) && cbor_value_is_boolean(&pconfMap))
492 cborFindResult = cbor_value_get_boolean(&pconfMap, &pconf->edp);
493 VERIFY_CBOR_SUCCESS(TAG, cborFindResult, "Failed to get value");
495 if (0 == strcmp(OIC_JSON_PRM_NAME, name))
498 CborValue prm = { .parser = NULL };
499 cborFindResult = cbor_value_get_array_length(&pconfMap, &pconf->prmLen);
500 VERIFY_CBOR_SUCCESS(TAG, cborFindResult, "Failed to get length");
501 VERIFY_SUCCESS(TAG, pconf->prmLen != 0, ERROR);
503 pconf->prm = (OicSecPrm_t *)OICCalloc(pconf->prmLen, sizeof(OicSecPrm_t));
504 VERIFY_NON_NULL(TAG, pconf->prm, ERROR);
505 cborFindResult = cbor_value_enter_container(&pconfMap, &prm);
506 VERIFY_CBOR_SUCCESS(TAG, cborFindResult, "Failed to eneter array");
508 while (cbor_value_is_valid(&prm) && cbor_value_is_integer(&prm))
510 cborFindResult = cbor_value_get_int(&prm, (int *)&pconf->prm[i++]);
511 VERIFY_CBOR_SUCCESS(TAG, cborFindResult, "Failed to get value");
512 cborFindResult = cbor_value_advance(&prm);
513 VERIFY_CBOR_SUCCESS(TAG, cborFindResult, "Failed to advance value");
517 if (0 == strcmp(OIC_JSON_PIN_NAME, name) && cbor_value_is_byte_string(&pconfMap))
520 cborFindResult = cbor_value_dup_byte_string(&pconfMap, &pin, &len, NULL);
521 VERIFY_CBOR_SUCCESS(TAG, cborFindResult, "Failed to get value");
522 memcpy(pconf->pin.val, pin, len);
527 if (0 == strcmp(OIC_JSON_PDACL_NAME, name))
529 CborValue pdAclArray = { .parser = NULL};
530 OicSecPdAcl_t *headPdacl = NULL;
532 cborFindResult = cbor_value_enter_container(&pconfMap, &pdAclArray);
533 VERIFY_CBOR_SUCCESS(TAG, cborFindResult, "Failed to enter");
535 while (cbor_value_is_valid(&pdAclArray))
537 CborValue pdAclMap = { .parser = NULL};
538 OicSecPdAcl_t *pdacl = (OicSecPdAcl_t *) OICCalloc(1, sizeof(OicSecPdAcl_t));
539 VERIFY_NON_NULL(TAG, pdacl, ERROR);
541 cborFindResult = cbor_value_enter_container(&pdAclArray, &pdAclMap);
542 VERIFY_CBOR_SUCCESS(TAG, cborFindResult, "Failed to enter");
544 while (cbor_value_is_valid(&pdAclMap))
548 CborType type = cbor_value_get_type(&pdAclMap);
549 if (type == CborTextStringType && cbor_value_is_text_string(&pdAclMap))
551 cborFindResult = cbor_value_dup_text_string(&pdAclMap, &name,
553 VERIFY_CBOR_SUCCESS(TAG, cborFindResult, "Failed to get text");
554 cborFindResult = cbor_value_advance(&pdAclMap);
555 VERIFY_CBOR_SUCCESS(TAG, cborFindResult, "Failed to advance value");
559 // Resources -- Mandatory
560 if (strcmp(name, OIC_JSON_RESOURCES_NAME) == 0 && cbor_value_is_array(&pdAclMap))
563 CborValue resources = { .parser = NULL };
564 cborFindResult = cbor_value_get_array_length(&pdAclMap,
565 &pdacl->resourcesLen);
566 VERIFY_CBOR_SUCCESS(TAG, cborFindResult, "Failed to get length");
567 cborFindResult = cbor_value_enter_container(&pdAclMap, &resources);
568 VERIFY_CBOR_SUCCESS(TAG, cborFindResult, "Failed to enter");
569 pdacl->resources = (char **) OICCalloc(pdacl->resourcesLen,
571 VERIFY_NON_NULL(TAG, pdacl->resources, ERROR);
573 while (cbor_value_is_valid(&resources))
575 CborValue rMap = { .parser = NULL };
576 cborFindResult = cbor_value_enter_container(&resources, &rMap);
577 VERIFY_CBOR_SUCCESS(TAG, cborFindResult, "Failed Entering Resource Map");
579 while(cbor_value_is_valid(&rMap) && cbor_value_is_text_string(&rMap))
581 char *rMapName = NULL;
582 size_t rMapNameLen = 0;
583 cborFindResult = cbor_value_dup_text_string(&rMap, &rMapName, &rMapNameLen, NULL);
584 VERIFY_CBOR_SUCCESS(TAG, cborFindResult, "Failed Finding RMap Data Name Tag.");
585 cborFindResult = cbor_value_advance(&rMap);
586 VERIFY_CBOR_SUCCESS(TAG, cborFindResult, "Failed Finding RMap Data Value.");
589 if (0 == strcmp(OIC_JSON_HREF_NAME, rMapName))
591 // TODO : Need to check data structure of OicSecPdAcl_t based on RAML spec.
592 cborFindResult = cbor_value_dup_text_string(&rMap, &pdacl->resources[i++], &len, NULL);
593 VERIFY_CBOR_SUCCESS(TAG, cborFindResult, "Failed Finding Href Value.");
597 if (0 == strcmp(OIC_JSON_REL_NAME, rMapName))
599 // TODO : Need to check data structure of OicSecPdAcl_t and assign based on RAML spec.
600 char *relData = NULL;
601 cborFindResult = cbor_value_dup_text_string(&rMap, &relData, &len, NULL);
602 VERIFY_CBOR_SUCCESS(TAG, cborFindResult, "Failed Finding REL Value.");
607 if (0 == strcmp(OIC_JSON_RT_NAME, rMapName))
609 // TODO : Need to check data structure of OicSecPdAcl_t and assign based on RAML spec.
611 cborFindResult = cbor_value_dup_text_string(&rMap, &rtData, &len, NULL);
612 VERIFY_CBOR_SUCCESS(TAG, cborFindResult, "Failed Finding RT Value.");
617 if (0 == strcmp(OIC_JSON_IF_NAME, rMapName))
619 // TODO : Need to check data structure of OicSecPdAcl_t and assign based on RAML spec.
621 cborFindResult = cbor_value_dup_text_string(&rMap, &ifData, &len, NULL);
622 VERIFY_CBOR_SUCCESS(TAG, cborFindResult, "Failed Finding IF Value.");
626 if (cbor_value_is_valid(&rMap))
628 cborFindResult = cbor_value_advance(&rMap);
629 VERIFY_CBOR_SUCCESS(TAG, cborFindResult, "Failed Advancing Rlist Map.");
634 if (cbor_value_is_valid(&resources))
636 cborFindResult = cbor_value_advance(&resources);
637 VERIFY_CBOR_SUCCESS(TAG, cborFindResult, "Failed to advance");
642 // Permissions -- Mandatory
643 if (strcmp(name, OIC_JSON_PERMISSION_NAME) == 0 && cbor_value_is_unsigned_integer(&pdAclMap))
645 uint64_t permission = 0;
646 cborFindResult = cbor_value_get_uint64(&pdAclMap, &permission);
647 pdacl->permission = (uint16_t)permission;
648 VERIFY_CBOR_SUCCESS(TAG, cborFindResult, "Failed to get value");
651 // Period -- Not mandatory
652 if (strcmp(name, OIC_JSON_PERIODS_NAME) == 0 && cbor_value_is_array(&pdAclMap))
655 CborValue period = { .parser = NULL };
656 cborFindResult = cbor_value_get_array_length(&pdAclMap,
658 VERIFY_CBOR_SUCCESS(TAG, cborFindResult, "Failed to get length");
659 cborFindResult = cbor_value_enter_container(&pdAclMap, &period);
660 VERIFY_CBOR_SUCCESS(TAG, cborFindResult, "Failed to enter");
661 pdacl->periods = (char **) OICCalloc(pdacl->prdRecrLen, sizeof(char*));
662 VERIFY_NON_NULL(TAG, pdacl->periods, ERROR);
664 while (cbor_value_is_text_string(&period) && cbor_value_is_text_string(&period))
666 cborFindResult = cbor_value_dup_text_string(&period,
667 &pdacl->periods[i++], &len, NULL);
668 VERIFY_CBOR_SUCCESS(TAG, cborFindResult, "Failed to get text");
669 cborFindResult = cbor_value_advance(&period);
670 VERIFY_CBOR_SUCCESS(TAG, cborFindResult, "Failed to advance");
675 // Recurrence -- Not mandatory
676 if (strcmp(name, OIC_JSON_RECURRENCES_NAME) == 0 && cbor_value_is_array(&pdAclMap))
679 CborValue recurrences = { .parser = NULL };
680 cborFindResult = cbor_value_get_array_length(&pdAclMap, &pdacl->prdRecrLen);
681 VERIFY_CBOR_SUCCESS(TAG, cborFindResult, "Failed to get length");
682 cborFindResult = cbor_value_enter_container(&pdAclMap, &recurrences);
683 VERIFY_CBOR_SUCCESS(TAG, cborFindResult, "Failed to enter");
684 pdacl->recurrences = (char **) OICCalloc(pdacl->prdRecrLen, sizeof(char*));
685 VERIFY_NON_NULL(TAG, pdacl->recurrences, ERROR);
687 while (cbor_value_is_text_string(&recurrences) && cbor_value_is_text_string(&recurrences))
689 cborFindResult = cbor_value_dup_text_string(&recurrences,
690 &pdacl->recurrences[i++], &len, NULL);
691 VERIFY_CBOR_SUCCESS(TAG, cborFindResult, "Failed to get value");
692 cborFindResult = cbor_value_advance(&recurrences);
693 VERIFY_CBOR_SUCCESS(TAG, cborFindResult, "Failed to advance");
696 if (type != CborMapType && cbor_value_is_valid(&pdAclMap))
698 cborFindResult = cbor_value_advance(&pdAclMap);
699 VERIFY_CBOR_SUCCESS(TAG, cborFindResult, "Failed to advance");
702 if (cbor_value_is_valid(&pdAclArray))
704 cborFindResult = cbor_value_advance(&pdAclArray);
705 VERIFY_CBOR_SUCCESS(TAG, cborFindResult, "Failed to advance");
711 if (headPdacl == NULL)
717 OicSecPdAcl_t *temp = headPdacl;
725 pconf->pdacls = headPdacl;
729 if (strcmp(name, OIC_JSON_PDDEV_LIST_NAME) == 0 && cbor_value_is_array(&pconfMap))
732 CborValue pddevs = { .parser = NULL };
733 cborFindResult = cbor_value_get_array_length(&pconfMap, &pconf->pddevLen);
734 VERIFY_CBOR_SUCCESS(TAG, cborFindResult, "Failed to get length");
735 cborFindResult = cbor_value_enter_container(&pconfMap, &pddevs);
736 VERIFY_CBOR_SUCCESS(TAG, cborFindResult, "Failed to enter");
738 pconf->pddevs = (OicUuid_t *)OICMalloc(pconf->pddevLen * sizeof(OicUuid_t));
739 VERIFY_NON_NULL(TAG, pconf->pddevs, ERROR);
740 while (cbor_value_is_valid(&pddevs) && cbor_value_is_text_string(&pddevs))
743 cborFindResult = cbor_value_dup_text_string(&pddevs, &pddev, &len, NULL);
744 VERIFY_CBOR_SUCCESS(TAG, cborFindResult, "Failed to get value");
745 cborFindResult = cbor_value_advance(&pddevs);
746 VERIFY_CBOR_SUCCESS(TAG, cborFindResult, "Failed to advance");
747 ret = ConvertStrToUuid(pddev, &pconf->pddevs[i++]);
748 VERIFY_SUCCESS(TAG, ret == OC_STACK_OK, ERROR);
753 //Mandatory - Device Id
754 if (0 == strcmp(OIC_JSON_DEVICE_ID_NAME, name) && cbor_value_is_text_string(&pconfMap))
756 char *deviceId = NULL;
757 cborFindResult = cbor_value_dup_text_string(&pconfMap, &deviceId, &len, NULL);
758 VERIFY_CBOR_SUCCESS(TAG, cborFindResult, "Failed to get deviceID");
759 ret = ConvertStrToUuid(deviceId, &pconf->deviceID);
760 VERIFY_SUCCESS(TAG, ret == OC_STACK_OK, ERROR);
764 // ROwner -- Mandatory
765 if (0 == strcmp(OIC_JSON_ROWNERID_NAME, name) && cbor_value_is_text_string(&pconfMap))
768 cborFindResult = cbor_value_dup_text_string(&pconfMap, &rowner, &len, NULL);
769 VERIFY_CBOR_SUCCESS(TAG, cborFindResult, "Failed to get rowner");
770 ret = ConvertStrToUuid(rowner, &pconf->rownerID);
771 VERIFY_SUCCESS(TAG, ret == OC_STACK_OK, ERROR);
775 if (CborMapType != type && cbor_value_is_valid(&pconfMap))
777 cborFindResult = cbor_value_advance(&pconfMap);
778 VERIFY_CBOR_SUCCESS(TAG, cborFindResult, "Failed to advance");
786 if (CborNoError != cborFindResult)
788 OIC_LOG (ERROR, TAG, "CBORPayloadToPconf failed");
789 DeletePconfBinData(pconf);
792 ret = OC_STACK_ERROR;
797 static bool UpdatePersistentStorage(const OicSecPconf_t * pconf)
801 // Convert PCONF data into Cborpayload for update to persistent storage
802 uint8_t *payload = NULL;
804 if (OC_STACK_OK == PconfToCBORPayload(pconf, &payload, &size) && NULL !=payload)
806 if (OC_STACK_OK == UpdateSecureResourceInPS(OIC_JSON_PCONF_NAME, payload, size))
815 static OCEntityHandlerResult HandlePconfGetRequest (const OCEntityHandlerRequest * ehRequest)
817 uint8_t* payload = NULL;
819 OCEntityHandlerResult ehRet = OC_EH_OK;
822 memset(&pconf, 0, sizeof(OicSecPconf_t));
824 OIC_LOG (DEBUG, TAG, "Pconf EntityHandle processing GET request");
826 if (true == GetDoxmResourceData()->dpc)
828 //Making response elements for Get request
829 if( (true == gPconf->edp) &&
830 (gPconf->prm && 0 < gPconf->prmLen) &&
831 (0 < strlen((const char*)gPconf->deviceID.id)) &&
832 (0 < strlen((const char*)gPconf->rownerID.id)))
835 pconf.prm = gPconf->prm;
836 pconf.prmLen = gPconf->prmLen;
837 memcpy(&pconf.deviceID, &gPconf->deviceID, sizeof(OicUuid_t));
838 memcpy(&pconf.rownerID, &gPconf->rownerID, sizeof(OicUuid_t));
839 OIC_LOG (DEBUG, TAG, "PCONF - direct pairing enabled");
841 else if (false == gPconf->edp)
844 memcpy(&pconf.rownerID, &gPconf->rownerID, sizeof(OicUuid_t));
845 OIC_LOG (DEBUG, TAG, "PCONF - direct pairing disable");
850 OIC_LOG (DEBUG, TAG, "PCONF - error");
855 OIC_LOG (DEBUG, TAG, "DPC == false : Direct-Pairing Disabled");
859 if (OC_STACK_OK != PconfToCBORPayload(gPconf, &payload, &size))
864 if(OC_EH_OK == ehRet)
866 ehRet = (payload ? OC_EH_OK : OC_EH_ERROR);
875 // Send response payload to request originator
876 if (OC_STACK_OK != SendSRMResponse(ehRequest, ehRet, payload, size))
879 OIC_LOG(ERROR, TAG, "SendSRMResponse failed in HandlePconfGetRequest");
881 OIC_LOG_V(DEBUG, TAG, "%s RetVal %d", __func__, ehRet);
887 static OCEntityHandlerResult HandlePconfPostRequest (const OCEntityHandlerRequest * ehRequest)
889 OCEntityHandlerResult ehRet = OC_EH_OK;
890 OCStackResult res=OC_STACK_OK;
891 OicSecPconf_t* newPconf = NULL;
893 if (true == GetDoxmResourceData()->dpc)
895 // Convert CBOR PCONF data into binary. This will also validate the PCONF data received.
896 uint8_t *payload = ((OCSecurityPayload *) ehRequest->payload)->securityData;
897 size_t size = ((OCSecurityPayload *) ehRequest->payload)->payloadSize;
900 res = CBORPayloadToPconf(payload, size, &newPconf);
905 OIC_LOG (DEBUG, TAG, "DPC == false : Direct-Pairing Disabled");
909 if (newPconf && res == OC_STACK_OK)
911 // Check if valid Post request
912 if ((true == newPconf->edp) && (0 < newPconf->prmLen) &&
913 DP_PIN_LENGTH == sizeof(newPconf->pin.val))
915 OicSecPrm_t *oldPrm = gPconf->prm;
916 OicSecPdAcl_t *oldPdacl = gPconf->pdacls;
918 // Update local PCONF with new PCONF
920 memcpy(&gPconf->pin, &newPconf->pin, sizeof(OicDpPin_t));
921 gPconf->prm = newPconf->prm;
922 gPconf->prmLen = newPconf->prmLen;
923 gPconf->pdacls = newPconf->pdacls;
924 memcpy(&gPconf->rownerID, &newPconf->rownerID, sizeof(OicUuid_t));
926 // to delete old value(prm, pdacl)
927 newPconf->prm = oldPrm;
928 newPconf->pdacls = oldPdacl;
930 else if (false == newPconf->edp)
940 if(OC_EH_ERROR != ehRet && true == UpdatePersistentStorage(gPconf))
942 ehRet = OC_EH_CHANGED;
945 DeletePconfBinData(newPconf);
952 // Send payload to request originator
953 if (OC_STACK_OK != SendSRMResponse(ehRequest, ehRet, NULL, 0))
956 OIC_LOG(ERROR, TAG, "SendSRMResponse failed in HandlePconfPostRequest");
959 OIC_LOG_V (DEBUG, TAG, "%s RetVal %d", __func__ , ehRet);
964 * This internal method is the entity handler for PCONF resources and
965 * will handle REST request (POST) for them.
967 OCEntityHandlerResult PconfEntityHandler (OCEntityHandlerFlag flag,
968 OCEntityHandlerRequest * ehRequest,
969 void* callbackParameter)
971 OIC_LOG(DEBUG, TAG, "Received request PconfEntityHandler");
972 (void)callbackParameter;
973 OCEntityHandlerResult ehRet = OC_EH_ERROR;
980 if (flag & OC_REQUEST_FLAG)
982 OIC_LOG (DEBUG, TAG, "Flag includes OC_REQUEST_FLAG");
983 switch (ehRequest->method)
986 ehRet = HandlePconfGetRequest(ehRequest);
990 ehRet = HandlePconfPostRequest(ehRequest);
998 SendSRMResponse(ehRequest, ehRet, NULL, 0);
1006 * This internal method is used to create '/oic/sec/pconf' resource.
1008 OCStackResult CreatePconfResource()
1012 ret = OCCreateResource(&gPconfHandle,
1013 OIC_RSRC_TYPE_SEC_PCONF,
1014 OC_RSRVD_INTERFACE_DEFAULT,
1018 OC_SECURE | OC_EXPLICIT_DISCOVERABLE);
1020 if (OC_STACK_OK != ret)
1022 OIC_LOG (ERROR, TAG, "Unable to instantiate PCONF resource");
1023 DeInitPconfResource();
1029 * Get the default value.
1030 * @retval the gDefaultPconf pointer;
1032 static OicSecPconf_t* GetPconfDefault()
1034 OIC_LOG (DEBUG, TAG, "GetPconfDefault");
1036 return &gDefaultPconf;
1040 * This method is used by SRM to retrieve PCONF resource data..
1042 * @retval reference to @ref OicSecPconf_t, binary format of Pconf resource data
1044 const OicSecPconf_t* GetPconfResourceData()
1050 * Initialize PCONF resource by loading data from persistent storage.
1052 * @retval OC_STACK_OK for Success, otherwise some error value
1054 OCStackResult InitPconfResource()
1056 OCStackResult ret = OC_STACK_ERROR;
1058 uint8_t *data = NULL;
1061 ret = GetSecureVirtualDatabaseFromPS(OIC_JSON_PCONF_NAME, &data, &size);
1062 // If database read failed
1063 if (ret != OC_STACK_OK)
1065 OIC_LOG(DEBUG, TAG, "ReadSVDataFromPS failed");
1069 CBORPayloadToPconf(data, size, &gPconf);
1072 if (!data || !gPconf)
1074 gPconf = GetPconfDefault();
1076 // device id from doxm
1077 OicUuid_t deviceId = {.id = {0}};
1078 OCStackResult ret = GetDoxmDeviceID( &deviceId);
1079 VERIFY_SUCCESS(TAG, OC_STACK_OK == ret, ERROR);
1080 memcpy(&gPconf->deviceID, &deviceId, sizeof(OicUuid_t));
1082 VERIFY_NON_NULL(TAG, gPconf, ERROR);
1084 // Instantiate 'oic.sec.pconf'
1085 ret = CreatePconfResource();
1088 if (OC_STACK_OK != ret)
1090 DeInitPconfResource();
1097 * Perform cleanup for PCONF resources.
1100 * OC_STACK_OK - no error
1101 * OC_STACK_ERROR - stack process error
1104 OCStackResult DeInitPconfResource()
1106 OCStackResult ret = OCDeleteResource(gPconfHandle);
1107 if(gPconf!= &gDefaultPconf)
1109 DeletePconfBinData(gPconf);
1113 if(OC_STACK_OK == ret)
1119 return OC_STACK_ERROR;
1124 * This method might be used to add a paired device id after direct-pairing process complete.
1126 * @param pdeviceId ID of the paired device.
1128 * @retval OC_STACK_OK for Success, otherwise some error value
1130 OCStackResult AddPairedDevice(OicUuid_t *pdeviceId)
1132 if (!gPconf || !pdeviceId)
1134 return OC_STACK_INVALID_PARAM;
1138 OicUuid_t *prevList = gPconf->pddevs;
1139 gPconf->pddevs = (OicUuid_t *)OICCalloc(gPconf->pddevLen+1, sizeof(OicUuid_t));
1142 return OC_STACK_NO_MEMORY;
1144 for (size_t i=0; i<gPconf->pddevLen; i++)
1146 memcpy(&gPconf->pddevs[i], &prevList[i], sizeof(OicUuid_t));
1149 // add new paired device id
1150 memcpy(&gPconf->pddevs[gPconf->pddevLen], pdeviceId, sizeof(OicUuid_t));
1154 if(true != UpdatePersistentStorage(gPconf))
1156 OIC_LOG (ERROR, TAG, "Fail to update pconf resource");
1157 return OC_STACK_ERROR;
1160 OIC_LOG (ERROR, TAG, "Add paired device success");
1165 * This method might be used by PolicyEngine to retrieve PDACL for a Subject.
1167 * @param subjectId ID of the subject for which PDACL is required.
1168 * @param savePtr is used internally by @ref GetACLResourceData to maintain index between
1169 * successive calls for same subjectId.
1171 * @retval reference to @ref OicSecPdAcl_t if PDACL is found, else NULL
1173 const OicSecPdAcl_t* GetPdAclData(const OicUuid_t* subjectId, OicSecPdAcl_t **savePtr)
1175 OicSecPdAcl_t *pdacl = NULL;
1177 if ( NULL == subjectId)
1183 * savePtr MUST point to NULL if this is the 'first' call to retrieve PDACL for
1186 if (NULL == *savePtr)
1188 pdacl = gPconf->pdacls;
1190 // Find if 'subjectID' is in paired device list.
1191 for(size_t i=0; i<gPconf->pddevLen; i++)
1193 if (memcmp(&(gPconf->pddevs[i]), subjectId, sizeof(OicUuid_t)) == 0)
1202 OicSecPdAcl_t *temp = NULL;
1205 * If this is a 'successive' call, search for location pointed by
1206 * savePtr and assign 'begin' to the next PDACL after it in the linked
1207 * list and start searching from there.
1209 LL_FOREACH(gPconf->pdacls, temp)
1211 if (temp == *savePtr)
1220 // Cleanup in case no PDACL is found
1226 * This method return whether device is paired or not.
1228 * @param pdeviceId Target device ID to find in paired list.
1229 * @retval ture if device is already paired, else false
1231 bool IsPairedDevice(const OicUuid_t* pdeviceId)
1233 // Find if 'pdeviceId' is in paired device list.
1234 for(size_t i=0; i<gPconf->pddevLen; i++)
1236 if (memcmp(&(gPconf->pddevs[i]), pdeviceId, sizeof(OicUuid_t)) == 0)
1244 OCStackResult SetPconfRownerId(const OicUuid_t* newROwner)
1246 OCStackResult ret = OC_STACK_ERROR;
1247 uint8_t *cborPayload = NULL;
1249 OicUuid_t prevId = {.id={0}};
1251 if(NULL == newROwner)
1253 ret = OC_STACK_INVALID_PARAM;
1257 ret = OC_STACK_NO_RESOURCE;
1260 if(newROwner && gPconf)
1262 memcpy(prevId.id, gPconf->rownerID.id, sizeof(prevId.id));
1263 memcpy(gPconf->rownerID.id, newROwner->id, sizeof(newROwner->id));
1265 ret = PconfToCBORPayload(gPconf, &cborPayload, &size);
1266 VERIFY_SUCCESS(TAG, OC_STACK_OK == ret, ERROR);
1268 ret = UpdateSecureResourceInPS(OIC_JSON_PCONF_NAME, cborPayload, size);
1269 VERIFY_SUCCESS(TAG, OC_STACK_OK == ret, ERROR);
1271 OICFree(cborPayload);
1277 OICFree(cborPayload);
1278 memcpy(gPconf->rownerID.id, prevId.id, sizeof(prevId.id));
1282 OCStackResult GetPconfRownerId(OicUuid_t *rowneruuid)
1284 OCStackResult retVal = OC_STACK_ERROR;
1287 *rowneruuid = gPconf->rownerID;
1288 retVal = OC_STACK_OK;