Coverage Report

Created: 2024-11-21 07:03

/src/cryptopp/ccm.cpp
Line
Count
Source (jump to first uncovered line)
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
5
{
13
5
  BlockCipher &blockCipher = AccessBlockCipher();
14
5
  blockCipher.SetKey(userKey, keylength, params);
15
16
5
  if (blockCipher.BlockSize() != REQUIRED_BLOCKSIZE)
17
0
    throw InvalidArgument(AlgorithmName() + ": block size of underlying block cipher is not 16");
18
19
5
  m_digestSize = params.GetIntValueWithDefault(Name::DigestSize(), DefaultDigestSize());
20
5
  if (m_digestSize % 2 > 0 || m_digestSize < 4 || m_digestSize > 16)
21
0
    throw InvalidArgument(AlgorithmName() + ": DigestSize must be 4, 6, 8, 10, 12, 14, or 16");
22
23
5
  m_buffer.Grow(2*REQUIRED_BLOCKSIZE);
24
5
  m_L = 8;
25
5
}
26
27
void CCM_Base::Resync(const byte *iv, size_t len)
28
0
{
29
0
  BlockCipher &cipher = AccessBlockCipher();
30
31
0
  m_L = REQUIRED_BLOCKSIZE-1-(int)len;
32
0
  CRYPTOPP_ASSERT(m_L >= 2);
33
0
  if (m_L > 8)
34
0
    m_L = 8;
35
36
0
  m_buffer[0] = byte(m_L-1);  // flag
37
0
  std::memcpy(m_buffer+1, iv, len);
38
0
  std::memset(m_buffer+1+len, 0, REQUIRED_BLOCKSIZE-1-len);
39
40
0
  if (m_state >= State_IVSet)
41
0
    m_ctr.Resynchronize(m_buffer, REQUIRED_BLOCKSIZE);
42
0
  else
43
0
    m_ctr.SetCipherWithIV(cipher, m_buffer);
44
45
0
  m_ctr.Seek(REQUIRED_BLOCKSIZE);
46
0
  m_aadLength = 0;
47
0
  m_messageLength = 0;
48
0
}
49
50
void CCM_Base::UncheckedSpecifyDataLengths(lword headerLength, lword messageLength, lword /*footerLength*/)
51
0
{
52
0
  if (m_state != State_IVSet)
53
0
    throw BadState(AlgorithmName(), "SpecifyDataLengths", "or after State_IVSet");
54
55
0
  m_aadLength = headerLength;
56
0
  m_messageLength = messageLength;
57
58
0
  byte *cbcBuffer = CBC_Buffer();
59
0
  const BlockCipher &cipher = GetBlockCipher();
60
61
0
  cbcBuffer[0] = byte(64*(headerLength>0) + 8*((m_digestSize-2)/2) + (m_L-1));  // flag
62
0
  PutWord<word64>(true, BIG_ENDIAN_ORDER, cbcBuffer+REQUIRED_BLOCKSIZE-8, m_messageLength);
63
0
  std::memcpy(cbcBuffer+1, m_buffer+1, REQUIRED_BLOCKSIZE-1-m_L);
64
0
  cipher.ProcessBlock(cbcBuffer);
65
66
0
  if (headerLength>0)
67
0
  {
68
0
    CRYPTOPP_ASSERT(m_bufferedDataLength == 0);
69
70
0
    if (headerLength < ((1<<16) - (1<<8)))
71
0
    {
72
0
      PutWord<word16>(true, BIG_ENDIAN_ORDER, m_buffer, (word16)headerLength);
73
0
      m_bufferedDataLength = 2;
74
0
    }
75
0
    else if (headerLength < (W64LIT(1)<<32))
76
0
    {
77
0
      m_buffer[0] = 0xff;
78
0
      m_buffer[1] = 0xfe;
79
0
      PutWord<word32>(false, BIG_ENDIAN_ORDER, m_buffer+2, (word32)headerLength);
80
0
      m_bufferedDataLength = 6;
81
0
    }
82
0
    else
83
0
    {
84
0
      m_buffer[0] = 0xff;
85
0
      m_buffer[1] = 0xff;
86
0
      PutWord<word64>(false, BIG_ENDIAN_ORDER, m_buffer+2, headerLength);
87
0
      m_bufferedDataLength = 10;
88
0
    }
89
0
  }
90
0
}
91
92
size_t CCM_Base::AuthenticateBlocks(const byte *data, size_t len)
93
0
{
94
0
  byte *cbcBuffer = CBC_Buffer();
95
0
  const BlockCipher &cipher = GetBlockCipher();
96
0
  return cipher.AdvancedProcessBlocks(cbcBuffer, data, cbcBuffer, len, BlockTransformation::BT_DontIncrementInOutPointers|BlockTransformation::BT_XorInput);
97
0
}
98
99
void CCM_Base::AuthenticateLastHeaderBlock()
100
0
{
101
0
  byte *cbcBuffer = CBC_Buffer();
102
0
  const BlockCipher &cipher = GetBlockCipher();
103
104
0
  if (m_aadLength != m_totalHeaderLength)
105
0
    throw InvalidArgument(AlgorithmName() + ": header length doesn't match that given in SpecifyDataLengths");
106
107
0
  if (m_bufferedDataLength > 0)
108
0
  {
109
0
    xorbuf(cbcBuffer, m_buffer, m_bufferedDataLength);
110
0
    cipher.ProcessBlock(cbcBuffer);
111
0
    m_bufferedDataLength = 0;
112
0
  }
113
0
}
114
115
void CCM_Base::AuthenticateLastConfidentialBlock()
116
0
{
117
0
  byte *cbcBuffer = CBC_Buffer();
118
0
  const BlockCipher &cipher = GetBlockCipher();
119
120
0
  if (m_messageLength != m_totalMessageLength)
121
0
    throw InvalidArgument(AlgorithmName() + ": message length doesn't match that given in SpecifyDataLengths");
122
123
0
  if (m_bufferedDataLength > 0)
124
0
  {
125
0
    xorbuf(cbcBuffer, m_buffer, m_bufferedDataLength);
126
0
    cipher.ProcessBlock(cbcBuffer);
127
0
    m_bufferedDataLength = 0;
128
0
  }
129
0
}
130
131
void CCM_Base::AuthenticateLastFooterBlock(byte *mac, size_t macSize)
132
0
{
133
0
  m_ctr.Seek(0);
134
0
  m_ctr.ProcessData(mac, CBC_Buffer(), macSize);
135
0
}
136
137
NAMESPACE_END
138
139
#endif