From 3eeb35e78738bdb00818ef018f60d2364b0b3705 Mon Sep 17 00:00:00 2001 From: devgianlu Date: Wed, 25 Dec 2024 23:42:49 +0100 Subject: [PATCH] LibCrypto: Implement `RSA_PSS_EMSA` with OpenSSL --- Libraries/LibCrypto/PK/RSA.cpp | 8 +++++ Libraries/LibCrypto/PK/RSA.h | 24 +++++++++++++++ Tests/LibCrypto/CMakeLists.txt | 1 + Tests/LibCrypto/TestPSS.cpp | 53 ++++++++++++++++++++++++++++++++++ 4 files changed, 86 insertions(+) create mode 100644 Tests/LibCrypto/TestPSS.cpp diff --git a/Libraries/LibCrypto/PK/RSA.cpp b/Libraries/LibCrypto/PK/RSA.cpp index 8551acadbc5..bca6d183536 100644 --- a/Libraries/LibCrypto/PK/RSA.cpp +++ b/Libraries/LibCrypto/PK/RSA.cpp @@ -454,4 +454,12 @@ ErrorOr RSA_OAEP_EME::configure(OpenSSL_PKEY_CTX& ctx) return {}; } +ErrorOr RSA_PSS_EMSA::configure(OpenSSL_PKEY_CTX& ctx) +{ + OPENSSL_TRY(EVP_PKEY_CTX_set_rsa_padding(ctx.ptr(), RSA_PKCS1_PSS_PADDING)); + OPENSSL_TRY(EVP_PKEY_CTX_set_rsa_mgf1_md(ctx.ptr(), TRY(hash_kind_to_hash_type(m_hash_kind)))); + OPENSSL_TRY(EVP_PKEY_CTX_set_rsa_pss_saltlen(ctx.ptr(), m_salt_length.value_or(RSA_PSS_SALTLEN_MAX))); + return {}; +} + } diff --git a/Libraries/LibCrypto/PK/RSA.h b/Libraries/LibCrypto/PK/RSA.h index 53fa3e17e43..1d3a074c756 100644 --- a/Libraries/LibCrypto/PK/RSA.h +++ b/Libraries/LibCrypto/PK/RSA.h @@ -344,4 +344,28 @@ private: Optional m_label {}; }; +class RSA_PSS_EMSA : public RSA_EMSA { +public: + template + RSA_PSS_EMSA(Hash::HashKind hash_kind, Args... args) + : RSA_EMSA(hash_kind, args...) + { + } + + ~RSA_PSS_EMSA() = default; + + virtual ByteString class_name() const override + { + return "RSA_PSS-EMSA"; + } + + void set_salt_length(int value) { m_salt_length = value; } + +protected: + ErrorOr configure(OpenSSL_PKEY_CTX& ctx) override; + +private: + Optional m_salt_length; +}; + } diff --git a/Tests/LibCrypto/CMakeLists.txt b/Tests/LibCrypto/CMakeLists.txt index 850ff405600..027aca79949 100644 --- a/Tests/LibCrypto/CMakeLists.txt +++ b/Tests/LibCrypto/CMakeLists.txt @@ -15,6 +15,7 @@ set(TEST_SOURCES TestOAEP.cpp TestPBKDF2.cpp TestPoly1305.cpp + TestPSS.cpp TestRSA.cpp ) diff --git a/Tests/LibCrypto/TestPSS.cpp b/Tests/LibCrypto/TestPSS.cpp new file mode 100644 index 00000000000..2f9f8793719 --- /dev/null +++ b/Tests/LibCrypto/TestPSS.cpp @@ -0,0 +1,53 @@ +/* + * Copyright (c) 2025, Altomani Gianluca + * + * SPDX-License-Identifier: BSD-2-Clause + */ + +#include +#include +#include + +TEST_CASE(test_pss) +{ + auto msg = "WellHelloFriendsWellHelloFriendsWellHelloFriendsWellHelloFriends"sv.bytes(); + + auto keypair = TRY_OR_FAIL(Crypto::PK::RSA::generate_key_pair(1024)); + auto rsa = Crypto::PK::RSA_PSS_EMSA(Crypto::Hash::HashKind::SHA1, keypair); + rsa.set_salt_length(48); + + auto sig = TRY_OR_FAIL(rsa.sign(msg)); + auto ok = TRY_OR_FAIL(rsa.verify(msg, sig)); + EXPECT(ok); +} + +TEST_CASE(test_pss_tampered_message) +{ + auto msg = "WellHelloFriendsWellHelloFriendsWellHelloFriendsWellHelloFriends"sv.bytes(); + auto msg_tampered = "WellHell0FriendsWellHelloFriendsWellHelloFriendsWellHelloFriends"sv.bytes(); + + auto keypair = TRY_OR_FAIL(Crypto::PK::RSA::generate_key_pair(1024)); + auto rsa = Crypto::PK::RSA_PSS_EMSA(Crypto::Hash::HashKind::SHA1, keypair); + rsa.set_salt_length(48); + + auto sig = TRY_OR_FAIL(rsa.sign(msg)); + auto ok = TRY_OR_FAIL(rsa.verify(msg_tampered, sig)); + EXPECT(!ok); +} + +TEST_CASE(test_pss_tampered_signature) +{ + auto msg = "WellHelloFriendsWellHelloFriendsWellHelloFriendsWellHelloFriends"sv.bytes(); + + auto keypair = TRY_OR_FAIL(Crypto::PK::RSA::generate_key_pair(1024)); + auto rsa = Crypto::PK::RSA_PSS_EMSA(Crypto::Hash::HashKind::SHA1, keypair); + rsa.set_salt_length(48); + + auto sig = TRY_OR_FAIL(rsa.sign(msg)); + + // Tamper with the signature + sig[8]++; + + auto ok = TRY_OR_FAIL(rsa.verify(msg, sig)); + EXPECT(!ok); +}