1 /*
2  * Copyright (c) 2018 Workaround GmbH.
3  * Copyright (c) 2017 Intel Corporation.
4  * Copyright (c) 2017 Nordic Semiconductor ASA
5  * Copyright (c) 2015 Runtime Inc
6  * Copyright (c) 2018 Google LLC.
7  * Copyright (c) 2022 Meta
8  *
9  * SPDX-License-Identifier: Apache-2.0
10  */
11 /** @file
12  * @brief CRC computation function
13  */
14 
15 #ifndef ZEPHYR_INCLUDE_SYS_CRC_H_
16 #define ZEPHYR_INCLUDE_SYS_CRC_H_
17 
18 #include <zephyr/types.h>
19 #include <stdbool.h>
20 #include <stddef.h>
21 
22 #include <zephyr/sys/__assert.h>
23 
24 #ifdef __cplusplus
25 extern "C" {
26 #endif
27 
28 /* Initial value expected to be used at the beginning of the crc8_ccitt
29  * computation.
30  */
31 #define CRC8_CCITT_INITIAL_VALUE 0xFF
32 
33 /**
34  * @defgroup checksum Checksum
35  * @ingroup os_services
36  */
37 
38 /**
39  * @defgroup crc CRC
40  * @ingroup checksum
41  * @{
42  */
43 
44 /**
45  * @brief CRC algorithm enumeration
46  *
47  * These values should be used with the @ref crc dispatch function.
48  */
49 enum crc_type {
50 	CRC4,        /**< Use @ref crc4 */
51 	CRC4_TI,     /**< Use @ref crc4_ti */
52 	CRC7_BE,     /**< Use @ref crc7_be */
53 	CRC8,	     /**< Use @ref crc8 */
54 	CRC8_CCITT,  /**< Use @ref crc8_ccitt */
55 	CRC16,	     /**< Use @ref crc16 */
56 	CRC16_ANSI,  /**< Use @ref crc16_ansi */
57 	CRC16_CCITT, /**< Use @ref crc16_ccitt */
58 	CRC16_ITU_T, /**< Use @ref crc16_itu_t */
59 	CRC32_C,     /**< Use @ref crc32_c */
60 	CRC32_IEEE,  /**< Use @ref crc32_ieee */
61 };
62 
63 /**
64  * @brief Generic function for computing a CRC-16 without input or output
65  *        reflection.
66  *
67  * Compute CRC-16 by passing in the address of the input, the input length
68  * and polynomial used in addition to the initial value. This is O(n*8) where n
69  * is the length of the buffer provided. No reflection is performed.
70  *
71  * @note If you are planning to use a CRC based on poly 0x1012 the functions
72  * crc16_itu_t() is faster and thus recommended over this one.
73  *
74  * @param poly The polynomial to use omitting the leading x^16
75  *             coefficient
76  * @param seed Initial value for the CRC computation
77  * @param src Input bytes for the computation
78  * @param len Length of the input in bytes
79  *
80  * @return The computed CRC16 value (without any XOR applied to it)
81  */
82 uint16_t crc16(uint16_t poly, uint16_t seed, const uint8_t *src, size_t len);
83 
84 /**
85  * @brief Generic function for computing a CRC-16 with input and output
86  *        reflection.
87  *
88  * Compute CRC-16 by passing in the address of the input, the input length
89  * and polynomial used in addition to the initial value. This is O(n*8) where n
90  * is the length of the buffer provided. Both input and output are reflected.
91  *
92  * @note If you are planning to use a CRC based on poly 0x1012 the function
93  * crc16_ccitt() is faster and thus recommended over this one.
94  *
95  * The following checksums can, among others, be calculated by this function,
96  * depending on the value provided for the initial seed and the value the final
97  * calculated CRC is XORed with:
98  *
99  * - CRC-16/ANSI, CRC-16/MODBUS, CRC-16/USB, CRC-16/IBM
100  *   https://reveng.sourceforge.io/crc-catalogue/16.htm#crc.cat.crc-16-modbus
101  *   poly: 0x8005 (0xA001) initial seed: 0xffff, xor output: 0x0000
102  *
103  * @param poly The polynomial to use omitting the leading x^16
104  *             coefficient. Important: please reflect the poly. For example,
105  *             use 0xA001 instead of 0x8005 for CRC-16-MODBUS.
106  * @param seed Initial value for the CRC computation
107  * @param src Input bytes for the computation
108  * @param len Length of the input in bytes
109  *
110  * @return The computed CRC16 value (without any XOR applied to it)
111  */
112 uint16_t crc16_reflect(uint16_t poly, uint16_t seed, const uint8_t *src, size_t len);
113 /**
114  * @brief Generic function for computing CRC 8
115  *
116  * Compute CRC 8 by passing in the address of the input, the input length
117  * and polynomial used in addition to the initial value.
118  *
119  * @param src Input bytes for the computation
120  * @param len Length of the input in bytes
121  * @param polynomial The polynomial to use omitting the leading x^8
122  *        coefficient
123  * @param initial_value Initial value for the CRC computation
124  * @param reversed Should we use reflected/reversed values or not
125  *
126  * @return The computed CRC8 value
127  */
128 uint8_t crc8(const uint8_t *src, size_t len, uint8_t polynomial, uint8_t initial_value,
129 	  bool reversed);
130 
131 /**
132  * @brief Compute the checksum of a buffer with polynomial 0x1021, reflecting
133  *        input and output.
134  *
135  * This function is able to calculate any CRC that uses 0x1021 as it polynomial
136  * and requires reflecting both the input and the output. It is a fast variant
137  * that runs in O(n) time, where n is the length of the input buffer.
138  *
139  * The following checksums can, among others, be calculated by this function,
140  * depending on the value provided for the initial seed and the value the final
141  * calculated CRC is XORed with:
142  *
143  * - CRC-16/CCITT, CRC-16/CCITT-TRUE, CRC-16/KERMIT
144  *   https://reveng.sourceforge.io/crc-catalogue/16.htm#crc.cat.crc-16-kermit
145  *   initial seed: 0x0000, xor output: 0x0000
146  *
147  * - CRC-16/X-25, CRC-16/IBM-SDLC, CRC-16/ISO-HDLC
148  *   https://reveng.sourceforge.io/crc-catalogue/16.htm#crc.cat.crc-16-ibm-sdlc
149  *   initial seed: 0xffff, xor output: 0xffff
150  *
151  * @note To calculate the CRC across non-contiguous blocks use the return
152  *       value from block N-1 as the seed for block N.
153  *
154  * See ITU-T Recommendation V.41 (November 1988).
155  *
156  * @param seed Value to seed the CRC with
157  * @param src Input bytes for the computation
158  * @param len Length of the input in bytes
159  *
160  * @return The computed CRC16 value (without any XOR applied to it)
161  */
162 uint16_t crc16_ccitt(uint16_t seed, const uint8_t *src, size_t len);
163 
164 /**
165  * @brief Compute the checksum of a buffer with polynomial 0x1021, no
166  *        reflection of input or output.
167  *
168  * This function is able to calculate any CRC that uses 0x1021 as it polynomial
169  * and requires no reflection on  both the input and the output. It is a fast
170  * variant that runs in O(n) time, where n is the length of the input buffer.
171  *
172  * The following checksums can, among others, be calculated by this function,
173  * depending on the value provided for the initial seed and the value the final
174  * calculated CRC is XORed with:
175  *
176  * - CRC-16/XMODEM, CRC-16/ACORN, CRC-16/LTE
177  *   https://reveng.sourceforge.io/crc-catalogue/16.htm#crc.cat.crc-16-xmodem
178  *   initial seed: 0x0000, xor output: 0x0000
179  *
180  * - CRC16/CCITT-FALSE, CRC-16/IBM-3740, CRC-16/AUTOSAR
181  *   https://reveng.sourceforge.io/crc-catalogue/16.htm#crc.cat.crc-16-ibm-3740
182  *   initial seed: 0xffff, xor output: 0x0000
183  *
184  * - CRC-16/GSM
185  *   https://reveng.sourceforge.io/crc-catalogue/16.htm#crc.cat.crc-16-gsm
186  *   initial seed: 0x0000, xor output: 0xffff
187  *
188  * @note To calculate the CRC across non-contiguous blocks use the return
189  *       value from block N-1 as the seed for block N.
190  *
191  * See ITU-T Recommendation V.41 (November 1988) (MSB first).
192  *
193  * @param seed Value to seed the CRC with
194  * @param src Input bytes for the computation
195  * @param len Length of the input in bytes
196  *
197  * @return The computed CRC16 value (without any XOR applied to it)
198  */
199 uint16_t crc16_itu_t(uint16_t seed, const uint8_t *src, size_t len);
200 
201 /**
202  * @brief Compute the ANSI (or Modbus) variant of CRC-16
203  *
204  * The ANSI variant of CRC-16 uses 0x8005 (0xA001 reflected) as its polynomial
205  * with the initial * value set to 0xffff.
206  *
207  * @param src Input bytes for the computation
208  * @param len Length of the input in bytes
209  *
210  * @return The computed CRC16 value
211  */
crc16_ansi(const uint8_t * src,size_t len)212 static inline uint16_t crc16_ansi(const uint8_t *src, size_t len)
213 {
214 	return crc16_reflect(0xA001, 0xffff, src, len);
215 }
216 
217 /**
218  * @brief Generate IEEE conform CRC32 checksum.
219  *
220  * @param  data         Pointer to data on which the CRC should be calculated.
221  * @param  len          Data length.
222  *
223  * @return CRC32 value.
224  *
225  */
226 uint32_t crc32_ieee(const uint8_t *data, size_t len);
227 
228 /**
229  * @brief Update an IEEE conforming CRC32 checksum.
230  *
231  * @param crc   CRC32 checksum that needs to be updated.
232  * @param data  Pointer to data on which the CRC should be calculated.
233  * @param len   Data length.
234  *
235  * @return CRC32 value.
236  *
237  */
238 uint32_t crc32_ieee_update(uint32_t crc, const uint8_t *data, size_t len);
239 
240 /**
241  * @brief Calculate CRC32C (Castagnoli) checksum.
242  *
243  * @param crc       CRC32C checksum that needs to be updated.
244  * @param data      Pointer to data on which the CRC should be calculated.
245  * @param len       Data length.
246  * @param first_pkt Whether this is the first packet in the stream.
247  * @param last_pkt  Whether this is the last packet in the stream.
248  *
249  * @return CRC32 value.
250  *
251  */
252 uint32_t crc32_c(uint32_t crc, const uint8_t *data,
253 		 size_t len, bool first_pkt, bool last_pkt);
254 
255 /**
256  * @brief Compute CCITT variant of CRC 8
257  *
258  * Normal CCITT variant of CRC 8 is using 0x07.
259  *
260  * @param initial_value Initial value for the CRC computation
261  * @param buf Input bytes for the computation
262  * @param len Length of the input in bytes
263  *
264  * @return The computed CRC8 value
265  */
266 uint8_t crc8_ccitt(uint8_t initial_value, const void *buf, size_t len);
267 
268 /**
269  * @brief Compute the CRC-7 checksum of a buffer.
270  *
271  * See JESD84-A441.  Used by the MMC protocol.  Uses 0x09 as the
272  * polynomial with no reflection.  The CRC is left
273  * justified, so bit 7 of the result is bit 6 of the CRC.
274  *
275  * @param seed Value to seed the CRC with
276  * @param src Input bytes for the computation
277  * @param len Length of the input in bytes
278  *
279  * @return The computed CRC7 value
280  */
281 uint8_t crc7_be(uint8_t seed, const uint8_t *src, size_t len);
282 
283 /**
284  * @brief Compute the CRC-4 checksum of a buffer.
285  *
286  * Used by the TMAG5170 sensor. Uses 0x03 as the
287  * polynomial with no reflection. 4 most significant
288  * bits of the CRC result will be set to zero.
289  *
290  * @param seed Value to seed the CRC with
291  * @param src Input bytes for the computation
292  * @param len Length of the input in bytes
293  *
294  * @return The computed CRC4 value
295  */
296 uint8_t crc4_ti(uint8_t seed, const uint8_t *src, size_t len);
297 
298 /**
299  * @brief Generic function for computing CRC 4
300  *
301  * Compute CRC 4 by passing in the address of the input, the input length
302  * and polynomial used in addition to the initial value. The input buffer
303  * must be aligned to a whole byte. It is guaranteed that 4 most significant
304  * bits of the result will be set to zero.
305  *
306  * @param src Input bytes for the computation
307  * @param len Length of the input in bytes
308  * @param polynomial The polynomial to use omitting the leading x^4
309  *        coefficient
310  * @param initial_value Initial value for the CRC computation
311  * @param reversed Should we use reflected/reversed values or not
312  *
313  * @return The computed CRC4 value
314  */
315 uint8_t crc4(const uint8_t *src, size_t len, uint8_t polynomial, uint8_t initial_value,
316 	  bool reversed);
317 
318 /**
319  * @brief Compute a CRC checksum, in a generic way.
320  *
321  * This is a dispatch function that calls the individual CRC routine
322  * determined by @p type.
323  *
324  * For 7, 8, and 16-bit CRCs, the relevant @p seed and @p poly values should
325  * be passed in via the least-significant byte(s).
326  *
327  * Similarly, for 7, 8, and 16-bit CRCs, the relevant result is stored in the
328  * least-significant byte(s) of the returned value.
329  *
330  * @param type CRC algorithm to use.
331  * @param src Input bytes for the computation
332  * @param len Length of the input in bytes
333  * @param seed Value to seed the CRC with
334  * @param poly The polynomial to use omitting the leading coefficient
335  * @param reflect Should we use reflected/reversed values or not
336  * @param first Whether this is the first packet in the stream.
337  * @param last Whether this is the last packet in the stream.
338  * @return uint32_t the computed CRC value
339  */
crc_by_type(enum crc_type type,const uint8_t * src,size_t len,uint32_t seed,uint32_t poly,bool reflect,bool first,bool last)340 static inline uint32_t crc_by_type(enum crc_type type, const uint8_t *src, size_t len,
341 				   uint32_t seed, uint32_t poly, bool reflect, bool first,
342 				   bool last)
343 {
344 	switch (type) {
345 	case CRC4:
346 		return crc4(src, len, poly, seed, reflect);
347 	case CRC4_TI:
348 		return crc4_ti(seed, src, len);
349 	case CRC7_BE:
350 		return crc7_be(seed, src, len);
351 	case CRC8:
352 		return crc8(src, len, poly, seed, reflect);
353 	case CRC8_CCITT:
354 		return crc8_ccitt(seed, src, len);
355 	case CRC16:
356 		if (reflect) {
357 			return crc16_reflect(poly, seed, src, len);
358 		} else {
359 			return crc16(poly, seed, src, len);
360 		}
361 	case CRC16_ANSI:
362 		return crc16_ansi(src, len);
363 	case CRC16_CCITT:
364 		return crc16_ccitt(seed, src, len);
365 	case CRC16_ITU_T:
366 		return crc16_itu_t(seed, src, len);
367 	case CRC32_C:
368 		return crc32_c(seed, src, len, first, last);
369 	case CRC32_IEEE:
370 		return crc32_ieee_update(seed, src, len);
371 	default:
372 		break;
373 	}
374 
375 	__ASSERT_NO_MSG(false);
376 	return -1;
377 }
378 
379 /**
380  * @}
381  */
382 
383 #ifdef __cplusplus
384 }
385 #endif
386 
387 #endif
388