X-Git-Url: http://review.tizen.org/git/?a=blobdiff_plain;f=resource%2Fcsdk%2Fsecurity%2Fsrc%2Fdoxmresource.c;h=3128723a69b1e415598d6cca4753928972446dd6;hb=588a5d602cc351dbed407b510c6902905af4b443;hp=b16f9749f6d2681b2f1cddefc37a0e1502ebc556;hpb=7704a4d2318cf63bccb3fc09c9e8ca9cb8eaf0c7;p=platform%2Fupstream%2Fiotivity.git diff --git a/resource/csdk/security/src/doxmresource.c b/resource/csdk/security/src/doxmresource.c index b16f974..3128723 100644 --- a/resource/csdk/security/src/doxmresource.c +++ b/resource/csdk/security/src/doxmresource.c @@ -25,10 +25,6 @@ #include #endif -#ifdef __WITH_DTLS__ -#include "global.h" -#endif - #include "ocstack.h" #include "oic_malloc.h" #include "payload_logging.h" @@ -51,9 +47,12 @@ #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 "OIC_SRM_DOXM" @@ -66,7 +65,35 @@ static const uint16_t CBOR_SIZE = 512; /** 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; @@ -82,13 +109,18 @@ static OicSecDoxm_t gDefaultDoxm = {.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 @@ -111,7 +143,7 @@ void DeleteDoxmBinData(OicSecDoxm_t* doxm) //clean oxm OICFree(doxm->oxm); -#ifdef _ENABLE_MULTIPLE_OWNER_ +#ifdef MULTIPLE_OWNER //clean mom OICFree(doxm->mom); @@ -126,11 +158,17 @@ void DeleteDoxmBinData(OicSecDoxm_t* doxm) 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, @@ -240,7 +278,7 @@ OCStackResult DoxmToCBORPayload(const OicSecDoxm_t *doxm, uint8_t **payload, siz strUuid = NULL; } -#ifdef _ENABLE_MULTIPLE_OWNER_ +#ifdef MULTIPLE_OWNER //Device SubOwnerID -- Not Mandatory if(doxm->subOwners) { @@ -281,7 +319,7 @@ OCStackResult DoxmToCBORPayload(const OicSecDoxm_t *doxm, uint8_t **payload, siz 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, @@ -352,6 +390,7 @@ exit: 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 += cbor_encoder_get_buffer_size(&encoder, encoder.end); OIC_LOG_V(DEBUG, TAG, "Doxm reallocation size : %zd.", cborLen); @@ -551,7 +590,7 @@ static OCStackResult CBORPayloadToDoxmBin(const uint8_t *cborPayload, size_t siz 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)) { @@ -625,7 +664,7 @@ static OCStackResult CBORPayloadToDoxmBin(const uint8_t *cborPayload, size_t siz 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)) @@ -712,10 +751,9 @@ static bool ValidateQuery(const char * query) 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}; @@ -738,10 +776,9 @@ static bool ValidateQuery(const char * query) } } -#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) { @@ -759,7 +796,7 @@ static bool ValidateQuery(const char * query) } return bMotMatch; } -#endif //_ENABLE_MULTIPLE_OWNER_ +#endif //MULTIPLE_OWNER if (strncasecmp((char *)parseIter.attrPos, OIC_JSON_DEVICE_ID_NAME, parseIter.attrLen) == 0) { @@ -784,14 +821,8 @@ static bool ValidateQuery(const char * query) } } -#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) @@ -862,24 +893,7 @@ static void updateWriteableProperty(const OicSecDoxm_t* src, OicSecDoxm_t* dst) 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"); @@ -892,27 +906,74 @@ static void updateWriteableProperty(const OicSecDoxm_t* src, OicSecDoxm_t* dst) } } } -#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 (!gDoxm) + { + OIC_LOG_V(ERROR, TAG, "%s: gDoxm is NULL", __func__); + return; + } - if(CA_STATUS_OK == errorInfo->result) + 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)) { - const CASecureEndpoint_t* authenticatedSubOwnerInfo = CAGetSecureEndpointData(object); - if(authenticatedSubOwnerInfo) + 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) { + if (0 == memcmp(authenticatedSubOwnerInfo->identity.id, gDoxm->owner.id, + authenticatedSubOwnerInfo->identity.id_length)) + { + OIC_LOG(WARNING, TAG, "Super owner tried MOT, this request will be ignored."); + return; + } + OicSecSubOwner_t* subOwnerInst = NULL; LL_FOREACH(gDoxm->subOwners, subOwnerInst) { @@ -924,19 +985,48 @@ void MultipleOwnerDTLSHandshakeCB(const CAEndpoint_t *object, } } - if(NULL == subOwnerInst) + if (NULL == subOwnerInst) { subOwnerInst = (OicSecSubOwner_t*)OICCalloc(1, sizeof(OicSecSubOwner_t)); - if(subOwnerInst) + if (subOwnerInst) { - 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)) + 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()) { - OIC_LOG(ERROR, TAG, "Failed to register SubOwner UUID into Doxm"); + 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); } } } @@ -947,17 +1037,57 @@ void MultipleOwnerDTLSHandshakeCB(const CAEndpoint_t *object, 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 @@ -973,6 +1103,34 @@ static OCEntityHandlerResult HandleDoxmPostRequest(const OCEntityHandlerRequest 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) { @@ -981,14 +1139,22 @@ static OCEntityHandlerResult HandleDoxmPostRequest(const OCEntityHandlerRequest 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) { @@ -1001,7 +1167,7 @@ static OCEntityHandlerResult HandleDoxmPostRequest(const OCEntityHandlerRequest 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"); @@ -1049,7 +1215,7 @@ static OCEntityHandlerResult HandleDoxmPostRequest(const OCEntityHandlerRequest 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 @@ -1068,7 +1234,32 @@ static OCEntityHandlerResult HandleDoxmPostRequest(const OCEntityHandlerRequest // 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 @@ -1077,6 +1268,18 @@ static OCEntityHandlerResult HandleDoxmPostRequest(const OCEntityHandlerRequest */ 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; @@ -1098,6 +1301,7 @@ static OCEntityHandlerResult HandleDoxmPostRequest(const OCEntityHandlerRequest { OIC_LOG(ERROR, TAG, "Failed to update DOXM in persistent storage"); ehRet = OC_EH_ERROR; + goto exit; } /* @@ -1109,6 +1313,59 @@ static OCEntityHandlerResult HandleDoxmPostRequest(const OCEntityHandlerRequest 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__ } } @@ -1140,15 +1397,14 @@ static OCEntityHandlerResult HandleDoxmPostRequest(const OCEntityHandlerRequest 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_MAX_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, sizeof(ranPin))) + 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); @@ -1168,29 +1424,6 @@ static OCEntityHandlerResult HandleDoxmPostRequest(const OCEntityHandlerRequest ehRet = OC_EH_ERROR; } } - else if(previousMsgId != ehRequest->messageID) - { - if(OC_STACK_OK == GeneratePin(ranPin, sizeof(ranPin))) - { - //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__) @@ -1199,6 +1432,12 @@ static OCEntityHandlerResult HandleDoxmPostRequest(const OCEntityHandlerRequest //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) { @@ -1213,8 +1452,28 @@ static OCEntityHandlerResult HandleDoxmPostRequest(const OCEntityHandlerRequest #endif // __WITH_DTLS__ or __WITH_TLS__ } #if defined(__WITH_DTLS__) || defined (__WITH_TLS__) - else if (OIC_MANUFACTURER_CERTIFICATE == newDoxm->oxmSel) + 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; @@ -1232,6 +1491,11 @@ static OCEntityHandlerResult HandleDoxmPostRequest(const OCEntityHandlerRequest 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); } @@ -1271,18 +1535,6 @@ static OCEntityHandlerResult HandleDoxmPostRequest(const OCEntityHandlerRequest 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)); @@ -1307,11 +1559,15 @@ static OCEntityHandlerResult HandleDoxmPostRequest(const OCEntityHandlerRequest ehRet = OC_EH_ERROR; } #if defined(__WITH_DTLS__) || defined (__WITH_TLS__) - if (OIC_MANUFACTURER_CERTIFICATE == gDoxm->oxmSel) + 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__ } } @@ -1320,19 +1576,26 @@ static OCEntityHandlerResult HandleDoxmPostRequest(const OCEntityHandlerRequest 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 @@ -1340,20 +1603,92 @@ exit: 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) @@ -1366,6 +1701,14 @@ OCEntityHandlerResult DoxmEntityHandler(OCEntityHandlerFlag flag, 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"); @@ -1380,11 +1723,19 @@ OCEntityHandlerResult DoxmEntityHandler(OCEntityHandlerFlag 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; @@ -1416,8 +1767,17 @@ OCStackResult CreateDoxmResource() */ 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) @@ -1429,12 +1789,64 @@ static OCStackResult CheckDeviceID() 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)) { @@ -1446,6 +1858,9 @@ static OCStackResult CheckDeviceID() { ret = OC_STACK_OK; } + + OIC_LOG_V(DEBUG, TAG, "OUT: %s", __func__); + return ret; } @@ -1465,7 +1880,7 @@ const OicSecDoxm_t* GetDoxmResourceData() return gDoxm; } -#if defined(__WITH_DTLS__) && defined(_ENABLE_MULTIPLE_OWNER_) +#if defined(__WITH_DTLS__) && defined(MULTIPLE_OWNER) /** * Internal API to prepare MOT */ @@ -1486,10 +1901,10 @@ static void PrepareMOT(const OicSecDoxm_t* doxm) 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"); @@ -1511,12 +1926,24 @@ static void PrepareMOT(const OicSecDoxm_t* doxm) 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; @@ -1541,11 +1968,18 @@ OCStackResult InitDoxmResource() 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(); @@ -1561,32 +1995,36 @@ OCStackResult InitDoxmResource() } 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; } } @@ -1611,26 +2049,56 @@ OCStackResult GetDoxmIsOwned(bool *isOwned) 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."); @@ -1639,27 +2107,40 @@ OCStackResult SetDoxmDeviceID(const OicUuid_t *deviceID) #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; @@ -1697,7 +2178,7 @@ OCStackResult GetDoxmRownerId(OicUuid_t *rowneruuid) return retVal; } -#ifdef _ENABLE_MULTIPLE_OWNER_ +#ifdef MULTIPLE_OWNER /** * Compare the UUID to SubOwner. * @@ -1709,17 +2190,22 @@ bool IsSubOwner(const OicUuid_t* uuid) { 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; } @@ -1727,7 +2213,164 @@ bool IsSubOwner(const OicUuid_t* uuid) } 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. @@ -1735,6 +2378,10 @@ bool IsSubOwner(const OicUuid_t* uuid) */ void RestoreDoxmToInitState() { + + gConfirmState = CONFIRM_STATE_READY; + gConfirmMsgId = 0; + if(gDoxm) { OIC_LOG(INFO, TAG, "DOXM resource will revert back to initial status."); @@ -1750,3 +2397,38 @@ void RestoreDoxmToInitState() } } } + +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; +} +