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