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:
Adrien Ricciardi 2024-05-14 19:07:00 +02:00 committed by Carles Cufí
commit 863f6affef
4 changed files with 74 additions and 2 deletions

View file

@ -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:

View file

@ -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
View 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;
}

View file

@ -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",
};