Training courses

Kernel and Embedded Linux

Bootlin training courses

Embedded Linux, kernel,
Yocto Project, Buildroot, real-time,
graphics, boot time, debugging...

Bootlin logo

Elixir Cross Referencer

/*
 * 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");
}