Add direct-pairing feature
[platform/upstream/iotivity.git] / resource / csdk / security / src / dpairingresource.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 "resourcemanager.h"\r
30 #include "dpairingresource.h"\r
31 #include "psinterface.h"\r
32 #include "utlist.h"\r
33 #include "srmresourcestrings.h"\r
34 #include "cainterface.h"\r
35 #include "doxmresource.h"\r
36 #include "pconfresource.h"\r
37 #include "credresource.h"\r
38 #include "aclresource.h"\r
39 #include "srmutility.h"\r
40 #include "ocserverrequest.h"\r
41 #include <stdlib.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 #ifdef __WITH_DTLS__\r
49 #include "global.h"\r
50 #endif\r
51 \r
52 #define TAG  "SRM-DPAIRING"\r
53 \r
54 \r
55 static OicSecDpairing_t     *gDpair = NULL;\r
56 static OCResourceHandle   gDpairHandle = NULL;\r
57 static OicSecDpairing_t      gDefaultDpair =\r
58 {\r
59     PRM_NOT_ALLOWED,       /* OicSecPrm_t spm */\r
60     {.id = {0}},                   /* OicUuid_t pdeviceID */\r
61     {.id = {0}},                   /* OicUuid_t rowner */\r
62 };\r
63 \r
64 void DeleteDpairingBinData(OicSecDpairing_t* dpair)\r
65 {\r
66     if (dpair)\r
67     {\r
68         //Clean dpairing itself\r
69         OICFree(dpair);\r
70     }\r
71 }\r
72 \r
73 /**\r
74  * Get the default value.\r
75  * @retval  the gDefaultDpair pointer;\r
76  */\r
77 static OicSecDpairing_t* GetDpairingDefault()\r
78 {\r
79     OIC_LOG (DEBUG, TAG, "GetDpairingDefault");\r
80 \r
81     return &gDefaultDpair;\r
82 }\r
83 \r
84 /**\r
85  * This method is used by SRM to retrieve Dpairing resource data..\r
86  */\r
87 void SetDpairingResourceOwner(OicUuid_t *rowner)\r
88 {\r
89     OIC_LOG (DEBUG, TAG, "SetDpairingResourceOwner");\r
90     if (gDpair)\r
91     {\r
92         memcpy(&gDpair->rowner, rowner, sizeof(OicUuid_t));\r
93     }\r
94 }\r
95 \r
96 #ifdef __WITH_DTLS__\r
97 /**\r
98  * Function to save PairingPSK.\r
99  *\r
100  * @param[in] endpoint   current endpoint.\r
101  * @param[in] peerDevID   peer device indentitiy.\r
102  * @param[in] isPairingServer   indicate if it generates PairingPSK for server or client.\r
103  *\r
104  * @return  OC_STACK_OK on success\r
105  */\r
106 OCStackResult SavePairingPSK(OCDevAddr *endpoint,\r
107             OicUuid_t *peerDevID, OicUuid_t *owner, bool isPairingServer)\r
108 {\r
109     OIC_LOG(DEBUG, TAG, "IN SavePairingPSK");\r
110 \r
111     if(NULL == endpoint || NULL == peerDevID || NULL == owner)\r
112     {\r
113         OIC_LOG_V(ERROR, TAG, "Invalid Input parameters in [%s]\n", __FUNCTION__);\r
114         return OC_STACK_INVALID_PARAM;\r
115     }\r
116 \r
117     OCStackResult res = OC_STACK_ERROR;\r
118 \r
119     OicUuid_t ptDeviceID = {.id={0}};\r
120     if (OC_STACK_OK != GetDoxmDeviceID(&ptDeviceID))\r
121     {\r
122         OIC_LOG(ERROR, TAG, "Error while retrieving provisioning tool's device ID");\r
123         return res;\r
124     }\r
125 \r
126     uint8_t pairingPSK[OWNER_PSK_LENGTH_128] = {0};\r
127 \r
128     //Generating PairingPSK using OwnerPSK scheme\r
129     CAResult_t pskRet = CAGenerateOwnerPSK((const CAEndpoint_t *)endpoint,\r
130             (uint8_t *)OIC_RSRC_TYPE_SEC_DPAIRING,\r
131             strlen(OIC_RSRC_TYPE_SEC_DPAIRING),\r
132             (isPairingServer ? ptDeviceID.id : peerDevID->id), sizeof(OicUuid_t), // server\r
133             (isPairingServer ? peerDevID->id : ptDeviceID.id), sizeof(OicUuid_t), // client\r
134             pairingPSK, OWNER_PSK_LENGTH_128);\r
135 \r
136     if (CA_STATUS_OK == pskRet)\r
137     {\r
138         OIC_LOG(INFO, TAG, "pairingPSK dump:\n");\r
139         OIC_LOG_BUFFER(INFO, TAG, pairingPSK, OWNER_PSK_LENGTH_128);\r
140         //Generating new credential for direct-pairing client\r
141         size_t ownLen = 1;\r
142         uint32_t outLen = 0;\r
143 \r
144         char base64Buff[B64ENCODE_OUT_SAFESIZE(sizeof(pairingPSK)) + 1] = {};\r
145         B64Result b64Ret = b64Encode(pairingPSK, sizeof(pairingPSK), base64Buff, sizeof(base64Buff),\r
146                 &outLen);\r
147         VERIFY_SUCCESS(TAG, B64_OK == b64Ret, ERROR);\r
148 \r
149         OicSecCred_t *cred = GenerateCredential(peerDevID,\r
150                 SYMMETRIC_PAIR_WISE_KEY, NULL,\r
151                 base64Buff, ownLen, owner);\r
152         VERIFY_NON_NULL(TAG, cred, ERROR);\r
153 \r
154         res = AddCredential(cred);\r
155         if(res != OC_STACK_OK)\r
156         {\r
157             DeleteCredList(cred);\r
158             return res;\r
159         }\r
160     }\r
161     else\r
162     {\r
163         OIC_LOG(ERROR, TAG, "CAGenerateOwnerPSK failed");\r
164     }\r
165 \r
166     OIC_LOG(DEBUG, TAG, "OUT SavePairingPSK");\r
167 exit:\r
168     return res;\r
169 }\r
170 #endif // __WITH_DTLS__\r
171 \r
172 /*\r
173  * This internal method converts DPairing data into JSON format.\r
174  * Does not error-check here, but check it in caller\r
175  *\r
176  * Note: Caller needs to invoke 'free' when finished done using\r
177  * return string.\r
178  */\r
179 char * BinToDpairingJSON(const OicSecDpairing_t * dpair)\r
180 {\r
181     OIC_LOG(DEBUG, TAG, "BinToDpairingJSON() IN");\r
182 \r
183     if (NULL == dpair)\r
184     {\r
185         return NULL;\r
186     }\r
187 \r
188     char *jsonStr = NULL;\r
189     cJSON *jsonDpair = NULL;\r
190     char base64Buff[B64ENCODE_OUT_SAFESIZE(sizeof(((OicUuid_t*)0)->id)) + 1] = {};\r
191     uint32_t outLen = 0;\r
192     B64Result b64Ret = B64_OK;\r
193 \r
194     cJSON *jsonRoot = cJSON_CreateObject();\r
195     VERIFY_NON_NULL(TAG, jsonRoot, ERROR);\r
196 \r
197     jsonDpair = cJSON_CreateObject();\r
198     VERIFY_NON_NULL(TAG, jsonDpair, ERROR);\r
199     cJSON_AddItemToObject(jsonRoot, OIC_JSON_DPAIRING_NAME, jsonDpair );\r
200 \r
201     //SPM -- Mandatory\r
202     if(PRM_RANDOM_PIN >= dpair->spm) // don't need to check "PRM_NOT_ALLOWED <= dpair->spm" because of always true\r
203     {\r
204         cJSON_AddNumberToObject(jsonDpair, OIC_JSON_SPM_NAME, (int)dpair->spm);\r
205     }\r
206 \r
207     //PDeviceID -- Mandatory\r
208     //There may not be paired devices if it did not be received pairing request\r
209     if ('\0' != (char)dpair->pdeviceID.id[0])\r
210     {\r
211         outLen = 0;\r
212         b64Ret = b64Encode(dpair->pdeviceID.id, sizeof(dpair->pdeviceID.id), base64Buff,\r
213                     sizeof(base64Buff), &outLen);\r
214         VERIFY_SUCCESS(TAG, b64Ret == B64_OK, ERROR);\r
215         cJSON_AddStringToObject(jsonDpair, OIC_JSON_PDEVICE_ID_NAME, base64Buff);\r
216     }\r
217 \r
218     //ROwner -- Mandatory\r
219     if ('\0' != (char)dpair->rowner.id[0])\r
220     {\r
221         outLen = 0;\r
222         b64Ret = b64Encode(dpair->rowner.id, sizeof(dpair->rowner.id), base64Buff,\r
223                     sizeof(base64Buff), &outLen);\r
224         VERIFY_SUCCESS(TAG, b64Ret == B64_OK, ERROR);\r
225         cJSON_AddStringToObject(jsonDpair, OIC_JSON_ROWNER_NAME, base64Buff);\r
226     }\r
227 \r
228 \r
229     jsonStr = cJSON_PrintUnformatted(jsonRoot);\r
230 \r
231 exit:\r
232     if (jsonRoot)\r
233     {\r
234         cJSON_Delete(jsonRoot);\r
235     }\r
236     return jsonStr;\r
237 }\r
238 \r
239 /*\r
240  * This internal method converts JSON Dpairing into binary Dpairing.\r
241  * Does not error-check here, but check it in caller\r
242  */\r
243 OicSecDpairing_t* JSONToDpairingBin(const char * jsonStr)\r
244 {\r
245     OIC_LOG(DEBUG, TAG, "JSONToDpairingBin() IN");\r
246 \r
247     OCStackResult ret = OC_STACK_ERROR;\r
248     OicSecDpairing_t *dpair =  NULL;\r
249     cJSON *jsonRoot = NULL;\r
250     cJSON *jsonDpair = NULL;\r
251     cJSON *jsonObj = NULL;\r
252 \r
253     unsigned char base64Buff[sizeof(((OicUuid_t*)0)->id)] = {};\r
254     uint32_t outLen = 0;\r
255     B64Result b64Ret = B64_OK;\r
256 \r
257 \r
258     VERIFY_NON_NULL(TAG, jsonStr, ERROR);\r
259 \r
260     jsonRoot = cJSON_Parse(jsonStr);\r
261     VERIFY_NON_NULL(TAG, jsonRoot, ERROR);\r
262 \r
263     jsonDpair = cJSON_GetObjectItem(jsonRoot, OIC_JSON_DPAIRING_NAME);\r
264     VERIFY_NON_NULL(TAG, jsonDpair, ERROR);\r
265 \r
266     dpair = (OicSecDpairing_t*)OICCalloc(1, sizeof(OicSecDpairing_t));\r
267     VERIFY_NON_NULL(TAG, dpair, ERROR);\r
268 \r
269     //SPM -- Mandatory\r
270     jsonObj = cJSON_GetObjectItem(jsonDpair, OIC_JSON_SPM_NAME);\r
271     if (jsonObj && cJSON_Number == jsonObj->type)\r
272     {\r
273         dpair->spm = (OicSecPrm_t)jsonObj->valueint;\r
274         OIC_LOG_V (DEBUG, TAG, "jsonObj->valueint = %d", jsonObj->valueint);\r
275         OIC_LOG_V (DEBUG, TAG, "dpair->spm = %d", dpair->spm);\r
276 \r
277         // don't need to check "PRM_NOT_ALLOWED <= dpair->spm" because of always true\r
278         VERIFY_SUCCESS(TAG, (PRM_RANDOM_PIN >= dpair->spm), ERROR);\r
279     }\r
280     else\r
281     {\r
282         dpair->spm = PRM_NOT_ALLOWED;\r
283     }\r
284 \r
285     //PDeviceId -- Mandatory\r
286     outLen = 0;\r
287     jsonObj = cJSON_GetObjectItem(jsonDpair, OIC_JSON_PDEVICE_ID_NAME);\r
288     if (jsonObj && cJSON_String == jsonObj->type)\r
289     {\r
290         b64Ret = b64Decode(jsonObj->valuestring, strlen(jsonObj->valuestring), base64Buff,\r
291                 sizeof(base64Buff), &outLen);\r
292         VERIFY_SUCCESS(TAG, (b64Ret == B64_OK && outLen <= sizeof(dpair->pdeviceID.id)), ERROR);\r
293         memcpy(dpair->pdeviceID.id, base64Buff, outLen);\r
294     }\r
295     else\r
296     {\r
297         memset(&dpair->pdeviceID, 0, sizeof(OicUuid_t));\r
298     }\r
299 \r
300     // ROwner -- Mandatory\r
301     outLen = 0;\r
302     jsonObj = cJSON_GetObjectItem(jsonDpair, OIC_JSON_ROWNER_NAME);\r
303     if (jsonObj && cJSON_String == jsonObj->type)\r
304     {\r
305         b64Ret = b64Decode(jsonObj->valuestring, strlen(jsonObj->valuestring), base64Buff,\r
306                 sizeof(base64Buff), &outLen);\r
307         VERIFY_SUCCESS(TAG, (b64Ret == B64_OK && outLen <= sizeof(dpair->rowner.id)), ERROR);\r
308         memcpy(dpair->rowner.id, base64Buff, outLen);\r
309     }\r
310     else\r
311     {\r
312         memset(&dpair->rowner, 0, sizeof(OicUuid_t));\r
313     }\r
314 \r
315     ret = OC_STACK_OK;\r
316 \r
317 exit:\r
318     cJSON_Delete(jsonRoot);\r
319     if (OC_STACK_OK != ret)\r
320     {\r
321         DeleteDpairingBinData(dpair);\r
322         dpair = NULL;\r
323     }\r
324 \r
325     OIC_LOG(DEBUG, TAG, "JSONToDpairingBin() OUT");\r
326     return dpair;\r
327 }\r
328 \r
329 /**\r
330  * Function to handle the handshake result in Direct-Pairing.\r
331  * This function will be invoked after DTLS handshake\r
332  * @param   endPoint  [IN] The remote endpoint.\r
333  * @param   errorInfo [IN] Error information from the endpoint.\r
334  * @return  NONE\r
335  */\r
336 void DPairingDTLSHandshakeCB(const CAEndpoint_t *endpoint, const CAErrorInfo_t *info)\r
337 {\r
338     OIC_LOG_V(INFO, TAG, "IN DPairingDTLSHandshakeCB");\r
339 \r
340     if(gDpair && endpoint && info)\r
341     {\r
342         OIC_LOG_V(INFO, TAG, "Received status from remote device(%s:%d) : %d",\r
343                  endpoint->addr, endpoint->port, info->result);\r
344 \r
345         if(CA_STATUS_OK == info->result)\r
346         {\r
347             OIC_LOG(INFO, TAG, "DPairingDTLSHandshakeCB - Connection success.");\r
348         }\r
349         else if(CA_DTLS_AUTHENTICATION_FAILURE == info->result)\r
350         {\r
351             OIC_LOG(INFO, TAG, "DPairingDTLSHandshakeCB - Authentication failed");\r
352 \r
353         }\r
354 \r
355 #ifdef __WITH_DTLS__\r
356         CARegisterDTLSHandshakeCallback(NULL);\r
357 #endif // __WITH_DTLS__\r
358 \r
359         // delete temporary key\r
360         RemoveCredential(&gDpair->pdeviceID);\r
361     }\r
362 \r
363     OIC_LOG_V(INFO, TAG, "OUT DPairingDTLSHandshakeCB");\r
364 }\r
365 \r
366 static OCEntityHandlerResult HandleDpairingPostRequest (const OCEntityHandlerRequest * ehRequest)\r
367 {\r
368     OIC_LOG (DEBUG, TAG, "Dpairing EntityHandle  processing POST request");\r
369     OCEntityHandlerResult ehRet = OC_EH_ERROR;\r
370     OicSecDpairing_t* newDpair = NULL;\r
371 \r
372     const OicSecPconf_t *pconf = GetPconfResourceData();\r
373     if (true == pconf->edp)\r
374     {\r
375         // Convert JSON DPAIRING data into binary. This will also validate the DPAIRING data received.\r
376         newDpair = JSONToDpairingBin(((OCSecurityPayload*)ehRequest->payload)->securityData);\r
377     }\r
378     else\r
379     {\r
380         OIC_LOG (DEBUG, TAG, "EDP == false : Direct-Pairing Disabled");\r
381         ehRet = OC_EH_ERROR;\r
382     }\r
383 \r
384     if (newDpair && false == IsPairedDevice(&newDpair->pdeviceID))\r
385     {\r
386         // Check if valid Post request\r
387         bool prmMached = false;\r
388         for (size_t i=0; i<pconf->prmLen; i++)\r
389         {\r
390             if (newDpair->spm == pconf->prm[i])\r
391             {\r
392                 prmMached = true;\r
393                 break;\r
394             }\r
395         }\r
396         OIC_LOG_V(DEBUG, TAG, "Parsed spm is %s", prmMached ? "valid" : "invalid, send error response");\r
397 \r
398         // Update local Dpairing with new Dpairing & prepare dtls session\r
399         if (prmMached && '\0' != (char)newDpair->pdeviceID.id[0])\r
400         {\r
401             if(!gDpair)\r
402             {\r
403                 gDpair = GetDpairingDefault();\r
404             }\r
405             gDpair->spm = newDpair->spm;\r
406             memcpy(&gDpair->pdeviceID, &newDpair->pdeviceID, sizeof(OicUuid_t));\r
407             memcpy(&gDpair->rowner, &pconf->rowner, sizeof(OicUuid_t));\r
408 \r
409 #ifdef __WITH_DTLS__\r
410             // Add temporary psk\r
411             OCStackResult res;\r
412             OicUuid_t subjectId = {.id={0}};\r
413             res = AddTmpPskWithPIN(&gDpair->pdeviceID,\r
414                            SYMMETRIC_PAIR_WISE_KEY,\r
415                            (char*)pconf->pin.val, DP_PIN_LENGTH,\r
416                            1, &gDpair->rowner, &subjectId);\r
417             if(res != OC_STACK_OK ||\r
418                     memcmp(&gDpair->pdeviceID, &subjectId, sizeof(OicUuid_t)))\r
419             {\r
420                 OIC_LOG_V(ERROR, TAG, "Failed to save the temporal PSK : %d", res);\r
421                 goto exit;\r
422             }\r
423 \r
424             // Prepare to establish a secure channel with Pin-based PSK cipher suite\r
425             if (CA_STATUS_OK != CAEnableAnonECDHCipherSuite(false) ||\r
426                 CA_STATUS_OK != CASelectCipherSuite(TLS_ECDHE_PSK_WITH_AES_128_CBC_SHA_256))\r
427             {\r
428                 OIC_LOG_V(ERROR, TAG, "Failed to select TLS_ECDHE_PSK_WITH_AES_128_CBC_SHA_256");\r
429                 goto exit;\r
430             }\r
431 \r
432             if(CA_STATUS_OK != CARegisterDTLSHandshakeCallback(DPairingDTLSHandshakeCB))\r
433             {\r
434                 OIC_LOG(WARNING, TAG, "DirectPairingHandler : Failed to register DTLS handshake callback.");\r
435                 goto exit;\r
436             }\r
437 #endif // __WITH_DTLS__\r
438 \r
439             // should be lock /oic/sec/dpairing resource if Direct-Pairing starts normally ?\r
440             OIC_LOG (DEBUG, TAG, "/oic/sec/dpairing resource created");\r
441 \r
442             ehRet = OC_EH_RESOURCE_CREATED;\r
443         }\r
444         else\r
445         {\r
446             OIC_LOG(ERROR, TAG, "Error in request check");\r
447         }\r
448     }\r
449 \r
450 \r
451 #ifdef __WITH_DTLS__\r
452 exit:\r
453 #endif // __WITH_DTLS__\r
454 \r
455     if (OC_EH_ERROR == ehRet && gDpair)\r
456     {\r
457         RemoveCredential(&gDpair->pdeviceID);\r
458         gDpair = NULL;\r
459     }\r
460 \r
461     // Send payload to request originator\r
462     if(OC_STACK_OK != SendSRMResponse(ehRequest, ehRet, NULL))\r
463     {\r
464         OIC_LOG (ERROR, TAG, "SendSRMResponse failed in HandleDpairingPostRequest");\r
465     }\r
466 \r
467     DeleteDpairingBinData(newDpair);\r
468     OIC_LOG_V (DEBUG, TAG, "%s RetVal %d", __func__ , ehRet);\r
469     return ehRet;\r
470 }\r
471 \r
472 static OCEntityHandlerResult HandleDpairingPutRequest (const OCEntityHandlerRequest * ehRequest)\r
473 {\r
474     OIC_LOG (DEBUG, TAG, "Dpairing EntityHandle  processing PUT request (Comfirmation)");\r
475 \r
476     OCEntityHandlerResult ehRet = OC_EH_ERROR;\r
477     OicSecDpairing_t* newDpair = NULL;\r
478 \r
479     const OicSecPconf_t *pconf = GetPconfResourceData();\r
480     if (true == pconf->edp)\r
481     {\r
482         // Convert JSON DPAIRING data into binary. This will also validate the DPAIRING data received.\r
483         newDpair = JSONToDpairingBin(((OCSecurityPayload*)ehRequest->payload)->securityData);\r
484     }\r
485     else\r
486     {\r
487         OIC_LOG (DEBUG, TAG, "EDP == false : Direct-Pairing Disabled");\r
488         ehRet = OC_EH_ERROR;\r
489     }\r
490 \r
491     if (gDpair && newDpair)\r
492     {\r
493         OIC_LOG(DEBUG, TAG, "Received direct-pairing finalization request");\r
494 \r
495         // Check if valid Put request\r
496         VERIFY_SUCCESS(TAG, PRM_NOT_ALLOWED == newDpair->spm, ERROR);\r
497 \r
498         const OicSecPconf_t *pconf = GetPconfResourceData();\r
499         VERIFY_NON_NULL(TAG, pconf, ERROR);\r
500 \r
501 #ifdef __WITH_DTLS__\r
502         OCServerRequest * request = (OCServerRequest *)ehRequest->requestHandle;\r
503         VERIFY_SUCCESS(TAG, (request->devAddr.flags | OC_FLAG_SECURE), ERROR);\r
504 \r
505         //Generate new credential\r
506         OIC_LOG_V(INFO, TAG, "SavePairingPSK for %s(%d)", request->devAddr.addr, request->devAddr.port);\r
507         OCStackResult res = SavePairingPSK(&request->devAddr, &newDpair->pdeviceID,\r
508                                                                   (OicUuid_t *)&pconf->rowner, true);\r
509         VERIFY_SUCCESS(TAG, OC_STACK_OK == res, ERROR);\r
510 #endif //__WITH_DTLS__\r
511 \r
512         //Generate new acl\r
513         OicSecPdAcl_t *pdAcl;\r
514         LL_FOREACH(pconf->pdacls, pdAcl)\r
515         {\r
516             OicSecAcl_t acl;\r
517             memset(&acl, 0, sizeof(OicSecAcl_t));\r
518             memcpy(&acl.subject, &gDpair->pdeviceID, sizeof(OicUuid_t));\r
519             acl.resources = pdAcl->resources;\r
520             acl.resourcesLen = pdAcl->resourcesLen;\r
521             acl.owners = (OicUuid_t*)&pconf->rowner;\r
522             acl.ownersLen = 1;\r
523             acl.permission = pdAcl->permission;\r
524             acl.periods = pdAcl->periods;\r
525             acl.recurrences = pdAcl->recurrences;\r
526             acl.prdRecrLen = pdAcl->prdRecrLen;\r
527 \r
528             char* aclJson = BinToAclJSON(&acl);\r
529             if (aclJson)\r
530             {\r
531                 InstallNewACL(aclJson);\r
532                 OICFree(aclJson);\r
533             }\r
534         }\r
535 \r
536         //update pconf device list\r
537         AddPairedDevice(&newDpair->pdeviceID);\r
538 \r
539         //Initialize dpairing resource\r
540         gDpair = NULL;\r
541 \r
542         OIC_LOG (DEBUG, TAG, "/oic/sec/dpairing resource updated, direct-pairing finalization success");\r
543         ehRet = OC_EH_OK;\r
544     }\r
545 \r
546 exit:\r
547 \r
548     //Send payload to request originator\r
549     if(OC_STACK_OK != SendSRMResponse(ehRequest, ehRet, NULL))\r
550     {\r
551         OIC_LOG (ERROR, TAG, "SendSRMResponse failed in HandleDpairingPutRequest");\r
552     }\r
553 \r
554     DeleteDpairingBinData(newDpair);\r
555     OIC_LOG_V (DEBUG, TAG, "%s RetVal %d", __func__ , ehRet);\r
556     return ehRet;\r
557 }\r
558 /*\r
559  * This internal method is the entity handler for Dpairing resources and\r
560  * will handle REST request (GET/POST) for them.\r
561  */\r
562 OCEntityHandlerResult DpairingEntityHandler (OCEntityHandlerFlag flag,\r
563                                         OCEntityHandlerRequest * ehRequest,\r
564                                         void* callbackParameter)\r
565 {\r
566     OIC_LOG(DEBUG, TAG, "Received request DpairingEntityHandler");\r
567     (void)callbackParameter;\r
568     OCEntityHandlerResult ehRet = OC_EH_ERROR;\r
569 \r
570     if (!ehRequest)\r
571     {\r
572         return ehRet;\r
573     }\r
574 \r
575     if (flag & OC_REQUEST_FLAG)\r
576     {\r
577         OIC_LOG (DEBUG, TAG, "Flag includes OC_REQUEST_FLAG");\r
578         switch (ehRequest->method)\r
579         {\r
580             case OC_REST_GET:\r
581                 break;\r
582 \r
583             case OC_REST_POST:\r
584                 ehRet = HandleDpairingPostRequest(ehRequest);\r
585                 break;\r
586 \r
587             case OC_REST_PUT:\r
588                 ehRet = HandleDpairingPutRequest(ehRequest);\r
589                 break;\r
590 \r
591             case OC_REST_DELETE:\r
592                 break;\r
593 \r
594             default:\r
595                 ehRet = OC_EH_ERROR;\r
596                 SendSRMResponse(ehRequest, ehRet, NULL);\r
597         }\r
598     }\r
599 \r
600     return ehRet;\r
601 }\r
602 \r
603 /*\r
604  * This internal method is used to create '/oic/sec/dpairing' resource.\r
605  */\r
606 OCStackResult CreateDpairingResource()\r
607 {\r
608     OCStackResult ret;\r
609 \r
610     ret = OCCreateResource(&gDpairHandle,\r
611                            OIC_RSRC_TYPE_SEC_DPAIRING,\r
612                            OIC_MI_DEF,\r
613                            OIC_RSRC_DPAIRING_URI,\r
614                            DpairingEntityHandler,\r
615                            NULL,\r
616                            OC_SECURE | OC_EXPLICIT_DISCOVERABLE);\r
617 \r
618     if (OC_STACK_OK != ret)\r
619     {\r
620         OIC_LOG (ERROR, TAG, "Unable to instantiate Dpairing resource");\r
621         DeInitDpairingResource();\r
622     }\r
623     return ret;\r
624 }\r
625 \r
626 /**\r
627  * Initialize Dpairing resource by loading data from persistent storage.\r
628  *\r
629  * @retval  OC_STACK_OK for Success, otherwise some error value\r
630  */\r
631 OCStackResult InitDpairingResource()\r
632 {\r
633     OCStackResult ret = OC_STACK_ERROR;\r
634 \r
635     // Instantiate 'oic.sec.dpairing'\r
636     ret = CreateDpairingResource();\r
637     if (OC_STACK_OK != ret)\r
638     {\r
639         DeInitDpairingResource();\r
640     }\r
641     return ret;\r
642 }\r
643 \r
644 /**\r
645  * Perform cleanup for Dpairing resources.\r
646  *\r
647  * @return\r
648  * OC_STACK_OK    - no error\r
649  * OC_STACK_ERROR - stack process error\r
650  *\r
651  */\r
652 OCStackResult DeInitDpairingResource()\r
653 {\r
654     OCStackResult ret = OCDeleteResource(gDpairHandle);\r
655     gDpair = NULL;\r
656 \r
657     if(OC_STACK_OK == ret)\r
658     {\r
659         return OC_STACK_OK;\r
660     }\r
661     else\r
662     {\r
663         return OC_STACK_ERROR;\r
664     }\r
665 }\r
666 \r
667 \r
668 \r