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