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"
58 #include "provisioningdatabasemanager.h"
59 #include "oxmrandompin.h"
64 * Array to store the callbacks for each owner transfer method.
66 static OTMCallbackData_t g_OTMDatas[OIC_OXM_COUNT];
69 * Variable for storing provisioning tool's provisioning capabilities
70 * Must be in decreasing order of preference. More prefered method should
71 * have lower array index.
73 static OicSecDpom_t gProvisioningToolCapability[] = { SINGLE_SERVICE_CLIENT_DRIVEN };
76 * Number of supported provisioning methods
77 * current version supports only one.
79 static size_t gNumOfProvisioningMethodsPT = 1;
82 * Function to getting string of ownership transfer method
84 static const char* GetOxmString(OicSecOxm_t oxmType)
89 return OXM_JUST_WORKS;
91 return OXM_MODE_SWITCH;
92 case OIC_RANDOM_DEVICE_PIN:
93 return OXM_RANDOM_DEVICE_PIN;
94 case OIC_PRE_PROVISIONED_DEVICE_PIN:
95 return OXM_PRE_PROVISIONED_DEVICE_PIN;
96 case OIC_PRE_PROVISION_STRONG_CREDENTIAL:
97 return OXM_PRE_PROVISIONED_STRONG_CREDENTIAL;
104 * Function to select appropriate provisioning method.
106 * @param[in] supportedMethods Array of supported methods
107 * @param[in] numberOfMethods number of supported methods
108 * @param[out] selectedMethod Selected methods
109 * @return OC_STACK_OK on success
111 static OCStackResult SelectProvisioningMethod(const OicSecOxm_t *supportedMethods,
112 size_t numberOfMethods,
113 OicSecOxm_t *selectedMethod)
115 OC_LOG(DEBUG, TAG, "IN SelectProvisioningMethod");
117 if(numberOfMethods == 0 || !supportedMethods)
119 OC_LOG(WARNING, TAG, "Could not find a supported OxM.");
120 return OC_STACK_ERROR;
123 *selectedMethod = supportedMethods[0];
124 for(size_t i = 0; i < numberOfMethods; i++)
126 if(*selectedMethod < supportedMethods[i])
128 *selectedMethod = supportedMethods[i];
136 * Function to select operation mode.This function will return most secure common operation mode.
138 * @param[in] selectedDeviceInfo selected device information to performing provisioning.
139 * @param[out] selectedMode selected operation mode
140 * @return OC_STACK_OK on success
142 static void SelectOperationMode(const OCProvisionDev_t *selectedDeviceInfo,
143 OicSecDpom_t *selectedMode)
145 OC_LOG(DEBUG, TAG, "IN SelectOperationMode");
150 while (i < gNumOfProvisioningMethodsPT && j < selectedDeviceInfo->pstat->smLen)
152 if (gProvisioningToolCapability[i] < selectedDeviceInfo->pstat->sm[j])
156 else if (selectedDeviceInfo->pstat->sm[j] < gProvisioningToolCapability[i])
160 else /* if gProvisioningToolCapability[i] == deviceSupportedMethods[j] */
162 *selectedMode = gProvisioningToolCapability[j];
166 OC_LOG(DEBUG, TAG, "OUT SelectOperationMode");
170 * Function to update owner transfer mode
172 * @param[in] otmCtx Context value of ownership transfer.
173 * @return OC_STACK_OK on success
175 static OCStackResult PutOwnerTransferModeToResource(OTMContext_t* otmCtx);
178 * Function to send request to resource to get its pstat resource information.
180 * @param[in] otmCtx Context value of ownership transfer.
181 * @return OC_STACK_OK on success
183 static OCStackResult GetProvisioningStatusResource(OTMContext_t* otmCtx);
187 * Function to send ownerShip info. This function would update Owned as true and
188 * owner as UUID for provisioning tool
190 * @param[in] otmCtx Context value of ownership transfer.
191 * @return OC_STACK_OK on success
193 static OCStackResult PutOwnershipInformation(OTMContext_t* otmCtx);
196 * Function to update the operation mode. As per the spec. Operation mode in client driven
197 * single service provisioning it will be updated to 0x3
199 * @param[in] otmCtx Context value of ownership transfer.
200 * @param[in] selectedOperationMode selected operation mode
201 * @return OC_STACK_OK on success
203 static OCStackResult PutUpdateOperationMode(OTMContext_t* otmCtx,
204 OicSecDpom_t selectedOperationMode);
207 * Function to start ownership transfer.
208 * This function will send the first request for provisioning,
209 * The next request message is sent from the response handler for this request.
211 * @param[in] ctx context value passed to callback from calling function.
212 * @param[in] selectedDevice selected device information to performing provisioning.
213 * @return OC_STACK_OK on success
215 static OCStackResult StartOwnershipTransfer(void* ctx, OCProvisionDev_t* selectedDevice);
218 * Function to finalize provisioning.
219 * This function will send default ACL and commit hash.
221 * @param[in] otmCtx Context value of ownership transfer.
222 * @return OC_STACK_OK on success
224 static OCStackResult FinalizeProvisioning(OTMContext_t* otmCtx);
227 static bool IsComplete(OTMContext_t* otmCtx)
229 for(size_t i = 0; i < otmCtx->ctxResultArraySize; i++)
231 if(OC_STACK_CONTINUE == otmCtx->ctxResultArray[i].res)
241 * Function to save the result of provisioning.
243 * @param[in,out] otmCtx Context value of ownership transfer.
244 * @param[in] res result of provisioning
246 static void SetResult(OTMContext_t* otmCtx, const OCStackResult res)
248 OC_LOG(DEBUG, TAG, "IN SetResult");
252 OC_LOG(WARNING, TAG, "OTMContext is NULL");
256 if(otmCtx->selectedDeviceInfo)
258 for(size_t i = 0; i < otmCtx->ctxResultArraySize; i++)
260 if(memcmp(otmCtx->selectedDeviceInfo->doxm->deviceID.id,
261 otmCtx->ctxResultArray[i].deviceId.id, UUID_LENGTH) == 0)
263 otmCtx->ctxResultArray[i].res = res;
264 if(OC_STACK_OK != res)
266 otmCtx->ctxHasError = true;
271 //If all request is completed, invoke the user callback.
272 if(IsComplete(otmCtx))
274 otmCtx->ctxResultCallback(otmCtx->userCtx, otmCtx->ctxResultArraySize,
275 otmCtx->ctxResultArray, otmCtx->ctxHasError);
276 OICFree(otmCtx->ctxResultArray);
281 if(OC_STACK_OK != StartOwnershipTransfer(otmCtx,
282 otmCtx->selectedDeviceInfo->next))
284 OC_LOG(ERROR, TAG, "Failed to StartOwnershipTransfer");
289 OC_LOG(DEBUG, TAG, "OUT SetResult");
294 * Function to save ownerPSK at provisioning tool end.
296 * @param[in] selectedDeviceInfo selected device information to performing provisioning.
297 * @return OC_STACK_OK on success
299 static OCStackResult SaveOwnerPSK(OCProvisionDev_t *selectedDeviceInfo)
301 OC_LOG(DEBUG, TAG, "IN SaveOwnerPSK");
303 OCStackResult res = OC_STACK_ERROR;
305 CAEndpoint_t endpoint;
306 memset(&endpoint, 0x00, sizeof(CAEndpoint_t));
307 OICStrcpy(endpoint.addr, MAX_ADDR_STR_SIZE_CA, selectedDeviceInfo->endpoint.addr);
308 endpoint.addr[MAX_ADDR_STR_SIZE_CA - 1] = '\0';
309 endpoint.port = selectedDeviceInfo->securePort;
311 OicUuid_t ptDeviceID = {.id={0}};
312 if (OC_STACK_OK != GetDoxmDeviceID(&ptDeviceID))
314 OC_LOG(ERROR, TAG, "Error while retrieving provisioning tool's device ID");
318 uint8_t ownerPSK[OWNER_PSK_LENGTH_128] = {0};
320 //Generating OwnerPSK
321 CAResult_t pskRet = CAGenerateOwnerPSK(&endpoint,
322 (uint8_t *)GetOxmString(selectedDeviceInfo->doxm->oxmSel),
323 strlen(GetOxmString(selectedDeviceInfo->doxm->oxmSel)), ptDeviceID.id,
324 sizeof(ptDeviceID.id), selectedDeviceInfo->doxm->deviceID.id,
325 sizeof(selectedDeviceInfo->doxm->deviceID.id), ownerPSK,
326 OWNER_PSK_LENGTH_128);
328 if (CA_STATUS_OK == pskRet)
330 OC_LOG(INFO, TAG,"ownerPSK dump:\n");
331 OC_LOG_BUFFER(INFO, TAG,ownerPSK, OWNER_PSK_LENGTH_128);
332 //Generating new credential for provisioning tool
336 char base64Buff[B64ENCODE_OUT_SAFESIZE(sizeof(ownerPSK)) + 1] = {};
337 B64Result b64Ret = b64Encode(ownerPSK, sizeof(ownerPSK), base64Buff, sizeof(base64Buff),
339 VERIFY_SUCCESS(TAG, B64_OK == b64Ret, ERROR);
341 OicSecCred_t *cred = GenerateCredential(&selectedDeviceInfo->doxm->deviceID,
342 SYMMETRIC_PAIR_WISE_KEY, NULL,
343 base64Buff, ownLen, &ptDeviceID);
344 VERIFY_NON_NULL(TAG, cred, ERROR);
346 res = AddCredential(cred);
347 if(res != OC_STACK_OK)
349 DeleteCredList(cred);
355 OC_LOG(ERROR, TAG, "CAGenerateOwnerPSK failed");
358 OC_LOG(DEBUG, TAG, "OUT SaveOwnerPSK");
364 * Callback handler for OwnerShipTransferModeHandler API.
366 * @param[in] ctx ctx value passed to callback from calling function.
367 * @param[in] UNUSED handle to an invocation
368 * @param[in] clientResponse Response from queries to remote servers.
369 * @return OC_STACK_DELETE_TRANSACTION to delete the transaction
370 * and OC_STACK_KEEP_TRANSACTION to keep it.
372 static OCStackApplicationResult OwnerTransferModeHandler(void *ctx, OCDoHandle UNUSED,
373 OCClientResponse *clientResponse)
375 OC_LOG(DEBUG, TAG, "IN OwnerTransferModeHandler");
377 VERIFY_NON_NULL(TAG, clientResponse, WARNING);
378 VERIFY_NON_NULL(TAG, ctx, WARNING);
380 OTMContext_t* otmCtx = (OTMContext_t*)ctx;
382 if(clientResponse->result == OC_STACK_OK)
384 OC_LOG(INFO, TAG, "OwnerTransferModeHandler : response result = OC_STACK_OK");
385 //Send request : GET /oic/sec/pstat
386 OCStackResult res = GetProvisioningStatusResource(otmCtx);
387 if(OC_STACK_OK != res)
389 OC_LOG(WARNING, TAG, "Failed to get pstat information");
390 SetResult(otmCtx, res);
395 OC_LOG_V(WARNING, TAG, "OwnerTransferModeHandler : Client response is incorrect : %d",
396 clientResponse->result);
397 SetResult(otmCtx, clientResponse->result);
400 OC_LOG(DEBUG, TAG, "OUT OwnerTransferModeHandler");
403 return OC_STACK_DELETE_TRANSACTION;
407 * Callback handler for ProvisioningStatusResouceHandler API.
409 * @param[in] ctx ctx value passed to callback from calling function.
410 * @param[in] UNUSED handle to an invocation
411 * @param[in] clientResponse Response from queries to remote servers.
412 * @return OC_STACK_DELETE_TRANSACTION to delete the transaction
413 * and OC_STACK_KEEP_TRANSACTION to keep it.
415 static OCStackApplicationResult ListMethodsHandler(void *ctx, OCDoHandle UNUSED,
416 OCClientResponse *clientResponse)
418 OC_LOG(DEBUG, TAG, "IN ListMethodsHandler");
420 VERIFY_NON_NULL(TAG, clientResponse, WARNING);
421 VERIFY_NON_NULL(TAG, ctx, WARNING);
423 OTMContext_t* otmCtx = (OTMContext_t*)ctx;
425 if (OC_STACK_OK == clientResponse->result)
427 if (NULL == clientResponse->payload)
429 OC_LOG(INFO, TAG, "Skiping Null payload");
430 SetResult(otmCtx, OC_STACK_ERROR);
431 return OC_STACK_DELETE_TRANSACTION;
434 if (PAYLOAD_TYPE_SECURITY != clientResponse->payload->type)
436 OC_LOG(INFO, TAG, "Unknown payload type");
437 SetResult(otmCtx, OC_STACK_ERROR);
438 return OC_STACK_DELETE_TRANSACTION;
441 OicSecPstat_t* pstat = JSONToPstatBin(
442 ((OCSecurityPayload*)clientResponse->payload)->securityData);
445 OC_LOG(ERROR, TAG, "Error while converting json to pstat bin");
446 SetResult(otmCtx, OC_STACK_ERROR);
447 return OC_STACK_DELETE_TRANSACTION;
449 otmCtx->selectedDeviceInfo->pstat = pstat;
451 //Select operation mode (Currently supported SINGLE_SERVICE_CLIENT_DRIVEN only)
452 OicSecDpom_t selectedOperationMode;
453 SelectOperationMode(otmCtx->selectedDeviceInfo, &selectedOperationMode);
455 //Send request : PUT /oic/sec/pstat [{"OM":"0x11", .. }]
456 OCStackResult res = PutUpdateOperationMode(otmCtx, selectedOperationMode);
457 if (OC_STACK_OK != res)
459 OC_LOG(ERROR, TAG, "Error while updating operation mode.");
460 SetResult(otmCtx, res);
465 OC_LOG_V(WARNING, TAG, "ListMethodsHandler : Client response is incorrect : %d",
466 clientResponse->result);
467 SetResult(otmCtx, clientResponse->result);
470 OC_LOG(DEBUG, TAG, "OUT ListMethodsHandler");
472 return OC_STACK_DELETE_TRANSACTION;
476 * Callback handler for OwnershipInformationHandler API.
478 * @param[in] ctx ctx value passed to callback from calling function.
479 * @param[in] UNUSED handle to an invocation
480 * @param[in] clientResponse Response from queries to remote servers.
481 * @return OC_STACK_DELETE_TRANSACTION to delete the transaction
482 * and OC_STACK_KEEP_TRANSACTION to keep it.
484 static OCStackApplicationResult OwnershipInformationHandler(void *ctx, OCDoHandle UNUSED,
485 OCClientResponse *clientResponse)
487 VERIFY_NON_NULL(TAG, clientResponse, WARNING);
488 VERIFY_NON_NULL(TAG, ctx, WARNING);
490 OC_LOG(DEBUG, TAG, "IN OwnershipInformationHandler");
492 OCStackResult res = OC_STACK_OK;
493 OTMContext_t* otmCtx = (OTMContext_t*)ctx;
494 if (OC_STACK_OK == clientResponse->result)
496 if(OIC_RANDOM_DEVICE_PIN == otmCtx->selectedDeviceInfo->doxm->oxmSel)
498 res = RemoveCredential(&otmCtx->subIdForPinOxm);
499 if(OC_STACK_RESOURCE_DELETED != res)
501 OC_LOG_V(ERROR, TAG, "Failed to remove temporal PSK : %d", res);
502 return OC_STACK_DELETE_TRANSACTION;
506 res = SaveOwnerPSK(otmCtx->selectedDeviceInfo);
507 if(OC_STACK_OK != res)
509 OC_LOG(ERROR, TAG, "OperationModeUpdate : Failed to owner PSK generation");
510 SetResult(otmCtx, res);
511 return OC_STACK_DELETE_TRANSACTION;
514 CAEndpoint_t* endpoint = (CAEndpoint_t *)&otmCtx->selectedDeviceInfo->endpoint;
515 endpoint->port = otmCtx->selectedDeviceInfo->securePort;
516 CAResult_t closeRes = CACloseDtlsSession(endpoint);
517 if(CA_STATUS_OK != closeRes)
519 OC_LOG(ERROR, TAG, "Failed to close DTLS session");
520 SetResult(otmCtx, closeRes);
521 return OC_STACK_DELETE_TRANSACTION;
524 OC_LOG(INFO, TAG, "Ownership transfer was successfully completed.");
525 OC_LOG(INFO, TAG, "Start defualt ACL & commit-hash provisioning.");
527 res = FinalizeProvisioning(otmCtx);
528 if(OC_STACK_OK != res)
530 SetResult(otmCtx, res);
535 res = clientResponse->result;
538 OC_LOG(DEBUG, TAG, "OUT OwnershipInformationHandler");
541 return OC_STACK_DELETE_TRANSACTION;
545 * Response handler for update operation mode.
547 * @param[in] ctx ctx value passed to callback from calling function.
548 * @param[in] UNUSED handle to an invocation
549 * @param[in] clientResponse Response from queries to remote servers.
550 * @return OC_STACK_DELETE_TRANSACTION to delete the transaction
551 * and OC_STACK_KEEP_TRANSACTION to keep it.
553 static OCStackApplicationResult OperationModeUpdateHandler(void *ctx, OCDoHandle UNUSED,
554 OCClientResponse *clientResponse)
556 OC_LOG(DEBUG, TAG, "IN OperationModeUpdateHandler");
558 VERIFY_NON_NULL(TAG, clientResponse, WARNING);
559 VERIFY_NON_NULL(TAG, ctx, WARNING);
561 OTMContext_t* otmCtx = (OTMContext_t*)ctx;
563 if (OC_STACK_OK == clientResponse->result)
565 OCStackResult res = OC_STACK_ERROR;
566 OicSecOxm_t selOxm = otmCtx->selectedDeviceInfo->doxm->oxmSel;
568 //Load secret for temporal secure session.
569 if(g_OTMDatas[selOxm].loadSecretCB)
571 res = g_OTMDatas[selOxm].loadSecretCB(otmCtx);
572 if(OC_STACK_OK != res)
574 OC_LOG(ERROR, TAG, "OperationModeUpdate : Failed to load secret");
575 SetResult(otmCtx, res);
576 return OC_STACK_DELETE_TRANSACTION;
580 //Try DTLS handshake to generate secure session
581 if(g_OTMDatas[selOxm].createSecureSessionCB)
583 res = g_OTMDatas[selOxm].createSecureSessionCB(otmCtx);
584 if(OC_STACK_OK != res)
586 OC_LOG(ERROR, TAG, "OperationModeUpdate : Failed to create DTLS session");
587 SetResult(otmCtx, res);
588 return OC_STACK_DELETE_TRANSACTION;
592 //Send request : PUT /oic/sec/doxm [{"Owned":"True", .. , "Owner":"PT's UUID"}]
593 res = PutOwnershipInformation(otmCtx);
594 if(OC_STACK_OK != res)
596 OC_LOG(ERROR, TAG, "OperationModeUpdate : Failed to send owner information");
597 SetResult(otmCtx, res);
602 OC_LOG(ERROR, TAG, "Error while update operation mode");
603 SetResult(otmCtx, clientResponse->result);
606 OC_LOG(DEBUG, TAG, "OUT OperationModeUpdateHandler");
609 return OC_STACK_DELETE_TRANSACTION;
613 static OCStackResult PutOwnerTransferModeToResource(OTMContext_t* otmCtx)
615 OC_LOG(DEBUG, TAG, "IN PutOwnerTransferModeToResource");
617 if(!otmCtx || !otmCtx->selectedDeviceInfo)
619 OC_LOG(ERROR, TAG, "Invalid parameters");
620 return OC_STACK_INVALID_PARAM;
623 OCProvisionDev_t* deviceInfo = otmCtx->selectedDeviceInfo;
624 OicSecOxm_t selectedOxm = deviceInfo->doxm->oxmSel;
625 char query[MAX_URI_LENGTH + MAX_QUERY_LENGTH] = {0};
627 if(!PMGenerateQuery(false,
628 deviceInfo->endpoint.addr, deviceInfo->endpoint.port,
629 deviceInfo->connType,
630 query, sizeof(query), OIC_RSRC_DOXM_URI))
632 OC_LOG(ERROR, TAG, "PutOwnerTransferModeToResource : Failed to generate query");
633 return OC_STACK_ERROR;
635 OC_LOG_V(DEBUG, TAG, "Query=%s", query);
636 OCSecurityPayload* secPayload = (OCSecurityPayload*)OICCalloc(1, sizeof(OCSecurityPayload));
639 OC_LOG(ERROR, TAG, "Failed to memory allocation");
640 return OC_STACK_NO_MEMORY;
642 secPayload->base.type = PAYLOAD_TYPE_SECURITY;
643 secPayload->securityData = g_OTMDatas[selectedOxm].createSelectOxmPayloadCB(otmCtx);
644 if (NULL == secPayload->securityData)
647 OC_LOG(ERROR, TAG, "Error while converting bin to json");
648 return OC_STACK_ERROR;
650 OC_LOG_V(DEBUG, TAG, "Payload : %s", secPayload->securityData);
652 OCCallbackData cbData;
653 cbData.cb = &OwnerTransferModeHandler;
654 cbData.context = (void *)otmCtx;
656 OCStackResult res = OCDoResource(NULL, OC_REST_PUT, query,
657 &deviceInfo->endpoint, (OCPayload*)secPayload,
658 deviceInfo->connType, OC_LOW_QOS, &cbData, NULL, 0);
659 if (res != OC_STACK_OK)
661 OC_LOG(ERROR, TAG, "OCStack resource error");
664 OC_LOG(DEBUG, TAG, "OUT PutOwnerTransferModeToResource");
669 static OCStackResult GetProvisioningStatusResource(OTMContext_t* otmCtx)
671 OC_LOG(DEBUG, TAG, "IN GetProvisioningStatusResource");
673 if(!otmCtx || !otmCtx->selectedDeviceInfo)
675 OC_LOG(ERROR, TAG, "Invailed parameters");
676 return OC_STACK_INVALID_PARAM;
679 OCProvisionDev_t* deviceInfo = otmCtx->selectedDeviceInfo;
680 char query[MAX_URI_LENGTH + MAX_QUERY_LENGTH] = {0};
681 if(!PMGenerateQuery(false,
682 deviceInfo->endpoint.addr, deviceInfo->endpoint.port,
683 deviceInfo->connType,
684 query, sizeof(query), OIC_RSRC_PSTAT_URI))
686 OC_LOG(ERROR, TAG, "GetProvisioningStatusResource : Failed to generate query");
687 return OC_STACK_ERROR;
689 OC_LOG_V(DEBUG, TAG, "Query=%s", query);
691 OCCallbackData cbData;
692 cbData.cb = &ListMethodsHandler;
693 cbData.context = (void *)otmCtx;
695 OCStackResult res = OCDoResource(NULL, OC_REST_GET, query, NULL, NULL,
696 deviceInfo->connType, OC_LOW_QOS, &cbData, NULL, 0);
697 if (res != OC_STACK_OK)
699 OC_LOG(ERROR, TAG, "OCStack resource error");
702 OC_LOG(DEBUG, TAG, "OUT GetProvisioningStatusResource");
708 static OCStackResult PutOwnershipInformation(OTMContext_t* otmCtx)
710 OC_LOG(DEBUG, TAG, "IN PutOwnershipInformation");
712 if(!otmCtx || !otmCtx->selectedDeviceInfo)
714 OC_LOG(ERROR, TAG, "Invailed parameters");
715 return OC_STACK_INVALID_PARAM;
718 OCProvisionDev_t* deviceInfo = otmCtx->selectedDeviceInfo;
719 char query[MAX_URI_LENGTH + MAX_QUERY_LENGTH] = {0};
720 if(!PMGenerateQuery(true,
721 deviceInfo->endpoint.addr, deviceInfo->securePort,
722 deviceInfo->connType,
723 query, sizeof(query), OIC_RSRC_DOXM_URI))
725 OC_LOG(ERROR, TAG, "PutOwnershipInformation : Failed to generate query");
726 return OC_STACK_ERROR;
728 OC_LOG_V(DEBUG, TAG, "Query=%s", query);
730 //OwnershipInformationHandler
731 OicSecOxm_t selOxm = deviceInfo->doxm->oxmSel;
732 OCSecurityPayload* secPayload = (OCSecurityPayload*)OICCalloc(1, sizeof(OCSecurityPayload));
735 OC_LOG(ERROR, TAG, "Failed to memory allocation");
736 return OC_STACK_NO_MEMORY;
738 secPayload->base.type = PAYLOAD_TYPE_SECURITY;
739 secPayload->securityData = g_OTMDatas[selOxm].createOwnerTransferPayloadCB(otmCtx);
740 if (NULL == secPayload->securityData)
743 OC_LOG(ERROR, TAG, "Error while converting doxm bin to json");
744 return OC_STACK_INVALID_PARAM;
747 OCCallbackData cbData;
748 cbData.cb = &OwnershipInformationHandler;
749 cbData.context = (void *)otmCtx;
751 OCStackResult res = OCDoResource(NULL, OC_REST_PUT, query, 0, (OCPayload*)secPayload,
752 deviceInfo->connType, OC_LOW_QOS, &cbData, NULL, 0);
753 if (res != OC_STACK_OK)
755 OC_LOG(ERROR, TAG, "OCStack resource error");
758 OC_LOG(DEBUG, TAG, "OUT PutOwnershipInformation");
763 static OCStackResult PutUpdateOperationMode(OTMContext_t* otmCtx,
764 OicSecDpom_t selectedOperationMode)
766 OC_LOG(DEBUG, TAG, "IN PutUpdateOperationMode");
768 if(!otmCtx || !otmCtx->selectedDeviceInfo)
770 return OC_STACK_INVALID_PARAM;
773 OCProvisionDev_t* deviceInfo = otmCtx->selectedDeviceInfo;
774 char query[MAX_URI_LENGTH + MAX_QUERY_LENGTH] = {0};
775 if(!PMGenerateQuery(false,
776 deviceInfo->endpoint.addr, deviceInfo->endpoint.port,
777 deviceInfo->connType,
778 query, sizeof(query), OIC_RSRC_PSTAT_URI))
780 OC_LOG(ERROR, TAG, "PutUpdateOperationMode : Failed to generate query");
781 return OC_STACK_ERROR;
783 OC_LOG_V(DEBUG, TAG, "Query=%s", query);
785 deviceInfo->pstat->om = selectedOperationMode;
787 OCSecurityPayload* secPayload = (OCSecurityPayload*)OICCalloc(1, sizeof(OCSecurityPayload));
790 OC_LOG(ERROR, TAG, "Failed to memory allocation");
791 return OC_STACK_NO_MEMORY;
793 secPayload->base.type = PAYLOAD_TYPE_SECURITY;
794 secPayload->securityData = BinToPstatJSON(deviceInfo->pstat);
795 if (NULL == secPayload->securityData)
798 OC_LOG(ERROR, TAG, "Error while converting pstat bin to json");
799 return OC_STACK_INVALID_PARAM;
802 OCCallbackData cbData;
803 cbData.cb = &OperationModeUpdateHandler;
804 cbData.context = (void *)otmCtx;
806 OCStackResult res = OCDoResource(NULL, OC_REST_PUT, query, 0, (OCPayload*)secPayload,
807 deviceInfo->connType, OC_LOW_QOS, &cbData, NULL, 0);
808 if (res != OC_STACK_OK)
810 OC_LOG(ERROR, TAG, "OCStack resource error");
813 OC_LOG(DEBUG, TAG, "OUT PutUpdateOperationMode");
818 static OCStackResult StartOwnershipTransfer(void* ctx, OCProvisionDev_t* selectedDevice)
820 OC_LOG(INFO, TAG, "IN StartOwnershipTransfer");
821 OTMContext_t* otmCtx = (OTMContext_t*)ctx;
822 otmCtx->selectedDeviceInfo = selectedDevice;
824 //Set to the lowest level OxM, and then find more higher level OxM.
825 OCStackResult res = SelectProvisioningMethod(selectedDevice->doxm->oxm,
826 selectedDevice->doxm->oxmLen,
827 &selectedDevice->doxm->oxmSel);
828 if(OC_STACK_OK != res)
830 OC_LOG(ERROR, TAG, "Failed to select the provisioning method");
831 SetResult(otmCtx, res);
834 OC_LOG_V(DEBUG, TAG, "Selected provisoning method = %d", selectedDevice->doxm->oxmSel);
836 //Send Req: PUT /oic/sec/doxm [{..."OxmSel" :g_OTMDatas[Index of Selected OxM].OXMString,...}]
837 res = PutOwnerTransferModeToResource(otmCtx);
838 if(OC_STACK_OK != res)
840 OC_LOG(WARNING, TAG, "Failed to select the provisioning method");
841 SetResult(otmCtx, res);
845 OC_LOG(INFO, TAG, "OUT StartOwnershipTransfer");
851 OCStackResult OTMSetOwnershipTransferCallbackData(OicSecOxm_t oxmType, OTMCallbackData_t* data)
853 OC_LOG(DEBUG, TAG, "IN OTMSetOwnerTransferCallbackData");
857 OC_LOG(ERROR, TAG, "OTMSetOwnershipTransferCallbackData : Invalid parameters");
858 return OC_STACK_INVALID_PARAM;
860 if(oxmType >= OIC_OXM_COUNT)
862 OC_LOG(INFO, TAG, "Unknow ownership transfer method");
863 return OC_STACK_INVALID_PARAM;
866 g_OTMDatas[oxmType].loadSecretCB= data->loadSecretCB;
867 g_OTMDatas[oxmType].createSecureSessionCB = data->createSecureSessionCB;
868 g_OTMDatas[oxmType].createSelectOxmPayloadCB = data->createSelectOxmPayloadCB;
869 g_OTMDatas[oxmType].createOwnerTransferPayloadCB = data->createOwnerTransferPayloadCB;
871 OC_LOG(DEBUG, TAG, "OUT OTMSetOwnerTransferCallbackData");
877 * NOTE : Unowned discovery should be done before performing OTMDoOwnershipTransfer
879 OCStackResult OTMDoOwnershipTransfer(void* ctx,
880 OCProvisionDev_t *selectedDevicelist,
881 OCProvisionResultCB resultCallback)
883 OC_LOG(DEBUG, TAG, "IN OTMDoOwnershipTransfer");
885 if (NULL == selectedDevicelist || NULL == resultCallback )
887 return OC_STACK_INVALID_PARAM;
890 OTMContext_t* otmCtx = (OTMContext_t*)OICCalloc(1,sizeof(OTMContext_t));
893 OC_LOG(ERROR, TAG, "Failed to create OTM Context");
894 return OC_STACK_NO_MEMORY;
896 otmCtx->ctxResultCallback = resultCallback;
897 otmCtx->ctxHasError = false;
898 otmCtx->userCtx = ctx;
899 OCProvisionDev_t* pCurDev = selectedDevicelist;
901 //Counting number of selected devices.
902 otmCtx->ctxResultArraySize = 0;
903 while(NULL != pCurDev)
905 otmCtx->ctxResultArraySize++;
906 pCurDev = pCurDev->next;
909 otmCtx->ctxResultArray =
910 (OCProvisionResult_t*)OICCalloc(otmCtx->ctxResultArraySize, sizeof(OCProvisionResult_t));
911 if(NULL == otmCtx->ctxResultArray)
913 OC_LOG(ERROR, TAG, "OTMDoOwnershipTransfer : Failed to memory allocation");
915 return OC_STACK_NO_MEMORY;
917 pCurDev = selectedDevicelist;
919 //Fill the device UUID for result array.
920 for(size_t devIdx = 0; devIdx < otmCtx->ctxResultArraySize; devIdx++)
922 //Checking duplication of Device ID.
923 if(true == PDMIsDuplicateDevice(&pCurDev->doxm->deviceID))
925 OC_LOG(ERROR, TAG, "OTMDoOwnershipTransfer : Device ID is duplicate");
926 OICFree(otmCtx->ctxResultArray);
928 return OC_STACK_INVALID_PARAM;
930 memcpy(otmCtx->ctxResultArray[devIdx].deviceId.id,
931 pCurDev->doxm->deviceID.id,
933 otmCtx->ctxResultArray[devIdx].res = OC_STACK_CONTINUE;
934 pCurDev = pCurDev->next;
936 StartOwnershipTransfer(otmCtx, selectedDevicelist);
938 OC_LOG(DEBUG, TAG, "OUT OTMDoOwnershipTransfer");
943 * Callback handler of SRPFinalizeProvisioning.
945 * @param[in] ctx ctx value passed to callback from calling function.
946 * @param[in] UNUSED handle to an invocation
947 * @param[in] clientResponse Response from queries to remote servers.
948 * @return OC_STACK_DELETE_TRANSACTION to delete the transaction
949 * and OC_STACK_KEEP_TRANSACTION to keep it.
951 static OCStackApplicationResult FinalizeProvisioningCB(void *ctx, OCDoHandle UNUSED,
952 OCClientResponse *clientResponse)
954 OC_LOG_V(INFO, TAG, "IN FinalizeProvisioningCB.");
956 VERIFY_NON_NULL(TAG, clientResponse, ERROR);
957 VERIFY_NON_NULL(TAG, ctx, ERROR);
959 OTMContext_t* otmCtx = (OTMContext_t*)ctx;
961 if(OC_STACK_OK == clientResponse->result)
963 OCStackResult res = PDMAddDevice(&otmCtx->selectedDeviceInfo->doxm->deviceID);
965 if (OC_STACK_OK == res)
967 OC_LOG_V(INFO, TAG, "Add device's UUID in PDM_DB");
968 SetResult(otmCtx, OC_STACK_OK);
969 return OC_STACK_DELETE_TRANSACTION;
973 OC_LOG(ERROR, TAG, "Ownership transfer is complete but adding information to DB is failed.");
977 return OC_STACK_DELETE_TRANSACTION;
981 * Callback handler of default ACL provisioning.
983 * @param[in] ctx ctx value passed to callback from calling function.
984 * @param[in] UNUSED handle to an invocation
985 * @param[in] clientResponse Response from queries to remote servers.
986 * @return OC_STACK_DELETE_TRANSACTION to delete the transaction
987 * and OC_STACK_KEEP_TRANSACTION to keep it.
989 static OCStackApplicationResult ProvisionDefaultACLCB(void *ctx, OCDoHandle UNUSED,
990 OCClientResponse *clientResponse)
992 OC_LOG_V(INFO, TAG, "IN ProvisionDefaultACLCB.");
994 VERIFY_NON_NULL(TAG, clientResponse, ERROR);
995 VERIFY_NON_NULL(TAG, ctx, ERROR);
997 OTMContext_t* otmCtx = (OTMContext_t*) ctx;
1000 if (OC_STACK_RESOURCE_CREATED == clientResponse->result)
1002 OC_LOG_V(INFO, TAG, "Staring commit hash task.");
1003 // TODO hash currently have fixed value 0.
1004 uint16_t aclHash = 0;
1005 otmCtx->selectedDeviceInfo->pstat->commitHash = aclHash;
1006 otmCtx->selectedDeviceInfo->pstat->tm = NORMAL;
1007 OCSecurityPayload* secPayload = (OCSecurityPayload*)OICCalloc(1, sizeof(OCSecurityPayload));
1010 OC_LOG(ERROR, TAG, "Failed to memory allocation");
1011 return OC_STACK_NO_MEMORY;
1013 secPayload->base.type = PAYLOAD_TYPE_SECURITY;
1014 secPayload->securityData = BinToPstatJSON(otmCtx->selectedDeviceInfo->pstat);
1015 if (NULL == secPayload->securityData)
1017 OICFree(secPayload);
1018 SetResult(otmCtx, OC_STACK_INVALID_JSON);
1019 return OC_STACK_DELETE_TRANSACTION;
1021 OC_LOG_V(INFO, TAG, "Created payload for commit hash: %s",secPayload->securityData);
1023 char query[MAX_URI_LENGTH + MAX_QUERY_LENGTH] = {0};
1024 if(!PMGenerateQuery(true,
1025 otmCtx->selectedDeviceInfo->endpoint.addr,
1026 otmCtx->selectedDeviceInfo->securePort,
1027 otmCtx->selectedDeviceInfo->connType,
1028 query, sizeof(query), OIC_RSRC_PSTAT_URI))
1030 OC_LOG(ERROR, TAG, "ProvisionDefaultACLCB : Failed to generate query");
1031 return OC_STACK_ERROR;
1033 OC_LOG_V(DEBUG, TAG, "Query=%s", query);
1035 OCCallbackData cbData = {.context=NULL, .cb=NULL, .cd=NULL};
1036 cbData.cb = &FinalizeProvisioningCB;
1037 cbData.context = (void*)otmCtx;
1039 OCStackResult ret = OCDoResource(NULL, OC_REST_PUT, query, 0, (OCPayload*)secPayload,
1040 otmCtx->selectedDeviceInfo->connType, OC_HIGH_QOS, &cbData, NULL, 0);
1041 OC_LOG_V(INFO, TAG, "OCDoResource returned: %d",ret);
1042 if (ret != OC_STACK_OK)
1044 OC_LOG(ERROR, TAG, "OCStack resource error");
1045 SetResult(otmCtx, ret);
1050 OC_LOG_V(INFO, TAG, "Error occured in provisionDefaultACLCB :: %d\n",
1051 clientResponse->result);
1052 SetResult(otmCtx, clientResponse->result);
1055 return OC_STACK_DELETE_TRANSACTION;
1059 OCStackResult FinalizeProvisioning(OTMContext_t* otmCtx)
1061 OC_LOG(INFO, TAG, "IN FinalizeProvisioning");
1065 OC_LOG(ERROR, TAG, "OTMContext is NULL");
1066 return OC_STACK_INVALID_PARAM;
1068 if(!otmCtx->selectedDeviceInfo)
1070 OC_LOG(ERROR, TAG, "Can't find device information in OTMContext");
1072 return OC_STACK_INVALID_PARAM;
1074 // Provision Default ACL to device
1075 OicSecAcl_t defaultAcl =
1088 OicUuid_t provTooldeviceID = {.id={0}};
1089 if (OC_STACK_OK != GetDoxmDeviceID(&provTooldeviceID))
1091 OC_LOG(ERROR, TAG, "Error while retrieving provisioning tool's device ID");
1092 SetResult(otmCtx, OC_STACK_ERROR);
1093 return OC_STACK_ERROR;
1095 OC_LOG(INFO, TAG, "Retieved deviceID");
1096 memcpy(defaultAcl.subject.id, provTooldeviceID.id, sizeof(defaultAcl.subject.id));
1097 char *wildCardResource = "*";
1098 defaultAcl.resources = &wildCardResource;
1100 defaultAcl.owners = (OicUuid_t *) OICCalloc(1, UUID_LENGTH);
1101 if(!defaultAcl.owners)
1103 OC_LOG(ERROR, TAG, "Failed to memory allocation for default ACL");
1104 SetResult(otmCtx, OC_STACK_NO_MEMORY);
1105 return OC_STACK_NO_MEMORY;
1107 memcpy(defaultAcl.owners->id, provTooldeviceID.id, UUID_LENGTH);
1108 OC_LOG(INFO, TAG, "Provisioning default ACL");
1110 OCSecurityPayload* secPayload = (OCSecurityPayload*)OICCalloc(1, sizeof(OCSecurityPayload));
1113 OC_LOG(ERROR, TAG, "Failed to memory allocation");
1114 return OC_STACK_NO_MEMORY;
1116 secPayload->base.type = PAYLOAD_TYPE_SECURITY;
1117 secPayload->securityData = BinToAclJSON(&defaultAcl);
1118 OICFree(defaultAcl.owners);
1119 if(!secPayload->securityData)
1121 OICFree(secPayload);
1122 OC_LOG(INFO, TAG, "FinalizeProvisioning : Failed to BinToAclJSON");
1123 SetResult(otmCtx, OC_STACK_ERROR);
1124 return OC_STACK_ERROR;
1126 OC_LOG_V(INFO, TAG, "Provisioning default ACL : %s",secPayload->securityData);
1128 char query[MAX_URI_LENGTH + MAX_QUERY_LENGTH] = {0};
1129 if(!PMGenerateQuery(true,
1130 otmCtx->selectedDeviceInfo->endpoint.addr,
1131 otmCtx->selectedDeviceInfo->securePort,
1132 otmCtx->selectedDeviceInfo->connType,
1133 query, sizeof(query), OIC_RSRC_ACL_URI))
1135 OC_LOG(ERROR, TAG, "FinalizeProvisioning : Failed to generate query");
1136 return OC_STACK_ERROR;
1138 OC_LOG_V(DEBUG, TAG, "Query=%s", query);
1140 OC_LOG_V(INFO, TAG, "Request URI for Provisioning default ACL : %s", query);
1142 OCCallbackData cbData = {.context=NULL, .cb=NULL, .cd=NULL};
1143 cbData.cb = &ProvisionDefaultACLCB;
1144 cbData.context = (void *)otmCtx;
1146 OCStackResult ret = OCDoResource(NULL, OC_REST_POST, query,
1147 &otmCtx->selectedDeviceInfo->endpoint, (OCPayload*)secPayload,
1148 otmCtx->selectedDeviceInfo->connType, OC_HIGH_QOS, &cbData, NULL, 0);
1149 if (OC_STACK_OK != ret)
1151 SetResult(otmCtx, ret);
1155 OC_LOG(INFO, TAG, "OUT FinalizeProvisioning");