0
Ravikumar

H3-Soc boot rom security & E-Fuse

Recommended Posts

Hi,

 

I bought nanopi_neo boards (for my hobby projects). I am learning about security.

I am able to dump e-Fuse area at uboot stage. But i can't modify it (i want to write my own key). I don't have any memory map information of e-fuse.

 

In present boards, bootROM is not verifying the uboot signature(RSA sign:-)). 

1) How to enable signature verification in bootROM?

2) Is there any code or information regarding BootROM security and e-Fuse area mapping?

3) Is there any support of TEE (Trusted execution environment)?

 

 

Share this post


Link to post
Share on other sites

You can find some info here: https://linux-sunxi.org/BROM

and here: https://linux-sunxi.org/EGON#eGON.BRM

and disassembled BROM code here: https://github.com/hno/Allwinner-Info/tree/master/BROM

 

I'm pretty sure BROM can only verify checksums and you can't make trusted boot with it.

Thanks for reply,

With present configuration, it just verifying checksum. But there are some unknow bits in efuse to enable security of the chip.

 

Please check following code

 

void sid_set_security_mode(void)
{
    uint reg_val;
 
    reg_val  = sid_read_key(EFUSE_LCJS);
    reg_val |= (0x01 << 11); //ʹÄÜsecurebit
    sid_program_key(EFUSE_LCJS, reg_val);
    reg_val = (sid_read_key(EFUSE_LCJS) >> 11) & 1;
 
    return;
}
 

I have written security (11-bit), now my board is not booting. I think BootROM trying to verify signature.

 

One more thing, H3 is not a simple soc. it has ARM trust zone and it can run TEE(both linux & secure os at a time). BootROM security must for TEE.

Share this post


Link to post
Share on other sites

Well, there is no documentation for BROM and probably there won't be any in the future from Allwinner side.

AFAIK the only way to go forward is to dump and disassemble BROM from H3, and I'm not sure if anyone here (on this forum) has more info on this undocumented stuff.

Share this post


Link to post
Share on other sites

Well, there is no documentation for BROM and probably there won't be any in the future from Allwinner side.

AFAIK the only way to go forward is to dump and disassemble BROM from H3, and I'm not sure if anyone here (on this forum) has more info on this undocumented stuff.

Please check the following code.

                      https://github.com/BPI-SINOVOIP/BPI-M3-bsp

there are some files in u-boot folder

                                       sunxi_efuse.c : efuse map and programing sequencing

                                       usb_burn.c : __sunxi_burn_key for burning efuse area

 

do you know this code? He is burning e-fuse area via usb device.

If you have any information this code. Please share with me.

Share this post


Link to post
Share on other sites

found some infos:

https://github.com/hno/Allwinner-Info/blob/master/BROM/ffff0000.s#L1

 

and looks like allwinner put h3 secure brom source code online:

https://github.com/Allwinner-Homlet/H3-BSP4.4-bootloader/tree/master/uboot_2014_sunxi_spl/sunxi_spl

there many printf -> which use sunxi_serial_putc

however i didn't find the function definition, would be great to get error message why its not booting the toc0

 

i set secure bit and wrote rotpk but it does not boot my toc0 image or any other image anymore only fel mode is working now,

maybe someone has an idea what it could be wrong:

https://pastebin.com/wHWqzPJ7

Share this post


Link to post
Share on other sites

still not yet, only some infos and bricks more...

 

burnend one board without rotpk, only the secure bit flag, does now boot only the toc header images (:

After that i tried jemk script to generate the sha rotpk checksum and wrote into a new board with secure bit,  however this does not boot my sigend toc .... ):

 

Found out there is a private toc0 header with a debug flag, maybe if its possible to set this flag it would be able to get some debug output and infos why the toc does not boot.

Compared source h3 sbrom src with the sha generation from jemks script  and it looks at first view all correct.

 

did you found something out or got it working?

 

Share this post


Link to post
Share on other sites
On 3/4/2019 at 10:22 AM, xeniter said:

