Nordic nrf51 sdk sources. Mirrored from https://github.com/ARMmbed/nrf51-sdk.

Dependents:   nRF51822 nRF51822

Committer:
vcoubard
Date:
Thu Apr 07 17:37:49 2016 +0100
Revision:
24:2aea0c1c57ee
Parent:
22:67a8d2c0bbbf
Child:
27:0fe148f1bca3
Synchronized with git rev 709d3cdb
Author: Liyou Zhou
Change version number in README

Who changed what in which revision?

UserRevisionLine numberNew contents of line
vcoubard 20:a90c48eb1d30 1 /*
vcoubard 20:a90c48eb1d30 2 * Copyright (c) Nordic Semiconductor ASA
vcoubard 20:a90c48eb1d30 3 * All rights reserved.
vcoubard 20:a90c48eb1d30 4 *
vcoubard 20:a90c48eb1d30 5 * Redistribution and use in source and binary forms, with or without modification,
vcoubard 20:a90c48eb1d30 6 * are permitted provided that the following conditions are met:
vcoubard 20:a90c48eb1d30 7 *
vcoubard 20:a90c48eb1d30 8 * 1. Redistributions of source code must retain the above copyright notice, this
vcoubard 20:a90c48eb1d30 9 * list of conditions and the following disclaimer.
vcoubard 20:a90c48eb1d30 10 *
vcoubard 20:a90c48eb1d30 11 * 2. Redistributions in binary form must reproduce the above copyright notice, this
vcoubard 20:a90c48eb1d30 12 * list of conditions and the following disclaimer in the documentation and/or
vcoubard 20:a90c48eb1d30 13 * other materials provided with the distribution.
vcoubard 20:a90c48eb1d30 14 *
vcoubard 20:a90c48eb1d30 15 * 3. Neither the name of Nordic Semiconductor ASA nor the names of other
vcoubard 20:a90c48eb1d30 16 * contributors to this software may be used to endorse or promote products
vcoubard 20:a90c48eb1d30 17 * derived from this software without specific prior written permission.
vcoubard 20:a90c48eb1d30 18 *
vcoubard 20:a90c48eb1d30 19 *
vcoubard 20:a90c48eb1d30 20 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
vcoubard 20:a90c48eb1d30 21 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
vcoubard 20:a90c48eb1d30 22 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
vcoubard 20:a90c48eb1d30 23 * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR
vcoubard 20:a90c48eb1d30 24 * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
vcoubard 20:a90c48eb1d30 25 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
vcoubard 20:a90c48eb1d30 26 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
vcoubard 20:a90c48eb1d30 27 * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
vcoubard 20:a90c48eb1d30 28 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
vcoubard 20:a90c48eb1d30 29 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
vcoubard 20:a90c48eb1d30 30 *
Vincent Coubard 0:f2542974c862 31 */
Vincent Coubard 0:f2542974c862 32
Vincent Coubard 0:f2542974c862 33 /**@file
Vincent Coubard 0:f2542974c862 34 *
Vincent Coubard 0:f2542974c862 35 * @defgroup nrf_dfu_init_template Template file with an DFU init packet handling example.
Vincent Coubard 0:f2542974c862 36 * @{
Vincent Coubard 0:f2542974c862 37 *
Vincent Coubard 0:f2542974c862 38 * @ingroup nrf_dfu
Vincent Coubard 0:f2542974c862 39 *
Vincent Coubard 0:f2542974c862 40 * @brief This file contains a template on how to implement DFU init packet handling.
Vincent Coubard 0:f2542974c862 41 *
Vincent Coubard 0:f2542974c862 42 * @details The template shows how device type and revision can be used for a safety check of the
Vincent Coubard 0:f2542974c862 43 * received image. It shows how validation can be performed in two stages:
Vincent Coubard 0:f2542974c862 44 * - Stage 1: Pre-check of firmware image before transfer to ensure the firmware matches:
Vincent Coubard 0:f2542974c862 45 * - Device Type.
Vincent Coubard 0:f2542974c862 46 * - Device Revision.
Vincent Coubard 0:f2542974c862 47 * Installed SoftDevice.
Vincent Coubard 0:f2542974c862 48 * This template can be extended with additional checks according to needs.
Vincent Coubard 0:f2542974c862 49 * For example, such a check could be the origin of the image (trusted source)
Vincent Coubard 0:f2542974c862 50 * based on a signature scheme.
Vincent Coubard 0:f2542974c862 51 * - Stage 2: Post-check of the image after image transfer but before installing firmware.
Vincent Coubard 0:f2542974c862 52 * For example, such a check could be an integrity check in form of hashing or
Vincent Coubard 0:f2542974c862 53 * verification of a signature.
Vincent Coubard 0:f2542974c862 54 * In this template, a simple CRC check is carried out.
Vincent Coubard 0:f2542974c862 55 * The CRC check can be replaced with other mechanisms, like signing.
Vincent Coubard 0:f2542974c862 56 *
Vincent Coubard 0:f2542974c862 57 * @note This module does not support security features such as image signing, but the
Vincent Coubard 0:f2542974c862 58 * implementation allows for such extension.
Vincent Coubard 0:f2542974c862 59 * If the init packet is signed by a trusted source, it must be decrypted before it can be
Vincent Coubard 0:f2542974c862 60 * processed.
Vincent Coubard 0:f2542974c862 61 */
Vincent Coubard 0:f2542974c862 62
Vincent Coubard 0:f2542974c862 63 #include "dfu_init.h"
Vincent Coubard 0:f2542974c862 64 #include <stdint.h>
Vincent Coubard 0:f2542974c862 65 #include <string.h>
vcoubard 1:ebc0e0ef0a11 66 #include <dfu_types.h>
Vincent Coubard 0:f2542974c862 67 #include "nrf_error.h"
Vincent Coubard 0:f2542974c862 68 #include "crc16.h"
Vincent Coubard 0:f2542974c862 69
Vincent Coubard 0:f2542974c862 70 #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. */
Vincent Coubard 0:f2542974c862 71 #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. */
Vincent Coubard 0:f2542974c862 72
Vincent Coubard 0:f2542974c862 73 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. */
Vincent Coubard 0:f2542974c862 74 static uint8_t m_extended_packet_length; //< Length of the extended data received with init packet. */
Vincent Coubard 0:f2542974c862 75
Vincent Coubard 0:f2542974c862 76
Vincent Coubard 0:f2542974c862 77 uint32_t dfu_init_prevalidate(uint8_t * p_init_data, uint32_t init_data_len)
Vincent Coubard 0:f2542974c862 78 {
Vincent Coubard 0:f2542974c862 79 uint32_t i = 0;
Vincent Coubard 0:f2542974c862 80
Vincent Coubard 0:f2542974c862 81 // In order to support signing or encryption then any init packet decryption function / library
Vincent Coubard 0:f2542974c862 82 // should be called from here or implemented at this location.
Vincent Coubard 0:f2542974c862 83
Vincent Coubard 0:f2542974c862 84 // Length check to ensure valid data are parsed.
Vincent Coubard 0:f2542974c862 85 if (init_data_len < sizeof(dfu_init_packet_t))
Vincent Coubard 0:f2542974c862 86 {
Vincent Coubard 0:f2542974c862 87 return NRF_ERROR_INVALID_LENGTH;
Vincent Coubard 0:f2542974c862 88 }
Vincent Coubard 0:f2542974c862 89
Vincent Coubard 0:f2542974c862 90 // Current template uses clear text data so they can be casted for pre-check.
Vincent Coubard 0:f2542974c862 91 dfu_init_packet_t * p_init_packet = (dfu_init_packet_t *)p_init_data;
Vincent Coubard 0:f2542974c862 92
Vincent Coubard 0:f2542974c862 93 m_extended_packet_length = ((uint32_t)p_init_data + init_data_len) -
Vincent Coubard 0:f2542974c862 94 (uint32_t)&p_init_packet->softdevice[p_init_packet->softdevice_len];
Vincent Coubard 0:f2542974c862 95 if (m_extended_packet_length < DFU_INIT_PACKET_EXT_LENGTH_MIN)
Vincent Coubard 0:f2542974c862 96 {
Vincent Coubard 0:f2542974c862 97 return NRF_ERROR_INVALID_LENGTH;
Vincent Coubard 0:f2542974c862 98 }
Vincent Coubard 0:f2542974c862 99
Vincent Coubard 0:f2542974c862 100 if (((uint32_t)p_init_data + init_data_len) <
Vincent Coubard 0:f2542974c862 101 (uint32_t)&p_init_packet->softdevice[p_init_packet->softdevice_len])
Vincent Coubard 0:f2542974c862 102 {
Vincent Coubard 0:f2542974c862 103 return NRF_ERROR_INVALID_LENGTH;
Vincent Coubard 0:f2542974c862 104 }
Vincent Coubard 0:f2542974c862 105
Vincent Coubard 0:f2542974c862 106 memcpy(m_extended_packet,
Vincent Coubard 0:f2542974c862 107 &p_init_packet->softdevice[p_init_packet->softdevice_len],
Vincent Coubard 0:f2542974c862 108 m_extended_packet_length);
Vincent Coubard 0:f2542974c862 109
Vincent Coubard 0:f2542974c862 110 /** [DFU init application version] */
Vincent Coubard 0:f2542974c862 111 // To support application versioning, this check should be updated.
Vincent Coubard 0:f2542974c862 112 // This template allows for any application to be installed. However,
Vincent Coubard 0:f2542974c862 113 // customers can place a revision number at the bottom of the application
Vincent Coubard 0:f2542974c862 114 // to be verified by the bootloader. This can be done at a location
Vincent Coubard 0:f2542974c862 115 // relative to the application, for example the application start
Vincent Coubard 0:f2542974c862 116 // address + 0x0100.
Vincent Coubard 0:f2542974c862 117 /** [DFU init application version] */
Vincent Coubard 0:f2542974c862 118
Vincent Coubard 0:f2542974c862 119 // First check to verify the image to be transfered matches the device type.
Vincent Coubard 0:f2542974c862 120 // If no Device type is present in DFU_DEVICE_INFO then any image will be accepted.
Vincent Coubard 0:f2542974c862 121 if ((DFU_DEVICE_INFO->device_type != DFU_DEVICE_TYPE_EMPTY) &&
Vincent Coubard 0:f2542974c862 122 (p_init_packet->device_type != DFU_DEVICE_INFO->device_type))
Vincent Coubard 0:f2542974c862 123 {
Vincent Coubard 0:f2542974c862 124 return NRF_ERROR_INVALID_DATA;
Vincent Coubard 0:f2542974c862 125 }
Vincent Coubard 0:f2542974c862 126
Vincent Coubard 0:f2542974c862 127 // Second check to verify the image to be transfered matches the device revision.
Vincent Coubard 0:f2542974c862 128 // If no Device revision is present in DFU_DEVICE_INFO then any image will be accepted.
Vincent Coubard 0:f2542974c862 129 if ((DFU_DEVICE_INFO->device_rev != DFU_DEVICE_REVISION_EMPTY) &&
Vincent Coubard 0:f2542974c862 130 (p_init_packet->device_rev != DFU_DEVICE_INFO->device_rev))
Vincent Coubard 0:f2542974c862 131 {
Vincent Coubard 0:f2542974c862 132 return NRF_ERROR_INVALID_DATA;
Vincent Coubard 0:f2542974c862 133 }
Vincent Coubard 0:f2542974c862 134
Vincent Coubard 0:f2542974c862 135 // Third check: Check the array of supported SoftDevices by this application.
Vincent Coubard 0:f2542974c862 136 // If the installed SoftDevice does not match any SoftDevice in the list then an
Vincent Coubard 0:f2542974c862 137 // error is returned.
Vincent Coubard 0:f2542974c862 138 while (i < p_init_packet->softdevice_len)
Vincent Coubard 0:f2542974c862 139 {
vcoubard 24:2aea0c1c57ee 140 if (p_init_packet->softdevice[i] == DFU_SOFTDEVICE_ANY ||
vcoubard 24:2aea0c1c57ee 141 p_init_packet->softdevice[i++] == SD_FWID_GET(MBR_SIZE))
Vincent Coubard 0:f2542974c862 142 {
Vincent Coubard 0:f2542974c862 143 return NRF_SUCCESS;
Vincent Coubard 0:f2542974c862 144 }
Vincent Coubard 0:f2542974c862 145 }
Vincent Coubard 0:f2542974c862 146
Vincent Coubard 0:f2542974c862 147 // No matching SoftDevice found - Return NRF_ERROR_INVALID_DATA.
Vincent Coubard 0:f2542974c862 148 return NRF_ERROR_INVALID_DATA;
Vincent Coubard 0:f2542974c862 149 }
Vincent Coubard 0:f2542974c862 150
Vincent Coubard 0:f2542974c862 151
Vincent Coubard 0:f2542974c862 152 uint32_t dfu_init_postvalidate(uint8_t * p_image, uint32_t image_len)
Vincent Coubard 0:f2542974c862 153 {
vcoubard 21:d9932bd925d0 154 #if NEED_CRC_CHECK /* disabled for now */
Vincent Coubard 0:f2542974c862 155 uint16_t image_crc;
Vincent Coubard 0:f2542974c862 156 uint16_t received_crc;
Vincent Coubard 0:f2542974c862 157
Vincent Coubard 0:f2542974c862 158 // In order to support hashing (and signing) then the (decrypted) hash should be fetched and
Vincent Coubard 0:f2542974c862 159 // the corresponding hash should be calculated over the image at this location.
Vincent Coubard 0:f2542974c862 160 // If hashing (or signing) is added to the system then the CRC validation should be removed.
Vincent Coubard 0:f2542974c862 161
Vincent Coubard 0:f2542974c862 162 // calculate CRC from active block.
Vincent Coubard 0:f2542974c862 163 image_crc = crc16_compute(p_image, image_len, NULL);
Vincent Coubard 0:f2542974c862 164
Vincent Coubard 0:f2542974c862 165 // Decode the received CRC from extended data.
Vincent Coubard 0:f2542974c862 166 received_crc = uint16_decode((uint8_t *)&m_extended_packet[0]);
Vincent Coubard 0:f2542974c862 167
Vincent Coubard 0:f2542974c862 168 // Compare the received and calculated CRC.
Vincent Coubard 0:f2542974c862 169 if (image_crc != received_crc)
Vincent Coubard 0:f2542974c862 170 {
Vincent Coubard 0:f2542974c862 171 return NRF_ERROR_INVALID_DATA;
Vincent Coubard 0:f2542974c862 172 }
vcoubard 21:d9932bd925d0 173 #endif /* NEED_CRC_CHECK */
Vincent Coubard 0:f2542974c862 174
Vincent Coubard 0:f2542974c862 175 return NRF_SUCCESS;
Vincent Coubard 0:f2542974c862 176 }
vcoubard 1:ebc0e0ef0a11 177