|
OpenVPN 3 Core Library
|
#include <proto.hpp>
Classes | |
| struct | DataChannelKey |
| struct | UnwrappedWkc |
| What a WKc yields, owned by whoever asked for the unwrap. More... | |
| struct | WkcMetadata |
| The metadata record a WKc carried, for TLSCryptMetadata::verify() More... | |
Public Types | |
| enum | EventType { KEV_NONE , KEV_ACTIVE , KEV_NEGOTIATE , KEV_BECOME_PRIMARY , KEV_PRIMARY_PENDING , KEV_RENEGOTIATE , KEV_RENEGOTIATE_FORCE , KEV_RENEGOTIATE_QUEUE , KEV_EXPIRE } |
| using | Ptr = RCPtr< KeyContext > |
Public Types inherited from openvpn::RC< thread_unsafe_refcount > | |
| using | Ptr = RCPtr< RC > |
Public Member Functions | |
| OPENVPN_SIMPLE_EXCEPTION (tls_crypt_unwrap_wkc_error) | |
| KeyContext (ProtoContext &p, const bool initiator, bool psid_cookie_mode=false) | |
| void | set_protocol (const Protocol &p) |
| uint32_t | get_tls_warnings () const |
| void | start (const ProtoSessionID cookie_psid=ProtoSessionID()) |
| Initialize the state machine and start protocol negotiation. | |
| void | flush () |
| void | invalidate (const Error::Type reason) |
| void | retransmit () |
| Time | next_retransmit () const |
| void | app_send_validate (BufferPtr &&bp) |
| void | app_send (BufferPtr &&bp) |
| bool | net_recv (Packet &&pkt) |
| void | encrypt (BufferAllocated &buf) |
| void | decrypt (BufferAllocated &buf) |
| void | prepare_expire (const EventType current_ev=KeyContext::KEV_NONE) |
| void | set_next_event_if_unspecified () |
| void | key_limit_reneg (const EventType ev, const Time &t) |
| Time | become_primary_time () |
| bool | event_pending () |
| EventType | get_event () const |
| void | reset_event () |
| bool | invalidated () const |
| Error::Type | invalidation_reason () const |
| unsigned int | key_id () const |
| bool | data_channel_ready () const |
| bool | is_dirty () const |
| void | rekey (const CryptoDCInstance::RekeyType type) |
| Time | reached_active () const |
| void | send_keepalive () |
| void | send_explicit_exit_notify () |
| void | send_data_channel_message (const unsigned char *data, const size_t size) |
| void | generate_datachannel_keys () |
| void | calculate_mssfix (ProtoConfig &c) |
| void | init_data_channel () |
| void | data_limit_notify (const DataLimit::Mode cdl_mode, const DataLimit::State cdl_status) |
| int | get_state () const |
Public Member Functions inherited from openvpn::RC< thread_unsafe_refcount > | |
| RC () noexcept=default | |
| RC (const RC &)=delete | |
| virtual | ~RC ()=default |
| RC & | operator= (const RC &)=delete |
| olong | use_count () const noexcept |
| Delegates call to RCImpl and returns the result. | |
Static Public Member Functions | |
| static const char * | event_type_string (const EventType et) |
| static bool | tls_crypt_v2_convertible (const ProtoContext &proto, const unsigned int opcode) |
| May a packet with this opcode convert a tls-auth session to tls-crypt-v2? | |
| static bool | validate (const Buffer &net_buf, ProtoContext &proto, TimePtr now) |
| static size_t | tls_crypt_frame_size (const ProtoConfig &proto_config) |
| Smallest tls-crypt frame a WKc can be appended to. | |
| static size_t | wkc_overhead (const ProtoConfig &proto_config) |
| What a WKc holds besides the client key and the metadata. | |
| static bool | trailing_wkc_len (const Buffer &recv, const ProtoConfig &proto_config, const size_t min_wkc_len, uint16_t &wkc_len) |
| Read and validate the WKc length a tls-crypt-v2 packet ends with. | |
| static Error::Type | unwrap_tls_crypt_wkc (Buffer &recv, const ProtoConfig &proto_config, TLSCryptInstance &tls_crypt_server, UnwrappedWkc &unwrapped) |
| Extract and process the TLS crypt WKc information. | |
| static bool | strip_resent_wkc (Buffer &recv, const ProtoConfig &proto_config) |
| Virtually remove a resent WKc from the end of a CONTROL_WKC_V1 packet. | |
Static Public Member Functions inherited from openvpn::RC< thread_unsafe_refcount > | |
| static constexpr bool | is_thread_safe () |
| Delegates call to RCImpl and returns the result. | |
Private Types | |
| using | Base = ProtoStackBase< Packet, KeyContext > |
| using | ReliableSend = Base::ReliableSend |
| using | ReliableRecv = Base::ReliableRecv |
Private Types inherited from openvpn::ProtoStackBase< Packet, KeyContext > | |
| enum | NetSendType |
| using | id_t = reliable::id_t |
| using | ReliableSend = ReliableSendTemplate< Packet > |
| using | ReliableRecv = ReliableRecvTemplate< Packet > |
Private Member Functions | |
| bool | do_encrypt (BufferAllocated &buf, const bool compress_hint) |
| void | cache_op32 () |
| void | set_state (const int newstate) |
| void | set_event (const EventType current) |
| void | set_event (const EventType current, const EventType next, const Time &next_time) |
| void | invalidate_callback () |
| void | schedule_key_limit_renegotiation () |
| bool | data_limit_add (const DataLimit::Mode mode, const size_t size) |
| void | data_limit_event (const DataLimit::Mode mode, const DataLimit::State state) |
| bool | data_limit_defer () const |
| Time | data_limit_expire () const |
| void | active_event () |
| void | process_next_event () |
| void | kev_error (const EventType ev, const Error::Type reason) |
| unsigned int | initial_op (const bool sender, const bool tls_crypt_v2) const |
| void | send_reset () |
| bool | parse_early_negotiation (const Packet &pkt) |
| void | raw_recv (Packet &&raw_pkt) |
| void | app_recv (BufferPtr &&to_app_buf) |
| void | net_send (const Packet &net_pkt, const Base::NetSendType nstype) |
| void | post_ack_action () |
| void | send_auth () |
| void | recv_auth (BufferPtr buf) |
| bool | recv_auth_complete (BufferComplete &bc) const |
| void | active () |
| void | prepend_dest_psid_and_acks (Buffer &buf, unsigned int opcode) |
| bool | verify_src_psid (const ProtoSessionID &src_psid) |
| void | accept_peer (const ProtoSessionID &src_psid) |
Adopt src_psid as our peer, and mark this packet as ours. | |
| bool | verify_dest_psid (Buffer &buf) |
| void | gen_head_tls_auth (const unsigned int opcode, Buffer &buf) |
| void | gen_head_tls_crypt (const unsigned int opcode, BufferAllocated &buf) |
| void | gen_head_tls_plain (const unsigned int opcode, Buffer &buf) |
| void | gen_head (const unsigned int opcode, BufferAllocated &buf) |
| bool | packet_carries_wkc (id_t id) const |
| size_t | control_channel_wrap_overhead () const |
| size_t | control_ciphertext_capacity (id_t id) const |
| void | encapsulate (id_t id, Packet &pkt) |
| void | generate_ack (Packet &pkt) |
| bool | decapsulate_post_process (Packet &pkt, ProtoSessionID &src_psid, const PacketIDControl pid) |
| bool | decapsulate_tls_auth (Packet &pkt) |
| bool | decapsulate_tls_crypt (Packet &pkt) |
| bool | decapsulate_tls_plain (Packet &pkt) |
| bool | tls_crypt_v2_wanted (const Packet &pkt) const |
| May this packet make a tls-auth server session a tls-crypt-v2 one? | |
| bool | decapsulate (Packet &pkt) |
| bool | verify_wkc_metadata (WkcMetadata &metadata) |
| Put the record a WKc carried to the embedder's hook, if it installed one. | |
| bool | decapsulate_by_wrap_mode (Packet &pkt) |
Decapsulate pkt with the wrap mode this session is in. | |
| int | seconds_until (const Time &next_time) |
Private Member Functions inherited from openvpn::ProtoStackBase< Packet, KeyContext > | |
| OPENVPN_SIMPLE_EXCEPTION (proto_stack_invalidated) | |
| OPENVPN_SIMPLE_EXCEPTION (unknown_status_from_ssl_layer) | |
| ProtoStackBase (SSLFactoryAPI &ssl_factory, TimePtr now_arg, const Time::Duration &tls_timeout_arg, const Frame::Ptr &frame, const SessionStats::Ptr &stats_arg, bool psid_cookie_mode) | |
| void | start_handshake () |
| uint32_t | get_tls_warnings () const |
| bool | net_recv (Packet &&pkt) |
| void | app_send (BufferPtr &&buf) |
| void | raw_send (Packet &&pkt) |
| void | flush () |
| void | send_pending_acks () |
| void | retransmit () |
| Time | next_retransmit () const |
| bool | ssl_started () const |
| bool | invalidated () const |
| Error::Type | invalidation_reason () const |
| void | invalidate (const Error::Type reason) |
| std::string | ssl_handshake_details () const |
| void | export_key_material (OpenVPNStaticKey &key, const std::string &label) const |
| const AuthCert::Ptr & | auth_cert () const |
Static Private Member Functions | |
| static bool | validate_tls_auth (Buffer &recv, ProtoContext &proto, TimePtr now) |
| static bool | validate_tls_crypt (Buffer &recv, ProtoContext &proto, TimePtr now) |
| static bool | validate_tls_plain (Buffer &recv, ProtoContext &proto, TimePtr now) |
| static const char * | state_string (const int s) |
Private Attributes | |
| friend | Base |
| ProtoContext & | proto |
| int | state |
| unsigned int | key_id_ |
| unsigned int | crypto_flags |
| int | remote_peer_id |
| bool | enable_op32 |
| bool | resend_wkc = false |
| bool | pkt_from_peer = false |
| Set per packet by accept_peer(), read by decapsulate() | |
| bool | dirty |
| bool | key_limit_renegotiation_fired |
| bool | is_reliable |
| Compress::Ptr | compress |
| CryptoDCInstance::Ptr | crypto |
| TLSPRFInstance::Ptr | tlsprf |
| Time | construct_time |
| Time | reached_active_time_ |
| Time | next_event_time |
| EventType | current_event |
| EventType | next_event |
| std::deque< BufferPtr > | app_pre_write_queue |
| std::unique_ptr< DataChannelKey > | data_channel_key |
| BufferComposed | app_recv_buf |
| std::unique_ptr< DataLimit > | data_limit |
| BufferAllocated | work |
Private Attributes inherited from openvpn::ProtoStackBase< Packet, KeyContext > | |
| TimePtr | now |
| ReliableRecv | rel_recv |
| ReliableSend | rel_send |
| ReliableAck | xmit_acks |
Static Private Attributes | |
| static BufferAllocated | static_work |
Static Private Attributes inherited from openvpn::ProtoStackBase< Packet, KeyContext > | |
| static constexpr size_t | ovpn_sending_window |
| static constexpr size_t | ovpn_receiving_window |
|
private |
|
private |
|
private |
|
inline |
|
inlineprivate |
Adopt src_psid as our peer, and mark this packet as ours.
Reached only once a packet has verified under one of this session's keys and echoed the psid we chose. Pinning earlier let a packet that was then rejected name the peer anyway. Must precede any queued ACK: prepend_dest_psid_and_acks() throws without a peer psid.
Definition at line 3749 of file proto.hpp.
|
inlineprivate |
|
inlineprivate |
|
inlineprivate |
|
inline |
|
inline |
|
inline |
|
inlineprivate |
|
inline |
|
inlineprivate |
|
inlineprivate |
|
inline |
|
inlineprivate |
|
inlineprivate |
|
inlineprivate |
|
inlineprivate |
|
inline |
|
inlineprivate |
|
inlineprivate |
Decapsulate pkt with the wrap mode this session is in.
Split out of decapsulate() so that what the wrap mode decides stays separate from what every packet gets: the tls-crypt-v2 arm is the one with a step of its own, since on a server the key its frame is read with comes from the WKc the packet carries and from nowhere else.
Definition at line 4178 of file proto.hpp.
|
inlineprivate |
|
inlineprivate |
|
inlineprivate |
|
inlineprivate |
|
inline |
|
inlineprivate |
|
inline |
|
inline |
|
inlinestatic |
|
inline |
|
inlineprivate |
|
inlineprivate |
|
inlineprivate |
|
inlineprivate |
|
inlineprivate |
|
inline |
|
inline |
|
inline |
|
inline |
|
inline |
|
inlineprivate |
|
inline |
|
inlineprivate |
|
inline |
|
inline |
|
inline |
|
inlineprivate |
|
inline |
|
inline |
|
inlineprivate |
|
inline |
| openvpn::ProtoContext::KeyContext::OPENVPN_SIMPLE_EXCEPTION | ( | tls_crypt_unwrap_wkc_error | ) |
|
inlineprivate |
|
inlineprivate |
|
inlineprivate |
|
inline |
|
inlineprivate |
|
inlineprivate |
|
inlineprivate |
|
inline |
|
inlineprivate |
|
inlineprivate |
|
inline |
|
inline |
|
inline |
|
inlineprivate |
|
inlineprivate |
|
inlineprivate |
|
inline |
|
inline |
|
inline |
|
inlineprivate |
|
inlineprivate |
|
inline |
|
inline |
|
inlineprivate |
|
inline |
Initialize the state machine and start protocol negotiation.
Called by ProtoContext::start()
| cookie_psid | see comment in ProtoContext::reset() |
|
inlinestaticprivate |
|
inlinestatic |
Virtually remove a resent WKc from the end of a CONTROL_WKC_V1 packet.
A client asked to resend its WKc (EARLY_NEG_FLAG_RESEND_WKC) appends it to every transmission of the third handshake packet, retransmissions included, since encapsulate() re-runs for each of them. By the time such a packet reaches a session the client key it wraps is already set up, so the WKc is of no further use and must simply be taken off: the tls-crypt frame in front of it is what gets decapsulated, and its auth tag covers that frame alone.
OpenVPN 2 does the same in tls_crypt_v2_extract_client_key() when its initial_packet argument is false, turning the packet back into a CONTROL_V1.
Definition at line 3108 of file proto.hpp.
|
inlinestatic |
Smallest tls-crypt frame a WKc can be appended to.
Header, auth tag, an empty ACK array and the reliable ID, with no ciphertext – a WKc can fill a packet by itself, see control_ciphertext_capacity().
Definition at line 2834 of file proto.hpp.
|
inlinestatic |
May a packet with this opcode convert a tls-auth session to tls-crypt-v2?
A server holding both keys starts every session in TLS_AUTH, and only decapsulate() converts it, once a WKc arrives. validate() runs ahead of that and has to agree on which packet may convert, so the test is shared.
Definition at line 2587 of file proto.hpp.
|
inlineprivate |
May this packet make a tls-auth server session a tls-crypt-v2 one?
Only the opcode asks for the switch and packet_type() weighs nothing else, so a spoofed datagram gets a say. Hence: on offer only until a packet of our peer's has been accepted, and decapsulate() takes it back if this one is not.
Definition at line 4070 of file proto.hpp.
|
inlinestatic |
Read and validate the WKc length a tls-crypt-v2 packet ends with.
wkc_len is read straight from the last two bytes of the packet and is therefore fully attacker-controlled. It has to be validated before any pointer arithmetic uses it: the WKc must fit between the end of the tls-crypt frame and the end of the packet, and hold at least min_wkc_len bytes. Without this a bogus length underflows the unsigned size computations into a wild pointer, causing an out-of-bounds read during decryption – an unauthenticated remote DoS.
recv is too short to hold the tls-crypt frame and the length field, or if wkc_len is smaller than min_wkc_len or larger than the space behind the frame. Definition at line 2871 of file proto.hpp.
|
inlinestatic |
Extract and process the TLS crypt WKc information.
| recv | Buffer containing the raw packet. |
| proto_config | Config object holding the settings needed for processing. |
| tls_crypt_server | Server context used only to process incoming WKc's. |
| unwrapped | Receives the client key and the metadata record the WKc carried. Written only on success. |
Definition at line 2926 of file proto.hpp.
|
inlinestatic |
|
inlinestaticprivate |
|
inlinestaticprivate |
|
inlinestaticprivate |
|
inlineprivate |
|
inlineprivate |
|
inlineprivate |
Put the record a WKc carried to the embedder's hook, if it installed one.
Asked only once the WKc's Kc has authenticated the frame that carried it, which is the most this layer can say about where a record came from.
Definition at line 4147 of file proto.hpp.
|
inlinestatic |
What a WKc holds besides the client key and the metadata.
Its own trailing length field, the authentication tag T, and the server key ID where one is configured. A WKc smaller than this cannot be parsed at all, so it is the floor an attacker-supplied length is held to.
Definition at line 2850 of file proto.hpp.
|
private |
|
private |
|
private |
|
private |
|
private |
|
private |
|
private |
|
private |
|
private |
|
private |
|
private |
|
private |
|
private |
|
private |
|
private |
|
private |
|
private |
Set per packet by accept_peer(), read by decapsulate()
|
private |
|
private |
|
private |
|
private |
|
staticprivate |
|
private |
|
private |