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