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