1 use crate::{
2     aead::{Aead, AeadCtx, AeadCtxR, AeadCtxS, AeadKey, AeadNonce},
3     kdf::Kdf as KdfTrait,
4     kem::Kem as KemTrait,
5     kex::{KeyExchange, Serializable},
6     op_mode::{OpModeR, OpModeS, PskBundle},
7     setup::ExporterSecret,
8 };
9 
10 use generic_array::GenericArray;
11 use rand::{rngs::StdRng, CryptoRng, Rng, RngCore, SeedableRng};
12 
13 /// Returns a random 32-byte buffer
gen_rand_buf() -> [u8; 32]14 pub(crate) fn gen_rand_buf() -> [u8; 32] {
15     let mut csprng = StdRng::from_entropy();
16     let mut buf = [0u8; 32];
17     csprng.fill_bytes(&mut buf);
18     buf
19 }
20 
21 /// Generates a keypair without the need of a KEM
kex_gen_keypair<Kex: KeyExchange, R: CryptoRng + RngCore>( csprng: &mut R, ) -> (Kex::PrivateKey, Kex::PublicKey)22 pub(crate) fn kex_gen_keypair<Kex: KeyExchange, R: CryptoRng + RngCore>(
23     csprng: &mut R,
24 ) -> (Kex::PrivateKey, Kex::PublicKey) {
25     // Make some keying material that's the size of a private key
26     let mut ikm: GenericArray<u8, <Kex::PrivateKey as Serializable>::OutputSize> =
27         GenericArray::default();
28     // Fill it with randomness
29     csprng.fill_bytes(&mut ikm);
30     // Run derive_keypair with a nonsense ciphersuite. We use SHA-512 to satisfy any security level
31     Kex::derive_keypair::<crate::kdf::HkdfSha512>(b"31337", &ikm)
32 }
33 
34 /// Creates a pair of `AeadCtx`s without doing a key exchange
gen_ctx_simple_pair<A, Kdf, Kem>() -> (AeadCtxS<A, Kdf, Kem>, AeadCtxR<A, Kdf, Kem>) where A: Aead, Kdf: KdfTrait, Kem: KemTrait,35 pub(crate) fn gen_ctx_simple_pair<A, Kdf, Kem>() -> (AeadCtxS<A, Kdf, Kem>, AeadCtxR<A, Kdf, Kem>)
36 where
37     A: Aead,
38     Kdf: KdfTrait,
39     Kem: KemTrait,
40 {
41     let mut csprng = StdRng::from_entropy();
42 
43     // Initialize the key and nonce
44     let key = {
45         let mut buf = AeadKey::<A>::default();
46         csprng.fill_bytes(buf.0.as_mut_slice());
47         buf
48     };
49     let base_nonce = {
50         let mut buf = AeadNonce::<A>::default();
51         csprng.fill_bytes(buf.0.as_mut_slice());
52         buf
53     };
54     let exporter_secret = {
55         let mut buf = ExporterSecret::<Kdf>::default();
56         csprng.fill_bytes(buf.0.as_mut_slice());
57         buf
58     };
59 
60     let ctx1 = AeadCtx::new(&key, base_nonce.clone(), exporter_secret.clone());
61     let ctx2 = AeadCtx::new(&key, base_nonce.clone(), exporter_secret.clone());
62 
63     (ctx1.into(), ctx2.into())
64 }
65 
66 #[derive(Clone, Copy)]
67 pub(crate) enum OpModeKind {
68     Base,
69     Auth,
70     Psk,
71     AuthPsk,
72 }
73 
74 /// Makes an agreeing pair of `OpMode`s of the specified variant
new_op_mode_pair<'a, Kex: KeyExchange, Kdf: KdfTrait>( kind: OpModeKind, psk: &'a [u8], psk_id: &'a [u8], ) -> (OpModeS<'a, Kex>, OpModeR<'a, Kex>)75 pub(crate) fn new_op_mode_pair<'a, Kex: KeyExchange, Kdf: KdfTrait>(
76     kind: OpModeKind,
77     psk: &'a [u8],
78     psk_id: &'a [u8],
79 ) -> (OpModeS<'a, Kex>, OpModeR<'a, Kex>) {
80     let mut csprng = StdRng::from_entropy();
81     let (sk_sender, pk_sender) = kex_gen_keypair::<Kex, _>(&mut csprng);
82     let psk_bundle = PskBundle { psk, psk_id };
83 
84     match kind {
85         OpModeKind::Base => {
86             let sender_mode = OpModeS::Base;
87             let receiver_mode = OpModeR::Base;
88             (sender_mode, receiver_mode)
89         }
90         OpModeKind::Psk => {
91             let sender_mode = OpModeS::Psk(psk_bundle);
92             let receiver_mode = OpModeR::Psk(psk_bundle);
93             (sender_mode, receiver_mode)
94         }
95         OpModeKind::Auth => {
96             let sender_mode = OpModeS::Auth((sk_sender, pk_sender.clone()));
97             let receiver_mode = OpModeR::Auth(pk_sender);
98             (sender_mode, receiver_mode)
99         }
100         OpModeKind::AuthPsk => {
101             let sender_mode = OpModeS::AuthPsk((sk_sender, pk_sender.clone()), psk_bundle);
102             let receiver_mode = OpModeR::AuthPsk(pk_sender, psk_bundle);
103             (sender_mode, receiver_mode)
104         }
105     }
106 }
107 
108 /// Evaluates the equivalence of two encryption contexts by doing some encryption-decryption
109 /// round trips. Returns `true` iff the contexts are equal after 1000 iterations
aead_ctx_eq<A: Aead, Kdf: KdfTrait, Kem: KemTrait>( sender: &mut AeadCtxS<A, Kdf, Kem>, receiver: &mut AeadCtxR<A, Kdf, Kem>, ) -> bool110 pub(crate) fn aead_ctx_eq<A: Aead, Kdf: KdfTrait, Kem: KemTrait>(
111     sender: &mut AeadCtxS<A, Kdf, Kem>,
112     receiver: &mut AeadCtxR<A, Kdf, Kem>,
113 ) -> bool {
114     let mut csprng = StdRng::from_entropy();
115 
116     // Some random input data
117     let msg = {
118         let len = csprng.gen::<u8>();
119         let mut buf = vec![0u8; len as usize];
120         csprng.fill_bytes(&mut buf);
121         buf
122     };
123     let aad = {
124         let len = csprng.gen::<u8>();
125         let mut buf = vec![0u8; len as usize];
126         csprng.fill_bytes(&mut buf);
127         buf
128     };
129 
130     // Do 1000 iterations of encryption-decryption. The underlying sequence number increments
131     // each time.
132     for i in 0..1000 {
133         let mut plaintext = msg.clone();
134         // Encrypt the plaintext
135         let tag = sender
136             .seal(&mut plaintext[..], &aad)
137             .expect(&format!("seal() #{} failed", i));
138         // Rename for clarity
139         let mut ciphertext = plaintext;
140 
141         // Now to decrypt on the other side
142         if let Err(_) = receiver.open(&mut ciphertext[..], &aad, &tag) {
143             // An error occurred in decryption. These encryption contexts are not identical.
144             return false;
145         }
146         // Rename for clarity
147         let roundtrip_plaintext = ciphertext;
148 
149         // Make sure the output message was the same as the input message. If it doesn't match,
150         // early return
151         if msg != roundtrip_plaintext {
152             return false;
153         }
154     }
155 
156     true
157 }
158