diff options
author | Daniel Baumann <daniel.baumann@progress-linux.org> | 2024-04-07 17:32:43 +0000 |
---|---|---|
committer | Daniel Baumann <daniel.baumann@progress-linux.org> | 2024-04-07 17:32:43 +0000 |
commit | 6bf0a5cb5034a7e684dcc3500e841785237ce2dd (patch) | |
tree | a68f146d7fa01f0134297619fbe7e33db084e0aa /comm/third_party/botan/src/lib/mac/gmac/gmac.cpp | |
parent | Initial commit. (diff) | |
download | thunderbird-6bf0a5cb5034a7e684dcc3500e841785237ce2dd.tar.xz thunderbird-6bf0a5cb5034a7e684dcc3500e841785237ce2dd.zip |
Adding upstream version 1:115.7.0.upstream/1%115.7.0upstream
Signed-off-by: Daniel Baumann <daniel.baumann@progress-linux.org>
Diffstat (limited to 'comm/third_party/botan/src/lib/mac/gmac/gmac.cpp')
-rw-r--r-- | comm/third_party/botan/src/lib/mac/gmac/gmac.cpp | 134 |
1 files changed, 134 insertions, 0 deletions
diff --git a/comm/third_party/botan/src/lib/mac/gmac/gmac.cpp b/comm/third_party/botan/src/lib/mac/gmac/gmac.cpp new file mode 100644 index 0000000000..6b162857f3 --- /dev/null +++ b/comm/third_party/botan/src/lib/mac/gmac/gmac.cpp @@ -0,0 +1,134 @@ +/* + * GMAC + * (C) 2016 Matthias Gierlings, René Korthaus + * (C) 2017 Jack Lloyd + * + * Botan is released under the Simplified BSD License (see license.txt) + */ + +#include <botan/gmac.h> +#include <botan/ghash.h> +#include <botan/exceptn.h> +#include <botan/block_cipher.h> + +namespace Botan { + +GMAC::GMAC(BlockCipher* cipher) : + m_cipher(cipher), + m_ghash(new GHASH), + m_aad_buf(GCM_BS), + m_aad_buf_pos(0), + m_initialized(false) + { + } + +void GMAC::clear() + { + m_cipher->clear(); + m_ghash->clear(); + zeroise(m_aad_buf); + m_aad_buf_pos = 0; + m_initialized = false; + } + +GMAC::~GMAC() { /* for unique_ptr */ } + +Key_Length_Specification GMAC::key_spec() const + { + return m_cipher->key_spec(); + } + +std::string GMAC::name() const + { + return "GMAC(" + m_cipher->name() + ")"; + } + +size_t GMAC::output_length() const + { + return GCM_BS; + } + +void GMAC::add_data(const uint8_t input[], size_t size) + { + if(m_aad_buf_pos > 0) + { + const size_t taking = std::min(GCM_BS - m_aad_buf_pos, size); + copy_mem(&m_aad_buf[m_aad_buf_pos], input, taking); + m_aad_buf_pos += taking; + input += taking; + size -= taking; + + if(m_aad_buf_pos == GCM_BS) + { + m_ghash->update_associated_data(m_aad_buf.data(), GCM_BS); + m_aad_buf_pos = 0; + } + } + + const size_t left_over = size % GCM_BS; + const size_t full_blocks = size - left_over; + m_ghash->update_associated_data(input, full_blocks); + input += full_blocks; + + if(left_over > 0) + { + copy_mem(&m_aad_buf[m_aad_buf_pos], input, left_over); + m_aad_buf_pos += left_over; + } + } + +void GMAC::key_schedule(const uint8_t key[], size_t size) + { + clear(); + m_cipher->set_key(key, size); + + secure_vector<uint8_t> H(GCM_BS); + m_cipher->encrypt(H); + m_ghash->set_key(H); + } + +void GMAC::start_msg(const uint8_t nonce[], size_t nonce_len) + { + secure_vector<uint8_t> y0(GCM_BS); + + if(nonce_len == 12) + { + copy_mem(y0.data(), nonce, nonce_len); + y0[GCM_BS - 1] = 1; + } + else + { + m_ghash->ghash_update(y0, nonce, nonce_len); + m_ghash->add_final_block(y0, 0, nonce_len); + } + + secure_vector<uint8_t> m_enc_y0(GCM_BS); + m_cipher->encrypt(y0.data(), m_enc_y0.data()); + m_ghash->start(m_enc_y0.data(), m_enc_y0.size()); + m_initialized = true; + } + +void GMAC::final_result(uint8_t mac[]) + { + // This ensures the GMAC computation has been initialized with a fresh + // nonce. The aim of this check is to prevent developers from re-using + // nonces (and potential nonce-reuse attacks). + if(m_initialized == false) + throw Invalid_State("GMAC was not used with a fresh nonce"); + + // process the rest of the aad buffer. Even if it is a partial block only + // ghash_update will process it properly. + if(m_aad_buf_pos > 0) + { + m_ghash->update_associated_data(m_aad_buf.data(), m_aad_buf_pos); + } + + m_ghash->final(mac, output_length()); + clear(); + } + +MessageAuthenticationCode* GMAC::clone() const + { + return new GMAC(m_cipher->clone()); + } +} |