Memory leak fixes
[platform/upstream/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 "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 "doxmresource.h"
38 #include "pconfresource.h"
39 #include "credentialgenerator.h"
40 #include "cainterface.h"
41 #if defined (__TIZENRT__)
42 #include <apps/netutils/cJSON.h>
43 #else
44 #include "cJSON.h"
45 #endif
46 #include "pmtypes.h"
47 #include "pmutility.h"
48 #include "srmutility.h"
49 #include "provisioningdatabasemanager.h"
50 #include "base64.h"
51 #include "utlist.h"
52 #include "ocpayload.h"
53
54 #ifdef __WITH_DTLS__
55 #include "crlresource.h"
56 #endif // WITH_X509__
57
58 #define TAG "OIC_SRPAPI"
59
60 /**
61  * Macro to verify argument is not equal to NULL.
62  * eg: VERIFY_NON_NULL_RET(TAG, ptrData, ERROR,OC_STACK_ERROR);
63  */
64 #define VERIFY_NON_NULL_RET(tag, arg, logLevel, retValue) { if (NULL == (arg)) \
65             { OIC_LOG((logLevel), tag, #arg " is NULL"); return retValue; } }
66
67 /**
68  * Macro to verify success of operation.
69  * eg: VERIFY_SUCCESS_RET(TAG, OC_STACK_OK == foo(), ERROR, OC_STACK_ERROR);
70  */
71 #define VERIFY_SUCCESS_RET(tag, op, logLevel, retValue) { if (!(op)) \
72             {OIC_LOG((logLevel), tag, #op " failed!!"); return retValue;} }
73
74
75 trustCertChainContext_t g_trustCertChainNotifier;
76
77 /**
78  * Structure to carry credential data to callback.
79  */
80 typedef struct CredentialData CredentialData_t;
81 struct CredentialData
82 {
83     void *ctx;                                  /**< Pointer to user context.**/
84     const OCProvisionDev_t *deviceInfo1;        /**< Pointer to OCProvisionDev_t.**/
85     const OCProvisionDev_t *deviceInfo2;        /**< Pointer to OCProvisionDev_t.**/
86     OicSecCred_t *credInfo;                     /**< Pointer to OicSecCred_t.**/
87     OicSecCred_t *credInfoFirst;                /**< Pointer to OicSecCred_t.**/
88     OCProvisionResultCB resultCallback;         /**< Pointer to result callback.**/
89     OCProvisionResult_t *resArr;                /**< Result array.**/
90     int numOfResults;                           /**< Number of results in result array.**/
91 };
92
93 /**
94  * Structure to carry ACL provision API data to callback.
95  */
96 typedef struct ACLData ACLData_t;
97 struct ACLData
98 {
99     void *ctx;                                  /**< Pointer to user context.**/
100     const OCProvisionDev_t *deviceInfo;         /**< Pointer to PMDevInfo_t.**/
101     OCProvisionResultCB resultCallback;         /**< Pointer to result callback.**/
102     OCProvisionResult_t *resArr;                /**< Result array.**/
103     int numOfResults;                           /**< Number of results in result array.**/
104 };
105
106 // Structure to carry get security resource APIs data to callback.
107 typedef struct GetSecData GetSecData_t;
108 struct GetSecData {
109     void *ctx;
110     const OCProvisionDev_t *deviceInfo;         /**< Pointer to PMDevInfo_t.**/
111     OCProvisionResultCB resultCallback;         /**< Pointer to result callback.**/
112     OCProvisionResult_t *resArr;                /**< Result array.**/
113     int numOfResults;                        /**< Number of results in result array.**/
114 };
115
116 /**
117  * Structure to carry PCONF provision API data to callback.
118  */
119 typedef struct PconfData PconfData_t;
120 struct PconfData
121 {
122     void *ctx;                                  /**< Pointer to user context.**/
123     const OCProvisionDev_t *deviceInfo;         /**< Pointer to PMDevInfo_t.**/
124     OCProvisionResultCB resultCallback;         /**< Pointer to result callback.**/
125     OCProvisionResult_t *resArr;                /**< Result array.**/
126     int numOfResults;                           /**< Number of results in result array.**/
127 };
128
129 // Enum type index for unlink callback.
130 typedef enum {
131     IDX_FIRST_DEVICE_RES = 0, // index for resulf of the first device
132     IDX_SECOND_DEVICE_RES,    // index for result of the second device
133     IDX_DB_UPDATE_RES         // index for result of updating provisioning database.
134 } IdxUnlinkRes_t;
135
136 // Structure to carry unlink APIs data to callback.
137 typedef struct UnlinkData UnlinkData_t;
138 struct UnlinkData {
139     void *ctx;
140     OCProvisionDev_t* unlinkDev;             /**< Pointer to OCProvisionDev_t to be unlinked.**/
141     OCProvisionResult_t* unlinkRes;          /**< Result array.**/
142     OCProvisionResultCB resultCallback;      /**< Pointer to result callback.**/
143     int numOfResults;                        /**< Number of results in result array.**/
144 };
145
146 //Example of DELETE cred request -> coaps://0.0.0.0:5684/oic/sec/cred?sub=(BASE64 ENCODED UUID)
147 const char * SRP_FORM_DELETE_CREDENTIAL = "coaps://[%s]:%d%s?%s=%s";
148 const char * SRP_FORM_DELETE_CREDENTIAL_TCP = "coaps+tcp://[%s]:%d%s?%s=%s";
149
150 // Structure to carry remove APIs data to callback.
151 typedef struct RemoveData RemoveData_t;
152 struct RemoveData {
153     void *ctx;
154     OCProvisionDev_t* revokeTargetDev;      /**< Device which is going to be revoked..**/
155     OCProvisionDev_t* linkedDevList;        /**< A list of devices which have invalid credential.**/
156     OCProvisionResult_t* removeRes;         /**< Result array.**/
157     OCProvisionResultCB resultCallback;     /**< Pointer to result callback.**/
158     OCClientContextDeleter deleteCallback;  /**< Pointer to delete callback.**/
159     size_t numOfResults;                    /**< Number of results in result array.**/
160     size_t sizeOfResArray;
161     bool hasError;
162 };
163
164 /**
165  * Function prototype
166  */
167 static OCStackResult provisionCredentials(const OicSecCred_t *cred,
168         const OCProvisionDev_t *deviceInfo, CredentialData_t *credData,
169         OCClientResponseHandler responseHandler);
170
171
172 /**
173  * Internal function to update result in result array.
174  */
175 static void registerResultForCredProvisioning(CredentialData_t *credData,
176                                               OCStackResult stackresult, int cause)
177 {
178
179    OIC_LOG_V(INFO,TAG,"value of credData->numOfResults is %d",credData->numOfResults);
180    if(1 == cause)
181    {
182        memcpy(credData->resArr[(credData->numOfResults)].deviceId.id,
183               credData->deviceInfo1->doxm->deviceID.id,UUID_LENGTH);
184    }
185    else
186    {
187        memcpy(credData->resArr[(credData->numOfResults)].deviceId.id,
188               credData->deviceInfo2->doxm->deviceID.id,UUID_LENGTH);
189    }
190    credData->resArr[(credData->numOfResults)].res = stackresult;
191    ++(credData->numOfResults);
192 }
193
194 /**
195  * Callback handler for handling callback of provisioning device 2.
196  *
197  * @param[in] ctx             ctx value passed to callback from calling function.
198  * @param[in] UNUSED          handle to an invocation
199  * @param[in] clientResponse  Response from queries to remote servers.
200  * @return  OC_STACK_DELETE_TRANSACTION to delete the transaction
201  *          and  OC_STACK_KEEP_TRANSACTION to keep it.
202  */
203 static OCStackApplicationResult provisionCredentialCB2(void *ctx, OCDoHandle UNUSED,
204                                                        OCClientResponse *clientResponse)
205 {
206     VERIFY_NON_NULL_RET(TAG, ctx, ERROR, OC_STACK_DELETE_TRANSACTION);
207     CredentialData_t *credData = (CredentialData_t *) ctx;
208     (void)UNUSED;
209
210     OCProvisionResultCB resultCallback = credData->resultCallback;
211     OIC_LOG(INFO, TAG, "provisionCredentialCB2 called");
212     if (clientResponse)
213     {
214         if(OC_STACK_RESOURCE_CHANGED == clientResponse->result)
215         {
216             registerResultForCredProvisioning(credData, OC_STACK_RESOURCE_CHANGED, 2);
217             OCStackResult res =  PDMLinkDevices(&credData->deviceInfo1->doxm->deviceID,
218                     &credData->deviceInfo2->doxm->deviceID);
219             if (OC_STACK_OK != res)
220             {
221                 OIC_LOG(ERROR, TAG, "Error occured on PDMLinkDevices");
222                 return OC_STACK_DELETE_TRANSACTION;
223             }
224             OIC_LOG(INFO, TAG, "Link created successfully");
225
226             ((OCProvisionResultCB)(resultCallback))(credData->ctx, credData->numOfResults,
227                                                     credData->resArr,
228                                                     false);
229              OICFree(credData->resArr);
230              OICFree(credData);
231              return OC_STACK_DELETE_TRANSACTION;
232         }
233
234     }
235     OIC_LOG(INFO, TAG, "provisionCredentialCB2 received Null clientResponse");
236     registerResultForCredProvisioning(credData, OC_STACK_ERROR, 2);
237     ((OCProvisionResultCB)(resultCallback))(credData->ctx, credData->numOfResults,
238                                             credData->resArr,
239                                             true);
240     OICFree(credData->resArr);
241     OICFree(credData);
242     return OC_STACK_DELETE_TRANSACTION;
243 }
244
245 /**
246  * Callback handler for handling callback of provisioning device 1.
247  *
248  * @param[in] ctx             ctx value passed to callback from calling function.
249  * @param[in] UNUSED          handle to an invocation
250  * @param[in] clientResponse  Response from queries to remote servers.
251  * @return  OC_STACK_DELETE_TRANSACTION to delete the transaction
252  *          and  OC_STACK_KEEP_TRANSACTION to keep it.
253  */
254 static OCStackApplicationResult provisionCredentialCB1(void *ctx, OCDoHandle UNUSED,
255                                                        OCClientResponse *clientResponse)
256 {
257     VERIFY_NON_NULL_RET(TAG, ctx, ERROR, OC_STACK_DELETE_TRANSACTION);
258     (void)UNUSED;
259     CredentialData_t* credData = (CredentialData_t*) ctx;
260     OICFree(credData->credInfoFirst);
261     const OCProvisionDev_t *deviceInfo = credData->deviceInfo2;
262     OicSecCred_t *credInfo = credData->credInfo;
263     const OCProvisionResultCB resultCallback = credData->resultCallback;
264     if (clientResponse)
265     {
266         if (OC_STACK_RESOURCE_CHANGED == clientResponse->result)
267         {
268             // send credentials to second device
269             registerResultForCredProvisioning(credData, OC_STACK_RESOURCE_CHANGED,1);
270             OCStackResult res = provisionCredentials(credInfo, deviceInfo, credData,
271                     provisionCredentialCB2);
272             DeleteCredList(credInfo);
273             if (OC_STACK_OK != res)
274             {
275                 registerResultForCredProvisioning(credData, res,2);
276                 ((OCProvisionResultCB)(resultCallback))(credData->ctx, credData->numOfResults,
277                                                         credData->resArr,
278                                                         true);
279                 OICFree(credData->resArr);
280                 OICFree(credData);
281                 credData = NULL;
282             }
283         }
284         else
285         {
286             registerResultForCredProvisioning(credData, OC_STACK_ERROR,1);
287             ((OCProvisionResultCB)(resultCallback))(credData->ctx, credData->numOfResults,
288                                                     credData->resArr,
289                                                     true);
290             OICFree(credData->resArr);
291             OICFree(credData);
292             credData = NULL;
293         }
294     }
295     else
296     {
297         OIC_LOG(INFO, TAG, "provisionCredentialCB received Null clientResponse for first device");
298         registerResultForCredProvisioning(credData, OC_STACK_ERROR,1);
299        ((OCProvisionResultCB)(resultCallback))(credData->ctx, credData->numOfResults,
300                                                      credData->resArr,
301                                                      true);
302         DeleteCredList(credInfo);
303         OICFree(credData->resArr);
304         OICFree(credData);
305         credData = NULL;
306     }
307     return OC_STACK_DELETE_TRANSACTION;
308 }
309
310
311
312 /**
313  * Internal function for handling credential generation and sending credential to resource server.
314  *
315  * @param[in] cred Instance of cred resource.
316  * @param[in] deviceInfo information about device to which credential is to be provisioned.
317  * @param[in] responseHandler callbak called by OC stack when request API receives response.
318  * @return  OC_STACK_OK in case of success and other value otherwise.
319  */
320 static OCStackResult provisionCredentials(const OicSecCred_t *cred,
321         const OCProvisionDev_t *deviceInfo, CredentialData_t *credData,
322         OCClientResponseHandler responseHandler)
323 {
324     OCSecurityPayload* secPayload = (OCSecurityPayload*)OICCalloc(1, sizeof(OCSecurityPayload));
325     if (!secPayload)
326     {
327         OIC_LOG(ERROR, TAG, "Failed to memory allocation");
328         return OC_STACK_NO_MEMORY;
329     }
330     secPayload->base.type = PAYLOAD_TYPE_SECURITY;
331     int secureFlag = 0;
332     OCStackResult res = CredToCBORPayload(cred, &secPayload->securityData,
333                                           &secPayload->payloadSize, secureFlag);
334     if((OC_STACK_OK != res) && (NULL == secPayload->securityData))
335     {
336         OCPayloadDestroy((OCPayload *)secPayload);
337         OIC_LOG(ERROR, TAG, "Failed to CredToCBORPayload");
338         return OC_STACK_NO_MEMORY;
339     }
340
341     OIC_LOG(DEBUG, TAG, "Created payload for Cred:");
342     OIC_LOG_BUFFER(DEBUG, TAG, secPayload->securityData, secPayload->payloadSize);
343     char query[MAX_URI_LENGTH + MAX_QUERY_LENGTH] = {0};
344     if(!PMGenerateQuery(true,
345                         deviceInfo->endpoint.addr,
346                         deviceInfo->securePort,
347                         deviceInfo->connType,
348                         query, sizeof(query), OIC_RSRC_CRED_URI))
349     {
350         OIC_LOG(ERROR, TAG, "DeviceDiscoveryHandler : Failed to generate query");
351         OCPayloadDestroy((OCPayload *)secPayload);
352         return OC_STACK_ERROR;
353     }
354     OIC_LOG_V(DEBUG, TAG, "Query=%s", query);
355
356     OCCallbackData cbData = {.context=NULL, .cb=NULL, .cd=NULL};
357     cbData.cb = responseHandler;
358     cbData.context = (void *) credData;
359     cbData.cd = NULL;
360
361     OCDoHandle handle = NULL;
362     OCMethod method = OC_REST_POST;
363     OCStackResult ret = OCDoResource(&handle, method, query, 0, (OCPayload*)secPayload,
364             deviceInfo->connType, OC_HIGH_QOS, &cbData, NULL, 0);
365     OIC_LOG_V(INFO, TAG, "OCDoResource::Credential provisioning returned : %d",ret);
366     if (ret != OC_STACK_OK)
367     {
368         OIC_LOG(ERROR, TAG, "OCStack resource error");
369         return ret;
370     }
371     return OC_STACK_OK;
372 }
373
374 #if defined(__WITH_DTLS__) || defined(__WITH_TLS__)
375 /**
376  * Structure to carry certificate data to callback.
377  */
378 typedef struct CertificateData CertData_t;
379 struct CertificateData
380 {
381     void *ctx;                                  /**< Pointer to user context.**/
382     const OCProvisionDev_t *deviceInfo;        /**< Pointer to OCProvisionDev_t.**/
383     OicSecCred_t *credInfo;                     /**< Pointer to OicSecCred_t.**/
384     OCProvisionResultCB resultCallback;         /**< Pointer to result callback.**/
385     OCProvisionResult_t *resArr;                /**< Result array.**/
386     int numOfResults;                           /**< Number of results in result array.**/
387 };
388
389 /**
390  * Internal function to update result in result array.
391  */
392 static void registerResultForCertProvisioning(CertData_t *certData,
393                                               OCStackResult stackresult)
394 {
395
396    OIC_LOG_V(INFO,TAG,"value of credData->numOfResults is %d",certData->numOfResults);
397    memcpy(certData->resArr[(certData->numOfResults)].deviceId.id,
398           certData->deviceInfo->doxm->deviceID.id,UUID_LENGTH);
399    certData->resArr[(certData->numOfResults)].res = stackresult;
400    ++(certData->numOfResults);
401 }
402
403 OCStackResult SRPRegisterTrustCertChainNotifier(void *ctx, TrustCertChainChangeCB callback)
404 {
405     if (g_trustCertChainNotifier.callback)
406     {
407         OIC_LOG(ERROR, TAG, "Can't register Notifier, Unregister previous one");
408         return OC_STACK_ERROR;
409     }
410
411     g_trustCertChainNotifier.callback = callback;
412     g_trustCertChainNotifier.context = ctx;
413     return OC_STACK_OK;
414 }
415
416 void SRPRemoveTrustCertChainNotifier()
417 {
418     g_trustCertChainNotifier.callback = NULL;
419     g_trustCertChainNotifier.context = NULL;
420     return;
421 }
422
423 /**
424  * Callback handler for handling callback of certificate provisioning device.
425  *
426  * @param[in] ctx             ctx value passed to callback from calling function.
427  * @param[in] UNUSED          handle to an invocation
428  * @param[in] clientResponse  Response from queries to remote servers.
429  * @return  OC_STACK_DELETE_TRANSACTION to delete the transaction
430  *          and  OC_STACK_KEEP_TRANSACTION to keep it.
431  */
432 static OCStackApplicationResult provisionCertCB(void *ctx, OCDoHandle UNUSED,
433                                                        OCClientResponse *clientResponse)
434 {
435     VERIFY_NON_NULL_RET(TAG, ctx, ERROR, OC_STACK_DELETE_TRANSACTION);
436     CertData_t *certData = (CertData_t *) ctx;
437     (void)UNUSED;
438
439     OCProvisionResultCB resultCallback = certData->resultCallback;
440     OIC_LOG(INFO, TAG, "provisionCertCB called");
441     if (clientResponse)
442     {
443         if(OC_STACK_RESOURCE_CHANGED == clientResponse->result)
444         {
445             registerResultForCertProvisioning(certData, OC_STACK_RESOURCE_CHANGED);
446             ((OCProvisionResultCB)(resultCallback))(certData->ctx, certData->numOfResults,
447                                                     certData->resArr,
448                                                     false);
449              OICFree(certData->resArr);
450              OICFree(certData);
451              return OC_STACK_DELETE_TRANSACTION;
452         }
453
454     }
455     OIC_LOG(INFO, TAG, "provisionCertCredCB received Null clientResponse");
456     registerResultForCertProvisioning(certData, OC_STACK_ERROR);
457     ((OCProvisionResultCB)(resultCallback))(certData->ctx, certData->numOfResults,
458                                             certData->resArr,
459                                             true);
460     OICFree(certData->resArr);
461     OICFree(certData);
462     return OC_STACK_DELETE_TRANSACTION;
463 }
464
465 OCStackResult SRPProvisionTrustCertChain(void *ctx, OicSecCredType_t type, uint16_t credId,
466         const OCProvisionDev_t *selectedDeviceInfo, OCProvisionResultCB resultCallback)
467 {
468     OIC_LOG(INFO, TAG, "In SRPProvisionTrustCertChain");
469     VERIFY_NON_NULL_RET(TAG, selectedDeviceInfo, ERROR,  OC_STACK_INVALID_PARAM);
470     VERIFY_NON_NULL_RET(TAG, resultCallback, ERROR,  OC_STACK_INVALID_CALLBACK);
471     if (SIGNED_ASYMMETRIC_KEY != type)
472     {
473         OIC_LOG(INFO, TAG, "Invalid key type");
474         return OC_STACK_INVALID_PARAM;
475     }
476
477     OicSecCred_t *trustCertChainCred = GetCredEntryByCredId(credId);
478     if(NULL == trustCertChainCred)
479     {
480         OIC_LOG(ERROR, TAG, "Can not find matched Trust Cert. Chain.");
481         return OC_STACK_NO_RESOURCE;
482     }
483
484     OCSecurityPayload* secPayload = (OCSecurityPayload*)OICCalloc(1, sizeof(OCSecurityPayload));
485     if(!secPayload)
486     {
487         DeleteCredList(trustCertChainCred);
488         OIC_LOG(ERROR, TAG, "Failed to memory allocation");
489         return OC_STACK_NO_MEMORY;
490     }
491     secPayload->base.type = PAYLOAD_TYPE_SECURITY;
492     int secureFlag = 0;
493     if(OC_STACK_OK != CredToCBORPayload(trustCertChainCred, &secPayload->securityData, &secPayload->payloadSize, secureFlag))
494     {
495         DeleteCredList(trustCertChainCred);
496         OCPayloadDestroy((OCPayload *)secPayload);
497         OIC_LOG(ERROR, TAG, "Failed to CredToCBORPayload");
498         return OC_STACK_NO_MEMORY;
499     }
500     DeleteCredList(trustCertChainCred);
501     OIC_LOG(DEBUG, TAG, "Created payload for Cred:");
502     OIC_LOG_BUFFER(DEBUG, TAG, secPayload->securityData, secPayload->payloadSize);
503
504     char query[MAX_URI_LENGTH + MAX_QUERY_LENGTH] = {0};
505     if(!PMGenerateQuery(true,
506                         selectedDeviceInfo->endpoint.addr,
507                         selectedDeviceInfo->securePort,
508                         selectedDeviceInfo->connType,
509                         query, sizeof(query), OIC_RSRC_CRED_URI))
510     {
511         OIC_LOG(ERROR, TAG, "SRPProvisionTrustCertChain : Failed to generate query");
512         OCPayloadDestroy((OCPayload *)secPayload);
513         return OC_STACK_ERROR;
514     }
515     OIC_LOG_V(DEBUG, TAG, "Query=%s", query);
516
517     OCCallbackData cbData =  {.context=NULL, .cb=NULL, .cd=NULL};
518     cbData.cb = &provisionCertCB;
519     CertData_t *certData = (CertData_t *) OICCalloc(1, sizeof(CertData_t));
520     if (NULL == certData)
521     {
522         OIC_LOG(ERROR, TAG, "Memory allocation problem");
523         OCPayloadDestroy((OCPayload *)secPayload);
524         return OC_STACK_NO_MEMORY;
525     }
526     certData->deviceInfo = selectedDeviceInfo;
527     certData->resultCallback = resultCallback;
528     certData->credInfo = NULL; //credInfo not used in the response handler
529     certData->numOfResults=0;
530     certData->ctx = ctx;
531
532     int noOfRiCalls = 1;
533     certData->resArr = (OCProvisionResult_t*)OICCalloc(noOfRiCalls, sizeof(OCProvisionResult_t));
534     if (certData->resArr == NULL)
535     {
536         OICFree(certData);
537         OCPayloadDestroy((OCPayload *)secPayload);
538         OIC_LOG(ERROR, TAG, "Unable to allocate memory");
539         return OC_STACK_NO_MEMORY;
540     }
541     cbData.context = (void *)certData;
542     cbData.cd = NULL;
543     OCMethod method = OC_REST_POST;
544     OCDoHandle handle = NULL;
545     OIC_LOG(DEBUG, TAG, "Sending Cred info to resource server");
546     OCStackResult ret = OCDoResource(&handle, method, query,
547             &selectedDeviceInfo->endpoint, (OCPayload*)secPayload,
548             selectedDeviceInfo->connType, OC_HIGH_QOS, &cbData, NULL, 0);
549     if (ret != OC_STACK_OK)
550     {
551         OICFree(certData->resArr);
552         OICFree(certData);
553     }
554
555     VERIFY_SUCCESS_RET(TAG, (OC_STACK_OK == ret), ERROR, OC_STACK_ERROR);
556     return OC_STACK_OK;
557 }
558
559 OCStackResult SRPSaveTrustCertChain(uint8_t *trustCertChain, size_t chainSize,
560                                             OicEncodingType_t encodingType, uint16_t *credId)
561 {
562     OIC_LOG_V(DEBUG, TAG, "In %s", __func__);
563
564     VERIFY_NON_NULL_RET(TAG, trustCertChain, ERROR,  OC_STACK_INVALID_PARAM);
565     VERIFY_NON_NULL_RET(TAG, credId, ERROR,  OC_STACK_INVALID_PARAM);
566
567     // It is temporary condition.
568     // 6144(6K) = 6 * 1024, generally, one Cert is less than 2k.
569     // because we use 3 Cert, 6K is enough size for saving Certs.
570     if (6144 <= chainSize)
571     {
572         OIC_LOG_V(ERROR, TAG, "chainSize(%zd) is invalid", chainSize);
573         return OC_STACK_INVALID_PARAM;
574     }
575
576     OCStackResult res = OC_STACK_ERROR;
577
578     OicSecCred_t *cred = (OicSecCred_t *)OICCalloc(1, sizeof(*cred));
579     VERIFY_NON_NULL_RET(TAG, cred, ERROR, OC_STACK_NO_MEMORY);
580
581     res = GetDoxmDeviceID(&cred->subject);
582     if (OC_STACK_OK != res)
583     {
584         OIC_LOG(ERROR, TAG, "Can't get the device id(GetDoxmDeviceID)");
585         goto exit;
586     }
587
588     cred->credUsage= (char *)OICCalloc(1, strlen(TRUST_CA)+1 );
589     if (cred->credUsage == NULL)
590     {
591         OIC_LOG_V(ERROR, TAG, "%s can't alloc credUsage", __func__);
592         res = OC_STACK_NO_MEMORY;
593         goto exit;
594     }
595     OICStrcpy(cred->credUsage, strlen(TRUST_CA) + 1, TRUST_CA);
596
597     cred->credType = SIGNED_ASYMMETRIC_KEY;
598
599     if (encodingType == OIC_ENCODING_PEM)
600     {
601         cred->optionalData.data = (uint8_t *)OICCalloc(1, chainSize + 1);
602         if (cred->optionalData.data == NULL)
603         {
604             OIC_LOG_V(ERROR, TAG, "%s can't alloc cred->optionalData.data", __func__);
605             res = OC_STACK_NO_MEMORY;
606             goto exit;
607         }
608         cred->optionalData.len = chainSize + 1;
609     }
610     else
611     {
612         cred->optionalData.data = (uint8_t *)OICCalloc(chainSize, sizeof(uint8_t));
613         if (NULL == cred->optionalData.data)
614         {
615             OIC_LOG_V(ERROR, TAG, "%s can't alloc cred->optionalData.data", __func__);
616             res = OC_STACK_NO_MEMORY;
617             goto exit;
618         }
619         cred->optionalData.len = chainSize;
620     }
621     memcpy(cred->optionalData.data, trustCertChain, chainSize);
622     cred->optionalData.encoding = encodingType;
623     cred->optionalData.revstat = false;
624
625     res = AddCredential(cred);
626     if(res != OC_STACK_OK)
627     {
628         OIC_LOG_V(ERROR, TAG, "%s can't add cred", __func__);
629         goto exit;
630     }
631     *credId = cred->credId;
632
633     if (g_trustCertChainNotifier.callback)
634     {
635         uint8_t *certChain = (uint8_t*)OICCalloc(chainSize, sizeof(uint8_t));
636         VERIFY_NON_NULL_RET(TAG, certChain, ERROR, OC_STACK_NO_MEMORY);
637         memcpy(certChain, trustCertChain, chainSize);
638         g_trustCertChainNotifier.callback(g_trustCertChainNotifier.context, *credId,
639                 certChain, chainSize);
640         OICFree(certChain);
641     }
642 exit:
643     if (OC_STACK_OK != res)
644     {
645         DeleteCredList(cred);
646     }
647
648     OIC_LOG_V(DEBUG, TAG, "Out %s", __func__);
649
650     return res;
651 }
652
653
654 OCStackResult SRPSaveOwnCertChain(OicSecKey_t * cert, OicSecKey_t * key, uint16_t *credId)
655 {
656     OIC_LOG_V(DEBUG, TAG, "In %s", __func__);
657     VERIFY_NON_NULL_RET(TAG, cert, ERROR,  OC_STACK_INVALID_PARAM);
658     VERIFY_NON_NULL_RET(TAG, cert->data, ERROR,  OC_STACK_INVALID_PARAM);
659     VERIFY_NON_NULL_RET(TAG, key, ERROR,  OC_STACK_INVALID_PARAM);
660     VERIFY_NON_NULL_RET(TAG, key->data, ERROR,  OC_STACK_INVALID_PARAM);
661     VERIFY_NON_NULL_RET(TAG, credId, ERROR,  OC_STACK_INVALID_PARAM);
662
663     OCStackResult res = OC_STACK_ERROR;
664
665     OicSecCred_t *cred = (OicSecCred_t *)OICCalloc(1, sizeof(OicSecCred_t));
666     VERIFY_NON_NULL_RET(TAG, cred, ERROR, OC_STACK_NO_MEMORY);
667
668     res = GetDoxmDeviceID(&cred->subject);
669     if (OC_STACK_OK != res)
670     {
671         OIC_LOG(ERROR, TAG, "Can't get the device id(GetDoxmDeviceID)");
672         goto exit;
673     }
674
675     cred->credUsage= (char *)OICCalloc(strlen(PRIMARY_CERT) + 1, sizeof(char));
676     if (cred->credUsage == NULL)
677     {
678         OIC_LOG_V(ERROR, TAG, "%s can't alloc credUsage", __func__);
679         res = OC_STACK_NO_MEMORY;
680         goto exit;
681     }
682     OICStrcpy(cred->credUsage, strlen(PRIMARY_CERT) + 1, PRIMARY_CERT) ;
683
684     cred->credType = SIGNED_ASYMMETRIC_KEY;
685
686     OicSecKey_t *publicData = &cred->publicData;
687     publicData->data = (uint8_t *)OICCalloc(cert->len, sizeof(uint8_t));
688     if (NULL == publicData->data)
689     {
690         OIC_LOG_V(ERROR, TAG, "%s can't alloc publicData", __func__);
691         res = OC_STACK_NO_MEMORY;
692         goto exit;
693     }
694     memcpy(publicData->data, cert->data, cert->len);
695     publicData->len = cert->len;
696     publicData->encoding = cert->encoding;
697
698     OicSecKey_t *privateData = &cred->privateData;
699     privateData->data = (uint8_t *)OICCalloc(key->len, sizeof(uint8_t));
700     if (NULL == privateData->data)
701     {
702         OIC_LOG_V(ERROR, TAG, "%s can't alloc privateData->data", __func__);
703         res = OC_STACK_NO_MEMORY;
704         goto exit;
705     }
706     memcpy(privateData->data, key->data, key->len);
707     privateData->len = key->len;
708     privateData->encoding = key->encoding;
709
710     res = AddCredential(cred);
711     if(res != OC_STACK_OK)
712     {
713         OIC_LOG_V(ERROR, TAG, "%s can't add cred", __func__);
714         goto exit;
715     }
716     *credId = cred->credId;
717 exit:
718     if (OC_STACK_OK != res)
719     {
720         DeleteCredList(cred);
721     }
722     OIC_LOG_V(DEBUG, TAG, "Out %s", __func__);
723
724     return res;
725 }
726 #endif // __WITH_DTLS__ || __WITH_TLS__
727
728 OCStackResult SRPProvisionCredentials(void *ctx, OicSecCredType_t type, size_t keySize,
729                                       const OCProvisionDev_t *pDev1,
730                                       const OCProvisionDev_t *pDev2,
731                                       OCProvisionResultCB resultCallback)
732 {
733     VERIFY_NON_NULL_RET(TAG, pDev1, ERROR,  OC_STACK_INVALID_PARAM);
734     if (SYMMETRIC_PAIR_WISE_KEY == type)
735     {
736         VERIFY_NON_NULL_RET(TAG, pDev2, ERROR,  OC_STACK_INVALID_PARAM);
737     }
738     if (!resultCallback)
739     {
740         OIC_LOG(INFO, TAG, "SRPUnlinkDevices : NULL Callback");
741         return OC_STACK_INVALID_CALLBACK;
742     }
743     if (SYMMETRIC_PAIR_WISE_KEY == type &&
744         0 == memcmp(&pDev1->doxm->deviceID, &pDev2->doxm->deviceID, sizeof(OicUuid_t)))
745     {
746         OIC_LOG(INFO, TAG, "SRPUnlinkDevices : Same device ID");
747         return OC_STACK_INVALID_PARAM;
748     }
749
750     if (SYMMETRIC_PAIR_WISE_KEY == type &&
751        !(OWNER_PSK_LENGTH_128 == keySize || OWNER_PSK_LENGTH_256 == keySize))
752     {
753         OIC_LOG(INFO, TAG, "Invalid key size");
754         return OC_STACK_INVALID_PARAM;
755     }
756
757     OIC_LOG(INFO, TAG, "In SRPProvisionCredentials");
758
759     if (SYMMETRIC_PAIR_WISE_KEY == type)
760     {
761         bool linkExisits = true;
762         OCStackResult res = PDMIsLinkExists(&pDev1->doxm->deviceID, &pDev2->doxm->deviceID, &linkExisits);
763
764         if (res != OC_STACK_OK)
765         {
766             OIC_LOG(ERROR, TAG, "Internal error occured");
767             return res;
768         }
769         if (linkExisits)
770         {
771             OIC_LOG(ERROR, TAG, "Link already exists");
772             return OC_STACK_INVALID_PARAM;
773         }
774     }
775
776     OicUuid_t provTooldeviceID =   {{0,}};
777     if (OC_STACK_OK != GetDoxmDeviceID(&provTooldeviceID))
778     {
779         OIC_LOG(ERROR, TAG, "Error while retrieving provisioning tool's device ID");
780         return OC_STACK_ERROR;
781     }
782     OIC_LOG(INFO, TAG, "retrieved deviceid");
783     switch (type)
784     {
785         case SYMMETRIC_PAIR_WISE_KEY:
786         {
787             const OCProvisionDev_t *firstDevice = pDev1;
788             const OCProvisionDev_t *secondDevice = pDev2;
789
790             OicSecCred_t *firstCred = NULL;
791             OicSecCred_t *secondCred = NULL;
792             OCStackResult res = PMGeneratePairWiseCredentials(type, keySize, &provTooldeviceID,
793                     &firstDevice->doxm->deviceID, &secondDevice->doxm->deviceID,
794                     &firstCred, &secondCred);
795             VERIFY_SUCCESS_RET(TAG, (res==OC_STACK_OK), ERROR, OC_STACK_ERROR);
796             OIC_LOG(INFO, TAG, "Credentials generated successfully");
797             CredentialData_t *credData =
798                 (CredentialData_t *) OICCalloc(1, sizeof(CredentialData_t));
799             if (NULL == credData)
800             {
801                 OICFree(firstCred);
802                 OICFree(secondCred);
803                 OIC_LOG(ERROR, TAG, "Memory allocation problem");
804                 return OC_STACK_NO_MEMORY;
805             }
806             credData->deviceInfo1 = firstDevice;
807             credData->deviceInfo2 = secondDevice;
808             credData->credInfo = secondCred;
809             credData->ctx = ctx;
810             credData->credInfoFirst = firstCred;
811             credData->numOfResults = 0;
812             credData->resultCallback = resultCallback;
813             // first call to provision creds to device1.
814             // second call to provision creds to device2.
815             int noOfRiCalls = 2;
816             credData->resArr =
817                 (OCProvisionResult_t*)OICCalloc(noOfRiCalls, sizeof(OCProvisionResult_t));
818             if (NULL == credData->resArr)
819             {
820                 OICFree(firstCred);
821                 OICFree(secondCred);
822                 OICFree(credData);
823                 OIC_LOG(ERROR, TAG, "Memory allocation problem");
824                 return OC_STACK_NO_MEMORY;
825             }
826             res = provisionCredentials(firstCred, firstDevice, credData, &provisionCredentialCB1);
827             if (OC_STACK_OK != res)
828             {
829                 DeleteCredList(firstCred);
830                 DeleteCredList(secondCred);
831                 OICFree(credData->resArr);
832                 OICFree(credData);
833             }
834             OIC_LOG_V(INFO, TAG, "provisionCredentials returned: %d",res);
835             VERIFY_SUCCESS_RET(TAG, (res==OC_STACK_OK), ERROR, OC_STACK_ERROR);
836             return res;
837         }
838         default:
839         {
840             OIC_LOG(ERROR, TAG, "Invalid option.");
841             return OC_STACK_INVALID_PARAM;
842         }
843     }
844     return OC_STACK_ERROR;
845 }
846
847 /**
848  * Internal Function to store results in result array during ACL provisioning.
849  */
850 static void registerResultForACLProvisioning(ACLData_t *aclData,
851                                              OCStackResult stackresult)
852 {
853    OIC_LOG_V(INFO, TAG, "Inside registerResultForACLProvisioning aclData->numOfResults is %d\n",
854                        aclData->numOfResults);
855    memcpy(aclData->resArr[(aclData->numOfResults)].deviceId.id,
856           aclData->deviceInfo->doxm->deviceID.id, UUID_LENGTH);
857    aclData->resArr[(aclData->numOfResults)].res = stackresult;
858    ++(aclData->numOfResults);
859 }
860
861 /**
862  * Callback handler of SRPProvisionACL.
863  *
864  * @param[in] ctx             ctx value passed to callback from calling function.
865  * @param[in] UNUSED          handle to an invocation
866  * @param[in] clientResponse  Response from queries to remote servers.
867  * @return  OC_STACK_DELETE_TRANSACTION to delete the transaction
868  *          and  OC_STACK_KEEP_TRANSACTION to keep it.
869  */
870 static OCStackApplicationResult SRPProvisionACLCB(void *ctx, OCDoHandle UNUSED,
871                                                   OCClientResponse *clientResponse)
872 {
873     OIC_LOG_V(INFO, TAG, "Inside SRPProvisionACLCB.");
874     (void)UNUSED;
875     VERIFY_NON_NULL_RET(TAG, ctx, ERROR, OC_STACK_DELETE_TRANSACTION);
876     ACLData_t *aclData = (ACLData_t*)ctx;
877     OCProvisionResultCB resultCallback = aclData->resultCallback;
878
879     if (clientResponse)
880     {
881         if(OC_STACK_RESOURCE_CHANGED == clientResponse->result)
882         {
883             registerResultForACLProvisioning(aclData, OC_STACK_RESOURCE_CHANGED);
884             ((OCProvisionResultCB)(resultCallback))(aclData->ctx, aclData->numOfResults,
885                                                     aclData->resArr,
886                                                     false);
887              OICFree(aclData->resArr);
888              OICFree(aclData);
889              return OC_STACK_DELETE_TRANSACTION;
890         }
891     }
892     registerResultForACLProvisioning(aclData, OC_STACK_ERROR);
893     ((OCProvisionResultCB)(resultCallback))(aclData->ctx, aclData->numOfResults,
894                                             aclData->resArr,
895                                             true);
896     OIC_LOG_V(ERROR, TAG, "SRPProvisionACLCB received Null clientResponse");
897     OICFree(aclData->resArr);
898     OICFree(aclData);
899     return OC_STACK_DELETE_TRANSACTION;
900 }
901
902 OCStackResult SRPProvisionACL(void *ctx, const OCProvisionDev_t *selectedDeviceInfo,
903         OicSecAcl_t *acl, OCProvisionResultCB resultCallback)
904 {
905     VERIFY_NON_NULL_RET(TAG, selectedDeviceInfo, ERROR,  OC_STACK_INVALID_PARAM);
906     VERIFY_NON_NULL_RET(TAG, acl, ERROR,  OC_STACK_INVALID_PARAM);
907     VERIFY_NON_NULL_RET(TAG, resultCallback, ERROR,  OC_STACK_INVALID_CALLBACK);
908
909     // if rowneruuid is empty, set it to device ID
910     OicUuid_t emptyOwner = {.id = {0} };
911     if (memcmp(&(acl->rownerID.id), &emptyOwner, UUID_IDENTITY_SIZE) == 0)
912     {
913         OIC_LOG(DEBUG, TAG, "Set Rowner to PT's deviceId, because Rowner of ACL is empty");
914         OicUuid_t oicUuid;
915
916         if (OC_STACK_OK == GetDoxmDeviceID(&oicUuid))
917         {
918             memcpy(&(acl->rownerID.id), &oicUuid, UUID_IDENTITY_SIZE);
919         }
920         else
921         {
922             OIC_LOG(DEBUG, TAG, "Failed to set Rowner to PT's deviceID\
923                 becuase it failed to retrieve Doxm DeviceID");
924             return OC_STACK_ERROR;
925         }
926     }
927
928     OCSecurityPayload* secPayload = (OCSecurityPayload*)OICCalloc(1, sizeof(OCSecurityPayload));
929     if(!secPayload)
930     {
931         OIC_LOG(ERROR, TAG, "Failed to memory allocation");
932         return OC_STACK_NO_MEMORY;
933     }
934     secPayload->base.type = PAYLOAD_TYPE_SECURITY;
935     if(OC_STACK_OK != AclToCBORPayload(acl, &secPayload->securityData, &secPayload->payloadSize))
936     {
937         OCPayloadDestroy((OCPayload *)secPayload);
938         OIC_LOG(ERROR, TAG, "Failed to AclToCBORPayload");
939         return OC_STACK_NO_MEMORY;
940     }
941     OIC_LOG(DEBUG, TAG, "Created payload for ACL:");
942     OIC_LOG_BUFFER(DEBUG, TAG, secPayload->securityData, secPayload->payloadSize);
943
944     char query[MAX_URI_LENGTH + MAX_QUERY_LENGTH] = {0};
945     if(!PMGenerateQuery(true,
946                         selectedDeviceInfo->endpoint.addr,
947                         selectedDeviceInfo->securePort,
948                         selectedDeviceInfo->connType,
949                         query, sizeof(query), OIC_RSRC_ACL_URI))
950     {
951         OIC_LOG(ERROR, TAG, "DeviceDiscoveryHandler : Failed to generate query");
952         return OC_STACK_ERROR;
953     }
954     OIC_LOG_V(DEBUG, TAG, "Query=%s", query);
955
956     OCCallbackData cbData =  {.context=NULL, .cb=NULL, .cd=NULL};
957     cbData.cb = &SRPProvisionACLCB;
958     ACLData_t *aclData = (ACLData_t *) OICCalloc(1, sizeof(ACLData_t));
959     if (aclData == NULL)
960     {
961         OCPayloadDestroy((OCPayload *)secPayload);
962         OIC_LOG(ERROR, TAG, "Unable to allocate memory");
963         return OC_STACK_NO_MEMORY;
964     }
965     aclData->deviceInfo = selectedDeviceInfo;
966     aclData->resultCallback = resultCallback;
967     aclData->numOfResults=0;
968     aclData->ctx = ctx;
969     // call to provision ACL to device1.
970     int noOfRiCalls = 1;
971     aclData->resArr = (OCProvisionResult_t*)OICCalloc(noOfRiCalls, sizeof(OCProvisionResult_t));
972     if (aclData->resArr == NULL)
973     {
974         OICFree(aclData);
975         OCPayloadDestroy((OCPayload *)secPayload);
976         OIC_LOG(ERROR, TAG, "Unable to allocate memory");
977         return OC_STACK_NO_MEMORY;
978     }
979     cbData.context = (void *)aclData;
980     cbData.cd = NULL;
981     OCMethod method = OC_REST_POST;
982     OCDoHandle handle = NULL;
983     OIC_LOG(DEBUG, TAG, "Sending ACL info to resource server");
984     OCStackResult ret = OCDoResource(&handle, method, query,
985             &selectedDeviceInfo->endpoint, (OCPayload*)secPayload,
986             selectedDeviceInfo->connType, OC_HIGH_QOS, &cbData, NULL, 0);
987     if (ret != OC_STACK_OK)
988     {
989         OICFree(aclData->resArr);
990         OICFree(aclData);
991     }
992     VERIFY_SUCCESS_RET(TAG, (OC_STACK_OK == ret), ERROR, OC_STACK_ERROR);
993     return OC_STACK_OK;
994 }
995
996 OCStackResult SRPSaveACL(const OicSecAcl_t *acl)
997 {
998     OIC_LOG(DEBUG, TAG, "IN SRPSaveACL");
999     VERIFY_NON_NULL_RET(TAG, acl, ERROR,  OC_STACK_INVALID_PARAM);
1000
1001     OCStackResult res =  InstallACL(acl);
1002
1003     OIC_LOG(DEBUG, TAG, "OUT SRPSaveACL");
1004     return res;
1005 }
1006
1007 /**
1008  * Internal Function to store results in result array during Direct-Pairing provisioning.
1009  */
1010 static void registerResultForDirectPairingProvisioning(PconfData_t *pconfData,
1011                                              OCStackResult stackresult)
1012 {
1013    OIC_LOG_V(INFO, TAG, "Inside registerResultForDirectPairingProvisioning "
1014            "pconfData->numOfResults is %d\n", pconfData->numOfResults);
1015    memcpy(pconfData->resArr[(pconfData->numOfResults)].deviceId.id,
1016           pconfData->deviceInfo->doxm->deviceID.id, UUID_LENGTH);
1017    pconfData->resArr[(pconfData->numOfResults)].res = stackresult;
1018    ++(pconfData->numOfResults);
1019 }
1020
1021 /**
1022  * Callback handler of SRPProvisionDirectPairing.
1023  *
1024  * @param[in] ctx             ctx value passed to callback from calling function.
1025  * @param[in] UNUSED          handle to an invocation
1026  * @param[in] clientResponse  Response from queries to remote servers.
1027  * @return  OC_STACK_DELETE_TRANSACTION to delete the transaction
1028  *          and  OC_STACK_KEEP_TRANSACTION to keep it.
1029  */
1030 static OCStackApplicationResult SRPProvisionDirectPairingCB(void *ctx, OCDoHandle UNUSED,
1031                                                   OCClientResponse *clientResponse)
1032 {
1033     OIC_LOG_V(INFO, TAG, "Inside SRPProvisionDirectPairingCB.");
1034     (void)UNUSED;
1035     VERIFY_NON_NULL_RET(TAG, ctx, ERROR, OC_STACK_DELETE_TRANSACTION);
1036     PconfData_t *pconfData = (PconfData_t*)ctx;
1037     OCProvisionResultCB resultCallback = pconfData->resultCallback;
1038
1039     if (clientResponse)
1040     {
1041         if(OC_STACK_RESOURCE_CHANGED == clientResponse->result)
1042         {
1043             registerResultForDirectPairingProvisioning(pconfData, OC_STACK_OK);
1044             ((OCProvisionResultCB)(resultCallback))(pconfData->ctx, pconfData->numOfResults,
1045                                                     pconfData->resArr,
1046                                                     false);
1047              OICFree(pconfData->resArr);
1048              OICFree(pconfData);
1049              return OC_STACK_DELETE_TRANSACTION;
1050         }
1051     }
1052     registerResultForDirectPairingProvisioning(pconfData, OC_STACK_ERROR);
1053     ((OCProvisionResultCB)(resultCallback))(pconfData->ctx, pconfData->numOfResults,
1054                                             pconfData->resArr,
1055                                             true);
1056     OIC_LOG_V(ERROR, TAG, "SRPProvisionDirectPairingCB received Null clientResponse");
1057     OICFree(pconfData->resArr);
1058     OICFree(pconfData);
1059     return OC_STACK_DELETE_TRANSACTION;
1060 }
1061
1062 OCStackResult SRPProvisionDirectPairing(void *ctx, const OCProvisionDev_t *selectedDeviceInfo,
1063         OicSecPconf_t *pconf, OCProvisionResultCB resultCallback)
1064 {
1065     VERIFY_NON_NULL_RET(TAG, selectedDeviceInfo, ERROR,  OC_STACK_INVALID_PARAM);
1066     VERIFY_NON_NULL_RET(TAG, pconf, ERROR,  OC_STACK_INVALID_PARAM);
1067     VERIFY_NON_NULL_RET(TAG, resultCallback, ERROR,  OC_STACK_INVALID_CALLBACK);
1068
1069     // check direct-pairing capability
1070     if (true != selectedDeviceInfo->doxm->dpc)
1071     {
1072         OIC_LOG(ERROR, TAG, "Resouce server does not have Direct-Pairing Capability ");
1073         return OC_STACK_UNAUTHORIZED_REQ;
1074     }
1075
1076     OicUuid_t provTooldeviceID =   {.id={0}};
1077     if (OC_STACK_OK != GetDoxmDeviceID(&provTooldeviceID))
1078     {
1079         OIC_LOG(ERROR, TAG, "Error while retrieving provisioning tool's device ID");
1080         return OC_STACK_ERROR;
1081     }
1082     memcpy(&pconf->rownerID, &provTooldeviceID, sizeof(OicUuid_t));
1083
1084     OCSecurityPayload* secPayload = (OCSecurityPayload*)OICCalloc(1, sizeof(OCSecurityPayload));
1085     if(!secPayload)
1086     {
1087         OIC_LOG(ERROR, TAG, "Failed to memory allocation");
1088         return OC_STACK_NO_MEMORY;
1089     }
1090     secPayload->base.type = PAYLOAD_TYPE_SECURITY;
1091
1092     if (OC_STACK_OK != PconfToCBORPayload(pconf, &(secPayload->securityData),
1093                 &(secPayload->payloadSize)))
1094     {
1095         OCPayloadDestroy((OCPayload*)secPayload);
1096         OIC_LOG(ERROR, TAG, "Failed to PconfToCborPayload");
1097         return OC_STACK_NO_MEMORY;
1098     }
1099     OIC_LOG(DEBUG, TAG, "Created payload for pconf set");
1100     OIC_LOG_BUFFER(DEBUG, TAG, secPayload->securityData, secPayload->payloadSize);
1101
1102
1103     char query[MAX_URI_LENGTH + MAX_QUERY_LENGTH] = {0};
1104     if(!PMGenerateQuery(true,
1105                 selectedDeviceInfo->endpoint.addr,
1106                 selectedDeviceInfo->securePort,
1107                 selectedDeviceInfo->connType,
1108                 query, sizeof(query), OIC_RSRC_PCONF_URI))
1109     {
1110         OIC_LOG(ERROR, TAG, "SRPProvisionDirectPairing : Failed to generate query");
1111         return OC_STACK_ERROR;
1112     }
1113     OIC_LOG_V(DEBUG, TAG, "Query=%s", query);
1114
1115     OCCallbackData cbData =  {.context=NULL, .cb=NULL, .cd=NULL};
1116     cbData.cb = &SRPProvisionDirectPairingCB;
1117     PconfData_t *pconfData = (PconfData_t *) OICCalloc(1, sizeof(PconfData_t));
1118     if (NULL == pconfData)
1119     {
1120         OCPayloadDestroy((OCPayload*)secPayload);
1121         OIC_LOG(ERROR, TAG, "Unable to allocate memory");
1122         return OC_STACK_NO_MEMORY;
1123     }
1124     pconfData->deviceInfo = selectedDeviceInfo;
1125     pconfData->resultCallback = resultCallback;
1126     pconfData->numOfResults=0;
1127     pconfData->ctx = ctx;
1128     // call to provision PCONF to device1.
1129     int noOfRiCalls = 1;
1130     pconfData->resArr = (OCProvisionResult_t*)OICCalloc(noOfRiCalls, sizeof(OCProvisionResult_t));
1131     if (NULL == pconfData->resArr)
1132     {
1133         OICFree(pconfData);
1134         OCPayloadDestroy((OCPayload*)secPayload);
1135         OIC_LOG(ERROR, TAG, "Unable to allocate memory");
1136         return OC_STACK_NO_MEMORY;
1137     }
1138     cbData.context = (void *)pconfData;
1139     cbData.cd = NULL;
1140     OCMethod method = OC_REST_POST;
1141     OCDoHandle handle = NULL;
1142     OIC_LOG(DEBUG, TAG, "Sending PCONF info to resource server");
1143     OCStackResult ret = OCDoResource(&handle, method, query,
1144             &selectedDeviceInfo->endpoint, (OCPayload*)secPayload,
1145             selectedDeviceInfo->connType, OC_HIGH_QOS, &cbData, NULL, 0);
1146     if (OC_STACK_OK != ret)
1147     {
1148         OICFree(pconfData->resArr);
1149         OICFree(pconfData);
1150     }
1151     VERIFY_SUCCESS_RET(TAG, (OC_STACK_OK == ret), ERROR, OC_STACK_ERROR);
1152     return OC_STACK_OK;
1153 }
1154
1155 static void DeleteUnlinkData_t(UnlinkData_t *unlinkData)
1156 {
1157     if (unlinkData)
1158     {
1159         OICFree(unlinkData->unlinkDev);
1160         OICFree(unlinkData->unlinkRes);
1161         OICFree(unlinkData);
1162     }
1163 }
1164
1165 static void registerResultForUnlinkDevices(UnlinkData_t *unlinkData, OCStackResult stackresult,
1166                                            IdxUnlinkRes_t idx)
1167 {
1168     if (NULL != unlinkData)
1169     {
1170         OIC_LOG_V(INFO, TAG, "Inside registerResultForUnlinkDevices unlinkData->numOfResults is %d\n",
1171                             unlinkData->numOfResults);
1172         OIC_LOG_V(INFO, TAG, "Stack result :: %d", stackresult);
1173
1174         OicUuid_t *pUuid = &unlinkData->unlinkRes[(unlinkData->numOfResults)].deviceId;
1175
1176         // Set result in the result array according to the position (devNum).
1177         if (idx != IDX_DB_UPDATE_RES)
1178         {
1179             memcpy(pUuid->id, unlinkData->unlinkDev[idx].doxm->deviceID.id, sizeof(pUuid->id));
1180         }
1181         else
1182         {   // When deivce ID is 000... this means it's the result of database update.
1183             memset(pUuid->id, 0, sizeof(pUuid->id));
1184         }
1185         unlinkData->unlinkRes[(unlinkData->numOfResults)].res = stackresult;
1186         ++(unlinkData->numOfResults);
1187         OIC_LOG (INFO, TAG, "Out registerResultForUnlinkDevices");
1188     }
1189 }
1190
1191 static OCStackResult SendDeleteCredentialRequest(void* ctx,
1192                                                  OCClientResponseHandler respHandler,
1193                                                  const OCProvisionDev_t* revokedDev,
1194                                                  const OCProvisionDev_t* destDev)
1195 {
1196     OIC_LOG(DEBUG, TAG, "IN SendDeleteCredentialRequest");
1197
1198     if (NULL == ctx || NULL == respHandler || NULL == revokedDev || NULL == destDev)
1199     {
1200         return OC_STACK_INVALID_PARAM;
1201     }
1202
1203     char *subID = NULL;
1204     OCStackResult ret = ConvertUuidToStr(&revokedDev->doxm->deviceID, &subID);
1205     if(OC_STACK_OK != ret)
1206     {
1207         OIC_LOG(ERROR, TAG, "SendDeleteCredentialRequest : Failed to canonical UUID encoding");
1208         return OC_STACK_ERROR;
1209     }
1210
1211     char addressEncoded[CA_MAX_URI_LENGTH] = {0};
1212     OCStackResult result = OCEncodeAddressForRFC6874(addressEncoded,
1213                                                      sizeof(addressEncoded),
1214                                                      destDev->endpoint.addr);
1215     if (OC_STACK_OK != result)
1216     {
1217         OIC_LOG_V(ERROR, TAG, "SendDeleteCredentialRequest : encoding error %d\n", result);
1218         OICFree(subID);
1219         return OC_STACK_ERROR;
1220     }
1221
1222     char reqBuf[MAX_URI_LENGTH + MAX_QUERY_LENGTH] = {0};
1223     int snRet = 0;
1224                     //coaps://0.0.0.0:5684/oic/sec/cred?subjectid=(Canonical ENCODED UUID)
1225     const char *srpUri = SRP_FORM_DELETE_CREDENTIAL;
1226 #ifdef __WITH_TLS__
1227     if(OC_ADAPTER_TCP == destDev->endpoint.adapter)
1228     {
1229         srpUri = SRP_FORM_DELETE_CREDENTIAL_TCP;
1230     }
1231 #endif
1232
1233     snRet = snprintf(reqBuf, sizeof(reqBuf), srpUri, addressEncoded,
1234                      destDev->securePort, OIC_RSRC_CRED_URI, OIC_JSON_SUBJECTID_NAME, subID);
1235     OICFree(subID);
1236     if (snRet < 0)
1237     {
1238         OIC_LOG_V(ERROR, TAG, "SendDeleteCredentialRequest : Error (snprintf) %d\n", snRet);
1239         return OC_STACK_ERROR;
1240     }
1241     else if ((size_t)snRet >= sizeof(reqBuf))
1242     {
1243         OIC_LOG_V(ERROR, TAG, "SendDeleteCredentialRequest : Truncated (snprintf) %d\n", snRet);
1244         return OC_STACK_ERROR;
1245     }
1246
1247     OCCallbackData cbData;
1248     memset(&cbData, 0, sizeof(cbData));
1249     cbData.context = ctx;
1250     cbData.cb = respHandler;
1251     cbData.cd = NULL;
1252     OIC_LOG_V(INFO, TAG, "URI: %s",reqBuf);
1253
1254     OIC_LOG(DEBUG, TAG, "Sending remove credential request to resource server");
1255
1256     ret = OCDoResource(NULL, OC_REST_DELETE, reqBuf,
1257                                      &destDev->endpoint, NULL,
1258                                      CT_ADAPTER_IP, OC_HIGH_QOS, &cbData, NULL, 0);
1259     if (OC_STACK_OK != ret)
1260     {
1261         OIC_LOG_V(ERROR, TAG, "SendDeleteCredentialRequest : Error in OCDoResource %d", ret);
1262     }
1263     OIC_LOG(DEBUG, TAG, "OUT SendDeleteCredentialRequest");
1264
1265     return ret;
1266 }
1267
1268 static OCStackResult SendDeleteACLRequest(void* ctx,
1269                                                  OCClientResponseHandler respHandler,
1270                                                  const OCProvisionDev_t* revokedDev,
1271                                                  const OCProvisionDev_t* destDev)
1272 {
1273     OIC_LOG(DEBUG, TAG, "IN SendDeleteACLRequest");
1274
1275     if (NULL == ctx || NULL == respHandler || NULL == revokedDev || NULL == destDev)
1276     {
1277         return OC_STACK_INVALID_PARAM;
1278     }
1279
1280     char *subID = NULL;
1281     OCStackResult ret = ConvertUuidToStr(&revokedDev->doxm->deviceID, &subID);
1282     if(OC_STACK_OK != ret)
1283     {
1284         OIC_LOG(ERROR, TAG, "SendDeleteACLRequest : Failed to canonical UUID encoding");
1285         return OC_STACK_ERROR;
1286     }
1287
1288     char addressEncoded[CA_MAX_URI_LENGTH] = {0};
1289     OCStackResult result = OCEncodeAddressForRFC6874(addressEncoded,
1290                                                      sizeof(addressEncoded),
1291                                                      destDev->endpoint.addr);
1292     if (OC_STACK_OK != result)
1293     {
1294         OICFree(subID);
1295         OIC_LOG_V(ERROR, TAG, "SendDeleteCredentialRequest : encoding error %d\n", result);
1296         return OC_STACK_ERROR;
1297     }
1298
1299
1300     char reqBuf[MAX_URI_LENGTH + MAX_QUERY_LENGTH] = {0};
1301     int snRet = 0;
1302                     //coaps://0.0.0.0:5684/oic/sec/acl?subjectuuid=(Canonical ENCODED UUID)
1303     snRet = snprintf(reqBuf, sizeof(reqBuf), SRP_FORM_DELETE_CREDENTIAL, addressEncoded,
1304                      destDev->securePort, OIC_RSRC_ACL_URI, OIC_JSON_SUBJECTID_NAME, subID);
1305     OICFree(subID);
1306     if (snRet < 0)
1307     {
1308         OIC_LOG_V(ERROR, TAG, "SendDeleteACLRequest : Error (snprintf) %d\n", snRet);
1309         return OC_STACK_ERROR;
1310     }
1311     else if ((size_t)snRet >= sizeof(reqBuf))
1312     {
1313         OIC_LOG_V(ERROR, TAG, "SendDeleteACLRequest : Truncated (snprintf) %d\n", snRet);
1314         return OC_STACK_ERROR;
1315     }
1316
1317     OCCallbackData cbData;
1318     memset(&cbData, 0, sizeof(cbData));
1319     cbData.context = ctx;
1320     cbData.cb = respHandler;
1321     cbData.cd = NULL;
1322     OIC_LOG_V(INFO, TAG, "URI: %s",reqBuf);
1323
1324     OIC_LOG(DEBUG, TAG, "Sending remove ACL request to resource server");
1325
1326     ret = OCDoResource(NULL, OC_REST_DELETE, reqBuf,
1327                                      &destDev->endpoint, NULL,
1328                                      CT_ADAPTER_IP, OC_HIGH_QOS, &cbData, NULL, 0);
1329     if (OC_STACK_OK != ret)
1330     {
1331         OIC_LOG_V(ERROR, TAG, "SendDeleteACLRequest : Error in OCDoResource %d", ret);
1332     }
1333     OIC_LOG(DEBUG, TAG, "OUT SendDeleteACLRequest");
1334
1335     return ret;
1336 }
1337
1338 /**
1339  * Callback handler of unlink second device.
1340  *
1341  * @param[in] ctx             ctx value passed to callback from calling function.
1342  * @param[in] handle          handle to an invocation
1343  * @param[in] clientResponse  Response from queries to remote servers.
1344  * @return  OC_STACK_DELETE_TRANSACTION to delete the transaction and
1345  *          OC_STACK_KEEP_TRANSACTION to keep it.
1346  */
1347 static OCStackApplicationResult SRPUnlinkDevice2CB(void *unlinkCtx, OCDoHandle handle,
1348         OCClientResponse *clientResponse)
1349 {
1350     (void) handle;
1351     OIC_LOG(DEBUG, TAG, "IN SRPUnlinkDevice2CB");
1352     VERIFY_NON_NULL_RET(TAG, unlinkCtx, ERROR, OC_STACK_DELETE_TRANSACTION);
1353     UnlinkData_t* unlinkData = (UnlinkData_t*)unlinkCtx;
1354
1355     if (clientResponse)
1356     {
1357         OIC_LOG(DEBUG, TAG, "Valid client response for device 2");
1358         registerResultForUnlinkDevices(unlinkData, clientResponse->result, IDX_SECOND_DEVICE_RES);
1359
1360         if (OC_STACK_RESOURCE_DELETED == clientResponse->result)
1361         {
1362             OIC_LOG(DEBUG, TAG, "Credential of device2 revoked");
1363         }
1364         else
1365         {
1366             OIC_LOG(ERROR, TAG, "Unable to delete credential information from device 2");
1367             unlinkData->resultCallback(unlinkData->ctx,
1368                                        unlinkData->numOfResults, unlinkData->unlinkRes, true);
1369             goto error;
1370         }
1371     }
1372     else
1373     {
1374         registerResultForUnlinkDevices(unlinkData, OC_STACK_INVALID_REQUEST_HANDLE,
1375                                        IDX_SECOND_DEVICE_RES);
1376         unlinkData->resultCallback(unlinkData->ctx,
1377                                    unlinkData->numOfResults, unlinkData->unlinkRes, true);
1378         OIC_LOG(ERROR, TAG, "SRPUnlinkDevice2CB received Null clientResponse");
1379         goto error;
1380     }
1381
1382     //Update provisioning DB when succes case.
1383     if (OC_STACK_OK != PDMUnlinkDevices(&unlinkData->unlinkDev[0].doxm->deviceID,
1384                                        &unlinkData->unlinkDev[1].doxm->deviceID))
1385     {
1386         OIC_LOG(FATAL, TAG, "All requests are successfully done but update provisioning DB FAILED.");
1387         registerResultForUnlinkDevices(unlinkData, OC_STACK_INCONSISTENT_DB, IDX_DB_UPDATE_RES);
1388         unlinkData->resultCallback(unlinkData->ctx,
1389                                    unlinkData->numOfResults, unlinkData->unlinkRes, true);
1390         goto error;
1391     }
1392     unlinkData->resultCallback(unlinkData->ctx, unlinkData->numOfResults, unlinkData->unlinkRes,
1393                                false);
1394
1395 error:
1396     DeleteUnlinkData_t(unlinkData);
1397     OIC_LOG(DEBUG, TAG, "OUT SRPUnlinkDevice2CB");
1398     return OC_STACK_DELETE_TRANSACTION;
1399
1400 }
1401
1402 /**
1403  * Callback handler of unlink first device.
1404  *
1405  * @param[in] ctx             ctx value passed to callback from calling function.
1406  * @param[in] handle          handle to an invocation
1407  * @param[in] clientResponse  Response from queries to remote servers.
1408  * @return  OC_STACK_DELETE_TRANSACTION to delete the transaction and
1409  *          OC_STACK_KEEP_TRANSACTION to keep it.
1410  */
1411 static OCStackApplicationResult SRPUnlinkDevice1CB(void *unlinkCtx, OCDoHandle handle,
1412         OCClientResponse *clientResponse)
1413 {
1414     OIC_LOG_V(INFO, TAG, "Inside SRPUnlinkDevice1CB ");
1415     VERIFY_NON_NULL_RET(TAG, unlinkCtx, ERROR, OC_STACK_DELETE_TRANSACTION);
1416     UnlinkData_t* unlinkData = (UnlinkData_t*)unlinkCtx;
1417     (void) handle;
1418
1419     if (clientResponse)
1420     {
1421         OIC_LOG(DEBUG, TAG, "Valid client response for device 1");
1422         registerResultForUnlinkDevices(unlinkData, clientResponse->result, IDX_FIRST_DEVICE_RES);
1423
1424         if (OC_STACK_RESOURCE_DELETED == clientResponse->result)
1425         {
1426             OIC_LOG(DEBUG, TAG, "Credential of device 1 is revoked");
1427
1428             // Second revocation request to second device.
1429             OCStackResult res = SendDeleteCredentialRequest((void*)unlinkData, &SRPUnlinkDevice2CB,
1430                                                     &unlinkData->unlinkDev[0],
1431                                                     &unlinkData->unlinkDev[1] /*Dest*/);
1432             OIC_LOG_V(DEBUG, TAG, "Credential revocation request device 2, result :: %d",res);
1433             if (OC_STACK_OK != res)
1434             {
1435                  OIC_LOG(ERROR, TAG, "Error while sending revocation request for device 2");
1436                  registerResultForUnlinkDevices(unlinkData, OC_STACK_INVALID_REQUEST_HANDLE,
1437                                                 IDX_SECOND_DEVICE_RES);
1438                  unlinkData->resultCallback(unlinkData->ctx,
1439                                             unlinkData->numOfResults, unlinkData->unlinkRes, true);
1440                  goto error;
1441             }
1442             else
1443             {
1444                 OIC_LOG(DEBUG, TAG, "Request for credential revocation successfully sent");
1445                 return OC_STACK_DELETE_TRANSACTION;
1446             }
1447         }
1448         else
1449         {
1450             OIC_LOG(ERROR, TAG, "Unable to delete credential information from device 1");
1451
1452             unlinkData->resultCallback(unlinkData->ctx, unlinkData->numOfResults,
1453                                             unlinkData->unlinkRes, true);
1454             goto error;
1455         }
1456     }
1457     else
1458     {
1459         OIC_LOG(DEBUG, TAG, "Invalid response from server");
1460         registerResultForUnlinkDevices(unlinkData, OC_STACK_INVALID_REQUEST_HANDLE,
1461                                        IDX_FIRST_DEVICE_RES );
1462         unlinkData->resultCallback(unlinkData->ctx,
1463                                    unlinkData->numOfResults, unlinkData->unlinkRes,
1464                                    true);
1465         OIC_LOG(ERROR, TAG, "SRPUnlinkDevice1CB received Null clientResponse");
1466     }
1467
1468 error:
1469     OIC_LOG_V(INFO, TAG, "Out SRPUnlinkDevice1CB");
1470     DeleteUnlinkData_t(unlinkData);
1471     return OC_STACK_DELETE_TRANSACTION;
1472 }
1473
1474 /*
1475 * Function to unlink devices.
1476 * This function will remove the credential & relationship between the two devices.
1477 *
1478 * @param[in] ctx Application context would be returned in result callback
1479 * @param[in] pTargetDev1 first device information to be unlinked.
1480 * @param[in] pTargetDev2 second device information to be unlinked.
1481 * @param[in] resultCallback callback provided by API user, callback will be called when
1482 *            device unlink is finished.
1483  * @return  OC_STACK_OK in case of success and other value otherwise.
1484 */
1485 OCStackResult SRPUnlinkDevices(void* ctx,
1486                                const OCProvisionDev_t* pTargetDev1,
1487                                const OCProvisionDev_t* pTargetDev2,
1488                                OCProvisionResultCB resultCallback)
1489 {
1490     OIC_LOG(INFO, TAG, "IN SRPUnlinkDevices");
1491
1492     if (!pTargetDev1 || !pTargetDev2 || !pTargetDev1->doxm || !pTargetDev2->doxm)
1493     {
1494         OIC_LOG(INFO, TAG, "SRPUnlinkDevices : NULL parameters");
1495         return OC_STACK_INVALID_PARAM;
1496     }
1497     if (!resultCallback)
1498     {
1499         OIC_LOG(INFO, TAG, "SRPUnlinkDevices : NULL Callback");
1500         return OC_STACK_INVALID_CALLBACK;
1501     }
1502     if (0 == memcmp(&pTargetDev1->doxm->deviceID, &pTargetDev2->doxm->deviceID, sizeof(OicUuid_t)))
1503     {
1504         OIC_LOG(INFO, TAG, "SRPUnlinkDevices : Same device ID");
1505         return OC_STACK_INVALID_PARAM;
1506     }
1507
1508     OIC_LOG(INFO, TAG, "Unlinking following devices: ");
1509     PMPrintOCProvisionDev(pTargetDev1);
1510     PMPrintOCProvisionDev(pTargetDev2);
1511
1512     // Mark the link status stale
1513     OCStackResult res = PDMSetLinkStale(&pTargetDev1->doxm->deviceID, &pTargetDev2->doxm->deviceID);
1514     if (OC_STACK_OK != res)
1515     {
1516         OIC_LOG(FATAL, TAG, "unable to update DB. Try again.");
1517         return res;
1518     }
1519
1520     UnlinkData_t* unlinkData = (UnlinkData_t*)OICCalloc(1, sizeof(UnlinkData_t));
1521     VERIFY_NON_NULL_RET(TAG, unlinkData, ERROR, OC_STACK_NO_MEMORY);
1522
1523     //Initialize unlink data
1524     unlinkData->ctx = ctx;
1525     unlinkData->unlinkDev = (OCProvisionDev_t*)OICCalloc(2, sizeof(OCProvisionDev_t));
1526     if (NULL == unlinkData->unlinkDev)
1527     {
1528         OIC_LOG(ERROR, TAG, "Memory allocation failed");
1529         res = OC_STACK_NO_MEMORY;
1530         goto error;
1531     }
1532
1533     unlinkData->unlinkRes = (OCProvisionResult_t*)OICCalloc(3, sizeof(OCProvisionResult_t));
1534     if (NULL == unlinkData->unlinkRes)
1535     {
1536         OIC_LOG(ERROR, TAG, "Memory allocation failed");
1537         res = OC_STACK_NO_MEMORY;
1538         goto error;
1539     }
1540
1541     memcpy(&unlinkData->unlinkDev[0], pTargetDev1, sizeof(OCProvisionDev_t));
1542     memcpy(&unlinkData->unlinkDev[1], pTargetDev2, sizeof(OCProvisionDev_t));
1543
1544     unlinkData->numOfResults = 0;
1545     unlinkData->resultCallback = resultCallback;
1546
1547     res = SendDeleteCredentialRequest((void*)unlinkData, &SRPUnlinkDevice1CB,
1548                                        &unlinkData->unlinkDev[1], &unlinkData->unlinkDev[0]);
1549     if (OC_STACK_OK != res)
1550     {
1551         OIC_LOG(ERROR, TAG, "SRPUnlinkDevices : SendDeleteCredentialRequest failed");
1552         goto error;
1553     }
1554
1555     return res;
1556
1557 error:
1558     OIC_LOG(INFO, TAG, "OUT SRPUnlinkDevices");
1559     DeleteUnlinkData_t(unlinkData);
1560     return res;
1561 }
1562
1563 static void DeleteRemoveData_t(RemoveData_t* pRemoveData)
1564 {
1565     if (pRemoveData)
1566     {
1567         OICFree(pRemoveData->revokeTargetDev);
1568         OCDeleteDiscoveredDevices(pRemoveData->linkedDevList);
1569         OICFree(pRemoveData->removeRes);
1570         OICFree(pRemoveData);
1571     }
1572 }
1573
1574 static void registerResultForRemoveDevice(RemoveData_t *removeData, OicUuid_t *pLinkedDevId,
1575                                           OCStackResult stackresult, bool hasError)
1576 {
1577     OIC_LOG_V(INFO, TAG, "Inside registerResultForRemoveDevice removeData->numOfResults is %zu\n",
1578                          removeData->numOfResults + 1);
1579     if (pLinkedDevId)
1580     {
1581         memcpy(removeData->removeRes[(removeData->numOfResults)].deviceId.id,
1582                &pLinkedDevId->id, sizeof(pLinkedDevId->id));
1583     }
1584     else
1585     {
1586         memset(removeData->removeRes[(removeData->numOfResults)].deviceId.id,
1587                0, sizeof(pLinkedDevId->id) );
1588     }
1589     removeData->removeRes[(removeData->numOfResults)].res = stackresult;
1590     removeData->hasError = hasError;
1591     ++(removeData->numOfResults);
1592
1593     // If we get suffcient result from linked devices, we have to call user callback and do free
1594     if (removeData->sizeOfResArray == removeData->numOfResults)
1595     {
1596         if(!removeData->hasError)
1597         {
1598             // Remove device info from prvisioning database
1599             if (OC_STACK_OK != PDMDeleteDevice(&removeData->revokeTargetDev->doxm->deviceID))
1600             {
1601                 OIC_LOG(ERROR, TAG, "ResultForRemoveDevice : Failed to remove device in PDM.");
1602                 removeData->hasError = true;
1603             }
1604         }
1605         removeData->resultCallback(removeData->ctx, removeData->numOfResults, removeData->removeRes,
1606                                    removeData->hasError);
1607         DeleteRemoveData_t(removeData);
1608     }
1609  }
1610
1611 static void registerResultForResetDevice(RemoveData_t *removeData, OicUuid_t *pLinkedDevId,
1612                                           OCStackResult stackresult, bool hasError)
1613 {
1614     OIC_LOG_V(INFO, TAG, "Inside registerResultForResetDevice removeData->numOfResults is %zu\n",
1615                          removeData->numOfResults + 1);
1616     if (pLinkedDevId)
1617     {
1618         memcpy(removeData->removeRes[(removeData->numOfResults)].deviceId.id,
1619                &pLinkedDevId->id, sizeof(pLinkedDevId->id));
1620     }
1621     else
1622     {
1623         memset(removeData->removeRes[(removeData->numOfResults)].deviceId.id,
1624                0, sizeof(pLinkedDevId->id) );
1625     }
1626     removeData->removeRes[(removeData->numOfResults)].res = stackresult;
1627     removeData->hasError = hasError;
1628     ++(removeData->numOfResults);
1629
1630     // If we get suffcient result from linked devices, we have to call user callback and do free
1631     if (removeData->sizeOfResArray == removeData->numOfResults)
1632     {
1633         removeData->resultCallback(removeData->ctx, removeData->numOfResults, removeData->removeRes,
1634                                    removeData->hasError);
1635         DeleteRemoveData_t(removeData);
1636     }
1637 }
1638
1639 /**
1640  * Callback handler of unlink first device.
1641  *
1642  * @param[in] ctx             ctx value passed to callback from calling function.
1643  * @param[in] handle          handle to an invocation
1644  * @param[in] clientResponse  Response from queries to remote servers.
1645  * @return  OC_STACK_DELETE_TRANSACTION to delete the transaction
1646  *          and  OC_STACK_KEEP_TRANSACTION to keep it.
1647  */
1648 static OCStackApplicationResult SRPRemoveDeviceCB(void *delDevCtx, OCDoHandle handle,
1649         OCClientResponse *clientResponse)
1650 {
1651     //Update the delete credential into delete device context
1652     //Save the deleted status in delDevCtx
1653     (void)handle;
1654     OIC_LOG_V(INFO, TAG, "Inside SRPRemoveDeviceCB.");
1655     VERIFY_NON_NULL_RET(TAG, delDevCtx, ERROR, OC_STACK_DELETE_TRANSACTION);
1656     OCStackResult res = OC_STACK_ERROR;
1657
1658     RemoveData_t* removeData = (RemoveData_t*)delDevCtx;
1659
1660     if (clientResponse)
1661     {
1662         OicUuid_t revDevUuid = {.id={0}};
1663         if(UUID_LENGTH == clientResponse->identity.id_length)
1664         {
1665             memcpy(revDevUuid.id, clientResponse->identity.id, sizeof(revDevUuid.id));
1666             if (OC_STACK_RESOURCE_DELETED == clientResponse->result)
1667             {
1668                 res = PDMUnlinkDevices(&removeData->revokeTargetDev->doxm->deviceID, &revDevUuid);
1669                 if (OC_STACK_OK != res)
1670                 {
1671                     OIC_LOG(ERROR, TAG, "PDMSetLinkStale() FAIL: PDB is an obsolete one.");
1672                            registerResultForRemoveDevice(removeData, &revDevUuid,
1673                            OC_STACK_INCONSISTENT_DB, true);
1674
1675                     return OC_STACK_DELETE_TRANSACTION;
1676                 }
1677
1678                 registerResultForRemoveDevice(removeData, &revDevUuid,
1679                                               OC_STACK_RESOURCE_DELETED, false);
1680             }
1681             else
1682             {
1683                 registerResultForRemoveDevice(removeData, &revDevUuid,
1684                                               clientResponse->result, true);
1685                 OIC_LOG(ERROR, TAG, "Unexpected result from DELETE credential request!");
1686             }
1687         }
1688         else
1689         {
1690             OIC_LOG_V(WARNING, TAG, "Incorrect length of device UUID was sent from %s:%d",
1691                      clientResponse->devAddr.addr, clientResponse->devAddr.port);
1692
1693             if (OC_STACK_RESOURCE_DELETED == clientResponse->result)
1694             {
1695                 /**
1696                   * Since server's credential was deleted,
1697                   * register result as OC_STACK_INCONSISTENT_DB with NULL UUID.
1698                   */
1699                 OIC_LOG_V(ERROR, TAG, "But server's credential was deleted.");
1700                 registerResultForRemoveDevice(removeData, NULL, OC_STACK_INCONSISTENT_DB, true);
1701             }
1702             else
1703             {
1704                 registerResultForRemoveDevice(removeData, NULL, clientResponse->result, true);
1705             }
1706         }
1707     }
1708     else
1709     {
1710         registerResultForRemoveDevice(removeData, NULL, OC_STACK_ERROR, true);
1711         OIC_LOG(ERROR, TAG, "SRPRemoveDevices received Null clientResponse");
1712     }
1713
1714
1715     return OC_STACK_DELETE_TRANSACTION;
1716 }
1717
1718 /**
1719  * Callback handler of reset device.
1720  *
1721  * @param[in] ctx             ctx value passed to callback from calling function.
1722  * @param[in] handle          handle to an invocation
1723  * @param[in] clientResponse  Response from queries to remote servers.
1724  * @return  OC_STACK_DELETE_TRANSACTION to delete the transaction
1725  *          and  OC_STACK_KEEP_TRANSACTION to keep it.
1726  */
1727 static OCStackApplicationResult SRPSyncDeviceCredCB(void *delDevCtx, OCDoHandle handle,
1728         OCClientResponse *clientResponse)
1729 {
1730     //Update the delete credential into delete device context
1731     //Save the deleted status in delDevCtx
1732     (void)handle;
1733     OIC_LOG_V(INFO, TAG, "Inside SRPSyncDeviceCredCB.");
1734     VERIFY_NON_NULL_RET(TAG, delDevCtx, ERROR, OC_STACK_DELETE_TRANSACTION);
1735     OCStackResult res = OC_STACK_ERROR;
1736
1737     RemoveData_t* removeData = (RemoveData_t*)delDevCtx;
1738     OCProvisionDev_t * pTargetDev = PMCloneOCProvisionDev(removeData->revokeTargetDev);
1739     OCClientContextDeleter deleteCallback = removeData->deleteCallback;
1740     if (clientResponse)
1741     {
1742         OicUuid_t revDevUuid = {.id={0}};
1743         if(UUID_LENGTH == clientResponse->identity.id_length)
1744         {
1745             memcpy(revDevUuid.id, clientResponse->identity.id, sizeof(revDevUuid.id));
1746             if (OC_STACK_RESOURCE_DELETED == clientResponse->result)
1747             {
1748                 res = PDMUnlinkDevices(&removeData->revokeTargetDev->doxm->deviceID, &revDevUuid);
1749                 if (OC_STACK_OK != res)
1750                 {
1751                     OIC_LOG(ERROR, TAG, "PDMSetLinkStale() FAIL: PDB is an obsolete one.");
1752                            registerResultForResetDevice(removeData, &revDevUuid,
1753                            OC_STACK_INCONSISTENT_DB, true);
1754
1755                     return OC_STACK_DELETE_TRANSACTION;
1756                 }
1757
1758                 registerResultForResetDevice(removeData, &revDevUuid,
1759                                               OC_STACK_RESOURCE_DELETED, false);
1760             }
1761             else
1762             {
1763                 registerResultForResetDevice(removeData, &revDevUuid,
1764                                               clientResponse->result, false);
1765                 OIC_LOG(ERROR, TAG, "Unexpected result from DELETE credential request!");
1766             }
1767         }
1768         else
1769         {
1770             OIC_LOG_V(WARNING, TAG, "Incorrect length of device UUID was sent from %s:%d",
1771                      clientResponse->devAddr.addr, clientResponse->devAddr.port);
1772
1773             if (OC_STACK_RESOURCE_DELETED == clientResponse->result)
1774             {
1775                 /**
1776                   * Since server's credential was deleted,
1777                   * register result as OC_STACK_INCONSISTENT_DB with NULL UUID.
1778                   */
1779                 OIC_LOG_V(ERROR, TAG, "But server's credential was deleted.");
1780                 registerResultForResetDevice(removeData, NULL, OC_STACK_INCONSISTENT_DB, true);
1781             }
1782             else
1783             {
1784                 registerResultForResetDevice(removeData, NULL, clientResponse->result, true);
1785             }
1786         }
1787     }
1788     else
1789     {
1790         registerResultForResetDevice(removeData, NULL, OC_STACK_ERROR, true);
1791         OIC_LOG(ERROR, TAG, "SRPSyncDevice received Null clientResponse");
1792     }
1793
1794     SRPResetDevice(pTargetDev, deleteCallback);
1795
1796     return OC_STACK_DELETE_TRANSACTION;
1797 }
1798
1799 /**
1800  * Callback handler of reset device sync-up
1801  *
1802  * @param[in] ctx             ctx value passed to callback from calling function.
1803  * @param[in] handle          handle to an invocation
1804  * @param[in] clientResponse  Response from queries to remote servers.
1805  * @return  OC_STACK_DELETE_TRANSACTION to delete the transaction
1806  *          and  OC_STACK_KEEP_TRANSACTION to keep it.
1807  */
1808 static OCStackApplicationResult SRPSyncDeviceACLCB(void *ctx, OCDoHandle UNUSED,
1809         OCClientResponse *clientResponse)
1810 {
1811     (void)ctx;
1812     (void)UNUSED;
1813     (void)clientResponse;
1814     return OC_STACK_DELETE_TRANSACTION;
1815 }
1816
1817 /**
1818  * Callback handler of device remote reset.
1819  *
1820  * @param[in] ctx             ctx value passed to callback from calling function.
1821  * @param[in] UNUSED          handle to an invocation
1822  * @param[in] clientResponse  Response from queries to remote servers.
1823  * @return  OC_STACK_DELETE_TRANSACTION to delete the transaction
1824  *          and  OC_STACK_KEEP_TRANSACTION to keep it.
1825  */
1826 static OCStackApplicationResult SRPResetDeviceCB(void *ctx, OCDoHandle UNUSED,
1827         OCClientResponse *clientResponse)
1828 {
1829     OIC_LOG(DEBUG, TAG, "IN SRPResetDeviceCB");
1830     (void)UNUSED;
1831     if(OC_STACK_OK == clientResponse->result)
1832     {
1833         OIC_LOG(DEBUG, TAG, "Change Target Device Pstat Cm SUCCEEDED");
1834     }
1835
1836     // Delete Cred and ACL related to the target device.
1837     const OicSecCred_t *cred = NULL;
1838     OCProvisionDev_t * pTargetDev = (OCProvisionDev_t *)ctx;
1839     cred = GetCredResourceData(&pTargetDev->doxm->deviceID);
1840     if (cred == NULL)
1841     {
1842         OIC_LOG(ERROR, TAG, "OCResetDevice : Failed to get credential of target device.");
1843         goto error;
1844     }
1845
1846     OCStackResult res = RemoveCredential(&cred->subject);
1847     if (res != OC_STACK_RESOURCE_DELETED && res != OC_STACK_NO_RESOURCE)
1848     {
1849         OIC_LOG(ERROR, TAG, "OCResetDevice : Failed to remove credential.");
1850         goto error;
1851     }
1852
1853     res = RemoveACE(&cred->subject, NULL);
1854     if (res != OC_STACK_RESOURCE_DELETED && res != OC_STACK_NO_RESOURCE)
1855     {
1856         OIC_LOG(ERROR, TAG, "OCResetDevice : Failed to remove ACL.");
1857         goto error;
1858     }
1859     if (OC_STACK_OK != PDMDeleteDevice(&pTargetDev->doxm->deviceID))
1860     {
1861         OIC_LOG(ERROR, TAG, "OCResetDevice : Failed to delete device from PDM");
1862     }
1863
1864     //Close the DTLS session of the reset device.
1865     CAEndpoint_t* endpoint = (CAEndpoint_t *)&clientResponse->devAddr;
1866     CAResult_t caResult = CAcloseSslSession(endpoint);
1867     if(CA_STATUS_OK != caResult)
1868     {
1869         OIC_LOG_V(WARNING, TAG, "OCResetDevice : Failed to close DTLS session : %d", caResult);
1870     }
1871
1872     /**
1873      * If there is no linked device, PM does not send any request.
1874      * So we should directly invoke the result callback to inform the result of OCResetDevice.
1875      */
1876     if(OC_STACK_NO_RESOURCE == res)
1877     {
1878         res = OC_STACK_OK;
1879     }
1880
1881 error:
1882     OICFree(pTargetDev);
1883     return OC_STACK_DELETE_TRANSACTION;
1884
1885 }
1886
1887 static OCStackResult GetListofDevToReqDeleteCred(const OCProvisionDev_t* pRevokeTargetDev,
1888                                                  const OCProvisionDev_t* pOwnedDevList,
1889                                                  OCUuidList_t* pLinkedUuidList,
1890                                                  OCProvisionDev_t** ppLinkedDevList,
1891                                                  size_t *numOfLinkedDev)
1892 {
1893     // pOwnedDevList could be NULL. It means no alived and owned device now.
1894     if (pRevokeTargetDev == NULL || pLinkedUuidList == NULL ||\
1895         ppLinkedDevList == NULL || numOfLinkedDev == NULL)
1896     {
1897         return OC_STACK_INVALID_PARAM;
1898     }
1899
1900     size_t cnt = 0;
1901     OCUuidList_t *curUuid = NULL, *tmpUuid = NULL;
1902     LL_FOREACH_SAFE(pLinkedUuidList, curUuid, tmpUuid)
1903     {
1904         // Mark the link status stale.
1905         OCStackResult res = PDMSetLinkStale(&curUuid->dev, &pRevokeTargetDev->doxm->deviceID);
1906         if (OC_STACK_OK != res)
1907         {
1908             OIC_LOG(FATAL, TAG, "PDMSetLinkStale() FAIL: PDB is an obsolete one.");
1909             return OC_STACK_SVR_DB_NOT_EXIST;
1910         }
1911
1912         if (pOwnedDevList)
1913         {
1914             // If this linked device is alive (power-on), add the deivce to the list.
1915             const OCProvisionDev_t *curDev = NULL;
1916             const OCProvisionDev_t *tmpDev = NULL;
1917             LL_FOREACH_SAFE(pOwnedDevList, curDev, tmpDev)
1918             {
1919                 if (memcmp(curDev->doxm->deviceID.id, curUuid->dev.id, sizeof(curUuid->dev.id)) == 0)
1920                 {
1921                     OCProvisionDev_t* targetDev = PMCloneOCProvisionDev(curDev);
1922                     if (NULL == targetDev)
1923                     {
1924                         OIC_LOG(ERROR, TAG, "SRPRemoveDevice : Cloning OCProvisionDev_t Failed.");
1925                         return OC_STACK_NO_MEMORY;
1926                     }
1927
1928                     LL_PREPEND(*ppLinkedDevList, targetDev);
1929                     cnt++;
1930                     break;
1931                 }
1932             }
1933         }
1934     }
1935     *numOfLinkedDev = cnt;
1936     return OC_STACK_OK;
1937 }
1938
1939 /*
1940 * Function to device revocation
1941 * This function will remove credential of target device from all devices in subnet.
1942 *
1943 * @param[in] ctx Application context would be returned in result callback
1944 * @param[in] waitTimeForOwnedDeviceDiscovery Maximum wait time for owned device discovery.(seconds)
1945 * @param[in] pTargetDev Device information to be revoked.
1946 * @param[in] resultCallback callback provided by API user, callback will be called when
1947 *            credential revocation is finished.
1948 * @return  OC_STACK_OK in case of success and other value otherwise.
1949 *          If OC_STACK_OK is returned, the caller of this API should wait for callback.
1950 *          OC_STACK_CONTINUE means operation is success but no request is need to be initiated.
1951 */
1952 OCStackResult SRPRemoveDevice(void* ctx, unsigned short waitTimeForOwnedDeviceDiscovery,
1953                              const OCProvisionDev_t* pTargetDev, OCProvisionResultCB resultCallback)
1954 {
1955     OIC_LOG(INFO, TAG, "IN SRPRemoveDevice");
1956
1957     if (!pTargetDev  || 0 == waitTimeForOwnedDeviceDiscovery)
1958     {
1959         OIC_LOG(INFO, TAG, "SRPRemoveDevice : NULL parameters");
1960         return OC_STACK_INVALID_PARAM;
1961     }
1962     if (!resultCallback)
1963     {
1964         OIC_LOG(INFO, TAG, "SRPRemoveDevice : NULL Callback");
1965         return OC_STACK_INVALID_CALLBACK;
1966     }
1967
1968     // Declare variables in here to handle error cases with goto statement.
1969     OCProvisionDev_t* pOwnedDevList = NULL;
1970     OCProvisionDev_t* pLinkedDevList = NULL;
1971     RemoveData_t* removeData = NULL;
1972
1973     //1. Find all devices that has a credential of the revoked device
1974     OCUuidList_t* pLinkedUuidList = NULL;
1975     size_t numOfDevices = 0;
1976     OCStackResult res = OC_STACK_ERROR;
1977     res = PDMGetLinkedDevices(&pTargetDev->doxm->deviceID, &pLinkedUuidList, &numOfDevices);
1978     if (OC_STACK_OK != res)
1979     {
1980         OIC_LOG(ERROR, TAG, "SRPRemoveDevice : Failed to get linked devices information");
1981         return res;
1982     }
1983     // if there is no related device, we can skip further process.
1984     if (0 == numOfDevices)
1985     {
1986         OIC_LOG(DEBUG, TAG, "SRPRemoveDevice : No linked device found.");
1987         res = OC_STACK_CONTINUE;
1988         goto error;
1989     }
1990
1991     //2. Find owned device from the network
1992     res = PMDeviceDiscovery(waitTimeForOwnedDeviceDiscovery, true, &pOwnedDevList);
1993     if (OC_STACK_OK != res)
1994     {
1995         OIC_LOG(ERROR, TAG, "SRPRemoveDevice : Failed to PMDeviceDiscovery");
1996         goto error;
1997     }
1998
1999     //3. Make a list of devices to send DELETE credential request
2000     //   by comparing owned devices from provisioning database with mutlicast discovery result.
2001     size_t numOfLinkedDev = 0;
2002     res = GetListofDevToReqDeleteCred(pTargetDev, pOwnedDevList, pLinkedUuidList,
2003                                       &pLinkedDevList, &numOfLinkedDev);
2004     if (OC_STACK_OK != res)
2005     {
2006         OIC_LOG(ERROR, TAG, "SRPRemoveDevice : GetListofDevToReqDeleteCred() failed");
2007         goto error;
2008     }
2009     if (0 == numOfLinkedDev) // This case means, there is linked device but it's not alive now.
2010     {                       // So we don't have to send request message.
2011         OIC_LOG(DEBUG, TAG, "SRPRemoveDevice : No alived & linked device found.");
2012         res = OC_STACK_CONTINUE;
2013         goto error;
2014     }
2015
2016     // 4. Prepare RemoveData Context data.
2017     removeData = (RemoveData_t*)OICCalloc(1, sizeof(RemoveData_t));
2018     if (!removeData)
2019     {
2020         OIC_LOG(ERROR, TAG, "SRPRemoveDevices : Failed to memory allocation");
2021         res = OC_STACK_NO_MEMORY;
2022         goto error;
2023     }
2024
2025     removeData->revokeTargetDev = PMCloneOCProvisionDev(pTargetDev);
2026     if (!removeData->revokeTargetDev)
2027     {
2028         OIC_LOG(ERROR, TAG, "SRPRemoveDevices : PMCloneOCProvisionDev Failed");
2029         res = OC_STACK_NO_MEMORY;
2030         goto error;
2031     }
2032
2033     removeData->removeRes =
2034         (OCProvisionResult_t*)OICCalloc(numOfLinkedDev, sizeof(OCProvisionResult_t));
2035     if (!removeData->removeRes)
2036     {
2037         OIC_LOG(ERROR, TAG, "SRPRemoveDevices : Failed to memory allocation");
2038         res = OC_STACK_NO_MEMORY;
2039         goto error;
2040     }
2041
2042     removeData->ctx = ctx;
2043     removeData->linkedDevList = pLinkedDevList;
2044     removeData->resultCallback = resultCallback;
2045     removeData->numOfResults = 0;
2046     removeData->sizeOfResArray = numOfLinkedDev;
2047     removeData->hasError = false;
2048
2049     // 5. Send DELETE credential request to linked devices.
2050     OCProvisionDev_t *curDev = NULL, *tmpDev = NULL;
2051     OCStackResult totalRes = OC_STACK_ERROR;  /* variable for checking request is sent or not */
2052     LL_FOREACH_SAFE(pLinkedDevList, curDev, tmpDev)
2053     {
2054         res = SendDeleteCredentialRequest((void*)removeData, &SRPRemoveDeviceCB,
2055                                            removeData->revokeTargetDev, curDev);
2056         if (OC_STACK_OK != res)
2057         {
2058             OIC_LOG_V(ERROR, TAG, "SRPRemoveDevice : Fail to send the DELETE credential request to\
2059                      %s:%u", curDev->endpoint.addr, curDev->endpoint.port);
2060         }
2061         else
2062         {
2063             totalRes = OC_STACK_OK; // This means at least one request is successfully sent.
2064         }
2065     }
2066
2067     PDMDestoryOicUuidLinkList(pLinkedUuidList); //TODO: Modify API name to have unified convention.
2068     PMDeleteDeviceList(pOwnedDevList);
2069     OIC_LOG(INFO, TAG, "OUT SRPRemoveDevice");
2070
2071     return totalRes; // Caller of this API should wait callback if totalRes == OC_STACK_OK.
2072
2073 error:
2074     PDMDestoryOicUuidLinkList(pLinkedUuidList);
2075     PMDeleteDeviceList(pOwnedDevList);
2076     PMDeleteDeviceList(pLinkedDevList);
2077     if (removeData)
2078     {
2079         OICFree(removeData->revokeTargetDev);
2080         OICFree(removeData->removeRes);
2081         OICFree(removeData);
2082     }
2083     OIC_LOG(INFO, TAG, "OUT ERROR case SRPRemoveDevice");
2084     return res;
2085 }
2086
2087 /*
2088 * Function to device revocation
2089 * This function will remove credential of target device from all devices in subnet.
2090 *
2091 * @param[in] ctx Application context would be returned in result callback
2092 * @param[in] pOwnedDevList List of owned devices
2093 * @param[in] pTargetDev Device information to be revoked.
2094 * @param[in] resultCallback callback provided by API user, callback will be called when
2095 *            credential revocation is finished.
2096 * @return  OC_STACK_OK in case of success and other value otherwise.
2097 *          If OC_STACK_OK is returned, the caller of this API should wait for callback.
2098 *          OC_STACK_CONTINUE means operation is success but no request is need to be initiated.
2099 */
2100 OCStackResult SRPRemoveDeviceWithoutDiscovery(void* ctx, const OCProvisionDev_t* pOwnedDevList,
2101                              const OCProvisionDev_t* pTargetDev, OCProvisionResultCB resultCallback)
2102 {
2103     OIC_LOG(INFO, TAG, "IN SRPRemoveDeviceWithoutDiscovery");
2104
2105     if (!pOwnedDevList)
2106     {
2107         OIC_LOG(WARNING, TAG, "SRPRemoveDeviceWithoutDiscovery : Owned Device List is empty");
2108         return OC_STACK_CONTINUE;
2109     }
2110     if (!pTargetDev)
2111     {
2112         OIC_LOG(INFO, TAG, "SRPRemoveDeviceWithoutDiscovery : NULL parameters");
2113         return OC_STACK_INVALID_PARAM;
2114     }
2115     if (!resultCallback)
2116     {
2117         OIC_LOG(INFO, TAG, "SRPRemoveDeviceWithoutDiscovery : NULL Callback");
2118         return OC_STACK_INVALID_CALLBACK;
2119     }
2120
2121     // Declare variables in here to handle error cases with goto statement.
2122     OCProvisionDev_t* pLinkedDevList = NULL;
2123     RemoveData_t* removeData = NULL;
2124
2125     //1. Find all devices that has a credential of the revoked device
2126     OCUuidList_t* pLinkedUuidList = NULL;
2127     size_t numOfDevices = 0;
2128     OCStackResult res = OC_STACK_ERROR;
2129     res = PDMGetLinkedDevices(&pTargetDev->doxm->deviceID, &pLinkedUuidList, &numOfDevices);
2130     if (OC_STACK_OK != res)
2131     {
2132         OIC_LOG(WARNING, TAG, "SRPRemoveDeviceWithoutDiscovery : Failed to get linked devices information");
2133         return OC_STACK_CONTINUE;
2134     }
2135     // if there is no related device, we can skip further process.
2136     if (0 == numOfDevices)
2137     {
2138         OIC_LOG(WARNING, TAG, "SRPRemoveDeviceWithoutDiscovery : No linked device found.");
2139         return OC_STACK_CONTINUE;
2140     }
2141
2142     //2. Make a list of devices to send DELETE credential request
2143     //   by comparing owned devices from provisioning database with mutlicast discovery result.
2144     size_t numOfLinkedDev = 0;
2145     res = GetListofDevToReqDeleteCred(pTargetDev, pOwnedDevList, pLinkedUuidList,
2146                                       &pLinkedDevList, &numOfLinkedDev);
2147     if (OC_STACK_OK != res)
2148     {
2149         OIC_LOG(ERROR, TAG, "SRPRemoveDeviceWithoutDiscovery : GetListofDevToReqDeleteCred() failed");
2150         goto error;
2151     }
2152     if (0 == numOfLinkedDev) // This case means, there is linked device but it's not alive now.
2153     {                       // So we don't have to send request message.
2154         OIC_LOG(DEBUG, TAG, "SRPRemoveDeviceWithoutDiscovery : No alived & linked device found.");
2155         return OC_STACK_CONTINUE;
2156     }
2157
2158     // 3. Prepare RemoveData Context data.
2159     removeData = (RemoveData_t*)OICCalloc(1, sizeof(RemoveData_t));
2160     if (!removeData)
2161     {
2162         OIC_LOG(ERROR, TAG, "SRPRemoveDeviceWithoutDiscovery : Failed to memory allocation");
2163         res = OC_STACK_NO_MEMORY;
2164         goto error;
2165     }
2166
2167     removeData->revokeTargetDev = PMCloneOCProvisionDev(pTargetDev);
2168     if (!removeData->revokeTargetDev)
2169     {
2170         OIC_LOG(ERROR, TAG, "SRPRemoveDeviceWithoutDiscovery : PMCloneOCProvisionDev Failed");
2171         res = OC_STACK_NO_MEMORY;
2172         goto error;
2173     }
2174
2175     removeData->removeRes =
2176         (OCProvisionResult_t*)OICCalloc(numOfLinkedDev, sizeof(OCProvisionResult_t));
2177     if (!removeData->removeRes)
2178     {
2179         OIC_LOG(ERROR, TAG, "SRPRemoveDeviceWithoutDiscovery : Failed to memory allocation");
2180         res = OC_STACK_NO_MEMORY;
2181         goto error;
2182     }
2183
2184     removeData->ctx = ctx;
2185     removeData->linkedDevList = pLinkedDevList;
2186     removeData->resultCallback = resultCallback;
2187     removeData->numOfResults = 0;
2188     removeData->sizeOfResArray = numOfLinkedDev;
2189     removeData->hasError = false;
2190
2191     // 5. Send DELETE credential request to linked devices.
2192     OCProvisionDev_t *curDev = NULL, *tmpDev = NULL;
2193     OCStackResult totalRes = OC_STACK_ERROR;  /* variable for checking request is sent or not */
2194     LL_FOREACH_SAFE(pLinkedDevList, curDev, tmpDev)
2195     {
2196         res = SendDeleteCredentialRequest((void*)removeData, &SRPRemoveDeviceCB,
2197                                            removeData->revokeTargetDev, curDev);
2198         if (OC_STACK_OK != res)
2199         {
2200             OIC_LOG_V(ERROR, TAG, "SRPRemoveDeviceWithoutDiscovery : Fail to send the DELETE credential request to\
2201                      %s:%u", curDev->endpoint.addr, curDev->endpoint.port);
2202         }
2203         else
2204         {
2205             totalRes = OC_STACK_OK; // This means at least one request is successfully sent.
2206         }
2207     }
2208
2209     PDMDestoryOicUuidLinkList(pLinkedUuidList); //TODO: Modify API name to have unified convention.
2210     OIC_LOG(INFO, TAG, "OUT SRPRemoveDeviceWithoutDiscovery");
2211
2212     return totalRes; // Caller of this API should wait callback if totalRes == OC_STACK_OK.
2213
2214 error:
2215     PDMDestoryOicUuidLinkList(pLinkedUuidList);
2216     PMDeleteDeviceList(pLinkedDevList);
2217     if (removeData)
2218     {
2219         OICFree(removeData->revokeTargetDev);
2220         OICFree(removeData->removeRes);
2221         OICFree(removeData);
2222     }
2223     OIC_LOG(INFO, TAG, "OUT ERROR case SRPRemoveDeviceWithoutDiscovery");
2224     return res;
2225 }
2226
2227 /*
2228  * Function to sync-up credential and ACL of the target device.
2229  * This function will remove credential and ACL of target device from all devices in subnet.
2230  *
2231  * @param[in] ctx Application context would be returned in result callback
2232  * @param[in] waitTimeForOwnedDeviceDiscovery Maximum wait time for owned device discovery.(seconds)
2233  * @param[in] pTargetDev Device information to be revoked.
2234  * @param[in] resultCallback callback provided by API user, callback will be called when
2235  *            credential revocation is finished.
2236  *            when there is an error, this user callback is called immediately.
2237  * @return OC_STACK_OK in case of success and other value otherwise.
2238  *         If OC_STACK_OK is returned, the caller of this API should wait for callback.
2239  *         OC_STACK_CONTINUE means operation is success but no request is need to be initiated.
2240  */
2241 OCStackResult SRPSyncDevice(void* ctx, unsigned short waitTimeForOwnedDeviceDiscovery,
2242                          const OCProvisionDev_t* pTargetDev, OCProvisionResultCB resultCallback)
2243 {
2244     OIC_LOG(INFO, TAG, "IN SRPSyncDevice");
2245     if (!pTargetDev  || 0 == waitTimeForOwnedDeviceDiscovery)
2246     {
2247         OIC_LOG(INFO, TAG, "SRPSyncDevice : NULL parameters");
2248         return OC_STACK_INVALID_PARAM;
2249     }
2250     if (!resultCallback)
2251     {
2252         OIC_LOG(INFO, TAG, "SRPSyncDevice : NULL Callback");
2253         return OC_STACK_INVALID_CALLBACK;
2254     }
2255
2256     // Declare variables in here to handle error cases with goto statement.
2257     OCProvisionDev_t* pOwnedDevList = NULL;
2258     OCProvisionDev_t* pLinkedDevList = NULL;
2259     RemoveData_t* removeData = NULL;
2260
2261     //1. Find all devices that has a credential of the revoked device
2262     OCUuidList_t* pLinkedUuidList = NULL;
2263     size_t numOfDevices = 0;
2264     OCStackResult res = OC_STACK_ERROR;
2265     res = PDMGetLinkedDevices(&pTargetDev->doxm->deviceID, &pLinkedUuidList, &numOfDevices);
2266     if (OC_STACK_OK != res)
2267     {
2268         OIC_LOG(ERROR, TAG, "SRPSyncDevice : Failed to get linked devices information");
2269         return res;
2270     }
2271     // if there is no related device, we can skip further process.
2272     if (0 == numOfDevices)
2273     {
2274         OIC_LOG(DEBUG, TAG, "SRPSyncDevice : No linked device found.");
2275         res = OC_STACK_CONTINUE;
2276         goto error;
2277     }
2278
2279     //2. Find owned device from the network
2280     res = PMDeviceDiscovery(waitTimeForOwnedDeviceDiscovery, true, &pOwnedDevList);
2281     if (OC_STACK_OK != res)
2282     {
2283         OIC_LOG(ERROR, TAG, "SRPSyncDevice : Failed to PMDeviceDiscovery");
2284         goto error;
2285     }
2286
2287     //3. Make a list of devices to send DELETE credential request
2288     //   by comparing owned devices from provisioning database with mutlicast discovery result.
2289     size_t numOfLinkedDev = 0;
2290     res = GetListofDevToReqDeleteCred(pTargetDev, pOwnedDevList, pLinkedUuidList,
2291                                       &pLinkedDevList, &numOfLinkedDev);
2292     if (OC_STACK_OK != res)
2293     {
2294         OIC_LOG(ERROR, TAG, "SRPSyncDevice : GetListofDevToReqDeleteCred() failed");
2295         goto error;
2296     }
2297     if (0 == numOfLinkedDev) // This case means, there is linked device but it's not alive now.
2298     {                       // So we don't have to send request message.
2299         OIC_LOG(DEBUG, TAG, "SRPSyncDevice : No alived & linked device found.");
2300         res = OC_STACK_CONTINUE;
2301         goto error;
2302     }
2303
2304     // 4. Prepare RemoveData Context data.
2305     removeData = (RemoveData_t*)OICCalloc(1, sizeof(RemoveData_t));
2306     if (!removeData)
2307     {
2308         OIC_LOG(ERROR, TAG, "SRPSyncDevice : Failed to memory allocation");
2309         res = OC_STACK_NO_MEMORY;
2310         goto error;
2311     }
2312
2313     removeData->revokeTargetDev = PMCloneOCProvisionDev(pTargetDev);
2314     if (!removeData->revokeTargetDev)
2315     {
2316         OIC_LOG(ERROR, TAG, "SRPSyncDevice : PMCloneOCProvisionDev Failed");
2317         res = OC_STACK_NO_MEMORY;
2318         goto error;
2319     }
2320
2321     removeData->removeRes =
2322         (OCProvisionResult_t*)OICCalloc(numOfLinkedDev, sizeof(OCProvisionResult_t));
2323     if (!removeData->removeRes)
2324     {
2325         OIC_LOG(ERROR, TAG, "SRPSyncDevice : Failed to allocate memory");
2326         res = OC_STACK_NO_MEMORY;
2327         goto error;
2328     }
2329
2330     removeData->ctx = ctx;
2331     removeData->linkedDevList = pLinkedDevList;
2332     removeData->resultCallback = resultCallback;
2333     removeData->numOfResults = 0;
2334     removeData->sizeOfResArray = numOfLinkedDev;
2335     removeData->hasError = false;
2336
2337     // 5. Send DELETE credential request to linked devices.
2338     OCProvisionDev_t *curDev = NULL, *tmpDev = NULL;
2339     OCStackResult totalRes = OC_STACK_ERROR;  /* variable for checking request is sent or not */
2340     LL_FOREACH_SAFE(pLinkedDevList, curDev, tmpDev)
2341     {
2342         res = SendDeleteACLRequest((void*)removeData, &SRPSyncDeviceACLCB,
2343                                            removeData->revokeTargetDev, curDev);
2344         if (OC_STACK_OK != res)
2345         {
2346             OIC_LOG_V(ERROR, TAG, "SRPSyncDevice : Fail to send the DELETE ACL request to\
2347                      %s:%u", curDev->endpoint.addr, curDev->endpoint.port);
2348             goto error;
2349         }
2350         res = SendDeleteCredentialRequest((void*)removeData, &SRPSyncDeviceCredCB,
2351                                            removeData->revokeTargetDev, curDev);
2352         if (OC_STACK_OK != res)
2353         {
2354             OIC_LOG_V(ERROR, TAG, "SRPSyncDevice : Fail to send the DELETE credential request to\
2355                      %s:%u", curDev->endpoint.addr, curDev->endpoint.port);
2356             totalRes = OC_STACK_ERROR;
2357         }
2358         else
2359         {
2360             totalRes = OC_STACK_OK; // This means at least one request is successfully sent.
2361         }
2362     }
2363
2364     PDMDestoryOicUuidLinkList(pLinkedUuidList); //TODO: Modify API name to have unified convention.
2365     PMDeleteDeviceList(pOwnedDevList);
2366     OIC_LOG(INFO, TAG, "OUT SRPSyncDevice");
2367
2368     return totalRes; // Caller of this API should wait callback if totalRes == OC_STACK_OK.
2369
2370 error:
2371     PDMDestoryOicUuidLinkList(pLinkedUuidList);
2372     PMDeleteDeviceList(pOwnedDevList);
2373     PMDeleteDeviceList(pLinkedDevList);
2374     if (removeData)
2375     {
2376         OICFree(removeData->revokeTargetDev);
2377         OICFree(removeData->removeRes);
2378         OICFree(removeData);
2379     }
2380     OIC_LOG(INFO, TAG, "OUT ERROR case SRPSyncDevice");
2381     return res;
2382 }
2383
2384 /*
2385  * Function for remote reset
2386  * This function will send pstat PUT message to the target device to initiate remote reset.
2387  *
2388  * @param[in] pTargetDev Device information to be revoked.
2389  * @param[in] resultCallback callback provided by API user, callback will be called when
2390  *            credential revocation is finished.
2391  *            when there is an error, this user callback is called immediately.
2392  * @return OC_STACK_OK in case of success and other value otherwise.
2393  *         If OC_STACK_OK is returned, the caller of this API should wait for callback.
2394  *         OC_STACK_CONTINUE means operation is success but no request is need to be initiated.
2395  */
2396 OCStackResult SRPResetDevice(const OCProvisionDev_t* pTargetDev,
2397         OCClientContextDeleter deleteCallback)
2398 {
2399     OIC_LOG(INFO, TAG, "IN SRPResetDevice");
2400     if (!pTargetDev)
2401     {
2402         OIC_LOG(INFO, TAG, "SRPResetDevice : NULL parameters");
2403         return OC_STACK_INVALID_PARAM;
2404     }
2405     if (!deleteCallback)
2406     {
2407         OIC_LOG(INFO, TAG, "SRPResetDevice : NULL Callback");
2408         return OC_STACK_INVALID_CALLBACK;
2409     }
2410
2411     OCStackResult res = OC_STACK_ERROR;
2412     OicSecPstat_t * pstat = (OicSecPstat_t *) OICCalloc(1, sizeof(OicSecPstat_t));
2413     if (!pstat)
2414     {
2415         OIC_LOG(ERROR, TAG, "Failed to allocate memory");
2416         return OC_STACK_NO_MEMORY;
2417     }
2418
2419     pstat->cm = RESET;
2420     pstat->isOp = false;
2421     memcpy(pstat->deviceID.id, pTargetDev->doxm->deviceID.id, sizeof(OicUuid_t));
2422     pstat->tm = TAKE_OWNER;
2423     pstat->om = (OicSecDpom_t)(SINGLE_SERVICE_CLIENT_DRIVEN); // the only mode IoTivity supports currently
2424     pstat->smLen = 1;
2425     pstat->sm = (OicSecDpom_t *) OICCalloc(pstat->smLen, sizeof(OicSecDpom_t));
2426     if (NULL == pstat->sm)
2427     {
2428         OIC_LOG(ERROR, TAG, "Failed to allocate memory");
2429         OICFree(pstat);
2430         return OC_STACK_NO_MEMORY;
2431     }
2432     pstat->sm[0] = (OicSecDpom_t)(SINGLE_SERVICE_CLIENT_DRIVEN); // the only mode IoTivity supports currently
2433
2434     OCSecurityPayload * secPayload = (OCSecurityPayload *) OICCalloc(1, sizeof(OCSecurityPayload));
2435     if (!secPayload)
2436     {
2437         OIC_LOG(ERROR, TAG, "Failed to allocate memory");
2438         res = OC_STACK_NO_MEMORY;
2439         goto error;
2440     }
2441     secPayload->base.type = PAYLOAD_TYPE_SECURITY;
2442
2443     if (OC_STACK_OK != PstatToCBORPayload(pstat, &(secPayload->securityData),
2444                 &(secPayload->payloadSize), true))
2445     {
2446         OCPayloadDestroy((OCPayload *) secPayload);
2447         OIC_LOG(ERROR, TAG, "Failed to PstatToCBORPayload");
2448         res = OC_STACK_NO_MEMORY;
2449         goto error;
2450     }
2451     OIC_LOG(DEBUG, TAG, "Created payload for pstat set");
2452     OIC_LOG_BUFFER(DEBUG, TAG, secPayload->securityData, secPayload->payloadSize);
2453
2454     char query[MAX_URI_LENGTH + MAX_QUERY_LENGTH] = {0};
2455     if (!PMGenerateQuery(true,
2456                 pTargetDev->endpoint.addr,
2457                 pTargetDev->securePort,
2458                 pTargetDev->connType,
2459                 query, sizeof(query), OIC_RSRC_PSTAT_URI))
2460     {
2461         OIC_LOG(ERROR, TAG, "SRPResetDevice : Failed to generate query");
2462         OCPayloadDestroy((OCPayload *) secPayload);
2463         res = OC_STACK_ERROR;
2464         goto error;
2465     }
2466     OIC_LOG_V(DEBUG, TAG, "Query=%s", query);
2467
2468     OCCallbackData cbData = { .context = NULL, .cb = NULL, .cd = NULL };
2469     OCMethod method = OC_REST_POST;
2470     OCDoHandle handle = NULL;
2471     OCProvisionDev_t * targetDev = PMCloneOCProvisionDev(pTargetDev);
2472     if (NULL == targetDev)
2473     {
2474         OIC_LOG(ERROR, TAG, "target dev is null");
2475         res = OC_STACK_ERROR;
2476         goto error;
2477     }
2478     cbData.cb = &SRPResetDeviceCB;
2479     cbData.context = (void *) targetDev;
2480     cbData.cd = deleteCallback;
2481     OIC_LOG(DEBUG, TAG, "Sending PSTAT info to resource server");
2482     res = OCDoResource(&handle, method, query,
2483             &targetDev->endpoint, (OCPayload *)secPayload,
2484             targetDev->connType, OC_LOW_QOS, &cbData, NULL, 0);\
2485     if (OC_STACK_OK != res)
2486     {
2487         OIC_LOG(ERROR, TAG, "OCStack resource error");
2488     }
2489
2490 error:
2491     OICFree(pstat->sm);
2492     OICFree(pstat);
2493     OIC_LOG(INFO, TAG, "OUT SRPResetDevice");
2494     return res;
2495 }
2496
2497 /**
2498  * Internal Function to store results in result array during GetCredResourceCB.
2499  */
2500 static void registerResultForGetCredResourceCB(GetSecData_t *GetSecData,
2501                                              OCStackResult stackresult)
2502 {
2503    OIC_LOG_V(INFO, TAG, "Inside registerResultForGetCredResourceCB "
2504            "GetSecData->numOfResults is %d\n", GetSecData->numOfResults);
2505    memcpy(GetSecData->resArr[(GetSecData->numOfResults)].deviceId.id,
2506           GetSecData->deviceInfo->doxm->deviceID.id, UUID_LENGTH);
2507    GetSecData->resArr[(GetSecData->numOfResults)].res = stackresult;
2508    ++(GetSecData->numOfResults);
2509 }
2510
2511 /**
2512  * Callback handler of SRPGetCredResource.
2513  *
2514  * @param[in] ctx             ctx value passed to callback from calling function.
2515  * @param[in] UNUSED          handle to an invocation
2516  * @param[in] clientResponse  Response from queries to remote servers.
2517  * @return  OC_STACK_DELETE_TRANSACTION to delete the transaction
2518  *          and  OC_STACK_KEEP_TRANSACTION to keep it.
2519  */
2520 static OCStackApplicationResult SRPGetCredResourceCB(void *ctx, OCDoHandle UNUSED,
2521                                                   OCClientResponse *clientResponse)
2522 {
2523     OIC_LOG_V(INFO, TAG, "Inside SRPGetCredResourceCB.");
2524     (void)UNUSED;
2525     VERIFY_NON_NULL_RET(TAG, ctx, ERROR, OC_STACK_DELETE_TRANSACTION);
2526     GetSecData_t *GetSecData = (GetSecData_t*)ctx;
2527     OCProvisionResultCB resultCallback = GetSecData->resultCallback;
2528
2529     if (clientResponse)
2530     {
2531         if(OC_STACK_OK == clientResponse->result)
2532         {
2533             uint8_t *payload = ((OCSecurityPayload*)clientResponse->payload)->securityData;
2534             size_t size = ((OCSecurityPayload*)clientResponse->payload)->payloadSize;
2535
2536             OIC_LOG_BUFFER(DEBUG, TAG, payload, size);
2537             (void)size;
2538             (void)payload;
2539
2540             registerResultForGetCredResourceCB(GetSecData, OC_STACK_OK);
2541             ((OCProvisionResultCB)(resultCallback))(GetSecData->ctx, GetSecData->numOfResults,
2542                                                     GetSecData->resArr,
2543                                                     false);
2544              OICFree(GetSecData->resArr);
2545              OICFree(GetSecData);
2546
2547             return OC_STACK_DELETE_TRANSACTION;
2548         }
2549     }
2550     registerResultForGetCredResourceCB(GetSecData, OC_STACK_OK);
2551     ((OCProvisionResultCB)(resultCallback))(GetSecData->ctx, GetSecData->numOfResults,
2552                                             GetSecData->resArr,
2553                                             false);
2554     OIC_LOG_V(ERROR, TAG, "SRPGetCredResourceCB received Null clientResponse");
2555     OICFree(GetSecData->resArr);
2556     OICFree(GetSecData);
2557
2558     return OC_STACK_DELETE_TRANSACTION;
2559 }
2560
2561
2562 OCStackResult SRPGetCredResource(void *ctx, const OCProvisionDev_t *selectedDeviceInfo,
2563         OCProvisionResultCB resultCallback)
2564 {
2565     VERIFY_NON_NULL_RET(TAG, selectedDeviceInfo, ERROR,  OC_STACK_INVALID_PARAM);
2566     VERIFY_NON_NULL_RET(TAG, resultCallback, ERROR,  OC_STACK_INVALID_CALLBACK);
2567
2568     char query[MAX_URI_LENGTH + MAX_QUERY_LENGTH] = {0};
2569     if(!PMGenerateQuery(true,
2570                         selectedDeviceInfo->endpoint.addr,
2571                         selectedDeviceInfo->securePort,
2572                         selectedDeviceInfo->connType,
2573                         query, sizeof(query), OIC_RSRC_CRED_URI))
2574     {
2575         OIC_LOG(ERROR, TAG, "SRPGetCredResource : Failed to generate query");
2576         return OC_STACK_ERROR;
2577     }
2578     OIC_LOG_V(DEBUG, TAG, "Query=%s", query);
2579
2580     OCCallbackData cbData =  {.context=NULL, .cb=NULL, .cd=NULL};
2581     cbData.cb = &SRPGetCredResourceCB;
2582     GetSecData_t* GetSecData = (GetSecData_t*)OICCalloc(1, sizeof(GetSecData_t));
2583     if (NULL == GetSecData)
2584     {
2585         OIC_LOG(ERROR, TAG, "Unable to allocate memory");
2586         return OC_STACK_NO_MEMORY;
2587     }
2588     GetSecData->deviceInfo = selectedDeviceInfo;
2589     GetSecData->resultCallback = resultCallback;
2590     GetSecData->numOfResults=0;
2591     GetSecData->ctx = ctx;
2592
2593     int noOfRiCalls = 1;
2594     GetSecData->resArr = (OCProvisionResult_t*)OICCalloc(noOfRiCalls, sizeof(OCProvisionResult_t));
2595     if (NULL == GetSecData->resArr)
2596     {
2597         OICFree(GetSecData);
2598         OIC_LOG(ERROR, TAG, "Unable to allocate memory");
2599         return OC_STACK_NO_MEMORY;
2600     }
2601     cbData.context = (void *)GetSecData;
2602     cbData.cd = NULL;
2603     OCMethod method = OC_REST_GET;
2604     OCDoHandle handle = NULL;
2605     OIC_LOG(DEBUG, TAG, "Sending Get Cred to  resource server");
2606     OCStackResult ret = OCDoResource(&handle, method, query, NULL, NULL,
2607             selectedDeviceInfo->connType, OC_HIGH_QOS, &cbData, NULL, 0);
2608     if (OC_STACK_OK != ret)
2609     {
2610         OIC_LOG(ERROR, TAG, "OCStack resource error");
2611         OICFree(GetSecData->resArr);
2612         OICFree(GetSecData);
2613     }
2614     VERIFY_SUCCESS_RET(TAG, (OC_STACK_OK == ret), ERROR, OC_STACK_ERROR);
2615     OIC_LOG(DEBUG, TAG, "OUT SRPGetCredResource");
2616
2617     return OC_STACK_OK;
2618 }
2619
2620 /**
2621  * Internal Function to store results in result array during GetACLResourceCB.
2622  */
2623 static void registerResultForGetACLResourceCB(GetSecData_t *GetSecData,
2624                                              OCStackResult stackresult)
2625 {
2626    OIC_LOG_V(INFO, TAG, "Inside registerResultForGetACLResourceCB "
2627            "GetSecData->numOfResults is %d\n", GetSecData->numOfResults);
2628    memcpy(GetSecData->resArr[(GetSecData->numOfResults)].deviceId.id,
2629           GetSecData->deviceInfo->doxm->deviceID.id, UUID_LENGTH);
2630    GetSecData->resArr[(GetSecData->numOfResults)].res = stackresult;
2631    ++(GetSecData->numOfResults);
2632 }
2633
2634 /**
2635  * Callback handler of SRPGetACLResource.
2636  *
2637  * @param[in] ctx             ctx value passed to callback from calling function.
2638  * @param[in] UNUSED          handle to an invocation
2639  * @param[in] clientResponse  Response from queries to remote servers.
2640  * @return  OC_STACK_DELETE_TRANSACTION to delete the transaction
2641  *          and  OC_STACK_KEEP_TRANSACTION to keep it.
2642  */
2643 static OCStackApplicationResult SRPGetACLResourceCB(void *ctx, OCDoHandle UNUSED,
2644                                                   OCClientResponse *clientResponse)
2645 {
2646     OIC_LOG_V(INFO, TAG, "Inside SRPGetACLResourceCB.");
2647     (void)UNUSED;
2648     VERIFY_NON_NULL_RET(TAG, ctx, ERROR, OC_STACK_DELETE_TRANSACTION);
2649     GetSecData_t *GetSecData = (GetSecData_t*)ctx;
2650     OCProvisionResultCB resultCallback = GetSecData->resultCallback;
2651
2652     if (clientResponse)
2653     {
2654         if(OC_STACK_OK == clientResponse->result)
2655         {
2656             uint8_t *payload = ((OCSecurityPayload*)clientResponse->payload)->securityData;
2657             size_t size = ((OCSecurityPayload*)clientResponse->payload)->payloadSize;
2658
2659             OIC_LOG_BUFFER(DEBUG, TAG, payload, size);
2660             (void)payload;
2661             (void)size;
2662
2663             registerResultForGetACLResourceCB(GetSecData, OC_STACK_OK);
2664             ((OCProvisionResultCB)(resultCallback))(GetSecData->ctx, GetSecData->numOfResults,
2665                                                     GetSecData->resArr,
2666                                                     false);
2667              OICFree(GetSecData->resArr);
2668              OICFree(GetSecData);
2669
2670             return OC_STACK_DELETE_TRANSACTION;
2671         }
2672     }
2673     registerResultForGetACLResourceCB(GetSecData, OC_STACK_OK);
2674     ((OCProvisionResultCB)(resultCallback))(GetSecData->ctx, GetSecData->numOfResults,
2675                                             GetSecData->resArr,
2676                                             false);
2677     OIC_LOG_V(ERROR, TAG, "SRPGetACLResourceCB received Null clientResponse");
2678     OICFree(GetSecData->resArr);
2679     OICFree(GetSecData);
2680
2681     return OC_STACK_DELETE_TRANSACTION;
2682 }
2683
2684
2685 OCStackResult SRPGetACLResource(void *ctx, const OCProvisionDev_t *selectedDeviceInfo,
2686         OCProvisionResultCB resultCallback)
2687 {
2688     VERIFY_NON_NULL_RET(TAG, selectedDeviceInfo, ERROR,  OC_STACK_INVALID_PARAM);
2689     VERIFY_NON_NULL_RET(TAG, resultCallback, ERROR,  OC_STACK_INVALID_CALLBACK);
2690
2691     char query[MAX_URI_LENGTH + MAX_QUERY_LENGTH] = {0};
2692     if(!PMGenerateQuery(true,
2693                         selectedDeviceInfo->endpoint.addr,
2694                         selectedDeviceInfo->securePort,
2695                         selectedDeviceInfo->connType,
2696                         query, sizeof(query), OIC_RSRC_ACL_URI))
2697     {
2698         OIC_LOG(ERROR, TAG, "SRPGetACLResource : Failed to generate query");
2699         return OC_STACK_ERROR;
2700     }
2701     OIC_LOG_V(DEBUG, TAG, "Query=%s", query);
2702
2703     OCCallbackData cbData =  {.context=NULL, .cb=NULL, .cd=NULL};
2704     cbData.cb = &SRPGetACLResourceCB;
2705     GetSecData_t* GetSecData = (GetSecData_t*)OICCalloc(1, sizeof(GetSecData_t));
2706     if (NULL == GetSecData)
2707     {
2708         OIC_LOG(ERROR, TAG, "Unable to allocate memory");
2709         return OC_STACK_NO_MEMORY;
2710     }
2711     GetSecData->deviceInfo = selectedDeviceInfo;
2712     GetSecData->resultCallback = resultCallback;
2713     GetSecData->numOfResults=0;
2714     GetSecData->ctx = ctx;
2715
2716     int noOfRiCalls = 1;
2717     GetSecData->resArr = (OCProvisionResult_t*)OICCalloc(noOfRiCalls, sizeof(OCProvisionResult_t));
2718     if (NULL == GetSecData->resArr)
2719     {
2720         OICFree(GetSecData);
2721         OIC_LOG(ERROR, TAG, "Unable to allocate memory");
2722         return OC_STACK_NO_MEMORY;
2723     }
2724     cbData.context = (void *)GetSecData;
2725     cbData.cd = NULL;
2726     OCMethod method = OC_REST_GET;
2727     OCDoHandle handle = NULL;
2728     OIC_LOG(DEBUG, TAG, "Sending Get ACL to resource server");
2729     OCStackResult ret = OCDoResource(&handle, method, query, NULL, NULL,
2730             selectedDeviceInfo->connType, OC_HIGH_QOS, &cbData, NULL, 0);
2731     if (OC_STACK_OK != ret)
2732     {
2733         OIC_LOG(ERROR, TAG, "OCStack resource error");
2734         OICFree(GetSecData->resArr);
2735         OICFree(GetSecData);
2736     }
2737     VERIFY_SUCCESS_RET(TAG, (OC_STACK_OK == ret), ERROR, OC_STACK_ERROR);
2738     OIC_LOG(DEBUG, TAG, "OUT SRPGetACLResource");
2739
2740     return OC_STACK_OK;
2741 }
2742
2743 OCStackResult SRPReadTrustCertChain(uint16_t credId, uint8_t **trustCertChain,
2744                                      size_t *chainSize)
2745 {
2746     OIC_LOG(DEBUG, TAG, "IN SRPReadTrustCertChain");
2747
2748     OCStackResult res = OC_STACK_ERROR;
2749     int secureFlag = 0;
2750     OicSecCred_t* credData = GetCredEntryByCredId(credId);
2751     if(credData)
2752     {
2753         res = CredToCBORPayload((const OicSecCred_t*) credData, trustCertChain,
2754                                 chainSize, secureFlag);
2755         if(OC_STACK_OK != res)
2756         {
2757             OIC_LOG(INFO, TAG, "CredToCBORPayload failed");
2758         }
2759     }
2760     DeleteCredList(credData);
2761     return res;
2762 }