Пример #1
0
uint32_t dfu_init_prevalidate(uint8_t * p_init_data, uint32_t init_data_len)
{
    uint32_t                i = 0;
    static uint32_t         err_code;
    nrf_sec_data_t          init_data;
    nrf_sec_ecc_signature_t signature;
        
    // In order to support encryption then any init packet decryption function / library
    // should be called from here or implemented at this location.

    // Length check to ensure valid data are parsed.
    if (init_data_len < sizeof(dfu_init_packet_t))
    {
        return NRF_ERROR_INVALID_LENGTH;
    }

    // Current template uses clear text data so they can be casted for pre-check.
    dfu_init_packet_t * p_init_packet = (dfu_init_packet_t *)p_init_data;
    
    
    m_extended_packet_length = ((uint32_t)p_init_data + init_data_len) -
                                (uint32_t)&p_init_packet->softdevice[p_init_packet->softdevice_len];
    
    if (m_extended_packet_length < DFU_INIT_PACKET_EXT_LENGTH_MIN)
    {
        return NRF_ERROR_INVALID_LENGTH;
    }

    if (((uint32_t)p_init_data + init_data_len) < 
         (uint32_t)&p_init_packet->softdevice[p_init_packet->softdevice_len])
    {
        return NRF_ERROR_INVALID_LENGTH;
    }
    
    memcpy(&m_extended_packet,
           &p_init_packet->softdevice[p_init_packet->softdevice_len],
           m_extended_packet_length);

/** [DFU init application version] */
    // To support application versioning, this check should be updated.
    // This template allows for any application to be installed. However, 
    // customers can place a revision number at the bottom of the application 
    // to be verified by the bootloader. This can be done at a location 
    // relative to the application, for example the application start 
    // address + 0x0100.
/** [DFU init application version] */
    
    // First check to verify the image to be transfered matches the device type.
    // If no Device type is present in DFU_DEVICE_INFO then any image will be accepted.
    if ((DFU_DEVICE_INFO->device_type != DFU_DEVICE_TYPE_EMPTY) &&
        (p_init_packet->device_type != DFU_DEVICE_INFO->device_type))
    {
        return NRF_ERROR_INVALID_DATA;
    }
    
    // Second check to verify the image to be transfered matches the device revision.
    // If no Device revision is present in DFU_DEVICE_INFO then any image will be accepted.
    if ((DFU_DEVICE_INFO->device_rev != DFU_DEVICE_REVISION_EMPTY) &&
        (p_init_packet->device_rev != DFU_DEVICE_INFO->device_rev))
    {
        return NRF_ERROR_INVALID_DATA;
    }

    // Third check: Check the array of supported SoftDevices by this application.
    //              If the installed SoftDevice does not match any SoftDevice in the list then an
    //              error is returned.
    while (i < p_init_packet->softdevice_len)
    {
        if (p_init_packet->softdevice[i]   == DFU_SOFTDEVICE_ANY ||
            p_init_packet->softdevice[i++] == SD_FWID_GET(MBR_SIZE))
        {
            // Found a match. Break the loop.
            break;
        }
        // No matching SoftDevice found - Return NRF_ERROR_INVALID_DATA.
        return NRF_ERROR_INVALID_DATA;
    }
    
    // Check that we have the correct identifier indicating that ECDS is used
    if(*(uint32_t*)&m_extended_packet[DFU_INIT_PACKET_POS_EXT_IDENTIFIER] != DFU_INIT_PACKET_USES_ECDS)
    {
        return NRF_ERROR_INVALID_DATA;
    }
    
    // init_data consists of the regular init-packet and all the extended packet data excluding the signing key
    init_data.length = (init_data_len - m_extended_packet_length) + DFU_INIT_PACKET_EXT_LENGTH_SIGNED;
    init_data.p_data = p_init_data;

    signature.p_r   = &m_extended_packet[DFU_INIT_PACKET_POS_EXT_INIT_SIGNATURE_R];
    signature.r_len = DFU_SIGNATURE_R_LENGTH;
    signature.p_s   = &m_extended_packet[DFU_INIT_PACKET_POS_EXT_INIT_SIGNATURE_S];
    signature.s_len = DFU_SIGNATURE_S_LENGTH;

    err_code = nrf_sec_svc_verify(&init_data, &Q ,&signature, NRF_SEC_NIST256_SHA256);
    return err_code;
}
Пример #2
0
uint32_t dfu_init_prevalidate(uint8_t * p_init_data, uint32_t init_data_len)
{
    uint32_t i = 0;
    
    // In order to support signing or encryption then any init packet decryption function / library
    // should be called from here or implemented at this location.

    // Length check to ensure valid data are parsed.
    if (init_data_len < sizeof(dfu_init_packet_t))
    {
        return NRF_ERROR_INVALID_LENGTH;
    }

    // Current template uses clear text data so they can be casted for pre-check.
    dfu_init_packet_t * p_init_packet = (dfu_init_packet_t *)p_init_data;

    m_extended_packet_length = ((uint32_t)p_init_data + init_data_len) -
                               (uint32_t)&p_init_packet->softdevice[p_init_packet->softdevice_len];
    if (m_extended_packet_length < DFU_INIT_PACKET_EXT_LENGTH_MIN)
    {
        return NRF_ERROR_INVALID_LENGTH;
    }

    if (((uint32_t)p_init_data + init_data_len) < 
        (uint32_t)&p_init_packet->softdevice[p_init_packet->softdevice_len])
    {
        return NRF_ERROR_INVALID_LENGTH;
    }

    memcpy(m_extended_packet,
           &p_init_packet->softdevice[p_init_packet->softdevice_len],
           m_extended_packet_length);

/** [DFU init application version] */
    // To support application versioning, this check should be updated.
    // This template allows for any application to be installed. However, 
    // customers can place a revision number at the bottom of the application 
    // to be verified by the bootloader. This can be done at a location 
    // relative to the application, for example the application start 
    // address + 0x0100.
/** [DFU init application version] */
    
    // First check to verify the image to be transfered matches the device type.
    // If no Device type is present in DFU_DEVICE_INFO then any image will be accepted.
    if ((DFU_DEVICE_INFO->device_type != DFU_DEVICE_TYPE_EMPTY) &&
        (p_init_packet->device_type != DFU_DEVICE_INFO->device_type))
    {
        return NRF_ERROR_INVALID_DATA;
    }
    
    // Second check to verify the image to be transfered matches the device revision.
    // If no Device revision is present in DFU_DEVICE_INFO then any image will be accepted.
    if ((DFU_DEVICE_INFO->device_rev != DFU_DEVICE_REVISION_EMPTY) &&
        (p_init_packet->device_rev != DFU_DEVICE_INFO->device_rev))
    {
        return NRF_ERROR_INVALID_DATA;
    }

    // Third check: Check the array of supported SoftDevices by this application.
    //              If the installed SoftDevice does not match any SoftDevice in the list then an
    //              error is returned.
    while (i < p_init_packet->softdevice_len)
    {
        if (p_init_packet->softdevice[i]   == DFU_SOFTDEVICE_ANY ||
            p_init_packet->softdevice[i++] == SD_FWID_GET(MBR_SIZE))
        {
            return NRF_SUCCESS;
        }
    }
    
    // No matching SoftDevice found - Return NRF_ERROR_INVALID_DATA.
    return NRF_ERROR_INVALID_DATA;
}
Пример #3
0
/** @brief Function to execute the continuation of a SoftDevice update.
 *
 * @param[in]       src_addr            Source address of the SoftDevice to copy from.
 * @param[in]       p_bank              Pointer to the bank where the SoftDevice resides.
 *
 * @retval NRF_SUCCESS Continuation was successful.
 * @retval NRF_ERROR_INVALID_LENGTH Invalid len
 * @retval NRF_ERROR_NO_MEM if UICR.NRFFW[1] is not set (i.e. is 0xFFFFFFFF).
 * @retval NRF_ERROR_INVALID_PARAM if an invalid command is given.
 * @retval NRF_ERROR_INTERNAL indicates that the contents of the memory blocks where not verified correctly after copying.
 * @retval NRF_ERROR_NULL If the content of the memory blocks differs after copying.
 */
