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