From f73634d17c9af8a9df602602bf3e3964e955a3ad Mon Sep 17 00:00:00 2001 From: NIIBE Yutaka Date: Mon, 4 Jun 2012 16:31:40 +0900 Subject: [PATCH] Implement CRC32 check --- ChangeLog | 7 ++++ regnual/regnual.c | 46 ++++++++++++++++++---- src/usb_ctrl.c | 36 ++++++++++++----- tool/gnuk_upgrade.py | 92 ++++++++++++++++++++++++++++++++++++++++++-- 4 files changed, 159 insertions(+), 22 deletions(-) diff --git a/ChangeLog b/ChangeLog index e82d5ca..5043cfa 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,5 +1,12 @@ 2012-06-04 Niibe Yutaka + Implement CRC32 check for firmware update. + * src/usb_ctrl.c (download_check_crc32): New. + * regnual/regnual.c (calc_crc32): New. + (regnual_ctrl_write_finish): Call calc_crc32. + * tool/gnuk_upgrade.py (crc32): New. + (regnual.download): Check crc32code. + * regnual/regnual.c (regnual_ctrl_write_finish): Bug fix. 2012-06-01 Niibe Yutaka diff --git a/regnual/regnual.c b/regnual/regnual.c index 66603c9..eecf698 100644 --- a/regnual/regnual.c +++ b/regnual/regnual.c @@ -147,28 +147,58 @@ static uint32_t result; static const uint8_t *const mem_info[] = { &_flash_start, &_flash_end, }; +static uint32_t fetch (int i) +{ + uint32_t r; + + r = (mem[i*4] << 24) | (mem[i*4+1] << 16) | (mem[i*4+2] << 8) | mem[i*4+3]; + return r; +} + +struct CRC { + __IO uint32_t DR; + __IO uint8_t IDR; + uint8_t RESERVED0; + uint16_t RESERVED1; + __IO uint32_t CR; +}; + +#define CRC_CR_RESET 0x01 +static uint32_t calc_crc32 (void) +{ + struct CRC *CRC = (struct CRC *)0x40023000; + int i; + + CRC->CR = CRC_CR_RESET; + + for (i = 0; i < 256/4; i++) + CRC->DR = fetch (i); + + return CRC->DR; +} + + static void regnual_ctrl_write_finish (uint8_t req, uint8_t req_no, uint16_t value, uint16_t index, uint16_t len) { uint8_t type_rcp = req & (REQUEST_TYPE|RECIPIENT); - if (type_rcp == (VENDOR_REQUEST | DEVICE_RECIPIENT) - && USB_SETUP_SET (req) && len == 0) + if (type_rcp == (VENDOR_REQUEST | DEVICE_RECIPIENT) && USB_SETUP_SET (req)) { if (req_no == USB_REGNUAL_SEND && value == 0) - { - result = 0; // calculate crc32 here!!! - } - else if (req_no == USB_REGNUAL_FLASH && index == 0) + result = calc_crc32 (); + else if (req_no == USB_REGNUAL_FLASH && len == 0 && index == 0) { uint32_t dst_addr = (0x08000000 + value * 0x100); result = flash_write (dst_addr, mem, 256); } - else if (req_no == USB_REGNUAL_PROTECT && value == 0 && index == 0) + else if (req_no == USB_REGNUAL_PROTECT && len == 0 + && value == 0 && index == 0) result = flash_protect (); - else if (req_no == USB_REGNUAL_FINISH && value == 0 && index == 0) + else if (req_no == USB_REGNUAL_FINISH && len == 0 + && value == 0 && index == 0) nvic_system_reset (); } } diff --git a/src/usb_ctrl.c b/src/usb_ctrl.c index 9c80e78..f43f229 100644 --- a/src/usb_ctrl.c +++ b/src/usb_ctrl.c @@ -26,6 +26,7 @@ #include "config.h" #include "ch.h" +#include "hal.h" #include "usb_lld.h" #include "usb_conf.h" #include "gnuk.h" @@ -187,17 +188,30 @@ static const uint8_t *const mem_info[] = { &_regnual_start, &__heap_end__, }; #define USB_FSIJ_GNUK_DOWNLOAD 1 #define USB_FSIJ_GNUK_EXEC 2 -static int download_check_crc32 (const uint8_t *p) +static uint32_t reverse32 (uint32_t v) { - uint32_t crc32 = 0; + uint32_t r; - crc32 += (*--p << 24); - crc32 += (*--p << 16); - crc32 += (*--p << 8); - crc32 += (*--p); + r = (v << 24) | ((v & 0xff00) << 8) | ((v & 0xff0000) >> 8) | (v >> 24); + return r; +} - /* Not yet: Calculate crc32 from &_regnual_start to p, then compare */ - return USB_SUCCESS; +/* After calling this function, CRC module remain enabled. */ +static int download_check_crc32 (const uint32_t *end_p) +{ + uint32_t crc32 = *end_p; + const uint32_t *p; + + RCC->AHBENR |= RCC_AHBENR_CRCEN; + CRC->CR = CRC_CR_RESET; + + for (p = (const uint32_t *)&_regnual_start; p < end_p; p++) + CRC->DR = reverse32 (*p); + + if ((CRC->DR ^ crc32) == 0xffffffff) + return USB_SUCCESS; + + return USB_UNSUPPORT; } static int @@ -239,8 +253,10 @@ gnuk_setup (uint8_t req, uint8_t req_no, if (icc_state_p == NULL || *icc_state_p != ICC_STATE_EXITED) return USB_UNSUPPORT; - /* There is a trailer at addr: crc32 */ - return download_check_crc32 (addr); + if (((uint32_t)addr & 0x03)) + return USB_UNSUPPORT; + + return download_check_crc32 ((uint32_t *)addr); } } } diff --git a/tool/gnuk_upgrade.py b/tool/gnuk_upgrade.py index 9677a01..18ed48b 100755 --- a/tool/gnuk_upgrade.py +++ b/tool/gnuk_upgrade.py @@ -83,6 +83,13 @@ class regnual: value = 0, index = 0, buffer = data[j*256:j*256+256], timeout = 10000) + crc32code = crc32(data[j*256:j*256+256], 0xffffffff) + res = self.__devhandle.controlMsg(requestType = 0xc0, request = 2, + value = 0, index = 0, buffer = 4, + timeout = 10000) + r_value = ((res[3]*256 + res[2])*256 + res[1])*256 + res[0] + if (crc32code ^ r_value) != 0xffffffff: + print "failure" self.__devhandle.controlMsg(requestType = 0x40, request = 3, value = i, index = 0, buffer = None, @@ -104,6 +111,13 @@ class regnual: value = 0, index = 0, buffer = data[j*256:], timeout = 10000) + crc32code = crc32(data[j*256:].ljust(256,chr(255)), 0xffffffff) + res = self.__devhandle.controlMsg(requestType = 0xc0, request = 2, + value = 0, index = 0, buffer = 4, + timeout = 10000) + r_value = ((res[3]*256 + res[2])*256 + res[1])*256 + res[0] + if (crc32code ^ r_value) != 0xffffffff: + print "failure" self.__devhandle.controlMsg(requestType = 0x40, request = 3, value = i, index = 0, buffer = None, @@ -397,9 +411,79 @@ def gpg_sign(keygrip, hash): raise ValueError, binascii.hexlify(signed) return signed -def main(keygrip, data_regnual, data_upgrade): - data_regnual += pack('>24)^ord(b) + crc = UNSIGNED((crc << 8)) ^ crctab[idx] + return UNSIGNED(~crc) + +def main(keygrip, data_regnual, data_upgrade): + l = len(data_regnual) + if (l & 0x03) != 0: + data_regnual = data_regnual.ljust(l + 4 - (l & 0x03), chr(0)) + crc32code = crc32(data_regnual, 0xffffffff) + print "CRC32: %04x\n" % crc32code + data_regnual += pack('