Fix Wformat build error
[platform/upstream/iotivity.git] / resource / csdk / security / provisioning / src / secureresourceprovider.c
index 7980e56..6804381 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"
 #include "logger.h"
 #include "oic_malloc.h"
+#include "oic_string.h"
 #include "aclresource.h"
 #include "pstatresource.h"
 #include "srmresourcestrings.h"
 #include "pconfresource.h"
 #include "credentialgenerator.h"
 #include "cainterface.h"
+#if defined (__TIZENRT__)
+#include <apps/netutils/cJSON.h>
+#else
 #include "cJSON.h"
+#endif
 #include "pmtypes.h"
 #include "pmutility.h"
+#include "srmutility.h"
 #include "provisioningdatabasemanager.h"
 #include "base64.h"
 #include "utlist.h"
 #include "ocpayload.h"
 
-#ifdef __WITH_X509__
+#ifdef __WITH_DTLS__
 #include "crlresource.h"
 #endif // WITH_X509__
 
-#define TAG "SRPAPI"
+#define TAG "OIC_SRPAPI"
 
 /**
  * Macro to verify argument is not equal to NULL.
- * eg: VERIFY_NON_NULL(TAG, ptrData, ERROR,OC_STACK_ERROR);
+ * eg: VERIFY_NON_NULL_RET(TAG, ptrData, ERROR,OC_STACK_ERROR);
  */
