diff --git a/.travis.yml b/.travis.yml index 4f6e1a8bd6..97670eb684 100644 --- a/.travis.yml +++ b/.travis.yml @@ -8,6 +8,7 @@ before_install: install: - sudo apt-get install -y build-essential gcc-multilib gcc-arm-embedded + - sudo apt-get install python-pil script: - make build_cross diff --git a/micropython/loader/main.c b/micropython/loader/main.c index 9b13d2c8b2..b23443b348 100644 --- a/micropython/loader/main.c +++ b/micropython/loader/main.c @@ -17,16 +17,26 @@ void pendsv_isr_handler(void) { void check_and_jump(void) { LOADER_PRINTLN("checking firmware"); - // TODO: check vendor header and its signature - uint32_t vhdrlen = *((const uint32_t *) (FIRMWARE_START + 4)); - if (image_check_signature((const uint8_t *) (FIRMWARE_START + vhdrlen))) { + + vendor_header vhdr; + if (!vendor_parse_header((const uint8_t *)(FIRMWARE_START), &vhdr)) { + LOADER_PRINTLN("invalid vendor header"); + return; + } + if (!vendor_check_signature((const uint8_t *)(FIRMWARE_START))) { + LOADER_PRINTLN("unsigned vendor header"); + return; + } + + // TODO: use keys from vendor header in image_check_signature + if (image_check_signature((const uint8_t *)(FIRMWARE_START + vhdr.hdrlen))) { LOADER_PRINTLN("valid firmware image"); // TODO: remove debug wait LOADER_PRINTLN("waiting 1 second"); HAL_Delay(1000); // end LOADER_PRINTLN("JUMP!"); - jump_to(FIRMWARE_START + vhdrlen + HEADER_SIZE); + jump_to(FIRMWARE_START + vhdr.hdrlen + HEADER_SIZE); } else { LOADER_PRINTLN("invalid firmware image"); } diff --git a/micropython/trezorhal/image.c b/micropython/trezorhal/image.c index c609120ef9..4b6a3c5aad 100644 --- a/micropython/trezorhal/image.c +++ b/micropython/trezorhal/image.c @@ -93,3 +93,72 @@ bool image_check_signature(const uint8_t *data) return pub && (0 == ed25519_sign_open(hash, BLAKE2S_DIGEST_LENGTH, *(const ed25519_public_key *)pub, *(const ed25519_signature *)hdr.sig)); } + +bool vendor_parse_header(const uint8_t *data, vendor_header *header) +{ + if (!header) { + vendor_header h; + header = &h; + } + + memcpy(&header->magic, data, 4); + if (header->magic != 0x565A5254) return false; // TRZV + + memcpy(&header->hdrlen, data + 4, 4); + + memcpy(&header->expiry, data + 8, 4); + if (header->expiry != 0) return false; + + memcpy(&header->version, data + 12, 2); + + memcpy(&header->vsig_m, data + 14, 1); + memcpy(&header->vsig_n, data + 15, 1); + + for (int i = 0; i < header->vsig_n; i++) { + header->vpub[i] = data + 16 + i * 32; + } + for (int i = header->vsig_n; i < 8; i++) { + header->vpub[i] = 0; + } + + memcpy(&header->vstr_len, data + 16 + header->vsig_n * 32, 1); + + header->vstr = data + 16 + header->vsig_n * 32 + 1; + + header->vimg = data + 16 + header->vsig_n * 32 + 1 + header->vstr_len; + // align to 4 bytes + header->vimg += (-(uintptr_t)header->vimg) & 3; + + // uint8_t reserved[427]; + + memcpy(&header->sigmask, data + header->hdrlen - 65, 1); + + memcpy(header->sig, data + header->hdrlen - 64, 64); + + return true; +} + +bool vendor_check_signature(const uint8_t *data) +{ + vendor_header hdr; + if (!vendor_parse_header(data, &hdr)) { + return false; + } + + uint8_t hash[BLAKE2S_DIGEST_LENGTH]; + BLAKE2S_CTX ctx; + blake2s_Init(&ctx, BLAKE2S_DIGEST_LENGTH); + blake2s_Update(&ctx, data, hdr.hdrlen - 65); + for (int i = 0; i < 65; i++) { + blake2s_Update(&ctx, (const uint8_t *)"\x00", 1); + } + blake2s_Final(&ctx, hash, BLAKE2S_DIGEST_LENGTH); + + const uint8_t *pub = get_pubkey(hdr.sigmask); + + // TODO: remove debug skip of unsigned + if (!pub) return true; + // end + + return pub && (0 == ed25519_sign_open(hash, BLAKE2S_DIGEST_LENGTH, *(const ed25519_public_key *)pub, *(const ed25519_signature *)hdr.sig)); +} diff --git a/micropython/trezorhal/image.h b/micropython/trezorhal/image.h index e7b4808826..8c4bd3b02f 100644 --- a/micropython/trezorhal/image.h +++ b/micropython/trezorhal/image.h @@ -17,8 +17,27 @@ typedef struct { uint8_t sig[64]; } image_header; +typedef struct { + uint32_t magic; + uint32_t hdrlen; + uint32_t expiry; + uint16_t version; + uint8_t vsig_m; + uint8_t vsig_n; + const uint8_t *vpub[8]; + uint8_t vstr_len; + const uint8_t *vstr; + const uint8_t *vimg; + uint8_t sigmask; + uint8_t sig[64]; +} vendor_header; + bool image_parse_header(const uint8_t *data, image_header *header); bool image_check_signature(const uint8_t *data); +bool vendor_parse_header(const uint8_t *data, vendor_header *header); + +bool vendor_check_signature(const uint8_t *data); + #endif