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
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
//! §4 — mac1, the day-one DoS gate.
//!
//! ```text
//! key = BLAKE2b-256(MAC1_LABEL ‖ recipient_static_canonical)
//! mac1 = keyed-BLAKE2b-128(key, all packet bytes preceding the tag)
//! ```
//!
//! **Both BLAKE2b invocations are plain** — no salt, no personalisation
//! (ruling 66), matching WireGuard's plain keyed BLAKE2s. Domain
//! separation is by **concatenation**: [`MAC1_LABEL`] is a prefix on the
//! key preimage, never the primitive's personalisation parameter. The key
//! preimage is `MAC1_LABEL.len() + STATIC_PUBLIC_LEN` = 12 + 65 = 77 bytes
//! on the reference suite.
//!
//! `recipient_static_canonical` is the **recipient's** static in §2.4's
//! canonical encoding: on a HandshakeInit the responder's, on a
//! HandshakeResp the initiator's.
//!
//! mac1 is verified **before any curve or DH work** (§4.2) — a garbage
//! flood, a wrong-key packet or a wrong-curve-suite packet dies at one
//! keyed hash and never reaches the DH provider. A same-curve sibling
//! suite's packet is mac1-valid — the key preimage above carries no suite
//! — and prices as §6.9's mac1-valid rows (§4.2, amended by ruling 279).
//! Data packets carry no mac1 at all (§3.4).
//!
//! # The one raw primitive
//!
//! This module takes BLAKE2b from `cryptoxide` **directly**, which is the
//! single exception to "every Noise/curve operation flows through hiss":
//! mac1 is a keyed hash over public data, not session cryptography. It
//! must not become two exceptions. In particular **no `hiss::noise` hash
//! type appears here**, because that would silently make mac1 follow the
//! suite's `Hash` and undo §4.4 — mac1 is fixed keyed-BLAKE2b for every
//! suite.
use Blake2b;
use crateconstants;
/// A mac1 key: `BLAKE2b-256(MAC1_LABEL ‖ recipient_static_canonical)`.
/// §4.1.
///
/// **Not secret** (§4.3). Anyone holding the recipient's public static can
/// compute it and mint mac1-valid packets; mac1 is an anti-amplification
/// and cheap-reject gate, and the real authentication is the Noise
/// handshake underneath. There is deliberately no `Zeroize` and no `Drop`
/// impl: either would imply a security property mac1 explicitly does not
/// have.
///
/// # Why a key type rather than a free function
///
/// The derivation happens **once per static**, not once per packet, and
/// the type is what makes that the easy thing to write. On the receive
/// path the recipient is always us, so the key is a constant of the
/// endpoint; on the send path it is a constant of the peer. A garbage
/// flood must cost one keyed hash, not a hash plus a key derivation
/// (§4.2's cost ladder) — and a free function keyed by a public key hands
/// every caller the chance to re-derive per packet, which nothing would
/// ever notice.
pub ;
// `Blake2b::<128>` above takes its output width as a const-generic
// *literal*, which is the one place `MAC1_LEN` could drift from the
// primitive that produces it: `finalize_at` checks the buffer length at
// run time, and a run-time panic in the DoS gate is not a failure mode
// worth having. This makes the disagreement a build failure instead.
// (Stage one needs no such tie: `Blake2b::<256>::finalize` returns
// `[u8; 32]`, and the field's type is that array.)
const _: = assert!;