/* * Copyright (c) Atmosphère-NX * * This program is free software; you can redistribute it and/or modify it * under the terms and conditions of the GNU General Public License, * version 2, as published by the Free Software Foundation. * * This program is distributed in the hope it will be useful, but WITHOUT * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for * more details. * * You should have received a copy of the GNU General Public License * along with this program. If not, see . */ #pragma once #include #include #include #include #include namespace ams::crypto::impl { template class GcmModeImpl { NON_COPYABLE(GcmModeImpl); NON_MOVEABLE(GcmModeImpl); public: static constexpr size_t KeySize = BlockCipher::KeySize; static constexpr size_t BlockSize = BlockCipher::BlockSize; static constexpr size_t MacSize = BlockCipher::BlockSize; private: enum State { State_None, State_Initialized, State_ProcessingAad, State_Encrypting, State_Decrypting, State_Done, }; struct Block128 { u64 hi; u64 lo; ALWAYS_INLINE void Clear() { this->hi = 0; this->lo = 0; } }; static_assert(util::is_pod::value); static_assert(sizeof(Block128) == 0x10); union Block { Block128 block_128; u32 block_32[4]; u8 block_8[16]; }; static_assert(util::is_pod::value); static_assert(sizeof(Block) == 0x10); using CipherFunction = void (*)(void *dst_block, const void *src_block, const void *ctx); private: State m_state; const BlockCipher *m_block_cipher; CipherFunction m_cipher_func; u8 m_pad[sizeof(u64)]; Block m_block_x; Block m_block_y; Block m_block_ek; Block m_block_ek0; Block m_block_tmp; size_t m_aad_size; size_t m_msg_size; u32 m_aad_remaining; u32 m_msg_remaining; u32 m_counter; Block m_h_mult_blocks[16]; public: GcmModeImpl() : m_state(State_None) { /* ... */ } ~GcmModeImpl() { ClearMemory(this, sizeof(*this)); } void Initialize(const BlockCipher *block_cipher); void Reset(const void *iv, size_t iv_size); void UpdateAad(const void *aad, size_t aad_size); size_t UpdateEncrypt(void *dst, size_t dst_size, const void *src, size_t src_size); size_t UpdateDecrypt(void *dst, size_t dst_size, const void *src, size_t src_size); void GetMac(void *dst, size_t dst_size); private: static void ProcessBlock(void *dst_block, const void *src_block, const void *ctx) { static_cast(ctx)->EncryptBlock(dst_block, BlockSize, src_block, BlockSize); } void InitializeHashKey(); void ComputeMac(bool encrypt); }; }