Modify OTM & SRM to resolve gap in ownership transfer sequence.
[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 #include "global.h"
47
48 #include "srmresourcestrings.h"
49 #include "doxmresource.h"
50 #include "pstatresource.h"
51 #include "credresource.h"
52 #include "aclresource.h"
53 #include "ownershiptransfermanager.h"
54 #include "securevirtualresourcetypes.h"
55 #include "oxmjustworks.h"
56 #include "pmtypes.h"
57 #include "pmutility.h"
58 #include "srmutility.h"
59 #include "provisioningdatabasemanager.h"
60 #include "oxmrandompin.h"
61
62 #define TAG "OTM"
63
64 /**
65  * Array to store the callbacks for each owner transfer method.
66  */
67 static OTMCallbackData_t g_OTMDatas[OIC_OXM_COUNT];
68
69 /**
70  * Variable for storing provisioning tool's provisioning capabilities
71  * Must be in decreasing order of preference. More prefered method should
72  * have lower array index.
73  */
74 static OicSecDpom_t gProvisioningToolCapability[] = { SINGLE_SERVICE_CLIENT_DRIVEN };
75
76 /**
77  * Number of supported provisioning methods
78  * current version supports only one.
79  */
80 static size_t gNumOfProvisioningMethodsPT = 1;
81
82 /**
83  * Variables for pointing the OTMContext to be used in the DTLS handshake result callback.
84  */
85 static OTMContext_t* g_otmCtx = NULL;
86
87 /**
88  * Function to select appropriate  provisioning method.
89  *
90  * @param[in] supportedMethods   Array of supported methods
91  * @param[in] numberOfMethods   number of supported methods
92  * @param[out]  selectedMethod         Selected methods
93  * @return  OC_STACK_OK on success
94  */
95 static OCStackResult SelectProvisioningMethod(const OicSecOxm_t *supportedMethods,
96                                                             size_t numberOfMethods,
97                                                             OicSecOxm_t *selectedMethod)
98 {
99     OIC_LOG(DEBUG, TAG, "IN SelectProvisioningMethod");
100
101     if(numberOfMethods == 0 || !supportedMethods)
102     {
103         OIC_LOG(WARNING, TAG, "Could not find a supported OxM.");
104         return OC_STACK_ERROR;
105     }
106
107     *selectedMethod  = supportedMethods[0];
108     for(size_t i = 0; i < numberOfMethods; i++)
109     {
110         if(*selectedMethod < supportedMethods[i])
111         {
112             *selectedMethod =  supportedMethods[i];
113         }
114     }
115
116     return OC_STACK_OK;
117 }
118
119 /**
120  * Function to select operation mode.This function will return most secure common operation mode.
121  *
122  * @param[in] selectedDeviceInfo   selected device information to performing provisioning.
123  * @param[out]   selectedMode   selected operation mode
124  * @return  OC_STACK_OK on success
125  */
126 static void SelectOperationMode(const OCProvisionDev_t *selectedDeviceInfo,
127                                 OicSecDpom_t *selectedMode)
128 {
129     OIC_LOG(DEBUG, TAG, "IN SelectOperationMode");
130
131     size_t i = 0;
132     size_t j = 0;
133
134     while (i < gNumOfProvisioningMethodsPT && j < selectedDeviceInfo->pstat->smLen)
135     {
136         if (gProvisioningToolCapability[i] < selectedDeviceInfo->pstat->sm[j])
137         {
138             i++;
139         }
140         else if (selectedDeviceInfo->pstat->sm[j] < gProvisioningToolCapability[i])
141         {
142             j++;
143         }
144         else /* if gProvisioningToolCapability[i] == deviceSupportedMethods[j] */
145         {
146             *selectedMode = gProvisioningToolCapability[j];
147             break;
148         }
149     }
150     OIC_LOG_V(DEBUG, TAG, "Selected Operation Mode = %d", *selectedMode);
151
152     OIC_LOG(DEBUG, TAG, "OUT SelectOperationMode");
153 }
154
155 /**
156  * Function to start ownership transfer.
157  * This function will send the first request for provisioning,
158  * The next request message is sent from the response handler for this request.
159  *
160  * @param[in] ctx   context value passed to callback from calling function.
161  * @param[in] selectedDevice   selected device information to performing provisioning.
162  * @return  OC_STACK_OK on success
163  */
164 static OCStackResult StartOwnershipTransfer(void* ctx, OCProvisionDev_t* selectedDevice);
165
166 /**
167  * Function to update owner transfer mode
168  *
169  * @param[in]  otmCtx  Context value of ownership transfer.
170  * @return  OC_STACK_OK on success
171  */
172 static OCStackResult PutOwnerTransferModeToResource(OTMContext_t* otmCtx);
173
174 /**
175  * Function to send request to resource to get its pstat resource information.
176  *
177  * @param[in]  otmCtx  Context value of ownership transfer.
178  * @return  OC_STACK_OK on success
179  */
180 static OCStackResult GetProvisioningStatusResource(OTMContext_t* otmCtx);
181
182
183 /**
184  * Function to send  uuid of owner device to new device.
185  * This function would update 'owner of doxm' as UUID for provisioning tool.
186  *
187  * @param[in]  otmCtx  Context value of ownership transfer.
188  * @return  OC_STACK_OK on success
189  */
190 static OCStackResult PutOwnerUuid(OTMContext_t* otmCtx);
191
192 /**
193  * Function to update the operation mode. As per the spec. Operation mode in client driven
194  * single service provisioning it will be updated to 0x3
195  *
196  * @param[in]  otmCtx  Context value of ownership transfer.
197  * @return  OC_STACK_OK on success
198  */
199 static OCStackResult PutUpdateOperationMode(OTMContext_t* otmCtx);
200
201 /**
202  * Function to update the owner credential to new device
203  *
204  * @param[in]  otmCtx  Context value of ownership transfer.
205  * @param[in] selectedOperationMode selected operation mode
206  * @return  OC_STACK_OK on success
207  */
208 static OCStackResult PutOwnerCredential(OTMContext_t* otmCtx);
209
210 /**
211  * Function to send ownerShip info.
212  * This function would update 'owned of doxm' as true.
213  *
214  * @param[in]  otmCtx  Context value of ownership transfer.
215  * @return  OC_STACK_OK on success
216  */
217 static OCStackResult PutOwnershipInformation(OTMContext_t* otmCtx);
218
219 /**
220  * Function to update pstat when finalize provisioning.
221  * This function would update 'cm' as bx0011,1100 and 'tm' as bx0000,0000.
222  *
223  * @param[in] ctx   context value passed to callback from calling function.
224  * @param[in] selectedDevice   selected device information to performing provisioning.
225  * @return  OC_STACK_OK on success
226  */
227 static OCStackResult PutProvisioningStatus(OTMContext_t* otmCtx);
228
229 /*
230  * Function to finalize provisioning.
231  * This function will send default ACL and commit hash.
232  *
233  * @param[in] otmCtx   Context value of ownership transfer.
234  * @return  OC_STACK_OK on success
235  */
236 static OCStackResult FinalizeProvisioning(OTMContext_t* otmCtx);
237
238
239 static bool IsComplete(OTMContext_t* otmCtx)
240 {
241     for(size_t i = 0; i < otmCtx->ctxResultArraySize; i++)
242     {
243         if(OC_STACK_CONTINUE == otmCtx->ctxResultArray[i].res)
244         {
245             return false;
246         }
247     }
248
249     return true;
250 }
251
252 /**
253  * Function to save the result of provisioning.
254  *
255  * @param[in,out] otmCtx   Context value of ownership transfer.
256  * @param[in] res   result of provisioning
257  */
258 static void SetResult(OTMContext_t* otmCtx, const OCStackResult res)
259 {
260     OIC_LOG_V(DEBUG, TAG, "IN SetResult : %d ", res);
261
262     if(!otmCtx)
263     {
264         OIC_LOG(WARNING, TAG, "OTMContext is NULL");
265         return;
266     }
267
268     if(otmCtx->selectedDeviceInfo)
269     {
270         //Revert psk_info callback and new deivce uuid in case of random PIN OxM
271         if(OIC_RANDOM_DEVICE_PIN == otmCtx->selectedDeviceInfo->doxm->oxmSel)
272         {
273             if(CA_STATUS_OK != CARegisterDTLSCredentialsHandler(GetDtlsPskCredentials))
274             {
275                 OIC_LOG(WARNING, TAG, "Failed to revert  is DTLS credential handler.");
276             }
277             OicUuid_t emptyUuid = { .id={0}};
278             SetUuidForRandomPinOxm(&emptyUuid);
279         }
280
281         for(size_t i = 0; i < otmCtx->ctxResultArraySize; i++)
282         {
283             if(memcmp(otmCtx->selectedDeviceInfo->doxm->deviceID.id,
284                       otmCtx->ctxResultArray[i].deviceId.id, UUID_LENGTH) == 0)
285             {
286                 otmCtx->ctxResultArray[i].res = res;
287                 if(OC_STACK_OK != res)
288                 {
289                     otmCtx->ctxHasError = true;
290                 }
291             }
292         }
293
294         g_otmCtx = NULL;
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                 OIC_LOG(ERROR, TAG, "Failed to StartOwnershipTransfer");
310             }
311         }
312     }
313
314     OIC_LOG(DEBUG, TAG, "OUT SetResult");
315 }
316
317 /**
318  * Function to handle the handshake result in OTM.
319  * This function will be invoked after DTLS handshake
320  * @param   endPoint  [IN] The remote endpoint.
321  * @param   errorInfo [IN] Error information from the endpoint.
322  * @return  NONE
323  */
324 void DTLSHandshakeCB(const CAEndpoint_t *endpoint, const CAErrorInfo_t *info)
325 {
326     if(g_otmCtx && endpoint && info)
327     {
328         OIC_LOG_V(INFO, TAG, "Received status from remote device(%s:%d) : %d",
329                  endpoint->addr, endpoint->port, info->result);
330
331         //Make sure the address matches.
332         if(strncmp(g_otmCtx->selectedDeviceInfo->endpoint.addr,
333            endpoint->addr,
334            sizeof(endpoint->addr)) == 0 &&
335            g_otmCtx->selectedDeviceInfo->securePort == endpoint->port)
336         {
337             OCStackResult res = OC_STACK_ERROR;
338
339             //In case of success, send next coaps request.
340             if(CA_STATUS_OK == info->result)
341             {
342                 //Send request : PUT /oic/sec/doxm [{... , "devowner":"PT's UUID"}]
343                 res = PutOwnerUuid(g_otmCtx);
344                 if(OC_STACK_OK != res)
345                 {
346                     OIC_LOG(ERROR, TAG, "OperationModeUpdate : Failed to send owner information");
347                     SetResult(g_otmCtx, res);
348                 }
349             }
350             //In case of failure, re-start the ownership transfer in case of PIN OxM
351             else if(CA_DTLS_AUTHENTICATION_FAILURE == info->result)
352             {
353                 g_otmCtx->selectedDeviceInfo->doxm->owned = false;
354                 g_otmCtx->attemptCnt++;
355
356                 if(g_otmCtx->selectedDeviceInfo->doxm->oxmSel == OIC_RANDOM_DEVICE_PIN)
357                 {
358                     /*
359                     res = RemoveCredential(&g_otmCtx->subIdForPinOxm);
360                     if(OC_STACK_RESOURCE_DELETED != res)
361                     {
362                         OIC_LOG_V(ERROR, TAG, "Failed to remove temporal PSK : %d", res);
363                         SetResult(g_otmCtx, res);
364                         return;
365                     }*/
366
367                     if(WRONG_PIN_MAX_ATTEMP > g_otmCtx->attemptCnt)
368                     {
369                         res = StartOwnershipTransfer(g_otmCtx, g_otmCtx->selectedDeviceInfo);
370                         if(OC_STACK_OK != res)
371                         {
372                             SetResult(g_otmCtx, res);
373                             OIC_LOG(ERROR, TAG, "Failed to Re-StartOwnershipTransfer");
374                         }
375                     }
376                     else
377                     {
378                         SetResult(g_otmCtx, OC_STACK_AUTHENTICATION_FAILURE);
379                     }
380                 }
381                 else
382                 {
383                     SetResult(g_otmCtx, OC_STACK_AUTHENTICATION_FAILURE);
384                 }
385             }
386         }
387     }
388 }
389
390 /**
391  * Function to save ownerPSK at provisioning tool end.
392  *
393  * @param[in] selectedDeviceInfo   selected device information to performing provisioning.
394  * @return  OC_STACK_OK on success
395  */
396 static OCStackResult SaveOwnerPSK(OCProvisionDev_t *selectedDeviceInfo)
397 {
398     OIC_LOG(DEBUG, TAG, "IN SaveOwnerPSK");
399
400     OCStackResult res = OC_STACK_ERROR;
401
402     CAEndpoint_t endpoint;
403     memset(&endpoint, 0x00, sizeof(CAEndpoint_t));
404     OICStrcpy(endpoint.addr, MAX_ADDR_STR_SIZE_CA, selectedDeviceInfo->endpoint.addr);
405     endpoint.addr[MAX_ADDR_STR_SIZE_CA - 1] = '\0';
406     endpoint.port = selectedDeviceInfo->securePort;
407
408     OicUuid_t ptDeviceID = {.id={0}};
409     if (OC_STACK_OK != GetDoxmDeviceID(&ptDeviceID))
410     {
411         OIC_LOG(ERROR, TAG, "Error while retrieving provisioning tool's device ID");
412         return res;
413     }
414
415     uint8_t ownerPSK[OWNER_PSK_LENGTH_128] = {0};
416
417     //Generating OwnerPSK
418     CAResult_t pskRet = CAGenerateOwnerPSK(&endpoint,
419             (uint8_t *)GetOxmString(selectedDeviceInfo->doxm->oxmSel),
420             strlen(GetOxmString(selectedDeviceInfo->doxm->oxmSel)),
421             ptDeviceID.id, sizeof(ptDeviceID.id),
422             selectedDeviceInfo->doxm->deviceID.id, sizeof(selectedDeviceInfo->doxm->deviceID.id),
423             ownerPSK, OWNER_PSK_LENGTH_128);
424
425     if (CA_STATUS_OK == pskRet)
426     {
427         OIC_LOG(INFO, TAG,"ownerPSK dump:\n");
428         OIC_LOG_BUFFER(INFO, TAG,ownerPSK, OWNER_PSK_LENGTH_128);
429         //Generating new credential for provisioning tool
430         size_t ownLen = 1;
431         uint32_t outLen = 0;
432
433         char base64Buff[B64ENCODE_OUT_SAFESIZE(sizeof(ownerPSK)) + 1] = {};
434         B64Result b64Ret = b64Encode(ownerPSK, sizeof(ownerPSK), base64Buff, sizeof(base64Buff),
435                 &outLen);
436         VERIFY_SUCCESS(TAG, B64_OK == b64Ret, ERROR);
437
438         OicSecCred_t *cred = GenerateCredential(&selectedDeviceInfo->doxm->deviceID,
439                 SYMMETRIC_PAIR_WISE_KEY, NULL,
440                 base64Buff, ownLen, &ptDeviceID);
441         VERIFY_NON_NULL(TAG, cred, ERROR);
442
443         res = AddCredential(cred);
444         if(res != OC_STACK_OK)
445         {
446             DeleteCredList(cred);
447             return res;
448         }
449     }
450     else
451     {
452         OIC_LOG(ERROR, TAG, "CAGenerateOwnerPSK failed");
453     }
454
455     OIC_LOG(DEBUG, TAG, "OUT SaveOwnerPSK");
456 exit:
457     return res;
458 }
459
460 /**
461  * Callback handler for OwnerShipTransferModeHandler API.
462  *
463  * @param[in] ctx             ctx value passed to callback from calling function.
464  * @param[in] UNUSED          handle to an invocation
465  * @param[in] clientResponse  Response from queries to remote servers.
466  * @return  OC_STACK_DELETE_TRANSACTION to delete the transaction
467  *          and  OC_STACK_KEEP_TRANSACTION to keep it.
468  */
469 static OCStackApplicationResult OwnerTransferModeHandler(void *ctx, OCDoHandle UNUSED,
470                                                          OCClientResponse *clientResponse)
471 {
472     OIC_LOG(DEBUG, TAG, "IN OwnerTransferModeHandler");
473
474     VERIFY_NON_NULL(TAG, clientResponse, WARNING);
475     VERIFY_NON_NULL(TAG, ctx, WARNING);
476
477     OTMContext_t* otmCtx = (OTMContext_t*)ctx;
478     (void)UNUSED;
479     if(clientResponse->result == OC_STACK_OK)
480     {
481         OIC_LOG(INFO, TAG, "OwnerTransferModeHandler : response result = OC_STACK_OK");
482         //Send request : GET /oic/sec/pstat
483         OCStackResult res = GetProvisioningStatusResource(otmCtx);
484         if(OC_STACK_OK != res)
485         {
486             OIC_LOG(WARNING, TAG, "Failed to get pstat information");
487             SetResult(otmCtx, res);
488         }
489     }
490     else
491     {
492         OIC_LOG_V(WARNING, TAG, "OwnerTransferModeHandler : Client response is incorrect : %d",
493         clientResponse->result);
494         SetResult(otmCtx, clientResponse->result);
495     }
496
497     OIC_LOG(DEBUG, TAG, "OUT OwnerTransferModeHandler");
498
499 exit:
500     return  OC_STACK_DELETE_TRANSACTION;
501 }
502
503 /**
504  * Callback handler for ProvisioningStatusResouceHandler API.
505  *
506  * @param[in] ctx             ctx value passed to callback from calling function.
507  * @param[in] UNUSED          handle to an invocation
508  * @param[in] clientResponse  Response from queries to remote servers.
509  * @return  OC_STACK_DELETE_TRANSACTION to delete the transaction
510  *          and  OC_STACK_KEEP_TRANSACTION to keep it.
511  */
512 static OCStackApplicationResult ListMethodsHandler(void *ctx, OCDoHandle UNUSED,
513                                                     OCClientResponse *clientResponse)
514 {
515     OIC_LOG(DEBUG, TAG, "IN ListMethodsHandler");
516
517     VERIFY_NON_NULL(TAG, clientResponse, WARNING);
518     VERIFY_NON_NULL(TAG, ctx, WARNING);
519
520     OTMContext_t* otmCtx = (OTMContext_t*)ctx;
521     (void)UNUSED;
522     if  (OC_STACK_OK == clientResponse->result)
523     {
524         if  (NULL == clientResponse->payload)
525         {
526             OIC_LOG(INFO, TAG, "Skiping Null payload");
527             SetResult(otmCtx, OC_STACK_ERROR);
528             return OC_STACK_DELETE_TRANSACTION;
529         }
530
531         if (PAYLOAD_TYPE_SECURITY != clientResponse->payload->type)
532         {
533             OIC_LOG(INFO, TAG, "Unknown payload type");
534             SetResult(otmCtx, OC_STACK_ERROR);
535             return OC_STACK_DELETE_TRANSACTION;
536         }
537
538         OicSecPstat_t* pstat = JSONToPstatBin(
539                 ((OCSecurityPayload*)clientResponse->payload)->securityData);
540         if(NULL == pstat)
541         {
542             OIC_LOG(ERROR, TAG, "Error while converting json to pstat bin");
543             SetResult(otmCtx, OC_STACK_ERROR);
544             return OC_STACK_DELETE_TRANSACTION;
545         }
546         otmCtx->selectedDeviceInfo->pstat = pstat;
547
548         //Select operation mode (Currently supported SINGLE_SERVICE_CLIENT_DRIVEN only)
549         SelectOperationMode(otmCtx->selectedDeviceInfo, &(otmCtx->selectedDeviceInfo->pstat->om));
550
551         //Send request : PUT /oic/sec/pstat [{"om":"bx11", .. }]
552         OCStackResult res = PutUpdateOperationMode(otmCtx);
553         if (OC_STACK_OK != res)
554         {
555             OIC_LOG(ERROR, TAG, "Error while updating operation mode.");
556             SetResult(otmCtx, res);
557         }
558     }
559     else
560     {
561         OIC_LOG_V(WARNING, TAG, "ListMethodsHandler : Client response is incorrect : %d",
562             clientResponse->result);
563         SetResult(otmCtx, clientResponse->result);
564     }
565
566     OIC_LOG(DEBUG, TAG, "OUT ListMethodsHandler");
567 exit:
568     return  OC_STACK_DELETE_TRANSACTION;
569 }
570
571 /**
572  * Response handler for update owner uuid request.
573  *
574  * @param[in] ctx             ctx value passed to callback from calling function.
575  * @param[in] UNUSED          handle to an invocation
576  * @param[in] clientResponse  Response from queries to remote servers.
577  * @return  OC_STACK_DELETE_TRANSACTION to delete the transaction
578  *          and  OC_STACK_KEEP_TRANSACTION to keep it.
579  */
580 static OCStackApplicationResult OwnerUuidUpdateHandler(void *ctx, OCDoHandle UNUSED,
581                                 OCClientResponse *clientResponse)
582 {
583     VERIFY_NON_NULL(TAG, clientResponse, WARNING);
584     VERIFY_NON_NULL(TAG, ctx, WARNING);
585
586     OIC_LOG(DEBUG, TAG, "IN OwnerUuidUpdateHandler");
587     (void)UNUSED;
588     OCStackResult res = OC_STACK_OK;
589     OTMContext_t* otmCtx = (OTMContext_t*)ctx;
590
591     if(OC_STACK_OK == clientResponse->result)
592     {
593         if(otmCtx && otmCtx->selectedDeviceInfo)
594         {
595             res = SaveOwnerPSK(otmCtx->selectedDeviceInfo);
596             if(OC_STACK_OK != res)
597             {
598                 OIC_LOG(ERROR, TAG, "OwnerUuidUpdateHandler:Failed to owner PSK generation");
599                 SetResult(otmCtx, res);
600                 return OC_STACK_DELETE_TRANSACTION;
601             }
602
603             //PUT owner credential to new device according to security spec B.
604             res = PutOwnerCredential(otmCtx);
605             if(OC_STACK_OK != res)
606             {
607                 OIC_LOG(ERROR, TAG,
608                         "OwnerUuidUpdateHandler:Failed to send PUT request for onwer credential");
609                 SetResult(otmCtx, res);
610                 return OC_STACK_DELETE_TRANSACTION;
611             }
612         }
613     }
614     else
615     {
616         res = clientResponse->result;
617         OIC_LOG_V(ERROR, TAG, "OwnerUuidHandler : Unexpected result %d", res);
618         SetResult(otmCtx, res);
619     }
620
621     OIC_LOG(DEBUG, TAG, "OUT OwnerUuidUpdateHandler");
622
623 exit:
624     return  OC_STACK_DELETE_TRANSACTION;
625 }
626
627 /**
628  * Response handler for update operation mode.
629  *
630  * @param[in] ctx             ctx value passed to callback from calling function.
631  * @param[in] UNUSED          handle to an invocation
632  * @param[in] clientResponse  Response from queries to remote servers.
633  * @return  OC_STACK_DELETE_TRANSACTION to delete the transaction
634  *          and  OC_STACK_KEEP_TRANSACTION to keep it.
635  */
636 static OCStackApplicationResult OperationModeUpdateHandler(void *ctx, OCDoHandle UNUSED,
637                                 OCClientResponse *clientResponse)
638 {
639     OIC_LOG(DEBUG, TAG, "IN OperationModeUpdateHandler");
640
641     VERIFY_NON_NULL(TAG, clientResponse, WARNING);
642     VERIFY_NON_NULL(TAG, ctx, WARNING);
643
644     OTMContext_t* otmCtx = (OTMContext_t*)ctx;
645     (void) UNUSED;
646     if  (OC_STACK_OK == clientResponse->result)
647     {
648         OCStackResult res = OC_STACK_ERROR;
649         OicSecOxm_t selOxm = otmCtx->selectedDeviceInfo->doxm->oxmSel;
650         //DTLS Handshake
651         //Load secret for temporal secure session.
652         if(g_OTMDatas[selOxm].loadSecretCB)
653         {
654             res = g_OTMDatas[selOxm].loadSecretCB(otmCtx);
655             if(OC_STACK_OK != res)
656             {
657                 OIC_LOG(ERROR, TAG, "OperationModeUpdate : Failed to load secret");
658                 SetResult(otmCtx, res);
659                 return  OC_STACK_DELETE_TRANSACTION;
660             }
661         }
662
663         //It will be used in handshake event handler
664         g_otmCtx = otmCtx;
665
666         //Try DTLS handshake to generate secure session
667         if(g_OTMDatas[selOxm].createSecureSessionCB)
668         {
669             res = g_OTMDatas[selOxm].createSecureSessionCB(otmCtx);
670             if(OC_STACK_OK != res)
671             {
672                 OIC_LOG(ERROR, TAG, "OperationModeUpdate : Failed to create DTLS session");
673                 SetResult(otmCtx, res);
674                 return OC_STACK_DELETE_TRANSACTION;
675             }
676         }
677     }
678     else
679     {
680         OIC_LOG(ERROR, TAG, "Error while update operation mode");
681         SetResult(otmCtx, clientResponse->result);
682     }
683
684     OIC_LOG(DEBUG, TAG, "OUT OperationModeUpdateHandler");
685
686 exit:
687     return  OC_STACK_DELETE_TRANSACTION;
688 }
689
690 /**
691  * Response handler for update owner crendetial request.
692  *
693  * @param[in] ctx             ctx value passed to callback from calling function.
694  * @param[in] UNUSED          handle to an invocation
695  * @param[in] clientResponse  Response from queries to remote servers.
696  * @return  OC_STACK_DELETE_TRANSACTION to delete the transaction
697  *          and  OC_STACK_KEEP_TRANSACTION to keep it.
698  */
699 static OCStackApplicationResult OwnerCredentialHandler(void *ctx, OCDoHandle UNUSED,
700                                 OCClientResponse *clientResponse)
701 {
702     VERIFY_NON_NULL(TAG, clientResponse, WARNING);
703     VERIFY_NON_NULL(TAG, ctx, WARNING);
704
705     OIC_LOG(DEBUG, TAG, "IN OwnerCredentialHandler");
706     (void)UNUSED;
707     OCStackResult res = OC_STACK_OK;
708     OTMContext_t* otmCtx = (OTMContext_t*)ctx;
709
710     if(OC_STACK_RESOURCE_CREATED == clientResponse->result)
711     {
712         if(otmCtx && otmCtx->selectedDeviceInfo)
713         {
714             //PUT /oic/sec/doxm [{ ..., "owned":"TRUE" }]
715             res = PutOwnershipInformation(otmCtx);
716             if(OC_STACK_OK != res)
717             {
718                 OIC_LOG(ERROR, TAG, "Failed to put ownership information to new device");
719                 SetResult(otmCtx, res);
720                 return OC_STACK_DELETE_TRANSACTION;
721             }
722         }
723     }
724     else
725     {
726         res = clientResponse->result;
727         OIC_LOG_V(ERROR, TAG, "OwnerCredentialHandler : Unexpected result %d", res);
728         SetResult(otmCtx, res);
729     }
730
731     OIC_LOG(DEBUG, TAG, "OUT OwnerCredentialHandler");
732
733 exit:
734     return  OC_STACK_DELETE_TRANSACTION;
735 }
736
737
738 /**
739  * Response handler for update owner information request.
740  *
741  * @param[in] ctx             ctx value passed to callback from calling function.
742  * @param[in] UNUSED          handle to an invocation
743  * @param[in] clientResponse  Response from queries to remote servers.
744  * @return  OC_STACK_DELETE_TRANSACTION to delete the transaction
745  *          and  OC_STACK_KEEP_TRANSACTION to keep it.
746  */
747 static OCStackApplicationResult OwnershipInformationHandler(void *ctx, OCDoHandle UNUSED,
748                                 OCClientResponse *clientResponse)
749 {
750     VERIFY_NON_NULL(TAG, clientResponse, WARNING);
751     VERIFY_NON_NULL(TAG, ctx, WARNING);
752
753     OIC_LOG(DEBUG, TAG, "IN OwnershipInformationHandler");
754     (void)UNUSED;
755     OCStackResult res = OC_STACK_OK;
756     OTMContext_t* otmCtx = (OTMContext_t*)ctx;
757
758     if(OC_STACK_OK == clientResponse->result)
759     {
760         if(otmCtx && otmCtx->selectedDeviceInfo)
761         {
762             OIC_LOG(INFO, TAG, "Ownership transfer was successfully completed.");
763             OIC_LOG(INFO, TAG, "Start defualt ACL & commit-hash provisioning.");
764
765             res = PutProvisioningStatus(otmCtx);
766             if(OC_STACK_OK != res)
767             {
768                 OIC_LOG(ERROR, TAG, "Failed to update pstat");
769                 SetResult(otmCtx, res);
770             }
771         }
772     }
773     else
774     {
775         res = clientResponse->result;
776         OIC_LOG_V(ERROR, TAG, "OwnershipInformationHandler : Unexpected result %d", res);
777         SetResult(otmCtx, res);
778     }
779
780     OIC_LOG(DEBUG, TAG, "OUT OwnershipInformationHandler");
781
782 exit:
783     return  OC_STACK_DELETE_TRANSACTION;
784 }
785
786 /**
787  * Response handler of update provisioning status.
788  *
789  * @param[in] ctx             ctx value passed to callback from calling function.
790  * @param[in] UNUSED          handle to an invocation
791  * @param[in] clientResponse  Response from queries to remote servers.
792  * @return  OC_STACK_DELETE_TRANSACTION to delete the transaction
793  *          and OC_STACK_KEEP_TRANSACTION to keep it.
794  */
795 static OCStackApplicationResult ProvisioningStatusHandler(void *ctx, OCDoHandle UNUSED,
796                                                        OCClientResponse *clientResponse)
797 {
798     OIC_LOG_V(INFO, TAG, "IN ProvisioningStatusHandler.");
799
800     VERIFY_NON_NULL(TAG, clientResponse, ERROR);
801     VERIFY_NON_NULL(TAG, ctx, ERROR);
802
803     OTMContext_t* otmCtx = (OTMContext_t*)ctx;
804     (void)UNUSED;
805     if(OC_STACK_OK == clientResponse->result)
806     {
807         OCStackResult res = FinalizeProvisioning(otmCtx);
808          if (OC_STACK_OK != res)
809          {
810                 OIC_LOG_V(INFO, TAG, "Failed to finalize provisioning.");
811                 SetResult(otmCtx, res);
812                 return OC_STACK_DELETE_TRANSACTION;
813          }
814     }
815
816 exit:
817     OIC_LOG_V(INFO, TAG, "OUT ProvisioningStatusHandler.");
818     return OC_STACK_DELETE_TRANSACTION;
819 }
820
821 /**
822  * Callback handler of finalize provisioning.
823  *
824  * @param[in] ctx             ctx value passed to callback from calling function.
825  * @param[in] UNUSED          handle to an invocation
826  * @param[in] clientResponse  Response from queries to remote servers.
827  * @return  OC_STACK_DELETE_TRANSACTION to delete the transaction
828  *          and OC_STACK_KEEP_TRANSACTION to keep it.
829  */
830 static OCStackApplicationResult FinalizeProvisioningCB(void *ctx, OCDoHandle UNUSED,
831                                                        OCClientResponse *clientResponse)
832 {
833     OIC_LOG_V(INFO, TAG, "IN ProvisionDefaultACLCB.");
834
835     VERIFY_NON_NULL(TAG, clientResponse, ERROR);
836     VERIFY_NON_NULL(TAG, ctx, ERROR);
837
838     OTMContext_t* otmCtx = (OTMContext_t*) ctx;
839     (void)UNUSED;
840
841     if (OC_STACK_RESOURCE_CREATED == clientResponse->result)
842     {
843         OCStackResult res = PDMAddDevice(&otmCtx->selectedDeviceInfo->doxm->deviceID);
844          if (OC_STACK_OK == res)
845          {
846                 OIC_LOG_V(INFO, TAG, "Add device's UUID in PDM_DB");
847                 SetResult(otmCtx, OC_STACK_OK);
848                 return OC_STACK_DELETE_TRANSACTION;
849          }
850           else
851          {
852               OIC_LOG(ERROR, TAG, "Ownership transfer is complete but adding information to DB is failed.");
853          }
854     }
855     else
856     {
857         OIC_LOG_V(INFO, TAG, "Error occured in provisionDefaultACLCB :: %d\n",
858                             clientResponse->result);
859         SetResult(otmCtx, clientResponse->result);
860     }
861 exit:
862     return OC_STACK_DELETE_TRANSACTION;
863 }
864
865 static OCStackResult PutOwnerCredential(OTMContext_t* otmCtx)
866 {
867     OIC_LOG(DEBUG, TAG, "IN PutOwnerCredential");
868
869     if(!otmCtx || !otmCtx->selectedDeviceInfo)
870     {
871         OIC_LOG(ERROR, TAG, "Invalid parameters");
872         return OC_STACK_INVALID_PARAM;
873     }
874
875     OCProvisionDev_t* deviceInfo = otmCtx->selectedDeviceInfo;
876     char query[MAX_URI_LENGTH + MAX_QUERY_LENGTH] = {0};
877
878     if(!PMGenerateQuery(true,
879                         deviceInfo->endpoint.addr, deviceInfo->securePort,
880                         deviceInfo->connType,
881                         query, sizeof(query), OIC_RSRC_CRED_URI))
882     {
883         OIC_LOG(ERROR, TAG, "PutOwnerCredential : Failed to generate query");
884         return OC_STACK_ERROR;
885     }
886     OIC_LOG_V(DEBUG, TAG, "Query=%s", query);
887     OCSecurityPayload* secPayload = (OCSecurityPayload*)OICCalloc(1, sizeof(OCSecurityPayload));
888     if(!secPayload)
889     {
890         OIC_LOG(ERROR, TAG, "Failed to memory allocation");
891         return OC_STACK_NO_MEMORY;
892     }
893
894     //Generate owner credential for new device
895     secPayload->base.type = PAYLOAD_TYPE_SECURITY;
896     OicSecCred_t* ownerCredential =
897         GetCredResourceData(&(deviceInfo->doxm->deviceID));
898     if(!ownerCredential)
899     {
900         OIC_LOG(ERROR, TAG, "Can not find OwnerPSK.");
901         return OC_STACK_NO_RESOURCE;
902     }
903
904     OicUuid_t credSubjectId = {.id={0}};
905     if(OC_STACK_OK == GetDoxmDeviceID(&credSubjectId))
906     {
907         OicSecCred_t newCredential;
908         memcpy(&newCredential, ownerCredential, sizeof(OicSecCred_t));
909         newCredential.next = NULL;
910         memcpy(&(newCredential.subject), &credSubjectId, sizeof(OicUuid_t));
911
912         //Send owner credential to new device : PUT /oic/sec/cred [ owner credential ]
913         secPayload->securityData = BinToCredJSON(&newCredential);
914         if (NULL == secPayload->securityData)
915         {
916             OICFree(secPayload);
917             OIC_LOG(ERROR, TAG, "Error while converting bin to json");
918             return OC_STACK_ERROR;
919         }
920         OIC_LOG_V(DEBUG, TAG, "Payload : %s", secPayload->securityData);
921
922         OCCallbackData cbData;
923         cbData.cb = &OwnerCredentialHandler;
924         cbData.context = (void *)otmCtx;
925         cbData.cd = NULL;
926         OCStackResult res = OCDoResource(NULL, OC_REST_PUT, query,
927                                          &deviceInfo->endpoint, (OCPayload*)secPayload,
928                                          deviceInfo->connType, OC_LOW_QOS, &cbData, NULL, 0);
929         if (res != OC_STACK_OK)
930         {
931             OIC_LOG(ERROR, TAG, "OCStack resource error");
932         }
933     }
934     else
935     {
936         OIC_LOG(ERROR, TAG, "Failed to read DOXM device ID.");
937         return OC_STACK_NO_RESOURCE;
938     }
939
940     OIC_LOG(DEBUG, TAG, "OUT PutOwnerCredential");
941
942     return OC_STACK_OK;
943 }
944
945 static OCStackResult PutOwnerTransferModeToResource(OTMContext_t* otmCtx)
946 {
947     OIC_LOG(DEBUG, TAG, "IN PutOwnerTransferModeToResource");
948
949     if(!otmCtx || !otmCtx->selectedDeviceInfo)
950     {
951         OIC_LOG(ERROR, TAG, "Invalid parameters");
952         return OC_STACK_INVALID_PARAM;
953     }
954
955     OCProvisionDev_t* deviceInfo = otmCtx->selectedDeviceInfo;
956     OicSecOxm_t selectedOxm = deviceInfo->doxm->oxmSel;
957     char query[MAX_URI_LENGTH + MAX_QUERY_LENGTH] = {0};
958
959     if(!PMGenerateQuery(false,
960                         deviceInfo->endpoint.addr, deviceInfo->endpoint.port,
961                         deviceInfo->connType,
962                         query, sizeof(query), OIC_RSRC_DOXM_URI))
963     {
964         OIC_LOG(ERROR, TAG, "PutOwnerTransferModeToResource : Failed to generate query");
965         return OC_STACK_ERROR;
966     }
967     OIC_LOG_V(DEBUG, TAG, "Query=%s", query);
968     OCSecurityPayload* secPayload = (OCSecurityPayload*)OICCalloc(1, sizeof(OCSecurityPayload));
969     if(!secPayload)
970     {
971         OIC_LOG(ERROR, TAG, "Failed to memory allocation");
972         return OC_STACK_NO_MEMORY;
973     }
974     secPayload->base.type = PAYLOAD_TYPE_SECURITY;
975     secPayload->securityData = g_OTMDatas[selectedOxm].createSelectOxmPayloadCB(otmCtx);
976     if (NULL == secPayload->securityData)
977     {
978         OICFree(secPayload);
979         OIC_LOG(ERROR, TAG, "Error while converting bin to json");
980         return OC_STACK_ERROR;
981     }
982
983     OCCallbackData cbData;
984     cbData.cb = &OwnerTransferModeHandler;
985     cbData.context = (void *)otmCtx;
986     cbData.cd = NULL;
987     OCStackResult res = OCDoResource(NULL, OC_REST_PUT, query,
988                                      &deviceInfo->endpoint, (OCPayload*)secPayload,
989                                      deviceInfo->connType, OC_LOW_QOS, &cbData, NULL, 0);
990     if (res != OC_STACK_OK)
991     {
992         OIC_LOG(ERROR, TAG, "OCStack resource error");
993     }
994
995     OIC_LOG(DEBUG, TAG, "OUT PutOwnerTransferModeToResource");
996
997     return res;
998 }
999
1000 static OCStackResult GetProvisioningStatusResource(OTMContext_t* otmCtx)
1001 {
1002     OIC_LOG(DEBUG, TAG, "IN GetProvisioningStatusResource");
1003
1004     if(!otmCtx || !otmCtx->selectedDeviceInfo)
1005     {
1006         OIC_LOG(ERROR, TAG, "Invailed parameters");
1007         return OC_STACK_INVALID_PARAM;
1008     }
1009
1010     OCProvisionDev_t* deviceInfo = otmCtx->selectedDeviceInfo;
1011     char query[MAX_URI_LENGTH + MAX_QUERY_LENGTH] = {0};
1012     if(!PMGenerateQuery(false,
1013                         deviceInfo->endpoint.addr, deviceInfo->endpoint.port,
1014                         deviceInfo->connType,
1015                         query, sizeof(query), OIC_RSRC_PSTAT_URI))
1016     {
1017         OIC_LOG(ERROR, TAG, "GetProvisioningStatusResource : Failed to generate query");
1018         return OC_STACK_ERROR;
1019     }
1020     OIC_LOG_V(DEBUG, TAG, "Query=%s", query);
1021
1022     OCCallbackData cbData;
1023     cbData.cb = &ListMethodsHandler;
1024     cbData.context = (void *)otmCtx;
1025     cbData.cd = NULL;
1026     OCStackResult res = OCDoResource(NULL, OC_REST_GET, query, NULL, NULL,
1027                                      deviceInfo->connType, OC_LOW_QOS, &cbData, NULL, 0);
1028     if (res != OC_STACK_OK)
1029     {
1030         OIC_LOG(ERROR, TAG, "OCStack resource error");
1031     }
1032
1033     OIC_LOG(DEBUG, TAG, "OUT GetProvisioningStatusResource");
1034
1035     return res;
1036 }
1037
1038 static OCStackResult PutOwnerUuid(OTMContext_t* otmCtx)
1039 {
1040     OIC_LOG(DEBUG, TAG, "IN PutOwnerUuid");
1041
1042     if(!otmCtx || !otmCtx->selectedDeviceInfo)
1043     {
1044         OIC_LOG(ERROR, TAG, "Invailed parameters");
1045         return OC_STACK_INVALID_PARAM;
1046     }
1047
1048     OCProvisionDev_t* deviceInfo = otmCtx->selectedDeviceInfo;
1049     char query[MAX_URI_LENGTH + MAX_QUERY_LENGTH] = {0};
1050     if(!PMGenerateQuery(true,
1051                         deviceInfo->endpoint.addr, deviceInfo->securePort,
1052                         deviceInfo->connType,
1053                         query, sizeof(query), OIC_RSRC_DOXM_URI))
1054     {
1055         OIC_LOG(ERROR, TAG, "PutOwnershipInformation : Failed to generate query");
1056         return OC_STACK_ERROR;
1057     }
1058     OIC_LOG_V(DEBUG, TAG, "Query=%s", query);
1059
1060     //PUT PT's uuid to new device
1061     OCSecurityPayload* secPayload = (OCSecurityPayload*)OICCalloc(1, sizeof(OCSecurityPayload));
1062     if(!secPayload)
1063     {
1064         OIC_LOG(ERROR, TAG, "Failed to memory allocation");
1065         return OC_STACK_NO_MEMORY;
1066     }
1067     secPayload->base.type = PAYLOAD_TYPE_SECURITY;
1068     secPayload->securityData =
1069         g_OTMDatas[deviceInfo->doxm->oxmSel].createOwnerTransferPayloadCB(otmCtx);
1070     if (NULL == secPayload->securityData)
1071     {
1072         OICFree(secPayload);
1073         OIC_LOG(ERROR, TAG, "Error while converting doxm bin to json");
1074         return OC_STACK_INVALID_PARAM;
1075     }
1076     OIC_LOG_V(DEBUG, TAG, "Payload : %s", secPayload->securityData);
1077
1078     OCCallbackData cbData;
1079     cbData.cb = &OwnerUuidUpdateHandler;
1080     cbData.context = (void *)otmCtx;
1081     cbData.cd = NULL;
1082
1083     OCStackResult res = OCDoResource(NULL, OC_REST_PUT, query, 0, (OCPayload*)secPayload,
1084                                      deviceInfo->connType, OC_LOW_QOS, &cbData, NULL, 0);
1085     if (res != OC_STACK_OK)
1086     {
1087         OIC_LOG(ERROR, TAG, "OCStack resource error");
1088     }
1089
1090     OIC_LOG(DEBUG, TAG, "OUT PutOwnerUuid");
1091
1092     return res;
1093 }
1094
1095 static OCStackResult PutOwnershipInformation(OTMContext_t* otmCtx)
1096 {
1097     OIC_LOG(DEBUG, TAG, "IN PutOwnershipInformation");
1098
1099     if(!otmCtx || !otmCtx->selectedDeviceInfo)
1100     {
1101         OIC_LOG(ERROR, TAG, "Invailed parameters");
1102         return OC_STACK_INVALID_PARAM;
1103     }
1104
1105     OCProvisionDev_t* deviceInfo = otmCtx->selectedDeviceInfo;
1106     char query[MAX_URI_LENGTH + MAX_QUERY_LENGTH] = {0};
1107     if(!PMGenerateQuery(true,
1108                         deviceInfo->endpoint.addr, deviceInfo->securePort,
1109                         deviceInfo->connType,
1110                         query, sizeof(query), OIC_RSRC_DOXM_URI))
1111     {
1112         OIC_LOG(ERROR, TAG, "PutOwnershipInformation : Failed to generate query");
1113         return OC_STACK_ERROR;
1114     }
1115     OIC_LOG_V(DEBUG, TAG, "Query=%s", query);
1116
1117     //OwnershipInformationHandler
1118     OCSecurityPayload* secPayload = (OCSecurityPayload*)OICCalloc(1, sizeof(OCSecurityPayload));
1119     if(!secPayload)
1120     {
1121         OIC_LOG(ERROR, TAG, "Failed to memory allocation");
1122         return OC_STACK_NO_MEMORY;
1123     }
1124
1125     otmCtx->selectedDeviceInfo->doxm->owned = true;
1126     secPayload->securityData = BinToDoxmJSON(otmCtx->selectedDeviceInfo->doxm);
1127     if (NULL == secPayload->securityData)
1128     {
1129         OICFree(secPayload);
1130         OIC_LOG(ERROR, TAG, "Error while converting doxm bin to json");
1131         return OC_STACK_INVALID_PARAM;
1132     }
1133     secPayload->base.type = PAYLOAD_TYPE_SECURITY;
1134
1135     OCCallbackData cbData;
1136     cbData.cb = &OwnershipInformationHandler;
1137     cbData.context = (void *)otmCtx;
1138     cbData.cd = NULL;
1139
1140     OCStackResult res = OCDoResource(NULL, OC_REST_PUT, query, 0, (OCPayload*)secPayload,
1141                                      deviceInfo->connType, OC_LOW_QOS, &cbData, NULL, 0);
1142     if (res != OC_STACK_OK)
1143     {
1144         OIC_LOG(ERROR, TAG, "OCStack resource error");
1145     }
1146
1147     OIC_LOG(DEBUG, TAG, "OUT PutOwnershipInformation");
1148
1149     return res;
1150 }
1151
1152 static OCStackResult PutUpdateOperationMode(OTMContext_t* otmCtx)
1153 {
1154     OIC_LOG(DEBUG, TAG, "IN PutUpdateOperationMode");
1155
1156     if(!otmCtx || !otmCtx->selectedDeviceInfo)
1157     {
1158         return OC_STACK_INVALID_PARAM;
1159     }
1160
1161     OCProvisionDev_t* deviceInfo = otmCtx->selectedDeviceInfo;
1162     char query[MAX_URI_LENGTH + MAX_QUERY_LENGTH] = {0};
1163     if(!PMGenerateQuery(false,
1164                         deviceInfo->endpoint.addr, deviceInfo->endpoint.port,
1165                         deviceInfo->connType,
1166                         query, sizeof(query), OIC_RSRC_PSTAT_URI))
1167     {
1168         OIC_LOG(ERROR, TAG, "PutUpdateOperationMode : Failed to generate query");
1169         return OC_STACK_ERROR;
1170     }
1171     OIC_LOG_V(DEBUG, TAG, "Query=%s", query);
1172
1173     OCSecurityPayload* secPayload = (OCSecurityPayload*)OICCalloc(1, sizeof(OCSecurityPayload));
1174     if(!secPayload)
1175     {
1176         OIC_LOG(ERROR, TAG, "Failed to memory allocation");
1177         return OC_STACK_NO_MEMORY;
1178     }
1179     secPayload->base.type = PAYLOAD_TYPE_SECURITY;
1180     secPayload->securityData = BinToPstatJSON(deviceInfo->pstat);
1181     if (NULL == secPayload->securityData)
1182     {
1183         OICFree(secPayload);
1184         OIC_LOG(ERROR, TAG, "Error while converting pstat bin to json");
1185         return OC_STACK_INVALID_PARAM;
1186     }
1187
1188     OCCallbackData cbData;
1189     cbData.cb = &OperationModeUpdateHandler;
1190     cbData.context = (void *)otmCtx;
1191     cbData.cd = NULL;
1192     OCStackResult res = OCDoResource(NULL, OC_REST_PUT, query, 0, (OCPayload*)secPayload,
1193                                      deviceInfo->connType, OC_LOW_QOS, &cbData, NULL, 0);
1194     if (res != OC_STACK_OK)
1195     {
1196         OIC_LOG(ERROR, TAG, "OCStack resource error");
1197     }
1198
1199     OIC_LOG(DEBUG, TAG, "OUT PutUpdateOperationMode");
1200
1201     return res;
1202 }
1203
1204 static OCStackResult StartOwnershipTransfer(void* ctx, OCProvisionDev_t* selectedDevice)
1205 {
1206     OIC_LOG(INFO, TAG, "IN StartOwnershipTransfer");
1207     OTMContext_t* otmCtx = (OTMContext_t*)ctx;
1208     otmCtx->selectedDeviceInfo = selectedDevice;
1209
1210     //Set to the lowest level OxM, and then find more higher level OxM.
1211     OCStackResult res = SelectProvisioningMethod(selectedDevice->doxm->oxm,
1212                                                  selectedDevice->doxm->oxmLen,
1213                                                  &selectedDevice->doxm->oxmSel);
1214     if(OC_STACK_OK != res)
1215     {
1216         OIC_LOG(ERROR, TAG, "Failed to select the provisioning method");
1217         SetResult(otmCtx, res);
1218         return res;
1219     }
1220     OIC_LOG_V(DEBUG, TAG, "Selected provisoning method = %d", selectedDevice->doxm->oxmSel);
1221
1222     //Send Req: PUT /oic/sec/doxm [{..."OxmSel" :g_OTMDatas[Index of Selected OxM].OXMString,...}]
1223     res = PutOwnerTransferModeToResource(otmCtx);
1224     if(OC_STACK_OK != res)
1225     {
1226         OIC_LOG(WARNING, TAG, "Failed to select the provisioning method");
1227         SetResult(otmCtx, res);
1228         return res;
1229     }
1230
1231     //Register DTLS event handler to catch the dtls event while handshake
1232     if(CA_STATUS_OK != CARegisterDTLSHandshakeCallback(DTLSHandshakeCB))
1233     {
1234         OIC_LOG(WARNING, TAG, "StartOwnershipTransfer : Failed to register DTLS handshake callback.");
1235     }
1236
1237     OIC_LOG(INFO, TAG, "OUT StartOwnershipTransfer");
1238
1239     return res;
1240
1241 }
1242
1243 OCStackResult OTMSetOwnershipTransferCallbackData(OicSecOxm_t oxmType, OTMCallbackData_t* data)
1244 {
1245     OIC_LOG(DEBUG, TAG, "IN OTMSetOwnerTransferCallbackData");
1246
1247     if(!data)
1248     {
1249         OIC_LOG(ERROR, TAG, "OTMSetOwnershipTransferCallbackData : Invalid parameters");
1250         return OC_STACK_INVALID_PARAM;
1251     }
1252     if(oxmType >= OIC_OXM_COUNT)
1253     {
1254         OIC_LOG(INFO, TAG, "Unknow ownership transfer method");
1255         return OC_STACK_INVALID_PARAM;
1256     }
1257
1258     g_OTMDatas[oxmType].loadSecretCB= data->loadSecretCB;
1259     g_OTMDatas[oxmType].createSecureSessionCB = data->createSecureSessionCB;
1260     g_OTMDatas[oxmType].createSelectOxmPayloadCB = data->createSelectOxmPayloadCB;
1261     g_OTMDatas[oxmType].createOwnerTransferPayloadCB = data->createOwnerTransferPayloadCB;
1262
1263     OIC_LOG(DEBUG, TAG, "OUT OTMSetOwnerTransferCallbackData");
1264
1265     return OC_STACK_OK;
1266 }
1267
1268 /**
1269  * NOTE : Unowned discovery should be done before performing OTMDoOwnershipTransfer
1270  */
1271 OCStackResult OTMDoOwnershipTransfer(void* ctx,
1272                                      OCProvisionDev_t *selectedDevicelist,
1273                                      OCProvisionResultCB resultCallback)
1274 {
1275     OIC_LOG(DEBUG, TAG, "IN OTMDoOwnershipTransfer");
1276
1277     if (NULL == selectedDevicelist || NULL == resultCallback )
1278     {
1279         return OC_STACK_INVALID_PARAM;
1280     }
1281
1282     OTMContext_t* otmCtx = (OTMContext_t*)OICCalloc(1,sizeof(OTMContext_t));
1283     if(!otmCtx)
1284     {
1285         OIC_LOG(ERROR, TAG, "Failed to create OTM Context");
1286         return OC_STACK_NO_MEMORY;
1287     }
1288     otmCtx->ctxResultCallback = resultCallback;
1289     otmCtx->ctxHasError = false;
1290     otmCtx->userCtx = ctx;
1291     OCProvisionDev_t* pCurDev = selectedDevicelist;
1292
1293     //Counting number of selected devices.
1294     otmCtx->ctxResultArraySize = 0;
1295     while(NULL != pCurDev)
1296     {
1297         otmCtx->ctxResultArraySize++;
1298         pCurDev = pCurDev->next;
1299     }
1300
1301     otmCtx->ctxResultArray =
1302         (OCProvisionResult_t*)OICCalloc(otmCtx->ctxResultArraySize, sizeof(OCProvisionResult_t));
1303     if(NULL == otmCtx->ctxResultArray)
1304     {
1305         OIC_LOG(ERROR, TAG, "OTMDoOwnershipTransfer : Failed to memory allocation");
1306         OICFree(otmCtx);
1307         return OC_STACK_NO_MEMORY;
1308     }
1309     pCurDev = selectedDevicelist;
1310
1311     OCStackResult res = OC_STACK_OK;
1312     //Fill the device UUID for result array.
1313     for(size_t devIdx = 0; devIdx < otmCtx->ctxResultArraySize; devIdx++)
1314     {
1315         //Checking duplication of Device ID.
1316         bool isDuplicate = true;
1317         res = PDMIsDuplicateDevice(&pCurDev->doxm->deviceID, &isDuplicate);
1318         if (OC_STACK_OK != res)
1319         {
1320             goto error;
1321         }
1322         if (isDuplicate)
1323         {
1324             OIC_LOG(ERROR, TAG, "OTMDoOwnershipTransfer : Device ID is duplicated");
1325             res = OC_STACK_INVALID_PARAM;
1326             goto error;
1327         }
1328         memcpy(otmCtx->ctxResultArray[devIdx].deviceId.id,
1329                pCurDev->doxm->deviceID.id,
1330                UUID_LENGTH);
1331         otmCtx->ctxResultArray[devIdx].res = OC_STACK_CONTINUE;
1332         pCurDev = pCurDev->next;
1333     }
1334
1335     StartOwnershipTransfer(otmCtx, selectedDevicelist);
1336
1337     OIC_LOG(DEBUG, TAG, "OUT OTMDoOwnershipTransfer");
1338     return OC_STACK_OK;
1339
1340 error:
1341     OICFree(otmCtx->ctxResultArray);
1342     OICFree(otmCtx);
1343     return res;
1344
1345 }
1346
1347 OCStackResult PutProvisioningStatus(OTMContext_t* otmCtx)
1348 {
1349     OIC_LOG(INFO, TAG, "IN PutProvisioningStatus");
1350
1351     if(!otmCtx)
1352     {
1353         OIC_LOG(ERROR, TAG, "OTMContext is NULL");
1354         return OC_STACK_INVALID_PARAM;
1355     }
1356     if(!otmCtx->selectedDeviceInfo)
1357     {
1358         OIC_LOG(ERROR, TAG, "Can't find device information in OTMContext");
1359         OICFree(otmCtx);
1360         return OC_STACK_INVALID_PARAM;
1361     }
1362
1363     otmCtx->selectedDeviceInfo->pstat->tm = NORMAL;
1364     otmCtx->selectedDeviceInfo->pstat->cm = PROVISION_ACLS | PROVISION_CREDENTIALS |
1365                                             SECURITY_MANAGEMENT_SERVICES | BOOTSTRAP_SERVICE;
1366     OCSecurityPayload* secPayload = (OCSecurityPayload*)OICCalloc(1, sizeof(OCSecurityPayload));
1367     if(!secPayload)
1368     {
1369         OIC_LOG(ERROR, TAG, "Failed to memory allocation");
1370         return OC_STACK_NO_MEMORY;
1371     }
1372     secPayload->base.type = PAYLOAD_TYPE_SECURITY;
1373     secPayload->securityData = BinToPstatJSON(otmCtx->selectedDeviceInfo->pstat);
1374     if (NULL == secPayload->securityData)
1375     {
1376         OICFree(secPayload);
1377         SetResult(otmCtx, OC_STACK_INVALID_JSON);
1378         return OC_STACK_INVALID_JSON;
1379     }
1380     OIC_LOG_V(INFO, TAG, "Created payload for commit hash: %s",secPayload->securityData);
1381
1382     char query[MAX_URI_LENGTH + MAX_QUERY_LENGTH] = {0};
1383     if(!PMGenerateQuery(true,
1384                         otmCtx->selectedDeviceInfo->endpoint.addr,
1385                         otmCtx->selectedDeviceInfo->securePort,
1386                         otmCtx->selectedDeviceInfo->connType,
1387                         query, sizeof(query), OIC_RSRC_PSTAT_URI))
1388     {
1389         OIC_LOG(ERROR, TAG, "PutProvisioningStatus : Failed to generate query");
1390         return OC_STACK_ERROR;
1391     }
1392     OIC_LOG_V(DEBUG, TAG, "Query=%s", query);
1393
1394     OCCallbackData cbData = {.context=NULL, .cb=NULL, .cd=NULL};
1395     cbData.cb = &ProvisioningStatusHandler;
1396     cbData.context = (void*)otmCtx;
1397     cbData.cd = NULL;
1398     OCStackResult ret = OCDoResource(NULL, OC_REST_PUT, query, 0, (OCPayload*)secPayload,
1399             otmCtx->selectedDeviceInfo->connType, OC_HIGH_QOS, &cbData, NULL, 0);
1400     OIC_LOG_V(INFO, TAG, "OCDoResource returned: %d",ret);
1401     if (ret != OC_STACK_OK)
1402     {
1403         OIC_LOG(ERROR, TAG, "OCStack resource error");
1404         SetResult(otmCtx, ret);
1405     }
1406
1407     OIC_LOG(INFO, TAG, "OUT PutProvisioningStatus");
1408
1409     return ret;
1410 }
1411
1412 OCStackResult FinalizeProvisioning(OTMContext_t* otmCtx)
1413 {
1414     OIC_LOG(INFO, TAG, "IN FinalizeProvisioning");
1415
1416     if(!otmCtx)
1417     {
1418         OIC_LOG(ERROR, TAG, "OTMContext is NULL");
1419         return OC_STACK_INVALID_PARAM;
1420     }
1421     if(!otmCtx->selectedDeviceInfo)
1422     {
1423         OIC_LOG(ERROR, TAG, "Can't find device information in OTMContext");
1424         OICFree(otmCtx);
1425         return OC_STACK_INVALID_PARAM;
1426     }
1427     // Provision Default ACL to device
1428     OicSecAcl_t defaultAcl =
1429     { {.id={0}},
1430         1,
1431         NULL,
1432         0x001F,
1433         0,
1434         NULL,
1435         NULL,
1436         1,
1437         NULL,
1438         NULL,
1439     };
1440
1441     OicUuid_t provTooldeviceID = {.id={0}};
1442     if (OC_STACK_OK != GetDoxmDeviceID(&provTooldeviceID))
1443     {
1444         OIC_LOG(ERROR, TAG, "Error while retrieving provisioning tool's device ID");
1445         SetResult(otmCtx, OC_STACK_ERROR);
1446         return OC_STACK_ERROR;
1447     }
1448     OIC_LOG(INFO, TAG, "Retieved deviceID");
1449     memcpy(defaultAcl.subject.id, provTooldeviceID.id, sizeof(defaultAcl.subject.id));
1450     char *wildCardResource = "*";
1451     defaultAcl.resources = &wildCardResource;
1452
1453     defaultAcl.owners = (OicUuid_t *) OICCalloc(1, UUID_LENGTH);
1454     if(!defaultAcl.owners)
1455     {
1456         OIC_LOG(ERROR, TAG, "Failed to memory allocation for default ACL");
1457         SetResult(otmCtx, OC_STACK_NO_MEMORY);
1458         return OC_STACK_NO_MEMORY;
1459     }
1460     memcpy(defaultAcl.owners->id, provTooldeviceID.id, UUID_LENGTH);
1461     OIC_LOG(INFO, TAG, "Provisioning default ACL");
1462
1463     OCSecurityPayload* secPayload = (OCSecurityPayload*)OICCalloc(1, sizeof(OCSecurityPayload));
1464     if(!secPayload)
1465     {
1466         OIC_LOG(ERROR, TAG, "Failed to memory allocation");
1467         return OC_STACK_NO_MEMORY;
1468     }
1469     secPayload->base.type = PAYLOAD_TYPE_SECURITY;
1470     secPayload->securityData = BinToAclJSON(&defaultAcl);
1471     OICFree(defaultAcl.owners);
1472     if(!secPayload->securityData)
1473     {
1474         OICFree(secPayload);
1475         OIC_LOG(INFO, TAG, "FinalizeProvisioning : Failed to BinToAclJSON");
1476         SetResult(otmCtx, OC_STACK_ERROR);
1477         return OC_STACK_ERROR;
1478     }
1479     OIC_LOG_V(INFO, TAG, "Provisioning default ACL : %s",secPayload->securityData);
1480
1481     char query[MAX_URI_LENGTH + MAX_QUERY_LENGTH] = {0};
1482     if(!PMGenerateQuery(true,
1483                         otmCtx->selectedDeviceInfo->endpoint.addr,
1484                         otmCtx->selectedDeviceInfo->securePort,
1485                         otmCtx->selectedDeviceInfo->connType,
1486                         query, sizeof(query), OIC_RSRC_ACL_URI))
1487     {
1488         OIC_LOG(ERROR, TAG, "FinalizeProvisioning : Failed to generate query");
1489         return OC_STACK_ERROR;
1490     }
1491     OIC_LOG_V(DEBUG, TAG, "Query=%s", query);
1492
1493     OIC_LOG_V(INFO, TAG, "Request URI for Provisioning default ACL : %s", query);
1494
1495     OCCallbackData cbData =  {.context=NULL, .cb=NULL, .cd=NULL};
1496     cbData.cb = &FinalizeProvisioningCB;
1497     cbData.context = (void *)otmCtx;
1498     cbData.cd = NULL;
1499     OCStackResult ret = OCDoResource(NULL, OC_REST_POST, query,
1500             &otmCtx->selectedDeviceInfo->endpoint, (OCPayload*)secPayload,
1501             otmCtx->selectedDeviceInfo->connType, OC_HIGH_QOS, &cbData, NULL, 0);
1502     if (OC_STACK_OK != ret)
1503     {
1504         SetResult(otmCtx, ret);
1505         return ret;
1506     }
1507
1508     OIC_LOG(INFO, TAG, "OUT FinalizeProvisioning");
1509
1510     return ret;
1511
1512 }
1513