Botan 3.13.0
Crypto and TLS for C&
cipher_mode.cpp
Go to the documentation of this file.
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/exceptn.h>
11#include <botan/internal/parsing.h>
12#include <botan/internal/scan_name.h>
13#include <botan/internal/stream_mode.h>
14#include <memory>
15#include <sstream>
16#include <utility>
17
18#if defined(BOTAN_HAS_BLOCK_CIPHER)
19 #include <botan/block_cipher.h>
20#endif
21
22#if defined(BOTAN_HAS_AEAD_MODES)
23 #include <botan/aead.h>
24#endif
25
26#if defined(BOTAN_HAS_MODE_CBC)
27 #include <botan/internal/cbc.h>
28#endif
29
30#if defined(BOTAN_HAS_MODE_CFB)
31 #include <botan/internal/cfb.h>
32#endif
33
34#if defined(BOTAN_HAS_MODE_XTS)
35 #include <botan/internal/xts.h>
36#endif
37
38#if defined(BOTAN_HAS_COMMONCRYPTO)
39 #include <botan/internal/commoncrypto.h>
40#endif
41
42namespace Botan {
43
44std::unique_ptr<Cipher_Mode> Cipher_Mode::create_or_throw(std::string_view algo,
45 Cipher_Dir direction,
46 std::string_view provider) {
47 if(auto mode = Cipher_Mode::create(algo, direction, provider)) {
48 return mode;
49 }
50
51 throw Lookup_Error("Cipher mode", algo, provider);
52}
53
54std::unique_ptr<Cipher_Mode> Cipher_Mode::create(std::string_view algo,
55 Cipher_Dir direction,
56 std::string_view provider) {
57#if defined(BOTAN_HAS_COMMONCRYPTO)
58 if(provider.empty() || provider == "commoncrypto") {
59 if(auto cm = make_commoncrypto_cipher_mode(algo, direction))
60 return cm;
61
62 if(!provider.empty())
63 return nullptr;
64 }
65#endif
66
67 if(provider != "base" && !provider.empty()) {
68 return nullptr;
69 }
70
71#if defined(BOTAN_HAS_STREAM_CIPHER)
72 if(auto sc = StreamCipher::create(algo)) {
73 return std::make_unique<Stream_Cipher_Mode>(std::move(sc));
74 }
75#endif
76
77#if defined(BOTAN_HAS_AEAD_MODES)
78 if(auto aead = AEAD_Mode::create(algo, direction)) {
79 return aead;
80 }
81#endif
82
83 if(algo.find('/') != std::string::npos) {
84 const std::vector<std::string> algo_parts = split_on(algo, '/');
85 if(algo_parts.size() < 2) {
86 return std::unique_ptr<Cipher_Mode>();
87 }
88 const std::string_view cipher_name = algo_parts[0];
89 const std::vector<std::string> mode_info = parse_algorithm_name(algo_parts[1]);
90
91 if(mode_info.empty()) {
92 return std::unique_ptr<Cipher_Mode>();
93 }
94
95 std::ostringstream mode_name;
96
97 mode_name << mode_info[0] << '(' << cipher_name;
98 for(size_t i = 1; i < mode_info.size(); ++i) {
99 mode_name << ',' << mode_info[i];
100 }
101 for(size_t i = 2; i < algo_parts.size(); ++i) {
102 mode_name << ',' << algo_parts[i];
103 }
104 mode_name << ')';
105
106 return Cipher_Mode::create(mode_name.str(), direction, provider);
107 }
108
109#if defined(BOTAN_HAS_BLOCK_CIPHER)
110
111 const SCAN_Name spec(algo);
112
113 if(spec.arg_count() == 0) {
114 return std::unique_ptr<Cipher_Mode>();
115 }
116
117 auto bc = BlockCipher::create(spec.arg(0), provider);
118
119 if(!bc) {
120 return std::unique_ptr<Cipher_Mode>();
121 }
122
123 #if defined(BOTAN_HAS_MODE_CBC)
124 if(spec.algo_name() == "CBC") {
125 const std::string padding = spec.arg(1, "PKCS7");
126
127 if(padding == "CTS") {
128 if(direction == Cipher_Dir::Encryption) {
129 return std::make_unique<CTS_Encryption>(std::move(bc));
130 } else {
131 return std::make_unique<CTS_Decryption>(std::move(bc));
132 }
133 } else {
134 auto pad = BlockCipherModePaddingMethod::create(padding);
135
136 if(pad) {
137 if(direction == Cipher_Dir::Encryption) {
138 return std::make_unique<CBC_Encryption>(std::move(bc), std::move(pad));
139 } else {
140 return std::make_unique<CBC_Decryption>(std::move(bc), std::move(pad));
141 }
142 }
143 }
144 }
145 #endif
146
147 #if defined(BOTAN_HAS_MODE_XTS)
148 if(spec.algo_name() == "XTS") {
149 if(direction == Cipher_Dir::Encryption) {
150 return std::make_unique<XTS_Encryption>(std::move(bc));
151 } else {
152 return std::make_unique<XTS_Decryption>(std::move(bc));
153 }
154 }
155 #endif
156
157 #if defined(BOTAN_HAS_MODE_CFB)
158 if(spec.algo_name() == "CFB") {
159 const size_t feedback_bits = spec.arg_as_integer(1, 8 * bc->block_size());
160 if(direction == Cipher_Dir::Encryption) {
161 return std::make_unique<CFB_Encryption>(std::move(bc), feedback_bits);
162 } else {
163 return std::make_unique<CFB_Decryption>(std::move(bc), feedback_bits);
164 }
165 }
166 #endif
167
168#endif
169
170 return std::unique_ptr<Cipher_Mode>();
171}
172
173//static
174std::vector<std::string> Cipher_Mode::providers(std::string_view algo_spec) {
175 const std::vector<std::string>& possible = {"base", "commoncrypto"};
176 std::vector<std::string> providers;
177 for(auto&& prov : possible) {
178 auto mode = Cipher_Mode::create(algo_spec, Cipher_Dir::Encryption, prov);
179 if(mode) {
180 providers.push_back(prov); // available
181 }
182 }
183 return providers;
184}
185
186} // namespace Botan
static std::unique_ptr< AEAD_Mode > create(std::string_view algo, Cipher_Dir direction, std::string_view provider="")
Definition aead.cpp:63
static std::unique_ptr< BlockCipherModePaddingMethod > create(std::string_view algo_spec)
Definition mode_pad.cpp:26
static std::unique_ptr< BlockCipher > create(std::string_view algo_spec, std::string_view provider="")
static std::unique_ptr< Cipher_Mode > create(std::string_view algo, Cipher_Dir direction, std::string_view provider="")
virtual std::string provider() const
static std::unique_ptr< Cipher_Mode > create_or_throw(std::string_view algo, Cipher_Dir direction, std::string_view provider="")
static std::vector< std::string > providers(std::string_view algo_spec)
std::string arg(size_t i) const
size_t arg_count() const
Definition scan_name.h:43
const std::string & algo_name() const
Definition scan_name.h:38
size_t arg_as_integer(size_t i, size_t def_value) const
static std::unique_ptr< StreamCipher > create(std::string_view algo_spec, std::string_view provider="")
std::vector< std::string > split_on(std::string_view str, char delim)
Definition parsing.cpp:141
std::unique_ptr< Cipher_Mode > make_commoncrypto_cipher_mode(std::string_view name, Cipher_Dir direction)
std::vector< std::string > parse_algorithm_name(std::string_view scan_name)
Definition parsing.cpp:87