Botan 1.10.17
core_modes.cpp
Go to the documentation of this file.
1/*
2* Core Engine
3* (C) 1999-2007,2011 Jack Lloyd
4*
5* Distributed under the terms of the Botan license
6*/
7
8#include <botan/internal/core_engine.h>
9#include <botan/parsing.h>
10#include <botan/filters.h>
11#include <botan/algo_factory.h>
12#include <botan/mode_pad.h>
13#include <memory>
14
15#if defined(BOTAN_HAS_ECB)
16 #include <botan/ecb.h>
17#endif
18
19#if defined(BOTAN_HAS_CBC)
20 #include <botan/cbc.h>
21#endif
22
23#if defined(BOTAN_HAS_CTS)
24 #include <botan/cts.h>
25#endif
26
27#if defined(BOTAN_HAS_CFB)
28 #include <botan/cfb.h>
29#endif
30
31#if defined(BOTAN_HAS_OFB)
32 #include <botan/ofb.h>
33#endif
34
35#if defined(BOTAN_HAS_CTR_BE)
36 #include <botan/ctr.h>
37#endif
38
39#if defined(BOTAN_HAS_EAX)
40 #include <botan/eax.h>
41#endif
42
43#if defined(BOTAN_HAS_XTS)
44 #include <botan/xts.h>
45#endif
46
47namespace Botan {
48
49namespace {
50
51/**
52* Get a block cipher padding method by name
53*/
54BlockCipherModePaddingMethod* get_bc_pad(const std::string& algo_spec,
55 const std::string& def_if_empty)
56 {
57#if defined(BOTAN_HAS_CIPHER_MODE_PADDING)
58 if(algo_spec == "NoPadding" || (algo_spec == "" && def_if_empty == "NoPadding"))
59 return new Null_Padding;
60
61 if(algo_spec == "PKCS7" || (algo_spec == "" && def_if_empty == "PKCS7"))
62 return new PKCS7_Padding;
63
64 if(algo_spec == "OneAndZeros")
65 return new OneAndZeros_Padding;
66
67 if(algo_spec == "X9.23")
68 return new ANSI_X923_Padding;
69
70#endif
71
72 throw Algorithm_Not_Found(algo_spec);
73 }
74
75}
76
78 Cipher_Dir direction,
79 const std::string& mode,
80 const std::string& padding)
81 {
82#if defined(BOTAN_HAS_OFB)
83 if(mode == "OFB")
84 return new StreamCipher_Filter(new OFB(block_cipher->clone()));
85#endif
86
87#if defined(BOTAN_HAS_CTR_BE)
88 if(mode == "CTR-BE")
89 return new StreamCipher_Filter(new CTR_BE(block_cipher->clone()));
90#endif
91
92#if defined(BOTAN_HAS_ECB)
93 if(mode == "ECB" || mode == "")
94 {
95 if(direction == ENCRYPTION)
96 return new ECB_Encryption(block_cipher->clone(),
97 get_bc_pad(padding, "NoPadding"));
98 else
99 return new ECB_Decryption(block_cipher->clone(),
100 get_bc_pad(padding, "NoPadding"));
101 }
102#endif
103
104 if(mode == "CBC")
105 {
106 if(padding == "CTS")
107 {
108#if defined(BOTAN_HAS_CTS)
109 if(direction == ENCRYPTION)
110 return new CTS_Encryption(block_cipher->clone());
111 else
112 return new CTS_Decryption(block_cipher->clone());
113#else
114 return 0;
115#endif
116 }
117
118#if defined(BOTAN_HAS_CBC)
119 if(direction == ENCRYPTION)
120 return new CBC_Encryption(block_cipher->clone(),
121 get_bc_pad(padding, "PKCS7"));
122 else
123 return new CBC_Decryption(block_cipher->clone(),
124 get_bc_pad(padding, "PKCS7"));
125#else
126 return 0;
127#endif
128 }
129
130#if defined(BOTAN_HAS_XTS)
131 if(mode == "XTS")
132 {
133 if(direction == ENCRYPTION)
134 return new XTS_Encryption(block_cipher->clone());
135 else
136 return new XTS_Decryption(block_cipher->clone());
137 }
138#endif
139
140 if(mode.find("CFB") != std::string::npos ||
141 mode.find("EAX") != std::string::npos)
142 {
143 size_t bits = 0;
144
145 std::vector<std::string> algo_info = parse_algorithm_name(mode);
146 std::string mode_name = algo_info[0];
147 if(algo_info.size() == 1)
148 bits = 8 * block_cipher->block_size();
149 else if(algo_info.size() == 2)
150 bits = to_u32bit(algo_info[1]);
151 else
152 return 0;
153
154#if defined(BOTAN_HAS_CFB)
155 if(mode_name == "CFB")
156 {
157 if(direction == ENCRYPTION)
158 return new CFB_Encryption(block_cipher->clone(), bits);
159 else
160 return new CFB_Decryption(block_cipher->clone(), bits);
161 }
162#endif
163
164#if defined(BOTAN_HAS_EAX)
165 if(mode_name == "EAX")
166 {
167 if(direction == ENCRYPTION)
168 return new EAX_Encryption(block_cipher->clone(), bits);
169 else
170 return new EAX_Decryption(block_cipher->clone(), bits);
171 }
172#endif
173 }
174
175 return 0;
176 }
177
178/*
179* Get a cipher object
180*/
181Keyed_Filter* Core_Engine::get_cipher(const std::string& algo_spec,
182 Cipher_Dir direction,
184 {
185 std::vector<std::string> algo_parts = split_on(algo_spec, '/');
186 if(algo_parts.empty())
187 throw Invalid_Algorithm_Name(algo_spec);
188
189 const std::string cipher_name = algo_parts[0];
190
191 // check if it is a stream cipher first (easy case)
192 const StreamCipher* stream_cipher = af.prototype_stream_cipher(cipher_name);
193 if(stream_cipher)
194 return new StreamCipher_Filter(stream_cipher->clone());
195
196 const BlockCipher* block_cipher = af.prototype_block_cipher(cipher_name);
197 if(!block_cipher)
198 return 0;
199
200 if(algo_parts.size() >= 4)
201 return 0; // 4 part mode, not something we know about
202
203 if(algo_parts.size() < 2)
204 throw Lookup_Error("Cipher specification '" + algo_spec +
205 "' is missing mode identifier");
206
207 std::string mode = algo_parts[1];
208
209 std::string padding;
210 if(algo_parts.size() == 3)
211 padding = algo_parts[2];
212 else
213 padding = (mode == "CBC") ? "PKCS7" : "NoPadding";
214
215 if(mode == "ECB" && padding == "CTS")
216 return 0;
217 else if((mode != "CBC" && mode != "ECB") && padding != "NoPadding")
218 throw Invalid_Algorithm_Name(algo_spec);
219
220 Keyed_Filter* filt = get_cipher_mode(block_cipher, direction, mode, padding);
221 if(filt)
222 return filt;
223
224 throw Algorithm_Not_Found(cipher_name + "/" + mode + "/" + padding);
225 }
226
227}
const BlockCipher * prototype_block_cipher(const std::string &algo_spec, const std::string &provider="")
const StreamCipher * prototype_stream_cipher(const std::string &algo_spec, const std::string &provider="")
virtual BlockCipher * clone() const =0
virtual size_t block_size() const =0
CBC_Decryption(BlockCipher *cipher, BlockCipherModePaddingMethod *padding)
Definition cbc.cpp:115
CBC_Encryption(BlockCipher *cipher, BlockCipherModePaddingMethod *padding)
Definition cbc.cpp:17
CFB_Decryption(BlockCipher *cipher, size_t feedback=0)
Definition cfb.cpp:95
CFB_Encryption(BlockCipher *cipher, size_t feedback=0)
Definition cfb.cpp:18
CTR_BE(BlockCipher *cipher)
Definition ctr.cpp:17
CTS_Decryption(BlockCipher *cipher)
Definition cts.cpp:117
CTS_Encryption(BlockCipher *cipher)
Definition cts.cpp:17
Keyed_Filter * get_cipher(const std::string &, Cipher_Dir, Algorithm_Factory &)
EAX_Decryption(BlockCipher *ciph, size_t tag_size=0)
Definition eax_dec.cpp:18
EAX_Encryption(BlockCipher *ciph, size_t tag_size=0)
Definition eax.h:107
ECB_Decryption(BlockCipher *ciph, BlockCipherModePaddingMethod *pad)
Definition ecb.cpp:112
ECB_Encryption(BlockCipher *ciph, BlockCipherModePaddingMethod *pad)
Definition ecb.cpp:15
OFB(BlockCipher *cipher)
Definition ofb.cpp:17
StreamCipher_Filter(StreamCipher *cipher_obj)
Definition algo_filt.cpp:17
virtual StreamCipher * clone() const =0
XTS_Decryption(BlockCipher *ciph)
Definition xts.cpp:219
XTS_Encryption(BlockCipher *ciph)
Definition xts.cpp:47
std::vector< std::string > parse_algorithm_name(const std::string &namex)
Definition parsing.cpp:96
u32bit to_u32bit(const std::string &number)
Definition parsing.cpp:18
std::vector< std::string > split_on(const std::string &str, char delim)
Definition parsing.cpp:152
Cipher_Dir
Definition sym_algo.h:87
@ ENCRYPTION
Definition sym_algo.h:87
Keyed_Filter * get_cipher_mode(const BlockCipher *block_cipher, Cipher_Dir direction, const std::string &mode, const std::string &padding)
Algorithm_Not_Found(const std::string &name)
Definition exceptn.h:111
Invalid_Algorithm_Name(const std::string &name)
Definition exceptn.h:121
Lookup_Error(const std::string &err)
Definition exceptn.h:37