IOT-2258: Allow secure and nonsecure endpoints with OCCreateResource.
[iotivity.git] / resource / csdk / security / src / doxmresource.c
index fdcb7de..b2a2445 100644 (file)
@@ -18,6 +18,7 @@
 //
 //-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
 #include "iotivity_config.h"
+#include "iotivity_debug.h"
 #include <stdlib.h>
 #include <string.h>
 
 #include <strings.h>
 #endif
 
-#ifdef __WITH_DTLS__
-#include "global.h"
-#endif
-
 #include "ocstack.h"
 #include "oic_malloc.h"
 #include "payload_logging.h"
 #include "utlist.h"
 #include "ocrandom.h"
 #include "ocpayload.h"
+#include "ocpayloadcbor.h"
 #include "cainterface.h"
 #include "ocserverrequest.h"
 #include "resourcemanager.h"
 #include "doxmresource.h"
 #include "pstatresource.h"
+#include "deviceonboardingstate.h"
 #include "aclresource.h"
 #include "amaclresource.h"
 #include "pconfresource.h"
 #include "credresource.h"
 #include "srmutility.h"
 #include "pinoxmcommon.h"
+#include "oxmverifycommon.h"
+#if defined(__WITH_DTLS__) || defined (__WITH_TLS__)
+#include <mbedtls/ssl_ciphersuites.h>
+#include <mbedtls/md.h>
+#include "pkix_interface.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.
@@ -61,36 +66,96 @@ 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
+
 static OicSecDoxm_t        *gDoxm = NULL;
 static OCResourceHandle    gDoxmHandle = NULL;
 
-static OicSecOxm_t gOicSecDoxmJustWorks = OIC_JUST_WORKS;
+static OicSecOxm_t gDoxmDefaultOxm = OIC_RANDOM_DEVICE_PIN;
 static OicSecDoxm_t gDefaultDoxm =
 {
     NULL,                   /* OicUrn_t *oxmType */
     0,                      /* size_t oxmTypeLen */
-    &gOicSecDoxmJustWorks,  /* uint16_t *oxm */
+    &gDoxmDefaultOxm,       /* uint16_t *oxm */
     1,                      /* size_t oxmLen */
-    OIC_JUST_WORKS,         /* uint16_t oxmSel */
+    OIC_RANDOM_DEVICE_PIN,  /* uint16_t oxmSel */
     SYMMETRIC_PAIR_WISE_KEY,/* OicSecCredType_t sct */
     false,                  /* bool owned */
     {.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 */
 };
 
+#define R PERMISSION_READ
+#define W PERMISSION_WRITE
+#define RW PERMISSION_READ | PERMISSION_WRITE
+
+// NOTE that this table must match the DoxmProperty_t enum in doxmresource.h
+static const uint8_t gDoxmPropertyAccessModes[DOXM_PROPERTY_COUNT][DOS_STATE_COUNT] =
+{ // RESET RFOTM  RFPRO   RFNOP   SRESET
+    { R,    R,      R,      R,      R   }, // .oxmtype TODO [IOT-2105]
+    { R,    R,      R,      R,      R   }, // .oxms
+    { R,    RW,     R,      R,      R   }, // .oxmsel
+    { R,    R,      R,      R,      R   }, // .sct
+    { R,    RW,     R,      R,      R   }, // .owned
+#ifdef MULTIPLE_OWNER
+    { RW,   RW,    RW,      RW,     RW  }, // .subowner
+    { RW,   RW,    RW,      RW,     RW  }, // .mom
+#endif // MULTIPLE_OWNER
+    { R,    RW,     R,      R,      R   }, // .deviceuuid
+    { R,    RW,     R,      R,      R   }, // .devowneruuid
+    { R,    RW,     R,      R,      RW  }  // .rowneruuid
+};
+
+#undef R
+#undef W
+#undef RW
+
+static bool IsPropertyReadOnly(DoxmProperty_t p,
+                               OicSecDeviceOnboardingState_t s)
+{
+    bool ret = false;
+
+    if (PERMISSION_READ == gDoxmPropertyAccessModes[p][s])
+    {
+        OIC_LOG_V(DEBUG, TAG, "%s: property %d is read-only in state %d.",
+           __func__, p, s);
+        ret = true;
+    }
+
+    return ret;
+}
+
 /**
- * This method is internal method.
- * the param roParsed is optionally used to know whether cborPayload has
- * at least read only property value or not.
- */
+ * Internal method converts CBOR into DOXM data, and determines if a read-only
+ *  Property was parsed in the CBOR payload.
+ *
+ * @param[in] cborPayload The doxm data in cbor format.
+ * @param[in] size Size of the cborPayload. In case 0 is provided it assigns CBOR_SIZE (255) value.
+ * @param[out] doxm Pointer to @ref OicSecDoxm_t.
+ * @param[out] roParsed Ptr to bool marked "true" iff a read-only Property is parsed
+ * @param[in] stateForReadOnlyCheck The state to use when determining if a Property is
+ *                              read-only.
+ *
+ * @return ::OC_STACK_OK for Success, otherwise some error value.
+*/
 static OCStackResult CBORPayloadToDoxmBin(const uint8_t *cborPayload, size_t size,
-                                OicSecDoxm_t **doxm, bool *roParsed);
+                                OicSecDoxm_t **doxm, bool *roParsed,
+                                OicSecDeviceOnboardingState_t stateForReadOnlyCheck);
 
 void DeleteDoxmBinData(OicSecDoxm_t* doxm)
 {
@@ -106,7 +171,7 @@ void DeleteDoxmBinData(OicSecDoxm_t* doxm)
         //clean oxm
         OICFree(doxm->oxm);
 
-#ifdef _ENABLE_MULTIPLE_OWNER_
+#ifdef MULTIPLE_OWNER
         //clean mom
         OICFree(doxm->mom);
 
@@ -121,15 +186,15 @@ void DeleteDoxmBinData(OicSecDoxm_t* doxm)
                 OICFree(subowner);
             }
         }
-#endif //_ENABLE_MULTIPLE_OWNER_
+#endif //MULTIPLE_OWNER
 
         //Clean doxm itself
         OICFree(doxm);
     }
 }
 
