replace : iotivity -> iotivity-sec
[platform/upstream/iotivity.git] / resource / csdk / security / provisioning / src / pmutility.c
old mode 100755 (executable)
new mode 100644 (file)
index f679388..0efb109
@@ -21,7 +21,8 @@
 #define _POSIX_C_SOURCE 200112L
 #endif
 
-#if HAVE_UNISTD_H
+#include "iotivity_config.h"
+#ifdef HAVE_UNISTD_H
 #include <unistd.h>
 #endif
 #ifdef HAVE_STRING_H
 #include "oic_string.h"
 #include "oic_time.h"
 #include "logger.h"
+#if defined (__TIZENRT__)
+#include <apps/netutils/cJSON.h>
+#else
 #include "cJSON.h"
+#endif
 #include "utlist.h"
 #include "ocpayload.h"
 
 
 #include "srmutility.h"
 
-#define TAG ("PM-UTILITY")
+#define TAG ("OIC_PM_UTILITY")
 
 typedef struct _DiscoveryInfo{
     OCProvisionDev_t    **ppDevicesList;
+    OCProvisionDev_t    *pCandidateList;
     bool                isOwnedDiscovery;
     bool                isSingleDiscovery;
     bool                isFound;
+    const OicUuid_t     *targetId;
 } DiscoveryInfo;
 
 /*
@@ -68,17 +75,6 @@ typedef struct _DiscoveryInfo{
 static OCStackResult SecurePortDiscovery(DiscoveryInfo* discoveryInfo,
                                          const OCClientResponse *clientResponse);
 
-/*
- * Function to discover security version information through unicast
- *
- * @param[in] discoveryInfo The pointer of discovery information to matain result of discovery
- * @param[in] clientResponse  Response information(It will contain payload)
- *
- * @return OC_STACK_OK on success otherwise error.
- */
-static OCStackResult SecurityVersionDiscovery(DiscoveryInfo* discoveryInfo,
-                                              const OCClientResponse *clientResponse);
-
 /**
  * Callback handler for PMDeviceDiscovery API.
  *
@@ -91,6 +87,22 @@ static OCStackResult SecurityVersionDiscovery(DiscoveryInfo* discoveryInfo,
 static OCStackApplicationResult DeviceDiscoveryHandler(void *ctx, OCDoHandle UNUSED,
                                 OCClientResponse *clientResponse);
 
+/*
+ * Since security version discovery does not used anymore, disable security version discovery.
+ * Need to discussion to removing all version discovery related codes.
+ */
+#if 0
+/*
+ * Function to discover security version information through unicast
+ *
+ * @param[in] discoveryInfo The pointer of discovery information to matain result of discovery
+ * @param[in] clientResponse  Response information(It will contain payload)
+ *
+ * @return OC_STACK_OK on success otherwise error.
+ */
+static OCStackResult SecurityVersionDiscovery(DiscoveryInfo* discoveryInfo,
+                                              const OCClientResponse *clientResponse);
+
 /**
  * Callback handler for getting secure port information using /oic/res discovery.
  *
@@ -103,7 +115,13 @@ static OCStackApplicationResult DeviceDiscoveryHandler(void *ctx, OCDoHandle UNU
  */
 static OCStackApplicationResult SecurePortDiscoveryHandler(void *ctx, OCDoHandle UNUSED,
                                  OCClientResponse *clientResponse);
+#endif
 
+/*
+ * Since security version discovery does not used anymore, disable security version discovery.
+ * Need to discussion to removing all version discovery related codes.
+ */
+#if 0
 /**
  * Callback handler for security version discovery.
  *
@@ -115,6 +133,7 @@ static OCStackApplicationResult SecurePortDiscoveryHandler(void *ctx, OCDoHandle
  */
 static OCStackApplicationResult SecVersionDiscoveryHandler(void *ctx, OCDoHandle UNUSED,
                                 OCClientResponse *clientResponse);
