Coverage Report

Created: 2021-02-21 07:20

/src/botan/src/lib/modes/aead/aead.cpp
Line
Count
Source (jump to first uncovered line)
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/internal/scan_name.h>
9
#include <botan/internal/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/internal/ccm.h>
18
#endif
19
20
#if defined(BOTAN_HAS_AEAD_CHACHA20_POLY1305)
21
  #include <botan/internal/chacha20poly1305.h>
22
#endif
23
24
#if defined(BOTAN_HAS_AEAD_EAX)
25
  #include <botan/internal/eax.h>
26
#endif
27
28
#if defined(BOTAN_HAS_AEAD_GCM)
29
  #include <botan/internal/gcm.h>
30
#endif
31
32
#if defined(BOTAN_HAS_AEAD_OCB)
33
  #include <botan/internal/ocb.h>
34
#endif
35
36
#if defined(BOTAN_HAS_AEAD_SIV)
37
  #include <botan/internal/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
0
   {
44
0
   if(i == 0)
45
0
      this->set_associated_data(ad, ad_len);
46
0
   else
47
0
      throw Invalid_Argument("AEAD '" + name() + "' does not support multiple associated data");
48
0
   }
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
1.82k
   {
54
1.82k
   if(auto aead = AEAD_Mode::create(algo, dir, provider))
55
1.82k
      return aead;
56
57
0
   throw Lookup_Error("AEAD", algo, provider);
58
0
   }
59
60
std::unique_ptr<AEAD_Mode> AEAD_Mode::create(const std::string& algo,
61
                                             Cipher_Dir dir,
62
                                             const std::string& provider)
63
3.54k
   {
64
3.54k
   BOTAN_UNUSED(provider);
65
3.54k
#if defined(BOTAN_HAS_AEAD_CHACHA20_POLY1305)
66
3.54k
   if(algo == "ChaCha20Poly1305")
67
109
      {
68
109
      if(dir == ENCRYPTION)
69
56
         return std::unique_ptr<AEAD_Mode>(new ChaCha20Poly1305_Encryption);
70
53
      else
71
53
         return std::unique_ptr<AEAD_Mode>(new ChaCha20Poly1305_Decryption);
72
73
3.43k
      }
74
3.43k
#endif
75
76
3.43k
   if(algo.find('/') != std::string::npos)
77
1.71k
      {
78
1.71k
      const std::vector<std::string> algo_parts = split_on(algo, '/');
79
1.71k
      const std::string cipher_name = algo_parts[0];
80
1.71k
      const std::vector<std::string> mode_info = parse_algorithm_name(algo_parts[1]);
81
82
1.71k
      if(mode_info.empty())
83
0
         return std::unique_ptr<AEAD_Mode>();
84
85
1.71k
      std::ostringstream alg_args;
86
87
1.71k
      alg_args << '(' << cipher_name;
88
2.45k
      for(size_t i = 1; i < mode_info.size(); ++i)
89
731
         alg_args << ',' << mode_info[i];
90
1.71k
      for(size_t i = 2; i < algo_parts.size(); ++i)
91
0
         alg_args << ',' << algo_parts[i];
92
1.71k
      alg_args << ')';
93
94
1.71k
      const std::string mode_name = mode_info[0] + alg_args.str();
95
1.71k
      return AEAD_Mode::create(mode_name, dir);
96
1.71k
      }
97
98
1.71k
#if defined(BOTAN_HAS_BLOCK_CIPHER)
99
100
1.71k
   SCAN_Name req(algo);
101
102
1.71k
   if(req.arg_count() == 0)
103
0
      {
104
0
      return std::unique_ptr<AEAD_Mode>();
105
0
      }
106
107
1.71k
   std::unique_ptr<BlockCipher> bc(BlockCipher::create(req.arg(0), provider));
108
109
1.71k
   if(!bc)
110
0
      {
111
0
      return std::unique_ptr<AEAD_Mode>();
112
0
      }
113
114
1.71k
#if defined(BOTAN_HAS_AEAD_CCM)
115
1.71k
   if(req.algo_name() == "CCM")
116
375
      {
117
375
      size_t tag_len = req.arg_as_integer(1, 16);
118
375
      size_t L_len = req.arg_as_integer(2, 3);
119
375
      if(dir == ENCRYPTION)
120
184
         return std::unique_ptr<AEAD_Mode>(new CCM_Encryption(bc.release(), tag_len, L_len));
121
191
      else
122
191
         return std::unique_ptr<AEAD_Mode>(new CCM_Decryption(bc.release(), tag_len, L_len));
123
1.34k
      }
124
1.34k
#endif
125
126
1.34k
#if defined(BOTAN_HAS_AEAD_GCM)
127
1.34k
   if(req.algo_name() == "GCM")
128
964
      {
129
964
      size_t tag_len = req.arg_as_integer(1, 16);
130
964
      if(dir == ENCRYPTION)
131
654
         return std::unique_ptr<AEAD_Mode>(new GCM_Encryption(bc.release(), tag_len));
132
310
      else
133
310
         return std::unique_ptr<AEAD_Mode>(new GCM_Decryption(bc.release(), tag_len));
134
380
      }
135
380
#endif
136
137
380
#if defined(BOTAN_HAS_AEAD_OCB)
138
380
   if(req.algo_name() == "OCB")
139
380
      {
140
380
      size_t tag_len = req.arg_as_integer(1, 16);
141
380
      if(dir == ENCRYPTION)
142
173
         return std::unique_ptr<AEAD_Mode>(new OCB_Encryption(bc.release(), tag_len));
143
207
      else
144
207
         return std::unique_ptr<AEAD_Mode>(new OCB_Decryption(bc.release(), tag_len));
145
0
      }
146
0
#endif
147
148
0
#if defined(BOTAN_HAS_AEAD_EAX)
149
0
   if(req.algo_name() == "EAX")
150
0
      {
151
0
      size_t tag_len = req.arg_as_integer(1, bc->block_size());
152
0
      if(dir == ENCRYPTION)
153
0
         return std::unique_ptr<AEAD_Mode>(new EAX_Encryption(bc.release(), tag_len));
154
0
      else
155
0
         return std::unique_ptr<AEAD_Mode>(new EAX_Decryption(bc.release(), tag_len));
156
0
      }
157
0
#endif
158
159
0
#if defined(BOTAN_HAS_AEAD_SIV)
160
0
   if(req.algo_name() == "SIV")
161
0
      {
162
0
      if(dir == ENCRYPTION)
163
0
         return std::unique_ptr<AEAD_Mode>(new SIV_Encryption(bc.release()));
164
0
      else
165
0
         return std::unique_ptr<AEAD_Mode>(new SIV_Decryption(bc.release()));
166
0
      }
167
0
#endif
168
169
0
#endif
170
171
0
   return std::unique_ptr<AEAD_Mode>();
172
0
   }
173
174
}