Program Listing for File protocol.hpp
↰ Return to documentation for file (libspookyaction/include/desfire/protocol.hpp
)
//
// Created by Pietro Saccardi on 02/01/2021.
//
#ifndef DESFIRE_PROTOCOL_HPP
#define DESFIRE_PROTOCOL_HPP
#include <desfire/bits.hpp>
#include <desfire/crypto.hpp>
#include <desfire/log.h>
#include <memory>
#include <mlab/bin_data.hpp>
namespace desfire {
struct block_tag {};
class protocol {
public:
virtual void prepare_tx(bin_data &data, std::size_t offset, comm_mode mode) = 0;
virtual bool confirm_rx(bin_data &data, comm_mode mode) = 0;
virtual void init_session(bin_data const &random_data) = 0;
[[nodiscard]] virtual bool is_legacy() const = 0;
virtual ~protocol() = default;
};
class protocol_dummy final : public protocol {
public:
inline void prepare_tx(bin_data &, std::size_t, comm_mode mode) override;
inline bool confirm_rx(bin_data &, comm_mode mode) override;
inline void init_session(bin_data const &) override;
[[nodiscard]] bool is_legacy() const override;
};
class protocol_legacy final : public protocol {
public:
static constexpr std::size_t block_size = 8;
static constexpr std::size_t mac_size = 4;
static constexpr std::size_t crc_size = 2;
using block_t = mlab::tagged_array<block_tag, block_size>;
using mac_t = mlab::tagged_array<mac_tag, mac_size>;
explicit protocol_legacy(std::unique_ptr<crypto> crypto);
void prepare_tx(bin_data &data, std::size_t offset, comm_mode mode) override;
bool confirm_rx(bin_data &data, comm_mode mode) override;
void init_session(bin_data const &random_data) override;
[[nodiscard]] bool is_legacy() const override;
private:
[[nodiscard]] block_t &get_zeroed_iv();
[[nodiscard]] crypto &crypto_provider();
mac_t compute_mac(range<bin_data::const_iterator> data);
static bool drop_padding_verify_crc(bin_data &d);
block_t _iv;
std::unique_ptr<crypto> _crypto;
};
class protocol_default final : public protocol {
public:
static constexpr std::size_t mac_size = 8;
static constexpr std::size_t crc_size = 4;
explicit protocol_default(std::unique_ptr<crypto_with_cmac> crypto);
void prepare_tx(bin_data &data, std::size_t offset, comm_mode mode) override;
bool confirm_rx(bin_data &data, comm_mode mode) override;
void init_session(bin_data const &random_data) override;
[[nodiscard]] bool is_legacy() const override;
private:
[[nodiscard]] crypto_with_cmac &crypto_provider();
[[nodiscard]] range<std::uint8_t *> iv();
bool drop_padding_verify_crc(bin_data &d, std::uint8_t status);
std::unique_ptr<std::uint8_t[]> _iv;
std::unique_ptr<crypto_with_cmac> _crypto;
};
}// namespace desfire
namespace desfire {
void protocol_dummy::prepare_tx(bin_data &, std::size_t, comm_mode mode) {
if (mode != comm_mode::plain) {
DESFIRE_LOGE("Dummy protocol supports only plain comm mode.");
}
}
bool protocol_dummy::confirm_rx(bin_data &, comm_mode mode) {
if (mode != comm_mode::plain) {
DESFIRE_LOGE("Dummy protocol supports only plain comm mode.");
return false;
}
return true;
}
void protocol_dummy::init_session(bin_data const &) {}
}// namespace desfire
#endif//DESFIRE_PROTOCOL_HPP