- Main Page
- Namespaces
- Classes
- Files

# cmac.cpp

    00001 // cmac.cpp - written and placed in the public domain by Wei Dai
    00002
    00003 #include "pch.h"
    00004
    00005 #ifndef CRYPTOPP_IMPORTS
    00006
    00007 #include "cmac.h"
    00008
    00009 NAMESPACE_BEGIN(CryptoPP)
    00010
    00011 static void MulU(byte *k, unsigned int length)
    00012 {
    00013         byte carry = 0;
    00014
    00015         for (int i=length-1; i>=1; i-=2)
    00016         {
    00017                 byte carry2 = k[i] >> 7;
    00018                 k[i] += k[i] + carry;
    00019                 carry = k[i-1] >> 7;
    00020                 k[i-1] += k[i-1] + carry2;
    00021         }
    00022
    00023         if (carry)
    00024         {
    00025                 switch (length)
    00026                 {
    00027                 case 8:
    00028                         k[7] ^= 0x1b;
    00029                         break;
    00030                 case 16:
    00031                         k[15] ^= 0x87;
    00032                         break;
    00033                 case 32:
    00034                         k[30] ^= 4;
    00035                         k[31] ^= 0x23;
    00036                         break;
    00037                 default:
    00038                         throw InvalidArgument("CMAC: " + IntToString(length) + " is not a supported cipher block size");
    00039                 }
    00040         }
    00041 }
    00042
    00043 void CMAC_Base::UncheckedSetKey(const byte *key, unsigned int length, const NameValuePairs &params)
    00044 {
    00045         BlockCipher &cipher = AccessCipher();
    00046         unsigned int blockSize = cipher.BlockSize();
    00047
    00048         cipher.SetKey(key, length, params);
    00049         m_reg.CleanNew(3*blockSize);
    00050         m_counter = 0;
    00051
    00052         cipher.ProcessBlock(m_reg, m_reg+blockSize);
    00053         MulU(m_reg+blockSize, blockSize);
    00054         memcpy(m_reg+2*blockSize, m_reg+blockSize, blockSize);
    00055         MulU(m_reg+2*blockSize, blockSize);
    00056 }
    00057
    00058 void CMAC_Base::Update(const byte *input, size_t length)
    00059 {
    00060         if (!length)
    00061                 return;
    00062
    00063         BlockCipher &cipher = AccessCipher();
    00064         unsigned int blockSize = cipher.BlockSize();
    00065
    00066         if (m_counter > 0)
    00067         {
    00068                 unsigned int len = UnsignedMin(blockSize - m_counter, length);
    00069                 xorbuf(m_reg+m_counter, input, len);
    00070                 length -= len;
    00071                 input += len;
    00072                 m_counter += len;
    00073
    00074                 if (m_counter == blockSize && length > 0)
    00075                 {
    00076                         cipher.ProcessBlock(m_reg);
    00077                         m_counter = 0;
    00078                 }
    00079         }
    00080
    00081         if (length > blockSize)
    00082         {
    00083                 assert(m_counter == 0);
    00084                 size_t leftOver = 1 + cipher.AdvancedProcessBlocks(m_reg, input, m_reg, length-1, BlockTransformation::BT_DontIncrementInOutPointers|BlockTransformation::BT_XorInput);
    00085                 input += (length - leftOver);
    00086                 length = leftOver;
    00087         }
    00088
    00089         if (length > 0)
    00090         {
    00091                 assert(m_counter + length <= blockSize);
    00092                 xorbuf(m_reg+m_counter, input, length);
    00093                 m_counter += (unsigned int)length;
    00094         }
    00095
    00096         assert(m_counter > 0);
    00097 }
    00098
    00099 void CMAC_Base::TruncatedFinal(byte *mac, size_t size)
    00100 {
    00101         ThrowIfInvalidTruncatedSize(size);
    00102
    00103         BlockCipher &cipher = AccessCipher();
    00104         unsigned int blockSize = cipher.BlockSize();
    00105
    00106         if (m_counter < blockSize)
    00107         {
    00108                 m_reg[m_counter] ^= 0x80;
    00109                 cipher.AdvancedProcessBlocks(m_reg, m_reg+2*blockSize, m_reg, blockSize, BlockTransformation::BT_DontIncrementInOutPointers|BlockTransformation::BT_XorInput);
    00110         }
    00111         else
    00112                 cipher.AdvancedProcessBlocks(m_reg, m_reg+blockSize, m_reg, blockSize, BlockTransformation::BT_DontIncrementInOutPointers|BlockTransformation::BT_XorInput);
    00113
    00114         memcpy(mac, m_reg, size);
    00115
    00116         m_counter = 0;
    00117         memset(m_reg, 0, blockSize);
    00118 }
    00119
    00120 NAMESPACE_END
    00121
    00122 #endif