+#endif
 
 /**
  * Function to search node in linked list that matches given IP and port.
@@ -136,7 +155,7 @@ OCProvisionDev_t* GetDevice(OCProvisionDev_t **ppDevicesList, const char* addr,
     OCProvisionDev_t *ptr = NULL;
     LL_FOREACH(*ppDevicesList, ptr)
     {
-        if( strcmp(ptr->endpoint.addr, addr) == 0 && port == ptr->endpoint.port)
+        if( (ptr && ptr->endpoint.addr) && strncmp(ptr->endpoint.addr, addr, MAX_ADDR_STR_SIZE) == 0 && port == ptr->endpoint.port)
         {
             return ptr;
         }
@@ -176,11 +195,13 @@ OCStackResult AddDevice(OCProvisionDev_t **ppDevicesList, OCDevAddr* endpoint,
 
         ptr->endpoint = *endpoint;
         ptr->doxm = doxm;
-        ptr->securePort = DEFAULT_SECURE_PORT;
+        ptr->securePort = (CT_ADAPTER_GATT_BTLE == connType) ?
+                          endpoint->port : DEFAULT_SECURE_PORT;
         ptr->next = NULL;
         ptr->connType = connType;
         ptr->devStatus = DEV_STATUS_ON; //AddDevice is called when discovery(=alive)
-        OICStrcpy(ptr->secVer, MAX_VERSION_LEN, DEFAULT_SEC_VERSION); // version initialization
+        OICStrcpy(ptr->secVer, OIC_SEC_MAX_VER_LEN, DEFAULT_SEC_VERSION); // version initialization
+        ptr->handle = NULL;
 
         LL_PREPEND(*ppDevicesList, ptr);
     }
@@ -189,6 +210,35 @@ OCStackResult AddDevice(OCProvisionDev_t **ppDevicesList, OCDevAddr* endpoint,
 }
 
 /**
+ * Move device object between two device lists.
+ *
+ * @param[in] ppDstDevicesList         Destination list of OCProvisionDev_t.
+ * @param[in] ppSrcDevicesList         Source list of OCProvisionDev_t.
+ * @param[in] endpoint      target device endpoint.
+ *
+ * @return OC_STACK_OK for success and error code otherwise.
+ */
+OCStackResult MoveDeviceList(OCProvisionDev_t **ppDstDevicesList,
+                        OCProvisionDev_t **ppSrcDevicesList, OCDevAddr* endpoint)
+{
+    if (NULL == ppSrcDevicesList || NULL == endpoint)
+    {
+        return OC_STACK_INVALID_PARAM;
+    }
+
+    OCProvisionDev_t *ptr = GetDevice(ppSrcDevicesList, endpoint->addr, endpoint->port);
+    if(ptr)
+    {
+        LL_DELETE(*ppSrcDevicesList, ptr);
+        LL_PREPEND(*ppDstDevicesList, ptr);
+        OIC_LOG_V(DEBUG, TAG, "MoveDeviceList success : %s(%d)", endpoint->addr, endpoint->port);
+        return OC_STACK_OK;
+    }
+
+    return OC_STACK_ERROR;
+}
+
+/**
  * Function to set secure port information from the given list of devices.
  *
  * @param[in] pList         List of OCProvisionDev_t.
@@ -213,7 +263,8 @@ static OCStackResult UpdateSecurePortOfDevice(OCProvisionDev_t **ppDevicesList,
         return OC_STACK_ERROR;
     }
 
-    ptr->securePort = securePort;
+    ptr->securePort = (OC_ADAPTER_GATT_BTLE == ptr->endpoint.adapter) ?
+                      ptr->endpoint.port : securePort;
 
 #ifdef __WITH_TLS__
     ptr->tcpPort = tcpPort;
@@ -248,7 +299,7 @@ OCStackResult UpdateSecVersionOfDevice(OCProvisionDev_t **ppDevicesList, const c
         return OC_STACK_ERROR;
     }
 
-    OICStrcpy(ptr->secVer, MAX_VERSION_LEN, secVer);
+    OICStrcpy(ptr->secVer, OIC_SEC_MAX_VER_LEN, secVer);
 
     return OC_STACK_OK;
 }
@@ -313,11 +364,11 @@ OCProvisionDev_t* PMCloneOCProvisionDev(const OCProvisionDev_t* src)
 
     if (0 == strlen(src->secVer))
     {
-        OICStrcpy(newDev->secVer, MAX_VERSION_LEN, DEFAULT_SEC_VERSION);
+        OICStrcpy(newDev->secVer, OIC_SEC_MAX_VER_LEN, DEFAULT_SEC_VERSION);
     }
     else
     {
-        OICStrcpy(newDev->secVer, MAX_VERSION_LEN, src->secVer);
+        OICStrcpy(newDev->secVer, OIC_SEC_MAX_VER_LEN, src->secVer);
     }
 
     newDev->securePort = src->securePort;
@@ -441,13 +492,26 @@ bool PMGenerateQuery(bool isSecure,
             switch(connType & CT_MASK_FLAGS & ~CT_FLAG_SECURE)
             {
                 case CT_IP_USE_V4:
-                        snRet = snprintf(buffer, bufferSize, "%s%s:%d%s",
-                                         prefix, address, port, uri);
+                    snRet = snprintf(buffer, bufferSize, "%s%s:%d%s",
+                                     prefix, address, port, uri);
                     break;
                 case CT_IP_USE_V6:
-                        snRet = snprintf(buffer, bufferSize, "%s[%s]:%d%s",
-                                         prefix, address, port, uri);
+                {
+                    char addressEncoded[128] = {0};
+
+                    OCStackResult result = OCEncodeAddressForRFC6874(addressEncoded,
+                                                                     sizeof(addressEncoded),
+                                                                     address);
+                    if (OC_STACK_OK != result)
+                    {
+                        OIC_LOG_V(ERROR, TAG, "PMGenerateQuery : encoding error %d\n", result);
+                        return false;
+                    }
+
+                    snRet = snprintf(buffer, bufferSize, "%s[%s]:%d%s",
+                                     prefix, addressEncoded, port, uri);
                     break;
+                }
                 default:
                     OIC_LOG(ERROR, TAG, "Unknown address format.");
                     return false;
@@ -465,8 +529,23 @@ bool PMGenerateQuery(bool isSecure,
             }
 
             break;
-        // TODO: We need to verify tinyDTLS in below cases
         case CT_ADAPTER_GATT_BTLE:
+            snRet = snprintf(buffer, bufferSize, "%s%s%s",
+                             prefix, address, uri);
+            // snprintf return value check
+            if (snRet < 0)
+            {
+                OIC_LOG_V(ERROR, TAG, "PMGenerateQuery : Error (snprintf) %d\n", snRet);
+                return false;
+            }
+            else if ((size_t)snRet >= bufferSize)
+            {
+                OIC_LOG_V(ERROR, TAG, "PMGenerateQuery : Truncated (snprintf) %d\n", snRet);
+                return false;
+            }
+
+            break;
+        // TODO: We need to verify tinyDTLS in below cases
         case CT_ADAPTER_RFCOMM_BTEDR:
             OIC_LOG(ERROR, TAG, "Not supported connectivity adapter.");
             return false;
@@ -479,6 +558,11 @@ bool PMGenerateQuery(bool isSecure,
     return true;
 }
 
+/*
+ * Since security version discovery does not used anymore, disable security version discovery.
+ * Need to discussion to removing all version discovery related codes.
+ */
+#if 0
 static OCStackApplicationResult SecurityVersionDiscoveryHandler(void *ctx, OCDoHandle UNUSED,
                                 OCClientResponse *clientResponse)
 {
@@ -540,10 +624,6 @@ static OCStackApplicationResult SecurityVersionDiscoveryHandler(void *ctx, OCDoH
 
                 OIC_LOG(INFO, TAG, "Exiting SecVersionDiscoveryHandler.");
                 DeleteVerBinData(ptrVer);
-                if(pDInfo->isSingleDiscovery)
-                {
-                    pDInfo->isFound = true;
-                }
             }
         }
     }
