xzcrc.c 4.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162
  1. /*++
  2. Copyright (c) Alex Ionescu. All rights reserved.
  3. Module Name:
  4. xzcrc.c
  5. Abstract:
  6. This module implements the XZ checksum algorithms for CRC32 and CRC64. The
  7. latter is a specialized implementation (ofter mislabelled "ECMA-182") which
  8. is only available in Go, making it highly unlikely to be found in any other
  9. OS or language runtime. See the XZ Format Specification, Section 6.
  10. Author:
  11. Alex Ionescu (@aionescu) 15-May-2021 - Initial version
  12. Environment:
  13. Windows & Linux, user mode and kernel mode.
  14. --*/
  15. #include "minlzlib.h"
  16. #ifdef MINLZ_INTEGRITY_CHECKS
  17. const uint32_t k_Crc32Polynomial = UINT32_C(0xEDB88320);
  18. const uint64_t k_Crc64Polynomial = UINT64_C(0xC96C5795D7870F42);
  19. //
  20. // XZ CRC State
  21. //
  22. typedef struct _CHECKSUM_STATE
  23. {
  24. uint32_t Crc32Table[256];
  25. uint64_t Crc64Table[256];
  26. bool Initialized;
  27. } CHECKSUM_STATE, * PCHECKSUM_STATE;
  28. CHECKSUM_STATE Checksum;
  29. void
  30. XzCrcInitialize (
  31. void
  32. )
  33. {
  34. uint32_t i;
  35. uint32_t j;
  36. uint32_t crc32;
  37. uint64_t crc64;
  38. //
  39. // Don't do anything if the tables are already computed
  40. //
  41. if (!Checksum.Initialized)
  42. {
  43. //
  44. // Build a table of all possible CRC values for each byte, essentially
  45. // creating the checksums for either 00 00 00 XX in the case of 32-bit
  46. // CRC or for 00 00 00 00 00 00 XX in the base of 64-bit CRC.
  47. //
  48. for (i = 0; i < 256; i++)
  49. {
  50. crc32 = i;
  51. crc64 = i;
  52. //
  53. // Divide the input in the 8 coefficients, where the LSB represents
  54. // the coefficient of the highest degree term of the dividend.
  55. //
  56. for (j = 0; j < 8; j++)
  57. {
  58. //
  59. // Is the current coefficient set?
  60. //
  61. if (crc32 & 1)
  62. {
  63. //
  64. // Move to next coefficient and add the rest of the divisor
  65. //
  66. crc32 = (crc32 >> 1) ^ k_Crc32Polynomial;
  67. }
  68. else
  69. {
  70. //
  71. // Skip this and move to the next coefficient
  72. //
  73. crc32 >>= 1;
  74. }
  75. //
  76. // Compute the 64-bit entry using the same algorithm
  77. //
  78. if (crc64 & 1)
  79. {
  80. crc64 = (crc64 >> 1) ^ k_Crc64Polynomial;
  81. }
  82. else
  83. {
  84. crc64 >>= 1;
  85. }
  86. }
  87. //
  88. // Store the final generated result
  89. //
  90. Checksum.Crc32Table[i] = crc32;
  91. Checksum.Crc64Table[i] = crc64;
  92. }
  93. //
  94. // No need to do this again
  95. //
  96. Checksum.Initialized = true;
  97. }
  98. }
  99. uint32_t
  100. XzCrc32 (
  101. uint32_t Crc,
  102. const uint8_t *Buffer,
  103. uint32_t Length
  104. )
  105. {
  106. uint32_t i;
  107. //
  108. // This uses the Dilip V. Sarwate algorithm which shifts one byte at a time
  109. // and produces an intermediate remainder which can then be subtracted from
  110. // the lookup table by using the high 8 bits as an index (since we computed
  111. // all possible one-byte inputs). This relies on the following property:
  112. //
  113. // Mod(A * x^n, P(x)) = Mod(x^n * Mod(A, P(X)), P(X))
  114. //
  115. for (XzCrcInitialize(), Crc = ~Crc, i = 0; i < Length; ++i)
  116. {
  117. Crc = Checksum.Crc32Table[Buffer[i] ^ (Crc & 0xFF)] ^ (Crc >> 8);
  118. }
  119. return ~Crc;
  120. }
  121. uint64_t
  122. XzCrc64 (
  123. uint64_t Crc,
  124. const uint8_t *Buffer,
  125. uint32_t Length
  126. )
  127. {
  128. uint32_t i;
  129. //
  130. // Use the same algorithm to the 64-bit case too. Note that for very large
  131. // input data, a parallel "slicing by 8" approach would yield much faster
  132. // results (as would a "slicing by 4" approach for the 32-bit CRC case).
  133. //
  134. for (XzCrcInitialize(), Crc = ~Crc, i = 0; i < Length; ++i)
  135. {
  136. Crc = Checksum.Crc64Table[Buffer[i] ^ (Crc & 0xFF)] ^ (Crc >> 8);
  137. }
  138. return ~Crc;
  139. }
  140. #endif