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

cmac.cpp
1 // cmac.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 "cmac.h"
8
9 NAMESPACE_BEGIN(CryptoPP)
10
11 static void MulU(byte *k, unsigned int length)
12 {
13 byte carry = 0;
14
15 for (int i=length-1; i>=1; i-=2)
16 {
17 byte carry2 = k[i] >> 7;
18 k[i] += k[i] + carry;
19 carry = k[i-1] >> 7;
20 k[i-1] += k[i-1] + carry2;
21 }
22
23 if (carry)
24 {
25 switch (length)
26 {
27 case 8:
28 k[7] ^= 0x1b;
29 break;
30 case 16:
31 k[15] ^= 0x87;
32 break;
33 case 32:
34 // https://crypto.stackexchange.com/q/9815/10496
35 // Polynomial x^256 + x^10 + x^5 + x^2 + 1
36 k[30] ^= 4;
37 k[31] ^= 0x25;
38 break;
39 case 64:
40 // https://crypto.stackexchange.com/q/9815/10496
41 // Polynomial x^512 + x^8 + x^5 + x^2 + 1
42 k[62] ^= 1;
43 k[63] ^= 0x25;
44 break;
45 case 128:
46 // https://crypto.stackexchange.com/q/9815/10496
47 // Polynomial x^1024 + x^19 + x^6 + x + 1
48 k[125] ^= 8;
49 k[126] ^= 0x00;
50 k[127] ^= 0x43;
51 break;
52 default:
53 throw InvalidArgument("CMAC: " + IntToString(length) + " is not a supported cipher block size");
54 }
55 }
56 }
57
58 void CMAC_Base::UncheckedSetKey(const byte *key, unsigned int length, const NameValuePairs &params)
59 {
60 BlockCipher &cipher = AccessCipher();
61 cipher.SetKey(key, length, params);
62
63 unsigned int blockSize = cipher.BlockSize();
64 m_reg.CleanNew(3*blockSize);
65 m_counter = 0;
66
67 cipher.ProcessBlock(m_reg, m_reg+blockSize);
68 MulU(m_reg+blockSize, blockSize);
69 memcpy(m_reg+2*blockSize, m_reg+blockSize, blockSize);
70 MulU(m_reg+2*blockSize, blockSize);
71 }
72
73 void CMAC_Base::Update(const byte *input, size_t length)
74 {
75 CRYPTOPP_ASSERT((input && length) || !(input || length));
76 if (!length)
77 return;
78
79 BlockCipher &cipher = AccessCipher();
80 unsigned int blockSize = cipher.BlockSize();
81
82 if (m_counter > 0)
83 {
84 const unsigned int len = UnsignedMin(blockSize - m_counter, length);
85 if (len)
86 {
87 xorbuf(m_reg+m_counter, input, len);
88 length -= len;
89 input += len;
90 m_counter += len;
91 }
92
93 if (m_counter == blockSize && length > 0)
94 {
95 cipher.ProcessBlock(m_reg);
96 m_counter = 0;
97 }
98 }
99
100 if (length > blockSize)
101 {
102 CRYPTOPP_ASSERT(m_counter == 0);
103 size_t leftOver = 1 + cipher.AdvancedProcessBlocks(m_reg, input, m_reg, length-1, BlockTransformation::BT_DontIncrementInOutPointers|BlockTransformation::BT_XorInput);
104 input += (length - leftOver);
105 length = leftOver;
106 }
107
108 if (length > 0)
109 {
110 CRYPTOPP_ASSERT(m_counter + length <= blockSize);
111 xorbuf(m_reg+m_counter, input, length);
112 m_counter += (unsigned int)length;
113 }
114
115 CRYPTOPP_ASSERT(m_counter > 0);
116 }
117
118 void CMAC_Base::TruncatedFinal(byte *mac, size_t size)
119 {
120 ThrowIfInvalidTruncatedSize(size);
121
122 BlockCipher &cipher = AccessCipher();
123 unsigned int blockSize = cipher.BlockSize();
124
125 if (m_counter < blockSize)
126 {
127 m_reg[m_counter] ^= 0x80;
128 cipher.AdvancedProcessBlocks(m_reg, m_reg+2*blockSize, m_reg, blockSize, BlockTransformation::BT_DontIncrementInOutPointers|BlockTransformation::BT_XorInput);
129 }
130 else
131 cipher.AdvancedProcessBlocks(m_reg, m_reg+blockSize, m_reg, blockSize, BlockTransformation::BT_DontIncrementInOutPointers|BlockTransformation::BT_XorInput);
132
133 memcpy(mac, m_reg, size);
134
135 m_counter = 0;
136 memset(m_reg, 0, blockSize);
137 }
138
139 NAMESPACE_END
140
141 #endif
InvalidArgument
An invalid argument was detected.
Definition: cryptlib.h:202
SimpleKeyingInterface::SetKey
virtual void SetKey(const byte *key, size_t length, const NameValuePairs &params=g_nullNameValuePairs)
Sets or reset the key of this object.
Definition: cryptlib.cpp:58
SecBlock::CleanNew
void CleanNew(size_type newSize)
Change size without preserving contents.
Definition: secblock.h:974
BlockTransformation::BT_DontIncrementInOutPointers
should not modify block pointers
Definition: cryptlib.h:891
cmac.h
Classes for CMAC message authentication code.
BlockCipher
Interface for one direction (encryption or decryption) of a block cipher.
Definition: cryptlib.h:1248
BlockTransformation::BlockSize
virtual unsigned int BlockSize() const =0
Provides the block size of the cipher.
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.
Definition: cryptlib.cpp:141
pch.h
Precompiled header file.
BlockTransformation::ProcessBlock
void ProcessBlock(const byte *inBlock, byte *outBlock) const
Encrypt or decrypt a block.
Definition: cryptlib.h:851
CMAC_Base::UncheckedSetKey
void UncheckedSetKey(const byte *key, unsigned int length, const NameValuePairs &params)
Sets the key for this object without performing parameter validation.
Definition: cmac.cpp:58
UnsignedMin
const T1 UnsignedMin(const T1 &a, const T2 &b)
Safe comparison of values that could be neagtive and incorrectly promoted.
Definition: misc.h:602
CRYPTOPP_ASSERT
#define CRYPTOPP_ASSERT(exp)
Debugging and diagnostic assertion.
Definition: trap.h:60
xorbuf
void xorbuf(byte *buf, const byte *mask, size_t count)
Performs an XOR of a buffer with a mask.
Definition: misc.cpp:32
BlockTransformation::BT_XorInput
Xor inputs before transformation.
Definition: cryptlib.h:893
IntToString
std::string IntToString(T value, unsigned int base=10)
Converts a value to a string.
Definition: misc.h:632
CMAC_Base::TruncatedFinal
void TruncatedFinal(byte *mac, size_t size)
Computes the hash of the current message.
Definition: cmac.cpp:118
CryptoPP
Crypto++ library namespace.
CMAC_Base::Update
void Update(const byte *input, size_t length)
Updates a hash with additional input.
Definition: cmac.cpp:73
NameValuePairs
Interface for retrieving values given their names.
Definition: cryptlib.h:293