ab89e3ce2da3962019235d794f07b55c41a2f979
[platform/upstream/iotivity.git] / resource / csdk / security / src / pconfresource.c
1 /* *****************************************************************
2  *
3  * Copyright 2016 Samsung Electronics All Rights Reserved.
4  *
5  *
6  *
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
10  *
11  *     http://www.apache.org/licenses/LICENSE-2.0
12  *
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.
18  *
19  * *****************************************************************/
20
21 #include "iotivity_config.h"
22 #include <stdlib.h>
23 #include <string.h>
24 #include "ocstack.h"
25 #include "logger.h"
26 #include "oic_malloc.h"
27 #include "oic_string.h"
28 #include "cJSON.h"
29 #include "base64.h"
30 #include "ocpayload.h"
31 #include "ocpayloadcbor.h"
32 #include "payload_logging.h"
33 #include "resourcemanager.h"
34 #include "pconfresource.h"
35 #include "psinterface.h"
36 #include "utlist.h"
37 #include "srmresourcestrings.h"
38 #include "doxmresource.h"
39 #include "srmutility.h"
40 #include "ocserverrequest.h"
41 #include "psinterface.h"
42 #include "security_internals.h"
43 #ifdef HAVE_STRINGS_H
44 #include <strings.h>
45 #endif
46
47 #define TAG  "OIC_SRM_PCONF"
48
49 static const uint16_t CBOR_SIZE = 1024;
50 static const uint64_t CBOR_MAX_SIZE = 4400;
51 static const uint8_t  PCONF_MAP_SIZE = 4;
52 static const uint8_t  PCONF_RESOURCE_MAP_SIZE = 4;
53
54 static OicSecPconf_t          *gPconf = NULL;
55 static OCResourceHandle   gPconfHandle = NULL;
56 static OicSecPconf_t         gDefaultPconf =
57 {
58     false,                  /* bool edp */
59     NULL,                  /* OicSecPrm *prm */
60     0,                       /* size_t prmLen */
61     {.val = {0}},       /* OicDpPin_t pin */
62     NULL,                  /* OicSecPdAcl_t *pdacls */
63     NULL,                  /* OicUuid_t *pddevs */
64     0,                       /* size_t pddevLen */
65     {.id = {0}},        /* OicUuid_t deviceID */
66     {.id = {0}},        /* OicUuid_t rowner */
67 };
68
69 /**
70  * This function frees OicSecPdAcl_t object's fields and object itself.
71  */
72 void FreePdAclList(OicSecPdAcl_t* pdacls)
73 {
74     if (pdacls)
75     {
76         size_t i = 0;
77
78         //Clean pdacl objecs
79         OicSecPdAcl_t *aclTmp1 = NULL;
80         OicSecPdAcl_t *aclTmp2 = NULL;
81         LL_FOREACH_SAFE(pdacls, aclTmp1, aclTmp2)
82         {
83             LL_DELETE(pdacls, aclTmp1);
84
85             // Clean Resources
86             for (i = 0; i < aclTmp1->resourcesLen; i++)
87             {
88                 OICFree(aclTmp1->resources[i]);
89             }
90             OICFree(aclTmp1->resources);
91
92             //Clean Period
93             if(aclTmp1->periods)
94             {
95                 for(i = 0; i < aclTmp1->prdRecrLen; i++)
96                 {
97                     OICFree(aclTmp1->periods[i]);
98                 }
99                 OICFree(aclTmp1->periods);
100             }
101
102             //Clean Recurrence
103             if(aclTmp1->recurrences)
104             {
105                 for(i = 0; i < aclTmp1->prdRecrLen; i++)
106                 {
107                     OICFree(aclTmp1->recurrences[i]);
108                 }
109                 OICFree(aclTmp1->recurrences);
110             }
111         }
112
113         //Clean pconf itself
114         OICFree(pdacls);
115     }
116 }
117
118 void DeletePconfBinData(OicSecPconf_t* pconf)
119 {
120     if (pconf)
121     {
122         //Clean prm
123         OICFree(pconf->prm);
124
125         //Clean pdacl
126         if (pconf->pdacls)
127         {
128             FreePdAclList(pconf->pdacls);
129         }
130
131         //Clean pddev
132         OICFree(pconf->pddevs);
133
134         //Clean pconf itself
135         OICFree(pconf);
136     }
137 }
138
139 static size_t OicPdAclSize(const OicSecPdAcl_t *pdAcl)
140 {
141     if (!pdAcl)
142     {
143         return 0;
144     }
145
146     OicSecPdAcl_t *tmp = (OicSecPdAcl_t *)pdAcl;
147     size_t size = 0;
148     while (tmp)
149     {
150         size++;
151         tmp = tmp->next;
152     }
153     return size;
154 }
155
156 OCStackResult PconfToCBORPayload(const OicSecPconf_t *pconf,uint8_t **payload,size_t *size)
157 {
158     if (NULL == pconf || NULL == payload || NULL != *payload || NULL == size)
159     {
160         return OC_STACK_INVALID_PARAM;
161     }
162     size_t cborLen = *size;
163     if(0 == cborLen)
164     {
165         cborLen = CBOR_SIZE;
166     }
167     *payload = NULL;
168
169     OCStackResult ret = OC_STACK_ERROR;
170     CborEncoder encoder;
171     CborEncoder pconfMap;
172
173     int64_t cborEncoderResult = CborNoError;
174     uint8_t mapSize = PCONF_MAP_SIZE;
175
176     if (pconf->prmLen > 0)
177     {
178         mapSize++;
179     }
180     if (pconf->pdacls)
181     {
182         mapSize++;
183     }
184     if (pconf->pddevs)
185     {
186         mapSize++;
187     }
188
189     uint8_t *outPayload = (uint8_t *)OICCalloc(1, cborLen);
190     VERIFY_NON_NULL(TAG, outPayload, ERROR);
191
192     cbor_encoder_init(&encoder, outPayload, cborLen, 0);
193     cborEncoderResult = cbor_encoder_create_map(&encoder, &pconfMap, mapSize);
194     VERIFY_CBOR_SUCCESS(TAG, cborEncoderResult, "Failed Creating Pconf Map.");
195
196     //edp  -- Mandatory
197     cborEncoderResult = cbor_encode_text_string(&pconfMap, OIC_JSON_EDP_NAME,
198             strlen(OIC_JSON_EDP_NAME));
199     VERIFY_CBOR_SUCCESS(TAG, cborEncoderResult, "Failed Encode EDP String.");
200     cborEncoderResult = cbor_encode_boolean(&pconfMap, pconf->edp);
201     VERIFY_CBOR_SUCCESS(TAG, cborEncoderResult, "Failed Convert PconfEDP value");
202
203     //PRM type -- Not Mandatory
204     if(pconf->prmLen > 0)
205     {
206         CborEncoder prm;
207         cborEncoderResult = cbor_encode_text_string(&pconfMap, OIC_JSON_PRM_NAME,
208                 strlen(OIC_JSON_PRM_NAME));
209         VERIFY_CBOR_SUCCESS(TAG, cborEncoderResult, "Failed Convert Pconf PRM NAME");
210         cborEncoderResult = cbor_encoder_create_array(&pconfMap, &prm, pconf->prmLen);
211         VERIFY_CBOR_SUCCESS(TAG, cborEncoderResult, "Failed Convert Pconf PRM value");
212
213         for (size_t i = 0; i < pconf->prmLen; i++)
214         {
215             cborEncoderResult = cbor_encode_int(&prm, pconf->prm[i]);
216             VERIFY_CBOR_SUCCESS(TAG, cborEncoderResult, "Failed Convert Pconf PRM Array");
217         }
218         cborEncoderResult = cbor_encoder_close_container(&pconfMap, &prm);
219         VERIFY_CBOR_SUCCESS(TAG, cborEncoderResult, "Failed to close encode array");
220     }
221
222     //PIN -- Mandatory
223     cborEncoderResult = cbor_encode_text_string(&pconfMap, OIC_JSON_PIN_NAME,
224             strlen(OIC_JSON_PIN_NAME));
225     VERIFY_CBOR_SUCCESS(TAG, cborEncoderResult, "Failed to create OIC_JSON_PIN_NAME");
226     cborEncoderResult = cbor_encode_byte_string(&pconfMap, pconf->pin.val, sizeof(pconf->pin.val));
227     VERIFY_CBOR_SUCCESS(TAG, cborEncoderResult, "Failed to convert pin value");
228
229     //PDACL -- Mandatory
230     if (pconf->pdacls)
231     {
232         OicSecPdAcl_t *pdacl = pconf->pdacls;
233         CborEncoder pdAclArray;
234         cborEncoderResult = cbor_encode_text_string(&pconfMap, OIC_JSON_PDACL_NAME,
235                 strlen(OIC_JSON_PDACL_NAME));
236         VERIFY_CBOR_SUCCESS(TAG, cborEncoderResult, "Failed to create OIC_JSON_PDACL_NAME");
237         cborEncoderResult = cbor_encoder_create_array(&pconfMap, &pdAclArray,
238                 OicPdAclSize(pconf->pdacls));
239         VERIFY_CBOR_SUCCESS(TAG, cborEncoderResult, "Failed to creeate _pdacl array");
240
241         while(pdacl)
242         {
243             CborEncoder pdAclMap;
244             // PDACL Map size - Number of mandatory items
245             uint8_t aclMapSize = 2;
246
247             if (pdacl->prdRecrLen)
248             {
249                 ++aclMapSize;
250             }
251             if (pdacl->recurrences)
252             {
253                 ++aclMapSize;
254             }
255
256             cborEncoderResult = cbor_encoder_create_map(&pdAclArray, &pdAclMap, aclMapSize);
257             VERIFY_CBOR_SUCCESS(TAG, cborEncoderResult,  "Failed to creeate _pdacl array");
258
259             // Resources -- Mandatory
260             cborEncoderResult = cbor_encode_text_string(&pdAclMap, OIC_JSON_RESOURCES_NAME,
261                     strlen(OIC_JSON_RESOURCES_NAME));
262             VERIFY_CBOR_SUCCESS(TAG, cborEncoderResult,  "Failed to encode resource result");
263
264             CborEncoder resources;
265             cborEncoderResult = cbor_encoder_create_array(&pdAclMap, &resources,
266                     pdacl->resourcesLen);
267             VERIFY_CBOR_SUCCESS(TAG, cborEncoderResult,  "Failed to create resource array");
268
269             for (size_t i = 0; i < pdacl->resourcesLen; i++)
270             {
271                 CborEncoder rMap;
272                 cborEncoderResult = cbor_encoder_create_map(&resources, &rMap,
273                         PCONF_RESOURCE_MAP_SIZE);
274                 VERIFY_CBOR_SUCCESS(TAG, cborEncoderResult, "Failed Addding Resource Map.");
275
276                 cborEncoderResult = cbor_encode_text_string(&rMap, OIC_JSON_HREF_NAME,
277                         strlen(OIC_JSON_HREF_NAME));
278                 VERIFY_CBOR_SUCCESS(TAG, cborEncoderResult, "Failed Addding HREF Name Tag.");
279                 cborEncoderResult = cbor_encode_text_string(&rMap, pdacl->resources[i],
280                         strlen(pdacl->resources[i]));
281                 VERIFY_CBOR_SUCCESS(TAG, cborEncoderResult, "Failed Addding HREF Value in Map.");
282
283                 cborEncoderResult = cbor_encode_text_string(&rMap, OIC_JSON_REL_NAME,
284                         strlen(OIC_JSON_REL_NAME));
285                 VERIFY_CBOR_SUCCESS(TAG, cborEncoderResult, "Failed Addding REL Name Tag.");
286
287                 // TODO : Need to assign real value of REL
288                 cborEncoderResult = cbor_encode_text_string(&rMap, OIC_JSON_EMPTY_STRING,
289                         strlen(OIC_JSON_EMPTY_STRING));
290                 VERIFY_CBOR_SUCCESS(TAG, cborEncoderResult, "Failed Addding REL Value.");
291
292                 cborEncoderResult = cbor_encode_text_string(&rMap, OIC_JSON_RT_NAME,
293                         strlen(OIC_JSON_RT_NAME));
294                 VERIFY_CBOR_SUCCESS(TAG, cborEncoderResult, "Failed Addding RT Name Tag.");
295
296                 // TODO : Need to assign real value of RT
297                 cborEncoderResult = cbor_encode_text_string(&rMap, OIC_JSON_EMPTY_STRING,
298                         strlen(OIC_JSON_EMPTY_STRING));
299                 VERIFY_CBOR_SUCCESS(TAG, cborEncoderResult, "Failed Addding RT Value.");
300
301                 cborEncoderResult = cbor_encode_text_string(&rMap, OIC_JSON_IF_NAME,
302                         strlen(OIC_JSON_IF_NAME));
303                 VERIFY_CBOR_SUCCESS(TAG, cborEncoderResult, "Failed Addding IF Name Tag.");
304
305                 // TODO : Need to assign real value of IF
306                 cborEncoderResult = cbor_encode_text_string(&rMap, OIC_JSON_EMPTY_STRING,
307                         strlen(OIC_JSON_EMPTY_STRING));
308                 VERIFY_CBOR_SUCCESS(TAG, cborEncoderResult, "Failed Addding IF Value.");
309
310                 cborEncoderResult = cbor_encoder_close_container(&resources, &rMap);
311                 VERIFY_CBOR_SUCCESS(TAG, cborEncoderResult, "Failed Closing Resource Map.");
312             }
313
314             cborEncoderResult = cbor_encoder_close_container(&pdAclMap, &resources);
315             VERIFY_CBOR_SUCCESS(TAG, cborEncoderResult,  "Failed to close resource array");
316
317             // Permissions -- Mandatory
318             cborEncoderResult = cbor_encode_text_string(&pdAclMap, OIC_JSON_PERMISSION_NAME,
319                     strlen(OIC_JSON_PERMISSION_NAME));
320             VERIFY_CBOR_SUCCESS(TAG, cborEncoderResult,  "Failed to create permition string");
321             cborEncoderResult = cbor_encode_int(&pdAclMap, pdacl->permission);
322             VERIFY_CBOR_SUCCESS(TAG, cborEncoderResult, "Failed to encode permition calue");
323
324             // Period -- Not Mandatory
325             if (pdacl->periods)
326             {
327                 CborEncoder period;
328                 cborEncoderResult = cbor_encode_text_string(&pdAclMap, OIC_JSON_PERIODS_NAME,
329                         strlen(OIC_JSON_PERIODS_NAME));
330                 VERIFY_CBOR_SUCCESS(TAG, cborEncoderResult, "Failed to encode period value");
331                 cborEncoderResult = cbor_encoder_create_array(&pdAclMap, &period,
332                         pdacl->prdRecrLen);
333                 VERIFY_CBOR_SUCCESS(TAG, cborEncoderResult, "Failed to create array");
334
335                 for (size_t i = 0; i < pdacl->prdRecrLen; i++)
336                 {
337                     cborEncoderResult = cbor_encode_text_string(&period, pdacl->periods[i],
338                             strlen(pdacl->periods[i]));
339                     VERIFY_CBOR_SUCCESS(TAG, cborEncoderResult, "Failed to encode period");
340                 }
341                 cborEncoderResult = cbor_encoder_close_container(&pdAclMap, &period);
342                 VERIFY_CBOR_SUCCESS(TAG, cborEncoderResult,"Failed to close period array");
343             }
344
345             // Period -- Not Mandatory
346             if(0 != pdacl->prdRecrLen && pdacl->recurrences)
347             {
348                 CborEncoder recurrences;
349                 cborEncoderResult = cbor_encode_text_string(&pdAclMap, OIC_JSON_RECURRENCES_NAME,
350                         strlen(OIC_JSON_RECURRENCES_NAME));
351                 VERIFY_CBOR_SUCCESS(TAG, cborEncoderResult,"Failed to encode recurrences");
352                 cborEncoderResult = cbor_encoder_create_array(&pdAclMap, &recurrences,
353                         pdacl->prdRecrLen);
354                 VERIFY_CBOR_SUCCESS(TAG, cborEncoderResult, "Failed to create rec array");
355
356                 for (size_t i = 0; i < pdacl->prdRecrLen; i++)
357                 {
358                     cborEncoderResult = cbor_encode_text_string(&recurrences,
359                             pdacl->recurrences[i], strlen(pdacl->recurrences[i]));
360                     VERIFY_CBOR_SUCCESS(TAG, cborEncoderResult, "Failed to encode recurrences");
361                 }
362                 cborEncoderResult = cbor_encoder_close_container(&pdAclMap, &recurrences);
363                 VERIFY_CBOR_SUCCESS(TAG, cborEncoderResult, "Failed to close rec array");
364             }
365             cborEncoderResult = cbor_encoder_close_container(&pdAclArray, &pdAclMap);
366             VERIFY_CBOR_SUCCESS(TAG, cborEncoderResult, "Failed to close acl map");
367
368             pdacl = pdacl->next;
369         }
370         //clsoe the array
371         cborEncoderResult = cbor_encoder_close_container(&pconfMap, &pdAclArray);
372         VERIFY_CBOR_SUCCESS(TAG, cborEncoderResult, "Failed to close acl array");
373     }
374
375     //PDDev -- Mandatory
376     //There may not be paired devices if it did not pairing before
377     if (pconf->pddevs && 0 < pconf->pddevLen)
378     {
379         CborEncoder pddev;
380         cborEncoderResult = cbor_encode_text_string(&pconfMap, OIC_JSON_PDDEV_LIST_NAME,
381                 strlen(OIC_JSON_PDDEV_LIST_NAME));
382         VERIFY_CBOR_SUCCESS(TAG, cborEncoderResult, "Failed to encode pddev");
383         cborEncoderResult = cbor_encoder_create_array(&pconfMap, &pddev,  pconf->pddevLen);
384         VERIFY_CBOR_SUCCESS(TAG, cborEncoderResult, "Failed to create array");
385
386         for (size_t i = 0; i < pconf->pddevLen; i++)
387         {
388             char *pddevId = NULL;
389             ret = ConvertUuidToStr(&pconf->pddevs[i], &pddevId);
390             VERIFY_SUCCESS(TAG, ret == OC_STACK_OK, ERROR);
391             cborEncoderResult = cbor_encode_text_string(&pddev, pddevId, strlen(pddevId));
392             VERIFY_CBOR_SUCCESS(TAG, cborEncoderResult, "Failed Addding pddev Id Value.");
393             OICFree(pddevId);
394         }
395         cborEncoderResult = cbor_encoder_close_container(&pconfMap, &pddev);
396         VERIFY_CBOR_SUCCESS(TAG, cborEncoderResult, "Failed to close pddev array");
397     }
398
399     //DeviceId -- Mandatory
400     //There may not be devicd id if caller is provisoning tool
401     cborEncoderResult = cbor_encode_text_string(&pconfMap, OIC_JSON_DEVICE_ID_NAME,
402             strlen(OIC_JSON_DEVICE_ID_NAME));
403     VERIFY_CBOR_SUCCESS(TAG, cborEncoderResult, "Failed to encode device id");
404     {
405         char *deviceId = NULL;
406         ret = ConvertUuidToStr(&pconf->deviceID, &deviceId);
407         VERIFY_SUCCESS(TAG, ret == OC_STACK_OK, ERROR);
408         cborEncoderResult = cbor_encode_text_string(&pconfMap, deviceId, strlen(deviceId));
409         VERIFY_CBOR_SUCCESS(TAG, cborEncoderResult, "Failed to encode deviceID value");
410         OICFree(deviceId);
411     }
412
413     //ROwner -- Mandatory
414     {
415         char *rowner = NULL;
416         cborEncoderResult = cbor_encode_text_string(&pconfMap, OIC_JSON_ROWNERID_NAME,
417                 strlen(OIC_JSON_ROWNERID_NAME));
418         VERIFY_CBOR_SUCCESS(TAG, cborEncoderResult, "Failed to encode rowner string");
419         ret = ConvertUuidToStr(&pconf->rownerID, &rowner);
420         VERIFY_SUCCESS(TAG, ret == OC_STACK_OK, ERROR);
421         cborEncoderResult = cbor_encode_text_string(&pconfMap, rowner, strlen(rowner));
422         VERIFY_CBOR_SUCCESS(TAG, cborEncoderResult, "Failed to encode rwoner value");
423         OICFree(rowner);
424     }
425
426     cborEncoderResult = cbor_encoder_close_container(&encoder, &pconfMap);
427     VERIFY_CBOR_SUCCESS(TAG, cborEncoderResult, "Failed to close pconfMap");
428
429     *size = cbor_encoder_get_buffer_size(&encoder, outPayload);
430     *payload = outPayload;
431     ret = OC_STACK_OK;
432 exit:
433     if ((CborErrorOutOfMemory == cborEncoderResult) && (cborLen < CBOR_MAX_SIZE))
434     {
435         // reallocate and try again!
436         OICFree(outPayload);
437         // Since the allocated initial memory failed, double the memory.
438         cborLen += cbor_encoder_get_buffer_size(&encoder, encoder.end);
439         cborEncoderResult = CborNoError;
440         ret = PconfToCBORPayload(pconf, payload, &cborLen);
441         *size = cborLen;
442     }
443     if ((CborNoError != cborEncoderResult) || (OC_STACK_OK != ret))
444     {
445         OICFree(outPayload);
446         outPayload = NULL;
447         *payload = NULL;
448         *size = 0;
449         ret = OC_STACK_ERROR;
450     }
451     return ret;
452 }
453
454 OCStackResult CBORPayloadToPconf(const uint8_t *cborPayload, size_t size, OicSecPconf_t **secPconf)
455 {
456     if (NULL == cborPayload || NULL == secPconf || NULL != *secPconf || 0 == size)
457     {
458         return OC_STACK_INVALID_PARAM;
459     }
460     OCStackResult ret = OC_STACK_ERROR;
461     *secPconf = NULL;
462     CborValue pconfCbor = { .parser = NULL };
463     CborParser parser = { .end = NULL };
464     CborError cborFindResult = CborNoError;
465
466     cbor_parser_init(cborPayload, size, 0, &parser, &pconfCbor);
467     CborValue pconfMap = { .parser = NULL } ;
468     OicSecPconf_t *pconf = NULL;
469     cborFindResult = cbor_value_enter_container(&pconfCbor, &pconfMap);
470     VERIFY_CBOR_SUCCESS(TAG, cborFindResult, "Failed to enter map");
471     pconf = (OicSecPconf_t *)OICCalloc(1, sizeof(*pconf));
472     VERIFY_NON_NULL(TAG, pconf, ERROR);
473     while (cbor_value_is_valid(&pconfMap))
474     {
475         char *name = NULL;
476         size_t len = 0;
477         CborType type = cbor_value_get_type(&pconfMap);
478         if (type == CborTextStringType && cbor_value_is_text_string(&pconfMap))
479         {
480             cborFindResult = cbor_value_dup_text_string(&pconfMap, &name, &len, NULL);
481             VERIFY_CBOR_SUCCESS(TAG, cborFindResult, "Failed to get value");
482             cborFindResult = cbor_value_advance(&pconfMap);
483             VERIFY_CBOR_SUCCESS(TAG, cborFindResult, "Failed to advance value");
484         }
485
486         if (name)
487         {
488             //EDP -- Mandatory
489             if(0 == strcmp(OIC_JSON_EDP_NAME, name) && cbor_value_is_boolean(&pconfMap))
490             {
491                 cborFindResult = cbor_value_get_boolean(&pconfMap, &pconf->edp);
492                 VERIFY_CBOR_SUCCESS(TAG, cborFindResult, "Failed to get value");
493             }
494             if (0 == strcmp(OIC_JSON_PRM_NAME, name))
495             {
496                 int i = 0;
497                 CborValue prm = { .parser = NULL };
498                 cborFindResult = cbor_value_get_array_length(&pconfMap, &pconf->prmLen);
499                 VERIFY_CBOR_SUCCESS(TAG, cborFindResult, "Failed to get length");
500                 VERIFY_SUCCESS(TAG, pconf->prmLen != 0, ERROR);
501
502                 pconf->prm = (OicSecPrm_t *)OICCalloc(pconf->prmLen, sizeof(OicSecPrm_t));
503                 VERIFY_NON_NULL(TAG, pconf->prm, ERROR);
504                 cborFindResult = cbor_value_enter_container(&pconfMap, &prm);
505                 VERIFY_CBOR_SUCCESS(TAG, cborFindResult, "Failed to eneter array");
506
507                 while (cbor_value_is_valid(&prm) && cbor_value_is_integer(&prm))
508                 {
509                     int prm_val;
510
511                     cborFindResult = cbor_value_get_int(&prm, &prm_val);
512                     VERIFY_CBOR_SUCCESS(TAG, cborFindResult, "Failed to get value");
513                     pconf->prm[i++] = (OicSecPrm_t)prm_val;
514                     cborFindResult = cbor_value_advance(&prm);
515                     VERIFY_CBOR_SUCCESS(TAG, cborFindResult, "Failed to advance value");
516                 }
517             }
518             //PIN -- Mandatory
519             if (0 == strcmp(OIC_JSON_PIN_NAME, name) && cbor_value_is_byte_string(&pconfMap))
520             {
521                 uint8_t *pin = NULL;
522                 cborFindResult = cbor_value_dup_byte_string(&pconfMap, &pin, &len, NULL);
523                 VERIFY_CBOR_SUCCESS(TAG, cborFindResult, "Failed to get value");
524                 memcpy(pconf->pin.val, pin, len);
525                 OICFree(pin);
526             }
527
528             //PDACL -- Mandatory
529             if (0 == strcmp(OIC_JSON_PDACL_NAME, name))
530             {
531                 CborValue pdAclArray = { .parser = NULL};
532                 OicSecPdAcl_t *headPdacl = NULL;
533
534                 cborFindResult = cbor_value_enter_container(&pconfMap, &pdAclArray);
535                 VERIFY_CBOR_SUCCESS(TAG, cborFindResult, "Failed to enter");
536
537                 while (cbor_value_is_valid(&pdAclArray))
538                 {
539                     CborValue pdAclMap = { .parser = NULL};
540                     OicSecPdAcl_t *pdacl = (OicSecPdAcl_t *) OICCalloc(1, sizeof(OicSecPdAcl_t));
541                     VERIFY_NON_NULL(TAG, pdacl, ERROR);
542
543                     cborFindResult = cbor_value_enter_container(&pdAclArray, &pdAclMap);
544                     VERIFY_CBOR_SUCCESS(TAG, cborFindResult, "Failed to enter");
545
546                     while (cbor_value_is_valid(&pdAclMap))
547                     {
548                         char* name = NULL;
549                         size_t len = 0;
550                         CborType type = cbor_value_get_type(&pdAclMap);
551                         if (type == CborTextStringType && cbor_value_is_text_string(&pdAclMap))
552                         {
553                             cborFindResult = cbor_value_dup_text_string(&pdAclMap, &name,
554                                     &len, NULL);
555                             VERIFY_CBOR_SUCCESS(TAG, cborFindResult, "Failed to get text");
556                             cborFindResult = cbor_value_advance(&pdAclMap);
557                             VERIFY_CBOR_SUCCESS(TAG, cborFindResult, "Failed to advance value");
558                         }
559                         if (name)
560                         {
561                             // Resources -- Mandatory
562                             if (strcmp(name, OIC_JSON_RESOURCES_NAME) == 0 && cbor_value_is_array(&pdAclMap))
563                             {
564                                 int i = 0;
565                                 CborValue resources = { .parser = NULL };
566                                 cborFindResult = cbor_value_get_array_length(&pdAclMap,
567                                         &pdacl->resourcesLen);
568                                 VERIFY_CBOR_SUCCESS(TAG, cborFindResult, "Failed to get length");
569                                 cborFindResult = cbor_value_enter_container(&pdAclMap, &resources);
570                                 VERIFY_CBOR_SUCCESS(TAG, cborFindResult, "Failed to enter");
571                                 pdacl->resources = (char **) OICCalloc(pdacl->resourcesLen,
572                                         sizeof(char*));
573                                 VERIFY_NON_NULL(TAG, pdacl->resources, ERROR);
574
575                                 while (cbor_value_is_valid(&resources))
576                                 {
577                                     CborValue rMap = { .parser = NULL  };
578                                     cborFindResult = cbor_value_enter_container(&resources, &rMap);
579                                     VERIFY_CBOR_SUCCESS(TAG, cborFindResult, "Failed Entering Resource Map");
580
581                                     while(cbor_value_is_valid(&rMap) && cbor_value_is_text_string(&rMap))
582                                     {
583                                         char *rMapName = NULL;
584                                         size_t rMapNameLen = 0;
585                                         cborFindResult = cbor_value_dup_text_string(&rMap, &rMapName, &rMapNameLen, NULL);
586                                         VERIFY_CBOR_SUCCESS(TAG, cborFindResult, "Failed Finding RMap Data Name Tag.");
587                                         cborFindResult = cbor_value_advance(&rMap);
588                                         VERIFY_CBOR_SUCCESS(TAG, cborFindResult, "Failed Finding RMap Data Value.");
589
590                                         // "href"
591                                         if (0 == strcmp(OIC_JSON_HREF_NAME, rMapName))
592                                         {
593                                             // TODO : Need to check data structure of OicSecPdAcl_t based on RAML spec.
594                                             cborFindResult = cbor_value_dup_text_string(&rMap, &pdacl->resources[i++], &len, NULL);
595                                             VERIFY_CBOR_SUCCESS(TAG, cborFindResult, "Failed Finding Href Value.");
596                                         }
597
598                                         // "rel"
599                                         if (0 == strcmp(OIC_JSON_REL_NAME, rMapName))
600                                         {
601                                             // TODO : Need to check data structure of OicSecPdAcl_t and assign based on RAML spec.
602                                             char *relData = NULL;
603                                             cborFindResult = cbor_value_dup_text_string(&rMap, &relData, &len, NULL);
604                                             VERIFY_CBOR_SUCCESS(TAG, cborFindResult, "Failed Finding REL Value.");
605                                             OICFree(relData);
606                                         }
607
608                                         // "rt"
609                                         if (0 == strcmp(OIC_JSON_RT_NAME, rMapName))
610                                         {
611                                             // TODO : Need to check data structure of OicSecPdAcl_t and assign based on RAML spec.
612                                             char *rtData = NULL;
613                                             cborFindResult = cbor_value_dup_text_string(&rMap, &rtData, &len, NULL);
614                                             VERIFY_CBOR_SUCCESS(TAG, cborFindResult, "Failed Finding RT Value.");
615                                             OICFree(rtData);
616                                         }
617
618                                         // "if"
619                                         if (0 == strcmp(OIC_JSON_IF_NAME, rMapName))
620                                         {
621                                             // TODO : Need to check data structure of OicSecPdAcl_t and assign based on RAML spec.
622                                             char *ifData = NULL;
623                                             cborFindResult = cbor_value_dup_text_string(&rMap, &ifData, &len, NULL);
624                                             VERIFY_CBOR_SUCCESS(TAG, cborFindResult, "Failed Finding IF Value.");
625                                             OICFree(ifData);
626                                         }
627
628                                         if (cbor_value_is_valid(&rMap))
629                                         {
630                                             cborFindResult = cbor_value_advance(&rMap);
631                                             VERIFY_CBOR_SUCCESS(TAG, cborFindResult, "Failed Advancing Rlist Map.");
632                                         }
633                                         OICFree(rMapName);
634                                     }
635
636                                     if (cbor_value_is_valid(&resources))
637                                     {
638                                         cborFindResult = cbor_value_advance(&resources);
639                                         VERIFY_CBOR_SUCCESS(TAG, cborFindResult, "Failed to advance");
640                                     }
641                                 }
642                             }
643
644                             // Permissions -- Mandatory
645                             if (strcmp(name, OIC_JSON_PERMISSION_NAME) == 0 && cbor_value_is_unsigned_integer(&pdAclMap))
646                             {
647                                 uint64_t permission = 0;
648                                 cborFindResult = cbor_value_get_uint64(&pdAclMap, &permission);
649                                 pdacl->permission = (uint16_t)permission;
650                                 VERIFY_CBOR_SUCCESS(TAG, cborFindResult, "Failed to get value");
651                             }
652
653                             // Period -- Not mandatory
654                             if (strcmp(name, OIC_JSON_PERIODS_NAME) == 0 && cbor_value_is_array(&pdAclMap))
655                             {
656                                 int i = 0;
657                                 CborValue period = { .parser = NULL };
658                                 cborFindResult = cbor_value_get_array_length(&pdAclMap,
659                                         &pdacl->prdRecrLen);
660                                 VERIFY_CBOR_SUCCESS(TAG, cborFindResult, "Failed to get length");
661                                 cborFindResult = cbor_value_enter_container(&pdAclMap, &period);
662                                 VERIFY_CBOR_SUCCESS(TAG, cborFindResult, "Failed to enter");
663                                 pdacl->periods = (char **) OICCalloc(pdacl->prdRecrLen, sizeof(char*));
664                                 VERIFY_NON_NULL(TAG, pdacl->periods, ERROR);
665
666                                 while (cbor_value_is_text_string(&period) && cbor_value_is_text_string(&period))
667                                 {
668                                     cborFindResult = cbor_value_dup_text_string(&period,
669                                             &pdacl->periods[i++], &len, NULL);
670                                     VERIFY_CBOR_SUCCESS(TAG, cborFindResult, "Failed to get text");
671                                     cborFindResult = cbor_value_advance(&period);
672                                     VERIFY_CBOR_SUCCESS(TAG, cborFindResult, "Failed to advance");
673                                     pdacl->prdRecrLen++;
674                                 }
675                             }
676
677                             // Recurrence -- Not mandatory
678                             if (strcmp(name, OIC_JSON_RECURRENCES_NAME) == 0 && cbor_value_is_array(&pdAclMap))
679                             {
680                                 int i = 0;
681                                 CborValue recurrences = { .parser = NULL };
682                                 cborFindResult = cbor_value_get_array_length(&pdAclMap, &pdacl->prdRecrLen);
683                                 VERIFY_CBOR_SUCCESS(TAG, cborFindResult, "Failed to get length");
684                                 cborFindResult = cbor_value_enter_container(&pdAclMap, &recurrences);
685                                 VERIFY_CBOR_SUCCESS(TAG, cborFindResult, "Failed to enter");
686                                 pdacl->recurrences = (char **) OICCalloc(pdacl->prdRecrLen, sizeof(char*));
687                                 VERIFY_NON_NULL(TAG, pdacl->recurrences, ERROR);
688
689                                 while (cbor_value_is_text_string(&recurrences) && cbor_value_is_text_string(&recurrences))
690                                 {
691                                     cborFindResult = cbor_value_dup_text_string(&recurrences,
692                                             &pdacl->recurrences[i++], &len, NULL);
693                                     VERIFY_CBOR_SUCCESS(TAG, cborFindResult, "Failed to get value");
694                                     cborFindResult = cbor_value_advance(&recurrences);
695                                     VERIFY_CBOR_SUCCESS(TAG, cborFindResult, "Failed to advance");
696                                 }
697                             }
698                             if (type != CborMapType && cbor_value_is_valid(&pdAclMap))
699                             {
700                                 cborFindResult = cbor_value_advance(&pdAclMap);
701                                 VERIFY_CBOR_SUCCESS(TAG, cborFindResult, "Failed to advance");
702                             }
703                         }
704                         if (cbor_value_is_valid(&pdAclArray))
705                         {
706                             cborFindResult = cbor_value_advance(&pdAclArray);
707                             VERIFY_CBOR_SUCCESS(TAG, cborFindResult, "Failed to advance");
708                         }
709                         OICFree(name);
710                         name = NULL;
711                     }
712                     pdacl->next = NULL;
713                     if (headPdacl == NULL)
714                     {
715                         headPdacl = pdacl;
716                     }
717                     else
718                     {
719                         OicSecPdAcl_t *temp = headPdacl;
720                         while (temp->next)
721                         {
722                             temp = temp->next;
723                         }
724                         temp->next = pdacl;
725                     }
726                 }
727                 pconf->pdacls = headPdacl;
728             }
729
730             //PDDev -- Mandatory
731             if (strcmp(name, OIC_JSON_PDDEV_LIST_NAME) == 0 && cbor_value_is_array(&pconfMap))
732             {
733                 int i = 0;
734                 CborValue pddevs = { .parser = NULL };
735                 cborFindResult = cbor_value_get_array_length(&pconfMap, &pconf->pddevLen);
736                 VERIFY_CBOR_SUCCESS(TAG, cborFindResult, "Failed to get length");
737                 cborFindResult = cbor_value_enter_container(&pconfMap, &pddevs);
738                 VERIFY_CBOR_SUCCESS(TAG, cborFindResult, "Failed to enter");
739
740                 pconf->pddevs = (OicUuid_t *)OICMalloc(pconf->pddevLen * sizeof(OicUuid_t));
741                 VERIFY_NON_NULL(TAG, pconf->pddevs, ERROR);
742                 while (cbor_value_is_valid(&pddevs) && cbor_value_is_text_string(&pddevs))
743                 {
744                     char *pddev = NULL;
745                     cborFindResult = cbor_value_dup_text_string(&pddevs, &pddev, &len, NULL);
746                     VERIFY_CBOR_SUCCESS(TAG, cborFindResult, "Failed to get value");
747                     cborFindResult = cbor_value_advance(&pddevs);
748                     VERIFY_CBOR_SUCCESS(TAG, cborFindResult, "Failed to advance");
749                     ret = ConvertStrToUuid(pddev, &pconf->pddevs[i++]);
750                     VERIFY_SUCCESS(TAG, ret == OC_STACK_OK, ERROR);
751                     OICFree(pddev);
752                 }
753             }
754
755             //Mandatory - Device Id
756             if (0 == strcmp(OIC_JSON_DEVICE_ID_NAME, name) && cbor_value_is_text_string(&pconfMap))
757             {
758                 char *deviceId = NULL;
759                 cborFindResult = cbor_value_dup_text_string(&pconfMap, &deviceId, &len, NULL);
760                 VERIFY_CBOR_SUCCESS(TAG, cborFindResult, "Failed to get deviceID");
761                 ret = ConvertStrToUuid(deviceId, &pconf->deviceID);
762                 VERIFY_SUCCESS(TAG, ret == OC_STACK_OK, ERROR);
763                 OICFree(deviceId);
764             }
765
766             // ROwner -- Mandatory
767             if (0 == strcmp(OIC_JSON_ROWNERID_NAME, name) && cbor_value_is_text_string(&pconfMap))
768             {
769                 char *rowner = NULL;
770                 cborFindResult = cbor_value_dup_text_string(&pconfMap, &rowner, &len, NULL);
771                 VERIFY_CBOR_SUCCESS(TAG, cborFindResult, "Failed to get rowner");
772                 ret = ConvertStrToUuid(rowner, &pconf->rownerID);
773                 VERIFY_SUCCESS(TAG, ret == OC_STACK_OK, ERROR);
774                 OICFree(rowner);
775             }
776         }
777         if (CborMapType != type && cbor_value_is_valid(&pconfMap))
778         {
779             cborFindResult = cbor_value_advance(&pconfMap);
780             VERIFY_CBOR_SUCCESS(TAG, cborFindResult, "Failed to advance");
781         }
782         OICFree(name);
783         name = NULL;
784     }
785     *secPconf=pconf;
786     ret = OC_STACK_OK;
787 exit:
788     if (CborNoError != cborFindResult)
789     {
790         OIC_LOG (ERROR, TAG, "CBORPayloadToPconf failed");
791         DeletePconfBinData(pconf);
792         pconf = NULL;
793         *secPconf = NULL;
794         ret = OC_STACK_ERROR;
795     }
796     return ret;
797 }
798
799 static bool UpdatePersistentStorage(const OicSecPconf_t * pconf)
800 {
801     bool ret = false;
802
803     // Convert PCONF data into Cborpayload for update to persistent storage
804     uint8_t *payload = NULL;
805     size_t size = 0;
806     if (OC_STACK_OK == PconfToCBORPayload(pconf, &payload, &size) && NULL !=payload)
807     {
808         if (OC_STACK_OK == UpdateSecureResourceInPS(OIC_JSON_PCONF_NAME, payload, size))
809         {
810             ret = true;
811         }
812         OICFree(payload);
813     }
814     return ret;
815 }
816
817 static OCEntityHandlerResult HandlePconfGetRequest (const OCEntityHandlerRequest * ehRequest)
818 {
819     uint8_t* payload = NULL;
820     size_t size = 0;
821     OCEntityHandlerResult ehRet = OC_EH_OK;
822
823     OicSecPconf_t pconf;
824     memset(&pconf, 0, sizeof(OicSecPconf_t));
825
826     OIC_LOG (DEBUG, TAG, "Pconf EntityHandle processing GET request");
827
828     if (true == GetDoxmResourceData()->dpc)
829     {
830         //Making response elements for Get request
831         if( (true == gPconf->edp) &&
832             (gPconf->prm && 0 < gPconf->prmLen) &&
833             (0 < strlen((const char*)gPconf->deviceID.id)) &&
834             (0 < strlen((const char*)gPconf->rownerID.id)))
835         {
836             pconf.edp = true;
837             pconf.prm = gPconf->prm;
838             pconf.prmLen = gPconf->prmLen;
839             memcpy(&pconf.deviceID, &gPconf->deviceID, sizeof(OicUuid_t));
840             memcpy(&pconf.rownerID, &gPconf->rownerID, sizeof(OicUuid_t));
841             OIC_LOG (DEBUG, TAG, "PCONF - direct pairing enabled");
842         }
843         else if (false == gPconf->edp)
844         {
845             pconf.edp = false;
846             memcpy(&pconf.rownerID, &gPconf->rownerID, sizeof(OicUuid_t));
847             OIC_LOG (DEBUG, TAG, "PCONF - direct pairing disable");
848         }
849         else
850         {
851             ehRet= OC_EH_ERROR;
852             OIC_LOG (DEBUG, TAG, "PCONF - error");
853         }
854     }
855     else
856     {
857         OIC_LOG (DEBUG, TAG, "DPC == false : Direct-Pairing Disabled");
858     }
859
860
861     if (OC_STACK_OK != PconfToCBORPayload(gPconf, &payload, &size))
862     {
863         ehRet = OC_EH_ERROR;
864     }
865
866     if(OC_EH_OK == ehRet)
867     {
868         ehRet = (payload ? OC_EH_OK : OC_EH_ERROR);
869     }
870     else
871     {
872         OICFree(payload);
873         payload = NULL;
874         size = 0;
875     }
876
877     // Send response payload to request originator
878     if (OC_STACK_OK != SendSRMResponse(ehRequest, ehRet, payload, size))
879     {
880         ehRet = OC_EH_ERROR;
881         OIC_LOG(ERROR, TAG, "SendSRMResponse failed in HandlePconfGetRequest");
882     }
883     OIC_LOG_V(DEBUG, TAG, "%s RetVal %d", __func__, ehRet);
884
885     OICFree(payload);
886     return ehRet;
887 }
888
889 static OCEntityHandlerResult HandlePconfPostRequest (const OCEntityHandlerRequest * ehRequest)
890 {
891     OCEntityHandlerResult ehRet = OC_EH_OK;
892     OCStackResult res=OC_STACK_OK;
893     OicSecPconf_t* newPconf = NULL;
894
895     if (NULL != GetDoxmResourceData() && true == GetDoxmResourceData()->dpc)
896     {
897         // Convert CBOR PCONF data into binary. This will also validate the PCONF data received.
898         uint8_t *payload = ((OCSecurityPayload *) ehRequest->payload)->securityData;
899         size_t size = ((OCSecurityPayload *) ehRequest->payload)->payloadSize;
900
901         if(payload){
902             res = CBORPayloadToPconf(payload, size, &newPconf);
903         }
904     }
905     else
906     {
907         OIC_LOG (DEBUG, TAG, "DPC == false : Direct-Pairing Disabled");
908         ehRet = OC_EH_ERROR;
909     }
910
911     if (newPconf && res == OC_STACK_OK)
912     {
913         // Check if valid Post request
914         if ((true == newPconf->edp) && (0 < newPconf->prmLen) &&
915                 DP_PIN_LENGTH == sizeof(newPconf->pin.val))
916         {
917             OicSecPrm_t *oldPrm = gPconf->prm;
918             OicSecPdAcl_t *oldPdacl = gPconf->pdacls;
919
920             // Update local PCONF with new PCONF
921             gPconf->edp = true;
922             memcpy(&gPconf->pin, &newPconf->pin, sizeof(OicDpPin_t));
923             gPconf->prm = newPconf->prm;
924             gPconf->prmLen = newPconf->prmLen;
925             gPconf->pdacls = newPconf->pdacls;
926             memcpy(&gPconf->rownerID, &newPconf->rownerID, sizeof(OicUuid_t));
927
928             // to delete old value(prm, pdacl)
929             newPconf->prm = oldPrm;
930             newPconf->pdacls = oldPdacl;
931         }
932         else if (false == newPconf->edp)
933         {
934             gPconf->edp = false;
935         }
936         else
937         {
938             ehRet = OC_EH_ERROR;
939         }
940
941         // Update storage
942         if(OC_EH_ERROR != ehRet && true == UpdatePersistentStorage(gPconf))
943         {
944             ehRet = OC_EH_CHANGED;
945         }
946
947         DeletePconfBinData(newPconf);
948     }
949     else
950     {
951         ehRet = OC_EH_ERROR;
952     }
953
954     // Send payload to request originator
955     if (OC_STACK_OK != SendSRMResponse(ehRequest, ehRet, NULL, 0))
956     {
957         ehRet = OC_EH_ERROR;
958         OIC_LOG(ERROR, TAG, "SendSRMResponse failed in HandlePconfPostRequest");
959     }
960
961     OIC_LOG_V (DEBUG, TAG, "%s RetVal %d", __func__ , ehRet);
962     return ehRet;
963 }
964
965 /*
966  * This internal method is the entity handler for PCONF resources and
967  * will handle REST request (POST) for them.
968  */
969 OCEntityHandlerResult PconfEntityHandler (OCEntityHandlerFlag flag,
970                                         OCEntityHandlerRequest * ehRequest,
971                                         void* callbackParameter)
972 {
973     OIC_LOG(DEBUG, TAG, "Received request PconfEntityHandler");
974     (void)callbackParameter;
975     OCEntityHandlerResult ehRet = OC_EH_ERROR;
976
977     if (!ehRequest)
978     {
979         return ehRet;
980     }
981
982     if (flag & OC_REQUEST_FLAG)
983     {
984         OIC_LOG (DEBUG, TAG, "Flag includes OC_REQUEST_FLAG");
985         switch (ehRequest->method)
986         {
987             case OC_REST_GET:
988                 ehRet = HandlePconfGetRequest(ehRequest);
989                 break;
990
991             case OC_REST_POST:
992                 ehRet = HandlePconfPostRequest(ehRequest);
993                 break;
994
995             case OC_REST_DELETE:
996                 break;
997
998             default:
999                 ehRet = OC_EH_ERROR;
1000                 SendSRMResponse(ehRequest, ehRet, NULL, 0);
1001         }
1002     }
1003
1004     return ehRet;
1005 }
1006
1007 /*
1008  * This internal method is used to create '/oic/sec/pconf' resource.
1009  */
1010 OCStackResult CreatePconfResource()
1011 {
1012     OCStackResult ret;
1013
1014     ret = OCCreateResource(&gPconfHandle,
1015                            OIC_RSRC_TYPE_SEC_PCONF,
1016                            OC_RSRVD_INTERFACE_DEFAULT,
1017                            OIC_RSRC_PCONF_URI,
1018                            PconfEntityHandler,
1019                            NULL,
1020                            OC_SECURE | OC_EXPLICIT_DISCOVERABLE);
1021
1022     if (OC_STACK_OK != ret)
1023     {
1024         OIC_LOG (ERROR, TAG, "Unable to instantiate PCONF resource");
1025         DeInitPconfResource();
1026     }
1027     return ret;
1028 }
1029
1030 /**
1031  * Get the default value.
1032  * @retval  the gDefaultPconf pointer;
1033  */
1034 static OicSecPconf_t* GetPconfDefault()
1035 {
1036     OIC_LOG (DEBUG, TAG, "GetPconfDefault");
1037
1038     return &gDefaultPconf;
1039 }
1040
1041 /**
1042  * This method is used by SRM to retrieve PCONF resource data..
1043  *
1044  * @retval  reference to @ref OicSecPconf_t, binary format of Pconf resource data
1045  */
1046 const OicSecPconf_t* GetPconfResourceData()
1047 {
1048     return gPconf;
1049 }
1050
1051 /**
1052  * Initialize PCONF resource by loading data from persistent storage.
1053  *
1054  * @retval  OC_STACK_OK for Success, otherwise some error value
1055  */
1056 OCStackResult InitPconfResource()
1057 {
1058     OCStackResult ret = OC_STACK_ERROR;
1059
1060     uint8_t *data = NULL;
1061     size_t size = 0;
1062
1063     ret = GetSecureVirtualDatabaseFromPS(OIC_JSON_PCONF_NAME, &data, &size);
1064     // If database read failed
1065     if (ret != OC_STACK_OK)
1066     {
1067         OIC_LOG(DEBUG, TAG, "ReadSVDataFromPS failed");
1068     }
1069     if (data)
1070     {
1071         CBORPayloadToPconf(data, size, &gPconf);
1072     }
1073
1074     if (!data || !gPconf)
1075     {
1076         gPconf = GetPconfDefault();
1077
1078         // device id from doxm
1079         OicUuid_t deviceId = {.id = {0}};
1080         OCStackResult ret = GetDoxmDeviceID( &deviceId);
1081         VERIFY_SUCCESS(TAG, OC_STACK_OK == ret, ERROR);
1082         memcpy(&gPconf->deviceID, &deviceId, sizeof(OicUuid_t));
1083     }
1084     VERIFY_NON_NULL(TAG, gPconf, ERROR);
1085
1086     // Instantiate 'oic.sec.pconf'
1087     ret = CreatePconfResource();
1088
1089 exit:
1090     if (OC_STACK_OK != ret)
1091     {
1092         DeInitPconfResource();
1093     }
1094     OICFree(data);
1095     return ret;
1096 }
1097
1098 /**
1099  * Perform cleanup for PCONF resources.
1100  *
1101  * @return
1102  * OC_STACK_OK    - no error
1103  * OC_STACK_ERROR - stack process error
1104  *
1105  */
1106 OCStackResult DeInitPconfResource()
1107 {
1108     OCStackResult ret = OCDeleteResource(gPconfHandle);
1109     if(gPconf!= &gDefaultPconf)
1110     {
1111         DeletePconfBinData(gPconf);
1112     }
1113     gPconf = NULL;
1114
1115     if(OC_STACK_OK == ret)
1116     {
1117         return OC_STACK_OK;
1118     }
1119     else
1120     {
1121         return OC_STACK_ERROR;
1122     }
1123 }
1124
1125 /**
1126  * This method might be used to add a paired device id after direct-pairing process complete.
1127  *
1128  * @param pdeviceId ID of the paired device.
1129  *
1130  * @retval  OC_STACK_OK for Success, otherwise some error value
1131  */
1132 OCStackResult AddPairedDevice(OicUuid_t *pdeviceId)
1133 {
1134     if (!gPconf || !pdeviceId)
1135     {
1136         return OC_STACK_INVALID_PARAM;
1137     }
1138
1139
1140     OicUuid_t *prevList = gPconf->pddevs;
1141     gPconf->pddevs = (OicUuid_t *)OICCalloc(gPconf->pddevLen+1, sizeof(OicUuid_t));
1142     if(!gPconf->pddevs)
1143     {
1144         return OC_STACK_NO_MEMORY;
1145     }
1146     for (size_t i=0; i<gPconf->pddevLen; i++)
1147     {
1148         memcpy(&gPconf->pddevs[i], &prevList[i], sizeof(OicUuid_t));
1149     }
1150
1151     // add new paired device id
1152     memcpy(&gPconf->pddevs[gPconf->pddevLen], pdeviceId, sizeof(OicUuid_t));
1153     gPconf->pddevLen++;
1154
1155     // Update storage
1156     if(true != UpdatePersistentStorage(gPconf))
1157     {
1158         OIC_LOG (ERROR, TAG, "Fail to update pconf resource");
1159         return OC_STACK_ERROR;
1160     }
1161
1162     OIC_LOG (ERROR, TAG, "Add paired device success");
1163     return OC_STACK_OK;
1164 }
1165
1166 /**
1167  * This method might be used by PolicyEngine to retrieve PDACL for a Subject.
1168  *
1169  * @param subjectId ID of the subject for which PDACL is required.
1170  * @param savePtr is used internally by @ref GetACLResourceData to maintain index between
1171  *                successive calls for same subjectId.
1172  *
1173  * @retval  reference to @ref OicSecPdAcl_t if PDACL is found, else NULL
1174  */
1175 const OicSecPdAcl_t* GetPdAclData(const OicUuid_t* subjectId, OicSecPdAcl_t **savePtr)
1176 {
1177     OicSecPdAcl_t *pdacl = NULL;
1178
1179     if ( NULL == subjectId)
1180     {
1181         return NULL;
1182     }
1183
1184     /*
1185      * savePtr MUST point to NULL if this is the 'first' call to retrieve PDACL for
1186      * subjectID.
1187      */
1188     if (NULL == *savePtr)
1189     {
1190         pdacl = gPconf->pdacls;
1191
1192         // Find if 'subjectID' is in paired device list.
1193         for(size_t i=0; i<gPconf->pddevLen; i++)
1194         {
1195             if (memcmp(&(gPconf->pddevs[i]), subjectId, sizeof(OicUuid_t)) == 0)
1196             {
1197                 *savePtr = pdacl;
1198                 return pdacl;
1199             }
1200         }
1201     }
1202     else
1203     {
1204         OicSecPdAcl_t *temp = NULL;
1205
1206         /*
1207          * If this is a 'successive' call, search for location pointed by
1208          * savePtr and assign 'begin' to the next PDACL after it in the linked
1209          * list and start searching from there.
1210          */
1211         LL_FOREACH(gPconf->pdacls, temp)
1212         {
1213             if (temp == *savePtr)
1214             {
1215                 pdacl = temp->next;
1216                 *savePtr = pdacl;
1217                 return pdacl;
1218             }
1219         }
1220     }
1221
1222     // Cleanup in case no PDACL is found
1223     *savePtr = NULL;
1224     return NULL;
1225 }
1226
1227 /**
1228  * This method return whether device is paired or not.
1229  *
1230  * @param pdeviceId Target device ID to find in paired list.
1231  * @retval  ture if device is already paired, else false
1232  */
1233 bool IsPairedDevice(const OicUuid_t* pdeviceId)
1234 {
1235     // Find if 'pdeviceId' is in paired device list.
1236     for(size_t i=0; i<gPconf->pddevLen; i++)
1237     {
1238         if (memcmp(&(gPconf->pddevs[i]), pdeviceId, sizeof(OicUuid_t)) == 0)
1239         {
1240             return true;
1241         }
1242     }
1243     return false;
1244 }
1245
1246 OCStackResult SetPconfRownerId(const OicUuid_t* newROwner)
1247 {
1248     OCStackResult ret = OC_STACK_ERROR;
1249     uint8_t *cborPayload = NULL;
1250     size_t size = 0;
1251     OicUuid_t prevId = {.id={0}};
1252
1253     if(NULL == newROwner)
1254     {
1255         ret = OC_STACK_INVALID_PARAM;
1256     }
1257     if(NULL == gPconf)
1258     {
1259         ret = OC_STACK_NO_RESOURCE;
1260     }
1261
1262     if(newROwner && gPconf)
1263     {
1264         memcpy(prevId.id, gPconf->rownerID.id, sizeof(prevId.id));
1265         memcpy(gPconf->rownerID.id, newROwner->id, sizeof(newROwner->id));
1266
1267         ret = PconfToCBORPayload(gPconf, &cborPayload, &size);
1268         VERIFY_SUCCESS(TAG, OC_STACK_OK == ret, ERROR);
1269
1270         ret = UpdateSecureResourceInPS(OIC_JSON_PCONF_NAME, cborPayload, size);
1271         VERIFY_SUCCESS(TAG, OC_STACK_OK == ret, ERROR);
1272
1273         OICFree(cborPayload);
1274     }
1275
1276     return ret;
1277
1278 exit:
1279     OICFree(cborPayload);
1280     memcpy(gPconf->rownerID.id, prevId.id, sizeof(prevId.id));
1281     return ret;
1282 }
1283
1284 OCStackResult GetPconfRownerId(OicUuid_t *rowneruuid)
1285 {
1286     OCStackResult retVal = OC_STACK_ERROR;
1287     if (gPconf)
1288     {
1289         *rowneruuid = gPconf->rownerID;
1290         retVal = OC_STACK_OK;
1291     }
1292     return retVal;
1293 }