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