#include <strings.h>
#endif
-#ifdef __WITH_DTLS__
-#include "global.h"
-#endif
-
#include "ocstack.h"
#include "oic_malloc.h"
#include "payload_logging.h"
#include "credresource.h"
#include "srmutility.h"
#include "pinoxmcommon.h"
+#include "oxmverifycommon.h"
+#include "octhread.h"
+
+#if defined(__WITH_DTLS__) || defined (__WITH_TLS__)
+#include "pkix_interface.h"
+#include "ca_adapter_net_ssl.h"
+#endif
-#define TAG "SRM-DOXM"
+#define TAG "OIC_SRM_DOXM"
#define CHAR_ZERO ('0')
/** Default cbor payload size. This value is increased in case of CborErrorOutOfMemory.
/** Max cbor size payload. */
static const uint16_t CBOR_MAX_SIZE = 4400;
+#if defined(__WITH_DTLS__) || defined (__WITH_TLS__)
+/** MAX uuid seed size */
+#define MAX_UUID_SEED_SIZE (64)
+/** MIN uuid seed size */
+#define MIN_UUID_SEED_SIZE (8)
+
+/** Buffer to save the seed of device UUID */
+static uint8_t gUuidSeed[MAX_UUID_SEED_SIZE];
+static size_t gUuidSeedSize = 0;
+#endif
+
+#ifdef MULTIPLE_OWNER
+#define MAX_SUBOWNER_SIZE (64)
+#define MIN_SUBOWNER_SIZE (1)
+#define DEFAULT_SUBOWNER_SIZE (32)
+
+static size_t gMaxSubOwnerSize = DEFAULT_SUBOWNER_SIZE;
+#endif
+
+typedef enum ConfirmState{
+ CONFIRM_STATE_READY = 0,
+ CONFIRM_STATE_WAIT = 1,
+ CONFIRM_STATE_ACCEPTED = 2,
+ CONFIRM_STATE_DENIED = 3
+}ConfirmState_t;
+
static OicSecDoxm_t *gDoxm = NULL;
+static oc_mutex g_mutexDoxm = NULL;
+static bool g_isDoxmNull = false;
static OCResourceHandle gDoxmHandle = NULL;
static OicSecOxm_t gOicSecDoxmJustWorks = OIC_JUST_WORKS;
{.id = {0}}, /* OicUuid_t deviceID */
false, /* bool dpc */
{.id = {0}}, /* OicUuid_t owner */
-#ifdef _ENABLE_MULTIPLE_OWNER_
+#ifdef MULTIPLE_OWNER
NULL, /* OicSecSubOwner_t sub-owner list */
NULL, /* OicSecMomType_t multiple owner mode */
-#endif //_ENABLE_MULTIPLE_OWNER_
+#endif //MULTIPLE_OWNER
{.id = {0}}, /* OicUuid_t rownerID */
};
+static uint16_t gConfirmMsgId = 0;
+static ConfirmState_t gConfirmState = CONFIRM_STATE_READY;
+
+static uint8_t gEmptyUuid[UUID_LENGTH] = {0};
+
/**
* This method is internal method.
* the param roParsed is optionally used to know whether cborPayload has
//clean oxm
OICFree(doxm->oxm);
-#ifdef _ENABLE_MULTIPLE_OWNER_
+#ifdef MULTIPLE_OWNER
//clean mom
OICFree(doxm->mom);
OICFree(subowner);
}
}
-#endif //_ENABLE_MULTIPLE_OWNER_
+#endif //MULTIPLE_OWNER
//Clean doxm itself
OICFree(doxm);
}
+
+ if(g_mutexDoxm)
+ {
+ oc_mutex_free(g_mutexDoxm);
+ g_mutexDoxm = NULL;
+ }
}
OCStackResult DoxmToCBORPayload(const OicSecDoxm_t *doxm, uint8_t **payload, size_t *size,
strUuid = NULL;
}
-#ifdef _ENABLE_MULTIPLE_OWNER_
+#ifdef MULTIPLE_OWNER
//Device SubOwnerID -- Not Mandatory
if(doxm->subOwners)
{
cborEncoderResult = cbor_encode_int(&doxmMap, (int64_t)doxm->mom->mode);
VERIFY_CBOR_SUCCESS(TAG, cborEncoderResult, "Failed Adding mom Value.");
}
-#endif //_ENABLE_MULTIPLE_OWNER_
+#endif //MULTIPLE_OWNER
//devownerid -- Mandatory
cborEncoderResult = cbor_encode_text_string(&doxmMap, OIC_JSON_DEVOWNERID_NAME,
OICFree(strUuid);
strUuid = NULL;
- //x.org.iotivity.dpc -- not Mandatory(vendor-specific), but this type is boolean, so instance always has a value.
- cborEncoderResult = cbor_encode_text_string(&doxmMap, OIC_JSON_DPC_NAME,
- strlen(OIC_JSON_DPC_NAME));
- VERIFY_CBOR_SUCCESS(TAG, cborEncoderResult, "Failed Adding DPC Tag.");
- cborEncoderResult = cbor_encode_boolean(&doxmMap, doxm->dpc);
- VERIFY_CBOR_SUCCESS(TAG, cborEncoderResult, "Failed Adding DPC Value.");
-
//RT -- Mandatory
CborEncoder rtArray;
cborEncoderResult = cbor_encode_text_string(&doxmMap, OIC_JSON_RT_NAME,
if (CborNoError == cborEncoderResult)
{
- *size = encoder.ptr - outPayload;
+ *size = cbor_encoder_get_buffer_size(&encoder, outPayload);
*payload = outPayload;
ret = OC_STACK_OK;
}
OIC_LOG(DEBUG, TAG, "Memory getting reallocated.");
// reallocate and try again!
OICFree(outPayload);
+ outPayload = NULL;
// Since the allocated initial memory failed, double the memory.
- cborLen += encoder.ptr - encoder.end;
+ cborLen += cbor_encoder_get_buffer_size(&encoder, encoder.end);
OIC_LOG_V(DEBUG, TAG, "Doxm reallocation size : %zd.", cborLen);
cborEncoderResult = CborNoError;
ret = DoxmToCBORPayload(doxm, payload, &cborLen, rwOnly);
doxm->owned = gDoxm->owned;
}
- cborFindResult = cbor_value_map_find_value(&doxmCbor, OIC_JSON_DPC_NAME, &doxmMap);
- if (CborNoError == cborFindResult && cbor_value_is_boolean(&doxmMap))
- {
- cborFindResult = cbor_value_get_boolean(&doxmMap, &doxm->dpc);
- VERIFY_CBOR_SUCCESS(TAG, cborFindResult, "Failed Finding DPC Value.")
- }
- else // PUT/POST JSON may not have dpc so set it to the gDomx->dpc
- {
- VERIFY_NON_NULL(TAG, gDoxm, ERROR);
- doxm->dpc = gDoxm->dpc;
- }
-
cborFindResult = cbor_value_map_find_value(&doxmCbor, OIC_JSON_DEVICE_ID_NAME, &doxmMap);
if (CborNoError == cborFindResult && cbor_value_is_text_string(&doxmMap))
{
VERIFY_SUCCESS(TAG, OC_STACK_OK == ret, ERROR);
OICFree(strUuid);
strUuid = NULL;
-
- if (roParsed)
- {
- *roParsed = true;
- }
}
else
{
memcpy(doxm->owner.id, gDoxm->owner.id, sizeof(doxm->owner.id));
}
-#ifdef _ENABLE_MULTIPLE_OWNER_
+#ifdef MULTIPLE_OWNER
cborFindResult = cbor_value_map_find_value(&doxmCbor, OIC_JSON_MOM_NAME, &doxmMap);
if(CborNoError == cborFindResult && cbor_value_is_integer(&doxmMap))
{
LL_APPEND(doxm->subOwners, subOwnerId);
}
}
-#endif //_ENABLE_MULTIPLE_OWNER_
+#endif //MULTIPLE_OWNER
cborFindResult = cbor_value_map_find_value(&doxmCbor, OIC_JSON_ROWNERID_NAME, &doxmMap);
if (CborNoError == cborFindResult && cbor_value_is_text_string(&doxmMap))
bool bDeviceIDMatch = false; // does 'deviceid' query matches with doxm.deviceid ?
bool bInterfaceQry = false; // does querystring contains 'if' query ?
bool bInterfaceMatch = false; // does 'if' query matches with oic.if.baseline ?
-#ifdef _ENABLE_MULTIPLE_OWNER_
- bool bMotQry = false; // does querystring contains 'mom' and 'owned' query ?
+#ifdef MULTIPLE_OWNER
bool bMotMatch = false; // does 'mom' query value is not '0' && does query value matches with doxm.owned status?
-#endif //_ENABLE_MULTIPLE_OWNER_
+#endif //MULTIPLE_OWNER
OicParseQueryIter_t parseIter = {.attrPos = NULL};
}
}
-#ifdef _ENABLE_MULTIPLE_OWNER_
+#ifdef MULTIPLE_OWNER
if (strncasecmp((char *)parseIter.attrPos, OIC_JSON_MOM_NAME, strlen(OIC_JSON_MOM_NAME)) == 0)
{
- bMotQry = true;
OicSecMomType_t momMode = (OicSecMomType_t)(parseIter.valPos[0] - CHAR_ZERO);
if(NULL != gDoxm->mom && momMode != gDoxm->mom->mode)
{
}
return bMotMatch;
}
-#endif //_ENABLE_MULTIPLE_OWNER_
+#endif //MULTIPLE_OWNER
if (strncasecmp((char *)parseIter.attrPos, OIC_JSON_DEVICE_ID_NAME, parseIter.attrLen) == 0)
{
}
}
-#ifdef _ENABLE_MULTIPLE_OWNER_
- return ((bOwnedQry ? bOwnedMatch : true) &&
- (bDeviceIDQry ? bDeviceIDMatch : true) &&
- (bMotQry ? bMotMatch : true));
-#else
return ((bOwnedQry ? bOwnedMatch : true) &&
(bDeviceIDQry ? bDeviceIDMatch : true));
-#endif //_ENABLE_MULTIPLE_OWNER_
}
static OCEntityHandlerResult HandleDoxmGetRequest (const OCEntityHandlerRequest * ehRequest)
//update rowner
memcpy(&(dst->rownerID), &(src->rownerID), sizeof(OicUuid_t));
+ //update deviceuuid
+ memcpy(&(dst->deviceID), &(src->deviceID), sizeof(OicUuid_t));
+
//Update owned status
if(dst->owned != src->owned)
{
dst->owned = src->owned;
}
- //update oxms
- if(0 < src->oxmLen)
- {
- OicSecOxm_t* tempOxm = (OicSecOxm_t*)OICMalloc(sizeof(OicSecOxm_t) * src->oxmLen);
- if(NULL != tempOxm)
- {
- for(size_t i = 0; i < src->oxmLen; i++)
- {
- tempOxm[i] = src->oxm[i];
- }
- OICFree(dst->oxm);
-
- dst->oxm = tempOxm;
- dst->oxmLen = src->oxmLen;
- }
- }
-
-#ifdef _ENABLE_MULTIPLE_OWNER_
+#ifdef MULTIPLE_OWNER
if(src->mom)
{
OIC_LOG(DEBUG, TAG, "dectected 'mom' property");
}
}
}
-#endif //_ENABLE_MULTIPLE_OWNER_
+#endif //MULTIPLE_OWNER
}
}
#if defined(__WITH_DTLS__) || defined (__WITH_TLS__)
-#ifdef _ENABLE_MULTIPLE_OWNER_
+#ifdef MULTIPLE_OWNER
+/**
+ * Internal function to get number of sub-owner
+ */
+static size_t GetSubOwnerSize()
+{
+ OIC_LOG_V(DEBUG, TAG, "In %s", __func__);
+
+ size_t numberOfSubOwner = 0;
+
+ if (gDoxm && gDoxm->subOwners)
+ {
+ OicSecSubOwner_t* subowner = NULL;
+ LL_FOREACH(gDoxm->subOwners, subowner)
+ {
+ numberOfSubOwner++;
+ }
+ }
+
+ OIC_LOG_V(DEBUG, TAG, "Numer of registered sub-owner=%d", numberOfSubOwner);
+ OIC_LOG_V(DEBUG, TAG, "Out %s", __func__);
+
+ return numberOfSubOwner;
+}
+
/**
* Callback function to handle MOT DTLS handshake result.
- * @param[out] object remote device information.
+ * @param[out] endpoint remote device information.
* @param[out] errorInfo CA Error information.
*/
-void MultipleOwnerDTLSHandshakeCB(const CAEndpoint_t *object,
+void MultipleOwnerDTLSHandshakeCB(const CAEndpoint_t *endpoint,
const CAErrorInfo_t *errorInfo)
{
- OIC_LOG(DEBUG, TAG, "IN MultipleOwnerDTLSHandshakeCB");
+ OIC_LOG_V(DEBUG, TAG, "In %s", __func__);
+ if (!endpoint || !errorInfo)
+ {
+ OIC_LOG(ERROR, TAG, "Invalid param");
+ return;
+ }
- if(CA_STATUS_OK == errorInfo->result)
+ if (!gDoxm)
{
- const CASecureEndpoint_t* authenticatedSubOwnerInfo = CAGetSecureEndpointData(object);
- if(authenticatedSubOwnerInfo)
+ OIC_LOG_V(ERROR, TAG, "%s: gDoxm is NULL", __func__);
+ return;
+ }
+
+ if ((CA_STATUS_OK == errorInfo->result) && (true == gDoxm->owned)
+ && (OIC_PRECONFIG_PIN == gDoxm->oxmSel) && (NULL != gDoxm->mom)
+ && (OIC_MULTIPLE_OWNER_DISABLE != gDoxm->mom->mode) && (CA_ADAPTER_TCP != endpoint->adapter))
+ {
+ OIC_LOG_V(INFO, TAG, "DTLS session established for sub-owner authentication : (%s:%d)",
+ endpoint->addr, endpoint->port);
+
+ const CASecureEndpoint_t* authenticatedSubOwnerInfo = CAGetSecureEndpointData(endpoint);
+ if (authenticatedSubOwnerInfo)
{
- OicSecSubOwner_t* subOwnerInst = (OicSecSubOwner_t*)OICMalloc(sizeof(OicSecSubOwner_t));
- if(subOwnerInst)
+ if (0 == memcmp(authenticatedSubOwnerInfo->identity.id, gDoxm->owner.id,
+ authenticatedSubOwnerInfo->identity.id_length))
{
- OIC_LOG(DEBUG, TAG, "Adding New SubOwner");
- memcpy(subOwnerInst->uuid.id, authenticatedSubOwnerInfo->identity.id, authenticatedSubOwnerInfo->identity.id_length);
- LL_APPEND(gDoxm->subOwners, subOwnerInst);
- if(!UpdatePersistentStorage(gDoxm))
+ OIC_LOG(WARNING, TAG, "Super owner tried MOT, this request will be ignored.");
+ return;
+ }
+
+ OicSecSubOwner_t* subOwnerInst = NULL;
+ LL_FOREACH(gDoxm->subOwners, subOwnerInst)
+ {
+ if(0 == memcmp(subOwnerInst->uuid.id,
+ authenticatedSubOwnerInfo->identity.id,
+ authenticatedSubOwnerInfo->identity.id_length))
{
- OIC_LOG(ERROR, TAG, "Failed to register SubOwner UUID into Doxm");
+ break;
+ }
+ }
+
+ if (NULL == subOwnerInst)
+ {
+ subOwnerInst = (OicSecSubOwner_t*)OICCalloc(1, sizeof(OicSecSubOwner_t));
+ if (subOwnerInst)
+ {
+ char* strUuid = NULL;
+ if (OC_STACK_OK != ConvertUuidToStr(&subOwnerInst->uuid, &strUuid))
+ {
+ OIC_LOG(WARNING, TAG, "ConvertUuidToStr error");
+ }
+ OIC_LOG_V(DEBUG, TAG, "Adding New SubOwner(%s)", strUuid);
+
+ if (gMaxSubOwnerSize > GetSubOwnerSize())
+ {
+ memcpy(subOwnerInst->uuid.id, authenticatedSubOwnerInfo->identity.id,
+ authenticatedSubOwnerInfo->identity.id_length);
+ LL_APPEND(gDoxm->subOwners, subOwnerInst);
+ if (!UpdatePersistentStorage(gDoxm))
+ {
+ OIC_LOG(ERROR, TAG, "Failed to register SubOwner UUID into Doxm");
+ }
+ }
+ else
+ {
+ OIC_LOG_V(ERROR, TAG, "Number of sub-owner exceeded : (MAX SIZE=%d)", gMaxSubOwnerSize);
+
+ //Close DTLS session
+ if (CA_STATUS_OK != CAcloseSslSession(endpoint))
+ {
+ OIC_LOG_V(ERROR, TAG, "CAcloseSslSession error for [%s:%d]", endpoint->addr, endpoint->port);
+ }
+
+ //Remove credential
+ if (OC_STACK_RESOURCE_DELETED != RemoveCredential(&subOwnerInst->uuid))
+ {
+ OIC_LOG_V(ERROR, TAG, "RemoveCredential error for [%s]", strUuid);
+ }
+
+ // TODO: How to send error to client side?
+ }
+
+ OICFree(strUuid);
}
}
}
OIC_LOG(WARNING, TAG, "Failed to revert the DTLS credential handler");
}
- OIC_LOG(DEBUG, TAG, "OUT MultipleOwnerDTLSHandshakeCB");
+ OIC_LOG_V(DEBUG, TAG, "Out %s", __func__);
}
-#endif //_ENABLE_MULTIPLE_OWNER_
+#endif //MULTIPLE_OWNER
#endif // defined(__WITH_DTLS__) || defined (__WITH_TLS__)
-static OCEntityHandlerResult HandleDoxmPostRequest(const OCEntityHandlerRequest * ehRequest)
+/**
+ * Function to validate oxmsel with oxms.
+ *
+ * @param[in] supportedMethods Array of supported methods
+ * @param[in] numberOfMethods number of supported methods
+ * @param[out] selectedMethod Selected methods
+ * @return TRUE on success
+ */
+static bool ValidateOxmsel(const OicSecOxm_t *supportedMethods,
+ size_t numberOfMethods, OicSecOxm_t *selectedMethod)
+{
+ bool isValidOxmsel = false;
+
+ OIC_LOG(DEBUG, TAG, "IN ValidateOxmsel");
+ if (numberOfMethods == 0 || !supportedMethods)
+ {
+ OIC_LOG(WARNING, TAG, "Could not find a supported OxM.");
+ return isValidOxmsel;
+ }
+
+ for (size_t i = 0; i < numberOfMethods; i++)
+ {
+ if (*selectedMethod == supportedMethods[i])
+ {
+ isValidOxmsel = true;
+ break;
+ }
+ }
+ if (!isValidOxmsel)
+ {
+ OIC_LOG(ERROR, TAG, "Not allowed Oxmsel.");
+ return isValidOxmsel;
+ }
+
+ OIC_LOG(DEBUG, TAG, "OUT ValidateOxmsel");
+
+ return isValidOxmsel;
+}
+
+static OCEntityHandlerResult HandleDoxmPostRequest(OCEntityHandlerRequest * ehRequest)
{
OIC_LOG (DEBUG, TAG, "Doxm EntityHandle processing POST request");
OCEntityHandlerResult ehRet = OC_EH_ERROR;
OicUuid_t emptyOwner = {.id = {0} };
static uint16_t previousMsgId = 0;
+ bool isDuplicatedMsg = false;
/*
* Convert CBOR Doxm data into binary. This will also validate
OCStackResult res = CBORPayloadToDoxmBin(payload, size, &newDoxm, &roParsed);
if (newDoxm && OC_STACK_OK == res)
{
+ /*
+ * message ID is supported for CoAP over UDP only according to RFC 7252
+ * So we should check message ID to prevent duplicate request handling in case of OC_ADAPTER_IP.
+ * In case of other transport adapter, duplicate message check is not required.
+ */
+ if (OC_ADAPTER_IP == ehRequest->devAddr.adapter &&
+ previousMsgId == ehRequest->messageID)
+ {
+ isDuplicatedMsg = true;
+ }
+
+ if (isDuplicatedMsg && ehRequest->messageID == gConfirmMsgId)
+ {
+ if (CONFIRM_STATE_WAIT == gConfirmState)
+ {
+ OIC_LOG(DEBUG, TAG, "Confirm callback already invoked.");
+ OIC_LOG(DEBUG, TAG, "This request will be ignored.");
+ DeleteDoxmBinData(newDoxm);
+ return OC_EH_OK;
+ }
+ else
+ {
+ OIC_LOG_V(DEBUG, TAG, "Confirm request already done, Confirm Result = %s", (CONFIRM_STATE_ACCEPTED == gConfirmState ? "ACCEPTED" : "DENIED"));
+ ehRet = (CONFIRM_STATE_ACCEPTED == gConfirmState ? OC_EH_OK : OC_EH_NOT_ACCEPTABLE);
+ goto exit;
+ }
+ }
+
// Check request on RO property
if (true == roParsed)
{
goto exit;
}
+ VERIFY_NON_NULL(TAG, gDoxm, ERROR);
+
// in owned state
if (true == gDoxm->owned)
{
+ if (false == ValidateOxmsel(gDoxm->oxm, gDoxm->oxmLen, &newDoxm->oxmSel))
+ {
+ OIC_LOG(ERROR, TAG, "Not acceptable request because oxmsel does not support on Server");
+ ehRet = OC_EH_NOT_ACCEPTABLE;
+ goto exit;
+ }
//Update gDoxm based on newDoxm
updateWriteableProperty(newDoxm, gDoxm);
#if defined(__WITH_DTLS__) || defined (__WITH_TLS__)
-#ifdef _ENABLE_MULTIPLE_OWNER_
+#ifdef MULTIPLE_OWNER
//handle mom
if(gDoxm->mom)
{
VERIFY_SUCCESS(TAG, caRes == CA_STATUS_OK, ERROR);
OIC_LOG(INFO, TAG, "ECDH_ANON CipherSuite is DISABLED");
- caRes = CASelectCipherSuite((uint16_t)TLS_ECDHE_PSK_WITH_AES_128_CBC_SHA_256, ehRequest->devAddr.adapter);
+ caRes = CASelectCipherSuite((uint16_t)MBEDTLS_TLS_ECDHE_PSK_WITH_AES_128_CBC_SHA256, ehRequest->devAddr.adapter);
VERIFY_SUCCESS(TAG, caRes == CA_STATUS_OK, ERROR);
OIC_LOG(INFO, TAG, "ECDHE_PSK CipherSuite will be used for MOT");
LL_APPEND(gDoxm->subOwners, subowner);
}
}
-#endif //_ENABLE_MULTIPLE_OWNER_
+#endif //MULTIPLE_OWNER
#endif // defined(__WITH_DTLS__) || defined (__WITH_TLS__)
//Update new state in persistent storage
// in unowned state
if ((false == gDoxm->owned) && (false == newDoxm->owned))
{
- if (OIC_JUST_WORKS == newDoxm->oxmSel)
+ if (false == ValidateOxmsel(gDoxm->oxm, gDoxm->oxmLen, &newDoxm->oxmSel))
+ {
+ OIC_LOG(ERROR, TAG, "Not acceptable request because oxmsel does not support on Server");
+ ehRet = OC_EH_NOT_ACCEPTABLE;
+ goto exit;
+ }
+
+#if defined (__WITH_TLS__) || defined(__WITH_DTLS__)
+ if (memcmp(&(newDoxm->owner), &emptyOwner, sizeof(OicUuid_t)) == 0)
+ {
+ InvokeOtmEventHandler(ehRequest->devAddr.addr, ehRequest->devAddr.port,
+ NULL, OIC_OTM_STARTED);
+ }
+ else
+ {
+ OIC_LOG_V(INFO, TAG, "%s: request owner not empty",__func__);
+ char* strUuid = NULL;
+ if (OC_STACK_OK == ConvertUuidToStr(&newDoxm->owner, &strUuid))
+ {
+ OIC_LOG_V(INFO, TAG, "%s: request owner: %s",__func__, strUuid);
+ OICFree(strUuid);
+ }
+ }
+#endif
+
+ if (OIC_JUST_WORKS == newDoxm->oxmSel || OIC_MV_JUST_WORKS == newDoxm->oxmSel)
{
/*
* If current state of the device is un-owned, enable
*/
if (memcmp(&(newDoxm->owner), &emptyOwner, sizeof(OicUuid_t)) == 0)
{
+ gDoxm->oxmSel = newDoxm->oxmSel;
+ //Update new state in persistent storage
+ if ((UpdatePersistentStorage(gDoxm) == true))
+ {
+ ehRet = OC_EH_OK;
+ }
+ else
+ {
+ OIC_LOG(WARNING, TAG, "Failed to update DOXM in persistent storage");
+ ehRet = OC_EH_ERROR;
+ goto exit;
+ }
OIC_LOG (INFO, TAG, "Doxm EntityHandle enabling AnonECDHCipherSuite");
#if defined(__WITH_DTLS__) || defined(__WITH_TLS__)
ehRet = (CAEnableAnonECDHCipherSuite(true) == CA_STATUS_OK) ? OC_EH_OK : OC_EH_ERROR;
{
OIC_LOG(ERROR, TAG, "Failed to update DOXM in persistent storage");
ehRet = OC_EH_ERROR;
+ goto exit;
}
/*
VERIFY_SUCCESS(TAG, caRes == CA_STATUS_OK, ERROR);
OIC_LOG(INFO, TAG, "ECDH_ANON CipherSuite is DISABLED");
+ //In case of Mutual Verified Just-Works, verify mutualVerifNum
+ if (OIC_MV_JUST_WORKS == newDoxm->oxmSel && false == newDoxm->owned &&
+ false == isDuplicatedMsg)
+ {
+ uint8_t preMutualVerifNum[OWNER_PSK_LENGTH_128] = {0};
+ uint8_t mutualVerifNum[MUTUAL_VERIF_NUM_LEN] = {0};
+ OicUuid_t deviceID = {.id = {0}};
+
+ //Generate mutualVerifNum
+ OCServerRequest * request = GetServerRequestUsingHandle(ehRequest->requestHandle);
+
+ char label[LABEL_LEN] = {0};
+ snprintf(label, LABEL_LEN, "%s%s", MUTUAL_VERIF_NUM, OXM_MV_JUST_WORKS);
+ if (OC_STACK_OK != GetDoxmDeviceID(&deviceID))
+ {
+ OIC_LOG(ERROR, TAG, "Error while retrieving Owner's device ID");
+ ehRet = OC_EH_ERROR;
+ goto exit;
+
+ }
+
+ CAResult_t pskRet = CAGenerateOwnerPSK((CAEndpoint_t *)&request->devAddr,
+ (uint8_t *)label,
+ strlen(label),
+ gDoxm->owner.id, sizeof(gDoxm->owner.id),
+ gDoxm->deviceID.id, sizeof(gDoxm->deviceID.id),
+ preMutualVerifNum, OWNER_PSK_LENGTH_128);
+ if (CA_STATUS_OK != pskRet)
+ {
+ OIC_LOG(WARNING, TAG, "Failed to remove the invaild owner credential");
+ ehRet = OC_EH_ERROR;
+ goto exit;
+
+ }
+
+ memcpy(mutualVerifNum, preMutualVerifNum + OWNER_PSK_LENGTH_128 - sizeof(mutualVerifNum),
+ sizeof(mutualVerifNum));
+
+ gConfirmMsgId = ehRequest->messageID;
+ gConfirmState = CONFIRM_STATE_WAIT;
+ //Wait for user confirmation
+ if (OC_STACK_OK != VerifyOwnershipTransfer(mutualVerifNum, DISPLAY_NUM | USER_CONFIRM))
+ {
+ ehRet = OC_EH_NOT_ACCEPTABLE;
+ gConfirmState = CONFIRM_STATE_DENIED;
+ }
+ else
+ {
+ ehRet = OC_EH_OK;
+ gConfirmState = CONFIRM_STATE_ACCEPTED;
+ }
+ }
+
#endif // __WITH_DTLS__ or __WITH_TLS__
}
}
VERIFY_SUCCESS(TAG, caRes == CA_STATUS_OK, ERROR);
OIC_LOG(INFO, TAG, "ECDH_ANON CipherSuite is DISABLED");
- caRes = CASelectCipherSuite(TLS_ECDHE_PSK_WITH_AES_128_CBC_SHA_256,
+ caRes = CASelectCipherSuite(MBEDTLS_TLS_ECDHE_PSK_WITH_AES_128_CBC_SHA256,
ehRequest->devAddr.adapter);
VERIFY_SUCCESS(TAG, caRes == CA_STATUS_OK, ERROR);
- char ranPin[OXM_RANDOM_PIN_SIZE + 1] = {0,};
- //TODO ehRequest->messageID for copa over TCP always is null. Find reason why.
- if(ehRequest->devAddr.adapter == OC_ADAPTER_IP && previousMsgId != ehRequest->messageID)
+ if (!isDuplicatedMsg)
{
- if(OC_STACK_OK == GeneratePin(ranPin, OXM_RANDOM_PIN_SIZE + 1))
+ char ranPin[OXM_RANDOM_PIN_MAX_SIZE + 1] = {0};
+ if (OC_STACK_OK == GeneratePin(ranPin, sizeof(ranPin)))
{
//Set the device id to derive temporal PSK
SetUuidForPinBasedOxm(&gDoxm->deviceID);
ehRet = OC_EH_ERROR;
}
}
- else if(previousMsgId != ehRequest->messageID)
- {
- if(OC_STACK_OK == GeneratePin(ranPin, OXM_RANDOM_PIN_SIZE + 1))
- {
- //Set the device id to derive temporal PSK
- SetUuidForPinBasedOxm(&gDoxm->deviceID);
-
- /**
- * Since PSK will be used directly by DTLS layer while PIN based ownership transfer,
- * Credential should not be saved into SVR.
- * For this reason, use a temporary get_psk_info callback to random PIN OxM.
- */
- caRes = CAregisterPskCredentialsHandler(GetDtlsPskForRandomPinOxm);
- VERIFY_SUCCESS(TAG, caRes == CA_STATUS_OK, ERROR);
- ehRet = OC_EH_OK;
- }
- else
- {
- OIC_LOG(ERROR, TAG, "Failed to generate random PIN");
- ehRet = OC_EH_ERROR;
- }
-
- }
#endif // __WITH_DTLS__ or __WITH_TLS__
}
#if defined(__WITH_DTLS__) || defined(__WITH_TLS__)
//Save the owner's UUID to derive owner credential
memcpy(&(gDoxm->owner), &(newDoxm->owner), sizeof(OicUuid_t));
+ // In case of random-pin based OTM, close the PIN display if callback is registered.
+ if (!isDuplicatedMsg)
+ {
+ ClosePinDisplay();
+ }
+
//Update new state in persistent storage
if (UpdatePersistentStorage(gDoxm) == true)
{
}
#endif // __WITH_DTLS__ or __WITH_TLS__
}
+#if defined(__WITH_DTLS__) || defined (__WITH_TLS__)
+ else if (OIC_MANUFACTURER_CERTIFICATE == newDoxm->oxmSel || OIC_CON_MFG_CERT == newDoxm->oxmSel)
+ {
+ //Get user confirmation
+ if (false == newDoxm->owned &&
+ false == isDuplicatedMsg &&
+ memcmp(&(newDoxm->owner), &emptyOwner, sizeof(OicUuid_t)) != 0)
+ {
+ gConfirmMsgId = ehRequest->messageID;
+ gConfirmState = CONFIRM_STATE_WAIT;
+ if (OC_STACK_OK != VerifyOwnershipTransfer(NULL, USER_CONFIRM))
+ {
+ ehRet = OC_EH_NOT_ACCEPTABLE;
+ gConfirmState = CONFIRM_STATE_DENIED;
+ goto exit;
+ }
+ else
+ {
+ ehRet = OC_EH_OK;
+ gConfirmState = CONFIRM_STATE_ACCEPTED;
+ }
+ }
+
+ //Save the owner's UUID to derive owner credential
+ memcpy(&(gDoxm->owner), &(newDoxm->owner), sizeof(OicUuid_t));
+ gDoxm->oxmSel = newDoxm->oxmSel;
+ //Update new state in persistent storage
+ if (UpdatePersistentStorage(gDoxm))
+ {
+ ehRet = OC_EH_OK;
+ }
+ else
+ {
+ OIC_LOG(WARNING, TAG, "Failed to update DOXM in persistent storage");
+ ehRet = OC_EH_ERROR;
+ }
+ CAResult_t caRes = CAEnableAnonECDHCipherSuite(false);
+ VERIFY_SUCCESS(TAG, caRes == CA_STATUS_OK, ERROR);
+ OIC_LOG(INFO, TAG, "ECDH_ANON CipherSuite is DISABLED");
+
+ //Unset pre-selected ciphersuite, if any
+ caRes = CASelectCipherSuite(0, ehRequest->devAddr.adapter);
+ VERIFY_SUCCESS(TAG, caRes == CA_STATUS_OK, ERROR);
+ OIC_LOG(DEBUG, TAG, "No ciphersuite preferred");
+
+ VERIFY_SUCCESS(TAG, CA_STATUS_OK == CAregisterPkixInfoHandler(GetManufacturerPkixInfo), ERROR);
+ VERIFY_SUCCESS(TAG, CA_STATUS_OK == CAregisterGetCredentialTypesHandler(InitManufacturerCipherSuiteList), ERROR);
+ }
+#endif // __WITH_DTLS__ or __WITH_TLS__
}
/*
ehRet = OC_EH_ERROR;
goto exit;
}
- ownerRes = SetDpairingRownerId(&gDoxm->owner);
- if(OC_STACK_OK != ownerRes && OC_STACK_NO_RESOURCE != ownerRes)
- {
- ehRet = OC_EH_ERROR;
- goto exit;
- }
- ownerRes = SetPconfRownerId(&gDoxm->owner);
- if(OC_STACK_OK != ownerRes && OC_STACK_NO_RESOURCE != ownerRes)
- {
- ehRet = OC_EH_ERROR;
- goto exit;
- }
gDoxm->owned = true;
memcpy(&gDoxm->rownerID, &gDoxm->owner, sizeof(OicUuid_t));
OIC_LOG(ERROR, TAG, "Failed to update DOXM in persistent storage");
ehRet = OC_EH_ERROR;
}
+#if defined(__WITH_DTLS__) || defined (__WITH_TLS__)
+ if (OIC_MANUFACTURER_CERTIFICATE == gDoxm->oxmSel ||
+ OIC_CON_MFG_CERT== gDoxm->oxmSel)
+ {
+ CAregisterPkixInfoHandler(GetPkixInfo);
+ CAregisterGetCredentialTypesHandler(InitCipherSuiteList);
+ }
+
+ InvokeOtmEventHandler(ehRequest->devAddr.addr, ehRequest->devAddr.port,
+ &gDoxm->owner, OIC_OTM_DONE);
+#endif // __WITH_DTLS__ or __WITH_TLS__
}
}
}
exit:
if(OC_EH_OK != ehRet)
{
-
/*
* If some error is occured while ownership transfer,
* ownership transfer related resource should be revert back to initial status.
*/
if(gDoxm)
{
- if(!gDoxm->owned && previousMsgId != ehRequest->messageID)
+ if(!gDoxm->owned)
{
- OIC_LOG(WARNING, TAG, "The operation failed during handle DOXM request,"\
- "DOXM will be reverted.");
- RestoreDoxmToInitState();
- RestorePstatToInitState();
+ OIC_LOG(WARNING, TAG, "The operation failed during handle DOXM request");
+
+ if (!isDuplicatedMsg)
+ {
+#if defined (__WITH_TLS__) || defined(__WITH_DTLS__)
+ InvokeOtmEventHandler(ehRequest->devAddr.addr, ehRequest->devAddr.port,
+ NULL, OIC_OTM_ERROR);
+#endif
+ RestoreDoxmToInitState();
+ RestorePstatToInitState();
+ OIC_LOG(WARNING, TAG, "DOXM will be reverted.");
+ }
}
}
else
OIC_LOG(ERROR, TAG, "Invalid DOXM resource.");
}
}
+
+ previousMsgId = ehRequest->messageID;
+
+#if defined (__WITH_TLS__) || defined(__WITH_DTLS__)
+ CAEndpoint_t peer = {0};
+ OCDevAddr devAddr = ehRequest->devAddr;
+
+ memcpy(&peer.addr, &devAddr.addr, sizeof(peer.addr));
+ peer.port = devAddr.port;
+ peer.adapter = (CATransportAdapter_t)devAddr.adapter;
+
+ if ((devAddr.flags & OC_FLAG_SECURE) && (false == CAIsExistSslPeer(&peer)))
+ {
+ OIC_LOG_V(WARNING, TAG, "Not Exist Peer");
+ ehRet = OC_EH_OK;
+ }
else
{
- previousMsgId = ehRequest->messageID;
+ //Send payload to request originator
+ ehRet = ((SendSRMResponse(ehRequest, ehRet, NULL, 0)) == OC_STACK_OK) ?
+ OC_EH_OK : OC_EH_ERROR;
}
-
+#else
//Send payload to request originator
ehRet = ((SendSRMResponse(ehRequest, ehRet, NULL, 0)) == OC_STACK_OK) ?
- OC_EH_OK : OC_EH_ERROR;
+ OC_EH_OK : OC_EH_ERROR;
+#endif
DeleteDoxmBinData(newDoxm);
return ehRet;
}
+#ifdef MULTIPLE_OWNER
+static OCEntityHandlerResult HandleDoxmDeleteRequest(const OCEntityHandlerRequest *ehRequest)
+{
+ OIC_LOG(DEBUG, TAG, "Processing DoxmDeleteRequest");
+
+ OCEntityHandlerResult ehRet = OC_EH_BAD_REQ;
+
+ if (NULL == ehRequest->query)
+ {
+ return ehRet;
+ }
+
+ OicParseQueryIter_t parseIter = { .attrPos=NULL };
+ OicUuid_t subject = {.id={0}};
+
+ //Parsing REST query to get the subject
+ ParseQueryIterInit((unsigned char *)ehRequest->query, &parseIter);
+ while (GetNextQuery(&parseIter))
+ {
+ if (strncasecmp((char *)parseIter.attrPos, OIC_JSON_SUBOWNERID_NAME,
+ parseIter.attrLen) == 0)
+ {
+ if (0 == strncmp((const char*)parseIter.valPos, WILDCARD_RESOURCE_URI,
+ strlen(WILDCARD_RESOURCE_URI)))
+ {
+ if(OC_STACK_RESOURCE_DELETED == RemoveSubOwner(&WILDCARD_SUBJECT_ID))
+ {
+ ehRet = OC_EH_RESOURCE_DELETED;
+ }
+ }
+ else
+ {
+ OCStackResult ret = ConvertStrToUuid((const char*)parseIter.valPos, &subject);
+ VERIFY_SUCCESS(TAG, OC_STACK_OK == ret, ERROR);
+
+ if(OC_STACK_RESOURCE_DELETED == RemoveSubOwner(&subject))
+ {
+ ehRet = OC_EH_RESOURCE_DELETED;
+ }
+ }
+ }
+ }
+
+ //Send response to request originator
+ ehRet = ((SendSRMResponse(ehRequest, ehRet, NULL, 0)) == OC_STACK_OK) ?
+ OC_EH_OK : OC_EH_ERROR;
+
+ return ehRet;
+exit:
+ return OC_EH_ERROR;
+}
+#endif //MULTIPLE_OWNER
+
OCEntityHandlerResult DoxmEntityHandler(OCEntityHandlerFlag flag,
OCEntityHandlerRequest * ehRequest,
void* callbackParam)
return ehRet;
}
+ oc_mutex_lock(g_mutexDoxm);
+
+ if(g_isDoxmNull)
+ {
+ oc_mutex_unlock(g_mutexDoxm);
+ return OC_EH_SERVICE_UNAVAILABLE;
+ }
+
if (flag & OC_REQUEST_FLAG)
{
OIC_LOG(DEBUG, TAG, "Flag includes OC_REQUEST_FLAG");
ehRet = HandleDoxmPostRequest(ehRequest);
break;
+#ifdef MULTIPLE_OWNER
+ case OC_REST_DELETE:
+ ehRet = HandleDoxmDeleteRequest(ehRequest);
+ break;
+#endif //MULTIPLE_OWNER
+
default:
ehRet = ((SendSRMResponse(ehRequest, ehRet, NULL, 0)) == OC_STACK_OK) ?
OC_EH_OK : OC_EH_ERROR;
break;
}
+
+ oc_mutex_unlock(g_mutexDoxm);
}
return ehRet;
*/
static OCStackResult CheckDeviceID()
{
+ OIC_LOG_V(DEBUG, TAG, "IN: %s", __func__);
+
OCStackResult ret = OC_STACK_ERROR;
bool validId = false;
+
+ if (!gDoxm)
+ {
+ OIC_LOG_V(ERROR, TAG, "%s: gDoxm is NULL", __func__);
+ return OC_STACK_INVALID_PARAM;
+ }
+
for (uint8_t i = 0; i < UUID_LENGTH; i++)
{
if (gDoxm->deviceID.id[i] != 0)
if (!validId)
{
- if (OCGenerateUuid(gDoxm->deviceID.id) != RAND_UUID_OK)
+ char* strUuid = NULL;
+#if defined(__WITH_DTLS__) || defined (__WITH_TLS__)
+ //If seed value is exist, generate UUID using seed with SHA256
+ if (0 != gUuidSeedSize)
+ {
+ uint8_t hashVal[MBEDTLS_MD_MAX_SIZE] = {0};
+ mbedtls_md_context_t sha_ctx;
+ int mbedret = 1;
+
+ OIC_LOG(DEBUG, TAG, "UUID will be generated using seed w/ SHA256");
+ OIC_LOG(DEBUG, TAG, "Seed value : ");
+ OIC_LOG_BUFFER(DEBUG, TAG, gUuidSeed, gUuidSeedSize);
+
+ mbedtls_md_init( &sha_ctx );
+ mbedret = mbedtls_md_setup( &sha_ctx, mbedtls_md_info_from_type( MBEDTLS_MD_SHA256 ), 1 );
+ if (0 == mbedret)
+ {
+ mbedtls_md_starts( &sha_ctx );
+ mbedtls_md_update( &sha_ctx, gUuidSeed, gUuidSeedSize);
+ mbedtls_md_finish(&sha_ctx, (unsigned char*)hashVal);
+ memcpy(gDoxm->deviceID.id, hashVal, sizeof(gDoxm->deviceID.id));
+ ret = OC_STACK_OK;
+ }
+ else
+ {
+ OIC_LOG_V(ERROR, TAG, "mbedtls_md_setup() returned -0x%04x\n", -mbedret);
+ ret = OC_STACK_ERROR;
+ }
+ mbedtls_md_free( &sha_ctx );
+ }
+ else
+ {
+ if (RAND_UUID_OK != OCGenerateUuid(gDoxm->deviceID.id))
+ {
+ OIC_LOG(FATAL, TAG, "Generate UUID for Server Instance failed!");
+ return OC_STACK_ERROR;
+ }
+ ret = OC_STACK_OK;
+ }
+#else
+ if (RAND_UUID_OK != OCGenerateUuid(gDoxm->deviceID.id))
{
OIC_LOG(FATAL, TAG, "Generate UUID for Server Instance failed!");
return ret;
}
ret = OC_STACK_OK;
+#endif
+
+ if (OC_STACK_OK == ConvertUuidToStr(&gDoxm->deviceID, &strUuid))
+ {
+ OIC_LOG_V(DEBUG, TAG, "Generated device UUID is [%s]", strUuid);
+ OICFree(strUuid);
+ }
+ else
+ {
+ OIC_LOG(WARNING, TAG, "Failed to convert UUID to string");
+ }
+
if (!UpdatePersistentStorage(gDoxm))
{
{
ret = OC_STACK_OK;
}
+
+ OIC_LOG_V(DEBUG, TAG, "OUT: %s", __func__);
+
return ret;
}
return gDoxm;
}
-#if defined(__WITH_DTLS__) && defined(_ENABLE_MULTIPLE_OWNER_)
+#if defined(__WITH_DTLS__) && defined(MULTIPLE_OWNER)
/**
* Internal API to prepare MOT
*/
VERIFY_SUCCESS(TAG, caRes == CA_STATUS_OK, ERROR);
OIC_LOG(INFO, TAG, "ECDH_ANON CipherSuite is DISABLED");
- caRes = CASelectCipherSuite((uint16_t)TLS_ECDHE_PSK_WITH_AES_128_CBC_SHA_256, CA_ADAPTER_IP);
+ caRes = CASelectCipherSuite((uint16_t)MBEDTLS_TLS_ECDHE_PSK_WITH_AES_128_CBC_SHA256, CA_ADAPTER_IP);
VERIFY_SUCCESS(TAG, caRes == CA_STATUS_OK, ERROR);
#ifdef __WITH_TLS__
- caRes = CASelectCipherSuite((uint16_t)TLS_ECDHE_PSK_WITH_AES_128_CBC_SHA_256, CA_ADAPTER_TCP);
+ caRes = CASelectCipherSuite((uint16_t)MBEDTLS_TLS_ECDHE_PSK_WITH_AES_128_CBC_SHA256, CA_ADAPTER_TCP);
VERIFY_SUCCESS(TAG, caRes == CA_STATUS_OK, ERROR);
#endif
OIC_LOG(INFO, TAG, "ECDHE_PSK CipherSuite will be used for MOT");
exit:
OIC_LOG(WARNING, TAG, "Error in PrepareMOT");
}
-#endif //defined(__WITH_DTLS__) && defined(_ENABLE_MULTIPLE_OWNER_)
+#endif //defined(__WITH_DTLS__) && defined(MULTIPLE_OWNER)
OCStackResult InitDoxmResource()
{
OCStackResult ret = OC_STACK_ERROR;
+ if (!g_mutexDoxm)
+ {
+ g_mutexDoxm = oc_mutex_new();
+ if(!g_mutexDoxm)
+ {
+ return OC_STACK_ERROR;
+ }
+ }
+
+ gConfirmState = CONFIRM_STATE_READY;
+ gConfirmMsgId = 0;
+
//Read DOXM resource from PS
uint8_t *data = NULL;
size_t size = 0;
gDoxm = GetDoxmDefault();
}
+ oc_mutex_lock(g_mutexDoxm);
+ g_isDoxmNull = false;
+ oc_mutex_unlock(g_mutexDoxm);
+
//In case of the server is shut down unintentionally, we should initialize the owner
- if(false == gDoxm->owned)
+ if(gDoxm && (false == gDoxm->owned))
{
OicUuid_t emptyUuid = {.id={0}};
memcpy(&gDoxm->owner, &emptyUuid, sizeof(OicUuid_t));
+#if defined (__WITH_TLS__) || defined(__WITH_DTLS__)
+ InvokeOtmEventHandler(NULL, 0, NULL, OIC_OTM_READY);
+#endif
}
ret = CheckDeviceID();
}
OICFree(data);
-#if defined(__WITH_DTLS__) && defined(_ENABLE_MULTIPLE_OWNER_)
+#if defined(__WITH_DTLS__) && defined(MULTIPLE_OWNER)
//if MOT is enabled, MOT should be prepared.
if(gDoxm && gDoxm->owned)
{
PrepareMOT(gDoxm);
}
-#endif // defined(__WITH_DTLS__) && defined(_ENABLE_MULTIPLE_OWNER_)
+#endif // defined(__WITH_DTLS__) && defined(MULTIPLE_OWNER)
return ret;
}
OCStackResult DeInitDoxmResource()
{
+ oc_mutex_lock(g_mutexDoxm);
OCStackResult ret = OCDeleteResource(gDoxmHandle);
if (gDoxm != &gDefaultDoxm)
{
DeleteDoxmBinData(gDoxm);
}
gDoxm = NULL;
+ g_isDoxmNull = true;
if (OC_STACK_OK == ret)
{
+ oc_mutex_unlock(g_mutexDoxm);
return OC_STACK_OK;
}
else
{
+ oc_mutex_unlock(g_mutexDoxm);
return OC_STACK_ERROR;
}
}
return OC_STACK_ERROR;
}
-OCStackResult SetDoxmDeviceID(const OicUuid_t *deviceID)
+#if defined(__WITH_DTLS__) || defined (__WITH_TLS__)
+OCStackResult SetDoxmDeviceIDSeed(const uint8_t* seed, size_t seedSize)
{
- bool isPT = false;
+ OIC_LOG_V(INFO, TAG, "In %s", __func__);
- if(NULL == deviceID)
+ if (NULL == seed)
{
return OC_STACK_INVALID_PARAM;
}
- if(NULL == gDoxm)
+ if (MAX_UUID_SEED_SIZE < seedSize)
+ {
+ OIC_LOG_V(ERROR, TAG, "Seed size is too long (MAX size is %d bytes)", MAX_UUID_SEED_SIZE);
+ return OC_STACK_INVALID_PARAM;
+ }
+ if (MIN_UUID_SEED_SIZE > seedSize)
+ {
+ OIC_LOG_V(ERROR, TAG, "Seed size is too small (MIN size is %d bytes)", MIN_UUID_SEED_SIZE);
+ return OC_STACK_INVALID_PARAM;
+ }
+
+ memset(gUuidSeed, 0x00, sizeof(gUuidSeed));
+ memcpy(gUuidSeed, seed, seedSize);
+ gUuidSeedSize = seedSize;
+
+ OIC_LOG_V(INFO, TAG, "Out %s", __func__);
+
+ return OC_STACK_OK;
+}
+
+#endif
+
+OCStackResult SetDoxmDeviceID(const OicUuid_t *deviceID)
+{
+ bool isOwnerUpdated = false;
+ bool isRownerUpdated = false;
+ if (NULL == deviceID)
+ {
+ return OC_STACK_INVALID_PARAM;
+ }
+ if (NULL == gDoxm)
{
OIC_LOG(ERROR, TAG, "Doxm resource is not initialized.");
return OC_STACK_NO_RESOURCE;
}
- //Check the device's OTM state
-
#ifdef __WITH_DTLS__
//for normal device.
- if(true == gDoxm->owned &&
- memcmp(gDoxm->deviceID.id, gDoxm->owner.id, sizeof(gDoxm->owner.id)) != 0)
+ if (true == gDoxm->owned
+ && memcmp(gEmptyUuid, gDoxm->owner.id, sizeof(gDoxm->owner.id)) != 0
+ && memcmp(gDoxm->deviceID.id, gDoxm->owner.id, sizeof(gDoxm->owner.id)) != 0)
{
OIC_LOG(ERROR, TAG, "This device owned by owner's device.");
OIC_LOG(ERROR, TAG, "Device UUID cannot be changed to guarantee the reliability of the connection.");
#endif //__WITH_DTLS
//Save the previous UUID
- OicUuid_t tempUuid;
- memcpy(tempUuid.id, gDoxm->deviceID.id, sizeof(tempUuid.id));
+ OicUuid_t prevUuid;
+ memcpy(prevUuid.id, gDoxm->deviceID.id, sizeof(prevUuid.id));
- //Change the UUID
+ //Change the device UUID
memcpy(gDoxm->deviceID.id, deviceID->id, sizeof(deviceID->id));
- if(isPT)
+
+ //Change the owner ID if necessary
+ if (memcmp(gDoxm->owner.id, prevUuid.id, sizeof(prevUuid.id)) == 0)
{
memcpy(gDoxm->owner.id, deviceID->id, sizeof(deviceID->id));
+ isOwnerUpdated = true;
+ }
+ //Change the resource owner ID if necessary
+ if (memcmp(gDoxm->rownerID.id, prevUuid.id, sizeof(prevUuid.id)) == 0)
+ {
memcpy(gDoxm->rownerID.id, deviceID->id, sizeof(deviceID->id));
+ isRownerUpdated = true;
}
+ // TODO: T.B.D Change resource owner for pstat, acl and cred
//Update PS
- if(!UpdatePersistentStorage(gDoxm))
+ if (!UpdatePersistentStorage(gDoxm))
{
- //revert UUID in case of update error
- memcpy(gDoxm->deviceID.id, tempUuid.id, sizeof(tempUuid.id));
- if(isPT)
+ //revert UUID in case of PSI error
+ memcpy(gDoxm->deviceID.id, prevUuid.id, sizeof(prevUuid.id));
+ if (isOwnerUpdated)
+ {
+ memcpy(gDoxm->owner.id, prevUuid.id, sizeof(prevUuid.id));
+ }
+ if (isRownerUpdated)
{
- memcpy(gDoxm->owner.id, tempUuid.id, sizeof(tempUuid.id));
- memcpy(gDoxm->rownerID.id, tempUuid.id, sizeof(tempUuid.id));
+ memcpy(gDoxm->rownerID.id, prevUuid.id, sizeof(prevUuid.id));
}
+ // TODO: T.B.D Revert resource owner for pstat, acl and cred
OIC_LOG(ERROR, TAG, "Failed to update persistent storage");
return OC_STACK_ERROR;
return retVal;
}
-#ifdef _ENABLE_MULTIPLE_OWNER_
+#ifdef MULTIPLE_OWNER
/**
* Compare the UUID to SubOwner.
*
{
bool retVal = false;
- if(NULL == uuid)
+ if (NULL == uuid)
{
return retVal;
}
if (gDoxm && gDoxm->subOwners)
{
+ if (memcmp(gDoxm->owner.id, uuid->id, sizeof(gDoxm->owner.id)) == 0)
+ {
+ return false;
+ }
+
OicSecSubOwner_t* subOwner = NULL;
LL_FOREACH(gDoxm->subOwners, subOwner)
{
- if(memcmp(subOwner->uuid.id, uuid->id, sizeof(uuid->id)) == 0)
+ if (memcmp(subOwner->uuid.id, uuid->id, sizeof(uuid->id)) == 0)
{
return true;
}
}
return retVal;
}
-#endif //_ENABLE_MULTIPLE_OWNER_
+#endif //MULTIPLE_OWNER
+
+OCStackResult SetMOTStatus(bool enable)
+{
+ OIC_LOG_V(DEBUG, TAG, "In %s", __func__);
+#ifdef MULTIPLE_OWNER
+ OCStackResult ret = OC_STACK_NO_MEMORY;
+ uint8_t *cborPayload = NULL;
+ size_t size = 0;
+ bool isDeallocateRequired = false;
+
+ VERIFY_NON_NULL(TAG, gDoxm, ERROR);
+
+ if (NULL == gDoxm->mom && !enable)
+ {
+ OIC_LOG_V(DEBUG, TAG, "Out %s", __func__);
+ return OC_STACK_OK;
+ }
+
+ if (NULL == gDoxm->mom)
+ {
+ gDoxm->mom = (OicSecMom_t*)OICCalloc(1, sizeof(OicSecMom_t));
+ VERIFY_NON_NULL(TAG, gDoxm->mom, ERROR);
+ isDeallocateRequired = true;
+ }
+
+ gDoxm->mom->mode = (enable ? OIC_MULTIPLE_OWNER_ENABLE : OIC_MULTIPLE_OWNER_DISABLE);
+ gDoxm->oxmSel = OIC_PRECONFIG_PIN;
+
+ ret = DoxmToCBORPayload(gDoxm, &cborPayload, &size, false);
+ VERIFY_SUCCESS(TAG, OC_STACK_OK == ret, ERROR);
+
+ ret = UpdateSecureResourceInPS(OIC_JSON_DOXM_NAME, cborPayload, size);
+ VERIFY_SUCCESS(TAG, OC_STACK_OK == ret, ERROR);
+
+ isDeallocateRequired = false;
+
+exit:
+ if (isDeallocateRequired)
+ {
+ OICFree(gDoxm->mom);
+ }
+ if (cborPayload)
+ {
+ OICFree(cborPayload);
+ }
+ OIC_LOG_V(DEBUG, TAG, "Out %s : %d", __func__, ret);
+ return ret;
+#else
+ OC_UNUSED(enable);
+ OIC_LOG(DEBUG, TAG, "Multiple Owner is not enabled.");
+ OIC_LOG_V(DEBUG, TAG, "Out %s", __func__);
+ return OC_STACK_ERROR;
+#endif //MULTIPLE_OWNER
+}
+
+OCStackResult RemoveSubOwner(const OicUuid_t* subOwner)
+{
+ OIC_LOG_V(DEBUG, TAG, "In %s", __func__);
+#ifdef MULTIPLE_OWNER
+ OCStackResult ret = OC_STACK_ERROR;
+ bool isDeleted = false;
+
+ if (NULL == subOwner)
+ {
+ OIC_LOG(ERROR, TAG, "Invalid sub owner UUID.");
+ return OC_STACK_INVALID_PARAM;
+ }
+ if (NULL == gDoxm)
+ {
+ OIC_LOG(ERROR, TAG, "Doxm resource is NULL");
+ return OC_STACK_NO_RESOURCE;
+ }
+ if ( NULL == gDoxm->subOwners)
+ {
+ OIC_LOG(WARNING, TAG, "Sub Owner list is empty.");
+ return OC_STACK_ERROR;
+ }
+
+ OicSecSubOwner_t* curSubOwner = NULL;
+ OicSecSubOwner_t* tempSubOwner = NULL;
+ LL_FOREACH_SAFE(gDoxm->subOwners, curSubOwner, tempSubOwner)
+ {
+ if (memcmp(curSubOwner->uuid.id, subOwner->id, sizeof(subOwner->id)) == 0 ||
+ memcmp(WILDCARD_SUBJECT_ID.id, subOwner->id, sizeof(OicUuid_t)) == 0)
+ {
+ char* strUuid = NULL;
+ ret = ConvertUuidToStr(&curSubOwner->uuid, &strUuid);
+ if (OC_STACK_OK != ret)
+ {
+ OIC_LOG_V(ERROR, TAG, "ConvertUuidToStr error : %d", ret);
+ break;
+ }
+
+ OIC_LOG_V(INFO, TAG, "[%s] will be removed from sub owner list.", strUuid);
+ LL_DELETE(gDoxm->subOwners, curSubOwner);
+
+ //Remove the cred for sub owner
+ ret = RemoveCredential(&curSubOwner->uuid);
+ if (OC_STACK_RESOURCE_DELETED != ret)
+ {
+ OIC_LOG_V(WARNING, TAG, "RemoveCredential error for [%s] : %d", strUuid, ret);
+ break;
+ }
+
+ // TODO: Remove the ACL for sub owner (Currently ACL is not required for sub-owner)
+
+ OICFree(strUuid);
+
+ isDeleted = true;
+ }
+ }
+
+ if (isDeleted)
+ {
+ //Update persistent storage
+ if (UpdatePersistentStorage(gDoxm))
+ {
+ ret = OC_STACK_RESOURCE_DELETED;
+ }
+ else
+ {
+ OIC_LOG(ERROR, TAG, "UpdatePersistentStorage error");
+ ret = OC_STACK_ERROR;
+ }
+ }
+
+ OIC_LOG_V(DEBUG, TAG, "Out %s", __func__);
+ return ret;
+#else
+ OC_UNUSED(subOwner);
+ OIC_LOG(DEBUG, TAG, "Multiple Owner is not enabled.");
+ OIC_LOG_V(DEBUG, TAG, "Out %s", __func__);
+ return OC_STACK_ERROR;
+#endif //MULTIPLE_OWNER
+
+}
+
+OCStackResult SetNumberOfSubOwner(size_t numOfSubOwner)
+{
+ OIC_LOG_V(DEBUG, TAG, "In %s", __func__);
+#ifdef MULTIPLE_OWNER
+ if (MAX_SUBOWNER_SIZE < numOfSubOwner || MIN_SUBOWNER_SIZE > numOfSubOwner)
+ {
+ OIC_LOG_V(ERROR, TAG, "Invalid number of sub owner : %d", numOfSubOwner);
+ return OC_STACK_INVALID_PARAM;
+ }
+ gMaxSubOwnerSize = numOfSubOwner;
+ OIC_LOG_V(DEBUG, TAG, "Number of SubOwner = %d", gMaxSubOwnerSize);
+ OIC_LOG_V(DEBUG, TAG, "Out %s", __func__);
+ return OC_STACK_OK;
+#else
+ OC_UNUSED(numOfSubOwner);
+ OIC_LOG(DEBUG, TAG, "Multiple Owner is not enabled.");
+ OIC_LOG_V(DEBUG, TAG, "Out %s", __func__);
+ return OC_STACK_ERROR;
+#endif //MULTIPLE_OWNER
+}
/**
* Function to restore doxm resurce to initial status.
*/
void RestoreDoxmToInitState()
{
+
+ gConfirmState = CONFIRM_STATE_READY;
+ gConfirmMsgId = 0;
+
if(gDoxm)
{
OIC_LOG(INFO, TAG, "DOXM resource will revert back to initial status.");
}
}
}
+
+OCStackResult SetDoxmSelfOwnership(const OicUuid_t* newROwner)
+{
+ OCStackResult ret = OC_STACK_ERROR;
+ uint8_t *cborPayload = NULL;
+ size_t size = 0;
+
+ if(NULL == gDoxm)
+ {
+ ret = OC_STACK_NO_RESOURCE;
+ return ret;
+ }
+
+ if( newROwner && (false == gDoxm->owned) )
+ {
+ gDoxm->owned = true;
+ memcpy(gDoxm->owner.id, newROwner->id, sizeof(newROwner->id));
+ memcpy(gDoxm->rownerID.id, newROwner->id, sizeof(newROwner->id));
+
+ ret = DoxmToCBORPayload(gDoxm, &cborPayload, &size, false);
+ VERIFY_SUCCESS(TAG, OC_STACK_OK == ret, ERROR);
+
+ ret = UpdateSecureResourceInPS(OIC_JSON_DOXM_NAME, cborPayload, size);
+ VERIFY_SUCCESS(TAG, OC_STACK_OK == ret, ERROR);
+
+ OICFree(cborPayload);
+ }
+
+ return ret;
+
+exit:
+ OICFree(cborPayload);
+ return ret;
+}
+