Skip to content

Commit b70452a

Browse files
committed
WIP
1 parent 7fb431f commit b70452a

File tree

19 files changed

+508
-392
lines changed

19 files changed

+508
-392
lines changed

src/lib/modes/aead/chacha20poly1305/chacha20poly1305.cpp

Lines changed: 28 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -102,21 +102,29 @@ size_t ChaCha20Poly1305_Encryption::process_msg(uint8_t buf[], size_t sz) {
102102
return sz;
103103
}
104104

105-
void ChaCha20Poly1305_Encryption::finish_msg(secure_vector<uint8_t>& buffer, size_t offset) {
106-
update(buffer, offset);
105+
size_t ChaCha20Poly1305_Encryption::finish_msg(std::span<uint8_t> buffer, size_t input_bytes) {
106+
const auto tag_length = tag_size();
107+
108+
BOTAN_ASSERT_NOMSG(input_bytes + tag_length == buffer.size());
109+
110+
const auto payload = buffer.first(input_bytes);
111+
const auto tag = buffer.last(tag_length);
112+
113+
process(payload);
107114
if(cfrg_version()) {
108115
if(m_ctext_len % 16) {
109-
const uint8_t zeros[16] = {0};
110-
m_poly1305->update(zeros, 16 - m_ctext_len % 16);
116+
std::array<uint8_t, 16> zeros{};
117+
m_poly1305->update(std::span{zeros}.first(16 - m_ctext_len % 16));
111118
}
112119
update_len(m_ad.size());
113120
}
114121
update_len(m_ctext_len);
115122

116-
buffer.resize(buffer.size() + tag_size());
117-
m_poly1305->final(&buffer[buffer.size() - tag_size()]);
123+
m_poly1305->final(tag);
118124
m_ctext_len = 0;
119125
m_nonce_len = 0;
126+
127+
return buffer.size();
120128
}
121129

122130
size_t ChaCha20Poly1305_Decryption::process_msg(uint8_t buf[], size_t sz) {
@@ -126,43 +134,40 @@ size_t ChaCha20Poly1305_Decryption::process_msg(uint8_t buf[], size_t sz) {
126134
return sz;
127135
}
128136

129-
void ChaCha20Poly1305_Decryption::finish_msg(secure_vector<uint8_t>& buffer, size_t offset) {
130-
BOTAN_ARG_CHECK(buffer.size() >= offset, "Offset is out of range");
131-
const size_t sz = buffer.size() - offset;
132-
uint8_t* buf = buffer.data() + offset;
137+
size_t ChaCha20Poly1305_Decryption::finish_msg(std::span<uint8_t> buffer, size_t input_bytes) {
138+
const auto tag_length = tag_size();
133139

134-
BOTAN_ARG_CHECK(sz >= tag_size(), "input did not include the tag");
140+
BOTAN_ASSERT_NOMSG(buffer.size() == input_bytes);
141+
BOTAN_ASSERT_NOMSG(buffer.size() >= tag_length);
135142

136-
const size_t remaining = sz - tag_size();
143+
const auto remaining = buffer.first(buffer.size() - tag_length);
144+
const auto tag = buffer.last(tag_length);
137145

138-
if(remaining) {
139-
m_poly1305->update(buf, remaining); // poly1305 of ciphertext
140-
m_chacha->cipher1(buf, remaining);
141-
m_ctext_len += remaining;
146+
if(!remaining.empty()) {
147+
process(remaining);
142148
}
143149

144150
if(cfrg_version()) {
145151
if(m_ctext_len % 16) {
146-
const uint8_t zeros[16] = {0};
147-
m_poly1305->update(zeros, 16 - m_ctext_len % 16);
152+
std::array<uint8_t, 16> zeros{};
153+
m_poly1305->update(std::span{zeros}.first(16 - m_ctext_len % 16));
148154
}
149155
update_len(m_ad.size());
150156
}
151157

152158
update_len(m_ctext_len);
153159

154-
uint8_t mac[16];
160+
std::array<uint8_t, 16> mac;
155161
m_poly1305->final(mac);
156162

157-
const uint8_t* included_tag = &buf[remaining];
158-
159163
m_ctext_len = 0;
160164
m_nonce_len = 0;
161165

162-
if(!CT::is_equal(mac, included_tag, tag_size()).as_bool()) {
166+
if(!CT::is_equal(mac.data(), tag.data(), tag.size()).as_bool()) {
163167
throw Invalid_Authentication_Tag("ChaCha20Poly1305 tag check failed");
164168
}
165-
buffer.resize(offset + remaining);
169+
170+
return remaining.size();
166171
}
167172

168173
} // namespace Botan

src/lib/modes/aead/chacha20poly1305/chacha20poly1305.h

Lines changed: 11 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -77,9 +77,13 @@ class ChaCha20Poly1305_Encryption final : public ChaCha20Poly1305_Mode {
7777

7878
size_t minimum_final_size() const override { return 0; }
7979

80+
size_t bytes_needed_for_finalization(size_t final_input_length) const override {
81+
return output_length(final_input_length);
82+
}
83+
8084
private:
8185
size_t process_msg(uint8_t buf[], size_t size) override;
82-
void finish_msg(secure_vector<uint8_t>& final_block, size_t offset = 0) override;
86+
size_t finish_msg(std::span<uint8_t> final_block, size_t input_bytes) override;
8387
};
8488

8589
/**
@@ -94,9 +98,14 @@ class ChaCha20Poly1305_Decryption final : public ChaCha20Poly1305_Mode {
9498

9599
size_t minimum_final_size() const override { return tag_size(); }
96100

101+
size_t bytes_needed_for_finalization(size_t final_input_length) const override {
102+
BOTAN_ARG_CHECK(final_input_length >= tag_size(), "Sufficient input");
103+
return final_input_length;
104+
}
105+
97106
private:
98107
size_t process_msg(uint8_t buf[], size_t size) override;
99-
void finish_msg(secure_vector<uint8_t>& final_block, size_t offset = 0) override;
108+
size_t finish_msg(std::span<uint8_t> final_block, size_t input_bytes) override;
100109
};
101110

102111
} // namespace Botan

src/lib/modes/aead/eax/eax.cpp

Lines changed: 26 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -128,10 +128,17 @@ size_t EAX_Encryption::process_msg(uint8_t buf[], size_t sz) {
128128
return sz;
129129
}
130130

131-
void EAX_Encryption::finish_msg(secure_vector<uint8_t>& buffer, size_t offset) {
131+
size_t EAX_Encryption::finish_msg(std::span<uint8_t> buffer, size_t input_bytes) {
132132
BOTAN_STATE_CHECK(!m_nonce_mac.empty());
133-
update(buffer, offset);
134133

134+
const size_t tag_length = tag_size();
135+
136+
BOTAN_ASSERT_NOMSG(input_bytes + tag_length == buffer.size());
137+
138+
const auto payload = buffer.first(input_bytes);
139+
const auto tag = buffer.last(tag_length);
140+
141+
process(payload);
135142
secure_vector<uint8_t> data_mac = m_cmac->final();
136143
xor_buf(data_mac, m_nonce_mac, data_mac.size());
137144

@@ -141,9 +148,11 @@ void EAX_Encryption::finish_msg(secure_vector<uint8_t>& buffer, size_t offset) {
141148

142149
xor_buf(data_mac, m_ad_mac, data_mac.size());
143150

144-
buffer += std::make_pair(data_mac.data(), tag_size());
151+
copy_mem(tag, std::span{data_mac}.first(tag_length));
145152

146153
m_nonce_mac.clear();
154+
155+
return buffer.size();
147156
}
148157

149158
size_t EAX_Decryption::process_msg(uint8_t buf[], size_t sz) {
@@ -153,40 +162,37 @@ size_t EAX_Decryption::process_msg(uint8_t buf[], size_t sz) {
153162
return sz;
154163
}
155164

156-
void EAX_Decryption::finish_msg(secure_vector<uint8_t>& buffer, size_t offset) {
157-
BOTAN_ARG_CHECK(buffer.size() >= offset, "Offset is out of range");
158-
const size_t sz = buffer.size() - offset;
159-
uint8_t* buf = buffer.data() + offset;
165+
size_t EAX_Decryption::finish_msg(std::span<uint8_t> buffer, size_t input_bytes) {
166+
const size_t tag_length = tag_size();
160167

161-
BOTAN_ARG_CHECK(sz >= tag_size(), "input did not include the tag");
168+
BOTAN_ASSERT_NOMSG(buffer.size() == input_bytes);
169+
BOTAN_ASSERT_NOMSG(buffer.size() >= tag_length);
162170

163-
const size_t remaining = sz - tag_size();
171+
const auto remaining = buffer.first(buffer.size() - tag_length);
172+
const auto tag = buffer.last(tag_length);
164173

165-
if(remaining) {
166-
m_cmac->update(buf, remaining);
167-
m_ctr->cipher(buf, buf, remaining);
174+
if(!remaining.empty()) {
175+
process(remaining);
168176
}
169177

170-
const uint8_t* included_tag = &buf[remaining];
171-
172-
secure_vector<uint8_t> mac = m_cmac->final();
173-
mac ^= m_nonce_mac;
178+
auto mac = m_cmac->final();
179+
xor_buf(mac, m_nonce_mac);
174180

175181
if(m_ad_mac.empty()) {
176182
m_ad_mac = eax_prf(1, block_size(), *m_cmac, nullptr, 0);
177183
}
178184

179-
mac ^= m_ad_mac;
180-
181-
const bool accept_mac = CT::is_equal(mac.data(), included_tag, tag_size()).as_bool();
185+
xor_buf(mac, m_ad_mac);
182186

183-
buffer.resize(offset + remaining);
187+
const bool accept_mac = CT::is_equal(mac.data(), tag.data(), tag_length).as_bool();
184188

185189
m_nonce_mac.clear();
186190

187191
if(!accept_mac) {
188192
throw Invalid_Authentication_Tag("EAX tag check failed");
189193
}
194+
195+
return remaining.size();
190196
}
191197

192198
} // namespace Botan

src/lib/modes/aead/eax/eax.h

Lines changed: 11 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -83,11 +83,15 @@ class EAX_Encryption final : public EAX_Mode {
8383

8484
size_t output_length(size_t input_length) const override { return input_length + tag_size(); }
8585

86+
size_t bytes_needed_for_finalization(size_t final_input_length) const override {
87+
return output_length(final_input_length);
88+
}
89+
8690
size_t minimum_final_size() const override { return 0; }
8791

8892
private:
8993
size_t process_msg(uint8_t buf[], size_t size) override;
90-
void finish_msg(secure_vector<uint8_t>& final_block, size_t offset = 0) override;
94+
size_t finish_msg(std::span<uint8_t> final_block, size_t input_bytes) override;
9195
};
9296

9397
/**
@@ -107,11 +111,16 @@ class EAX_Decryption final : public EAX_Mode {
107111
return input_length - tag_size();
108112
}
109113

114+
size_t bytes_needed_for_finalization(size_t final_input_length) const override {
115+
BOTAN_ARG_CHECK(final_input_length >= tag_size(), "Sufficient input");
116+
return final_input_length;
117+
}
118+
110119
size_t minimum_final_size() const override { return tag_size(); }
111120

112121
private:
113122
size_t process_msg(uint8_t buf[], size_t size) override;
114-
void finish_msg(secure_vector<uint8_t>& final_block, size_t offset = 0) override;
123+
size_t finish_msg(std::span<uint8_t> final_block, size_t input_bytes) override;
115124
};
116125

117126
} // namespace Botan

src/lib/modes/aead/gcm/gcm.cpp

Lines changed: 20 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -128,17 +128,17 @@ size_t GCM_Encryption::process_msg(uint8_t buf[], size_t sz) {
128128
return sz;
129129
}
130130

131-
void GCM_Encryption::finish_msg(secure_vector<uint8_t>& buffer, size_t offset) {
132-
BOTAN_ARG_CHECK(offset <= buffer.size(), "Invalid offset");
133-
const size_t sz = buffer.size() - offset;
134-
uint8_t* buf = buffer.data() + offset;
131+
size_t GCM_Encryption::finish_msg(std::span<uint8_t> buffer, size_t input_bytes) {
132+
const auto tag_length = tag_size();
135133

136-
m_ctr->cipher(buf, buf, sz);
137-
m_ghash->update({buf, sz});
134+
BOTAN_ASSERT_NOMSG(input_bytes + tag_length == buffer.size());
138135

139-
std::array<uint8_t, 16> mac = {0};
140-
m_ghash->final(std::span(mac).first(tag_size()));
141-
buffer += std::make_pair(mac.data(), tag_size());
136+
const auto payload = buffer.first(input_bytes);
137+
const auto tag = buffer.last(tag_length);
138+
139+
process(payload);
140+
m_ghash->final(tag);
141+
return buffer.size();
142142
}
143143

144144
size_t GCM_Decryption::process_msg(uint8_t buf[], size_t sz) {
@@ -148,31 +148,28 @@ size_t GCM_Decryption::process_msg(uint8_t buf[], size_t sz) {
148148
return sz;
149149
}
150150

151-
void GCM_Decryption::finish_msg(secure_vector<uint8_t>& buffer, size_t offset) {
152-
BOTAN_ARG_CHECK(offset <= buffer.size(), "Invalid offset");
153-
const size_t sz = buffer.size() - offset;
154-
uint8_t* buf = buffer.data() + offset;
151+
size_t GCM_Decryption::finish_msg(std::span<uint8_t> buffer, size_t input_bytes) {
152+
const auto tag_length = tag_size();
155153

156-
BOTAN_ARG_CHECK(sz >= tag_size(), "input did not include the tag");
154+
BOTAN_ASSERT_NOMSG(buffer.size() == input_bytes);
155+
BOTAN_ASSERT_NOMSG(buffer.size() >= tag_length);
157156

158-
const size_t remaining = sz - tag_size();
157+
const auto remaining = buffer.first(buffer.size() - tag_length);
158+
const auto tag = buffer.last(tag_length);
159159

160160
// handle any final input before the tag
161-
if(remaining) {
162-
m_ghash->update({buf, remaining});
163-
m_ctr->cipher(buf, buf, remaining);
161+
if(!remaining.empty()) {
162+
process(remaining);
164163
}
165164

166165
std::array<uint8_t, 16> mac = {0};
167-
m_ghash->final(std::span(mac).first(tag_size()));
168-
169-
const uint8_t* included_tag = &buffer[remaining + offset];
166+
m_ghash->final(std::span{mac}.first(tag_length));
170167

171-
if(!CT::is_equal(mac.data(), included_tag, tag_size()).as_bool()) {
168+
if(!CT::is_equal(mac.data(), tag.data(), tag.size()).as_bool()) {
172169
throw Invalid_Authentication_Tag("GCM tag check failed");
173170
}
174171

175-
buffer.resize(offset + remaining);
172+
return remaining.size();
176173
}
177174

178175
} // namespace Botan

src/lib/modes/aead/gcm/gcm.h

Lines changed: 11 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -82,11 +82,15 @@ class GCM_Encryption final : public GCM_Mode {
8282

8383
size_t output_length(size_t input_length) const override { return input_length + tag_size(); }
8484

85+
size_t bytes_needed_for_finalization(size_t final_input_length) const override {
86+
return output_length(final_input_length);
87+
}
88+
8589
size_t minimum_final_size() const override { return 0; }
8690

8791
private:
8892
size_t process_msg(uint8_t buf[], size_t size) override;
89-
void finish_msg(secure_vector<uint8_t>& final_block, size_t offset = 0) override;
93+
size_t finish_msg(std::span<uint8_t> final_block, size_t input_bytes) override;
9094
};
9195

9296
/**
@@ -106,11 +110,16 @@ class GCM_Decryption final : public GCM_Mode {
106110
return input_length - tag_size();
107111
}
108112

113+
size_t bytes_needed_for_finalization(size_t final_input_length) const override {
114+
BOTAN_ARG_CHECK(final_input_length >= tag_size(), "Sufficient input");
115+
return final_input_length;
116+
}
117+
109118
size_t minimum_final_size() const override { return tag_size(); }
110119

111120
private:
112121
size_t process_msg(uint8_t buf[], size_t size) override;
113-
void finish_msg(secure_vector<uint8_t>& final_block, size_t offset = 0) override;
122+
size_t finish_msg(std::span<uint8_t> final_block, size_t input_bytes) override;
114123
};
115124

116125
} // namespace Botan

0 commit comments

Comments
 (0)