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

randombit / botan / 16239649803

12 Jul 2025 03:54PM UTC coverage: 90.588% (+0.02%) from 90.572%
16239649803

Pull #4880

github

web-flow
Merge 79ae69b5e into e3b3452ec
Pull Request #4880: Refactor: Cipher_Mode::finish_msg() using std::span

99178 of 109483 relevant lines covered (90.59%)

12365337.5 hits per line

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

96.0
/src/lib/modes/cipher_mode.cpp
1
/*
2
* Cipher Modes
3
* (C) 2015 Jack Lloyd
4
*
5
* Botan is released under the Simplified BSD License (see license.txt)
6
*/
7

8
#include <botan/cipher_mode.h>
9

10
#include <botan/internal/fmt.h>
11
#include <botan/internal/parsing.h>
12
#include <botan/internal/scan_name.h>
13
#include <botan/internal/stream_mode.h>
14
#include <sstream>
15

16
#if defined(BOTAN_HAS_BLOCK_CIPHER)
17
   #include <botan/block_cipher.h>
18
#endif
19

20
#if defined(BOTAN_HAS_AEAD_MODES)
21
   #include <botan/aead.h>
22
#endif
23

24
#if defined(BOTAN_HAS_MODE_CBC)
25
   #include <botan/internal/cbc.h>
26
#endif
27

28
#if defined(BOTAN_HAS_MODE_CFB)
29
   #include <botan/internal/cfb.h>
30
#endif
31

32
#if defined(BOTAN_HAS_MODE_XTS)
33
   #include <botan/internal/xts.h>
34
#endif
35

36
#if defined(BOTAN_HAS_COMMONCRYPTO)
37
   #include <botan/internal/commoncrypto.h>
38
#endif
39

