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