Skip to content

Commit 1acfbd6

Browse files
committed
WIP
1 parent 7fb431f commit 1acfbd6

File tree

10 files changed

+267
-199
lines changed

10 files changed

+267
-199
lines changed

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

src/lib/modes/aead/siv/siv.cpp

Lines changed: 41 additions & 37 deletions
Original file line numberDiff line numberDiff line change
@@ -115,10 +115,10 @@ size_t SIV_Mode::process_msg(uint8_t buf[], size_t sz) {
115115
return 0;
116116
}
117117

118-
secure_vector<uint8_t> SIV_Mode::S2V(const uint8_t* text, size_t text_len) {
118+
std::array<uint8_t, SIV_Mode::tag_length> SIV_Mode::S2V(std::span<const uint8_t> text) {
119119
const std::vector<uint8_t> zeros(block_size());
120120

121-
secure_vector<uint8_t> V = m_mac->process(zeros.data(), zeros.size());
121+
secure_vector<uint8_t> V = m_mac->process(zeros);
122122

123123
for(size_t i = 0; i != m_ad_macs.size(); ++i) {
124124
poly_double_n(V.data(), V.size());
@@ -130,70 +130,74 @@ secure_vector<uint8_t> SIV_Mode::S2V(const uint8_t* text, size_t text_len) {
130130
V ^= m_nonce;
131131
}
132132

133-
if(text_len < block_size()) {
133+
if(text.size() < block_size()) {
134134
poly_double_n(V.data(), V.size());
135-
xor_buf(V.data(), text, text_len);
136-
V[text_len] ^= 0x80;
137-
return m_mac->process(V);
135+
xor_buf(std::span{V}.first(text.size()), text);
136+
V[text.size()] ^= 0x80;
137+
m_mac->update(V);
138+
} else {
139+
m_mac->update(text.first(text.size() - block_size()));
140+
xor_buf(std::span{V}, text.last(block_size()));
141+
m_mac->update(V);
138142
}
139143

140-
m_mac->update(text, text_len - block_size());
141-
xor_buf(V.data(), &text[text_len - block_size()], block_size());
142-
m_mac->update(V);
143-
144-
return m_mac->final();
144+
std::array<uint8_t, tag_length> out;
145+
m_mac->final(out);
146+
return out;
145147
}
146148

147-
void SIV_Mode::set_ctr_iv(secure_vector<uint8_t> V) {
149+
void SIV_Mode::set_ctr_iv(std::array<uint8_t, SIV_Mode::tag_length> V) {
148150
V[m_bs - 8] &= 0x7F;
149151
V[m_bs - 4] &= 0x7F;
150152

151-
ctr().set_iv(V.data(), V.size());
153+
ctr().set_iv(V);
152154
}
153155

154-
void SIV_Encryption::finish_msg(secure_vector<uint8_t>& buffer, size_t offset) {
155-
BOTAN_ARG_CHECK(buffer.size() >= offset, "Offset is out of range");
156+
size_t SIV_Encryption::finish_msg(std::span<uint8_t> buffer, size_t input_bytes) {
157+
auto& buffered = msg_buf();
158+
BOTAN_ASSERT_NOMSG(buffered.size() + input_bytes + tag_length == buffer.size());
156159

157-
buffer.insert(buffer.begin() + offset, msg_buf().begin(), msg_buf().end());
158-
msg_buf().clear();
160+
const auto entire_payload = buffer.subspan(tag_length);
159161

160-
const secure_vector<uint8_t> V = S2V(buffer.data() + offset, buffer.size() - offset);
162+
copy_mem(entire_payload.last(input_bytes), buffer.first(input_bytes));
163+
copy_mem(entire_payload.first(buffered.size()), buffered);
161164

162-
buffer.insert(buffer.begin() + offset, V.begin(), V.end());
165+
const auto V = S2V(entire_payload);
166+
copy_mem(buffer.first<tag_length>(), V);
163167

164-
if(buffer.size() != offset + V.size()) {
168+
if(!entire_payload.empty()) {
165169
set_ctr_iv(V);
166-
ctr().cipher1(&buffer[offset + V.size()], buffer.size() - offset - V.size());
170+
ctr().cipher1(entire_payload);
167171
}
172+
173+
return buffer.size();
168174
}
169175

170-
void SIV_Decryption::finish_msg(secure_vector<uint8_t>& buffer, size_t offset) {
171-
BOTAN_ARG_CHECK(buffer.size() >= offset, "Offset is out of range");
176+
size_t SIV_Decryption::finish_msg(std::span<uint8_t> buffer, size_t input_bytes) {
177+
auto& buffered = msg_buf();
178+
BOTAN_ASSERT_NOMSG(buffered.size() + input_bytes == buffer.size());
172179

173-
if(!msg_buf().empty()) {
174-
buffer.insert(buffer.begin() + offset, msg_buf().begin(), msg_buf().end());
175-
msg_buf().clear();
180+
if(!buffered.empty()) {
181+
copy_mem(buffer.last(input_bytes), buffer.first(input_bytes));
182+
copy_mem(buffer.first(buffered.size()), buffered);
183+
buffered.clear();
176184
}
177185

178-
const size_t sz = buffer.size() - offset;
179-
180-
BOTAN_ARG_CHECK(sz >= tag_size(), "input did not include the tag");
181-
182-
secure_vector<uint8_t> V(buffer.data() + offset, buffer.data() + offset + block_size());
183-
184-
if(buffer.size() != offset + V.size()) {
186+
const auto V = typecast_copy<std::array<uint8_t, tag_length>>(buffer.first<tag_length>());
187+
const auto encrypted_payload = buffer.subspan(tag_length);
188+
const auto plaintext_payload = buffer.first(encrypted_payload.size());
189+
if(!encrypted_payload.empty()) {
185190
set_ctr_iv(V);
186-
187-
ctr().cipher(buffer.data() + offset + V.size(), buffer.data() + offset, buffer.size() - offset - V.size());
191+
ctr().cipher(encrypted_payload, plaintext_payload);
188192
}
189193

190-
const secure_vector<uint8_t> T = S2V(buffer.data() + offset, buffer.size() - offset - V.size());
194+
const auto T = S2V(plaintext_payload);
191195

192196
if(!CT::is_equal(T.data(), V.data(), T.size()).as_bool()) {
193197
throw Invalid_Authentication_Tag("SIV tag check failed");
194198
}
195199

196-
buffer.resize(buffer.size() - tag_size());
200+
return plaintext_payload.size();
197201
}
198202

199203
} // namespace Botan

0 commit comments

Comments
 (0)