Esempio n. 1
0
int main()
{
    static char address[5];

    sd_mbr_command(&startSdCmd);
    sd_softdevice_vector_table_base_set(BOOTLOADER_ADDRESS);

    // If the master boot switch has detected short or no click: boot the firmware
    if (((NRF_POWER->GPREGRET&0x86U) != 0x82U) &&
            ((NRF_POWER->GPREGRET&0x40U) != 0x40U) &&
            (*(uint32_t *)FW_ADDRESS != 0xFFFFFFFFU) ) {
        start_firmware();
    }

    if (NRF_POWER->GPREGRET&0x40U) {
        address[4] = 0xb1;
        memcpy(&address[0], (char*)&NRF_FICR->DEVICEADDR[0], 4);
        esbSetAddress(address);
    }

    NRF_POWER->GPREGRET &= ~(0x60U);

    // Enable the radio LNA
    nrf_gpio_cfg_output(RADIO_PAEN_PIN);
    nrf_gpio_pin_set(RADIO_PAEN_PIN);

    // Initialize timer module.
    APP_TIMER_INIT(APP_TIMER_PRESCALER, APP_TIMER_MAX_TIMERS, APP_TIMER_OP_QUEUE_SIZE, false);

    ble_init();
    /*
      NRF_CLOCK->LFCLKSRC = CLOCK_LFCLKSTAT_SRC_Synth;

      NRF_CLOCK->TASKS_LFCLKSTART = 1UL;
      while(!NRF_CLOCK->EVENTS_LFCLKSTARTED);
    */
    systickInit();
    buttonInit(buttonIdle);

#ifndef DEBUG_TIMESLOT
    //sd_ppi_channel_assign(0, &(NRF_TIMER1->EVENTS_COMPARE[0]), &(NRF_GPIOTE->TASKS_OUT[0]));
    //sd_ppi_channel_enable_set(PPI_CHEN_CH0_Msk);

    //NRF_PPI->CH[0].EEP = &(NRF_TIMER1->EVENTS_COMPARE[0]);
    //NRF_PPI->CH[0].TEP = &(NRF_GPIOTE->TASKS_OUT[0]);
    //NRF_PPI->CHENSET = 1;
#endif

    // Start (or continue) to blink  the LED at 0.5Hz
    //NRF_TIMER1->TASKS_STOP = 1;

    //NRF_TIMER1->MODE      = TIMER_MODE_MODE_Timer;
    //NRF_TIMER1->PRESCALER = 7;
    //NRF_TIMER1->BITMODE = TIMER_BITMODE_BITMODE_16Bit << TIMER_BITMODE_BITMODE_Pos;
    //NRF_TIMER1->SHORTS = TIMER_SHORTS_COMPARE0_CLEAR_Msk; // | TIMER_SHORTS_COMPARE1_CLEAR_Msk;

    //NRF_TIMER1->TASKS_CLEAR = 1;

    NRF_TIMER1->CC[0] = 1*SEC; //0x1E84 ;
    NRF_TIMER1->CC[1] = 2*SEC;


    nrf_gpio_cfg_output(LED_PIN);

    nrf_gpiote_task_config(0,
                           LED_PIN,
                           NRF_GPIOTE_POLARITY_TOGGLE,
                           NRF_GPIOTE_INITIAL_VALUE_LOW);
    NRF_TIMER1->TASKS_START = 1;


    // Enable 500mA USB input and enable battery charging
    nrf_gpio_cfg_output(PM_EN1);
    nrf_gpio_pin_set(PM_EN1);
    nrf_gpio_cfg_output(PM_EN2);
    nrf_gpio_pin_clear(PM_EN2);
    nrf_gpio_cfg_output(PM_CHG_EN);
    nrf_gpio_pin_clear(PM_CHG_EN);


    // Power STM32, hold reset
    nrf_gpio_cfg_output(PM_VCCEN_PIN);
    nrf_gpio_pin_set(PM_VCCEN_PIN);
    nrf_gpio_cfg_output(STM_NRST_PIN);
    nrf_gpio_pin_clear(STM_NRST_PIN);

    // Set flow control and activate pull-down on RX data pin
    nrf_gpio_cfg_output(UART_TX_PIN);
    nrf_gpio_pin_set(UART_TX_PIN);
    nrf_gpio_cfg_output(UART_RTS_PIN);
    nrf_gpio_pin_set(UART_RTS_PIN);
    nrf_gpio_cfg_input(UART_RX_PIN, NRF_GPIO_PIN_PULLDOWN);


    nrf_gpio_pin_set(STM_NRST_PIN);

    //systickInit();
    //syslinkInit();
    //buttonInit();

//  nrf_gpio_cfg_input(BUTTON_PIN, NRF_GPIO_PIN_PULLUP);

    mainLoop();

    while(1);
}
Esempio n. 2
0
/*! \fn     main(void)
*   \brief  Main function
*   \note   For our security chain to be valid, EEP_BOOT_PWD_SET in eeprom needs to be set to BOOTLOADER_PWDOK_KEY
*/
int main(void)
{
    /* Fetch bootkey in eeprom */
    uint16_t current_bootkey_val = eeprom_read_word((uint16_t*)EEP_BOOTKEY_ADDR);                                       // Bootkey in EEPROM
    uint8_t new_aes_key[AES_KEY_LENGTH/8];                                                                              // New AES encryption key
    uint8_t cur_aes_key[AES_KEY_LENGTH/8];                                                                              // AES encryption key
    uint8_t firmware_data[SPM_PAGESIZE];                                                                                // One page of firmware data
    aes256_context temp_aes_context;                                                                                    // AES context
    uint8_t cur_cbc_mac[16];                                                                                            // Current CBCMAC val
    uint8_t temp_data[16];                                                                                              // Temporary 16 bytes array
    RET_TYPE flash_init_result;                                                                                         // Flash initialization result
    uint16_t firmware_start_address = UINT16_MAX - MAX_FIRMWARE_SIZE - sizeof(cur_cbc_mac) - sizeof(cur_aes_key) + 1;   // Start address of firmware in external memory
    uint16_t firmware_end_address = UINT16_MAX - sizeof(cur_cbc_mac) - sizeof(cur_aes_key) + 1;                         // End address of firmware in external memory


    /* Just in case we are going to disable the watch dog timer and disable interrupts */
    cli();
    wdt_reset();
    wdt_clear_flag();
    wdt_change_enable();
    wdt_stop();

    /* Check fuses: 2k words, SPIEN, BOD 4.3V, BOOTRST programming & ver disabled >> http://www.engbedded.com/fusecalc/ */
    if ((boot_lock_fuse_bits_get(GET_LOW_FUSE_BITS) != 0xFF) || (boot_lock_fuse_bits_get(GET_HIGH_FUSE_BITS) != 0xD8) || (boot_lock_fuse_bits_get(GET_EXTENDED_FUSE_BITS) != 0xF8) || (boot_lock_fuse_bits_get(GET_LOCK_BITS) != 0xFC))
    {
        while(1);
    }

    /* If security isn't set in place yet, no point in launching the bootloader */
    if (eeprom_read_byte((uint8_t*)EEP_BOOT_PWD_SET) != BOOTLOADER_PWDOK_KEY)
    {
        start_firmware();
    }

    /* Check if the device is booting normally, if the bootloader was called, or unknown state */
    if (current_bootkey_val == CORRECT_BOOTKEY)
    {
        /* Security system set, correct bootkey for firmware */
        start_firmware();
    }
    else if (current_bootkey_val != BOOTLOADER_BOOTKEY)
    {
        /* Security system set, bootkey isn't the bootloader one nor the main fw one... */
        while(1);
    }

    /* By default, brick the device so it's an all or nothing update procedure */
    eeprom_write_word((uint16_t*)EEP_BOOTKEY_ADDR, BRICKED_BOOTKEY);

    /* Init IOs */
    UHWCON = 0x01;                          // Enable USB 3.3V LDO
    initFlashIOs();                         // Init EXT Flash IOs
    spiUsartBegin();                        // Init SPI Controller    
    DDR_ACC_SS |= (1 << PORTID_ACC_SS);     // Setup PORT for the Accelerometer SS
    PORT_ACC_SS |= (1 << PORTID_ACC_SS);    // Setup PORT for the Accelerometer SS    
    DDR_OLED_SS |= (1 << PORTID_OLED_SS);   // Setup PORT for the OLED SS
    PORT_OLED_SS |= (1 << PORTID_OLED_SS);  // Setup PORT for the OLED SS
    for (uint16_t i = 0; i < 20000; i++) asm volatile ("NOP");

    /* Disable I2C block of the Accelerometer */
    PORT_ACC_SS &= ~(1 << PORTID_ACC_SS);
    spiUsartTransfer(0x23);
    spiUsartTransfer(0x02);
    PORT_ACC_SS |= (1 << PORTID_ACC_SS);

    /* Check Flash */
    flash_init_result = checkFlashID();
    if (flash_init_result != RETURN_OK)
    {
        while(1);
    }

    for (uint8_t pass_number = 0; pass_number < 2; pass_number++)
    {
        /* Init CBCMAC encryption context*/
        eeprom_read_block((void*)cur_aes_key, (void*)EEP_BOOT_PWD, sizeof(cur_aes_key));
        memset((void*)cur_cbc_mac, 0x00, sizeof(cur_cbc_mac));
        memset((void*)temp_data, 0x00, sizeof(temp_data));
        aes256_init_ecb(&temp_aes_context, cur_aes_key);

        // Compute CBCMAC for between the start of the graphics zone until the max addressing space (65536) - the size of the CBCMAC
        for (uint16_t i = GRAPHIC_ZONE_START; i < (UINT16_MAX - sizeof(cur_cbc_mac) + 1); i += sizeof(cur_cbc_mac))
        {
            // Read data from external flash
            flashRawRead(temp_data, i, sizeof(temp_data));

            // If we got to the part containing to firmware
            if ((i >= firmware_start_address) && (i < firmware_end_address))
            {
                // Append firmware data to current buffer
                uint16_t firmware_data_address = i - firmware_start_address;
                memcpy(firmware_data + (firmware_data_address & SPM_PAGE_SIZE_BYTES_BM), temp_data, sizeof(temp_data));

                // If we have a full page in buffer, flash it
                firmware_data_address += sizeof(cur_cbc_mac);
                if (((firmware_data_address & SPM_PAGE_SIZE_BYTES_BM) == 0x0000) && (pass_number == 1))
                {
                    boot_program_page(firmware_data_address - SPM_PAGESIZE, firmware_data);
                }
            }

            // If we got to the part containing the encrypted new aes key (end of the for())
            if (i >= firmware_end_address)
            {
                memcpy(new_aes_key + i - firmware_end_address, temp_data, sizeof(temp_data));
            }

            // Continue computation of CBCMAC
            aesXorVectors(cur_cbc_mac, temp_data, sizeof(temp_data));
            aes256_encrypt_ecb(&temp_aes_context, cur_cbc_mac);
        }

        // Read CBCMAC in memory and compare it with the computed value
        flashRawRead(temp_data, (UINT16_MAX - sizeof(cur_cbc_mac) + 1), sizeof(cur_cbc_mac));
        if (pass_number == 0)
        {
            // First pass, compare CBCMAC and see if we do the next pass or start the firmware
            if (sideChannelSafeMemCmp(temp_data, cur_cbc_mac, sizeof(cur_cbc_mac)) != 0)
            {
                // No match, start the main firmware
                eeprom_write_word((uint16_t*)EEP_BOOTKEY_ADDR, CORRECT_BOOTKEY);
                start_firmware();
            }
            else
            {
                // Otherwise, next pass!
            }
        }
        else
        {
            // Second pass, compare CBCMAC and then update AES keys
            if (sideChannelSafeMemCmp(temp_data, cur_cbc_mac, sizeof(cur_cbc_mac)) == 0)
            {
                // Fetch the encrypted new aes key from flash, decrypt it, store it
                aes256_decrypt_ecb(&temp_aes_context, new_aes_key);
                aes256_decrypt_ecb(&temp_aes_context, new_aes_key+16);
                eeprom_write_block((void*)new_aes_key, (void*)EEP_BOOT_PWD, sizeof(new_aes_key));
                eeprom_write_word((uint16_t*)EEP_BOOTKEY_ADDR, CORRECT_BOOTKEY);
                start_firmware();
            }
            else
            {
                // Fail, erase everything! >> maybe just write a while(1) in the future?
                for (uint16_t i = 0; i < MAX_FIRMWARE_SIZE; i += SPM_PAGESIZE)
                {
                    boot_page_erase(i);
                    boot_spm_busy_wait();
                }
                while(1);
            }
        }
    }
}