Configuration of OSMC RAM Scrambling
Closed this issue · 5 comments
As I noted some times ago in the forum, the SAMA5d3 datasheet describes the opportunity to use the RAM scrambler. OCMS Register in chapter 29.5.5 in the datasheet
I didn't found support for this in at91bootstrap. (did I miss it maybe?)
Would it be interesting/mergable to propose some config items and a minimal driver for this feature, similar to the other secure boot related configs?
Hi,
For sure any new feature, if it's implemented correctly, can be of added value for this project.
So from my perspective, we are waiting to see your implementation :)
Eugen
Hello
We did implement this ourselves for our custom board file for an A5D4 and as a result didn't really work easily to submit a pull request. I expect A5D3 and A5D2 would be largely identical. So I submit here the code from our version that you can do with as you please 👍
We just use the TRNG and generate a random code at every boot.
The code may not paste nicely formatted, but it would be a reasonable start. I also note the timeout code is a bit dirty and doesn't try an alternative if doesn't get a number in time, which may be some sort of security hole since somehow making it timeout would result in a known key (being the timout counter)
In our ddramc_init() function after the DDR is setup we have this code - this would need to be moved to make it generic for all board types and probably called after hw_init() in main.c
#if defined(CONFIG_SCRAMBLED_EXTERNAL_RAM)
#if (BOOTSTRAP_DEBUG_LEVEL >= DEBUG_LOUD)
dbg_info("\nScrambling DDR RAM:\n");
#endif
if (readl(AT91C_BASE_MPDDRC + HDDRSDRC2_WPCR) & 0x00000001) {
#if (BOOTSTRAP_DEBUG_LEVEL >= DEBUG_LOUD)
dbg_info("\nDisabling write protect\n");
#endif
writel( 0x44445200, (AT91C_BASE_MPDDRC + HDDRSDRC2_WPCR));
}
/* Enable TRNG */
#if (BOOTSTRAP_DEBUG_LEVEL >= DEBUG_LOUD)
dbg_info("\nEnable TRNG\n");
#endif
/* Allow PMC Clock update for TRNG, clear WPEN bit */
writel( 0x504D4300, AT91C_BASE_PMC+PMC_WPMR); // password + 00
/* Enable Peripheral 53 (0x35) clock in PMC Peripheral Clock Register */
writel( 0x10001035, AT91C_BASE_PMC+PMC_PCR);
/* Enable PMC Clock for TRNG */
writel( 0x00200000, AT91C_BASE_TRNG+PMC_PCER1); // enable periph id 53
/* Enable TRNG Interrupt Enable Register */
writel( 0x00000001, 0xFC030010);
/* Unlock TRNG */
writel( 0x524E4701, AT91C_BASE_TRNG);
/* initialise OCMS_KEY1 */
for(reg=0; reg < MAXTRNGLOOPCNT; reg++) {
/* check DATRDY bit in TRNG_ISR register */
if (readl(AT91C_BASE_TRNG+0x1C) & 1) {
break;
}
else {
#if (BOOTSTRAP_DEBUG_LEVEL >= DEBUG_LOUD)
dbg_info("Waiting for TRNG\n");
#endif
}
}
if (reg == MAXTRNGLOOPCNT) {
dbg_info("\nTRNG not ready for OCMS_KEY1\n");
// add in alternative RNG
}
else {
reg = readl(AT91C_BASE_TRNG+0x50); // ODATA register
#if (BOOTSTRAP_DEBUG_LEVEL >= DEBUG_LOUD)
dbg_info("OCMS_KEY1: %x\n", reg);
#endif
writel( reg, (AT91C_BASE_MPDDRC + MPDDRC_OCMS_KEY1));
}
/* initialise OCMS_KEY2 */
for(reg=0; reg < MAXTRNGLOOPCNT; reg++) {
/* check DATRDY bit in TRNG_ISR register */
if (readl(AT91C_BASE_TRNG+0x1C) & 1) {
break;
}
else {
#if (BOOTSTRAP_DEBUG_LEVEL >= DEBUG_LOUD)
dbg_info("Waiting for TRNG\n");
#endif
}
}
if (reg == MAXTRNGLOOPCNT) {
dbg_info("\nTRNG not ready for OCMS_KEY2\n");
// add in alternate RNG
}
else {
reg = readl(AT91C_BASE_TRNG+0x50); // ODATA register
#if (BOOTSTRAP_DEBUG_LEVEL >= DEBUG_LOUD)
dbg_info("OCMS_KEY2: %x\n", reg);
#endif
writel( reg, (AT91C_BASE_MPDDRC + MPDDRC_OCMS_KEY2));
}
/* ensure TRNG not left in RAM */
reg = 0;
/* Turn on scrambling */
writel( 0x00000001, (AT91C_BASE_MPDDRC + MPDDRC_OCMS));
#endif /* #if defined(CONFIG_SCRAMBLED_EXTERNAL_RAM) */
and in driver/Config.in.memory after the DDR-SDRAM device type
config CONFIG_SCRAMBLED_EXTERNAL_RAM
bool "Scramble external DRAM with TRNG generated key"
default n
I created #115 as a RFC, could you have a look at my pending questions? I added basic configuration based implementation, but left a placeholder for the TRNG based one. The simple one is more in sync with the other "Secure Mode" configs. With the TRNG based one I like that it does not require the secure mode, and it could enhance security by using new keys for each start-up!
@ShonkyCH why did you add the time-out? The datasheet mentions that the TRNG provides a new word after each 84 cycle. Did you face issues with it? Or just didn't want to implement that exact calculation? Anyway, thanks for the idea and the code, I find it very smart!
@lnksz Main reason is we don't want the system hanging at boot if for some reason the TRNG doesn't work. Very low chance but in an embedded environment, you don't get second chances. Defensive programming.
We didn't ever see it not work. We should implement an alternate random number generator in the case of the timeout though.