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"
46 #define TAG "SRM-PCONF"
48 static const uint16_t CBOR_SIZE = 1024;
49 static const uint64_t CBOR_MAX_SIZE = 4400;
50 static const uint8_t PCONF_MAP_SIZE = 4;
51 static const uint8_t PCONF_RESOURCE_MAP_SIZE = 4;
53 static OicSecPconf_t *gPconf = NULL;
54 static OCResourceHandle gPconfHandle = NULL;
55 static OicSecPconf_t gDefaultPconf =
58 NULL, /* OicSecPrm *prm */
59 0, /* size_t prmLen */
60 {.val = {0}}, /* OicDpPin_t pin */
61 NULL, /* OicSecPdAcl_t *pdacls */
62 NULL, /* OicUuid_t *pddevs */
63 0, /* size_t pddevLen */
64 {.id = {0}}, /* OicUuid_t deviceID */
65 {.id = {0}}, /* OicUuid_t rowner */
69 * This function frees OicSecPdAcl_t object's fields and object itself.
71 void FreePdAclList(OicSecPdAcl_t* pdacls)
78 OicSecPdAcl_t *aclTmp1 = NULL;
79 OicSecPdAcl_t *aclTmp2 = NULL;
80 LL_FOREACH_SAFE(pdacls, aclTmp1, aclTmp2)
82 LL_DELETE(pdacls, aclTmp1);
85 for (i = 0; i < aclTmp1->resourcesLen; i++)
87 OICFree(aclTmp1->resources[i]);
89 OICFree(aclTmp1->resources);
94 for(i = 0; i < aclTmp1->prdRecrLen; i++)
96 OICFree(aclTmp1->periods[i]);
98 OICFree(aclTmp1->periods);
102 if(aclTmp1->recurrences)
104 for(i = 0; i < aclTmp1->prdRecrLen; i++)
106 OICFree(aclTmp1->recurrences[i]);
108 OICFree(aclTmp1->recurrences);
117 void DeletePconfBinData(OicSecPconf_t* pconf)
127 FreePdAclList(pconf->pdacls);
131 OICFree(pconf->pddevs);
138 static size_t OicPdAclSize(const OicSecPdAcl_t *pdAcl)
145 OicSecPdAcl_t *tmp = (OicSecPdAcl_t *)pdAcl;
155 OCStackResult PconfToCBORPayload(const OicSecPconf_t *pconf,uint8_t **payload,size_t *size)
157 if (NULL == pconf || NULL == payload || NULL != *payload || NULL == size)
159 return OC_STACK_INVALID_PARAM;
161 size_t cborLen = *size;
168 OCStackResult ret = OC_STACK_ERROR;
170 CborEncoder pconfMap;
172 int64_t cborEncoderResult = CborNoError;
173 uint8_t mapSize = PCONF_MAP_SIZE;
175 if (pconf->prmLen > 0)
188 uint8_t *outPayload = (uint8_t *)OICCalloc(1, cborLen);
189 VERIFY_NON_NULL(TAG, outPayload, ERROR);
191 cbor_encoder_init(&encoder, outPayload, cborLen, 0);
192 cborEncoderResult = cbor_encoder_create_map(&encoder, &pconfMap, mapSize);
193 VERIFY_CBOR_SUCCESS(TAG, cborEncoderResult, "Failed Creating Pconf Map.");
196 cborEncoderResult = cbor_encode_text_string(&pconfMap, OIC_JSON_EDP_NAME,
197 strlen(OIC_JSON_EDP_NAME));
198 VERIFY_CBOR_SUCCESS(TAG, cborEncoderResult, "Failed Encode EDP String.");
199 cborEncoderResult = cbor_encode_boolean(&pconfMap, pconf->edp);
200 VERIFY_CBOR_SUCCESS(TAG, cborEncoderResult, "Failed Convert PconfEDP value");
202 //PRM type -- Not Mandatory
203 if(pconf->prmLen > 0)
206 cborEncoderResult = cbor_encode_text_string(&pconfMap, OIC_JSON_PRM_NAME,
207 strlen(OIC_JSON_PRM_NAME));
208 VERIFY_CBOR_SUCCESS(TAG, cborEncoderResult, "Failed Convert Pconf PRM NAME");
209 cborEncoderResult = cbor_encoder_create_array(&pconfMap, &prm, pconf->prmLen);
210 VERIFY_CBOR_SUCCESS(TAG, cborEncoderResult, "Failed Convert Pconf PRM value");
212 for (size_t i = 0; i < pconf->prmLen; i++)
214 cborEncoderResult = cbor_encode_int(&prm, pconf->prm[i]);
215 VERIFY_CBOR_SUCCESS(TAG, cborEncoderResult, "Failed Convert Pconf PRM Array");
217 cborEncoderResult = cbor_encoder_close_container(&pconfMap, &prm);
218 VERIFY_CBOR_SUCCESS(TAG, cborEncoderResult, "Failed to close encode array");
222 cborEncoderResult = cbor_encode_text_string(&pconfMap, OIC_JSON_PIN_NAME,
223 strlen(OIC_JSON_PIN_NAME));
224 VERIFY_CBOR_SUCCESS(TAG, cborEncoderResult, "Failed to create OIC_JSON_PIN_NAME");
225 cborEncoderResult = cbor_encode_byte_string(&pconfMap, pconf->pin.val, sizeof(pconf->pin.val));
226 VERIFY_CBOR_SUCCESS(TAG, cborEncoderResult, "Failed to convert pin value");
231 OicSecPdAcl_t *pdacl = pconf->pdacls;
232 CborEncoder pdAclArray;
233 cborEncoderResult = cbor_encode_text_string(&pconfMap, OIC_JSON_PDACL_NAME,
234 strlen(OIC_JSON_PDACL_NAME));
235 VERIFY_CBOR_SUCCESS(TAG, cborEncoderResult, "Failed to create OIC_JSON_PDACL_NAME");
236 cborEncoderResult = cbor_encoder_create_array(&pconfMap, &pdAclArray,
237 OicPdAclSize(pconf->pdacls));
238 VERIFY_CBOR_SUCCESS(TAG, cborEncoderResult, "Failed to creeate _pdacl array");
242 CborEncoder pdAclMap;
243 // PDACL Map size - Number of mandatory items
244 uint8_t aclMapSize = 2;
246 if (pdacl->prdRecrLen)
250 if (pdacl->recurrences)
255 cborEncoderResult = cbor_encoder_create_map(&pdAclArray, &pdAclMap, aclMapSize);
256 VERIFY_CBOR_SUCCESS(TAG, cborEncoderResult, "Failed to creeate _pdacl array");
258 // Resources -- Mandatory
259 cborEncoderResult = cbor_encode_text_string(&pdAclMap, OIC_JSON_RESOURCES_NAME,
260 strlen(OIC_JSON_RESOURCES_NAME));
261 VERIFY_CBOR_SUCCESS(TAG, cborEncoderResult, "Failed to encode resource result");
263 CborEncoder resources;
264 cborEncoderResult = cbor_encoder_create_array(&pdAclMap, &resources,
265 pdacl->resourcesLen);
266 VERIFY_CBOR_SUCCESS(TAG, cborEncoderResult, "Failed to create resource array");
268 for (size_t i = 0; i < pdacl->resourcesLen; i++)
271 cborEncoderResult = cbor_encoder_create_map(&resources, &rMap,
272 PCONF_RESOURCE_MAP_SIZE);
273 VERIFY_CBOR_SUCCESS(TAG, cborEncoderResult, "Failed Addding Resource Map.");
275 cborEncoderResult = cbor_encode_text_string(&rMap, OIC_JSON_HREF_NAME,
276 strlen(OIC_JSON_HREF_NAME));
277 VERIFY_CBOR_SUCCESS(TAG, cborEncoderResult, "Failed Addding HREF Name Tag.");
278 cborEncoderResult = cbor_encode_text_string(&rMap, pdacl->resources[i],
279 strlen(pdacl->resources[i]));
280 VERIFY_CBOR_SUCCESS(TAG, cborEncoderResult, "Failed Addding HREF Value in Map.");
282 cborEncoderResult = cbor_encode_text_string(&rMap, OIC_JSON_REL_NAME,
283 strlen(OIC_JSON_REL_NAME));
284 VERIFY_CBOR_SUCCESS(TAG, cborEncoderResult, "Failed Addding REL Name Tag.");
286 // TODO : Need to assign real value of REL
287 cborEncoderResult = cbor_encode_text_string(&rMap, OIC_JSON_EMPTY_STRING,
288 strlen(OIC_JSON_EMPTY_STRING));
289 VERIFY_CBOR_SUCCESS(TAG, cborEncoderResult, "Failed Addding REL Value.");
291 cborEncoderResult = cbor_encode_text_string(&rMap, OIC_JSON_RT_NAME,
292 strlen(OIC_JSON_RT_NAME));
293 VERIFY_CBOR_SUCCESS(TAG, cborEncoderResult, "Failed Addding RT Name Tag.");
295 // TODO : Need to assign real value of RT
296 cborEncoderResult = cbor_encode_text_string(&rMap, OIC_JSON_EMPTY_STRING,
297 strlen(OIC_JSON_EMPTY_STRING));
298 VERIFY_CBOR_SUCCESS(TAG, cborEncoderResult, "Failed Addding RT Value.");
300 cborEncoderResult = cbor_encode_text_string(&rMap, OIC_JSON_IF_NAME,
301 strlen(OIC_JSON_IF_NAME));
302 VERIFY_CBOR_SUCCESS(TAG, cborEncoderResult, "Failed Addding IF Name Tag.");
304 // TODO : Need to assign real value of IF
305 cborEncoderResult = cbor_encode_text_string(&rMap, OIC_JSON_EMPTY_STRING,
306 strlen(OIC_JSON_EMPTY_STRING));
307 VERIFY_CBOR_SUCCESS(TAG, cborEncoderResult, "Failed Addding IF Value.");
309 cborEncoderResult = cbor_encoder_close_container(&resources, &rMap);
310 VERIFY_CBOR_SUCCESS(TAG, cborEncoderResult, "Failed Closing Resource Map.");
313 cborEncoderResult = cbor_encoder_close_container(&pdAclMap, &resources);
314 VERIFY_CBOR_SUCCESS(TAG, cborEncoderResult, "Failed to close resource array");
316 // Permissions -- Mandatory
317 cborEncoderResult = cbor_encode_text_string(&pdAclMap, OIC_JSON_PERMISSION_NAME,
318 strlen(OIC_JSON_PERMISSION_NAME));
319 VERIFY_CBOR_SUCCESS(TAG, cborEncoderResult, "Failed to create permition string");
320 cborEncoderResult = cbor_encode_int(&pdAclMap, pdacl->permission);
321 VERIFY_CBOR_SUCCESS(TAG, cborEncoderResult, "Failed to encode permition calue");
323 // Period -- Not Mandatory
327 cborEncoderResult = cbor_encode_text_string(&pdAclMap, OIC_JSON_PERIODS_NAME,
328 strlen(OIC_JSON_PERIODS_NAME));
329 VERIFY_CBOR_SUCCESS(TAG, cborEncoderResult, "Failed to encode period value");
330 cborEncoderResult = cbor_encoder_create_array(&pdAclMap, &period,
332 VERIFY_CBOR_SUCCESS(TAG, cborEncoderResult, "Failed to create array");
334 for (size_t i = 0; i < pdacl->prdRecrLen; i++)
336 cborEncoderResult = cbor_encode_text_string(&period, pdacl->periods[i],
337 strlen(pdacl->periods[i]));
338 VERIFY_CBOR_SUCCESS(TAG, cborEncoderResult, "Failed to encode period");
340 cborEncoderResult = cbor_encoder_close_container(&pdAclMap, &period);
341 VERIFY_CBOR_SUCCESS(TAG, cborEncoderResult,"Failed to close period array");
344 // Period -- Not Mandatory
345 if(0 != pdacl->prdRecrLen && pdacl->recurrences)
347 CborEncoder recurrences;
348 cborEncoderResult = cbor_encode_text_string(&pdAclMap, OIC_JSON_RECURRENCES_NAME,
349 strlen(OIC_JSON_RECURRENCES_NAME));
350 VERIFY_CBOR_SUCCESS(TAG, cborEncoderResult,"Failed to encode recurrences");
351 cborEncoderResult = cbor_encoder_create_array(&pdAclMap, &recurrences,
353 VERIFY_CBOR_SUCCESS(TAG, cborEncoderResult, "Failed to create rec array");
355 for (size_t i = 0; i < pdacl->prdRecrLen; i++)
357 cborEncoderResult = cbor_encode_text_string(&recurrences,
358 pdacl->recurrences[i], strlen(pdacl->recurrences[i]));
359 VERIFY_CBOR_SUCCESS(TAG, cborEncoderResult, "Failed to encode recurrences");
361 cborEncoderResult = cbor_encoder_close_container(&pdAclMap, &recurrences);
362 VERIFY_CBOR_SUCCESS(TAG, cborEncoderResult, "Failed to close rec array");
364 cborEncoderResult = cbor_encoder_close_container(&pdAclArray, &pdAclMap);
365 VERIFY_CBOR_SUCCESS(TAG, cborEncoderResult, "Failed to close acl map");
370 cborEncoderResult = cbor_encoder_close_container(&pconfMap, &pdAclArray);
371 VERIFY_CBOR_SUCCESS(TAG, cborEncoderResult, "Failed to close acl array");
375 //There may not be paired devices if it did not pairing before
376 if (pconf->pddevs && 0 < pconf->pddevLen)
379 cborEncoderResult = cbor_encode_text_string(&pconfMap, OIC_JSON_PDDEV_LIST_NAME,
380 strlen(OIC_JSON_PDDEV_LIST_NAME));
381 VERIFY_CBOR_SUCCESS(TAG, cborEncoderResult, "Failed to encode pddev");
382 cborEncoderResult = cbor_encoder_create_array(&pconfMap, &pddev, pconf->pddevLen);
383 VERIFY_CBOR_SUCCESS(TAG, cborEncoderResult, "Failed to create array");
385 for (size_t i = 0; i < pconf->pddevLen; i++)
387 char *pddevId = NULL;
388 ret = ConvertUuidToStr(&pconf->pddevs[i], &pddevId);
389 VERIFY_SUCCESS(TAG, ret == OC_STACK_OK, ERROR);
390 cborEncoderResult = cbor_encode_text_string(&pddev, pddevId, strlen(pddevId));
391 VERIFY_CBOR_SUCCESS(TAG, cborEncoderResult, "Failed Addding pddev Id Value.");
394 cborEncoderResult = cbor_encoder_close_container(&pconfMap, &pddev);
395 VERIFY_CBOR_SUCCESS(TAG, cborEncoderResult, "Failed to close pddev array");
398 //DeviceId -- Mandatory
399 //There may not be devicd id if caller is provisoning tool
400 cborEncoderResult = cbor_encode_text_string(&pconfMap, OIC_JSON_DEVICE_ID_NAME,
401 strlen(OIC_JSON_DEVICE_ID_NAME));
402 VERIFY_CBOR_SUCCESS(TAG, cborEncoderResult, "Failed to encode device id");
404 char *deviceId = NULL;
405 ret = ConvertUuidToStr(&pconf->deviceID, &deviceId);
406 VERIFY_SUCCESS(TAG, ret == OC_STACK_OK, ERROR);
407 cborEncoderResult = cbor_encode_text_string(&pconfMap, deviceId, strlen(deviceId));
408 VERIFY_CBOR_SUCCESS(TAG, cborEncoderResult, "Failed to encode deviceID value");
412 //ROwner -- Mandatory
415 cborEncoderResult = cbor_encode_text_string(&pconfMap, OIC_JSON_ROWNERID_NAME,
416 strlen(OIC_JSON_ROWNERID_NAME));
417 VERIFY_CBOR_SUCCESS(TAG, cborEncoderResult, "Failed to encode rowner string");
418 ret = ConvertUuidToStr(&pconf->rownerID, &rowner);
419 VERIFY_SUCCESS(TAG, ret == OC_STACK_OK, ERROR);
420 cborEncoderResult = cbor_encode_text_string(&pconfMap, rowner, strlen(rowner));
421 VERIFY_CBOR_SUCCESS(TAG, cborEncoderResult, "Failed to encode rwoner value");
425 cborEncoderResult = cbor_encoder_close_container(&encoder, &pconfMap);
426 VERIFY_CBOR_SUCCESS(TAG, cborEncoderResult, "Failed to close pconfMap");
428 *size = encoder.ptr - outPayload;
429 *payload = outPayload;
432 if ((CborErrorOutOfMemory == cborEncoderResult) && (cborLen < CBOR_MAX_SIZE))
434 // reallocate and try again!
436 // Since the allocated initial memory failed, double the memory.
437 cborLen += encoder.ptr - encoder.end;
438 cborEncoderResult = CborNoError;
439 ret = PconfToCBORPayload(pconf, payload, &cborLen);
442 if ((CborNoError != cborEncoderResult) || (OC_STACK_OK != ret))
448 ret = OC_STACK_ERROR;
453 OCStackResult CBORPayloadToPconf(const uint8_t *cborPayload, size_t size, OicSecPconf_t **secPconf)
455 if (NULL == cborPayload || NULL == secPconf || NULL != *secPconf || 0 == size)
457 return OC_STACK_INVALID_PARAM;
459 OCStackResult ret = OC_STACK_ERROR;
461 CborValue pconfCbor = { .parser = NULL };
462 CborParser parser = { .end = NULL };
463 CborError cborFindResult = CborNoError;
465 cbor_parser_init(cborPayload, size, 0, &parser, &pconfCbor);
466 CborValue pconfMap = { .parser = NULL } ;
467 OicSecPconf_t *pconf = NULL;
468 cborFindResult = cbor_value_enter_container(&pconfCbor, &pconfMap);
469 VERIFY_CBOR_SUCCESS(TAG, cborFindResult, "Failed to enter map");
470 pconf = (OicSecPconf_t *)OICCalloc(1, sizeof(*pconf));
471 VERIFY_NON_NULL(TAG, pconf, ERROR);
472 while (cbor_value_is_valid(&pconfMap))
476 CborType type = cbor_value_get_type(&pconfMap);
477 if (type == CborTextStringType && cbor_value_is_text_string(&pconfMap))
479 cborFindResult = cbor_value_dup_text_string(&pconfMap, &name, &len, NULL);
480 VERIFY_CBOR_SUCCESS(TAG, cborFindResult, "Failed to get value");
481 cborFindResult = cbor_value_advance(&pconfMap);
482 VERIFY_CBOR_SUCCESS(TAG, cborFindResult, "Failed to advance value");
488 if(0 == strcmp(OIC_JSON_EDP_NAME, name) && cbor_value_is_boolean(&pconfMap))
490 cborFindResult = cbor_value_get_boolean(&pconfMap, &pconf->edp);
491 VERIFY_CBOR_SUCCESS(TAG, cborFindResult, "Failed to get value");
493 if (0 == strcmp(OIC_JSON_PRM_NAME, name))
496 CborValue prm = { .parser = NULL };
497 cborFindResult = cbor_value_get_array_length(&pconfMap, &pconf->prmLen);
498 VERIFY_CBOR_SUCCESS(TAG, cborFindResult, "Failed to get length");
499 VERIFY_SUCCESS(TAG, pconf->prmLen != 0, ERROR);
501 pconf->prm = (OicSecPrm_t *)OICCalloc(pconf->prmLen, sizeof(OicSecPrm_t));
502 VERIFY_NON_NULL(TAG, pconf->prm, ERROR);
503 cborFindResult = cbor_value_enter_container(&pconfMap, &prm);
504 VERIFY_CBOR_SUCCESS(TAG, cborFindResult, "Failed to eneter array");
506 while (cbor_value_is_valid(&prm) && cbor_value_is_integer(&prm))
510 cborFindResult = cbor_value_get_int(&prm, &prm_val);
511 VERIFY_CBOR_SUCCESS(TAG, cborFindResult, "Failed to get value");
512 pconf->prm[i++] = (OicSecPrm_t)prm_val;
513 cborFindResult = cbor_value_advance(&prm);
514 VERIFY_CBOR_SUCCESS(TAG, cborFindResult, "Failed to advance value");
518 if (0 == strcmp(OIC_JSON_PIN_NAME, name) && cbor_value_is_byte_string(&pconfMap))
521 cborFindResult = cbor_value_dup_byte_string(&pconfMap, &pin, &len, NULL);
522 VERIFY_CBOR_SUCCESS(TAG, cborFindResult, "Failed to get value");
523 memcpy(pconf->pin.val, pin, len);
528 if (0 == strcmp(OIC_JSON_PDACL_NAME, name))
530 CborValue pdAclArray = { .parser = NULL};
531 OicSecPdAcl_t *headPdacl = NULL;
533 cborFindResult = cbor_value_enter_container(&pconfMap, &pdAclArray);
534 VERIFY_CBOR_SUCCESS(TAG, cborFindResult, "Failed to enter");
536 while (cbor_value_is_valid(&pdAclArray))
538 CborValue pdAclMap = { .parser = NULL};
539 OicSecPdAcl_t *pdacl = (OicSecPdAcl_t *) OICCalloc(1, sizeof(OicSecPdAcl_t));
540 VERIFY_NON_NULL(TAG, pdacl, ERROR);
542 cborFindResult = cbor_value_enter_container(&pdAclArray, &pdAclMap);
543 VERIFY_CBOR_SUCCESS(TAG, cborFindResult, "Failed to enter");
545 while (cbor_value_is_valid(&pdAclMap))
549 CborType type = cbor_value_get_type(&pdAclMap);
550 if (type == CborTextStringType && cbor_value_is_text_string(&pdAclMap))
552 cborFindResult = cbor_value_dup_text_string(&pdAclMap, &name,
554 VERIFY_CBOR_SUCCESS(TAG, cborFindResult, "Failed to get text");
555 cborFindResult = cbor_value_advance(&pdAclMap);
556 VERIFY_CBOR_SUCCESS(TAG, cborFindResult, "Failed to advance value");
560 // Resources -- Mandatory
561 if (strcmp(name, OIC_JSON_RESOURCES_NAME) == 0 && cbor_value_is_array(&pdAclMap))
564 CborValue resources = { .parser = NULL };
565 cborFindResult = cbor_value_get_array_length(&pdAclMap,
566 &pdacl->resourcesLen);
567 VERIFY_CBOR_SUCCESS(TAG, cborFindResult, "Failed to get length");
568 cborFindResult = cbor_value_enter_container(&pdAclMap, &resources);
569 VERIFY_CBOR_SUCCESS(TAG, cborFindResult, "Failed to enter");
570 pdacl->resources = (char **) OICCalloc(pdacl->resourcesLen,
572 VERIFY_NON_NULL(TAG, pdacl->resources, ERROR);
574 while (cbor_value_is_valid(&resources))
576 CborValue rMap = { .parser = NULL };
577 cborFindResult = cbor_value_enter_container(&resources, &rMap);
578 VERIFY_CBOR_SUCCESS(TAG, cborFindResult, "Failed Entering Resource Map");
580 while(cbor_value_is_valid(&rMap) && cbor_value_is_text_string(&rMap))
582 char *rMapName = NULL;
583 size_t rMapNameLen = 0;
584 cborFindResult = cbor_value_dup_text_string(&rMap, &rMapName, &rMapNameLen, NULL);
585 VERIFY_CBOR_SUCCESS(TAG, cborFindResult, "Failed Finding RMap Data Name Tag.");
586 cborFindResult = cbor_value_advance(&rMap);
587 VERIFY_CBOR_SUCCESS(TAG, cborFindResult, "Failed Finding RMap Data Value.");
590 if (0 == strcmp(OIC_JSON_HREF_NAME, rMapName))
592 // TODO : Need to check data structure of OicSecPdAcl_t based on RAML spec.
593 cborFindResult = cbor_value_dup_text_string(&rMap, &pdacl->resources[i++], &len, NULL);
594 VERIFY_CBOR_SUCCESS(TAG, cborFindResult, "Failed Finding Href Value.");
598 if (0 == strcmp(OIC_JSON_REL_NAME, rMapName))
600 // TODO : Need to check data structure of OicSecPdAcl_t and assign based on RAML spec.
601 char *relData = NULL;
602 cborFindResult = cbor_value_dup_text_string(&rMap, &relData, &len, NULL);
603 VERIFY_CBOR_SUCCESS(TAG, cborFindResult, "Failed Finding REL Value.");
608 if (0 == strcmp(OIC_JSON_RT_NAME, rMapName))
610 // TODO : Need to check data structure of OicSecPdAcl_t and assign based on RAML spec.
612 cborFindResult = cbor_value_dup_text_string(&rMap, &rtData, &len, NULL);
613 VERIFY_CBOR_SUCCESS(TAG, cborFindResult, "Failed Finding RT Value.");
618 if (0 == strcmp(OIC_JSON_IF_NAME, rMapName))
620 // TODO : Need to check data structure of OicSecPdAcl_t and assign based on RAML spec.
622 cborFindResult = cbor_value_dup_text_string(&rMap, &ifData, &len, NULL);
623 VERIFY_CBOR_SUCCESS(TAG, cborFindResult, "Failed Finding IF Value.");
627 if (cbor_value_is_valid(&rMap))
629 cborFindResult = cbor_value_advance(&rMap);
630 VERIFY_CBOR_SUCCESS(TAG, cborFindResult, "Failed Advancing Rlist Map.");
635 if (cbor_value_is_valid(&resources))
637 cborFindResult = cbor_value_advance(&resources);
638 VERIFY_CBOR_SUCCESS(TAG, cborFindResult, "Failed to advance");
643 // Permissions -- Mandatory
644 if (strcmp(name, OIC_JSON_PERMISSION_NAME) == 0 && cbor_value_is_unsigned_integer(&pdAclMap))
646 uint64_t permission = 0;
647 cborFindResult = cbor_value_get_uint64(&pdAclMap, &permission);
648 pdacl->permission = (uint16_t)permission;
649 VERIFY_CBOR_SUCCESS(TAG, cborFindResult, "Failed to get value");
652 // Period -- Not mandatory
653 if (strcmp(name, OIC_JSON_PERIODS_NAME) == 0 && cbor_value_is_array(&pdAclMap))
656 CborValue period = { .parser = NULL };
657 cborFindResult = cbor_value_get_array_length(&pdAclMap,
659 VERIFY_CBOR_SUCCESS(TAG, cborFindResult, "Failed to get length");
660 cborFindResult = cbor_value_enter_container(&pdAclMap, &period);
661 VERIFY_CBOR_SUCCESS(TAG, cborFindResult, "Failed to enter");
662 pdacl->periods = (char **) OICCalloc(pdacl->prdRecrLen, sizeof(char*));
663 VERIFY_NON_NULL(TAG, pdacl->periods, ERROR);
665 while (cbor_value_is_text_string(&period) && cbor_value_is_text_string(&period))
667 cborFindResult = cbor_value_dup_text_string(&period,
668 &pdacl->periods[i++], &len, NULL);
669 VERIFY_CBOR_SUCCESS(TAG, cborFindResult, "Failed to get text");
670 cborFindResult = cbor_value_advance(&period);
671 VERIFY_CBOR_SUCCESS(TAG, cborFindResult, "Failed to advance");
676 // Recurrence -- Not mandatory
677 if (strcmp(name, OIC_JSON_RECURRENCES_NAME) == 0 && cbor_value_is_array(&pdAclMap))
680 CborValue recurrences = { .parser = NULL };
681 cborFindResult = cbor_value_get_array_length(&pdAclMap, &pdacl->prdRecrLen);
682 VERIFY_CBOR_SUCCESS(TAG, cborFindResult, "Failed to get length");
683 cborFindResult = cbor_value_enter_container(&pdAclMap, &recurrences);
684 VERIFY_CBOR_SUCCESS(TAG, cborFindResult, "Failed to enter");
685 pdacl->recurrences = (char **) OICCalloc(pdacl->prdRecrLen, sizeof(char*));
686 VERIFY_NON_NULL(TAG, pdacl->recurrences, ERROR);
688 while (cbor_value_is_text_string(&recurrences) && cbor_value_is_text_string(&recurrences))
690 cborFindResult = cbor_value_dup_text_string(&recurrences,
691 &pdacl->recurrences[i++], &len, NULL);
692 VERIFY_CBOR_SUCCESS(TAG, cborFindResult, "Failed to get value");
693 cborFindResult = cbor_value_advance(&recurrences);
694 VERIFY_CBOR_SUCCESS(TAG, cborFindResult, "Failed to advance");
697 if (type != CborMapType && cbor_value_is_valid(&pdAclMap))
699 cborFindResult = cbor_value_advance(&pdAclMap);
700 VERIFY_CBOR_SUCCESS(TAG, cborFindResult, "Failed to advance");
703 if (cbor_value_is_valid(&pdAclArray))
705 cborFindResult = cbor_value_advance(&pdAclArray);
706 VERIFY_CBOR_SUCCESS(TAG, cborFindResult, "Failed to advance");
712 if (headPdacl == NULL)
718 OicSecPdAcl_t *temp = headPdacl;
726 pconf->pdacls = headPdacl;
730 if (strcmp(name, OIC_JSON_PDDEV_LIST_NAME) == 0 && cbor_value_is_array(&pconfMap))
733 CborValue pddevs = { .parser = NULL };
734 cborFindResult = cbor_value_get_array_length(&pconfMap, &pconf->pddevLen);
735 VERIFY_CBOR_SUCCESS(TAG, cborFindResult, "Failed to get length");
736 cborFindResult = cbor_value_enter_container(&pconfMap, &pddevs);
737 VERIFY_CBOR_SUCCESS(TAG, cborFindResult, "Failed to enter");
739 pconf->pddevs = (OicUuid_t *)OICMalloc(pconf->pddevLen * sizeof(OicUuid_t));
740 VERIFY_NON_NULL(TAG, pconf->pddevs, ERROR);
741 while (cbor_value_is_valid(&pddevs) && cbor_value_is_text_string(&pddevs))
744 cborFindResult = cbor_value_dup_text_string(&pddevs, &pddev, &len, NULL);
745 VERIFY_CBOR_SUCCESS(TAG, cborFindResult, "Failed to get value");
746 cborFindResult = cbor_value_advance(&pddevs);
747 VERIFY_CBOR_SUCCESS(TAG, cborFindResult, "Failed to advance");
748 ret = ConvertStrToUuid(pddev, &pconf->pddevs[i++]);
749 VERIFY_SUCCESS(TAG, ret == OC_STACK_OK, ERROR);
754 //Mandatory - Device Id
755 if (0 == strcmp(OIC_JSON_DEVICE_ID_NAME, name) && cbor_value_is_text_string(&pconfMap))
757 char *deviceId = NULL;
758 cborFindResult = cbor_value_dup_text_string(&pconfMap, &deviceId, &len, NULL);
759 VERIFY_CBOR_SUCCESS(TAG, cborFindResult, "Failed to get deviceID");
760 ret = ConvertStrToUuid(deviceId, &pconf->deviceID);
761 VERIFY_SUCCESS(TAG, ret == OC_STACK_OK, ERROR);
765 // ROwner -- Mandatory
766 if (0 == strcmp(OIC_JSON_ROWNERID_NAME, name) && cbor_value_is_text_string(&pconfMap))
769 cborFindResult = cbor_value_dup_text_string(&pconfMap, &rowner, &len, NULL);
770 VERIFY_CBOR_SUCCESS(TAG, cborFindResult, "Failed to get rowner");
771 ret = ConvertStrToUuid(rowner, &pconf->rownerID);
772 VERIFY_SUCCESS(TAG, ret == OC_STACK_OK, ERROR);
776 if (CborMapType != type && cbor_value_is_valid(&pconfMap))
778 cborFindResult = cbor_value_advance(&pconfMap);
779 VERIFY_CBOR_SUCCESS(TAG, cborFindResult, "Failed to advance");
787 if (CborNoError != cborFindResult)
789 OIC_LOG (ERROR, TAG, "CBORPayloadToPconf failed");
790 DeletePconfBinData(pconf);
793 ret = OC_STACK_ERROR;
798 static bool UpdatePersistentStorage(const OicSecPconf_t * pconf)
802 // Convert PCONF data into Cborpayload for update to persistent storage
803 uint8_t *payload = NULL;
805 if (OC_STACK_OK == PconfToCBORPayload(pconf, &payload, &size) && NULL !=payload)
807 if (OC_STACK_OK == UpdateSecureResourceInPS(OIC_JSON_PCONF_NAME, payload, size))
816 static OCEntityHandlerResult HandlePconfGetRequest (const OCEntityHandlerRequest * ehRequest)
818 uint8_t* payload = NULL;
820 OCEntityHandlerResult ehRet = OC_EH_OK;
823 memset(&pconf, 0, sizeof(OicSecPconf_t));
825 OIC_LOG (DEBUG, TAG, "Pconf EntityHandle processing GET request");
827 if (true == GetDoxmResourceData()->dpc)
829 //Making response elements for Get request
830 if( (true == gPconf->edp) &&
831 (gPconf->prm && 0 < gPconf->prmLen) &&
832 (0 < strlen((const char*)gPconf->deviceID.id)) &&
833 (0 < strlen((const char*)gPconf->rownerID.id)))
836 pconf.prm = gPconf->prm;
837 pconf.prmLen = gPconf->prmLen;
838 memcpy(&pconf.deviceID, &gPconf->deviceID, sizeof(OicUuid_t));
839 memcpy(&pconf.rownerID, &gPconf->rownerID, sizeof(OicUuid_t));
840 OIC_LOG (DEBUG, TAG, "PCONF - direct pairing enabled");
842 else if (false == gPconf->edp)
845 memcpy(&pconf.rownerID, &gPconf->rownerID, sizeof(OicUuid_t));
846 OIC_LOG (DEBUG, TAG, "PCONF - direct pairing disable");
851 OIC_LOG (DEBUG, TAG, "PCONF - error");
856 OIC_LOG (DEBUG, TAG, "DPC == false : Direct-Pairing Disabled");
860 if (OC_STACK_OK != PconfToCBORPayload(gPconf, &payload, &size))
865 if(OC_EH_OK == ehRet)
867 ehRet = (payload ? OC_EH_OK : OC_EH_ERROR);
876 // Send response payload to request originator
877 if (OC_STACK_OK != SendSRMResponse(ehRequest, ehRet, payload, size))
880 OIC_LOG(ERROR, TAG, "SendSRMResponse failed in HandlePconfGetRequest");
882 OIC_LOG_V(DEBUG, TAG, "%s RetVal %d", __func__, ehRet);
888 static OCEntityHandlerResult HandlePconfPostRequest (const OCEntityHandlerRequest * ehRequest)
890 OCEntityHandlerResult ehRet = OC_EH_OK;
891 OCStackResult res=OC_STACK_OK;
892 OicSecPconf_t* newPconf = NULL;
894 if (true == GetDoxmResourceData()->dpc)
896 // Convert CBOR PCONF data into binary. This will also validate the PCONF data received.
897 uint8_t *payload = ((OCSecurityPayload *) ehRequest->payload)->securityData;
898 size_t size = ((OCSecurityPayload *) ehRequest->payload)->payloadSize;
901 res = CBORPayloadToPconf(payload, size, &newPconf);
906 OIC_LOG (DEBUG, TAG, "DPC == false : Direct-Pairing Disabled");
910 if (newPconf && res == OC_STACK_OK)
912 // Check if valid Post request
913 if ((true == newPconf->edp) && (0 < newPconf->prmLen) &&
914 DP_PIN_LENGTH == sizeof(newPconf->pin.val))
916 OicSecPrm_t *oldPrm = gPconf->prm;
917 OicSecPdAcl_t *oldPdacl = gPconf->pdacls;
919 // Update local PCONF with new PCONF
921 memcpy(&gPconf->pin, &newPconf->pin, sizeof(OicDpPin_t));
922 gPconf->prm = newPconf->prm;
923 gPconf->prmLen = newPconf->prmLen;
924 gPconf->pdacls = newPconf->pdacls;
925 memcpy(&gPconf->rownerID, &newPconf->rownerID, sizeof(OicUuid_t));
927 // to delete old value(prm, pdacl)
928 newPconf->prm = oldPrm;
929 newPconf->pdacls = oldPdacl;
931 else if (false == newPconf->edp)
941 if(OC_EH_ERROR != ehRet && true == UpdatePersistentStorage(gPconf))
943 ehRet = OC_EH_CHANGED;
946 DeletePconfBinData(newPconf);
953 // Send payload to request originator
954 if (OC_STACK_OK != SendSRMResponse(ehRequest, ehRet, NULL, 0))
957 OIC_LOG(ERROR, TAG, "SendSRMResponse failed in HandlePconfPostRequest");
960 OIC_LOG_V (DEBUG, TAG, "%s RetVal %d", __func__ , ehRet);
965 * This internal method is the entity handler for PCONF resources and
966 * will handle REST request (POST) for them.
968 OCEntityHandlerResult PconfEntityHandler (OCEntityHandlerFlag flag,
969 OCEntityHandlerRequest * ehRequest,
970 void* callbackParameter)
972 OIC_LOG(DEBUG, TAG, "Received request PconfEntityHandler");
973 (void)callbackParameter;
974 OCEntityHandlerResult ehRet = OC_EH_ERROR;
981 if (flag & OC_REQUEST_FLAG)
983 OIC_LOG (DEBUG, TAG, "Flag includes OC_REQUEST_FLAG");
984 switch (ehRequest->method)
987 ehRet = HandlePconfGetRequest(ehRequest);
991 ehRet = HandlePconfPostRequest(ehRequest);
999 SendSRMResponse(ehRequest, ehRet, NULL, 0);
1007 * This internal method is used to create '/oic/sec/pconf' resource.
1009 OCStackResult CreatePconfResource()
1013 ret = OCCreateResource(&gPconfHandle,
1014 OIC_RSRC_TYPE_SEC_PCONF,
1015 OC_RSRVD_INTERFACE_DEFAULT,
1019 OC_SECURE | OC_EXPLICIT_DISCOVERABLE);
1021 if (OC_STACK_OK != ret)
1023 OIC_LOG (ERROR, TAG, "Unable to instantiate PCONF resource");
1024 DeInitPconfResource();
1030 * Get the default value.
1031 * @retval the gDefaultPconf pointer;
1033 static OicSecPconf_t* GetPconfDefault()
1035 OIC_LOG (DEBUG, TAG, "GetPconfDefault");
1037 return &gDefaultPconf;
1041 * This method is used by SRM to retrieve PCONF resource data..
1043 * @retval reference to @ref OicSecPconf_t, binary format of Pconf resource data
1045 const OicSecPconf_t* GetPconfResourceData()
1051 * Initialize PCONF resource by loading data from persistent storage.
1053 * @retval OC_STACK_OK for Success, otherwise some error value
1055 OCStackResult InitPconfResource()
1057 OCStackResult ret = OC_STACK_ERROR;
1059 uint8_t *data = NULL;
1062 ret = GetSecureVirtualDatabaseFromPS(OIC_JSON_PCONF_NAME, &data, &size);
1063 // If database read failed
1064 if (ret != OC_STACK_OK)
1066 OIC_LOG(DEBUG, TAG, "ReadSVDataFromPS failed");
1070 CBORPayloadToPconf(data, size, &gPconf);
1073 if (!data || !gPconf)
1075 gPconf = GetPconfDefault();
1077 // device id from doxm
1078 OicUuid_t deviceId = {.id = {0}};
1079 OCStackResult ret = GetDoxmDeviceID( &deviceId);
1080 VERIFY_SUCCESS(TAG, OC_STACK_OK == ret, ERROR);
1081 memcpy(&gPconf->deviceID, &deviceId, sizeof(OicUuid_t));
1083 VERIFY_NON_NULL(TAG, gPconf, ERROR);
1085 // Instantiate 'oic.sec.pconf'
1086 ret = CreatePconfResource();
1089 if (OC_STACK_OK != ret)
1091 DeInitPconfResource();
1098 * Perform cleanup for PCONF resources.
1101 * OC_STACK_OK - no error
1102 * OC_STACK_ERROR - stack process error
1105 OCStackResult DeInitPconfResource()
1107 OCStackResult ret = OCDeleteResource(gPconfHandle);
1108 if(gPconf!= &gDefaultPconf)
1110 DeletePconfBinData(gPconf);
1114 if(OC_STACK_OK == ret)
1120 return OC_STACK_ERROR;
1125 * This method might be used to add a paired device id after direct-pairing process complete.
1127 * @param pdeviceId ID of the paired device.
1129 * @retval OC_STACK_OK for Success, otherwise some error value
1131 OCStackResult AddPairedDevice(OicUuid_t *pdeviceId)
1133 if (!gPconf || !pdeviceId)
1135 return OC_STACK_INVALID_PARAM;
1139 OicUuid_t *prevList = gPconf->pddevs;
1140 gPconf->pddevs = (OicUuid_t *)OICCalloc(gPconf->pddevLen+1, sizeof(OicUuid_t));
1143 return OC_STACK_NO_MEMORY;
1145 for (size_t i=0; i<gPconf->pddevLen; i++)
1147 memcpy(&gPconf->pddevs[i], &prevList[i], sizeof(OicUuid_t));
1150 // add new paired device id
1151 memcpy(&gPconf->pddevs[gPconf->pddevLen], pdeviceId, sizeof(OicUuid_t));
1155 if(true != UpdatePersistentStorage(gPconf))
1157 OIC_LOG (ERROR, TAG, "Fail to update pconf resource");
1158 return OC_STACK_ERROR;
1161 OIC_LOG (ERROR, TAG, "Add paired device success");
1166 * This method might be used by PolicyEngine to retrieve PDACL for a Subject.
1168 * @param subjectId ID of the subject for which PDACL is required.
1169 * @param savePtr is used internally by @ref GetACLResourceData to maintain index between
1170 * successive calls for same subjectId.
1172 * @retval reference to @ref OicSecPdAcl_t if PDACL is found, else NULL
1174 const OicSecPdAcl_t* GetPdAclData(const OicUuid_t* subjectId, OicSecPdAcl_t **savePtr)
1176 OicSecPdAcl_t *pdacl = NULL;
1178 if ( NULL == subjectId)
1184 * savePtr MUST point to NULL if this is the 'first' call to retrieve PDACL for
1187 if (NULL == *savePtr)
1189 pdacl = gPconf->pdacls;
1191 // Find if 'subjectID' is in paired device list.
1192 for(size_t i=0; i<gPconf->pddevLen; i++)
1194 if (memcmp(&(gPconf->pddevs[i]), subjectId, sizeof(OicUuid_t)) == 0)
1203 OicSecPdAcl_t *temp = NULL;
1206 * If this is a 'successive' call, search for location pointed by
1207 * savePtr and assign 'begin' to the next PDACL after it in the linked
1208 * list and start searching from there.
1210 LL_FOREACH(gPconf->pdacls, temp)
1212 if (temp == *savePtr)
1221 // Cleanup in case no PDACL is found
1227 * This method return whether device is paired or not.
1229 * @param pdeviceId Target device ID to find in paired list.
1230 * @retval ture if device is already paired, else false
1232 bool IsPairedDevice(const OicUuid_t* pdeviceId)
1234 // Find if 'pdeviceId' is in paired device list.
1235 for(size_t i=0; i<gPconf->pddevLen; i++)
1237 if (memcmp(&(gPconf->pddevs[i]), pdeviceId, sizeof(OicUuid_t)) == 0)
1245 OCStackResult SetPconfRownerId(const OicUuid_t* newROwner)
1247 OCStackResult ret = OC_STACK_ERROR;
1248 uint8_t *cborPayload = NULL;
1250 OicUuid_t prevId = {.id={0}};
1252 if(NULL == newROwner)
1254 ret = OC_STACK_INVALID_PARAM;
1258 ret = OC_STACK_NO_RESOURCE;
1261 if(newROwner && gPconf)
1263 memcpy(prevId.id, gPconf->rownerID.id, sizeof(prevId.id));
1264 memcpy(gPconf->rownerID.id, newROwner->id, sizeof(newROwner->id));
1266 ret = PconfToCBORPayload(gPconf, &cborPayload, &size);
1267 VERIFY_SUCCESS(TAG, OC_STACK_OK == ret, ERROR);
1269 ret = UpdateSecureResourceInPS(OIC_JSON_PCONF_NAME, cborPayload, size);
1270 VERIFY_SUCCESS(TAG, OC_STACK_OK == ret, ERROR);
1272 OICFree(cborPayload);
1278 OICFree(cborPayload);
1279 memcpy(gPconf->rownerID.id, prevId.id, sizeof(prevId.id));
1283 OCStackResult GetPconfRownerId(OicUuid_t *rowneruuid)
1285 OCStackResult retVal = OC_STACK_ERROR;
1288 *rowneruuid = gPconf->rownerID;
1289 retVal = OC_STACK_OK;