@@ -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