Nordic stack and drivers for the mbed BLE API

Fork of nRF51822 by Nordic Semiconductor

Committer:
Vincent Coubard
Date:
Wed Sep 14 14:39:43 2016 +0100
Revision:
640:c90ae1400bf2
Sync with bdab10dc0f90748b6989c8b577771bb403ca6bd8 from ARMmbed/mbed-os.

Who changed what in which revision?

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