Botan 2.19.3
Crypto and TLS for C&
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
40namespace Botan {
41
42void 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
50std::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
60std::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}
#define BOTAN_UNUSED(...)
Definition assert.h:142
virtual void set_associated_data(const uint8_t ad[], size_t ad_len)=0
static std::unique_ptr< AEAD_Mode > create_or_throw(const std::string &algo, Cipher_Dir direction, const std::string &provider="")
Definition aead.cpp:50
static std::unique_ptr< AEAD_Mode > create(const std::string &algo, Cipher_Dir direction, const std::string &provider="")
Definition aead.cpp:60
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< BlockCipher > create(const std::string &algo_spec, const std::string &provider="")
virtual std::string provider() const
std::string arg(size_t i) const
size_t arg_count() const
Definition scan_name.h:56
const std::string & algo_name() const
Definition scan_name.h:51
size_t arg_as_integer(size_t i, size_t def_value) const
virtual std::string name() const =0
std::vector< std::string > split_on(const std::string &str, char delim)
Definition parsing.cpp:148
@ ENCRYPTION
Definition cipher_mode.h:23
std::vector< std::string > parse_algorithm_name(const std::string &namex)
Definition parsing.cpp:95