@@ -555,6 +635,7 @@ static OCStackApplicationResult SecurityVersionDiscoveryHandler(void *ctx, OCDoH
 
     return  OC_STACK_DELETE_TRANSACTION;
 }
+#endif
 
 static OCStackApplicationResult SecurePortDiscoveryHandler(void *ctx, OCDoHandle UNUSED,
                                  OCClientResponse *clientResponse)
@@ -614,7 +695,16 @@ static OCStackApplicationResult SecurePortDiscoveryHandler(void *ctx, OCDoHandle
             OIC_LOG_V(DEBUG, TAG, "%s: TCP port from discovery = %d", __func__, resPayload->tcpPort);
 #endif
             DiscoveryInfo* pDInfo = (DiscoveryInfo*)ctx;
-            OCStackResult res = UpdateSecurePortOfDevice(pDInfo->ppDevicesList,
+            OCProvisionDev_t *ptr = GetDevice(&pDInfo->pCandidateList,
+                                                         clientResponse->devAddr.addr,
+                                                         clientResponse->devAddr.port);
+            if(!ptr)
+            {
+                OIC_LOG(ERROR, TAG, "Can not find device information in the discovery candidate device list");
+                return OC_STACK_DELETE_TRANSACTION;
+            }
+
+            OCStackResult res = UpdateSecurePortOfDevice(&pDInfo->pCandidateList,
                                                          clientResponse->devAddr.addr,
                                                          clientResponse->devAddr.port,
                                                          securePort
@@ -628,13 +718,30 @@ static OCStackApplicationResult SecurePortDiscoveryHandler(void *ctx, OCDoHandle
                 return OC_STACK_DELETE_TRANSACTION;
             }
 
+            res = MoveDeviceList(pDInfo->ppDevicesList, &pDInfo->pCandidateList, &clientResponse->devAddr);
+            if(OC_STACK_OK != res)
+            {
+                OIC_LOG(ERROR, TAG, "Error while move the discovered device to list.");
+                return OC_STACK_DELETE_TRANSACTION;
+            }
+
+            if(pDInfo->isSingleDiscovery)
+            {
+                pDInfo->isFound = true;
+            }
+
+/*
+ * Since security version discovery does not used anymore, disable security version discovery.
+ * Need to discussion to removing all version discovery related codes.
+ */
+#if 0
             res = SecurityVersionDiscovery(pDInfo, clientResponse);
             if(OC_STACK_OK != res)
             {
                 OIC_LOG(ERROR, TAG, "Failed to SecurityVersionDiscovery");
                 return OC_STACK_DELETE_TRANSACTION;
             }
-
+#endif
             OIC_LOG(INFO, TAG, "Exiting SecurePortDiscoveryHandler.");
         }
 
@@ -693,12 +800,12 @@ static OCStackApplicationResult DeviceDiscoveryHandler(void *ctx, OCDoHandle UNU
 
                 //If this is owend device discovery we have to filter out the responses.
                 DiscoveryInfo* pDInfo = (DiscoveryInfo*)ctx;
-                OCProvisionDev_t **ppDevicesList = pDInfo->ppDevicesList;
+                OCProvisionDev_t **ppDevicesList = &pDInfo->pCandidateList;
 
                 // Get my device ID from doxm resource
                 OicUuid_t myId;
                 memset(&myId, 0, sizeof(myId));
-                OCStackResult res = GetDoxmDevOwnerId(&myId);
+                OCStackResult res = GetDoxmDeviceID(&myId);
                 if(OC_STACK_OK != res)
                 {
                     OIC_LOG(ERROR, TAG, "Error while getting my device ID.");
@@ -715,16 +822,16 @@ static OCStackApplicationResult DeviceDiscoveryHandler(void *ctx, OCDoHandle UNU
                     return OC_STACK_KEEP_TRANSACTION;
                 }
 
-                res = GetDoxmDeviceID(&myId);
-                if(OC_STACK_OK != res)
+                //if targetId and discovered deviceID are different, discard it
+                if ((pDInfo->isSingleDiscovery) &&
+                    (0 != memcmp(&ptrDoxm->deviceID.id, &pDInfo->targetId->id, sizeof(pDInfo->targetId->id))) )
                 {
-                    OIC_LOG(ERROR, TAG, "Error while getting my UUID.");
+                    OIC_LOG(DEBUG, TAG, "Discovered device is not target device");
                     DeleteDoxmBinData(ptrDoxm);
                     return OC_STACK_KEEP_TRANSACTION;
                 }
-                //if this is owned discovery and this is PT's reply, discard it
-                if(((pDInfo->isSingleDiscovery) || (pDInfo->isOwnedDiscovery)) &&
-                        (0 == memcmp(&ptrDoxm->deviceID.id, &myId.id, sizeof(myId.id))) )
+                //If self reply, discard it
+                if (0 == memcmp(&ptrDoxm->deviceID.id, &myId.id, sizeof(myId.id)))
                 {
                     OIC_LOG(DEBUG, TAG, "discarding provision tool's reply");
                     DeleteDoxmBinData(ptrDoxm);
@@ -739,7 +846,6 @@ static OCStackApplicationResult DeviceDiscoveryHandler(void *ctx, OCDoHandle UNU
                     DeleteDoxmBinData(ptrDoxm);
                     return OC_STACK_KEEP_TRANSACTION;
                 }
-
                 res = SecurePortDiscovery(pDInfo, clientResponse);
                 if(OC_STACK_OK != res)
                 {
@@ -749,12 +855,7 @@ static OCStackApplicationResult DeviceDiscoveryHandler(void *ctx, OCDoHandle UNU
                 }
 
                 OIC_LOG(INFO, TAG, "Exiting ProvisionDiscoveryHandler.");
-                if(pDInfo->isSingleDiscovery)
-                {
-                    return OC_STACK_DELETE_TRANSACTION;
-                }
             }
-
             return  OC_STACK_KEEP_TRANSACTION;
         }
     }
@@ -767,29 +868,62 @@ static OCStackApplicationResult DeviceDiscoveryHandler(void *ctx, OCDoHandle UNU
     return  OC_STACK_DELETE_TRANSACTION;
 }
 
+static void DeviceDiscoveryDeleteHandler(void *ctx)
+{
+    OIC_LOG(DEBUG, TAG, "IN DeviceDiscoveryDeleteHandler");
+    if (NULL == ctx)
+    {
+        OIC_LOG(WARNING, TAG, "Not found context in DeviceDiscoveryDeleteHandler");
+        return;
+    }
+
+    DiscoveryInfo* pDInfo = (DiscoveryInfo*)ctx;
+    if (NULL != pDInfo->pCandidateList)
+    {
+        OCProvisionDev_t *pDev = NULL;
+        LL_FOREACH(pDInfo->pCandidateList, pDev)
+        {
+            OIC_LOG_V(DEBUG, TAG, "OCCancel - %s : %d",
+                            pDev->endpoint.addr, pDev->endpoint.port);
+            if(OC_STACK_OK !=  OCCancel(pDev->handle,OC_HIGH_QOS,NULL,0))
+            {
+                OIC_LOG(ERROR, TAG, "Failed to remove registered callback");
+            }
+        }
+        PMDeleteDeviceList(pDInfo->pCandidateList);
+    }
+    OIC_LOG(DEBUG, TAG, "OUT DeviceDiscoveryDeleteHandler");
+}
 
 /**
- * Discover owned/unowned devices in the specified endpoint.
- * It will return when found one or more device even though timeout is not exceeded
+ * Discover owned/unowned device in the specified endpoint/deviceID.
+ * It will return the found device even though timeout is not exceeded.
  *
  * @param[in] waittime           Timeout in seconds
- * @param[in] host               address of target endpoint
- * @param[in] connType           connectivity type of endpoint
- * @param[out] ppDevicesList      List of OCProvisionDev_t
+ * @param[in] deviceID           deviceID of target device.
+ * @param[out] ppFoundDevice     OCProvisionDev_t of found device
  *
- * @return OC_STACK_OK on success otherwise error.
+ * @return OC_STACK_OK on success otherwise error.\n
+ *         OC_STACK_INVALID_PARAM when deviceID is NULL or ppFoundDevice is not initailized.
  */
-OCStackResult PMSingleDeviceDiscovery(unsigned short waittime, const char* host,
-                                 OCConnectivityType connType, OCProvisionDev_t **ppDevicesList)
+OCStackResult PMSingleDeviceDiscovery(unsigned short waittime, const OicUuid_t* deviceID,
+                                 OCProvisionDev_t **ppFoundDevice)
 {
     OIC_LOG(DEBUG, TAG, "IN PMSingleDeviceDiscovery");
 
-    if (NULL != *ppDevicesList)
+    if (NULL != *ppFoundDevice)
     {
         OIC_LOG(ERROR, TAG, "List is not null can cause memory leak");
         return OC_STACK_INVALID_PARAM;
     }
 
+    if (NULL == deviceID)
+    {
+        OIC_LOG(ERROR, TAG, "Invalid device ID");
+        return OC_STACK_INVALID_PARAM;
+    }
+
+
     DiscoveryInfo *pDInfo = OICCalloc(1, sizeof(DiscoveryInfo));
     if(NULL == pDInfo)
     {
@@ -797,27 +931,26 @@ OCStackResult PMSingleDeviceDiscovery(unsigned short waittime, const char* host,
         return OC_STACK_NO_MEMORY;
     }
 
-    pDInfo->ppDevicesList = ppDevicesList;
+    pDInfo->ppDevicesList = ppFoundDevice;
+    pDInfo->pCandidateList = NULL;
     pDInfo->isOwnedDiscovery = false;
     pDInfo->isSingleDiscovery = true;
     pDInfo->isFound = false;
+    pDInfo->targetId = deviceID;
 
     OCCallbackData cbData;
     cbData.cb = &DeviceDiscoveryHandler;
     cbData.context = (void *)pDInfo;
-    cbData.cd = NULL;
+    cbData.cd = &DeviceDiscoveryDeleteHandler;
+
     OCStackResult res = OC_STACK_ERROR;
 
     char query[MAX_URI_LENGTH + MAX_QUERY_LENGTH + 1] = { '\0' };
-    if(host == NULL)
-    {
-        host = "";
-    }
-    snprintf(query, MAX_URI_LENGTH + MAX_QUERY_LENGTH + 1, "%s/oic/sec/doxm", host);
+    snprintf(query, MAX_URI_LENGTH + MAX_QUERY_LENGTH + 1, "/oic/sec/doxm");
 
     OCDoHandle handle = NULL;
     res = OCDoResource(&handle, OC_REST_DISCOVER, query, 0, 0,
-                                     connType, OC_HIGH_QOS, &cbData, NULL, 0);
+                                     CT_DEFAULT, OC_HIGH_QOS, &cbData, NULL, 0);
     if (res != OC_STACK_OK)
     {
         OIC_LOG(ERROR, TAG, "OCStack resource error");
@@ -828,7 +961,7 @@ OCStackResult PMSingleDeviceDiscovery(unsigned short waittime, const char* host,
     //Waiting for each response.
     res = OC_STACK_OK;
     uint64_t startTime = OICGetCurrentTime(TIME_IN_MS);
-    while (OC_STACK_OK == res && pDInfo->isFound == false)
+    while (OC_STACK_OK == res && !pDInfo->isFound)
     {
         uint64_t currTime = OICGetCurrentTime(TIME_IN_MS);
 
@@ -852,23 +985,22 @@ OCStackResult PMSingleDeviceDiscovery(unsigned short waittime, const char* host,
         return res;
     }
 
-    if(*ppDevicesList == NULL)
-    {
-        res = OCCancel(handle,OC_HIGH_QOS,NULL,0);
-    }
-
+    res = OCCancel(handle,OC_HIGH_QOS,NULL,0);
     if (OC_STACK_OK != res)
     {
         OIC_LOG(ERROR, TAG, "Failed to remove registered callback");
         OICFree(pDInfo);
         return res;
     }
-    OIC_LOG(DEBUG, TAG, "OUT PMSingleDeviceDiscovery");
+    if (!pDInfo->isFound)
+    {
+        res = OC_STACK_TIMEOUT;
+    }
     OICFree(pDInfo);
+    OIC_LOG(DEBUG, TAG, "OUT PMSingleDeviceDiscovery");
     return res;
 }
 
-
 /**
  * Discover owned/unowned devices in the same IP subnet. .
  *
@@ -899,13 +1031,15 @@ OCStackResult PMDeviceDiscovery(unsigned short waittime, bool isOwned, OCProvisi
     }
 
     pDInfo->ppDevicesList = ppDevicesList;
+    pDInfo->pCandidateList = NULL;
     pDInfo->isOwnedDiscovery = isOwned;
     pDInfo->isSingleDiscovery = false;
+    pDInfo->targetId = NULL;
 
     OCCallbackData cbData;
     cbData.cb = &DeviceDiscoveryHandler;
     cbData.context = (void *)pDInfo;
-    cbData.cd = NULL;
+    cbData.cd = &DeviceDiscoveryDeleteHandler;
     OCStackResult res = OC_STACK_ERROR;
 
     const char* query = isOwned ? DOXM_OWNED_TRUE_MULTICAST_QUERY :
@@ -946,6 +1080,354 @@ OCStackResult PMDeviceDiscovery(unsigned short waittime, bool isOwned, OCProvisi
     return res;
 }
 
+OCStackResult PMSingleDeviceDiscoveryInUnicast(unsigned short waittime, const OicUuid_t* deviceID,
+                                 const char* hostAddress, OCConnectivityType connType,
+                                 OCProvisionDev_t **ppFoundDevice)
+{
+    OIC_LOG(DEBUG, TAG, "IN PMSingleDeviceDiscoveryInUnicast");
+
+    if (NULL != *ppFoundDevice)
+    {
+        OIC_LOG(ERROR, TAG, "List is not null can cause memory leak");
+        return OC_STACK_INVALID_PARAM;
+    }
+
+    if (NULL == deviceID)
+    {
+        OIC_LOG(ERROR, TAG, "Invalid device ID");
+        return OC_STACK_INVALID_PARAM;
+    }
+
+    DiscoveryInfo *pDInfo = (DiscoveryInfo*)OICCalloc(1, sizeof(DiscoveryInfo));
+    if (NULL == pDInfo)
+    {
+        OIC_LOG(ERROR, TAG, "PMSingleDeviceDiscoveryInUnicast : Memory allocation failed.");
+        return OC_STACK_NO_MEMORY;
+    }
+
+    pDInfo->ppDevicesList = ppFoundDevice;
+    pDInfo->pCandidateList = NULL;
+    pDInfo->isOwnedDiscovery = false;
+    pDInfo->isSingleDiscovery = true;
+    pDInfo->isFound = false;
+    pDInfo->targetId = deviceID;
+
+    OCCallbackData cbData;
+    cbData.cb = &DeviceDiscoveryHandler;
+    cbData.context = (void *)pDInfo;
+    cbData.cd = &DeviceDiscoveryDeleteHandler;
+
+    OCStackResult res = OC_STACK_ERROR;
+
+    char query[MAX_URI_LENGTH + MAX_QUERY_LENGTH + 1] = { '\0' };
+    if (hostAddress == NULL)
+    {
+        hostAddress = "";
+    }
+    snprintf(query, MAX_URI_LENGTH + MAX_QUERY_LENGTH + 1, "%s/oic/sec/doxm", hostAddress);
+    connType = connType & CT_MASK_ADAPTER;
+
+    OCDoHandle handle = NULL;
+    res = OCDoResource(&handle, OC_REST_DISCOVER, query, 0, 0,
+            connType, OC_HIGH_QOS, &cbData, NULL, 0);
+
+    if (res != OC_STACK_OK)
+    {
+        OIC_LOG(ERROR, TAG, "OCStack resource error");
+        OICFree(pDInfo);
+        pDInfo = NULL;
+        return res;
+    }
+
+    res = OC_STACK_OK;
+    uint64_t startTime = OICGetCurrentTime(TIME_IN_MS);
+    while (OC_STACK_OK == res && !pDInfo->isFound)
+    {
+        uint64_t currTime = OICGetCurrentTime(TIME_IN_MS);
+
+        long elapsed = (long)((currTime - startTime) / MS_PER_SEC);
+        if (elapsed > waittime)
+        {
+            break;
+        }
+        res = OCProcess();
+    }
+
+    if (OC_STACK_OK != res)
+    {
+        OIC_LOG (ERROR, TAG, "Failed to wait response for secure discovery.");
+        OICFree(pDInfo);
+        pDInfo = NULL;
+        OCStackResult resCancel = OCCancel(handle, OC_HIGH_QOS, NULL, 0);
+        if (OC_STACK_OK !=  resCancel)
+        {
+            OIC_LOG(ERROR, TAG, "Failed to remove registered callback");
+        }
+        return res;
+    }
+
+    res = OCCancel(handle, OC_HIGH_QOS, NULL, 0);
+    if (OC_STACK_OK != res)
+    {
+        OIC_LOG(ERROR, TAG, "Failed to remove registered callback");
+        OICFree(pDInfo);
+        pDInfo = NULL;
+        return res;
+    }
+    OIC_LOG(DEBUG, TAG, "OUT PMSingleDeviceDiscoveryInUnicast");
+
+    if (!pDInfo->isFound)
+    {
+        res = OC_STACK_TIMEOUT;
+    }
+
+    OICFree(pDInfo);
+    pDInfo = NULL;
+    return res;
+}
+
+#ifdef MULTIPLE_OWNER
+static OCStackApplicationResult MOTDeviceDiscoveryHandler(void *ctx, OCDoHandle UNUSED,
+                                OCClientResponse *clientResponse)
+{
+    if (ctx == NULL)
+    {
+        OIC_LOG(ERROR, TAG, "Lost List of device information");
+        return OC_STACK_KEEP_TRANSACTION;
+    }
+    (void)UNUSED;
+    if (clientResponse)
+    {
+        if  (NULL == clientResponse->payload)
+        {
+            OIC_LOG(INFO, TAG, "Skipping Null payload");
+            return OC_STACK_KEEP_TRANSACTION;
+        }
+        if (OC_STACK_OK != clientResponse->result)
+        {
+            OIC_LOG(INFO, TAG, "Error in response");
+            return OC_STACK_KEEP_TRANSACTION;
+        }
+        else
+        {
+            if (PAYLOAD_TYPE_SECURITY != clientResponse->payload->type)
+            {
+                OIC_LOG(INFO, TAG, "Unknown payload type");
+                return OC_STACK_KEEP_TRANSACTION;
+            }
+
+            OicSecDoxm_t *ptrDoxm = NULL;
+            uint8_t *payload = ((OCSecurityPayload*)clientResponse->payload)->securityData;
+            size_t size = ((OCSecurityPayload*)clientResponse->payload)->payloadSize;
+
+            OCStackResult res = CBORPayloadToDoxm(payload, size, &ptrDoxm);
+            if ((NULL == ptrDoxm) || (OC_STACK_OK != res))
+            {
+                OIC_LOG(INFO, TAG, "Ignoring malformed CBOR");
+                return OC_STACK_KEEP_TRANSACTION;
+            }
+            else
+            {
+                OIC_LOG(DEBUG, TAG, "Successfully converted doxm cbor to bin.");
+
+                //If this is owend device discovery we have to filter out the responses.
+                DiscoveryInfo* pDInfo = (DiscoveryInfo*)ctx;
+                OCProvisionDev_t **ppDevicesList = &pDInfo->pCandidateList;
+
+                // Get my device ID from doxm resource
+                OicUuid_t myId;
+                memset(&myId, 0, sizeof(myId));
+                OCStackResult res = GetDoxmDevOwnerId(&myId);
+                if(OC_STACK_OK != res)
+                {
+                    OIC_LOG(ERROR, TAG, "Error while getting my device ID.");
+                    DeleteDoxmBinData(ptrDoxm);
+                    return OC_STACK_KEEP_TRANSACTION;
+                }
+
+                res = GetDoxmDeviceID(&myId);
+                if(OC_STACK_OK != res)
+                {
+                    OIC_LOG(ERROR, TAG, "Error while getting my UUID.");
+                    DeleteDoxmBinData(ptrDoxm);
+                    return OC_STACK_KEEP_TRANSACTION;
+                }
+                //if this is owned discovery and this is PT's reply, discard it
+                if((pDInfo->isOwnedDiscovery) &&
+                        (0 == memcmp(&ptrDoxm->deviceID.id, &myId.id, sizeof(myId.id))) )
+                {
+                    OIC_LOG(DEBUG, TAG, "discarding provision tool's reply");
+                    DeleteDoxmBinData(ptrDoxm);
+                    return OC_STACK_KEEP_TRANSACTION;
+                }
+
+                if(pDInfo->isOwnedDiscovery)
+                {
+                    OicSecSubOwner_t* subOwner = NULL;
+                    LL_FOREACH(ptrDoxm->subOwners, subOwner)
+                    {
+                        if(memcmp(myId.id, subOwner->uuid.id, sizeof(myId.id)) == 0)
+                        {
+                            break;
+                        }
+                    }
+
+                    if(subOwner)
+                    {
+                        res = AddDevice(ppDevicesList, &clientResponse->devAddr,
+                                clientResponse->connType, ptrDoxm);
+                        if (OC_STACK_OK != res)
+                        {
+                            OIC_LOG(ERROR, TAG, "Error while adding data to linkedlist.");
+                            DeleteDoxmBinData(ptrDoxm);
+                            return OC_STACK_KEEP_TRANSACTION;
+                        }
+
+                        res = SecurePortDiscovery(pDInfo, clientResponse);
+                        if(OC_STACK_OK != res)
+                        {
+                            OIC_LOG(ERROR, TAG, "Failed to SecurePortDiscovery");
+                            DeleteDoxmBinData(ptrDoxm);
+                            return OC_STACK_KEEP_TRANSACTION;
+                        }
+                    }
+                    else
+                    {
+                        OIC_LOG(ERROR, TAG, "discarding device's reply, because not a SubOwner.");
+                        DeleteDoxmBinData(ptrDoxm);
+                        return OC_STACK_KEEP_TRANSACTION;
+                    }
+                }
+                else
+                {
+                    if(ptrDoxm->mom && OIC_MULTIPLE_OWNER_DISABLE != ptrDoxm->mom->mode)
+                    {
+                        res = AddDevice(ppDevicesList, &clientResponse->devAddr,
+                                clientResponse->connType, ptrDoxm);
+                        if (OC_STACK_OK != res)
+                        {
+                            OIC_LOG(ERROR, TAG, "Error while adding data to linkedlist.");
+                            DeleteDoxmBinData(ptrDoxm);
+                            return OC_STACK_KEEP_TRANSACTION;
+                        }
+
+                        res = SecurePortDiscovery(pDInfo, clientResponse);
+                        if(OC_STACK_OK != res)
+                        {
+                            OIC_LOG(ERROR, TAG, "Failed to SecurePortDiscovery");
+                            DeleteDoxmBinData(ptrDoxm);
+                            return OC_STACK_KEEP_TRANSACTION;
+                        }
+                    }
+                    else
+                    {
+                        OIC_LOG(ERROR, TAG, "discarding mom disabled device's reply");
+                        DeleteDoxmBinData(ptrDoxm);
+                        return OC_STACK_KEEP_TRANSACTION;
+                    }
+                }
+
+                OIC_LOG(INFO, TAG, "Exiting ProvisionDiscoveryHandler.");
+            }
+
+            return  OC_STACK_KEEP_TRANSACTION;
+        }
+    }
+    else
+    {
+        OIC_LOG(INFO, TAG, "Skiping Null response");
+        return OC_STACK_KEEP_TRANSACTION;
+    }
+
+    return  OC_STACK_DELETE_TRANSACTION;
+}
+
+
+/**
+ * Discover multiple OTM enabled devices in the same IP subnet.
+ *
+ * @param[in] waittime      Timeout in seconds.
+ * @param[in] ppDevicesList        List of OCProvisionDev_t.
+ *
+ * @return OC_STACK_OK on success otherwise error.
+ */
+OCStackResult PMMultipleOwnerDeviceDiscovery(unsigned short waittime, bool isMultipleOwned, OCProvisionDev_t **ppDevicesList)
+{
+    OIC_LOG(DEBUG, TAG, "IN PMMultipleOwnerEnabledDeviceDiscovery");
+
+    if (NULL != *ppDevicesList)
+    {
+        OIC_LOG(ERROR, TAG, "List is not null can cause memory leak");
+        return OC_STACK_INVALID_PARAM;
+    }
+
+    char DOXM_MOM_ENABLE_MULTICAST_QUERY[MAX_URI_LENGTH + MAX_QUERY_LENGTH] = {0};
+    char DOXM_MULTIPLE_OWNED_MULTICAST_QUERY[MAX_URI_LENGTH + MAX_QUERY_LENGTH] = {0};
+    snprintf(DOXM_MOM_ENABLE_MULTICAST_QUERY, sizeof(DOXM_MOM_ENABLE_MULTICAST_QUERY),
+             "%s?%s=%d&%s=TRUE",
+             OIC_RSRC_DOXM_URI, OIC_JSON_MOM_NAME, OIC_MULTIPLE_OWNER_DISABLE,
+             OIC_JSON_OWNED_NAME);
+    snprintf(DOXM_MULTIPLE_OWNED_MULTICAST_QUERY, sizeof(DOXM_MOM_ENABLE_MULTICAST_QUERY),
+             "%s?%s=TRUE",
+             OIC_RSRC_DOXM_URI, OIC_JSON_OWNED_NAME);
+
+    DiscoveryInfo *pDInfo = OICCalloc(1, sizeof(DiscoveryInfo));
+    if(NULL == pDInfo)
+    {
+        OIC_LOG(ERROR, TAG, "PMDeviceDiscovery : Memory allocation failed.");
+        return OC_STACK_NO_MEMORY;
+    }
+
+    pDInfo->ppDevicesList = ppDevicesList;
+    pDInfo->pCandidateList = NULL;
+    pDInfo->isOwnedDiscovery = isMultipleOwned;
+
+    OCCallbackData cbData;
+    cbData.cb = &MOTDeviceDiscoveryHandler;
+    cbData.context = (void *)pDInfo;
+    cbData.cd = NULL;
+    OCStackResult res = OC_STACK_ERROR;
+
+    const char* query = isMultipleOwned ? DOXM_MULTIPLE_OWNED_MULTICAST_QUERY :
+                                          DOXM_MOM_ENABLE_MULTICAST_QUERY;
+
+    OCDoHandle handle = NULL;
+    res = OCDoResource(&handle, OC_REST_DISCOVER, query, 0, 0,
+                                     CT_DEFAULT, OC_HIGH_QOS, &cbData, NULL, 0);
+    if (res != OC_STACK_OK)
+    {
+        OIC_LOG(ERROR, TAG, "OCStack resource error");
+        OICFree(pDInfo);
+        return res;
+    }
+
+    //Waiting for each response.
+    res = PMTimeout(waittime, true);
+    if(OC_STACK_OK != res)
+    {
+        OIC_LOG(ERROR, TAG, "Failed to wait response for secure discovery.");
+        OICFree(pDInfo);
+        OCStackResult resCancel = OCCancel(handle, OC_HIGH_QOS, NULL, 0);
+        if(OC_STACK_OK !=  resCancel)
+        {
+            OIC_LOG(ERROR, TAG, "Failed to remove registered callback");
+        }
+        return res;
+    }
+    res = OCCancel(handle,OC_HIGH_QOS,NULL,0);
+    if (OC_STACK_OK != res)
+    {
+        OIC_LOG(ERROR, TAG, "Failed to remove registered callback");
+        OICFree(pDInfo);
+        return res;
+    }
+    OIC_LOG(DEBUG, TAG, "OUT PMMultipleOwnerEnabledDeviceDiscovery");
+    OICFree(pDInfo);
+    return res;
+}
+
+#endif //MULTIPLE_OWNER
+
 static OCStackResult SecurePortDiscovery(DiscoveryInfo* discoveryInfo,
                                          const OCClientResponse *clientResponse)
 {
@@ -955,11 +1437,20 @@ static OCStackResult SecurePortDiscovery(DiscoveryInfo* discoveryInfo,
     {
         return OC_STACK_INVALID_PARAM;
     }
+
+    OCProvisionDev_t *pDev = GetDevice(&discoveryInfo->pCandidateList,
+                        clientResponse->devAddr.addr, clientResponse->devAddr.port);
+    if(NULL == pDev)
+    {
+        OIC_LOG(ERROR, TAG, "SecurePortDiscovery : Failed to get device");
+        return OC_STACK_ERROR;
+    }
+
     //Try to the unicast discovery to getting secure port
     char query[MAX_URI_LENGTH+MAX_QUERY_LENGTH+1] = {0};
     if(!PMGenerateQuery(false,
-                        clientResponse->devAddr.addr, clientResponse->devAddr.port,
-                        clientResponse->connType,
+                        pDev->endpoint.addr, pDev->endpoint.port,
+                        pDev->connType,
                         query, sizeof(query), OC_RSRVD_WELL_KNOWN_URI))
     {
         OIC_LOG(ERROR, TAG, "SecurePortDiscovery : Failed to generate query");
@@ -967,12 +1458,20 @@ static OCStackResult SecurePortDiscovery(DiscoveryInfo* discoveryInfo,
     }
     OIC_LOG_V(DEBUG, TAG, "Query=%s", query);
 
+    // Set filter query with rt=oic.r.doxm
+    const char RES_DOXM_QUERY_FMT[] = "%s?%s=%s";
+    char uri[MAX_URI_LENGTH + MAX_QUERY_LENGTH] = {0};
+    snprintf(uri, sizeof(uri), RES_DOXM_QUERY_FMT, query,
+            OC_RSRVD_RESOURCE_TYPE, OIC_RSRC_TYPE_SEC_DOXM);
+
+    OIC_LOG_V(DEBUG, TAG, "URI=%s", uri);
+
     OCCallbackData cbData;
     cbData.cb = &SecurePortDiscoveryHandler;
     cbData.context = (void*)discoveryInfo;
     cbData.cd = NULL;
-    OCStackResult ret = OCDoResource(NULL, OC_REST_DISCOVER, query, 0, 0,
-            clientResponse->connType, OC_HIGH_QOS, &cbData, NULL, 0);
+    OCStackResult ret = OCDoResource(&pDev->handle, OC_REST_DISCOVER, uri, 0, 0,
+            pDev->connType, OC_HIGH_QOS, &cbData, NULL, 0);
     if(OC_STACK_OK != ret)
     {
         OIC_LOG(ERROR, TAG, "Failed to Secure Port Discovery");
@@ -988,6 +1487,11 @@ static OCStackResult SecurePortDiscovery(DiscoveryInfo* discoveryInfo,
     return ret;
 }
 
+/*
+ * Since security version discovery does not used anymore, disable security version discovery.
+ * Need to discussion to removing all version discovery related codes.
+ */
+#if 0
 static OCStackResult SecurityVersionDiscovery(DiscoveryInfo* discoveryInfo,
                                               const OCClientResponse *clientResponse)
 {
@@ -1030,6 +1534,7 @@ static OCStackResult SecurityVersionDiscovery(DiscoveryInfo* discoveryInfo,
 
     return ret;
 }
+#endif
 
 /**
  * Function to print OCProvisionDev_t for debug purpose.