still not yet, only some infos and bricks more...

 

burnend one board without rotpk, only the secure bit flag, does now boot only the toc header images (:

After that i tried jemk script to generate the sha rotpk checksum and wrote into a new board with secure bit,  however this does not boot my sigend toc .... ):

 

Found out there is a private toc0 header with a debug flag, maybe if its possible to set this flag it would be able to get some debug output and infos why the toc does not boot.

Compared source h3 sbrom src with the sha generation from jemks script  and it looks at first view all correct.

 

did you found something out or got it working?

 

Hi, unfortunately no, I'm still looking at sbrom source.

I'm even having problems compiling the fuse burner (it gives me linking error in your implementation of printf). Could you tell me how did you manage to compile it?

By the way yes, toc0 header has a debug flag to enable debug prints, but as far as I can see from a sbrom dump they've been removed in production.

What about trying to debug sbrom code by making a fel-bootable image containing part of that code?

Share this post


Link to post
Share on other sites

hi,

did only copy paste the printf somewhere so no warranties.

copied the makefile also somewhere together to compile bare metal, also without warranties

 

https://pastebin.com/x9RftzVm is the makefile (make main.elf)

original is from https://github.com/linux-sunxi/sunxi-tools/blob/master/uart0-helloworld-sdboot.c

had often issues that programmed died, didn't find out why yet so don't trust it

 

the sram is very limited because of the FEL mode see http://linux-sunxi.org/FEL/USBBoot

what helped is to load the uboot spl to init ram, after that i copied my program to the ddr ram.

./sunxi-fel spl ./sunxi-spl.bin
./sunxi-fel write 0x40000000 ./main.elf
./sunxi-fel exe 0x40000000

make sure you adjust linker script with correct adress

-> main.lds     . = 0x40000000;    => set program to start of ddr ram

 

 

found out, or it looks like the ruby tocgen is missing the

#define ITEM_NAME_SBROMSW_KEY    0x010303

 

pack_tools/toc_tools/key_ladder/create_key_ladder.c:    key_item_bin.KEY0_PK_e_len = (key0_e_len+1)>>1;

typedef struct SBROM_TOC0_KEY_ITEM_info {

    unsigned int    vendor_id;
    unsigned int    KEY0_PK_mod_len;
    unsigned int    KEY0_PK_e_len;
    unsigned int    KEY1_PK_mod_len;
    unsigned int    KEY1_PK_e_len;
    unsigned int    sign_len;
    unsigned char    KEY0_PK[PK_MAX_LEN_BYTE];
    unsigned char    KEY1_PK[PK_MAX_LEN_BYTE];
    unsigned char    reserve[32];
    unsigned char    sign[256];
} SBROM_TOC0_KEY_ITEM_info_t;

 

assume h3 boot code reads length from it, that could be a possible reason why its not booting the toc.

haven't tried to add it yet

 

will continue to test it when i have time for it left again...

 

 

Share this post


Link to post
Share on other sites

Hi @xeniter,

were you able to verify the secure boot on H3? I have some spare boards i am willing try on.  Jmks script generates the files, the rotpk-hash is then also programmed but like yours, the nanopi doesnt boot. When setting all the rotpk-hash to all 0xff, the board boots.

 

any help is highly appreciated 

 

wbr

 

Share this post


Link to post
Share on other sites
(edited)

No results yet...

 

Found maybe the original tool to create toc0, always looked over it.

https://github.com/friendlyarm/h3_lichee/tree/75b584e2502450b1e8d2f98ac16fb2410cf8c30a/tools/pack/pctools/linux/openssl

looks like with it it could be possible to create a valid toc0 which boots with key (assume jemk scripts are based on it)

question is now how to use it, haven't tried it yet

 

edit:

generating keys:

/h3_lichee/tools/pack/pctools/linux/openssl/dragonsecboot -toc0 dragon_toc.cfg ../../../common/keys/

generate toc0:

.

