Merge branch '1.3-rel' (5c831e6) 79/22479/5
authorGeorge Nash <george.nash@intel.com>
Fri, 15 Sep 2017 17:51:48 +0000 (10:51 -0700)
committerGeorge Nash <george.nash@intel.com>
Mon, 18 Sep 2017 17:20:31 +0000 (10:20 -0700)
Relate-to:
https://gerrit.iotivity.org/gerrit/22125
https://gerrit.iotivity.org/gerrit/22291
https://gerrit.iotivity.org/gerrit/21917
https://gerrit.iotivity.org/gerrit/22173
https://gerrit.iotivity.org/gerrit/22153
https://gerrit.iotivity.org/gerrit/22379
https://gerrit.iotivity.org/gerrit/22377
https://gerrit.iotivity.org/gerrit/22331
https://gerrit.iotivity.org/gerrit/21915
https://gerrit.iotivity.org/gerrit/22391
https://gerrit.iotivity.org/gerrit/21899
https://gerrit.iotivity.org/gerrit/22315
https://gerrit.iotivity.org/gerrit/22401
https://gerrit.iotivity.org/gerrit/20323
https://gerrit.iotivity.org/gerrit/22279
https://gerrit.iotivity.org/gerrit/22013
https://gerrit.iotivity.org/gerrit/22447

Conflicts:
    .gitignore
    java/jni/SConscript
    resource/csdk/connectivity/src/bt_le_adapter/caleadapter.c
    resource/csdk/security/provisioning/sample/SConscript
    resource/csdk/security/src/doxmresource.c
    resource/provisioning/examples/SConscript
    resource/provisioning/unittests/SConscript

Bug: https://jira.iotivity.org/browse/IOT-2453
Change-Id: I38edf767568c80aad54c0c97e9b32581e31f4942
Signed-off-by: George Nash <george.nash@intel.com>
63 files changed:
1  2 
.gitignore
java/jni/JniOcResource.h
resource/IPCA/unittests/IPCAUnitTest.dat
resource/csdk/connectivity/src/adapter_util/ca_adapter_net_ssl.c
resource/csdk/connectivity/src/bt_le_adapter/caleadapter.c
resource/csdk/connectivity/src/caconnectivitymanager.c
resource/csdk/connectivity/src/camessagehandler.c
resource/csdk/connectivity/src/caprotocolmessage.c
resource/csdk/connectivity/src/ip_adapter/caipadapter.c
resource/csdk/connectivity/src/ip_adapter/caipserver.c
resource/csdk/connectivity/src/tcp_adapter/catcpadapter.c
resource/csdk/connectivity/src/tcp_adapter/catcpserver.c
resource/csdk/connectivity/test/ssladapter_test.cpp
resource/csdk/include/octypes.h
resource/csdk/logger/src/logger.c
resource/csdk/resource-directory/src/internal/rd_database.c
resource/csdk/resource-directory/src/rd_server.c
resource/csdk/security/provisioning/sample/SConscript
resource/csdk/security/provisioning/sample/oic_svr_db_client.dat
resource/csdk/security/provisioning/sample/oic_svr_db_server_mfg.dat
resource/csdk/security/provisioning/src/multipleownershiptransfermanager.c
resource/csdk/security/provisioning/src/ownershiptransfermanager.c
resource/csdk/security/provisioning/src/oxmjustworks.c
resource/csdk/security/provisioning/src/oxmmanufacturercert.c
resource/csdk/security/provisioning/src/oxmpreconfpin.c
resource/csdk/security/provisioning/src/oxmrandompin.c
resource/csdk/security/provisioning/src/secureresourceprovider.c
resource/csdk/security/src/aclresource.c
resource/csdk/security/src/certhelpers.c
resource/csdk/security/src/credresource.c
resource/csdk/security/src/directpairing.c
resource/csdk/security/src/doxmresource.c
resource/csdk/security/src/dpairingresource.c
resource/csdk/security/src/rolesresource.c
resource/csdk/security/src/secureresourcemanager.c
resource/csdk/security/tool/json2cbor.c
resource/csdk/security/tool/svrdbeditor_src/svrdbeditorcred.c
resource/csdk/security/unittest/credentialresource.cpp
resource/csdk/security/unittest/oic_svr_db_prov.dat
resource/csdk/stack/samples/linux/SimpleClientServer/occlient.cpp
resource/csdk/stack/samples/linux/secure/oic_amss_db.dat
resource/csdk/stack/samples/linux/secure/oic_svr_db_client_devowner.dat
resource/csdk/stack/samples/linux/secure/oic_svr_db_client_nondevowner.dat
resource/csdk/stack/samples/linux/secure/oic_svr_db_server.dat
resource/csdk/stack/src/ocpayload.c
resource/csdk/stack/src/ocstack.c
resource/csdk/stack/test/SConscript
resource/csdk/stack/test/stacktests.cpp
resource/examples/oic_svr_db_client.dat
resource/examples/oic_svr_db_server.dat
resource/provisioning/examples/SConscript
resource/provisioning/unittests/SConscript
service/easy-setup/enrollee/src/easysetup.c
service/easy-setup/enrollee/src/resourcehandler.c
service/easy-setup/enrollee/src/resourcehandler.h
service/easy-setup/enrollee/unittests/ESEnrolleeTest.cpp
service/easy-setup/mediator/richsdk/inc/ESRichCommon.h
service/easy-setup/mediator/richsdk/src/CloudResource.cpp
service/easy-setup/mediator/richsdk/src/EnrolleeResource.cpp
service/easy-setup/mediator/richsdk/src/EnrolleeSecurity.cpp
service/easy-setup/mediator/richsdk/src/RemoteEnrollee.cpp
service/easy-setup/mediator/richsdk/unittests/ESMediatorTest.cpp
service/easy-setup/sampleapp/enrollee/linux/easysetup_x.c

