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