Skip to content

Commit 22840e5

Browse files
committed
WIP
1 parent 7fb431f commit 22840e5

File tree

9 files changed

+223
-177
lines changed

9 files changed

+223
-177
lines changed

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

Lines changed: 22 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -128,17 +128,18 @@ 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 = std::span{buffer}.first(input_bytes);
137+
const auto tag = std::span{buffer}.last(tag_length);
138+
139+
m_ctr->cipher1(payload);
140+
m_ghash->update(payload);
141+
m_ghash->final(tag);
142+
return buffer.size();
142143
}
143144

144145
size_t GCM_Decryption::process_msg(uint8_t buf[], size_t sz) {
@@ -148,31 +149,29 @@ size_t GCM_Decryption::process_msg(uint8_t buf[], size_t sz) {
148149
return sz;
149150
}
150151

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;
152+
size_t GCM_Decryption::finish_msg(std::span<uint8_t> buffer, size_t input_bytes) {
153+
const auto tag_length = tag_size();
155154

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

158-
const size_t remaining = sz - tag_size();
158+
const auto remaining = std::span{buffer}.first(buffer.size() - tag_length);
159+
const auto tag = std::span{buffer}.last(tag_length);
159160

160161
// handle any final input before the tag
161-
if(remaining) {
162-
m_ghash->update({buf, remaining});
163-
m_ctr->cipher(buf, buf, remaining);
162+
if(!remaining.empty()) {
163+
m_ghash->update(remaining);
164+
m_ctr->cipher1(remaining);
164165
}
165166

166167
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];
168+
m_ghash->final(std::span(mac).first(tag_length));
170169

171-
if(!CT::is_equal(mac.data(), included_tag, tag_size()).as_bool()) {
170+
if(!CT::is_equal(mac.data(), tag.data(), tag.size()).as_bool()) {
172171
throw Invalid_Authentication_Tag("GCM tag check failed");
173172
}
174173

175-
buffer.resize(offset + remaining);
174+
return remaining.size();
176175
}
177176

178177
} // 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

src/lib/modes/aead/siv/siv.h

Lines changed: 17 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,8 @@ class MessageAuthenticationCode;
2424
*/
2525
class BOTAN_TEST_API SIV_Mode : public AEAD_Mode {
2626
public:
27+
constexpr static size_t tag_length = 16;
28+
2729
/**
2830
* Sets the nth element of the vector of associated data
2931
* @param n index into the AD vector
@@ -49,7 +51,7 @@ class BOTAN_TEST_API SIV_Mode : public AEAD_Mode {
4951

5052
void reset() override final;
5153

52-
size_t tag_size() const override final { return 16; }
54+
size_t tag_size() const override final { return tag_length; }
5355

5456
bool has_keying_material() const override final;
5557

@@ -62,11 +64,13 @@ class BOTAN_TEST_API SIV_Mode : public AEAD_Mode {
6264

6365
StreamCipher& ctr() { return *m_ctr; }
6466

65-
void set_ctr_iv(secure_vector<uint8_t> V);
67+
void set_ctr_iv(std::array<uint8_t, tag_length> V);
6668

6769
secure_vector<uint8_t>& msg_buf() { return m_msg_buf; }
6870

69-
secure_vector<uint8_t> S2V(const uint8_t text[], size_t text_len);
71+
const secure_vector<uint8_t>& msg_buf() const { return m_msg_buf; }
72+
73+
std::array<uint8_t, tag_length> S2V(std::span<const uint8_t> text);
7074

7175
private:
7276
void start_msg(const uint8_t nonce[], size_t nonce_len) override final;
@@ -95,10 +99,14 @@ class BOTAN_TEST_API SIV_Encryption final : public SIV_Mode {
9599

96100
size_t output_length(size_t input_length) const override { return input_length + tag_size(); }
97101

102+
size_t bytes_needed_for_finalization(size_t final_input_length) const override {
103+
return output_length(msg_buf().size() + final_input_length);
104+
}
105+
98106
size_t minimum_final_size() const override { return 0; }
99107

100108
private:
101-
void finish_msg(secure_vector<uint8_t>& final_block, size_t offset = 0) override;
109+
size_t finish_msg(std::span<uint8_t> final_block, size_t input_bytes) override;
102110
};
103111

104112
/**
@@ -116,10 +124,14 @@ class BOTAN_TEST_API SIV_Decryption final : public SIV_Mode {
116124
return input_length - tag_size();
117125
}
118126

127+
size_t bytes_needed_for_finalization(size_t final_input_length) const override {
128+
return msg_buf().size() + final_input_length;
129+
}
130+
119131
size_t minimum_final_size() const override { return tag_size(); }
120132

121133
private:
122-
void finish_msg(secure_vector<uint8_t>& final_block, size_t offset = 0) override;
134+
size_t finish_msg(std::span<uint8_t> final_block, size_t input_bytes) override;
123135
};
124136

125137
} // namespace Botan

0 commit comments

Comments
 (0)