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