]> git.karo-electronics.de Git - karo-tx-uboot.git/blobdiff - tools/elftosb/common/RijndaelCBCMAC.cpp
Added source of Freescale's 'elftosb' tool
[karo-tx-uboot.git] / tools / elftosb / common / RijndaelCBCMAC.cpp
diff --git a/tools/elftosb/common/RijndaelCBCMAC.cpp b/tools/elftosb/common/RijndaelCBCMAC.cpp
new file mode 100644 (file)
index 0000000..fad0339
--- /dev/null
@@ -0,0 +1,86 @@
+/*
+ * 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 <assert.h>
+#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");
+}
+