Botan
1.11.15
|
00001 /* 00002 * CMAC 00003 * (C) 1999-2007,2014 Jack Lloyd 00004 * 00005 * Botan is released under the Simplified BSD License (see license.txt) 00006 */ 00007 00008 #include <botan/internal/mac_utils.h> 00009 #include <botan/cmac.h> 00010 00011 namespace Botan { 00012 00013 CMAC* CMAC::make(const Spec& spec) 00014 { 00015 if(spec.arg_count() == 1) 00016 return new CMAC(Algo_Registry<BlockCipher>::global_registry().make(spec.arg(0))); 00017 return nullptr; 00018 } 00019 00020 BOTAN_REGISTER_NAMED_T(MessageAuthenticationCode, "CMAC", CMAC, CMAC::make); 00021 00022 /* 00023 * Perform CMAC's multiplication in GF(2^n) 00024 */ 00025 secure_vector<byte> CMAC::poly_double(const secure_vector<byte>& in) 00026 { 00027 const bool top_carry = (in[0] & 0x80); 00028 00029 secure_vector<byte> out = in; 00030 00031 byte carry = 0; 00032 for(size_t i = out.size(); i != 0; --i) 00033 { 00034 byte temp = out[i-1]; 00035 out[i-1] = (temp << 1) | carry; 00036 carry = (temp >> 7); 00037 } 00038 00039 if(top_carry) 00040 { 00041 switch(in.size()) 00042 { 00043 case 8: 00044 out[out.size()-1] ^= 0x1B; 00045 break; 00046 case 16: 00047 out[out.size()-1] ^= 0x87; 00048 break; 00049 case 32: 00050 out[out.size()-2] ^= 0x4; 00051 out[out.size()-1] ^= 0x25; 00052 break; 00053 case 64: 00054 out[out.size()-2] ^= 0x1; 00055 out[out.size()-1] ^= 0x25; 00056 break; 00057 default: 00058 throw std::runtime_error("Unsupported CMAC size " + std::to_string(in.size())); 00059 } 00060 } 00061 00062 return out; 00063 } 00064 00065 /* 00066 * Update an CMAC Calculation 00067 */ 00068 void CMAC::add_data(const byte input[], size_t length) 00069 { 00070 buffer_insert(m_buffer, m_position, input, length); 00071 if(m_position + length > output_length()) 00072 { 00073 xor_buf(m_state, m_buffer, output_length()); 00074 m_cipher->encrypt(m_state); 00075 input += (output_length() - m_position); 00076 length -= (output_length() - m_position); 00077 while(length > output_length()) 00078 { 00079 xor_buf(m_state, input, output_length()); 00080 m_cipher->encrypt(m_state); 00081 input += output_length(); 00082 length -= output_length(); 00083 } 00084 copy_mem(&m_buffer[0], input, length); 00085 m_position = 0; 00086 } 00087 m_position += length; 00088 } 00089 00090 /* 00091 * Finalize an CMAC Calculation 00092 */ 00093 void CMAC::final_result(byte mac[]) 00094 { 00095 xor_buf(m_state, m_buffer, m_position); 00096 00097 if(m_position == output_length()) 00098 { 00099 xor_buf(m_state, m_B, output_length()); 00100 } 00101 else 00102 { 00103 m_state[m_position] ^= 0x80; 00104 xor_buf(m_state, m_P, output_length()); 00105 } 00106 00107 m_cipher->encrypt(m_state); 00108 00109 for(size_t i = 0; i != output_length(); ++i) 00110 mac[i] = m_state[i]; 00111 00112 zeroise(m_state); 00113 zeroise(m_buffer); 00114 m_position = 0; 00115 } 00116 00117 /* 00118 * CMAC Key Schedule 00119 */ 00120 void CMAC::key_schedule(const byte key[], size_t length) 00121 { 00122 clear(); 00123 m_cipher->set_key(key, length); 00124 m_cipher->encrypt(m_B); 00125 m_B = poly_double(m_B); 00126 m_P = poly_double(m_B); 00127 } 00128 00129 /* 00130 * Clear memory of sensitive data 00131 */ 00132 void CMAC::clear() 00133 { 00134 m_cipher->clear(); 00135 zeroise(m_state); 00136 zeroise(m_buffer); 00137 zeroise(m_B); 00138 zeroise(m_P); 00139 m_position = 0; 00140 } 00141 00142 /* 00143 * Return the name of this type 00144 */ 00145 std::string CMAC::name() const 00146 { 00147 return "CMAC(" + m_cipher->name() + ")"; 00148 } 00149 00150 /* 00151 * Return a clone of this object 00152 */ 00153 MessageAuthenticationCode* CMAC::clone() const 00154 { 00155 return new CMAC(m_cipher->clone()); 00156 } 00157 00158 /* 00159 * CMAC Constructor 00160 */ 00161 CMAC::CMAC(BlockCipher* cipher) : m_cipher(cipher) 00162 { 00163 if(m_cipher->block_size() != 8 && m_cipher->block_size() != 16 && 00164 m_cipher->block_size() != 32 && m_cipher->block_size() != 64) 00165 { 00166 throw Invalid_Argument("CMAC cannot use the " + 00167 std::to_string(m_cipher->block_size() * 8) + 00168 " bit cipher " + m_cipher->name()); 00169 } 00170 00171 m_state.resize(output_length()); 00172 m_buffer.resize(output_length()); 00173 m_B.resize(output_length()); 00174 m_P.resize(output_length()); 00175 m_position = 0; 00176 } 00177 00178 }