8 years, 6 months ago.

Firmware checksum generation

Since i couldn't find anything similiar online...can anyone help me with some code for generating the firmware checksum in runtime from mbed microcontroller. I am using NucleoF401RE board. I do not have any constraints, i just need to calculate it in some way, whether using the incorporated CRC calculation unit or some other way.

What i want to achieve is to compute the software signature during runtime and compare it with a precalculated signature of the same software to make sure that the software on mbed was not altered.

Thanks

This should be possible yes, although if you don't save the length of the binary somewhere too, you need to take into account the CRC would be calculated over the complete flash memory, which means alot of 0xFF padding.

Also how are you going to make sure the reference CRC is not altered also?

posted by Erik - 05 Jun 2016

Hi Erik, oh and how can i save the length of the binary and make sure that that address will never be overwritten by anything else like program variables or the binary itself? The reference software signature is not an issue. I just do not know how to calculate it in runtime.

posted by anteo c 05 Jun 2016

You can just add an integer to your code with the length in it, but then each time you have a new binary you need to modify it. Or you can include the 0xFF until the end of the flash in your CRC.

Anyway what is your exact problem? Calculating a CRC? Reading the binary for the CRC?

posted by Erik - 05 Jun 2016

Having an integer with the length of the binary is ok for me. I could use that as solution. My Problem is that i do not know how to do this at all. Neil has some code here https://developer.mbed.org/forum/mbed/topic/4557/ but that is for LPC and i have no clue how to adopt it for the Board i have (NucleoF401RE). This is something that i have never done and i do not know what are the steps to do such thing.

What i thought about is having a method which i can call and just get the software signature, but the body of that method is for me just a question mark :)

posted by anteo c 05 Jun 2016

That code seems to use a special feature of the NXP MCUs. I don't know if STM has something similar, you would need to look it up in the reference manual.

The alternative however is simply doing it in software. And then the question is how far do you get with that. Chop it up in little bits and try to make that work, until you get stuck somewhere. So get some code to generate the CRC (there is an example code in mbed, although a bit too extensive maybe so you might want to copy paste what is relevant for you) for starters.

I can probably write it, but problem 1 is that I need to feel like it, and doing it yourself is so much more satisfying ;). So step 1: Get a string in your program (or some other block of data), and perform the CRC check on it you want to use, and compare that with what you expected it should return. And then make a function that takes a random array/pointer/string and a length, and returns its CRC value. This is a very old one which shows one example of CRC functions: https://developer.mbed.org/users/jpelletier/code/CRC/

posted by Erik - 05 Jun 2016

Hi Erik. Thanks for the tips. Ok I understand. And how can i read the flash memory as byte/char array or get a reference as char * from where the binary starts until its end? I am seeing in the example that you wrote that Jacues is calculating the crc through incrementing a char* pointer (*p++), can i be sure that the binary is written in flash in contiguous addresses?

posted by anteo c 05 Jun 2016

I'm going to chuck in a small detail about CRC tests that might be helpful, and it is a detail that is easy to miss. Often you do NOT compare the calculated CRC value with a stored CRC value. Doing it that way creates the problem that the "correct" value has to be stored somewhere else as if it was embedded in the block the act of inserting it would invalidate it.

Instead when programming you calculate the CRC for the block of data then append the CRC value to the data. To test the block you recalculate the CRC on the resulting block including the appended CRC. This will yield a fixed value, typically either all 0s or all 1s. This is a characteristic of the CRC, unlike hash functions it is trivial to create a CRC "collision".

posted by Oliver Broad 06 Jun 2016

Hi Oliver, thanks a lot for that second tip. I did not know that appending the crc and recalculating would result in all "0"s or all "1"s. i am using such kind of validation but i just removed the crc and recalculated. Now i can make my code simplier.

Regarding the crc of the flash, yes u are right. I was not planning to save it inside the binary itself.

posted by anteo c 07 Jun 2016

1 Answer

8 years, 6 months ago.

Time to switch it to an answer:

Yes, the binary is written contingious to the flash. The binary you get on your PC from the compiler should be copied 1 on 1 to the flash memory of your device. Normally flash starts at 0x000000, but if I remember correctly and looking at an old program of mine, in the F401 flash starts at 0x08000000 and is remapped to 0x0000000. So I believe both should work, but if 0x000000 doesn't work, try the other one.

You can make your pointer like:

char *flashpointer = (char*) 0x00000000;

Also an idea: Again do it in small steps. I assume you have a hex editor on your PC? (I use notepad++ with a hex editor plugin, but there are other options). So for example look what the first 10 hex characters of the bin file are. Calculate the CRC of it on your PC, and do it on the MCU and return it via serial. Is it the same? Great. Is it not the same? Then write those first 10 characters to your PC via Serial and check manually where it is going wrong.

Accepted Answer

Just a quick note - you will need to include length in the code somewhere and then ensure your CRC calculation stops at that point. If the aim is to avoid malicious changes to the code and you are including the unused sections of flash then someone could put a suitable pattern into that unused area to give the correct CRC after making changes to the code.

posted by Andy A 06 Jun 2016

While a good point, it is also worth noting that there is a ton of 'unused' code in an mbed generated binary. For example all runtime printf messages could be changed to make the CRC match the original again. Not to mention the CRC calculation function could simply be changed to return something else.

It can protect against basic errors or very simple attempts to upload another binary, but not much more than that. Code-read-protection is in general more suited to make sure no one changes the binary, possibly together with some kind of public-private encryption key. It all depends on how paranoid you are ;).

posted by Erik - 06 Jun 2016

Hi Erik,

Thanks a lot for the great help...and yes doing it myself is much more satisfying :). I followed your steps and i have the calculation now. Here are some extra info if anyone is going to do same thing:

1. the calculation with char *flashpointer = (char*) 0x00000000; worked fine.

2. link for comparing the crc generated from mbed through the lib https://developer.mbed.org/users/jpelletier/code/CRC/ and some online calculator http://www.online-convert.com/result/0746fdd7e1a5cc30ae13b7a970028b6a. The crc generated from the online calculator is the same as the BZIP2 variant of the mbed lib.

posted by anteo c 09 Jun 2016

Nice, good to hear :).

posted by Erik - 09 Jun 2016