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