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
40 #include "oic_malloc.h"
41 #include "oic_string.h"
43 #include "cainterface.h"
47 #include "srmresourcestrings.h"
48 #include "doxmresource.h"
49 #include "pstatresource.h"
50 #include "credresource.h"
51 #include "aclresource.h"
52 #include "ownershiptransfermanager.h"
53 #include "securevirtualresourcetypes.h"
54 #include "oxmjustworks.h"
56 #include "pmutility.h"
58 // TODO: Not yet supported.
59 //#include "oxmrandompin.h"
61 #define DEFAULT_CONTEXT_VALUE 0x99
62 #define DEFAULT_SECURE_PORT 5684
66 OCProvisionResultCB g_resultCallback;
67 OCProvisionResult_t* g_resultArray = NULL;
68 uint32_t g_resultArraySize = 0;
69 bool hasError = false;
72 * Possible states of ownership transfer manager module.
77 SP_DISCOVERY_STARTED = (0x1 << 1),
78 SP_DISCOVERY_ERROR = (0x1 << 2),
79 SP_DISCOVERY_DONE = (0x1 << 3),
80 SP_UP_OWN_TR_METH_STARTED = (0x1 << 4),
81 SP_UP_OWN_TR_METH_ERROR = (0x1 << 5),
82 SP_UP_OWN_TR_METH_DONE = (0x1 << 6),
83 SP_LIST_METHODS_STARTED = (0x1 << 7),
84 SP_LIST_METHODS_ERROR = (0x1 << 8),
85 SP_LIST_METHODS_DONE = (0x1 << 9),
86 SP_UPDATE_OP_MODE_STARTED = (0x1 << 10),
87 SP_UPDATE_OP_MODE_ERROR = (0x1 << 11),
88 SP_UPDATE_OP_MODE_DONE = (0x1 << 12),
89 SP_UPDATE_OWNER_STARTED = (0x1 << 13),
90 SP_UPDATE_OWNER_ERROR = (0x1 << 14),
91 SP_UPDATE_OWNER_DONE = (0x1 << 15)
97 * Array to store the callbacks for each owner transfer method.
99 OTMCallbackData_t g_OTMDatas[OIC_OXM_COUNT];
102 * Variable for storing provisioning tool's provisioning capabilities
103 * Must be in decreasing order of preference. More prefered method should
104 * have lower array index.
106 static OicSecDpom_t gProvisioningToolCapability[] = { SINGLE_SERVICE_CLIENT_DRIVEN };
109 * Number of supported provisioning methods
110 * current version supports only one.
112 static int gNumOfProvisioningMethodsPT = 1;
115 * Function to getting string of ownership transfer method
117 static const char* GetOxmString(OicSecOxm_t oxmType)
122 return OXM_JUST_WORKS;
123 case OIC_MODE_SWITCH:
124 return OXM_MODE_SWITCH;
125 case OIC_RANDOM_DEVICE_PIN:
126 return OXM_RANDOM_DEVICE_PIN;
127 case OIC_PRE_PROVISIONED_DEVICE_PIN:
128 return OXM_PRE_PROVISIONED_DEVICE_PIN;
129 case OIC_PRE_PROVISION_STRONG_CREDENTIAL:
130 return OXM_PRE_PROVISIONED_STRONG_CREDENTIAL;
137 * Function to select appropriate provisioning method.
139 * @param[in] supportedMethodsList List of supported methods
140 * @param[out] selectedMethod Selected methods
141 * @return SP_SUCCESS on success
143 static OCStackResult SelectProvisioningMethod(const OicSecOxm_t *supportedMethods, size_t numberOfMethods,
144 OicSecOxm_t *selectedMethod)
147 OC_LOG(DEBUG, TAG, "IN SelectProvisioningMethod");
149 if(numberOfMethods == 0 || !supportedMethods)
151 OC_LOG(WARNING, TAG, "Could not find a supported OxM.");
152 return OC_STACK_ERROR;
155 *selectedMethod = supportedMethods[0];
156 for(i = 0; i < numberOfMethods; i++)
158 if(*selectedMethod < supportedMethods[i])
160 *selectedMethod = supportedMethods[i];
168 * Function to select operation mode.This function will return most secure common operation mode.
170 * @param[out] selectedMode selected operation mode
171 * @return SP_SUCCESS on success
173 static void SelectOperationMode(const OCProvisionDev_t *selectedDeviceInfo,
174 OicSecDpom_t *selectedMode)
176 OC_LOG(DEBUG, TAG, "IN SelectOperationMode");
181 while (i < gNumOfProvisioningMethodsPT && j < selectedDeviceInfo->pstat->smLen)
183 if (gProvisioningToolCapability[i] < selectedDeviceInfo->pstat->sm[j])
187 else if (selectedDeviceInfo->pstat->sm[j] < gProvisioningToolCapability[i])
191 else /* if gProvisioningToolCapability[i] == deviceSupportedMethods[j] */
193 *selectedMode = gProvisioningToolCapability[j];
197 OC_LOG(DEBUG, TAG, "OUT SelectOperationMode");
201 * Function to update owner transfer mode
203 * @param[in] deviceInfo Device Info.
204 * @return OC_STACK_OK on success
206 static OCStackResult PutOwnerTransferModeToResource(OTMContext_t* otmCtx);
209 * Function to send request to resource to get its pstat resource information.
211 * @param[in] deviceInfo Selected device Info.
212 * @param[in] otmCtx address of pointer variable for OTMContext_t
213 * @return OC_STACK_OK on success
215 static OCStackResult GetProvisioningStatusResource(OTMContext_t* otmCtx);
219 * Function to send ownerShip info. This function would update Owned as true and
220 * owner as UUID for provisioning tool
222 * @param[in] deviceInfo Selected device info
223 * @param[in] otmCtx address of pointer variable for OTMContext_t
224 * @return OC_STACK_OK on success
226 static OCStackResult PutOwnershipInformation(OTMContext_t* otmCtx);
229 * Function to update the operation mode. As per the spec. Operation mode in client driven
230 * single service provisioning it will be updated to 0x3
232 * @param[in] deviceInfo Selected device Info.
233 * @param[in] selectedOperationMode selected operation mode
234 * @param[in] otmCtx address of pointer variable for OTMContext_t
235 * @return OC_STACK_OK on success
237 static OCStackResult PutUpdateOperationMode(OTMContext_t* otmCtx,
238 OicSecDpom_t selectedOperationMode);
240 static OCStackResult StartOwnershipTransfer(void* ctx, OCProvisionDev_t* selectedDevice);
242 static OCStackResult FinalizeProvisioning(OTMContext_t* otmCtx);
245 static bool IsComplete()
248 for(i = 0; i < g_resultArraySize; i++)
250 if(OC_STACK_CONTINUE == g_resultArray[i].res)
259 static void SetResult(OTMContext_t* otmCtx, OCStackResult res)
263 OC_LOG(DEBUG, TAG, "IN SetResult");
267 OC_LOG(WARNING, TAG, "OTMContext is NULL");
270 if(otmCtx->selectedDeviceInfo)
272 for(i = 0; i < g_resultArraySize; i++)
274 if(memcmp(otmCtx->selectedDeviceInfo->doxm->deviceID.id,
275 g_resultArray[i].deviceId.id, UUID_LENGTH) == 0)
277 g_resultArray[i].res = res;
278 if(OC_STACK_OK != res)
285 //If all request is completed, invoke the user callback.
288 g_resultCallback(otmCtx->userCtx, g_resultArraySize, g_resultArray, hasError);
292 if(OC_STACK_OK != StartOwnershipTransfer(otmCtx->userCtx,
293 otmCtx->selectedDeviceInfo->next))
295 OC_LOG(ERROR, TAG, "Failed to StartOwnershipTransfer");
300 OC_LOG(DEBUG, TAG, "OUT SetResult");
307 * Function to save ownerPSK at provisioning tool end.
309 * @return OC_STACK_OK on success
311 static OCStackResult SaveOwnerPSK(OCProvisionDev_t *selectedDeviceInfo)
313 OC_LOG(DEBUG, TAG, "IN SaveOwnerPSK");
315 OCStackResult res = OC_STACK_ERROR;
317 CAEndpoint_t endpoint = {0};
318 OICStrcpy(endpoint.addr, MAX_ADDR_STR_SIZE_CA, selectedDeviceInfo->endpoint.addr);
319 endpoint.addr[MAX_ADDR_STR_SIZE_CA - 1] = '\0';
320 endpoint.port = selectedDeviceInfo->securePort;
322 OicUuid_t ptDeviceID = {};
323 if (OC_STACK_OK != GetDoxmDeviceID(&ptDeviceID))
325 OC_LOG(ERROR, TAG, "Error while retrieving provisioning tool's device ID");
329 uint8_t ownerPSK[OWNER_PSK_LENGTH_128] = {};
331 //Generating OwnerPSK
332 CAResult_t pskRet = CAGenerateOwnerPSK(&endpoint,
333 (uint8_t *)GetOxmString(selectedDeviceInfo->doxm->oxmSel),
334 strlen(GetOxmString(selectedDeviceInfo->doxm->oxmSel)), ptDeviceID.id,
335 sizeof(ptDeviceID.id), selectedDeviceInfo->doxm->deviceID.id,
336 sizeof(selectedDeviceInfo->doxm->deviceID.id), ownerPSK,
337 OWNER_PSK_LENGTH_128);
339 if (CA_STATUS_OK == pskRet)
341 OC_LOG(INFO, TAG,"ownerPSK dump:\n");
342 OC_LOG_BUFFER(INFO, TAG,ownerPSK, OWNER_PSK_LENGTH_128);
343 //Generating new credential for provisioning tool
347 char base64Buff[B64ENCODE_OUT_SAFESIZE(sizeof(ownerPSK)) + 1] = {};
348 B64Result b64Ret = b64Encode(ownerPSK, sizeof(ownerPSK), base64Buff, sizeof(base64Buff),
350 if (B64_OK == b64Ret)
352 OicSecCred_t *cred = GenerateCredential(&selectedDeviceInfo->doxm->deviceID,
353 SYMMETRIC_PAIR_WISE_KEY, NULL,
354 base64Buff, ownLen, &ptDeviceID);
357 //Update the SVR database.
358 if (OC_STACK_OK == AddCredential(cred))
364 OC_LOG(ERROR, TAG, "AddCredential failed");
369 OC_LOG(ERROR, TAG, "GenerateCredential failed");
374 OC_LOG(ERROR, TAG, "b64Encode failed");
379 OC_LOG(ERROR, TAG, "CAGenerateOwnerPSK failed");
382 OC_LOG(DEBUG, TAG, "OUT SaveOwnerPSK");
388 * Callback handler for OwnerShipTransferModeHandler API.
390 * @param[in] ctx IP of target device.
391 * @param[in] handle port of remote server.
392 * @param[in] clientResponse adapter type of endpoint.
393 * @param[in] doxm pointer to doxm instance.
394 * @return OC_STACK_KEEP_TRANSACTION to keep transaction and
395 * OC_STACK_DELETE_TRANSACTION to delete it.
397 static OCStackApplicationResult OwnerTransferModeHandler(void *ctx, OCDoHandle handle,
398 OCClientResponse *clientResponse)
402 OC_LOG(DEBUG, TAG, "IN OwnerTransferModeHandler");
404 OTMContext_t* otmCtx = (OTMContext_t*)ctx;
407 OC_LOG(ERROR, TAG, "Can't find OTMContext");
408 return OC_STACK_DELETE_TRANSACTION;
411 if(clientResponse->result == OC_STACK_OK)
413 OC_LOG(INFO, TAG, "OwnerTransferModeHandler : response result = OC_STACK_OK");
414 //Send request : GET /oic/sec/pstat
415 OCStackResult res = GetProvisioningStatusResource(otmCtx);
416 if(OC_STACK_OK != res)
419 OC_LOG(WARNING, TAG, "Failed to getting pstat information");
420 SetResult(otmCtx, res);
421 return OC_STACK_DELETE_TRANSACTION;
427 OC_LOG_V(WARNING, TAG, "OwnerTransferModeHandler : Client response is incorrect : %d",
428 clientResponse->result);
429 SetResult(otmCtx, clientResponse->result);
430 return OC_STACK_DELETE_TRANSACTION;
432 OC_LOG(DEBUG, TAG, "OUT OwnerTransferModeHandler");
435 return OC_STACK_DELETE_TRANSACTION;
439 * Callback handler for ProvisioningStatusResouceHandler API.
441 * @param[in] ctx IP of target device.
442 * @param[in] handle port of remote server.
443 * @param[in] clientResponse adapter type of endpoint.
444 * @param[in] doxm pointer to doxm instance.
445 * @return OC_STACK_KEEP_TRANSACTION to keep transaction and
446 * OC_STACK_DELETE_TRANSACTION to delete it.
448 static OCStackApplicationResult ListMethodsHandler(void *ctx, OCDoHandle handle,
449 OCClientResponse *clientResponse)
453 OC_LOG(DEBUG, TAG, "IN ListMethodsHandler");
455 OTMContext_t* otmCtx = (OTMContext_t*)ctx;
458 OC_LOG(ERROR, TAG, "Can't find OTMContext");
459 return OC_STACK_DELETE_TRANSACTION;
462 if (OC_STACK_OK == clientResponse->result)
464 if (NULL == clientResponse->payload)
466 OC_LOG(INFO, TAG, "Skiping Null payload");
467 SetResult(otmCtx, OC_STACK_ERROR);
468 return OC_STACK_DELETE_TRANSACTION;
471 if (PAYLOAD_TYPE_SECURITY != clientResponse->payload->type)
473 OC_LOG(INFO, TAG, "Unknown payload type");
474 SetResult(otmCtx, OC_STACK_ERROR);
475 return OC_STACK_KEEP_TRANSACTION;
478 OicSecPstat_t* pstat = JSONToPstatBin(
479 ((OCSecurityPayload*)clientResponse->payload)->securityData);
482 OC_LOG(ERROR, TAG, "Error while converting json to pstat bin");
483 SetResult(otmCtx, OC_STACK_ERROR);
484 return OC_STACK_DELETE_TRANSACTION;
486 otmCtx->selectedDeviceInfo->pstat = pstat;
488 //Select operation mode (Currently supported SINGLE_SERVICE_CLIENT_DRIVEN only)
489 OicSecDpom_t selectedOperationMode;
490 SelectOperationMode(otmCtx->selectedDeviceInfo, &selectedOperationMode);
492 //Send request : PUT /oic/sec/pstat [{"OM":"0x11", .. }]
493 OCStackResult res = PutUpdateOperationMode(otmCtx, selectedOperationMode);
494 if (OC_STACK_OK != res)
496 OC_LOG(ERROR, TAG, "Error while updating operation mode.");
497 SetResult(otmCtx, res);
503 OC_LOG_V(WARNING, TAG, "ListMethodsHandler : Client response is incorrect : %d",
504 clientResponse->result);
505 SetResult(otmCtx, clientResponse->result);
508 OC_LOG(DEBUG, TAG, "OUT ListMethodsHandler");
511 return OC_STACK_DELETE_TRANSACTION;
515 * Callback handler for OwnershipInformationHandler API.
517 * @param[in] ctx IP of target device.
518 * @param[in] handle port of remote server.
519 * @param[in] clientResponse adapter type of endpoint.
520 * @param[in] doxm pointer to doxm instance.
521 * @return OC_STACK_KEEP_TRANSACTION to keep transaction and
522 * OC_STACK_DELETE_TRANSACTION to delete it.
524 static OCStackApplicationResult OwnershipInformationHandler(void *ctx,
525 OCDoHandle handle, OCClientResponse *clientResponse)
530 OC_LOG(DEBUG, TAG, "IN OwnershipInformationHandler");
532 OCStackResult res = OC_STACK_OK;
533 OTMContext_t* otmCtx = (OTMContext_t*)ctx;
534 if (OC_STACK_OK == clientResponse->result)
536 res = SaveOwnerPSK(otmCtx->selectedDeviceInfo);
537 if(OC_STACK_OK != res)
539 OC_LOG(ERROR, TAG, "OperationModeUpdate : Failed to owner PSK generation");
540 SetResult(otmCtx, res);
541 return OC_STACK_DELETE_TRANSACTION;
544 CAEndpoint_t* endpoint = (CAEndpoint_t *)&otmCtx->selectedDeviceInfo->endpoint;
545 endpoint->port = otmCtx->selectedDeviceInfo->securePort;
546 CAResult_t closeRes = CACloseDtlsSession(endpoint);
547 if(CA_STATUS_OK != closeRes)
549 OC_LOG(ERROR, TAG, "Failed to close DTLS session");
550 SetResult(otmCtx, closeRes);
551 return OC_STACK_DELETE_TRANSACTION;
554 // TODO: PIN based OxM is required.
556 if(OIC_RANDOM_DEVICE_PIN == otmCtx->selectedDeviceInfo->doxm->oxmSel)
558 res = RemoveCredential(otmCtx->tempCredId);
559 if(OC_STACK_OK != res)
561 OC_LOG_V(ERROR, TAG, "Failed to remove temporal PSK : %d", res);
562 return OC_STACK_DELETE_TRANSACTION;
566 OC_LOG(INFO, TAG, "Ownership transfer was successfully completed.");
567 OC_LOG(INFO, TAG, "Start defualt ACL & commit-hash provisioning.");
569 res = FinalizeProvisioning(otmCtx);
570 if(OC_STACK_OK != res)
572 SetResult(otmCtx, res);
573 return OC_STACK_DELETE_TRANSACTION;
578 res = clientResponse->result;
581 OC_LOG(DEBUG, TAG, "OUT OwnershipInformationHandler");
584 return OC_STACK_DELETE_TRANSACTION;
588 * Response handler for update operation mode.
590 * @param[in] object Remote endpoint object
591 * @param[in] requestInfo Datastructure containing request information.
593 static OCStackApplicationResult OperationModeUpdateHandler(void *ctx,
594 OCDoHandle handle, OCClientResponse *clientResponse)
598 OC_LOG(DEBUG, TAG, "IN OperationModeUpdateHandler");
600 OTMContext_t* otmCtx = (OTMContext_t*)ctx;
601 if (OC_STACK_OK == clientResponse->result)
603 OCStackResult res = OC_STACK_ERROR;
604 OicSecOxm_t selOxm = otmCtx->selectedDeviceInfo->doxm->oxmSel;
606 //Load secret for temporal secure session.
607 if(g_OTMDatas[selOxm].loadSecretCB)
609 res = g_OTMDatas[selOxm].loadSecretCB(otmCtx);
610 if(OC_STACK_OK != res)
612 OC_LOG(ERROR, TAG, "OperationModeUpdate : Failed to load secret");
613 SetResult(otmCtx, res);
614 return OC_STACK_DELETE_TRANSACTION;
618 //Try DTLS handshake to generate secure session
619 if(g_OTMDatas[selOxm].createSecureSessionCB)
621 res = g_OTMDatas[selOxm].createSecureSessionCB(otmCtx);
622 if(OC_STACK_OK != res)
624 OC_LOG(ERROR, TAG, "OperationModeUpdate : Failed to create DTLS session");
625 SetResult(otmCtx, res);
626 return OC_STACK_DELETE_TRANSACTION;
630 //Send request : PUT /oic/sec/doxm [{"Owned":"True", .. , "Owner":"PT's UUID"}]
631 res = PutOwnershipInformation(otmCtx);
632 if(OC_STACK_OK != res)
634 OC_LOG(ERROR, TAG, "OperationModeUpdate : Failed to send owner information");
635 SetResult(otmCtx, res);
636 return OC_STACK_DELETE_TRANSACTION;
641 OC_LOG(ERROR, TAG, "Error while update operation mode");
642 SetResult(otmCtx, clientResponse->result);
643 return OC_STACK_DELETE_TRANSACTION;
645 OC_LOG(DEBUG, TAG, "OUT OperationModeUpdateHandler");
648 return OC_STACK_DELETE_TRANSACTION;
652 static OCStackResult PutOwnerTransferModeToResource(OTMContext_t* otmCtx)
654 OC_LOG(DEBUG, TAG, "IN PutOwnerTransferModeToResource");
656 if(!otmCtx || !otmCtx->selectedDeviceInfo)
658 OC_LOG(ERROR, TAG, "Invailed parameters");
659 return OC_STACK_INVALID_PARAM;
662 OCProvisionDev_t* deviceInfo = otmCtx->selectedDeviceInfo;
663 OicSecOxm_t selectedOxm = deviceInfo->doxm->oxmSel;
664 char query[MAX_QUERY_LENGTH] = {};
665 sprintf(query, "%s%s:%d%s", COAP_PREFIX,
666 deviceInfo->endpoint.addr, deviceInfo->endpoint.port,
668 OCSecurityPayload* secPayload = (OCSecurityPayload*)OICCalloc(1, sizeof(OCSecurityPayload));
671 OC_LOG(ERROR, TAG, "Failed to memory allocation");
672 return OC_STACK_NO_MEMORY;
674 secPayload->base.type = PAYLOAD_TYPE_SECURITY;
675 secPayload->securityData = g_OTMDatas[selectedOxm].createSelectOxmPayloadCB(otmCtx);
676 if (NULL == secPayload->securityData)
678 OC_LOG(ERROR, TAG, "Error while converting bin to json");
679 return OC_STACK_ERROR;
681 OC_LOG_V(DEBUG, TAG, "Payload : %s", secPayload->securityData);
683 OCCallbackData cbData;
684 cbData.cb = &OwnerTransferModeHandler;
685 cbData.context = (void *)otmCtx;
688 // TODO: 6th argument need to be changed, if we have to use CT_FLAG_SECURE
689 OCStackResult res = OCDoResource(NULL, OC_REST_PUT, query,
690 &deviceInfo->endpoint, (OCPayload*)secPayload,
691 CT_ADAPTER_IP, OC_LOW_QOS, &cbData, NULL, 0);
692 if (res != OC_STACK_OK)
694 OC_LOG(ERROR, TAG, "OCStack resource error");
697 OC_LOG(DEBUG, TAG, "OUT PutOwnerTransferModeToResource");
703 * Function to send request to resource to get its pstat resource information.
705 * @param[in] timeout timeout for operation.
706 * @param[in] deviceInfo Device Info.
707 * @return OC_STACK_OK on success
709 static OCStackResult GetProvisioningStatusResource(OTMContext_t* otmCtx)
711 OC_LOG(DEBUG, TAG, "IN GetProvisioningStatusResource");
713 if(!otmCtx || !otmCtx->selectedDeviceInfo)
715 OC_LOG(ERROR, TAG, "Invailed parameters");
716 return OC_STACK_INVALID_PARAM;
719 OCProvisionDev_t* deviceInfo = otmCtx->selectedDeviceInfo;
720 char query[MAX_QUERY_LENGTH] = {};
721 sprintf(query, "%s%s:%d%s", COAP_PREFIX,
722 deviceInfo->endpoint.addr, deviceInfo->endpoint.port,
724 OCCallbackData cbData;
725 cbData.cb = &ListMethodsHandler;
726 cbData.context = (void *)otmCtx;
729 // TODO: 6th argument need to be changed, if we have to use CT_FLAG_SECURE
730 OCStackResult res = OCDoResource(NULL, OC_REST_GET, query, NULL, NULL,
731 CT_ADAPTER_IP, OC_LOW_QOS, &cbData, NULL, 0);
732 if (res != OC_STACK_OK)
734 OC_LOG(ERROR, TAG, "OCStack resource error");
737 OC_LOG(DEBUG, TAG, "OUT GetProvisioningStatusResource");
744 * Function to send ownerShip info. This function would update Owned as true and
745 * owner as UUID for provisioning tool
747 * @param[in] timeout timeout value for the operation.
748 * @param[in] deviceInfo provisioning context.
749 * @return OC_STACK_OK on success
751 static OCStackResult PutOwnershipInformation(OTMContext_t* otmCtx)
753 OC_LOG(DEBUG, TAG, "IN PutOwnershipInformation");
755 if(!otmCtx || !otmCtx->selectedDeviceInfo)
757 OC_LOG(ERROR, TAG, "Invailed parameters");
758 return OC_STACK_INVALID_PARAM;
761 OCProvisionDev_t* deviceInfo = otmCtx->selectedDeviceInfo;
762 char query[MAX_QUERY_LENGTH] = {};
763 sprintf(query, "%s%s:%d%s", COAPS_PREFIX,
764 deviceInfo->endpoint.addr, deviceInfo->securePort,
766 //OwnershipInformationHandler
767 OicSecOxm_t selOxm = deviceInfo->doxm->oxmSel;
768 OCSecurityPayload* secPayload = (OCSecurityPayload*)OICCalloc(1, sizeof(OCSecurityPayload));
771 OC_LOG(ERROR, TAG, "Failed to memory allocation");
772 return OC_STACK_NO_MEMORY;
774 secPayload->base.type = PAYLOAD_TYPE_SECURITY;
775 secPayload->securityData = g_OTMDatas[selOxm].createOwnerTransferPayloadCB(otmCtx);
776 if (NULL == secPayload->securityData)
778 OC_LOG(ERROR, TAG, "Error while converting doxm bin to json");
779 return OC_STACK_INVALID_PARAM;
782 OCCallbackData cbData;
783 cbData.cb = &OwnershipInformationHandler;
784 cbData.context = (void *)otmCtx;
787 // TODO: 6th argument need to be changed, if we have to use CT_FLAG_SECURE
788 OCStackResult res = OCDoResource(NULL, OC_REST_PUT, query, 0, (OCPayload*)secPayload,
789 CT_ADAPTER_IP, OC_LOW_QOS, &cbData, NULL, 0);
790 if (res != OC_STACK_OK)
792 OC_LOG(ERROR, TAG, "OCStack resource error");
795 OC_LOG(DEBUG, TAG, "OUT PutOwnershipInformation");
801 * Function to update the operation mode. As per the spec. Operation mode in client driven
802 * single service provisioning it will be updated to 0x3
804 * @param[in] timeout timeout for operation.
805 * @param[in] deviceInfo Device Info.
806 * @return OC_STACK_OK on success
808 static OCStackResult PutUpdateOperationMode(OTMContext_t* otmCtx,
809 OicSecDpom_t selectedOperationMode)
811 OC_LOG(DEBUG, TAG, "IN PutUpdateOperationMode");
813 if(!otmCtx || !otmCtx->selectedDeviceInfo)
815 return OC_STACK_INVALID_PARAM;
818 OCProvisionDev_t* deviceInfo = otmCtx->selectedDeviceInfo;
819 char query[MAX_QUERY_LENGTH] = {};
820 sprintf(query, "%s%s:%d%s", COAP_PREFIX,
821 deviceInfo->endpoint.addr, deviceInfo->endpoint.port,
823 deviceInfo->pstat->om = selectedOperationMode;
825 OCSecurityPayload* secPayload = (OCSecurityPayload*)OICCalloc(1, sizeof(OCSecurityPayload));
828 OC_LOG(ERROR, TAG, "Failed to memory allocation");
829 return OC_STACK_NO_MEMORY;
831 secPayload->base.type = PAYLOAD_TYPE_SECURITY;
832 secPayload->securityData = BinToPstatJSON(deviceInfo->pstat);
833 if (NULL == secPayload->securityData)
835 OC_LOG(ERROR, TAG, "Error while converting pstat bin to json");
836 return OC_STACK_INVALID_PARAM;
839 OCCallbackData cbData;
840 cbData.cb = &OperationModeUpdateHandler;
841 cbData.context = (void *)otmCtx;
844 OCStackResult res = OCDoResource(NULL, OC_REST_PUT, query, 0, (OCPayload*)secPayload,
845 CT_ADAPTER_IP, OC_LOW_QOS, &cbData, NULL, 0);
846 if (res != OC_STACK_OK)
848 OC_LOG(ERROR, TAG, "OCStack resource error");
851 OC_LOG(DEBUG, TAG, "OUT PutUpdateOperationMode");
856 static OCStackResult StartOwnershipTransfer(void* ctx, OCProvisionDev_t* selectedDevice)
858 OC_LOG(INFO, TAG, "IN StartOwnershipTransfer");
859 OTMContext_t* otmCtx = (OTMContext_t*)OICMalloc(sizeof(OTMContext_t));
862 OC_LOG(ERROR, TAG, "Failed to create OTM Context");
863 return OC_STACK_NO_MEMORY;
865 otmCtx->userCtx = ctx;
866 otmCtx->selectedDeviceInfo = selectedDevice;
868 //Set to the lowest level OxM, and then find more higher level OxM.
869 OCStackResult res = SelectProvisioningMethod(selectedDevice->doxm->oxm,
870 selectedDevice->doxm->oxmLen,
871 &selectedDevice->doxm->oxmSel);
872 if(OC_STACK_OK != res)
874 OC_LOG(ERROR, TAG, "Failed to select the provisioning method");
875 SetResult(otmCtx, res);
878 OC_LOG_V(DEBUG, TAG, "Selected provisoning method = %d", selectedDevice->doxm->oxmSel);
880 //Send Req: PUT /oic/sec/doxm [{..."OxmSel" :g_OTMDatas[Index of Selected OxM].OXMString,...}]
881 res = PutOwnerTransferModeToResource(otmCtx);
882 if(OC_STACK_OK != res)
884 OC_LOG(WARNING, TAG, "Failed to select the provisioning method");
885 SetResult(otmCtx, res);
889 OC_LOG(INFO, TAG, "OUT StartOwnershipTransfer");
895 OCStackResult OTMSetOwnershipTransferCallbackData(OicSecOxm_t oxmType, OTMCallbackData_t* data)
897 OC_LOG(DEBUG, TAG, "IN OTMSetOwnerTransferCallbackData");
901 OC_LOG(ERROR, TAG, "OTMSetOwnershipTransferCallbackData : Invalid parameters");
902 return OC_STACK_INVALID_PARAM;
904 if(oxmType >= OIC_OXM_COUNT)
906 OC_LOG(INFO, TAG, "Unknow ownership transfer method");
907 return OC_STACK_INVALID_PARAM;
910 g_OTMDatas[oxmType].loadSecretCB= data->loadSecretCB;
911 g_OTMDatas[oxmType].createSecureSessionCB = data->createSecureSessionCB;
912 g_OTMDatas[oxmType].createSelectOxmPayloadCB = data->createSelectOxmPayloadCB;
913 g_OTMDatas[oxmType].createOwnerTransferPayloadCB = data->createOwnerTransferPayloadCB;
915 OC_LOG(DEBUG, TAG, "OUT OTMSetOwnerTransferCallbackData");
921 * NOTE : Unowned discovery should be done before performing OTMDoOwnershipTransfer
923 OCStackResult OTMDoOwnershipTransfer(void* ctx,
924 OCProvisionDev_t *selectedDevicelist,
925 OCProvisionResultCB resultCallback)
927 OC_LOG(DEBUG, TAG, "IN OTMDoOwnershipTransfer");
929 if (NULL == selectedDevicelist || NULL == resultCallback )
931 return OC_STACK_INVALID_PARAM;
934 g_resultCallback = resultCallback;
937 OCProvisionDev_t* pCurDev = selectedDevicelist;
939 //Counting number of selected devices.
940 g_resultArraySize = 0;
941 while(NULL != pCurDev)
944 pCurDev = pCurDev->next;
949 OICFree(g_resultArray);
952 (OCProvisionResult_t*)OICMalloc(sizeof(OCProvisionResult_t) * g_resultArraySize);
953 if(NULL == g_resultArray)
955 OC_LOG(ERROR, TAG, "OTMDoOwnershipTransfer : Failed to memory allocation");
956 return OC_STACK_NO_MEMORY;
960 pCurDev = selectedDevicelist;
961 //Fill the device UUID for result array.
962 for(devIdx = 0; devIdx < g_resultArraySize; devIdx++)
964 memcpy(g_resultArray[devIdx].deviceId.id,
965 pCurDev->doxm->deviceID.id,
967 g_resultArray[devIdx].res = OC_STACK_CONTINUE;
968 pCurDev = pCurDev->next;
971 StartOwnershipTransfer(ctx, selectedDevicelist);
973 OC_LOG(DEBUG, TAG, "OUT OTMDoOwnershipTransfer");
975 return (hasError ? OC_STACK_ERROR : OC_STACK_OK);
979 * Callback handler of SRPFinalizeProvisioning.
981 * @param[in] ctx ctx value passed to callback from calling function.
982 * @param[in] handle handle to an invocation
983 * @param[in] clientResponse Response from queries to remote servers.
984 * @return OC_STACK_DELETE_TRANSACTION to delete the transaction
985 * and OC_STACK_KEEP_TRANSACTION to keep it.
987 static OCStackApplicationResult FinalizeProvisioningCB(void *ctx, OCDoHandle handle,
988 OCClientResponse *clientResponse)
992 OC_LOG_V(INFO, TAG, "IN FinalizeProvisioningCB.");
993 OTMContext_t* otmCtx = (OTMContext_t*)ctx;
996 OC_LOG(ERROR, TAG, "OTMContext is NULL");
997 return OC_STACK_DELETE_TRANSACTION;
1000 if(OC_STACK_OK == clientResponse->result)
1002 SetResult(otmCtx, OC_STACK_OK);
1003 return OC_STACK_DELETE_TRANSACTION;
1007 return OC_STACK_DELETE_TRANSACTION;
1011 * Callback handler of default ACL provisioning.
1013 * @param[in] ctx ctx value passed to callback from calling function.
1014 * @param[in] handle handle to an invocation
1015 * @param[in] clientResponse Response from queries to remote servers.
1016 * @return OC_STACK_DELETE_TRANSACTION to delete the transaction
1017 * and OC_STACK_KEEP_TRANSACTION to keep it.
1019 static OCStackApplicationResult ProvisionDefaultACLCB(void *ctx, OCDoHandle handle,
1020 OCClientResponse *clientResponse)
1022 OC_LOG_V(INFO, TAG, "IN ProvisionDefaultACLCB.");
1026 OTMContext_t* otmCtx = (OTMContext_t*) ctx;
1029 OC_LOG(ERROR, TAG, "OTMContext is NULL");
1030 return OC_STACK_DELETE_TRANSACTION;
1033 if (OC_STACK_RESOURCE_CREATED == clientResponse->result)
1035 OC_LOG_V(INFO, TAG, "Staring commit hash task.");
1036 // TODO hash currently have fixed value 0.
1037 uint16_t aclHash = 0;
1038 otmCtx->selectedDeviceInfo->pstat->commitHash = aclHash;
1039 otmCtx->selectedDeviceInfo->pstat->tm = NORMAL;
1040 OCSecurityPayload* secPayload = (OCSecurityPayload*)OICCalloc(1, sizeof(OCSecurityPayload));
1043 OC_LOG(ERROR, TAG, "Failed to memory allocation");
1044 return OC_STACK_NO_MEMORY;
1046 secPayload->base.type = PAYLOAD_TYPE_SECURITY;
1047 secPayload->securityData = BinToPstatJSON(otmCtx->selectedDeviceInfo->pstat);
1048 if (NULL == secPayload->securityData)
1050 SetResult(otmCtx, OC_STACK_INVALID_JSON);
1051 return OC_STACK_DELETE_TRANSACTION;
1053 OC_LOG_V(INFO, TAG, "Created payload for commit hash: %s",secPayload->securityData);
1055 char uri[MAX_QUERY_LENGTH] = { 0 };
1056 size_t uriLen = sizeof(uri);
1058 snprintf(uri, uriLen - 1, COAPS_QUERY, otmCtx->selectedDeviceInfo->endpoint.addr,
1059 otmCtx->selectedDeviceInfo->securePort, OIC_RSRC_PSTAT_URI);
1060 uri[uriLen - 1] = '\0';
1061 OCCallbackData cbData = {0,};
1062 cbData.cb = &FinalizeProvisioningCB;
1063 cbData.context = (void*)otmCtx; // forward context to SRPFinalizeProvisioningCB
1066 // TODO change value of CT_ADAPTER_IP with val from discovery
1067 OCStackResult ret = OCDoResource(NULL, OC_REST_PUT, uri, 0, (OCPayload*)secPayload,
1068 CT_ADAPTER_IP, OC_HIGH_QOS, &cbData, NULL, 0);
1069 OC_LOG_V(INFO, TAG, "OCDoResource returned: %d",ret);
1070 if (ret != OC_STACK_OK)
1072 OC_LOG(ERROR, TAG, "OCStack resource error");
1073 SetResult(otmCtx, ret);
1074 return OC_STACK_DELETE_TRANSACTION;
1076 return OC_STACK_DELETE_TRANSACTION;
1080 OC_LOG_V(INFO, TAG, "Error occured in provisionDefaultACLCB :: %d\n",
1081 clientResponse->result);
1082 SetResult(otmCtx, clientResponse->result);
1086 return OC_STACK_DELETE_TRANSACTION;
1090 OCStackResult FinalizeProvisioning(OTMContext_t* otmCtx)
1092 OC_LOG(INFO, TAG, "IN FinalizeProvisioning");
1096 OC_LOG(ERROR, TAG, "OTMContext is NULL");
1097 return OC_STACK_INVALID_PARAM;
1099 if(!otmCtx->selectedDeviceInfo)
1101 OC_LOG(ERROR, TAG, "Can't find device information in OTMContext");
1103 return OC_STACK_INVALID_PARAM;
1105 // Provision Default ACL to device
1106 OicSecAcl_t defaultAcl =
1119 OicUuid_t provTooldeviceID = {{0,}};
1120 if (OC_STACK_OK != GetDoxmDeviceID(&provTooldeviceID))
1122 OC_LOG(ERROR, TAG, "Error while retrieving provisioning tool's device ID");
1123 SetResult(otmCtx, OC_STACK_ERROR);
1124 return OC_STACK_ERROR;
1126 OC_LOG(INFO, TAG, "Retieved deviceID");
1127 memcpy(defaultAcl.subject.id, provTooldeviceID.id, sizeof(defaultAcl.subject.id));
1128 char *wildCardResource = "*";
1129 defaultAcl.resources = &wildCardResource;
1131 defaultAcl.owners = (OicUuid_t *) OICCalloc(1, UUID_LENGTH);
1132 if(!defaultAcl.owners)
1134 OC_LOG(ERROR, TAG, "Failed to memory allocation for default ACL");
1135 SetResult(otmCtx, OC_STACK_NO_MEMORY);
1136 return OC_STACK_NO_MEMORY;
1138 memcpy(defaultAcl.owners->id, provTooldeviceID.id, UUID_LENGTH);
1139 OC_LOG(INFO, TAG, "Provisioning default ACL");
1141 OCSecurityPayload* secPayload = (OCSecurityPayload*)OICCalloc(1, sizeof(OCSecurityPayload));
1144 OC_LOG(ERROR, TAG, "Failed to memory allocation");
1145 return OC_STACK_NO_MEMORY;
1147 secPayload->base.type = PAYLOAD_TYPE_SECURITY;
1148 secPayload->securityData = BinToAclJSON(&defaultAcl);
1149 OICFree(defaultAcl.owners);
1150 if(!secPayload->securityData)
1152 OC_LOG(INFO, TAG, "FinalizeProvisioning : Failed to BinToAclJSON");
1153 SetResult(otmCtx, OC_STACK_ERROR);
1154 return OC_STACK_ERROR;
1156 OC_LOG_V(INFO, TAG, "Provisioning default ACL : %s",secPayload->securityData);
1158 char uri[MAX_QUERY_LENGTH] = { 0 };
1160 size_t uriLen = sizeof(uri);
1161 snprintf(uri, uriLen - 1, COAPS_QUERY, otmCtx->selectedDeviceInfo->endpoint.addr,
1162 otmCtx->selectedDeviceInfo->securePort, OIC_RSRC_ACL_URI);
1163 uri[uriLen - 1] = '\0';
1164 OC_LOG_V(INFO, TAG, "Request URI for Provisioning default ACL : %s",uri);
1166 OCCallbackData cbData = {};
1167 cbData.cb = &ProvisionDefaultACLCB;
1168 cbData.context = (void *)otmCtx;
1171 OCStackResult ret = OCDoResource(NULL, OC_REST_POST, uri,
1172 &otmCtx->selectedDeviceInfo->endpoint, (OCPayload*)secPayload,
1173 CT_ADAPTER_IP, OC_HIGH_QOS, &cbData, NULL, 0);
1174 if (OC_STACK_OK != ret)
1176 SetResult(otmCtx, ret);
1180 OC_LOG(INFO, TAG, "OUT FinalizeProvisioning");