Set ACL Rowner to PT's Device ID in SRPProvisionACL
[platform/upstream/iotivity.git] / resource / csdk / security / provisioning / src / secureresourceprovider.c
index 1a2a65a..3a8f242 100644 (file)
  * limitations under the License.
  *
  * *****************************************************************/
+#include "iotivity_config.h"
 #include <stdio.h>
 #include <string.h>
 #include <stdint.h>
+#ifdef HAVE_UNISTD_H
 #include <unistd.h>
+#endif
 
 #include "ocprovisioningmanager.h"
 #include "secureresourceprovider.h"
@@ -42,7 +45,7 @@
 #include "utlist.h"
 #include "ocpayload.h"
 
-#ifdef __WITH_X509__
+#ifdef __WITH_DTLS__
 #include "crlresource.h"
 #endif // WITH_X509__
 
@@ -133,6 +136,7 @@ struct UnlinkData {
 
 //Example of DELETE cred request -> coaps://0.0.0.0:5684/oic/sec/cred?sub=(BASE64 ENCODED UUID)
 const char * SRP_FORM_DELETE_CREDENTIAL = "coaps://[%s]:%d%s?%s=%s";
+const char * SRP_FORM_DELETE_CREDENTIAL_TCP = "coaps+tcp://[%s]:%d%s?%s=%s";
 
 // Structure to carry remove APIs data to callback.
 typedef struct RemoveData RemoveData_t;
@@ -197,9 +201,9 @@ static OCStackApplicationResult provisionCredentialCB2(void *ctx, OCDoHandle UNU
     OIC_LOG(INFO, TAG, "provisionCredentialCB2 called");
     if (clientResponse)
     {
-        if(OC_STACK_RESOURCE_CREATED == clientResponse->result)
+        if(OC_STACK_RESOURCE_CHANGED == clientResponse->result)
         {
-            registerResultForCredProvisioning(credData, OC_STACK_RESOURCE_CREATED, 2);
+            registerResultForCredProvisioning(credData, OC_STACK_RESOURCE_CHANGED, 2);
             OCStackResult res =  PDMLinkDevices(&credData->deviceInfo1->doxm->deviceID,
                     &credData->deviceInfo2->doxm->deviceID);
             if (OC_STACK_OK != res)
@@ -249,10 +253,10 @@ static OCStackApplicationResult provisionCredentialCB1(void *ctx, OCDoHandle UNU
     const OCProvisionResultCB resultCallback = credData->resultCallback;
     if (clientResponse)
     {
-        if (OC_STACK_RESOURCE_CREATED == clientResponse->result)
+        if (OC_STACK_RESOURCE_CHANGED == clientResponse->result)
         {
             // send credentials to second device
-            registerResultForCredProvisioning(credData, OC_STACK_RESOURCE_CREATED,1);
+            registerResultForCredProvisioning(credData, OC_STACK_RESOURCE_CHANGED,1);
             OCStackResult res = provisionCredentials(credInfo, deviceInfo, credData,
                     provisionCredentialCB2);
             DeleteCredList(credInfo);
@@ -356,7 +360,7 @@ static OCStackResult provisionCredentials(const OicSecCred_t *cred,
     return OC_STACK_OK;
 }
 
-#ifdef __WITH_X509__
+#if defined(__WITH_DTLS__) || defined(__WITH_TLS__)
 /**
  * Structure to carry certificate data to callback.
  */
@@ -372,19 +376,6 @@ struct CertificateData
 };
 
 /**
- * Structure to carry CRL provision API data to callback.
- */
-typedef struct CRLData CRLData_t;
-struct CRLData
-{
-    void *ctx;                                  /**< Pointer to user context.**/
-    const OCProvisionDev_t *deviceInfo;         /**< Pointer to PMDevInfo_t.**/
-    OCProvisionResultCB resultCallback;         /**< Pointer to result callback.**/
-    OCProvisionResult_t *resArr;                /**< Result array.**/
-    int numOfResults;                           /**< Number of results in result array.**/
-};
-
-/**
  * Internal function to update result in result array.
  */
 static void registerResultForCertProvisioning(CertData_t *certData,
@@ -399,142 +390,6 @@ static void registerResultForCertProvisioning(CertData_t *certData,
 }
 
 /**
- * Internal Function to store results in result array during ACL provisioning.
- */
-static void registerResultForCRLProvisioning(CRLData_t *crlData,
-                                             OCStackResult stackresult)
-{
-   OIC_LOG_V(INFO, TAG, "Inside registerResultForCRLProvisioning crlData->numOfResults is %d\n",
-                       crlData->numOfResults);
-   memcpy(crlData->resArr[(crlData->numOfResults)].deviceId.id,
-          crlData->deviceInfo->doxm->deviceID.id, UUID_LENGTH);
-   crlData->resArr[(crlData->numOfResults)].res = stackresult;
-   ++(crlData->numOfResults);
-}
-
-
-/**
- * Callback handler of SRPProvisionCRL.
- *
- * @param[in] ctx             ctx value passed to callback from calling function.
- * @param[in] UNUSED          handle to an invocation
- * @param[in] clientResponse  Response from queries to remote servers.
- * @return  OC_STACK_DELETE_TRANSACTION to delete the transaction
- *          and  OC_STACK_KEEP_TRANSACTION to keep it.
- */
-static OCStackApplicationResult SRPProvisionCRLCB(void *ctx, OCDoHandle UNUSED,
-                                                  OCClientResponse *clientResponse)
-{
-    OIC_LOG_V(INFO, TAG, "Inside SRPProvisionCRLCB.");
-    (void)UNUSED;
-    VERIFY_NON_NULL(TAG, ctx, ERROR, OC_STACK_DELETE_TRANSACTION);
-    CRLData_t *crlData = (CRLData_t*)ctx;
-    OCProvisionResultCB resultCallback = crlData->resultCallback;
-
-    if (clientResponse)
-    {
-        if(OC_STACK_RESOURCE_CREATED == clientResponse->result)
-        {
-            registerResultForCRLProvisioning(crlData, OC_STACK_RESOURCE_CREATED);
-            ((OCProvisionResultCB)(resultCallback))(crlData->ctx, crlData->numOfResults,
-                                                    crlData->resArr,
-                                                    false);
-             OICFree(crlData->resArr);
-             OICFree(crlData);
-             return OC_STACK_DELETE_TRANSACTION;
-        }
-    }
-    registerResultForCRLProvisioning(crlData, OC_STACK_ERROR);
-    ((OCProvisionResultCB)(resultCallback))(crlData->ctx, crlData->numOfResults,
-                                            crlData->resArr,
-                                            true);
-    OIC_LOG_V(ERROR, TAG, "SRPProvisionCRLCB received Null clientResponse");
-    OICFree(crlData->resArr);
-    OICFree(crlData);
-    return OC_STACK_DELETE_TRANSACTION;
-}
-
-OCStackResult SRPProvisionCRL(void *ctx, const OCProvisionDev_t *selectedDeviceInfo,
-        OicSecCrl_t *crl, OCProvisionResultCB resultCallback)
-{
-    VERIFY_NON_NULL(TAG, selectedDeviceInfo, ERROR,  OC_STACK_INVALID_PARAM);
-    VERIFY_NON_NULL(TAG, crl, ERROR,  OC_STACK_INVALID_PARAM);
-    VERIFY_NON_NULL(TAG, resultCallback, ERROR,  OC_STACK_INVALID_CALLBACK);
-
-    OCSecurityPayload* secPayload = (OCSecurityPayload*)OICCalloc(1, sizeof(OCSecurityPayload));
-    if (!secPayload)
-    {
-        OIC_LOG(ERROR, TAG, "Failed to memory allocation");
-        return OC_STACK_NO_MEMORY;
-    }
-
-    secPayload->base.type = PAYLOAD_TYPE_SECURITY;
-    OCStackResult res = CrlToCBORPayload(crl, &secPayload->securityData, &secPayload->payloadSize);
-    if((OC_STACK_OK != res) && (NULL == secPayload->securityData))
-    {
-        OICFree(secPayload);
-        OIC_LOG(ERROR, TAG, "Failed to BinToCrlJSON");
-        return OC_STACK_NO_MEMORY;
-    }
-    OIC_LOG(DEBUG, TAG, "Created payload for CRL:");
-    OIC_LOG_BUFFER(DEBUG, TAG, secPayload->securityData, secPayload->payloadSize);
-
-    char query[MAX_URI_LENGTH + MAX_QUERY_LENGTH] = {0};
-    if(!PMGenerateQuery(true,
-                        selectedDeviceInfo->endpoint.addr,
-                        selectedDeviceInfo->securePort,
-                        selectedDeviceInfo->connType,
-                        query, sizeof(query), OIC_RSRC_CRL_URI))
-    {
-        OIC_LOG(ERROR, TAG, "DeviceDiscoveryHandler : Failed to generate query");
-        OCPayloadDestroy((OCPayload *)secPayload);
-        return OC_STACK_ERROR;
-    }
-    OIC_LOG_V(DEBUG, TAG, "Query=%s", query);
-
-    OCCallbackData cbData =  {.context=NULL, .cb=NULL, .cd=NULL};
-    cbData.cb = &SRPProvisionCRLCB;
-    CRLData_t *crlData = (CRLData_t *) OICCalloc(1, sizeof(CRLData_t));
-    if (crlData == NULL)
-    {
-        OCPayloadDestroy((OCPayload *)secPayload);
-        OIC_LOG(ERROR, TAG, "Unable to allocate memory");
-        return OC_STACK_NO_MEMORY;
-    }
-
-    crlData->deviceInfo = selectedDeviceInfo;
-    crlData->resultCallback = resultCallback;
-    crlData->numOfResults=0;
-    crlData->ctx = ctx;
-
-    crlData->resArr = (OCProvisionResult_t*)OICCalloc(1, sizeof(OCProvisionResult_t));
-    if (crlData->resArr == NULL)
-    {
-        OCPayloadDestroy((OCPayload *)secPayload);
-        OIC_LOG(ERROR, TAG, "Unable to allocate memory");
-        return OC_STACK_NO_MEMORY;
-    }
-
-    cbData.context = (void *)crlData;
-    cbData.cd = NULL;
-    OCMethod method = OC_REST_POST;
-    OCDoHandle handle = NULL;
-    OIC_LOG(DEBUG, TAG, "Sending CRL info to resource server");
-
-    OCStackResult ret = OCDoResource(&handle, method, query,
-            &selectedDeviceInfo->endpoint, (OCPayload*)secPayload,
-            selectedDeviceInfo->connType, OC_HIGH_QOS, &cbData, NULL, 0);
-
-    if (ret != OC_STACK_OK)
-    {
-        OICFree(crlData->resArr);
-        OICFree(crlData);
-    }
-
-    return ret;
-}
-
-/**
  * Internal function for handling credential generation and sending cretificate credential.
  *
  * @param[in] cred Instance of cred resource.
@@ -617,9 +472,9 @@ static OCStackApplicationResult provisionCertCB(void *ctx, OCDoHandle UNUSED,
     OIC_LOG(INFO, TAG, "provisionCertCred called");
     if (clientResponse)
     {
-        if(OC_STACK_RESOURCE_CREATED == clientResponse->result)
+        if(OC_STACK_RESOURCE_CHANGED == clientResponse->result)
         {
-            registerResultForCertProvisioning(certData, OC_STACK_RESOURCE_CREATED);
+            registerResultForCertProvisioning(certData, OC_STACK_RESOURCE_CHANGED);
             ((OCProvisionResultCB)(resultCallback))(certData->ctx, certData->numOfResults,
                                                     certData->resArr,
                                                     false);
@@ -638,7 +493,198 @@ static OCStackApplicationResult provisionCertCB(void *ctx, OCDoHandle UNUSED,
     OICFree(certData);
     return OC_STACK_DELETE_TRANSACTION;
 }
-#endif // __WITH_X509__
+
+OCStackResult SRPProvisionTrustCertChain(void *ctx, OicSecCredType_t type, uint16_t credId,
+        const OCProvisionDev_t *selectedDeviceInfo, OCProvisionResultCB resultCallback)
+{
+    OIC_LOG(INFO, TAG, "In SRPProvisionTrustCertChain");
+    VERIFY_NON_NULL(TAG, selectedDeviceInfo, ERROR,  OC_STACK_INVALID_PARAM);
+    VERIFY_NON_NULL(TAG, resultCallback, ERROR,  OC_STACK_INVALID_CALLBACK);
+    if (SIGNED_ASYMMETRIC_KEY != type || NULL == type)
+    {
+        OIC_LOG(INFO, TAG, "Invalid key type");
+        return OC_STACK_INVALID_PARAM;
+    }
+
+    OicSecCred_t *trustCertChainCred = GetCredResourceDataByCredId(credId);
+    if(NULL == trustCertChainCred)
+    {
+        OIC_LOG(ERROR, TAG, "Can not find matched Trust Cert. Chain.");
+        return OC_STACK_NO_RESOURCE;
+    }
+
+    OCSecurityPayload* secPayload = (OCSecurityPayload*)OICCalloc(1, sizeof(OCSecurityPayload));
+    if(!secPayload)
+    {
+        OIC_LOG(ERROR, TAG, "Failed to memory allocation");
+        return OC_STACK_NO_MEMORY;
+    }
+    secPayload->base.type = PAYLOAD_TYPE_SECURITY;
+    int secureFlag = 0;
+    if(OC_STACK_OK != CredToCBORPayload(trustCertChainCred, &secPayload->securityData, &secPayload->payloadSize, secureFlag))
+    {
+        OCPayloadDestroy((OCPayload *)secPayload);
+        OIC_LOG(ERROR, TAG, "Failed to CredToCBORPayload");
+        return OC_STACK_NO_MEMORY;
+    }
+    OIC_LOG(DEBUG, TAG, "Created payload for Cred:");
+    OIC_LOG_BUFFER(DEBUG, TAG, secPayload->securityData, secPayload->payloadSize);
+
+    char query[MAX_URI_LENGTH + MAX_QUERY_LENGTH] = {0};
+    if(!PMGenerateQuery(true,
+                        selectedDeviceInfo->endpoint.addr,
+                        selectedDeviceInfo->securePort,
+                        selectedDeviceInfo->connType,
+                        query, sizeof(query), OIC_RSRC_CRED_URI))
+    {
+        OIC_LOG(ERROR, TAG, "SRPProvisionTrustCertChain : Failed to generate query");
+        return OC_STACK_ERROR;
+    }
+    OIC_LOG_V(DEBUG, TAG, "Query=%s", query);
+
+    OCCallbackData cbData =  {.context=NULL, .cb=NULL, .cd=NULL};
+    cbData.cb = &provisionCertCB;
+    CertData_t *certData = (CertData_t *) OICCalloc(1, sizeof(CertData_t));
+    if (NULL == certData)
+    {
+        OIC_LOG(ERROR, TAG, "Memory allocation problem");
+        return OC_STACK_NO_MEMORY;
+    }
+    certData->deviceInfo = selectedDeviceInfo;
+    certData->resultCallback = resultCallback;
+    certData->credInfo = NULL; //credInfo not used in the response handler
+    certData->numOfResults=0;
+    certData->ctx = ctx;
+
+    int noOfRiCalls = 1;
+    certData->resArr = (OCProvisionResult_t*)OICCalloc(noOfRiCalls, sizeof(OCProvisionResult_t));
+    if (certData->resArr == NULL)
+    {
+        OICFree(certData);
+        OCPayloadDestroy((OCPayload *)secPayload);
+        OIC_LOG(ERROR, TAG, "Unable to allocate memory");
+        return OC_STACK_NO_MEMORY;
+    }
+    cbData.context = (void *)certData;
+    cbData.cd = NULL;
+    OCMethod method = OC_REST_POST;
+    OCDoHandle handle = NULL;
+    OIC_LOG(DEBUG, TAG, "Sending Cred info to resource server");
+    OCStackResult ret = OCDoResource(&handle, method, query,
+            &selectedDeviceInfo->endpoint, (OCPayload*)secPayload,
+            selectedDeviceInfo->connType, OC_HIGH_QOS, &cbData, NULL, 0);
+    if (ret != OC_STACK_OK)
+    {
+        OICFree(certData->resArr);
+        OICFree(certData);
+    }
+
+    VERIFY_SUCCESS(TAG, (OC_STACK_OK == ret), ERROR, OC_STACK_ERROR);
+    return OC_STACK_OK;
+}
+
+OCStackResult SRPSaveTrustCertChain(uint8_t *trustCertChain, size_t chainSize,
+                                            OicEncodingType_t encodingType, uint16_t *credId)
+{
+    OIC_LOG(DEBUG, TAG, "IN SRPSaveTrustCertChain");
+    VERIFY_NON_NULL(TAG, trustCertChain, ERROR,  OC_STACK_INVALID_PARAM);
+    VERIFY_NON_NULL(TAG, credId, ERROR,  OC_STACK_INVALID_PARAM);
+
+    OCStackResult res = OC_STACK_ERROR;
+
+    OicSecCred_t *cred = (OicSecCred_t *)OICCalloc(1, sizeof(*cred));
+    VERIFY_NON_NULL(TAG, cred, ERROR, OC_STACK_NO_MEMORY);
+
+    memcpy(cred->subject.id, &WILDCARD_SUBJECT_ID, WILDCARD_SUBJECT_ID_LEN);
+
+    cred->credUsage= (char *)OICCalloc(1, strlen(TRUST_CA)+1 );
+    VERIFY_NON_NULL(TAG, cred->credUsage, ERROR, OC_STACK_NO_MEMORY);
+    OICStrcpy(cred->credUsage, strlen(TRUST_CA) + 1, TRUST_CA) ;
+
+    cred->credType = SIGNED_ASYMMETRIC_KEY;
+
+    if (encodingType == OIC_ENCODING_PEM)
+    {
+        cred->optionalData.data = (uint8_t *)OICCalloc(1, chainSize + 1);
+        VERIFY_NON_NULL(TAG, cred->optionalData.data, ERROR, OC_STACK_NO_MEMORY);
+        cred->optionalData.len = chainSize + 1;
+    }
+    else
+    {
+        cred->optionalData.data = (uint8_t *)OICCalloc(1, chainSize);
+        VERIFY_NON_NULL(TAG, cred->optionalData.data, ERROR, OC_STACK_NO_MEMORY);
+        cred->optionalData.len = chainSize;
+    }
+    memcpy(cred->optionalData.data, trustCertChain, chainSize);
+    cred->optionalData.encoding = encodingType;
+
+    res = AddCredential(cred);
+    if(res != OC_STACK_OK)
+    {
+        DeleteCredList(cred);
+        return res;
+    }
+    *credId = cred->credId;
+
+    OIC_LOG(DEBUG, TAG, "OUT SRPSaveTrustCertChain");
+
+    return res;
+}
+
+
+OCStackResult SRPSaveOwnCertChain(OicSecCert_t * cert, OicSecKey_t * key, uint16_t *credId)
+{
+    OIC_LOG_V(DEBUG, TAG, "In %s", __func__);
+    VERIFY_NON_NULL(TAG, cert, ERROR,  OC_STACK_INVALID_PARAM);
+    VERIFY_NON_NULL(TAG, cert->data, ERROR,  OC_STACK_INVALID_PARAM);
+    VERIFY_NON_NULL(TAG, key, ERROR,  OC_STACK_INVALID_PARAM);
+    VERIFY_NON_NULL(TAG, key->data, ERROR,  OC_STACK_INVALID_PARAM);
+    VERIFY_NON_NULL(TAG, credId, ERROR,  OC_STACK_INVALID_PARAM);
+
+    OCStackResult res = OC_STACK_ERROR;
+
+    OicSecCred_t *cred = (OicSecCred_t *)OICCalloc(1, sizeof(*cred));
+    VERIFY_NON_NULL(TAG, cred, ERROR, OC_STACK_NO_MEMORY);
+
+    OIC_LOG_V(DEBUG, TAG, "IN: %s", __func__);
+
+    if (OC_STACK_OK != GetDoxmDeviceID(&cred->subject))
+    {
+        OIC_LOG(ERROR, TAG, "Cann't get the device id(GetDoxmDeviceID)");
+    }
+
+    cred->credUsage= (char *)OICCalloc(1, strlen(PRIMARY_CERT)+1 );
+    VERIFY_NON_NULL(TAG, cred->credUsage, ERROR, OC_STACK_NO_MEMORY);
+    OICStrcpy(cred->credUsage, strlen(PRIMARY_CERT) + 1, PRIMARY_CERT) ;
+
+    cred->credType = SIGNED_ASYMMETRIC_KEY;
+
+    OicSecCert_t *publicData = &cred->publicData;
+    publicData->data = (uint8_t *)OICCalloc(1, cert->len);
+    VERIFY_NON_NULL(TAG, publicData->data, ERROR, OC_STACK_NO_MEMORY);
+    memcpy(publicData->data, cert->data, cert->len);
+    publicData->len = cert->len;
+
+    OicSecKey_t *privateData = &cred->privateData;
+    privateData->data = (uint8_t *)OICCalloc(1, key->len);
+    VERIFY_NON_NULL(TAG, privateData->data, ERROR, OC_STACK_NO_MEMORY);
+    memcpy(privateData->data, key->data, key->len);
+    privateData->len = key->len;
+    privateData->encoding = key->encoding;
+
+    res = AddCredential(cred);
+    if(res != OC_STACK_OK)
+    {
+        DeleteCredList(cred);
+        return res;
+    }
+    *credId = cred->credId;
+
+    OIC_LOG_V(DEBUG, TAG, "Out %s", __func__);
+
+    return res;
+}
+#endif // __WITH_DTLS__ || __WITH_TLS__
 
 OCStackResult SRPProvisionCredentials(void *ctx, OicSecCredType_t type, size_t keySize,
                                       const OCProvisionDev_t *pDev1,
@@ -750,50 +796,6 @@ OCStackResult SRPProvisionCredentials(void *ctx, OicSecCredType_t type, size_t k
             VERIFY_SUCCESS(TAG, (res==OC_STACK_OK), ERROR, OC_STACK_ERROR);
             return res;
         }
-#ifdef __WITH_X509__
-        case SIGNED_ASYMMETRIC_KEY:
-        {
-            const OCProvisionDev_t *firstDevice = pDev1;
-            OicSecCred_t *cred = NULL;
-            OCStackResult res = PMGenerateCertificateCredentials(&provTooldeviceID,
-                                                                &firstDevice->doxm->deviceID,&cred);
-            VERIFY_SUCCESS(TAG, (res==OC_STACK_OK), ERROR, OC_STACK_ERROR);
-            OIC_LOG(INFO, TAG, "Certificate credentials generated successfully");
-            CertData_t *certData = (CertData_t *) OICCalloc(1, sizeof(CertData_t));
-            if (NULL == certData)
-            {
-                OICFree(cred);
-                OIC_LOG(ERROR, TAG, "Memory allocation problem");
-                return OC_STACK_NO_MEMORY;
-            }
-
-            certData->deviceInfo = firstDevice;
-            certData->ctx = ctx;
-            certData->credInfo = cred;
-            certData->numOfResults = 0;
-            certData->resultCallback = resultCallback;
-
-            certData->resArr = (OCProvisionResult_t*)OICCalloc(1, sizeof(OCProvisionResult_t));
-            if (NULL == certData->resArr)
-            {
-                DeleteCredList(cred);
-                OICFree(certData);
-                OIC_LOG(ERROR, TAG, "Memory allocation problem");
-                return OC_STACK_NO_MEMORY;
-            }
-
-            res = provisionCertCred(cred, firstDevice, certData, &provisionCertCB);
-            if (OC_STACK_OK != res)
-            {
-                OICFree(certData->resArr);
-                OICFree(certData);
-            }
-            DeleteCredList(cred);
-            OIC_LOG_V(INFO, TAG, "provisionCertCredentials returned: %d",res);
-
-            return res;
-        }
-#endif
         default:
         {
             OIC_LOG(ERROR, TAG, "Invalid option.");
@@ -837,9 +839,9 @@ static OCStackApplicationResult SRPProvisionACLCB(void *ctx, OCDoHandle UNUSED,
 
     if (clientResponse)
     {
-        if(OC_STACK_RESOURCE_CREATED == clientResponse->result)
+        if(OC_STACK_RESOURCE_CHANGED == clientResponse->result)
         {
-            registerResultForACLProvisioning(aclData, OC_STACK_RESOURCE_CREATED);
+            registerResultForACLProvisioning(aclData, OC_STACK_RESOURCE_CHANGED);
             ((OCProvisionResultCB)(resultCallback))(aclData->ctx, aclData->numOfResults,
                                                     aclData->resArr,
                                                     false);
@@ -865,6 +867,25 @@ OCStackResult SRPProvisionACL(void *ctx, const OCProvisionDev_t *selectedDeviceI
     VERIFY_NON_NULL(TAG, acl, ERROR,  OC_STACK_INVALID_PARAM);
     VERIFY_NON_NULL(TAG, resultCallback, ERROR,  OC_STACK_INVALID_CALLBACK);
 
+    // if rowneruuid is empty, set it to device ID
+    OicUuid_t emptyOwner = {.id = {0} };
+    if (memcmp(&(acl->rownerID.id), &emptyOwner, UUID_IDENTITY_SIZE) == 0)
+    {
+        OIC_LOG(DEBUG, TAG, "Set Rowner to PT's deviceId, because Rowner of ACL is empty");
+        OicUuid_t oicUuid;
+
+        if (OC_STACK_OK == GetDoxmDeviceID(&oicUuid))
+        {
+            memcpy(&(acl->rownerID.id), &oicUuid, UUID_IDENTITY_SIZE);
+        }
+        else
+        {
+            OIC_LOG(DEBUG, TAG, "Failed to set Rowner to PT's deviceID\
+                becuase it failed to retrieve Doxm DeviceID");
+            return OC_STACK_ERROR;
+        }
+    }
+
     OCSecurityPayload* secPayload = (OCSecurityPayload*)OICCalloc(1, sizeof(OCSecurityPayload));
     if(!secPayload)
     {
@@ -878,6 +899,9 @@ OCStackResult SRPProvisionACL(void *ctx, const OCProvisionDev_t *selectedDeviceI
         OIC_LOG(ERROR, TAG, "Failed to AclToCBORPayload");
         return OC_STACK_NO_MEMORY;
     }
+    OIC_LOG(DEBUG, TAG, "Created payload for ACL:");
+    OIC_LOG_BUFFER(DEBUG, TAG, secPayload->securityData, secPayload->payloadSize);
+
     char query[MAX_URI_LENGTH + MAX_QUERY_LENGTH] = {0};
     if(!PMGenerateQuery(true,
                         selectedDeviceInfo->endpoint.addr,
@@ -964,7 +988,7 @@ static OCStackApplicationResult SRPProvisionDirectPairingCB(void *ctx, OCDoHandl
 
     if (clientResponse)
     {
-        if(OC_STACK_RESOURCE_CREATED == clientResponse->result)
+        if(OC_STACK_RESOURCE_CHANGED == clientResponse->result)
         {
             registerResultForDirectPairingProvisioning(pconfData, OC_STACK_OK);
             ((OCProvisionResultCB)(resultCallback))(pconfData->ctx, pconfData->numOfResults,
@@ -1137,7 +1161,14 @@ static OCStackResult SendDeleteCredentialRequest(void* ctx,
     char reqBuf[MAX_URI_LENGTH + MAX_QUERY_LENGTH] = {0};
     int snRet = 0;
                     //coaps://0.0.0.0:5684/oic/sec/cred?subjectid=(Canonical ENCODED UUID)
-    snRet = snprintf(reqBuf, sizeof(reqBuf), SRP_FORM_DELETE_CREDENTIAL, destDev->endpoint.addr,
+    char *srpUri = SRP_FORM_DELETE_CREDENTIAL;
+#ifdef __WITH_TLS__
+    if(CA_ADAPTER_TCP == destDev->endpoint.adapter)
+    {
+        srpUri = SRP_FORM_DELETE_CREDENTIAL_TCP;
+    }
+#endif
+    snRet = snprintf(reqBuf, sizeof(reqBuf), srpUri, destDev->endpoint.addr,
                      destDev->securePort, OIC_RSRC_CRED_URI, OIC_JSON_SUBJECTID_NAME, subID);
     OICFree(subID);
     if (snRet < 0)
@@ -1172,17 +1203,75 @@ static OCStackResult SendDeleteCredentialRequest(void* ctx,
     return ret;
 }
 
-/**
- * Callback handler of unlink second device.
- *
- * @param[in] ctx             ctx value passed to callback from calling function.
- * @param[in] handle          handle to an invocation
- * @param[in] clientResponse  Response from queries to remote servers.
- * @return  OC_STACK_DELETE_TRANSACTION to delete the transaction and
- *          OC_STACK_KEEP_TRANSACTION to keep it.
- */
-static OCStackApplicationResult SRPUnlinkDevice2CB(void *unlinkCtx, OCDoHandle handle,
-        OCClientResponse *clientResponse)
+static OCStackResult SendDeleteACLRequest(void* ctx,
+                                                 OCClientResponseHandler respHandler,
+                                                 const OCProvisionDev_t* revokedDev,
+                                                 const OCProvisionDev_t* destDev)
+{
+    OIC_LOG(DEBUG, TAG, "IN SendDeleteACLRequest");
+
+    if (NULL == ctx || NULL == respHandler || NULL == revokedDev || NULL == destDev)
+    {
+        return OC_STACK_INVALID_PARAM;
+    }
+
+    char *subID = NULL;
+    OCStackResult ret = ConvertUuidToStr(&revokedDev->doxm->deviceID, &subID);
+    if(OC_STACK_OK != ret)
+    {
+        OIC_LOG(ERROR, TAG, "SendDeleteACLRequest : Failed to canonical UUID encoding");
+        return OC_STACK_ERROR;
+    }
+
+    char reqBuf[MAX_URI_LENGTH + MAX_QUERY_LENGTH] = {0};
+    int snRet = 0;
+                    //coaps://0.0.0.0:5684/oic/sec/acl?subjectuuid=(Canonical ENCODED UUID)
+    snRet = snprintf(reqBuf, sizeof(reqBuf), SRP_FORM_DELETE_CREDENTIAL, destDev->endpoint.addr,
+                     destDev->securePort, OIC_RSRC_ACL_URI, OIC_JSON_SUBJECTID_NAME, subID);
+    OICFree(subID);
+    if (snRet < 0)
+    {
+        OIC_LOG_V(ERROR, TAG, "SendDeleteACLRequest : Error (snprintf) %d\n", snRet);
+        return OC_STACK_ERROR;
+    }
+    else if ((size_t)snRet >= sizeof(reqBuf))
+    {
+        OIC_LOG_V(ERROR, TAG, "SendDeleteACLRequest : Truncated (snprintf) %d\n", snRet);
+        return OC_STACK_ERROR;
+    }
+
+    OCCallbackData cbData;
+    memset(&cbData, 0, sizeof(cbData));
+    cbData.context = ctx;
+    cbData.cb = respHandler;
+    cbData.cd = NULL;
+    OIC_LOG_V(INFO, TAG, "URI: %s",reqBuf);
+
+    OIC_LOG(DEBUG, TAG, "Sending remove ACL request to resource server");
+
+    ret = OCDoResource(NULL, OC_REST_DELETE, reqBuf,
+                                     &destDev->endpoint, NULL,
+                                     CT_ADAPTER_IP, OC_HIGH_QOS, &cbData, NULL, 0);
+    if (OC_STACK_OK != ret)
+    {
+        OIC_LOG_V(ERROR, TAG, "SendDeleteACLRequest : Error in OCDoResource %d", ret);
+    }
+    OIC_LOG(DEBUG, TAG, "OUT SendDeleteACLRequest");
+
+    return ret;
+}
+
+/**
+ * Callback handler of unlink second device.
+ *
+ * @param[in] ctx             ctx value passed to callback from calling function.
+ * @param[in] handle          handle to an invocation
+ * @param[in] clientResponse  Response from queries to remote servers.
+ * @return  OC_STACK_DELETE_TRANSACTION to delete the transaction and
+ *          OC_STACK_KEEP_TRANSACTION to keep it.
+ */
+static OCStackApplicationResult SRPUnlinkDevice2CB(void *unlinkCtx, OCDoHandle handle,
+        OCClientResponse *clientResponse)
 {
     (void) handle;
     OIC_LOG(DEBUG, TAG, "IN SRPUnlinkDevice2CB");
@@ -1445,6 +1534,34 @@ static void registerResultForRemoveDevice(RemoveData_t *removeData, OicUuid_t *p
     }
  }
 
+static void registerResultForResetDevice(RemoveData_t *removeData, OicUuid_t *pLinkedDevId,
+                                          OCStackResult stackresult, bool hasError)
+{
+    OIC_LOG_V(INFO, TAG, "Inside registerResultForResetDevice removeData->numOfResults is %zu\n",
+                         removeData->numOfResults + 1);
+    if (pLinkedDevId)
+    {
+        memcpy(removeData->removeRes[(removeData->numOfResults)].deviceId.id,
+               &pLinkedDevId->id, sizeof(pLinkedDevId->id));
+    }
+    else
+    {
+        memset(removeData->removeRes[(removeData->numOfResults)].deviceId.id,
+               0, sizeof(pLinkedDevId->id) );
+    }
+    removeData->removeRes[(removeData->numOfResults)].res = stackresult;
+    removeData->hasError = hasError;
+    ++(removeData->numOfResults);
+
+    // If we get suffcient result from linked devices, we have to call user callback and do free
+    if (removeData->sizeOfResArray == removeData->numOfResults)
+    {
+        removeData->resultCallback(removeData->ctx, removeData->numOfResults, removeData->removeRes,
+                                   removeData->hasError);
+        DeleteRemoveData_t(removeData);
+    }
+}
+
 /**
  * Callback handler of unlink first device.
  *
@@ -1524,6 +1641,171 @@ static OCStackApplicationResult SRPRemoveDeviceCB(void *delDevCtx, OCDoHandle ha
     return OC_STACK_DELETE_TRANSACTION;
 }
 
+/**
+ * Callback handler of reset device.
+ *
+ * @param[in] ctx             ctx value passed to callback from calling function.
+ * @param[in] handle          handle to an invocation
+ * @param[in] clientResponse  Response from queries to remote servers.
+ * @return  OC_STACK_DELETE_TRANSACTION to delete the transaction
+ *          and  OC_STACK_KEEP_TRANSACTION to keep it.
+ */
+static OCStackApplicationResult SRPSyncDeviceCredCB(void *delDevCtx, OCDoHandle handle,
+        OCClientResponse *clientResponse)
+{
+    //Update the delete credential into delete device context
+    //Save the deleted status in delDevCtx
+    (void)handle;
+    OIC_LOG_V(INFO, TAG, "Inside SRPSyncDeviceCredCB.");
+    VERIFY_NON_NULL(TAG, delDevCtx, ERROR, OC_STACK_DELETE_TRANSACTION);
+    OCStackResult res = OC_STACK_ERROR;
+
+    RemoveData_t* removeData = (RemoveData_t*)delDevCtx;
+    OCProvisionDev_t * pTargetDev = PMCloneOCProvisionDev(removeData->revokeTargetDev);
+    OCProvisionResultCB resultCallback = removeData->resultCallback;
+    if (clientResponse)
+    {
+        OicUuid_t revDevUuid = {.id={0}};
+        if(UUID_LENGTH == clientResponse->identity.id_length)
+        {
+            memcpy(revDevUuid.id, clientResponse->identity.id, sizeof(revDevUuid.id));
+            if (OC_STACK_RESOURCE_DELETED == clientResponse->result)
+            {
+                res = PDMUnlinkDevices(&removeData->revokeTargetDev->doxm->deviceID, &revDevUuid);
+                if (OC_STACK_OK != res)
+                {
+                    OIC_LOG(ERROR, TAG, "PDMSetLinkStale() FAIL: PDB is an obsolete one.");
+                           registerResultForResetDevice(removeData, &revDevUuid,
+                           OC_STACK_INCONSISTENT_DB, true);
+
+                    return OC_STACK_DELETE_TRANSACTION;
+                }
+
+                registerResultForResetDevice(removeData, &revDevUuid,
+                                              OC_STACK_RESOURCE_DELETED, false);
+            }
+            else
+            {
+                registerResultForResetDevice(removeData, &revDevUuid,
+                                              clientResponse->result, false);
+                OIC_LOG(ERROR, TAG, "Unexpected result from DELETE credential request!");
+            }
+        }
+        else
+        {
+            OIC_LOG_V(WARNING, TAG, "Incorrect length of device UUID was sent from %s:%d",
+                     clientResponse->devAddr.addr, clientResponse->devAddr.port);
+
+            if (OC_STACK_RESOURCE_DELETED == clientResponse->result)
+            {
+                /**
+                  * Since server's credential was deleted,
+                  * register result as OC_STACK_INCONSISTENT_DB with NULL UUID.
+                  */
+                OIC_LOG_V(ERROR, TAG, "But server's credential was deleted.");
+                registerResultForResetDevice(removeData, NULL, OC_STACK_INCONSISTENT_DB, true);
+            }
+            else
+            {
+                registerResultForResetDevice(removeData, NULL, clientResponse->result, true);
+            }
+        }
+    }
+    else
+    {
+        registerResultForResetDevice(removeData, NULL, OC_STACK_ERROR, true);
+        OIC_LOG(ERROR, TAG, "SRPSyncDevice received Null clientResponse");
+    }
+
+    SRPResetDevice(pTargetDev, resultCallback);
+
+    return OC_STACK_DELETE_TRANSACTION;
+}
+
+/**
+ * Callback handler of reset device sync-up
+ *
+ * @param[in] ctx             ctx value passed to callback from calling function.
+ * @param[in] handle          handle to an invocation
+ * @param[in] clientResponse  Response from queries to remote servers.
+ * @return  OC_STACK_DELETE_TRANSACTION to delete the transaction
+ *          and  OC_STACK_KEEP_TRANSACTION to keep it.
+ */
+static OCStackApplicationResult SRPSyncDeviceACLCB(void *ctx, OCDoHandle handle,
+        OCClientResponse *clientResponse)
+{
+    return OC_STACK_DELETE_TRANSACTION;
+}
+
+/**
+ * Callback handler of device remote reset.
+ *
+ * @param[in] ctx             ctx value passed to callback from calling function.
+ * @param[in] handle          handle to an invocation
+ * @param[in] clientResponse  Response from queries to remote servers.
+ * @return  OC_STACK_DELETE_TRANSACTION to delete the transaction
+ *          and  OC_STACK_KEEP_TRANSACTION to keep it.
+ */
+static OCStackApplicationResult SRPResetDeviceCB(void *ctx, OCDoHandle handle,
+        OCClientResponse *clientResponse)
+{
+    OIC_LOG(DEBUG, TAG, "IN SRPResetDeviceCB");
+    if(OC_STACK_OK == clientResponse->result)
+    {
+        OIC_LOG(DEBUG, TAG, "Change Target Device Pstat Cm SUCCEEDED");
+    }
+
+    // Delete Cred and ACL related to the target device.
+    const OicSecCred_t *cred = NULL;
+    OCProvisionDev_t * pTargetDev = (OCProvisionDev_t *)ctx;
+    cred = GetCredResourceData(&pTargetDev->doxm->deviceID);
+    if (cred == NULL)
+    {
+        OIC_LOG(ERROR, TAG, "OCResetDevice : Failed to get credential of target device.");
+        goto error;
+    }
+
+    OCStackResult res = RemoveCredential(&cred->subject);
+    if (res != OC_STACK_RESOURCE_DELETED && res != OC_STACK_NO_RESOURCE)
+    {
+        OIC_LOG(ERROR, TAG, "OCResetDevice : Failed to remove credential.");
+        goto error;
+    }
+
+    res = RemoveACE(&cred->subject, NULL);
+    if (res != OC_STACK_RESOURCE_DELETED && res != OC_STACK_NO_RESOURCE)
+    {
+        OIC_LOG(ERROR, TAG, "OCResetDevice : Failed to remove ACL.");
+        goto error;
+    }
+    if (OC_STACK_OK != PDMDeleteDevice(&pTargetDev->doxm->deviceID))
+    {
+        OIC_LOG(ERROR, TAG, "OCResetDevice : Failed to delete device from PDM");
+    }
+
+    //Close the DTLS session of the reset device.
+    CAEndpoint_t* endpoint = (CAEndpoint_t *)&clientResponse->devAddr;
+    CAResult_t caResult = CAcloseSslSession(endpoint);
+    if(CA_STATUS_OK != caResult)
+    {
+        OIC_LOG_V(WARNING, TAG, "OCResetDevice : Failed to close DTLS session : %d", caResult);
+    }
+
+    /**
+     * If there is no linked device, PM does not send any request.
+     * So we should directly invoke the result callback to inform the result of OCResetDevice.
+     */
+    if(OC_STACK_NO_RESOURCE == res)
+    {
+        res = OC_STACK_OK;
+    }
+
+error:
+    OICFree(pTargetDev);
+    return OC_STACK_DELETE_TRANSACTION;
+
+}
+
 static OCStackResult GetListofDevToReqDeleteCred(const OCProvisionDev_t* pRevokeTargetDev,
                                                  OCProvisionDev_t* pOwnedDevList,
                                                  OCUuidList_t* pLinkedUuidList,
@@ -1723,6 +2005,416 @@ error:
     return res;
 }
 
+/*
+* Function to device revocation
+* This function will remove credential of target device from all devices in subnet.
+*
+* @param[in] ctx Application context would be returned in result callback
+* @param[in] pOwnedDevList List of owned devices
+* @param[in] pTargetDev Device information to be revoked.
+* @param[in] resultCallback callback provided by API user, callback will be called when
+*            credential revocation is finished.
+* @return  OC_STACK_OK in case of success and other value otherwise.
+*          If OC_STACK_OK is returned, the caller of this API should wait for callback.
+*          OC_STACK_CONTINUE means operation is success but no request is need to be initiated.
+*/
+OCStackResult SRPRemoveDeviceWithoutDiscovery(void* ctx, const OCProvisionDev_t* pOwnedDevList,
+                             const OCProvisionDev_t* pTargetDev, OCProvisionResultCB resultCallback)
+{
+    OIC_LOG(INFO, TAG, "IN SRPRemoveDeviceWithoutDiscovery");
+
+    if (!pOwnedDevList)
+    {
+        OIC_LOG(WARNING, TAG, "SRPRemoveDeviceWithoutDiscovery : Owned Device List is empty");
+        return OC_STACK_CONTINUE;
+    }
+    if (!pTargetDev)
+    {
+        OIC_LOG(INFO, TAG, "SRPRemoveDeviceWithoutDiscovery : NULL parameters");
+        return OC_STACK_INVALID_PARAM;
+    }
+    if (!resultCallback)
+    {
+        OIC_LOG(INFO, TAG, "SRPRemoveDeviceWithoutDiscovery : NULL Callback");
+        return OC_STACK_INVALID_CALLBACK;
+    }
+
+    // Declare variables in here to handle error cases with goto statement.
+    OCProvisionDev_t* pLinkedDevList = NULL;
+    RemoveData_t* removeData = NULL;
+
+    //1. Find all devices that has a credential of the revoked device
+    OCUuidList_t* pLinkedUuidList = NULL;
+    size_t numOfDevices = 0;
+    OCStackResult res = OC_STACK_ERROR;
+    res = PDMGetLinkedDevices(&pTargetDev->doxm->deviceID, &pLinkedUuidList, &numOfDevices);
+    if (OC_STACK_OK != res)
+    {
+        OIC_LOG(WARNING, TAG, "SRPRemoveDeviceWithoutDiscovery : Failed to get linked devices information");
+        return OC_STACK_CONTINUE;
+    }
+    // if there is no related device, we can skip further process.
+    if (0 == numOfDevices)
+    {
+        OIC_LOG(WARNING, TAG, "SRPRemoveDeviceWithoutDiscovery : No linked device found.");
+        return OC_STACK_CONTINUE;
+    }
+
+    //2. Make a list of devices to send DELETE credential request
+    //   by comparing owned devices from provisioning database with mutlicast discovery result.
+    size_t numOfLinkedDev = 0;
+    res = GetListofDevToReqDeleteCred(pTargetDev, pOwnedDevList, pLinkedUuidList,
+                                      &pLinkedDevList, &numOfLinkedDev);
+    if (OC_STACK_OK != res)
+    {
+        OIC_LOG(ERROR, TAG, "SRPRemoveDeviceWithoutDiscovery : GetListofDevToReqDeleteCred() failed");
+        goto error;
+    }
+    if (0 == numOfLinkedDev) // This case means, there is linked device but it's not alive now.
+    {                       // So we don't have to send request message.
+        OIC_LOG(DEBUG, TAG, "SRPRemoveDeviceWithoutDiscovery : No alived & linked device found.");
+        return OC_STACK_CONTINUE;
+    }
+
+    // 3. Prepare RemoveData Context data.
+    removeData = (RemoveData_t*)OICCalloc(1, sizeof(RemoveData_t));
+    if (!removeData)
+    {
+        OIC_LOG(ERROR, TAG, "SRPRemoveDeviceWithoutDiscovery : Failed to memory allocation");
+        res = OC_STACK_NO_MEMORY;
+        goto error;
+    }
+
+    removeData->revokeTargetDev = PMCloneOCProvisionDev(pTargetDev);
+    if (!removeData->revokeTargetDev)
+    {
+        OIC_LOG(ERROR, TAG, "SRPRemoveDeviceWithoutDiscovery : PMCloneOCProvisionDev Failed");
+        res = OC_STACK_NO_MEMORY;
+        goto error;
+    }
+
+    removeData->removeRes =
+        (OCProvisionResult_t*)OICCalloc(numOfLinkedDev, sizeof(OCProvisionResult_t));
+    if (!removeData->removeRes)
+    {
+        OIC_LOG(ERROR, TAG, "SRPRemoveDeviceWithoutDiscovery : Failed to memory allocation");
+        res = OC_STACK_NO_MEMORY;
+        goto error;
+    }
+
+    removeData->ctx = ctx;
+    removeData->linkedDevList = pLinkedDevList;
+    removeData->resultCallback = resultCallback;
+    removeData->numOfResults = 0;
+    removeData->sizeOfResArray = numOfLinkedDev;
+    removeData->hasError = false;
+
+    // 5. Send DELETE credential request to linked devices.
+    OCProvisionDev_t *curDev = NULL, *tmpDev = NULL;
+    OCStackResult totalRes = OC_STACK_ERROR;  /* variable for checking request is sent or not */
+    LL_FOREACH_SAFE(pLinkedDevList, curDev, tmpDev)
+    {
+        res = SendDeleteCredentialRequest((void*)removeData, &SRPRemoveDeviceCB,
+                                           removeData->revokeTargetDev, curDev);
+        if (OC_STACK_OK != res)
+        {
+            OIC_LOG_V(ERROR, TAG, "SRPRemoveDeviceWithoutDiscovery : Fail to send the DELETE credential request to\
+                     %s:%u", curDev->endpoint.addr, curDev->endpoint.port);
+        }
+        else
+        {
+            totalRes = OC_STACK_OK; // This means at least one request is successfully sent.
+        }
+    }
+
+    PDMDestoryOicUuidLinkList(pLinkedUuidList); //TODO: Modify API name to have unified convention.
+    OIC_LOG(INFO, TAG, "OUT SRPRemoveDeviceWithoutDiscovery");
+
+    return totalRes; // Caller of this API should wait callback if totalRes == OC_STACK_OK.
+
+error:
+    PDMDestoryOicUuidLinkList(pLinkedUuidList);
+    PMDeleteDeviceList(pLinkedDevList);
+    if (removeData)
+    {
+        OICFree(removeData->revokeTargetDev);
+        OICFree(removeData->removeRes);
+        OICFree(removeData);
+    }
+    OIC_LOG(INFO, TAG, "OUT ERROR case SRPRemoveDeviceWithoutDiscovery");
+    return res;
+}
+
+/*
+ * Function to sync-up credential and ACL of the target device.
+ * This function will remove credential and ACL of target device from all devices in subnet.
+ *
+ * @param[in] ctx Application context would be returned in result callback
+ * @param[in] waitTimeForOwnedDeviceDiscovery Maximum wait time for owned device discovery.(seconds)
+ * @param[in] pTargetDev Device information to be revoked.
+ * @param[in] resultCallback callback provided by API user, callback will be called when
+ *            credential revocation is finished.
+ *            when there is an error, this user callback is called immediately.
+ * @return OC_STACK_OK in case of success and other value otherwise.
+ *         If OC_STACK_OK is returned, the caller of this API should wait for callback.
+ *         OC_STACK_CONTINUE means operation is success but no request is need to be initiated.
+ */
+OCStackResult SRPSyncDevice(void* ctx, unsigned short waitTimeForOwnedDeviceDiscovery,
+                         const OCProvisionDev_t* pTargetDev, OCProvisionResultCB resultCallback)
+{
+    OIC_LOG(INFO, TAG, "IN SRPSyncDevice");
+    if (!pTargetDev  || 0 == waitTimeForOwnedDeviceDiscovery)
+    {
+        OIC_LOG(INFO, TAG, "SRPSyncDevice : NULL parameters");
+        return OC_STACK_INVALID_PARAM;
+    }
+    if (!resultCallback)
+    {
+        OIC_LOG(INFO, TAG, "SRPSyncDevice : NULL Callback");
+        return OC_STACK_INVALID_CALLBACK;
+    }
+
+    // Declare variables in here to handle error cases with goto statement.
+    OCProvisionDev_t* pOwnedDevList = NULL;
+    OCProvisionDev_t* pLinkedDevList = NULL;
+    RemoveData_t* removeData = NULL;
+
+    //1. Find all devices that has a credential of the revoked device
+    OCUuidList_t* pLinkedUuidList = NULL;
+    size_t numOfDevices = 0;
+    OCStackResult res = OC_STACK_ERROR;
+    res = PDMGetLinkedDevices(&pTargetDev->doxm->deviceID, &pLinkedUuidList, &numOfDevices);
+    if (OC_STACK_OK != res)
+    {
+        OIC_LOG(ERROR, TAG, "SRPSyncDevice : Failed to get linked devices information");
+        return res;
+    }
+    // if there is no related device, we can skip further process.
+    if (0 == numOfDevices)
+    {
+        OIC_LOG(DEBUG, TAG, "SRPSyncDevice : No linked device found.");
+        res = OC_STACK_CONTINUE;
+        goto error;
+    }
+
+    //2. Find owned device from the network
+    res = PMDeviceDiscovery(waitTimeForOwnedDeviceDiscovery, true, &pOwnedDevList);
+    if (OC_STACK_OK != res)
+    {
+        OIC_LOG(ERROR, TAG, "SRPSyncDevice : Failed to PMDeviceDiscovery");
+        goto error;
+    }
+
+    //3. Make a list of devices to send DELETE credential request
+    //   by comparing owned devices from provisioning database with mutlicast discovery result.
+    size_t numOfLinkedDev = 0;
+    res = GetListofDevToReqDeleteCred(pTargetDev, pOwnedDevList, pLinkedUuidList,
+                                      &pLinkedDevList, &numOfLinkedDev);
+    if (OC_STACK_OK != res)
+    {
+        OIC_LOG(ERROR, TAG, "SRPSyncDevice : GetListofDevToReqDeleteCred() failed");
+        goto error;
+    }
+    if (0 == numOfLinkedDev) // This case means, there is linked device but it's not alive now.
+    {                       // So we don't have to send request message.
+        OIC_LOG(DEBUG, TAG, "SRPSyncDevice : No alived & linked device found.");
+        res = OC_STACK_CONTINUE;
+        goto error;
+    }
+
+    // 4. Prepare RemoveData Context data.
+    removeData = (RemoveData_t*)OICCalloc(1, sizeof(RemoveData_t));
+    if (!removeData)
+    {
+        OIC_LOG(ERROR, TAG, "SRPSyncDevice : Failed to memory allocation");
+        res = OC_STACK_NO_MEMORY;
+        goto error;
+    }
+
+    removeData->revokeTargetDev = PMCloneOCProvisionDev(pTargetDev);
+    if (!removeData->revokeTargetDev)
+    {
+        OIC_LOG(ERROR, TAG, "SRPSyncDevice : PMCloneOCProvisionDev Failed");
+        res = OC_STACK_NO_MEMORY;
+        goto error;
+    }
+
+    removeData->removeRes =
+        (OCProvisionResult_t*)OICCalloc(numOfLinkedDev, sizeof(OCProvisionResult_t));
+    if (!removeData->removeRes)
+    {
+        OIC_LOG(ERROR, TAG, "SRPSyncDevice : Failed to allocate memory");
+        res = OC_STACK_NO_MEMORY;
+        goto error;
+    }
+
+    removeData->ctx = ctx;
+    removeData->linkedDevList = pLinkedDevList;
+    removeData->resultCallback = resultCallback;
+    removeData->numOfResults = 0;
+    removeData->sizeOfResArray = numOfLinkedDev;
+    removeData->hasError = false;
+
+    // 5. Send DELETE credential request to linked devices.
+    OCProvisionDev_t *curDev = NULL, *tmpDev = NULL;
+    OCStackResult totalRes = OC_STACK_ERROR;  /* variable for checking request is sent or not */
+    LL_FOREACH_SAFE(pLinkedDevList, curDev, tmpDev)
+    {
+        res = SendDeleteACLRequest((void*)removeData, &SRPSyncDeviceACLCB,
+                                           removeData->revokeTargetDev, curDev);
+        if (OC_STACK_OK != res)
+        {
+            OIC_LOG_V(ERROR, TAG, "SRPSyncDevice : Fail to send the DELETE ACL request to\
+                     %s:%u", curDev->endpoint.addr, curDev->endpoint.port);
+            goto error;
+        }
+        res = SendDeleteCredentialRequest((void*)removeData, &SRPSyncDeviceCredCB,
+                                           removeData->revokeTargetDev, curDev);
+        if (OC_STACK_OK != res)
+        {
+            OIC_LOG_V(ERROR, TAG, "SRPSyncDevice : Fail to send the DELETE credential request to\
+                     %s:%u", curDev->endpoint.addr, curDev->endpoint.port);
+            totalRes = OC_STACK_ERROR;
+        }
+        else
+        {
+            totalRes = OC_STACK_OK; // This means at least one request is successfully sent.
+        }
+    }
+
+    PDMDestoryOicUuidLinkList(pLinkedUuidList); //TODO: Modify API name to have unified convention.
+    PMDeleteDeviceList(pOwnedDevList);
+    OIC_LOG(INFO, TAG, "OUT SRPSyncDevice");
+
+    return totalRes; // Caller of this API should wait callback if totalRes == OC_STACK_OK.
+
+error:
+    PDMDestoryOicUuidLinkList(pLinkedUuidList);
+    PMDeleteDeviceList(pOwnedDevList);
+    PMDeleteDeviceList(pLinkedDevList);
+    if (removeData)
+    {
+        OICFree(removeData->revokeTargetDev);
+        OICFree(removeData->removeRes);
+        OICFree(removeData);
+    }
+    OIC_LOG(INFO, TAG, "OUT ERROR case SRPSyncDevice");
+    return res;
+}
+
+/*
+ * Function for remote reset
+ * This function will send pstat PUT message to the target device to initiate remote reset.
+ *
+ * @param[in] pTargetDev Device information to be revoked.
+ * @param[in] resultCallback callback provided by API user, callback will be called when
+ *            credential revocation is finished.
+ *            when there is an error, this user callback is called immediately.
+ * @return OC_STACK_OK in case of success and other value otherwise.
+ *         If OC_STACK_OK is returned, the caller of this API should wait for callback.
+ *         OC_STACK_CONTINUE means operation is success but no request is need to be initiated.
+ */
+OCStackResult SRPResetDevice(const OCProvisionDev_t* pTargetDev,
+        OCProvisionResultCB resultCallback)
+{
+    OIC_LOG(INFO, TAG, "IN SRPResetDevice");
+    if (!pTargetDev)
+    {
+        OIC_LOG(INFO, TAG, "SRPResetDevice : NULL parameters");
+        return OC_STACK_INVALID_PARAM;
+    }
+    if (!resultCallback)
+    {
+        OIC_LOG(INFO, TAG, "SRPResetDevice : NULL Callback");
+        return OC_STACK_INVALID_CALLBACK;
+    }
+
+    OCStackResult res = OC_STACK_ERROR;
+    OicSecPstat_t * pstat = (OicSecPstat_t *) OICCalloc(1, sizeof(OicSecPstat_t));
+    if (!pstat)
+    {
+        OIC_LOG(ERROR, TAG, "Failed to allocate memory");
+        return OC_STACK_NO_MEMORY;
+    }
+
+    pstat->cm = RESET;
+    pstat->isOp = false;
+    memcpy(pstat->deviceID.id, pTargetDev->doxm->deviceID.id, sizeof(OicUuid_t));
+    pstat->tm = TAKE_OWNER;
+    pstat->om = (OicSecDpom_t)(SINGLE_SERVICE_CLIENT_DRIVEN); // the only mode IoTivity supports currently
+    pstat->smLen = 1;
+    pstat->sm = (OicSecDpom_t *) OICCalloc(pstat->smLen, sizeof(OicSecDpom_t));
+    if (NULL == pstat->sm)
+    {
+        OIC_LOG(ERROR, TAG, "Failed to allocate memory");
+        OICFree(pstat);
+        return OC_STACK_NO_MEMORY;
+    }
+    pstat->sm[0] = (OicSecDpom_t)(SINGLE_SERVICE_CLIENT_DRIVEN); // the only mode IoTivity supports currently
+
+    OCSecurityPayload * secPayload = (OCSecurityPayload *) OICCalloc(1, sizeof(OCSecurityPayload));
+    if (!secPayload)
+    {
+        OIC_LOG(ERROR, TAG, "Failed to allocate memory");
+        res = OC_STACK_NO_MEMORY;
+        goto error;
+    }
+    secPayload->base.type = PAYLOAD_TYPE_SECURITY;
+
+    if (OC_STACK_OK != PstatToCBORPayload(pstat, &(secPayload->securityData),
+                &(secPayload->payloadSize), true))
+    {
+        OCPayloadDestroy((OCPayload *) secPayload);
+        OIC_LOG(ERROR, TAG, "Failed to PstatToCBORPayload");
+        res = OC_STACK_NO_MEMORY;
+        goto error;
+    }
+    OIC_LOG(DEBUG, TAG, "Created payload for pstat set");
+    OIC_LOG_BUFFER(DEBUG, TAG, secPayload->securityData, secPayload->payloadSize);
+
+    char query[MAX_URI_LENGTH + MAX_QUERY_LENGTH] = {0};
+    if (!PMGenerateQuery(true,
+                pTargetDev->endpoint.addr,
+                pTargetDev->securePort,
+                pTargetDev->connType,
+                query, sizeof(query), OIC_RSRC_PSTAT_URI))
+    {
+        OIC_LOG(ERROR, TAG, "SRPResetDevice : Failed to generate query");
+        OCPayloadDestroy((OCPayload *) secPayload);
+        res = OC_STACK_ERROR;
+        goto error;
+    }
+    OIC_LOG_V(DEBUG, TAG, "Query=%s", query);
+
+    OCCallbackData cbData = { .context = NULL, .cb = NULL, .cd = NULL };
+    OCMethod method = OC_REST_POST;
+    OCDoHandle handle = NULL;
+    OCProvisionDev_t * targetDev = PMCloneOCProvisionDev(pTargetDev);
+    if (NULL == targetDev)
+    {
+        OIC_LOG(ERROR, TAG, "target dev is null");
+        res = OC_STACK_ERROR;
+        goto error;
+    }
+    cbData.cb = &SRPResetDeviceCB;
+    cbData.context = (void *) targetDev;
+    cbData.cd = NULL;
+    OIC_LOG(DEBUG, TAG, "Sending PSTAT info to resource server");
+    res = OCDoResource(&handle, method, query,
+            &targetDev->endpoint, (OCPayload *)secPayload,
+            targetDev->connType, OC_LOW_QOS, &cbData, NULL, 0);\
+    if (OC_STACK_OK != res)
+    {
+        OIC_LOG(ERROR, TAG, "OCStack resource error");
+    }
+
+error:
+    OICFree(pstat->sm);
+    OICFree(pstat);
+    OIC_LOG(INFO, TAG, "OUT SRPResetDevice");
+    return res;
+}
+
 /**
  * Internal Function to store results in result array during GetCredResourceCB.
  */