Botan 2.13.0 Crypto and TLS for C++11

- Main Page
- Namespaces
- Classes
- Files

- File List
- File Members

gcm.cpp
Go to the documentation of this file.
1 /*
2 * GCM Mode Encryption
3 * (C) 2013,2015 Jack Lloyd
4 * (C) 2016 Daniel Neus, Rohde & Schwarz Cybersecurity
5 *
6 * Botan is released under the Simplified BSD License (see license.txt)
7 */
8
9 #include <botan/gcm.h>
10 #include <botan/ghash.h>
11 #include <botan/block_cipher.h>
12 #include <botan/ctr.h>
13
14 namespace Botan {
15
16 /*
17 * GCM_Mode Constructor
18 */
19 GCM_Mode::GCM_Mode(BlockCipher* cipher, size_t tag_size) :
20 m_tag_size(tag_size),
21 m_cipher_name(cipher->name())
22 {
23 if(cipher->block_size() != GCM_BS)
24 throw Invalid_Argument("Invalid block cipher for GCM");
25
26 m_ghash.reset(new GHASH);
27
28 m_ctr.reset(new CTR_BE(cipher, 4)); // CTR_BE takes ownership of cipher
29
30 /* We allow any of the values 128, 120, 112, 104, or 96 bits as a tag size */
31 /* 64 bit tag is still supported but deprecated and will be removed in the future */
32 if(m_tag_size != 8 && (m_tag_size < 12 || m_tag_size > 16))
33 throw Invalid_Argument(name() + ": Bad tag size " + std::to_string(m_tag_size));
34 }
35
36 GCM_Mode::~GCM_Mode() { /* for unique_ptr */ }
37
38 void GCM_Mode::clear()
39 {
40 m_ctr->clear();
41 m_ghash->clear();
42 reset();
43 }
44
45 void GCM_Mode::reset()
46 {
47 m_ghash->reset();
48 }
49
50 std::string GCM_Mode::name() const
51 {
52 return (m_cipher_name + "/GCM(" + std::to_string(tag_size()) + ")");
53 }
54
55 std::string GCM_Mode::provider() const
56 {
57 return m_ghash->provider();
58 }
59
60 size_t GCM_Mode::update_granularity() const
61 {
62 return GCM_BS * std::max<size_t>(2, BOTAN_BLOCK_CIPHER_PAR_MULT);
63 }
64
65 bool GCM_Mode::valid_nonce_length(size_t len) const
66 {
67 // GCM does not support empty nonces
68 return (len > 0);
69 }
70
71 Key_Length_Specification GCM_Mode::key_spec() const
72 {
73 return m_ctr->key_spec();
74 }
75
76 void GCM_Mode::key_schedule(const uint8_t key[], size_t keylen)
77 {
78 m_ctr->set_key(key, keylen);
79
80 const std::vector<uint8_t> zeros(GCM_BS);
81 m_ctr->set_iv(zeros.data(), zeros.size());
82
83 secure_vector<uint8_t> H(GCM_BS);
84 m_ctr->encipher(H);
85 m_ghash->set_key(H);
86 }
87
88 void GCM_Mode::set_associated_data(const uint8_t ad[], size_t ad_len)
89 {
90 m_ghash->set_associated_data(ad, ad_len);
91 }
92
93 void GCM_Mode::start_msg(const uint8_t nonce[], size_t nonce_len)
94 {
95 if(!valid_nonce_length(nonce_len))
96 throw Invalid_IV_Length(name(), nonce_len);
97
98 m_y0.resize(GCM_BS);
99
100 if(nonce_len == 12)
101 {
102 copy_mem(m_y0.data(), nonce, nonce_len);
103 m_y0[15] = 1;
104 }
105 else
106 {
107 m_ghash->nonce_hash(m_y0, nonce, nonce_len);
108 }
109
110 m_ctr->set_iv(m_y0.data(), m_y0.size());
111
112 zeroise(m_y0);
113 m_ctr->encipher(m_y0);
114
115 m_ghash->start(m_y0.data(), m_y0.size());
116 m_y0.clear();
117 }
118
119 size_t GCM_Encryption::process(uint8_t buf[], size_t sz)
120 {
121 BOTAN_ARG_CHECK(sz % update_granularity() == 0, "Invalid buffer size");
122 m_ctr->cipher(buf, buf, sz);
123 m_ghash->update(buf, sz);
124 return sz;
125 }
126
127 void GCM_Encryption::finish(secure_vector<uint8_t>& buffer, size_t offset)
128 {
129 BOTAN_ARG_CHECK(offset <= buffer.size(), "Invalid offset");
130 const size_t sz = buffer.size() - offset;
131 uint8_t* buf = buffer.data() + offset;
132
133 m_ctr->cipher(buf, buf, sz);
134 m_ghash->update(buf, sz);
135
136 uint8_t mac[16] = { 0 };
137 m_ghash->final(mac, tag_size());
138 buffer += std::make_pair(mac, tag_size());
139 }
140
141 size_t GCM_Decryption::process(uint8_t buf[], size_t sz)
142 {
143 BOTAN_ARG_CHECK(sz % update_granularity() == 0, "Invalid buffer size");
144 m_ghash->update(buf, sz);
145 m_ctr->cipher(buf, buf, sz);
146 return sz;
147 }
148
149 void GCM_Decryption::finish(secure_vector<uint8_t>& buffer, size_t offset)
150 {
151 BOTAN_ARG_CHECK(offset <= buffer.size(), "Invalid offset");
152 const size_t sz = buffer.size() - offset;
153 uint8_t* buf = buffer.data() + offset;
154
155 if(sz < tag_size())
156 throw Decoding_Error("Insufficient input for GCM decryption, tag missing");
157
158 const size_t remaining = sz - tag_size();
159
160 // handle any final input before the tag
161 if(remaining)
162 {
163 m_ghash->update(buf, remaining);
164 m_ctr->cipher(buf, buf, remaining);
165 }
166
167 uint8_t mac[16] = { 0 };
168 m_ghash->final(mac, tag_size());
169
170 const uint8_t* included_tag = &buffer[remaining+offset];
171
172 if(!constant_time_compare(mac, included_tag, tag_size()))
173 throw Invalid_Authentication_Tag("GCM tag check failed");
174
175 buffer.resize(offset + remaining);
176 }
177
178 }
Botan::GCM_Encryption::finish
void finish(secure_vector< uint8_t > &final_block, size_t offset=0) override
Definition: gcm.cpp:127
Botan::GCM_Mode::provider
std::string provider() const override
Definition: gcm.cpp:55
Botan::Invalid_Argument
Definition: exceptn.h:136
Botan::GCM_Mode::name
std::string name() const override
Definition: gcm.cpp:50
Botan::GCM_Mode::m_ctr
std::unique_ptr< StreamCipher > m_ctr
Definition: gcm.h:56
Botan::Invalid_IV_Length
Definition: exceptn.h:161
Botan::GHASH
Definition: ghash.h:22
Botan::Key_Length_Specification
Definition: key_spec.h:18
Botan::CTR_BE
Definition: ctr.h:21
Botan::constant_time_compare
bool constant_time_compare(const uint8_t x[], const uint8_t y[], size_t len)
Definition: mem_ops.h:82
Botan::GCM_Decryption::finish
void finish(secure_vector< uint8_t > &final_block, size_t offset=0) override
Definition: gcm.cpp:149
Botan::ASN1::to_string
std::string to_string(const BER_Object &obj)
Definition: asn1_obj.cpp:213
Botan::GCM_Mode::clear
void clear() override
Definition: gcm.cpp:38
m_cipher_name
std::string m_cipher_name
Definition: commoncrypto_block.cpp:66
Botan::GCM_Mode::update_granularity
size_t update_granularity() const override
Definition: gcm.cpp:60
Botan::GCM_Mode::m_tag_size
const size_t m_tag_size
Definition: gcm.h:53
Botan::Decoding_Error
Definition: exceptn.h:199
Botan::GCM_Mode::GCM_Mode
GCM_Mode(BlockCipher *cipher, size_t tag_size)
Definition: gcm.cpp:19
Botan::GCM_Mode::reset
void reset() override
Definition: gcm.cpp:45
name
std::string name
Definition: commoncrypto_hash.cpp:23
Botan::secure_vector
std::vector< T, secure_allocator< T >> secure_vector
Definition: secmem.h:65
Botan::GCM_Encryption::process
size_t process(uint8_t buf[], size_t size) override
Definition: gcm.cpp:119
Botan::GCM_Decryption::process
size_t process(uint8_t buf[], size_t size) override
Definition: gcm.cpp:141
Botan::GCM_Mode::m_cipher_name
const std::string m_cipher_name
Definition: gcm.h:54
Botan::copy_mem
void copy_mem(T *out, const T *in, size_t n)
Definition: mem_ops.h:132
Botan
Definition: alg_id.cpp:13
Botan::GCM_Mode::tag_size
size_t tag_size() const override
Definition: gcm.h:39
BOTAN_ARG_CHECK
#define BOTAN_ARG_CHECK(expr, msg)
Definition: assert.h:37
Botan::GCM_Mode::m_ghash
std::unique_ptr< GHASH > m_ghash
Definition: gcm.h:57
Botan::GCM_Mode::GCM_BS
static const size_t GCM_BS
Definition: gcm.h:51
Botan::GCM_Mode::set_associated_data
void set_associated_data(const uint8_t ad[], size_t ad_len) override
Definition: gcm.cpp:88
Botan::GCM_Mode::valid_nonce_length
bool valid_nonce_length(size_t len) const override
Definition: gcm.cpp:65
Botan::BlockCipher::block_size
virtual size_t block_size() const =0
Botan::Invalid_Authentication_Tag
Definition: exceptn.h:290
Botan::BlockCipher
Definition: block_cipher.h:21
Botan::zeroise
void zeroise(std::vector< T, Alloc > &vec)
Definition: secmem.h:160
Botan::GCM_Mode::key_spec
Key_Length_Specification key_spec() const override
Definition: gcm.cpp:71
Botan::GCM_Mode::~GCM_Mode
~GCM_Mode()
Definition: gcm.cpp:36