diff --cc .gitignore
@@@ -140,12 -134,15 +140,18 @@@ extlibs/yaml/yam
  # Ignore Valgrind generated files.
  *.memcheck
  
 -# Ignore  generated files
 -*.dat
 +# Ignore generated documentation files
 +docs/c-doc/docs/
 +docs/c-doc/doxygen.log
 +docs/cpp-doc/docs/
 +docs/cpp-doc/doxygen.log
  
+ # Ignore generated documentation files
+ docs/c-doc/docs/
+ docs/c-doc/doxygen.log
+ docs/cpp-doc/docs/
+ docs/cpp-doc/doxygen.log
  # Ignore debian generated files
  debian/files
  debian/*.debhelper.log
Simple merge
index e2b196b,e2b196b..f940301
Binary files differ
Simple merge
Simple merge
@@@ -132,12 -158,17 +132,13 @@@ if target_os not in ['msys_nt', 'window
          rootcert = provisioning_sample_env.Install(
              sec_provisioning_build_dir,
              sec_provisioning_src_dir + 'rootca.crt')
-         Alias("cloud", [
-             rootcert,
-             cloudClient,
-             cloudServer
-         ])
-         provisioning_sample_env.AppendTarget("cloud")
+         if provisioning_sample_env.get('WITH_TCP') == True and provisioning_sample_env.get('WITH_CLOUD') == True:
+             Alias("cloud", [
 -                clouddat,
+                 rootcert,
+                 cloudClient,
+                 cloudServer
+             ])
+             provisioning_sample_env.AppendTarget("cloud")
 -
  sampleapps = [
      provisioningclient,
      autoprovisioningclient,
@@@ -1190,507 -1191,550 +1192,550 @@@ static void RegisterOTMSslHandshakeCall
  {
      OC_VERIFY(CA_STATUS_OK == CAregisterSslHandshakeCallback(callback));
  }
- #endif // __WITH_DTLS__ or __WITH_TLS__
  
- static OCEntityHandlerResult HandleDoxmPostRequest(OCEntityHandlerRequest * ehRequest)
+ #ifdef MULTIPLE_OWNER
+ void HandleDoxmPostRequestMom(OicSecDoxm_t *newDoxm, OCEntityHandlerRequest *ehRequest)
  {
-     OIC_LOG (DEBUG, TAG, "Doxm EntityHandle  processing POST request");
-     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
-      * the Doxm data received.
-      */
-     OicSecDoxm_t *newDoxm = NULL;
-     if (ehRequest->payload)
+     OIC_LOG_V(DEBUG, TAG, "%s: IN", __func__);
+     //handle mom
+     if (gDoxm->mom)
      {
-         uint8_t *payload = ((OCSecurityPayload *)ehRequest->payload)->securityData;
-         size_t size = ((OCSecurityPayload *)ehRequest->payload)->payloadSize;
-         bool roParsed = false;
-         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)
+         if (OIC_MULTIPLE_OWNER_DISABLE != gDoxm->mom->mode)
          {
-             /*
-              * 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)
+             CAResult_t caRes = CA_STATUS_FAILED;
+             if (OIC_PRECONFIG_PIN == gDoxm->oxmSel || OIC_RANDOM_DEVICE_PIN == gDoxm->oxmSel)
              {
-                 isDuplicatedMsg = true;
+                 caRes = CAEnableAnonECDHCipherSuite(false);
+                 VERIFY_SUCCESS(TAG, caRes == CA_STATUS_OK, ERROR);
+                 OIC_LOG(INFO, TAG, "ECDH_ANON CipherSuite is DISABLED");
+                 RegisterOTMSslHandshakeCallback(DoxmDTLSHandshakeCB);
+                 caRes = CASelectCipherSuite((uint16_t)MBEDTLS_TLS_ECDHE_PSK_WITH_AES_128_CBC_SHA256,
+                                             (CATransportAdapter_t)ehRequest->devAddr.adapter);
+                 VERIFY_SUCCESS(TAG, caRes == CA_STATUS_OK, ERROR);
+                 OIC_LOG(INFO, TAG, "ECDHE_PSK CipherSuite will be used for MOT");
+                 //Set the device id to derive temporal PSK
+                 SetUuidForPinBasedOxm(&gDoxm->deviceID);
+             }
+             else
+             {
+                 OIC_LOG(WARNING, TAG, "Unsupported OxM for Multiple Ownership Transfer.");
              }
  
-             // Check request on RO property
-             if (true == roParsed)
+             CAregisterSslHandshakeCallback(MultipleOwnerDTLSHandshakeCB);
+         }
+         else
+         {
+             //if MOM is disabled, revert the DTLS handshake callback
+             if (CA_STATUS_OK != CAregisterSslHandshakeCallback(NULL))
              {
-                 OIC_LOG(ERROR, TAG, "Not acceptable request because of read-only properties");
-                 ehRet = OC_EH_NOT_ACCEPTABLE;
-                 goto exit;
+                 OIC_LOG(WARNING, TAG, "Error while revert the DTLS Handshake Callback.");
              }
+         }
+     }
+     if (newDoxm->subOwners)
+     {
+         OicSecSubOwner_t *subowner = NULL;
+         OicSecSubOwner_t *temp = NULL;
  
-             VERIFY_NOT_NULL(TAG, gDoxm, ERROR);
+         OIC_LOG(DEBUG, TAG, "dectected 'subowners' property");
  
-             // in owned state
-             if (true == gDoxm->owned)
+         if (gDoxm->subOwners)
+         {
+             LL_FOREACH_SAFE(gDoxm->subOwners, subowner, temp)
              {
-                 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;
-                 }
+                 LL_DELETE(gDoxm->subOwners, subowner);
+                 OICFree(subowner);
+             }
+         }
  
-                 // 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;
-                 }
+         subowner = NULL;
+         temp = NULL;
+         LL_FOREACH_SAFE(newDoxm->subOwners, subowner, temp)
+         {
+             LL_DELETE(newDoxm->subOwners, subowner);
+             LL_APPEND(gDoxm->subOwners, subowner);
+         }
+     }
+ exit:
+     OIC_LOG_V(DEBUG, TAG, "%s: OUT", __func__);
+ }
+ #endif //MULTIPLE_OWNER
+ #endif // __WITH_DTLS__ or __WITH_TLS__
  
- #if defined(__WITH_DTLS__) || defined (__WITH_TLS__)
- #ifdef MULTIPLE_OWNER
-                 //handle mom
-                 if(gDoxm->mom)
-                 {
-                     if(OIC_MULTIPLE_OWNER_DISABLE != gDoxm->mom->mode)
-                     {
-                         CAResult_t caRes = CA_STATUS_FAILED;
-                         if(OIC_PRECONFIG_PIN == gDoxm->oxmSel || OIC_RANDOM_DEVICE_PIN == gDoxm->oxmSel)
-                         {
-                             caRes = CAEnableAnonECDHCipherSuite(false);
-                             VERIFY_SUCCESS(TAG, caRes == CA_STATUS_OK, ERROR);
-                             OIC_LOG(INFO, TAG, "ECDH_ANON CipherSuite is DISABLED");
+ int HandleDoxmPostRequestSVR()
+ {
+     OCStackResult ownerRes = SetAclRownerId(&gDoxm->owner);
+     if (OC_STACK_OK != ownerRes && OC_STACK_NO_RESOURCE != ownerRes)
+     {
+         OIC_LOG_V(ERROR, TAG, "%s: set acl RownerId", __func__);
+         return 1;
+     }
+     ownerRes = SetCredRownerId(&gDoxm->owner);
+     if (OC_STACK_OK != ownerRes && OC_STACK_NO_RESOURCE != ownerRes)
+     {
+         OIC_LOG_V(ERROR, TAG, "%s: set cred RownerId", __func__);
+         return 1;
+     }
+     ownerRes = SetPstatRownerId(&gDoxm->owner);
+     if (OC_STACK_OK != ownerRes && OC_STACK_NO_RESOURCE != ownerRes)
+     {
+         OIC_LOG_V(ERROR, TAG, "%s: set pstat RownerId", __func__);
+         return 1;
+     }
+     ownerRes = SetDpairingRownerId(&gDoxm->owner);
+     if (OC_STACK_OK != ownerRes && OC_STACK_NO_RESOURCE != ownerRes)
+     {
+         OIC_LOG_V(ERROR, TAG, "%s: set dpairing RownerId", __func__);
+         return 1;
+     }
+     ownerRes = SetPconfRownerId(&gDoxm->owner);
+     if (OC_STACK_OK != ownerRes && OC_STACK_NO_RESOURCE != ownerRes)
+     {
+         OIC_LOG_V(ERROR, TAG, "%s: set pconf RownerId", __func__);
+         return 1;
+     }
  
-                             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");
+     return 0;
+ }
  
-                             //Set the device id to derive temporal PSK
-                             SetUuidForPinBasedOxm(&gDoxm->deviceID);
-                         }
-                         else
-                         {
-                             OIC_LOG(WARNING, TAG, "Unsupported OxM for Multiple Ownership Transfer.");
-                         }
+ OCEntityHandlerResult HandleDoxmPostRequestUpdatePS(bool fACE)
+ {
+     //Update new state in persistent storage
+     if (UpdatePersistentStorage(gDoxm) == true)
+     {
+         //Update default ACE of security resource to prevent anonymous user access.
+         if (fACE)
+         {
+             if (OC_STACK_OK == UpdateDefaultSecProvACE())
+             {
+                 return  OC_EH_OK;
+             }
+             else
+             {
+                 OIC_LOG_V(ERROR, TAG, "%s: Failed to remove default ACL for security provisioning", __func__);
+                 return OC_EH_ERROR;
+             }
+         }
+         return OC_EH_OK;
+     }
+     else
+     {
+         OIC_LOG_V(ERROR, TAG, "%s: Failed to update DOXM in persistent storage", __func__);
+         return OC_EH_ERROR;
+     }
+ }
  
-                         CAregisterSslHandshakeCallback(MultipleOwnerDTLSHandshakeCB);
-                     }
-                     else
-                     {
-                         //if MOM is disabled, revert the DTLS handshake callback
-                         if(CA_STATUS_OK != CAregisterSslHandshakeCallback(NULL))
-                         {
-                             OIC_LOG(WARNING, TAG, "Error while revert the DTLS Handshake Callback.");
-                         }
-                     }
-                 }
+ OCEntityHandlerResult HandleDoxmPostRequestJustWork(OicSecDoxm_t *newDoxm,
+         OCEntityHandlerRequest *ehRequest,
+         bool isDuplicatedMsg)
+ {
+     OIC_LOG_V(DEBUG, TAG, "%s: IN", __func__);
+     OCEntityHandlerResult ehRet = OC_EH_OK;
  
                if(newDoxm->subOwners)
-                 {
-                     OicSecSubOwner_t* subowner = NULL;
-                     OicSecSubOwner_t* temp = NULL;
#if !(defined(__WITH_DTLS__) || defined(__WITH_TLS__))
+     OC_UNUSED(isDuplicatedMsg);
+     OC_UNUSED(ehRequest);
+ #endif // not __WITH_DTLS__ and not __WITH_TLS__
  
-                     OIC_LOG(DEBUG, TAG, "dectected 'subowners' property");
+     if (IsNilUuid(&newDoxm->owner))
+     {
+         gDoxm->oxmSel = newDoxm->oxmSel;
+         /*
+         * 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.
+         */
+ #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;
+     }
+     else
+     {
+ #if defined(__WITH_DTLS__) || defined(__WITH_TLS__)
+         //Save the owner's UUID to derive owner credential
+         memcpy(&(gDoxm->owner), &(newDoxm->owner), sizeof(OicUuid_t));
  
-                     if(gDoxm->subOwners)
-                     {
-                         LL_FOREACH_SAFE(gDoxm->subOwners, subowner, temp)
-                         {
-                             LL_DELETE(gDoxm->subOwners, subowner);
-                             OICFree(subowner);
-                         }
-                     }
+         /*
+          * 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}};
  
-                     subowner = NULL;
-                     temp = NULL;
-                     LL_FOREACH_SAFE(newDoxm->subOwners, subowner, temp)
-                     {
-                         LL_DELETE(newDoxm->subOwners, subowner);
-                         LL_APPEND(gDoxm->subOwners, subowner);
-                     }
-                 }
- #endif //MULTIPLE_OWNER
- #endif // defined(__WITH_DTLS__) || defined (__WITH_TLS__)
+             //Generate mutualVerifNum
 -            OCServerRequest *request = GetServerRequestUsingHandle(ehRequest->requestHandle);
++            OCServerRequest * request = (OCServerRequest *)ehRequest->requestHandle;
  
-                 //Update new state in persistent storage
-                 if (UpdatePersistentStorage(gDoxm) == true)
-                 {
-                     ehRet = OC_EH_OK;
-                 }
-                 else
-                 {
-                     OIC_LOG(ERROR, TAG, "Failed to update DOXM in persistent storage");
-                     ehRet = OC_EH_ERROR;
-                 }
+             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;
              }
  
-             // in unowned state
-             // TODO [IOT-2107] this logic assumes that the only POST to /doxm in
-             // unowned state is either a) changing to owned or b) setting oxmsel and
-             // therefore (in case b) should enable the proper cipher for OTM.  But it's
-             // allowable for Client to be posting other things such as /doxm.rowneruuid
-             // when owned == false, too.  Added a workaround (see 'workaround' below)
-             // but this POST handler needs to be fixed per IOT-2107.
-             if ((false == gDoxm->owned) && (false == newDoxm->owned))
+             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)
              {
-                 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;
-                 }
+                 OIC_LOG(WARNING, TAG, "Failed to remove the invaild owner credential");
+                 ehRet = OC_EH_ERROR;
+                 goto exit;
  
-                 // workaround
-                 // We wouldn't be at this point in the
-                 // code if the POST contained R-only Properties for the current /pstat.dos.s
-                 // state, so we want to update writeable properties now that we've validated
-                 // oxmsel is a valid oxm for this device.
-                 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 (OIC_JUST_WORKS == newDoxm->oxmSel || OIC_MV_JUST_WORKS == newDoxm->oxmSel)
-                 {
-                     /*
-                      * 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.
-                      */
-                     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;
-                         }
- #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;
-                     }
-                     else
-                     {
- #if defined(__WITH_DTLS__) || defined(__WITH_TLS__)
-                         //Save the owner's UUID to derive owner credential
-                         memcpy(&(gDoxm->owner), &(newDoxm->owner), sizeof(OicUuid_t));
+             memcpy(mutualVerifNum, preMutualVerifNum + OWNER_PSK_LENGTH_128 - sizeof(mutualVerifNum),
+                    sizeof(mutualVerifNum));
  
-                         // Update new state in persistent storage
-                         if (true == UpdatePersistentStorage(gDoxm))
-                         {
-                             ehRet = OC_EH_OK;
-                         }
-                         else
-                         {
-                             OIC_LOG(ERROR, TAG, "Failed to update DOXM in persistent storage");
-                             ehRet = OC_EH_ERROR;
-                             goto exit;
-                         }
+             //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__
+     }
+ exit:
+     OIC_LOG_V(DEBUG, TAG, "%s: OUT", __func__);
+     return ehRet;
+ }
  
