Svace Defects Fixes.
[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  * Variables for pointing the OTMContext to be used in the DTLS handshake result callback.
73  */
74 static OTMContext_t* g_otmCtx = NULL;
75
76 /**
77  * Function to select appropriate  provisioning method.
78  *
79  * @param[in] supportedMethods   Array of supported methods
80  * @param[in] numberOfMethods   number of supported methods
81  * @param[out]  selectedMethod         Selected methods
82  * @return  OC_STACK_OK on success
83  */
84 static OCStackResult SelectProvisioningMethod(const OicSecOxm_t *supportedMethods,
85         size_t numberOfMethods, OicSecOxm_t *selectedMethod)
86 {
87     OIC_LOG(DEBUG, TAG, "IN SelectProvisioningMethod");
88
89     if(numberOfMethods == 0 || !supportedMethods)
90     {
91         OIC_LOG(WARNING, TAG, "Could not find a supported OxM.");
92         return OC_STACK_ERROR;
93     }
94
95     *selectedMethod  = supportedMethods[0];
96     for(size_t i = 0; i < numberOfMethods; i++)
97     {
98         if(*selectedMethod < supportedMethods[i])
99         {
100             *selectedMethod =  supportedMethods[i];
101         }
102     }
103
104     return OC_STACK_OK;
105 }
106
107 /**
108  * Function to select operation mode.This function will return most secure common operation mode.
109  *
110  * @param[in] selectedDeviceInfo   selected device information to performing provisioning.
111  * @param[out]   selectedMode   selected operation mode
112  * @return  OC_STACK_OK on success
113  */
114 static void SelectOperationMode(const OCProvisionDev_t *selectedDeviceInfo,
115                                 OicSecDpom_t *selectedMode)
116 {
117     OIC_LOG(DEBUG, TAG, "IN SelectOperationMode");
118     *selectedMode = selectedDeviceInfo->pstat->sm[0];
119     OIC_LOG_V(DEBUG, TAG, "Selected Operation Mode = %d", *selectedMode);
120 }
121
122 /**
123  * Function to start ownership transfer.
124  * This function will send the first request for provisioning,
125  * The next request message is sent from the response handler for this request.
126  *
127  * @param[in] ctx   context value passed to callback from calling function.
128  * @param[in] selectedDevice   selected device information to performing provisioning.
129  * @return  OC_STACK_OK on success
130  */
131 static OCStackResult StartOwnershipTransfer(void* ctx, OCProvisionDev_t* selectedDevice);
132
133 /**
134  * Function to update owner transfer mode
135  *
136  * @param[in]  otmCtx  Context value of ownership transfer.
137  * @return  OC_STACK_OK on success
138  */
139 static OCStackResult PostOwnerTransferModeToResource(OTMContext_t* otmCtx);
140
141 /**
142  * Function to send request to resource to get its pstat resource information.
143  *
144  * @param[in]  otmCtx  Context value of ownership transfer.
145  * @return  OC_STACK_OK on success
146  */
147 static OCStackResult GetProvisioningStatusResource(OTMContext_t* otmCtx);
148
149
150 /**
151  * Function to send  uuid of owner device to new device.
152  * This function would update 'owner of doxm' as UUID for provisioning tool.
153  *
154  * @param[in]  otmCtx  Context value of ownership transfer.
155  * @return  OC_STACK_OK on success
156  */
157 static OCStackResult PostOwnerUuid(OTMContext_t* otmCtx);
158
159 /**
160  * Function to update the operation mode. As per the spec. Operation mode in client driven
161  * single service provisioning it will be updated to 0x3
162  *
163  * @param[in]  otmCtx  Context value of ownership transfer.
164  * @return  OC_STACK_OK on success
165  */
166 static OCStackResult PostUpdateOperationMode(OTMContext_t* otmCtx);
167
168 /**
169  * Function to update the owner credential to new device
170  *
171  * @param[in]  otmCtx  Context value of ownership transfer.
172  * @param[in] selectedOperationMode selected operation mode
173  * @return  OC_STACK_OK on success
174  */
175 static OCStackResult PutOwnerCredential(OTMContext_t* otmCtx);
176
177 /**
178  * Function to send ownerShip info.
179  * This function would update 'owned of doxm' as true.
180  *
181  * @param[in]  otmCtx  Context value of ownership transfer.
182  * @return  OC_STACK_OK on success
183  */
184 static OCStackResult PostOwnershipInformation(OTMContext_t* otmCtx);
185
186 /**
187  * Function to update pstat as Ready for provisioning.
188  * This function would update 'cm' from bx0000,0010 to bx0000,0000.
189  *
190  * @param[in] ctx   context value passed to callback from calling function.
191  * @param[in] selectedDevice   selected device information to performing provisioning.
192  * @return  OC_STACK_OK on success
193  */
194 static OCStackResult PostProvisioningStatus(OTMContext_t* otmCtx);
195
196 /**
197  * Function to update pstat as Ready for Normal Operation.
198  * This function would update 'isop' from false to true.
199  *
200  * @param[in] ctx   context value passed to callback from calling function.
201  * @param[in] selectedDevice   selected device information to performing provisioning.
202  * @return  OC_STACK_OK on success
203  */
204 static OCStackResult PostNormalOperationStatus(OTMContext_t* otmCtx);
205
206 static bool IsComplete(OTMContext_t* otmCtx)
207 {
208     for(size_t i = 0; i < otmCtx->ctxResultArraySize; i++)
209     {
210         if(OC_STACK_CONTINUE == otmCtx->ctxResultArray[i].res)
211         {
212             return false;
213         }
214     }
215
216     return true;
217 }
218
219 /**
220  * Function to save the result of provisioning.
221  *
222  * @param[in,out] otmCtx   Context value of ownership transfer.
223  * @param[in] res   result of provisioning
224  */
225 static void SetResult(OTMContext_t* otmCtx, const OCStackResult res)
226 {
227     OIC_LOG_V(DEBUG, TAG, "IN SetResult : %d ", res);
228
229     if(!otmCtx)
230     {
231         OIC_LOG(WARNING, TAG, "OTMContext is NULL");
232         return;
233     }
234
235     if(otmCtx->selectedDeviceInfo)
236     {
237         //Revert psk_info callback and new deivce uuid in case of random PIN OxM
238         if(OIC_RANDOM_DEVICE_PIN == otmCtx->selectedDeviceInfo->doxm->oxmSel)
239         {
240             if(CA_STATUS_OK != CARegisterDTLSCredentialsHandler(GetDtlsPskCredentials))
241             {
242                 OIC_LOG(WARNING, TAG, "Failed to revert  is DTLS credential handler.");
243             }
244             OicUuid_t emptyUuid = { .id={0}};
245             SetUuidForRandomPinOxm(&emptyUuid);
246         }
247
248         for(size_t i = 0; i < otmCtx->ctxResultArraySize; i++)
249         {
250             if(memcmp(otmCtx->selectedDeviceInfo->doxm->deviceID.id,
251                       otmCtx->ctxResultArray[i].deviceId.id, UUID_LENGTH) == 0)
252             {
253                 otmCtx->ctxResultArray[i].res = res;
254                 if(OC_STACK_OK != res)
255                 {
256                     otmCtx->ctxHasError = true;
257                 }
258             }
259         }
260
261         g_otmCtx = NULL;
262
263         //If all request is completed, invoke the user callback.
264         if(IsComplete(otmCtx))
265         {
266             otmCtx->ctxResultCallback(otmCtx->userCtx, otmCtx->ctxResultArraySize,
267                                        otmCtx->ctxResultArray, otmCtx->ctxHasError);
268             OICFree(otmCtx->ctxResultArray);
269             OICFree(otmCtx);
270         }
271         else
272         {
273             if(OC_STACK_OK != StartOwnershipTransfer(otmCtx,
274                                                      otmCtx->selectedDeviceInfo->next))
275             {
276                 OIC_LOG(ERROR, TAG, "Failed to StartOwnershipTransfer");
277             }
278         }
279     }
280
281     OIC_LOG(DEBUG, TAG, "OUT SetResult");
282 }
283
284 /**
285  * Function to handle the handshake result in OTM.
286  * This function will be invoked after DTLS handshake
287  * @param   endPoint  [IN] The remote endpoint.
288  * @param   errorInfo [IN] Error information from the endpoint.
289  * @return  NONE
290  */
291 void DTLSHandshakeCB(const CAEndpoint_t *endpoint, const CAErrorInfo_t *info)
292 {
293     if(NULL != g_otmCtx && NULL != g_otmCtx->selectedDeviceInfo &&
294        NULL != endpoint && NULL != info)
295     {
296         OIC_LOG_V(INFO, TAG, "Received status from remote device(%s:%d) : %d",
297                  endpoint->addr, endpoint->port, info->result);
298
299         OicSecDoxm_t* newDevDoxm = g_otmCtx->selectedDeviceInfo->doxm;
300
301         if(NULL != newDevDoxm)
302         {
303             OicUuid_t emptyUuid = {.id={0}};
304
305             //Make sure the address matches.
306             if(strncmp(g_otmCtx->selectedDeviceInfo->endpoint.addr,
307                endpoint->addr,
308                sizeof(endpoint->addr)) == 0 &&
309                g_otmCtx->selectedDeviceInfo->securePort == endpoint->port)
310             {
311                 OCStackResult res = OC_STACK_ERROR;
312
313                 //If temporal secure sesstion established successfully
314                 if(CA_STATUS_OK == info->result &&
315                    false == newDevDoxm->owned &&
316                    memcmp(&(newDevDoxm->owner), &emptyUuid, sizeof(OicUuid_t)) == 0)
317                 {
318                     //Send request : POST /oic/sec/doxm [{... , "devowner":"PT's UUID"}]
319                     res = PostOwnerUuid(g_otmCtx);
320                     if(OC_STACK_OK != res)
321                     {
322                         OIC_LOG(ERROR, TAG, "OperationModeUpdate : Failed to send owner information");
323                         SetResult(g_otmCtx, res);
324                     }
325                 }
326                 //In case of authentication failure
327                 else if(CA_DTLS_AUTHENTICATION_FAILURE == info->result)
328                 {
329                     //in case of error from owner credential
330                     if(memcmp(&(newDevDoxm->owner), &emptyUuid, sizeof(OicUuid_t)) != 0 &&
331                         true == newDevDoxm->owned)
332                     {
333                         OIC_LOG(ERROR, TAG, "The owner credential may incorrect.");
334
335                         if(OC_STACK_OK != RemoveCredential(&(newDevDoxm->deviceID)))
336                         {
337                             OIC_LOG(WARNING, TAG, "Failed to remove the invaild owner credential");
338                         }
339                         SetResult(g_otmCtx, OC_STACK_AUTHENTICATION_FAILURE);
340                     }
341                     //in case of error from wrong PIN, re-start the ownership transfer
342                     else if(OIC_RANDOM_DEVICE_PIN == newDevDoxm->oxmSel)
343                     {
344                         OIC_LOG(ERROR, TAG, "The PIN number may incorrect.");
345
346                         memcpy(&(newDevDoxm->owner), &emptyUuid, sizeof(OicUuid_t));
347                         newDevDoxm->owned = false;
348                         g_otmCtx->attemptCnt++;
349
350                         if(WRONG_PIN_MAX_ATTEMP > g_otmCtx->attemptCnt)
351                         {
352                             res = StartOwnershipTransfer(g_otmCtx, g_otmCtx->selectedDeviceInfo);
353                             if(OC_STACK_OK != res)
354                             {
355                                 SetResult(g_otmCtx, res);
356                                 OIC_LOG(ERROR, TAG, "Failed to Re-StartOwnershipTransfer");
357                             }
358                         }
359                         else
360                         {
361                             OIC_LOG(ERROR, TAG, "User has exceeded the number of authentication attempts.");
362                             SetResult(g_otmCtx, OC_STACK_AUTHENTICATION_FAILURE);
363                         }
364                     }
365                     else
366                     {
367                         OIC_LOG(ERROR, TAG, "Failed to establish secure session.");
368                         SetResult(g_otmCtx, OC_STACK_AUTHENTICATION_FAILURE);
369                     }
370                 }
371             }
372         }
373     }
374 }
375
376 /**
377  * Function to save ownerPSK at provisioning tool end.
378  *
379  * @param[in] selectedDeviceInfo   selected device information to performing provisioning.
380  * @return  OC_STACK_OK on success
381  */
382 static OCStackResult SaveOwnerPSK(OCProvisionDev_t *selectedDeviceInfo)
383 {
384     OIC_LOG(DEBUG, TAG, "IN SaveOwnerPSK");
385
386     OCStackResult res = OC_STACK_ERROR;
387
388     CAEndpoint_t endpoint;
389     memset(&endpoint, 0x00, sizeof(CAEndpoint_t));
390     OICStrcpy(endpoint.addr, MAX_ADDR_STR_SIZE_CA, selectedDeviceInfo->endpoint.addr);
391     endpoint.addr[MAX_ADDR_STR_SIZE_CA - 1] = '\0';
392     endpoint.port = selectedDeviceInfo->securePort;
393
394     OicUuid_t ptDeviceID = {.id={0}};
395     if (OC_STACK_OK != GetDoxmDeviceID(&ptDeviceID))
396     {
397         OIC_LOG(ERROR, TAG, "Error while retrieving provisioning tool's device ID");
398         return res;
399     }
400
401     uint8_t ownerPSK[OWNER_PSK_LENGTH_128] = {0};
402     OicSecKey_t ownerKey = {ownerPSK, OWNER_PSK_LENGTH_128};
403
404     //Generating OwnerPSK
405     CAResult_t pskRet = CAGenerateOwnerPSK(&endpoint,
406             (uint8_t *)GetOxmString(selectedDeviceInfo->doxm->oxmSel),
407             strlen(GetOxmString(selectedDeviceInfo->doxm->oxmSel)),
408             ptDeviceID.id, sizeof(ptDeviceID.id),
409             selectedDeviceInfo->doxm->deviceID.id, sizeof(selectedDeviceInfo->doxm->deviceID.id),
410             ownerPSK, OWNER_PSK_LENGTH_128);
411
412     if (CA_STATUS_OK == pskRet)
413     {
414         OIC_LOG(INFO, TAG,"ownerPSK dump:\n");
415         OIC_LOG_BUFFER(INFO, TAG,ownerPSK, OWNER_PSK_LENGTH_128);
416         //Generating new credential for provisioning tool
417         OicSecCred_t *cred = GenerateCredential(&selectedDeviceInfo->doxm->deviceID,
418                 SYMMETRIC_PAIR_WISE_KEY, NULL,
419                 &ownerKey, &ptDeviceID);
420         VERIFY_NON_NULL(TAG, cred, ERROR);
421
422         // TODO: Added as workaround. Will be replaced soon.
423         cred->privateData.encoding = OIC_ENCODING_RAW;
424
425 #if 1
426         // NOTE: Test codes to use BASE64 encoded owner PSK.
427         uint32_t outSize = 0;
428         size_t b64BufSize = B64ENCODE_OUT_SAFESIZE((OWNER_PSK_LENGTH_128 + 1));
429         char* b64Buf = (uint8_t *)OICCalloc(1, b64BufSize);
430         VERIFY_NON_NULL(TAG, b64Buf, ERROR);
431         b64Encode(cred->privateData.data, cred->privateData.len, b64Buf, b64BufSize, &outSize);
432
433         OICFree( cred->privateData.data );
434         cred->privateData.data = (uint8_t *)OICCalloc(1, outSize + 1);
435         VERIFY_NON_NULL(TAG, cred->privateData.data, ERROR);
436
437         strncpy(cred->privateData.data, b64Buf, outSize);
438         cred->privateData.data[outSize] = '\0';
439         cred->privateData.encoding = OIC_ENCODING_BASE64;
440         cred->privateData.len = outSize;
441         OICFree(b64Buf);
442 #endif //End of Test codes
443
444         res = AddCredential(cred);
445         if(res != OC_STACK_OK)
446         {
447             DeleteCredList(cred);
448             return res;
449         }
450     }
451     else
452     {
453         OIC_LOG(ERROR, TAG, "CAGenerateOwnerPSK failed");
454     }
455
456     OIC_LOG(DEBUG, TAG, "OUT SaveOwnerPSK");
457 exit:
458     return res;
459 }
460
461 /**
462  * Callback handler for OwnerShipTransferModeHandler API.
463  *
464  * @param[in] ctx             ctx value passed to callback from calling function.
465  * @param[in] UNUSED          handle to an invocation
466  * @param[in] clientResponse  Response from queries to remote servers.
467  * @return  OC_STACK_DELETE_TRANSACTION to delete the transaction
468  *          and  OC_STACK_KEEP_TRANSACTION to keep it.
469  */
470 static OCStackApplicationResult OwnerTransferModeHandler(void *ctx, OCDoHandle UNUSED,
471                                                          OCClientResponse *clientResponse)
472 {
473     OIC_LOG(DEBUG, TAG, "IN OwnerTransferModeHandler");
474
475     VERIFY_NON_NULL(TAG, clientResponse, WARNING);
476     VERIFY_NON_NULL(TAG, ctx, WARNING);
477
478     OTMContext_t* otmCtx = (OTMContext_t*)ctx;
479     (void)UNUSED;
480     if(clientResponse->result == OC_STACK_OK)
481     {
482         OIC_LOG(INFO, TAG, "OwnerTransferModeHandler : response result = OC_STACK_OK");
483         //Send request : GET /oic/sec/pstat
484         OCStackResult res = GetProvisioningStatusResource(otmCtx);
485         if(OC_STACK_OK != res)
486         {
487             OIC_LOG(WARNING, TAG, "Failed to get pstat information");
488             SetResult(otmCtx, res);
489         }
490     }
491     else
492     {
493         OIC_LOG_V(WARNING, TAG, "OwnerTransferModeHandler : Client response is incorrect : %d",
494         clientResponse->result);
495         SetResult(otmCtx, clientResponse->result);
496     }
497
498     OIC_LOG(DEBUG, TAG, "OUT OwnerTransferModeHandler");
499
500 exit:
501     return  OC_STACK_DELETE_TRANSACTION;
502 }
503
504 /**
505  * Callback handler for ProvisioningStatusResouceHandler API.
506  *
507  * @param[in] ctx             ctx value passed to callback from calling function.
508  * @param[in] UNUSED          handle to an invocation
509  * @param[in] clientResponse  Response from queries to remote servers.
510  * @return  OC_STACK_DELETE_TRANSACTION to delete the transaction
511  *          and  OC_STACK_KEEP_TRANSACTION to keep it.
512  */
513 static OCStackApplicationResult ListMethodsHandler(void *ctx, OCDoHandle UNUSED,
514                                                     OCClientResponse *clientResponse)
515 {
516     OIC_LOG(DEBUG, TAG, "IN ListMethodsHandler");
517
518     VERIFY_NON_NULL(TAG, clientResponse, WARNING);
519     VERIFY_NON_NULL(TAG, ctx, WARNING);
520
521     OTMContext_t* otmCtx = (OTMContext_t*)ctx;
522     (void)UNUSED;
523     if  (OC_STACK_OK == clientResponse->result)
524     {
525         if  (NULL == clientResponse->payload)
526         {
527             OIC_LOG(INFO, TAG, "Skiping Null payload");
528             SetResult(otmCtx, OC_STACK_ERROR);
529             return OC_STACK_DELETE_TRANSACTION;
530         }
531
532         if (PAYLOAD_TYPE_SECURITY != clientResponse->payload->type)
533         {
534             OIC_LOG(INFO, TAG, "Unknown payload type");
535             SetResult(otmCtx, OC_STACK_ERROR);
536             return OC_STACK_DELETE_TRANSACTION;
537         }
538         OicSecPstat_t* pstat = NULL;
539         OCStackResult result = CBORPayloadToPstat(
540                 ((OCSecurityPayload*)clientResponse->payload)->securityData,
541                 ((OCSecurityPayload*)clientResponse->payload)->payloadSize,
542                 &pstat);
543         if(NULL == pstat || result != OC_STACK_OK)
544         {
545             OIC_LOG(ERROR, TAG, "Error while converting cbor to pstat.");
546             SetResult(otmCtx, OC_STACK_ERROR);
547             return OC_STACK_DELETE_TRANSACTION;
548         }
549         if(false == (TAKE_OWNER & pstat->cm))
550         {
551             OIC_LOG(ERROR, TAG, "Device pairing mode enabling owner transfer operations is disabled");
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 : POST /oic/sec/pstat [{"om":"bx11", .. }]
561         OCStackResult res = PostUpdateOperationMode(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             //POST /oic/sec/doxm [{ ..., "owned":"TRUE" }]
764             res = PostOwnershipInformation(otmCtx);
765             if(OC_STACK_OK != res)
766             {
767                 OIC_LOG(ERROR, TAG, "Failed to post 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, "Set Ready for provisioning state .");
813
814             res = PostProvisioningStatus(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     OCStackResult res = OC_STACK_OK;
855
856     if(OC_STACK_OK == clientResponse->result)
857     {
858         if(otmCtx && otmCtx->selectedDeviceInfo)
859         {
860             OIC_LOG(INFO, TAG, "Device state is in Ready for Provisionig.");
861
862             res = PostNormalOperationStatus(otmCtx);
863             if(OC_STACK_OK != res)
864             {
865                 OIC_LOG(ERROR, TAG, "Failed to update pstat");
866                 SetResult(otmCtx, res);
867             }
868         }
869     }
870     else
871     {
872         OIC_LOG_V(INFO, TAG, "Error occured in provisionDefaultACLCB :: %d\n",
873                             clientResponse->result);
874         SetResult(otmCtx, clientResponse->result);
875     }
876
877 exit:
878     OIC_LOG_V(INFO, TAG, "OUT ProvisioningStatusHandler.");
879     return OC_STACK_DELETE_TRANSACTION;
880 }
881
882 /**
883  * Response handler of update provisioning status to Ready for Normal..
884  *
885  * @param[in] ctx             ctx value passed to callback from calling function.
886  * @param[in] UNUSED          handle to an invocation
887  * @param[in] clientResponse  Response from queries to remote servers.
888  * @return  OC_STACK_DELETE_TRANSACTION to delete the transaction
889  *          and OC_STACK_KEEP_TRANSACTION to keep it.
890  */
891 static OCStackApplicationResult ReadyForNomalStatusHandler(void *ctx, OCDoHandle UNUSED,
892                                                        OCClientResponse *clientResponse)
893 {
894     OIC_LOG_V(INFO, TAG, "IN ReadyForNomalStatusHandler.");
895
896     VERIFY_NON_NULL(TAG, clientResponse, ERROR);
897     VERIFY_NON_NULL(TAG, ctx, ERROR);
898
899     OTMContext_t* otmCtx = (OTMContext_t*) ctx;
900     (void)UNUSED;
901
902     if (OC_STACK_OK == clientResponse->result)
903     {
904         OIC_LOG(INFO, TAG, "Device state is in Ready for Normal Operation.");
905         OCStackResult res = PDMAddDevice(&otmCtx->selectedDeviceInfo->doxm->deviceID);
906          if (OC_STACK_OK == res)
907          {
908                 OIC_LOG_V(INFO, TAG, "Add device's UUID in PDM_DB");
909                 SetResult(otmCtx, OC_STACK_OK);
910                 return OC_STACK_DELETE_TRANSACTION;
911          }
912           else
913          {
914               OIC_LOG(ERROR, TAG, "Ownership transfer is complete but adding information to DB is failed.");
915          }
916     }
917     else
918     {
919         OIC_LOG_V(INFO, TAG, "Error occured in provisionDefaultACLCB :: %d\n",
920                             clientResponse->result);
921         SetResult(otmCtx, clientResponse->result);
922     }
923
924 exit:
925     OIC_LOG_V(INFO, TAG, "OUT ReadyForNomalStatusHandler.");
926     return OC_STACK_DELETE_TRANSACTION;
927 }
928
929 static OCStackResult PutOwnerCredential(OTMContext_t* otmCtx)
930 {
931     OIC_LOG(DEBUG, TAG, "IN PutOwnerCredential");
932
933     if(!otmCtx || !otmCtx->selectedDeviceInfo)
934     {
935         OIC_LOG(ERROR, TAG, "Invalid parameters");
936         return OC_STACK_INVALID_PARAM;
937     }
938
939     OCProvisionDev_t* deviceInfo = otmCtx->selectedDeviceInfo;
940     char query[MAX_URI_LENGTH + MAX_QUERY_LENGTH] = {0};
941
942     if(!PMGenerateQuery(true,
943                         deviceInfo->endpoint.addr, deviceInfo->securePort,
944                         deviceInfo->connType,
945                         query, sizeof(query), OIC_RSRC_CRED_URI))
946     {
947         OIC_LOG(ERROR, TAG, "PutOwnerCredential : Failed to generate query");
948         return OC_STACK_ERROR;
949     }
950     OIC_LOG_V(DEBUG, TAG, "Query=%s", query);
951     OCSecurityPayload* secPayload = (OCSecurityPayload*)OICCalloc(1, sizeof(OCSecurityPayload));
952     if(!secPayload)
953     {
954         OIC_LOG(ERROR, TAG, "Failed to memory allocation");
955         return OC_STACK_NO_MEMORY;
956     }
957
958     //Generate owner credential for new device
959     secPayload->base.type = PAYLOAD_TYPE_SECURITY;
960     const OicSecCred_t* ownerCredential = GetCredResourceData(&(deviceInfo->doxm->deviceID));
961     if(!ownerCredential)
962     {
963         OIC_LOG(ERROR, TAG, "Can not find OwnerPSK.");
964         return OC_STACK_NO_RESOURCE;
965     }
966
967     OicUuid_t credSubjectId = {.id={0}};
968     if(OC_STACK_OK == GetDoxmDeviceID(&credSubjectId))
969     {
970         OicSecCred_t newCredential;
971         memcpy(&newCredential, ownerCredential, sizeof(OicSecCred_t));
972         newCredential.next = NULL;
973
974         //Set subject ID as PT's ID
975         memcpy(&(newCredential.subject), &credSubjectId, sizeof(OicUuid_t));
976
977         //Fill private data as empty string
978         newCredential.privateData.data = "";
979         newCredential.privateData.len = 0;
980         newCredential.privateData.encoding = ownerCredential->privateData.encoding;
981 #ifdef __WITH_X509__
982         newCredential.publicData.data = NULL;
983         newCredential.publicData.len = 0;
984 #endif
985         int secureFlag = 0;
986         //Send owner credential to new device : PUT /oic/sec/cred [ owner credential ]
987         if (OC_STACK_OK != CredToCBORPayload(&newCredential, &secPayload->securityData,
988                                         &secPayload->payloadSize, secureFlag))
989         {
990             OICFree(secPayload);
991             OIC_LOG(ERROR, TAG, "Error while converting bin to cbor.");
992             return OC_STACK_ERROR;
993         }
994         OIC_LOG(DEBUG, TAG, "Cred Payload:");
995         OIC_LOG_BUFFER(DEBUG, TAG, secPayload->securityData, secPayload->payloadSize);
996
997         OCCallbackData cbData;
998         cbData.cb = &OwnerCredentialHandler;
999         cbData.context = (void *)otmCtx;
1000         cbData.cd = NULL;
1001         OCStackResult res = OCDoResource(NULL, OC_REST_PUT, query,
1002                                          &deviceInfo->endpoint, (OCPayload*)secPayload,
1003                                          deviceInfo->connType, OC_HIGH_QOS, &cbData, NULL, 0);
1004         if (res != OC_STACK_OK)
1005         {
1006             OIC_LOG(ERROR, TAG, "OCStack resource error");
1007         }
1008     }
1009     else
1010     {
1011         OIC_LOG(ERROR, TAG, "Failed to read DOXM device ID.");
1012         return OC_STACK_NO_RESOURCE;
1013     }
1014
1015     OIC_LOG(DEBUG, TAG, "OUT PutOwnerCredential");
1016
1017     return OC_STACK_OK;
1018 }
1019
1020 static OCStackResult PostOwnerTransferModeToResource(OTMContext_t* otmCtx)
1021 {
1022     OIC_LOG(DEBUG, TAG, "IN PostOwnerTransferModeToResource");
1023
1024     if(!otmCtx || !otmCtx->selectedDeviceInfo)
1025     {
1026         OIC_LOG(ERROR, TAG, "Invalid parameters");
1027         return OC_STACK_INVALID_PARAM;
1028     }
1029
1030     OCProvisionDev_t* deviceInfo = otmCtx->selectedDeviceInfo;
1031     OicSecOxm_t selectedOxm = deviceInfo->doxm->oxmSel;
1032     char query[MAX_URI_LENGTH + MAX_QUERY_LENGTH] = {0};
1033
1034     if(!PMGenerateQuery(false,
1035                         deviceInfo->endpoint.addr, deviceInfo->endpoint.port,
1036                         deviceInfo->connType,
1037                         query, sizeof(query), OIC_RSRC_DOXM_URI))
1038     {
1039         OIC_LOG(ERROR, TAG, "PostOwnerTransferModeToResource : Failed to generate query");
1040         return OC_STACK_ERROR;
1041     }
1042     OIC_LOG_V(DEBUG, TAG, "Query=%s", query);
1043     OCSecurityPayload* secPayload = (OCSecurityPayload*)OICCalloc(1, sizeof(OCSecurityPayload));
1044     if(!secPayload)
1045     {
1046         OIC_LOG(ERROR, TAG, "Failed to memory allocation");
1047         return OC_STACK_NO_MEMORY;
1048     }
1049     secPayload->base.type = PAYLOAD_TYPE_SECURITY;
1050     OCStackResult res = g_OTMDatas[selectedOxm].createSelectOxmPayloadCB(otmCtx,
1051             &secPayload->securityData, &secPayload->payloadSize);
1052     if (OC_STACK_OK != res && NULL == secPayload->securityData)
1053     {
1054         OCPayloadDestroy((OCPayload *)secPayload);
1055         OIC_LOG(ERROR, TAG, "Error while converting bin to cbor");
1056         return OC_STACK_ERROR;
1057     }
1058
1059     OCCallbackData cbData;
1060     cbData.cb = &OwnerTransferModeHandler;
1061     cbData.context = (void *)otmCtx;
1062     cbData.cd = NULL;
1063     res = OCDoResource(NULL, OC_REST_POST, query,
1064                        &deviceInfo->endpoint, (OCPayload *)secPayload,
1065                        deviceInfo->connType, OC_HIGH_QOS, &cbData, NULL, 0);
1066     if (res != OC_STACK_OK)
1067     {
1068         OIC_LOG(ERROR, TAG, "OCStack resource error");
1069     }
1070
1071     OIC_LOG(DEBUG, TAG, "OUT PostOwnerTransferModeToResource");
1072
1073     return res;
1074 }
1075
1076 static OCStackResult GetProvisioningStatusResource(OTMContext_t* otmCtx)
1077 {
1078     OIC_LOG(DEBUG, TAG, "IN GetProvisioningStatusResource");
1079
1080     if(!otmCtx || !otmCtx->selectedDeviceInfo)
1081     {
1082         OIC_LOG(ERROR, TAG, "Invailed parameters");
1083         return OC_STACK_INVALID_PARAM;
1084     }
1085
1086     OCProvisionDev_t* deviceInfo = otmCtx->selectedDeviceInfo;
1087     char query[MAX_URI_LENGTH + MAX_QUERY_LENGTH] = {0};
1088     if(!PMGenerateQuery(false,
1089                         deviceInfo->endpoint.addr, deviceInfo->endpoint.port,
1090                         deviceInfo->connType,
1091                         query, sizeof(query), OIC_RSRC_PSTAT_URI))
1092     {
1093         OIC_LOG(ERROR, TAG, "GetProvisioningStatusResource : Failed to generate query");
1094         return OC_STACK_ERROR;
1095     }
1096     OIC_LOG_V(DEBUG, TAG, "Query=%s", query);
1097
1098     OCCallbackData cbData;
1099     cbData.cb = &ListMethodsHandler;
1100     cbData.context = (void *)otmCtx;
1101     cbData.cd = NULL;
1102     OCStackResult res = OCDoResource(NULL, OC_REST_GET, query, NULL, NULL,
1103                                      deviceInfo->connType, OC_HIGH_QOS, &cbData, NULL, 0);
1104     if (res != OC_STACK_OK)
1105     {
1106         OIC_LOG(ERROR, TAG, "OCStack resource error");
1107     }
1108
1109     OIC_LOG(DEBUG, TAG, "OUT GetProvisioningStatusResource");
1110
1111     return res;
1112 }
1113
1114 static OCStackResult PostOwnerUuid(OTMContext_t* otmCtx)
1115 {
1116     OIC_LOG(DEBUG, TAG, "IN PostOwnerUuid");
1117
1118     if(!otmCtx || !otmCtx->selectedDeviceInfo)
1119     {
1120         OIC_LOG(ERROR, TAG, "Invailed parameters");
1121         return OC_STACK_INVALID_PARAM;
1122     }
1123
1124     OCProvisionDev_t* deviceInfo = otmCtx->selectedDeviceInfo;
1125     char query[MAX_URI_LENGTH + MAX_QUERY_LENGTH] = {0};
1126     if(!PMGenerateQuery(true,
1127                         deviceInfo->endpoint.addr, deviceInfo->securePort,
1128                         deviceInfo->connType,
1129                         query, sizeof(query), OIC_RSRC_DOXM_URI))
1130     {
1131         OIC_LOG(ERROR, TAG, "PostOwnerUuid : Failed to generate query");
1132         return OC_STACK_ERROR;
1133     }
1134     OIC_LOG_V(DEBUG, TAG, "Query=%s", query);
1135
1136     //Post PT's uuid to new device
1137     OCSecurityPayload* secPayload = (OCSecurityPayload*)OICCalloc(1, sizeof(OCSecurityPayload));
1138     if(!secPayload)
1139     {
1140         OIC_LOG(ERROR, TAG, "Failed to memory allocation");
1141         return OC_STACK_NO_MEMORY;
1142     }
1143     secPayload->base.type = PAYLOAD_TYPE_SECURITY;
1144     OCStackResult res =  g_OTMDatas[deviceInfo->doxm->oxmSel].createOwnerTransferPayloadCB(
1145             otmCtx, &secPayload->securityData, &secPayload->payloadSize);
1146     if (OC_STACK_OK != res && NULL == secPayload->securityData)
1147     {
1148         OCPayloadDestroy((OCPayload *)secPayload);
1149         OIC_LOG(ERROR, TAG, "Error while converting doxm bin to cbor.");
1150         return OC_STACK_INVALID_PARAM;
1151     }
1152     OIC_LOG_BUFFER(DEBUG, TAG, secPayload->securityData, secPayload->payloadSize);
1153
1154     OCCallbackData cbData;
1155     cbData.cb = &OwnerUuidUpdateHandler;
1156     cbData.context = (void *)otmCtx;
1157     cbData.cd = NULL;
1158
1159     res = OCDoResource(NULL, OC_REST_POST, query, 0, (OCPayload *)secPayload,
1160             deviceInfo->connType, OC_HIGH_QOS, &cbData, NULL, 0);
1161     if (res != OC_STACK_OK)
1162     {
1163         OIC_LOG(ERROR, TAG, "OCStack resource error");
1164     }
1165
1166     OIC_LOG(DEBUG, TAG, "OUT PostOwnerUuid");
1167
1168     return res;
1169 }
1170
1171 static OCStackResult PostOwnershipInformation(OTMContext_t* otmCtx)
1172 {
1173     OIC_LOG(DEBUG, TAG, "IN PostOwnershipInformation");
1174
1175     if(!otmCtx || !otmCtx->selectedDeviceInfo)
1176     {
1177         OIC_LOG(ERROR, TAG, "Invailed parameters");
1178         return OC_STACK_INVALID_PARAM;
1179     }
1180
1181     OCProvisionDev_t* deviceInfo = otmCtx->selectedDeviceInfo;
1182     char query[MAX_URI_LENGTH + MAX_QUERY_LENGTH] = {0};
1183     if(!PMGenerateQuery(true,
1184                         deviceInfo->endpoint.addr, deviceInfo->securePort,
1185                         deviceInfo->connType,
1186                         query, sizeof(query), OIC_RSRC_DOXM_URI))
1187     {
1188         OIC_LOG(ERROR, TAG, "PostOwnershipInformation : Failed to generate query");
1189         return OC_STACK_ERROR;
1190     }
1191     OIC_LOG_V(DEBUG, TAG, "Query=%s", query);
1192
1193     //OwnershipInformationHandler
1194     OCSecurityPayload *secPayload = (OCSecurityPayload*)OICCalloc(1, sizeof(OCSecurityPayload));
1195     if (!secPayload)
1196     {
1197         OIC_LOG(ERROR, TAG, "Failed to memory allocation");
1198         return OC_STACK_NO_MEMORY;
1199     }
1200
1201     otmCtx->selectedDeviceInfo->doxm->owned = true;
1202
1203     secPayload->base.type = PAYLOAD_TYPE_SECURITY;
1204     OCStackResult res = DoxmToCBORPayload(otmCtx->selectedDeviceInfo->doxm,
1205             &secPayload->securityData, &secPayload->payloadSize);
1206     if (OC_STACK_OK != res && NULL == secPayload->securityData)
1207     {
1208         OCPayloadDestroy((OCPayload *)secPayload);
1209         OIC_LOG(ERROR, TAG, "Error while converting doxm bin to json");
1210         return OC_STACK_INVALID_PARAM;
1211     }
1212
1213     OCCallbackData cbData;
1214     cbData.cb = &OwnershipInformationHandler;
1215     cbData.context = (void *)otmCtx;
1216     cbData.cd = NULL;
1217
1218     res = OCDoResource(NULL, OC_REST_POST, query, 0, (OCPayload*)secPayload,
1219                        deviceInfo->connType, OC_HIGH_QOS, &cbData, NULL, 0);
1220     if (res != OC_STACK_OK)
1221     {
1222         OIC_LOG(ERROR, TAG, "OCStack resource error");
1223     }
1224
1225     OIC_LOG(DEBUG, TAG, "OUT PostOwnershipInformation");
1226
1227     return res;
1228 }
1229
1230 static OCStackResult PostUpdateOperationMode(OTMContext_t* otmCtx)
1231 {
1232     OIC_LOG(DEBUG, TAG, "IN PostUpdateOperationMode");
1233
1234     if(!otmCtx || !otmCtx->selectedDeviceInfo)
1235     {
1236         return OC_STACK_INVALID_PARAM;
1237     }
1238
1239     OCProvisionDev_t* deviceInfo = otmCtx->selectedDeviceInfo;
1240     char query[MAX_URI_LENGTH + MAX_QUERY_LENGTH] = {0};
1241     if(!PMGenerateQuery(false,
1242                         deviceInfo->endpoint.addr, deviceInfo->endpoint.port,
1243                         deviceInfo->connType,
1244                         query, sizeof(query), OIC_RSRC_PSTAT_URI))
1245     {
1246         OIC_LOG(ERROR, TAG, "PostUpdateOperationMode : Failed to generate query");
1247         return OC_STACK_ERROR;
1248     }
1249     OIC_LOG_V(DEBUG, TAG, "Query=%s", query);
1250
1251     OCSecurityPayload* secPayload = (OCSecurityPayload*)OICCalloc(1, sizeof(OCSecurityPayload));
1252     if(!secPayload)
1253     {
1254         OIC_LOG(ERROR, TAG, "Failed to memory allocation");
1255         return OC_STACK_NO_MEMORY;
1256     }
1257     secPayload->base.type = PAYLOAD_TYPE_SECURITY;
1258     OCStackResult res = PstatToCBORPayload(deviceInfo->pstat, &secPayload->securityData,
1259                                            &secPayload->payloadSize);
1260    if (OC_STACK_OK != res)
1261     {
1262         OCPayloadDestroy((OCPayload *)secPayload);
1263         OIC_LOG(ERROR, TAG, "Error while converting pstat to cbor.");
1264         return OC_STACK_INVALID_PARAM;
1265     }
1266
1267     OCCallbackData cbData;
1268     cbData.cb = &OperationModeUpdateHandler;
1269     cbData.context = (void *)otmCtx;
1270     cbData.cd = NULL;
1271     res = OCDoResource(NULL, OC_REST_POST, query, 0, (OCPayload *)secPayload,
1272                        deviceInfo->connType, OC_HIGH_QOS, &cbData, NULL, 0);
1273     if (res != OC_STACK_OK)
1274     {
1275         OIC_LOG(ERROR, TAG, "OCStack resource error");
1276     }
1277
1278     OIC_LOG(DEBUG, TAG, "OUT PostUpdateOperationMode");
1279
1280     return res;
1281 }
1282
1283 static OCStackResult StartOwnershipTransfer(void* ctx, OCProvisionDev_t* selectedDevice)
1284 {
1285     OIC_LOG(INFO, TAG, "IN StartOwnershipTransfer");
1286     OTMContext_t* otmCtx = (OTMContext_t*)ctx;
1287     otmCtx->selectedDeviceInfo = selectedDevice;
1288
1289     //Set to the lowest level OxM, and then find more higher level OxM.
1290     OCStackResult res = SelectProvisioningMethod(selectedDevice->doxm->oxm,
1291                                                  selectedDevice->doxm->oxmLen,
1292                                                  &selectedDevice->doxm->oxmSel);
1293     if(OC_STACK_OK != res)
1294     {
1295         OIC_LOG(ERROR, TAG, "Failed to select the provisioning method");
1296         SetResult(otmCtx, res);
1297         return res;
1298     }
1299     OIC_LOG_V(DEBUG, TAG, "Selected provisoning method = %d", selectedDevice->doxm->oxmSel);
1300
1301     //Send Req: POST /oic/sec/doxm [{..."OxmSel" :g_OTMDatas[Index of Selected OxM].OXMString,...}]
1302     res = PostOwnerTransferModeToResource(otmCtx);
1303     if(OC_STACK_OK != res)
1304     {
1305         OIC_LOG(WARNING, TAG, "Failed to select the provisioning method");
1306         SetResult(otmCtx, res);
1307         return res;
1308     }
1309
1310     //Register DTLS event handler to catch the dtls event while handshake
1311     if(CA_STATUS_OK != CARegisterDTLSHandshakeCallback(DTLSHandshakeCB))
1312     {
1313         OIC_LOG(WARNING, TAG, "StartOwnershipTransfer : Failed to register DTLS handshake callback.");
1314     }
1315
1316     OIC_LOG(INFO, TAG, "OUT StartOwnershipTransfer");
1317
1318     return res;
1319
1320 }
1321
1322 OCStackResult OTMSetOwnershipTransferCallbackData(OicSecOxm_t oxmType, OTMCallbackData_t* data)
1323 {
1324     OIC_LOG(DEBUG, TAG, "IN OTMSetOwnerTransferCallbackData");
1325
1326     if(!data)
1327     {
1328         OIC_LOG(ERROR, TAG, "OTMSetOwnershipTransferCallbackData : Invalid parameters");
1329         return OC_STACK_INVALID_PARAM;
1330     }
1331     if(oxmType >= OIC_OXM_COUNT)
1332     {
1333         OIC_LOG(INFO, TAG, "Unknow ownership transfer method");
1334         return OC_STACK_INVALID_PARAM;
1335     }
1336
1337     g_OTMDatas[oxmType].loadSecretCB= data->loadSecretCB;
1338     g_OTMDatas[oxmType].createSecureSessionCB = data->createSecureSessionCB;
1339     g_OTMDatas[oxmType].createSelectOxmPayloadCB = data->createSelectOxmPayloadCB;
1340     g_OTMDatas[oxmType].createOwnerTransferPayloadCB = data->createOwnerTransferPayloadCB;
1341
1342     OIC_LOG(DEBUG, TAG, "OUT OTMSetOwnerTransferCallbackData");
1343
1344     return OC_STACK_OK;
1345 }
1346
1347 /**
1348  * NOTE : Unowned discovery should be done before performing OTMDoOwnershipTransfer
1349  */
1350 OCStackResult OTMDoOwnershipTransfer(void* ctx,
1351                                      OCProvisionDev_t *selectedDevicelist,
1352                                      OCProvisionResultCB resultCallback)
1353 {
1354     OIC_LOG(DEBUG, TAG, "IN OTMDoOwnershipTransfer");
1355
1356     if (NULL == selectedDevicelist)
1357     {
1358         return OC_STACK_INVALID_PARAM;
1359     }
1360     if (NULL == resultCallback)
1361     {
1362         return OC_STACK_INVALID_CALLBACK;
1363     }
1364
1365     OTMContext_t* otmCtx = (OTMContext_t*)OICCalloc(1,sizeof(OTMContext_t));
1366     if(!otmCtx)
1367     {
1368         OIC_LOG(ERROR, TAG, "Failed to create OTM Context");
1369         return OC_STACK_NO_MEMORY;
1370     }
1371     otmCtx->ctxResultCallback = resultCallback;
1372     otmCtx->ctxHasError = false;
1373     otmCtx->userCtx = ctx;
1374     OCProvisionDev_t* pCurDev = selectedDevicelist;
1375
1376     //Counting number of selected devices.
1377     otmCtx->ctxResultArraySize = 0;
1378     while(NULL != pCurDev)
1379     {
1380         otmCtx->ctxResultArraySize++;
1381         pCurDev = pCurDev->next;
1382     }
1383
1384     otmCtx->ctxResultArray =
1385         (OCProvisionResult_t*)OICCalloc(otmCtx->ctxResultArraySize, sizeof(OCProvisionResult_t));
1386     if(NULL == otmCtx->ctxResultArray)
1387     {
1388         OIC_LOG(ERROR, TAG, "OTMDoOwnershipTransfer : Failed to memory allocation");
1389         OICFree(otmCtx);
1390         return OC_STACK_NO_MEMORY;
1391     }
1392     pCurDev = selectedDevicelist;
1393
1394     OCStackResult res = OC_STACK_OK;
1395     //Fill the device UUID for result array.
1396     for(size_t devIdx = 0; devIdx < otmCtx->ctxResultArraySize; devIdx++)
1397     {
1398         //Checking duplication of Device ID.
1399         bool isDuplicate = true;
1400         res = PDMIsDuplicateDevice(&pCurDev->doxm->deviceID, &isDuplicate);
1401         if (OC_STACK_OK != res)
1402         {
1403             goto error;
1404         }
1405         if (isDuplicate)
1406         {
1407             OIC_LOG(ERROR, TAG, "OTMDoOwnershipTransfer : Device ID is duplicated");
1408             res = OC_STACK_INVALID_PARAM;
1409             goto error;
1410         }
1411         memcpy(otmCtx->ctxResultArray[devIdx].deviceId.id,
1412                pCurDev->doxm->deviceID.id,
1413                UUID_LENGTH);
1414         otmCtx->ctxResultArray[devIdx].res = OC_STACK_CONTINUE;
1415         pCurDev = pCurDev->next;
1416     }
1417
1418     StartOwnershipTransfer(otmCtx, selectedDevicelist);
1419
1420     OIC_LOG(DEBUG, TAG, "OUT OTMDoOwnershipTransfer");
1421     return OC_STACK_OK;
1422
1423 error:
1424     OICFree(otmCtx->ctxResultArray);
1425     OICFree(otmCtx);
1426     return res;
1427 }
1428
1429 OCStackResult PostProvisioningStatus(OTMContext_t* otmCtx)
1430 {
1431     OIC_LOG(INFO, TAG, "IN PostProvisioningStatus");
1432
1433     if(!otmCtx || !otmCtx->selectedDeviceInfo)
1434     {
1435         OIC_LOG(ERROR, TAG, "OTMContext is NULL");
1436         return OC_STACK_INVALID_PARAM;
1437     }
1438
1439     //Change the TAKE_OWNER bit of CM to 0.
1440     otmCtx->selectedDeviceInfo->pstat->cm &= (~TAKE_OWNER);
1441
1442     OCSecurityPayload *secPayload = (OCSecurityPayload *)OICCalloc(1, sizeof(OCSecurityPayload));
1443     if (!secPayload)
1444     {
1445         OIC_LOG(ERROR, TAG, "Failed to memory allocation");
1446         return OC_STACK_NO_MEMORY;
1447     }
1448     secPayload->base.type = PAYLOAD_TYPE_SECURITY;
1449     if (OC_STACK_OK != PstatToCBORPayload(otmCtx->selectedDeviceInfo->pstat,
1450             &secPayload->securityData, &secPayload->payloadSize))
1451     {
1452         OCPayloadDestroy((OCPayload *)secPayload);
1453         return OC_STACK_INVALID_JSON;
1454     }
1455     OIC_LOG(DEBUG, TAG, "Created payload for chage to Provisiong state");
1456     OIC_LOG_BUFFER(DEBUG, TAG, secPayload->securityData, secPayload->payloadSize);
1457
1458     char query[MAX_URI_LENGTH + MAX_QUERY_LENGTH] = {0};
1459     if(!PMGenerateQuery(true,
1460                         otmCtx->selectedDeviceInfo->endpoint.addr,
1461                         otmCtx->selectedDeviceInfo->securePort,
1462                         otmCtx->selectedDeviceInfo->connType,
1463                         query, sizeof(query), OIC_RSRC_PSTAT_URI))
1464     {
1465         OIC_LOG(ERROR, TAG, "PostProvisioningStatus : Failed to generate query");
1466         return OC_STACK_ERROR;
1467     }
1468     OIC_LOG_V(DEBUG, TAG, "Query=%s", query);
1469
1470     OCCallbackData cbData = {.context=NULL, .cb=NULL, .cd=NULL};
1471     cbData.cb = &ProvisioningStatusHandler;
1472     cbData.context = (void*)otmCtx;
1473     cbData.cd = NULL;
1474     OCStackResult ret = OCDoResource(NULL, OC_REST_POST, query, 0, (OCPayload*)secPayload,
1475             otmCtx->selectedDeviceInfo->connType, OC_HIGH_QOS, &cbData, NULL, 0);
1476     OIC_LOG_V(INFO, TAG, "OCDoResource returned: %d",ret);
1477     if (ret != OC_STACK_OK)
1478     {
1479         OIC_LOG(ERROR, TAG, "OCStack resource error");
1480     }
1481
1482     OIC_LOG(INFO, TAG, "OUT PostProvisioningStatus");
1483
1484     return ret;
1485 }
1486
1487 OCStackResult PostNormalOperationStatus(OTMContext_t* otmCtx)
1488 {
1489     OIC_LOG(INFO, TAG, "IN PostNormalOperationStatus");
1490
1491     if(!otmCtx || !otmCtx->selectedDeviceInfo)
1492     {
1493         OIC_LOG(ERROR, TAG, "OTMContext is NULL");
1494         return OC_STACK_INVALID_PARAM;
1495     }
1496
1497     //Set isop to true.
1498     otmCtx->selectedDeviceInfo->pstat->isOp = true;
1499
1500     OCSecurityPayload *secPayload = (OCSecurityPayload *)OICCalloc(1, sizeof(OCSecurityPayload));
1501     if (!secPayload)
1502     {
1503         OIC_LOG(ERROR, TAG, "Failed to memory allocation");
1504         return OC_STACK_NO_MEMORY;
1505     }
1506     secPayload->base.type = PAYLOAD_TYPE_SECURITY;
1507     if (OC_STACK_OK != PstatToCBORPayload(otmCtx->selectedDeviceInfo->pstat,
1508             &secPayload->securityData, &secPayload->payloadSize))
1509     {
1510         OCPayloadDestroy((OCPayload *)secPayload);
1511         return OC_STACK_INVALID_JSON;
1512     }
1513     OIC_LOG(DEBUG, TAG, "Created payload for chage to Provisiong state");
1514     OIC_LOG_BUFFER(DEBUG, TAG, secPayload->securityData, secPayload->payloadSize);
1515
1516     char query[MAX_URI_LENGTH + MAX_QUERY_LENGTH] = {0};
1517     if(!PMGenerateQuery(true,
1518                         otmCtx->selectedDeviceInfo->endpoint.addr,
1519                         otmCtx->selectedDeviceInfo->securePort,
1520                         otmCtx->selectedDeviceInfo->connType,
1521                         query, sizeof(query), OIC_RSRC_PSTAT_URI))
1522     {
1523         OIC_LOG(ERROR, TAG, "PostNormalOperationStatus : Failed to generate query");
1524         return OC_STACK_ERROR;
1525     }
1526     OIC_LOG_V(DEBUG, TAG, "Query=%s", query);
1527
1528     OCCallbackData cbData = {.context=NULL, .cb=NULL, .cd=NULL};
1529     cbData.cb = &ReadyForNomalStatusHandler;
1530     cbData.context = (void*)otmCtx;
1531     cbData.cd = NULL;
1532     OCStackResult ret = OCDoResource(NULL, OC_REST_POST, query, 0, (OCPayload*)secPayload,
1533             otmCtx->selectedDeviceInfo->connType, OC_HIGH_QOS, &cbData, NULL, 0);
1534     OIC_LOG_V(INFO, TAG, "OCDoResource returned: %d",ret);
1535     if (ret != OC_STACK_OK)
1536     {
1537         OIC_LOG(ERROR, TAG, "OCStack resource error");
1538     }
1539
1540     OIC_LOG(INFO, TAG, "OUT PostNormalOperationStatus");
1541
1542     return ret;
1543 }