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