-                         /*
-                          * 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 = (OCServerRequest *)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;
-                             }
-                             CAEndpoint_t endpoint = {.adapter = CA_DEFAULT_ADAPTER};
-                             CopyDevAddrToEndpoint(&request->devAddr, &endpoint);
-                             CAResult_t pskRet = CAGenerateOwnerPSK(&endpoint,
-                                     (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;
-                             }
-                         }
+ OCEntityHandlerResult HandleDoxmPostRequestRandomPin(OicSecDoxm_t *newDoxm,
+         OCEntityHandlerRequest *ehRequest,
+         bool isDuplicatedMsg)
+ {
+     OIC_LOG_V(DEBUG, TAG, "%s: IN", __func__);
+     OCEntityHandlerResult ehRet = OC_EH_OK;
  
- #endif // __WITH_DTLS__ or __WITH_TLS__
-                     }
-                 }
-                 else if (OIC_RANDOM_DEVICE_PIN == newDoxm->oxmSel)
-                 {
-                     /*
-                      * If current state of the device is un-owned, enable
-                      * ECDHE_PSK cipher so that the Provisioning tool can
-                      * initiate the ownership transfer.
-                      */
-                     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;
-                         }
+ #if !(defined(__WITH_DTLS__) || defined(__WITH_TLS__))
+     OC_UNUSED(isDuplicatedMsg);
+     OC_UNUSED(ehRequest);
+ #endif // not __WITH_DTLS__ and not __WITH_TLS__
  
