Botan  2.6.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/scan_name.h>
10 #include <botan/mem_ops.h>
11 
12 #if defined(BOTAN_HAS_CBC_MAC)
13  #include <botan/cbc_mac.h>
14 #endif
15 
16 #if defined(BOTAN_HAS_CMAC)
17  #include <botan/cmac.h>
18 #endif
19 
20 #if defined(BOTAN_HAS_GMAC)
21  #include <botan/gmac.h>
22  #include <botan/block_cipher.h>
23 #endif
24 
25 #if defined(BOTAN_HAS_HMAC)
26  #include <botan/hmac.h>
27  #include <botan/hash.h>
28 #endif
29 
30 #if defined(BOTAN_HAS_POLY1305)
31  #include <botan/poly1305.h>
32 #endif
33 
34 #if defined(BOTAN_HAS_SIPHASH)
35  #include <botan/siphash.h>
36 #endif
37 
38 #if defined(BOTAN_HAS_ANSI_X919_MAC)
39  #include <botan/x919_mac.h>
40 #endif
41 
42 namespace Botan {
43 
44 std::unique_ptr<MessageAuthenticationCode>
45 MessageAuthenticationCode::create(const std::string& algo_spec,
46  const std::string& provider)
47  {
48  const SCAN_Name req(algo_spec);
49 
50 #if defined(BOTAN_HAS_GMAC)
51  if(req.algo_name() == "GMAC" && req.arg_count() == 1)
52  {
53  if(provider.empty() || provider == "base")
54  {
55  if(auto bc = BlockCipher::create(req.arg(0)))
56  return std::unique_ptr<MessageAuthenticationCode>(new GMAC(bc.release()));
57  }
58  }
59 #endif
60 
61 #if defined(BOTAN_HAS_HMAC)
62  if(req.algo_name() == "HMAC" && req.arg_count() == 1)
63  {
64  // TODO OpenSSL
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  // TODO: OpenSSL CMAC
96  if(provider.empty() || provider == "base")
97  {
98  if(auto bc = BlockCipher::create(req.arg(0)))
99  return std::unique_ptr<MessageAuthenticationCode>(new CMAC(bc.release()));
100  }
101  }
102 #endif
103 
104 
105 #if defined(BOTAN_HAS_CBC_MAC)
106  if(req.algo_name() == "CBC-MAC" && req.arg_count() == 1)
107  {
108  if(provider.empty() || provider == "base")
109  {
110  if(auto bc = BlockCipher::create(req.arg(0)))
111  return std::unique_ptr<MessageAuthenticationCode>(new CBC_MAC(bc.release()));
112  }
113  }
114 #endif
115 
116 #if defined(BOTAN_HAS_ANSI_X919_MAC)
117  if(req.algo_name() == "X9.19-MAC")
118  {
119  if(provider.empty() || provider == "base")
120  {
121  return std::unique_ptr<MessageAuthenticationCode>(new ANSI_X919_MAC);
122  }
123  }
124 #endif
125 
126  BOTAN_UNUSED(req);
128 
129  return nullptr;
130  }
131 
132 std::vector<std::string>
133 MessageAuthenticationCode::providers(const std::string& algo_spec)
134  {
135  return probe_providers_of<MessageAuthenticationCode>(algo_spec, {"base", "openssl"});
136  }
137 
138 //static
139 std::unique_ptr<MessageAuthenticationCode>
141  const std::string& provider)
142  {
143  if(auto mac = MessageAuthenticationCode::create(algo, provider))
144  {
145  return mac;
146  }
147  throw Lookup_Error("MAC", algo, provider);
148  }
149 
150 /*
151 * Default (deterministic) MAC verification operation
152 */
153 bool MessageAuthenticationCode::verify_mac(const uint8_t mac[], size_t length)
154  {
155  secure_vector<uint8_t> our_mac = final();
156 
157  if(our_mac.size() != length)
158  return false;
159 
160  return constant_time_compare(our_mac.data(), mac, length);
161  }
162 
163 }
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:45
virtual std::string provider() const
Definition: mac.h:140
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:133
virtual bool verify_mac(const uint8_t in[], size_t length)
Definition: mac.cpp:153
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:117
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:140
std::vector< T, secure_allocator< T > > secure_vector
Definition: secmem.h:88