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