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