Sync-up to Changed RAML spec v1.1
[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  * Number of supported provisioning methods
73  * current version supports only one.
74  */
75 static size_t gNumOfProvisioningMethodsPT = 1;
76
77 /**
78  * Variables for pointing the OTMContext to be used in the DTLS handshake result callback.
79  */
80 static OTMContext_t* g_otmCtx = NULL;
81
82 /**
83  * Function to select appropriate  provisioning method.
84  *
85  * @param[in] supportedMethods   Array of supported methods
86  * @param[in] numberOfMethods   number of supported methods
87  * @param[out]  selectedMethod         Selected methods
88  * @return  OC_STACK_OK on success
89  */
90 static OCStackResult SelectProvisioningMethod(const OicSecOxm_t *supportedMethods,
91         size_t numberOfMethods, OicSecOxm_t *selectedMethod)
92 {
93     OIC_LOG(DEBUG, TAG, "IN SelectProvisioningMethod");
94
95     if(numberOfMethods == 0 || !supportedMethods)
96     {
97         OIC_LOG(WARNING, TAG, "Could not find a supported OxM.");
98         return OC_STACK_ERROR;
99     }
100
101     *selectedMethod  = supportedMethods[0];
102     for(size_t i = 0; i < numberOfMethods; i++)
103     {
104         if(*selectedMethod < supportedMethods[i])
105         {
106             *selectedMethod =  supportedMethods[i];
107         }
108     }
109
110     return OC_STACK_OK;
111 }
112
113 /**
114  * Function to select operation mode.This function will return most secure common operation mode.
115  *
116  * @param[in] selectedDeviceInfo   selected device information to performing provisioning.
117  * @param[out]   selectedMode   selected operation mode
118  * @return  OC_STACK_OK on success
119  */
120 static void SelectOperationMode(const OCProvisionDev_t *selectedDeviceInfo,
121                                 OicSecDpom_t *selectedMode)
122 {
123     OIC_LOG(DEBUG, TAG, "IN SelectOperationMode");
124     *selectedMode = selectedDeviceInfo->pstat->sm[0];
125     OIC_LOG_V(DEBUG, TAG, "Selected Operation Mode = %d", *selectedMode);
126 }
127
128 /**
129  * Function to start ownership transfer.
130  * This function will send the first request for provisioning,
131  * The next request message is sent from the response handler for this request.
132  *
133  * @param[in] ctx   context value passed to callback from calling function.
134  * @param[in] selectedDevice   selected device information to performing provisioning.
135  * @return  OC_STACK_OK on success
136  */
137 static OCStackResult StartOwnershipTransfer(void* ctx, OCProvisionDev_t* selectedDevice);
138
139 /**
140  * Function to update owner transfer mode
141  *
142  * @param[in]  otmCtx  Context value of ownership transfer.
143  * @return  OC_STACK_OK on success
144  */
145 static OCStackResult PutOwnerTransferModeToResource(OTMContext_t* otmCtx);
146
147 /**
148  * Function to send request to resource to get its pstat resource information.
149  *
150  * @param[in]  otmCtx  Context value of ownership transfer.
151  * @return  OC_STACK_OK on success
152  */
153 static OCStackResult GetProvisioningStatusResource(OTMContext_t* otmCtx);
154
155
156 /**
157  * Function to send  uuid of owner device to new device.
158  * This function would update 'owner of doxm' as UUID for provisioning tool.
159  *
160  * @param[in]  otmCtx  Context value of ownership transfer.
161  * @return  OC_STACK_OK on success
162  */
163 static OCStackResult PutOwnerUuid(OTMContext_t* otmCtx);
164
165 /**
166  * Function to update the operation mode. As per the spec. Operation mode in client driven
167  * single service provisioning it will be updated to 0x3
168  *
169  * @param[in]  otmCtx  Context value of ownership transfer.
170  * @return  OC_STACK_OK on success
171  */
172 static OCStackResult PutUpdateOperationMode(OTMContext_t* otmCtx);
173
174 /**
175  * Function to update the owner credential to new device
176  *
177  * @param[in]  otmCtx  Context value of ownership transfer.
178  * @param[in] selectedOperationMode selected operation mode
179  * @return  OC_STACK_OK on success
180  */
181 static OCStackResult PutOwnerCredential(OTMContext_t* otmCtx);
182
183 /**
184  * Function to send ownerShip info.
185  * This function would update 'owned of doxm' as true.
186  *
187  * @param[in]  otmCtx  Context value of ownership transfer.
188  * @return  OC_STACK_OK on success
189  */
190 static OCStackResult PutOwnershipInformation(OTMContext_t* otmCtx);
191
192 /**
193  * Function to update pstat when finalize provisioning.
194  * This function would update 'cm' as bx0011,1100 and 'tm' as bx0000,0000.
195  *
196  * @param[in] ctx   context value passed to callback from calling function.
197  * @param[in] selectedDevice   selected device information to performing provisioning.
198  * @return  OC_STACK_OK on success
199  */
200 static OCStackResult PutProvisioningStatus(OTMContext_t* otmCtx);
201
202 static bool IsComplete(OTMContext_t* otmCtx)
203 {
204     for(size_t i = 0; i < otmCtx->ctxResultArraySize; i++)
205     {
206         if(OC_STACK_CONTINUE == otmCtx->ctxResultArray[i].res)
207         {
208             return false;
209         }
210     }
211
212     return true;
213 }
214
215 /**
216  * Function to save the result of provisioning.
217  *
218  * @param[in,out] otmCtx   Context value of ownership transfer.
219  * @param[in] res   result of provisioning
220  */
221 static void SetResult(OTMContext_t* otmCtx, const OCStackResult res)
222 {
223     OIC_LOG_V(DEBUG, TAG, "IN SetResult : %d ", res);
224
225     if(!otmCtx)
226     {
227         OIC_LOG(WARNING, TAG, "OTMContext is NULL");
228         return;
229     }
230
231     if(otmCtx->selectedDeviceInfo)
232     {
233         //Revert psk_info callback and new deivce uuid in case of random PIN OxM
234         if(OIC_RANDOM_DEVICE_PIN == otmCtx->selectedDeviceInfo->doxm->oxmSel)
235         {
236             if(CA_STATUS_OK != CARegisterDTLSCredentialsHandler(GetDtlsPskCredentials))
237             {
238                 OIC_LOG(WARNING, TAG, "Failed to revert  is DTLS credential handler.");
239             }
240             OicUuid_t emptyUuid = { .id={0}};
241             SetUuidForRandomPinOxm(&emptyUuid);
242         }
243
244         for(size_t i = 0; i < otmCtx->ctxResultArraySize; i++)
245         {
246             if(memcmp(otmCtx->selectedDeviceInfo->doxm->deviceID.id,
247                       otmCtx->ctxResultArray[i].deviceId.id, UUID_LENGTH) == 0)
248             {
249                 otmCtx->ctxResultArray[i].res = res;
250                 if(OC_STACK_OK != res)
251                 {
252                     otmCtx->ctxHasError = true;
253                 }
254             }
255         }
256
257         g_otmCtx = NULL;
258
259         //If all request is completed, invoke the user callback.
260         if(IsComplete(otmCtx))
261         {
262             otmCtx->ctxResultCallback(otmCtx->userCtx, otmCtx->ctxResultArraySize,
263                                        otmCtx->ctxResultArray, otmCtx->ctxHasError);
264             OICFree(otmCtx->ctxResultArray);
265             OICFree(otmCtx);
266         }
267         else
268         {
269             if(OC_STACK_OK != StartOwnershipTransfer(otmCtx,
270                                                      otmCtx->selectedDeviceInfo->next))
271             {
272                 OIC_LOG(ERROR, TAG, "Failed to StartOwnershipTransfer");
273             }
274         }
275     }
276
277     OIC_LOG(DEBUG, TAG, "OUT SetResult");
278 }
279
280 /**
281  * Function to handle the handshake result in OTM.
282  * This function will be invoked after DTLS handshake
283  * @param   endPoint  [IN] The remote endpoint.
284  * @param   errorInfo [IN] Error information from the endpoint.
285  * @return  NONE
286  */
287 void DTLSHandshakeCB(const CAEndpoint_t *endpoint, const CAErrorInfo_t *info)
288 {
289     if(NULL != g_otmCtx && NULL != g_otmCtx->selectedDeviceInfo &&
290        NULL != endpoint && NULL != info)
291     {
292         OIC_LOG_V(INFO, TAG, "Received status from remote device(%s:%d) : %d",
293                  endpoint->addr, endpoint->port, info->result);
294
295         OicSecDoxm_t* newDevDoxm = g_otmCtx->selectedDeviceInfo->doxm;
296
297         if(NULL != newDevDoxm)
298         {
299             OicUuid_t emptyUuid = {.id={0}};
300
301             //Make sure the address matches.
302             if(strncmp(g_otmCtx->selectedDeviceInfo->endpoint.addr,
303                endpoint->addr,
304                sizeof(endpoint->addr)) == 0 &&
305                g_otmCtx->selectedDeviceInfo->securePort == endpoint->port)
306             {
307                 OCStackResult res = OC_STACK_ERROR;
308
309                 //If temporal secure sesstion established successfully
310                 if(CA_STATUS_OK == info->result &&
311                    false == newDevDoxm->owned &&
312                    memcmp(&(newDevDoxm->owner), &emptyUuid, sizeof(OicUuid_t)) == 0)
313                 {
314                     //Send request : PUT /oic/sec/doxm [{... , "devowner":"PT's UUID"}]
315                     res = PutOwnerUuid(g_otmCtx);
316                     if(OC_STACK_OK != res)
317                     {
318                         OIC_LOG(ERROR, TAG, "OperationModeUpdate : Failed to send owner information");
319                         SetResult(g_otmCtx, res);
320                     }
321                 }
322                 //In case of authentication failure
323                 else if(CA_DTLS_AUTHENTICATION_FAILURE == info->result)
324                 {
325                     //in case of error from owner credential
326                     if(memcmp(&(newDevDoxm->owner), &emptyUuid, sizeof(OicUuid_t)) != 0 &&
327                         true == newDevDoxm->owned)
328                     {
329                         OIC_LOG(ERROR, TAG, "The owner credential may incorrect.");
330
331                         if(OC_STACK_OK != RemoveCredential(&(newDevDoxm->deviceID)))
332                         {
333                             OIC_LOG(WARNING, TAG, "Failed to remove the invaild owner credential");
334                         }
335                         SetResult(g_otmCtx, OC_STACK_AUTHENTICATION_FAILURE);
336                     }
337                     //in case of error from wrong PIN, re-start the ownership transfer
338                     else if(OIC_RANDOM_DEVICE_PIN == newDevDoxm->oxmSel)
339                     {
340                         OIC_LOG(ERROR, TAG, "The PIN number may incorrect.");
341
342                         memcpy(&(newDevDoxm->owner), &emptyUuid, sizeof(OicUuid_t));
343                         newDevDoxm->owned = false;
344                         g_otmCtx->attemptCnt++;
345
346                         if(WRONG_PIN_MAX_ATTEMP > g_otmCtx->attemptCnt)
347                         {
348                             res = StartOwnershipTransfer(g_otmCtx, g_otmCtx->selectedDeviceInfo);
349                             if(OC_STACK_OK != res)
350                             {
351                                 SetResult(g_otmCtx, res);
352                                 OIC_LOG(ERROR, TAG, "Failed to Re-StartOwnershipTransfer");
353                             }
354                         }
355                         else
356                         {
357                             OIC_LOG(ERROR, TAG, "User has exceeded the number of authentication attempts.");
358                             SetResult(g_otmCtx, OC_STACK_AUTHENTICATION_FAILURE);
359                         }
360                     }
361                     else
362                     {
363                         OIC_LOG(ERROR, TAG, "Failed to establish secure session.");
364                         SetResult(g_otmCtx, OC_STACK_AUTHENTICATION_FAILURE);
365                     }
366                 }
367             }
368         }
369     }
370 }
371
372 /**
373  * Function to save ownerPSK at provisioning tool end.
374  *
375  * @param[in] selectedDeviceInfo   selected device information to performing provisioning.
376  * @return  OC_STACK_OK on success
377  */
378 static OCStackResult SaveOwnerPSK(OCProvisionDev_t *selectedDeviceInfo)
379 {
380     OIC_LOG(DEBUG, TAG, "IN SaveOwnerPSK");
381
382     OCStackResult res = OC_STACK_ERROR;
383
384     CAEndpoint_t endpoint;
385     memset(&endpoint, 0x00, sizeof(CAEndpoint_t));
386     OICStrcpy(endpoint.addr, MAX_ADDR_STR_SIZE_CA, selectedDeviceInfo->endpoint.addr);
387     endpoint.addr[MAX_ADDR_STR_SIZE_CA - 1] = '\0';
388     endpoint.port = selectedDeviceInfo->securePort;
389
390     OicUuid_t ptDeviceID = {.id={0}};
391     if (OC_STACK_OK != GetDoxmDeviceID(&ptDeviceID))
392     {
393         OIC_LOG(ERROR, TAG, "Error while retrieving provisioning tool's device ID");
394         return res;
395     }
396
397     uint8_t ownerPSK[OWNER_PSK_LENGTH_128] = {0};
398     OicSecKey_t ownerKey = {ownerPSK, OWNER_PSK_LENGTH_128};
399
400     //Generating OwnerPSK
401     CAResult_t pskRet = CAGenerateOwnerPSK(&endpoint,
402             (uint8_t *)GetOxmString(selectedDeviceInfo->doxm->oxmSel),
403             strlen(GetOxmString(selectedDeviceInfo->doxm->oxmSel)),
404             ptDeviceID.id, sizeof(ptDeviceID.id),
405             selectedDeviceInfo->doxm->deviceID.id, sizeof(selectedDeviceInfo->doxm->deviceID.id),
406             ownerPSK, OWNER_PSK_LENGTH_128);
407
408     if (CA_STATUS_OK == pskRet)
409     {
410         OIC_LOG(INFO, TAG,"ownerPSK dump:\n");
411         OIC_LOG_BUFFER(INFO, TAG,ownerPSK, OWNER_PSK_LENGTH_128);
412         //Generating new credential for provisioning tool
413         size_t ownLen = 1;
414
415         OicSecCred_t *cred = GenerateCredential(&selectedDeviceInfo->doxm->deviceID,
416                 SYMMETRIC_PAIR_WISE_KEY, NULL,
417                 &ownerKey, ownLen, &ptDeviceID);
418         VERIFY_NON_NULL(TAG, cred, ERROR);
419
420         res = AddCredential(cred);
421         if(res != OC_STACK_OK)
422         {
423             DeleteCredList(cred);
424             return res;
425         }
426     }
427     else
428     {
429         OIC_LOG(ERROR, TAG, "CAGenerateOwnerPSK failed");
430     }
431
432     OIC_LOG(DEBUG, TAG, "OUT SaveOwnerPSK");
433 exit:
434     return res;
435 }
436
437 /**
438  * Callback handler for OwnerShipTransferModeHandler API.
439  *
440  * @param[in] ctx             ctx value passed to callback from calling function.
441  * @param[in] UNUSED          handle to an invocation
442  * @param[in] clientResponse  Response from queries to remote servers.
443  * @return  OC_STACK_DELETE_TRANSACTION to delete the transaction
444  *          and  OC_STACK_KEEP_TRANSACTION to keep it.
445  */
446 static OCStackApplicationResult OwnerTransferModeHandler(void *ctx, OCDoHandle UNUSED,
447                                                          OCClientResponse *clientResponse)
448 {
449     OIC_LOG(DEBUG, TAG, "IN OwnerTransferModeHandler");
450
451     VERIFY_NON_NULL(TAG, clientResponse, WARNING);
452     VERIFY_NON_NULL(TAG, ctx, WARNING);
453
454     OTMContext_t* otmCtx = (OTMContext_t*)ctx;
455     (void)UNUSED;
456     if(clientResponse->result == OC_STACK_OK)
457     {
458         OIC_LOG(INFO, TAG, "OwnerTransferModeHandler : response result = OC_STACK_OK");
459         //Send request : GET /oic/sec/pstat
460         OCStackResult res = GetProvisioningStatusResource(otmCtx);
461         if(OC_STACK_OK != res)
462         {
463             OIC_LOG(WARNING, TAG, "Failed to get pstat information");
464             SetResult(otmCtx, res);
465         }
466     }
467     else
468     {
469         OIC_LOG_V(WARNING, TAG, "OwnerTransferModeHandler : Client response is incorrect : %d",
470         clientResponse->result);
471         SetResult(otmCtx, clientResponse->result);
472     }
473
474     OIC_LOG(DEBUG, TAG, "OUT OwnerTransferModeHandler");
475
476 exit:
477     return  OC_STACK_DELETE_TRANSACTION;
478 }
479
480 /**
481  * Callback handler for ProvisioningStatusResouceHandler API.
482  *
483  * @param[in] ctx             ctx value passed to callback from calling function.
484  * @param[in] UNUSED          handle to an invocation
485  * @param[in] clientResponse  Response from queries to remote servers.
486  * @return  OC_STACK_DELETE_TRANSACTION to delete the transaction
487  *          and  OC_STACK_KEEP_TRANSACTION to keep it.
488  */
489 static OCStackApplicationResult ListMethodsHandler(void *ctx, OCDoHandle UNUSED,
490                                                     OCClientResponse *clientResponse)
491 {
492     OIC_LOG(DEBUG, TAG, "IN ListMethodsHandler");
493
494     VERIFY_NON_NULL(TAG, clientResponse, WARNING);
495     VERIFY_NON_NULL(TAG, ctx, WARNING);
496
497     OTMContext_t* otmCtx = (OTMContext_t*)ctx;
498     (void)UNUSED;
499     if  (OC_STACK_OK == clientResponse->result)
500     {
501         if  (NULL == clientResponse->payload)
502         {
503             OIC_LOG(INFO, TAG, "Skiping Null payload");
504             SetResult(otmCtx, OC_STACK_ERROR);
505             return OC_STACK_DELETE_TRANSACTION;
506         }
507
508         if (PAYLOAD_TYPE_SECURITY != clientResponse->payload->type)
509         {
510             OIC_LOG(INFO, TAG, "Unknown payload type");
511             SetResult(otmCtx, OC_STACK_ERROR);
512             return OC_STACK_DELETE_TRANSACTION;
513         }
514         OicSecPstat_t* pstat = NULL;
515         OCStackResult result = CBORPayloadToPstat(
516                 ((OCSecurityPayload*)clientResponse->payload)->securityData1,
517                 ((OCSecurityPayload*)clientResponse->payload)->payloadSize,
518                 &pstat);
519         if(NULL == pstat && result != OC_STACK_OK)
520         {
521             OIC_LOG(ERROR, TAG, "Error while converting cbor to pstat.");
522             SetResult(otmCtx, OC_STACK_ERROR);
523             return OC_STACK_DELETE_TRANSACTION;
524         }
525         if(false == (TAKE_OWNER & pstat->cm))
526         {
527             OIC_LOG(ERROR, TAG, "Device pairing mode enabling owner transfer operations is disabled");
528             SetResult(otmCtx, OC_STACK_ERROR);
529             return OC_STACK_DELETE_TRANSACTION;
530         }
531         otmCtx->selectedDeviceInfo->pstat = pstat;
532
533         //Select operation mode (Currently supported SINGLE_SERVICE_CLIENT_DRIVEN only)
534         SelectOperationMode(otmCtx->selectedDeviceInfo, &(otmCtx->selectedDeviceInfo->pstat->om));
535
536         //Send request : PUT /oic/sec/pstat [{"om":"bx11", .. }]
537         OCStackResult res = PutUpdateOperationMode(otmCtx);
538         if (OC_STACK_OK != res)
539         {
540             OIC_LOG(ERROR, TAG, "Error while updating operation mode.");
541             SetResult(otmCtx, res);
542         }
543     }
544     else
545     {
546         OIC_LOG_V(WARNING, TAG, "ListMethodsHandler : Client response is incorrect : %d",
547             clientResponse->result);
548         SetResult(otmCtx, clientResponse->result);
549     }
550
551     OIC_LOG(DEBUG, TAG, "OUT ListMethodsHandler");
552 exit:
553     return  OC_STACK_DELETE_TRANSACTION;
554 }
555
556 /**
557  * Response handler for update owner uuid request.
558  *
559  * @param[in] ctx             ctx value passed to callback from calling function.
560  * @param[in] UNUSED          handle to an invocation
561  * @param[in] clientResponse  Response from queries to remote servers.
562  * @return  OC_STACK_DELETE_TRANSACTION to delete the transaction
563  *          and  OC_STACK_KEEP_TRANSACTION to keep it.
564  */
565 static OCStackApplicationResult OwnerUuidUpdateHandler(void *ctx, OCDoHandle UNUSED,
566                                 OCClientResponse *clientResponse)
567 {
568     VERIFY_NON_NULL(TAG, clientResponse, WARNING);
569     VERIFY_NON_NULL(TAG, ctx, WARNING);
570
571     OIC_LOG(DEBUG, TAG, "IN OwnerUuidUpdateHandler");
572     (void)UNUSED;
573     OCStackResult res = OC_STACK_OK;
574     OTMContext_t* otmCtx = (OTMContext_t*)ctx;
575
576     if(OC_STACK_OK == clientResponse->result)
577     {
578         if(otmCtx && otmCtx->selectedDeviceInfo)
579         {
580             res = SaveOwnerPSK(otmCtx->selectedDeviceInfo);
581             if(OC_STACK_OK != res)
582             {
583                 OIC_LOG(ERROR, TAG, "OwnerUuidUpdateHandler:Failed to owner PSK generation");
584                 SetResult(otmCtx, res);
585                 return OC_STACK_DELETE_TRANSACTION;
586             }
587
588             //PUT owner credential to new device according to security spec B.
589             res = PutOwnerCredential(otmCtx);
590             if(OC_STACK_OK != res)
591             {
592                 OIC_LOG(ERROR, TAG,
593                         "OwnerUuidUpdateHandler:Failed to send PUT request for onwer credential");
594                 SetResult(otmCtx, res);
595                 return OC_STACK_DELETE_TRANSACTION;
596             }
597         }
598     }
599     else
600     {
601         res = clientResponse->result;
602         OIC_LOG_V(ERROR, TAG, "OwnerUuidHandler : Unexpected result %d", res);
603         SetResult(otmCtx, res);
604     }
605
606     OIC_LOG(DEBUG, TAG, "OUT OwnerUuidUpdateHandler");
607
608 exit:
609     return  OC_STACK_DELETE_TRANSACTION;
610 }
611
612 /**
613  * Response handler for update operation mode.
614  *
615  * @param[in] ctx             ctx value passed to callback from calling function.
616  * @param[in] UNUSED          handle to an invocation
617  * @param[in] clientResponse  Response from queries to remote servers.
618  * @return  OC_STACK_DELETE_TRANSACTION to delete the transaction
619  *          and  OC_STACK_KEEP_TRANSACTION to keep it.
620  */
621 static OCStackApplicationResult OperationModeUpdateHandler(void *ctx, OCDoHandle UNUSED,
622                                 OCClientResponse *clientResponse)
623 {
624     OIC_LOG(DEBUG, TAG, "IN OperationModeUpdateHandler");
625
626     VERIFY_NON_NULL(TAG, clientResponse, WARNING);
627     VERIFY_NON_NULL(TAG, ctx, WARNING);
628
629     OTMContext_t* otmCtx = (OTMContext_t*)ctx;
630     (void) UNUSED;
631     if  (OC_STACK_OK == clientResponse->result)
632     {
633         OCStackResult res = OC_STACK_ERROR;
634         OicSecOxm_t selOxm = otmCtx->selectedDeviceInfo->doxm->oxmSel;
635         //DTLS Handshake
636         //Load secret for temporal secure session.
637         if(g_OTMDatas[selOxm].loadSecretCB)
638         {
639             res = g_OTMDatas[selOxm].loadSecretCB(otmCtx);
640             if(OC_STACK_OK != res)
641             {
642                 OIC_LOG(ERROR, TAG, "OperationModeUpdate : Failed to load secret");
643                 SetResult(otmCtx, res);
644                 return  OC_STACK_DELETE_TRANSACTION;
645             }
646         }
647
648         //It will be used in handshake event handler
649         g_otmCtx = otmCtx;
650
651         //Try DTLS handshake to generate secure session
652         if(g_OTMDatas[selOxm].createSecureSessionCB)
653         {
654             res = g_OTMDatas[selOxm].createSecureSessionCB(otmCtx);
655             if(OC_STACK_OK != res)
656             {
657                 OIC_LOG(ERROR, TAG, "OperationModeUpdate : Failed to create DTLS session");
658                 SetResult(otmCtx, res);
659                 return OC_STACK_DELETE_TRANSACTION;
660             }
661         }
662     }
663     else
664     {
665         OIC_LOG(ERROR, TAG, "Error while update operation mode");
666         SetResult(otmCtx, clientResponse->result);
667     }
668
669     OIC_LOG(DEBUG, TAG, "OUT OperationModeUpdateHandler");
670
671 exit:
672     return  OC_STACK_DELETE_TRANSACTION;
673 }
674
675 /**
676  * Response handler for update owner crendetial request.
677  *
678  * @param[in] ctx             ctx value passed to callback from calling function.
679  * @param[in] UNUSED          handle to an invocation
680  * @param[in] clientResponse  Response from queries to remote servers.
681  * @return  OC_STACK_DELETE_TRANSACTION to delete the transaction
682  *          and  OC_STACK_KEEP_TRANSACTION to keep it.
683  */
684 static OCStackApplicationResult OwnerCredentialHandler(void *ctx, OCDoHandle UNUSED,
685                                 OCClientResponse *clientResponse)
686 {
687     VERIFY_NON_NULL(TAG, clientResponse, WARNING);
688     VERIFY_NON_NULL(TAG, ctx, WARNING);
689
690     OIC_LOG(DEBUG, TAG, "IN OwnerCredentialHandler");
691     (void)UNUSED;
692     OCStackResult res = OC_STACK_OK;
693     OTMContext_t* otmCtx = (OTMContext_t*)ctx;
694
695     if(OC_STACK_RESOURCE_CREATED == clientResponse->result)
696     {
697         if(otmCtx && otmCtx->selectedDeviceInfo)
698         {
699             //Close the temporal secure session to verify the owner credential
700             CAEndpoint_t* endpoint = (CAEndpoint_t *)&otmCtx->selectedDeviceInfo->endpoint;
701             endpoint->port = otmCtx->selectedDeviceInfo->securePort;
702             CAResult_t caResult = CACloseDtlsSession(endpoint);
703             if(CA_STATUS_OK != caResult)
704             {
705                 OIC_LOG(ERROR, TAG, "Failed to close DTLS session");
706                 SetResult(otmCtx, caResult);
707                 return OC_STACK_DELETE_TRANSACTION;
708             }
709
710             /**
711              * If we select NULL cipher,
712              * client will select appropriate cipher suite according to server's cipher-suite list.
713              */
714             caResult = CASelectCipherSuite(TLS_NULL_WITH_NULL_NULL);
715             if(CA_STATUS_OK != caResult)
716             {
717                 OIC_LOG(ERROR, TAG, "Failed to select TLS_NULL_WITH_NULL_NULL");
718                 SetResult(otmCtx, caResult);
719                 return OC_STACK_DELETE_TRANSACTION;
720             }
721
722             /**
723              * in case of random PIN based OxM,
724              * revert get_psk_info callback of tinyDTLS to use owner credential.
725              */
726             if(OIC_RANDOM_DEVICE_PIN == otmCtx->selectedDeviceInfo->doxm->oxmSel)
727             {
728                 OicUuid_t emptyUuid = { .id={0}};
729                 SetUuidForRandomPinOxm(&emptyUuid);
730
731                 if(CA_STATUS_OK != CARegisterDTLSCredentialsHandler(GetDtlsPskCredentials))
732                 {
733                     OIC_LOG(ERROR, TAG, "Failed to revert DTLS credential handler.");
734                     SetResult(otmCtx, OC_STACK_INVALID_CALLBACK);
735                     return OC_STACK_DELETE_TRANSACTION;
736                 }
737             }
738
739             //PUT /oic/sec/doxm [{ ..., "owned":"TRUE" }]
740             res = PutOwnershipInformation(otmCtx);
741             if(OC_STACK_OK != res)
742             {
743                 OIC_LOG(ERROR, TAG, "Failed to put ownership information to new device");
744                 SetResult(otmCtx, res);
745                 return OC_STACK_DELETE_TRANSACTION;
746             }
747         }
748     }
749     else
750     {
751         res = clientResponse->result;
752         OIC_LOG_V(ERROR, TAG, "OwnerCredentialHandler : Unexpected result %d", res);
753         SetResult(otmCtx, res);
754     }
755
756     OIC_LOG(DEBUG, TAG, "OUT OwnerCredentialHandler");
757
758 exit:
759     return  OC_STACK_DELETE_TRANSACTION;
760 }
761
762
763 /**
764  * Response handler for update owner information request.
765  *
766  * @param[in] ctx             ctx value passed to callback from calling function.
767  * @param[in] UNUSED          handle to an invocation
768  * @param[in] clientResponse  Response from queries to remote servers.
769  * @return  OC_STACK_DELETE_TRANSACTION to delete the transaction
770  *          and  OC_STACK_KEEP_TRANSACTION to keep it.
771  */
772 static OCStackApplicationResult OwnershipInformationHandler(void *ctx, OCDoHandle UNUSED,
773                                 OCClientResponse *clientResponse)
774 {
775     VERIFY_NON_NULL(TAG, clientResponse, WARNING);
776     VERIFY_NON_NULL(TAG, ctx, WARNING);
777
778     OIC_LOG(DEBUG, TAG, "IN OwnershipInformationHandler");
779     (void)UNUSED;
780     OCStackResult res = OC_STACK_OK;
781     OTMContext_t* otmCtx = (OTMContext_t*)ctx;
782
783     if(OC_STACK_OK == clientResponse->result)
784     {
785         if(otmCtx && otmCtx->selectedDeviceInfo)
786         {
787             OIC_LOG(INFO, TAG, "Ownership transfer was successfully completed.");
788             OIC_LOG(INFO, TAG, "Start defualt ACL & commit-hash provisioning.");
789
790             res = PutProvisioningStatus(otmCtx);
791             if(OC_STACK_OK != res)
792             {
793                 OIC_LOG(ERROR, TAG, "Failed to update pstat");
794                 SetResult(otmCtx, res);
795             }
796         }
797     }
798     else
799     {
800         res = clientResponse->result;
801         OIC_LOG_V(ERROR, TAG, "OwnershipInformationHandler : Unexpected result %d", res);
802         SetResult(otmCtx, res);
803     }
804
805     OIC_LOG(DEBUG, TAG, "OUT OwnershipInformationHandler");
806
807 exit:
808     return  OC_STACK_DELETE_TRANSACTION;
809 }
810
811 /**
812  * Response handler of update provisioning status.
813  *
814  * @param[in] ctx             ctx value passed to callback from calling function.
815  * @param[in] UNUSED          handle to an invocation
816  * @param[in] clientResponse  Response from queries to remote servers.
817  * @return  OC_STACK_DELETE_TRANSACTION to delete the transaction
818  *          and OC_STACK_KEEP_TRANSACTION to keep it.
819  */
820 static OCStackApplicationResult ProvisioningStatusHandler(void *ctx, OCDoHandle UNUSED,
821                                                        OCClientResponse *clientResponse)
822 {
823     OIC_LOG_V(INFO, TAG, "IN ProvisioningStatusHandler.");
824
825     VERIFY_NON_NULL(TAG, clientResponse, ERROR);
826     VERIFY_NON_NULL(TAG, ctx, ERROR);
827
828     OTMContext_t* otmCtx = (OTMContext_t*) ctx;
829     (void)UNUSED;
830
831     if (OC_STACK_OK == clientResponse->result)
832     {
833         OCStackResult res = PDMAddDevice(&otmCtx->selectedDeviceInfo->doxm->deviceID);
834          if (OC_STACK_OK == res)
835          {
836                 OIC_LOG_V(INFO, TAG, "Add device's UUID in PDM_DB");
837                 SetResult(otmCtx, OC_STACK_OK);
838                 return OC_STACK_DELETE_TRANSACTION;
839          }
840           else
841          {
842               OIC_LOG(ERROR, TAG, "Ownership transfer is complete but adding information to DB is failed.");
843          }
844     }
845     else
846     {
847         OIC_LOG_V(INFO, TAG, "Error occured in provisionDefaultACLCB :: %d\n",
848                             clientResponse->result);
849         SetResult(otmCtx, clientResponse->result);
850     }
851
852
853 exit:
854     OIC_LOG_V(INFO, TAG, "OUT ProvisioningStatusHandler.");
855     return OC_STACK_DELETE_TRANSACTION;
856 }
857
858 static OCStackResult PutOwnerCredential(OTMContext_t* otmCtx)
859 {
860     OIC_LOG(DEBUG, TAG, "IN PutOwnerCredential");
861
862     if(!otmCtx || !otmCtx->selectedDeviceInfo)
863     {
864         OIC_LOG(ERROR, TAG, "Invalid parameters");
865         return OC_STACK_INVALID_PARAM;
866     }
867
868     OCProvisionDev_t* deviceInfo = otmCtx->selectedDeviceInfo;
869     char query[MAX_URI_LENGTH + MAX_QUERY_LENGTH] = {0};
870
871     if(!PMGenerateQuery(true,
872                         deviceInfo->endpoint.addr, deviceInfo->securePort,
873                         deviceInfo->connType,
874                         query, sizeof(query), OIC_RSRC_CRED_URI))
875     {
876         OIC_LOG(ERROR, TAG, "PutOwnerCredential : Failed to generate query");
877         return OC_STACK_ERROR;
878     }
879     OIC_LOG_V(DEBUG, TAG, "Query=%s", query);
880     OCSecurityPayload* secPayload = (OCSecurityPayload*)OICCalloc(1, sizeof(OCSecurityPayload));
881     if(!secPayload)
882     {
883         OIC_LOG(ERROR, TAG, "Failed to memory allocation");
884         return OC_STACK_NO_MEMORY;
885     }
886
887     //Generate owner credential for new device
888     secPayload->base.type = PAYLOAD_TYPE_SECURITY;
889     OicSecCred_t* ownerCredential = GetCredResourceData(&(deviceInfo->doxm->deviceID));
890     if(!ownerCredential)
891     {
892         OIC_LOG(ERROR, TAG, "Can not find OwnerPSK.");
893         return OC_STACK_NO_RESOURCE;
894     }
895
896     OicUuid_t credSubjectId = {.id={0}};
897     if(OC_STACK_OK == GetDoxmDeviceID(&credSubjectId))
898     {
899         OicSecCred_t newCredential;
900         memcpy(&newCredential, ownerCredential, sizeof(OicSecCred_t));
901         newCredential.next = NULL;
902
903         //Set subject ID as PT's ID
904         memcpy(&(newCredential.subject), &credSubjectId, sizeof(OicUuid_t));
905
906         //Fill private data as empty string
907         newCredential.privateData.data = NULL;
908         newCredential.privateData.len = 0;
909 #ifdef __WITH_X509__
910         newCredential.publicData.data = NULL;
911         newCredential.publicData.len = 0;
912 #endif
913
914         //Send owner credential to new device : PUT /oic/sec/cred [ owner credential ]
915         if (OC_STACK_OK != CredToCBORPayload(&newCredential, &secPayload->securityData1, &secPayload->payloadSize))
916         {
917             OICFree(secPayload);
918             OIC_LOG(ERROR, TAG, "Error while converting bin to cbor.");
919             return OC_STACK_ERROR;
920         }
921         OIC_LOG_V(DEBUG, TAG, "Payload : %s", secPayload->securityData1);
922
923         OCCallbackData cbData;
924         cbData.cb = &OwnerCredentialHandler;
925         cbData.context = (void *)otmCtx;
926         cbData.cd = NULL;
927         OCStackResult res = OCDoResource(NULL, OC_REST_PUT, query,
928                                          &deviceInfo->endpoint, (OCPayload*)secPayload,
929                                          deviceInfo->connType, OC_LOW_QOS, &cbData, NULL, 0);
930         if (res != OC_STACK_OK)
931         {
932             OIC_LOG(ERROR, TAG, "OCStack resource error");
933         }
934     }
935     else
936     {
937         OIC_LOG(ERROR, TAG, "Failed to read DOXM device ID.");
938         return OC_STACK_NO_RESOURCE;
939     }
940
941     OIC_LOG(DEBUG, TAG, "OUT PutOwnerCredential");
942
943     return OC_STACK_OK;
944 }
945
946 static OCStackResult PutOwnerTransferModeToResource(OTMContext_t* otmCtx)
947 {
948     OIC_LOG(DEBUG, TAG, "IN PutOwnerTransferModeToResource");
949
950     if(!otmCtx || !otmCtx->selectedDeviceInfo)
951     {
952         OIC_LOG(ERROR, TAG, "Invalid parameters");
953         return OC_STACK_INVALID_PARAM;
954     }
955
956     OCProvisionDev_t* deviceInfo = otmCtx->selectedDeviceInfo;
957     OicSecOxm_t selectedOxm = deviceInfo->doxm->oxmSel;
958     char query[MAX_URI_LENGTH + MAX_QUERY_LENGTH] = {0};
959
960     if(!PMGenerateQuery(false,
961                         deviceInfo->endpoint.addr, deviceInfo->endpoint.port,
962                         deviceInfo->connType,
963                         query, sizeof(query), OIC_RSRC_DOXM_URI))
964     {
965         OIC_LOG(ERROR, TAG, "PutOwnerTransferModeToResource : Failed to generate query");
966         return OC_STACK_ERROR;
967     }
968     OIC_LOG_V(DEBUG, TAG, "Query=%s", query);
969     OCSecurityPayload* secPayload = (OCSecurityPayload*)OICCalloc(1, sizeof(OCSecurityPayload));
970     if(!secPayload)
971     {
972         OIC_LOG(ERROR, TAG, "Failed to memory allocation");
973         return OC_STACK_NO_MEMORY;
974     }
975     secPayload->base.type = PAYLOAD_TYPE_SECURITY;
976     OCStackResult res = g_OTMDatas[selectedOxm].createSelectOxmPayloadCB(otmCtx,
977             &secPayload->securityData1, &secPayload->payloadSize);
978     if (OC_STACK_OK != res && NULL == secPayload->securityData1)
979     {
980         OCPayloadDestroy((OCPayload *)secPayload);
981         OIC_LOG(ERROR, TAG, "Error while converting bin to cbor");
982         return OC_STACK_ERROR;
983     }
984
985     OCCallbackData cbData;
986     cbData.cb = &OwnerTransferModeHandler;
987     cbData.context = (void *)otmCtx;
988     cbData.cd = NULL;
989     res = OCDoResource(NULL, OC_REST_PUT, query,
990                        &deviceInfo->endpoint, (OCPayload *)secPayload,
991                        deviceInfo->connType, OC_LOW_QOS, &cbData, NULL, 0);
992     if (res != OC_STACK_OK)
993     {
994         OIC_LOG(ERROR, TAG, "OCStack resource error");
995     }
996
997     OIC_LOG(DEBUG, TAG, "OUT PutOwnerTransferModeToResource");
998
999     return res;
1000 }
1001
1002 static OCStackResult GetProvisioningStatusResource(OTMContext_t* otmCtx)
1003 {
1004     OIC_LOG(DEBUG, TAG, "IN GetProvisioningStatusResource");
1005
1006     if(!otmCtx || !otmCtx->selectedDeviceInfo)
1007     {
1008         OIC_LOG(ERROR, TAG, "Invailed parameters");
1009         return OC_STACK_INVALID_PARAM;
1010     }
1011
1012     OCProvisionDev_t* deviceInfo = otmCtx->selectedDeviceInfo;
1013     char query[MAX_URI_LENGTH + MAX_QUERY_LENGTH] = {0};
1014     if(!PMGenerateQuery(false,
1015                         deviceInfo->endpoint.addr, deviceInfo->endpoint.port,
1016                         deviceInfo->connType,
1017                         query, sizeof(query), OIC_RSRC_PSTAT_URI))
1018     {
1019         OIC_LOG(ERROR, TAG, "GetProvisioningStatusResource : Failed to generate query");
1020         return OC_STACK_ERROR;
1021     }
1022     OIC_LOG_V(DEBUG, TAG, "Query=%s", query);
1023
1024     OCCallbackData cbData;
1025     cbData.cb = &ListMethodsHandler;
1026     cbData.context = (void *)otmCtx;
1027     cbData.cd = NULL;
1028     OCStackResult res = OCDoResource(NULL, OC_REST_GET, query, NULL, NULL,
1029                                      deviceInfo->connType, OC_LOW_QOS, &cbData, NULL, 0);
1030     if (res != OC_STACK_OK)
1031     {
1032         OIC_LOG(ERROR, TAG, "OCStack resource error");
1033     }
1034
1035     OIC_LOG(DEBUG, TAG, "OUT GetProvisioningStatusResource");
1036
1037     return res;
1038 }
1039
1040 static OCStackResult PutOwnerUuid(OTMContext_t* otmCtx)
1041 {
1042     OIC_LOG(DEBUG, TAG, "IN PutOwnerUuid");
1043
1044     if(!otmCtx || !otmCtx->selectedDeviceInfo)
1045     {
1046         OIC_LOG(ERROR, TAG, "Invailed parameters");
1047         return OC_STACK_INVALID_PARAM;
1048     }
1049
1050     OCProvisionDev_t* deviceInfo = otmCtx->selectedDeviceInfo;
1051     char query[MAX_URI_LENGTH + MAX_QUERY_LENGTH] = {0};
1052     if(!PMGenerateQuery(true,
1053                         deviceInfo->endpoint.addr, deviceInfo->securePort,
1054                         deviceInfo->connType,
1055                         query, sizeof(query), OIC_RSRC_DOXM_URI))
1056     {
1057         OIC_LOG(ERROR, TAG, "PutOwnershipInformation : Failed to generate query");
1058         return OC_STACK_ERROR;
1059     }
1060     OIC_LOG_V(DEBUG, TAG, "Query=%s", query);
1061
1062     //PUT PT's uuid to new device
1063     OCSecurityPayload* secPayload = (OCSecurityPayload*)OICCalloc(1, sizeof(OCSecurityPayload));
1064     if(!secPayload)
1065     {
1066         OIC_LOG(ERROR, TAG, "Failed to memory allocation");
1067         return OC_STACK_NO_MEMORY;
1068     }
1069     secPayload->base.type = PAYLOAD_TYPE_SECURITY;
1070     OCStackResult res =  g_OTMDatas[deviceInfo->doxm->oxmSel].createOwnerTransferPayloadCB(
1071             otmCtx, &secPayload->securityData1, &secPayload->payloadSize);
1072     if (NULL == secPayload->securityData1)
1073     {
1074         OCPayloadDestroy((OCPayload *)secPayload);
1075         OIC_LOG(ERROR, TAG, "Error while converting doxm bin to cbor.");
1076         return OC_STACK_INVALID_PARAM;
1077     }
1078     OIC_LOG_V(DEBUG, TAG, "Payload : %s", secPayload->securityData1);
1079
1080     OCCallbackData cbData;
1081     cbData.cb = &OwnerUuidUpdateHandler;
1082     cbData.context = (void *)otmCtx;
1083     cbData.cd = NULL;
1084
1085     res = OCDoResource(NULL, OC_REST_PUT, query, 0, (OCPayload *)secPayload,
1086             deviceInfo->connType, OC_LOW_QOS, &cbData, NULL, 0);
1087     if (res != OC_STACK_OK)
1088     {
1089         OIC_LOG(ERROR, TAG, "OCStack resource error");
1090     }
1091
1092     OIC_LOG(DEBUG, TAG, "OUT PutOwnerUuid");
1093
1094     return res;
1095 }
1096
1097 static OCStackResult PutOwnershipInformation(OTMContext_t* otmCtx)
1098 {
1099     OIC_LOG(DEBUG, TAG, "IN PutOwnershipInformation");
1100
1101     if(!otmCtx || !otmCtx->selectedDeviceInfo)
1102     {
1103         OIC_LOG(ERROR, TAG, "Invailed parameters");
1104         return OC_STACK_INVALID_PARAM;
1105     }
1106
1107     OCProvisionDev_t* deviceInfo = otmCtx->selectedDeviceInfo;
1108     char query[MAX_URI_LENGTH + MAX_QUERY_LENGTH] = {0};
1109     if(!PMGenerateQuery(true,
1110                         deviceInfo->endpoint.addr, deviceInfo->securePort,
1111                         deviceInfo->connType,
1112                         query, sizeof(query), OIC_RSRC_DOXM_URI))
1113     {
1114         OIC_LOG(ERROR, TAG, "PutOwnershipInformation : Failed to generate query");
1115         return OC_STACK_ERROR;
1116     }
1117     OIC_LOG_V(DEBUG, TAG, "Query=%s", query);
1118
1119     //OwnershipInformationHandler
1120     OCSecurityPayload *secPayload = (OCSecurityPayload*)OICCalloc(1, sizeof(OCSecurityPayload));
1121     if (!secPayload)
1122     {
1123         OIC_LOG(ERROR, TAG, "Failed to memory allocation");
1124         return OC_STACK_NO_MEMORY;
1125     }
1126
1127     otmCtx->selectedDeviceInfo->doxm->owned = true;
1128
1129     secPayload->base.type = PAYLOAD_TYPE_SECURITY;
1130     OCStackResult res = DoxmToCBORPayload(otmCtx->selectedDeviceInfo->doxm,
1131             &secPayload->securityData1, &secPayload->payloadSize);
1132     if (OC_STACK_OK != res && NULL == secPayload->securityData1)
1133     {
1134         OCPayloadDestroy((OCPayload *)secPayload);
1135         OIC_LOG(ERROR, TAG, "Error while converting doxm bin to json");
1136         return OC_STACK_INVALID_PARAM;
1137     }
1138
1139     OCCallbackData cbData;
1140     cbData.cb = &OwnershipInformationHandler;
1141     cbData.context = (void *)otmCtx;
1142     cbData.cd = NULL;
1143
1144     res = OCDoResource(NULL, OC_REST_PUT, query, 0, (OCPayload*)secPayload,
1145                        deviceInfo->connType, OC_LOW_QOS, &cbData, NULL, 0);
1146     if (res != OC_STACK_OK)
1147     {
1148         OIC_LOG(ERROR, TAG, "OCStack resource error");
1149     }
1150
1151     OIC_LOG(DEBUG, TAG, "OUT PutOwnershipInformation");
1152
1153     return res;
1154 }
1155
1156 static OCStackResult PutUpdateOperationMode(OTMContext_t* otmCtx)
1157 {
1158     OIC_LOG(DEBUG, TAG, "IN PutUpdateOperationMode");
1159
1160     if(!otmCtx || !otmCtx->selectedDeviceInfo)
1161     {
1162         return OC_STACK_INVALID_PARAM;
1163     }
1164
1165     OCProvisionDev_t* deviceInfo = otmCtx->selectedDeviceInfo;
1166     char query[MAX_URI_LENGTH + MAX_QUERY_LENGTH] = {0};
1167     if(!PMGenerateQuery(false,
1168                         deviceInfo->endpoint.addr, deviceInfo->endpoint.port,
1169                         deviceInfo->connType,
1170                         query, sizeof(query), OIC_RSRC_PSTAT_URI))
1171     {
1172         OIC_LOG(ERROR, TAG, "PutUpdateOperationMode : Failed to generate query");
1173         return OC_STACK_ERROR;
1174     }
1175     OIC_LOG_V(DEBUG, TAG, "Query=%s", query);
1176
1177     OCSecurityPayload* secPayload = (OCSecurityPayload*)OICCalloc(1, sizeof(OCSecurityPayload));
1178     if(!secPayload)
1179     {
1180         OIC_LOG(ERROR, TAG, "Failed to memory allocation");
1181         return OC_STACK_NO_MEMORY;
1182     }
1183     secPayload->base.type = PAYLOAD_TYPE_SECURITY;
1184     OCStackResult res = PstatToCBORPayload(deviceInfo->pstat, &secPayload->securityData1,
1185                                            &secPayload->payloadSize);
1186    if (OC_STACK_OK != res)
1187     {
1188         OCPayloadDestroy((OCPayload *)secPayload);
1189         OIC_LOG(ERROR, TAG, "Error while converting pstat to cbor.");
1190         return OC_STACK_INVALID_PARAM;
1191     }
1192
1193     OCCallbackData cbData;
1194     cbData.cb = &OperationModeUpdateHandler;
1195     cbData.context = (void *)otmCtx;
1196     cbData.cd = NULL;
1197     res = OCDoResource(NULL, OC_REST_PUT, query, 0, (OCPayload *)secPayload,
1198                        deviceInfo->connType, OC_LOW_QOS, &cbData, NULL, 0);
1199     if (res != OC_STACK_OK)
1200     {
1201         OIC_LOG(ERROR, TAG, "OCStack resource error");
1202     }
1203
1204     OIC_LOG(DEBUG, TAG, "OUT PutUpdateOperationMode");
1205
1206     return res;
1207 }
1208
1209 static OCStackResult StartOwnershipTransfer(void* ctx, OCProvisionDev_t* selectedDevice)
1210 {
1211     OIC_LOG(INFO, TAG, "IN StartOwnershipTransfer");
1212     OTMContext_t* otmCtx = (OTMContext_t*)ctx;
1213     otmCtx->selectedDeviceInfo = selectedDevice;
1214
1215     //Set to the lowest level OxM, and then find more higher level OxM.
1216     OCStackResult res = SelectProvisioningMethod(selectedDevice->doxm->oxm,
1217                                                  selectedDevice->doxm->oxmLen,
1218                                                  &selectedDevice->doxm->oxmSel);
1219     if(OC_STACK_OK != res)
1220     {
1221         OIC_LOG(ERROR, TAG, "Failed to select the provisioning method");
1222         SetResult(otmCtx, res);
1223         return res;
1224     }
1225     OIC_LOG_V(DEBUG, TAG, "Selected provisoning method = %d", selectedDevice->doxm->oxmSel);
1226
1227     //Send Req: PUT /oic/sec/doxm [{..."OxmSel" :g_OTMDatas[Index of Selected OxM].OXMString,...}]
1228     res = PutOwnerTransferModeToResource(otmCtx);
1229     if(OC_STACK_OK != res)
1230     {
1231         OIC_LOG(WARNING, TAG, "Failed to select the provisioning method");
1232         SetResult(otmCtx, res);
1233         return res;
1234     }
1235
1236     //Register DTLS event handler to catch the dtls event while handshake
1237     if(CA_STATUS_OK != CARegisterDTLSHandshakeCallback(DTLSHandshakeCB))
1238     {
1239         OIC_LOG(WARNING, TAG, "StartOwnershipTransfer : Failed to register DTLS handshake callback.");
1240     }
1241
1242     OIC_LOG(INFO, TAG, "OUT StartOwnershipTransfer");
1243
1244     return res;
1245
1246 }
1247
1248 OCStackResult OTMSetOwnershipTransferCallbackData(OicSecOxm_t oxmType, OTMCallbackData_t* data)
1249 {
1250     OIC_LOG(DEBUG, TAG, "IN OTMSetOwnerTransferCallbackData");
1251
1252     if(!data)
1253     {
1254         OIC_LOG(ERROR, TAG, "OTMSetOwnershipTransferCallbackData : Invalid parameters");
1255         return OC_STACK_INVALID_PARAM;
1256     }
1257     if(oxmType >= OIC_OXM_COUNT)
1258     {
1259         OIC_LOG(INFO, TAG, "Unknow ownership transfer method");
1260         return OC_STACK_INVALID_PARAM;
1261     }
1262
1263     g_OTMDatas[oxmType].loadSecretCB= data->loadSecretCB;
1264     g_OTMDatas[oxmType].createSecureSessionCB = data->createSecureSessionCB;
1265     g_OTMDatas[oxmType].createSelectOxmPayloadCB = data->createSelectOxmPayloadCB;
1266     g_OTMDatas[oxmType].createOwnerTransferPayloadCB = data->createOwnerTransferPayloadCB;
1267
1268     OIC_LOG(DEBUG, TAG, "OUT OTMSetOwnerTransferCallbackData");
1269
1270     return OC_STACK_OK;
1271 }
1272
1273 /**
1274  * NOTE : Unowned discovery should be done before performing OTMDoOwnershipTransfer
1275  */
1276 OCStackResult OTMDoOwnershipTransfer(void* ctx,
1277                                      OCProvisionDev_t *selectedDevicelist,
1278                                      OCProvisionResultCB resultCallback)
1279 {
1280     OIC_LOG(DEBUG, TAG, "IN OTMDoOwnershipTransfer");
1281
1282     if (NULL == selectedDevicelist)
1283     {
1284         return OC_STACK_INVALID_PARAM;
1285     }
1286     if (NULL == resultCallback)
1287     {
1288         return OC_STACK_INVALID_CALLBACK;
1289     }
1290
1291     OTMContext_t* otmCtx = (OTMContext_t*)OICCalloc(1,sizeof(OTMContext_t));
1292     if(!otmCtx)
1293     {
1294         OIC_LOG(ERROR, TAG, "Failed to create OTM Context");
1295         return OC_STACK_NO_MEMORY;
1296     }
1297     otmCtx->ctxResultCallback = resultCallback;
1298     otmCtx->ctxHasError = false;
1299     otmCtx->userCtx = ctx;
1300     OCProvisionDev_t* pCurDev = selectedDevicelist;
1301
1302     //Counting number of selected devices.
1303     otmCtx->ctxResultArraySize = 0;
1304     while(NULL != pCurDev)
1305     {
1306         otmCtx->ctxResultArraySize++;
1307         pCurDev = pCurDev->next;
1308     }
1309
1310     otmCtx->ctxResultArray =
1311         (OCProvisionResult_t*)OICCalloc(otmCtx->ctxResultArraySize, sizeof(OCProvisionResult_t));
1312     if(NULL == otmCtx->ctxResultArray)
1313     {
1314         OIC_LOG(ERROR, TAG, "OTMDoOwnershipTransfer : Failed to memory allocation");
1315         OICFree(otmCtx);
1316         return OC_STACK_NO_MEMORY;
1317     }
1318     pCurDev = selectedDevicelist;
1319
1320     OCStackResult res = OC_STACK_OK;
1321     //Fill the device UUID for result array.
1322     for(size_t devIdx = 0; devIdx < otmCtx->ctxResultArraySize; devIdx++)
1323     {
1324         //Checking duplication of Device ID.
1325         bool isDuplicate = true;
1326         res = PDMIsDuplicateDevice(&pCurDev->doxm->deviceID, &isDuplicate);
1327         if (OC_STACK_OK != res)
1328         {
1329             goto error;
1330         }
1331         if (isDuplicate)
1332         {
1333             OIC_LOG(ERROR, TAG, "OTMDoOwnershipTransfer : Device ID is duplicated");
1334             res = OC_STACK_INVALID_PARAM;
1335             goto error;
1336         }
1337         memcpy(otmCtx->ctxResultArray[devIdx].deviceId.id,
1338                pCurDev->doxm->deviceID.id,
1339                UUID_LENGTH);
1340         otmCtx->ctxResultArray[devIdx].res = OC_STACK_CONTINUE;
1341         pCurDev = pCurDev->next;
1342     }
1343
1344     StartOwnershipTransfer(otmCtx, selectedDevicelist);
1345
1346     OIC_LOG(DEBUG, TAG, "OUT OTMDoOwnershipTransfer");
1347     return OC_STACK_OK;
1348
1349 error:
1350     OICFree(otmCtx->ctxResultArray);
1351     OICFree(otmCtx);
1352     return res;
1353 }
1354
1355 /**
1356  * Callback handler of SRPFinalizeProvisioning.
1357  *
1358  * @param[in] ctx             ctx value passed to callback from calling function.
1359  * @param[in] UNUSED          handle to an invocation
1360  * @param[in] clientResponse  Response from queries to remote servers.
1361  * @return  OC_STACK_DELETE_TRANSACTION to delete the transaction
1362  *          and OC_STACK_KEEP_TRANSACTION to keep it.
1363  */
1364 static OCStackApplicationResult FinalizeProvisioningCB(void *ctx, OCDoHandle UNUSED,
1365                                                        OCClientResponse *clientResponse)
1366 {
1367     OIC_LOG_V(INFO, TAG, "IN FinalizeProvisioningCB.");
1368
1369     VERIFY_NON_NULL(TAG, clientResponse, ERROR);
1370     VERIFY_NON_NULL(TAG, ctx, ERROR);
1371
1372     OTMContext_t* otmCtx = (OTMContext_t*)ctx;
1373     (void)UNUSED;
1374     if(OC_STACK_OK == clientResponse->result)
1375     {
1376         OCStackResult res = PDMAddDevice(&otmCtx->selectedDeviceInfo->doxm->deviceID);
1377
1378          if (OC_STACK_OK == res)
1379          {
1380                 OIC_LOG_V(INFO, TAG, "Add device's UUID in PDM_DB");
1381                 SetResult(otmCtx, OC_STACK_OK);
1382                 return OC_STACK_DELETE_TRANSACTION;
1383          }
1384          else
1385          {
1386               OIC_LOG(ERROR, TAG, "Ownership transfer is complete but adding information to DB is failed.");
1387          }
1388     }
1389 exit:
1390     return OC_STACK_DELETE_TRANSACTION;
1391 }
1392
1393 /**
1394  * Callback handler of default ACL provisioning.
1395  *
1396  * @param[in] ctx             ctx value passed to callback from calling function.
1397  * @param[in] UNUSED          handle to an invocation
1398  * @param[in] clientResponse  Response from queries to remote servers.
1399  * @return  OC_STACK_DELETE_TRANSACTION to delete the transaction
1400  *          and OC_STACK_KEEP_TRANSACTION to keep it.
1401  */
1402 static OCStackApplicationResult ProvisionDefaultACLCB(void *ctx, OCDoHandle UNUSED,
1403                                                        OCClientResponse *clientResponse)
1404 {
1405     OIC_LOG_V(INFO, TAG, "IN ProvisionDefaultACLCB.");
1406
1407     VERIFY_NON_NULL(TAG, clientResponse, ERROR);
1408     VERIFY_NON_NULL(TAG, ctx, ERROR);
1409
1410     OTMContext_t* otmCtx = (OTMContext_t*) ctx;
1411     (void)UNUSED;
1412
1413     if (OC_STACK_RESOURCE_CREATED == clientResponse->result)
1414     {
1415         OIC_LOG_V(INFO, TAG, "Staring commit hash task.");
1416         // TODO hash currently have fixed value 0.
1417         uint16_t aclHash = 0;
1418         otmCtx->selectedDeviceInfo->pstat->commitHash = aclHash;
1419         otmCtx->selectedDeviceInfo->pstat->tm = NORMAL;
1420         OCSecurityPayload* secPayload = (OCSecurityPayload*)OICCalloc(1, sizeof(OCSecurityPayload));
1421         if(!secPayload)
1422         {
1423             OIC_LOG(ERROR, TAG, "Failed to memory allocation");
1424             return OC_STACK_NO_MEMORY;
1425         }
1426         secPayload->base.type = PAYLOAD_TYPE_SECURITY;
1427         OCStackResult res = PstatToCBORPayload(otmCtx->selectedDeviceInfo->pstat,
1428                 &secPayload->securityData1, &secPayload->payloadSize);
1429         if (OC_STACK_OK != res || NULL == secPayload->securityData1)
1430         {
1431             OICFree(secPayload);
1432             SetResult(otmCtx, OC_STACK_INVALID_JSON);
1433             return OC_STACK_DELETE_TRANSACTION;
1434         }
1435
1436         char query[MAX_URI_LENGTH + MAX_QUERY_LENGTH] = {0};
1437         if(!PMGenerateQuery(true,
1438                             otmCtx->selectedDeviceInfo->endpoint.addr,
1439                             otmCtx->selectedDeviceInfo->securePort,
1440                             otmCtx->selectedDeviceInfo->connType,
1441                             query, sizeof(query), OIC_RSRC_PSTAT_URI))
1442         {
1443             OIC_LOG(ERROR, TAG, "ProvisionDefaultACLCB : Failed to generate query");
1444             return OC_STACK_ERROR;
1445         }
1446         OIC_LOG_V(DEBUG, TAG, "Query=%s", query);
1447
1448         OCCallbackData cbData = {.context=NULL, .cb=NULL, .cd=NULL};
1449         cbData.cb = &FinalizeProvisioningCB;
1450         cbData.context = (void*)otmCtx;
1451         cbData.cd = NULL;
1452         OCStackResult ret = OCDoResource(NULL, OC_REST_PUT, query, 0, (OCPayload*)secPayload,
1453                 otmCtx->selectedDeviceInfo->connType, OC_HIGH_QOS, &cbData, NULL, 0);
1454         OIC_LOG_V(INFO, TAG, "OCDoResource returned: %d",ret);
1455         if (ret != OC_STACK_OK)
1456         {
1457             OIC_LOG(ERROR, TAG, "OCStack resource error");
1458             SetResult(otmCtx, ret);
1459         }
1460     }
1461     else
1462     {
1463         OIC_LOG_V(INFO, TAG, "Error occured in provisionDefaultACLCB :: %d\n",
1464                             clientResponse->result);
1465         SetResult(otmCtx, clientResponse->result);
1466     }
1467 exit:
1468     return OC_STACK_DELETE_TRANSACTION;
1469 }
1470
1471 OCStackResult PutProvisioningStatus(OTMContext_t* otmCtx)
1472 {
1473     OIC_LOG(INFO, TAG, "IN PutProvisioningStatus");
1474
1475     if(!otmCtx)
1476     {
1477         OIC_LOG(ERROR, TAG, "OTMContext is NULL");
1478         return OC_STACK_INVALID_PARAM;
1479     }
1480     if(!otmCtx->selectedDeviceInfo)
1481     {
1482         OIC_LOG(ERROR, TAG, "Can't find device information in OTMContext");
1483         OICFree(otmCtx);
1484         return OC_STACK_INVALID_PARAM;
1485     }
1486
1487     //Change the TAKE_OWNER bit of CM to 0.
1488     otmCtx->selectedDeviceInfo->pstat->cm &= (~TAKE_OWNER);
1489
1490     OCSecurityPayload *secPayload = (OCSecurityPayload *)OICCalloc(1, sizeof(OCSecurityPayload));
1491     if (!secPayload)
1492     {
1493         OIC_LOG(ERROR, TAG, "Failed to memory allocation");
1494         return OC_STACK_NO_MEMORY;
1495     }
1496     secPayload->base.type = PAYLOAD_TYPE_SECURITY;
1497     if (OC_STACK_OK != PstatToCBORPayload(otmCtx->selectedDeviceInfo->pstat,
1498             &secPayload->securityData1, &secPayload->payloadSize))
1499     {
1500         OCPayloadDestroy((OCPayload *)secPayload);
1501         SetResult(otmCtx, OC_STACK_INVALID_JSON);
1502         return OC_STACK_INVALID_JSON;
1503     }
1504     OIC_LOG_V(INFO, TAG, "Created payload for commit hash: %s",secPayload->securityData1);
1505
1506     char query[MAX_URI_LENGTH + MAX_QUERY_LENGTH] = {0};
1507     if(!PMGenerateQuery(true,
1508                         otmCtx->selectedDeviceInfo->endpoint.addr,
1509                         otmCtx->selectedDeviceInfo->securePort,
1510                         otmCtx->selectedDeviceInfo->connType,
1511                         query, sizeof(query), OIC_RSRC_PSTAT_URI))
1512     {
1513         OIC_LOG(ERROR, TAG, "PutProvisioningStatus : Failed to generate query");
1514         return OC_STACK_ERROR;
1515     }
1516     OIC_LOG_V(DEBUG, TAG, "Query=%s", query);
1517
1518     OCCallbackData cbData = {.context=NULL, .cb=NULL, .cd=NULL};
1519     cbData.cb = &ProvisioningStatusHandler;
1520     cbData.context = (void*)otmCtx;
1521     cbData.cd = NULL;
1522     OCStackResult ret = OCDoResource(NULL, OC_REST_PUT, query, 0, (OCPayload*)secPayload,
1523             otmCtx->selectedDeviceInfo->connType, OC_HIGH_QOS, &cbData, NULL, 0);
1524     OIC_LOG_V(INFO, TAG, "OCDoResource returned: %d",ret);
1525     if (ret != OC_STACK_OK)
1526     {
1527         OIC_LOG(ERROR, TAG, "OCStack resource error");
1528         SetResult(otmCtx, ret);
1529     }
1530
1531     OIC_LOG(INFO, TAG, "OUT PutProvisioningStatus");
1532
1533     return ret;
1534 }