When BK7231 MCUs load the SPI flash contents into memory, they do not simply copy the bytes; every 32 bytes are followed by 2 bytes of CRC, which the bootloader supposedly checks and removes. In addition, the flash contents can optionally be encrypted with a key stored in eFuse, so the bootloader would also decrypt them before copying to memory.
In the other direction, both of these tasks are performed by the encrypt
tool in the SDK: this takes the built code, inserts CRC bytes and (optionally) encrypts with the eFuse key.
This image is almost but not quite ready to flash: some spots of the image must then be overwritten with bootloader (RBL) and partition table (FAL) markers;
these are stored in plaintext so they can be interpreted before decryption has taken place. These markers respect the 2-byte CRCs,
so they are discontinuous in the flash memory if they're bigger than 1 block, and cause the CRC numbers to be updated.
The encryption consists of an ad-hoc stream cipher which is applied in 32-bit blocks, described below. The input to the stream cipher is the address of the 32-bit block, in bytes. CRC bytes do not have encryption applied to them, nor they count towards the block addresses; so, the addresses passed to the cipher are always a multiple of 4.
The CRC is calculated after the block has been encrypted, so there's no authentication at all. The polynomial is
Based on abc.c, which seems to be a direct C transpilation of the HDL.
From user's perspective, the cipher takes a key in eFuse, which is made up of 4 u32s. in order these are:
- key used for stage 3
- key used to derive the stage 1 and 2 keys
- key used for stage 4 (static key)
- encryption parameters
The cipher works by XORing the output of 4 stages, each of which takes a stage-specific key, the input address and a 2-bit selector. The key and output of a stage have the same width: 16 bits for stage 1, 17 bits for stage 2, and 32 bits for stages 3 and 4.
The eFuse key is used to derive the stage keys for the 4 stages: for stage 3 and 4, the key comes directly from one of the words in the eFuse key, but for stages 1 and 2, bits of the second word of the eFuse key (and one bit of the encryption parameters) assemble their keys. Check the code for the actual expression.
The stages all have a common structure (explained below) except for the last stage, which simply outputs its key unchanged. This means the stage 4 key (the third integer in the eFuse key) is a static key; it is XORed with all ciphertexts (unless the stage is disabled, see below).
Encryption parameters is a bitfield with the following structure:
(MSB) (LSB)
EEEEEEEE ........ ...SS.SS .SSKBBBB
[------] [] [] []|||||
| | | | ||||+- Stage 1 bypass
| | | | |||+-- Stage 2 bypass
| | | | ||+--- Stage 3 bypass
| | | | |+---- Stage 4 bypass
| | | | +----- Bit participating in stage 2 key
| | | +------- Stage 1 selector
| | +----------- Stage 2 selector
| +-------------- Stage 3 selector
+-------------------------------- Must be != then 00 or FF for
encryption to be enabled
If the bypass bit (B) of a stage is set to 1, the output of that stage is ignored and doesn't participate in the ciphertext.
Each stage starts by preprocessing the input address in a certain way (which depends on its 2-bit selector SS) and XORing the result with the stage key. It then performs a stage-specific transform on that.
Any other parameter bits (.) are ignored.