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