/create_toc0 dragon_toc.cfg /h3_lichee/tools/pack/common/keys
dd if=./toc0.fex of=/dev/sd? bs=1024 seek=8

 

> did only boot on my board with rotpk fuses burned with all zeros ):

maybe you have more luck (cause maybe i burned fuses in wrong order... or something else...)

 

used this to generate Trustkey.bin to be able to use my old generated key:

openssl rsa -in rotprivk_rsa.pem -text > /robart/mdipolt/2del/SECBOOT/h3_lichee/tools/pack/common/keys/Trustkey.bin

 

sboot.bin must be raw bin file (no spl and no elf file!)

you can verify your sboot.bin with executing it via fel mode:
 

./sunxi-fel version
./sunxi-fel -p write 0x2000 sboot.bin
./sunxi-fel exe 0x2000

 

create_toc0 created the ".\\x509_rotpk.bin" which had the same rotpk checksum as jemk script, so i assume its correct.

question is how had it to be written into the fuses

 

xxd -i .\\x509_rotpk.bin
unsigned char __x509_rotpk_bin[] = {
  0xf6, 0xab, 0x5e, 0x33, 0x80, 0xd9, 0xdd, 0xa8, 0x82, 0x86, 0x85, 0x5f,
  0x22, 0xdc, 0x9d, 0xc0, 0xf9, 0xa4, 0x2c, 0xbf, 0xec, 0x05, 0xd0, 0xcd,
  0xcd, 0xa4, 0x9b, 0xf4, 0xb4, 0xba, 0xf8, 0x94
};
unsigned int __x509_rotpk_bin_len = 32;

 

i burned it like that:


 

// allwinner H3 == sun8iw7p1
#define SID_PRKEY_NEU	(SUNXI_SID_BASE_NEU + 0x50)
#define EFUSE_ROTPK (0x64)

static void sid_program_key(unsigned int key_index, unsigned int key_value)
{
    unsigned int reg_val;

    writel(key_value, SID_PRKEY_NEU);

    reg_val = readl(SID_PRCTL_NEU);
    reg_val &= ~((0x1ff<<16)|0x3);
    reg_val |= key_index<<16;
    writel(reg_val, SID_PRCTL_NEU);

    reg_val &= ~((0xff<<8)|0x3);
    reg_val |= (SID_OP_LOCK<<8) | 0x1;
    writel(reg_val, SID_PRCTL_NEU);

    while(readl(SID_PRCTL_NEU)&0x1){};

    reg_val &= ~((0x1ff<<16)|(0xff<<8)|0x3);
    writel(reg_val, SID_PRCTL_NEU);

    return;
}

 for(int i = 0; i < 8; i++) {    
        printf("%08x:", rotpk[i]);       
        sid_program_key(EFUSE_ROTPK+4*i, rotpk[i]);
    } 

 

 

 

 

 

 

Edited by xeniter
new tests

Share this post


Link to post
Share on other sites

yes finally it worked (with jemp script, maybe with tocgen also not tested yet...)

you have to write the keys only little endian instead big endian

 

 

 

Share this post


Link to post
Share on other sites
On 5/24/2019 at 10:48 AM, xeniter said:

yes finally it worked (with jemp script, maybe with tocgen also not tested yet...)

you have to write the keys only little endian instead big endian

 

 

 

Hi Xeniter,

Still haven't succeded into booting a TOC0 spl image. 

- Wrote the generated ROTPK as little endian 

 

SHA256 = 18 D8 E4 D5 A2 4D 8B F2 AA 00 61 98 9B 92 15 E7 9B 99 0A 82 F9 21 A6 5B 0F 56 0D A6 D2 05 E8 CE

 

wrote these values in the Key-section of the efuse(0x64...) as little endian : D5 E4 D8 18 .....CE E8 05 D2

Burned 0xF4(LCJS) -> 0x800 (bit 11->'1' to enable secure boot)

 

Used jmek's Ruby script and used the spl which i compiled from a FriendlyArm's Uboot repository(19KB).

 

