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