Coverage Report

Created: 2026-05-16 06:40

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
size_t GMAC::output_length() const {
39
0
   return GCM_BS;
40
0
}
41
42
0
void GMAC::add_data(std::span<const uint8_t> input) {
43
0
   m_ghash->update_associated_data(input);
44
0
}
45
46
0
bool GMAC::has_keying_material() const {
47
0
   return m_cipher->has_keying_material();
48
0
}
49
50
0
void GMAC::key_schedule(std::span<const uint8_t> key) {
51
0
   clear();
52
0
   m_cipher->set_key(key);
53
54
0
   m_cipher->encrypt(m_H);
55
0
   m_ghash->set_key(m_H);
56
0
}
57
58
0
void GMAC::start_msg(std::span<const uint8_t> nonce) {
59
0
   std::array<uint8_t, GCM_BS> y0 = {0};
60
61
0
   if(nonce.size() == 12) {
62
0
      copy_mem(y0.data(), nonce.data(), nonce.size());
63
0
      y0[GCM_BS - 1] = 1;
64
0
   } else {
65
0
      m_ghash->nonce_hash(y0, nonce);
66
0
   }
67
68
0
   m_cipher->encrypt(y0.data());
69
0
   m_ghash->start(y0);
70
0
   m_initialized = true;
71
0
}
72
73
0
void GMAC::final_result(std::span<uint8_t> mac) {
74
   // This ensures the GMAC computation has been initialized with a fresh
75
   // nonce. The aim of this check is to prevent developers from re-using
76
   // nonces (and potential nonce-reuse attacks).
77
0
   if(!m_initialized) {
78
0
      throw Invalid_State("GMAC was not used with a fresh nonce");
79
0
   }
80
81
0
   m_ghash->final(mac.first(output_length()));
82
0
   m_ghash->set_key(m_H);
83
0
}
84
85
0
std::unique_ptr<MessageAuthenticationCode> GMAC::new_object() const {
86
0
   return std::make_unique<GMAC>(m_cipher->new_object());
87
0
}
88
}  // namespace Botan