Botan 2.19.3
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#include <botan/exceptn.h>
10#include <botan/scan_name.h>
11#include <botan/mem_ops.h>
12
13#if defined(BOTAN_HAS_CBC_MAC)
14 #include <botan/cbc_mac.h>
15#endif
16
17#if defined(BOTAN_HAS_CMAC)
18 #include <botan/cmac.h>
19#endif
20
21#if defined(BOTAN_HAS_GMAC)
22 #include <botan/gmac.h>
23 #include <botan/block_cipher.h>
24#endif
25
26#if defined(BOTAN_HAS_HMAC)
27 #include <botan/hmac.h>
28 #include <botan/hash.h>
29#endif
30
31#if defined(BOTAN_HAS_POLY1305)
32 #include <botan/poly1305.h>
33#endif
34
35#if defined(BOTAN_HAS_SIPHASH)
36 #include <botan/siphash.h>
37#endif
38
39#if defined(BOTAN_HAS_ANSI_X919_MAC)
40 #include <botan/x919_mac.h>
41#endif
42
43namespace Botan {
44
45std::unique_ptr<MessageAuthenticationCode>
46MessageAuthenticationCode::create(const std::string& algo_spec,
47 const std::string& provider)
48 {
49 const SCAN_Name req(algo_spec);
50
51#if defined(BOTAN_HAS_GMAC)
52 if(req.algo_name() == "GMAC" && req.arg_count() == 1)
53 {
54 if(provider.empty() || provider == "base")
55 {
56 if(auto bc = BlockCipher::create(req.arg(0)))
57 return std::unique_ptr<MessageAuthenticationCode>(new GMAC(bc.release()));
58 }
59 }
60#endif
61
62#if defined(BOTAN_HAS_HMAC)
63 if(req.algo_name() == "HMAC" && req.arg_count() == 1)
64 {
65 if(provider.empty() || provider == "base")
66 {
67 if(auto h = HashFunction::create(req.arg(0)))
68 return std::unique_ptr<MessageAuthenticationCode>(new HMAC(h.release()));
69 }
70 }
71#endif
72
73#if defined(BOTAN_HAS_POLY1305)
74 if(req.algo_name() == "Poly1305" && req.arg_count() == 0)
75 {
76 if(provider.empty() || provider == "base")
77 return std::unique_ptr<MessageAuthenticationCode>(new Poly1305);
78 }
79#endif
80
81#if defined(BOTAN_HAS_SIPHASH)
82 if(req.algo_name() == "SipHash")
83 {
84 if(provider.empty() || provider == "base")
85 {
86 return std::unique_ptr<MessageAuthenticationCode>(
87 new SipHash(req.arg_as_integer(0, 2), req.arg_as_integer(1, 4)));
88 }
89 }
90#endif
91
92#if defined(BOTAN_HAS_CMAC)
93 if((req.algo_name() == "CMAC" || req.algo_name() == "OMAC") && req.arg_count() == 1)
94 {
95 if(provider.empty() || provider == "base")
96 {
97 if(auto bc = BlockCipher::create(req.arg(0)))
98 return std::unique_ptr<MessageAuthenticationCode>(new CMAC(bc.release()));
99 }
100 }
101#endif
102
103
104#if defined(BOTAN_HAS_CBC_MAC)
105 if(req.algo_name() == "CBC-MAC" && req.arg_count() == 1)
106 {
107 if(provider.empty() || provider == "base")
108 {
109 if(auto bc = BlockCipher::create(req.arg(0)))
110 return std::unique_ptr<MessageAuthenticationCode>(new CBC_MAC(bc.release()));
111 }
112 }
113#endif
114
115#if defined(BOTAN_HAS_ANSI_X919_MAC)
116 if(req.algo_name() == "X9.19-MAC")
117 {
118 if(provider.empty() || provider == "base")
119 {
120 return std::unique_ptr<MessageAuthenticationCode>(new ANSI_X919_MAC);
121 }
122 }
123#endif
124
125 BOTAN_UNUSED(req);
127
128 return nullptr;
129 }
130
131std::vector<std::string>
132MessageAuthenticationCode::providers(const std::string& algo_spec)
133 {
134 return probe_providers_of<MessageAuthenticationCode>(algo_spec, {"base", "openssl"});
135 }
136
137//static
138std::unique_ptr<MessageAuthenticationCode>
140 const std::string& provider)
141 {
142 if(auto mac = MessageAuthenticationCode::create(algo, provider))
143 {
144 return mac;
145 }
146 throw Lookup_Error("MAC", algo, provider);
147 }
148
149void MessageAuthenticationCode::start_msg(const uint8_t nonce[], size_t nonce_len)
150 {
151 BOTAN_UNUSED(nonce);
152 if(nonce_len > 0)
153 throw Invalid_IV_Length(name(), nonce_len);
154 }
155
156/*
157* Default (deterministic) MAC verification operation
158*/
159bool MessageAuthenticationCode::verify_mac(const uint8_t mac[], size_t length)
160 {
161 secure_vector<uint8_t> our_mac = final();
162
163 if(our_mac.size() != length)
164 return false;
165
166 return constant_time_compare(our_mac.data(), mac, length);
167 }
168
169}
#define BOTAN_UNUSED(...)
Definition assert.h:142
static std::unique_ptr< BlockCipher > create(const std::string &algo_spec, const std::string &provider="")
static std::unique_ptr< HashFunction > create(const std::string &algo_spec, const std::string &provider="")
Definition hash.cpp:102
static std::vector< std::string > providers(const std::string &algo_spec)
Definition mac.cpp:132
virtual void start_msg(const uint8_t nonce[], size_t nonce_len)
Definition mac.cpp:149
virtual std::string provider() const
Definition mac.h:135
static std::unique_ptr< MessageAuthenticationCode > create(const std::string &algo_spec, const std::string &provider="")
Definition mac.cpp:46
virtual bool verify_mac(const uint8_t in[], size_t length)
Definition mac.cpp:159
static std::unique_ptr< MessageAuthenticationCode > create_or_throw(const std::string &algo_spec, const std::string &provider="")
Definition mac.cpp:139
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
bool constant_time_compare(const uint8_t x[], const uint8_t y[], size_t len)
Definition mem_ops.h:82
std::vector< T, secure_allocator< T > > secure_vector
Definition secmem.h:65