After jmek's script, a restuling TOC file generated. 

The file boots ok if the keys are burned either as 0's or 1's and secure bit-11 in the 0xF4 is set to '1', but when the nanopi neo board is burned with the exact sha256 , it doesn't boot.

 

Can you please describe step by step what you did in order to get a correct spl and how you programmed the exact sha256 of a .pem file in the Key-efuse section.

 

Thank you

 

wbr

 

Spitfire

Share this post


Link to post
Share on other sites

hi can you post or pm me the private key? assume hash is wrong, simple sha256 hash of pem file is not correct..

 

you can use tocgen to generate it for you, or generate it yourself liked described in the sunxi wiki

ROTPK_HASH = SHA256([Byte 0-255] = RSA modulus || [Byte 256-x] = RSA public exponent || [Byte x-511] filled with 0x91)

means SHA256 from [256 bytes modules + 3 bytes public key exponent ( normally 65537 means 0x010001) + 253*0x91 fill bytes]

 

if you used exactly this key, please try to read the hash back and post me the result + source of reading the rotpk fuse out

 

Share this post


Link to post
Share on other sites

Hi @xeniter

I used tocgen from the lichee repository. So far i was able to generate ,/x509_rotpk.bin file which holds the hash-value to be programmed.

 

the resulting toc0.fex boots ok when the rotpk-hash is all '0's and '1's. (or all keys are the same) with secure-bit burned.

 

 

My read_register routine:

def read_register(register_addr):
    sid_ctrl_data = (0xAC<<8)
    sid_ctrl_data = sid_ctrl_data+(register_addr<<16)
    sid_ctrl_data = sid_ctrl_data+0x02
    #print("SID ctrl content ",hex(sid_ctrl_data))
    writel(sid_base_addr+0x40,sid_ctrl_data)
    while((readl(sid_base_addr+0x40)&0x02)==0x02):
        print("finishing read ..")
        time.sleep(1)
    read_val= readl(sid_base_addr+0x40)
    #print("read val:",hex(read_val))
    reg_val = readl(sid_base_addr+0x60)
    return reg_val

 

programmed HASH in the rotpk section:

('reg ', '0x64', ':', '0xe9e6181a')
('reg ', '0x68', ':', '0x5fb19a8f')
('reg ', '0x6c', ':', '0xf91d6e62')
('reg ', '0x70', ':', '0x652b9fd8')
('reg ', '0x74', ':', '0x3573e89e')
('reg ', '0x78', ':', '0x6f9c3d21')
('reg ', '0x7c', ':', '0xa8f92947')
('reg ', '0x80', ':', '0xf5326ac5')
('reg ', '0x84', ':', '0x0')
('reg ', '0x88', ':', '0x0')
('reg ', '0x8c', ':', '0x0')
('reg ', '0x90', ':', '0x0')
('reg ', '0x94', ':', '0x0')
('reg ', '0x98', ':', '0x0')
('reg ', '0x9c', ':', '0x0')
('reg ', '0xa0', ':', '0x0')
('reg ', '0xa4', ':', '0x0')
('reg ', '0xa8', ':', '0x0')
('reg ', '0xac', ':', '0x0')
('reg ', '0xb0', ':', '0x0')
('reg ', '0xb4', ':', '0x0')
('reg ', '0xb8', ':', '0x0')
('reg ', '0xbc', ':', '0x0')
('reg ', '0xc0', ':', '0x0')
('reg ', '0xc4', ':', '0x0')
('reg ', '0xc8', ':', '0x0')
('reg ', '0xcc', ':', '0x0')
('reg ', '0xd0', ':', '0x0')
('reg ', '0xd4', ':', '0x0')
('reg ', '0xd8', ':', '0x0')
('reg ', '0xdc', ':', '0x0')
('reg ', '0xe0', ':', '0x0')
('reg ', '0xe4', ':', '0x0')
('reg ', '0xe8', ':', '0x0')
('reg ', '0xec', ':', '0x0')
('reg ', '0xf0', ':', '0x0')
('reg ', '0xf4', ':', '0x800')
('reg ', '0xf8', ':', '0x0')
('reg ', '0xfc', ':', '0x0')

 

 

