Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 3 additions & 2 deletions doc/design/pq-transport.md
Original file line number Diff line number Diff line change
Expand Up @@ -309,8 +309,9 @@ qbit reports each v2 connection's negotiation status as one of these values:
- `hybrid` once the peer's confirmation verifies;
- `legacy_peer` when the peer's version packet carries no usable offer or
accept, so the ECDH keys stay;
- `off` when the switch is off, or after a local key generation, key check or
encapsulation fault that left the connection on plain v2;
- `off` when the switch is off, when a responder sheds its offer under load,
or after a local key generation, key check or encapsulation fault that left
the connection on plain v2;
- `fallback` for an outbound connection that runs plain v2 because of earlier
failures; inbound connections never fall back.

Expand Down
19 changes: 19 additions & 0 deletions src/bip324_pq.h
Original file line number Diff line number Diff line change
Expand Up @@ -70,6 +70,13 @@ enum class PQFailure : uint8_t {
CIPHER_STATE_INTERNAL = 11,
};

/** Why the peer counts as a legacy peer: its contents carried no own record, or did not parse. */
enum class PQLegacyReason : uint8_t { NONE = 0, NO_FEATURES = 1, PARSE_ERROR = 2 };

/** Why the transport closed before the peer's version packet authenticated (the transport's own
* reasons for an abandoned offer). The first one recorded is kept. */
enum class PQAbort : uint8_t { NONE = 0, GARBAGE_TERMINATOR = 1, VERSION_LENGTH = 2, VERSION_TAG = 3 };

/** Entropy for key generation and encapsulation, 32 bytes per call. */
struct PQRandomSource {
using Fill32 = void (*)(void*, std::span<uint8_t, 32>) noexcept;
Expand Down Expand Up @@ -118,6 +125,9 @@ class PQHandshake
//! The peer's key confirmation verified.
bool confirmed{false};
PQFailure failure{PQFailure::NONE};
//! Set when the negotiation ended with a legacy peer.
PQLegacyReason legacy{PQLegacyReason::NONE};
PQAbort abort{PQAbort::NONE};
};

/**
Expand Down Expand Up @@ -180,6 +190,15 @@ class PQHandshake
void SetVersionReceived() noexcept { m_snapshot.version_received = true; }
void SetSwitched() noexcept { m_snapshot.switched = true; }
void SetConfirmed() noexcept { m_snapshot.confirmed = true; }
/** The peer's contents parsed as kind, without an own record: a legacy peer. */
void SetLegacy(ParseKind kind) noexcept
{
m_snapshot.legacy = kind == ParseKind::INVALID_GRAMMAR ? PQLegacyReason::PARSE_ERROR : PQLegacyReason::NO_FEATURES;
}
void SetAbort(PQAbort abort) noexcept
{
if (m_snapshot.abort == PQAbort::NONE) m_snapshot.abort = abort;
}
/** Record a failure unless one is recorded already, and wipe the secrets. */
void SetFailure(PQFailure failure) noexcept;
Snapshot GetSnapshot() const noexcept { return m_snapshot; }
Expand Down
558 changes: 544 additions & 14 deletions src/net.cpp

Large diffs are not rendered by default.

Loading
Loading