Team Fortress 2 Source Code as on 22/4/2020
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.

99 lines
2.7 KiB

  1. // dmac.h - written and placed in the public domain by Wei Dai
  2. //! \file
  3. //! \headerfile dmac.h
  4. //! \brief Classes for DMAC message authentication code
  5. #ifndef CRYPTOPP_DMAC_H
  6. #define CRYPTOPP_DMAC_H
  7. #include "cbcmac.h"
  8. NAMESPACE_BEGIN(CryptoPP)
  9. //! _
  10. template <class T>
  11. class CRYPTOPP_NO_VTABLE DMAC_Base : public SameKeyLengthAs<T>, public MessageAuthenticationCode
  12. {
  13. public:
  14. static std::string StaticAlgorithmName() {return std::string("DMAC(") + T::StaticAlgorithmName() + ")";}
  15. CRYPTOPP_CONSTANT(DIGESTSIZE=T::BLOCKSIZE)
  16. DMAC_Base() : m_subkeylength(0), m_counter(0) {}
  17. void UncheckedSetKey(const byte *key, unsigned int length, const NameValuePairs &params);
  18. void Update(const byte *input, size_t length);
  19. void TruncatedFinal(byte *mac, size_t size);
  20. unsigned int DigestSize() const {return DIGESTSIZE;}
  21. private:
  22. byte *GenerateSubKeys(const byte *key, size_t keylength);
  23. size_t m_subkeylength;
  24. SecByteBlock m_subkeys;
  25. CBC_MAC<T> m_mac1;
  26. typename T::Encryption m_f2;
  27. unsigned int m_counter;
  28. };
  29. //! DMAC
  30. /*! Based on "CBC MAC for Real-Time Data Sources" by Erez Petrank
  31. and Charles Rackoff. T should be a class derived from BlockCipherDocumentation.
  32. */
  33. template <class T>
  34. class DMAC : public MessageAuthenticationCodeFinal<DMAC_Base<T> >
  35. {
  36. public:
  37. DMAC() {}
  38. DMAC(const byte *key, size_t length=DMAC_Base<T>::DEFAULT_KEYLENGTH)
  39. {this->SetKey(key, length);}
  40. };
  41. template <class T>
  42. void DMAC_Base<T>::UncheckedSetKey(const byte *key, unsigned int length, const NameValuePairs &params)
  43. {
  44. m_subkeylength = T::StaticGetValidKeyLength(T::BLOCKSIZE);
  45. m_subkeys.resize(2*UnsignedMin((unsigned int)T::BLOCKSIZE, m_subkeylength));
  46. m_mac1.SetKey(GenerateSubKeys(key, length), m_subkeylength, params);
  47. m_f2.SetKey(m_subkeys+m_subkeys.size()/2, m_subkeylength, params);
  48. m_counter = 0;
  49. m_subkeys.resize(0);
  50. }
  51. template <class T>
  52. void DMAC_Base<T>::Update(const byte *input, size_t length)
  53. {
  54. m_mac1.Update(input, length);
  55. m_counter = (unsigned int)((m_counter + length) % T::BLOCKSIZE);
  56. }
  57. template <class T>
  58. void DMAC_Base<T>::TruncatedFinal(byte *mac, size_t size)
  59. {
  60. ThrowIfInvalidTruncatedSize(size);
  61. byte pad[T::BLOCKSIZE];
  62. byte padByte = byte(T::BLOCKSIZE-m_counter);
  63. memset(pad, padByte, padByte);
  64. m_mac1.Update(pad, padByte);
  65. m_mac1.TruncatedFinal(mac, size);
  66. m_f2.ProcessBlock(mac);
  67. m_counter = 0; // reset for next message
  68. }
  69. template <class T>
  70. byte *DMAC_Base<T>::GenerateSubKeys(const byte *key, size_t keylength)
  71. {
  72. typename T::Encryption cipher(key, keylength);
  73. memset(m_subkeys, 0, m_subkeys.size());
  74. cipher.ProcessBlock(m_subkeys);
  75. m_subkeys[m_subkeys.size()/2 + T::BLOCKSIZE - 1] = 1;
  76. cipher.ProcessBlock(m_subkeys+m_subkeys.size()/2);
  77. return m_subkeys;
  78. }
  79. NAMESPACE_END
  80. #endif