static uint32_t nrf_dfu_sd_continue_impl(uint32_t             src_addr,
                                         nrf_dfu_bank_t     * p_bank)
{
    uint32_t   ret_val      = NRF_SUCCESS;
    uint32_t   target_addr  = SOFTDEVICE_REGION_START + s_dfu_settings.write_offset;
    uint32_t   length_left  = align_to_page(s_dfu_settings.sd_size - s_dfu_settings.write_offset, CODE_PAGE_SIZE);
    uint32_t   split_size   = align_to_page(length_left / 4, CODE_PAGE_SIZE);

    NRF_LOG_INFO("Enter nrf_bootloader_dfu_sd_continue\r\n");

    // This can be a continuation due to a power failure
    src_addr += s_dfu_settings.write_offset;

    if (s_dfu_settings.sd_size != 0 && s_dfu_settings.write_offset == s_dfu_settings.sd_size)
    {
        NRF_LOG_INFO("SD already copied\r\n");
        return NRF_SUCCESS;
    }

    NRF_LOG_INFO("Updating SD. Old SD ver: 0x%04x\r\n", SD_FWID_GET(MBR_SIZE));

    do
    {
        NRF_LOG_INFO("Copying [0x%08x-0x%08x] to [0x%08x-0x%08x]: Len: 0x%08x\r\n", src_addr, src_addr + split_size, target_addr, target_addr + split_size, split_size);

        // Copy a chunk of the SD. Size in words
        ret_val = nrf_dfu_mbr_copy_sd((uint32_t*)target_addr, (uint32_t*)src_addr, split_size);
        if (ret_val != NRF_SUCCESS)
        {
            NRF_LOG_INFO("Failed to copy SD: target: 0x%08x, src: 0x%08x, len: 0x%08x\r\n", target_addr, src_addr, split_size);
            return ret_val;
        }

        NRF_LOG_INFO("Finished copying [0x%08x-0x%08x] to [0x%08x-0x%08x]: Len: 0x%08x\r\n", src_addr, src_addr + split_size, target_addr, target_addr + split_size, split_size);

        // Validate copy. Size in words
        ret_val = nrf_dfu_mbr_compare((uint32_t*)target_addr, (uint32_t*)src_addr, split_size);
        if (ret_val != NRF_SUCCESS)
        {
            NRF_LOG_INFO("Failed to Compare SD: target: 0x%08x, src: 0x%08x, len: 0x%08x\r\n", target_addr, src_addr, split_size);
            return ret_val;
        }

        NRF_LOG_INFO("Validated 0x%08x-0x%08x to 0x%08x-0x%08x: Size: 0x%08x\r\n", src_addr, src_addr + split_size, target_addr, target_addr + split_size, split_size);

        target_addr += split_size;
        src_addr += split_size;

        if (split_size > length_left)
        {
            length_left = 0;
        }
        else
        {
            length_left -= split_size;
        }

        NRF_LOG_INFO("Finished with the SD update.\r\n");

        // Save the updated point of writes in case of power loss
        s_dfu_settings.write_offset = s_dfu_settings.sd_size - length_left;
        (void)nrf_dfu_settings_write(NULL);
    }
    while (length_left > 0);

    return ret_val;
}