From 7ebd56579f5e90861c39fdf46fa7d53446cfeccf Mon Sep 17 00:00:00 2001 From: Linus Nordberg Date: Wed, 18 May 2016 12:07:50 +0200 Subject: Read from and write to MKM when panic button is pressed. --- Makefile | 14 ++++ README.md | 33 +++++++++ tamper.c | 227 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ upload.sh | 6 ++ 4 files changed, 280 insertions(+) create mode 100644 Makefile create mode 100644 README.md create mode 100644 tamper.c create mode 100755 upload.sh diff --git a/Makefile b/Makefile new file mode 100644 index 0000000..8ac277b --- /dev/null +++ b/Makefile @@ -0,0 +1,14 @@ +CC = avr-gcc +CFLAGS = -Wall -Werror -mmcu=avr25 -D__AVR_ATtiny828__ +OBJCOPY = avr-objcopy + +all: tamper.hex + +%.elf: %.c + $(CC) $(CFLAGS) -o $@ $^ + +%.hex: %.elf + $(OBJCOPY) -O ihex $< $@ + +clean: + -rm *.o *.elf *.hex diff --git a/README.md b/README.md new file mode 100644 index 0000000..2ccba7d --- /dev/null +++ b/README.md @@ -0,0 +1,33 @@ +Tamper detection for Atmel AVR ATtiny828 MCU on the Cryptech alpha +board, rev02. + + ************* + * P A N I C * + * button * + ************* + / + / + / + AVR ---- SPI mux ---- FPGA + | | + | ARM + MKM + +AVR -- Atmel MCU +FPGA -- FPGA +MKM -- Master Key Memory, 23K640 SRAM +SPI mux -- 2 x MC74AC244DW +ARM -- ARM CPU + +The MKM holds the master key for the device. + +The AVR, MKM and the mux are battery powered. + +The AVR and the FPGA are sharing access to the MKM through the mux, +with the AVR connected to the pins used for deciding who's in control +of the memory. The FPGA is in control by default. + +When the panic button is pressed, the AVR grabs the MKM and writes +zeros to it as quickly as possible. In idle mode, i.e. when the panic +button is not pressed, the AVR tries to consume as little power as +possible. diff --git a/tamper.c b/tamper.c new file mode 100644 index 0000000..ca3cb2d --- /dev/null +++ b/tamper.c @@ -0,0 +1,227 @@ +/* FIXME: copyright */ + +#include +#include /* -D__AVR_ATtiny828__ will include */ + +/* Mapping of pins to names. */ +#define AVR_LED1 PORTA0 +#define AVR_LED2 PORTA3 +#define AVR_LED3 PORTA2 +#define AVR_LED4 PORTA1 +#define AVR_PANIC PORTA4 + +#define MKM_AVR_CS_N PORTA5 +#define MKM_CONTROL_AVR_ENA PORTA6 +#define MKM_CONTROL_FPGA_DIS PORTA7 + +#define MKM_AVR_MOSI PORTD0 +#define MKM_AVR_MISO PORTD1 +#define MKM_AVR_SCK PORTD3 + + +/* Input pins. */ +#define AVR_PANIC_PIN PINA /* Panic button. */ +#define AVR_PANIC_BIT PINA4 /* 0 = panic. */ + +/* Output ports. */ +#define AVR_LED_PORT PORTA +#define AVR_LED_BLUE_BIT PORTA0 +#define AVR_LED_RED_BIT PORTA3 +#define AVR_LED_YELLOW_BIT PORTA2 +#define AVR_LED_GREEN_BIT PORTA1 + +#define MKM_CS_PORT PORTA /* MKM chip select. */ +#define MKM_CS_BIT MKM_AVR_CS_N /* 0 -> selected. */ + +#define MKM_CONTROL_AVR_PORT PORTA /* AVR in control. */ +#define MKM_CONTROL_AVR_BIT MKM_CONTROL_AVR_ENA /* 0 -> in control. */ + +#define MKM_CONTROL_FPGA_PORT PORTA /* FPGA in control. */ +#define MKM_CONTROL_FPGA_BIT MKM_CONTROL_FPGA_DIS /* 0 -> in control. */ + +/* SPI. */ +#define MKM_AVR_MOSI_PORT PORTD +#define MKM_AVR_MOSI_BIT MKM_AVR_MOSI /* PD0, Master Out Slave In. */ +#define MKM_AVR_MISO_PORT PORTD +#define MKM_AVR_MISO_BIT PORTD1 /* PD1, Master In Slave Out. */ +#define MKM_AVR_SCK_PORT PORTD +#define MKM_AVR_SCK_BIT PORTD3 /* PD3, SPI clock. */ + +/*******/ +/* MKM */ +static inline void +mkm_chip_select(int select_flag) +{ + if (select_flag) + MKM_CS_PORT &= ~_BV(MKM_CS_BIT); /* CS low. */ + else + MKM_CS_PORT |= _BV(MKM_CS_BIT); /* CS high. */ +} + +static inline void +mkm_grab() +{ + MKM_CONTROL_FPGA_PORT |= _BV(MKM_CONTROL_FPGA_BIT); + MKM_CONTROL_AVR_PORT &= ~_BV(MKM_CONTROL_AVR_BIT); +} + +static inline void +mkm_release() +{ + MKM_CONTROL_AVR_PORT |= _BV(MKM_CONTROL_AVR_BIT); + MKM_CONTROL_FPGA_PORT &= ~_BV(MKM_CONTROL_FPGA_BIT); +} + +/*******/ +/* SPI */ +#define SPI_SS DDRC0 /* SPI slave select. */ + +static inline void +spi_setup(int on_flag) +{ + if (on_flag) + { + /* Disable SPI power reduction. */ + PRR &= ~_BV(PRSPI); + + /* Set MOSI and SCK to output. */ + DDRD = _BV(MKM_AVR_MOSI_BIT) | _BV(MKM_AVR_SCK_BIT); + + /* Make sure SPI slave select (SS) is configured as output before + enabling SPI master mode!. */ + DDRC |= _BV(SPI_SS); + + /* Enable SPI in master mode, clock rate f/16. */ + SPCR = _BV(SPE) | _BV(MSTR) | _BV(SPR0); + } + else + { + SPCR &= ~_BV(SPE); + PRR |= _BV(PRSPI); + } +} + +/* SPI commands for MKM (23K640). */ +#define SPI_READ 0x03 +#define SPI_WRITE 0x02 +#define SPI_RDSR 0x05 /* Read status register. */ +#define SPI_WRSR 0x01 /* Write status register. */ + +static inline void +spi_write(uint8_t val) +{ + SPDR = val; + loop_until_bit_is_set(SPSR, SPIF); +} + +static inline uint8_t +spi_read() +{ + spi_write(0); + return SPDR; +} + +static inline uint8_t +spi_read_status() +{ + spi_write(SPI_RDSR); + return SPDR; +} + +static inline void +spi_set_operation_byte() +{ + spi_write(SPI_WRSR); + spi_write(0x00); +} + +static inline void +spi_set_operation_page() +{ + spi_write(SPI_WRSR); + spi_write(0x80); +} + +static inline void +spi_set_operation_seq() +{ + spi_write(SPI_WRSR); + spi_write(0x40); +} + +static void +spi_write_byte(uint16_t addr, uint8_t data) +{ + mkm_chip_select(1); + spi_write(SPI_WRITE); + spi_write(addr & 0xff00); + spi_write(addr & 0x00ff); + spi_write(data); + mkm_chip_select(0); +} + +static uint8_t +spi_read_byte(uint16_t addr) +{ + mkm_chip_select(1); + spi_write(SPI_READ); + spi_write(addr & 0xff00); + spi_write(addr & 0x00ff); + uint8_t data = spi_read(); + mkm_chip_select(0); + return data; +} + +static inline int +panic_p() +{ + return !bit_is_set(AVR_PANIC_PIN, AVR_PANIC_BIT); +} + + +static inline void +init_ports() +{ + /* Configure all PORTA pins except the tamper detection pin to + outputs. */ + DDRA = 0xff & ~_BV(AVR_PANIC_BIT); +} + +int +main() +{ + init_ports(); + + int i, j = 0, wait; + uint8_t mkm_val = 0; + while (1) + { + if (panic_p()) + { + spi_setup(1); + mkm_grab(); + + spi_write_byte(0, spi_read_byte(0) + 1); + mkm_val = spi_read_byte(0); + AVR_LED_PORT = (AVR_LED_PORT & 0xf0) | (mkm_val & 0x0f); + + wait = 32000; + } + else + { + mkm_release(); + spi_setup(0); + + if ((j++ & 1) == 0) + AVR_LED_PORT = (AVR_LED_PORT & 0xf0) | 0xa; + else + AVR_LED_PORT = (AVR_LED_PORT & 0xf0) | 0x5; + + wait = 16000; + } + + for (i = 0; i < wait; i++); + } + + return 0; +} diff --git a/upload.sh b/upload.sh new file mode 100755 index 0000000..d34d4ed --- /dev/null +++ b/upload.sh @@ -0,0 +1,6 @@ +#! /bin/sh + +HEXFILE=$1 +[ -z "$HEXFILE" ] && exit 1 + +avrdude -c usbtiny -p attiny828 -U flash:w:$HEXFILE -- cgit v1.2.3