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