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