f4af64c3e5fb3eea2196b08b87276616c90e14cc
[iotivity.git] / resource / csdk / security / provisioning / src / secureresourceprovider.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 "iotivity_config.h"
21 #include <stdio.h>
22 #include <string.h>
23 #include <stdint.h>
24 #ifdef HAVE_UNISTD_H
25 #include <unistd.h>
26 #endif
27
28 #include "ocprovisioningmanager.h"
29 #include "secureresourceprovider.h"
30 #include "experimental/logger.h"
31 #include "oic_malloc.h"
32 #include "oic_string.h"
33 #include "aclresource.h"
34 #include "pstatresource.h"
35 #include "srmresourcestrings.h"
36 #include "credresource.h"
37 #include "spresource.h"
38 #include "csrresource.h"
39 #include "rolesresource.h"
40 #include "experimental/doxmresource.h"
41 #include "credentialgenerator.h"
42 #include "cainterface.h"
43 #include "oic_string.h"
44 #include "pmtypes.h"
45 #include "pmutility.h"
46 #include "srmutility.h"
47 #include "provisioningdatabasemanager.h"
48 #include "utlist.h"
49 #include "ocpayload.h"
50 #include "srmutility.h"
51 #include "certhelpers.h"
52 #include "ocstackinternal.h"
53
54 #ifdef __WITH_DTLS__
55 #include "crlresource.h"
56 #endif
57
58 #define TAG "OIC_SRPAPI"
59
60 trustCertChainContext_t g_trustCertChainNotifier;
61
62 /**
63  * Structure to carry credential data to callback.
64  */
65 typedef struct CredentialData
66 {
67     void *ctx;                                  /**< Pointer to user context.**/
68     const OCProvisionDev_t *deviceInfo[2];      /**< Array of pointers to OCProvisionDev_t.**/
69     OicSecCred_t *credInfo[2];                  /**< Array of pointers to OicSecCred_t.**/
70     int currIndex;                              /**< Index of current remote device.**/
71     OCProvisionResultCB resultCallback;         /**< Pointer to result callback.**/
72     OCProvisionResult_t *resArr;                /**< Result array.**/
73     int numOfResults;                           /**< Number of results in result array.**/
74     OicSecCredType_t type;                      /**< Type of credentials to be provisioned to the device.**/
75     size_t keySize;                             /**< Size of key.**/
76     const char *pemCert;                        /**< Certificate (SIGNED_ASYMMETRIC_KEY) encoded as PEM.**/
77     const OicSecRole_t *role1;                  /**< Role of the deviceInfo[0].**/
78     const OicSecRole_t *role2;                  /**< Role of the deviceInfo[1].**/
79 } CredentialData_t;
80
81 /**
82  * Structure to carry ACL provision API data to callback.
83  */
84 typedef struct ACLData
85 {
86     void *ctx;                                   /**< Pointer to user context.**/
87     const OCProvisionDev_t *deviceInfo;          /**< Pointer to PMDevInfo_t.**/
88     OCProvisionResultCB resultCallback;         /**< Pointer to result callback.**/
89     OCProvisionResult_t *resArr;                 /**< Result array.**/
90     int numOfResults;                           /**< Number of results in result array.**/
91     OicSecAcl_t *acl;
92     OicSecAclVersion_t aclVersion;
93 } ACLData_t;
94
95 /**
96  * Structure to carry Trust Chain provision API data to callback.
97  */
98 typedef struct TrustChainData
99 {
100     void *ctx;                                  /**< Pointer to user context.**/
101     const OCProvisionDev_t *targetDev;          /**< Pointer to OCProvisionDev_t.**/
102     OCProvisionResultCB resultCallback;         /**< Pointer to result callback.**/
103     uint16_t credId;                            /**< Trust chain id to be provisioned.**/
104     OCProvisionResult_t *resArr;                /**< Result array.**/
105     int numOfResults;                           /**< Number of results in result array.**/
106 } TrustChainData_t;
107
108 /**
109  * Structure to carry Certificate provision API data to callback.
110  */
111 typedef struct CertData
112 {
113     void *ctx;                                  /**< Pointer to user context.**/
114     const OCProvisionDev_t *targetDev;          /**< Pointer to OCProvisionDev_t.**/
115     OicSecCred_t *credInfo;                     /**< Array of pointers to OicSecCred_t.**/
116     OCProvisionResultCB resultCallback;         /**< Pointer to result callback.**/
117     OCProvisionResult_t *resArr;                /**< Result array.**/
118     int numOfResults;                           /**< Number of results in result array.**/
119     const char* cert;                           /**< The certificate.**/
120 } CertData_t;
121
122 /**
123  * Structure to carry security profiles provision API data to callback.
124  */
125 typedef struct SpData
126 {
127     void *ctx;                                  /**< Pointer to user context.**/
128     const OCProvisionDev_t *targetDev;          /**< Pointer to OCProvisionDev_t.**/
129     OCProvisionResultCB resultCallback;         /**< Pointer to result callback.**/
130     OCProvisionResult_t *resArr;                /**< Result array.**/
131     int numOfResults;                           /**< Number of results in result array.**/
132     OicSecSp_t *sp;
133 } SpData_t;
134
135 // Structure to carry get security resource APIs data to callback.
136 typedef struct GetSecData GetSecData_t;
137 struct GetSecData {
138     void *ctx;
139     const OCProvisionDev_t *deviceInfo;         /**< Pointer to PMDevInfo_t.**/
140     OCProvisionResultCB resultCallback;         /**< Pointer to result callback.**/
141     OCProvisionResult_t *resArr;                /**< Result array.**/
142     int numOfResults;                        /**< Number of results in result array.**/
143 };
144
145 typedef struct GetCsrData GetCsrData_t;
146 struct GetCsrData {
147     void *ctx;
148     const OCProvisionDev_t *deviceInfo;         /**< Pointer to PMDevInfo_t.**/
149     OCGetCSRResultCB resultCallback;            /**< Pointer to result callback.**/
150     OCPMGetCsrResult_t *resArr;                 /**< Result array.**/
151     size_t numOfResults;                        /**< Number of results in result array.**/
152 };
153
154 typedef struct GetSpData GetSpData_t;
155 struct GetSpData {
156     void *ctx;
157     const OCProvisionDev_t *deviceInfo;         /**< Pointer to PMDevInfo_t.**/
158     OCGetSpResultCB resultCallback;             /**< Pointer to result callback.**/
159     OCPMGetSpResult_t *resArr;                  /**< Result array.**/
160     size_t numOfResults;                        /**< Number of results in result array.**/
161 };
162
163
164 typedef struct GetRolesData GetRolesData_t;
165 struct GetRolesData {
166     void *ctx;                                  /**< User-provided context **/
167     const OCProvisionDev_t *deviceInfo;         /**< Pointer to PMDevInfo_t.**/
168     OCGetRolesResultCB resultCallback;          /**< Pointer to result callback.**/
169     OCPMGetRolesResult_t *resArr;               /**< Result array.**/
170     size_t numOfResults;                        /**< Number of results in result array.**/
171 };
172
173 // Enum type index for unlink callback.
174 typedef enum {
175     IDX_FIRST_DEVICE_RES = 0, // index for resulf of the first device
176     IDX_SECOND_DEVICE_RES,    // index for result of the second device
177     IDX_DB_UPDATE_RES         // index for result of updating provisioning database.
178 } IdxUnlinkRes_t;
179
180 // Structure to carry unlink APIs data to callback.
181 typedef struct UnlinkData UnlinkData_t;
182 struct UnlinkData {
183     void *ctx;
184     OCProvisionDev_t* unlinkDev;             /**< Pointer to OCProvisionDev_t to be unlinked.**/
185     OCProvisionResult_t* unlinkRes;          /**< Result array.**/
186     OCProvisionResultCB resultCallback;      /**< Pointer to result callback.**/
187     int numOfResults;                        /**< Number of results in result array.**/
188 };
189
190 //Example of DELETE cred request -> coaps://0.0.0.0:5684/oic/sec/cred?sub=(BASE64 ENCODED UUID)
191 const char * SRP_FORM_DELETE_CREDENTIAL = "coaps://[%s]:%d%s?%s=%s";
192 const char * SRP_FORM_DELETE_CREDENTIAL_TCP = "coaps+tcp://[%s]:%d%s?%s=%s";
193
194 // Structure to carry remove APIs data to callback.
195 typedef struct RemoveData RemoveData_t;
196 struct RemoveData {
197     void *ctx;
198     OCProvisionDev_t* revokeTargetDev;      /**< Device which is going to be revoked..**/
199     OCProvisionDev_t* linkedDevList;        /**< A list of devices which have invalid credential.**/
200     OCProvisionResult_t* removeRes;         /**< Result array.**/
201     OCProvisionResultCB resultCallback;     /**< Pointer to result callback.**/
202     size_t numOfResults;                    /**< Number of results in result array.**/
203     size_t sizeOfResArray;
204     bool hasError;
205 };
206
207 /**
208  * Function prototypes
209  */
210 static OCStackResult ProvisionCredentialsDos(void *ctx, OicSecCred_t *cred,
211         const OCProvisionDev_t *deviceInfo, OCClientResponseHandler responseHandler);
212 static OCStackResult provisionCredentials(OicSecCred_t *cred,
213         const OCProvisionDev_t *deviceInfo, CredentialData_t *credData,
214         OCClientResponseHandler responseHandler);
215 static OCStackApplicationResult  ProvisionPskCB(void *ctx, OCDoHandle UNUSED,
216         OCClientResponse *clientResponse);
217 static OCStackResult ProvisionLocalCredential(void *ctx, OicSecCred_t *cred);
218
219 typedef enum {
220     DEVICE_1_FINISHED,
221     DEVICE_2_FINISHED,
222     DEVICE_LOCAL_FINISHED
223 } CredProvisioningResultCause_t;
224
225 /**
226  * Deallocates a block of memory.
227  *
228  * @param[in] data    Pointer to block of memory previously allocated for Data_t.
229  */
230 void FreeData(Data_t *data)
231 {
232     if(NULL == data)
233     {
234         return;
235     }
236
237     if (NULL == data->ctx)
238     {
239         OICFree(data);
240         return;
241     }
242
243     switch (data->type)
244     {
245         case CHAIN_TYPE:
246             {
247                 TrustChainData_t *chainData = (TrustChainData_t *) data->ctx;
248                 OICFree(chainData->resArr);
249                 OICFree(chainData);
250                 break;
251             }
252         case SP_TYPE:
253             {
254                 SpData_t *spData = (SpData_t *) data->ctx;
255                 OICFree(spData->resArr);
256                 OICFree(spData);
257                 break;
258             }
259         case ACL_TYPE:
260             {
261                 ACLData_t *aclData = (ACLData_t *) data->ctx;
262                 OICFree(aclData->resArr);
263                 OICFree(aclData);
264                 break;
265             }
266         case PSK_TYPE:
267             {
268                 CredentialData_t *pskData = (CredentialData_t *) data->ctx;
269                 OICFree(pskData->resArr);
270                 OICFree(pskData);
271                 break;
272             }
273         case CERT_TYPE:
274             {
275                 CertData_t *certData = (CertData_t *) data->ctx;
276                 if (NULL != certData->resArr)
277                 {
278                      OICFreeAndSetToNull((void**)&certData->resArr);
279                 }
280                 FreeCred(certData->credInfo);
281                 OICFreeAndSetToNull((void**)&certData);
282                 break;
283             }
284         case MOT_TYPE:
285             {
286                 OTMContext_t *motData = (OTMContext_t *) data->ctx;
287                 OICFree(motData->ctxResultArray);
288                 OICFree(motData);
289                 break;
290             }
291 #if defined(WITH_CLOUD)
292         case CLOUD_TYPE:
293             {
294                 CloudData_t *cloudData = (CloudData_t *) data->ctx;
295                 OICFree(cloudData->resArr);
296                 OICFree(cloudData);
297                 break;
298             }
299 #endif
300         default:
301             {
302                 OIC_LOG_V(INFO, TAG, "Unknown type %d", data->type);
303             }
304     }
305     OICFree(data);
306 }
307
308 /**
309  * Internal function to update result in result array.
310  */
311 static void registerResultForCredProvisioning(CredentialData_t *credData,
312                                               OCStackResult stackresult, CredProvisioningResultCause_t cause)
313 {
314    OCStackResult res = OC_STACK_ERROR;
315    OIC_LOG_V(INFO,TAG,"value of credData->numOfResults is %d",credData->numOfResults);
316    switch (cause)
317    {
318    case DEVICE_1_FINISHED:
319        memcpy(credData->resArr[(credData->numOfResults)].deviceId.id,
320               credData->deviceInfo[0]->doxm->deviceID.id,UUID_LENGTH);
321        break;
322    case DEVICE_2_FINISHED:
323        memcpy(credData->resArr[(credData->numOfResults)].deviceId.id,
324               credData->deviceInfo[1]->doxm->deviceID.id,UUID_LENGTH);
325        break;
326    case DEVICE_LOCAL_FINISHED:
327        res = GetDoxmDeviceID(&credData->resArr[(credData->numOfResults)].deviceId);
328        if (OC_STACK_OK != res)
329        {
330            OIC_LOG_V(WARNING, TAG, "%s: Could not retrieve own device ID to populate result for cred provisioning: %d", __func__, res);
331            memset(credData->resArr[(credData->numOfResults)].deviceId.id, 0, UUID_LENGTH);
332        }
333        break;
334    default:
335        assert(!"Unknown value for cause");
336        OIC_LOG_V(ERROR, TAG, "%s: unknown value of cause: %d", __func__, cause);
337        memset(credData->resArr[(credData->numOfResults)].deviceId.id, 0, UUID_LENGTH);
338        break;
339    }
340    credData->resArr[(credData->numOfResults)].res = stackresult;
341    ++(credData->numOfResults);
342 }
343
344 /**
345  * Callback handler for handling callback of provisioning device 2.
346  *
347  * @param[in] ctx             ctx value passed to callback from calling function.
348  * @param[in] UNUSED          handle to an invocation
349  * @param[in] clientResponse  Response from queries to remote servers.
350  * @return  OC_STACK_DELETE_TRANSACTION to delete the transaction
351  *          and  OC_STACK_KEEP_TRANSACTION to keep it.
352  */
353 static OCStackApplicationResult provisionCredentialCB2(void *ctx, OCDoHandle UNUSED,
354                                                        OCClientResponse *clientResponse)
355 {
356     VERIFY_NOT_NULL_RETURN(TAG, ctx, ERROR, OC_STACK_DELETE_TRANSACTION);
357     CredentialData_t *credData = (CredentialData_t *) ctx;
358     (void)UNUSED;
359
360     OCProvisionResultCB resultCallback = credData->resultCallback;
361     OIC_LOG(INFO, TAG, "provisionCredentialCB2 called");
362     if (clientResponse)
363     {
364         if(OC_STACK_RESOURCE_CHANGED == clientResponse->result)
365         {
366             registerResultForCredProvisioning(credData, OC_STACK_RESOURCE_CHANGED, DEVICE_2_FINISHED);
367             OCStackResult res =  PDMLinkDevices(&credData->deviceInfo[0]->doxm->deviceID,
368                     &credData->deviceInfo[1]->doxm->deviceID);
369             if (OC_STACK_OK != res)
370             {
371                 OIC_LOG(ERROR, TAG, "Error occured on PDMLinkDevices");
372                 return OC_STACK_DELETE_TRANSACTION;
373             }
374             OIC_LOG(INFO, TAG, "Link created successfully");
375
376             ((OCProvisionResultCB)(resultCallback))(credData->ctx, credData->numOfResults,
377                                                     credData->resArr,
378                                                     false);
379              OICFree(credData->resArr);
380              OICFree(credData);
381              return OC_STACK_DELETE_TRANSACTION;
382         }
383
384     }
385     OIC_LOG(INFO, TAG, "provisionCredentialCB2 received Null clientResponse");
386     registerResultForCredProvisioning(credData, OC_STACK_ERROR, DEVICE_2_FINISHED);
387     ((OCProvisionResultCB)(resultCallback))(credData->ctx, credData->numOfResults,
388                                             credData->resArr,
389                                             true);
390     OICFree(credData->resArr);
391     OICFree(credData);
392     return OC_STACK_DELETE_TRANSACTION;
393 }
394
395 /**
396  * Callback handler for handling callback of provisioning device 1.
397  *
398  * @param[in] ctx             ctx value passed to callback from calling function.
399  * @param[in] UNUSED          handle to an invocation
400  * @param[in] clientResponse  Response from queries to remote servers.
401  * @return  OC_STACK_DELETE_TRANSACTION to delete the transaction
402  *          and  OC_STACK_KEEP_TRANSACTION to keep it.
403  */
404 static OCStackApplicationResult provisionCredentialCB1(void *ctx, OCDoHandle UNUSED,
405                                                        OCClientResponse *clientResponse)
406 {
407     VERIFY_NOT_NULL_RETURN(TAG, ctx, ERROR, OC_STACK_DELETE_TRANSACTION);
408     (void)UNUSED;
409     CredentialData_t* credData = (CredentialData_t*) ctx;
410     OICFree(credData->credInfo[0]);
411     const OCProvisionDev_t *deviceInfo = credData->deviceInfo[1];
412     OicSecCred_t *credInfo = credData->credInfo[1];
413     const OCProvisionResultCB resultCallback = credData->resultCallback;
414     if (clientResponse)
415     {
416         if (OC_STACK_RESOURCE_CHANGED == clientResponse->result)
417         {
418             // send credentials to second device
419             registerResultForCredProvisioning(credData, OC_STACK_RESOURCE_CHANGED, DEVICE_1_FINISHED);
420             OCStackResult res = provisionCredentials(credInfo, deviceInfo, credData,
421                     provisionCredentialCB2);
422             // If deviceInfo is NULL, this device is the second device. Don't delete the cred
423             // because provisionCredentials added it to the local cred store and it now owns
424             // the memory.
425             if ((NULL != deviceInfo) || (OC_STACK_OK != res))
426             {
427                 DeleteCredList(credInfo);
428             }
429             if (OC_STACK_OK != res)
430             {
431                 registerResultForCredProvisioning(credData, res,2);
432                 ((OCProvisionResultCB)(resultCallback))(credData->ctx, credData->numOfResults,
433                                                         credData->resArr,
434                                                         true);
435                 OICFree(credData->resArr);
436                 OICFree(credData);
437                 credData = NULL;
438             }
439         }
440         else
441         {
442             registerResultForCredProvisioning(credData, OC_STACK_ERROR, DEVICE_1_FINISHED);
443             ((OCProvisionResultCB)(resultCallback))(credData->ctx, credData->numOfResults,
444                                                     credData->resArr,
445                                                     true);
446             OICFree(credData->resArr);
447             OICFree(credData);
448             credData = NULL;
449         }
450     }
451     else
452     {
453         OIC_LOG(INFO, TAG, "provisionCredentialCB received Null clientResponse for first device");
454         registerResultForCredProvisioning(credData, OC_STACK_ERROR, DEVICE_1_FINISHED);
455        ((OCProvisionResultCB)(resultCallback))(credData->ctx, credData->numOfResults,
456                                                      credData->resArr,
457                                                      true);
458         DeleteCredList(credInfo);
459         OICFree(credData->resArr);
460         OICFree(credData);
461         credData = NULL;
462     }
463     return OC_STACK_DELETE_TRANSACTION;
464 }
465
466 /**
467  * Callback handler for handling callback of provisioning device 2.
468  *
469  * @param[in] ctx             ctx value passed to callback from calling function.
470  * @param[in] UNUSED          handle to an invocation
471  * @param[in] clientResponse  Response from queries to remote servers.
472  * @return  OC_STACK_DELETE_TRANSACTION to delete the transaction
473  *          and  OC_STACK_KEEP_TRANSACTION to keep it.
474  */
475 static OCStackApplicationResult ProvisionCredentialDosCB2(void *ctx, OCDoHandle UNUSED,
476                                                        OCClientResponse *clientResponse)
477 {
478     VERIFY_NOT_NULL_RETURN(TAG, ctx, ERROR, OC_STACK_DELETE_TRANSACTION);
479     CredentialData_t *credData = (CredentialData_t *) ((Data_t *) ctx)->ctx;
480     (void)UNUSED;
481
482     OCProvisionResultCB resultCallback = credData->resultCallback;
483     OIC_LOG_V(DEBUG, TAG, "IN %s", __func__);
484     if (clientResponse)
485     {
486         if (OC_STACK_RESOURCE_CHANGED == clientResponse->result)
487         {
488             registerResultForCredProvisioning(credData, OC_STACK_RESOURCE_CHANGED, DEVICE_2_FINISHED);
489             OCStackResult res =  PDMLinkDevices(&credData->deviceInfo[0]->doxm->deviceID,
490                                                 &credData->deviceInfo[1]->doxm->deviceID);
491             if (OC_STACK_OK != res)
492             {
493                 OIC_LOG(ERROR, TAG, "Error occured on PDMLinkDevices");
494                 return OC_STACK_DELETE_TRANSACTION;
495             }
496             OIC_LOG(INFO, TAG, "Link created successfully");
497
498             ((OCProvisionResultCB)(resultCallback))(credData->ctx, credData->numOfResults,
499                                                     credData->resArr,
500                                                     false);
501             FreeData(ctx);
502             return OC_STACK_DELETE_TRANSACTION;
503         }
504
505     }
506     OIC_LOG(INFO, TAG, "ProvisionCredentialDosCB2 received Null clientResponse");
507     registerResultForCredProvisioning(credData, OC_STACK_ERROR, DEVICE_2_FINISHED);
508     ((OCProvisionResultCB)(resultCallback))(credData->ctx, credData->numOfResults,
509                                             credData->resArr,
510                                             true);
511     FreeData(ctx);
512     OIC_LOG_V(DEBUG, TAG, "OUT %s", __func__);
513     return OC_STACK_DELETE_TRANSACTION;
514 }
515
516 /**
517  * Callback handler for handling callback of provisioning device 1.
518  *
519  * @param[in] ctx             ctx value passed to callback from calling function.
520  * @param[in] UNUSED          handle to an invocation
521  * @param[in] clientResponse  Response from queries to remote servers.
522  * @return  OC_STACK_DELETE_TRANSACTION to delete the transaction
523  *          and  OC_STACK_KEEP_TRANSACTION to keep it.
524  */
525 static OCStackApplicationResult ProvisionCredentialDosCB1(void *ctx, OCDoHandle UNUSED,
526         OCClientResponse *clientResponse)
527 {
528     OIC_LOG_V(DEBUG, TAG, "IN %s", __func__);
529     VERIFY_NOT_NULL_RETURN(TAG, ctx, ERROR, OC_STACK_DELETE_TRANSACTION);
530     (void) UNUSED;
531     OCStackResult res = OC_STACK_OK;
532     CredentialData_t *credData = (CredentialData_t *) ((Data_t *) ctx)->ctx;
533     const OCProvisionDev_t *deviceInfo = credData->deviceInfo[1];
534     OicSecCred_t *credInfo = credData->credInfo[1];
535     const OCProvisionResultCB resultCallback = credData->resultCallback;
536     if (clientResponse)
537     {
538         if (OC_STACK_RESOURCE_CHANGED == clientResponse->result)
539         {
540             // send credentials to second device
541             registerResultForCredProvisioning(credData, OC_STACK_RESOURCE_CHANGED, DEVICE_1_FINISHED);
542
543             // If deviceInfo is NULL, this device is the second device. Don't delete the cred
544             // because provisionCredentials added it to the local cred store and it now owns
545             // the memory.
546             if (NULL != deviceInfo)
547             {
548                 // A second device was specifed. Set the device into RFPRO and send it the cred.
549                 res = SetDOS((Data_t *)ctx, DOS_RFPRO, ProvisionPskCB);
550             }
551             else
552             {
553                 // A second device was not specified. Add the cred to the local cred store.
554                 res = ProvisionLocalCredential(ctx, credInfo);
555             }
556
557             if (OC_STACK_OK != res)
558             {
559                 DeleteCredList(credInfo);
560             }
561             if (OC_STACK_OK != res)
562             {
563                 registerResultForCredProvisioning(credData, res, 2);
564                 ((OCProvisionResultCB)(resultCallback))(credData->ctx, credData->numOfResults,
565                                                         credData->resArr,
566                                                         true);
567                 FreeData(ctx);
568             }
569         }
570         else
571         {
572             registerResultForCredProvisioning(credData, OC_STACK_ERROR, DEVICE_1_FINISHED);
573             ((OCProvisionResultCB)(resultCallback))(credData->ctx, credData->numOfResults,
574                                                     credData->resArr,
575                                                     true);
576             FreeData(ctx);
577         }
578     }
579     else
580     {
581         OIC_LOG(INFO, TAG, "provisionCredentialCB received Null clientResponse for first device");
582         registerResultForCredProvisioning(credData, OC_STACK_ERROR, DEVICE_1_FINISHED);
583         ((OCProvisionResultCB)(resultCallback))(credData->ctx, credData->numOfResults,
584                                                 credData->resArr,
585                                                 true);
586         FreeData(ctx);
587     }
588     OIC_LOG_V(DEBUG, TAG, "OUT %s", __func__);
589     return OC_STACK_DELETE_TRANSACTION;
590 }
591 /**
592  * Internal function for handling credential generation and sending credential to resource server.
593  *
594  * @param[in] cred Instance of cred resource.
595  * @param[in] deviceInfo information about device to which credential is to be provisioned.
596  * @param[in] responseHandler callbak called by OC stack when request API receives response.
597  * @return  OC_STACK_OK in case of success and other value otherwise.
598  */
599 static OCStackResult provisionCredentials(OicSecCred_t *cred,
600         const OCProvisionDev_t *deviceInfo, CredentialData_t *credData,
601         OCClientResponseHandler responseHandler)
602 {
603     OCStackResult res = OC_STACK_OK;
604
605     if (NULL != deviceInfo)
606     {
607         OCSecurityPayload* secPayload = (OCSecurityPayload*)OICCalloc(1, sizeof(OCSecurityPayload));
608         if (!secPayload)
609         {
610             OIC_LOG(ERROR, TAG, "Failed to allocate memory");
611             return OC_STACK_NO_MEMORY;
612         }
613         secPayload->base.type = PAYLOAD_TYPE_SECURITY;
614         int secureFlag = 0;
615         bool propertiesToInclude[CRED_PROPERTY_COUNT];
616         memset(propertiesToInclude, 0, sizeof(propertiesToInclude));
617         propertiesToInclude[CRED_CREDS] = true;
618         res = CredToCBORPayloadPartial(cred, NULL, &secPayload->securityData, &secPayload->payloadSize, secureFlag, propertiesToInclude);
619         if ((OC_STACK_OK != res) && (NULL == secPayload->securityData))
620         {
621             OCPayloadDestroy((OCPayload *)secPayload);
622             OIC_LOG(ERROR, TAG, "Failed to CredToCBORPayloadPartial");
623             return OC_STACK_NO_MEMORY;
624         }
625
626         OIC_LOG(DEBUG, TAG, "Created payload for Cred:");
627         OIC_LOG_BUFFER(DEBUG, TAG, secPayload->securityData, secPayload->payloadSize);
628         char query[MAX_URI_LENGTH + MAX_QUERY_LENGTH] = { 0 };
629         if (!PMGenerateQuery(true,
630             deviceInfo->endpoint.addr,
631             deviceInfo->securePort,
632             deviceInfo->connType,
633             query, sizeof(query), OIC_RSRC_CRED_URI))
634         {
635             OIC_LOG(ERROR, TAG, "DeviceDiscoveryHandler : Failed to generate query");
636             OCPayloadDestroy((OCPayload *)secPayload);
637             return OC_STACK_ERROR;
638         }
639         OIC_LOG_V(DEBUG, TAG, "Query=%s", query);
640
641         OCCallbackData cbData;
642         memset(&cbData, 0, sizeof(cbData));
643         cbData.cb = responseHandler;
644         cbData.context = (void *)credData;
645         cbData.cd = NULL;
646
647         OCDoHandle handle = NULL;
648         OCMethod method = OC_REST_POST;
649         res = OCDoResource(&handle, method, query, 0, (OCPayload*)secPayload,
650             deviceInfo->connType, OC_HIGH_QOS, &cbData, NULL, 0);
651         OIC_LOG_V(INFO, TAG, "OCDoResource::Credential provisioning returned : %d", res);
652         if (res != OC_STACK_OK)
653         {
654             OIC_LOG(ERROR, TAG, "OCStack resource error");
655             return res;
656         }
657         return OC_STACK_OK;
658     }
659     else
660     {
661         /* Provision this credential to the local cred store. On success, the cred resource takes
662          * ownership of the memory. On failure, provisionCredentialCB1 will delete the cred object.
663          */
664         res = AddCredential(cred);
665         /* Call the result callback directly. */
666         registerResultForCredProvisioning(credData, OC_STACK_RESOURCE_CHANGED, DEVICE_LOCAL_FINISHED);
667         (credData->resultCallback)(credData->ctx, credData->numOfResults, credData->resArr, false);
668         return res;
669     }
670 }
671 /**
672  * Internal function for handling credential generation and sending credential to resource server.
673  *
674  * @param[in] cred Instance of cred resource.
675  * @param[in] deviceInfo information about device to which credential is to be provisioned.
676  * @param[in] responseHandler callbak called by OC stack when request API receives response.
677  * @return  OC_STACK_OK in case of success and other value otherwise.
678  */
679 static OCStackResult ProvisionCredentialsDos(void *ctx, OicSecCred_t *cred,
680         const OCProvisionDev_t *deviceInfo, OCClientResponseHandler responseHandler)
681 {
682     OCStackResult res = OC_STACK_OK;
683
684     if (NULL != deviceInfo)
685     {
686         OCSecurityPayload *secPayload = (OCSecurityPayload *)OICCalloc(1, sizeof(OCSecurityPayload));
687         if (!secPayload)
688         {
689             OIC_LOG(ERROR, TAG, "Failed to allocate memory");
690             return OC_STACK_NO_MEMORY;
691         }
692         secPayload->base.type = PAYLOAD_TYPE_SECURITY;
693         int secureFlag = 0;
694         bool propertiesToInclude[CRED_PROPERTY_COUNT];
695         memset(propertiesToInclude, 0, sizeof(propertiesToInclude));
696         propertiesToInclude[CRED_CREDS] = true;
697         res = CredToCBORPayloadPartial(cred, NULL, &secPayload->securityData, &secPayload->payloadSize, secureFlag, propertiesToInclude);
698         if ((OC_STACK_OK != res) && (NULL == secPayload->securityData))
699         {
700             OCPayloadDestroy((OCPayload *)secPayload);
701             OIC_LOG(ERROR, TAG, "Failed to CredToCBORPayloadPartial");
702             return OC_STACK_NO_MEMORY;
703         }
704
705         OIC_LOG(DEBUG, TAG, "Created payload for Cred:");
706         OIC_LOG_BUFFER(DEBUG, TAG, secPayload->securityData, secPayload->payloadSize);
707         char query[MAX_URI_LENGTH + MAX_QUERY_LENGTH] = { 0 };
708         if (!PMGenerateQuery(true,
709                              deviceInfo->endpoint.addr,
710                              deviceInfo->securePort,
711                              deviceInfo->connType,
712                              query, sizeof(query), OIC_RSRC_CRED_URI))
713         {
714             OIC_LOG(ERROR, TAG, "DeviceDiscoveryHandler : Failed to generate query");
715             OCPayloadDestroy((OCPayload *)secPayload);
716             return OC_STACK_ERROR;
717         }
718         OIC_LOG_V(DEBUG, TAG, "Query=%s", query);
719
720         OCCallbackData cbData = { .context = NULL, .cb = NULL, .cd = NULL };
721         cbData.cb = responseHandler;
722         cbData.context = ctx;
723         cbData.cd = NULL;
724
725         OCDoHandle handle = NULL;
726         OCMethod method = OC_REST_POST;
727         res = OCDoResource(&handle, method, query, 0, (OCPayload *)secPayload,
728                            deviceInfo->connType, OC_HIGH_QOS, &cbData, NULL, 0);
729         OIC_LOG_V(INFO, TAG, "OCDoResource::Credential provisioning returned : %d", res);
730         if (res != OC_STACK_OK)
731         {
732             OIC_LOG(ERROR, TAG, "OCStack resource error");
733             return res;
734         }
735         return OC_STACK_OK;
736     }
737     else
738     {
739         /* Provision this credential to the local cred store. */
740         return ProvisionLocalCredential(ctx, cred);
741     }
742 }
743
744 /**
745  * Internal function for adding credentials to the local cred store
746  *
747  * @param[in] cred Instance of cred resource.
748  * @return  OC_STACK_OK in case of success and other value otherwise.
749  */
750 static OCStackResult ProvisionLocalCredential(void *ctx, OicSecCred_t *cred)
751 {
752     CredentialData_t *credData = (CredentialData_t *)((Data_t *)ctx)->ctx;
753
754     OCStackResult res = AddCredential(cred);
755
756     /* Call the result callback directly. */
757     registerResultForCredProvisioning(credData, OC_STACK_RESOURCE_CHANGED, DEVICE_LOCAL_FINISHED);
758     (credData->resultCallback)(credData->ctx, credData->numOfResults, credData->resArr, false);
759     return res;
760 }
761
762 /**
763  * Updates result in result array of the target device.
764  */
765 static OCStackResult RegisterProvResult(const OCProvisionDev_t *targetDev, OCProvisionResult_t *resArr,
766                                int *numOfResults, OCStackResult stackResult);
767
768 OCStackApplicationResult SetReadyForNormalOperationCB(void *ctx, OCDoHandle handler,
769         OCClientResponse *clientResponse)
770 {
771     OIC_LOG_V(DEBUG, TAG, "IN %s", __func__);
772     VERIFY_NOT_NULL_RETURN(TAG, ctx, ERROR, OC_STACK_DELETE_TRANSACTION);
773     DataType_t dataType = ((Data_t *) ctx)->type;
774
775     OCProvisionResultCB resultCallback = NULL;
776     const OCProvisionDev_t *targetDev = NULL;
777     OCProvisionResult_t *resArr = NULL;
778     int *numOfResults = NULL;
779
780     void *dataCtx = NULL;
781     OIC_LOG_V(DEBUG, TAG, "Data type %d", dataType);
782
783     switch (dataType)
784     {
785         case CHAIN_TYPE:
786         {
787             TrustChainData_t *chainData = (TrustChainData_t *) ((Data_t *) ctx)->ctx;
788             resultCallback = chainData->resultCallback;
789             targetDev = chainData->targetDev;
790             resArr = chainData->resArr;
791             numOfResults = &(chainData->numOfResults);
792             dataCtx = chainData->ctx;
793             break;
794         }
795         case SP_TYPE:
796         {
797             SpData_t *spData = (SpData_t *) ((Data_t *) ctx)->ctx;
798             resultCallback = spData->resultCallback;
799             targetDev = spData->targetDev;
800             resArr = spData->resArr;
801             numOfResults = &(spData->numOfResults);
802             dataCtx = spData->ctx;
803             break;
804         }
805         case ACL_TYPE:
806         {
807             ACLData_t *aclData = (ACLData_t *) ((Data_t *) ctx)->ctx;
808             resultCallback = aclData->resultCallback;
809             targetDev = aclData->deviceInfo;
810             resArr = aclData->resArr;
811             numOfResults = &(aclData->numOfResults);
812             dataCtx = aclData->ctx;
813             break;
814         }
815         case PSK_TYPE:
816         {
817             CredentialData_t *pskData = (CredentialData_t *) ((Data_t *) ctx)->ctx;
818             resArr = pskData->resArr;
819             numOfResults = &(pskData->numOfResults);
820             dataCtx = pskData->ctx;
821             OIC_LOG_V(DEBUG, TAG, "PSK index %d", pskData->currIndex);
822             break;
823         }
824         case CERT_TYPE:
825         {
826             CertData_t *certData = (CertData_t *) ((Data_t *) ctx)->ctx;
827             if (NULL == certData)
828             {
829                 OIC_LOG_V(ERROR, TAG, "%s: certData is NULL", __func__);
830                 break;
831             }
832             resultCallback = certData->resultCallback;
833             targetDev = certData->targetDev;
834             resArr = certData->resArr;
835             numOfResults = &(certData->numOfResults);
836             dataCtx = certData->ctx;
837             break;
838         }
839 #if defined(WITH_CLOUD)
840         case CLOUD_TYPE:
841         {
842             CloudData_t *cloudData = (CloudData_t *) ((Data_t *) ctx)->ctx;
843             if (NULL == cloudData)
844             {
845                 OIC_LOG_V(ERROR, TAG, "%s: cloudData is NULL", __func__);
846                 break;
847             }
848             resultCallback = cloudData->resultCallback;
849             targetDev = cloudData->targetDev;
850             resArr = cloudData->resArr;
851             numOfResults = &(cloudData->numOfResults);
852             dataCtx = cloudData->ctx;
853             break;
854         }
855 #endif
856         default:
857         {
858             OIC_LOG_V(ERROR, TAG, "Unknown type %d", dataType);
859             OIC_LOG_V(ERROR, TAG, "OUT %s", __func__);
860             return OC_STACK_DELETE_TRANSACTION;
861         }
862     }
863
864     if (dataType != PSK_TYPE)
865     {
866         if (NULL != resultCallback)
867         {
868             RegisterProvResult(targetDev, resArr, numOfResults, clientResponse->result);
869             resultCallback(dataCtx, *numOfResults, resArr, clientResponse->result != OC_STACK_RESOURCE_CHANGED);
870             FreeData(ctx);
871         }
872         else
873         {
874             OIC_LOG_V(ERROR, TAG, "resultCallback is NULL");
875             OIC_LOG_V(ERROR, TAG, "OUT %s", __func__);
876             return OC_STACK_DELETE_TRANSACTION;
877         }
878     }
879     else
880     {
881         CredentialData_t *pskData = (CredentialData_t *) ((Data_t *) ctx)->ctx;
882         if (pskData->currIndex == 0)
883         {
884             pskData->currIndex = 1;
885             ProvisionCredentialDosCB1(ctx, handler, clientResponse);
886         }
887         else
888         {
889             ProvisionCredentialDosCB2(ctx, handler, clientResponse);
890         }
891     }
892
893     OIC_LOG_V(DEBUG, TAG, "OUT %s", __func__);
894     return OC_STACK_DELETE_TRANSACTION;
895 }
896
897 OCStackResult SetDOS(const Data_t *data, OicSecDeviceOnboardingState_t dos,
898                             OCClientResponseHandler resultCallback)
899 {
900     OIC_LOG_V(DEBUG, TAG, "IN %s", __func__);
901     if (NULL == data || NULL == resultCallback)
902     {
903         OIC_LOG(ERROR, TAG, "NULL parameters");
904         OIC_LOG_V(ERROR, TAG, "OUT %s", __func__);
905         return OC_STACK_INVALID_PARAM;
906     }
907
908     const OCProvisionDev_t *pTargetDev = NULL;
909
910     switch (data->type)
911     {
912         case CHAIN_TYPE:
913         {
914             pTargetDev = ((TrustChainData_t *)data->ctx)->targetDev;
915             break;
916         }
917         case SP_TYPE:
918         {
919             pTargetDev = ((SpData_t *)data->ctx)->targetDev;
920             break;
921         }
922         case ACL_TYPE:
923         {
924             pTargetDev = ((ACLData_t *)data->ctx)->deviceInfo;
925             break;
926         }
927         case PSK_TYPE:
928         {
929             CredentialData_t *credData = ((CredentialData_t *)data)->ctx;
930             pTargetDev = credData->deviceInfo[credData->currIndex];
931             break;
932         }
933         case CERT_TYPE:
934         {
935             pTargetDev = ((CertData_t *)data->ctx)->targetDev;
936             break;
937         }
938         case MOT_TYPE:
939         {
940             pTargetDev = ((OTMContext_t *)data->ctx)->selectedDeviceInfo;
941             break;
942         }
943 #if defined(WITH_CLOUD)
944         case CLOUD_TYPE:
945         {
946             pTargetDev = ((CloudData_t *)data->ctx)->targetDev;
947             break;
948         }
949 #endif
950         default:
951         {
952             OIC_LOG_V(ERROR, TAG, "Unknown type: %d", data->type);
953             return OC_STACK_INVALID_PARAM;
954         }
955     }
956     // Skip posting new DOS state in case of OIC server
957     if (IS_OIC(pTargetDev->specVer))
958     {
959         OCClientResponse clientResponse = {.result = OC_STACK_RESOURCE_CHANGED};
960         resultCallback((void*) data, NULL, &clientResponse);
961         return OC_STACK_OK;
962     }
963
964     OCStackResult res = OC_STACK_ERROR;
965     OicSecPstat_t *pstat = (OicSecPstat_t *) OICCalloc(1, sizeof(OicSecPstat_t));
966     if (!pstat)
967     {
968         OIC_LOG(ERROR, TAG, "Failed to allocate memory");
969         return OC_STACK_NO_MEMORY;
970     }
971
972     pstat->dos.state = dos;
973
974     OCSecurityPayload *secPayload = (OCSecurityPayload *) OICCalloc(1, sizeof(OCSecurityPayload));
975     if (!secPayload)
976     {
977         OIC_LOG(ERROR, TAG, "Failed to allocate memory");
978         res = OC_STACK_NO_MEMORY;
979         goto error;
980     }
981     secPayload->base.type = PAYLOAD_TYPE_SECURITY;
982
983     // Note [IOT-2052] all the POST payloads in the provisioningclient app
984     // should be updated to use the Partial payload APIs for the SVRs, so they
985     // do not include read-only Properties for the Server device current
986     // state.
987     bool propertiesToInclude[PSTAT_PROPERTY_COUNT] = {false};
988     propertiesToInclude[PSTAT_DOS] = true;
989
990     if (OC_STACK_OK != PstatToCBORPayloadPartial(pstat, &(secPayload->securityData),
991             &(secPayload->payloadSize), propertiesToInclude, false))
992     {
993         OCPayloadDestroy((OCPayload *) secPayload);
994         OIC_LOG(ERROR, TAG, "Failed to PstatToCBORPayload");
995         res = OC_STACK_NO_MEMORY;
996         goto error;
997     }
998     OIC_LOG(DEBUG, TAG, "Created payload for pstat set");
999     OIC_LOG_BUFFER(DEBUG, TAG, secPayload->securityData, secPayload->payloadSize);
1000
1001     char query[MAX_URI_LENGTH + MAX_QUERY_LENGTH] = {0};
1002     if (!PMGenerateQuery(true,
1003                          pTargetDev->endpoint.addr,
1004                          pTargetDev->securePort,
1005                          pTargetDev->connType,
1006                          query, sizeof(query), OIC_RSRC_PSTAT_URI))
1007     {
1008         OIC_LOG(ERROR, TAG, "Failed to generate query");
1009         OCPayloadDestroy((OCPayload *) secPayload);
1010         res = OC_STACK_ERROR;
1011         goto error;
1012     }
1013     OIC_LOG_V(DEBUG, TAG, "Query=%s", query);
1014
1015     OCCallbackData cbData = { .context = NULL, .cb = NULL, .cd = NULL };
1016     OCMethod method = OC_REST_POST;
1017     OCDoHandle handle = NULL;
1018     OCProvisionDev_t *targetDev = NULL;
1019
1020     targetDev = PMCloneOCProvisionDev(pTargetDev);
1021
1022     if (NULL == targetDev)
1023     {
1024         OIC_LOG(ERROR, TAG, "target dev is null");
1025         res = OC_STACK_ERROR;
1026         goto error;
1027     }
1028     cbData.cb = resultCallback;
1029     cbData.context = (void *) data;
1030     cbData.cd = NULL;
1031     OIC_LOG(DEBUG, TAG, "Sending PSTAT info to resource server");
1032     res = OCDoResource(&handle, method, query,
1033                        &targetDev->endpoint, (OCPayload *)secPayload,
1034                        targetDev->connType, OC_HIGH_QOS, &cbData, NULL, 0);
1035     if (OC_STACK_OK != res)
1036     {
1037         OIC_LOG(ERROR, TAG, "OCStack resource error");
1038     }
1039
1040 error:
1041     OICFree(pstat);
1042     OIC_LOG_V(DEBUG, TAG, "OUT %s", __func__);
1043     return res;
1044 }
1045
1046 OCStackApplicationResult ProvisionCB(void *ctx, OCDoHandle handle,
1047         OCClientResponse *clientResponse)
1048 {
1049     OIC_LOG_V(DEBUG, TAG, "IN %s", __func__);
1050     VERIFY_NOT_NULL_RETURN(TAG, ctx, ERROR, OC_STACK_DELETE_TRANSACTION);
1051     OC_UNUSED(handle);
1052     if (clientResponse && OC_STACK_RESOURCE_CHANGED != clientResponse->result)
1053     {
1054         OIC_LOG_V(ERROR, TAG, "Responce result: %d", clientResponse->result);
1055     }
1056     if (OC_STACK_OK != SetDOS(ctx, DOS_RFNOP, SetReadyForNormalOperationCB))
1057     {
1058         OIC_LOG_V(ERROR, TAG, "OUT %s", __func__);
1059         return OC_STACK_DELETE_TRANSACTION;
1060     }
1061
1062     OIC_LOG_V(DEBUG, TAG, "OUT %s", __func__);
1063     return OC_STACK_DELETE_TRANSACTION;
1064 }
1065 /**
1066  * Callback for PSK provisioning.
1067  */
1068 static OCStackApplicationResult  ProvisionPskCB(void *ctx, OCDoHandle UNUSED,
1069                                                 OCClientResponse *clientResponse)
1070 {
1071     VERIFY_NOT_NULL_RETURN(TAG, ctx, ERROR, OC_STACK_DELETE_TRANSACTION);
1072     (void) UNUSED;
1073     CredentialData_t *credData = (CredentialData_t *) ((Data_t *) ctx)->ctx;
1074     const OCProvisionDev_t *device = credData->deviceInfo[credData->currIndex];
1075     OicSecCred_t *cred = credData->credInfo[credData->currIndex];
1076     const OCProvisionResultCB resultCallback = credData->resultCallback;
1077
1078     if (clientResponse)
1079     {
1080         if (OC_STACK_RESOURCE_CHANGED == clientResponse->result)
1081         {
1082             OCStackResult res = ProvisionCredentialsDos(ctx, cred, device, ProvisionCB);
1083             if (OC_STACK_OK != res)
1084             {
1085                 registerResultForCredProvisioning(credData, res, 2);
1086                 ((OCProvisionResultCB)(resultCallback))(credData->ctx, credData->numOfResults,
1087                                                         credData->resArr, true);
1088                 FreeData(ctx);
1089                 return OC_STACK_DELETE_TRANSACTION;
1090             }
1091         }
1092         else
1093         {
1094             registerResultForCredProvisioning(credData, OC_STACK_ERROR, credData->currIndex);
1095             ((OCProvisionResultCB)(resultCallback))(credData->ctx, credData->numOfResults,
1096                                                     credData->resArr,
1097                                                     true);
1098             FreeData(ctx);
1099         }
1100     }
1101     else
1102     {
1103         OIC_LOG(INFO, TAG, "provisionCredentialCB received Null clientResponse for first device");
1104         registerResultForCredProvisioning(credData, OC_STACK_ERROR, credData->currIndex);
1105         ((OCProvisionResultCB)(resultCallback))(credData->ctx, credData->numOfResults,
1106                                                 credData->resArr,
1107                                                 true);
1108         FreeData(ctx);
1109         credData = NULL;
1110     }
1111     return OC_STACK_DELETE_TRANSACTION;
1112 }
1113
1114
1115 #if defined(__WITH_DTLS__) || defined(__WITH_TLS__)
1116 OCStackResult SRPRegisterTrustCertChainNotifier(void *ctx, TrustCertChainChangeCB callback)
1117 {
1118     if (g_trustCertChainNotifier.callback)
1119     {
1120         OIC_LOG(ERROR, TAG, "Can't register Notifier, Unregister previous one");
1121         return OC_STACK_ERROR;
1122     }
1123
1124     g_trustCertChainNotifier.callback = callback;
1125     g_trustCertChainNotifier.context = ctx;
1126     return OC_STACK_OK;
1127 }
1128
1129 void SRPRemoveTrustCertChainNotifier()
1130 {
1131     g_trustCertChainNotifier.callback = NULL;
1132     g_trustCertChainNotifier.context = NULL;
1133     return;
1134 }
1135
1136 static OCStackApplicationResult provisionCertificateCB(void *ctx, OCDoHandle UNUSED,
1137     OCClientResponse *clientResponse)
1138 {
1139     // Just call the callback provided to SRProvisionCredentials
1140     VERIFY_NOT_NULL_RETURN(TAG, ctx, ERROR, OC_STACK_DELETE_TRANSACTION);
1141     CredentialData_t* credData = (CredentialData_t *)ctx;
1142     (void)UNUSED;
1143     bool hasError;
1144
1145     // We expect OC_STACK_RESOURCE_CHANGED, anything else is an error
1146     if (clientResponse && (OC_STACK_RESOURCE_CHANGED == clientResponse->result))
1147     {
1148         hasError = false;
1149     }
1150     else
1151     {
1152         hasError = true;
1153     }
1154
1155     OCProvisionResultCB resultCallback = credData->resultCallback;
1156     VERIFY_NOT_NULL_RETURN(TAG, resultCallback, ERROR, OC_STACK_DELETE_TRANSACTION);
1157
1158     ((OCProvisionResultCB)(resultCallback))(credData->ctx, credData->numOfResults,
1159         credData->resArr, hasError);
1160
1161     OICFree(credData);
1162
1163     return OC_STACK_DELETE_TRANSACTION;
1164
1165 }
1166 /**
1167  * Callback for Trust Chain provisioning.
1168  */
1169 static OCStackApplicationResult ProvisionTrustChainCB(void *ctx, OCDoHandle UNUSED,
1170         OCClientResponse *clientResponse)
1171 {
1172     OIC_LOG_V(INFO, TAG, "IN %s", __func__);
1173     (void) UNUSED;
1174     if (NULL == ctx)
1175     {
1176         OIC_LOG(ERROR, TAG, "Context is NULL");
1177         return OC_STACK_INVALID_PARAM;
1178     }
1179     if (OC_STACK_RESOURCE_CHANGED == clientResponse->result)
1180     {
1181         Data_t *data = (Data_t *) ctx;
1182         if (CHAIN_TYPE != data->type)
1183         {
1184             OIC_LOG(ERROR, TAG, "Invalid type");
1185             return OC_STACK_INVALID_PARAM;
1186         }
1187         TrustChainData_t *chainData = (TrustChainData_t *) (data->ctx);
1188         OicSecCred_t *trustCertChainCred = GetCredEntryByCredId(chainData->credId);
1189         if (NULL == trustCertChainCred)
1190         {
1191             OIC_LOG(ERROR, TAG, "Can not find matched Trust Cert. Chain.");
1192             return OC_STACK_NO_RESOURCE;
1193         }
1194
1195         OCSecurityPayload *secPayload = (OCSecurityPayload *)OICCalloc(1, sizeof(OCSecurityPayload));
1196         if (!secPayload)
1197         {
1198             DeleteCredList(trustCertChainCred);
1199             OIC_LOG(ERROR, TAG, "Failed to allocate memory");
1200             return OC_STACK_NO_MEMORY;
1201         }
1202         secPayload->base.type = PAYLOAD_TYPE_SECURITY;
1203         int secureFlag = 1; /* Don't send the private key to the device, if it happens to be present */
1204         bool propertiesToInclude[CRED_PROPERTY_COUNT];
1205         memset(propertiesToInclude, 0, sizeof(propertiesToInclude));
1206         propertiesToInclude[CRED_CREDS] = true;
1207         if (OC_STACK_OK != CredToCBORPayloadPartial(trustCertChainCred, NULL, &secPayload->securityData,
1208                                              &secPayload->payloadSize, secureFlag, propertiesToInclude))
1209         {
1210             DeleteCredList(trustCertChainCred);
1211             OCPayloadDestroy((OCPayload *)secPayload);
1212             OIC_LOG(ERROR, TAG, "Failed to CredToCBORPayloadPartial");
1213             return OC_STACK_NO_MEMORY;
1214         }
1215         DeleteCredList(trustCertChainCred);
1216         OIC_LOG(DEBUG, TAG, "Created payload for Cred:");
1217         OIC_LOG_BUFFER(DEBUG, TAG, secPayload->securityData, secPayload->payloadSize);
1218
1219         char query[MAX_URI_LENGTH + MAX_QUERY_LENGTH] = {0};
1220         if (!PMGenerateQuery(true,
1221                              chainData->targetDev->endpoint.addr,
1222                              chainData->targetDev->securePort,
1223                              chainData->targetDev->connType,
1224                              query, sizeof(query), OIC_RSRC_CRED_URI))
1225         {
1226             OIC_LOG(ERROR, TAG, "Failed to generate query");
1227             OCPayloadDestroy((OCPayload *)secPayload);
1228             return OC_STACK_ERROR;
1229         }
1230         OIC_LOG_V(DEBUG, TAG, "Query=%s", query);
1231
1232         OCCallbackData cbData =  {.context = NULL, .cb = NULL, .cd = NULL};
1233         cbData.cb = ProvisionCB;
1234         cbData.context = ctx;
1235         cbData.cd = NULL;
1236         OCMethod method = OC_REST_POST;
1237         OCDoHandle handle = NULL;
1238         OIC_LOG(DEBUG, TAG, "Sending Cred info to resource server");
1239         OCStackResult ret = OCDoResource(&handle, method, query,
1240                                          &chainData->targetDev->endpoint, (OCPayload *)secPayload,
1241                                          chainData->targetDev->connType, OC_HIGH_QOS, &cbData, NULL, 0);
1242         if (ret != OC_STACK_OK)
1243         {
1244             OIC_LOG_V(INFO, TAG, "OUT %s", __func__);
1245             return ret;
1246         }
1247     }
1248     else
1249     {
1250         OIC_LOG_V(ERROR, TAG, "OUT %s", __func__);
1251         return OC_STACK_ERROR;
1252     }
1253
1254     OIC_LOG_V(INFO, TAG, "OUT %s", __func__);
1255     return OC_STACK_OK;
1256 }
1257
1258 /**
1259  * Callback for Security Profile provisioning.
1260  */
1261 static OCStackApplicationResult ProvisionSecurityProfileInfoCB(void *ctx, OCDoHandle UNUSED,
1262         OCClientResponse *clientResponse)
1263 {
1264     OIC_LOG_V(INFO, TAG, "IN %s", __func__);
1265     (void) UNUSED;
1266     if (NULL == ctx)
1267     {
1268         OIC_LOG(ERROR, TAG, "Context is NULL");
1269         return OC_STACK_INVALID_PARAM;
1270     }
1271     if (OC_STACK_RESOURCE_CHANGED == clientResponse->result)
1272     {
1273         Data_t *data = (Data_t *) ctx;
1274         if (SP_TYPE != data->type)
1275         {
1276             OIC_LOG(ERROR, TAG, "Invalid type");
1277             return OC_STACK_INVALID_PARAM;
1278         }
1279         SpData_t *spData = (SpData_t *) (data->ctx);
1280
1281         OCSecurityPayload *secPayload = (OCSecurityPayload *)OICCalloc(1, sizeof(OCSecurityPayload));
1282         if (!secPayload)
1283         {
1284             OIC_LOG(ERROR, TAG, "Failed to allocate memory");
1285             return OC_STACK_NO_MEMORY;
1286         }
1287
1288         secPayload->base.type = PAYLOAD_TYPE_SECURITY;
1289         if (OC_STACK_OK != SpToCBORPayload(spData->sp, &secPayload->securityData,
1290                                            &secPayload->payloadSize))
1291         {
1292             OCPayloadDestroy((OCPayload *)secPayload);
1293             OIC_LOG(ERROR, TAG, "Failed to SpToCBORPayload");
1294             return OC_STACK_NO_MEMORY;
1295         }
1296         OIC_LOG(DEBUG, TAG, "Created payload for SP:");
1297         OIC_LOG_BUFFER(DEBUG, TAG, secPayload->securityData, secPayload->payloadSize);
1298
1299         char query[MAX_URI_LENGTH + MAX_QUERY_LENGTH] = {0};
1300         if (!PMGenerateQuery(true,
1301                              spData->targetDev->endpoint.addr,
1302                              spData->targetDev->securePort,
1303                              spData->targetDev->connType,
1304                              query, sizeof(query), OIC_RSRC_SP_URI))
1305         {
1306             OIC_LOG(ERROR, TAG, "Failed to generate query");
1307             OCPayloadDestroy((OCPayload *)secPayload);
1308             return OC_STACK_ERROR;
1309         }
1310         OIC_LOG_V(DEBUG, TAG, "Query=%s", query);
1311
1312         OCCallbackData cbData =  {.context = NULL, .cb = NULL, .cd = NULL};
1313         cbData.cb = ProvisionCB;
1314         cbData.context = ctx;
1315         cbData.cd = NULL;
1316         OCMethod method = OC_REST_POST;
1317         OCDoHandle handle = NULL;
1318         OIC_LOG(DEBUG, TAG, "Sending SP info to resource server");
1319         OCStackResult ret = OCDoResource(&handle, method, query,
1320                                          &spData->targetDev->endpoint, (OCPayload *)secPayload,
1321                                          spData->targetDev->connType, OC_HIGH_QOS, &cbData, NULL, 0);
1322         if (ret != OC_STACK_OK)
1323         {
1324             OIC_LOG_V(INFO, TAG, "OUT %s", __func__);
1325             return ret;
1326         }
1327     }
1328     else
1329     {
1330         OIC_LOG_V(ERROR, TAG, "OUT %s", __func__);
1331         return OC_STACK_ERROR;
1332     }
1333
1334     OIC_LOG_V(INFO, TAG, "OUT %s", __func__);
1335     return OC_STACK_OK;
1336 }
1337
1338 OCStackResult SRPProvisionTrustCertChain(void *ctx, OicSecCredType_t type, uint16_t credId,
1339         const OCProvisionDev_t *selectedDeviceInfo, OCProvisionResultCB resultCallback)
1340 {
1341     OIC_LOG_V(INFO, TAG, "IN %s", __func__);
1342     VERIFY_NOT_NULL_RETURN(TAG, selectedDeviceInfo, ERROR,  OC_STACK_INVALID_PARAM);
1343     VERIFY_NOT_NULL_RETURN(TAG, resultCallback, ERROR,  OC_STACK_INVALID_CALLBACK);
1344     if (SIGNED_ASYMMETRIC_KEY != type)
1345     {
1346         OIC_LOG(INFO, TAG, "Invalid key type");
1347         return OC_STACK_INVALID_PARAM;
1348     }
1349
1350     TrustChainData_t *chainData = (TrustChainData_t *) OICCalloc(1, sizeof(TrustChainData_t));
1351     if (NULL == chainData)
1352     {
1353         OIC_LOG(ERROR, TAG, "Memory allocation problem");
1354         return OC_STACK_NO_MEMORY;
1355     }
1356     chainData->targetDev = selectedDeviceInfo;
1357     chainData->resultCallback = resultCallback;
1358     chainData->credId = credId;
1359     chainData->ctx = ctx;
1360     chainData->numOfResults = 0;
1361
1362     int noOfRiCalls = 1;
1363     chainData->resArr = (OCProvisionResult_t *)OICCalloc(noOfRiCalls, sizeof(OCProvisionResult_t));
1364     if (chainData->resArr == NULL)
1365     {
1366         OICFree(chainData);
1367         OIC_LOG(ERROR, TAG, "Unable to allocate memory");
1368         return OC_STACK_NO_MEMORY;
1369     }
1370
1371     Data_t *data = (Data_t *) OICCalloc(1, sizeof(Data_t));
1372     VERIFY_NOT_NULL_RETURN(TAG, data, ERROR, OC_STACK_NO_MEMORY);
1373     data->type = CHAIN_TYPE;
1374     data->ctx = chainData;
1375
1376     if (SetDOS(data, DOS_RFPRO, ProvisionTrustChainCB) != OC_STACK_OK)
1377     {
1378         FreeData(data);
1379         OIC_LOG_V(INFO, TAG, "OUT %s", __func__);
1380         return OC_STACK_ERROR;
1381     }
1382
1383     OIC_LOG_V(INFO, TAG, "OUT %s", __func__);
1384     return OC_STACK_OK;
1385 }
1386
1387 /**
1388  * function to provision security profile info
1389  *
1390  * @param[in] ctx Application context to be returned in result callback.
1391  * @param[in] sp security profile to be provisioned
1392  * @param[in] selectedDeviceInfo Pointer to OCProvisionDev_t instance,respresenting resource to be provsioned.
1393  * @param[in] resultCallback callback provided by API user, callback will be called when
1394  *            provisioning request recieves a response from first resource server.
1395  * @return  OC_STACK_OK in case of success and other value otherwise.
1396  */
1397 OCStackResult SRPProvisionSecurityProfileInfo(void *ctx, OicSecSp_t *sp,
1398                                               const OCProvisionDev_t *selectedDeviceInfo,
1399                                               OCProvisionResultCB resultCallback)
1400 {
1401     OIC_LOG_V(INFO, TAG, "IN %s", __func__);
1402     VERIFY_NOT_NULL_RETURN(TAG, selectedDeviceInfo, ERROR,  OC_STACK_INVALID_PARAM);
1403     VERIFY_NOT_NULL_RETURN(TAG, resultCallback, ERROR,  OC_STACK_INVALID_CALLBACK);
1404
1405     SpData_t *spData = (SpData_t *) OICCalloc(1, sizeof(SpData_t));
1406     if (NULL == spData)
1407     {
1408         OIC_LOG(ERROR, TAG, "Memory allocation problem");
1409         return OC_STACK_NO_MEMORY;
1410     }
1411
1412     spData->targetDev = selectedDeviceInfo;
1413     spData->resultCallback = resultCallback;
1414     spData->ctx = ctx;
1415     spData->numOfResults = 0;
1416     spData->sp = sp;
1417
1418     int noOfRiCalls = 1;
1419     spData->resArr = (OCProvisionResult_t *)OICCalloc(noOfRiCalls, sizeof(OCProvisionResult_t));
1420     if (spData->resArr == NULL)
1421     {
1422         OICFree(spData);
1423         OIC_LOG(ERROR, TAG, "Unable to allocate memory");
1424         return OC_STACK_NO_MEMORY;
1425     }
1426
1427     Data_t *data = (Data_t *) OICCalloc(1, sizeof(Data_t));
1428     VERIFY_NOT_NULL_RETURN(TAG, data, ERROR, OC_STACK_NO_MEMORY);
1429     data->type = SP_TYPE;
1430     data->ctx = spData;
1431
1432     if (SetDOS(data, DOS_RFPRO, ProvisionSecurityProfileInfoCB) != OC_STACK_OK)
1433     {
1434         FreeData(data);
1435         OIC_LOG_V(INFO, TAG, "OUT %s", __func__);
1436         return OC_STACK_ERROR;
1437     }
1438
1439     OIC_LOG_V(INFO, TAG, "OUT %s", __func__);
1440     return OC_STACK_OK;
1441 }
1442
1443 OCStackResult SRPSaveTrustCertChain(const uint8_t *trustCertChain, size_t chainSize,
1444                                             OicEncodingType_t encodingType, uint16_t *credId)
1445 {
1446     OIC_LOG(DEBUG, TAG, "IN SRPSaveTrustCertChain");
1447     VERIFY_NOT_NULL_RETURN(TAG, trustCertChain, ERROR,  OC_STACK_INVALID_PARAM);
1448     VERIFY_NOT_NULL_RETURN(TAG, credId, ERROR,  OC_STACK_INVALID_PARAM);
1449
1450     OCStackResult res = OC_STACK_ERROR;
1451
1452     OicSecCred_t *cred = (OicSecCred_t *)OICCalloc(1, sizeof(*cred));
1453     VERIFY_NOT_NULL_RETURN(TAG, cred, ERROR, OC_STACK_NO_MEMORY);
1454
1455     res = GetDoxmDeviceID(&cred->subject);
1456     if (OC_STACK_OK != res)
1457     {
1458         OIC_LOG(ERROR, TAG, "Can't get the device id(GetDoxmDeviceID)");
1459         DeleteCredList(cred);
1460         return res;
1461     }
1462
1463     cred->credUsage= (char *)OICCalloc(1, strlen(TRUST_CA) + 1);
1464     VERIFY_NOT_NULL_RETURN(TAG, cred->credUsage, ERROR, OC_STACK_NO_MEMORY);
1465     OICStrcpy(cred->credUsage, strlen(TRUST_CA) + 1, TRUST_CA);
1466
1467     cred->credType = SIGNED_ASYMMETRIC_KEY;
1468
1469     if (encodingType == OIC_ENCODING_PEM)
1470     {
1471         cred->publicData.data = (uint8_t *)OICCalloc(1, chainSize + 1);
1472         VERIFY_NOT_NULL_RETURN(TAG, cred->publicData.data, ERROR, OC_STACK_NO_MEMORY);
1473         cred->publicData.len = chainSize + 1;
1474     }
1475     else if (encodingType == OIC_ENCODING_DER)
1476     {
1477         cred->publicData.data = (uint8_t *)OICCalloc(1, chainSize);
1478         VERIFY_NOT_NULL_RETURN(TAG, cred->publicData.data, ERROR, OC_STACK_NO_MEMORY);
1479         cred->publicData.len = chainSize;
1480     }
1481     else
1482     {
1483         OIC_LOG_V(ERROR, TAG, "Unknown encoding in %s", __func__);
1484         DeleteCredList(cred);
1485         return OC_STACK_INVALID_PARAM;
1486     }
1487     memcpy(cred->publicData.data, trustCertChain, chainSize);
1488     cred->publicData.encoding = encodingType;
1489
1490     res = AddCredential(cred);
1491     if(res != OC_STACK_OK)
1492     {
1493         DeleteCredList(cred);
1494         return res;
1495     }
1496     *credId = cred->credId;
1497
1498     if (g_trustCertChainNotifier.callback)
1499     {
1500         uint8_t *certChain = (uint8_t*)OICCalloc(1, sizeof(uint8_t) * chainSize);
1501         VERIFY_NOT_NULL_RETURN(TAG, certChain, ERROR, OC_STACK_NO_MEMORY);
1502         memcpy(certChain, trustCertChain, chainSize);
1503         g_trustCertChainNotifier.callback(g_trustCertChainNotifier.context, *credId,
1504                 certChain, chainSize);
1505         OICFree(certChain);
1506     }
1507
1508     OIC_LOG(DEBUG, TAG, "OUT SRPSaveTrustCertChain");
1509
1510     return res;
1511 }
1512
1513 static OCStackResult saveCertChain(OicSecKey_t * cert, OicSecKey_t * key, uint16_t *credId, const char* usage)
1514 {
1515     OIC_LOG_V(DEBUG, TAG, "IN %s", __func__);
1516     VERIFY_NOT_NULL_RETURN(TAG, cert, ERROR,  OC_STACK_INVALID_PARAM);
1517     VERIFY_NOT_NULL_RETURN(TAG, cert->data, ERROR,  OC_STACK_INVALID_PARAM);
1518
1519     VERIFY_NOT_NULL_RETURN(TAG, credId, ERROR,  OC_STACK_INVALID_PARAM);
1520     VERIFY_NOT_NULL_RETURN(TAG, usage, ERROR, OC_STACK_INVALID_PARAM);
1521
1522     if (NULL == key && PRIMARY_CERT == usage)
1523     {
1524         OIC_LOG_V(ERROR, TAG, "Key is NULL, but it is mandatory if usage is %s", PRIMARY_CERT);
1525         return OC_STACK_INVALID_PARAM;
1526     }
1527
1528     if (key != NULL)
1529     {
1530         /* Key is optional. */
1531         VERIFY_NOT_NULL_RETURN(TAG, key->data, ERROR, OC_STACK_INVALID_PARAM);
1532     }
1533
1534     OCStackResult res = OC_STACK_ERROR;
1535
1536     OicSecCred_t *cred = (OicSecCred_t *)OICCalloc(1, sizeof(*cred));
1537     VERIFY_NOT_NULL_RETURN(TAG, cred, ERROR, OC_STACK_NO_MEMORY);
1538
1539     OIC_LOG_V(DEBUG, TAG, "IN: %s", __func__);
1540
1541     res = GetDoxmDeviceID(&cred->subject);
1542     if (OC_STACK_OK != res)
1543     {
1544         OIC_LOG(ERROR, TAG, "Can't get the device id(GetDoxmDeviceID)");
1545         DeleteCredList(cred);
1546         return res;
1547     }
1548
1549     cred->credUsage= (char *)OICCalloc(1, strlen(usage) + 1);
1550     VERIFY_NOT_NULL_RETURN(TAG, cred->credUsage, ERROR, OC_STACK_NO_MEMORY);
1551     OICStrcpy(cred->credUsage, strlen(usage) + 1, usage);
1552
1553     cred->credType = SIGNED_ASYMMETRIC_KEY;
1554
1555     OicSecKey_t *publicData = &cred->publicData;
1556     publicData->data = (uint8_t *)OICCalloc(1, cert->len);
1557     VERIFY_NOT_NULL_RETURN(TAG, publicData->data, ERROR, OC_STACK_NO_MEMORY);
1558     memcpy(publicData->data, cert->data, cert->len);
1559     publicData->len = cert->len;
1560     publicData->encoding = cert->encoding;
1561
1562     if (key != NULL)
1563     {
1564         OicSecKey_t *privateData = &cred->privateData;
1565         privateData->data = (uint8_t *)OICCalloc(1, key->len);
1566         VERIFY_NOT_NULL_RETURN(TAG, privateData->data, ERROR, OC_STACK_NO_MEMORY);
1567         memcpy(privateData->data, key->data, key->len);
1568         privateData->len = key->len;
1569         privateData->encoding = key->encoding;
1570     }
1571
1572     res = AddCredential(cred);
1573     if(res != OC_STACK_OK)
1574     {
1575         DeleteCredList(cred);
1576         return res;
1577     }
1578     *credId = cred->credId;
1579
1580     OIC_LOG_V(DEBUG, TAG, "OUT %s", __func__);
1581
1582     return res;
1583 }
1584
1585 OCStackResult SRPSaveOwnCertChain(OicSecKey_t * cert, OicSecKey_t * key, uint16_t *credId)
1586 {
1587     return saveCertChain(cert, key, credId, PRIMARY_CERT);
1588 }
1589
1590 OCStackResult SRPSaveOwnRoleCert(OicSecKey_t * cert, uint16_t *credId)
1591 {
1592     return saveCertChain(cert, NULL, credId, ROLE_CERT);
1593 }
1594 /**
1595  * Callback for Certificate provisioning.
1596  */
1597 static OCStackApplicationResult ProvisionCertificateCB(void *ctx, OCDoHandle handle,
1598         OCClientResponse *clientResponse)
1599 {
1600     OIC_LOG_V(INFO, TAG, "IN %s", __func__);
1601
1602     OC_UNUSED(handle);
1603     OCStackResult ret = OC_STACK_ERROR;
1604     char *query = NULL;
1605     const OCProvisionDev_t *pDev = NULL;
1606     OicSecCred_t *cred = NULL;
1607     OCSecurityPayload *secPayload = NULL;
1608
1609     VERIFY_NOT_NULL_RETURN(TAG, ctx, ERROR,  OC_STACK_INVALID_PARAM);
1610     VERIFY_NOT_NULL_RETURN(TAG, clientResponse, ERROR,  OC_STACK_INVALID_PARAM);
1611
1612     VERIFY_SUCCESS_RETURN(TAG, (OC_STACK_RESOURCE_CHANGED == clientResponse->result), ERROR,
1613         OC_STACK_INVALID_PARAM);
1614
1615     Data_t *data = (Data_t *) ctx;
1616     VERIFY_SUCCESS_RETURN(TAG, (CERT_TYPE == data->type), ERROR, OC_STACK_INVALID_PARAM);
1617
1618     CertData_t *certData = (CertData_t *) (data->ctx);
1619     VERIFY_NOT_NULL(TAG, certData, ERROR);
1620     pDev = certData->targetDev;
1621     VERIFY_NOT_NULL(TAG, pDev, ERROR);
1622     cred = certData->credInfo;
1623     VERIFY_NOT_NULL(TAG, cred, ERROR);
1624
1625     secPayload = (OCSecurityPayload *)OICCalloc(1, sizeof(OCSecurityPayload));
1626     VERIFY_NOT_NULL(TAG, secPayload, ERROR);
1627     secPayload->base.type = PAYLOAD_TYPE_SECURITY;
1628
1629     int secureFlag = 0;//don't send private data(key)
1630     bool propertiesToInclude[CRED_PROPERTY_COUNT];
1631     memset(propertiesToInclude, 0, sizeof(propertiesToInclude));
1632     propertiesToInclude[CRED_CREDS] = true;
1633     VERIFY_SUCCESS(TAG, OC_STACK_OK == CredToCBORPayloadPartial(cred, NULL, &secPayload->securityData,
1634                                              &secPayload->payloadSize, secureFlag, propertiesToInclude), ERROR);
1635     OIC_LOG_BUFFER(DEBUG, TAG, secPayload->securityData, secPayload->payloadSize);
1636
1637     query = OICCalloc(1, DEFAULT_URI_LENGTH);
1638     VERIFY_NOT_NULL(TAG, query, ERROR);
1639     VERIFY_SUCCESS(TAG, PMGenerateQuery(true,
1640                              pDev->endpoint.addr,
1641                              pDev->securePort,
1642                              pDev->connType,
1643                              query, DEFAULT_URI_LENGTH, OIC_RSRC_CRED_URI), ERROR);
1644
1645     OCCallbackData cbData =  {.context = ctx, .cb = ProvisionCB, .cd = NULL};
1646     OCDoHandle lHandle = NULL;
1647
1648     ret = OCDoResource(&lHandle, OC_REST_POST, query,
1649                                 &pDev->endpoint, (OCPayload *)secPayload,
1650                                 pDev->connType, OC_HIGH_QOS, &cbData, NULL, 0);
1651     OIC_LOG_V(DEBUG, TAG, "POST:%s ret:%d", query, ret);
1652 exit:
1653     OICFree(query);
1654     if (OC_STACK_OK != ret)
1655     {
1656         if(NULL != secPayload)
1657         {
1658             OCPayloadDestroy((OCPayload *)secPayload);
1659         }
1660         if(NULL != cred)
1661         {
1662             FreeCred(cred);
1663         }
1664     }
1665
1666     OIC_LOG_V(INFO, TAG, "OUT %s", __func__);
1667
1668     return ret;
1669 }
1670
1671 OCStackResult SRPProvisionCertificate(void *ctx,
1672     const OCProvisionDev_t *pDev,
1673     const char* pemCert,
1674     OCProvisionResultCB resultCallback)
1675 {
1676     OIC_LOG_V(INFO, TAG, "IN %s", __func__);
1677
1678     VERIFY_NOT_NULL_RETURN(TAG, pDev, ERROR,  OC_STACK_INVALID_PARAM);
1679     VERIFY_NOT_NULL_RETURN(TAG, resultCallback, ERROR,  OC_STACK_INVALID_CALLBACK);
1680     VERIFY_NOT_NULL_RETURN(TAG, pemCert, ERROR,  OC_STACK_INVALID_CALLBACK);
1681
1682     OCStackResult ret = OC_STACK_ERROR;
1683     Data_t *data = NULL;
1684
1685     OicUuid_t provTooldeviceID =   {{0,}};
1686     if (OC_STACK_OK != GetDoxmDeviceID(&provTooldeviceID))
1687     {
1688         OIC_LOG(ERROR, TAG, "Error while retrieving provisioning tool's device ID");
1689         return OC_STACK_ERROR;
1690     }
1691
1692     data = (Data_t *)OICCalloc(1, sizeof(Data_t));
1693     VERIFY_NOT_NULL(TAG, data, ERROR);
1694     data->type = CERT_TYPE;
1695
1696     CertData_t *certData = (CertData_t *)OICCalloc(1, sizeof(CertData_t));
1697     VERIFY_NOT_NULL(TAG, certData, ERROR);
1698     data->ctx = certData;
1699     certData->ctx = ctx;
1700     certData->targetDev = pDev;
1701     certData->resultCallback = resultCallback;
1702     certData->numOfResults = 0;
1703     certData->credInfo = NULL;
1704
1705     certData->resArr = (OCProvisionResult_t *)OICCalloc(1, sizeof(OCProvisionResult_t));
1706     VERIFY_NOT_NULL(TAG, certData->resArr, ERROR);
1707
1708     OicSecKey_t deviceCert = { 0 };
1709     deviceCert.data = (uint8_t*) pemCert;
1710     deviceCert.len = strlen(pemCert) + 1;
1711     deviceCert.encoding = OIC_ENCODING_PEM;
1712
1713     OicSecCred_t *cred = GenerateCredential(&pDev->doxm->deviceID, SIGNED_ASYMMETRIC_KEY,
1714         &deviceCert, NULL, NULL);
1715     VERIFY_NOT_NULL(TAG, cred, ERROR);
1716     certData->credInfo = cred;
1717
1718     cred->publicData.encoding = OIC_ENCODING_PEM;
1719
1720     if (OC_STACK_OK == OCInternalIsValidRoleCertificate(deviceCert.data, deviceCert.len, NULL, NULL))
1721     {
1722         cred->credUsage = OICStrdup(ROLE_CERT);
1723     }
1724     else
1725     {
1726         cred->credUsage = OICStrdup(PRIMARY_CERT);
1727     }
1728
1729     ret = SetDOS(data, DOS_RFPRO, ProvisionCertificateCB);
1730 exit:
1731     if (OC_STACK_OK != ret)
1732     {
1733          FreeData(data);
1734     }
1735
1736     OIC_LOG_V(INFO, TAG, "OUT %s", __func__);
1737
1738     return ret;
1739 }
1740
1741
1742 #endif // __WITH_DTLS__ || __WITH_TLS__
1743
1744 OCStackResult SRPProvisionCredentials(void *ctx, OicSecCredType_t type, size_t keySize,
1745                                       const OCProvisionDev_t *pDev1,
1746                                       const OCProvisionDev_t *pDev2,
1747                                       const char* pemCert,
1748                                       const OicSecRole_t *role1,
1749                                       const OicSecRole_t *role2,
1750                                       OCProvisionResultCB resultCallback)
1751 {
1752     VERIFY_NOT_NULL_RETURN(TAG, pDev1, ERROR,  OC_STACK_INVALID_PARAM);
1753     if (!resultCallback)
1754     {
1755         OIC_LOG(INFO, TAG, "SRPProvisionCredentials: NULL Callback");
1756         return OC_STACK_INVALID_CALLBACK;
1757     }
1758     if ((SYMMETRIC_PAIR_WISE_KEY == type) &&
1759         (NULL != pDev2) &&
1760         (0 == memcmp(&pDev1->doxm->deviceID, &pDev2->doxm->deviceID, sizeof(OicUuid_t))))
1761     {
1762         OIC_LOG(INFO, TAG, "SRPProvisionCredentials : Same device ID");
1763         return OC_STACK_INVALID_PARAM;
1764     }
1765
1766     if (SYMMETRIC_PAIR_WISE_KEY == type &&
1767        !(OWNER_PSK_LENGTH_128 == keySize || OWNER_PSK_LENGTH_256 == keySize))
1768     {
1769         OIC_LOG(INFO, TAG, "Invalid key size");
1770         return OC_STACK_INVALID_PARAM;
1771     }
1772
1773     OIC_LOG(INFO, TAG, "In SRPProvisionCredentials");
1774
1775     if ((SYMMETRIC_PAIR_WISE_KEY == type) && (NULL != pDev2))
1776     {
1777         bool linkExisits = true;
1778         OCStackResult res = PDMIsLinkExists(&pDev1->doxm->deviceID, &pDev2->doxm->deviceID, &linkExisits);
1779
1780         if (res != OC_STACK_OK)
1781         {
1782             OIC_LOG(ERROR, TAG, "Internal error occured");
1783             return res;
1784         }
1785         if (linkExisits)
1786         {
1787             OIC_LOG(ERROR, TAG, "Link already exists");
1788             return OC_STACK_INVALID_PARAM;
1789         }
1790     }
1791
1792     OicUuid_t provTooldeviceID =   {{0,}};
1793     if (OC_STACK_OK != GetDoxmDeviceID(&provTooldeviceID))
1794     {
1795         OIC_LOG(ERROR, TAG, "Error while retrieving provisioning tool's device ID");
1796         return OC_STACK_ERROR;
1797     }
1798     OIC_LOG(INFO, TAG, "retrieved deviceid");
1799     switch (type)
1800     {
1801         case SYMMETRIC_PAIR_WISE_KEY:
1802         {
1803             const OCProvisionDev_t *firstDevice = pDev1;
1804             const OCProvisionDev_t *secondDevice = pDev2;
1805
1806             OicSecCred_t *firstCred = NULL;
1807             OicSecCred_t *secondCred = NULL;
1808             OCStackResult res = PMGeneratePairWiseCredentials(type, keySize,
1809                     &firstDevice->doxm->deviceID, (NULL != secondDevice) ? &secondDevice->doxm->deviceID : &provTooldeviceID,
1810                     role1, role2,
1811                     &firstCred, &secondCred);
1812             VERIFY_SUCCESS_RETURN(TAG, (res==OC_STACK_OK), ERROR, OC_STACK_ERROR);
1813             OIC_LOG(INFO, TAG, "Credentials generated successfully");
1814             CredentialData_t *credData =
1815                 (CredentialData_t *) OICCalloc(1, sizeof(CredentialData_t));
1816             if (NULL == credData)
1817             {
1818                 OICFree(firstCred);
1819                 OICFree(secondCred);
1820                 OIC_LOG(ERROR, TAG, "Memory allocation problem");
1821                 return OC_STACK_NO_MEMORY;
1822             }
1823             credData->deviceInfo[0] = firstDevice;
1824             credData->deviceInfo[1] = secondDevice;
1825             credData->credInfo[1] = secondCred;
1826             credData->ctx = ctx;
1827             credData->credInfo[0] = firstCred;
1828             credData->numOfResults = 0;
1829             credData->resultCallback = resultCallback;
1830             // first call to provision creds to device1.
1831             // second call to provision creds to device2.
1832             int noOfRiCalls = 2;
1833             credData->resArr =
1834                 (OCProvisionResult_t*)OICCalloc(noOfRiCalls, sizeof(OCProvisionResult_t));
1835             if (NULL == credData->resArr)
1836             {
1837                 OICFree(firstCred);
1838                 OICFree(secondCred);
1839                 OICFree(credData);
1840                 OIC_LOG(ERROR, TAG, "Memory allocation problem");
1841                 return OC_STACK_NO_MEMORY;
1842             }
1843             res = provisionCredentials(firstCred, firstDevice, credData, &provisionCredentialCB1);
1844             if (OC_STACK_OK != res)
1845             {
1846                 DeleteCredList(firstCred);
1847                 DeleteCredList(secondCred);
1848                 OICFree(credData->resArr);
1849                 OICFree(credData);
1850             }
1851             OIC_LOG_V(INFO, TAG, "provisionCredentials returned: %d",res);
1852             VERIFY_SUCCESS_RETURN(TAG, (res==OC_STACK_OK), ERROR, OC_STACK_ERROR);
1853             return res;
1854         }
1855         case SIGNED_ASYMMETRIC_KEY:
1856         {
1857             /* pDev1 is the device to be provisioned, checked non-null above */
1858             /* pDev2 is not used, should be NULL */
1859             /* size param is not used. */
1860             /* pemCert is the cerficiate to be provisioned */
1861             VERIFY_NOT_NULL_RETURN(TAG, pemCert, ERROR, OC_STACK_INVALID_PARAM);
1862
1863             OicSecKey_t deviceCert = { 0 };
1864             deviceCert.data = (uint8_t*) pemCert; /* Casting away const is OK here */
1865             deviceCert.len = strlen(pemCert) + 1;
1866             deviceCert.encoding = OIC_ENCODING_PEM;
1867
1868             /* Create a credential object */
1869             OicSecCred_t* cred =  GenerateCredential(&pDev1->doxm->deviceID, SIGNED_ASYMMETRIC_KEY,
1870                     &deviceCert, NULL, // oic.sec.cred.publicdata = deviceCert, .privatedata = NULL
1871                     NULL); // no eowner
1872             VERIFY_NOT_NULL_RETURN(TAG, cred, ERROR, OC_STACK_ERROR);
1873
1874             cred->publicData.encoding = OIC_ENCODING_PEM;
1875
1876             if (OCInternalIsValidRoleCertificate(deviceCert.data, deviceCert.len, NULL, NULL) == OC_STACK_OK)
1877             {
1878                 cred->credUsage = OICStrdup(ROLE_CERT);
1879             }
1880             else
1881             {
1882                 cred->credUsage = OICStrdup(PRIMARY_CERT);
1883             }
1884
1885             /* Create credential data (used by the response handler provisionCertificateCB and freed there) */
1886             CredentialData_t *credData = (CredentialData_t *)OICCalloc(1, sizeof(CredentialData_t));
1887             if ((NULL == credData) || (NULL == cred->credUsage))
1888             {
1889                 DeleteCredList(cred);
1890                 OIC_LOG(ERROR, TAG, "Memory allocation problem");
1891                 return OC_STACK_NO_MEMORY;
1892             }
1893             credData->deviceInfo[0] = pDev1;
1894             credData->deviceInfo[1] = NULL;
1895             credData->credInfo[1] = cred;
1896             credData->ctx = ctx;
1897             credData->credInfo[0] = cred;
1898             credData->numOfResults = 0;
1899             credData->resultCallback = resultCallback;
1900             credData->resArr = NULL;
1901
1902             /* Note: the callback is of type OCClientResponseHandler, thin wrapper that calls resultCallback */
1903             OCStackResult res = provisionCredentials(cred, pDev1, credData, &provisionCertificateCB);
1904             if (res != OC_STACK_OK)
1905             {
1906                 OICFree(credData);
1907             }
1908
1909             DeleteCredList(cred);
1910             return OC_STACK_OK;
1911         }
1912         default:
1913         {
1914             OIC_LOG(ERROR, TAG, "Invalid option.");
1915             return OC_STACK_INVALID_PARAM;
1916         }
1917     }
1918 }
1919
1920 OCStackResult SRPProvisionCredentialsDos(void *ctx, OicSecCredType_t type, size_t keySize,
1921                                          const OCProvisionDev_t *pDev1,
1922                                          const OCProvisionDev_t *pDev2,
1923                                          const OicSecRole_t *role1,
1924                                          const OicSecRole_t *role2,
1925                                          OCProvisionResultCB resultCallback)
1926 {
1927     VERIFY_NOT_NULL_RETURN(TAG, pDev1, ERROR,  OC_STACK_INVALID_PARAM);
1928     VERIFY_NOT_NULL_RETURN(TAG, pDev2, ERROR,  OC_STACK_INVALID_PARAM);
1929     if (!resultCallback)
1930     {
1931         OIC_LOG(INFO, TAG, "SRPProvisionCredentialsDos: NULL Callback");
1932         return OC_STACK_INVALID_CALLBACK;
1933     }
1934     if ((SYMMETRIC_PAIR_WISE_KEY == type) &&
1935         (NULL != pDev2) &&
1936         (0 == memcmp(&pDev1->doxm->deviceID, &pDev2->doxm->deviceID, sizeof(OicUuid_t))))
1937     {
1938         OIC_LOG(INFO, TAG, "SRPProvisionCredentialsDos : Same device ID");
1939         return OC_STACK_INVALID_PARAM;
1940     }
1941
1942     if (SYMMETRIC_PAIR_WISE_KEY == type &&
1943        !(OWNER_PSK_LENGTH_128 == keySize || OWNER_PSK_LENGTH_256 == keySize))
1944     {
1945         OIC_LOG(INFO, TAG, "Invalid key size");
1946         return OC_STACK_INVALID_PARAM;
1947     }
1948
1949     OIC_LOG(INFO, TAG, "In SRPProvisionCredentialsDos");
1950
1951     if ((SYMMETRIC_PAIR_WISE_KEY == type) && (NULL != pDev2))
1952     {
1953         bool linkExisits = true;
1954         OCStackResult res = PDMIsLinkExists(&pDev1->doxm->deviceID, &pDev2->doxm->deviceID, &linkExisits);
1955
1956         if (res != OC_STACK_OK)
1957         {
1958             OIC_LOG(ERROR, TAG, "Internal error occured");
1959             return res;
1960         }
1961         if (linkExisits)
1962         {
1963             OIC_LOG(ERROR, TAG, "Link already exists");
1964             return OC_STACK_INVALID_PARAM;
1965         }
1966     }
1967
1968     OicUuid_t provTooldeviceID =   {{0,}};
1969     if (OC_STACK_OK != GetDoxmDeviceID(&provTooldeviceID))
1970     {
1971         OIC_LOG(ERROR, TAG, "Error while retrieving provisioning tool's device ID");
1972         return OC_STACK_ERROR;
1973     }
1974     OIC_LOG(INFO, TAG, "retrieved deviceid");
1975
1976     CredentialData_t *credData = (CredentialData_t *) OICCalloc(1, sizeof(CredentialData_t));
1977     Data_t *data = (Data_t *) OICCalloc(1, sizeof(Data_t));
1978     if (NULL == credData || NULL == data)
1979     {
1980
1981         OICFree(credData);
1982         OICFree(data);
1983         OIC_LOG(ERROR, TAG, "Memory allocation problem");
1984         return OC_STACK_NO_MEMORY;
1985     }
1986
1987     data->ctx = credData;
1988
1989     switch (type)
1990     {
1991         case SYMMETRIC_PAIR_WISE_KEY:
1992         {
1993             data->type = PSK_TYPE;
1994             OicSecCred_t *firstCred = NULL;
1995             OicSecCred_t *secondCred = NULL;
1996             OCStackResult res = PMGeneratePairWiseCredentials(type, keySize,
1997                                 &pDev1->doxm->deviceID, (NULL != pDev2) ? &pDev2->doxm->deviceID :
1998                                 &provTooldeviceID,
1999                                 role1, role2,
2000                                 &firstCred, &secondCred);
2001             VERIFY_SUCCESS_RETURN(TAG, (OC_STACK_OK == res), ERROR, OC_STACK_ERROR);
2002             OIC_LOG(INFO, TAG, "Credentials generated successfully");
2003
2004             credData->deviceInfo[0] = pDev1;
2005             credData->deviceInfo[1] = pDev2;
2006             credData->credInfo[0] = firstCred;
2007             credData->credInfo[1] = secondCred;
2008             credData->ctx = ctx;
2009             credData->currIndex = 0;
2010             credData->numOfResults = 0;
2011             credData->resultCallback = resultCallback;
2012             // first call to provision creds to device1.
2013             // second call to provision creds to device2.
2014             int noOfRiCalls = 2;
2015             credData->resArr =
2016                 (OCProvisionResult_t *)OICCalloc(noOfRiCalls, sizeof(OCProvisionResult_t));
2017             if (NULL == credData->resArr)
2018             {
2019                 OICFree(firstCred);
2020                 OICFree(secondCred);
2021                 OICFree(credData);
2022                 OIC_LOG(ERROR, TAG, "Memory allocation problem");
2023                 return OC_STACK_NO_MEMORY;
2024             }
2025
2026             res = SetDOS(data, DOS_RFPRO, ProvisionPskCB);
2027             if (OC_STACK_OK != res)
2028             {
2029                 DeleteCredList(firstCred);
2030                 DeleteCredList(secondCred);
2031                 FreeData(data);
2032                 OIC_LOG_V(ERROR, TAG, "OUT %s", __func__);
2033                 return res;
2034             }
2035             OIC_LOG_V(INFO, TAG, "provisionCredentials returned: %d", res);
2036             return res;
2037         }
2038         default:
2039         {
2040             OIC_LOG(ERROR, TAG, "Invalid option.");
2041             return OC_STACK_INVALID_PARAM;
2042         }
2043     }
2044 }
2045 /**
2046  * Callback for ACL provisioning.
2047  */
2048 static OCStackApplicationResult ProvisionAclCB(void *ctx, OCDoHandle UNUSED,
2049         OCClientResponse *clientResponse);
2050
2051 OCStackResult SRPProvisionACL(void *ctx, const OCProvisionDev_t *selectedDeviceInfo,
2052         OicSecAcl_t *acl, OicSecAclVersion_t aclVersion, OCProvisionResultCB resultCallback)
2053 {
2054     VERIFY_NOT_NULL_RETURN(TAG, selectedDeviceInfo, ERROR,  OC_STACK_INVALID_PARAM);
2055     VERIFY_NOT_NULL_RETURN(TAG, acl, ERROR,  OC_STACK_INVALID_PARAM);
2056     VERIFY_NOT_NULL_RETURN(TAG, resultCallback, ERROR,  OC_STACK_INVALID_CALLBACK);
2057     OIC_LOG_V(INFO, TAG, "IN %s", __func__);
2058
2059
2060     ACLData_t *aclData = (ACLData_t *) OICCalloc(1, sizeof(ACLData_t));
2061     if (NULL == aclData)
2062     {
2063         OIC_LOG(ERROR, TAG, "Memory allocation problem");
2064         OIC_LOG_V(ERROR, TAG, "OUT %s", __func__);
2065         return OC_STACK_NO_MEMORY;
2066     }
2067     aclData->deviceInfo = selectedDeviceInfo;
2068     aclData->resultCallback = resultCallback;
2069     aclData->aclVersion = aclVersion;
2070     aclData->acl = acl;
2071     aclData->ctx = ctx;
2072     aclData->numOfResults = 0;
2073
2074     aclData->resArr = (OCProvisionResult_t *) OICCalloc(1, sizeof(OCProvisionResult_t));
2075     if (aclData->resArr == NULL)
2076     {
2077         OICFree(aclData);
2078         OIC_LOG(ERROR, TAG, "Unable to allocate memory");
2079         OIC_LOG_V(ERROR, TAG, "OUT %s", __func__);
2080         return OC_STACK_NO_MEMORY;
2081     }
2082
2083     Data_t *data = (Data_t *) OICCalloc(1, sizeof(Data_t));
2084     if (data == NULL)
2085     {
2086         OICFree(aclData->resArr);
2087         OICFree(aclData);
2088         OIC_LOG(ERROR, TAG, "Unable to allocate memory");
2089         OIC_LOG_V(ERROR, TAG, "OUT %s", __func__);
2090         return OC_STACK_NO_MEMORY;
2091     }
2092     data->type = ACL_TYPE;
2093     data->ctx = aclData;
2094
2095     if (SetDOS(data, DOS_RFPRO, ProvisionAclCB) != OC_STACK_OK)
2096     {
2097         FreeData(data);
2098         OIC_LOG_V(ERROR, TAG, "OUT %s", __func__);
2099         return OC_STACK_ERROR;
2100     }
2101
2102     OIC_LOG_V(INFO, TAG, "OUT %s", __func__);
2103     return OC_STACK_OK;
2104 }
2105
2106 OCStackResult SRPSaveACL(const OicSecAcl_t *acl)
2107 {
2108     OIC_LOG(DEBUG, TAG, "IN SRPSaveACL");
2109     VERIFY_NOT_NULL_RETURN(TAG, acl, ERROR,  OC_STACK_INVALID_PARAM);
2110
2111     OCStackResult res =  InstallACL(acl);
2112
2113     OIC_LOG(DEBUG, TAG, "OUT SRPSaveACL");
2114     return res;
2115 }
2116
2117 static void DeleteUnlinkData_t(UnlinkData_t *unlinkData)
2118 {
2119     if (unlinkData)
2120     {
2121         OICFree(unlinkData->unlinkDev);
2122         OICFree(unlinkData->unlinkRes);
2123         OICFree(unlinkData);
2124     }
2125 }
2126
2127 static void registerResultForUnlinkDevices(UnlinkData_t *unlinkData, OCStackResult stackresult,
2128                                            IdxUnlinkRes_t idx)
2129 {
2130     if (NULL != unlinkData)
2131     {
2132         OIC_LOG_V(INFO, TAG, "Inside registerResultForUnlinkDevices unlinkData->numOfResults is %d",
2133                             unlinkData->numOfResults);
2134         OIC_LOG_V(INFO, TAG, "Stack result :: %d", stackresult);
2135
2136         OicUuid_t *pUuid = &unlinkData->unlinkRes[(unlinkData->numOfResults)].deviceId;
2137
2138         // Set result in the result array according to the position (devNum).
2139         if (idx != IDX_DB_UPDATE_RES)
2140         {
2141             memcpy(pUuid->id, unlinkData->unlinkDev[idx].doxm->deviceID.id, sizeof(pUuid->id));
2142         }
2143         else
2144         {   // When deivce ID is 000... this means it's the result of database update.
2145             memset(pUuid->id, 0, sizeof(pUuid->id));
2146         }
2147         unlinkData->unlinkRes[(unlinkData->numOfResults)].res = stackresult;
2148         ++(unlinkData->numOfResults);
2149         OIC_LOG (INFO, TAG, "Out registerResultForUnlinkDevices");
2150     }
2151 }
2152
2153 static OCStackResult SendDeleteCredentialRequest(void* ctx,
2154                                                  OCClientResponseHandler respHandler,
2155                                                  const OCProvisionDev_t* revokedDev,
2156                                                  const OCProvisionDev_t* destDev)
2157 {
2158     OIC_LOG(DEBUG, TAG, "IN SendDeleteCredentialRequest");
2159
2160     if (NULL == ctx || NULL == respHandler || NULL == revokedDev || NULL == destDev)
2161     {
2162         return OC_STACK_INVALID_PARAM;
2163     }
2164
2165     char *subID = NULL;
2166     OCStackResult ret = ConvertUuidToStr(&revokedDev->doxm->deviceID, &subID);
2167     if(OC_STACK_OK != ret)
2168     {
2169         OIC_LOG(ERROR, TAG, "SendDeleteCredentialRequest : Failed to canonical UUID encoding");
2170         return OC_STACK_ERROR;
2171     }
2172
2173     char addressEncoded[CA_MAX_URI_LENGTH] = {0};
2174     OCStackResult result = OCEncodeAddressForRFC6874(addressEncoded,
2175                                                      sizeof(addressEncoded),
2176                                                      destDev->endpoint.addr);
2177     if (OC_STACK_OK != result)
2178     {
2179         OIC_LOG_V(ERROR, TAG, "SendDeleteCredentialRequest : encoding error %d", result);
2180         return OC_STACK_ERROR;
2181     }
2182
2183     char reqBuf[MAX_URI_LENGTH + MAX_QUERY_LENGTH] = {0};
2184     int snRet = 0;
2185                     //coaps://0.0.0.0:5684/oic/sec/cred?subjectid=(Canonical ENCODED UUID)
2186     const char *srpUri = SRP_FORM_DELETE_CREDENTIAL;
2187 #ifdef __WITH_TLS__
2188     if((int)CA_ADAPTER_TCP == (int)destDev->endpoint.adapter)
2189     {
2190         srpUri = SRP_FORM_DELETE_CREDENTIAL_TCP;
2191     }
2192 #endif
2193
2194     snRet = snprintf(reqBuf, sizeof(reqBuf), srpUri, addressEncoded,
2195                      destDev->securePort, OIC_RSRC_CRED_URI, OIC_JSON_SUBJECTID_NAME, subID);
2196     OICFree(subID);
2197     if (snRet < 0)
2198     {
2199         OIC_LOG_V(ERROR, TAG, "SendDeleteCredentialRequest : Error (snprintf) %d", snRet);
2200         return OC_STACK_ERROR;
2201     }
2202     else if ((size_t)snRet >= sizeof(reqBuf))
2203     {
2204         OIC_LOG_V(ERROR, TAG, "SendDeleteCredentialRequest : Truncated (snprintf) %d", snRet);
2205         return OC_STACK_ERROR;
2206     }
2207
2208     OCCallbackData cbData;
2209     memset(&cbData, 0, sizeof(cbData));
2210     cbData.context = ctx;
2211     cbData.cb = respHandler;
2212     cbData.cd = NULL;
2213     OIC_LOG_V(INFO, TAG, "URI: %s",reqBuf);
2214
2215     OIC_LOG(DEBUG, TAG, "Sending remove credential request to resource server");
2216
2217     ret = OCDoResource(NULL, OC_REST_DELETE, reqBuf,
2218                                      &destDev->endpoint, NULL,
2219                                      CT_ADAPTER_IP, OC_HIGH_QOS, &cbData, NULL, 0);
2220     if (OC_STACK_OK != ret)
2221     {
2222         OIC_LOG_V(ERROR, TAG, "SendDeleteCredentialRequest : Error in OCDoResource %d", ret);
2223     }
2224     OIC_LOG(DEBUG, TAG, "OUT SendDeleteCredentialRequest");
2225
2226     return ret;
2227 }
2228
2229 static OCStackResult SendDeleteACLRequest(void* ctx,
2230                                                  OCClientResponseHandler respHandler,
2231                                                  const OCProvisionDev_t* revokedDev,
2232                                                  const OCProvisionDev_t* destDev)
2233 {
2234     OIC_LOG(DEBUG, TAG, "IN SendDeleteACLRequest");
2235
2236     if (NULL == ctx || NULL == respHandler || NULL == revokedDev || NULL == destDev)
2237     {
2238         return OC_STACK_INVALID_PARAM;
2239     }
2240
2241     char *subID = NULL;
2242     OCStackResult ret = ConvertUuidToStr(&revokedDev->doxm->deviceID, &subID);
2243     if(OC_STACK_OK != ret)
2244     {
2245         OIC_LOG(ERROR, TAG, "SendDeleteACLRequest : Failed to canonical UUID encoding");
2246         return OC_STACK_ERROR;
2247     }
2248
2249     char addressEncoded[CA_MAX_URI_LENGTH] = {0};
2250     OCStackResult result = OCEncodeAddressForRFC6874(addressEncoded,
2251                                                      sizeof(addressEncoded),
2252                                                      destDev->endpoint.addr);
2253     if (OC_STACK_OK != result)
2254     {
2255         OIC_LOG_V(ERROR, TAG, "SendDeleteCredentialRequest : encoding error %d", result);
2256         return OC_STACK_ERROR;
2257     }
2258
2259     char reqBuf[MAX_URI_LENGTH + MAX_QUERY_LENGTH] = {0};
2260     int snRet = 0;
2261                     //coaps://0.0.0.0:5684/oic/sec/acl?subjectuuid=(Canonical ENCODED UUID)
2262     snRet = snprintf(reqBuf, sizeof(reqBuf), SRP_FORM_DELETE_CREDENTIAL, addressEncoded,
2263                      destDev->securePort, OIC_RSRC_ACL2_URI, OIC_JSON_SUBJECTID_NAME, subID);
2264     OICFree(subID);
2265     if (snRet < 0)
2266     {
2267         OIC_LOG_V(ERROR, TAG, "SendDeleteACLRequest : Error (snprintf) %d", snRet);
2268         return OC_STACK_ERROR;
2269     }
2270     else if ((size_t)snRet >= sizeof(reqBuf))
2271     {
2272         OIC_LOG_V(ERROR, TAG, "SendDeleteACLRequest : Truncated (snprintf) %d", snRet);
2273         return OC_STACK_ERROR;
2274     }
2275
2276     OCCallbackData cbData;
2277     memset(&cbData, 0, sizeof(cbData));
2278     cbData.context = ctx;
2279     cbData.cb = respHandler;
2280     cbData.cd = NULL;
2281     OIC_LOG_V(INFO, TAG, "URI: %s",reqBuf);
2282
2283     OIC_LOG(DEBUG, TAG, "Sending remove ACL request to resource server");
2284
2285     ret = OCDoResource(NULL, OC_REST_DELETE, reqBuf,
2286                                      &destDev->endpoint, NULL,
2287                                      CT_ADAPTER_IP, OC_HIGH_QOS, &cbData, NULL, 0);
2288     if (OC_STACK_OK != ret)
2289     {
2290         OIC_LOG_V(ERROR, TAG, "SendDeleteACLRequest : Error in OCDoResource %d", ret);
2291     }
2292     OIC_LOG(DEBUG, TAG, "OUT SendDeleteACLRequest");
2293
2294     return ret;
2295 }
2296
2297 /**
2298  * Callback handler of unlink second device.
2299  *
2300  * @param[in] ctx             ctx value passed to callback from calling function.
2301  * @param[in] handle          handle to an invocation
2302  * @param[in] clientResponse  Response from queries to remote servers.
2303  * @return  OC_STACK_DELETE_TRANSACTION to delete the transaction and
2304  *          OC_STACK_KEEP_TRANSACTION to keep it.
2305  */
2306 static OCStackApplicationResult SRPUnlinkDevice2CB(void *unlinkCtx, OCDoHandle handle,
2307         OCClientResponse *clientResponse)
2308 {
2309     (void) handle;
2310     OIC_LOG(DEBUG, TAG, "IN SRPUnlinkDevice2CB");
2311     VERIFY_NOT_NULL_RETURN(TAG, unlinkCtx, ERROR, OC_STACK_DELETE_TRANSACTION);
2312     UnlinkData_t* unlinkData = (UnlinkData_t*)unlinkCtx;
2313
2314     if (clientResponse)
2315     {
2316         OIC_LOG(DEBUG, TAG, "Valid client response for device 2");
2317         clientResponse->result = OC_STACK_RESOURCE_DELETED;
2318         registerResultForUnlinkDevices(unlinkData, clientResponse->result, IDX_SECOND_DEVICE_RES);
2319
2320         if (OC_STACK_RESOURCE_DELETED == clientResponse->result)
2321         {
2322             OIC_LOG(DEBUG, TAG, "Credential of device2 revoked");
2323         }
2324         else
2325         {
2326             OIC_LOG(ERROR, TAG, "Unable to delete credential information from device 2");
2327             unlinkData->resultCallback(unlinkData->ctx,
2328                                        unlinkData->numOfResults, unlinkData->unlinkRes, true);
2329             goto error;
2330         }
2331     }
2332     else
2333     {
2334         registerResultForUnlinkDevices(unlinkData, OC_STACK_INVALID_REQUEST_HANDLE,
2335                                        IDX_SECOND_DEVICE_RES);
2336         unlinkData->resultCallback(unlinkData->ctx,
2337                                    unlinkData->numOfResults, unlinkData->unlinkRes, true);
2338         OIC_LOG(ERROR, TAG, "SRPUnlinkDevice2CB received Null clientResponse");
2339         goto error;
2340     }
2341
2342     //Update provisioning DB when succes case.
2343     if (OC_STACK_OK != PDMUnlinkDevices(&unlinkData->unlinkDev[0].doxm->deviceID,
2344                                        &unlinkData->unlinkDev[1].doxm->deviceID))
2345     {
2346         OIC_LOG(FATAL, TAG, "All requests are successfully done but update provisioning DB FAILED.");
2347         registerResultForUnlinkDevices(unlinkData, OC_STACK_INCONSISTENT_DB, IDX_DB_UPDATE_RES);
2348         unlinkData->resultCallback(unlinkData->ctx,
2349                                    unlinkData->numOfResults, unlinkData->unlinkRes, true);
2350         goto error;
2351     }
2352     unlinkData->resultCallback(unlinkData->ctx, unlinkData->numOfResults, unlinkData->unlinkRes,
2353                                false);
2354
2355 error:
2356     DeleteUnlinkData_t(unlinkData);
2357     OIC_LOG(DEBUG, TAG, "OUT SRPUnlinkDevice2CB");
2358     return OC_STACK_DELETE_TRANSACTION;
2359
2360 }
2361
2362 /**
2363  * Callback handler of unlink first device.
2364  *
2365  * @param[in] ctx             ctx value passed to callback from calling function.
2366  * @param[in] handle          handle to an invocation
2367  * @param[in] clientResponse  Response from queries to remote servers.
2368  * @return  OC_STACK_DELETE_TRANSACTION to delete the transaction and
2369  *          OC_STACK_KEEP_TRANSACTION to keep it.
2370  */
2371 static OCStackApplicationResult SRPUnlinkDevice1CB(void *unlinkCtx, OCDoHandle handle,
2372         OCClientResponse *clientResponse)
2373 {
2374     OIC_LOG_V(INFO, TAG, "Inside SRPUnlinkDevice1CB ");
2375     VERIFY_NOT_NULL_RETURN(TAG, unlinkCtx, ERROR, OC_STACK_DELETE_TRANSACTION);
2376     UnlinkData_t* unlinkData = (UnlinkData_t*)unlinkCtx;
2377     (void) handle;
2378
2379     if (clientResponse)
2380     {
2381         OIC_LOG(DEBUG, TAG, "Valid client response for device 1");
2382         clientResponse->result = OC_STACK_RESOURCE_DELETED;
2383         registerResultForUnlinkDevices(unlinkData, clientResponse->result, IDX_FIRST_DEVICE_RES);
2384
2385         if (OC_STACK_RESOURCE_DELETED == clientResponse->result)
2386         {
2387             OIC_LOG(DEBUG, TAG, "Credential of device 1 is revoked");
2388
2389             // Second revocation request to second device.
2390             OCStackResult res = SendDeleteCredentialRequest((void*)unlinkData, &SRPUnlinkDevice2CB,
2391                                                     &unlinkData->unlinkDev[0],
2392                                                     &unlinkData->unlinkDev[1] /*Dest*/);
2393             OIC_LOG_V(DEBUG, TAG, "Credential revocation request device 2, result :: %d",res);
2394             if (OC_STACK_OK != res)
2395             {
2396                  OIC_LOG(ERROR, TAG, "Error while sending revocation request for device 2");
2397                  registerResultForUnlinkDevices(unlinkData, OC_STACK_INVALID_REQUEST_HANDLE,
2398                                                 IDX_SECOND_DEVICE_RES);
2399                  unlinkData->resultCallback(unlinkData->ctx,
2400                                             unlinkData->numOfResults, unlinkData->unlinkRes, true);
2401                  goto error;
2402             }
2403             else
2404             {
2405                 OIC_LOG(DEBUG, TAG, "Request for credential revocation successfully sent");
2406                 return OC_STACK_DELETE_TRANSACTION;
2407             }
2408         }
2409         else
2410         {
2411             OIC_LOG(ERROR, TAG, "Unable to delete credential information from device 1");
2412
2413             unlinkData->resultCallback(unlinkData->ctx, unlinkData->numOfResults,
2414                                             unlinkData->unlinkRes, true);
2415             goto error;
2416         }
2417     }
2418     else
2419     {
2420         OIC_LOG(DEBUG, TAG, "Invalid response from server");
2421         registerResultForUnlinkDevices(unlinkData, OC_STACK_INVALID_REQUEST_HANDLE,
2422                                        IDX_FIRST_DEVICE_RES );
2423         unlinkData->resultCallback(unlinkData->ctx,
2424                                    unlinkData->numOfResults, unlinkData->unlinkRes,
2425                                    true);
2426         OIC_LOG(ERROR, TAG, "SRPUnlinkDevice1CB received Null clientResponse");
2427     }
2428
2429 error:
2430     OIC_LOG_V(INFO, TAG, "Out SRPUnlinkDevice1CB");
2431     DeleteUnlinkData_t(unlinkData);
2432     return OC_STACK_DELETE_TRANSACTION;
2433 }
2434
2435 /*
2436 * Function to unlink devices.
2437 * This function will remove the credential & relationship between the two devices.
2438 *
2439 * @param[in] ctx Application context would be returned in result callback
2440 * @param[in] pTargetDev1 first device information to be unlinked.
2441 * @param[in] pTargetDev2 second device information to be unlinked.
2442 * @param[in] resultCallback callback provided by API user, callback will be called when
2443 *            device unlink is finished.
2444  * @return  OC_STACK_OK in case of success and other value otherwise.
2445 */
2446 OCStackResult SRPUnlinkDevices(void* ctx,
2447                                const OCProvisionDev_t* pTargetDev1,
2448                                const OCProvisionDev_t* pTargetDev2,
2449                                OCProvisionResultCB resultCallback)
2450 {
2451     OIC_LOG(INFO, TAG, "IN SRPUnlinkDevices");
2452
2453     if (!pTargetDev1 || !pTargetDev2 || !pTargetDev1->doxm || !pTargetDev2->doxm)
2454     {
2455         OIC_LOG(INFO, TAG, "SRPUnlinkDevices : NULL parameters");
2456         return OC_STACK_INVALID_PARAM;
2457     }
2458     if (!resultCallback)
2459     {
2460         OIC_LOG(INFO, TAG, "SRPUnlinkDevices : NULL Callback");
2461         return OC_STACK_INVALID_CALLBACK;
2462     }
2463     if (0 == memcmp(&pTargetDev1->doxm->deviceID, &pTargetDev2->doxm->deviceID, sizeof(OicUuid_t)))
2464     {
2465         OIC_LOG(INFO, TAG, "SRPUnlinkDevices : Same device ID");
2466         return OC_STACK_INVALID_PARAM;
2467     }
2468
2469     OIC_LOG(INFO, TAG, "Unlinking following devices: ");
2470     PMPrintOCProvisionDev(pTargetDev1);
2471     PMPrintOCProvisionDev(pTargetDev2);
2472
2473     // Mark the link status stale
2474     OCStackResult res = PDMSetLinkStale(&pTargetDev1->doxm->deviceID, &pTargetDev2->doxm->deviceID);
2475     if (OC_STACK_OK != res)
2476     {
2477         OIC_LOG(FATAL, TAG, "unable to update DB. Try again.");
2478         return res;
2479     }
2480
2481     UnlinkData_t* unlinkData = (UnlinkData_t*)OICCalloc(1, sizeof(UnlinkData_t));
2482     VERIFY_NOT_NULL_RETURN(TAG, unlinkData, ERROR, OC_STACK_NO_MEMORY);
2483
2484     //Initialize unlink data
2485     unlinkData->ctx = ctx;
2486     unlinkData->unlinkDev = (OCProvisionDev_t*)OICCalloc(2, sizeof(OCProvisionDev_t));
2487     if (NULL == unlinkData->unlinkDev)
2488     {
2489         OIC_LOG(ERROR, TAG, "Memory allocation failed");
2490         res = OC_STACK_NO_MEMORY;
2491         goto error;
2492     }
2493
2494     unlinkData->unlinkRes = (OCProvisionResult_t*)OICCalloc(3, sizeof(OCProvisionResult_t));
2495     if (NULL == unlinkData->unlinkRes)
2496     {
2497         OIC_LOG(ERROR, TAG, "Memory allocation failed");
2498         res = OC_STACK_NO_MEMORY;
2499         goto error;
2500     }
2501
2502     memcpy(&unlinkData->unlinkDev[0], pTargetDev1, sizeof(OCProvisionDev_t));
2503     memcpy(&unlinkData->unlinkDev[1], pTargetDev2, sizeof(OCProvisionDev_t));
2504
2505     unlinkData->numOfResults = 0;
2506     unlinkData->resultCallback = resultCallback;
2507
2508     res = SendDeleteCredentialRequest((void*)unlinkData, &SRPUnlinkDevice1CB,
2509                                        &unlinkData->unlinkDev[1], &unlinkData->unlinkDev[0]);
2510     if (OC_STACK_OK != res)
2511     {
2512         OIC_LOG(ERROR, TAG, "SRPUnlinkDevices : SendDeleteCredentialRequest failed");
2513         goto error;
2514     }
2515
2516     return res;
2517
2518 error:
2519     OIC_LOG(INFO, TAG, "OUT SRPUnlinkDevices");
2520     DeleteUnlinkData_t(unlinkData);
2521     return res;
2522 }
2523
2524 static void DeleteRemoveData_t(RemoveData_t* pRemoveData)
2525 {
2526     if (pRemoveData)
2527     {
2528         OICFree(pRemoveData->revokeTargetDev);
2529         OCDeleteDiscoveredDevices(pRemoveData->linkedDevList);
2530         OICFree(pRemoveData->removeRes);
2531         OICFree(pRemoveData);
2532     }
2533 }
2534
2535 static void registerResultForRemoveDevice(RemoveData_t *removeData, OicUuid_t *pLinkedDevId,
2536                                           OCStackResult stackresult, bool hasError)
2537 {
2538     OIC_LOG_V(INFO, TAG, "Inside registerResultForRemoveDevice removeData->numOfResults is %" PRIuPTR,
2539                          removeData->numOfResults + 1);
2540     if (pLinkedDevId)
2541     {
2542         memcpy(removeData->removeRes[(removeData->numOfResults)].deviceId.id,
2543                &pLinkedDevId->id, sizeof(pLinkedDevId->id));
2544     }
2545     else
2546     {
2547         memset(removeData->removeRes[(removeData->numOfResults)].deviceId.id,
2548                0, sizeof(pLinkedDevId->id) );
2549     }
2550     removeData->removeRes[(removeData->numOfResults)].res = stackresult;
2551     removeData->hasError = hasError;
2552     ++(removeData->numOfResults);
2553
2554     // If we get suffcient result from linked devices, we have to call user callback and do free
2555     if (removeData->sizeOfResArray == removeData->numOfResults)
2556     {
2557         if(!removeData->hasError)
2558         {
2559             // Remove device info from prvisioning database
2560             if (OC_STACK_OK != PDMDeleteDevice(&removeData->revokeTargetDev->doxm->deviceID))
2561             {
2562                 OIC_LOG(ERROR, TAG, "ResultForRemoveDevice : Failed to remove device in PDM.");
2563                 removeData->hasError = true;
2564             }
2565         }
2566         removeData->resultCallback(removeData->ctx, removeData->numOfResults, removeData->removeRes,
2567                                    removeData->hasError);
2568         DeleteRemoveData_t(removeData);
2569     }
2570  }
2571
2572 static void registerResultForResetDevice(RemoveData_t *removeData, OicUuid_t *pLinkedDevId,
2573                                           OCStackResult stackresult, bool hasError)
2574 {
2575     OIC_LOG_V(INFO, TAG, "Inside registerResultForResetDevice removeData->numOfResults is %" PRIuPTR,
2576                          removeData->numOfResults + 1);
2577     if (pLinkedDevId)
2578     {
2579         memcpy(removeData->removeRes[(removeData->numOfResults)].deviceId.id,
2580                &pLinkedDevId->id, sizeof(pLinkedDevId->id));
2581     }
2582     else
2583     {
2584         memset(removeData->removeRes[(removeData->numOfResults)].deviceId.id,
2585                0, sizeof(pLinkedDevId->id) );
2586     }
2587     removeData->removeRes[(removeData->numOfResults)].res = stackresult;
2588     removeData->hasError = hasError;
2589     ++(removeData->numOfResults);
2590
2591     // If we get suffcient result from linked devices, we have to call user callback and do free
2592     if (removeData->sizeOfResArray == removeData->numOfResults)
2593     {
2594         removeData->resultCallback(removeData->ctx, removeData->numOfResults, removeData->removeRes,
2595                                    removeData->hasError);
2596         DeleteRemoveData_t(removeData);
2597     }
2598 }
2599
2600 /**
2601  * Callback handler of unlink first device.
2602  *
2603  * @param[in] ctx             ctx value passed to callback from calling function.
2604  * @param[in] handle          handle to an invocation
2605  * @param[in] clientResponse  Response from queries to remote servers.
2606  * @return  OC_STACK_DELETE_TRANSACTION to delete the transaction
2607  *          and  OC_STACK_KEEP_TRANSACTION to keep it.
2608  */
2609 static OCStackApplicationResult SRPRemoveDeviceCB(void *delDevCtx, OCDoHandle handle,
2610         OCClientResponse *clientResponse)
2611 {
2612     //Update the delete credential into delete device context
2613     //Save the deleted status in delDevCtx
2614     (void)handle;
2615     OIC_LOG_V(INFO, TAG, "Inside SRPRemoveDeviceCB.");
2616     VERIFY_NOT_NULL_RETURN(TAG, delDevCtx, ERROR, OC_STACK_DELETE_TRANSACTION);
2617     OCStackResult res = OC_STACK_ERROR;
2618
2619     RemoveData_t* removeData = (RemoveData_t*)delDevCtx;
2620
2621     if (clientResponse)
2622     {
2623         OicUuid_t revDevUuid = {.id={0}};
2624         if(UUID_LENGTH == clientResponse->identity.id_length)
2625         {
2626             memcpy(revDevUuid.id, clientResponse->identity.id, sizeof(revDevUuid.id));
2627             if (OC_STACK_RESOURCE_DELETED == clientResponse->result)
2628             {
2629                 res = PDMUnlinkDevices(&removeData->revokeTargetDev->doxm->deviceID, &revDevUuid);
2630                 if (OC_STACK_OK != res)
2631                 {
2632                     OIC_LOG(ERROR, TAG, "PDMSetLinkStale() FAIL: PDB is an obsolete one.");
2633                            registerResultForRemoveDevice(removeData, &revDevUuid,
2634                            OC_STACK_INCONSISTENT_DB, true);
2635
2636                     return OC_STACK_DELETE_TRANSACTION;
2637                 }
2638
2639                 registerResultForRemoveDevice(removeData, &revDevUuid,
2640                                               OC_STACK_RESOURCE_DELETED, false);
2641             }
2642             else
2643             {
2644                 registerResultForRemoveDevice(removeData, &revDevUuid,
2645                                               clientResponse->result, true);
2646                 OIC_LOG(ERROR, TAG, "Unexpected result from DELETE credential request!");
2647             }
2648         }
2649         else
2650         {
2651             OIC_LOG_V(WARNING, TAG, "Incorrect length of device UUID was sent from %s:%d",
2652                      clientResponse->devAddr.addr, clientResponse->devAddr.port);
2653
2654             if (OC_STACK_RESOURCE_DELETED == clientResponse->result)
2655             {
2656                 /**
2657                   * Since server's credential was deleted,
2658                   * register result as OC_STACK_INCONSISTENT_DB with NULL UUID.
2659                   */
2660                 OIC_LOG_V(ERROR, TAG, "But server's credential was deleted.");
2661                 registerResultForRemoveDevice(removeData, NULL, OC_STACK_INCONSISTENT_DB, true);
2662             }
2663             else
2664             {
2665                 registerResultForRemoveDevice(removeData, NULL, clientResponse->result, true);
2666             }
2667         }
2668     }
2669     else
2670     {
2671         registerResultForRemoveDevice(removeData, NULL, OC_STACK_ERROR, true);
2672         OIC_LOG(ERROR, TAG, "SRPRemoveDevices received Null clientResponse");
2673     }
2674
2675     return OC_STACK_DELETE_TRANSACTION;
2676 }
2677
2678 /**
2679  * Callback handler of reset device.
2680  *
2681  * @param[in] ctx             ctx value passed to callback from calling function.
2682  * @param[in] handle          handle to an invocation
2683  * @param[in] clientResponse  Response from queries to remote servers.
2684  * @return  OC_STACK_DELETE_TRANSACTION to delete the transaction
2685  *          and  OC_STACK_KEEP_TRANSACTION to keep it.
2686  */
2687 static OCStackApplicationResult SRPSyncDeviceCredCB(void *delDevCtx, OCDoHandle handle,
2688         OCClientResponse *clientResponse)
2689 {
2690     //Update the delete credential into delete device context
2691     //Save the deleted status in delDevCtx
2692     (void)handle;
2693     OIC_LOG_V(INFO, TAG, "Inside SRPSyncDeviceCredCB.");
2694     VERIFY_NOT_NULL_RETURN(TAG, delDevCtx, ERROR, OC_STACK_DELETE_TRANSACTION);
2695     OCStackResult res = OC_STACK_ERROR;
2696
2697     RemoveData_t* removeData = (RemoveData_t*)delDevCtx;
2698     OCProvisionDev_t * pTargetDev = PMCloneOCProvisionDev(removeData->revokeTargetDev);
2699     OCProvisionResultCB resultCallback = removeData->resultCallback;
2700     if (clientResponse)
2701     {
2702         OicUuid_t revDevUuid = {.id={0}};
2703         if(UUID_LENGTH == clientResponse->identity.id_length)
2704         {
2705             memcpy(revDevUuid.id, clientResponse->identity.id, sizeof(revDevUuid.id));
2706             if (OC_STACK_RESOURCE_DELETED == clientResponse->result)
2707             {
2708                 res = PDMUnlinkDevices(&removeData->revokeTargetDev->doxm->deviceID, &revDevUuid);
2709                 if (OC_STACK_OK != res)
2710                 {
2711                     OIC_LOG(ERROR, TAG, "PDMSetLinkStale() FAIL: PDB is an obsolete one.");
2712                            registerResultForResetDevice(removeData, &revDevUuid,
2713                            OC_STACK_INCONSISTENT_DB, true);
2714
2715                     return OC_STACK_DELETE_TRANSACTION;
2716                 }
2717
2718                 registerResultForResetDevice(removeData, &revDevUuid,
2719                                               OC_STACK_RESOURCE_DELETED, false);
2720             }
2721             else
2722             {
2723                 registerResultForResetDevice(removeData, &revDevUuid,
2724                                               clientResponse->result, false);
2725                 OIC_LOG(ERROR, TAG, "Unexpected result from DELETE credential request!");
2726             }
2727         }
2728         else
2729         {
2730             OIC_LOG_V(WARNING, TAG, "Incorrect length of device UUID was sent from %s:%d",
2731                      clientResponse->devAddr.addr, clientResponse->devAddr.port);
2732
2733             if (OC_STACK_RESOURCE_DELETED == clientResponse->result)
2734             {
2735                 /**
2736                   * Since server's credential was deleted,
2737                   * register result as OC_STACK_INCONSISTENT_DB with NULL UUID.
2738                   */
2739                 OIC_LOG_V(ERROR, TAG, "But server's credential was deleted.");
2740                 registerResultForResetDevice(removeData, NULL, OC_STACK_INCONSISTENT_DB, true);
2741             }
2742             else
2743             {
2744                 registerResultForResetDevice(removeData, NULL, clientResponse->result, true);
2745             }
2746         }
2747     }
2748     else
2749     {
2750         registerResultForResetDevice(removeData, NULL, OC_STACK_ERROR, true);
2751         OIC_LOG(ERROR, TAG, "SRPSyncDevice received Null clientResponse");
2752     }
2753
2754     SRPResetDevice(pTargetDev, resultCallback);
2755
2756     return OC_STACK_DELETE_TRANSACTION;
2757 }
2758
2759 /**
2760  * Callback handler of reset device sync-up
2761  *
2762  * @param[in] ctx             ctx value passed to callback from calling function.
2763  * @param[in] handle          handle to an invocation
2764  * @param[in] clientResponse  Response from queries to remote servers.
2765  * @return  OC_STACK_DELETE_TRANSACTION to delete the transaction
2766  *          and  OC_STACK_KEEP_TRANSACTION to keep it.
2767  */
2768 static OCStackApplicationResult SRPSyncDeviceACLCB(void *ctx, OCDoHandle UNUSED,
2769         OCClientResponse *clientResponse)
2770 {
2771     (void)ctx;
2772     (void)UNUSED;
2773     (void)clientResponse;
2774     return OC_STACK_DELETE_TRANSACTION;
2775 }
2776
2777 /**
2778  * Callback handler of device remote reset.
2779  *
2780  * @param[in] ctx             ctx value passed to callback from calling function.
2781  * @param[in] UNUSED          handle to an invocation
2782  * @param[in] clientResponse  Response from queries to remote servers.
2783  * @return  OC_STACK_DELETE_TRANSACTION to delete the transaction
2784  *          and  OC_STACK_KEEP_TRANSACTION to keep it.
2785  */
2786 static OCStackApplicationResult SRPResetDeviceCB(void *ctx, OCDoHandle UNUSED,
2787         OCClientResponse *clientResponse)
2788 {
2789     OIC_LOG(DEBUG, TAG, "IN SRPResetDeviceCB");
2790     (void)UNUSED;
2791     if(OC_STACK_OK == clientResponse->result)
2792     {
2793         OIC_LOG(DEBUG, TAG, "Change Target Device Pstat Cm SUCCEEDED");
2794     }
2795
2796     // Delete Cred and ACL related to the target device.
2797     const OicSecCred_t *cred = NULL;
2798     OCProvisionDev_t * pTargetDev = (OCProvisionDev_t *)ctx;
2799     cred = GetCredResourceData(&pTargetDev->doxm->deviceID);
2800     if (cred == NULL)
2801     {
2802         OIC_LOG(ERROR, TAG, "OCResetDevice : Failed to get credential of target device.");
2803         goto error;
2804     }
2805
2806     OCStackResult res = RemoveCredential(&cred->subject);
2807     if (res != OC_STACK_RESOURCE_DELETED && res != OC_STACK_NO_RESOURCE)
2808     {
2809         OIC_LOG(ERROR, TAG, "OCResetDevice : Failed to remove credential.");
2810         goto error;
2811     }
2812
2813     res = RemoveACE(&cred->subject, NULL);
2814     if (res != OC_STACK_RESOURCE_DELETED && res != OC_STACK_NO_RESOURCE)
2815     {
2816         OIC_LOG(ERROR, TAG, "OCResetDevice : Failed to remove ACL.");
2817         goto error;
2818     }
2819     if (OC_STACK_OK != PDMDeleteDevice(&pTargetDev->doxm->deviceID))
2820     {
2821         OIC_LOG(ERROR, TAG, "OCResetDevice : Failed to delete device from PDM");
2822     }
2823
2824     //Close the DTLS session of the reset device.
2825     CAEndpoint_t endpoint = {.adapter = CA_DEFAULT_ADAPTER};
2826     CopyDevAddrToEndpoint(&clientResponse->devAddr, &endpoint);
2827     CAResult_t caResult = CAcloseSslSession(&endpoint);
2828     if(CA_STATUS_OK != caResult)
2829     {
2830         OIC_LOG_V(WARNING, TAG, "OCResetDevice : Failed to close DTLS session : %d", caResult);
2831     }
2832
2833     /**
2834      * If there is no linked device, PM does not send any request.
2835      * So we should directly invoke the result callback to inform the result of OCResetDevice.
2836      */
2837     if(OC_STACK_NO_RESOURCE == res)
2838     {
2839         res = OC_STACK_OK;
2840     }
2841
2842 error:
2843     OICFree(pTargetDev);
2844     return OC_STACK_DELETE_TRANSACTION;
2845
2846 }
2847
2848 static OCStackResult GetListofDevToReqDeleteCred(const OCProvisionDev_t* pRevokeTargetDev,
2849                                                  const OCProvisionDev_t* pOwnedDevList,
2850                                                  OCUuidList_t* pLinkedUuidList,
2851                                                  OCProvisionDev_t** ppLinkedDevList,
2852                                                  size_t *numOfLinkedDev)
2853 {
2854     // pOwnedDevList could be NULL. It means no alived and owned device now.
2855     if (pRevokeTargetDev == NULL || pLinkedUuidList == NULL ||\
2856         ppLinkedDevList == NULL || numOfLinkedDev == NULL)
2857     {
2858         return OC_STACK_INVALID_PARAM;
2859     }
2860
2861     size_t cnt = 0;
2862     OCUuidList_t *curUuid = NULL, *tmpUuid = NULL;
2863     LL_FOREACH_SAFE(pLinkedUuidList, curUuid, tmpUuid)
2864     {
2865         // Mark the link status stale.
2866         OCStackResult res = PDMSetLinkStale(&curUuid->dev, &pRevokeTargetDev->doxm->deviceID);
2867         if (OC_STACK_OK != res)
2868         {
2869             OIC_LOG(FATAL, TAG, "PDMSetLinkStale() FAIL: PDB is an obsolete one.");
2870             return OC_STACK_INCONSISTENT_DB;
2871         }
2872
2873         if (pOwnedDevList)
2874         {
2875             // If this linked device is alive (power-on), add the deivce to the list.
2876             const OCProvisionDev_t *curDev = NULL;
2877             const OCProvisionDev_t *tmpDev = NULL;
2878             LL_FOREACH_SAFE(pOwnedDevList, curDev, tmpDev)
2879             {
2880                 if (memcmp(curDev->doxm->deviceID.id, curUuid->dev.id, sizeof(curUuid->dev.id)) == 0)
2881                 {
2882                     OCProvisionDev_t* targetDev = PMCloneOCProvisionDev(curDev);
2883                     if (NULL == targetDev)
2884                     {
2885                         OIC_LOG(ERROR, TAG, "SRPRemoveDevice : Cloning OCProvisionDev_t Failed.");
2886                         return OC_STACK_NO_MEMORY;
2887                     }
2888
2889                     LL_PREPEND(*ppLinkedDevList, targetDev);
2890                     cnt++;
2891                     break;
2892                 }
2893             }
2894         }
2895     }
2896     *numOfLinkedDev = cnt;
2897     return OC_STACK_OK;
2898 }
2899
2900 /*
2901 * Function to device revocation
2902 * This function will remove credential of target device from all devices in subnet.
2903 *
2904 * @param[in] ctx Application context would be returned in result callback
2905 * @param[in] waitTimeForOwnedDeviceDiscovery Maximum wait time for owned device discovery.(seconds)
2906 * @param[in] pTargetDev Device information to be revoked.
2907 * @param[in] resultCallback callback provided by API user, callback will be called when
2908 *            credential revocation is finished.
2909 * @return  OC_STACK_OK in case of success and other value otherwise.
2910 *          If OC_STACK_OK is returned, the caller of this API should wait for callback.
2911 *          OC_STACK_CONTINUE means operation is success but no request is need to be initiated.
2912 */
2913 OCStackResult SRPRemoveDevice(void* ctx, unsigned short waitTimeForOwnedDeviceDiscovery,
2914                              const OCProvisionDev_t* pTargetDev, OCProvisionResultCB resultCallback)
2915 {
2916     OIC_LOG(INFO, TAG, "IN SRPRemoveDevice");
2917
2918     if (!pTargetDev  || 0 == waitTimeForOwnedDeviceDiscovery)
2919     {
2920         OIC_LOG(INFO, TAG, "SRPRemoveDevice : NULL parameters");
2921         return OC_STACK_INVALID_PARAM;
2922     }
2923     if (!resultCallback)
2924     {
2925         OIC_LOG(INFO, TAG, "SRPRemoveDevice : NULL Callback");
2926         return OC_STACK_INVALID_CALLBACK;
2927     }
2928
2929     // Declare variables in here to handle error cases with goto statement.
2930     OCProvisionDev_t* pOwnedDevList = NULL;
2931     OCProvisionDev_t* pLinkedDevList = NULL;
2932     RemoveData_t* removeData = NULL;
2933
2934     //1. Find all devices that has a credential of the revoked device
2935     OCUuidList_t* pLinkedUuidList = NULL;
2936     size_t numOfDevices = 0;
2937     OCStackResult res = OC_STACK_ERROR;
2938     res = PDMGetLinkedDevices(&pTargetDev->doxm->deviceID, &pLinkedUuidList, &numOfDevices);
2939     if (OC_STACK_OK != res)
2940     {
2941         OIC_LOG(ERROR, TAG, "SRPRemoveDevice : Failed to get linked devices information");
2942         return res;
2943     }
2944     // if there is no related device, we can skip further process.
2945     if (0 == numOfDevices)
2946     {
2947         OIC_LOG(DEBUG, TAG, "SRPRemoveDevice : No linked device found.");
2948         res = OC_STACK_CONTINUE;
2949         goto error;
2950     }
2951
2952     //2. Find owned device from the network
2953     res = PMDeviceDiscovery(waitTimeForOwnedDeviceDiscovery, true, &pOwnedDevList);
2954     if (OC_STACK_OK != res)
2955     {
2956         OIC_LOG(ERROR, TAG, "SRPRemoveDevice : Failed to PMDeviceDiscovery");
2957         goto error;
2958     }
2959
2960     //3. Make a list of devices to send DELETE credential request
2961     //   by comparing owned devices from provisioning database with mutlicast discovery result.
2962     size_t numOfLinkedDev = 0;
2963     res = GetListofDevToReqDeleteCred(pTargetDev, pOwnedDevList, pLinkedUuidList,
2964                                       &pLinkedDevList, &numOfLinkedDev);
2965     if (OC_STACK_OK != res)
2966     {
2967         OIC_LOG(ERROR, TAG, "SRPRemoveDevice : GetListofDevToReqDeleteCred() failed");
2968         goto error;
2969     }
2970     if (0 == numOfLinkedDev) // This case means, there is linked device but it's not alive now.
2971     {                       // So we don't have to send request message.
2972         OIC_LOG(DEBUG, TAG, "SRPRemoveDevice : No alived & linked device found.");
2973         res = OC_STACK_CONTINUE;
2974         goto error;
2975     }
2976
2977     // 4. Prepare RemoveData Context data.
2978     removeData = (RemoveData_t*)OICCalloc(1, sizeof(RemoveData_t));
2979     if (!removeData)
2980     {
2981         OIC_LOG(ERROR, TAG, "SRPRemoveDevices : Failed to allocate memory");
2982         res = OC_STACK_NO_MEMORY;
2983         goto error;
2984     }
2985
2986     removeData->revokeTargetDev = PMCloneOCProvisionDev(pTargetDev);
2987     if (!removeData->revokeTargetDev)
2988     {
2989         OIC_LOG(ERROR, TAG, "SRPRemoveDevices : PMCloneOCProvisionDev Failed");
2990         res = OC_STACK_NO_MEMORY;
2991         goto error;
2992     }
2993
2994     removeData->removeRes =
2995         (OCProvisionResult_t*)OICCalloc(numOfLinkedDev, sizeof(OCProvisionResult_t));
2996     if (!removeData->removeRes)
2997     {
2998         OIC_LOG(ERROR, TAG, "SRPRemoveDevices : Failed to allocate memory");
2999         res = OC_STACK_NO_MEMORY;
3000         goto error;
3001     }
3002
3003     removeData->ctx = ctx;
3004     removeData->linkedDevList = pLinkedDevList;
3005     removeData->resultCallback = resultCallback;
3006     removeData->numOfResults = 0;
3007     removeData->sizeOfResArray = numOfLinkedDev;
3008     removeData->hasError = false;
3009
3010     // 5. Send DELETE credential request to linked devices.
3011     OCProvisionDev_t *curDev = NULL, *tmpDev = NULL;
3012     OCStackResult totalRes = OC_STACK_ERROR;  /* variable for checking request is sent or not */
3013     LL_FOREACH_SAFE(pLinkedDevList, curDev, tmpDev)
3014     {
3015         res = SendDeleteCredentialRequest((void*)removeData, &SRPRemoveDeviceCB,
3016                                            removeData->revokeTargetDev, curDev);
3017         if (OC_STACK_OK != res)
3018         {
3019             OIC_LOG_V(ERROR, TAG, "SRPRemoveDevice : Fail to send the DELETE credential request to\
3020                      %s:%u", curDev->endpoint.addr, curDev->endpoint.port);
3021         }
3022         else
3023         {
3024             totalRes = OC_STACK_OK; // This means at least one request is successfully sent.
3025         }
3026     }
3027
3028     PDMDestoryOicUuidLinkList(pLinkedUuidList); //TODO: Modify API name to have unified convention.
3029     PMDeleteDeviceList(pOwnedDevList);
3030     OIC_LOG(INFO, TAG, "OUT SRPRemoveDevice");
3031
3032     return totalRes; // Caller of this API should wait callback if totalRes == OC_STACK_OK.
3033
3034 error:
3035     PDMDestoryOicUuidLinkList(pLinkedUuidList);
3036     PMDeleteDeviceList(pOwnedDevList);
3037     PMDeleteDeviceList(pLinkedDevList);
3038     if (removeData)
3039     {
3040         OICFree(removeData->revokeTargetDev);
3041         OICFree(removeData->removeRes);
3042         OICFree(removeData);
3043     }
3044     OIC_LOG(INFO, TAG, "OUT ERROR case SRPRemoveDevice");
3045     return res;
3046 }
3047
3048 /*
3049 * Function to device revocation
3050 * This function will remove credential of target device from all devices in subnet.
3051 *
3052 * @param[in] ctx Application context would be returned in result callback
3053 * @param[in] pOwnedDevList List of owned devices
3054 * @param[in] pTargetDev Device information to be revoked.
3055 * @param[in] resultCallback callback provided by API user, callback will be called when
3056 *            credential revocation is finished.
3057 * @return  OC_STACK_OK in case of success and other value otherwise.
3058 *          If OC_STACK_OK is returned, the caller of this API should wait for callback.
3059 *          OC_STACK_CONTINUE means operation is success but no request is need to be initiated.
3060 */
3061 OCStackResult SRPRemoveDeviceWithoutDiscovery(void* ctx, const OCProvisionDev_t* pOwnedDevList,
3062                              const OCProvisionDev_t* pTargetDev, OCProvisionResultCB resultCallback)
3063 {
3064     OIC_LOG(INFO, TAG, "IN SRPRemoveDeviceWithoutDiscovery");
3065
3066     if (!pOwnedDevList)
3067     {
3068         OIC_LOG(WARNING, TAG, "SRPRemoveDeviceWithoutDiscovery : Owned Device List is empty");
3069         return OC_STACK_CONTINUE;
3070     }
3071     if (!pTargetDev)
3072     {
3073         OIC_LOG(INFO, TAG, "SRPRemoveDeviceWithoutDiscovery : NULL parameters");
3074         return OC_STACK_INVALID_PARAM;
3075     }
3076     if (!resultCallback)
3077     {
3078         OIC_LOG(INFO, TAG, "SRPRemoveDeviceWithoutDiscovery : NULL Callback");
3079         return OC_STACK_INVALID_CALLBACK;
3080     }
3081
3082     // Declare variables in here to handle error cases with goto statement.
3083     OCProvisionDev_t* pLinkedDevList = NULL;
3084     RemoveData_t* removeData = NULL;
3085
3086     //1. Find all devices that has a credential of the revoked device
3087     OCUuidList_t* pLinkedUuidList = NULL;
3088     size_t numOfDevices = 0;
3089     OCStackResult res = OC_STACK_ERROR;
3090     res = PDMGetLinkedDevices(&pTargetDev->doxm->deviceID, &pLinkedUuidList, &numOfDevices);
3091     if (OC_STACK_OK != res)
3092     {
3093         OIC_LOG(WARNING, TAG, "SRPRemoveDeviceWithoutDiscovery : Failed to get linked devices information");
3094         return OC_STACK_CONTINUE;
3095     }
3096     // if there is no related device, we can skip further process.
3097     if (0 == numOfDevices)
3098     {
3099         OIC_LOG(WARNING, TAG, "SRPRemoveDeviceWithoutDiscovery : No linked device found.");
3100         return OC_STACK_CONTINUE;
3101     }
3102
3103     //2. Make a list of devices to send DELETE credential request
3104     //   by comparing owned devices from provisioning database with mutlicast discovery result.
3105     size_t numOfLinkedDev = 0;
3106     res = GetListofDevToReqDeleteCred(pTargetDev, pOwnedDevList, pLinkedUuidList,
3107                                       &pLinkedDevList, &numOfLinkedDev);
3108     if (OC_STACK_OK != res)
3109     {
3110         OIC_LOG(ERROR, TAG, "SRPRemoveDeviceWithoutDiscovery : GetListofDevToReqDeleteCred() failed");
3111         goto error;
3112     }
3113     if (0 == numOfLinkedDev) // This case means, there is linked device but it's not alive now.
3114     {                       // So we don't have to send request message.
3115         OIC_LOG(DEBUG, TAG, "SRPRemoveDeviceWithoutDiscovery : No alived & linked device found.");
3116         return OC_STACK_CONTINUE;
3117     }
3118
3119     // 3. Prepare RemoveData Context data.
3120     removeData = (RemoveData_t*)OICCalloc(1, sizeof(RemoveData_t));
3121     if (!removeData)
3122     {
3123         OIC_LOG(ERROR, TAG, "SRPRemoveDeviceWithoutDiscovery : Failed to allocate memory");
3124         res = OC_STACK_NO_MEMORY;
3125         goto error;
3126     }
3127
3128     removeData->revokeTargetDev = PMCloneOCProvisionDev(pTargetDev);
3129     if (!removeData->revokeTargetDev)
3130     {
3131         OIC_LOG(ERROR, TAG, "SRPRemoveDeviceWithoutDiscovery : PMCloneOCProvisionDev Failed");
3132         res = OC_STACK_NO_MEMORY;
3133         goto error;
3134     }
3135
3136     removeData->removeRes =
3137         (OCProvisionResult_t*)OICCalloc(numOfLinkedDev, sizeof(OCProvisionResult_t));
3138     if (!removeData->removeRes)
3139     {
3140         OIC_LOG(ERROR, TAG, "SRPRemoveDeviceWithoutDiscovery : Failed to allocate memory");
3141         res = OC_STACK_NO_MEMORY;
3142         goto error;
3143     }
3144
3145     removeData->ctx = ctx;
3146     removeData->linkedDevList = pLinkedDevList;
3147     removeData->resultCallback = resultCallback;
3148     removeData->numOfResults = 0;
3149     removeData->sizeOfResArray = numOfLinkedDev;
3150     removeData->hasError = false;
3151
3152     // 5. Send DELETE credential request to linked devices.
3153     OCProvisionDev_t *curDev = NULL, *tmpDev = NULL;
3154     OCStackResult totalRes = OC_STACK_ERROR;  /* variable for checking request is sent or not */
3155     LL_FOREACH_SAFE(pLinkedDevList, curDev, tmpDev)
3156     {
3157         res = SendDeleteCredentialRequest((void*)removeData, &SRPRemoveDeviceCB,
3158                                            removeData->revokeTargetDev, curDev);
3159         if (OC_STACK_OK != res)
3160         {
3161             OIC_LOG_V(ERROR, TAG, "SRPRemoveDeviceWithoutDiscovery : Fail to send the DELETE credential request to\
3162                      %s:%u", curDev->endpoint.addr, curDev->endpoint.port);
3163         }
3164         else
3165         {
3166             totalRes = OC_STACK_OK; // This means at least one request is successfully sent.
3167         }
3168     }
3169
3170     PDMDestoryOicUuidLinkList(pLinkedUuidList); //TODO: Modify API name to have unified convention.
3171     OIC_LOG(INFO, TAG, "OUT SRPRemoveDeviceWithoutDiscovery");
3172
3173     return totalRes; // Caller of this API should wait callback if totalRes == OC_STACK_OK.
3174
3175 error:
3176     PDMDestoryOicUuidLinkList(pLinkedUuidList);
3177     PMDeleteDeviceList(pLinkedDevList);
3178     if (removeData)
3179     {
3180         OICFree(removeData->revokeTargetDev);
3181         OICFree(removeData->removeRes);
3182         OICFree(removeData);
3183     }
3184     OIC_LOG(INFO, TAG, "OUT ERROR case SRPRemoveDeviceWithoutDiscovery");
3185     return res;
3186 }
3187
3188 /*
3189  * Function to sync-up credential and ACL of the target device.
3190  * This function will remove credential and ACL of target device from all devices in subnet.
3191  *
3192  * @param[in] ctx Application context would be returned in result callback
3193  * @param[in] waitTimeForOwnedDeviceDiscovery Maximum wait time for owned device discovery.(seconds)
3194  * @param[in] pTargetDev Device information to be revoked.
3195  * @param[in] resultCallback callback provided by API user, callback will be called when
3196  *            credential revocation is finished.
3197  *            when there is an error, this user callback is called immediately.
3198  * @return OC_STACK_OK in case of success and other value otherwise.
3199  *         If OC_STACK_OK is returned, the caller of this API should wait for callback.
3200  *         OC_STACK_CONTINUE means operation is success but no request is need to be initiated.
3201  */
3202 OCStackResult SRPSyncDevice(void* ctx, unsigned short waitTimeForOwnedDeviceDiscovery,
3203                          const OCProvisionDev_t* pTargetDev, OCProvisionResultCB resultCallback)
3204 {
3205     OIC_LOG(INFO, TAG, "IN SRPSyncDevice");
3206     if (!pTargetDev  || 0 == waitTimeForOwnedDeviceDiscovery)
3207     {
3208         OIC_LOG(INFO, TAG, "SRPSyncDevice : NULL parameters");
3209         return OC_STACK_INVALID_PARAM;
3210     }
3211     if (!resultCallback)
3212     {
3213         OIC_LOG(INFO, TAG, "SRPSyncDevice : NULL Callback");
3214         return OC_STACK_INVALID_CALLBACK;
3215     }
3216
3217     // Declare variables in here to handle error cases with goto statement.
3218     OCProvisionDev_t* pOwnedDevList = NULL;
3219     OCProvisionDev_t* pLinkedDevList = NULL;
3220     RemoveData_t* removeData = NULL;
3221
3222     //1. Find all devices that has a credential of the revoked device
3223     OCUuidList_t* pLinkedUuidList = NULL;
3224     size_t numOfDevices = 0;
3225     OCStackResult res = OC_STACK_ERROR;
3226     res = PDMGetLinkedDevices(&pTargetDev->doxm->deviceID, &pLinkedUuidList, &numOfDevices);
3227     if (OC_STACK_OK != res)
3228     {
3229         OIC_LOG(ERROR, TAG, "SRPSyncDevice : Failed to get linked devices information");
3230         return res;
3231     }
3232     // if there is no related device, we can skip further process.
3233     if (0 == numOfDevices)
3234     {
3235         OIC_LOG(DEBUG, TAG, "SRPSyncDevice : No linked device found.");
3236         res = OC_STACK_CONTINUE;
3237         goto error;
3238     }
3239
3240     //2. Find owned device from the network
3241     res = PMDeviceDiscovery(waitTimeForOwnedDeviceDiscovery, true, &pOwnedDevList);
3242     if (OC_STACK_OK != res)
3243     {
3244         OIC_LOG(ERROR, TAG, "SRPSyncDevice : Failed to PMDeviceDiscovery");
3245         goto error;
3246     }
3247
3248     //3. Make a list of devices to send DELETE credential request
3249     //   by comparing owned devices from provisioning database with mutlicast discovery result.
3250     size_t numOfLinkedDev = 0;
3251     res = GetListofDevToReqDeleteCred(pTargetDev, pOwnedDevList, pLinkedUuidList,
3252                                       &pLinkedDevList, &numOfLinkedDev);
3253     if (OC_STACK_OK != res)
3254     {
3255         OIC_LOG(ERROR, TAG, "SRPSyncDevice : GetListofDevToReqDeleteCred() failed");
3256         goto error;
3257     }
3258     if (0 == numOfLinkedDev) // This case means, there is linked device but it's not alive now.
3259     {                       // So we don't have to send request message.
3260         OIC_LOG(DEBUG, TAG, "SRPSyncDevice : No alived & linked device found.");
3261         res = OC_STACK_CONTINUE;
3262         goto error;
3263     }
3264
3265     // 4. Prepare RemoveData Context data.
3266     removeData = (RemoveData_t*)OICCalloc(1, sizeof(RemoveData_t));
3267     if (!removeData)
3268     {
3269         OIC_LOG(ERROR, TAG, "SRPSyncDevice : Failed to allocate memory");
3270         res = OC_STACK_NO_MEMORY;
3271         goto error;
3272     }
3273
3274     removeData->revokeTargetDev = PMCloneOCProvisionDev(pTargetDev);
3275     if (!removeData->revokeTargetDev)
3276     {
3277         OIC_LOG(ERROR, TAG, "SRPSyncDevice : PMCloneOCProvisionDev Failed");
3278         res = OC_STACK_NO_MEMORY;
3279         goto error;
3280     }
3281
3282     removeData->removeRes =
3283         (OCProvisionResult_t*)OICCalloc(numOfLinkedDev, sizeof(OCProvisionResult_t));
3284     if (!removeData->removeRes)
3285     {
3286         OIC_LOG(ERROR, TAG, "SRPSyncDevice : Failed to allocate memory");
3287         res = OC_STACK_NO_MEMORY;
3288         goto error;
3289     }
3290
3291     removeData->ctx = ctx;
3292     removeData->linkedDevList = pLinkedDevList;
3293     removeData->resultCallback = resultCallback;
3294     removeData->numOfResults = 0;
3295     removeData->sizeOfResArray = numOfLinkedDev;
3296     removeData->hasError = false;
3297
3298     // 5. Send DELETE credential request to linked devices.
3299     OCProvisionDev_t *curDev = NULL, *tmpDev = NULL;
3300     OCStackResult totalRes = OC_STACK_ERROR;  /* variable for checking request is sent or not */
3301     LL_FOREACH_SAFE(pLinkedDevList, curDev, tmpDev)
3302     {
3303         res = SendDeleteACLRequest((void*)removeData, &SRPSyncDeviceACLCB,
3304                                            removeData->revokeTargetDev, curDev);
3305         if (OC_STACK_OK != res)
3306         {
3307             OIC_LOG_V(ERROR, TAG, "SRPSyncDevice : Fail to send the DELETE ACL request to\
3308                      %s:%u", curDev->endpoint.addr, curDev->endpoint.port);
3309             goto error;
3310         }
3311         res = SendDeleteCredentialRequest((void*)removeData, &SRPSyncDeviceCredCB,
3312                                            removeData->revokeTargetDev, curDev);
3313         if (OC_STACK_OK != res)
3314         {
3315             OIC_LOG_V(ERROR, TAG, "SRPSyncDevice : Fail to send the DELETE credential request to\
3316                      %s:%u", curDev->endpoint.addr, curDev->endpoint.port);
3317             totalRes = OC_STACK_ERROR;
3318         }
3319         else
3320         {
3321             totalRes = OC_STACK_OK; // This means at least one request is successfully sent.
3322         }
3323     }
3324
3325     PDMDestoryOicUuidLinkList(pLinkedUuidList); //TODO: Modify API name to have unified convention.
3326     PMDeleteDeviceList(pOwnedDevList);
3327     OIC_LOG(INFO, TAG, "OUT SRPSyncDevice");
3328
3329     return totalRes; // Caller of this API should wait callback if totalRes == OC_STACK_OK.
3330
3331 error:
3332     PDMDestoryOicUuidLinkList(pLinkedUuidList);
3333     PMDeleteDeviceList(pOwnedDevList);
3334     PMDeleteDeviceList(pLinkedDevList);
3335     if (removeData)
3336     {
3337         OICFree(removeData->revokeTargetDev);
3338         OICFree(removeData->removeRes);
3339         OICFree(removeData);
3340     }
3341     OIC_LOG(INFO, TAG, "OUT ERROR case SRPSyncDevice");
3342     return res;
3343 }
3344
3345 /*
3346  * Function for remote reset
3347  * This function will send pstat PUT message to the target device to initiate remote reset.
3348  *
3349  * @param[in] pTargetDev Device information to be revoked.
3350  * @param[in] resultCallback callback provided by API user, callback will be called when
3351  *            credential revocation is finished.
3352  *            when there is an error, this user callback is called immediately.
3353  * @return OC_STACK_OK in case of success and other value otherwise.
3354  *         If OC_STACK_OK is returned, the caller of this API should wait for callback.
3355  *         OC_STACK_CONTINUE means operation is success but no request is need to be initiated.
3356  */
3357 OCStackResult SRPResetDevice(const OCProvisionDev_t* pTargetDev,
3358         OCProvisionResultCB resultCallback)
3359 {
3360     OIC_LOG(INFO, TAG, "IN SRPResetDevice");
3361     if (!pTargetDev)
3362     {
3363         OIC_LOG(INFO, TAG, "SRPResetDevice : NULL parameters");
3364         return OC_STACK_INVALID_PARAM;
3365     }
3366     if (!resultCallback)
3367     {
3368         OIC_LOG(INFO, TAG, "SRPResetDevice : NULL Callback");
3369         return OC_STACK_INVALID_CALLBACK;
3370     }
3371
3372     OCStackResult res = OC_STACK_ERROR;
3373     OicSecPstat_t * pstat = (OicSecPstat_t *) OICCalloc(1, sizeof(OicSecPstat_t));
3374     if (!pstat)
3375     {
3376         OIC_LOG(ERROR, TAG, "Failed to allocate memory");
3377         return OC_STACK_NO_MEMORY;
3378     }