Coverage Report

Created: 2026-02-07 06:16

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/botan/src/lib/mac/gmac/gmac.cpp
Line
Count
Source
1
/*
2
 * GMAC
3
 * (C) 2016 Matthias Gierlings, René Korthaus
4
 * (C) 2017 Jack Lloyd
5
 *
6
 * Botan is released under the Simplified BSD License (see license.txt)
7
 */
8
9
#include <botan/internal/gmac.h>
10
11
#include <botan/block_cipher.h>
12
#include <botan/exceptn.h>
13
#include <botan/internal/fmt.h>
14
#include <botan/internal/ghash.h>
15
16
namespace Botan {
17
18
GMAC::GMAC(std::unique_ptr<BlockCipher> cipher) :
19
0
      m_cipher(std::move(cipher)), m_ghash(std::make_unique<GHASH>()), m_H(GCM_BS), m_initialized(false) {}
20
21
0
void GMAC::clear() {
22
0
   m_cipher->clear();
23
0
   m_ghash->clear();
24
0
   zeroise(m_H);
25
0
   m_initialized = false;
26
0
}
27
28
0
GMAC::~GMAC() = default;
29
30
0
Key_Length_Specification GMAC::key_spec() const {
31
0
   return m_cipher->key_spec();
32
0
}
33
34
0
std::string GMAC::name() const {
35
0
   return fmt("GMAC({})", m_cipher->name());
36
0
}
37
38
0
std::string GMAC::provider() const {
39
0
   return m_ghash->provider();
40
0
}
41
42
0
size_t GMAC::output_length() const {
43
0
   return GCM_BS;
44
0
}
45
46
0
void GMAC::add_data(std::span<const uint8_t> input) {
47
0
   m_ghash->update_associated_data(input);
48
0
}
49
50
0
bool GMAC::has_keying_material() const {
51
0
   return m_cipher->has_keying_material();
52
0
}
53
54
0
void GMAC::key_schedule(std::span<const uint8_t> key) {
55
0
   clear();
56
0
   m_cipher->set_key(key);
57
58
0
   m_cipher->encrypt(m_H);
59
0
   m_ghash->set_key(m_H);
60
0
}
61
62
0
void GMAC::start_msg(std::span<const uint8_t> nonce) {
63
0
   std::array<uint8_t, GCM_BS> y0 = {0};
64
65
0
   if(nonce.size() == 12) {
66
0
      copy_mem(y0.data(), nonce.data(), nonce.size());
67
0
      y0[GCM_BS - 1] = 1;
68
0
   } else {
69
0
      m_ghash->nonce_hash(y0, nonce);
70
0
   }
71
72
0
   m_cipher->encrypt(y0.data());
73
0
   m_ghash->start(y0);
74
0
   m_initialized = true;
75
0
}
76
77
0
void GMAC::final_result(std::span<uint8_t> mac) {
78
   // This ensures the GMAC computation has been initialized with a fresh
79
   // nonce. The aim of this check is to prevent developers from re-using
80
   // nonces (and potential nonce-reuse attacks).
81
0
   if(!m_initialized) {
82
0
      throw Invalid_State("GMAC was not used with a fresh nonce");
83
0
   }
84
85
0
   m_ghash->final(mac.first(output_length()));
86
0
   m_ghash->reset_associated_data();
87
0
}
88
89
0
std::unique_ptr<MessageAuthenticationCode> GMAC::new_object() const {
90
0
   return std::make_unique<GMAC>(m_cipher->new_object());
91
0
}
92
}  // namespace Botan