OpenTTD Source  20240919-master-gdf0233f4c2
test_network_crypto.cpp
Go to the documentation of this file.
1 /*
2  * This file is part of OpenTTD.
3  * OpenTTD is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, version 2.
4  * OpenTTD is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
5  * See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with OpenTTD. If not, see <http://www.gnu.org/licenses/>.
6  */
7 
10 #include "../stdafx.h"
11 
12 #include "../3rdparty/catch2/catch.hpp"
13 
14 #include "../core/format.hpp"
15 #include "../network/network_crypto_internal.h"
16 #include "../network/core/packet.h"
17 #include "../string_func.h"
18 
19 /* The length of the hexadecimal representation of a X25519 key must fit in the key length. */
20 static_assert(NETWORK_SECRET_KEY_LENGTH >= X25519_KEY_SIZE * 2 + 1);
21 static_assert(NETWORK_PUBLIC_KEY_LENGTH >= X25519_KEY_SIZE * 2 + 1);
22 
24 public:
25  MockNetworkSocketHandler(std::unique_ptr<NetworkEncryptionHandler> &&receive = {}, std::unique_ptr<NetworkEncryptionHandler> &&send = {})
26  {
27  this->receive_encryption_handler = std::move(receive);
28  this->send_encryption_handler = std::move(send);
29  }
30 };
31 
32 static MockNetworkSocketHandler mock_socket_handler;
33 
34 static std::tuple<Packet, bool> CreatePacketForReading(Packet &source, MockNetworkSocketHandler *socket_handler)
35 {
36  source.PrepareToSend();
37 
38  Packet dest(socket_handler, COMPAT_MTU, source.Size());
39 
40  auto transfer_in = [](Packet &source, char *dest_data, size_t length) {
41  auto transfer_out = [](char *dest_data, const char *source_data, size_t length) {
42  std::copy(source_data, source_data + length, dest_data);
43  return length;
44  };
45  return source.TransferOutWithLimit(transfer_out, length, dest_data);
46  };
47  dest.TransferIn(transfer_in, source);
48 
49  bool valid = dest.PrepareToRead();
50  dest.Recv_uint8(); // Ignore the type
51  return { dest, valid };
52 }
53 
55 private:
56  std::string password;
57 public:
58  TestPasswordRequestHandler(std::string &password) : password(password) {}
59  void SendResponse() override {}
60  void AskUserForPassword(std::shared_ptr<NetworkAuthenticationPasswordRequest> request) override { request->Reply(this->password); }
61 };
62 
63 static void TestAuthentication(NetworkAuthenticationServerHandler &server, NetworkAuthenticationClientHandler &client,
66 {
67  Packet request(&mock_socket_handler, PacketType{});
68  server.SendRequest(request);
69 
70  bool valid;
71  std::tie(request, valid) = CreatePacketForReading(request, &mock_socket_handler);
72  CHECK(valid);
73  CHECK(client.ReceiveRequest(request) == expected_request_result);
74 
75  Packet response(&mock_socket_handler, PacketType{});
76  client.SendResponse(response);
77 
78  std::tie(response, valid) = CreatePacketForReading(response, &mock_socket_handler);
79  CHECK(valid);
80  CHECK(server.ReceiveResponse(response) == expected_response_result);
81 }
82 
83 
84 TEST_CASE("Authentication_KeyExchangeOnly")
85 {
88 
90 }
91 
92 
93 static void TestAuthenticationPAKE(std::string server_password, std::string client_password,
95 {
96  NetworkAuthenticationDefaultPasswordProvider server_password_provider(server_password);
97  X25519PAKEServerHandler server(X25519SecretKey::CreateRandom(), &server_password_provider);
98  X25519PAKEClientHandler client(X25519SecretKey::CreateRandom(), std::make_shared<TestPasswordRequestHandler>(client_password));
99 
100  TestAuthentication(server, client, expected_response_result, NetworkAuthenticationClientHandler::AWAIT_USER_INPUT);
101 }
102 
103 TEST_CASE("Authentication_PAKE")
104 {
105  SECTION("Correct password") {
106  TestAuthenticationPAKE("sikrit", "sikrit", NetworkAuthenticationServerHandler::AUTHENTICATED);
107  }
108 
109  SECTION("Empty password") {
110  TestAuthenticationPAKE("", "", NetworkAuthenticationServerHandler::AUTHENTICATED);
111  }
112 
113  SECTION("Wrong password") {
114  TestAuthenticationPAKE("sikrit", "secret", NetworkAuthenticationServerHandler::NOT_AUTHENTICATED);
115  }
116 }
117 
118 
119 static void TestAuthenticationAuthorizedKey(const X25519SecretKey &client_secret_key, const X25519PublicKey &server_expected_public_key,
121 {
122  NetworkAuthorizedKeys authorized_keys;
123  authorized_keys.Add(FormatArrayAsHex(server_expected_public_key));
124 
125  NetworkAuthenticationDefaultAuthorizedKeyHandler authorized_key_handler(authorized_keys);
126  X25519AuthorizedKeyServerHandler server(X25519SecretKey::CreateRandom(), &authorized_key_handler);
127  X25519AuthorizedKeyClientHandler client(client_secret_key);
128 
129  TestAuthentication(server, client, expected_response_result, NetworkAuthenticationClientHandler::READY_FOR_RESPONSE);
130 }
131 
132 TEST_CASE("Authentication_AuthorizedKey")
133 {
134  auto client_secret_key = X25519SecretKey::CreateRandom();
135  auto valid_client_public_key = client_secret_key.CreatePublicKey();
136  auto invalid_client_public_key = X25519SecretKey::CreateRandom().CreatePublicKey();
137 
138  SECTION("Correct public key") {
139  TestAuthenticationAuthorizedKey(client_secret_key, valid_client_public_key, NetworkAuthenticationServerHandler::AUTHENTICATED);
140  }
141 
142  SECTION("Incorrect public key") {
143  TestAuthenticationAuthorizedKey(client_secret_key, invalid_client_public_key, NetworkAuthenticationServerHandler::NOT_AUTHENTICATED);
144  }
145 }
146 
147 
148 TEST_CASE("Authentication_Combined")
149 {
150  auto client_secret_key = X25519SecretKey::CreateRandom();
151  std::string client_secret_key_str = FormatArrayAsHex(client_secret_key);
152  auto client_public_key = client_secret_key.CreatePublicKey();
153  std::string client_public_key_str = FormatArrayAsHex(client_public_key);
154 
155  NetworkAuthorizedKeys valid_authorized_keys;
156  valid_authorized_keys.Add(client_public_key_str);
157  NetworkAuthenticationDefaultAuthorizedKeyHandler valid_authorized_key_handler(valid_authorized_keys);
158 
159  NetworkAuthorizedKeys invalid_authorized_keys;
160  invalid_authorized_keys.Add("not-a-valid-authorized-key");
161  NetworkAuthenticationDefaultAuthorizedKeyHandler invalid_authorized_key_handler(invalid_authorized_keys);
162 
163  NetworkAuthorizedKeys no_authorized_keys;
164  NetworkAuthenticationDefaultAuthorizedKeyHandler no_authorized_key_handler(no_authorized_keys);
165 
166  std::string no_password = "";
167  NetworkAuthenticationDefaultPasswordProvider no_password_provider(no_password);
168  std::string valid_password = "sikrit";
169  NetworkAuthenticationDefaultPasswordProvider valid_password_provider(valid_password);
170  std::string invalid_password = "secret";
171  NetworkAuthenticationDefaultPasswordProvider invalid_password_provider(invalid_password);
172 
173  auto client = NetworkAuthenticationClientHandler::Create(std::make_shared<TestPasswordRequestHandler>(valid_password), client_secret_key_str, client_public_key_str);
174 
175  SECTION("Invalid authorized keys, invalid password") {
176  auto server = NetworkAuthenticationServerHandler::Create(&invalid_password_provider, &invalid_authorized_key_handler);
177 
180  }
181 
182  SECTION("Invalid authorized keys, valid password") {
183  auto server = NetworkAuthenticationServerHandler::Create(&valid_password_provider, &invalid_authorized_key_handler);
184 
187  }
188 
189  SECTION("Valid authorized keys, valid password") {
190  auto server = NetworkAuthenticationServerHandler::Create(&valid_password_provider, &valid_authorized_key_handler);
191 
193  }
194 
195  SECTION("No authorized keys, invalid password") {
196  auto server = NetworkAuthenticationServerHandler::Create(&invalid_password_provider, &no_authorized_key_handler);
197 
199  }
200 
201  SECTION("No authorized keys, valid password") {
202  auto server = NetworkAuthenticationServerHandler::Create(&valid_password_provider, &no_authorized_key_handler);
203 
205  }
206 
207  SECTION("No authorized keys, no password") {
208  auto server = NetworkAuthenticationServerHandler::Create(&no_password_provider, &no_authorized_key_handler);
209 
211  }
212 }
213 
214 
215 static void CheckEncryption(MockNetworkSocketHandler *sending_socket_handler, MockNetworkSocketHandler *receiving_socket_handler)
216 {
217  PacketType sent_packet_type{ 1 };
218  uint64_t sent_value = 0x1234567890ABCDEF;
219  std::set<PacketType> encrypted_packet_types;
220 
221  for (int i = 0; i < 10; i++) {
222  Packet request(sending_socket_handler, sent_packet_type);
223  request.Send_uint64(sent_value);
224 
225  auto [response, valid] = CreatePacketForReading(request, receiving_socket_handler);
226  CHECK(valid);
227  CHECK(response.Recv_uint64() == sent_value);
228 
229  encrypted_packet_types.insert(request.GetPacketType());
230  }
231  /*
232  * Check whether it looks like encryption has happened. This is done by checking the value
233  * of the packet type after encryption. If after a few iterations more than one encrypted
234  * value has been seen, then we know that some type of encryption/scrambling is happening.
235  *
236  * Technically this check could fail erroneously when 16 subsequent encryptions yield the
237  * same encrypted packet type. However, with encryption that byte should have random value
238  * value, so the chance of this happening are tiny given enough iterations.
239  * Roughly in the order of 2**((iterations - 1) * 8), which with 10 iterations is in the
240  * one-in-sextillion (10**21) order of magnitude.
241  */
242  CHECK(encrypted_packet_types.size() != 1);
243 
244 }
245 
246 TEST_CASE("Encryption handling")
247 {
250 
252 
253  Packet packet(&mock_socket_handler, PacketType{});
254  server.SendEnableEncryption(packet);
255 
256  bool valid;
257  std::tie(packet, valid) = CreatePacketForReading(packet, &mock_socket_handler);
258  CHECK(valid);
259  CHECK(client.ReceiveEnableEncryption(packet));
260 
263 
264  SECTION("Encyption happening client -> server") {
265  CheckEncryption(&client_socket_handler, &server_socket_handler);
266  }
267 
268  SECTION("Encyption happening server -> client") {
269  CheckEncryption(&server_socket_handler, &client_socket_handler);
270  }
271 
272  SECTION("Unencrypted packet sent causes invalid read packet") {
273  Packet request(&mock_socket_handler, PacketType{});
274  request.Send_uint64(0);
275 
276  auto [response, valid] = CreatePacketForReading(request, &client_socket_handler);
277  CHECK(!valid);
278  }
279 }
NetworkAuthenticationClientHandler::Create
static std::unique_ptr< NetworkAuthenticationClientHandler > Create(std::shared_ptr< NetworkAuthenticationPasswordRequestHandler > password_handler, std::string &secret_key, std::string &public_key)
Create a NetworkAuthenticationClientHandler.
Definition: network_crypto.cpp:462
X25519PAKEServerHandler
Server side handler for using X25519 with a password-authenticated key exchange.
Definition: network_crypto_internal.h:213
Packet::Send_uint64
void Send_uint64(uint64_t data)
Package a 64 bits integer in the packet.
Definition: packet.cpp:154
Packet::PrepareToSend
void PrepareToSend()
Writes the packet size from the raw packet from packet->size.
Definition: packet.cpp:66
Packet::Size
size_t Size() const
Get the number of bytes in the packet.
Definition: packet.cpp:250
NetworkSocketHandler::send_encryption_handler
std::unique_ptr< class NetworkEncryptionHandler > send_encryption_handler
The handler for encrypting sent packets.
Definition: core.h:50
NetworkAuthenticationClientHandler::SendResponse
virtual bool SendResponse(struct Packet &p)=0
Create the response to send to the server.
NetworkSocketHandler
SocketHandler for all network sockets in OpenTTD.
Definition: core.h:43
NetworkAuthenticationServerHandler::SendRequest
virtual void SendRequest(struct Packet &p)=0
Create the request to send to the client.
valid
uint8_t valid
Bits indicating what variable is valid (for each bit, 0 is invalid, 1 is valid).
Definition: newgrf_station.cpp:247
NetworkAuthenticationDefaultPasswordProvider
Default implementation of the password provider.
Definition: network_crypto.h:123
NetworkAuthenticationServerHandler::Create
static std::unique_ptr< NetworkAuthenticationServerHandler > Create(const NetworkAuthenticationPasswordProvider *password_provider, const NetworkAuthenticationAuthorizedKeyHandler *authorized_key_handler, NetworkAuthenticationMethodMask client_supported_method_mask=~static_cast< NetworkAuthenticationMethodMask >(0))
Create a NetworkAuthenticationServerHandler.
Definition: network_crypto.cpp:478
PacketType
uint8_t PacketType
Identifier for the packet.
Definition: packet.h:21
NetworkAuthenticationDefaultAuthorizedKeyHandler
Default implementation for the authorized key handler.
Definition: network_crypto.h:161
TestPasswordRequestHandler
Definition: test_network_crypto.cpp:54
X25519KeyExchangeOnlyClientHandler
Client side handler for using X25519 without actual authentication.
Definition: network_crypto_internal.h:135
TestPasswordRequestHandler::SendResponse
void SendResponse() override
Callback to trigger sending the response for the password request.
Definition: test_network_crypto.cpp:59
NetworkAuthenticationServerHandler::SendEnableEncryption
virtual void SendEnableEncryption(struct Packet &p)=0
Create the request to enable encryption to the client.
NetworkAuthorizedKeys::Add
bool Add(std::string_view key)
Add the given key to the authorized keys, when it is not already contained.
Definition: network.cpp:190
NetworkAuthenticationPasswordRequestHandler
Callback interface for client implementations to provide the handling of the password requests.
Definition: network_crypto.h:84
NetworkAuthenticationClientHandler::ReceiveRequest
virtual RequestResult ReceiveRequest(struct Packet &p)=0
Read a request from the server.
Packet::TransferOutWithLimit
ssize_t TransferOutWithLimit(F transfer_function, size_t limit, D destination, Args &&... args)
Transfer data from the packet to the given function.
Definition: packet.h:109
X25519PAKEClientHandler
Client side handler for using X25519 with a password-authenticated key exchange.
Definition: network_crypto_internal.h:185
X25519AuthorizedKeyClientHandler
Handler for clients using a X25519 key exchange to perform authentication via a set of authorized (pu...
Definition: network_crypto_internal.h:244
FormatArrayAsHex
std::string FormatArrayAsHex(std::span< const uint8_t > data)
Format a byte array into a continuous hex string.
Definition: string.cpp:81
NetworkAuthenticationClientHandler::READY_FOR_RESPONSE
@ READY_FOR_RESPONSE
We do not have to wait for user input, and can immediately respond to the server.
Definition: network_crypto.h:227
NetworkAuthenticationServerHandler::NOT_AUTHENTICATED
@ NOT_AUTHENTICATED
All authentications for this handler have been exhausted.
Definition: network_crypto.h:263
X25519PublicKey
Container for a X25519 public key.
Definition: network_crypto_internal.h:30
NetworkAuthenticationServerHandler::AUTHENTICATED
@ AUTHENTICATED
The client was authenticated successfully.
Definition: network_crypto.h:262
NetworkAuthenticationClientHandler
Base class for client side cryptographic authentication handlers.
Definition: network_crypto.h:222
NetworkAuthenticationClientHandler::ReceiveEnableEncryption
virtual bool ReceiveEnableEncryption(struct Packet &p)=0
Read the request to enable encryption from the server.
NetworkAuthenticationClientHandler::RequestResult
RequestResult
The processing result of receiving a request.
Definition: network_crypto.h:225
NetworkAuthenticationHandler::CreateClientToServerEncryptionHandler
virtual std::unique_ptr< NetworkEncryptionHandler > CreateClientToServerEncryptionHandler() const =0
Create a NetworkEncryptionHandler to encrypt or decrypt messages from the client to the server.
NetworkAuthenticationServerHandler
Base class for server side cryptographic authentication handlers.
Definition: network_crypto.h:258
Packet
Internal entity of a packet.
Definition: packet.h:42
NetworkAuthenticationClientHandler::AWAIT_USER_INPUT
@ AWAIT_USER_INPUT
We have requested some user input, but must wait on that.
Definition: network_crypto.h:226
NetworkAuthenticationServerHandler::ReceiveResponse
virtual ResponseResult ReceiveResponse(struct Packet &p)=0
Read the response from the client.
NETWORK_PUBLIC_KEY_LENGTH
static const uint NETWORK_PUBLIC_KEY_LENGTH
The maximum length of the hexadecimal encoded public keys, in bytes including '\0'.
Definition: config.h:102
X25519SecretKey::CreatePublicKey
X25519PublicKey CreatePublicKey() const
Create the public key associated with this secret key.
Definition: network_crypto.cpp:156
NetworkAuthenticationServerHandler::ResponseResult
ResponseResult
The processing result of receiving a response.
Definition: network_crypto.h:261
NetworkAuthorizedKeys
Simple helper to (more easily) manage authorized keys.
Definition: network_type.h:148
COMPAT_MTU
static const size_t COMPAT_MTU
Number of bytes we can pack in a single packet for backward compatibility.
Definition: config.h:46
X25519_KEY_SIZE
constexpr size_t X25519_KEY_SIZE
The number of bytes the public and secret keys are in X25519.
Definition: network_crypto_internal.h:16
NetworkAuthenticationServerHandler::RETRY_NEXT_METHOD
@ RETRY_NEXT_METHOD
The client failed to authenticate, but there is another method to try.
Definition: network_crypto.h:264
MockNetworkSocketHandler
Definition: test_network_crypto.cpp:23
NetworkSocketHandler::receive_encryption_handler
std::unique_ptr< class NetworkEncryptionHandler > receive_encryption_handler
The handler for decrypting received packets.
Definition: core.h:49
X25519SecretKey::CreateRandom
static X25519SecretKey CreateRandom()
Create a new secret key that's filled with random bytes.
Definition: network_crypto.cpp:145
X25519AuthorizedKeyServerHandler
Handler for servers using a X25519 key exchange to perform authentication via a set of authorized (pu...
Definition: network_crypto_internal.h:271
X25519SecretKey
Container for a X25519 secret key.
Definition: network_crypto_internal.h:34
X25519KeyExchangeOnlyServerHandler
Server side handler for using X25519 without actual authentication.
Definition: network_crypto_internal.h:159
NETWORK_SECRET_KEY_LENGTH
static const uint NETWORK_SECRET_KEY_LENGTH
The maximum length of the hexadecimal encoded secret keys, in bytes including '\0'.
Definition: config.h:97
NetworkAuthenticationHandler::CreateServerToClientEncryptionHandler
virtual std::unique_ptr< NetworkEncryptionHandler > CreateServerToClientEncryptionHandler() const =0
Create a NetworkEncryptionHandler to encrypt or decrypt messages from the server to the client.
TestPasswordRequestHandler::AskUserForPassword
void AskUserForPassword(std::shared_ptr< NetworkAuthenticationPasswordRequest > request) override
Callback to trigger asking the user for the password.
Definition: test_network_crypto.cpp:60