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