chore(whitepaper): Biscuit and pidi cipher texts now called pidi_ct/biscuit_ct

This commit is contained in:
Karolin Varner
2025-08-28 15:14:54 +02:00
parent 75ff1e8292
commit 4daca9ed56
9 changed files with 39 additions and 37 deletions

View File

@@ -58,7 +58,7 @@ let secure_init_hello(initiator: kem_sk_tmpl, sidi : SessionId, psk: key_tmpl, r
new epkit:kem_pk; // epki
new sctrt:bits; // sctr
new pidiCt:bits; // pidiC
new pidi_ct:bits; // pidi_ct
new autht:bits; // auth
NEW_TRUSTED_SEED(seski_trusted_seed)
@@ -70,9 +70,9 @@ let secure_init_hello(initiator: kem_sk_tmpl, sidi : SessionId, psk: key_tmpl, r
let secure_resp_hello(initiator: kem_sk_tmpl, responder: kem_sk_tmpl, sidi:SessionId, sidr:SessionId, biscuit_no:Atom, psk:key_tmpl) =
in(D, InitHello(=secure_sidi, epki, sctr, pidiC, auth));
in(D, InitHello(=secure_sidi, epki, sctr, pidi_ct, auth));
ih <- InitHello(sidi, epki, sctr, pidiC, auth);
ih <- InitHello(sidi, epki, sctr, pidi_ct, auth);
NEW_TRUSTED_SEED(septi_trusted_seed)
NEW_TRUSTED_SEED(sspti_trusted_seed)
new last_cookie:key;

View File

@@ -19,7 +19,7 @@ fun CookieMsg(
COOKIE_EV(event MCAT(eventLbl, _UnderLoadEV) (spkm, spkt, last_cookie);) \
msgB <- Envelope(mac1, RH2b(rh)); \
mac2_key <- create_mac2_key(sskm, spkt) \
let RespHello(sidi, sidr, ecti, scti, biscuit, auth) = rh in \
let RespHello(sidi, sidr, ecti, scti, biscuit_ct, auth) = rh in \
if Envelope(mac2_key, msgB) = mac2 then \
COOKIE_EV(event MCAT(eventLbl, _CookieValidated) (spkm, last_cookie);) \
innerFunc \

View File

@@ -86,8 +86,8 @@ MTX_EV( event RHRjct(RespHello_t, key, kem_sk, kem_pk). )
MTX_EV( event ICSent(RespHello_t, InitConf_t, key, kem_sk, kem_pk). )
SES_EV( event InitiatorSession(RespHello_t, key). )
let Oresp_hello(HS_DECL_ARGS) =
in(C, Cresp_hello(RespHello(sidr, =sidi, ecti, scti, biscuit, auth)));
rh <- RespHello(sidr, sidi, ecti, scti, biscuit, auth);
in(C, Cresp_hello(RespHello(sidr, =sidi, ecti, scti, biscuit_ct, auth)));
rh <- RespHello(sidr, sidi, ecti, scti, biscuit_ct, auth);
/* try */ let ic = (
ck_ini <- ck;
RESPHELLO_CONSUME()
@@ -124,7 +124,7 @@ let Oinit_hello() =
call <- Cinit_hello(sidr, biscuit_no, Ssskm, Spsk, Sspkt, Septi, Sspti, ih);
#endif
// TODO: This is ugly
let InitHello(sidi, epki, sctr, pidiC, auth) = ih in
let InitHello(sidi, epki, sctr, pidi_ct, auth) = ih in
SETUP_HANDSHAKE_STATE()
eski <- kem_sk0;
epti <- rng_key(setup_seed(Septi)); // RHR4

View File

@@ -7,7 +7,7 @@ fun InitHello(
SessionId, // sidi
kem_pk, // epki
bits, // sctr
bits, // pidiC
bits, // pidi_ct
bits // auth
) : InitHello_t [data].
@@ -17,16 +17,16 @@ fun InitHello(
/* not handled here */ /* IHI3 */ \
MIX2(sid2b(sidi), kem_pk2b(epki)) /* IHI4 */ \
ENCAPS_AND_MIX(sctr, spkr, sptr) /* IHI5 */ \
ENCRYPT_AND_MIX(pidiC, pidi) /* IHI6 */ \
ENCRYPT_AND_MIX(pidi_ct, pidi) /* IHI6 */ \
MIX2(kem_pk2b(spki), k2b(psk)) /* IHI7 */ \
ENCRYPT_AND_MIX(auth, empty) /* IHI8 */ \
ih <- InitHello(sidi, epki, sctr, pidiC, auth);
ih <- InitHello(sidi, epki, sctr, pidi_ct, auth);
#define INITHELLO_CONSUME() \
ck <- lprf1(CK_INIT, kem_pk2b(spkr)); /* IHR1 */ \
MIX2(sid2b(sidi), kem_pk2b(epki)) /* IHR4 */ \
DECAPS_AND_MIX(sskr, spkr, sctr) /* IHR5 */ \
DECRYPT_AND_MIX(pid, pidiC) /* IHR6 */ \
DECRYPT_AND_MIX(pid, pidi_ct) /* IHR6 */ \
LOOKUP_SENDER(pid) /* IHR6 */ \
MIX2(kem_pk2b(spki), k2b(psk)) /* IHR7 */ \
DECRYPT_AND_MIX(DUMMY(empty), auth)
@@ -46,17 +46,17 @@ fun RespHello(
MIX2(sid2b(sidr), sid2b(sidi)) /* RHR3 */ \
ENCAPS_AND_MIX(ecti, epki, epti) /* RHR4 */ \
ENCAPS_AND_MIX(scti, spki, spti) /* RHR5 */ \
STORE_BISCUIT(biscuit) /* RHR6 */ \
STORE_BISCUIT(biscuit_ct) /* RHR6 */ \
ENCRYPT_AND_MIX(auth, empty) /* RHR7 */ \
rh <- RespHello(sidr, sidi, ecti, scti, biscuit, auth);
rh <- RespHello(sidr, sidi, ecti, scti, biscuit_ct, auth);
#define RESPHELLO_CONSUME() \
let RespHello(sidr, sidi, ecti, scti, biscuit, auth) = rh in \
let RespHello(sidr, sidi, ecti, scti, biscuit_ct, auth) = rh in \
/* not handled here */ /* RHI2 */ \
MIX2(sid2b(sidr), sid2b(sidi)) /* RHI3 */ \
DECAPS_AND_MIX(eski, epki, ecti) /* RHI4 */ \
DECAPS_AND_MIX(sski, spki, scti) /* RHI5 */ \
MIX(biscuit) /* RHI6 */ \
MIX(biscuit_ct) /* RHI6 */ \
DECRYPT_AND_MIX(DUMMY(empty), auth) /* RHI7 */
type InitConf_t.
@@ -70,11 +70,11 @@ fun InitConf(
#define INITCONF_PRODUCE() \
MIX2(sid2b(sidi), sid2b(sidr)) /* ICI3 */ \
ENCRYPT_AND_MIX(auth, empty) /* ICI4 */ \
ic <- InitConf(sidi, sidr, biscuit, auth);
ic <- InitConf(sidi, sidr, biscuit_ct, auth);
#define INITCONF_CONSUME() \
let InitConf(sidi, sidr, biscuit, auth) = ic in \
LOAD_BISCUIT(biscuit_no, biscuit) /* ICR1 */ \
let InitConf(sidi, sidr, biscuit_ct, auth) = ic in \
LOAD_BISCUIT(biscuit_no, biscuit_ct)/* ICR1 */ \
ENCRYPT_AND_MIX(rh_auth, empty) /* ICIR */ \
ck_rh <- ck; /* ---- */ /* TODO: Move into oracles.mpv */ \
MIX2(sid2b(sidi), sid2b(sidr)) /* ICR3 */ \

View File

@@ -479,20 +479,20 @@ fn store_biscuit() {
"biscuit additional data",
spkr, sidi, sidr);
let ct = XAEAD::enc(k, n, pt, ad);
let nct = concat(n, ct);
let biscuit_ct = concat(n, ct);
mix(nct)
nct
mix(biscuit_ct)
biscuit_ct
}
```
Note that the `mix(nct)` call updates the chaining key, but that update does not make it into the biscuit. Therefore, `mix(nct)` is reapplied in `load_biscuit`. The responder handshake code also needs to reapply any other operations modifying `ck` after calling `store_biscuit`. The handshake code on the initiator's side also needs to call `mix(nct)`.
Note that the `mix(biscuit_ct)` call updates the chaining key, but that update does not make it into the biscuit. Therefore, `mix(biscuit_ct)` is reapplied in `load_biscuit`. The responder handshake code also needs to reapply any other operations modifying `ck` after calling `store_biscuit`. The handshake code on the initiator's side also needs to call `mix(biscuit_ct)`.
```pseudorust
fn load_biscuit(nct) {
fn load_biscuit(biscuit_ct) {
// Decrypt the biscuit
let k = biscuit_key;
let (n, ct) = nct;
let (n, ct) = biscuit_ct;
let ad = lhash(
"biscuit additional data",
spkr, sidi, sidr);
@@ -512,7 +512,7 @@ fn load_biscuit(nct) {
// Restore the chaining key
ck ← pt.ck;
mix(nct);
mix(biscuit_ct);
// Expose the biscuit no,
// so the handshake code can differentiate
@@ -955,6 +955,8 @@ Changes, in particular:
```
16. Point out explicitly that we use KEMs from NIST-Competition Round 3. Include links to the competition submission packages. Update citations to reflect the exact specification version.
17. Consistent naming convention. Always use the term `secret key`, never `private key`.
18. `pidiC` -> `pidi_ct`; to make it clearer that this is a cipher text
19. Where we refer to the biscuit ciphertext, we now use the term `biscuit_ct`. Previously we had used various variable names such as `nct` (nonce followed by cipher text) or just plain `biscuit`.
#### 2025-06-24 Specifying the `osk` used for WireGuard as a protocol extension

View File

@@ -150,7 +150,7 @@ test_vec_set_code_location = "rosenpass/src/protocol/test_vector_sets.rs:44"
[[entries]]
entry_type = "Output"
name = "ih.pidic"
name = "ih.pidi_ct"
value = "Y3Wstn84+vmUb/a/CtWHFixkdyTFKEaE7joUFM0vBZPehPAeDOXls/u5I1PvViF6"
code_location = "rosenpass/src/protocol/protocol.rs:3615"
test_vec_set_code_location = "rosenpass/src/protocol/test_vector_sets.rs:44"

View File

@@ -166,7 +166,7 @@ hash_domain_ns!(
protocol, cookie_key, "cookie-key");
hash_domain_ns!(
/// Hash domain based on [protocol] for calculating the peer id as transmitted (encrypted)
/// in [crate::msgs::InitHello::pidic].
/// in [crate::msgs::InitHello::pidi_ct].
///
/// # Examples
///
@@ -179,7 +179,7 @@ hash_domain_ns!(
hash_domain_ns!(
/// Hash domain based on [protocol] for calculating the additional data
/// during [crate::msgs::Biscuit] encryption, storing the biscuit into
/// [crate::msgs::RespHello::biscuit].
/// [crate::msgs::RespHello::biscuit_ct].
///
/// # Examples
///

View File

@@ -135,7 +135,7 @@ pub struct InitHello {
/// Classic McEliece Ciphertext
pub sctr: [u8; StaticKem::CT_LEN],
/// Encryped: 16 byte hash of McEliece initiator static key
pub pidic: [u8; Aead::TAG_LEN + 32],
pub pidi_ct: [u8; Aead::TAG_LEN + 32],
/// Encrypted TAI64N Time Stamp (against replay attacks)
pub auth: [u8; Aead::TAG_LEN],
}
@@ -188,7 +188,7 @@ pub struct RespHello {
/// Empty encrypted message (just an auth tag)
pub auth: [u8; Aead::TAG_LEN],
/// Responders handshake state in encrypted form
pub biscuit: [u8; BISCUIT_CT_LEN],
pub biscuit_ct: [u8; BISCUIT_CT_LEN],
}
/// This is the third message sent by the initiator to the responder
@@ -233,7 +233,7 @@ pub struct InitConf {
/// Copied from RespHello
pub sidr: [u8; 4],
/// Responders handshake state in encrypted form
pub biscuit: [u8; BISCUIT_CT_LEN],
pub biscuit_ct: [u8; BISCUIT_CT_LEN],
/// Empty encrypted message (just an auth tag)
pub auth: [u8; Aead::TAG_LEN],
}

View File

@@ -3608,7 +3608,7 @@ impl CryptoServer {
// IHI6
protocol_section!("IHI6", {
hs.core.encrypt_and_mix(
ih.pidic.as_mut_slice(),
ih.pidi_ct.as_mut_slice(),
self.pidm(peer.get(self).protocol_version.keyed_hash())?
.as_ref(),
)?;
@@ -3707,7 +3707,7 @@ impl CryptoServer {
// IHR6
let peer = protocol_section!("IHR6", {
let mut peerid = PeerId::zero();
core.decrypt_and_mix(&mut *peerid, &ih.pidic)?;
core.decrypt_and_mix(&mut *peerid, &ih.pidi_ct)?;
self.find_peer(peerid)
.with_context(|| format!("No such peer {peerid:?}."))?
});
@@ -3784,7 +3784,7 @@ impl CryptoServer {
// RHR6
protocol_section!("RHR6", {
core.store_biscuit_with_test_vector::<TV>(self, peer, &mut rh.biscuit)?;
core.store_biscuit_with_test_vector::<TV>(self, peer, &mut rh.biscuit_ct)?;
TV::check_value(
&test_values.chaining_key_rhr_6,
&core.ck.clone().danger_into_secret(),
@@ -3872,7 +3872,7 @@ impl CryptoServer {
// RHI6
protocol_section!("RHI6", {
core.mix(&rh.biscuit)?;
core.mix(&rh.biscuit_ct)?;
});
// RHI7
@@ -3889,7 +3889,7 @@ impl CryptoServer {
// ICI3
protocol_section!("ICI3", {
core.mix(&ic.sidi)?.mix(&ic.sidr)?;
ic.biscuit.copy_from_slice(&rh.biscuit);
ic.biscuit_ct.copy_from_slice(&rh.biscuit_ct);
});
// ICI4
@@ -3937,7 +3937,7 @@ impl CryptoServer {
let (peer, biscuit_no, mut core) = protocol_section!("ICR1", {
HandshakeState::load_biscuit(
self,
&ic.biscuit,
&ic.biscuit_ct,
SessionId::from_slice(&ic.sidi),
SessionId::from_slice(&ic.sidr),
keyed_hash,