- Main Page
- Namespaces
- Classes
- Files

# ccm.cpp

    00001 // ccm.cpp - written and placed in the public domain by Wei Dai
    00002
    00003 #include "pch.h"
    00004
    00005 #ifndef CRYPTOPP_IMPORTS
    00006
    00007 #include "ccm.h"
    00008
    00009 NAMESPACE_BEGIN(CryptoPP)
    00010
    00011 void CCM_Base::SetKeyWithoutResync(const byte *userKey, size_t keylength, const NameValuePairs &params)
    00012 {
    00013         BlockCipher &blockCipher = AccessBlockCipher();
    00014
    00015         blockCipher.SetKey(userKey, keylength, params);
    00016
    00017         if (blockCipher.BlockSize() != REQUIRED_BLOCKSIZE)
    00018                 throw InvalidArgument(AlgorithmName() + ": block size of underlying block cipher is not 16");
    00019
    00020         m_digestSize = params.GetIntValueWithDefault(Name::DigestSize(), DefaultDigestSize());
    00021         if (m_digestSize % 2 > 0 || m_digestSize < 4 || m_digestSize > 16)
    00022                 throw InvalidArgument(AlgorithmName() + ": DigestSize must be 4, 6, 8, 10, 12, 14, or 16");
    00023
    00024         m_buffer.Grow(2*REQUIRED_BLOCKSIZE);
    00025         m_L = 8;
    00026 }
    00027
    00028 void CCM_Base::Resync(const byte *iv, size_t len)
    00029 {
    00030         BlockCipher &cipher = AccessBlockCipher();
    00031
    00032         m_L = REQUIRED_BLOCKSIZE-1-(int)len;
    00033         assert(m_L >= 2);
    00034         if (m_L > 8)
    00035                 m_L = 8;
    00036
    00037         m_buffer[0] = byte(m_L-1);      // flag
    00038         memcpy(m_buffer+1, iv, len);
    00039         memset(m_buffer+1+len, 0, REQUIRED_BLOCKSIZE-1-len);
    00040
    00041         if (m_state >= State_IVSet)
    00042                 m_ctr.Resynchronize(m_buffer, REQUIRED_BLOCKSIZE);
    00043         else
    00044                 m_ctr.SetCipherWithIV(cipher, m_buffer);
    00045
    00046         m_ctr.Seek(REQUIRED_BLOCKSIZE);
    00047         m_aadLength = 0;
    00048         m_messageLength = 0;
    00049 }
    00050
    00051 void CCM_Base::UncheckedSpecifyDataLengths(lword headerLength, lword messageLength, lword footerLength)
    00052 {
    00053         if (m_state != State_IVSet)
    00054                 throw BadState(AlgorithmName(), "SpecifyDataLengths", "or after State_IVSet");
    00055
    00056         m_aadLength = headerLength;
    00057         m_messageLength = messageLength;
    00058
    00059         byte *cbcBuffer = CBC_Buffer();
    00060         const BlockCipher &cipher = GetBlockCipher();
    00061
    00062         cbcBuffer[0] = byte(64*(headerLength>0) + 8*((m_digestSize-2)/2) + (m_L-1));    // flag
    00063         PutWord<word64>(true, BIG_ENDIAN_ORDER, cbcBuffer+REQUIRED_BLOCKSIZE-8, m_messageLength);
    00064         memcpy(cbcBuffer+1, m_buffer+1, REQUIRED_BLOCKSIZE-1-m_L);
    00065         cipher.ProcessBlock(cbcBuffer);
    00066
    00067         if (headerLength>0)
    00068         {
    00069                 assert(m_bufferedDataLength == 0);
    00070
    00071                 if (headerLength < ((1<<16) - (1<<8)))
    00072                 {
    00073                         PutWord<word16>(true, BIG_ENDIAN_ORDER, m_buffer, (word16)headerLength);
    00074                         m_bufferedDataLength = 2;
    00075                 }
    00076                 else if (headerLength < (W64LIT(1)<<32))
    00077                 {
    00078                         m_buffer[0] = 0xff;
    00079                         m_buffer[1] = 0xfe;
    00080                         PutWord<word32>(false, BIG_ENDIAN_ORDER, m_buffer+2, (word32)headerLength);
    00081                         m_bufferedDataLength = 6;
    00082                 }
    00083                 else
    00084                 {
    00085                         m_buffer[0] = 0xff;
    00086                         m_buffer[1] = 0xff;
    00087                         PutWord<word64>(false, BIG_ENDIAN_ORDER, m_buffer+2, headerLength);
    00088                         m_bufferedDataLength = 10;
    00089                 }
    00090         }
    00091 }
    00092
    00093 size_t CCM_Base::AuthenticateBlocks(const byte *data, size_t len)
    00094 {
    00095         byte *cbcBuffer = CBC_Buffer();
    00096         const BlockCipher &cipher = GetBlockCipher();
    00097         return cipher.AdvancedProcessBlocks(cbcBuffer, data, cbcBuffer, len, BlockTransformation::BT_DontIncrementInOutPointers|BlockTransformation::BT_XorInput);
    00098 }
    00099
    00100 void CCM_Base::AuthenticateLastHeaderBlock()
    00101 {
    00102         byte *cbcBuffer = CBC_Buffer();
    00103         const BlockCipher &cipher = GetBlockCipher();
    00104
    00105         if (m_aadLength != m_totalHeaderLength)
    00106                 throw InvalidArgument(AlgorithmName() + ": header length doesn't match that given in SpecifyDataLengths");
    00107
    00108         if (m_bufferedDataLength > 0)
    00109         {
    00110                 xorbuf(cbcBuffer, m_buffer, m_bufferedDataLength);
    00111                 cipher.ProcessBlock(cbcBuffer);
    00112                 m_bufferedDataLength = 0;
    00113         }
    00114 }
    00115
    00116 void CCM_Base::AuthenticateLastConfidentialBlock()
    00117 {
    00118         byte *cbcBuffer = CBC_Buffer();
    00119         const BlockCipher &cipher = GetBlockCipher();
    00120
    00121         if (m_messageLength != m_totalMessageLength)
    00122                 throw InvalidArgument(AlgorithmName() + ": message length doesn't match that given in SpecifyDataLengths");
    00123
    00124         if (m_bufferedDataLength > 0)
    00125         {
    00126                 xorbuf(cbcBuffer, m_buffer, m_bufferedDataLength);
    00127                 cipher.ProcessBlock(cbcBuffer);
    00128                 m_bufferedDataLength = 0;
    00129         }
    00130 }
    00131
    00132 void CCM_Base::AuthenticateLastFooterBlock(byte *mac, size_t macSize)
    00133 {
    00134         m_ctr.Seek(0);
    00135         m_ctr.ProcessData(mac, CBC_Buffer(), macSize);
    00136 }
    00137
    00138 NAMESPACE_END
    00139
    00140 #endif