lib: crc: Add OpenPGP CRC-24
Implementation is based on the section 6.1 of the RFC 4880. Signed-off-by: Adrien Ricciardi <aricciardi@baylibre.com>
This commit is contained in:
parent
62fa3f729c
commit
863f6affef
4 changed files with 74 additions and 2 deletions
|
@ -30,6 +30,14 @@ extern "C" {
|
|||
*/
|
||||
#define CRC8_CCITT_INITIAL_VALUE 0xFF
|
||||
|
||||
/* Initial value expected to be used at the beginning of the OpenPGP CRC-24 computation. */
|
||||
#define CRC24_PGP_INITIAL_VALUE 0x00B704CEU
|
||||
/*
|
||||
* The CRC-24 value is stored on a 32-bit value, only the 3 least significant bytes
|
||||
* are meaningful. Use the following mask to only keep the CRC-24 value.
|
||||
*/
|
||||
#define CRC24_FINAL_VALUE_MASK 0x00FFFFFFU
|
||||
|
||||
/**
|
||||
* @defgroup checksum Checksum
|
||||
* @ingroup os_services
|
||||
|
@ -56,6 +64,7 @@ enum crc_type {
|
|||
CRC16_ANSI, /**< Use @ref crc16_ansi */
|
||||
CRC16_CCITT, /**< Use @ref crc16_ccitt */
|
||||
CRC16_ITU_T, /**< Use @ref crc16_itu_t */
|
||||
CRC24_PGP, /**< Use @ref crc24_pgp */
|
||||
CRC32_C, /**< Use @ref crc32_c */
|
||||
CRC32_IEEE, /**< Use @ref crc32_ieee */
|
||||
};
|
||||
|
@ -315,16 +324,39 @@ uint8_t crc4_ti(uint8_t seed, const uint8_t *src, size_t len);
|
|||
uint8_t crc4(const uint8_t *src, size_t len, uint8_t polynomial, uint8_t initial_value,
|
||||
bool reversed);
|
||||
|
||||
/**
|
||||
* @brief Generate an OpenPGP CRC-24 checksum as defined in RFC 4880 section 6.1.
|
||||
*
|
||||
* @param data A pointer to the data on which the CRC will be calculated.
|
||||
* @param len Data length in bytes.
|
||||
*
|
||||
* @return The CRC-24 value.
|
||||
*/
|
||||
uint32_t crc24_pgp(const uint8_t *data, size_t len);
|
||||
|
||||
/**
|
||||
* @brief Update an OpenPGP CRC-24 checksum.
|
||||
*
|
||||
* @param crc The CRC-24 checksum that needs to be updated. The full 32-bit value of the CRC needs
|
||||
* to be used between calls, do not mask the value to keep only the last 24 bits.
|
||||
* @param data A pointer to the data on which the CRC will be calculated.
|
||||
* @param len Data length in bytes.
|
||||
*
|
||||
* @return The CRC-24 value. When the last buffer of data has been processed, mask the value
|
||||
* with CRC24_FINAL_VALUE_MASK to keep only the meaningful 24 bits of the CRC result.
|
||||
*/
|
||||
uint32_t crc24_pgp_update(uint32_t crc, const uint8_t *data, size_t len);
|
||||
|
||||
/**
|
||||
* @brief Compute a CRC checksum, in a generic way.
|
||||
*
|
||||
* This is a dispatch function that calls the individual CRC routine
|
||||
* determined by @p type.
|
||||
*
|
||||
* For 7, 8, and 16-bit CRCs, the relevant @p seed and @p poly values should
|
||||
* For 7, 8, 16 and 24-bit CRCs, the relevant @p seed and @p poly values should
|
||||
* be passed in via the least-significant byte(s).
|
||||
*
|
||||
* Similarly, for 7, 8, and 16-bit CRCs, the relevant result is stored in the
|
||||
* Similarly, for 7, 8, 16 and 24-bit CRCs, the relevant result is stored in the
|
||||
* least-significant byte(s) of the returned value.
|
||||
*
|
||||
* @param type CRC algorithm to use.
|
||||
|
@ -364,6 +396,13 @@ static inline uint32_t crc_by_type(enum crc_type type, const uint8_t *src, size_
|
|||
return crc16_ccitt(seed, src, len);
|
||||
case CRC16_ITU_T:
|
||||
return crc16_itu_t(seed, src, len);
|
||||
case CRC24_PGP: {
|
||||
uint32_t crc = crc24_pgp_update(seed, src, len);
|
||||
|
||||
if (last)
|
||||
crc &= CRC24_FINAL_VALUE_MASK;
|
||||
return crc;
|
||||
}
|
||||
case CRC32_C:
|
||||
return crc32_c(seed, src, len, first, last);
|
||||
case CRC32_IEEE:
|
||||
|
|
|
@ -3,6 +3,7 @@
|
|||
zephyr_sources_ifdef(CONFIG_CRC
|
||||
crc32c_sw.c
|
||||
crc32_sw.c
|
||||
crc24_sw.c
|
||||
crc16_sw.c
|
||||
crc8_sw.c
|
||||
crc7_sw.c
|
||||
|
|
31
lib/crc/crc24_sw.c
Normal file
31
lib/crc/crc24_sw.c
Normal file
|
@ -0,0 +1,31 @@
|
|||
/*
|
||||
* Copyright (C) 2024 BayLibre.
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
|
||||
#include <zephyr/sys/crc.h>
|
||||
|
||||
#define CRC24_PGP_POLY 0x01864cfbU
|
||||
|
||||
uint32_t crc24_pgp(const uint8_t *data, size_t len)
|
||||
{
|
||||
return crc24_pgp_update(CRC24_PGP_INITIAL_VALUE, data, len) & CRC24_FINAL_VALUE_MASK;
|
||||
}
|
||||
|
||||
/* CRC-24 implementation from the section 6.1 of the RFC 4880 */
|
||||
uint32_t crc24_pgp_update(uint32_t crc, const uint8_t *data, size_t len)
|
||||
{
|
||||
int i;
|
||||
|
||||
while (len--) {
|
||||
crc ^= (*data++) << 16;
|
||||
for (i = 0; i < 8; i++) {
|
||||
crc <<= 1;
|
||||
if (crc & 0x01000000)
|
||||
crc ^= CRC24_PGP_POLY;
|
||||
}
|
||||
}
|
||||
|
||||
return crc;
|
||||
}
|
|
@ -28,6 +28,7 @@ static const char *const crc_types[] = {
|
|||
[CRC16_ANSI] = "16_ansi",
|
||||
[CRC16_CCITT] = "16_ccitt",
|
||||
[CRC16_ITU_T] = "16_itu_t",
|
||||
[CRC24_PGP] = "24_pgp",
|
||||
[CRC32_C] = "32_c",
|
||||
[CRC32_IEEE] = "32_ieee",
|
||||
};
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue