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 * Possible states of ownership transfer manager module.
69 SP_DISCOVERY_STARTED = (0x1 << 1),
70 SP_DISCOVERY_ERROR = (0x1 << 2),
71 SP_DISCOVERY_DONE = (0x1 << 3),
72 SP_UP_OWN_TR_METH_STARTED = (0x1 << 4),
73 SP_UP_OWN_TR_METH_ERROR = (0x1 << 5),
74 SP_UP_OWN_TR_METH_DONE = (0x1 << 6),
75 SP_LIST_METHODS_STARTED = (0x1 << 7),
76 SP_LIST_METHODS_ERROR = (0x1 << 8),
77 SP_LIST_METHODS_DONE = (0x1 << 9),
78 SP_UPDATE_OP_MODE_STARTED = (0x1 << 10),
79 SP_UPDATE_OP_MODE_ERROR = (0x1 << 11),
80 SP_UPDATE_OP_MODE_DONE = (0x1 << 12),
81 SP_UPDATE_OWNER_STARTED = (0x1 << 13),
82 SP_UPDATE_OWNER_ERROR = (0x1 << 14),
83 SP_UPDATE_OWNER_DONE = (0x1 << 15)
89 * Array to store the callbacks for each owner transfer method.
91 static OTMCallbackData_t g_OTMDatas[OIC_OXM_COUNT];
94 * Variable for storing provisioning tool's provisioning capabilities
95 * Must be in decreasing order of preference. More prefered method should
96 * have lower array index.
98 static OicSecDpom_t gProvisioningToolCapability[] = { SINGLE_SERVICE_CLIENT_DRIVEN };
101 * Number of supported provisioning methods
102 * current version supports only one.
104 static size_t gNumOfProvisioningMethodsPT = 1;
107 * Function to getting string of ownership transfer method
109 static const char* GetOxmString(OicSecOxm_t oxmType)
114 return OXM_JUST_WORKS;
115 case OIC_MODE_SWITCH:
116 return OXM_MODE_SWITCH;
117 case OIC_RANDOM_DEVICE_PIN:
118 return OXM_RANDOM_DEVICE_PIN;
119 case OIC_PRE_PROVISIONED_DEVICE_PIN:
120 return OXM_PRE_PROVISIONED_DEVICE_PIN;
121 case OIC_PRE_PROVISION_STRONG_CREDENTIAL:
122 return OXM_PRE_PROVISIONED_STRONG_CREDENTIAL;
129 * Function to select appropriate provisioning method.
131 * @param[in] supportedMethods Array of supported methods
132 * @param[in] numberOfMethods number of supported methods
133 * @param[out] selectedMethod Selected methods
134 * @return SP_SUCCESS on success
136 static OCStackResult SelectProvisioningMethod(const OicSecOxm_t *supportedMethods,
137 size_t numberOfMethods,
138 OicSecOxm_t *selectedMethod)
140 OC_LOG(DEBUG, TAG, "IN SelectProvisioningMethod");
142 if(numberOfMethods == 0 || !supportedMethods)
144 OC_LOG(WARNING, TAG, "Could not find a supported OxM.");
145 return OC_STACK_ERROR;
148 *selectedMethod = supportedMethods[0];
149 for(size_t i = 0; i < numberOfMethods; i++)
151 if(*selectedMethod < supportedMethods[i])
153 *selectedMethod = supportedMethods[i];
161 * Function to select operation mode.This function will return most secure common operation mode.
163 * @param[in] selectedDeviceInfo selected device information to performing provisioning.
164 * @param[out] selectedMode selected operation mode
165 * @return SP_SUCCESS on success
167 static void SelectOperationMode(const OCProvisionDev_t *selectedDeviceInfo,
168 OicSecDpom_t *selectedMode)
170 OC_LOG(DEBUG, TAG, "IN SelectOperationMode");
175 while (i < gNumOfProvisioningMethodsPT && j < selectedDeviceInfo->pstat->smLen)
177 if (gProvisioningToolCapability[i] < selectedDeviceInfo->pstat->sm[j])
181 else if (selectedDeviceInfo->pstat->sm[j] < gProvisioningToolCapability[i])
185 else /* if gProvisioningToolCapability[i] == deviceSupportedMethods[j] */
187 *selectedMode = gProvisioningToolCapability[j];
191 OC_LOG(DEBUG, TAG, "OUT SelectOperationMode");
195 * Function to update owner transfer mode
197 * @param[in] otmCtx Context value of ownership transfer.
198 * @return OC_STACK_OK on success
200 static OCStackResult PutOwnerTransferModeToResource(OTMContext_t* otmCtx);
203 * Function to send request to resource to get its pstat resource information.
205 * @param[in] otmCtx Context value of ownership transfer.
206 * @return OC_STACK_OK on success
208 static OCStackResult GetProvisioningStatusResource(OTMContext_t* otmCtx);
212 * Function to send ownerShip info. This function would update Owned as true and
213 * owner as UUID for provisioning tool
215 * @param[in] otmCtx Context value of ownership transfer.
216 * @return OC_STACK_OK on success
218 static OCStackResult PutOwnershipInformation(OTMContext_t* otmCtx);
221 * Function to update the operation mode. As per the spec. Operation mode in client driven
222 * single service provisioning it will be updated to 0x3
224 * @param[in] otmCtx Context value of ownership transfer.
225 * @param[in] selectedOperationMode selected operation mode
226 * @return OC_STACK_OK on success
228 static OCStackResult PutUpdateOperationMode(OTMContext_t* otmCtx,
229 OicSecDpom_t selectedOperationMode);
232 * Function to start ownership transfer.
233 * This function will send the first request for provisioning,
234 * The next request message is sent from the response handler for this request.
236 * @param[in] ctx context value passed to callback from calling function.
237 * @param[in] selectedDevice selected device information to performing provisioning.
238 * @return OC_STACK_OK on success
240 static OCStackResult StartOwnershipTransfer(void* ctx, OCProvisionDev_t* selectedDevice);
243 * Function to finalize provisioning.
244 * This function will send default ACL and commit hash.
246 * @param[in] otmCtx Context value of ownership transfer.
247 * @return OC_STACK_OK on success
249 static OCStackResult FinalizeProvisioning(OTMContext_t* otmCtx);
252 static bool IsComplete(OTMContext_t* otmCtx)
254 for(size_t i = 0; i < otmCtx->ctxResultArraySize; i++)
256 if(OC_STACK_CONTINUE == otmCtx->ctxResultArray[i].res)
266 * Function to save the result of provisioning.
268 * @param[in,out] otmCtx Context value of ownership transfer.
269 * @param[in] res result of provisioning
271 static void SetResult(OTMContext_t* otmCtx, const OCStackResult res)
273 OC_LOG(DEBUG, TAG, "IN SetResult");
277 OC_LOG(WARNING, TAG, "OTMContext is NULL");
281 if(otmCtx->selectedDeviceInfo)
283 for(size_t i = 0; i < otmCtx->ctxResultArraySize; i++)
285 if(memcmp(otmCtx->selectedDeviceInfo->doxm->deviceID.id,
286 otmCtx->ctxResultArray[i].deviceId.id, UUID_LENGTH) == 0)
288 otmCtx->ctxResultArray[i].res = res;
289 if(OC_STACK_OK != res)
291 otmCtx->ctxHasError = true;
296 //If all request is completed, invoke the user callback.
297 if(IsComplete(otmCtx))
299 otmCtx->ctxResultCallback(otmCtx->userCtx, otmCtx->ctxResultArraySize,
300 otmCtx->ctxResultArray, otmCtx->ctxHasError);
301 OICFree(otmCtx->ctxResultArray);
306 if(OC_STACK_OK != StartOwnershipTransfer(otmCtx,
307 otmCtx->selectedDeviceInfo->next))
309 OC_LOG(ERROR, TAG, "Failed to StartOwnershipTransfer");
314 OC_LOG(DEBUG, TAG, "OUT SetResult");
319 * Function to save ownerPSK at provisioning tool end.
321 * @param[in] selectedDeviceInfo selected device information to performing provisioning.
322 * @return OC_STACK_OK on success
324 static OCStackResult SaveOwnerPSK(OCProvisionDev_t *selectedDeviceInfo)
326 OC_LOG(DEBUG, TAG, "IN SaveOwnerPSK");
328 OCStackResult res = OC_STACK_ERROR;
330 CAEndpoint_t endpoint;
331 memset(&endpoint, 0x00, sizeof(CAEndpoint_t));
332 OICStrcpy(endpoint.addr, MAX_ADDR_STR_SIZE_CA, selectedDeviceInfo->endpoint.addr);
333 endpoint.addr[MAX_ADDR_STR_SIZE_CA - 1] = '\0';
334 endpoint.port = selectedDeviceInfo->securePort;
336 OicUuid_t ptDeviceID = {.id={0}};
337 if (OC_STACK_OK != GetDoxmDeviceID(&ptDeviceID))
339 OC_LOG(ERROR, TAG, "Error while retrieving provisioning tool's device ID");
343 uint8_t ownerPSK[OWNER_PSK_LENGTH_128] = {0};
345 //Generating OwnerPSK
346 CAResult_t pskRet = CAGenerateOwnerPSK(&endpoint,
347 (uint8_t *)GetOxmString(selectedDeviceInfo->doxm->oxmSel),
348 strlen(GetOxmString(selectedDeviceInfo->doxm->oxmSel)), ptDeviceID.id,
349 sizeof(ptDeviceID.id), selectedDeviceInfo->doxm->deviceID.id,
350 sizeof(selectedDeviceInfo->doxm->deviceID.id), ownerPSK,
351 OWNER_PSK_LENGTH_128);
353 if (CA_STATUS_OK == pskRet)
355 OC_LOG(INFO, TAG,"ownerPSK dump:\n");
356 OC_LOG_BUFFER(INFO, TAG,ownerPSK, OWNER_PSK_LENGTH_128);
357 //Generating new credential for provisioning tool
361 char base64Buff[B64ENCODE_OUT_SAFESIZE(sizeof(ownerPSK)) + 1] = {};
362 B64Result b64Ret = b64Encode(ownerPSK, sizeof(ownerPSK), base64Buff, sizeof(base64Buff),
364 VERIFY_SUCCESS(TAG, B64_OK == b64Ret, ERROR);
366 OicSecCred_t *cred = GenerateCredential(&selectedDeviceInfo->doxm->deviceID,
367 SYMMETRIC_PAIR_WISE_KEY, NULL,
368 base64Buff, ownLen, &ptDeviceID);
369 VERIFY_NON_NULL(TAG, cred, ERROR);
371 res = AddCredential(cred);
372 if(res != OC_STACK_OK)
374 DeleteCredList(cred);
380 OC_LOG(ERROR, TAG, "CAGenerateOwnerPSK failed");
383 OC_LOG(DEBUG, TAG, "OUT SaveOwnerPSK");
389 * Callback handler for OwnerShipTransferModeHandler API.
391 * @param[in] ctx ctx value passed to callback from calling function.
392 * @param[in] UNUSED handle to an invocation
393 * @param[in] clientResponse Response from queries to remote servers.
394 * @return OC_STACK_DELETE_TRANSACTION to delete the transaction
395 * and OC_STACK_KEEP_TRANSACTION to keep it.
397 static OCStackApplicationResult OwnerTransferModeHandler(void *ctx, OCDoHandle UNUSED,
398 OCClientResponse *clientResponse)
400 OC_LOG(DEBUG, TAG, "IN OwnerTransferModeHandler");
402 VERIFY_NON_NULL(TAG, clientResponse, WARNING);
403 VERIFY_NON_NULL(TAG, ctx, WARNING);
405 OTMContext_t* otmCtx = (OTMContext_t*)ctx;
407 if(clientResponse->result == OC_STACK_OK)
409 OC_LOG(INFO, TAG, "OwnerTransferModeHandler : response result = OC_STACK_OK");
410 //Send request : GET /oic/sec/pstat
411 OCStackResult res = GetProvisioningStatusResource(otmCtx);
412 if(OC_STACK_OK != res)
414 OC_LOG(WARNING, TAG, "Failed to get pstat information");
415 SetResult(otmCtx, res);
420 OC_LOG_V(WARNING, TAG, "OwnerTransferModeHandler : Client response is incorrect : %d",
421 clientResponse->result);
422 SetResult(otmCtx, clientResponse->result);
425 OC_LOG(DEBUG, TAG, "OUT OwnerTransferModeHandler");
428 return OC_STACK_DELETE_TRANSACTION;
432 * Callback handler for ProvisioningStatusResouceHandler API.
434 * @param[in] ctx ctx value passed to callback from calling function.
435 * @param[in] UNUSED handle to an invocation
436 * @param[in] clientResponse Response from queries to remote servers.
437 * @return OC_STACK_DELETE_TRANSACTION to delete the transaction
438 * and OC_STACK_KEEP_TRANSACTION to keep it.
440 static OCStackApplicationResult ListMethodsHandler(void *ctx, OCDoHandle UNUSED,
441 OCClientResponse *clientResponse)
443 OC_LOG(DEBUG, TAG, "IN ListMethodsHandler");
445 VERIFY_NON_NULL(TAG, clientResponse, WARNING);
446 VERIFY_NON_NULL(TAG, ctx, WARNING);
448 OTMContext_t* otmCtx = (OTMContext_t*)ctx;
450 if (OC_STACK_OK == clientResponse->result)
452 if (NULL == clientResponse->payload)
454 OC_LOG(INFO, TAG, "Skiping Null payload");
455 SetResult(otmCtx, OC_STACK_ERROR);
456 return OC_STACK_DELETE_TRANSACTION;
459 if (PAYLOAD_TYPE_SECURITY != clientResponse->payload->type)
461 OC_LOG(INFO, TAG, "Unknown payload type");
462 SetResult(otmCtx, OC_STACK_ERROR);
463 return OC_STACK_DELETE_TRANSACTION;
466 OicSecPstat_t* pstat = JSONToPstatBin(
467 ((OCSecurityPayload*)clientResponse->payload)->securityData);
470 OC_LOG(ERROR, TAG, "Error while converting json to pstat bin");
471 SetResult(otmCtx, OC_STACK_ERROR);
472 return OC_STACK_DELETE_TRANSACTION;
474 otmCtx->selectedDeviceInfo->pstat = pstat;
476 //Select operation mode (Currently supported SINGLE_SERVICE_CLIENT_DRIVEN only)
477 OicSecDpom_t selectedOperationMode;
478 SelectOperationMode(otmCtx->selectedDeviceInfo, &selectedOperationMode);
480 //Send request : PUT /oic/sec/pstat [{"OM":"0x11", .. }]
481 OCStackResult res = PutUpdateOperationMode(otmCtx, selectedOperationMode);
482 if (OC_STACK_OK != res)
484 OC_LOG(ERROR, TAG, "Error while updating operation mode.");
485 SetResult(otmCtx, res);
490 OC_LOG_V(WARNING, TAG, "ListMethodsHandler : Client response is incorrect : %d",
491 clientResponse->result);
492 SetResult(otmCtx, clientResponse->result);
495 OC_LOG(DEBUG, TAG, "OUT ListMethodsHandler");
497 return OC_STACK_DELETE_TRANSACTION;
501 * Callback handler for OwnershipInformationHandler API.
503 * @param[in] ctx ctx value passed to callback from calling function.
504 * @param[in] UNUSED handle to an invocation
505 * @param[in] clientResponse Response from queries to remote servers.
506 * @return OC_STACK_DELETE_TRANSACTION to delete the transaction
507 * and OC_STACK_KEEP_TRANSACTION to keep it.
509 static OCStackApplicationResult OwnershipInformationHandler(void *ctx, OCDoHandle UNUSED,
510 OCClientResponse *clientResponse)
512 VERIFY_NON_NULL(TAG, clientResponse, WARNING);
513 VERIFY_NON_NULL(TAG, ctx, WARNING);
515 OC_LOG(DEBUG, TAG, "IN OwnershipInformationHandler");
517 OCStackResult res = OC_STACK_OK;
518 OTMContext_t* otmCtx = (OTMContext_t*)ctx;
519 if (OC_STACK_OK == clientResponse->result)
521 if(OIC_RANDOM_DEVICE_PIN == otmCtx->selectedDeviceInfo->doxm->oxmSel)
523 res = RemoveCredential(&otmCtx->subIdForPinOxm);
524 if(OC_STACK_RESOURCE_DELETED != res)
526 OC_LOG_V(ERROR, TAG, "Failed to remove temporal PSK : %d", res);
527 return OC_STACK_DELETE_TRANSACTION;
531 res = SaveOwnerPSK(otmCtx->selectedDeviceInfo);
532 if(OC_STACK_OK != res)
534 OC_LOG(ERROR, TAG, "OperationModeUpdate : Failed to owner PSK generation");
535 SetResult(otmCtx, res);
536 return OC_STACK_DELETE_TRANSACTION;
539 CAEndpoint_t* endpoint = (CAEndpoint_t *)&otmCtx->selectedDeviceInfo->endpoint;
540 endpoint->port = otmCtx->selectedDeviceInfo->securePort;
541 CAResult_t closeRes = CACloseDtlsSession(endpoint);
542 if(CA_STATUS_OK != closeRes)
544 OC_LOG(ERROR, TAG, "Failed to close DTLS session");
545 SetResult(otmCtx, closeRes);
546 return OC_STACK_DELETE_TRANSACTION;
549 OC_LOG(INFO, TAG, "Ownership transfer was successfully completed.");
550 OC_LOG(INFO, TAG, "Start defualt ACL & commit-hash provisioning.");
552 res = FinalizeProvisioning(otmCtx);
553 if(OC_STACK_OK != res)
555 SetResult(otmCtx, res);
560 res = clientResponse->result;
563 OC_LOG(DEBUG, TAG, "OUT OwnershipInformationHandler");
566 return OC_STACK_DELETE_TRANSACTION;
570 * Response handler for update operation mode.
572 * @param[in] ctx ctx value passed to callback from calling function.
573 * @param[in] UNUSED handle to an invocation
574 * @param[in] clientResponse Response from queries to remote servers.
575 * @return OC_STACK_DELETE_TRANSACTION to delete the transaction
576 * and OC_STACK_KEEP_TRANSACTION to keep it.
578 static OCStackApplicationResult OperationModeUpdateHandler(void *ctx, OCDoHandle UNUSED,
579 OCClientResponse *clientResponse)
581 OC_LOG(DEBUG, TAG, "IN OperationModeUpdateHandler");
583 VERIFY_NON_NULL(TAG, clientResponse, WARNING);
584 VERIFY_NON_NULL(TAG, ctx, WARNING);
586 OTMContext_t* otmCtx = (OTMContext_t*)ctx;
588 if (OC_STACK_OK == clientResponse->result)
590 OCStackResult res = OC_STACK_ERROR;
591 OicSecOxm_t selOxm = otmCtx->selectedDeviceInfo->doxm->oxmSel;
593 //Load secret for temporal secure session.
594 if(g_OTMDatas[selOxm].loadSecretCB)
596 res = g_OTMDatas[selOxm].loadSecretCB(otmCtx);
597 if(OC_STACK_OK != res)
599 OC_LOG(ERROR, TAG, "OperationModeUpdate : Failed to load secret");
600 SetResult(otmCtx, res);
601 return OC_STACK_DELETE_TRANSACTION;
605 //Try DTLS handshake to generate secure session
606 if(g_OTMDatas[selOxm].createSecureSessionCB)
608 res = g_OTMDatas[selOxm].createSecureSessionCB(otmCtx);
609 if(OC_STACK_OK != res)
611 OC_LOG(ERROR, TAG, "OperationModeUpdate : Failed to create DTLS session");
612 SetResult(otmCtx, res);
613 return OC_STACK_DELETE_TRANSACTION;
617 //Send request : PUT /oic/sec/doxm [{"Owned":"True", .. , "Owner":"PT's UUID"}]
618 res = PutOwnershipInformation(otmCtx);
619 if(OC_STACK_OK != res)
621 OC_LOG(ERROR, TAG, "OperationModeUpdate : Failed to send owner information");
622 SetResult(otmCtx, res);
627 OC_LOG(ERROR, TAG, "Error while update operation mode");
628 SetResult(otmCtx, clientResponse->result);
631 OC_LOG(DEBUG, TAG, "OUT OperationModeUpdateHandler");
634 return OC_STACK_DELETE_TRANSACTION;
638 static OCStackResult PutOwnerTransferModeToResource(OTMContext_t* otmCtx)
640 OC_LOG(DEBUG, TAG, "IN PutOwnerTransferModeToResource");
642 if(!otmCtx || !otmCtx->selectedDeviceInfo)
644 OC_LOG(ERROR, TAG, "Invalid parameters");
645 return OC_STACK_INVALID_PARAM;
648 OCProvisionDev_t* deviceInfo = otmCtx->selectedDeviceInfo;
649 OicSecOxm_t selectedOxm = deviceInfo->doxm->oxmSel;
650 char query[MAX_URI_LENGTH + MAX_QUERY_LENGTH] = {0};
652 if(!PMGenerateQuery(false,
653 deviceInfo->endpoint.addr, deviceInfo->endpoint.port,
654 deviceInfo->connType,
655 query, sizeof(query), OIC_RSRC_DOXM_URI))
657 OC_LOG(ERROR, TAG, "PutOwnerTransferModeToResource : Failed to generate query");
658 return OC_STACK_ERROR;
660 OC_LOG_V(DEBUG, TAG, "Query=%s", query);
661 OCSecurityPayload* secPayload = (OCSecurityPayload*)OICCalloc(1, sizeof(OCSecurityPayload));
664 OC_LOG(ERROR, TAG, "Failed to memory allocation");
665 return OC_STACK_NO_MEMORY;
667 secPayload->base.type = PAYLOAD_TYPE_SECURITY;
668 secPayload->securityData = g_OTMDatas[selectedOxm].createSelectOxmPayloadCB(otmCtx);
669 if (NULL == secPayload->securityData)
672 OC_LOG(ERROR, TAG, "Error while converting bin to json");
673 return OC_STACK_ERROR;
675 OC_LOG_V(DEBUG, TAG, "Payload : %s", secPayload->securityData);
677 OCCallbackData cbData;
678 cbData.cb = &OwnerTransferModeHandler;
679 cbData.context = (void *)otmCtx;
681 OCStackResult res = OCDoResource(NULL, OC_REST_PUT, query,
682 &deviceInfo->endpoint, (OCPayload*)secPayload,
683 deviceInfo->connType, OC_LOW_QOS, &cbData, NULL, 0);
684 if (res != OC_STACK_OK)
686 OC_LOG(ERROR, TAG, "OCStack resource error");
689 OC_LOG(DEBUG, TAG, "OUT PutOwnerTransferModeToResource");
694 static OCStackResult GetProvisioningStatusResource(OTMContext_t* otmCtx)
696 OC_LOG(DEBUG, TAG, "IN GetProvisioningStatusResource");
698 if(!otmCtx || !otmCtx->selectedDeviceInfo)
700 OC_LOG(ERROR, TAG, "Invailed parameters");
701 return OC_STACK_INVALID_PARAM;
704 OCProvisionDev_t* deviceInfo = otmCtx->selectedDeviceInfo;
705 char query[MAX_URI_LENGTH + MAX_QUERY_LENGTH] = {0};
706 if(!PMGenerateQuery(false,
707 deviceInfo->endpoint.addr, deviceInfo->endpoint.port,
708 deviceInfo->connType,
709 query, sizeof(query), OIC_RSRC_PSTAT_URI))
711 OC_LOG(ERROR, TAG, "GetProvisioningStatusResource : Failed to generate query");
712 return OC_STACK_ERROR;
714 OC_LOG_V(DEBUG, TAG, "Query=%s", query);
716 OCCallbackData cbData;
717 cbData.cb = &ListMethodsHandler;
718 cbData.context = (void *)otmCtx;
720 OCStackResult res = OCDoResource(NULL, OC_REST_GET, query, NULL, NULL,
721 deviceInfo->connType, OC_LOW_QOS, &cbData, NULL, 0);
722 if (res != OC_STACK_OK)
724 OC_LOG(ERROR, TAG, "OCStack resource error");
727 OC_LOG(DEBUG, TAG, "OUT GetProvisioningStatusResource");
733 static OCStackResult PutOwnershipInformation(OTMContext_t* otmCtx)
735 OC_LOG(DEBUG, TAG, "IN PutOwnershipInformation");
737 if(!otmCtx || !otmCtx->selectedDeviceInfo)
739 OC_LOG(ERROR, TAG, "Invailed parameters");
740 return OC_STACK_INVALID_PARAM;
743 OCProvisionDev_t* deviceInfo = otmCtx->selectedDeviceInfo;
744 char query[MAX_URI_LENGTH + MAX_QUERY_LENGTH] = {0};
745 if(!PMGenerateQuery(true,
746 deviceInfo->endpoint.addr, deviceInfo->securePort,
747 deviceInfo->connType,
748 query, sizeof(query), OIC_RSRC_DOXM_URI))
750 OC_LOG(ERROR, TAG, "PutOwnershipInformation : Failed to generate query");
751 return OC_STACK_ERROR;
753 OC_LOG_V(DEBUG, TAG, "Query=%s", query);
755 //OwnershipInformationHandler
756 OicSecOxm_t selOxm = deviceInfo->doxm->oxmSel;
757 OCSecurityPayload* secPayload = (OCSecurityPayload*)OICCalloc(1, sizeof(OCSecurityPayload));
760 OC_LOG(ERROR, TAG, "Failed to memory allocation");
761 return OC_STACK_NO_MEMORY;
763 secPayload->base.type = PAYLOAD_TYPE_SECURITY;
764 secPayload->securityData = g_OTMDatas[selOxm].createOwnerTransferPayloadCB(otmCtx);
765 if (NULL == secPayload->securityData)
768 OC_LOG(ERROR, TAG, "Error while converting doxm bin to json");
769 return OC_STACK_INVALID_PARAM;
772 OCCallbackData cbData;
773 cbData.cb = &OwnershipInformationHandler;
774 cbData.context = (void *)otmCtx;
776 OCStackResult res = OCDoResource(NULL, OC_REST_PUT, query, 0, (OCPayload*)secPayload,
777 deviceInfo->connType, OC_LOW_QOS, &cbData, NULL, 0);
778 if (res != OC_STACK_OK)
780 OC_LOG(ERROR, TAG, "OCStack resource error");
783 OC_LOG(DEBUG, TAG, "OUT PutOwnershipInformation");
788 static OCStackResult PutUpdateOperationMode(OTMContext_t* otmCtx,
789 OicSecDpom_t selectedOperationMode)
791 OC_LOG(DEBUG, TAG, "IN PutUpdateOperationMode");
793 if(!otmCtx || !otmCtx->selectedDeviceInfo)
795 return OC_STACK_INVALID_PARAM;
798 OCProvisionDev_t* deviceInfo = otmCtx->selectedDeviceInfo;
799 char query[MAX_URI_LENGTH + MAX_QUERY_LENGTH] = {0};
800 if(!PMGenerateQuery(false,
801 deviceInfo->endpoint.addr, deviceInfo->endpoint.port,
802 deviceInfo->connType,
803 query, sizeof(query), OIC_RSRC_PSTAT_URI))
805 OC_LOG(ERROR, TAG, "PutUpdateOperationMode : Failed to generate query");
806 return OC_STACK_ERROR;
808 OC_LOG_V(DEBUG, TAG, "Query=%s", query);
810 deviceInfo->pstat->om = selectedOperationMode;
812 OCSecurityPayload* secPayload = (OCSecurityPayload*)OICCalloc(1, sizeof(OCSecurityPayload));
815 OC_LOG(ERROR, TAG, "Failed to memory allocation");
816 return OC_STACK_NO_MEMORY;
818 secPayload->base.type = PAYLOAD_TYPE_SECURITY;
819 secPayload->securityData = BinToPstatJSON(deviceInfo->pstat);
820 if (NULL == secPayload->securityData)
823 OC_LOG(ERROR, TAG, "Error while converting pstat bin to json");
824 return OC_STACK_INVALID_PARAM;
827 OCCallbackData cbData;
828 cbData.cb = &OperationModeUpdateHandler;
829 cbData.context = (void *)otmCtx;
831 OCStackResult res = OCDoResource(NULL, OC_REST_PUT, query, 0, (OCPayload*)secPayload,
832 deviceInfo->connType, OC_LOW_QOS, &cbData, NULL, 0);
833 if (res != OC_STACK_OK)
835 OC_LOG(ERROR, TAG, "OCStack resource error");
838 OC_LOG(DEBUG, TAG, "OUT PutUpdateOperationMode");
843 static OCStackResult StartOwnershipTransfer(void* ctx, OCProvisionDev_t* selectedDevice)
845 OC_LOG(INFO, TAG, "IN StartOwnershipTransfer");
846 OTMContext_t* otmCtx = (OTMContext_t*)ctx;
847 otmCtx->selectedDeviceInfo = selectedDevice;
849 //Set to the lowest level OxM, and then find more higher level OxM.
850 OCStackResult res = SelectProvisioningMethod(selectedDevice->doxm->oxm,
851 selectedDevice->doxm->oxmLen,
852 &selectedDevice->doxm->oxmSel);
853 if(OC_STACK_OK != res)
855 OC_LOG(ERROR, TAG, "Failed to select the provisioning method");
856 SetResult(otmCtx, res);
859 OC_LOG_V(DEBUG, TAG, "Selected provisoning method = %d", selectedDevice->doxm->oxmSel);
861 //Send Req: PUT /oic/sec/doxm [{..."OxmSel" :g_OTMDatas[Index of Selected OxM].OXMString,...}]
862 res = PutOwnerTransferModeToResource(otmCtx);
863 if(OC_STACK_OK != res)
865 OC_LOG(WARNING, TAG, "Failed to select the provisioning method");
866 SetResult(otmCtx, res);
870 OC_LOG(INFO, TAG, "OUT StartOwnershipTransfer");
876 OCStackResult OTMSetOwnershipTransferCallbackData(OicSecOxm_t oxmType, OTMCallbackData_t* data)
878 OC_LOG(DEBUG, TAG, "IN OTMSetOwnerTransferCallbackData");
882 OC_LOG(ERROR, TAG, "OTMSetOwnershipTransferCallbackData : Invalid parameters");
883 return OC_STACK_INVALID_PARAM;
885 if(oxmType >= OIC_OXM_COUNT)
887 OC_LOG(INFO, TAG, "Unknow ownership transfer method");
888 return OC_STACK_INVALID_PARAM;
891 g_OTMDatas[oxmType].loadSecretCB= data->loadSecretCB;
892 g_OTMDatas[oxmType].createSecureSessionCB = data->createSecureSessionCB;
893 g_OTMDatas[oxmType].createSelectOxmPayloadCB = data->createSelectOxmPayloadCB;
894 g_OTMDatas[oxmType].createOwnerTransferPayloadCB = data->createOwnerTransferPayloadCB;
896 OC_LOG(DEBUG, TAG, "OUT OTMSetOwnerTransferCallbackData");
902 * NOTE : Unowned discovery should be done before performing OTMDoOwnershipTransfer
904 OCStackResult OTMDoOwnershipTransfer(void* ctx,
905 OCProvisionDev_t *selectedDevicelist,
906 OCProvisionResultCB resultCallback)
908 OC_LOG(DEBUG, TAG, "IN OTMDoOwnershipTransfer");
910 if (NULL == selectedDevicelist || NULL == resultCallback )
912 return OC_STACK_INVALID_PARAM;
915 OTMContext_t* otmCtx = (OTMContext_t*)OICCalloc(1,sizeof(OTMContext_t));
918 OC_LOG(ERROR, TAG, "Failed to create OTM Context");
919 return OC_STACK_NO_MEMORY;
921 otmCtx->ctxResultCallback = resultCallback;
922 otmCtx->ctxHasError = false;
923 otmCtx->userCtx = ctx;
924 OCProvisionDev_t* pCurDev = selectedDevicelist;
926 //Counting number of selected devices.
927 otmCtx->ctxResultArraySize = 0;
928 while(NULL != pCurDev)
930 otmCtx->ctxResultArraySize++;
931 pCurDev = pCurDev->next;
934 otmCtx->ctxResultArray =
935 (OCProvisionResult_t*)OICCalloc(otmCtx->ctxResultArraySize, sizeof(OCProvisionResult_t));
936 if(NULL == otmCtx->ctxResultArray)
938 OC_LOG(ERROR, TAG, "OTMDoOwnershipTransfer : Failed to memory allocation");
940 return OC_STACK_NO_MEMORY;
942 pCurDev = selectedDevicelist;
944 //Fill the device UUID for result array.
945 for(size_t devIdx = 0; devIdx < otmCtx->ctxResultArraySize; devIdx++)
947 //Checking duplication of Device ID.
948 if(true == PDMIsDuplicateDevice(&pCurDev->doxm->deviceID))
950 OC_LOG(ERROR, TAG, "OTMDoOwnershipTransfer : Device ID is duplicate");
951 OICFree(otmCtx->ctxResultArray);
953 return OC_STACK_INVALID_PARAM;
955 memcpy(otmCtx->ctxResultArray[devIdx].deviceId.id,
956 pCurDev->doxm->deviceID.id,
958 otmCtx->ctxResultArray[devIdx].res = OC_STACK_CONTINUE;
959 pCurDev = pCurDev->next;
961 StartOwnershipTransfer(otmCtx, selectedDevicelist);
963 OC_LOG(DEBUG, TAG, "OUT OTMDoOwnershipTransfer");
968 * Callback handler of SRPFinalizeProvisioning.
970 * @param[in] ctx ctx value passed to callback from calling function.
971 * @param[in] UNUSED handle to an invocation
972 * @param[in] clientResponse Response from queries to remote servers.
973 * @return OC_STACK_DELETE_TRANSACTION to delete the transaction
974 * and OC_STACK_KEEP_TRANSACTION to keep it.
976 static OCStackApplicationResult FinalizeProvisioningCB(void *ctx, OCDoHandle UNUSED,
977 OCClientResponse *clientResponse)
979 OC_LOG_V(INFO, TAG, "IN FinalizeProvisioningCB.");
981 VERIFY_NON_NULL(TAG, clientResponse, ERROR);
982 VERIFY_NON_NULL(TAG, ctx, ERROR);
984 OTMContext_t* otmCtx = (OTMContext_t*)ctx;
986 if(OC_STACK_OK == clientResponse->result)
988 OCStackResult res = PDMAddDevice(&otmCtx->selectedDeviceInfo->doxm->deviceID);
990 if (OC_STACK_OK == res)
992 OC_LOG_V(INFO, TAG, "Add device's UUID in PDM_DB");
993 SetResult(otmCtx, OC_STACK_OK);
994 return OC_STACK_DELETE_TRANSACTION;
998 OC_LOG(ERROR, TAG, "Ownership transfer is complete but adding information to DB is failed.");
1002 return OC_STACK_DELETE_TRANSACTION;
1006 * Callback handler of default ACL provisioning.
1008 * @param[in] ctx ctx value passed to callback from calling function.
1009 * @param[in] UNUSED handle to an invocation
1010 * @param[in] clientResponse Response from queries to remote servers.
1011 * @return OC_STACK_DELETE_TRANSACTION to delete the transaction
1012 * and OC_STACK_KEEP_TRANSACTION to keep it.
1014 static OCStackApplicationResult ProvisionDefaultACLCB(void *ctx, OCDoHandle UNUSED,
1015 OCClientResponse *clientResponse)
1017 OC_LOG_V(INFO, TAG, "IN ProvisionDefaultACLCB.");
1019 VERIFY_NON_NULL(TAG, clientResponse, ERROR);
1020 VERIFY_NON_NULL(TAG, ctx, ERROR);
1022 OTMContext_t* otmCtx = (OTMContext_t*) ctx;
1025 if (OC_STACK_RESOURCE_CREATED == clientResponse->result)
1027 OC_LOG_V(INFO, TAG, "Staring commit hash task.");
1028 // TODO hash currently have fixed value 0.
1029 uint16_t aclHash = 0;
1030 otmCtx->selectedDeviceInfo->pstat->commitHash = aclHash;
1031 otmCtx->selectedDeviceInfo->pstat->tm = NORMAL;
1032 OCSecurityPayload* secPayload = (OCSecurityPayload*)OICCalloc(1, sizeof(OCSecurityPayload));
1035 OC_LOG(ERROR, TAG, "Failed to memory allocation");
1036 return OC_STACK_NO_MEMORY;
1038 secPayload->base.type = PAYLOAD_TYPE_SECURITY;
1039 secPayload->securityData = BinToPstatJSON(otmCtx->selectedDeviceInfo->pstat);
1040 if (NULL == secPayload->securityData)
1042 OICFree(secPayload);
1043 SetResult(otmCtx, OC_STACK_INVALID_JSON);
1044 return OC_STACK_DELETE_TRANSACTION;
1046 OC_LOG_V(INFO, TAG, "Created payload for commit hash: %s",secPayload->securityData);
1048 char query[MAX_URI_LENGTH + MAX_QUERY_LENGTH] = {0};
1049 if(!PMGenerateQuery(true,
1050 otmCtx->selectedDeviceInfo->endpoint.addr,
1051 otmCtx->selectedDeviceInfo->securePort,
1052 otmCtx->selectedDeviceInfo->connType,
1053 query, sizeof(query), OIC_RSRC_PSTAT_URI))
1055 OC_LOG(ERROR, TAG, "ProvisionDefaultACLCB : Failed to generate query");
1056 return OC_STACK_ERROR;
1058 OC_LOG_V(DEBUG, TAG, "Query=%s", query);
1060 OCCallbackData cbData = {.context=NULL, .cb=NULL, .cd=NULL};
1061 cbData.cb = &FinalizeProvisioningCB;
1062 cbData.context = (void*)otmCtx;
1064 OCStackResult ret = OCDoResource(NULL, OC_REST_PUT, query, 0, (OCPayload*)secPayload,
1065 otmCtx->selectedDeviceInfo->connType, OC_HIGH_QOS, &cbData, NULL, 0);
1066 OC_LOG_V(INFO, TAG, "OCDoResource returned: %d",ret);
1067 if (ret != OC_STACK_OK)
1069 OC_LOG(ERROR, TAG, "OCStack resource error");
1070 SetResult(otmCtx, ret);
1075 OC_LOG_V(INFO, TAG, "Error occured in provisionDefaultACLCB :: %d\n",
1076 clientResponse->result);
1077 SetResult(otmCtx, clientResponse->result);
1080 return OC_STACK_DELETE_TRANSACTION;
1084 OCStackResult FinalizeProvisioning(OTMContext_t* otmCtx)
1086 OC_LOG(INFO, TAG, "IN FinalizeProvisioning");
1090 OC_LOG(ERROR, TAG, "OTMContext is NULL");
1091 return OC_STACK_INVALID_PARAM;
1093 if(!otmCtx->selectedDeviceInfo)
1095 OC_LOG(ERROR, TAG, "Can't find device information in OTMContext");
1097 return OC_STACK_INVALID_PARAM;
1099 // Provision Default ACL to device
1100 OicSecAcl_t defaultAcl =
1113 OicUuid_t provTooldeviceID = {.id={0}};
1114 if (OC_STACK_OK != GetDoxmDeviceID(&provTooldeviceID))
1116 OC_LOG(ERROR, TAG, "Error while retrieving provisioning tool's device ID");
1117 SetResult(otmCtx, OC_STACK_ERROR);
1118 return OC_STACK_ERROR;
1120 OC_LOG(INFO, TAG, "Retieved deviceID");
1121 memcpy(defaultAcl.subject.id, provTooldeviceID.id, sizeof(defaultAcl.subject.id));
1122 char *wildCardResource = "*";
1123 defaultAcl.resources = &wildCardResource;
1125 defaultAcl.owners = (OicUuid_t *) OICCalloc(1, UUID_LENGTH);
1126 if(!defaultAcl.owners)
1128 OC_LOG(ERROR, TAG, "Failed to memory allocation for default ACL");
1129 SetResult(otmCtx, OC_STACK_NO_MEMORY);
1130 return OC_STACK_NO_MEMORY;
1132 memcpy(defaultAcl.owners->id, provTooldeviceID.id, UUID_LENGTH);
1133 OC_LOG(INFO, TAG, "Provisioning default ACL");
1135 OCSecurityPayload* secPayload = (OCSecurityPayload*)OICCalloc(1, sizeof(OCSecurityPayload));
1138 OC_LOG(ERROR, TAG, "Failed to memory allocation");
1139 return OC_STACK_NO_MEMORY;
1141 secPayload->base.type = PAYLOAD_TYPE_SECURITY;
1142 secPayload->securityData = BinToAclJSON(&defaultAcl);
1143 OICFree(defaultAcl.owners);
1144 if(!secPayload->securityData)
1146 OICFree(secPayload);
1147 OC_LOG(INFO, TAG, "FinalizeProvisioning : Failed to BinToAclJSON");
1148 SetResult(otmCtx, OC_STACK_ERROR);
1149 return OC_STACK_ERROR;
1151 OC_LOG_V(INFO, TAG, "Provisioning default ACL : %s",secPayload->securityData);
1153 char query[MAX_URI_LENGTH + MAX_QUERY_LENGTH] = {0};
1154 if(!PMGenerateQuery(true,
1155 otmCtx->selectedDeviceInfo->endpoint.addr,
1156 otmCtx->selectedDeviceInfo->securePort,
1157 otmCtx->selectedDeviceInfo->connType,
1158 query, sizeof(query), OIC_RSRC_ACL_URI))
1160 OC_LOG(ERROR, TAG, "FinalizeProvisioning : Failed to generate query");
1161 return OC_STACK_ERROR;
1163 OC_LOG_V(DEBUG, TAG, "Query=%s", query);
1165 OC_LOG_V(INFO, TAG, "Request URI for Provisioning default ACL : %s", query);
1167 OCCallbackData cbData = {.context=NULL, .cb=NULL, .cd=NULL};
1168 cbData.cb = &ProvisionDefaultACLCB;
1169 cbData.context = (void *)otmCtx;
1171 OCStackResult ret = OCDoResource(NULL, OC_REST_POST, query,
1172 &otmCtx->selectedDeviceInfo->endpoint, (OCPayload*)secPayload,
1173 otmCtx->selectedDeviceInfo->connType, OC_HIGH_QOS, &cbData, NULL, 0);
1174 if (OC_STACK_OK != ret)
1176 SetResult(otmCtx, ret);
1180 OC_LOG(INFO, TAG, "OUT FinalizeProvisioning");