Software APIs
crc32.c
1// Copyright lowRISC contributors (OpenTitan project).
2// Licensed under the Apache License, Version 2.0, see LICENSE for details.
3// SPDX-License-Identifier: Apache-2.0
4
5#include "sw/device/lib/base/crc32.h"
6
7#include <stdbool.h>
8
11
12#ifdef OT_PLATFORM_RV32
13enum {
14 /**
15 * CRC32 polynomial.
16 */
17 kCrc32Poly = 0xedb88320,
18 kCrc32Mu = 0xf7011641,
19};
20
22static uint32_t crc32_i(uint32_t x) {
23 uint32_t result;
24 asm(".option push;"
25 ".option arch, +zbc;"
26 "clmul %[result], %[x], %[mu];"
27 "clmulr %[result], %[result], %[poly];"
28 ".option pop;"
29 : [result] "=&r"(result)
30 : [x] "r"(x), [mu] "r"(kCrc32Mu), [poly] "r"(kCrc32Poly));
31 return result;
32}
33
35static uint32_t crc32_internal_add8(uint32_t ctx, uint8_t byte) {
36 ctx ^= byte;
37 return crc32_i(ctx << 24) ^ (ctx >> 8);
38}
39
41static uint32_t crc32_internal_add32(uint32_t ctx, uint32_t word) {
42 ctx ^= word;
43 return crc32_i(ctx);
44}
45#else
46enum {
47 /**
48 * CRC32 polynomial.
49 */
50 kCrc32Poly = 0xedb88320,
51};
52
53/**
54 * Computes the CRC32 of a buffer as expected by Python's `zlib.crc32()`. The
55 * implementation below is basically a simplified, i.e. byte-by-byte and without
56 * a lookup table, version of zlib's crc32, which also matches IEEE 802.3
57 * CRC-32. See
58 * https://github.com/madler/zlib/blob/2fa463bacfff79181df1a5270fb67cc679a53e71/crc32.c,
59 * lines 111-112 and 276-279.
60 */
62static uint32_t crc32_internal_add8(uint32_t ctx, uint8_t byte) {
63 ctx ^= byte;
64 for (size_t i = 0; i < 8; ++i) {
65 bool lsb = ctx & 1;
66 ctx >>= 1;
67 if (lsb) {
68 ctx ^= kCrc32Poly;
69 }
70 }
71 return ctx;
72}
73
75static uint32_t crc32_internal_add32(uint32_t ctx, uint32_t word) {
76 char *bytes = (char *)&word;
77 for (size_t i = 0; i < sizeof(uint32_t); ++i) {
78 ctx = crc32_internal_add8(ctx, bytes[i]);
79 }
80 return ctx;
81}
82#endif
83
84void crc32_init(uint32_t *ctx) { *ctx = UINT32_MAX; }
85
86void crc32_add8(uint32_t *ctx, uint8_t byte) {
87 *ctx = crc32_internal_add8(*ctx, byte);
88}
89
90void crc32_add32(uint32_t *ctx, uint32_t word) {
91 *ctx = crc32_internal_add32(*ctx, word);
92}
93
94void crc32_add(uint32_t *ctx, const void *buf, size_t len) {
95 const char *data = buf;
96 uint32_t state = *ctx;
97 // Unaligned head.
98 for (; len > 0 && (uintptr_t)data & 0x3; --len, ++data) {
99 state = crc32_internal_add8(state, *data);
100 }
101 // Aligned body.
102 for (; len >= sizeof(uint32_t);
103 len -= sizeof(uint32_t), data += sizeof(uint32_t)) {
104 state = crc32_internal_add32(state, read_32(data));
105 }
106 // Unaligned tail.
107 for (; len > 0; --len, ++data) {
108 state = crc32_internal_add8(state, *data);
109 }
110 *ctx = state;
111}
112
113uint32_t crc32_finish(const uint32_t *ctx) { return *ctx ^ UINT32_MAX; }
114
115uint32_t crc32(const void *buf, size_t len) {
116 uint32_t ctx;
117 crc32_init(&ctx);
118 crc32_add(&ctx, buf, len);
119 return crc32_finish(&ctx);
120}