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;
92 return OXM_MODE_SWITCH;
93 case OIC_RANDOM_DEVICE_PIN:
94 return OXM_RANDOM_DEVICE_PIN;
95 case OIC_PRE_PROVISIONED_DEVICE_PIN:
96 return OXM_PRE_PROVISIONED_DEVICE_PIN;
97 case OIC_PRE_PROVISION_STRONG_CREDENTIAL:
98 return OXM_PRE_PROVISIONED_STRONG_CREDENTIAL;
105 * Function to select appropriate provisioning method.
107 * @param[in] supportedMethods Array of supported methods
108 * @param[in] numberOfMethods number of supported methods
109 * @param[out] selectedMethod Selected methods
110 * @return OC_STACK_OK on success
112 static OCStackResult SelectProvisioningMethod(const OicSecOxm_t *supportedMethods,
113 size_t numberOfMethods,
114 OicSecOxm_t *selectedMethod)
116 OC_LOG(DEBUG, TAG, "IN SelectProvisioningMethod");
118 if(numberOfMethods == 0 || !supportedMethods)
120 OC_LOG(WARNING, TAG, "Could not find a supported OxM.");
121 return OC_STACK_ERROR;
124 *selectedMethod = supportedMethods[0];
125 for(size_t i = 0; i < numberOfMethods; i++)
127 if(*selectedMethod < supportedMethods[i])
129 *selectedMethod = supportedMethods[i];
137 * Function to select operation mode.This function will return most secure common operation mode.
139 * @param[in] selectedDeviceInfo selected device information to performing provisioning.
140 * @param[out] selectedMode selected operation mode
141 * @return OC_STACK_OK on success
143 static void SelectOperationMode(const OCProvisionDev_t *selectedDeviceInfo,
144 OicSecDpom_t *selectedMode)
146 OC_LOG(DEBUG, TAG, "IN SelectOperationMode");
151 while (i < gNumOfProvisioningMethodsPT && j < selectedDeviceInfo->pstat->smLen)
153 if (gProvisioningToolCapability[i] < selectedDeviceInfo->pstat->sm[j])
157 else if (selectedDeviceInfo->pstat->sm[j] < gProvisioningToolCapability[i])
161 else /* if gProvisioningToolCapability[i] == deviceSupportedMethods[j] */
163 *selectedMode = gProvisioningToolCapability[j];
167 OC_LOG(DEBUG, TAG, "OUT SelectOperationMode");
171 * Function to update owner transfer mode
173 * @param[in] otmCtx Context value of ownership transfer.
174 * @return OC_STACK_OK on success
176 static OCStackResult PutOwnerTransferModeToResource(OTMContext_t* otmCtx);
179 * Function to send request to resource to get its pstat resource information.
181 * @param[in] otmCtx Context value of ownership transfer.
182 * @return OC_STACK_OK on success
184 static OCStackResult GetProvisioningStatusResource(OTMContext_t* otmCtx);
188 * Function to send ownerShip info. This function would update Owned as true and
189 * owner as UUID for provisioning tool
191 * @param[in] otmCtx Context value of ownership transfer.
192 * @return OC_STACK_OK on success
194 static OCStackResult PutOwnershipInformation(OTMContext_t* otmCtx);
197 * Function to update the operation mode. As per the spec. Operation mode in client driven
198 * single service provisioning it will be updated to 0x3
200 * @param[in] otmCtx Context value of ownership transfer.
201 * @param[in] selectedOperationMode selected operation mode
202 * @return OC_STACK_OK on success
204 static OCStackResult PutUpdateOperationMode(OTMContext_t* otmCtx,
205 OicSecDpom_t selectedOperationMode);
208 * Function to start ownership transfer.
209 * This function will send the first request for provisioning,
210 * The next request message is sent from the response handler for this request.
212 * @param[in] ctx context value passed to callback from calling function.
213 * @param[in] selectedDevice selected device information to performing provisioning.
214 * @return OC_STACK_OK on success
216 static OCStackResult StartOwnershipTransfer(void* ctx, OCProvisionDev_t* selectedDevice);
219 * Function to finalize provisioning.
220 * This function will send default ACL and commit hash.
222 * @param[in] otmCtx Context value of ownership transfer.
223 * @return OC_STACK_OK on success
225 static OCStackResult FinalizeProvisioning(OTMContext_t* otmCtx);
228 static bool IsComplete(OTMContext_t* otmCtx)
230 for(size_t i = 0; i < otmCtx->ctxResultArraySize; i++)
232 if(OC_STACK_CONTINUE == otmCtx->ctxResultArray[i].res)
242 * Function to save the result of provisioning.
244 * @param[in,out] otmCtx Context value of ownership transfer.
245 * @param[in] res result of provisioning
247 static void SetResult(OTMContext_t* otmCtx, const OCStackResult res)
249 OC_LOG(DEBUG, TAG, "IN SetResult");
253 OC_LOG(WARNING, TAG, "OTMContext is NULL");
257 if(otmCtx->selectedDeviceInfo)
259 for(size_t i = 0; i < otmCtx->ctxResultArraySize; i++)
261 if(memcmp(otmCtx->selectedDeviceInfo->doxm->deviceID.id,
262 otmCtx->ctxResultArray[i].deviceId.id, UUID_LENGTH) == 0)
264 otmCtx->ctxResultArray[i].res = res;
265 if(OC_STACK_OK != res)
267 otmCtx->ctxHasError = true;
272 //If all request is completed, invoke the user callback.
273 if(IsComplete(otmCtx))
275 otmCtx->ctxResultCallback(otmCtx->userCtx, otmCtx->ctxResultArraySize,
276 otmCtx->ctxResultArray, otmCtx->ctxHasError);
277 OICFree(otmCtx->ctxResultArray);
282 if(OC_STACK_OK != StartOwnershipTransfer(otmCtx,
283 otmCtx->selectedDeviceInfo->next))
285 OC_LOG(ERROR, TAG, "Failed to StartOwnershipTransfer");
290 OC_LOG(DEBUG, TAG, "OUT SetResult");
295 * Function to save ownerPSK at provisioning tool end.
297 * @param[in] selectedDeviceInfo selected device information to performing provisioning.
298 * @return OC_STACK_OK on success
300 static OCStackResult SaveOwnerPSK(OCProvisionDev_t *selectedDeviceInfo)
302 OC_LOG(DEBUG, TAG, "IN SaveOwnerPSK");
304 OCStackResult res = OC_STACK_ERROR;
306 CAEndpoint_t endpoint;
307 memset(&endpoint, 0x00, sizeof(CAEndpoint_t));
308 OICStrcpy(endpoint.addr, MAX_ADDR_STR_SIZE_CA, selectedDeviceInfo->endpoint.addr);
309 endpoint.addr[MAX_ADDR_STR_SIZE_CA - 1] = '\0';
310 endpoint.port = selectedDeviceInfo->securePort;
312 OicUuid_t ptDeviceID = {.id={0}};
313 if (OC_STACK_OK != GetDoxmDeviceID(&ptDeviceID))
315 OC_LOG(ERROR, TAG, "Error while retrieving provisioning tool's device ID");
319 uint8_t ownerPSK[OWNER_PSK_LENGTH_128] = {0};
321 //Generating OwnerPSK
322 CAResult_t pskRet = CAGenerateOwnerPSK(&endpoint,
323 (uint8_t *)GetOxmString(selectedDeviceInfo->doxm->oxmSel),
324 strlen(GetOxmString(selectedDeviceInfo->doxm->oxmSel)), ptDeviceID.id,
325 sizeof(ptDeviceID.id), selectedDeviceInfo->doxm->deviceID.id,
326 sizeof(selectedDeviceInfo->doxm->deviceID.id), ownerPSK,
327 OWNER_PSK_LENGTH_128);
329 if (CA_STATUS_OK == pskRet)
331 OC_LOG(INFO, TAG,"ownerPSK dump:\n");
332 OC_LOG_BUFFER(INFO, TAG,ownerPSK, OWNER_PSK_LENGTH_128);
333 //Generating new credential for provisioning tool
337 char base64Buff[B64ENCODE_OUT_SAFESIZE(sizeof(ownerPSK)) + 1] = {};
338 B64Result b64Ret = b64Encode(ownerPSK, sizeof(ownerPSK), base64Buff, sizeof(base64Buff),
340 VERIFY_SUCCESS(TAG, B64_OK == b64Ret, ERROR);
342 OicSecCred_t *cred = GenerateCredential(&selectedDeviceInfo->doxm->deviceID,
343 SYMMETRIC_PAIR_WISE_KEY, NULL,
344 base64Buff, ownLen, &ptDeviceID);
345 VERIFY_NON_NULL(TAG, cred, ERROR);
347 res = AddCredential(cred);
348 if(res != OC_STACK_OK)
350 DeleteCredList(cred);
356 OC_LOG(ERROR, TAG, "CAGenerateOwnerPSK failed");
359 OC_LOG(DEBUG, TAG, "OUT SaveOwnerPSK");
365 * Callback handler for OwnerShipTransferModeHandler API.
367 * @param[in] ctx ctx value passed to callback from calling function.
368 * @param[in] UNUSED handle to an invocation
369 * @param[in] clientResponse Response from queries to remote servers.
370 * @return OC_STACK_DELETE_TRANSACTION to delete the transaction
371 * and OC_STACK_KEEP_TRANSACTION to keep it.
373 static OCStackApplicationResult OwnerTransferModeHandler(void *ctx, OCDoHandle UNUSED,
374 OCClientResponse *clientResponse)
376 OC_LOG(DEBUG, TAG, "IN OwnerTransferModeHandler");
378 VERIFY_NON_NULL(TAG, clientResponse, WARNING);
379 VERIFY_NON_NULL(TAG, ctx, WARNING);
381 OTMContext_t* otmCtx = (OTMContext_t*)ctx;
383 if(clientResponse->result == OC_STACK_OK)
385 OC_LOG(INFO, TAG, "OwnerTransferModeHandler : response result = OC_STACK_OK");
386 //Send request : GET /oic/sec/pstat
387 OCStackResult res = GetProvisioningStatusResource(otmCtx);
388 if(OC_STACK_OK != res)
390 OC_LOG(WARNING, TAG, "Failed to get pstat information");
391 SetResult(otmCtx, res);
396 OC_LOG_V(WARNING, TAG, "OwnerTransferModeHandler : Client response is incorrect : %d",
397 clientResponse->result);
398 SetResult(otmCtx, clientResponse->result);
401 OC_LOG(DEBUG, TAG, "OUT OwnerTransferModeHandler");
404 return OC_STACK_DELETE_TRANSACTION;
408 * Callback handler for ProvisioningStatusResouceHandler API.
410 * @param[in] ctx ctx value passed to callback from calling function.
411 * @param[in] UNUSED handle to an invocation
412 * @param[in] clientResponse Response from queries to remote servers.
413 * @return OC_STACK_DELETE_TRANSACTION to delete the transaction
414 * and OC_STACK_KEEP_TRANSACTION to keep it.
416 static OCStackApplicationResult ListMethodsHandler(void *ctx, OCDoHandle UNUSED,
417 OCClientResponse *clientResponse)
419 OC_LOG(DEBUG, TAG, "IN ListMethodsHandler");
421 VERIFY_NON_NULL(TAG, clientResponse, WARNING);
422 VERIFY_NON_NULL(TAG, ctx, WARNING);
424 OTMContext_t* otmCtx = (OTMContext_t*)ctx;
426 if (OC_STACK_OK == clientResponse->result)
428 if (NULL == clientResponse->payload)
430 OC_LOG(INFO, TAG, "Skiping Null payload");
431 SetResult(otmCtx, OC_STACK_ERROR);
432 return OC_STACK_DELETE_TRANSACTION;
435 if (PAYLOAD_TYPE_SECURITY != clientResponse->payload->type)
437 OC_LOG(INFO, TAG, "Unknown payload type");
438 SetResult(otmCtx, OC_STACK_ERROR);
439 return OC_STACK_DELETE_TRANSACTION;
442 OicSecPstat_t* pstat = JSONToPstatBin(
443 ((OCSecurityPayload*)clientResponse->payload)->securityData);
446 OC_LOG(ERROR, TAG, "Error while converting json to pstat bin");
447 SetResult(otmCtx, OC_STACK_ERROR);
448 return OC_STACK_DELETE_TRANSACTION;
450 otmCtx->selectedDeviceInfo->pstat = pstat;
452 //Select operation mode (Currently supported SINGLE_SERVICE_CLIENT_DRIVEN only)
453 OicSecDpom_t selectedOperationMode;
454 SelectOperationMode(otmCtx->selectedDeviceInfo, &selectedOperationMode);
456 //Send request : PUT /oic/sec/pstat [{"OM":"0x11", .. }]
457 OCStackResult res = PutUpdateOperationMode(otmCtx, selectedOperationMode);
458 if (OC_STACK_OK != res)
460 OC_LOG(ERROR, TAG, "Error while updating operation mode.");
461 SetResult(otmCtx, res);
466 OC_LOG_V(WARNING, TAG, "ListMethodsHandler : Client response is incorrect : %d",
467 clientResponse->result);
468 SetResult(otmCtx, clientResponse->result);
471 OC_LOG(DEBUG, TAG, "OUT ListMethodsHandler");
473 return OC_STACK_DELETE_TRANSACTION;
477 * Callback handler for OwnershipInformationHandler API.
479 * @param[in] ctx ctx value passed to callback from calling function.
480 * @param[in] UNUSED handle to an invocation
481 * @param[in] clientResponse Response from queries to remote servers.
482 * @return OC_STACK_DELETE_TRANSACTION to delete the transaction
483 * and OC_STACK_KEEP_TRANSACTION to keep it.
485 static OCStackApplicationResult OwnershipInformationHandler(void *ctx, OCDoHandle UNUSED,
486 OCClientResponse *clientResponse)
488 VERIFY_NON_NULL(TAG, clientResponse, WARNING);
489 VERIFY_NON_NULL(TAG, ctx, WARNING);
491 OC_LOG(DEBUG, TAG, "IN OwnershipInformationHandler");
493 OCStackResult res = OC_STACK_OK;
494 OTMContext_t* otmCtx = (OTMContext_t*)ctx;
495 if (OC_STACK_OK == clientResponse->result)
497 if(OIC_RANDOM_DEVICE_PIN == otmCtx->selectedDeviceInfo->doxm->oxmSel)
499 res = RemoveCredential(&otmCtx->subIdForPinOxm);
500 if(OC_STACK_RESOURCE_DELETED != res)
502 OC_LOG_V(ERROR, TAG, "Failed to remove temporal PSK : %d", res);
503 return OC_STACK_DELETE_TRANSACTION;
507 res = SaveOwnerPSK(otmCtx->selectedDeviceInfo);
508 if(OC_STACK_OK != res)
510 OC_LOG(ERROR, TAG, "OperationModeUpdate : Failed to owner PSK generation");
511 SetResult(otmCtx, res);
512 return OC_STACK_DELETE_TRANSACTION;
515 CAEndpoint_t* endpoint = (CAEndpoint_t *)&otmCtx->selectedDeviceInfo->endpoint;
516 endpoint->port = otmCtx->selectedDeviceInfo->securePort;
517 CAResult_t caResult = CACloseDtlsSession(endpoint);
518 if(CA_STATUS_OK != caResult)
520 OC_LOG(ERROR, TAG, "Failed to close DTLS session");
521 SetResult(otmCtx, caResult);
522 return OC_STACK_DELETE_TRANSACTION;
526 * If we select NULL cipher,
527 * client will select appropriate cipher suite according to server's cipher-suite list.
529 caResult = CASelectCipherSuite(TLS_NULL_WITH_NULL_NULL);
530 if(CA_STATUS_OK != caResult)
532 OC_LOG(ERROR, TAG, "Failed to select TLS_NULL_WITH_NULL_NULL");
533 SetResult(otmCtx, caResult);
534 return OC_STACK_DELETE_TRANSACTION;
537 OC_LOG(INFO, TAG, "Ownership transfer was successfully completed.");
538 OC_LOG(INFO, TAG, "Start defualt ACL & commit-hash provisioning.");
540 res = FinalizeProvisioning(otmCtx);
541 if(OC_STACK_OK != res)
543 SetResult(otmCtx, res);
548 res = clientResponse->result;
551 OC_LOG(DEBUG, TAG, "OUT OwnershipInformationHandler");
554 return OC_STACK_DELETE_TRANSACTION;
558 * Response handler for update operation mode.
560 * @param[in] ctx ctx value passed to callback from calling function.
561 * @param[in] UNUSED handle to an invocation
562 * @param[in] clientResponse Response from queries to remote servers.
563 * @return OC_STACK_DELETE_TRANSACTION to delete the transaction
564 * and OC_STACK_KEEP_TRANSACTION to keep it.
566 static OCStackApplicationResult OperationModeUpdateHandler(void *ctx, OCDoHandle UNUSED,
567 OCClientResponse *clientResponse)
569 OC_LOG(DEBUG, TAG, "IN OperationModeUpdateHandler");
571 VERIFY_NON_NULL(TAG, clientResponse, WARNING);
572 VERIFY_NON_NULL(TAG, ctx, WARNING);
574 OTMContext_t* otmCtx = (OTMContext_t*)ctx;
576 if (OC_STACK_OK == clientResponse->result)
578 OCStackResult res = OC_STACK_ERROR;
579 OicSecOxm_t selOxm = otmCtx->selectedDeviceInfo->doxm->oxmSel;
581 //Load secret for temporal secure session.
582 if(g_OTMDatas[selOxm].loadSecretCB)
584 res = g_OTMDatas[selOxm].loadSecretCB(otmCtx);
585 if(OC_STACK_OK != res)
587 OC_LOG(ERROR, TAG, "OperationModeUpdate : Failed to load secret");
588 SetResult(otmCtx, res);
589 return OC_STACK_DELETE_TRANSACTION;
593 //Try DTLS handshake to generate secure session
594 if(g_OTMDatas[selOxm].createSecureSessionCB)
596 res = g_OTMDatas[selOxm].createSecureSessionCB(otmCtx);
597 if(OC_STACK_OK != res)
599 OC_LOG(ERROR, TAG, "OperationModeUpdate : Failed to create DTLS session");
600 SetResult(otmCtx, res);
601 return OC_STACK_DELETE_TRANSACTION;
605 //Send request : PUT /oic/sec/doxm [{"Owned":"True", .. , "Owner":"PT's UUID"}]
606 res = PutOwnershipInformation(otmCtx);
607 if(OC_STACK_OK != res)
609 OC_LOG(ERROR, TAG, "OperationModeUpdate : Failed to send owner information");
610 SetResult(otmCtx, res);
615 OC_LOG(ERROR, TAG, "Error while update operation mode");
616 SetResult(otmCtx, clientResponse->result);
619 OC_LOG(DEBUG, TAG, "OUT OperationModeUpdateHandler");
622 return OC_STACK_DELETE_TRANSACTION;
626 static OCStackResult PutOwnerTransferModeToResource(OTMContext_t* otmCtx)
628 OC_LOG(DEBUG, TAG, "IN PutOwnerTransferModeToResource");
630 if(!otmCtx || !otmCtx->selectedDeviceInfo)
632 OC_LOG(ERROR, TAG, "Invalid parameters");
633 return OC_STACK_INVALID_PARAM;
636 OCProvisionDev_t* deviceInfo = otmCtx->selectedDeviceInfo;
637 OicSecOxm_t selectedOxm = deviceInfo->doxm->oxmSel;
638 char query[MAX_URI_LENGTH + MAX_QUERY_LENGTH] = {0};
640 if(!PMGenerateQuery(false,
641 deviceInfo->endpoint.addr, deviceInfo->endpoint.port,
642 deviceInfo->connType,
643 query, sizeof(query), OIC_RSRC_DOXM_URI))
645 OC_LOG(ERROR, TAG, "PutOwnerTransferModeToResource : Failed to generate query");
646 return OC_STACK_ERROR;
648 OC_LOG_V(DEBUG, TAG, "Query=%s", query);
649 OCSecurityPayload* secPayload = (OCSecurityPayload*)OICCalloc(1, sizeof(OCSecurityPayload));
652 OC_LOG(ERROR, TAG, "Failed to memory allocation");
653 return OC_STACK_NO_MEMORY;
655 secPayload->base.type = PAYLOAD_TYPE_SECURITY;
656 secPayload->securityData = g_OTMDatas[selectedOxm].createSelectOxmPayloadCB(otmCtx);
657 if (NULL == secPayload->securityData)
660 OC_LOG(ERROR, TAG, "Error while converting bin to json");
661 return OC_STACK_ERROR;
663 OC_LOG_V(DEBUG, TAG, "Payload : %s", secPayload->securityData);
665 OCCallbackData cbData;
666 cbData.cb = &OwnerTransferModeHandler;
667 cbData.context = (void *)otmCtx;
669 OCStackResult res = OCDoResource(NULL, OC_REST_PUT, query,
670 &deviceInfo->endpoint, (OCPayload*)secPayload,
671 deviceInfo->connType, OC_LOW_QOS, &cbData, NULL, 0);
672 if (res != OC_STACK_OK)
674 OC_LOG(ERROR, TAG, "OCStack resource error");
677 OC_LOG(DEBUG, TAG, "OUT PutOwnerTransferModeToResource");
682 static OCStackResult GetProvisioningStatusResource(OTMContext_t* otmCtx)
684 OC_LOG(DEBUG, TAG, "IN GetProvisioningStatusResource");
686 if(!otmCtx || !otmCtx->selectedDeviceInfo)
688 OC_LOG(ERROR, TAG, "Invailed parameters");
689 return OC_STACK_INVALID_PARAM;
692 OCProvisionDev_t* deviceInfo = otmCtx->selectedDeviceInfo;
693 char query[MAX_URI_LENGTH + MAX_QUERY_LENGTH] = {0};
694 if(!PMGenerateQuery(false,
695 deviceInfo->endpoint.addr, deviceInfo->endpoint.port,
696 deviceInfo->connType,
697 query, sizeof(query), OIC_RSRC_PSTAT_URI))
699 OC_LOG(ERROR, TAG, "GetProvisioningStatusResource : Failed to generate query");
700 return OC_STACK_ERROR;
702 OC_LOG_V(DEBUG, TAG, "Query=%s", query);
704 OCCallbackData cbData;
705 cbData.cb = &ListMethodsHandler;
706 cbData.context = (void *)otmCtx;
708 OCStackResult res = OCDoResource(NULL, OC_REST_GET, query, NULL, NULL,
709 deviceInfo->connType, OC_LOW_QOS, &cbData, NULL, 0);
710 if (res != OC_STACK_OK)
712 OC_LOG(ERROR, TAG, "OCStack resource error");
715 OC_LOG(DEBUG, TAG, "OUT GetProvisioningStatusResource");
721 static OCStackResult PutOwnershipInformation(OTMContext_t* otmCtx)
723 OC_LOG(DEBUG, TAG, "IN PutOwnershipInformation");
725 if(!otmCtx || !otmCtx->selectedDeviceInfo)
727 OC_LOG(ERROR, TAG, "Invailed parameters");
728 return OC_STACK_INVALID_PARAM;
731 OCProvisionDev_t* deviceInfo = otmCtx->selectedDeviceInfo;
732 char query[MAX_URI_LENGTH + MAX_QUERY_LENGTH] = {0};
733 if(!PMGenerateQuery(true,
734 deviceInfo->endpoint.addr, deviceInfo->securePort,
735 deviceInfo->connType,
736 query, sizeof(query), OIC_RSRC_DOXM_URI))
738 OC_LOG(ERROR, TAG, "PutOwnershipInformation : Failed to generate query");
739 return OC_STACK_ERROR;
741 OC_LOG_V(DEBUG, TAG, "Query=%s", query);
743 //OwnershipInformationHandler
744 OicSecOxm_t selOxm = deviceInfo->doxm->oxmSel;
745 OCSecurityPayload* secPayload = (OCSecurityPayload*)OICCalloc(1, sizeof(OCSecurityPayload));
748 OC_LOG(ERROR, TAG, "Failed to memory allocation");
749 return OC_STACK_NO_MEMORY;
751 secPayload->base.type = PAYLOAD_TYPE_SECURITY;
752 secPayload->securityData = g_OTMDatas[selOxm].createOwnerTransferPayloadCB(otmCtx);
753 if (NULL == secPayload->securityData)
756 OC_LOG(ERROR, TAG, "Error while converting doxm bin to json");
757 return OC_STACK_INVALID_PARAM;
760 OCCallbackData cbData;
761 cbData.cb = &OwnershipInformationHandler;
762 cbData.context = (void *)otmCtx;
764 OCStackResult res = OCDoResource(NULL, OC_REST_PUT, query, 0, (OCPayload*)secPayload,
765 deviceInfo->connType, OC_LOW_QOS, &cbData, NULL, 0);
766 if (res != OC_STACK_OK)
768 OC_LOG(ERROR, TAG, "OCStack resource error");
771 OC_LOG(DEBUG, TAG, "OUT PutOwnershipInformation");
776 static OCStackResult PutUpdateOperationMode(OTMContext_t* otmCtx,
777 OicSecDpom_t selectedOperationMode)
779 OC_LOG(DEBUG, TAG, "IN PutUpdateOperationMode");
781 if(!otmCtx || !otmCtx->selectedDeviceInfo)
783 return OC_STACK_INVALID_PARAM;
786 OCProvisionDev_t* deviceInfo = otmCtx->selectedDeviceInfo;
787 char query[MAX_URI_LENGTH + MAX_QUERY_LENGTH] = {0};
788 if(!PMGenerateQuery(false,
789 deviceInfo->endpoint.addr, deviceInfo->endpoint.port,
790 deviceInfo->connType,
791 query, sizeof(query), OIC_RSRC_PSTAT_URI))
793 OC_LOG(ERROR, TAG, "PutUpdateOperationMode : Failed to generate query");
794 return OC_STACK_ERROR;
796 OC_LOG_V(DEBUG, TAG, "Query=%s", query);
798 deviceInfo->pstat->om = selectedOperationMode;
800 OCSecurityPayload* secPayload = (OCSecurityPayload*)OICCalloc(1, sizeof(OCSecurityPayload));
803 OC_LOG(ERROR, TAG, "Failed to memory allocation");
804 return OC_STACK_NO_MEMORY;
806 secPayload->base.type = PAYLOAD_TYPE_SECURITY;
807 secPayload->securityData = BinToPstatJSON(deviceInfo->pstat);
808 if (NULL == secPayload->securityData)
811 OC_LOG(ERROR, TAG, "Error while converting pstat bin to json");
812 return OC_STACK_INVALID_PARAM;
815 OCCallbackData cbData;
816 cbData.cb = &OperationModeUpdateHandler;
817 cbData.context = (void *)otmCtx;
819 OCStackResult res = OCDoResource(NULL, OC_REST_PUT, query, 0, (OCPayload*)secPayload,
820 deviceInfo->connType, OC_LOW_QOS, &cbData, NULL, 0);
821 if (res != OC_STACK_OK)
823 OC_LOG(ERROR, TAG, "OCStack resource error");
826 OC_LOG(DEBUG, TAG, "OUT PutUpdateOperationMode");
831 static OCStackResult StartOwnershipTransfer(void* ctx, OCProvisionDev_t* selectedDevice)
833 OC_LOG(INFO, TAG, "IN StartOwnershipTransfer");
834 OTMContext_t* otmCtx = (OTMContext_t*)ctx;
835 otmCtx->selectedDeviceInfo = selectedDevice;
837 //Set to the lowest level OxM, and then find more higher level OxM.
838 OCStackResult res = SelectProvisioningMethod(selectedDevice->doxm->oxm,
839 selectedDevice->doxm->oxmLen,
840 &selectedDevice->doxm->oxmSel);
841 if(OC_STACK_OK != res)
843 OC_LOG(ERROR, TAG, "Failed to select the provisioning method");
844 SetResult(otmCtx, res);
847 OC_LOG_V(DEBUG, TAG, "Selected provisoning method = %d", selectedDevice->doxm->oxmSel);
849 //Send Req: PUT /oic/sec/doxm [{..."OxmSel" :g_OTMDatas[Index of Selected OxM].OXMString,...}]
850 res = PutOwnerTransferModeToResource(otmCtx);
851 if(OC_STACK_OK != res)
853 OC_LOG(WARNING, TAG, "Failed to select the provisioning method");
854 SetResult(otmCtx, res);
858 OC_LOG(INFO, TAG, "OUT StartOwnershipTransfer");
864 OCStackResult OTMSetOwnershipTransferCallbackData(OicSecOxm_t oxmType, OTMCallbackData_t* data)
866 OC_LOG(DEBUG, TAG, "IN OTMSetOwnerTransferCallbackData");
870 OC_LOG(ERROR, TAG, "OTMSetOwnershipTransferCallbackData : Invalid parameters");
871 return OC_STACK_INVALID_PARAM;
873 if(oxmType >= OIC_OXM_COUNT)
875 OC_LOG(INFO, TAG, "Unknow ownership transfer method");
876 return OC_STACK_INVALID_PARAM;
879 g_OTMDatas[oxmType].loadSecretCB= data->loadSecretCB;
880 g_OTMDatas[oxmType].createSecureSessionCB = data->createSecureSessionCB;
881 g_OTMDatas[oxmType].createSelectOxmPayloadCB = data->createSelectOxmPayloadCB;
882 g_OTMDatas[oxmType].createOwnerTransferPayloadCB = data->createOwnerTransferPayloadCB;
884 OC_LOG(DEBUG, TAG, "OUT OTMSetOwnerTransferCallbackData");
890 * NOTE : Unowned discovery should be done before performing OTMDoOwnershipTransfer
892 OCStackResult OTMDoOwnershipTransfer(void* ctx,
893 OCProvisionDev_t *selectedDevicelist,
894 OCProvisionResultCB resultCallback)
896 OC_LOG(DEBUG, TAG, "IN OTMDoOwnershipTransfer");
898 if (NULL == selectedDevicelist || NULL == resultCallback )
900 return OC_STACK_INVALID_PARAM;
903 OTMContext_t* otmCtx = (OTMContext_t*)OICCalloc(1,sizeof(OTMContext_t));
906 OC_LOG(ERROR, TAG, "Failed to create OTM Context");
907 return OC_STACK_NO_MEMORY;
909 otmCtx->ctxResultCallback = resultCallback;
910 otmCtx->ctxHasError = false;
911 otmCtx->userCtx = ctx;
912 OCProvisionDev_t* pCurDev = selectedDevicelist;
914 //Counting number of selected devices.
915 otmCtx->ctxResultArraySize = 0;
916 while(NULL != pCurDev)
918 otmCtx->ctxResultArraySize++;
919 pCurDev = pCurDev->next;
922 otmCtx->ctxResultArray =
923 (OCProvisionResult_t*)OICCalloc(otmCtx->ctxResultArraySize, sizeof(OCProvisionResult_t));
924 if(NULL == otmCtx->ctxResultArray)
926 OC_LOG(ERROR, TAG, "OTMDoOwnershipTransfer : Failed to memory allocation");
928 return OC_STACK_NO_MEMORY;
930 pCurDev = selectedDevicelist;
932 //Fill the device UUID for result array.
933 for(size_t devIdx = 0; devIdx < otmCtx->ctxResultArraySize; devIdx++)
935 //Checking duplication of Device ID.
936 bool isDuplicate = true;
937 OCStackResult res = PDMIsDuplicateDevice(&pCurDev->doxm->deviceID, &isDuplicate);
938 if (OC_STACK_OK != res)
940 OICFree(otmCtx->ctxResultArray);
946 OC_LOG(ERROR, TAG, "OTMDoOwnershipTransfer : Device ID is duplicated");
947 OICFree(otmCtx->ctxResultArray);
949 return OC_STACK_INVALID_PARAM;
951 memcpy(otmCtx->ctxResultArray[devIdx].deviceId.id,
952 pCurDev->doxm->deviceID.id,
954 otmCtx->ctxResultArray[devIdx].res = OC_STACK_CONTINUE;
955 pCurDev = pCurDev->next;
957 StartOwnershipTransfer(otmCtx, selectedDevicelist);
959 OC_LOG(DEBUG, TAG, "OUT OTMDoOwnershipTransfer");
964 * Callback handler of SRPFinalizeProvisioning.
966 * @param[in] ctx ctx value passed to callback from calling function.
967 * @param[in] UNUSED handle to an invocation
968 * @param[in] clientResponse Response from queries to remote servers.
969 * @return OC_STACK_DELETE_TRANSACTION to delete the transaction
970 * and OC_STACK_KEEP_TRANSACTION to keep it.
972 static OCStackApplicationResult FinalizeProvisioningCB(void *ctx, OCDoHandle UNUSED,
973 OCClientResponse *clientResponse)
975 OC_LOG_V(INFO, TAG, "IN FinalizeProvisioningCB.");
977 VERIFY_NON_NULL(TAG, clientResponse, ERROR);
978 VERIFY_NON_NULL(TAG, ctx, ERROR);
980 OTMContext_t* otmCtx = (OTMContext_t*)ctx;
982 if(OC_STACK_OK == clientResponse->result)
984 OCStackResult res = PDMAddDevice(&otmCtx->selectedDeviceInfo->doxm->deviceID);
986 if (OC_STACK_OK == res)
988 OC_LOG_V(INFO, TAG, "Add device's UUID in PDM_DB");
989 SetResult(otmCtx, OC_STACK_OK);
990 return OC_STACK_DELETE_TRANSACTION;
994 OC_LOG(ERROR, TAG, "Ownership transfer is complete but adding information to DB is failed.");
998 return OC_STACK_DELETE_TRANSACTION;
1002 * Callback handler of default ACL provisioning.
1004 * @param[in] ctx ctx value passed to callback from calling function.
1005 * @param[in] UNUSED handle to an invocation
1006 * @param[in] clientResponse Response from queries to remote servers.
1007 * @return OC_STACK_DELETE_TRANSACTION to delete the transaction
1008 * and OC_STACK_KEEP_TRANSACTION to keep it.
1010 static OCStackApplicationResult ProvisionDefaultACLCB(void *ctx, OCDoHandle UNUSED,
1011 OCClientResponse *clientResponse)
1013 OC_LOG_V(INFO, TAG, "IN ProvisionDefaultACLCB.");
1015 VERIFY_NON_NULL(TAG, clientResponse, ERROR);
1016 VERIFY_NON_NULL(TAG, ctx, ERROR);
1018 OTMContext_t* otmCtx = (OTMContext_t*) ctx;
1021 if (OC_STACK_RESOURCE_CREATED == clientResponse->result)
1023 OC_LOG_V(INFO, TAG, "Staring commit hash task.");
1024 // TODO hash currently have fixed value 0.
1025 uint16_t aclHash = 0;
1026 otmCtx->selectedDeviceInfo->pstat->commitHash = aclHash;
1027 otmCtx->selectedDeviceInfo->pstat->tm = NORMAL;
1028 OCSecurityPayload* secPayload = (OCSecurityPayload*)OICCalloc(1, sizeof(OCSecurityPayload));
1031 OC_LOG(ERROR, TAG, "Failed to memory allocation");
1032 return OC_STACK_NO_MEMORY;
1034 secPayload->base.type = PAYLOAD_TYPE_SECURITY;
1035 secPayload->securityData = BinToPstatJSON(otmCtx->selectedDeviceInfo->pstat);
1036 if (NULL == secPayload->securityData)
1038 OICFree(secPayload);
1039 SetResult(otmCtx, OC_STACK_INVALID_JSON);
1040 return OC_STACK_DELETE_TRANSACTION;
1042 OC_LOG_V(INFO, TAG, "Created payload for commit hash: %s",secPayload->securityData);
1044 char query[MAX_URI_LENGTH + MAX_QUERY_LENGTH] = {0};
1045 if(!PMGenerateQuery(true,
1046 otmCtx->selectedDeviceInfo->endpoint.addr,
1047 otmCtx->selectedDeviceInfo->securePort,
1048 otmCtx->selectedDeviceInfo->connType,
1049 query, sizeof(query), OIC_RSRC_PSTAT_URI))
1051 OC_LOG(ERROR, TAG, "ProvisionDefaultACLCB : Failed to generate query");
1052 return OC_STACK_ERROR;
1054 OC_LOG_V(DEBUG, TAG, "Query=%s", query);
1056 OCCallbackData cbData = {.context=NULL, .cb=NULL, .cd=NULL};
1057 cbData.cb = &FinalizeProvisioningCB;
1058 cbData.context = (void*)otmCtx;
1060 OCStackResult ret = OCDoResource(NULL, OC_REST_PUT, query, 0, (OCPayload*)secPayload,
1061 otmCtx->selectedDeviceInfo->connType, OC_HIGH_QOS, &cbData, NULL, 0);
1062 OC_LOG_V(INFO, TAG, "OCDoResource returned: %d",ret);
1063 if (ret != OC_STACK_OK)
1065 OC_LOG(ERROR, TAG, "OCStack resource error");
1066 SetResult(otmCtx, ret);
1071 OC_LOG_V(INFO, TAG, "Error occured in provisionDefaultACLCB :: %d\n",
1072 clientResponse->result);
1073 SetResult(otmCtx, clientResponse->result);
1076 return OC_STACK_DELETE_TRANSACTION;
1080 OCStackResult FinalizeProvisioning(OTMContext_t* otmCtx)
1082 OC_LOG(INFO, TAG, "IN FinalizeProvisioning");
1086 OC_LOG(ERROR, TAG, "OTMContext is NULL");
1087 return OC_STACK_INVALID_PARAM;
1089 if(!otmCtx->selectedDeviceInfo)
1091 OC_LOG(ERROR, TAG, "Can't find device information in OTMContext");
1093 return OC_STACK_INVALID_PARAM;
1095 // Provision Default ACL to device
1096 OicSecAcl_t defaultAcl =
1109 OicUuid_t provTooldeviceID = {.id={0}};
1110 if (OC_STACK_OK != GetDoxmDeviceID(&provTooldeviceID))
1112 OC_LOG(ERROR, TAG, "Error while retrieving provisioning tool's device ID");
1113 SetResult(otmCtx, OC_STACK_ERROR);
1114 return OC_STACK_ERROR;
1116 OC_LOG(INFO, TAG, "Retieved deviceID");
1117 memcpy(defaultAcl.subject.id, provTooldeviceID.id, sizeof(defaultAcl.subject.id));
1118 char *wildCardResource = "*";
1119 defaultAcl.resources = &wildCardResource;
1121 defaultAcl.owners = (OicUuid_t *) OICCalloc(1, UUID_LENGTH);
1122 if(!defaultAcl.owners)
1124 OC_LOG(ERROR, TAG, "Failed to memory allocation for default ACL");
1125 SetResult(otmCtx, OC_STACK_NO_MEMORY);
1126 return OC_STACK_NO_MEMORY;
1128 memcpy(defaultAcl.owners->id, provTooldeviceID.id, UUID_LENGTH);
1129 OC_LOG(INFO, TAG, "Provisioning default ACL");
1131 OCSecurityPayload* secPayload = (OCSecurityPayload*)OICCalloc(1, sizeof(OCSecurityPayload));
1134 OC_LOG(ERROR, TAG, "Failed to memory allocation");
1135 return OC_STACK_NO_MEMORY;
1137 secPayload->base.type = PAYLOAD_TYPE_SECURITY;
1138 secPayload->securityData = BinToAclJSON(&defaultAcl);
1139 OICFree(defaultAcl.owners);
1140 if(!secPayload->securityData)
1142 OICFree(secPayload);
1143 OC_LOG(INFO, TAG, "FinalizeProvisioning : Failed to BinToAclJSON");
1144 SetResult(otmCtx, OC_STACK_ERROR);
1145 return OC_STACK_ERROR;
1147 OC_LOG_V(INFO, TAG, "Provisioning default ACL : %s",secPayload->securityData);
1149 char query[MAX_URI_LENGTH + MAX_QUERY_LENGTH] = {0};
1150 if(!PMGenerateQuery(true,
1151 otmCtx->selectedDeviceInfo->endpoint.addr,
1152 otmCtx->selectedDeviceInfo->securePort,
1153 otmCtx->selectedDeviceInfo->connType,
1154 query, sizeof(query), OIC_RSRC_ACL_URI))
1156 OC_LOG(ERROR, TAG, "FinalizeProvisioning : Failed to generate query");
1157 return OC_STACK_ERROR;
1159 OC_LOG_V(DEBUG, TAG, "Query=%s", query);
1161 OC_LOG_V(INFO, TAG, "Request URI for Provisioning default ACL : %s", query);
1163 OCCallbackData cbData = {.context=NULL, .cb=NULL, .cd=NULL};
1164 cbData.cb = &ProvisionDefaultACLCB;
1165 cbData.context = (void *)otmCtx;
1167 OCStackResult ret = OCDoResource(NULL, OC_REST_POST, query,
1168 &otmCtx->selectedDeviceInfo->endpoint, (OCPayload*)secPayload,
1169 otmCtx->selectedDeviceInfo->connType, OC_HIGH_QOS, &cbData, NULL, 0);
1170 if (OC_STACK_OK != ret)
1172 SetResult(otmCtx, ret);
1176 OC_LOG(INFO, TAG, "OUT FinalizeProvisioning");