Pstat 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         uint32_t outLen = 0;
443
444         char base64Buff[B64ENCODE_OUT_SAFESIZE(sizeof(ownerPSK)) + 1] = {};
445         B64Result b64Ret = b64Encode(ownerPSK, sizeof(ownerPSK), base64Buff, sizeof(base64Buff),
446                 &outLen);
447         VERIFY_SUCCESS(TAG, B64_OK == b64Ret, ERROR);
448
449         OicSecCred_t *cred = GenerateCredential(&selectedDeviceInfo->doxm->deviceID,
450                 SYMMETRIC_PAIR_WISE_KEY, NULL,
451                 base64Buff, ownLen, &ptDeviceID);
452         VERIFY_NON_NULL(TAG, cred, ERROR);
453
454         res = AddCredential(cred);
455         if(res != OC_STACK_OK)
456         {
457             DeleteCredList(cred);
458             return res;
459         }
460     }
461     else
462     {
463         OIC_LOG(ERROR, TAG, "CAGenerateOwnerPSK failed");
464     }
465
466     OIC_LOG(DEBUG, TAG, "OUT SaveOwnerPSK");
467 exit:
468     return res;
469 }
470
471 /**
472  * Callback handler for OwnerShipTransferModeHandler API.
473  *
474  * @param[in] ctx             ctx value passed to callback from calling function.
475  * @param[in] UNUSED          handle to an invocation
476  * @param[in] clientResponse  Response from queries to remote servers.
477  * @return  OC_STACK_DELETE_TRANSACTION to delete the transaction
478  *          and  OC_STACK_KEEP_TRANSACTION to keep it.
479  */
480 static OCStackApplicationResult OwnerTransferModeHandler(void *ctx, OCDoHandle UNUSED,
481                                                          OCClientResponse *clientResponse)
482 {
483     OIC_LOG(DEBUG, TAG, "IN OwnerTransferModeHandler");
484
485     VERIFY_NON_NULL(TAG, clientResponse, WARNING);
486     VERIFY_NON_NULL(TAG, ctx, WARNING);
487
488     OTMContext_t* otmCtx = (OTMContext_t*)ctx;
489     (void)UNUSED;
490     if(clientResponse->result == OC_STACK_OK)
491     {
492         OIC_LOG(INFO, TAG, "OwnerTransferModeHandler : response result = OC_STACK_OK");
493         //Send request : GET /oic/sec/pstat
494         OCStackResult res = GetProvisioningStatusResource(otmCtx);
495         if(OC_STACK_OK != res)
496         {
497             OIC_LOG(WARNING, TAG, "Failed to get pstat information");
498             SetResult(otmCtx, res);
499         }
500     }
501     else
502     {
503         OIC_LOG_V(WARNING, TAG, "OwnerTransferModeHandler : Client response is incorrect : %d",
504         clientResponse->result);
505         SetResult(otmCtx, clientResponse->result);
506     }
507
508     OIC_LOG(DEBUG, TAG, "OUT OwnerTransferModeHandler");
509
510 exit:
511     return  OC_STACK_DELETE_TRANSACTION;
512 }
513
514 /**
515  * Callback handler for ProvisioningStatusResouceHandler API.
516  *
517  * @param[in] ctx             ctx value passed to callback from calling function.
518  * @param[in] UNUSED          handle to an invocation
519  * @param[in] clientResponse  Response from queries to remote servers.
520  * @return  OC_STACK_DELETE_TRANSACTION to delete the transaction
521  *          and  OC_STACK_KEEP_TRANSACTION to keep it.
522  */
523 static OCStackApplicationResult ListMethodsHandler(void *ctx, OCDoHandle UNUSED,
524                                                     OCClientResponse *clientResponse)
525 {
526     OIC_LOG(DEBUG, TAG, "IN ListMethodsHandler");
527
528     VERIFY_NON_NULL(TAG, clientResponse, WARNING);
529     VERIFY_NON_NULL(TAG, ctx, WARNING);
530
531     OTMContext_t* otmCtx = (OTMContext_t*)ctx;
532     (void)UNUSED;
533     if  (OC_STACK_OK == clientResponse->result)
534     {
535         if  (NULL == clientResponse->payload)
536         {
537             OIC_LOG(INFO, TAG, "Skiping Null payload");
538             SetResult(otmCtx, OC_STACK_ERROR);
539             return OC_STACK_DELETE_TRANSACTION;
540         }
541
542         if (PAYLOAD_TYPE_SECURITY != clientResponse->payload->type)
543         {
544             OIC_LOG(INFO, TAG, "Unknown payload type");
545             SetResult(otmCtx, OC_STACK_ERROR);
546             return OC_STACK_DELETE_TRANSACTION;
547         }
548         uint8_t size = 0;
549         OicSecPstat_t* pstat = NULL;
550         OCStackResult result = CBORPayloadToPstat(
551                 ((OCSecurityPayload*)clientResponse->payload)->securityData1,
552                 size, &pstat);
553         if(NULL == pstat && result != OC_STACK_OK)
554         {
555             OIC_LOG(ERROR, TAG, "Error while converting cbor to pstat.");
556             SetResult(otmCtx, OC_STACK_ERROR);
557             return OC_STACK_DELETE_TRANSACTION;
558         }
559         otmCtx->selectedDeviceInfo->pstat = pstat;
560
561         //Select operation mode (Currently supported SINGLE_SERVICE_CLIENT_DRIVEN only)
562         SelectOperationMode(otmCtx->selectedDeviceInfo, &(otmCtx->selectedDeviceInfo->pstat->om));
563
564         //Send request : PUT /oic/sec/pstat [{"om":"bx11", .. }]
565         OCStackResult res = PutUpdateOperationMode(otmCtx);
566         if (OC_STACK_OK != res)
567         {
568             OIC_LOG(ERROR, TAG, "Error while updating operation mode.");
569             SetResult(otmCtx, res);
570         }
571     }
572     else
573     {
574         OIC_LOG_V(WARNING, TAG, "ListMethodsHandler : Client response is incorrect : %d",
575             clientResponse->result);
576         SetResult(otmCtx, clientResponse->result);
577     }
578
579     OIC_LOG(DEBUG, TAG, "OUT ListMethodsHandler");
580 exit:
581     return  OC_STACK_DELETE_TRANSACTION;
582 }
583
584 /**
585  * Response handler for update owner uuid request.
586  *
587  * @param[in] ctx             ctx value passed to callback from calling function.
588  * @param[in] UNUSED          handle to an invocation
589  * @param[in] clientResponse  Response from queries to remote servers.
590  * @return  OC_STACK_DELETE_TRANSACTION to delete the transaction
591  *          and  OC_STACK_KEEP_TRANSACTION to keep it.
592  */
593 static OCStackApplicationResult OwnerUuidUpdateHandler(void *ctx, OCDoHandle UNUSED,
594                                 OCClientResponse *clientResponse)
595 {
596     VERIFY_NON_NULL(TAG, clientResponse, WARNING);
597     VERIFY_NON_NULL(TAG, ctx, WARNING);
598
599     OIC_LOG(DEBUG, TAG, "IN OwnerUuidUpdateHandler");
600     (void)UNUSED;
601     OCStackResult res = OC_STACK_OK;
602     OTMContext_t* otmCtx = (OTMContext_t*)ctx;
603
604     if(OC_STACK_OK == clientResponse->result)
605     {
606         if(otmCtx && otmCtx->selectedDeviceInfo)
607         {
608             res = SaveOwnerPSK(otmCtx->selectedDeviceInfo);
609             if(OC_STACK_OK != res)
610             {
611                 OIC_LOG(ERROR, TAG, "OwnerUuidUpdateHandler:Failed to owner PSK generation");
612                 SetResult(otmCtx, res);
613                 return OC_STACK_DELETE_TRANSACTION;
614             }
615
616             //PUT owner credential to new device according to security spec B.
617             res = PutOwnerCredential(otmCtx);
618             if(OC_STACK_OK != res)
619             {
620                 OIC_LOG(ERROR, TAG,
621                         "OwnerUuidUpdateHandler:Failed to send PUT request for onwer credential");
622                 SetResult(otmCtx, res);
623                 return OC_STACK_DELETE_TRANSACTION;
624             }
625         }
626     }
627     else
628     {
629         res = clientResponse->result;
630         OIC_LOG_V(ERROR, TAG, "OwnerUuidHandler : Unexpected result %d", res);
631         SetResult(otmCtx, res);
632     }
633
634     OIC_LOG(DEBUG, TAG, "OUT OwnerUuidUpdateHandler");
635
636 exit:
637     return  OC_STACK_DELETE_TRANSACTION;
638 }
639
640 /**
641  * Response handler for update operation mode.
642  *
643  * @param[in] ctx             ctx value passed to callback from calling function.
644  * @param[in] UNUSED          handle to an invocation
645  * @param[in] clientResponse  Response from queries to remote servers.
646  * @return  OC_STACK_DELETE_TRANSACTION to delete the transaction
647  *          and  OC_STACK_KEEP_TRANSACTION to keep it.
648  */
649 static OCStackApplicationResult OperationModeUpdateHandler(void *ctx, OCDoHandle UNUSED,
650                                 OCClientResponse *clientResponse)
651 {
652     OIC_LOG(DEBUG, TAG, "IN OperationModeUpdateHandler");
653
654     VERIFY_NON_NULL(TAG, clientResponse, WARNING);
655     VERIFY_NON_NULL(TAG, ctx, WARNING);
656
657     OTMContext_t* otmCtx = (OTMContext_t*)ctx;
658     (void) UNUSED;
659     if  (OC_STACK_OK == clientResponse->result)
660     {
661         OCStackResult res = OC_STACK_ERROR;
662         OicSecOxm_t selOxm = otmCtx->selectedDeviceInfo->doxm->oxmSel;
663         //DTLS Handshake
664         //Load secret for temporal secure session.
665         if(g_OTMDatas[selOxm].loadSecretCB)
666         {
667             res = g_OTMDatas[selOxm].loadSecretCB(otmCtx);
668             if(OC_STACK_OK != res)
669             {
670                 OIC_LOG(ERROR, TAG, "OperationModeUpdate : Failed to load secret");
671                 SetResult(otmCtx, res);
672                 return  OC_STACK_DELETE_TRANSACTION;
673             }
674         }
675
676         //It will be used in handshake event handler
677         g_otmCtx = otmCtx;
678
679         //Try DTLS handshake to generate secure session
680         if(g_OTMDatas[selOxm].createSecureSessionCB)
681         {
682             res = g_OTMDatas[selOxm].createSecureSessionCB(otmCtx);
683             if(OC_STACK_OK != res)
684             {
685                 OIC_LOG(ERROR, TAG, "OperationModeUpdate : Failed to create DTLS session");
686                 SetResult(otmCtx, res);
687                 return OC_STACK_DELETE_TRANSACTION;
688             }
689         }
690     }
691     else
692     {
693         OIC_LOG(ERROR, TAG, "Error while update operation mode");
694         SetResult(otmCtx, clientResponse->result);
695     }
696
697     OIC_LOG(DEBUG, TAG, "OUT OperationModeUpdateHandler");
698
699 exit:
700     return  OC_STACK_DELETE_TRANSACTION;
701 }
702
703 /**
704  * Response handler for update owner crendetial request.
705  *
706  * @param[in] ctx             ctx value passed to callback from calling function.
707  * @param[in] UNUSED          handle to an invocation
708  * @param[in] clientResponse  Response from queries to remote servers.
709  * @return  OC_STACK_DELETE_TRANSACTION to delete the transaction
710  *          and  OC_STACK_KEEP_TRANSACTION to keep it.
711  */
712 static OCStackApplicationResult OwnerCredentialHandler(void *ctx, OCDoHandle UNUSED,
713                                 OCClientResponse *clientResponse)
714 {
715     VERIFY_NON_NULL(TAG, clientResponse, WARNING);
716     VERIFY_NON_NULL(TAG, ctx, WARNING);
717
718     OIC_LOG(DEBUG, TAG, "IN OwnerCredentialHandler");
719     (void)UNUSED;
720     OCStackResult res = OC_STACK_OK;
721     OTMContext_t* otmCtx = (OTMContext_t*)ctx;
722
723     if(OC_STACK_RESOURCE_CREATED == clientResponse->result)
724     {
725         if(otmCtx && otmCtx->selectedDeviceInfo)
726         {
727             //Close the temporal secure session to verify the owner credential
728             CAEndpoint_t* endpoint = (CAEndpoint_t *)&otmCtx->selectedDeviceInfo->endpoint;
729             endpoint->port = otmCtx->selectedDeviceInfo->securePort;
730             CAResult_t caResult = CACloseDtlsSession(endpoint);
731             if(CA_STATUS_OK != caResult)
732             {
733                 OIC_LOG(ERROR, TAG, "Failed to close DTLS session");
734                 SetResult(otmCtx, caResult);
735                 return OC_STACK_DELETE_TRANSACTION;
736             }
737
738             /**
739              * If we select NULL cipher,
740              * client will select appropriate cipher suite according to server's cipher-suite list.
741              */
742             caResult = CASelectCipherSuite(TLS_NULL_WITH_NULL_NULL);
743             if(CA_STATUS_OK != caResult)
744             {
745                 OIC_LOG(ERROR, TAG, "Failed to select TLS_NULL_WITH_NULL_NULL");
746                 SetResult(otmCtx, caResult);
747                 return OC_STACK_DELETE_TRANSACTION;
748             }
749
750             /**
751              * in case of random PIN based OxM,
752              * revert get_psk_info callback of tinyDTLS to use owner credential.
753              */
754             if(OIC_RANDOM_DEVICE_PIN == otmCtx->selectedDeviceInfo->doxm->oxmSel)
755             {
756                 OicUuid_t emptyUuid = { .id={0}};
757                 SetUuidForRandomPinOxm(&emptyUuid);
758
759                 if(CA_STATUS_OK != CARegisterDTLSCredentialsHandler(GetDtlsPskCredentials))
760                 {
761                     OIC_LOG(ERROR, TAG, "Failed to revert DTLS credential handler.");
762                     SetResult(otmCtx, OC_STACK_INVALID_CALLBACK);
763                     return OC_STACK_DELETE_TRANSACTION;
764                 }
765             }
766
767             //PUT /oic/sec/doxm [{ ..., "owned":"TRUE" }]
768             res = PutOwnershipInformation(otmCtx);
769             if(OC_STACK_OK != res)
770             {
771                 OIC_LOG(ERROR, TAG, "Failed to put ownership information to new device");
772                 SetResult(otmCtx, res);
773                 return OC_STACK_DELETE_TRANSACTION;
774             }
775         }
776     }
777     else
778     {
779         res = clientResponse->result;
780         OIC_LOG_V(ERROR, TAG, "OwnerCredentialHandler : Unexpected result %d", res);
781         SetResult(otmCtx, res);
782     }
783
784     OIC_LOG(DEBUG, TAG, "OUT OwnerCredentialHandler");
785
786 exit:
787     return  OC_STACK_DELETE_TRANSACTION;
788 }
789
790
791 /**
792  * Response handler for update owner information request.
793  *
794  * @param[in] ctx             ctx value passed to callback from calling function.
795  * @param[in] UNUSED          handle to an invocation
796  * @param[in] clientResponse  Response from queries to remote servers.
797  * @return  OC_STACK_DELETE_TRANSACTION to delete the transaction
798  *          and  OC_STACK_KEEP_TRANSACTION to keep it.
799  */
800 static OCStackApplicationResult OwnershipInformationHandler(void *ctx, OCDoHandle UNUSED,
801                                 OCClientResponse *clientResponse)
802 {
803     VERIFY_NON_NULL(TAG, clientResponse, WARNING);
804     VERIFY_NON_NULL(TAG, ctx, WARNING);
805
806     OIC_LOG(DEBUG, TAG, "IN OwnershipInformationHandler");
807     (void)UNUSED;
808     OCStackResult res = OC_STACK_OK;
809     OTMContext_t* otmCtx = (OTMContext_t*)ctx;
810
811     if(OC_STACK_OK == clientResponse->result)
812     {
813         if(otmCtx && otmCtx->selectedDeviceInfo)
814         {
815             OIC_LOG(INFO, TAG, "Ownership transfer was successfully completed.");
816             OIC_LOG(INFO, TAG, "Start defualt ACL & commit-hash provisioning.");
817
818             res = PutProvisioningStatus(otmCtx);
819             if(OC_STACK_OK != res)
820             {
821                 OIC_LOG(ERROR, TAG, "Failed to update pstat");
822                 SetResult(otmCtx, res);
823             }
824         }
825     }
826     else
827     {
828         res = clientResponse->result;
829         OIC_LOG_V(ERROR, TAG, "OwnershipInformationHandler : Unexpected result %d", res);
830         SetResult(otmCtx, res);
831     }
832
833     OIC_LOG(DEBUG, TAG, "OUT OwnershipInformationHandler");
834
835 exit:
836     return  OC_STACK_DELETE_TRANSACTION;
837 }
838
839 /**
840  * Response handler of update provisioning status.
841  *
842  * @param[in] ctx             ctx value passed to callback from calling function.
843  * @param[in] UNUSED          handle to an invocation
844  * @param[in] clientResponse  Response from queries to remote servers.
845  * @return  OC_STACK_DELETE_TRANSACTION to delete the transaction
846  *          and OC_STACK_KEEP_TRANSACTION to keep it.
847  */
848 static OCStackApplicationResult ProvisioningStatusHandler(void *ctx, OCDoHandle UNUSED,
849                                                        OCClientResponse *clientResponse)
850 {
851     OIC_LOG_V(INFO, TAG, "IN ProvisioningStatusHandler.");
852
853     VERIFY_NON_NULL(TAG, clientResponse, ERROR);
854     VERIFY_NON_NULL(TAG, ctx, ERROR);
855
856     OTMContext_t* otmCtx = (OTMContext_t*) ctx;
857     (void)UNUSED;
858
859     if (OC_STACK_OK == clientResponse->result)
860     {
861         OCStackResult res = PDMAddDevice(&otmCtx->selectedDeviceInfo->doxm->deviceID);
862          if (OC_STACK_OK == res)
863          {
864                 OIC_LOG_V(INFO, TAG, "Add device's UUID in PDM_DB");
865                 SetResult(otmCtx, OC_STACK_OK);
866                 return OC_STACK_DELETE_TRANSACTION;
867          }
868           else
869          {
870               OIC_LOG(ERROR, TAG, "Ownership transfer is complete but adding information to DB is failed.");
871          }
872     }
873     else
874     {
875         OIC_LOG_V(INFO, TAG, "Error occured in provisionDefaultACLCB :: %d\n",
876                             clientResponse->result);
877         SetResult(otmCtx, clientResponse->result);
878     }
879
880
881 exit:
882     OIC_LOG_V(INFO, TAG, "OUT ProvisioningStatusHandler.");
883     return OC_STACK_DELETE_TRANSACTION;
884 }
885
886 static OCStackResult PutOwnerCredential(OTMContext_t* otmCtx)
887 {
888     OIC_LOG(DEBUG, TAG, "IN PutOwnerCredential");
889
890     if(!otmCtx || !otmCtx->selectedDeviceInfo)
891     {
892         OIC_LOG(ERROR, TAG, "Invalid parameters");
893         return OC_STACK_INVALID_PARAM;
894     }
895
896     OCProvisionDev_t* deviceInfo = otmCtx->selectedDeviceInfo;
897     char query[MAX_URI_LENGTH + MAX_QUERY_LENGTH] = {0};
898
899     if(!PMGenerateQuery(true,
900                         deviceInfo->endpoint.addr, deviceInfo->securePort,
901                         deviceInfo->connType,
902                         query, sizeof(query), OIC_RSRC_CRED_URI))
903     {
904         OIC_LOG(ERROR, TAG, "PutOwnerCredential : Failed to generate query");
905         return OC_STACK_ERROR;
906     }
907     OIC_LOG_V(DEBUG, TAG, "Query=%s", query);
908     OCSecurityPayload* secPayload = (OCSecurityPayload*)OICCalloc(1, sizeof(OCSecurityPayload));
909     if(!secPayload)
910     {
911         OIC_LOG(ERROR, TAG, "Failed to memory allocation");
912         return OC_STACK_NO_MEMORY;
913     }
914
915     //Generate owner credential for new device
916     secPayload->base.type = PAYLOAD_TYPE_SECURITY;
917     OicSecCred_t* ownerCredential =
918         GetCredResourceData(&(deviceInfo->doxm->deviceID));
919     if(!ownerCredential)
920     {
921         OIC_LOG(ERROR, TAG, "Can not find OwnerPSK.");
922         return OC_STACK_NO_RESOURCE;
923     }
924
925     OicUuid_t credSubjectId = {.id={0}};
926     if(OC_STACK_OK == GetDoxmDeviceID(&credSubjectId))
927     {
928         OicSecCred_t newCredential;
929         memcpy(&newCredential, ownerCredential, sizeof(OicSecCred_t));
930         newCredential.next = NULL;
931
932         //Set subject ID as PT's ID
933         memcpy(&(newCredential.subject), &credSubjectId, sizeof(OicUuid_t));
934
935         //Fill private data as empty string
936         newCredential.privateData.data = NULL;
937
938         //Send owner credential to new device : PUT /oic/sec/cred [ owner credential ]
939         secPayload->securityData = BinToCredJSON(&newCredential);
940         if (NULL == secPayload->securityData)
941         {
942             OICFree(secPayload);
943             OIC_LOG(ERROR, TAG, "Error while converting bin to json");
944             return OC_STACK_ERROR;
945         }
946         OIC_LOG_V(DEBUG, TAG, "Payload : %s", secPayload->securityData);
947
948         OCCallbackData cbData;
949         cbData.cb = &OwnerCredentialHandler;
950         cbData.context = (void *)otmCtx;
951         cbData.cd = NULL;
952         OCStackResult res = OCDoResource(NULL, OC_REST_PUT, query,
953                                          &deviceInfo->endpoint, (OCPayload*)secPayload,
954                                          deviceInfo->connType, OC_LOW_QOS, &cbData, NULL, 0);
955         if (res != OC_STACK_OK)
956         {
957             OIC_LOG(ERROR, TAG, "OCStack resource error");
958         }
959     }
960     else
961     {
962         OIC_LOG(ERROR, TAG, "Failed to read DOXM device ID.");
963         return OC_STACK_NO_RESOURCE;
964     }
965
966     OIC_LOG(DEBUG, TAG, "OUT PutOwnerCredential");
967
968     return OC_STACK_OK;
969 }
970
971 static OCStackResult PutOwnerTransferModeToResource(OTMContext_t* otmCtx)
972 {
973     OIC_LOG(DEBUG, TAG, "IN PutOwnerTransferModeToResource");
974
975     if(!otmCtx || !otmCtx->selectedDeviceInfo)
976     {
977         OIC_LOG(ERROR, TAG, "Invalid parameters");
978         return OC_STACK_INVALID_PARAM;
979     }
980
981     OCProvisionDev_t* deviceInfo = otmCtx->selectedDeviceInfo;
982     OicSecOxm_t selectedOxm = deviceInfo->doxm->oxmSel;
983     char query[MAX_URI_LENGTH + MAX_QUERY_LENGTH] = {0};
984
985     if(!PMGenerateQuery(false,
986                         deviceInfo->endpoint.addr, deviceInfo->endpoint.port,
987                         deviceInfo->connType,
988                         query, sizeof(query), OIC_RSRC_DOXM_URI))
989     {
990         OIC_LOG(ERROR, TAG, "PutOwnerTransferModeToResource : Failed to generate query");
991         return OC_STACK_ERROR;
992     }
993     OIC_LOG_V(DEBUG, TAG, "Query=%s", query);
994     OCSecurityPayload* secPayload = (OCSecurityPayload*)OICCalloc(1, sizeof(OCSecurityPayload));
995     if(!secPayload)
996     {
997         OIC_LOG(ERROR, TAG, "Failed to memory allocation");
998         return OC_STACK_NO_MEMORY;
999     }
1000     secPayload->base.type = PAYLOAD_TYPE_SECURITY;
1001     secPayload->securityData = g_OTMDatas[selectedOxm].createSelectOxmPayloadCB(otmCtx);
1002     if (NULL == secPayload->securityData)
1003     {
1004         OICFree(secPayload);
1005         OIC_LOG(ERROR, TAG, "Error while converting bin to json");
1006         return OC_STACK_ERROR;
1007     }
1008
1009     OCCallbackData cbData;
1010     cbData.cb = &OwnerTransferModeHandler;
1011     cbData.context = (void *)otmCtx;
1012     cbData.cd = NULL;
1013     OCStackResult res = OCDoResource(NULL, OC_REST_PUT, query,
1014                                      &deviceInfo->endpoint, (OCPayload*)secPayload,
1015                                      deviceInfo->connType, OC_LOW_QOS, &cbData, NULL, 0);
1016     if (res != OC_STACK_OK)
1017     {
1018         OIC_LOG(ERROR, TAG, "OCStack resource error");
1019     }
1020
1021     OIC_LOG(DEBUG, TAG, "OUT PutOwnerTransferModeToResource");
1022
1023     return res;
1024 }
1025
1026 static OCStackResult GetProvisioningStatusResource(OTMContext_t* otmCtx)
1027 {
1028     OIC_LOG(DEBUG, TAG, "IN GetProvisioningStatusResource");
1029
1030     if(!otmCtx || !otmCtx->selectedDeviceInfo)
1031     {
1032         OIC_LOG(ERROR, TAG, "Invailed parameters");
1033         return OC_STACK_INVALID_PARAM;
1034     }
1035
1036     OCProvisionDev_t* deviceInfo = otmCtx->selectedDeviceInfo;
1037     char query[MAX_URI_LENGTH + MAX_QUERY_LENGTH] = {0};
1038     if(!PMGenerateQuery(false,
1039                         deviceInfo->endpoint.addr, deviceInfo->endpoint.port,
1040                         deviceInfo->connType,
1041                         query, sizeof(query), OIC_RSRC_PSTAT_URI))
1042     {
1043         OIC_LOG(ERROR, TAG, "GetProvisioningStatusResource : Failed to generate query");
1044         return OC_STACK_ERROR;
1045     }
1046     OIC_LOG_V(DEBUG, TAG, "Query=%s", query);
1047
1048     OCCallbackData cbData;
1049     cbData.cb = &ListMethodsHandler;
1050     cbData.context = (void *)otmCtx;
1051     cbData.cd = NULL;
1052     OCStackResult res = OCDoResource(NULL, OC_REST_GET, query, NULL, NULL,
1053                                      deviceInfo->connType, OC_LOW_QOS, &cbData, NULL, 0);
1054     if (res != OC_STACK_OK)
1055     {
1056         OIC_LOG(ERROR, TAG, "OCStack resource error");
1057     }
1058
1059     OIC_LOG(DEBUG, TAG, "OUT GetProvisioningStatusResource");
1060
1061     return res;
1062 }
1063
1064 static OCStackResult PutOwnerUuid(OTMContext_t* otmCtx)
1065 {
1066     OIC_LOG(DEBUG, TAG, "IN PutOwnerUuid");
1067
1068     if(!otmCtx || !otmCtx->selectedDeviceInfo)
1069     {
1070         OIC_LOG(ERROR, TAG, "Invailed parameters");
1071         return OC_STACK_INVALID_PARAM;
1072     }
1073
1074     OCProvisionDev_t* deviceInfo = otmCtx->selectedDeviceInfo;
1075     char query[MAX_URI_LENGTH + MAX_QUERY_LENGTH] = {0};
1076     if(!PMGenerateQuery(true,
1077                         deviceInfo->endpoint.addr, deviceInfo->securePort,
1078                         deviceInfo->connType,
1079                         query, sizeof(query), OIC_RSRC_DOXM_URI))
1080     {
1081         OIC_LOG(ERROR, TAG, "PutOwnershipInformation : Failed to generate query");
1082         return OC_STACK_ERROR;
1083     }
1084     OIC_LOG_V(DEBUG, TAG, "Query=%s", query);
1085
1086     //PUT PT's uuid to new device
1087     OCSecurityPayload* secPayload = (OCSecurityPayload*)OICCalloc(1, sizeof(OCSecurityPayload));
1088     if(!secPayload)
1089     {
1090         OIC_LOG(ERROR, TAG, "Failed to memory allocation");
1091         return OC_STACK_NO_MEMORY;
1092     }
1093     secPayload->base.type = PAYLOAD_TYPE_SECURITY;
1094     secPayload->securityData =
1095         g_OTMDatas[deviceInfo->doxm->oxmSel].createOwnerTransferPayloadCB(otmCtx);
1096     if (NULL == secPayload->securityData)
1097     {
1098         OICFree(secPayload);
1099         OIC_LOG(ERROR, TAG, "Error while converting doxm bin to json");
1100         return OC_STACK_INVALID_PARAM;
1101     }
1102     OIC_LOG_V(DEBUG, TAG, "Payload : %s", secPayload->securityData);
1103
1104     OCCallbackData cbData;
1105     cbData.cb = &OwnerUuidUpdateHandler;
1106     cbData.context = (void *)otmCtx;
1107     cbData.cd = NULL;
1108
1109     OCStackResult res = OCDoResource(NULL, OC_REST_PUT, query, 0, (OCPayload*)secPayload,
1110                                      deviceInfo->connType, OC_LOW_QOS, &cbData, NULL, 0);
1111     if (res != OC_STACK_OK)
1112     {
1113         OIC_LOG(ERROR, TAG, "OCStack resource error");
1114     }
1115
1116     OIC_LOG(DEBUG, TAG, "OUT PutOwnerUuid");
1117
1118     return res;
1119 }
1120
1121 static OCStackResult PutOwnershipInformation(OTMContext_t* otmCtx)
1122 {
1123     OIC_LOG(DEBUG, TAG, "IN PutOwnershipInformation");
1124
1125     if(!otmCtx || !otmCtx->selectedDeviceInfo)
1126     {
1127         OIC_LOG(ERROR, TAG, "Invailed parameters");
1128         return OC_STACK_INVALID_PARAM;
1129     }
1130
1131     OCProvisionDev_t* deviceInfo = otmCtx->selectedDeviceInfo;
1132     char query[MAX_URI_LENGTH + MAX_QUERY_LENGTH] = {0};
1133     if(!PMGenerateQuery(true,
1134                         deviceInfo->endpoint.addr, deviceInfo->securePort,
1135                         deviceInfo->connType,
1136                         query, sizeof(query), OIC_RSRC_DOXM_URI))
1137     {
1138         OIC_LOG(ERROR, TAG, "PutOwnershipInformation : Failed to generate query");
1139         return OC_STACK_ERROR;
1140     }
1141     OIC_LOG_V(DEBUG, TAG, "Query=%s", query);
1142
1143     //OwnershipInformationHandler
1144     OCSecurityPayload* secPayload = (OCSecurityPayload*)OICCalloc(1, sizeof(OCSecurityPayload));
1145     if(!secPayload)
1146     {
1147         OIC_LOG(ERROR, TAG, "Failed to memory allocation");
1148         return OC_STACK_NO_MEMORY;
1149     }
1150
1151     otmCtx->selectedDeviceInfo->doxm->owned = true;
1152     secPayload->securityData = BinToDoxmJSON(otmCtx->selectedDeviceInfo->doxm);
1153     if (NULL == secPayload->securityData)
1154     {
1155         OICFree(secPayload);
1156         OIC_LOG(ERROR, TAG, "Error while converting doxm bin to json");
1157         return OC_STACK_INVALID_PARAM;
1158     }
1159     secPayload->base.type = PAYLOAD_TYPE_SECURITY;
1160
1161     OCCallbackData cbData;
1162     cbData.cb = &OwnershipInformationHandler;
1163     cbData.context = (void *)otmCtx;
1164     cbData.cd = NULL;
1165
1166     OCStackResult res = OCDoResource(NULL, OC_REST_PUT, query, 0, (OCPayload*)secPayload,
1167                                      deviceInfo->connType, OC_LOW_QOS, &cbData, NULL, 0);
1168     if (res != OC_STACK_OK)
1169     {
1170         OIC_LOG(ERROR, TAG, "OCStack resource error");
1171     }
1172
1173     OIC_LOG(DEBUG, TAG, "OUT PutOwnershipInformation");
1174
1175     return res;
1176 }
1177
1178 static OCStackResult PutUpdateOperationMode(OTMContext_t* otmCtx)
1179 {
1180     OIC_LOG(DEBUG, TAG, "IN PutUpdateOperationMode");
1181
1182     if(!otmCtx || !otmCtx->selectedDeviceInfo)
1183     {
1184         return OC_STACK_INVALID_PARAM;
1185     }
1186
1187     OCProvisionDev_t* deviceInfo = otmCtx->selectedDeviceInfo;
1188     char query[MAX_URI_LENGTH + MAX_QUERY_LENGTH] = {0};
1189     if(!PMGenerateQuery(false,
1190                         deviceInfo->endpoint.addr, deviceInfo->endpoint.port,
1191                         deviceInfo->connType,
1192                         query, sizeof(query), OIC_RSRC_PSTAT_URI))
1193     {
1194         OIC_LOG(ERROR, TAG, "PutUpdateOperationMode : Failed to generate query");
1195         return OC_STACK_ERROR;
1196     }
1197     OIC_LOG_V(DEBUG, TAG, "Query=%s", query);
1198
1199     OCSecurityPayload* secPayload = (OCSecurityPayload*)OICCalloc(1, sizeof(OCSecurityPayload));
1200     if(!secPayload)
1201     {
1202         OIC_LOG(ERROR, TAG, "Failed to memory allocation");
1203         return OC_STACK_NO_MEMORY;
1204     }
1205     secPayload->base.type = PAYLOAD_TYPE_SECURITY;
1206     size_t size = 0;
1207     OCStackResult res = PstatToCBORPayload(deviceInfo->pstat, &secPayload->securityData1,
1208                                            &size);
1209    if (OC_STACK_OK != res)
1210     {
1211         OCPayloadDestroy((OCPayload *)secPayload);
1212         OIC_LOG(ERROR, TAG, "Error while converting pstat to cbor.");
1213         return OC_STACK_INVALID_PARAM;
1214     }
1215
1216     OCCallbackData cbData;
1217     cbData.cb = &OperationModeUpdateHandler;
1218     cbData.context = (void *)otmCtx;
1219     cbData.cd = NULL;
1220     res = OCDoResource(NULL, OC_REST_PUT, query, 0, (OCPayload*)secPayload,
1221                        deviceInfo->connType, OC_LOW_QOS, &cbData, NULL, 0);
1222     if (res != OC_STACK_OK)
1223     {
1224         OIC_LOG(ERROR, TAG, "OCStack resource error");
1225     }
1226
1227     OIC_LOG(DEBUG, TAG, "OUT PutUpdateOperationMode");
1228
1229     return res;
1230 }
1231
1232 static OCStackResult StartOwnershipTransfer(void* ctx, OCProvisionDev_t* selectedDevice)
1233 {
1234     OIC_LOG(INFO, TAG, "IN StartOwnershipTransfer");
1235     OTMContext_t* otmCtx = (OTMContext_t*)ctx;
1236     otmCtx->selectedDeviceInfo = selectedDevice;
1237
1238     //Set to the lowest level OxM, and then find more higher level OxM.
1239     OCStackResult res = SelectProvisioningMethod(selectedDevice->doxm->oxm,
1240                                                  selectedDevice->doxm->oxmLen,
1241                                                  &selectedDevice->doxm->oxmSel);
1242     if(OC_STACK_OK != res)
1243     {
1244         OIC_LOG(ERROR, TAG, "Failed to select the provisioning method");
1245         SetResult(otmCtx, res);
1246         return res;
1247     }
1248     OIC_LOG_V(DEBUG, TAG, "Selected provisoning method = %d", selectedDevice->doxm->oxmSel);
1249
1250     //Send Req: PUT /oic/sec/doxm [{..."OxmSel" :g_OTMDatas[Index of Selected OxM].OXMString,...}]
1251     res = PutOwnerTransferModeToResource(otmCtx);
1252     if(OC_STACK_OK != res)
1253     {
1254         OIC_LOG(WARNING, TAG, "Failed to select the provisioning method");
1255         SetResult(otmCtx, res);
1256         return res;
1257     }
1258
1259     //Register DTLS event handler to catch the dtls event while handshake
1260     if(CA_STATUS_OK != CARegisterDTLSHandshakeCallback(DTLSHandshakeCB))
1261     {
1262         OIC_LOG(WARNING, TAG, "StartOwnershipTransfer : Failed to register DTLS handshake callback.");
1263     }
1264
1265     OIC_LOG(INFO, TAG, "OUT StartOwnershipTransfer");
1266
1267     return res;
1268
1269 }
1270
1271 OCStackResult OTMSetOwnershipTransferCallbackData(OicSecOxm_t oxmType, OTMCallbackData_t* data)
1272 {
1273     OIC_LOG(DEBUG, TAG, "IN OTMSetOwnerTransferCallbackData");
1274
1275     if(!data)
1276     {
1277         OIC_LOG(ERROR, TAG, "OTMSetOwnershipTransferCallbackData : Invalid parameters");
1278         return OC_STACK_INVALID_PARAM;
1279     }
1280     if(oxmType >= OIC_OXM_COUNT)
1281     {
1282         OIC_LOG(INFO, TAG, "Unknow ownership transfer method");
1283         return OC_STACK_INVALID_PARAM;
1284     }
1285
1286     g_OTMDatas[oxmType].loadSecretCB= data->loadSecretCB;
1287     g_OTMDatas[oxmType].createSecureSessionCB = data->createSecureSessionCB;
1288     g_OTMDatas[oxmType].createSelectOxmPayloadCB = data->createSelectOxmPayloadCB;
1289     g_OTMDatas[oxmType].createOwnerTransferPayloadCB = data->createOwnerTransferPayloadCB;
1290
1291     OIC_LOG(DEBUG, TAG, "OUT OTMSetOwnerTransferCallbackData");
1292
1293     return OC_STACK_OK;
1294 }
1295
1296 /**
1297  * NOTE : Unowned discovery should be done before performing OTMDoOwnershipTransfer
1298  */
1299 OCStackResult OTMDoOwnershipTransfer(void* ctx,
1300                                      OCProvisionDev_t *selectedDevicelist,
1301                                      OCProvisionResultCB resultCallback)
1302 {
1303     OIC_LOG(DEBUG, TAG, "IN OTMDoOwnershipTransfer");
1304
1305     if (NULL == selectedDevicelist)
1306     {
1307         return OC_STACK_INVALID_PARAM;
1308     }
1309     if (NULL == resultCallback)
1310     {
1311         return OC_STACK_INVALID_CALLBACK;
1312     }
1313
1314     OTMContext_t* otmCtx = (OTMContext_t*)OICCalloc(1,sizeof(OTMContext_t));
1315     if(!otmCtx)
1316     {
1317         OIC_LOG(ERROR, TAG, "Failed to create OTM Context");
1318         return OC_STACK_NO_MEMORY;
1319     }
1320     otmCtx->ctxResultCallback = resultCallback;
1321     otmCtx->ctxHasError = false;
1322     otmCtx->userCtx = ctx;
1323     OCProvisionDev_t* pCurDev = selectedDevicelist;
1324
1325     //Counting number of selected devices.
1326     otmCtx->ctxResultArraySize = 0;
1327     while(NULL != pCurDev)
1328     {
1329         otmCtx->ctxResultArraySize++;
1330         pCurDev = pCurDev->next;
1331     }
1332
1333     otmCtx->ctxResultArray =
1334         (OCProvisionResult_t*)OICCalloc(otmCtx->ctxResultArraySize, sizeof(OCProvisionResult_t));
1335     if(NULL == otmCtx->ctxResultArray)
1336     {
1337         OIC_LOG(ERROR, TAG, "OTMDoOwnershipTransfer : Failed to memory allocation");
1338         OICFree(otmCtx);
1339         return OC_STACK_NO_MEMORY;
1340     }
1341     pCurDev = selectedDevicelist;
1342
1343     OCStackResult res = OC_STACK_OK;
1344     //Fill the device UUID for result array.
1345     for(size_t devIdx = 0; devIdx < otmCtx->ctxResultArraySize; devIdx++)
1346     {
1347         //Checking duplication of Device ID.
1348         bool isDuplicate = true;
1349         res = PDMIsDuplicateDevice(&pCurDev->doxm->deviceID, &isDuplicate);
1350         if (OC_STACK_OK != res)
1351         {
1352             goto error;
1353         }
1354         if (isDuplicate)
1355         {
1356             OIC_LOG(ERROR, TAG, "OTMDoOwnershipTransfer : Device ID is duplicated");
1357             res = OC_STACK_INVALID_PARAM;
1358             goto error;
1359         }
1360         memcpy(otmCtx->ctxResultArray[devIdx].deviceId.id,
1361                pCurDev->doxm->deviceID.id,
1362                UUID_LENGTH);
1363         otmCtx->ctxResultArray[devIdx].res = OC_STACK_CONTINUE;
1364         pCurDev = pCurDev->next;
1365     }
1366
1367     StartOwnershipTransfer(otmCtx, selectedDevicelist);
1368
1369     OIC_LOG(DEBUG, TAG, "OUT OTMDoOwnershipTransfer");
1370     return OC_STACK_OK;
1371
1372 error:
1373     OICFree(otmCtx->ctxResultArray);
1374     OICFree(otmCtx);
1375     return res;
1376 }
1377
1378 OCStackResult PutProvisioningStatus(OTMContext_t* otmCtx)
1379 {
1380     OIC_LOG(INFO, TAG, "IN PutProvisioningStatus");
1381
1382     if(!otmCtx)
1383     {
1384         OIC_LOG(ERROR, TAG, "OTMContext is NULL");
1385         return OC_STACK_INVALID_PARAM;
1386     }
1387     if(!otmCtx->selectedDeviceInfo)
1388     {
1389         OIC_LOG(ERROR, TAG, "Can't find device information in OTMContext");
1390         OICFree(otmCtx);
1391         return OC_STACK_INVALID_PARAM;
1392     }
1393
1394     otmCtx->selectedDeviceInfo->pstat->tm = NORMAL;
1395     otmCtx->selectedDeviceInfo->pstat->cm = PROVISION_ACLS | PROVISION_CREDENTIALS |
1396                                             SECURITY_MANAGEMENT_SERVICES | BOOTSTRAP_SERVICE;
1397     OCSecurityPayload* secPayload = (OCSecurityPayload*)OICCalloc(1, sizeof(OCSecurityPayload));
1398     if(!secPayload)
1399     {
1400         OIC_LOG(ERROR, TAG, "Failed to memory allocation");
1401         return OC_STACK_NO_MEMORY;
1402     }
1403     secPayload->base.type = PAYLOAD_TYPE_SECURITY;
1404     size_t size = 0;
1405     if (OC_STACK_OK != PstatToCBORPayload(otmCtx->selectedDeviceInfo->pstat,
1406             &secPayload->securityData1, &size))
1407     {
1408         OCPayloadDestroy((OCPayload *)secPayload);
1409         SetResult(otmCtx, OC_STACK_INVALID_JSON);
1410         return OC_STACK_INVALID_JSON;
1411     }
1412     OIC_LOG_V(INFO, TAG, "Created payload for commit hash: %s",secPayload->securityData1);
1413
1414     char query[MAX_URI_LENGTH + MAX_QUERY_LENGTH] = {0};
1415     if(!PMGenerateQuery(true,
1416                         otmCtx->selectedDeviceInfo->endpoint.addr,
1417                         otmCtx->selectedDeviceInfo->securePort,
1418                         otmCtx->selectedDeviceInfo->connType,
1419                         query, sizeof(query), OIC_RSRC_PSTAT_URI))
1420     {
1421         OIC_LOG(ERROR, TAG, "PutProvisioningStatus : Failed to generate query");
1422         return OC_STACK_ERROR;
1423     }
1424     OIC_LOG_V(DEBUG, TAG, "Query=%s", query);
1425
1426     OCCallbackData cbData = {.context=NULL, .cb=NULL, .cd=NULL};
1427     cbData.cb = &ProvisioningStatusHandler;
1428     cbData.context = (void*)otmCtx;
1429     cbData.cd = NULL;
1430     OCStackResult ret = OCDoResource(NULL, OC_REST_PUT, query, 0, (OCPayload*)secPayload,
1431             otmCtx->selectedDeviceInfo->connType, OC_HIGH_QOS, &cbData, NULL, 0);
1432     OIC_LOG_V(INFO, TAG, "OCDoResource returned: %d",ret);
1433     if (ret != OC_STACK_OK)
1434     {
1435         OIC_LOG(ERROR, TAG, "OCStack resource error");
1436         SetResult(otmCtx, ret);
1437     }
1438
1439     OIC_LOG(INFO, TAG, "OUT PutProvisioningStatus");
1440
1441     return ret;
1442 }