Coverage Report

Created: 2023-09-25 06:34

/src/botan/src/lib/mac/mac.cpp
Line
Count
Source (jump to first uncovered line)
1
/*
2
* Message Authentication Code base class
3
* (C) 1999-2008 Jack Lloyd
4
*
5
* Botan is released under the Simplified BSD License (see license.txt)
6
*/
7
8
#include <botan/mac.h>
9
10
#include <botan/exceptn.h>
11
#include <botan/mem_ops.h>
12
#include <botan/internal/scan_name.h>
13
14
#if defined(BOTAN_HAS_CMAC)
15
   #include <botan/internal/cmac.h>
16
#endif
17
18
#if defined(BOTAN_HAS_GMAC)
19
   #include <botan/block_cipher.h>
20
   #include <botan/internal/gmac.h>
21
#endif
22
23
#if defined(BOTAN_HAS_HMAC)
24
   #include <botan/hash.h>
25
   #include <botan/internal/hmac.h>
26
#endif
27
28
#if defined(BOTAN_HAS_POLY1305)
29
   #include <botan/internal/poly1305.h>
30
#endif
31
32
#if defined(BOTAN_HAS_SIPHASH)
33
   #include <botan/internal/siphash.h>
34
#endif
35
36
#if defined(BOTAN_HAS_ANSI_X919_MAC)
37
   #include <botan/internal/x919_mac.h>
38
#endif
39
40
#if defined(BOTAN_HAS_BLAKE2BMAC)
41
   #include <botan/internal/blake2bmac.h>
42
#endif
43
44
#if defined(BOTAN_HAS_KMAC)
45
   #include <botan/internal/kmac.h>
46
#endif
47
48
namespace Botan {
49
50
std::unique_ptr<MessageAuthenticationCode> MessageAuthenticationCode::create(std::string_view algo_spec,
51
9.41k
                                                                             std::string_view provider) {
52
9.41k
   const SCAN_Name req(algo_spec);
53
54
9.41k
#if defined(BOTAN_HAS_BLAKE2BMAC)
55
9.41k
   if(req.algo_name() == "Blake2b" || req.algo_name() == "BLAKE2b") {
56
96
      return std::make_unique<BLAKE2bMAC>(req.arg_as_integer(0, 512));
57
96
   }
58
9.31k
#endif
59
60
9.31k
#if defined(BOTAN_HAS_GMAC)
61
9.31k
   if(req.algo_name() == "GMAC" && req.arg_count() == 1) {
62
0
      if(provider.empty() || provider == "base") {
63
0
         if(auto bc = BlockCipher::create(req.arg(0))) {
64
0
            return std::make_unique<GMAC>(std::move(bc));
65
0
         }
66
0
      }
67
0
   }
68
9.31k
#endif
69
70
9.31k
#if defined(BOTAN_HAS_HMAC)
71
9.31k
   if(req.algo_name() == "HMAC" && req.arg_count() == 1) {
72
6.86k
      if(provider.empty() || provider == "base") {
73
6.86k
         if(auto hash = HashFunction::create(req.arg(0))) {
74
5.57k
            return std::make_unique<HMAC>(std::move(hash));
75
5.57k
         }
76
6.86k
      }
77
6.86k
   }
78
3.74k
#endif
79
80
3.74k
#if defined(BOTAN_HAS_POLY1305)
81
3.74k
   if(req.algo_name() == "Poly1305" && req.arg_count() == 0) {
82
0
      if(provider.empty() || provider == "base") {
83
0
         return std::make_unique<Poly1305>();
84
0
      }
85
0
   }
86
3.74k
#endif
87
88
3.74k
#if defined(BOTAN_HAS_SIPHASH)
89
3.74k
   if(req.algo_name() == "SipHash") {
90
348
      if(provider.empty() || provider == "base") {
91
348
         return std::make_unique<SipHash>(req.arg_as_integer(0, 2), req.arg_as_integer(1, 4));
92
348
      }
93
348
   }
94
3.39k
#endif
95
96
3.39k
#if defined(BOTAN_HAS_CMAC)
97
3.39k
   if((req.algo_name() == "CMAC" || req.algo_name() == "OMAC") && req.arg_count() == 1) {
98
2.10k
      if(provider.empty() || provider == "base") {
99
2.10k
         if(auto bc = BlockCipher::create(req.arg(0))) {
100
2.10k
            return std::make_unique<CMAC>(std::move(bc));
101
2.10k
         }
102
2.10k
      }
103
2.10k
   }
104
1.28k
#endif
105
106
1.28k
#if defined(BOTAN_HAS_ANSI_X919_MAC)
107
1.28k
   if(req.algo_name() == "X9.19-MAC") {
108
0
      if(provider.empty() || provider == "base") {
109
0
         return std::make_unique<ANSI_X919_MAC>();
110
0
      }
111
0
   }
112
1.28k
#endif
113
114
1.28k
#if defined(BOTAN_HAS_KMAC)
115
1.28k
   if(req.algo_name() == "KMAC-128") {
116
0
      if(provider.empty() || provider == "base") {
117
0
         if(req.arg_count() != 1) {
118
0
            throw Invalid_Argument(
119
0
               "invalid algorithm specification for KMAC-128: need exactly one argument for output bit length");
120
0
         }
121
0
         return std::make_unique<KMAC128>(req.arg_as_integer(0));
122
0
      }
123
0
   }
124
125
1.28k
   if(req.algo_name() == "KMAC-256") {
126
0
      if(provider.empty() || provider == "base") {
127
0
         if(req.arg_count() != 1) {
128
0
            throw Invalid_Argument(
129
0
               "invalid algorithm specification for KMAC-256: need exactly one argument for output bit length");
130
0
         }
131
0
         return std::make_unique<KMAC256>(req.arg_as_integer(0));
132
0
      }
133
0
   }
134
1.28k
#endif
135
136
1.28k
   BOTAN_UNUSED(req);
137
1.28k
   BOTAN_UNUSED(provider);
138
139
1.28k
   return nullptr;
140
1.28k
}
141
142
0
std::vector<std::string> MessageAuthenticationCode::providers(std::string_view algo_spec) {
143
0
   return probe_providers_of<MessageAuthenticationCode>(algo_spec);
144
0
}
145
146
//static
147
std::unique_ptr<MessageAuthenticationCode> MessageAuthenticationCode::create_or_throw(std::string_view algo,
148
529
                                                                                      std::string_view provider) {
149
529
   if(auto mac = MessageAuthenticationCode::create(algo, provider)) {
150
529
      return mac;
151
529
   }
152
0
   throw Lookup_Error("MAC", algo, provider);
153
529
}
154
155
0
void MessageAuthenticationCode::start_msg(const uint8_t nonce[], size_t nonce_len) {
156
0
   BOTAN_UNUSED(nonce);
157
0
   if(nonce_len > 0) {
158
0
      throw Invalid_IV_Length(name(), nonce_len);
159
0
   }
160
0
}
161
162
/*
163
* Default (deterministic) MAC verification operation
164
*/
165
0
bool MessageAuthenticationCode::verify_mac_result(const uint8_t mac[], size_t length) {
166
0
   secure_vector<uint8_t> our_mac = final();
167
168
0
   if(our_mac.size() != length) {
169
0
      return false;
170
0
   }
171
172
0
   return constant_time_compare(our_mac.data(), mac, length);
173
0
}
174
175
}  // namespace Botan