Add OCUnlink / OCRemove API to Provisioning Manager
[platform/upstream/iotivity.git] / resource / csdk / security / provisioning / src / ownershiptransfermanager.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
21 // Defining _POSIX_C_SOURCE macro with 199309L (or greater) as value
22 // causes header files to expose definitions
23 // corresponding to the POSIX.1b, Real-time extensions
24 // (IEEE Std 1003.1b-1993) specification
25 //
26 // For this specific file, see use of clock_gettime,
27 // Refer to http://pubs.opengroup.org/stage7tc1/functions/clock_gettime.html
28 // and to http://man7.org/linux/man-pages/man2/clock_gettime.2.html
29 #ifndef _POSIX_C_SOURCE
30 #define _POSIX_C_SOURCE 200809L
31 #endif
32
33 #include <time.h>
34 #include <unistd.h>
35 #include <sys/time.h>
36 #include <stdbool.h>
37 #include <string.h>
38
39 #include "logger.h"
40 #include "oic_malloc.h"
41 #include "oic_string.h"
42 #include "cacommon.h"
43 #include "cainterface.h"
44 #include "base64.h"
45 #include "cJSON.h"
46
47 #include "srmresourcestrings.h"
48 #include "doxmresource.h"
49 #include "pstatresource.h"
50 #include "credresource.h"
51 #include "aclresource.h"
52 #include "ownershiptransfermanager.h"
53 #include "securevirtualresourcetypes.h"
54 #include "oxmjustworks.h"
55 #include "pmtypes.h"
56 #include "pmutility.h"
57 #include "srmutility.h"
58 #include "provisioningdatabasemanager.h"
59 #include "oxmrandompin.h"
60
61 #define TAG "OTM"
62
63 /**
64  * Possible states of ownership transfer manager module.
65  */
66 typedef enum
67 {
68     SP_NO_MASK                = (0       ),
69     SP_DISCOVERY_STARTED      = (0x1 << 1),
70     SP_DISCOVERY_ERROR        = (0x1 << 2),
71     SP_DISCOVERY_DONE         = (0x1 << 3),
72     SP_UP_OWN_TR_METH_STARTED = (0x1 << 4),
73     SP_UP_OWN_TR_METH_ERROR   = (0x1 << 5),
74     SP_UP_OWN_TR_METH_DONE    = (0x1 << 6),
75     SP_LIST_METHODS_STARTED   = (0x1 << 7),
76     SP_LIST_METHODS_ERROR     = (0x1 << 8),
77     SP_LIST_METHODS_DONE      = (0x1 << 9),
78     SP_UPDATE_OP_MODE_STARTED = (0x1 << 10),
79     SP_UPDATE_OP_MODE_ERROR   = (0x1 << 11),
80     SP_UPDATE_OP_MODE_DONE    = (0x1 << 12),
81     SP_UPDATE_OWNER_STARTED   = (0x1 << 13),
82     SP_UPDATE_OWNER_ERROR     = (0x1 << 14),
83     SP_UPDATE_OWNER_DONE      = (0x1 << 15)
84 } OTMStates;
85
86
87
88 /**
89  * Array to store the callbacks for each owner transfer method.
90  */
91 static OTMCallbackData_t g_OTMDatas[OIC_OXM_COUNT];
92
93 /**
94  * Variable for storing provisioning tool's provisioning capabilities
95  * Must be in decreasing order of preference. More prefered method should
96  * have lower array index.
97  */
98 static OicSecDpom_t gProvisioningToolCapability[] = { SINGLE_SERVICE_CLIENT_DRIVEN };
99
100 /**
101  * Number of supported provisioning methods
102  * current version supports only one.
103  */
104 static size_t gNumOfProvisioningMethodsPT = 1;
105
106 /**
107  * Function to getting string of ownership transfer method
108  */
109 static const char* GetOxmString(OicSecOxm_t oxmType)
110 {
111     switch(oxmType)
112     {
113         case OIC_JUST_WORKS:
114             return OXM_JUST_WORKS;
115         case OIC_MODE_SWITCH:
116             return OXM_MODE_SWITCH;
117         case OIC_RANDOM_DEVICE_PIN:
118             return OXM_RANDOM_DEVICE_PIN;
119         case OIC_PRE_PROVISIONED_DEVICE_PIN:
120             return OXM_PRE_PROVISIONED_DEVICE_PIN;
121         case OIC_PRE_PROVISION_STRONG_CREDENTIAL:
122             return OXM_PRE_PROVISIONED_STRONG_CREDENTIAL;
123         default:
124             return NULL;
125     }
126 }
127
128 /**
129  * Function to select appropriate  provisioning method.
130  *
131  * @param[in] supportedMethods   Array of supported methods
132  * @param[in] numberOfMethods   number of supported methods
133  * @param[out]  selectedMethod         Selected methods
134  * @return  OC_STACK_OK on success
135  */
136 static OCStackResult SelectProvisioningMethod(const OicSecOxm_t *supportedMethods,
137                                                             size_t numberOfMethods,
138                                                             OicSecOxm_t *selectedMethod)
139 {
140     OC_LOG(DEBUG, TAG, "IN SelectProvisioningMethod");
141
142     if(numberOfMethods == 0 || !supportedMethods)
143     {
144         OC_LOG(WARNING, TAG, "Could not find a supported OxM.");
145         return OC_STACK_ERROR;
146     }
147
148     *selectedMethod  = supportedMethods[0];
149     for(size_t i = 0; i < numberOfMethods; i++)
150     {
151         if(*selectedMethod < supportedMethods[i])
152         {
153             *selectedMethod =  supportedMethods[i];
154         }
155     }
156
157     return OC_STACK_OK;
158 }
159
160 /**
161  * Function to select operation mode.This function will return most secure common operation mode.
162  *
163  * @param[in] selectedDeviceInfo   selected device information to performing provisioning.
164  * @param[out]   selectedMode   selected operation mode
165  * @return  OC_STACK_OK on success
166  */
167 static void SelectOperationMode(const OCProvisionDev_t *selectedDeviceInfo,
168                                 OicSecDpom_t *selectedMode)
169 {
170     OC_LOG(DEBUG, TAG, "IN SelectOperationMode");
171
172     size_t i = 0;
173     size_t j = 0;
174
175     while (i < gNumOfProvisioningMethodsPT && j < selectedDeviceInfo->pstat->smLen)
176     {
177         if (gProvisioningToolCapability[i] < selectedDeviceInfo->pstat->sm[j])
178         {
179             i++;
180         }
181         else if (selectedDeviceInfo->pstat->sm[j] < gProvisioningToolCapability[i])
182         {
183             j++;
184         }
185         else /* if gProvisioningToolCapability[i] == deviceSupportedMethods[j] */
186         {
187             *selectedMode = gProvisioningToolCapability[j];
188             break;
189         }
190     }
191     OC_LOG(DEBUG, TAG, "OUT SelectOperationMode");
192 }
193
194 /**
195  * Function to update owner transfer mode
196  *
197  * @param[in]  otmCtx  Context value of ownership transfer.
198  * @return  OC_STACK_OK on success
199  */
200 static OCStackResult PutOwnerTransferModeToResource(OTMContext_t* otmCtx);
201
202 /**
203  * Function to send request to resource to get its pstat resource information.
204  *
205  * @param[in]  otmCtx  Context value of ownership transfer.
206  * @return  OC_STACK_OK on success
207  */
208 static OCStackResult GetProvisioningStatusResource(OTMContext_t* otmCtx);
209
210
211 /**
212  * Function to send ownerShip info. This function would update Owned as true and
213  * owner as UUID for provisioning tool
214  *
215  * @param[in]  otmCtx  Context value of ownership transfer.
216  * @return  OC_STACK_OK on success
217  */
218 static OCStackResult PutOwnershipInformation(OTMContext_t* otmCtx);
219
220 /**
221  * Function to update the operation mode. As per the spec. Operation mode in client driven
222  * single service provisioning it will be updated to 0x3
223  *
224  * @param[in]  otmCtx  Context value of ownership transfer.
225  * @param[in] selectedOperationMode selected operation mode
226  * @return  OC_STACK_OK on success
227  */
228 static OCStackResult PutUpdateOperationMode(OTMContext_t* otmCtx,
229                                     OicSecDpom_t selectedOperationMode);
230
231 /**
232  * Function to start ownership transfer.
233  * This function will send the first request for provisioning,
234  * The next request message is sent from the response handler for this request.
235  *
236  * @param[in] ctx   context value passed to callback from calling function.
237  * @param[in] selectedDevice   selected device information to performing provisioning.
238  * @return  OC_STACK_OK on success
239  */
240 static OCStackResult StartOwnershipTransfer(void* ctx, OCProvisionDev_t* selectedDevice);
241
242 /*
243  * Function to finalize provisioning.
244  * This function will send default ACL and commit hash.
245  *
246  * @param[in] otmCtx   Context value of ownership transfer.
247  * @return  OC_STACK_OK on success
248  */
249 static OCStackResult FinalizeProvisioning(OTMContext_t* otmCtx);
250
251
252 static bool IsComplete(OTMContext_t* otmCtx)
253 {
254     for(size_t i = 0; i < otmCtx->ctxResultArraySize; i++)
255     {
256         if(OC_STACK_CONTINUE == otmCtx->ctxResultArray[i].res)
257         {
258             return false;
259         }
260     }
261
262     return true;
263 }
264
265 /**
266  * Function to save the result of provisioning.
267  *
268  * @param[in,out] otmCtx   Context value of ownership transfer.
269  * @param[in] res   result of provisioning
270  */
271 static void SetResult(OTMContext_t* otmCtx, const OCStackResult res)
272 {
273     OC_LOG(DEBUG, TAG, "IN SetResult");
274
275     if(!otmCtx)
276     {
277         OC_LOG(WARNING, TAG, "OTMContext is NULL");
278         return;
279     }
280
281     if(otmCtx->selectedDeviceInfo)
282     {
283         for(size_t i = 0; i < otmCtx->ctxResultArraySize; i++)
284         {
285             if(memcmp(otmCtx->selectedDeviceInfo->doxm->deviceID.id,
286                       otmCtx->ctxResultArray[i].deviceId.id, UUID_LENGTH) == 0)
287             {
288                 otmCtx->ctxResultArray[i].res = res;
289                 if(OC_STACK_OK != res)
290                 {
291                     otmCtx->ctxHasError = true;
292                 }
293             }
294         }
295
296         //If all request is completed, invoke the user callback.
297         if(IsComplete(otmCtx))
298         {
299             otmCtx->ctxResultCallback(otmCtx->userCtx, otmCtx->ctxResultArraySize,
300                                        otmCtx->ctxResultArray, otmCtx->ctxHasError);
301             OICFree(otmCtx->ctxResultArray);
302             OICFree(otmCtx);
303         }
304         else
305         {
306             if(OC_STACK_OK != StartOwnershipTransfer(otmCtx,
307                                                      otmCtx->selectedDeviceInfo->next))
308             {
309                 OC_LOG(ERROR, TAG, "Failed to StartOwnershipTransfer");
310             }
311         }
312     }
313
314     OC_LOG(DEBUG, TAG, "OUT SetResult");
315 }
316
317
318 /**
319  * Function to save ownerPSK at provisioning tool end.
320  *
321  * @param[in] selectedDeviceInfo   selected device information to performing provisioning.
322  * @return  OC_STACK_OK on success
323  */
324 static OCStackResult SaveOwnerPSK(OCProvisionDev_t *selectedDeviceInfo)
325 {
326     OC_LOG(DEBUG, TAG, "IN SaveOwnerPSK");
327
328     OCStackResult res = OC_STACK_ERROR;
329
330     CAEndpoint_t endpoint;
331     memset(&endpoint, 0x00, sizeof(CAEndpoint_t));
332     OICStrcpy(endpoint.addr, MAX_ADDR_STR_SIZE_CA, selectedDeviceInfo->endpoint.addr);
333     endpoint.addr[MAX_ADDR_STR_SIZE_CA - 1] = '\0';
334     endpoint.port = selectedDeviceInfo->securePort;
335
336     OicUuid_t ptDeviceID = {.id={0}};
337     if (OC_STACK_OK != GetDoxmDeviceID(&ptDeviceID))
338     {
339         OC_LOG(ERROR, TAG, "Error while retrieving provisioning tool's device ID");
340         return res;
341     }
342
343     uint8_t ownerPSK[OWNER_PSK_LENGTH_128] = {0};
344
345     //Generating OwnerPSK
346     CAResult_t pskRet = CAGenerateOwnerPSK(&endpoint,
347             (uint8_t *)GetOxmString(selectedDeviceInfo->doxm->oxmSel),
348             strlen(GetOxmString(selectedDeviceInfo->doxm->oxmSel)), ptDeviceID.id,
349             sizeof(ptDeviceID.id), selectedDeviceInfo->doxm->deviceID.id,
350             sizeof(selectedDeviceInfo->doxm->deviceID.id), ownerPSK,
351             OWNER_PSK_LENGTH_128);
352
353     if (CA_STATUS_OK == pskRet)
354     {
355         OC_LOG(INFO, TAG,"ownerPSK dump:\n");
356         OC_LOG_BUFFER(INFO, TAG,ownerPSK, OWNER_PSK_LENGTH_128);
357         //Generating new credential for provisioning tool
358         size_t ownLen = 1;
359         uint32_t outLen = 0;
360
361         char base64Buff[B64ENCODE_OUT_SAFESIZE(sizeof(ownerPSK)) + 1] = {};
362         B64Result b64Ret = b64Encode(ownerPSK, sizeof(ownerPSK), base64Buff, sizeof(base64Buff),
363                 &outLen);
364         VERIFY_SUCCESS(TAG, B64_OK == b64Ret, ERROR);
365
366         OicSecCred_t *cred = GenerateCredential(&selectedDeviceInfo->doxm->deviceID,
367                 SYMMETRIC_PAIR_WISE_KEY, NULL,
368                 base64Buff, ownLen, &ptDeviceID);
369         VERIFY_NON_NULL(TAG, cred, ERROR);
370
371         res = AddCredential(cred);
372         if(res != OC_STACK_OK)
373         {
374             DeleteCredList(cred);
375             return res;
376         }
377     }
378     else
379     {
380         OC_LOG(ERROR, TAG, "CAGenerateOwnerPSK failed");
381     }
382
383     OC_LOG(DEBUG, TAG, "OUT SaveOwnerPSK");
384 exit:
385     return res;
386 }
387
388 /**
389  * Callback handler for OwnerShipTransferModeHandler API.
390  *
391  * @param[in] ctx             ctx value passed to callback from calling function.
392  * @param[in] UNUSED          handle to an invocation
393  * @param[in] clientResponse  Response from queries to remote servers.
394  * @return  OC_STACK_DELETE_TRANSACTION to delete the transaction
395  *          and  OC_STACK_KEEP_TRANSACTION to keep it.
396  */
397 static OCStackApplicationResult OwnerTransferModeHandler(void *ctx, OCDoHandle UNUSED,
398                                                          OCClientResponse *clientResponse)
399 {
400     OC_LOG(DEBUG, TAG, "IN OwnerTransferModeHandler");
401
402     VERIFY_NON_NULL(TAG, clientResponse, WARNING);
403     VERIFY_NON_NULL(TAG, ctx, WARNING);
404
405     OTMContext_t* otmCtx = (OTMContext_t*)ctx;
406     (void)UNUSED;
407     if(clientResponse->result == OC_STACK_OK)
408     {
409         OC_LOG(INFO, TAG, "OwnerTransferModeHandler : response result = OC_STACK_OK");
410         //Send request : GET /oic/sec/pstat
411         OCStackResult res = GetProvisioningStatusResource(otmCtx);
412         if(OC_STACK_OK != res)
413         {
414             OC_LOG(WARNING, TAG, "Failed to get pstat information");
415             SetResult(otmCtx, res);
416         }
417     }
418     else
419     {
420         OC_LOG_V(WARNING, TAG, "OwnerTransferModeHandler : Client response is incorrect : %d",
421         clientResponse->result);
422         SetResult(otmCtx, clientResponse->result);
423     }
424
425     OC_LOG(DEBUG, TAG, "OUT OwnerTransferModeHandler");
426
427 exit:
428     return  OC_STACK_DELETE_TRANSACTION;
429 }
430
431 /**
432  * Callback handler for ProvisioningStatusResouceHandler API.
433  *
434  * @param[in] ctx             ctx value passed to callback from calling function.
435  * @param[in] UNUSED          handle to an invocation
436  * @param[in] clientResponse  Response from queries to remote servers.
437  * @return  OC_STACK_DELETE_TRANSACTION to delete the transaction
438  *          and  OC_STACK_KEEP_TRANSACTION to keep it.
439  */
440 static OCStackApplicationResult ListMethodsHandler(void *ctx, OCDoHandle UNUSED,
441                                                     OCClientResponse *clientResponse)
442 {
443     OC_LOG(DEBUG, TAG, "IN ListMethodsHandler");
444
445     VERIFY_NON_NULL(TAG, clientResponse, WARNING);
446     VERIFY_NON_NULL(TAG, ctx, WARNING);
447
448     OTMContext_t* otmCtx = (OTMContext_t*)ctx;
449     (void)UNUSED;
450     if  (OC_STACK_OK == clientResponse->result)
451     {
452         if  (NULL == clientResponse->payload)
453         {
454             OC_LOG(INFO, TAG, "Skiping Null payload");
455             SetResult(otmCtx, OC_STACK_ERROR);
456             return OC_STACK_DELETE_TRANSACTION;
457         }
458
459         if (PAYLOAD_TYPE_SECURITY != clientResponse->payload->type)
460         {
461             OC_LOG(INFO, TAG, "Unknown payload type");
462             SetResult(otmCtx, OC_STACK_ERROR);
463             return OC_STACK_DELETE_TRANSACTION;
464         }
465
466         OicSecPstat_t* pstat = JSONToPstatBin(
467                 ((OCSecurityPayload*)clientResponse->payload)->securityData);
468         if(NULL == pstat)
469         {
470             OC_LOG(ERROR, TAG, "Error while converting json to pstat bin");
471             SetResult(otmCtx, OC_STACK_ERROR);
472             return OC_STACK_DELETE_TRANSACTION;
473         }
474         otmCtx->selectedDeviceInfo->pstat = pstat;
475
476         //Select operation mode (Currently supported SINGLE_SERVICE_CLIENT_DRIVEN only)
477         OicSecDpom_t selectedOperationMode;
478         SelectOperationMode(otmCtx->selectedDeviceInfo, &selectedOperationMode);
479
480         //Send request : PUT /oic/sec/pstat [{"OM":"0x11", .. }]
481         OCStackResult res = PutUpdateOperationMode(otmCtx, selectedOperationMode);
482         if (OC_STACK_OK != res)
483         {
484             OC_LOG(ERROR, TAG, "Error while updating operation mode.");
485             SetResult(otmCtx, res);
486         }
487     }
488     else
489     {
490         OC_LOG_V(WARNING, TAG, "ListMethodsHandler : Client response is incorrect : %d",
491             clientResponse->result);
492         SetResult(otmCtx, clientResponse->result);
493     }
494
495     OC_LOG(DEBUG, TAG, "OUT ListMethodsHandler");
496 exit:
497     return  OC_STACK_DELETE_TRANSACTION;
498 }
499
500 /**
501  * Callback handler for OwnershipInformationHandler API.
502  *
503  * @param[in] ctx             ctx value passed to callback from calling function.
504  * @param[in] UNUSED          handle to an invocation
505  * @param[in] clientResponse  Response from queries to remote servers.
506  * @return  OC_STACK_DELETE_TRANSACTION to delete the transaction
507  *          and  OC_STACK_KEEP_TRANSACTION to keep it.
508  */
509 static OCStackApplicationResult OwnershipInformationHandler(void *ctx, OCDoHandle UNUSED,
510                                 OCClientResponse *clientResponse)
511 {
512     VERIFY_NON_NULL(TAG, clientResponse, WARNING);
513     VERIFY_NON_NULL(TAG, ctx, WARNING);
514
515     OC_LOG(DEBUG, TAG, "IN OwnershipInformationHandler");
516     (void)UNUSED;
517     OCStackResult res = OC_STACK_OK;
518     OTMContext_t* otmCtx = (OTMContext_t*)ctx;
519     if  (OC_STACK_OK == clientResponse->result)
520     {
521         if(OIC_RANDOM_DEVICE_PIN == otmCtx->selectedDeviceInfo->doxm->oxmSel)
522         {
523             res = RemoveCredential(&otmCtx->subIdForPinOxm);
524             if(OC_STACK_RESOURCE_DELETED != res)
525             {
526                 OC_LOG_V(ERROR, TAG, "Failed to remove temporal PSK : %d", res);
527                 return OC_STACK_DELETE_TRANSACTION;
528             }
529         }
530
531         res = SaveOwnerPSK(otmCtx->selectedDeviceInfo);
532         if(OC_STACK_OK != res)
533         {
534             OC_LOG(ERROR, TAG, "OperationModeUpdate : Failed to owner PSK generation");
535             SetResult(otmCtx, res);
536             return OC_STACK_DELETE_TRANSACTION;
537         }
538
539         CAEndpoint_t* endpoint = (CAEndpoint_t *)&otmCtx->selectedDeviceInfo->endpoint;
540         endpoint->port = otmCtx->selectedDeviceInfo->securePort;
541         CAResult_t closeRes = CACloseDtlsSession(endpoint);
542         if(CA_STATUS_OK != closeRes)
543         {
544             OC_LOG(ERROR, TAG, "Failed to close DTLS session");
545             SetResult(otmCtx, closeRes);
546             return OC_STACK_DELETE_TRANSACTION;
547         }
548
549         OC_LOG(INFO, TAG, "Ownership transfer was successfully completed.");
550         OC_LOG(INFO, TAG, "Start defualt ACL & commit-hash provisioning.");
551
552         res = FinalizeProvisioning(otmCtx);
553         if(OC_STACK_OK != res)
554         {
555             SetResult(otmCtx, res);
556         }
557     }
558     else
559     {
560         res = clientResponse->result;
561     }
562
563     OC_LOG(DEBUG, TAG, "OUT OwnershipInformationHandler");
564
565 exit:
566     return  OC_STACK_DELETE_TRANSACTION;
567 }
568
569 /**
570  * Response handler for update operation mode.
571  *
572  * @param[in] ctx             ctx value passed to callback from calling function.
573  * @param[in] UNUSED          handle to an invocation
574  * @param[in] clientResponse  Response from queries to remote servers.
575  * @return  OC_STACK_DELETE_TRANSACTION to delete the transaction
576  *          and  OC_STACK_KEEP_TRANSACTION to keep it.
577  */
578 static OCStackApplicationResult OperationModeUpdateHandler(void *ctx, OCDoHandle UNUSED,
579                                 OCClientResponse *clientResponse)
580 {
581     OC_LOG(DEBUG, TAG, "IN OperationModeUpdateHandler");
582
583     VERIFY_NON_NULL(TAG, clientResponse, WARNING);
584     VERIFY_NON_NULL(TAG, ctx, WARNING);
585
586     OTMContext_t* otmCtx = (OTMContext_t*)ctx;
587     (void) UNUSED;
588     if  (OC_STACK_OK == clientResponse->result)
589     {
590         OCStackResult res = OC_STACK_ERROR;
591         OicSecOxm_t selOxm = otmCtx->selectedDeviceInfo->doxm->oxmSel;
592         //DTLS Handshake
593         //Load secret for temporal secure session.
594         if(g_OTMDatas[selOxm].loadSecretCB)
595         {
596             res = g_OTMDatas[selOxm].loadSecretCB(otmCtx);
597             if(OC_STACK_OK != res)
598             {
599                 OC_LOG(ERROR, TAG, "OperationModeUpdate : Failed to load secret");
600                 SetResult(otmCtx, res);
601                 return  OC_STACK_DELETE_TRANSACTION;
602             }
603         }
604
605         //Try DTLS handshake to generate secure session
606         if(g_OTMDatas[selOxm].createSecureSessionCB)
607         {
608             res = g_OTMDatas[selOxm].createSecureSessionCB(otmCtx);
609             if(OC_STACK_OK != res)
610             {
611                 OC_LOG(ERROR, TAG, "OperationModeUpdate : Failed to create DTLS session");
612                 SetResult(otmCtx, res);
613                 return OC_STACK_DELETE_TRANSACTION;
614             }
615         }
616
617         //Send request : PUT /oic/sec/doxm [{"Owned":"True", .. , "Owner":"PT's UUID"}]
618         res = PutOwnershipInformation(otmCtx);
619         if(OC_STACK_OK != res)
620         {
621             OC_LOG(ERROR, TAG, "OperationModeUpdate : Failed to send owner information");
622             SetResult(otmCtx, res);
623         }
624     }
625     else
626     {
627         OC_LOG(ERROR, TAG, "Error while update operation mode");
628         SetResult(otmCtx, clientResponse->result);
629     }
630
631     OC_LOG(DEBUG, TAG, "OUT OperationModeUpdateHandler");
632
633 exit:
634     return  OC_STACK_DELETE_TRANSACTION;
635 }
636
637
638 static OCStackResult PutOwnerTransferModeToResource(OTMContext_t* otmCtx)
639 {
640     OC_LOG(DEBUG, TAG, "IN PutOwnerTransferModeToResource");
641
642     if(!otmCtx || !otmCtx->selectedDeviceInfo)
643     {
644         OC_LOG(ERROR, TAG, "Invalid parameters");
645         return OC_STACK_INVALID_PARAM;
646     }
647
648     OCProvisionDev_t* deviceInfo = otmCtx->selectedDeviceInfo;
649     OicSecOxm_t selectedOxm = deviceInfo->doxm->oxmSel;
650     char query[MAX_URI_LENGTH + MAX_QUERY_LENGTH] = {0};
651
652     if(!PMGenerateQuery(false,
653                         deviceInfo->endpoint.addr, deviceInfo->endpoint.port,
654                         deviceInfo->connType,
655                         query, sizeof(query), OIC_RSRC_DOXM_URI))
656     {
657         OC_LOG(ERROR, TAG, "PutOwnerTransferModeToResource : Failed to generate query");
658         return OC_STACK_ERROR;
659     }
660     OC_LOG_V(DEBUG, TAG, "Query=%s", query);
661     OCSecurityPayload* secPayload = (OCSecurityPayload*)OICCalloc(1, sizeof(OCSecurityPayload));
662     if(!secPayload)
663     {
664         OC_LOG(ERROR, TAG, "Failed to memory allocation");
665         return OC_STACK_NO_MEMORY;
666     }
667     secPayload->base.type = PAYLOAD_TYPE_SECURITY;
668     secPayload->securityData = g_OTMDatas[selectedOxm].createSelectOxmPayloadCB(otmCtx);
669     if (NULL == secPayload->securityData)
670     {
671         OICFree(secPayload);
672         OC_LOG(ERROR, TAG, "Error while converting bin to json");
673         return OC_STACK_ERROR;
674     }
675     OC_LOG_V(DEBUG, TAG, "Payload : %s", secPayload->securityData);
676
677     OCCallbackData cbData;
678     cbData.cb = &OwnerTransferModeHandler;
679     cbData.context = (void *)otmCtx;
680     cbData.cd = NULL;
681     OCStackResult res = OCDoResource(NULL, OC_REST_PUT, query,
682                                      &deviceInfo->endpoint, (OCPayload*)secPayload,
683                                      deviceInfo->connType, OC_LOW_QOS, &cbData, NULL, 0);
684     if (res != OC_STACK_OK)
685     {
686         OC_LOG(ERROR, TAG, "OCStack resource error");
687     }
688
689     OC_LOG(DEBUG, TAG, "OUT PutOwnerTransferModeToResource");
690
691     return res;
692 }
693
694 static OCStackResult GetProvisioningStatusResource(OTMContext_t* otmCtx)
695 {
696     OC_LOG(DEBUG, TAG, "IN GetProvisioningStatusResource");
697
698     if(!otmCtx || !otmCtx->selectedDeviceInfo)
699     {
700         OC_LOG(ERROR, TAG, "Invailed parameters");
701         return OC_STACK_INVALID_PARAM;
702     }
703
704     OCProvisionDev_t* deviceInfo = otmCtx->selectedDeviceInfo;
705     char query[MAX_URI_LENGTH + MAX_QUERY_LENGTH] = {0};
706     if(!PMGenerateQuery(false,
707                         deviceInfo->endpoint.addr, deviceInfo->endpoint.port,
708                         deviceInfo->connType,
709                         query, sizeof(query), OIC_RSRC_PSTAT_URI))
710     {
711         OC_LOG(ERROR, TAG, "GetProvisioningStatusResource : Failed to generate query");
712         return OC_STACK_ERROR;
713     }
714     OC_LOG_V(DEBUG, TAG, "Query=%s", query);
715
716     OCCallbackData cbData;
717     cbData.cb = &ListMethodsHandler;
718     cbData.context = (void *)otmCtx;
719     cbData.cd = NULL;
720     OCStackResult res = OCDoResource(NULL, OC_REST_GET, query, NULL, NULL,
721                                      deviceInfo->connType, OC_LOW_QOS, &cbData, NULL, 0);
722     if (res != OC_STACK_OK)
723     {
724         OC_LOG(ERROR, TAG, "OCStack resource error");
725     }
726
727     OC_LOG(DEBUG, TAG, "OUT GetProvisioningStatusResource");
728
729     return res;
730 }
731
732
733 static OCStackResult PutOwnershipInformation(OTMContext_t* otmCtx)
734 {
735     OC_LOG(DEBUG, TAG, "IN PutOwnershipInformation");
736
737     if(!otmCtx || !otmCtx->selectedDeviceInfo)
738     {
739         OC_LOG(ERROR, TAG, "Invailed parameters");
740         return OC_STACK_INVALID_PARAM;
741     }
742
743     OCProvisionDev_t* deviceInfo = otmCtx->selectedDeviceInfo;
744     char query[MAX_URI_LENGTH + MAX_QUERY_LENGTH] = {0};
745     if(!PMGenerateQuery(true,
746                         deviceInfo->endpoint.addr, deviceInfo->securePort,
747                         deviceInfo->connType,
748                         query, sizeof(query), OIC_RSRC_DOXM_URI))
749     {
750         OC_LOG(ERROR, TAG, "PutOwnershipInformation : Failed to generate query");
751         return OC_STACK_ERROR;
752     }
753     OC_LOG_V(DEBUG, TAG, "Query=%s", query);
754
755     //OwnershipInformationHandler
756     OicSecOxm_t selOxm = deviceInfo->doxm->oxmSel;
757     OCSecurityPayload* secPayload = (OCSecurityPayload*)OICCalloc(1, sizeof(OCSecurityPayload));
758     if(!secPayload)
759     {
760         OC_LOG(ERROR, TAG, "Failed to memory allocation");
761         return OC_STACK_NO_MEMORY;
762     }
763     secPayload->base.type = PAYLOAD_TYPE_SECURITY;
764     secPayload->securityData = g_OTMDatas[selOxm].createOwnerTransferPayloadCB(otmCtx);
765     if (NULL == secPayload->securityData)
766     {
767         OICFree(secPayload);
768         OC_LOG(ERROR, TAG, "Error while converting doxm bin to json");
769         return OC_STACK_INVALID_PARAM;
770     }
771
772     OCCallbackData cbData;
773     cbData.cb = &OwnershipInformationHandler;
774     cbData.context = (void *)otmCtx;
775     cbData.cd = NULL;
776     OCStackResult res = OCDoResource(NULL, OC_REST_PUT, query, 0, (OCPayload*)secPayload,
777                                      deviceInfo->connType, OC_LOW_QOS, &cbData, NULL, 0);
778     if (res != OC_STACK_OK)
779     {
780         OC_LOG(ERROR, TAG, "OCStack resource error");
781     }
782
783     OC_LOG(DEBUG, TAG, "OUT PutOwnershipInformation");
784
785     return res;
786 }
787
788 static OCStackResult PutUpdateOperationMode(OTMContext_t* otmCtx,
789                                     OicSecDpom_t selectedOperationMode)
790 {
791     OC_LOG(DEBUG, TAG, "IN PutUpdateOperationMode");
792
793     if(!otmCtx || !otmCtx->selectedDeviceInfo)
794     {
795         return OC_STACK_INVALID_PARAM;
796     }
797
798     OCProvisionDev_t* deviceInfo = otmCtx->selectedDeviceInfo;
799     char query[MAX_URI_LENGTH + MAX_QUERY_LENGTH] = {0};
800     if(!PMGenerateQuery(false,
801                         deviceInfo->endpoint.addr, deviceInfo->endpoint.port,
802                         deviceInfo->connType,
803                         query, sizeof(query), OIC_RSRC_PSTAT_URI))
804     {
805         OC_LOG(ERROR, TAG, "PutUpdateOperationMode : Failed to generate query");
806         return OC_STACK_ERROR;
807     }
808     OC_LOG_V(DEBUG, TAG, "Query=%s", query);
809
810     deviceInfo->pstat->om = selectedOperationMode;
811
812     OCSecurityPayload* secPayload = (OCSecurityPayload*)OICCalloc(1, sizeof(OCSecurityPayload));
813     if(!secPayload)
814     {
815         OC_LOG(ERROR, TAG, "Failed to memory allocation");
816         return OC_STACK_NO_MEMORY;
817     }
818     secPayload->base.type = PAYLOAD_TYPE_SECURITY;
819     secPayload->securityData = BinToPstatJSON(deviceInfo->pstat);
820     if (NULL == secPayload->securityData)
821     {
822         OICFree(secPayload);
823         OC_LOG(ERROR, TAG, "Error while converting pstat bin to json");
824         return OC_STACK_INVALID_PARAM;
825     }
826
827     OCCallbackData cbData;
828     cbData.cb = &OperationModeUpdateHandler;
829     cbData.context = (void *)otmCtx;
830     cbData.cd = NULL;
831     OCStackResult res = OCDoResource(NULL, OC_REST_PUT, query, 0, (OCPayload*)secPayload,
832                                      deviceInfo->connType, OC_LOW_QOS, &cbData, NULL, 0);
833     if (res != OC_STACK_OK)
834     {
835         OC_LOG(ERROR, TAG, "OCStack resource error");
836     }
837
838     OC_LOG(DEBUG, TAG, "OUT PutUpdateOperationMode");
839
840     return res;
841 }
842
843 static OCStackResult StartOwnershipTransfer(void* ctx, OCProvisionDev_t* selectedDevice)
844 {
845     OC_LOG(INFO, TAG, "IN StartOwnershipTransfer");
846     OTMContext_t* otmCtx = (OTMContext_t*)ctx;
847     otmCtx->selectedDeviceInfo = selectedDevice;
848
849     //Set to the lowest level OxM, and then find more higher level OxM.
850     OCStackResult res = SelectProvisioningMethod(selectedDevice->doxm->oxm,
851                                                  selectedDevice->doxm->oxmLen,
852                                                  &selectedDevice->doxm->oxmSel);
853     if(OC_STACK_OK != res)
854     {
855         OC_LOG(ERROR, TAG, "Failed to select the provisioning method");
856         SetResult(otmCtx, res);
857         return res;
858     }
859     OC_LOG_V(DEBUG, TAG, "Selected provisoning method = %d", selectedDevice->doxm->oxmSel);
860
861     //Send Req: PUT /oic/sec/doxm [{..."OxmSel" :g_OTMDatas[Index of Selected OxM].OXMString,...}]
862     res = PutOwnerTransferModeToResource(otmCtx);
863     if(OC_STACK_OK != res)
864     {
865         OC_LOG(WARNING, TAG, "Failed to select the provisioning method");
866         SetResult(otmCtx, res);
867         return res;
868     }
869
870     OC_LOG(INFO, TAG, "OUT StartOwnershipTransfer");
871
872     return res;
873
874 }
875
876 OCStackResult OTMSetOwnershipTransferCallbackData(OicSecOxm_t oxmType, OTMCallbackData_t* data)
877 {
878     OC_LOG(DEBUG, TAG, "IN OTMSetOwnerTransferCallbackData");
879
880     if(!data)
881     {
882         OC_LOG(ERROR, TAG, "OTMSetOwnershipTransferCallbackData : Invalid parameters");
883         return OC_STACK_INVALID_PARAM;
884     }
885     if(oxmType >= OIC_OXM_COUNT)
886     {
887         OC_LOG(INFO, TAG, "Unknow ownership transfer method");
888         return OC_STACK_INVALID_PARAM;
889     }
890
891     g_OTMDatas[oxmType].loadSecretCB= data->loadSecretCB;
892     g_OTMDatas[oxmType].createSecureSessionCB = data->createSecureSessionCB;
893     g_OTMDatas[oxmType].createSelectOxmPayloadCB = data->createSelectOxmPayloadCB;
894     g_OTMDatas[oxmType].createOwnerTransferPayloadCB = data->createOwnerTransferPayloadCB;
895
896     OC_LOG(DEBUG, TAG, "OUT OTMSetOwnerTransferCallbackData");
897
898     return OC_STACK_OK;
899 }
900
901 /**
902  * NOTE : Unowned discovery should be done before performing OTMDoOwnershipTransfer
903  */
904 OCStackResult OTMDoOwnershipTransfer(void* ctx,
905                                      OCProvisionDev_t *selectedDevicelist,
906                                      OCProvisionResultCB resultCallback)
907 {
908     OC_LOG(DEBUG, TAG, "IN OTMDoOwnershipTransfer");
909
910     if (NULL == selectedDevicelist || NULL == resultCallback )
911     {
912         return OC_STACK_INVALID_PARAM;
913     }
914
915     OTMContext_t* otmCtx = (OTMContext_t*)OICCalloc(1,sizeof(OTMContext_t));
916     if(!otmCtx)
917     {
918         OC_LOG(ERROR, TAG, "Failed to create OTM Context");
919         return OC_STACK_NO_MEMORY;
920     }
921     otmCtx->ctxResultCallback = resultCallback;
922     otmCtx->ctxHasError = false;
923     otmCtx->userCtx = ctx;
924     OCProvisionDev_t* pCurDev = selectedDevicelist;
925
926     //Counting number of selected devices.
927     otmCtx->ctxResultArraySize = 0;
928     while(NULL != pCurDev)
929     {
930         otmCtx->ctxResultArraySize++;
931         pCurDev = pCurDev->next;
932     }
933
934     otmCtx->ctxResultArray =
935         (OCProvisionResult_t*)OICCalloc(otmCtx->ctxResultArraySize, sizeof(OCProvisionResult_t));
936     if(NULL == otmCtx->ctxResultArray)
937     {
938         OC_LOG(ERROR, TAG, "OTMDoOwnershipTransfer : Failed to memory allocation");
939         OICFree(otmCtx);
940         return OC_STACK_NO_MEMORY;
941     }
942     pCurDev = selectedDevicelist;
943
944     //Fill the device UUID for result array.
945     for(size_t devIdx = 0; devIdx < otmCtx->ctxResultArraySize; devIdx++)
946     {
947         //Checking duplication of Device ID.
948         if(true == PDMIsDuplicateDevice(&pCurDev->doxm->deviceID))
949         {
950             OC_LOG(ERROR, TAG, "OTMDoOwnershipTransfer : Device ID is duplicate");
951             OICFree(otmCtx->ctxResultArray);
952             OICFree(otmCtx);
953             return OC_STACK_INVALID_PARAM;
954         }
955         memcpy(otmCtx->ctxResultArray[devIdx].deviceId.id,
956                pCurDev->doxm->deviceID.id,
957                UUID_LENGTH);
958         otmCtx->ctxResultArray[devIdx].res = OC_STACK_CONTINUE;
959         pCurDev = pCurDev->next;
960     }
961     StartOwnershipTransfer(otmCtx, selectedDevicelist);
962
963     OC_LOG(DEBUG, TAG, "OUT OTMDoOwnershipTransfer");
964     return OC_STACK_OK;
965 }
966
967 /**
968  * Callback handler of SRPFinalizeProvisioning.
969  *
970  * @param[in] ctx             ctx value passed to callback from calling function.
971  * @param[in] UNUSED          handle to an invocation
972  * @param[in] clientResponse  Response from queries to remote servers.
973  * @return  OC_STACK_DELETE_TRANSACTION to delete the transaction
974  *          and OC_STACK_KEEP_TRANSACTION to keep it.
975  */
976 static OCStackApplicationResult FinalizeProvisioningCB(void *ctx, OCDoHandle UNUSED,
977                                                        OCClientResponse *clientResponse)
978 {
979     OC_LOG_V(INFO, TAG, "IN FinalizeProvisioningCB.");
980
981     VERIFY_NON_NULL(TAG, clientResponse, ERROR);
982     VERIFY_NON_NULL(TAG, ctx, ERROR);
983
984     OTMContext_t* otmCtx = (OTMContext_t*)ctx;
985     (void)UNUSED;
986     if(OC_STACK_OK == clientResponse->result)
987     {
988         OCStackResult res = PDMAddDevice(&otmCtx->selectedDeviceInfo->doxm->deviceID);
989
990          if (OC_STACK_OK == res)
991          {
992                 OC_LOG_V(INFO, TAG, "Add device's UUID in PDM_DB");
993                 SetResult(otmCtx, OC_STACK_OK);
994                 return OC_STACK_DELETE_TRANSACTION;
995          }
996          else
997          {
998               OC_LOG(ERROR, TAG, "Ownership transfer is complete but adding information to DB is failed.");
999          }
1000     }
1001 exit:
1002     return OC_STACK_DELETE_TRANSACTION;
1003 }
1004
1005 /**
1006  * Callback handler of default ACL provisioning.
1007  *
1008  * @param[in] ctx             ctx value passed to callback from calling function.
1009  * @param[in] UNUSED          handle to an invocation
1010  * @param[in] clientResponse  Response from queries to remote servers.
1011  * @return  OC_STACK_DELETE_TRANSACTION to delete the transaction
1012  *          and OC_STACK_KEEP_TRANSACTION to keep it.
1013  */
1014 static OCStackApplicationResult ProvisionDefaultACLCB(void *ctx, OCDoHandle UNUSED,
1015                                                        OCClientResponse *clientResponse)
1016 {
1017     OC_LOG_V(INFO, TAG, "IN ProvisionDefaultACLCB.");
1018
1019     VERIFY_NON_NULL(TAG, clientResponse, ERROR);
1020     VERIFY_NON_NULL(TAG, ctx, ERROR);
1021
1022     OTMContext_t* otmCtx = (OTMContext_t*) ctx;
1023     (void)UNUSED;
1024
1025     if (OC_STACK_RESOURCE_CREATED == clientResponse->result)
1026     {
1027         OC_LOG_V(INFO, TAG, "Staring commit hash task.");
1028         // TODO hash currently have fixed value 0.
1029         uint16_t aclHash = 0;
1030         otmCtx->selectedDeviceInfo->pstat->commitHash = aclHash;
1031         otmCtx->selectedDeviceInfo->pstat->tm = NORMAL;
1032         OCSecurityPayload* secPayload = (OCSecurityPayload*)OICCalloc(1, sizeof(OCSecurityPayload));
1033         if(!secPayload)
1034         {
1035             OC_LOG(ERROR, TAG, "Failed to memory allocation");
1036             return OC_STACK_NO_MEMORY;
1037         }
1038         secPayload->base.type = PAYLOAD_TYPE_SECURITY;
1039         secPayload->securityData = BinToPstatJSON(otmCtx->selectedDeviceInfo->pstat);
1040         if (NULL == secPayload->securityData)
1041         {
1042             OICFree(secPayload);
1043             SetResult(otmCtx, OC_STACK_INVALID_JSON);
1044             return OC_STACK_DELETE_TRANSACTION;
1045         }
1046         OC_LOG_V(INFO, TAG, "Created payload for commit hash: %s",secPayload->securityData);
1047
1048         char query[MAX_URI_LENGTH + MAX_QUERY_LENGTH] = {0};
1049         if(!PMGenerateQuery(true,
1050                             otmCtx->selectedDeviceInfo->endpoint.addr,
1051                             otmCtx->selectedDeviceInfo->securePort,
1052                             otmCtx->selectedDeviceInfo->connType,
1053                             query, sizeof(query), OIC_RSRC_PSTAT_URI))
1054         {
1055             OC_LOG(ERROR, TAG, "ProvisionDefaultACLCB : Failed to generate query");
1056             return OC_STACK_ERROR;
1057         }
1058         OC_LOG_V(DEBUG, TAG, "Query=%s", query);
1059
1060         OCCallbackData cbData = {.context=NULL, .cb=NULL, .cd=NULL};
1061         cbData.cb = &FinalizeProvisioningCB;
1062         cbData.context = (void*)otmCtx;
1063         cbData.cd = NULL;
1064         OCStackResult ret = OCDoResource(NULL, OC_REST_PUT, query, 0, (OCPayload*)secPayload,
1065                 otmCtx->selectedDeviceInfo->connType, OC_HIGH_QOS, &cbData, NULL, 0);
1066         OC_LOG_V(INFO, TAG, "OCDoResource returned: %d",ret);
1067         if (ret != OC_STACK_OK)
1068         {
1069             OC_LOG(ERROR, TAG, "OCStack resource error");
1070             SetResult(otmCtx, ret);
1071         }
1072     }
1073     else
1074     {
1075         OC_LOG_V(INFO, TAG, "Error occured in provisionDefaultACLCB :: %d\n",
1076                             clientResponse->result);
1077         SetResult(otmCtx, clientResponse->result);
1078     }
1079 exit:
1080     return OC_STACK_DELETE_TRANSACTION;
1081 }
1082
1083
1084 OCStackResult FinalizeProvisioning(OTMContext_t* otmCtx)
1085 {
1086     OC_LOG(INFO, TAG, "IN FinalizeProvisioning");
1087
1088     if(!otmCtx)
1089     {
1090         OC_LOG(ERROR, TAG, "OTMContext is NULL");
1091         return OC_STACK_INVALID_PARAM;
1092     }
1093     if(!otmCtx->selectedDeviceInfo)
1094     {
1095         OC_LOG(ERROR, TAG, "Can't find device information in OTMContext");
1096         OICFree(otmCtx);
1097         return OC_STACK_INVALID_PARAM;
1098     }
1099     // Provision Default ACL to device
1100     OicSecAcl_t defaultAcl =
1101     { {.id={0}},
1102         1,
1103         NULL,
1104         0x001F,
1105         0,
1106         NULL,
1107         NULL,
1108         1,
1109         NULL,
1110         NULL,
1111     };
1112
1113     OicUuid_t provTooldeviceID = {.id={0}};
1114     if (OC_STACK_OK != GetDoxmDeviceID(&provTooldeviceID))
1115     {
1116         OC_LOG(ERROR, TAG, "Error while retrieving provisioning tool's device ID");
1117         SetResult(otmCtx, OC_STACK_ERROR);
1118         return OC_STACK_ERROR;
1119     }
1120     OC_LOG(INFO, TAG, "Retieved deviceID");
1121     memcpy(defaultAcl.subject.id, provTooldeviceID.id, sizeof(defaultAcl.subject.id));
1122     char *wildCardResource = "*";
1123     defaultAcl.resources = &wildCardResource;
1124
1125     defaultAcl.owners = (OicUuid_t *) OICCalloc(1, UUID_LENGTH);
1126     if(!defaultAcl.owners)
1127     {
1128         OC_LOG(ERROR, TAG, "Failed to memory allocation for default ACL");
1129         SetResult(otmCtx, OC_STACK_NO_MEMORY);
1130         return OC_STACK_NO_MEMORY;
1131     }
1132     memcpy(defaultAcl.owners->id, provTooldeviceID.id, UUID_LENGTH);
1133     OC_LOG(INFO, TAG, "Provisioning default ACL");
1134
1135     OCSecurityPayload* secPayload = (OCSecurityPayload*)OICCalloc(1, sizeof(OCSecurityPayload));
1136     if(!secPayload)
1137     {
1138         OC_LOG(ERROR, TAG, "Failed to memory allocation");
1139         return OC_STACK_NO_MEMORY;
1140     }
1141     secPayload->base.type = PAYLOAD_TYPE_SECURITY;
1142     secPayload->securityData = BinToAclJSON(&defaultAcl);
1143     OICFree(defaultAcl.owners);
1144     if(!secPayload->securityData)
1145     {
1146         OICFree(secPayload);
1147         OC_LOG(INFO, TAG, "FinalizeProvisioning : Failed to BinToAclJSON");
1148         SetResult(otmCtx, OC_STACK_ERROR);
1149         return OC_STACK_ERROR;
1150     }
1151     OC_LOG_V(INFO, TAG, "Provisioning default ACL : %s",secPayload->securityData);
1152
1153     char query[MAX_URI_LENGTH + MAX_QUERY_LENGTH] = {0};
1154     if(!PMGenerateQuery(true,
1155                         otmCtx->selectedDeviceInfo->endpoint.addr,
1156                         otmCtx->selectedDeviceInfo->securePort,
1157                         otmCtx->selectedDeviceInfo->connType,
1158                         query, sizeof(query), OIC_RSRC_ACL_URI))
1159     {
1160         OC_LOG(ERROR, TAG, "FinalizeProvisioning : Failed to generate query");
1161         return OC_STACK_ERROR;
1162     }
1163     OC_LOG_V(DEBUG, TAG, "Query=%s", query);
1164
1165     OC_LOG_V(INFO, TAG, "Request URI for Provisioning default ACL : %s", query);
1166
1167     OCCallbackData cbData =  {.context=NULL, .cb=NULL, .cd=NULL};
1168     cbData.cb = &ProvisionDefaultACLCB;
1169     cbData.context = (void *)otmCtx;
1170     cbData.cd = NULL;
1171     OCStackResult ret = OCDoResource(NULL, OC_REST_POST, query,
1172             &otmCtx->selectedDeviceInfo->endpoint, (OCPayload*)secPayload,
1173             otmCtx->selectedDeviceInfo->connType, OC_HIGH_QOS, &cbData, NULL, 0);
1174     if (OC_STACK_OK != ret)
1175     {
1176         SetResult(otmCtx, ret);
1177         return ret;
1178     }
1179
1180     OC_LOG(INFO, TAG, "OUT FinalizeProvisioning");
1181
1182     return ret;
1183
1184 }
1185