Botan  2.7.0
Crypto and TLS for C++11
gmac.cpp
Go to the documentation of this file.
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/gmac.h>
10 #include <botan/ghash.h>
11 #include <botan/exceptn.h>
12 #include <botan/block_cipher.h>
13 
14 namespace Botan {
15 
17  m_cipher(cipher),
18  m_ghash(new GHASH),
19  m_aad_buf(GCM_BS),
20  m_aad_buf_pos(0),
21  m_initialized(false)
22  {
23  }
24 
26  {
27  m_cipher->clear();
28  m_ghash->clear();
29  zeroise(m_aad_buf);
30  m_aad_buf_pos = 0;
31  m_initialized = false;
32  }
33 
34 GMAC::~GMAC() { /* for unique_ptr */ }
35 
37  {
38  return m_cipher->key_spec();
39  }
40 
41 std::string GMAC::name() const
42  {
43  return "GMAC(" + m_cipher->name() + ")";
44  }
45 
46 size_t GMAC::output_length() const
47  {
48  return GCM_BS;
49  }
50 
51 void GMAC::add_data(const uint8_t input[], size_t size)
52  {
53  if(m_aad_buf_pos > 0)
54  {
55  const size_t taking = std::min(GCM_BS - m_aad_buf_pos, size);
56  copy_mem(&m_aad_buf[m_aad_buf_pos], input, taking);
57  m_aad_buf_pos += taking;
58  input += taking;
59  size -= taking;
60 
61  if(m_aad_buf_pos == GCM_BS)
62  {
63  m_ghash->update_associated_data(m_aad_buf.data(), GCM_BS);
64  m_aad_buf_pos = 0;
65  }
66  }
67 
68  const size_t left_over = size % GCM_BS;
69  const size_t full_blocks = size - left_over;
70  m_ghash->update_associated_data(input, full_blocks);
71  input += full_blocks;
72 
73  if(left_over > 0)
74  {
75  copy_mem(&m_aad_buf[m_aad_buf_pos], input, left_over);
76  m_aad_buf_pos += left_over;
77  }
78  }
79 
80 void GMAC::key_schedule(const uint8_t key[], size_t size)
81  {
82  clear();
83  m_cipher->set_key(key, size);
84 
85  secure_vector<uint8_t> H(GCM_BS);
86  m_cipher->encrypt(H);
87  m_ghash->set_key(H);
88  }
89 
90 void GMAC::start_msg(const uint8_t nonce[], size_t nonce_len)
91  {
92  secure_vector<uint8_t> y0(GCM_BS);
93 
94  if(nonce_len == 12)
95  {
96  copy_mem(y0.data(), nonce, nonce_len);
97  y0[GCM_BS - 1] = 1;
98  }
99  else
100  {
101  m_ghash->ghash_update(y0, nonce, nonce_len);
102  m_ghash->add_final_block(y0, 0, nonce_len);
103  }
104 
105  secure_vector<uint8_t> m_enc_y0(GCM_BS);
106  m_cipher->encrypt(y0.data(), m_enc_y0.data());
107  m_ghash->start(m_enc_y0.data(), m_enc_y0.size());
108  m_initialized = true;
109  }
110 
111 void GMAC::final_result(uint8_t mac[])
112  {
113  // This ensures the GMAC computation has been initialized with a fresh
114  // nonce. The aim of this check is to prevent developers from re-using
115  // nonces (and potential nonce-reuse attacks).
116  if(m_initialized == false)
117  throw Invalid_State("GMAC was not used with a fresh nonce");
118 
119  // process the rest of the aad buffer. Even if it is a partial block only
120  // ghash_update will process it properly.
121  if(m_aad_buf_pos > 0)
122  {
123  m_ghash->update_associated_data(m_aad_buf.data(), m_aad_buf_pos);
124  }
125  secure_vector<uint8_t> result = m_ghash->final();
126  copy_mem(mac, result.data(), result.size());
127  clear();
128  }
129 
131  {
132  return new GMAC(m_cipher->clone());
133  }
134 }
Key_Length_Specification key_spec() const override
Definition: gmac.cpp:36
void clear() override
Definition: gmac.cpp:25
void copy_mem(T *out, const T *in, size_t n)
Definition: mem_ops.h:108
Definition: alg_id.cpp:13
GMAC(BlockCipher *cipher)
Definition: gmac.cpp:16
MessageAuthenticationCode * clone() const override
Definition: gmac.cpp:130
std::string name() const override
Definition: gmac.cpp:41
size_t output_length() const override
Definition: gmac.cpp:46
void zeroise(std::vector< T, Alloc > &vec)
Definition: secmem.h:183