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