Botan 3.9.0
Crypto and TLS for C&
cmac.cpp
Go to the documentation of this file.
1/*
2* CMAC
3* (C) 1999-2007,2014 Jack Lloyd
4*
5* Botan is released under the Simplified BSD License (see license.txt)
6*/
7
8#include <botan/internal/cmac.h>
9
10#include <botan/exceptn.h>
11#include <botan/mem_ops.h>
12#include <botan/internal/fmt.h>
13#include <botan/internal/poly_dbl.h>
14#include <botan/internal/stl_util.h>
15
16namespace Botan {
17
18/*
19* Update an CMAC Calculation
20*/
21void CMAC::add_data(std::span<const uint8_t> input) {
22 const size_t bs = output_length();
23
24 const size_t initial_fill = std::min(m_buffer.size() - m_position, input.size());
25 copy_mem(m_buffer.data() + m_position, input.data(), initial_fill);
26
27 if(m_position + input.size() > bs) {
28 xor_buf(m_state, m_buffer, bs);
29 m_cipher->encrypt(m_state);
30
31 BufferSlicer in(input);
32 in.skip(bs - m_position);
33 while(in.remaining() > bs) {
34 xor_buf(m_state, in.take(bs), bs);
35 m_cipher->encrypt(m_state);
36 }
37
38 const auto remaining = in.take(in.remaining());
39 copy_mem(m_buffer.data(), remaining.data(), remaining.size());
40 m_position = remaining.size();
41 } else {
42 m_position += input.size();
43 }
44}
45
46/*
47* Finalize an CMAC Calculation
48*/
49void CMAC::final_result(std::span<uint8_t> mac) {
50 xor_buf(m_state, m_buffer, m_position);
51
52 if(m_position == output_length()) {
53 xor_buf(m_state, m_B, output_length());
54 } else {
55 m_state[m_position] ^= 0x80;
56 xor_buf(m_state, m_P, output_length());
57 }
58
59 m_cipher->encrypt(m_state);
60
61 copy_mem(mac.data(), m_state.data(), output_length());
62
63 zeroise(m_state);
64 zeroise(m_buffer);
65 m_position = 0;
66}
67
69 return m_cipher->has_keying_material();
70}
71
72/*
73* CMAC Key Schedule
74*/
75void CMAC::key_schedule(std::span<const uint8_t> key) {
76 clear();
77 m_cipher->set_key(key);
78 m_cipher->encrypt(m_B);
79 poly_double_n(m_B.data(), m_B.size());
80 poly_double_n(m_P.data(), m_B.data(), m_P.size());
81}
82
83/*
84* Clear memory of sensitive data
85*/
87 m_cipher->clear();
88 zeroise(m_state);
89 zeroise(m_buffer);
90 zeroise(m_B);
91 zeroise(m_P);
92 m_position = 0;
93}
94
95/*
96* Return the name of this type
97*/
98std::string CMAC::name() const {
99 return fmt("CMAC({})", m_cipher->name());
100}
101
102/*
103* Return a new_object of this object
104*/
105std::unique_ptr<MessageAuthenticationCode> CMAC::new_object() const {
106 return std::make_unique<CMAC>(m_cipher->new_object());
107}
108
109/*
110* CMAC Constructor
111*/
112CMAC::CMAC(std::unique_ptr<BlockCipher> cipher) : m_cipher(std::move(cipher)), m_block_size(m_cipher->block_size()) {
113 if(!poly_double_supported_size(m_block_size)) {
114 throw Invalid_Argument(fmt("CMAC cannot use the {} bit cipher {}", m_block_size * 8, m_cipher->name()));
115 }
116
117 m_state.resize(output_length());
118 m_buffer.resize(output_length());
119 m_B.resize(output_length());
120 m_P.resize(output_length());
121 m_position = 0;
122}
123
124} // namespace Botan
size_t output_length() const override
Definition cmac.h:23
CMAC(std::unique_ptr< BlockCipher > cipher)
Definition cmac.cpp:112
std::unique_ptr< MessageAuthenticationCode > new_object() const override
Definition cmac.cpp:105
void clear() override
Definition cmac.cpp:86
bool has_keying_material() const override
Definition cmac.cpp:68
std::string name() const override
Definition cmac.cpp:98
void zeroise(std::vector< T, Alloc > &vec)
Definition secmem.h:125
constexpr void copy_mem(T *out, const T *in, size_t n)
Definition mem_ops.h:145
std::string fmt(std::string_view format, const T &... args)
Definition fmt.h:53
constexpr void xor_buf(ranges::contiguous_output_range< uint8_t > auto &&out, ranges::contiguous_range< uint8_t > auto &&in)
Definition mem_ops.h:342
void poly_double_n(uint8_t out[], const uint8_t in[], size_t n)
Definition poly_dbl.cpp:81
bool poly_double_supported_size(size_t n)
Definition poly_dbl.h:22