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

Dependents:   nRF51822 nRF51822

Committer:
vcoubard
Date:
Thu Apr 07 17:37:40 2016 +0100
Revision:
19:47192cb9def7
Parent:
12:54c9ebc92faa
Child:
20:a90c48eb1d30
Synchronized with git rev 9251259f
Author: Liyou Zhou
Copy over coresponding files from nordic-sdk 9.0.0

Who changed what in which revision?

UserRevisionLine numberNew contents of line
vcoubard 19:47192cb9def7 1 /* Copyright (c) 2014 Nordic Semiconductor. All Rights Reserved.
vcoubard 19:47192cb9def7 2 *
vcoubard 19:47192cb9def7 3 * The information contained herein is property of Nordic Semiconductor ASA.
vcoubard 19:47192cb9def7 4 * Terms and conditions of usage are described in detail in NORDIC
vcoubard 19:47192cb9def7 5 * SEMICONDUCTOR STANDARD SOFTWARE LICENSE AGREEMENT.
vcoubard 19:47192cb9def7 6 *
vcoubard 19:47192cb9def7 7 * Licensees are granted free, non-transferable use of the information. NO
vcoubard 19:47192cb9def7 8 * WARRANTY of ANY KIND is provided. This heading must NOT be removed from
vcoubard 19:47192cb9def7 9 * the file.
vcoubard 19:47192cb9def7 10 *
Vincent Coubard 0:f2542974c862 11 */
Vincent Coubard 0:f2542974c862 12
Vincent Coubard 0:f2542974c862 13 /**@file
Vincent Coubard 0:f2542974c862 14 *
Vincent Coubard 0:f2542974c862 15 * @defgroup nrf_dfu_init_template Template file with an DFU init packet handling example.
Vincent Coubard 0:f2542974c862 16 * @{
Vincent Coubard 0:f2542974c862 17 *
Vincent Coubard 0:f2542974c862 18 * @ingroup nrf_dfu
Vincent Coubard 0:f2542974c862 19 *
Vincent Coubard 0:f2542974c862 20 * @brief This file contains a template on how to implement DFU init packet handling.
Vincent Coubard 0:f2542974c862 21 *
Vincent Coubard 0:f2542974c862 22 * @details The template shows how device type and revision can be used for a safety check of the
Vincent Coubard 0:f2542974c862 23 * received image. It shows how validation can be performed in two stages:
Vincent Coubard 0:f2542974c862 24 * - Stage 1: Pre-check of firmware image before transfer to ensure the firmware matches:
Vincent Coubard 0:f2542974c862 25 * - Device Type.
Vincent Coubard 0:f2542974c862 26 * - Device Revision.
Vincent Coubard 0:f2542974c862 27 * Installed SoftDevice.
Vincent Coubard 0:f2542974c862 28 * This template can be extended with additional checks according to needs.
Vincent Coubard 0:f2542974c862 29 * For example, such a check could be the origin of the image (trusted source)
Vincent Coubard 0:f2542974c862 30 * based on a signature scheme.
Vincent Coubard 0:f2542974c862 31 * - Stage 2: Post-check of the image after image transfer but before installing firmware.
Vincent Coubard 0:f2542974c862 32 * For example, such a check could be an integrity check in form of hashing or
Vincent Coubard 0:f2542974c862 33 * verification of a signature.
Vincent Coubard 0:f2542974c862 34 * In this template, a simple CRC check is carried out.
Vincent Coubard 0:f2542974c862 35 * The CRC check can be replaced with other mechanisms, like signing.
Vincent Coubard 0:f2542974c862 36 *
Vincent Coubard 0:f2542974c862 37 * @note This module does not support security features such as image signing, but the
Vincent Coubard 0:f2542974c862 38 * implementation allows for such extension.
Vincent Coubard 0:f2542974c862 39 * If the init packet is signed by a trusted source, it must be decrypted before it can be
Vincent Coubard 0:f2542974c862 40 * processed.
Vincent Coubard 0:f2542974c862 41 */
Vincent Coubard 0:f2542974c862 42
Vincent Coubard 0:f2542974c862 43 #include "dfu_init.h"
Vincent Coubard 0:f2542974c862 44 #include <stdint.h>
Vincent Coubard 0:f2542974c862 45 #include <string.h>
vcoubard 1:ebc0e0ef0a11 46 #include <dfu_types.h>
Vincent Coubard 0:f2542974c862 47 #include "nrf_error.h"
Vincent Coubard 0:f2542974c862 48 #include "crc16.h"
Vincent Coubard 0:f2542974c862 49
Vincent Coubard 0:f2542974c862 50 #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 51 #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 52
Vincent Coubard 0:f2542974c862 53 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 54 static uint8_t m_extended_packet_length; //< Length of the extended data received with init packet. */
Vincent Coubard 0:f2542974c862 55
Vincent Coubard 0:f2542974c862 56
Vincent Coubard 0:f2542974c862 57 uint32_t dfu_init_prevalidate(uint8_t * p_init_data, uint32_t init_data_len)
Vincent Coubard 0:f2542974c862 58 {
Vincent Coubard 0:f2542974c862 59 uint32_t i = 0;
Vincent Coubard 0:f2542974c862 60
Vincent Coubard 0:f2542974c862 61 // In order to support signing or encryption then any init packet decryption function / library
Vincent Coubard 0:f2542974c862 62 // should be called from here or implemented at this location.
Vincent Coubard 0:f2542974c862 63
Vincent Coubard 0:f2542974c862 64 // Length check to ensure valid data are parsed.
Vincent Coubard 0:f2542974c862 65 if (init_data_len < sizeof(dfu_init_packet_t))
Vincent Coubard 0:f2542974c862 66 {
Vincent Coubard 0:f2542974c862 67 return NRF_ERROR_INVALID_LENGTH;
Vincent Coubard 0:f2542974c862 68 }
Vincent Coubard 0:f2542974c862 69
Vincent Coubard 0:f2542974c862 70 // Current template uses clear text data so they can be casted for pre-check.
Vincent Coubard 0:f2542974c862 71 dfu_init_packet_t * p_init_packet = (dfu_init_packet_t *)p_init_data;
Vincent Coubard 0:f2542974c862 72
Vincent Coubard 0:f2542974c862 73 m_extended_packet_length = ((uint32_t)p_init_data + init_data_len) -
Vincent Coubard 0:f2542974c862 74 (uint32_t)&p_init_packet->softdevice[p_init_packet->softdevice_len];
Vincent Coubard 0:f2542974c862 75 if (m_extended_packet_length < DFU_INIT_PACKET_EXT_LENGTH_MIN)
Vincent Coubard 0:f2542974c862 76 {
Vincent Coubard 0:f2542974c862 77 return NRF_ERROR_INVALID_LENGTH;
Vincent Coubard 0:f2542974c862 78 }
Vincent Coubard 0:f2542974c862 79
Vincent Coubard 0:f2542974c862 80 if (((uint32_t)p_init_data + init_data_len) <
Vincent Coubard 0:f2542974c862 81 (uint32_t)&p_init_packet->softdevice[p_init_packet->softdevice_len])
Vincent Coubard 0:f2542974c862 82 {
Vincent Coubard 0:f2542974c862 83 return NRF_ERROR_INVALID_LENGTH;
Vincent Coubard 0:f2542974c862 84 }
Vincent Coubard 0:f2542974c862 85
Vincent Coubard 0:f2542974c862 86 memcpy(m_extended_packet,
Vincent Coubard 0:f2542974c862 87 &p_init_packet->softdevice[p_init_packet->softdevice_len],
Vincent Coubard 0:f2542974c862 88 m_extended_packet_length);
Vincent Coubard 0:f2542974c862 89
Vincent Coubard 0:f2542974c862 90 /** [DFU init application version] */
Vincent Coubard 0:f2542974c862 91 // To support application versioning, this check should be updated.
Vincent Coubard 0:f2542974c862 92 // This template allows for any application to be installed. However,
Vincent Coubard 0:f2542974c862 93 // customers can place a revision number at the bottom of the application
Vincent Coubard 0:f2542974c862 94 // to be verified by the bootloader. This can be done at a location
Vincent Coubard 0:f2542974c862 95 // relative to the application, for example the application start
Vincent Coubard 0:f2542974c862 96 // address + 0x0100.
Vincent Coubard 0:f2542974c862 97 /** [DFU init application version] */
Vincent Coubard 0:f2542974c862 98
Vincent Coubard 0:f2542974c862 99 // First check to verify the image to be transfered matches the device type.
Vincent Coubard 0:f2542974c862 100 // If no Device type is present in DFU_DEVICE_INFO then any image will be accepted.
Vincent Coubard 0:f2542974c862 101 if ((DFU_DEVICE_INFO->device_type != DFU_DEVICE_TYPE_EMPTY) &&
Vincent Coubard 0:f2542974c862 102 (p_init_packet->device_type != DFU_DEVICE_INFO->device_type))
Vincent Coubard 0:f2542974c862 103 {
Vincent Coubard 0:f2542974c862 104 return NRF_ERROR_INVALID_DATA;
Vincent Coubard 0:f2542974c862 105 }
Vincent Coubard 0:f2542974c862 106
Vincent Coubard 0:f2542974c862 107 // Second check to verify the image to be transfered matches the device revision.
Vincent Coubard 0:f2542974c862 108 // If no Device revision is present in DFU_DEVICE_INFO then any image will be accepted.
Vincent Coubard 0:f2542974c862 109 if ((DFU_DEVICE_INFO->device_rev != DFU_DEVICE_REVISION_EMPTY) &&
Vincent Coubard 0:f2542974c862 110 (p_init_packet->device_rev != DFU_DEVICE_INFO->device_rev))
Vincent Coubard 0:f2542974c862 111 {
Vincent Coubard 0:f2542974c862 112 return NRF_ERROR_INVALID_DATA;
Vincent Coubard 0:f2542974c862 113 }
Vincent Coubard 0:f2542974c862 114
Vincent Coubard 0:f2542974c862 115 // Third check: Check the array of supported SoftDevices by this application.
Vincent Coubard 0:f2542974c862 116 // If the installed SoftDevice does not match any SoftDevice in the list then an
Vincent Coubard 0:f2542974c862 117 // error is returned.
Vincent Coubard 0:f2542974c862 118 while (i < p_init_packet->softdevice_len)
Vincent Coubard 0:f2542974c862 119 {
vcoubard 19:47192cb9def7 120 if (p_init_packet->softdevice[i] == DFU_SOFTDEVICE_ANY ||
vcoubard 19:47192cb9def7 121 p_init_packet->softdevice[i++] == SD_FWID_GET(MBR_SIZE))
Vincent Coubard 0:f2542974c862 122 {
Vincent Coubard 0:f2542974c862 123 return NRF_SUCCESS;
Vincent Coubard 0:f2542974c862 124 }
Vincent Coubard 0:f2542974c862 125 }
Vincent Coubard 0:f2542974c862 126
Vincent Coubard 0:f2542974c862 127 // No matching SoftDevice found - Return NRF_ERROR_INVALID_DATA.
Vincent Coubard 0:f2542974c862 128 return NRF_ERROR_INVALID_DATA;
Vincent Coubard 0:f2542974c862 129 }
Vincent Coubard 0:f2542974c862 130
Vincent Coubard 0:f2542974c862 131
Vincent Coubard 0:f2542974c862 132 uint32_t dfu_init_postvalidate(uint8_t * p_image, uint32_t image_len)
Vincent Coubard 0:f2542974c862 133 {
Vincent Coubard 0:f2542974c862 134 uint16_t image_crc;
Vincent Coubard 0:f2542974c862 135 uint16_t received_crc;
Vincent Coubard 0:f2542974c862 136
Vincent Coubard 0:f2542974c862 137 // In order to support hashing (and signing) then the (decrypted) hash should be fetched and
Vincent Coubard 0:f2542974c862 138 // the corresponding hash should be calculated over the image at this location.
Vincent Coubard 0:f2542974c862 139 // If hashing (or signing) is added to the system then the CRC validation should be removed.
Vincent Coubard 0:f2542974c862 140
Vincent Coubard 0:f2542974c862 141 // calculate CRC from active block.
Vincent Coubard 0:f2542974c862 142 image_crc = crc16_compute(p_image, image_len, NULL);
Vincent Coubard 0:f2542974c862 143
Vincent Coubard 0:f2542974c862 144 // Decode the received CRC from extended data.
Vincent Coubard 0:f2542974c862 145 received_crc = uint16_decode((uint8_t *)&m_extended_packet[0]);
Vincent Coubard 0:f2542974c862 146
Vincent Coubard 0:f2542974c862 147 // Compare the received and calculated CRC.
Vincent Coubard 0:f2542974c862 148 if (image_crc != received_crc)
Vincent Coubard 0:f2542974c862 149 {
Vincent Coubard 0:f2542974c862 150 return NRF_ERROR_INVALID_DATA;
Vincent Coubard 0:f2542974c862 151 }
Vincent Coubard 0:f2542974c862 152
Vincent Coubard 0:f2542974c862 153 return NRF_SUCCESS;
Vincent Coubard 0:f2542974c862 154 }
vcoubard 1:ebc0e0ef0a11 155