replace : iotivity -> iotivity-sec
[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 #if defined (__TIZENRT__)
29 #include <apps/netutils/cJSON.h>
30 #else
31 #include "cJSON.h"
32 #endif
33 #include "base64.h"
34 #include "resourcemanager.h"
35 #include "dpairingresource.h"
36 #include "psinterface.h"
37 #include "utlist.h"
38 #include "srmresourcestrings.h"
39 #include "cainterface.h"
40 #include "doxmresource.h"
41 #include "pconfresource.h"
42 #include "credresource.h"
43 #include "aclresource.h"
44 #include "srmutility.h"
45 #include "ocserverrequest.h"
46 #include "ocpayload.h"
47 #include "ocpayloadcbor.h"
48 #include "payload_logging.h"
49
50 #ifdef HAVE_STRINGS_H
51 #include <strings.h>
52 #endif
53
54 #define TAG  "OIC_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(DEBUG, TAG, "pairingPSK dump:\n");
151         OIC_LOG_BUFFER(DEBUG, 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         OICClearMemory(pairingPSK, sizeof(pairingPSK));
158         VERIFY_NON_NULL(TAG, cred, ERROR);
159
160         res = AddCredential(cred);
161         if(res != OC_STACK_OK)
162         {
163             DeleteCredList(cred);
164             return res;
165         }
166     }
167     else
168     {
169         OIC_LOG(ERROR, TAG, "CAGenerateOwnerPSK failed");
170     }
171
172     OIC_LOG(DEBUG, TAG, "OUT SavePairingPSK");
173 exit:
174     return res;
175 }
176 #endif // __WITH_DTLS__ or __WITH_TLS__
177
178 OCStackResult DpairingToCBORPayload(const OicSecDpairing_t *dpair, uint8_t **payload, size_t *size)
179 {
180     if (NULL == dpair || NULL == payload || NULL != *payload || NULL == size)
181     {
182         return OC_STACK_INVALID_PARAM;
183     }
184
185     size_t cborLen = *size;
186     if (0 == cborLen)
187     {
188         cborLen = CBOR_SIZE;
189     }
190
191     *payload = NULL;
192     *size = 0;
193
194     OCStackResult ret = OC_STACK_ERROR;
195
196     CborEncoder encoder;
197     CborEncoder dpairMap;
198
199     int64_t cborEncoderResult = CborNoError;
200     uint8_t mapSize = DPAIR_MAP_SIZE;
201
202     uint8_t *outPayload = (uint8_t *)OICCalloc(1, cborLen);
203     VERIFY_NON_NULL(TAG, outPayload, ERROR);
204     cbor_encoder_init(&encoder, outPayload, cborLen, 0);
205
206     cborEncoderResult = cbor_encoder_create_map(&encoder, &dpairMap, mapSize);
207     VERIFY_CBOR_SUCCESS(TAG, cborEncoderResult, "Failed Creating DPAIRING Map");
208
209     //spm -- Mandatory
210     cborEncoderResult = cbor_encode_text_string(&dpairMap, OIC_JSON_SPM_NAME,
211         strlen(OIC_JSON_SPM_NAME));
212     VERIFY_CBOR_SUCCESS(TAG, cborEncoderResult, "Failed Adding SPM name tag");
213     cborEncoderResult = cbor_encode_int(&dpairMap, dpair->spm);
214     VERIFY_CBOR_SUCCESS(TAG, cborEncoderResult, "Failed Adding SPM value");
215
216     //PDEVICEID -- Mandatory
217     cborEncoderResult = cbor_encode_text_string(&dpairMap, OIC_JSON_PDEVICE_ID_NAME,
218         strlen(OIC_JSON_PDEVICE_ID_NAME));
219     VERIFY_CBOR_SUCCESS(TAG, cborEncoderResult, "Failed Adding PDeviceID tag");
220     {
221         char *deviceId = NULL;
222         ret = ConvertUuidToStr(&dpair->pdeviceID, &deviceId);
223         VERIFY_SUCCESS(TAG, ret == OC_STACK_OK, ERROR);
224         cborEncoderResult = cbor_encode_text_string(&dpairMap, deviceId, strlen(deviceId));
225         VERIFY_CBOR_SUCCESS(TAG, cborEncoderResult, "Failed to encode PDeviceID value");
226         OICFree(deviceId);
227     }
228
229     //ROWNER -- Mandatory
230     {
231         char *rowner = NULL;
232         cborEncoderResult = cbor_encode_text_string(&dpairMap, OIC_JSON_ROWNERID_NAME,
233             strlen(OIC_JSON_ROWNERID_NAME));
234         VERIFY_CBOR_SUCCESS(TAG, cborEncoderResult, "Failed Adding ROWNER tag");
235         ret = ConvertUuidToStr(&dpair->rownerID, &rowner);
236         VERIFY_SUCCESS(TAG, ret == OC_STACK_OK, ERROR);
237         cborEncoderResult = cbor_encode_text_string(&dpairMap, rowner, strlen(rowner));
238         VERIFY_CBOR_SUCCESS(TAG, cborEncoderResult, "Failed Adding Rowner ID value");
239         OICFree(rowner);
240     }
241
242     cborEncoderResult = cbor_encoder_close_container(&encoder, &dpairMap);
243     VERIFY_CBOR_SUCCESS(TAG, cborEncoderResult, "Failed to close dpairMap");
244
245      if (CborNoError == cborEncoderResult)
246     {
247         *size = cbor_encoder_get_buffer_size(&encoder, outPayload);
248         *payload = outPayload;
249         ret = OC_STACK_OK;
250     }
251
252 exit:
253     if ((CborErrorOutOfMemory == cborEncoderResult) && (cborLen < CBOR_MAX_SIZE))
254     {
255        // reallocate and try again!
256        OICFree(outPayload);
257        outPayload = NULL;
258        // Since the allocated initial memory failed, double the memory.
259        cborLen += cbor_encoder_get_buffer_size(&encoder, 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
292     cbor_parser_init(cborPayload, size, 0, &parser, &dpairCbor);
293     CborValue dpairMap = { .parser = NULL };
294     OicSecDpairing_t *dpair = NULL;
295     cborFindResult = cbor_value_enter_container(&dpairCbor, &dpairMap);
296     VERIFY_CBOR_SUCCESS(TAG, cborFindResult, "Failed Entering DPairing Map");
297
298     dpair = (OicSecDpairing_t *)OICCalloc(1, sizeof(*dpair));
299     VERIFY_NON_NULL(TAG, dpair, ERROR);
300
301     while (cbor_value_is_valid(&dpairMap) && cbor_value_is_text_string(&dpairMap))
302     {
303         char *name = NULL;
304         size_t len = 0;
305         CborType type = CborInvalidType;
306         cborFindResult = cbor_value_dup_text_string(&dpairMap, &name, &len, NULL);
307         VERIFY_CBOR_SUCCESS(TAG, cborFindResult, "Failed Finding tag name");
308         cborFindResult = cbor_value_advance(&dpairMap);
309         VERIFY_CBOR_SUCCESS(TAG, cborFindResult, "Failed Advancing a value in DPair map");
310
311         type = cbor_value_get_type(&dpairMap);
312         if (0 == strcmp(OIC_JSON_SPM_NAME, name) && cbor_value_is_integer(&dpairMap))
313         {
314             int spm;
315
316             cborFindResult = cbor_value_get_int(&dpairMap, &spm);
317             VERIFY_CBOR_SUCCESS(TAG, cborFindResult, "Failed Finding SPM Value");
318             dpair->spm = (OicSecPrm_t)spm;
319         }
320
321         if (0 == strcmp(OIC_JSON_PDEVICE_ID_NAME, name))
322         {
323             char *id = NULL;
324             cborFindResult = cbor_value_dup_text_string(&dpairMap, &id, &len, NULL);
325             VERIFY_CBOR_SUCCESS(TAG, cborFindResult, "Failed Finding PDeviceID value");
326             ret = ConvertStrToUuid(id, &dpair->pdeviceID);
327             VERIFY_SUCCESS(TAG, ret == OC_STACK_OK, ERROR);
328             OICFree(id);
329         }
330
331         if (0 == strcmp(OIC_JSON_ROWNERID_NAME, name))
332         {
333             char *id = NULL;
334             cborFindResult = cbor_value_dup_text_string(&dpairMap, &id, &len, NULL);
335             VERIFY_CBOR_SUCCESS(TAG, cborFindResult, "Failed Finding RownerID value");
336             ret = ConvertStrToUuid(id, &dpair->rownerID);
337             VERIFY_SUCCESS(TAG, ret == OC_STACK_OK, ERROR);
338             OICFree(id);
339         }
340
341         if (CborMapType != type && cbor_value_is_valid(&dpairMap))
342         {
343             cborFindResult = cbor_value_advance(&dpairMap);
344             VERIFY_CBOR_SUCCESS(TAG, cborFindResult, "Failed Advancing the Dpair Map");
345         }
346         OICFree(name);
347     }
348
349     *secDpair = dpair;
350     ret = OC_STACK_OK;
351
352 exit:
353     if (CborNoError != cborFindResult)
354     {
355         OIC_LOG (ERROR, TAG, "CBORPayloadToDoxm failed");
356         DeleteDpairingBinData(dpair);
357         dpair = NULL;
358         *secDpair = NULL;
359         ret = OC_STACK_ERROR;
360     }
361     return ret;
362 }
363 /**
364  * Function to handle the handshake result in Direct-Pairing.
365  * This function will be invoked after DTLS handshake
366  * @param   endPoint  [IN] The remote endpoint.
367  * @param   errorInfo [IN] Error information from the endpoint.
368  * @return  NONE
369  */
370 void DPairingDTLSHandshakeCB(const CAEndpoint_t *endpoint, const CAErrorInfo_t *info)
371 {
372     OIC_LOG_V(INFO, TAG, "IN DPairingDTLSHandshakeCB");
373
374     if(gDpair && endpoint && info)
375     {
376         OIC_LOG_V(INFO, TAG, "Received status from remote device(%s:%d) : %d",
377                  endpoint->addr, endpoint->port, info->result);
378
379         if(CA_STATUS_OK == info->result)
380         {
381             OIC_LOG(INFO, TAG, "DPairingDTLSHandshakeCB - Connection success.");
382         }
383         else if(CA_DTLS_AUTHENTICATION_FAILURE == info->result)
384         {
385             OIC_LOG(INFO, TAG, "DPairingDTLSHandshakeCB - Authentication failed");
386
387         }
388
389 #if defined(__WITH_DTLS__) || defined(__WITH_TLS__)
390         CAregisterSslHandshakeCallback(NULL);
391 #endif // __WITH_DTLS__ or __WITH_TLS__
392
393         // delete temporary key
394         RemoveCredential(&gDpair->pdeviceID);
395     }
396
397     OIC_LOG_V(INFO, TAG, "OUT DPairingDTLSHandshakeCB");
398 }
399
400 static OCEntityHandlerResult HandleDpairingPostRequest (const OCEntityHandlerRequest * ehRequest)
401 {
402     OIC_LOG (DEBUG, TAG, "Dpairing EntityHandle  processing POST request");
403     OCEntityHandlerResult ehRet = OC_EH_ERROR;
404     OicSecDpairing_t* newDpair = NULL;
405     OCStackResult res = OC_STACK_OK;
406
407     const OicSecPconf_t *pconf = GetPconfResourceData();
408     if (true == pconf->edp)
409     {
410         uint8_t *payload = ((OCSecurityPayload*)ehRequest->payload)->securityData;
411         size_t size = ((OCSecurityPayload*)ehRequest->payload)->payloadSize;
412         if (payload)
413         {
414             res = CBORPayloadToDpair(payload, size, &newDpair);
415         }
416     }
417     else
418     {
419         OIC_LOG (DEBUG, TAG, "EDP == false : Direct-Pairing Disabled");
420         ehRet = OC_EH_ERROR;
421     }
422
423     if (OC_STACK_OK == res && newDpair && false == IsPairedDevice(&newDpair->pdeviceID))
424     {
425         // Check if valid Post request
426         bool prmMached = false;
427         for (size_t i=0; i<pconf->prmLen; i++)
428         {
429             if (newDpair->spm == pconf->prm[i])
430             {
431                 prmMached = true;
432                 break;
433             }
434         }
435         OIC_LOG_V(DEBUG, TAG, "Parsed spm is %s", prmMached ? "valid" :
436                 "invalid, send error response");
437
438         // Update local Dpairing with new Dpairing & prepare dtls session
439         if (prmMached && '\0' != (char)newDpair->pdeviceID.id[0])
440         {
441             if(!gDpair)
442             {
443                 gDpair = GetDpairingDefault();
444             }
445             gDpair->spm = newDpair->spm;
446             memcpy(&gDpair->pdeviceID, &newDpair->pdeviceID, sizeof(OicUuid_t));
447             memcpy(&gDpair->rownerID, &pconf->rownerID, sizeof(OicUuid_t));
448
449 #if defined(__WITH_DTLS__) || defined(__WITH_TLS__)
450             // Add temporary psk
451             OCStackResult res;
452             OicUuid_t subjectId = {.id={0}};
453             res = AddTmpPskWithPIN(&gDpair->pdeviceID,
454                            SYMMETRIC_PAIR_WISE_KEY,
455                            (char*)pconf->pin.val, DP_PIN_LENGTH,
456                            &gDpair->rownerID, &subjectId);
457             if(res != OC_STACK_OK ||
458                     memcmp(&gDpair->pdeviceID, &subjectId, sizeof(OicUuid_t)))
459             {
460                 OIC_LOG_V(ERROR, TAG, "Failed to save the temporal PSK : %d", res);
461                 goto exit;
462             }
463
464             // Prepare to establish a secure channel with Pin-based PSK cipher suite
465             if (CA_STATUS_OK != CAEnableAnonECDHCipherSuite(false) ||
466                 CA_STATUS_OK != CASelectCipherSuite(MBEDTLS_TLS_ECDHE_PSK_WITH_AES_128_CBC_SHA256, CA_ADAPTER_IP))
467             {
468                 OIC_LOG_V(ERROR, TAG, "Failed to select TLS_ECDHE_PSK_WITH_AES_128_CBC_SHA_256");
469                 goto exit;
470             }
471
472             if(CA_STATUS_OK != CAregisterSslHandshakeCallback(DPairingDTLSHandshakeCB))
473             {
474                 OIC_LOG(WARNING, TAG, "DirectPairingHandler : Failed to register"
475                         " DTLS handshake callback.");
476                 goto exit;
477             }
478 #endif // __WITH_DTLS__ or __WITH_TLS__
479
480             // should be lock /oic/sec/dpairing resource if Direct-Pairing starts normally ?
481             OIC_LOG (DEBUG, TAG, "/oic/sec/dpairing resource created");
482
483             ehRet = OC_EH_RESOURCE_CREATED;
484         }
485         else
486         {
487             OIC_LOG(ERROR, TAG, "Error in request check");
488         }
489     }
490
491
492 #if defined(__WITH_DTLS__) || defined(__WITH_TLS__)
493 exit:
494 #endif // __WITH_DTLS__ or __WITH_TLS__
495
496     // Send payload to request originator
497     if(OC_STACK_OK != SendSRMResponse(ehRequest, ehRet, NULL, 0))
498     {
499         ehRet = OC_EH_ERROR;
500         OIC_LOG (ERROR, TAG, "SendSRMResponse failed in HandleDpairingPostRequest");
501     }
502
503     if (OC_EH_ERROR == ehRet && gDpair)
504     {
505         RemoveCredential(&gDpair->pdeviceID);
506         gDpair = NULL;
507     }
508
509     DeleteDpairingBinData(newDpair);
510     OIC_LOG_V (DEBUG, TAG, "%s RetVal %d", __func__ , ehRet);
511     return ehRet;
512 }
513
514 static OCEntityHandlerResult HandleDpairingPutRequest (const OCEntityHandlerRequest * ehRequest)
515 {
516     OIC_LOG (DEBUG, TAG, "Dpairing EntityHandle  processing PUT request (Comfirmation)");
517
518     OCEntityHandlerResult ehRet = OC_EH_ERROR;
519     OicSecDpairing_t* newDpair = NULL;
520     OCStackResult res = OC_STACK_OK;
521
522     const OicSecPconf_t *pconf = GetPconfResourceData();
523     if (true == pconf->edp)
524     {
525         uint8_t *payload = ((OCSecurityPayload*)ehRequest->payload)->securityData;
526         size_t size = ((OCSecurityPayload*)ehRequest->payload)->payloadSize;
527         if (payload)
528         {
529             res = CBORPayloadToDpair(payload, size, &newDpair);
530         }
531
532     }
533     else
534     {
535         OIC_LOG (DEBUG, TAG, "EDP == false : Direct-Pairing Disabled");
536         ehRet = OC_EH_ERROR;
537     }
538
539
540     if ((OC_STACK_OK == res) && gDpair && newDpair)
541     {
542         OIC_LOG(DEBUG, TAG, "Received direct-pairing finalization request");
543
544         // Check if valid Put request
545         VERIFY_SUCCESS(TAG, PRM_NOT_ALLOWED == newDpair->spm, ERROR);
546
547         const OicSecPconf_t *pconf = GetPconfResourceData();
548         VERIFY_NON_NULL(TAG, pconf, ERROR);
549
550 #if defined(__WITH_DTLS__) || defined(__WITH_TLS__)
551         OCServerRequest *request = GetServerRequestUsingHandle(ehRequest->requestHandle);
552         VERIFY_NON_NULL(TAG, request, ERROR);
553         VERIFY_SUCCESS(TAG, (request->devAddr.flags | OC_FLAG_SECURE), ERROR);
554
555         //Generate new credential
556         OIC_LOG_V(INFO, TAG, "SavePairingPSK for %s(%d)", request->devAddr.addr,
557                 request->devAddr.port);
558         OCStackResult res = SavePairingPSK(&request->devAddr, &newDpair->pdeviceID,
559                 (OicUuid_t *)&pconf->rownerID, true);
560         VERIFY_SUCCESS(TAG, OC_STACK_OK == res, ERROR);
561 #endif // __WITH_DTLS__ or __WITH_TLS__
562
563         //Generate new acl
564         OicSecPdAcl_t *pdAcl;
565         LL_FOREACH(pconf->pdacls, pdAcl)
566         {
567             OicSecAcl_t* acl = (OicSecAcl_t*)OICCalloc(1, sizeof(OicSecAcl_t));
568             VERIFY_NON_NULL(TAG, acl, ERROR);
569
570             OicSecAce_t* ace = (OicSecAce_t*)OICCalloc(1, sizeof(OicSecAce_t));
571             VERIFY_NON_NULL(TAG, ace, ERROR);
572
573             LL_APPEND(acl->aces, ace);
574
575             memcpy(&ace->subjectuuid, &gDpair->pdeviceID, sizeof(OicUuid_t));
576
577             for(size_t i = 0; i < pdAcl->resourcesLen; i++)
578             {
579                 OicSecRsrc_t* rsrc = (OicSecRsrc_t*)OICCalloc(1, sizeof(OicSecRsrc_t));
580                 VERIFY_NON_NULL(TAG, rsrc, ERROR);
581                 LL_APPEND(ace->resources, rsrc);
582
583                 //href
584                 rsrc->href = OICStrdup(pdAcl->resources[i]);
585
586                 // TODO: Append 'if' and 'rt' as workaround
587                 // if
588                 rsrc->interfaceLen = 1;
589                 rsrc->interfaces = (char**)OICCalloc(rsrc->interfaceLen, sizeof(char));
590                 VERIFY_NON_NULL(TAG, (rsrc->interfaces), ERROR);
591                 rsrc->interfaces[0] = OICStrdup(OC_RSRVD_INTERFACE_DEFAULT);
592                 VERIFY_NON_NULL(TAG, (rsrc->interfaces[0]), ERROR);
593
594                 //rt
595                 rsrc->typeLen = 1;
596                 rsrc->types = (char**)OICCalloc(rsrc->typeLen, sizeof(char));
597                 VERIFY_NON_NULL(TAG, (rsrc->types), ERROR);
598                 rsrc->types[0] = OICStrdup("oic.core");
599                 VERIFY_NON_NULL(TAG, (rsrc->types[0]), ERROR);
600             }
601
602             ace->permission = pdAcl->permission;
603
604             //Copy the validity
605             if(pdAcl->periods || pdAcl->recurrences)
606             {
607                 OicSecValidity_t* validity = (OicSecValidity_t*)OICCalloc(1, sizeof(OicSecValidity_t));
608                 VERIFY_NON_NULL(TAG, validity, ERROR);
609
610                 if(pdAcl->periods && pdAcl->periods[0])
611                 {
612                     size_t periodLen = strlen(pdAcl->periods[0]) + 1;
613                     validity->period = (char*)OICMalloc(periodLen * sizeof(char));
614                     VERIFY_NON_NULL(TAG, (validity->period), ERROR);
615                     OICStrcpy(validity->period, periodLen, pdAcl->periods[0]);
616                 }
617
618                 if(pdAcl->recurrences && 0 < pdAcl->prdRecrLen)
619                 {
620                     validity->recurrenceLen = pdAcl->prdRecrLen;
621                     validity->recurrences = (char**)OICMalloc(sizeof(char*) * pdAcl->prdRecrLen);
622                     VERIFY_NON_NULL(TAG, (validity->recurrences), ERROR);
623
624                     for(size_t i = 0; i < pdAcl->prdRecrLen; i++)
625                     {
626                         size_t recurrenceLen = strlen(pdAcl->recurrences[i]) + 1;
627                         validity->recurrences[i] = (char*)OICMalloc(recurrenceLen  * sizeof(char));
628                         VERIFY_NON_NULL(TAG, (validity->recurrences[i]), ERROR);
629
630                         OICStrcpy(validity->recurrences[i], recurrenceLen, pdAcl->recurrences[i]);
631                     }
632                 }
633
634                 LL_APPEND(ace->validities, validity);
635             }
636
637             size_t size = 0;
638             uint8_t *payload = NULL;
639             if (OC_STACK_OK == AclToCBORPayload(acl, &payload, &size))
640             {
641                 AppendACL(payload, size);
642                 OICFree(payload);
643             }
644             DeleteACLList(acl);
645         }
646
647         //update pconf device list
648         AddPairedDevice(&newDpair->pdeviceID);
649
650         //Initialize dpairing resource
651         gDpair = NULL;
652
653         OIC_LOG (DEBUG, TAG, "/oic/sec/dpairing resource updated,"
654                 "direct-pairing finalization success");
655         ehRet = OC_EH_OK;
656     }
657
658 exit:
659
660     //Send payload to request originator
661     if(OC_STACK_OK != SendSRMResponse(ehRequest, ehRet, NULL, 0))
662     {
663         ehRet = OC_EH_ERROR;
664         OIC_LOG (ERROR, TAG, "SendSRMResponse failed in HandleDpairingPutRequest");
665     }
666
667     DeleteDpairingBinData(newDpair);
668     OIC_LOG_V (DEBUG, TAG, "%s RetVal %d", __func__ , ehRet);
669     return ehRet;
670 }
671 /*
672  * This internal method is the entity handler for Dpairing resources and
673  * will handle REST request (GET/POST) for them.
674  */
675 OCEntityHandlerResult DpairingEntityHandler (OCEntityHandlerFlag flag,
676                                         OCEntityHandlerRequest * ehRequest,
677                                         void* callbackParameter)
678 {
679     OIC_LOG(DEBUG, TAG, "Received request DpairingEntityHandler");
680     (void)callbackParameter;
681     OCEntityHandlerResult ehRet = OC_EH_ERROR;
682
683     if (!ehRequest)
684     {
685         return ehRet;
686     }
687
688     if (flag & OC_REQUEST_FLAG)
689     {
690         OIC_LOG (DEBUG, TAG, "Flag includes OC_REQUEST_FLAG");
691         switch (ehRequest->method)
692         {
693             case OC_REST_GET:
694                 break;
695
696             case OC_REST_POST:
697                 ehRet = HandleDpairingPostRequest(ehRequest);
698                 break;
699
700             case OC_REST_PUT:
701                 ehRet = HandleDpairingPutRequest(ehRequest);
702                 break;
703
704             case OC_REST_DELETE:
705                 break;
706
707             default:
708                 ehRet = OC_EH_ERROR;
709                 SendSRMResponse(ehRequest, ehRet, NULL, 0);
710         }
711     }
712
713     return ehRet;
714 }
715
716 /*
717  * This internal method is used to create '/oic/sec/dpairing' resource.
718  */
719 OCStackResult CreateDpairingResource()
720 {
721     OCStackResult ret;
722
723     ret = OCCreateResource(&gDpairHandle,
724                            OIC_RSRC_TYPE_SEC_DPAIRING,
725                            OC_RSRVD_INTERFACE_DEFAULT,
726                            OIC_RSRC_DPAIRING_URI,
727                            DpairingEntityHandler,
728                            NULL,
729                            OC_SECURE | OC_EXPLICIT_DISCOVERABLE);
730
731     if (OC_STACK_OK != ret)
732     {
733         OIC_LOG (ERROR, TAG, "Unable to instantiate Dpairing resource");
734         DeInitDpairingResource();
735     }
736     return ret;
737 }
738
739 /**
740  * Initialize Dpairing resource by loading data from persistent storage.
741  *
742  * @retval  OC_STACK_OK for Success, otherwise some error value
743  */
744 OCStackResult InitDpairingResource()
745 {
746     OCStackResult ret = OC_STACK_ERROR;
747
748     // Instantiate 'oic.sec.dpairing'
749     ret = CreateDpairingResource();
750     if (OC_STACK_OK != ret)
751     {
752         DeInitDpairingResource();
753     }
754     return ret;
755 }
756
757 /**
758  * Perform cleanup for Dpairing resources.
759  *
760  * @return
761  * OC_STACK_OK    - no error
762  * OC_STACK_ERROR - stack process error
763  *
764  */
765 OCStackResult DeInitDpairingResource()
766 {
767     OCStackResult ret = OCDeleteResource(gDpairHandle);
768     gDpair = NULL;
769
770     if(OC_STACK_OK == ret)
771     {
772         return OC_STACK_OK;
773     }
774     else
775     {
776         return OC_STACK_ERROR;
777     }
778 }
779
780 OCStackResult SetDpairingRownerId(const OicUuid_t* newROwner)
781 {
782     OCStackResult ret = OC_STACK_ERROR;
783     uint8_t *cborPayload = NULL;
784     size_t size = 0;
785     OicUuid_t prevId = {.id={0}};
786
787     if(NULL == newROwner)
788     {
789         ret = OC_STACK_INVALID_PARAM;
790     }
791     if(NULL == gDpair)
792     {
793         ret = OC_STACK_NO_RESOURCE;
794     }
795
796     if(newROwner && gDpair)
797     {
798         memcpy(prevId.id, gDpair->rownerID.id, sizeof(prevId.id));
799         memcpy(gDpair->rownerID.id, newROwner->id, sizeof(newROwner->id));
800
801         ret = DpairingToCBORPayload(gDpair, &cborPayload, &size);
802         VERIFY_SUCCESS(TAG, OC_STACK_OK == ret, ERROR);
803
804         ret = UpdateSecureResourceInPS(OIC_JSON_DPAIRING_NAME, cborPayload, size);
805         VERIFY_SUCCESS(TAG, OC_STACK_OK == ret, ERROR);
806
807         OICFree(cborPayload);
808     }
809
810     return ret;
811
812 exit:
813     OICFree(cborPayload);
814     memcpy(gDpair->rownerID.id, prevId.id, sizeof(prevId.id));
815     return ret;
816 }
817
818 OCStackResult GetDpairingRownerId(OicUuid_t *rowneruuid)
819 {
820     OCStackResult retVal = OC_STACK_ERROR;
821     if (gDpair)
822     {
823         *rowneruuid = gDpair->rownerID;
824         retVal = OC_STACK_OK;
825     }
826     return retVal;
827 }