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