RAML v1.1 sync-up in SVR DB
[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 "ocpayloadcbor.h"
42 #include "ocpayload.h"
43 #include "payload_logging.h"
44 #include <stdlib.h>
45 #ifdef WITH_ARDUINO
46 #include <string.h>
47 #else
48 #include <strings.h>
49 #endif
50
51 #ifdef __WITH_DTLS__
52 #include "global.h"
53 #endif
54
55 #define TAG  "SRM-DPAIRING"
56
57 /** Default cbor payload size. This value is increased in case of CborErrorOutOfMemory.
58  * The value of payload size is increased until reaching belox max cbor size. */
59 static const uint16_t CBOR_SIZE = 1024;
60
61 /** Max cbor size payload. */
62 static const uint16_t CBOR_MAX_SIZE = 4400;
63
64 /** DOXM Map size - Number of mandatory items. */
65 static const uint8_t DPAIR_MAP_SIZE = 3;
66
67 static OicSecDpairing_t     *gDpair = NULL;
68 static OCResourceHandle   gDpairHandle = NULL;
69 static OicSecDpairing_t      gDefaultDpair =
70 {
71     PRM_NOT_ALLOWED,       /* OicSecPrm_t spm */
72     {.id = {0}},                   /* OicUuid_t pdeviceID */
73     {.id = {0}},                   /* OicUuid_t rowner */
74 };
75
76 void DeleteDpairingBinData(OicSecDpairing_t* dpair)
77 {
78     if (dpair)
79     {
80         //Clean dpairing itself
81         OICFree(dpair);
82     }
83 }
84
85 /**
86  * Get the default value.
87  * @retval  the gDefaultDpair pointer;
88  */
89 static OicSecDpairing_t* GetDpairingDefault()
90 {
91     OIC_LOG (DEBUG, TAG, "GetDpairingDefault");
92
93     return &gDefaultDpair;
94 }
95
96 /**
97  * This method is used by SRM to retrieve Dpairing resource data..
98  */
99 void SetDpairingResourceOwner(OicUuid_t *rowner)
100 {
101     OIC_LOG (DEBUG, TAG, "SetDpairingResourceOwner");
102     if (gDpair)
103     {
104         memcpy(&gDpair->rowner, rowner, sizeof(OicUuid_t));
105     }
106 }
107
108 #ifdef __WITH_DTLS__
109 /**
110  * Function to save PairingPSK.
111  *
112  * @param[in] endpoint   current endpoint.
113  * @param[in] peerDevID   peer device indentitiy.
114  * @param[in] isPairingServer   indicate if it generates PairingPSK for server or client.
115  *
116  * @return  OC_STACK_OK on success
117  */
118 OCStackResult SavePairingPSK(OCDevAddr *endpoint,
119             OicUuid_t *peerDevID, OicUuid_t *owner, bool isPairingServer)
120 {
121     OIC_LOG(DEBUG, TAG, "IN SavePairingPSK");
122
123     if(NULL == endpoint || NULL == peerDevID || NULL == owner)
124     {
125         OIC_LOG_V(ERROR, TAG, "Invalid Input parameters in [%s]\n", __FUNCTION__);
126         return OC_STACK_INVALID_PARAM;
127     }
128
129     OCStackResult res = OC_STACK_ERROR;
130
131     OicUuid_t ptDeviceID = {.id={0}};
132     if (OC_STACK_OK != GetDoxmDeviceID(&ptDeviceID))
133     {
134         OIC_LOG(ERROR, TAG, "Error while retrieving provisioning tool's device ID");
135         return res;
136     }
137
138     uint8_t pairingPSK[OWNER_PSK_LENGTH_128] = {0};
139     OicSecKey_t pairingKey = {pairingPSK, OWNER_PSK_LENGTH_128};
140
141     //Generating PairingPSK using OwnerPSK scheme
142     CAResult_t pskRet = CAGenerateOwnerPSK((const CAEndpoint_t *)endpoint,
143             (uint8_t *)OIC_RSRC_TYPE_SEC_DPAIRING,
144             strlen(OIC_RSRC_TYPE_SEC_DPAIRING),
145             (isPairingServer ? ptDeviceID.id : peerDevID->id), sizeof(OicUuid_t), // server
146             (isPairingServer ? peerDevID->id : ptDeviceID.id), sizeof(OicUuid_t), // client
147             pairingPSK, OWNER_PSK_LENGTH_128);
148
149     if (CA_STATUS_OK == pskRet)
150     {
151         OIC_LOG(INFO, TAG, "pairingPSK dump:\n");
152         OIC_LOG_BUFFER(INFO, TAG, pairingPSK, OWNER_PSK_LENGTH_128);
153         //Generating new credential for direct-pairing client
154         size_t ownLen = 1;
155
156         OicSecCred_t *cred = GenerateCredential(peerDevID,
157                 SYMMETRIC_PAIR_WISE_KEY, NULL,
158                 &pairingKey, ownLen, owner);
159         VERIFY_NON_NULL(TAG, cred, ERROR);
160
161         res = AddCredential(cred);
162         if(res != OC_STACK_OK)
163         {
164             DeleteCredList(cred);
165             return res;
166         }
167     }
168     else
169     {
170         OIC_LOG(ERROR, TAG, "CAGenerateOwnerPSK failed");
171     }
172
173     OIC_LOG(DEBUG, TAG, "OUT SavePairingPSK");
174 exit:
175     return res;
176 }
177 #endif // __WITH_DTLS__
178
179 OCStackResult DpairingToCBORPayload(const OicSecDpairing_t *dpair, uint8_t **payload, size_t *size)
180 {
181     if (NULL == dpair || NULL == payload || NULL != *payload || NULL == size)
182     {
183         return OC_STACK_INVALID_PARAM;
184     }
185
186     size_t cborLen = *size;
187     if (0 == cborLen)
188     {
189         cborLen = CBOR_SIZE;
190     }
191
192     *payload = NULL;
193     *size = 0;
194
195     OCStackResult ret = OC_STACK_ERROR;
196
197     CborEncoder encoder = { {.ptr = NULL }, .end = 0 };
198     CborEncoder dpairMap = { {.ptr = NULL }, .end = 0 };
199
200     int64_t cborEncoderResult = CborNoError;
201     uint8_t mapSize = DPAIR_MAP_SIZE;
202
203     uint8_t *outPayload = (uint8_t *)OICCalloc(1, cborLen);
204     VERIFY_NON_NULL(TAG, outPayload, ERROR);
205     cbor_encoder_init(&encoder, outPayload, cborLen, 0);
206
207     cborEncoderResult = cbor_encoder_create_map(&encoder, &dpairMap, mapSize);
208     VERIFY_CBOR_SUCCESS(TAG, cborEncoderResult, "Failed Creating DPAIRING Map");
209
210     //spm -- Mandatory
211     cborEncoderResult = cbor_encode_text_string(&dpairMap, OIC_JSON_SPM_NAME,
212         strlen(OIC_JSON_SPM_NAME));
213     VERIFY_CBOR_SUCCESS(TAG, cborEncoderResult, "Failed Adding SPM name tag");
214     cborEncoderResult = cbor_encode_int(&dpairMap, dpair->spm);
215     VERIFY_CBOR_SUCCESS(TAG, cborEncoderResult, "Failed Adding SPM value");
216
217     //PDEVICEID -- Mandatory
218     cborEncoderResult = cbor_encode_text_string(&dpairMap, OIC_JSON_PDEVICE_ID_NAME,
219         strlen(OIC_JSON_PDEVICE_ID_NAME));
220     VERIFY_CBOR_SUCCESS(TAG, cborEncoderResult, "Failed Adding PDeviceID tag");
221     {
222         char *deviceId = NULL;
223         ret = ConvertUuidToStr(&dpair->pdeviceID, &deviceId);
224         VERIFY_SUCCESS(TAG, ret == OC_STACK_OK, ERROR);
225         cborEncoderResult = cbor_encode_text_string(&dpairMap, deviceId, strlen(deviceId));
226         VERIFY_CBOR_SUCCESS(TAG, cborEncoderResult, "Failed to encode PDeviceID value");
227         OICFree(deviceId);
228     }
229
230     //ROWNER -- Mandatory
231     cborEncoderResult = cbor_encode_text_string(&dpairMap, OIC_JSON_ROWNERID_NAME,
232         strlen(OIC_JSON_ROWNERID_NAME));
233     VERIFY_CBOR_SUCCESS(TAG, cborEncoderResult, "Failed Adding ROWNER tag");
234     {
235         char *rowner = NULL;
236         ret = ConvertUuidToStr(&dpair->rowner, &rowner);
237         VERIFY_SUCCESS(TAG, ret == OC_STACK_OK, ERROR);
238         cborEncoderResult = cbor_encode_text_string(&dpairMap, rowner, strlen(rowner));
239         VERIFY_CBOR_SUCCESS(TAG, cborEncoderResult, "Failed Adding Rowner ID value");
240         OICFree(rowner);
241     }
242
243     cborEncoderResult = cbor_encoder_close_container(&encoder, &dpairMap);
244     VERIFY_CBOR_SUCCESS(TAG, cborEncoderResult, "Failed to close dpairMap");
245
246      if (CborNoError == cborEncoderResult)
247     {
248         *size = encoder.ptr - outPayload;
249         *payload = outPayload;
250         ret = OC_STACK_OK;
251     }
252
253 exit:
254     if ((CborErrorOutOfMemory == cborEncoderResult) && (cborLen < CBOR_MAX_SIZE))
255     {
256        // reallocate and try again!
257        OICFree(outPayload);
258        // Since the allocated initial memory failed, double the memory.
259        cborLen += encoder.ptr - encoder.end;
260        cborEncoderResult = CborNoError;
261        ret = DpairingToCBORPayload(dpair, payload, &cborLen);
262        *size = cborLen;
263     }
264
265     if ((CborNoError != cborEncoderResult) || (OC_STACK_OK != ret))
266     {
267        OICFree(outPayload);
268        outPayload = NULL;
269        *payload = NULL;
270        *size = 0;
271        ret = OC_STACK_ERROR;
272     }
273
274     return ret;
275 }
276
277 OCStackResult CBORPayloadToDpair(const uint8_t *cborPayload, size_t size,
278                                 OicSecDpairing_t **secDpair)
279 {
280     if (NULL == cborPayload || NULL == secDpair || NULL != *secDpair || 0 == size)
281     {
282         return OC_STACK_INVALID_PARAM;
283     }
284
285     OCStackResult ret = OC_STACK_ERROR;
286     *secDpair = NULL;
287
288     CborValue dpairCbor = { .parser = NULL };
289     CborParser parser = { .end = NULL };
290     CborError cborFindResult = CborNoError;
291     int cborLen = size;
292
293     cbor_parser_init(cborPayload, cborLen, 0, &parser, &dpairCbor);
294     CborValue dpairMap = { .parser = NULL };
295     OicSecDpairing_t *dpair = NULL;
296     cborFindResult = cbor_value_enter_container(&dpairCbor, &dpairMap);
297     VERIFY_CBOR_SUCCESS(TAG, cborFindResult, "Failed Entering DPairing Map");
298
299     dpair = (OicSecDpairing_t *)OICCalloc(1, sizeof(*dpair));
300     VERIFY_NON_NULL(TAG, dpair, ERROR);
301
302     while (cbor_value_is_valid(&dpairMap))
303     {
304         char *name = NULL;
305         size_t len = 0;
306         CborType type = CborInvalidType;
307         cborFindResult = cbor_value_dup_text_string(&dpairMap, &name, &len, NULL);
308         VERIFY_CBOR_SUCCESS(TAG, cborFindResult, "Failed Finding tag name");
309         cborFindResult = cbor_value_advance(&dpairMap);
310         VERIFY_CBOR_SUCCESS(TAG, cborFindResult, "Failed Advancing a value in DPair map");
311
312         type = cbor_value_get_type(&dpairMap);
313         if (0 == strcmp(OIC_JSON_SPM_NAME, name))
314         {
315             cborFindResult = cbor_value_get_int(&dpairMap, (int *) &dpair->spm);
316             VERIFY_CBOR_SUCCESS(TAG, cborFindResult, "Failed Finding SPM Value");
317         }
318
319         if (0 == strcmp(OIC_JSON_PDEVICE_ID_NAME, name))
320         {
321             char *id = NULL;
322             cborFindResult = cbor_value_dup_text_string(&dpairMap, &id, &len, NULL);
323             VERIFY_CBOR_SUCCESS(TAG, cborFindResult, "Failed Finding PDeviceID value");
324             ret = ConvertStrToUuid(id, &dpair->pdeviceID);
325             VERIFY_SUCCESS(TAG, ret == OC_STACK_OK, ERROR);
326             OICFree(id);
327         }
328
329         if (0 == strcmp(OIC_JSON_ROWNERID_NAME, name))
330         {
331             char *id = NULL;
332             cborFindResult = cbor_value_dup_text_string(&dpairMap, &id, &len, NULL);
333             VERIFY_CBOR_SUCCESS(TAG, cborFindResult, "Failed Finding RownerID value");
334             ret = ConvertStrToUuid(id, &dpair->rowner);
335             VERIFY_SUCCESS(TAG, ret == OC_STACK_OK, ERROR);
336             OICFree(id);
337         }
338
339         if (CborMapType != type && cbor_value_is_valid(&dpairMap))
340         {
341             cborFindResult = cbor_value_advance(&dpairMap);
342             VERIFY_CBOR_SUCCESS(TAG, cborFindResult, "Failed Advancing the Dpair Map");
343         }
344         OICFree(name);
345     }
346
347     *secDpair = dpair;
348     ret = OC_STACK_OK;
349
350 exit:
351     if (CborNoError != cborFindResult)
352     {
353         OIC_LOG (ERROR, TAG, "CBORPayloadToDoxm failed");
354         DeleteDpairingBinData(dpair);
355         dpair = NULL;
356         *secDpair = NULL;
357         ret = OC_STACK_ERROR;
358     }
359     return ret;
360 }
361 /**
362  * Function to handle the handshake result in Direct-Pairing.
363  * This function will be invoked after DTLS handshake
364  * @param   endPoint  [IN] The remote endpoint.
365  * @param   errorInfo [IN] Error information from the endpoint.
366  * @return  NONE
367  */
368 void DPairingDTLSHandshakeCB(const CAEndpoint_t *endpoint, const CAErrorInfo_t *info)
369 {
370     OIC_LOG_V(INFO, TAG, "IN DPairingDTLSHandshakeCB");
371
372     if(gDpair && endpoint && info)
373     {
374         OIC_LOG_V(INFO, TAG, "Received status from remote device(%s:%d) : %d",
375                  endpoint->addr, endpoint->port, info->result);
376
377         if(CA_STATUS_OK == info->result)
378         {
379             OIC_LOG(INFO, TAG, "DPairingDTLSHandshakeCB - Connection success.");
380         }
381         else if(CA_DTLS_AUTHENTICATION_FAILURE == info->result)
382         {
383             OIC_LOG(INFO, TAG, "DPairingDTLSHandshakeCB - Authentication failed");
384
385         }
386
387 #ifdef __WITH_DTLS__
388         CARegisterDTLSHandshakeCallback(NULL);
389 #endif // __WITH_DTLS__
390
391         // delete temporary key
392         RemoveCredential(&gDpair->pdeviceID);
393     }
394
395     OIC_LOG_V(INFO, TAG, "OUT DPairingDTLSHandshakeCB");
396 }
397
398 static OCEntityHandlerResult HandleDpairingPostRequest (const OCEntityHandlerRequest * ehRequest)
399 {
400     OIC_LOG (DEBUG, TAG, "Dpairing EntityHandle  processing POST request");
401     OCEntityHandlerResult ehRet = OC_EH_ERROR;
402     OicSecDpairing_t* newDpair = NULL;
403     OCStackResult res = OC_STACK_OK;
404
405     const OicSecPconf_t *pconf = GetPconfResourceData();
406     if (true == pconf->edp)
407     {
408         uint8_t *payload = ((OCSecurityPayload*)ehRequest->payload)->securityData1;
409         size_t size = ((OCSecurityPayload*)ehRequest->payload)->payloadSize;
410         if (payload)
411         {
412             res = CBORPayloadToDpair(payload, size, &newDpair);
413         }
414     }
415     else
416     {
417         OIC_LOG (DEBUG, TAG, "EDP == false : Direct-Pairing Disabled");
418         ehRet = OC_EH_ERROR;
419     }
420
421     if (OC_STACK_OK == res && newDpair && false == IsPairedDevice(&newDpair->pdeviceID))
422     {
423         // Check if valid Post request
424         bool prmMached = false;
425         for (size_t i=0; i<pconf->prmLen; i++)
426         {
427             if (newDpair->spm == pconf->prm[i])
428             {
429                 prmMached = true;
430                 break;
431             }
432         }
433         OIC_LOG_V(DEBUG, TAG, "Parsed spm is %s", prmMached ? "valid" :
434                 "invalid, send error response");
435
436         // Update local Dpairing with new Dpairing & prepare dtls session
437         if (prmMached && '\0' != (char)newDpair->pdeviceID.id[0])
438         {
439             if(!gDpair)
440             {
441                 gDpair = GetDpairingDefault();
442             }
443             gDpair->spm = newDpair->spm;
444             memcpy(&gDpair->pdeviceID, &newDpair->pdeviceID, sizeof(OicUuid_t));
445             memcpy(&gDpair->rowner, &pconf->rowner, sizeof(OicUuid_t));
446
447 #ifdef __WITH_DTLS__
448             // Add temporary psk
449             OCStackResult res;
450             OicUuid_t subjectId = {.id={0}};
451             res = AddTmpPskWithPIN(&gDpair->pdeviceID,
452                            SYMMETRIC_PAIR_WISE_KEY,
453                            (char*)pconf->pin.val, DP_PIN_LENGTH,
454                            1, &gDpair->rowner, &subjectId);
455             if(res != OC_STACK_OK ||
456                     memcmp(&gDpair->pdeviceID, &subjectId, sizeof(OicUuid_t)))
457             {
458                 OIC_LOG_V(ERROR, TAG, "Failed to save the temporal PSK : %d", res);
459                 goto exit;
460             }
461
462             // Prepare to establish a secure channel with Pin-based PSK cipher suite
463             if (CA_STATUS_OK != CAEnableAnonECDHCipherSuite(false) ||
464                 CA_STATUS_OK != CASelectCipherSuite(TLS_ECDHE_PSK_WITH_AES_128_CBC_SHA_256))
465             {
466                 OIC_LOG_V(ERROR, TAG, "Failed to select TLS_ECDHE_PSK_WITH_AES_128_CBC_SHA_256");
467                 goto exit;
468             }
469
470             if(CA_STATUS_OK != CARegisterDTLSHandshakeCallback(DPairingDTLSHandshakeCB))
471             {
472                 OIC_LOG(WARNING, TAG, "DirectPairingHandler : Failed to register"
473                         " DTLS handshake callback.");
474                 goto exit;
475             }
476 #endif // __WITH_DTLS__
477
478             // should be lock /oic/sec/dpairing resource if Direct-Pairing starts normally ?
479             OIC_LOG (DEBUG, TAG, "/oic/sec/dpairing resource created");
480
481             ehRet = OC_EH_RESOURCE_CREATED;
482         }
483         else
484         {
485             OIC_LOG(ERROR, TAG, "Error in request check");
486         }
487     }
488
489
490 #ifdef __WITH_DTLS__
491 exit:
492 #endif // __WITH_DTLS__
493
494     if (OC_EH_ERROR == ehRet && gDpair)
495     {
496         RemoveCredential(&gDpair->pdeviceID);
497         gDpair = NULL;
498     }
499
500     // Send payload to request originator
501     if(OC_STACK_OK != SendSRMCBORResponse(ehRequest, ehRet, NULL, 0))
502     {
503         OIC_LOG (ERROR, TAG, "SendSRMCBORResponse failed in HandleDpairingPostRequest");
504     }
505
506     DeleteDpairingBinData(newDpair);
507     OIC_LOG_V (DEBUG, TAG, "%s RetVal %d", __func__ , ehRet);
508     return ehRet;
509 }
510
511 static OCEntityHandlerResult HandleDpairingPutRequest (const OCEntityHandlerRequest * ehRequest)
512 {
513     OIC_LOG (DEBUG, TAG, "Dpairing EntityHandle  processing PUT request (Comfirmation)");
514
515     OCEntityHandlerResult ehRet = OC_EH_ERROR;
516     OicSecDpairing_t* newDpair = NULL;
517     OCStackResult res = OC_STACK_OK;
518
519     const OicSecPconf_t *pconf = GetPconfResourceData();
520     if (true == pconf->edp)
521     {
522         uint8_t *payload = ((OCSecurityPayload*)ehRequest->payload)->securityData1;
523         size_t size = ((OCSecurityPayload*)ehRequest->payload)->payloadSize;
524         if (payload)
525         {
526             res = CBORPayloadToDpair(payload, size, &newDpair);
527         }
528
529     }
530     else
531     {
532         OIC_LOG (DEBUG, TAG, "EDP == false : Direct-Pairing Disabled");
533         ehRet = OC_EH_ERROR;
534     }
535
536
537     if ((OC_STACK_OK == res) && gDpair && newDpair)
538     {
539         OIC_LOG(DEBUG, TAG, "Received direct-pairing finalization request");
540
541         // Check if valid Put request
542         VERIFY_SUCCESS(TAG, PRM_NOT_ALLOWED == newDpair->spm, ERROR);
543
544         const OicSecPconf_t *pconf = GetPconfResourceData();
545         VERIFY_NON_NULL(TAG, pconf, ERROR);
546
547 #ifdef __WITH_DTLS__
548         OCServerRequest * request = (OCServerRequest *)ehRequest->requestHandle;
549         VERIFY_SUCCESS(TAG, (request->devAddr.flags | OC_FLAG_SECURE), ERROR);
550
551         //Generate new credential
552         OIC_LOG_V(INFO, TAG, "SavePairingPSK for %s(%d)", request->devAddr.addr,
553                 request->devAddr.port);
554         OCStackResult res = SavePairingPSK(&request->devAddr, &newDpair->pdeviceID,
555                 (OicUuid_t *)&pconf->rowner, true);
556         VERIFY_SUCCESS(TAG, OC_STACK_OK == res, ERROR);
557 #endif //__WITH_DTLS__
558
559         //Generate new acl
560         OicSecPdAcl_t *pdAcl;
561         LL_FOREACH(pconf->pdacls, pdAcl)
562         {
563             OicSecAcl_t acl;
564             memset(&acl, 0, sizeof(OicSecAcl_t));
565             memcpy(&acl.subject, &gDpair->pdeviceID, sizeof(OicUuid_t));
566             acl.resources = pdAcl->resources;
567             acl.resourcesLen = pdAcl->resourcesLen;
568             acl.owners = (OicUuid_t*)&pconf->rowner;
569             acl.ownersLen = 1;
570             acl.permission = pdAcl->permission;
571             acl.periods = pdAcl->periods;
572             acl.recurrences = pdAcl->recurrences;
573             acl.prdRecrLen = pdAcl->prdRecrLen;
574
575             size_t size = 0;
576             uint8_t *payload = NULL;
577             if (OC_STACK_OK == AclToCBORPayload(&acl, &payload, &size))
578             {
579                 InstallNewACL(payload, size);
580                 OICFree(payload);
581             }
582         }
583
584         //update pconf device list
585         AddPairedDevice(&newDpair->pdeviceID);
586
587         //Initialize dpairing resource
588         gDpair = NULL;
589
590         OIC_LOG (DEBUG, TAG, "/oic/sec/dpairing resource updated,"
591                 "direct-pairing finalization success");
592         ehRet = OC_EH_OK;
593     }
594
595 exit:
596
597     //Send payload to request originator
598     if(OC_STACK_OK != SendSRMCBORResponse(ehRequest, ehRet, NULL, 0))
599     {
600         OIC_LOG (ERROR, TAG, "SendSRMCBORResponse failed in HandleDpairingPutRequest");
601     }
602
603     DeleteDpairingBinData(newDpair);
604     OIC_LOG_V (DEBUG, TAG, "%s RetVal %d", __func__ , ehRet);
605     return ehRet;
606 }
607 /*
608  * This internal method is the entity handler for Dpairing resources and
609  * will handle REST request (GET/POST) for them.
610  */
611 OCEntityHandlerResult DpairingEntityHandler (OCEntityHandlerFlag flag,
612                                         OCEntityHandlerRequest * ehRequest,
613                                         void* callbackParameter)
614 {
615     OIC_LOG(DEBUG, TAG, "Received request DpairingEntityHandler");
616     (void)callbackParameter;
617     OCEntityHandlerResult ehRet = OC_EH_ERROR;
618
619     if (!ehRequest)
620     {
621         return ehRet;
622     }
623
624     if (flag & OC_REQUEST_FLAG)
625     {
626         OIC_LOG (DEBUG, TAG, "Flag includes OC_REQUEST_FLAG");
627         switch (ehRequest->method)
628         {
629             case OC_REST_GET:
630                 break;
631
632             case OC_REST_POST:
633                 ehRet = HandleDpairingPostRequest(ehRequest);
634                 break;
635
636             case OC_REST_PUT:
637                 ehRet = HandleDpairingPutRequest(ehRequest);
638                 break;
639
640             case OC_REST_DELETE:
641                 break;
642
643             default:
644                 ehRet = OC_EH_ERROR;
645                 SendSRMCBORResponse(ehRequest, ehRet, NULL, 0);
646         }
647     }
648
649     return ehRet;
650 }
651
652 /*
653  * This internal method is used to create '/oic/sec/dpairing' resource.
654  */
655 OCStackResult CreateDpairingResource()
656 {
657     OCStackResult ret;
658
659     ret = OCCreateResource(&gDpairHandle,
660                            OIC_RSRC_TYPE_SEC_DPAIRING,
661                            OIC_MI_DEF,
662                            OIC_RSRC_DPAIRING_URI,
663                            DpairingEntityHandler,
664                            NULL,
665                            OC_SECURE | OC_EXPLICIT_DISCOVERABLE);
666
667     if (OC_STACK_OK != ret)
668     {
669         OIC_LOG (ERROR, TAG, "Unable to instantiate Dpairing resource");
670         DeInitDpairingResource();
671     }
672     return ret;
673 }
674
675 /**
676  * Initialize Dpairing resource by loading data from persistent storage.
677  *
678  * @retval  OC_STACK_OK for Success, otherwise some error value
679  */
680 OCStackResult InitDpairingResource()
681 {
682     OCStackResult ret = OC_STACK_ERROR;
683
684     // Instantiate 'oic.sec.dpairing'
685     ret = CreateDpairingResource();
686     if (OC_STACK_OK != ret)
687     {
688         DeInitDpairingResource();
689     }
690     return ret;
691 }
692
693 /**
694  * Perform cleanup for Dpairing resources.
695  *
696  * @return
697  * OC_STACK_OK    - no error
698  * OC_STACK_ERROR - stack process error
699  *
700  */
701 OCStackResult DeInitDpairingResource()
702 {
703     OCStackResult ret = OCDeleteResource(gDpairHandle);
704     gDpair = NULL;
705
706     if(OC_STACK_OK == ret)
707     {
708         return OC_STACK_OK;
709     }
710     else
711     {
712         return OC_STACK_ERROR;
713     }
714 }