LCOV - code coverage report
Current view: top level - zephyr/sys - crc.h Coverage Total Hit
Test: new.info Lines: 84.0 % 25 21
Test Date: 2025-09-05 16:43:28

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

Generated by: LCOV version 2.0-1