Remote Reset
authorJongmin Choi <jminl.choi@samsung.com>
Thu, 23 Jun 2016 06:46:27 +0000 (15:46 +0900)
committerRandeep Singh <randeep.s@samsung.com>
Wed, 20 Jul 2016 06:02:30 +0000 (06:02 +0000)
Create Reset Profile and Remote Reset by Provisioning Tool

Patch #2: Changes according to Ashwini's Comments
Patch #3: RemoveACE prototype added to header file

Change-Id: I6f4c443e8b54c5e0640da868cf7f2c5fbd4db78d
Signed-off-by: Jongmin Choi <jminl.choi@samsung.com>
Reviewed-on: https://gerrit.iotivity.org/gerrit/8915
Tested-by: jenkins-iotivity <jenkins-iotivity@opendaylight.org>
Reviewed-by: Randeep Singh <randeep.s@samsung.com>
12 files changed:
resource/csdk/security/include/internal/aclresource.h
resource/csdk/security/include/internal/psinterface.h
resource/csdk/security/include/internal/srmresourcestrings.h
resource/csdk/security/provisioning/include/internal/secureresourceprovider.h
resource/csdk/security/provisioning/sample/provisioningclient.c
resource/csdk/security/provisioning/src/ocprovisioningmanager.c
resource/csdk/security/provisioning/src/secureresourceprovider.c
resource/csdk/security/src/aclresource.c
resource/csdk/security/src/psinterface.c
resource/csdk/security/src/pstatresource.c
resource/csdk/security/src/srmresourcestrings.c
resource/csdk/stack/src/ocstack.c

