RLPXFrameCoder.h 6.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182
  1. /*
  2. This file is part of cpp-ethereum.
  3. cpp-ethereum is free software: you can redistribute it and/or modify
  4. it under the terms of the GNU General Public License as published by
  5. the Free Software Foundation, either version 3 of the License, or
  6. (at your option) any later version.
  7. cpp-ethereum is distributed in the hope that it will be useful,
  8. but WITHOUT ANY WARRANTY; without even the implied warranty of
  9. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  10. GNU General Public License for more details.
  11. You should have received a copy of the GNU General Public License
  12. along with cpp-ethereum. If not, see <http://www.gnu.org/licenses/>.
  13. */
  14. /** @file RLPXFrameCoder.h
  15. * @author Alex Leverington <nessence@gmail.com>
  16. * @date 2015
  17. */
  18. #pragma once
  19. #include <memory>
  20. #include <libdevcore/Guards.h>
  21. #include <libdevcrypto/ECDHE.h>
  22. #include <libdevcrypto/CryptoPP.h>
  23. #include "Common.h"
  24. namespace dev
  25. {
  26. namespace p2p
  27. {
  28. struct RLPXFrameDecryptFailed: virtual dev::Exception {};
  29. /**
  30. * @brief Encapsulation of Frame
  31. * @todo coder integration; padding derived from coder
  32. */
  33. struct RLPXFrameInfo
  34. {
  35. RLPXFrameInfo() = default;
  36. /// Constructor. frame-size || protocol-type, [sequence-id[, total-packet-size]]
  37. RLPXFrameInfo(bytesConstRef _frameHeader);
  38. uint32_t const length; ///< Size of frame (excludes padding). Max: 2**24
  39. uint8_t const padding; ///< Length of padding which follows @length.
  40. bytes const data; ///< Bytes of Header.
  41. RLP const header; ///< Header RLP.
  42. uint16_t const protocolId; ///< Protocol ID as negotiated by handshake.
  43. bool const multiFrame; ///< If this frame is part of a sequence
  44. uint16_t const sequenceId; ///< Sequence ID of frame
  45. uint32_t const totalLength; ///< Set to total length of packet in first frame of multiframe packet
  46. };
  47. class RLPXHandshake;
  48. /**
  49. * @brief Encoder/decoder transport for RLPx connection established by RLPXHandshake.
  50. *
  51. * @todo rename to RLPXTranscoder
  52. * @todo Remove 'Frame' nomenclature and expect caller to provide RLPXFrame
  53. * @todo Remove handshake as friend, remove handshake-based constructor
  54. *
  55. * Thread Safety
  56. * Distinct Objects: Unsafe.
  57. * Shared objects: Unsafe.
  58. */
  59. class RLPXFrameCoder
  60. {
  61. friend class RLPXFrameIOMux;
  62. friend class Session;
  63. public:
  64. /// Construct; requires instance of RLPXHandshake which has encrypted ECDH key exchange (first two phases of handshake).
  65. RLPXFrameCoder(RLPXHandshake const& _init);
  66. /// Construct with external key material.
  67. RLPXFrameCoder(bool _originated, h512 const& _remoteEphemeral, h256 const& _remoteNonce, crypto::ECDHE const& _ephemeral, h256 const& _nonce, bytesConstRef _ackCipher, bytesConstRef _authCipher);
  68. ~RLPXFrameCoder() {}
  69. /// Establish shared secrets and setup AES and MAC states.
  70. void setup(bool _originated, h512 const& _remoteEphemeral, h256 const& _remoteNonce, crypto::ECDHE const& _ephemeral, h256 const& _nonce, bytesConstRef _ackCipher, bytesConstRef _authCipher);
  71. /// Write single-frame payload of packet(s).
  72. void writeFrame(uint16_t _protocolType, bytesConstRef _payload, bytes& o_bytes);
  73. /// Write continuation frame of segmented payload.
  74. void writeFrame(uint16_t _protocolType, uint16_t _seqId, bytesConstRef _payload, bytes& o_bytes);
  75. /// Write first frame of segmented or sequence-tagged payload.
  76. void writeFrame(uint16_t _protocolType, uint16_t _seqId, uint32_t _totalSize, bytesConstRef _payload, bytes& o_bytes);
  77. /// Legacy. Encrypt _packet as ill-defined legacy RLPx frame.
  78. void writeSingleFramePacket(bytesConstRef _packet, bytes& o_bytes);
  79. /// Authenticate and decrypt header in-place.
  80. bool authAndDecryptHeader(bytesRef io_cipherWithMac);
  81. /// Authenticate and decrypt frame in-place.
  82. bool authAndDecryptFrame(bytesRef io_cipherWithMac);
  83. /// Return first 16 bytes of current digest from egress mac.
  84. h128 egressDigest();
  85. /// Return first 16 bytes of current digest from ingress mac.
  86. h128 ingressDigest();
  87. protected:
  88. void writeFrame(RLPStream const& _header, bytesConstRef _payload, bytes& o_bytes);
  89. /// Update state of egress MAC with frame header.
  90. void updateEgressMACWithHeader(bytesConstRef _headerCipher);
  91. /// Update state of egress MAC with frame.
  92. void updateEgressMACWithFrame(bytesConstRef _cipher);
  93. /// Update state of ingress MAC with frame header.
  94. void updateIngressMACWithHeader(bytesConstRef _headerCipher);
  95. /// Update state of ingress MAC with frame.
  96. void updateIngressMACWithFrame(bytesConstRef _cipher);
  97. private:
  98. #if defined(__GNUC__)
  99. // Do not warn about uses of functions (see Function Attributes), variables
  100. // (see Variable Attributes), and types (see Type Attributes) marked as
  101. // deprecated by using the deprecated attribute.
  102. //
  103. // Specifically we are suppressing the warnings from the deprecation
  104. // attributes added to the SHA3_256 and SHA3_512 classes in CryptoPP
  105. // after the 5.6.3 release.
  106. //
  107. // From that header file ...
  108. //
  109. // "The Crypto++ SHA-3 implementation dates back to January 2013 when NIST
  110. // selected Keccak as SHA-3. In August 2015 NIST finalized SHA-3, and it
  111. // was a modified version of the Keccak selection. Crypto++ 5.6.2 through
  112. // 5.6.4 provides the pre-FIPS 202 version of SHA-3; while Crypto++ 5.7
  113. // and above provides the FIPS 202 version of SHA-3.
  114. //
  115. // See also http://en.wikipedia.org/wiki/SHA-3
  116. //
  117. // This means that we will never be able to move to the CryptoPP-5.7.x
  118. // series of releases, because Ethereum requires Keccak, not the final
  119. // SHA-3 standard algorithm. We are planning to migrate cpp-ethereum
  120. // off CryptoPP anyway, so this is unlikely to be a long-standing issue.
  121. //
  122. // https://github.com/ethereum/cpp-ethereum/issues/3088
  123. //
  124. #pragma GCC diagnostic push
  125. #pragma GCC diagnostic ignored "-Wdeprecated-declarations"
  126. #endif // defined(__GNUC__)
  127. /// Update state of _mac.
  128. void updateMAC(CryptoPP::SHA3_256& _mac, bytesConstRef _seed = bytesConstRef());
  129. CryptoPP::SecByteBlock m_frameEncKey; ///< Key for m_frameEnc
  130. CryptoPP::CTR_Mode<CryptoPP::AES>::Encryption m_frameEnc; ///< Encoder for egress plaintext.
  131. CryptoPP::SecByteBlock m_frameDecKey; ///< Key for m_frameDec
  132. CryptoPP::CTR_Mode<CryptoPP::AES>::Encryption m_frameDec; ///< Decoder for egress plaintext.
  133. CryptoPP::SecByteBlock m_macEncKey; /// Key for m_macEnd
  134. CryptoPP::ECB_Mode<CryptoPP::AES>::Encryption m_macEnc; /// One-way coder used by updateMAC for ingress and egress MAC updates.
  135. Mutex x_macEnc; /// Mutex
  136. CryptoPP::SHA3_256 m_egressMac; ///< State of MAC for egress ciphertext.
  137. CryptoPP::SHA3_256 m_ingressMac; ///< State of MAC for ingress ciphertext.
  138. #if defined(__GNUC__)
  139. #pragma GCC diagnostic pop
  140. #endif // defined(__GNUC__)
  141. };
  142. }
  143. }