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"
48 #include "srmresourcestrings.h"
49 #include "doxmresource.h"
50 #include "pstatresource.h"
51 #include "credresource.h"
52 #include "aclresource.h"
53 #include "ownershiptransfermanager.h"
54 #include "securevirtualresourcetypes.h"
55 #include "oxmjustworks.h"
57 #include "pmutility.h"
58 #include "srmutility.h"
59 #include "provisioningdatabasemanager.h"
60 #include "oxmrandompin.h"
65 * Array to store the callbacks for each owner transfer method.
67 static OTMCallbackData_t g_OTMDatas[OIC_OXM_COUNT];
70 * Variable for storing provisioning tool's provisioning capabilities
71 * Must be in decreasing order of preference. More prefered method should
72 * have lower array index.
74 static OicSecDpom_t gProvisioningToolCapability[] = { SINGLE_SERVICE_CLIENT_DRIVEN };
77 * Number of supported provisioning methods
78 * current version supports only one.
80 static size_t gNumOfProvisioningMethodsPT = 1;
83 * Function to getting string of ownership transfer method
85 static const char* GetOxmString(OicSecOxm_t oxmType)
90 return OXM_JUST_WORKS;
91 case OIC_RANDOM_DEVICE_PIN:
92 return OXM_RANDOM_DEVICE_PIN;
93 case OIC_MANUFACTURER_CERTIFICATE:
94 return OXM_MANUFACTURER_CERTIFICATE;
101 * Function to select appropriate provisioning method.
103 * @param[in] supportedMethods Array of supported methods
104 * @param[in] numberOfMethods number of supported methods
105 * @param[out] selectedMethod Selected methods
106 * @return OC_STACK_OK on success
108 static OCStackResult SelectProvisioningMethod(const OicSecOxm_t *supportedMethods,
109 size_t numberOfMethods,
110 OicSecOxm_t *selectedMethod)
112 OC_LOG(DEBUG, TAG, "IN SelectProvisioningMethod");
114 if(numberOfMethods == 0 || !supportedMethods)
116 OC_LOG(WARNING, TAG, "Could not find a supported OxM.");
117 return OC_STACK_ERROR;
120 *selectedMethod = supportedMethods[0];
121 for(size_t i = 0; i < numberOfMethods; i++)
123 if(*selectedMethod < supportedMethods[i])
125 *selectedMethod = supportedMethods[i];
133 * Function to select operation mode.This function will return most secure common operation mode.
135 * @param[in] selectedDeviceInfo selected device information to performing provisioning.
136 * @param[out] selectedMode selected operation mode
137 * @return OC_STACK_OK on success
139 static void SelectOperationMode(const OCProvisionDev_t *selectedDeviceInfo,
140 OicSecDpom_t *selectedMode)
142 OC_LOG(DEBUG, TAG, "IN SelectOperationMode");
147 while (i < gNumOfProvisioningMethodsPT && j < selectedDeviceInfo->pstat->smLen)
149 if (gProvisioningToolCapability[i] < selectedDeviceInfo->pstat->sm[j])
153 else if (selectedDeviceInfo->pstat->sm[j] < gProvisioningToolCapability[i])
157 else /* if gProvisioningToolCapability[i] == deviceSupportedMethods[j] */
159 *selectedMode = gProvisioningToolCapability[j];
163 OC_LOG(DEBUG, TAG, "OUT SelectOperationMode");
167 * Function to update owner transfer mode
169 * @param[in] otmCtx Context value of ownership transfer.
170 * @return OC_STACK_OK on success
172 static OCStackResult PutOwnerTransferModeToResource(OTMContext_t* otmCtx);
175 * Function to send request to resource to get its pstat resource information.
177 * @param[in] otmCtx Context value of ownership transfer.
178 * @return OC_STACK_OK on success
180 static OCStackResult GetProvisioningStatusResource(OTMContext_t* otmCtx);
184 * Function to send ownerShip info. This function would update Owned as true and
185 * owner as UUID for provisioning tool
187 * @param[in] otmCtx Context value of ownership transfer.
188 * @return OC_STACK_OK on success
190 static OCStackResult PutOwnershipInformation(OTMContext_t* otmCtx);
193 * Function to update the operation mode. As per the spec. Operation mode in client driven
194 * single service provisioning it will be updated to 0x3
196 * @param[in] otmCtx Context value of ownership transfer.
197 * @param[in] selectedOperationMode selected operation mode
198 * @return OC_STACK_OK on success
200 static OCStackResult PutUpdateOperationMode(OTMContext_t* otmCtx,
201 OicSecDpom_t selectedOperationMode);
204 * Function to start ownership transfer.
205 * This function will send the first request for provisioning,
206 * The next request message is sent from the response handler for this request.
208 * @param[in] ctx context value passed to callback from calling function.
209 * @param[in] selectedDevice selected device information to performing provisioning.
210 * @return OC_STACK_OK on success
212 static OCStackResult StartOwnershipTransfer(void* ctx, OCProvisionDev_t* selectedDevice);
215 * Function to finalize provisioning.
216 * This function will send default ACL and commit hash.
218 * @param[in] otmCtx Context value of ownership transfer.
219 * @return OC_STACK_OK on success
221 static OCStackResult FinalizeProvisioning(OTMContext_t* otmCtx);
224 static bool IsComplete(OTMContext_t* otmCtx)
226 for(size_t i = 0; i < otmCtx->ctxResultArraySize; i++)
228 if(OC_STACK_CONTINUE == otmCtx->ctxResultArray[i].res)
238 * Function to save the result of provisioning.
240 * @param[in,out] otmCtx Context value of ownership transfer.
241 * @param[in] res result of provisioning
243 static void SetResult(OTMContext_t* otmCtx, const OCStackResult res)
245 OC_LOG(DEBUG, TAG, "IN SetResult");
249 OC_LOG(WARNING, TAG, "OTMContext is NULL");
253 if(otmCtx->selectedDeviceInfo)
255 for(size_t i = 0; i < otmCtx->ctxResultArraySize; i++)
257 if(memcmp(otmCtx->selectedDeviceInfo->doxm->deviceID.id,
258 otmCtx->ctxResultArray[i].deviceId.id, UUID_LENGTH) == 0)
260 otmCtx->ctxResultArray[i].res = res;
261 if(OC_STACK_OK != res)
263 otmCtx->ctxHasError = true;
268 //If all request is completed, invoke the user callback.
269 if(IsComplete(otmCtx))
271 otmCtx->ctxResultCallback(otmCtx->userCtx, otmCtx->ctxResultArraySize,
272 otmCtx->ctxResultArray, otmCtx->ctxHasError);
273 OICFree(otmCtx->ctxResultArray);
278 if(OC_STACK_OK != StartOwnershipTransfer(otmCtx,
279 otmCtx->selectedDeviceInfo->next))
281 OC_LOG(ERROR, TAG, "Failed to StartOwnershipTransfer");
286 OC_LOG(DEBUG, TAG, "OUT SetResult");
291 * Function to save ownerPSK at provisioning tool end.
293 * @param[in] selectedDeviceInfo selected device information to performing provisioning.
294 * @return OC_STACK_OK on success
296 static OCStackResult SaveOwnerPSK(OCProvisionDev_t *selectedDeviceInfo)
298 OC_LOG(DEBUG, TAG, "IN SaveOwnerPSK");
300 OCStackResult res = OC_STACK_ERROR;
302 CAEndpoint_t endpoint;
303 memset(&endpoint, 0x00, sizeof(CAEndpoint_t));
304 OICStrcpy(endpoint.addr, MAX_ADDR_STR_SIZE_CA, selectedDeviceInfo->endpoint.addr);
305 endpoint.addr[MAX_ADDR_STR_SIZE_CA - 1] = '\0';
306 endpoint.port = selectedDeviceInfo->securePort;
308 OicUuid_t ptDeviceID = {.id={0}};
309 if (OC_STACK_OK != GetDoxmDeviceID(&ptDeviceID))
311 OC_LOG(ERROR, TAG, "Error while retrieving provisioning tool's device ID");
315 uint8_t ownerPSK[OWNER_PSK_LENGTH_128] = {0};
317 //Generating OwnerPSK
318 CAResult_t pskRet = CAGenerateOwnerPSK(&endpoint,
319 (uint8_t *)GetOxmString(selectedDeviceInfo->doxm->oxmSel),
320 strlen(GetOxmString(selectedDeviceInfo->doxm->oxmSel)), ptDeviceID.id,
321 sizeof(ptDeviceID.id), selectedDeviceInfo->doxm->deviceID.id,
322 sizeof(selectedDeviceInfo->doxm->deviceID.id), ownerPSK,
323 OWNER_PSK_LENGTH_128);
325 if (CA_STATUS_OK == pskRet)
327 OC_LOG(INFO, TAG,"ownerPSK dump:\n");
328 OC_LOG_BUFFER(INFO, TAG,ownerPSK, OWNER_PSK_LENGTH_128);
329 //Generating new credential for provisioning tool
333 char base64Buff[B64ENCODE_OUT_SAFESIZE(sizeof(ownerPSK)) + 1] = {};
334 B64Result b64Ret = b64Encode(ownerPSK, sizeof(ownerPSK), base64Buff, sizeof(base64Buff),
336 VERIFY_SUCCESS(TAG, B64_OK == b64Ret, ERROR);
338 OicSecCred_t *cred = GenerateCredential(&selectedDeviceInfo->doxm->deviceID,
339 SYMMETRIC_PAIR_WISE_KEY, NULL,
340 base64Buff, ownLen, &ptDeviceID);
341 VERIFY_NON_NULL(TAG, cred, ERROR);
343 res = AddCredential(cred);
344 if(res != OC_STACK_OK)
346 DeleteCredList(cred);
352 OC_LOG(ERROR, TAG, "CAGenerateOwnerPSK failed");
355 OC_LOG(DEBUG, TAG, "OUT SaveOwnerPSK");
361 * Callback handler for OwnerShipTransferModeHandler API.
363 * @param[in] ctx ctx value passed to callback from calling function.
364 * @param[in] UNUSED handle to an invocation
365 * @param[in] clientResponse Response from queries to remote servers.
366 * @return OC_STACK_DELETE_TRANSACTION to delete the transaction
367 * and OC_STACK_KEEP_TRANSACTION to keep it.
369 static OCStackApplicationResult OwnerTransferModeHandler(void *ctx, OCDoHandle UNUSED,
370 OCClientResponse *clientResponse)
372 OC_LOG(DEBUG, TAG, "IN OwnerTransferModeHandler");
374 VERIFY_NON_NULL(TAG, clientResponse, WARNING);
375 VERIFY_NON_NULL(TAG, ctx, WARNING);
377 OTMContext_t* otmCtx = (OTMContext_t*)ctx;
379 if(clientResponse->result == OC_STACK_OK)
381 OC_LOG(INFO, TAG, "OwnerTransferModeHandler : response result = OC_STACK_OK");
382 //Send request : GET /oic/sec/pstat
383 OCStackResult res = GetProvisioningStatusResource(otmCtx);
384 if(OC_STACK_OK != res)
386 OC_LOG(WARNING, TAG, "Failed to get pstat information");
387 SetResult(otmCtx, res);
392 OC_LOG_V(WARNING, TAG, "OwnerTransferModeHandler : Client response is incorrect : %d",
393 clientResponse->result);
394 SetResult(otmCtx, clientResponse->result);
397 OC_LOG(DEBUG, TAG, "OUT OwnerTransferModeHandler");
400 return OC_STACK_DELETE_TRANSACTION;
404 * Callback handler for ProvisioningStatusResouceHandler API.
406 * @param[in] ctx ctx value passed to callback from calling function.
407 * @param[in] UNUSED handle to an invocation
408 * @param[in] clientResponse Response from queries to remote servers.
409 * @return OC_STACK_DELETE_TRANSACTION to delete the transaction
410 * and OC_STACK_KEEP_TRANSACTION to keep it.
412 static OCStackApplicationResult ListMethodsHandler(void *ctx, OCDoHandle UNUSED,
413 OCClientResponse *clientResponse)
415 OC_LOG(DEBUG, TAG, "IN ListMethodsHandler");
417 VERIFY_NON_NULL(TAG, clientResponse, WARNING);
418 VERIFY_NON_NULL(TAG, ctx, WARNING);
420 OTMContext_t* otmCtx = (OTMContext_t*)ctx;
422 if (OC_STACK_OK == clientResponse->result)
424 if (NULL == clientResponse->payload)
426 OC_LOG(INFO, TAG, "Skiping Null payload");
427 SetResult(otmCtx, OC_STACK_ERROR);
428 return OC_STACK_DELETE_TRANSACTION;
431 if (PAYLOAD_TYPE_SECURITY != clientResponse->payload->type)
433 OC_LOG(INFO, TAG, "Unknown payload type");
434 SetResult(otmCtx, OC_STACK_ERROR);
435 return OC_STACK_DELETE_TRANSACTION;
438 OicSecPstat_t* pstat = JSONToPstatBin(
439 ((OCSecurityPayload*)clientResponse->payload)->securityData);
442 OC_LOG(ERROR, TAG, "Error while converting json to pstat bin");
443 SetResult(otmCtx, OC_STACK_ERROR);
444 return OC_STACK_DELETE_TRANSACTION;
446 otmCtx->selectedDeviceInfo->pstat = pstat;
448 //Select operation mode (Currently supported SINGLE_SERVICE_CLIENT_DRIVEN only)
449 OicSecDpom_t selectedOperationMode;
450 SelectOperationMode(otmCtx->selectedDeviceInfo, &selectedOperationMode);
452 //Send request : PUT /oic/sec/pstat [{"OM":"0x11", .. }]
453 OCStackResult res = PutUpdateOperationMode(otmCtx, selectedOperationMode);
454 if (OC_STACK_OK != res)
456 OC_LOG(ERROR, TAG, "Error while updating operation mode.");
457 SetResult(otmCtx, res);
462 OC_LOG_V(WARNING, TAG, "ListMethodsHandler : Client response is incorrect : %d",
463 clientResponse->result);
464 SetResult(otmCtx, clientResponse->result);
467 OC_LOG(DEBUG, TAG, "OUT ListMethodsHandler");
469 return OC_STACK_DELETE_TRANSACTION;
473 * Callback handler for OwnershipInformationHandler API.
475 * @param[in] ctx ctx value passed to callback from calling function.
476 * @param[in] UNUSED handle to an invocation
477 * @param[in] clientResponse Response from queries to remote servers.
478 * @return OC_STACK_DELETE_TRANSACTION to delete the transaction
479 * and OC_STACK_KEEP_TRANSACTION to keep it.
481 static OCStackApplicationResult OwnershipInformationHandler(void *ctx, OCDoHandle UNUSED,
482 OCClientResponse *clientResponse)
484 VERIFY_NON_NULL(TAG, clientResponse, WARNING);
485 VERIFY_NON_NULL(TAG, ctx, WARNING);
487 OC_LOG(DEBUG, TAG, "IN OwnershipInformationHandler");
489 OCStackResult res = OC_STACK_OK;
490 OTMContext_t* otmCtx = (OTMContext_t*)ctx;
491 if (OC_STACK_OK == clientResponse->result)
493 if(OIC_RANDOM_DEVICE_PIN == otmCtx->selectedDeviceInfo->doxm->oxmSel)
495 res = RemoveCredential(&otmCtx->subIdForPinOxm);
496 if(OC_STACK_RESOURCE_DELETED != res)
498 OC_LOG_V(ERROR, TAG, "Failed to remove temporal PSK : %d", res);
499 return OC_STACK_DELETE_TRANSACTION;
503 res = SaveOwnerPSK(otmCtx->selectedDeviceInfo);
504 if(OC_STACK_OK != res)
506 OC_LOG(ERROR, TAG, "OperationModeUpdate : Failed to owner PSK generation");
507 SetResult(otmCtx, res);
508 return OC_STACK_DELETE_TRANSACTION;
511 CAEndpoint_t* endpoint = (CAEndpoint_t *)&otmCtx->selectedDeviceInfo->endpoint;
512 endpoint->port = otmCtx->selectedDeviceInfo->securePort;
513 CAResult_t caResult = CACloseDtlsSession(endpoint);
514 if(CA_STATUS_OK != caResult)
516 OC_LOG(ERROR, TAG, "Failed to close DTLS session");
517 SetResult(otmCtx, caResult);
518 return OC_STACK_DELETE_TRANSACTION;
522 * If we select NULL cipher,
523 * client will select appropriate cipher suite according to server's cipher-suite list.
525 caResult = CASelectCipherSuite(TLS_NULL_WITH_NULL_NULL);
526 if(CA_STATUS_OK != caResult)
528 OC_LOG(ERROR, TAG, "Failed to select TLS_NULL_WITH_NULL_NULL");
529 SetResult(otmCtx, caResult);
530 return OC_STACK_DELETE_TRANSACTION;
533 OC_LOG(INFO, TAG, "Ownership transfer was successfully completed.");
534 OC_LOG(INFO, TAG, "Start defualt ACL & commit-hash provisioning.");
536 res = FinalizeProvisioning(otmCtx);
537 if(OC_STACK_OK != res)
539 SetResult(otmCtx, res);
544 res = clientResponse->result;
547 OC_LOG(DEBUG, TAG, "OUT OwnershipInformationHandler");
550 return OC_STACK_DELETE_TRANSACTION;
554 * Response handler for update operation mode.
556 * @param[in] ctx ctx value passed to callback from calling function.
557 * @param[in] UNUSED handle to an invocation
558 * @param[in] clientResponse Response from queries to remote servers.
559 * @return OC_STACK_DELETE_TRANSACTION to delete the transaction
560 * and OC_STACK_KEEP_TRANSACTION to keep it.
562 static OCStackApplicationResult OperationModeUpdateHandler(void *ctx, OCDoHandle UNUSED,
563 OCClientResponse *clientResponse)
565 OC_LOG(DEBUG, TAG, "IN OperationModeUpdateHandler");
567 VERIFY_NON_NULL(TAG, clientResponse, WARNING);
568 VERIFY_NON_NULL(TAG, ctx, WARNING);
570 OTMContext_t* otmCtx = (OTMContext_t*)ctx;
572 if (OC_STACK_OK == clientResponse->result)
574 OCStackResult res = OC_STACK_ERROR;
575 OicSecOxm_t selOxm = otmCtx->selectedDeviceInfo->doxm->oxmSel;
577 //Load secret for temporal secure session.
578 if(g_OTMDatas[selOxm].loadSecretCB)
580 res = g_OTMDatas[selOxm].loadSecretCB(otmCtx);
581 if(OC_STACK_OK != res)
583 OC_LOG(ERROR, TAG, "OperationModeUpdate : Failed to load secret");
584 SetResult(otmCtx, res);
585 return OC_STACK_DELETE_TRANSACTION;
589 //Try DTLS handshake to generate secure session
590 if(g_OTMDatas[selOxm].createSecureSessionCB)
592 res = g_OTMDatas[selOxm].createSecureSessionCB(otmCtx);
593 if(OC_STACK_OK != res)
595 OC_LOG(ERROR, TAG, "OperationModeUpdate : Failed to create DTLS session");
596 SetResult(otmCtx, res);
597 return OC_STACK_DELETE_TRANSACTION;
601 //Send request : PUT /oic/sec/doxm [{"Owned":"True", .. , "Owner":"PT's UUID"}]
602 res = PutOwnershipInformation(otmCtx);
603 if(OC_STACK_OK != res)
605 OC_LOG(ERROR, TAG, "OperationModeUpdate : Failed to send owner information");
606 SetResult(otmCtx, res);
611 OC_LOG(ERROR, TAG, "Error while update operation mode");
612 SetResult(otmCtx, clientResponse->result);
615 OC_LOG(DEBUG, TAG, "OUT OperationModeUpdateHandler");
618 return OC_STACK_DELETE_TRANSACTION;
622 static OCStackResult PutOwnerTransferModeToResource(OTMContext_t* otmCtx)
624 OC_LOG(DEBUG, TAG, "IN PutOwnerTransferModeToResource");
626 if(!otmCtx || !otmCtx->selectedDeviceInfo)
628 OC_LOG(ERROR, TAG, "Invalid parameters");
629 return OC_STACK_INVALID_PARAM;
632 OCProvisionDev_t* deviceInfo = otmCtx->selectedDeviceInfo;
633 OicSecOxm_t selectedOxm = deviceInfo->doxm->oxmSel;
634 char query[MAX_URI_LENGTH + MAX_QUERY_LENGTH] = {0};
636 if(!PMGenerateQuery(false,
637 deviceInfo->endpoint.addr, deviceInfo->endpoint.port,
638 deviceInfo->connType,
639 query, sizeof(query), OIC_RSRC_DOXM_URI))
641 OC_LOG(ERROR, TAG, "PutOwnerTransferModeToResource : Failed to generate query");
642 return OC_STACK_ERROR;
644 OC_LOG_V(DEBUG, TAG, "Query=%s", query);
645 OCSecurityPayload* secPayload = (OCSecurityPayload*)OICCalloc(1, sizeof(OCSecurityPayload));
648 OC_LOG(ERROR, TAG, "Failed to memory allocation");
649 return OC_STACK_NO_MEMORY;
651 secPayload->base.type = PAYLOAD_TYPE_SECURITY;
652 secPayload->securityData = g_OTMDatas[selectedOxm].createSelectOxmPayloadCB(otmCtx);
653 if (NULL == secPayload->securityData)
656 OC_LOG(ERROR, TAG, "Error while converting bin to json");
657 return OC_STACK_ERROR;
659 OC_LOG_V(DEBUG, TAG, "Payload : %s", secPayload->securityData);
661 OCCallbackData cbData;
662 cbData.cb = &OwnerTransferModeHandler;
663 cbData.context = (void *)otmCtx;
665 OCStackResult res = OCDoResource(NULL, OC_REST_PUT, query,
666 &deviceInfo->endpoint, (OCPayload*)secPayload,
667 deviceInfo->connType, OC_LOW_QOS, &cbData, NULL, 0);
668 if (res != OC_STACK_OK)
670 OC_LOG(ERROR, TAG, "OCStack resource error");
673 OC_LOG(DEBUG, TAG, "OUT PutOwnerTransferModeToResource");
678 static OCStackResult GetProvisioningStatusResource(OTMContext_t* otmCtx)
680 OC_LOG(DEBUG, TAG, "IN GetProvisioningStatusResource");
682 if(!otmCtx || !otmCtx->selectedDeviceInfo)
684 OC_LOG(ERROR, TAG, "Invailed parameters");
685 return OC_STACK_INVALID_PARAM;
688 OCProvisionDev_t* deviceInfo = otmCtx->selectedDeviceInfo;
689 char query[MAX_URI_LENGTH + MAX_QUERY_LENGTH] = {0};
690 if(!PMGenerateQuery(false,
691 deviceInfo->endpoint.addr, deviceInfo->endpoint.port,
692 deviceInfo->connType,
693 query, sizeof(query), OIC_RSRC_PSTAT_URI))
695 OC_LOG(ERROR, TAG, "GetProvisioningStatusResource : Failed to generate query");
696 return OC_STACK_ERROR;
698 OC_LOG_V(DEBUG, TAG, "Query=%s", query);
700 OCCallbackData cbData;
701 cbData.cb = &ListMethodsHandler;
702 cbData.context = (void *)otmCtx;
704 OCStackResult res = OCDoResource(NULL, OC_REST_GET, query, NULL, NULL,
705 deviceInfo->connType, OC_LOW_QOS, &cbData, NULL, 0);
706 if (res != OC_STACK_OK)
708 OC_LOG(ERROR, TAG, "OCStack resource error");
711 OC_LOG(DEBUG, TAG, "OUT GetProvisioningStatusResource");
717 static OCStackResult PutOwnershipInformation(OTMContext_t* otmCtx)
719 OC_LOG(DEBUG, TAG, "IN PutOwnershipInformation");
721 if(!otmCtx || !otmCtx->selectedDeviceInfo)
723 OC_LOG(ERROR, TAG, "Invailed parameters");
724 return OC_STACK_INVALID_PARAM;
727 OCProvisionDev_t* deviceInfo = otmCtx->selectedDeviceInfo;
728 char query[MAX_URI_LENGTH + MAX_QUERY_LENGTH] = {0};
729 if(!PMGenerateQuery(true,
730 deviceInfo->endpoint.addr, deviceInfo->securePort,
731 deviceInfo->connType,
732 query, sizeof(query), OIC_RSRC_DOXM_URI))
734 OC_LOG(ERROR, TAG, "PutOwnershipInformation : Failed to generate query");
735 return OC_STACK_ERROR;
737 OC_LOG_V(DEBUG, TAG, "Query=%s", query);
739 //OwnershipInformationHandler
740 OicSecOxm_t selOxm = deviceInfo->doxm->oxmSel;
741 OCSecurityPayload* secPayload = (OCSecurityPayload*)OICCalloc(1, sizeof(OCSecurityPayload));
744 OC_LOG(ERROR, TAG, "Failed to memory allocation");
745 return OC_STACK_NO_MEMORY;
747 secPayload->base.type = PAYLOAD_TYPE_SECURITY;
748 secPayload->securityData = g_OTMDatas[selOxm].createOwnerTransferPayloadCB(otmCtx);
749 if (NULL == secPayload->securityData)
752 OC_LOG(ERROR, TAG, "Error while converting doxm bin to json");
753 return OC_STACK_INVALID_PARAM;
756 OCCallbackData cbData;
757 cbData.cb = &OwnershipInformationHandler;
758 cbData.context = (void *)otmCtx;
760 OCStackResult res = OCDoResource(NULL, OC_REST_PUT, query, 0, (OCPayload*)secPayload,
761 deviceInfo->connType, OC_LOW_QOS, &cbData, NULL, 0);
762 if (res != OC_STACK_OK)
764 OC_LOG(ERROR, TAG, "OCStack resource error");
767 OC_LOG(DEBUG, TAG, "OUT PutOwnershipInformation");
772 static OCStackResult PutUpdateOperationMode(OTMContext_t* otmCtx,
773 OicSecDpom_t selectedOperationMode)
775 OC_LOG(DEBUG, TAG, "IN PutUpdateOperationMode");
777 if(!otmCtx || !otmCtx->selectedDeviceInfo)
779 return OC_STACK_INVALID_PARAM;
782 OCProvisionDev_t* deviceInfo = otmCtx->selectedDeviceInfo;
783 char query[MAX_URI_LENGTH + MAX_QUERY_LENGTH] = {0};
784 if(!PMGenerateQuery(false,
785 deviceInfo->endpoint.addr, deviceInfo->endpoint.port,
786 deviceInfo->connType,
787 query, sizeof(query), OIC_RSRC_PSTAT_URI))
789 OC_LOG(ERROR, TAG, "PutUpdateOperationMode : Failed to generate query");
790 return OC_STACK_ERROR;
792 OC_LOG_V(DEBUG, TAG, "Query=%s", query);
794 deviceInfo->pstat->om = selectedOperationMode;
796 OCSecurityPayload* secPayload = (OCSecurityPayload*)OICCalloc(1, sizeof(OCSecurityPayload));
799 OC_LOG(ERROR, TAG, "Failed to memory allocation");
800 return OC_STACK_NO_MEMORY;
802 secPayload->base.type = PAYLOAD_TYPE_SECURITY;
803 secPayload->securityData = BinToPstatJSON(deviceInfo->pstat);
804 if (NULL == secPayload->securityData)
807 OC_LOG(ERROR, TAG, "Error while converting pstat bin to json");
808 return OC_STACK_INVALID_PARAM;
811 OCCallbackData cbData;
812 cbData.cb = &OperationModeUpdateHandler;
813 cbData.context = (void *)otmCtx;
815 OCStackResult res = OCDoResource(NULL, OC_REST_PUT, query, 0, (OCPayload*)secPayload,
816 deviceInfo->connType, OC_LOW_QOS, &cbData, NULL, 0);
817 if (res != OC_STACK_OK)
819 OC_LOG(ERROR, TAG, "OCStack resource error");
822 OC_LOG(DEBUG, TAG, "OUT PutUpdateOperationMode");
827 static OCStackResult StartOwnershipTransfer(void* ctx, OCProvisionDev_t* selectedDevice)
829 OC_LOG(INFO, TAG, "IN StartOwnershipTransfer");
830 OTMContext_t* otmCtx = (OTMContext_t*)ctx;
831 otmCtx->selectedDeviceInfo = selectedDevice;
833 //Set to the lowest level OxM, and then find more higher level OxM.
834 OCStackResult res = SelectProvisioningMethod(selectedDevice->doxm->oxm,
835 selectedDevice->doxm->oxmLen,
836 &selectedDevice->doxm->oxmSel);
837 if(OC_STACK_OK != res)
839 OC_LOG(ERROR, TAG, "Failed to select the provisioning method");
840 SetResult(otmCtx, res);
843 OC_LOG_V(DEBUG, TAG, "Selected provisoning method = %d", selectedDevice->doxm->oxmSel);
845 //Send Req: PUT /oic/sec/doxm [{..."OxmSel" :g_OTMDatas[Index of Selected OxM].OXMString,...}]
846 res = PutOwnerTransferModeToResource(otmCtx);
847 if(OC_STACK_OK != res)
849 OC_LOG(WARNING, TAG, "Failed to select the provisioning method");
850 SetResult(otmCtx, res);
854 OC_LOG(INFO, TAG, "OUT StartOwnershipTransfer");
860 OCStackResult OTMSetOwnershipTransferCallbackData(OicSecOxm_t oxmType, OTMCallbackData_t* data)
862 OC_LOG(DEBUG, TAG, "IN OTMSetOwnerTransferCallbackData");
866 OC_LOG(ERROR, TAG, "OTMSetOwnershipTransferCallbackData : Invalid parameters");
867 return OC_STACK_INVALID_PARAM;
869 if(oxmType >= OIC_OXM_COUNT)
871 OC_LOG(INFO, TAG, "Unknow ownership transfer method");
872 return OC_STACK_INVALID_PARAM;
875 g_OTMDatas[oxmType].loadSecretCB= data->loadSecretCB;
876 g_OTMDatas[oxmType].createSecureSessionCB = data->createSecureSessionCB;
877 g_OTMDatas[oxmType].createSelectOxmPayloadCB = data->createSelectOxmPayloadCB;
878 g_OTMDatas[oxmType].createOwnerTransferPayloadCB = data->createOwnerTransferPayloadCB;
880 OC_LOG(DEBUG, TAG, "OUT OTMSetOwnerTransferCallbackData");
886 * NOTE : Unowned discovery should be done before performing OTMDoOwnershipTransfer
888 OCStackResult OTMDoOwnershipTransfer(void* ctx,
889 OCProvisionDev_t *selectedDevicelist,
890 OCProvisionResultCB resultCallback)
892 OC_LOG(DEBUG, TAG, "IN OTMDoOwnershipTransfer");
894 if (NULL == selectedDevicelist || NULL == resultCallback )
896 return OC_STACK_INVALID_PARAM;
899 OTMContext_t* otmCtx = (OTMContext_t*)OICCalloc(1,sizeof(OTMContext_t));
902 OC_LOG(ERROR, TAG, "Failed to create OTM Context");
903 return OC_STACK_NO_MEMORY;
905 otmCtx->ctxResultCallback = resultCallback;
906 otmCtx->ctxHasError = false;
907 otmCtx->userCtx = ctx;
908 OCProvisionDev_t* pCurDev = selectedDevicelist;
910 //Counting number of selected devices.
911 otmCtx->ctxResultArraySize = 0;
912 while(NULL != pCurDev)
914 otmCtx->ctxResultArraySize++;
915 pCurDev = pCurDev->next;
918 otmCtx->ctxResultArray =
919 (OCProvisionResult_t*)OICCalloc(otmCtx->ctxResultArraySize, sizeof(OCProvisionResult_t));
920 if(NULL == otmCtx->ctxResultArray)
922 OC_LOG(ERROR, TAG, "OTMDoOwnershipTransfer : Failed to memory allocation");
924 return OC_STACK_NO_MEMORY;
926 pCurDev = selectedDevicelist;
928 //Fill the device UUID for result array.
929 for(size_t devIdx = 0; devIdx < otmCtx->ctxResultArraySize; devIdx++)
931 //Checking duplication of Device ID.
932 bool isDuplicate = true;
933 OCStackResult res = PDMIsDuplicateDevice(&pCurDev->doxm->deviceID, &isDuplicate);
934 if (OC_STACK_OK != res)
936 OICFree(otmCtx->ctxResultArray);
942 OC_LOG(ERROR, TAG, "OTMDoOwnershipTransfer : Device ID is duplicated");
943 OICFree(otmCtx->ctxResultArray);
945 return OC_STACK_INVALID_PARAM;
947 memcpy(otmCtx->ctxResultArray[devIdx].deviceId.id,
948 pCurDev->doxm->deviceID.id,
950 otmCtx->ctxResultArray[devIdx].res = OC_STACK_CONTINUE;
951 pCurDev = pCurDev->next;
953 StartOwnershipTransfer(otmCtx, selectedDevicelist);
955 OC_LOG(DEBUG, TAG, "OUT OTMDoOwnershipTransfer");
960 * Callback handler of SRPFinalizeProvisioning.
962 * @param[in] ctx ctx value passed to callback from calling function.
963 * @param[in] UNUSED handle to an invocation
964 * @param[in] clientResponse Response from queries to remote servers.
965 * @return OC_STACK_DELETE_TRANSACTION to delete the transaction
966 * and OC_STACK_KEEP_TRANSACTION to keep it.
968 static OCStackApplicationResult FinalizeProvisioningCB(void *ctx, OCDoHandle UNUSED,
969 OCClientResponse *clientResponse)
971 OC_LOG_V(INFO, TAG, "IN FinalizeProvisioningCB.");
973 VERIFY_NON_NULL(TAG, clientResponse, ERROR);
974 VERIFY_NON_NULL(TAG, ctx, ERROR);
976 OTMContext_t* otmCtx = (OTMContext_t*)ctx;
978 if(OC_STACK_OK == clientResponse->result)
980 OCStackResult res = PDMAddDevice(&otmCtx->selectedDeviceInfo->doxm->deviceID);
982 if (OC_STACK_OK == res)
984 OC_LOG_V(INFO, TAG, "Add device's UUID in PDM_DB");
985 SetResult(otmCtx, OC_STACK_OK);
986 return OC_STACK_DELETE_TRANSACTION;
990 OC_LOG(ERROR, TAG, "Ownership transfer is complete but adding information to DB is failed.");
994 return OC_STACK_DELETE_TRANSACTION;
998 * Callback handler of default ACL provisioning.
1000 * @param[in] ctx ctx value passed to callback from calling function.
1001 * @param[in] UNUSED handle to an invocation
1002 * @param[in] clientResponse Response from queries to remote servers.
1003 * @return OC_STACK_DELETE_TRANSACTION to delete the transaction
1004 * and OC_STACK_KEEP_TRANSACTION to keep it.
1006 static OCStackApplicationResult ProvisionDefaultACLCB(void *ctx, OCDoHandle UNUSED,
1007 OCClientResponse *clientResponse)
1009 OC_LOG_V(INFO, TAG, "IN ProvisionDefaultACLCB.");
1011 VERIFY_NON_NULL(TAG, clientResponse, ERROR);
1012 VERIFY_NON_NULL(TAG, ctx, ERROR);
1014 OTMContext_t* otmCtx = (OTMContext_t*) ctx;
1017 if (OC_STACK_RESOURCE_CREATED == clientResponse->result)
1019 OC_LOG_V(INFO, TAG, "Staring commit hash task.");
1020 // TODO hash currently have fixed value 0.
1021 uint16_t aclHash = 0;
1022 otmCtx->selectedDeviceInfo->pstat->commitHash = aclHash;
1023 otmCtx->selectedDeviceInfo->pstat->tm = NORMAL;
1024 OCSecurityPayload* secPayload = (OCSecurityPayload*)OICCalloc(1, sizeof(OCSecurityPayload));
1027 OC_LOG(ERROR, TAG, "Failed to memory allocation");
1028 return OC_STACK_NO_MEMORY;
1030 secPayload->base.type = PAYLOAD_TYPE_SECURITY;
1031 secPayload->securityData = BinToPstatJSON(otmCtx->selectedDeviceInfo->pstat);
1032 if (NULL == secPayload->securityData)
1034 OICFree(secPayload);
1035 SetResult(otmCtx, OC_STACK_INVALID_JSON);
1036 return OC_STACK_DELETE_TRANSACTION;
1038 OC_LOG_V(INFO, TAG, "Created payload for commit hash: %s",secPayload->securityData);
1040 char query[MAX_URI_LENGTH + MAX_QUERY_LENGTH] = {0};
1041 if(!PMGenerateQuery(true,
1042 otmCtx->selectedDeviceInfo->endpoint.addr,
1043 otmCtx->selectedDeviceInfo->securePort,
1044 otmCtx->selectedDeviceInfo->connType,
1045 query, sizeof(query), OIC_RSRC_PSTAT_URI))
1047 OC_LOG(ERROR, TAG, "ProvisionDefaultACLCB : Failed to generate query");
1048 return OC_STACK_ERROR;
1050 OC_LOG_V(DEBUG, TAG, "Query=%s", query);
1052 OCCallbackData cbData = {.context=NULL, .cb=NULL, .cd=NULL};
1053 cbData.cb = &FinalizeProvisioningCB;
1054 cbData.context = (void*)otmCtx;
1056 OCStackResult ret = OCDoResource(NULL, OC_REST_PUT, query, 0, (OCPayload*)secPayload,
1057 otmCtx->selectedDeviceInfo->connType, OC_HIGH_QOS, &cbData, NULL, 0);
1058 OC_LOG_V(INFO, TAG, "OCDoResource returned: %d",ret);
1059 if (ret != OC_STACK_OK)
1061 OC_LOG(ERROR, TAG, "OCStack resource error");
1062 SetResult(otmCtx, ret);
1067 OC_LOG_V(INFO, TAG, "Error occured in provisionDefaultACLCB :: %d\n",
1068 clientResponse->result);
1069 SetResult(otmCtx, clientResponse->result);
1072 return OC_STACK_DELETE_TRANSACTION;
1076 OCStackResult FinalizeProvisioning(OTMContext_t* otmCtx)
1078 OC_LOG(INFO, TAG, "IN FinalizeProvisioning");
1082 OC_LOG(ERROR, TAG, "OTMContext is NULL");
1083 return OC_STACK_INVALID_PARAM;
1085 if(!otmCtx->selectedDeviceInfo)
1087 OC_LOG(ERROR, TAG, "Can't find device information in OTMContext");
1089 return OC_STACK_INVALID_PARAM;
1091 // Provision Default ACL to device
1092 OicSecAcl_t defaultAcl =
1105 OicUuid_t provTooldeviceID = {.id={0}};
1106 if (OC_STACK_OK != GetDoxmDeviceID(&provTooldeviceID))
1108 OC_LOG(ERROR, TAG, "Error while retrieving provisioning tool's device ID");
1109 SetResult(otmCtx, OC_STACK_ERROR);
1110 return OC_STACK_ERROR;
1112 OC_LOG(INFO, TAG, "Retieved deviceID");
1113 memcpy(defaultAcl.subject.id, provTooldeviceID.id, sizeof(defaultAcl.subject.id));
1114 char *wildCardResource = "*";
1115 defaultAcl.resources = &wildCardResource;
1117 defaultAcl.owners = (OicUuid_t *) OICCalloc(1, UUID_LENGTH);
1118 if(!defaultAcl.owners)
1120 OC_LOG(ERROR, TAG, "Failed to memory allocation for default ACL");
1121 SetResult(otmCtx, OC_STACK_NO_MEMORY);
1122 return OC_STACK_NO_MEMORY;
1124 memcpy(defaultAcl.owners->id, provTooldeviceID.id, UUID_LENGTH);
1125 OC_LOG(INFO, TAG, "Provisioning default ACL");
1127 OCSecurityPayload* secPayload = (OCSecurityPayload*)OICCalloc(1, sizeof(OCSecurityPayload));
1130 OC_LOG(ERROR, TAG, "Failed to memory allocation");
1131 return OC_STACK_NO_MEMORY;
1133 secPayload->base.type = PAYLOAD_TYPE_SECURITY;
1134 secPayload->securityData = BinToAclJSON(&defaultAcl);
1135 OICFree(defaultAcl.owners);
1136 if(!secPayload->securityData)
1138 OICFree(secPayload);
1139 OC_LOG(INFO, TAG, "FinalizeProvisioning : Failed to BinToAclJSON");
1140 SetResult(otmCtx, OC_STACK_ERROR);
1141 return OC_STACK_ERROR;
1143 OC_LOG_V(INFO, TAG, "Provisioning default ACL : %s",secPayload->securityData);
1145 char query[MAX_URI_LENGTH + MAX_QUERY_LENGTH] = {0};
1146 if(!PMGenerateQuery(true,
1147 otmCtx->selectedDeviceInfo->endpoint.addr,
1148 otmCtx->selectedDeviceInfo->securePort,
1149 otmCtx->selectedDeviceInfo->connType,
1150 query, sizeof(query), OIC_RSRC_ACL_URI))
1152 OC_LOG(ERROR, TAG, "FinalizeProvisioning : Failed to generate query");
1153 return OC_STACK_ERROR;
1155 OC_LOG_V(DEBUG, TAG, "Query=%s", query);
1157 OC_LOG_V(INFO, TAG, "Request URI for Provisioning default ACL : %s", query);
1159 OCCallbackData cbData = {.context=NULL, .cb=NULL, .cd=NULL};
1160 cbData.cb = &ProvisionDefaultACLCB;
1161 cbData.context = (void *)otmCtx;
1163 OCStackResult ret = OCDoResource(NULL, OC_REST_POST, query,
1164 &otmCtx->selectedDeviceInfo->endpoint, (OCPayload*)secPayload,
1165 otmCtx->selectedDeviceInfo->connType, OC_HIGH_QOS, &cbData, NULL, 0);
1166 if (OC_STACK_OK != ret)
1168 SetResult(otmCtx, ret);
1172 OC_LOG(INFO, TAG, "OUT FinalizeProvisioning");