index 2b83f81..7daf51f 100644 (file)
@@ -63,6 +63,19 @@ const OicSecAce_t* GetACLResourceData(const OicUuid_t* subjectId, OicSecAce_t **
 OCStackResult AclToCBORPayload(const OicSecAcl_t * acl, uint8_t **outPayload, size_t *size);
 
 /**
+ * This method removes ACE for the subject and resource from the ACL
+ *
+ * @param subject of the ACE
+ * @param resource of the ACE
+ *
+ * @return
+ *     ::OC_STACK_RESOURCE_DELETED on success
+ *     ::OC_STACK_NO_RESOURCE on failure to find the appropriate ACE
+ *     ::OC_STACK_INVALID_PARAM on invalid parameter
+ */
+OCStackResult RemoveACE(const OicUuid_t * subject, const char * resource);
+
+/**
  * This function deletes ACL data.
  *
  * @param acl instance of @ref OicSecAcl_t structure to be deleted.
index 34a7822..493690a 100644 (file)
@@ -71,4 +71,21 @@ OCStackResult GetSecureVirtualDatabaseFromPS(const char *rsrcName, uint8_t **dat
  */
 OCStackResult UpdateSecureResourceInPS(const char* rsrcName, uint8_t* cborPayload, size_t size);
 
+/**
+ * This method resets the secure resources according to the reset profile.
+ *
+ * @return ::OC_STACK_OK for Success, otherwise some error value
+ */
+OCStackResult ResetSecureResourceInPS(void);
+
+/**
+ * This method creates the reset profile from the persistent storage.
+ * The reset profile is the copy of the initial state of SVR resources
+ * when secure resources are initiated at first.
+ * In remote reset, the SVR will be reset according to the reset profile.
+ *
+ * @return ::OC_STACK_OK for Success, otherwise some error value
+ */
+OCStackResult CreateResetProfile(void);
+
 #endif //IOTVT_SRM_PSI_H
index 7e84a76..d9e8de8 100644 (file)
@@ -89,6 +89,9 @@ extern const char * OIC_RSRC_TYPE_SEC_VER;
 extern const char * OIC_RSRC_VER_URI;
 extern const char * OIC_JSON_VER_NAME;
 
+//reset profile
+extern const char * OIC_JSON_RESET_PF_NAME;
+
 extern const char * OIC_JSON_SUBJECT_NAME;
 extern const char * OIC_JSON_SUBJECTID_NAME;
 extern const char * OIC_JSON_RESOURCES_NAME;
index fe4e546..5fbc284 100644 (file)
@@ -152,6 +152,39 @@ OCStackResult SRPRemoveDevice(void* ctx,
                               const OCProvisionDev_t* pTargetDev,
                               OCProvisionResultCB resultCallback);
 
+/*
+ * 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);
+
+/*
+ * Function for remote reset
+ * This function will send pstat POST(modify) message to the target device
+ * to change current mode to reset state in order 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);
+
 #ifdef __cplusplus
 }
 #endif
index a22e393..a2dc06c 100644 (file)
@@ -50,11 +50,12 @@ extern "C"
 #define _30_PROVIS_PAIR_DEVS_   30
 #define _31_PROVIS_CRED_        31
 #define _32_PROVIS_ACL_         32
-#define _33_PROVIS_DP_           33
+#define _33_PROVIS_DP_          33
 #define _34_CHECK_LINK_STATUS_  34
 #define _40_UNLINK_PAIR_DEVS_   40
 #define _50_REMOVE_SELEC_DEV_   50
-#define _60_GET_CRED_  60
+#define _51_RESET_SELEC_DEV_    51
+#define _60_GET_CRED_           60
 #define _61_GET_ACL_            61
 #define _99_EXIT_PRVN_CLT_      99
 
@@ -226,6 +227,20 @@ static void removeDeviceCB(void* ctx, int nOfRes, OCProvisionResult_t* arr, bool
     g_doneCB = true;
 }
 
+static void syncDeviceCB(void* ctx, int nOfRes, OCProvisionResult_t* arr, bool hasError)
+{
+    if(!hasError)
+    {
+        OIC_LOG_V(INFO, TAG, "Sync Device SUCCEEDED - ctx: %s", (char*) ctx);
+    }
+    else
+    {
+        OIC_LOG_V(ERROR, TAG, "Sync Device FAILED - ctx: %s", (char*) ctx);
+        printResultList((const OCProvisionResult_t*) arr, nOfRes);
+    }
+    g_doneCB = true;
+}
+
 static void inputPinCB(char* pin, size_t len)
 {
     if(!pin || OXM_RANDOM_PIN_SIZE>=len)
@@ -1031,6 +1046,58 @@ static int removeDevice(void)
     return 0;
 }
 
+static int resetDevice(void)
+{
+    // check |own_list| for removing device
+    if (!g_own_list || 1 > g_own_cnt)
+    {
+        printf("   > Owned Device List, to Reset Device, is Empty\n");
+        printf("   > Please Register Unowned Devices first, with [20] Menu\n");
+        return 0;
+    }
+
+    // select device for removing it
+    int dev_num = 0;
+    for ( ; ; )
+    {
+        printf("   > Enter Device Number, for Resetting Device: ");
+        for (int ret = 0; 1 != ret; )
+        {
+            ret = scanf("%d", &dev_num);
+            for ( ; 0x20 <= getchar() ; );  // for removing overflow garbages
+                                            // '0x20 <= code' is character region
+        }
+        if (0 < dev_num && g_own_cnt >= dev_num)
+        {
+            break;
+        }
+        printf("     Entered Wrong Number. Please Enter Again\n");
+    }
+
+    g_doneCB = false;
+    printf("   Resetting Selected Owned Device..\n");
+
+    OCStackResult rst = OCResetDevice((void *) g_ctx, DISCOVERY_TIMEOUT,
+                    getDevInst((const OCProvisionDev_t *) g_own_list, dev_num), syncDeviceCB);
+    if (OC_STACK_OK != rst)
+    {
+        OIC_LOG_V(ERROR, TAG, "OCResetDevice API error: %d", rst);
+        return -1;
+    }
+
+    if (waitCallbackRet())  // input |g_doneCB| flag implicitly
+    {
+        OIC_LOG(ERROR, TAG, "OCProvisionCredentials callback error");
+        return -1;
+    }
+
+    // display the removed result
+    printf("   > Reset Selected Owned Device SUCCEEDED\n");
+    printf("   > Please Discover Owned Devices for the Registered Result, with [10|12] Menu\n");
+
+    return 0;
+}
+
 static OicSecAcl_t* createAcl(const int dev_num)
 {
     if(0>=dev_num || g_own_cnt<dev_num)
@@ -1492,7 +1559,8 @@ static void printMenu(void)
     printf("** 40. Unlink Pairwise Things\n\n");
 
     printf("** [E] REMOVE THE SELECTED DEVICE\n");
-    printf("** 50. Remove the Selected Device\n\n");
+    printf("** 50. Remove the Selected Device\n");
+    printf("** 51. Reset the Selected Device\n\n");
 
     printf("** [F] GET SECURITY RESOURCE FOR DEBUGGING ONLY\n");
     printf("** 60. Get the Credential resources of the Selected Device\n");
@@ -1616,6 +1684,12 @@ int main()
                 OIC_LOG(ERROR, TAG, "_50_REMOVE_SELEC_DEV_: error");
             }
             break;
+        case _51_RESET_SELEC_DEV_:
+            if(resetDevice())
+            {
+                OIC_LOG(ERROR, TAG, "_51_RESET_SELEC_DEV_: error");
+            }
+            break;
         case _60_GET_CRED_:
             if(getCred())
             {
index ad8133d..488903d 100644 (file)
@@ -407,6 +407,53 @@ error:
     return res;
 }
 
+/*
+ * Function to reset 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.
+ * @return  OC_STACK_OK in case of success and other value otherwise.
+ */
+OCStackResult OCResetDevice(void* ctx, unsigned short waitTimeForOwnedDeviceDiscovery,
+                            const OCProvisionDev_t* pTargetDev,
+                            OCProvisionResultCB resultCallback)
+{
+    OIC_LOG(INFO, TAG, "IN OCResetDevice");
+    OCStackResult res = OC_STACK_ERROR;
+    if (!pTargetDev || 0 == waitTimeForOwnedDeviceDiscovery)
+    {
+        OIC_LOG(INFO, TAG, "OCResetDevice : Invalid parameters");
+        return OC_STACK_INVALID_PARAM;
+    }
+    if (!resultCallback)
+    {
+        OIC_LOG(INFO, TAG, "OCResetDevice : NULL Callback");
+        return OC_STACK_INVALID_CALLBACK;
+    }
+
+    // Send DELETE requests to linked devices
+    res = SRPSyncDevice(ctx, waitTimeForOwnedDeviceDiscovery, pTargetDev, resultCallback);
+    if (OC_STACK_CONTINUE == res)
+    {
+        OIC_LOG(DEBUG, TAG, "OCResetDevice : Target device has no linked device except PT.");
+        if(resultCallback)
+        {
+            resultCallback(ctx, 0, NULL, false);
+        }
+        SRPResetDevice(pTargetDev, resultCallback);
+        res = OC_STACK_OK;
+    }
+    else if(OC_STACK_OK != res)
+    {
+        OIC_LOG(ERROR, TAG, "OCResetDevice : Failed to invoke SRPSyncDevice");
+    }
+    OIC_LOG(INFO, TAG, "OUT OCResetDevice");
+    return res;
+}
 
 /**
  * Internal Function to update result in link result array.
index 35aebec..a51bd37 100644 (file)
@@ -1177,6 +1177,64 @@ static OCStackResult SendDeleteCredentialRequest(void* ctx,
     return ret;
 }
 
+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.
  *
@@ -1450,6 +1508,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.
  *
@@ -1529,6 +1615,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 = CACloseDtlsSession(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,
@@ -1728,6 +1979,270 @@ error:
     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 = (OicSecDpm_t) 1;
+    pstat->isOp = 0;
+    memcpy(pstat->deviceID.id, pTargetDev->doxm->deviceID.id, sizeof(OicUuid_t));
+    pstat->tm = (OicSecDpm_t) 2;
+    pstat->om = (OicSecDpom_t) 0;
+    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) 3;
+
+    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)))
+    {
+        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);
+
+    OCProvisionDev_t * targetDev = PMCloneOCProvisionDev(pTargetDev);
+    OCCallbackData cbData = { .context = NULL, .cb = NULL, .cd = NULL };
+    cbData.cb = &SRPResetDeviceCB;
+    cbData.context = (void *) targetDev;
+    cbData.cd = NULL;
+    OCMethod method = OC_REST_POST;
+    OCDoHandle handle = 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.
  */
index 9537efc..e3aef30 100644 (file)
@@ -949,7 +949,7 @@ exit:
  *     ::OC_STACK_NO_RESOURCE on failure to find the appropriate ACE
  *     ::OC_STACK_INVALID_PARAM on invalid parameter
  */
-static OCStackResult RemoveACE(const OicUuid_t * subject, const char * resource)
+OCStackResult RemoveACE(const OicUuid_t * subject, const char * resource)
 {
     OIC_LOG(DEBUG, TAG, "IN RemoveACE");
 
index d263892..7043f81 100644 (file)
@@ -36,6 +36,8 @@
 #include "secureresourcemanager.h"
 #include "srmresourcestrings.h"
 #include "srmutility.h"
+#include "pstatresource.h"
+#include "doxmresource.h"
 
 #define TAG  "SRM-PSI"
 
@@ -180,6 +182,7 @@ OCStackResult UpdateSecureResourceInPS(const char *rsrcName, const uint8_t *psPa
     uint8_t *svcCbor = NULL;
     uint8_t *credCbor = NULL;
     uint8_t *pconfCbor = NULL;
+    uint8_t *resetPfCbor = NULL;
 
     int64_t cborEncoderResult = CborNoError;
     OCStackResult ret = GetSecureVirtualDatabaseFromPS(NULL, &dbData, &dbSize);
@@ -192,6 +195,7 @@ OCStackResult UpdateSecureResourceInPS(const char *rsrcName, const uint8_t *psPa
         size_t svcCborLen = 0;
         size_t credCborLen = 0;
         size_t pconfCborLen = 0;
+        size_t resetPfCborLen = 0;
 
         // Gets each secure virtual resource from persistent storage
         // this local scoping intended, for destroying large cbor instances after use
@@ -244,13 +248,20 @@ OCStackResult UpdateSecureResourceInPS(const char *rsrcName, const uint8_t *psPa
                 cborFindResult = cbor_value_dup_byte_string(&curVal, &pconfCbor, &pconfCborLen, NULL);
                 VERIFY_CBOR_SUCCESS(TAG, cborFindResult, "Failed Finding PCONF Name Value.");
             }
+            cborFindResult = cbor_value_map_find_value(&cbor, OIC_JSON_RESET_PF_NAME, &curVal);
+            if (CborNoError == cborFindResult && cbor_value_is_byte_string(&curVal))
+            {
+                cborFindResult = cbor_value_dup_byte_string(&curVal, &resetPfCbor, &resetPfCborLen, NULL);
+                VERIFY_CBOR_SUCCESS(TAG, cborFindResult, "Failed Finding Reset Profile Name Value.");
+            }
         }
 
         // Updates the added |psPayload| with the existing secure virtual resource(s)
         // this local scoping intended, for destroying large cbor instances after use
         {
             size_t size = aclCborLen + pstatCborLen + doxmCborLen + amaclCborLen
-                        + svcCborLen + credCborLen + pconfCborLen + psSize + 255;
+                        + svcCborLen + credCborLen + pconfCborLen + resetPfCborLen
+                        + psSize + 255;
             // This added '255' is arbitrary value that is added to cover the name of the resource, map addition and ending
 
             outPayload = (uint8_t *) OICCalloc(1, size);
@@ -317,6 +328,13 @@ OCStackResult UpdateSecureResourceInPS(const char *rsrcName, const uint8_t *psPa
                 cborEncoderResult |= cbor_encode_byte_string(&secRsrc, pconfCbor, pconfCborLen);
                 VERIFY_CBOR_SUCCESS(TAG, cborEncoderResult, "Failed Adding Pconf Value.");
             }
+            if (strcmp(OIC_JSON_RESET_PF_NAME, rsrcName) && resetPfCborLen)
+            {
+                cborEncoderResult |= cbor_encode_text_string(&secRsrc, OIC_JSON_RESET_PF_NAME, strlen(OIC_JSON_RESET_PF_NAME));
+                VERIFY_CBOR_SUCCESS(TAG, cborEncoderResult, "Failed Adding Reset Profile Name.");
+                cborEncoderResult |= cbor_encode_byte_string(&secRsrc, resetPfCbor, resetPfCborLen);
+                VERIFY_CBOR_SUCCESS(TAG, cborEncoderResult, "Failed Adding Reset Profile Value.");
+            }
 
             cborEncoderResult |= cbor_encoder_close_container(&encoder, &secRsrc);
             VERIFY_CBOR_SUCCESS(TAG, cborEncoderResult, "Failed Closing Array.");
@@ -348,7 +366,7 @@ OCStackResult UpdateSecureResourceInPS(const char *rsrcName, const uint8_t *psPa
 
     if (outPayload && outSize)
     {
-        OIC_LOG_V(DEBUG, TAG, "Writting in the file: %zu", outSize);
+        OIC_LOG_V(DEBUG, TAG, "Writing in the file: %zu", outSize);
         OCPersistentStorage* ps = SRMGetPersistentStorageHandler();
         if (ps)
         {
@@ -386,5 +404,290 @@ exit:
     OICFree(svcCbor);
     OICFree(credCbor);
     OICFree(pconfCbor);
+    OICFree(resetPfCbor);
+    return ret;
+}
+
+/**
+ * Resets the Secure Virtual Resource(s).
+ * This function reads the Reset Profile
+ * and resets the secure virtual resources accordingly.
+ *
+ * @return OCStackResult - result of updating Secure Virtual Resource(s)
+ */
+OCStackResult ResetSecureResourceInPS(void)
+{
+    OIC_LOG(DEBUG, TAG, "ResetSecureResourceInPS IN");
+
+    size_t dbSize = 0;
+    size_t outSize = 0;
+    uint8_t *dbData = NULL;
+    uint8_t *outPayload = NULL;
+
+    uint8_t *aclCbor = NULL;
+    uint8_t *pstatCbor = NULL;
+    uint8_t *doxmCbor = NULL;
+    uint8_t *resetPfCbor = NULL;
+
+    int64_t cborEncoderResult = CborNoError;
+    OCStackResult ret = GetSecureVirtualDatabaseFromPS(NULL, &dbData, &dbSize);
+
+    if(dbData && dbSize)
+    {
+        size_t aclCborLen = 0;
+        size_t pstatCborLen = 0;
+        size_t doxmCborLen = 0;
+        size_t resetPfCborLen = 0;
+
+        // Gets the reset profile from persistent storage
+        {
+            CborParser parser;  // will be initialized in |cbor_parser_init|
+            CborValue cbor;     // will be initialized in |cbor_parser_init|
+            cbor_parser_init(dbData, dbSize, 0, &parser, &cbor);
+            CborValue curVal = {0};
+            CborError cborFindResult = CborNoError;
+            cborFindResult = cbor_value_map_find_value(&cbor, OIC_JSON_RESET_PF_NAME, &curVal);
+            if (CborNoError == cborFindResult && cbor_value_is_byte_string(&curVal))
+            {
+                cborFindResult = cbor_value_dup_byte_string(&curVal, &resetPfCbor, &resetPfCborLen, NULL);
+                VERIFY_CBOR_SUCCESS(TAG, cborFindResult, "Failed Finding Reset Profile Name Value.");
+            }
+        }
+
+        // Gets each secure virtual resource from the reset profile
+        {
+            CborParser parser;  // will be initialized in |cbor_parser_init|
+            CborValue cbor;     // will be initialized in |cbor_parser_init|
+            cbor_parser_init(resetPfCbor, resetPfCborLen, 0, &parser, &cbor);
+            CborValue curVal = {0};
+            CborError cborFindResult = CborNoError;
+            cborFindResult = cbor_value_map_find_value(&cbor, OIC_JSON_ACL_NAME, &curVal);
+            if (CborNoError == cborFindResult && cbor_value_is_byte_string(&curVal))
+            {
+                cborFindResult = cbor_value_dup_byte_string(&curVal, &aclCbor, &aclCborLen, NULL);
+                VERIFY_CBOR_SUCCESS(TAG, cborFindResult, "Failed Finding ACL Name Value.");
+            }
+            cborFindResult = cbor_value_map_find_value(&cbor, OIC_JSON_PSTAT_NAME, &curVal);
+            if (CborNoError == cborFindResult && cbor_value_is_byte_string(&curVal))
+            {
+                cborFindResult = cbor_value_dup_byte_string(&curVal, &pstatCbor, &pstatCborLen, NULL);
+                VERIFY_CBOR_SUCCESS(TAG, cborFindResult, "Failed Finding PSTAT Name Value.");
+            }
+            cborFindResult = cbor_value_map_find_value(&cbor, OIC_JSON_DOXM_NAME, &curVal);
+            if (CborNoError == cborFindResult && cbor_value_is_byte_string(&curVal))
+            {
+                cborFindResult = cbor_value_dup_byte_string(&curVal, &doxmCbor, &doxmCborLen, NULL);
+                VERIFY_CBOR_SUCCESS(TAG, cborFindResult, "Failed Finding DOXM Name Value.");
+            }
+        }
+
+        {
+            size_t size = aclCborLen + pstatCborLen + doxmCborLen + resetPfCborLen + 255;
+            // This added '255' is arbitrary value added to cover the name of the resource, map addition, and ending
+
+            outPayload = (uint8_t *) OICCalloc(1, size);
+            VERIFY_NON_NULL(TAG, outPayload, ERROR);
+            CborEncoder encoder;
+            cbor_encoder_init(&encoder, outPayload, size, 0);
+            CborEncoder secRsrc;
+            cborEncoderResult |= cbor_encoder_create_map(&encoder, &secRsrc, CborIndefiniteLength);
+
+            cborEncoderResult |= cbor_encode_text_string(&secRsrc, OIC_JSON_ACL_NAME, strlen(OIC_JSON_ACL_NAME));
+            VERIFY_CBOR_SUCCESS(TAG, cborEncoderResult, "Failed Adding ACL Name.");
+            cborEncoderResult |= cbor_encode_byte_string(&secRsrc, aclCbor, aclCborLen);
+            VERIFY_CBOR_SUCCESS(TAG, cborEncoderResult, "Failed Adding ACL Value.");
+
+            cborEncoderResult |= cbor_encode_text_string(&secRsrc, OIC_JSON_PSTAT_NAME, strlen(OIC_JSON_PSTAT_NAME));
+            VERIFY_CBOR_SUCCESS(TAG, cborEncoderResult, "Failed Adding PSTAT Name.");
+            cborEncoderResult |= cbor_encode_byte_string(&secRsrc, pstatCbor, pstatCborLen);
+            VERIFY_CBOR_SUCCESS(TAG, cborEncoderResult, "Failed Adding PSTAT Value.");
+
+            cborEncoderResult |= cbor_encode_text_string(&secRsrc, OIC_JSON_DOXM_NAME, strlen(OIC_JSON_DOXM_NAME));
+            VERIFY_CBOR_SUCCESS(TAG, cborEncoderResult, "Failed Adding DOXM Name.");
+            cborEncoderResult |= cbor_encode_byte_string(&secRsrc, doxmCbor, doxmCborLen);
+            VERIFY_CBOR_SUCCESS(TAG, cborEncoderResult, "Failed Adding DOXM Value.");
+
+            cborEncoderResult |= cbor_encode_text_string(&secRsrc, OIC_JSON_RESET_PF_NAME, strlen(OIC_JSON_RESET_PF_NAME));
+            VERIFY_CBOR_SUCCESS(TAG, cborEncoderResult, "Failed Adding Reset Profile Name.");
+            cborEncoderResult |= cbor_encode_byte_string(&secRsrc, resetPfCbor, resetPfCborLen);
+            VERIFY_CBOR_SUCCESS(TAG, cborEncoderResult, "Failed Adding Reset Profile Value.");
+
+            cborEncoderResult |= cbor_encoder_close_container(&encoder, &secRsrc);
+            VERIFY_CBOR_SUCCESS(TAG, cborEncoderResult, "Failed Closing Array.");
+            outSize = encoder.ptr - outPayload;
+        }
+
+        if (outPayload && outSize)
+        {
+            OIC_LOG_V(DEBUG, TAG, "Writing in the file: %zu", outSize);
+            OCPersistentStorage *ps = SRMGetPersistentStorageHandler();
+            if (ps)
+            {
+                FILE *fp = ps->open(SVR_DB_DAT_FILE_NAME, "wb");
+                if (fp)
+                {
+                    size_t numberItems = ps->write(outPayload, 1, outSize, fp);
+                    if (outSize == numberItems)
+                    {
+                        OIC_LOG_V(DEBUG, TAG, "Written %zu bytes into SVR database file", outSize);
+                        ret= OC_STACK_OK;
+                    }
+                    else
+                    {
+                        OIC_LOG_V(ERROR, TAG, "Failed writing %zu in the database", numberItems);
+                    }
+                    ps->close(fp);
+                }
+                else
+                {
+                    OIC_LOG(ERROR, TAG, "File open failed.");
+                }
+
+            }
+        }
+    }
+
+    SRMDeInitSecureResources();
+    InitSecureResources();
+    OIC_LOG(DEBUG, TAG, "ResetSecureResourceINPS OUT");
+
+exit:
+    OICFree(dbData);
+    OICFree(outPayload);
+    OICFree(aclCbor);
+    OICFree(pstatCbor);
+    OICFree(doxmCbor);
+    OICFree(resetPfCbor);
+}
+
+/**
+ * Creates Reset Profile from the initial secure virtual resources.
+ * This function copies the secure resources
+ * and creates the Reset Profile in the Persistent Storage.
+ * Device ID in doxm and pstat are left empty as it will be renewed after reset.
+ *
+ * @return OCStackResult - result of updating Secure Virtual Resource(s)
+ */
+OCStackResult CreateResetProfile(void)
+{
+    OIC_LOG(DEBUG, TAG, "CreateResetProfile IN");
+
+    size_t dbSize = 0;
+    uint8_t *dbData = NULL;
+
+    uint8_t *aclCbor = NULL;
+    uint8_t *pstatCbor = NULL;
+    uint8_t *doxmCbor = NULL;
+    uint8_t *resetPfCbor = NULL;
+
+    OCStackResult ret = OC_STACK_ERROR;
+    int64_t cborEncoderResult = CborNoError;
+    ret = GetSecureVirtualDatabaseFromPS(NULL, &dbData, &dbSize);
+    if (dbData && dbSize)
+    {
+        size_t aclCborLen = 0;
+        size_t pstatCborLen = 0;
+        size_t doxmCborLen = 0;
+        size_t resetPfCborLen = 0;
+
+        {
+            CborParser parser;
+            CborValue cbor;
+            cbor_parser_init(dbData, dbSize, 0, &parser, &cbor);
+            CborValue curVal = {0};
+            CborError cborFindResult = CborNoError;
+            cborFindResult = cbor_value_map_find_value(&cbor, OIC_JSON_ACL_NAME, &curVal);
+            if (CborNoError == cborFindResult && cbor_value_is_byte_string(&curVal))
+            {
+                cborFindResult = cbor_value_dup_byte_string(&curVal, &aclCbor, &aclCborLen, NULL);
+                VERIFY_CBOR_SUCCESS(TAG, cborFindResult, "Failed Finding ACL Name Value.");
+            }
+            cborFindResult = cbor_value_map_find_value(&cbor, OIC_JSON_PSTAT_NAME, &curVal);
+            if (CborNoError == cborFindResult && cbor_value_is_byte_string(&curVal))
+            {
+                cborFindResult = cbor_value_dup_byte_string(&curVal, &pstatCbor, &pstatCborLen, NULL);
+                VERIFY_CBOR_SUCCESS(TAG, cborFindResult, "Failed Finding PSTAT Name Value.");
+            }
+            cborFindResult = cbor_value_map_find_value(&cbor, OIC_JSON_DOXM_NAME, &curVal);
+            if (CborNoError == cborFindResult && cbor_value_is_byte_string(&curVal))
+            {
+                cborFindResult = cbor_value_dup_byte_string(&curVal, &doxmCbor, &doxmCborLen, NULL);
+                VERIFY_CBOR_SUCCESS(TAG, cborFindResult,  "Failed Finding DOXM Name Value.");
+            }
+        }
+
+        // Set the Device ID in doxm and pstat to empty
+        if (pstatCbor)
+        {
+            OicSecPstat_t *pstat = NULL;
+            ret = CBORPayloadToPstat(pstatCbor, pstatCborLen, &pstat);
+            OICFree(pstatCbor);
+            pstatCbor = NULL;
+            pstatCborLen = 0;
+
+            OicUuid_t emptyUuid = {.id = {0} };
+            memcpy(&pstat->deviceID, &emptyUuid, sizeof(OicUuid_t));
+            memcpy(&pstat->rownerID, &emptyUuid, sizeof(OicUuid_t));
+
+            ret = PstatToCBORPayload(pstat, &pstatCbor, &pstatCborLen);
+            OICFree(pstat);
+        }
+        if (doxmCbor)
+        {
+            OicSecDoxm_t *doxm = NULL;
+            ret = CBORPayloadToDoxm(doxmCbor, doxmCborLen, &doxm);
+            OICFree(doxmCbor);
+            doxmCbor = NULL;
+            doxmCborLen = 0;
+
+            OicUuid_t emptyUuid = {.id = {0} };
+            memcpy(&doxm->deviceID, &emptyUuid, sizeof(OicUuid_t));
+            memcpy(&doxm->rownerID, &emptyUuid, sizeof(OicUuid_t));
+
+            ret = DoxmToCBORPayload(doxm, &doxmCbor, &doxmCborLen);
+            OICFree(doxm);
+        }
+
+        {
+            size_t size = aclCborLen + pstatCborLen + doxmCborLen + 255;
+            resetPfCbor = (uint8_t *) OICCalloc(1, size);
+            VERIFY_NON_NULL(TAG, resetPfCbor, ERROR);
+            CborEncoder encoder;  // will be initialized in |cbor_parser_init|
+            cbor_encoder_init(&encoder, resetPfCbor, size, 0);
+            CborEncoder secRsrc;  // will be initialized in |cbor_encoder_create_map|
+            cborEncoderResult |= cbor_encoder_create_map(&encoder, &secRsrc, CborIndefiniteLength);
+
+            cborEncoderResult |= cbor_encode_text_string(&secRsrc, OIC_JSON_ACL_NAME, strlen(OIC_JSON_ACL_NAME));
+            VERIFY_CBOR_SUCCESS(TAG, cborEncoderResult, "Failed Adding ACL Name.");
+            cborEncoderResult |= cbor_encode_byte_string(&secRsrc, aclCbor, aclCborLen);
+            VERIFY_CBOR_SUCCESS(TAG, cborEncoderResult, "Failed Adding ACL Value.");
+
+            cborEncoderResult |= cbor_encode_text_string(&secRsrc, OIC_JSON_PSTAT_NAME, strlen(OIC_JSON_PSTAT_NAME));
+            VERIFY_CBOR_SUCCESS(TAG, cborEncoderResult, "Failed Adding PSTAT Name.");
+            cborEncoderResult |= cbor_encode_byte_string(&secRsrc, pstatCbor, pstatCborLen);
+            VERIFY_CBOR_SUCCESS(TAG, cborEncoderResult, "Failed Adding PSTAT Value.");
+
+            cborEncoderResult |= cbor_encode_text_string(&secRsrc, OIC_JSON_DOXM_NAME, strlen(OIC_JSON_DOXM_NAME));
+            VERIFY_CBOR_SUCCESS(TAG, cborEncoderResult, "Failed Adding Doxm Name.");
+            cborEncoderResult |= cbor_encode_byte_string(&secRsrc, doxmCbor, doxmCborLen);
+            VERIFY_CBOR_SUCCESS(TAG, cborEncoderResult, "Failed Adding Doxm Value.");
+
+            cborEncoderResult |= cbor_encoder_close_container(&encoder, &secRsrc);
+            VERIFY_CBOR_SUCCESS(TAG, cborEncoderResult, "Failed Closing Array.");
+            resetPfCborLen = encoder.ptr - resetPfCbor;
+        }
+
+        UpdateSecureResourceInPS(OIC_JSON_RESET_PF_NAME, resetPfCbor, resetPfCborLen);
+
+    }
+    OIC_LOG(DEBUG, TAG, "CreateResetProfile OUT");
+
+exit:
+    OICFree(dbData);
+    OICFree(aclCbor);
+    OICFree(pstatCbor);
+    OICFree(doxmCbor);
+    OICFree(resetPfCbor);
     return ret;
 }
+
index 050c497..3d49a4b 100644 (file)
@@ -448,7 +448,12 @@ static OCEntityHandlerResult HandlePstatPostRequest(const OCEntityHandlerRequest
         VERIFY_NON_NULL(TAG, pstat, ERROR);
         if (OC_STACK_OK == ret)
         {
-            if (false == (pstat->cm & TAKE_OWNER) && false == pstat->isOp)
+            if (true == (pstat->cm & RESET) && false == pstat->isOp)
+            {
+                gPstat->cm = pstat->cm;
+                OIC_LOG(INFO, TAG, "State changed to Ready for Reset");
+            }
+            else if (false == (pstat->cm & TAKE_OWNER) && false == pstat->isOp)
             {
                 gPstat->cm = pstat->cm;
                 OIC_LOG (INFO, TAG, "State changed to Ready for Provisioning");
@@ -482,6 +487,23 @@ static OCEntityHandlerResult HandlePstatPostRequest(const OCEntityHandlerRequest
             {
                 ehRet = OC_EH_OK;
             }
+            if (true == (pstat->cm & RESET))
+            {
+                if (OC_STACK_OK != SendSRMResponse(ehRequest, ehRet, NULL, 0))
+                {
+                    ehRet = OC_EH_ERROR;
+                    OIC_LOG(ERROR, TAG, "SendSRMResponse failed in HandlePstatPostRequest");
+                    DeletePstatBinData(pstat);
+                    return ehRet;
+                }
+                ret = ResetSecureResourceInPS();
+                if (OC_STACK_OK == ret)
+                {
+                    ehRet = OC_EH_OK;
+                }
+                DeletePstatBinData(pstat);
+                return ehRet;
+            }
         }
     }
  exit:
index 5414ef6..20f54bf 100644 (file)
@@ -83,6 +83,9 @@ const char * OIC_RSRC_TYPE_SEC_VER = "oic.r.ver";
 const char * OIC_RSRC_VER_URI =  "/oic/sec/ver";
 const char * OIC_JSON_VER_NAME = "ver";
 
+//reset profile
+const char * OIC_JSON_RESET_PF_NAME = "resetpf";
+
 const char * OIC_JSON_SUBJECT_NAME = "subject";
 const char * OIC_JSON_RESOURCES_NAME = "resources";
 const char * OIC_JSON_AMSS_NAME = "amss";
index 963c6aa..bcd6f44 100644 (file)
@@ -51,6 +51,7 @@
 #include "logger.h"
 #include "ocserverrequest.h"
 #include "secureresourcemanager.h"
+#include "psinterface.h"
 #include "doxmresource.h"
 #include "cacommon.h"
 #include "cainterface.h"
@@ -4150,6 +4151,7 @@ OCStackResult initResources()
 
     if(result == OC_STACK_OK)
     {
+        CreateResetProfile();
         result = OCCreateResource(&deviceResource,
                                   OC_RSRVD_RESOURCE_TYPE_DEVICE,
                                   OC_RSRVD_INTERFACE_DEFAULT,