1 /* 2 * File: RijndaelCBCMAC.cpp 3 * 4 * Copyright (c) Freescale Semiconductor, Inc. All rights reserved. 5 * See included license file for license details. 6 */ 7 8 #include "RijndaelCBCMAC.h" 9 #include "rijndael.h" 10 #include <assert.h> 11 #include "Logging.h" 12 13 void logHexArray(Logger::log_level_t level, const uint8_t * bytes, unsigned count); 14 15 //! \param key The key to use as the CBC-MAC secret. 16 //! \param iv Initialization vector. Defaults to zero if not provided. 17 RijndaelCBCMAC::RijndaelCBCMAC(const AESKey<128> & key, const uint8_t * iv) 18 : m_key(key) 19 { 20 if (iv) 21 { 22 memcpy(m_mac, iv, sizeof(m_mac)); 23 } 24 else 25 { 26 memset(m_mac, 0, sizeof(m_mac)); 27 } 28 } 29 30 //! \param data Pointer to data to process. 31 //! \param length Number of bytes to process. Must be evenly divisible by #BLOCK_SIZE. 32 void RijndaelCBCMAC::update(const uint8_t * data, unsigned length) 33 { 34 assert(length % BLOCK_SIZE == 0); 35 unsigned blocks = length / BLOCK_SIZE; 36 while (blocks--) 37 { 38 updateOneBlock(data); 39 data += BLOCK_SIZE; 40 } 41 } 42 43 //! It appears that some forms of CBC-MAC encrypt the final output block again in 44 //! order to protect against a plaintext attack. This method is a placeholder for 45 //! such an operation, but it currently does nothing. 46 void RijndaelCBCMAC::finalize() 47 { 48 } 49 50 //! On entry the current value of m_mac becomes the initialization vector 51 //! for the CBC encryption of this block. The output of the encryption then 52 //! becomes the new MAC, which is stored in m_mac. 53 void RijndaelCBCMAC::updateOneBlock(const uint8_t * data) 54 { 55 Rijndael cipher; 56 cipher.init(Rijndael::CBC, Rijndael::Encrypt, m_key, Rijndael::Key16Bytes, m_mac); 57 cipher.blockEncrypt(data, BLOCK_SIZE * 8, m_mac); // size is in bits 58 59 // Log::log(Logger::DEBUG2, "CBC-MAC output block:\n"); 60 // logHexArray(Logger::DEBUG2, (const uint8_t *)&m_mac, sizeof(m_mac)); 61 } 62 63 /*! 64 * \brief Log an array of bytes as hex. 65 */ 66 void logHexArray(Logger::log_level_t level, const uint8_t * bytes, unsigned count) 67 { 68 Log::SetOutputLevel leveler(level); 69 // Log::log(" "); 70 unsigned i; 71 for (i = 0; i < count; ++i, ++bytes) 72 { 73 if ((i % 16 == 0) && (i < count - 1)) 74 { 75 if (i != 0) 76 { 77 Log::log("\n"); 78 } 79 Log::log(" 0x%04x: ", i); 80 } 81 Log::log("%02x ", *bytes & 0xff); 82 } 83 84 Log::log("\n"); 85 } 86 87