[IOT-1469] Fix MOT build issues for Windows
[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 "iotivity_config.h"
34 #ifdef HAVE_TIME_H
35 #include <time.h>
36 #endif
37 #ifdef HAVE_UNISTD_H
38 #include <unistd.h>
39 #endif
40 #ifdef HAVE_SYS_TIME_H
41 #include <sys/time.h>
42 #endif
43 #include <stdbool.h>
44 #include <string.h>
45
46 #include "logger.h"
47 #include "oic_malloc.h"
48 #include "oic_string.h"
49 #include "cacommon.h"
50 #include "cainterface.h"
51 #include "base64.h"
52 #include "cJSON.h"
53 #include "global.h"
54 #include "utlist.h"
55
56 #include "srmresourcestrings.h"
57 #include "doxmresource.h"
58 #include "pstatresource.h"
59 #include "credresource.h"
60 #include "aclresource.h"
61 #include "ownershiptransfermanager.h"
62 #include "securevirtualresourcetypes.h"
63 #include "oxmjustworks.h"
64 #ifdef _ENABLE_MULTIPLE_OWNER_
65 #include "oxmrandompin.h"
66 #include "oxmpreconfpin.h"
67 #endif //_ENABLE_MULTIPLE_OWNER_
68 #include "pmtypes.h"
69 #include "pmutility.h"
70 #include "srmutility.h"
71 #include "provisioningdatabasemanager.h"
72 #include "oxmrandompin.h"
73 #include "ocpayload.h"
74 #include "payload_logging.h"
75
76 #define TAG "OTM"
77
78 /**
79  * Variables for pointing the OTMContext to be used in the DTLS handshake result callback.
80  */
81 static OTMContext_t* g_otmCtx = NULL;
82
83 OCStackResult OTMSetOTCallback(OicSecOxm_t oxm, OTMCallbackData_t* callbacks)
84 {
85     OCStackResult res = OC_STACK_INVALID_PARAM;
86
87     OIC_LOG(INFO, TAG, "IN OTMSetOTCallback");
88
89     VERIFY_NON_NULL(TAG, callbacks, ERROR);
90 #ifdef _ENABLE_MULTIPLE_OWNER_
91     VERIFY_SUCCESS(TAG, (OIC_OXM_COUNT > oxm || OIC_PRECONFIG_PIN == oxm), ERROR);
92 #else
93     VERIFY_SUCCESS(TAG, (OIC_OXM_COUNT > oxm), ERROR);
94 #endif //_ENABLE_MULTIPLE_OWNER_
95
96     switch(oxm)
97     {
98     case OIC_JUST_WORKS:
99         callbacks->loadSecretCB = LoadSecretJustWorksCallback;
100         callbacks->createSecureSessionCB = CreateSecureSessionJustWorksCallback;
101         callbacks->createSelectOxmPayloadCB = CreateJustWorksSelectOxmPayload;
102         callbacks->createOwnerTransferPayloadCB = CreateJustWorksOwnerTransferPayload;
103         break;
104     case OIC_RANDOM_DEVICE_PIN:
105         callbacks->loadSecretCB = InputPinCodeCallback;
106         callbacks->createSecureSessionCB = CreateSecureSessionRandomPinCallback;
107         callbacks->createSelectOxmPayloadCB = CreatePinBasedSelectOxmPayload;
108         callbacks->createOwnerTransferPayloadCB = CreatePinBasedOwnerTransferPayload;
109         break;
110     case OIC_MANUFACTURER_CERTIFICATE:
111         OIC_LOG(ERROR, TAG, "OIC_MANUFACTURER_CERTIFICATE not supported yet.");
112         return OC_STACK_INVALID_METHOD;
113     case OIC_DECENTRALIZED_PUBLIC_KEY:
114         OIC_LOG(ERROR, TAG, "OIC_DECENTRALIZED_PUBLIC_KEY not supported yet.");
115         return OC_STACK_INVALID_METHOD;
116 #ifdef _ENABLE_MULTIPLE_OWNER_
117     case OIC_PRECONFIG_PIN:
118         callbacks->loadSecretCB = LoadPreconfigPinCodeCallback;
119         callbacks->createSecureSessionCB = CreateSecureSessionPreconfigPinCallback;
120         callbacks->createSelectOxmPayloadCB = CreatePreconfigPinBasedSelectOxmPayload;
121         callbacks->createOwnerTransferPayloadCB = CreatePreconfigPinBasedOwnerTransferPayload;
122         break;
123 #endif //_ENABLE_MULTIPLE_OWNER_
124     default:
125         OIC_LOG_V(ERROR, TAG, "Unknown OxM : %d", (int)oxm);
126         return OC_STACK_INVALID_PARAM;
127         break;
128     }
129
130     res = OC_STACK_OK;
131 exit:
132     OIC_LOG(INFO, TAG, "OUT OTMSetOTCallback");
133     return res;
134 }
135
136
137 /**
138  * Function to select appropriate  provisioning method.
139  *
140  * @param[in] supportedMethods   Array of supported methods
141  * @param[in] numberOfMethods   number of supported methods
142  * @param[out]  selectedMethod         Selected methods
143  * @return  OC_STACK_OK on success
144  */
145 static OCStackResult SelectProvisioningMethod(const OicSecOxm_t *supportedMethods,
146         size_t numberOfMethods, OicSecOxm_t *selectedMethod)
147 {
148     OIC_LOG(DEBUG, TAG, "IN SelectProvisioningMethod");
149
150     if(numberOfMethods == 0 || !supportedMethods)
151     {
152         OIC_LOG(WARNING, TAG, "Could not find a supported OxM.");
153         return OC_STACK_ERROR;
154     }
155
156     *selectedMethod  = supportedMethods[0];
157     for(size_t i = 0; i < numberOfMethods; i++)
158     {
159         if(*selectedMethod < supportedMethods[i])
160         {
161             *selectedMethod =  supportedMethods[i];
162         }
163     }
164
165     OIC_LOG(DEBUG, TAG, "OUT SelectProvisioningMethod");
166
167     return OC_STACK_OK;
168 }
169
170 /**
171  * Function to select operation mode.This function will return most secure common operation mode.
172  *
173  * @param[in] selectedDeviceInfo   selected device information to performing provisioning.
174  * @param[out]   selectedMode   selected operation mode
175  * @return  OC_STACK_OK on success
176  */
177 static void SelectOperationMode(const OCProvisionDev_t *selectedDeviceInfo,
178                                 OicSecDpom_t *selectedMode)
179 {
180     OIC_LOG(DEBUG, TAG, "IN SelectOperationMode");
181     *selectedMode = selectedDeviceInfo->pstat->sm[0];
182     OIC_LOG_V(DEBUG, TAG, "Selected Operation Mode = %d", *selectedMode);
183 }
184
185 /**
186  * Function to start ownership transfer.
187  * This function will send the first request for provisioning,
188  * The next request message is sent from the response handler for this request.
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 StartOwnershipTransfer(void* ctx, OCProvisionDev_t* selectedDevice);
195
196 /**
197  * Function to update owner transfer mode
198  *
199  * @param[in]  otmCtx  Context value of ownership transfer.
200  * @return  OC_STACK_OK on success
201  */
202 static OCStackResult PostOwnerTransferModeToResource(OTMContext_t* otmCtx);
203
204 /**
205  * Function to send request to resource to get its pstat resource information.
206  *
207  * @param[in]  otmCtx  Context value of ownership transfer.
208  * @return  OC_STACK_OK on success
209  */
210 static OCStackResult GetProvisioningStatusResource(OTMContext_t* otmCtx);
211
212
213 /**
214  * Function to send  uuid of owner device to new device.
215  * This function would update 'owner of doxm' as UUID for provisioning tool.
216  *
217  * @param[in]  otmCtx  Context value of ownership transfer.
218  * @return  OC_STACK_OK on success
219  */
220 static OCStackResult PostOwnerUuid(OTMContext_t* otmCtx);
221
222 /**
223  * Function to update the operation mode. As per the spec. Operation mode in client driven
224  * single service provisioning it will be updated to 0x3
225  *
226  * @param[in]  otmCtx  Context value of ownership transfer.
227  * @return  OC_STACK_OK on success
228  */
229 static OCStackResult PostUpdateOperationMode(OTMContext_t* otmCtx);
230
231 /**
232  * Function to update the owner credential to new device
233  *
234  * @param[in]  otmCtx  Context value of ownership transfer.
235  * @param[in] selectedOperationMode selected operation mode
236  * @return  OC_STACK_OK on success
237  */
238 static OCStackResult PostOwnerCredential(OTMContext_t* otmCtx);
239
240 /**
241  * Function to update the owner ACL to new device.
242  *
243  * @param[in]  otmCtx  Context value of ownership transfer.
244  * @return  OC_STACK_OK on success
245  */
246 static OCStackResult PostOwnerAcl(OTMContext_t* otmCtx);
247
248 /**
249  * Function to send ownerShip info.
250  * This function would update 'owned of doxm' as true.
251  *
252  * @param[in]  otmCtx  Context value of ownership transfer.
253  * @return  OC_STACK_OK on success
254  */
255 static OCStackResult PostOwnershipInformation(OTMContext_t* otmCtx);
256
257 /**
258  * Function to update pstat as Ready for provisioning.
259  * This function would update 'cm' from bx0000,0010 to bx0000,0000.
260  *
261  * @param[in] ctx   context value passed to callback from calling function.
262  * @param[in] selectedDevice   selected device information to performing provisioning.
263  * @return  OC_STACK_OK on success
264  */
265 static OCStackResult PostProvisioningStatus(OTMContext_t* otmCtx);
266
267 /**
268  * Function to update pstat as Ready for Normal Operation.
269  * This function would update 'isop' from false to true.
270  *
271  * @param[in] ctx   context value passed to callback from calling function.
272  * @param[in] selectedDevice   selected device information to performing provisioning.
273  * @return  OC_STACK_OK on success
274  */
275 static OCStackResult PostNormalOperationStatus(OTMContext_t* otmCtx);
276
277 static bool IsComplete(OTMContext_t* otmCtx)
278 {
279     for(size_t i = 0; i < otmCtx->ctxResultArraySize; i++)
280     {
281         if(OC_STACK_CONTINUE == otmCtx->ctxResultArray[i].res)
282         {
283             return false;
284         }
285     }
286
287     return true;
288 }
289
290 /**
291  * Function to save the result of provisioning.
292  *
293  * @param[in,out] otmCtx   Context value of ownership transfer.
294  * @param[in] res   result of provisioning
295  */
296 static void SetResult(OTMContext_t* otmCtx, const OCStackResult res)
297 {
298     OIC_LOG_V(DEBUG, TAG, "IN SetResult : %d ", res);
299
300     if(!otmCtx)
301     {
302         OIC_LOG(WARNING, TAG, "OTMContext is NULL");
303         return;
304     }
305
306     if(otmCtx->selectedDeviceInfo)
307     {
308         //Revert psk_info callback and new deivce uuid in case of random PIN OxM
309         if(OIC_RANDOM_DEVICE_PIN == otmCtx->selectedDeviceInfo->doxm->oxmSel)
310         {
311             if(CA_STATUS_OK != CAregisterPskCredentialsHandler(GetDtlsPskCredentials))
312             {
313                 OIC_LOG(WARNING, TAG, "Failed to revert  is DTLS credential handler.");
314             }
315             OicUuid_t emptyUuid = { .id={0}};
316             SetUuidForPinBasedOxm(&emptyUuid);
317         }
318
319         for(size_t i = 0; i < otmCtx->ctxResultArraySize; i++)
320         {
321             if(memcmp(otmCtx->selectedDeviceInfo->doxm->deviceID.id,
322                       otmCtx->ctxResultArray[i].deviceId.id, UUID_LENGTH) == 0)
323             {
324                 otmCtx->ctxResultArray[i].res = res;
325                 if(OC_STACK_OK != res)
326                 {
327                     otmCtx->ctxHasError = true;
328                 }
329             }
330         }
331
332         g_otmCtx = NULL;
333
334         //If all request is completed, invoke the user callback.
335         if(IsComplete(otmCtx))
336         {
337             otmCtx->ctxResultCallback(otmCtx->userCtx, otmCtx->ctxResultArraySize,
338                                        otmCtx->ctxResultArray, otmCtx->ctxHasError);
339             OICFree(otmCtx->ctxResultArray);
340             OICFree(otmCtx);
341         }
342         else
343         {
344             if(OC_STACK_OK != StartOwnershipTransfer(otmCtx,
345                                                      otmCtx->selectedDeviceInfo->next))
346             {
347                 OIC_LOG(ERROR, TAG, "Failed to StartOwnershipTransfer");
348             }
349         }
350     }
351
352     OIC_LOG(DEBUG, TAG, "OUT SetResult");
353 }
354
355 /**
356  * Function to handle the handshake result in OTM.
357  * This function will be invoked after DTLS handshake
358  * @param   endPoint  [IN] The remote endpoint.
359  * @param   errorInfo [IN] Error information from the endpoint.
360  * @return  NONE
361  */
362 void DTLSHandshakeCB(const CAEndpoint_t *endpoint, const CAErrorInfo_t *info)
363 {
364     if(NULL != g_otmCtx && NULL != g_otmCtx->selectedDeviceInfo &&
365        NULL != endpoint && NULL != info)
366     {
367         OIC_LOG_V(INFO, TAG, "Received status from remote device(%s:%d) : %d",
368                  endpoint->addr, endpoint->port, info->result);
369
370         OicSecDoxm_t* newDevDoxm = g_otmCtx->selectedDeviceInfo->doxm;
371
372         if(NULL != newDevDoxm)
373         {
374             OicUuid_t emptyUuid = {.id={0}};
375
376             //Make sure the address matches.
377             if(strncmp(g_otmCtx->selectedDeviceInfo->endpoint.addr,
378                endpoint->addr,
379                sizeof(endpoint->addr)) == 0 &&
380                g_otmCtx->selectedDeviceInfo->securePort == endpoint->port)
381             {
382                 OCStackResult res = OC_STACK_ERROR;
383
384                 //If temporal secure sesstion established successfully
385                 if(CA_STATUS_OK == info->result &&
386                    false == newDevDoxm->owned &&
387                    memcmp(&(newDevDoxm->owner), &emptyUuid, sizeof(OicUuid_t)) == 0)
388                 {
389                     //Send request : POST /oic/sec/doxm [{... , "devowner":"PT's UUID"}]
390                     res = PostOwnerUuid(g_otmCtx);
391                     if(OC_STACK_OK != res)
392                     {
393                         OIC_LOG(ERROR, TAG, "OperationModeUpdate : Failed to send owner information");
394                         SetResult(g_otmCtx, res);
395                     }
396                 }
397                 //In case of authentication failure
398                 else if(CA_DTLS_AUTHENTICATION_FAILURE == info->result)
399                 {
400                     //in case of error from owner credential
401                     if(memcmp(&(newDevDoxm->owner), &emptyUuid, sizeof(OicUuid_t)) != 0 &&
402                         true == newDevDoxm->owned)
403                     {
404                         OIC_LOG(ERROR, TAG, "The owner credential may incorrect.");
405
406                         if(OC_STACK_OK != RemoveCredential(&(newDevDoxm->deviceID)))
407                         {
408                             OIC_LOG(WARNING, TAG, "Failed to remove the invaild owner credential");
409                         }
410                         SetResult(g_otmCtx, OC_STACK_AUTHENTICATION_FAILURE);
411                     }
412                     //in case of error from wrong PIN, re-start the ownership transfer
413                     else if(OIC_RANDOM_DEVICE_PIN == newDevDoxm->oxmSel)
414                     {
415                         OIC_LOG(ERROR, TAG, "The PIN number may incorrect.");
416
417                         memcpy(&(newDevDoxm->owner), &emptyUuid, sizeof(OicUuid_t));
418                         newDevDoxm->owned = false;
419                         g_otmCtx->attemptCnt++;
420
421                         if(WRONG_PIN_MAX_ATTEMP > g_otmCtx->attemptCnt)
422                         {
423                             res = StartOwnershipTransfer(g_otmCtx, g_otmCtx->selectedDeviceInfo);
424                             if(OC_STACK_OK != res)
425                             {
426                                 SetResult(g_otmCtx, res);
427                                 OIC_LOG(ERROR, TAG, "Failed to Re-StartOwnershipTransfer");
428                             }
429                         }
430                         else
431                         {
432                             OIC_LOG(ERROR, TAG, "User has exceeded the number of authentication attempts.");
433                             SetResult(g_otmCtx, OC_STACK_AUTHENTICATION_FAILURE);
434                         }
435                     }
436                     else
437                     {
438                         OIC_LOG(ERROR, TAG, "Failed to establish secure session.");
439                         SetResult(g_otmCtx, OC_STACK_AUTHENTICATION_FAILURE);
440                     }
441                 }
442             }
443         }
444     }
445 }
446
447 /**
448  * Function to save the Owner/SubOwner PSK.
449  *
450  * @param[in] selectedDeviceInfo   selected device information to performing provisioning.
451  * @return  OC_STACK_OK on success
452  */
453 static OCStackResult SaveOwnerPSK(OCProvisionDev_t *selectedDeviceInfo)
454 {
455     OIC_LOG(DEBUG, TAG, "IN SaveOwnerPSK");
456
457     OCStackResult res = OC_STACK_ERROR;
458
459     CAEndpoint_t endpoint;
460     memset(&endpoint, 0x00, sizeof(CAEndpoint_t));
461     OICStrcpy(endpoint.addr, MAX_ADDR_STR_SIZE_CA, selectedDeviceInfo->endpoint.addr);
462     endpoint.addr[MAX_ADDR_STR_SIZE_CA - 1] = '\0';
463     endpoint.port = selectedDeviceInfo->securePort;
464     endpoint.adapter = selectedDeviceInfo->endpoint.adapter;
465
466     OicUuid_t ownerDeviceID = {.id={0}};
467     if (OC_STACK_OK != GetDoxmDeviceID(&ownerDeviceID))
468     {
469         OIC_LOG(ERROR, TAG, "Error while retrieving Owner's device ID");
470         return res;
471     }
472
473     uint8_t ownerPSK[OWNER_PSK_LENGTH_128] = {0};
474     OicSecKey_t ownerKey = {ownerPSK, OWNER_PSK_LENGTH_128};
475
476     //Generating OwnerPSK
477     CAResult_t pskRet = CAGenerateOwnerPSK(&endpoint,
478             (uint8_t *)GetOxmString(selectedDeviceInfo->doxm->oxmSel),
479             strlen(GetOxmString(selectedDeviceInfo->doxm->oxmSel)),
480             ownerDeviceID.id, sizeof(ownerDeviceID.id),
481             selectedDeviceInfo->doxm->deviceID.id, sizeof(selectedDeviceInfo->doxm->deviceID.id),
482             ownerPSK, OWNER_PSK_LENGTH_128);
483
484     if (CA_STATUS_OK == pskRet)
485     {
486         OIC_LOG(INFO, TAG,"Owner PSK dump:\n");
487         OIC_LOG_BUFFER(INFO, TAG,ownerPSK, OWNER_PSK_LENGTH_128);
488         //Generating new credential for provisioning tool
489         OicSecCred_t *cred = GenerateCredential(&selectedDeviceInfo->doxm->deviceID,
490                                   SYMMETRIC_PAIR_WISE_KEY, NULL,
491                                   &ownerKey, &ownerDeviceID, NULL);
492         VERIFY_NON_NULL(TAG, cred, ERROR);
493
494         // TODO: Added as workaround. Will be replaced soon.
495         cred->privateData.encoding = OIC_ENCODING_RAW;
496
497 #if 1
498         // NOTE: Test codes to use BASE64 encoded owner PSK.
499         uint32_t outSize = 0;
500         size_t b64BufSize = B64ENCODE_OUT_SAFESIZE((OWNER_PSK_LENGTH_128 + 1));
501         char* b64Buf = (uint8_t *)OICCalloc(1, b64BufSize);
502         VERIFY_NON_NULL(TAG, b64Buf, ERROR);
503         b64Encode(cred->privateData.data, cred->privateData.len, b64Buf, b64BufSize, &outSize);
504
505         OICFree( cred->privateData.data );
506         cred->privateData.data = (uint8_t *)OICCalloc(1, outSize + 1);
507         VERIFY_NON_NULL(TAG, cred->privateData.data, ERROR);
508
509         strncpy(cred->privateData.data, b64Buf, outSize);
510         cred->privateData.data[outSize] = '\0';
511         cred->privateData.encoding = OIC_ENCODING_BASE64;
512         cred->privateData.len = outSize;
513         OICFree(b64Buf);
514 #endif //End of Test codes
515
516         //Finding previous ownerPSK.
517         const OicSecCred_t* credList = GetCredList();
518         OicSecCred_t* prevCred = NULL;
519         uint16_t credId = 0;
520         LL_FOREACH(credList, prevCred)
521         {
522             //OwnerPSK's type is SYMMETRIC_PAIR_WISE_KEY
523             if (SYMMETRIC_PAIR_WISE_KEY == prevCred->credType &&
524                 0 == memcmp(prevCred->subject.id, cred->subject.id, sizeof(cred->subject.id)))
525             {
526                 credId = prevCred->credId;
527                 break;
528             }
529         }
530
531         //If duplicate owner PSK is exists, remove it.
532         if(0 < credId)
533         {
534             OIC_LOG(WARNING, TAG, "Duplicate OwnerPSK was detected.");
535             OIC_LOG(WARNING, TAG, "[Subject] : ");
536             OIC_LOG_BUFFER(WARNING, TAG, prevCred->subject.id, sizeof(prevCred->subject.id));
537             OIC_LOG_V(WARNING, TAG, "[Encoding Type] : %d", prevCred->privateData.encoding);
538             OIC_LOG(WARNING, TAG, "[Private Data] : ");
539             OIC_LOG_BUFFER(WARNING, TAG, prevCred->privateData.data, prevCred->privateData.len);
540             OIC_LOG(WARNING, TAG, "Previous OwnerPSK will be removed.");
541
542             res = RemoveCredentialByCredId(credId);
543             if(OC_STACK_RESOURCE_DELETED != res)
544             {
545                 OIC_LOG(ERROR, TAG, "Failed to remove the previous OwnerPSK");
546                 DeleteCredList(cred);
547                 goto exit;
548             }
549         }
550
551         res = AddCredential(cred);
552         if(res != OC_STACK_OK)
553         {
554             DeleteCredList(cred);
555             return res;
556         }
557     }
558     else
559     {
560         OIC_LOG(ERROR, TAG, "CAGenerateOwnerPSK failed");
561     }
562
563     OIC_LOG(DEBUG, TAG, "OUT SaveOwnerPSK");
564 exit:
565     return res;
566 }
567
568 /**
569  * Callback handler for OwnerShipTransferModeHandler API.
570  *
571  * @param[in] ctx             ctx value passed to callback from calling function.
572  * @param[in] UNUSED          handle to an invocation
573  * @param[in] clientResponse  Response from queries to remote servers.
574  * @return  OC_STACK_DELETE_TRANSACTION to delete the transaction
575  *          and  OC_STACK_KEEP_TRANSACTION to keep it.
576  */
577 static OCStackApplicationResult OwnerTransferModeHandler(void *ctx, OCDoHandle UNUSED,
578                                                          OCClientResponse *clientResponse)
579 {
580     OIC_LOG(DEBUG, TAG, "IN OwnerTransferModeHandler");
581
582     VERIFY_NON_NULL(TAG, clientResponse, WARNING);
583     VERIFY_NON_NULL(TAG, ctx, WARNING);
584
585     OTMContext_t* otmCtx = (OTMContext_t*)ctx;
586     (void)UNUSED;
587     if (OC_STACK_RESOURCE_CHANGED == clientResponse->result)
588     {
589         OIC_LOG(INFO, TAG, "OwnerTransferModeHandler : response result = OC_STACK_OK");
590         //Send request : GET /oic/sec/pstat
591         OCStackResult res = GetProvisioningStatusResource(otmCtx);
592         if(OC_STACK_OK != res)
593         {
594             OIC_LOG(WARNING, TAG, "Failed to get pstat information");
595             SetResult(otmCtx, res);
596         }
597     }
598     else
599     {
600         OIC_LOG_V(WARNING, TAG, "OwnerTransferModeHandler : Client response is incorrect : %d",
601         clientResponse->result);
602         SetResult(otmCtx, clientResponse->result);
603     }
604
605     OIC_LOG(DEBUG, TAG, "OUT OwnerTransferModeHandler");
606
607 exit:
608     return  OC_STACK_DELETE_TRANSACTION;
609 }
610
611 /**
612  * Callback handler for ProvisioningStatusResouceHandler API.
613  *
614  * @param[in] ctx             ctx value passed to callback from calling function.
615  * @param[in] UNUSED          handle to an invocation
616  * @param[in] clientResponse  Response from queries to remote servers.
617  * @return  OC_STACK_DELETE_TRANSACTION to delete the transaction
618  *          and  OC_STACK_KEEP_TRANSACTION to keep it.
619  */
620 static OCStackApplicationResult ListMethodsHandler(void *ctx, OCDoHandle UNUSED,
621                                                     OCClientResponse *clientResponse)
622 {
623     OIC_LOG(DEBUG, TAG, "IN ListMethodsHandler");
624
625     VERIFY_NON_NULL(TAG, clientResponse, WARNING);
626     VERIFY_NON_NULL(TAG, ctx, WARNING);
627
628     OTMContext_t* otmCtx = (OTMContext_t*)ctx;
629     (void)UNUSED;
630     if  (OC_STACK_OK == clientResponse->result)
631     {
632         if  (NULL == clientResponse->payload)
633         {
634             OIC_LOG(INFO, TAG, "Skiping Null payload");
635             SetResult(otmCtx, OC_STACK_ERROR);
636             return OC_STACK_DELETE_TRANSACTION;
637         }
638
639         if (PAYLOAD_TYPE_SECURITY != clientResponse->payload->type)
640         {
641             OIC_LOG(INFO, TAG, "Unknown payload type");
642             SetResult(otmCtx, OC_STACK_ERROR);
643             return OC_STACK_DELETE_TRANSACTION;
644         }
645         OicSecPstat_t* pstat = NULL;
646         OCStackResult result = CBORPayloadToPstat(
647                 ((OCSecurityPayload*)clientResponse->payload)->securityData,
648                 ((OCSecurityPayload*)clientResponse->payload)->payloadSize,
649                 &pstat);
650         if(NULL == pstat || result != OC_STACK_OK)
651         {
652             OIC_LOG(ERROR, TAG, "Error while converting cbor to pstat.");
653             SetResult(otmCtx, OC_STACK_ERROR);
654             return OC_STACK_DELETE_TRANSACTION;
655         }
656         if(false == (TAKE_OWNER & pstat->cm))
657         {
658             OIC_LOG(ERROR, TAG, "Device pairing mode enabling owner transfer operations is disabled");
659             SetResult(otmCtx, OC_STACK_ERROR);
660             return OC_STACK_DELETE_TRANSACTION;
661         }
662         otmCtx->selectedDeviceInfo->pstat = pstat;
663
664         //Select operation mode (Currently supported SINGLE_SERVICE_CLIENT_DRIVEN only)
665         SelectOperationMode(otmCtx->selectedDeviceInfo, &(otmCtx->selectedDeviceInfo->pstat->om));
666
667         //Send request : POST /oic/sec/pstat [{"om":"bx11", .. }]
668         OCStackResult res = PostUpdateOperationMode(otmCtx);
669         if (OC_STACK_OK != res)
670         {
671             OIC_LOG(ERROR, TAG, "Error while updating operation mode.");
672             SetResult(otmCtx, res);
673         }
674     }
675     else
676     {
677         OIC_LOG_V(WARNING, TAG, "ListMethodsHandler : Client response is incorrect : %d",
678             clientResponse->result);
679         SetResult(otmCtx, clientResponse->result);
680     }
681
682     OIC_LOG(DEBUG, TAG, "OUT ListMethodsHandler");
683 exit:
684     return  OC_STACK_DELETE_TRANSACTION;
685 }
686
687 /**
688  * Response handler for update owner uuid request.
689  *
690  * @param[in] ctx             ctx value passed to callback from calling function.
691  * @param[in] UNUSED          handle to an invocation
692  * @param[in] clientResponse  Response from queries to remote servers.
693  * @return  OC_STACK_DELETE_TRANSACTION to delete the transaction
694  *          and  OC_STACK_KEEP_TRANSACTION to keep it.
695  */
696 static OCStackApplicationResult OwnerUuidUpdateHandler(void *ctx, OCDoHandle UNUSED,
697                                 OCClientResponse *clientResponse)
698 {
699     VERIFY_NON_NULL(TAG, clientResponse, WARNING);
700     VERIFY_NON_NULL(TAG, ctx, WARNING);
701
702     OIC_LOG(DEBUG, TAG, "IN OwnerUuidUpdateHandler");
703     (void)UNUSED;
704     OCStackResult res = OC_STACK_OK;
705     OTMContext_t* otmCtx = (OTMContext_t*)ctx;
706
707     if(OC_STACK_RESOURCE_CHANGED == clientResponse->result)
708     {
709         if(otmCtx && otmCtx->selectedDeviceInfo)
710         {
711             res = SaveOwnerPSK(otmCtx->selectedDeviceInfo);
712             if(OC_STACK_OK != res)
713             {
714                 OIC_LOG(ERROR, TAG, "OwnerUuidUpdateHandler:Failed to owner PSK generation");
715                 SetResult(otmCtx, res);
716                 return OC_STACK_DELETE_TRANSACTION;
717             }
718
719             //POST owner credential to new device according to security spec B.
720             res = PostOwnerCredential(otmCtx);
721             if(OC_STACK_OK != res)
722             {
723                 OIC_LOG(ERROR, TAG,
724                         "OwnerUuidUpdateHandler:Failed to send PosT request for onwer credential");
725                 SetResult(otmCtx, res);
726                 return OC_STACK_DELETE_TRANSACTION;
727             }
728         }
729     }
730     else
731     {
732         res = clientResponse->result;
733         OIC_LOG_V(ERROR, TAG, "OwnerUuidHandler : Unexpected result %d", res);
734         SetResult(otmCtx, res);
735     }
736
737     OIC_LOG(DEBUG, TAG, "OUT OwnerUuidUpdateHandler");
738
739 exit:
740     return  OC_STACK_DELETE_TRANSACTION;
741 }
742
743 /**
744  * Response handler for update operation mode.
745  *
746  * @param[in] ctx             ctx value passed to callback from calling function.
747  * @param[in] UNUSED          handle to an invocation
748  * @param[in] clientResponse  Response from queries to remote servers.
749  * @return  OC_STACK_DELETE_TRANSACTION to delete the transaction
750  *          and  OC_STACK_KEEP_TRANSACTION to keep it.
751  */
752 static OCStackApplicationResult OperationModeUpdateHandler(void *ctx, OCDoHandle UNUSED,
753                                 OCClientResponse *clientResponse)
754 {
755     OIC_LOG(DEBUG, TAG, "IN OperationModeUpdateHandler");
756
757     VERIFY_NON_NULL(TAG, clientResponse, WARNING);
758     VERIFY_NON_NULL(TAG, ctx, WARNING);
759
760     OTMContext_t* otmCtx = (OTMContext_t*)ctx;
761     (void) UNUSED;
762     if  (OC_STACK_RESOURCE_CHANGED == clientResponse->result)
763     {
764         OCStackResult res = OC_STACK_ERROR;
765         OicSecOxm_t selOxm = otmCtx->selectedDeviceInfo->doxm->oxmSel;
766
767         //DTLS Handshake
768         //Load secret for temporal secure session.
769         if(otmCtx->otmCallback.loadSecretCB)
770         {
771             res = otmCtx->otmCallback.loadSecretCB(otmCtx);
772             if(OC_STACK_OK != res)
773             {
774                 OIC_LOG(ERROR, TAG, "OperationModeUpdate : Failed to load secret");
775                 SetResult(otmCtx, res);
776                 return  OC_STACK_DELETE_TRANSACTION;
777             }
778         }
779
780         //It will be used in handshake event handler
781         g_otmCtx = otmCtx;
782
783         //Try DTLS handshake to generate secure session
784         if(otmCtx->otmCallback.createSecureSessionCB)
785         {
786             res = otmCtx->otmCallback.createSecureSessionCB(otmCtx);
787             if(OC_STACK_OK != res)
788             {
789                 OIC_LOG(ERROR, TAG, "OperationModeUpdate : Failed to create DTLS session");
790                 SetResult(otmCtx, res);
791                 return OC_STACK_DELETE_TRANSACTION;
792             }
793         }
794     }
795     else
796     {
797         OIC_LOG(ERROR, TAG, "Error while update operation mode");
798         SetResult(otmCtx, clientResponse->result);
799     }
800
801     OIC_LOG(DEBUG, TAG, "OUT OperationModeUpdateHandler");
802
803 exit:
804     return  OC_STACK_DELETE_TRANSACTION;
805 }
806
807 /**
808  * Response handler for update owner crendetial request.
809  *
810  * @param[in] ctx             ctx value passed to callback from calling function.
811  * @param[in] UNUSED          handle to an invocation
812  * @param[in] clientResponse  Response from queries to remote servers.
813  * @return  OC_STACK_DELETE_TRANSACTION to delete the transaction
814  *          and  OC_STACK_KEEP_TRANSACTION to keep it.
815  */
816 static OCStackApplicationResult OwnerCredentialHandler(void *ctx, OCDoHandle UNUSED,
817                                 OCClientResponse *clientResponse)
818 {
819     VERIFY_NON_NULL(TAG, clientResponse, WARNING);
820     VERIFY_NON_NULL(TAG, ctx, WARNING);
821
822     OIC_LOG(DEBUG, TAG, "IN OwnerCredentialHandler");
823     (void)UNUSED;
824     OCStackResult res = OC_STACK_OK;
825     OTMContext_t* otmCtx = (OTMContext_t*)ctx;
826
827     if(OC_STACK_RESOURCE_CHANGED == clientResponse->result)
828     {
829         if(otmCtx && otmCtx->selectedDeviceInfo)
830         {
831             //Close the temporal secure session to verify the owner credential
832             CAEndpoint_t* endpoint = (CAEndpoint_t *)&otmCtx->selectedDeviceInfo->endpoint;
833             endpoint->port = otmCtx->selectedDeviceInfo->securePort;
834             CAResult_t caResult = CA_STATUS_OK;
835             caResult = CAcloseSslConnection(endpoint);
836
837             if(CA_STATUS_OK != caResult)
838             {
839                 OIC_LOG(ERROR, TAG, "Failed to close DTLS session");
840                 SetResult(otmCtx, caResult);
841                 return OC_STACK_DELETE_TRANSACTION;
842             }
843
844             /**
845              * If we select NULL cipher,
846              * client will select appropriate cipher suite according to server's cipher-suite list.
847              */
848             // TLS_ECDHE_PSK_WITH_AES_128_CBC_SHA_256 = 0xC037, /**< see RFC 5489 */
849             caResult = CASelectCipherSuite(0xC037, endpoint->adapter);
850
851             if(CA_STATUS_OK != caResult)
852             {
853                 OIC_LOG(ERROR, TAG, "Failed to select TLS_NULL_WITH_NULL_NULL");
854                 SetResult(otmCtx, caResult);
855                 return OC_STACK_DELETE_TRANSACTION;
856             }
857
858             /**
859              * in case of random PIN based OxM,
860              * revert get_psk_info callback of tinyDTLS to use owner credential.
861              */
862             if(OIC_RANDOM_DEVICE_PIN == otmCtx->selectedDeviceInfo->doxm->oxmSel)
863             {
864                 OicUuid_t emptyUuid = { .id={0}};
865                 SetUuidForPinBasedOxm(&emptyUuid);
866
867                 caResult = CAregisterPskCredentialsHandler(GetDtlsPskCredentials);
868
869                 if(CA_STATUS_OK != caResult)
870                 {
871                     OIC_LOG(ERROR, TAG, "Failed to revert DTLS credential handler.");
872                     SetResult(otmCtx, OC_STACK_INVALID_CALLBACK);
873                     return OC_STACK_DELETE_TRANSACTION;
874                 }
875             }
876 #ifdef __WITH_TLS__
877            otmCtx->selectedDeviceInfo->connType |= CT_FLAG_SECURE;
878 #endif
879             res = PostOwnerAcl(otmCtx);
880             if(OC_STACK_OK != res)
881             {
882                 OIC_LOG(ERROR, TAG, "Failed to update owner ACL to new device");
883                 SetResult(otmCtx, res);
884                 return OC_STACK_DELETE_TRANSACTION;
885             }
886         }
887     }
888     else
889     {
890         res = clientResponse->result;
891         OIC_LOG_V(ERROR, TAG, "OwnerCredentialHandler : Unexpected result %d", res);
892         SetResult(otmCtx, res);
893     }
894
895     OIC_LOG(DEBUG, TAG, "OUT OwnerCredentialHandler");
896
897 exit:
898     return  OC_STACK_DELETE_TRANSACTION;
899 }
900
901 /**
902  * Response handler for update owner ACL request.
903  *
904  * @param[in] ctx             ctx value passed to callback from calling function.
905  * @param[in] UNUSED          handle to an invocation
906  * @param[in] clientResponse  Response from queries to remote servers.
907  * @return  OC_STACK_DELETE_TRANSACTION to delete the transaction
908  *          and  OC_STACK_KEEP_TRANSACTION to keep it.
909  */
910 static OCStackApplicationResult OwnerAclHandler(void *ctx, OCDoHandle UNUSED,
911                                 OCClientResponse *clientResponse)
912 {
913     VERIFY_NON_NULL(TAG, clientResponse, WARNING);
914     VERIFY_NON_NULL(TAG, ctx, WARNING);
915
916     OIC_LOG(DEBUG, TAG, "IN OwnerAclHandler");
917     (void)UNUSED;
918     OCStackResult res = OC_STACK_OK;
919     OTMContext_t* otmCtx = (OTMContext_t*)ctx;
920
921     if(OC_STACK_RESOURCE_CHANGED == clientResponse->result)
922     {
923         if(otmCtx && otmCtx->selectedDeviceInfo)
924         {
925             //POST /oic/sec/doxm [{ ..., "owned":"TRUE" }]
926             res = PostOwnershipInformation(otmCtx);
927             if(OC_STACK_OK != res)
928             {
929                 OIC_LOG(ERROR, TAG, "Failed to update ownership information to new device");
930                 SetResult(otmCtx, res);
931             }
932         }
933     }
934     else
935     {
936         res = clientResponse->result;
937         OIC_LOG_V(ERROR, TAG, "OwnerAclHandler : Unexpected result %d", res);
938         SetResult(otmCtx, res);
939     }
940
941     OIC_LOG(DEBUG, TAG, "OUT OwnerAclHandler");
942
943 exit:
944     return  OC_STACK_DELETE_TRANSACTION;
945 }
946
947
948 /**
949  * Response handler for update owner information request.
950  *
951  * @param[in] ctx             ctx value passed to callback from calling function.
952  * @param[in] UNUSED          handle to an invocation
953  * @param[in] clientResponse  Response from queries to remote servers.
954  * @return  OC_STACK_DELETE_TRANSACTION to delete the transaction
955  *          and  OC_STACK_KEEP_TRANSACTION to keep it.
956  */
957 static OCStackApplicationResult OwnershipInformationHandler(void *ctx, OCDoHandle UNUSED,
958                                 OCClientResponse *clientResponse)
959 {
960     VERIFY_NON_NULL(TAG, clientResponse, WARNING);
961     VERIFY_NON_NULL(TAG, ctx, WARNING);
962
963     OIC_LOG(DEBUG, TAG, "IN OwnershipInformationHandler");
964     (void)UNUSED;
965     OCStackResult res = OC_STACK_OK;
966     OTMContext_t* otmCtx = (OTMContext_t*)ctx;
967
968     if(OC_STACK_RESOURCE_CHANGED == clientResponse->result)
969     {
970         if(otmCtx && otmCtx->selectedDeviceInfo)
971         {
972             OIC_LOG(INFO, TAG, "Ownership transfer was successfully completed.");
973             OIC_LOG(INFO, TAG, "Set Ready for provisioning state .");
974
975             res = PostProvisioningStatus(otmCtx);
976             if(OC_STACK_OK != res)
977             {
978                 OIC_LOG(ERROR, TAG, "Failed to update pstat");
979                 SetResult(otmCtx, res);
980             }
981         }
982     }
983     else
984     {
985         res = clientResponse->result;
986         OIC_LOG_V(ERROR, TAG, "OwnershipInformationHandler : Unexpected result %d", res);
987         SetResult(otmCtx, res);
988     }
989
990     OIC_LOG(DEBUG, TAG, "OUT OwnershipInformationHandler");
991
992 exit:
993     return  OC_STACK_DELETE_TRANSACTION;
994 }
995
996 /**
997  * Response handler of update provisioning status.
998  *
999  * @param[in] ctx             ctx value passed to callback from calling function.
1000  * @param[in] UNUSED          handle to an invocation
1001  * @param[in] clientResponse  Response from queries to remote servers.
1002  * @return  OC_STACK_DELETE_TRANSACTION to delete the transaction
1003  *          and OC_STACK_KEEP_TRANSACTION to keep it.
1004  */
1005 static OCStackApplicationResult ProvisioningStatusHandler(void *ctx, OCDoHandle UNUSED,
1006                                                        OCClientResponse *clientResponse)
1007 {
1008     OIC_LOG_V(INFO, TAG, "IN ProvisioningStatusHandler.");
1009
1010     VERIFY_NON_NULL(TAG, clientResponse, ERROR);
1011     VERIFY_NON_NULL(TAG, ctx, ERROR);
1012
1013     OTMContext_t* otmCtx = (OTMContext_t*) ctx;
1014     (void)UNUSED;
1015     OCStackResult res = OC_STACK_OK;
1016
1017     if(OC_STACK_RESOURCE_CHANGED == clientResponse->result)
1018     {
1019         if(otmCtx && otmCtx->selectedDeviceInfo)
1020         {
1021             OIC_LOG(INFO, TAG, "Device state is in Ready for Provisionig.");
1022
1023             res = PostNormalOperationStatus(otmCtx);
1024             if(OC_STACK_OK != res)
1025             {
1026                 OIC_LOG(ERROR, TAG, "Failed to update pstat");
1027                 SetResult(otmCtx, res);
1028             }
1029         }
1030     }
1031     else
1032     {
1033         OIC_LOG_V(INFO, TAG, "Error occured in provisionDefaultACLCB :: %d\n",
1034                             clientResponse->result);
1035         SetResult(otmCtx, clientResponse->result);
1036     }
1037
1038 exit:
1039     OIC_LOG_V(INFO, TAG, "OUT ProvisioningStatusHandler.");
1040     return OC_STACK_DELETE_TRANSACTION;
1041 }
1042
1043 /**
1044  * Response handler of update provisioning status to Ready for Normal..
1045  *
1046  * @param[in] ctx             ctx value passed to callback from calling function.
1047  * @param[in] UNUSED          handle to an invocation
1048  * @param[in] clientResponse  Response from queries to remote servers.
1049  * @return  OC_STACK_DELETE_TRANSACTION to delete the transaction
1050  *          and OC_STACK_KEEP_TRANSACTION to keep it.
1051  */
1052 static OCStackApplicationResult ReadyForNomalStatusHandler(void *ctx, OCDoHandle UNUSED,
1053                                                        OCClientResponse *clientResponse)
1054 {
1055     OIC_LOG_V(INFO, TAG, "IN ReadyForNomalStatusHandler.");
1056
1057     VERIFY_NON_NULL(TAG, clientResponse, ERROR);
1058     VERIFY_NON_NULL(TAG, ctx, ERROR);
1059
1060     OTMContext_t* otmCtx = (OTMContext_t*) ctx;
1061     (void)UNUSED;
1062
1063     if (OC_STACK_RESOURCE_CHANGED == clientResponse->result)
1064     {
1065         OIC_LOG(INFO, TAG, "Device state is in Ready for Normal Operation.");
1066         OCStackResult res = PDMAddDevice(&otmCtx->selectedDeviceInfo->doxm->deviceID);
1067          if (OC_STACK_OK == res)
1068          {
1069                 OIC_LOG_V(INFO, TAG, "Add device's UUID in PDM_DB");
1070                 SetResult(otmCtx, OC_STACK_OK);
1071                 return OC_STACK_DELETE_TRANSACTION;
1072          }
1073           else
1074          {
1075               OIC_LOG(ERROR, TAG, "Ownership transfer is complete but adding information to DB is failed.");
1076          }
1077     }
1078     else
1079     {
1080         OIC_LOG_V(INFO, TAG, "Error occured in provisionDefaultACLCB :: %d\n",
1081                             clientResponse->result);
1082         SetResult(otmCtx, clientResponse->result);
1083     }
1084
1085 exit:
1086     OIC_LOG_V(INFO, TAG, "OUT ReadyForNomalStatusHandler.");
1087     return OC_STACK_DELETE_TRANSACTION;
1088 }
1089
1090 static OCStackResult PostOwnerCredential(OTMContext_t* otmCtx)
1091 {
1092     OIC_LOG(DEBUG, TAG, "IN PostOwnerCredential");
1093
1094     if(!otmCtx || !otmCtx->selectedDeviceInfo)
1095     {
1096         OIC_LOG(ERROR, TAG, "Invalid parameters");
1097         return OC_STACK_INVALID_PARAM;
1098     }
1099
1100     OCProvisionDev_t* deviceInfo = otmCtx->selectedDeviceInfo;
1101     char query[MAX_URI_LENGTH + MAX_QUERY_LENGTH] = {0};
1102
1103     if(!PMGenerateQuery(true,
1104                         deviceInfo->endpoint.addr, deviceInfo->securePort,
1105                         deviceInfo->connType,
1106                         query, sizeof(query), OIC_RSRC_CRED_URI))
1107     {
1108         OIC_LOG(ERROR, TAG, "PostOwnerCredential : Failed to generate query");
1109         return OC_STACK_ERROR;
1110     }
1111     OIC_LOG_V(DEBUG, TAG, "Query=%s", query);
1112     OCSecurityPayload* secPayload = (OCSecurityPayload*)OICCalloc(1, sizeof(OCSecurityPayload));
1113     if(!secPayload)
1114     {
1115         OIC_LOG(ERROR, TAG, "Failed to memory allocation");
1116         return OC_STACK_NO_MEMORY;
1117     }
1118
1119     //Generate owner credential for new device
1120     secPayload->base.type = PAYLOAD_TYPE_SECURITY;
1121     const OicSecCred_t* ownerCredential = GetCredResourceData(&(deviceInfo->doxm->deviceID));
1122     if(!ownerCredential)
1123     {
1124         OIC_LOG(ERROR, TAG, "Can not find OwnerPSK.");
1125         return OC_STACK_NO_RESOURCE;
1126     }
1127
1128     OicUuid_t credSubjectId = {.id={0}};
1129     if(OC_STACK_OK == GetDoxmDeviceID(&credSubjectId))
1130     {
1131         OicSecCred_t newCredential;
1132         memcpy(&newCredential, ownerCredential, sizeof(OicSecCred_t));
1133         newCredential.next = NULL;
1134
1135         //Set subject ID as PT's ID
1136         memcpy(&(newCredential.subject), &credSubjectId, sizeof(OicUuid_t));
1137
1138         //Fill private data as empty string
1139         newCredential.privateData.data = "";
1140         newCredential.privateData.len = 0;
1141         newCredential.privateData.encoding = ownerCredential->privateData.encoding;
1142
1143         newCredential.publicData.data = NULL;
1144         newCredential.publicData.len = 0;
1145
1146         int secureFlag = 0;
1147         //Send owner credential to new device : POST /oic/sec/cred [ owner credential ]
1148         if (OC_STACK_OK != CredToCBORPayload(&newCredential, &secPayload->securityData,
1149                                         &secPayload->payloadSize, secureFlag))
1150         {
1151             OICFree(secPayload);
1152             OIC_LOG(ERROR, TAG, "Error while converting bin to cbor.");
1153             return OC_STACK_ERROR;
1154         }
1155         OIC_LOG(DEBUG, TAG, "Cred Payload:");
1156         OIC_LOG_BUFFER(DEBUG, TAG, secPayload->securityData, secPayload->payloadSize);
1157
1158         OCCallbackData cbData;
1159         cbData.cb = &OwnerCredentialHandler;
1160         cbData.context = (void *)otmCtx;
1161         cbData.cd = NULL;
1162         OCStackResult res = OCDoResource(NULL, OC_REST_POST, query,
1163                                          &deviceInfo->endpoint, (OCPayload*)secPayload,
1164                                          deviceInfo->connType, OC_HIGH_QOS, &cbData, NULL, 0);
1165         if (res != OC_STACK_OK)
1166         {
1167             OIC_LOG(ERROR, TAG, "OCStack resource error");
1168         }
1169     }
1170     else
1171     {
1172         OIC_LOG(ERROR, TAG, "Failed to read DOXM device ID.");
1173         return OC_STACK_NO_RESOURCE;
1174     }
1175
1176     OIC_LOG(DEBUG, TAG, "OUT PostOwnerCredential");
1177
1178     return OC_STACK_OK;
1179 }
1180
1181 static OicSecAcl_t* GenerateOwnerAcl(const OicUuid_t* owner)
1182 {
1183     OicSecAcl_t* ownerAcl = (OicSecAcl_t*)OICCalloc(1, sizeof(OicSecAcl_t));
1184     OicSecAce_t* ownerAce = (OicSecAce_t*)OICCalloc(1, sizeof(OicSecAce_t));
1185     OicSecRsrc_t* wildcardRsrc = (OicSecRsrc_t*)OICCalloc(1, sizeof(OicSecRsrc_t));
1186     if(NULL == ownerAcl || NULL == ownerAce || NULL == wildcardRsrc)
1187     {
1188         OIC_LOG(ERROR, TAG, "Failed to memory allocation");
1189         goto error;
1190     }
1191     LL_APPEND(ownerAcl->aces, ownerAce);
1192     LL_APPEND(ownerAce->resources, wildcardRsrc);
1193
1194     //Set resource owner as PT
1195     memcpy(ownerAcl->rownerID.id, owner->id, sizeof(owner->id));
1196
1197     //PT has full permission.
1198     ownerAce->permission = PERMISSION_FULL_CONTROL;
1199
1200     //Set subject as PT's UUID
1201     memcpy(ownerAce->subjectuuid.id, owner->id, sizeof(owner->id));
1202
1203     wildcardRsrc->href = OICStrdup(WILDCARD_RESOURCE_URI);
1204     if(NULL == wildcardRsrc->href)
1205     {
1206         goto error;
1207     }
1208
1209     wildcardRsrc->interfaceLen = 1;
1210     wildcardRsrc->interfaces = (char**)OICMalloc(wildcardRsrc->interfaceLen * sizeof(char*));
1211     if(NULL == wildcardRsrc->interfaces)
1212     {
1213         goto error;
1214     }
1215     wildcardRsrc->interfaces[0] = OICStrdup(WILDCARD_RESOURCE_URI);
1216     if(NULL == wildcardRsrc->interfaces[0])
1217     {
1218         goto error;
1219     }
1220
1221     wildcardRsrc->typeLen = 1;
1222     wildcardRsrc->types = (char**)OICMalloc(wildcardRsrc->typeLen * sizeof(char*));
1223     if(NULL == wildcardRsrc->types)
1224     {
1225         goto error;
1226     }
1227     wildcardRsrc->types[0] = OICStrdup(WILDCARD_RESOURCE_URI);
1228     if(NULL == wildcardRsrc->types[0])
1229     {
1230         goto error;
1231     }
1232
1233     return ownerAcl;
1234
1235 error:
1236     //in case of memory allocation failed, each resource should be removed individually.
1237     if(NULL == ownerAcl || NULL == ownerAce || NULL == wildcardRsrc)
1238     {
1239         OICFree(ownerAcl);
1240         OICFree(ownerAce);
1241         OICFree(wildcardRsrc);
1242     }
1243     else
1244     {
1245         DeleteACLList(ownerAcl);
1246     }
1247     return NULL;
1248 }
1249
1250 /**
1251  * Function to update the owner ACL to new device.
1252  *
1253  * @param[in]  otmCtx  Context value of ownership transfer.
1254  * @return  OC_STACK_OK on success
1255  */
1256 static OCStackResult PostOwnerAcl(OTMContext_t* otmCtx)
1257 {
1258     OCStackResult res = OC_STACK_ERROR;
1259
1260     OIC_LOG(DEBUG, TAG, "IN PostOwnerAcl");
1261
1262     if(!otmCtx || !otmCtx->selectedDeviceInfo)
1263     {
1264         OIC_LOG(ERROR, TAG, "Invalid parameters");
1265         return OC_STACK_INVALID_PARAM;
1266     }
1267
1268     OCProvisionDev_t* deviceInfo = otmCtx->selectedDeviceInfo;
1269     char query[MAX_URI_LENGTH + MAX_QUERY_LENGTH] = {0};
1270     OicSecAcl_t* ownerAcl = NULL;
1271
1272     if(!PMGenerateQuery(true,
1273                         deviceInfo->endpoint.addr, deviceInfo->securePort,
1274                         deviceInfo->connType,
1275                         query, sizeof(query), OIC_RSRC_ACL_URI))
1276     {
1277         OIC_LOG(ERROR, TAG, "Failed to generate query");
1278         return OC_STACK_ERROR;
1279     }
1280     OIC_LOG_V(DEBUG, TAG, "Query=%s", query);
1281
1282     OicUuid_t ownerID;
1283     res = GetDoxmDeviceID(&ownerID);
1284     if(OC_STACK_OK != res)
1285     {
1286         OIC_LOG(ERROR, TAG, "Failed to generate owner ACL");
1287         return res;
1288     }
1289
1290     //Generate owner ACL for new device
1291     ownerAcl = GenerateOwnerAcl(&ownerID);
1292     if(NULL == ownerAcl)
1293     {
1294         OIC_LOG(ERROR, TAG, "Failed to generate owner ACL");
1295         return OC_STACK_NO_MEMORY;
1296     }
1297
1298     //Generate ACL payload
1299     OCSecurityPayload* secPayload = (OCSecurityPayload*)OICCalloc(1, sizeof(OCSecurityPayload));
1300     if(!secPayload)
1301     {
1302         OIC_LOG(ERROR, TAG, "Failed to memory allocation");
1303         res = OC_STACK_NO_MEMORY;
1304         goto error;
1305     }
1306
1307     res = AclToCBORPayload(ownerAcl, &secPayload->securityData, &secPayload->payloadSize);
1308     if (OC_STACK_OK != res)
1309     {
1310         OICFree(secPayload);
1311         OIC_LOG(ERROR, TAG, "Error while converting bin to cbor.");
1312         goto error;
1313     }
1314     secPayload->base.type = PAYLOAD_TYPE_SECURITY;
1315
1316     OIC_LOG(DEBUG, TAG, "Owner ACL Payload:");
1317     OIC_LOG_BUFFER(DEBUG, TAG, secPayload->securityData, secPayload->payloadSize);
1318
1319     //Send owner ACL to new device : POST /oic/sec/cred [ owner credential ]
1320     OCCallbackData cbData;
1321     cbData.cb = &OwnerAclHandler;
1322     cbData.context = (void *)otmCtx;
1323     cbData.cd = NULL;
1324     res = OCDoResource(NULL, OC_REST_POST, query,
1325                                      &deviceInfo->endpoint, (OCPayload*)secPayload,
1326                                      deviceInfo->connType, OC_HIGH_QOS, &cbData, NULL, 0);
1327     if (res != OC_STACK_OK)
1328     {
1329         OIC_LOG(ERROR, TAG, "OCStack resource error");
1330         goto error;
1331     }
1332
1333     OIC_LOG(DEBUG, TAG, "OUT PostOwnerAcl");
1334
1335 error:
1336     DeleteACLList(ownerAcl);
1337
1338     return OC_STACK_OK;
1339 }
1340
1341 static OCStackResult PostOwnerTransferModeToResource(OTMContext_t* otmCtx)
1342 {
1343     OIC_LOG(DEBUG, TAG, "IN PostOwnerTransferModeToResource");
1344
1345     if(!otmCtx || !otmCtx->selectedDeviceInfo)
1346     {
1347         OIC_LOG(ERROR, TAG, "Invalid parameters");
1348         return OC_STACK_INVALID_PARAM;
1349     }
1350
1351     OCProvisionDev_t* deviceInfo = otmCtx->selectedDeviceInfo;
1352     OicSecOxm_t selectedOxm = deviceInfo->doxm->oxmSel;
1353     char query[MAX_URI_LENGTH + MAX_QUERY_LENGTH] = {0};
1354
1355     if(!PMGenerateQuery(false,
1356                         deviceInfo->endpoint.addr, deviceInfo->endpoint.port,
1357                         deviceInfo->connType,
1358                         query, sizeof(query), OIC_RSRC_DOXM_URI))
1359     {
1360         OIC_LOG(ERROR, TAG, "PostOwnerTransferModeToResource : Failed to generate query");
1361         return OC_STACK_ERROR;
1362     }
1363     OIC_LOG_V(DEBUG, TAG, "Query=%s", query);
1364
1365     OCSecurityPayload* secPayload = (OCSecurityPayload*)OICCalloc(1, sizeof(OCSecurityPayload));
1366     if(!secPayload)
1367     {
1368         OIC_LOG(ERROR, TAG, "Failed to memory allocation");
1369         return OC_STACK_NO_MEMORY;
1370     }
1371
1372     secPayload->base.type = PAYLOAD_TYPE_SECURITY;
1373     OCStackResult res = otmCtx->otmCallback.createSelectOxmPayloadCB(otmCtx,
1374             &secPayload->securityData, &secPayload->payloadSize);
1375     if (OC_STACK_OK != res && NULL == secPayload->securityData)
1376     {
1377         OCPayloadDestroy((OCPayload *)secPayload);
1378         OIC_LOG(ERROR, TAG, "Error while converting bin to cbor");
1379         return OC_STACK_ERROR;
1380     }
1381
1382     OCCallbackData cbData;
1383     cbData.cb = &OwnerTransferModeHandler;
1384     cbData.context = (void *)otmCtx;
1385     cbData.cd = NULL;
1386     res = OCDoResource(NULL, OC_REST_POST, query,
1387                        &deviceInfo->endpoint, (OCPayload *)secPayload,
1388                        deviceInfo->connType, OC_HIGH_QOS, &cbData, NULL, 0);
1389     if (res != OC_STACK_OK)
1390     {
1391         OIC_LOG(ERROR, TAG, "OCStack resource error");
1392     }
1393
1394     OIC_LOG(DEBUG, TAG, "OUT PostOwnerTransferModeToResource");
1395
1396     return res;
1397 }
1398
1399 static OCStackResult GetProvisioningStatusResource(OTMContext_t* otmCtx)
1400 {
1401     OIC_LOG(DEBUG, TAG, "IN GetProvisioningStatusResource");
1402
1403     if(!otmCtx || !otmCtx->selectedDeviceInfo)
1404     {
1405         OIC_LOG(ERROR, TAG, "Invailed parameters");
1406         return OC_STACK_INVALID_PARAM;
1407     }
1408
1409     OCProvisionDev_t* deviceInfo = otmCtx->selectedDeviceInfo;
1410     char query[MAX_URI_LENGTH + MAX_QUERY_LENGTH] = {0};
1411     if(!PMGenerateQuery(false,
1412                         deviceInfo->endpoint.addr, deviceInfo->endpoint.port,
1413                         deviceInfo->connType,
1414                         query, sizeof(query), OIC_RSRC_PSTAT_URI))
1415     {
1416         OIC_LOG(ERROR, TAG, "GetProvisioningStatusResource : Failed to generate query");
1417         return OC_STACK_ERROR;
1418     }
1419     OIC_LOG_V(DEBUG, TAG, "Query=%s", query);
1420
1421     OCCallbackData cbData;
1422     cbData.cb = &ListMethodsHandler;
1423     cbData.context = (void *)otmCtx;
1424     cbData.cd = NULL;
1425     OCStackResult res = OCDoResource(NULL, OC_REST_GET, query, NULL, NULL,
1426                                      deviceInfo->connType, OC_HIGH_QOS, &cbData, NULL, 0);
1427     if (res != OC_STACK_OK)
1428     {
1429         OIC_LOG(ERROR, TAG, "OCStack resource error");
1430     }
1431
1432     OIC_LOG(DEBUG, TAG, "OUT GetProvisioningStatusResource");
1433
1434     return res;
1435 }
1436
1437 static OCStackResult PostOwnerUuid(OTMContext_t* otmCtx)
1438 {
1439     OIC_LOG(DEBUG, TAG, "IN PostOwnerUuid");
1440
1441     if(!otmCtx || !otmCtx->selectedDeviceInfo)
1442     {
1443         OIC_LOG(ERROR, TAG, "Invailed parameters");
1444         return OC_STACK_INVALID_PARAM;
1445     }
1446
1447     OCProvisionDev_t* deviceInfo = otmCtx->selectedDeviceInfo;
1448     char query[MAX_URI_LENGTH + MAX_QUERY_LENGTH] = {0};
1449     if(!PMGenerateQuery(true,
1450                         deviceInfo->endpoint.addr, deviceInfo->securePort,
1451                         deviceInfo->connType,
1452                         query, sizeof(query), OIC_RSRC_DOXM_URI))
1453     {
1454         OIC_LOG(ERROR, TAG, "PostOwnerUuid : Failed to generate query");
1455         return OC_STACK_ERROR;
1456     }
1457     OIC_LOG_V(DEBUG, TAG, "Query=%s", query);
1458
1459     //Post PT's uuid to new device
1460     OCSecurityPayload* secPayload = (OCSecurityPayload*)OICCalloc(1, sizeof(OCSecurityPayload));
1461     if(!secPayload)
1462     {
1463         OIC_LOG(ERROR, TAG, "Failed to memory allocation");
1464         return OC_STACK_NO_MEMORY;
1465     }
1466     secPayload->base.type = PAYLOAD_TYPE_SECURITY;
1467     OCStackResult res = otmCtx->otmCallback.createOwnerTransferPayloadCB(
1468             otmCtx, &secPayload->securityData, &secPayload->payloadSize);
1469     if (OC_STACK_OK != res && NULL == secPayload->securityData)
1470     {
1471         OCPayloadDestroy((OCPayload *)secPayload);
1472         OIC_LOG(ERROR, TAG, "Error while converting doxm bin to cbor.");
1473         return OC_STACK_INVALID_PARAM;
1474     }
1475     OIC_LOG_BUFFER(DEBUG, TAG, secPayload->securityData, secPayload->payloadSize);
1476
1477     OCCallbackData cbData;
1478     cbData.cb = &OwnerUuidUpdateHandler;
1479     cbData.context = (void *)otmCtx;
1480     cbData.cd = NULL;
1481
1482     res = OCDoResource(NULL, OC_REST_POST, query, 0, (OCPayload *)secPayload,
1483             deviceInfo->connType, OC_HIGH_QOS, &cbData, NULL, 0);
1484     if (res != OC_STACK_OK)
1485     {
1486         OIC_LOG(ERROR, TAG, "OCStack resource error");
1487     }
1488
1489     OIC_LOG(DEBUG, TAG, "OUT PostOwnerUuid");
1490
1491     return res;
1492 }
1493
1494 static OCStackResult PostOwnershipInformation(OTMContext_t* otmCtx)
1495 {
1496     OIC_LOG(DEBUG, TAG, "IN PostOwnershipInformation");
1497
1498     if(!otmCtx || !otmCtx->selectedDeviceInfo)
1499     {
1500         OIC_LOG(ERROR, TAG, "Invailed parameters");
1501         return OC_STACK_INVALID_PARAM;
1502     }
1503
1504     OCProvisionDev_t* deviceInfo = otmCtx->selectedDeviceInfo;
1505     char query[MAX_URI_LENGTH + MAX_QUERY_LENGTH] = {0};
1506     if(!PMGenerateQuery(true,
1507                         deviceInfo->endpoint.addr, deviceInfo->securePort,
1508                         deviceInfo->connType,
1509                         query, sizeof(query), OIC_RSRC_DOXM_URI))
1510     {
1511         OIC_LOG(ERROR, TAG, "PostOwnershipInformation : Failed to generate query");
1512         return OC_STACK_ERROR;
1513     }
1514     OIC_LOG_V(DEBUG, TAG, "Query=%s", query);
1515
1516     //OwnershipInformationHandler
1517     OCSecurityPayload *secPayload = (OCSecurityPayload*)OICCalloc(1, sizeof(OCSecurityPayload));
1518     if (!secPayload)
1519     {
1520         OIC_LOG(ERROR, TAG, "Failed to memory allocation");
1521         return OC_STACK_NO_MEMORY;
1522     }
1523
1524     otmCtx->selectedDeviceInfo->doxm->owned = true;
1525
1526     secPayload->base.type = PAYLOAD_TYPE_SECURITY;
1527     OCStackResult res = DoxmToCBORPayload(otmCtx->selectedDeviceInfo->doxm,
1528             &secPayload->securityData, &secPayload->payloadSize, true);
1529     if (OC_STACK_OK != res && NULL == secPayload->securityData)
1530     {
1531         OCPayloadDestroy((OCPayload *)secPayload);
1532         OIC_LOG(ERROR, TAG, "Error while converting doxm bin to json");
1533         return OC_STACK_INVALID_PARAM;
1534     }
1535
1536     OCCallbackData cbData;
1537     cbData.cb = &OwnershipInformationHandler;
1538     cbData.context = (void *)otmCtx;
1539     cbData.cd = NULL;
1540
1541     res = OCDoResource(NULL, OC_REST_POST, query, 0, (OCPayload*)secPayload,
1542                        deviceInfo->connType, OC_HIGH_QOS, &cbData, NULL, 0);
1543     if (res != OC_STACK_OK)
1544     {
1545         OIC_LOG(ERROR, TAG, "OCStack resource error");
1546     }
1547
1548     OIC_LOG(DEBUG, TAG, "OUT PostOwnershipInformation");
1549
1550     return res;
1551 }
1552
1553 static OCStackResult PostUpdateOperationMode(OTMContext_t* otmCtx)
1554 {
1555     OIC_LOG(DEBUG, TAG, "IN PostUpdateOperationMode");
1556
1557     if(!otmCtx || !otmCtx->selectedDeviceInfo)
1558     {
1559         return OC_STACK_INVALID_PARAM;
1560     }
1561
1562     OCProvisionDev_t* deviceInfo = otmCtx->selectedDeviceInfo;
1563     char query[MAX_URI_LENGTH + MAX_QUERY_LENGTH] = {0};
1564     if(!PMGenerateQuery(false,
1565                         deviceInfo->endpoint.addr, deviceInfo->endpoint.port,
1566                         deviceInfo->connType,
1567                         query, sizeof(query), OIC_RSRC_PSTAT_URI))
1568     {
1569         OIC_LOG(ERROR, TAG, "PostUpdateOperationMode : Failed to generate query");
1570         return OC_STACK_ERROR;
1571     }
1572     OIC_LOG_V(DEBUG, TAG, "Query=%s", query);
1573
1574     OCSecurityPayload* secPayload = (OCSecurityPayload*)OICCalloc(1, sizeof(OCSecurityPayload));
1575     if(!secPayload)
1576     {
1577         OIC_LOG(ERROR, TAG, "Failed to memory allocation");
1578         return OC_STACK_NO_MEMORY;
1579     }
1580     secPayload->base.type = PAYLOAD_TYPE_SECURITY;
1581     OCStackResult res = PstatToCBORPayload(deviceInfo->pstat, &secPayload->securityData,
1582                                            &secPayload->payloadSize, true);
1583    if (OC_STACK_OK != res)
1584     {
1585         OCPayloadDestroy((OCPayload *)secPayload);
1586         OIC_LOG(ERROR, TAG, "Error while converting pstat to cbor.");
1587         return OC_STACK_INVALID_PARAM;
1588     }
1589
1590     OCCallbackData cbData;
1591     cbData.cb = &OperationModeUpdateHandler;
1592     cbData.context = (void *)otmCtx;
1593     cbData.cd = NULL;
1594     res = OCDoResource(NULL, OC_REST_POST, query, 0, (OCPayload *)secPayload,
1595                        deviceInfo->connType, OC_HIGH_QOS, &cbData, NULL, 0);
1596     if (res != OC_STACK_OK)
1597     {
1598         OIC_LOG(ERROR, TAG, "OCStack resource error");
1599     }
1600
1601     OIC_LOG(DEBUG, TAG, "OUT PostUpdateOperationMode");
1602
1603     return res;
1604 }
1605
1606 static OCStackResult StartOwnershipTransfer(void* ctx, OCProvisionDev_t* selectedDevice)
1607 {
1608     OIC_LOG(INFO, TAG, "IN StartOwnershipTransfer");
1609     OCStackResult res = OC_STACK_INVALID_PARAM;
1610
1611     VERIFY_NON_NULL(TAG, selectedDevice, ERROR);
1612     VERIFY_NON_NULL(TAG, selectedDevice->doxm, ERROR);
1613
1614     OTMContext_t* otmCtx = (OTMContext_t*)ctx;
1615     otmCtx->selectedDeviceInfo = selectedDevice;
1616
1617     //Set to the lowest level OxM, and then find more higher level OxM.
1618     res = SelectProvisioningMethod(selectedDevice->doxm->oxm,
1619                                    selectedDevice->doxm->oxmLen,
1620                                    &selectedDevice->doxm->oxmSel);
1621     if(OC_STACK_OK != res)
1622     {
1623         OIC_LOG(ERROR, TAG, "Failed to select the provisioning method");
1624         SetResult(otmCtx, res);
1625         return res;
1626     }
1627     OIC_LOG_V(DEBUG, TAG, "Selected provisoning method = %d", selectedDevice->doxm->oxmSel);
1628
1629     res = OTMSetOTCallback(selectedDevice->doxm->oxmSel, &otmCtx->otmCallback);
1630     if(OC_STACK_OK != res)
1631     {
1632         OIC_LOG_V(ERROR, TAG, "Error in OTMSetOTCallback : %d", res);
1633         return res;
1634     }
1635
1636     //Send Req: POST /oic/sec/doxm [{..."OxmSel" :g_OTMCbDatas[Index of Selected OxM].OXMString,...}]
1637     res = PostOwnerTransferModeToResource(otmCtx);
1638     if(OC_STACK_OK != res)
1639     {
1640         OIC_LOG(WARNING, TAG, "Failed to select the provisioning method");
1641         SetResult(otmCtx, res);
1642         return res;
1643     }
1644
1645 #if defined(__WITH_DTLS__) || defined(__WITH_TLS__)
1646     //Register TLS event handler to catch the tls event while handshake
1647     if(CA_STATUS_OK != CAregisterSslHandshakeCallback(DTLSHandshakeCB))
1648     {
1649         OIC_LOG(WARNING, TAG, "StartOwnershipTransfer : Failed to register TLS handshake callback.");
1650     }
1651 #endif // __WITH_DTLS__ or __WITH_TLS__
1652     OIC_LOG(INFO, TAG, "OUT StartOwnershipTransfer");
1653
1654 exit:
1655     return res;
1656 }
1657
1658 OCStackResult OTMSetOwnershipTransferCallbackData(OicSecOxm_t oxmType, OTMCallbackData_t* data)
1659 {
1660     OIC_LOG(DEBUG, TAG, "IN OTMSetOwnerTransferCallbackData");
1661
1662     if(!data)
1663     {
1664         OIC_LOG(ERROR, TAG, "OTMSetOwnershipTransferCallbackData : Invalid parameters");
1665         return OC_STACK_INVALID_PARAM;
1666     }
1667     if(oxmType >= OIC_OXM_COUNT)
1668     {
1669         OIC_LOG(INFO, TAG, "Unknow ownership transfer method");
1670         return OC_STACK_INVALID_PARAM;
1671     }
1672
1673     // TODO: Remove this API, Please see the jira ticket IOT-1484
1674
1675     OIC_LOG(DEBUG, TAG, "OUT OTMSetOwnerTransferCallbackData");
1676
1677     return OC_STACK_OK;
1678 }
1679
1680 /**
1681  * NOTE : Unowned discovery should be done before performing OTMDoOwnershipTransfer
1682  */
1683 OCStackResult OTMDoOwnershipTransfer(void* ctx,
1684                                      OCProvisionDev_t *selectedDevicelist,
1685                                      OCProvisionResultCB resultCallback)
1686 {
1687     OIC_LOG(DEBUG, TAG, "IN OTMDoOwnershipTransfer");
1688
1689     if (NULL == selectedDevicelist)
1690     {
1691         return OC_STACK_INVALID_PARAM;
1692     }
1693     if (NULL == resultCallback)
1694     {
1695         return OC_STACK_INVALID_CALLBACK;
1696     }
1697
1698     OTMContext_t* otmCtx = (OTMContext_t*)OICCalloc(1,sizeof(OTMContext_t));
1699     if(!otmCtx)
1700     {
1701         OIC_LOG(ERROR, TAG, "Failed to create OTM Context");
1702         return OC_STACK_NO_MEMORY;
1703     }
1704     otmCtx->ctxResultCallback = resultCallback;
1705     otmCtx->ctxHasError = false;
1706     otmCtx->userCtx = ctx;
1707     OCProvisionDev_t* pCurDev = selectedDevicelist;
1708
1709     //Counting number of selected devices.
1710     otmCtx->ctxResultArraySize = 0;
1711     while(NULL != pCurDev)
1712     {
1713         otmCtx->ctxResultArraySize++;
1714         pCurDev = pCurDev->next;
1715     }
1716
1717     otmCtx->ctxResultArray =
1718         (OCProvisionResult_t*)OICCalloc(otmCtx->ctxResultArraySize, sizeof(OCProvisionResult_t));
1719     if(NULL == otmCtx->ctxResultArray)
1720     {
1721         OIC_LOG(ERROR, TAG, "OTMDoOwnershipTransfer : Failed to memory allocation");
1722         OICFree(otmCtx);
1723         return OC_STACK_NO_MEMORY;
1724     }
1725     pCurDev = selectedDevicelist;
1726
1727     OCStackResult res = OC_STACK_OK;
1728     //Fill the device UUID for result array.
1729     for(size_t devIdx = 0; devIdx < otmCtx->ctxResultArraySize; devIdx++)
1730     {
1731         //Checking duplication of Device ID.
1732         bool isDuplicate = true;
1733         res = PDMIsDuplicateDevice(&pCurDev->doxm->deviceID, &isDuplicate);
1734         if (OC_STACK_OK != res)
1735         {
1736             goto error;
1737         }
1738         if (isDuplicate)
1739         {
1740             bool isStale = false;
1741             res = PDMIsDeviceStale(&pCurDev->doxm->deviceID, &isStale);
1742             if(OC_STACK_OK != res)
1743             {
1744                 OIC_LOG(ERROR, TAG, "Internal error in PDMIsDeviceStale");
1745                 goto error;
1746             }
1747             if(isStale)
1748             {
1749                 OIC_LOG(INFO, TAG, "Detected duplicated UUID in stale status, "\
1750                                    "this UUID will be removed from PDM");
1751
1752                 res = PDMDeleteDevice(&pCurDev->doxm->deviceID);
1753                 if(OC_STACK_OK != res)
1754                 {
1755                     OIC_LOG(ERROR, TAG, "Internal error in PDMDeleteDevice");
1756                     goto error;
1757                 }
1758             }
1759             else
1760             {
1761                 OIC_LOG(ERROR, TAG, "OTMDoOwnershipTransfer : Device UUID is duplicated");
1762                 res = OC_STACK_INVALID_PARAM;
1763                 goto error;
1764             }
1765         }
1766         memcpy(otmCtx->ctxResultArray[devIdx].deviceId.id,
1767                pCurDev->doxm->deviceID.id,
1768                UUID_LENGTH);
1769         otmCtx->ctxResultArray[devIdx].res = OC_STACK_CONTINUE;
1770         pCurDev = pCurDev->next;
1771     }
1772
1773     StartOwnershipTransfer(otmCtx, selectedDevicelist);
1774
1775     OIC_LOG(DEBUG, TAG, "OUT OTMDoOwnershipTransfer");
1776     return OC_STACK_OK;
1777
1778 error:
1779     OICFree(otmCtx->ctxResultArray);
1780     OICFree(otmCtx);
1781     return res;
1782 }
1783
1784 OCStackResult PostProvisioningStatus(OTMContext_t* otmCtx)
1785 {
1786     OIC_LOG(INFO, TAG, "IN PostProvisioningStatus");
1787
1788     if(!otmCtx || !otmCtx->selectedDeviceInfo)
1789     {
1790         OIC_LOG(ERROR, TAG, "OTMContext is NULL");
1791         return OC_STACK_INVALID_PARAM;
1792     }
1793
1794     //Change the TAKE_OWNER bit of CM to 0.
1795     otmCtx->selectedDeviceInfo->pstat->cm &= (~TAKE_OWNER);
1796
1797     OCSecurityPayload *secPayload = (OCSecurityPayload *)OICCalloc(1, sizeof(OCSecurityPayload));
1798     if (!secPayload)
1799     {
1800         OIC_LOG(ERROR, TAG, "Failed to memory allocation");
1801         return OC_STACK_NO_MEMORY;
1802     }
1803     secPayload->base.type = PAYLOAD_TYPE_SECURITY;
1804     if (OC_STACK_OK != PstatToCBORPayload(otmCtx->selectedDeviceInfo->pstat,
1805             &secPayload->securityData, &secPayload->payloadSize, true))
1806     {
1807         OCPayloadDestroy((OCPayload *)secPayload);
1808         return OC_STACK_INVALID_JSON;
1809     }
1810     OIC_LOG(DEBUG, TAG, "Created payload for chage to Provisiong state");
1811     OIC_LOG_BUFFER(DEBUG, TAG, secPayload->securityData, secPayload->payloadSize);
1812
1813     char query[MAX_URI_LENGTH + MAX_QUERY_LENGTH] = {0};
1814     if(!PMGenerateQuery(true,
1815                         otmCtx->selectedDeviceInfo->endpoint.addr,
1816                         otmCtx->selectedDeviceInfo->securePort,
1817                         otmCtx->selectedDeviceInfo->connType,
1818                         query, sizeof(query), OIC_RSRC_PSTAT_URI))
1819     {
1820         OIC_LOG(ERROR, TAG, "PostProvisioningStatus : Failed to generate query");
1821         return OC_STACK_ERROR;
1822     }
1823     OIC_LOG_V(DEBUG, TAG, "Query=%s", query);
1824
1825     OCCallbackData cbData = {.context=NULL, .cb=NULL, .cd=NULL};
1826     cbData.cb = &ProvisioningStatusHandler;
1827     cbData.context = (void*)otmCtx;
1828     cbData.cd = NULL;
1829     OCStackResult ret = OCDoResource(NULL, OC_REST_POST, query, 0, (OCPayload*)secPayload,
1830             otmCtx->selectedDeviceInfo->connType, OC_HIGH_QOS, &cbData, NULL, 0);
1831     OIC_LOG_V(INFO, TAG, "OCDoResource returned: %d",ret);
1832     if (ret != OC_STACK_OK)
1833     {
1834         OIC_LOG(ERROR, TAG, "OCStack resource error");
1835     }
1836
1837     OIC_LOG(INFO, TAG, "OUT PostProvisioningStatus");
1838
1839     return ret;
1840 }
1841
1842 OCStackResult PostNormalOperationStatus(OTMContext_t* otmCtx)
1843 {
1844     OIC_LOG(INFO, TAG, "IN PostNormalOperationStatus");
1845
1846     if(!otmCtx || !otmCtx->selectedDeviceInfo)
1847     {
1848         OIC_LOG(ERROR, TAG, "OTMContext is NULL");
1849         return OC_STACK_INVALID_PARAM;
1850     }
1851
1852     //Set isop to true.
1853     otmCtx->selectedDeviceInfo->pstat->isOp = true;
1854
1855     OCSecurityPayload *secPayload = (OCSecurityPayload *)OICCalloc(1, sizeof(OCSecurityPayload));
1856     if (!secPayload)
1857     {
1858         OIC_LOG(ERROR, TAG, "Failed to memory allocation");
1859         return OC_STACK_NO_MEMORY;
1860     }
1861     secPayload->base.type = PAYLOAD_TYPE_SECURITY;
1862     if (OC_STACK_OK != PstatToCBORPayload(otmCtx->selectedDeviceInfo->pstat,
1863             &secPayload->securityData, &secPayload->payloadSize, true))
1864     {
1865         OCPayloadDestroy((OCPayload *)secPayload);
1866         return OC_STACK_INVALID_JSON;
1867     }
1868     OIC_LOG(DEBUG, TAG, "Created payload for chage to Provisiong state");
1869     OIC_LOG_BUFFER(DEBUG, TAG, secPayload->securityData, secPayload->payloadSize);
1870
1871     char query[MAX_URI_LENGTH + MAX_QUERY_LENGTH] = {0};
1872     if(!PMGenerateQuery(true,
1873                         otmCtx->selectedDeviceInfo->endpoint.addr,
1874                         otmCtx->selectedDeviceInfo->securePort,
1875                         otmCtx->selectedDeviceInfo->connType,
1876                         query, sizeof(query), OIC_RSRC_PSTAT_URI))
1877     {
1878         OIC_LOG(ERROR, TAG, "PostNormalOperationStatus : Failed to generate query");
1879         return OC_STACK_ERROR;
1880     }
1881     OIC_LOG_V(DEBUG, TAG, "Query=%s", query);
1882
1883     OCCallbackData cbData = {.context=NULL, .cb=NULL, .cd=NULL};
1884     cbData.cb = &ReadyForNomalStatusHandler;
1885     cbData.context = (void*)otmCtx;
1886     cbData.cd = NULL;
1887     OCStackResult ret = OCDoResource(NULL, OC_REST_POST, query, 0, (OCPayload*)secPayload,
1888             otmCtx->selectedDeviceInfo->connType, OC_HIGH_QOS, &cbData, NULL, 0);
1889     OIC_LOG_V(INFO, TAG, "OCDoResource returned: %d",ret);
1890     if (ret != OC_STACK_OK)
1891     {
1892         OIC_LOG(ERROR, TAG, "OCStack resource error");
1893     }
1894
1895     OIC_LOG(INFO, TAG, "OUT PostNormalOperationStatus");
1896
1897     return ret;
1898 }