Botan  2.7.0
Crypto and TLS for C++11
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 
43 namespace Botan {
44 
45 std::unique_ptr<MessageAuthenticationCode>
46 MessageAuthenticationCode::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  // TODO OpenSSL
66  if(provider.empty() || provider == "base")
67  {
68  if(auto h = HashFunction::create(req.arg(0)))
69  return std::unique_ptr<MessageAuthenticationCode>(new HMAC(h.release()));
70  }
71  }
72 #endif
73 
74 #if defined(BOTAN_HAS_POLY1305)
75  if(req.algo_name() == "Poly1305" && req.arg_count() == 0)
76  {
77  if(provider.empty() || provider == "base")
78  return std::unique_ptr<MessageAuthenticationCode>(new Poly1305);
79  }
80 #endif
81 
82 #if defined(BOTAN_HAS_SIPHASH)
83  if(req.algo_name() == "SipHash")
84  {
85  if(provider.empty() || provider == "base")
86  {
87  return std::unique_ptr<MessageAuthenticationCode>(
88  new SipHash(req.arg_as_integer(0, 2), req.arg_as_integer(1, 4)));
89  }
90  }
91 #endif
92 
93 #if defined(BOTAN_HAS_CMAC)
94  if((req.algo_name() == "CMAC" || req.algo_name() == "OMAC") && req.arg_count() == 1)
95  {
96  // TODO: OpenSSL CMAC
97  if(provider.empty() || provider == "base")
98  {
99  if(auto bc = BlockCipher::create(req.arg(0)))
100  return std::unique_ptr<MessageAuthenticationCode>(new CMAC(bc.release()));
101  }
102  }
103 #endif
104 
105 
106 #if defined(BOTAN_HAS_CBC_MAC)
107  if(req.algo_name() == "CBC-MAC" && req.arg_count() == 1)
108  {
109  if(provider.empty() || provider == "base")
110  {
111  if(auto bc = BlockCipher::create(req.arg(0)))
112  return std::unique_ptr<MessageAuthenticationCode>(new CBC_MAC(bc.release()));
113  }
114  }
115 #endif
116 
117 #if defined(BOTAN_HAS_ANSI_X919_MAC)
118  if(req.algo_name() == "X9.19-MAC")
119  {
120  if(provider.empty() || provider == "base")
121  {
122  return std::unique_ptr<MessageAuthenticationCode>(new ANSI_X919_MAC);
123  }
124  }
125 #endif
126 
127  BOTAN_UNUSED(req);
129 
130  return nullptr;
131  }
132 
133 std::vector<std::string>
134 MessageAuthenticationCode::providers(const std::string& algo_spec)
135  {
136  return probe_providers_of<MessageAuthenticationCode>(algo_spec, {"base", "openssl"});
137  }
138 
139 //static
140 std::unique_ptr<MessageAuthenticationCode>
142  const std::string& provider)
143  {
144  if(auto mac = MessageAuthenticationCode::create(algo, provider))
145  {
146  return mac;
147  }
148  throw Lookup_Error("MAC", algo, provider);
149  }
150 
151 void MessageAuthenticationCode::start_msg(const uint8_t nonce[], size_t nonce_len)
152  {
153  BOTAN_UNUSED(nonce);
154  if(nonce_len > 0)
155  throw Invalid_IV_Length(name(), nonce_len);
156  }
157 
158 /*
159 * Default (deterministic) MAC verification operation
160 */
161 bool MessageAuthenticationCode::verify_mac(const uint8_t mac[], size_t length)
162  {
163  secure_vector<uint8_t> our_mac = final();
164 
165  if(our_mac.size() != length)
166  return false;
167 
168  return constant_time_compare(our_mac.data(), mac, length);
169  }
170 
171 }
virtual void start_msg(const uint8_t nonce[], size_t nonce_len)
Definition: mac.cpp:151
size_t arg_count() const
Definition: scan_name.h:49
static std::unique_ptr< MessageAuthenticationCode > create(const std::string &algo_spec, const std::string &provider="")
Definition: mac.cpp:46
virtual std::string provider() const
Definition: mac.h:135
size_t arg_as_integer(size_t i, size_t def_value) const
Definition: scan_name.cpp:137
bool constant_time_compare(const uint8_t x[], const uint8_t y[], size_t len)
Definition: mem_ops.cpp:51
static std::vector< std::string > providers(const std::string &algo_spec)
Definition: mac.cpp:134
virtual std::string name() const =0
virtual bool verify_mac(const uint8_t in[], size_t length)
Definition: mac.cpp:161
std::string arg(size_t i) const
Definition: scan_name.cpp:122
static std::unique_ptr< HashFunction > create(const std::string &algo_spec, const std::string &provider="")
Definition: hash.cpp:106
Definition: alg_id.cpp:13
#define BOTAN_UNUSED(...)
Definition: assert.h:130
static std::unique_ptr< BlockCipher > create(const std::string &algo_spec, const std::string &provider="")
const std::string & algo_name() const
Definition: scan_name.h:44
static std::unique_ptr< MessageAuthenticationCode > create_or_throw(const std::string &algo_spec, const std::string &provider="")
Definition: mac.cpp:141
std::vector< T, secure_allocator< T > > secure_vector
Definition: secmem.h:88