-OCStackResult DoxmToCBORPayload(const OicSecDoxm_t *doxm, uint8_t **payload, size_t *size,
-                                bool rwOnly)
+OCStackResult DoxmToCBORPayloadPartial(const OicSecDoxm_t *doxm,
+    uint8_t **payload, size_t *size, const bool *propertiesToInclude)
 {
     if (NULL == doxm || NULL == payload || NULL != *payload || NULL == size)
     {
@@ -152,93 +217,108 @@ OCStackResult DoxmToCBORPayload(const OicSecDoxm_t *doxm, uint8_t **payload, siz
     int64_t cborEncoderResult = CborNoError;
 
     uint8_t *outPayload = (uint8_t *)OICCalloc(1, cborLen);
-    VERIFY_NON_NULL(TAG, outPayload, ERROR);
+    VERIFY_NOT_NULL_RETURN(TAG, outPayload, ERROR, OC_STACK_ERROR);
+
     cbor_encoder_init(&encoder, outPayload, cborLen, 0);
 
     cborEncoderResult = cbor_encoder_create_map(&encoder, &doxmMap, CborIndefiniteLength);
     VERIFY_CBOR_SUCCESS(TAG, cborEncoderResult, "Failed Adding Doxm Map.");
 
-    //OxmType -- Not Mandatory
-    if (doxm->oxmTypeLen > 0)
+    // oxmtype
+    // TODO [IOT-2105]: resolve "oxmtype" undocumented tag/value
+    if (propertiesToInclude[DOXM_OXMTYPE] && doxm->oxmTypeLen > 0)
     {
+        OIC_LOG_V(DEBUG, TAG, "%s: including %s.", __func__, OIC_JSON_OXM_TYPE_NAME);
         CborEncoder oxmType;
         cborEncoderResult = cbor_encode_text_string(&doxmMap, OIC_JSON_OXM_TYPE_NAME,
             strlen(OIC_JSON_OXM_TYPE_NAME));
-        VERIFY_CBOR_SUCCESS(TAG, cborEncoderResult, "Failed Adding oxmType Tag.");
+        VERIFY_CBOR_SUCCESS(TAG, cborEncoderResult, "Failed Adding oxmtype Tag.");
         cborEncoderResult = cbor_encoder_create_array(&doxmMap, &oxmType, doxm->oxmTypeLen);
-        VERIFY_CBOR_SUCCESS(TAG, cborEncoderResult, "Failed Adding oxmType Array.");
+        VERIFY_CBOR_SUCCESS(TAG, cborEncoderResult, "Failed Adding oxmtype Array.");
 
         for (size_t i = 0; i < doxm->oxmTypeLen; i++)
         {
             cborEncoderResult = cbor_encode_text_string(&oxmType, doxm->oxmType[i],
                 strlen(doxm->oxmType[i]));
-            VERIFY_CBOR_SUCCESS(TAG, cborEncoderResult, "Failed Adding oxmType Value.");
+            VERIFY_CBOR_SUCCESS(TAG, cborEncoderResult, "Failed Adding oxmtype Value.");
         }
         cborEncoderResult = cbor_encoder_close_container(&doxmMap, &oxmType);
-        VERIFY_CBOR_SUCCESS(TAG, cborEncoderResult, "Failed Closing oxmType.");
+        VERIFY_CBOR_SUCCESS(TAG, cborEncoderResult, "Failed Closing oxmtype.");
     }
 
-    //Oxm -- Not Mandatory
-    if (doxm->oxmLen > 0 && false == rwOnly)
+    // oxms Property
+    if (propertiesToInclude[DOXM_OXMS] && doxm->oxmLen > 0)
     {
+        OIC_LOG_V(DEBUG, TAG, "%s: including %s Property.", __func__, OIC_JSON_OXMS_NAME);
         CborEncoder oxm;
         cborEncoderResult = cbor_encode_text_string(&doxmMap, OIC_JSON_OXMS_NAME,
             strlen(OIC_JSON_OXMS_NAME));
-        VERIFY_CBOR_SUCCESS(TAG, cborEncoderResult, "Failed Adding oxmName Tag.");
+        VERIFY_CBOR_SUCCESS(TAG, cborEncoderResult, "Failed Adding oxms Tag.");
         cborEncoderResult = cbor_encoder_create_array(&doxmMap, &oxm, doxm->oxmLen);
-        VERIFY_CBOR_SUCCESS(TAG, cborEncoderResult, "Failed Adding oxmName Array.");
+        VERIFY_CBOR_SUCCESS(TAG, cborEncoderResult, "Failed Adding oxms Array.");
 
         for (size_t i = 0; i < doxm->oxmLen; i++)
         {
             cborEncoderResult = cbor_encode_int(&oxm, doxm->oxm[i]);
-            VERIFY_CBOR_SUCCESS(TAG, cborEncoderResult, "Failed Adding oxmName Value");
+            VERIFY_CBOR_SUCCESS(TAG, cborEncoderResult, "Failed Adding oxms Value");
         }
         cborEncoderResult = cbor_encoder_close_container(&doxmMap, &oxm);
-        VERIFY_CBOR_SUCCESS(TAG, cborEncoderResult, "Failed Closing oxmName.");
+        VERIFY_CBOR_SUCCESS(TAG, cborEncoderResult, "Failed Closing oxms.");
     }
 
-    //OxmSel -- Mandatory
-    cborEncoderResult = cbor_encode_text_string(&doxmMap, OIC_JSON_OXM_SEL_NAME,
-        strlen(OIC_JSON_OXM_SEL_NAME));
-    VERIFY_CBOR_SUCCESS(TAG, cborEncoderResult, "Failed Adding Sel Tag.");
-    cborEncoderResult = cbor_encode_int(&doxmMap, doxm->oxmSel);
-    VERIFY_CBOR_SUCCESS(TAG, cborEncoderResult, "Failed Adding Sel Value.");
+    // oxmsel Property
+    if (propertiesToInclude[DOXM_OXMSEL] && doxm->oxmLen > 0)
+    {
+        OIC_LOG_V(DEBUG, TAG, "%s: including %s Property.", __func__, OIC_JSON_OXM_SEL_NAME);
+        cborEncoderResult = cbor_encode_text_string(&doxmMap, OIC_JSON_OXM_SEL_NAME,
+            strlen(OIC_JSON_OXM_SEL_NAME));
+        VERIFY_CBOR_SUCCESS(TAG, cborEncoderResult, "Failed Adding oxmsel Tag.");
+        cborEncoderResult = cbor_encode_int(&doxmMap, doxm->oxmSel);
+        VERIFY_CBOR_SUCCESS(TAG, cborEncoderResult, "Failed Adding oxmsel Value.");
+    }
 
-    //sct -- Mandatory
-    if (false == rwOnly)
+    // sct Property
+    if (propertiesToInclude[DOXM_SCT])
     {
+        OIC_LOG_V(DEBUG, TAG, "%s: including %s Property.", __func__, OIC_JSON_SUPPORTED_CRED_TYPE_NAME);
         cborEncoderResult = cbor_encode_text_string(&doxmMap, OIC_JSON_SUPPORTED_CRED_TYPE_NAME,
             strlen(OIC_JSON_SUPPORTED_CRED_TYPE_NAME));
-        VERIFY_CBOR_SUCCESS(TAG, cborEncoderResult, "Failed Adding Cred Type Tag");
+        VERIFY_CBOR_SUCCESS(TAG, cborEncoderResult, "Failed Adding sct Tag");
         cborEncoderResult = cbor_encode_int(&doxmMap, doxm->sct);
-        VERIFY_CBOR_SUCCESS(TAG, cborEncoderResult, "Failed Adding Cred Type Value.");
+        VERIFY_CBOR_SUCCESS(TAG, cborEncoderResult, "Failed Adding sct Value.");
     }
 
-    //Owned -- Mandatory
-    cborEncoderResult = cbor_encode_text_string(&doxmMap, OIC_JSON_OWNED_NAME,
-        strlen(OIC_JSON_OWNED_NAME));
-    VERIFY_CBOR_SUCCESS(TAG, cborEncoderResult, "Failed Adding Owned Tag.");
-    cborEncoderResult = cbor_encode_boolean(&doxmMap, doxm->owned);
-    VERIFY_CBOR_SUCCESS(TAG, cborEncoderResult, "Failed Adding Owned Value.");
+    // owned Property
+    if (propertiesToInclude[DOXM_OWNED])
+    {
+        OIC_LOG_V(DEBUG, TAG, "%s: including %s Property.", __func__, OIC_JSON_OWNED_NAME);
+        cborEncoderResult = cbor_encode_text_string(&doxmMap, OIC_JSON_OWNED_NAME,
+            strlen(OIC_JSON_OWNED_NAME));
+        VERIFY_CBOR_SUCCESS(TAG, cborEncoderResult, "Failed Adding owned Tag.");
+        cborEncoderResult = cbor_encode_boolean(&doxmMap, doxm->owned);
+        VERIFY_CBOR_SUCCESS(TAG, cborEncoderResult, "Failed Adding owned Value.");
+    }
 
-    if (false == rwOnly)
+    // deviceuuid Property
+    if (propertiesToInclude[DOXM_DEVICEUUID])
     {
-        //DeviceId -- Mandatory
+        OIC_LOG_V(DEBUG, TAG, "%s: including %s Property.", __func__, OIC_JSON_DEVICE_ID_NAME);
         cborEncoderResult = cbor_encode_text_string(&doxmMap, OIC_JSON_DEVICE_ID_NAME,
             strlen(OIC_JSON_DEVICE_ID_NAME));
-        VERIFY_CBOR_SUCCESS(TAG, cborEncoderResult, "Failed Adding Device Id Tag.");
+        VERIFY_CBOR_SUCCESS(TAG, cborEncoderResult, "Failed Adding deviceuuid Tag.");
         ret = ConvertUuidToStr(&doxm->deviceID, &strUuid);
         VERIFY_SUCCESS(TAG, OC_STACK_OK == ret , ERROR);
         cborEncoderResult = cbor_encode_text_string(&doxmMap, strUuid, strlen(strUuid));
-        VERIFY_CBOR_SUCCESS(TAG, cborEncoderResult, "Failed Adding Device Id Value.");
+        VERIFY_CBOR_SUCCESS(TAG, cborEncoderResult, "Failed Adding deviceuuid Value.");
         OICFree(strUuid);
         strUuid = NULL;
     }
 
-#ifdef _ENABLE_MULTIPLE_OWNER_
+#ifdef MULTIPLE_OWNER
     //Device SubOwnerID -- Not Mandatory
-    if(doxm->subOwners)
+    if(propertiesToInclude[DOXM_SUBOWNER] && doxm->subOwners)
     {
+        OIC_LOG_V(DEBUG, TAG, "%s: including %s Property.", __func__, OIC_JSON_SUBOWNERID_NAME);
         size_t subOwnerLen = 0;
         OicSecSubOwner_t* subOwner = NULL;
         LL_FOREACH(doxm->subOwners, subOwner)
@@ -256,11 +336,11 @@ OCStackResult DoxmToCBORPayload(const OicSecDoxm_t *doxm, uint8_t **payload, siz
         subOwner = NULL;
         LL_FOREACH(doxm->subOwners, subOwner)
         {
-            char* strUuid = NULL;
-            ret = ConvertUuidToStr(&subOwner->uuid, &strUuid);
+            char* strSubOwnerUuid = NULL;
+            ret = ConvertUuidToStr(&subOwner->uuid, &strSubOwnerUuid);
             VERIFY_SUCCESS(TAG, OC_STACK_OK == ret , ERROR);
-            cborEncoderResult = cbor_encode_text_string(&subOwners, strUuid, strlen(strUuid));
-            OICFree(strUuid);
+            cborEncoderResult = cbor_encode_text_string(&subOwners, strSubOwnerUuid, strlen(strSubOwnerUuid));
+            OICFree(strSubOwnerUuid);
             VERIFY_CBOR_SUCCESS(TAG, cborEncoderResult, "Failed Adding SubOwnerId Value");
         }
         cborEncoderResult = cbor_encoder_close_container(&doxmMap, &subOwners);
@@ -268,44 +348,46 @@ OCStackResult DoxmToCBORPayload(const OicSecDoxm_t *doxm, uint8_t **payload, siz
     }
 
     //Multiple Owner Mode -- Not Mandatory
-    if(doxm->mom)
+    if(propertiesToInclude[DOXM_MOM] && doxm->mom)
     {
+        OIC_LOG_V(DEBUG, TAG, "%s: including %s Property.", __func__, OIC_JSON_MOM_NAME);
         cborEncoderResult = cbor_encode_text_string(&doxmMap, OIC_JSON_MOM_NAME,
             strlen(OIC_JSON_MOM_NAME));
         VERIFY_CBOR_SUCCESS(TAG, cborEncoderResult, "Failed Adding mom Tag");
         cborEncoderResult = cbor_encode_int(&doxmMap, (int64_t)doxm->mom->mode);
         VERIFY_CBOR_SUCCESS(TAG, cborEncoderResult, "Failed Adding mom Value.");
     }
-#endif //_ENABLE_MULTIPLE_OWNER_
-
-    //devownerid -- Mandatory
-    cborEncoderResult = cbor_encode_text_string(&doxmMap, OIC_JSON_DEVOWNERID_NAME,
-        strlen(OIC_JSON_DEVOWNERID_NAME));
-    VERIFY_CBOR_SUCCESS(TAG, cborEncoderResult, "Failed Adding Owner Id Tag.");
-    ret = ConvertUuidToStr(&doxm->owner, &strUuid);
-    VERIFY_SUCCESS(TAG, OC_STACK_OK == ret , ERROR);
-    cborEncoderResult = cbor_encode_text_string(&doxmMap, strUuid, strlen(strUuid));
-    VERIFY_CBOR_SUCCESS(TAG, cborEncoderResult, "Failed Adding Owner Id Value.");
-    OICFree(strUuid);
-    strUuid = NULL;
-
-    //ROwner -- Mandatory
-    cborEncoderResult = cbor_encode_text_string(&doxmMap, OIC_JSON_ROWNERID_NAME,
-        strlen(OIC_JSON_ROWNERID_NAME));
-    VERIFY_CBOR_SUCCESS(TAG, cborEncoderResult, "Failed Adding ROwner Id Tag.");
-    ret = ConvertUuidToStr(&doxm->rownerID, &strUuid);
-    VERIFY_SUCCESS(TAG, OC_STACK_OK == ret , ERROR);
-    cborEncoderResult = cbor_encode_text_string(&doxmMap, strUuid, strlen(strUuid));
-    VERIFY_CBOR_SUCCESS(TAG, cborEncoderResult, "Failed Adding ROwner Id Value.");
-    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.");
+#endif //MULTIPLE_OWNER
+
+    // devowneruuid Property
+    if (propertiesToInclude[DOXM_DEVOWNERUUID])
+    {
+        OIC_LOG_V(DEBUG, TAG, "%s: including %s Property.", __func__, OIC_JSON_DEVOWNERID_NAME);
+        cborEncoderResult = cbor_encode_text_string(&doxmMap, OIC_JSON_DEVOWNERID_NAME,
+            strlen(OIC_JSON_DEVOWNERID_NAME));
+        VERIFY_CBOR_SUCCESS(TAG, cborEncoderResult, "Failed Adding devowneruuid Tag.");
+        ret = ConvertUuidToStr(&doxm->owner, &strUuid);
+        VERIFY_SUCCESS(TAG, OC_STACK_OK == ret , ERROR);
+        cborEncoderResult = cbor_encode_text_string(&doxmMap, strUuid, strlen(strUuid));
+        VERIFY_CBOR_SUCCESS(TAG, cborEncoderResult, "Failed Adding devowneruuid Value.");
+        OICFree(strUuid);
+        strUuid = NULL;
+    }
+
+    // rowneruuid Property
+    if (propertiesToInclude[DOXM_ROWNERUUID])
+    {
+        OIC_LOG_V(DEBUG, TAG, "%s: including %s Property.", __func__, OIC_JSON_ROWNERID_NAME);
+        cborEncoderResult = cbor_encode_text_string(&doxmMap, OIC_JSON_ROWNERID_NAME,
+            strlen(OIC_JSON_ROWNERID_NAME));
+        VERIFY_CBOR_SUCCESS(TAG, cborEncoderResult, "Failed Adding rowneruuid Tag.");
+        ret = ConvertUuidToStr(&doxm->rownerID, &strUuid);
+        VERIFY_SUCCESS(TAG, OC_STACK_OK == ret , ERROR);
+        cborEncoderResult = cbor_encode_text_string(&doxmMap, strUuid, strlen(strUuid));
+        VERIFY_CBOR_SUCCESS(TAG, cborEncoderResult, "Failed Adding rowneruuid Value.");
+        OICFree(strUuid);
+        strUuid = NULL;
+    }
 
     //RT -- Mandatory
     CborEncoder rtArray;
@@ -324,12 +406,12 @@ OCStackResult DoxmToCBORPayload(const OicSecDoxm_t *doxm, uint8_t **payload, siz
     VERIFY_CBOR_SUCCESS(TAG, cborEncoderResult, "Failed Closing RT.");
 
     //IF-- Mandatory
-     CborEncoder ifArray;
-     cborEncoderResult = cbor_encode_text_string(&doxmMap, OIC_JSON_IF_NAME,
-             strlen(OIC_JSON_IF_NAME));
-     VERIFY_CBOR_SUCCESS(TAG, cborEncoderResult, "Failed Addding IF Name Tag.");
-     cborEncoderResult = cbor_encoder_create_array(&doxmMap, &ifArray, 1);
-     VERIFY_CBOR_SUCCESS(TAG, cborEncoderResult, "Failed Addding IF Value.");
+    CborEncoder ifArray;
+    cborEncoderResult = cbor_encode_text_string(&doxmMap, OIC_JSON_IF_NAME,
+       strlen(OIC_JSON_IF_NAME));
+    VERIFY_CBOR_SUCCESS(TAG, cborEncoderResult, "Failed Addding IF Name Tag.");
+    cborEncoderResult = cbor_encoder_create_array(&doxmMap, &ifArray, 1);
+    VERIFY_CBOR_SUCCESS(TAG, cborEncoderResult, "Failed Addding IF Value.");
     for (size_t i = 0; i < 1; i++)
     {
         cborEncoderResult = cbor_encode_text_string(&ifArray, OC_RSRVD_INTERFACE_DEFAULT,
@@ -344,7 +426,7 @@ OCStackResult DoxmToCBORPayload(const OicSecDoxm_t *doxm, uint8_t **payload, siz
 
     if (CborNoError == cborEncoderResult)
     {
-        *size = encoder.ptr - outPayload;
+        *size = cbor_encoder_get_buffer_size(&encoder, outPayload);
         *payload = outPayload;
         ret = OC_STACK_OK;
     }
@@ -354,11 +436,12 @@ 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 += 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);
+        ret = DoxmToCBORPayloadPartial(doxm, payload, &cborLen, propertiesToInclude);
         *size = cborLen;
     }
 
@@ -374,14 +457,30 @@ exit:
     return ret;
 }
 
+OCStackResult DoxmToCBORPayload(const OicSecDoxm_t *doxm,
+                                 uint8_t **payload, size_t *size)
+{
+    bool allProps[DOXM_PROPERTY_COUNT];
+
+    for (int i = 0; i < DOXM_PROPERTY_COUNT; i++)
+    {
+        allProps[i] = true;
+    }
+
+    allProps[DOXM_OXMTYPE] = false; // TODO [IOT-2105]: resolve "oxmtype" undocumented tag/value
+
+    return DoxmToCBORPayloadPartial(doxm, payload, size, allProps);
+}
+
 OCStackResult CBORPayloadToDoxm(const uint8_t *cborPayload, size_t size,
                                 OicSecDoxm_t **secDoxm)
 {
-    return CBORPayloadToDoxmBin(cborPayload, size, secDoxm, NULL);
+    return CBORPayloadToDoxmBin(cborPayload, size, secDoxm, NULL, DOS_RESET);
 }
 
 static OCStackResult CBORPayloadToDoxmBin(const uint8_t *cborPayload, size_t size,
-                                OicSecDoxm_t **secDoxm, bool *roParsed)
+                                OicSecDoxm_t **secDoxm, bool *roParsed,
+                                OicSecDeviceOnboardingState_t stateForReadOnlyCheck)
 {
     if (NULL == cborPayload || NULL == secDoxm || NULL != *secDoxm || 0 == size)
     {
@@ -400,12 +499,15 @@ static OCStackResult CBORPayloadToDoxmBin(const uint8_t *cborPayload, size_t siz
     cbor_parser_init(cborPayload, size, 0, &parser, &doxmCbor);
     CborValue doxmMap;
     OicSecDoxm_t *doxm = (OicSecDoxm_t *)OICCalloc(1, sizeof(*doxm));
-    VERIFY_NON_NULL(TAG, doxm, ERROR);
+    VERIFY_NOT_NULL(TAG, doxm, ERROR);
 
     cborFindResult = cbor_value_map_find_value(&doxmCbor, OIC_JSON_OXM_TYPE_NAME, &doxmMap);
-    //OxmType -- not Mandatory
+    // OxmType
+    // TODO [IOT-2105]: resolve "oxmtype" undocumented tag/value
     if (CborNoError == cborFindResult && cbor_value_is_array(&doxmMap))
     {
+        OIC_LOG(DEBUG, TAG, "Found doxm.oxmtype tag in doxmMap.");
+
         CborValue oxmType;
 
         cborFindResult = cbor_value_get_array_length(&doxmMap, &doxm->oxmTypeLen);
@@ -413,17 +515,18 @@ static OCStackResult CBORPayloadToDoxmBin(const uint8_t *cborPayload, size_t siz
         VERIFY_SUCCESS(TAG, doxm->oxmTypeLen != 0, ERROR);
 
         doxm->oxmType = (OicUrn_t *)OICCalloc(doxm->oxmTypeLen, sizeof(*doxm->oxmType));
-        VERIFY_NON_NULL(TAG, doxm->oxmType, ERROR);
+        VERIFY_NOT_NULL(TAG, doxm->oxmType, ERROR);
 
         cborFindResult = cbor_value_enter_container(&doxmMap, &oxmType);
         VERIFY_CBOR_SUCCESS(TAG, cborFindResult, "Failed Entering oxmType Array.")
 
         int i = 0;
-        size_t len = 0;
+        size_t oxmTypeStrlen = 0;
         while (cbor_value_is_valid(&oxmType) && cbor_value_is_text_string(&oxmType))
         {
+            OIC_LOG_V(DEBUG, TAG, "Read doxm.oxmtype value = %s", oxmType);
             cborFindResult = cbor_value_dup_text_string(&oxmType, &doxm->oxmType[i++],
-                                                        &len, NULL);
+                                                        &oxmTypeStrlen, NULL);
             VERIFY_CBOR_SUCCESS(TAG, cborFindResult, "Failed Finding omxType text string.");
             cborFindResult = cbor_value_advance(&oxmType);
             VERIFY_CBOR_SUCCESS(TAG, cborFindResult, "Failed Advancing oxmType.");
@@ -431,19 +534,21 @@ static OCStackResult CBORPayloadToDoxmBin(const uint8_t *cborPayload, size_t siz
     }
 
     cborFindResult = cbor_value_map_find_value(&doxmCbor, OIC_JSON_OXMS_NAME, &doxmMap);
-    //Oxm -- not Mandatory
+
+    // oxms
     if (CborNoError == cborFindResult && cbor_value_is_array(&doxmMap))
     {
+        OIC_LOG(DEBUG, TAG, "Found doxm.oxms tag in doxmMap.");
         CborValue oxm;
         cborFindResult = cbor_value_get_array_length(&doxmMap, &doxm->oxmLen);
-        VERIFY_CBOR_SUCCESS(TAG, cborFindResult, "Failed Finding oxmName array Length.");
+        VERIFY_CBOR_SUCCESS(TAG, cborFindResult, "Failed Finding oxms array Length.");
         VERIFY_SUCCESS(TAG, doxm->oxmLen != 0, ERROR);
 
         doxm->oxm = (OicSecOxm_t *)OICCalloc(doxm->oxmLen, sizeof(*doxm->oxm));
-        VERIFY_NON_NULL(TAG, doxm->oxm, ERROR);
+        VERIFY_NOT_NULL(TAG, doxm->oxm, ERROR);
 
         cborFindResult = cbor_value_enter_container(&doxmMap, &oxm);
-        VERIFY_CBOR_SUCCESS(TAG, cborFindResult, "Failed Entering oxmName Array.")
+        VERIFY_CBOR_SUCCESS(TAG, cborFindResult, "Failed Entering oxms Array.")
 
         int i = 0;
         while (cbor_value_is_valid(&oxm) && cbor_value_is_integer(&oxm))
@@ -451,22 +556,26 @@ static OCStackResult CBORPayloadToDoxmBin(const uint8_t *cborPayload, size_t siz
             int tmp;
 
             cborFindResult = cbor_value_get_int(&oxm, &tmp);
-            VERIFY_CBOR_SUCCESS(TAG, cborFindResult, "Failed Finding oxmName Value")
+            VERIFY_CBOR_SUCCESS(TAG, cborFindResult, "Failed Finding oxms Value")
+            OIC_LOG_V(DEBUG, TAG, "Read doxm.oxms value = %d", tmp);
             doxm->oxm[i++] = (OicSecOxm_t)tmp;
             cborFindResult = cbor_value_advance(&oxm);
-            VERIFY_CBOR_SUCCESS(TAG, cborFindResult, "Failed Advancing oxmName.")
+            VERIFY_CBOR_SUCCESS(TAG, cborFindResult, "Failed Advancing oxms.")
         }
 
         if (roParsed)
         {
-            *roParsed = true;
+            if (IsPropertyReadOnly(DOXM_OXMS, stateForReadOnlyCheck))
+            {
+                *roParsed = true;
+            }
         }
     }
     else
     {
-        VERIFY_NON_NULL(TAG, gDoxm, ERROR);
+        VERIFY_NOT_NULL(TAG, gDoxm, ERROR);
         doxm->oxm = (OicSecOxm_t *) OICCalloc(gDoxm->oxmLen, sizeof(*doxm->oxm));
-        VERIFY_NON_NULL(TAG, doxm->oxm, ERROR);
+        VERIFY_NOT_NULL(TAG, doxm->oxm, ERROR);
         doxm->oxmLen = gDoxm->oxmLen;
         for (size_t i = 0; i < gDoxm->oxmLen; i++)
         {
@@ -474,115 +583,156 @@ static OCStackResult CBORPayloadToDoxmBin(const uint8_t *cborPayload, size_t siz
         }
     }
 
+    // oxmsel
     cborFindResult = cbor_value_map_find_value(&doxmCbor, OIC_JSON_OXM_SEL_NAME, &doxmMap);
     if (CborNoError == cborFindResult && cbor_value_is_integer(&doxmMap))
     {
+        OIC_LOG(DEBUG, TAG, "Found doxm.oxmsel tag in doxmMap.");
+
         int oxmSel;
 
         cborFindResult = cbor_value_get_int(&doxmMap, &oxmSel);
         VERIFY_CBOR_SUCCESS(TAG, cborFindResult, "Failed Finding Sel Name Value.")
+        OIC_LOG_V(DEBUG, TAG, "Read doxm.oxmsel value = %d", oxmSel);
         doxm->oxmSel = (OicSecOxm_t)oxmSel;
+        if (roParsed)
+        {
+            if (IsPropertyReadOnly(DOXM_OXMSEL, stateForReadOnlyCheck))
+            {
+                *roParsed = true;
+            }
+        }
     }
     else // PUT/POST JSON may not have oxmsel so set it to the gDoxm->oxmSel
     {
-        VERIFY_NON_NULL(TAG, gDoxm, ERROR);
+        VERIFY_NOT_NULL(TAG, gDoxm, ERROR);
         doxm->oxmSel = gDoxm->oxmSel;
     }
 
+    // sct
     cborFindResult = cbor_value_map_find_value(&doxmCbor, OIC_JSON_SUPPORTED_CRED_TYPE_NAME, &doxmMap);
     if (CborNoError == cborFindResult && cbor_value_is_integer(&doxmMap))
     {
+        OIC_LOG(DEBUG, TAG, "Found doxm.oxmsel tag in doxmMap.");
         int sct;
 
         cborFindResult = cbor_value_get_int(&doxmMap, &sct);
         VERIFY_CBOR_SUCCESS(TAG, cborFindResult, "Failed Finding Sct Name Value.")
+        OIC_LOG_V(DEBUG, TAG, "Read doxm.sct value = %d", sct);
         doxm->sct = (OicSecCredType_t)sct;
 
         if (roParsed)
         {
-            *roParsed = true;
+            if (IsPropertyReadOnly(DOXM_SCT, stateForReadOnlyCheck))
+            {
+                *roParsed = true;
+            }
         }
     }
     else // PUT/POST JSON may not have sct so set it to the gDoxm->sct
     {
-        VERIFY_NON_NULL(TAG, gDoxm, ERROR);
+        VERIFY_NOT_NULL(TAG, gDoxm, ERROR);
         doxm->sct = gDoxm->sct;
     }
 
+    // owned
     cborFindResult = cbor_value_map_find_value(&doxmCbor, OIC_JSON_OWNED_NAME, &doxmMap);
     if (CborNoError == cborFindResult && cbor_value_is_boolean(&doxmMap))
     {
+        OIC_LOG(DEBUG, TAG, "Found doxm.owned tag in doxmMap.");
         cborFindResult = cbor_value_get_boolean(&doxmMap, &doxm->owned);
         VERIFY_CBOR_SUCCESS(TAG, cborFindResult, "Failed Finding Owned Value.")
+        OIC_LOG_V(DEBUG, TAG, "Read doxm.owned value = %s", doxm->owned?"true":"false");
+
+        if (roParsed)
+        {
+            if (IsPropertyReadOnly(DOXM_OWNED, stateForReadOnlyCheck))
+            {
+                *roParsed = true;
+            }
+        }
     }
     else // PUT/POST JSON may not have owned so set it to the gDomx->owned
     {
-        VERIFY_NON_NULL(TAG, gDoxm, ERROR);
+        VERIFY_NOT_NULL(TAG, gDoxm, ERROR);
         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;
-    }
-
+    // deviceuuid
     cborFindResult = cbor_value_map_find_value(&doxmCbor, OIC_JSON_DEVICE_ID_NAME, &doxmMap);
     if (CborNoError == cborFindResult && cbor_value_is_text_string(&doxmMap))
     {
+        OIC_LOG(DEBUG, TAG, "Found doxm.deviceuuid tag in doxmMap.");
         cborFindResult = cbor_value_dup_text_string(&doxmMap, &strUuid , &len, NULL);
         VERIFY_CBOR_SUCCESS(TAG, cborFindResult, "Failed Finding Device Id Value.");
-        ret = ConvertStrToUuid(strUuid , &doxm->deviceID);
+        OIC_LOG_V(DEBUG, TAG, "Read doxm.deviceuuid value = %s", strUuid);
+        ret = ConvertStrToUuid(strUuid, &doxm->deviceID);
         VERIFY_SUCCESS(TAG, OC_STACK_OK == ret, ERROR);
         OICFree(strUuid);
         strUuid  = NULL;
 
         if (roParsed)
         {
-            *roParsed = true;
+            if (IsPropertyReadOnly(DOXM_DEVICEUUID, stateForReadOnlyCheck))
+            {
+                *roParsed = true;
+            }
         }
     }
     else
     {
-        VERIFY_NON_NULL(TAG, gDoxm, ERROR);
+        VERIFY_NOT_NULL(TAG, gDoxm, ERROR);
         memcpy(doxm->deviceID.id, &gDoxm->deviceID.id, sizeof(doxm->deviceID.id));
     }
 
+    // devowneruuid
     cborFindResult = cbor_value_map_find_value(&doxmCbor, OIC_JSON_DEVOWNERID_NAME, &doxmMap);
     if (CborNoError == cborFindResult && cbor_value_is_text_string(&doxmMap))
     {
+        OIC_LOG(DEBUG, TAG, "Found doxm.devowneruuid tag in doxmMap.");
         cborFindResult = cbor_value_dup_text_string(&doxmMap, &strUuid , &len, NULL);
-        VERIFY_CBOR_SUCCESS(TAG, cborFindResult, "Failed Finding Owner Value.");
+        VERIFY_CBOR_SUCCESS(TAG, cborFindResult, "Failed Finding devowneruuid Value.");
+        OIC_LOG_V(DEBUG, TAG, "Read doxm.devowneruuid value = %s", strUuid);
         ret = ConvertStrToUuid(strUuid , &doxm->owner);
         VERIFY_SUCCESS(TAG, OC_STACK_OK == ret, ERROR);
         OICFree(strUuid);
         strUuid  = NULL;
+
+        if (roParsed)
+        {
+            if (IsPropertyReadOnly(DOXM_DEVOWNERUUID, stateForReadOnlyCheck))
+            {
+                *roParsed = true;
+            }
+        }
     }
     else
     {
-        VERIFY_NON_NULL(TAG, gDoxm, ERROR);
+        VERIFY_NOT_NULL(TAG, gDoxm, ERROR);
         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))
     {
+        OIC_LOG(DEBUG, TAG, "Found doxm.mom tag in doxmMap.");
         int mode = 0;
         cborFindResult = cbor_value_get_int(&doxmMap, &mode);
         VERIFY_CBOR_SUCCESS(TAG, cborFindResult, "Failed Finding mom Name Value.")
         if(NULL == doxm->mom)
         {
             doxm->mom = (OicSecMom_t*)OICCalloc(1, sizeof(OicSecMom_t));
-            VERIFY_NON_NULL(TAG, doxm->mom, ERROR);
+            VERIFY_NOT_NULL(TAG, doxm->mom, ERROR);
         }
         doxm->mom->mode = (OicSecMomType_t)mode;
+        if (roParsed)
+        {
+            if (IsPropertyReadOnly(DOXM_MOM, stateForReadOnlyCheck))
+            {
+                *roParsed = true;
+            }
+        }
     }
     else if(NULL != gDoxm && NULL != gDoxm->mom)
     {
@@ -590,7 +740,7 @@ static OCStackResult CBORPayloadToDoxmBin(const uint8_t *cborPayload, size_t siz
         if(NULL == doxm->mom)
         {
             doxm->mom = (OicSecMom_t*)OICCalloc(1, sizeof(OicSecMom_t));
-            VERIFY_NON_NULL(TAG, doxm->mom, ERROR);
+            VERIFY_NOT_NULL(TAG, doxm->mom, ERROR);
         }
         doxm->mom->mode = gDoxm->mom->mode;
     }
@@ -598,6 +748,7 @@ static OCStackResult CBORPayloadToDoxmBin(const uint8_t *cborPayload, size_t siz
     cborFindResult = cbor_value_map_find_value(&doxmCbor, OIC_JSON_SUBOWNERID_NAME, &doxmMap);
     if(CborNoError == cborFindResult && cbor_value_is_array(&doxmMap))
     {
+        OIC_LOG(DEBUG, TAG, "Found doxm.subowner tag in doxmMap.");
         size_t subOwnerLen = 0;
         CborValue subOwnerCbor;
         cborFindResult = cbor_value_get_array_length(&doxmMap, &subOwnerLen);
@@ -611,16 +762,16 @@ static OCStackResult CBORPayloadToDoxmBin(const uint8_t *cborPayload, size_t siz
         {
             OCStackResult convertRes = OC_STACK_ERROR;
             OicSecSubOwner_t* subOwner = NULL;
-            char* strUuid = NULL;
+            char* strSubOwnerUuid = NULL;
             size_t uuidLen = 0;
 
-            cborFindResult = cbor_value_dup_text_string(&subOwnerCbor, &strUuid, &uuidLen, NULL);
+            cborFindResult = cbor_value_dup_text_string(&subOwnerCbor, &strSubOwnerUuid, &uuidLen, NULL);
             VERIFY_CBOR_SUCCESS(TAG, cborFindResult, "Failed Finding SubOwnerId Value");
 
             subOwner = (OicSecSubOwner_t*)OICCalloc(1, sizeof(OicSecSubOwner_t));
-            VERIFY_NON_NULL(TAG, subOwner, ERROR);
+            VERIFY_NOT_NULL(TAG, subOwner, ERROR);
 
-            convertRes = ConvertStrToUuid(strUuid, &subOwner->uuid);
+            convertRes = ConvertStrToUuid(strSubOwnerUuid, &subOwner->uuid);
             VERIFY_SUCCESS(TAG, OC_STACK_OK == convertRes, ERROR);
             subOwner->status = MOT_STATUS_DONE;
             LL_APPEND(doxm->subOwners, subOwner);
@@ -628,6 +779,13 @@ static OCStackResult CBORPayloadToDoxmBin(const uint8_t *cborPayload, size_t siz
             cborFindResult = cbor_value_advance(&subOwnerCbor);
             VERIFY_CBOR_SUCCESS(TAG, cborFindResult, "Failed Advancing SubOwnerId.")
         }
+        if (roParsed)
+        {
+            if (IsPropertyReadOnly(DOXM_SUBOWNER, stateForReadOnlyCheck))
+            {
+                *roParsed = true;
+            }
+        }
     }
     else if(NULL != gDoxm && NULL != gDoxm->subOwners)
     {
@@ -636,7 +794,7 @@ static OCStackResult CBORPayloadToDoxmBin(const uint8_t *cborPayload, size_t siz
         LL_FOREACH(gDoxm->subOwners, subOwnerItor)
         {
             OicSecSubOwner_t* subOwnerId = (OicSecSubOwner_t*)OICCalloc(1, sizeof(OicSecSubOwner_t));
-            VERIFY_NON_NULL(TAG, subOwnerId, ERROR);
+            VERIFY_NOT_NULL(TAG, subOwnerId, ERROR);
 
             memcpy(&subOwnerId->uuid, &subOwnerItor->uuid, sizeof(OicUuid_t));
             subOwnerId->status = MOT_STATUS_DONE;
@@ -644,21 +802,32 @@ static OCStackResult CBORPayloadToDoxmBin(const uint8_t *cborPayload, size_t siz
             LL_APPEND(doxm->subOwners, subOwnerId);
         }
     }
-#endif //_ENABLE_MULTIPLE_OWNER_
+#endif //MULTIPLE_OWNER
 
+    // rowneruuid
     cborFindResult = cbor_value_map_find_value(&doxmCbor, OIC_JSON_ROWNERID_NAME, &doxmMap);
     if (CborNoError == cborFindResult && cbor_value_is_text_string(&doxmMap))
     {
+        OIC_LOG(DEBUG, TAG, "Found doxm.rowneruuid tag in doxmMap.");
         cborFindResult = cbor_value_dup_text_string(&doxmMap, &strUuid , &len, NULL);
-        VERIFY_CBOR_SUCCESS(TAG, cborFindResult, "Failed Finding ROwner Value.");
+        VERIFY_CBOR_SUCCESS(TAG, cborFindResult, "Failed Finding rowneruuid Value.");
+        OIC_LOG_V(DEBUG, TAG, "Read doxm.rowneruuid value = %s", strUuid);
         ret = ConvertStrToUuid(strUuid , &doxm->rownerID);
         VERIFY_SUCCESS(TAG, OC_STACK_OK == ret, ERROR);
         OICFree(strUuid);
         strUuid  = NULL;
+
+        if (roParsed)
+        {
+            if (IsPropertyReadOnly(DOXM_ROWNERUUID, stateForReadOnlyCheck))
+            {
+                *roParsed = true;
+            }
+        }
     }
     else
     {
-        VERIFY_NON_NULL(TAG, gDoxm, ERROR);
+        VERIFY_NOT_NULL(TAG, gDoxm, ERROR);
         memcpy(doxm->rownerID.id, gDoxm->rownerID.id, sizeof(doxm->rownerID.id));
     }
 
@@ -690,7 +859,7 @@ static bool UpdatePersistentStorage(OicSecDoxm_t * doxm)
         // Convert Doxm data into CBOR for update to persistent storage
         uint8_t *payload = NULL;
         size_t size = 0;
-        OCStackResult res = DoxmToCBORPayload(doxm, &payload, &size, false);
+        OCStackResult res = DoxmToCBORPayload(doxm, &payload, &size);
         if (payload && (OC_STACK_OK == res)
             && (OC_STACK_OK == UpdateSecureResourceInPS(OIC_JSON_DOXM_NAME, payload, size)))
         {
@@ -727,14 +896,13 @@ static bool ValidateQuery(const char * query)
 
     bool bOwnedQry = false;         // does querystring contains 'owned' query ?
     bool bOwnedMatch = false;       // does 'owned' query value matches with doxm.owned status?
-    bool bDeviceIDQry = false;      // does querystring contains 'deviceid' query ?
-    bool bDeviceIDMatch = false;    // does 'deviceid' query matches with doxm.deviceid ?
+    bool bDeviceIDQry = false;      // does querystring contains 'deviceuuid' query ?
+    bool bDeviceIDMatch = false;    // does 'deviceuuid' query matches with doxm.deviceuuid ?
     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};
 
@@ -757,10 +925,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)
             {
@@ -778,13 +945,18 @@ 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)
         {
             bDeviceIDQry = true;
             OicUuid_t subject = {.id={0}};
 
+            if (sizeof(subject.id) < parseIter.valLen)
+            {
+                OIC_LOG (ERROR, TAG, "Subject ID length is too long");
+                return false;
+            }
             memcpy(subject.id, parseIter.valPos, parseIter.valLen);
             if (0 == memcmp(&gDoxm->deviceID.id, &subject.id, sizeof(gDoxm->deviceID.id)))
             {
@@ -803,14 +975,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)
@@ -841,7 +1007,7 @@ static OCEntityHandlerResult HandleDoxmGetRequest (const OCEntityHandlerRequest
 
     if (ehRet == OC_EH_OK)
     {
-        if (OC_STACK_OK != DoxmToCBORPayload(gDoxm, &payload, &size, false))
+        if (OC_STACK_OK != DoxmToCBORPayload(gDoxm, &payload, &size))
         {
             OIC_LOG(WARNING, TAG, "DoxmToCBORPayload failed in HandleDoxmGetRequest");
         }
@@ -859,61 +1025,56 @@ static OCEntityHandlerResult HandleDoxmGetRequest (const OCEntityHandlerRequest
     return ehRet;
 }
 
-static void updateWriteableProperty(const OicSecDoxm_t* src, OicSecDoxm_t* dst)
+OCStackResult DoxmUpdateWriteableProperty(const OicSecDoxm_t* src, OicSecDoxm_t* dst)
 {
+    OCStackResult result = OC_STACK_OK;
+
     if(src && dst)
-   {
-        // update oxmsel
+    {
+        // Update oxmsel
         dst->oxmSel = src->oxmSel;
 
-        //update owner
+        // Update owner
         memcpy(&(dst->owner), &(src->owner), sizeof(OicUuid_t));
 
-        //update rowner
+        // Update rowner
         memcpy(&(dst->rownerID), &(src->rownerID), sizeof(OicUuid_t));
 
-        //Update owned status
+        // 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");
+            OIC_LOG(DEBUG, TAG, "Detected 'mom' property");
             if(NULL == dst->mom)
             {
                 dst->mom = (OicSecMom_t*)OICCalloc(1, sizeof(OicSecMom_t));
-                if(NULL != dst->mom)
+                if (NULL == dst->mom)
                 {
-                    dst->mom->mode = src->mom->mode;
+                    result = OC_STACK_NO_MEMORY;
                 }
             }
+
+            if (NULL != dst->mom)
+            {
+                dst->mom->mode = src->mom->mode;
+            }
         }
-#endif //_ENABLE_MULTIPLE_OWNER_
+#endif //MULTIPLE_OWNER
     }
+
+    return result;
 }
 
 #if defined(__WITH_DTLS__) || defined (__WITH_TLS__)
-#ifdef _ENABLE_MULTIPLE_OWNER_
+#ifdef MULTIPLE_OWNER
 /**
  * Callback function to handle MOT DTLS handshake result.
  * @param[out]   object           remote device information.
@@ -926,21 +1087,60 @@ void MultipleOwnerDTLSHandshakeCB(const CAEndpoint_t *object,
 
     if(CA_STATUS_OK == errorInfo->result)
     {
-        const CASecureEndpoint_t* authenticatedSubOwnerInfo = CAGetSecureEndpointData(object);
-        if(authenticatedSubOwnerInfo)
+        CASecureEndpoint_t authenticationSubOwnerInfo;
+        CAResult_t caRes = CAGetSecureEndpointData(object, &authenticationSubOwnerInfo);
+        if (CA_STATUS_OK == caRes)
         {
-            OicSecSubOwner_t* subOwnerInst = (OicSecSubOwner_t*)OICMalloc(sizeof(OicSecSubOwner_t));
-            if(subOwnerInst)
+            if (0 == memcmp(authenticationSubOwnerInfo.identity.id, gDoxm->owner.id,
+                            authenticationSubOwnerInfo.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)
             {
-                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))
+                if(0 == memcmp(subOwnerInst->uuid.id,
+                               authenticationSubOwnerInfo.identity.id,
+                               authenticationSubOwnerInfo.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 (sizeof(subOwnerInst->uuid.id) < authenticationSubOwnerInfo.identity.id_length)
+                    {
+                        OIC_LOG(ERROR, TAG, "Identity id is too long");
+                        return;
+                    }
+                    memcpy(subOwnerInst->uuid.id, authenticationSubOwnerInfo.identity.id,
+                           authenticationSubOwnerInfo.identity.id_length);
+                    if(OC_STACK_OK != ConvertUuidToStr(&subOwnerInst->uuid, &strUuid))
+                    {
+                        OIC_LOG(ERROR, TAG, "Failed to allocate memory.");
+                        return;
+                    }
+                    OIC_LOG_V(DEBUG, TAG, "Adding New SubOwner(%s)", strUuid);
+                    OICFree(strUuid);
+                    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, "Could not CAGetSecureEndpointData: %d", caRes);
+        }
     }
 
     if(CA_STATUS_OK != CAregisterPskCredentialsHandler(GetDtlsPskCredentials))
@@ -950,15 +1150,79 @@ void MultipleOwnerDTLSHandshakeCB(const CAEndpoint_t *object,
 
     OIC_LOG(DEBUG, TAG, "OUT MultipleOwnerDTLSHandshakeCB");
 }
-#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;
+}
+
+#if defined(__WITH_DTLS__) || defined(__WITH_TLS__)
+static void DoxmDTLSHandshakeCB(const CAEndpoint_t *endpoint, const CAErrorInfo_t *info)
+{
+    OIC_LOG_V(DEBUG, TAG, "In %s(%p, %p)", __func__, endpoint, info);
+
+    if ((NULL != endpoint) && (NULL != info) && (CA_STATUS_OK == info->result))
+    {
+        /*
+         * Allow this OBT endpoint to bypass ACE checks for SVRs, while this
+         * device is not yet owned.
+         */
+        OC_VERIFY(CASetSecureEndpointAttribute(endpoint,
+            CA_SECURE_ENDPOINT_ATTRIBUTE_ADMINISTRATOR));
+    }
+
+    OIC_LOG_V(DEBUG, TAG, "Out %s(%p, %p)", __func__, endpoint, info);
+}
+
+static void RegisterOTMSslHandshakeCallback(CAErrorCallback callback)
+{
+    OC_VERIFY(CA_STATUS_OK == CAregisterSslHandshakeCallback(callback));
+}
+#endif // __WITH_DTLS__ or __WITH_TLS__
+
+static OCEntityHandlerResult HandleDoxmPostRequest(OCEntityHandlerRequest * ehRequest)
 {
     OIC_LOG (DEBUG, TAG, "Doxm EntityHandle  processing POST request");
-    OCEntityHandlerResult ehRet = OC_EH_ERROR;
+    OCEntityHandlerResult ehRet = OC_EH_INTERNAL_SERVER_ERROR;
     OicUuid_t emptyOwner = {.id = {0} };
     static uint16_t previousMsgId = 0;
+    bool isDuplicatedMsg = false;
 
     /*
      * Convert CBOR Doxm data into binary. This will also validate
@@ -971,13 +1235,27 @@ static OCEntityHandlerResult HandleDoxmPostRequest(const OCEntityHandlerRequest
         uint8_t *payload = ((OCSecurityPayload *)ehRequest->payload)->securityData;
         size_t size = ((OCSecurityPayload *)ehRequest->payload)->payloadSize;
         bool roParsed = false;
-        OCStackResult res = CBORPayloadToDoxmBin(payload, size, &newDoxm, &roParsed);
+        OicSecDostype_t onboardingState;
+        VERIFY_SUCCESS(TAG, OC_STACK_OK == GetDos(&onboardingState), ERROR);
+        OCStackResult res = CBORPayloadToDoxmBin(payload, size, &newDoxm, &roParsed,
+            onboardingState.state);
         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;
+            }
+
             // Check request on RO property
             if (true == roParsed)
             {
-                OIC_LOG(ERROR, TAG, "Not acceptable request because of read-only propertys");
+                OIC_LOG(ERROR, TAG, "Not acceptable request because of read-only properties");
                 ehRet = OC_EH_NOT_ACCEPTABLE;
                 goto exit;
             }
@@ -985,11 +1263,24 @@ static OCEntityHandlerResult HandleDoxmPostRequest(const OCEntityHandlerRequest
             // in owned state
             if (true == gDoxm->owned)
             {
-                //Update gDoxm based on newDoxm
-                updateWriteableProperty(newDoxm, gDoxm);
+                if (false == ValidateOxmsel(gDoxm->oxm, gDoxm->oxmLen, &newDoxm->oxmSel))
+                {
+                    OIC_LOG(ERROR, TAG, "Not acceptable request because oxmsel is not supported on Server");
+                    ehRet = OC_EH_NOT_ACCEPTABLE;
+                    goto exit;
+                }
+
+                // Update gDoxm based on newDoxm
+                res = DoxmUpdateWriteableProperty(newDoxm, gDoxm);
+                if (OC_STACK_OK != res)
+                {
+                    OIC_LOG(ERROR, TAG, "gDoxm properties were not able to be updated so we cannot handle the request.");
+                    ehRet = OC_EH_ERROR;
+                    goto exit;
+                }
 
 #if defined(__WITH_DTLS__) || defined (__WITH_TLS__)
-#ifdef _ENABLE_MULTIPLE_OWNER_
+#ifdef MULTIPLE_OWNER
                 //handle mom
                 if(gDoxm->mom)
                 {
@@ -1002,7 +1293,8 @@ 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);
+                            RegisterOTMSslHandshakeCallback(DoxmDTLSHandshakeCB);
+                            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");
 
@@ -1050,7 +1342,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
@@ -1069,7 +1361,14 @@ 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 (OIC_JUST_WORKS == newDoxm->oxmSel || OIC_MV_JUST_WORKS == newDoxm->oxmSel)
                 {
                     /*
                      * If current state of the device is un-owned, enable
@@ -1078,8 +1377,21 @@ static OCEntityHandlerResult HandleDoxmPostRequest(const OCEntityHandlerRequest
                      */
                     if (memcmp(&(newDoxm->owner), &emptyOwner, sizeof(OicUuid_t)) == 0)
                     {
-                        OIC_LOG (INFO, TAG, "Doxm EntityHandle  enabling AnonECDHCipherSuite");
+                        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;
+                        }
 #if defined(__WITH_DTLS__) || defined(__WITH_TLS__)
+                        RegisterOTMSslHandshakeCallback(DoxmDTLSHandshakeCB);
+                        OIC_LOG(INFO, TAG, "Doxm EntityHandle  enabling AnonECDHCipherSuite");
                         ehRet = (CAEnableAnonECDHCipherSuite(true) == CA_STATUS_OK) ? OC_EH_OK : OC_EH_ERROR;
 #endif // __WITH_DTLS__ or __WITH_TLS__
                         goto exit;
@@ -1099,17 +1411,68 @@ static OCEntityHandlerResult HandleDoxmPostRequest(const OCEntityHandlerRequest
                         {
                             OIC_LOG(ERROR, TAG, "Failed to update DOXM in persistent storage");
                             ehRet = OC_EH_ERROR;
+                            goto exit;
                         }
 
                         /*
                          * Disable anonymous ECDH cipher in tinyDTLS since device is now
                          * in owned state.
                          */
+                        RegisterOTMSslHandshakeCallback(NULL);
                         CAResult_t caRes = CA_STATUS_OK;
                         caRes = CAEnableAnonECDHCipherSuite(false);
                         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));
+
+                            //Wait for user confirmation
+                            if (OC_STACK_OK != VerifyOwnershipTransfer(mutualVerifNum, DISPLAY_NUM | USER_CONFIRM))
+                            {
+                                ehRet = OC_EH_NOT_ACCEPTABLE;
+                            }
+                            else
+                            {
+                                ehRet = OC_EH_OK;
+                            }
+                        }
+
 #endif // __WITH_DTLS__ or __WITH_TLS__
                     }
                 }
@@ -1117,8 +1480,8 @@ static OCEntityHandlerResult HandleDoxmPostRequest(const OCEntityHandlerRequest
                 {
                     /*
                      * If current state of the device is un-owned, enable
-                     * anonymous ECDH cipher in tinyDTLS so that Provisioning
-                     * tool can initiate JUST_WORKS ownership transfer process.
+                     * ECDHE_PSK cipher so that the Provisioning tool can
+                     * initiate the ownership transfer.
                      */
                     if(memcmp(&(newDoxm->owner), &emptyOwner, sizeof(OicUuid_t)) == 0)
                     {
@@ -1135,43 +1498,19 @@ static OCEntityHandlerResult HandleDoxmPostRequest(const OCEntityHandlerRequest
                         }
 
 #if defined(__WITH_DTLS__) || defined(__WITH_TLS__)
-                        CAResult_t caRes = CA_STATUS_OK;
-
-                        caRes = CAEnableAnonECDHCipherSuite(false);
+                        CAResult_t caRes = CAEnableAnonECDHCipherSuite(false);
                         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,
+                        RegisterOTMSslHandshakeCallback(DoxmDTLSHandshakeCB);
+                        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(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;
-                            }
-                        }
-                        else if(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);
@@ -1190,7 +1529,6 @@ static OCEntityHandlerResult HandleDoxmPostRequest(const OCEntityHandlerRequest
                                 OIC_LOG(ERROR, TAG, "Failed to generate random PIN");
                                 ehRet = OC_EH_ERROR;
                             }
-
                         }
 #endif // __WITH_DTLS__ or __WITH_TLS__
                     }
@@ -1200,6 +1538,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,24 +1557,66 @@ static OCEntityHandlerResult HandleDoxmPostRequest(const OCEntityHandlerRequest
                     }
 #endif // __WITH_DTLS__ or __WITH_TLS__
                 }
-            }
-
-            /*
-             * When current state of the device is un-owned and Provisioning
-             * Tool is attempting to change the state to 'Owned' with a
-             * qualified value for the field 'Owner'
-             */
-            if ((false == gDoxm->owned) && (true == newDoxm->owned) &&
-                    (memcmp(&(gDoxm->owner), &(newDoxm->owner), sizeof(OicUuid_t)) == 0))
-            {
-                //Change the SVR's resource owner as owner device.
-                OCStackResult ownerRes = SetAclRownerId(&gDoxm->owner);
-                if(OC_STACK_OK != ownerRes && OC_STACK_NO_RESOURCE != ownerRes)
+#if defined(__WITH_DTLS__) || defined (__WITH_TLS__)
+                else if (OIC_MANUFACTURER_CERTIFICATE ==  newDoxm->oxmSel || OIC_CON_MFG_CERT == newDoxm->oxmSel)
                 {
-                    ehRet = OC_EH_ERROR;
-                    goto exit;
+                    //In case of Confirm Manufacturer Cert, get user confirmation
+                    if (OIC_CON_MFG_CERT == newDoxm->oxmSel && false == newDoxm->owned &&
+                        false == isDuplicatedMsg &&
+                        memcmp(&(newDoxm->owner), &emptyOwner, sizeof(OicUuid_t)) != 0)
+                    {
+                        if (OC_STACK_OK != VerifyOwnershipTransfer(NULL, USER_CONFIRM))
+                        {
+                            ehRet = OC_EH_NOT_ACCEPTABLE;
+                            goto exit;
+                        }
+                        else
+                        {
+                            ehRet = OC_EH_OK;
+                        }
+                    }
+
+                    //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;
+                    }
+
+                    RegisterOTMSslHandshakeCallback(NULL);
+                    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);
                 }
-                ownerRes = SetAmaclRownerId(&gDoxm->owner);
+#endif // __WITH_DTLS__ or __WITH_TLS__
+            }
+
+            /*
+             * When current state of the device is un-owned and Provisioning
+             * Tool is attempting to change the state to 'Owned' with a
+             * qualified value for the field 'Owner'
+             */
+            // TODO [IOT-2107] reconcile POST handler behavior with Specification
+            if ((false == gDoxm->owned) && (true == newDoxm->owned) &&
+                    (memcmp(&(gDoxm->owner), &(newDoxm->owner), sizeof(OicUuid_t)) == 0))
+            {
+                //Change the SVR's resource owner as owner device.
+                OCStackResult ownerRes = SetAclRownerId(&gDoxm->owner);
                 if(OC_STACK_OK != ownerRes && OC_STACK_NO_RESOURCE != ownerRes)
                 {
                     ehRet = OC_EH_ERROR;
@@ -1283,6 +1669,14 @@ static OCEntityHandlerResult HandleDoxmPostRequest(const OCEntityHandlerRequest
                     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);
+                }
+#endif // __WITH_DTLS__ or __WITH_TLS__
             }
         }
     }
@@ -1297,12 +1691,16 @@ exit:
         */
         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)
+                {
+                    RestoreDoxmToInitState();
+                    RestorePstatToInitState();
+                    OIC_LOG(WARNING, TAG, "DOXM will be reverted.");
+                }
             }
         }
         else
@@ -1368,7 +1766,7 @@ OCStackResult CreateDoxmResource()
                                          OIC_RSRC_DOXM_URI,
                                          DoxmEntityHandler,
                                          NULL,
-                                         OC_SECURE |
+                                         OC_SECURE | OC_NONSECURE |
                                          OC_DISCOVERABLE);
 
     if (OC_STACK_OK != ret)
@@ -1388,6 +1786,7 @@ static OCStackResult CheckDeviceID()
 {
     OCStackResult ret = OC_STACK_ERROR;
     bool validId = false;
+
     for (uint8_t i = 0; i < UUID_LENGTH; i++)
     {
         if (gDoxm->deviceID.id[i] != 0)
@@ -1399,12 +1798,65 @@ 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 exists, generate UUID using seed with SHA256
+        if (0 != gUuidSeedSize)
+        {
+            uint8_t hashVal[MBEDTLS_MD_MAX_SIZE] = {0};
+            int mbedret = 0;
+
+            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);
+
+            mbedret = mbedtls_md(mbedtls_md_info_from_type(MBEDTLS_MD_SHA256),
+                                 gUuidSeed, gUuidSeedSize, hashVal);
+            if(0 == mbedret)
+            {
+                memcpy(gDoxm->deviceID.id, hashVal, sizeof(gDoxm->deviceID.id));
+                ret = OC_STACK_OK;
+            }
+            else
+            {
+                OIC_LOG_V(ERROR, TAG, "mbedtls_md error : %d", mbedret);
+                ret = OC_STACK_ERROR;
+            }
+        }
+        else
+        {
+            if (!OCGenerateUuid(gDoxm->deviceID.id))
+            {
+                OIC_LOG(FATAL, TAG, "Generate UUID for Server Instance failed!");
+                ret = OC_STACK_ERROR;
+            }
+            else
+            {
+                ret = OC_STACK_OK;
+            }
+        }
+#else
+        if (!OCGenerateUuid(gDoxm->deviceID.id))
         {
             OIC_LOG(FATAL, TAG, "Generate UUID for Server Instance failed!");
-            return ret;
+            ret = OC_STACK_ERROR;
         }
-        ret = OC_STACK_OK;
+        else
+        {
+            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))
         {
@@ -1416,6 +1868,7 @@ static OCStackResult CheckDeviceID()
     {
         ret = OC_STACK_OK;
     }
+
     return ret;
 }
 
@@ -1435,14 +1888,14 @@ 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
  */
 static void PrepareMOT(const OicSecDoxm_t* doxm)
 {
     OIC_LOG(INFO, TAG, "IN PrepareMOT");
-    VERIFY_NON_NULL(TAG, doxm, ERROR);
+    VERIFY_NOT_NULL(TAG, doxm, ERROR);
 
     if(true == doxm->owned && NULL != doxm->mom && OIC_MULTIPLE_OWNER_DISABLE != doxm->mom->mode)
     {
@@ -1456,10 +1909,11 @@ 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);
+            RegisterOTMSslHandshakeCallback(DoxmDTLSHandshakeCB);
+            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");
@@ -1481,7 +1935,7 @@ 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()
 {
@@ -1512,7 +1966,7 @@ OCStackResult InitDoxmResource()
     }
 
     //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));
@@ -1531,13 +1985,13 @@ 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;
 }
@@ -1561,45 +2015,64 @@ OCStackResult DeInitDoxmResource()
     }
 }
 
-OCStackResult GetDoxmDeviceID(OicUuid_t *deviceID)
+#if defined(__WITH_DTLS__) || defined (__WITH_TLS__)
+OCStackResult SetDoxmDeviceIDSeed(const uint8_t* seed, size_t seedSize)
 {
-    if (deviceID && gDoxm)
+    OIC_LOG_V(INFO, TAG, "In %s", __func__);
+
+    if (NULL == seed)
     {
-       *deviceID = gDoxm->deviceID;
-        return OC_STACK_OK;
+        return OC_STACK_INVALID_PARAM;
     }
-    return OC_STACK_ERROR;
+    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 GetDoxmIsOwned(bool *isOwned)
+OCStackResult GetDoxmDeviceID(OicUuid_t *deviceuuid)
 {
-    if (isOwned && gDoxm)
+    if (deviceuuid && gDoxm)
     {
-       *isOwned = gDoxm->owned;
+        *deviceuuid = gDoxm->deviceID;
         return OC_STACK_OK;
     }
     return OC_STACK_ERROR;
 }
 
-OCStackResult SetDoxmDeviceID(const OicUuid_t *deviceID)
+OCStackResult SetDoxmDeviceID(const OicUuid_t *deviceuuid)
 {
-    bool isPT = false;
-
-    if(NULL == deviceID)
+    bool isOwnerUpdated = false;
+    bool isRownerUpdated = false;
+    if (NULL == deviceuuid)
     {
         return OC_STACK_INVALID_PARAM;
     }
-    if(NULL == gDoxm)
+    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)
+    if (true == gDoxm->owned &&
+        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.");
@@ -1608,26 +2081,39 @@ 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 device UUID
+    memcpy(gDoxm->deviceID.id, deviceuuid->id, sizeof(gDoxm->deviceID.id));
 
-    //Change the 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, deviceuuid->id, sizeof(gDoxm->owner.id));
+        isOwnerUpdated = true;
+    }
+    //Change the resource owner ID if necessary
+    // TODO [IOT-2023] change this behavior and upate the usage of this function
+    // so that rowneruuid for each resource is set by OBT
+    if (memcmp(gDoxm->rownerID.id, prevUuid.id, sizeof(prevUuid.id)) == 0)
     {
-        memcpy(gDoxm->owner.id, deviceID->id, sizeof(deviceID->id));
-        memcpy(gDoxm->rownerID.id, deviceID->id, sizeof(deviceID->id));
+        memcpy(gDoxm->rownerID.id, deviceuuid->id, sizeof(gDoxm->rownerID.id));
+        isRownerUpdated = true;
     }
 
     //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(gDoxm->deviceID.id));
+        if (isOwnerUpdated)
         {
-            memcpy(gDoxm->owner.id, tempUuid.id, sizeof(tempUuid.id));
-            memcpy(gDoxm->rownerID.id, tempUuid.id, sizeof(tempUuid.id));
+            memcpy(gDoxm->owner.id, prevUuid.id, sizeof(gDoxm->owner.id));
+        }
+        if (isRownerUpdated)
+        {
+            memcpy(gDoxm->rownerID.id, prevUuid.id, sizeof(gDoxm->rownerID.id));
         }
 
         OIC_LOG(ERROR, TAG, "Failed to update persistent storage");
@@ -1636,37 +2122,67 @@ OCStackResult SetDoxmDeviceID(const OicUuid_t *deviceID)
     return OC_STACK_OK;
 }
 
-OCStackResult GetDoxmDevOwnerId(OicUuid_t *devownerid)
+OCStackResult GetDoxmDevOwnerId(OicUuid_t *devowneruuid)
+{
+    if (gDoxm && devowneruuid)
+    {
+        memcpy(&(devowneruuid->id), &(gDoxm->owner.id), sizeof(devowneruuid->id));
+        return OC_STACK_OK;
+    }
+    return OC_STACK_ERROR;
+}
+
+OCStackResult SetDoxmDevOwnerId(const OicUuid_t *devowneruuid)
+{
+    if (gDoxm && devowneruuid)
+    {
+        memcpy(&(gDoxm->owner.id), &(devowneruuid->id), sizeof(gDoxm->owner.id));
+        return OC_STACK_OK;
+    }
+    return OC_STACK_ERROR;
+}
+
+OCStackResult GetDoxmIsOwned(bool *isowned)
+{
+    if (isowned && gDoxm)
+    {
+        *isowned = gDoxm->owned;
+        return OC_STACK_OK;
+    }
+    return OC_STACK_ERROR;
+}
+
+OCStackResult SetDoxmIsOwned(const bool isowned)
 {
-    OCStackResult retVal = OC_STACK_ERROR;
     if (gDoxm)
     {
-        OIC_LOG_V(DEBUG, TAG, "GetDoxmDevOwnerId(): gDoxm owned =  %d.", \
-            gDoxm->owned);
-        if (gDoxm->owned)
-        {
-            *devownerid = gDoxm->owner;
-            retVal = OC_STACK_OK;
-        }
+        gDoxm->owned = isowned;
+        return OC_STACK_OK;
     }
-    return retVal;
+    return OC_STACK_ERROR;
 }
 
 OCStackResult GetDoxmRownerId(OicUuid_t *rowneruuid)
 {
-    OCStackResult retVal = OC_STACK_ERROR;
-    if (gDoxm)
+    if (gDoxm && rowneruuid)
     {
-        if( gDoxm->owned )
-        {
-            *rowneruuid = gDoxm->rownerID;
-                    retVal = OC_STACK_OK;
-        }
+        memcpy(&(rowneruuid->id), &(gDoxm->rownerID.id), sizeof(rowneruuid->id));
+        return OC_STACK_OK;
     }
-    return retVal;
+    return OC_STACK_ERROR;
 }
 
-#ifdef _ENABLE_MULTIPLE_OWNER_
+OCStackResult SetDoxmRownerId(const OicUuid_t *rowneruuid)
+{
+    if (gDoxm && rowneruuid)
+    {
+        memcpy(&(gDoxm->rownerID.id), &(rowneruuid->id), sizeof(gDoxm->rownerID.id));
+        return OC_STACK_OK;
+    }
+    return OC_STACK_ERROR;
+}
+
+#ifdef MULTIPLE_OWNER
 /**
  * Compare the UUID to SubOwner.
  *
@@ -1678,17 +2194,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;
             }
@@ -1696,7 +2217,50 @@ bool IsSubOwner(const OicUuid_t* uuid)
     }
     return retVal;
 }
-#endif //_ENABLE_MULTIPLE_OWNER_
+
+OCStackResult SetMOTStatus(bool enable)
+{
+    OCStackResult ret = OC_STACK_NO_MEMORY;
+    uint8_t *cborPayload = NULL;
+    size_t size = 0;
+    bool isDeallocateRequired = false;
+
+    OIC_LOG_V(DEBUG, TAG, "In %s", __func__);
+
+    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_NOT_NULL(TAG, gDoxm->mom, ERROR);
+        isDeallocateRequired = true;
+    }
+
+    gDoxm->mom->mode = (enable ? OIC_MULTIPLE_OWNER_ENABLE : OIC_MULTIPLE_OWNER_DISABLE);
+
+    ret = DoxmToCBORPayload(gDoxm, &cborPayload, &size);
+    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);
+    }
+    OICFree(cborPayload);
+    OIC_LOG_V(DEBUG, TAG, "Out %s : %d", __func__, ret);
+    return ret;
+}
+
+#endif //MULTIPLE_OWNER
 
 /**
  * Function to restore doxm resurce to initial status.
@@ -1719,3 +2283,222 @@ 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);
+        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;
+}
+
+#ifdef MULTIPLE_OWNER
+/** This function checks if two sets of /oic/sec/doxm MOT-specific properties are identical.
+ *
+ * @param doxm1 is a pointer to the first @ref OicSecDoxm_t data.
+ * @param doxm2 is a pointer to the second @ref OicSecDoxm_t data.
+ *
+ * @return true if all of the properties are identical, else false.
+ */
+static bool AreDoxmBinMOTPropertyValuesEqual(OicSecDoxm_t* doxm1, OicSecDoxm_t* doxm2)
+{
+    //Compare the subOwners lists.
+    OicSecSubOwner_t* subOwner1 = doxm1->subOwners;
+    OicSecSubOwner_t* subOwner2 = doxm2->subOwners;
+
+    for (;;)
+    {
+        if ((NULL == subOwner1) && (NULL == subOwner2))
+        {
+            //Reached the end of both lists, so the two lists were identical.
+            break;
+        }
+
+        if ((NULL != subOwner1) && (NULL != subOwner2))
+        {
+            if (0 != memcmp(&subOwner1->uuid, &subOwner2->uuid, sizeof(subOwner1->uuid)))
+            {
+                OIC_LOG_V(ERROR, TAG, "%s: subOwner uuid mismatch", __func__);
+                return false;
+            }
+
+            if (subOwner1->status != subOwner2->status)
+            {
+                OIC_LOG_V(ERROR, TAG, "%s: subOwner status mismatch: (%u, %u)",
+                    __func__, (uint32_t)subOwner1->status, (uint32_t)subOwner2->status);
+                return false;
+            }
+
+            //Go to the next elements from the two lists.
+            subOwner1 = subOwner1->next;
+            subOwner2 = subOwner2->next;
+            continue;
+        }
+
+        OIC_LOG_V(ERROR, TAG, "%s: subOwner list length mismatch", __func__);
+        return false;
+    }
+
+    // Compare the mom values.
+    if (NULL == doxm1->mom)
+    {
+        if (NULL != doxm2->mom)
+        {
+            OIC_LOG_V(ERROR, TAG, "%s: doxm1->mom is NULL", __func__);
+            return false;
+        }
+
+        return true;
+    }
+
+    if (NULL == doxm2->mom)
+    {
+        OIC_LOG_V(ERROR, TAG, "%s: doxm2->mom is NULL", __func__);
+        return false;
+    }
+
+    if (doxm1->mom->mode != doxm2->mom->mode)
+    {
+        OIC_LOG_V(ERROR, TAG, "%s: mom->mode mismatch: (%u, %u)",
+            __func__, (uint32_t)doxm1->mom->mode, (uint32_t)doxm2->mom->mode);
+        return false;
+    }
+
+    return true;
+}
+#endif //#ifdef MULTIPLE_OWNER
+
+bool AreDoxmBinPropertyValuesEqual(OicSecDoxm_t* doxm1, OicSecDoxm_t* doxm2)
+{
+    if (NULL == doxm1 || NULL == doxm2)
+    {
+        OIC_LOG_V(ERROR, TAG, "%s: unxpected NULL doxm pointer", __func__);
+        return false;
+    }
+
+    //Compare the contents of the oxmType array and its length oxmTypeLen.
+    size_t arrayLength = doxm1->oxmTypeLen;
+
+    if (arrayLength != doxm2->oxmTypeLen)
+    {
+        OIC_LOG_V(ERROR, TAG, "%s: oxmTypeLen mismatch: (%" PRIuPTR ", %" PRIuPTR ")",
+            __func__, arrayLength, doxm2->oxmTypeLen);
+        return false;
+    }
+
+    for (size_t i = 0; i < arrayLength; i++)
+    {
+        if (NULL == doxm1->oxmType[i] || NULL == doxm2->oxmType[i])
+        {
+            OIC_LOG_V(ERROR, TAG, "%s: unexpected NULL found in the oxmType array",
+                __func__);
+            return false;
+        }
+
+        if (0 != strcmp(doxm1->oxmType[i], doxm2->oxmType[i]))
+        {
+            OIC_LOG_V(ERROR, TAG, "%s: oxmType mismatch: (%s, %s)",
+                __func__, doxm1->oxmType[i], doxm2->oxmType[i]);
+            return false;
+        }
+    }
+
+    //Compare the contents of the oxm array and its length oxmLen.
+    arrayLength = doxm1->oxmLen;
+
+    if (arrayLength != doxm2->oxmLen)
+    {
+        OIC_LOG_V(ERROR, TAG, "%s: oxmLen mismatch: (%" PRIuPTR ", %" PRIuPTR ")",
+            __func__, arrayLength, doxm2->oxmLen);
+        return false;
+    }
+
+    for (size_t i = 0; i < arrayLength; i++)
+    {
+        if (doxm1->oxm[i] != doxm2->oxm[i])
+        {
+            OIC_LOG_V(ERROR, TAG, "%s: oxmType mismatch: (%u, %u)",
+                __func__, (uint32_t)doxm1->oxm[i], (uint32_t)doxm2->oxm[i]);
+            return false;
+        }
+    }
+
+    //Compare the remaining property values.
+    if (doxm1->oxmSel != doxm2->oxmSel)
+    {
+        OIC_LOG_V(ERROR, TAG, "%s: oxmSel mismatch: (%u, %u)",
+            __func__, (uint32_t)doxm1->oxmSel, (uint32_t)doxm2->oxmSel);
+        return false;
+    }
+
+    if (doxm1->sct != doxm2->sct)
+    {
+        OIC_LOG_V(ERROR, TAG, "%s: sct mismatch: (%u, %u)",
+            __func__, (uint32_t)doxm1->sct, (uint32_t)doxm2->sct);
+        return false;
+    }
+
+    if (doxm1->owned != doxm2->owned)
+    {
+        OIC_LOG_V(ERROR, TAG, "%s: owned mismatch: (%u, %u)",
+            __func__, (uint32_t)doxm1->owned, (uint32_t)doxm2->owned);
+        return false;
+    }
+
+    if (0 != memcmp(&doxm1->deviceID, &doxm2->deviceID, sizeof(doxm1->deviceID)))
+    {
+        OIC_LOG_V(ERROR, TAG, "%s: deviceID mismatch", __func__);
+        return false;
+    }
+
+    if (doxm1->dpc != doxm2->dpc)
+    {
+        OIC_LOG_V(ERROR, TAG, "%s: dpc mismatch: (%u, %u)",
+            __func__, (uint32_t)doxm1->dpc, (uint32_t)doxm2->dpc);
+        return false;
+    }
+
+    if (0 != memcmp(&doxm1->owner, &doxm2->owner, sizeof(doxm1->owner)))
+    {
+        OIC_LOG_V(ERROR, TAG, "%s: owner mismatch", __func__);
+        return false;
+    }
+
+    if (0 != memcmp(&doxm1->rownerID, &doxm2->rownerID, sizeof(doxm1->rownerID)))
+    {
+        OIC_LOG_V(ERROR, TAG, "%s: rownerID mismatch", __func__);
+        return false;
+    }
+
+#ifdef MULTIPLE_OWNER
+    return AreDoxmBinMOTPropertyValuesEqual(doxm1, doxm2);
+#else
+    return true;
+#endif
+}