-#define VERIFY_NON_NULL(tag, arg, logLevel, retValue) { if (NULL == (arg)) \
+#define VERIFY_NON_NULL_RET(tag, arg, logLevel, retValue) { if (NULL == (arg)) \
             { OIC_LOG((logLevel), tag, #arg " is NULL"); return retValue; } }
 
 /**
  * Macro to verify success of operation.
- * eg: VERIFY_SUCCESS(TAG, OC_STACK_OK == foo(), ERROR, OC_STACK_ERROR);
+ * eg: VERIFY_SUCCESS_RET(TAG, OC_STACK_OK == foo(), ERROR, OC_STACK_ERROR);
  */
-#define VERIFY_SUCCESS(tag, op, logLevel, retValue) { if (!(op)) \
+#define VERIFY_SUCCESS_RET(tag, op, logLevel, retValue) { if (!(op)) \
             {OIC_LOG((logLevel), tag, #op " failed!!"); return retValue;} }
 
+
+trustCertChainContext_t g_trustCertChainNotifier;
+
 /**
  * Structure to carry credential data to callback.
  */
@@ -91,6 +103,16 @@ struct ACLData
     int numOfResults;                           /**< Number of results in result array.**/
 };
 
+// Structure to carry get security resource APIs data to callback.
+typedef struct GetSecData GetSecData_t;
+struct GetSecData {
+    void *ctx;
+    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.**/
+};
+
 /**
  * Structure to carry PCONF provision API data to callback.
  */
@@ -123,6 +145,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;
@@ -132,6 +155,7 @@ struct RemoveData {
     OCProvisionDev_t* linkedDevList;        /**< A list of devices which have invalid credential.**/
     OCProvisionResult_t* removeRes;         /**< Result array.**/
     OCProvisionResultCB resultCallback;     /**< Pointer to result callback.**/
+    OCClientContextDeleter deleteCallback;  /**< Pointer to delete callback.**/
     size_t numOfResults;                    /**< Number of results in result array.**/
     size_t sizeOfResArray;
     bool hasError;
@@ -179,7 +203,7 @@ static void registerResultForCredProvisioning(CredentialData_t *credData,
 static OCStackApplicationResult provisionCredentialCB2(void *ctx, OCDoHandle UNUSED,
                                                        OCClientResponse *clientResponse)
 {
-    VERIFY_NON_NULL(TAG, ctx, ERROR, OC_STACK_DELETE_TRANSACTION);
+    VERIFY_NON_NULL_RET(TAG, ctx, ERROR, OC_STACK_DELETE_TRANSACTION);
     CredentialData_t *credData = (CredentialData_t *) ctx;
     (void)UNUSED;
 
@@ -187,9 +211,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)
@@ -230,7 +254,7 @@ static OCStackApplicationResult provisionCredentialCB2(void *ctx, OCDoHandle UNU
 static OCStackApplicationResult provisionCredentialCB1(void *ctx, OCDoHandle UNUSED,
                                                        OCClientResponse *clientResponse)
 {
-    VERIFY_NON_NULL(TAG, ctx, ERROR, OC_STACK_DELETE_TRANSACTION);
+    VERIFY_NON_NULL_RET(TAG, ctx, ERROR, OC_STACK_DELETE_TRANSACTION);
     (void)UNUSED;
     CredentialData_t* credData = (CredentialData_t*) ctx;
     OICFree(credData->credInfoFirst);
@@ -239,10 +263,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);
@@ -304,7 +328,9 @@ static OCStackResult provisionCredentials(const OicSecCred_t *cred,
         return OC_STACK_NO_MEMORY;
     }
     secPayload->base.type = PAYLOAD_TYPE_SECURITY;
-    OCStackResult res = CredToCBORPayload(cred, &secPayload->securityData, &secPayload->payloadSize);
+    int secureFlag = 0;
+    OCStackResult res = CredToCBORPayload(cred, &secPayload->securityData,
+                                          &secPayload->payloadSize, secureFlag);
     if((OC_STACK_OK != res) && (NULL == secPayload->securityData))
     {
         OCPayloadDestroy((OCPayload *)secPayload);
@@ -322,6 +348,7 @@ static OCStackResult provisionCredentials(const OicSecCred_t *cred,
                         query, sizeof(query), OIC_RSRC_CRED_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);
@@ -344,7 +371,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.
  */
@@ -360,19 +387,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,
@@ -386,23 +400,28 @@ static void registerResultForCertProvisioning(CertData_t *certData,
    ++(certData->numOfResults);
 }
 
-/**
- * Internal Function to store results in result array during ACL provisioning.
- */
-static void registerResultForCRLProvisioning(CRLData_t *crlData,
-                                             OCStackResult stackresult)
+OCStackResult SRPRegisterTrustCertChainNotifier(void *ctx, TrustCertChainChangeCB callback)
 {
-   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);
+    if (g_trustCertChainNotifier.callback)
+    {
+        OIC_LOG(ERROR, TAG, "Can't register Notifier, Unregister previous one");
+        return OC_STACK_ERROR;
+    }
+
+    g_trustCertChainNotifier.callback = callback;
+    g_trustCertChainNotifier.context = ctx;
+    return OC_STACK_OK;
 }
 
+void SRPRemoveTrustCertChainNotifier()
+{
+    g_trustCertChainNotifier.callback = NULL;
+    g_trustCertChainNotifier.context = NULL;
+    return;
+}
 
 /**
- * Callback handler of SRPProvisionCRL.
+ * Callback handler for handling callback of certificate provisioning device.
  *
  * @param[in] ctx             ctx value passed to callback from calling function.
  * @param[in] UNUSED          handle to an invocation
@@ -410,61 +429,76 @@ static void registerResultForCRLProvisioning(CRLData_t *crlData,
  * @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)
+static OCStackApplicationResult provisionCertCB(void *ctx, OCDoHandle UNUSED,
+                                                       OCClientResponse *clientResponse)
 {
-    OIC_LOG_V(INFO, TAG, "Inside SRPProvisionCRLCB.");
+    VERIFY_NON_NULL_RET(TAG, ctx, ERROR, OC_STACK_DELETE_TRANSACTION);
+    CertData_t *certData = (CertData_t *) ctx;
     (void)UNUSED;
-    VERIFY_NON_NULL(TAG, ctx, ERROR, OC_STACK_DELETE_TRANSACTION);
-    CRLData_t *crlData = (CRLData_t*)ctx;
-    OCProvisionResultCB resultCallback = crlData->resultCallback;
 
+    OCProvisionResultCB resultCallback = certData->resultCallback;
+    OIC_LOG(INFO, TAG, "provisionCertCB called");
     if (clientResponse)
     {
-        if(OC_STACK_RESOURCE_CREATED == clientResponse->result)
+        if(OC_STACK_RESOURCE_CHANGED == clientResponse->result)
         {
-            registerResultForCRLProvisioning(crlData, OC_STACK_RESOURCE_CREATED);
-            ((OCProvisionResultCB)(resultCallback))(crlData->ctx, crlData->numOfResults,
-                                                    crlData->resArr,
+            registerResultForCertProvisioning(certData, OC_STACK_RESOURCE_CHANGED);
+            ((OCProvisionResultCB)(resultCallback))(certData->ctx, certData->numOfResults,
+                                                    certData->resArr,
                                                     false);
-             OICFree(crlData->resArr);
-             OICFree(crlData);
+             OICFree(certData->resArr);
+             OICFree(certData);
              return OC_STACK_DELETE_TRANSACTION;
         }
+
     }
-    registerResultForCRLProvisioning(crlData, OC_STACK_ERROR);
-    ((OCProvisionResultCB)(resultCallback))(crlData->ctx, crlData->numOfResults,
-                                            crlData->resArr,
+    OIC_LOG(INFO, TAG, "provisionCertCredCB received Null clientResponse");
+    registerResultForCertProvisioning(certData, OC_STACK_ERROR);
+    ((OCProvisionResultCB)(resultCallback))(certData->ctx, certData->numOfResults,
+                                            certData->resArr,
                                             true);
-    OIC_LOG_V(ERROR, TAG, "SRPProvisionCRLCB received Null clientResponse");
-    OICFree(crlData->resArr);
-    OICFree(crlData);
+    OICFree(certData->resArr);
+    OICFree(certData);
     return OC_STACK_DELETE_TRANSACTION;
 }
 
-OCStackResult SRPProvisionCRL(void *ctx, const OCProvisionDev_t *selectedDeviceInfo,
-        OicSecCrl_t *crl, OCProvisionResultCB resultCallback)
+OCStackResult SRPProvisionTrustCertChain(void *ctx, OicSecCredType_t type, uint16_t credId,
+        const OCProvisionDev_t *selectedDeviceInfo, 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);
+    OIC_LOG(INFO, TAG, "In SRPProvisionTrustCertChain");
+    VERIFY_NON_NULL_RET(TAG, selectedDeviceInfo, ERROR,  OC_STACK_INVALID_PARAM);
+    VERIFY_NON_NULL_RET(TAG, resultCallback, ERROR,  OC_STACK_INVALID_CALLBACK);
+    if (SIGNED_ASYMMETRIC_KEY != type)
+    {
+        OIC_LOG(INFO, TAG, "Invalid key type");
+        return OC_STACK_INVALID_PARAM;
+    }
+
+    OicSecCred_t *trustCertChainCred = GetCredEntryByCredId(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)
+    if(!secPayload)
     {
+        DeleteCredList(trustCertChainCred);
         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))
+    int secureFlag = 0;
+    if(OC_STACK_OK != CredToCBORPayload(trustCertChainCred, &secPayload->securityData, &secPayload->payloadSize, secureFlag))
     {
-        OICFree(secPayload);
-        OIC_LOG(ERROR, TAG, "Failed to BinToCrlJSON");
+        DeleteCredList(trustCertChainCred);
+        OCPayloadDestroy((OCPayload *)secPayload);
+        OIC_LOG(ERROR, TAG, "Failed to CredToCBORPayload");
         return OC_STACK_NO_MEMORY;
     }
-    OIC_LOG(DEBUG, TAG, "Created payload for CRL:");
+    DeleteCredList(trustCertChainCred);
+    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};
@@ -472,170 +506,198 @@ OCStackResult SRPProvisionCRL(void *ctx, const OCProvisionDev_t *selectedDeviceI
                         selectedDeviceInfo->endpoint.addr,
                         selectedDeviceInfo->securePort,
                         selectedDeviceInfo->connType,
-                        query, sizeof(query), OIC_RSRC_CRL_URI))
+                        query, sizeof(query), OIC_RSRC_CRED_URI))
     {
-        OIC_LOG(ERROR, TAG, "DeviceDiscoveryHandler : Failed to generate query");
+        OIC_LOG(ERROR, TAG, "SRPProvisionTrustCertChain : 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)
+    cbData.cb = &provisionCertCB;
+    CertData_t *certData = (CertData_t *) OICCalloc(1, sizeof(CertData_t));
+    if (NULL == certData)
     {
+        OIC_LOG(ERROR, TAG, "Memory allocation problem");
         OCPayloadDestroy((OCPayload *)secPayload);
-        OIC_LOG(ERROR, TAG, "Unable to allocate memory");
         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;
 
-    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)
+    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 *)crlData;
+    cbData.context = (void *)certData;
     cbData.cd = NULL;
     OCMethod method = OC_REST_POST;
     OCDoHandle handle = NULL;
-    OIC_LOG(DEBUG, TAG, "Sending CRL info to resource server");
-
+    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(crlData->resArr);
-        OICFree(crlData);
+        OICFree(certData->resArr);
+        OICFree(certData);
     }
 
-    return ret;
+    VERIFY_SUCCESS_RET(TAG, (OC_STACK_OK == ret), ERROR, OC_STACK_ERROR);
+    return OC_STACK_OK;
 }
 
-/**
- * Internal function for handling credential generation and sending cretificate credential.
- *
- * @param[in] cred Instance of cred resource.
- * @param[in] deviceInfo information about device to which credential is to be provisioned.
- * @param[in] responseHandler callbak called by OC stack when request API receives response.
- * @return  OC_STACK_OK in case of success and other value otherwise.
- */
-static OCStackResult provisionCertCred(const OicSecCred_t *cred,
-        const OCProvisionDev_t *deviceInfo, CertData_t *certData,
-        OCClientResponseHandler responseHandler)
+OCStackResult SRPSaveTrustCertChain(uint8_t *trustCertChain, size_t chainSize,
+                                            OicEncodingType_t encodingType, uint16_t *credId)
 {
-    OCSecurityPayload* secPayload = (OCSecurityPayload*)OICCalloc(1, sizeof(OCSecurityPayload));
-    if(!secPayload)
+    OIC_LOG(DEBUG, TAG, "IN SRPSaveTrustCertChain");
+    VERIFY_NON_NULL_RET(TAG, trustCertChain, ERROR,  OC_STACK_INVALID_PARAM);
+    VERIFY_NON_NULL_RET(TAG, credId, ERROR,  OC_STACK_INVALID_PARAM);
+
+    // It is temporary condition.
+    // 6144(6K) = 6 * 1024, generally, one Cert is less than 2k.
+    // because we use 3 Cert, 6K is enough size for saving Certs.
+    if (6144 <= chainSize)
     {
-        OIC_LOG(ERROR, TAG, "Failed to memory allocation");
-        return OC_STACK_NO_MEMORY;
+        OIC_LOG_V(ERROR, TAG, "chainSize(%u) is invalid", chainSize);
+        return OC_STACK_INVALID_PARAM;
     }
-    secPayload->base.type = PAYLOAD_TYPE_SECURITY;
-    OCStackResult res = CredToCBORPayload(cred, &secPayload->securityData,
-        &secPayload->payloadSize);
 
-    if ((OC_STACK_OK != res) || (NULL == secPayload->securityData))
+    OCStackResult res = OC_STACK_ERROR;
+
+    OicSecCred_t *cred = (OicSecCred_t *)OICCalloc(1, sizeof(*cred));
+    VERIFY_NON_NULL_RET(TAG, cred, ERROR, OC_STACK_NO_MEMORY);
+
+    res = GetDoxmDeviceID(&cred->subject);
+    if (OC_STACK_OK != res)
     {
-        OICFree(secPayload);
-        OIC_LOG(ERROR, TAG, "Failed to CredToCBORPayload");
-        return OC_STACK_NO_MEMORY;
+        OIC_LOG(ERROR, TAG, "Cann't get the device id(GetDoxmDeviceID)");
+        DeleteCredList(cred);
+        return res;
     }
 
-    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,
-                        deviceInfo->endpoint.addr,
-                        deviceInfo->securePort,
-                        deviceInfo->connType,
-                        query, sizeof(query), OIC_RSRC_CRED_URI))
+    cred->credUsage= (char *)OICCalloc(1, strlen(TRUST_CA)+1 );
+    VERIFY_NON_NULL_RET(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)
     {
-        OIC_LOG(ERROR, TAG, "DeviceDiscoveryHandler : Failed to generate query");
-        OCPayloadDestroy((OCPayload *)secPayload);
-        return OC_STACK_ERROR;
+        cred->optionalData.data = (uint8_t *)OICCalloc(1, chainSize + 1);
+        VERIFY_NON_NULL_RET(TAG, cred->optionalData.data, ERROR, OC_STACK_NO_MEMORY);
+        cred->optionalData.len = chainSize + 1;
     }
-    OIC_LOG_V(DEBUG, TAG, "Query=%s", query);
+    else
+    {
+        cred->optionalData.data = (uint8_t *)OICCalloc(1, chainSize);
+        VERIFY_NON_NULL_RET(TAG, cred->optionalData.data, ERROR, OC_STACK_NO_MEMORY);
+        cred->optionalData.len = chainSize;
+    }
+    memcpy(cred->optionalData.data, trustCertChain, chainSize);
+    cred->optionalData.encoding = encodingType;
+    cred->optionalData.revstat = false;
 
-    OCCallbackData cbData = {.context=NULL, .cb=NULL, .cd=NULL};
-    cbData.cb = responseHandler;
-    cbData.context = (void *) certData;
-    cbData.cd = NULL;
+    res = AddCredential(cred);
+    if(res != OC_STACK_OK)
+    {
+        DeleteCredList(cred);
+        return res;
+    }
+    *credId = cred->credId;
 
-    OCDoHandle handle = NULL;
-    OCMethod method = OC_REST_POST;
-    OCStackResult ret = OCDoResource(&handle, method, query, 0, (OCPayload*)secPayload,
-            deviceInfo->connType, OC_HIGH_QOS, &cbData, NULL, 0);
-    OIC_LOG_V(INFO, TAG, "OCDoResource::Certificate provisioning returned : %d",ret);
-    if (ret != OC_STACK_OK)
+    if (g_trustCertChainNotifier.callback)
     {
-        OIC_LOG(ERROR, TAG, "OCStack resource error");
+        uint8_t *certChain = (uint8_t*)OICCalloc(1, sizeof(uint8_t) * chainSize);
+        VERIFY_NON_NULL_RET(TAG, certChain, ERROR, OC_STACK_NO_MEMORY);
+        memcpy(certChain, trustCertChain, chainSize);
+        g_trustCertChainNotifier.callback(g_trustCertChainNotifier.context, *credId,
+                certChain, chainSize);
+        OICFree(certChain);
     }
 
-    return ret;
+    OIC_LOG(DEBUG, TAG, "OUT SRPSaveTrustCertChain");
+
+    return res;
 }
 
-/**
- * Callback handler for handling callback of certificate provisioning device.
- *
- * @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 provisionCertCB(void *ctx, OCDoHandle UNUSED,
-                                                       OCClientResponse *clientResponse)
+
+OCStackResult SRPSaveOwnCertChain(OicSecKey_t * cert, OicSecKey_t * key, uint16_t *credId)
 {
-    VERIFY_NON_NULL(TAG, ctx, ERROR, OC_STACK_DELETE_TRANSACTION);
-    CertData_t *certData = (CertData_t *) ctx;
-    (void)UNUSED;
+    OIC_LOG_V(DEBUG, TAG, "In %s", __func__);
+    VERIFY_NON_NULL_RET(TAG, cert, ERROR,  OC_STACK_INVALID_PARAM);
+    VERIFY_NON_NULL_RET(TAG, cert->data, ERROR,  OC_STACK_INVALID_PARAM);
+    VERIFY_NON_NULL_RET(TAG, key, ERROR,  OC_STACK_INVALID_PARAM);
+    VERIFY_NON_NULL_RET(TAG, key->data, ERROR,  OC_STACK_INVALID_PARAM);
+    VERIFY_NON_NULL_RET(TAG, credId, ERROR,  OC_STACK_INVALID_PARAM);
 
-    OCProvisionResultCB resultCallback = certData->resultCallback;
-    OIC_LOG(INFO, TAG, "provisionCertCred called");
-    if (clientResponse)
+    OCStackResult res = OC_STACK_ERROR;
+
+    OicSecCred_t *cred = (OicSecCred_t *)OICCalloc(1, sizeof(*cred));
+    VERIFY_NON_NULL_RET(TAG, cred, ERROR, OC_STACK_NO_MEMORY);
+
+    OIC_LOG_V(DEBUG, TAG, "IN: %s", __func__);
+
+    res = GetDoxmDeviceID(&cred->subject);
+    if (OC_STACK_OK != res)
     {
-        if(OC_STACK_RESOURCE_CREATED == clientResponse->result)
-        {
-            registerResultForCertProvisioning(certData, OC_STACK_RESOURCE_CREATED);
-            ((OCProvisionResultCB)(resultCallback))(certData->ctx, certData->numOfResults,
-                                                    certData->resArr,
-                                                    false);
-             OICFree(certData->resArr);
-             OICFree(certData);
-             return OC_STACK_DELETE_TRANSACTION;
-        }
+        OIC_LOG(ERROR, TAG, "Cann't get the device id(GetDoxmDeviceID)");
+        DeleteCredList(cred);
+        return res;
+    }
 
+    cred->credUsage= (char *)OICCalloc(1, strlen(PRIMARY_CERT)+1 );
+    VERIFY_NON_NULL_RET(TAG, cred->credUsage, ERROR, OC_STACK_NO_MEMORY);
+    OICStrcpy(cred->credUsage, strlen(PRIMARY_CERT) + 1, PRIMARY_CERT) ;
+
+    cred->credType = SIGNED_ASYMMETRIC_KEY;
+
+    OicSecKey_t *publicData = &cred->publicData;
+    publicData->data = (uint8_t *)OICCalloc(1, cert->len);
+    VERIFY_NON_NULL_RET(TAG, publicData->data, ERROR, OC_STACK_NO_MEMORY);
+    memcpy(publicData->data, cert->data, cert->len);
+    publicData->len = cert->len;
+    publicData->encoding = cert->encoding;
+
+    OicSecKey_t *privateData = &cred->privateData;
+    privateData->data = (uint8_t *)OICCalloc(1, key->len);
+    VERIFY_NON_NULL_RET(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;
     }
-    OIC_LOG(INFO, TAG, "provisionCertCredCB received Null clientResponse");
-    registerResultForCertProvisioning(certData, OC_STACK_ERROR);
-    ((OCProvisionResultCB)(resultCallback))(certData->ctx, certData->numOfResults,
-                                            certData->resArr,
-                                            true);
-    OICFree(certData->resArr);
-    OICFree(certData);
-    return OC_STACK_DELETE_TRANSACTION;
+    *credId = cred->credId;
+
+    OIC_LOG_V(DEBUG, TAG, "Out %s", __func__);
+
+    return res;
 }
-#endif // __WITH_X509__
+#endif // __WITH_DTLS__ || __WITH_TLS__
 
 OCStackResult SRPProvisionCredentials(void *ctx, OicSecCredType_t type, size_t keySize,
                                       const OCProvisionDev_t *pDev1,
                                       const OCProvisionDev_t *pDev2,
                                       OCProvisionResultCB resultCallback)
 {
-    VERIFY_NON_NULL(TAG, pDev1, ERROR,  OC_STACK_INVALID_PARAM);
+    VERIFY_NON_NULL_RET(TAG, pDev1, ERROR,  OC_STACK_INVALID_PARAM);
     if (SYMMETRIC_PAIR_WISE_KEY == type)
     {
-        VERIFY_NON_NULL(TAG, pDev2, ERROR,  OC_STACK_INVALID_PARAM);
+        VERIFY_NON_NULL_RET(TAG, pDev2, ERROR,  OC_STACK_INVALID_PARAM);
     }
     if (!resultCallback)
     {
@@ -694,7 +756,7 @@ OCStackResult SRPProvisionCredentials(void *ctx, OicSecCredType_t type, size_t k
             OCStackResult res = PMGeneratePairWiseCredentials(type, keySize, &provTooldeviceID,
                     &firstDevice->doxm->deviceID, &secondDevice->doxm->deviceID,
                     &firstCred, &secondCred);
-            VERIFY_SUCCESS(TAG, (res==OC_STACK_OK), ERROR, OC_STACK_ERROR);
+            VERIFY_SUCCESS_RET(TAG, (res==OC_STACK_OK), ERROR, OC_STACK_ERROR);
             OIC_LOG(INFO, TAG, "Credentials generated successfully");
             CredentialData_t *credData =
                 (CredentialData_t *) OICCalloc(1, sizeof(CredentialData_t));
@@ -734,53 +796,9 @@ OCStackResult SRPProvisionCredentials(void *ctx, OicSecCredType_t type, size_t k
                 OICFree(credData);
             }
             OIC_LOG_V(INFO, TAG, "provisionCredentials returned: %d",res);
-            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);
-
+            VERIFY_SUCCESS_RET(TAG, (res==OC_STACK_OK), ERROR, OC_STACK_ERROR);
             return res;
         }
-#endif
         default:
         {
             OIC_LOG(ERROR, TAG, "Invalid option.");
@@ -818,15 +836,15 @@ static OCStackApplicationResult SRPProvisionACLCB(void *ctx, OCDoHandle UNUSED,
 {
     OIC_LOG_V(INFO, TAG, "Inside SRPProvisionACLCB.");
     (void)UNUSED;
-    VERIFY_NON_NULL(TAG, ctx, ERROR, OC_STACK_DELETE_TRANSACTION);
+    VERIFY_NON_NULL_RET(TAG, ctx, ERROR, OC_STACK_DELETE_TRANSACTION);
     ACLData_t *aclData = (ACLData_t*)ctx;
     OCProvisionResultCB resultCallback = aclData->resultCallback;
 
     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);
@@ -848,9 +866,28 @@ static OCStackApplicationResult SRPProvisionACLCB(void *ctx, OCDoHandle UNUSED,
 OCStackResult SRPProvisionACL(void *ctx, const OCProvisionDev_t *selectedDeviceInfo,
         OicSecAcl_t *acl, OCProvisionResultCB resultCallback)
 {
-    VERIFY_NON_NULL(TAG, selectedDeviceInfo, ERROR,  OC_STACK_INVALID_PARAM);
-    VERIFY_NON_NULL(TAG, acl, ERROR,  OC_STACK_INVALID_PARAM);
-    VERIFY_NON_NULL(TAG, resultCallback, ERROR,  OC_STACK_INVALID_CALLBACK);
+    VERIFY_NON_NULL_RET(TAG, selectedDeviceInfo, ERROR,  OC_STACK_INVALID_PARAM);
+    VERIFY_NON_NULL_RET(TAG, acl, ERROR,  OC_STACK_INVALID_PARAM);
+    VERIFY_NON_NULL_RET(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)
@@ -865,6 +902,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,
@@ -913,10 +953,21 @@ OCStackResult SRPProvisionACL(void *ctx, const OCProvisionDev_t *selectedDeviceI
         OICFree(aclData->resArr);
         OICFree(aclData);
     }
-    VERIFY_SUCCESS(TAG, (OC_STACK_OK == ret), ERROR, OC_STACK_ERROR);
+    VERIFY_SUCCESS_RET(TAG, (OC_STACK_OK == ret), ERROR, OC_STACK_ERROR);
     return OC_STACK_OK;
 }
 
+OCStackResult SRPSaveACL(const OicSecAcl_t *acl)
+{
+    OIC_LOG(DEBUG, TAG, "IN SRPSaveACL");
+    VERIFY_NON_NULL_RET(TAG, acl, ERROR,  OC_STACK_INVALID_PARAM);
+
+    OCStackResult res =  InstallACL(acl);
+
+    OIC_LOG(DEBUG, TAG, "OUT SRPSaveACL");
+    return res;
+}
+
 /**
  * Internal Function to store results in result array during Direct-Pairing provisioning.
  */
@@ -945,13 +996,13 @@ static OCStackApplicationResult SRPProvisionDirectPairingCB(void *ctx, OCDoHandl
 {
     OIC_LOG_V(INFO, TAG, "Inside SRPProvisionDirectPairingCB.");
     (void)UNUSED;
-    VERIFY_NON_NULL(TAG, ctx, ERROR, OC_STACK_DELETE_TRANSACTION);
+    VERIFY_NON_NULL_RET(TAG, ctx, ERROR, OC_STACK_DELETE_TRANSACTION);
     PconfData_t *pconfData = (PconfData_t*)ctx;
     OCProvisionResultCB resultCallback = pconfData->resultCallback;
 
     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,
@@ -975,9 +1026,9 @@ static OCStackApplicationResult SRPProvisionDirectPairingCB(void *ctx, OCDoHandl
 OCStackResult SRPProvisionDirectPairing(void *ctx, const OCProvisionDev_t *selectedDeviceInfo,
         OicSecPconf_t *pconf, OCProvisionResultCB resultCallback)
 {
-    VERIFY_NON_NULL(TAG, selectedDeviceInfo, ERROR,  OC_STACK_INVALID_PARAM);
-    VERIFY_NON_NULL(TAG, pconf, ERROR,  OC_STACK_INVALID_PARAM);
-    VERIFY_NON_NULL(TAG, resultCallback, ERROR,  OC_STACK_INVALID_CALLBACK);
+    VERIFY_NON_NULL_RET(TAG, selectedDeviceInfo, ERROR,  OC_STACK_INVALID_PARAM);
+    VERIFY_NON_NULL_RET(TAG, pconf, ERROR,  OC_STACK_INVALID_PARAM);
+    VERIFY_NON_NULL_RET(TAG, resultCallback, ERROR,  OC_STACK_INVALID_CALLBACK);
 
     // check direct-pairing capability
     if (true != selectedDeviceInfo->doxm->dpc)
@@ -1061,7 +1112,7 @@ OCStackResult SRPProvisionDirectPairing(void *ctx, const OCProvisionDev_t *selec
         OICFree(pconfData->resArr);
         OICFree(pconfData);
     }
-    VERIFY_SUCCESS(TAG, (OC_STACK_OK == ret), ERROR, OC_STACK_ERROR);
+    VERIFY_SUCCESS_RET(TAG, (OC_STACK_OK == ret), ERROR, OC_STACK_ERROR);
     return OC_STACK_OK;
 }
 
@@ -1121,10 +1172,28 @@ static OCStackResult SendDeleteCredentialRequest(void* ctx,
         return OC_STACK_ERROR;
     }
 
+    char addressEncoded[CA_MAX_URI_LENGTH] = {0};
+    OCStackResult result = OCEncodeAddressForRFC6874(addressEncoded,
+                                                     sizeof(addressEncoded),
+                                                     destDev->endpoint.addr);
+    if (OC_STACK_OK != result)
+    {
+        OIC_LOG_V(ERROR, TAG, "SendDeleteCredentialRequest : encoding error %d\n", result);
+        return OC_STACK_ERROR;
+    }
+
     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,
+    const char *srpUri = SRP_FORM_DELETE_CREDENTIAL;
+#ifdef __WITH_TLS__
+    if(OC_ADAPTER_TCP == destDev->endpoint.adapter)
+    {
+        srpUri = SRP_FORM_DELETE_CREDENTIAL_TCP;
+    }
+#endif
+
+    snRet = snprintf(reqBuf, sizeof(reqBuf), srpUri, addressEncoded,
                      destDev->securePort, OIC_RSRC_CRED_URI, OIC_JSON_SUBJECTID_NAME, subID);
     OICFree(subID);
     if (snRet < 0)
@@ -1159,39 +1228,108 @@ 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)
 {
-    (void) handle;
-    OIC_LOG(DEBUG, TAG, "IN SRPUnlinkDevice2CB");
-    VERIFY_NON_NULL(TAG, unlinkCtx, ERROR, OC_STACK_DELETE_TRANSACTION);
-    UnlinkData_t* unlinkData = (UnlinkData_t*)unlinkCtx;
+    OIC_LOG(DEBUG, TAG, "IN SendDeleteACLRequest");
 
-    if (clientResponse)
+    if (NULL == ctx || NULL == respHandler || NULL == revokedDev || NULL == destDev)
     {
-        OIC_LOG(DEBUG, TAG, "Valid client response for device 2");
-        registerResultForUnlinkDevices(unlinkData, clientResponse->result, IDX_SECOND_DEVICE_RES);
-
-        if (OC_STACK_RESOURCE_DELETED == clientResponse->result)
-        {
-            OIC_LOG(DEBUG, TAG, "Credential of device2 revoked");
-        }
-        else
-        {
-            OIC_LOG(ERROR, TAG, "Unable to delete credential information from device 2");
-            unlinkData->resultCallback(unlinkData->ctx,
-                                       unlinkData->numOfResults, unlinkData->unlinkRes, true);
-            goto error;
-        }
+        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 addressEncoded[CA_MAX_URI_LENGTH] = {0};
+    OCStackResult result = OCEncodeAddressForRFC6874(addressEncoded,
+                                                     sizeof(addressEncoded),
+                                                     destDev->endpoint.addr);
+    if (OC_STACK_OK != result)
+    {
+        OIC_LOG_V(ERROR, TAG, "SendDeleteCredentialRequest : encoding error %d\n", result);
+        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, addressEncoded,
+                     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");
+    VERIFY_NON_NULL_RET(TAG, unlinkCtx, ERROR, OC_STACK_DELETE_TRANSACTION);
+    UnlinkData_t* unlinkData = (UnlinkData_t*)unlinkCtx;
+
+    if (clientResponse)
+    {
+        OIC_LOG(DEBUG, TAG, "Valid client response for device 2");
+        registerResultForUnlinkDevices(unlinkData, clientResponse->result, IDX_SECOND_DEVICE_RES);
+
+        if (OC_STACK_RESOURCE_DELETED == clientResponse->result)
+        {
+            OIC_LOG(DEBUG, TAG, "Credential of device2 revoked");
+        }
+        else
+        {
+            OIC_LOG(ERROR, TAG, "Unable to delete credential information from device 2");
+            unlinkData->resultCallback(unlinkData->ctx,
+                                       unlinkData->numOfResults, unlinkData->unlinkRes, true);
+            goto error;
+        }
     }
     else
     {
@@ -1236,7 +1374,7 @@ static OCStackApplicationResult SRPUnlinkDevice1CB(void *unlinkCtx, OCDoHandle h
         OCClientResponse *clientResponse)
 {
     OIC_LOG_V(INFO, TAG, "Inside SRPUnlinkDevice1CB ");
-    VERIFY_NON_NULL(TAG, unlinkCtx, ERROR, OC_STACK_DELETE_TRANSACTION);
+    VERIFY_NON_NULL_RET(TAG, unlinkCtx, ERROR, OC_STACK_DELETE_TRANSACTION);
     UnlinkData_t* unlinkData = (UnlinkData_t*)unlinkCtx;
     (void) handle;
 
@@ -1342,7 +1480,7 @@ OCStackResult SRPUnlinkDevices(void* ctx,
     }
 
     UnlinkData_t* unlinkData = (UnlinkData_t*)OICCalloc(1, sizeof(UnlinkData_t));
-    VERIFY_NON_NULL(TAG, unlinkData, ERROR, OC_STACK_NO_MEMORY);
+    VERIFY_NON_NULL_RET(TAG, unlinkData, ERROR, OC_STACK_NO_MEMORY);
 
     //Initialize unlink data
     unlinkData->ctx = ctx;
@@ -1432,6 +1570,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.
  *
@@ -1448,7 +1614,7 @@ static OCStackApplicationResult SRPRemoveDeviceCB(void *delDevCtx, OCDoHandle ha
     //Save the deleted status in delDevCtx
     (void)handle;
     OIC_LOG_V(INFO, TAG, "Inside SRPRemoveDeviceCB.");
-    VERIFY_NON_NULL(TAG, delDevCtx, ERROR, OC_STACK_DELETE_TRANSACTION);
+    VERIFY_NON_NULL_RET(TAG, delDevCtx, ERROR, OC_STACK_DELETE_TRANSACTION);
     OCStackResult res = OC_STACK_ERROR;
 
     RemoveData_t* removeData = (RemoveData_t*)delDevCtx;
@@ -1511,8 +1677,177 @@ 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_RET(TAG, delDevCtx, ERROR, OC_STACK_DELETE_TRANSACTION);
+    OCStackResult res = OC_STACK_ERROR;
+
+    RemoveData_t* removeData = (RemoveData_t*)delDevCtx;
+    OCProvisionDev_t * pTargetDev = PMCloneOCProvisionDev(removeData->revokeTargetDev);
+    OCClientContextDeleter deleteCallback = removeData->deleteCallback;
+    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, deleteCallback);
+
+    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 UNUSED,
+        OCClientResponse *clientResponse)
+{
+    (void)ctx;
+    (void)UNUSED;
+    (void)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] 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 SRPResetDeviceCB(void *ctx, OCDoHandle UNUSED,
+        OCClientResponse *clientResponse)
+{
+    OIC_LOG(DEBUG, TAG, "IN SRPResetDeviceCB");
+    (void)UNUSED;
+    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,
+                                                 const OCProvisionDev_t* pOwnedDevList,
                                                  OCUuidList_t* pLinkedUuidList,
                                                  OCProvisionDev_t** ppLinkedDevList,
                                                  size_t *numOfLinkedDev)
@@ -1533,13 +1868,14 @@ static OCStackResult GetListofDevToReqDeleteCred(const OCProvisionDev_t* pRevoke
         if (OC_STACK_OK != res)
         {
             OIC_LOG(FATAL, TAG, "PDMSetLinkStale() FAIL: PDB is an obsolete one.");
-            return OC_STACK_INCONSISTENT_DB;
+            return OC_STACK_SVR_DB_NOT_EXIST;
         }
 
         if (pOwnedDevList)
         {
             // If this linked device is alive (power-on), add the deivce to the list.
-            OCProvisionDev_t *curDev = NULL, *tmpDev = NULL;
+            const OCProvisionDev_t *curDev = NULL;
+            const OCProvisionDev_t *tmpDev = NULL;
             LL_FOREACH_SAFE(pOwnedDevList, curDev, tmpDev)
             {
                 if (memcmp(curDev->doxm->deviceID.id, curUuid->dev.id, sizeof(curUuid->dev.id)) == 0)
@@ -1709,3 +2045,680 @@ error:
     OIC_LOG(INFO, TAG, "OUT ERROR case SRPRemoveDevice");
     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,
+        OCClientContextDeleter deleteCallback)
+{
+    OIC_LOG(INFO, TAG, "IN SRPResetDevice");
+    if (!pTargetDev)
+    {
+        OIC_LOG(INFO, TAG, "SRPResetDevice : NULL parameters");
+        return OC_STACK_INVALID_PARAM;
+    }
+    if (!deleteCallback)
+    {
+        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 = deleteCallback;
+    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.
+ */
+static void registerResultForGetCredResourceCB(GetSecData_t *GetSecData,
+                                             OCStackResult stackresult)
+{
+   OIC_LOG_V(INFO, TAG, "Inside registerResultForGetCredResourceCB "
+           "GetSecData->numOfResults is %d\n", GetSecData->numOfResults);
+   memcpy(GetSecData->resArr[(GetSecData->numOfResults)].deviceId.id,
+          GetSecData->deviceInfo->doxm->deviceID.id, UUID_LENGTH);
+   GetSecData->resArr[(GetSecData->numOfResults)].res = stackresult;
+   ++(GetSecData->numOfResults);
+}
+
+/**
+ * Callback handler of SRPGetCredResource.
+ *
+ * @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 SRPGetCredResourceCB(void *ctx, OCDoHandle UNUSED,
+                                                  OCClientResponse *clientResponse)
+{
+    OIC_LOG_V(INFO, TAG, "Inside SRPGetCredResourceCB.");
+    (void)UNUSED;
+    VERIFY_NON_NULL_RET(TAG, ctx, ERROR, OC_STACK_DELETE_TRANSACTION);
+    GetSecData_t *GetSecData = (GetSecData_t*)ctx;
+    OCProvisionResultCB resultCallback = GetSecData->resultCallback;
+
+    if (clientResponse)
+    {
+        if(OC_STACK_OK == clientResponse->result)
+        {
+            uint8_t *payload = ((OCSecurityPayload*)clientResponse->payload)->securityData;
+            size_t size = ((OCSecurityPayload*)clientResponse->payload)->payloadSize;
+
+            OIC_LOG_BUFFER(DEBUG, TAG, payload, size);
+            (void)size;
+            (void)payload;
+
+            registerResultForGetCredResourceCB(GetSecData, OC_STACK_OK);
+            ((OCProvisionResultCB)(resultCallback))(GetSecData->ctx, GetSecData->numOfResults,
+                                                    GetSecData->resArr,
+                                                    false);
+             OICFree(GetSecData->resArr);
+             OICFree(GetSecData);
+
+            return OC_STACK_DELETE_TRANSACTION;
+        }
+    }
+    registerResultForGetCredResourceCB(GetSecData, OC_STACK_OK);
+    ((OCProvisionResultCB)(resultCallback))(GetSecData->ctx, GetSecData->numOfResults,
+                                            GetSecData->resArr,
+                                            false);
+    OIC_LOG_V(ERROR, TAG, "SRPGetCredResourceCB received Null clientResponse");
+    OICFree(GetSecData->resArr);
+    OICFree(GetSecData);
+
+    return OC_STACK_DELETE_TRANSACTION;
+}
+
+
+OCStackResult SRPGetCredResource(void *ctx, const OCProvisionDev_t *selectedDeviceInfo,
+        OCProvisionResultCB resultCallback)
+{
+    VERIFY_NON_NULL_RET(TAG, selectedDeviceInfo, ERROR,  OC_STACK_INVALID_PARAM);
+    VERIFY_NON_NULL_RET(TAG, resultCallback, ERROR,  OC_STACK_INVALID_CALLBACK);
+
+    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, "SRPGetCredResource : 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 = &SRPGetCredResourceCB;
+    GetSecData_t* GetSecData = (GetSecData_t*)OICCalloc(1, sizeof(GetSecData_t));
+    if (NULL == GetSecData)
+    {
+        OIC_LOG(ERROR, TAG, "Unable to allocate memory");
+        return OC_STACK_NO_MEMORY;
+    }
+    GetSecData->deviceInfo = selectedDeviceInfo;
+    GetSecData->resultCallback = resultCallback;
+    GetSecData->numOfResults=0;
+    GetSecData->ctx = ctx;
+
+    int noOfRiCalls = 1;
+    GetSecData->resArr = (OCProvisionResult_t*)OICCalloc(noOfRiCalls, sizeof(OCProvisionResult_t));
+    if (NULL == GetSecData->resArr)
+    {
+        OICFree(GetSecData);
+        OIC_LOG(ERROR, TAG, "Unable to allocate memory");
+        return OC_STACK_NO_MEMORY;
+    }
+    cbData.context = (void *)GetSecData;
+    cbData.cd = NULL;
+    OCMethod method = OC_REST_GET;
+    OCDoHandle handle = NULL;
+    OIC_LOG(DEBUG, TAG, "Sending Get Cred to  resource server");
+    OCStackResult ret = OCDoResource(&handle, method, query, NULL, NULL,
+            selectedDeviceInfo->connType, OC_HIGH_QOS, &cbData, NULL, 0);
+    if (OC_STACK_OK != ret)
+    {
+        OIC_LOG(ERROR, TAG, "OCStack resource error");
+        OICFree(GetSecData->resArr);
+        OICFree(GetSecData);
+    }
+    VERIFY_SUCCESS_RET(TAG, (OC_STACK_OK == ret), ERROR, OC_STACK_ERROR);
+    OIC_LOG(DEBUG, TAG, "OUT SRPGetCredResource");
+
+    return OC_STACK_OK;
+}
+
+/**
+ * Internal Function to store results in result array during GetACLResourceCB.
+ */
+static void registerResultForGetACLResourceCB(GetSecData_t *GetSecData,
+                                             OCStackResult stackresult)
+{
+   OIC_LOG_V(INFO, TAG, "Inside registerResultForGetACLResourceCB "
+           "GetSecData->numOfResults is %d\n", GetSecData->numOfResults);
+   memcpy(GetSecData->resArr[(GetSecData->numOfResults)].deviceId.id,
+          GetSecData->deviceInfo->doxm->deviceID.id, UUID_LENGTH);
+   GetSecData->resArr[(GetSecData->numOfResults)].res = stackresult;
+   ++(GetSecData->numOfResults);
+}
+
+/**
+ * Callback handler of SRPGetACLResource.
+ *
+ * @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 SRPGetACLResourceCB(void *ctx, OCDoHandle UNUSED,
+                                                  OCClientResponse *clientResponse)
+{
+    OIC_LOG_V(INFO, TAG, "Inside SRPGetACLResourceCB.");
+    (void)UNUSED;
+    VERIFY_NON_NULL_RET(TAG, ctx, ERROR, OC_STACK_DELETE_TRANSACTION);
+    GetSecData_t *GetSecData = (GetSecData_t*)ctx;
+    OCProvisionResultCB resultCallback = GetSecData->resultCallback;
+
+    if (clientResponse)
+    {
+        if(OC_STACK_OK == clientResponse->result)
+        {
+            uint8_t *payload = ((OCSecurityPayload*)clientResponse->payload)->securityData;
+            size_t size = ((OCSecurityPayload*)clientResponse->payload)->payloadSize;
+
+            OIC_LOG_BUFFER(DEBUG, TAG, payload, size);
+            (void)payload;
+            (void)size;
+
+            registerResultForGetACLResourceCB(GetSecData, OC_STACK_OK);
+            ((OCProvisionResultCB)(resultCallback))(GetSecData->ctx, GetSecData->numOfResults,
+                                                    GetSecData->resArr,
+                                                    false);
+             OICFree(GetSecData->resArr);
+             OICFree(GetSecData);
+
+            return OC_STACK_DELETE_TRANSACTION;
+        }
+    }
+    registerResultForGetACLResourceCB(GetSecData, OC_STACK_OK);
+    ((OCProvisionResultCB)(resultCallback))(GetSecData->ctx, GetSecData->numOfResults,
+                                            GetSecData->resArr,
+                                            false);
+    OIC_LOG_V(ERROR, TAG, "SRPGetACLResourceCB received Null clientResponse");
+    OICFree(GetSecData->resArr);
+    OICFree(GetSecData);
+
+    return OC_STACK_DELETE_TRANSACTION;
+}
+
+
+OCStackResult SRPGetACLResource(void *ctx, const OCProvisionDev_t *selectedDeviceInfo,
+        OCProvisionResultCB resultCallback)
+{
+    VERIFY_NON_NULL_RET(TAG, selectedDeviceInfo, ERROR,  OC_STACK_INVALID_PARAM);
+    VERIFY_NON_NULL_RET(TAG, resultCallback, ERROR,  OC_STACK_INVALID_CALLBACK);
+
+    char query[MAX_URI_LENGTH + MAX_QUERY_LENGTH] = {0};
+    if(!PMGenerateQuery(true,
+                        selectedDeviceInfo->endpoint.addr,
+                        selectedDeviceInfo->securePort,
+                        selectedDeviceInfo->connType,
+                        query, sizeof(query), OIC_RSRC_ACL_URI))
+    {
+        OIC_LOG(ERROR, TAG, "SRPGetACLResource : 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 = &SRPGetACLResourceCB;
+    GetSecData_t* GetSecData = (GetSecData_t*)OICCalloc(1, sizeof(GetSecData_t));
+    if (NULL == GetSecData)
+    {
+        OIC_LOG(ERROR, TAG, "Unable to allocate memory");
+        return OC_STACK_NO_MEMORY;
+    }
+    GetSecData->deviceInfo = selectedDeviceInfo;
+    GetSecData->resultCallback = resultCallback;
+    GetSecData->numOfResults=0;
+    GetSecData->ctx = ctx;
+
+    int noOfRiCalls = 1;
+    GetSecData->resArr = (OCProvisionResult_t*)OICCalloc(noOfRiCalls, sizeof(OCProvisionResult_t));
+    if (NULL == GetSecData->resArr)
+    {
+        OICFree(GetSecData);
+        OIC_LOG(ERROR, TAG, "Unable to allocate memory");
+        return OC_STACK_NO_MEMORY;
+    }
+    cbData.context = (void *)GetSecData;
+    cbData.cd = NULL;
+    OCMethod method = OC_REST_GET;
+    OCDoHandle handle = NULL;
+    OIC_LOG(DEBUG, TAG, "Sending Get ACL to resource server");
+    OCStackResult ret = OCDoResource(&handle, method, query, NULL, NULL,
+            selectedDeviceInfo->connType, OC_HIGH_QOS, &cbData, NULL, 0);
+    if (OC_STACK_OK != ret)
+    {
+        OIC_LOG(ERROR, TAG, "OCStack resource error");
+        OICFree(GetSecData->resArr);
+        OICFree(GetSecData);
+    }
+    VERIFY_SUCCESS_RET(TAG, (OC_STACK_OK == ret), ERROR, OC_STACK_ERROR);
+    OIC_LOG(DEBUG, TAG, "OUT SRPGetACLResource");
+
+    return OC_STACK_OK;
+}
+
+OCStackResult SRPReadTrustCertChain(uint16_t credId, uint8_t **trustCertChain,
+                                     size_t *chainSize)
+{
+    OIC_LOG(DEBUG, TAG, "IN SRPReadTrustCertChain");
+
+    OCStackResult res = OC_STACK_ERROR;
+    int secureFlag = 0;
+    OicSecCred_t* credData = GetCredEntryByCredId(credId);
+    if(credData)
+    {
+        res = CredToCBORPayload((const OicSecCred_t*) credData, trustCertChain,
+                                chainSize, secureFlag);
+        if(OC_STACK_OK != res)
+        {
+            OIC_LOG(INFO, TAG, "CredToCBORPayload failed");
+        }
+    }
+    DeleteCredList(credData);
+    return res;
+}