+     if (IsNilUuid(&newDoxm->owner))
+     {
+         gDoxm->oxmSel = newDoxm->oxmSel;
+         /*
+         * If current state of the device is un-owned, enable
+         * ECDHE_PSK cipher so that the Provisioning tool can
+         * initiate the ownership transfer.
+         */
  #if defined(__WITH_DTLS__) || defined(__WITH_TLS__)
-                         CAResult_t caRes = CAEnableAnonECDHCipherSuite(false);
-                         VERIFY_SUCCESS(TAG, caRes == CA_STATUS_OK, ERROR);
-                         OIC_LOG(INFO, TAG, "ECDH_ANON CipherSuite is DISABLED");
+         CAResult_t caRes = CAEnableAnonECDHCipherSuite(false);
+         VERIFY_SUCCESS(TAG, caRes == CA_STATUS_OK, ERROR);
+         OIC_LOG(INFO, TAG, "ECDH_ANON CipherSuite is DISABLED");
  
-                         RegisterOTMSslHandshakeCallback(DoxmDTLSHandshakeCB);
-                         caRes = CASelectCipherSuite(MBEDTLS_TLS_ECDHE_PSK_WITH_AES_128_CBC_SHA256,
-                                                     ehRequest->devAddr.adapter);
-                         VERIFY_SUCCESS(TAG, caRes == CA_STATUS_OK, ERROR);
+         RegisterOTMSslHandshakeCallback(DoxmDTLSHandshakeCB);
+         caRes = CASelectCipherSuite(MBEDTLS_TLS_ECDHE_PSK_WITH_AES_128_CBC_SHA256,
+                                     (CATransportAdapter_t)ehRequest->devAddr.adapter);
+         VERIFY_SUCCESS(TAG, caRes == CA_STATUS_OK, ERROR);
  
-                         if (!isDuplicatedMsg)
-                         {
-                             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);
-                                 /**
-                                  * 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;
-                             }
-                         }
+         if (!isDuplicatedMsg)
+         {
+             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);
+                 /**
+                  * 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__)
-                     else
-                     {
-                         //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();
-                         }
+     else
+     {
+         //Save the owner's UUID to derive owner credential
+         memcpy(&(gDoxm->owner), &(newDoxm->owner), sizeof(OicUuid_t));
  
-                         //Update new state in persistent storage
-                         if (UpdatePersistentStorage(gDoxm) == true)
-                         {
-                             ehRet = OC_EH_OK;
-                         }
-                         else
-                         {
-                             OIC_LOG(ERROR, TAG, "Failed to update DOXM in persistent storage");
-                             ehRet = OC_EH_ERROR;
-                         }
-                     }
+         // In case of random-pin based OTM, close the PIN display if callback is registered.
+         if (!isDuplicatedMsg)
+         {
+             ClosePinDisplay();
+         }
+     }
  #endif // __WITH_DTLS__ or __WITH_TLS__
-                 }
+     goto exit;
+ exit:
+     OIC_LOG_V(DEBUG, TAG, "%s: OUT", __func__);
+     return ehRet;
+ }
  #if defined(__WITH_DTLS__) || defined (__WITH_TLS__)
-                 else if (OIC_MANUFACTURER_CERTIFICATE ==  newDoxm->oxmSel || OIC_CON_MFG_CERT == newDoxm->oxmSel)
-                 {
-                     //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;
-                         }
-                     }
+ OCEntityHandlerResult HandleDoxmPostRequestMfg(OicSecDoxm_t *newDoxm,
+         OCEntityHandlerRequest *ehRequest,
+         bool isDuplicatedMsg)
+ {
+     OIC_LOG_V(DEBUG, TAG, "%s: IN", __func__);
+     OCEntityHandlerResult 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(DoxmDTLSHandshakeCB);
-                     CAResult_t caRes = CAEnableAnonECDHCipherSuite(false);
-                     VERIFY_SUCCESS(TAG, caRes == CA_STATUS_OK, ERROR);
-                     OIC_LOG(INFO, TAG, "ECDH_ANON CipherSuite is DISABLED");
+         //In case of Confirm Manufacturer Cert, get user confirmation
+         if (OIC_CON_MFG_CERT == newDoxm->oxmSel && false == newDoxm->owned &&
+             false == isDuplicatedMsg && !IsNilUuid(&newDoxm->owner))
+         {
+             if (OC_STACK_OK != VerifyOwnershipTransfer(NULL, USER_CONFIRM))
+             {
+                 ehRet = OC_EH_NOT_ACCEPTABLE;
+                 goto exit;
+             }
+             else
+             {
+                 ehRet = OC_EH_OK;
+             }
+         }
  
-                     //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");
+         //Save the owner's UUID to derive owner credential
+         memcpy(&(gDoxm->owner), &(newDoxm->owner), sizeof(OicUuid_t));
+         gDoxm->oxmSel = newDoxm->oxmSel;
  
-                     VERIFY_SUCCESS(TAG, CA_STATUS_OK == CAregisterPkixInfoHandler(GetManufacturerPkixInfo), ERROR);
-                     VERIFY_SUCCESS(TAG, CA_STATUS_OK == CAregisterGetCredentialTypesHandler(InitManufacturerCipherSuiteList), ERROR);
-                 }
- #endif // __WITH_DTLS__ or __WITH_TLS__
-             }
+         RegisterOTMSslHandshakeCallback(DoxmDTLSHandshakeCB);
+         CAResult_t caRes = CAEnableAnonECDHCipherSuite(false);
+         VERIFY_SUCCESS(TAG, caRes == CA_STATUS_OK, ERROR);
+         OIC_LOG(INFO, TAG, "ECDH_ANON CipherSuite is DISABLED");
  
-             /*
-              * 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;
-                     goto exit;
-                 }
-                 ownerRes = SetCredRownerId(&gDoxm->owner);
-                 if(OC_STACK_OK != ownerRes && OC_STACK_NO_RESOURCE != ownerRes)
-                 {
-                     ehRet = OC_EH_ERROR;
-                     goto exit;
-                 }
-                 ownerRes = SetPstatRownerId(&gDoxm->owner);
-                 if(OC_STACK_OK != ownerRes && OC_STACK_NO_RESOURCE != ownerRes)
-                 {
-                     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;
-                 }
+         //Unset pre-selected ciphersuite, if any
+         caRes = CASelectCipherSuite(0,(CATransportAdapter_t)ehRequest->devAddr.adapter);
+         VERIFY_SUCCESS(TAG, caRes == CA_STATUS_OK, ERROR);
+         OIC_LOG(DEBUG, TAG, "No ciphersuite preferred");
  
-                 gDoxm->owned = true;
-                 memcpy(&gDoxm->rownerID, &gDoxm->owner, sizeof(OicUuid_t));
+         VERIFY_SUCCESS(TAG, CA_STATUS_OK == CAregisterPkixInfoHandler(GetManufacturerPkixInfo), ERROR);
+         VERIFY_SUCCESS(TAG, CA_STATUS_OK == CAregisterGetCredentialTypesHandler(
+                            InitManufacturerCipherSuiteList), ERROR);
+ exit:
+     OIC_LOG_V(DEBUG, TAG, "%s: OUT", __func__);
+     return ehRet;
+     }
+ #endif // __WITH_DTLS__ or __WITH_TLS__
  
-                 // Update new state in persistent storage
-                 if (UpdatePersistentStorage(gDoxm))
-                 {
-                     //Update default ACE of security resource to prevent anonymous user access.
-                     if(OC_STACK_OK == UpdateDefaultSecProvACE())
-                     {
-                         ehRet = OC_EH_OK;
-                     }
-                     else
-                     {
-                         OIC_LOG(ERROR, TAG, "Failed to remove default ACL for security provisioning");
-                         ehRet = OC_EH_ERROR;
-                     }
-                 }
-                 else
-                 {
-                     OIC_LOG(ERROR, TAG, "Failed to update DOXM in persistent storage");
-                     ehRet = OC_EH_ERROR;
-                 }
+ //Change the SVR's resource owner as owner device.
+ OCEntityHandlerResult HandleDoxmPostRequestSrv(OicSecDoxm_t *newDoxm,
+         OCEntityHandlerRequest *ehRequest,
+         bool isDuplicatedMsg)
+ {
+     OIC_LOG_V(DEBUG, TAG, "%s: IN", __func__);
+     OCEntityHandlerResult ehRet = OC_EH_OK;
+     switch (newDoxm->oxmSel)
+     {
+         case OIC_JUST_WORKS:
+         case OIC_MV_JUST_WORKS:
+             ehRet = HandleDoxmPostRequestJustWork(newDoxm, ehRequest, isDuplicatedMsg);
+             break;
+         case OIC_RANDOM_DEVICE_PIN:
+             ehRet = HandleDoxmPostRequestRandomPin(newDoxm, ehRequest, isDuplicatedMsg);
+             break;
  #if defined(__WITH_DTLS__) || defined (__WITH_TLS__)
-                 if (OIC_MANUFACTURER_CERTIFICATE == gDoxm->oxmSel ||
-                                             OIC_CON_MFG_CERT== gDoxm->oxmSel)
-                 {
-                     CAregisterPkixInfoHandler(GetPkixInfo);
-                     CAregisterGetCredentialTypesHandler(InitCipherSuiteList);
-                 }
+         case OIC_MANUFACTURER_CERTIFICATE:
+         case OIC_CON_MFG_CERT:
+             ehRet = HandleDoxmPostRequestMfg(newDoxm, ehRequest, isDuplicatedMsg);
+             break;
  #endif // __WITH_DTLS__ or __WITH_TLS__
-             }
+         default:
+             break;
+     }
+     OIC_LOG_V(DEBUG, TAG, "%s: OUT", __func__);
+     return ehRet;
+ }
+ static OCEntityHandlerResult HandleDoxmPostRequest(OCEntityHandlerRequest *ehRequest)
+ {
+     OIC_LOG_V(DEBUG, TAG, "%s: IN", __func__);
+     OCEntityHandlerResult ehRet = OC_EH_INTERNAL_SERVER_ERROR;
+     static uint16_t previousMsgId = 0;
+     bool isDuplicatedMsg = false;
+     /*
+      * Convert CBOR Doxm data into binary. This will also validate
+      * the Doxm data received.
+      */
+     OicSecDoxm_t *newDoxm = NULL;
+     VERIFY_NOT_NULL(TAG, ehRequest, ERROR);
+     VERIFY_NOT_NULL(TAG, ehRequest->payload, ERROR);
+     uint8_t *payload = ((OCSecurityPayload *)ehRequest->payload)->securityData;
+     VERIFY_NOT_NULL(TAG, payload, ERROR);
+     size_t size = ((OCSecurityPayload *)ehRequest->payload)->payloadSize;
+     bool roParsed = false;
+     OicSecDostype_t onboardingState;
+     //get new doxm
+     VERIFY_SUCCESS(TAG, OC_STACK_OK == GetDos(&onboardingState), ERROR);
+     OCStackResult res = CBORPayloadToDoxmBin(payload, size, &newDoxm, &roParsed,
+                         onboardingState.state);
+     VERIFY_SUCCESS(TAG, OC_STACK_OK == res, ERROR);
+     VERIFY_NOT_NULL(TAG, newDoxm, ERROR);
+     /*
+      * 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 properties");
+         ehRet = OC_EH_NOT_ACCEPTABLE;
+         goto exit;
+     }
+     VERIFY_NOT_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 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 MULTIPLE_OWNER
+         HandleDoxmPostRequestMom(newDoxm, ehRequest);
+ #endif //MULTIPLE_OWNER
+ #endif // defined(__WITH_DTLS__) || defined (__WITH_TLS__)
+         //Update new state in persistent storage
+         ehRet = HandleDoxmPostRequestUpdatePS(false);
+         goto exit;
      }
  
- exit:
-     if(OC_EH_OK != ehRet)
+     // in unowned state
+     // TODO [IOT-2107] this logic assumes that the only POST to /doxm in
+     // unowned state is either a) changing to owned or b) setting oxmsel and
+     // therefore (in case b) should enable the proper cipher for OTM.  But it's
+     // allowable for Client to be posting other things such as /doxm.rowneruuid
+     // when owned == false, too.  Added a workaround (see 'workaround' below)
+     // but this POST handler needs to be fixed per IOT-2107.
+     if ((false == gDoxm->owned) && (false == newDoxm->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;
+         }
  
-         /*
-          * If some error is occured while ownership transfer,
-          * ownership transfer related resource should be revert back to initial status.
-         */
-         if(gDoxm)
+         // workaround
+         // We wouldn't be at this point in the
+         // code if the POST contained R-only Properties for the current /pstat.dos.s
+         // state, so we want to update writeable properties now that we've validated
+         // oxmsel is a valid oxm for this device.
+         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;
+         }
+         ehRet = HandleDoxmPostRequestSrv(newDoxm, ehRequest, isDuplicatedMsg);
+         VERIFY_SUCCESS(TAG, OC_EH_OK == ehRet, ERROR);
+         // Update new state in persistent storage
+         ehRet = HandleDoxmPostRequestUpdatePS(false);
+     }
+     /*
+      * 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) &&
+             UuidCmp(&gDoxm->owner, &newDoxm->owner))
+     {
+         if (HandleDoxmPostRequestSVR())
+         {
+             ehRet = OC_EH_ERROR;
+             goto exit;
+         }
+         gDoxm->owned = true;
+         memcpy(&gDoxm->rownerID, &gDoxm->owner, sizeof(OicUuid_t));
+         // Update new state in persistent storage
+         ehRet = HandleDoxmPostRequestUpdatePS(true);
+ #if defined(__WITH_DTLS__) || defined (__WITH_TLS__)
+         if (OIC_MANUFACTURER_CERTIFICATE == gDoxm->oxmSel ||
+             OIC_CON_MFG_CERT == gDoxm->oxmSel)
          {
-             if(!gDoxm->owned)
+             CAregisterPkixInfoHandler(GetPkixInfo);
+             CAregisterGetCredentialTypesHandler(InitCipherSuiteList);
+         }
+ #endif // __WITH_DTLS__ or __WITH_TLS__
+     }
+ exit:
+     if (OC_EH_OK != ehRet)
+     {
+     /*
+      * If some error is occured while ownership transfer,
+      * ownership transfer related resource should be revert back to initial status.
+     */
+     if (gDoxm)
+         {
+             if (!gDoxm->owned)
              {
                  OIC_LOG(WARNING, TAG, "The operation failed during handle DOXM request");
  
Simple merge
Simple merge
Simple merge
index 2d3f18c,2d3f18c..a450e95
Binary files differ
index ccae7d3,ccae7d3..f2f55a5
Binary files differ
@@@ -123,15 -123,24 +123,15 @@@ svr_db_src_dir = src_dir + '/resource/p
  svr_db_build_dir = examples_env.get(
      'BUILD_DIR') + '/resource/provisioning/examples/'
  
 -clientjson = examples_env.Install(
 -    svr_db_build_dir, svr_db_src_dir + 'oic_svr_db_client.json')
 -clientdat = examples_env.Install(
 -    svr_db_build_dir, svr_db_src_dir + 'oic_svr_db_client.dat')
 +actions += examples_env.ScanJSON('resource/provisioning/examples')
  
 -if examples_env.get('MULTIPLE_OWNER') == '1':
 -    subownerclientdat = examples_env.Install(
 -        svr_db_build_dir, svr_db_src_dir + 'oic_svr_db_subowner_client.dat')
 -    Alias("subowner", [subownerclientdat, subownerclient])
 -    examples_env.AppendTarget("subowner")
 +if examples_env.get('MULTIPLE_OWNER') != '1':
 +    Delete(svr_db_build_dir  + 'oic_svr_db_subowner_client.dat')
  
- if examples_env.get('WITH_TCP') == True:
+ if examples_env.get('WITH_TCP') == True and examples_env.get('WITH_CLOUD') == True:
 -    clouddat = examples_env.Install(
 -        svr_db_build_dir, svr_db_src_dir + 'cloud.dat')
 -    rootcert = examples_env.Install(
 -        svr_db_build_dir, svr_db_src_dir + 'rootca.crt')
 -    Alias("cloud", [clouddat, rootcert, cloudClient])
 -    examples_env.AppendTarget("cloud")
 -
 -Alias("examples", [provisioningclient, clientjson, clientdat])
 +    actions += examples_env.Install(svr_db_build_dir, svr_db_src_dir + 'rootca.crt')
 +else:
 +    Delete(svr_db_build_dir  + 'cloud.dat')
 +
 +Alias("examples", actions)
  examples_env.AppendTarget('examples')
@@@ -104,10 -96,14 +104,10 @@@ if provisiontests_env.get('SECURED') =
  ######################################################################
  # Source files and Targets
  ######################################################################
 -ocprovisiontest_src = [
 -        'OCProvisioningTest.cpp'
 -        ]
 +ocprovisiontest_src = ['OCProvisioningTest.cpp']
  
- if provisiontests_env.get('WITH_TCP') == True:
+ if provisiontests_env.get('WITH_TCP') == True and provisiontests_env.get('WITH_CLOUD') == True:
 -        ocprovisiontest_src = ocprovisiontest_src + [
 -        'OCCloudProvisioningTest.cpp'
 -        ]
 +    ocprovisiontest_src = ocprovisiontest_src + ['OCCloudProvisioningTest.cpp']
  
  unittests = provisiontests_env.Program('provisiontests', ocprovisiontest_src)
  
@@@ -317,8 -324,8 +324,8 @@@ TEST_F(EasysetupEnrolleeTest, DevicePro
              if(status->getESResult() == ES_OK)
              {
                  EnrolleeConf conf = status->getEnrolleeConf();
-                 if(conf.getWiFiModes().at(0) == WIFI_11G &&
-                     conf.getWiFiFreq() == WIFI_5G &&
+                 if(conf.getWiFiModes().size() > 0 && conf.getWiFiModes().at(0) == WIFI_11G &&
 -                    conf.getWiFiFreq() == WIFI_5G &&
++                    conf.getWiFiFreq() == WIFI_BOTH &&
                      !strcmp(conf.getDeviceName().c_str(), "Test Device"))
                  {
                      isWellConstructed = true;
@@@ -39,6 -39,8 +39,8 @@@
  
  #include "escommon.h"
  
 -#include "logger.h"
++#include "experimental/logger.h"
  using namespace OC;
  using namespace std;