CRC Calculation Of A Mostly Static Data Stream

前端 未结 2 543
盖世英雄少女心
盖世英雄少女心 2020-11-29 08:35

Background:

I have a section of memory, 1024 bytes. The last 1020 bytes will always be the same. The first 4 bytes will change (serial number of a product). I nee

2条回答
  •  抹茶落季
    2020-11-29 09:14

    Below is example C code for an alternative approach for CRC(A0). Rather than working with a matrix, a CRC can be cycled forward n bits by muliplying (CRC · ((2^n)%POLY)%POLY . So the repeated squaring is performed on an integer rather than a matrix. If n is constant, then (2^n)%POLY can be pre-computed.

    /*  crcpad.c  - crc - data has a large number of trailing zeroes */
    
    #include 
    #include 
    
    typedef unsigned char       uint8_t;
    typedef unsigned int       uint32_t;
    
    #define POLY (0x04c11db7u)
    
    static uint32_t crctbl[256];
    
    void GenTbl(void)                       /* generate crc table */
    {
    uint32_t crc;
    uint32_t c;
    uint32_t i;
        for(c = 0; c < 0x100; c++){
            crc = c<<24;
            for(i = 0; i < 8; i++)
                /* assumes twos complement */
                crc = (crc<<1)^((0-(crc>>31))&POLY);
            crctbl[c] = crc;
        }
    }
    
    uint32_t GenCrc(uint8_t * bfr, size_t size) /* generate crc */
    {
    uint32_t crc = 0u;
        while(size--)
            crc = (crc<<8)^crctbl[(crc>>24)^*bfr++];
        return(crc);
    }
    
    /* carryless multiply modulo crc */
    uint32_t MpyModCrc(uint32_t a, uint32_t b) /* (a*b)%crc */
    {
    uint32_t pd = 0;
    uint32_t i;
        for(i = 0; i < 32; i++){
            /* assumes twos complement */
            pd = (pd<<1)^((0-(pd>>31))&POLY);
            pd ^= (0-(b>>31))&a;
            b <<= 1;
        }
        return pd;
    }
    
    /* exponentiate by repeated squaring modulo crc */
    uint32_t PowModCrc(uint32_t p)          /* pow(2,p)%crc */
    {
    uint32_t prd = 0x1u;                    /* current product */
    uint32_t sqr = 0x2u;                    /* current square */
        while(p){
            if(p&1)
                prd = MpyModCrc(prd, sqr);
            sqr = MpyModCrc(sqr, sqr);
            p >>= 1;
        }
        return prd;
    }
    
    /* # data bytes */
    #define DAT  ( 32)
    /* # zero bytes */
    #define PAD  (992)
    /* DATA+PAD */
    #define CNT (1024)
    
    int main()
    {
    uint32_t pmc;
    uint32_t crc;
    uint32_t crf;
    uint32_t i;
    uint8_t *msg = malloc(CNT);
    
        for(i = 0; i < DAT; i++)           /* generate msg */
            msg[i] = (uint8_t)rand();
        for( ; i < CNT; i++)
            msg[i] = 0;
        GenTbl();                           /* generate crc table */
        crc = GenCrc(msg, CNT);             /* generate crc normally */
        crf = GenCrc(msg, DAT);             /* generate crc for data */
        pmc = PowModCrc(PAD*8);             /* pmc = pow(2,PAD*8)%crc */
        crf = MpyModCrc(crf, pmc);          /* crf = (crf*pmc)%crc */
        printf("%08x %08x\n", crc, crf);
        free(msg);
        return 0;
    }
    

    Example C code using intrinsic for carryless multiply, pclmulqdq == _mm_clmulepi64_si128:

    /*  crcpadm.c  - crc - data has a large number of trailing zeroes */
    /*                     pclmulqdq intrinsic version                */
    
    #include 
    #include 
    #include 
    
    typedef unsigned char       uint8_t;
    typedef unsigned int       uint32_t;
    typedef unsigned long long uint64_t;
    
    #define POLY  (0x104c11db7ull)
    #define POLYM ( 0x04c11db7u)
    
    static uint32_t crctbl[256];
    
    static __m128i poly;                    /* poly */
    static __m128i invpoly;                 /* 2^64 / POLY */
    
    void GenMPoly(void)                     /* generate __m12i8 poly info */
    {
    uint64_t N = 0x100000000ull;
    uint64_t Q = 0;
        for(size_t i = 0; i < 33; i++){
            Q <<= 1;
            if(N&0x100000000ull){
                Q |= 1;
                N ^= POLY;
            }
            N <<= 1;
        }
        poly.m128i_u64[0] = POLY;
        invpoly.m128i_u64[0] = Q;
    }
    
    void GenTbl(void)                       /* generate crc table */
    {
    uint32_t crc;
    uint32_t c;
    uint32_t i;
        for(c = 0; c < 0x100; c++){
            crc = c<<24;
            for(i = 0; i < 8; i++)
                /* assumes twos complement */
                crc = (crc<<1)^((0-(crc>>31))&POLYM);
            crctbl[c] = crc;
        }
    }
    
    uint32_t GenCrc(uint8_t * bfr, size_t size) /* generate crc */
    {
    uint32_t crc = 0u;
        while(size--)
            crc = (crc<<8)^crctbl[(crc>>24)^*bfr++];
        return(crc);
    }
    
    /* carryless multiply modulo crc */
    uint32_t MpyModCrc(uint32_t a, uint32_t b) /* (a*b)%crc */
    {
    __m128i ma, mb, mp, mt;
        ma.m128i_u64[0] = a;
        mb.m128i_u64[0] = b;
        mp = _mm_clmulepi64_si128(ma, mb, 0x00);      /* p[0] = a*b */
        mt = _mm_clmulepi64_si128(mp, invpoly, 0x00); /* t[1] = (p[0]*((2^64)/POLY))>>64 */
        mt = _mm_clmulepi64_si128(mt, poly, 0x01);    /* t[0] = t[1]*POLY */
        return mp.m128i_u32[0] ^ mt.m128i_u32[0];     /* ret =  p[0] ^ t[0] */
    }
    
    /* exponentiate by repeated squaring modulo crc */
    uint32_t PowModCrc(uint32_t p)          /* pow(2,p)%crc */
    {
    uint32_t prd = 0x1u;                    /* current product */
    uint32_t sqr = 0x2u;                    /* current square */
        while(p){
            if(p&1)
                prd = MpyModCrc(prd, sqr);
            sqr = MpyModCrc(sqr, sqr);
            p >>= 1;
        }
        return prd;
    }
    
    /* # data bytes */
    #define DAT  ( 32)
    /* # zero bytes */
    #define PAD  (992)
    /* DATA+PAD */
    #define CNT (1024)
    
    int main()
    {
    uint32_t pmc;
    uint32_t crc;
    uint32_t crf;
    uint32_t i;
    uint8_t *msg = malloc(CNT);
    
        GenMPoly();                         /* generate __m128 polys */
        GenTbl();                           /* generate crc table */
        for(i = 0; i < DAT; i++)            /* generate msg */
            msg[i] = (uint8_t)rand();
        for( ; i < CNT; i++)
            msg[i] = 0;
        crc = GenCrc(msg, CNT);             /* generate crc normally */
        crf = GenCrc(msg, DAT);             /* generate crc for data */
        pmc = PowModCrc(PAD*8);             /* pmc = pow(2,PAD*8)%crc */
        crf = MpyModCrc(crf, pmc);          /* crf = (crf*pmc)%crc */
        printf("%08x %08x\n", crc, crf);
        free(msg);
        return 0;
    }
    

提交回复
热议问题