Counter Strike : Global Offensive Source Code
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

140 lines
3.8 KiB

  1. // ccm.cpp - written and placed in the public domain by Wei Dai
  2. #include "pch.h"
  3. #ifndef CRYPTOPP_IMPORTS
  4. #include "ccm.h"
  5. NAMESPACE_BEGIN(CryptoPP)
  6. void CCM_Base::SetKeyWithoutResync(const byte *userKey, size_t keylength, const NameValuePairs &params)
  7. {
  8. BlockCipher &blockCipher = AccessBlockCipher();
  9. blockCipher.SetKey(userKey, keylength, params);
  10. if (blockCipher.BlockSize() != REQUIRED_BLOCKSIZE)
  11. throw InvalidArgument(AlgorithmName() + ": block size of underlying block cipher is not 16");
  12. m_digestSize = params.GetIntValueWithDefault(Name::DigestSize(), DefaultDigestSize());
  13. if (m_digestSize % 2 > 0 || m_digestSize < 4 || m_digestSize > 16)
  14. throw InvalidArgument(AlgorithmName() + ": DigestSize must be 4, 6, 8, 10, 12, 14, or 16");
  15. m_buffer.Grow(2*REQUIRED_BLOCKSIZE);
  16. m_L = 8;
  17. }
  18. void CCM_Base::Resync(const byte *iv, size_t len)
  19. {
  20. BlockCipher &cipher = AccessBlockCipher();
  21. m_L = REQUIRED_BLOCKSIZE-1-(int)len;
  22. assert(m_L >= 2);
  23. if (m_L > 8)
  24. m_L = 8;
  25. m_buffer[0] = byte(m_L-1); // flag
  26. memcpy(m_buffer+1, iv, len);
  27. memset(m_buffer+1+len, 0, REQUIRED_BLOCKSIZE-1-len);
  28. if (m_state >= State_IVSet)
  29. m_ctr.Resynchronize(m_buffer, REQUIRED_BLOCKSIZE);
  30. else
  31. m_ctr.SetCipherWithIV(cipher, m_buffer);
  32. m_ctr.Seek(REQUIRED_BLOCKSIZE);
  33. m_aadLength = 0;
  34. m_messageLength = 0;
  35. }
  36. void CCM_Base::UncheckedSpecifyDataLengths(lword headerLength, lword messageLength, lword footerLength)
  37. {
  38. if (m_state != State_IVSet)
  39. throw BadState(AlgorithmName(), "SpecifyDataLengths", "or after State_IVSet");
  40. m_aadLength = headerLength;
  41. m_messageLength = messageLength;
  42. byte *cbcBuffer = CBC_Buffer();
  43. const BlockCipher &cipher = GetBlockCipher();
  44. cbcBuffer[0] = byte(64*(headerLength>0) + 8*((m_digestSize-2)/2) + (m_L-1)); // flag
  45. PutWord<word64>(true, BIG_ENDIAN_ORDER, cbcBuffer+REQUIRED_BLOCKSIZE-8, m_messageLength);
  46. memcpy(cbcBuffer+1, m_buffer+1, REQUIRED_BLOCKSIZE-1-m_L);
  47. cipher.ProcessBlock(cbcBuffer);
  48. if (headerLength>0)
  49. {
  50. assert(m_bufferedDataLength == 0);
  51. if (headerLength < ((1<<16) - (1<<8)))
  52. {
  53. PutWord<word16>(true, BIG_ENDIAN_ORDER, m_buffer, (word16)headerLength);
  54. m_bufferedDataLength = 2;
  55. }
  56. else if (headerLength < (W64LIT(1)<<32))
  57. {
  58. m_buffer[0] = 0xff;
  59. m_buffer[1] = 0xfe;
  60. PutWord<word32>(false, BIG_ENDIAN_ORDER, m_buffer+2, (word32)headerLength);
  61. m_bufferedDataLength = 6;
  62. }
  63. else
  64. {
  65. m_buffer[0] = 0xff;
  66. m_buffer[1] = 0xff;
  67. PutWord<word64>(false, BIG_ENDIAN_ORDER, m_buffer+2, headerLength);
  68. m_bufferedDataLength = 10;
  69. }
  70. }
  71. }
  72. size_t CCM_Base::AuthenticateBlocks(const byte *data, size_t len)
  73. {
  74. byte *cbcBuffer = CBC_Buffer();
  75. const BlockCipher &cipher = GetBlockCipher();
  76. return cipher.AdvancedProcessBlocks(cbcBuffer, data, cbcBuffer, len, BlockTransformation::BT_DontIncrementInOutPointers|BlockTransformation::BT_XorInput);
  77. }
  78. void CCM_Base::AuthenticateLastHeaderBlock()
  79. {
  80. byte *cbcBuffer = CBC_Buffer();
  81. const BlockCipher &cipher = GetBlockCipher();
  82. if (m_aadLength != m_totalHeaderLength)
  83. throw InvalidArgument(AlgorithmName() + ": header length doesn't match that given in SpecifyDataLengths");
  84. if (m_bufferedDataLength > 0)
  85. {
  86. xorbuf(cbcBuffer, m_buffer, m_bufferedDataLength);
  87. cipher.ProcessBlock(cbcBuffer);
  88. m_bufferedDataLength = 0;
  89. }
  90. }
  91. void CCM_Base::AuthenticateLastConfidentialBlock()
  92. {
  93. byte *cbcBuffer = CBC_Buffer();
  94. const BlockCipher &cipher = GetBlockCipher();
  95. if (m_messageLength != m_totalMessageLength)
  96. throw InvalidArgument(AlgorithmName() + ": message length doesn't match that given in SpecifyDataLengths");
  97. if (m_bufferedDataLength > 0)
  98. {
  99. xorbuf(cbcBuffer, m_buffer, m_bufferedDataLength);
  100. cipher.ProcessBlock(cbcBuffer);
  101. m_bufferedDataLength = 0;
  102. }
  103. }
  104. void CCM_Base::AuthenticateLastFooterBlock(byte *mac, size_t macSize)
  105. {
  106. m_ctr.Seek(0);
  107. m_ctr.ProcessData(mac, CBC_Buffer(), macSize);
  108. }
  109. NAMESPACE_END
  110. #endif