mirror of
https://github.com/rosenpass/rosenpass.git
synced 2026-02-28 06:23:08 -08:00
add proverif analysis of Rosenpass, the protocol
The analysis was conducted as joint effort between @koraa and @blipp. Co-authored-by: Benjamin Lipp <blipp@mailbox.org>
This commit is contained in:
0
analysis/rosenpass/common.macro
Normal file
0
analysis/rosenpass/common.macro
Normal file
192
analysis/rosenpass/handshake_state.mpv
Normal file
192
analysis/rosenpass/handshake_state.mpv
Normal file
@@ -0,0 +1,192 @@
|
||||
#pragma once
|
||||
#include "prelude/basic.mpv"
|
||||
#include "prelude/bits.mpv"
|
||||
#include "crypto/key.mpv"
|
||||
#include "crypto/kem.mpv"
|
||||
#include "crypto/aead.mpv"
|
||||
#include "rosenpass/prf.mpv"
|
||||
|
||||
type SessionId.
|
||||
const sid0:SessionId.
|
||||
letfun sid_new() =
|
||||
new sid:SessionId;
|
||||
sid.
|
||||
fun sid2b(SessionId) : bits [typeConverter].
|
||||
|
||||
type Role.
|
||||
const ini_role:Role.
|
||||
const res_role:Role.
|
||||
|
||||
type Handshake_t.
|
||||
fun Handshake(
|
||||
Role, // role
|
||||
key, // biscuit_key
|
||||
kem_sk, // sskm
|
||||
kem_pk, // spkm
|
||||
key, // psk
|
||||
kem_pk, // spkt
|
||||
SessionId, // sidm (session id of mine)
|
||||
SessionId, // sidt (session id of theirs)
|
||||
key, // ck
|
||||
kem_sk, // eski
|
||||
kem_pk // epki
|
||||
) : Handshake_t [data].
|
||||
|
||||
#define decl_hs() \
|
||||
biscuit_key <- key0; \
|
||||
sskm <- kem_sk0; \
|
||||
spkm <- kem_pk0; \
|
||||
psk <- key0; \
|
||||
spkt <- kem_pk0; \
|
||||
sidm <- sid0; \
|
||||
sidt <- sid0; \
|
||||
ck <- key0; \
|
||||
eski <- ccakem_sk0; \
|
||||
epki <- ccakem_pk0
|
||||
|
||||
#define HS_DECL_ARGS \
|
||||
biscuit_key:key, \
|
||||
sskm:kem_sk, \
|
||||
spkm:kem_pk, \
|
||||
psk:key, \
|
||||
spkt:kem_pk, \
|
||||
sidm:SessionId, \
|
||||
sidt:SessionId, \
|
||||
ck:key, \
|
||||
eski:kem_sk, \
|
||||
epki:kem_pk
|
||||
#define HS_PASS_ARGS \
|
||||
biscuit_key, \
|
||||
sskm, \
|
||||
spkm, \
|
||||
psk, \
|
||||
spkt, \
|
||||
sidm, \
|
||||
sidt, \
|
||||
ck, \
|
||||
eski, \
|
||||
epki
|
||||
|
||||
#define hs Handshake(role, biscuit_key, sskm, spkm, psk, spkt, sidm, sidt, ck, eski, epki)
|
||||
|
||||
#define is_ini role(hs) = ini_role.
|
||||
#define is_res role(hs) = res_role.
|
||||
|
||||
// peer id
|
||||
|
||||
#ifdef SIMPLE_MODEL
|
||||
fun peerid(kem_pk) : bits.
|
||||
#else
|
||||
letfun peerid(pk:kem_pk) =
|
||||
k2b(lprf1(PEER_ID, kem_pk2b(pk))).
|
||||
#endif
|
||||
|
||||
#define pidm peerid(spkm)
|
||||
#define pidt peerid(spkt)
|
||||
|
||||
#define LOOKUP_SENDER(pid) \
|
||||
ASSERT(pidt = (pid));
|
||||
|
||||
// Handshake processing functions
|
||||
|
||||
#ifdef SIMPLE_MODEL
|
||||
fun ck_mix(key, bits) : key.
|
||||
fun ck_hs_enc(key) : key.
|
||||
fun ck_osk(key) : key.
|
||||
#endif
|
||||
|
||||
#ifdef SIMPLE_MODEL
|
||||
#define MIX(ikm) ck <- ck_mix(ck, ikm);
|
||||
#else
|
||||
#define MIX(ikm) ck <- prf(extract_key(MIX), ikm).
|
||||
#endif
|
||||
|
||||
#define EXTRACT_KEY(l) prf(ck, k2b(lprf1(CK_EXTRACT, l)));
|
||||
#define EXTRACT_KEY2(a, b) prf(ck, k2b(lprf2(CK_EXTRACT, a, b)));
|
||||
#define EXPORT_KEY(l) EXTRACT_KEY2(USER, l)
|
||||
#define MIX2(a, b) MIX(a) MIX(b)
|
||||
#define MIX3(a, b, c) MIX(a) MIX2(b, c)
|
||||
|
||||
#ifdef SIMPLE_MODEL
|
||||
#define hs_enc ck_hs_enc(ck)
|
||||
#define osk ck_osk(ck)
|
||||
#else
|
||||
#define hs_enc EXTRACT_KEY(HS_ENC)
|
||||
#define osk EXPORT_KEY(OSK)
|
||||
#endif
|
||||
|
||||
(* PERFORMANCE: This leads to exponential expression tree sizes because
|
||||
it updates the hash to contain itself twice: Once as part of the hash
|
||||
chain and once through the AEAD cipher text.
|
||||
|
||||
As a fix, the hash of the AEAD cipher text is used itself to generate
|
||||
the hash chain. This improves performance reducing runtime from ~60s to ~35.
|
||||
Whether this is actually a good idea remains to be debated. *)
|
||||
#ifdef SIMPLE_MODEL
|
||||
#define ENCRYPT_AND_MIX(ct, pt) \
|
||||
ct <- aead_enc(hs_enc, pt); \
|
||||
MIX(pt)
|
||||
#define DECRYPT_AND_MIX(pt, ct) \
|
||||
pt <- aead_dec(hs_enc, ct); \
|
||||
MIX(pt)
|
||||
|
||||
#else
|
||||
letfun ENCRYPT_AND_MIX(ct, pt) \
|
||||
AEAD_ENC(ct, hs_enc, 0, pt, empty) \
|
||||
MIX(ct)
|
||||
#define DECRYPT_AND_MIX(pt, ct) \
|
||||
AEAD_DEC(pt, hs_enc, 0, ct, empty)
|
||||
MIX(ct)
|
||||
|
||||
#endif
|
||||
|
||||
// TODO: Migrate kems to use binary ciphertexts directly
|
||||
#define ENCAPS_AND_MIX(ct, pk, shk) \
|
||||
ct <- kem_enc(pk, shk); \
|
||||
MIX3(kem_pk2b(pk), ct, k2b(shk))
|
||||
#define DECAPS_AND_MIX(sk, pk, ct) \
|
||||
DUMMY(shk) <- kem_dec(sk, ct); \
|
||||
MIX3(kem_pk2b(pk), ct, k2b(DUMMY(shk)))
|
||||
|
||||
|
||||
// biscuits
|
||||
|
||||
/*
|
||||
Biscuit replay protection is handled differently
|
||||
in the model than in the specification; the specification
|
||||
uses a nonce counter; the model uses a biscuit id
|
||||
the adversary and stores a table of all used nonces.
|
||||
This technique is used because modeling state updates in proverif
|
||||
is possible but inefficient.
|
||||
*/
|
||||
|
||||
type Biscuit_t.
|
||||
fun Biscuit(
|
||||
bits, // pidi
|
||||
Atom, // no
|
||||
key // ck
|
||||
) : Biscuit_t [data].
|
||||
|
||||
fun Biscuit2b(Biscuit_t) : bitstring [typeConverter].
|
||||
|
||||
#define BiscuitBits(pidi, no, ck) Biscuit2b(Biscuit(pidi, no, ck))
|
||||
|
||||
#ifdef SIMPLE_MODEL
|
||||
fun biscuit_ad(kem_pk, SessionId, SessionId) : bits.
|
||||
#else
|
||||
letfun biscuit_ad(spkr:kem_pk, sidi:SessionId, sidr:SessionId) =
|
||||
k2b(lprf3(BISCUIT_AD, kem_pk2b(spkr), sid2b(sidi), sid2b(sidr))).
|
||||
#endif
|
||||
|
||||
#define STORE_BISCUIT(ct) \
|
||||
ct <- xaead_enc(biscuit_key, \
|
||||
/* pt */ BiscuitBits(pidi, biscuit_no, ck), \
|
||||
/* ad */ biscuit_ad(spkr, sidi, sidr)); \
|
||||
MIX(ct)
|
||||
|
||||
#define LOAD_BISCUIT(nonce, ct) \
|
||||
let BiscuitBits(DUMMY(pid), nonce, ck) = \
|
||||
xaead_dec(biscuit_key, ct, \
|
||||
/* ad */ biscuit_ad(spkr, sidi, sidr)) in \
|
||||
MIX(ct) \
|
||||
LOOKUP_SENDER(DUMMY(pid))
|
||||
12
analysis/rosenpass/initiator.macro
Normal file
12
analysis/rosenpass/initiator.macro
Normal file
@@ -0,0 +1,12 @@
|
||||
#include "rosenpass/undef.macro"
|
||||
#define role ini_role
|
||||
#define sski sskm
|
||||
#define spki spkm
|
||||
#define sskr kem_sk0
|
||||
#define spkr spkt
|
||||
#define eskm eski
|
||||
#define epkm epki
|
||||
#define sidi sidm
|
||||
#define sidr sidt
|
||||
#define pidi pidm
|
||||
#define pidr pidt
|
||||
227
analysis/rosenpass/oracles.mpv
Normal file
227
analysis/rosenpass/oracles.mpv
Normal file
@@ -0,0 +1,227 @@
|
||||
#pragma once
|
||||
#include "rosenpass/prf.mpv"
|
||||
#include "rosenpass/handshake_state.mpv"
|
||||
#include "rosenpass/protocol.mpv"
|
||||
|
||||
DECL_SETUP(key)
|
||||
|
||||
DECL_SETUP(kem_sk)
|
||||
#define kem_pk_tmpl kem_sk_tmpl
|
||||
letfun setup_kem_pk(sks:kem_pk_tmpl) =
|
||||
kem_pub(setup_kem_sk(sks)).
|
||||
#define SETUP_KEM_PAIR(sk, pk, setup) \
|
||||
sk <- setup_kem_sk(setup); \
|
||||
pk <- kem_pub(sk);
|
||||
|
||||
// TODO: Model use of multiple shared keys
|
||||
// TODO: Hide shk inside the kem abstraction?
|
||||
fun biscuit_key(kem_sk) : key [private].
|
||||
|
||||
#define SETUP_SERVER(biscuit_key, sk, pk, setup) \
|
||||
SETUP_KEM_PAIR(sk, pk, setup) \
|
||||
biscuit_key <- biscuit_key(sk);
|
||||
|
||||
#define SETUP_HANDSHAKE_STATE() \
|
||||
SETUP_SERVER(biscuit_key, sskm, spkm, Ssskm) \
|
||||
psk <- setup_key(Spsk); \
|
||||
spkt <- setup_kem_pk(Sspkt);
|
||||
|
||||
type seed.
|
||||
fun rng_key(seed) : key.
|
||||
fun rng_kem_sk(seed) : kem_sk.
|
||||
DECL_SETUP(seed)
|
||||
#define RNG_KEM_PAIR(sk, pk, setup) \
|
||||
sk <- rng_kem_sk(setup_seed(setup)); \
|
||||
pk <- kem_pub(sk);
|
||||
|
||||
event ConsumeSeed(Atom, seed, Atom).
|
||||
const Sptr, Epti, Spti, Eski:Atom.
|
||||
|
||||
restriction s:seed, p1:Atom, p2:Atom, ad1:Atom, ad2:Atom;
|
||||
event(ConsumeSeed(p1, s, ad1)) && event(ConsumeSeed(p2, s, ad2))
|
||||
==> p1 = p2 && ad1 = ad2.
|
||||
|
||||
#include "rosenpass/responder.macro"
|
||||
fun Cinit_conf(kem_sk_tmpl, key_tmpl, kem_pk_tmpl, InitConf_t) : Atom [data].
|
||||
CK_EV( event OskOinit_conf(key, key). )
|
||||
MTX_EV( event ICRjct(InitConf_t, key, kem_sk, kem_pk). )
|
||||
SES_EV( event ResponderSession(InitConf_t, key). )
|
||||
event ConsumeBiscuit(Atom, kem_sk, kem_pk, Atom).
|
||||
let Oinit_conf() =
|
||||
in(C, Cinit_conf(Ssskm, Spsk, Sspkt, ic));
|
||||
#if RANDOMIZED_CALL_IDS
|
||||
new call:Atom;
|
||||
#else
|
||||
call <- Cinit_conf(Ssskm, Spsk, Sspkt, ic);
|
||||
#endif
|
||||
SETUP_HANDSHAKE_STATE()
|
||||
eski <- kem_sk0;
|
||||
epki <- kem_pk0;
|
||||
let try_ = (
|
||||
INITCONF_CONSUME()
|
||||
event ConsumeBiscuit(biscuit_no, sskm, spkt, call);
|
||||
CK_EV( event OskOinit_conf(ck_rh, osk); )
|
||||
SES_EV( event ResponderSession(ic, osk); )
|
||||
0
|
||||
) in (
|
||||
NOP
|
||||
) else (
|
||||
#if MESSAGE_TRANSMISSION_EVENTS
|
||||
MTX_EV( event ICRjct(ic, psk, sskr, spki) )
|
||||
#else
|
||||
0
|
||||
#endif
|
||||
).
|
||||
|
||||
restriction biscuit_no:Atom, sskm:kem_sk, spkr:kem_pk, ad1:Atom, ad2:Atom;
|
||||
event(ConsumeBiscuit(biscuit_no, sskm, spkr, ad1)) && event(ConsumeBiscuit(biscuit_no, sskm, spkr, ad2))
|
||||
==> ad1 = ad2.
|
||||
|
||||
// TODO: Restriction biscuit no invalidation
|
||||
|
||||
#include "rosenpass/initiator.macro"
|
||||
fun Cresp_hello(RespHello_t) : Atom [data].
|
||||
CK_EV( event OskOresp_hello(key, key, key). )
|
||||
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);
|
||||
/* try */ let ic = (
|
||||
ck_ini <- ck;
|
||||
RESPHELLO_CONSUME()
|
||||
ck_ih <- ck;
|
||||
INITCONF_PRODUCE()
|
||||
CK_EV (event OskOresp_hello(ck_ini, ck_ih, osk); ) // TODO: Queries testing that there is no duplication
|
||||
MTX_EV( event ICSent(rh, ic, psk, sski, spkr); )
|
||||
SES_EV( event InitiatorSession(rh, osk); )
|
||||
ic
|
||||
/* success */ ) in (
|
||||
out(C, ic)
|
||||
/* fail */ ) else (
|
||||
#if MESSAGE_TRANSMISSION_EVENTS
|
||||
event RHRjct(rh, psk, sski, spkr)
|
||||
#else
|
||||
0
|
||||
#endif
|
||||
).
|
||||
|
||||
// TODO: Restriction: Biscuit no invalidation
|
||||
|
||||
#include "rosenpass/responder.macro"
|
||||
fun Cinit_hello(SessionId, Atom, kem_sk_tmpl, key_tmpl, kem_pk_tmpl, seed_tmpl, seed_tmpl, InitHello_t) : Atom [data].
|
||||
CK_EV( event OskOinit_hello(key, key, key, kem_sk, kem_pk, kem_pk, key, key). )
|
||||
MTX_EV( event IHRjct(InitHello_t, key, kem_sk, kem_pk). )
|
||||
MTX_EV( event RHSent(InitHello_t, RespHello_t, key, kem_sk, kem_pk). )
|
||||
event ConsumeSidr(SessionId, Atom).
|
||||
event ConsumeBn(Atom, kem_sk, kem_pk, Atom).
|
||||
let Oinit_hello() =
|
||||
in(C, Cinit_hello(sidr, biscuit_no, Ssskm, Spsk, Sspkt, Septi, Sspti, ih));
|
||||
#if RANDOMIZED_CALL_IDS
|
||||
new call:Atom;
|
||||
#else
|
||||
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
|
||||
SETUP_HANDSHAKE_STATE()
|
||||
eski <- kem_sk0;
|
||||
epti <- rng_key(setup_seed(Septi)); // RHR4
|
||||
spti <- rng_key(setup_seed(Sspti)); // RHR5
|
||||
event ConsumeBn(biscuit_no, sskm, spkt, call);
|
||||
event ConsumeSidr(sidr, call);
|
||||
event ConsumeSeed(Epti, setup_seed(Septi), call);
|
||||
event ConsumeSeed(Spti, setup_seed(Sspti), call);
|
||||
let rh = (
|
||||
INITHELLO_CONSUME()
|
||||
ck_ini <- ck;
|
||||
RESPHELLO_PRODUCE()
|
||||
CK_EV( event OskOinit_hello(ck_ini, ck, psk, sskr, spki, epki, epti, spti); ) // TODO: Queries testing that there is no duplication
|
||||
MTX_EV( event RHSent(ih, rh, psk, sskr, spki); )
|
||||
rh
|
||||
/* success */ ) in (
|
||||
out(C, rh)
|
||||
/* fail */ ) else (
|
||||
#if MESSAGE_TRANSMISSION_EVENTS
|
||||
event IHRjct(ih, psk, sskr, spki)
|
||||
#else
|
||||
0
|
||||
#endif
|
||||
).
|
||||
|
||||
restriction sid:SessionId, ad1:Atom, ad2:Atom;
|
||||
event(ConsumeSidr(sid, ad1)) && event(ConsumeSidr(sid, ad2))
|
||||
==> ad1 = ad2.
|
||||
|
||||
restriction biscuit_no:Atom, sskm:kem_sk, spkr:kem_pk, ad1:Atom, ad2:Atom;
|
||||
event(ConsumeBn(biscuit_no, sskm, spkr, ad1)) && event(ConsumeBn(biscuit_no, sskm, spkr, ad2))
|
||||
==> ad1 = ad2.
|
||||
|
||||
// TODO: Restriction: Attacker may not reuse session ids
|
||||
// TODO: Restriction: Attacker may not reuse biscuit no
|
||||
|
||||
#include "rosenpass/initiator.macro"
|
||||
fun Cinitiator(SessionId, kem_sk_tmpl, key_tmpl, kem_pk_tmpl, seed_tmpl, seed_tmpl) : Atom [data].
|
||||
CK_EV( event OskOinitiator_ck(key). )
|
||||
CK_EV( event OskOinitiator(key, key, kem_sk, kem_pk, key). )
|
||||
MTX_EV( event IHSent(InitHello_t, key, kem_sk, kem_pk). )
|
||||
event ConsumeSidi(SessionId, Atom).
|
||||
let Oinitiator() =
|
||||
in(C, Cinitiator(sidi, Ssskm, Spsk, Sspkt, Seski, Ssptr));
|
||||
#if RANDOMIZED_CALL_IDS
|
||||
new call:Atom;
|
||||
#else
|
||||
call <- Cinitiator(sidi, Ssskm, Spsk, Sspkt, Seski, Ssptr);
|
||||
#endif
|
||||
SETUP_HANDSHAKE_STATE()
|
||||
RNG_KEM_PAIR(eski, epki, Seski) // IHI3
|
||||
sidr <- sid0;
|
||||
sptr <- rng_key(setup_seed(Ssptr)); // IHI5
|
||||
event ConsumeSidi(sidi, call);
|
||||
event ConsumeSeed(Sptr, setup_seed(Ssptr), call);
|
||||
event ConsumeSeed(Eski, setup_seed(Seski), call);
|
||||
INITHELLO_PRODUCE()
|
||||
CK_EV( event OskOinitiator_ck(ck); )
|
||||
CK_EV( event OskOinitiator(ck, psk, sski, spkr, sptr); )
|
||||
MTX_EV( event IHSent(ih, psk, sski, spkr); )
|
||||
out(C, ih);
|
||||
Oresp_hello(HS_PASS_ARGS).
|
||||
|
||||
restriction sid:SessionId, ad1:Atom, ad2:Atom;
|
||||
event(ConsumeSidi(sid, ad1)) && event(ConsumeSidi(sid, ad2))
|
||||
==> ad1 = ad2.
|
||||
|
||||
// TODO: Should this be modeled without an oracle
|
||||
fun Creveal_kem_pk(kem_sk_tmpl) : Atom [data].
|
||||
event RevealPk(kem_pk).
|
||||
let Oreveal_kem_pk =
|
||||
in(C, Creveal_kem_pk(Spk));
|
||||
pk <- setup_kem_pk(Spk);
|
||||
event RevealPk(pk);
|
||||
out(C, pk).
|
||||
|
||||
let rosenpass_main() = 0
|
||||
| !Oreveal_kem_pk
|
||||
| REP(INITIATOR_BOUND, Oinitiator)
|
||||
| REP(RESPONDER_BOUND, Oinit_hello)
|
||||
| REP(RESPONDER_BOUND, Oinit_conf).
|
||||
|
||||
nounif v:seed_prec; attacker(prepare_seed(trusted_seed( v )))/6217[hypothesis].
|
||||
nounif v:seed; attacker(prepare_seed( v ))/6216[hypothesis].
|
||||
nounif v:seed; attacker(rng_kem_sk( v ))/6215[hypothesis].
|
||||
nounif v:seed; attacker(rng_key( v ))/6214[hypothesis].
|
||||
nounif v:key_prec; attacker(prepare_key(trusted_key( v )))/6213[hypothesis].
|
||||
nounif v:kem_sk_prec; attacker(prepare_kem_sk(trusted_kem_sk( v )))/6212[hypothesis].
|
||||
nounif v:key; attacker(prepare_key( v ))/6211[hypothesis].
|
||||
nounif v:kem_sk; attacker(prepare_kem_sk( v ))/6210[hypothesis].
|
||||
nounif Spk:kem_sk_tmpl;
|
||||
attacker(Creveal_kem_pk(Spk))/6110[conclusion].
|
||||
nounif sid:SessionId, Ssskm:kem_sk_tmpl, Spsk:key_tmpl, Sspkt:kem_sk_tmpl, Seski:seed_tmpl, Ssptr:seed_tmpl;
|
||||
attacker(Cinitiator( *sid, *Ssskm, *Spsk, *Sspkt, *Seski, *Ssptr ))/6109[conclusion].
|
||||
nounif sid:SessionId, biscuit_no:Atom, Ssskm:kem_sk_tmpl, Spsk:key_tmpl, Sspkt:kem_sk_tmpl, Septi:seed_tmpl, Sspti:seed_tmpl, ih:InitHello_t;
|
||||
attacker(Cinit_hello( *sid, *biscuit_no, *Ssskm, *Spsk, *Sspkt, *Septi, *Sspti, *ih ))/6108[conclusion].
|
||||
nounif rh:RespHello_t;
|
||||
attacker(Cresp_hello( *rh ))/6107[conclusion].
|
||||
nounif Ssskm:kem_sk_tmpl, Spsk:key_tmpl, Sspkt:kem_sk_tmpl, ic:InitConf_t;
|
||||
attacker(Cinit_conf( *Ssskm, *Spsk, *Sspkt, *ic ))/6106[conclusion].
|
||||
32
analysis/rosenpass/prf.mpv
Normal file
32
analysis/rosenpass/prf.mpv
Normal file
@@ -0,0 +1,32 @@
|
||||
#pragma once
|
||||
#include "prelude/bits.mpv"
|
||||
#include "crypto/key.mpv"
|
||||
|
||||
@module prfs
|
||||
|
||||
(* Labels, as specified in the paper *)
|
||||
fun prf(key, bits) : key.
|
||||
|
||||
const PROTOCOL:bits.
|
||||
|
||||
const MAC:bits.
|
||||
const COOKIE:bits.
|
||||
const PEER_ID:bits.
|
||||
const BISCUIT_AD:bits.
|
||||
const CK_INIT:bits.
|
||||
const CK_EXTRACT:bits.
|
||||
|
||||
const MIX:bits.
|
||||
const USER:bits.
|
||||
const HS_ENC:bits.
|
||||
const INI_ENC:bits.
|
||||
const RES_ENC:bits.
|
||||
|
||||
const OSK:bits.
|
||||
|
||||
letfun prf2(k:key, a:bits, b:bits) = prf(prf(k, a), b).
|
||||
|
||||
letfun lprf0(lbl:bits) = prf2(key0, PROTOCOL, lbl).
|
||||
letfun lprf1(lbl:bits, a:bits) = prf(lprf0(lbl), a).
|
||||
letfun lprf2(lbl:bits, a:bits, b:bits) = prf(lprf1(lbl, a), b).
|
||||
letfun lprf3(lbl:bits, a:bits, b:bits, c:bits) = prf(lprf2(lbl, a, b), c).
|
||||
81
analysis/rosenpass/protocol.mpv
Normal file
81
analysis/rosenpass/protocol.mpv
Normal file
@@ -0,0 +1,81 @@
|
||||
#pragma once
|
||||
#include "crypto/kem.mpv"
|
||||
#include "rosenpass/handshake_state.mpv"
|
||||
|
||||
type InitHello_t.
|
||||
fun InitHello(
|
||||
SessionId, // sidi
|
||||
kem_pk, // epki
|
||||
bits, // sctr
|
||||
bits, // pidiC
|
||||
bits // auth
|
||||
) : InitHello_t [data].
|
||||
|
||||
#define INITHELLO_PRODUCE() \
|
||||
ck <- lprf1(CK_INIT, kem_pk2b(spkr)); /* IHI1 */ \
|
||||
/* not handled here */ /* IHI2 */ \
|
||||
/* not handled here */ /* IHI3 */ \
|
||||
MIX2(sid2b(sidi), kem_pk2b(epki)) /* IHI4 */ \
|
||||
ENCAPS_AND_MIX(sctr, spkr, sptr) /* IHI5 */ \
|
||||
ENCRYPT_AND_MIX(pidiC, pidi) /* IHI6 */ \
|
||||
MIX2(kem_pk2b(spki), k2b(psk)) /* IHI7 */ \
|
||||
ENCRYPT_AND_MIX(auth, empty) /* IHI8 */ \
|
||||
ih <- InitHello(sidi, epki, sctr, pidiC, 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 */ \
|
||||
LOOKUP_SENDER(pid) /* IHR6 */ \
|
||||
MIX2(kem_pk2b(spki), k2b(psk)) /* IHR7 */ \
|
||||
DECRYPT_AND_MIX(DUMMY(empty), auth)
|
||||
|
||||
type RespHello_t.
|
||||
fun RespHello(
|
||||
SessionId, // sidr
|
||||
SessionId, // sidi
|
||||
bits, // ecti
|
||||
bits, // scti
|
||||
bits, // biscuit
|
||||
bits // auth
|
||||
) : RespHello_t [data].
|
||||
|
||||
#define RESPHELLO_PRODUCE() \
|
||||
/* not handled here */ /* RHR1 */ \
|
||||
MIX2(sid2b(sidr), sid2b(sidi)) /* RHR3 */ \
|
||||
ENCAPS_AND_MIX(ecti, epki, epti) /* RHR4 */ \
|
||||
ENCAPS_AND_MIX(scti, spki, spti) /* RHR5 */ \
|
||||
STORE_BISCUIT(biscuit) /* RHR6 */ \
|
||||
ENCRYPT_AND_MIX(auth, empty) /* RHR7 */ \
|
||||
rh <- RespHello(sidr, sidi, ecti, scti, biscuit, auth);
|
||||
|
||||
#define RESPHELLO_CONSUME() \
|
||||
let RespHello(sidr, sidi, ecti, scti, biscuit, 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 */ \
|
||||
DECRYPT_AND_MIX(DUMMY(empty), auth) /* RHI7 */
|
||||
|
||||
type InitConf_t.
|
||||
fun InitConf(
|
||||
SessionId, // sidi
|
||||
SessionId, // sidr
|
||||
bits, // biscuit
|
||||
bits // auth
|
||||
) : InitConf_t [data].
|
||||
|
||||
#define INITCONF_PRODUCE() \
|
||||
MIX2(sid2b(sidi), sid2b(sidr)) /* ICI3 */ \
|
||||
ENCRYPT_AND_MIX(auth, empty) /* ICI4 */ \
|
||||
ic <- InitConf(sidi, sidr, biscuit, auth);
|
||||
|
||||
#define INITCONF_CONSUME() \
|
||||
let InitConf(sidi, sidr, biscuit, auth) = ic in \
|
||||
LOAD_BISCUIT(biscuit_no, biscuit) /* ICR1 */ \
|
||||
ENCRYPT_AND_MIX(rh_auth, empty) /* ICIR */ \
|
||||
ck_rh <- ck; /* ---- */ /* TODO: Move into oracles.mpv */ \
|
||||
MIX2(sid2b(sidi), sid2b(sidr)) /* ICR3 */ \
|
||||
DECRYPT_AND_MIX(DUMMY(empty), auth) /* ICR4 */
|
||||
12
analysis/rosenpass/responder.macro
Normal file
12
analysis/rosenpass/responder.macro
Normal file
@@ -0,0 +1,12 @@
|
||||
#include "rosenpass/undef.macro"
|
||||
#define role res_role
|
||||
#define sski kem_sk0
|
||||
#define spki spkt
|
||||
#define sskr sskm
|
||||
#define spkr spkm
|
||||
#define eskm kem_sk0
|
||||
#define epkm kem_pk0
|
||||
#define sidi sidt
|
||||
#define sidr sidm
|
||||
#define pidi pidt
|
||||
#define pidr pidm
|
||||
11
analysis/rosenpass/server.mpv
Normal file
11
analysis/rosenpass/server.mpv
Normal file
@@ -0,0 +1,11 @@
|
||||
#pragma once
|
||||
#include "prelude/basic.mpv"
|
||||
#include "crypto/key.mpv"
|
||||
#include "crypto/kem.mpv"
|
||||
|
||||
#define SERVER_NEW(biscuit_key, sk, pk) \
|
||||
biscuit_key <- key_new(); \
|
||||
new sk:kem_sk; \
|
||||
pk <- kem_pub(sk);
|
||||
|
||||
fun Server_id(kem_pk) : Atom.
|
||||
33
analysis/rosenpass/undef.macro
Normal file
33
analysis/rosenpass/undef.macro
Normal file
@@ -0,0 +1,33 @@
|
||||
#ifdef role
|
||||
#undef role
|
||||
#endif
|
||||
#ifdef sski
|
||||
#undef sski
|
||||
#endif
|
||||
#ifdef spki
|
||||
#undef spki
|
||||
#endif
|
||||
#ifdef sskr
|
||||
#undef sskr
|
||||
#endif
|
||||
#ifdef spkr
|
||||
#undef spkr
|
||||
#endif
|
||||
#ifdef eskm
|
||||
#undef eskm
|
||||
#endif
|
||||
#ifdef epkm
|
||||
#undef epkm
|
||||
#endif
|
||||
#ifdef sidi
|
||||
#undef sidi
|
||||
#endif
|
||||
#ifdef sidr
|
||||
#undef sidr
|
||||
#endif
|
||||
#ifdef pidi
|
||||
#undef pidi
|
||||
#endif
|
||||
#ifdef pidr
|
||||
#undef pidr
|
||||
#endif
|
||||
Reference in New Issue
Block a user