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"
57 #include "srmutility.h"
59 // TODO: Not yet supported.
60 //#include "oxmrandompin.h"
62 #define DEFAULT_CONTEXT_VALUE 0x99
63 #define DEFAULT_SECURE_PORT 5684
67 OCProvisionResultCB g_resultCallback;
68 OCProvisionResult_t* g_resultArray = NULL;
69 size_t g_resultArraySize = 0;
70 bool g_hasError = false;
73 * Possible states of ownership transfer manager module.
78 SP_DISCOVERY_STARTED = (0x1 << 1),
79 SP_DISCOVERY_ERROR = (0x1 << 2),
80 SP_DISCOVERY_DONE = (0x1 << 3),
81 SP_UP_OWN_TR_METH_STARTED = (0x1 << 4),
82 SP_UP_OWN_TR_METH_ERROR = (0x1 << 5),
83 SP_UP_OWN_TR_METH_DONE = (0x1 << 6),
84 SP_LIST_METHODS_STARTED = (0x1 << 7),
85 SP_LIST_METHODS_ERROR = (0x1 << 8),
86 SP_LIST_METHODS_DONE = (0x1 << 9),
87 SP_UPDATE_OP_MODE_STARTED = (0x1 << 10),
88 SP_UPDATE_OP_MODE_ERROR = (0x1 << 11),
89 SP_UPDATE_OP_MODE_DONE = (0x1 << 12),
90 SP_UPDATE_OWNER_STARTED = (0x1 << 13),
91 SP_UPDATE_OWNER_ERROR = (0x1 << 14),
92 SP_UPDATE_OWNER_DONE = (0x1 << 15)
98 * Array to store the callbacks for each owner transfer method.
100 OTMCallbackData_t g_OTMDatas[OIC_OXM_COUNT];
103 * Variable for storing provisioning tool's provisioning capabilities
104 * Must be in decreasing order of preference. More prefered method should
105 * have lower array index.
107 static OicSecDpom_t gProvisioningToolCapability[] = { SINGLE_SERVICE_CLIENT_DRIVEN };
110 * Number of supported provisioning methods
111 * current version supports only one.
113 static size_t gNumOfProvisioningMethodsPT = 1;
116 * Function to getting string of ownership transfer method
118 static const char* GetOxmString(OicSecOxm_t oxmType)
123 return OXM_JUST_WORKS;
124 case OIC_MODE_SWITCH:
125 return OXM_MODE_SWITCH;
126 case OIC_RANDOM_DEVICE_PIN:
127 return OXM_RANDOM_DEVICE_PIN;
128 case OIC_PRE_PROVISIONED_DEVICE_PIN:
129 return OXM_PRE_PROVISIONED_DEVICE_PIN;
130 case OIC_PRE_PROVISION_STRONG_CREDENTIAL:
131 return OXM_PRE_PROVISIONED_STRONG_CREDENTIAL;
138 * Function to select appropriate provisioning method.
140 * @param[in] supportedMethods Array of supported methods
141 * @param[in] numberOfMethods number of supported methods
142 * @param[out] selectedMethod Selected methods
143 * @return SP_SUCCESS on success
145 static OCStackResult SelectProvisioningMethod(const OicSecOxm_t *supportedMethods,
146 size_t numberOfMethods,
147 OicSecOxm_t *selectedMethod)
149 OC_LOG(DEBUG, TAG, "IN SelectProvisioningMethod");
151 if(numberOfMethods == 0 || !supportedMethods)
153 OC_LOG(WARNING, TAG, "Could not find a supported OxM.");
154 return OC_STACK_ERROR;
157 *selectedMethod = supportedMethods[0];
158 for(size_t i = 0; i < numberOfMethods; i++)
160 if(*selectedMethod < supportedMethods[i])
162 *selectedMethod = supportedMethods[i];
170 * Function to select operation mode.This function will return most secure common operation mode.
172 * @param[in] selectedDeviceInfo selected device information to performing provisioning.
173 * @param[out] selectedMode selected operation mode
174 * @return SP_SUCCESS on success
176 static void SelectOperationMode(const OCProvisionDev_t *selectedDeviceInfo,
177 OicSecDpom_t *selectedMode)
179 OC_LOG(DEBUG, TAG, "IN SelectOperationMode");
184 while (i < gNumOfProvisioningMethodsPT && j < selectedDeviceInfo->pstat->smLen)
186 if (gProvisioningToolCapability[i] < selectedDeviceInfo->pstat->sm[j])
190 else if (selectedDeviceInfo->pstat->sm[j] < gProvisioningToolCapability[i])
194 else /* if gProvisioningToolCapability[i] == deviceSupportedMethods[j] */
196 *selectedMode = gProvisioningToolCapability[j];
200 OC_LOG(DEBUG, TAG, "OUT SelectOperationMode");
204 * Function to update owner transfer mode
206 * @param[in] otmCtx Context value of ownership transfer.
207 * @return OC_STACK_OK on success
209 static OCStackResult PutOwnerTransferModeToResource(OTMContext_t* otmCtx);
212 * Function to send request to resource to get its pstat resource information.
214 * @param[in] otmCtx Context value of ownership transfer.
215 * @return OC_STACK_OK on success
217 static OCStackResult GetProvisioningStatusResource(OTMContext_t* otmCtx);
221 * Function to send ownerShip info. This function would update Owned as true and
222 * owner as UUID for provisioning tool
224 * @param[in] otmCtx Context value of ownership transfer.
225 * @return OC_STACK_OK on success
227 static OCStackResult PutOwnershipInformation(OTMContext_t* otmCtx);
230 * Function to update the operation mode. As per the spec. Operation mode in client driven
231 * single service provisioning it will be updated to 0x3
233 * @param[in] otmCtx Context value of ownership transfer.
234 * @param[in] selectedOperationMode selected operation mode
235 * @return OC_STACK_OK on success
237 static OCStackResult PutUpdateOperationMode(OTMContext_t* otmCtx,
238 OicSecDpom_t selectedOperationMode);
241 * Function to start ownership transfer.
242 * This function will send the first request for provisioning,
243 * The next request message is sent from the response handler for this request.
245 * @param[in] ctx context value passed to callback from calling function.
246 * @param[in] selectedDevice selected device information to performing provisioning.
247 * @return OC_STACK_OK on success
249 static OCStackResult StartOwnershipTransfer(void* ctx, OCProvisionDev_t* selectedDevice);
252 * Function to finalize provisioning.
253 * This function will send default ACL and commit hash.
255 * @param[in] otmCtx Context value of ownership transfer.
256 * @return OC_STACK_OK on success
258 static OCStackResult FinalizeProvisioning(OTMContext_t* otmCtx);
261 static bool IsComplete()
263 for(size_t i = 0; i < g_resultArraySize; i++)
265 if(OC_STACK_CONTINUE == g_resultArray[i].res)
275 * Function to save the result of provisioning.
277 * @param[in,out] otmCtx Context value of ownership transfer.
278 * @param[in] res result of provisioning
280 static void SetResult(OTMContext_t* otmCtx, const OCStackResult res)
282 OC_LOG(DEBUG, TAG, "IN SetResult");
286 OC_LOG(WARNING, TAG, "OTMContext is NULL");
290 if(otmCtx->selectedDeviceInfo)
292 for(size_t i = 0; i < g_resultArraySize; i++)
294 if(memcmp(otmCtx->selectedDeviceInfo->doxm->deviceID.id,
295 g_resultArray[i].deviceId.id, UUID_LENGTH) == 0)
297 g_resultArray[i].res = res;
298 if(OC_STACK_OK != res)
305 //If all request is completed, invoke the user callback.
308 g_resultCallback(otmCtx->userCtx, g_resultArraySize, g_resultArray, g_hasError);
312 if(OC_STACK_OK != StartOwnershipTransfer(otmCtx->userCtx,
313 otmCtx->selectedDeviceInfo->next))
315 OC_LOG(ERROR, TAG, "Failed to StartOwnershipTransfer");
320 OC_LOG(DEBUG, TAG, "OUT SetResult");
327 * Function to save ownerPSK at provisioning tool end.
329 * @param[in] selectedDeviceInfo selected device information to performing provisioning.
330 * @return OC_STACK_OK on success
332 static OCStackResult SaveOwnerPSK(OCProvisionDev_t *selectedDeviceInfo)
334 OC_LOG(DEBUG, TAG, "IN SaveOwnerPSK");
336 OCStackResult res = OC_STACK_ERROR;
338 CAEndpoint_t endpoint;
339 memset(&endpoint, 0x00, sizeof(CAEndpoint_t));
340 OICStrcpy(endpoint.addr, MAX_ADDR_STR_SIZE_CA, selectedDeviceInfo->endpoint.addr);
341 endpoint.addr[MAX_ADDR_STR_SIZE_CA - 1] = '\0';
342 endpoint.port = selectedDeviceInfo->securePort;
344 OicUuid_t ptDeviceID = {.id={0}};
345 if (OC_STACK_OK != GetDoxmDeviceID(&ptDeviceID))
347 OC_LOG(ERROR, TAG, "Error while retrieving provisioning tool's device ID");
351 uint8_t ownerPSK[OWNER_PSK_LENGTH_128] = {0};
353 //Generating OwnerPSK
354 CAResult_t pskRet = CAGenerateOwnerPSK(&endpoint,
355 (uint8_t *)GetOxmString(selectedDeviceInfo->doxm->oxmSel),
356 strlen(GetOxmString(selectedDeviceInfo->doxm->oxmSel)), ptDeviceID.id,
357 sizeof(ptDeviceID.id), selectedDeviceInfo->doxm->deviceID.id,
358 sizeof(selectedDeviceInfo->doxm->deviceID.id), ownerPSK,
359 OWNER_PSK_LENGTH_128);
361 if (CA_STATUS_OK == pskRet)
363 OC_LOG(INFO, TAG,"ownerPSK dump:\n");
364 OC_LOG_BUFFER(INFO, TAG,ownerPSK, OWNER_PSK_LENGTH_128);
365 //Generating new credential for provisioning tool
369 char base64Buff[B64ENCODE_OUT_SAFESIZE(sizeof(ownerPSK)) + 1] = {};
370 B64Result b64Ret = b64Encode(ownerPSK, sizeof(ownerPSK), base64Buff, sizeof(base64Buff),
372 VERIFY_SUCCESS(TAG, B64_OK == b64Ret, ERROR);
374 OicSecCred_t *cred = GenerateCredential(&selectedDeviceInfo->doxm->deviceID,
375 SYMMETRIC_PAIR_WISE_KEY, NULL,
376 base64Buff, ownLen, &ptDeviceID);
377 VERIFY_NON_NULL(TAG, cred, ERROR);
379 res = AddCredential(cred);
380 if(res != OC_STACK_OK)
382 DeleteCredList(cred);
388 OC_LOG(ERROR, TAG, "CAGenerateOwnerPSK failed");
391 OC_LOG(DEBUG, TAG, "OUT SaveOwnerPSK");
397 * Callback handler for OwnerShipTransferModeHandler API.
399 * @param[in] ctx ctx value passed to callback from calling function.
400 * @param[in] UNUSED handle to an invocation
401 * @param[in] clientResponse Response from queries to remote servers.
402 * @return OC_STACK_DELETE_TRANSACTION to delete the transaction
403 * and OC_STACK_KEEP_TRANSACTION to keep it.
405 static OCStackApplicationResult OwnerTransferModeHandler(void *ctx, OCDoHandle UNUSED,
406 OCClientResponse *clientResponse)
408 OC_LOG(DEBUG, TAG, "IN OwnerTransferModeHandler");
410 VERIFY_NON_NULL(TAG, clientResponse, WARNING);
411 VERIFY_NON_NULL(TAG, ctx, WARNING);
413 OTMContext_t* otmCtx = (OTMContext_t*)ctx;
415 if(clientResponse->result == OC_STACK_OK)
417 OC_LOG(INFO, TAG, "OwnerTransferModeHandler : response result = OC_STACK_OK");
418 //Send request : GET /oic/sec/pstat
419 OCStackResult res = GetProvisioningStatusResource(otmCtx);
420 if(OC_STACK_OK != res)
422 OC_LOG(WARNING, TAG, "Failed to get pstat information");
423 SetResult(otmCtx, res);
428 OC_LOG_V(WARNING, TAG, "OwnerTransferModeHandler : Client response is incorrect : %d",
429 clientResponse->result);
430 SetResult(otmCtx, clientResponse->result);
433 OC_LOG(DEBUG, TAG, "OUT OwnerTransferModeHandler");
436 return OC_STACK_DELETE_TRANSACTION;
440 * Callback handler for ProvisioningStatusResouceHandler API.
442 * @param[in] ctx ctx value passed to callback from calling function.
443 * @param[in] UNUSED handle to an invocation
444 * @param[in] clientResponse Response from queries to remote servers.
445 * @return OC_STACK_DELETE_TRANSACTION to delete the transaction
446 * and OC_STACK_KEEP_TRANSACTION to keep it.
448 static OCStackApplicationResult ListMethodsHandler(void *ctx, OCDoHandle UNUSED,
449 OCClientResponse *clientResponse)
451 OC_LOG(DEBUG, TAG, "IN ListMethodsHandler");
453 VERIFY_NON_NULL(TAG, clientResponse, WARNING);
454 VERIFY_NON_NULL(TAG, ctx, WARNING);
456 OTMContext_t* otmCtx = (OTMContext_t*)ctx;
458 if (OC_STACK_OK == clientResponse->result)
460 if (NULL == clientResponse->payload)
462 OC_LOG(INFO, TAG, "Skiping Null payload");
463 SetResult(otmCtx, OC_STACK_ERROR);
464 return OC_STACK_DELETE_TRANSACTION;
467 if (PAYLOAD_TYPE_SECURITY != clientResponse->payload->type)
469 OC_LOG(INFO, TAG, "Unknown payload type");
470 SetResult(otmCtx, OC_STACK_ERROR);
471 return OC_STACK_DELETE_TRANSACTION;
474 OicSecPstat_t* pstat = JSONToPstatBin(
475 ((OCSecurityPayload*)clientResponse->payload)->securityData);
478 OC_LOG(ERROR, TAG, "Error while converting json to pstat bin");
479 SetResult(otmCtx, OC_STACK_ERROR);
480 return OC_STACK_DELETE_TRANSACTION;
482 otmCtx->selectedDeviceInfo->pstat = pstat;
484 //Select operation mode (Currently supported SINGLE_SERVICE_CLIENT_DRIVEN only)
485 OicSecDpom_t selectedOperationMode;
486 SelectOperationMode(otmCtx->selectedDeviceInfo, &selectedOperationMode);
488 //Send request : PUT /oic/sec/pstat [{"OM":"0x11", .. }]
489 OCStackResult res = PutUpdateOperationMode(otmCtx, selectedOperationMode);
490 if (OC_STACK_OK != res)
492 OC_LOG(ERROR, TAG, "Error while updating operation mode.");
493 SetResult(otmCtx, res);
498 OC_LOG_V(WARNING, TAG, "ListMethodsHandler : Client response is incorrect : %d",
499 clientResponse->result);
500 SetResult(otmCtx, clientResponse->result);
503 OC_LOG(DEBUG, TAG, "OUT ListMethodsHandler");
505 return OC_STACK_DELETE_TRANSACTION;
509 * Callback handler for OwnershipInformationHandler API.
511 * @param[in] ctx ctx value passed to callback from calling function.
512 * @param[in] UNUSED handle to an invocation
513 * @param[in] clientResponse Response from queries to remote servers.
514 * @return OC_STACK_DELETE_TRANSACTION to delete the transaction
515 * and OC_STACK_KEEP_TRANSACTION to keep it.
517 static OCStackApplicationResult OwnershipInformationHandler(void *ctx, OCDoHandle UNUSED,
518 OCClientResponse *clientResponse)
520 VERIFY_NON_NULL(TAG, clientResponse, WARNING);
521 VERIFY_NON_NULL(TAG, ctx, WARNING);
523 OC_LOG(DEBUG, TAG, "IN OwnershipInformationHandler");
525 OCStackResult res = OC_STACK_OK;
526 OTMContext_t* otmCtx = (OTMContext_t*)ctx;
527 if (OC_STACK_OK == clientResponse->result)
529 if(OIC_RANDOM_DEVICE_PIN == otmCtx->selectedDeviceInfo->doxm->oxmSel)
531 res = RemoveCredential(&otmCtx->tempCredId);
532 if(OC_STACK_RESOURCE_DELETED != res)
534 OC_LOG_V(ERROR, TAG, "Failed to remove temporal PSK : %d", res);
535 return OC_STACK_DELETE_TRANSACTION;
539 res = SaveOwnerPSK(otmCtx->selectedDeviceInfo);
540 if(OC_STACK_OK != res)
542 OC_LOG(ERROR, TAG, "OperationModeUpdate : Failed to owner PSK generation");
543 SetResult(otmCtx, res);
544 return OC_STACK_DELETE_TRANSACTION;
547 CAEndpoint_t* endpoint = (CAEndpoint_t *)&otmCtx->selectedDeviceInfo->endpoint;
548 endpoint->port = otmCtx->selectedDeviceInfo->securePort;
549 CAResult_t closeRes = CACloseDtlsSession(endpoint);
550 if(CA_STATUS_OK != closeRes)
552 OC_LOG(ERROR, TAG, "Failed to close DTLS session");
553 SetResult(otmCtx, closeRes);
554 return OC_STACK_DELETE_TRANSACTION;
557 OC_LOG(INFO, TAG, "Ownership transfer was successfully completed.");
558 OC_LOG(INFO, TAG, "Start defualt ACL & commit-hash provisioning.");
560 res = FinalizeProvisioning(otmCtx);
561 if(OC_STACK_OK != res)
563 SetResult(otmCtx, res);
568 res = clientResponse->result;
571 OC_LOG(DEBUG, TAG, "OUT OwnershipInformationHandler");
574 return OC_STACK_DELETE_TRANSACTION;
578 * Response handler for update operation mode.
580 * @param[in] ctx ctx value passed to callback from calling function.
581 * @param[in] UNUSED handle to an invocation
582 * @param[in] clientResponse Response from queries to remote servers.
583 * @return OC_STACK_DELETE_TRANSACTION to delete the transaction
584 * and OC_STACK_KEEP_TRANSACTION to keep it.
586 static OCStackApplicationResult OperationModeUpdateHandler(void *ctx, OCDoHandle UNUSED,
587 OCClientResponse *clientResponse)
589 OC_LOG(DEBUG, TAG, "IN OperationModeUpdateHandler");
591 VERIFY_NON_NULL(TAG, clientResponse, WARNING);
592 VERIFY_NON_NULL(TAG, ctx, WARNING);
594 OTMContext_t* otmCtx = (OTMContext_t*)ctx;
596 if (OC_STACK_OK == clientResponse->result)
598 OCStackResult res = OC_STACK_ERROR;
599 OicSecOxm_t selOxm = otmCtx->selectedDeviceInfo->doxm->oxmSel;
601 //Load secret for temporal secure session.
602 if(g_OTMDatas[selOxm].loadSecretCB)
604 res = g_OTMDatas[selOxm].loadSecretCB(otmCtx);
605 if(OC_STACK_OK != res)
607 OC_LOG(ERROR, TAG, "OperationModeUpdate : Failed to load secret");
608 SetResult(otmCtx, res);
609 return OC_STACK_DELETE_TRANSACTION;
613 //Try DTLS handshake to generate secure session
614 if(g_OTMDatas[selOxm].createSecureSessionCB)
616 res = g_OTMDatas[selOxm].createSecureSessionCB(otmCtx);
617 if(OC_STACK_OK != res)
619 OC_LOG(ERROR, TAG, "OperationModeUpdate : Failed to create DTLS session");
620 SetResult(otmCtx, res);
621 return OC_STACK_DELETE_TRANSACTION;
625 //Send request : PUT /oic/sec/doxm [{"Owned":"True", .. , "Owner":"PT's UUID"}]
626 res = PutOwnershipInformation(otmCtx);
627 if(OC_STACK_OK != res)
629 OC_LOG(ERROR, TAG, "OperationModeUpdate : Failed to send owner information");
630 SetResult(otmCtx, res);
635 OC_LOG(ERROR, TAG, "Error while update operation mode");
636 SetResult(otmCtx, clientResponse->result);
639 OC_LOG(DEBUG, TAG, "OUT OperationModeUpdateHandler");
642 return OC_STACK_DELETE_TRANSACTION;
646 static OCStackResult PutOwnerTransferModeToResource(OTMContext_t* otmCtx)
648 OC_LOG(DEBUG, TAG, "IN PutOwnerTransferModeToResource");
650 if(!otmCtx || !otmCtx->selectedDeviceInfo)
652 OC_LOG(ERROR, TAG, "Invailed parameters");
653 return OC_STACK_INVALID_PARAM;
656 OCProvisionDev_t* deviceInfo = otmCtx->selectedDeviceInfo;
657 OicSecOxm_t selectedOxm = deviceInfo->doxm->oxmSel;
658 char query[MAX_QUERY_LENGTH] = {};
659 sprintf(query, "%s%s:%d%s", COAP_PREFIX,
660 deviceInfo->endpoint.addr, deviceInfo->endpoint.port,
662 OCSecurityPayload* secPayload = (OCSecurityPayload*)OICCalloc(1, sizeof(OCSecurityPayload));
665 OC_LOG(ERROR, TAG, "Failed to memory allocation");
666 return OC_STACK_NO_MEMORY;
668 secPayload->base.type = PAYLOAD_TYPE_SECURITY;
669 secPayload->securityData = g_OTMDatas[selectedOxm].createSelectOxmPayloadCB(otmCtx);
670 if (NULL == secPayload->securityData)
673 OC_LOG(ERROR, TAG, "Error while converting bin to json");
674 return OC_STACK_ERROR;
676 OC_LOG_V(DEBUG, TAG, "Payload : %s", secPayload->securityData);
678 OCCallbackData cbData;
679 cbData.cb = &OwnerTransferModeHandler;
680 cbData.context = (void *)otmCtx;
683 // TODO: 6th argument need to be changed, if we have to use CT_FLAG_SECURE
684 OCStackResult res = OCDoResource(NULL, OC_REST_PUT, query,
685 &deviceInfo->endpoint, (OCPayload*)secPayload,
686 CT_ADAPTER_IP, OC_LOW_QOS, &cbData, NULL, 0);
687 if (res != OC_STACK_OK)
689 OC_LOG(ERROR, TAG, "OCStack resource error");
692 OC_LOG(DEBUG, TAG, "OUT PutOwnerTransferModeToResource");
697 static OCStackResult GetProvisioningStatusResource(OTMContext_t* otmCtx)
699 OC_LOG(DEBUG, TAG, "IN GetProvisioningStatusResource");
701 if(!otmCtx || !otmCtx->selectedDeviceInfo)
703 OC_LOG(ERROR, TAG, "Invailed parameters");
704 return OC_STACK_INVALID_PARAM;
707 OCProvisionDev_t* deviceInfo = otmCtx->selectedDeviceInfo;
708 char query[MAX_QUERY_LENGTH] = {};
709 sprintf(query, "%s%s:%d%s", COAP_PREFIX,
710 deviceInfo->endpoint.addr, deviceInfo->endpoint.port,
712 OCCallbackData cbData;
713 cbData.cb = &ListMethodsHandler;
714 cbData.context = (void *)otmCtx;
717 // TODO: 6th argument need to be changed, if we have to use CT_FLAG_SECURE
718 OCStackResult res = OCDoResource(NULL, OC_REST_GET, query, NULL, NULL,
719 CT_ADAPTER_IP, OC_LOW_QOS, &cbData, NULL, 0);
720 if (res != OC_STACK_OK)
722 OC_LOG(ERROR, TAG, "OCStack resource error");
725 OC_LOG(DEBUG, TAG, "OUT GetProvisioningStatusResource");
731 static OCStackResult PutOwnershipInformation(OTMContext_t* otmCtx)
733 OC_LOG(DEBUG, TAG, "IN PutOwnershipInformation");
735 if(!otmCtx || !otmCtx->selectedDeviceInfo)
737 OC_LOG(ERROR, TAG, "Invailed parameters");
738 return OC_STACK_INVALID_PARAM;
741 OCProvisionDev_t* deviceInfo = otmCtx->selectedDeviceInfo;
742 char query[MAX_QUERY_LENGTH] = {};
743 sprintf(query, "%s%s:%d%s", COAPS_PREFIX,
744 deviceInfo->endpoint.addr, deviceInfo->securePort,
746 //OwnershipInformationHandler
747 OicSecOxm_t selOxm = deviceInfo->doxm->oxmSel;
748 OCSecurityPayload* secPayload = (OCSecurityPayload*)OICCalloc(1, sizeof(OCSecurityPayload));
751 OC_LOG(ERROR, TAG, "Failed to memory allocation");
752 return OC_STACK_NO_MEMORY;
754 secPayload->base.type = PAYLOAD_TYPE_SECURITY;
755 secPayload->securityData = g_OTMDatas[selOxm].createOwnerTransferPayloadCB(otmCtx);
756 if (NULL == secPayload->securityData)
759 OC_LOG(ERROR, TAG, "Error while converting doxm bin to json");
760 return OC_STACK_INVALID_PARAM;
763 OCCallbackData cbData;
764 cbData.cb = &OwnershipInformationHandler;
765 cbData.context = (void *)otmCtx;
767 // TODO: 6th argument need to be changed, if we have to use CT_FLAG_SECURE
768 OCStackResult res = OCDoResource(NULL, OC_REST_PUT, query, 0, (OCPayload*)secPayload,
769 CT_ADAPTER_IP, OC_LOW_QOS, &cbData, NULL, 0);
770 if (res != OC_STACK_OK)
772 OC_LOG(ERROR, TAG, "OCStack resource error");
775 OC_LOG(DEBUG, TAG, "OUT PutOwnershipInformation");
780 static OCStackResult PutUpdateOperationMode(OTMContext_t* otmCtx,
781 OicSecDpom_t selectedOperationMode)
783 OC_LOG(DEBUG, TAG, "IN PutUpdateOperationMode");
785 if(!otmCtx || !otmCtx->selectedDeviceInfo)
787 return OC_STACK_INVALID_PARAM;
790 OCProvisionDev_t* deviceInfo = otmCtx->selectedDeviceInfo;
791 char query[MAX_QUERY_LENGTH] = {};
792 sprintf(query, "%s%s:%d%s", COAP_PREFIX,
793 deviceInfo->endpoint.addr, deviceInfo->endpoint.port,
795 deviceInfo->pstat->om = selectedOperationMode;
797 OCSecurityPayload* secPayload = (OCSecurityPayload*)OICCalloc(1, sizeof(OCSecurityPayload));
800 OC_LOG(ERROR, TAG, "Failed to memory allocation");
801 return OC_STACK_NO_MEMORY;
803 secPayload->base.type = PAYLOAD_TYPE_SECURITY;
804 secPayload->securityData = BinToPstatJSON(deviceInfo->pstat);
805 if (NULL == secPayload->securityData)
808 OC_LOG(ERROR, TAG, "Error while converting pstat bin to json");
809 return OC_STACK_INVALID_PARAM;
812 OCCallbackData cbData;
813 cbData.cb = &OperationModeUpdateHandler;
814 cbData.context = (void *)otmCtx;
817 OCStackResult res = OCDoResource(NULL, OC_REST_PUT, query, 0, (OCPayload*)secPayload,
818 CT_ADAPTER_IP, OC_LOW_QOS, &cbData, NULL, 0);
819 if (res != OC_STACK_OK)
821 OC_LOG(ERROR, TAG, "OCStack resource error");
824 OC_LOG(DEBUG, TAG, "OUT PutUpdateOperationMode");
829 static OCStackResult StartOwnershipTransfer(void* ctx, OCProvisionDev_t* selectedDevice)
831 OC_LOG(INFO, TAG, "IN StartOwnershipTransfer");
832 OTMContext_t* otmCtx = (OTMContext_t*)OICMalloc(sizeof(OTMContext_t));
835 OC_LOG(ERROR, TAG, "Failed to create OTM Context");
836 return OC_STACK_NO_MEMORY;
838 otmCtx->userCtx = ctx;
839 otmCtx->selectedDeviceInfo = selectedDevice;
841 //Set to the lowest level OxM, and then find more higher level OxM.
842 OCStackResult res = SelectProvisioningMethod(selectedDevice->doxm->oxm,
843 selectedDevice->doxm->oxmLen,
844 &selectedDevice->doxm->oxmSel);
845 if(OC_STACK_OK != res)
847 OC_LOG(ERROR, TAG, "Failed to select the provisioning method");
848 SetResult(otmCtx, res);
851 OC_LOG_V(DEBUG, TAG, "Selected provisoning method = %d", selectedDevice->doxm->oxmSel);
853 //Send Req: PUT /oic/sec/doxm [{..."OxmSel" :g_OTMDatas[Index of Selected OxM].OXMString,...}]
854 res = PutOwnerTransferModeToResource(otmCtx);
855 if(OC_STACK_OK != res)
857 OC_LOG(WARNING, TAG, "Failed to select the provisioning method");
858 SetResult(otmCtx, res);
862 OC_LOG(INFO, TAG, "OUT StartOwnershipTransfer");
868 OCStackResult OTMSetOwnershipTransferCallbackData(OicSecOxm_t oxmType, OTMCallbackData_t* data)
870 OC_LOG(DEBUG, TAG, "IN OTMSetOwnerTransferCallbackData");
874 OC_LOG(ERROR, TAG, "OTMSetOwnershipTransferCallbackData : Invalid parameters");
875 return OC_STACK_INVALID_PARAM;
877 if(oxmType >= OIC_OXM_COUNT)
879 OC_LOG(INFO, TAG, "Unknow ownership transfer method");
880 return OC_STACK_INVALID_PARAM;
883 g_OTMDatas[oxmType].loadSecretCB= data->loadSecretCB;
884 g_OTMDatas[oxmType].createSecureSessionCB = data->createSecureSessionCB;
885 g_OTMDatas[oxmType].createSelectOxmPayloadCB = data->createSelectOxmPayloadCB;
886 g_OTMDatas[oxmType].createOwnerTransferPayloadCB = data->createOwnerTransferPayloadCB;
888 OC_LOG(DEBUG, TAG, "OUT OTMSetOwnerTransferCallbackData");
894 * NOTE : Unowned discovery should be done before performing OTMDoOwnershipTransfer
896 OCStackResult OTMDoOwnershipTransfer(void* ctx,
897 OCProvisionDev_t *selectedDevicelist,
898 OCProvisionResultCB resultCallback)
900 OC_LOG(DEBUG, TAG, "IN OTMDoOwnershipTransfer");
902 if (NULL == selectedDevicelist || NULL == resultCallback )
904 return OC_STACK_INVALID_PARAM;
907 g_resultCallback = resultCallback;
910 OCProvisionDev_t* pCurDev = selectedDevicelist;
912 //Counting number of selected devices.
913 g_resultArraySize = 0;
914 while(NULL != pCurDev)
917 pCurDev = pCurDev->next;
922 OICFree(g_resultArray);
925 (OCProvisionResult_t*)OICMalloc(sizeof(OCProvisionResult_t) * g_resultArraySize);
926 if(NULL == g_resultArray)
928 OC_LOG(ERROR, TAG, "OTMDoOwnershipTransfer : Failed to memory allocation");
929 return OC_STACK_NO_MEMORY;
932 pCurDev = selectedDevicelist;
933 //Fill the device UUID for result array.
934 for(size_t devIdx = 0; devIdx < g_resultArraySize; devIdx++)
936 memcpy(g_resultArray[devIdx].deviceId.id,
937 pCurDev->doxm->deviceID.id,
939 g_resultArray[devIdx].res = OC_STACK_CONTINUE;
940 pCurDev = pCurDev->next;
943 StartOwnershipTransfer(ctx, selectedDevicelist);
945 OC_LOG(DEBUG, TAG, "OUT OTMDoOwnershipTransfer");
947 return (g_hasError ? OC_STACK_ERROR : OC_STACK_OK);
951 * Callback handler of SRPFinalizeProvisioning.
953 * @param[in] ctx ctx value passed to callback from calling function.
954 * @param[in] UNUSED handle to an invocation
955 * @param[in] clientResponse Response from queries to remote servers.
956 * @return OC_STACK_DELETE_TRANSACTION to delete the transaction
957 * and OC_STACK_KEEP_TRANSACTION to keep it.
959 static OCStackApplicationResult FinalizeProvisioningCB(void *ctx, OCDoHandle UNUSED,
960 OCClientResponse *clientResponse)
962 OC_LOG_V(INFO, TAG, "IN FinalizeProvisioningCB.");
964 VERIFY_NON_NULL(TAG, clientResponse, ERROR);
965 VERIFY_NON_NULL(TAG, ctx, ERROR);
967 OTMContext_t* otmCtx = (OTMContext_t*)ctx;
969 if(OC_STACK_OK == clientResponse->result)
971 SetResult(otmCtx, OC_STACK_OK);
974 return OC_STACK_DELETE_TRANSACTION;
978 * Callback handler of default ACL provisioning.
980 * @param[in] ctx ctx value passed to callback from calling function.
981 * @param[in] UNUSED handle to an invocation
982 * @param[in] clientResponse Response from queries to remote servers.
983 * @return OC_STACK_DELETE_TRANSACTION to delete the transaction
984 * and OC_STACK_KEEP_TRANSACTION to keep it.
986 static OCStackApplicationResult ProvisionDefaultACLCB(void *ctx, OCDoHandle UNUSED,
987 OCClientResponse *clientResponse)
989 OC_LOG_V(INFO, TAG, "IN ProvisionDefaultACLCB.");
991 VERIFY_NON_NULL(TAG, clientResponse, ERROR);
992 VERIFY_NON_NULL(TAG, ctx, ERROR);
994 OTMContext_t* otmCtx = (OTMContext_t*) ctx;
997 if (OC_STACK_RESOURCE_CREATED == clientResponse->result)
999 OC_LOG_V(INFO, TAG, "Staring commit hash task.");
1000 // TODO hash currently have fixed value 0.
1001 uint16_t aclHash = 0;
1002 otmCtx->selectedDeviceInfo->pstat->commitHash = aclHash;
1003 otmCtx->selectedDeviceInfo->pstat->tm = NORMAL;
1004 OCSecurityPayload* secPayload = (OCSecurityPayload*)OICCalloc(1, sizeof(OCSecurityPayload));
1007 OC_LOG(ERROR, TAG, "Failed to memory allocation");
1008 return OC_STACK_NO_MEMORY;
1010 secPayload->base.type = PAYLOAD_TYPE_SECURITY;
1011 secPayload->securityData = BinToPstatJSON(otmCtx->selectedDeviceInfo->pstat);
1012 if (NULL == secPayload->securityData)
1014 OICFree(secPayload);
1015 SetResult(otmCtx, OC_STACK_INVALID_JSON);
1016 return OC_STACK_DELETE_TRANSACTION;
1018 OC_LOG_V(INFO, TAG, "Created payload for commit hash: %s",secPayload->securityData);
1020 char uri[MAX_QUERY_LENGTH] = { 0 };
1021 size_t uriLen = sizeof(uri);
1023 snprintf(uri, uriLen - 1, COAPS_QUERY, otmCtx->selectedDeviceInfo->endpoint.addr,
1024 otmCtx->selectedDeviceInfo->securePort, OIC_RSRC_PSTAT_URI);
1025 uri[uriLen - 1] = '\0';
1026 OCCallbackData cbData = {.context=NULL, .cb=NULL, .cd=NULL};
1027 cbData.cb = &FinalizeProvisioningCB;
1028 cbData.context = (void*)otmCtx; // forward context to SRPFinalizeProvisioningCB
1031 // TODO change value of CT_ADAPTER_IP with val from discovery
1032 OCStackResult ret = OCDoResource(NULL, OC_REST_PUT, uri, 0, (OCPayload*)secPayload,
1033 CT_ADAPTER_IP, OC_HIGH_QOS, &cbData, NULL, 0);
1034 OC_LOG_V(INFO, TAG, "OCDoResource returned: %d",ret);
1035 if (ret != OC_STACK_OK)
1037 OC_LOG(ERROR, TAG, "OCStack resource error");
1038 SetResult(otmCtx, ret);
1043 OC_LOG_V(INFO, TAG, "Error occured in provisionDefaultACLCB :: %d\n",
1044 clientResponse->result);
1045 SetResult(otmCtx, clientResponse->result);
1048 return OC_STACK_DELETE_TRANSACTION;
1052 OCStackResult FinalizeProvisioning(OTMContext_t* otmCtx)
1054 OC_LOG(INFO, TAG, "IN FinalizeProvisioning");
1058 OC_LOG(ERROR, TAG, "OTMContext is NULL");
1059 return OC_STACK_INVALID_PARAM;
1061 if(!otmCtx->selectedDeviceInfo)
1063 OC_LOG(ERROR, TAG, "Can't find device information in OTMContext");
1065 return OC_STACK_INVALID_PARAM;
1067 // Provision Default ACL to device
1068 OicSecAcl_t defaultAcl =
1081 OicUuid_t provTooldeviceID = {.id={0}};
1082 if (OC_STACK_OK != GetDoxmDeviceID(&provTooldeviceID))
1084 OC_LOG(ERROR, TAG, "Error while retrieving provisioning tool's device ID");
1085 SetResult(otmCtx, OC_STACK_ERROR);
1086 return OC_STACK_ERROR;
1088 OC_LOG(INFO, TAG, "Retieved deviceID");
1089 memcpy(defaultAcl.subject.id, provTooldeviceID.id, sizeof(defaultAcl.subject.id));
1090 char *wildCardResource = "*";
1091 defaultAcl.resources = &wildCardResource;
1093 defaultAcl.owners = (OicUuid_t *) OICCalloc(1, UUID_LENGTH);
1094 if(!defaultAcl.owners)
1096 OC_LOG(ERROR, TAG, "Failed to memory allocation for default ACL");
1097 SetResult(otmCtx, OC_STACK_NO_MEMORY);
1098 return OC_STACK_NO_MEMORY;
1100 memcpy(defaultAcl.owners->id, provTooldeviceID.id, UUID_LENGTH);
1101 OC_LOG(INFO, TAG, "Provisioning default ACL");
1103 OCSecurityPayload* secPayload = (OCSecurityPayload*)OICCalloc(1, sizeof(OCSecurityPayload));
1106 OC_LOG(ERROR, TAG, "Failed to memory allocation");
1107 return OC_STACK_NO_MEMORY;
1109 secPayload->base.type = PAYLOAD_TYPE_SECURITY;
1110 secPayload->securityData = BinToAclJSON(&defaultAcl);
1111 OICFree(defaultAcl.owners);
1112 if(!secPayload->securityData)
1114 OICFree(secPayload);
1115 OC_LOG(INFO, TAG, "FinalizeProvisioning : Failed to BinToAclJSON");
1116 SetResult(otmCtx, OC_STACK_ERROR);
1117 return OC_STACK_ERROR;
1119 OC_LOG_V(INFO, TAG, "Provisioning default ACL : %s",secPayload->securityData);
1121 char uri[MAX_QUERY_LENGTH] = { 0 };
1123 size_t uriLen = sizeof(uri);
1124 snprintf(uri, uriLen - 1, COAPS_QUERY, otmCtx->selectedDeviceInfo->endpoint.addr,
1125 otmCtx->selectedDeviceInfo->securePort, OIC_RSRC_ACL_URI);
1126 uri[uriLen - 1] = '\0';
1127 OC_LOG_V(INFO, TAG, "Request URI for Provisioning default ACL : %s",uri);
1129 OCCallbackData cbData = {.context=NULL, .cb=NULL, .cd=NULL};
1130 cbData.cb = &ProvisionDefaultACLCB;
1131 cbData.context = (void *)otmCtx;
1134 OCStackResult ret = OCDoResource(NULL, OC_REST_POST, uri,
1135 &otmCtx->selectedDeviceInfo->endpoint, (OCPayload*)secPayload,
1136 CT_ADAPTER_IP, OC_HIGH_QOS, &cbData, NULL, 0);
1137 if (OC_STACK_OK != ret)
1139 SetResult(otmCtx, ret);
1143 OC_LOG(INFO, TAG, "OUT FinalizeProvisioning");