34#define OOB_KEYDIR UNITTEST_SOURCE_DIR "../ssl/"
62 cp->tls_auth_key.parse(tls_auth_key);
64 cp->key_direction = -1;
67 case WrapMode::CRYPT_V2:
71 auto cc = SSLLib::SSLAPI::Config::Ptr(
new SSLLib::SSLAPI::Config());
78 cp->ssl_factory = cc->new_factory();
81 cp->set_tls_crypt_algs();
82 if (m == WrapMode::CRYPT)
84 cp->tls_crypt_key.parse(tls_auth_key);
85 cp->tls_crypt_ = ProtoContext::ProtoConfig::TLSCrypt::V1;
91 k.extract_key(cp->tls_crypt_key);
92 k.extract_wkc(cp->wkc);
93 cp->tls_crypt_ = ProtoContext::ProtoConfig::TLSCrypt::V2;
111 : config(cp),
mode(m)
113 pid_recv.init(
"OOB-SRV", 0, stats);
114 psid_self.randomize(*config->rng);
119 hmac_size = config->tls_auth_context->size();
122 case WrapMode::CRYPT:
123 case WrapMode::CRYPT_V2:
124 hmac_size = config->tls_crypt_context->digest_size();
127 case WrapMode::PLAIN:
141 case WrapMode::CRYPT:
142 case WrapMode::CRYPT_V2:
144 case WrapMode::PLAIN:
147 return ProtoContext::UnwrapStatus::OK;
149 return ProtoContext::UnwrapStatus::DROP;
161 case WrapMode::CRYPT:
162 case WrapMode::CRYPT_V2:
163 ProtoContext::wrap_tls_crypt(
ProtoContext::CONTROL_OOB_V1, buf,
work, *config->frame, pid_send, now_secs, hmac_size, psid_self, 0, *tc_send,
nullptr);
165 case WrapMode::PLAIN:
176 size_t hmac_size = 0;
191void run_roundtrip(WrapMode m)
199 auto cp = make_config(m, frame, rng, time);
203 ServerSim server(cp, m, stats);
211 client.wrap(probe, cwork);
217 ASSERT_EQ(server.unwrap(probe, swork, src, pid), ProtoContext::UnwrapStatus::OK);
218 EXPECT_TRUE(src.
match(client.self_psid()));
221 ASSERT_TRUE(got_param);
222 EXPECT_EQ(got_param->timestamp, param.timestamp);
223 EXPECT_EQ(got_param->flags, param.flags);
229 .max_latency_diff = 0,
230 .connect_lifetime = 60,
236 server.wrap_reply(rbuf, rwork);
242 ASSERT_EQ(client.unwrap(rbuf, cwork2, rsrc, rpid), ProtoContext::UnwrapStatus::OK);
243 EXPECT_TRUE(rsrc.
match(server.psid_self));
246 ASSERT_TRUE(got_reply);
247 EXPECT_TRUE(got_reply->peer_session_id.match(client.self_psid()));
248 EXPECT_EQ(got_reply->priority, reply.priority);
249 EXPECT_EQ(got_reply->weight, reply.weight);
250 EXPECT_EQ(got_reply->connect_lifetime, reply.connect_lifetime);
255TEST(OobProbeWrap, plaintext_roundtrip)
257 run_roundtrip(WrapMode::PLAIN);
260TEST(OobProbeWrap, tls_auth_roundtrip)
262 run_roundtrip(WrapMode::AUTH);
265TEST(OobProbeWrap, tls_crypt_roundtrip)
267 run_roundtrip(WrapMode::CRYPT);
273TEST(OobProbeWrap, tls_crypt_v2_probe_appends_wkc)
278 auto cp = make_config(WrapMode::CRYPT_V2, frame, rng, time);
281 ASSERT_TRUE(cp->wkc.defined());
282 const size_t wkc_size = cp->wkc.size();
291 client.
wrap(probe, cwork);
294 const unsigned char expected_op =
296 ASSERT_GE(probe.
size(), wkc_size);
297 EXPECT_EQ(probe.
c_data()[0], expected_op);
300 EXPECT_EQ(std::memcmp(probe.
c_data() + probe.
size() - wkc_size, cp->wkc.c_data(), wkc_size), 0);
307 ServerSim server(cp, WrapMode::CRYPT_V2, stats);
311 ASSERT_EQ(server.unwrap(stripped, swork, src, pid), ProtoContext::UnwrapStatus::OK);
315 ASSERT_TRUE(got_param);
316 EXPECT_EQ(got_param->timestamp, param.timestamp);
325void run_truncated_reply_is_dropped(WrapMode m)
330 auto cp = make_config(m, frame, rng, time);
337 for (
size_t len = 1; len <=
sizeof(junk); ++len)
340 recv.
write(junk, len);
345 EXPECT_EQ(client.unwrap(recv,
work, src, pid), ProtoContext::UnwrapStatus::DROP) <<
"len=" << len;
351TEST(OobProbeWrap, plaintext_truncated_reply_is_dropped)
353 run_truncated_reply_is_dropped(WrapMode::PLAIN);
356TEST(OobProbeWrap, tls_auth_truncated_reply_is_dropped)
358 run_truncated_reply_is_dropped(WrapMode::AUTH);
361TEST(OobProbeWrap, tls_crypt_truncated_reply_is_dropped)
363 run_truncated_reply_is_dropped(WrapMode::CRYPT);
void reset(const size_t min_capacity, const BufferFlags flags=BufAllocFlags::NO_FLAGS)
Resets the buffer with the specified minimum capacity and flags.
const T * c_data() const
Returns a const pointer to the start of the buffer.
size_t size() const
Returns the size of the buffer in T objects.
void advance(const size_t delta)
Advances the buffer by the specified delta.
void write(const T *data, const size_t size)
Write data to the buffer.
Wrap an out-of-band SERVER_PROBE / unwrap the matching PROBE_REPLY.
const ProtoSessionID & self_psid() const
the client session id carried in the probe (echoed back in the reply)
void wrap(BufferAllocated &buf, BufferAllocated &work)
Wrap an already-encoded SERVER_PROBE payload in place.
static void wrap_tls_plain(const unsigned int opcode, Buffer &buf, const ProtoSessionID &psid_self, const unsigned int key_id)
plaintext control channel: [op][psid][payload]
static UnwrapStatus unwrap_tls_auth(Buffer &recv, const size_t hmac_size, OvpnHMACInstance &ta_hmac_recv, const PacketIDControlReceive &pid_recv, ProtoSessionID &src_psid, PacketIDControl &pid)
static void build_tls_auth(const ProtoConfig &c, OvpnHMACInstance::Ptr &send, OvpnHMACInstance::Ptr &recv)
static void wrap_tls_auth(const unsigned int opcode, Buffer &buf, PacketIDControlSend &pid_send, const PacketIDControl::time_t now_secs, const size_t hmac_size, const ProtoSessionID &psid_self, const unsigned int key_id, OvpnHMACInstance &ta_hmac_send)
tls-auth: [op][psid][hmac][pid][payload]
static void wrap_tls_crypt(const unsigned int opcode, BufferAllocated &buf, BufferAllocated &work, Frame &frame, PacketIDControlSend &pid_send, const PacketIDControl::time_t now_secs, const size_t hmac_size, const ProtoSessionID &psid_self, const unsigned int key_id, TLSCryptInstance &tls_crypt_send, const Buffer *wkc)
static UnwrapStatus unwrap_tls_crypt(BufferAllocated &recv, BufferAllocated &work, Frame &frame, const size_t hmac_size, TLSCryptInstance &tls_crypt_recv, const PacketIDControlReceive &pid_recv, ProtoSessionID &src_psid, PacketIDControl &pid)
static void build_tls_crypt(const ProtoConfig &c, const bool server, const OpenVPNStaticKey &key, TLSCryptInstance::Ptr &send, TLSCryptInstance::Ptr &recv)
bool match(const ProtoSessionID &other) const
void work(openvpn_io::io_context &io_context, ThreadCommon &tc, MyRunContext &runctx, const unsigned int unit)
constexpr BufferFlags NO_FLAGS(0U)
no flags set
Mode mode(const Type type)
Type lookup(const std::string &name)
bool server_probe_write(Buffer &buf, const ProbeParameter ¶m)
Write a complete SERVER_PROBE (message header + probe_parameter TLV). Client.
bool client_reply_write(Buffer &buf, const ProbeReply &reply)
Write a complete PROBE_REPLY (message header + probe_reply TLV). Server.
std::optional< ProbeReply > client_reply_read(Buffer &buf)
std::optional< ProbeParameter > server_probe_read(Buffer &buf)
std::string read_text(const std::string &filename, const std::uint64_t max_size=0)
probe parameter TLV (sent by the client in a SERVER_PROBE).
std::uint64_t timestamp
client clock as a UNIX timestamp
probe reply TLV (sent by the server in a PROBE_REPLY).
ProtoSessionID peer_session_id
echoes the session id of the request
TEST(OobProbeWrap, plaintext_roundtrip)