Security is perhaps the hottest topic going right now, and that’s led to the arrival of many approaches for implementing different aspects of system security. For example, secure boot protects the code that’s initially run by a system providing at least a root of trust needed to guarantee that secured code is checking any subsequent code. Making sure that code is operating properly is also important.
Dover Microsystems’ CoreGuard (see figure) takes a different approach to check how code is being executed: It lets programmers specify micro security policies that are implemented in hardware. The policies allow the system to do things like prevent buffer overflow errors.
CoreGuard is IP that’s included as part of the processor design. It hooks into a number of processor subsystems so that it can see which registers or memory is being accessed. It also tracks details like the instruction counter and current instruction. The other main components are the policy enforcer, the micro policies, and the CoreGuard cache. The cache is a front end for CoreGuard memory that’s part of main memory. Thr memory is hidden from any program code running on the system.
Dover Microsystems’ CoreGuard implements micro security policies by tracking instruction execution.
What CoreGuard does is examine an instruction as it’s executed, and this along with other information is compared to CoreGuard policies. The result may be a determination that the instruction will violate the policies. If that’s the case, the system generates an interrupt so that the instruction will not complete execution and the error can be handled by the interrupt software.
The CoreGuard system may also cache some information in its memory to track the use of memory. For example, the system can hook in the C malloc routine so that it knows the location and size of the buffer being allocated. It essentially colors the matching cache memory; therefore, it can be checked when a subsequent instruction tries to access the buffer. An access to data that violates a policy results in an interrupt.
For this memory allocation policy, CoreGuard needs to know where the malloc routine is located and how it works. This isn’t to modify the program, but rather so the CoreGuard hardware can be set up to monitor the instruction stream so that it knows when the malloc routine is called. Binary analysis of the code image is sufficient to find this type of information.
Controlling the Tracking of Secure Data
Another type of policy can control tracking of secure information such as a social security number. In this case, the system marks data that needs to be secured. This means CoreGuard support needs to know what the data is, how it will be manipulated, and how related data will be tracked. For example, if the social-security-number buffer is passed to an encryption routine, then the destination buffer of that routine can be marked as not containing data that has to be secured. That’s because the encrypted data can be safely used anywhere, including sending it off-chip.
On the flip side, CoreGuard uses the idea of “tainted” data to track changes. The social-security-number buffer is tainted/marked so that the system can recognize it in a similar way to how it tracks data allocation from malloc. The difference is tainted data can taint other data that’s related to it programmatically. A subroutine with access to the social-security-number buffer manipulates this data into another buffer or register; subsequently, tainted data is in this new location. CoreGuard then tracks how this new data is used and would prevent it from being exported to a public interface, such as sent out a serial port.
The CoreGuard micro policies can be written to track what routines can manipulate the tainted data like an encryption routine so that the resulting data isn’t marked as tainted. This includes identifying routines that can perform secure manipulations. Library routines like this can be identified from the program code in the same fashion as the malloc routine detection was performed.
CoreGuard uses the cache to match against the currently executing instruction. As a result, it can quickly determine whether the current instruction will meet the policy requirements. Remember, an instruction may be affected by more than one policy. As with most caching systems, if the information is in the cache and it meets the policies, then the instruction will execute without delay.
The policies are defined using a system provided by Dover Microsystems. The use of programmable policies allows a developer to determine how much and what will be checked. There are limitations based on what CoreGuard can track, but it can handle a range of security problems that could not be addressed easily without hardware.
While the ideas behind CoreGuard are simple and compelling, the implementation and overhead are details that developers will have to investigate carefully. CoreGuard’s memory size isn’t the same as memory available to the application, but it’s proportional. Policies will have to be written, although Dover Microsystems supplies many sample policies that can be used as a starting point. Likewise, it provides the program analysis tools. These target C and C++, but can be applied to other programming languages and environments.
The initial use will be in microcontrollers, where memory protection is simpler. It can be application-to-application processors with virtual memory, though these are more complicated.
The advantage of Dover Microsystems’ approach is that programmers don’t have to change their tools or approach to programming. It can be applied to existing code and it’s essentially transparent to programs. Deterministic systems may require additional analysis to make sure a cache miss doesn’t have a major effect on a system.