diff --git a/Libraries/LibCrypto/CMakeLists.txt b/Libraries/LibCrypto/CMakeLists.txt index 06248104ac3..5bb84381955 100644 --- a/Libraries/LibCrypto/CMakeLists.txt +++ b/Libraries/LibCrypto/CMakeLists.txt @@ -18,7 +18,6 @@ set(SOURCES BigInt/UnsignedBigInteger.cpp Certificate/Certificate.cpp Checksum/cksum.cpp - Checksum/CRC32.cpp Cipher/AES.cpp Curves/EdwardsCurve.cpp Curves/SECPxxxr1.cpp diff --git a/Libraries/LibCrypto/Checksum/CRC16.h b/Libraries/LibCrypto/Checksum/CRC16.h deleted file mode 100644 index 22112be7ba4..00000000000 --- a/Libraries/LibCrypto/Checksum/CRC16.h +++ /dev/null @@ -1,82 +0,0 @@ -/* - * Copyright (c) 2023, kleines Filmröllchen . - * - * SPDX-License-Identifier: BSD-2-Clause - */ - -#pragma once - -#include -#include -#include -#include - -namespace Crypto::Checksum { - -// A generic 16-bit Cyclic Redundancy Check. -// Just like CRC32, this class receives its polynomial little-endian. -// For example, the polynomial x¹⁶ + x¹² + x⁵ + 1 is represented as 0x8408. -template -class CRC16 : public ChecksumFunction { -public: - static constexpr u16 be_polynomial = bitswap(polynomial); - - // This is a big endian table, while CRC-32 uses a little endian table. - static constexpr auto generate_table() - { - Array data {}; - data[0] = 0; - u16 value = 0x8000; - auto i = 1u; - do { - if ((value & 0x8000) != 0) { - value = be_polynomial ^ (value << 1); - } else { - value = value << 1; - } - - for (auto j = 0u; j < i; ++j) { - data[i + j] = value ^ data[j]; - } - i <<= 1; - } while (i < 256); - - return data; - } - - static constexpr auto table = generate_table(); - - virtual ~CRC16() = default; - - CRC16() = default; - CRC16(ReadonlyBytes data) - { - update(data); - } - - CRC16(u16 initial_state, ReadonlyBytes data) - : m_state(initial_state) - { - update(data); - } - - // FIXME: This implementation is naive and slow. - // Figure out how to adopt the slicing-by-8 algorithm (see CRC32) for 16-bit polynomials. - virtual void update(ReadonlyBytes data) override - { - for (size_t i = 0; i < data.size(); i++) { - size_t table_index = ((m_state >> 8) ^ data.at(i)) & 0xFF; - m_state = (table[table_index] ^ (static_cast(m_state) << 8)) & 0xFFFF; - } - } - - virtual u16 digest() override - { - return m_state; - } - -private: - u16 m_state { 0 }; -}; - -} diff --git a/Libraries/LibCrypto/Checksum/CRC32.cpp b/Libraries/LibCrypto/Checksum/CRC32.cpp deleted file mode 100644 index 87699a3a81d..00000000000 --- a/Libraries/LibCrypto/Checksum/CRC32.cpp +++ /dev/null @@ -1,176 +0,0 @@ -/* - * Copyright (c) 2020-2022, the SerenityOS developers. - * - * SPDX-License-Identifier: BSD-2-Clause - */ - -#include -#include -#include -#include - -#ifdef __ARM_ACLE -# include -#endif - -namespace Crypto::Checksum { - -#if __ARM_ARCH >= 8 && defined(__ARM_FEATURE_CRC32) && defined(__ARM_ACLE) -void CRC32::update(ReadonlyBytes span) -{ - // FIXME: Does this require runtime checking on rpi? - // (Maybe the instruction is present on the rpi4 but not on the rpi3?) - - u8 const* data = span.data(); - size_t size = span.size(); - - while (size > 0 && (reinterpret_cast(data) & 7) != 0) { - m_state = __crc32b(m_state, *data); - ++data; - --size; - } - - auto* data64 = reinterpret_cast(data); - while (size >= 8) { - m_state = __crc32d(m_state, *data64); - ++data64; - size -= 8; - } - - data = reinterpret_cast(data64); - while (size > 0) { - m_state = __crc32b(m_state, *data); - ++data; - --size; - } -} - -// FIXME: On Intel, use _mm_crc32_u8 / _mm_crc32_u64 if available (SSE 4.2). - -#else - -static constexpr size_t ethernet_polynomial = 0xEDB88320; - -# if __BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__ - -// This implements Intel's slicing-by-8 algorithm. Their original paper is no longer on their website, -// but their source code is still available for reference: -// https://sourceforge.net/projects/slicing-by-8/ -static constexpr auto generate_table() -{ - Array, 8> data {}; - - for (u32 i = 0; i < 256; ++i) { - auto value = i; - - for (size_t j = 0; j < 8; ++j) - value = (value >> 1) ^ ((value & 1) * ethernet_polynomial); - - data[0][i] = value; - } - - for (u32 i = 0; i < 256; ++i) { - for (size_t j = 1; j < 8; ++j) - data[j][i] = (data[j - 1][i] >> 8) ^ data[0][data[j - 1][i] & 0xff]; - } - - return data; -} - -static constexpr auto table = generate_table(); - -struct AlignmentData { - ReadonlyBytes misaligned; - ReadonlyBytes aligned; -}; - -static AlignmentData split_bytes_for_alignment(ReadonlyBytes data, size_t alignment) -{ - auto address = reinterpret_cast(data.data()); - auto offset = alignment - address % alignment; - - if (offset == alignment) - return { {}, data }; - - if (data.size() < alignment) - return { data, {} }; - - return { data.trim(offset), data.slice(offset) }; -} - -static constexpr u32 single_byte_crc(u32 crc, u8 byte) -{ - return (crc >> 8) ^ table[0][(crc & 0xff) ^ byte]; -} - -void CRC32::update(ReadonlyBytes data) -{ - // The provided data may not be aligned to a 4-byte boundary, required to reinterpret its address - // into a u32 in the loop below. So we split the bytes into two segments: the misaligned bytes - // (which undergo the standard 1-byte-at-a-time algorithm) and remaining aligned bytes. - auto [misaligned_data, aligned_data] = split_bytes_for_alignment(data, alignof(u32)); - - for (auto byte : misaligned_data) - m_state = single_byte_crc(m_state, byte); - - while (aligned_data.size() >= 8) { - auto const* segment = reinterpret_cast(aligned_data.data()); - auto low = *segment ^ m_state; - auto high = *(++segment); - - m_state = table[0][(high >> 24) & 0xff] - ^ table[1][(high >> 16) & 0xff] - ^ table[2][(high >> 8) & 0xff] - ^ table[3][high & 0xff] - ^ table[4][(low >> 24) & 0xff] - ^ table[5][(low >> 16) & 0xff] - ^ table[6][(low >> 8) & 0xff] - ^ table[7][low & 0xff]; - - aligned_data = aligned_data.slice(8); - } - - for (auto byte : aligned_data) - m_state = single_byte_crc(m_state, byte); -} - -# else - -// FIXME: Implement the slicing-by-8 algorithm for big endian CPUs. -static constexpr auto generate_table() -{ - Array data {}; - for (auto i = 0u; i < data.size(); i++) { - u32 value = i; - - for (auto j = 0; j < 8; j++) { - if (value & 1) { - value = ethernet_polynomial ^ (value >> 1); - } else { - value = value >> 1; - } - } - - data[i] = value; - } - return data; -} - -static constexpr auto table = generate_table(); - -void CRC32::update(ReadonlyBytes data) -{ - for (size_t i = 0; i < data.size(); i++) { - m_state = table[(m_state ^ data.at(i)) & 0xFF] ^ (m_state >> 8); - } -} - -# endif -#endif - -u32 CRC32::digest() -{ - return ~m_state; -} - -} diff --git a/Libraries/LibCrypto/Checksum/CRC32.h b/Libraries/LibCrypto/Checksum/CRC32.h deleted file mode 100644 index 97322f58e7b..00000000000 --- a/Libraries/LibCrypto/Checksum/CRC32.h +++ /dev/null @@ -1,36 +0,0 @@ -/* - * Copyright (c) 2020-2022, the SerenityOS developers. - * - * SPDX-License-Identifier: BSD-2-Clause - */ - -#pragma once - -#include -#include -#include - -namespace Crypto::Checksum { - -class CRC32 : public ChecksumFunction { -public: - CRC32() = default; - CRC32(ReadonlyBytes data) - { - update(data); - } - - CRC32(u32 initial_state, ReadonlyBytes data) - : m_state(initial_state) - { - update(data); - } - - virtual void update(ReadonlyBytes data) override; - virtual u32 digest() override; - -private: - u32 m_state { ~0u }; -}; - -} diff --git a/Libraries/LibCrypto/Checksum/CRC8.h b/Libraries/LibCrypto/Checksum/CRC8.h deleted file mode 100644 index 8850162c97c..00000000000 --- a/Libraries/LibCrypto/Checksum/CRC8.h +++ /dev/null @@ -1,76 +0,0 @@ -/* - * Copyright (c) 2023, kleines Filmröllchen - * - * SPDX-License-Identifier: BSD-2-Clause - */ - -#pragma once - -#include -#include - -namespace Crypto::Checksum { - -// A generic 8-bit Cyclic Redundancy Check. -// Note that as opposed to CRC32, this class operates with MSB first, so the polynomial must not be reversed. -// For example, the polynomial x⁸ + x² + x + 1 is represented as 0x07 and not 0xE0. -template -class CRC8 : public ChecksumFunction { -public: - // This is a big endian table, while CRC-32 uses a little endian table. - static constexpr auto generate_table() - { - Array data {}; - u8 value = 0x80; - auto i = 1u; - do { - if ((value & 0x80) != 0) { - value = polynomial ^ (value << 1); - } else { - value = value << 1; - } - - for (auto j = 0u; j < i; ++j) { - data[i + j] = value ^ data[j]; - } - i <<= 1; - } while (i < 256); - return data; - } - - static constexpr auto table = generate_table(); - - virtual ~CRC8() = default; - - CRC8() = default; - CRC8(ReadonlyBytes data) - { - update(data); - } - - CRC8(u8 initial_state, ReadonlyBytes data) - : m_state(initial_state) - { - update(data); - } - - // FIXME: This implementation is naive and slow. - // Figure out how to adopt the slicing-by-8 algorithm (see CRC32) for 8 bit polynomials. - virtual void update(ReadonlyBytes data) override - { - for (size_t i = 0; i < data.size(); i++) { - size_t table_index = (m_state ^ data.at(i)) & 0xFF; - m_state = (table[table_index] ^ (static_cast(m_state) << 8)) & 0xFF; - } - } - - virtual u8 digest() override - { - return m_state; - } - -private: - u8 m_state { 0 }; -}; - -} diff --git a/Tests/LibCrypto/TestChecksum.cpp b/Tests/LibCrypto/TestChecksum.cpp index 2c5574266b3..7db17ae5201 100644 --- a/Tests/LibCrypto/TestChecksum.cpp +++ b/Tests/LibCrypto/TestChecksum.cpp @@ -4,7 +4,6 @@ * SPDX-License-Identifier: BSD-2-Clause */ -#include #include #include @@ -36,15 +35,3 @@ TEST_CASE(test_cksum_atomic_digest) compare(digest, 0x2D65C7E0); } - -TEST_CASE(test_crc32) -{ - auto do_test = [](ReadonlyBytes input, u32 expected_result) { - auto digest = Crypto::Checksum::CRC32(input).digest(); - EXPECT_EQ(digest, expected_result); - }; - - do_test(""sv.bytes(), 0x0); - do_test("The quick brown fox jumps over the lazy dog"sv.bytes(), 0x414FA339); - do_test("various CRC algorithms input data"sv.bytes(), 0x9BD366AE); -}