Crypto++ 8.9 Free C++ class library of cryptographic schemes

ccm.cpp
1 // ccm.cpp - originally written and placed in the public domain by Wei Dai
2
3 #include "pch.h"
4
5 #ifndef CRYPTOPP_IMPORTS
6
7 #include "ccm.h"
8
9 NAMESPACE_BEGIN(CryptoPP)
10
11 void CCM_Base::SetKeyWithoutResync(const byte *userKey, size_t keylength, const NameValuePairs &params)
12 {
13 BlockCipher &blockCipher = AccessBlockCipher();
14 blockCipher.SetKey(userKey, keylength, params);
15
16 if (blockCipher.BlockSize() != REQUIRED_BLOCKSIZE)
17 throw InvalidArgument(AlgorithmName() + ": block size of underlying block cipher is not 16");
18
19 m_digestSize = params.GetIntValueWithDefault(Name::DigestSize(), DefaultDigestSize());
20 if (m_digestSize % 2 > 0 || m_digestSize < 4 || m_digestSize > 16)
21 throw InvalidArgument(AlgorithmName() + ": DigestSize must be 4, 6, 8, 10, 12, 14, or 16");
22
23 m_buffer.Grow(2*REQUIRED_BLOCKSIZE);
24 m_L = 8;
25 }
26
27 void CCM_Base::Resync(const byte *iv, size_t len)
28 {
29 BlockCipher &cipher = AccessBlockCipher();
30
31 m_L = REQUIRED_BLOCKSIZE-1-(int)len;
32 CRYPTOPP_ASSERT(m_L >= 2);
33 if (m_L > 8)
34 m_L = 8;
35
36 m_buffer[0] = byte(m_L-1); // flag
37 std::memcpy(m_buffer+1, iv, len);
38 std::memset(m_buffer+1+len, 0, REQUIRED_BLOCKSIZE-1-len);
39
40 if (m_state >= State_IVSet)
41 m_ctr.Resynchronize(m_buffer, REQUIRED_BLOCKSIZE);
42 else
43 m_ctr.SetCipherWithIV(cipher, m_buffer);
44
45 m_ctr.Seek(REQUIRED_BLOCKSIZE);
46 m_aadLength = 0;
47 m_messageLength = 0;
48 }
49
50 void CCM_Base::UncheckedSpecifyDataLengths(lword headerLength, lword messageLength, lword /*footerLength*/)
51 {
52 if (m_state != State_IVSet)
53 throw BadState(AlgorithmName(), "SpecifyDataLengths", "or after State_IVSet");
54
55 m_aadLength = headerLength;
56 m_messageLength = messageLength;
57
58 byte *cbcBuffer = CBC_Buffer();
59 const BlockCipher &cipher = GetBlockCipher();
60
61 cbcBuffer[0] = byte(64*(headerLength>0) + 8*((m_digestSize-2)/2) + (m_L-1)); // flag
62 PutWord<word64>(true, BIG_ENDIAN_ORDER, cbcBuffer+REQUIRED_BLOCKSIZE-8, m_messageLength);
63 std::memcpy(cbcBuffer+1, m_buffer+1, REQUIRED_BLOCKSIZE-1-m_L);
64 cipher.ProcessBlock(cbcBuffer);
65
66 if (headerLength>0)
67 {
68 CRYPTOPP_ASSERT(m_bufferedDataLength == 0);
69
70 if (headerLength < ((1<<16) - (1<<8)))
71 {
72 PutWord<word16>(true, BIG_ENDIAN_ORDER, m_buffer, (word16)headerLength);
73 m_bufferedDataLength = 2;
74 }
75 else if (headerLength < (W64LIT(1)<<32))
76 {
77 m_buffer[0] = 0xff;
78 m_buffer[1] = 0xfe;
79 PutWord<word32>(false, BIG_ENDIAN_ORDER, m_buffer+2, (word32)headerLength);
80 m_bufferedDataLength = 6;
81 }
82 else
83 {
84 m_buffer[0] = 0xff;
85 m_buffer[1] = 0xff;
86 PutWord<word64>(false, BIG_ENDIAN_ORDER, m_buffer+2, headerLength);
87 m_bufferedDataLength = 10;
88 }
89 }
90 }
91
92 size_t CCM_Base::AuthenticateBlocks(const byte *data, size_t len)
93 {
94 byte *cbcBuffer = CBC_Buffer();
95 const BlockCipher &cipher = GetBlockCipher();
96 return cipher.AdvancedProcessBlocks(cbcBuffer, data, cbcBuffer, len, BlockTransformation::BT_DontIncrementInOutPointers|BlockTransformation::BT_XorInput);
97 }
98
99 void CCM_Base::AuthenticateLastHeaderBlock()
100 {
101 byte *cbcBuffer = CBC_Buffer();
102 const BlockCipher &cipher = GetBlockCipher();
103
104 if (m_aadLength != m_totalHeaderLength)
105 throw InvalidArgument(AlgorithmName() + ": header length doesn't match that given in SpecifyDataLengths");
106
107 if (m_bufferedDataLength > 0)
108 {
109 xorbuf(cbcBuffer, m_buffer, m_bufferedDataLength);
110 cipher.ProcessBlock(cbcBuffer);
111 m_bufferedDataLength = 0;
112 }
113 }
114
115 void CCM_Base::AuthenticateLastConfidentialBlock()
116 {
117 byte *cbcBuffer = CBC_Buffer();
118 const BlockCipher &cipher = GetBlockCipher();
119
120 if (m_messageLength != m_totalMessageLength)
121 throw InvalidArgument(AlgorithmName() + ": message length doesn't match that given in SpecifyDataLengths");
122
123 if (m_bufferedDataLength > 0)
124 {
125 xorbuf(cbcBuffer, m_buffer, m_bufferedDataLength);
126 cipher.ProcessBlock(cbcBuffer);
127 m_bufferedDataLength = 0;
128 }
129 }
130
131 void CCM_Base::AuthenticateLastFooterBlock(byte *mac, size_t macSize)
132 {
133 m_ctr.Seek(0);
134 m_ctr.ProcessData(mac, CBC_Buffer(), macSize);
135 }
136
137 NAMESPACE_END
138
139 #endif
ccm.h
CCM block cipher mode of operation.
BlockCipher
Interface for one direction (encryption or decryption) of a block cipher.
Definition: cryptlib.h:1288
BlockTransformation::ProcessBlock
void ProcessBlock(const byte *inBlock, byte *outBlock) const
Encrypt or decrypt a block.
Definition: cryptlib.h:884
BlockTransformation::AdvancedProcessBlocks
virtual size_t AdvancedProcessBlocks(const byte *inBlocks, const byte *xorBlocks, byte *outBlocks, size_t length, word32 flags) const
Encrypt and xor multiple blocks using additional flags.
BlockTransformation::BT_XorInput
@ BT_XorInput
Xor inputs before transformation.
Definition: cryptlib.h:926
BlockTransformation::BT_DontIncrementInOutPointers
@ BT_DontIncrementInOutPointers
should not modify block pointers
Definition: cryptlib.h:924
BlockTransformation::BlockSize
virtual unsigned int BlockSize() const =0
Provides the block size of the cipher.
CCM_Base::AlgorithmName
std::string AlgorithmName() const
Provides the name of this algorithm.
Definition: ccm.h:25
InvalidArgument
An invalid argument was detected.
Definition: cryptlib.h:208
NameValuePairs
Interface for retrieving values given their names.
Definition: cryptlib.h:327
NameValuePairs::GetIntValueWithDefault
CRYPTOPP_DLL int GetIntValueWithDefault(const char *name, int defaultValue) const
Get a named value with type int, with default.
Definition: cryptlib.h:429
SimpleKeyingInterface::SetKey
virtual void SetKey(const byte *key, size_t length, const NameValuePairs &params=g_nullNameValuePairs)
Sets or reset the key of this object.
byte
unsigned char byte
8-bit unsigned datatype
Definition: config_int.h:66
W64LIT
#define W64LIT(x)
Declare an unsigned word64.
Definition: config_int.h:129
word32
unsigned int word32
32-bit unsigned datatype
Definition: config_int.h:72
word16
unsigned short word16
16-bit unsigned datatype
Definition: config_int.h:69
lword
word64 lword
Large word type.
Definition: config_int.h:168
BIG_ENDIAN_ORDER
@ BIG_ENDIAN_ORDER
byte order is big-endian
Definition: cryptlib.h:152
xorbuf
CRYPTOPP_DLL void xorbuf(byte *buf, const byte *mask, size_t count)
Performs an XOR of a buffer with a mask.
CryptoPP
Crypto++ library namespace.
Name::DigestSize
const char * DigestSize()
int, in bytes
Definition: argnames.h:79
pch.h
Precompiled header file.
CRYPTOPP_ASSERT
#define CRYPTOPP_ASSERT(exp)
Debugging and diagnostic assertion.
Definition: trap.h:68