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 bool isDuplicate = true;
924 OCStackResult res = PDMIsDuplicateDevice(&pCurDev->doxm->deviceID, &isDuplicate);
925 if (OC_STACK_OK != res)
927 OICFree(otmCtx->ctxResultArray);
933 OC_LOG(ERROR, TAG, "OTMDoOwnershipTransfer : Device ID is duplicated");
934 OICFree(otmCtx->ctxResultArray);
936 return OC_STACK_INVALID_PARAM;
938 memcpy(otmCtx->ctxResultArray[devIdx].deviceId.id,
939 pCurDev->doxm->deviceID.id,
941 otmCtx->ctxResultArray[devIdx].res = OC_STACK_CONTINUE;
942 pCurDev = pCurDev->next;
944 StartOwnershipTransfer(otmCtx, selectedDevicelist);
946 OC_LOG(DEBUG, TAG, "OUT OTMDoOwnershipTransfer");
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 OCStackResult res = PDMAddDevice(&otmCtx->selectedDeviceInfo->doxm->deviceID);
973 if (OC_STACK_OK == res)
975 OC_LOG_V(INFO, TAG, "Add device's UUID in PDM_DB");
976 SetResult(otmCtx, OC_STACK_OK);
977 return OC_STACK_DELETE_TRANSACTION;
981 OC_LOG(ERROR, TAG, "Ownership transfer is complete but adding information to DB is failed.");
985 return OC_STACK_DELETE_TRANSACTION;
989 * Callback handler of default ACL provisioning.
991 * @param[in] ctx ctx value passed to callback from calling function.
992 * @param[in] UNUSED handle to an invocation
993 * @param[in] clientResponse Response from queries to remote servers.
994 * @return OC_STACK_DELETE_TRANSACTION to delete the transaction
995 * and OC_STACK_KEEP_TRANSACTION to keep it.
997 static OCStackApplicationResult ProvisionDefaultACLCB(void *ctx, OCDoHandle UNUSED,
998 OCClientResponse *clientResponse)
1000 OC_LOG_V(INFO, TAG, "IN ProvisionDefaultACLCB.");
1002 VERIFY_NON_NULL(TAG, clientResponse, ERROR);
1003 VERIFY_NON_NULL(TAG, ctx, ERROR);
1005 OTMContext_t* otmCtx = (OTMContext_t*) ctx;
1008 if (OC_STACK_RESOURCE_CREATED == clientResponse->result)
1010 OC_LOG_V(INFO, TAG, "Staring commit hash task.");
1011 // TODO hash currently have fixed value 0.
1012 uint16_t aclHash = 0;
1013 otmCtx->selectedDeviceInfo->pstat->commitHash = aclHash;
1014 otmCtx->selectedDeviceInfo->pstat->tm = NORMAL;
1015 OCSecurityPayload* secPayload = (OCSecurityPayload*)OICCalloc(1, sizeof(OCSecurityPayload));
1018 OC_LOG(ERROR, TAG, "Failed to memory allocation");
1019 return OC_STACK_NO_MEMORY;
1021 secPayload->base.type = PAYLOAD_TYPE_SECURITY;
1022 secPayload->securityData = BinToPstatJSON(otmCtx->selectedDeviceInfo->pstat);
1023 if (NULL == secPayload->securityData)
1025 OICFree(secPayload);
1026 SetResult(otmCtx, OC_STACK_INVALID_JSON);
1027 return OC_STACK_DELETE_TRANSACTION;
1029 OC_LOG_V(INFO, TAG, "Created payload for commit hash: %s",secPayload->securityData);
1031 char query[MAX_URI_LENGTH + MAX_QUERY_LENGTH] = {0};
1032 if(!PMGenerateQuery(true,
1033 otmCtx->selectedDeviceInfo->endpoint.addr,
1034 otmCtx->selectedDeviceInfo->securePort,
1035 otmCtx->selectedDeviceInfo->connType,
1036 query, sizeof(query), OIC_RSRC_PSTAT_URI))
1038 OC_LOG(ERROR, TAG, "ProvisionDefaultACLCB : Failed to generate query");
1039 return OC_STACK_ERROR;
1041 OC_LOG_V(DEBUG, TAG, "Query=%s", query);
1043 OCCallbackData cbData = {.context=NULL, .cb=NULL, .cd=NULL};
1044 cbData.cb = &FinalizeProvisioningCB;
1045 cbData.context = (void*)otmCtx;
1047 OCStackResult ret = OCDoResource(NULL, OC_REST_PUT, query, 0, (OCPayload*)secPayload,
1048 otmCtx->selectedDeviceInfo->connType, OC_HIGH_QOS, &cbData, NULL, 0);
1049 OC_LOG_V(INFO, TAG, "OCDoResource returned: %d",ret);
1050 if (ret != OC_STACK_OK)
1052 OC_LOG(ERROR, TAG, "OCStack resource error");
1053 SetResult(otmCtx, ret);
1058 OC_LOG_V(INFO, TAG, "Error occured in provisionDefaultACLCB :: %d\n",
1059 clientResponse->result);
1060 SetResult(otmCtx, clientResponse->result);
1063 return OC_STACK_DELETE_TRANSACTION;
1067 OCStackResult FinalizeProvisioning(OTMContext_t* otmCtx)
1069 OC_LOG(INFO, TAG, "IN FinalizeProvisioning");
1073 OC_LOG(ERROR, TAG, "OTMContext is NULL");
1074 return OC_STACK_INVALID_PARAM;
1076 if(!otmCtx->selectedDeviceInfo)
1078 OC_LOG(ERROR, TAG, "Can't find device information in OTMContext");
1080 return OC_STACK_INVALID_PARAM;
1082 // Provision Default ACL to device
1083 OicSecAcl_t defaultAcl =
1096 OicUuid_t provTooldeviceID = {.id={0}};
1097 if (OC_STACK_OK != GetDoxmDeviceID(&provTooldeviceID))
1099 OC_LOG(ERROR, TAG, "Error while retrieving provisioning tool's device ID");
1100 SetResult(otmCtx, OC_STACK_ERROR);
1101 return OC_STACK_ERROR;
1103 OC_LOG(INFO, TAG, "Retieved deviceID");
1104 memcpy(defaultAcl.subject.id, provTooldeviceID.id, sizeof(defaultAcl.subject.id));
1105 char *wildCardResource = "*";
1106 defaultAcl.resources = &wildCardResource;
1108 defaultAcl.owners = (OicUuid_t *) OICCalloc(1, UUID_LENGTH);
1109 if(!defaultAcl.owners)
1111 OC_LOG(ERROR, TAG, "Failed to memory allocation for default ACL");
1112 SetResult(otmCtx, OC_STACK_NO_MEMORY);
1113 return OC_STACK_NO_MEMORY;
1115 memcpy(defaultAcl.owners->id, provTooldeviceID.id, UUID_LENGTH);
1116 OC_LOG(INFO, TAG, "Provisioning default ACL");
1118 OCSecurityPayload* secPayload = (OCSecurityPayload*)OICCalloc(1, sizeof(OCSecurityPayload));
1121 OC_LOG(ERROR, TAG, "Failed to memory allocation");
1122 return OC_STACK_NO_MEMORY;
1124 secPayload->base.type = PAYLOAD_TYPE_SECURITY;
1125 secPayload->securityData = BinToAclJSON(&defaultAcl);
1126 OICFree(defaultAcl.owners);
1127 if(!secPayload->securityData)
1129 OICFree(secPayload);
1130 OC_LOG(INFO, TAG, "FinalizeProvisioning : Failed to BinToAclJSON");
1131 SetResult(otmCtx, OC_STACK_ERROR);
1132 return OC_STACK_ERROR;
1134 OC_LOG_V(INFO, TAG, "Provisioning default ACL : %s",secPayload->securityData);
1136 char query[MAX_URI_LENGTH + MAX_QUERY_LENGTH] = {0};
1137 if(!PMGenerateQuery(true,
1138 otmCtx->selectedDeviceInfo->endpoint.addr,
1139 otmCtx->selectedDeviceInfo->securePort,
1140 otmCtx->selectedDeviceInfo->connType,
1141 query, sizeof(query), OIC_RSRC_ACL_URI))
1143 OC_LOG(ERROR, TAG, "FinalizeProvisioning : Failed to generate query");
1144 return OC_STACK_ERROR;
1146 OC_LOG_V(DEBUG, TAG, "Query=%s", query);
1148 OC_LOG_V(INFO, TAG, "Request URI for Provisioning default ACL : %s", query);
1150 OCCallbackData cbData = {.context=NULL, .cb=NULL, .cd=NULL};
1151 cbData.cb = &ProvisionDefaultACLCB;
1152 cbData.context = (void *)otmCtx;
1154 OCStackResult ret = OCDoResource(NULL, OC_REST_POST, query,
1155 &otmCtx->selectedDeviceInfo->endpoint, (OCPayload*)secPayload,
1156 otmCtx->selectedDeviceInfo->connType, OC_HIGH_QOS, &cbData, NULL, 0);
1157 if (OC_STACK_OK != ret)
1159 SetResult(otmCtx, ret);
1163 OC_LOG(INFO, TAG, "OUT FinalizeProvisioning");