updates

Fork of nrf51-sdk by Lancaster University

Embed: (wiki syntax)

« Back to documentation index

Show/hide line numbers dfu_init_template.c Source File

dfu_init_template.c

Go to the documentation of this file.
00001 /*
00002  * Copyright (c) Nordic Semiconductor ASA
00003  * All rights reserved.
00004  *
00005  * Redistribution and use in source and binary forms, with or without modification,
00006  * are permitted provided that the following conditions are met:
00007  *
00008  *   1. Redistributions of source code must retain the above copyright notice, this
00009  *   list of conditions and the following disclaimer.
00010  *
00011  *   2. Redistributions in binary form must reproduce the above copyright notice, this
00012  *   list of conditions and the following disclaimer in the documentation and/or
00013  *   other materials provided with the distribution.
00014  *
00015  *   3. Neither the name of Nordic Semiconductor ASA nor the names of other
00016  *   contributors to this software may be used to endorse or promote products
00017  *   derived from this software without specific prior written permission.
00018  *
00019  *
00020  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
00021  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
00022  * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
00023  * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR
00024  * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
00025  * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
00026  * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
00027  * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
00028  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
00029  * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
00030  *
00031  */
00032 
00033 /**@file
00034  *
00035  * @defgroup nrf_dfu_init_template Template file with an DFU init packet handling example.
00036  * @{
00037  *
00038  * @ingroup nrf_dfu
00039  *
00040  * @brief This file contains a template on how to implement DFU init packet handling.
00041  *
00042  * @details The template shows how device type and revision can be used for a safety check of the 
00043  *          received image. It shows how validation can be performed in two stages:
00044  *          - Stage 1: Pre-check of firmware image before transfer to ensure the firmware matches:
00045  *                     - Device Type.
00046  *                     - Device Revision.
00047  *                     Installed SoftDevice.
00048  *                     This template can be extended with additional checks according to needs.
00049  *                     For example, such a check could be the origin of the image (trusted source) 
00050  *                     based on a signature scheme.
00051  *          - Stage 2: Post-check of the image after image transfer but before installing firmware.
00052  *                     For example, such a check could be an integrity check in form of hashing or 
00053  *                     verification of a signature.
00054  *                     In this template, a simple CRC check is carried out.
00055  *                     The CRC check can be replaced with other mechanisms, like signing.
00056  *
00057  * @note This module does not support security features such as image signing, but the 
00058  *       implementation allows for such extension.
00059  *       If the init packet is signed by a trusted source, it must be decrypted before it can be
00060  *       processed.
00061  */
00062 
00063 #include "dfu_init.h "
00064 #include <stdint.h>
00065 #include <string.h>
00066 #include <dfu_types.h >
00067 #include "nrf_error.h"
00068 #include "crc16.h "
00069 
00070 #define DFU_INIT_PACKET_EXT_LENGTH_MIN      2                       //< Minimum length of the extended init packet. The extended init packet may contain a CRC, a HASH, or other data. This value must be changed according to the requirements of the system. The template uses a minimum value of two in order to hold a CRC. */
00071 #define DFU_INIT_PACKET_EXT_LENGTH_MAX      10                      //< Maximum length of the extended init packet. The extended init packet may contain a CRC, a HASH, or other data. This value must be changed according to the requirements of the system. The template uses a maximum value of 10 in order to hold a CRC and any padded data on transport layer without overflow. */
00072 
00073 static uint8_t m_extended_packet[DFU_INIT_PACKET_EXT_LENGTH_MAX];   //< Data array for storage of the extended data received. The extended data follows the normal init data of type \ref dfu_init_packet_t. Extended data can be used for a CRC, hash, signature, or other data. */
00074 static uint8_t m_extended_packet_length;                            //< Length of the extended data received with init packet. */
00075 
00076 
00077 uint32_t dfu_init_prevalidate(uint8_t * p_init_data, uint32_t init_data_len)
00078 {
00079     uint32_t i = 0;
00080     
00081     // In order to support signing or encryption then any init packet decryption function / library
00082     // should be called from here or implemented at this location.
00083 
00084     // Length check to ensure valid data are parsed.
00085     if (init_data_len < sizeof(dfu_init_packet_t))
00086     {
00087         return NRF_ERROR_INVALID_LENGTH;
00088     }
00089 
00090     // Current template uses clear text data so they can be casted for pre-check.
00091     dfu_init_packet_t * p_init_packet = (dfu_init_packet_t *)p_init_data;
00092 
00093     m_extended_packet_length = ((uint32_t)p_init_data + init_data_len) -
00094                                (uint32_t)&p_init_packet->softdevice[p_init_packet->softdevice_len];
00095     if (m_extended_packet_length < DFU_INIT_PACKET_EXT_LENGTH_MIN)
00096     {
00097         return NRF_ERROR_INVALID_LENGTH;
00098     }
00099 
00100     if (((uint32_t)p_init_data + init_data_len) < 
00101         (uint32_t)&p_init_packet->softdevice[p_init_packet->softdevice_len])
00102     {
00103         return NRF_ERROR_INVALID_LENGTH;
00104     }
00105 
00106     memcpy(m_extended_packet,
00107            &p_init_packet->softdevice[p_init_packet->softdevice_len],
00108            m_extended_packet_length);
00109 
00110 /** [DFU init application version] */
00111     // To support application versioning, this check should be updated.
00112     // This template allows for any application to be installed. However, 
00113     // customers can place a revision number at the bottom of the application 
00114     // to be verified by the bootloader. This can be done at a location 
00115     // relative to the application, for example the application start 
00116     // address + 0x0100.
00117 /** [DFU init application version] */
00118     
00119     // First check to verify the image to be transfered matches the device type.
00120     // If no Device type is present in DFU_DEVICE_INFO then any image will be accepted.
00121     if ((DFU_DEVICE_INFO->device_type != DFU_DEVICE_TYPE_EMPTY) &&
00122         (p_init_packet->device_type != DFU_DEVICE_INFO->device_type))
00123     {
00124         return NRF_ERROR_INVALID_DATA;
00125     }
00126     
00127     // Second check to verify the image to be transfered matches the device revision.
00128     // If no Device revision is present in DFU_DEVICE_INFO then any image will be accepted.
00129     if ((DFU_DEVICE_INFO->device_rev != DFU_DEVICE_REVISION_EMPTY) &&
00130         (p_init_packet->device_rev != DFU_DEVICE_INFO->device_rev))
00131     {
00132         return NRF_ERROR_INVALID_DATA;
00133     }
00134 
00135     // Third check: Check the array of supported SoftDevices by this application.
00136     //              If the installed SoftDevice does not match any SoftDevice in the list then an
00137     //              error is returned.
00138     while (i < p_init_packet->softdevice_len)
00139     {
00140         if (p_init_packet->softdevice[i]   == DFU_SOFTDEVICE_ANY ||
00141             p_init_packet->softdevice[i++] == SD_FWID_GET(MBR_SIZE))
00142         {
00143             return NRF_SUCCESS;
00144         }
00145     }
00146     
00147     // No matching SoftDevice found - Return NRF_ERROR_INVALID_DATA.
00148     return NRF_ERROR_INVALID_DATA;
00149 }
00150 
00151 
00152 uint32_t dfu_init_postvalidate(uint8_t * p_image, uint32_t image_len)
00153 {
00154 #if NEED_CRC_CHECK /* disabled for now */
00155     uint16_t image_crc;
00156     uint16_t received_crc;
00157     
00158     // In order to support hashing (and signing) then the (decrypted) hash should be fetched and
00159     // the corresponding hash should be calculated over the image at this location.
00160     // If hashing (or signing) is added to the system then the CRC validation should be removed.
00161 
00162     // calculate CRC from active block.
00163     image_crc = crc16_compute(p_image, image_len, NULL);
00164 
00165     // Decode the received CRC from extended data.    
00166     received_crc = uint16_decode((uint8_t *)&m_extended_packet[0]);
00167 
00168     // Compare the received and calculated CRC.
00169     if (image_crc != received_crc)
00170     {
00171         return NRF_ERROR_INVALID_DATA;
00172     }
00173 #endif /* NEED_CRC_CHECK */
00174 
00175     return NRF_SUCCESS;
00176 }
00177