LCOV - code coverage report
Current view: top level - zephyr/sys - crc.h Coverage Total Hit
Test: new.info Lines: 89.2 % 37 33
Test Date: 2025-09-25 19:22:35

            Line data    Source code
       1            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              :  * Copyright (c) 2024 Intercreate, Inc.
       9              :  *
      10              :  * SPDX-License-Identifier: Apache-2.0
      11              :  */
      12              : /** @file
      13              :  * @brief CRC computation function
      14              :  */
      15              : 
      16              : #ifndef ZEPHYR_INCLUDE_SYS_CRC_H_
      17              : #define ZEPHYR_INCLUDE_SYS_CRC_H_
      18              : 
      19              : #include <zephyr/types.h>
      20              : #include <stdbool.h>
      21              : #include <stddef.h>
      22              : 
      23              : #include <zephyr/sys/__assert.h>
      24              : 
      25              : #ifdef __cplusplus
      26              : extern "C" {
      27              : #endif
      28              : 
      29              : /* Initial value expected to be used at the beginning of the crc8_ccitt
      30              :  * computation.
      31              :  */
      32            0 : #define CRC8_CCITT_INITIAL_VALUE 0xFF
      33            0 : #define CRC8_ROHC_INITIAL_VALUE  0xFF
      34              : 
      35              : /* Initial value expected to be used at the beginning of the OpenPGP CRC-24 computation. */
      36            0 : #define CRC24_PGP_INITIAL_VALUE 0x00B704CEU
      37              : /*
      38              :  * The CRC-24 value is stored on a 32-bit value, only the 3 least significant bytes
      39              :  * are meaningful. Use the following mask to only keep the CRC-24 value.
      40              :  */
      41            0 : #define CRC24_FINAL_VALUE_MASK 0x00FFFFFFU
      42              : 
      43              : /**
      44              :  * @defgroup checksum Checksum
      45              :  * @ingroup os_services
      46              :  */
      47              : 
      48              : /**
      49              :  * @defgroup crc CRC
      50              :  * @ingroup checksum
      51              :  * @{
      52              :  */
      53              : 
      54              : /**
      55              :  * @brief CRC polynomial definitions
      56              :  * @anchor CRC_POLYNOMIAL
      57              :  *
      58              :  * @{
      59              :  */
      60              : 
      61              : /** CRC4 polynomial */
      62            1 : #define CRC4_POLY 0x3
      63              : 
      64              : /** CRC4_TI polynomial */
      65            1 : #define CRC4_REFLECT_POLY 0xC
      66              : 
      67              : /** CRC7_BE polynomial */
      68            1 : #define CRC7_BE_POLY 0x09
      69              : 
      70              : /** CRC8 polynomial */
      71            1 : #define CRC8_POLY 0x07
      72              : 
      73              : /** CRC8_CCITT polynomial */
      74            1 : #define CRC8_REFLECT_POLY 0xE0
      75              : 
      76              : /** CRC8_ROHC polynomial */
      77            1 : #define CRC16_POLY 0x8005
      78              : 
      79              : /** CRC16_ANSI polynomial */
      80            1 : #define CRC16_REFLECT_POLY 0xA001
      81              : 
      82              : /** CRC16_CCITT polynomial */
      83            1 : #define CRC16_CCITT_POLY 0x1021
      84              : 
      85              : /** CRC16_ITU_T polynomial */
      86            1 : #define CRC24_PGP_POLY 0x01864CFBU
      87              : 
      88              : /** CRC32_C polynomial */
      89            1 : #define CRC32_IEEE_POLY 0x04C11DB7U
      90              : 
      91              : /** CRC32C polynomial */
      92            1 : #define CRC32C_POLY 0x1EDC6F41U
      93              : 
      94              : /** CRC32_K_4_2 polynomial */
      95            1 : #define CRC32K_4_2_POLY 0x93A409EBU
      96              : 
      97              : /** @} */
      98              : 
      99              : /**
     100              :  * @brief CRC algorithm enumeration
     101              :  *
     102              :  * These values should be used with the @ref crc dispatch function.
     103              :  */
     104            1 : enum crc_type {
     105              :         CRC4,        /**< Use @ref crc4 */
     106              :         CRC4_TI,     /**< Use @ref crc4_ti */
     107              :         CRC7_BE,     /**< Use @ref crc7_be */
     108              :         CRC8,        /**< Use @ref crc8 */
     109              :         CRC8_CCITT,  /**< Use @ref crc8_ccitt */
     110              :         CRC8_ROHC,   /**< Use @ref crc8_rohc */
     111              :         CRC16,       /**< Use @ref crc16 */
     112              :         CRC16_ANSI,  /**< Use @ref crc16_ansi */
     113              :         CRC16_CCITT, /**< Use @ref crc16_ccitt */
     114              :         CRC16_ITU_T, /**< Use @ref crc16_itu_t */
     115              :         CRC24_PGP,   /**< Use @ref crc24_pgp */
     116              :         CRC32_C,     /**< Use @ref crc32_c */
     117              :         CRC32_IEEE,  /**< Use @ref crc32_ieee */
     118              :         CRC32_K_4_2, /**< Use @ref crc32_k_4_2_update */
     119              : };
     120              : 
     121              : /**
     122              :  * @brief Generic function for computing a CRC-16 without input or output
     123              :  *        reflection.
     124              :  *
     125              :  * Compute CRC-16 by passing in the address of the input, the input length
     126              :  * and polynomial used in addition to the initial value. This is O(n*8) where n
     127              :  * is the length of the buffer provided. No reflection is performed.
     128              :  *
     129              :  * @note If you are planning to use a CRC based on poly 0x1012 the functions
     130              :  * crc16_itu_t() is faster and thus recommended over this one.
     131              :  *
     132              :  * @param poly The polynomial to use omitting the leading x^16
     133              :  *             coefficient
     134              :  * @param seed Initial value for the CRC computation
     135              :  * @param src Input bytes for the computation
     136              :  * @param len Length of the input in bytes
     137              :  *
     138              :  * @return The computed CRC16 value (without any XOR applied to it)
     139              :  */
     140            1 : uint16_t crc16(uint16_t poly, uint16_t seed, const uint8_t *src, size_t len);
     141              : 
     142              : /**
     143              :  * @brief Generic function for computing a CRC-16 with input and output
     144              :  *        reflection.
     145              :  *
     146              :  * Compute CRC-16 by passing in the address of the input, the input length
     147              :  * and polynomial used in addition to the initial value. This is O(n*8) where n
     148              :  * is the length of the buffer provided. Both input and output are reflected.
     149              :  *
     150              :  * @note If you are planning to use a CRC based on poly 0x1012 the function
     151              :  * crc16_ccitt() is faster and thus recommended over this one.
     152              :  *
     153              :  * The following checksums can, among others, be calculated by this function,
     154              :  * depending on the value provided for the initial seed and the value the final
     155              :  * calculated CRC is XORed with:
     156              :  *
     157              :  * - CRC-16/ANSI, CRC-16/MODBUS, CRC-16/USB, CRC-16/IBM
     158              :  *   https://reveng.sourceforge.io/crc-catalogue/16.htm#crc.cat.crc-16-modbus
     159              :  *   poly: 0x8005 (0xA001) initial seed: 0xffff, xor output: 0x0000
     160              :  *
     161              :  * @param poly The polynomial to use omitting the leading x^16
     162              :  *             coefficient. Important: please reflect the poly. For example,
     163              :  *             use 0xA001 instead of 0x8005 for CRC-16-MODBUS.
     164              :  * @param seed Initial value for the CRC computation
     165              :  * @param src Input bytes for the computation
     166              :  * @param len Length of the input in bytes
     167              :  *
     168              :  * @return The computed CRC16 value (without any XOR applied to it)
     169              :  */
     170            1 : uint16_t crc16_reflect(uint16_t poly, uint16_t seed, const uint8_t *src, size_t len);
     171              : /**
     172              :  * @brief Generic function for computing CRC 8
     173              :  *
     174              :  * Compute CRC 8 by passing in the address of the input, the input length
     175              :  * and polynomial used in addition to the initial value.
     176              :  *
     177              :  * @param src Input bytes for the computation
     178              :  * @param len Length of the input in bytes
     179              :  * @param polynomial The polynomial to use omitting the leading x^8
     180              :  *        coefficient
     181              :  * @param initial_value Initial value for the CRC computation
     182              :  * @param reversed Should we use reflected/reversed values or not
     183              :  *
     184              :  * @return The computed CRC8 value
     185              :  */
     186            1 : uint8_t crc8(const uint8_t *src, size_t len, uint8_t polynomial, uint8_t initial_value,
     187              :              bool reversed);
     188              : 
     189              : /**
     190              :  * @brief Compute the checksum of a buffer with polynomial 0x1021, reflecting
     191              :  *        input and output.
     192              :  *
     193              :  * This function is able to calculate any CRC that uses 0x1021 as it polynomial
     194              :  * and requires reflecting both the input and the output. It is a fast variant
     195              :  * that runs in O(n) time, where n is the length of the input buffer.
     196              :  *
     197              :  * The following checksums can, among others, be calculated by this function,
     198              :  * depending on the value provided for the initial seed and the value the final
     199              :  * calculated CRC is XORed with:
     200              :  *
     201              :  * - CRC-16/CCITT, CRC-16/CCITT-TRUE, CRC-16/KERMIT
     202              :  *   https://reveng.sourceforge.io/crc-catalogue/16.htm#crc.cat.crc-16-kermit
     203              :  *   initial seed: 0x0000, xor output: 0x0000
     204              :  *
     205              :  * - CRC-16/X-25, CRC-16/IBM-SDLC, CRC-16/ISO-HDLC
     206              :  *   https://reveng.sourceforge.io/crc-catalogue/16.htm#crc.cat.crc-16-ibm-sdlc
     207              :  *   initial seed: 0xffff, xor output: 0xffff
     208              :  *
     209              :  * @note To calculate the CRC across non-contiguous blocks use the return
     210              :  *       value from block N-1 as the seed for block N.
     211              :  *
     212              :  * See ITU-T Recommendation V.41 (November 1988).
     213              :  *
     214              :  * @param seed Value to seed the CRC with
     215              :  * @param src Input bytes for the computation
     216              :  * @param len Length of the input in bytes
     217              :  *
     218              :  * @return The computed CRC16 value (without any XOR applied to it)
     219              :  */
     220            1 : uint16_t crc16_ccitt(uint16_t seed, const uint8_t *src, size_t len);
     221              : 
     222              : /**
     223              :  * @brief Compute the checksum of a buffer with polynomial 0x1021, no
     224              :  *        reflection of input or output.
     225              :  *
     226              :  * This function is able to calculate any CRC that uses 0x1021 as it polynomial
     227              :  * and requires no reflection on  both the input and the output. It is a fast
     228              :  * variant that runs in O(n) time, where n is the length of the input buffer.
     229              :  *
     230              :  * The following checksums can, among others, be calculated by this function,
     231              :  * depending on the value provided for the initial seed and the value the final
     232              :  * calculated CRC is XORed with:
     233              :  *
     234              :  * - CRC-16/XMODEM, CRC-16/ACORN, CRC-16/LTE
     235              :  *   https://reveng.sourceforge.io/crc-catalogue/16.htm#crc.cat.crc-16-xmodem
     236              :  *   initial seed: 0x0000, xor output: 0x0000
     237              :  *
     238              :  * - CRC16/CCITT-FALSE, CRC-16/IBM-3740, CRC-16/AUTOSAR
     239              :  *   https://reveng.sourceforge.io/crc-catalogue/16.htm#crc.cat.crc-16-ibm-3740
     240              :  *   initial seed: 0xffff, xor output: 0x0000
     241              :  *
     242              :  * - CRC-16/GSM
     243              :  *   https://reveng.sourceforge.io/crc-catalogue/16.htm#crc.cat.crc-16-gsm
     244              :  *   initial seed: 0x0000, xor output: 0xffff
     245              :  *
     246              :  * @note To calculate the CRC across non-contiguous blocks use the return
     247              :  *       value from block N-1 as the seed for block N.
     248              :  *
     249              :  * See ITU-T Recommendation V.41 (November 1988) (MSB first).
     250              :  *
     251              :  * @param seed Value to seed the CRC with
     252              :  * @param src Input bytes for the computation
     253              :  * @param len Length of the input in bytes
     254              :  *
     255              :  * @return The computed CRC16 value (without any XOR applied to it)
     256              :  */
     257            1 : uint16_t crc16_itu_t(uint16_t seed, const uint8_t *src, size_t len);
     258              : 
     259              : /**
     260              :  * @brief Compute the ANSI (or Modbus) variant of CRC-16
     261              :  *
     262              :  * The ANSI variant of CRC-16 uses 0x8005 (0xA001 reflected) as its polynomial
     263              :  * with the initial * value set to 0xffff.
     264              :  *
     265              :  * @param src Input bytes for the computation
     266              :  * @param len Length of the input in bytes
     267              :  *
     268              :  * @return The computed CRC16 value
     269              :  */
     270            1 : static inline uint16_t crc16_ansi(const uint8_t *src, size_t len)
     271              : {
     272              :         return crc16_reflect(0xA001, 0xffff, src, len);
     273              : }
     274              : 
     275              : /**
     276              :  * @brief Generate IEEE conform CRC32 checksum.
     277              :  *
     278              :  * @param  data         Pointer to data on which the CRC should be calculated.
     279              :  * @param  len          Data length.
     280              :  *
     281              :  * @return CRC32 value.
     282              :  *
     283              :  */
     284            1 : uint32_t crc32_ieee(const uint8_t *data, size_t len);
     285              : 
     286              : /**
     287              :  * @brief Update an IEEE conforming CRC32 checksum.
     288              :  *
     289              :  * @param crc   CRC32 checksum that needs to be updated.
     290              :  * @param data  Pointer to data on which the CRC should be calculated.
     291              :  * @param len   Data length.
     292              :  *
     293              :  * @return CRC32 value.
     294              :  *
     295              :  */
     296            1 : uint32_t crc32_ieee_update(uint32_t crc, const uint8_t *data, size_t len);
     297              : 
     298              : /**
     299              :  * @brief Calculate CRC32C (Castagnoli) checksum.
     300              :  *
     301              :  * @param crc       CRC32C checksum that needs to be updated.
     302              :  * @param data      Pointer to data on which the CRC should be calculated.
     303              :  * @param len       Data length.
     304              :  * @param first_pkt Whether this is the first packet in the stream.
     305              :  * @param last_pkt  Whether this is the last packet in the stream.
     306              :  *
     307              :  * @return CRC32 value.
     308              :  *
     309              :  */
     310            1 : uint32_t crc32_c(uint32_t crc, const uint8_t *data,
     311              :                  size_t len, bool first_pkt, bool last_pkt);
     312              : 
     313              : /**
     314              :  * @brief Update a CRC-32K/4.2 (*op) (Koopman) checksum. This is a good HD=4
     315              :  * checksum up to 2,147,483,615 bits and HD=5/6 up to 6,167 bits.
     316              :  *
     317              :  * Hamming Distance and properties:
     318              :  *
     319              :  * - Polynomial: 0x93a409eb
     320              :  * - reflect-in: false
     321              :  * - initial value (xor-in): provided by caller as crc argument (0xFFFFFFFF is OK)
     322              :  * - reflect-out: false
     323              :  * - xor-out: 0
     324              :  * - HD=4 @ 2,147,483,615 bits
     325              :  * - HD=5 @ 6,167 bits
     326              :  * - HD=6 @ 6,167 bits
     327              :  * - HD=7 @ 148 bits
     328              :  *
     329              :  * Reference: https://users.ece.cmu.edu/~koopman/crc/crc32.html
     330              :  *
     331              :  * @param crc       CRC32 checksum that needs to be updated.
     332              :  * @param data      Pointer to data on which the CRC should be calculated.
     333              :  * @param len       Data length.
     334              :  *
     335              :  * @return CRC32 value.
     336              :  */
     337            1 : uint32_t crc32_k_4_2_update(uint32_t crc, const uint8_t *data, size_t len);
     338              : 
     339              : /**
     340              :  * @brief Compute CCITT variant of CRC 8
     341              :  *
     342              :  * Normal CCITT variant of CRC 8 is using 0x07.
     343              :  *
     344              :  * @param initial_value Initial value for the CRC computation
     345              :  * @param buf Input bytes for the computation
     346              :  * @param len Length of the input in bytes
     347              :  *
     348              :  * @return The computed CRC8 value
     349              :  */
     350            1 : uint8_t crc8_ccitt(uint8_t initial_value, const void *buf, size_t len);
     351              : 
     352              : /**
     353              :  * @brief Compute ROHC variant of CRC 8
     354              :  *
     355              :  * ROHC (Robust Header Compression) variant of CRC 8.
     356              :  * Uses 0x07 as the polynomial with reflection.
     357              :  *
     358              :  * @param initial_value Initial value for the CRC computation
     359              :  * @param buf Input bytes for the computation
     360              :  * @param len Length of the input in bytes
     361              :  *
     362              :  * @return The computed CRC8 value
     363              :  */
     364            1 : uint8_t crc8_rohc(uint8_t initial_value, const void *buf, size_t len);
     365              : 
     366              : /**
     367              :  * @brief Compute the CRC-7 checksum of a buffer.
     368              :  *
     369              :  * See JESD84-A441.  Used by the MMC protocol.  Uses 0x09 as the
     370              :  * polynomial with no reflection.  The CRC is left
     371              :  * justified, so bit 7 of the result is bit 6 of the CRC.
     372              :  *
     373              :  * @param seed Value to seed the CRC with
     374              :  * @param src Input bytes for the computation
     375              :  * @param len Length of the input in bytes
     376              :  *
     377              :  * @return The computed CRC7 value
     378              :  */
     379            1 : uint8_t crc7_be(uint8_t seed, const uint8_t *src, size_t len);
     380              : 
     381              : /**
     382              :  * @brief Compute the CRC-4 checksum of a buffer.
     383              :  *
     384              :  * Used by the TMAG5170 sensor. Uses 0x03 as the
     385              :  * polynomial with no reflection. 4 most significant
     386              :  * bits of the CRC result will be set to zero.
     387              :  *
     388              :  * @param seed Value to seed the CRC with
     389              :  * @param src Input bytes for the computation
     390              :  * @param len Length of the input in bytes
     391              :  *
     392              :  * @return The computed CRC4 value
     393              :  */
     394            1 : uint8_t crc4_ti(uint8_t seed, const uint8_t *src, size_t len);
     395              : 
     396              : /**
     397              :  * @brief Generic function for computing CRC 4
     398              :  *
     399              :  * Compute CRC 4 by passing in the address of the input, the input length
     400              :  * and polynomial used in addition to the initial value. The input buffer
     401              :  * must be aligned to a whole byte. It is guaranteed that 4 most significant
     402              :  * bits of the result will be set to zero.
     403              :  *
     404              :  * @param src Input bytes for the computation
     405              :  * @param len Length of the input in bytes
     406              :  * @param polynomial The polynomial to use omitting the leading x^4
     407              :  *        coefficient
     408              :  * @param initial_value Initial value for the CRC computation
     409              :  * @param reversed Should we use reflected/reversed values or not
     410              :  *
     411              :  * @return The computed CRC4 value
     412              :  */
     413            1 : uint8_t crc4(const uint8_t *src, size_t len, uint8_t polynomial, uint8_t initial_value,
     414              :              bool reversed);
     415              : 
     416              : /**
     417              :  * @brief Generate an OpenPGP CRC-24 checksum as defined in RFC 4880 section 6.1.
     418              :  *
     419              :  * @param data A pointer to the data on which the CRC will be calculated.
     420              :  * @param len Data length in bytes.
     421              :  *
     422              :  * @return The CRC-24 value.
     423              :  */
     424            1 : uint32_t crc24_pgp(const uint8_t *data, size_t len);
     425              : 
     426              : /**
     427              :  * @brief Update an OpenPGP CRC-24 checksum.
     428              :  *
     429              :  * @param crc The CRC-24 checksum that needs to be updated. The full 32-bit value of the CRC needs
     430              :  *            to be used between calls, do not mask the value to keep only the last 24 bits.
     431              :  * @param data A pointer to the data on which the CRC will be calculated.
     432              :  * @param len  Data length in bytes.
     433              :  *
     434              :  * @return The CRC-24 value. When the last buffer of data has been processed, mask the value
     435              :  *         with CRC24_FINAL_VALUE_MASK to keep only the meaningful 24 bits of the CRC result.
     436              :  */
     437            1 : uint32_t crc24_pgp_update(uint32_t crc, const uint8_t *data, size_t len);
     438              : 
     439              : /**
     440              :  * @brief Calculate an RTCM3 CRC24Q frame checksum
     441              :  *
     442              :  * @param[in] data RTCM3 Frame
     443              :  * @param[in] len Frame length in bytes.
     444              :  *
     445              :  * @return 0 if the data-frame contains a checksum and it matches.
     446              :  * @return Result if data-frame does not contain checksum.
     447              :  */
     448            1 : uint32_t crc24q_rtcm3(const uint8_t *data, size_t len);
     449              : 
     450              : /**
     451              :  * @brief Compute a CRC checksum, in a generic way.
     452              :  *
     453              :  * This is a dispatch function that calls the individual CRC routine
     454              :  * determined by @p type.
     455              :  *
     456              :  * For 7, 8, 16 and 24-bit CRCs, the relevant @p seed and @p poly values should
     457              :  * be passed in via the least-significant byte(s).
     458              :  *
     459              :  * Similarly, for 7, 8, 16 and 24-bit CRCs, the relevant result is stored in the
     460              :  * least-significant byte(s) of the returned value.
     461              :  *
     462              :  * @param type CRC algorithm to use.
     463              :  * @param src Input bytes for the computation
     464              :  * @param len Length of the input in bytes
     465              :  * @param seed Seed or existing CRC value to update
     466              :  * @param poly The polynomial to use omitting the leading coefficient
     467              :  * @param reflect Should we use reflected/reversed values or not
     468              :  * @param first Whether this is the first packet in the stream.
     469              :  * @param last Whether this is the last packet in the stream.
     470              :  * @return uint32_t the computed CRC value
     471              :  */
     472            1 : static inline uint32_t crc_by_type(enum crc_type type, const uint8_t *src, size_t len,
     473              :                                    uint32_t seed, uint32_t poly, bool reflect, bool first,
     474              :                                    bool last)
     475              : {
     476              :         switch (type) {
     477              :         case CRC4:
     478              :                 return crc4(src, len, poly, seed, reflect);
     479              :         case CRC4_TI:
     480              :                 return crc4_ti(seed, src, len);
     481              :         case CRC7_BE:
     482              :                 return crc7_be(seed, src, len);
     483              :         case CRC8:
     484              :                 return crc8(src, len, poly, seed, reflect);
     485              :         case CRC8_CCITT:
     486              :                 return crc8_ccitt(seed, src, len);
     487              :         case CRC8_ROHC:
     488              :                 return crc8_rohc(seed, src, len);
     489              :         case CRC16:
     490              :                 if (reflect) {
     491              :                         return crc16_reflect(poly, seed, src, len);
     492              :                 } else {
     493              :                         return crc16(poly, seed, src, len);
     494              :                 }
     495              :         case CRC16_ANSI:
     496              :                 return crc16_ansi(src, len);
     497              :         case CRC16_CCITT:
     498              :                 return crc16_ccitt(seed, src, len);
     499              :         case CRC16_ITU_T:
     500              :                 return crc16_itu_t(seed, src, len);
     501              :         case CRC24_PGP: {
     502              :                 uint32_t crc = crc24_pgp_update(seed, src, len);
     503              : 
     504              :                 if (last) {
     505              :                         crc &= CRC24_FINAL_VALUE_MASK;
     506              :                 }
     507              :                 return crc;
     508              :         }
     509              :         case CRC32_C:
     510              :                 return crc32_c(seed, src, len, first, last);
     511              :         case CRC32_IEEE:
     512              :                 return crc32_ieee_update(seed, src, len);
     513              :         case CRC32_K_4_2:
     514              :                 return crc32_k_4_2_update(seed, src, len);
     515              :         default:
     516              :                 break;
     517              :         }
     518              : 
     519              :         __ASSERT_NO_MSG(false);
     520              :         return -1;
     521              : }
     522              : 
     523              : /**
     524              :  * @}
     525              :  */
     526              : 
     527              : #ifdef __cplusplus
     528              : }
     529              : #endif
     530              : 
     531              : #endif
        

Generated by: LCOV version 2.0-1