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 * Variables for pointing the OTMContext to be used in the DTLS handshake result callback.
85 static OTMContext_t* g_otmCtx = NULL;
88 * Function to getting string of ownership transfer method
90 static const char* GetOxmString(OicSecOxm_t oxmType)
95 return OXM_JUST_WORKS;
96 case OIC_RANDOM_DEVICE_PIN:
97 return OXM_RANDOM_DEVICE_PIN;
98 case OIC_MANUFACTURER_CERTIFICATE:
99 return OXM_MANUFACTURER_CERTIFICATE;
106 * Function to select appropriate provisioning method.
108 * @param[in] supportedMethods Array of supported methods
109 * @param[in] numberOfMethods number of supported methods
110 * @param[out] selectedMethod Selected methods
111 * @return OC_STACK_OK on success
113 static OCStackResult SelectProvisioningMethod(const OicSecOxm_t *supportedMethods,
114 size_t numberOfMethods,
115 OicSecOxm_t *selectedMethod)
117 OC_LOG(DEBUG, TAG, "IN SelectProvisioningMethod");
119 if(numberOfMethods == 0 || !supportedMethods)
121 OC_LOG(WARNING, TAG, "Could not find a supported OxM.");
122 return OC_STACK_ERROR;
125 *selectedMethod = supportedMethods[0];
126 for(size_t i = 0; i < numberOfMethods; i++)
128 if(*selectedMethod < supportedMethods[i])
130 *selectedMethod = supportedMethods[i];
138 * Function to select operation mode.This function will return most secure common operation mode.
140 * @param[in] selectedDeviceInfo selected device information to performing provisioning.
141 * @param[out] selectedMode selected operation mode
142 * @return OC_STACK_OK on success
144 static void SelectOperationMode(const OCProvisionDev_t *selectedDeviceInfo,
145 OicSecDpom_t *selectedMode)
147 OC_LOG(DEBUG, TAG, "IN SelectOperationMode");
152 while (i < gNumOfProvisioningMethodsPT && j < selectedDeviceInfo->pstat->smLen)
154 if (gProvisioningToolCapability[i] < selectedDeviceInfo->pstat->sm[j])
158 else if (selectedDeviceInfo->pstat->sm[j] < gProvisioningToolCapability[i])
162 else /* if gProvisioningToolCapability[i] == deviceSupportedMethods[j] */
164 *selectedMode = gProvisioningToolCapability[j];
168 OC_LOG(DEBUG, TAG, "OUT SelectOperationMode");
172 * Function to update owner transfer mode
174 * @param[in] otmCtx Context value of ownership transfer.
175 * @return OC_STACK_OK on success
177 static OCStackResult PutOwnerTransferModeToResource(OTMContext_t* otmCtx);
180 * Function to send request to resource to get its pstat resource information.
182 * @param[in] otmCtx Context value of ownership transfer.
183 * @return OC_STACK_OK on success
185 static OCStackResult GetProvisioningStatusResource(OTMContext_t* otmCtx);
189 * Function to send ownerShip info. This function would update Owned as true and
190 * owner as UUID for provisioning tool
192 * @param[in] otmCtx Context value of ownership transfer.
193 * @return OC_STACK_OK on success
195 static OCStackResult PutOwnershipInformation(OTMContext_t* otmCtx);
198 * Function to update the operation mode. As per the spec. Operation mode in client driven
199 * single service provisioning it will be updated to 0x3
201 * @param[in] otmCtx Context value of ownership transfer.
202 * @param[in] selectedOperationMode selected operation mode
203 * @return OC_STACK_OK on success
205 static OCStackResult PutUpdateOperationMode(OTMContext_t* otmCtx,
206 OicSecDpom_t selectedOperationMode);
209 * Function to start ownership transfer.
210 * This function will send the first request for provisioning,
211 * The next request message is sent from the response handler for this request.
213 * @param[in] ctx context value passed to callback from calling function.
214 * @param[in] selectedDevice selected device information to performing provisioning.
215 * @return OC_STACK_OK on success
217 static OCStackResult StartOwnershipTransfer(void* ctx, OCProvisionDev_t* selectedDevice);
220 * Function to finalize provisioning.
221 * This function will send default ACL and commit hash.
223 * @param[in] otmCtx Context value of ownership transfer.
224 * @return OC_STACK_OK on success
226 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_V(DEBUG, TAG, "IN SetResult : %d ", res);
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;
274 //If all request is completed, invoke the user callback.
275 if(IsComplete(otmCtx))
277 otmCtx->ctxResultCallback(otmCtx->userCtx, otmCtx->ctxResultArraySize,
278 otmCtx->ctxResultArray, otmCtx->ctxHasError);
279 OICFree(otmCtx->ctxResultArray);
284 if(OC_STACK_OK != StartOwnershipTransfer(otmCtx,
285 otmCtx->selectedDeviceInfo->next))
287 OC_LOG(ERROR, TAG, "Failed to StartOwnershipTransfer");
292 OC_LOG(DEBUG, TAG, "OUT SetResult");
296 * Function to handle the handshake result in OTM.
297 * This function will be invoked after DTLS handshake
298 * @param endPoint [IN] The remote endpoint.
299 * @param errorInfo [IN] Error information from the endpoint.
302 void DTLSHandshakeCB(const CAEndpoint_t *endpoint, const CAErrorInfo_t *info)
304 if(g_otmCtx && endpoint && info)
306 OC_LOG_V(INFO, TAG, "Received status from remote device(%s:%d) : %d",
307 endpoint->addr, endpoint->port, info->result);
309 //Make sure the address matches.
310 if(strncmp(g_otmCtx->selectedDeviceInfo->endpoint.addr,
312 sizeof(endpoint->addr)) == 0 &&
313 g_otmCtx->selectedDeviceInfo->securePort == endpoint->port)
317 CARegisterDTLSHandshakeCallback(NULL);
319 //In case of success, send next coaps request.
320 if(CA_STATUS_OK == info->result)
322 //Send request : PUT /oic/sec/doxm [{"Owned":"True", .. , "Owner":"PT's UUID"}]
323 res = PutOwnershipInformation(g_otmCtx);
324 if(OC_STACK_OK != res)
326 OC_LOG(ERROR, TAG, "OperationModeUpdate : Failed to send owner information");
327 SetResult(g_otmCtx, res);
330 //In case of failure, re-start the ownership transfer in case of PIN OxM
331 else if(CA_DTLS_AUTHENTICATION_FAILURE == info->result)
333 g_otmCtx->selectedDeviceInfo->doxm->owned = false;
334 g_otmCtx->attemptCnt++;
336 if(g_otmCtx->selectedDeviceInfo->doxm->oxmSel == OIC_RANDOM_DEVICE_PIN)
338 res = RemoveCredential(&g_otmCtx->subIdForPinOxm);
339 if(OC_STACK_RESOURCE_DELETED != res)
341 OC_LOG_V(ERROR, TAG, "Failed to remove temporal PSK : %d", res);
342 SetResult(g_otmCtx, res);
346 if(WRONG_PIN_MAX_ATTEMP > g_otmCtx->attemptCnt)
348 res = StartOwnershipTransfer(g_otmCtx, g_otmCtx->selectedDeviceInfo);
349 if(OC_STACK_OK != res)
351 SetResult(g_otmCtx, res);
352 OC_LOG(ERROR, TAG, "Failed to Re-StartOwnershipTransfer");
357 SetResult(g_otmCtx, OC_STACK_AUTHENTICATION_FAILURE);
362 SetResult(g_otmCtx, OC_STACK_AUTHENTICATION_FAILURE);
370 * Function to save ownerPSK at provisioning tool end.
372 * @param[in] selectedDeviceInfo selected device information to performing provisioning.
373 * @return OC_STACK_OK on success
375 static OCStackResult SaveOwnerPSK(OCProvisionDev_t *selectedDeviceInfo)
377 OC_LOG(DEBUG, TAG, "IN SaveOwnerPSK");
379 OCStackResult res = OC_STACK_ERROR;
381 CAEndpoint_t endpoint;
382 memset(&endpoint, 0x00, sizeof(CAEndpoint_t));
383 OICStrcpy(endpoint.addr, MAX_ADDR_STR_SIZE_CA, selectedDeviceInfo->endpoint.addr);
384 endpoint.addr[MAX_ADDR_STR_SIZE_CA - 1] = '\0';
385 endpoint.port = selectedDeviceInfo->securePort;
387 OicUuid_t ptDeviceID = {.id={0}};
388 if (OC_STACK_OK != GetDoxmDeviceID(&ptDeviceID))
390 OC_LOG(ERROR, TAG, "Error while retrieving provisioning tool's device ID");
394 uint8_t ownerPSK[OWNER_PSK_LENGTH_128] = {0};
396 //Generating OwnerPSK
397 CAResult_t pskRet = CAGenerateOwnerPSK(&endpoint,
398 (uint8_t *)GetOxmString(selectedDeviceInfo->doxm->oxmSel),
399 strlen(GetOxmString(selectedDeviceInfo->doxm->oxmSel)), ptDeviceID.id,
400 sizeof(ptDeviceID.id), selectedDeviceInfo->doxm->deviceID.id,
401 sizeof(selectedDeviceInfo->doxm->deviceID.id), ownerPSK,
402 OWNER_PSK_LENGTH_128);
404 if (CA_STATUS_OK == pskRet)
406 OC_LOG(INFO, TAG,"ownerPSK dump:\n");
407 OC_LOG_BUFFER(INFO, TAG,ownerPSK, OWNER_PSK_LENGTH_128);
408 //Generating new credential for provisioning tool
412 char base64Buff[B64ENCODE_OUT_SAFESIZE(sizeof(ownerPSK)) + 1] = {};
413 B64Result b64Ret = b64Encode(ownerPSK, sizeof(ownerPSK), base64Buff, sizeof(base64Buff),
415 VERIFY_SUCCESS(TAG, B64_OK == b64Ret, ERROR);
417 OicSecCred_t *cred = GenerateCredential(&selectedDeviceInfo->doxm->deviceID,
418 SYMMETRIC_PAIR_WISE_KEY, NULL,
419 base64Buff, ownLen, &ptDeviceID);
420 VERIFY_NON_NULL(TAG, cred, ERROR);
422 res = AddCredential(cred);
423 if(res != OC_STACK_OK)
425 DeleteCredList(cred);
431 OC_LOG(ERROR, TAG, "CAGenerateOwnerPSK failed");
434 OC_LOG(DEBUG, TAG, "OUT SaveOwnerPSK");
440 * Callback handler for OwnerShipTransferModeHandler API.
442 * @param[in] ctx ctx value passed to callback from calling function.
443 * @param[in] UNUSED handle to an invocation
444 * @param[in] clientResponse Response from queries to remote servers.
445 * @return OC_STACK_DELETE_TRANSACTION to delete the transaction
446 * and OC_STACK_KEEP_TRANSACTION to keep it.
448 static OCStackApplicationResult OwnerTransferModeHandler(void *ctx, OCDoHandle UNUSED,
449 OCClientResponse *clientResponse)
451 OC_LOG(DEBUG, TAG, "IN OwnerTransferModeHandler");
453 VERIFY_NON_NULL(TAG, clientResponse, WARNING);
454 VERIFY_NON_NULL(TAG, ctx, WARNING);
456 OTMContext_t* otmCtx = (OTMContext_t*)ctx;
458 if(clientResponse->result == OC_STACK_OK)
460 OC_LOG(INFO, TAG, "OwnerTransferModeHandler : response result = OC_STACK_OK");
461 //Send request : GET /oic/sec/pstat
462 OCStackResult res = GetProvisioningStatusResource(otmCtx);
463 if(OC_STACK_OK != res)
465 OC_LOG(WARNING, TAG, "Failed to get pstat information");
466 SetResult(otmCtx, res);
471 OC_LOG_V(WARNING, TAG, "OwnerTransferModeHandler : Client response is incorrect : %d",
472 clientResponse->result);
473 SetResult(otmCtx, clientResponse->result);
476 OC_LOG(DEBUG, TAG, "OUT OwnerTransferModeHandler");
479 return OC_STACK_DELETE_TRANSACTION;
483 * Callback handler for ProvisioningStatusResouceHandler API.
485 * @param[in] ctx ctx value passed to callback from calling function.
486 * @param[in] UNUSED handle to an invocation
487 * @param[in] clientResponse Response from queries to remote servers.
488 * @return OC_STACK_DELETE_TRANSACTION to delete the transaction
489 * and OC_STACK_KEEP_TRANSACTION to keep it.
491 static OCStackApplicationResult ListMethodsHandler(void *ctx, OCDoHandle UNUSED,
492 OCClientResponse *clientResponse)
494 OC_LOG(DEBUG, TAG, "IN ListMethodsHandler");
496 VERIFY_NON_NULL(TAG, clientResponse, WARNING);
497 VERIFY_NON_NULL(TAG, ctx, WARNING);
499 OTMContext_t* otmCtx = (OTMContext_t*)ctx;
501 if (OC_STACK_OK == clientResponse->result)
503 if (NULL == clientResponse->payload)
505 OC_LOG(INFO, TAG, "Skiping Null payload");
506 SetResult(otmCtx, OC_STACK_ERROR);
507 return OC_STACK_DELETE_TRANSACTION;
510 if (PAYLOAD_TYPE_SECURITY != clientResponse->payload->type)
512 OC_LOG(INFO, TAG, "Unknown payload type");
513 SetResult(otmCtx, OC_STACK_ERROR);
514 return OC_STACK_DELETE_TRANSACTION;
517 OicSecPstat_t* pstat = JSONToPstatBin(
518 ((OCSecurityPayload*)clientResponse->payload)->securityData, false);
521 OC_LOG(ERROR, TAG, "Error while converting json to pstat bin");
522 SetResult(otmCtx, OC_STACK_ERROR);
523 return OC_STACK_DELETE_TRANSACTION;
525 otmCtx->selectedDeviceInfo->pstat = pstat;
527 //Select operation mode (Currently supported SINGLE_SERVICE_CLIENT_DRIVEN only)
528 OicSecDpom_t selectedOperationMode;
529 SelectOperationMode(otmCtx->selectedDeviceInfo, &selectedOperationMode);
531 //Send request : PUT /oic/sec/pstat [{"OM":"0x11", .. }]
532 OCStackResult res = PutUpdateOperationMode(otmCtx, selectedOperationMode);
533 if (OC_STACK_OK != res)
535 OC_LOG(ERROR, TAG, "Error while updating operation mode.");
536 SetResult(otmCtx, res);
541 OC_LOG_V(WARNING, TAG, "ListMethodsHandler : Client response is incorrect : %d",
542 clientResponse->result);
543 SetResult(otmCtx, clientResponse->result);
546 OC_LOG(DEBUG, TAG, "OUT ListMethodsHandler");
548 return OC_STACK_DELETE_TRANSACTION;
552 * Callback handler for OwnershipInformationHandler API.
554 * @param[in] ctx ctx value passed to callback from calling function.
555 * @param[in] UNUSED handle to an invocation
556 * @param[in] clientResponse Response from queries to remote servers.
557 * @return OC_STACK_DELETE_TRANSACTION to delete the transaction
558 * and OC_STACK_KEEP_TRANSACTION to keep it.
560 static OCStackApplicationResult OwnershipInformationHandler(void *ctx, OCDoHandle UNUSED,
561 OCClientResponse *clientResponse)
563 VERIFY_NON_NULL(TAG, clientResponse, WARNING);
564 VERIFY_NON_NULL(TAG, ctx, WARNING);
566 OC_LOG(DEBUG, TAG, "IN OwnershipInformationHandler");
568 OCStackResult res = OC_STACK_OK;
569 OTMContext_t* otmCtx = (OTMContext_t*)ctx;
571 if(OC_STACK_OK == clientResponse->result)
573 if(otmCtx && otmCtx->selectedDeviceInfo)
575 if(OIC_RANDOM_DEVICE_PIN == otmCtx->selectedDeviceInfo->doxm->oxmSel)
577 res = RemoveCredential(&otmCtx->subIdForPinOxm);
578 if(OC_STACK_RESOURCE_DELETED != res)
580 OC_LOG_V(ERROR, TAG, "Failed to remove temporal PSK : %d", res);
581 return OC_STACK_DELETE_TRANSACTION;
585 res = SaveOwnerPSK(otmCtx->selectedDeviceInfo);
586 if(OC_STACK_OK != res)
588 OC_LOG(ERROR, TAG, "OperationModeUpdate : Failed to owner PSK generation");
589 SetResult(otmCtx, res);
590 return OC_STACK_DELETE_TRANSACTION;
593 CAEndpoint_t* endpoint = (CAEndpoint_t *)&otmCtx->selectedDeviceInfo->endpoint;
594 endpoint->port = otmCtx->selectedDeviceInfo->securePort;
595 CAResult_t caResult = CACloseDtlsSession(endpoint);
596 if(CA_STATUS_OK != caResult)
598 OC_LOG(ERROR, TAG, "Failed to close DTLS session");
599 SetResult(otmCtx, caResult);
600 return OC_STACK_DELETE_TRANSACTION;
604 * If we select NULL cipher,
605 * client will select appropriate cipher suite according to server's cipher-suite list.
607 caResult = CASelectCipherSuite(TLS_NULL_WITH_NULL_NULL);
608 if(CA_STATUS_OK != caResult)
610 OC_LOG(ERROR, TAG, "Failed to select TLS_NULL_WITH_NULL_NULL");
611 SetResult(otmCtx, caResult);
612 return OC_STACK_DELETE_TRANSACTION;
615 OC_LOG(INFO, TAG, "Ownership transfer was successfully completed.");
616 OC_LOG(INFO, TAG, "Start defualt ACL & commit-hash provisioning.");
618 res = FinalizeProvisioning(otmCtx);
619 if(OC_STACK_OK != res)
621 SetResult(otmCtx, res);
627 res = clientResponse->result;
628 OC_LOG_V(ERROR, TAG, "OwnershipInformationHandler : Unexpected result %d", res);
629 SetResult(otmCtx, res);
632 OC_LOG(DEBUG, TAG, "OUT OwnershipInformationHandler");
635 return OC_STACK_DELETE_TRANSACTION;
639 * Response handler for update operation mode.
641 * @param[in] ctx ctx value passed to callback from calling function.
642 * @param[in] UNUSED handle to an invocation
643 * @param[in] clientResponse Response from queries to remote servers.
644 * @return OC_STACK_DELETE_TRANSACTION to delete the transaction
645 * and OC_STACK_KEEP_TRANSACTION to keep it.
647 static OCStackApplicationResult OperationModeUpdateHandler(void *ctx, OCDoHandle UNUSED,
648 OCClientResponse *clientResponse)
650 OC_LOG(DEBUG, TAG, "IN OperationModeUpdateHandler");
652 VERIFY_NON_NULL(TAG, clientResponse, WARNING);
653 VERIFY_NON_NULL(TAG, ctx, WARNING);
655 OTMContext_t* otmCtx = (OTMContext_t*)ctx;
657 if (OC_STACK_OK == clientResponse->result)
659 OCStackResult res = OC_STACK_ERROR;
660 OicSecOxm_t selOxm = otmCtx->selectedDeviceInfo->doxm->oxmSel;
662 //Load secret for temporal secure session.
663 if(g_OTMDatas[selOxm].loadSecretCB)
665 res = g_OTMDatas[selOxm].loadSecretCB(otmCtx);
666 if(OC_STACK_OK != res)
668 OC_LOG(ERROR, TAG, "OperationModeUpdate : Failed to load secret");
669 SetResult(otmCtx, res);
670 return OC_STACK_DELETE_TRANSACTION;
674 //It will be used in handshake event handler
677 //Try DTLS handshake to generate secure session
678 if(g_OTMDatas[selOxm].createSecureSessionCB)
680 res = g_OTMDatas[selOxm].createSecureSessionCB(otmCtx);
681 if(OC_STACK_OK != res)
683 OC_LOG(ERROR, TAG, "OperationModeUpdate : Failed to create DTLS session");
684 SetResult(otmCtx, res);
685 return OC_STACK_DELETE_TRANSACTION;
691 OC_LOG(ERROR, TAG, "Error while update operation mode");
692 SetResult(otmCtx, clientResponse->result);
695 OC_LOG(DEBUG, TAG, "OUT OperationModeUpdateHandler");
698 return OC_STACK_DELETE_TRANSACTION;
702 static OCStackResult PutOwnerTransferModeToResource(OTMContext_t* otmCtx)
704 OC_LOG(DEBUG, TAG, "IN PutOwnerTransferModeToResource");
706 if(!otmCtx || !otmCtx->selectedDeviceInfo)
708 OC_LOG(ERROR, TAG, "Invalid parameters");
709 return OC_STACK_INVALID_PARAM;
712 OCProvisionDev_t* deviceInfo = otmCtx->selectedDeviceInfo;
713 OicSecOxm_t selectedOxm = deviceInfo->doxm->oxmSel;
714 char query[MAX_URI_LENGTH + MAX_QUERY_LENGTH] = {0};
716 if(!PMGenerateQuery(false,
717 deviceInfo->endpoint.addr, deviceInfo->endpoint.port,
718 deviceInfo->connType,
719 query, sizeof(query), OIC_RSRC_DOXM_URI))
721 OC_LOG(ERROR, TAG, "PutOwnerTransferModeToResource : Failed to generate query");
722 return OC_STACK_ERROR;
724 OC_LOG_V(DEBUG, TAG, "Query=%s", query);
725 OCSecurityPayload* secPayload = (OCSecurityPayload*)OICCalloc(1, sizeof(OCSecurityPayload));
728 OC_LOG(ERROR, TAG, "Failed to memory allocation");
729 return OC_STACK_NO_MEMORY;
731 secPayload->base.type = PAYLOAD_TYPE_SECURITY;
732 secPayload->securityData = g_OTMDatas[selectedOxm].createSelectOxmPayloadCB(otmCtx);
733 if (NULL == secPayload->securityData)
736 OC_LOG(ERROR, TAG, "Error while converting bin to json");
737 return OC_STACK_ERROR;
739 OC_LOG_V(DEBUG, TAG, "Payload : %s", secPayload->securityData);
741 OCCallbackData cbData;
742 cbData.cb = &OwnerTransferModeHandler;
743 cbData.context = (void *)otmCtx;
745 OCStackResult res = OCDoResource(NULL, OC_REST_PUT, query,
746 &deviceInfo->endpoint, (OCPayload*)secPayload,
747 deviceInfo->connType, OC_LOW_QOS, &cbData, NULL, 0);
748 if (res != OC_STACK_OK)
750 OC_LOG(ERROR, TAG, "OCStack resource error");
753 OC_LOG(DEBUG, TAG, "OUT PutOwnerTransferModeToResource");
758 static OCStackResult GetProvisioningStatusResource(OTMContext_t* otmCtx)
760 OC_LOG(DEBUG, TAG, "IN GetProvisioningStatusResource");
762 if(!otmCtx || !otmCtx->selectedDeviceInfo)
764 OC_LOG(ERROR, TAG, "Invailed parameters");
765 return OC_STACK_INVALID_PARAM;
768 OCProvisionDev_t* deviceInfo = otmCtx->selectedDeviceInfo;
769 char query[MAX_URI_LENGTH + MAX_QUERY_LENGTH] = {0};
770 if(!PMGenerateQuery(false,
771 deviceInfo->endpoint.addr, deviceInfo->endpoint.port,
772 deviceInfo->connType,
773 query, sizeof(query), OIC_RSRC_PSTAT_URI))
775 OC_LOG(ERROR, TAG, "GetProvisioningStatusResource : Failed to generate query");
776 return OC_STACK_ERROR;
778 OC_LOG_V(DEBUG, TAG, "Query=%s", query);
780 OCCallbackData cbData;
781 cbData.cb = &ListMethodsHandler;
782 cbData.context = (void *)otmCtx;
784 OCStackResult res = OCDoResource(NULL, OC_REST_GET, query, NULL, NULL,
785 deviceInfo->connType, OC_LOW_QOS, &cbData, NULL, 0);
786 if (res != OC_STACK_OK)
788 OC_LOG(ERROR, TAG, "OCStack resource error");
791 OC_LOG(DEBUG, TAG, "OUT GetProvisioningStatusResource");
797 static OCStackResult PutOwnershipInformation(OTMContext_t* otmCtx)
799 OC_LOG(DEBUG, TAG, "IN PutOwnershipInformation");
801 if(!otmCtx || !otmCtx->selectedDeviceInfo)
803 OC_LOG(ERROR, TAG, "Invailed parameters");
804 return OC_STACK_INVALID_PARAM;
807 OCProvisionDev_t* deviceInfo = otmCtx->selectedDeviceInfo;
808 char query[MAX_URI_LENGTH + MAX_QUERY_LENGTH] = {0};
809 if(!PMGenerateQuery(true,
810 deviceInfo->endpoint.addr, deviceInfo->securePort,
811 deviceInfo->connType,
812 query, sizeof(query), OIC_RSRC_DOXM_URI))
814 OC_LOG(ERROR, TAG, "PutOwnershipInformation : Failed to generate query");
815 return OC_STACK_ERROR;
817 OC_LOG_V(DEBUG, TAG, "Query=%s", query);
819 //OwnershipInformationHandler
820 OicSecOxm_t selOxm = deviceInfo->doxm->oxmSel;
821 OCSecurityPayload* secPayload = (OCSecurityPayload*)OICCalloc(1, sizeof(OCSecurityPayload));
824 OC_LOG(ERROR, TAG, "Failed to memory allocation");
825 return OC_STACK_NO_MEMORY;
827 secPayload->base.type = PAYLOAD_TYPE_SECURITY;
828 secPayload->securityData = g_OTMDatas[selOxm].createOwnerTransferPayloadCB(otmCtx);
829 if (NULL == secPayload->securityData)
832 OC_LOG(ERROR, TAG, "Error while converting doxm bin to json");
833 return OC_STACK_INVALID_PARAM;
836 OCCallbackData cbData;
837 cbData.cb = &OwnershipInformationHandler;
838 cbData.context = (void *)otmCtx;
841 OCStackResult res = OCDoResource(NULL, OC_REST_PUT, query, 0, (OCPayload*)secPayload,
842 deviceInfo->connType, OC_LOW_QOS, &cbData, NULL, 0);
843 if (res != OC_STACK_OK)
845 OC_LOG(ERROR, TAG, "OCStack resource error");
848 OC_LOG(DEBUG, TAG, "OUT PutOwnershipInformation");
853 static OCStackResult PutUpdateOperationMode(OTMContext_t* otmCtx,
854 OicSecDpom_t selectedOperationMode)
856 OC_LOG(DEBUG, TAG, "IN PutUpdateOperationMode");
858 if(!otmCtx || !otmCtx->selectedDeviceInfo)
860 return OC_STACK_INVALID_PARAM;
863 OCProvisionDev_t* deviceInfo = otmCtx->selectedDeviceInfo;
864 char query[MAX_URI_LENGTH + MAX_QUERY_LENGTH] = {0};
865 if(!PMGenerateQuery(false,
866 deviceInfo->endpoint.addr, deviceInfo->endpoint.port,
867 deviceInfo->connType,
868 query, sizeof(query), OIC_RSRC_PSTAT_URI))
870 OC_LOG(ERROR, TAG, "PutUpdateOperationMode : Failed to generate query");
871 return OC_STACK_ERROR;
873 OC_LOG_V(DEBUG, TAG, "Query=%s", query);
875 deviceInfo->pstat->om = selectedOperationMode;
877 OCSecurityPayload* secPayload = (OCSecurityPayload*)OICCalloc(1, sizeof(OCSecurityPayload));
880 OC_LOG(ERROR, TAG, "Failed to memory allocation");
881 return OC_STACK_NO_MEMORY;
883 secPayload->base.type = PAYLOAD_TYPE_SECURITY;
884 secPayload->securityData = BinToPstatJSON(deviceInfo->pstat, false);
885 if (NULL == secPayload->securityData)
888 OC_LOG(ERROR, TAG, "Error while converting pstat bin to json");
889 return OC_STACK_INVALID_PARAM;
892 OCCallbackData cbData;
893 cbData.cb = &OperationModeUpdateHandler;
894 cbData.context = (void *)otmCtx;
896 OCStackResult res = OCDoResource(NULL, OC_REST_PUT, query, 0, (OCPayload*)secPayload,
897 deviceInfo->connType, OC_LOW_QOS, &cbData, NULL, 0);
898 if (res != OC_STACK_OK)
900 OC_LOG(ERROR, TAG, "OCStack resource error");
903 OC_LOG(DEBUG, TAG, "OUT PutUpdateOperationMode");
908 static OCStackResult StartOwnershipTransfer(void* ctx, OCProvisionDev_t* selectedDevice)
910 OC_LOG(INFO, TAG, "IN StartOwnershipTransfer");
911 OTMContext_t* otmCtx = (OTMContext_t*)ctx;
912 otmCtx->selectedDeviceInfo = selectedDevice;
914 //Set to the lowest level OxM, and then find more higher level OxM.
915 OCStackResult res = SelectProvisioningMethod(selectedDevice->doxm->oxm,
916 selectedDevice->doxm->oxmLen,
917 &selectedDevice->doxm->oxmSel);
918 if(OC_STACK_OK != res)
920 OC_LOG(ERROR, TAG, "Failed to select the provisioning method");
921 SetResult(otmCtx, res);
924 OC_LOG_V(DEBUG, TAG, "Selected provisoning method = %d", selectedDevice->doxm->oxmSel);
926 //Send Req: PUT /oic/sec/doxm [{..."OxmSel" :g_OTMDatas[Index of Selected OxM].OXMString,...}]
927 res = PutOwnerTransferModeToResource(otmCtx);
928 if(OC_STACK_OK != res)
930 OC_LOG(WARNING, TAG, "Failed to select the provisioning method");
931 SetResult(otmCtx, res);
935 //Register DTLS event handler to catch the dtls event while handshake
936 if(CA_STATUS_OK != CARegisterDTLSHandshakeCallback(DTLSHandshakeCB))
938 OC_LOG(WARNING, TAG, "StartOwnershipTransfer : Failed to register DTLS handshake callback.");
941 OC_LOG(INFO, TAG, "OUT StartOwnershipTransfer");
947 OCStackResult OTMSetOwnershipTransferCallbackData(OicSecOxm_t oxmType, OTMCallbackData_t* data)
949 OC_LOG(DEBUG, TAG, "IN OTMSetOwnerTransferCallbackData");
953 OC_LOG(ERROR, TAG, "OTMSetOwnershipTransferCallbackData : Invalid parameters");
954 return OC_STACK_INVALID_PARAM;
956 if(oxmType >= OIC_OXM_COUNT)
958 OC_LOG(INFO, TAG, "Unknow ownership transfer method");
959 return OC_STACK_INVALID_PARAM;
962 g_OTMDatas[oxmType].loadSecretCB= data->loadSecretCB;
963 g_OTMDatas[oxmType].createSecureSessionCB = data->createSecureSessionCB;
964 g_OTMDatas[oxmType].createSelectOxmPayloadCB = data->createSelectOxmPayloadCB;
965 g_OTMDatas[oxmType].createOwnerTransferPayloadCB = data->createOwnerTransferPayloadCB;
967 OC_LOG(DEBUG, TAG, "OUT OTMSetOwnerTransferCallbackData");
973 * NOTE : Unowned discovery should be done before performing OTMDoOwnershipTransfer
975 OCStackResult OTMDoOwnershipTransfer(void* ctx,
976 OCProvisionDev_t *selectedDevicelist,
977 OCProvisionResultCB resultCallback)
979 OC_LOG(DEBUG, TAG, "IN OTMDoOwnershipTransfer");
981 if (NULL == selectedDevicelist || NULL == resultCallback )
983 return OC_STACK_INVALID_PARAM;
986 OTMContext_t* otmCtx = (OTMContext_t*)OICCalloc(1,sizeof(OTMContext_t));
989 OC_LOG(ERROR, TAG, "Failed to create OTM Context");
990 return OC_STACK_NO_MEMORY;
992 otmCtx->ctxResultCallback = resultCallback;
993 otmCtx->ctxHasError = false;
994 otmCtx->userCtx = ctx;
995 OCProvisionDev_t* pCurDev = selectedDevicelist;
997 //Counting number of selected devices.
998 otmCtx->ctxResultArraySize = 0;
999 while(NULL != pCurDev)
1001 otmCtx->ctxResultArraySize++;
1002 pCurDev = pCurDev->next;
1005 otmCtx->ctxResultArray =
1006 (OCProvisionResult_t*)OICCalloc(otmCtx->ctxResultArraySize, sizeof(OCProvisionResult_t));
1007 if(NULL == otmCtx->ctxResultArray)
1009 OC_LOG(ERROR, TAG, "OTMDoOwnershipTransfer : Failed to memory allocation");
1011 return OC_STACK_NO_MEMORY;
1013 pCurDev = selectedDevicelist;
1015 OCStackResult res = OC_STACK_OK;
1016 //Fill the device UUID for result array.
1017 for(size_t devIdx = 0; devIdx < otmCtx->ctxResultArraySize; devIdx++)
1019 //Checking duplication of Device ID.
1020 bool isDuplicate = true;
1021 res = PDMIsDuplicateDevice(&pCurDev->doxm->deviceID, &isDuplicate);
1022 if (OC_STACK_OK != res)
1028 OC_LOG(ERROR, TAG, "OTMDoOwnershipTransfer : Device ID is duplicated");
1029 res = OC_STACK_INVALID_PARAM;
1032 memcpy(otmCtx->ctxResultArray[devIdx].deviceId.id,
1033 pCurDev->doxm->deviceID.id,
1035 otmCtx->ctxResultArray[devIdx].res = OC_STACK_CONTINUE;
1036 pCurDev = pCurDev->next;
1039 StartOwnershipTransfer(otmCtx, selectedDevicelist);
1041 OC_LOG(DEBUG, TAG, "OUT OTMDoOwnershipTransfer");
1045 OICFree(otmCtx->ctxResultArray);
1052 * Callback handler of SRPFinalizeProvisioning.
1054 * @param[in] ctx ctx value passed to callback from calling function.
1055 * @param[in] UNUSED handle to an invocation
1056 * @param[in] clientResponse Response from queries to remote servers.
1057 * @return OC_STACK_DELETE_TRANSACTION to delete the transaction
1058 * and OC_STACK_KEEP_TRANSACTION to keep it.
1060 static OCStackApplicationResult FinalizeProvisioningCB(void *ctx, OCDoHandle UNUSED,
1061 OCClientResponse *clientResponse)
1063 OC_LOG_V(INFO, TAG, "IN FinalizeProvisioningCB.");
1065 VERIFY_NON_NULL(TAG, clientResponse, ERROR);
1066 VERIFY_NON_NULL(TAG, ctx, ERROR);
1068 OTMContext_t* otmCtx = (OTMContext_t*)ctx;
1070 if(OC_STACK_OK == clientResponse->result)
1072 OCStackResult res = PDMAddDevice(&otmCtx->selectedDeviceInfo->doxm->deviceID);
1074 if (OC_STACK_OK == res)
1076 OC_LOG_V(INFO, TAG, "Add device's UUID in PDM_DB");
1077 SetResult(otmCtx, OC_STACK_OK);
1078 return OC_STACK_DELETE_TRANSACTION;
1082 OC_LOG(ERROR, TAG, "Ownership transfer is complete but adding information to DB is failed.");
1086 return OC_STACK_DELETE_TRANSACTION;
1090 * Callback handler of default ACL provisioning.
1092 * @param[in] ctx ctx value passed to callback from calling function.
1093 * @param[in] UNUSED handle to an invocation
1094 * @param[in] clientResponse Response from queries to remote servers.
1095 * @return OC_STACK_DELETE_TRANSACTION to delete the transaction
1096 * and OC_STACK_KEEP_TRANSACTION to keep it.
1098 static OCStackApplicationResult ProvisionDefaultACLCB(void *ctx, OCDoHandle UNUSED,
1099 OCClientResponse *clientResponse)
1101 OC_LOG_V(INFO, TAG, "IN ProvisionDefaultACLCB.");
1103 VERIFY_NON_NULL(TAG, clientResponse, ERROR);
1104 VERIFY_NON_NULL(TAG, ctx, ERROR);
1106 OTMContext_t* otmCtx = (OTMContext_t*) ctx;
1109 if (OC_STACK_RESOURCE_CREATED == clientResponse->result)
1111 OC_LOG_V(INFO, TAG, "Staring commit hash task.");
1112 // TODO hash currently have fixed value 0.
1113 uint16_t aclHash = 0;
1114 otmCtx->selectedDeviceInfo->pstat->commitHash = aclHash;
1115 otmCtx->selectedDeviceInfo->pstat->tm = NORMAL;
1116 OCSecurityPayload* secPayload = (OCSecurityPayload*)OICCalloc(1, sizeof(OCSecurityPayload));
1119 OC_LOG(ERROR, TAG, "Failed to memory allocation");
1120 return OC_STACK_NO_MEMORY;
1122 secPayload->base.type = PAYLOAD_TYPE_SECURITY;
1123 secPayload->securityData = BinToPstatJSON(otmCtx->selectedDeviceInfo->pstat, false);
1124 if (NULL == secPayload->securityData)
1126 OICFree(secPayload);
1127 SetResult(otmCtx, OC_STACK_INVALID_JSON);
1128 return OC_STACK_DELETE_TRANSACTION;
1130 OC_LOG_V(INFO, TAG, "Created payload for commit hash: %s",secPayload->securityData);
1132 char query[MAX_URI_LENGTH + MAX_QUERY_LENGTH] = {0};
1133 if(!PMGenerateQuery(true,
1134 otmCtx->selectedDeviceInfo->endpoint.addr,
1135 otmCtx->selectedDeviceInfo->securePort,
1136 otmCtx->selectedDeviceInfo->connType,
1137 query, sizeof(query), OIC_RSRC_PSTAT_URI))
1139 OC_LOG(ERROR, TAG, "ProvisionDefaultACLCB : Failed to generate query");
1140 return OC_STACK_ERROR;
1142 OC_LOG_V(DEBUG, TAG, "Query=%s", query);
1144 OCCallbackData cbData = {.context=NULL, .cb=NULL, .cd=NULL};
1145 cbData.cb = &FinalizeProvisioningCB;
1146 cbData.context = (void*)otmCtx;
1148 OCStackResult ret = OCDoResource(NULL, OC_REST_PUT, query, 0, (OCPayload*)secPayload,
1149 otmCtx->selectedDeviceInfo->connType, OC_HIGH_QOS, &cbData, NULL, 0);
1150 OC_LOG_V(INFO, TAG, "OCDoResource returned: %d",ret);
1151 if (ret != OC_STACK_OK)
1153 OC_LOG(ERROR, TAG, "OCStack resource error");
1154 SetResult(otmCtx, ret);
1159 OC_LOG_V(INFO, TAG, "Error occured in provisionDefaultACLCB :: %d\n",
1160 clientResponse->result);
1161 SetResult(otmCtx, clientResponse->result);
1164 return OC_STACK_DELETE_TRANSACTION;
1168 OCStackResult FinalizeProvisioning(OTMContext_t* otmCtx)
1170 OC_LOG(INFO, TAG, "IN FinalizeProvisioning");
1174 OC_LOG(ERROR, TAG, "OTMContext is NULL");
1175 return OC_STACK_INVALID_PARAM;
1177 if(!otmCtx->selectedDeviceInfo)
1179 OC_LOG(ERROR, TAG, "Can't find device information in OTMContext");
1181 return OC_STACK_INVALID_PARAM;
1183 // Provision Default ACL to device
1184 OicSecAcl_t defaultAcl =
1197 OicUuid_t provTooldeviceID = {.id={0}};
1198 if (OC_STACK_OK != GetDoxmDeviceID(&provTooldeviceID))
1200 OC_LOG(ERROR, TAG, "Error while retrieving provisioning tool's device ID");
1201 SetResult(otmCtx, OC_STACK_ERROR);
1202 return OC_STACK_ERROR;
1204 OC_LOG(INFO, TAG, "Retieved deviceID");
1205 memcpy(defaultAcl.subject.id, provTooldeviceID.id, sizeof(defaultAcl.subject.id));
1206 char *wildCardResource = "*";
1207 defaultAcl.resources = &wildCardResource;
1209 defaultAcl.owners = (OicUuid_t *) OICCalloc(1, UUID_LENGTH);
1210 if(!defaultAcl.owners)
1212 OC_LOG(ERROR, TAG, "Failed to memory allocation for default ACL");
1213 SetResult(otmCtx, OC_STACK_NO_MEMORY);
1214 return OC_STACK_NO_MEMORY;
1216 memcpy(defaultAcl.owners->id, provTooldeviceID.id, UUID_LENGTH);
1217 OC_LOG(INFO, TAG, "Provisioning default ACL");
1219 OCSecurityPayload* secPayload = (OCSecurityPayload*)OICCalloc(1, sizeof(OCSecurityPayload));
1222 OC_LOG(ERROR, TAG, "Failed to memory allocation");
1223 return OC_STACK_NO_MEMORY;
1225 secPayload->base.type = PAYLOAD_TYPE_SECURITY;
1226 secPayload->securityData = BinToAclJSON(&defaultAcl, false);
1227 OICFree(defaultAcl.owners);
1228 if(!secPayload->securityData)
1230 OICFree(secPayload);
1231 OC_LOG(INFO, TAG, "FinalizeProvisioning : Failed to BinToAclJSON");
1232 SetResult(otmCtx, OC_STACK_ERROR);
1233 return OC_STACK_ERROR;
1235 OC_LOG_V(INFO, TAG, "Provisioning default ACL : %s",secPayload->securityData);
1237 char query[MAX_URI_LENGTH + MAX_QUERY_LENGTH] = {0};
1238 if(!PMGenerateQuery(true,
1239 otmCtx->selectedDeviceInfo->endpoint.addr,
1240 otmCtx->selectedDeviceInfo->securePort,
1241 otmCtx->selectedDeviceInfo->connType,
1242 query, sizeof(query), OIC_RSRC_ACL_URI))
1244 OC_LOG(ERROR, TAG, "FinalizeProvisioning : Failed to generate query");
1245 return OC_STACK_ERROR;
1247 OC_LOG_V(DEBUG, TAG, "Query=%s", query);
1249 OC_LOG_V(INFO, TAG, "Request URI for Provisioning default ACL : %s", query);
1251 OCCallbackData cbData = {.context=NULL, .cb=NULL, .cd=NULL};
1252 cbData.cb = &ProvisionDefaultACLCB;
1253 cbData.context = (void *)otmCtx;
1255 OCStackResult ret = OCDoResource(NULL, OC_REST_POST, query,
1256 &otmCtx->selectedDeviceInfo->endpoint, (OCPayload*)secPayload,
1257 otmCtx->selectedDeviceInfo->connType, OC_HIGH_QOS, &cbData, NULL, 0);
1258 if (OC_STACK_OK != ret)
1260 SetResult(otmCtx, ret);
1264 OC_LOG(INFO, TAG, "OUT FinalizeProvisioning");