Program Listing for File cmac_provider.hpp

Return to documentation for file (libspookyaction/include/desfire/cmac_provider.hpp)

//
// Created by spak on 5/8/21.
//

#ifndef DESFIRE_CRYPTO_CMAC_HPP
#define DESFIRE_CRYPTO_CMAC_HPP

#include <memory>
#include <mlab/bin_data.hpp>

namespace desfire {
    using mlab::bin_data;
    using mlab::range;
    class crypto;

    struct mac_tag {};

    class cmac_keychain {
        std::size_t _block_size;
        std::uint8_t _last_byte_xor;
        std::unique_ptr<std::uint8_t[]> _subkey_pad;
        std::unique_ptr<std::uint8_t[]> _subkey_nopad;

    public:
        static constexpr auto xor_byte_des = desfire::bits::crypto_cmac_xor_byte_des;
        static constexpr auto xor_byte_2k3des = desfire::bits::crypto_cmac_xor_byte_2k3des;
        static constexpr auto xor_byte_3k3des = desfire::bits::crypto_cmac_xor_byte_3k3des;
        static constexpr auto xor_byte_aes = desfire::bits::crypto_cmac_xor_byte_aes;

        inline cmac_keychain(std::size_t block_size, std::uint8_t last_byte_xor);

        [[nodiscard]] inline range<std::uint8_t *> key_pad() const;

        [[nodiscard]] inline range<std::uint8_t *> key_nopad() const;

        [[nodiscard]] inline std::size_t block_size() const;

        [[nodiscard]] inline std::uint8_t last_byte_xor() const;

        static void prepare_subkey(range<std::uint8_t *> subkey, std::uint8_t last_byte_xor);

        void initialize_subkeys(crypto &crypto);

        void prepare_cmac_data(bin_data &data) const;

        void prepare_cmac_data(bin_data &data, std::size_t desired_padded_length) const;
    };

    class cmac_provider {
        cmac_keychain _keychain;
        bin_data _cmac_buffer;

    public:
        using mac_t = mlab::tagged_array<mac_tag, 8>;

        inline cmac_provider(std::size_t block_size, std::uint8_t last_byte_xor);

        [[nodiscard]] inline cmac_keychain const &keychain() const;

        void initialize_subkeys(crypto &crypto);

        mac_t compute_cmac(crypto &crypto, range<std::uint8_t *> iv, range<std::uint8_t const *> data);
    };
}// namespace desfire

namespace desfire {
    cmac_provider::cmac_provider(std::size_t block_size, std::uint8_t last_byte_xor)
        : _keychain{block_size, last_byte_xor} {}

    cmac_keychain::cmac_keychain(std::size_t block_size, std::uint8_t last_byte_xor)
        : _block_size{block_size},
          _last_byte_xor{last_byte_xor},
          _subkey_pad{std::make_unique<std::uint8_t[]>(static_cast<std::size_t>(block_size))},
          _subkey_nopad{std::make_unique<std::uint8_t[]>(static_cast<std::size_t>(block_size))} {}

    std::size_t cmac_keychain::block_size() const {
        return _block_size;
    }

    std::uint8_t cmac_keychain::last_byte_xor() const {
        return _last_byte_xor;
    }

    range<std::uint8_t *> cmac_keychain::key_pad() const {
        return {_subkey_pad.get(), _subkey_pad.get() + block_size()};
    }

    range<std::uint8_t *> cmac_keychain::key_nopad() const {
        return {_subkey_nopad.get(), _subkey_nopad.get() + block_size()};
    }

    cmac_keychain const &cmac_provider::keychain() const {
        return _keychain;
    }

}// namespace desfire
#endif//DESFIRE_CRYPTO_CMAC_HPP