Botan 3.2.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/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
48namespace Botan {
49
50std::unique_ptr<MessageAuthenticationCode> MessageAuthenticationCode::create(std::string_view algo_spec,
51 std::string_view provider) {
52 const SCAN_Name req(algo_spec);
53
54#if defined(BOTAN_HAS_BLAKE2BMAC)
55 if(req.algo_name() == "Blake2b" || req.algo_name() == "BLAKE2b") {
56 return std::make_unique<BLAKE2bMAC>(req.arg_as_integer(0, 512));
57 }
58#endif
59
60#if defined(BOTAN_HAS_GMAC)
61 if(req.algo_name() == "GMAC" && req.arg_count() == 1) {
62 if(provider.empty() || provider == "base") {
63 if(auto bc = BlockCipher::create(req.arg(0))) {
64 return std::make_unique<GMAC>(std::move(bc));
65 }
66 }
67 }
68#endif
69
70#if defined(BOTAN_HAS_HMAC)
71 if(req.algo_name() == "HMAC" && req.arg_count() == 1) {
72 if(provider.empty() || provider == "base") {
73 if(auto hash = HashFunction::create(req.arg(0))) {
74 return std::make_unique<HMAC>(std::move(hash));
75 }
76 }
77 }
78#endif
79
80#if defined(BOTAN_HAS_POLY1305)
81 if(req.algo_name() == "Poly1305" && req.arg_count() == 0) {
82 if(provider.empty() || provider == "base") {
83 return std::make_unique<Poly1305>();
84 }
85 }
86#endif
87
88#if defined(BOTAN_HAS_SIPHASH)
89 if(req.algo_name() == "SipHash") {
90 if(provider.empty() || provider == "base") {
91 return std::make_unique<SipHash>(req.arg_as_integer(0, 2), req.arg_as_integer(1, 4));
92 }
93 }
94#endif
95
96#if defined(BOTAN_HAS_CMAC)
97 if((req.algo_name() == "CMAC" || req.algo_name() == "OMAC") && req.arg_count() == 1) {
98 if(provider.empty() || provider == "base") {
99 if(auto bc = BlockCipher::create(req.arg(0))) {
100 return std::make_unique<CMAC>(std::move(bc));
101 }
102 }
103 }
104#endif
105
106#if defined(BOTAN_HAS_ANSI_X919_MAC)
107 if(req.algo_name() == "X9.19-MAC") {
108 if(provider.empty() || provider == "base") {
109 return std::make_unique<ANSI_X919_MAC>();
110 }
111 }
112#endif
113
114#if defined(BOTAN_HAS_KMAC)
115 if(req.algo_name() == "KMAC-128") {
116 if(provider.empty() || provider == "base") {
117 if(req.arg_count() != 1) {
118 throw Invalid_Argument(
119 "invalid algorithm specification for KMAC-128: need exactly one argument for output bit length");
120 }
121 return std::make_unique<KMAC128>(req.arg_as_integer(0));
122 }
123 }
124
125 if(req.algo_name() == "KMAC-256") {
126 if(provider.empty() || provider == "base") {
127 if(req.arg_count() != 1) {
128 throw Invalid_Argument(
129 "invalid algorithm specification for KMAC-256: need exactly one argument for output bit length");
130 }
131 return std::make_unique<KMAC256>(req.arg_as_integer(0));
132 }
133 }
134#endif
135
136 BOTAN_UNUSED(req);
138
139 return nullptr;
140}
141
142std::vector<std::string> MessageAuthenticationCode::providers(std::string_view algo_spec) {
143 return probe_providers_of<MessageAuthenticationCode>(algo_spec);
144}
145
146//static
147std::unique_ptr<MessageAuthenticationCode> MessageAuthenticationCode::create_or_throw(std::string_view algo,
148 std::string_view provider) {
149 if(auto mac = MessageAuthenticationCode::create(algo, provider)) {
150 return mac;
151 }
152 throw Lookup_Error("MAC", algo, provider);
153}
154
155void MessageAuthenticationCode::start_msg(std::span<const uint8_t> nonce) {
156 BOTAN_UNUSED(nonce);
157 if(!nonce.empty()) {
158 throw Invalid_IV_Length(name(), nonce.size());
159 }
160}
161
162/*
163* Default (deterministic) MAC verification operation
164*/
165bool MessageAuthenticationCode::verify_mac_result(std::span<const uint8_t> mac) {
166 secure_vector<uint8_t> our_mac = final();
167
168 if(our_mac.size() != mac.size()) {
169 return false;
170 }
171
172 return constant_time_compare(our_mac.data(), mac.data(), mac.size());
173}
174
175} // 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:103
virtual bool verify_mac_result(std::span< const uint8_t > in)
Definition mac.cpp:165
static std::unique_ptr< MessageAuthenticationCode > create_or_throw(std::string_view algo_spec, std::string_view provider="")
Definition mac.cpp:147
static std::unique_ptr< MessageAuthenticationCode > create(std::string_view algo_spec, std::string_view provider="")
Definition mac.cpp:50
virtual std::string provider() const
Definition mac.h:108
virtual void start_msg(std::span< const uint8_t > nonce)
Definition mac.cpp:155
static std::vector< std::string > providers(std::string_view algo_spec)
Definition mac.cpp:142
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
bool constant_time_compare(const uint8_t x[], const uint8_t y[], size_t len)
Definition mem_ops.h:80
std::vector< T, secure_allocator< T > > secure_vector
Definition secmem.h:61