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