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