my x509_rotpk_:

unsigned char x509_rotpk_bin[] = {
  0x1a, 0x18, 0xe6, 0xe9, 0x8f, 0x9a, 0xb1, 0x5f, 0x62, 0x6e, 0x1d, 0xf9,
  0xd8, 0x9f, 0x2b, 0x65, 0x9e, 0xe8, 0x73, 0x35, 0x21, 0x3d, 0x9c, 0x6f,
  0x47, 0x29, 0xf9, 0xa8, 0xc5, 0x6a, 0x32, 0xf5
};
unsigned int x509_rotpk_bin_len = 32;

 

 

RSA .pem file:

-----BEGIN RSA PRIVATE KEY-----
MIIEowIBAAKCAQEA4T91fvEiHwHeNYKY/mgQ4qWUU7CpzzknpOWAy/MQpwrcAUwy
TCX/nq6FrDPa2yyucpL4Sd3zPACTUURFSzSTYwkglm8fjWX+iCgWlvOYYXlA3Zjl
6nSEhe08mIvbdNHuhEF0yEdHZ1JfHkbwhIU8yq4oqh4sdYshAgLC5WmOoSBoVQOz
7uNms1wHo3Hy2hT9TQ5ed0ttKoPVgH5CgyA19yW+TKVjvpK8vqw1KuHnZILxH9V7
Id/ElSuNPgE8JIdghl9k/cA5HQ4dglWu2pVyKZfIC3VGB1+M5uJCQmatIU9dmoHL
sPaWi79Sn/3qhuxu47en96tShDZL9gasy4qoXwIDAQABAoIBAGeBBJnPblF3R0ep
emo1IcU0NwN6A53QcrIoL9YIHFfV+qCyBc7OCzc8lPo7Xc8nKgZGGMfAsLuavBc0
2u6i+zMgB5R4/bO48YxZd3/n8dagpDjvwH7LCfaMvDKQ2chFi2fEuEgr0NjelgzQ
pkcO/o9YFiGN+foNc5577FkE92B8KgRCsXrKHMx8UZLCmM1Fw3LIsTKWQCm+/7SL
2gb+D3GDwuCnMRrKxQ7J6oYVeMZ/dqxkHhfZdZXy6ofmdmxvabJAism1xXBPJaBl
OD1HX+UAdK2bkIEQDWzVhI+sm2K/0N6MkM3xHxf1gnE0H0Icm8hy6FeZuYm65erc
RlIXsXECgYEA+F6e9Wmh2c2SL7mjxYU1cFj7R3OXE6kR7ln3I/QN7fzH2vmcysB/
3+WhHiWA49rGEMQUjHb9AJ+EYcjyz9PXSLWEWd2rd/78i3SFZvmdZIpNsFJVbhao
hELV/6541ehNymr0XmfU9wCnHY3JUq03Yahrlmabt0h2vRGw3vyVJtcCgYEA6Cr9
eInMhisempaXEgloRT61vkxddQXIfwdZ0GMn4uhgnzRPsQHZXWq4iVj5sD1OOID/
R/oF52MhPrItQKf97unAlrsfFwrVwFX+p8wGwg5OY2Vw44ElfQItWaFXgSZLVtPM
2RRO7pDLHn7dnjuEmSuiBX3DgarzixGTE2ajQbkCgYAFi18zDUueqBcmV5ePVjzu
KB5b5vmtZ63Ny1ZYCB+ze1weyEm2wPtZzS9+k8m/zGd1glsPE6zsMaNr52d8Ojdp
GRw+QVONlzSeDFjaBqJ71xaK5BuiHIFginlqfsOVytzJsv+Hh/vaE7qnTz36SYGd
/XuBXQMG4Wg9KkLvh2Xw+wKBgQCBlEz4U+DFGZfxLA+RT5LU4xVI6xJWWC35SD8G
ofEHIi+ba/T2lFOfYgsxDWn+xZi8zLKul4toA9nwRj4fkiOWjvygpDvL/o4i1VxW
hvdWo+l4bIu/Trt/tBFfrz9Jo/f0tC3nEwCjAkl78c77m7h8TPAXJIRUAPgBLIPs
FiMUcQKBgEjAqVqrYpxf/LjVDmE97lzKwR2Yb+BIuzH+4e7QlQEtg9IqVK53+Re1
p4nb46r643RJEkoDLwJqvZQoqngCsSkKCd5jAG1cE9mMyaT/shNDwefYMULf7FLr
ScKN2oP6LVdye+2shTMDKfv6fbb2NQ2E3xYThzhUmNvMnkZbj4d8
-----END RSA PRIVATE KEY-----

 

 

