Revert back cbor related patches.
[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 static bool IsComplete(OTMContext_t* otmCtx)
230 {
231     for(size_t i = 0; i < otmCtx->ctxResultArraySize; i++)
232     {
233         if(OC_STACK_CONTINUE == otmCtx->ctxResultArray[i].res)
234         {
235             return false;
236         }
237     }
238
239     return true;
240 }
241
242 /**
243  * Function to save the result of provisioning.
244  *
245  * @param[in,out] otmCtx   Context value of ownership transfer.
246  * @param[in] res   result of provisioning
247  */
248 static void SetResult(OTMContext_t* otmCtx, const OCStackResult res)
249 {
250     OIC_LOG_V(DEBUG, TAG, "IN SetResult : %d ", res);
251
252     if(!otmCtx)
253     {
254         OIC_LOG(WARNING, TAG, "OTMContext is NULL");
255         return;
256     }
257
258     if(otmCtx->selectedDeviceInfo)
259     {
260         //Revert psk_info callback and new deivce uuid in case of random PIN OxM
261         if(OIC_RANDOM_DEVICE_PIN == otmCtx->selectedDeviceInfo->doxm->oxmSel)
262         {
263             if(CA_STATUS_OK != CARegisterDTLSCredentialsHandler(GetDtlsPskCredentials))
264             {
265                 OIC_LOG(WARNING, TAG, "Failed to revert  is DTLS credential handler.");
266             }
267             OicUuid_t emptyUuid = { .id={0}};
268             SetUuidForRandomPinOxm(&emptyUuid);
269         }
270
271         for(size_t i = 0; i < otmCtx->ctxResultArraySize; i++)
272         {
273             if(memcmp(otmCtx->selectedDeviceInfo->doxm->deviceID.id,
274                       otmCtx->ctxResultArray[i].deviceId.id, UUID_LENGTH) == 0)
275             {
276                 otmCtx->ctxResultArray[i].res = res;
277                 if(OC_STACK_OK != res)
278                 {
279                     otmCtx->ctxHasError = true;
280                 }
281             }
282         }
283
284         g_otmCtx = NULL;
285
286         //If all request is completed, invoke the user callback.
287         if(IsComplete(otmCtx))
288         {
289             otmCtx->ctxResultCallback(otmCtx->userCtx, otmCtx->ctxResultArraySize,
290                                        otmCtx->ctxResultArray, otmCtx->ctxHasError);
291             OICFree(otmCtx->ctxResultArray);
292             OICFree(otmCtx);
293         }
294         else
295         {
296             if(OC_STACK_OK != StartOwnershipTransfer(otmCtx,
297                                                      otmCtx->selectedDeviceInfo->next))
298             {
299                 OIC_LOG(ERROR, TAG, "Failed to StartOwnershipTransfer");
300             }
301         }
302     }
303
304     OIC_LOG(DEBUG, TAG, "OUT SetResult");
305 }
306
307 /**
308  * Function to handle the handshake result in OTM.
309  * This function will be invoked after DTLS handshake
310  * @param   endPoint  [IN] The remote endpoint.
311  * @param   errorInfo [IN] Error information from the endpoint.
312  * @return  NONE
313  */
314 void DTLSHandshakeCB(const CAEndpoint_t *endpoint, const CAErrorInfo_t *info)
315 {
316     if(NULL != g_otmCtx && NULL != g_otmCtx->selectedDeviceInfo &&
317        NULL != endpoint && NULL != info)
318     {
319         OIC_LOG_V(INFO, TAG, "Received status from remote device(%s:%d) : %d",
320                  endpoint->addr, endpoint->port, info->result);
321
322         OicSecDoxm_t* newDevDoxm = g_otmCtx->selectedDeviceInfo->doxm;
323
324         if(NULL != newDevDoxm)
325         {
326             OicUuid_t emptyUuid = {.id={0}};
327
328             //Make sure the address matches.
329             if(strncmp(g_otmCtx->selectedDeviceInfo->endpoint.addr,
330                endpoint->addr,
331                sizeof(endpoint->addr)) == 0 &&
332                g_otmCtx->selectedDeviceInfo->securePort == endpoint->port)
333             {
334                 OCStackResult res = OC_STACK_ERROR;
335
336                 //If temporal secure sesstion established successfully
337                 if(CA_STATUS_OK == info->result &&
338                    false == newDevDoxm->owned &&
339                    memcmp(&(newDevDoxm->owner), &emptyUuid, sizeof(OicUuid_t)) == 0)
340                 {
341                     //Send request : PUT /oic/sec/doxm [{... , "devowner":"PT's UUID"}]
342                     res = PutOwnerUuid(g_otmCtx);
343                     if(OC_STACK_OK != res)
344                     {
345                         OIC_LOG(ERROR, TAG, "OperationModeUpdate : Failed to send owner information");
346                         SetResult(g_otmCtx, res);
347                     }
348                 }
349                 //In case of authentication failure
350                 else if(CA_DTLS_AUTHENTICATION_FAILURE == info->result)
351                 {
352                     //in case of error from owner credential
353                     if(memcmp(&(newDevDoxm->owner), &emptyUuid, sizeof(OicUuid_t)) != 0 &&
354                         true == newDevDoxm->owned)
355                     {
356                         OIC_LOG(ERROR, TAG, "The owner credential may incorrect.");
357
358                         if(OC_STACK_OK != RemoveCredential(&(newDevDoxm->deviceID)))
359                         {
360                             OIC_LOG(WARNING, TAG, "Failed to remove the invaild owner credential");
361                         }
362                         SetResult(g_otmCtx, OC_STACK_AUTHENTICATION_FAILURE);
363                     }
364                     //in case of error from wrong PIN, re-start the ownership transfer
365                     else if(OIC_RANDOM_DEVICE_PIN == newDevDoxm->oxmSel)
366                     {
367                         OIC_LOG(ERROR, TAG, "The PIN number may incorrect.");
368
369                         memcpy(&(newDevDoxm->owner), &emptyUuid, sizeof(OicUuid_t));
370                         newDevDoxm->owned = false;
371                         g_otmCtx->attemptCnt++;
372
373                         if(WRONG_PIN_MAX_ATTEMP > g_otmCtx->attemptCnt)
374                         {
375                             res = StartOwnershipTransfer(g_otmCtx, g_otmCtx->selectedDeviceInfo);
376                             if(OC_STACK_OK != res)
377                             {
378                                 SetResult(g_otmCtx, res);
379                                 OIC_LOG(ERROR, TAG, "Failed to Re-StartOwnershipTransfer");
380                             }
381                         }
382                         else
383                         {
384                             OIC_LOG(ERROR, TAG, "User has exceeded the number of authentication attempts.");
385                             SetResult(g_otmCtx, OC_STACK_AUTHENTICATION_FAILURE);
386                         }
387                     }
388                     else
389                     {
390                         OIC_LOG(ERROR, TAG, "Failed to establish secure session.");
391                         SetResult(g_otmCtx, OC_STACK_AUTHENTICATION_FAILURE);
392                     }
393                 }
394             }
395         }
396     }
397 }
398
399 /**
400  * Function to save ownerPSK at provisioning tool end.
401  *
402  * @param[in] selectedDeviceInfo   selected device information to performing provisioning.
403  * @return  OC_STACK_OK on success
404  */
405 static OCStackResult SaveOwnerPSK(OCProvisionDev_t *selectedDeviceInfo)
406 {
407     OIC_LOG(DEBUG, TAG, "IN SaveOwnerPSK");
408
409     OCStackResult res = OC_STACK_ERROR;
410
411     CAEndpoint_t endpoint;
412     memset(&endpoint, 0x00, sizeof(CAEndpoint_t));
413     OICStrcpy(endpoint.addr, MAX_ADDR_STR_SIZE_CA, selectedDeviceInfo->endpoint.addr);
414     endpoint.addr[MAX_ADDR_STR_SIZE_CA - 1] = '\0';
415     endpoint.port = selectedDeviceInfo->securePort;
416
417     OicUuid_t ptDeviceID = {.id={0}};
418     if (OC_STACK_OK != GetDoxmDeviceID(&ptDeviceID))
419     {
420         OIC_LOG(ERROR, TAG, "Error while retrieving provisioning tool's device ID");
421         return res;
422     }
423
424     uint8_t ownerPSK[OWNER_PSK_LENGTH_128] = {0};
425
426     //Generating OwnerPSK
427     CAResult_t pskRet = CAGenerateOwnerPSK(&endpoint,
428             (uint8_t *)GetOxmString(selectedDeviceInfo->doxm->oxmSel),
429             strlen(GetOxmString(selectedDeviceInfo->doxm->oxmSel)),
430             ptDeviceID.id, sizeof(ptDeviceID.id),
431             selectedDeviceInfo->doxm->deviceID.id, sizeof(selectedDeviceInfo->doxm->deviceID.id),
432             ownerPSK, OWNER_PSK_LENGTH_128);
433
434     if (CA_STATUS_OK == pskRet)
435     {
436         OIC_LOG(INFO, TAG,"ownerPSK dump:\n");
437         OIC_LOG_BUFFER(INFO, TAG,ownerPSK, OWNER_PSK_LENGTH_128);
438         //Generating new credential for provisioning tool
439         size_t ownLen = 1;
440         uint32_t outLen = 0;
441
442         char base64Buff[B64ENCODE_OUT_SAFESIZE(sizeof(ownerPSK)) + 1] = {};
443         B64Result b64Ret = b64Encode(ownerPSK, sizeof(ownerPSK), base64Buff, sizeof(base64Buff),
444                 &outLen);
445         VERIFY_SUCCESS(TAG, B64_OK == b64Ret, ERROR);
446
447         OicSecCred_t *cred = GenerateCredential(&selectedDeviceInfo->doxm->deviceID,
448                 SYMMETRIC_PAIR_WISE_KEY, NULL,
449                 base64Buff, ownLen, &ptDeviceID);
450         VERIFY_NON_NULL(TAG, cred, ERROR);
451
452         res = AddCredential(cred);
453         if(res != OC_STACK_OK)
454         {
455             DeleteCredList(cred);
456             return res;
457         }
458     }
459     else
460     {
461         OIC_LOG(ERROR, TAG, "CAGenerateOwnerPSK failed");
462     }
463
464     OIC_LOG(DEBUG, TAG, "OUT SaveOwnerPSK");
465 exit:
466     return res;
467 }
468
469 /**
470  * Callback handler for OwnerShipTransferModeHandler API.
471  *
472  * @param[in] ctx             ctx value passed to callback from calling function.
473  * @param[in] UNUSED          handle to an invocation
474  * @param[in] clientResponse  Response from queries to remote servers.
475  * @return  OC_STACK_DELETE_TRANSACTION to delete the transaction
476  *          and  OC_STACK_KEEP_TRANSACTION to keep it.
477  */
478 static OCStackApplicationResult OwnerTransferModeHandler(void *ctx, OCDoHandle UNUSED,
479                                                          OCClientResponse *clientResponse)
480 {
481     OIC_LOG(DEBUG, TAG, "IN OwnerTransferModeHandler");
482
483     VERIFY_NON_NULL(TAG, clientResponse, WARNING);
484     VERIFY_NON_NULL(TAG, ctx, WARNING);
485
486     OTMContext_t* otmCtx = (OTMContext_t*)ctx;
487     (void)UNUSED;
488     if(clientResponse->result == OC_STACK_OK)
489     {
490         OIC_LOG(INFO, TAG, "OwnerTransferModeHandler : response result = OC_STACK_OK");
491         //Send request : GET /oic/sec/pstat
492         OCStackResult res = GetProvisioningStatusResource(otmCtx);
493         if(OC_STACK_OK != res)
494         {
495             OIC_LOG(WARNING, TAG, "Failed to get pstat information");
496             SetResult(otmCtx, res);
497         }
498     }
499     else
500     {
501         OIC_LOG_V(WARNING, TAG, "OwnerTransferModeHandler : Client response is incorrect : %d",
502         clientResponse->result);
503         SetResult(otmCtx, clientResponse->result);
504     }
505
506     OIC_LOG(DEBUG, TAG, "OUT OwnerTransferModeHandler");
507
508 exit:
509     return  OC_STACK_DELETE_TRANSACTION;
510 }
511
512 /**
513  * Callback handler for ProvisioningStatusResouceHandler API.
514  *
515  * @param[in] ctx             ctx value passed to callback from calling function.
516  * @param[in] UNUSED          handle to an invocation
517  * @param[in] clientResponse  Response from queries to remote servers.
518  * @return  OC_STACK_DELETE_TRANSACTION to delete the transaction
519  *          and  OC_STACK_KEEP_TRANSACTION to keep it.
520  */
521 static OCStackApplicationResult ListMethodsHandler(void *ctx, OCDoHandle UNUSED,
522                                                     OCClientResponse *clientResponse)
523 {
524     OIC_LOG(DEBUG, TAG, "IN ListMethodsHandler");
525
526     VERIFY_NON_NULL(TAG, clientResponse, WARNING);
527     VERIFY_NON_NULL(TAG, ctx, WARNING);
528
529     OTMContext_t* otmCtx = (OTMContext_t*)ctx;
530     (void)UNUSED;
531     if  (OC_STACK_OK == clientResponse->result)
532     {
533         if  (NULL == clientResponse->payload)
534         {
535             OIC_LOG(INFO, TAG, "Skiping Null payload");
536             SetResult(otmCtx, OC_STACK_ERROR);
537             return OC_STACK_DELETE_TRANSACTION;
538         }
539
540         if (PAYLOAD_TYPE_SECURITY != clientResponse->payload->type)
541         {
542             OIC_LOG(INFO, TAG, "Unknown payload type");
543             SetResult(otmCtx, OC_STACK_ERROR);
544             return OC_STACK_DELETE_TRANSACTION;
545         }
546
547         OicSecPstat_t* pstat = JSONToPstatBin(
548                 ((OCSecurityPayload*)clientResponse->payload)->securityData);
549         if(NULL == pstat)
550         {
551             OIC_LOG(ERROR, TAG, "Error while converting json to pstat bin");
552             SetResult(otmCtx, OC_STACK_ERROR);
553             return OC_STACK_DELETE_TRANSACTION;
554         }
555         otmCtx->selectedDeviceInfo->pstat = pstat;
556
557         //Select operation mode (Currently supported SINGLE_SERVICE_CLIENT_DRIVEN only)
558         SelectOperationMode(otmCtx->selectedDeviceInfo, &(otmCtx->selectedDeviceInfo->pstat->om));
559
560         //Send request : PUT /oic/sec/pstat [{"om":"bx11", .. }]
561         OCStackResult res = PutUpdateOperationMode(otmCtx);
562         if (OC_STACK_OK != res)
563         {
564             OIC_LOG(ERROR, TAG, "Error while updating operation mode.");
565             SetResult(otmCtx, res);
566         }
567     }
568     else
569     {
570         OIC_LOG_V(WARNING, TAG, "ListMethodsHandler : Client response is incorrect : %d",
571             clientResponse->result);
572         SetResult(otmCtx, clientResponse->result);
573     }
574
575     OIC_LOG(DEBUG, TAG, "OUT ListMethodsHandler");
576 exit:
577     return  OC_STACK_DELETE_TRANSACTION;
578 }
579
580 /**
581  * Response handler for update owner uuid request.
582  *
583  * @param[in] ctx             ctx value passed to callback from calling function.
584  * @param[in] UNUSED          handle to an invocation
585  * @param[in] clientResponse  Response from queries to remote servers.
586  * @return  OC_STACK_DELETE_TRANSACTION to delete the transaction
587  *          and  OC_STACK_KEEP_TRANSACTION to keep it.
588  */
589 static OCStackApplicationResult OwnerUuidUpdateHandler(void *ctx, OCDoHandle UNUSED,
590                                 OCClientResponse *clientResponse)
591 {
592     VERIFY_NON_NULL(TAG, clientResponse, WARNING);
593     VERIFY_NON_NULL(TAG, ctx, WARNING);
594
595     OIC_LOG(DEBUG, TAG, "IN OwnerUuidUpdateHandler");
596     (void)UNUSED;
597     OCStackResult res = OC_STACK_OK;
598     OTMContext_t* otmCtx = (OTMContext_t*)ctx;
599
600     if(OC_STACK_OK == clientResponse->result)
601     {
602         if(otmCtx && otmCtx->selectedDeviceInfo)
603         {
604             res = SaveOwnerPSK(otmCtx->selectedDeviceInfo);
605             if(OC_STACK_OK != res)
606             {
607                 OIC_LOG(ERROR, TAG, "OwnerUuidUpdateHandler:Failed to owner PSK generation");
608                 SetResult(otmCtx, res);
609                 return OC_STACK_DELETE_TRANSACTION;
610             }
611
612             //PUT owner credential to new device according to security spec B.
613             res = PutOwnerCredential(otmCtx);
614             if(OC_STACK_OK != res)
615             {
616                 OIC_LOG(ERROR, TAG,
617                         "OwnerUuidUpdateHandler:Failed to send PUT request for onwer credential");
618                 SetResult(otmCtx, res);
619                 return OC_STACK_DELETE_TRANSACTION;
620             }
621         }
622     }
623     else
624     {
625         res = clientResponse->result;
626         OIC_LOG_V(ERROR, TAG, "OwnerUuidHandler : Unexpected result %d", res);
627         SetResult(otmCtx, res);
628     }
629
630     OIC_LOG(DEBUG, TAG, "OUT OwnerUuidUpdateHandler");
631
632 exit:
633     return  OC_STACK_DELETE_TRANSACTION;
634 }
635
636 /**
637  * Response handler for update operation mode.
638  *
639  * @param[in] ctx             ctx value passed to callback from calling function.
640  * @param[in] UNUSED          handle to an invocation
641  * @param[in] clientResponse  Response from queries to remote servers.
642  * @return  OC_STACK_DELETE_TRANSACTION to delete the transaction
643  *          and  OC_STACK_KEEP_TRANSACTION to keep it.
644  */
645 static OCStackApplicationResult OperationModeUpdateHandler(void *ctx, OCDoHandle UNUSED,
646                                 OCClientResponse *clientResponse)
647 {
648     OIC_LOG(DEBUG, TAG, "IN OperationModeUpdateHandler");
649
650     VERIFY_NON_NULL(TAG, clientResponse, WARNING);
651     VERIFY_NON_NULL(TAG, ctx, WARNING);
652
653     OTMContext_t* otmCtx = (OTMContext_t*)ctx;
654     (void) UNUSED;
655     if  (OC_STACK_OK == clientResponse->result)
656     {
657         OCStackResult res = OC_STACK_ERROR;
658         OicSecOxm_t selOxm = otmCtx->selectedDeviceInfo->doxm->oxmSel;
659         //DTLS Handshake
660         //Load secret for temporal secure session.
661         if(g_OTMDatas[selOxm].loadSecretCB)
662         {
663             res = g_OTMDatas[selOxm].loadSecretCB(otmCtx);
664             if(OC_STACK_OK != res)
665             {
666                 OIC_LOG(ERROR, TAG, "OperationModeUpdate : Failed to load secret");
667                 SetResult(otmCtx, res);
668                 return  OC_STACK_DELETE_TRANSACTION;
669             }
670         }
671
672         //It will be used in handshake event handler
673         g_otmCtx = otmCtx;
674
675         //Try DTLS handshake to generate secure session
676         if(g_OTMDatas[selOxm].createSecureSessionCB)
677         {
678             res = g_OTMDatas[selOxm].createSecureSessionCB(otmCtx);
679             if(OC_STACK_OK != res)
680             {
681                 OIC_LOG(ERROR, TAG, "OperationModeUpdate : Failed to create DTLS session");
682                 SetResult(otmCtx, res);
683                 return OC_STACK_DELETE_TRANSACTION;
684             }
685         }
686     }
687     else
688     {
689         OIC_LOG(ERROR, TAG, "Error while update operation mode");
690         SetResult(otmCtx, clientResponse->result);
691     }
692
693     OIC_LOG(DEBUG, TAG, "OUT OperationModeUpdateHandler");
694
695 exit:
696     return  OC_STACK_DELETE_TRANSACTION;
697 }
698
699 /**
700  * Response handler for update owner crendetial request.
701  *
702  * @param[in] ctx             ctx value passed to callback from calling function.
703  * @param[in] UNUSED          handle to an invocation
704  * @param[in] clientResponse  Response from queries to remote servers.
705  * @return  OC_STACK_DELETE_TRANSACTION to delete the transaction
706  *          and  OC_STACK_KEEP_TRANSACTION to keep it.
707  */
708 static OCStackApplicationResult OwnerCredentialHandler(void *ctx, OCDoHandle UNUSED,
709                                 OCClientResponse *clientResponse)
710 {
711     VERIFY_NON_NULL(TAG, clientResponse, WARNING);
712     VERIFY_NON_NULL(TAG, ctx, WARNING);
713
714     OIC_LOG(DEBUG, TAG, "IN OwnerCredentialHandler");
715     (void)UNUSED;
716     OCStackResult res = OC_STACK_OK;
717     OTMContext_t* otmCtx = (OTMContext_t*)ctx;
718
719     if(OC_STACK_RESOURCE_CREATED == clientResponse->result)
720     {
721         if(otmCtx && otmCtx->selectedDeviceInfo)
722         {
723             //Close the temporal secure session to verify the owner credential
724             CAEndpoint_t* endpoint = (CAEndpoint_t *)&otmCtx->selectedDeviceInfo->endpoint;
725             endpoint->port = otmCtx->selectedDeviceInfo->securePort;
726             CAResult_t caResult = CACloseDtlsSession(endpoint);
727             if(CA_STATUS_OK != caResult)
728             {
729                 OIC_LOG(ERROR, TAG, "Failed to close DTLS session");
730                 SetResult(otmCtx, caResult);
731                 return OC_STACK_DELETE_TRANSACTION;
732             }
733
734             /**
735              * If we select NULL cipher,
736              * client will select appropriate cipher suite according to server's cipher-suite list.
737              */
738             caResult = CASelectCipherSuite(TLS_NULL_WITH_NULL_NULL);
739             if(CA_STATUS_OK != caResult)
740             {
741                 OIC_LOG(ERROR, TAG, "Failed to select TLS_NULL_WITH_NULL_NULL");
742                 SetResult(otmCtx, caResult);
743                 return OC_STACK_DELETE_TRANSACTION;
744             }
745
746             /**
747              * in case of random PIN based OxM,
748              * revert get_psk_info callback of tinyDTLS to use owner credential.
749              */
750             if(OIC_RANDOM_DEVICE_PIN == otmCtx->selectedDeviceInfo->doxm->oxmSel)
751             {
752                 OicUuid_t emptyUuid = { .id={0}};
753                 SetUuidForRandomPinOxm(&emptyUuid);
754
755                 if(CA_STATUS_OK != CARegisterDTLSCredentialsHandler(GetDtlsPskCredentials))
756                 {
757                     OIC_LOG(ERROR, TAG, "Failed to revert DTLS credential handler.");
758                     SetResult(otmCtx, OC_STACK_INVALID_CALLBACK);
759                     return OC_STACK_DELETE_TRANSACTION;
760                 }
761             }
762
763             //PUT /oic/sec/doxm [{ ..., "owned":"TRUE" }]
764             res = PutOwnershipInformation(otmCtx);
765             if(OC_STACK_OK != res)
766             {
767                 OIC_LOG(ERROR, TAG, "Failed to put ownership information to new device");
768                 SetResult(otmCtx, res);
769                 return OC_STACK_DELETE_TRANSACTION;
770             }
771         }
772     }
773     else
774     {
775         res = clientResponse->result;
776         OIC_LOG_V(ERROR, TAG, "OwnerCredentialHandler : Unexpected result %d", res);
777         SetResult(otmCtx, res);
778     }
779
780     OIC_LOG(DEBUG, TAG, "OUT OwnerCredentialHandler");
781
782 exit:
783     return  OC_STACK_DELETE_TRANSACTION;
784 }
785
786
787 /**
788  * Response handler for update owner information request.
789  *
790  * @param[in] ctx             ctx value passed to callback from calling function.
791  * @param[in] UNUSED          handle to an invocation
792  * @param[in] clientResponse  Response from queries to remote servers.
793  * @return  OC_STACK_DELETE_TRANSACTION to delete the transaction
794  *          and  OC_STACK_KEEP_TRANSACTION to keep it.
795  */
796 static OCStackApplicationResult OwnershipInformationHandler(void *ctx, OCDoHandle UNUSED,
797                                 OCClientResponse *clientResponse)
798 {
799     VERIFY_NON_NULL(TAG, clientResponse, WARNING);
800     VERIFY_NON_NULL(TAG, ctx, WARNING);
801
802     OIC_LOG(DEBUG, TAG, "IN OwnershipInformationHandler");
803     (void)UNUSED;
804     OCStackResult res = OC_STACK_OK;
805     OTMContext_t* otmCtx = (OTMContext_t*)ctx;
806
807     if(OC_STACK_OK == clientResponse->result)
808     {
809         if(otmCtx && otmCtx->selectedDeviceInfo)
810         {
811             OIC_LOG(INFO, TAG, "Ownership transfer was successfully completed.");
812             OIC_LOG(INFO, TAG, "Start defualt ACL & commit-hash provisioning.");
813
814             res = PutProvisioningStatus(otmCtx);
815             if(OC_STACK_OK != res)
816             {
817                 OIC_LOG(ERROR, TAG, "Failed to update pstat");
818                 SetResult(otmCtx, res);
819             }
820         }
821     }
822     else
823     {
824         res = clientResponse->result;
825         OIC_LOG_V(ERROR, TAG, "OwnershipInformationHandler : Unexpected result %d", res);
826         SetResult(otmCtx, res);
827     }
828
829     OIC_LOG(DEBUG, TAG, "OUT OwnershipInformationHandler");
830
831 exit:
832     return  OC_STACK_DELETE_TRANSACTION;
833 }
834
835 /**
836  * Response handler of update provisioning status.
837  *
838  * @param[in] ctx             ctx value passed to callback from calling function.
839  * @param[in] UNUSED          handle to an invocation
840  * @param[in] clientResponse  Response from queries to remote servers.
841  * @return  OC_STACK_DELETE_TRANSACTION to delete the transaction
842  *          and OC_STACK_KEEP_TRANSACTION to keep it.
843  */
844 static OCStackApplicationResult ProvisioningStatusHandler(void *ctx, OCDoHandle UNUSED,
845                                                        OCClientResponse *clientResponse)
846 {
847     OIC_LOG_V(INFO, TAG, "IN ProvisioningStatusHandler.");
848
849     VERIFY_NON_NULL(TAG, clientResponse, ERROR);
850     VERIFY_NON_NULL(TAG, ctx, ERROR);
851
852     OTMContext_t* otmCtx = (OTMContext_t*) ctx;
853     (void)UNUSED;
854
855     if (OC_STACK_OK == clientResponse->result)
856     {
857         OCStackResult res = PDMAddDevice(&otmCtx->selectedDeviceInfo->doxm->deviceID);
858          if (OC_STACK_OK == res)
859          {
860                 OIC_LOG_V(INFO, TAG, "Add device's UUID in PDM_DB");
861                 SetResult(otmCtx, OC_STACK_OK);
862                 return OC_STACK_DELETE_TRANSACTION;
863          }
864           else
865          {
866               OIC_LOG(ERROR, TAG, "Ownership transfer is complete but adding information to DB is failed.");
867          }
868     }
869     else
870     {
871         OIC_LOG_V(INFO, TAG, "Error occured in provisionDefaultACLCB :: %d\n",
872                             clientResponse->result);
873         SetResult(otmCtx, clientResponse->result);
874     }
875
876
877 exit:
878     OIC_LOG_V(INFO, TAG, "OUT ProvisioningStatusHandler.");
879     return OC_STACK_DELETE_TRANSACTION;
880 }
881
882 static OCStackResult PutOwnerCredential(OTMContext_t* otmCtx)
883 {
884     OIC_LOG(DEBUG, TAG, "IN PutOwnerCredential");
885
886     if(!otmCtx || !otmCtx->selectedDeviceInfo)
887     {
888         OIC_LOG(ERROR, TAG, "Invalid parameters");
889         return OC_STACK_INVALID_PARAM;
890     }
891
892     OCProvisionDev_t* deviceInfo = otmCtx->selectedDeviceInfo;
893     char query[MAX_URI_LENGTH + MAX_QUERY_LENGTH] = {0};
894
895     if(!PMGenerateQuery(true,
896                         deviceInfo->endpoint.addr, deviceInfo->securePort,
897                         deviceInfo->connType,
898                         query, sizeof(query), OIC_RSRC_CRED_URI))
899     {
900         OIC_LOG(ERROR, TAG, "PutOwnerCredential : Failed to generate query");
901         return OC_STACK_ERROR;
902     }
903     OIC_LOG_V(DEBUG, TAG, "Query=%s", query);
904     OCSecurityPayload* secPayload = (OCSecurityPayload*)OICCalloc(1, sizeof(OCSecurityPayload));
905     if(!secPayload)
906     {
907         OIC_LOG(ERROR, TAG, "Failed to memory allocation");
908         return OC_STACK_NO_MEMORY;
909     }
910
911     //Generate owner credential for new device
912     secPayload->base.type = PAYLOAD_TYPE_SECURITY;
913     OicSecCred_t* ownerCredential =
914         GetCredResourceData(&(deviceInfo->doxm->deviceID));
915     if(!ownerCredential)
916     {
917         OIC_LOG(ERROR, TAG, "Can not find OwnerPSK.");
918         return OC_STACK_NO_RESOURCE;
919     }
920
921     OicUuid_t credSubjectId = {.id={0}};
922     if(OC_STACK_OK == GetDoxmDeviceID(&credSubjectId))
923     {
924         OicSecCred_t newCredential;
925         memcpy(&newCredential, ownerCredential, sizeof(OicSecCred_t));
926         newCredential.next = NULL;
927
928         //Set subject ID as PT's ID
929         memcpy(&(newCredential.subject), &credSubjectId, sizeof(OicUuid_t));
930
931         //Fill private data as empty string
932         newCredential.privateData.data = NULL;
933
934         //Send owner credential to new device : PUT /oic/sec/cred [ owner credential ]
935         secPayload->securityData = BinToCredJSON(&newCredential);
936         if (NULL == secPayload->securityData)
937         {
938             OICFree(secPayload);
939             OIC_LOG(ERROR, TAG, "Error while converting bin to json");
940             return OC_STACK_ERROR;
941         }
942         OIC_LOG_V(DEBUG, TAG, "Payload : %s", secPayload->securityData);
943
944         OCCallbackData cbData;
945         cbData.cb = &OwnerCredentialHandler;
946         cbData.context = (void *)otmCtx;
947         cbData.cd = NULL;
948         OCStackResult res = OCDoResource(NULL, OC_REST_PUT, query,
949                                          &deviceInfo->endpoint, (OCPayload*)secPayload,
950                                          deviceInfo->connType, OC_LOW_QOS, &cbData, NULL, 0);
951         if (res != OC_STACK_OK)
952         {
953             OIC_LOG(ERROR, TAG, "OCStack resource error");
954         }
955     }
956     else
957     {
958         OIC_LOG(ERROR, TAG, "Failed to read DOXM device ID.");
959         return OC_STACK_NO_RESOURCE;
960     }
961
962     OIC_LOG(DEBUG, TAG, "OUT PutOwnerCredential");
963
964     return OC_STACK_OK;
965 }
966
967 static OCStackResult PutOwnerTransferModeToResource(OTMContext_t* otmCtx)
968 {
969     OIC_LOG(DEBUG, TAG, "IN PutOwnerTransferModeToResource");
970
971     if(!otmCtx || !otmCtx->selectedDeviceInfo)
972     {
973         OIC_LOG(ERROR, TAG, "Invalid parameters");
974         return OC_STACK_INVALID_PARAM;
975     }
976
977     OCProvisionDev_t* deviceInfo = otmCtx->selectedDeviceInfo;
978     OicSecOxm_t selectedOxm = deviceInfo->doxm->oxmSel;
979     char query[MAX_URI_LENGTH + MAX_QUERY_LENGTH] = {0};
980
981     if(!PMGenerateQuery(false,
982                         deviceInfo->endpoint.addr, deviceInfo->endpoint.port,
983                         deviceInfo->connType,
984                         query, sizeof(query), OIC_RSRC_DOXM_URI))
985     {
986         OIC_LOG(ERROR, TAG, "PutOwnerTransferModeToResource : Failed to generate query");
987         return OC_STACK_ERROR;
988     }
989     OIC_LOG_V(DEBUG, TAG, "Query=%s", query);
990     OCSecurityPayload* secPayload = (OCSecurityPayload*)OICCalloc(1, sizeof(OCSecurityPayload));
991     if(!secPayload)
992     {
993         OIC_LOG(ERROR, TAG, "Failed to memory allocation");
994         return OC_STACK_NO_MEMORY;
995     }
996     secPayload->base.type = PAYLOAD_TYPE_SECURITY;
997     secPayload->securityData = g_OTMDatas[selectedOxm].createSelectOxmPayloadCB(otmCtx);
998     if (NULL == secPayload->securityData)
999     {
1000         OICFree(secPayload);
1001         OIC_LOG(ERROR, TAG, "Error while converting bin to json");
1002         return OC_STACK_ERROR;
1003     }
1004
1005     OCCallbackData cbData;
1006     cbData.cb = &OwnerTransferModeHandler;
1007     cbData.context = (void *)otmCtx;
1008     cbData.cd = NULL;
1009     OCStackResult res = OCDoResource(NULL, OC_REST_PUT, query,
1010                                      &deviceInfo->endpoint, (OCPayload*)secPayload,
1011                                      deviceInfo->connType, OC_LOW_QOS, &cbData, NULL, 0);
1012     if (res != OC_STACK_OK)
1013     {
1014         OIC_LOG(ERROR, TAG, "OCStack resource error");
1015     }
1016
1017     OIC_LOG(DEBUG, TAG, "OUT PutOwnerTransferModeToResource");
1018
1019     return res;
1020 }
1021
1022 static OCStackResult GetProvisioningStatusResource(OTMContext_t* otmCtx)
1023 {
1024     OIC_LOG(DEBUG, TAG, "IN GetProvisioningStatusResource");
1025
1026     if(!otmCtx || !otmCtx->selectedDeviceInfo)
1027     {
1028         OIC_LOG(ERROR, TAG, "Invailed parameters");
1029         return OC_STACK_INVALID_PARAM;
1030     }
1031
1032     OCProvisionDev_t* deviceInfo = otmCtx->selectedDeviceInfo;
1033     char query[MAX_URI_LENGTH + MAX_QUERY_LENGTH] = {0};
1034     if(!PMGenerateQuery(false,
1035                         deviceInfo->endpoint.addr, deviceInfo->endpoint.port,
1036                         deviceInfo->connType,
1037                         query, sizeof(query), OIC_RSRC_PSTAT_URI))
1038     {
1039         OIC_LOG(ERROR, TAG, "GetProvisioningStatusResource : Failed to generate query");
1040         return OC_STACK_ERROR;
1041     }
1042     OIC_LOG_V(DEBUG, TAG, "Query=%s", query);
1043
1044     OCCallbackData cbData;
1045     cbData.cb = &ListMethodsHandler;
1046     cbData.context = (void *)otmCtx;
1047     cbData.cd = NULL;
1048     OCStackResult res = OCDoResource(NULL, OC_REST_GET, query, NULL, NULL,
1049                                      deviceInfo->connType, OC_LOW_QOS, &cbData, NULL, 0);
1050     if (res != OC_STACK_OK)
1051     {
1052         OIC_LOG(ERROR, TAG, "OCStack resource error");
1053     }
1054
1055     OIC_LOG(DEBUG, TAG, "OUT GetProvisioningStatusResource");
1056
1057     return res;
1058 }
1059
1060 static OCStackResult PutOwnerUuid(OTMContext_t* otmCtx)
1061 {
1062     OIC_LOG(DEBUG, TAG, "IN PutOwnerUuid");
1063
1064     if(!otmCtx || !otmCtx->selectedDeviceInfo)
1065     {
1066         OIC_LOG(ERROR, TAG, "Invailed parameters");
1067         return OC_STACK_INVALID_PARAM;
1068     }
1069
1070     OCProvisionDev_t* deviceInfo = otmCtx->selectedDeviceInfo;
1071     char query[MAX_URI_LENGTH + MAX_QUERY_LENGTH] = {0};
1072     if(!PMGenerateQuery(true,
1073                         deviceInfo->endpoint.addr, deviceInfo->securePort,
1074                         deviceInfo->connType,
1075                         query, sizeof(query), OIC_RSRC_DOXM_URI))
1076     {
1077         OIC_LOG(ERROR, TAG, "PutOwnershipInformation : Failed to generate query");
1078         return OC_STACK_ERROR;
1079     }
1080     OIC_LOG_V(DEBUG, TAG, "Query=%s", query);
1081
1082     //PUT PT's uuid to new device
1083     OCSecurityPayload* secPayload = (OCSecurityPayload*)OICCalloc(1, sizeof(OCSecurityPayload));
1084     if(!secPayload)
1085     {
1086         OIC_LOG(ERROR, TAG, "Failed to memory allocation");
1087         return OC_STACK_NO_MEMORY;
1088     }
1089     secPayload->base.type = PAYLOAD_TYPE_SECURITY;
1090     secPayload->securityData =
1091         g_OTMDatas[deviceInfo->doxm->oxmSel].createOwnerTransferPayloadCB(otmCtx);
1092     if (NULL == secPayload->securityData)
1093     {
1094         OICFree(secPayload);
1095         OIC_LOG(ERROR, TAG, "Error while converting doxm bin to json");
1096         return OC_STACK_INVALID_PARAM;
1097     }
1098     OIC_LOG_V(DEBUG, TAG, "Payload : %s", secPayload->securityData);
1099
1100     OCCallbackData cbData;
1101     cbData.cb = &OwnerUuidUpdateHandler;
1102     cbData.context = (void *)otmCtx;
1103     cbData.cd = NULL;
1104
1105     OCStackResult res = OCDoResource(NULL, OC_REST_PUT, query, 0, (OCPayload*)secPayload,
1106                                      deviceInfo->connType, OC_LOW_QOS, &cbData, NULL, 0);
1107     if (res != OC_STACK_OK)
1108     {
1109         OIC_LOG(ERROR, TAG, "OCStack resource error");
1110     }
1111
1112     OIC_LOG(DEBUG, TAG, "OUT PutOwnerUuid");
1113
1114     return res;
1115 }
1116
1117 static OCStackResult PutOwnershipInformation(OTMContext_t* otmCtx)
1118 {
1119     OIC_LOG(DEBUG, TAG, "IN PutOwnershipInformation");
1120
1121     if(!otmCtx || !otmCtx->selectedDeviceInfo)
1122     {
1123         OIC_LOG(ERROR, TAG, "Invailed parameters");
1124         return OC_STACK_INVALID_PARAM;
1125     }
1126
1127     OCProvisionDev_t* deviceInfo = otmCtx->selectedDeviceInfo;
1128     char query[MAX_URI_LENGTH + MAX_QUERY_LENGTH] = {0};
1129     if(!PMGenerateQuery(true,
1130                         deviceInfo->endpoint.addr, deviceInfo->securePort,
1131                         deviceInfo->connType,
1132                         query, sizeof(query), OIC_RSRC_DOXM_URI))
1133     {
1134         OIC_LOG(ERROR, TAG, "PutOwnershipInformation : Failed to generate query");
1135         return OC_STACK_ERROR;
1136     }
1137     OIC_LOG_V(DEBUG, TAG, "Query=%s", query);
1138
1139     //OwnershipInformationHandler
1140     OCSecurityPayload* secPayload = (OCSecurityPayload*)OICCalloc(1, sizeof(OCSecurityPayload));
1141     if(!secPayload)
1142     {
1143         OIC_LOG(ERROR, TAG, "Failed to memory allocation");
1144         return OC_STACK_NO_MEMORY;
1145     }
1146
1147     otmCtx->selectedDeviceInfo->doxm->owned = true;
1148     secPayload->securityData = BinToDoxmJSON(otmCtx->selectedDeviceInfo->doxm);
1149     if (NULL == secPayload->securityData)
1150     {
1151         OICFree(secPayload);
1152         OIC_LOG(ERROR, TAG, "Error while converting doxm bin to json");
1153         return OC_STACK_INVALID_PARAM;
1154     }
1155     secPayload->base.type = PAYLOAD_TYPE_SECURITY;
1156
1157     OCCallbackData cbData;
1158     cbData.cb = &OwnershipInformationHandler;
1159     cbData.context = (void *)otmCtx;
1160     cbData.cd = NULL;
1161
1162     OCStackResult res = OCDoResource(NULL, OC_REST_PUT, query, 0, (OCPayload*)secPayload,
1163                                      deviceInfo->connType, OC_LOW_QOS, &cbData, NULL, 0);
1164     if (res != OC_STACK_OK)
1165     {
1166         OIC_LOG(ERROR, TAG, "OCStack resource error");
1167     }
1168
1169     OIC_LOG(DEBUG, TAG, "OUT PutOwnershipInformation");
1170
1171     return res;
1172 }
1173
1174 static OCStackResult PutUpdateOperationMode(OTMContext_t* otmCtx)
1175 {
1176     OIC_LOG(DEBUG, TAG, "IN PutUpdateOperationMode");
1177
1178     if(!otmCtx || !otmCtx->selectedDeviceInfo)
1179     {
1180         return OC_STACK_INVALID_PARAM;
1181     }
1182
1183     OCProvisionDev_t* deviceInfo = otmCtx->selectedDeviceInfo;
1184     char query[MAX_URI_LENGTH + MAX_QUERY_LENGTH] = {0};
1185     if(!PMGenerateQuery(false,
1186                         deviceInfo->endpoint.addr, deviceInfo->endpoint.port,
1187                         deviceInfo->connType,
1188                         query, sizeof(query), OIC_RSRC_PSTAT_URI))
1189     {
1190         OIC_LOG(ERROR, TAG, "PutUpdateOperationMode : Failed to generate query");
1191         return OC_STACK_ERROR;
1192     }
1193     OIC_LOG_V(DEBUG, TAG, "Query=%s", query);
1194
1195     OCSecurityPayload* secPayload = (OCSecurityPayload*)OICCalloc(1, sizeof(OCSecurityPayload));
1196     if(!secPayload)
1197     {
1198         OIC_LOG(ERROR, TAG, "Failed to memory allocation");
1199         return OC_STACK_NO_MEMORY;
1200     }
1201     secPayload->base.type = PAYLOAD_TYPE_SECURITY;
1202     secPayload->securityData = BinToPstatJSON(deviceInfo->pstat);
1203     if (NULL == secPayload->securityData)
1204     {
1205         OICFree(secPayload);
1206         OIC_LOG(ERROR, TAG, "Error while converting pstat bin to json");
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     OCStackResult 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
1373 OCStackResult PutProvisioningStatus(OTMContext_t* otmCtx)
1374 {
1375     OIC_LOG(INFO, TAG, "IN PutProvisioningStatus");
1376
1377     if(!otmCtx)
1378     {
1379         OIC_LOG(ERROR, TAG, "OTMContext is NULL");
1380         return OC_STACK_INVALID_PARAM;
1381     }
1382     if(!otmCtx->selectedDeviceInfo)
1383     {
1384         OIC_LOG(ERROR, TAG, "Can't find device information in OTMContext");
1385         OICFree(otmCtx);
1386         return OC_STACK_INVALID_PARAM;
1387     }
1388
1389     otmCtx->selectedDeviceInfo->pstat->tm = NORMAL;
1390     otmCtx->selectedDeviceInfo->pstat->cm = PROVISION_ACLS | PROVISION_CREDENTIALS |
1391                                             SECURITY_MANAGEMENT_SERVICES | BOOTSTRAP_SERVICE;
1392     OCSecurityPayload* secPayload = (OCSecurityPayload*)OICCalloc(1, sizeof(OCSecurityPayload));
1393     if(!secPayload)
1394     {
1395         OIC_LOG(ERROR, TAG, "Failed to memory allocation");
1396         return OC_STACK_NO_MEMORY;
1397     }
1398     secPayload->base.type = PAYLOAD_TYPE_SECURITY;
1399     secPayload->securityData = BinToPstatJSON(otmCtx->selectedDeviceInfo->pstat);
1400     if (NULL == secPayload->securityData)
1401     {
1402         OICFree(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->securityData);
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 }
1437