.. _program_listing_file_libspookyaction_include_desfire_keys.hpp: Program Listing for File keys.hpp ================================= |exhale_lsh| :ref:`Return to documentation for file ` (``libspookyaction/include/desfire/keys.hpp``) .. |exhale_lsh| unicode:: U+021B0 .. UPWARDS ARROW WITH TIP LEFTWARDS .. code-block:: cpp // // Created by spak on 11/24/22. // #ifndef DESFIRE_KEYS_HPP #define DESFIRE_KEYS_HPP #include #include #include #include namespace desfire { using mlab::bin_data; struct random_oracle { using fn_t = void (*)(void *, std::size_t); fn_t fn = nullptr; explicit random_oracle(fn_t fn_) : fn{fn_} {} void operator()(void *ptr, std::size_t len) const { fn(ptr, len); } }; template struct key { static constexpr cipher_type cipher = Cipher;// { public: using mlab::any_of::any_of; any_key() = default; template any_key(key obj); any_key(any_key const &other); any_key &operator=(any_key const &other); any_key(any_key &&other) noexcept = default; any_key &operator=(any_key &&other) noexcept = default; explicit any_key(cipher_type cipher); any_key(cipher_type cipher, mlab::range k, std::uint8_t key_no = 0); any_key(cipher_type cipher, mlab::range k, std::uint8_t key_no, std::uint8_t v); any_key(cipher_type cipher, random_oracle rng, std::uint8_t key_no = 0); any_key(cipher_type cipher, random_oracle rng, std::uint8_t key_no, std::uint8_t v); [[nodiscard]] std::uint8_t key_number() const; [[nodiscard]] std::uint8_t version() const; [[nodiscard]] mlab::range body() const; void set_key_number(std::uint8_t v); void set_version(std::uint8_t v); void set_body(mlab::range k); void randomize(random_oracle rng); [[nodiscard]] any_key with_key_number(std::uint8_t key_no) const; [[nodiscard]] std::size_t size() const; [[nodiscard]] bool parity_bits_are_version() const; [[nodiscard]] bin_data get_packed_key_body() const; [[nodiscard]] bin_data xored_with(any_key const &key_to_xor_with) const; [[nodiscard]] bool operator==(any_key const &other) const; [[nodiscard]] bool operator!=(any_key const &other) const; }; struct key_tag {}; template using key_body = mlab::tagged_array; template class key_storage; template class key_storage { public: static constexpr std::size_t size = KeyLength; using key_body_t = key_body; [[nodiscard]] constexpr mlab::range as_range() const; key_storage() = default; inline explicit key_storage(random_oracle rng); key_storage(random_oracle rng, std::uint8_t v); constexpr explicit key_storage(key_body_t k); constexpr key_storage(key_body_t k, std::uint8_t v); [[nodiscard]] constexpr std::uint8_t version() const; inline void set_version(std::uint8_t v); [[nodiscard]] constexpr key_body_t const &body() const; inline void set_body(key_body_t k); void randomize(random_oracle rng); protected: key_body_t _body{}; }; template class key_storage : private key_storage { public: using key_body_t = typename key_storage::key_body_t; using key_storage::size; using key_storage::as_range; constexpr key_storage() = default; explicit key_storage(random_oracle rng, std::uint8_t v = 0); constexpr explicit key_storage(key_body_t k, std::uint8_t v = 0); [[nodiscard]] constexpr std::uint8_t version() const; inline void set_version(std::uint8_t v); void randomize(random_oracle rng); using key_storage::body; using key_storage::set_body; private: std::uint8_t _version{}; }; template class key_base : public key_storage { public: using storage = key_storage; static constexpr bool parity_bits_are_version = ParityBitsAreVersion; using typename storage::key_body_t; using storage::as_range; using storage::body; using storage::randomize; using storage::set_body; using storage::set_version; using storage::size; using storage::version; constexpr key_base() = default; explicit key_base(random_oracle rng); key_base(std::uint8_t key_no, random_oracle rng); constexpr key_base(std::uint8_t key_no, key_body_t k); key_base(std::uint8_t key_no, random_oracle rng, std::uint8_t v); constexpr key_base(std::uint8_t key_no, key_body_t k, std::uint8_t v); [[nodiscard]] CRTPSubclass with_key_number(std::uint8_t key_no) const; [[nodiscard]] constexpr std::uint8_t key_number() const; inline void set_key_number(std::uint8_t key_no); [[nodiscard]] inline bool operator==(key_base const &other) const; [[nodiscard]] inline bool operator!=(key_base const &other) const; private: std::uint8_t _key_no{0}; }; template <> struct key : public key_base<8, true, key> { using key_base = key_base<8, true, key>; static constexpr cipher_type cipher = cipher_type::des; using key_base::body; using key_base::key_base; using key_base::key_number; using key_base::randomize; using key_base::set_body; using key_base::set_key_number; using key_base::set_version; using key_base::size; using key_base::version; using key_base::with_key_number; }; template <> struct key : public key_base<16, true, key> { using key_base = key_base<16, true, key>; static constexpr cipher_type cipher = cipher_type::des3_2k; using key_base::body; using key_base::key_base; using key_base::key_number; using key_base::randomize; using key_base::set_body; using key_base::set_key_number; using key_base::set_version; using key_base::size; using key_base::version; using key_base::with_key_number; }; template <> struct key : public key_base<24, true, key> { using key_base = key_base<24, true, key>; static constexpr cipher_type cipher = cipher_type::des3_3k; using key_base::body; using key_base::key_base; using key_base::key_number; using key_base::randomize; using key_base::set_body; using key_base::set_key_number; using key_base::set_version; using key_base::size; using key_base::version; using key_base::with_key_number; }; template <> struct key : public key_base<16, false, key> { using key_base = key_base<16, false, key>; static constexpr cipher_type cipher = cipher_type::aes128; using key_base::body; using key_base::key_base; using key_base::key_number; using key_base::randomize; using key_base::set_body; using key_base::set_key_number; using key_base::set_version; using key_base::size; using key_base::version; using key_base::with_key_number; }; }// namespace desfire namespace mlab { #ifndef DOXYGEN_SHOULD_SKIP_THIS bin_data &operator<<(bin_data &bd, desfire::any_key const &k); #endif }// namespace mlab namespace desfire { template constexpr key_storage::key_storage(key_body_t k, std::uint8_t v) : key_storage{k}, _version{v} {} template key_storage::key_storage(random_oracle rng, std::uint8_t v) : key_storage{rng}, _version{v} {} template constexpr std::uint8_t key_storage::version() const { return _version; } template void key_storage::set_version(std::uint8_t v) { _version = v; } template void key_storage::randomize(random_oracle rng) { rng(key_storage::_body.data(), key_storage::_body.size()); } template constexpr mlab::range key_storage::as_range() const { return mlab::make_range(_body); } template constexpr key_storage::key_storage(key_body_t k) : _body{k} {} template key_storage::key_storage(random_oracle rng) : key_storage{} { rng(_body.data(), _body.size()); } template key_storage::key_storage(random_oracle rng, std::uint8_t v) : key_storage{} { rng(_body.data(), _body.size()); set_version(v); } template constexpr key_storage::key_storage(key_body_t k, std::uint8_t v) : _body{k} { set_version(v); } template constexpr std::uint8_t key_storage::version() const { return get_key_version(_body); } template void key_storage::set_version(std::uint8_t v) { set_key_version(_body, v); } template void key_storage::randomize(random_oracle rng) { const auto v = version(); rng(_body.data(), _body.size()); set_version(v); } template constexpr typename key_storage::key_body_t const &key_storage::body() const { return _body; } template void key_storage::set_body(key_body_t k) { _body = k; } template constexpr key_base::key_base(std::uint8_t key_no, key_body_t k_) : storage{k_}, _key_no{key_no} {} template constexpr key_base::key_base(std::uint8_t key_no, key_body_t k_, std::uint8_t v_) : storage{k_, v_}, _key_no{key_no} {} template key_base::key_base(random_oracle rng) : storage{rng}, _key_no{0} {} template key_base::key_base(std::uint8_t key_no, random_oracle rng) : storage{rng}, _key_no{key_no} {} template key_base::key_base(std::uint8_t key_no, random_oracle rng, std::uint8_t v) : storage{rng, v}, _key_no{key_no} {} template CRTPSubclass key_base::with_key_number(std::uint8_t key_no) const { return CRTPSubclass{key_no, body(), version()}; } template constexpr std::uint8_t key_base::key_number() const { return _key_no; } template void key_base::set_key_number(std::uint8_t key_no) { _key_no = key_no; } template bool key_base::operator==(key_base const &other) const { return key_number() == other.key_number() and version() == other.version() and body() == other.body(); } template bool key_base::operator!=(key_base const &other) const { return key_number() != other.key_number() or version() != other.version() or body() != other.body(); } template any_key::any_key(key obj) : mlab::any_of{std::move(obj)} {} }// namespace desfire #endif//DESFIRE_KEYS_HPP