Botan  2.7.0
Crypto and TLS for C++11
stream_cipher.cpp
Go to the documentation of this file.
1 /*
2 * Stream Ciphers
3 * (C) 2015,2016 Jack Lloyd
4 *
5 * Botan is released under the Simplified BSD License (see license.txt)
6 */
7 
8 #include <botan/stream_cipher.h>
9 #include <botan/scan_name.h>
10 #include <botan/exceptn.h>
11 
12 #if defined(BOTAN_HAS_CHACHA)
13  #include <botan/chacha.h>
14 #endif
15 
16 #if defined(BOTAN_HAS_SALSA20)
17  #include <botan/salsa20.h>
18 #endif
19 
20 #if defined(BOTAN_HAS_SHAKE_CIPHER)
21  #include <botan/shake_cipher.h>
22 #endif
23 
24 #if defined(BOTAN_HAS_CTR_BE)
25  #include <botan/ctr.h>
26 #endif
27 
28 #if defined(BOTAN_HAS_OFB)
29  #include <botan/ofb.h>
30 #endif
31 
32 #if defined(BOTAN_HAS_RC4)
33  #include <botan/rc4.h>
34 #endif
35 
36 #if defined(BOTAN_HAS_OPENSSL)
37  #include <botan/internal/openssl.h>
38 #endif
39 
40 namespace Botan {
41 
42 std::unique_ptr<StreamCipher> StreamCipher::create(const std::string& algo_spec,
43  const std::string& provider)
44  {
45  const SCAN_Name req(algo_spec);
46 
47 #if defined(BOTAN_HAS_CTR_BE)
48  if((req.algo_name() == "CTR-BE" || req.algo_name() == "CTR") && req.arg_count_between(1,2))
49  {
50  if(provider.empty() || provider == "base")
51  {
52  auto cipher = BlockCipher::create(req.arg(0));
53  if(cipher)
54  {
55  size_t ctr_size = req.arg_as_integer(1, cipher->block_size());
56  return std::unique_ptr<StreamCipher>(new CTR_BE(cipher.release(), ctr_size));
57  }
58  }
59  }
60 #endif
61 
62 #if defined(BOTAN_HAS_CHACHA)
63  if(req.algo_name() == "ChaCha")
64  {
65  if(provider.empty() || provider == "base")
66  return std::unique_ptr<StreamCipher>(new ChaCha(req.arg_as_integer(0, 20)));
67  }
68 
69  if(req.algo_name() == "ChaCha20")
70  {
71  if(provider.empty() || provider == "base")
72  return std::unique_ptr<StreamCipher>(new ChaCha(20));
73  }
74 #endif
75 
76 #if defined(BOTAN_HAS_SALSA20)
77  if(req.algo_name() == "Salsa20")
78  {
79  if(provider.empty() || provider == "base")
80  return std::unique_ptr<StreamCipher>(new Salsa20);
81  }
82 #endif
83 
84 #if defined(BOTAN_HAS_SHAKE_CIPHER)
85  if(req.algo_name() == "SHAKE-128")
86  {
87  if(provider.empty() || provider == "base")
88  return std::unique_ptr<StreamCipher>(new SHAKE_128_Cipher);
89  }
90 #endif
91 
92 #if defined(BOTAN_HAS_OFB)
93  if(req.algo_name() == "OFB" && req.arg_count() == 1)
94  {
95  if(provider.empty() || provider == "base")
96  {
97  if(auto c = BlockCipher::create(req.arg(0)))
98  return std::unique_ptr<StreamCipher>(new OFB(c.release()));
99  }
100  }
101 #endif
102 
103 #if defined(BOTAN_HAS_RC4)
104 
105  if(req.algo_name() == "RC4" ||
106  req.algo_name() == "ARC4" ||
107  req.algo_name() == "MARK-4")
108  {
109  const size_t skip = (req.algo_name() == "MARK-4") ? 256 : req.arg_as_integer(0, 0);
110 
111 #if defined(BOTAN_HAS_OPENSSL)
112  if(provider.empty() || provider == "openssl")
113  {
114  return std::unique_ptr<StreamCipher>(make_openssl_rc4(skip));
115  }
116 #endif
117 
118  if(provider.empty() || provider == "base")
119  {
120  return std::unique_ptr<StreamCipher>(new RC4(skip));
121  }
122  }
123 
124 #endif
125 
126  BOTAN_UNUSED(req);
128 
129  return nullptr;
130  }
131 
132 //static
133 std::unique_ptr<StreamCipher>
134 StreamCipher::create_or_throw(const std::string& algo,
135  const std::string& provider)
136  {
137  if(auto sc = StreamCipher::create(algo, provider))
138  {
139  return sc;
140  }
141  throw Lookup_Error("Stream cipher", algo, provider);
142  }
143 
144 std::vector<std::string> StreamCipher::providers(const std::string& algo_spec)
145  {
146  return probe_providers_of<StreamCipher>(algo_spec, {"base", "openssl"});
147  }
148 
149 }
size_t arg_count() const
Definition: scan_name.h:49
static std::unique_ptr< StreamCipher > create_or_throw(const std::string &algo_spec, const std::string &provider="")
Definition: ofb.h:19
size_t arg_as_integer(size_t i, size_t def_value) const
Definition: scan_name.cpp:137
virtual void cipher(const uint8_t in[], uint8_t out[], size_t len)=0
virtual std::string provider() const
std::string arg(size_t i) const
Definition: scan_name.cpp:122
Definition: rc4.h:19
Definition: alg_id.cpp:13
static std::vector< std::string > providers(const std::string &algo_spec)
#define BOTAN_UNUSED(...)
Definition: assert.h:130
static std::unique_ptr< BlockCipher > create(const std::string &algo_spec, const std::string &provider="")
const std::string & algo_name() const
Definition: scan_name.h:44
bool arg_count_between(size_t lower, size_t upper) const
Definition: scan_name.h:56
static std::unique_ptr< StreamCipher > create(const std::string &algo_spec, const std::string &provider="")