1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97
// Copyright 2022 Parity Technologies (UK) Ltd.
//
// Permission is hereby granted, free of charge, to any person obtaining a
// copy of this software and associated documentation files (the "Software"),
// to deal in the Software without restriction, including without limitation
// the rights to use, copy, modify, merge, publish, distribute, sublicense,
// and/or sell copies of the Software, and to permit persons to whom the
// Software is furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
// OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
// DEALINGS IN THE SOFTWARE.
//! Sphinx packet format.
//!
//! Packets consist of the following, in order:
//!
//! - [`Header`]:
//! - Key-exchange public key ([`KxPublic`], alpha in the Sphinx paper).
//! - [`Mac`] (gamma in the Sphinx paper).
//! - Routing actions ([`Actions`], beta in the Sphinx paper).
//! - [`Payload`] (delta in the Sphinx paper):
//! - [`PayloadData`].
//! - [`PayloadTag`] (for detecting tampering).
//!
//! For each hop, the routing actions field contains, in order:
//!
//! - A [`RawAction`]. Always a deliver action for the last hop and a forward action for earlier
//! hops.
//! - If the [`RawAction`] is [`RAW_ACTION_FORWARD_TO_PEER_ID`], a [`PeerId`].
//! - If the [`RawAction`] is a forward action, a [`Mac`] for the next hop.
//! - If the [`RawAction`] is [`RAW_ACTION_DELIVER_REPLY`], a [`SurbId`].
//! - If the [`RawAction`] is [`RAW_ACTION_DELIVER_COVER_WITH_ID`], a [`CoverId`].
/// Size in bytes of a [`KxPublic`].
pub const KX_PUBLIC_SIZE: usize = 32;
/// Key-exchange public key.
pub type KxPublic = [u8; KX_PUBLIC_SIZE];
pub const MAC_SIZE: usize = 16;
pub type Mac = [u8; MAC_SIZE];
/// Maximum number of hops a packet can traverse. Sending a packet directly to the final
/// destination node would count as one hop. Strictly speaking it is possible to construct packets
/// that will traverse slightly more hops than this, but not using this crate.
pub const MAX_HOPS: usize = 6;
pub const RAW_MIXNODE_INDEX_SIZE: usize = 2;
/// Raw mixnode index type, not guaranteed to be <= [`MAX_MIXNODE_INDEX`].
pub type RawMixnodeIndex = u16;
/// Maximum valid mixnode index.
pub const MAX_MIXNODE_INDEX: RawMixnodeIndex = 0xfeff;
pub const RAW_ACTION_SIZE: usize = RAW_MIXNODE_INDEX_SIZE; // A mixnode index means forward to that mixnode
pub type RawAction = RawMixnodeIndex;
pub const RAW_ACTION_FORWARD_TO_PEER_ID: RawAction = 0xff00;
pub const RAW_ACTION_DELIVER_REQUEST: RawAction = 0xff01;
pub const RAW_ACTION_DELIVER_REPLY: RawAction = 0xff02;
pub const RAW_ACTION_DELIVER_COVER: RawAction = 0xff03;
pub const RAW_ACTION_DELIVER_COVER_WITH_ID: RawAction = 0xff04;
/// Size in bytes of a [`PeerId`].
pub const PEER_ID_SIZE: usize = 32;
/// Globally unique identifier for a network peer. This is treated as an opaque type.
pub type PeerId = [u8; PEER_ID_SIZE];
/// Maximum amount of padding that might need to be appended to the routing actions for length
/// invariance at each hop.
pub const MAX_ACTIONS_PAD_SIZE: usize = RAW_ACTION_SIZE + PEER_ID_SIZE + MAC_SIZE;
pub const SURB_COVER_ID_SIZE: usize = 16;
pub const SURB_ID_SIZE: usize = SURB_COVER_ID_SIZE;
pub type SurbId = [u8; SURB_ID_SIZE];
pub const COVER_ID_SIZE: usize = SURB_COVER_ID_SIZE;
pub type CoverId = [u8; COVER_ID_SIZE];
pub const ACTIONS_SIZE: usize = (MAX_HOPS * (RAW_ACTION_SIZE + MAC_SIZE)) +
PEER_ID_SIZE + // Allow one hop to use a peer ID
SURB_COVER_ID_SIZE // Last hop may have a SURB ID or a cover ID...
- MAC_SIZE; // ...but no next-hop MAC
pub type Actions = [u8; ACTIONS_SIZE];
pub const PAYLOAD_DATA_SIZE: usize = 2048;
pub type PayloadData = [u8; PAYLOAD_DATA_SIZE];
pub const PAYLOAD_TAG_SIZE: usize = 16;
pub type PayloadTag = [u8; PAYLOAD_TAG_SIZE];
pub const PAYLOAD_TAG: PayloadTag = [0; PAYLOAD_TAG_SIZE];
pub const HEADER_SIZE: usize = KX_PUBLIC_SIZE + MAC_SIZE + ACTIONS_SIZE;
pub type Header = [u8; HEADER_SIZE];
pub const PAYLOAD_SIZE: usize = PAYLOAD_DATA_SIZE + PAYLOAD_TAG_SIZE;
pub type Payload = [u8; PAYLOAD_SIZE];
/// Size in bytes of a [`Packet`].
pub const PACKET_SIZE: usize = HEADER_SIZE + PAYLOAD_SIZE;
/// Type for packets sent between nodes. Note that all packets are the same size.
pub type Packet = [u8; PACKET_SIZE];