Botan 3.3.0
Crypto and TLS for C&
mac.cpp
Go to the documentation of this file.
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/ct_utils.h>
13#include <botan/internal/scan_name.h>
14
15#if defined(BOTAN_HAS_CMAC)
16 #include <botan/internal/cmac.h>
17#endif
18
19#if defined(BOTAN_HAS_GMAC)
20 #include <botan/block_cipher.h>
21 #include <botan/internal/gmac.h>
22#endif
23
24#if defined(BOTAN_HAS_HMAC)
25 #include <botan/hash.h>
26 #include <botan/internal/hmac.h>
27#endif
28
29#if defined(BOTAN_HAS_POLY1305)
30 #include <botan/internal/poly1305.h>
31#endif
32
33#if defined(BOTAN_HAS_SIPHASH)
34 #include <botan/internal/siphash.h>
35#endif
36
37#if defined(BOTAN_HAS_ANSI_X919_MAC)
38 #include <botan/internal/x919_mac.h>
39#endif
40
41#if defined(BOTAN_HAS_BLAKE2BMAC)
42 #include <botan/internal/blake2bmac.h>
43#endif
44
45#if defined(BOTAN_HAS_KMAC)
46 #include <botan/internal/kmac.h>
47#endif
48
49namespace Botan {
50
51std::unique_ptr<MessageAuthenticationCode> MessageAuthenticationCode::create(std::string_view algo_spec,
52 std::string_view provider) {
53 const SCAN_Name req(algo_spec);
54
55#if defined(BOTAN_HAS_BLAKE2BMAC)
56 if(req.algo_name() == "Blake2b" || req.algo_name() == "BLAKE2b") {
57 return std::make_unique<BLAKE2bMAC>(req.arg_as_integer(0, 512));
58 }
59#endif
60
61#if defined(BOTAN_HAS_GMAC)
62 if(req.algo_name() == "GMAC" && req.arg_count() == 1) {
63 if(provider.empty() || provider == "base") {
64 if(auto bc = BlockCipher::create(req.arg(0))) {
65 return std::make_unique<GMAC>(std::move(bc));
66 }
67 }
68 }
69#endif
70
71#if defined(BOTAN_HAS_HMAC)
72 if(req.algo_name() == "HMAC" && req.arg_count() == 1) {
73 if(provider.empty() || provider == "base") {
74 if(auto hash = HashFunction::create(req.arg(0))) {
75 return std::make_unique<HMAC>(std::move(hash));
76 }
77 }
78 }
79#endif
80
81#if defined(BOTAN_HAS_POLY1305)
82 if(req.algo_name() == "Poly1305" && req.arg_count() == 0) {
83 if(provider.empty() || provider == "base") {
84 return std::make_unique<Poly1305>();
85 }
86 }
87#endif
88
89#if defined(BOTAN_HAS_SIPHASH)
90 if(req.algo_name() == "SipHash") {
91 if(provider.empty() || provider == "base") {
92 return std::make_unique<SipHash>(req.arg_as_integer(0, 2), req.arg_as_integer(1, 4));
93 }
94 }
95#endif
96
97#if defined(BOTAN_HAS_CMAC)
98 if((req.algo_name() == "CMAC" || req.algo_name() == "OMAC") && req.arg_count() == 1) {
99 if(provider.empty() || provider == "base") {
100 if(auto bc = BlockCipher::create(req.arg(0))) {
101 return std::make_unique<CMAC>(std::move(bc));
102 }
103 }
104 }
105#endif
106
107#if defined(BOTAN_HAS_ANSI_X919_MAC)
108 if(req.algo_name() == "X9.19-MAC") {
109 if(provider.empty() || provider == "base") {
110 return std::make_unique<ANSI_X919_MAC>();
111 }
112 }
113#endif
114
115#if defined(BOTAN_HAS_KMAC)
116 if(req.algo_name() == "KMAC-128") {
117 if(provider.empty() || provider == "base") {
118 if(req.arg_count() != 1) {
119 throw Invalid_Argument(
120 "invalid algorithm specification for KMAC-128: need exactly one argument for output bit length");
121 }
122 return std::make_unique<KMAC128>(req.arg_as_integer(0));
123 }
124 }
125
126 if(req.algo_name() == "KMAC-256") {
127 if(provider.empty() || provider == "base") {
128 if(req.arg_count() != 1) {
129 throw Invalid_Argument(
130 "invalid algorithm specification for KMAC-256: need exactly one argument for output bit length");
131 }
132 return std::make_unique<KMAC256>(req.arg_as_integer(0));
133 }
134 }
135#endif
136
137 BOTAN_UNUSED(req);
139
140 return nullptr;
141}
142
143std::vector<std::string> MessageAuthenticationCode::providers(std::string_view algo_spec) {
144 return probe_providers_of<MessageAuthenticationCode>(algo_spec);
145}
146
147//static
148std::unique_ptr<MessageAuthenticationCode> MessageAuthenticationCode::create_or_throw(std::string_view algo,
149 std::string_view provider) {
150 if(auto mac = MessageAuthenticationCode::create(algo, provider)) {
151 return mac;
152 }
153 throw Lookup_Error("MAC", algo, provider);
154}
155
156void MessageAuthenticationCode::start_msg(std::span<const uint8_t> nonce) {
157 BOTAN_UNUSED(nonce);
158 if(!nonce.empty()) {
159 throw Invalid_IV_Length(name(), nonce.size());
160 }
161}
162
163/*
164* Default (deterministic) MAC verification operation
165*/
166bool MessageAuthenticationCode::verify_mac_result(std::span<const uint8_t> mac) {
167 secure_vector<uint8_t> our_mac = final();
168
169 if(our_mac.size() != mac.size()) {
170 return false;
171 }
172
173 return CT::is_equal(our_mac.data(), mac.data(), mac.size()).as_bool();
174}
175
176} // namespace Botan
#define BOTAN_UNUSED
Definition assert.h:118
static std::unique_ptr< BlockCipher > create(std::string_view algo_spec, std::string_view provider="")
static std::unique_ptr< HashFunction > create(std::string_view algo_spec, std::string_view provider="")
Definition hash.cpp:107
virtual bool verify_mac_result(std::span< const uint8_t > in)
Definition mac.cpp:166
static std::unique_ptr< MessageAuthenticationCode > create_or_throw(std::string_view algo_spec, std::string_view provider="")
Definition mac.cpp:148
static std::unique_ptr< MessageAuthenticationCode > create(std::string_view algo_spec, std::string_view provider="")
Definition mac.cpp:51
virtual std::string provider() const
Definition mac.h:108
virtual void start_msg(std::span< const uint8_t > nonce)
Definition mac.cpp:156
static std::vector< std::string > providers(std::string_view algo_spec)
Definition mac.cpp:143
std::string arg(size_t i) const
size_t arg_count() const
Definition scan_name.h:49
const std::string & algo_name() const
Definition scan_name.h:44
size_t arg_as_integer(size_t i, size_t def_value) const
virtual std::string name() const =0
CT::Mask< T > is_equal(const T x[], const T y[], size_t len)
Definition ct_utils.h:339
std::vector< T, secure_allocator< T > > secure_vector
Definition secmem.h:61