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 epkit:kem_pk; // epki
new sctrt:bits; // sctr new sctrt:bits; // sctr
new pidiCt:bits; // pidiC new pidi_ct:bits; // pidi_ct
new autht:bits; // auth new autht:bits; // auth
NEW_TRUSTED_SEED(seski_trusted_seed) 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) = 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(septi_trusted_seed)
NEW_TRUSTED_SEED(sspti_trusted_seed) NEW_TRUSTED_SEED(sspti_trusted_seed)
new last_cookie:key; new last_cookie:key;

View File

@@ -19,7 +19,7 @@ fun CookieMsg(
COOKIE_EV(event MCAT(eventLbl, _UnderLoadEV) (spkm, spkt, last_cookie);) \ COOKIE_EV(event MCAT(eventLbl, _UnderLoadEV) (spkm, spkt, last_cookie);) \
msgB <- Envelope(mac1, RH2b(rh)); \ msgB <- Envelope(mac1, RH2b(rh)); \
mac2_key <- create_mac2_key(sskm, spkt) \ 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 \ if Envelope(mac2_key, msgB) = mac2 then \
COOKIE_EV(event MCAT(eventLbl, _CookieValidated) (spkm, last_cookie);) \ COOKIE_EV(event MCAT(eventLbl, _CookieValidated) (spkm, last_cookie);) \
innerFunc \ 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). ) MTX_EV( event ICSent(RespHello_t, InitConf_t, key, kem_sk, kem_pk). )
SES_EV( event InitiatorSession(RespHello_t, key). ) SES_EV( event InitiatorSession(RespHello_t, key). )
let Oresp_hello(HS_DECL_ARGS) = let Oresp_hello(HS_DECL_ARGS) =
in(C, Cresp_hello(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, auth); rh <- RespHello(sidr, sidi, ecti, scti, biscuit_ct, auth);
/* try */ let ic = ( /* try */ let ic = (
ck_ini <- ck; ck_ini <- ck;
RESPHELLO_CONSUME() RESPHELLO_CONSUME()
@@ -124,7 +124,7 @@ let Oinit_hello() =
call <- Cinit_hello(sidr, biscuit_no, Ssskm, Spsk, Sspkt, Septi, Sspti, ih); call <- Cinit_hello(sidr, biscuit_no, Ssskm, Spsk, Sspkt, Septi, Sspti, ih);
#endif #endif
// TODO: This is ugly // 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() SETUP_HANDSHAKE_STATE()
eski <- kem_sk0; eski <- kem_sk0;
epti <- rng_key(setup_seed(Septi)); // RHR4 epti <- rng_key(setup_seed(Septi)); // RHR4

View File

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

View File

@@ -479,20 +479,20 @@ fn store_biscuit() {
"biscuit additional data", "biscuit additional data",
spkr, sidi, sidr); spkr, sidi, sidr);
let ct = XAEAD::enc(k, n, pt, ad); let ct = XAEAD::enc(k, n, pt, ad);
let nct = concat(n, ct); let biscuit_ct = concat(n, ct);
mix(nct) mix(biscuit_ct)
nct 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 ```pseudorust
fn load_biscuit(nct) { fn load_biscuit(biscuit_ct) {
// Decrypt the biscuit // Decrypt the biscuit
let k = biscuit_key; let k = biscuit_key;
let (n, ct) = nct; let (n, ct) = biscuit_ct;
let ad = lhash( let ad = lhash(
"biscuit additional data", "biscuit additional data",
spkr, sidi, sidr); spkr, sidi, sidr);
@@ -512,7 +512,7 @@ fn load_biscuit(nct) {
// Restore the chaining key // Restore the chaining key
ck ← pt.ck; ck ← pt.ck;
mix(nct); mix(biscuit_ct);
// Expose the biscuit no, // Expose the biscuit no,
// so the handshake code can differentiate // 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. 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`. 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 #### 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]] [[entries]]
entry_type = "Output" entry_type = "Output"
name = "ih.pidic" name = "ih.pidi_ct"
value = "Y3Wstn84+vmUb/a/CtWHFixkdyTFKEaE7joUFM0vBZPehPAeDOXls/u5I1PvViF6" value = "Y3Wstn84+vmUb/a/CtWHFixkdyTFKEaE7joUFM0vBZPehPAeDOXls/u5I1PvViF6"
code_location = "rosenpass/src/protocol/protocol.rs:3615" code_location = "rosenpass/src/protocol/protocol.rs:3615"
test_vec_set_code_location = "rosenpass/src/protocol/test_vector_sets.rs:44" 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"); protocol, cookie_key, "cookie-key");
hash_domain_ns!( hash_domain_ns!(
/// Hash domain based on [protocol] for calculating the peer id as transmitted (encrypted) /// 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 /// # Examples
/// ///
@@ -179,7 +179,7 @@ hash_domain_ns!(
hash_domain_ns!( hash_domain_ns!(
/// Hash domain based on [protocol] for calculating the additional data /// Hash domain based on [protocol] for calculating the additional data
/// during [crate::msgs::Biscuit] encryption, storing the biscuit into /// during [crate::msgs::Biscuit] encryption, storing the biscuit into
/// [crate::msgs::RespHello::biscuit]. /// [crate::msgs::RespHello::biscuit_ct].
/// ///
/// # Examples /// # Examples
/// ///

View File

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

View File

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