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