#include "logger.h"
#include "ESException.h"
#include "oic_malloc.h"
+#include "provisioningdatabasemanager.h"
#include "oic_string.h"
#include "utlist.h"
+#include "srmutility.h"
+#include "aclresource.h"
+#include "internal/doxmresource.h"
+#include "ocrandom.h"
namespace OIC
{
namespace Service
{
+ namespace
+ {
+ static const char COAP[] = "coap://";
+ static const char COAPS[] = "coaps://";
+ static const char COAP_TCP[] = "coap+tcp://";
+ static const char COAP_GATT[] = "coap+gatt://";
+ static const char COAP_RFCOMM[] = "coap+rfcomm://";
+ }
+
#define MAX_PERMISSION_LENGTH (5)
#define CREATE (1)
#define READ (2)
#define NOTIFY (16)
#define DASH '-'
- //TODO : Currently discovery timeout for owned and unowned devices is fixed as 5
+ // TODO : Currently discovery timeout for owned and unowned devices is fixed as 5
// The value should be accepted from the application as a parameter during ocplatform
// config call
+
+#ifdef __APPLE__
+ #define ES_SEC_DISCOVERY_TIMEOUT 15
+#else
#define ES_SEC_DISCOVERY_TIMEOUT 5
+#endif
+
+ EnrolleeSecurity::EnrolleeSecurity(std::shared_ptr< OC::OCResource > resource)
+ {
+ m_ocResource = resource;
+ }
+
+ void EnrolleeSecurity::onEnrolleeSecuritySafetyCB(OC::PMResultList_t *result,
+ int hasError,
+ ESSecurityCb cb,
+ std::weak_ptr<EnrolleeSecurity> this_ptr)
+ {
+ OIC_LOG(DEBUG, ENROLEE_SECURITY_TAG, "onEnrolleeSecuritySafetyCB");
+ std::shared_ptr<EnrolleeSecurity> Ptr = this_ptr.lock();
+ if(Ptr)
+ {
+ cb(result, hasError);
+ }
+ }
+
+ void EnrolleeSecurity::convertUUIDToString(const uint8_t uuid[UUID_SIZE],
+ std::string& uuidString)
+ {
+ char uuidArray[UUID_STRING_SIZE] = {'\0',};
+ int ret = snprintf(uuidArray, UUID_STRING_SIZE,
+ "%02x%02x%02x%02x-%02x%02x-%02x%02x-%02x%02x-%02x%02x%02x%02x%02x%02x",
+ uuid[0], uuid[1], uuid[2], uuid[3],
+ uuid[4], uuid[5], uuid[6], uuid[7],
+ uuid[8], uuid[9], uuid[10], uuid[11],
+ uuid[12], uuid[13], uuid[14], uuid[15]
+ );
+
+ if (ret != UUID_STRING_SIZE - 1)
+ {
+ return;
+ }
+
+ uuidString = uuidArray;
+ }
+
+ std::string EnrolleeSecurity::getResourceDeviceAddress(const std::string& host)
+ {
+ size_t prefix_len = 0;
+
+ if (host.compare(0, sizeof(COAP) - 1, COAP) == 0)
+ {
+ prefix_len = sizeof(COAP) - 1;
+ }
+ else if (host.compare(0, sizeof(COAPS) - 1, COAPS) == 0)
+ {
+ prefix_len = sizeof(COAPS) - 1;
+ }
+ else if (host.compare(0, sizeof(COAP_TCP) - 1, COAP_TCP) == 0)
+ {
+ prefix_len = sizeof(COAP_TCP) - 1;
+ }
+ else if (host.compare(0, sizeof(COAP_GATT) - 1, COAP_GATT) == 0)
+ {
+ prefix_len = sizeof(COAP_GATT) - 1;
+ }
+ else if (host.compare(0, sizeof(COAP_RFCOMM) - 1, COAP_RFCOMM) == 0)
+ {
+ prefix_len = sizeof(COAP_RFCOMM) - 1;
+ }
+ else
+ {
+ OIC_LOG(DEBUG, ENROLEE_SECURITY_TAG,
+ "Well-known prefix for connectivity is not found. Please check OCResource::setHost");
+ return {};
+ }
+
+ // remove prefix
+ std::string host_token = host.substr(prefix_len);
+
+ if (host_token[0] == '[') // IPv6
+ {
+ size_t bracket = host_token.find(']');
+
+ // extract the ipv6 address
+ return host_token.substr(0, bracket + 1);
+ }
+ else
+ {
+ size_t dot = host_token.find('.');
+ if (std::string::npos == dot) // MAC
+ {
+ size_t semi_count = std::count(host_token.begin(), host_token.end(), ':');
+ if (semi_count > 5)
+ {
+ size_t found_semi = host_token.find_last_of(':');
+ host_token = host_token.substr(0, found_semi);
+ }
+ return host_token;
+ }
+ else // IPv4
+ {
+ size_t colon = host_token.find(':');
+
+ // extract the ipv4 address
+ return host_token.substr(0, colon);
+ }
+ }
+ }
+
+ bool EnrolleeSecurity::isOwnerIDMatched(std::shared_ptr< OC::OCSecureResource > foundDevice)
+ {
+ OIC_LOG(DEBUG, ENROLEE_SECURITY_TAG, "isOwnerIDMatched IN");
+
+ if(foundDevice.get() == nullptr)
+ {
+ OIC_LOG(ERROR, ENROLEE_SECURITY_TAG, "foundDevice is NULL ptr");
+ return false;
+ }
+
+ bool ret = false;
+ std::string ownerID;
+ char uuidString[UUID_STRING_SIZE] = {};
+ if(RAND_UUID_OK == OCConvertUuidToString(foundDevice->getDevPtr()->doxm->owner.id, uuidString))
+ {
+ ownerID = uuidString;
+ }
+ else
+ {
+ ownerID = {};
+ }
+
+ OIC_LOG_V(INFO_PRIVATE, ENROLEE_SECURITY_TAG, "Mediator ID %s", m_mediatorID.c_str());
+ OIC_LOG_V(INFO_PRIVATE, ENROLEE_SECURITY_TAG, "Enrollee's Owner ID %s", ownerID.c_str());
+
+ if(ownerID == m_mediatorID)
+ {
+ OIC_LOG(DEBUG, ENROLEE_SECURITY_TAG,
+ "The found device's first owner ID is matched with Mediator's ID");
+ ret = true;
+ }
+ else
+ {
+ OIC_LOG(DEBUG, ENROLEE_SECURITY_TAG,
+ "The found device's first owner ID is NOT matched with Mediator's ID");
+ }
+
+ OIC_LOG(DEBUG, ENROLEE_SECURITY_TAG, "isOwnerIDMatched OUT");
+
+ return ret;
+ }
+
+#ifdef MULTIPLE_OWNER
+ bool EnrolleeSecurity::isSubOwnerIDMatched(std::shared_ptr< OC::OCSecureResource > foundDevice)
+ {
+ OIC_LOG(DEBUG, ENROLEE_SECURITY_TAG, "isSubOwnerIDMatched IN");
+
+ if(foundDevice.get() == nullptr)
+ {
+ OIC_LOG(ERROR, ENROLEE_SECURITY_TAG,
+ "The found device's sub owner ID is NOT matched with Mediator's ID");
+
+ return false;
+ }
+
+ bool ret = false;
+ std::string subOwnerID;
+ char uuidString[UUID_STRING_SIZE] = {};
+
+ OicSecSubOwner_t* subOwnerList = foundDevice->getDevPtr()->doxm->subOwners;
+
+ while(subOwnerList)
+ {
+ if(RAND_UUID_OK == OCConvertUuidToString(subOwnerList->uuid.id, uuidString))
+ {
+ subOwnerID = uuidString;
+ }
+ else
+ {
+ subOwnerID = {};
+ }
+
+ if(subOwnerID == m_mediatorID)
+ {
+ OIC_LOG(DEBUG, ENROLEE_SECURITY_TAG,
+ "The found device's owner ID is matched with Mediator's ID as a second owner");
+ ret = true;
+ break;
+ }
+ subOwnerList = subOwnerList->next;
+ }
+
+ if(!ret)
+ {
+ OIC_LOG(DEBUG, ENROLEE_SECURITY_TAG,
+ "The found device's sub owner ID is NOT matched with Mediator's ID");
+ }
+
+ OIC_LOG(DEBUG, ENROLEE_SECURITY_TAG, "isSubOwnerIDMatched OUT");
+ return ret;
+ }
+
+ void EnrolleeSecurity::changeMOTMethodCB(PMResultList_t *result, int hasError)
+ {
+ OIC_LOG(DEBUG, ENROLEE_SECURITY_TAG, "changeMOTMethodCB IN");
+ if (hasError)
+ {
+ OIC_LOG_V(ERROR, ENROLEE_SECURITY_TAG,
+ "requestEnableMOTMode API is failed with error %d", hasError);
+ enableMOTModeResult = false;
+ }
+ else
+ {
+ OIC_LOG(DEBUG, ENROLEE_SECURITY_TAG, "requestEnableMOTMode API is succeeded");
+ enableMOTModeResult = true;
+ }
+
+ delete result;
+ m_cond.notify_all();
+ }
+
+
+ void EnrolleeSecurity::selectMOTMethodCB(PMResultList_t *result, int hasError)
+ {
+ OIC_LOG(DEBUG, ENROLEE_SECURITY_TAG, "selectMOTMethodCB IN");
+ if (hasError)
+ {
+ OIC_LOG_V(ERROR, ENROLEE_SECURITY_TAG,
+ "selectMOTMethod API is failed with error %d", hasError);
+ motMethodProvResult = false;
+ }
+ else
+ {
+ OIC_LOG(DEBUG, ENROLEE_SECURITY_TAG, "selectMOTMethod API is succeeded");
+ motMethodProvResult = true;
+ }
+
+ delete result;
+ m_cond.notify_all();
+ }
+
+ void EnrolleeSecurity::preconfigPinProvCB(PMResultList_t *result, int hasError)
+ {
+ OIC_LOG(DEBUG, ENROLEE_SECURITY_TAG, "preconfigPinProvCB IN");
+ if (hasError)
+ {
+ OIC_LOG_V(ERROR, ENROLEE_SECURITY_TAG,
+ "provisionPreconfPin API is failed with error %d", hasError);
+ preConfigPinProvResult = false;
+ }
+ else
+ {
+ OIC_LOG(DEBUG, ENROLEE_SECURITY_TAG, "provisionPreconfPin API is succeeded");
+ preConfigPinProvResult = true;
+ }
+
+ delete result;
+ m_cond.notify_all();
+ }
+
+ void EnrolleeSecurity::multipleOwnershipTransferCb(OC::PMResultList_t *result, int hasError)
+ {
+ OIC_LOG(DEBUG, ENROLEE_SECURITY_TAG, "multipleOwnershipTransferCb IN");
+
+ otmResult = false;
+
+ if (hasError)
+ {
+ OIC_LOG_V(ERROR, ENROLEE_SECURITY_TAG, "multipleOwnershipTransferCb is failed with code(%d)", hasError);
+ otmResult = false;
+ m_cond.notify_all();
+ }
+ else
+ {
+ for (unsigned int i = 0; i < result->size(); i++)
+ {
+ std::string uuid;
+ convertUUIDToString(result->at(i).deviceId.id, uuid);
+
+ if(m_ocResource != NULL && m_ocResource->sid() == uuid)
+ {
+ if( OC_STACK_OK == result->at(i).res )
+ {
+ OIC_LOG(DEBUG, ENROLEE_SECURITY_TAG, "multipleOwnershipTransferCb is succeeded");
+ OIC_LOG_V(DEBUG, ENROLEE_SECURITY_TAG, "Result is = %d", result->at(i).res);
+ OIC_LOG_V(INFO_PRIVATE, ENROLEE_SECURITY_TAG, "device uuid : %s", uuid.c_str());
+
+ otmResult = true;
+ }
+ else
+ {
+ OIC_LOG_V(ERROR, ENROLEE_SECURITY_TAG, "multipleOwnershipTransfer is failed with code(%d)", hasError);
+ otmResult = false;
+ }
+ }
+ }
+ delete result;
+ m_cond.notify_all();
+ }
+ }
+
+ ESResult EnrolleeSecurity::requestSetPreconfPinData(const ESOwnershipTransferData& MOTData)
+ {
+ OIC_LOG(DEBUG, ENROLEE_SECURITY_TAG, "requestSetPreconfPinData IN");
+
+ ESResult res = ESResult::ES_ERROR;
+
+ OC::ResultCallBack preconfigPinProvCB = std::bind(
+ &EnrolleeSecurity::onEnrolleeSecuritySafetyCB,
+ std::placeholders::_1, std::placeholders::_2,
+ static_cast<ESSecurityCb>(std::bind(&EnrolleeSecurity::preconfigPinProvCB,
+ this, std::placeholders::_1, std::placeholders::_2)),
+ shared_from_this());
+
+ std::string pin = MOTData.getPreConfiguredPin();
+
+ OIC_LOG(DEBUG, ENROLEE_SECURITY_TAG, "provisionPreconfPin is called.");
+ if(OC_STACK_OK != m_securedResource->provisionPreconfPin(
+ pin.c_str(), pin.length(), preconfigPinProvCB))
+ {
+ OIC_LOG(ERROR, ENROLEE_SECURITY_TAG, "provisionPreconfPin API error");
+ res = ESResult:: ES_PRE_CONFIG_PIN_PROVISIONING_FAILURE;
+ return res;
+ }
+
+ std::unique_lock<std::mutex> lck(m_mtx);
+ m_cond.wait(lck);
+
+ if(!preConfigPinProvResult)
+ {
+ OIC_LOG(ERROR, ENROLEE_SECURITY_TAG, "provisionPreconfPin is failed.");
+ res = ESResult:: ES_PRE_CONFIG_PIN_PROVISIONING_FAILURE;
+ return res;
+ }
+
+ return ESResult::ES_OK;
+ }
+
+ ESResult EnrolleeSecurity::requestSetMOTMethod(const ESOwnershipTransferData& MOTData)
+ {
+ OIC_LOG(DEBUG, ENROLEE_SECURITY_TAG, "requestSetMOTMethod IN");
+
+ ESResult res = ESResult::ES_ERROR;
+
+ OC::ResultCallBack selectMOTMethodCB = std::bind(
+ &EnrolleeSecurity::onEnrolleeSecuritySafetyCB,
+ std::placeholders::_1, std::placeholders::_2,
+ static_cast<ESSecurityCb>(std::bind(&EnrolleeSecurity::selectMOTMethodCB,
+ this, std::placeholders::_1, std::placeholders::_2)),
+ shared_from_this());
+
+ OIC_LOG(DEBUG, ENROLEE_SECURITY_TAG, "selectMOTMethod is called.");
+ if(OC_STACK_OK != m_securedResource->selectMOTMethod(
+ MOTData.getMOTMethod(),
+ selectMOTMethodCB))
+ {
+ OIC_LOG(ERROR, ENROLEE_SECURITY_TAG, "selectMOTMethod API error");
+ res = ESResult:: ES_MOT_METHOD_SELECTION_FAILURE;
+ return res;
+ }
+
+ std::unique_lock<std::mutex> lck(m_mtx);
+ m_cond.wait(lck);
+
+ if(!motMethodProvResult)
+ {
+ OIC_LOG(ERROR, ENROLEE_SECURITY_TAG, "selectMOTMethod is failed.");
+ res = ESResult:: ES_MOT_METHOD_SELECTION_FAILURE;
+ return res;
+ }
+
+ return ESResult::ES_OK;
+ }
+
+ ESResult EnrolleeSecurity::requestEnableMOTMode()
+ {
+ OIC_LOG(DEBUG, ENROLEE_SECURITY_TAG, "requestEnableMOTMode IN");
+ ESResult res = ESResult:: ES_ERROR;
+
+ OC::ResultCallBack changeMOTMethodCB = std::bind(
+ &EnrolleeSecurity::onEnrolleeSecuritySafetyCB,
+ std::placeholders::_1, std::placeholders::_2,
+ static_cast<ESSecurityCb>(std::bind(&EnrolleeSecurity::changeMOTMethodCB,
+ this, std::placeholders::_1, std::placeholders::_2)),
+ shared_from_this());
+
+ if(OC_STACK_OK !=
+ m_securedResource->changeMOTMode(OIC_MULTIPLE_OWNER_ENABLE, changeMOTMethodCB))
+ {
+ OIC_LOG(ERROR, ENROLEE_SECURITY_TAG, "changeMOTMode is failed.");
+ return ESResult:: ES_MOT_ENABLING_FAILURE;
+ }
+
+ std::unique_lock<std::mutex> lck(m_mtx);
+ m_cond.wait(lck);
+
+ if(!enableMOTModeResult)
+ {
+ OIC_LOG(ERROR, ENROLEE_SECURITY_TAG, "requestEnableMOTMode is failed.");
+ res = ESResult:: ES_MOT_ENABLING_FAILURE;
+ return res;
+ }
+
+ return ESResult::ES_OK;
+ }
+
+ ESResult EnrolleeSecurity::provisionMOTConfig(const ESOwnershipTransferData& MOTData)
+ {
+ OIC_LOG(DEBUG, ENROLEE_SECURITY_TAG, "provisionMOTConfig IN");
+ ESResult res = ESResult:: ES_ERROR;
+
+ if(!m_securedResource->isMOTEnabled())
+ {
+ res = requestEnableMOTMode();
+ if(res != ESResult::ES_OK)
+ {
+ OIC_LOG(ERROR, ENROLEE_SECURITY_TAG, "requestEnableMOTMode is failed.");
+ return res;
+ }
+ }
+
+ if( OIC_PRECONFIG_PIN == MOTData.getMOTMethod() &&
+ !MOTData.getPreConfiguredPin().empty())
+ {
+ res = requestSetPreconfPinData(MOTData);
+
+ if(res != ESResult::ES_OK)
+ {
+ OIC_LOG(ERROR, ENROLEE_SECURITY_TAG, "RequestSetPreconfPinData is failed.");
+ return res;
+ }
+ }
+ if(OIC_PRECONFIG_PIN == MOTData.getMOTMethod() ||
+ OIC_RANDOM_DEVICE_PIN == MOTData.getMOTMethod())
+ {
+ res = requestSetMOTMethod(MOTData);
+
+ if(res != ESResult::ES_OK)
+ {
+ OIC_LOG(ERROR, ENROLEE_SECURITY_TAG, "RequestSetMOTMethod is failed.");
+ return res;
+ }
+ }
+ return res;
+ }
+#endif
+
+ void EnrolleeSecurity::ownershipTransferCb(OC::PMResultList_t *result, int hasError
+ , ESResult& res)
+ {
+ OIC_LOG(DEBUG, ENROLEE_SECURITY_TAG, "ownershipTransferCb IN");
+
+ otmResult = false;
+
+ if (hasError)
+ {
+ for (unsigned int i = 0; i < result->size(); i++)
+ {
+ std::string uuid;
+ convertUUIDToString(result->at(i).deviceId.id, uuid);
+
+ if(m_ocResource != NULL && m_ocResource->sid() == uuid)
+ {
+ if(OC_STACK_USER_DENIED_REQ == result->at(i).res)
+ {
+ res = ESResult::ES_USER_DENIED_CONFIRMATION_REQ;
+ }
+ else if(OC_STACK_AUTHENTICATION_FAILURE == result->at(i).res)
+ {
+ OicSecOxm_t oxm = OIC_OXM_COUNT;
+ if(OC_STACK_OK != m_securedResource->getOTMethod(&oxm))
+ {
+ otmResult = false;
+ return;
+ }
+
+ if(OIC_MANUFACTURER_CERTIFICATE == oxm)
+ {
+ res = ESResult::ES_AUTHENTICATION_FAILURE_WITH_WRONG_CERT;
+ }
+ else if(OIC_CON_MFG_CERT == oxm)
+ {
+ res = ESResult::ES_AUTHENTICATION_FAILURE_WITH_WRONG_CERT;
+ }
+ else if(OIC_RANDOM_DEVICE_PIN == oxm)
+ {
+ res = ESResult::ES_AUTHENTICATION_FAILURE_WITH_WRONG_PIN;
+ }
+ }
+ else if(OC_STACK_COMM_ERROR == result->at(i).res)
+ {
+ OIC_LOG(ERROR, ENROLEE_SECURITY_TAG,
+ "OwnershipTransfer is failed with OC_STACK_COMM_ERROR");
+ res = ESResult::ES_COMMUNICATION_ERROR;
+ }
+ else if(OC_STACK_TIMEOUT == result->at(i).res)
+ {
+ OIC_LOG(ERROR, ENROLEE_SECURITY_TAG,
+ "OwnershipTransfer is failed with OC_STACK_TIMEOUT");
+ res = ESResult::ES_COMMUNICATION_ERROR;
+ }
+ else if(OC_STACK_GATEWAY_TIMEOUT== result->at(i).res)
+ {
+ OIC_LOG(ERROR, ENROLEE_SECURITY_TAG,
+ "OwnershipTransfer is failed with OC_STACK_GATEWAY_TIMEOUT");
+ res = ESResult::ES_COMMUNICATION_ERROR;
+ }
+ }
+ }
+ OIC_LOG_V(ERROR, ENROLEE_SECURITY_TAG, "OwnershipTransfer is failed with ESResult(%d)", res);
+
+ otmResult = false;
+ }
+ else
+ {
+ for (unsigned int i = 0; i < result->size(); i++)
+ {
+ std::string uuid;
+ convertUUIDToString(result->at(i).deviceId.id, uuid);
+
+ if(m_ocResource != NULL && m_ocResource->sid() == uuid)
+ {
+ if( OC_STACK_OK == result->at(i).res )
+ {
+ OIC_LOG(DEBUG, ENROLEE_SECURITY_TAG, "OwnershipTransfer is succeeded");
+ OIC_LOG_V(DEBUG, ENROLEE_SECURITY_TAG, "Result is = %d", result->at(i).res);
+ OIC_LOG_V(INFO_PRIVATE, ENROLEE_SECURITY_TAG, "device uuid : %s", uuid.c_str());
+
+ otmResult = true;
+ }
+ else
+ {
+ OIC_LOG_V(ERROR, ENROLEE_SECURITY_TAG, "OwnershipTransfer is failed with code(%d)", hasError);
+ otmResult = false;
+ }
+ }
+ }
+ }
+
+ delete result;
+ m_cond.notify_all();
+ }
+
+ ESResult EnrolleeSecurity::discoverTargetSecureResource()
+ {
+ OIC_LOG(DEBUG, ENROLEE_SECURITY_TAG, "discoverTargetSecureResource IN");
+
+ OCStackResult result = OC_STACK_ERROR;
+
+ OicUuid_t uuid;
+ if(OC_STACK_OK != ConvertStrToUuid(m_ocResource->sid().c_str(), &uuid))
+ {
+ OIC_LOG(DEBUG, ENROLEE_SECURITY_TAG, "Convert to uuid from deviceID failed.");
+ return ES_ERROR;
+ }
+
+ // If a discovered resource uses BLE transport, unicast for secure resource discovery is
+ // used.
+ if( m_ocResource->connectivityType() & CT_ADAPTER_GATT_BTLE )
+ {
+ std::string GattAddress = getResourceDeviceAddress(m_ocResource->host());
+ if(!GattAddress.empty())
+ {
+ result = OCSecure::discoverSingleDeviceInUnicast(ES_SEC_DISCOVERY_TIMEOUT,
+ &uuid,
+ GattAddress,
+ m_ocResource->connectivityType(),
+ m_securedResource);
+ if(result != OC_STACK_OK)
+ {
+ return ES_SECURE_RESOURCE_DISCOVERY_FAILURE;
+ }
+ }
+ else
+ {
+ OIC_LOG(ERROR, ENROLEE_SECURITY_TAG, "GATT BTLE address format is wrong.");
+ return ES_ERROR;
+ }
+ }
+ else
+ {
+ result = OCSecure::discoverSingleDevice(ES_SEC_DISCOVERY_TIMEOUT,
+ &uuid,
+ m_securedResource);
+ if(result != OC_STACK_OK)
+ {
+ return ES_SECURE_RESOURCE_DISCOVERY_FAILURE;
+ }
+ }
+
+ OIC_LOG(DEBUG, ENROLEE_SECURITY_TAG, "Secured resource is found.");
+ OIC_LOG_V(DEBUG, ENROLEE_SECURITY_TAG, "HOST: %s", m_securedResource->getDevAddr().c_str());
+ OIC_LOG_V(INFO_PRIVATE, ENROLEE_SECURITY_TAG, "SID: %s", m_securedResource->getDeviceID().c_str());
+ OIC_LOG_V(DEBUG, ENROLEE_SECURITY_TAG, "Owned status: %d", m_securedResource->getOwnedStatus());
+
+ OicSecOxm_t selectedOTMethod = OIC_OXM_COUNT;
+ if( OC_STACK_OK != m_securedResource->getOTMethod(&selectedOTMethod) )
+ {
+ selectedOTMethod = OIC_OXM_COUNT; // Out-of-range
+ }
+ OIC_LOG_V(DEBUG, ENROLEE_SECURITY_TAG, "Selected OT Method: %d", (int)(selectedOTMethod));
+#ifdef MULTIPLE_OWNER
+ OIC_LOG_V(DEBUG, ENROLEE_SECURITY_TAG, "MOT Supported: %d", (int)(m_securedResource->isMOTSupported()));
+ OIC_LOG_V(DEBUG, ENROLEE_SECURITY_TAG, "MOT Enabled: %d", (int)(m_securedResource->isMOTEnabled()));
+#endif
+ if(m_securedResource->getOwnedStatus())
+ {
+ char uuidString[UUID_STRING_SIZE] = {};
+ if(RAND_UUID_OK == OCConvertUuidToString(m_securedResource->getDevPtr()->doxm->owner.id, uuidString))
+ {
+ OIC_LOG_V(INFO_PRIVATE, ENROLEE_SECURITY_TAG, "Owner ID: %s", uuidString);
+ }
+ else
+ {
+ OIC_LOG(ERROR, ENROLEE_SECURITY_TAG, "OCConvertUuidToString is failed");
+ }
+ }
+
+ return ES_OK;
+ }
+
+ ESOwnershipTransferData EnrolleeSecurity::getOwnershipTransferDataFromUser
+ (SecurityProvStatusCbWithOption callback)
+ {
+ OIC_LOG(DEBUG, ENROLEE_SECURITY_TAG, "getOwnershipTransferDataFromUser IN");
+ ESOwnershipTransferData ownershipTransferData;
+
+ std::shared_ptr< SecProvisioningStatus > securityProvisioningStatus =
+ std::make_shared< SecProvisioningStatus >
+ (m_securedResource,
+ ESResult::ES_SECURE_RESOURCE_IS_DISCOVERED);
+ ownershipTransferData = callback(securityProvisioningStatus);
+#ifdef MULTIPLE_OWNER
+ if(OIC_RANDOM_DEVICE_PIN == ownershipTransferData.getMOTMethod())
+ {
+ OIC_LOG(DEBUG, ENROLEE_SECURITY_TAG, "Selected MOT Method: OIC_RANDOM_DEVICE_PIN");
+ }
+ else if(OIC_PRECONFIG_PIN == ownershipTransferData.getMOTMethod())
+ {
+ OIC_LOG(DEBUG, ENROLEE_SECURITY_TAG, "Selected MOT Method: OIC_PRECONFIG_PIN");
+ OIC_LOG_V(INFO_PRIVATE, ENROLEE_SECURITY_TAG, "Pre-configured PIN: %s",
+ ownershipTransferData.getPreConfiguredPin().c_str());
+ }
+#endif
+ return ownershipTransferData;
+ }
- EnrolleeSecurity::EnrolleeSecurity(
- std::shared_ptr< OC::OCResource > resource,
- const std::string secDbPath)
+ ESResult EnrolleeSecurity::syncUpWithMediatorDB()
{
- (void) secDbPath;
- m_ocResource = resource;
+ OIC_LOG(DEBUG, ENROLEE_SECURITY_TAG, "syncUpWithMediatorDB IN");
+
+ OCStackResult result = OC_STACK_ERROR;
+ ESResult res = ESResult::ES_ERROR;
+
+ OC::ResultCallBack removeDeviceWithUuidCB = std::bind(
+ &EnrolleeSecurity::onEnrolleeSecuritySafetyCB,
+ std::placeholders::_1, std::placeholders::_2,
+ static_cast<ESSecurityCb>(std::bind(&EnrolleeSecurity::removeDeviceWithUuidCB,
+ this, std::placeholders::_1, std::placeholders::_2)),
+ shared_from_this());
+
+ result = OCSecure::removeDeviceWithUuid(ES_SEC_DISCOVERY_TIMEOUT,
+ m_ocResource->sid(),
+ removeDeviceWithUuidCB);
+ if(result != OC_STACK_OK)
+ {
+ OIC_LOG_V(ERROR, ENROLEE_SECURITY_TAG, "removeDeviceWithUuid failed. (%d)", result);
+ res = ESResult::ES_OWNERSHIP_IS_NOT_SYNCHRONIZED;
+ return res;
+ }
+
+ std::unique_lock<std::mutex> lck(m_mtx);
+ m_cond.wait_for(lck, std::chrono::seconds(ES_SEC_DISCOVERY_TIMEOUT));
+
+ if(!removeDeviceResult)
+ {
+ OIC_LOG(ERROR, ENROLEE_SECURITY_TAG, "Removing device is failed.");
+ res = ESResult::ES_OWNERSHIP_IS_NOT_SYNCHRONIZED;
+ return res;
+ }
+ return ESResult::ES_OK;
}
- void EnrolleeSecurity::registerCallbackHandler(
- const SecurityProvStatusCb securityProvStatusCb,
- const SecurityPinCb securityPinCb,
- const SecProvisioningDbPathCb secProvisioningDbPathCb)
+ std::string EnrolleeSecurity::getMediatorDevID()
{
- m_securityProvStatusCb = securityProvStatusCb;
- m_securityPinCb = securityPinCb;
- m_secProvisioningDbPathCb = secProvisioningDbPathCb;
+ OIC_LOG(DEBUG, ENROLEE_SECURITY_TAG, "getMediatorDevID IN");
+ OCUUIdentity* mediatorDevId = (OCUUIdentity* )OICMalloc(sizeof(OCUUIdentity));
+ if(!mediatorDevId)
+ {
+ OIC_LOG(ERROR, ENROLEE_SECURITY_TAG, "provisionOwnership: OICMalloc error return");
+ return {};
+ }
+
+ if(OC::OCPlatform::getDeviceId(mediatorDevId) != OC_STACK_OK)
+ {
+ OIC_LOG(ERROR, ENROLEE_SECURITY_TAG, "getDeviceId is failed.");
+ OICFree(mediatorDevId);
+ return {};
+ }
+
+ char uuidString[UUID_STRING_SIZE] = {};
+ if(RAND_UUID_OK == OCConvertUuidToString(mediatorDevId->id, uuidString))
+ {
+ OIC_LOG_V(INFO_PRIVATE, ENROLEE_SECURITY_TAG, "Mediator UUID : %s", uuidString);
+ OICFree(mediatorDevId);
+ return std::string(uuidString);
+ }
+
+ OIC_LOG(ERROR, ENROLEE_SECURITY_TAG, "OCConvertUuidToString is failed.");
+ OICFree(mediatorDevId);
+ return {};
}
- std::shared_ptr< OC::OCSecureResource > EnrolleeSecurity::getEnrollee(
- DeviceList_t &list)
+ ESResult EnrolleeSecurity::provisionOwnership(SecurityProvStatusCbWithOption callback)
{
- for (unsigned int i = 0; i < list.size(); i++)
+ OIC_LOG(DEBUG, ENROLEE_SECURITY_TAG, "provisionOwnership IN");
+
+ ESResult res = ESResult:: ES_ERROR;
+
+ ESOwnershipTransferData ownershipTransferData;
+
+ std::string mediatorDevIdStr = getMediatorDevID();
+ if(mediatorDevIdStr.empty())
{
- if(m_ocResource->sid() == list[i]->getDeviceID().c_str())
+ OIC_LOG(ERROR, ENROLEE_SECURITY_TAG, "getMediatorDevID is failed.");
+ return res;
+ }
+ else
+ {
+ m_mediatorID = mediatorDevIdStr;
+ }
+
+ res = discoverTargetSecureResource();
+
+ if (res != ES_OK)
+ {
+ OIC_LOG(ERROR, ENROLEE_SECURITY_TAG, "Secure Resource Discovery failed.");
+ res = ESResult:: ES_SECURE_RESOURCE_DISCOVERY_FAILURE;
+ return res;
+ }
+ else if (m_securedResource)
+ {
+ if(callback != NULL)
+ {
+ ownershipTransferData = getOwnershipTransferDataFromUser(callback);
+ }
+
+ if(m_securedResource->getOwnedStatus())
+ {
+ if(isOwnedDeviceRegisteredInDB())
+ {
+#ifdef MULTIPLE_OWNER
+ if(isSubOwnerIDMatched(m_securedResource))
+ {
+ OIC_LOG(DEBUG, ENROLEE_SECURITY_TAG,
+ "The found device is already owned by Mediator.(SUCCESS)");
+ res = ESResult::ES_OK;
+ return res;
+ }
+
+ if(isOwnerIDMatched(m_securedResource))
+ {
+ if((OIC_PRECONFIG_PIN == ownershipTransferData.getMOTMethod() ||
+ OIC_RANDOM_DEVICE_PIN == ownershipTransferData.getMOTMethod()))
+ {
+ if(m_securedResource->isMOTSupported())
+ {
+ res = provisionMOTConfig(ownershipTransferData);
+ if(res != ES_OK)
+ {
+ OIC_LOG(DEBUG, ENROLEE_SECURITY_TAG,
+ "provisionMOTConfig is failed.");
+ return res;
+ }
+ OIC_LOG(DEBUG, ENROLEE_SECURITY_TAG,
+ "The found device is already owned by Mediator and enabled MOT mode.");
+ return res;
+ }
+ else
+ {
+ OIC_LOG(DEBUG, ENROLEE_SECURITY_TAG,
+ "The found device is not supported MOT");
+ return ESResult:: ES_MOT_NOT_SUPPORTED;
+ }
+ }
+ else
+ {
+ OIC_LOG(DEBUG, ENROLEE_SECURITY_TAG,
+ "The found device is already owned by Mediator.(SUCCESS)");
+ res = ESResult::ES_OK;
+ return res;
+ }
+ }
+
+ OIC_LOG(ERROR, ENROLEE_SECURITY_TAG,
+ "An ownership transfer knowledge is not synchronized"
+ "between mediator and found enrollee.(FAILED)");
+ res = ESResult::ES_OWNERSHIP_IS_NOT_SYNCHRONIZED;
+ return res;
+#else
+ if(isOwnerIDMatched(m_securedResource))
+ {
+ OIC_LOG(DEBUG, ENROLEE_SECURITY_TAG,
+ "The found device is already owned by Mediator.(SUCCESS)");
+ res = ESResult::ES_OK;
+ return res;
+ }
+ else
+ {
+ OIC_LOG(ERROR, ENROLEE_SECURITY_TAG,
+ "An ownership transfer knowledge is not synchronized"
+ "between mediator and found enrollee.(FAILED)");
+ res = ESResult::ES_OWNERSHIP_IS_NOT_SYNCHRONIZED;
+ return res;
+ }
+#endif
+ }
+#ifdef MULTIPLE_OWNER
+ else if( !isOwnedDeviceRegisteredInDB() &&
+ !isOwnerIDMatched(m_securedResource) &&
+ !isSubOwnerIDMatched(m_securedResource) &&
+ m_securedResource->isMOTEnabled() &&
+ (OIC_PRECONFIG_PIN == ownershipTransferData.getMOTMethod() ||
+ OIC_RANDOM_DEVICE_PIN == ownershipTransferData.getMOTMethod()))
+ {
+ // MOT case;
+ res = performMultipleOwnershipTransfer(ownershipTransferData);
+
+ if(res != ESResult::ES_OK)
+ {
+ OIC_LOG_V(ERROR, ENROLEE_SECURITY_TAG,
+ "Multiple Ownership-Transfer failed. (%d)", res);
+ return res;
+ }
+ }
+ else if( !isOwnedDeviceRegisteredInDB() &&
+ (isOwnerIDMatched(m_securedResource) ||
+ isSubOwnerIDMatched(m_securedResource)))
+#else
+ else if( !isOwnedDeviceRegisteredInDB() && isOwnerIDMatched(m_securedResource))
+#endif
+ {
+ OIC_LOG(ERROR, ENROLEE_SECURITY_TAG,
+ "An ownership transfer knowledge is not synchronized between mediator and found enrollee.(FAILED)");
+ res = ESResult::ES_OWNERSHIP_IS_NOT_SYNCHRONIZED;
+ return res;
+ }
+ else
+ {
+ OIC_LOG(ERROR, ENROLEE_SECURITY_TAG,
+ "The found device is already owned by Other Mediator.(FAILED)");
+ res = ESResult::ES_OWNERSHIP_TRANSFER_FAILURE;
+ return res;
+ }
+ }
+ else
{
- OIC_LOG_V(DEBUG, ENROLEE_SECURITY_TAG, "Device %d ID %s ", i + 1,
- list[i]->getDeviceID().c_str());
- OIC_LOG_V(DEBUG, ENROLEE_SECURITY_TAG, "From IP :%s",
- list[i]->getDevAddr().c_str());
- return list[i];
+ if(isOwnedDeviceRegisteredInDB())
+ {
+ res = syncUpWithMediatorDB();
+
+ if(res != ESResult::ES_OK)
+ {
+ OIC_LOG_V(ERROR, ENROLEE_SECURITY_TAG,
+ "syncUpWithMediatorDB failed. (%d)", res);
+ return res;
+ }
+ OIC_LOG(DEBUG, ENROLEE_SECURITY_TAG, "Removing device is succeeded.");
+ }
+ res = performOwnershipTransfer();
+
+ if(res != ESResult::ES_OK)
+ {
+ OIC_LOG_V(ERROR, ENROLEE_SECURITY_TAG, "Ownership-Transfer failed. (%d)", res);
+ return res;
+ }
+#ifdef MULTIPLE_OWNER
+ if( m_securedResource->isMOTSupported() &&
+ ownershipTransferData.getMOTMethod() != OIC_OXM_COUNT)
+ {
+ res = provisionMOTConfig(ownershipTransferData);
+ }
+ return res;
+#endif
}
}
- OIC_LOG(ERROR, ENROLEE_SECURITY_TAG,"Error!!! DeviceList_t is NULL");
- return NULL;
+ else
+ {
+ OIC_LOG(ERROR, ENROLEE_SECURITY_TAG, "No secure resource is found.");
+ res = ESResult:: ES_SECURE_RESOURCE_DISCOVERY_FAILURE;
+ }
+ return res;
}
- void EnrolleeSecurity::convertUUIDToString(const OicUuid_t uuid,
- std::string& uuidString)
+ ESResult EnrolleeSecurity::performOwnershipTransfer()
{
- char base64Buff[B64ENCODE_OUT_SAFESIZE(sizeof(((OicUuid_t*) 0)->id)) + 1] =
- { 0, };
- uint32_t outLen = 0;
- B64Result b64Ret = B64_OK;
- std::ostringstream deviceId("");
+ OIC_LOG(DEBUG, ENROLEE_SECURITY_TAG, "performOwnershipTransfer IN.");
+
+ OCStackResult result = OC_STACK_ERROR;
+ ESResult res = ESResult::ES_ERROR;
+
+ OIC_LOG_V(INFO_PRIVATE, ENROLEE_SECURITY_TAG, "Transfering ownership for : %s ",
+ m_securedResource->getDeviceID().c_str());
+
+ OC::ResultCallBack ownershipTransferCb =
+ std::bind(&EnrolleeSecurity::onEnrolleeSecuritySafetyCB,
+ std::placeholders::_1, std::placeholders::_2,
+ static_cast<ESSecurityCb>(std::bind(&EnrolleeSecurity::ownershipTransferCb,
+ this, std::placeholders::_1, std::placeholders::_2, std::ref(res))),
+ shared_from_this());
+
- b64Ret = b64Encode(uuid.id, sizeof(uuid.id),
- base64Buff, sizeof(base64Buff), &outLen);
+ OIC_LOG(DEBUG, ENROLEE_SECURITY_TAG, "doOwnershipTransfer is excuted");
+ result = m_securedResource->doOwnershipTransfer(ownershipTransferCb);
- if (B64_OK == b64Ret)
+ if (result != OC_STACK_OK)
+ {
+ OIC_LOG(ERROR, ENROLEE_SECURITY_TAG, "doOwnershipTransfer is failed");
+ return ESResult::ES_ERROR;
+ }
+
+ std::unique_lock<std::mutex> lck(m_mtx);
+ m_cond.wait(lck);
+
+ if(!otmResult)
{
- deviceId << base64Buff;
+ OIC_LOG(ERROR, ENROLEE_SECURITY_TAG, "Ownership-Transfer failed.");
+ return res;
}
- uuidString = deviceId.str();
+
+ return ESResult::ES_OK;
}
- void EnrolleeSecurity::convertStringToUUID(OicUuid_t& uuid,
- const std::string uuidString)
+#ifdef MULTIPLE_OWNER
+ ESResult EnrolleeSecurity::performMultipleOwnershipTransfer(const ESOwnershipTransferData& MOTdata)
{
- size_t outBufSize = B64DECODE_OUT_SAFESIZE((uuidString.length() + 1));
- uint8_t* outKey = (uint8_t*)OICCalloc(1, outBufSize);
- uint32_t outKeySize = 0;
- if(NULL == outKey)
+ OIC_LOG(DEBUG, ENROLEE_SECURITY_TAG, "performMultipleOwnershipTransfer IN.");
+
+ OCStackResult result = OC_STACK_ERROR;
+
+ OIC_LOG_V(INFO_PRIVATE, ENROLEE_SECURITY_TAG, "Transfering sub-ownership for : %s ",
+ m_securedResource->getDeviceID().c_str());
+
+ if(OIC_PRECONFIG_PIN == MOTdata.getMOTMethod() &&
+ !MOTdata.getPreConfiguredPin().empty())
{
- OIC_LOG (ERROR, ENROLEE_SECURITY_TAG, "Failed to memoray allocation.");
- throw ESBadRequestException ("Failed to memoray allocation.");
+ std::string pin = MOTdata.getPreConfiguredPin();
+
+ result = m_securedResource->addPreconfigPIN(pin.c_str(), pin.length());
+ if(OC_STACK_OK != result)
+ {
+ OIC_LOG(ERROR, ENROLEE_SECURITY_TAG, "addPreconfigPIN is failed");
+ return ESResult::ES_ERROR;
+ }
+
+ OIC_LOG_V(DEBUG, ENROLEE_SECURITY_TAG, "Preconfig PIN : %s", pin.c_str());
}
- if(B64_OK == b64Decode((char*)uuidString.c_str(),
- uuidString.length(),
- outKey,
- outBufSize,
- &outKeySize))
+ OC::ResultCallBack multipleOwnershipTransferCb =
+ std::bind(&EnrolleeSecurity::onEnrolleeSecuritySafetyCB,
+ std::placeholders::_1, std::placeholders::_2,
+ static_cast<ESSecurityCb>(std::bind(&EnrolleeSecurity::multipleOwnershipTransferCb,
+ this, std::placeholders::_1, std::placeholders::_2)),
+ shared_from_this());
+
+ OIC_LOG(DEBUG, ENROLEE_SECURITY_TAG, "doMultipleOwnershipTransfer is excuted");
+
+ result = m_securedResource->doMultipleOwnershipTransfer(multipleOwnershipTransferCb);
+ if(OC_STACK_OK != result)
{
- memcpy(uuid.id, outKey, outKeySize);
+ OIC_LOG(ERROR, ENROLEE_SECURITY_TAG, "doMultipleOwnershipTransfer is failed");
+ return ESResult::ES_ERROR;
}
- else
+
+ std::unique_lock<std::mutex> lck(m_mtx);
+ m_cond.wait(lck);
+
+ if(!otmResult)
{
- OIC_LOG (ERROR, ENROLEE_SECURITY_TAG, "Failed to base64 decoding.");
- throw ESBadRequestException ("Failed to base64 decoding.");
+ OIC_LOG(ERROR, ENROLEE_SECURITY_TAG, "Multiple Ownership-Transfer failed.");
+ return ESResult::ES_OWNERSHIP_TRANSFER_FAILURE;
}
- OICFree(outKey);
+ return ESResult::ES_OK;
}
+#endif
- void EnrolleeSecurity::ownershipTransferCb(OC::PMResultList_t *result, int hasError)
+ void EnrolleeSecurity::removeDeviceWithUuidCB(OC::PMResultList_t *result, int hasError)
{
+ OIC_LOG(DEBUG, ENROLEE_SECURITY_TAG, "removeDeviceWithUuidCB IN");
+
if (hasError)
{
- OIC_LOG(ERROR, ENROLEE_SECURITY_TAG,"Error!!! in OwnershipTransfer");
-
- std::string uuid;
- convertUUIDToString(result->at(0).deviceId, uuid);
- std::shared_ptr< SecProvisioningStatus > securityProvisioningStatus =
- std::make_shared< SecProvisioningStatus >(uuid, ES_ERROR);
- m_securityProvStatusCb(securityProvisioningStatus);
- return;
+ OIC_LOG_V(ERROR, ENROLEE_SECURITY_TAG, "removeDeviceWithUuid is failed with code (%d)", hasError);
+ removeDeviceResult = false;
}
+
else
{
- OIC_LOG(DEBUG, ENROLEE_SECURITY_TAG, "ownershipTransferCb : Received provisioning results: ");
- for (unsigned int i = 0; i < result->size(); i++)
- {
- OIC_LOG_V(DEBUG, ENROLEE_SECURITY_TAG, "Result is = %d for device",result->at(i).res);
- std::string uuid;
- convertUUIDToString(result->at(0).deviceId, uuid);
+ OIC_LOG(DEBUG, ENROLEE_SECURITY_TAG, "removeDeviceWithUuid is succeeded");
- OIC_LOG_V(DEBUG, ENROLEE_SECURITY_TAG, "UUID : %s",uuid.c_str());
- std::shared_ptr< SecProvisioningStatus > securityProvisioningStatus =
- std::make_shared< SecProvisioningStatus >(uuid, ES_OK);
- m_securityProvStatusCb(securityProvisioningStatus);
- return;
- }
+ for (unsigned int i = 0; i < result->size(); i++)
+ {
+ std::string uuid;
+ convertUUIDToString(result->at(i).deviceId.id, uuid);
- delete result;
+ OIC_LOG_V(DEBUG, ENROLEE_SECURITY_TAG, "Result is = %d", result->at(i).res);
+ OIC_LOG_V(INFO_PRIVATE, ENROLEE_SECURITY_TAG, "device uuid : %s", uuid.c_str());
+ }
+ removeDeviceResult = true;
}
+ m_cond.notify_all();
}
- void EnrolleeSecurity::performOwnershipTransfer()
+ bool EnrolleeSecurity::isOwnedDeviceRegisteredInDB()
{
- OC::DeviceList_t pUnownedDevList, pOwnedDevList;
+ OIC_LOG(DEBUG, ENROLEE_SECURITY_TAG, "isOwnedDeviceRegisteredInDB IN");
- pOwnedDevList.clear();
- pUnownedDevList.clear();
+ OCStackResult res = OC_STACK_ERROR;
- OCStackResult result = OC_STACK_ERROR;
+ OCUuidList_t *uuidList = NULL;
+ size_t numOfDevices = 0;
- result = OCSecure::discoverOwnedDevices(ES_SEC_DISCOVERY_TIMEOUT,
- pOwnedDevList);
- if (result != OC_STACK_OK)
+ res = PDMGetOwnedDevices(&uuidList, &numOfDevices);
+ if (OC_STACK_OK != res)
+ {
+ OIC_LOG(ERROR, ENROLEE_SECURITY_TAG, "Error while getting info from DB");
+ OICFree(uuidList);
+ return false;
+ }
+
+ OCUuidList_t *pUuidList = uuidList;
+ while (pUuidList)
{
- OIC_LOG(ERROR, ENROLEE_SECURITY_TAG, "Owned Discovery failed.");
- //Throw exception
- throw ESPlatformException(result);
+ std::string uuid;
+ convertUUIDToString(pUuidList->dev.id, uuid);
+ OIC_LOG_V(INFO_PRIVATE, ENROLEE_SECURITY_TAG,
+ "m_ocResource->sid(): %s, cur DB UUID %s",
+ m_ocResource->sid().c_str(), uuid.c_str());
+ if(m_ocResource->sid() == uuid.c_str())
+ {
+ OICFree(uuidList);
+ return true;
+ }
+ pUuidList = pUuidList->next;
}
- else if (pOwnedDevList.size())
+ OICFree(uuidList);
+ return false;
+ }
+
+
+ std::string EnrolleeSecurity::getUUID() const
+ {
+ return m_ocResource->sid();
+ };
+
+#if defined(__WITH_DTLS__) && defined(__WITH_TLS__)
+ ESResult EnrolleeSecurity::provisionSecurityForCloudServer(
+ std::string cloudUuid, int credId)
+ {
+ OIC_LOG(DEBUG, ENROLEE_SECURITY_TAG, "provisionSecurityForCloudServer IN");
+
+ ESResult res = ESResult::ES_ERROR;
+
+ // Need to discover Owned device in a given network, again
+ std::shared_ptr< OC::OCSecureResource > ownedDevice = NULL;
+
+ OCStackResult result = OC_STACK_ERROR;
+ OicUuid_t uuid;
+ if(OC_STACK_OK != ConvertStrToUuid(m_ocResource->sid().c_str(), &uuid))
{
- OIC_LOG_V(DEBUG, ENROLEE_SECURITY_TAG, "Found owned devices. Count =%d",
- pOwnedDevList.size());
- std::shared_ptr< OC::OCSecureResource > ownedDevice = getEnrollee(pOwnedDevList);
+ OIC_LOG(DEBUG, ENROLEE_SECURITY_TAG, "Convert to uuid from deviceID failed.");
+ return res;
+ }
- if (ownedDevice)
+ // If a discovered resource uses BLE transport, unicast for secure resource discovery is
+ // used.
+ if( m_ocResource->connectivityType() & CT_ADAPTER_GATT_BTLE )
+ {
+ std::string GattAddress = getResourceDeviceAddress(m_ocResource->host());
+ if(!GattAddress.empty())
+ {
+ result = OCSecure::discoverSingleDeviceInUnicast(ES_SEC_DISCOVERY_TIMEOUT,
+ &uuid,
+ GattAddress,
+ m_ocResource->connectivityType(),
+ ownedDevice);
+ }
+ else
{
- std::shared_ptr< SecProvisioningStatus > securityProvisioningStatus =
- std::make_shared< SecProvisioningStatus >(ownedDevice->getDeviceID(), ES_OK);
- m_securityProvStatusCb(securityProvisioningStatus);
- return;
+ OIC_LOG(ERROR, ENROLEE_SECURITY_TAG, "GATT BTLE address format is wrong.");
+ res = ESResult:: ES_ERROR;
+ return res;
}
}
+ else
+ {
+ result = OCSecure::discoverSingleDevice(ES_SEC_DISCOVERY_TIMEOUT,
+ &uuid,
+ ownedDevice);
+ }
- result = OCSecure::discoverUnownedDevices(ES_SEC_DISCOVERY_TIMEOUT, pUnownedDevList);
if (result != OC_STACK_OK)
{
- OIC_LOG(ERROR, ENROLEE_SECURITY_TAG, "UnOwned Discovery failed.");
- //Throw exception
- throw ESPlatformException(result);
+ OIC_LOG(ERROR, ENROLEE_SECURITY_TAG, "secureResource Discovery failed.");
+ res = ESResult::ES_SECURE_RESOURCE_DISCOVERY_FAILURE;
+ return res;
}
- else if (pUnownedDevList.size())
+ else if (ownedDevice)
{
- OIC_LOG_V(DEBUG, ENROLEE_SECURITY_TAG, "Found Unowned devices. Count =%d",
- pUnownedDevList.size());
+ OIC_LOG(DEBUG, ENROLEE_SECURITY_TAG, "Secured resource is found.");
+ OIC_LOG_V(DEBUG, ENROLEE_SECURITY_TAG, "HOST: %s", ownedDevice->getDevAddr().c_str());
+ OIC_LOG_V(INFO_PRIVATE, ENROLEE_SECURITY_TAG, "SID: %s", ownedDevice->getDeviceID().c_str());
+ OIC_LOG_V(DEBUG, ENROLEE_SECURITY_TAG, "Owned status: %d", ownedDevice->getOwnedStatus());
- m_unownedDevice = getEnrollee(pUnownedDevList);
- if (m_unownedDevice)
+ if (ownedDevice->getOwnedStatus())
{
- OTMCallbackData_t justWorksCBData;
- justWorksCBData.loadSecretCB = LoadSecretJustWorksCallback;
- justWorksCBData.createSecureSessionCB = CreateSecureSessionJustWorksCallback;
- justWorksCBData.createSelectOxmPayloadCB = CreateJustWorksSelectOxmPayload;
- justWorksCBData.createOwnerTransferPayloadCB =
- CreateJustWorksOwnerTransferPayload;
- OCSecure::setOwnerTransferCallbackData(OIC_JUST_WORKS, &justWorksCBData, NULL);
-
- OIC_LOG_V(DEBUG, ENROLEE_SECURITY_TAG, "Transfering ownership for : %s ",
- m_unownedDevice->getDeviceID().c_str());
-
- OC::ResultCallBack ownershipTransferCb = std::bind(
- &EnrolleeSecurity::ownershipTransferCb, this, std::placeholders::_1,
- std::placeholders::_2);
-
- result = m_unownedDevice->doOwnershipTransfer(ownershipTransferCb);
- if (result != OC_STACK_OK)
+ if(!isOwnedDeviceRegisteredInDB())
{
- OIC_LOG(ERROR, ENROLEE_SECURITY_TAG, "OwnershipTransferCallback is failed");
- throw ESPlatformException(result);
+ OIC_LOG(ERROR, ENROLEE_SECURITY_TAG, "The found device is not one in SVR DB");
+ res = ESResult::ES_SECURE_RESOURCE_DISCOVERY_FAILURE;
+ return res;
}
}
else
{
- OIC_LOG(ERROR, ENROLEE_SECURITY_TAG, "No matched unowned devices found.");
- throw ESException("No matched unowned devices found.");
+ OIC_LOG(ERROR, ENROLEE_SECURITY_TAG, "The found device is unowned.");
+ OIC_LOG(ERROR, ENROLEE_SECURITY_TAG, "Ownerthip transfer is required.");
+
+ res = ESResult::ES_SECURE_RESOURCE_DISCOVERY_FAILURE;
+ return res;
+ }
+ }
+ else
+ {
+ OIC_LOG(ERROR, ENROLEE_SECURITY_TAG, "No secure resource is found");
+ res = ESResult::ES_SECURE_RESOURCE_DISCOVERY_FAILURE;
+ return res;
+ }
+
+ if(cloudUuid.empty())
+ {
+ OIC_LOG(ERROR, ENROLEE_SECURITY_TAG,
+ "ACL provisioning is skipped due to empty UUID of cloud server");
+ }
+ else
+ {
+ res = performACLProvisioningForCloudServer(ownedDevice, cloudUuid);
+ if(res != ESResult::ES_OK)
+ {
+ OIC_LOG(ERROR, ENROLEE_SECURITY_TAG, "error performACLProvisioningForCloudServer");
+ return res;
}
}
+
+ if(credId < 1)
+ {
+ OIC_LOG(ERROR, ENROLEE_SECURITY_TAG,
+ "Cert. provisioning is skipped due to wrong cred ID (<1)");
+ }
else
{
- OIC_LOG(ERROR, ENROLEE_SECURITY_TAG, "No unowned devices found.");
- throw ESException("No unowned devices found.");
+ res = performCertProvisioningForCloudServer(ownedDevice, credId);
+ if(res != ESResult::ES_OK)
+ {
+ OIC_LOG(ERROR, ENROLEE_SECURITY_TAG, "error performCertProvisioningForCloudServer");
+ return res;
+ }
}
+
+ return res;
}
- ESResult EnrolleeSecurity::performACLProvisioningForCloudServer(std::string cloudUuid)
+ ESResult EnrolleeSecurity::performCertProvisioningForCloudServer(
+ std::shared_ptr< OC::OCSecureResource > ownedDevice, int credId)
{
- ESResult res = ESResult::ES_ERROR;
+ OIC_LOG(DEBUG, ENROLEE_SECURITY_TAG, "performCertProvisioningForCloudServer IN");
- OicUuid_t uuid;
- convertStringToUUID(uuid, cloudUuid);
+ ESResult res = ESResult::ES_CERT_PROVISIONING_FAILURE;
- // Need to discover Owned device in a given network, again
- OC::DeviceList_t pOwnedDevList;
- std::shared_ptr< OC::OCSecureResource > ownedDevice = NULL;
+ if(!ownedDevice)
+ {
+ OIC_LOG(ERROR, ENROLEE_SECURITY_TAG, "Given ownedDevice is null");
+ return res;
+ }
- pOwnedDevList.clear();
+ OIC_LOG_V(DEBUG, ENROLEE_SECURITY_TAG, "Given CredId: %d", credId);
- OCStackResult result;
+ OC::ResultCallBack CertProvisioningCb =
+ std::bind(&EnrolleeSecurity::onEnrolleeSecuritySafetyCB,
+ std::placeholders::_1, std::placeholders::_2,
+ static_cast<ESSecurityCb>(std::bind(&EnrolleeSecurity::certProvisioningCb,
+ this, std::placeholders::_1, std::placeholders::_2)),
+ shared_from_this());
- result = OCSecure::discoverOwnedDevices(ES_SEC_DISCOVERY_TIMEOUT,
- pOwnedDevList);
- if (result != OC_STACK_OK)
+ OCStackResult rst = ownedDevice->provisionTrustCertChain(SIGNED_ASYMMETRIC_KEY,
+ static_cast<uint16_t>(credId),
+ CertProvisioningCb);
+ if(OC_STACK_OK != rst)
{
- OIC_LOG(ERROR, ENROLEE_SECURITY_TAG, "Owned Discovery failed.");
- //Throw exception
- throw ESPlatformException(result);
+ OIC_LOG_V(ERROR, ENROLEE_SECURITY_TAG, "provisionTrustCertChain error: %d", rst);
+ return res;
}
- else if (pOwnedDevList.size())
+
+ std::unique_lock<std::mutex> lck(m_mtx);
+ m_cond.wait(lck);
+
+ if(certResult)
{
- OIC_LOG_V(DEBUG, ENROLEE_SECURITY_TAG, "Found owned devices. Count =%d",
- pOwnedDevList.size());
- ownedDevice = getEnrollee(pOwnedDevList);
+ res = ESResult::ES_OK;
+ }
- if (!ownedDevice)
- {
- OIC_LOG(DEBUG, ENROLEE_SECURITY_TAG, "Not found owned devices.");
- return res;
- }
+ return res;
+ }
+
+ ESResult EnrolleeSecurity::performACLProvisioningForCloudServer(
+ std::shared_ptr< OC::OCSecureResource > ownedDevice, std::string& cloudUuid)
+ {
+ OIC_LOG(DEBUG, ENROLEE_SECURITY_TAG, "performACLProvisioningForCloudServer IN");
+
+ ESResult res = ESResult::ES_ACL_PROVISIONING_FAILURE;
+
+ if(!ownedDevice)
+ {
+ OIC_LOG(ERROR, ENROLEE_SECURITY_TAG, "Given ownedDevice is null");
+ return res;
}
- else
+
+ OIC_LOG_V(INFO_PRIVATE, ENROLEE_SECURITY_TAG, "Given cloudUuid: %s", cloudUuid.c_str());
+
+ OicUuid_t uuid;
+ if(OC_STACK_OK != ConvertStrToUuid(cloudUuid.c_str(), &uuid))
{
- OIC_LOG(DEBUG, ENROLEE_SECURITY_TAG, "Not found owned devices.");
+ OIC_LOG(DEBUG, ENROLEE_SECURITY_TAG, "Convert to uuid from deviceID failed.");
return res;
}
+
// Create Acl for Cloud Server to be provisioned to Enrollee
OicSecAcl_t* acl = createAcl(uuid);
if(!acl)
return res;
}
- OC::ResultCallBack aclProvisioningCb = std::bind(
- &EnrolleeSecurity::ACLProvisioningCb, this, std::placeholders::_1,
- std::placeholders::_2);
+ OC::ResultCallBack aclProvisioningCb =
+ std::bind(&EnrolleeSecurity::onEnrolleeSecuritySafetyCB,
+ std::placeholders::_1, std::placeholders::_2,
+ static_cast<ESSecurityCb>(std::bind(&EnrolleeSecurity::aclProvisioningCb,
+ this, std::placeholders::_1, std::placeholders::_2)),
+ shared_from_this());
+
// ACL provisioning to Enrollee
OCStackResult rst = ownedDevice->provisionACL(acl, aclProvisioningCb);
if(OC_STACK_OK != rst)
}
std::unique_lock<std::mutex> lck(m_mtx);
- m_cond.wait_for(lck, std::chrono::seconds(ES_SEC_DISCOVERY_TIMEOUT));
+ m_cond.wait(lck);
if(aclResult)
{
res = ESResult::ES_OK;
}
-
+ OCDeleteACLList(acl);
return res;
}
- std::string EnrolleeSecurity::getUUID() const
- {
- return m_ocResource->sid();
- };
-
OicSecAcl_t* EnrolleeSecurity::createAcl(const OicUuid_t cloudUuid)
{
+ OIC_LOG(DEBUG, ENROLEE_SECURITY_TAG, "creatAcl IN");
+
// allocate memory for |acl| struct
OicSecAcl_t* acl = (OicSecAcl_t*) OICCalloc(1, sizeof(OicSecAcl_t));
if(!acl)
{
- OIC_LOG(DEBUG, ENROLEE_SECURITY_TAG, "createAcl: OICCalloc error return");
+ OIC_LOG(ERROR, ENROLEE_SECURITY_TAG, "createAcl: OICCalloc error return");
return NULL; // not need to 'goto' |ERROR| before allocating |acl|
}
OicSecAce_t* ace = (OicSecAce_t*) OICCalloc(1, sizeof(OicSecAce_t));
if(!ace)
{
- OIC_LOG(DEBUG, ENROLEE_SECURITY_TAG, "createAcl: OICCalloc error return");
+ OIC_LOG(ERROR, ENROLEE_SECURITY_TAG, "createAcl: OICCalloc error return");
return NULL; // not need to 'goto' |ERROR| before allocating |acl|
}
LL_APPEND(acl->aces, ace);
OicSecRsrc_t* rsrc = (OicSecRsrc_t*)OICCalloc(1, sizeof(OicSecRsrc_t));
if(!rsrc)
{
- OIC_LOG(DEBUG, ENROLEE_SECURITY_TAG, "createAcl: OICCalloc error return");
+ OIC_LOG(ERROR, ENROLEE_SECURITY_TAG, "createAcl: OICCalloc error return");
OCDeleteACLList(acl);
return NULL;
}
rsrc->href = (char*) OICCalloc(len, sizeof(char));
if(!rsrc->href)
{
- OIC_LOG(DEBUG, ENROLEE_SECURITY_TAG, "createAcl: OICCalloc error return");
+ OIC_LOG(ERROR, ENROLEE_SECURITY_TAG, "createAcl: OICCalloc error return");
+ FreeRsrc(rsrc);
OCDeleteACLList(acl);
return NULL;
}
size_t arrLen = 1;
rsrc->typeLen = arrLen;
rsrc->types = (char**)OICCalloc(arrLen, sizeof(char*));
- rsrc->interfaces = (char**)OICCalloc(arrLen, sizeof(char*));
+ if(!rsrc->types)
+ {
+ OIC_LOG(ERROR, ENROLEE_SECURITY_TAG, "createAcl: OICCalloc error return");
+ FreeRsrc(rsrc);
+ OCDeleteACLList(acl);
+ return NULL;
+ }
rsrc->types[0] = OICStrdup("rt"); // ignore
+ if(!rsrc->types[0])
+ {
+ OIC_LOG(ERROR, ENROLEE_SECURITY_TAG, "createAcl: OICStrdup error return");
+ FreeRsrc(rsrc);
+ OCDeleteACLList(acl);
+ return NULL;
+ }
+
+ rsrc->interfaceLen = 1;
+ rsrc->interfaces = (char**)OICCalloc(arrLen, sizeof(char*));
+ if(!rsrc->interfaces)
+ {
+ OIC_LOG(ERROR, ENROLEE_SECURITY_TAG, "createAcl: OICCalloc error return");
+ FreeRsrc(rsrc);
+ OCDeleteACLList(acl);
+ return NULL;
+ }
rsrc->interfaces[0] = OICStrdup("if"); // ignore
+ if(!rsrc->interfaces[0])
+ {
+ OIC_LOG(ERROR, ENROLEE_SECURITY_TAG, "createAcl: OICStrdup error return");
+ FreeRsrc(rsrc);
+ OCDeleteACLList(acl);
+ return NULL;
+ }
LL_APPEND(ace->resources, rsrc);
ace->permission = 31; // R/W/U/D
+ OIC_LOG(DEBUG, ENROLEE_SECURITY_TAG, "creatAcl OUT");
+
return acl;
}
- void EnrolleeSecurity::ACLProvisioningCb(PMResultList_t *result, int hasError)
+ void EnrolleeSecurity::aclProvisioningCb(PMResultList_t *result, int hasError)
{
+ OIC_LOG(DEBUG, ENROLEE_SECURITY_TAG, "aclProvisioningCb IN");
+
if (hasError)
{
- OIC_LOG(DEBUG, ENROLEE_SECURITY_TAG, "Error in provisioning operation!");
+ OIC_LOG_V(ERROR, ENROLEE_SECURITY_TAG, "ACL provisioning is failed with code (%d)", hasError);
aclResult = false;
}
else
{
- OIC_LOG(DEBUG, ENROLEE_SECURITY_TAG, "Received provisioning results: ");
+ OIC_LOG(DEBUG, ENROLEE_SECURITY_TAG, "Received ACL provisioning results: ");
std::string devUuid;
for (unsigned int i = 0; i < result->size(); i++)
{
- convertUUIDToString(result->at(i).deviceId, devUuid);
- OIC_LOG_V(DEBUG, ENROLEE_SECURITY_TAG, "Result is = %d for device %s",
- result->at(i).res, devUuid.c_str());
+ convertUUIDToString(result->at(i).deviceId.id, devUuid);
+
+ OIC_LOG_V(DEBUG, ENROLEE_SECURITY_TAG, "Result is = %d", result->at(i).res);
+ OIC_LOG_V(INFO_PRIVATE, ENROLEE_SECURITY_TAG, "device uuid : %s", devUuid.c_str());
}
delete result;
aclResult = true;
}
m_cond.notify_all();
}
+
+ void EnrolleeSecurity::certProvisioningCb(PMResultList_t *result, int hasError)
+ {
+ OIC_LOG(DEBUG, ENROLEE_SECURITY_TAG, "certProvisioningCb IN");
+
+ if (hasError)
+ {
+ OIC_LOG_V(ERROR, ENROLEE_SECURITY_TAG, "Cert provisioning is failed with code (%d)", hasError);
+ certResult = false;
+ }
+ else
+ {
+ OIC_LOG(DEBUG, ENROLEE_SECURITY_TAG, "Received Cert. provisioning results: ");
+
+ std::string devUuid;
+ for (unsigned int i = 0; i < result->size(); i++)
+ {
+ convertUUIDToString(result->at(i).deviceId.id, devUuid);
+
+ OIC_LOG_V(DEBUG, ENROLEE_SECURITY_TAG, "Result is = %d", result->at(i).res);
+ OIC_LOG_V(INFO_PRIVATE, ENROLEE_SECURITY_TAG, "device uuid : %s", devUuid.c_str());
+ }
+ delete result;
+ certResult= true;
+ }
+ m_cond.notify_all();
+ }
+#endif //defined(__WITH_DTLS__) && defined(__WITH_TLS__)
}
}