IOT-1583: Removing /W3 warning from resource/csdk/security.
[iotivity.git] / resource / csdk / security / provisioning / src / ocprovisioningmanager.c
1 /* *****************************************************************
2  *
3  * Copyright 2015 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 #include <stdint.h>
21 #include <stdio.h>
22 #include <string.h>
23 #include "ocprovisioningmanager.h"
24 #include "pmutility.h"
25 #include "srmutility.h"
26 #include "ownershiptransfermanager.h"
27 #ifdef MULTIPLE_OWNER
28 #include "multipleownershiptransfermanager.h"
29 #endif //MULTIPLE_OWNER
30 #include "oic_malloc.h"
31 #include "logger.h"
32 #include "secureresourceprovider.h"
33 #include "provisioningdatabasemanager.h"
34 #include "credresource.h"
35 #include "utlist.h"
36 #include "aclresource.h" //Note: SRM internal header
37 #include "pconfresource.h"
38 #include "psinterface.h"
39
40 #define TAG "OIC_OCPMAPI"
41
42 typedef struct Linkdata Linkdata_t;
43 struct Linkdata
44 {
45     void *ctx;
46     const OCProvisionDev_t *pDev1;
47     OicSecAcl_t *pDev1Acl;
48     const OCProvisionDev_t *pDev2;
49     OicSecAcl_t *pDev2Acl;
50     OCProvisionResult_t *resArr;
51     int numOfResults;
52     int currentCountResults;
53     OCProvisionResultCB resultCallback;
54
55 };
56
57 #ifdef MULTIPLE_OWNER
58 typedef struct ProvPreconfPINCtx ProvPreconfPINCtx_t;
59 struct ProvPreconfPINCtx
60 {
61     void *ctx;
62     const OCProvisionDev_t *devInfo;
63     const char* pin;
64     size_t pinLen;
65     OCProvisionResultCB resultCallback;
66 };
67 #endif //MULTIPLE_OWNER
68
69 /**
70  * The function is responsible for initializaton of the provisioning manager. It will load
71  * provisioning database which have owned device's list and their linked status.
72  * TODO: In addition, if there is a device(s) which has not up-to-date credentials, this function will
73  * automatically try to update the deivce(s).
74  *
75  * @param[in] dbPath file path of the sqlite3 db
76  *
77  * @return OC_STACK_OK in case of success and other value otherwise.
78  */
79 OCStackResult OCInitPM(const char* dbPath)
80 {
81     return PDMInit(dbPath);
82 }
83
84 /**
85  * The function is responsible for discovery of owned/unowned device is specified endpoint/deviceID.
86  * And this function will only return the specified device's response.
87  *
88  * @param[in] timeout Timeout in seconds, value till which function will listen to responses from
89  *                    server before returning the device.
90  * @param[in] deviceID         deviceID of target device.
91  * @param[out] ppFoundDevice     OCProvisionDev_t of found device
92  * @return OTM_SUCCESS in case of success and other value otherwise.
93  */
94 OCStackResult OCDiscoverSingleDevice(unsigned short timeout, const OicUuid_t* deviceID,
95                              OCProvisionDev_t **ppFoundDevice)
96 {
97     if( NULL == ppFoundDevice || NULL != *ppFoundDevice || 0 == timeout || NULL == deviceID)
98     {
99         return OC_STACK_INVALID_PARAM;
100     }
101
102     return PMSingleDeviceDiscovery(timeout, deviceID, ppFoundDevice);
103 }
104
105 /**
106  * The function is responsible for discovery of owned/unowned device is specified endpoint/deviceID.
107  * And this function will only return the specified device's response.
108  *
109  * @param[in] timeout Timeout in seconds, value till which function will listen to responses from
110  *                    server before returning the device.
111  * @param[in] deviceID         deviceID of target device.
112  * @param[in] hostAddress       MAC address of target device.
113  * @param[in] connType       ConnectivityType for discovery.
114  * @param[out] ppFoundDevice     OCProvisionDev_t of found device.
115  * @return OTM_SUCCESS in case of success and other value otherwise.
116  */
117 OCStackResult OCDiscoverSingleDeviceInUnicast(unsigned short timeout, const OicUuid_t* deviceID,
118                              const char* hostAddress, OCConnectivityType connType,
119                              OCProvisionDev_t **ppFoundDevice)
120 {
121     if( NULL == ppFoundDevice || NULL != *ppFoundDevice || 0 == timeout || NULL == deviceID ||
122             NULL == hostAddress)
123     {
124         OIC_LOG(ERROR, TAG, "OCDiscoverSingleDeviceInUnicast : Invalid Parameter");
125         return OC_STACK_INVALID_PARAM;
126     }
127
128     return PMSingleDeviceDiscoveryInUnicast(timeout, deviceID, hostAddress, connType,
129             ppFoundDevice);
130 }
131
132 /**
133  * The function is responsible for discovery of device is current subnet. It will list
134  * all the device in subnet which are not yet owned. Please call OCInit with OC_CLIENT_SERVER as
135  * OCMode.
136  *
137  * @param[in] timeout Timeout in seconds, value till which function will listen to responses from
138  *                    server before returning the list of devices.
139  * @param[out] ppList List of candidate devices to be provisioned
140  * @return OTM_SUCCESS in case of success and other value otherwise.
141  */
142 OCStackResult OCDiscoverUnownedDevices(unsigned short timeout, OCProvisionDev_t **ppList)
143 {
144     if( ppList == NULL || *ppList != NULL || 0 == timeout)
145     {
146         return OC_STACK_INVALID_PARAM;
147     }
148
149     return PMDeviceDiscovery(timeout, false, ppList);
150 }
151
152 /**
153  * The function is responsible for discovery of owned device is current subnet. It will list
154  * all the device in subnet which are owned by calling provisioning client.
155  *
156  * @param[in] timeout Timeout in seconds, value till which function will listen to responses from
157  *                    server before returning the list of devices.
158  * @param[out] ppList List of device owned by provisioning tool.
159  * @return OTM_SUCCESS in case of success and other value otherwise.
160  */
161 OCStackResult OCDiscoverOwnedDevices(unsigned short timeout, OCProvisionDev_t **ppList)
162 {
163     if( ppList == NULL || *ppList != NULL || 0 == timeout)
164     {
165         return OC_STACK_INVALID_PARAM;
166     }
167
168     return PMDeviceDiscovery(timeout, true, ppList);
169 }
170
171 #ifdef MULTIPLE_OWNER
172 /**
173  * The function is responsible for the discovery of an MOT-enabled device with the specified deviceID.
174  * The function will return when security information for device with deviceID has been obtained or the
175  * timeout has been exceeded.
176  *
177  * @param[in]  timeoutSeconds  Maximum time, in seconds, this function will listen for responses from 
178  *                             servers before returning.
179  * @param[in]  deviceID        deviceID of target device.
180  * @param[out] ppFoundDevice   OCProvisionDev_t of discovered device. Caller should use
181  *                             OCDeleteDiscoveredDevices to delete the device.
182  * @return OC_STACK_OK in case of success and other values otherwise.
183  */
184 OCStackResult OCDiscoverMultipleOwnerEnabledSingleDevice(unsigned short timeoutSeconds,
185                                                          const OicUuid_t* deviceID, 
186                                                          OCProvisionDev_t **ppFoundDevice)
187 {
188     if ((NULL == ppFoundDevice) || (NULL != *ppFoundDevice) || (0 == timeoutSeconds) || (NULL == deviceID))
189     {
190         return OC_STACK_INVALID_PARAM;
191     }
192
193     return PMMultipleOwnerSingleDeviceDiscovery(timeoutSeconds, deviceID, ppFoundDevice);
194 }
195
196 /**
197  * The function is responsible for discovery of MOT enabled device is current subnet.
198  *
199  * @param[in] timeout Timeout in seconds, value till which function will listen to responses from
200  *                    server before returning the list of devices.
201  * @param[out] ppList List of MOT enabled devices.
202  * @return OC_STACK_OK in case of success and other value otherwise.
203  */
204 OCStackResult OCDiscoverMultipleOwnerEnabledDevices(unsigned short timeout, OCProvisionDev_t **ppList)
205 {
206     if( ppList == NULL || *ppList != NULL || 0 == timeout)
207     {
208         return OC_STACK_INVALID_PARAM;
209     }
210
211     return PMMultipleOwnerDeviceDiscovery(timeout, false, ppList);
212 }
213
214 /**
215  * The function is responsible for discovery of Multiple Owned device is current subnet.
216  *
217  * @param[in] timeout Timeout in seconds, value till which function will listen to responses from
218  *                    server before returning the list of devices.
219  * @param[out] ppList List of Multiple Owned devices.
220  * @return OC_STACK_OK in case of success and other value otherwise.
221  */
222 OCStackResult OCDiscoverMultipleOwnedDevices(unsigned short timeout, OCProvisionDev_t **ppList)
223 {
224     if( ppList == NULL || *ppList != NULL || 0 == timeout)
225     {
226         return OC_STACK_INVALID_PARAM;
227     }
228
229     return PMMultipleOwnerDeviceDiscovery(timeout, true, ppList);
230 }
231
232 /**
233  * API to add preconfigured PIN to local SVR DB.
234  *
235  * @param[in] targetDeviceInfo Selected target device.
236  * @param[in] preconfigPin Preconfig PIN which is used while multiple owner authentication
237  * @param[in] preconfigPinLen Byte length of preconfigPin
238  * @return OC_STACK_OK in case of success and other value otherwise.
239  */
240 OCStackResult OCAddPreconfigPin(const OCProvisionDev_t *targetDeviceInfo,
241                                 const char *preconfigPin,
242                                 size_t preconfigPinLen)
243 {
244     return MOTAddPreconfigPIN(targetDeviceInfo, preconfigPin, preconfigPinLen);
245 }
246
247 OCStackResult OCDoMultipleOwnershipTransfer(void* ctx,
248                                       OCProvisionDev_t *targetDevices,
249                                       OCProvisionResultCB resultCallback)
250 {
251     if( NULL == targetDevices )
252     {
253         return OC_STACK_INVALID_PARAM;
254     }
255     if (NULL == resultCallback)
256     {
257         OIC_LOG(INFO, TAG, "OCDoOwnershipTransfer : NULL Callback");
258         return OC_STACK_INVALID_CALLBACK;
259     }
260     return MOTDoOwnershipTransfer(ctx, targetDevices, resultCallback);
261 }
262
263 /**
264  * The function is responsible for determining if the caller is a subowner of the specified device.
265  *
266  * @param[in]  device      MOT enabled device that contains a list of subowners
267  * @param[out] isSubowner  Bool indicating whether the caller is a subowner of device
268  * @return OC_STACK_OK in case of success and other value otherwise.
269  */
270 OCStackResult OCIsSubownerOfDevice(OCProvisionDev_t *device, bool *isSubowner)
271 {
272     if ((NULL == device) || (NULL == isSubowner))
273     {
274         return OC_STACK_INVALID_PARAM;
275     }
276
277     return PMIsSubownerOfDevice(device, isSubowner);
278 }
279 #endif //MULTIPLE_OWNER
280
281 /**
282  * API to register for particular OxM.
283  *
284  * @param[in] Ownership transfer method.
285  * @param[in] Implementation of callback functions for owership transfer.
286  * @return  OC_STACK_OK in case of success and other value otherwise.
287  */
288 OCStackResult OCSetOwnerTransferCallbackData(OicSecOxm_t oxm, OTMCallbackData_t* callbackData)
289 {
290     if(NULL == callbackData)
291     {
292         return OC_STACK_INVALID_CALLBACK ;
293     }
294
295     return OTMSetOwnershipTransferCallbackData(oxm, callbackData);
296 }
297
298 /**
299  * API to set a allow status of OxM
300  *
301  * @param[in] oxm Owership transfer method (ref. OicSecOxm_t)
302  * @param[in] allowStatus allow status (true = allow, false = not allow)
303  *
304  * @return OC_STACK_OK in case of success and other value otherwise.
305  */
306 OCStackResult OCSetOxmAllowStatus(const OicSecOxm_t oxm, const bool allowStatus)
307 {
308     return OTMSetOxmAllowStatus(oxm, allowStatus);
309 }
310
311 OCStackResult OCDoOwnershipTransfer(void* ctx,
312                                       OCProvisionDev_t *targetDevices,
313                                       OCProvisionResultCB resultCallback)
314 {
315     if( NULL == targetDevices )
316     {
317         return OC_STACK_INVALID_PARAM;
318     }
319     if (!resultCallback)
320     {
321         OIC_LOG(INFO, TAG, "OCDoOwnershipTransfer : NULL Callback");
322         return OC_STACK_INVALID_CALLBACK;
323     }
324     return OTMDoOwnershipTransfer(ctx, targetDevices, resultCallback);
325 }
326
327 /**
328  * This function deletes memory allocated to linked list created by OCDiscover_XXX_Devices API.
329  *
330  * @param[in] pList Pointer to OCProvisionDev_t which should be deleted.
331  */
332 void OCDeleteDiscoveredDevices(OCProvisionDev_t *pList)
333 {
334     PMDeleteDeviceList(pList);
335 }
336
337 /**
338  * this function sends ACL information to resource.
339  *
340  * @param[in] ctx Application context would be returned in result callback.
341  * @param[in] selectedDeviceInfo Selected target device.
342  * @param[in] acl ACL to provision.
343  * @param[in] resultCallback callback provided by API user, callback will be called when provisioning
344               request recieves a response from resource server.
345  * @return  OC_STACK_OK in case of success and other value otherwise.
346  */
347 OCStackResult OCProvisionACL(void* ctx, const OCProvisionDev_t *selectedDeviceInfo, OicSecAcl_t *acl,
348                              OCProvisionResultCB resultCallback)
349 {
350     return SRPProvisionACL(ctx, selectedDeviceInfo, acl, resultCallback);
351 }
352
353 /**
354  * function to save ACL which has several ACE into Acl of SVR.
355  *
356  * @param acl ACL to be saved in Acl of SVR.
357  * @return  OC_STACK_OK in case of success and other value otherwise.
358  */
359 OCStackResult OCSaveACL(const OicSecAcl_t* acl)
360 {
361     return SRPSaveACL(acl);
362 }
363
364 /**
365  * this function requests CRED information to resource.
366  *
367  * @param[in] ctx Application context would be returned in result callback.
368  * @param[in] selectedDeviceInfo Selected target device.
369  * @param[in] resultCallback callback provided by API user, callback will be called when provisioning
370               request recieves a response from resource server.
371  * @return  OC_STACK_OK in case of success and other value otherwise.
372  */
373 OCStackResult OCGetCredResource(void* ctx, const OCProvisionDev_t *selectedDeviceInfo,
374                              OCProvisionResultCB resultCallback)
375 {
376     return SRPGetCredResource(ctx, selectedDeviceInfo, resultCallback);
377 }
378
379 /**
380  * this function requests ACL information to resource.
381  *
382  * @param[in] ctx Application context would be returned in result callback.
383  * @param[in] selectedDeviceInfo Selected target device.
384  * @param[in] resultCallback callback provided by API user, callback will be called when provisioning
385               request recieves a response from resource server.
386  * @return  OC_STACK_OK in case of success and other value otherwise.
387  */
388 OCStackResult OCGetACLResource(void* ctx, const OCProvisionDev_t *selectedDeviceInfo,
389                              OCProvisionResultCB resultCallback)
390 {
391     return SRPGetACLResource(ctx, selectedDeviceInfo, resultCallback);
392 }
393
394
395 OCStackResult OCReadTrustCertChain(uint16_t credId, uint8_t **trustCertChain,
396                                      size_t *chainSize)
397 {
398     return SRPReadTrustCertChain(credId, trustCertChain, chainSize);
399 }
400 /**
401  * function to provision credential to devices.
402  *
403  * @param[in] ctx Application context would be returned in result callback.
404  * @param[in] type Type of credentials to be provisioned to the device.
405  * @param[in] pDev1 Pointer to OCProvisionDev_t instance,respresenting resource to be provsioned.
406    @param[in] pDev2 Pointer to OCProvisionDev_t instance,respresenting resource to be provsioned.
407  * @param[in] resultCallback callback provided by API user, callback will be called when
408  *            provisioning request recieves a response from first resource server.
409  * @return  OC_STACK_OK in case of success and other value otherwise.
410  */
411 OCStackResult OCProvisionCredentials(void *ctx, OicSecCredType_t type, size_t keySize,
412                                       const OCProvisionDev_t *pDev1,
413                                       const OCProvisionDev_t *pDev2,
414                                       OCProvisionResultCB resultCallback)
415 {
416     return SRPProvisionCredentials(ctx, type, keySize,
417                                       pDev1, pDev2, resultCallback);
418
419 }
420
421 /**
422  * this function sends Direct-Pairing Configuration to a device.
423  *
424  * @param[in] ctx Application context would be returned in result callback.
425  * @param[in] selectedDeviceInfo Selected target device.
426  * @param[in] pconf PCONF pointer.
427  * @param[in] resultCallback callback provided by API user, callback will be called when provisioning
428               request recieves a response from resource server.
429  * @return  OC_STACK_OK in case of success and other value otherwise.
430  */
431 OCStackResult OCProvisionDirectPairing(void* ctx, const OCProvisionDev_t *selectedDeviceInfo, OicSecPconf_t *pconf,
432                              OCProvisionResultCB resultCallback)
433 {
434     return SRPProvisionDirectPairing(ctx, selectedDeviceInfo, pconf, resultCallback);
435 }
436
437 #ifdef MULTIPLE_OWNER
438 static void AddPreconfPinOxMCB(void* ctx, size_t nOfRes, OCProvisionResult_t *arr, bool hasError)
439 {
440     ProvPreconfPINCtx_t* provCtx = (ProvPreconfPINCtx_t*)ctx;
441     if(provCtx)
442     {
443         OCStackResult res = MOTProvisionPreconfigPIN(provCtx->ctx, provCtx->devInfo, provCtx->pin, provCtx->pinLen, provCtx->resultCallback);
444         if(OC_STACK_OK != res)
445         {
446             arr->res = res;
447             provCtx->resultCallback(provCtx->ctx, nOfRes, arr, true);
448         }
449     }
450 }
451
452 OCStackResult OCProvisionPreconfigPin(void *ctx,
453                                       OCProvisionDev_t *targetDeviceInfo,
454                                       const char *preconfigPin,
455                                       size_t preconfigPinLen,
456                                       OCProvisionResultCB resultCallback)
457 {
458     if( NULL == targetDeviceInfo )
459     {
460         return OC_STACK_INVALID_PARAM;
461     }
462     if (NULL == resultCallback)
463     {
464         OIC_LOG(INFO, TAG, "OCProvisionPreconfigPinCredential : NULL Callback");
465         return OC_STACK_INVALID_CALLBACK;
466     }
467
468     ProvPreconfPINCtx_t* provCtx = (ProvPreconfPINCtx_t*)OICCalloc(1, sizeof(ProvPreconfPINCtx_t));
469     if(NULL == provCtx)
470     {
471         return OC_STACK_NO_MEMORY;
472     }
473     provCtx->ctx = ctx;
474     provCtx->devInfo = targetDeviceInfo;
475     provCtx->pin = preconfigPin;
476     provCtx->pinLen = preconfigPinLen;
477     provCtx->resultCallback = resultCallback;
478     /*
479      * First of all, update OxMs to support preconfigured PIN OxM.
480      * In case of Preconfigured PIN OxM already supported on the server side,
481      * MOTAddMOTMethod API will be send POST Cred request.
482      * In case of Preconfigure PIN OxM not exist on the server side,
483      * the MOTAddMOTMethod API will be send POST doxm request to update OxMs and then send POST Cred request.
484      */
485     return MOTAddMOTMethod((void*)provCtx, targetDeviceInfo, OIC_PRECONFIG_PIN, AddPreconfPinOxMCB);
486 }
487 #endif //MULTIPLE_OWNER
488
489 /*
490 * Function to unlink devices.
491 * This function will remove the credential & relationship between the two devices.
492 *
493 * @param[in] ctx Application context would be returned in result callback
494 * @param[in] pTargetDev1 first device information to be unlinked.
495 * @param[in] pTargetDev2 second device information to be unlinked.
496 * @param[in] resultCallback callback provided by API user, callback will be called when
497 *            device unlink is finished.
498  * @return  OC_STACK_OK in case of success and other value otherwise.
499 */
500 OCStackResult OCUnlinkDevices(void* ctx,
501                               const OCProvisionDev_t* pTargetDev1,
502                               const OCProvisionDev_t* pTargetDev2,
503                               OCProvisionResultCB resultCallback)
504 {
505     OIC_LOG(INFO, TAG, "IN OCUnlinkDevices");
506     OCUuidList_t* idList = NULL;
507     size_t numOfDev = 0;
508
509     if (!pTargetDev1 || !pTargetDev2 || !pTargetDev1->doxm || !pTargetDev2->doxm)
510     {
511         OIC_LOG(ERROR, TAG, "OCUnlinkDevices : NULL parameters");
512         return OC_STACK_INVALID_PARAM;
513     }
514     if (!resultCallback)
515     {
516         OIC_LOG(INFO, TAG, "OCUnlinkDevices : NULL Callback");
517         return OC_STACK_INVALID_CALLBACK;
518     }
519     if (0 == memcmp(&pTargetDev1->doxm->deviceID, &pTargetDev2->doxm->deviceID, sizeof(OicUuid_t)))
520     {
521         OIC_LOG(INFO, TAG, "OCUnlinkDevices : Same device ID");
522         return OC_STACK_INVALID_PARAM;
523     }
524
525     // Get linked devices with the first device.
526     OCStackResult res = PDMGetLinkedDevices(&(pTargetDev1->doxm->deviceID), &idList, &numOfDev);
527     if (OC_STACK_OK != res)
528     {
529         OIC_LOG(ERROR, TAG, "OCUnlinkDevices : PDMgetOwnedDevices failed");
530         goto error;
531     }
532     if (1 > numOfDev)
533     {
534         OIC_LOG(DEBUG, TAG, "OCUnlinkDevices : Can not find linked devices");
535         res = OC_STACK_INVALID_PARAM; // Input devices are not linked, No request is made
536         goto error;
537     }
538
539     // Check the linked devices contains the second device. If yes send credential DELETE request.
540     OCUuidList_t* curDev = idList;
541     while (NULL != curDev)
542     {
543         if (memcmp(pTargetDev2->doxm->deviceID.id, curDev->dev.id, sizeof(curDev->dev.id)) == 0)
544         {
545             res = SRPUnlinkDevices(ctx, pTargetDev1, pTargetDev2, resultCallback);
546             if (OC_STACK_OK != res)
547             {
548                 OIC_LOG(ERROR, TAG, "OCUnlinkDevices : Failed to unlink devices.");
549             }
550             goto error;
551         }
552         curDev = curDev->next;
553     }
554     OIC_LOG(DEBUG, TAG, "No matched pair found from provisioning database");
555     res = OC_STACK_INVALID_PARAM; // Input devices are not linked, No request is made
556
557 error:
558     OIC_LOG(INFO, TAG, "OUT OCUnlinkDevices");
559
560     PDMDestoryOicUuidLinkList(idList);
561     return res;
562 }
563
564 static OCStackResult RemoveDeviceInfoFromLocal(const OCProvisionDev_t* pTargetDev)
565 {
566     // Remove credential of revoked device from SVR database
567     OCStackResult res = OC_STACK_ERROR;
568     const OicSecCred_t *cred = NULL;
569
570     OIC_LOG(DEBUG, TAG, "IN RemoveDeviceInfoFromLocal");
571     cred = GetCredResourceData(&pTargetDev->doxm->deviceID);
572     if (NULL != cred)
573     {
574         res = RemoveCredential(&cred->subject);
575         if (res != OC_STACK_RESOURCE_DELETED)
576         {
577             OIC_LOG(ERROR, TAG, "RemoveDeviceInfoFromLocal : Failed to remove credential.");
578             goto error;
579         }
580     }
581     /**
582      * Change the device status as stale status.
583      * If all request are successed, this device information will be deleted.
584      */
585     res = PDMSetDeviceState(&pTargetDev->doxm->deviceID, PDM_DEVICE_STALE);
586     if (res != OC_STACK_OK)
587     {
588         OIC_LOG(WARNING, TAG, "OCRemoveDevice : Failed to set device status as stale");
589     }
590
591     // TODO: We need to add new mechanism to clean up the stale state of the device.
592
593     // Close the DTLS session of the removed device.
594     CAEndpoint_t *endpoint = (CAEndpoint_t *)&pTargetDev->endpoint;
595     endpoint->port = pTargetDev->securePort;
596     CAResult_t caResult = CAcloseSslSession(endpoint);
597     if(CA_STATUS_OK != caResult)
598     {
599         OIC_LOG_V(WARNING, TAG, "OCRemoveDevice : Failed to close DTLS session : %d", caResult);
600     }
601
602     OIC_LOG(DEBUG, TAG, "OUT RemoveDeviceInfoFromLocal");
603 error:
604     return res;
605 }
606
607 /*
608 * Function to device revocation
609 * This function will remove credential of target device from all devices in subnet.
610 *
611 * @param[in] ctx Application context would be returned in result callback
612 * @param[in] waitTimeForOwnedDeviceDiscovery Maximum wait time for owned device discovery.(seconds)
613 * @param[in] pTargetDev Device information to be revoked.
614 * @param[in] resultCallback callback provided by API user, callback will be called when
615 *            credential revocation is finished.
616  * @return  OC_STACK_OK in case of success and other value otherwise.
617 */
618 OCStackResult OCRemoveDevice(void* ctx, unsigned short waitTimeForOwnedDeviceDiscovery,
619                             const OCProvisionDev_t* pTargetDev,
620                             OCProvisionResultCB resultCallback)
621 {
622     OIC_LOG(INFO, TAG, "IN OCRemoveDevice");
623     OCStackResult res = OC_STACK_ERROR;
624     if (!pTargetDev || 0 == waitTimeForOwnedDeviceDiscovery)
625     {
626         OIC_LOG(INFO, TAG, "OCRemoveDevice : Invalied parameters");
627         return OC_STACK_INVALID_PARAM;
628     }
629     if (!resultCallback)
630     {
631         OIC_LOG(INFO, TAG, "OCRemoveDevice : NULL Callback");
632         return OC_STACK_INVALID_CALLBACK;
633     }
634
635     // Send DELETE requests to linked devices
636     OCStackResult resReq = OC_STACK_ERROR; // Check that we have to wait callback or not.
637     resReq = SRPRemoveDevice(ctx, waitTimeForOwnedDeviceDiscovery, pTargetDev, resultCallback);
638     if (OC_STACK_OK != resReq)
639     {
640         if (OC_STACK_CONTINUE == resReq)
641         {
642             OIC_LOG(DEBUG, TAG, "OCRemoveDevice : Revoked device has no linked device except PT.");
643         }
644         else
645         {
646             OIC_LOG(ERROR, TAG, "OCRemoveDevice : Failed to invoke SRPRemoveDevice");
647             res = resReq;
648             goto error;
649         }
650     }
651
652     res = RemoveDeviceInfoFromLocal(pTargetDev);
653     if(OC_STACK_OK != res)
654     {
655         OIC_LOG(ERROR, TAG, "Filed to remove the device information from local.");
656         goto error;
657     }
658
659     if(OC_STACK_CONTINUE == resReq)
660     {
661         /**
662           * If there is no linked device, PM does not send any request.
663           * So we should directly invoke the result callback to inform the result of OCRemoveDevice.
664           */
665         if(resultCallback)
666         {
667             resultCallback(ctx, 0, NULL, false);
668         }
669         res = OC_STACK_OK;
670     }
671
672 error:
673     OIC_LOG(INFO, TAG, "OUT OCRemoveDevice");
674     return res;
675 }
676
677 /*
678 * Function to device revocation
679 * This function will remove credential of target device from all devices in subnet.
680 *
681 * @param[in] ctx Application context would be returned in result callback
682 * @param[in] waitTimeForOwnedDeviceDiscovery Maximum wait time for owned device discovery.(seconds)
683 * @param[in] pTargetDev Device information to be revoked.
684 * @param[in] resultCallback callback provided by API user, callback will be called when
685 *            credential revocation is finished.
686  * @return  OC_STACK_OK in case of success and other value otherwise.
687 */
688 OCStackResult OCRemoveDeviceWithUuid(void* ctx, unsigned short waitTimeForOwnedDeviceDiscovery,
689                             const OicUuid_t* pTargetUuid,
690                             OCProvisionResultCB resultCallback)
691 {
692     OIC_LOG(INFO, TAG, "IN OCRemoveDeviceWithUuid");
693
694     OCStackResult res = OC_STACK_ERROR;
695     OCProvisionDev_t* pTargetDev = NULL;
696     bool discoverdFlag = false;
697     OCProvisionDev_t* pOwnedDevList = NULL;
698     OCStackResult resReq = OC_STACK_CONTINUE;
699
700     if (!pTargetUuid || 0 == waitTimeForOwnedDeviceDiscovery)
701     {
702         OIC_LOG(INFO, TAG, "OCRemoveDeviceWithUuid : Invalied parameters");
703         return OC_STACK_INVALID_PARAM;
704     }
705     if (!resultCallback)
706     {
707         OIC_LOG(INFO, TAG, "OCRemoveDeviceWithUuid : NULL Callback");
708         return OC_STACK_INVALID_CALLBACK;
709     }
710
711     char* strUuid = NULL;
712     if(OC_STACK_OK != ConvertUuidToStr(pTargetUuid, &strUuid))
713     {
714         OIC_LOG(WARNING, TAG, "Failed to covert UUID to String.");
715         goto error;
716     }
717
718     //Generate OCProvisionDev_t instance to use when target device not found on the network.
719     //In this case, the device id required only.
720     pTargetDev = (OCProvisionDev_t*)OICCalloc(1, sizeof(OCProvisionDev_t));
721     if(NULL == pTargetDev)
722     {
723         OIC_LOG(ERROR, TAG, "Failed to allocate memory.");
724         res = OC_STACK_NO_MEMORY;
725         goto error;
726     }
727     pTargetDev->doxm = (OicSecDoxm_t*)OICCalloc(1, sizeof(OicSecDoxm_t));
728     if(NULL == pTargetDev->doxm)
729     {
730         OIC_LOG(ERROR, TAG, "Failed to allocate memory.");
731         res = OC_STACK_NO_MEMORY;
732         goto error;
733     }
734     memcpy(pTargetDev->doxm->deviceID.id, pTargetUuid->id, sizeof(pTargetUuid->id));
735
736     OCUuidList_t* linkedDevices = NULL;
737     size_t numOfLinkedDevices = 0;
738     res = PDMGetLinkedDevices(pTargetUuid, &linkedDevices, &numOfLinkedDevices);
739     if(OC_STACK_OK != res)
740     {
741         OIC_LOG(ERROR, TAG, "Error in PDMGetLinkedDevices");
742         goto error;
743     }
744     PDMDestoryOicUuidLinkList(linkedDevices);
745
746     //If there is no linked devices, device revocation step can be skipped.
747     if(0 != numOfLinkedDevices)
748     {
749         OIC_LOG_V(INFO, TAG, "[%s] linked with other devices.", strUuid);
750         //2. Find owned device from the network
751         res = PMDeviceDiscovery(waitTimeForOwnedDeviceDiscovery, true, &pOwnedDevList);
752         if (OC_STACK_OK != res)
753         {
754             OIC_LOG(ERROR, TAG, "OCRemoveDeviceWithUuid : Failed to PMDeviceDiscovery");
755             goto error;
756         }
757
758         OCProvisionDev_t* tempDev = NULL;
759         LL_FOREACH(pOwnedDevList, tempDev)
760         {
761             if(memcmp(&tempDev->doxm->deviceID.id, pTargetUuid->id, sizeof(pTargetUuid->id)) == 0)
762             {
763                 break;
764             }
765         }
766
767         if(NULL == tempDev)
768         {
769             OIC_LOG_V(WARNING, TAG, "Can not find [%s] on the network.", strUuid);
770             OIC_LOG_V(WARNING, TAG, "[%s]'s information will be deleted from local and other devices.", strUuid);
771         }
772         else
773         {
774             OICFree(pTargetDev->doxm);
775             OICFree(pTargetDev);
776             pTargetDev = tempDev;
777             discoverdFlag = true;
778             OIC_LOG_V(INFO, TAG, "[%s] is dectected on the network.", strUuid);
779         }
780
781         OIC_LOG_V(INFO, TAG, "Trying [%s] revocation.", strUuid);
782
783         // Send DELETE requests to linked devices
784         resReq = SRPRemoveDeviceWithoutDiscovery(ctx, pOwnedDevList, pTargetDev, resultCallback);
785         if (OC_STACK_OK != resReq)
786         {
787             if (OC_STACK_CONTINUE == resReq)
788             {
789                 OIC_LOG(INFO, TAG, "OCRemoveDeviceWithUuid : Revoked device has no linked device except PT.");
790             }
791             else
792             {
793                 OIC_LOG(ERROR, TAG, "OCRemoveDeviceWithUuid : Failed to invoke SRPRemoveDevice");
794                 res = resReq;
795                 goto error;
796             }
797         }
798     }
799     else
800     {
801         OIC_LOG_V(INFO, TAG, "There is no linked devices with [%s]", strUuid);
802         OIC_LOG(INFO, TAG, "Device discovery and SRPRemoveDevice will be skipped.");
803     }
804
805     res = RemoveDeviceInfoFromLocal(pTargetDev);
806     if(OC_STACK_OK != res)
807     {
808         OIC_LOG(ERROR, TAG, "OCRemoveDeviceWithUuid : Filed to remove the device information from local.");
809         goto error;
810     }
811
812     if(OC_STACK_CONTINUE == resReq)
813     {
814         /**
815           * If there is no linked device, PM does not send any request.
816           * So we should directly invoke the result callback to inform the result of OCRemoveDevice.
817           */
818         if(resultCallback)
819         {
820             resultCallback(ctx, 0, NULL, false);
821         }
822         res = OC_STACK_OK;
823     }
824
825 error:
826     OICFree(strUuid);
827     PMDeleteDeviceList(pOwnedDevList);
828     if(pTargetDev && false == discoverdFlag)
829     {
830         OICFree(pTargetDev->doxm);
831         OICFree(pTargetDev);
832     }
833     OIC_LOG(INFO, TAG, "OUT OCRemoveDeviceWithUuid");
834     return res;
835 }
836
837 /*
838  * Function to reset the target device.
839  * This function will remove credential and ACL of target device from all devices in subnet.
840  *
841  * @param[in] ctx Application context would be returned in result callback
842  * @param[in] waitTimeForOwnedDeviceDiscovery Maximum wait time for owned device discovery.(seconds)
843  * @param[in] pTargetDev Device information to be revoked.
844  * @param[in] resultCallback callback provided by API user, callback will be called when
845  *            credential revocation is finished.
846  * @return  OC_STACK_OK in case of success and other value otherwise.
847  */
848 OCStackResult OCResetDevice(void* ctx, unsigned short waitTimeForOwnedDeviceDiscovery,
849                             const OCProvisionDev_t* pTargetDev,
850                             OCProvisionResultCB resultCallback)
851 {
852     OIC_LOG(INFO, TAG, "IN OCResetDevice");
853     OCStackResult res = OC_STACK_ERROR;
854     if (!pTargetDev || 0 == waitTimeForOwnedDeviceDiscovery)
855     {
856         OIC_LOG(INFO, TAG, "OCResetDevice : Invalid parameters");
857         return OC_STACK_INVALID_PARAM;
858     }
859     if (!resultCallback)
860     {
861         OIC_LOG(INFO, TAG, "OCResetDevice : NULL Callback");
862         return OC_STACK_INVALID_CALLBACK;
863     }
864
865     // Send DELETE requests to linked devices
866     res = SRPSyncDevice(ctx, waitTimeForOwnedDeviceDiscovery, pTargetDev, resultCallback);
867     if (OC_STACK_CONTINUE == res)
868     {
869         OIC_LOG(DEBUG, TAG, "OCResetDevice : Target device has no linked device except PT.");
870         if(resultCallback)
871         {
872             resultCallback(ctx, 0, NULL, false);
873         }
874         SRPResetDevice(pTargetDev, resultCallback);
875         res = OC_STACK_OK;
876     }
877     else if(OC_STACK_OK != res)
878     {
879         OIC_LOG(ERROR, TAG, "OCResetDevice : Failed to invoke SRPSyncDevice");
880     }
881     OIC_LOG(INFO, TAG, "OUT OCResetDevice");
882     return res;
883 }
884
885 /**
886  * This function resets SVR DB to its factory setting.
887  *
888  * @return OC_STACK_OK in case of successful reset and other value otherwise.
889  */
890 OCStackResult OCResetSVRDB(void)
891 {
892     return ResetSecureResourceInPS();
893 }
894
895 /**
896  * This function configures SVR DB as self-ownership.
897  *
898  *@return OC_STACK_OK in case of successful configue and other value otherwise.
899  */
900 OCStackResult OCConfigSelfOwnership(void)
901 {
902     return ConfigSelfOwnership();
903 }
904
905 /**
906  * Internal Function to update result in link result array.
907  */
908 static void UpdateLinkResults(Linkdata_t *link, int device, OCStackResult stackresult)
909 {
910
911     OIC_LOG_V(INFO,TAG,"value of link->currentCountResults is %d",link->currentCountResults);
912     if (1 == device)
913     {
914         memcpy(link->resArr[(link->currentCountResults)].deviceId.id, link->pDev1->doxm->deviceID.id,UUID_LENGTH);
915     }
916     else
917     {
918         memcpy(link->resArr[(link->currentCountResults)].deviceId.id, link->pDev2->doxm->deviceID.id,UUID_LENGTH);
919     }
920     link->resArr[(link->currentCountResults)].res = stackresult;
921     ++(link->currentCountResults);
922
923 }
924
925 /**
926  * Callback to handle ACL provisioning for device 2.
927  */
928 static void AclProv2CB(void* ctx, size_t nOfRes, OCProvisionResult_t *arr, bool hasError)
929 {
930
931     if (NULL == ctx)
932     {
933         OIC_LOG(ERROR,TAG,"Context is Null in ACLProv 2");
934         return;
935     }
936     (void)nOfRes;
937     Linkdata_t *link = (Linkdata_t*)ctx;
938     OCProvisionResultCB resultCallback = link->resultCallback;
939
940
941     if (hasError)
942     {
943         UpdateLinkResults(link, 2,arr[0].res);
944         OIC_LOG(ERROR,TAG,"Error occured while ACL provisioning device 1");
945         ((OCProvisionResultCB)(resultCallback))(link->ctx, link->currentCountResults,
946                                                 link->resArr,
947                                                 true);
948         OICFree(link->resArr);
949         OICFree(link) ;
950         return;
951     }
952     UpdateLinkResults(link, 2, arr[0].res);
953    ((OCProvisionResultCB)(resultCallback))(link->ctx, link->currentCountResults,
954                                            link->resArr,
955                                            false);
956     OICFree(link->resArr);
957     OICFree(link);
958     return;
959 }
960
961 /**
962  * Callback to handle ACL provisioning for device 1
963  */
964 static void AclProv1CB(void* ctx, size_t nOfRes, OCProvisionResult_t *arr, bool hasError)
965 {
966
967     if (NULL == ctx)
968     {
969         OIC_LOG(ERROR,TAG,"Context is Null in ACLProv1");
970         return;
971     }
972     (void)nOfRes;
973     Linkdata_t *link = (Linkdata_t*)ctx;
974     OCProvisionResultCB resultCallback = link->resultCallback;
975
976     if (hasError)
977     {
978         OIC_LOG(ERROR,TAG,"Error occured while ACL provisioning device 1");
979         UpdateLinkResults(link, 1, arr[0].res);
980         ((OCProvisionResultCB)(resultCallback))(link->ctx, link->currentCountResults,
981                                                 link->resArr,
982                                                 true);
983         OICFree(link->resArr);
984         OICFree(link);
985         return;
986     }
987     UpdateLinkResults(link, 1, arr[0].res);
988     if (NULL != link->pDev2Acl)
989     {
990         OCStackResult res =  SRPProvisionACL(ctx, link->pDev2, link->pDev2Acl, &AclProv2CB);
991         if (OC_STACK_OK!=res)
992         {
993              UpdateLinkResults(link, 2, res);
994              ((OCProvisionResultCB)(resultCallback))(link->ctx, link->currentCountResults,
995                                                      link->resArr,
996                                                      true);
997
998         }
999     }
1000     else
1001     {
1002         ((OCProvisionResultCB)(resultCallback))(link->ctx, link->currentCountResults,
1003                                                 link->resArr,
1004                                                 false);
1005         OICFree(link->resArr);
1006         OICFree(link);
1007     }
1008
1009     return;
1010 }
1011
1012 /**
1013  * Callback to handle credential provisioning.
1014  */
1015 static void ProvisionCredsCB(void* ctx, size_t nOfRes, OCProvisionResult_t *arr, bool hasError)
1016 {
1017     if (NULL == ctx)
1018     {
1019         OIC_LOG(ERROR,TAG,"Error occured while credential provisioning");
1020         return;
1021     }
1022     Linkdata_t *link = (Linkdata_t*)ctx;
1023     OCProvisionResultCB resultCallback = link->resultCallback;
1024     OIC_LOG_V(INFO, TAG, "has error returned %d",hasError);
1025     UpdateLinkResults(link, 1, arr[0].res);
1026     UpdateLinkResults(link, 2, arr[1].res);
1027     if (hasError)
1028     {
1029         OIC_LOG(ERROR,TAG,"Error occured while credential provisioning");
1030         ((OCProvisionResultCB)(resultCallback))(link->ctx, nOfRes,
1031                                                 link->resArr,
1032                                                 true);
1033          OICFree(link->resArr);
1034          OICFree(link);
1035          return;
1036     }
1037     if (NULL != link->pDev1Acl)
1038     {
1039
1040         OCStackResult res =  SRPProvisionACL(ctx, link->pDev1, link->pDev1Acl, &AclProv1CB);
1041         if (OC_STACK_OK!=res)
1042         {
1043              OIC_LOG(ERROR, TAG, "Error while provisioning ACL for device 1");
1044              UpdateLinkResults(link, 1, res);
1045              ((OCProvisionResultCB)(resultCallback))(link->ctx, link->currentCountResults,
1046                                                      link->resArr,
1047                                                      true);
1048               OICFree(link->resArr);
1049               OICFree(link);
1050         }
1051     }
1052     else if (NULL!=link->pDev2Acl)
1053     {
1054         OIC_LOG(ERROR, TAG, "ACL for device 1 is NULL");
1055         OCStackResult res =  SRPProvisionACL(ctx, link->pDev2, link->pDev2Acl, &AclProv2CB);
1056         if (OC_STACK_OK!=res)
1057         {
1058              OIC_LOG(ERROR, TAG, "Error while provisioning ACL for device 2");
1059               UpdateLinkResults(link, 2, res);
1060              ((OCProvisionResultCB)(resultCallback))(link->ctx, link->currentCountResults,
1061                                                      link->resArr,
1062                                                      true);
1063               OICFree(link->resArr);
1064               OICFree(link);
1065         }
1066     }
1067     else
1068     {
1069         OIC_LOG(INFO, TAG, "ACLs of both devices are NULL");
1070         ((OCProvisionResultCB)(resultCallback))(link->ctx, link->currentCountResults,
1071                                                 link->resArr,
1072                                                 false);
1073         OICFree(link->resArr);
1074         OICFree(link);
1075     }
1076     return;
1077 }
1078 /**
1079  * function to provision credentials between two devices and ACLs for the devices who act as a server.
1080  *
1081  * @param[in] ctx Application context would be returned in result callback.
1082  * @param[in] type Type of credentials to be provisioned to the device.
1083  * @param[in] pDev1 Pointer to OCProvisionDev_t instance,respresenting resource to be provsioned.
1084  * @param[in] acl ACL for device 1. If this is not required set NULL.
1085  * @param[in] pDev2 Pointer to OCProvisionDev_t instance,respresenting resource to be provsioned.
1086  * @param[in] acl ACL for device 2. If this is not required set NULL.
1087  * @param[in] resultCallback callback provided by API user, callback will be called when
1088  *            provisioning request recieves a response from first resource server.
1089  * @return  OC_STACK_OK in case of success and other value otherwise.
1090  */
1091 OCStackResult OCProvisionPairwiseDevices(void* ctx, OicSecCredType_t type, size_t keySize,
1092                                          const OCProvisionDev_t *pDev1, OicSecAcl_t *pDev1Acl,
1093                                          const OCProvisionDev_t *pDev2, OicSecAcl_t *pDev2Acl,
1094                                          OCProvisionResultCB resultCallback)
1095 {
1096
1097     if (!pDev1 || !pDev2 || !pDev1->doxm || !pDev2->doxm)
1098     {
1099         OIC_LOG(ERROR, TAG, "OCProvisionPairwiseDevices : Invalid parameters");
1100         return OC_STACK_INVALID_PARAM;
1101     }
1102     if (!resultCallback)
1103     {
1104         OIC_LOG(INFO, TAG, "OCProvisionPairwiseDevices : NULL Callback");
1105         return OC_STACK_INVALID_CALLBACK;
1106     }
1107     if (!(keySize == OWNER_PSK_LENGTH_128 || keySize == OWNER_PSK_LENGTH_256))
1108     {
1109         OIC_LOG(INFO, TAG, "OCProvisionPairwiseDevices : Invalid key size");
1110         return OC_STACK_INVALID_PARAM;
1111     }
1112     if (0 == memcmp(&pDev1->doxm->deviceID, &pDev2->doxm->deviceID, sizeof(OicUuid_t)))
1113     {
1114         OIC_LOG(INFO, TAG, "OCProvisionPairwiseDevices : Same device ID");
1115         return OC_STACK_INVALID_PARAM;
1116     }
1117
1118     OIC_LOG(DEBUG, TAG, "Checking link in DB");
1119     bool linkExists = true;
1120     OCStackResult res = PDMIsLinkExists(&pDev1->doxm->deviceID, &pDev2->doxm->deviceID, &linkExists);
1121     if(res != OC_STACK_OK)
1122     {
1123         OIC_LOG(ERROR, TAG, "Internal Error Occured");
1124         return res;
1125     }
1126     if (linkExists)
1127     {
1128         OIC_LOG(ERROR, TAG, "Link already exists");
1129         return OC_STACK_INVALID_PARAM;
1130     }
1131
1132     int noOfResults = 2; // Initial Value
1133     if (NULL != pDev1Acl)
1134     {
1135         ++noOfResults;
1136     }
1137     if (NULL != pDev2Acl)
1138     {
1139        ++noOfResults;
1140     }
1141     Linkdata_t *link = (Linkdata_t*) OICMalloc(sizeof(Linkdata_t));
1142     if (!link)
1143     {
1144         OIC_LOG(ERROR, TAG, "Failed to memory allocation");
1145         return OC_STACK_NO_MEMORY;
1146     }
1147     OIC_LOG_V(INFO,TAG, "Maximum no od results %d",noOfResults);
1148
1149     link->pDev1 = pDev1;
1150     link->pDev1Acl = pDev1Acl;
1151     link->pDev2 = pDev2;
1152     link->pDev2Acl = pDev2Acl;
1153     link->ctx = ctx;
1154     // 1 call for each device for credential provisioning. implict call by SRPProvisioning credential
1155     // 1 call for ACL provisioning for device 1 and 1 call for ACL provisioning for device 2.
1156     link->numOfResults = noOfResults;
1157     link->resultCallback = resultCallback;
1158     link->currentCountResults = 0;
1159     link->resArr = (OCProvisionResult_t*) OICMalloc(sizeof(OCProvisionResult_t)*noOfResults);
1160     res = SRPProvisionCredentials(link, type, keySize,
1161                                      pDev1, pDev2, &ProvisionCredsCB);
1162     if (res != OC_STACK_OK)
1163     {
1164         OICFree(link->resArr);
1165         OICFree(link);
1166     }
1167     return res;
1168
1169 }
1170
1171 OCStackResult OCGetDevInfoFromNetwork(unsigned short waittime,
1172                                        OCProvisionDev_t** pOwnedDevList,
1173                                        OCProvisionDev_t** pUnownedDevList)
1174 {
1175     //TODO will be replaced by more efficient logic
1176     if (pOwnedDevList == NULL || *pOwnedDevList != NULL || pUnownedDevList == NULL
1177          || *pUnownedDevList != NULL || 0 == waittime)
1178     {
1179         return OC_STACK_INVALID_PARAM;
1180     }
1181
1182     // Code for unowned discovery
1183     OCProvisionDev_t *unownedDevice = NULL;
1184     OCStackResult res =  OCDiscoverUnownedDevices(waittime/2, &unownedDevice);
1185     if (OC_STACK_OK != res)
1186     {
1187         OIC_LOG(ERROR,TAG, "Error in unowned discovery");
1188         return res;
1189     }
1190
1191     // Code for owned discovery
1192     OCProvisionDev_t *ownedDevice = NULL;
1193     res =  OCDiscoverOwnedDevices(waittime/2, &ownedDevice);
1194     if (OC_STACK_OK != res)
1195     {
1196         OIC_LOG(ERROR,TAG, "Error in owned discovery");
1197         PMDeleteDeviceList(unownedDevice);
1198         return res;
1199     }
1200
1201     // Code to get list of all the owned devices.
1202     OCUuidList_t *uuidList = NULL;
1203     size_t numOfDevices = 0;
1204     res =  PDMGetOwnedDevices(&uuidList, &numOfDevices);
1205     if (OC_STACK_OK != res)
1206     {
1207         OIC_LOG(ERROR, TAG, "Error while getting info from DB");
1208         PMDeleteDeviceList(unownedDevice);
1209         PMDeleteDeviceList(ownedDevice);
1210         return res;
1211     }
1212
1213     // Code to compare devices in unowned list and deviceid from DB
1214     // (In case of hard reset of the device)
1215     OCProvisionDev_t* pUnownedList = unownedDevice;
1216     while (pUnownedList && uuidList)
1217     {
1218         OCUuidList_t *tmp1 = NULL,*tmp2=NULL;
1219         LL_FOREACH_SAFE(uuidList, tmp1, tmp2)
1220         {
1221             if(0 == memcmp(tmp1->dev.id, pUnownedList->doxm->deviceID.id,
1222                             sizeof(pUnownedList->doxm->deviceID.id)))
1223             {
1224                 OIC_LOG_V(INFO, TAG, "OCGetDevInfoFromNetwork : \
1225                             Removing device id = %s in PDM and dat.", pUnownedList->doxm->deviceID.id);
1226                 if (OC_STACK_OK != PDMDeleteDevice(&pUnownedList->doxm->deviceID))
1227                 {
1228                     OIC_LOG(ERROR, TAG, "OCGetDevInfoFromNetwork : \
1229                             Failed to remove device in PDM.");
1230                 }
1231                 //remove the cred entry from dat file
1232                 if (OC_STACK_OK != RemoveDeviceInfoFromLocal(pUnownedList))
1233                 {
1234                     OIC_LOG(ERROR, TAG, "OCGetDevInfoFromNetwork : \
1235                             Failed to remove cred entry device in dat file.");
1236                 }
1237                 LL_DELETE(uuidList, tmp1);
1238                 OICFree(tmp1);
1239             }
1240         }
1241         pUnownedList = pUnownedList->next;
1242     }
1243     // Code to compare devices in owned list and deviceid from DB.
1244     OCProvisionDev_t* pCurDev = ownedDevice;
1245     size_t deleteCnt = 0;
1246     while (pCurDev)
1247     {
1248         if(true == PMDeleteFromUUIDList(&uuidList, &pCurDev->doxm->deviceID))
1249         {
1250             deleteCnt++;
1251         }
1252         pCurDev = pCurDev->next;
1253     }
1254     // If there is no remaind device in uuidList, we have to assign NULL to prevent free.
1255     if (deleteCnt == numOfDevices)
1256     {
1257         uuidList = NULL;
1258     }
1259     // Code to add information of the devices which are currently off in owned list.
1260     OCUuidList_t *powerOffDeviceList = uuidList;
1261     while (powerOffDeviceList)
1262     {
1263         OCProvisionDev_t *ptr = (OCProvisionDev_t *)OICCalloc(1, sizeof (OCProvisionDev_t));
1264         if (NULL == ptr)
1265         {
1266             OIC_LOG(ERROR,TAG,"Fail to allocate memory");
1267             PMDeleteDeviceList(unownedDevice);
1268             PMDeleteDeviceList(ownedDevice);
1269             OCDeleteUuidList(uuidList);
1270             return OC_STACK_NO_MEMORY;
1271         }
1272
1273         ptr->doxm = (OicSecDoxm_t*)OICCalloc(1, sizeof(OicSecDoxm_t));
1274         if (NULL == ptr->doxm)
1275         {
1276             OIC_LOG(ERROR,TAG,"Fail to allocate memory");
1277             PMDeleteDeviceList(unownedDevice);
1278             PMDeleteDeviceList(ownedDevice);
1279             OCDeleteUuidList(uuidList);
1280             OICFree(ptr);
1281             return OC_STACK_NO_MEMORY;
1282         }
1283
1284         memcpy(ptr->doxm->deviceID.id, powerOffDeviceList->dev.id, sizeof(ptr->doxm->deviceID.id));
1285
1286         ptr->devStatus = DEV_STATUS_OFF;
1287         LL_PREPEND(ownedDevice, ptr);
1288         powerOffDeviceList = powerOffDeviceList->next;
1289
1290     }
1291     OCDeleteUuidList(uuidList);
1292     *pOwnedDevList = ownedDevice;
1293     *pUnownedDevList = unownedDevice;
1294     return OC_STACK_OK;
1295 }
1296
1297 OCStackResult OCGetLinkedStatus(const OicUuid_t* uuidOfDevice, OCUuidList_t** uuidList,
1298                                  size_t* numOfDevices)
1299 {
1300     return PDMGetLinkedDevices(uuidOfDevice, uuidList, numOfDevices);
1301 }
1302
1303 void OCDeleteUuidList(OCUuidList_t* pList)
1304 {
1305     PDMDestoryOicUuidLinkList(pList);
1306 }
1307
1308 /**
1309  * This function deletes ACL data.
1310  *
1311  * @param pAcl Pointer to OicSecAcl_t structure.
1312  */
1313 void OCDeleteACLList(OicSecAcl_t* pAcl)
1314 {
1315     DeleteACLList(pAcl);
1316 }
1317
1318 /**
1319  * This function deletes PDACL data.
1320  *
1321  * @param pPdAcl Pointer to OicSecPdAcl_t structure.
1322  */
1323 void OCDeletePdAclList(OicSecPdAcl_t* pPdAcl)
1324 {
1325     FreePdAclList(pPdAcl);
1326 }
1327
1328 #ifdef MULTIPLE_OWNER
1329 /**
1330  * API to update 'doxm.mom' to resource server.
1331  *
1332  * @param[in] targetDeviceInfo Selected target device.
1333  * @param[in] momType Mode of multiple ownership transfer (ref. oic.sec.mom)
1334  * @param[in] resultCallback callback provided by API user, callback will be called when
1335  *            POST 'mom' request recieves a response from resource server.
1336  * @return OC_STACK_OK in case of success and other value otherwise.
1337  */
1338 OCStackResult OCChangeMOTMode(void *ctx, const OCProvisionDev_t *targetDeviceInfo,
1339                             const OicSecMomType_t momType, OCProvisionResultCB resultCallback)
1340 {
1341     return MOTChangeMode(ctx, targetDeviceInfo, momType, resultCallback);
1342 }
1343
1344 /**
1345  * API to update 'doxm.oxmsel' to resource server.
1346  *
1347  * @param[in] targetDeviceInfo Selected target device.
1348   * @param[in] oxmSelValue Method of multiple ownership transfer (ref. oic.sec.oxm)
1349  * @param[in] resultCallback callback provided by API user, callback will be called when
1350  *            POST 'oxmsel' request recieves a response from resource server.
1351  * @return OC_STACK_OK in case of success and other value otherwise.
1352  */
1353 OCStackResult OCSelectMOTMethod(void *ctx, const OCProvisionDev_t *targetDeviceInfo,
1354                                  const OicSecOxm_t oxmSelValue, OCProvisionResultCB resultCallback)
1355 {
1356     return MOTSelectMOTMethod(ctx, targetDeviceInfo, oxmSelValue, resultCallback);
1357 }
1358 #endif //MULTIPLE_OWNER
1359
1360 /**
1361  * Function to select appropriate security provisioning method.
1362  *
1363  * @param[in] supportedMethods   Array of supported methods
1364  * @param[in] numberOfMethods   number of supported methods
1365  * @param[out]  selectedMethod         Selected methods
1366  * @param[in] ownerType type of owner device (SUPER_OWNER or SUB_OWNER)
1367  * @return  OC_STACK_OK on success
1368  */
1369 OCStackResult OCSelectOwnershipTransferMethod(const OicSecOxm_t *supportedMethods,
1370         size_t numberOfMethods, OicSecOxm_t *selectedMethod, OwnerType_t ownerType)
1371 {
1372     return OTMSelectOwnershipTransferMethod(supportedMethods, numberOfMethods,
1373                                             selectedMethod, ownerType);
1374 }
1375
1376 #if defined(__WITH_DTLS__) || defined(__WITH_TLS__)
1377 /**
1378  * function to provision Trust certificate chain to devices.
1379  *
1380  * @param[in] ctx Application context would be returned in result callback.
1381  * @param[in] type Type of credentials to be provisioned to the device.
1382  * @param[in] credId CredId of trust certificate chain to be provisioned to the device.
1383  * @param[in] selectedDeviceInfo Pointer to OCProvisionDev_t instance,respresenting resource to be provsioned.
1384  * @param[in] resultCallback callback provided by API user, callback will be called when
1385  *            provisioning request recieves a response from first resource server.
1386  * @return  OC_STACK_OK in case of success and other value otherwise.
1387  */
1388 OCStackResult OCProvisionTrustCertChain(void *ctx, OicSecCredType_t type, uint16_t credId,
1389                                       const OCProvisionDev_t *selectedDeviceInfo,
1390                                       OCProvisionResultCB resultCallback)
1391 {
1392     return SRPProvisionTrustCertChain(ctx, type, credId,
1393                                       selectedDeviceInfo, resultCallback);
1394 }
1395
1396 /**
1397  * function to save Trust certificate chain into Cred of SVR.
1398  *
1399  * @param[in] trustCertChain Trust certificate chain to be saved in Cred of SVR.
1400  * @param[in] chainSize Size of trust certificate chain to be saved in Cred of SVR
1401  * @param[in] encodingType Encoding type of trust certificate chain to be saved in Cred of SVR
1402  * @param[out] credId CredId of saved trust certificate chain in Cred of SVR.
1403  * @return  OC_STACK_OK in case of success and other value otherwise.
1404  */
1405 OCStackResult OCSaveTrustCertChain(uint8_t *trustCertChain, size_t chainSize,
1406                                     OicEncodingType_t encodingType, uint16_t *credId)
1407 {
1408     return SRPSaveTrustCertChain(trustCertChain, chainSize, encodingType, credId);
1409 }
1410
1411 /**
1412  * function to register notifier for Trustcertchain change.
1413  *
1414  * @param[in] ctx user context.
1415  * @param[in] TrustCertChainChangeCB notification callback fucntion.
1416  * @return    OC_STACK_OK in case of success and other value otherwise.
1417  */
1418 OCStackResult OCRegisterTrustCertChainNotifier(void *ctx, TrustCertChainChangeCB Callback)
1419 {
1420     return SRPRegisterTrustCertChainNotifier(ctx, Callback);
1421 }
1422
1423 /**
1424  * function to de-register notifier for Trustcertchain change.
1425  */
1426 void OCRemoveTrustCertChainNotifier()
1427 {
1428     SRPRemoveTrustCertChainNotifier();
1429 }
1430 #endif // __WITH_DTLS__ || __WITH_TLS__
1431