Multiple Ownership Transfer support.
[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 "iotivity_config.h"
22 #include <stdlib.h>
23 #include <string.h>
24 #include "ocstack.h"
25 #include "logger.h"
26 #include "oic_malloc.h"
27 #include "oic_string.h"
28 #include "cJSON.h"
29 #include "base64.h"
30 #include "resourcemanager.h"
31 #include "dpairingresource.h"
32 #include "psinterface.h"
33 #include "utlist.h"
34 #include "srmresourcestrings.h"
35 #include "cainterface.h"
36 #include "doxmresource.h"
37 #include "pconfresource.h"
38 #include "credresource.h"
39 #include "aclresource.h"
40 #include "srmutility.h"
41 #include "ocserverrequest.h"
42 #include "ocpayloadcbor.h"
43 #include "ocpayload.h"
44 #include "payload_logging.h"
45 #include <stdlib.h>
46 #ifdef HAVE_STRINGS_H
47 #include <strings.h>
48 #endif
49
50 #ifdef __WITH_DTLS__
51 #include "global.h"
52 #endif
53
54 #define TAG  "SRM-DPAIRING"
55
56 /** Default cbor payload size. This value is increased in case of CborErrorOutOfMemory.
57  * The value of payload size is increased until reaching belox max cbor size. */
58 static const uint16_t CBOR_SIZE = 1024;
59
60 /** Max cbor size payload. */
61 static const uint16_t CBOR_MAX_SIZE = 4400;
62
63 /** DOXM Map size - Number of mandatory items. */
64 static const uint8_t DPAIR_MAP_SIZE = 3;
65
66 static OicSecDpairing_t     *gDpair = NULL;
67 static OCResourceHandle   gDpairHandle = NULL;
68 static OicSecDpairing_t      gDefaultDpair =
69 {
70     PRM_NOT_ALLOWED,       /* OicSecPrm_t spm */
71     {.id = {0}},                   /* OicUuid_t pdeviceID */
72     {.id = {0}},                   /* OicUuid_t rowner */
73 };
74
75 void DeleteDpairingBinData(OicSecDpairing_t* dpair)
76 {
77     if (dpair)
78     {
79         //Clean dpairing itself
80         OICFree(dpair);
81     }
82 }
83
84 /**
85  * Get the default value.
86  * @retval  the gDefaultDpair pointer;
87  */
88 static OicSecDpairing_t* GetDpairingDefault()
89 {
90     OIC_LOG (DEBUG, TAG, "GetDpairingDefault");
91
92     return &gDefaultDpair;
93 }
94
95 /**
96  * This method is used by SRM to retrieve Dpairing resource data..
97  */
98 void SetDpairingResourceOwner(OicUuid_t *rowner)
99 {
100     OIC_LOG (DEBUG, TAG, "SetDpairingResourceOwner");
101     if (gDpair)
102     {
103         memcpy(&gDpair->rownerID, rowner, sizeof(OicUuid_t));
104     }
105 }
106
107 #if defined(__WITH_DTLS__) || defined(__WITH_TLS__)
108 /**
109  * Function to save PairingPSK.
110  *
111  * @param[in] endpoint   current endpoint.
112  * @param[in] peerDevID   peer device indentitiy.
113  * @param[in] isPairingServer   indicate if it generates PairingPSK for server or client.
114  *
115  * @return  OC_STACK_OK on success
116  */
117 OCStackResult SavePairingPSK(OCDevAddr *endpoint,
118             OicUuid_t *peerDevID, OicUuid_t *owner, bool isPairingServer)
119 {
120     OIC_LOG(DEBUG, TAG, "IN SavePairingPSK");
121
122     if(NULL == endpoint || NULL == peerDevID || NULL == owner)
123     {
124         OIC_LOG_V(ERROR, TAG, "Invalid Input parameters in [%s]\n", __FUNCTION__);
125         return OC_STACK_INVALID_PARAM;
126     }
127
128     OCStackResult res = OC_STACK_ERROR;
129
130     OicUuid_t ptDeviceID = {.id={0}};
131     if (OC_STACK_OK != GetDoxmDeviceID(&ptDeviceID))
132     {
133         OIC_LOG(ERROR, TAG, "Error while retrieving provisioning tool's device ID");
134         return res;
135     }
136
137     uint8_t pairingPSK[OWNER_PSK_LENGTH_128] = {0};
138     OicSecKey_t pairingKey = {pairingPSK, OWNER_PSK_LENGTH_128, OIC_ENCODING_RAW};
139
140     //Generating PairingPSK using OwnerPSK scheme
141     CAResult_t pskRet = CAGenerateOwnerPSK((const CAEndpoint_t *)endpoint,
142             (uint8_t *)OIC_RSRC_TYPE_SEC_DPAIRING,
143             strlen(OIC_RSRC_TYPE_SEC_DPAIRING),
144             (isPairingServer ? ptDeviceID.id : peerDevID->id), sizeof(OicUuid_t), // server
145             (isPairingServer ? peerDevID->id : ptDeviceID.id), sizeof(OicUuid_t), // client
146             pairingPSK, OWNER_PSK_LENGTH_128);
147
148     if (CA_STATUS_OK == pskRet)
149     {
150         OIC_LOG(INFO, TAG, "pairingPSK dump:\n");
151         OIC_LOG_BUFFER(INFO, TAG, pairingPSK, OWNER_PSK_LENGTH_128);
152         //Generating new credential for direct-pairing client
153
154         OicSecCred_t *cred = GenerateCredential(peerDevID,
155                 SYMMETRIC_PAIR_WISE_KEY, NULL,
156                 &pairingKey, owner, NULL);
157         VERIFY_NON_NULL(TAG, cred, ERROR);
158
159         res = AddCredential(cred);
160         if(res != OC_STACK_OK)
161         {
162             DeleteCredList(cred);
163             return res;
164         }
165     }
166     else
167     {
168         OIC_LOG(ERROR, TAG, "CAGenerateOwnerPSK failed");
169     }
170
171     OIC_LOG(DEBUG, TAG, "OUT SavePairingPSK");
172 exit:
173     return res;
174 }
175 #endif // __WITH_DTLS__ or __WITH_TLS__
176
177 OCStackResult DpairingToCBORPayload(const OicSecDpairing_t *dpair, uint8_t **payload, size_t *size)
178 {
179     if (NULL == dpair || NULL == payload || NULL != *payload || NULL == size)
180     {
181         return OC_STACK_INVALID_PARAM;
182     }
183
184     size_t cborLen = *size;
185     if (0 == cborLen)
186     {
187         cborLen = CBOR_SIZE;
188     }
189
190     *payload = NULL;
191     *size = 0;
192
193     OCStackResult ret = OC_STACK_ERROR;
194
195     CborEncoder encoder;
196     CborEncoder dpairMap;
197
198     int64_t cborEncoderResult = CborNoError;
199     uint8_t mapSize = DPAIR_MAP_SIZE;
200
201     uint8_t *outPayload = (uint8_t *)OICCalloc(1, cborLen);
202     VERIFY_NON_NULL(TAG, outPayload, ERROR);
203     cbor_encoder_init(&encoder, outPayload, cborLen, 0);
204
205     cborEncoderResult = cbor_encoder_create_map(&encoder, &dpairMap, mapSize);
206     VERIFY_CBOR_SUCCESS(TAG, cborEncoderResult, "Failed Creating DPAIRING Map");
207
208     //spm -- Mandatory
209     cborEncoderResult = cbor_encode_text_string(&dpairMap, OIC_JSON_SPM_NAME,
210         strlen(OIC_JSON_SPM_NAME));
211     VERIFY_CBOR_SUCCESS(TAG, cborEncoderResult, "Failed Adding SPM name tag");
212     cborEncoderResult = cbor_encode_int(&dpairMap, dpair->spm);
213     VERIFY_CBOR_SUCCESS(TAG, cborEncoderResult, "Failed Adding SPM value");
214
215     //PDEVICEID -- Mandatory
216     cborEncoderResult = cbor_encode_text_string(&dpairMap, OIC_JSON_PDEVICE_ID_NAME,
217         strlen(OIC_JSON_PDEVICE_ID_NAME));
218     VERIFY_CBOR_SUCCESS(TAG, cborEncoderResult, "Failed Adding PDeviceID tag");
219     {
220         char *deviceId = NULL;
221         ret = ConvertUuidToStr(&dpair->pdeviceID, &deviceId);
222         VERIFY_SUCCESS(TAG, ret == OC_STACK_OK, ERROR);
223         cborEncoderResult = cbor_encode_text_string(&dpairMap, deviceId, strlen(deviceId));
224         VERIFY_CBOR_SUCCESS(TAG, cborEncoderResult, "Failed to encode PDeviceID value");
225         OICFree(deviceId);
226     }
227
228     //ROWNER -- Mandatory
229     {
230         char *rowner = NULL;
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         ret = ConvertUuidToStr(&dpair->rownerID, &rowner);
235         VERIFY_SUCCESS(TAG, ret == OC_STACK_OK, ERROR);
236         cborEncoderResult = cbor_encode_text_string(&dpairMap, rowner, strlen(rowner));
237         VERIFY_CBOR_SUCCESS(TAG, cborEncoderResult, "Failed Adding Rowner ID value");
238         OICFree(rowner);
239     }
240
241     cborEncoderResult = cbor_encoder_close_container(&encoder, &dpairMap);
242     VERIFY_CBOR_SUCCESS(TAG, cborEncoderResult, "Failed to close dpairMap");
243
244      if (CborNoError == cborEncoderResult)
245     {
246         *size = encoder.ptr - outPayload;
247         *payload = outPayload;
248         ret = OC_STACK_OK;
249     }
250
251 exit:
252     if ((CborErrorOutOfMemory == cborEncoderResult) && (cborLen < CBOR_MAX_SIZE))
253     {
254        // reallocate and try again!
255        OICFree(outPayload);
256        // Since the allocated initial memory failed, double the memory.
257        cborLen += encoder.ptr - encoder.end;
258        cborEncoderResult = CborNoError;
259        ret = DpairingToCBORPayload(dpair, payload, &cborLen);
260        *size = cborLen;
261     }
262
263     if ((CborNoError != cborEncoderResult) || (OC_STACK_OK != ret))
264     {
265        OICFree(outPayload);
266        outPayload = NULL;
267        *payload = NULL;
268        *size = 0;
269        ret = OC_STACK_ERROR;
270     }
271
272     return ret;
273 }
274
275 OCStackResult CBORPayloadToDpair(const uint8_t *cborPayload, size_t size,
276                                 OicSecDpairing_t **secDpair)
277 {
278     if (NULL == cborPayload || NULL == secDpair || NULL != *secDpair || 0 == size)
279     {
280         return OC_STACK_INVALID_PARAM;
281     }
282
283     OCStackResult ret = OC_STACK_ERROR;
284     *secDpair = NULL;
285
286     CborValue dpairCbor = { .parser = NULL };
287     CborParser parser = { .end = NULL };
288     CborError cborFindResult = CborNoError;
289
290     cbor_parser_init(cborPayload, size, 0, &parser, &dpairCbor);
291     CborValue dpairMap = { .parser = NULL };
292     OicSecDpairing_t *dpair = NULL;
293     cborFindResult = cbor_value_enter_container(&dpairCbor, &dpairMap);
294     VERIFY_CBOR_SUCCESS(TAG, cborFindResult, "Failed Entering DPairing Map");
295
296     dpair = (OicSecDpairing_t *)OICCalloc(1, sizeof(*dpair));
297     VERIFY_NON_NULL(TAG, dpair, ERROR);
298
299     while (cbor_value_is_valid(&dpairMap) && cbor_value_is_text_string(&dpairMap))
300     {
301         char *name = NULL;
302         size_t len = 0;
303         CborType type = CborInvalidType;
304         cborFindResult = cbor_value_dup_text_string(&dpairMap, &name, &len, NULL);
305         VERIFY_CBOR_SUCCESS(TAG, cborFindResult, "Failed Finding tag name");
306         cborFindResult = cbor_value_advance(&dpairMap);
307         VERIFY_CBOR_SUCCESS(TAG, cborFindResult, "Failed Advancing a value in DPair map");
308
309         type = cbor_value_get_type(&dpairMap);
310         if (0 == strcmp(OIC_JSON_SPM_NAME, name) && cbor_value_is_integer(&dpairMap))
311         {
312             int spm;
313
314             cborFindResult = cbor_value_get_int(&dpairMap, &spm);
315             VERIFY_CBOR_SUCCESS(TAG, cborFindResult, "Failed Finding SPM Value");
316             dpair->spm = (OicSecPrm_t)spm;
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->rownerID);
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 #if defined(__WITH_DTLS__) || defined(__WITH_TLS__)
388         CAregisterSslHandshakeCallback(NULL);
389 #endif // __WITH_DTLS__ or __WITH_TLS__
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)->securityData;
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->rownerID, &pconf->rownerID, sizeof(OicUuid_t));
446
447 #if defined(__WITH_DTLS__) || defined(__WITH_TLS__)
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                            &gDpair->rownerID, &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, CA_ADAPTER_IP))
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 != CAregisterSslHandshakeCallback(DPairingDTLSHandshakeCB))
471             {
472                 OIC_LOG(WARNING, TAG, "DirectPairingHandler : Failed to register"
473                         " DTLS handshake callback.");
474                 goto exit;
475             }
476 #endif // __WITH_DTLS__ or __WITH_TLS__
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 #if defined(__WITH_DTLS__) || defined(__WITH_TLS__)
491 exit:
492 #endif // __WITH_DTLS__ or __WITH_TLS__
493
494     // Send payload to request originator
495     if(OC_STACK_OK != SendSRMResponse(ehRequest, ehRet, NULL, 0))
496     {
497         ehRet = OC_EH_ERROR;
498         OIC_LOG (ERROR, TAG, "SendSRMResponse failed in HandleDpairingPostRequest");
499     }
500
501     if (OC_EH_ERROR == ehRet && gDpair)
502     {
503         RemoveCredential(&gDpair->pdeviceID);
504         gDpair = NULL;
505     }
506
507     DeleteDpairingBinData(newDpair);
508     OIC_LOG_V (DEBUG, TAG, "%s RetVal %d", __func__ , ehRet);
509     return ehRet;
510 }
511
512 static OCEntityHandlerResult HandleDpairingPutRequest (const OCEntityHandlerRequest * ehRequest)
513 {
514     OIC_LOG (DEBUG, TAG, "Dpairing EntityHandle  processing PUT request (Comfirmation)");
515
516     OCEntityHandlerResult ehRet = OC_EH_ERROR;
517     OicSecDpairing_t* newDpair = NULL;
518     OCStackResult res = OC_STACK_OK;
519
520     const OicSecPconf_t *pconf = GetPconfResourceData();
521     if (true == pconf->edp)
522     {
523         uint8_t *payload = ((OCSecurityPayload*)ehRequest->payload)->securityData;
524         size_t size = ((OCSecurityPayload*)ehRequest->payload)->payloadSize;
525         if (payload)
526         {
527             res = CBORPayloadToDpair(payload, size, &newDpair);
528         }
529
530     }
531     else
532     {
533         OIC_LOG (DEBUG, TAG, "EDP == false : Direct-Pairing Disabled");
534         ehRet = OC_EH_ERROR;
535     }
536
537
538     if ((OC_STACK_OK == res) && gDpair && newDpair)
539     {
540         OIC_LOG(DEBUG, TAG, "Received direct-pairing finalization request");
541
542         // Check if valid Put request
543         VERIFY_SUCCESS(TAG, PRM_NOT_ALLOWED == newDpair->spm, ERROR);
544
545         const OicSecPconf_t *pconf = GetPconfResourceData();
546         VERIFY_NON_NULL(TAG, pconf, ERROR);
547
548 #if defined(__WITH_DTLS__) || defined(__WITH_TLS__)
549         OCServerRequest * request = (OCServerRequest *)ehRequest->requestHandle;
550         VERIFY_SUCCESS(TAG, (request->devAddr.flags | OC_FLAG_SECURE), ERROR);
551
552         //Generate new credential
553         OIC_LOG_V(INFO, TAG, "SavePairingPSK for %s(%d)", request->devAddr.addr,
554                 request->devAddr.port);
555         OCStackResult res = SavePairingPSK(&request->devAddr, &newDpair->pdeviceID,
556                 (OicUuid_t *)&pconf->rownerID, true);
557         VERIFY_SUCCESS(TAG, OC_STACK_OK == res, ERROR);
558 #endif // __WITH_DTLS__ or __WITH_TLS__
559
560         //Generate new acl
561         OicSecPdAcl_t *pdAcl;
562         LL_FOREACH(pconf->pdacls, pdAcl)
563         {
564             OicSecAcl_t* acl = (OicSecAcl_t*)OICCalloc(1, sizeof(OicSecAcl_t));
565             VERIFY_NON_NULL(TAG, acl, ERROR);
566
567             OicSecAce_t* ace = (OicSecAce_t*)OICCalloc(1, sizeof(OicSecAce_t));
568             VERIFY_NON_NULL(TAG, ace, ERROR);
569
570             LL_APPEND(acl->aces, ace);
571
572             memcpy(&ace->subjectuuid, &gDpair->pdeviceID, sizeof(OicUuid_t));
573
574             for(size_t i = 0; i < pdAcl->resourcesLen; i++)
575             {
576                 OicSecRsrc_t* rsrc = (OicSecRsrc_t*)OICCalloc(1, sizeof(OicSecRsrc_t));
577                 VERIFY_NON_NULL(TAG, rsrc, ERROR);
578                 LL_APPEND(ace->resources, rsrc);
579
580                 //href
581                 rsrc->href = OICStrdup(pdAcl->resources[i]);
582
583                 // TODO: Append 'if' and 'rt' as workaround
584                 // if
585                 rsrc->interfaceLen = 1;
586                 rsrc->interfaces = (char**)OICCalloc(rsrc->interfaceLen, sizeof(char));
587                 VERIFY_NON_NULL(TAG, (rsrc->interfaces), ERROR);
588                 rsrc->interfaces[0] = OICStrdup(OC_RSRVD_INTERFACE_DEFAULT);
589                 VERIFY_NON_NULL(TAG, (rsrc->interfaces[0]), ERROR);
590
591                 //rt
592                 rsrc->typeLen = 1;
593                 rsrc->types = (char**)OICCalloc(rsrc->typeLen, sizeof(char));
594                 VERIFY_NON_NULL(TAG, (rsrc->types), ERROR);
595                 rsrc->types[0] = OICStrdup("oic.core");
596                 VERIFY_NON_NULL(TAG, (rsrc->types[0]), ERROR);
597             }
598
599             ace->permission = pdAcl->permission;
600
601             //Copy the validity
602             if(pdAcl->periods || pdAcl->recurrences)
603             {
604                 OicSecValidity_t* validity = (OicSecValidity_t*)OICCalloc(1, sizeof(OicSecValidity_t));
605                 VERIFY_NON_NULL(TAG, validity, ERROR);
606
607                 if(pdAcl->periods && pdAcl->periods[0])
608                 {
609                     size_t periodLen = strlen(pdAcl->periods[0]) + 1;
610                     validity->period = (char*)OICMalloc(periodLen * sizeof(char));
611                     VERIFY_NON_NULL(TAG, (validity->period), ERROR);
612                     OICStrcpy(validity->period, periodLen, pdAcl->periods[0]);
613                 }
614
615                 if(pdAcl->recurrences && 0 < pdAcl->prdRecrLen)
616                 {
617                     validity->recurrenceLen = pdAcl->prdRecrLen;
618                     validity->recurrences = (char**)OICMalloc(sizeof(char*) * pdAcl->prdRecrLen);
619                     VERIFY_NON_NULL(TAG, (validity->recurrences), ERROR);
620
621                     for(size_t i = 0; i < pdAcl->prdRecrLen; i++)
622                     {
623                         size_t recurrenceLen = strlen(pdAcl->recurrences[i]) + 1;
624                         validity->recurrences[i] = (char*)OICMalloc(recurrenceLen  * sizeof(char));
625                         VERIFY_NON_NULL(TAG, (validity->recurrences[i]), ERROR);
626
627                         OICStrcpy(validity->recurrences[i], recurrenceLen, pdAcl->recurrences[i]);
628                     }
629                 }
630
631                 LL_APPEND(ace->validities, validity);
632             }
633
634             size_t size = 0;
635             uint8_t *payload = NULL;
636             if (OC_STACK_OK == AclToCBORPayload(acl, &payload, &size))
637             {
638                 InstallNewACL(payload, size);
639                 OICFree(payload);
640             }
641             DeleteACLList(acl);
642         }
643
644         //update pconf device list
645         AddPairedDevice(&newDpair->pdeviceID);
646
647         //Initialize dpairing resource
648         gDpair = NULL;
649
650         OIC_LOG (DEBUG, TAG, "/oic/sec/dpairing resource updated,"
651                 "direct-pairing finalization success");
652         ehRet = OC_EH_OK;
653     }
654
655 exit:
656
657     //Send payload to request originator
658     if(OC_STACK_OK != SendSRMResponse(ehRequest, ehRet, NULL, 0))
659     {
660         ehRet = OC_EH_ERROR;
661         OIC_LOG (ERROR, TAG, "SendSRMResponse failed in HandleDpairingPutRequest");
662     }
663
664     DeleteDpairingBinData(newDpair);
665     OIC_LOG_V (DEBUG, TAG, "%s RetVal %d", __func__ , ehRet);
666     return ehRet;
667 }
668 /*
669  * This internal method is the entity handler for Dpairing resources and
670  * will handle REST request (GET/POST) for them.
671  */
672 OCEntityHandlerResult DpairingEntityHandler (OCEntityHandlerFlag flag,
673                                         OCEntityHandlerRequest * ehRequest,
674                                         void* callbackParameter)
675 {
676     OIC_LOG(DEBUG, TAG, "Received request DpairingEntityHandler");
677     (void)callbackParameter;
678     OCEntityHandlerResult ehRet = OC_EH_ERROR;
679
680     if (!ehRequest)
681     {
682         return ehRet;
683     }
684
685     if (flag & OC_REQUEST_FLAG)
686     {
687         OIC_LOG (DEBUG, TAG, "Flag includes OC_REQUEST_FLAG");
688         switch (ehRequest->method)
689         {
690             case OC_REST_GET:
691                 break;
692
693             case OC_REST_POST:
694                 ehRet = HandleDpairingPostRequest(ehRequest);
695                 break;
696
697             case OC_REST_PUT:
698                 ehRet = HandleDpairingPutRequest(ehRequest);
699                 break;
700
701             case OC_REST_DELETE:
702                 break;
703
704             default:
705                 ehRet = OC_EH_ERROR;
706                 SendSRMResponse(ehRequest, ehRet, NULL, 0);
707         }
708     }
709
710     return ehRet;
711 }
712
713 /*
714  * This internal method is used to create '/oic/sec/dpairing' resource.
715  */
716 OCStackResult CreateDpairingResource()
717 {
718     OCStackResult ret;
719
720     ret = OCCreateResource(&gDpairHandle,
721                            OIC_RSRC_TYPE_SEC_DPAIRING,
722                            OC_RSRVD_INTERFACE_DEFAULT,
723                            OIC_RSRC_DPAIRING_URI,
724                            DpairingEntityHandler,
725                            NULL,
726                            OC_SECURE | OC_EXPLICIT_DISCOVERABLE);
727
728     if (OC_STACK_OK != ret)
729     {
730         OIC_LOG (ERROR, TAG, "Unable to instantiate Dpairing resource");
731         DeInitDpairingResource();
732     }
733     return ret;
734 }
735
736 /**
737  * Initialize Dpairing resource by loading data from persistent storage.
738  *
739  * @retval  OC_STACK_OK for Success, otherwise some error value
740  */
741 OCStackResult InitDpairingResource()
742 {
743     OCStackResult ret = OC_STACK_ERROR;
744
745     // Instantiate 'oic.sec.dpairing'
746     ret = CreateDpairingResource();
747     if (OC_STACK_OK != ret)
748     {
749         DeInitDpairingResource();
750     }
751     return ret;
752 }
753
754 /**
755  * Perform cleanup for Dpairing resources.
756  *
757  * @return
758  * OC_STACK_OK    - no error
759  * OC_STACK_ERROR - stack process error
760  *
761  */
762 OCStackResult DeInitDpairingResource()
763 {
764     OCStackResult ret = OCDeleteResource(gDpairHandle);
765     gDpair = NULL;
766
767     if(OC_STACK_OK == ret)
768     {
769         return OC_STACK_OK;
770     }
771     else
772     {
773         return OC_STACK_ERROR;
774     }
775 }
776
777 OCStackResult SetDpairingRownerId(const OicUuid_t* newROwner)
778 {
779     OCStackResult ret = OC_STACK_ERROR;
780     uint8_t *cborPayload = NULL;
781     size_t size = 0;
782     OicUuid_t prevId = {.id={0}};
783
784     if(NULL == newROwner)
785     {
786         ret = OC_STACK_INVALID_PARAM;
787     }
788     if(NULL == gDpair)
789     {
790         ret = OC_STACK_NO_RESOURCE;
791     }
792
793     if(newROwner && gDpair)
794     {
795         memcpy(prevId.id, gDpair->rownerID.id, sizeof(prevId.id));
796         memcpy(gDpair->rownerID.id, newROwner->id, sizeof(newROwner->id));
797
798         ret = DpairingToCBORPayload(gDpair, &cborPayload, &size);
799         VERIFY_SUCCESS(TAG, OC_STACK_OK == ret, ERROR);
800
801         ret = UpdateSecureResourceInPS(OIC_JSON_DPAIRING_NAME, cborPayload, size);
802         VERIFY_SUCCESS(TAG, OC_STACK_OK == ret, ERROR);
803
804         OICFree(cborPayload);
805     }
806
807     return ret;
808
809 exit:
810     OICFree(cborPayload);
811     memcpy(gDpair->rownerID.id, prevId.id, sizeof(prevId.id));
812     return ret;
813 }
814
815 OCStackResult GetDpairingRownerId(OicUuid_t *rowneruuid)
816 {
817     OCStackResult retVal = OC_STACK_ERROR;
818     if (gDpair)
819     {
820         *rowneruuid = gDpair->rownerID;
821         retVal = OC_STACK_OK;
822     }
823     return retVal;
824 }