40
namespace Botan {
41

42
std::unique_ptr<Cipher_Mode> Cipher_Mode::create_or_throw(std::string_view algo,
163✔
43
                                                          Cipher_Dir direction,
44
                                                          std::string_view provider) {
45
   if(auto mode = Cipher_Mode::create(algo, direction, provider)) {
163✔
46
      return mode;
162✔
47
   }
162✔
48

49
   throw Lookup_Error("Cipher mode", algo, provider);
1✔
50
}
51

52
std::unique_ptr<Cipher_Mode> Cipher_Mode::create(std::string_view algo,
20,406✔
53
                                                 Cipher_Dir direction,
54
                                                 std::string_view provider) {
55
#if defined(BOTAN_HAS_COMMONCRYPTO)
56
   if(provider.empty() || provider == "commoncrypto") {
57
      if(auto cm = make_commoncrypto_cipher_mode(algo, direction))
58
         return cm;
59

60
      if(!provider.empty())
61
         return nullptr;
62
   }
63
#endif
64

65
   if(provider != "base" && !provider.empty()) {
27,876✔
66
      return nullptr;
1,249✔
67
   }
68

69
#if defined(BOTAN_HAS_STREAM_CIPHER)
70
   if(auto sc = StreamCipher::create(algo)) {
19,157✔
71
      return std::make_unique<Stream_Cipher_Mode>(std::move(sc));
51✔
72
   }
51✔
73
#endif
74

75
#if defined(BOTAN_HAS_AEAD_MODES)
76
   if(auto aead = AEAD_Mode::create(algo, direction)) {
19,106✔
77
      return aead;
3,861✔
78
   }
3,861✔
79
#endif
80

81
   if(algo.find('/') != std::string::npos) {
15,245✔
82
      const std::vector<std::string> algo_parts = split_on(algo, '/');
7,489✔
83
      std::string_view cipher_name = algo_parts[0];
7,489✔
84
      const std::vector<std::string> mode_info = parse_algorithm_name(algo_parts[1]);
7,489✔
85

86
      if(mode_info.empty()) {
7,489✔
87
         return std::unique_ptr<Cipher_Mode>();
×
88
      }
89

90
      std::ostringstream mode_name;
7,489✔
91

92
      mode_name << mode_info[0] << '(' << cipher_name;
7,489✔
93
      for(size_t i = 1; i < mode_info.size(); ++i) {
7,721✔
94
         mode_name << ',' << mode_info[i];
232✔
95
      }
96
      for(size_t i = 2; i < algo_parts.size(); ++i) {
9,153✔
97
         mode_name << ',' << algo_parts[i];
1,664✔
98
      }
99
      mode_name << ')';
7,489✔
100

101
      return Cipher_Mode::create(mode_name.str(), direction, provider);
7,489✔
102
   }
7,489✔
103

104
#if defined(BOTAN_HAS_BLOCK_CIPHER)
105

106
   SCAN_Name spec(algo);
7,756✔
107

108
   if(spec.arg_count() == 0) {
7,756✔
109
      return std::unique_ptr<Cipher_Mode>();
1✔
110
   }
111

112
   auto bc = BlockCipher::create(spec.arg(0), provider);
7,755✔
113

114
   if(!bc) {
7,755✔
115
      return std::unique_ptr<Cipher_Mode>();
2✔
116
   }
117

118
   #if defined(BOTAN_HAS_MODE_CBC)
119
   if(spec.algo_name() == "CBC") {
7,753✔
120
      const std::string padding = spec.arg(1, "PKCS7");
2,873✔
121

122
      if(padding == "CTS") {
2,873✔
123
         if(direction == Cipher_Dir::Encryption) {
240✔
124
            return std::make_unique<CTS_Encryption>(std::move(bc));
144✔
125
         } else {
126
            return std::make_unique<CTS_Decryption>(std::move(bc));
96✔
127
         }
128
      } else {
129
         auto pad = BlockCipherModePaddingMethod::create(padding);
2,633✔
130

131
         if(pad) {
2,633✔
132
            if(direction == Cipher_Dir::Encryption) {
2,633✔
133
               return std::make_unique<CBC_Encryption>(std::move(bc), std::move(pad));
1,480✔
134
            } else {
135
               return std::make_unique<CBC_Decryption>(std::move(bc), std::move(pad));
1,153✔
136
            }
137
         }
138
      }
2,633✔
139
   }
2,873✔
140
   #endif
141

142
   #if defined(BOTAN_HAS_MODE_XTS)
143
   if(spec.algo_name() == "XTS") {
4,880✔
144
      if(direction == Cipher_Dir::Encryption) {
4,175✔
145
         return std::make_unique<XTS_Encryption>(std::move(bc));
2,505✔
146
      } else {
147
         return std::make_unique<XTS_Decryption>(std::move(bc));
1,670✔
148
      }
149
   }
150
   #endif
151

152
   #if defined(BOTAN_HAS_MODE_CFB)
153
   if(spec.algo_name() == "CFB") {
705✔
154
      const size_t feedback_bits = spec.arg_as_integer(1, 8 * bc->block_size());
705✔
155
      if(direction == Cipher_Dir::Encryption) {
705✔
156
         return std::make_unique<CFB_Encryption>(std::move(bc), feedback_bits);
340✔
157
      } else {
158
         return std::make_unique<CFB_Decryption>(std::move(bc), feedback_bits);
365✔
159
      }
160
   }
161
   #endif
162

163
#endif
164

165
   return std::unique_ptr<Cipher_Mode>();
×
166
}
7,756✔
167

168
//static
169
std::vector<std::string> Cipher_Mode::providers(std::string_view algo_spec) {
1,249✔
170
   const std::vector<std::string>& possible = {"base", "commoncrypto"};
1,249✔
171
   std::vector<std::string> providers;
1,249✔
172
   for(auto&& prov : possible) {
3,747✔
173
      auto mode = Cipher_Mode::create(algo_spec, Cipher_Dir::Encryption, prov);
2,498✔
174
      if(mode) {
2,498✔
175
         providers.push_back(prov);  // available
1,247✔
176
      }
177
   }
2,498✔
178
   return providers;
1,249✔
179
}
1,249✔
180

181
size_t Cipher_Mode::calculate_final_input_bytes(size_t final_block_length, size_t offset) const {
156,613✔
182
   if(offset > final_block_length) {
156,613✔
183
      throw Invalid_Argument(Botan::fmt("invalid offset in finalization of {}", name()));
×
184
   }
185

186
   const size_t final_input_bytes = final_block_length - offset;
156,613✔
187
   BOTAN_DEBUG_ASSERT(final_input_bytes >= minimum_final_size());
156,613✔
188
   return final_input_bytes;
156,613✔
189
}
190

191
}  // namespace Botan
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