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