Branch data Line data Source code
1 : : // Copyright 2026 HPActor Contributors
2 : : //
3 : : // Licensed under the Apache License, Version 2.0 (the "License");
4 : : // you may not use this file except in compliance with the License.
5 : : // You may obtain a copy of the License at
6 : : //
7 : : // http://www.apache.org/licenses/LICENSE-2.0
8 : : //
9 : : // Unless required by applicable law or agreed to in writing, software
10 : : // distributed under the License is distributed on an "AS IS" BASIS,
11 : : // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 : : // See the License for the specific language governing permissions and
13 : : // limitations under the License.
14 : :
15 : : #pragma once
16 : :
17 : : #include <hpactor/adt/stream_buffer.hpp>
18 : : #include <hpactor/net/event_loop.hpp>
19 : : #include <hpactor/net/tls_context.hpp>
20 : : #include <hpactor/net/transport.hpp>
21 : :
22 : : #include <array>
23 : : #include <deque>
24 : : #include <functional>
25 : :
26 : : namespace hpactor {
27 : :
28 : : namespace net {
29 : :
30 : : // -----------------------------------------------------------------------------
31 : : // TlsConnection - TLS connection with handshake and encrypted session
32 : : // -----------------------------------------------------------------------------
33 : : // Implements the TLS-like handshake protocol with mutual certificate
34 : : // authentication and RSA key transport for session encryption.
35 : : // -----------------------------------------------------------------------------
36 : :
37 : : // TLS message types for the handshake protocol
38 : : enum class TlsMessageType : uint8_t {
39 : : ClientHello = 1,
40 : : ServerHello = 2,
41 : : Certificate = 3,
42 : : CertificateVerify = 4,
43 : : Finished = 5,
44 : : };
45 : :
46 : : // Handshake state machine states
47 : : enum class TlsHandshakeState : uint8_t {
48 : : Idle,
49 : : WaitingForServerHello,
50 : : WaitingForCertificate,
51 : : WaitingForCertificateVerify,
52 : : WaitingForFinished,
53 : : HandshakeComplete,
54 : : Error,
55 : : };
56 : :
57 : : // Session state (post-handshake)
58 : : enum class TlsSessionState : uint8_t {
59 : : Handshake,
60 : : Encrypted,
61 : : Error,
62 : : };
63 : :
64 : : // Fixed-size nonces
65 : : constexpr size_t kNonceSize = 32;
66 : : using Nonce = std::array<uint8_t, kNonceSize>;
67 : :
68 : : // Connection pointer
69 : : class TlsConnection;
70 : : using TlsConnectionPtr = std::shared_ptr<TlsConnection>;
71 : :
72 : : class TlsConnection : public Connection,
73 : : public std::enable_shared_from_this<TlsConnection> {
74 : : public:
75 : : // Create client-side connection
76 : : static TlsConnectionPtr create_client(EndPoint local_endpoint,
77 : : EndPoint remote_endpoint,
78 : : TlsContext* tls_context, EventLoop* loop);
79 : :
80 : : // Create server-side connection (from accepted socket)
81 : : static TlsConnectionPtr
82 : : create_server(int fd, EndPoint local_endpoint, EndPoint remote_endpoint,
83 : : TlsContext* tls_context, EventLoop* loop);
84 : :
85 : : // Set file descriptor (for connected client sockets after TCP handshake)
86 : : void set_fd(int fd);
87 : :
88 : : ~TlsConnection();
89 : :
90 : : // Non-copyable
91 : : TlsConnection(const TlsConnection&) = delete;
92 : : TlsConnection& operator=(const TlsConnection&) = delete;
93 : :
94 : : // Set callbacks
95 : : void set_ready_handler(std::function<void(ConnectionPtr)> handler);
96 : : void set_frame_handler(frame_handler handler);
97 : : void
98 : : set_error_handler(std::function<void(ConnectionPtr, const error&)> handler);
99 : : void set_send_completion_handler(std::function<void(int result)> handler);
100 : :
101 : : // Complete post-connect setup: registers for Read events and establishes
102 : : // the read handler. Static to avoid shared_from_this issues.
103 : : static void setup_after_connect(TlsConnectionPtr conn);
104 : :
105 : : // Initiate client handshake (called after connection established)
106 : : void start_client_handshake();
107 : :
108 : : // Handle incoming data from socket
109 : : void handle_read() override;
110 : :
111 : : // Send encrypted frame
112 : : void send(const StreamBuffer& frame_data) override;
113 : :
114 : : // Close connection
115 : : void close() override;
116 : :
117 : : // Handle send completion (called by TcpTransport on async_send completion)
118 : : void handle_send_completion(int result) override;
119 : :
120 : : // Get session state
121 : 7 : TlsSessionState session_state() const {
122 : 7 : return session_state_;
123 : : }
124 : :
125 : : private:
126 : : TlsConnection(int fd, EndPoint local_endpoint, EndPoint remote_endpoint,
127 : : TlsContext* tls_context, EventLoop* loop);
128 : :
129 : : // Handshake message builders
130 : : StreamBuffer build_client_hello();
131 : : StreamBuffer build_certificate();
132 : : StreamBuffer build_certificate_verify(const Nonce& challenge);
133 : : StreamBuffer build_finished();
134 : :
135 : : // Handshake message handlers
136 : : void handle_server_hello(const StreamBuffer& data);
137 : : void handle_certificate(const StreamBuffer& data);
138 : : void handle_certificate_verify(const StreamBuffer& data);
139 : : void handle_finished(const StreamBuffer& data);
140 : :
141 : : // Process buffered data (TLS record parsing and dispatch)
142 : : void process_buffer();
143 : :
144 : : // Helper: derive session key from pre_master_secret
145 : : void derive_session_keys(const StreamBuffer& pre_master_secret,
146 : : const Nonce& client_nonce, const Nonce& server_nonce);
147 : :
148 : : // Helper: encrypt data with session key (AES-256-CBC)
149 : : StreamBuffer encrypt_aes(const StreamBuffer& plaintext);
150 : :
151 : : // Helper: decrypt data with session key
152 : : StreamBuffer decrypt_aes(const StreamBuffer& ciphertext);
153 : :
154 : : // Helper: compute TLS PRF (SHA-256 based)
155 : : StreamBuffer prf_sha256(const StreamBuffer& secret, const char* label, const StreamBuffer& data);
156 : :
157 : : // Transition handshake/session state
158 : : void set_handshake_state(TlsHandshakeState new_state);
159 : : void set_session_state(TlsSessionState new_state);
160 : :
161 : : // Send raw bytes on socket
162 : : void send_raw(const StreamBuffer& data);
163 : :
164 : : // Flush write buffer (called after async_send completion)
165 : : void flush_write_buffer();
166 : :
167 : : TlsContext* tls_context_ = nullptr;
168 : :
169 : : TlsHandshakeState handshake_state_ = TlsHandshakeState::Idle;
170 : : TlsSessionState session_state_ = TlsSessionState::Handshake;
171 : :
172 : : // Handshake nonces
173 : : Nonce client_nonce_;
174 : : Nonce server_nonce_;
175 : : StreamBuffer pre_master_secret_;
176 : :
177 : : // Session keys
178 : : StreamBuffer master_secret_;
179 : : StreamBuffer session_key_; // AES-256 key
180 : : StreamBuffer session_iv_; // AES IV
181 : :
182 : : // Read buffer
183 : : adt::StreamBuffer read_buffer_;
184 : :
185 : : // Write buffer
186 : : adt::StreamBuffer write_buffer_;
187 : :
188 : : // True while async send is in progress
189 : : bool is_sending_ = false;
190 : :
191 : : // Handshake message buffer (for Finished verify_data)
192 : : StreamBuffer handshake_messages_;
193 : :
194 : : // Callbacks
195 : : std::function<void(ConnectionPtr)> ready_handler_;
196 : : frame_handler frame_handler_;
197 : : std::function<void(ConnectionPtr, const error&)> error_handler_;
198 : : std::function<void(int result)> send_completion_handler_;
199 : :
200 : : // Server-side flag
201 : : bool is_server_ = false;
202 : :
203 : : // Read chunk size
204 : : static constexpr size_t kReadChunkSize = 65536;
205 : : };
206 : :
207 : : } // namespace net
208 : : } // namespace hpactor
|