#ifndef CHAOS_PADDING_PADDERPKCS7_HPP #define CHAOS_PADDING_PADDERPKCS7_HPP #include #include #include #include #include "Padding/Padder.hpp" #include "Service/Branchless.hpp" #include "Service/ChaosException.hpp" namespace Chaos::Padding { class PadderPkcs7 : public Padder { public: template static void Pad(OutputIt begin, OutputIt end) { auto dist = std::distance(begin, end); if (dist > 0 && dist <= std::numeric_limits::max()) { for (OutputIt it = begin; it != end; ++it) { *it = static_cast(dist); } } else { throw Service::ChaosException("PadderPkcs7::Pad(): invalid range"); } } struct ComputeUnpadResult { bool IsOkay_; uint8_t PadSize_; }; template static ComputeUnpadResult ComputeUnpad(InputIt begin, InputIt end) noexcept { if (begin == end) { return { .IsOkay_ = false, .PadSize_ = 0 }; } const uint8_t padSize = *std::prev(end); uint8_t isOkay = ~Branchless::IsZero(padSize); size_t suffixSize = 0; InputIt it = end; while (it != begin && suffixSize < std::numeric_limits::max()) { --it; ++suffixSize; isOkay &= (Branchless::Eq(*it, padSize) | Branchless::Gt(suffixSize, padSize)); } isOkay &= Branchless::Ge(suffixSize, padSize); return { .IsOkay_ = static_cast(isOkay), .PadSize_ = Branchless::Sel(isOkay, padSize, 0) }; } private: using Branchless = Service::Branchless; }; } // namespace Chaos::Padding #endif // CHAOS_PADDING_PADDERPKCS7_HPP