Index: obuspa-10.0.5.0/src/core/device.h
===================================================================
--- obuspa-10.0.5.0.orig/src/core/device.h
+++ obuspa-10.0.5.0/src/core/device.h
@@ -311,6 +311,9 @@ int DEVICE_CTRUST_InstSelToRoleInstance(
 char *DEVICE_CTRUST_InstSelToPermTarget(int role_index, void *is, int *perm_instance);
 int DEVICE_CTRUST_SetRoleParameter(int instance, char *param_name, char *new_value);
 int DEVICE_CTRUST_SetPermissionParameter(int instance1, int instance2, char *param_name, char *new_value);
+
+bool DEVICE_CTRUST_IsControllerSecured(void);
+
 int DEVICE_CTRUST_DumpPermissionSelectors(int role_instance, char *path);
 int DEVICE_REQUEST_Init(void);
 int DEVICE_REQUEST_Add(char *path, char *command_key, int *instance);
Index: obuspa-10.0.5.0/src/core/device_ctrust.c
===================================================================
--- obuspa-10.0.5.0.orig/src/core/device_ctrust.c
+++ obuspa-10.0.5.0/src/core/device_ctrust.c
@@ -246,6 +246,7 @@ credential_t *FindCredentialByCertInstan
 int Get_CredentialRole(dm_req_t *req, char *buf, int len);
 int Get_CredentialCertificate(dm_req_t *req, char *buf, int len);
 int Get_CredentialNumEntries(dm_req_t *req, char *buf, int len);
+int Validate_SecuredRoles(dm_req_t *req, char *value);
 void ApplySearchExpressionPermissions(char *path, inst_sel_t *sel);
 bool ValidateDataModelPathSegment(char *segment, bool is_last, char *path);
 
@@ -293,6 +294,9 @@ int DEVICE_CTRUST_Init(void)
     // Create a timer which will be used to apply all modified permissions to the data model, after processing a USP Message
     SYNC_TIMER_Add(ApplyModifiedPermissions, 0, END_OF_TIME);
 
+    // Register Device.LocalAgent.ControllerTrust.SecuredRoles parameter
+    err |= USP_REGISTER_DBParam_ReadWrite(DEVICE_CTRUST_ROOT ".SecuredRoles", "", Validate_SecuredRoles, NULL, DM_STRING);
+
     // Register parameters implemented by this component
     // Device.LocalAgent.ControllerTrust.Role.{i}
     err |= USP_REGISTER_Object(DEVICE_ROLE_ROOT, ValidateAdd_CTrustRole, NULL, Notify_CTrustRoleAdded,
@@ -3533,3 +3537,139 @@ exit:
     return err;
 }
 #endif // REMOVE_DEVICE_SECURITY
+
+
+/*********************************************************************//**
+**
+** Validate_SecuredRoles
+**
+** Validates Device.LocalAgent.ControllerTrust.SecuredRoles
+** Each list item MUST be the Path Name of a row in the Device.LocalAgent.ControllerTrust.Role table
+**
+** \param   req - pointer to structure identifying the parameter
+** \param   value - value that the controller would like to set the parameter to
+**
+** \return  USP_ERR_OK if successful
+**
+**************************************************************************/
+int Validate_SecuredRoles(dm_req_t *req, char *value)
+{
+    char *role_path;
+    char *saveptr;
+    char *str;
+    char temp[MAX_DM_PATH];
+    int role_instance;
+    int err;
+
+    // Empty string is valid
+    if (*value == '\0')
+    {
+        return USP_ERR_OK;
+    }
+
+    // Copy the value as strtok_r modifies the string
+    USP_STRNCPY(temp, value, sizeof(temp));
+
+    // Iterate through comma-separated list
+    str = temp;
+    role_path = strtok_r(str, ",", &saveptr);
+    while (role_path != NULL)
+    {
+        // Trim whitespace
+        role_path = TEXT_UTILS_TrimBuffer(role_path);
+
+        // Verify that this path exists in the Role table using DM_ACCESS_ValidateReference
+        err = DM_ACCESS_ValidateReference(role_path, "Device.LocalAgent.ControllerTrust.Role.{i}", &role_instance);
+        if (err != USP_ERR_OK)
+        {
+            USP_ERR_SetMessage("%s: Role path '%s' does not exist in Device.LocalAgent.ControllerTrust.Role table", __FUNCTION__, role_path);
+            return USP_ERR_INVALID_VALUE;
+        }
+
+        role_path = strtok_r(NULL, ",", &saveptr);
+    }
+
+    return USP_ERR_OK;
+}
+
+/*********************************************************************//**
+**
+** DEVICE_CTRUST_IsControllerSecured
+**
+** Determines whether the specified controller has a secured role
+**
+** \param   combined_role - pointer to structure containing the role indexes for this controller
+**
+** \return  true if the controller has a secured role, false otherwise
+**
+**************************************************************************/
+bool DEVICE_CTRUST_IsControllerSecured()
+{
+    char secured_roles[MAX_DM_PATH];
+    char *role_path;
+    char *saveptr;
+    char *str;
+    char temp[MAX_DM_PATH];
+    int err;
+    role_t *role;
+    int role_instance;
+    combined_role_t combined_role;
+    controller_info_t ci;
+
+    // Exit if unable to get the secured roles
+    err = DATA_MODEL_GetParameterValue("Device.LocalAgent.ControllerTrust.SecuredRoles", secured_roles, sizeof(secured_roles), 0);
+    if (err != USP_ERR_OK)
+    {
+        return false;
+    }
+
+    // Empty string means no secured roles
+    if (*secured_roles == '\0')
+    {
+        return false;
+    }
+
+    MSG_HANDLER_GetControllerInfo(&ci);
+    if (ci.endpoint_id == NULL)
+    {
+        return false;
+    }
+    if(strlen(ci.endpoint_id) == 0)
+    {
+        return false;
+    }
+
+    MSG_HANDLER_GetMsgRole(&combined_role);
+    // Copy the value as strtok_r modifies the string
+    USP_STRNCPY(temp, secured_roles, sizeof(temp));
+
+    // Iterate through comma-separated list
+    str = temp;
+    role_path = strtok_r(str, ",", &saveptr);
+    while (role_path != NULL)
+    {
+        // Trim whitespace
+        role_path = TEXT_UTILS_TrimBuffer(role_path);
+
+        // Extract the instance number from the role path
+        err = DM_ACCESS_ValidateReference(role_path, "Device.LocalAgent.ControllerTrust.Role.{i}", &role_instance);
+        if (err == USP_ERR_OK)
+        {
+            // Find the role in our internal array
+            role = FindRoleByInstance(role_instance);
+            if (role != NULL)
+            {
+                // Check if this role matches either the inherited or assigned role
+                if ((role - roles == combined_role.inherited_index) ||
+                    (role - roles == combined_role.assigned_index))
+                {
+                    return true;
+                }
+            }
+        }
+
+        role_path = strtok_r(NULL, ",", &saveptr);
+    }
+
+    return false;
+}