I have used the /keys folder which i first used the create_keys script for and the posted key is the Trustkey.pem

 

Still unable to boot in secure-mode, any help is appreciated.

 

wbr

 

spitfire

 

 

Share this post


Link to post
Share on other sites

looks like your rotpk key is okay

 

verified with:

https://pastebin.com/ShSQFe95

rotpk
00000000  1a 18 e6 e9 8f 9a b1 5f 62 6e 1d f9 d8 9f 2b 65  |......._bn....+e|
00000010  9e e8 73 35 21 3d 9c 6f 47 29 f9 a8 c5 6a 32 f5  |..s5!=.oG)...j2.|

 

only used tocgen from lichee when fuses where all zero, did you try it also with jemk egon2toc.rb?

 

here is my bare metal example of writing the key, use it at own risk! and double check you replaced your rotpk (1a=f6.... 94=f5) correctly:

https://pastebin.com/Aw5q6bdU

 

to read keys create new main and call print_stuff and add a smc instruction before it to be able to print your burned roptk key via fel mode

to run it via fel from sdram:
arm-none-eabi-objcopy -O binary main.elf main.bin
./sunxi-fel version
./sunxi-fel -p write 0x2000 main.bin
./sunxi-fel exe 0x2000

 

 

Share this post


Link to post
Share on other sites

@xeniter

finally good news: i was able to boot the SoC in secure mode...

 

using the jmk's egon2toc did the trick. Before i was using the lichee's toc generator, i guess that has some sort of bug.

I used sunxi-fel to burn my keys.

The keys should be of course burned "little-endian"

 

anyways, thanks for your tremendous work and help.

 

wbr

 

 

Share this post


Link to post
Share on other sites

@xeniter now that secure spl is working, i guess, is there any way to disable fel? as securing the spl does not overcome someone to gain access over fel.... and program the rotpk to all '1' and run their own "certified spl"

i guess there might be a SID-bit to burn after which no modification is allowed to the SID...

 

I will keep digging and see if you have info as well.

Share this post


Link to post
Share on other sites

@spitfirenice to hear that it finally worked

strange that the original tocgen does not work, was lucky that i test the ruby script before.

good point with fel mode, would be very interesting if its possible somehow to disable it

Share this post


Link to post
Share on other sites

can we use this secure mode to run encrypted sd card ?

or its only to be sure the os isn't changed by using trust chain

thanks

Share this post


Link to post
Share on other sites

now its only for verification of the spl bootloader, maybe you could write some aes keys in the fuses and use it later for decryption.

the h3 has also a crypto engine didn't look into deeper it yet, maybe someone has some experience with it already

Share this post


Link to post
Share on other sites

Join the conversation

You can post now and register later. If you have an account, sign in now to post with your account.
Note: Your post will require moderator approval before it will be visible.

Guest
Reply to this topic...

×   Pasted as rich text.   Restore formatting

  Only 75 emoji are allowed.

×   Your link has been automatically embedded.   Display as a link instead

×   Your previous content has been restored.   Clear editor

×   You cannot paste images directly. Upload or insert images from URL.

Loading...
0