123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162 |
- /*++
- Copyright (c) Alex Ionescu. All rights reserved.
- Module Name:
- xzcrc.c
- Abstract:
- This module implements the XZ checksum algorithms for CRC32 and CRC64. The
- latter is a specialized implementation (ofter mislabelled "ECMA-182") which
- is only available in Go, making it highly unlikely to be found in any other
- OS or language runtime. See the XZ Format Specification, Section 6.
- Author:
- Alex Ionescu (@aionescu) 15-May-2021 - Initial version
- Environment:
- Windows & Linux, user mode and kernel mode.
- --*/
- #include "minlzlib.h"
- #ifdef MINLZ_INTEGRITY_CHECKS
- const uint32_t k_Crc32Polynomial = UINT32_C(0xEDB88320);
- const uint64_t k_Crc64Polynomial = UINT64_C(0xC96C5795D7870F42);
- //
- // XZ CRC State
- //
- typedef struct _CHECKSUM_STATE
- {
- uint32_t Crc32Table[256];
- uint64_t Crc64Table[256];
- bool Initialized;
- } CHECKSUM_STATE, * PCHECKSUM_STATE;
- CHECKSUM_STATE Checksum;
- void
- XzCrcInitialize (
- void
- )
- {
- uint32_t i;
- uint32_t j;
- uint32_t crc32;
- uint64_t crc64;
- //
- // Don't do anything if the tables are already computed
- //
- if (!Checksum.Initialized)
- {
- //
- // Build a table of all possible CRC values for each byte, essentially
- // creating the checksums for either 00 00 00 XX in the case of 32-bit
- // CRC or for 00 00 00 00 00 00 XX in the base of 64-bit CRC.
- //
- for (i = 0; i < 256; i++)
- {
- crc32 = i;
- crc64 = i;
- //
- // Divide the input in the 8 coefficients, where the LSB represents
- // the coefficient of the highest degree term of the dividend.
- //
- for (j = 0; j < 8; j++)
- {
- //
- // Is the current coefficient set?
- //
- if (crc32 & 1)
- {
- //
- // Move to next coefficient and add the rest of the divisor
- //
- crc32 = (crc32 >> 1) ^ k_Crc32Polynomial;
- }
- else
- {
- //
- // Skip this and move to the next coefficient
- //
- crc32 >>= 1;
- }
- //
- // Compute the 64-bit entry using the same algorithm
- //
- if (crc64 & 1)
- {
- crc64 = (crc64 >> 1) ^ k_Crc64Polynomial;
- }
- else
- {
- crc64 >>= 1;
- }
- }
- //
- // Store the final generated result
- //
- Checksum.Crc32Table[i] = crc32;
- Checksum.Crc64Table[i] = crc64;
- }
- //
- // No need to do this again
- //
- Checksum.Initialized = true;
- }
- }
- uint32_t
- XzCrc32 (
- uint32_t Crc,
- const uint8_t *Buffer,
- uint32_t Length
- )
- {
- uint32_t i;
- //
- // This uses the Dilip V. Sarwate algorithm which shifts one byte at a time
- // and produces an intermediate remainder which can then be subtracted from
- // the lookup table by using the high 8 bits as an index (since we computed
- // all possible one-byte inputs). This relies on the following property:
- //
- // Mod(A * x^n, P(x)) = Mod(x^n * Mod(A, P(X)), P(X))
- //
- for (XzCrcInitialize(), Crc = ~Crc, i = 0; i < Length; ++i)
- {
- Crc = Checksum.Crc32Table[Buffer[i] ^ (Crc & 0xFF)] ^ (Crc >> 8);
- }
- return ~Crc;
- }
- uint64_t
- XzCrc64 (
- uint64_t Crc,
- const uint8_t *Buffer,
- uint32_t Length
- )
- {
- uint32_t i;
- //
- // Use the same algorithm to the 64-bit case too. Note that for very large
- // input data, a parallel "slicing by 8" approach would yield much faster
- // results (as would a "slicing by 4" approach for the 32-bit CRC case).
- //
- for (XzCrcInitialize(), Crc = ~Crc, i = 0; i < Length; ++i)
- {
- Crc = Checksum.Crc64Table[Buffer[i] ^ (Crc & 0xFF)] ^ (Crc >> 8);
- }
- return ~Crc;
- }
- #endif
|