In "System Design with ARMv8M, Section 1.6 Block-based Gate", a Block-based gate is described.
The document describes 2 hard requirements for a Block-base Gate followed by an explanation for the 2nd requirement.
The gate has two hard requirements: 1. It must not-permit Non-secure transactions to read/write blocks that the controls mark as Secure. 2. It must not-permit Secure transactions to read blocks that the controls mark as Non-secure. In addition to other less obvious attack vectors, requirement 2 is designed to prevent Non-secure software using the aliasing to install code, including SG instructions into Secure memory and then calling into it.
The gate has two hard requirements:
1. It must not-permit Non-secure transactions to read/write blocks that the controls mark as Secure.
2. It must not-permit Secure transactions to read blocks that the controls mark as Non-secure.
In addition to other less obvious attack vectors, requirement 2 is designed to prevent Non-secure
software using the aliasing to install code, including SG instructions into Secure memory and then
calling into it.
How is the scenario regarding the need for the 2nd requirement possible if the SAU/IDAU sections are programmed correctly?
Is this more of a precaution against incorrect SAU/IDAU programming?
Even if SAU/IDAU are setup correctly, Secure software could potentially have other bugs that can lead to vulnerabilities. For example, a stack corruption (e.g. buffer overflow) could lead to branching to a different Secure address during function return, and if that memory location is accessible from Non-secure world and is executable, then an attacker could compromise the system.
There are of course other ways to inject data into Secure memory space (e.g. some Secure functions might need to copy Non-secure data into Secure memory for processing). While the MPU could help as you can mark those address Non-executable, but some devices might not have Secure MPU. So it is important to have high quality in Secure software to reduce these risks.
regards,
Joseph
Hi Joseph,
To summarize, the strict requirement that Secure Transactions only read secure memory/peripherals is in place to protect against low quality software.
It's up to the Hardware implementer to enforce this at the bus level.
If the implementer does not enforce this, then the burden is put on the SW team to ensure extreme high quality code.
You say the some functions may copy Non-Secure Data in to Secure Memory for processing.
Can you confirm my understanding of how that is actually done.
Let us assume we are just copying a word of encrypted data from non-secure ram to secure ram for decryption and then write some status word back to Non-Secure memory.
The steps are as follows:
1. Non-Secure Code calls a secure veneer in a NSC region of memory passing the Non-Secure Address to the encrypted word.
2. The Secure veneer confirms the data address lies solely in one Non-Secure Region via the TT instruction and then performs the other various tasks needed for a non-secure to secure transition.
3. While the PE is in the Secure State, a read transaction occurs to the Non-Secure data address and the SAU/IDAU will mark the read as a Non-Secure transaction. Let's say the data is read into R0.
4. The Secure code decrypts the data in R0 and generates a status word that needs to go back into Non-Secure Memory.
5. While in the secure state, the PE issues a write to the Non-Secure address for the status word and the SAU/IDAU marks this as a Non-Secure transaction.
6. Cleanup and return to non-secure state.
The Secure veneer (in NSC) usually only contain SG and a branch instruction to the actual Secure API, and the checking of pointer would be carried out inside the Secure API.
We keep the Secure veneer as small as possible to reduce chance that the code could contain a SG instruction by accident (due to constant/literal data).
The other steps looks fine.
One comment on Joseph's reply:
In fact, it's not allowed to put any literal data into NSC if you are rigorous about system security.
Even secure veneers are using MOVW and MOVT to encode target branch address into OPCODE, so the NSC could be put into eXecute-Only memory (Instruction Fetch Only memory). This implies that attackers cannot get the actual addresses of target functions of secure API.
--------------------
One famous attack scheme is trying to find a way to
a. Disable SAU
b. Mark entire 4G address space as Secure
so the original non-secure code will be able to access secure resources freely.
By taking this into consideration, putting NSC into physically eXecute-Only memory has significant security meaning.