• Home
  • Features
  • Pricing
  • Docs
  • Announcements
  • Sign In

randombit / botan / 5079590438

25 May 2023 12:28PM UTC coverage: 92.228% (+0.5%) from 91.723%
5079590438

Pull #3502

github

Pull Request #3502: Apply clang-format to the codebase

75589 of 81959 relevant lines covered (92.23%)

12139530.51 hits per line

Source File
Press 'n' to go to next uncovered line, 'b' for previous

98.46
/src/lib/modes/xts/xts.cpp
1
/*
2
* XTS Mode
3
* (C) 2009,2013 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/internal/xts.h>
10

11
#include <botan/internal/fmt.h>
12
#include <botan/internal/poly_dbl.h>
13

14
namespace Botan {
15

16
XTS_Mode::XTS_Mode(std::unique_ptr<BlockCipher> cipher) :
4,175✔
17
      m_cipher(std::move(cipher)),
4,175✔
18
      m_cipher_block_size(m_cipher->block_size()),
4,175✔
19
      m_cipher_parallelism(m_cipher->parallel_bytes()),
4,175✔
20
      m_tweak_blocks(m_cipher_parallelism / m_cipher_block_size) {
4,175✔
21
   if(poly_double_supported_size(m_cipher_block_size) == false) {
4,175✔
22
      throw Invalid_Argument(fmt("Cannot use {} with XTS", m_cipher->name()));
×
23
   }
24

25
   m_tweak_cipher = m_cipher->new_object();
4,175✔
26
}
4,175✔
27

28
void XTS_Mode::clear() {
1,670✔
29
   m_cipher->clear();
1,670✔
30
   m_tweak_cipher->clear();
1,670✔
31
   reset();
3,340✔
32
}
1,670✔
33

34
size_t XTS_Mode::update_granularity() const { return m_cipher_block_size; }
5,845✔
35

36
size_t XTS_Mode::ideal_granularity() const { return m_cipher_parallelism; }
5,010✔
37

38
void XTS_Mode::reset() { m_tweak.clear(); }
5,010✔
39

40
std::string XTS_Mode::name() const { return cipher().name() + "/XTS"; }
6,680✔
41

42
size_t XTS_Mode::minimum_final_size() const { return cipher_block_size(); }
14,258✔
43

44
Key_Length_Specification XTS_Mode::key_spec() const { return cipher().key_spec().multiple(2); }
5,010✔
45

46
size_t XTS_Mode::default_nonce_length() const { return cipher_block_size(); }
1,670✔
47

48
bool XTS_Mode::valid_nonce_length(size_t n) const { return n <= cipher_block_size(); }
15,928✔
49

50
bool XTS_Mode::has_keying_material() const {
5,010✔
51
   return m_cipher->has_keying_material() && m_tweak_cipher->has_keying_material();
5,010✔
52
}
53

54
void XTS_Mode::key_schedule(const uint8_t key[], size_t length) {
5,010✔
55
   const size_t key_half = length / 2;
5,010✔
56

57
   if(length % 2 == 1 || !m_cipher->valid_keylength(key_half))
5,010✔
58
      throw Invalid_Key_Length(name(), length);
×
59

60
   m_cipher->set_key(key, key_half);
5,010✔
61
   m_tweak_cipher->set_key(&key[key_half], key_half);
5,010✔
62
}
5,010✔
63

64
void XTS_Mode::start_msg(const uint8_t nonce[], size_t nonce_len) {
12,588✔
65
   if(!valid_nonce_length(nonce_len))
12,588✔
66
      throw Invalid_IV_Length(name(), nonce_len);
3,340✔
67

68
   m_tweak.resize(m_cipher_parallelism);
10,918✔
69
   clear_mem(m_tweak.data(), m_tweak.size());
10,918✔
70
   copy_mem(m_tweak.data(), nonce, nonce_len);
10,918✔
71
   m_tweak_cipher->encrypt(m_tweak.data());
10,918✔
72

73
   update_tweak(0);
10,918✔
74
}
10,918✔
75

76
void XTS_Mode::update_tweak(size_t which) {
34,812✔
77
   const size_t BS = m_tweak_cipher->block_size();
34,812✔
78

79
   if(which > 0)
34,812✔
80
      poly_double_n_le(m_tweak.data(), &m_tweak[(which - 1) * BS], BS);
23,894✔
81

82
   const size_t blocks_in_tweak = tweak_blocks();
34,812✔
83

84
   for(size_t i = 1; i < blocks_in_tweak; ++i)
326,560✔
85
      poly_double_n_le(&m_tweak[i * BS], &m_tweak[(i - 1) * BS], BS);
291,748✔
86
}
34,812✔
87

88
size_t XTS_Encryption::output_length(size_t input_length) const { return input_length; }
835✔
89

90
size_t XTS_Encryption::process_msg(uint8_t buf[], size_t sz) {
16,715✔
91
   BOTAN_STATE_CHECK(tweak_set());
16,715✔
92
   const size_t BS = cipher_block_size();
11,705✔
93

94
   BOTAN_ARG_CHECK(sz % BS == 0, "Input is not full blocks");
11,705✔
95
   size_t blocks = sz / BS;
11,705✔
96

97
   const size_t blocks_in_tweak = tweak_blocks();
11,705✔
98

99
   while(blocks) {
23,652✔
100
      const size_t to_proc = std::min(blocks, blocks_in_tweak);
11,947✔
101

102
      cipher().encrypt_n_xex(buf, tweak(), to_proc);
11,947✔
103

104
      buf += to_proc * BS;
11,947✔
105
      blocks -= to_proc;
11,947✔
106

107
      update_tweak(to_proc);
11,947✔
108
   }
109

110
   return sz;
11,705✔
111
}
112

113
void XTS_Encryption::finish_msg(secure_vector<uint8_t>& buffer, size_t offset) {
6,294✔
114
   BOTAN_ARG_CHECK(buffer.size() >= offset, "Offset is out of range");
6,294✔
115
   const size_t sz = buffer.size() - offset;
6,294✔
116
   uint8_t* buf = buffer.data() + offset;
6,294✔
117

118
   BOTAN_ARG_CHECK(sz >= minimum_final_size(), "missing sufficient final input in XTS encrypt");
6,294✔
119

120
   const size_t BS = cipher_block_size();
6,294✔
121

122
   if(sz % BS == 0) {
6,294✔
123
      update(buffer, offset);
2,862✔
124
   } else {
125
      // steal ciphertext
126
      const size_t full_blocks = ((sz / BS) - 1) * BS;
3,432✔
127
      const size_t final_bytes = sz - full_blocks;
3,432✔
128
      BOTAN_ASSERT(final_bytes > BS && final_bytes < 2 * BS, "Left over size in expected range");
3,432✔
129

130
      secure_vector<uint8_t> last(buf + full_blocks, buf + full_blocks + final_bytes);
3,432✔
131
      buffer.resize(full_blocks + offset);
3,432✔
132
      update(buffer, offset);
3,432✔
133

134
      xor_buf(last, tweak(), BS);
3,432✔
135
      cipher().encrypt(last);
3,432✔
136
      xor_buf(last, tweak(), BS);
3,432✔
137

138
      for(size_t i = 0; i != final_bytes - BS; ++i) {
27,560✔
139
         last[i] ^= last[i + BS];
24,128✔
140
         last[i + BS] ^= last[i];
24,128✔
141
         last[i] ^= last[i + BS];
24,128✔
142
      }
143

144
      xor_buf(last, tweak() + BS, BS);
3,432✔
145
      cipher().encrypt(last);
3,432✔
146
      xor_buf(last, tweak() + BS, BS);
3,432✔
147

148
      buffer += last;
3,432✔
149
   }
3,432✔
150
}
3,789✔
151

152
size_t XTS_Decryption::output_length(size_t input_length) const { return input_length; }
835✔
153

154
size_t XTS_Decryption::process_msg(uint8_t buf[], size_t sz) {
16,715✔
155
   BOTAN_STATE_CHECK(tweak_set());
16,715✔
156
   const size_t BS = cipher_block_size();
11,705✔
157

158
   BOTAN_ARG_CHECK(sz % BS == 0, "Input is not full blocks");
11,705✔
159
   size_t blocks = sz / BS;
11,705✔
160

161
   const size_t blocks_in_tweak = tweak_blocks();
11,705✔
162

163
   while(blocks) {
23,652✔
164
      const size_t to_proc = std::min(blocks, blocks_in_tweak);
11,947✔
165

166
      cipher().decrypt_n_xex(buf, tweak(), to_proc);
11,947✔
167

168
      buf += to_proc * BS;
11,947✔
169
      blocks -= to_proc;
11,947✔
170

171
      update_tweak(to_proc);
11,947✔
172
   }
173

174
   return sz;
11,705✔
175
}
176

177
void XTS_Decryption::finish_msg(secure_vector<uint8_t>& buffer, size_t offset) {
6,294✔
178
   BOTAN_ARG_CHECK(buffer.size() >= offset, "Offset is out of range");
6,294✔
179
   const size_t sz = buffer.size() - offset;
6,294✔
180
   uint8_t* buf = buffer.data() + offset;
6,294✔
181

182
   BOTAN_ARG_CHECK(sz >= minimum_final_size(), "missing sufficient final input in XTS decrypt");
6,294✔
183

184
   const size_t BS = cipher_block_size();
6,294✔
185

186
   if(sz % BS == 0) {
6,294✔
187
      update(buffer, offset);
2,862✔
188
   } else {
189
      // steal ciphertext
190
      const size_t full_blocks = ((sz / BS) - 1) * BS;
3,432✔
191
      const size_t final_bytes = sz - full_blocks;
3,432✔
192
      BOTAN_ASSERT(final_bytes > BS && final_bytes < 2 * BS, "Left over size in expected range");
3,432✔
193

194
      secure_vector<uint8_t> last(buf + full_blocks, buf + full_blocks + final_bytes);
3,432✔
195
      buffer.resize(full_blocks + offset);
3,432✔
196
      update(buffer, offset);
3,432✔
197

198
      xor_buf(last, tweak() + BS, BS);
3,432✔
199
      cipher().decrypt(last);
3,432✔
200
      xor_buf(last, tweak() + BS, BS);
3,432✔
201

202
      for(size_t i = 0; i != final_bytes - BS; ++i) {
27,560✔
203
         last[i] ^= last[i + BS];
24,128✔
204
         last[i + BS] ^= last[i];
24,128✔
205
         last[i] ^= last[i + BS];
24,128✔
206
      }
207

208
      xor_buf(last, tweak(), BS);
3,432✔
209
      cipher().decrypt(last);
3,432✔
210
      xor_buf(last, tweak(), BS);
3,432✔
211

212
      buffer += last;
3,432✔
213
   }
3,432✔
214
}
3,789✔
215

216
}
STATUS · Troubleshooting · Open an Issue · Sales · Support · CAREERS · ENTERPRISE · START FREE · SCHEDULE DEMO
ANNOUNCEMENTS · TWITTER · TOS & SLA · Supported CI Services · What's a CI service? · Automated Testing

© 2026 Coveralls, Inc