Botan  1.11.16
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/mac_utils.h>
9 #include <botan/cmac.h>
10 
11 namespace Botan {
12 
13 CMAC* CMAC::make(const Spec& spec)
14  {
15  if(spec.arg_count() == 1)
16  {
17  if(BlockCipher* bc = get_block_cipher(spec.arg(0)))
18  return new CMAC(bc);
19  }
20  return nullptr;
21  }
22 
24 
25 /*
26 * Perform CMAC's multiplication in GF(2^n)
27 */
29  {
30  const bool top_carry = static_cast<bool>(in[0] & 0x80);
31 
32  secure_vector<byte> out = in;
33 
34  byte carry = 0;
35  for(size_t i = out.size(); i != 0; --i)
36  {
37  byte temp = out[i-1];
38  out[i-1] = (temp << 1) | carry;
39  carry = (temp >> 7);
40  }
41 
42  if(top_carry)
43  {
44  switch(in.size())
45  {
46  case 8:
47  out[out.size()-1] ^= 0x1B;
48  break;
49  case 16:
50  out[out.size()-1] ^= 0x87;
51  break;
52  case 32:
53  out[out.size()-2] ^= 0x4;
54  out[out.size()-1] ^= 0x25;
55  break;
56  case 64:
57  out[out.size()-2] ^= 0x1;
58  out[out.size()-1] ^= 0x25;
59  break;
60  default:
61  throw std::runtime_error("Unsupported CMAC size " + std::to_string(in.size()));
62  }
63  }
64 
65  return out;
66  }
67 
68 /*
69 * Update an CMAC Calculation
70 */
71 void CMAC::add_data(const byte input[], size_t length)
72  {
73  buffer_insert(m_buffer, m_position, input, length);
74  if(m_position + length > output_length())
75  {
76  xor_buf(m_state, m_buffer, output_length());
77  m_cipher->encrypt(m_state);
78  input += (output_length() - m_position);
79  length -= (output_length() - m_position);
80  while(length > output_length())
81  {
82  xor_buf(m_state, input, output_length());
83  m_cipher->encrypt(m_state);
84  input += output_length();
85  length -= output_length();
86  }
87  copy_mem(&m_buffer[0], input, length);
88  m_position = 0;
89  }
90  m_position += length;
91  }
92 
93 /*
94 * Finalize an CMAC Calculation
95 */
96 void CMAC::final_result(byte mac[])
97  {
98  xor_buf(m_state, m_buffer, m_position);
99 
100  if(m_position == output_length())
101  {
102  xor_buf(m_state, m_B, output_length());
103  }
104  else
105  {
106  m_state[m_position] ^= 0x80;
107  xor_buf(m_state, m_P, output_length());
108  }
109 
110  m_cipher->encrypt(m_state);
111 
112  for(size_t i = 0; i != output_length(); ++i)
113  mac[i] = m_state[i];
114 
115  zeroise(m_state);
116  zeroise(m_buffer);
117  m_position = 0;
118  }
119 
120 /*
121 * CMAC Key Schedule
122 */
123 void CMAC::key_schedule(const byte key[], size_t length)
124  {
125  clear();
126  m_cipher->set_key(key, length);
127  m_cipher->encrypt(m_B);
128  m_B = poly_double(m_B);
129  m_P = poly_double(m_B);
130  }
131 
132 /*
133 * Clear memory of sensitive data
134 */
136  {
137  m_cipher->clear();
138  zeroise(m_state);
139  zeroise(m_buffer);
140  zeroise(m_B);
141  zeroise(m_P);
142  m_position = 0;
143  }
144 
145 /*
146 * Return the name of this type
147 */
148 std::string CMAC::name() const
149  {
150  return "CMAC(" + m_cipher->name() + ")";
151  }
152 
153 /*
154 * Return a clone of this object
155 */
157  {
158  return new CMAC(m_cipher->clone());
159  }
160 
161 /*
162 * CMAC Constructor
163 */
164 CMAC::CMAC(BlockCipher* cipher) : m_cipher(cipher)
165  {
166  if(m_cipher->block_size() != 8 && m_cipher->block_size() != 16 &&
167  m_cipher->block_size() != 32 && m_cipher->block_size() != 64)
168  {
169  throw Invalid_Argument("CMAC cannot use the " +
170  std::to_string(m_cipher->block_size() * 8) +
171  " bit cipher " + m_cipher->name());
172  }
173 
174  m_state.resize(output_length());
175  m_buffer.resize(output_length());
176  m_B.resize(output_length());
177  m_P.resize(output_length());
178  m_position = 0;
179  }
180 
181 }
void xor_buf(T out[], const T in[], size_t length)
Definition: xor_buf.h:23
std::string arg(size_t i) const
Definition: scan_name.cpp:156
std::unique_ptr< MessageAuthenticationCode > mac
Definition: fpe_fe1.cpp:89
BlockCipher * get_block_cipher(const std::string &algo_spec, const std::string &provider)
Definition: lookup.cpp:27
size_t arg_count() const
Definition: scan_name.h:64
std::invalid_argument Invalid_Argument
Definition: exceptn.h:20
std::string to_string(const BER_Object &obj)
Definition: asn1_obj.cpp:46
void clear()
Definition: cmac.cpp:135
static secure_vector< byte > poly_double(const secure_vector< byte > &in)
Definition: cmac.cpp:28
std::vector< T, secure_allocator< T >> secure_vector
Definition: secmem.h:93
uint8_t byte
Definition: types.h:31
size_t output_length() const
Definition: cmac.h:23
void copy_mem(T *out, const T *in, size_t n)
Definition: mem_ops.h:39
BOTAN_REGISTER_NAMED_T(BlockCipher,"Cascade", Cascade_Cipher, Cascade_Cipher::make)
static CMAC * make(const Spec &spec)
Definition: cmac.cpp:13
CMAC(BlockCipher *cipher)
Definition: cmac.cpp:164
size_t buffer_insert(std::vector< T, Alloc > &buf, size_t buf_offset, const T input[], size_t input_length)
Definition: secmem.h:105
MessageAuthenticationCode * clone() const
Definition: cmac.cpp:156
std::string name() const
Definition: cmac.cpp:148
void zeroise(std::vector< T, Alloc > &vec)
Definition: secmem.h:168