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