diff options
author | Vencislav Atanasov <user890104@freemyipod.org> | 2024-12-11 00:04:07 +0200 |
---|---|---|
committer | Vencislav Atanasov <user890104@freemyipod.org> | 2024-12-11 00:04:26 +0200 |
commit | 4d632a1774d88b8f1d3f96a578a0c376fb5944bb (patch) | |
tree | baed7d95457d0298185f99c6467b319d482dfe1b | |
parent | 68c51456ff8e85795a69acbd11e8eb9b0c64da10 (diff) | |
download | rockbox-4d632a1774.tar.gz rockbox-4d632a1774.zip |
S5L8702: Move IM3 sign/crypt functions from norboot to crypto
Also adds support for IM3 functions and SHA-1 on S5L8720.
Tested on ipod6g (normal and bootloader builds)
This is a part of the large iPod Nano 3G and iPod Nano 4G support patch.
Credit: Cástor Muñoz <cmvidal@gmail.com>
Change-Id: Ic5e6f5a3321d4b1ec4efd753a4c30e29d83fd7c2
-rw-r--r-- | firmware/target/arm/s5l8702/crypto-s5l8702.c | 32 | ||||
-rw-r--r-- | firmware/target/arm/s5l8702/crypto-s5l8702.h | 51 | ||||
-rw-r--r-- | firmware/target/arm/s5l8702/norboot-s5l8702.c | 23 | ||||
-rw-r--r-- | firmware/target/arm/s5l8702/norboot-target.h | 39 |
4 files changed, 86 insertions, 59 deletions
diff --git a/firmware/target/arm/s5l8702/crypto-s5l8702.c b/firmware/target/arm/s5l8702/crypto-s5l8702.c index 0788177de7..a6f148112f 100644 --- a/firmware/target/arm/s5l8702/crypto-s5l8702.c +++ b/firmware/target/arm/s5l8702/crypto-s5l8702.c @@ -68,6 +68,10 @@ void sha1(void* data, uint32_t size, void* hash) while (SHA1CONFIG & 1); SHA1RESET = 0; SHA1CONFIG = 0; +#if CONFIG_CPU == S5L8720 + SHA1UNK10 = 0; + SHA1UNK80 = 0; +#endif while (!done) { space = ((uint32_t)databuf) - ((uint32_t)data) - size + 64; @@ -100,3 +104,31 @@ void sha1(void* data, uint32_t size, void* hash) for (i = 0; i < 5; i++) *hashbuf++ = SHA1RESULT[i]; clockgate_enable(CLOCKGATE_SHA, false); } + + +/* + * IM3 + */ +static inline uint32_t get_uint32le(unsigned char *p) +{ + return p[0] | (p[1] << 8) | (p[2] << 16) | (p[3] << 24); +} + +/* calculates SHA1, truncate the result to 128 bits, and encrypt it */ +void im3_sign(uint32_t keyidx, void* data, uint32_t size, void* sign) +{ + unsigned char hash[SHA1_SZ]; + sha1(data, size, hash); + memcpy(sign, hash, SIGN_SZ); + hwkeyaes(HWKEYAES_ENCRYPT, keyidx, sign, SIGN_SZ); +} + +/* only supports enc_type 1 and 2 (UKEY) */ +void im3_crypt(enum hwkeyaes_direction direction, + struct Im3Info *hinfo, void *fw_addr) +{ + uint32_t fw_size = get_uint32le(hinfo->data_sz); + hinfo->enc_type = (direction == HWKEYAES_ENCRYPT) ? 1 : 2; + im3_sign(HWKEYAES_UKEY, hinfo, IM3INFOSIGN_SZ, hinfo->info_sign); + hwkeyaes(direction, HWKEYAES_UKEY, fw_addr, fw_size); +} diff --git a/firmware/target/arm/s5l8702/crypto-s5l8702.h b/firmware/target/arm/s5l8702/crypto-s5l8702.h index 541a67889c..e9f923589c 100644 --- a/firmware/target/arm/s5l8702/crypto-s5l8702.h +++ b/firmware/target/arm/s5l8702/crypto-s5l8702.h @@ -25,7 +25,52 @@ #include "config.h" + +/* IM3 */ +#if CONFIG_CPU == S5L8702 +#define IM3_IDENT "8702" +#define IM3_VERSION "1.0" +#define IM3HDR_SZ 0x800 +#elif CONFIG_CPU == S5L8720 +#define IM3_IDENT "8720" +#define IM3_VERSION "2.0" +#define IM3HDR_SZ 0x600 +#endif + #define SHA1_SZ 20 /* bytes */ +#define SIGN_SZ 16 + +#ifndef ASM +#define IM3INFO_SZ (sizeof(struct Im3Info)) +#define IM3INFOSIGN_SZ (offsetof(struct Im3Info, info_sign)) + +struct Im3Info +{ + uint8_t ident[4]; + uint8_t version[3]; + uint8_t enc_type; + uint8_t entry[4]; /* LE */ + uint8_t data_sz[4]; /* LE */ + union { + struct { + uint8_t data_sign[SIGN_SZ]; + uint8_t _reserved[32]; + } enc12; + struct { + uint8_t sign_off[4]; /* LE */ + uint8_t cert_off[4]; /* LE */ + uint8_t cert_sz[4]; /* LE */ + uint8_t _reserved[36]; + } enc34; + } u; + uint8_t info_sign[SIGN_SZ]; +} __attribute__ ((packed)); + +struct Im3Hdr +{ + struct Im3Info info; + uint8_t _zero[IM3HDR_SZ - sizeof(struct Im3Info)]; +} __attribute__ ((packed)); enum hwkeyaes_direction { @@ -43,4 +88,10 @@ void hwkeyaes(enum hwkeyaes_direction direction, uint32_t keyidx, void* data, uint32_t size); void sha1(void* data, uint32_t size, void* hash); +void im3_sign(uint32_t keyidx, void* data, uint32_t size, void* sign); +void im3_crypt(enum hwkeyaes_direction direction, + struct Im3Info *hinfo, void *fw_addr); + +#endif /* ASM */ + #endif /* __CRYPTO_S5L8702_H__ */ diff --git a/firmware/target/arm/s5l8702/norboot-s5l8702.c b/firmware/target/arm/s5l8702/norboot-s5l8702.c index f0175a02af..21dc178995 100644 --- a/firmware/target/arm/s5l8702/norboot-s5l8702.c +++ b/firmware/target/arm/s5l8702/norboot-s5l8702.c @@ -206,36 +206,19 @@ void bootflash_write(int port, int offset, void* addr, int size) /* * IM3 */ -static uint32_t get_uint32le(unsigned char *p) +static inline uint32_t get_uint32le(unsigned char *p) { return p[0] | (p[1] << 8) | (p[2] << 16) | (p[3] << 24); } +// TODO: rename to bootflash_im3_sz(), norboot_im3_sz() or nb_im3_sz() /* return full IM3 size aligned to NOR sector size */ unsigned im3_nor_sz(struct Im3Info* hinfo) { return ALIGN_UP(IM3HDR_SZ + get_uint32le(hinfo->data_sz), 0x1000); } -/* calculates SHA1, truncate the result to 128 bits, and encrypt it */ -void im3_sign(uint32_t keyidx, void* data, uint32_t size, void* sign) -{ - unsigned char hash[SHA1_SZ]; - sha1(data, size, hash); - memcpy(sign, hash, SIGN_SZ); - hwkeyaes(HWKEYAES_ENCRYPT, keyidx, sign, SIGN_SZ); -} - -/* only supports enc_type 1 and 2 (UKEY) */ -void im3_crypt(enum hwkeyaes_direction direction, - struct Im3Info *hinfo, void *fw_addr) -{ - uint32_t fw_size = get_uint32le(hinfo->data_sz); - hinfo->enc_type = (direction == HWKEYAES_ENCRYPT) ? 1 : 2; - im3_sign(HWKEYAES_UKEY, hinfo, IM3INFOSIGN_SZ, hinfo->info_sign); - hwkeyaes(direction, HWKEYAES_UKEY, fw_addr, fw_size); -} - +// TODO: norboot_im3_read(), on s5l8720 we could set nandboot_im3_read(), then norboot_ and nandboot_ could go to boot-s5l8702.c int im3_read(uint32_t offset, struct Im3Info *hinfo, void *fw_addr) { unsigned char hash[SIGN_SZ]; diff --git a/firmware/target/arm/s5l8702/norboot-target.h b/firmware/target/arm/s5l8702/norboot-target.h index 3d2790d123..36b8643d0f 100644 --- a/firmware/target/arm/s5l8702/norboot-target.h +++ b/firmware/target/arm/s5l8702/norboot-target.h @@ -119,46 +119,7 @@ struct SysCfgEntry { /* * IM3 */ -#define IM3_IDENT "8702" -#define IM3_VERSION "1.0" -#define IM3HDR_SZ 0x800 -#define IM3INFO_SZ (sizeof(struct Im3Info)) -#define IM3INFOSIGN_SZ (offsetof(struct Im3Info, info_sign)) - -#define SIGN_SZ 16 - -struct Im3Info -{ - uint8_t ident[4]; - uint8_t version[3]; - uint8_t enc_type; - uint8_t entry[4]; /* LE */ - uint8_t data_sz[4]; /* LE */ - union { - struct { - uint8_t data_sign[SIGN_SZ]; - uint8_t _reserved[32]; - } enc12; - struct { - uint8_t sign_off[4]; /* LE */ - uint8_t cert_off[4]; /* LE */ - uint8_t cert_sz[4]; /* LE */ - uint8_t _reserved[36]; - } enc34; - } u; - uint8_t info_sign[SIGN_SZ]; -} __attribute__ ((packed)); - -struct Im3Hdr -{ - struct Im3Info info; - uint8_t _zero[IM3HDR_SZ - sizeof(struct Im3Info)]; -} __attribute__ ((packed)); - unsigned im3_nor_sz(struct Im3Info* hinfo); -void im3_sign(uint32_t keyidx, void* data, uint32_t size, void* sign); -void im3_crypt(enum hwkeyaes_direction direction, - struct Im3Info *hinfo, void *fw_addr); int im3_read(uint32_t offset, struct Im3Info *hinfo, void *fw_addr); bool im3_write(int offset, void *im3_addr); |