[IOT-2359][IOT-2360][IOT-2364] Separate provisioning with DOS
[platform/upstream/iotivity.git] / resource / csdk / security / provisioning / src / secureresourceprovider.c
1 /* *****************************************************************
2  *
3  * Copyright 2015 Samsung Electronics All Rights Reserved.
4  *
5  *
6  *
7  * Licensed under the Apache License, Version 2.0 (the "License");
8  * you may not use this file except in compliance with the License.
9  * You may obtain a copy of the License at
10  *
11  *     http://www.apache.org/licenses/LICENSE-2.0
12  *
13  * Unless required by applicable law or agreed to in writing, software
14  * distributed under the License is distributed on an "AS IS" BASIS,
15  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16  * See the License for the specific language governing permissions and
17  * limitations under the License.
18  *
19  * *****************************************************************/
20 #include "iotivity_config.h"
21 #include <stdio.h>
22 #include <string.h>
23 #include <stdint.h>
24 #ifdef HAVE_UNISTD_H
25 #include <unistd.h>
26 #endif
27
28 #include "ocprovisioningmanager.h"
29 #include "secureresourceprovider.h"
30 #include "logger.h"
31 #include "oic_malloc.h"
32 #include "oic_string.h"
33 #include "aclresource.h"
34 #include "pstatresource.h"
35 #include "srmresourcestrings.h"
36 #include "credresource.h"
37 #include "csrresource.h"
38 #include "rolesresource.h"
39 #include "doxmresource.h"
40 #include "pconfresource.h"
41 #include "credentialgenerator.h"
42 #include "cainterface.h"
43 #include "oic_string.h"
44 #include "pmtypes.h"
45 #include "pmutility.h"
46 #include "srmutility.h"
47 #include "provisioningdatabasemanager.h"
48 #include "base64.h"
49 #include "utlist.h"
50 #include "ocpayload.h"
51 #include "srmutility.h"
52 #include "certhelpers.h"
53
54 #ifdef __WITH_DTLS__
55 #include "crlresource.h"
56 #endif
57
58 #define TAG "OIC_SRPAPI"
59
60 trustCertChainContext_t g_trustCertChainNotifier;
61
62 // Enum type index for data types.
63 typedef enum
64 {
65     CHAIN_TYPE = 0,                       /**< Certificate trust chain.**/
66     ACL_TYPE,                             /**< Access control list.**/
67     PSK_TYPE,                             /**< Pre-Shared Key.**/
68     CERT_TYPE                             /**< X.509 certificate.**/
69 } DataType_t;
70
71 /**
72  * Structure to carry general data to callback.
73  */
74 typedef struct Data
75 {
76     void *ctx;                                   /**< Pointer to user context.**/
77     DataType_t type;                             /**< Data type of the context.**/
78 } Data_t;
79
80 /**
81  * Structure to carry credential data to callback.
82  */
83 typedef struct CredentialData
84 {
85     void *ctx;                                  /**< Pointer to user context.**/
86     const OCProvisionDev_t *deviceInfo[2];      /**< Array of pointers to OCProvisionDev_t.**/
87     OicSecCred_t *credInfo[2];                  /**< Array of pointers to OicSecCred_t.**/
88     int currIndex;                              /**< Index of current remote device.**/
89     OCProvisionResultCB resultCallback;         /**< Pointer to result callback.**/
90     OCProvisionResult_t *resArr;                /**< Result array.**/
91     int numOfResults;                           /**< Number of results in result array.**/
92     OicSecCredType_t type;                      /**< Type of credentials to be provisioned to the device.**/
93     size_t keySize;                             /**< Size of key.**/
94     const char *pemCert;                        /**< Certificate (SIGNED_ASYMMETRIC_KEY) encoded as PEM.**/
95     const OicSecRole_t *role1;                  /**< Role of the deviceInfo[0].**/
96     const OicSecRole_t *role2;                  /**< Role of the deviceInfo[1].**/
97 } CredentialData_t;
98
99 /**
100  * Structure to carry ACL provision API data to callback.
101  */
102 typedef struct ACLData
103 {
104     void *ctx;                                   /**< Pointer to user context.**/
105     const OCProvisionDev_t *deviceInfo;          /**< Pointer to PMDevInfo_t.**/
106     OCProvisionResultCB resultCallback;         /**< Pointer to result callback.**/
107     OCProvisionResult_t *resArr;                 /**< Result array.**/
108     int numOfResults;                           /**< Number of results in result array.**/
109     OicSecAcl_t *acl;
110     OicSecAclVersion_t aclVersion;
111 } ACLData_t;
112
113 /**
114  * Structure to carry Trust Chain provision API data to callback.
115  */
116 typedef struct TrustChainData
117 {
118     void *ctx;                                  /**< Pointer to user context.**/
119     const OCProvisionDev_t *targetDev;          /**< Pointer to OCProvisionDev_t.**/
120     OCProvisionResultCB resultCallback;         /**< Pointer to result callback.**/
121     uint16_t credId;                            /**< Trust chain id to be provisioned.**/
122     OCProvisionResult_t *resArr;                /**< Result array.**/
123     int numOfResults;                           /**< Number of results in result array.**/
124 } TrustChainData_t;
125
126
127 // Structure to carry get security resource APIs data to callback.
128 typedef struct GetSecData GetSecData_t;
129 struct GetSecData {
130     void *ctx;
131     const OCProvisionDev_t *deviceInfo;         /**< Pointer to PMDevInfo_t.**/
132     OCProvisionResultCB resultCallback;         /**< Pointer to result callback.**/
133     OCProvisionResult_t *resArr;                /**< Result array.**/
134     int numOfResults;                        /**< Number of results in result array.**/
135 };
136
137 typedef struct GetCsrData GetCsrData_t;
138 struct GetCsrData {
139     void *ctx;
140     const OCProvisionDev_t *deviceInfo;         /**< Pointer to PMDevInfo_t.**/
141     OCGetCSRResultCB resultCallback;            /**< Pointer to result callback.**/
142     OCPMGetCsrResult_t *resArr;                 /**< Result array.**/
143     size_t numOfResults;                        /**< Number of results in result array.**/
144 };
145
146 typedef struct GetRolesData GetRolesData_t;
147 struct GetRolesData {
148     void *ctx;                                  /**< User-provided context **/
149     const OCProvisionDev_t *deviceInfo;         /**< Pointer to PMDevInfo_t.**/
150     OCGetRolesResultCB resultCallback;          /**< Pointer to result callback.**/
151     OCPMGetRolesResult_t *resArr;               /**< Result array.**/
152     size_t numOfResults;                        /**< Number of results in result array.**/
153 };
154
155 /**
156  * Structure to carry PCONF provision API data to callback.
157  */
158 typedef struct PconfData PconfData_t;
159 struct PconfData
160 {
161     void *ctx;                                  /**< Pointer to user context.**/
162     const OCProvisionDev_t *deviceInfo;         /**< Pointer to PMDevInfo_t.**/
163     OCProvisionResultCB resultCallback;         /**< Pointer to result callback.**/
164     OCProvisionResult_t *resArr;                /**< Result array.**/
165     int numOfResults;                           /**< Number of results in result array.**/
166 };
167
168 // Enum type index for unlink callback.
169 typedef enum {
170     IDX_FIRST_DEVICE_RES = 0, // index for resulf of the first device
171     IDX_SECOND_DEVICE_RES,    // index for result of the second device
172     IDX_DB_UPDATE_RES         // index for result of updating provisioning database.
173 } IdxUnlinkRes_t;
174
175 // Structure to carry unlink APIs data to callback.
176 typedef struct UnlinkData UnlinkData_t;
177 struct UnlinkData {
178     void *ctx;
179     OCProvisionDev_t* unlinkDev;             /**< Pointer to OCProvisionDev_t to be unlinked.**/
180     OCProvisionResult_t* unlinkRes;          /**< Result array.**/
181     OCProvisionResultCB resultCallback;      /**< Pointer to result callback.**/
182     int numOfResults;                        /**< Number of results in result array.**/
183 };
184
185 //Example of DELETE cred request -> coaps://0.0.0.0:5684/oic/sec/cred?sub=(BASE64 ENCODED UUID)
186 const char * SRP_FORM_DELETE_CREDENTIAL = "coaps://[%s]:%d%s?%s=%s";
187 const char * SRP_FORM_DELETE_CREDENTIAL_TCP = "coaps+tcp://[%s]:%d%s?%s=%s";
188
189 // Structure to carry remove APIs data to callback.
190 typedef struct RemoveData RemoveData_t;
191 struct RemoveData {
192     void *ctx;
193     OCProvisionDev_t* revokeTargetDev;      /**< Device which is going to be revoked..**/
194     OCProvisionDev_t* linkedDevList;        /**< A list of devices which have invalid credential.**/
195     OCProvisionResult_t* removeRes;         /**< Result array.**/
196     OCProvisionResultCB resultCallback;     /**< Pointer to result callback.**/
197     size_t numOfResults;                    /**< Number of results in result array.**/
198     size_t sizeOfResArray;
199     bool hasError;
200 };
201
202 /**
203  * Function prototypes
204  */
205 static OCStackResult ProvisionCredentialsDos(void *ctx, OicSecCred_t *cred,
206         const OCProvisionDev_t *deviceInfo, OCClientResponseHandler responseHandler);
207 static OCStackResult provisionCredentials(OicSecCred_t *cred,
208         const OCProvisionDev_t *deviceInfo, CredentialData_t *credData,
209         OCClientResponseHandler responseHandler);
210 static OCStackApplicationResult  ProvisionPskCB(void *ctx, OCDoHandle UNUSED,
211         OCClientResponse *clientResponse);
212 static OCStackResult SetDOS(const Data_t *data, OicSecDeviceOnboardingState_t dos,
213                             OCClientResponseHandler resultCallback);
214
215 typedef enum {
216     DEVICE_1_FINISHED,
217     DEVICE_2_FINISHED,
218     DEVICE_LOCAL_FINISHED
219 } CredProvisioningResultCause_t;
220
221 /**
222  * Deallocates a block of memory.
223  *
224  * @param[in] data    Pointer to block of memory previously allocated for Data_t.
225  */
226 static void FreeData(Data_t *data)
227 {
228     switch (data->type)
229     {
230         case CHAIN_TYPE:
231             {
232                 TrustChainData_t *chainData = (TrustChainData_t *) data->ctx;
233                 OICFree(chainData->resArr);
234                 OICFree(chainData);
235                 break;
236             }
237         case ACL_TYPE:
238             {
239                 ACLData_t *aclData = (ACLData_t *) data->ctx;
240                 OICFree(aclData->resArr);
241                 OICFree(aclData);
242                 break;
243             }
244         case PSK_TYPE:
245             {
246                 CredentialData_t *pskData = (CredentialData_t *) data->ctx;
247                 OICFree(pskData->resArr);
248                 OICFree(pskData);
249                 break;
250             }
251         default:
252             {
253                 OIC_LOG_V(INFO, TAG, "Unknown type %d", data->type);
254             }
255     }
256     OICFree(data);
257 }
258
259 /**
260  * Internal function to update result in result array.
261  */
262 static void registerResultForCredProvisioning(CredentialData_t *credData,
263                                               OCStackResult stackresult, CredProvisioningResultCause_t cause)
264 {
265    OCStackResult res = OC_STACK_ERROR;
266    OIC_LOG_V(INFO,TAG,"value of credData->numOfResults is %d",credData->numOfResults);
267    switch (cause)
268    {
269    case DEVICE_1_FINISHED:
270        memcpy(credData->resArr[(credData->numOfResults)].deviceId.id,
271               credData->deviceInfo[0]->doxm->deviceID.id,UUID_LENGTH);
272        break;
273    case DEVICE_2_FINISHED:
274        memcpy(credData->resArr[(credData->numOfResults)].deviceId.id,
275               credData->deviceInfo[1]->doxm->deviceID.id,UUID_LENGTH);
276        break;
277    case DEVICE_LOCAL_FINISHED:
278        res = GetDoxmDeviceID(&credData->resArr[(credData->numOfResults)].deviceId);
279        if (OC_STACK_OK != res)
280        {
281            OIC_LOG_V(WARNING, TAG, "%s: Could not retrieve own device ID to populate result for cred provisioning: %d", __func__, res);
282            memset(credData->resArr[(credData->numOfResults)].deviceId.id, 0, UUID_LENGTH);
283        }
284        break;
285    default:
286        assert(!"Unknown value for cause");
287        OIC_LOG_V(ERROR, TAG, "%s: unknown value of cause: %d", __func__, cause);
288        memset(credData->resArr[(credData->numOfResults)].deviceId.id, 0, UUID_LENGTH);
289        break;
290    }
291    credData->resArr[(credData->numOfResults)].res = stackresult;
292    ++(credData->numOfResults);
293 }
294
295 /**
296  * Callback handler for handling callback of provisioning device 2.
297  *
298  * @param[in] ctx             ctx value passed to callback from calling function.
299  * @param[in] UNUSED          handle to an invocation
300  * @param[in] clientResponse  Response from queries to remote servers.
301  * @return  OC_STACK_DELETE_TRANSACTION to delete the transaction
302  *          and  OC_STACK_KEEP_TRANSACTION to keep it.
303  */
304 static OCStackApplicationResult provisionCredentialCB2(void *ctx, OCDoHandle UNUSED,
305                                                        OCClientResponse *clientResponse)
306 {
307     VERIFY_NOT_NULL_RETURN(TAG, ctx, ERROR, OC_STACK_DELETE_TRANSACTION);
308     CredentialData_t *credData = (CredentialData_t *) ctx;
309     (void)UNUSED;
310
311     OCProvisionResultCB resultCallback = credData->resultCallback;
312     OIC_LOG(INFO, TAG, "provisionCredentialCB2 called");
313     if (clientResponse)
314     {
315         if(OC_STACK_RESOURCE_CHANGED == clientResponse->result)
316         {
317             registerResultForCredProvisioning(credData, OC_STACK_RESOURCE_CHANGED, DEVICE_2_FINISHED);
318             OCStackResult res =  PDMLinkDevices(&credData->deviceInfo[0]->doxm->deviceID,
319                     &credData->deviceInfo[1]->doxm->deviceID);
320             if (OC_STACK_OK != res)
321             {
322                 OIC_LOG(ERROR, TAG, "Error occured on PDMLinkDevices");
323                 return OC_STACK_DELETE_TRANSACTION;
324             }
325             OIC_LOG(INFO, TAG, "Link created successfully");
326
327             ((OCProvisionResultCB)(resultCallback))(credData->ctx, credData->numOfResults,
328                                                     credData->resArr,
329                                                     false);
330              OICFree(credData->resArr);
331              OICFree(credData);
332              return OC_STACK_DELETE_TRANSACTION;
333         }
334
335     }
336     OIC_LOG(INFO, TAG, "provisionCredentialCB2 received Null clientResponse");
337     registerResultForCredProvisioning(credData, OC_STACK_ERROR, DEVICE_2_FINISHED);
338     ((OCProvisionResultCB)(resultCallback))(credData->ctx, credData->numOfResults,
339                                             credData->resArr,
340                                             true);
341     OICFree(credData->resArr);
342     OICFree(credData);
343     return OC_STACK_DELETE_TRANSACTION;
344 }
345
346 /**
347  * Callback handler for handling callback of provisioning device 1.
348  *
349  * @param[in] ctx             ctx value passed to callback from calling function.
350  * @param[in] UNUSED          handle to an invocation
351  * @param[in] clientResponse  Response from queries to remote servers.
352  * @return  OC_STACK_DELETE_TRANSACTION to delete the transaction
353  *          and  OC_STACK_KEEP_TRANSACTION to keep it.
354  */
355 static OCStackApplicationResult provisionCredentialCB1(void *ctx, OCDoHandle UNUSED,
356                                                        OCClientResponse *clientResponse)
357 {
358     VERIFY_NOT_NULL_RETURN(TAG, ctx, ERROR, OC_STACK_DELETE_TRANSACTION);
359     (void)UNUSED;
360     CredentialData_t* credData = (CredentialData_t*) ctx;
361     OICFree(credData->credInfo[0]);
362     const OCProvisionDev_t *deviceInfo = credData->deviceInfo[1];
363     OicSecCred_t *credInfo = credData->credInfo[1];
364     const OCProvisionResultCB resultCallback = credData->resultCallback;
365     if (clientResponse)
366     {
367         if (OC_STACK_RESOURCE_CHANGED == clientResponse->result)
368         {
369             // send credentials to second device
370             registerResultForCredProvisioning(credData, OC_STACK_RESOURCE_CHANGED, DEVICE_1_FINISHED);
371             OCStackResult res = provisionCredentials(credInfo, deviceInfo, credData,
372                     provisionCredentialCB2);
373             // If deviceInfo is NULL, this device is the second device. Don't delete the cred
374             // because provisionCredentials added it to the local cred store and it now owns
375             // the memory.
376             if ((NULL != deviceInfo) || (OC_STACK_OK != res))
377             {
378                 DeleteCredList(credInfo);
379             }
380             if (OC_STACK_OK != res)
381             {
382                 registerResultForCredProvisioning(credData, res,2);
383                 ((OCProvisionResultCB)(resultCallback))(credData->ctx, credData->numOfResults,
384                                                         credData->resArr,
385                                                         true);
386                 OICFree(credData->resArr);
387                 OICFree(credData);
388                 credData = NULL;
389             }
390         }
391         else
392         {
393             registerResultForCredProvisioning(credData, OC_STACK_ERROR, DEVICE_1_FINISHED);
394             ((OCProvisionResultCB)(resultCallback))(credData->ctx, credData->numOfResults,
395                                                     credData->resArr,
396                                                     true);
397             OICFree(credData->resArr);
398             OICFree(credData);
399             credData = NULL;
400         }
401     }
402     else
403     {
404         OIC_LOG(INFO, TAG, "provisionCredentialCB received Null clientResponse for first device");
405         registerResultForCredProvisioning(credData, OC_STACK_ERROR, DEVICE_1_FINISHED);
406        ((OCProvisionResultCB)(resultCallback))(credData->ctx, credData->numOfResults,
407                                                      credData->resArr,
408                                                      true);
409         DeleteCredList(credInfo);
410         OICFree(credData->resArr);
411         OICFree(credData);
412         credData = NULL;
413     }
414     return OC_STACK_DELETE_TRANSACTION;
415 }
416
417 /**
418  * Callback handler for handling callback of provisioning device 2.
419  *
420  * @param[in] ctx             ctx value passed to callback from calling function.
421  * @param[in] UNUSED          handle to an invocation
422  * @param[in] clientResponse  Response from queries to remote servers.
423  * @return  OC_STACK_DELETE_TRANSACTION to delete the transaction
424  *          and  OC_STACK_KEEP_TRANSACTION to keep it.
425  */
426 static OCStackApplicationResult ProvisionCredentialDosCB2(void *ctx, OCDoHandle UNUSED,
427                                                        OCClientResponse *clientResponse)
428 {
429     VERIFY_NOT_NULL_RETURN(TAG, ctx, ERROR, OC_STACK_DELETE_TRANSACTION);
430     CredentialData_t *credData = (CredentialData_t *) ((Data_t *) ctx)->ctx;
431     (void)UNUSED;
432
433     OCProvisionResultCB resultCallback = credData->resultCallback;
434     OIC_LOG_V(DEBUG, TAG, "IN %s", __func__);
435     if (clientResponse)
436     {
437         if (OC_STACK_RESOURCE_CHANGED == clientResponse->result)
438         {
439             registerResultForCredProvisioning(credData, OC_STACK_RESOURCE_CHANGED, DEVICE_2_FINISHED);
440             OCStackResult res =  PDMLinkDevices(&credData->deviceInfo[0]->doxm->deviceID,
441                                                 &credData->deviceInfo[1]->doxm->deviceID);
442             if (OC_STACK_OK != res)
443             {
444                 OIC_LOG(ERROR, TAG, "Error occured on PDMLinkDevices");
445                 return OC_STACK_DELETE_TRANSACTION;
446             }
447             OIC_LOG(INFO, TAG, "Link created successfully");
448
449             ((OCProvisionResultCB)(resultCallback))(credData->ctx, credData->numOfResults,
450                                                     credData->resArr,
451                                                     false);
452             FreeData(ctx);
453             return OC_STACK_DELETE_TRANSACTION;
454         }
455
456     }
457     OIC_LOG(INFO, TAG, "ProvisionCredentialDosCB2 received Null clientResponse");
458     registerResultForCredProvisioning(credData, OC_STACK_ERROR, DEVICE_2_FINISHED);
459     ((OCProvisionResultCB)(resultCallback))(credData->ctx, credData->numOfResults,
460                                             credData->resArr,
461                                             true);
462     FreeData(ctx);
463     OIC_LOG_V(DEBUG, TAG, "OUT %s", __func__);
464     return OC_STACK_DELETE_TRANSACTION;
465 }
466
467 /**
468  * Callback handler for handling callback of provisioning device 1.
469  *
470  * @param[in] ctx             ctx value passed to callback from calling function.
471  * @param[in] UNUSED          handle to an invocation
472  * @param[in] clientResponse  Response from queries to remote servers.
473  * @return  OC_STACK_DELETE_TRANSACTION to delete the transaction
474  *          and  OC_STACK_KEEP_TRANSACTION to keep it.
475  */
476 static OCStackApplicationResult ProvisionCredentialDosCB1(void *ctx, OCDoHandle UNUSED,
477         OCClientResponse *clientResponse)
478 {
479     OIC_LOG_V(DEBUG, TAG, "IN %s", __func__);
480     VERIFY_NOT_NULL_RETURN(TAG, ctx, ERROR, OC_STACK_DELETE_TRANSACTION);
481     (void) UNUSED;
482     CredentialData_t *credData = (CredentialData_t *) ((Data_t *) ctx)->ctx;
483     const OCProvisionResultCB resultCallback = credData->resultCallback;
484     if (clientResponse)
485     {
486         if (OC_STACK_RESOURCE_CHANGED == clientResponse->result)
487         {
488             // send credentials to second device
489             registerResultForCredProvisioning(credData, OC_STACK_RESOURCE_CHANGED, DEVICE_1_FINISHED);
490             OCStackResult res = SetDOS((Data_t *) ctx, DOS_RFPRO, ProvisionPskCB);
491             // If deviceInfo is NULL, this device is the second device. Don't delete the cred
492             // because provisionCredentials added it to the local cred store and it now owns
493             // the memory.
494             if (OC_STACK_OK != res)
495             {
496                 registerResultForCredProvisioning(credData, res, 2);
497                 ((OCProvisionResultCB)(resultCallback))(credData->ctx, credData->numOfResults,
498                                                         credData->resArr,
499                                                         true);
500                 FreeData(ctx);
501             }
502         }
503         else
504         {
505             registerResultForCredProvisioning(credData, OC_STACK_ERROR, DEVICE_1_FINISHED);
506             ((OCProvisionResultCB)(resultCallback))(credData->ctx, credData->numOfResults,
507                                                     credData->resArr,
508                                                     true);
509             FreeData(ctx);
510         }
511     }
512     else
513     {
514         OIC_LOG(INFO, TAG, "provisionCredentialCB received Null clientResponse for first device");
515         registerResultForCredProvisioning(credData, OC_STACK_ERROR, DEVICE_1_FINISHED);
516         ((OCProvisionResultCB)(resultCallback))(credData->ctx, credData->numOfResults,
517                                                 credData->resArr,
518                                                 true);
519         FreeData(ctx);
520     }
521     OIC_LOG_V(DEBUG, TAG, "OUT %s", __func__);
522     return OC_STACK_DELETE_TRANSACTION;
523 }
524 /**
525  * Internal function for handling credential generation and sending credential to resource server.
526  *
527  * @param[in] cred Instance of cred resource.
528  * @param[in] deviceInfo information about device to which credential is to be provisioned.
529  * @param[in] responseHandler callbak called by OC stack when request API receives response.
530  * @return  OC_STACK_OK in case of success and other value otherwise.
531  */
532 static OCStackResult provisionCredentials(OicSecCred_t *cred,
533         const OCProvisionDev_t *deviceInfo, CredentialData_t *credData,
534         OCClientResponseHandler responseHandler)
535 {
536     OCStackResult res = OC_STACK_OK;
537
538     if (NULL != deviceInfo)
539     {
540         OCSecurityPayload* secPayload = (OCSecurityPayload*)OICCalloc(1, sizeof(OCSecurityPayload));
541         if (!secPayload)
542         {
543             OIC_LOG(ERROR, TAG, "Failed to allocate memory");
544             return OC_STACK_NO_MEMORY;
545         }
546         secPayload->base.type = PAYLOAD_TYPE_SECURITY;
547         int secureFlag = 0;
548         res = CredToCBORPayload(cred, &secPayload->securityData, &secPayload->payloadSize, secureFlag);
549         if ((OC_STACK_OK != res) && (NULL == secPayload->securityData))
550         {
551             OCPayloadDestroy((OCPayload *)secPayload);
552             OIC_LOG(ERROR, TAG, "Failed to CredToCBORPayload");
553             return OC_STACK_NO_MEMORY;
554         }
555
556         OIC_LOG(DEBUG, TAG, "Created payload for Cred:");
557         OIC_LOG_BUFFER(DEBUG, TAG, secPayload->securityData, secPayload->payloadSize);
558         char query[MAX_URI_LENGTH + MAX_QUERY_LENGTH] = { 0 };
559         if (!PMGenerateQuery(true,
560             deviceInfo->endpoint.addr,
561             deviceInfo->securePort,
562             deviceInfo->connType,
563             query, sizeof(query), OIC_RSRC_CRED_URI))
564         {
565             OIC_LOG(ERROR, TAG, "DeviceDiscoveryHandler : Failed to generate query");
566             OCPayloadDestroy((OCPayload *)secPayload);
567             return OC_STACK_ERROR;
568         }
569         OIC_LOG_V(DEBUG, TAG, "Query=%s", query);
570
571         OCCallbackData cbData;
572         memset(&cbData, 0, sizeof(cbData));
573         cbData.cb = responseHandler;
574         cbData.context = (void *)credData;
575         cbData.cd = NULL;
576
577         OCDoHandle handle = NULL;
578         OCMethod method = OC_REST_POST;
579         res = OCDoResource(&handle, method, query, 0, (OCPayload*)secPayload,
580             deviceInfo->connType, OC_HIGH_QOS, &cbData, NULL, 0);
581         OIC_LOG_V(INFO, TAG, "OCDoResource::Credential provisioning returned : %d", res);
582         if (res != OC_STACK_OK)
583         {
584             OIC_LOG(ERROR, TAG, "OCStack resource error");
585             return res;
586         }
587         return OC_STACK_OK;
588     }
589     else
590     {
591         /* Provision this credential to the local cred store. On success, the cred resource takes
592          * ownership of the memory. On failure, provisionCredentialCB1 will delete the cred object.
593          */
594         res = AddCredential(cred);
595         /* Call the result callback directly. */
596         registerResultForCredProvisioning(credData, OC_STACK_RESOURCE_CHANGED, DEVICE_LOCAL_FINISHED);
597         (credData->resultCallback)(credData->ctx, credData->numOfResults, credData->resArr, false);
598         return res;
599     }
600 }
601 /**
602  * Internal function for handling credential generation and sending credential to resource server.
603  *
604  * @param[in] cred Instance of cred resource.
605  * @param[in] deviceInfo information about device to which credential is to be provisioned.
606  * @param[in] responseHandler callbak called by OC stack when request API receives response.
607  * @return  OC_STACK_OK in case of success and other value otherwise.
608  */
609 static OCStackResult ProvisionCredentialsDos(void *ctx, OicSecCred_t *cred,
610         const OCProvisionDev_t *deviceInfo, OCClientResponseHandler responseHandler)
611 {
612     OCStackResult res = OC_STACK_OK;
613     CredentialData_t *credData = (CredentialData_t *) ((Data_t *) ctx)->ctx;
614
615     if (NULL != deviceInfo)
616     {
617         OCSecurityPayload *secPayload = (OCSecurityPayload *)OICCalloc(1, sizeof(OCSecurityPayload));
618         if (!secPayload)
619         {
620             OIC_LOG(ERROR, TAG, "Failed to allocate memory");
621             return OC_STACK_NO_MEMORY;
622         }
623         secPayload->base.type = PAYLOAD_TYPE_SECURITY;
624         int secureFlag = 0;
625         res = CredToCBORPayload(cred, &secPayload->securityData, &secPayload->payloadSize, secureFlag);
626         if ((OC_STACK_OK != res) && (NULL == secPayload->securityData))
627         {
628             OCPayloadDestroy((OCPayload *)secPayload);
629             OIC_LOG(ERROR, TAG, "Failed to CredToCBORPayload");
630             return OC_STACK_NO_MEMORY;
631         }
632
633         OIC_LOG(DEBUG, TAG, "Created payload for Cred:");
634         OIC_LOG_BUFFER(DEBUG, TAG, secPayload->securityData, secPayload->payloadSize);
635         char query[MAX_URI_LENGTH + MAX_QUERY_LENGTH] = { 0 };
636         if (!PMGenerateQuery(true,
637                              deviceInfo->endpoint.addr,
638                              deviceInfo->securePort,
639                              deviceInfo->connType,
640                              query, sizeof(query), OIC_RSRC_CRED_URI))
641         {
642             OIC_LOG(ERROR, TAG, "DeviceDiscoveryHandler : Failed to generate query");
643             OCPayloadDestroy((OCPayload *)secPayload);
644             return OC_STACK_ERROR;
645         }
646         OIC_LOG_V(DEBUG, TAG, "Query=%s", query);
647
648         OCCallbackData cbData = { .context = NULL, .cb = NULL, .cd = NULL };
649         cbData.cb = responseHandler;
650         cbData.context = ctx;
651         cbData.cd = NULL;
652
653         OCDoHandle handle = NULL;
654         OCMethod method = OC_REST_POST;
655         res = OCDoResource(&handle, method, query, 0, (OCPayload *)secPayload,
656                            deviceInfo->connType, OC_HIGH_QOS, &cbData, NULL, 0);
657         OIC_LOG_V(INFO, TAG, "OCDoResource::Credential provisioning returned : %d", res);
658         if (res != OC_STACK_OK)
659         {
660             OIC_LOG(ERROR, TAG, "OCStack resource error");
661             return res;
662         }
663         return OC_STACK_OK;
664     }
665     else
666     {
667         /* Provision this credential to the local cred store. On success, the cred resource takes
668          * ownership of the memory. On failure, ProvisionCredentialDosCB1 will delete the cred object.
669          */
670         res = AddCredential(cred);
671         /* Call the result callback directly. */
672         registerResultForCredProvisioning(credData, OC_STACK_RESOURCE_CHANGED, DEVICE_LOCAL_FINISHED);
673         (credData->resultCallback)(credData->ctx, credData->numOfResults, credData->resArr, false);
674         return res;
675     }
676 }
677
678 /**
679  * Updates result in result array of the target device.
680  */
681 static void RegisterProvResult(const OCProvisionDev_t *targetDev, OCProvisionResult_t *resArr,
682                                int *numOfResults, OCStackResult stackResult);
683 /**
684  * Callback handler for handling callback of posting DOS_RFNOP.
685  *
686  * @param[in] ctx             ctx value passed to callback from calling function.
687  * @param[in] UNUSED          handle to an invocation
688  * @param[in] clientResponse  Response from queries to remote servers.
689  * @return  OC_STACK_DELETE_TRANSACTION to delete the transaction
690  *          and  OC_STACK_KEEP_TRANSACTION to keep it.
691  */
692 static OCStackApplicationResult SetReadyForNormalOperationCB(void *ctx, OCDoHandle handler,
693         OCClientResponse *clientResponse)
694 {
695     OIC_LOG_V(DEBUG, TAG, "IN %s", __func__);
696     VERIFY_NOT_NULL_RETURN(TAG, ctx, ERROR, OC_STACK_DELETE_TRANSACTION);
697     DataType_t dataType = ((Data_t *) ctx)->type;
698
699     OCProvisionResultCB resultCallback = NULL;
700     const OCProvisionDev_t *targetDev = NULL;
701     OCProvisionResult_t *resArr = NULL;
702     int *numOfResults = NULL;
703
704     void *dataCtx = NULL;
705     OIC_LOG_V(DEBUG, TAG, "Data type %d", dataType);
706
707     switch (dataType)
708     {
709         case CHAIN_TYPE:
710         {
711             TrustChainData_t *chainData = (TrustChainData_t *) ((Data_t *) ctx)->ctx;
712             resultCallback = chainData->resultCallback;
713             targetDev = chainData->targetDev;
714             resArr = chainData->resArr;
715             numOfResults = &(chainData->numOfResults);
716             dataCtx = chainData->ctx;
717             break;
718         }
719         case ACL_TYPE:
720         {
721             ACLData_t *aclData = (ACLData_t *) ((Data_t *) ctx)->ctx;
722             resultCallback = aclData->resultCallback;
723             targetDev = aclData->deviceInfo;
724             resArr = aclData->resArr;
725             numOfResults = &(aclData->numOfResults);
726             dataCtx = aclData->ctx;
727             break;
728         }
729         case PSK_TYPE:
730         {
731             CredentialData_t *pskData = (CredentialData_t *) ((Data_t *) ctx)->ctx;
732             resArr = pskData->resArr;
733             numOfResults = &(pskData->numOfResults);
734             dataCtx = pskData->ctx;
735             OIC_LOG_V(DEBUG, TAG, "PSK index %d", pskData->currIndex);
736             break;
737         }
738         case CERT_TYPE:
739         {
740             OIC_LOG_V(ERROR, TAG, "Not implemented type %d", dataType);
741             OIC_LOG_V(ERROR, TAG, "OUT %s", __func__);
742             return OC_STACK_DELETE_TRANSACTION;
743         }
744         default:
745         {
746             OIC_LOG_V(ERROR, TAG, "Unknown type %d", dataType);
747             OIC_LOG_V(ERROR, TAG, "OUT %s", __func__);
748             return OC_STACK_DELETE_TRANSACTION;
749         }
750     }
751
752     if (dataType != PSK_TYPE)
753     {
754         RegisterProvResult(targetDev, resArr, numOfResults, clientResponse->result);
755         resultCallback(dataCtx, *numOfResults, resArr, clientResponse->result != OC_STACK_RESOURCE_CHANGED);
756         FreeData(ctx);
757     }
758     else
759     {
760         CredentialData_t *pskData = (CredentialData_t *) ((Data_t *) ctx)->ctx;
761         if (pskData->currIndex == 0)
762         {
763             pskData->currIndex = 1;
764             ProvisionCredentialDosCB1(ctx, handler, clientResponse);
765         }
766         else
767         {
768             ProvisionCredentialDosCB2(ctx, handler, clientResponse);
769         }
770     }
771
772     OIC_LOG_V(DEBUG, TAG, "OUT %s", __func__);
773     return OC_STACK_DELETE_TRANSACTION;
774 }
775
776 /**
777  * Updates pstat resource of server.
778  */
779 static OCStackResult SetDOS(const Data_t *data, OicSecDeviceOnboardingState_t dos,
780                             OCClientResponseHandler resultCallback)
781 {
782     OIC_LOG_V(DEBUG, TAG, "IN %s", __func__);
783     if (NULL == data || NULL == resultCallback)
784     {
785         OIC_LOG(ERROR, TAG, "NULL parameters");
786         OIC_LOG_V(ERROR, TAG, "OUT %s", __func__);
787         return OC_STACK_INVALID_PARAM;
788     }
789
790
791     const OCProvisionDev_t *pTargetDev = NULL;
792
793     switch (data->type)
794     {
795         case CHAIN_TYPE:
796         {
797             pTargetDev = ((TrustChainData_t *)data->ctx)->targetDev;
798             break;
799         }
800         case ACL_TYPE:
801         {
802             pTargetDev = ((ACLData_t *)data->ctx)->deviceInfo;
803             break;
804         }
805         case PSK_TYPE:
806         {
807             CredentialData_t *credData = ((CredentialData_t *)data)->ctx;
808             pTargetDev = credData->deviceInfo[credData->currIndex];
809             break;
810         }
811         case CERT_TYPE:
812         {
813             // TODO check cert provision flow
814             OIC_LOG_V(ERROR, TAG, "Not implemented type: %d", data->type);
815             return OC_STACK_INVALID_PARAM;
816         }
817         default:
818         {
819             OIC_LOG_V(ERROR, TAG, "Unknown type: %d", data->type);
820             return OC_STACK_INVALID_PARAM;
821         }
822     }
823
824     OCStackResult res = OC_STACK_ERROR;
825     OicSecPstat_t *pstat = (OicSecPstat_t *) OICCalloc(1, sizeof(OicSecPstat_t));
826     if (!pstat)
827     {
828         OIC_LOG(ERROR, TAG, "Failed to allocate memory");
829         return OC_STACK_NO_MEMORY;
830     }
831
832     pstat->dos.state = dos;
833
834     OCSecurityPayload *secPayload = (OCSecurityPayload *) OICCalloc(1, sizeof(OCSecurityPayload));
835     if (!secPayload)
836     {
837         OIC_LOG(ERROR, TAG, "Failed to allocate memory");
838         res = OC_STACK_NO_MEMORY;
839         goto error;
840     }
841     secPayload->base.type = PAYLOAD_TYPE_SECURITY;
842
843     // Note [IOT-2052] all the POST payloads in the provisioningclient app
844     // should be updated to use the Partial payload APIs for the SVRs, so they
845     // do not include read-only Properties for the Server device current
846     // state.
847     bool propertiesToInclude[PSTAT_PROPERTY_COUNT] = {false};
848     propertiesToInclude[PSTAT_DOS] = true;
849
850     if (OC_STACK_OK != PstatToCBORPayloadPartial(pstat, &(secPayload->securityData),
851             &(secPayload->payloadSize), propertiesToInclude))
852     {
853         OCPayloadDestroy((OCPayload *) secPayload);
854         OIC_LOG(ERROR, TAG, "Failed to PstatToCBORPayload");
855         res = OC_STACK_NO_MEMORY;
856         goto error;
857     }
858     OIC_LOG(DEBUG, TAG, "Created payload for pstat set");
859     OIC_LOG_BUFFER(DEBUG, TAG, secPayload->securityData, secPayload->payloadSize);
860
861     char query[MAX_URI_LENGTH + MAX_QUERY_LENGTH] = {0};
862     if (!PMGenerateQuery(true,
863                          pTargetDev->endpoint.addr,
864                          pTargetDev->securePort,
865                          pTargetDev->connType,
866                          query, sizeof(query), OIC_RSRC_PSTAT_URI))
867     {
868         OIC_LOG(ERROR, TAG, "Failed to generate query");
869         OCPayloadDestroy((OCPayload *) secPayload);
870         res = OC_STACK_ERROR;
871         goto error;
872     }
873     OIC_LOG_V(DEBUG, TAG, "Query=%s", query);
874
875     OCCallbackData cbData = { .context = NULL, .cb = NULL, .cd = NULL };
876     OCMethod method = OC_REST_POST;
877     OCDoHandle handle = NULL;
878     OCProvisionDev_t *targetDev = NULL;
879
880     targetDev = PMCloneOCProvisionDev(pTargetDev);
881
882     if (NULL == targetDev)
883     {
884         OIC_LOG(ERROR, TAG, "target dev is null");
885         res = OC_STACK_ERROR;
886         goto error;
887     }
888     cbData.cb = resultCallback;
889     cbData.context = (void *) data;
890     cbData.cd = NULL;
891     OIC_LOG(DEBUG, TAG, "Sending PSTAT info to resource server");
892     res = OCDoResource(&handle, method, query,
893                        &targetDev->endpoint, (OCPayload *)secPayload,
894                        targetDev->connType, OC_HIGH_QOS, &cbData, NULL, 0);
895     if (OC_STACK_OK != res)
896     {
897         OIC_LOG(ERROR, TAG, "OCStack resource error");
898     }
899
900 error:
901     OICFree(pstat);
902     OIC_LOG_V(DEBUG, TAG, "OUT %s", __func__);
903     return res;
904 }
905
906 /**
907  * Restores pstat after provisioning.
908  */
909 static OCStackApplicationResult ProvisionCB(void *ctx, OCDoHandle UNUSED,
910         OCClientResponse *clientResponse)
911 {
912     OIC_LOG_V(DEBUG, TAG, "IN %s", __func__);
913     VERIFY_NOT_NULL_RETURN(TAG, ctx, ERROR, OC_STACK_DELETE_TRANSACTION);
914     (void) UNUSED;
915     if (clientResponse && OC_STACK_RESOURCE_CHANGED != clientResponse->result)
916     {
917         OIC_LOG_V(ERROR, TAG, "Responce result: %d", clientResponse->result);
918     }
919     if (OC_STACK_OK != SetDOS(ctx, DOS_RFNOP, SetReadyForNormalOperationCB))
920     {
921         OIC_LOG_V(ERROR, TAG, "OUT %s", __func__);
922         return OC_STACK_DELETE_TRANSACTION;
923     }
924
925     OIC_LOG_V(DEBUG, TAG, "OUT %s", __func__);
926     return OC_STACK_DELETE_TRANSACTION;
927 }
928 /**
929  * Callback for PSK provisioning.
930  */
931 static OCStackApplicationResult  ProvisionPskCB(void *ctx, OCDoHandle UNUSED,
932                                                 OCClientResponse *clientResponse)
933 {
934     VERIFY_NOT_NULL_RETURN(TAG, ctx, ERROR, OC_STACK_DELETE_TRANSACTION);
935     (void) UNUSED;
936     CredentialData_t *credData = (CredentialData_t *) ((Data_t *) ctx)->ctx;
937     const OCProvisionDev_t *device = credData->deviceInfo[credData->currIndex];
938     OicSecCred_t *cred = credData->credInfo[credData->currIndex];
939     const OCProvisionResultCB resultCallback = credData->resultCallback;
940
941     if (clientResponse)
942     {
943         if (OC_STACK_RESOURCE_CHANGED == clientResponse->result)
944         {
945             OCStackResult res = ProvisionCredentialsDos(ctx, cred, device, ProvisionCB);
946             if (OC_STACK_OK != res)
947             {
948                 registerResultForCredProvisioning(credData, res, 2);
949                 ((OCProvisionResultCB)(resultCallback))(credData->ctx, credData->numOfResults,
950                                                         credData->resArr, true);
951                 FreeData(ctx);
952                 return OC_STACK_DELETE_TRANSACTION;
953             }
954         }
955         else
956         {
957             registerResultForCredProvisioning(credData, OC_STACK_ERROR, credData->currIndex);
958             ((OCProvisionResultCB)(resultCallback))(credData->ctx, credData->numOfResults,
959                                                     credData->resArr,
960                                                     true);
961             FreeData(ctx);
962         }
963     }
964     else
965     {
966         OIC_LOG(INFO, TAG, "provisionCredentialCB received Null clientResponse for first device");
967         registerResultForCredProvisioning(credData, OC_STACK_ERROR, credData->currIndex);
968         ((OCProvisionResultCB)(resultCallback))(credData->ctx, credData->numOfResults,
969                                                 credData->resArr,
970                                                 true);
971         FreeData(ctx);
972         credData = NULL;
973     }
974     return OC_STACK_DELETE_TRANSACTION;
975 }
976
977
978 #if defined(__WITH_DTLS__) || defined(__WITH_TLS__)
979 /**
980  * Structure to carry certificate data to callback.
981  */
982 typedef struct CertificateData CertData_t;
983 struct CertificateData
984 {
985     void *ctx;                                  /**< Pointer to user context.**/
986     const OCProvisionDev_t *deviceInfo;        /**< Pointer to OCProvisionDev_t.**/
987     OicSecCred_t *credInfo;                     /**< Pointer to OicSecCred_t.**/
988     OCProvisionResultCB resultCallback;         /**< Pointer to result callback.**/
989     OCProvisionResult_t *resArr;                /**< Result array.**/
990     int numOfResults;                           /**< Number of results in result array.**/
991 };
992
993 OCStackResult SRPRegisterTrustCertChainNotifier(void *ctx, TrustCertChainChangeCB callback)
994 {
995     if (g_trustCertChainNotifier.callback)
996     {
997         OIC_LOG(ERROR, TAG, "Can't register Notifier, Unregister previous one");
998         return OC_STACK_ERROR;
999     }
1000
1001     g_trustCertChainNotifier.callback = callback;
1002     g_trustCertChainNotifier.context = ctx;
1003     return OC_STACK_OK;
1004 }
1005
1006 void SRPRemoveTrustCertChainNotifier()
1007 {
1008     g_trustCertChainNotifier.callback = NULL;
1009     g_trustCertChainNotifier.context = NULL;
1010     return;
1011 }
1012
1013 static OCStackApplicationResult provisionCertificateCB(void *ctx, OCDoHandle UNUSED,
1014     OCClientResponse *clientResponse)
1015 {
1016     // Just call the callback provided to SRProvisionCredentials
1017     VERIFY_NOT_NULL_RETURN(TAG, ctx, ERROR, OC_STACK_DELETE_TRANSACTION);
1018     CredentialData_t* credData = (CredentialData_t *)ctx;
1019     (void)UNUSED;
1020     bool hasError;
1021
1022     // We expect OC_STACK_RESOURCE_CHANGED, anything else is an error
1023     if (clientResponse && (OC_STACK_RESOURCE_CHANGED == clientResponse->result))
1024     {
1025         hasError = false;
1026     }
1027     else
1028     {
1029         hasError = true;
1030     }
1031
1032     OCProvisionResultCB resultCallback = credData->resultCallback;
1033     VERIFY_NOT_NULL_RETURN(TAG, resultCallback, ERROR, OC_STACK_DELETE_TRANSACTION);
1034
1035     ((OCProvisionResultCB)(resultCallback))(credData->ctx, credData->numOfResults,
1036         credData->resArr, hasError);
1037
1038     OICFree(credData);
1039
1040     return OC_STACK_DELETE_TRANSACTION;
1041
1042 }
1043 /**
1044  * Callback for Trust Chain provisioning.
1045  */
1046 static OCStackApplicationResult ProvisionTrustChainCB(void *ctx, OCDoHandle UNUSED,
1047         OCClientResponse *clientResponse)
1048 {
1049     OIC_LOG_V(INFO, TAG, "IN %s", __func__);
1050     (void) UNUSED;
1051     if (NULL == ctx)
1052     {
1053         OIC_LOG(ERROR, TAG, "Context is NULL");
1054         return OC_STACK_INVALID_PARAM;
1055     }
1056     if (OC_STACK_RESOURCE_CHANGED == clientResponse->result)
1057     {
1058         Data_t *data = (Data_t *) ctx;
1059         if (CHAIN_TYPE != data->type)
1060         {
1061             OIC_LOG(ERROR, TAG, "Invalid type");
1062             return OC_STACK_INVALID_PARAM;
1063         }
1064         TrustChainData_t *chainData = (TrustChainData_t *) (data->ctx);
1065         OicSecCred_t *trustCertChainCred = GetCredEntryByCredId(chainData->credId);
1066         if (NULL == trustCertChainCred)
1067         {
1068             OIC_LOG(ERROR, TAG, "Can not find matched Trust Cert. Chain.");
1069             return OC_STACK_NO_RESOURCE;
1070         }
1071
1072         OCSecurityPayload *secPayload = (OCSecurityPayload *)OICCalloc(1, sizeof(OCSecurityPayload));
1073         if (!secPayload)
1074         {
1075             DeleteCredList(trustCertChainCred);
1076             OIC_LOG(ERROR, TAG, "Failed to allocate memory");
1077             return OC_STACK_NO_MEMORY;
1078         }
1079         secPayload->base.type = PAYLOAD_TYPE_SECURITY;
1080         int secureFlag = 1; /* Don't send the private key to the device, if it happens to be present */
1081         if (OC_STACK_OK != CredToCBORPayload(trustCertChainCred, &secPayload->securityData,
1082                                              &secPayload->payloadSize, secureFlag))
1083         {
1084             DeleteCredList(trustCertChainCred);
1085             OCPayloadDestroy((OCPayload *)secPayload);
1086             OIC_LOG(ERROR, TAG, "Failed to CredToCBORPayload");
1087             return OC_STACK_NO_MEMORY;
1088         }
1089         DeleteCredList(trustCertChainCred);
1090         OIC_LOG(DEBUG, TAG, "Created payload for Cred:");
1091         OIC_LOG_BUFFER(DEBUG, TAG, secPayload->securityData, secPayload->payloadSize);
1092
1093         char query[MAX_URI_LENGTH + MAX_QUERY_LENGTH] = {0};
1094         if (!PMGenerateQuery(true,
1095                              chainData->targetDev->endpoint.addr,
1096                              chainData->targetDev->securePort,
1097                              chainData->targetDev->connType,
1098                              query, sizeof(query), OIC_RSRC_CRED_URI))
1099         {
1100             OIC_LOG(ERROR, TAG, "Failed to generate query");
1101             OCPayloadDestroy((OCPayload *)secPayload);
1102             return OC_STACK_ERROR;
1103         }
1104         OIC_LOG_V(DEBUG, TAG, "Query=%s", query);
1105
1106         OCCallbackData cbData =  {.context = NULL, .cb = NULL, .cd = NULL};
1107         cbData.cb = ProvisionCB;
1108         cbData.context = ctx;
1109         cbData.cd = NULL;
1110         OCMethod method = OC_REST_POST;
1111         OCDoHandle handle = NULL;
1112         OIC_LOG(DEBUG, TAG, "Sending Cred info to resource server");
1113         OCStackResult ret = OCDoResource(&handle, method, query,
1114                                          &chainData->targetDev->endpoint, (OCPayload *)secPayload,
1115                                          chainData->targetDev->connType, OC_HIGH_QOS, &cbData, NULL, 0);
1116         if (ret != OC_STACK_OK)
1117         {
1118             OIC_LOG_V(INFO, TAG, "OUT %s", __func__);
1119             return ret;
1120         }
1121     }
1122     else
1123     {
1124         OIC_LOG_V(ERROR, TAG, "OUT %s", __func__);
1125         return OC_STACK_ERROR;
1126     }
1127
1128     OIC_LOG_V(INFO, TAG, "OUT %s", __func__);
1129     return OC_STACK_OK;
1130 }
1131
1132 OCStackResult SRPProvisionTrustCertChain(void *ctx, OicSecCredType_t type, uint16_t credId,
1133         const OCProvisionDev_t *selectedDeviceInfo, OCProvisionResultCB resultCallback)
1134 {
1135     OIC_LOG_V(INFO, TAG, "IN %s", __func__);
1136     VERIFY_NOT_NULL_RETURN(TAG, selectedDeviceInfo, ERROR,  OC_STACK_INVALID_PARAM);
1137     VERIFY_NOT_NULL_RETURN(TAG, resultCallback, ERROR,  OC_STACK_INVALID_CALLBACK);
1138     if (SIGNED_ASYMMETRIC_KEY != type)
1139     {
1140         OIC_LOG(INFO, TAG, "Invalid key type");
1141         return OC_STACK_INVALID_PARAM;
1142     }
1143
1144     TrustChainData_t *chainData = (TrustChainData_t *) OICCalloc(1, sizeof(TrustChainData_t));
1145     if (NULL == chainData)
1146     {
1147         OIC_LOG(ERROR, TAG, "Memory allocation problem");
1148         return OC_STACK_NO_MEMORY;
1149     }
1150     chainData->targetDev = selectedDeviceInfo;
1151     chainData->resultCallback = resultCallback;
1152     chainData->credId = credId;
1153     chainData->ctx = ctx;
1154     chainData->numOfResults = 0;
1155
1156     int noOfRiCalls = 1;
1157     chainData->resArr = (OCProvisionResult_t *)OICCalloc(noOfRiCalls, sizeof(OCProvisionResult_t));
1158     if (chainData->resArr == NULL)
1159     {
1160         OICFree(chainData);
1161         OIC_LOG(ERROR, TAG, "Unable to allocate memory");
1162         return OC_STACK_NO_MEMORY;
1163     }
1164
1165     Data_t *data = (Data_t *) OICCalloc(1, sizeof(Data_t));
1166     data->type = CHAIN_TYPE;
1167     data->ctx = chainData;
1168
1169     if (SetDOS(data, DOS_RFPRO, ProvisionTrustChainCB) != OC_STACK_OK)
1170     {
1171         FreeData(data);
1172         OIC_LOG_V(INFO, TAG, "OUT %s", __func__);
1173         return OC_STACK_ERROR;
1174     }
1175
1176     OIC_LOG_V(INFO, TAG, "OUT %s", __func__);
1177     return OC_STACK_OK;
1178 }
1179
1180 OCStackResult SRPSaveTrustCertChain(const uint8_t *trustCertChain, size_t chainSize,
1181                                             OicEncodingType_t encodingType, uint16_t *credId)
1182 {
1183     OIC_LOG(DEBUG, TAG, "IN SRPSaveTrustCertChain");
1184     VERIFY_NOT_NULL_RETURN(TAG, trustCertChain, ERROR,  OC_STACK_INVALID_PARAM);
1185     VERIFY_NOT_NULL_RETURN(TAG, credId, ERROR,  OC_STACK_INVALID_PARAM);
1186
1187     OCStackResult res = OC_STACK_ERROR;
1188
1189     OicSecCred_t *cred = (OicSecCred_t *)OICCalloc(1, sizeof(*cred));
1190     VERIFY_NOT_NULL_RETURN(TAG, cred, ERROR, OC_STACK_NO_MEMORY);
1191
1192     res = GetDoxmDeviceID(&cred->subject);
1193     if (OC_STACK_OK != res)
1194     {
1195         OIC_LOG(ERROR, TAG, "Can't get the device id(GetDoxmDeviceID)");
1196         DeleteCredList(cred);
1197         return res;
1198     }
1199
1200     cred->credUsage= (char *)OICCalloc(1, strlen(TRUST_CA) + 1);
1201     VERIFY_NOT_NULL_RETURN(TAG, cred->credUsage, ERROR, OC_STACK_NO_MEMORY);
1202     OICStrcpy(cred->credUsage, strlen(TRUST_CA) + 1, TRUST_CA);
1203
1204     cred->credType = SIGNED_ASYMMETRIC_KEY;
1205
1206     if (encodingType == OIC_ENCODING_PEM)
1207     {
1208         cred->optionalData.data = (uint8_t *)OICCalloc(1, chainSize + 1);
1209         VERIFY_NOT_NULL_RETURN(TAG, cred->optionalData.data, ERROR, OC_STACK_NO_MEMORY);
1210         cred->optionalData.len = chainSize + 1;
1211     }
1212     else if (encodingType == OIC_ENCODING_DER)
1213     {
1214         cred->optionalData.data = (uint8_t *)OICCalloc(1, chainSize);
1215         VERIFY_NOT_NULL_RETURN(TAG, cred->optionalData.data, ERROR, OC_STACK_NO_MEMORY);
1216         cred->optionalData.len = chainSize;
1217     }
1218     else
1219     {
1220         OIC_LOG_V(ERROR, TAG, "Unknown encoding in %s", __func__);
1221         DeleteCredList(cred);
1222         return OC_STACK_INVALID_PARAM;
1223     }
1224     memcpy(cred->optionalData.data, trustCertChain, chainSize);
1225     cred->optionalData.encoding = encodingType;
1226     cred->optionalData.revstat = false;
1227
1228     res = AddCredential(cred);
1229     if(res != OC_STACK_OK)
1230     {
1231         DeleteCredList(cred);
1232         return res;
1233     }
1234     *credId = cred->credId;
1235
1236     if (g_trustCertChainNotifier.callback)
1237     {
1238         uint8_t *certChain = (uint8_t*)OICCalloc(1, sizeof(uint8_t) * chainSize);
1239         VERIFY_NOT_NULL_RETURN(TAG, certChain, ERROR, OC_STACK_NO_MEMORY);
1240         memcpy(certChain, trustCertChain, chainSize);
1241         g_trustCertChainNotifier.callback(g_trustCertChainNotifier.context, *credId,
1242                 certChain, chainSize);
1243         OICFree(certChain);
1244     }
1245
1246     OIC_LOG(DEBUG, TAG, "OUT SRPSaveTrustCertChain");
1247
1248     return res;
1249 }
1250
1251 static OCStackResult saveCertChain(OicSecKey_t * cert, OicSecKey_t * key, uint16_t *credId, const char* usage)
1252 {
1253     OIC_LOG_V(DEBUG, TAG, "IN %s", __func__);
1254     VERIFY_NOT_NULL_RETURN(TAG, cert, ERROR,  OC_STACK_INVALID_PARAM);
1255     VERIFY_NOT_NULL_RETURN(TAG, cert->data, ERROR,  OC_STACK_INVALID_PARAM);
1256
1257     VERIFY_NOT_NULL_RETURN(TAG, credId, ERROR,  OC_STACK_INVALID_PARAM);
1258     VERIFY_NOT_NULL_RETURN(TAG, usage, ERROR, OC_STACK_INVALID_PARAM);
1259
1260     if (NULL == key && PRIMARY_CERT == usage)
1261     {
1262         OIC_LOG_V(ERROR, TAG, "Key is NULL, but it is mandatory if usage is %s", PRIMARY_CERT);
1263         return OC_STACK_INVALID_PARAM;
1264     }
1265
1266     if (key != NULL)
1267     {
1268         /* Key is optional. */
1269         VERIFY_NOT_NULL_RETURN(TAG, key->data, ERROR, OC_STACK_INVALID_PARAM);
1270     }
1271
1272     OCStackResult res = OC_STACK_ERROR;
1273
1274     OicSecCred_t *cred = (OicSecCred_t *)OICCalloc(1, sizeof(*cred));
1275     VERIFY_NOT_NULL_RETURN(TAG, cred, ERROR, OC_STACK_NO_MEMORY);
1276
1277     OIC_LOG_V(DEBUG, TAG, "IN: %s", __func__);
1278
1279     res = GetDoxmDeviceID(&cred->subject);
1280     if (OC_STACK_OK != res)
1281     {
1282         OIC_LOG(ERROR, TAG, "Can't get the device id(GetDoxmDeviceID)");
1283         DeleteCredList(cred);
1284         return res;
1285     }
1286
1287     cred->credUsage= (char *)OICCalloc(1, strlen(usage) + 1);
1288     VERIFY_NOT_NULL_RETURN(TAG, cred->credUsage, ERROR, OC_STACK_NO_MEMORY);
1289     OICStrcpy(cred->credUsage, strlen(usage) + 1, usage);
1290
1291     cred->credType = SIGNED_ASYMMETRIC_KEY;
1292
1293     OicSecKey_t *publicData = &cred->publicData;
1294     publicData->data = (uint8_t *)OICCalloc(1, cert->len);
1295     VERIFY_NOT_NULL_RETURN(TAG, publicData->data, ERROR, OC_STACK_NO_MEMORY);
1296     memcpy(publicData->data, cert->data, cert->len);
1297     publicData->len = cert->len;
1298     publicData->encoding = cert->encoding;
1299
1300     if (key != NULL)
1301     {
1302         OicSecKey_t *privateData = &cred->privateData;
1303         privateData->data = (uint8_t *)OICCalloc(1, key->len);
1304         VERIFY_NOT_NULL_RETURN(TAG, privateData->data, ERROR, OC_STACK_NO_MEMORY);
1305         memcpy(privateData->data, key->data, key->len);
1306         privateData->len = key->len;
1307         privateData->encoding = key->encoding;
1308     }
1309
1310     res = AddCredential(cred);
1311     if(res != OC_STACK_OK)
1312     {
1313         DeleteCredList(cred);
1314         return res;
1315     }
1316     *credId = cred->credId;
1317
1318     OIC_LOG_V(DEBUG, TAG, "OUT %s", __func__);
1319
1320     return res;
1321 }
1322
1323 OCStackResult SRPSaveOwnCertChain(OicSecKey_t * cert, OicSecKey_t * key, uint16_t *credId)
1324 {
1325     return saveCertChain(cert, key, credId, PRIMARY_CERT);
1326 }
1327
1328 OCStackResult SRPSaveOwnRoleCert(OicSecKey_t * cert, uint16_t *credId)
1329 {
1330     return saveCertChain(cert, NULL, credId, ROLE_CERT);
1331 }
1332
1333 #endif // __WITH_DTLS__ || __WITH_TLS__
1334
1335 OCStackResult SRPProvisionCredentials(void *ctx, OicSecCredType_t type, size_t keySize,
1336                                       const OCProvisionDev_t *pDev1,
1337                                       const OCProvisionDev_t *pDev2,
1338                                       const char* pemCert,
1339                                       const OicSecRole_t *role1,
1340                                       const OicSecRole_t *role2,
1341                                       OCProvisionResultCB resultCallback)
1342 {
1343     VERIFY_NOT_NULL_RETURN(TAG, pDev1, ERROR,  OC_STACK_INVALID_PARAM);
1344     if (!resultCallback)
1345     {
1346         OIC_LOG(INFO, TAG, "SRPProvisionCredentials: NULL Callback");
1347         return OC_STACK_INVALID_CALLBACK;
1348     }
1349     if ((SYMMETRIC_PAIR_WISE_KEY == type) &&
1350         (NULL != pDev2) &&
1351         (0 == memcmp(&pDev1->doxm->deviceID, &pDev2->doxm->deviceID, sizeof(OicUuid_t))))
1352     {
1353         OIC_LOG(INFO, TAG, "SRPProvisionCredentials : Same device ID");
1354         return OC_STACK_INVALID_PARAM;
1355     }
1356
1357     if (SYMMETRIC_PAIR_WISE_KEY == type &&
1358        !(OWNER_PSK_LENGTH_128 == keySize || OWNER_PSK_LENGTH_256 == keySize))
1359     {
1360         OIC_LOG(INFO, TAG, "Invalid key size");
1361         return OC_STACK_INVALID_PARAM;
1362     }
1363
1364     OIC_LOG(INFO, TAG, "In SRPProvisionCredentials");
1365
1366     if ((SYMMETRIC_PAIR_WISE_KEY == type) && (NULL != pDev2))
1367     {
1368         bool linkExisits = true;
1369         OCStackResult res = PDMIsLinkExists(&pDev1->doxm->deviceID, &pDev2->doxm->deviceID, &linkExisits);
1370
1371         if (res != OC_STACK_OK)
1372         {
1373             OIC_LOG(ERROR, TAG, "Internal error occured");
1374             return res;
1375         }
1376         if (linkExisits)
1377         {
1378             OIC_LOG(ERROR, TAG, "Link already exists");
1379             return OC_STACK_INVALID_PARAM;
1380         }
1381     }
1382
1383     OicUuid_t provTooldeviceID =   {{0,}};
1384     if (OC_STACK_OK != GetDoxmDeviceID(&provTooldeviceID))
1385     {
1386         OIC_LOG(ERROR, TAG, "Error while retrieving provisioning tool's device ID");
1387         return OC_STACK_ERROR;
1388     }
1389     OIC_LOG(INFO, TAG, "retrieved deviceid");
1390     switch (type)
1391     {
1392         case SYMMETRIC_PAIR_WISE_KEY:
1393         {
1394             const OCProvisionDev_t *firstDevice = pDev1;
1395             const OCProvisionDev_t *secondDevice = pDev2;
1396
1397             OicSecCred_t *firstCred = NULL;
1398             OicSecCred_t *secondCred = NULL;
1399             OCStackResult res = PMGeneratePairWiseCredentials(type, keySize, &provTooldeviceID,
1400                     &firstDevice->doxm->deviceID, (NULL != secondDevice) ? &secondDevice->doxm->deviceID : &provTooldeviceID,
1401                     role1, role2,
1402                     &firstCred, &secondCred);
1403             VERIFY_SUCCESS_RETURN(TAG, (res==OC_STACK_OK), ERROR, OC_STACK_ERROR);
1404             OIC_LOG(INFO, TAG, "Credentials generated successfully");
1405             CredentialData_t *credData =
1406                 (CredentialData_t *) OICCalloc(1, sizeof(CredentialData_t));
1407             if (NULL == credData)
1408             {
1409                 OICFree(firstCred);
1410                 OICFree(secondCred);
1411                 OIC_LOG(ERROR, TAG, "Memory allocation problem");
1412                 return OC_STACK_NO_MEMORY;
1413             }
1414             credData->deviceInfo[0] = firstDevice;
1415             credData->deviceInfo[1] = secondDevice;
1416             credData->credInfo[1] = secondCred;
1417             credData->ctx = ctx;
1418             credData->credInfo[0] = firstCred;
1419             credData->numOfResults = 0;
1420             credData->resultCallback = resultCallback;
1421             // first call to provision creds to device1.
1422             // second call to provision creds to device2.
1423             int noOfRiCalls = 2;
1424             credData->resArr =
1425                 (OCProvisionResult_t*)OICCalloc(noOfRiCalls, sizeof(OCProvisionResult_t));
1426             if (NULL == credData->resArr)
1427             {
1428                 OICFree(firstCred);
1429                 OICFree(secondCred);
1430                 OICFree(credData);
1431                 OIC_LOG(ERROR, TAG, "Memory allocation problem");
1432                 return OC_STACK_NO_MEMORY;
1433             }
1434             res = provisionCredentials(firstCred, firstDevice, credData, &provisionCredentialCB1);
1435             if (OC_STACK_OK != res)
1436             {
1437                 DeleteCredList(firstCred);
1438                 DeleteCredList(secondCred);
1439                 OICFree(credData->resArr);
1440                 OICFree(credData);
1441             }
1442             OIC_LOG_V(INFO, TAG, "provisionCredentials returned: %d",res);
1443             VERIFY_SUCCESS_RETURN(TAG, (res==OC_STACK_OK), ERROR, OC_STACK_ERROR);
1444             return res;
1445         }
1446         case SIGNED_ASYMMETRIC_KEY:
1447         {
1448             /* pDev1 is the device to be provisioned, checked non-null above */
1449             /* pDev2 is not used, should be NULL */
1450             /* size param is not used. */
1451             /* pemCert is the cerficiate to be provisioned */
1452             VERIFY_NOT_NULL_RETURN(TAG, pemCert, ERROR, OC_STACK_INVALID_PARAM);
1453
1454             OicSecKey_t deviceCert = { 0 };
1455             deviceCert.data = (uint8_t*) pemCert; /* Casting away const is OK here */
1456             deviceCert.len = strlen(pemCert) + 1;
1457             deviceCert.encoding = OIC_ENCODING_PEM;
1458
1459             /* Create a credential object */
1460             OicSecCred_t* cred =  GenerateCredential(&pDev1->doxm->deviceID, SIGNED_ASYMMETRIC_KEY,
1461                     &deviceCert, NULL, // oic.sec.cred.publicdata = deviceCert, .privatedata = NULL
1462                     &provTooldeviceID, NULL); // rowner is the provisioning tool and no eowner
1463             VERIFY_NOT_NULL_RETURN(TAG, cred, ERROR, OC_STACK_ERROR);
1464
1465             cred->publicData.encoding = OIC_ENCODING_PEM;
1466
1467             if (OCInternalIsValidRoleCertificate(deviceCert.data, deviceCert.len, NULL, NULL) == OC_STACK_OK)
1468             {
1469                 cred->credUsage = OICStrdup(ROLE_CERT);
1470             }
1471             else
1472             {
1473                 cred->credUsage = OICStrdup(PRIMARY_CERT);
1474             }
1475
1476             /* Create credential data (used by the response handler provisionCertificateCB and freed there) */
1477             CredentialData_t *credData = (CredentialData_t *)OICCalloc(1, sizeof(CredentialData_t));
1478             if ((NULL == credData) || (NULL == cred->credUsage))
1479             {
1480                 DeleteCredList(cred);
1481                 OIC_LOG(ERROR, TAG, "Memory allocation problem");
1482                 return OC_STACK_NO_MEMORY;
1483             }
1484             credData->deviceInfo[0] = pDev1;
1485             credData->deviceInfo[1] = NULL;
1486             credData->credInfo[1] = cred;
1487             credData->ctx = ctx;
1488             credData->credInfo[0] = cred;
1489             credData->numOfResults = 0;
1490             credData->resultCallback = resultCallback;
1491             credData->resArr = NULL;
1492
1493             /* Note: the callback is of type OCClientResponseHandler, thin wrapper that calls resultCallback */
1494             OCStackResult res = provisionCredentials(cred, pDev1, credData, &provisionCertificateCB);
1495             if (res != OC_STACK_OK)
1496             {
1497                 OICFree(credData);
1498             }
1499
1500             DeleteCredList(cred);
1501             return OC_STACK_OK;
1502         }
1503         default:
1504         {
1505             OIC_LOG(ERROR, TAG, "Invalid option.");
1506             return OC_STACK_INVALID_PARAM;
1507         }
1508     }
1509 }
1510
1511 OCStackResult SRPProvisionCredentialsDos(void *ctx, OicSecCredType_t type, size_t keySize,
1512                                       const OCProvisionDev_t *pDev1,
1513                                       const OCProvisionDev_t *pDev2,
1514                                       OCProvisionResultCB resultCallback)
1515 {
1516     VERIFY_NOT_NULL_RETURN(TAG, pDev1, ERROR,  OC_STACK_INVALID_PARAM);
1517     if (!resultCallback)
1518     {
1519         OIC_LOG(INFO, TAG, "SRPProvisionCredentialsDos: NULL Callback");
1520         return OC_STACK_INVALID_CALLBACK;
1521     }
1522     if ((SYMMETRIC_PAIR_WISE_KEY == type) &&
1523         (NULL != pDev2) &&
1524         (0 == memcmp(&pDev1->doxm->deviceID, &pDev2->doxm->deviceID, sizeof(OicUuid_t))))
1525     {
1526         OIC_LOG(INFO, TAG, "SRPProvisionCredentialsDos : Same device ID");
1527         return OC_STACK_INVALID_PARAM;
1528     }
1529     if (SYMMETRIC_PAIR_WISE_KEY == type && NULL == pDev2)
1530     {
1531         OIC_LOG(INFO, TAG, "SRPProvisionCredentialsDos : NULL device");
1532         return OC_STACK_INVALID_PARAM;
1533     }
1534
1535     if (SYMMETRIC_PAIR_WISE_KEY == type &&
1536        !(OWNER_PSK_LENGTH_128 == keySize || OWNER_PSK_LENGTH_256 == keySize))
1537     {
1538         OIC_LOG(INFO, TAG, "Invalid key size");
1539         return OC_STACK_INVALID_PARAM;
1540     }
1541
1542     OIC_LOG(INFO, TAG, "In SRPProvisionCredentialsDos");
1543
1544     if ((SYMMETRIC_PAIR_WISE_KEY == type) && (NULL != pDev2))
1545     {
1546         bool linkExisits = true;
1547         OCStackResult res = PDMIsLinkExists(&pDev1->doxm->deviceID, &pDev2->doxm->deviceID, &linkExisits);
1548
1549         if (res != OC_STACK_OK)
1550         {
1551             OIC_LOG(ERROR, TAG, "Internal error occured");
1552             return res;
1553         }
1554         if (linkExisits)
1555         {
1556             OIC_LOG(ERROR, TAG, "Link already exists");
1557             return OC_STACK_INVALID_PARAM;
1558         }
1559     }
1560
1561     OicUuid_t provTooldeviceID =   {{0,}};
1562     if (OC_STACK_OK != GetDoxmDeviceID(&provTooldeviceID))
1563     {
1564         OIC_LOG(ERROR, TAG, "Error while retrieving provisioning tool's device ID");
1565         return OC_STACK_ERROR;
1566     }
1567     OIC_LOG(INFO, TAG, "retrieved deviceid");
1568
1569     CredentialData_t *credData = (CredentialData_t *) OICCalloc(1, sizeof(CredentialData_t));
1570     Data_t *data = (Data_t *) OICCalloc(1, sizeof(Data_t));
1571     if (NULL == credData || NULL == data)
1572     {
1573
1574         OICFree(credData);
1575         OICFree(data);
1576         OIC_LOG(ERROR, TAG, "Memory allocation problem");
1577         return OC_STACK_NO_MEMORY;
1578     }
1579
1580     data->ctx = credData;
1581
1582     switch (type)
1583     {
1584         case SYMMETRIC_PAIR_WISE_KEY:
1585         {
1586             data->type = PSK_TYPE;
1587             OicSecCred_t *firstCred = NULL;
1588             OicSecCred_t *secondCred = NULL;
1589             OCStackResult res = PMGeneratePairWiseCredentials(type, keySize, &provTooldeviceID,
1590                                 &pDev1->doxm->deviceID, (NULL != pDev2) ? &pDev2->doxm->deviceID :
1591                                 &provTooldeviceID,
1592                                 NULL, NULL,
1593                                 &firstCred, &secondCred);
1594             VERIFY_SUCCESS_RETURN(TAG, (res == OC_STACK_OK), ERROR, OC_STACK_ERROR);
1595             OIC_LOG(INFO, TAG, "Credentials generated successfully");
1596
1597             credData->deviceInfo[0] = pDev1;
1598             credData->deviceInfo[1] = pDev2;
1599             credData->credInfo[0] = firstCred;
1600             credData->credInfo[1] = secondCred;
1601             credData->ctx = ctx;
1602             credData->currIndex = 0;
1603             credData->numOfResults = 0;
1604             credData->resultCallback = resultCallback;
1605             // first call to provision creds to device1.
1606             // second call to provision creds to device2.
1607             int noOfRiCalls = 2;
1608             credData->resArr =
1609                 (OCProvisionResult_t *)OICCalloc(noOfRiCalls, sizeof(OCProvisionResult_t));
1610             if (NULL == credData->resArr)
1611             {
1612                 OICFree(firstCred);
1613                 OICFree(secondCred);
1614                 OICFree(credData);
1615                 OIC_LOG(ERROR, TAG, "Memory allocation problem");
1616                 return OC_STACK_NO_MEMORY;
1617             }
1618
1619             res = SetDOS(data, DOS_RFPRO, ProvisionPskCB);
1620
1621             if (OC_STACK_OK != res)
1622             {
1623                 DeleteCredList(firstCred);
1624                 DeleteCredList(secondCred);
1625                 FreeData(data);
1626                 OIC_LOG_V(ERROR, TAG, "OUT %s", __func__);
1627                 return res;
1628             }
1629             OIC_LOG_V(INFO, TAG, "provisionCredentials returned: %d", res);
1630             return res;
1631         }
1632         default:
1633         {
1634             OIC_LOG(ERROR, TAG, "Invalid option.");
1635             return OC_STACK_INVALID_PARAM;
1636         }
1637     }
1638 }
1639 /**
1640  * Callback for ACL provisioning.
1641  */
1642 static OCStackApplicationResult ProvisionAclCB(void *ctx, OCDoHandle UNUSED,
1643         OCClientResponse *clientResponse);
1644
1645 OCStackResult SRPProvisionACL(void *ctx, const OCProvisionDev_t *selectedDeviceInfo,
1646         OicSecAcl_t *acl, OicSecAclVersion_t aclVersion, OCProvisionResultCB resultCallback)
1647 {
1648     VERIFY_NOT_NULL_RETURN(TAG, selectedDeviceInfo, ERROR,  OC_STACK_INVALID_PARAM);
1649     VERIFY_NOT_NULL_RETURN(TAG, acl, ERROR,  OC_STACK_INVALID_PARAM);
1650     VERIFY_NOT_NULL_RETURN(TAG, resultCallback, ERROR,  OC_STACK_INVALID_CALLBACK);
1651     OIC_LOG_V(INFO, TAG, "IN %s", __func__);
1652
1653
1654     ACLData_t *aclData = (ACLData_t *) OICCalloc(1, sizeof(ACLData_t));
1655     if (NULL == aclData)
1656     {
1657         OIC_LOG(ERROR, TAG, "Memory allocation problem");
1658         OIC_LOG_V(ERROR, TAG, "OUT %s", __func__);
1659         return OC_STACK_NO_MEMORY;
1660     }
1661     aclData->deviceInfo = selectedDeviceInfo;
1662     aclData->resultCallback = resultCallback;
1663     aclData->aclVersion = aclVersion;
1664     aclData->acl = acl;
1665     aclData->ctx = ctx;
1666     aclData->numOfResults = 0;
1667
1668     aclData->resArr = (OCProvisionResult_t *) OICCalloc(1, sizeof(OCProvisionResult_t));
1669     if (aclData->resArr == NULL)
1670     {
1671         OICFree(aclData);
1672         OIC_LOG(ERROR, TAG, "Unable to allocate memory");
1673         OIC_LOG_V(ERROR, TAG, "OUT %s", __func__);
1674         return OC_STACK_NO_MEMORY;
1675     }
1676
1677     Data_t *data = (Data_t *) OICCalloc(1, sizeof(Data_t));
1678     if (data == NULL)
1679     {
1680         OICFree(aclData->resArr);
1681         OICFree(aclData);
1682         OIC_LOG(ERROR, TAG, "Unable to allocate memory");
1683         OIC_LOG_V(ERROR, TAG, "OUT %s", __func__);
1684         return OC_STACK_NO_MEMORY;
1685     }
1686     data->type = ACL_TYPE;
1687     data->ctx = aclData;
1688
1689     if (SetDOS(data, DOS_RFPRO, ProvisionAclCB) != OC_STACK_OK)
1690     {
1691         FreeData(data);
1692         OIC_LOG_V(ERROR, TAG, "OUT %s", __func__);
1693         return OC_STACK_ERROR;
1694     }
1695
1696     OIC_LOG_V(INFO, TAG, "OUT %s", __func__);
1697     return OC_STACK_OK;
1698 }
1699
1700 OCStackResult SRPSaveACL(const OicSecAcl_t *acl)
1701 {
1702     OIC_LOG(DEBUG, TAG, "IN SRPSaveACL");
1703     VERIFY_NOT_NULL_RETURN(TAG, acl, ERROR,  OC_STACK_INVALID_PARAM);
1704
1705     OCStackResult res =  InstallACL(acl);
1706
1707     OIC_LOG(DEBUG, TAG, "OUT SRPSaveACL");
1708     return res;
1709 }
1710
1711 /**
1712  * Internal Function to store results in result array during Direct-Pairing provisioning.
1713  */
1714 static void registerResultForDirectPairingProvisioning(PconfData_t *pconfData,
1715                                              OCStackResult stackresult)
1716 {
1717    OIC_LOG_V(INFO, TAG, "Inside registerResultForDirectPairingProvisioning "
1718            "pconfData->numOfResults is %d", pconfData->numOfResults);
1719    memcpy(pconfData->resArr[(pconfData->numOfResults)].deviceId.id,
1720           pconfData->deviceInfo->doxm->deviceID.id, UUID_LENGTH);
1721    pconfData->resArr[(pconfData->numOfResults)].res = stackresult;
1722    ++(pconfData->numOfResults);
1723 }
1724
1725 /**
1726  * Callback handler of SRPProvisionDirectPairing.
1727  *
1728  * @param[in] ctx             ctx value passed to callback from calling function.
1729  * @param[in] UNUSED          handle to an invocation
1730  * @param[in] clientResponse  Response from queries to remote servers.
1731  * @return  OC_STACK_DELETE_TRANSACTION to delete the transaction
1732  *          and  OC_STACK_KEEP_TRANSACTION to keep it.
1733  */
1734 static OCStackApplicationResult SRPProvisionDirectPairingCB(void *ctx, OCDoHandle UNUSED,
1735                                                   OCClientResponse *clientResponse)
1736 {
1737     OIC_LOG_V(INFO, TAG, "Inside SRPProvisionDirectPairingCB.");
1738     (void)UNUSED;
1739     VERIFY_NOT_NULL_RETURN(TAG, ctx, ERROR, OC_STACK_DELETE_TRANSACTION);
1740     PconfData_t *pconfData = (PconfData_t*)ctx;
1741     OCProvisionResultCB resultCallback = pconfData->resultCallback;
1742
1743     if (clientResponse)
1744     {
1745         if(OC_STACK_RESOURCE_CHANGED == clientResponse->result)
1746         {
1747             registerResultForDirectPairingProvisioning(pconfData, OC_STACK_OK);
1748             ((OCProvisionResultCB)(resultCallback))(pconfData->ctx, pconfData->numOfResults,
1749                                                     pconfData->resArr,
1750                                                     false);
1751              OICFree(pconfData->resArr);
1752              OICFree(pconfData);
1753              return OC_STACK_DELETE_TRANSACTION;
1754         }
1755     }
1756     registerResultForDirectPairingProvisioning(pconfData, OC_STACK_ERROR);
1757     ((OCProvisionResultCB)(resultCallback))(pconfData->ctx, pconfData->numOfResults,
1758                                             pconfData->resArr,
1759                                             true);
1760     OIC_LOG_V(ERROR, TAG, "SRPProvisionDirectPairingCB received Null clientResponse");
1761     OICFree(pconfData->resArr);
1762     OICFree(pconfData);
1763     return OC_STACK_DELETE_TRANSACTION;
1764 }
1765
1766 OCStackResult SRPProvisionDirectPairing(void *ctx, const OCProvisionDev_t *selectedDeviceInfo,
1767         OicSecPconf_t *pconf, OCProvisionResultCB resultCallback)
1768 {
1769     VERIFY_NOT_NULL_RETURN(TAG, selectedDeviceInfo, ERROR,  OC_STACK_INVALID_PARAM);
1770     VERIFY_NOT_NULL_RETURN(TAG, pconf, ERROR,  OC_STACK_INVALID_PARAM);
1771     VERIFY_NOT_NULL_RETURN(TAG, resultCallback, ERROR,  OC_STACK_INVALID_CALLBACK);
1772
1773     // check direct-pairing capability
1774     if (true != selectedDeviceInfo->doxm->dpc)
1775     {
1776         OIC_LOG(ERROR, TAG, "Resouce server does not have Direct-Pairing Capability ");
1777         return OC_STACK_UNAUTHORIZED_REQ;
1778     }
1779
1780     OicUuid_t provTooldeviceID =   {.id={0}};
1781     if (OC_STACK_OK != GetDoxmDeviceID(&provTooldeviceID))
1782     {
1783         OIC_LOG(ERROR, TAG, "Error while retrieving provisioning tool's device ID");
1784         return OC_STACK_ERROR;
1785     }
1786     memcpy(&pconf->rownerID, &provTooldeviceID, sizeof(OicUuid_t));
1787
1788     OCSecurityPayload* secPayload = (OCSecurityPayload*)OICCalloc(1, sizeof(OCSecurityPayload));
1789     if(!secPayload)
1790     {
1791         OIC_LOG(ERROR, TAG, "Failed to allocate memory");
1792         return OC_STACK_NO_MEMORY;
1793     }
1794     secPayload->base.type = PAYLOAD_TYPE_SECURITY;
1795
1796     if (OC_STACK_OK != PconfToCBORPayload(pconf, &(secPayload->securityData),
1797                 &(secPayload->payloadSize)))
1798     {
1799         OCPayloadDestroy((OCPayload*)secPayload);
1800         OIC_LOG(ERROR, TAG, "Failed to PconfToCborPayload");
1801         return OC_STACK_NO_MEMORY;
1802     }
1803     OIC_LOG(DEBUG, TAG, "Created payload for pconf set");
1804     OIC_LOG_BUFFER(DEBUG, TAG, secPayload->securityData, secPayload->payloadSize);
1805
1806     char query[MAX_URI_LENGTH + MAX_QUERY_LENGTH] = {0};
1807     if(!PMGenerateQuery(true,
1808                 selectedDeviceInfo->endpoint.addr,
1809                 selectedDeviceInfo->securePort,
1810                 selectedDeviceInfo->connType,
1811                 query, sizeof(query), OIC_RSRC_PCONF_URI))
1812     {
1813         OIC_LOG(ERROR, TAG, "SRPProvisionDirectPairing : Failed to generate query");
1814         return OC_STACK_ERROR;
1815     }
1816     OIC_LOG_V(DEBUG, TAG, "Query=%s", query);
1817
1818     OCCallbackData cbData =  {.context=NULL, .cb=NULL, .cd=NULL};
1819     cbData.cb = &SRPProvisionDirectPairingCB;
1820     PconfData_t *pconfData = (PconfData_t *) OICCalloc(1, sizeof(PconfData_t));
1821     if (NULL == pconfData)
1822     {
1823         OCPayloadDestroy((OCPayload*)secPayload);
1824         OIC_LOG(ERROR, TAG, "Unable to allocate memory");
1825         return OC_STACK_NO_MEMORY;
1826     }
1827     pconfData->deviceInfo = selectedDeviceInfo;
1828     pconfData->resultCallback = resultCallback;
1829     pconfData->numOfResults=0;
1830     pconfData->ctx = ctx;
1831     // call to provision PCONF to device1.
1832     int noOfRiCalls = 1;
1833     pconfData->resArr = (OCProvisionResult_t*)OICCalloc(noOfRiCalls, sizeof(OCProvisionResult_t));
1834     if (NULL == pconfData->resArr)
1835     {
1836         OICFree(pconfData);
1837         OCPayloadDestroy((OCPayload*)secPayload);
1838         OIC_LOG(ERROR, TAG, "Unable to allocate memory");
1839         return OC_STACK_NO_MEMORY;
1840     }
1841     cbData.context = (void *)pconfData;
1842     cbData.cd = NULL;
1843     OCMethod method = OC_REST_POST;
1844     OCDoHandle handle = NULL;
1845     OIC_LOG(DEBUG, TAG, "Sending PCONF info to resource server");
1846     OCStackResult ret = OCDoResource(&handle, method, query,
1847             &selectedDeviceInfo->endpoint, (OCPayload*)secPayload,
1848             selectedDeviceInfo->connType, OC_HIGH_QOS, &cbData, NULL, 0);
1849     if (OC_STACK_OK != ret)
1850     {
1851         OICFree(pconfData->resArr);
1852         OICFree(pconfData);
1853     }
1854     VERIFY_SUCCESS_RETURN(TAG, (OC_STACK_OK == ret), ERROR, OC_STACK_ERROR);
1855     return OC_STACK_OK;
1856 }
1857
1858 static void DeleteUnlinkData_t(UnlinkData_t *unlinkData)
1859 {
1860     if (unlinkData)
1861     {
1862         OICFree(unlinkData->unlinkDev);
1863         OICFree(unlinkData->unlinkRes);
1864         OICFree(unlinkData);
1865     }
1866 }
1867
1868 static void registerResultForUnlinkDevices(UnlinkData_t *unlinkData, OCStackResult stackresult,
1869                                            IdxUnlinkRes_t idx)
1870 {
1871     if (NULL != unlinkData)
1872     {
1873         OIC_LOG_V(INFO, TAG, "Inside registerResultForUnlinkDevices unlinkData->numOfResults is %d",
1874                             unlinkData->numOfResults);
1875         OIC_LOG_V(INFO, TAG, "Stack result :: %d", stackresult);
1876
1877         OicUuid_t *pUuid = &unlinkData->unlinkRes[(unlinkData->numOfResults)].deviceId;
1878
1879         // Set result in the result array according to the position (devNum).
1880         if (idx != IDX_DB_UPDATE_RES)
1881         {
1882             memcpy(pUuid->id, unlinkData->unlinkDev[idx].doxm->deviceID.id, sizeof(pUuid->id));
1883         }
1884         else
1885         {   // When deivce ID is 000... this means it's the result of database update.
1886             memset(pUuid->id, 0, sizeof(pUuid->id));
1887         }
1888         unlinkData->unlinkRes[(unlinkData->numOfResults)].res = stackresult;
1889         ++(unlinkData->numOfResults);
1890         OIC_LOG (INFO, TAG, "Out registerResultForUnlinkDevices");
1891     }
1892 }
1893
1894 static OCStackResult SendDeleteCredentialRequest(void* ctx,
1895                                                  OCClientResponseHandler respHandler,
1896                                                  const OCProvisionDev_t* revokedDev,
1897                                                  const OCProvisionDev_t* destDev)
1898 {
1899     OIC_LOG(DEBUG, TAG, "IN SendDeleteCredentialRequest");
1900
1901     if (NULL == ctx || NULL == respHandler || NULL == revokedDev || NULL == destDev)
1902     {
1903         return OC_STACK_INVALID_PARAM;
1904     }
1905
1906     char *subID = NULL;
1907     OCStackResult ret = ConvertUuidToStr(&revokedDev->doxm->deviceID, &subID);
1908     if(OC_STACK_OK != ret)
1909     {
1910         OIC_LOG(ERROR, TAG, "SendDeleteCredentialRequest : Failed to canonical UUID encoding");
1911         return OC_STACK_ERROR;
1912     }
1913
1914     char addressEncoded[CA_MAX_URI_LENGTH] = {0};
1915     OCStackResult result = OCEncodeAddressForRFC6874(addressEncoded,
1916                                                      sizeof(addressEncoded),
1917                                                      destDev->endpoint.addr);
1918     if (OC_STACK_OK != result)
1919     {
1920         OIC_LOG_V(ERROR, TAG, "SendDeleteCredentialRequest : encoding error %d", result);
1921         return OC_STACK_ERROR;
1922     }
1923
1924     char reqBuf[MAX_URI_LENGTH + MAX_QUERY_LENGTH] = {0};
1925     int snRet = 0;
1926                     //coaps://0.0.0.0:5684/oic/sec/cred?subjectid=(Canonical ENCODED UUID)
1927     const char *srpUri = SRP_FORM_DELETE_CREDENTIAL;
1928 #ifdef __WITH_TLS__
1929     if((int)CA_ADAPTER_TCP == (int)destDev->endpoint.adapter)
1930     {
1931         srpUri = SRP_FORM_DELETE_CREDENTIAL_TCP;
1932     }
1933 #endif
1934
1935     snRet = snprintf(reqBuf, sizeof(reqBuf), srpUri, addressEncoded,
1936                      destDev->securePort, OIC_RSRC_CRED_URI, OIC_JSON_SUBJECTID_NAME, subID);
1937     OICFree(subID);
1938     if (snRet < 0)
1939     {
1940         OIC_LOG_V(ERROR, TAG, "SendDeleteCredentialRequest : Error (snprintf) %d", snRet);
1941         return OC_STACK_ERROR;
1942     }
1943     else if ((size_t)snRet >= sizeof(reqBuf))
1944     {
1945         OIC_LOG_V(ERROR, TAG, "SendDeleteCredentialRequest : Truncated (snprintf) %d", snRet);
1946         return OC_STACK_ERROR;
1947     }
1948
1949     OCCallbackData cbData;
1950     memset(&cbData, 0, sizeof(cbData));
1951     cbData.context = ctx;
1952     cbData.cb = respHandler;
1953     cbData.cd = NULL;
1954     OIC_LOG_V(INFO, TAG, "URI: %s",reqBuf);
1955
1956     OIC_LOG(DEBUG, TAG, "Sending remove credential request to resource server");
1957
1958     ret = OCDoResource(NULL, OC_REST_DELETE, reqBuf,
1959                                      &destDev->endpoint, NULL,
1960                                      CT_ADAPTER_IP, OC_HIGH_QOS, &cbData, NULL, 0);
1961     if (OC_STACK_OK != ret)
1962     {
1963         OIC_LOG_V(ERROR, TAG, "SendDeleteCredentialRequest : Error in OCDoResource %d", ret);
1964     }
1965     OIC_LOG(DEBUG, TAG, "OUT SendDeleteCredentialRequest");
1966
1967     return ret;
1968 }
1969
1970 static OCStackResult SendDeleteACLRequest(void* ctx,
1971                                                  OCClientResponseHandler respHandler,
1972                                                  const OCProvisionDev_t* revokedDev,
1973                                                  const OCProvisionDev_t* destDev)
1974 {
1975     OIC_LOG(DEBUG, TAG, "IN SendDeleteACLRequest");
1976
1977     if (NULL == ctx || NULL == respHandler || NULL == revokedDev || NULL == destDev)
1978     {
1979         return OC_STACK_INVALID_PARAM;
1980     }
1981
1982     char *subID = NULL;
1983     OCStackResult ret = ConvertUuidToStr(&revokedDev->doxm->deviceID, &subID);
1984     if(OC_STACK_OK != ret)
1985     {
1986         OIC_LOG(ERROR, TAG, "SendDeleteACLRequest : Failed to canonical UUID encoding");
1987         return OC_STACK_ERROR;
1988     }
1989
1990     char addressEncoded[CA_MAX_URI_LENGTH] = {0};
1991     OCStackResult result = OCEncodeAddressForRFC6874(addressEncoded,
1992                                                      sizeof(addressEncoded),
1993                                                      destDev->endpoint.addr);
1994     if (OC_STACK_OK != result)
1995     {
1996         OIC_LOG_V(ERROR, TAG, "SendDeleteCredentialRequest : encoding error %d", result);
1997         return OC_STACK_ERROR;
1998     }
1999
2000     char reqBuf[MAX_URI_LENGTH + MAX_QUERY_LENGTH] = {0};
2001     int snRet = 0;
2002                     //coaps://0.0.0.0:5684/oic/sec/acl?subjectuuid=(Canonical ENCODED UUID)
2003     snRet = snprintf(reqBuf, sizeof(reqBuf), SRP_FORM_DELETE_CREDENTIAL, addressEncoded,
2004                      destDev->securePort, OIC_RSRC_ACL2_URI, OIC_JSON_SUBJECTID_NAME, subID);
2005     OICFree(subID);
2006     if (snRet < 0)
2007     {
2008         OIC_LOG_V(ERROR, TAG, "SendDeleteACLRequest : Error (snprintf) %d", snRet);
2009         return OC_STACK_ERROR;
2010     }
2011     else if ((size_t)snRet >= sizeof(reqBuf))
2012     {
2013         OIC_LOG_V(ERROR, TAG, "SendDeleteACLRequest : Truncated (snprintf) %d", snRet);
2014         return OC_STACK_ERROR;
2015     }
2016
2017     OCCallbackData cbData;
2018     memset(&cbData, 0, sizeof(cbData));
2019     cbData.context = ctx;
2020     cbData.cb = respHandler;
2021     cbData.cd = NULL;
2022     OIC_LOG_V(INFO, TAG, "URI: %s",reqBuf);
2023
2024     OIC_LOG(DEBUG, TAG, "Sending remove ACL request to resource server");
2025
2026     ret = OCDoResource(NULL, OC_REST_DELETE, reqBuf,
2027                                      &destDev->endpoint, NULL,
2028                                      CT_ADAPTER_IP, OC_HIGH_QOS, &cbData, NULL, 0);
2029     if (OC_STACK_OK != ret)
2030     {
2031         OIC_LOG_V(ERROR, TAG, "SendDeleteACLRequest : Error in OCDoResource %d", ret);
2032     }
2033     OIC_LOG(DEBUG, TAG, "OUT SendDeleteACLRequest");
2034
2035     return ret;
2036 }
2037
2038 /**
2039  * Callback handler of unlink second device.
2040  *
2041  * @param[in] ctx             ctx value passed to callback from calling function.
2042  * @param[in] handle          handle to an invocation
2043  * @param[in] clientResponse  Response from queries to remote servers.
2044  * @return  OC_STACK_DELETE_TRANSACTION to delete the transaction and
2045  *          OC_STACK_KEEP_TRANSACTION to keep it.
2046  */
2047 static OCStackApplicationResult SRPUnlinkDevice2CB(void *unlinkCtx, OCDoHandle handle,
2048         OCClientResponse *clientResponse)
2049 {
2050     (void) handle;
2051     OIC_LOG(DEBUG, TAG, "IN SRPUnlinkDevice2CB");
2052     VERIFY_NOT_NULL_RETURN(TAG, unlinkCtx, ERROR, OC_STACK_DELETE_TRANSACTION);
2053     UnlinkData_t* unlinkData = (UnlinkData_t*)unlinkCtx;
2054
2055     if (clientResponse)
2056     {
2057         OIC_LOG(DEBUG, TAG, "Valid client response for device 2");
2058         registerResultForUnlinkDevices(unlinkData, clientResponse->result, IDX_SECOND_DEVICE_RES);
2059
2060         if (OC_STACK_RESOURCE_DELETED == clientResponse->result)
2061         {
2062             OIC_LOG(DEBUG, TAG, "Credential of device2 revoked");
2063         }
2064         else
2065         {
2066             OIC_LOG(ERROR, TAG, "Unable to delete credential information from device 2");
2067             unlinkData->resultCallback(unlinkData->ctx,
2068                                        unlinkData->numOfResults, unlinkData->unlinkRes, true);
2069             goto error;
2070         }
2071     }
2072     else
2073     {
2074         registerResultForUnlinkDevices(unlinkData, OC_STACK_INVALID_REQUEST_HANDLE,
2075                                        IDX_SECOND_DEVICE_RES);
2076         unlinkData->resultCallback(unlinkData->ctx,
2077                                    unlinkData->numOfResults, unlinkData->unlinkRes, true);
2078         OIC_LOG(ERROR, TAG, "SRPUnlinkDevice2CB received Null clientResponse");
2079         goto error;
2080     }
2081
2082     //Update provisioning DB when succes case.
2083     if (OC_STACK_OK != PDMUnlinkDevices(&unlinkData->unlinkDev[0].doxm->deviceID,
2084                                        &unlinkData->unlinkDev[1].doxm->deviceID))
2085     {
2086         OIC_LOG(FATAL, TAG, "All requests are successfully done but update provisioning DB FAILED.");
2087         registerResultForUnlinkDevices(unlinkData, OC_STACK_INCONSISTENT_DB, IDX_DB_UPDATE_RES);
2088         unlinkData->resultCallback(unlinkData->ctx,
2089                                    unlinkData->numOfResults, unlinkData->unlinkRes, true);
2090         goto error;
2091     }
2092     unlinkData->resultCallback(unlinkData->ctx, unlinkData->numOfResults, unlinkData->unlinkRes,
2093                                false);
2094
2095 error:
2096     DeleteUnlinkData_t(unlinkData);
2097     OIC_LOG(DEBUG, TAG, "OUT SRPUnlinkDevice2CB");
2098     return OC_STACK_DELETE_TRANSACTION;
2099
2100 }
2101
2102 /**
2103  * Callback handler of unlink first device.
2104  *
2105  * @param[in] ctx             ctx value passed to callback from calling function.
2106  * @param[in] handle          handle to an invocation
2107  * @param[in] clientResponse  Response from queries to remote servers.
2108  * @return  OC_STACK_DELETE_TRANSACTION to delete the transaction and
2109  *          OC_STACK_KEEP_TRANSACTION to keep it.
2110  */
2111 static OCStackApplicationResult SRPUnlinkDevice1CB(void *unlinkCtx, OCDoHandle handle,
2112         OCClientResponse *clientResponse)
2113 {
2114     OIC_LOG_V(INFO, TAG, "Inside SRPUnlinkDevice1CB ");
2115     VERIFY_NOT_NULL_RETURN(TAG, unlinkCtx, ERROR, OC_STACK_DELETE_TRANSACTION);
2116     UnlinkData_t* unlinkData = (UnlinkData_t*)unlinkCtx;
2117     (void) handle;
2118
2119     if (clientResponse)
2120     {
2121         OIC_LOG(DEBUG, TAG, "Valid client response for device 1");
2122         registerResultForUnlinkDevices(unlinkData, clientResponse->result, IDX_FIRST_DEVICE_RES);
2123
2124         if (OC_STACK_RESOURCE_DELETED == clientResponse->result)
2125         {
2126             OIC_LOG(DEBUG, TAG, "Credential of device 1 is revoked");
2127
2128             // Second revocation request to second device.
2129             OCStackResult res = SendDeleteCredentialRequest((void*)unlinkData, &SRPUnlinkDevice2CB,
2130                                                     &unlinkData->unlinkDev[0],
2131                                                     &unlinkData->unlinkDev[1] /*Dest*/);
2132             OIC_LOG_V(DEBUG, TAG, "Credential revocation request device 2, result :: %d",res);
2133             if (OC_STACK_OK != res)
2134             {
2135                  OIC_LOG(ERROR, TAG, "Error while sending revocation request for device 2");
2136                  registerResultForUnlinkDevices(unlinkData, OC_STACK_INVALID_REQUEST_HANDLE,
2137                                                 IDX_SECOND_DEVICE_RES);
2138                  unlinkData->resultCallback(unlinkData->ctx,
2139                                             unlinkData->numOfResults, unlinkData->unlinkRes, true);
2140                  goto error;
2141             }
2142             else
2143             {
2144                 OIC_LOG(DEBUG, TAG, "Request for credential revocation successfully sent");
2145                 return OC_STACK_DELETE_TRANSACTION;
2146             }
2147         }
2148         else
2149         {
2150             OIC_LOG(ERROR, TAG, "Unable to delete credential information from device 1");
2151
2152             unlinkData->resultCallback(unlinkData->ctx, unlinkData->numOfResults,
2153                                             unlinkData->unlinkRes, true);
2154             goto error;
2155         }
2156     }
2157     else
2158     {
2159         OIC_LOG(DEBUG, TAG, "Invalid response from server");
2160         registerResultForUnlinkDevices(unlinkData, OC_STACK_INVALID_REQUEST_HANDLE,
2161                                        IDX_FIRST_DEVICE_RES );
2162         unlinkData->resultCallback(unlinkData->ctx,
2163                                    unlinkData->numOfResults, unlinkData->unlinkRes,
2164                                    true);
2165         OIC_LOG(ERROR, TAG, "SRPUnlinkDevice1CB received Null clientResponse");
2166     }
2167
2168 error:
2169     OIC_LOG_V(INFO, TAG, "Out SRPUnlinkDevice1CB");
2170     DeleteUnlinkData_t(unlinkData);
2171     return OC_STACK_DELETE_TRANSACTION;
2172 }
2173
2174 /*
2175 * Function to unlink devices.
2176 * This function will remove the credential & relationship between the two devices.
2177 *
2178 * @param[in] ctx Application context would be returned in result callback
2179 * @param[in] pTargetDev1 first device information to be unlinked.
2180 * @param[in] pTargetDev2 second device information to be unlinked.
2181 * @param[in] resultCallback callback provided by API user, callback will be called when
2182 *            device unlink is finished.
2183  * @return  OC_STACK_OK in case of success and other value otherwise.
2184 */
2185 OCStackResult SRPUnlinkDevices(void* ctx,
2186                                const OCProvisionDev_t* pTargetDev1,
2187                                const OCProvisionDev_t* pTargetDev2,
2188                                OCProvisionResultCB resultCallback)
2189 {
2190     OIC_LOG(INFO, TAG, "IN SRPUnlinkDevices");
2191
2192     if (!pTargetDev1 || !pTargetDev2 || !pTargetDev1->doxm || !pTargetDev2->doxm)
2193     {
2194         OIC_LOG(INFO, TAG, "SRPUnlinkDevices : NULL parameters");
2195         return OC_STACK_INVALID_PARAM;
2196     }
2197     if (!resultCallback)
2198     {
2199         OIC_LOG(INFO, TAG, "SRPUnlinkDevices : NULL Callback");
2200         return OC_STACK_INVALID_CALLBACK;
2201     }
2202     if (0 == memcmp(&pTargetDev1->doxm->deviceID, &pTargetDev2->doxm->deviceID, sizeof(OicUuid_t)))
2203     {
2204         OIC_LOG(INFO, TAG, "SRPUnlinkDevices : Same device ID");
2205         return OC_STACK_INVALID_PARAM;
2206     }
2207
2208     OIC_LOG(INFO, TAG, "Unlinking following devices: ");
2209     PMPrintOCProvisionDev(pTargetDev1);
2210     PMPrintOCProvisionDev(pTargetDev2);
2211
2212     // Mark the link status stale
2213     OCStackResult res = PDMSetLinkStale(&pTargetDev1->doxm->deviceID, &pTargetDev2->doxm->deviceID);
2214     if (OC_STACK_OK != res)
2215     {
2216         OIC_LOG(FATAL, TAG, "unable to update DB. Try again.");
2217         return res;
2218     }
2219
2220     UnlinkData_t* unlinkData = (UnlinkData_t*)OICCalloc(1, sizeof(UnlinkData_t));
2221     VERIFY_NOT_NULL_RETURN(TAG, unlinkData, ERROR, OC_STACK_NO_MEMORY);
2222
2223     //Initialize unlink data
2224     unlinkData->ctx = ctx;
2225     unlinkData->unlinkDev = (OCProvisionDev_t*)OICCalloc(2, sizeof(OCProvisionDev_t));
2226     if (NULL == unlinkData->unlinkDev)
2227     {
2228         OIC_LOG(ERROR, TAG, "Memory allocation failed");
2229         res = OC_STACK_NO_MEMORY;
2230         goto error;
2231     }
2232
2233     unlinkData->unlinkRes = (OCProvisionResult_t*)OICCalloc(3, sizeof(OCProvisionResult_t));
2234     if (NULL == unlinkData->unlinkRes)
2235     {
2236         OIC_LOG(ERROR, TAG, "Memory allocation failed");
2237         res = OC_STACK_NO_MEMORY;
2238         goto error;
2239     }
2240
2241     memcpy(&unlinkData->unlinkDev[0], pTargetDev1, sizeof(OCProvisionDev_t));
2242     memcpy(&unlinkData->unlinkDev[1], pTargetDev2, sizeof(OCProvisionDev_t));
2243
2244     unlinkData->numOfResults = 0;
2245     unlinkData->resultCallback = resultCallback;
2246
2247     res = SendDeleteCredentialRequest((void*)unlinkData, &SRPUnlinkDevice1CB,
2248                                        &unlinkData->unlinkDev[1], &unlinkData->unlinkDev[0]);
2249     if (OC_STACK_OK != res)
2250     {
2251         OIC_LOG(ERROR, TAG, "SRPUnlinkDevices : SendDeleteCredentialRequest failed");
2252         goto error;
2253     }
2254
2255     return res;
2256
2257 error:
2258     OIC_LOG(INFO, TAG, "OUT SRPUnlinkDevices");
2259     DeleteUnlinkData_t(unlinkData);
2260     return res;
2261 }
2262
2263 static void DeleteRemoveData_t(RemoveData_t* pRemoveData)
2264 {
2265     if (pRemoveData)
2266     {
2267         OICFree(pRemoveData->revokeTargetDev);
2268         OCDeleteDiscoveredDevices(pRemoveData->linkedDevList);
2269         OICFree(pRemoveData->removeRes);
2270         OICFree(pRemoveData);
2271     }
2272 }
2273
2274 static void registerResultForRemoveDevice(RemoveData_t *removeData, OicUuid_t *pLinkedDevId,
2275                                           OCStackResult stackresult, bool hasError)
2276 {
2277     OIC_LOG_V(INFO, TAG, "Inside registerResultForRemoveDevice removeData->numOfResults is %" PRIuPTR,
2278                          removeData->numOfResults + 1);
2279     if (pLinkedDevId)
2280     {
2281         memcpy(removeData->removeRes[(removeData->numOfResults)].deviceId.id,
2282                &pLinkedDevId->id, sizeof(pLinkedDevId->id));
2283     }
2284     else
2285     {
2286         memset(removeData->removeRes[(removeData->numOfResults)].deviceId.id,
2287                0, sizeof(pLinkedDevId->id) );
2288     }
2289     removeData->removeRes[(removeData->numOfResults)].res = stackresult;
2290     removeData->hasError = hasError;
2291     ++(removeData->numOfResults);
2292
2293     // If we get suffcient result from linked devices, we have to call user callback and do free
2294     if (removeData->sizeOfResArray == removeData->numOfResults)
2295     {
2296         if(!removeData->hasError)
2297         {
2298             // Remove device info from prvisioning database
2299             if (OC_STACK_OK != PDMDeleteDevice(&removeData->revokeTargetDev->doxm->deviceID))
2300             {
2301                 OIC_LOG(ERROR, TAG, "ResultForRemoveDevice : Failed to remove device in PDM.");
2302                 removeData->hasError = true;
2303             }
2304         }
2305         removeData->resultCallback(removeData->ctx, removeData->numOfResults, removeData->removeRes,
2306                                    removeData->hasError);
2307         DeleteRemoveData_t(removeData);
2308     }
2309  }
2310
2311 static void registerResultForResetDevice(RemoveData_t *removeData, OicUuid_t *pLinkedDevId,
2312                                           OCStackResult stackresult, bool hasError)
2313 {
2314     OIC_LOG_V(INFO, TAG, "Inside registerResultForResetDevice removeData->numOfResults is %" PRIuPTR,
2315                          removeData->numOfResults + 1);
2316     if (pLinkedDevId)
2317     {
2318         memcpy(removeData->removeRes[(removeData->numOfResults)].deviceId.id,
2319                &pLinkedDevId->id, sizeof(pLinkedDevId->id));
2320     }
2321     else
2322     {
2323         memset(removeData->removeRes[(removeData->numOfResults)].deviceId.id,
2324                0, sizeof(pLinkedDevId->id) );
2325     }
2326     removeData->removeRes[(removeData->numOfResults)].res = stackresult;
2327     removeData->hasError = hasError;
2328     ++(removeData->numOfResults);
2329
2330     // If we get suffcient result from linked devices, we have to call user callback and do free
2331     if (removeData->sizeOfResArray == removeData->numOfResults)
2332     {
2333         removeData->resultCallback(removeData->ctx, removeData->numOfResults, removeData->removeRes,
2334                                    removeData->hasError);
2335         DeleteRemoveData_t(removeData);
2336     }
2337 }
2338
2339 /**
2340  * Callback handler of unlink first device.
2341  *
2342  * @param[in] ctx             ctx value passed to callback from calling function.
2343  * @param[in] handle          handle to an invocation
2344  * @param[in] clientResponse  Response from queries to remote servers.
2345  * @return  OC_STACK_DELETE_TRANSACTION to delete the transaction
2346  *          and  OC_STACK_KEEP_TRANSACTION to keep it.
2347  */
2348 static OCStackApplicationResult SRPRemoveDeviceCB(void *delDevCtx, OCDoHandle handle,
2349         OCClientResponse *clientResponse)
2350 {
2351     //Update the delete credential into delete device context
2352     //Save the deleted status in delDevCtx
2353     (void)handle;
2354     OIC_LOG_V(INFO, TAG, "Inside SRPRemoveDeviceCB.");
2355     VERIFY_NOT_NULL_RETURN(TAG, delDevCtx, ERROR, OC_STACK_DELETE_TRANSACTION);
2356     OCStackResult res = OC_STACK_ERROR;
2357
2358     RemoveData_t* removeData = (RemoveData_t*)delDevCtx;
2359
2360     if (clientResponse)
2361     {
2362         OicUuid_t revDevUuid = {.id={0}};
2363         if(UUID_LENGTH == clientResponse->identity.id_length)
2364         {
2365             memcpy(revDevUuid.id, clientResponse->identity.id, sizeof(revDevUuid.id));
2366             if (OC_STACK_RESOURCE_DELETED == clientResponse->result)
2367             {
2368                 res = PDMUnlinkDevices(&removeData->revokeTargetDev->doxm->deviceID, &revDevUuid);
2369                 if (OC_STACK_OK != res)
2370                 {
2371                     OIC_LOG(ERROR, TAG, "PDMSetLinkStale() FAIL: PDB is an obsolete one.");
2372                            registerResultForRemoveDevice(removeData, &revDevUuid,
2373                            OC_STACK_INCONSISTENT_DB, true);
2374
2375                     return OC_STACK_DELETE_TRANSACTION;
2376                 }
2377
2378                 registerResultForRemoveDevice(removeData, &revDevUuid,
2379                                               OC_STACK_RESOURCE_DELETED, false);
2380             }
2381             else
2382             {
2383                 registerResultForRemoveDevice(removeData, &revDevUuid,
2384                                               clientResponse->result, true);
2385                 OIC_LOG(ERROR, TAG, "Unexpected result from DELETE credential request!");
2386             }
2387         }
2388         else
2389         {
2390             OIC_LOG_V(WARNING, TAG, "Incorrect length of device UUID was sent from %s:%d",
2391                      clientResponse->devAddr.addr, clientResponse->devAddr.port);
2392
2393             if (OC_STACK_RESOURCE_DELETED == clientResponse->result)
2394             {
2395                 /**
2396                   * Since server's credential was deleted,
2397                   * register result as OC_STACK_INCONSISTENT_DB with NULL UUID.
2398                   */
2399                 OIC_LOG_V(ERROR, TAG, "But server's credential was deleted.");
2400                 registerResultForRemoveDevice(removeData, NULL, OC_STACK_INCONSISTENT_DB, true);
2401             }
2402             else
2403             {
2404                 registerResultForRemoveDevice(removeData, NULL, clientResponse->result, true);
2405             }
2406         }
2407     }
2408     else
2409     {
2410         registerResultForRemoveDevice(removeData, NULL, OC_STACK_ERROR, true);
2411         OIC_LOG(ERROR, TAG, "SRPRemoveDevices received Null clientResponse");
2412     }
2413
2414     return OC_STACK_DELETE_TRANSACTION;
2415 }
2416
2417 /**
2418  * Callback handler of reset device.
2419  *
2420  * @param[in] ctx             ctx value passed to callback from calling function.
2421  * @param[in] handle          handle to an invocation
2422  * @param[in] clientResponse  Response from queries to remote servers.
2423  * @return  OC_STACK_DELETE_TRANSACTION to delete the transaction
2424  *          and  OC_STACK_KEEP_TRANSACTION to keep it.
2425  */
2426 static OCStackApplicationResult SRPSyncDeviceCredCB(void *delDevCtx, OCDoHandle handle,
2427         OCClientResponse *clientResponse)
2428 {
2429     //Update the delete credential into delete device context
2430     //Save the deleted status in delDevCtx
2431     (void)handle;
2432     OIC_LOG_V(INFO, TAG, "Inside SRPSyncDeviceCredCB.");
2433     VERIFY_NOT_NULL_RETURN(TAG, delDevCtx, ERROR, OC_STACK_DELETE_TRANSACTION);
2434     OCStackResult res = OC_STACK_ERROR;
2435
2436     RemoveData_t* removeData = (RemoveData_t*)delDevCtx;
2437     OCProvisionDev_t * pTargetDev = PMCloneOCProvisionDev(removeData->revokeTargetDev);
2438     OCProvisionResultCB resultCallback = removeData->resultCallback;
2439     if (clientResponse)
2440     {
2441         OicUuid_t revDevUuid = {.id={0}};
2442         if(UUID_LENGTH == clientResponse->identity.id_length)
2443         {
2444             memcpy(revDevUuid.id, clientResponse->identity.id, sizeof(revDevUuid.id));
2445             if (OC_STACK_RESOURCE_DELETED == clientResponse->result)
2446             {
2447                 res = PDMUnlinkDevices(&removeData->revokeTargetDev->doxm->deviceID, &revDevUuid);
2448                 if (OC_STACK_OK != res)
2449                 {
2450                     OIC_LOG(ERROR, TAG, "PDMSetLinkStale() FAIL: PDB is an obsolete one.");
2451                            registerResultForResetDevice(removeData, &revDevUuid,
2452                            OC_STACK_INCONSISTENT_DB, true);
2453
2454                     return OC_STACK_DELETE_TRANSACTION;
2455                 }
2456
2457                 registerResultForResetDevice(removeData, &revDevUuid,
2458                                               OC_STACK_RESOURCE_DELETED, false);
2459             }
2460             else
2461             {
2462                 registerResultForResetDevice(removeData, &revDevUuid,
2463                                               clientResponse->result, false);
2464                 OIC_LOG(ERROR, TAG, "Unexpected result from DELETE credential request!");
2465             }
2466         }
2467         else
2468         {
2469             OIC_LOG_V(WARNING, TAG, "Incorrect length of device UUID was sent from %s:%d",
2470                      clientResponse->devAddr.addr, clientResponse->devAddr.port);
2471
2472             if (OC_STACK_RESOURCE_DELETED == clientResponse->result)
2473             {
2474                 /**
2475                   * Since server's credential was deleted,
2476                   * register result as OC_STACK_INCONSISTENT_DB with NULL UUID.
2477                   */
2478                 OIC_LOG_V(ERROR, TAG, "But server's credential was deleted.");
2479                 registerResultForResetDevice(removeData, NULL, OC_STACK_INCONSISTENT_DB, true);
2480             }
2481             else
2482             {
2483                 registerResultForResetDevice(removeData, NULL, clientResponse->result, true);
2484             }
2485         }
2486     }
2487     else
2488     {
2489         registerResultForResetDevice(removeData, NULL, OC_STACK_ERROR, true);
2490         OIC_LOG(ERROR, TAG, "SRPSyncDevice received Null clientResponse");
2491     }
2492
2493     SRPResetDevice(pTargetDev, resultCallback);
2494
2495     return OC_STACK_DELETE_TRANSACTION;
2496 }
2497
2498 /**
2499  * Callback handler of reset device sync-up
2500  *
2501  * @param[in] ctx             ctx value passed to callback from calling function.
2502  * @param[in] handle          handle to an invocation
2503  * @param[in] clientResponse  Response from queries to remote servers.
2504  * @return  OC_STACK_DELETE_TRANSACTION to delete the transaction
2505  *          and  OC_STACK_KEEP_TRANSACTION to keep it.
2506  */
2507 static OCStackApplicationResult SRPSyncDeviceACLCB(void *ctx, OCDoHandle UNUSED,
2508         OCClientResponse *clientResponse)
2509 {
2510     (void)ctx;
2511     (void)UNUSED;
2512     (void)clientResponse;
2513     return OC_STACK_DELETE_TRANSACTION;
2514 }
2515
2516 /**
2517  * Callback handler of device remote reset.
2518  *
2519  * @param[in] ctx             ctx value passed to callback from calling function.
2520  * @param[in] UNUSED          handle to an invocation
2521  * @param[in] clientResponse  Response from queries to remote servers.
2522  * @return  OC_STACK_DELETE_TRANSACTION to delete the transaction
2523  *          and  OC_STACK_KEEP_TRANSACTION to keep it.
2524  */
2525 static OCStackApplicationResult SRPResetDeviceCB(void *ctx, OCDoHandle UNUSED,
2526         OCClientResponse *clientResponse)
2527 {
2528     OIC_LOG(DEBUG, TAG, "IN SRPResetDeviceCB");
2529     (void)UNUSED;
2530     if(OC_STACK_OK == clientResponse->result)
2531     {
2532         OIC_LOG(DEBUG, TAG, "Change Target Device Pstat Cm SUCCEEDED");
2533     }
2534
2535     // Delete Cred and ACL related to the target device.
2536     const OicSecCred_t *cred = NULL;
2537     OCProvisionDev_t * pTargetDev = (OCProvisionDev_t *)ctx;
2538     cred = GetCredResourceData(&pTargetDev->doxm->deviceID);
2539     if (cred == NULL)
2540     {
2541         OIC_LOG(ERROR, TAG, "OCResetDevice : Failed to get credential of target device.");
2542         goto error;
2543     }
2544
2545     OCStackResult res = RemoveCredential(&cred->subject);
2546     if (res != OC_STACK_RESOURCE_DELETED && res != OC_STACK_NO_RESOURCE)
2547     {
2548         OIC_LOG(ERROR, TAG, "OCResetDevice : Failed to remove credential.");
2549         goto error;
2550     }
2551
2552     res = RemoveACE(&cred->subject, NULL);
2553     if (res != OC_STACK_RESOURCE_DELETED && res != OC_STACK_NO_RESOURCE)
2554     {
2555         OIC_LOG(ERROR, TAG, "OCResetDevice : Failed to remove ACL.");
2556         goto error;
2557     }
2558     if (OC_STACK_OK != PDMDeleteDevice(&pTargetDev->doxm->deviceID))
2559     {
2560         OIC_LOG(ERROR, TAG, "OCResetDevice : Failed to delete device from PDM");
2561     }
2562
2563     //Close the DTLS session of the reset device.
2564     CAEndpoint_t* endpoint = (CAEndpoint_t *)&clientResponse->devAddr;
2565     CAResult_t caResult = CAcloseSslSession(endpoint);
2566     if(CA_STATUS_OK != caResult)
2567     {
2568         OIC_LOG_V(WARNING, TAG, "OCResetDevice : Failed to close DTLS session : %d", caResult);
2569     }
2570
2571     /**
2572      * If there is no linked device, PM does not send any request.
2573      * So we should directly invoke the result callback to inform the result of OCResetDevice.
2574      */
2575     if(OC_STACK_NO_RESOURCE == res)
2576     {
2577         res = OC_STACK_OK;
2578     }
2579
2580 error:
2581     OICFree(pTargetDev);
2582     return OC_STACK_DELETE_TRANSACTION;
2583
2584 }
2585
2586 static OCStackResult GetListofDevToReqDeleteCred(const OCProvisionDev_t* pRevokeTargetDev,
2587                                                  const OCProvisionDev_t* pOwnedDevList,
2588                                                  OCUuidList_t* pLinkedUuidList,
2589                                                  OCProvisionDev_t** ppLinkedDevList,
2590                                                  size_t *numOfLinkedDev)
2591 {
2592     // pOwnedDevList could be NULL. It means no alived and owned device now.
2593     if (pRevokeTargetDev == NULL || pLinkedUuidList == NULL ||\
2594         ppLinkedDevList == NULL || numOfLinkedDev == NULL)
2595     {
2596         return OC_STACK_INVALID_PARAM;
2597     }
2598
2599     size_t cnt = 0;
2600     OCUuidList_t *curUuid = NULL, *tmpUuid = NULL;
2601     LL_FOREACH_SAFE(pLinkedUuidList, curUuid, tmpUuid)
2602     {
2603         // Mark the link status stale.
2604         OCStackResult res = PDMSetLinkStale(&curUuid->dev, &pRevokeTargetDev->doxm->deviceID);
2605         if (OC_STACK_OK != res)
2606         {
2607             OIC_LOG(FATAL, TAG, "PDMSetLinkStale() FAIL: PDB is an obsolete one.");
2608             return OC_STACK_INCONSISTENT_DB;
2609         }
2610
2611         if (pOwnedDevList)
2612         {
2613             // If this linked device is alive (power-on), add the deivce to the list.
2614             const OCProvisionDev_t *curDev = NULL;
2615             const OCProvisionDev_t *tmpDev = NULL;
2616             LL_FOREACH_SAFE(pOwnedDevList, curDev, tmpDev)
2617             {
2618                 if (memcmp(curDev->doxm->deviceID.id, curUuid->dev.id, sizeof(curUuid->dev.id)) == 0)
2619                 {
2620                     OCProvisionDev_t* targetDev = PMCloneOCProvisionDev(curDev);
2621                     if (NULL == targetDev)
2622                     {
2623                         OIC_LOG(ERROR, TAG, "SRPRemoveDevice : Cloning OCProvisionDev_t Failed.");
2624                         return OC_STACK_NO_MEMORY;
2625                     }
2626
2627                     LL_PREPEND(*ppLinkedDevList, targetDev);
2628                     cnt++;
2629                     break;
2630                 }
2631             }
2632         }
2633     }
2634     *numOfLinkedDev = cnt;
2635     return OC_STACK_OK;
2636 }
2637
2638 /*
2639 * Function to device revocation
2640 * This function will remove credential of target device from all devices in subnet.
2641 *
2642 * @param[in] ctx Application context would be returned in result callback
2643 * @param[in] waitTimeForOwnedDeviceDiscovery Maximum wait time for owned device discovery.(seconds)
2644 * @param[in] pTargetDev Device information to be revoked.
2645 * @param[in] resultCallback callback provided by API user, callback will be called when
2646 *            credential revocation is finished.
2647 * @return  OC_STACK_OK in case of success and other value otherwise.
2648 *          If OC_STACK_OK is returned, the caller of this API should wait for callback.
2649 *          OC_STACK_CONTINUE means operation is success but no request is need to be initiated.
2650 */
2651 OCStackResult SRPRemoveDevice(void* ctx, unsigned short waitTimeForOwnedDeviceDiscovery,
2652                              const OCProvisionDev_t* pTargetDev, OCProvisionResultCB resultCallback)
2653 {
2654     OIC_LOG(INFO, TAG, "IN SRPRemoveDevice");
2655
2656     if (!pTargetDev  || 0 == waitTimeForOwnedDeviceDiscovery)
2657     {
2658         OIC_LOG(INFO, TAG, "SRPRemoveDevice : NULL parameters");
2659         return OC_STACK_INVALID_PARAM;
2660     }
2661     if (!resultCallback)
2662     {
2663         OIC_LOG(INFO, TAG, "SRPRemoveDevice : NULL Callback");
2664         return OC_STACK_INVALID_CALLBACK;
2665     }
2666
2667     // Declare variables in here to handle error cases with goto statement.
2668     OCProvisionDev_t* pOwnedDevList = NULL;
2669     OCProvisionDev_t* pLinkedDevList = NULL;
2670     RemoveData_t* removeData = NULL;
2671
2672     //1. Find all devices that has a credential of the revoked device
2673     OCUuidList_t* pLinkedUuidList = NULL;
2674     size_t numOfDevices = 0;
2675     OCStackResult res = OC_STACK_ERROR;
2676     res = PDMGetLinkedDevices(&pTargetDev->doxm->deviceID, &pLinkedUuidList, &numOfDevices);
2677     if (OC_STACK_OK != res)
2678     {
2679         OIC_LOG(ERROR, TAG, "SRPRemoveDevice : Failed to get linked devices information");
2680         return res;
2681     }
2682     // if there is no related device, we can skip further process.
2683     if (0 == numOfDevices)
2684     {
2685         OIC_LOG(DEBUG, TAG, "SRPRemoveDevice : No linked device found.");
2686         res = OC_STACK_CONTINUE;
2687         goto error;
2688     }
2689
2690     //2. Find owned device from the network
2691     res = PMDeviceDiscovery(waitTimeForOwnedDeviceDiscovery, true, &pOwnedDevList);
2692     if (OC_STACK_OK != res)
2693     {
2694         OIC_LOG(ERROR, TAG, "SRPRemoveDevice : Failed to PMDeviceDiscovery");
2695         goto error;
2696     }
2697
2698     //3. Make a list of devices to send DELETE credential request
2699     //   by comparing owned devices from provisioning database with mutlicast discovery result.
2700     size_t numOfLinkedDev = 0;
2701     res = GetListofDevToReqDeleteCred(pTargetDev, pOwnedDevList, pLinkedUuidList,
2702                                       &pLinkedDevList, &numOfLinkedDev);
2703     if (OC_STACK_OK != res)
2704     {
2705         OIC_LOG(ERROR, TAG, "SRPRemoveDevice : GetListofDevToReqDeleteCred() failed");
2706         goto error;
2707     }
2708     if (0 == numOfLinkedDev) // This case means, there is linked device but it's not alive now.
2709     {                       // So we don't have to send request message.
2710         OIC_LOG(DEBUG, TAG, "SRPRemoveDevice : No alived & linked device found.");
2711         res = OC_STACK_CONTINUE;
2712         goto error;
2713     }
2714
2715     // 4. Prepare RemoveData Context data.
2716     removeData = (RemoveData_t*)OICCalloc(1, sizeof(RemoveData_t));
2717     if (!removeData)
2718     {
2719         OIC_LOG(ERROR, TAG, "SRPRemoveDevices : Failed to allocate memory");
2720         res = OC_STACK_NO_MEMORY;
2721         goto error;
2722     }
2723
2724     removeData->revokeTargetDev = PMCloneOCProvisionDev(pTargetDev);
2725     if (!removeData->revokeTargetDev)
2726     {
2727         OIC_LOG(ERROR, TAG, "SRPRemoveDevices : PMCloneOCProvisionDev Failed");
2728         res = OC_STACK_NO_MEMORY;
2729         goto error;
2730     }
2731
2732     removeData->removeRes =
2733         (OCProvisionResult_t*)OICCalloc(numOfLinkedDev, sizeof(OCProvisionResult_t));
2734     if (!removeData->removeRes)
2735     {
2736         OIC_LOG(ERROR, TAG, "SRPRemoveDevices : Failed to allocate memory");
2737         res = OC_STACK_NO_MEMORY;
2738         goto error;
2739     }
2740
2741     removeData->ctx = ctx;
2742     removeData->linkedDevList = pLinkedDevList;
2743     removeData->resultCallback = resultCallback;
2744     removeData->numOfResults = 0;
2745     removeData->sizeOfResArray = numOfLinkedDev;
2746     removeData->hasError = false;
2747
2748     // 5. Send DELETE credential request to linked devices.
2749     OCProvisionDev_t *curDev = NULL, *tmpDev = NULL;
2750     OCStackResult totalRes = OC_STACK_ERROR;  /* variable for checking request is sent or not */
2751     LL_FOREACH_SAFE(pLinkedDevList, curDev, tmpDev)
2752     {
2753         res = SendDeleteCredentialRequest((void*)removeData, &SRPRemoveDeviceCB,
2754                                            removeData->revokeTargetDev, curDev);
2755         if (OC_STACK_OK != res)
2756         {
2757             OIC_LOG_V(ERROR, TAG, "SRPRemoveDevice : Fail to send the DELETE credential request to\
2758                      %s:%u", curDev->endpoint.addr, curDev->endpoint.port);
2759         }
2760         else
2761         {
2762             totalRes = OC_STACK_OK; // This means at least one request is successfully sent.
2763         }
2764     }
2765
2766     PDMDestoryOicUuidLinkList(pLinkedUuidList); //TODO: Modify API name to have unified convention.
2767     PMDeleteDeviceList(pOwnedDevList);
2768     OIC_LOG(INFO, TAG, "OUT SRPRemoveDevice");
2769
2770     return totalRes; // Caller of this API should wait callback if totalRes == OC_STACK_OK.
2771
2772 error:
2773     PDMDestoryOicUuidLinkList(pLinkedUuidList);
2774     PMDeleteDeviceList(pOwnedDevList);
2775     PMDeleteDeviceList(pLinkedDevList);
2776     if (removeData)
2777     {
2778         OICFree(removeData->revokeTargetDev);
2779         OICFree(removeData->removeRes);
2780         OICFree(removeData);
2781     }
2782     OIC_LOG(INFO, TAG, "OUT ERROR case SRPRemoveDevice");
2783     return res;
2784 }
2785
2786 /*
2787 * Function to device revocation
2788 * This function will remove credential of target device from all devices in subnet.
2789 *
2790 * @param[in] ctx Application context would be returned in result callback
2791 * @param[in] pOwnedDevList List of owned devices
2792 * @param[in] pTargetDev Device information to be revoked.
2793 * @param[in] resultCallback callback provided by API user, callback will be called when
2794 *            credential revocation is finished.
2795 * @return  OC_STACK_OK in case of success and other value otherwise.
2796 *          If OC_STACK_OK is returned, the caller of this API should wait for callback.
2797 *          OC_STACK_CONTINUE means operation is success but no request is need to be initiated.
2798 */
2799 OCStackResult SRPRemoveDeviceWithoutDiscovery(void* ctx, const OCProvisionDev_t* pOwnedDevList,
2800                              const OCProvisionDev_t* pTargetDev, OCProvisionResultCB resultCallback)
2801 {
2802     OIC_LOG(INFO, TAG, "IN SRPRemoveDeviceWithoutDiscovery");
2803
2804     if (!pOwnedDevList)
2805     {
2806         OIC_LOG(WARNING, TAG, "SRPRemoveDeviceWithoutDiscovery : Owned Device List is empty");
2807         return OC_STACK_CONTINUE;
2808     }
2809     if (!pTargetDev)
2810     {
2811         OIC_LOG(INFO, TAG, "SRPRemoveDeviceWithoutDiscovery : NULL parameters");
2812         return OC_STACK_INVALID_PARAM;
2813     }
2814     if (!resultCallback)
2815     {
2816         OIC_LOG(INFO, TAG, "SRPRemoveDeviceWithoutDiscovery : NULL Callback");
2817         return OC_STACK_INVALID_CALLBACK;
2818     }
2819
2820     // Declare variables in here to handle error cases with goto statement.
2821     OCProvisionDev_t* pLinkedDevList = NULL;
2822     RemoveData_t* removeData = NULL;
2823
2824     //1. Find all devices that has a credential of the revoked device
2825     OCUuidList_t* pLinkedUuidList = NULL;
2826     size_t numOfDevices = 0;
2827     OCStackResult res = OC_STACK_ERROR;
2828     res = PDMGetLinkedDevices(&pTargetDev->doxm->deviceID, &pLinkedUuidList, &numOfDevices);
2829     if (OC_STACK_OK != res)
2830     {
2831         OIC_LOG(WARNING, TAG, "SRPRemoveDeviceWithoutDiscovery : Failed to get linked devices information");
2832         return OC_STACK_CONTINUE;
2833     }
2834     // if there is no related device, we can skip further process.
2835     if (0 == numOfDevices)
2836     {
2837         OIC_LOG(WARNING, TAG, "SRPRemoveDeviceWithoutDiscovery : No linked device found.");
2838         return OC_STACK_CONTINUE;
2839     }
2840
2841     //2. Make a list of devices to send DELETE credential request
2842     //   by comparing owned devices from provisioning database with mutlicast discovery result.
2843     size_t numOfLinkedDev = 0;
2844     res = GetListofDevToReqDeleteCred(pTargetDev, pOwnedDevList, pLinkedUuidList,
2845                                       &pLinkedDevList, &numOfLinkedDev);
2846     if (OC_STACK_OK != res)
2847     {
2848         OIC_LOG(ERROR, TAG, "SRPRemoveDeviceWithoutDiscovery : GetListofDevToReqDeleteCred() failed");
2849         goto error;
2850     }
2851     if (0 == numOfLinkedDev) // This case means, there is linked device but it's not alive now.
2852     {                       // So we don't have to send request message.
2853         OIC_LOG(DEBUG, TAG, "SRPRemoveDeviceWithoutDiscovery : No alived & linked device found.");
2854         return OC_STACK_CONTINUE;
2855     }
2856
2857     // 3. Prepare RemoveData Context data.
2858     removeData = (RemoveData_t*)OICCalloc(1, sizeof(RemoveData_t));
2859     if (!removeData)
2860     {
2861         OIC_LOG(ERROR, TAG, "SRPRemoveDeviceWithoutDiscovery : Failed to allocate memory");
2862         res = OC_STACK_NO_MEMORY;
2863         goto error;
2864     }
2865
2866     removeData->revokeTargetDev = PMCloneOCProvisionDev(pTargetDev);
2867     if (!removeData->revokeTargetDev)
2868     {
2869         OIC_LOG(ERROR, TAG, "SRPRemoveDeviceWithoutDiscovery : PMCloneOCProvisionDev Failed");
2870         res = OC_STACK_NO_MEMORY;
2871         goto error;
2872     }
2873
2874     removeData->removeRes =
2875         (OCProvisionResult_t*)OICCalloc(numOfLinkedDev, sizeof(OCProvisionResult_t));
2876     if (!removeData->removeRes)
2877     {
2878         OIC_LOG(ERROR, TAG, "SRPRemoveDeviceWithoutDiscovery : Failed to allocate memory");
2879         res = OC_STACK_NO_MEMORY;
2880         goto error;
2881     }
2882
2883     removeData->ctx = ctx;
2884     removeData->linkedDevList = pLinkedDevList;
2885     removeData->resultCallback = resultCallback;
2886     removeData->numOfResults = 0;
2887     removeData->sizeOfResArray = numOfLinkedDev;
2888     removeData->hasError = false;
2889
2890     // 5. Send DELETE credential request to linked devices.
2891     OCProvisionDev_t *curDev = NULL, *tmpDev = NULL;
2892     OCStackResult totalRes = OC_STACK_ERROR;  /* variable for checking request is sent or not */
2893     LL_FOREACH_SAFE(pLinkedDevList, curDev, tmpDev)
2894     {
2895         res = SendDeleteCredentialRequest((void*)removeData, &SRPRemoveDeviceCB,
2896                                            removeData->revokeTargetDev, curDev);
2897         if (OC_STACK_OK != res)
2898         {
2899             OIC_LOG_V(ERROR, TAG, "SRPRemoveDeviceWithoutDiscovery : Fail to send the DELETE credential request to\
2900                      %s:%u", curDev->endpoint.addr, curDev->endpoint.port);
2901         }
2902         else
2903         {
2904             totalRes = OC_STACK_OK; // This means at least one request is successfully sent.
2905         }
2906     }
2907
2908     PDMDestoryOicUuidLinkList(pLinkedUuidList); //TODO: Modify API name to have unified convention.
2909     OIC_LOG(INFO, TAG, "OUT SRPRemoveDeviceWithoutDiscovery");
2910
2911     return totalRes; // Caller of this API should wait callback if totalRes == OC_STACK_OK.
2912
2913 error:
2914     PDMDestoryOicUuidLinkList(pLinkedUuidList);
2915     PMDeleteDeviceList(pLinkedDevList);
2916     if (removeData)
2917     {
2918         OICFree(removeData->revokeTargetDev);
2919         OICFree(removeData->removeRes);
2920         OICFree(removeData);
2921     }
2922     OIC_LOG(INFO, TAG, "OUT ERROR case SRPRemoveDeviceWithoutDiscovery");
2923     return res;
2924 }
2925
2926 /*
2927  * Function to sync-up credential and ACL of the target device.
2928  * This function will remove credential and ACL of target device from all devices in subnet.
2929  *
2930  * @param[in] ctx Application context would be returned in result callback
2931  * @param[in] waitTimeForOwnedDeviceDiscovery Maximum wait time for owned device discovery.(seconds)
2932  * @param[in] pTargetDev Device information to be revoked.
2933  * @param[in] resultCallback callback provided by API user, callback will be called when
2934  *            credential revocation is finished.
2935  *            when there is an error, this user callback is called immediately.
2936  * @return OC_STACK_OK in case of success and other value otherwise.
2937  *         If OC_STACK_OK is returned, the caller of this API should wait for callback.
2938  *         OC_STACK_CONTINUE means operation is success but no request is need to be initiated.
2939  */
2940 OCStackResult SRPSyncDevice(void* ctx, unsigned short waitTimeForOwnedDeviceDiscovery,
2941                          const OCProvisionDev_t* pTargetDev, OCProvisionResultCB resultCallback)
2942 {
2943     OIC_LOG(INFO, TAG, "IN SRPSyncDevice");
2944     if (!pTargetDev  || 0 == waitTimeForOwnedDeviceDiscovery)
2945     {
2946         OIC_LOG(INFO, TAG, "SRPSyncDevice : NULL parameters");
2947         return OC_STACK_INVALID_PARAM;
2948     }
2949     if (!resultCallback)
2950     {
2951         OIC_LOG(INFO, TAG, "SRPSyncDevice : NULL Callback");
2952         return OC_STACK_INVALID_CALLBACK;
2953     }
2954
2955     // Declare variables in here to handle error cases with goto statement.
2956     OCProvisionDev_t* pOwnedDevList = NULL;
2957     OCProvisionDev_t* pLinkedDevList = NULL;
2958     RemoveData_t* removeData = NULL;
2959
2960     //1. Find all devices that has a credential of the revoked device
2961     OCUuidList_t* pLinkedUuidList = NULL;
2962     size_t numOfDevices = 0;
2963     OCStackResult res = OC_STACK_ERROR;
2964     res = PDMGetLinkedDevices(&pTargetDev->doxm->deviceID, &pLinkedUuidList, &numOfDevices);
2965     if (OC_STACK_OK != res)
2966     {
2967         OIC_LOG(ERROR, TAG, "SRPSyncDevice : Failed to get linked devices information");
2968         return res;
2969     }
2970     // if there is no related device, we can skip further process.
2971     if (0 == numOfDevices)
2972     {
2973         OIC_LOG(DEBUG, TAG, "SRPSyncDevice : No linked device found.");
2974         res = OC_STACK_CONTINUE;
2975         goto error;
2976     }
2977
2978     //2. Find owned device from the network
2979     res = PMDeviceDiscovery(waitTimeForOwnedDeviceDiscovery, true, &pOwnedDevList);
2980     if (OC_STACK_OK != res)
2981     {
2982         OIC_LOG(ERROR, TAG, "SRPSyncDevice : Failed to PMDeviceDiscovery");
2983         goto error;
2984     }
2985
2986     //3. Make a list of devices to send DELETE credential request
2987     //   by comparing owned devices from provisioning database with mutlicast discovery result.
2988     size_t numOfLinkedDev = 0;
2989     res = GetListofDevToReqDeleteCred(pTargetDev, pOwnedDevList, pLinkedUuidList,
2990                                       &pLinkedDevList, &numOfLinkedDev);
2991     if (OC_STACK_OK != res)
2992     {
2993         OIC_LOG(ERROR, TAG, "SRPSyncDevice : GetListofDevToReqDeleteCred() failed");
2994         goto error;
2995     }
2996     if (0 == numOfLinkedDev) // This case means, there is linked device but it's not alive now.
2997     {                       // So we don't have to send request message.
2998         OIC_LOG(DEBUG, TAG, "SRPSyncDevice : No alived & linked device found.");
2999         res = OC_STACK_CONTINUE;
3000         goto error;
3001     }
3002
3003     // 4. Prepare RemoveData Context data.
3004     removeData = (RemoveData_t*)OICCalloc(1, sizeof(RemoveData_t));
3005     if (!removeData)
3006     {
3007         OIC_LOG(ERROR, TAG, "SRPSyncDevice : Failed to allocate memory");
3008         res = OC_STACK_NO_MEMORY;
3009         goto error;
3010     }
3011
3012     removeData->revokeTargetDev = PMCloneOCProvisionDev(pTargetDev);
3013     if (!removeData->revokeTargetDev)
3014     {
3015         OIC_LOG(ERROR, TAG, "SRPSyncDevice : PMCloneOCProvisionDev Failed");
3016         res = OC_STACK_NO_MEMORY;
3017         goto error;
3018     }
3019
3020     removeData->removeRes =
3021         (OCProvisionResult_t*)OICCalloc(numOfLinkedDev, sizeof(OCProvisionResult_t));
3022     if (!removeData->removeRes)
3023     {
3024         OIC_LOG(ERROR, TAG, "SRPSyncDevice : Failed to allocate memory");
3025         res = OC_STACK_NO_MEMORY;
3026         goto error;
3027     }
3028
3029     removeData->ctx = ctx;
3030     removeData->linkedDevList = pLinkedDevList;
3031     removeData->resultCallback = resultCallback;
3032     removeData->numOfResults = 0;
3033     removeData->sizeOfResArray = numOfLinkedDev;
3034     removeData->hasError = false;
3035
3036     // 5. Send DELETE credential request to linked devices.
3037     OCProvisionDev_t *curDev = NULL, *tmpDev = NULL;
3038     OCStackResult totalRes = OC_STACK_ERROR;  /* variable for checking request is sent or not */
3039     LL_FOREACH_SAFE(pLinkedDevList, curDev, tmpDev)
3040     {
3041         res = SendDeleteACLRequest((void*)removeData, &SRPSyncDeviceACLCB,
3042                                            removeData->revokeTargetDev, curDev);
3043         if (OC_STACK_OK != res)
3044         {
3045             OIC_LOG_V(ERROR, TAG, "SRPSyncDevice : Fail to send the DELETE ACL request to\
3046                      %s:%u", curDev->endpoint.addr, curDev->endpoint.port);
3047             goto error;
3048         }
3049         res = SendDeleteCredentialRequest((void*)removeData, &SRPSyncDeviceCredCB,
3050                                            removeData->revokeTargetDev, curDev);
3051         if (OC_STACK_OK != res)
3052         {
3053             OIC_LOG_V(ERROR, TAG, "SRPSyncDevice : Fail to send the DELETE credential request to\
3054                      %s:%u", curDev->endpoint.addr, curDev->endpoint.port);
3055             totalRes = OC_STACK_ERROR;
3056         }
3057         else
3058         {
3059             totalRes = OC_STACK_OK; // This means at least one request is successfully sent.
3060         }
3061     }
3062
3063     PDMDestoryOicUuidLinkList(pLinkedUuidList); //TODO: Modify API name to have unified convention.
3064     PMDeleteDeviceList(pOwnedDevList);
3065     OIC_LOG(INFO, TAG, "OUT SRPSyncDevice");
3066
3067     return totalRes; // Caller of this API should wait callback if totalRes == OC_STACK_OK.
3068
3069 error:
3070     PDMDestoryOicUuidLinkList(pLinkedUuidList);
3071     PMDeleteDeviceList(pOwnedDevList);
3072     PMDeleteDeviceList(pLinkedDevList);
3073     if (removeData)
3074     {
3075         OICFree(removeData->revokeTargetDev);
3076         OICFree(removeData->removeRes);
3077         OICFree(removeData);
3078     }
3079     OIC_LOG(INFO, TAG, "OUT ERROR case SRPSyncDevice");
3080     return res;
3081 }
3082
3083 /*
3084  * Function for remote reset
3085  * This function will send pstat PUT message to the target device to initiate remote reset.
3086  *
3087  * @param[in] pTargetDev Device information to be revoked.
3088  * @param[in] resultCallback callback provided by API user, callback will be called when
3089  *            credential revocation is finished.
3090  *            when there is an error, this user callback is called immediately.
3091  * @return OC_STACK_OK in case of success and other value otherwise.
3092  *         If OC_STACK_OK is returned, the caller of this API should wait for callback.
3093  *         OC_STACK_CONTINUE means operation is success but no request is need to be initiated.
3094  */
3095 OCStackResult SRPResetDevice(const OCProvisionDev_t* pTargetDev,
3096         OCProvisionResultCB resultCallback)
3097 {
3098     OIC_LOG(INFO, TAG, "IN SRPResetDevice");
3099     if (!pTargetDev)
3100     {
3101         OIC_LOG(INFO, TAG, "SRPResetDevice : NULL parameters");
3102         return OC_STACK_INVALID_PARAM;
3103     }
3104     if (!resultCallback)
3105     {
3106         OIC_LOG(INFO, TAG, "SRPResetDevice : NULL Callback");
3107         return OC_STACK_INVALID_CALLBACK;
3108     }
3109
3110     OCStackResult res = OC_STACK_ERROR;
3111     OicSecPstat_t * pstat = (OicSecPstat_t *) OICCalloc(1, sizeof(OicSecPstat_t));
3112     if (!pstat)
3113     {
3114         OIC_LOG(ERROR, TAG, "Failed to allocate memory");
3115         return OC_STACK_NO_MEMORY;
3116     }
3117
3118     pstat->dos.state = DOS_RESET; // TODO IOT-2052 in OCF 1.0 this is the only
3119                                   // value that needs to be set to cause RESET
3120     pstat->cm = RESET;
3121     pstat->isOp = false;
3122     pstat->tm = TAKE_OWNER;
3123     pstat->om = (OicSecDpom_t)(SINGLE_SERVICE_CLIENT_DRIVEN); // the only mode IoTivity supports currently
3124     pstat->smLen = 1;
3125     pstat->sm = (OicSecDpom_t *) OICCalloc(pstat->smLen, sizeof(OicSecDpom_t));
3126     if (NULL == pstat->sm)
3127     {
3128         OIC_LOG(ERROR, TAG, "Failed to allocate memory");
3129         OICFree(pstat);
3130         return OC_STACK_NO_MEMORY;
3131     }
3132     pstat->sm[0] = (OicSecDpom_t)(SINGLE_SERVICE_CLIENT_DRIVEN); // the only mode IoTivity supports currently
3133
3134     OCSecurityPayload * secPayload = (OCSecurityPayload *) OICCalloc(1, sizeof(OCSecurityPayload));
3135     if (!secPayload)
3136     {
3137         OIC_LOG(ERROR, TAG, "Failed to allocate memory");
3138         res = OC_STACK_NO_MEMORY;
3139         goto error;
3140     }
3141     secPayload->base.type = PAYLOAD_TYPE_SECURITY;
3142
3143     // Note [IOT-2052] all the POST payloads in the provisioningclient app
3144     // should be updated to use the Partial payload APIs for the SVRs, so they
3145     // do not include read-only Properties for the Server device current
3146     // state.
3147     bool propertiesToInclude[PSTAT_PROPERTY_COUNT];
3148     memset(propertiesToInclude, 0, sizeof(propertiesToInclude));
3149     propertiesToInclude[PSTAT_DOS] = true;
3150
3151     if (OC_STACK_OK != PstatToCBORPayloadPartial(pstat, &(secPayload->securityData),
3152                 &(secPayload->payloadSize), propertiesToInclude))
3153     {
3154         OCPayloadDestroy((OCPayload *) secPayload);
3155         OIC_LOG(ERROR, TAG, "Failed to PstatToCBORPayload");
3156         res = OC_STACK_NO_MEMORY;
3157         goto error;
3158     }
3159     OIC_LOG(DEBUG, TAG, "Created payload for pstat set");
3160     OIC_LOG_BUFFER(DEBUG, TAG, secPayload->securityData, secPayload->payloadSize);
3161
3162     char query[MAX_URI_LENGTH + MAX_QUERY_LENGTH] = {0};
3163     if (!PMGenerateQuery(true,
3164                 pTargetDev->endpoint.addr,
3165                 pTargetDev->securePort,
3166                 pTargetDev->connType,
3167                 query, sizeof(query), OIC_RSRC_PSTAT_URI))
3168     {
3169         OIC_LOG(ERROR, TAG, "SRPResetDevice : Failed to generate query");
3170         OCPayloadDestroy((OCPayload *) secPayload);
3171         res = OC_STACK_ERROR;
3172         goto error;
3173     }
3174     OIC_LOG_V(DEBUG, TAG, "Query=%s", query);
3175
3176     OCCallbackData cbData = { .context = NULL, .cb = NULL, .cd = NULL };
3177     OCMethod method = OC_REST_POST;
3178     OCDoHandle handle = NULL;
3179     OCProvisionDev_t * targetDev = PMCloneOCProvisionDev(pTargetDev);
3180     if (NULL == targetDev)
3181     {
3182         OIC_LOG(ERROR, TAG, "target dev is null");
3183         res = OC_STACK_ERROR;
3184         goto error;
3185     }
3186     cbData.cb = &SRPResetDeviceCB;
3187     cbData.context = (void *) targetDev;
3188     cbData.cd = NULL;
3189     OIC_LOG(DEBUG, TAG, "Sending PSTAT info to resource server");
3190     res = OCDoResource(&handle, method, query,
3191             &targetDev->endpoint, (OCPayload *)secPayload,
3192             targetDev->connType, OC_LOW_QOS, &cbData, NULL, 0);\
3193     if (OC_STACK_OK != res)
3194     {
3195         OIC_LOG(ERROR, TAG, "OCStack resource error");
3196     }
3197
3198 error:
3199     OICFree(pstat->sm);
3200     OICFree(pstat);
3201     OIC_LOG(INFO, TAG, "OUT SRPResetDevice");
3202     return res;
3203 }
3204
3205 /**
3206  * Internal Function to store results in result array during GetCredResourceCB.
3207  */
3208 static void registerResultForGetCredResourceCB(GetSecData_t *GetSecData,
3209                                              OCStackResult stackresult)
3210 {
3211    OIC_LOG_V(INFO, TAG, "Inside registerResultForGetCredResourceCB "
3212            "GetSecData->numOfResults is %d", GetSecData->numOfResults);
3213    memcpy(GetSecData->resArr[(GetSecData->numOfResults)].deviceId.id,
3214           GetSecData->deviceInfo->doxm->deviceID.id, UUID_LENGTH);
3215    GetSecData->resArr[(GetSecData->numOfResults)].res = stackresult;
3216    ++(GetSecData->numOfResults);
3217 }
3218
3219 /**
3220  * Callback handler of SRPGetCredResource.
3221  *
3222  * @param[in] ctx             ctx value passed to callback from calling function.
3223  * @param[in] UNUSED          handle to an invocation
3224  * @param[in] clientResponse  Response from queries to remote servers.
3225  * @return  OC_STACK_DELETE_TRANSACTION to delete the transaction
3226  *          and  OC_STACK_KEEP_TRANSACTION to keep it.
3227  */
3228 static OCStackApplicationResult SRPGetCredResourceCB(void *ctx, OCDoHandle UNUSED,
3229                                                   OCClientResponse *clientResponse)
3230 {
3231     OIC_LOG_V(INFO, TAG, "Inside SRPGetCredResourceCB.");
3232     (void)UNUSED;
3233     VERIFY_NOT_NULL_RETURN(TAG, ctx, ERROR, OC_STACK_DELETE_TRANSACTION);
3234     GetSecData_t *GetSecData = (GetSecData_t*)ctx;
3235     OCProvisionResultCB resultCallback = GetSecData->resultCallback;
3236
3237     if (clientResponse)
3238     {
3239         if(OC_STACK_OK == clientResponse->result)
3240         {
3241             uint8_t *payload = ((OCSecurityPayload*)clientResponse->payload)->securityData;
3242             size_t size = ((OCSecurityPayload*)clientResponse->payload)->payloadSize;
3243
3244             OIC_LOG_BUFFER(DEBUG, TAG, payload, size);
3245             (void)size;
3246             (void)payload;
3247
3248             registerResultForGetCredResourceCB(GetSecData, OC_STACK_OK);
3249             ((OCProvisionResultCB)(resultCallback))(GetSecData->ctx, GetSecData->numOfResults,
3250                                                     GetSecData->resArr,
3251                                                     false);
3252              OICFree(GetSecData->resArr);
3253              OICFree(GetSecData);
3254
3255             return OC_STACK_DELETE_TRANSACTION;
3256         }
3257     }
3258     registerResultForGetCredResourceCB(GetSecData, OC_STACK_OK);
3259     ((OCProvisionResultCB)(resultCallback))(GetSecData->ctx, GetSecData->numOfResults,
3260                                             GetSecData->resArr,
3261                                             false);
3262     OIC_LOG_V(ERROR, TAG, "SRPGetCredResourceCB received Null clientResponse");
3263     OICFree(GetSecData->resArr);
3264     OICFree(GetSecData);
3265
3266     return OC_STACK_DELETE_TRANSACTION;
3267 }
3268
3269 OCStackResult SRPGetCredResource(void *ctx, const OCProvisionDev_t *selectedDeviceInfo,
3270         OCProvisionResultCB resultCallback)
3271 {
3272     VERIFY_NOT_NULL_RETURN(TAG, selectedDeviceInfo, ERROR,  OC_STACK_INVALID_PARAM);
3273     VERIFY_NOT_NULL_RETURN(TAG, resultCallback, ERROR,  OC_STACK_INVALID_CALLBACK);
3274
3275     char query[MAX_URI_LENGTH + MAX_QUERY_LENGTH] = {0};
3276     if(!PMGenerateQuery(true,
3277                         selectedDeviceInfo->endpoint.addr,
3278                         selectedDeviceInfo->securePort,
3279                         selectedDeviceInfo->connType,
3280                         query, sizeof(query), OIC_RSRC_CRED_URI))
3281     {
3282         OIC_LOG(ERROR, TAG, "SRPGetCredResource : Failed to generate query");
3283         return OC_STACK_ERROR;
3284     }
3285     OIC_LOG_V(DEBUG, TAG, "Query=%s", query);
3286
3287     OCCallbackData cbData =  {.context=NULL, .cb=NULL, .cd=NULL};
3288     cbData.cb = &SRPGetCredResourceCB;
3289     GetSecData_t* GetSecData = (GetSecData_t*)OICCalloc(1, sizeof(GetSecData_t));
3290     if (NULL == GetSecData)
3291     {
3292         OIC_LOG(ERROR, TAG, "Unable to allocate memory");
3293         return OC_STACK_NO_MEMORY;
3294     }
3295     GetSecData->deviceInfo = selectedDeviceInfo;
3296     GetSecData->resultCallback = resultCallback;
3297     GetSecData->numOfResults=0;
3298     GetSecData->ctx = ctx;
3299
3300     int noOfRiCalls = 1;
3301     GetSecData->resArr = (OCProvisionResult_t*)OICCalloc(noOfRiCalls, sizeof(OCProvisionResult_t));
3302     if (NULL == GetSecData->resArr)
3303     {
3304         OICFree(GetSecData);
3305         OIC_LOG(ERROR, TAG, "Unable to allocate memory");
3306         return OC_STACK_NO_MEMORY;
3307     }
3308     cbData.context = (void *)GetSecData;
3309     cbData.cd = NULL;
3310     OCMethod method = OC_REST_GET;
3311     OCDoHandle handle = NULL;
3312     OIC_LOG(DEBUG, TAG, "Sending Get Cred to  resource server");
3313     OCStackResult ret = OCDoResource(&handle, method, query, NULL, NULL,
3314             selectedDeviceInfo->connType, OC_HIGH_QOS, &cbData, NULL, 0);
3315     if (OC_STACK_OK != ret)
3316     {
3317         OIC_LOG(ERROR, TAG, "OCStack resource error");
3318         OICFree(GetSecData->resArr);
3319         OICFree(GetSecData);
3320     }
3321     VERIFY_SUCCESS_RETURN(TAG, (OC_STACK_OK == ret), ERROR, OC_STACK_ERROR);
3322     OIC_LOG(DEBUG, TAG, "OUT SRPGetCredResource");
3323
3324     return OC_STACK_OK;
3325 }
3326
3327 /**
3328  * Internal Function to store results in result array during GetACLResourceCB.
3329  */
3330 static void registerResultForGetACLResourceCB(GetSecData_t *GetSecData,
3331                                              OCStackResult stackresult)
3332 {
3333    OIC_LOG_V(INFO, TAG, "Inside registerResultForGetACLResourceCB "
3334            "GetSecData->numOfResults is %d", GetSecData->numOfResults);
3335    memcpy(GetSecData->resArr[(GetSecData->numOfResults)].deviceId.id,
3336           GetSecData->deviceInfo->doxm->deviceID.id, UUID_LENGTH);
3337    GetSecData->resArr[(GetSecData->numOfResults)].res = stackresult;
3338    ++(GetSecData->numOfResults);
3339 }
3340
3341 /**
3342  * Callback handler of SRPGetACLResource.
3343  *
3344  * @param[in] ctx             ctx value passed to callback from calling function.
3345  * @param[in] UNUSED          handle to an invocation
3346  * @param[in] clientResponse  Response from queries to remote servers.
3347  * @return  OC_STACK_DELETE_TRANSACTION to delete the transaction
3348  *          and  OC_STACK_KEEP_TRANSACTION to keep it.
3349  */
3350 static OCStackApplicationResult SRPGetACLResourceCB(void *ctx, OCDoHandle UNUSED,
3351                                                   OCClientResponse *clientResponse)
3352 {
3353     OIC_LOG_V(INFO, TAG, "Inside SRPGetACLResourceCB.");
3354     (void)UNUSED;
3355     VERIFY_NOT_NULL_RETURN(TAG, ctx, ERROR, OC_STACK_DELETE_TRANSACTION);
3356     GetSecData_t *GetSecData = (GetSecData_t*)ctx;
3357     OCProvisionResultCB resultCallback = GetSecData->resultCallback;
3358
3359     if (clientResponse)
3360     {
3361         if(OC_STACK_OK == clientResponse->result)
3362         {
3363             uint8_t *payload = ((OCSecurityPayload*)clientResponse->payload)->securityData;
3364             size_t size = ((OCSecurityPayload*)clientResponse->payload)->payloadSize;
3365
3366             OIC_LOG_BUFFER(DEBUG, TAG, payload, size);
3367             (void)payload;
3368             (void)size;
3369
3370             registerResultForGetACLResourceCB(GetSecData, OC_STACK_OK);
3371             ((OCProvisionResultCB)(resultCallback))(GetSecData->ctx, GetSecData->numOfResults,
3372                                                     GetSecData->resArr,
3373                                                     false);
3374              OICFree(GetSecData->resArr);
3375              OICFree(GetSecData);
3376
3377             return OC_STACK_DELETE_TRANSACTION;
3378         }
3379     }
3380     registerResultForGetACLResourceCB(GetSecData, OC_STACK_OK);
3381     ((OCProvisionResultCB)(resultCallback))(GetSecData->ctx, GetSecData->numOfResults,
3382                                             GetSecData->resArr,
3383                                             false);
3384     OIC_LOG_V(ERROR, TAG, "SRPGetACLResourceCB received Null clientResponse");
3385     OICFree(GetSecData->resArr);
3386     OICFree(GetSecData);
3387
3388     return OC_STACK_DELETE_TRANSACTION;
3389 }
3390
3391 OCStackResult SRPGetACLResource(void *ctx, const OCProvisionDev_t *selectedDeviceInfo,
3392         OicSecAclVersion_t aclVersion, OCProvisionResultCB resultCallback)
3393 {
3394     VERIFY_NOT_NULL_RETURN(TAG, selectedDeviceInfo, ERROR,  OC_STACK_INVALID_PARAM);
3395     VERIFY_NOT_NULL_RETURN(TAG, resultCallback, ERROR,  OC_STACK_INVALID_CALLBACK);
3396
3397     const char *uri = NULL;
3398
3399     switch (aclVersion)
3400     {
3401     case OIC_SEC_ACL_V1:
3402         OIC_LOG_V(WARNING, TAG, "%s using ACL v1... this should only be used for provisioning OIC 1.1 and earlier Servers.", __func__);
3403         uri = OIC_RSRC_ACL_URI;
3404         break;
3405     case OIC_SEC_ACL_V2:
3406         uri = OIC_RSRC_ACL2_URI;
3407         break;
3408     default:
3409         return OC_STACK_INVALID_PARAM;
3410     }
3411
3412     char query[MAX_URI_LENGTH + MAX_QUERY_LENGTH] = {0};
3413     if(!PMGenerateQuery(true,
3414                         selectedDeviceInfo->endpoint.addr,
3415                         selectedDeviceInfo->securePort,
3416                         selectedDeviceInfo->connType,
3417                         query, sizeof(query), uri))
3418     {
3419         OIC_LOG(ERROR, TAG, "SRPGetACLResource : Failed to generate query");
3420         return OC_STACK_ERROR;
3421     }
3422     OIC_LOG_V(DEBUG, TAG, "Query=%s", query);
3423
3424     OCCallbackData cbData =  {.context=NULL, .cb=NULL, .cd=NULL};
3425     cbData.cb = &SRPGetACLResourceCB;
3426     GetSecData_t* GetSecData = (GetSecData_t*)OICCalloc(1, sizeof(GetSecData_t));
3427     if (NULL == GetSecData)
3428     {
3429         OIC_LOG(ERROR, TAG, "Unable to allocate memory");
3430         return OC_STACK_NO_MEMORY;
3431     }
3432     GetSecData->deviceInfo = selectedDeviceInfo;
3433     GetSecData->resultCallback = resultCallback;
3434     GetSecData->numOfResults=0;
3435     GetSecData->ctx = ctx;
3436
3437     int noOfRiCalls = 1;
3438     GetSecData->resArr = (OCProvisionResult_t*)OICCalloc(noOfRiCalls, sizeof(OCProvisionResult_t));
3439     if (NULL == GetSecData->resArr)
3440     {
3441         OICFree(GetSecData);
3442         OIC_LOG(ERROR, TAG, "Unable to allocate memory");
3443         return OC_STACK_NO_MEMORY;
3444     }
3445     cbData.context = (void *)GetSecData;
3446     cbData.cd = NULL;
3447     OCMethod method = OC_REST_GET;
3448     OCDoHandle handle = NULL;
3449     OIC_LOG(DEBUG, TAG, "Sending Get ACL to resource server");
3450     OCStackResult ret = OCDoResource(&handle, method, query, NULL, NULL,
3451             selectedDeviceInfo->connType, OC_HIGH_QOS, &cbData, NULL, 0);
3452     if (OC_STACK_OK != ret)
3453     {
3454         OIC_LOG(ERROR, TAG, "OCStack resource error");
3455         OICFree(GetSecData->resArr);
3456         OICFree(GetSecData);
3457     }
3458     VERIFY_SUCCESS_RETURN(TAG, (OC_STACK_OK == ret), ERROR, OC_STACK_ERROR);
3459     OIC_LOG(DEBUG, TAG, "OUT SRPGetACLResource");
3460
3461     return OC_STACK_OK;
3462 }
3463
3464 /**
3465  * Internal Function to store results in result array during GetCSRResourceCB.
3466  */
3467 static void registerResultForGetCSRResourceCB(GetCsrData_t *getCsrData,
3468                                              OCStackResult stackresult,
3469                                              const uint8_t *payload,
3470                                              size_t payloadSize)
3471 {
3472     /* SRPGetCSRResource allocates the memory for getCsrData. When it calls this callback,
3473      * numOfResults points to the current entry we're filling out. Later when this structure
3474      * gets returned to the caller, that's when it actually reflects the number of
3475      * results returned.
3476      */
3477     OCPMGetCsrResult_t* currentEntry = &getCsrData->resArr[getCsrData->numOfResults];
3478     OIC_LOG_V(INFO, TAG, "Inside registerResultForGetCSRResourceCB "
3479         "getCsrData->numOfResults is %zu\n", getCsrData->numOfResults);
3480     memcpy(currentEntry->deviceId.id,
3481         getCsrData->deviceInfo->doxm->deviceID.id, UUID_LENGTH);
3482     currentEntry->res = stackresult;
3483
3484     if (OC_STACK_OK == stackresult)
3485     {
3486         OCStackResult res = CBORPayloadToCSR(payload, payloadSize,
3487             &currentEntry->csr,
3488             &currentEntry->csrLen,
3489             &currentEntry->encoding);
3490         if (OC_STACK_OK != res)
3491         {
3492             currentEntry->res = res;
3493             currentEntry->csr = NULL;
3494             currentEntry->csrLen = 0;
3495             currentEntry->encoding = OIC_ENCODING_UNKNOW;
3496         }
3497     }
3498
3499     ++(getCsrData->numOfResults);
3500 }
3501
3502 /**
3503  * Callback handler of SRPGetCSRResource.
3504  *
3505  * @param[in] ctx             ctx value passed to callback from calling function.
3506  * @param[in] UNUSED          handle to an invocation
3507  * @param[in] clientResponse  Response from queries to remote servers.
3508  * @return  OC_STACK_DELETE_TRANSACTION to delete the transaction
3509  *          and  OC_STACK_KEEP_TRANSACTION to keep it.
3510  */
3511 static OCStackApplicationResult SRPGetCSRResourceCB(void *ctx, OCDoHandle UNUSED,
3512     OCClientResponse *clientResponse)
3513 {
3514     size_t i = 0;
3515     OIC_LOG_V(INFO, TAG, "IN %s", __func__);
3516     OC_UNUSED(UNUSED);
3517     VERIFY_NOT_NULL_RETURN(TAG, ctx, ERROR, OC_STACK_DELETE_TRANSACTION);
3518     GetCsrData_t *getCsrData = (GetCsrData_t*)ctx;
3519     OCGetCSRResultCB resultCallback = getCsrData->resultCallback;
3520
3521     if (clientResponse)
3522     {
3523         if (OC_STACK_OK == clientResponse->result)
3524         {
3525             uint8_t *payload = ((OCSecurityPayload*)clientResponse->payload)->securityData;
3526             size_t size = ((OCSecurityPayload*)clientResponse->payload)->payloadSize;
3527
3528             OIC_LOG_BUFFER(DEBUG, TAG, payload, size);
3529
3530             registerResultForGetCSRResourceCB(getCsrData, OC_STACK_OK, payload, size);
3531         }
3532     }
3533     else
3534     {
3535         registerResultForGetCSRResourceCB(getCsrData, OC_STACK_ERROR, NULL, 0);
3536     }
3537
3538     ((OCGetCSRResultCB)(resultCallback))(getCsrData->ctx, getCsrData->numOfResults,
3539         getCsrData->resArr,
3540         false);
3541     OIC_LOG_V(ERROR, TAG, "%s: received Null clientResponse", __func__);
3542     for (i = 0; i < getCsrData->numOfResults; i++)
3543     {
3544         OICFree(getCsrData->resArr[i].csr);
3545     }
3546     OICFree(getCsrData->resArr);
3547     OICFree(getCsrData);
3548     OIC_LOG_V(INFO, TAG, "OUT %s", __func__);
3549
3550     return OC_STACK_DELETE_TRANSACTION;
3551 }
3552
3553 OCStackResult SRPGetCSRResource(void *ctx, const OCProvisionDev_t *selectedDeviceInfo,
3554         OCGetCSRResultCB resultCallback)
3555 {
3556     VERIFY_NOT_NULL_RETURN(TAG, selectedDeviceInfo, ERROR,  OC_STACK_INVALID_PARAM);
3557     VERIFY_NOT_NULL_RETURN(TAG, resultCallback, ERROR,  OC_STACK_INVALID_CALLBACK);
3558
3559     char query[MAX_URI_LENGTH + MAX_QUERY_LENGTH] = {0};
3560     if (!PMGenerateQuery(true,
3561                         selectedDeviceInfo->endpoint.addr,
3562                         selectedDeviceInfo->securePort,
3563                         selectedDeviceInfo->connType,
3564                         query, sizeof(query), OIC_RSRC_CSR_URI))
3565     {
3566         OIC_LOG(ERROR, TAG, "SRPGetCSRResource : Failed to generate query");
3567         return OC_STACK_ERROR;
3568     }
3569     OIC_LOG_V(DEBUG, TAG, "Query=%s", query);
3570
3571     OCCallbackData cbData =  {.context=NULL, .cb=NULL, .cd=NULL};
3572     cbData.cb = &SRPGetCSRResourceCB;
3573     GetCsrData_t* getCsrData = (GetCsrData_t*)OICCalloc(1, sizeof(GetCsrData_t));
3574     if (NULL == getCsrData)
3575     {
3576         OIC_LOG(ERROR, TAG, "Unable to allocate memory");
3577         return OC_STACK_NO_MEMORY;
3578     }
3579     getCsrData->deviceInfo = selectedDeviceInfo;
3580     getCsrData->resultCallback = resultCallback;
3581     getCsrData->numOfResults=0;
3582     getCsrData->ctx = ctx;
3583
3584     int noOfRiCalls = 1;
3585     getCsrData->resArr = (OCPMGetCsrResult_t*)OICCalloc(noOfRiCalls, sizeof(OCPMGetCsrResult_t));
3586     if (NULL == getCsrData->resArr)
3587     {
3588         OICFree(getCsrData);
3589         OIC_LOG(ERROR, TAG, "Unable to allocate memory");
3590         return OC_STACK_NO_MEMORY;
3591     }
3592     cbData.context = (void *)getCsrData;
3593     OCMethod method = OC_REST_GET;
3594     OCDoHandle handle = NULL;
3595     OIC_LOG(DEBUG, TAG, "Sending Get CSR to resource server");
3596     OCStackResult ret = OCDoResource(&handle, method, query, NULL, NULL,
3597             selectedDeviceInfo->connType, OC_HIGH_QOS, &cbData, NULL, 0);
3598     if (OC_STACK_OK != ret)
3599     {
3600         OIC_LOG(ERROR, TAG, "OCStack resource error");
3601         OICFree(getCsrData->resArr);
3602         OICFree(getCsrData);
3603     }
3604     OIC_LOG(DEBUG, TAG, "OUT SRPGetCSRResource");
3605
3606     return ret;
3607 }
3608
3609 /**
3610  * Internal Function to store results in result array during GetRolesResourceCB.
3611  */
3612 static void registerResultForGetRolesResourceCB(GetRolesData_t *getRolesData,
3613                                                 OCStackResult stackresult,
3614                                                 const uint8_t *payload,
3615                                                 size_t payloadSize)
3616 {
3617     /* SRPGetRolesResource allocates the memory for getRolesData. When it calls this callback,
3618      * numOfResults points to the current entry we're filling out. Later when this structure
3619      * gets returned to the caller, that's when it actually reflects the number of
3620      * results returned.
3621      */
3622     OCPMGetRolesResult_t* currentEntry = &getRolesData->resArr[getRolesData->numOfResults];
3623     OIC_LOG_V(INFO, TAG, "Inside registerResultForGetCSRResourceCB "
3624         "getRolesData->numOfResults is %zu\n", getRolesData->numOfResults);
3625     memcpy(currentEntry->deviceId.id,
3626         getRolesData->deviceInfo->doxm->deviceID.id, UUID_LENGTH);
3627     currentEntry->res = stackresult;
3628     currentEntry->chainsLength = 0;
3629
3630     if (OC_STACK_OK == stackresult)
3631     {
3632         RoleCertChain_t *chains = NULL;
3633         OCStackResult res = CBORPayloadToRoles(payload, payloadSize, &chains);
3634         if (OC_STACK_OK != res)
3635         {
3636             currentEntry->res = res;
3637             currentEntry->chains = NULL;
3638         }
3639         else
3640         {
3641             RoleCertChain_t *curr = NULL;
3642             for (curr = chains; NULL != curr; curr = curr->next)
3643             {
3644                 currentEntry->chainsLength++;
3645             }
3646             currentEntry->chains = (OCPMRoleCertChain_t *)OICCalloc(currentEntry->chainsLength, sizeof(OCPMRoleCertChain_t));
3647             if (NULL == currentEntry->chains)
3648             {
3649                 OIC_LOG(ERROR, TAG, "No memory allocating role chains");
3650                 currentEntry->chainsLength = 0;
3651                 currentEntry->res = OC_STACK_NO_MEMORY;
3652             }
3653             else
3654             {
3655                 size_t i;
3656                 for (i = 0, curr = chains; NULL != curr; curr = curr->next, i++)
3657                 {
3658                     currentEntry->chains[i].credId = curr->credId;
3659                     /* Take ownership of the buffers from certificate and optData, rather than copy. */
3660                     currentEntry->chains[i].certificate = curr->certificate;
3661                     currentEntry->chains[i].optData = curr->optData;
3662
3663                     curr->certificate.data = NULL;
3664                     curr->certificate.len = 0;
3665                     curr->optData.data = NULL;
3666                     curr->optData.len = 0;
3667                 }
3668             }
3669             FreeRoleCertChainList(chains);
3670         }
3671     }
3672
3673     ++(getRolesData->numOfResults);
3674 }
3675
3676 /**
3677  * Callback handler of SRPGetRolesResource.
3678  *
3679  * @param[in] ctx             ctx value passed to callback from calling function.
3680  * @param[in] UNUSED          handle to an invocation
3681  * @param[in] clientResponse  Response from queries to remote servers.
3682  * @return  OC_STACK_DELETE_TRANSACTION to delete the transaction
3683  *          and  OC_STACK_KEEP_TRANSACTION to keep it.
3684  */
3685 static OCStackApplicationResult SRPGetRolesResourceCB(void *ctx, OCDoHandle handle,
3686                                                       OCClientResponse *clientResponse)
3687 {
3688     OIC_LOG(INFO, TAG, "Inside SRPGetRolesResourceCB.");
3689     OC_UNUSED(handle);
3690     VERIFY_NOT_NULL_RETURN(TAG, ctx, ERROR, OC_STACK_DELETE_TRANSACTION);
3691     GetRolesData_t *getRolesData = (GetRolesData_t*)ctx;
3692     OCGetRolesResultCB resultCallback = getRolesData->resultCallback;
3693
3694     if (clientResponse)
3695     {
3696         if (OC_STACK_OK == clientResponse->result)
3697         {
3698             uint8_t *payload = ((OCSecurityPayload*)clientResponse->payload)->securityData;
3699             size_t size = ((OCSecurityPayload*)clientResponse->payload)->payloadSize;
3700
3701             OIC_LOG_BUFFER(DEBUG, TAG, payload, size);
3702
3703             registerResultForGetRolesResourceCB(getRolesData, OC_STACK_OK, payload, size);
3704         }
3705     }
3706     else
3707     {
3708         OIC_LOG(ERROR, TAG, "SRPGetRolesResourceCB received Null clientResponse");
3709         registerResultForGetRolesResourceCB(getRolesData, OC_STACK_ERROR, NULL, 0);
3710     }
3711
3712     resultCallback(getRolesData->ctx, getRolesData->numOfResults,
3713                    getRolesData->resArr,
3714                    false);
3715     for (size_t i = 0; i < getRolesData->numOfResults; i++)
3716     {
3717         /* We took ownership of certificate.data and optData.data, so we must free them.
3718          * These are allocated internally by tinycbor, which uses malloc and free, so we call
3719          * free directly for those.
3720          */
3721         for (size_t j = 0; j < getRolesData->resArr[i].chainsLength; j++)
3722         {
3723             free(getRolesData->resArr[i].chains[j].certificate.data);
3724             free(getRolesData->resArr[i].chains[j].optData.data);
3725         }
3726         OICFree(getRolesData->resArr[i].chains);
3727     }
3728     OICFree(getRolesData->resArr);
3729     OICFree(getRolesData);
3730
3731     return OC_STACK_DELETE_TRANSACTION;
3732 }
3733
3734 OCStackResult SRPGetRolesResource(void *ctx, const OCProvisionDev_t *selectedDeviceInfo,
3735         OCGetRolesResultCB resultCallback)
3736 {
3737     VERIFY_NOT_NULL_RETURN(TAG, selectedDeviceInfo, ERROR,  OC_STACK_INVALID_PARAM);
3738     VERIFY_NOT_NULL_RETURN(TAG, resultCallback, ERROR,  OC_STACK_INVALID_CALLBACK);
3739
3740     char query[MAX_URI_LENGTH + MAX_QUERY_LENGTH] = {0};
3741     if (!PMGenerateQuery(true,
3742                         selectedDeviceInfo->endpoint.addr,
3743                         selectedDeviceInfo->securePort,
3744                         selectedDeviceInfo->connType,
3745                         query, sizeof(query), OIC_RSRC_ROLES_URI))
3746     {
3747         OIC_LOG(ERROR, TAG, "SRPGetRolesResource : Failed to generate query");
3748         return OC_STACK_ERROR;
3749     }
3750     OIC_LOG_V(DEBUG, TAG, "Query=%s", query);
3751
3752     OCCallbackData cbData =  {.context=NULL, .cb=NULL, .cd=NULL};
3753     cbData.cb = &SRPGetRolesResourceCB;
3754     GetRolesData_t *getRolesData = (GetRolesData_t*)OICCalloc(1, sizeof(GetRolesData_t));
3755     if (NULL == getRolesData)
3756     {
3757         OIC_LOG(ERROR, TAG, "Unable to allocate memory");
3758         return OC_STACK_NO_MEMORY;
3759     }
3760     getRolesData->deviceInfo = selectedDeviceInfo;
3761     getRolesData->resultCallback = resultCallback;
3762     getRolesData->numOfResults = 0;
3763     getRolesData->ctx = ctx;
3764
3765     getRolesData->resArr = (OCPMGetRolesResult_t*)OICCalloc(1, sizeof(OCPMGetRolesResult_t));
3766     if (NULL == getRolesData->resArr)
3767     {
3768         OICFree(getRolesData);
3769         OIC_LOG(ERROR, TAG, "Unable to allocate memory");
3770         return OC_STACK_NO_MEMORY;
3771     }
3772     cbData.context = (void *)getRolesData;
3773     OCDoHandle handle = NULL;
3774     OIC_LOG(DEBUG, TAG, "Sending Get Roles to resource server");
3775     OCStackResult ret = OCDoResource(&handle, OC_REST_GET, query, NULL, NULL,
3776             selectedDeviceInfo->connType, OC_HIGH_QOS, &cbData, NULL, 0);
3777     if (OC_STACK_OK != ret)
3778     {
3779         OIC_LOG(ERROR, TAG, "OCStack resource error");
3780         OICFree(getRolesData->resArr);
3781         OICFree(getRolesData);
3782     }
3783     OIC_LOG(DEBUG, TAG, "OUT SRPGetRolesResource");
3784
3785     return ret;
3786 }
3787
3788 /**
3789  * Callback handler of SRPDeleteRoleCertificateByCredId.
3790  *
3791  * @param[in] ctx             ctx value passed to callback from calling function.
3792  * @param[in] UNUSED          handle to an invocation
3793  * @param[in] clientResponse  Response from queries to remote servers.
3794  * @return  OC_STACK_DELETE_TRANSACTION to delete the transaction
3795  *          and  OC_STACK_KEEP_TRANSACTION to keep it.
3796  */
3797 static OCStackApplicationResult SRPDeleteRoleCertificateCB(void *ctx, OCDoHandle UNUSED,
3798                                                            OCClientResponse *clientResponse)
3799 {
3800     OC_UNUSED(UNUSED);
3801     GetSecData_t *getSecData = (GetSecData_t *)ctx;
3802     OCProvisionResultCB resultCallback = getSecData->resultCallback;
3803
3804     OIC_LOG(DEBUG, TAG, "SRPDeleteRoleCertificateCB IN");
3805
3806     if (NULL != clientResponse)
3807     {
3808         memcpy(getSecData->resArr[(getSecData->numOfResults)].deviceId.id,
3809             getSecData->deviceInfo->doxm->deviceID.id, UUID_LENGTH);
3810         getSecData->resArr[(getSecData->numOfResults)].res = clientResponse->result;
3811         ++(getSecData->numOfResults);
3812         resultCallback(getSecData->ctx, getSecData->numOfResults, getSecData->resArr, false);
3813     }
3814
3815     OIC_LOG(DEBUG, TAG, "SRPDeleteRoleCertificateCB OUT");
3816
3817     return OC_STACK_DELETE_TRANSACTION;
3818 }
3819
3820 OCStackResult SRPDeleteRoleCertificateByCredId(void* ctx, const OCProvisionDev_t *selectedDeviceInfo,
3821                                                OCProvisionResultCB resultCallback, uint32_t credId)
3822 {
3823     VERIFY_NOT_NULL_RETURN(TAG, selectedDeviceInfo, ERROR,  OC_STACK_INVALID_PARAM);
3824     VERIFY_NOT_NULL_RETURN(TAG, resultCallback, ERROR,  OC_STACK_INVALID_CALLBACK);
3825
3826     char query[MAX_URI_LENGTH + MAX_QUERY_LENGTH] = {0};
3827     if (!PMGenerateQuery(true,
3828                         selectedDeviceInfo->endpoint.addr,
3829                         selectedDeviceInfo->securePort,
3830                         selectedDeviceInfo->connType,
3831                         query, sizeof(query), OIC_RSRC_ROLES_URI))
3832     {
3833         OIC_LOG(ERROR, TAG, "SRPDeleteRoleCertificateByCredId : Failed to generate query");
3834         return OC_STACK_ERROR;
3835     }
3836     size_t queryLen = strlen(query);
3837     int snRet = snprintf(query + queryLen, sizeof(query) - queryLen, "?credId=%u", credId);
3838
3839     if (0 > snRet)
3840     {
3841         OIC_LOG_V(ERROR, TAG, "snprintf returned error: %d", snRet);
3842         return OC_STACK_ERROR;
3843     }
3844     else if ((size_t)snRet >= (sizeof(query) - queryLen))
3845     {
3846         OIC_LOG_V(ERROR, TAG, "snprintf truncated");
3847         return OC_STACK_ERROR;
3848     }
3849
3850     OIC_LOG_V(DEBUG, TAG, "Query=%s", query);
3851
3852     OCCallbackData cbData =  {.context=NULL, .cb=NULL, .cd=NULL};
3853     cbData.cb = &SRPDeleteRoleCertificateCB;
3854     GetSecData_t *getSecData = (GetSecData_t*)OICCalloc(1, sizeof(GetSecData_t));
3855     if (NULL == getSecData)
3856     {
3857         OIC_LOG(ERROR, TAG, "Unable to allocate memory");
3858         return OC_STACK_NO_MEMORY;
3859     }
3860     getSecData->deviceInfo = selectedDeviceInfo;
3861     getSecData->resultCallback = resultCallback;
3862     getSecData->numOfResults = 0;
3863     getSecData->ctx = ctx;
3864
3865     getSecData->resArr = (OCProvisionResult_t*)OICCalloc(1, sizeof(OCProvisionResult_t));
3866     if (NULL == getSecData->resArr)
3867     {
3868         OICFree(getSecData);
3869         OIC_LOG(ERROR, TAG, "Unable to allocate memory");
3870         return OC_STACK_NO_MEMORY;
3871     }
3872     cbData.context = (void *)getSecData;
3873     OCMethod method = OC_REST_DELETE;
3874     OCDoHandle handle = NULL;
3875     OIC_LOG(DEBUG, TAG, "Sending Delete Roles to resource server");
3876     OCStackResult ret = OCDoResource(&handle, method, query, NULL, NULL,
3877             selectedDeviceInfo->connType, OC_HIGH_QOS, &cbData, NULL, 0);
3878     if (OC_STACK_OK != ret)
3879     {
3880         OIC_LOG(ERROR, TAG, "OCStack resource error");
3881         OICFree(getSecData->resArr);
3882         OICFree(getSecData);
3883     }
3884     OIC_LOG(DEBUG, TAG, "OUT SRPGetRolesResource");
3885
3886     return ret;
3887 }
3888
3889 OCStackResult SRPReadTrustCertChain(uint16_t credId, uint8_t **trustCertChain,
3890                                      size_t *chainSize)
3891 {
3892     OIC_LOG(DEBUG, TAG, "IN SRPReadTrustCertChain");
3893
3894     OCStackResult res = OC_STACK_ERROR;
3895     int secureFlag = 0;
3896     OicSecCred_t* credData = GetCredEntryByCredId(credId);
3897     if(credData)
3898     {
3899         res = CredToCBORPayload((const OicSecCred_t*) credData, trustCertChain,
3900                                 chainSize, secureFlag);
3901         if(OC_STACK_OK != res)
3902         {
3903             OIC_LOG(INFO, TAG, "CredToCBORPayload failed");
3904         }
3905     }
3906     DeleteCredList(credData);
3907     return res;
3908 }
3909
3910
3911 /**
3912  * Updates provisioning result.
3913  */
3914 static void RegisterProvResult(const OCProvisionDev_t *targetDev, OCProvisionResult_t *resArr,
3915                                int *numOfResults, OCStackResult stackResult)
3916 {
3917
3918     OIC_LOG_V(INFO, TAG, "value of  numOfResults is %d", *numOfResults);
3919     memcpy(resArr[*numOfResults].deviceId.id, targetDev->doxm->deviceID.id, UUID_LENGTH);
3920     resArr[*numOfResults].res = stackResult;
3921     (*numOfResults)++;
3922 }
3923
3924 static OCStackApplicationResult ProvisionAclCB(void *ctx, OCDoHandle UNUSED,
3925         OCClientResponse *clientResponse)
3926 {
3927     if (NULL == ctx || NULL == clientResponse)
3928     {
3929         OIC_LOG_V(ERROR, TAG, " ctx: %p, clientResponse: %p", ctx, clientResponse);
3930         return OC_STACK_INVALID_PARAM;
3931     }
3932     (void) UNUSED;
3933     if (OC_STACK_RESOURCE_CHANGED == clientResponse->result)
3934     {
3935         Data_t *data = (Data_t *) ctx;
3936         if (ACL_TYPE != data->type)
3937         {
3938             OIC_LOG(ERROR, TAG, "Invalid type");
3939             return OC_STACK_INVALID_PARAM;
3940         }
3941
3942         ACLData_t *aclData = (ACLData_t *) (data->ctx);
3943
3944         const char *uri = NULL;
3945
3946         switch (aclData->aclVersion)
3947         {
3948             case OIC_SEC_ACL_V1:
3949                 OIC_LOG(WARNING, TAG,
3950                         "%s using ACL v1... this should only be used for provisioning OIC 1.1 and earlier Servers.");
3951                 uri = OIC_RSRC_ACL_URI;
3952                 break;
3953             case OIC_SEC_ACL_V2:
3954                 uri = OIC_RSRC_ACL2_URI;
3955                 break;
3956             default:
3957                 return OC_STACK_INVALID_PARAM;
3958         }
3959
3960         // if rowneruuid is empty, set it to device ID
3961         OicUuid_t emptyOwner = {.id = {0} };
3962         if (memcmp(&(aclData->acl->rownerID.id), &emptyOwner, UUID_IDENTITY_SIZE) == 0)
3963         {
3964             OIC_LOG(DEBUG, TAG, "Set Rowner to PT's deviceId, because Rowner of ACL is empty");
3965             OicUuid_t oicUuid;
3966
3967             if (OC_STACK_OK == GetDoxmDeviceID(&oicUuid))
3968             {
3969                 memcpy(&(aclData->acl->rownerID.id), &oicUuid, UUID_IDENTITY_SIZE);
3970             }
3971             else
3972             {
3973                 OIC_LOG(ERROR, TAG, "Failed to set Rowner to PT's deviceID\
3974                     becuase it failed to retrieve Doxm DeviceID");
3975                 return OC_STACK_ERROR;
3976             }
3977         }
3978
3979         OCSecurityPayload *secPayload = (OCSecurityPayload *)OICCalloc(1, sizeof(OCSecurityPayload));
3980         if (!secPayload)
3981         {
3982             OIC_LOG(ERROR, TAG, "Failed to allocate memory");
3983             OIC_LOG_V(ERROR, TAG, "OUT %s", __func__);
3984             return OC_STACK_NO_MEMORY;
3985         }
3986         secPayload->base.type = PAYLOAD_TYPE_SECURITY;
3987         if (OC_STACK_OK != AclToCBORPayload(aclData->acl, aclData->aclVersion, &secPayload->securityData,
3988                                             &secPayload->payloadSize))
3989         {
3990             OCPayloadDestroy((OCPayload *)secPayload);
3991             OIC_LOG(ERROR, TAG, "Failed to AclToCBORPayload");
3992             OIC_LOG_V(ERROR, TAG, "OUT %s", __func__);
3993             return OC_STACK_NO_MEMORY;
3994         }
3995         OIC_LOG(DEBUG, TAG, "Created payload for ACL:");
3996         OIC_LOG_BUFFER(DEBUG, TAG, secPayload->securityData, secPayload->payloadSize);
3997
3998         char query[MAX_URI_LENGTH + MAX_QUERY_LENGTH] = {0};
3999         if (!PMGenerateQuery(true,
4000                              aclData->deviceInfo->endpoint.addr,
4001                              aclData->deviceInfo->securePort,
4002                              aclData->deviceInfo->connType,
4003                              query, sizeof(query), uri))
4004         {
4005             OIC_LOG(ERROR, TAG, "DeviceDiscoveryHandler : Failed to generate query");
4006             return OC_STACK_ERROR;
4007         }
4008         OIC_LOG_V(DEBUG, TAG, "Query=%s", query);
4009
4010         OCCallbackData cbData =  {.context = NULL, .cb = NULL, .cd = NULL};
4011         cbData.cb = ProvisionCB;
4012         cbData.context = ctx;
4013         cbData.cd = NULL;
4014         OCMethod method = OC_REST_POST;
4015         OCDoHandle handle = NULL;
4016         OIC_LOG(DEBUG, TAG, "Sending ACL info to resource server");
4017         OCStackResult ret = OCDoResource(&handle, method, query,
4018                                          &aclData->deviceInfo->endpoint, (OCPayload *)secPayload,
4019                                          aclData->deviceInfo->connType, OC_HIGH_QOS, &cbData, NULL, 0);
4020         if (ret != OC_STACK_OK)
4021         {
4022             OIC_LOG_V(ERROR, TAG, "OUT %s", __func__);
4023             return OC_STACK_ERROR;
4024         }
4025     }
4026     else
4027     {
4028         OIC_LOG_V(ERROR, TAG, "OUT %s", __func__);
4029         return OC_STACK_ERROR;
4030     }
4031     OIC_LOG_V(DEBUG, TAG, "OUT %s", __func__);
4032     return OC_STACK_OK;
4033 }
4034