/* * File: RijndaelCBCMAC.cpp * * Copyright (c) Freescale Semiconductor, Inc. All rights reserved. * See included license file for license details. */ #include "RijndaelCBCMAC.h" #include "rijndael.h" #include #include "Logging.h" void logHexArray(Logger::log_level_t level, const uint8_t * bytes, unsigned count); //! \param key The key to use as the CBC-MAC secret. //! \param iv Initialization vector. Defaults to zero if not provided. RijndaelCBCMAC::RijndaelCBCMAC(const AESKey<128> & key, const uint8_t * iv) : m_key(key) { if (iv) { memcpy(m_mac, iv, sizeof(m_mac)); } else { memset(m_mac, 0, sizeof(m_mac)); } } //! \param data Pointer to data to process. //! \param length Number of bytes to process. Must be evenly divisible by #BLOCK_SIZE. void RijndaelCBCMAC::update(const uint8_t * data, unsigned length) { assert(length % BLOCK_SIZE == 0); unsigned blocks = length / BLOCK_SIZE; while (blocks--) { updateOneBlock(data); data += BLOCK_SIZE; } } //! It appears that some forms of CBC-MAC encrypt the final output block again in //! order to protect against a plaintext attack. This method is a placeholder for //! such an operation, but it currently does nothing. void RijndaelCBCMAC::finalize() { } //! On entry the current value of m_mac becomes the initialization vector //! for the CBC encryption of this block. The output of the encryption then //! becomes the new MAC, which is stored in m_mac. void RijndaelCBCMAC::updateOneBlock(const uint8_t * data) { Rijndael cipher; cipher.init(Rijndael::CBC, Rijndael::Encrypt, m_key, Rijndael::Key16Bytes, m_mac); cipher.blockEncrypt(data, BLOCK_SIZE * 8, m_mac); // size is in bits // Log::log(Logger::DEBUG2, "CBC-MAC output block:\n"); // logHexArray(Logger::DEBUG2, (const uint8_t *)&m_mac, sizeof(m_mac)); } /*! * \brief Log an array of bytes as hex. */ void logHexArray(Logger::log_level_t level, const uint8_t * bytes, unsigned count) { Log::SetOutputLevel leveler(level); // Log::log(" "); unsigned i; for (i = 0; i < count; ++i, ++bytes) { if ((i % 16 == 0) && (i < count - 1)) { if (i != 0) { Log::log("\n"); } Log::log(" 0x%04x: ", i); } Log::log("%02x ", *bytes & 0xff); } Log::log("\n"); }