0

I am implementing a flash integrity check for an STM32F10x MCU-based board. This check needs to process the program flash, one block at a time, i.e. 64-byte block per CRC32 invocation, because it needs to be periodic and interruptible.

Unfortunately, CRC hardware in STM32F10x doesn't allow configuring the initial checksum for the CRC32, so effectively, for each block CRC32 algorithm starts with 0xFFFFFFFF.

I am looking for a way to "merge" these checksums to provide some signature that would be more robust than a trivial XOR of all the checksums. This XOR solution has a problem with swapping of the order of blocks and, of course, the traditional "even number of errors cancels itself" kind of problem.

What would be a better way of integrity checking of blocks sequence in this case? Would the following pseudo-code be "good enough":

checksum = 0xffffffff;
for (idx=0; idx<size_in_blocks; idx++)
{
    CRC_ResetDR();
    checksum = (checksum >> 8) ^ CRC_CalcBlockCRC(blocks[idx], block_size)
}

We can't calculate the whole flash CRC32 in one go, as it takes a too long time, and the CRC HW block is used by other entities in the OS as well, i.e. can be reset in the middle.

NOTE: there is no need to reconstruct the exact CRC32 as if it would be a one single CRC32 input block. If it can be done, this would be even better, but it can be just reliable enough to guarantee a certain lack of flash manipulation.

Edited: Clearly, CRC32 is not a cryptographic hash, so the word "cryptography" was taken off the title.

mash5
  • 124
  • 1
  • 4
  • 3
    If "Cryptographically sound incremental CRC32" isn't an oxymoron then I do not know what is. – Antti Haapala -- Слава Україні Aug 02 '19 at 13:46
  • 2
    Notice that it is trivial to find blocks that have the same CRC32, so the same thing that you worry about XOR will almost equally apply to CRC32 – Antti Haapala -- Слава Україні Aug 02 '19 at 13:51
  • @AnttiHaapala If you meant to say "there is no good solution", I totally get it. let's see if somebody else might have a viable suggestion. – mash5 Aug 02 '19 at 13:52
  • What Antti is saying is that CRC32 is not cryptographically sound. It's a simple scheme that provides some measure of protection against accidental corruption, but no actual _security_. – Snild Dolkow Aug 02 '19 at 13:58
  • CRC32, whatever variant, *is not a cryptographic hash*! And cannot be used as one. – Eugene Sh. Aug 02 '19 at 14:01
  • @mash5 can you do it in software instead? Then you can calculate the checksum on as big chunks as you wish, and it can be interrupted etc. I've done this in a few projects: Calculate a checksum in HW on startup, and then use a SW-implementation to do the running incremental calculation. – Morten Jensen Aug 02 '19 at 14:37
  • In principle, you can process a 32-bit value to change the initial CRC32 value to any other value. The tricky part is figuring out that 32-bit value. – Ian Abbott Aug 02 '19 at 15:25
  • @Snild Dolkow - ah, yes, now I get that "cryptography" has nothing to do with CRC32. That surely is confusing for anybody who prefer that words to be used as scientifically as intended. Hopefully, the content of the question is more explanatory. So, I'll try to fix the title. – mash5 Aug 03 '19 at 21:03
  • @ian-abbott That's a great idea! If only there was an easy way to get any given checksum from ```0xFFFFFFFF``` in a precalculated way. That is, if we know what checksum/remainder we need, how to prepare the dividend, if the polynomial is known. – mash5 Aug 03 '19 at 21:08
  • The CRCs of block A and block B can be combined such that you get the CRC of the block AB, this is a well known operation that is used in practice to parallelise CRC calculations – harold Aug 03 '19 at 21:23
  • @harold Can you please point to any source that shows how to get CRC(AB) from CRC(A) and CRC(B)? Simple ```CRC(A)^CRC(B)``` or ```CRC(CRC(A)CRC(B))``` doesn't seem to produce the desired result. – mash5 Aug 05 '19 at 07:33
  • https://stackoverflow.com/a/23126768/555045 – harold Aug 05 '19 at 10:12

0 Answers0