Skip to content

Commit

Permalink
lib: crc: Add OpenPGP CRC-24
Browse files Browse the repository at this point in the history
Implementation is based on the section 6.1 of the RFC 4880.

Signed-off-by: Adrien Ricciardi <[email protected]>
  • Loading branch information
RICCIARDI-Adrien authored and carlescufi committed May 29, 2024
1 parent 62fa3f7 commit 863f6af
Show file tree
Hide file tree
Showing 4 changed files with 74 additions and 2 deletions.
43 changes: 41 additions & 2 deletions include/zephyr/sys/crc.h
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand All @@ -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 */
};
Expand Down Expand Up @@ -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.
Expand Down Expand Up @@ -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:
Expand Down
1 change: 1 addition & 0 deletions lib/crc/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
31 changes: 31 additions & 0 deletions lib/crc/crc24_sw.c
Original file line number Diff line number Diff line change
@@ -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;
}
1 change: 1 addition & 0 deletions lib/crc/crc_shell.c
Original file line number Diff line number Diff line change
Expand Up @@ -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",
};
Expand Down

0 comments on commit 863f6af

Please sign in to comment.