Botan  2.18.1
Crypto and TLS for C++11
aead.cpp
Go to the documentation of this file.
1 /*
2 * (C) 2013,2015 Jack Lloyd
3 *
4 * Botan is released under the Simplified BSD License (see license.txt)
5 */
6 
7 #include <botan/aead.h>
8 #include <botan/scan_name.h>
9 #include <botan/parsing.h>
10 #include <sstream>
11 
12 #if defined(BOTAN_HAS_BLOCK_CIPHER)
13  #include <botan/block_cipher.h>
14 #endif
15 
16 #if defined(BOTAN_HAS_AEAD_CCM)
17  #include <botan/ccm.h>
18 #endif
19 
20 #if defined(BOTAN_HAS_AEAD_CHACHA20_POLY1305)
21  #include <botan/chacha20poly1305.h>
22 #endif
23 
24 #if defined(BOTAN_HAS_AEAD_EAX)
25  #include <botan/eax.h>
26 #endif
27 
28 #if defined(BOTAN_HAS_AEAD_GCM)
29  #include <botan/gcm.h>
30 #endif
31 
32 #if defined(BOTAN_HAS_AEAD_OCB)
33  #include <botan/ocb.h>
34 #endif
35 
36 #if defined(BOTAN_HAS_AEAD_SIV)
37  #include <botan/siv.h>
38 #endif
39 
40 namespace Botan {
41 
42 void AEAD_Mode::set_associated_data_n(size_t i, const uint8_t ad[], size_t ad_len)
43  {
44  if(i == 0)
45  this->set_associated_data(ad, ad_len);
46  else
47  throw Invalid_Argument("AEAD '" + name() + "' does not support multiple associated data");
48  }
49 
50 std::unique_ptr<AEAD_Mode> AEAD_Mode::create_or_throw(const std::string& algo,
51  Cipher_Dir dir,
52  const std::string& provider)
53  {
54  if(auto aead = AEAD_Mode::create(algo, dir, provider))
55  return aead;
56 
57  throw Lookup_Error("AEAD", algo, provider);
58  }
59 
60 std::unique_ptr<AEAD_Mode> AEAD_Mode::create(const std::string& algo,
61  Cipher_Dir dir,
62  const std::string& provider)
63  {
65 #if defined(BOTAN_HAS_AEAD_CHACHA20_POLY1305)
66  if(algo == "ChaCha20Poly1305")
67  {
68  if(dir == ENCRYPTION)
69  return std::unique_ptr<AEAD_Mode>(new ChaCha20Poly1305_Encryption);
70  else
71  return std::unique_ptr<AEAD_Mode>(new ChaCha20Poly1305_Decryption);
72 
73  }
74 #endif
75 
76  if(algo.find('/') != std::string::npos)
77  {
78  const std::vector<std::string> algo_parts = split_on(algo, '/');
79  const std::string cipher_name = algo_parts[0];
80  const std::vector<std::string> mode_info = parse_algorithm_name(algo_parts[1]);
81 
82  if(mode_info.empty())
83  return std::unique_ptr<AEAD_Mode>();
84 
85  std::ostringstream alg_args;
86 
87  alg_args << '(' << cipher_name;
88  for(size_t i = 1; i < mode_info.size(); ++i)
89  alg_args << ',' << mode_info[i];
90  for(size_t i = 2; i < algo_parts.size(); ++i)
91  alg_args << ',' << algo_parts[i];
92  alg_args << ')';
93 
94  const std::string mode_name = mode_info[0] + alg_args.str();
95  return AEAD_Mode::create(mode_name, dir);
96  }
97 
98 #if defined(BOTAN_HAS_BLOCK_CIPHER)
99 
100  SCAN_Name req(algo);
101 
102  if(req.arg_count() == 0)
103  {
104  return std::unique_ptr<AEAD_Mode>();
105  }
106 
107  std::unique_ptr<BlockCipher> bc(BlockCipher::create(req.arg(0), provider));
108 
109  if(!bc)
110  {
111  return std::unique_ptr<AEAD_Mode>();
112  }
113 
114 #if defined(BOTAN_HAS_AEAD_CCM)
115  if(req.algo_name() == "CCM")
116  {
117  size_t tag_len = req.arg_as_integer(1, 16);
118  size_t L_len = req.arg_as_integer(2, 3);
119  if(dir == ENCRYPTION)
120  return std::unique_ptr<AEAD_Mode>(new CCM_Encryption(bc.release(), tag_len, L_len));
121  else
122  return std::unique_ptr<AEAD_Mode>(new CCM_Decryption(bc.release(), tag_len, L_len));
123  }
124 #endif
125 
126 #if defined(BOTAN_HAS_AEAD_GCM)
127  if(req.algo_name() == "GCM")
128  {
129  size_t tag_len = req.arg_as_integer(1, 16);
130  if(dir == ENCRYPTION)
131  return std::unique_ptr<AEAD_Mode>(new GCM_Encryption(bc.release(), tag_len));
132  else
133  return std::unique_ptr<AEAD_Mode>(new GCM_Decryption(bc.release(), tag_len));
134  }
135 #endif
136 
137 #if defined(BOTAN_HAS_AEAD_OCB)
138  if(req.algo_name() == "OCB")
139  {
140  size_t tag_len = req.arg_as_integer(1, 16);
141  if(dir == ENCRYPTION)
142  return std::unique_ptr<AEAD_Mode>(new OCB_Encryption(bc.release(), tag_len));
143  else
144  return std::unique_ptr<AEAD_Mode>(new OCB_Decryption(bc.release(), tag_len));
145  }
146 #endif
147 
148 #if defined(BOTAN_HAS_AEAD_EAX)
149  if(req.algo_name() == "EAX")
150  {
151  size_t tag_len = req.arg_as_integer(1, bc->block_size());
152  if(dir == ENCRYPTION)
153  return std::unique_ptr<AEAD_Mode>(new EAX_Encryption(bc.release(), tag_len));
154  else
155  return std::unique_ptr<AEAD_Mode>(new EAX_Decryption(bc.release(), tag_len));
156  }
157 #endif
158 
159 #if defined(BOTAN_HAS_AEAD_SIV)
160  if(req.algo_name() == "SIV")
161  {
162  if(dir == ENCRYPTION)
163  return std::unique_ptr<AEAD_Mode>(new SIV_Encryption(bc.release()));
164  else
165  return std::unique_ptr<AEAD_Mode>(new SIV_Decryption(bc.release()));
166  }
167 #endif
168 
169 #endif
170 
171  return std::unique_ptr<AEAD_Mode>();
172  }
173 
174 
175 
176 }
size_t arg_count() const
Definition: scan_name.h:56
std::vector< std::string > split_on(const std::string &str, char delim)
Definition: parsing.cpp:148
size_t arg_as_integer(size_t i, size_t def_value) const
Definition: scan_name.cpp:142
virtual std::string name() const =0
std::string arg(size_t i) const
Definition: scan_name.cpp:127
static std::unique_ptr< AEAD_Mode > create(const std::string &algo, Cipher_Dir direction, const std::string &provider="")
Definition: aead.cpp:60
std::vector< std::string > parse_algorithm_name(const std::string &namex)
Definition: parsing.cpp:95
Definition: alg_id.cpp:13
#define BOTAN_UNUSED(...)
Definition: assert.h:142
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:51
Cipher_Dir
Definition: cipher_mode.h:23
virtual std::string provider() const
Definition: cipher_mode.h:180
virtual void set_associated_data(const uint8_t ad[], size_t ad_len)=0
virtual void set_associated_data_n(size_t i, const uint8_t ad[], size_t ad_len)
Definition: aead.cpp:42
static std::unique_ptr< AEAD_Mode > create_or_throw(const std::string &algo, Cipher_Dir direction, const std::string &provider="")
Definition: aead.cpp:50