1 /* *****************************************************************
3 * Copyright 2015 Samsung Electronics All Rights Reserved.
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
11 * http://www.apache.org/licenses/LICENSE-2.0
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.
19 * *****************************************************************/
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
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
39 #ifdef HAVE_SYS_TIME_H
46 #include "oic_malloc.h"
47 #include "oic_string.h"
49 #include "cainterface.h"
54 #include "srmresourcestrings.h"
55 #include "doxmresource.h"
56 #include "pstatresource.h"
57 #include "credresource.h"
58 #include "aclresource.h"
59 #include "ownershiptransfermanager.h"
60 #include "securevirtualresourcetypes.h"
61 #include "oxmjustworks.h"
63 #include "pmutility.h"
64 #include "srmutility.h"
65 #include "provisioningdatabasemanager.h"
66 #include "oxmrandompin.h"
67 #include "ocpayload.h"
68 #include "payload_logging.h"
73 * Array to store the callbacks for each owner transfer method.
75 static OTMCallbackData_t g_OTMDatas[OIC_OXM_COUNT];
78 * Variables for pointing the OTMContext to be used in the DTLS handshake result callback.
80 static OTMContext_t* g_otmCtx = NULL;
83 * Function to select appropriate provisioning method.
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
90 static OCStackResult SelectProvisioningMethod(const OicSecOxm_t *supportedMethods,
91 size_t numberOfMethods, OicSecOxm_t *selectedMethod)
93 OIC_LOG(DEBUG, TAG, "IN SelectProvisioningMethod");
95 if(numberOfMethods == 0 || !supportedMethods)
97 OIC_LOG(WARNING, TAG, "Could not find a supported OxM.");
98 return OC_STACK_ERROR;
101 *selectedMethod = supportedMethods[0];
102 for(size_t i = 0; i < numberOfMethods; i++)
104 if(*selectedMethod < supportedMethods[i])
106 *selectedMethod = supportedMethods[i];
114 * Function to select operation mode.This function will return most secure common operation mode.
116 * @param[in] selectedDeviceInfo selected device information to performing provisioning.
117 * @param[out] selectedMode selected operation mode
118 * @return OC_STACK_OK on success
120 static void SelectOperationMode(const OCProvisionDev_t *selectedDeviceInfo,
121 OicSecDpom_t *selectedMode)
123 OIC_LOG(DEBUG, TAG, "IN SelectOperationMode");
124 *selectedMode = selectedDeviceInfo->pstat->sm[0];
125 OIC_LOG_V(DEBUG, TAG, "Selected Operation Mode = %d", *selectedMode);
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.
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
137 static OCStackResult StartOwnershipTransfer(void* ctx, OCProvisionDev_t* selectedDevice);
140 * Function to update owner transfer mode
142 * @param[in] otmCtx Context value of ownership transfer.
143 * @return OC_STACK_OK on success
145 static OCStackResult PostOwnerTransferModeToResource(OTMContext_t* otmCtx);
148 * Function to send request to resource to get its pstat resource information.
150 * @param[in] otmCtx Context value of ownership transfer.
151 * @return OC_STACK_OK on success
153 static OCStackResult GetProvisioningStatusResource(OTMContext_t* otmCtx);
157 * Function to send uuid of owner device to new device.
158 * This function would update 'owner of doxm' as UUID for provisioning tool.
160 * @param[in] otmCtx Context value of ownership transfer.
161 * @return OC_STACK_OK on success
163 static OCStackResult PostOwnerUuid(OTMContext_t* otmCtx);
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
169 * @param[in] otmCtx Context value of ownership transfer.
170 * @return OC_STACK_OK on success
172 static OCStackResult PostUpdateOperationMode(OTMContext_t* otmCtx);
175 * Function to update the owner credential to new device
177 * @param[in] otmCtx Context value of ownership transfer.
178 * @param[in] selectedOperationMode selected operation mode
179 * @return OC_STACK_OK on success
181 static OCStackResult PostOwnerCredential(OTMContext_t* otmCtx);
184 * Function to send ownerShip info.
185 * This function would update 'owned of doxm' as true.
187 * @param[in] otmCtx Context value of ownership transfer.
188 * @return OC_STACK_OK on success
190 static OCStackResult PostOwnershipInformation(OTMContext_t* otmCtx);
193 * Function to update pstat as Ready for provisioning.
194 * This function would update 'cm' from bx0000,0010 to bx0000,0000.
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
200 static OCStackResult PostProvisioningStatus(OTMContext_t* otmCtx);
203 * Function to update pstat as Ready for Normal Operation.
204 * This function would update 'isop' from false to true.
206 * @param[in] ctx context value passed to callback from calling function.
207 * @param[in] selectedDevice selected device information to performing provisioning.
208 * @return OC_STACK_OK on success
210 static OCStackResult PostNormalOperationStatus(OTMContext_t* otmCtx);
212 static bool IsComplete(OTMContext_t* otmCtx)
214 for(size_t i = 0; i < otmCtx->ctxResultArraySize; i++)
216 if(OC_STACK_CONTINUE == otmCtx->ctxResultArray[i].res)
226 * Function to save the result of provisioning.
228 * @param[in,out] otmCtx Context value of ownership transfer.
229 * @param[in] res result of provisioning
231 static void SetResult(OTMContext_t* otmCtx, const OCStackResult res)
233 OIC_LOG_V(DEBUG, TAG, "IN SetResult : %d ", res);
237 OIC_LOG(WARNING, TAG, "OTMContext is NULL");
241 if(otmCtx->selectedDeviceInfo)
243 //Revert psk_info callback and new deivce uuid in case of random PIN OxM
244 if(OIC_RANDOM_DEVICE_PIN == otmCtx->selectedDeviceInfo->doxm->oxmSel)
246 if(CA_STATUS_OK != CARegisterDTLSCredentialsHandler(GetDtlsPskCredentials))
248 OIC_LOG(WARNING, TAG, "Failed to revert is DTLS credential handler.");
250 OicUuid_t emptyUuid = { .id={0}};
251 SetUuidForRandomPinOxm(&emptyUuid);
254 for(size_t i = 0; i < otmCtx->ctxResultArraySize; i++)
256 if(memcmp(otmCtx->selectedDeviceInfo->doxm->deviceID.id,
257 otmCtx->ctxResultArray[i].deviceId.id, UUID_LENGTH) == 0)
259 otmCtx->ctxResultArray[i].res = res;
260 if(OC_STACK_OK != res)
262 otmCtx->ctxHasError = true;
269 //If all request is completed, invoke the user callback.
270 if(IsComplete(otmCtx))
272 otmCtx->ctxResultCallback(otmCtx->userCtx, otmCtx->ctxResultArraySize,
273 otmCtx->ctxResultArray, otmCtx->ctxHasError);
274 OICFree(otmCtx->ctxResultArray);
279 if(OC_STACK_OK != StartOwnershipTransfer(otmCtx,
280 otmCtx->selectedDeviceInfo->next))
282 OIC_LOG(ERROR, TAG, "Failed to StartOwnershipTransfer");
287 OIC_LOG(DEBUG, TAG, "OUT SetResult");
291 * Function to handle the handshake result in OTM.
292 * This function will be invoked after DTLS handshake
293 * @param endPoint [IN] The remote endpoint.
294 * @param errorInfo [IN] Error information from the endpoint.
297 void DTLSHandshakeCB(const CAEndpoint_t *endpoint, const CAErrorInfo_t *info)
299 if(NULL != g_otmCtx && NULL != g_otmCtx->selectedDeviceInfo &&
300 NULL != endpoint && NULL != info)
302 OIC_LOG_V(INFO, TAG, "Received status from remote device(%s:%d) : %d",
303 endpoint->addr, endpoint->port, info->result);
305 OicSecDoxm_t* newDevDoxm = g_otmCtx->selectedDeviceInfo->doxm;
307 if(NULL != newDevDoxm)
309 OicUuid_t emptyUuid = {.id={0}};
311 //Make sure the address matches.
312 if(strncmp(g_otmCtx->selectedDeviceInfo->endpoint.addr,
314 sizeof(endpoint->addr)) == 0 &&
315 g_otmCtx->selectedDeviceInfo->securePort == endpoint->port)
317 OCStackResult res = OC_STACK_ERROR;
319 //If temporal secure sesstion established successfully
320 if(CA_STATUS_OK == info->result &&
321 false == newDevDoxm->owned &&
322 memcmp(&(newDevDoxm->owner), &emptyUuid, sizeof(OicUuid_t)) == 0)
324 //Send request : POST /oic/sec/doxm [{... , "devowner":"PT's UUID"}]
325 res = PostOwnerUuid(g_otmCtx);
326 if(OC_STACK_OK != res)
328 OIC_LOG(ERROR, TAG, "OperationModeUpdate : Failed to send owner information");
329 SetResult(g_otmCtx, res);
332 //In case of authentication failure
333 else if(CA_DTLS_AUTHENTICATION_FAILURE == info->result)
335 //in case of error from owner credential
336 if(memcmp(&(newDevDoxm->owner), &emptyUuid, sizeof(OicUuid_t)) != 0 &&
337 true == newDevDoxm->owned)
339 OIC_LOG(ERROR, TAG, "The owner credential may incorrect.");
341 if(OC_STACK_OK != RemoveCredential(&(newDevDoxm->deviceID)))
343 OIC_LOG(WARNING, TAG, "Failed to remove the invaild owner credential");
345 SetResult(g_otmCtx, OC_STACK_AUTHENTICATION_FAILURE);
347 //in case of error from wrong PIN, re-start the ownership transfer
348 else if(OIC_RANDOM_DEVICE_PIN == newDevDoxm->oxmSel)
350 OIC_LOG(ERROR, TAG, "The PIN number may incorrect.");
352 memcpy(&(newDevDoxm->owner), &emptyUuid, sizeof(OicUuid_t));
353 newDevDoxm->owned = false;
354 g_otmCtx->attemptCnt++;
356 if(WRONG_PIN_MAX_ATTEMP > g_otmCtx->attemptCnt)
358 res = StartOwnershipTransfer(g_otmCtx, g_otmCtx->selectedDeviceInfo);
359 if(OC_STACK_OK != res)
361 SetResult(g_otmCtx, res);
362 OIC_LOG(ERROR, TAG, "Failed to Re-StartOwnershipTransfer");
367 OIC_LOG(ERROR, TAG, "User has exceeded the number of authentication attempts.");
368 SetResult(g_otmCtx, OC_STACK_AUTHENTICATION_FAILURE);
373 OIC_LOG(ERROR, TAG, "Failed to establish secure session.");
374 SetResult(g_otmCtx, OC_STACK_AUTHENTICATION_FAILURE);
383 * Function to save ownerPSK at provisioning tool end.
385 * @param[in] selectedDeviceInfo selected device information to performing provisioning.
386 * @return OC_STACK_OK on success
388 static OCStackResult SaveOwnerPSK(OCProvisionDev_t *selectedDeviceInfo)
390 OIC_LOG(DEBUG, TAG, "IN SaveOwnerPSK");
392 OCStackResult res = OC_STACK_ERROR;
394 CAEndpoint_t endpoint;
395 memset(&endpoint, 0x00, sizeof(CAEndpoint_t));
396 OICStrcpy(endpoint.addr, MAX_ADDR_STR_SIZE_CA, selectedDeviceInfo->endpoint.addr);
397 endpoint.addr[MAX_ADDR_STR_SIZE_CA - 1] = '\0';
398 endpoint.port = selectedDeviceInfo->securePort;
400 OicUuid_t ptDeviceID = {.id={0}};
401 if (OC_STACK_OK != GetDoxmDeviceID(&ptDeviceID))
403 OIC_LOG(ERROR, TAG, "Error while retrieving provisioning tool's device ID");
407 uint8_t ownerPSK[OWNER_PSK_LENGTH_128] = {0};
408 OicSecKey_t ownerKey = {ownerPSK, OWNER_PSK_LENGTH_128};
410 //Generating OwnerPSK
411 CAResult_t pskRet = CAGenerateOwnerPSK(&endpoint,
412 (uint8_t *)GetOxmString(selectedDeviceInfo->doxm->oxmSel),
413 strlen(GetOxmString(selectedDeviceInfo->doxm->oxmSel)),
414 ptDeviceID.id, sizeof(ptDeviceID.id),
415 selectedDeviceInfo->doxm->deviceID.id, sizeof(selectedDeviceInfo->doxm->deviceID.id),
416 ownerPSK, OWNER_PSK_LENGTH_128);
418 if (CA_STATUS_OK == pskRet)
420 OIC_LOG(INFO, TAG,"ownerPSK dump:\n");
421 OIC_LOG_BUFFER(INFO, TAG,ownerPSK, OWNER_PSK_LENGTH_128);
422 //Generating new credential for provisioning tool
423 OicSecCred_t *cred = GenerateCredential(&selectedDeviceInfo->doxm->deviceID,
424 SYMMETRIC_PAIR_WISE_KEY, NULL,
425 &ownerKey, &ptDeviceID);
426 VERIFY_NON_NULL(TAG, cred, ERROR);
428 // TODO: Added as workaround. Will be replaced soon.
429 cred->privateData.encoding = OIC_ENCODING_RAW;
432 // NOTE: Test codes to use BASE64 encoded owner PSK.
433 uint32_t outSize = 0;
434 size_t b64BufSize = B64ENCODE_OUT_SAFESIZE((OWNER_PSK_LENGTH_128 + 1));
435 char* b64Buf = (uint8_t *)OICCalloc(1, b64BufSize);
436 VERIFY_NON_NULL(TAG, b64Buf, ERROR);
437 b64Encode(cred->privateData.data, cred->privateData.len, b64Buf, b64BufSize, &outSize);
439 OICFree( cred->privateData.data );
440 cred->privateData.data = (uint8_t *)OICCalloc(1, outSize + 1);
441 VERIFY_NON_NULL(TAG, cred->privateData.data, ERROR);
443 strncpy(cred->privateData.data, b64Buf, outSize);
444 cred->privateData.data[outSize] = '\0';
445 cred->privateData.encoding = OIC_ENCODING_BASE64;
446 cred->privateData.len = outSize;
448 #endif //End of Test codes
450 res = AddCredential(cred);
451 if(res != OC_STACK_OK)
453 DeleteCredList(cred);
459 OIC_LOG(ERROR, TAG, "CAGenerateOwnerPSK failed");
462 OIC_LOG(DEBUG, TAG, "OUT SaveOwnerPSK");
468 * Callback handler for OwnerShipTransferModeHandler API.
470 * @param[in] ctx ctx value passed to callback from calling function.
471 * @param[in] UNUSED handle to an invocation
472 * @param[in] clientResponse Response from queries to remote servers.
473 * @return OC_STACK_DELETE_TRANSACTION to delete the transaction
474 * and OC_STACK_KEEP_TRANSACTION to keep it.
476 static OCStackApplicationResult OwnerTransferModeHandler(void *ctx, OCDoHandle UNUSED,
477 OCClientResponse *clientResponse)
479 OIC_LOG(DEBUG, TAG, "IN OwnerTransferModeHandler");
481 VERIFY_NON_NULL(TAG, clientResponse, WARNING);
482 VERIFY_NON_NULL(TAG, ctx, WARNING);
484 OTMContext_t* otmCtx = (OTMContext_t*)ctx;
486 if(OC_STACK_RESOURCE_CHANGED == clientResponse->result)
488 OIC_LOG(INFO, TAG, "OwnerTransferModeHandler : response result = OC_STACK_OK");
489 //Send request : GET /oic/sec/pstat
490 OCStackResult res = GetProvisioningStatusResource(otmCtx);
491 if(OC_STACK_OK != res)
493 OIC_LOG(WARNING, TAG, "Failed to get pstat information");
494 SetResult(otmCtx, res);
499 OIC_LOG_V(WARNING, TAG, "OwnerTransferModeHandler : Client response is incorrect : %d",
500 clientResponse->result);
501 SetResult(otmCtx, clientResponse->result);
504 OIC_LOG(DEBUG, TAG, "OUT OwnerTransferModeHandler");
507 return OC_STACK_DELETE_TRANSACTION;
511 * Callback handler for ProvisioningStatusResouceHandler API.
513 * @param[in] ctx ctx value passed to callback from calling function.
514 * @param[in] UNUSED handle to an invocation
515 * @param[in] clientResponse Response from queries to remote servers.
516 * @return OC_STACK_DELETE_TRANSACTION to delete the transaction
517 * and OC_STACK_KEEP_TRANSACTION to keep it.
519 static OCStackApplicationResult ListMethodsHandler(void *ctx, OCDoHandle UNUSED,
520 OCClientResponse *clientResponse)
522 OIC_LOG(DEBUG, TAG, "IN ListMethodsHandler");
524 VERIFY_NON_NULL(TAG, clientResponse, WARNING);
525 VERIFY_NON_NULL(TAG, ctx, WARNING);
527 OTMContext_t* otmCtx = (OTMContext_t*)ctx;
529 if (OC_STACK_OK == clientResponse->result)
531 if (NULL == clientResponse->payload)
533 OIC_LOG(INFO, TAG, "Skiping Null payload");
534 SetResult(otmCtx, OC_STACK_ERROR);
535 return OC_STACK_DELETE_TRANSACTION;
538 if (PAYLOAD_TYPE_SECURITY != clientResponse->payload->type)
540 OIC_LOG(INFO, TAG, "Unknown payload type");
541 SetResult(otmCtx, OC_STACK_ERROR);
542 return OC_STACK_DELETE_TRANSACTION;
544 OicSecPstat_t* pstat = NULL;
545 OCStackResult result = CBORPayloadToPstat(
546 ((OCSecurityPayload*)clientResponse->payload)->securityData,
547 ((OCSecurityPayload*)clientResponse->payload)->payloadSize,
549 if(NULL == pstat || result != OC_STACK_OK)
551 OIC_LOG(ERROR, TAG, "Error while converting cbor to pstat.");
552 SetResult(otmCtx, OC_STACK_ERROR);
553 return OC_STACK_DELETE_TRANSACTION;
555 if(false == (TAKE_OWNER & pstat->cm))
557 OIC_LOG(ERROR, TAG, "Device pairing mode enabling owner transfer operations is disabled");
558 SetResult(otmCtx, OC_STACK_ERROR);
559 return OC_STACK_DELETE_TRANSACTION;
561 otmCtx->selectedDeviceInfo->pstat = pstat;
563 //Select operation mode (Currently supported SINGLE_SERVICE_CLIENT_DRIVEN only)
564 SelectOperationMode(otmCtx->selectedDeviceInfo, &(otmCtx->selectedDeviceInfo->pstat->om));
566 //Send request : POST /oic/sec/pstat [{"om":"bx11", .. }]
567 OCStackResult res = PostUpdateOperationMode(otmCtx);
568 if (OC_STACK_OK != res)
570 OIC_LOG(ERROR, TAG, "Error while updating operation mode.");
571 SetResult(otmCtx, res);
576 OIC_LOG_V(WARNING, TAG, "ListMethodsHandler : Client response is incorrect : %d",
577 clientResponse->result);
578 SetResult(otmCtx, clientResponse->result);
581 OIC_LOG(DEBUG, TAG, "OUT ListMethodsHandler");
583 return OC_STACK_DELETE_TRANSACTION;
587 * Response handler for update owner uuid request.
589 * @param[in] ctx ctx value passed to callback from calling function.
590 * @param[in] UNUSED handle to an invocation
591 * @param[in] clientResponse Response from queries to remote servers.
592 * @return OC_STACK_DELETE_TRANSACTION to delete the transaction
593 * and OC_STACK_KEEP_TRANSACTION to keep it.
595 static OCStackApplicationResult OwnerUuidUpdateHandler(void *ctx, OCDoHandle UNUSED,
596 OCClientResponse *clientResponse)
598 VERIFY_NON_NULL(TAG, clientResponse, WARNING);
599 VERIFY_NON_NULL(TAG, ctx, WARNING);
601 OIC_LOG(DEBUG, TAG, "IN OwnerUuidUpdateHandler");
603 OCStackResult res = OC_STACK_OK;
604 OTMContext_t* otmCtx = (OTMContext_t*)ctx;
606 if(OC_STACK_RESOURCE_CHANGED == clientResponse->result)
608 if(otmCtx && otmCtx->selectedDeviceInfo)
610 res = SaveOwnerPSK(otmCtx->selectedDeviceInfo);
611 if(OC_STACK_OK != res)
613 OIC_LOG(ERROR, TAG, "OwnerUuidUpdateHandler:Failed to owner PSK generation");
614 SetResult(otmCtx, res);
615 return OC_STACK_DELETE_TRANSACTION;
618 //POST owner credential to new device according to security spec B.
619 res = PostOwnerCredential(otmCtx);
620 if(OC_STACK_OK != res)
623 "OwnerUuidUpdateHandler:Failed to send PosT request for onwer credential");
624 SetResult(otmCtx, res);
625 return OC_STACK_DELETE_TRANSACTION;
631 res = clientResponse->result;
632 OIC_LOG_V(ERROR, TAG, "OwnerUuidHandler : Unexpected result %d", res);
633 SetResult(otmCtx, res);
636 OIC_LOG(DEBUG, TAG, "OUT OwnerUuidUpdateHandler");
639 return OC_STACK_DELETE_TRANSACTION;
643 * Response handler for update operation mode.
645 * @param[in] ctx ctx value passed to callback from calling function.
646 * @param[in] UNUSED handle to an invocation
647 * @param[in] clientResponse Response from queries to remote servers.
648 * @return OC_STACK_DELETE_TRANSACTION to delete the transaction
649 * and OC_STACK_KEEP_TRANSACTION to keep it.
651 static OCStackApplicationResult OperationModeUpdateHandler(void *ctx, OCDoHandle UNUSED,
652 OCClientResponse *clientResponse)
654 OIC_LOG(DEBUG, TAG, "IN OperationModeUpdateHandler");
656 VERIFY_NON_NULL(TAG, clientResponse, WARNING);
657 VERIFY_NON_NULL(TAG, ctx, WARNING);
659 OTMContext_t* otmCtx = (OTMContext_t*)ctx;
661 if (OC_STACK_RESOURCE_CHANGED == clientResponse->result)
663 OCStackResult res = OC_STACK_ERROR;
664 OicSecOxm_t selOxm = otmCtx->selectedDeviceInfo->doxm->oxmSel;
666 //Load secret for temporal secure session.
667 if(g_OTMDatas[selOxm].loadSecretCB)
669 res = g_OTMDatas[selOxm].loadSecretCB(otmCtx);
670 if(OC_STACK_OK != res)
672 OIC_LOG(ERROR, TAG, "OperationModeUpdate : Failed to load secret");
673 SetResult(otmCtx, res);
674 return OC_STACK_DELETE_TRANSACTION;
678 //It will be used in handshake event handler
681 //Try DTLS handshake to generate secure session
682 if(g_OTMDatas[selOxm].createSecureSessionCB)
684 res = g_OTMDatas[selOxm].createSecureSessionCB(otmCtx);
685 if(OC_STACK_OK != res)
687 OIC_LOG(ERROR, TAG, "OperationModeUpdate : Failed to create DTLS session");
688 SetResult(otmCtx, res);
689 return OC_STACK_DELETE_TRANSACTION;
695 OIC_LOG(ERROR, TAG, "Error while update operation mode");
696 SetResult(otmCtx, clientResponse->result);
699 OIC_LOG(DEBUG, TAG, "OUT OperationModeUpdateHandler");
702 return OC_STACK_DELETE_TRANSACTION;
706 * Response handler for update owner crendetial request.
708 * @param[in] ctx ctx value passed to callback from calling function.
709 * @param[in] UNUSED handle to an invocation
710 * @param[in] clientResponse Response from queries to remote servers.
711 * @return OC_STACK_DELETE_TRANSACTION to delete the transaction
712 * and OC_STACK_KEEP_TRANSACTION to keep it.
714 static OCStackApplicationResult OwnerCredentialHandler(void *ctx, OCDoHandle UNUSED,
715 OCClientResponse *clientResponse)
717 VERIFY_NON_NULL(TAG, clientResponse, WARNING);
718 VERIFY_NON_NULL(TAG, ctx, WARNING);
720 OIC_LOG(DEBUG, TAG, "IN OwnerCredentialHandler");
722 OCStackResult res = OC_STACK_OK;
723 OTMContext_t* otmCtx = (OTMContext_t*)ctx;
725 if(OC_STACK_RESOURCE_CREATED == clientResponse->result)
727 if(otmCtx && otmCtx->selectedDeviceInfo)
729 //Close the temporal secure session to verify the owner credential
730 CAEndpoint_t* endpoint = (CAEndpoint_t *)&otmCtx->selectedDeviceInfo->endpoint;
731 endpoint->port = otmCtx->selectedDeviceInfo->securePort;
732 CAResult_t caResult = CACloseDtlsSession(endpoint);
733 if(CA_STATUS_OK != caResult)
735 OIC_LOG(ERROR, TAG, "Failed to close DTLS session");
736 SetResult(otmCtx, caResult);
737 return OC_STACK_DELETE_TRANSACTION;
741 * If we select NULL cipher,
742 * client will select appropriate cipher suite according to server's cipher-suite list.
744 caResult = CASelectCipherSuite(TLS_NULL_WITH_NULL_NULL);
745 if(CA_STATUS_OK != caResult)
747 OIC_LOG(ERROR, TAG, "Failed to select TLS_NULL_WITH_NULL_NULL");
748 SetResult(otmCtx, caResult);
749 return OC_STACK_DELETE_TRANSACTION;
753 * in case of random PIN based OxM,
754 * revert get_psk_info callback of tinyDTLS to use owner credential.
756 if(OIC_RANDOM_DEVICE_PIN == otmCtx->selectedDeviceInfo->doxm->oxmSel)
758 OicUuid_t emptyUuid = { .id={0}};
759 SetUuidForRandomPinOxm(&emptyUuid);
761 if(CA_STATUS_OK != CARegisterDTLSCredentialsHandler(GetDtlsPskCredentials))
763 OIC_LOG(ERROR, TAG, "Failed to revert DTLS credential handler.");
764 SetResult(otmCtx, OC_STACK_INVALID_CALLBACK);
765 return OC_STACK_DELETE_TRANSACTION;
769 //POST /oic/sec/doxm [{ ..., "owned":"TRUE" }]
770 res = PostOwnershipInformation(otmCtx);
771 if(OC_STACK_OK != res)
773 OIC_LOG(ERROR, TAG, "Failed to post ownership information to new device");
774 SetResult(otmCtx, res);
775 return OC_STACK_DELETE_TRANSACTION;
781 res = clientResponse->result;
782 OIC_LOG_V(ERROR, TAG, "OwnerCredentialHandler : Unexpected result %d", res);
783 SetResult(otmCtx, res);
786 OIC_LOG(DEBUG, TAG, "OUT OwnerCredentialHandler");
789 return OC_STACK_DELETE_TRANSACTION;
794 * Response handler for update owner information request.
796 * @param[in] ctx ctx value passed to callback from calling function.
797 * @param[in] UNUSED handle to an invocation
798 * @param[in] clientResponse Response from queries to remote servers.
799 * @return OC_STACK_DELETE_TRANSACTION to delete the transaction
800 * and OC_STACK_KEEP_TRANSACTION to keep it.
802 static OCStackApplicationResult OwnershipInformationHandler(void *ctx, OCDoHandle UNUSED,
803 OCClientResponse *clientResponse)
805 VERIFY_NON_NULL(TAG, clientResponse, WARNING);
806 VERIFY_NON_NULL(TAG, ctx, WARNING);
808 OIC_LOG(DEBUG, TAG, "IN OwnershipInformationHandler");
810 OCStackResult res = OC_STACK_OK;
811 OTMContext_t* otmCtx = (OTMContext_t*)ctx;
813 if(OC_STACK_RESOURCE_CHANGED == clientResponse->result)
815 if(otmCtx && otmCtx->selectedDeviceInfo)
817 OIC_LOG(INFO, TAG, "Ownership transfer was successfully completed.");
818 OIC_LOG(INFO, TAG, "Set Ready for provisioning state .");
820 res = PostProvisioningStatus(otmCtx);
821 if(OC_STACK_OK != res)
823 OIC_LOG(ERROR, TAG, "Failed to update pstat");
824 SetResult(otmCtx, res);
830 res = clientResponse->result;
831 OIC_LOG_V(ERROR, TAG, "OwnershipInformationHandler : Unexpected result %d", res);
832 SetResult(otmCtx, res);
835 OIC_LOG(DEBUG, TAG, "OUT OwnershipInformationHandler");
838 return OC_STACK_DELETE_TRANSACTION;
842 * Response handler of update provisioning status.
844 * @param[in] ctx ctx value passed to callback from calling function.
845 * @param[in] UNUSED handle to an invocation
846 * @param[in] clientResponse Response from queries to remote servers.
847 * @return OC_STACK_DELETE_TRANSACTION to delete the transaction
848 * and OC_STACK_KEEP_TRANSACTION to keep it.
850 static OCStackApplicationResult ProvisioningStatusHandler(void *ctx, OCDoHandle UNUSED,
851 OCClientResponse *clientResponse)
853 OIC_LOG_V(INFO, TAG, "IN ProvisioningStatusHandler.");
855 VERIFY_NON_NULL(TAG, clientResponse, ERROR);
856 VERIFY_NON_NULL(TAG, ctx, ERROR);
858 OTMContext_t* otmCtx = (OTMContext_t*) ctx;
860 OCStackResult res = OC_STACK_OK;
862 if(OC_STACK_RESOURCE_CHANGED == clientResponse->result)
864 if(otmCtx && otmCtx->selectedDeviceInfo)
866 OIC_LOG(INFO, TAG, "Device state is in Ready for Provisionig.");
868 res = PostNormalOperationStatus(otmCtx);
869 if(OC_STACK_OK != res)
871 OIC_LOG(ERROR, TAG, "Failed to update pstat");
872 SetResult(otmCtx, res);
878 OIC_LOG_V(INFO, TAG, "Error occured in provisionDefaultACLCB :: %d\n",
879 clientResponse->result);
880 SetResult(otmCtx, clientResponse->result);
884 OIC_LOG_V(INFO, TAG, "OUT ProvisioningStatusHandler.");
885 return OC_STACK_DELETE_TRANSACTION;
889 * Response handler of update provisioning status to Ready for Normal..
891 * @param[in] ctx ctx value passed to callback from calling function.
892 * @param[in] UNUSED handle to an invocation
893 * @param[in] clientResponse Response from queries to remote servers.
894 * @return OC_STACK_DELETE_TRANSACTION to delete the transaction
895 * and OC_STACK_KEEP_TRANSACTION to keep it.
897 static OCStackApplicationResult ReadyForNomalStatusHandler(void *ctx, OCDoHandle UNUSED,
898 OCClientResponse *clientResponse)
900 OIC_LOG_V(INFO, TAG, "IN ReadyForNomalStatusHandler.");
902 VERIFY_NON_NULL(TAG, clientResponse, ERROR);
903 VERIFY_NON_NULL(TAG, ctx, ERROR);
905 OTMContext_t* otmCtx = (OTMContext_t*) ctx;
908 if (OC_STACK_RESOURCE_CHANGED == clientResponse->result)
910 OIC_LOG(INFO, TAG, "Device state is in Ready for Normal Operation.");
911 OCStackResult res = PDMAddDevice(&otmCtx->selectedDeviceInfo->doxm->deviceID);
912 if (OC_STACK_OK == res)
914 OIC_LOG_V(INFO, TAG, "Add device's UUID in PDM_DB");
915 SetResult(otmCtx, OC_STACK_OK);
916 return OC_STACK_DELETE_TRANSACTION;
920 OIC_LOG(ERROR, TAG, "Ownership transfer is complete but adding information to DB is failed.");
925 OIC_LOG_V(INFO, TAG, "Error occured in provisionDefaultACLCB :: %d\n",
926 clientResponse->result);
927 SetResult(otmCtx, clientResponse->result);
931 OIC_LOG_V(INFO, TAG, "OUT ReadyForNomalStatusHandler.");
932 return OC_STACK_DELETE_TRANSACTION;
935 static OCStackResult PostOwnerCredential(OTMContext_t* otmCtx)
937 OIC_LOG(DEBUG, TAG, "IN PostOwnerCredential");
939 if(!otmCtx || !otmCtx->selectedDeviceInfo)
941 OIC_LOG(ERROR, TAG, "Invalid parameters");
942 return OC_STACK_INVALID_PARAM;
945 OCProvisionDev_t* deviceInfo = otmCtx->selectedDeviceInfo;
946 char query[MAX_URI_LENGTH + MAX_QUERY_LENGTH] = {0};
948 if(!PMGenerateQuery(true,
949 deviceInfo->endpoint.addr, deviceInfo->securePort,
950 deviceInfo->connType,
951 query, sizeof(query), OIC_RSRC_CRED_URI))
953 OIC_LOG(ERROR, TAG, "PostOwnerCredential : Failed to generate query");
954 return OC_STACK_ERROR;
956 OIC_LOG_V(DEBUG, TAG, "Query=%s", query);
957 OCSecurityPayload* secPayload = (OCSecurityPayload*)OICCalloc(1, sizeof(OCSecurityPayload));
960 OIC_LOG(ERROR, TAG, "Failed to memory allocation");
961 return OC_STACK_NO_MEMORY;
964 //Generate owner credential for new device
965 secPayload->base.type = PAYLOAD_TYPE_SECURITY;
966 const OicSecCred_t* ownerCredential = GetCredResourceData(&(deviceInfo->doxm->deviceID));
969 OIC_LOG(ERROR, TAG, "Can not find OwnerPSK.");
970 return OC_STACK_NO_RESOURCE;
973 OicUuid_t credSubjectId = {.id={0}};
974 if(OC_STACK_OK == GetDoxmDeviceID(&credSubjectId))
976 OicSecCred_t newCredential;
977 memcpy(&newCredential, ownerCredential, sizeof(OicSecCred_t));
978 newCredential.next = NULL;
980 //Set subject ID as PT's ID
981 memcpy(&(newCredential.subject), &credSubjectId, sizeof(OicUuid_t));
983 //Fill private data as empty string
984 newCredential.privateData.data = "";
985 newCredential.privateData.len = 0;
986 newCredential.privateData.encoding = ownerCredential->privateData.encoding;
988 newCredential.publicData.data = NULL;
989 newCredential.publicData.len = 0;
992 //Send owner credential to new device : POST /oic/sec/cred [ owner credential ]
993 if (OC_STACK_OK != CredToCBORPayload(&newCredential, &secPayload->securityData,
994 &secPayload->payloadSize, secureFlag))
997 OIC_LOG(ERROR, TAG, "Error while converting bin to cbor.");
998 return OC_STACK_ERROR;
1000 OIC_LOG(DEBUG, TAG, "Cred Payload:");
1001 OIC_LOG_BUFFER(DEBUG, TAG, secPayload->securityData, secPayload->payloadSize);
1003 OCCallbackData cbData;
1004 cbData.cb = &OwnerCredentialHandler;
1005 cbData.context = (void *)otmCtx;
1007 OCStackResult res = OCDoResource(NULL, OC_REST_POST, query,
1008 &deviceInfo->endpoint, (OCPayload*)secPayload,
1009 deviceInfo->connType, OC_HIGH_QOS, &cbData, NULL, 0);
1010 if (res != OC_STACK_OK)
1012 OIC_LOG(ERROR, TAG, "OCStack resource error");
1017 OIC_LOG(ERROR, TAG, "Failed to read DOXM device ID.");
1018 return OC_STACK_NO_RESOURCE;
1021 OIC_LOG(DEBUG, TAG, "OUT PostOwnerCredential");
1026 static OCStackResult PostOwnerTransferModeToResource(OTMContext_t* otmCtx)
1028 OIC_LOG(DEBUG, TAG, "IN PostOwnerTransferModeToResource");
1030 if(!otmCtx || !otmCtx->selectedDeviceInfo)
1032 OIC_LOG(ERROR, TAG, "Invalid parameters");
1033 return OC_STACK_INVALID_PARAM;
1036 OCProvisionDev_t* deviceInfo = otmCtx->selectedDeviceInfo;
1037 OicSecOxm_t selectedOxm = deviceInfo->doxm->oxmSel;
1038 char query[MAX_URI_LENGTH + MAX_QUERY_LENGTH] = {0};
1040 if(!PMGenerateQuery(false,
1041 deviceInfo->endpoint.addr, deviceInfo->endpoint.port,
1042 deviceInfo->connType,
1043 query, sizeof(query), OIC_RSRC_DOXM_URI))
1045 OIC_LOG(ERROR, TAG, "PostOwnerTransferModeToResource : Failed to generate query");
1046 return OC_STACK_ERROR;
1048 OIC_LOG_V(DEBUG, TAG, "Query=%s", query);
1049 OCSecurityPayload* secPayload = (OCSecurityPayload*)OICCalloc(1, sizeof(OCSecurityPayload));
1052 OIC_LOG(ERROR, TAG, "Failed to memory allocation");
1053 return OC_STACK_NO_MEMORY;
1055 secPayload->base.type = PAYLOAD_TYPE_SECURITY;
1056 OCStackResult res = g_OTMDatas[selectedOxm].createSelectOxmPayloadCB(otmCtx,
1057 &secPayload->securityData, &secPayload->payloadSize);
1058 if (OC_STACK_OK != res && NULL == secPayload->securityData)
1060 OCPayloadDestroy((OCPayload *)secPayload);
1061 OIC_LOG(ERROR, TAG, "Error while converting bin to cbor");
1062 return OC_STACK_ERROR;
1065 OCCallbackData cbData;
1066 cbData.cb = &OwnerTransferModeHandler;
1067 cbData.context = (void *)otmCtx;
1069 res = OCDoResource(NULL, OC_REST_POST, query,
1070 &deviceInfo->endpoint, (OCPayload *)secPayload,
1071 deviceInfo->connType, OC_HIGH_QOS, &cbData, NULL, 0);
1072 if (res != OC_STACK_OK)
1074 OIC_LOG(ERROR, TAG, "OCStack resource error");
1077 OIC_LOG(DEBUG, TAG, "OUT PostOwnerTransferModeToResource");
1082 static OCStackResult GetProvisioningStatusResource(OTMContext_t* otmCtx)
1084 OIC_LOG(DEBUG, TAG, "IN GetProvisioningStatusResource");
1086 if(!otmCtx || !otmCtx->selectedDeviceInfo)
1088 OIC_LOG(ERROR, TAG, "Invailed parameters");
1089 return OC_STACK_INVALID_PARAM;
1092 OCProvisionDev_t* deviceInfo = otmCtx->selectedDeviceInfo;
1093 char query[MAX_URI_LENGTH + MAX_QUERY_LENGTH] = {0};
1094 if(!PMGenerateQuery(false,
1095 deviceInfo->endpoint.addr, deviceInfo->endpoint.port,
1096 deviceInfo->connType,
1097 query, sizeof(query), OIC_RSRC_PSTAT_URI))
1099 OIC_LOG(ERROR, TAG, "GetProvisioningStatusResource : Failed to generate query");
1100 return OC_STACK_ERROR;
1102 OIC_LOG_V(DEBUG, TAG, "Query=%s", query);
1104 OCCallbackData cbData;
1105 cbData.cb = &ListMethodsHandler;
1106 cbData.context = (void *)otmCtx;
1108 OCStackResult res = OCDoResource(NULL, OC_REST_GET, query, NULL, NULL,
1109 deviceInfo->connType, OC_HIGH_QOS, &cbData, NULL, 0);
1110 if (res != OC_STACK_OK)
1112 OIC_LOG(ERROR, TAG, "OCStack resource error");
1115 OIC_LOG(DEBUG, TAG, "OUT GetProvisioningStatusResource");
1120 static OCStackResult PostOwnerUuid(OTMContext_t* otmCtx)
1122 OIC_LOG(DEBUG, TAG, "IN PostOwnerUuid");
1124 if(!otmCtx || !otmCtx->selectedDeviceInfo)
1126 OIC_LOG(ERROR, TAG, "Invailed parameters");
1127 return OC_STACK_INVALID_PARAM;
1130 OCProvisionDev_t* deviceInfo = otmCtx->selectedDeviceInfo;
1131 char query[MAX_URI_LENGTH + MAX_QUERY_LENGTH] = {0};
1132 if(!PMGenerateQuery(true,
1133 deviceInfo->endpoint.addr, deviceInfo->securePort,
1134 deviceInfo->connType,
1135 query, sizeof(query), OIC_RSRC_DOXM_URI))
1137 OIC_LOG(ERROR, TAG, "PostOwnerUuid : Failed to generate query");
1138 return OC_STACK_ERROR;
1140 OIC_LOG_V(DEBUG, TAG, "Query=%s", query);
1142 //Post PT's uuid to new device
1143 OCSecurityPayload* secPayload = (OCSecurityPayload*)OICCalloc(1, sizeof(OCSecurityPayload));
1146 OIC_LOG(ERROR, TAG, "Failed to memory allocation");
1147 return OC_STACK_NO_MEMORY;
1149 secPayload->base.type = PAYLOAD_TYPE_SECURITY;
1150 OCStackResult res = g_OTMDatas[deviceInfo->doxm->oxmSel].createOwnerTransferPayloadCB(
1151 otmCtx, &secPayload->securityData, &secPayload->payloadSize);
1152 if (OC_STACK_OK != res && NULL == secPayload->securityData)
1154 OCPayloadDestroy((OCPayload *)secPayload);
1155 OIC_LOG(ERROR, TAG, "Error while converting doxm bin to cbor.");
1156 return OC_STACK_INVALID_PARAM;
1158 OIC_LOG_BUFFER(DEBUG, TAG, secPayload->securityData, secPayload->payloadSize);
1160 OCCallbackData cbData;
1161 cbData.cb = &OwnerUuidUpdateHandler;
1162 cbData.context = (void *)otmCtx;
1165 res = OCDoResource(NULL, OC_REST_POST, query, 0, (OCPayload *)secPayload,
1166 deviceInfo->connType, OC_HIGH_QOS, &cbData, NULL, 0);
1167 if (res != OC_STACK_OK)
1169 OIC_LOG(ERROR, TAG, "OCStack resource error");
1172 OIC_LOG(DEBUG, TAG, "OUT PostOwnerUuid");
1177 static OCStackResult PostOwnershipInformation(OTMContext_t* otmCtx)
1179 OIC_LOG(DEBUG, TAG, "IN PostOwnershipInformation");
1181 if(!otmCtx || !otmCtx->selectedDeviceInfo)
1183 OIC_LOG(ERROR, TAG, "Invailed parameters");
1184 return OC_STACK_INVALID_PARAM;
1187 OCProvisionDev_t* deviceInfo = otmCtx->selectedDeviceInfo;
1188 char query[MAX_URI_LENGTH + MAX_QUERY_LENGTH] = {0};
1189 if(!PMGenerateQuery(true,
1190 deviceInfo->endpoint.addr, deviceInfo->securePort,
1191 deviceInfo->connType,
1192 query, sizeof(query), OIC_RSRC_DOXM_URI))
1194 OIC_LOG(ERROR, TAG, "PostOwnershipInformation : Failed to generate query");
1195 return OC_STACK_ERROR;
1197 OIC_LOG_V(DEBUG, TAG, "Query=%s", query);
1199 //OwnershipInformationHandler
1200 OCSecurityPayload *secPayload = (OCSecurityPayload*)OICCalloc(1, sizeof(OCSecurityPayload));
1203 OIC_LOG(ERROR, TAG, "Failed to memory allocation");
1204 return OC_STACK_NO_MEMORY;
1207 otmCtx->selectedDeviceInfo->doxm->owned = true;
1209 secPayload->base.type = PAYLOAD_TYPE_SECURITY;
1210 OCStackResult res = DoxmToCBORPayload(otmCtx->selectedDeviceInfo->doxm,
1211 &secPayload->securityData, &secPayload->payloadSize);
1212 if (OC_STACK_OK != res && NULL == secPayload->securityData)
1214 OCPayloadDestroy((OCPayload *)secPayload);
1215 OIC_LOG(ERROR, TAG, "Error while converting doxm bin to json");
1216 return OC_STACK_INVALID_PARAM;
1219 OCCallbackData cbData;
1220 cbData.cb = &OwnershipInformationHandler;
1221 cbData.context = (void *)otmCtx;
1224 res = OCDoResource(NULL, OC_REST_POST, query, 0, (OCPayload*)secPayload,
1225 deviceInfo->connType, OC_HIGH_QOS, &cbData, NULL, 0);
1226 if (res != OC_STACK_OK)
1228 OIC_LOG(ERROR, TAG, "OCStack resource error");
1231 OIC_LOG(DEBUG, TAG, "OUT PostOwnershipInformation");
1236 static OCStackResult PostUpdateOperationMode(OTMContext_t* otmCtx)
1238 OIC_LOG(DEBUG, TAG, "IN PostUpdateOperationMode");
1240 if(!otmCtx || !otmCtx->selectedDeviceInfo)
1242 return OC_STACK_INVALID_PARAM;
1245 OCProvisionDev_t* deviceInfo = otmCtx->selectedDeviceInfo;
1246 char query[MAX_URI_LENGTH + MAX_QUERY_LENGTH] = {0};
1247 if(!PMGenerateQuery(false,
1248 deviceInfo->endpoint.addr, deviceInfo->endpoint.port,
1249 deviceInfo->connType,
1250 query, sizeof(query), OIC_RSRC_PSTAT_URI))
1252 OIC_LOG(ERROR, TAG, "PostUpdateOperationMode : Failed to generate query");
1253 return OC_STACK_ERROR;
1255 OIC_LOG_V(DEBUG, TAG, "Query=%s", query);
1257 OCSecurityPayload* secPayload = (OCSecurityPayload*)OICCalloc(1, sizeof(OCSecurityPayload));
1260 OIC_LOG(ERROR, TAG, "Failed to memory allocation");
1261 return OC_STACK_NO_MEMORY;
1263 secPayload->base.type = PAYLOAD_TYPE_SECURITY;
1264 OCStackResult res = PstatToCBORPayload(deviceInfo->pstat, &secPayload->securityData,
1265 &secPayload->payloadSize);
1266 if (OC_STACK_OK != res)
1268 OCPayloadDestroy((OCPayload *)secPayload);
1269 OIC_LOG(ERROR, TAG, "Error while converting pstat to cbor.");
1270 return OC_STACK_INVALID_PARAM;
1273 OCCallbackData cbData;
1274 cbData.cb = &OperationModeUpdateHandler;
1275 cbData.context = (void *)otmCtx;
1277 res = OCDoResource(NULL, OC_REST_POST, query, 0, (OCPayload *)secPayload,
1278 deviceInfo->connType, OC_HIGH_QOS, &cbData, NULL, 0);
1279 if (res != OC_STACK_OK)
1281 OIC_LOG(ERROR, TAG, "OCStack resource error");
1284 OIC_LOG(DEBUG, TAG, "OUT PostUpdateOperationMode");
1289 static OCStackResult StartOwnershipTransfer(void* ctx, OCProvisionDev_t* selectedDevice)
1291 OIC_LOG(INFO, TAG, "IN StartOwnershipTransfer");
1292 OTMContext_t* otmCtx = (OTMContext_t*)ctx;
1293 otmCtx->selectedDeviceInfo = selectedDevice;
1295 //Set to the lowest level OxM, and then find more higher level OxM.
1296 OCStackResult res = SelectProvisioningMethod(selectedDevice->doxm->oxm,
1297 selectedDevice->doxm->oxmLen,
1298 &selectedDevice->doxm->oxmSel);
1299 if(OC_STACK_OK != res)
1301 OIC_LOG(ERROR, TAG, "Failed to select the provisioning method");
1302 SetResult(otmCtx, res);
1305 OIC_LOG_V(DEBUG, TAG, "Selected provisoning method = %d", selectedDevice->doxm->oxmSel);
1307 //Send Req: POST /oic/sec/doxm [{..."OxmSel" :g_OTMDatas[Index of Selected OxM].OXMString,...}]
1308 res = PostOwnerTransferModeToResource(otmCtx);
1309 if(OC_STACK_OK != res)
1311 OIC_LOG(WARNING, TAG, "Failed to select the provisioning method");
1312 SetResult(otmCtx, res);
1316 //Register DTLS event handler to catch the dtls event while handshake
1317 if(CA_STATUS_OK != CARegisterDTLSHandshakeCallback(DTLSHandshakeCB))
1319 OIC_LOG(WARNING, TAG, "StartOwnershipTransfer : Failed to register DTLS handshake callback.");
1322 OIC_LOG(INFO, TAG, "OUT StartOwnershipTransfer");
1328 OCStackResult OTMSetOwnershipTransferCallbackData(OicSecOxm_t oxmType, OTMCallbackData_t* data)
1330 OIC_LOG(DEBUG, TAG, "IN OTMSetOwnerTransferCallbackData");
1334 OIC_LOG(ERROR, TAG, "OTMSetOwnershipTransferCallbackData : Invalid parameters");
1335 return OC_STACK_INVALID_PARAM;
1337 if(oxmType >= OIC_OXM_COUNT)
1339 OIC_LOG(INFO, TAG, "Unknow ownership transfer method");
1340 return OC_STACK_INVALID_PARAM;
1343 g_OTMDatas[oxmType].loadSecretCB= data->loadSecretCB;
1344 g_OTMDatas[oxmType].createSecureSessionCB = data->createSecureSessionCB;
1345 g_OTMDatas[oxmType].createSelectOxmPayloadCB = data->createSelectOxmPayloadCB;
1346 g_OTMDatas[oxmType].createOwnerTransferPayloadCB = data->createOwnerTransferPayloadCB;
1348 OIC_LOG(DEBUG, TAG, "OUT OTMSetOwnerTransferCallbackData");
1354 * NOTE : Unowned discovery should be done before performing OTMDoOwnershipTransfer
1356 OCStackResult OTMDoOwnershipTransfer(void* ctx,
1357 OCProvisionDev_t *selectedDevicelist,
1358 OCProvisionResultCB resultCallback)
1360 OIC_LOG(DEBUG, TAG, "IN OTMDoOwnershipTransfer");
1362 if (NULL == selectedDevicelist)
1364 return OC_STACK_INVALID_PARAM;
1366 if (NULL == resultCallback)
1368 return OC_STACK_INVALID_CALLBACK;
1371 OTMContext_t* otmCtx = (OTMContext_t*)OICCalloc(1,sizeof(OTMContext_t));
1374 OIC_LOG(ERROR, TAG, "Failed to create OTM Context");
1375 return OC_STACK_NO_MEMORY;
1377 otmCtx->ctxResultCallback = resultCallback;
1378 otmCtx->ctxHasError = false;
1379 otmCtx->userCtx = ctx;
1380 OCProvisionDev_t* pCurDev = selectedDevicelist;
1382 //Counting number of selected devices.
1383 otmCtx->ctxResultArraySize = 0;
1384 while(NULL != pCurDev)
1386 otmCtx->ctxResultArraySize++;
1387 pCurDev = pCurDev->next;
1390 otmCtx->ctxResultArray =
1391 (OCProvisionResult_t*)OICCalloc(otmCtx->ctxResultArraySize, sizeof(OCProvisionResult_t));
1392 if(NULL == otmCtx->ctxResultArray)
1394 OIC_LOG(ERROR, TAG, "OTMDoOwnershipTransfer : Failed to memory allocation");
1396 return OC_STACK_NO_MEMORY;
1398 pCurDev = selectedDevicelist;
1400 OCStackResult res = OC_STACK_OK;
1401 //Fill the device UUID for result array.
1402 for(size_t devIdx = 0; devIdx < otmCtx->ctxResultArraySize; devIdx++)
1404 //Checking duplication of Device ID.
1405 bool isDuplicate = true;
1406 res = PDMIsDuplicateDevice(&pCurDev->doxm->deviceID, &isDuplicate);
1407 if (OC_STACK_OK != res)
1413 OIC_LOG(ERROR, TAG, "OTMDoOwnershipTransfer : Device ID is duplicated");
1414 res = OC_STACK_INVALID_PARAM;
1417 memcpy(otmCtx->ctxResultArray[devIdx].deviceId.id,
1418 pCurDev->doxm->deviceID.id,
1420 otmCtx->ctxResultArray[devIdx].res = OC_STACK_CONTINUE;
1421 pCurDev = pCurDev->next;
1424 StartOwnershipTransfer(otmCtx, selectedDevicelist);
1426 OIC_LOG(DEBUG, TAG, "OUT OTMDoOwnershipTransfer");
1430 OICFree(otmCtx->ctxResultArray);
1435 OCStackResult PostProvisioningStatus(OTMContext_t* otmCtx)
1437 OIC_LOG(INFO, TAG, "IN PostProvisioningStatus");
1439 if(!otmCtx || !otmCtx->selectedDeviceInfo)
1441 OIC_LOG(ERROR, TAG, "OTMContext is NULL");
1442 return OC_STACK_INVALID_PARAM;
1445 //Change the TAKE_OWNER bit of CM to 0.
1446 otmCtx->selectedDeviceInfo->pstat->cm &= (~TAKE_OWNER);
1448 OCSecurityPayload *secPayload = (OCSecurityPayload *)OICCalloc(1, sizeof(OCSecurityPayload));
1451 OIC_LOG(ERROR, TAG, "Failed to memory allocation");
1452 return OC_STACK_NO_MEMORY;
1454 secPayload->base.type = PAYLOAD_TYPE_SECURITY;
1455 if (OC_STACK_OK != PstatToCBORPayload(otmCtx->selectedDeviceInfo->pstat,
1456 &secPayload->securityData, &secPayload->payloadSize))
1458 OCPayloadDestroy((OCPayload *)secPayload);
1459 return OC_STACK_INVALID_JSON;
1461 OIC_LOG(DEBUG, TAG, "Created payload for chage to Provisiong state");
1462 OIC_LOG_BUFFER(DEBUG, TAG, secPayload->securityData, secPayload->payloadSize);
1464 char query[MAX_URI_LENGTH + MAX_QUERY_LENGTH] = {0};
1465 if(!PMGenerateQuery(true,
1466 otmCtx->selectedDeviceInfo->endpoint.addr,
1467 otmCtx->selectedDeviceInfo->securePort,
1468 otmCtx->selectedDeviceInfo->connType,
1469 query, sizeof(query), OIC_RSRC_PSTAT_URI))
1471 OIC_LOG(ERROR, TAG, "PostProvisioningStatus : Failed to generate query");
1472 return OC_STACK_ERROR;
1474 OIC_LOG_V(DEBUG, TAG, "Query=%s", query);
1476 OCCallbackData cbData = {.context=NULL, .cb=NULL, .cd=NULL};
1477 cbData.cb = &ProvisioningStatusHandler;
1478 cbData.context = (void*)otmCtx;
1480 OCStackResult ret = OCDoResource(NULL, OC_REST_POST, query, 0, (OCPayload*)secPayload,
1481 otmCtx->selectedDeviceInfo->connType, OC_HIGH_QOS, &cbData, NULL, 0);
1482 OIC_LOG_V(INFO, TAG, "OCDoResource returned: %d",ret);
1483 if (ret != OC_STACK_OK)
1485 OIC_LOG(ERROR, TAG, "OCStack resource error");
1488 OIC_LOG(INFO, TAG, "OUT PostProvisioningStatus");
1493 OCStackResult PostNormalOperationStatus(OTMContext_t* otmCtx)
1495 OIC_LOG(INFO, TAG, "IN PostNormalOperationStatus");
1497 if(!otmCtx || !otmCtx->selectedDeviceInfo)
1499 OIC_LOG(ERROR, TAG, "OTMContext is NULL");
1500 return OC_STACK_INVALID_PARAM;
1504 otmCtx->selectedDeviceInfo->pstat->isOp = true;
1506 OCSecurityPayload *secPayload = (OCSecurityPayload *)OICCalloc(1, sizeof(OCSecurityPayload));
1509 OIC_LOG(ERROR, TAG, "Failed to memory allocation");
1510 return OC_STACK_NO_MEMORY;
1512 secPayload->base.type = PAYLOAD_TYPE_SECURITY;
1513 if (OC_STACK_OK != PstatToCBORPayload(otmCtx->selectedDeviceInfo->pstat,
1514 &secPayload->securityData, &secPayload->payloadSize))
1516 OCPayloadDestroy((OCPayload *)secPayload);
1517 return OC_STACK_INVALID_JSON;
1519 OIC_LOG(DEBUG, TAG, "Created payload for chage to Provisiong state");
1520 OIC_LOG_BUFFER(DEBUG, TAG, secPayload->securityData, secPayload->payloadSize);
1522 char query[MAX_URI_LENGTH + MAX_QUERY_LENGTH] = {0};
1523 if(!PMGenerateQuery(true,
1524 otmCtx->selectedDeviceInfo->endpoint.addr,
1525 otmCtx->selectedDeviceInfo->securePort,
1526 otmCtx->selectedDeviceInfo->connType,
1527 query, sizeof(query), OIC_RSRC_PSTAT_URI))
1529 OIC_LOG(ERROR, TAG, "PostNormalOperationStatus : Failed to generate query");
1530 return OC_STACK_ERROR;
1532 OIC_LOG_V(DEBUG, TAG, "Query=%s", query);
1534 OCCallbackData cbData = {.context=NULL, .cb=NULL, .cd=NULL};
1535 cbData.cb = &ReadyForNomalStatusHandler;
1536 cbData.context = (void*)otmCtx;
1538 OCStackResult ret = OCDoResource(NULL, OC_REST_POST, query, 0, (OCPayload*)secPayload,
1539 otmCtx->selectedDeviceInfo->connType, OC_HIGH_QOS, &cbData, NULL, 0);
1540 OIC_LOG_V(INFO, TAG, "OCDoResource returned: %d",ret);
1541 if (ret != OC_STACK_OK)
1543 OIC_LOG(ERROR, TAG, "OCStack resource error");
1546 OIC_LOG(INFO, TAG, "OUT PostNormalOperationStatus");