Coverage Report

Created: 2023-09-25 06:34

/src/botan/src/lib/mac/cmac/cmac.cpp
Line
Count
Source (jump to first uncovered line)
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/internal/fmt.h>
12
#include <botan/internal/poly_dbl.h>
13
#include <botan/internal/stl_util.h>
14
15
namespace Botan {
16
17
/*
18
* Update an CMAC Calculation
19
*/
20
75.9k
void CMAC::add_data(std::span<const uint8_t> input) {
21
75.9k
   const size_t bs = output_length();
22
23
75.9k
   buffer_insert(m_buffer, m_position, input.data(), input.size());
24
75.9k
   if(m_position + input.size() > bs) {
25
3.24k
      xor_buf(m_state, m_buffer, bs);
26
3.24k
      m_cipher->encrypt(m_state);
27
28
3.24k
      BufferSlicer in(input);
29
3.24k
      in.skip(bs - m_position);
30
29.2k
      while(in.remaining() > bs) {
31
25.9k
         xor_buf(m_state, in.take(bs), bs);
32
25.9k
         m_cipher->encrypt(m_state);
33
25.9k
      }
34
35
3.24k
      const auto remaining = in.take(in.remaining());
36
3.24k
      copy_mem(m_buffer.data(), remaining.data(), remaining.size());
37
3.24k
      m_position = remaining.size();
38
72.7k
   } else {
39
72.7k
      m_position += input.size();
40
72.7k
   }
41
75.9k
}
42
43
/*
44
* Finalize an CMAC Calculation
45
*/
46
3.80k
void CMAC::final_result(std::span<uint8_t> mac) {
47
3.80k
   xor_buf(m_state, m_buffer, m_position);
48
49
3.80k
   if(m_position == output_length()) {
50
1.26k
      xor_buf(m_state, m_B, output_length());
51
2.54k
   } else {
52
2.54k
      m_state[m_position] ^= 0x80;
53
2.54k
      xor_buf(m_state, m_P, output_length());
54
2.54k
   }
55
56
3.80k
   m_cipher->encrypt(m_state);
57
58
3.80k
   copy_mem(mac.data(), m_state.data(), output_length());
59
60
3.80k
   zeroise(m_state);
61
3.80k
   zeroise(m_buffer);
62
3.80k
   m_position = 0;
63
3.80k
}
64
65
0
bool CMAC::has_keying_material() const {
66
0
   return m_cipher->has_keying_material();
67
0
}
68
69
/*
70
* CMAC Key Schedule
71
*/
72
2.21k
void CMAC::key_schedule(std::span<const uint8_t> key) {
73
2.21k
   clear();
74
2.21k
   m_cipher->set_key(key);
75
2.21k
   m_cipher->encrypt(m_B);
76
2.21k
   poly_double_n(m_B.data(), m_B.size());
77
2.21k
   poly_double_n(m_P.data(), m_B.data(), m_P.size());
78
2.21k
}
79
80
/*
81
* Clear memory of sensitive data
82
*/
83
2.21k
void CMAC::clear() {
84
2.21k
   m_cipher->clear();
85
2.21k
   zeroise(m_state);
86
2.21k
   zeroise(m_buffer);
87
2.21k
   zeroise(m_B);
88
2.21k
   zeroise(m_P);
89
2.21k
   m_position = 0;
90
2.21k
}
91
92
/*
93
* Return the name of this type
94
*/
95
430
std::string CMAC::name() const {
96
430
   return fmt("CMAC({})", m_cipher->name());
97
430
}
98
99
/*
100
* Return a new_object of this object
101
*/
102
0
std::unique_ptr<MessageAuthenticationCode> CMAC::new_object() const {
103
0
   return std::make_unique<CMAC>(m_cipher->new_object());
104
0
}
105
106
/*
107
* CMAC Constructor
108
*/
109
2.94k
CMAC::CMAC(std::unique_ptr<BlockCipher> cipher) : m_cipher(std::move(cipher)), m_block_size(m_cipher->block_size()) {
110
2.94k
   if(poly_double_supported_size(m_block_size) == false) {
111
0
      throw Invalid_Argument(fmt("CMAC cannot use the {} bit cipher {}", m_block_size * 8, m_cipher->name()));
112
0
   }
113
114
2.94k
   m_state.resize(output_length());
115
2.94k
   m_buffer.resize(output_length());
116
2.94k
   m_B.resize(output_length());
117
2.94k
   m_P.resize(output_length());
118
2.94k
   m_position = 0;
119
2.94k
}
120
121
}  // namespace Botan