00001
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 ¶ms)
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