• Main Page
  • Namespaces
  • Classes
  • Files
  • File List
  • File Members

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

Generated on Mon Aug 9 2010 15:56:33 for Crypto++ by  doxygen 1.7.1