Botan 2.19.3
Crypto and TLS for C&
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
14namespace 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
34GMAC::~GMAC() { /* for unique_ptr */ }
35
37 {
38 return m_cipher->key_spec();
39 }
40
41std::string GMAC::name() const
42 {
43 return "GMAC(" + m_cipher->name() + ")";
44 }
45
46size_t GMAC::output_length() const
47 {
48 return GCM_BS;
49 }
50
51void 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
80void 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
90void 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
111void 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
126 m_ghash->final(mac, output_length());
127 clear();
128 }
129
131 {
132 return new GMAC(m_cipher->clone());
133 }
134}
MessageAuthenticationCode * clone() const override
Definition gmac.cpp:130
std::string name() const override
Definition gmac.cpp:41
Key_Length_Specification key_spec() const override
Definition gmac.cpp:36
GMAC(BlockCipher *cipher)
Definition gmac.cpp:16
void clear() override
Definition gmac.cpp:25
size_t output_length() const override
Definition gmac.cpp:46
void zeroise(std::vector< T, Alloc > &vec)
Definition secmem.h:114
void copy_mem(T *out, const T *in, size_t n)
Definition mem_ops.h:133