Beware that this post is related to an SDK in maintenance mode
More Info: Consider nRF Connect SDK for new designs
This post is older than 2 years and might not be relevant anymore
More Info: Consider searching for newer posts

Adding Encryption to Secure DFU SDK v15

I am attempting to add encryption to the secure DFU process with SDK 15.2. I am following the process described in this post, however am running into an issue related to the firmware type. 

I have made all of the changes to nrfutil as described in the original post, including regenerating the proto messages for both the python files (dfu_cc_pb.py) and the .c/.h files (dfu-cc.pb.c and dfu-cc.pb.h). I am able to generate an unencrypted package, unzip it, encrypt the app.bin file, and rezip the package for use in the dfu. After doing that, I can run 

nrfutil pkg display tmp/app_firmware-encrypted.zip

and receive the following output, suggesting that the package has been created and the new nonce value has been included:

DFU Package: <tmp/app_firmware-encrypted.zip>:
|
|- Image count: 1
|
|- Image #0:
   |- Type: application
   |- Image file: app.bin
   |- Init packet file: app.dat
      |
      |- op_code: INIT
      |- signature_type: ECDSA_P256_SHA256
      |- signature (little-endian): 991c0df5b6e175fbbd416491104d409f6148935d70af9cb3af8d1b8965e5f62e2d6e727d26e34454522530f2f4ae9aaff2a95f2c5b74d1b554d4609d892d49b2
      |
      |- fw_version: 0x00000001 (1)
      |- hw_version 0x00000034 (52)
      |- sd_req: 0xAE
      |- type: APPLICATION
      |- sd_size: 0
      |- bl_size: 0
      |- app_size: 440540
      |
      |- hash_type: SHA256
      |- hash (little-endian): 5932e4b93f5abcee9b5fc7701727067e7e598b3478063e6e235895df9e34711f
      |
      |- is_debug: False
      |- nonce (little-endian): 0df22086afa07264c4bb3c03

As you can see, this output suggests that the init packet knows I am attempting to do a DFU of "type: APPLICATION".

However when I try to actually preform the DFU with my new bootloader, I am running into an error in the function nrf_dfu_ver_validation_check(). When the function checks fw_type_ok(p_init), it is giving me an error. I've edited error logging to see what type I am getting back (see below), and somehow the init pointer has registered a type of 62, when it should in fact be 0 (corresponding to the dfu_fw_type_t enum, from dfu-cc.pb.h, also displayed below)

// nrf_dfu_ver_validation.c
nrf_dfu_result_t nrf_dfu_ver_validation_check(dfu_init_command_t const * p_init)
{
    nrf_dfu_result_t ret_val = NRF_DFU_RES_CODE_SUCCESS;
    if (!fw_type_ok(p_init))
    {
        NRF_LOG_ERROR("Invalid firmware type of %d", p_init->type); \\ telling me 62, but should be DFU_FW_TYPE_APPLICATION = 0
        ret_val = EXT_ERR(NRF_DFU_EXT_ERROR_INIT_COMMAND_INVALID);
    }
...
}

// dfu-cc.pb.h
typedef enum
{
    DFU_FW_TYPE_APPLICATION = 0,
    DFU_FW_TYPE_SOFTDEVICE = 1,
    DFU_FW_TYPE_BOOTLOADER = 2,
    DFU_FW_TYPE_SOFTDEVICE_BOOTLOADER = 3
} dfu_fw_type_t;

