Crypto++  5.6.3
Free C++ class library of cryptographic schemes
cmac.cpp
1 // cmac.cpp - 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  k[30] ^= 4;
35  k[31] ^= 0x23;
36  break;
37  default:
38  throw InvalidArgument("CMAC: " + IntToString(length) + " is not a supported cipher block size");
39  }
40  }
41 }
42 
43 void CMAC_Base::UncheckedSetKey(const byte *key, unsigned int length, const NameValuePairs &params)
44 {
45  BlockCipher &cipher = AccessCipher();
46  unsigned int blockSize = cipher.BlockSize();
47 
48  cipher.SetKey(key, length, params);
49  m_reg.CleanNew(3*blockSize);
50  m_counter = 0;
51 
52  cipher.ProcessBlock(m_reg, m_reg+blockSize);
53  MulU(m_reg+blockSize, blockSize);
54  memcpy(m_reg+2*blockSize, m_reg+blockSize, blockSize);
55  MulU(m_reg+2*blockSize, blockSize);
56 }
57 
58 void CMAC_Base::Update(const byte *input, size_t length)
59 {
60  assert((input && length) || !(input || length));
61  if (!length)
62  return;
63 
64  BlockCipher &cipher = AccessCipher();
65  unsigned int blockSize = cipher.BlockSize();
66 
67  if (m_counter > 0)
68  {
69  const unsigned int len = UnsignedMin(blockSize - m_counter, length);
70  if (len)
71  {
72  xorbuf(m_reg+m_counter, input, len);
73  length -= len;
74  input += len;
75  m_counter += len;
76  }
77 
78  if (m_counter == blockSize && length > 0)
79  {
80  cipher.ProcessBlock(m_reg);
81  m_counter = 0;
82  }
83  }
84 
85  if (length > blockSize)
86  {
87  assert(m_counter == 0);
88  size_t leftOver = 1 + cipher.AdvancedProcessBlocks(m_reg, input, m_reg, length-1, BlockTransformation::BT_DontIncrementInOutPointers|BlockTransformation::BT_XorInput);
89  input += (length - leftOver);
90  length = leftOver;
91  }
92 
93  if (length > 0)
94  {
95  assert(m_counter + length <= blockSize);
96  xorbuf(m_reg+m_counter, input, length);
97  m_counter += (unsigned int)length;
98  }
99 
100  assert(m_counter > 0);
101 }
102 
103 void CMAC_Base::TruncatedFinal(byte *mac, size_t size)
104 {
105  ThrowIfInvalidTruncatedSize(size);
106 
107  BlockCipher &cipher = AccessCipher();
108  unsigned int blockSize = cipher.BlockSize();
109 
110  if (m_counter < blockSize)
111  {
112  m_reg[m_counter] ^= 0x80;
113  cipher.AdvancedProcessBlocks(m_reg, m_reg+2*blockSize, m_reg, blockSize, BlockTransformation::BT_DontIncrementInOutPointers|BlockTransformation::BT_XorInput);
114  }
115  else
116  cipher.AdvancedProcessBlocks(m_reg, m_reg+blockSize, m_reg, blockSize, BlockTransformation::BT_DontIncrementInOutPointers|BlockTransformation::BT_XorInput);
117 
118  memcpy(mac, m_reg, size);
119 
120  m_counter = 0;
121  memset(m_reg, 0, blockSize);
122 }
123 
124 NAMESPACE_END
125 
126 #endif
An invalid argument was detected.
Definition: cryptlib.h:182
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:100
void CleanNew(size_type newSize)
Change size without preserving contents.
Definition: secblock.h:652
virtual unsigned int BlockSize() const =0
Provides the block size of the cipher.
should not modify block pointers
Definition: cryptlib.h:775
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:181
Classes for CMAC message authentication code.
Interface for one direction (encryption or decryption) of a block cipher.
Definition: cryptlib.h:1081
void ProcessBlock(const byte *inBlock, byte *outBlock) const
Encrypt or decrypt a block.
Definition: cryptlib.h:737
void UncheckedSetKey(const byte *key, unsigned int length, const NameValuePairs &params)
Sets the key for this object without performing parameter validation.
Definition: cmac.cpp:43
const T1 UnsignedMin(const T1 &a, const T2 &b)
Safe comparison of values that could be neagtive and incorrectly promoted.
Definition: misc.h:433
void xorbuf(byte *buf, const byte *mask, size_t count)
Performs an XOR of a buffer with a mask.
Definition: misc.cpp:28
std::string IntToString(T value, unsigned int base=10)
Converts a value to a string.
Definition: misc.h:460
void TruncatedFinal(byte *mac, size_t size)
Computes the hash of the current message.
Definition: cmac.cpp:103
Crypto++ library namespace.
void Update(const byte *input, size_t length)
Updates a hash with additional input.
Definition: cmac.cpp:58
Interface for retrieving values given their names.
Definition: cryptlib.h:277