CRC 中间而不是最后

CRC midstream instead of at the end

通常会在数据流的末尾添加一个CRC。 CRC 检查将包括 CRC 本身和 return 0 如果 CRC 正确。

我需要添加 CRC 来验证我的嵌入式代码。它需要检查到位,但内存中的最高字 space 用于中断向量。是否可以在中间放置一个键值,以便整个代码的 CRC 检查 returns 0? (或者这是无解的?)

绝对有可能。您可以 运行 一个 CRC 向后,这将是快速和容易的。下面是示例代码。

事实上,您可以告诉我散布在流中任何位置的位的位置,如果您提供足够多的位,我可以告诉您如何将它们设置为最后得到零 CRC,或任何与此相关的其他 CRC 值。我的 spoof code 通过求解线性方程得出这个答案。

不过我想知道你为什么要这样做。为什么不只知道 CRC 的存储位置并为除此之外的所有内容计算 CRC,然后根据存储的 CRC 检查结果?

// Example of the generation of a "middle" CRC, which is inserted somewhere in
// the middle of a sequence, where the CRC is generated such that the CRC of
// the complete sequence will be zero. This particular CRC has no pre or post
// processing.
//
// Placed into the public domain by Mark Adler, 11 May 2016.

#include <stddef.h>         // for size_t
#include <stdint.h>         // for uint32_t and uint64_t

#define POLY 0xedb88320     // CRC polynomial

// Byte-wise CRC tables for forward and reverse calculations.
uint32_t crc_forward_table[256];
uint32_t crc_reverse_table[256];

// Fill in CRC tables using bit-wise calculations.
void crc32_make_tables(void) {
    for (uint32_t n = 0; n < 256; n++) {
        uint32_t crc = n;
        for (int k = 0; k < 8; k++)
            crc = crc & 1 ? (crc >> 1) ^ POLY : crc >> 1;
        crc_forward_table[n] = crc;
        crc_reverse_table[crc >> 24] = (crc << 8) ^ n;
    }
}

// Return the forward CRC of buf[0..len-1], starting with crc at the front.
uint32_t crc32(uint32_t crc, unsigned char *buf, size_t len) {
    for (size_t n = 0; n < len; n++)
        crc = (crc >> 8) ^ crc_forward_table[(crc ^ buf[n]) & 0xff];
    return crc;
}

// Return the reverse CRC of buf[0..len-1], starting with crc at the end.
uint32_t crc32_reverse(uint32_t crc, unsigned char *buf, size_t len) {
    while (len)
        crc = (crc << 8) ^ crc_reverse_table[crc >> 24] ^ buf[--len];
    return crc;
}

// Put a 32-bit value into a byte buffer in little-endian order.
void put4(uint32_t word, unsigned char *pos) {
    pos[0] = word;
    pos[1] = word >> 8;
    pos[2] = word >> 16;
    pos[3] = word >> 24;
}

#include <stdlib.h>         // for random() and srandomdev()

// Fill dat[0..len-1] with uniformly random byte values. All of the bits from
// each random() call are used, except for possibly a few leftover at the end.
void ranfill(unsigned char *dat, size_t len) {
    uint64_t ran = 1;
    while (len) {
        if (ran < 0x100)
            ran = (ran << 31) + random();
        *dat++ = ran;
        ran >>= 8;
        len--;
    }
}

#include <stdio.h>          // for printf()

#define LEN 1024            // length of the message without the CRC

// Demonstrate the generation of a middle-CRC, using the forward and reverse
// CRC computations. Verify that the CRC of the resulting sequence is zero.
int main(void) {
    crc32_make_tables();
    srandomdev();
    unsigned char dat[LEN+4];
    ranfill(dat, LEN/2);
    put4(0, dat + LEN/2);       // put zeros where the CRC will go
    ranfill(dat + LEN/2 + 4, (LEN+1)/2);
    put4(crc32(0, dat, LEN/2) ^ crc32_reverse(0, dat + LEN/2, (LEN+1)/2 + 4),
         dat + LEN/2);          // replace the zeros with the CRC
    printf("%08x\n", crc32(0, dat, LEN+4));
    return 0;
}