I am somewhat stumped here, I'm not sure exactly how this init packet is being loaded into memory from the zip file, and what to do to debug this issue. I've tried to add the minimum amount of code necessary to debug this, but if there is more I need to add please just request it and I will upload it. Generally I am following the linked tutorial line by line, however the line numbers of the tutorial are a bit outdated so I may have misplaced something (particularly in the nrfutil revisions). Note that I am using the code from nrfutil repository, version 4.0.0.

  • Hi, 

    I hope you will get help from on this case. Just want to let you know the m_packet (which p_command->init get the pointer from ) is generated when we decode the protobuf inside stored_init_cmd_decode(). You can step in pb_decode() to see why you get type = 62. 

    Maybe you can post your protobuf message format. 

  • Thanks Hung. I believe there is a mistake with my protobuf message now, I realized that Matthew's tutorial is modifying nrfutil 3.5.1 but I've been hacking it together with 4.0.0. I'm going to test this out with 3.5.1 and will report back if I manage to solve it that way.

  • I just retried this using pc-nrfutil-3.5.1 and am getting a similar error (this time it says type of 38). My protobuf message is as follows:

    package dfu;
    
    // Version 0.1
    
    // Definition of enums and types
    enum OpCode {
    	RESET	= 0;
    	INIT	= 1;
    }
    
    enum FwType {
    	APPLICATION				= 0; // default, compatible with proto3
    	SOFTDEVICE				= 1;
    	BOOTLOADER				= 2;
    	SOFTDEVICE_BOOTLOADER	= 3;
    }
    
    enum HashType {
    	NO_HASH	= 0;
    	CRC		= 1;
    	SHA128	= 2;
    	SHA256	= 3;
    	SHA512	= 4;
    }
    
    message Hash {
    	required HashType 	hash_type	= 1;
    	required bytes 		hash		= 2;
    }
    
    // Commands data
    message InitCommand {
    	optional uint32	fw_version	= 1;
    	optional uint32	hw_version	= 2;
    	repeated uint32	sd_req		= 3 [packed = true]; // packed option is default in proto3
    	optional FwType	type		= 4;
    
    	optional uint32	sd_size		= 5;
    	optional uint32	bl_size		= 6;
    	optional uint32	app_size	= 7;
    
    	optional Hash	hash		= 8;
        
      optional bool   is_debug    = 9 [default = false];
    	optional bytes  nonce		= 10;
    }
    
    message ResetCommand {
    	required uint32 timeout	= 1;
    }
    
    // Command type
    message Command {
    	optional OpCode			op_code	= 1;
    	optional InitCommand	init 	= 2;
    	optional ResetCommand	reset 	= 3;
    }
    
    // Signed command types
    enum SignatureType {
    	ECDSA_P256_SHA256	= 0;
    	ED25519				= 1;
    }
    
    message SignedCommand {
    	required Command		command			= 1;
    	required SignatureType	signature_type	= 2;
    	required bytes			signature		= 3;
    }
    
    // Parent packet type
    message Packet {
    	optional Command 		command			= 1;
    	optional SignedCommand	signed_command	= 2;
    }
    

  • One thing I can imagine might potentially be causing a problem is that when I compile the .proto into dfu_cc_pb2.py (as described in step 3 here), I am not making use of the dfu-cc.options file, however when I compile it into dfu-cc.pb.c/h, I am using nanopb_generator.py with the -f option to include dfu-cc.options i.e.

    python $NANO_PB_GEN_PATH dfu-cc.pb -f dfu-cc.options

    Could that be causing some sort of misalignment when the package is created? My dfu-cc.options file looks like:

    dfu.Hash.hash				max_size:32
    dfu.SignedCommand.signature	max_size:64
    dfu.InitCommand.sd_req		max_count:4
    dfu.InitCommand.nonce		max_size:12

  • I changed dfu-cc.options to

     

    dfu.Hash.hash				max_size:32
    dfu.SignedCommand.signature	max_size:64
    dfu.InitCommand.sd_req		max_count:12
    dfu.InitCommand.nonce		max_size:12

    since I noticed that's how @Matthew has it (sd_req max_count is 12 instead of 4), and now I'm passing the firmware type check but getting caught at the hash type check:

    "Invalid hash type of 189."

    My intuition is that there's some sort of 'alignment' issue here with parsing the message, but I'm not an expert in how proto messages work so I'm still not quite sure how I might go about debugging this.

Related